Pastebin

New pastes are no longer accepted · Stats

Latest Pastes

playercommand.hpp


/* $Id$
 * EOSERV is released under the zlib license.
 * See LICENSE.txt for more info.
 */

#ifndef PLAYERCOMMANDS_HPP_INCLUDED
#define PLAYERCOMMANDS_HPP_INCLUDED

#include <map>
#include <set>
#include <string>
#include <unordered_map>
#include <vector>

#include "../character.hpp"
#include "../command_source.hpp"

#define PLAYER_COMMAND_HANDLER_PASTE_AUX2(base, id) base##id
#define PLAYER_COMMAND_HANDLER_PASTE_AUX(base, id) PLAYER_COMMAND_HANDLER_PASTE_AUX2(base, id)

#define PLAYER_COMMAND_HANDLER_REGISTER() \
namespace { struct PLAYER_COMMAND_HANDLER_PASTE_AUX(player_command_handler_register_helper_, __LINE__) : public player_command_handler_register_helper \
{ \
	PLAYER_COMMAND_HANDLER_PASTE_AUX(player_command_handler_register_helper_, __LINE__)() \
	{ \
		player_command_handler_register_init _init; \

#define PLAYER_COMMAND_HANDLER_REGISTER_END() ; \
	} \
} PLAYER_COMMAND_HANDLER_PASTE_AUX(player_command_handler_register_helper_instance_, __LINE__); }

namespace PlayerCommands
{

struct player_command_info
{
	std::string name;
	std::vector<std::string> arguments;
	std::vector<std::string> optional_arguments;
	std::size_t partial_min_chars;
	bool require_character;

	player_command_info(std::string name, std::vector<std::string> arguments = std::vector<std::string>(), std::vector<std::string> optional_arguments = std::vector<std::string>(), std::size_t partial_min_chars = 0)
		: name(name)
		, arguments(arguments)
		, optional_arguments(optional_arguments)
		, partial_min_chars(partial_min_chars)
		, require_character(false)
	{ }
};

struct player_command_handler
{
	player_command_info info;
	std::function<void(const std::vector<std::string>&, Command_Source*)> f;

	player_command_handler(player_command_info info, std::function<void(const std::vector<std::string>&, Command_Source*)> f)
		: info(info)
		, f(f)
	{ }

	player_command_handler(player_command_info info, std::function<void(const std::vector<std::string>&, Character*)> f)
		: info(info)
		, f([f](const std::vector<std::string>& arguments, Command_Source* from) { f(arguments, static_cast<Character*>(from)); })
	{
		this->info.require_character = true;
	}

	bool operator <(const player_command_handler& rhs) const
	{
		// This ordering is very important for making sure the most specific command gets picked
		return (info.partial_min_chars < rhs.info.partial_min_chars) || (info.name.length() < rhs.info.name.length()) || (info.name < rhs.info.name);
	}
};

class player_command_handler_register
{
	private:
		std::map<std::string, player_command_handler> handlers;
		std::unordered_map<std::string, std::string> aliases;

	public:
		void Register(player_command_handler handler);
		void RegisterAlias(const std::string& alias, const std::string& command);

		bool Handle(std::string command, const std::vector<std::string>& arguments, Command_Source* from, int alias_depth = 0) const;
};

extern player_command_handler_register *player_command_handler_register_instance;

class player_command_handler_register_init
{
	private:
		bool master;

	public:
		player_command_handler_register_init(bool master = false)
			: master(master)
		{
			static bool initialized;

			if (!initialized)
			{
				initialized = true;
				init();
			}
		}

		void init() const;

		~player_command_handler_register_init();
};

class player_command_handler_register_helper
{
	public:
		template <class F> void Register(player_command_info info, const F& f)
		{
			player_command_handler_register_instance->Register(player_command_handler(info, std::function<void(const std::vector<std::string>&, Command_Source*)>(f)));
		}

		template <class F>  void RegisterCharacter(player_command_info info, const F& f)
		{
			player_command_handler_register_instance->Register(player_command_handler(info, std::function<void(const std::vector<std::string>&, Character*)>(f)));
		}

		void RegisterAlias(const std::string& alias, const std::string& command)
		{
			player_command_handler_register_instance->RegisterAlias(alias, command);
		}
};

inline bool Handle(std::string command, const std::vector<std::string>& arguments, Command_Source* from)
{
	return player_command_handler_register_instance->Handle(command, arguments, from);
}

}

#endif // PLAYERCOMMANDS_HPP_INCLUDED