// #pragma once // #include "Global.h" // class Actor; // #define USE_PARSE_ENUM_STRING // //#define ENABLE_PARAMETER_TYPE_POSTFIX // #include "MC/Command.hpp" // #include "MC/CommandOrigin.hpp" // #include "MC/CommandOutput.hpp" // #include "MC/CommandParameterData.hpp" // #include "MC/CommandRegistry.hpp" // #include "MC/CommandSelector.hpp" // #include "MC/CommandPosition.hpp" // #include "Utils/WinHelper.h" // #include // /////////////////////////////////////////////////////// // // Dynamic Command Registry // // // // [Example] // // ## One Example: // // // Direct setup of dynamic command with necessary information // // using ParamType = DynamicCommand::ParameterType; // // using Param = DynamicCommand::ParameterData; // // DynamicCommand::setup( // // "testenum", // command name // // "dynamic command", // command description // // { // // // enums{enumName, {values...}} // // {"TestEnum1", {"add", "remove"}}, // // {"TestEnum2", {"list"}}, // // }, // // { // // // parameters(type, name, [optional], [enumOptions(also enumName)], [identifier]) // // // identifier: used to identify unique parameter data, if idnetifier is not set, // // // it is set to be the same as enumOptions or name (identifier = enumOptions.empty() ? name:enumOptions) // // Param("testEnum", ParamType::Enum, "TestEnum1"), // // Param("testEnum", ParamType::Enum, "TestEnum2"), // // Param("testInt", ParamType::Int, true), // // }, // // { // // // overloads{ (type == Enum ? enumOptions : name) ...} // // {"TestEnum1", "testInt"}, // testenum [testInt] // // {"TestEnum2"}, // testenum // // }, // // // dynamic command callback // // [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, // // std::unordered_map& results) { // // auto& action = results["testEnum"].get(); // // switch (do_hash(action.c_str())) // // { // // case do_hash("add"): // // if (results["testInt"].isSet) // // output.success(fmt::format("add {}", results["testInt"].getRaw())); // // else // // output.success("add nothing"); // // break; // // case do_hash("remove"): // // if (results["testInt"].isSet) // // output.success(fmt::format("remove {}", results["testInt"].getRaw())); // // else // // output.success("remove nothing"); // // break; // // case do_hash("list"): // // output.success("list"); // // break; // // default: // // break; // // } // // }, // // CommandPermissionLevel::GameMasters); // // // // ## Another Example // // using ParamType = DynamicCommand::ParameterType; // // // create a dynamic command // // auto command = DynamicCommand::createCommand("testcmd", "dynamic command", CommandPermissionLevel::GameMasters); // // // // auto& optionsAdd = command->setEnum("TestOperation1", {"add", "remove"}); // // auto& optionsList = command->setEnum("TestOperation2", {"list"}); // // // // command->mandatory("testEnum", ParamType::Enum, optionsAdd, CommandParameterOption::EnumAutocompleteExpansion); // // command->mandatory("testEnum", ParamType::Enum, optionsList, CommandParameterOption::EnumAutocompleteExpansion); // // command->mandatory("testString", ParamType::String); // // // // command->addOverload({optionsAdd, "testString"}); // dyncmd // // command->addOverload({"TestOperation2"}); // dyncmd // // // // command->setCallback([](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, std::unordered_map& results) { // // switch (do_hash(results["testEnum"].getRaw().c_str())) // // { // // case do_hash("add"): // // output.success(fmt::format("Add - {}", results["testString"].getRaw())); // // break; // // case do_hash("remove"): // // output.success(fmt::format("Remove - {}", results["testString"].getRaw())); // // break; // // case do_hash("list"): // // output.success("List"); // // break; // // default: // // break; // // } // // }); // // // do not forget to setup the command instance // // DynamicCommand::setup(std::move(command)); // // // ///////////////////////////////////////////////////// // struct DCCallback; // struct DCArgs; // typedef union DCValue_ DCValue; // class DynamicCommandInstance; // class CommandMessage; // class CommandOutput; // class CommandRegistry; // class Player; // #define AllResultType bool const*, int const*, float const*, std::string const*, CommandSelector const*, CommandSelector const*, CommandPosition const*, CommandPositionFloat const*, CommandRawText const*, CommandMessage const*, Json::Value const*, CommandItem const*, Block const* const*, MobEffect const* const*, ActorDefinitionIdentifier const* const*, std::unique_ptr const* // class DynamicCommand : public Command { // template // static constexpr bool is_one_of_v = std::_Meta_find_unique_index, std::add_pointer_t>>::value < sizeof...(_Types); // template // static constexpr bool is_supported_result_type_v = is_one_of_v<_Ty, AllResultType>; // template // using enable_if_supported_t = std::enable_if_t, Type>; // public: // enum class ParameterType { // Bool, // bool // Int, // int // Float, // float // String, // std::string // Actor, // CommandSelector // Player, // CommandSelector // BlockPos, // CommandPosition // Vec3, // CommandPositionFloat // RawText, // CommandRawText // Message, // CommandMessage // JsonValue, // Json::Value // Item, // CommandItem // Block, // Block const* // Effect, // MobEffect const* // Enum, // ENUM // SoftEnum, // SOFT_ENUM // ActorType, // ActorDefinitionIdentifier const* // Command, // std::unique_ptr // WildcardSelector, // WildcardCommandSelector // #ifdef ENABLE_PARAMETER_TYPE_POSTFIX // Postfix, // int? // #endif // ENABLE_PARAMETER_TYPE_POSTFIX // }; // struct ParameterPtr; // struct Result { // ParameterType const type; // size_t const offset; // bool const isSet; // DynamicCommand const* command; // DynamicCommandInstance const* instance; // CommandOrigin const* origin; // LIAPI Result(ParameterPtr const* ptr, DynamicCommand const* command, CommandOrigin const* origin, DynamicCommandInstance const* instance = nullptr); // LIAPI Result(); // LIAPI std::string const& getEnumValue() const; // LIAPI ParameterType getType() const; // LIAPI std::string getName() const; // LIAPI std::string toDebugString() const; // LIAPI DynamicCommandInstance const* getInstance() const; // template // inline enable_if_supported_t getRaw() const { // #ifdef USE_PARSE_ENUM_STRING // if (type == ParameterType::Enum) { // auto& val = dAccess>(command, offset); // if constexpr (std::is_same_v, int> || std::is_enum_v) { // return static_cast(val.second); // } else if constexpr (std::is_same_v, std::string>) { // return static_cast(val.first); // } // } // #else // if constexpr (std::is_same_v, std::string>) { // if (type == ParameterType::Enum) // return getEnumValue(); // } // #endif // USE_PARSE_ENUM_STRING // if (checkTempateType(type)) // return dAccess(command, offset); // throw std::runtime_error(fmt::format("Raw type not match, parameter Type: {}, data type: {}", magic_enum::enum_name(type), typeid(T).name())); // } // template // inline enable_if_supported_t value_or(T const& defaultValue) { // if (isSet) // return getRaw(); // return defaultValue; // } // template // inline std::conditional_t, std::add_lvalue_reference_t>>, T> // get() const { // static_assert(is_supported_result_type_v || (std::is_lvalue_reference_v && is_supported_result_type_v>), // "Unsupported Result Type in " __FUNCTION__); // if constexpr (std::is_lvalue_reference_v) // return getRaw>(); // else // return getRaw(); // } // template <> // inline std::vector get>() const { // if (type == ParameterType::Player) { // auto players = get>(); // std::vector actors(players.size()); // std::transform(players.begin(), players.end(), actors.begin(), // [](Player* player) { return static_cast(player); }); // return actors; // } // std::vector rtn; // for (auto& result : getRaw>().results(*origin)) { // rtn.push_back(result); // } // return rtn; // } // template <> // inline std::vector get>() const { // std::vector rtn; // for (auto& result : getRaw>().results(*origin)) { // rtn.push_back(result); // } // return rtn; // } // template <> // inline BlockPos get() const { // auto& pos = getRaw(); // return pos.getBlockPos(*origin, Vec3::ZERO); // } // template <> // inline Vec3 get() const { // auto& pos = getRaw(); // return pos.getPosition(*origin, Vec3::ZERO); // } // }; // struct ParameterPtr { // ParameterType type; // private: // size_t offset = -1; // friend struct Result; // public: // LIAPI ParameterPtr(ParameterType type, size_t offset); // LIAPI bool isValueSet(DynamicCommand const* command) const; // LIAPI Result getResult(DynamicCommand const* command, CommandOrigin const* origin) const; // inline size_t getOffset() const { // return offset; // } // }; // struct ParameterData { // protected: // DynamicCommand::ParameterType type; // size_t offset = -1; // std::string name; // std::string description; // std::string identifier; // bool optional = false; // CommandParameterOption option; // public: // ParameterData() = delete; // LIAPI ParameterData(ParameterData const&); // LIAPI ParameterData(std::string const& name, DynamicCommand::ParameterType type, bool optional = false, std::string const& enumOptions = "", std::string const& identifier = "", CommandParameterOption parameterOption = (CommandParameterOption)0); // LIAPI ParameterData(std::string const& name, DynamicCommand::ParameterType type, std::string const& enumOptions = "", std::string const& identifier = "", CommandParameterOption parameterOption = (CommandParameterOption)0); // LIAPI CommandParameterData makeParameterData() const; // friend class DynamicCommandInstance; // friend class DynamicCommand; // template // inline static constexpr CommandParameterDataType getCommandParameterDataType() { // if constexpr (type == ParameterType::Enum) // return CommandParameterDataType::ENUM; // else if constexpr (type == ParameterType::SoftEnum) // return CommandParameterDataType::SOFT_ENUM; // // else if constexpr (type == ParameterType::Postfix) // // return CommandParameterDataType::POSIFIX; // else // return CommandParameterDataType::NORMAL; // } // template // CommandParameterData makeParameterData() const { // CommandParameterData param{ // type == ParameterType::Enum ? typeid_t::count++ : type_id(), // type == ParameterType::Enum ? &CommandRegistry::fakeParse : CommandRegistry::getParseFn(), // name, // getCommandParameterDataType(), // description == "" ? nullptr : description.data(), // (int)offset, // optional, // (int)offset + std::max(8, (int)sizeof(T))}; // param.addOptions(option); // // logger.warn(Global->describe(param)); // return std::move(param); // } // inline void setOptional(bool optional) { // this->optional = optional; // } // inline bool setEnumOptions(std::string const& enumOptions) { // if (type != DynamicCommand::ParameterType::Enum && type != DynamicCommand::ParameterType::SoftEnum) // return false; // this->description = enumOptions; // return true; // } // inline bool setParameterOption(CommandParameterOption parameterOption) { // this->option = parameterOption; // } // inline ParameterData(std::string const& name, ParameterType type, const char* enumOptions = "", std::string const& identifer = "", CommandParameterOption parameterOption = (CommandParameterOption)0) // : ParameterData(name, type, (std::string const&)enumOptions, identifer, parameterOption){}; // }; // using CallBackFn = std::function& results)>; // using BuilderFn = std::unique_ptr (*)(); // private: // template // inline static enable_if_supported_t<_Ty, bool> checkTempateType(ParameterType type) { // switch (type) { // case ParameterType::Bool: // return std::is_same_v>; // case ParameterType::Int: // return std::is_same_v>; // case ParameterType::Float: // return std::is_same_v>; // case ParameterType::String: // return std::is_same_v>; // case ParameterType::Actor: // return std::is_same_v, std::remove_cv_t<_Ty>>; // case ParameterType::Player: // return std::is_same_v, std::remove_cv_t<_Ty>>; // case ParameterType::BlockPos: // case ParameterType::Vec3: // return std::is_same_v> || std::is_same_v>; // case ParameterType::RawText: // return std::is_same_v> || std::is_same_v>; // case ParameterType::Message: // return std::is_same_v>; // case ParameterType::JsonValue: // return std::is_same_v>; // case ParameterType::Item: // return std::is_same_v>; // case ParameterType::Block: // return std::is_same_v>; // case ParameterType::Effect: // return std::is_same_v>; // // case ParameterType::Position: // // return std::is_same_v> || std::is_same_v> || std::is_same_v>; // case ParameterType::Enum: // return std::is_same_v> || std::is_same_v> || std::is_enum_v<_Ty>; // case ParameterType::SoftEnum: // return std::is_same_v>; // case ParameterType::ActorType: // return std::is_same_v>; // case ParameterType::Command: // return std::is_same_v, std::remove_cv_t<_Ty>>; // default: // return false; // break; // } // return false; // } // LIAPI static char builderCallbackHanler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata); // LIAPI static std::unique_ptr* commandBuilder(std::unique_ptr* rtn, std::string name); // LIAPI static DynamicCommandInstance* _setup(std::unique_ptr commandInstance); // public: // static bool onServerCommandsRegister(CommandRegistry& registry); // friend class DynamicCommandInstance; // public: // /*0*/ virtual ~DynamicCommand(); // /*1*/ virtual void execute(class CommandOrigin const& origin, class CommandOutput& output) const; // LIAPI static std::unique_ptr createCommand(std::string const& name, std::string const& description, CommandPermissionLevel permission = CommandPermissionLevel::GameMasters, CommandFlag flag1 = {(CommandFlagValue)0x80}, CommandFlag flag2 = {(CommandFlagValue)0}, HMODULE handle = GetCurrentModule()); // LIAPI static std::unique_ptr createCommand( // std::string const& name, // std::string const& description, // std::unordered_map>&& enums, // std::vector&& params, // std::vector>&& overloads, // CallBackFn callback, // CommandPermissionLevel permission = CommandPermissionLevel::GameMasters, // CommandFlag flag1 = {(CommandFlagValue)0x80}, // CommandFlag flag2 = {(CommandFlagValue)0}, // HMODULE handle = GetCurrentModule()); // LIAPI static DynamicCommandInstance const* setup(std::unique_ptr commandInstance); // inline static DynamicCommandInstance const* setup( // std::string const& name, // std::string const& description, // std::unordered_map>&& enums, // std::vector&& params, // std::vector>&& overloads, // CallBackFn callback, // CommandPermissionLevel permission = CommandPermissionLevel::GameMasters, // CommandFlag flag1 = {(CommandFlagValue)0x80}, // CommandFlag flag2 = {(CommandFlagValue)0}, // HMODULE handle = GetCurrentModule()) { // return setup(createCommand(name, description, std::move(enums), std::move(params), std::move(overloads), std::move(callback), permission, flag1, flag2, handle)); // }; // // Experiment // LIAPI static bool unregisterCommand(std::string const& name); // LIAPI static bool updateAvailableCommands(); // LIAPI DynamicCommandInstance const* getInstance() const; // LIAPI static DynamicCommandInstance const* getInstance(std::string const& commandName); // }; // class DynamicCommandInstance { // public: // struct ParameterIndex { // DynamicCommandInstance* instance; // size_t index; // ParameterIndex(DynamicCommandInstance* instance, size_t index) // : instance(instance) // , index(index){}; // inline operator size_t() const { // return index; // } // inline DynamicCommand::ParameterData& operator->() { // return instance->parameterDatas.at(index); // } // inline bool isValid() const { // size_t size = instance->parameterDatas.size(); // return index >= 0 && index < size; // } // }; // private: // std::string name; // std::string alias; // std::unique_ptr description; // CommandPermissionLevel permission; // CommandFlag flag; // DynamicCommand::BuilderFn builder = nullptr; // public: // // Parameter Pointers to DynamicCommand Extra Part // size_t commandSize = sizeof(DynamicCommand); // std::unordered_map parameterPtrs = {}; // // Use unique_ptr to keep the address of enumName.c_str() immutable // std::vector> enumNames = {}; // std::vector enumValues = {}; // // unordered_map{ enumName, pair{ enumIndex, enumSize } } // std::unordered_map> enumRanges = {}; // //// unordered_map{ enumName, pair{ enumIndex, enumConstraint } } // // std::unordered_map> enumConstraints = {}; // // SoftEnum // mutable std::unordered_map> softEnums; // std::vector parameterDatas = {}; // private: // std::vector> overloads = {}; // indices of parameter instance // mutable DynamicCommand::CallBackFn callback = nullptr; // HMODULE handle = nullptr; // friend class DynamicCommand; // LIAPI DynamicCommandInstance(std::string const& name, std::string const& description, CommandPermissionLevel permission = CommandPermissionLevel::GameMasters, CommandFlag flag = {(CommandFlagValue)0x80}, HMODULE handle = GetCurrentModule()); // LIAPI bool setBuilder(DynamicCommand::BuilderFn builder); // LIAPI DynamicCommand::BuilderFn initCommandBuilder(); // LIAPI std::vector buildOverload(std::vector const& overload); // public: // virtual ~DynamicCommandInstance(); // LIAPI static std::unique_ptr create(std::string const& name, std::string const& description, CommandPermissionLevel permission, CommandFlag flag, HMODULE handle = GetCurrentModule()); // LIAPI std::string const& setEnum(std::string const& description, std::vector const& values); // LIAPI std::string const& getEnumValue(int index) const; // LIAPI ParameterIndex newParameter(DynamicCommand::ParameterData&& data); // LIAPI ParameterIndex newParameter(std::string const& name, DynamicCommand::ParameterType type, bool optional = false, std::string const& description = "", std::string const& identifier = "", CommandParameterOption parameterOption = (CommandParameterOption)0); // LIAPI ParameterIndex findParameterIndex(std::string const& param); // LIAPI ParameterIndex mandatory(std::string const& name, DynamicCommand::ParameterType type, std::string const& description, std::string const& identifier, CommandParameterOption parameterOption = (CommandParameterOption)0); // LIAPI ParameterIndex mandatory(std::string const& name, DynamicCommand::ParameterType type, std::string const& description, CommandParameterOption parameterOption = (CommandParameterOption)0); // LIAPI ParameterIndex mandatory(std::string const& name, DynamicCommand::ParameterType type, CommandParameterOption parameterOption = CommandParameterOption::None); // LIAPI ParameterIndex optional(std::string const& name, DynamicCommand::ParameterType type, std::string const& description, std::string const& identifier, CommandParameterOption parameterOption = (CommandParameterOption)0); // LIAPI ParameterIndex optional(std::string const& name, DynamicCommand::ParameterType type, std::string const& description, CommandParameterOption parameterOption = (CommandParameterOption)0); // LIAPI ParameterIndex optional(std::string const& name, DynamicCommand::ParameterType type, CommandParameterOption parameterOption = CommandParameterOption::None); // // LIAPI bool addOverload(); // LIAPI bool addOverload(std::vector&& params); // LIAPI bool addOverload(std::vector&& params); // LIAPI bool addOverload(std::vector&& params); // LIAPI bool addOverload(std::vector&& params); // LIAPI bool setAlias(std::string const& alias); // LIAPI void setCallback(DynamicCommand::CallBackFn&& callback) const; // LIAPI void removeCallback() const; // // LIAPI static bool updateSoftEnum(std::string const& name = "") const; // LIAPI std::string setSoftEnum(std::string const& name, std::vector const& values) const; // LIAPI bool addSoftEnumValues(std::string const& name, std::vector const& values) const; // LIAPI bool removeSoftEnumValues(std::string const& name, std::vector const& values) const; // LIAPI static std::vector getSoftEnumValues(std::string const& name); // LIAPI static std::vector getSoftEnumNames(); // template // inline std::enable_if_t::value, ParameterIndex> // toIndex(T const& arg) { // return findParameterIndex(arg); // } // template // inline std::enable_if_t::value, ParameterIndex> // toIndex(T const& arg) = delete; // template <> // inline ParameterIndex toIndex(ParameterIndex const& arg) { // return arg; // } // template <> // inline ParameterIndex toIndex(DynamicCommand::ParameterData const& arg) { // return newParameter(DynamicCommand::ParameterData(arg)); // } // template // inline bool addOverload(Args const&... args) { // return addOverload(std::vector{toIndex(args)...}); // } // template // inline bool addOverload(std::initializer_list&& params) { // return addOverload((std::vector)params); // } // LIAPI std::string const& getCommandName() const; // inline ParameterIndex newParameter(std::string const& name, DynamicCommand::ParameterType type, const char* description, std::string const& identifier, CommandParameterOption parameterOption = (CommandParameterOption)0) { // return newParameter(name, type, false, (std::string const&)description, identifier, parameterOption); // }; // inline bool hasRegistered() const { // return DynamicCommand::getInstance(getCommandName()) != nullptr; // }; // inline void onExecute(DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output) const { // }; // };