aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Server/Console/ServerCliRegistry.cpp
blob: 432907b237536b36f4592d6e875793568e0f9a69 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include "stdafx.h"

#include "ServerCliRegistry.h"

#include "commands\IServerCliCommand.h"
#include "..\Common\StringUtils.h"

namespace ServerRuntime
{
	bool ServerCliRegistry::Register(std::unique_ptr<IServerCliCommand> command)
	{
		if (!command)
		{
			return false;
		}

		IServerCliCommand *raw = command.get();
		std::string baseName = StringUtils::ToLowerAscii(raw->Name());
		// Reject empty/duplicate primary command names.
		if (baseName.empty() || m_lookup.find(baseName) != m_lookup.end())
		{
			return false;
		}
		std::vector<std::string> aliases = raw->Aliases();
		std::vector<std::string> normalizedAliases;
		normalizedAliases.reserve(aliases.size());
		for (size_t i = 0; i < aliases.size(); ++i)
		{
			std::string alias = StringUtils::ToLowerAscii(aliases[i]);
			// Alias must also be unique across all names and aliases.
			if (alias.empty() || m_lookup.find(alias) != m_lookup.end())
			{
				return false;
			}
			normalizedAliases.push_back(alias);
		}

		m_lookup[baseName] = raw;
		for (size_t i = 0; i < normalizedAliases.size(); ++i)
		{
			m_lookup[normalizedAliases[i]] = raw;
		}

		// Command objects are owned here; lookup stores non-owning pointers.
		m_commands.push_back(std::move(command));
		return true;
	}

	const IServerCliCommand *ServerCliRegistry::Find(const std::string &name) const
	{
		std::string key = StringUtils::ToLowerAscii(name);
		auto it = m_lookup.find(key);
		if (it == m_lookup.end())
		{
			return NULL;
		}
		return it->second;
	}

	IServerCliCommand *ServerCliRegistry::FindMutable(const std::string &name)
	{
		std::string key = StringUtils::ToLowerAscii(name);
		auto it = m_lookup.find(key);
		if (it == m_lookup.end())
		{
			return NULL;
		}
		return it->second;
	}

	void ServerCliRegistry::SuggestCommandNames(const std::string &prefix, const std::string &linePrefix, std::vector<std::string> *out) const
	{
		for (size_t i = 0; i < m_commands.size(); ++i)
		{
			const IServerCliCommand *command = m_commands[i].get();
			std::string name = command->Name();
			if (StringUtils::StartsWithIgnoreCase(name, prefix))
			{
				out->push_back(linePrefix + name);
			}

			// Include aliases so users can discover shorthand commands.
			std::vector<std::string> aliases = command->Aliases();
			for (size_t aliasIndex = 0; aliasIndex < aliases.size(); ++aliasIndex)
			{
				if (StringUtils::StartsWithIgnoreCase(aliases[aliasIndex], prefix))
				{
					out->push_back(linePrefix + aliases[aliasIndex]);
				}
			}
		}
	}

	const std::vector<std::unique_ptr<IServerCliCommand>> &ServerCliRegistry::Commands() const
	{
		return m_commands;
	}
}