diff --git a/LiteLoader/Header/DynamicCommandAPI.h b/LiteLoader/Header/DynamicCommandAPI.h index 9b120ee..d19b617 100644 --- a/LiteLoader/Header/DynamicCommandAPI.h +++ b/LiteLoader/Header/DynamicCommandAPI.h @@ -1,558 +1,558 @@ -// #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 + #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)); -// // -// ///////////////////////////////////////////////////// + /////////////////////////////////////////////////////// + // 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; + 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* + #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>; + 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; + 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; + struct Result { + ParameterType const type; + size_t const offset; + bool const isSet; -// DynamicCommand const* command; -// DynamicCommandInstance const* instance; -// CommandOrigin const* origin; + 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; + 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 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 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::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); -// } -// }; + 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; + struct ParameterPtr { + ParameterType type; -// private: -// size_t offset = -1; + private: + size_t offset = -1; -// friend struct Result; + 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; + 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; -// } -// }; + 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; + 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; + 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; + 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); -// } + 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 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){}; -// }; + 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 (*)(); + 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; -// } + 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); + 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); + public: + static bool onServerCommandsRegister(CommandRegistry& registry); -// friend class DynamicCommandInstance; + friend class DynamicCommandInstance; -// public: -// /*0*/ virtual ~DynamicCommand(); -// /*1*/ virtual void execute(class CommandOrigin const& origin, class CommandOutput& output) const; + 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 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)); -// }; + 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); + // Experiment + LIAPI static bool unregisterCommand(std::string const& name); -// LIAPI static bool updateAvailableCommands(); + LIAPI static bool updateAvailableCommands(); -// LIAPI DynamicCommandInstance const* getInstance() const; + LIAPI DynamicCommandInstance const* getInstance() const; -// LIAPI static DynamicCommandInstance const* getInstance(std::string const& commandName); -// }; + 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; -// } -// }; + 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; + 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 = {}; + 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 = {}; + // 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 = {}; + //// unordered_map{ enumName, pair{ enumIndex, enumConstraint } } + // std::unordered_map> enumConstraints = {}; -// // SoftEnum -// mutable std::unordered_map> softEnums; + // SoftEnum + mutable std::unordered_map> softEnums; -// std::vector parameterDatas = {}; + std::vector parameterDatas = {}; -// private: -// std::vector> overloads = {}; // indices of parameter instance + private: + std::vector> overloads = {}; // indices of parameter instance -// mutable DynamicCommand::CallBackFn callback = nullptr; -// HMODULE handle = nullptr; + mutable DynamicCommand::CallBackFn callback = nullptr; + HMODULE handle = nullptr; -// friend class DynamicCommand; + 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 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); + LIAPI bool setBuilder(DynamicCommand::BuilderFn builder); + LIAPI DynamicCommand::BuilderFn initCommandBuilder(); + LIAPI std::vector buildOverload(std::vector const& overload); -// public: -// virtual ~DynamicCommandInstance(); + 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 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(); + // 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 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 { + 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 { -// }; -// }; + }; + }; diff --git a/LiteLoader/Header/MC/Actor.hpp b/LiteLoader/Header/MC/Actor.hpp index ef8c242..4c3f296 100644 --- a/LiteLoader/Header/MC/Actor.hpp +++ b/LiteLoader/Header/MC/Actor.hpp @@ -9,6 +9,7 @@ #include "Tick.hpp" #include "ActorDamageSource.hpp" #include "SimpleContainer.hpp" +#include "ActorDefinitionIdentifier.hpp" class Actor; class Player; class NetworkIdentifier; @@ -52,8 +53,8 @@ public: //LIAPI bool stopFire(); LIAPI bool hasTag(const string& tag); //LIAPI bool hurtEntity(float damage, ActorDamageCause damageCause = ActorDamageCause::ActorDamageCause_Override); - //LIAPI bool teleport(Vec3 to, int dimID, float x, float y); - //LIAPI bool teleport(Vec3 pos,int dimid); + LIAPI bool teleport(Vec3 to, int dimID, float x, float y); + LIAPI bool teleport(Vec3 pos,int dimid); LIAPI ItemStack* getHandSlot(); LIAPI bool rename(const string& name); LIAPI std::unique_ptr getNbt(); @@ -84,6 +85,15 @@ public: return (dAccess(this, 79) & actorCategory) !=0; }; + Vec2 getRotation() const{ + // Actor::getMapDecorationRotation + return dAccess(this, 65); + }; + ActorDefinitionIdentifier getActorIdentifier() const{ + //ServerPlayer::handleActorPickRequestOnServer Line144 1048-128-8 = 912; + return dAccess(this, 912); + } + #undef AFTER_EXTRA #ifndef DISABLE_CONSTRUCTOR_PREVENTION_ACTOR public: diff --git a/LiteLoader/Header/MC/ActorDamageSource.hpp b/LiteLoader/Header/MC/ActorDamageSource.hpp index 810ca16..ad5ce2c 100644 --- a/LiteLoader/Header/MC/ActorDamageSource.hpp +++ b/LiteLoader/Header/MC/ActorDamageSource.hpp @@ -4,12 +4,55 @@ #include "../Global.h" #define BEFORE_EXTRA +// Include Headers or Declare Types Here +class Actor; + +enum ActorDamageCause : int { + ActorDamageCause_None = -0x01, + ActorDamageCause_Override = 0x00, + ActorDamageCause_Contact = 0x01, + ActorDamageCause_EntityAttack = 0x02, + ActorDamageCause_Projectile = 0x03, + ActorDamageCause_Suffocation = 0x04, + FActorDamageCause_all = 0x05, + ActorDamageCause_Fire = 0x06, + ActorDamageCause_FireTick = 0x07, + ActorDamageCause_Lava = 0x08, + ActorDamageCause_Drowning = 0x09, + ActorDamageCause_BlockExplosion = 0x0A, + ActorDamageCause_EntityExplosion = 0x0B, + ActorDamageCause_Void = 0x0C, + ActorDamageCause_Suicide = 0x0D, + ActorDamageCause_Magic = 0x0E, + ActorDamageCause_Wither = 0x0F, + ActorDamageCause_Starve = 0x10, + ActorDamageCause_Anvil = 0x11, + ActorDamageCause_Thorns = 0x12, + ActorDamageCause_FallingBlock = 0x13, + ActorDamageCause_Piston = 0x14, + ActorDamageCause_FlyIntoWall = 0x15, + ActorDamageCause_Magma = 0x16, + ActorDamageCause_Fireworks = 0x17, + ActorDamageCause_Lightning = 0x18, + ActorDamageCause_Charging = 0x19, + ActorDamageCause_Temperature = 0x1A, + ActorDamageCause_Freezing = 0x1B, + ActorDamageCause_Stalactite = 0x1C, + ActorDamageCause_Stalagmite = 0x1D, + ActorDamageCause_All = 0x1F, +}; #undef BEFORE_EXTRA class ActorDamageSource { #define AFTER_EXTRA + // Add Member There + ActorDamageCause mCause; + char filler[4]; + +public: + LIAPI Actor* getEntity(); #undef AFTER_EXTRA #ifndef DISABLE_CONSTRUCTOR_PREVENTION_ACTORDAMAGESOURCE diff --git a/LiteLoader/Header/MC/ActorDefinitionIdentifier.hpp b/LiteLoader/Header/MC/ActorDefinitionIdentifier.hpp index cf787fd..bcfeb13 100644 --- a/LiteLoader/Header/MC/ActorDefinitionIdentifier.hpp +++ b/LiteLoader/Header/MC/ActorDefinitionIdentifier.hpp @@ -18,7 +18,7 @@ std::string fullname; // 96 HashedString canonicalHash; // 128 public: - inline const std::string getCanonicalName(){ + inline std::string const& getCanonicalName() const{ return this->canonicalHash.getString(); } #undef AFTER_EXTRA diff --git a/LiteLoader/Header/MC/AvailableCommandsPacket.hpp b/LiteLoader/Header/MC/AvailableCommandsPacket.hpp index 3a5a10f..75508e3 100644 --- a/LiteLoader/Header/MC/AvailableCommandsPacket.hpp +++ b/LiteLoader/Header/MC/AvailableCommandsPacket.hpp @@ -5,12 +5,111 @@ #include "Packet.hpp" #define BEFORE_EXTRA +// Include Headers or Declare Types Here +#include "CommandFlag.hpp" +enum CommandPermissionLevel : char; #undef BEFORE_EXTRA class AvailableCommandsPacket : public Packet { #define AFTER_EXTRA + // Add Member There +public: + struct EnumData + { + std::string name; + std::vector valueIndices; + };//56 + struct ConstrainedValueData + { + int enumIndex; + int enumNameIndex; + std::vector indices; + }; + struct ParamData + { + std::string desc; + unsigned int sym; + }; + struct OverloadData + { + std::vector datas; + }; + struct CommandData + { + std::string name; //0 + std::string description; //32 + CommandFlag flag; //64 + CommandPermissionLevel perm; //66 + std::vector overloads; //72 + signed int aliasIndex; //96 + };//104 + struct SoftEnumData + { + std::string name; + std::vector values; + };//56 + + std::vector mAllEnums;//48 + std::vector mAllSuffix;//72 + std::vector mEnumDatas;//96 + std::vector mCommandDatas;//120 + std::vector mSoftEnums;//144 + std::vector mConstrainedValueDatas; //168 + inline void test() + { + static_assert(sizeof(AvailableCommandsPacket) == 192); + static_assert(sizeof(EnumData) == 56); + static_assert(sizeof(CommandData) == 104); + static_assert(offsetof(CommandData, perm) == 66); + static_assert(offsetof(AvailableCommandsPacket, mAllEnums) == 48); + static_assert(offsetof(AvailableCommandsPacket, mAllSuffix) == 72); + static_assert(offsetof(AvailableCommandsPacket, mConstrainedValueDatas) == 168); + } + +public: + inline std::vector getEnumNames() + { + std::vector names; + for (auto& data : mEnumDatas) { + names.push_back(data.name); + } + return names; + } + inline std::vector getSoftEnumNames() + { + std::vector names; + for (auto& data : mSoftEnums) + { + names.push_back(data.name); + } + return names; + } + inline std::vector getEnumValues(std::string const& name) + { + std::vector values; + for (auto& data : mEnumDatas) + { + if (data.name == name) + { + for (auto& index : data.valueIndices) { + values.push_back(mAllEnums.at(index)); + } + break; + } + } + return values; + } + inline std::vector getSoftEnumValues(std::string const& name) + { + for (auto& data : mSoftEnums) + { + if (data.name == name) + return data.values; + } + return {}; + } #undef AFTER_EXTRA #ifndef DISABLE_CONSTRUCTOR_PREVENTION_AVAILABLECOMMANDSPACKET diff --git a/LiteLoader/Header/MC/Command.hpp b/LiteLoader/Header/MC/Command.hpp index 47dffb7..21f1588 100644 --- a/LiteLoader/Header/MC/Command.hpp +++ b/LiteLoader/Header/MC/Command.hpp @@ -4,19 +4,79 @@ #include "../Global.h" #define BEFORE_EXTRA +// Include Headers or Declare Types Here +#include "CommandRegistry.hpp" +#include "CommandParameterData.hpp" +#include "CommandFlag.hpp" +class CommandRegistry; +// class CommandRegistry::Symbol; +enum CommandPermissionLevel : char { + Any = 0, + GameMasters = 1, + Admin = 2, + HostPlayer = 3, + Console = 4, + Internal = 5, +}; + +enum class OriginType : char { + Player = 0, + Block = 1, + MinecartBlock = 2, + DevConsole = 3, + Test = 4, + AutomationPlayer = 5, + ClientAutomation = 6, + Server = 7, + Actor = 8, + Virtual = 9, + GameArgument = 10, + ActorServer = 11, + Precompiled = 12, + GameDirectorEntity = 13, + Script = 14, + ExecuteContext = 15, + + DedicatedServer = 7, // Server +}; + +class CommandOutput; #undef BEFORE_EXTRA class Command { #define AFTER_EXTRA + // Add Member There + +protected: + int version; // 8 + CommandRegistry* registry; // 16 + CommandRegistry::Symbol symbol; // 24, + CommandPermissionLevel permission; // 28 + CommandFlag flag; // 30 + +public: + template + static bool checkHasTargets(CommandSelectorResults const& a, CommandOutput& b) { + bool (*sym)(CommandSelectorResults const& a, CommandOutput& b); + if constexpr (std::is_same()) { + sym = (decltype(sym))dlsym("??$checkHasTargets@VActor@@@Command@@KA_NAEBV?$CommandSelectorResults@VActor@@@@AEAVCommandOutput@@@Z"); + } else { + sym = (decltype(sym))dlsym("??$checkHasTargets@VPlayer@@@Command@@KA_NAEBV?$CommandSelectorResults@VPlayer@@@@AEAVCommandOutput@@@Z"); + } + return sym(a, b); + } + std::string getCommandName() const{ + return this->registry->symbolToString(this->symbol); + }; #undef AFTER_EXTRA #ifndef DISABLE_CONSTRUCTOR_PREVENTION_COMMAND public: class Command& operator=(class Command const &) = delete; Command(class Command const &) = delete; - Command() = delete; + Command(){}; #endif public: diff --git a/LiteLoader/Header/MC/CommandContext.hpp b/LiteLoader/Header/MC/CommandContext.hpp index 3f317ab..560fb6a 100644 --- a/LiteLoader/Header/MC/CommandContext.hpp +++ b/LiteLoader/Header/MC/CommandContext.hpp @@ -4,12 +4,38 @@ #include "../Global.h" #define BEFORE_EXTRA - +// Include Headers or Declare Types Here +#include +#include "CommandOrigin.hpp" +class CommandOrigin; #undef BEFORE_EXTRA class CommandContext { #define AFTER_EXTRA + // Add Member There + +public: + std::string command; + std::unique_ptr origin; + int Version = 18; + + std::string& getCmd() { + return command; + } + class CommandOrigin& getOrigin() { + return *origin; + } + + template + [[deprecated]] + CommandContext(T&& x, CommandOrigin* o) + : command(std::forward(x)) + , origin(o){}; + template + CommandContext(T&& x, std::unique_ptr ori) + : command(std::forward(x)) + , origin(std::move(ori)){}; #undef AFTER_EXTRA #ifndef DISABLE_CONSTRUCTOR_PREVENTION_COMMANDCONTEXT diff --git a/LiteLoader/Header/MC/CommandFlag.hpp b/LiteLoader/Header/MC/CommandFlag.hpp new file mode 100644 index 0000000..e750cab --- /dev/null +++ b/LiteLoader/Header/MC/CommandFlag.hpp @@ -0,0 +1,32 @@ +#pragma once + +enum class CommandFlagValue : unsigned short +{ + None = 0, + Usage = 1, + Visibility2 = 2, + Visibility4 = 4, + Visibility6 = 6, + Sync = 8, + Execute = 16, + Type = 32, + Cheat = 64, +}; +struct CommandFlag +{ + CommandFlagValue value; + + constexpr bool operator==(CommandFlag const& rhs) const noexcept + { + return value == rhs.value; + } + constexpr bool operator!=(CommandFlag const& rhs) const noexcept + { + return value != rhs.value; + } + CommandFlag& operator|=(CommandFlag const& rhs) + { + value = (CommandFlagValue)((char)rhs.value | (char)value); + return *this; + } +}; \ No newline at end of file diff --git a/LiteLoader/Header/MC/CommandIntegerRange.hpp b/LiteLoader/Header/MC/CommandIntegerRange.hpp new file mode 100644 index 0000000..559ca6d --- /dev/null +++ b/LiteLoader/Header/MC/CommandIntegerRange.hpp @@ -0,0 +1,57 @@ +/** + * @file CommandIntegerRange.hpp + * @note This Header is auto generated by LiteLoaderBDS Toolchain. + * + */ +#pragma once +#include "../Global.h" + +class CommandIntegerRange { + +#define AFTER_EXTRA +public: + int min, max; + bool inverted; + + CommandIntegerRange(){ + this->min = std::numeric_limits::min(); + this->max = std::numeric_limits::max(); + this->inverted = 0; + } + CommandIntegerRange(int minVal,int maxVal,bool invert){ + this->min = minVal; + this->max = maxVal; + this->inverted = invert; + }; + bool isWithinRange(int value) const{ + bool temp = false; + if(this->min <= value) + temp = this->max >= value; + return temp != this->inverted; + }; + +#undef AFTER_EXTRA +#ifndef DISABLE_CONSTRUCTOR_PREVENTION_COMMANDINTEGERRANGE +public: + class CommandIntegerRange& operator=(class CommandIntegerRange const &) = delete; + CommandIntegerRange(class CommandIntegerRange const &) = delete; +#endif + +public: + /** + * @symbol ??0CommandIntegerRange@@QEAA@XZ + * @hash -2077189482 + */ + //MCAPI CommandIntegerRange(); + /** + * @symbol ??0CommandIntegerRange@@QEAA@HH_N@Z + * @hash -697074593 + */ + //MCAPI CommandIntegerRange(int, int, bool); + /** + * @symbol ?isWithinRange@CommandIntegerRange@@QEBA_NH@Z + * @hash 1413957599 + */ + //MCAPI bool isWithinRange(int) const; + +}; \ No newline at end of file diff --git a/LiteLoader/Header/MC/CommandItem.hpp b/LiteLoader/Header/MC/CommandItem.hpp index 7f4129a..f5939e7 100644 --- a/LiteLoader/Header/MC/CommandItem.hpp +++ b/LiteLoader/Header/MC/CommandItem.hpp @@ -10,13 +10,22 @@ class CommandItem { #define AFTER_EXTRA + // Add Member There + int version; //0 + int itemId; //4 + +public: + CommandItem(){ + this->version = 0; + this->itemId = 0; + } #undef AFTER_EXTRA #ifndef DISABLE_CONSTRUCTOR_PREVENTION_COMMANDITEM public: class CommandItem& operator=(class CommandItem const &) = delete; CommandItem(class CommandItem const &) = delete; - CommandItem() = delete; + //CommandItem() = delete; #endif public: diff --git a/LiteLoader/Header/MC/CommandMessage.hpp b/LiteLoader/Header/MC/CommandMessage.hpp index f29401b..e53563e 100644 --- a/LiteLoader/Header/MC/CommandMessage.hpp +++ b/LiteLoader/Header/MC/CommandMessage.hpp @@ -10,13 +10,24 @@ class CommandMessage { #define AFTER_EXTRA + // Add Member There + struct MessageComponent + { + char filler[200]; + void* unk[2]; + std::vector unk2[5]; + }; + std::vector components; + +public: + CommandMessage(){}; #undef AFTER_EXTRA #ifndef DISABLE_CONSTRUCTOR_PREVENTION_COMMANDMESSAGE public: class CommandMessage& operator=(class CommandMessage const &) = delete; CommandMessage(class CommandMessage const &) = delete; - CommandMessage() = delete; + //CommandMessage() = delete; #endif public: diff --git a/LiteLoader/Header/MC/CommandOrigin.hpp b/LiteLoader/Header/MC/CommandOrigin.hpp index 65dac7c..f879942 100644 --- a/LiteLoader/Header/MC/CommandOrigin.hpp +++ b/LiteLoader/Header/MC/CommandOrigin.hpp @@ -3,14 +3,20 @@ #define AUTO_GENERATED #include "../Global.h" #include "Json.hpp" +#include "Bedrock.hpp" #define BEFORE_EXTRA - +class ServerPlayer; +class CommandArea; +enum CommandOriginType : char; #undef BEFORE_EXTRA class CommandOrigin { #define AFTER_EXTRA + // Add Member There +public: + LIAPI ServerPlayer* getPlayer() const; #undef AFTER_EXTRA #ifndef DISABLE_CONSTRUCTOR_PREVENTION_COMMANDORIGIN diff --git a/LiteLoader/Header/MC/CommandOutput.hpp b/LiteLoader/Header/MC/CommandOutput.hpp index 6066c7d..eb8c59e 100644 --- a/LiteLoader/Header/MC/CommandOutput.hpp +++ b/LiteLoader/Header/MC/CommandOutput.hpp @@ -4,12 +4,128 @@ #include "../Global.h" #define BEFORE_EXTRA +// Include Headers or Declare Types Here +#include "CommandOutputParameter.hpp" +#include "CommandOrigin.hpp" +#include "Command.hpp" +#include "ServerPlayer.hpp" +#include "../Utils/PluginOwnData.h" +#include "../I18nAPI.h" +#define POD_COMMANDOUTPUT_LANGCODE ("_ll_plugin_cmdoutp_langcode_" + std::to_string((uint64_t)this)) #undef BEFORE_EXTRA class CommandOutput { #define AFTER_EXTRA + // Add Member There +public: + + int getSuccessCount() const{ + //DayLockCommand::execute Line91 + return dAccess(this,10); + }; + + void success(){ + int successCount = dAccess(this,10); + ++successCount; + dAccess(this,10) = successCount; + }; + /** + * @brief Output a message(without I18nBase). + * + * @param str The message + */ + LIAPI void addMessage(const std::string& str); + /** + * @brief Output a success message(without I18nBase). + * + * @param str The message + */ + LIAPI void success(const string& str); + /** + * @brief Output a success message(without I18nBase). + * + * @param str The message + */ + LIAPI void error(const string& str); + + /** + * @brief Set the output language code of this CommandOutput object. + * + * @param code The language code + */ + inline void setLanguageCode(const std::string& code = "") { + PluginOwnData::set(POD_COMMANDOUTPUT_LANGCODE, code); + } + /** + * @brief Set the output language code of this CommandOutput object(convenience func). + * + * @param ori The command origin object for the CommandOutput object + */ + inline void setLanguageCode(const CommandOrigin& ori) { + std::string code = "en_US"; + if (PluginOwnData::has(I18nBase::POD_KEY)) { + auto& i18n = PluginOwnData::get(I18nBase::POD_KEY); + switch ((OriginType)ori.getOriginType()) { + case OriginType::Player: + code = ori.getPlayer()->getLanguageCode(); + break; + default: + code = i18n.getDefaultLocaleName(); + break; + } + } + PluginOwnData::set(POD_COMMANDOUTPUT_LANGCODE, code); + } + + /** + * @brief Output a message(I18nBase, convenience func). + * + * @tparam Args ... + * @param format The str to translate and format + * @param args The format arguments + * @see tr + */ + template + inline void trAddMessage(const std::string& format, Args&&... args) { + if (PluginOwnData::has(POD_COMMANDOUTPUT_LANGCODE)) + this->addMessage(trl(PluginOwnData::get(POD_COMMANDOUTPUT_LANGCODE), format, std::forward(args)...)); + else + this->addMessage(tr(format, std::forward(args)...)); + } + + /** + * @brief Output a success message(I18nBase, convenience func). + * + * @tparam Args ... + * @param format The str to translate and format + * @param args The format arguments + * @see tr + */ + template + inline void trSuccess(const std::string& format, Args&&... args) { + if (PluginOwnData::has(POD_COMMANDOUTPUT_LANGCODE)) + this->success(trl(PluginOwnData::get(POD_COMMANDOUTPUT_LANGCODE), format, std::forward(args)...)); + else + this->success(tr(format, std::forward(args)...)); + } + + /** + * @brief Output a error message(I18nBase, convenience func). + * + * @tparam Args ... + * @param format The str to translate and format + * @param args The format arguments + * @see tr + */ + template + inline void trError(const std::string& format, Args&&... args) { + if (PluginOwnData::has(POD_COMMANDOUTPUT_LANGCODE)) + this->error(trl(PluginOwnData::get(POD_COMMANDOUTPUT_LANGCODE), format, std::forward(args)...)); + else + this->error(tr(format, std::forward(args)...)); + } #undef AFTER_EXTRA #ifndef DISABLE_CONSTRUCTOR_PREVENTION_COMMANDOUTPUT diff --git a/LiteLoader/Header/MC/CommandOutputParameter.hpp b/LiteLoader/Header/MC/CommandOutputParameter.hpp index a3096ef..fd35f44 100644 --- a/LiteLoader/Header/MC/CommandOutputParameter.hpp +++ b/LiteLoader/Header/MC/CommandOutputParameter.hpp @@ -10,12 +10,20 @@ class CommandOutputParameter { #define AFTER_EXTRA + enum NoCountType; + std::string str; + int type; +public: + CommandOutputParameter(class CommandOutputParameter const & output){ + this->str = output.str; + this->type = output.type; + }; #undef AFTER_EXTRA #ifndef DISABLE_CONSTRUCTOR_PREVENTION_COMMANDOUTPUTPARAMETER public: class CommandOutputParameter& operator=(class CommandOutputParameter const &) = delete; - CommandOutputParameter(class CommandOutputParameter const &) = delete; +// CommandOutputParameter(class CommandOutputParameter const &) = delete; CommandOutputParameter() = delete; #endif diff --git a/LiteLoader/Header/MC/CommandParameterData.hpp b/LiteLoader/Header/MC/CommandParameterData.hpp index c8f0bd3..f3f3276 100644 --- a/LiteLoader/Header/MC/CommandParameterData.hpp +++ b/LiteLoader/Header/MC/CommandParameterData.hpp @@ -4,13 +4,77 @@ #include "../Global.h" #define BEFORE_EXTRA +// Include Headers or Declare Types Here +#include +#include "CommandRegistry.hpp" + +enum class CommandParameterDataType { + NORMAL, + ENUM, + SOFT_ENUM, + POSIFIX, +}; +enum SemanticConstraint: unsigned char +{ + NoneConstraint = 0, + RequiresCheatsEnabled=1, + RequiresElevatedPermissions=2, + RequiresHostPermissions=4, + VALUE_MASK=8, +}; +enum CommandParameterOption : unsigned char +{ + None = 0, + EnumAutocompleteExpansion = 1, + HasSemanticConstraint = 2, //be used in block or item name enum + EnumAsChainedCommand = 4, //be used in NewExecuteCommand +}; +class CommandRegistry; #undef BEFORE_EXTRA class CommandParameterData { #define AFTER_EXTRA +// Add Member There +#define DISABLE_CONSTRUCTOR_PREVENTION_COMMANDPARAMETERDATA + using ParseFn = bool (CommandRegistry::*)( + void*, CommandRegistry::ParseToken const&, CommandOrigin const&, int, std::string&, + std::vector&) const; +public: + typeid_t tid; // 0 + ParseFn parser; // 8 + std::string name; // 16 + char const* desc; // 48 + int unk56; // 56 + CommandParameterDataType type; // 60 + int offset; // 64 + int flag_offset; // 68 + bool mand; // 72 + unsigned char options; // 73 + + CommandParameterData() + : tid(tid){}; + + CommandParameterData( + typeid_t tid, ParseFn parser, std::string_view describe, + CommandParameterDataType type, char const* enumName, int offset, bool optional, int flag_offset) + : tid(tid) + , parser(parser) + , name(describe) + , desc(enumName) + , unk56(-1) + , type(type) + , offset(offset) + , flag_offset(flag_offset) + , mand(optional) + , options(0){}; + + CommandParameterData & addOptions(enum CommandParameterOption options){ + this->options = this->options | options; + return *this; + }; #undef AFTER_EXTRA #ifndef DISABLE_CONSTRUCTOR_PREVENTION_COMMANDPARAMETERDATA public: diff --git a/LiteLoader/Header/MC/CommandPosition.hpp b/LiteLoader/Header/MC/CommandPosition.hpp index c7eb2f3..85f3a8a 100644 --- a/LiteLoader/Header/MC/CommandPosition.hpp +++ b/LiteLoader/Header/MC/CommandPosition.hpp @@ -4,13 +4,52 @@ #include "../Global.h" #define BEFORE_EXTRA - +#include "CompoundTag.hpp" #undef BEFORE_EXTRA class CommandPosition { #define AFTER_EXTRA +// Add Member There +#define DISABLE_CONSTRUCTOR_PREVENTION_COMMANDPOSITION + float offsetX; + float offsetY; + float offsetZ; + bool relativeX; + bool relativeY; + bool relativeZ; + bool local; +public: + CommandPosition(){ + this->offsetX = 0; + this->offsetY = 0; + this->offsetZ = 0; + this->relativeX = 1; + this->relativeY = 1; + this->relativeZ = 1; + this->local = 0; + } + CommandPosition(Vec3 *pos){ + this->offsetX = pos->x; + this->offsetY = pos->y; + this->offsetZ = pos->z; + this->relativeX = pos->x + 2; + this->relativeY = pos->y + 2; + this->relativeZ = pos->z + 2; + this->local = 0; + } + CompoundTag serialize() const{ + CompoundTag tag; + tag.putFloat("OffsetX",0); + tag.putFloat("OffsetY",0); + tag.putFloat("OffsetZ",0); + tag.putBoolean("RelativeX",this->relativeX); + tag.putBoolean("RelativeY",this->relativeY); + tag.putBoolean("RelativeZ",this->relativeZ); + tag.putBoolean("Local",this->local); + return tag; + }; #undef AFTER_EXTRA #ifndef DISABLE_CONSTRUCTOR_PREVENTION_COMMANDPOSITION public: diff --git a/LiteLoader/Header/MC/CommandPositionFloat.hpp b/LiteLoader/Header/MC/CommandPositionFloat.hpp new file mode 100644 index 0000000..eb3e43d --- /dev/null +++ b/LiteLoader/Header/MC/CommandPositionFloat.hpp @@ -0,0 +1,6 @@ +#pragma once +#include "CommandPosition.hpp" + +class CommandPositionFloat : public CommandPosition +{ +}; \ No newline at end of file diff --git a/LiteLoader/Header/MC/CommandRawText.hpp b/LiteLoader/Header/MC/CommandRawText.hpp new file mode 100644 index 0000000..c43d49a --- /dev/null +++ b/LiteLoader/Header/MC/CommandRawText.hpp @@ -0,0 +1,32 @@ +/** + * @file CommandRawText.hpp + * @note This Header is auto generated by LiteLoaderBDS Toolchain. + * + */ +#pragma once +#include "../Global.h" + +class CommandRawText { + +#define AFTER_EXTRA +// Add Member There + std::string text; + +public: +inline operator std::string()const +{ + return text; +} + +std::string const & getText() const{ + return this->text; +} +#define DISABLE_CONSTRUCTOR_PREVENTION_COMMANDRAWTEXT +#undef AFTER_EXTRA +#ifndef DISABLE_CONSTRUCTOR_PREVENTION_COMMANDRAWTEXT +public: + class CommandRawText& operator=(class CommandRawText const &) = delete; + CommandRawText(class CommandRawText const &) = delete; + CommandRawText() = delete; +#endif +}; \ No newline at end of file diff --git a/LiteLoader/Header/MC/CommandRegistry.hpp b/LiteLoader/Header/MC/CommandRegistry.hpp index 699002a..8a559fd 100644 --- a/LiteLoader/Header/MC/CommandRegistry.hpp +++ b/LiteLoader/Header/MC/CommandRegistry.hpp @@ -4,12 +4,112 @@ #include "../Global.h" #define BEFORE_EXTRA +// Include Headers or Declare Types Here +enum CommandPermissionLevel : char; +enum class CommandFlagValue : unsigned short; +enum SemanticConstraint : unsigned char; +class CommandParameterData; +#include "CommandFlag.hpp" +#include +//#include "typeid_t.hpp" +//#include "Command.hpp" +#include "CommandPosition.hpp" +#include "CommandPositionFloat.hpp" +#include "CommandMessage.hpp" +#include "CommandSelector.hpp" +#include "CommandOrigin.hpp" +#include "CommandVersion.hpp" +#include "CommandRawText.hpp" +#include "CommandItem.hpp" +#include "CommandIntegerRange.hpp" +#include "ActorDamageSource.hpp" +#include "ActorDefinitionIdentifier.hpp" + +#pragma region typeid + template class typeid_t { public: - typeid_t& operator=(typeid_t const&) = delete; - typeid_t(typeid_t const&) = delete; + inline static unsigned short count = 0; + unsigned short value; + typeid_t(typeid_t const& id) + : value(id.value){}; + typeid_t(unsigned short value) + : value(value){}; }; +template <> +class typeid_t { +public: + MCAPI static unsigned short count; + unsigned short value; + typeid_t(typeid_t const& id) + : value(id.value){}; + typeid_t(unsigned short value) + : value(value){}; +}; +template +typeid_t type_id() { + static typeid_t id = typeid_t::count++; + return id; +} + +template MCAPI typeid_t type_id(); +template MCAPI typeid_t type_id>(); +// template MCAPI typeid_t type_id(); +// template MCAPI typeid_t type_id(); +template MCAPI typeid_t type_id(); +template MCAPI typeid_t type_id(); +template MCAPI typeid_t type_id(); +template MCAPI typeid_t type_id(); +template MCAPI typeid_t type_id(); +template MCAPI typeid_t type_id>(); +template MCAPI typeid_t type_id>(); +template MCAPI typeid_t type_id(); +template MCAPI typeid_t type_id(); +template MCAPI typeid_t type_id(); +template MCAPI typeid_t type_id(); +template MCAPI typeid_t type_id(); +template MCAPI typeid_t type_id(); +template MCAPI typeid_t type_id(); +template MCAPI typeid_t type_id(); +template MCAPI typeid_t type_id>(); +template MCAPI typeid_t type_id>(); +// template MCAPI typeid_t type_id(); +template MCAPI typeid_t type_id(); +// template MCAPI typeid_t type_id(); + +template <> +inline typeid_t type_id() { + static typeid_t id = *(typeid_t*)dlsym_real("?id@?1???$type_id@VCommandRegistry@@PEBUActorDefinitionIdentifier@@@@YA?AV?$typeid_t@VCommandRegistry@@@@XZ@4V1@A"); + // static typeid_t id = ([]() -> typeid_t { + // CommandParameterData data = SymCall("??$mandatory@VRideCommand@@PEBUActorDefinitionIdentifier@@@commands@@YA?AVCommandParameterData@@PEQRideCommand@@PEBUActorDefinitionIdentifier@@PEBDPEQ2@_N@Z", + // CommandParameterData, void*, char const*, uintptr_t)(nullptr, "entityType", 0); + // return data.tid; + // })(); + return id; +}; + +template <> +inline typeid_t type_id() { + static typeid_t id = *(typeid_t*)dlsym_real("?id@?1???$type_id@VCommandRegistry@@VCommandItem@@@@YA?AV?$typeid_t@VCommandRegistry@@@@XZ@4V1@A"); + return id; +}; + +template <> +inline typeid_t type_id() { + static typeid_t id = *(typeid_t*)dlsym_real("?id@?1???$type_id@VCommandRegistry@@_N@@YA?AV?$typeid_t@VCommandRegistry@@@@XZ@4V1@A"); + return id; +}; + + +template <> +inline typeid_t type_id() { + static typeid_t id = *(typeid_t*)dlsym_real("?id@?1???$type_id@VCommandRegistry@@PEBVBlock@@@@YA?AV?$typeid_t@VCommandRegistry@@@@XZ@4V1@A"); + return id; +}; + +#pragma endregion + #undef BEFORE_EXTRA class CommandRegistry { @@ -18,27 +118,513 @@ class CommandRegistry { public: struct ParseTable; class Symbol { - Symbol& operator=(Symbol const&) = delete; - Symbol(Symbol const&) = delete; + public: + unsigned val; + MCAPI Symbol(unsigned __int64 = -1); + MCAPI Symbol(class Symbol const&); + MCAPI unsigned __int64 toIndex() const; + MCAPI int value() const; + inline bool operator==(Symbol const& right) const { + return val == right.val; + } + inline std::string toString() const { + return Global->symbolToString(*this); + } + inline std::string toDebugString() const { + return fmt::format("", toString(), val); + } }; struct ParseToken { - ParseToken() = delete; - ParseToken(ParseToken const&) = delete; - ParseToken(ParseToken const&&) = delete; + std::unique_ptr child; + std::unique_ptr next; + CommandRegistry::ParseToken* parent; + const char* text; // 24 + uint32_t length; // 32 + Symbol type; // 36 + MCAPI std::string toString() const; + //{ + // if (text) + // return std::string(text, length); + // auto v6 = child.get(); + // auto v8 = child.get(); + // while (v8->child) + // { + // v8 = v8->child.get(); + // } + // while (v6->child || v6->next) + // { + // v6 = v6->next ? v6->next.get() : v6->child.get(); + // } + // auto v10 = v6->text + v6->length; + // auto v11 = v8->text; + // return std::string(v11, v10 - v11); + //}; + inline std::string toDebugString() const { + return fmt::format("", toString()); + } }; + static_assert(sizeof(ParseToken) == 40); + using ParseFn = bool (CommandRegistry::*)( + void*, ParseToken const&, CommandOrigin const&, int, std::string&, + std::vector&) const; struct Overload { - Overload() = delete; - Overload(Overload const&) = delete; - Overload(Overload const&&) = delete; + using FactoryFn = std::unique_ptr (*)(); + + CommandVersion version; // 0 + FactoryFn factory; // 8 + std::vector params; // 16 + unsigned char unk; // 40 + std::vector syms = {}; // 48 + + LIAPI Overload(CommandVersion version, + FactoryFn factory, + std::vector&& args); + + LIAPI ~Overload(); + + inline std::string toDebugString() { + return fmt::format(""); + } }; struct Signature { - Signature() = delete; - Signature(Signature const&) = delete; - Signature(Signature const&&) = delete; + std::string name; // 0 + std::string desc; // 32 + std::vector overloads; // 64 + CommandPermissionLevel perm; // 88 + Symbol main_symbol; // 92 + Symbol alt_symbol; // 96 + CommandFlag flag; // 100 + int unk72; + int unk76; + int unk80; + bool b84; + + inline Signature(std::string_view name, + std::string_view desc, + CommandPermissionLevel perm, + Symbol symbol, + CommandFlag flag) + : name(name), desc(desc), perm(perm), main_symbol(symbol), flag(flag) { + } + + inline std::string toDebugString() const { + return fmt::format("", name); + } }; + + struct SoftEnum { + std::string name; // 0 + std::vector list; // 32 + }; + + struct Enum { + std::string name; // 0 + typeid_t type; // 32 + ParseFn parse; // 40 + std::vector> values; // 48 + + inline std::string toDebugString() const { + return fmt::format("", name); + } + }; + + LIAPI static std::vector getEnumNames(); + LIAPI static std::vector getSoftEnumNames(); + LIAPI static std::vector getEnumValues(std::string const& name); + LIAPI static std::vector getSoftEnumValues(std::string const& name); + LIAPI static std::string getCommandFullName(std::string const& name); + // Experiment + LIAPI bool unregisterCommand(std::string const& name); + + template + struct DefaultIdConverter { + template + static Target convert(Source source) { + return (Target)source; + } + uint64_t operator()(Type value) const { + return convert(value); + } + Type operator()(uint64_t value) const { + return convert(value); + } + }; + +#ifdef COMMAND_REGISTRY_EXTRA + inline static std::string toString(std::vector const& syms) { + std::ostringstream oss; + bool first = true; + for (auto& sym : syms) { + if (!first) + oss << ", "; + oss << sym.toString(); + first = false; + } + return oss.str(); + } + struct ParseRule { + Symbol sym; + std::function func; + std::vector syms; + CommandVersion version; + inline std::string toDebugString() const { + + return fmt::format("", sym.toDebugString(), toString(syms)); + } + }; + struct ParseTable { + std::map> first; + std::map> follow; + std::map, int> predict; + inline std::string toDebugString() const { + std::ostringstream oss; + bool f = true; + for (auto& [k, v] : first) { + if (!f) + oss << ", "; + oss << k.toString() << ":[" << toString(v) << "]"; + f = false; + } + oss << "\n"; + for (auto& [k, v] : follow) { + if (!f) + oss << ", "; + oss << k.toString() << ":[" << toString(v) << "]"; + f = false; + } + return fmt::format("[{}]", oss.str()); + } + }; + struct OptionalParameterChain { + int parameterCount; + int followingRuleIndex; + Symbol paramSymbol; + inline std::string toDebugString() const { + return fmt::format("", parameterCount, followingRuleIndex, paramSymbol.toDebugString()); + } + }; + struct Factorization { + Symbol sym; + inline std::string toDebugString() const { + return fmt::format("", sym.toDebugString()); + } + }; + struct RegistryState { + int signatureCount; + int enumValueCount; + int postfixCount; + int enumCount; + int factorizationCount; + int optionalCount; + int ruleCount; + int softEnumCount; + int constraintCount; + std::vector constrainedValueCount; + std::vector softEnumValuesCount; + }; + struct ConstrainedValue { + Symbol mValue; + Symbol mEnum; + std::vector mConstraints; + inline std::string toDebugString() const { + std::ostringstream oss; + bool first = true; + for (auto& i : mConstraints) { + if (!first) + oss << ", "; + oss << (int)i; + first = false; + } + return fmt::format("", mValue.toDebugString(), mEnum.toDebugString(), oss.str()); + } + }; + + using CommandOverrideFunctor = std::function, class std::allocator> const&)>; + using ParamSymbols = std::array; + + std::function mGetScoreForObjective; // 0 + std::function mNetworkUpdateCallback; // 64 + std::vector mRules; // 128 + // map + std::map mParseTableMap; // 152 + std::vector mOptionals; // 168 + std::vector mEnumValues; // 192 + std::vector mEnums; // 216 + std::vector mFactorizations; // 240 + std::vector mPostfixes; // 264 + std::map mEnumLookup; // 288 + std::map mEnumValueLookup; // 304 + std::vector mCommandSymbols; // 320 + std::map mSignatures; // 344 + std::map, int> mTypeLookup; // 360 + std::map unk376; // 376 + std::map mAliases; // 392 + std::vector mSemanticConstraints; // 408 + std::map mSemanticConstraintLookup; // 432 + std::vector mConstrainedValues; // 448 + std::map, unsigned int> mConstrainedValueLookup; // 472 + std::vector mSoftEnums; // 488 + std::map mSoftEnumLookup; // 512 + std::vector mStateStack; // 528 + ParamSymbols mArgs; // 552 + CommandOverrideFunctor mCommandOverrideFunctor; // 640 + // 704 + + inline void printAll() const; + inline void printSize() const; + + void test() { + auto mParseTableMapCopy = mParseTableMap; + auto mEnumLookupCopy = mEnumLookup; + auto mEnumValueLookupCopy = mEnumValueLookup; + auto mSignaturesCopy = mSignatures; + auto mTypeLookupCopy = mTypeLookup; + auto unk376Copy = unk376; + auto mAliasesCopy = mAliases; + auto mSemanticConstraintLookupCopy = mSemanticConstraintLookup; + auto mConstrainedValueLookupCopy = mConstrainedValueLookup; + auto mSoftEnumLookupCopy = mSoftEnumLookup; + + constexpr auto size = sizeof(CommandRegistry); + + static_assert(sizeof(Enum) == 72); + static_assert(sizeof(ParseTable) == 48); + static_assert(sizeof(ParseRule) == 104); + static_assert(sizeof(CommandRegistry) == 0x2c0); + static_assert(offsetof(CommandRegistry, mGetScoreForObjective) == 0); + static_assert(offsetof(CommandRegistry, mNetworkUpdateCallback) == 64); + static_assert(offsetof(CommandRegistry, mRules) == 128); + static_assert(offsetof(CommandRegistry, mParseTableMap) == 152); + static_assert(offsetof(CommandRegistry, mOptionals) == 168); + static_assert(offsetof(CommandRegistry, mEnumValues) == 192); + static_assert(offsetof(CommandRegistry, mEnums) == 216); + static_assert(offsetof(CommandRegistry, mFactorizations) == 240); + static_assert(offsetof(CommandRegistry, mPostfixes) == 264); + static_assert(offsetof(CommandRegistry, mEnumLookup) == 288); + static_assert(offsetof(CommandRegistry, mEnumValueLookup) == 304); + static_assert(offsetof(CommandRegistry, mCommandSymbols) == 320); + static_assert(offsetof(CommandRegistry, mSignatures) == 344); + static_assert(offsetof(CommandRegistry, mTypeLookup) == 360); + static_assert(offsetof(CommandRegistry, unk376) == 376); + static_assert(offsetof(CommandRegistry, mAliases) == 392); + static_assert(offsetof(CommandRegistry, mSemanticConstraints) == 408); + static_assert(offsetof(CommandRegistry, mSemanticConstraintLookup) == 432); + static_assert(offsetof(CommandRegistry, mConstrainedValues) == 448); + static_assert(offsetof(CommandRegistry, mConstrainedValueLookup) == 472); + static_assert(offsetof(CommandRegistry, mSoftEnums) == 488); + static_assert(offsetof(CommandRegistry, mSoftEnumLookup) == 512); + static_assert(offsetof(CommandRegistry, mStateStack) == 528); + static_assert(offsetof(CommandRegistry, mArgs) == 552); + static_assert(offsetof(CommandRegistry, mCommandOverrideFunctor) == 640); + } +#endif COMMAND_REGISTRY_EXTRA + + template + inline static std::unique_ptr allocateCommand() { + return std::make_unique(); + } + inline void registerOverload( + std::string const& name, Overload::FactoryFn factory, std::vector&& args) { + Signature* signature = const_cast(findCommand(name)); + auto& overload = signature->overloads.emplace_back(CommandVersion{}, factory, std::move(args)); + registerOverloadInternal(*signature, overload); + } + template + inline void registerOverload(std::string const& name, Params... params) { + registerOverload(name, &allocateCommand, {params...}); + } + + template + bool + fakeParse(void*, ParseToken const&, CommandOrigin const&, int, std::string&, std::vector&) const { + return false; + } + inline static std::unordered_map parse_ptr = { + {typeid(CommandMessage).name(), + dlsym_real( + "??$parse@VCommandMessage@@@CommandRegistry@@AEBA_NPEAXAEBUParseToken@0@AEBVCommandOrigin@" + "@HAEAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEAV?$vector@V?$basic_" + "string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$" + "char_traits@D@std@@V?$allocator@D@2@@std@@@2@@4@@Z")}, + {typeid(std::string).name(), + dlsym_real("??$parse@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@" + "CommandRegistry@@AEBA_NPEAXAEBUParseToken@0@AEBVCommandOrigin@@HAEAV?$basic_" + "string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEAV?$vector@V?$basic_string@" + "DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$" + "char_traits@D@std@@V?$allocator@D@2@@std@@@2@@4@@Z")}, + {typeid(bool).name(), + dlsym_real("??$parse@_N@CommandRegistry@@AEBA_NPEAXAEBUParseToken@0@AEBVCommandOrigin@@HAEAV?$" + "basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEAV?$vector@V?$basic_string@" + "DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_" + "traits@D@std@@V?$allocator@D@2@@std@@@2@@4@@Z")}, + {typeid(float).name(), + dlsym_real("??$parse@M@CommandRegistry@@AEBA_NPEAXAEBUParseToken@0@AEBVCommandOrigin@@HAEAV?$" + "basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEAV?$vector@V?$basic_" + "string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@" + "DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@4@@Z")}, + {typeid(int).name(), + dlsym_real("??$parse@H@CommandRegistry@@AEBA_NPEAXAEBUParseToken@0@AEBVCommandOrigin@@HAEAV?$" + "basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEAV?$vector@V?$basic_" + "string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@" + "DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@4@@Z")}, + {typeid(CommandSelector).name(), + dlsym_real( + "??$parse@V?$CommandSelector@VActor@@@@@CommandRegistry@@AEBA_NPEAXAEBUParseToken@0@" + "AEBVCommandOrigin@@HAEAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@" + "AEAV?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@" + "V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@4@@Z")}, + {typeid(CommandSelector).name(), + dlsym_real( + "??$parse@V?$CommandSelector@VPlayer@@@@@CommandRegistry@@AEBA_NPEAXAEBUParseToken@0@" + "AEBVCommandOrigin@@HAEAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@" + "AEAV?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@" + "V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@4@@Z")}, + {typeid(CommandPosition).name(), + dlsym_real( + "??$parse@VCommandPosition@@@CommandRegistry@@AEBA_NPEAXAEBUParseToken@0@AEBVCommandOrigin@@" + "HAEAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEAV?$vector@V?$basic_string@" + "DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@" + "std@@V?$allocator@D@2@@std@@@2@@4@@Z")}, + {typeid(CommandPositionFloat).name(), + dlsym_real( + "??$parse@VCommandPositionFloat@@@CommandRegistry@@AEBA_NPEAXAEBUParseToken@0@AEBVCommandOrigin@@" + "HAEAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEAV?$vector@V?$basic_string@" + "DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@" + "V?$allocator@D@2@@std@@@2@@4@@Z")}, + {typeid(Json::Value).name(), + dlsym_real( + "??$parse@VValue@Json@@@CommandRegistry@@AEBA_NPEAXAEBUParseToken@0@AEBVCommandOrigin@@" + "HAEAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEAV?$vector@V?$basic_string@" + "DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@" + "V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@4@@Z")}, + {typeid(std::unique_ptr).name(), + dlsym_real( + "??$parse@V?$unique_ptr@VCommand@@U?$default_delete@VCommand@@@std@@@std@@@CommandRegistry@@AEBA_NPEAXAEBUParseToken@0@AEBVCommandOrigin@@HAEAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEAV?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@4@@Z")}, + {typeid(RelativeFloat).name(), + dlsym_real( + "??$parse@VRelativeFloat@@@CommandRegistry@@AEBA_NPEAXAEBUParseToken@0@AEBVCommandOrigin@@HAEAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEAV?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@4@@Z")}, + {typeid(CommandRawText).name(), + dlsym_real( + "??$parse@VCommandRawText@@@CommandRegistry@@AEBA_NPEAXAEBUParseToken@0@AEBVCommandOrigin@@HAEAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEAV?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@4@@Z")}, + {typeid(class Block const*).name(), + dlsym_real( + "??$parse@PEBVBlock@@@CommandRegistry@@AEBA_NPEAXAEBUParseToken@0@AEBVCommandOrigin@@HAEAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEAV?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@4@@Z")}, + {typeid(class MobEffect const*).name(), + dlsym_real( + "??$parse@PEBVMobEffect@@@CommandRegistry@@AEBA_NPEAXAEBUParseToken@0@AEBVCommandOrigin@@HAEAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEAV?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@4@@Z")}, + {typeid(CommandItem).name(), + dlsym_real( + "??$parse@VCommandItem@@@CommandRegistry@@AEBA_NPEAXAEBUParseToken@0@AEBVCommandOrigin@@HAEAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEAV?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@4@@Z")}, + {typeid(WildcardCommandSelector).name(), + dlsym_real( + "??$parse@V?$WildcardCommandSelector@VActor@@@@@CommandRegistry@@AEBA_NPEAXAEBUParseToken@0@AEBVCommandOrigin@@HAEAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEAV?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@4@@Z")}, + {typeid(ActorDefinitionIdentifier const*).name(), + dlsym_real( + "??$parse@PEBUActorDefinitionIdentifier@@@CommandRegistry@@AEBA_NPEAXAEBUParseToken@0@AEBVCommandOrigin@@HAEAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEAV?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@4@@Z")}, + }; + +private: + template + bool parse(void*, ParseToken const&, CommandOrigin const&, int, std::string&, std::vector&) const { + + }; + +public: + template + inline static ParseFn getParseFn() { + if constexpr (!std::is_same_v && std::is_enum_v) + return &fakeParse; + // else + // return &parse; + bool (CommandRegistry::*ptr)(void*, CommandRegistry::ParseToken const&, + CommandOrigin const&, int, std::string&, + std::vector&) const; + *(void**)&ptr = parse_ptr[typeid(T).name()]; + if (!ptr) { + printf("Cant parse cmd data %s\n", typeid(T).name()); + std::this_thread::sleep_for(std::chrono::seconds(10)); + exit(1); + } + return ptr; + } + bool parseEnumInt(void* target, + CommandRegistry::ParseToken const& token, + CommandOrigin const&, + int, + std::string&, + std::vector&) const { + auto data = getEnumData(token); + *(int*)target = (int)data; + return true; + } + bool parseEnumString(void* target, + CommandRegistry::ParseToken const& token, + CommandOrigin const&, + int, + std::string&, + std::vector&) const { + auto data = token.toString(); + *(std::string*)target = data; + return true; + } + bool parseEnumStringAndInt(void* target, + CommandRegistry::ParseToken const& token, + CommandOrigin const&, + int, + std::string&, + std::vector&) const { + auto str = token.toString(); + auto data = getEnumData(token); + *(std::pair*)target = {str, (int)data}; + return true; + } + + template > + bool parseEnum( + void* target, CommandRegistry::ParseToken const& token, CommandOrigin const&, int, std::string&, + std::vector&) const { + // fmt::print(token.toString() + '\n'); + auto data = getEnumData(token); + *(Type*)target = IDConverter{}(data); + return true; + } + + template > + unsigned addEnumValues( + std::string const& name, typeid_t tid, + std::vector> const& values) { + std::vector> converted; + IDConverter converter; + for (auto& value : values) + converted.emplace_back(value.first, converter(value.second)); + return addEnumValuesInternal(name, converted, tid, &CommandRegistry::parseEnum).val; + } + unsigned addEnumValues(std::string const& name, + typeid_t tid, + std::initializer_list const& values) { + std::vector> converted; + uint64_t idx = 0; + for (auto& value : values) + converted.emplace_back(value, ++idx); + return addEnumValuesInternal(name, converted, tid, &CommandRegistry::parseEnumInt).val; + } + + // inline static typeid_t getNextTypeId() { + // return typeid_t::count++; + // } + + template + CommandRegistry* addEnum(char const* name, std::vector> const& values) { + this->addEnumValues(name, type_id(), values); + return this; + } + + friend class DynamicCommand; + friend class DynamicCommandInstance; + #undef AFTER_EXTRA #ifndef DISABLE_CONSTRUCTOR_PREVENTION_COMMANDREGISTRY public: diff --git a/LiteLoader/Header/MC/CommandSelector.hpp b/LiteLoader/Header/MC/CommandSelector.hpp new file mode 100644 index 0000000..6cd762a --- /dev/null +++ b/LiteLoader/Header/MC/CommandSelector.hpp @@ -0,0 +1,30 @@ +#pragma once +#include "CommandSelectorBase.hpp" + +// static_assert(offsetof(CommandSelectorBase, explicitIdSelector) == 165); +template +class CommandSelector : public CommandSelectorBase { +public: + LIAPI CommandSelector() : CommandSelectorBase(std::is_same_v) {} + + inline CommandSelectorResults results(CommandOrigin const& a0) const + { + CommandSelectorResults (CommandSelector::*rv)(CommandOrigin const& a0) const; + if constexpr (std::is_same_v) { + *((void**)&rv) = dlsym("?results@?$CommandSelector@VActor@@@@QEBA?AV?$CommandSelectorResults@VActor@@@@AEBVCommandOrigin@@@Z"); + return (this->*rv)(a0); + } + else { + *((void**)&rv) = dlsym("?results@?$CommandSelector@VPlayer@@@@QEBA?AV?$CommandSelectorResults@VPlayer@@@@AEBVCommandOrigin@@@Z"); + return (this->*rv)(a0); + } + } +}; + +template +class WildcardCommandSelector : public CommandSelectorBase +{ +public: + WildcardCommandSelector() + : CommandSelectorBase(std::is_same_v){}; +}; \ No newline at end of file diff --git a/LiteLoader/Header/MC/CommandSoftEnumRegistry.hpp b/LiteLoader/Header/MC/CommandSoftEnumRegistry.hpp index 5659734..93c148d 100644 --- a/LiteLoader/Header/MC/CommandSoftEnumRegistry.hpp +++ b/LiteLoader/Header/MC/CommandSoftEnumRegistry.hpp @@ -4,13 +4,20 @@ #include "../Global.h" #define BEFORE_EXTRA - +// Include Headers or Declare Types Here +#include "UpdateSoftEnumPacket.hpp" #undef BEFORE_EXTRA class CommandSoftEnumRegistry { #define AFTER_EXTRA - + // Add Member There + class CommandRegistry* registry; +public: + CommandSoftEnumRegistry(class CommandRegistry *reg){ + this->registry = reg; + }; +#define DISABLE_CONSTRUCTOR_PREVENTION_COMMANDSOFTENUMREGISTRY #undef AFTER_EXTRA #ifndef DISABLE_CONSTRUCTOR_PREVENTION_COMMANDSOFTENUMREGISTRY public: diff --git a/LiteLoader/Header/MC/CommandUtils.hpp b/LiteLoader/Header/MC/CommandUtils.hpp index f944bde..30a81e7 100644 --- a/LiteLoader/Header/MC/CommandUtils.hpp +++ b/LiteLoader/Header/MC/CommandUtils.hpp @@ -5,13 +5,19 @@ #include "Json.hpp" #define BEFORE_EXTRA - +class Actor; #undef BEFORE_EXTRA namespace CommandUtils { #define AFTER_EXTRA +// std::string getActorName(Actor &actor,int a1) { +// //a1是没啥用的,只是为了改变符号 +// std::string (*rv)(Actor &); +// *((void**)&rv) = dlsym("?getEntityName@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEBVActor@@@Z"); +// return (*rv)(actor); +// } #undef AFTER_EXTRA MCAPI extern std::vector> const CMD_INPUT_UNICODE_TRANSLATE_MAP; MCAPI bool addItemInstanceComponents(class ItemInstance &, class Json::Value const &, std::string &); diff --git a/LiteLoader/Header/MC/CommandVersion.hpp b/LiteLoader/Header/MC/CommandVersion.hpp index 93f6d9a..02bdbb0 100644 --- a/LiteLoader/Header/MC/CommandVersion.hpp +++ b/LiteLoader/Header/MC/CommandVersion.hpp @@ -10,7 +10,12 @@ class CommandVersion { #define AFTER_EXTRA + // Add Member There +public: + int Min = 1, Max = 0x7FFFFFFF; + CommandVersion(){}; +#define DISABLE_CONSTRUCTOR_PREVENTION_COMMANDVERSION #undef AFTER_EXTRA #ifndef DISABLE_CONSTRUCTOR_PREVENTION_COMMANDVERSION public: diff --git a/LiteLoader/Header/MC/MinecraftCommands.hpp b/LiteLoader/Header/MC/MinecraftCommands.hpp index 056e182..31d8ed7 100644 --- a/LiteLoader/Header/MC/MinecraftCommands.hpp +++ b/LiteLoader/Header/MC/MinecraftCommands.hpp @@ -4,12 +4,42 @@ #include "../Global.h" #define BEFORE_EXTRA - +// Include Headers or Declare Types Here +#include "CommandContext.hpp" +#include "MCRESULT.hpp" #undef BEFORE_EXTRA class MinecraftCommands { #define AFTER_EXTRA + // Add Member There +public: + [[deprecated]] + static MCRESULT _runcmd(void* origin, const std::string& cmd) { + if (!Global) + return {0}; + try + { + return Global->executeCommand(std::make_shared(cmd, std::unique_ptr((CommandOrigin*)origin)), false); + } + catch (...) + { + } + return {0}; + } + static MCRESULT _runcmd(std::unique_ptr origin, const std::string& cmd) + { + if (!Global) + return {0}; + try + { + return Global->executeCommand(std::make_shared(cmd, std::move(origin)), false); + } + catch (...) + { + } + return {0}; + } #undef AFTER_EXTRA #ifndef DISABLE_CONSTRUCTOR_PREVENTION_MINECRAFTCOMMANDS diff --git a/LiteLoader/Header/MC/MobEffect.hpp b/LiteLoader/Header/MC/MobEffect.hpp index 7520839..5809d9c 100644 --- a/LiteLoader/Header/MC/MobEffect.hpp +++ b/LiteLoader/Header/MC/MobEffect.hpp @@ -51,6 +51,11 @@ public: FactorCalculationData(FactorCalculationData const&&) = delete; }; + std::string const & getResourceName() const{ + //EffectCommand::execute Line247 + return dAccess(this,80); + }; + #undef AFTER_EXTRA #ifndef DISABLE_CONSTRUCTOR_PREVENTION_MOBEFFECT public: diff --git a/LiteLoader/Header/MC/RelativeFloat.hpp b/LiteLoader/Header/MC/RelativeFloat.hpp new file mode 100644 index 0000000..ec16aea --- /dev/null +++ b/LiteLoader/Header/MC/RelativeFloat.hpp @@ -0,0 +1,75 @@ +/** + * @file RelativeFloat.hpp + * @note This Header is auto generated by LiteLoaderBDS Toolchain. + * + */ +#pragma once +#define AUTO_GENERATED +#include "../Global.h" + +#define BEFORE_EXTRA +// Include Headers or Declare Types Here + +#undef BEFORE_EXTRA + +/** + * @brief MC class RelativeFloat. + * + */ +class RelativeFloat { + +#define AFTER_EXTRA +// Add Member There +public: + float value; + bool is_relative; + + RelativeFloat(float value) + : value(value) + , is_relative(true) { + } + + inline float getFloat(float center) const { + if (is_relative) + return center + value; + return value; + } + RelativeFloat(){ + this->value = 0.0; + this->is_relative = 1; + }; + RelativeFloat(float base, bool relative){ + this->value = base; + this->is_relative = relative; + }; + float getValue(float base) const{ + if(this->is_relative) + return base + this->value; + else + return this->value; + }; +#undef AFTER_EXTRA +#ifndef DISABLE_CONSTRUCTOR_PREVENTION_RELATIVEFLOAT +public: + class RelativeFloat& operator=(class RelativeFloat const &) = delete; + RelativeFloat(class RelativeFloat const &) = delete; +#endif + +public: + /** + * @symbol ??0RelativeFloat@@QEAA@XZ + * @hash 1491997340 + */ + //MCAPI RelativeFloat(); + /** + * @symbol ??0RelativeFloat@@QEAA@M_N@Z + * @hash -528987998 + */ + //MCAPI RelativeFloat(float, bool); + /** + * @symbol ?getValue@RelativeFloat@@QEBAMM@Z + * @hash -802423667 + */ + //MCAPI float getValue(float) const; + +}; \ No newline at end of file diff --git a/LiteLoader/Header/MC/TeleportCommand.hpp b/LiteLoader/Header/MC/TeleportCommand.hpp index 87fad8a..ba7a787 100644 --- a/LiteLoader/Header/MC/TeleportCommand.hpp +++ b/LiteLoader/Header/MC/TeleportCommand.hpp @@ -11,7 +11,10 @@ class TeleportCommand : public Command { #define AFTER_EXTRA - + // Add Member There +public: + enum FacingResult; + enum TeleportAnalysis; #undef AFTER_EXTRA #ifndef DISABLE_CONSTRUCTOR_PREVENTION_TELEPORTCOMMAND public: diff --git a/LiteLoader/Header/MC/TeleportRotationData.hpp b/LiteLoader/Header/MC/TeleportRotationData.hpp new file mode 100644 index 0000000..cb83535 --- /dev/null +++ b/LiteLoader/Header/MC/TeleportRotationData.hpp @@ -0,0 +1,42 @@ +/** + * @file TeleportRotationData.hpp + * @note This Header is auto generated by LiteLoaderBDS Toolchain. + * + */ +#pragma once +#define AUTO_GENERATED +#include "../Global.h" + +#define BEFORE_EXTRA + +#undef BEFORE_EXTRA + +/** + * @brief MC class TeleportRotationData. + * + */ +class TeleportRotationData { + +#define AFTER_EXTRA +#define DISABLE_CONSTRUCTOR_PREVENTION_TELEPORTROTATIONDATA +public: + char filler[32]; + class TeleportRotationData& operator=(class TeleportRotationData const&) = delete; + TeleportRotationData(class TeleportRotationData const&) = default; + TeleportRotationData() = default; +#undef AFTER_EXTRA +#ifndef DISABLE_CONSTRUCTOR_PREVENTION_TELEPORTROTATIONDATA +public: + class TeleportRotationData& operator=(class TeleportRotationData const &) = delete; + TeleportRotationData(class TeleportRotationData const &) = delete; + TeleportRotationData() = delete; +#endif + +public: + /** + * @symbol ??0TeleportRotationData@@QEAA@AEBVRelativeFloat@@0AEBV?$optional@VVec2@@@std@@@Z + * @hash 954629233 + */ + MCAPI TeleportRotationData(class RelativeFloat const &, class RelativeFloat const &, class std::optional const &); + +}; \ No newline at end of file diff --git a/LiteLoader/Header/MC/TeleportTarget.hpp b/LiteLoader/Header/MC/TeleportTarget.hpp new file mode 100644 index 0000000..46d2b83 --- /dev/null +++ b/LiteLoader/Header/MC/TeleportTarget.hpp @@ -0,0 +1,29 @@ +// This Header is auto generated by BDSLiteLoader Toolchain +#pragma once +#include "../Global.h" + + +#define BEFORE_EXTRA //DO NOT EDIT THIS LINE + +#undef BEFORE_EXTRA //DO NOT EDIT THIS LINE + +class TeleportTarget { + +#define AFTER_EXTRA //DO NOT EDIT THIS LINE + struct UnknownStruct{ + char filler[40]; + }; + char filler[40]; // IDA TeleportCommand::computeTarget + UnknownStruct *unk40; +#undef AFTER_EXTRA //DO NOT EDIT THIS LINE + +public: + + //MCAPI ~TeleportTarget(); + +protected: + + +private: + +}; \ No newline at end of file diff --git a/LiteLoader/Header/MC/Types.hpp b/LiteLoader/Header/MC/Types.hpp index 9e6b881..16df41c 100644 --- a/LiteLoader/Header/MC/Types.hpp +++ b/LiteLoader/Header/MC/Types.hpp @@ -374,7 +374,7 @@ public: }; // static_assert(std::is_pod_v); -// #include "RelativeFloat.hpp" +#include "RelativeFloat.hpp" // namespace Core { // diff --git a/LiteLoader/Header/MC/UpdateSoftEnumPacket.hpp b/LiteLoader/Header/MC/UpdateSoftEnumPacket.hpp index d2fd912..929bffd 100644 --- a/LiteLoader/Header/MC/UpdateSoftEnumPacket.hpp +++ b/LiteLoader/Header/MC/UpdateSoftEnumPacket.hpp @@ -5,7 +5,13 @@ #include "Packet.hpp" #define BEFORE_EXTRA - +// Include Headers or Declare Types Here +enum SoftEnumUpdateType : char +{ + Add = 0, + Remove = 1, + Set = 2, +}; #undef BEFORE_EXTRA class UpdateSoftEnumPacket : public Packet { diff --git a/LiteLoader/Header/RegCommandAPI.h b/LiteLoader/Header/RegCommandAPI.h index ba2b1f0..150d661 100644 --- a/LiteLoader/Header/RegCommandAPI.h +++ b/LiteLoader/Header/RegCommandAPI.h @@ -1,87 +1,87 @@ -//#pragma once -//#include "Global.h" -//#include "MC/Actor.hpp" -//#include "MC/Player.hpp" -//#include "MC/Command.hpp" -//#include "MC/CommandMessage.hpp" -//#include "MC/CommandOutput.hpp" -//#include "MC/CommandParameterData.hpp" -//#include "MC/CommandPosition.hpp" -//#include "MC/CommandSelector.hpp" -//#include "MC/CommandRegistry.hpp" -//#include -// -//namespace RegisterCommandHelper { -//template -//static int getOffset(Type Command::*src) { -// union { -// Type Command::*src; -// int value; -// } u; -// u.src = src; -// return u.value; -//} -// -//using ParseFn = bool (CommandRegistry::*)( -// void*, CommandRegistry::ParseToken const&, CommandOrigin const&, int, std::string&, -// std::vector&) const; -// -//template -//static CommandParameterData makeMandatory(Type Command::*field, std::string name, bool Command::*isSet = nullptr) { -// -// return { -// type_id(), -// CommandRegistry::getParseFn(), -// name, -// CommandParameterDataType::NORMAL, -// nullptr, -// getOffset(field), -// false, -// isSet ? getOffset(isSet) : -1, -// }; -//} -//template -//static CommandParameterData -// makeMandatory(Type Command::*field, std::string name, char const* desc = nullptr, bool Command::*isSet = nullptr) { -// return { -// type_id(), -// CommandRegistry::getParseFn(), -// name, -// DataType, -// desc, -// getOffset(field), -// false, -// isSet ? getOffset(isSet) : -1, -// }; -//} -//template -//static CommandParameterData makeOptional(Type Command::*field, std::string name, bool Command::*isSet = nullptr) { -// typeid_t tpid{0}; -// -// return { -// type_id(), -// CommandRegistry::getParseFn(), -// name, -// CommandParameterDataType::NORMAL, -// nullptr, -// getOffset(field), -// true, -// isSet ? getOffset(isSet) : -1, -// }; -//} -//template -//static CommandParameterData -// makeOptional(Type Command::*field, std::string name, char const* desc = nullptr, bool Command::*isSet = nullptr) { -// -// return { -// type_id(), -// CommandRegistry::getParseFn(), -// name, -// DataType, -// desc, -// getOffset(field), -// true, -// isSet ? getOffset(isSet) : -1, -// }; -//} -//} // namespace RegisterCommandHelper +#pragma once +#include "Global.h" +#include "MC/Actor.hpp" +#include "MC/Player.hpp" +#include "MC/Command.hpp" +#include "MC/CommandMessage.hpp" +#include "MC/CommandOutput.hpp" +#include "MC/CommandParameterData.hpp" +#include "MC/CommandPosition.hpp" +#include "MC/CommandSelector.hpp" +#include "MC/CommandRegistry.hpp" +#include + +namespace RegisterCommandHelper { +template +static int getOffset(Type Command::*src) { + union { + Type Command::*src; + int value; + } u; + u.src = src; + return u.value; +} + +using ParseFn = bool (CommandRegistry::*)( + void*, CommandRegistry::ParseToken const&, CommandOrigin const&, int, std::string&, + std::vector&) const; + +template +static CommandParameterData makeMandatory(Type Command::*field, std::string name, bool Command::*isSet = nullptr) { + + return { + type_id(), + CommandRegistry::getParseFn(), + name, + CommandParameterDataType::NORMAL, + nullptr, + getOffset(field), + false, + isSet ? getOffset(isSet) : -1, + }; +} +template +static CommandParameterData + makeMandatory(Type Command::*field, std::string name, char const* desc = nullptr, bool Command::*isSet = nullptr) { + return { + type_id(), + CommandRegistry::getParseFn(), + name, + DataType, + desc, + getOffset(field), + false, + isSet ? getOffset(isSet) : -1, + }; +} +template +static CommandParameterData makeOptional(Type Command::*field, std::string name, bool Command::*isSet = nullptr) { + typeid_t tpid{0}; + + return { + type_id(), + CommandRegistry::getParseFn(), + name, + CommandParameterDataType::NORMAL, + nullptr, + getOffset(field), + true, + isSet ? getOffset(isSet) : -1, + }; +} +template +static CommandParameterData + makeOptional(Type Command::*field, std::string name, char const* desc = nullptr, bool Command::*isSet = nullptr) { + + return { + type_id(), + CommandRegistry::getParseFn(), + name, + DataType, + desc, + getOffset(field), + true, + isSet ? getOffset(isSet) : -1, + }; +} +} // namespace RegisterCommandHelper diff --git a/LiteLoader/Kernel/Command/CommandOriginAPI.cpp b/LiteLoader/Kernel/Command/CommandOriginAPI.cpp index 11eba87..eabbc82 100644 --- a/LiteLoader/Kernel/Command/CommandOriginAPI.cpp +++ b/LiteLoader/Kernel/Command/CommandOriginAPI.cpp @@ -1,7 +1,7 @@ -// #include -// #include + #include + #include -// ServerPlayer* CommandOrigin::getPlayer() const { -// Actor* origin = getEntity(); -// return origin->isPlayer() ? (ServerPlayer*)origin : nullptr; -// } \ No newline at end of file + ServerPlayer* CommandOrigin::getPlayer() const { + Actor* origin = getEntity(); + return origin->isPlayer() ? (ServerPlayer*)origin : nullptr; + } \ No newline at end of file diff --git a/LiteLoader/Kernel/Command/CommandOutputAPI.cpp b/LiteLoader/Kernel/Command/CommandOutputAPI.cpp index 7c32073..b6ddd47 100644 --- a/LiteLoader/Kernel/Command/CommandOutputAPI.cpp +++ b/LiteLoader/Kernel/Command/CommandOutputAPI.cpp @@ -1,13 +1,13 @@ -// #include + #include -// void CommandOutput::addMessage(const std::string& str) { -// this->addMessage(str, {}, (CommandOutputMessageType)0); -// } + void CommandOutput::addMessage(const std::string& str) { + this->addMessage(str, {}, (CommandOutputMessageType)0); + } -// void CommandOutput::success(const std::string& str) { -// this->success(str, {}); -// } + void CommandOutput::success(const std::string& str) { + this->success(str, {}); + } -// void CommandOutput::error(const std::string& str) { -// this->error(str, {}); -// } \ No newline at end of file + void CommandOutput::error(const std::string& str) { + this->error(str, {}); + } \ No newline at end of file diff --git a/LiteLoader/Kernel/Command/CommandRegistryAPI.cpp b/LiteLoader/Kernel/Command/CommandRegistryAPI.cpp index 486ef78..ea5ba65 100644 --- a/LiteLoader/Kernel/Command/CommandRegistryAPI.cpp +++ b/LiteLoader/Kernel/Command/CommandRegistryAPI.cpp @@ -1,256 +1,256 @@ -// #define COMMAND_REGISTRY_EXTRA -// #include -// #include -// #include -// #include -// #include -// #include -// static_assert(offsetof(CommandParameterData, options) == 73); -// static_assert(offsetof(CommandParameterData, name) == 16); -// static_assert(offsetof(CommandParameterData, unk56) == 56); -// static_assert(offsetof(CommandRegistry::Overload, unk) == 40); -// static_assert(sizeof(CommandRegistry::Overload) == 72); -// static_assert(offsetof(CommandRegistry::Signature, alt_symbol) == 96); -// static_assert(sizeof(CommandRegistry::Signature) == 120); -// /* -// void CommandRegistry::registerOverload(std::string const& name, Overload::FactoryFn factory, std::vector&& args) -// { -// Signature* signature = const_cast(findCommand(name)); -// auto& overload = signature->overloads.emplace_back(CommandVersion{}, factory, std::move(args)); -// registerOverloadInternal(*signature, overload); -// }*/ + #define COMMAND_REGISTRY_EXTRA + #include + #include + #include + #include + #include + #include + static_assert(offsetof(CommandParameterData, options) == 73); + static_assert(offsetof(CommandParameterData, name) == 16); + static_assert(offsetof(CommandParameterData, unk56) == 56); + static_assert(offsetof(CommandRegistry::Overload, unk) == 40); + static_assert(sizeof(CommandRegistry::Overload) == 72); + static_assert(offsetof(CommandRegistry::Signature, alt_symbol) == 96); + static_assert(sizeof(CommandRegistry::Signature) == 120); + /* + void CommandRegistry::registerOverload(std::string const& name, Overload::FactoryFn factory, std::vector&& args) + { + Signature* signature = const_cast(findCommand(name)); + auto& overload = signature->overloads.emplace_back(CommandVersion{}, factory, std::move(args)); + registerOverloadInternal(*signature, overload); + }*/ -// extern Logger logger; + extern Logger logger; -// CommandRegistry::Overload::Overload(CommandVersion version, -// FactoryFn factory, -// std::vector&& args) -// : version(version) -// , factory(factory) -// , params(std::forward>(args)) -// , unk(255){}; + CommandRegistry::Overload::Overload(CommandVersion version, + FactoryFn factory, + std::vector&& args) + : version(version) + , factory(factory) + , params(std::forward>(args)) + , unk(255){}; -// CommandRegistry::Overload::~Overload(){}; + CommandRegistry::Overload::~Overload(){}; -// std::vector CommandRegistry::getEnumNames() { -// if (!Global) -// return {}; -// std::vector results; -// for (auto& e : Global->mEnums) -// results.push_back(e.name); -// return results; + std::vector CommandRegistry::getEnumNames() { + if (!Global) + return {}; + std::vector results; + for (auto& e : Global->mEnums) + results.push_back(e.name); + return results; -// auto packet = Global->serializeAvailableCommands(); -// return packet.getEnumNames(); -// } -// std::vector CommandRegistry::getSoftEnumNames() { -// if (!Global) -// return {}; -// std::vector results; -// for (auto& e : Global->mSoftEnums) -// results.push_back(e.name); -// return results; + auto packet = Global->serializeAvailableCommands(); + return packet.getEnumNames(); + } + std::vector CommandRegistry::getSoftEnumNames() { + if (!Global) + return {}; + std::vector results; + for (auto& e : Global->mSoftEnums) + results.push_back(e.name); + return results; -// auto packet = Global->serializeAvailableCommands(); -// return packet.getEnumNames(); -// } -// std::vector CommandRegistry::getEnumValues(std::string const& name) { -// if (!Global) -// return {}; -// std::vector results; -// auto& enums = Global->mEnums; -// auto iter = std::find_if(enums.begin(), enums.end(), [&](CommandRegistry::Enum const& r) { return r.name == name; }); -// if (iter == enums.end()) -// return results; -// for (auto& i : iter->values) -// results.push_back(Global->mEnumValues.at(std::get<3>(i))); -// return results; + auto packet = Global->serializeAvailableCommands(); + return packet.getEnumNames(); + } + std::vector CommandRegistry::getEnumValues(std::string const& name) { + if (!Global) + return {}; + std::vector results; + auto& enums = Global->mEnums; + auto iter = std::find_if(enums.begin(), enums.end(), [&](CommandRegistry::Enum const& r) { return r.name == name; }); + if (iter == enums.end()) + return results; + for (auto& i : iter->values) + results.push_back(Global->mEnumValues.at(std::get<3>(i))); + return results; -// auto packet = Global->serializeAvailableCommands(); -// return packet.getEnumValues(name); -// } -// std::vector CommandRegistry::getSoftEnumValues(std::string const& name) { -// if (!Global) -// return {}; -// std::vector results; -// auto& enums = Global->mSoftEnums; -// auto iter = std::find_if(enums.begin(), enums.end(), [&](CommandRegistry::SoftEnum const& r) { return r.name == name; }); -// if (iter != enums.end()) -// return iter->list; -// return {}; + auto packet = Global->serializeAvailableCommands(); + return packet.getEnumValues(name); + } + std::vector CommandRegistry::getSoftEnumValues(std::string const& name) { + if (!Global) + return {}; + std::vector results; + auto& enums = Global->mSoftEnums; + auto iter = std::find_if(enums.begin(), enums.end(), [&](CommandRegistry::SoftEnum const& r) { return r.name == name; }); + if (iter != enums.end()) + return iter->list; + return {}; -// auto packet = Global->serializeAvailableCommands(); -// return packet.getEnumValues(name); -// } -// std::string CommandRegistry::getCommandFullName(std::string const& name) { -// if (!Global) -// return ""; -// auto sig = Global->findCommand(name); -// if (sig) -// return sig->name; -// return ""; -// } + auto packet = Global->serializeAvailableCommands(); + return packet.getEnumValues(name); + } + std::string CommandRegistry::getCommandFullName(std::string const& name) { + if (!Global) + return ""; + auto sig = Global->findCommand(name); + if (sig) + return sig->name; + return ""; + } -// #include
-// bool CommandRegistry::unregisterCommand(std::string const& name) { -// if (!LL::globalConfig.debugMode) { -// logger.error("unregister command is only enabled in debug mode"); -// return false; -// } -// logger.warn("Unregister Command \"{}\"!", name); -// try { -// auto command = getCommandFullName(name); -// if (command.empty()) -// return false; -// auto alias = getAliases(name); -// auto aliasKey = command + "CommandAliases"; -// static size_t removeIndex = 0; -// auto iter = std::find_if(mEnums.begin(), mEnums.end(), [](Enum const& e) { return e.name == "CommandName"; }); -// for (auto i = iter->values.begin(); i != iter->values.end();) { -// auto& enumValue = mEnumValues.at(std::get<3>(*i)); -// if (enumValue == command || std::find(alias.begin(), alias.end(), enumValue) != alias.end()) { -// mEnumValueLookup.erase(enumValue); -// i = iter->values.erase(i); -// enumValue = fmt::format("removed_{}", removeIndex++); -// } else { -// ++i; -// } -// } -// auto aliasIter = std::find_if(mEnums.begin(), mEnums.end(), [&aliasKey](Enum const& e) { return e.name == aliasKey; }); -// if (aliasIter != mEnums.end()) { -// aliasIter->values.clear(); -// mEnumLookup.erase(aliasIter->name); -// aliasIter->name = fmt::format("removed_{}", removeIndex++); -// } -// auto sig = mSignatures.find(command); -// if (sig == mSignatures.end()) -// return false; -// { -// auto iter = std::remove_if(mCommandSymbols.begin(), mCommandSymbols.end(), -// [&](Symbol const& r) { return r == sig->second.main_symbol || r == sig->second.alt_symbol; }); -// if (iter != mCommandSymbols.end()) -// mCommandSymbols.erase(iter, mCommandSymbols.end()); -// } -// //{ -// // auto iter = std::remove_if(mRules.begin(), mRules.end(), -// // [&](ParseRule const& r) { return r.sym == sig->second.main_symbol || r.sym == sig->second.alt_symbol; }); -// // if (iter == mRules.end()) -// // mRules.erase(iter, mRules.end()); -// //}; -// { -// auto iter = std::remove_if(mFactorizations.begin(), mFactorizations.end(), -// [&](Factorization const& r) { return r.sym == sig->second.main_symbol || r.sym == sig->second.alt_symbol; }); -// if (iter != mFactorizations.end()) -// mFactorizations.erase(iter, mFactorizations.end()); -// }; + #include
+ bool CommandRegistry::unregisterCommand(std::string const& name) { + if (!LL::globalConfig.debugMode) { + logger.error("unregister command is only enabled in debug mode"); + return false; + } + logger.warn("Unregister Command \"{}\"!", name); + try { + auto command = getCommandFullName(name); + if (command.empty()) + return false; + auto alias = getAliases(name); + auto aliasKey = command + "CommandAliases"; + static size_t removeIndex = 0; + auto iter = std::find_if(mEnums.begin(), mEnums.end(), [](Enum const& e) { return e.name == "CommandName"; }); + for (auto i = iter->values.begin(); i != iter->values.end();) { + auto& enumValue = mEnumValues.at(std::get<3>(*i)); + if (enumValue == command || std::find(alias.begin(), alias.end(), enumValue) != alias.end()) { + mEnumValueLookup.erase(enumValue); + i = iter->values.erase(i); + enumValue = fmt::format("removed_{}", removeIndex++); + } else { + ++i; + } + } + auto aliasIter = std::find_if(mEnums.begin(), mEnums.end(), [&aliasKey](Enum const& e) { return e.name == aliasKey; }); + if (aliasIter != mEnums.end()) { + aliasIter->values.clear(); + mEnumLookup.erase(aliasIter->name); + aliasIter->name = fmt::format("removed_{}", removeIndex++); + } + auto sig = mSignatures.find(command); + if (sig == mSignatures.end()) + return false; + { + auto iter = std::remove_if(mCommandSymbols.begin(), mCommandSymbols.end(), + [&](Symbol const& r) { return r == sig->second.main_symbol || r == sig->second.alt_symbol; }); + if (iter != mCommandSymbols.end()) + mCommandSymbols.erase(iter, mCommandSymbols.end()); + } + //{ + // auto iter = std::remove_if(mRules.begin(), mRules.end(), + // [&](ParseRule const& r) { return r.sym == sig->second.main_symbol || r.sym == sig->second.alt_symbol; }); + // if (iter == mRules.end()) + // mRules.erase(iter, mRules.end()); + //}; + { + auto iter = std::remove_if(mFactorizations.begin(), mFactorizations.end(), + [&](Factorization const& r) { return r.sym == sig->second.main_symbol || r.sym == sig->second.alt_symbol; }); + if (iter != mFactorizations.end()) + mFactorizations.erase(iter, mFactorizations.end()); + }; -// mSignatures.erase(sig); -// mAliases.erase(command); -// return true; -// } catch (...) { -// logger.error("Error in CommandRegistry::unregisterCommand"); -// } -// return false; -// } + mSignatures.erase(sig); + mAliases.erase(command); + return true; + } catch (...) { + logger.error("Error in CommandRegistry::unregisterCommand"); + } + return false; + } -// inline void CommandRegistry::printAll() const { -// logger.error("mRules"); -// for (auto& rule : mRules) { -// logger.warn("{}", rule.toDebugString()); -// } -// logger.error("mParseTableMap"); -// for (auto& [key, table] : mParseTableMap) { -// logger.warn("{}: {}", key, table.toDebugString()); -// } -// logger.error("mOptionals"); -// for (auto& optional : mOptionals) { -// logger.warn("{}", optional.toDebugString()); -// } -// logger.error("mEnums"); -// for (auto& en : mEnums) { -// logger.warn("{}", en.toDebugString()); -// } -// logger.error("mFactorizations"); -// for (auto& i : mFactorizations) { -// logger.warn("{}", i.toDebugString()); -// } -// logger.error("mCommandSymbols"); -// for (auto& i : mCommandSymbols) { -// logger.warn("{}", i.toDebugString()); -// } -// logger.error("mSignatures"); -// for (auto& [k, v] : mSignatures) { -// logger.warn("{}: {}", k, v.toDebugString()); -// } -// logger.error("mConstrainedValues"); -// for (auto& i : mConstrainedValues) { -// logger.warn("{}", i.toDebugString()); -// } -// } -// inline void CommandRegistry::printSize() const { -// static auto log = std::unordered_map{ -// {"mRules ", ""}, -// {"mParseTableMap ", ""}, -// {"mOptionals ", ""}, -// {"mEnumValues ", ""}, -// {"mEnums ", ""}, -// {"mFactorizations ", ""}, -// {"mPostfixes ", ""}, -// {"mEnumLookup ", ""}, -// {"mEnumValueLookup ", ""}, -// {"mCommandSymbols ", ""}, -// {"mSignatures ", ""}, -// {"mTypeLookup ", ""}, -// {"unk376 ", ""}, -// {"mAliases ", ""}, -// {"mSemanticConstraints ", ""}, -// {"mSemanticConstraintLookup", ""}, -// {"mConstrainedValues ", ""}, -// {"mConstrainedValueLookup ", ""}, -// {"mSoftEnums ", ""}, -// {"mSoftEnumLookup ", ""}, -// {"mStateStack ", ""}, -// {"mEnumsValues ", ""}, -// {"mConstrainedValuesValues ", ""}, -// }; -// auto mEnumsValuesSize = ([&]() -> size_t { -// size_t size = 0; -// for (auto& i : mEnums) { -// size += i.values.size(); -// } -// return size; -// })(); -// auto mConstrainedValuesSize = ([&]() -> size_t { -// size_t size = 0; -// for (auto& i : mConstrainedValues) { -// size += i.mConstraints.size(); -// } -// return size; -// })(); -// log["mRules "].append(fmt::format(", {:4}", mRules.size())); -// log["mParseTableMap "].append(fmt::format(", {:4}", mParseTableMap.size())); -// log["mOptionals "].append(fmt::format(", {:4}", mOptionals.size())); -// log["mEnumValues "].append(fmt::format(", {:4}", mEnumValues.size())); -// log["mEnums "].append(fmt::format(", {:4}", mEnums.size())); -// log["mFactorizations "].append(fmt::format(", {:4}", mFactorizations.size())); -// log["mPostfixes "].append(fmt::format(", {:4}", mPostfixes.size())); -// log["mEnumLookup "].append(fmt::format(", {:4}", mEnumLookup.size())); -// log["mEnumValueLookup "].append(fmt::format(", {:4}", mEnumValueLookup.size())); -// log["mCommandSymbols "].append(fmt::format(", {:4}", mCommandSymbols.size())); -// log["mSignatures "].append(fmt::format(", {:4}", mSignatures.size())); -// log["mTypeLookup "].append(fmt::format(", {:4}", mTypeLookup.size())); -// log["unk376 "].append(fmt::format(", {:4}", unk376.size())); -// log["mAliases "].append(fmt::format(", {:4}", mAliases.size())); -// log["mSemanticConstraints "].append(fmt::format(", {:4}", mSemanticConstraints.size())); -// log["mSemanticConstraintLookup"].append(fmt::format(", {:4}", mSemanticConstraintLookup.size())); -// log["mConstrainedValues "].append(fmt::format(", {:4}", mConstrainedValues.size())); -// log["mConstrainedValueLookup "].append(fmt::format(", {:4}", mConstrainedValueLookup.size())); -// log["mSoftEnums "].append(fmt::format(", {:4}", mSoftEnums.size())); -// log["mSoftEnumLookup "].append(fmt::format(", {:4}", mSoftEnumLookup.size())); -// log["mStateStack "].append(fmt::format(", {:4}", mStateStack.size())); -// log["mEnumsValues "].append(fmt::format(", {:4}", mEnumsValuesSize)); -// log["mConstrainedValuesValues "].append(fmt::format(", {:4}", mConstrainedValuesSize)); -// for (auto& [k, v] : log) { -// logger.warn("{}{}", k, v); -// } -// } \ No newline at end of file + inline void CommandRegistry::printAll() const { + logger.error("mRules"); + for (auto& rule : mRules) { + logger.warn("{}", rule.toDebugString()); + } + logger.error("mParseTableMap"); + for (auto& [key, table] : mParseTableMap) { + logger.warn("{}: {}", key, table.toDebugString()); + } + logger.error("mOptionals"); + for (auto& optional : mOptionals) { + logger.warn("{}", optional.toDebugString()); + } + logger.error("mEnums"); + for (auto& en : mEnums) { + logger.warn("{}", en.toDebugString()); + } + logger.error("mFactorizations"); + for (auto& i : mFactorizations) { + logger.warn("{}", i.toDebugString()); + } + logger.error("mCommandSymbols"); + for (auto& i : mCommandSymbols) { + logger.warn("{}", i.toDebugString()); + } + logger.error("mSignatures"); + for (auto& [k, v] : mSignatures) { + logger.warn("{}: {}", k, v.toDebugString()); + } + logger.error("mConstrainedValues"); + for (auto& i : mConstrainedValues) { + logger.warn("{}", i.toDebugString()); + } + } + inline void CommandRegistry::printSize() const { + static auto log = std::unordered_map{ + {"mRules ", ""}, + {"mParseTableMap ", ""}, + {"mOptionals ", ""}, + {"mEnumValues ", ""}, + {"mEnums ", ""}, + {"mFactorizations ", ""}, + {"mPostfixes ", ""}, + {"mEnumLookup ", ""}, + {"mEnumValueLookup ", ""}, + {"mCommandSymbols ", ""}, + {"mSignatures ", ""}, + {"mTypeLookup ", ""}, + {"unk376 ", ""}, + {"mAliases ", ""}, + {"mSemanticConstraints ", ""}, + {"mSemanticConstraintLookup", ""}, + {"mConstrainedValues ", ""}, + {"mConstrainedValueLookup ", ""}, + {"mSoftEnums ", ""}, + {"mSoftEnumLookup ", ""}, + {"mStateStack ", ""}, + {"mEnumsValues ", ""}, + {"mConstrainedValuesValues ", ""}, + }; + auto mEnumsValuesSize = ([&]() -> size_t { + size_t size = 0; + for (auto& i : mEnums) { + size += i.values.size(); + } + return size; + })(); + auto mConstrainedValuesSize = ([&]() -> size_t { + size_t size = 0; + for (auto& i : mConstrainedValues) { + size += i.mConstraints.size(); + } + return size; + })(); + log["mRules "].append(fmt::format(", {:4}", mRules.size())); + log["mParseTableMap "].append(fmt::format(", {:4}", mParseTableMap.size())); + log["mOptionals "].append(fmt::format(", {:4}", mOptionals.size())); + log["mEnumValues "].append(fmt::format(", {:4}", mEnumValues.size())); + log["mEnums "].append(fmt::format(", {:4}", mEnums.size())); + log["mFactorizations "].append(fmt::format(", {:4}", mFactorizations.size())); + log["mPostfixes "].append(fmt::format(", {:4}", mPostfixes.size())); + log["mEnumLookup "].append(fmt::format(", {:4}", mEnumLookup.size())); + log["mEnumValueLookup "].append(fmt::format(", {:4}", mEnumValueLookup.size())); + log["mCommandSymbols "].append(fmt::format(", {:4}", mCommandSymbols.size())); + log["mSignatures "].append(fmt::format(", {:4}", mSignatures.size())); + log["mTypeLookup "].append(fmt::format(", {:4}", mTypeLookup.size())); + log["unk376 "].append(fmt::format(", {:4}", unk376.size())); + log["mAliases "].append(fmt::format(", {:4}", mAliases.size())); + log["mSemanticConstraints "].append(fmt::format(", {:4}", mSemanticConstraints.size())); + log["mSemanticConstraintLookup"].append(fmt::format(", {:4}", mSemanticConstraintLookup.size())); + log["mConstrainedValues "].append(fmt::format(", {:4}", mConstrainedValues.size())); + log["mConstrainedValueLookup "].append(fmt::format(", {:4}", mConstrainedValueLookup.size())); + log["mSoftEnums "].append(fmt::format(", {:4}", mSoftEnums.size())); + log["mSoftEnumLookup "].append(fmt::format(", {:4}", mSoftEnumLookup.size())); + log["mStateStack "].append(fmt::format(", {:4}", mStateStack.size())); + log["mEnumsValues "].append(fmt::format(", {:4}", mEnumsValuesSize)); + log["mConstrainedValuesValues "].append(fmt::format(", {:4}", mConstrainedValuesSize)); + for (auto& [k, v] : log) { + logger.warn("{}{}", k, v); + } + } \ No newline at end of file diff --git a/LiteLoader/Kernel/Command/DynamicCommandAPI.cpp b/LiteLoader/Kernel/Command/DynamicCommandAPI.cpp index fec25a2..a0370c3 100644 --- a/LiteLoader/Kernel/Command/DynamicCommandAPI.cpp +++ b/LiteLoader/Kernel/Command/DynamicCommandAPI.cpp @@ -1,1285 +1,1286 @@ -// //#define COMMAND_REGISTRY_EXTRA -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include + //#define COMMAND_REGISTRY_EXTRA + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include -// extern Logger logger; + extern Logger logger; -// #define ForEachParameterType(func) \ -// func(Bool); \ -// func(Int); \ -// func(Float); \ -// func(String); \ -// func(Actor); \ -// func(Player); \ -// func(BlockPos); \ -// func(Vec3); \ -// func(RawText); \ -// func(Message); \ -// func(JsonValue); \ -// func(Item); \ -// func(Block); \ -// func(Effect); \ -// func(Enum); \ -// func(SoftEnum); \ -// func(ActorType); \ -// func(Command); \ -// func(WildcardSelector); + #define ForEachParameterType(func) \ + func(Bool); \ + func(Int); \ + func(Float); \ + func(String); \ + func(Actor); \ + func(Player); \ + func(BlockPos); \ + func(Vec3); \ + func(RawText); \ + func(Message); \ + func(JsonValue); \ + func(Item); \ + func(Block); \ + func(Effect); \ + func(Enum); \ + func(SoftEnum); \ + func(ActorType); \ + func(Command); \ + func(WildcardSelector); -// #define CatchDynamicCommandError(func, handle) \ -// catch (const seh_exception& e) { \ -// OutputError("Uncaught SEH Exception Detected!", e.code(), TextEncoding::toUTF8(e.what()), func, handle); \ -// } \ -// catch (const std::exception& e) { \ -// OutputError("Uncaught C++ Exception Detected!", errno, TextEncoding::toUTF8(e.what()), func, handle); \ -// } \ -// catch (...) { \ -// OutputError("Uncaught Exception Detected!", -1, "", func, handle); \ -// } + #define CatchDynamicCommandError(func, handle) \ + catch (const seh_exception& e) { \ + OutputError("Uncaught SEH Exception Detected!", e.code(), TextEncoding::toUTF8(e.what()), func, handle); \ + } \ + catch (const std::exception& e) { \ + OutputError("Uncaught C++ Exception Detected!", errno, TextEncoding::toUTF8(e.what()), func, handle); \ + } \ + catch (...) { \ + OutputError("Uncaught Exception Detected!", -1, "", func, handle); \ + } -// // global variable and function -// namespace { -// bool serverCommandsRegistered = false; -// std::unordered_map> dynamicCommandInstances; -// std::vector> delaySetupCommandInstances; -// SRWLock delaySetupLock; + // global variable and function + namespace { + bool serverCommandsRegistered = false; + std::unordered_map> dynamicCommandInstances; + std::vector> delaySetupCommandInstances; + SRWLock delaySetupLock; -// using Result = DynamicCommand::Result; -// using ParameterType = DynamicCommand::ParameterType; -// using ParameterPtr = DynamicCommand::ParameterPtr; -// using ParameterData = DynamicCommand::ParameterData; -// using ParameterIndex = DynamicCommandInstance::ParameterIndex; + using Result = DynamicCommand::Result; + using ParameterType = DynamicCommand::ParameterType; + using ParameterPtr = DynamicCommand::ParameterPtr; + using ParameterData = DynamicCommand::ParameterData; + using ParameterIndex = DynamicCommandInstance::ParameterIndex; -// namespace ParameterDataType { -// typedef bool Bool; -// typedef int Int; -// typedef float Float; -// typedef std::string String; -// typedef WildcardCommandSelector WildcardSelector; -// typedef CommandSelector Actor; -// typedef CommandSelector Player; -// typedef CommandPosition BlockPos; -// typedef CommandPositionFloat Vec3; -// typedef CommandRawText RawText; -// typedef CommandMessage Message; -// typedef Json::Value JsonValue; -// typedef CommandItem Item; -// typedef Block const* Block; -// typedef MobEffect const* Effect; -// // typedef CommandPosition Position; -// #ifdef USE_PARSE_ENUM_STRING -// typedef std::pair Enum; -// #else -// typedef int Enum; -// #endif // USE_PARSE_ENUM_STRING -// typedef std::string SoftEnum; -// typedef ActorDefinitionIdentifier const* ActorType; -// typedef std::unique_ptr Command; -// #ifdef ENABLE_PARAMETER_TYPE_POSTFIX -// typedef int Postfix; -// #endif // ENABLE_PARAMETER_TYPE_POSTFIX -// } // namespace ParameterDataType + namespace ParameterDataType { + typedef bool Bool; + typedef int Int; + typedef float Float; + typedef std::string String; + typedef WildcardCommandSelector WildcardSelector; + typedef CommandSelector Actor; + typedef CommandSelector Player; + typedef CommandPosition BlockPos; + typedef CommandPositionFloat Vec3; + typedef CommandRawText RawText; + typedef CommandMessage Message; + typedef Json::Value JsonValue; + typedef CommandItem Item; + typedef Block const* Block; + typedef MobEffect const* Effect; + // typedef CommandPosition Position; + #ifdef USE_PARSE_ENUM_STRING + typedef std::pair Enum; + #else + typedef int Enum; + #endif // USE_PARSE_ENUM_STRING + typedef std::string SoftEnum; + typedef ActorDefinitionIdentifier const* ActorType; + typedef std::unique_ptr Command; + #ifdef ENABLE_PARAMETER_TYPE_POSTFIX + typedef int Postfix; + #endif // ENABLE_PARAMETER_TYPE_POSTFIX + } // namespace ParameterDataType -// auto const ParameterSizeMap = std::unordered_map{ -// {ParameterType::Bool, std::max((size_t)8, sizeof(ParameterDataType::Bool))}, -// {ParameterType::Int, std::max((size_t)8, sizeof(ParameterDataType::Int))}, -// {ParameterType::Float, std::max((size_t)8, sizeof(ParameterDataType::Float))}, -// {ParameterType::Actor, std::max((size_t)8, sizeof(ParameterDataType::Actor))}, -// {ParameterType::Player, std::max((size_t)8, sizeof(ParameterDataType::Player))}, -// {ParameterType::String, std::max((size_t)8, sizeof(ParameterDataType::String))}, -// {ParameterType::BlockPos, std::max((size_t)8, sizeof(ParameterDataType::BlockPos))}, -// {ParameterType::Vec3, std::max((size_t)8, sizeof(ParameterDataType::Vec3))}, -// {ParameterType::RawText, std::max((size_t)8, sizeof(ParameterDataType::RawText))}, -// {ParameterType::Message, std::max((size_t)8, sizeof(ParameterDataType::Message))}, -// {ParameterType::JsonValue, std::max((size_t)8, sizeof(ParameterDataType::JsonValue))}, -// {ParameterType::Item, std::max((size_t)8, sizeof(ParameterDataType::Item))}, -// {ParameterType::Block, std::max((size_t)8, sizeof(ParameterDataType::Block))}, -// {ParameterType::Effect, std::max((size_t)8, sizeof(ParameterDataType::Effect))}, -// {ParameterType::Enum, std::max((size_t)8, sizeof(ParameterDataType::Enum))}, -// {ParameterType::SoftEnum, std::max((size_t)8, sizeof(ParameterDataType::SoftEnum))}, -// {ParameterType::ActorType, std::max((size_t)8, sizeof(ParameterDataType::ActorType))}, -// {ParameterType::Command, std::max((size_t)8, sizeof(ParameterDataType::Command))}, -// #ifdef ENABLE_PARAMETER_TYPE_POSTFIX -// {ParameterType::Postfix, std::max((size_t)8, sizeof(ParameterDataType::Postfix))}, -// #endif // ENABLE_PARAMETER_TYPE_POSTFIX -// }; + auto const ParameterSizeMap = std::unordered_map{ + {ParameterType::Bool, std::max((size_t)8, sizeof(ParameterDataType::Bool))}, + {ParameterType::Int, std::max((size_t)8, sizeof(ParameterDataType::Int))}, + {ParameterType::Float, std::max((size_t)8, sizeof(ParameterDataType::Float))}, + {ParameterType::Actor, std::max((size_t)8, sizeof(ParameterDataType::Actor))}, + {ParameterType::Player, std::max((size_t)8, sizeof(ParameterDataType::Player))}, + {ParameterType::String, std::max((size_t)8, sizeof(ParameterDataType::String))}, + {ParameterType::BlockPos, std::max((size_t)8, sizeof(ParameterDataType::BlockPos))}, + {ParameterType::Vec3, std::max((size_t)8, sizeof(ParameterDataType::Vec3))}, + {ParameterType::RawText, std::max((size_t)8, sizeof(ParameterDataType::RawText))}, + {ParameterType::Message, std::max((size_t)8, sizeof(ParameterDataType::Message))}, + {ParameterType::JsonValue, std::max((size_t)8, sizeof(ParameterDataType::JsonValue))}, + {ParameterType::Item, std::max((size_t)8, sizeof(ParameterDataType::Item))}, + {ParameterType::Block, std::max((size_t)8, sizeof(ParameterDataType::Block))}, + {ParameterType::Effect, std::max((size_t)8, sizeof(ParameterDataType::Effect))}, + {ParameterType::Enum, std::max((size_t)8, sizeof(ParameterDataType::Enum))}, + {ParameterType::SoftEnum, std::max((size_t)8, sizeof(ParameterDataType::SoftEnum))}, + {ParameterType::ActorType, std::max((size_t)8, sizeof(ParameterDataType::ActorType))}, + {ParameterType::Command, std::max((size_t)8, sizeof(ParameterDataType::Command))}, + #ifdef ENABLE_PARAMETER_TYPE_POSTFIX + {ParameterType::Postfix, std::max((size_t)8, sizeof(ParameterDataType::Postfix))}, + #endif // ENABLE_PARAMETER_TYPE_POSTFIX + }; -// inline void OutputError(std::string errorMsg, int errorCode, std::string errorWhat, std::string func, HMODULE handle) { -// logger.error(errorMsg); -// logger.error("Error: Code [{}] {}", errorCode, errorWhat); -// logger.error("In Function ({})", func); -// if (auto plugin = LL::getPlugin(handle)) -// logger.error("In Plugin <{}>", plugin->name); -// } + inline void OutputError(std::string errorMsg, int errorCode, std::string errorWhat, std::string func, HMODULE handle) { + logger.error(errorMsg); + logger.error("Error: Code [{}] {}", errorCode, errorWhat); + logger.error("In Function ({})", func); + if (auto plugin = LL::getPlugin(handle)) + logger.error("In Plugin <{}>", plugin->name); + } -// } // namespace + } // namespace -// #pragma region Command init and destroy + #pragma region Command init and destroy -// template -// inline void destruct(void* command, size_t offset) { -// dAccess(command, offset).~T(); -// } + template + inline void destruct(void* command, size_t offset) { + dAccess(command, offset).~T(); + } -// template -// inline void initValue(void* command, size_t offset) { -// dAccess(command, offset) = T(); -// } -// template <> -// inline void initValue(void* command, size_t offset) { -// dAccess(command, offset).basic_string::basic_string(); -// } -// template <> -// inline void initValue(void* command, size_t offset) { -// dAccess(command, offset).CommandItem::CommandItem(); -// } -// template <> -// inline void initValue(void* command, size_t offset) { -// dAccess(command, offset).CommandMessage::CommandMessage(); -// } -// template <> -// inline void initValue>(void* command, size_t offset) { -// dAccess>(command, offset).CommandSelector::CommandSelector(); -// } -// template <> -// inline void initValue>(void* command, size_t offset) { -// dAccess>(command, offset).CommandSelector::CommandSelector(); -// } -// template <> -// inline void initValue>(void* command, size_t offset) { -// dAccess>(command, offset).WildcardCommandSelector::WildcardCommandSelector(); -// } + template + inline void initValue(void* command, size_t offset) { + dAccess(command, offset) = T(); + } + template <> + inline void initValue(void* command, size_t offset) { + dAccess(command, offset).basic_string::basic_string(); + } + template <> + inline void initValue(void* command, size_t offset) { + dAccess(command, offset).CommandItem::CommandItem(); + } + template <> + inline void initValue(void* command, size_t offset) { + dAccess(command, offset).CommandMessage::CommandMessage(); + } + template <> + inline void initValue>(void* command, size_t offset) { + dAccess>(command, offset).CommandSelector::CommandSelector(); + } + template <> + inline void initValue>(void* command, size_t offset) { + dAccess>(command, offset).CommandSelector::CommandSelector(); + } + template <> + inline void initValue>(void* command, size_t offset) { + dAccess>(command, offset).WildcardCommandSelector::WildcardCommandSelector(); + } -// #pragma endregion + #pragma endregion -// #pragma region ParameterPtr + #pragma region ParameterPtr -// inline DynamicCommand::ParameterPtr::ParameterPtr(ParameterType type, size_t offset) -// : type(type) -// , offset(offset) { -// } + inline DynamicCommand::ParameterPtr::ParameterPtr(ParameterType type, size_t offset) + : type(type) + , offset(offset) { + } -// inline bool DynamicCommand::ParameterPtr::isValueSet(DynamicCommand const* command) const { -// return dAccess(command, offset + ParameterSizeMap.at(type)); -// } + inline bool DynamicCommand::ParameterPtr::isValueSet(DynamicCommand const* command) const { + return dAccess(command, offset + ParameterSizeMap.at(type)); + } -// Result ParameterPtr::getResult(DynamicCommand const* command, CommandOrigin const* origin) const { -// // auto commandInstance = dynamicCommandInstances.at(command->getCommandName()).get(); -// return {this, command, origin}; -// } + Result ParameterPtr::getResult(DynamicCommand const* command, CommandOrigin const* origin) const { + // auto commandInstance = dynamicCommandInstances.at(command->getCommandName()).get(); + return {this, command, origin}; + } -// #pragma endregion + #pragma endregion -// #pragma region ParameterData + #pragma region ParameterData -// DynamicCommand::ParameterData::ParameterData(ParameterData const& right) -// : ParameterData(right.name, right.type, right.optional, right.description, right.identifier, right.option) { -// offset = right.offset; -// }; + DynamicCommand::ParameterData::ParameterData(ParameterData const& right) + : ParameterData(right.name, right.type, right.optional, right.description, right.identifier, right.option) { + offset = right.offset; + }; -// inline DynamicCommand::ParameterData::ParameterData(std::string const& name, ParameterType type, bool optional, std::string const& enumOptions, std::string const& identifier, CommandParameterOption parameterOption) -// : name(name) -// , type(type) -// , optional(optional) -// , description(enumOptions) -// , option(parameterOption) { -// if (identifier.empty()) -// this->identifier = description.empty() ? name : description; -// else -// this->identifier = identifier; -// if (type != DynamicCommand::ParameterType::Enum && type != DynamicCommand::ParameterType::SoftEnum) { -// if (!description.empty()) -// description = ""; -// } else { -// if (description.empty()) -// throw std::runtime_error("Enum or SoftEnum parameter need a description to confirm which enum to use"); -// } -// } + inline DynamicCommand::ParameterData::ParameterData(std::string const& name, ParameterType type, bool optional, std::string const& enumOptions, std::string const& identifier, CommandParameterOption parameterOption) + : name(name) + , type(type) + , optional(optional) + , description(enumOptions) + , option(parameterOption) { + if (identifier.empty()) + this->identifier = description.empty() ? name : description; + else + this->identifier = identifier; + if (type != DynamicCommand::ParameterType::Enum && type != DynamicCommand::ParameterType::SoftEnum) { + if (!description.empty()) + description = ""; + } else { + if (description.empty()) + throw std::runtime_error("Enum or SoftEnum parameter need a description to confirm which enum to use"); + } + } -// inline DynamicCommand::ParameterData::ParameterData(std::string const& name, DynamicCommand::ParameterType type, std::string const& enumOptions, std::string const& identifier, CommandParameterOption parameterOption) -// : ParameterData(name, type, false, enumOptions, identifier, parameterOption) { -// } + inline DynamicCommand::ParameterData::ParameterData(std::string const& name, DynamicCommand::ParameterType type, std::string const& enumOptions, std::string const& identifier, CommandParameterOption parameterOption) + : ParameterData(name, type, false, enumOptions, identifier, parameterOption) { + } -// inline CommandParameterData DynamicCommand::ParameterData::makeParameterData() const { -// switch (type) { -// case ParameterType::Bool: -// return makeParameterData(); -// case ParameterType::Int: -// return makeParameterData(); -// case ParameterType::Float: -// return makeParameterData(); -// case ParameterType::String: -// return makeParameterData(); -// case ParameterType::Actor: -// return makeParameterData(); -// case ParameterType::Player: -// return makeParameterData(); -// case ParameterType::BlockPos: -// return makeParameterData(); -// case ParameterType::Vec3: -// return makeParameterData(); -// case ParameterType::RawText: -// return makeParameterData(); -// case ParameterType::Message: -// return makeParameterData(); -// case ParameterType::JsonValue: -// return makeParameterData(); -// case ParameterType::Item: -// return makeParameterData(); -// case ParameterType::Block: -// return makeParameterData(); -// case ParameterType::Effect: -// return makeParameterData(); -// // case ParameterType::Position: -// // return makeParameterData(); -// case ParameterType::Enum: -// return makeParameterData(); -// case ParameterType::SoftEnum: -// return makeParameterData(); -// case ParameterType::ActorType: -// return makeParameterData(); -// case ParameterType::Command: -// return makeParameterData(); -// #ifdef ENABLE_PARAMETER_TYPE_POSTFIX -// case ParameterType::Postfix: -// return makeParameterData(); -// #endif // ENABLE_PARAMETER_TYPE_POSTFIX -// default: -// return {}; -// } -// } + inline CommandParameterData DynamicCommand::ParameterData::makeParameterData() const { + switch (type) { + case ParameterType::Bool: + return makeParameterData(); + case ParameterType::Int: + return makeParameterData(); + case ParameterType::Float: + return makeParameterData(); + case ParameterType::String: + return makeParameterData(); + case ParameterType::Actor: + return makeParameterData(); + case ParameterType::Player: + return makeParameterData(); + case ParameterType::BlockPos: + return makeParameterData(); + case ParameterType::Vec3: + return makeParameterData(); + case ParameterType::RawText: + return makeParameterData(); + case ParameterType::Message: + return makeParameterData(); + case ParameterType::JsonValue: + return makeParameterData(); + case ParameterType::Item: + return makeParameterData(); + case ParameterType::Block: + return makeParameterData(); + case ParameterType::Effect: + return makeParameterData(); + // case ParameterType::Position: + // return makeParameterData(); + case ParameterType::Enum: + return makeParameterData(); + case ParameterType::SoftEnum: + return makeParameterData(); + case ParameterType::ActorType: + return makeParameterData(); + case ParameterType::Command: + return makeParameterData(); + #ifdef ENABLE_PARAMETER_TYPE_POSTFIX + case ParameterType::Postfix: + return makeParameterData(); + #endif // ENABLE_PARAMETER_TYPE_POSTFIX + default: + return {}; + } + } -// #pragma endregion + #pragma endregion -// #pragma region Result + #pragma region Result -// inline DynamicCommand::Result::Result(ParameterPtr const* ptr, DynamicCommand const* command, CommandOrigin const* origin, DynamicCommandInstance const* instance) -// : type(ptr->type) -// , offset(ptr->offset) -// , command(command) -// , origin(origin) -// , instance(instance ? instance : command->getInstance()) -// , isSet(ptr->isValueSet(command)) { -// } + inline DynamicCommand::Result::Result(ParameterPtr const* ptr, DynamicCommand const* command, CommandOrigin const* origin, DynamicCommandInstance const* instance) + : type(ptr->type) + , offset(ptr->offset) + , command(command) + , origin(origin) + , instance(instance ? instance : command->getInstance()) + , isSet(ptr->isValueSet(command)) { + } -// inline DynamicCommand::Result::Result() -// : type((ParameterType)-1) -// , offset(-1) -// , command(nullptr) -// , origin(nullptr) -// , instance(nullptr) -// , isSet(false) { -// } + inline DynamicCommand::Result::Result() + : type((ParameterType)-1) + , offset(-1) + , command(nullptr) + , origin(nullptr) + , instance(nullptr) + , isSet(false) { + } -// inline std::string const& DynamicCommand::Result::getEnumValue() const { -// if (getType() == ParameterType::Enum) { -// return getRaw(); -// } else if (getType() == ParameterType::SoftEnum) { -// return getRaw(); -// } -// static std::string const EMPTY_STRING = ""; -// return EMPTY_STRING; -// } + inline std::string const& DynamicCommand::Result::getEnumValue() const { + if (getType() == ParameterType::Enum) { + return getRaw(); + } else if (getType() == ParameterType::SoftEnum) { + return getRaw(); + } + static std::string const EMPTY_STRING = ""; + return EMPTY_STRING; + } -// inline ParameterType DynamicCommand::Result::getType() const { -// return type; -// } + inline ParameterType DynamicCommand::Result::getType() const { + return type; + } -// inline std::string DynamicCommand::Result::getName() const { -// for (auto& [name, ptr] : instance->parameterPtrs) { -// if (ptr.getOffset() == offset) -// return name; -// } -// return ""; -// } + inline std::string DynamicCommand::Result::getName() const { + for (auto& [name, ptr] : instance->parameterPtrs) { + if (ptr.getOffset() == offset) + return name; + } + return ""; + } -// std::string DynamicCommand::Result::toDebugString() const { -// std::string name = getName(); -// ParameterType type = getType(); -// std::string typeName = fmt::format("{}({})", magic_enum::enum_name(type), (int)type); -// switch (type) { -// case ParameterType::Bool: -// return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, getRaw()); -// case ParameterType::Int: -// return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, getRaw()); -// case ParameterType::Float: -// return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, getRaw()); -// case ParameterType::Actor: -// // return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, getRaw>().getName()); -// case ParameterType::Player: { -// std::vector actors = get>(); -// std::ostringstream oss; -// oss << "count: " << actors.size() << ", actors: ["; -// bool first = true; -// for (auto& actor : actors) { -// if (!first) -// oss << ", "; -// oss << CommandUtils::getActorName(*actor); -// } -// oss << "]"; -// return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, oss.str()); -// } -// case ParameterType::String: -// return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, getRaw()); -// case ParameterType::BlockPos: -// return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, getRaw().serialize().toSNBT()); -// case ParameterType::Vec3: -// return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, getRaw().serialize().toSNBT()); -// case ParameterType::RawText: -// return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, getRaw().getText()); -// case ParameterType::Message: -// return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, getRaw().getMessage(*origin)); -// case ParameterType::JsonValue: -// return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, getRaw().toStyledString().substr(0, getRaw().toStyledString().size() - 1)); -// case ParameterType::Item: -// return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, getRaw().createInstance(1, 1, nullptr, true).value_or(ItemInstance::EMPTY_ITEM).toString()); -// case ParameterType::Block: -// return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, isSet ? getRaw()->toDebugString() : "nullptr"); -// case ParameterType::Effect: -// return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, isSet ? getRaw()->getResourceName() : "nullptr"); -// case ParameterType::Enum: -// return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, fmt::format("{}({})", getRaw(), getRaw())); -// case ParameterType::SoftEnum: -// return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, getRaw()); -// case ParameterType::ActorType: -// return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, isSet ? getRaw()->getCanonicalName() : "Null"); -// case ParameterType::Command: -// return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, isSet ? getRaw>()->getCommandName() : "Null"); -// #ifdef ENABLE_PARAMETER_TYPE_POSTFIX -// case ParameterType::Postfix: -// return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, get()); -// #endif // ENABLE_PARAMETER_TYPE_POSTFIX -// default: -// logger.error("Unknown Parameter Type {}, name: {}", typeName, name); -// return ""; -// } -// } + std::string DynamicCommand::Result::toDebugString() const { + std::string name = getName(); + ParameterType type = getType(); + std::string typeName = fmt::format("{}({})", magic_enum::enum_name(type), (int)type); + switch (type) { + case ParameterType::Bool: + return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, getRaw()); + case ParameterType::Int: + return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, getRaw()); + case ParameterType::Float: + return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, getRaw()); + case ParameterType::Actor: + // return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, getRaw>().getName()); + case ParameterType::Player: { + std::vector actors = get>(); + std::ostringstream oss; + oss << "count: " << actors.size() << ", actors: ["; + bool first = true; + for (auto& actor : actors) { + if (!first) + oss << ", "; + oss << actor->getNameTag(); + //oss << CommandUtils::getActorName(*actor,1); + } + oss << "]"; + return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, oss.str()); + } + case ParameterType::String: + return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, getRaw()); + case ParameterType::BlockPos: + return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, getRaw().serialize().toSNBT()); + case ParameterType::Vec3: + return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, getRaw().serialize().toSNBT()); + case ParameterType::RawText: + return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, getRaw().getText()); + case ParameterType::Message: + return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, getRaw().getMessage(*origin)); + case ParameterType::JsonValue: + return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, getRaw().toStyledString().substr(0, getRaw().toStyledString().size() - 1)); + case ParameterType::Item: + return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, getRaw().createInstance(1, 1, nullptr, true).value_or(ItemInstance::EMPTY_ITEM).toString()); + case ParameterType::Block: + return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, isSet ? getRaw()->toDebugString() : "nullptr"); + case ParameterType::Effect: + return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, isSet ? getRaw()->getResourceName() : "nullptr"); + case ParameterType::Enum: + return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, fmt::format("{}({})", getRaw(), getRaw())); + case ParameterType::SoftEnum: + return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, getRaw()); + case ParameterType::ActorType: + return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, isSet ? getRaw()->getCanonicalName() : "Null"); + case ParameterType::Command: + return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, isSet ? getRaw>()->getCommandName() : "Null"); + #ifdef ENABLE_PARAMETER_TYPE_POSTFIX + case ParameterType::Postfix: + return fmt::format("name: {:15s}, type: {:15s}, isSet: {:5}, value: {}", name, typeName, isSet, get()); + #endif // ENABLE_PARAMETER_TYPE_POSTFIX + default: + logger.error("Unknown Parameter Type {}, name: {}", typeName, name); + return ""; + } + } -// inline DynamicCommandInstance const* DynamicCommand::Result::getInstance() const { -// std::string commandName = command->getCommandName(); -// auto iter = dynamicCommandInstances.find(commandName); -// if (iter == dynamicCommandInstances.end()) -// return nullptr; -// return iter->second.get(); -// } + inline DynamicCommandInstance const* DynamicCommand::Result::getInstance() const { + std::string commandName = command->getCommandName(); + auto iter = dynamicCommandInstances.find(commandName); + if (iter == dynamicCommandInstances.end()) + return nullptr; + return iter->second.get(); + } -// #pragma endregion + #pragma endregion -// #pragma region DynamicCommand + #pragma region DynamicCommand -// // std::unique_ptr DynamicCommand::commandBuilder() -// //{ -// // std::unique_ptr command; -// // commandBuilder2(&command, latestAllocateName); -// // return std::move(command); -// // } + // std::unique_ptr DynamicCommand::commandBuilder() + //{ + // std::unique_ptr command; + // commandBuilder2(&command, latestAllocateName); + // return std::move(command); + // } -// inline char DynamicCommand::builderCallbackHanler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata) { -// DynamicCommandInstance& command = *(DynamicCommandInstance*)userdata; -// auto arg1 = (std::unique_ptr*)dcbArgPointer(args); -// DynamicCommand::commandBuilder(arg1, command.getCommandName()); -// return 'p'; -// } + inline char DynamicCommand::builderCallbackHanler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata) { + DynamicCommandInstance& command = *(DynamicCommandInstance*)userdata; + auto arg1 = (std::unique_ptr*)dcbArgPointer(args); + DynamicCommand::commandBuilder(arg1, command.getCommandName()); + return 'p'; + } -// std::unique_ptr* DynamicCommand::commandBuilder(std::unique_ptr* rtn, std::string name) { -// #define CaseInitBreak(type) \ -// case ParameterType::type: \ -// initValue(command, offset); \ -// break; + std::unique_ptr* DynamicCommand::commandBuilder(std::unique_ptr* rtn, std::string name) { + #define CaseInitBreak(type) \ + case ParameterType::type: \ + initValue(command, offset); \ + break; -// assert(dynamicCommandInstances.count(name) == 1); -// if (dynamicCommandInstances.count(name) == 0) { -// logger.error("Error in allocate dynamic command"); -// return rtn; -// } -// auto& commandInstance = *dynamicCommandInstances.at(name); -// auto command = new char[commandInstance.commandSize]{0}; -// (*(DynamicCommand*)command).DynamicCommand::DynamicCommand(); -// for (auto& [name, param] : commandInstance.parameterPtrs) { -// size_t offset = param.getOffset(); -// dAccess(command, offset + ParameterSizeMap.at(param.type)) = false; // XXXX_isSet; -// switch (param.type) { -// ForEachParameterType(CaseInitBreak); -// default: -// break; -// } -// } -// rtn->reset(std::move((Command*)command)); -// return rtn; -// } + assert(dynamicCommandInstances.count(name) == 1); + if (dynamicCommandInstances.count(name) == 0) { + logger.error("Error in allocate dynamic command"); + return rtn; + } + auto& commandInstance = *dynamicCommandInstances.at(name); + auto command = new char[commandInstance.commandSize]{0}; + (*(DynamicCommand*)command).DynamicCommand::DynamicCommand(); + for (auto& [name, param] : commandInstance.parameterPtrs) { + size_t offset = param.getOffset(); + dAccess(command, offset + ParameterSizeMap.at(param.type)) = false; // XXXX_isSet; + switch (param.type) { + ForEachParameterType(CaseInitBreak); + default: + break; + } + } + rtn->reset(std::move((Command*)command)); + return rtn; + } -// DynamicCommandInstance* DynamicCommand::_setup(std::unique_ptr commandInstance) { -// std::string name = commandInstance->getCommandName(); -// #ifdef DEBUG -// logger.info("Setting up command \"{}\"", name); -// #endif // DEBUG + DynamicCommandInstance* DynamicCommand::_setup(std::unique_ptr commandInstance) { + std::string name = commandInstance->getCommandName(); + #ifdef DEBUG + logger.info("Setting up command \"{}\"", name); + #endif // DEBUG -// // Check if there is another command with the same name -// auto signature = Global->findCommand(name); -// if (signature) { -// throw std::runtime_error("There is already a command named " + signature->name); -// } - -// auto handle = commandInstance->handle; -// try { -// if (!commandInstance) -// throw std::runtime_error("Command instance is null"); -// if (!commandInstance->callback) -// throw std::runtime_error("Can't setup command without callback"); -// if (commandInstance->overloads.empty()) -// throw std::runtime_error("Can't setup command without overloads"); -// // commandInstance->updateSoftEnum(); - -// for (auto& param : commandInstance->parameterDatas) { -// if (param.type == ParameterType::Enum) { -// // clone BDS's enum -// if (commandInstance->enumRanges.count(param.description) == 0) { -// auto namesInBds = CommandRegistry::getEnumNames(); -// auto iter = std::find(namesInBds.begin(), namesInBds.end(), param.description); -// if (iter == namesInBds.end()) -// throw std::runtime_error("Enum " + std::string(param.description) + "not found in command and BDS"); -// #ifndef USE_PARSE_ENUM_STRING_ // fix Enum -// commandInstance->setEnum(*iter, CommandRegistry::getEnumValues(*iter)); -// #endif // USE_PARSE_ENUM_STRING -// } -// } else if (param.type == ParameterType::SoftEnum) { -// // add empty Soft Enum if not found in command and BDS -// if (commandInstance->softEnums.count(param.description) == 0) { -// auto namesInBds = CommandRegistry::getSoftEnumNames(); -// auto iter = std::find(namesInBds.begin(), namesInBds.end(), param.description); -// if (iter == namesInBds.end()) -// commandInstance->setSoftEnum(param.description, {}); -// } -// } -// } - -// // fix enum name with prefix '_...' if Enum name is exists in BDS -// auto namesInBds = CommandRegistry::getEnumNames(); -// std::unordered_map> convertedEnumRanges; -// for (auto& [name, range] : commandInstance->enumRanges) { -// std::string fixedName = name.data(); -// while (std::find(namesInBds.begin(), namesInBds.end(), fixedName) != namesInBds.end()) { -// fixedName.append("_"); -// } -// std::string_view fixedView = name; -// if (fixedName != name) { -// for (auto& namePtr : commandInstance->enumNames) { -// if (*namePtr == name) { -// namePtr->swap(fixedName); -// fixedView = *namePtr; -// for (auto& data : commandInstance->parameterDatas) { -// if (data.description == fixedName) { -// data.description = *namePtr; -// } -// } -// break; -// } -// } -// } -// std::vector> values; -// size_t index = range.first; -// for (auto iter = commandInstance->enumValues.begin() + range.first; iter != commandInstance->enumValues.begin() + range.first + range.second; ++iter) { -// values.emplace_back(*iter, index); -// ++index; -// } -// #ifdef USE_PARSE_ENUM_STRING -// Global->_addEnumValuesInternal(fixedView.data(), values, typeid_t::count++, &CommandRegistry::parseEnumStringAndInt).val; -// #else -// Global->_addEnumValuesInternal(fixedView.data(), values, typeid_t::count++, &CommandRegistry::parseEnum).val; -// #endif // USE_PARSE_ENUM_STRING -// } -// commandInstance->enumRanges.swap(convertedEnumRanges); - -// // add Soft Enum to BDS -// for (auto& [name, values] : commandInstance->softEnums) { -// Global->addSoftEnum(name, values); -// } - -// Global->registerCommand(commandInstance->name, commandInstance->description->c_str(), commandInstance->permission, commandInstance->flag, commandInstance->flag); -// if (!commandInstance->alias.empty()) -// Global->registerAlias(commandInstance->name, commandInstance->alias); -// auto builder = commandInstance->initCommandBuilder(); -// for (auto& overload : commandInstance->overloads) { -// Global->registerOverload(commandInstance->name, builder, commandInstance->buildOverload(overload)); -// } -// // commandInstance->overloads.clear(); -// auto res = dynamicCommandInstances.emplace(commandInstance->name, std::move(commandInstance)); -// return res.first->second.get(); -// } -// CatchDynamicCommandError("DynamicCommand::_setup - " + name, handle); -// return nullptr; -// } - -// bool DynamicCommand::onServerCommandsRegister(CommandRegistry& registry) { -// serverCommandsRegistered = true; -// SRWLockHolder locker(delaySetupLock); -// for (auto& command : delaySetupCommandInstances) { -// std::string name = command->getCommandName(); -// auto handle = command->handle; -// try { -// if (!LL::getPlugin(handle) && handle != GetCurrentModule()) -// throw std::runtime_error("Plugin that registered command \"" + name + "\" not found"); -// auto res = DynamicCommand::_setup(std::move(command)); -// if (!res) -// throw std::runtime_error("Command \"" + name + "\" setup failed"); -// } -// CatchDynamicCommandError("DynamicCommand::_setup - " + name, handle); -// }; -// delaySetupCommandInstances.clear(); -// return true; -// } - -// DynamicCommand::~DynamicCommand() { -// #define CaseDestructBreak(type) \ -// case ParameterType::type: \ -// destruct(this, offset); \ -// break; - -// std::string commandName = getCommandName(); -// auto iter = dynamicCommandInstances.find(commandName); -// if (iter == dynamicCommandInstances.end()) { -// logger.error("Error in DynamicCommand::~DynamicCommand(), command \"{}\" not found", commandName); -// return; -// } -// auto& commandIns = *iter->second; -// for (auto& [name, parameter] : commandIns.parameterPtrs) { -// auto offset = parameter.getOffset(); -// switch (parameter.type) { -// ForEachParameterType(CaseDestructBreak); -// default: -// break; -// } -// } -// } - -// void DynamicCommand::execute(CommandOrigin const& origin, CommandOutput& output) const { -// auto iter = dynamicCommandInstances.find(getCommandName()); -// if (iter == dynamicCommandInstances.end()) { -// return output.error("Dynamic Command Not Found"); -// } -// auto& commandIns = *iter->second; -// if (!commandIns.callback) { -// return output.error(fmt::format("Command {} has been removed.", getCommandName())); -// } -// try { -// std::unordered_map results; - -// for (auto& [name, param] : commandIns.parameterPtrs) { -// results.emplace(name, param.getResult(this, &origin)); -// } -// commandIns.callback(*this, origin, output, results); -// } -// CatchDynamicCommandError("DynamicCommand::execute", commandIns.handle); -// } - -// std::unique_ptr DynamicCommand::createCommand(std::string const& name, std::string const& description, CommandPermissionLevel permission, CommandFlag flag1, CommandFlag flag2, HMODULE handle) { -// return DynamicCommandInstance::create(name, description, permission, flag1 |= flag2, handle); -// } -// #include -// #include -// #include
- -// DynamicCommandInstance const* DynamicCommand::setup(std::unique_ptr commandInstance) { -// auto ptr = commandInstance.get(); -// if (!ptr) -// throw std::runtime_error("DynamicCommand::setup - commandInstance is null"); -// if (!serverCommandsRegistered) { -// delaySetupLock.lock(); -// auto& uptr = delaySetupCommandInstances.emplace_back(std::move(commandInstance)); -// delaySetupLock.unlock(); -// return uptr.get(); -// } -// // logger.warn("Registering command \"{}\" after RegCmdEvent, note that this is unstable!", commandInstance->getCommandName()); -// Schedule::nextTick([instance{commandInstance.release()}]() { -// if (!_setup(std::unique_ptr(instance))) -// logger.warn("Registering command \"{}\" failed", instance->getCommandName()); -// updateAvailableCommands(); -// }); -// return ptr; -// } - -// std::unique_ptr DynamicCommand::createCommand(std::string const& name, std::string const& description, std::unordered_map>&& enums, std::vector&& params, std::vector>&& overloads, CallBackFn callback, CommandPermissionLevel permission, CommandFlag flag1, CommandFlag flag2, HMODULE handle) { -// auto command = createCommand(name, description, permission, flag1, flag2, handle); -// if (!command) -// return std::unique_ptr(); -// for (auto& [name, values] : enums) { -// command->setEnum(name, std::move(values)); -// } -// for (auto& param : params) { -// command->newParameter(std::move(param)); -// } -// for (auto& overload : overloads) { -// command->addOverload(std::move(overload)); -// } -// command->setCallback(std::move(callback)); -// return std::move(command); -// } - -// bool DynamicCommand::unregisterCommand(std::string const& name) { -// #ifdef DEBUG -// Schedule::nextTick([tid = std::this_thread::get_id()]() { -// // Call DynamicCommand::unregisterCommand in other thread is not allowed! -// assert(tid == std::this_thread::get_id()); -// }); -// #endif // DEBUG -// if (Global->unregisterCommand(name)) { -// dynamicCommandInstances.erase(name); -// updateAvailableCommands(); -// return true; -// } -// return false; -// } - -// inline bool DynamicCommand::updateAvailableCommands() { -// #ifdef DEBUG -// Schedule::nextTick([tid = std::this_thread::get_id()]() { -// // Call DynamicCommand::updateAvailableCommands in other thread is not allowed! -// assert(tid == std::this_thread::get_id()); -// }); -// #endif // DEBUG - -// if (!Global || !Global) -// return false; -// auto packet = Global->serializeAvailableCommands(); -// auto sender = (LoopbackPacketSender*)Global->getPacketSender(); -// if (!sender) -// return false; -// sender->sendBroadcast(packet); -// return true; -// } - -// inline DynamicCommandInstance const* DynamicCommand::getInstance() const { -// return getInstance(getCommandName()); -// } - -// DynamicCommandInstance const* DynamicCommand::getInstance(std::string const& commandName) { -// auto iter = dynamicCommandInstances.find(commandName); -// if (iter == dynamicCommandInstances.end()) -// return nullptr; -// else -// return iter->second.get(); -// } - -// #pragma endregion - -// #pragma region DynamicCommandInstance - -// inline DynamicCommandInstance::DynamicCommandInstance(std::string const& name, std::string const& description, CommandPermissionLevel permission, CommandFlag flag, HMODULE handle) -// : name(name) -// , description(std::make_unique(description)) -// , permission(permission) -// , flag(flag) -// , handle(handle){}; - -// inline DynamicCommandInstance::~DynamicCommandInstance() { -// if (this->builder) -// dcbFreeCallback((DCCallback*)this->builder); -// this->builder = nullptr; -// } - -// inline std::unique_ptr DynamicCommandInstance::create(std::string const& name, std::string const& description, CommandPermissionLevel permission, CommandFlag flag, HMODULE handle) { -// if (LL::globalConfig.serverStatus != LL::LLServerStatus::Running) { -// for (auto& cmd : delaySetupCommandInstances) { -// if (cmd->name == name) { -// logger.error("Command \"{}\" already exists", name); -// return {}; -// } -// } -// } else if (Global->findCommand(name)) { -// logger.error("Command \"{}\" already exists", name); -// return {}; -// } -// return std::unique_ptr(new DynamicCommandInstance(name, description, permission, flag, handle)); -// } - -// inline bool DynamicCommandInstance::addOverload(std::vector&& params) { -// std::vector indices; -// for (auto& param : params) { -// indices.push_back(newParameter(std::forward(param))); -// } -// return addOverload(std::move(indices)); -// } - -// inline std::string const& DynamicCommandInstance::setEnum(std::string const& description, std::vector const& values) { -// auto& desc = enumNames.emplace_back(std::make_unique(description)); -// enumRanges.emplace(*desc, std::pair{enumValues.size(), values.size()}); -// enumValues.insert(enumValues.end(), values.begin(), values.end()); -// return *desc; -// } - -// inline std::string const& DynamicCommandInstance::getEnumValue(int index) const { -// if (index < 0 || index >= enumValues.size()) -// throw std::runtime_error("Enum index out of range"); -// return enumValues.at(index); -// } - -// ParameterIndex DynamicCommandInstance::newParameter(DynamicCommand::ParameterData&& data) { -// auto iter = parameterPtrs.find(data.name); -// size_t offset = -1; -// if (iter == parameterPtrs.end()) { -// offset = commandSize; -// parameterPtrs.emplace(data.name, DynamicCommand::ParameterPtr(data.type, offset)); -// commandSize += ParameterSizeMap.at(data.type) + 8; -// } else { -// offset = iter->second.getOffset(); -// if (iter->second.type != data.type) -// throw std::runtime_error(fmt::format("dynamic command \"{}\" register failed, Different type parameters with the same name {} are not allowed", name, data.name)); -// } -// std::string const& identifier = data.identifier; -// if (parameterDatas.end() != std::find_if(parameterDatas.begin(), parameterDatas.end(), -// [&](DynamicCommand::ParameterData const& data) { return data.identifier == identifier; })) -// throw std::runtime_error("parameter identifier already exists"); -// data.offset = offset; -// parameterDatas.emplace_back(std::move(data)); -// return {this, parameterDatas.size() - 1}; -// } - -// inline ParameterIndex DynamicCommandInstance::newParameter(std::string const& name, DynamicCommand::ParameterType type, bool optional, std::string const& description, std::string const& identifier, CommandParameterOption parameterOption) { -// return newParameter(ParameterData(name, type, optional, description, identifier, parameterOption)); -// } - -// inline ParameterIndex DynamicCommandInstance::findParameterIndex(std::string const& indentifier) { -// size_t index = 0; -// for (auto& paramData : parameterDatas) { -// if (paramData.identifier == indentifier || paramData.description == indentifier || paramData.name == indentifier) -// break; -// ++index; -// } -// if (index == parameterDatas.size()) -// index = -1; -// return {this, index}; -// } - -// inline ParameterIndex DynamicCommandInstance::mandatory(std::string const& name, DynamicCommand::ParameterType type, std::string const& description, std::string const& identifier, CommandParameterOption parameterOption) { -// return newParameter(ParameterData(name, type, false, description, identifier, parameterOption)); -// } -// inline ParameterIndex DynamicCommandInstance::mandatory(std::string const& name, DynamicCommand::ParameterType type, std::string const& description, CommandParameterOption parameterOption) { -// return mandatory(name, type, description, "", parameterOption); -// }; -// inline ParameterIndex DynamicCommandInstance::mandatory(std::string const& name, DynamicCommand::ParameterType type, CommandParameterOption parameterOption) { -// return mandatory(name, type, "", "", parameterOption); -// }; - -// inline ParameterIndex DynamicCommandInstance::optional(std::string const& name, DynamicCommand::ParameterType type, std::string const& description, std::string const& identifier, CommandParameterOption parameterOption) { -// return newParameter(ParameterData(name, type, true, description, identifier, parameterOption)); -// } - -// inline ParameterIndex DynamicCommandInstance::optional(std::string const& name, DynamicCommand::ParameterType type, std::string const& description, CommandParameterOption parameterOption) { -// return optional(name, type, description, "", parameterOption); -// } - -// inline ParameterIndex DynamicCommandInstance::optional(std::string const& name, DynamicCommand::ParameterType type, CommandParameterOption parameterOption) { -// return optional(name, type, "", "", parameterOption); -// } - -// bool DynamicCommandInstance::addOverload(std::vector&& params) { -// for (auto& index : params) { -// if (index >= parameterDatas.size()) -// throw std::runtime_error("parameter index " + std::to_string(index) + " out of range 0 ~ " + std::to_string(parameterDatas.size())); -// } -// overloads.emplace_back(params); -// return true; -// } - -// inline bool DynamicCommandInstance::addOverload(std::vector&& params) { -// std::vector paramIndices; -// for (auto& param : params) { -// auto index = findParameterIndex(param); -// if (!index.isValid()) { -// throw std::runtime_error("Parameter " + std::string(param) + "not found"); -// } -// paramIndices.push_back(index); -// } -// return addOverload(std::move(paramIndices)); -// } - -// inline bool DynamicCommandInstance::addOverload(std::vector&& params) { -// std::vector paramIndices; -// for (auto& param : params) { -// paramIndices.push_back(findParameterIndex(param)); -// } -// return addOverload(std::move(paramIndices)); -// } - -// inline bool DynamicCommandInstance::setAlias(std::string const& alias) { -// this->alias = alias; -// return true; -// } - -// inline std::vector DynamicCommandInstance::buildOverload(std::vector const& overload) { -// std::vector datas; -// for (auto& index : overload) { -// auto& param = parameterDatas.at(index); -// datas.emplace_back(param.makeParameterData()); -// } -// return datas; -// } - -// // bool DynamicCommandInstance::updateSoftEnum(std::string const& name) const -// //{ -// // if (!hasRegistered()) -// // { -// // for (auto& [key, values] : softEnumValues) -// // { -// // Global->addSoftEnum(key, values); -// // } -// // return true; -// // } -// // if (!name.empty()) -// // { -// // auto iter = softEnumValues.find(name); -// // if (iter != softEnumValues.end()) -// // CommandSoftEnumRegistry(Global).updateSoftEnum(SoftEnumUpdateType::Set, iter->first, iter->second); -// // else -// // return false; -// // return true; -// // } -// // else -// // { -// // for (auto& [key, values] : softEnumValues) -// // { -// // CommandSoftEnumRegistry(Global).updateSoftEnum(SoftEnumUpdateType::Set, key, values); -// // } -// // } -// // } -// std::string DynamicCommandInstance::setSoftEnum(std::string const& name, std::vector const& values) const { -// if (!hasRegistered()) { -// softEnums.emplace(name, values); -// } else { -// if (!Global) -// return ""; -// auto names = CommandRegistry::getSoftEnumNames(); -// if (std::find(names.begin(), names.end(), name) == names.end()) { -// Global->addSoftEnum(name, values); -// return name; -// } -// CommandSoftEnumRegistry(Global).updateSoftEnum(SoftEnumUpdateType::Set, name, values); -// } -// return name; -// } -// bool DynamicCommandInstance::addSoftEnumValues(std::string const& name, std::vector const& values) const { -// if (!hasRegistered()) { -// auto iter = softEnums.find(name); -// if (iter != softEnums.end()) { -// iter->second.insert(iter->second.end(), values.begin(), values.end()); -// } else { -// setSoftEnum(name, values); -// } -// } else { -// if (!Global) -// return false; -// auto names = CommandRegistry::getSoftEnumNames(); -// if (std::find(names.begin(), names.end(), name) == names.end()) { -// Global->addSoftEnum(name, values); -// return true; -// } -// CommandSoftEnumRegistry(Global).updateSoftEnum(SoftEnumUpdateType::Add, name, values); -// } -// return true; -// }; -// bool DynamicCommandInstance::removeSoftEnumValues(std::string const& name, std::vector const& values) const { -// if (!hasRegistered()) { -// auto iter = softEnums.find(name); -// if (iter != softEnums.end()) { -// auto tmp = std::remove_if( -// iter->second.begin(), iter->second.end(), -// [values](std::string const& val) { -// return std::find(values.begin(), values.end(), val) != values.end(); -// }); -// iter->second.erase(tmp, iter->second.end()); -// return true; -// } -// return false; -// } else { -// if (Global) -// CommandSoftEnumRegistry(Global).updateSoftEnum(SoftEnumUpdateType::Remove, name, values); -// } -// return true; -// } -// inline std::vector DynamicCommandInstance::getSoftEnumValues(std::string const& name) { -// return CommandRegistry::getSoftEnumValues(name); -// } -// inline std::vector DynamicCommandInstance::getSoftEnumNames() { -// return CommandRegistry::getSoftEnumNames(); -// } - -// inline void DynamicCommandInstance::setCallback(DynamicCommand::CallBackFn&& callback) const { -// this->callback = callback; -// } - -// inline void DynamicCommandInstance::removeCallback() const { -// callback = nullptr; -// } - -// inline std::string const& DynamicCommandInstance::getCommandName() const { -// return name; -// } - -// inline bool DynamicCommandInstance::setBuilder(DynamicCommand::BuilderFn builder) { -// if (this->builder == nullptr) -// this->builder = builder; -// else -// return false; -// return true; -// } - -// inline DynamicCommand::BuilderFn DynamicCommandInstance::initCommandBuilder() { -// auto builder = (DynamicCommand::BuilderFn)dcbNewCallback("ifsdl)p", &DynamicCommand::builderCallbackHanler, this); -// if (this->setBuilder(builder)) -// return builder; -// dcbFreeCallback((DCCallback*)builder); -// return nullptr; -// } - -// #pragma endregion - -// #ifdef DEBUG -// #define TEST_DYNAMIC_COMMAND -// #define successf(...) success(fmt::format(__VA_ARGS__)) -// #define errorf(...) error(fmt::format(__VA_ARGS__)) -// using Param = DynamicCommand::ParameterData; -// using ParamType = DynamicCommand::ParameterType; -// using ParamIndex = DynamicCommandInstance::ParameterIndex; - -// #ifdef TEST_DYNAMIC_COMMAND - -// #include -// #include -// #include - -// void setupTestParamCommand() { -// using Param = DynamicCommand::ParameterData; -// using ParamType = DynamicCommand::ParameterType; -// Param boolParam("testBool", ParamType::Bool, true); -// Param intParam("testInt", ParamType::Int, true); -// Param floatParam("testFloat", ParamType::Float, true); -// Param strParam("testStr", ParamType::String, true); -// Param actorParam("testActor", ParamType::Actor, true); -// Param playerParam("testPlayer", ParamType::Player, true); -// Param BlockPosParam("testBlockPos", ParamType::BlockPos, true); -// Param Vec3Param("testVec3", ParamType::Vec3, true); -// Param RawTextParam("testRawText", ParamType::RawText, true); -// Param MessageParam("testMessage", ParamType::Message, true); -// Param JsonValueParam("testJsonValue", ParamType::JsonValue, true); -// Param ItemParam("testItem", ParamType::Item, true); -// Param BlockParam("testBlock", ParamType::Block, true); -// Param ActorTypeParam("testActorType", ParamType::ActorType, true); -// Param EffectParam("testEffect", ParamType::Effect, true); -// Param CommandParam("testCommand", ParamType::Command, true); -// // Param posParam(ParamType::Position, "testPos", true); -// // Test Command: dynparam true 114 3.14 str @e @a 3 1 4 ~3 ~1 ~4 raw text msg {"a":4} stick concrete speed version -// DynamicCommand::setup( -// "param", "dynamic command", -// {}, -// { -// boolParam, -// intParam, -// floatParam, -// strParam, -// actorParam, -// playerParam, -// BlockPosParam, -// Vec3Param, -// RawTextParam, -// MessageParam, -// JsonValueParam, -// ItemParam, -// BlockParam, -// ActorTypeParam, -// EffectParam, -// CommandParam, -// }, -// {{ -// "testActorType", -// "testBool", -// "testInt", -// "testFloat", -// "testStr", -// "testActor", -// "testPlayer", -// "testBlockPos", -// "testVec3", -// //"testRawText", -// //"testMessage", -// //"testJsonValue", -// //"testItem", -// //"testBlock", -// //"testEffect", -// //"testCommand", -// }}, -// [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, std::unordered_map& results) { -// for (auto& [name, result] : results) { -// output.success(result.toDebugString()); -// } -// }, -// CommandPermissionLevel::Any); -// } - -// void setupTestEnumCommand() { -// 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", "", CommandParameterOption::EnumAutocompleteExpansion), -// Param("testEnum", ParamType::Enum, "TestEnum2", "", CommandParameterOption::EnumAutocompleteExpansion), -// 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"].getRaw(); -// 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); -// } - -// void setupExampleCommand() { -// 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)); -// } - -// // "remove command" command -// void setupRemoveCommand() { -// auto command = DynamicCommand::createCommand("unregister", "unregister command", CommandPermissionLevel::Any); -// command->setAlias("remove"); -// auto name = command->mandatory("name", ParamType::SoftEnum, -// command->setSoftEnum("CommandNames", {})); -// command->addOverload(name); -// command->setCallback( -// [](DynamicCommand const& cmd, CommandOrigin const& origin, CommandOutput& output, -// std::unordered_map& results) { -// auto& name = results["name"].getRaw(); -// auto fullName = Global->getCommandFullName(name); -// if (fullName == cmd.getCommandName()) { -// output.success("Request unregister itself"); -// Schedule::delay([fullName]() { -// auto res = Global->unregisterCommand(fullName); -// if (res) { -// dynamicCommandInstances.erase(fullName); -// logger.info("unregister command " + fullName); -// ((DynamicCommandInstance*)0)->setSoftEnum("CommandNames", CommandRegistry::getEnumValues("CommandName")); -// } else -// logger.error("error in unregister command " + fullName); -// }, -// 20); -// return; -// } -// auto res = Global->unregisterCommand(fullName); -// if (res) { -// dynamicCommandInstances.erase(fullName); -// output.success("unregister command " + fullName); -// cmd.getInstance()->setSoftEnum("CommandNames", CommandRegistry::getEnumValues("CommandName")); -// } else -// output.error("error in unregister command " + fullName); -// }); -// command->setSoftEnum("CommandNames", CommandRegistry::getEnumValues("CommandName")); -// DynamicCommand::setup(std::move(command)); -// } - - -// // TInstanceHook(void, "?run@Command@@QEBAXAEBVCommandOrigin@@AEAVCommandOutput@@@Z", -// // Command, class CommandOrigin const& origin, class CommandOutput& output) -// //{ -// // logger.info("Command({})::run()", getCommandName()); -// // } - -// // force enable cheat -// TClasslessInstanceHook(bool, "?hasCommandsEnabled@LevelData@@QEBA_NXZ") { -// return true; -// } - -// TInstanceHook(CommandParameterData&, "?addOptions@CommandParameterData@@QEAAAEAV1@W4CommandParameterOption@@@Z", -// CommandParameterData, CommandParameterOption option) { -// // logger.warn("CommandParameterData::addOptions - name: {}, type: {}, desc: {}, option: {:x}", -// // name, magic_enum::enum_name(type), desc ? desc : "", (int)option); -// return original(this, option); -// } - -// #endif // TEST_DYNAMIC_COMMAND - -// // enum command -// void onEnumExecute(DynamicCommand const& cmd, CommandOrigin const& origin, CommandOutput& output, -// std::unordered_map& results) { -// auto enumNames = Global->getEnumNames(); -// auto softEnumNames = Global->getSoftEnumNames(); -// cmd.getInstance()->setSoftEnum("EnumNameList", enumNames); -// cmd.getInstance()->addSoftEnumValues("EnumNameList", softEnumNames); -// if (results["name"].isSet) { -// auto& enumName = results["name"].getRaw(); -// bool found = false; -// if (std::find(enumNames.begin(), enumNames.end(), enumName) != enumNames.end()) { -// found = true; -// output.successf("§eEnum §l{}§r§e Values:", enumName); -// for (auto& val : CommandRegistry::getEnumValues(enumName)) { -// output.success(val); -// // output.addToResultList("enums", val); -// } -// // output.success("Enums: %1$s", {CommandOutputParameter("enums")}); -// } -// if (std::find(softEnumNames.begin(), softEnumNames.end(), enumName) != softEnumNames.end()) { -// found = true; -// output.successf("§eSoft Enum §l{}§r§e Values:", enumName); -// for (auto& val : CommandRegistry::getSoftEnumValues(enumName)) { -// output.success(val); -// } -// } -// if (!found) -// output.errorf("Enum or Soft Enum \"{}\" not found", enumName); -// } else { -// output.success("§eEnum Names:"); -// for (auto& val : CommandRegistry::getEnumNames()) { -// output.success(val); -// } -// output.success("§eSoft Enum Names:"); -// for (auto& val : CommandRegistry::getSoftEnumNames()) { -// output.success(val); -// } -// } -// } - -// void setupEnumCommand() { -// auto command = DynamicCommand::createCommand("enum", "get command enum names or values", CommandPermissionLevel::Any); -// command->setAlias("enums"); -// auto name = command->mandatory("name", ParamType::SoftEnum, -// command->setSoftEnum("EnumNameList", {})); -// command->addOverload(name); -// command->addOverload(); -// command->setCallback(onEnumExecute); -// auto cmd = DynamicCommand::setup(std::move(command)); -// Schedule::delay( -// [cmd]() { -// auto packet = Global->serializeAvailableCommands(); -// cmd->setSoftEnum("EnumNameList", packet.getEnumNames()); -// cmd->addSoftEnumValues("EnumNameList", packet.getSoftEnumNames()); -// }, -// 10); -// } - -// // echo command -// void setupEchoCommand() { -// auto command = DynamicCommand::createCommand("echo", "show message", CommandPermissionLevel::Any); -// command->addOverload(command->mandatory("text", ParamType::RawText)); -// command->setCallback( -// [](DynamicCommand const& cmd, CommandOrigin const& origin, CommandOutput& output, -// std::unordered_map& results) { -// auto& text = results["text"].getRaw(); -// output.success(text); -// }); -// DynamicCommand::setup(std::move(command)); -// } - -// TClasslessInstanceHook2("startServerThread_RegisterDebugCommand", void, "?startServerThread@ServerInstance@@QEAAXXZ") { -// #ifdef DEBUG -// setupRemoveCommand(); -// setupTestEnumCommand(); -// setupTestParamCommand(); -// setupExampleCommand(); -// #if false -// Global->printAll(); -// Schedule::delayRepeat( -// []() { -// static bool Switch = true; -// if (Switch) -// Global->runcmd("remove example"); -// else -// setupExampleCommand(); -// Switch = !Switch; -// }, -// 200, 2); -// #endif // COMMAND_REGISTRY_EXTRA -// #endif // DEBUG -// original(this); -// setupEnumCommand(); -// setupEchoCommand(); -// } - -// #endif // DEBUG - -// TClasslessInstanceHook(void, "?compile@BaseCommandBlock@@AEAAXAEBVCommandOrigin@@AEAVLevel@@@Z", -// class CommandOrigin const& origin, class Level& level) { -// if (LL::globalConfig.tickThreadId != std::this_thread::get_id()) { -// SRWLockSharedHolder locker(delaySetupLock); -// return original(this, origin, level); -// } -// return original(this, origin, level); -// } + // Check if there is another command with the same name + auto signature = Global->findCommand(name); + if (signature) { + throw std::runtime_error("There is already a command named " + signature->name); + } + + auto handle = commandInstance->handle; + try { + if (!commandInstance) + throw std::runtime_error("Command instance is null"); + if (!commandInstance->callback) + throw std::runtime_error("Can't setup command without callback"); + if (commandInstance->overloads.empty()) + throw std::runtime_error("Can't setup command without overloads"); + // commandInstance->updateSoftEnum(); + + for (auto& param : commandInstance->parameterDatas) { + if (param.type == ParameterType::Enum) { + // clone BDS's enum + if (commandInstance->enumRanges.count(param.description) == 0) { + auto namesInBds = CommandRegistry::getEnumNames(); + auto iter = std::find(namesInBds.begin(), namesInBds.end(), param.description); + if (iter == namesInBds.end()) + throw std::runtime_error("Enum " + std::string(param.description) + "not found in command and BDS"); + #ifndef USE_PARSE_ENUM_STRING_ // fix Enum + commandInstance->setEnum(*iter, CommandRegistry::getEnumValues(*iter)); + #endif // USE_PARSE_ENUM_STRING + } + } else if (param.type == ParameterType::SoftEnum) { + // add empty Soft Enum if not found in command and BDS + if (commandInstance->softEnums.count(param.description) == 0) { + auto namesInBds = CommandRegistry::getSoftEnumNames(); + auto iter = std::find(namesInBds.begin(), namesInBds.end(), param.description); + if (iter == namesInBds.end()) + commandInstance->setSoftEnum(param.description, {}); + } + } + } + + // fix enum name with prefix '_...' if Enum name is exists in BDS + auto namesInBds = CommandRegistry::getEnumNames(); + std::unordered_map> convertedEnumRanges; + for (auto& [name, range] : commandInstance->enumRanges) { + std::string fixedName = name.data(); + while (std::find(namesInBds.begin(), namesInBds.end(), fixedName) != namesInBds.end()) { + fixedName.append("_"); + } + std::string_view fixedView = name; + if (fixedName != name) { + for (auto& namePtr : commandInstance->enumNames) { + if (*namePtr == name) { + namePtr->swap(fixedName); + fixedView = *namePtr; + for (auto& data : commandInstance->parameterDatas) { + if (data.description == fixedName) { + data.description = *namePtr; + } + } + break; + } + } + } + std::vector> values; + size_t index = range.first; + for (auto iter = commandInstance->enumValues.begin() + range.first; iter != commandInstance->enumValues.begin() + range.first + range.second; ++iter) { + values.emplace_back(*iter, index); + ++index; + } + #ifdef USE_PARSE_ENUM_STRING + Global->addEnumValuesInternal(fixedView.data(), values, typeid_t::count++, &CommandRegistry::parseEnumStringAndInt).val; + #else + Global->_addEnumValuesInternal(fixedView.data(), values, typeid_t::count++, &CommandRegistry::parseEnum).val; + #endif // USE_PARSE_ENUM_STRING + } + commandInstance->enumRanges.swap(convertedEnumRanges); + + // add Soft Enum to BDS + for (auto& [name, values] : commandInstance->softEnums) { + Global->addSoftEnum(name, values); + } + + Global->registerCommand(commandInstance->name, commandInstance->description->c_str(), commandInstance->permission, commandInstance->flag, commandInstance->flag); + if (!commandInstance->alias.empty()) + Global->registerAlias(commandInstance->name, commandInstance->alias); + auto builder = commandInstance->initCommandBuilder(); + for (auto& overload : commandInstance->overloads) { + Global->registerOverload(commandInstance->name, builder, commandInstance->buildOverload(overload)); + } + // commandInstance->overloads.clear(); + auto res = dynamicCommandInstances.emplace(commandInstance->name, std::move(commandInstance)); + return res.first->second.get(); + } + CatchDynamicCommandError("DynamicCommand::_setup - " + name, handle); + return nullptr; + } + + bool DynamicCommand::onServerCommandsRegister(CommandRegistry& registry) { + serverCommandsRegistered = true; + SRWLockHolder locker(delaySetupLock); + for (auto& command : delaySetupCommandInstances) { + std::string name = command->getCommandName(); + auto handle = command->handle; + try { + if (!LL::getPlugin(handle) && handle != GetCurrentModule()) + throw std::runtime_error("Plugin that registered command \"" + name + "\" not found"); + auto res = DynamicCommand::_setup(std::move(command)); + if (!res) + throw std::runtime_error("Command \"" + name + "\" setup failed"); + } + CatchDynamicCommandError("DynamicCommand::_setup - " + name, handle); + }; + delaySetupCommandInstances.clear(); + return true; + } + + DynamicCommand::~DynamicCommand() { + #define CaseDestructBreak(type) \ + case ParameterType::type: \ + destruct(this, offset); \ + break; + + std::string commandName = getCommandName(); + auto iter = dynamicCommandInstances.find(commandName); + if (iter == dynamicCommandInstances.end()) { + logger.error("Error in DynamicCommand::~DynamicCommand(), command \"{}\" not found", commandName); + return; + } + auto& commandIns = *iter->second; + for (auto& [name, parameter] : commandIns.parameterPtrs) { + auto offset = parameter.getOffset(); + switch (parameter.type) { + ForEachParameterType(CaseDestructBreak); + default: + break; + } + } + } + + void DynamicCommand::execute(CommandOrigin const& origin, CommandOutput& output) const { + auto iter = dynamicCommandInstances.find(getCommandName()); + if (iter == dynamicCommandInstances.end()) { + return output.error("Dynamic Command Not Found"); + } + auto& commandIns = *iter->second; + if (!commandIns.callback) { + return output.error(fmt::format("Command {} has been removed.", getCommandName())); + } + try { + std::unordered_map results; + + for (auto& [name, param] : commandIns.parameterPtrs) { + results.emplace(name, param.getResult(this, &origin)); + } + commandIns.callback(*this, origin, output, results); + } + CatchDynamicCommandError("DynamicCommand::execute", commandIns.handle); + } + + std::unique_ptr DynamicCommand::createCommand(std::string const& name, std::string const& description, CommandPermissionLevel permission, CommandFlag flag1, CommandFlag flag2, HMODULE handle) { + return DynamicCommandInstance::create(name, description, permission, flag1 |= flag2, handle); + } + #include + #include + #include
+ + DynamicCommandInstance const* DynamicCommand::setup(std::unique_ptr commandInstance) { + auto ptr = commandInstance.get(); + if (!ptr) + throw std::runtime_error("DynamicCommand::setup - commandInstance is null"); + if (!serverCommandsRegistered) { + delaySetupLock.lock(); + auto& uptr = delaySetupCommandInstances.emplace_back(std::move(commandInstance)); + delaySetupLock.unlock(); + return uptr.get(); + } + // logger.warn("Registering command \"{}\" after RegCmdEvent, note that this is unstable!", commandInstance->getCommandName()); + Schedule::nextTick([instance{commandInstance.release()}]() { + if (!_setup(std::unique_ptr(instance))) + logger.warn("Registering command \"{}\" failed", instance->getCommandName()); + updateAvailableCommands(); + }); + return ptr; + } + + std::unique_ptr DynamicCommand::createCommand(std::string const& name, std::string const& description, std::unordered_map>&& enums, std::vector&& params, std::vector>&& overloads, CallBackFn callback, CommandPermissionLevel permission, CommandFlag flag1, CommandFlag flag2, HMODULE handle) { + auto command = createCommand(name, description, permission, flag1, flag2, handle); + if (!command) + return std::unique_ptr(); + for (auto& [name, values] : enums) { + command->setEnum(name, std::move(values)); + } + for (auto& param : params) { + command->newParameter(std::move(param)); + } + for (auto& overload : overloads) { + command->addOverload(std::move(overload)); + } + command->setCallback(std::move(callback)); + return std::move(command); + } + + bool DynamicCommand::unregisterCommand(std::string const& name) { + #ifdef DEBUG + Schedule::nextTick([tid = std::this_thread::get_id()]() { + // Call DynamicCommand::unregisterCommand in other thread is not allowed! + assert(tid == std::this_thread::get_id()); + }); + #endif // DEBUG + if (Global->unregisterCommand(name)) { + dynamicCommandInstances.erase(name); + updateAvailableCommands(); + return true; + } + return false; + } + + inline bool DynamicCommand::updateAvailableCommands() { + #ifdef DEBUG + Schedule::nextTick([tid = std::this_thread::get_id()]() { + // Call DynamicCommand::updateAvailableCommands in other thread is not allowed! + assert(tid == std::this_thread::get_id()); + }); + #endif // DEBUG + + if (!Global || !Global) + return false; + auto packet = Global->serializeAvailableCommands(); + auto sender = (LoopbackPacketSender*)Global->getPacketSender(); + if (!sender) + return false; + sender->sendBroadcast(packet); + return true; + } + + inline DynamicCommandInstance const* DynamicCommand::getInstance() const { + return getInstance(getCommandName()); + } + + DynamicCommandInstance const* DynamicCommand::getInstance(std::string const& commandName) { + auto iter = dynamicCommandInstances.find(commandName); + if (iter == dynamicCommandInstances.end()) + return nullptr; + else + return iter->second.get(); + } + + #pragma endregion + + #pragma region DynamicCommandInstance + + inline DynamicCommandInstance::DynamicCommandInstance(std::string const& name, std::string const& description, CommandPermissionLevel permission, CommandFlag flag, HMODULE handle) + : name(name) + , description(std::make_unique(description)) + , permission(permission) + , flag(flag) + , handle(handle){}; + + inline DynamicCommandInstance::~DynamicCommandInstance() { + if (this->builder) + dcbFreeCallback((DCCallback*)this->builder); + this->builder = nullptr; + } + + inline std::unique_ptr DynamicCommandInstance::create(std::string const& name, std::string const& description, CommandPermissionLevel permission, CommandFlag flag, HMODULE handle) { + if (LL::globalConfig.serverStatus != LL::LLServerStatus::Running) { + for (auto& cmd : delaySetupCommandInstances) { + if (cmd->name == name) { + logger.error("Command \"{}\" already exists", name); + return {}; + } + } + } else if (Global->findCommand(name)) { + logger.error("Command \"{}\" already exists", name); + return {}; + } + return std::unique_ptr(new DynamicCommandInstance(name, description, permission, flag, handle)); + } + + inline bool DynamicCommandInstance::addOverload(std::vector&& params) { + std::vector indices; + for (auto& param : params) { + indices.push_back(newParameter(std::forward(param))); + } + return addOverload(std::move(indices)); + } + + inline std::string const& DynamicCommandInstance::setEnum(std::string const& description, std::vector const& values) { + auto& desc = enumNames.emplace_back(std::make_unique(description)); + enumRanges.emplace(*desc, std::pair{enumValues.size(), values.size()}); + enumValues.insert(enumValues.end(), values.begin(), values.end()); + return *desc; + } + + inline std::string const& DynamicCommandInstance::getEnumValue(int index) const { + if (index < 0 || index >= enumValues.size()) + throw std::runtime_error("Enum index out of range"); + return enumValues.at(index); + } + + ParameterIndex DynamicCommandInstance::newParameter(DynamicCommand::ParameterData&& data) { + auto iter = parameterPtrs.find(data.name); + size_t offset = -1; + if (iter == parameterPtrs.end()) { + offset = commandSize; + parameterPtrs.emplace(data.name, DynamicCommand::ParameterPtr(data.type, offset)); + commandSize += ParameterSizeMap.at(data.type) + 8; + } else { + offset = iter->second.getOffset(); + if (iter->second.type != data.type) + throw std::runtime_error(fmt::format("dynamic command \"{}\" register failed, Different type parameters with the same name {} are not allowed", name, data.name)); + } + std::string const& identifier = data.identifier; + if (parameterDatas.end() != std::find_if(parameterDatas.begin(), parameterDatas.end(), + [&](DynamicCommand::ParameterData const& data) { return data.identifier == identifier; })) + throw std::runtime_error("parameter identifier already exists"); + data.offset = offset; + parameterDatas.emplace_back(std::move(data)); + return {this, parameterDatas.size() - 1}; + } + + inline ParameterIndex DynamicCommandInstance::newParameter(std::string const& name, DynamicCommand::ParameterType type, bool optional, std::string const& description, std::string const& identifier, CommandParameterOption parameterOption) { + return newParameter(ParameterData(name, type, optional, description, identifier, parameterOption)); + } + + inline ParameterIndex DynamicCommandInstance::findParameterIndex(std::string const& indentifier) { + size_t index = 0; + for (auto& paramData : parameterDatas) { + if (paramData.identifier == indentifier || paramData.description == indentifier || paramData.name == indentifier) + break; + ++index; + } + if (index == parameterDatas.size()) + index = -1; + return {this, index}; + } + + inline ParameterIndex DynamicCommandInstance::mandatory(std::string const& name, DynamicCommand::ParameterType type, std::string const& description, std::string const& identifier, CommandParameterOption parameterOption) { + return newParameter(ParameterData(name, type, false, description, identifier, parameterOption)); + } + inline ParameterIndex DynamicCommandInstance::mandatory(std::string const& name, DynamicCommand::ParameterType type, std::string const& description, CommandParameterOption parameterOption) { + return mandatory(name, type, description, "", parameterOption); + }; + inline ParameterIndex DynamicCommandInstance::mandatory(std::string const& name, DynamicCommand::ParameterType type, CommandParameterOption parameterOption) { + return mandatory(name, type, "", "", parameterOption); + }; + + inline ParameterIndex DynamicCommandInstance::optional(std::string const& name, DynamicCommand::ParameterType type, std::string const& description, std::string const& identifier, CommandParameterOption parameterOption) { + return newParameter(ParameterData(name, type, true, description, identifier, parameterOption)); + } + + inline ParameterIndex DynamicCommandInstance::optional(std::string const& name, DynamicCommand::ParameterType type, std::string const& description, CommandParameterOption parameterOption) { + return optional(name, type, description, "", parameterOption); + } + + inline ParameterIndex DynamicCommandInstance::optional(std::string const& name, DynamicCommand::ParameterType type, CommandParameterOption parameterOption) { + return optional(name, type, "", "", parameterOption); + } + + bool DynamicCommandInstance::addOverload(std::vector&& params) { + for (auto& index : params) { + if (index >= parameterDatas.size()) + throw std::runtime_error("parameter index " + std::to_string(index) + " out of range 0 ~ " + std::to_string(parameterDatas.size())); + } + overloads.emplace_back(params); + return true; + } + + inline bool DynamicCommandInstance::addOverload(std::vector&& params) { + std::vector paramIndices; + for (auto& param : params) { + auto index = findParameterIndex(param); + if (!index.isValid()) { + throw std::runtime_error("Parameter " + std::string(param) + "not found"); + } + paramIndices.push_back(index); + } + return addOverload(std::move(paramIndices)); + } + + inline bool DynamicCommandInstance::addOverload(std::vector&& params) { + std::vector paramIndices; + for (auto& param : params) { + paramIndices.push_back(findParameterIndex(param)); + } + return addOverload(std::move(paramIndices)); + } + + inline bool DynamicCommandInstance::setAlias(std::string const& alias) { + this->alias = alias; + return true; + } + + inline std::vector DynamicCommandInstance::buildOverload(std::vector const& overload) { + std::vector datas; + for (auto& index : overload) { + auto& param = parameterDatas.at(index); + datas.emplace_back(param.makeParameterData()); + } + return datas; + } + + // bool DynamicCommandInstance::updateSoftEnum(std::string const& name) const + //{ + // if (!hasRegistered()) + // { + // for (auto& [key, values] : softEnumValues) + // { + // Global->addSoftEnum(key, values); + // } + // return true; + // } + // if (!name.empty()) + // { + // auto iter = softEnumValues.find(name); + // if (iter != softEnumValues.end()) + // CommandSoftEnumRegistry(Global).updateSoftEnum(SoftEnumUpdateType::Set, iter->first, iter->second); + // else + // return false; + // return true; + // } + // else + // { + // for (auto& [key, values] : softEnumValues) + // { + // CommandSoftEnumRegistry(Global).updateSoftEnum(SoftEnumUpdateType::Set, key, values); + // } + // } + // } + std::string DynamicCommandInstance::setSoftEnum(std::string const& name, std::vector const& values) const { + if (!hasRegistered()) { + softEnums.emplace(name, values); + } else { + if (!Global) + return ""; + auto names = CommandRegistry::getSoftEnumNames(); + if (std::find(names.begin(), names.end(), name) == names.end()) { + Global->addSoftEnum(name, values); + return name; + } + CommandSoftEnumRegistry(Global).updateSoftEnum(SoftEnumUpdateType::Set, name, values); + } + return name; + } + bool DynamicCommandInstance::addSoftEnumValues(std::string const& name, std::vector const& values) const { + if (!hasRegistered()) { + auto iter = softEnums.find(name); + if (iter != softEnums.end()) { + iter->second.insert(iter->second.end(), values.begin(), values.end()); + } else { + setSoftEnum(name, values); + } + } else { + if (!Global) + return false; + auto names = CommandRegistry::getSoftEnumNames(); + if (std::find(names.begin(), names.end(), name) == names.end()) { + Global->addSoftEnum(name, values); + return true; + } + CommandSoftEnumRegistry(Global).updateSoftEnum(SoftEnumUpdateType::Add, name, values); + } + return true; + }; + bool DynamicCommandInstance::removeSoftEnumValues(std::string const& name, std::vector const& values) const { + if (!hasRegistered()) { + auto iter = softEnums.find(name); + if (iter != softEnums.end()) { + auto tmp = std::remove_if( + iter->second.begin(), iter->second.end(), + [values](std::string const& val) { + return std::find(values.begin(), values.end(), val) != values.end(); + }); + iter->second.erase(tmp, iter->second.end()); + return true; + } + return false; + } else { + if (Global) + CommandSoftEnumRegistry(Global).updateSoftEnum(SoftEnumUpdateType::Remove, name, values); + } + return true; + } + inline std::vector DynamicCommandInstance::getSoftEnumValues(std::string const& name) { + return CommandRegistry::getSoftEnumValues(name); + } + inline std::vector DynamicCommandInstance::getSoftEnumNames() { + return CommandRegistry::getSoftEnumNames(); + } + + inline void DynamicCommandInstance::setCallback(DynamicCommand::CallBackFn&& callback) const { + this->callback = callback; + } + + inline void DynamicCommandInstance::removeCallback() const { + callback = nullptr; + } + + inline std::string const& DynamicCommandInstance::getCommandName() const { + return name; + } + + inline bool DynamicCommandInstance::setBuilder(DynamicCommand::BuilderFn builder) { + if (this->builder == nullptr) + this->builder = builder; + else + return false; + return true; + } + + inline DynamicCommand::BuilderFn DynamicCommandInstance::initCommandBuilder() { + auto builder = (DynamicCommand::BuilderFn)dcbNewCallback("ifsdl)p", &DynamicCommand::builderCallbackHanler, this); + if (this->setBuilder(builder)) + return builder; + dcbFreeCallback((DCCallback*)builder); + return nullptr; + } + + #pragma endregion + + #ifdef DEBUG + #define TEST_DYNAMIC_COMMAND + #define successf(...) success(fmt::format(__VA_ARGS__)) + #define errorf(...) error(fmt::format(__VA_ARGS__)) + using Param = DynamicCommand::ParameterData; + using ParamType = DynamicCommand::ParameterType; + using ParamIndex = DynamicCommandInstance::ParameterIndex; + + #ifdef TEST_DYNAMIC_COMMAND + + #include + #include + #include + + void setupTestParamCommand() { + using Param = DynamicCommand::ParameterData; + using ParamType = DynamicCommand::ParameterType; + Param boolParam("testBool", ParamType::Bool, true); + Param intParam("testInt", ParamType::Int, true); + Param floatParam("testFloat", ParamType::Float, true); + Param strParam("testStr", ParamType::String, true); + Param actorParam("testActor", ParamType::Actor, true); + Param playerParam("testPlayer", ParamType::Player, true); + Param BlockPosParam("testBlockPos", ParamType::BlockPos, true); + Param Vec3Param("testVec3", ParamType::Vec3, true); + Param RawTextParam("testRawText", ParamType::RawText, true); + Param MessageParam("testMessage", ParamType::Message, true); + Param JsonValueParam("testJsonValue", ParamType::JsonValue, true); + Param ItemParam("testItem", ParamType::Item, true); + Param BlockParam("testBlock", ParamType::Block, true); + Param ActorTypeParam("testActorType", ParamType::ActorType, true); + Param EffectParam("testEffect", ParamType::Effect, true); + Param CommandParam("testCommand", ParamType::Command, true); + // Param posParam(ParamType::Position, "testPos", true); + // Test Command: dynparam true 114 3.14 str @e @a 3 1 4 ~3 ~1 ~4 raw text msg {"a":4} stick concrete speed version + DynamicCommand::setup( + "param", "dynamic command", + {}, + { + boolParam, + intParam, + floatParam, + strParam, + actorParam, + playerParam, + BlockPosParam, + Vec3Param, + RawTextParam, + MessageParam, + JsonValueParam, + ItemParam, + BlockParam, + ActorTypeParam, + EffectParam, + CommandParam, + }, + {{ + "testActorType", + "testBool", + "testInt", + "testFloat", + "testStr", + "testActor", + "testPlayer", + "testBlockPos", + "testVec3", + //"testRawText", + //"testMessage", + //"testJsonValue", + //"testItem", + //"testBlock", + //"testEffect", + //"testCommand", + }}, + [](DynamicCommand const& command, CommandOrigin const& origin, CommandOutput& output, std::unordered_map& results) { + for (auto& [name, result] : results) { + output.success(result.toDebugString()); + } + }, + CommandPermissionLevel::Any); + } + + void setupTestEnumCommand() { + 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", "", CommandParameterOption::EnumAutocompleteExpansion), + Param("testEnum", ParamType::Enum, "TestEnum2", "", CommandParameterOption::EnumAutocompleteExpansion), + 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"].getRaw(); + 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); + } + + void setupExampleCommand() { + 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)); + } + + // "remove command" command + void setupRemoveCommand() { + auto command = DynamicCommand::createCommand("unregister", "unregister command", CommandPermissionLevel::Any); + command->setAlias("remove"); + auto name = command->mandatory("name", ParamType::SoftEnum, + command->setSoftEnum("CommandNames", {})); + command->addOverload(name); + command->setCallback( + [](DynamicCommand const& cmd, CommandOrigin const& origin, CommandOutput& output, + std::unordered_map& results) { + auto& name = results["name"].getRaw(); + auto fullName = Global->getCommandFullName(name); + if (fullName == cmd.getCommandName()) { + output.success("Request unregister itself"); + Schedule::delay([fullName]() { + auto res = Global->unregisterCommand(fullName); + if (res) { + dynamicCommandInstances.erase(fullName); + logger.info("unregister command " + fullName); + ((DynamicCommandInstance*)0)->setSoftEnum("CommandNames", CommandRegistry::getEnumValues("CommandName")); + } else + logger.error("error in unregister command " + fullName); + }, + 20); + return; + } + auto res = Global->unregisterCommand(fullName); + if (res) { + dynamicCommandInstances.erase(fullName); + output.success("unregister command " + fullName); + cmd.getInstance()->setSoftEnum("CommandNames", CommandRegistry::getEnumValues("CommandName")); + } else + output.error("error in unregister command " + fullName); + }); + command->setSoftEnum("CommandNames", CommandRegistry::getEnumValues("CommandName")); + DynamicCommand::setup(std::move(command)); + } + + + // TInstanceHook(void, "?run@Command@@QEBAXAEBVCommandOrigin@@AEAVCommandOutput@@@Z", + // Command, class CommandOrigin const& origin, class CommandOutput& output) + //{ + // logger.info("Command({})::run()", getCommandName()); + // } + + // force enable cheat + TClasslessInstanceHook(bool, "?hasCommandsEnabled@LevelData@@QEBA_NXZ") { + return true; + } + + TInstanceHook(CommandParameterData&, "?addOptions@CommandParameterData@@QEAAAEAV1@W4CommandParameterOption@@@Z", + CommandParameterData, CommandParameterOption option) { + // logger.warn("CommandParameterData::addOptions - name: {}, type: {}, desc: {}, option: {:x}", + // name, magic_enum::enum_name(type), desc ? desc : "", (int)option); + return original(this, option); + } + + #endif // TEST_DYNAMIC_COMMAND + + // enum command + void onEnumExecute(DynamicCommand const& cmd, CommandOrigin const& origin, CommandOutput& output, + std::unordered_map& results) { + auto enumNames = Global->getEnumNames(); + auto softEnumNames = Global->getSoftEnumNames(); + cmd.getInstance()->setSoftEnum("EnumNameList", enumNames); + cmd.getInstance()->addSoftEnumValues("EnumNameList", softEnumNames); + if (results["name"].isSet) { + auto& enumName = results["name"].getRaw(); + bool found = false; + if (std::find(enumNames.begin(), enumNames.end(), enumName) != enumNames.end()) { + found = true; + output.successf("§eEnum §l{}§r§e Values:", enumName); + for (auto& val : CommandRegistry::getEnumValues(enumName)) { + output.success(val); + // output.addToResultList("enums", val); + } + // output.success("Enums: %1$s", {CommandOutputParameter("enums")}); + } + if (std::find(softEnumNames.begin(), softEnumNames.end(), enumName) != softEnumNames.end()) { + found = true; + output.successf("§eSoft Enum §l{}§r§e Values:", enumName); + for (auto& val : CommandRegistry::getSoftEnumValues(enumName)) { + output.success(val); + } + } + if (!found) + output.errorf("Enum or Soft Enum \"{}\" not found", enumName); + } else { + output.success("§eEnum Names:"); + for (auto& val : CommandRegistry::getEnumNames()) { + output.success(val); + } + output.success("§eSoft Enum Names:"); + for (auto& val : CommandRegistry::getSoftEnumNames()) { + output.success(val); + } + } + } + + void setupEnumCommand() { + auto command = DynamicCommand::createCommand("enum", "get command enum names or values", CommandPermissionLevel::Any); + command->setAlias("enums"); + auto name = command->mandatory("name", ParamType::SoftEnum, + command->setSoftEnum("EnumNameList", {})); + command->addOverload(name); + command->addOverload(); + command->setCallback(onEnumExecute); + auto cmd = DynamicCommand::setup(std::move(command)); + Schedule::delay( + [cmd]() { + auto packet = Global->serializeAvailableCommands(); + cmd->setSoftEnum("EnumNameList", packet.getEnumNames()); + cmd->addSoftEnumValues("EnumNameList", packet.getSoftEnumNames()); + }, + 10); + } + + // echo command + void setupEchoCommand() { + auto command = DynamicCommand::createCommand("echo", "show message", CommandPermissionLevel::Any); + command->addOverload(command->mandatory("text", ParamType::RawText)); + command->setCallback( + [](DynamicCommand const& cmd, CommandOrigin const& origin, CommandOutput& output, + std::unordered_map& results) { + auto& text = results["text"].getRaw(); + output.success(text); + }); + DynamicCommand::setup(std::move(command)); + } + + TClasslessInstanceHook2("startServerThread_RegisterDebugCommand", void, "?startServerThread@ServerInstance@@QEAAXXZ") { + #ifdef DEBUG + setupRemoveCommand(); + setupTestEnumCommand(); + setupTestParamCommand(); + setupExampleCommand(); + #if false + Global->printAll(); + Schedule::delayRepeat( + []() { + static bool Switch = true; + if (Switch) + Global->runcmd("remove example"); + else + setupExampleCommand(); + Switch = !Switch; + }, + 200, 2); + #endif // COMMAND_REGISTRY_EXTRA + #endif // DEBUG + original(this); + setupEnumCommand(); + setupEchoCommand(); + } + + #endif // DEBUG + + TClasslessInstanceHook(void, "?compile@BaseCommandBlock@@AEAAXAEBVCommandOrigin@@AEAVLevel@@@Z", + class CommandOrigin const& origin, class Level& level) { + if (LL::globalConfig.tickThreadId != std::this_thread::get_id()) { + SRWLockSharedHolder locker(delaySetupLock); + return original(this, origin, level); + } + return original(this, origin, level); + } diff --git a/LiteLoader/Kernel/EventAPI.cpp b/LiteLoader/Kernel/EventAPI.cpp index 6d46d00..36f3194 100644 --- a/LiteLoader/Kernel/EventAPI.cpp +++ b/LiteLoader/Kernel/EventAPI.cpp @@ -2017,19 +2017,19 @@ TClasslessInstanceHook(void, "?execute@StopCommand@@UEBAXAEBVCommandOrigin@@AEAV ////////////// RegCmd ////////////// -// TInstanceHook(void, "?setup@ChangeSettingCommand@@SAXAEAVCommandRegistry@@@Z", -// CommandRegistry, void* a1) { -// Global = this; -// original(this, a1); -// IF_LISTENED(RegCmdEvent) { -// RegCmdEvent ev{}; -// ev.mCommandRegistry = this; -// ev.call(); -// // setup dynamic command -// DynamicCommand::onServerCommandsRegister(*this); -// } -// IF_LISTENED_END(RegCmdEvent) -// } + TInstanceHook(void, "?setup@ChangeSettingCommand@@SAXAEAVCommandRegistry@@@Z", + CommandRegistry, void* a1) { + Global = this; + original(this, a1); + IF_LISTENED(RegCmdEvent) { + RegCmdEvent ev{}; + ev.mCommandRegistry = this; + ev.call(); + // setup dynamic command + DynamicCommand::onServerCommandsRegister(*this); + } + IF_LISTENED_END(RegCmdEvent) + } ////////////// ConsoleOutput ////////////// THook(std::ostream&, diff --git a/LiteLoader/Kernel/MC/ActorAPI.cpp b/LiteLoader/Kernel/MC/ActorAPI.cpp index a4a0d99..b824154 100644 --- a/LiteLoader/Kernel/MC/ActorAPI.cpp +++ b/LiteLoader/Kernel/MC/ActorAPI.cpp @@ -18,10 +18,10 @@ #include #include #include -//#include +#include //#include //#include -//#include +#include //#include #include #include @@ -59,9 +59,9 @@ bool Actor::isOnGround() const { return (dAccess(this)); // IDA DirectActorProxyImpl::isOnGround } -// std::string Actor::getTypeName() const { -// return getActorIdentifier().getCanonicalName(); -// } + std::string Actor::getTypeName() const { + return getActorIdentifier().getCanonicalName(); + } // bool Actor::hurtEntity(float damage, ActorDamageCause damageCause) { // auto ads = new ActorDamageSource(damageCause); @@ -93,23 +93,25 @@ ActorUniqueID Actor::getActorUniqueId() const { } // static_assert(sizeof(TeleportRotationData) == 32); -// bool Actor::teleport(Vec3 to, int dimID) { -// if (!this->isAlive()) -// return false; + bool Actor::teleport(Vec3 to, int dimID) { + if (!this->isAlive()) + return false; // char mem[48]; // auto computeTarget = (TeleportTarget * (*)(void*, class Actor&, class Vec3, class Vec3*, class AutomaticID, std::optional const&, int))(&TeleportCommand::computeTarget); // auto target = computeTarget(mem, *this, to, nullptr, dimID, TeleportRotationData{getRotation().x, getRotation().y, {}}, 15); // TeleportCommand::applyTarget(*this, *target, false); -// return true; -// } + TeleportCommand::teleport(*this,to,nullptr,dimID,getRotation().x, getRotation().y,15,this->getUniqueID()); + return true; + } -// bool Actor::teleport(Vec3 to, int dimID, float x, float y) { + bool Actor::teleport(Vec3 to, int dimID, float x, float y) { // char mem[48]; // auto computeTarget = (TeleportTarget * (*)(void*, class Actor&, class Vec3, class Vec3*, class AutomaticID, std::optional const&, int))(&TeleportCommand::computeTarget); // auto target = computeTarget(mem, *this, to, nullptr, dimID, TeleportRotationData{x, y, {}}, 15); // TeleportCommand::applyTarget(*this, *target, false); -// return true; -// } + TeleportCommand::teleport(*this,to,nullptr,dimID,x,y,15,this->getUniqueID()); + return true; + } SimpleContainer & Actor::getHandContainer(){ //ScriptHandContainerComponent::hasComponent actor diff --git a/LiteLoader/Kernel/MC/LevelAPI.cpp b/LiteLoader/Kernel/MC/LevelAPI.cpp index 611683a..3de80fd 100644 --- a/LiteLoader/Kernel/MC/LevelAPI.cpp +++ b/LiteLoader/Kernel/MC/LevelAPI.cpp @@ -177,7 +177,7 @@ std::unique_ptr getPlayerOriginTag(Player& player) { // return MinecraftCommands::_runcmd(std::move(origin), cmd); // } -// std::unordered_map resultOfOrigin = {}; + std::unordered_map resultOfOrigin = {}; // std::pair Level::executeCommandEx(const string& cmd) { // auto origin = ::ServerCommandOrigin::load(getServerOriginTag(), *Global); diff --git a/LiteLoader/Main/BuiltinCommands.cpp b/LiteLoader/Main/BuiltinCommands.cpp index 265097e..1ee4359 100644 --- a/LiteLoader/Main/BuiltinCommands.cpp +++ b/LiteLoader/Main/BuiltinCommands.cpp @@ -1,383 +1,383 @@ -//#include -//#include -//#include -//#include -//#include -//#include -//#include -//#include -//#include -//#include -//#include -//#include -//#include
-//#include
-//#include "../ScriptEngine/Main/Configs.h" -// -//using namespace RegisterCommandHelper; -//using namespace LL; -// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include
+#include
+#include "../ScriptEngine/Main/Configs.h" + +using namespace RegisterCommandHelper; +using namespace LL; + //static_assert(sizeof(CommandSelector) == 200); -// -//class TeleportDimensionCommand : public Command { -// -// enum class DimensionType { -// OverWorld, -// Nether, -// TheEnd, -// } DimensionId; -// CommandSelector Victim; -// CommandPosition CommandPos; -// bool Victim_isSet = false; -// bool CommandPos_isSet = false; -// -// Vec3 getTargetPos(CommandOrigin const& ori, Actor* actor) const { -// if (CommandPos_isSet) -// return CommandPos.getPosition(ori, {0, 0, 0}); -// auto pos = actor->getPosition(); -// Vec3 result = pos; -// int actorDimensionId = actor->getDimensionId(); -// switch (DimensionId) { -// case TeleportDimensionCommand::DimensionType::OverWorld: -// if (actorDimensionId == 1) -// result = {pos.x * 8, pos.y, pos.z * 8}; -// break; -// case TeleportDimensionCommand::DimensionType::Nether: -// if (actorDimensionId != 1) -// result = {pos.x / 8, pos.y, pos.z / 8}; -// break; -// case TeleportDimensionCommand::DimensionType::TheEnd: -// if (actorDimensionId != 2) -// result = {100, 50, 0}; -// break; -// default: -// break; -// } -// return result; -// } -// -// bool teleportTarget(CommandOrigin const& ori, CommandOutput& output, Actor* actor) const { -// auto dim = VanillaDimensions::toString((int)DimensionId); -// auto pos = getTargetPos(ori, actor); -// actor->teleport(pos, (int)DimensionId); -// output.trSuccess("ll.cmd.tpdim.success", actor->getNameTag(), dim, pos.x, pos.y, pos.z); -// return true; -// } -// -// bool teleportTargets(CommandOrigin const& ori, CommandOutput& output, CommandSelectorResults& actors) const { -// auto dim = VanillaDimensions::toString((int)DimensionId); -// std::string names; -// for (auto& actor : actors) { -// std::string actorName = actor->getNameTag(); -// if (actorName.empty()) { -// actorName = actor->getTypeName(); -// } -// names.append(", ").append(actorName); -// if (actor->teleport(getTargetPos(ori, actor), (int)DimensionId)) { -// output.success(); -// } -// } -// if (output.getSuccessCount() == 0) { -// output.trError("ll.cmd.tpdim.error.noActorTeleported"); -// return false; -// } else { -// std::string message = fmt::format("Teleported {} to {}", names.substr(2), dim); -// if (CommandPos_isSet) { -// auto pos = CommandPos.getPosition(ori, {0, 0, 0}); -// message.append(fmt::format(" ({:2f}, {:2f}, {:2f})", pos.x, pos.y, pos.z)); -// } -// output.addMessage(message); -// return true; -// } -// } -// -//public: -// void execute(CommandOrigin const& ori, CommandOutput& output) const override { -// output.setLanguageCode(ori); -// if ((int)DimensionId < 0 || (int)DimensionId > 2) { -// output.trError("ll.cmd.tpdim.invalidDimid", (int)DimensionId); -// return; -// } -// if (Victim_isSet) { -// auto result = Victim.results(ori); -// if (result.empty()) -// output.trError("ll.cmd.tpdim.error.noActorSpecified"); -// else if (result.count() == 1) -// teleportTarget(ori, output, *result.begin()); -// else -// teleportTargets(ori, output, result); -// } else { -// auto actor = ori.getEntity(); -// if (!actor) -// output.trError("ll.cmd.tpdim.error.noActorSpecified"); -// else -// teleportTarget(ori, output, actor); -// } -// } -// -// static void setup(CommandRegistry* registry) { -// registry->registerCommand( -// "tpdim", "Teleport to Dimension", CommandPermissionLevel::GameMasters, -// {(CommandFlagValue)0}, {(CommandFlagValue)0x80}); -// registry->addEnum("DimensionType", -// { -// {"overworld", DimensionType::OverWorld}, -// {"o", DimensionType::OverWorld}, -// {"nether", DimensionType::Nether}, -// {"n", DimensionType::Nether}, -// {"end", DimensionType::TheEnd}, -// {"e", DimensionType::TheEnd}, -// }); -// auto dimensionTypeParam = makeMandatory(&TeleportDimensionCommand::DimensionId, -// "Dimension", "DimensionType"); -// auto dimensionIdParam = makeMandatory((int TeleportDimensionCommand::*)&TeleportDimensionCommand::DimensionId, -// "DimensionId"); -// auto victimParam = makeMandatory(&TeleportDimensionCommand::Victim, "victim", -// &TeleportDimensionCommand::Victim_isSet); -// auto positionParam = makeOptional(&TeleportDimensionCommand::CommandPos, -// "Position", &TeleportDimensionCommand::CommandPos_isSet); -// -// registry->registerOverload( -// "tpdim", victimParam, dimensionTypeParam, positionParam); -// registry->registerOverload( -// "tpdim", victimParam, dimensionIdParam, positionParam); -// // registry->registerOverload( -// // "tpdim", dimensionTypeParam, positionParam); -// registry->registerOverload( -// "tpdim", dimensionIdParam, positionParam); -// } -//}; -// -//void LLListPluginsCommand(CommandOutput& output) { -// auto plugins = LL::getAllPlugins(); -// output.trSuccess("ll.cmd.listPlugin.overview", plugins.size()); -// -// std::ostringstream oss; -// for (auto& [name, plugin] : plugins) { -// string pluginName = name; -// if (pluginName.find("§") == string::npos) -// pluginName = "§b" + pluginName; -// string desc = plugin->desc; -// if (desc.find("§") == string::npos) -// desc = "§7" + desc; -// -// auto fileName = UTF82String(std::filesystem::path(str2wstr(plugin->filePath)).filename().u8string()); -// oss << fmt::format("- {} §a[v{}] §8({})\n {}\n", -// pluginName, plugin->version.toString(), fileName, desc); -// } -// output.success(oss.str() + '\n'); -// output.trAddMessage("ll.cmd.listPlugin.tip"); -//} -// -//void LLPluginInfoCommand(CommandOutput& output, const string& pluginName) { -// auto plugin = LL::getPlugin(pluginName); -// if (plugin) { -// std::map outs; -// std::ostringstream oss; -// auto fn = UTF82String(std::filesystem::path(str2wstr(plugin->filePath)).filename().u8string()); -// string pluginType = plugin->type == Plugin::PluginType::ScriptPlugin ? "Script Plugin" : "DLL Plugin"; -// -// output.trAddMessage("ll.cmd.pluginInfo.title", pluginName); -// -// outs.emplace("Name", fmt::format("{} ({})", plugin->name, fn)); -// outs.emplace("Description", plugin->desc); -// outs.emplace("Version", "v" + plugin->version.toString(true)); -// outs.emplace("Type", pluginType); -// outs.emplace("File Path", plugin->filePath); -// outs.merge(plugin->others); -// size_t width = 10; -// for (auto& [k, _] : outs) -// width = std::max(width, k.length()); -// for (auto& [k, v] : outs) { -// if (k != "PluginType" && k != "PluginFilePath") -// oss << "- §l" << std::setw(width) << std::left << k << "§r: " << v << std::endl; -// } -// auto text = oss.str(); -// text.pop_back(); -// output.success(text, {}); -// } else { -// output.trError("ll.cmd.pluginInfo.error.pluginNotFound", pluginName); -// } -//} -// -//void LLVersionCommand(CommandOutput& output) { -// output.trSuccess("ll.cmd.version.msg", LL::getBdsVersion(), LL::getLoaderVersionString(), LL::getServerProtocolVersion()); -//} -// -//void LLHelpCommand(CommandOutput& output) { -// output.trSuccess("ll.cmd.help.msg"); -//} -// -//void LLLoadPluginCommand(CommandOutput& output, const string& path) { -// // if (!LL::isDebugMode()) -// // return; -// if (PluginManager::loadPlugin(path, true)) { -// output.trSuccess("ll.cmd.loadPlugin.success", path); -// } else { -// output.trError("ll.cmd.loadPlugin.fail", path); -// } -//} -// -//void LLUnloadPluginCommand(CommandOutput& output, const string& pluginName) { -// // if (!LL::isDebugMode()) -// // return; -// if (PluginManager::unloadPlugin(pluginName, true)) { -// output.trSuccess("ll.cmd.unloadPlugin.success", pluginName); -// } else { -// output.trError("ll.cmd.unloadPlugin.fail", pluginName); -// } -//} -// -//void LLReloadPluginCommand(CommandOutput& output, const string& pluginName, bool reloadAll) { -// // if (!LL::isDebugMode()) -// // return; -// if (!reloadAll) { -// if (PluginManager::reloadPlugin(pluginName, true)) { -// output.trSuccess("ll.cmd.reloadPlugin.success", pluginName); -// } else { -// output.trError("ll.cmd.reloadPlugin.fail", pluginName); -// } -// } else { -// int cnt = PluginManager::reloadAllPlugins(true); -// if (cnt > 0) { -// output.trSuccess("ll.cmd.reloadAllPlugins.success", cnt); -// } else { -// output.trError("ll.cmd.reloadAllPlugins.fail"); -// } -// } -//} -// -//class LLCommand : public Command { -// -// enum class Operation { -// Version, -// List, -// Help, -// Load, -// Unload, -// Reload -// }; -// -// Operation operation; -// bool hasUpgradeOption, hasPluginNameSet; -// CommandRawText pluginNameToDoOperation; -// -//public: -// void execute(CommandOrigin const& ori, CommandOutput& output) const override { -// output.setLanguageCode(ori); -// std::string pluginName = ""; -// if (hasPluginNameSet) { -// pluginName = pluginNameToDoOperation; -// if (pluginName.size() > 1 && pluginName[0] == '"' && pluginName[pluginName.size() - 1] == '"' && pluginName[pluginName.size() - 2] != '\\') { -// pluginName.erase(0, 1); -// pluginName.pop_back(); -// } -// } -// switch (operation) { -// case Operation::Version: -// LLVersionCommand(output); -// break; -// case Operation::List: -// if (!hasPluginNameSet) -// LLListPluginsCommand(output); -// else -// LLPluginInfoCommand(output, pluginName); -// break; -// case Operation::Load: -// if (hasPluginNameSet) -// LLLoadPluginCommand(output, pluginName); -// else -// output.trError("ll.cmd.error.noPathSpecified"); -// break; -// case Operation::Unload: -// if (hasPluginNameSet) -// LLUnloadPluginCommand(output, pluginName); -// else -// output.trError("ll.cmd.error.noNameSpecified"); -// break; -// case Operation::Reload: -// if (hasPluginNameSet) -// LLReloadPluginCommand(output, pluginName, false); -// else -// LLReloadPluginCommand(output, "", true); -// break; -// case Operation::Help: -// LLHelpCommand(output); -// break; -// default: -// break; -// } -// } -// -// static void setup(CommandRegistry* registry) { -// // Register Cmd -// registry->registerCommand("ll", "LiteLoaderBDS plugin operations", -// CommandPermissionLevel::Console, {(CommandFlagValue)0}, {(CommandFlagValue)0x80}); -// -// // Register softenum -// vector pluginList; -// for (auto& [name, p] : LL::getAllPlugins()) { -// pluginList.push_back(name); -// } -// registry->addSoftEnum("PluginName", pluginList); -// -// // ll version & help -// registry->addEnum("Operation_Common", {{"version", Operation::Version}, -// {"help", Operation::Help}}); -// registry->registerOverload( -// "ll", -// makeMandatory(&LLCommand::operation, "Operation", "Operation_Common").addOptions((CommandParameterOption)1)); -// -// // ll load -// registry->addEnum("Operation_FreeFilePath", { -// {"load", Operation::Load}, -// }); -// registry->registerOverload( -// "ll", -// makeMandatory(&LLCommand::operation, "Operation", "Operation_FreeFilePath").addOptions((CommandParameterOption)1), -// makeMandatory(&LLCommand::pluginNameToDoOperation, "pluginPath", nullptr, &LLCommand::hasPluginNameSet)); -// -// // ll unload -// registry->addEnum("Operation_MustPluginName", { -// {"unload", Operation::Unload}, -// }); -// registry->registerOverload( -// "ll", -// makeMandatory(&LLCommand::operation, "Operation", "Operation_MustPluginName").addOptions((CommandParameterOption)1), -// makeMandatory((std::string LLCommand::*)&LLCommand::pluginNameToDoOperation, "pluginName", "PluginName", &LLCommand::hasPluginNameSet)); -// -// // ll list & reload -// registry->addEnum("Operation_OptionalPluginName", { -// {"list", Operation::List}, -// {"plugins", Operation::List}, -// {"reload", Operation::Reload}, -// }); -// registry->registerOverload( -// "ll", -// makeMandatory(&LLCommand::operation, "Operation", "Operation_OptionalPluginName").addOptions((CommandParameterOption)1), -// makeOptional((std::string LLCommand::*)&LLCommand::pluginNameToDoOperation, "pluginName", "PluginName", &LLCommand::hasPluginNameSet)); -// } -//}; -// -//class VersionCommand : public Command { -// -//public: -// void execute(CommandOrigin const& ori, CommandOutput& output) const override { -// output.setLanguageCode(ori); -//#ifdef DEBUG -// Logger("CommandOrigin").warn(ori.serialize().toSNBT()); -//#endif // DEBUG -// LLVersionCommand(output); -// } -// -// static void setup(CommandRegistry* registry) { -// registry->registerCommand("version", "Get the version of this server", -// CommandPermissionLevel::GameMasters, {(CommandFlagValue)0}, {(CommandFlagValue)0x80}); -// registry->registerOverload("version"); -// } -//}; -// -//void RegisterCommands() { + +class TeleportDimensionCommand : public Command { + + enum class DimensionType { + OverWorld, + Nether, + TheEnd, + } DimensionId; + CommandSelector Victim; + CommandPosition CommandPos; + bool Victim_isSet = false; + bool CommandPos_isSet = false; + + Vec3 getTargetPos(CommandOrigin const& ori, Actor* actor) const { + if (CommandPos_isSet) + return CommandPos.getPosition(ori, {0, 0, 0}); + auto pos = actor->getPosition(); + Vec3 result = pos; + int actorDimensionId = actor->getDimensionId(); + switch (DimensionId) { + case TeleportDimensionCommand::DimensionType::OverWorld: + if (actorDimensionId == 1) + result = {pos.x * 8, pos.y, pos.z * 8}; + break; + case TeleportDimensionCommand::DimensionType::Nether: + if (actorDimensionId != 1) + result = {pos.x / 8, pos.y, pos.z / 8}; + break; + case TeleportDimensionCommand::DimensionType::TheEnd: + if (actorDimensionId != 2) + result = {100, 50, 0}; + break; + default: + break; + } + return result; + } + + bool teleportTarget(CommandOrigin const& ori, CommandOutput& output, Actor* actor) const { + auto dim = VanillaDimensions::toString((int)DimensionId); + auto pos = getTargetPos(ori, actor); + actor->teleport(pos, (int)DimensionId); + output.trSuccess("ll.cmd.tpdim.success", actor->getNameTag(), dim, pos.x, pos.y, pos.z); + return true; + } + + bool teleportTargets(CommandOrigin const& ori, CommandOutput& output, CommandSelectorResults& actors) const { + auto dim = VanillaDimensions::toString((int)DimensionId); + std::string names; + for (auto& actor : actors) { + std::string actorName = actor->getNameTag(); + if (actorName.empty()) { + actorName = actor->getTypeName(); + } + names.append(", ").append(actorName); + if (actor->teleport(getTargetPos(ori, actor), (int)DimensionId)) { + output.success(); + } + } + if (output.getSuccessCount() == 0) { + output.trError("ll.cmd.tpdim.error.noActorTeleported"); + return false; + } else { + std::string message = fmt::format("Teleported {} to {}", names.substr(2), dim); + if (CommandPos_isSet) { + auto pos = CommandPos.getPosition(ori, {0, 0, 0}); + message.append(fmt::format(" ({:2f}, {:2f}, {:2f})", pos.x, pos.y, pos.z)); + } + output.addMessage(message); + return true; + } + } + +public: + void execute(CommandOrigin const& ori, CommandOutput& output) const override { + output.setLanguageCode(ori); + if ((int)DimensionId < 0 || (int)DimensionId > 2) { + output.trError("ll.cmd.tpdim.invalidDimid", (int)DimensionId); + return; + } + if (Victim_isSet) { + auto result = Victim.results(ori); + if (result.empty()) + output.trError("ll.cmd.tpdim.error.noActorSpecified"); + else if (result.count() == 1) + teleportTarget(ori, output, *result.begin()); + else + teleportTargets(ori, output, result); + } else { + auto actor = ori.getEntity(); + if (!actor) + output.trError("ll.cmd.tpdim.error.noActorSpecified"); + else + teleportTarget(ori, output, actor); + } + } + + static void setup(CommandRegistry* registry) { + registry->registerCommand( + "tpdim", "Teleport to Dimension", CommandPermissionLevel::GameMasters, + {(CommandFlagValue)0}, {(CommandFlagValue)0x80}); + registry->addEnum("DimensionType", + { + {"overworld", DimensionType::OverWorld}, + {"o", DimensionType::OverWorld}, + {"nether", DimensionType::Nether}, + {"n", DimensionType::Nether}, + {"end", DimensionType::TheEnd}, + {"e", DimensionType::TheEnd}, + }); + auto dimensionTypeParam = makeMandatory(&TeleportDimensionCommand::DimensionId, + "Dimension", "DimensionType"); + auto dimensionIdParam = makeMandatory((int TeleportDimensionCommand::*)&TeleportDimensionCommand::DimensionId, + "DimensionId"); + auto victimParam = makeMandatory(&TeleportDimensionCommand::Victim, "victim", + &TeleportDimensionCommand::Victim_isSet); + auto positionParam = makeOptional(&TeleportDimensionCommand::CommandPos, + "Position", &TeleportDimensionCommand::CommandPos_isSet); + + registry->registerOverload( + "tpdim", victimParam, dimensionTypeParam, positionParam); + registry->registerOverload( + "tpdim", victimParam, dimensionIdParam, positionParam); + // registry->registerOverload( + // "tpdim", dimensionTypeParam, positionParam); + registry->registerOverload( + "tpdim", dimensionIdParam, positionParam); + } +}; + +void LLListPluginsCommand(CommandOutput& output) { + auto plugins = LL::getAllPlugins(); + output.trSuccess("ll.cmd.listPlugin.overview", plugins.size()); + + std::ostringstream oss; + for (auto& [name, plugin] : plugins) { + string pluginName = name; + if (pluginName.find("§") == string::npos) + pluginName = "§b" + pluginName; + string desc = plugin->desc; + if (desc.find("§") == string::npos) + desc = "§7" + desc; + + auto fileName = UTF82String(std::filesystem::path(str2wstr(plugin->filePath)).filename().u8string()); + oss << fmt::format("- {} §a[v{}] §8({})\n {}\n", + pluginName, plugin->version.toString(), fileName, desc); + } + output.success(oss.str() + '\n'); + output.trAddMessage("ll.cmd.listPlugin.tip"); +} + +void LLPluginInfoCommand(CommandOutput& output, const string& pluginName) { + auto plugin = LL::getPlugin(pluginName); + if (plugin) { + std::map outs; + std::ostringstream oss; + auto fn = UTF82String(std::filesystem::path(str2wstr(plugin->filePath)).filename().u8string()); + string pluginType = plugin->type == Plugin::PluginType::ScriptPlugin ? "Script Plugin" : "DLL Plugin"; + + output.trAddMessage("ll.cmd.pluginInfo.title", pluginName); + + outs.emplace("Name", fmt::format("{} ({})", plugin->name, fn)); + outs.emplace("Description", plugin->desc); + outs.emplace("Version", "v" + plugin->version.toString(true)); + outs.emplace("Type", pluginType); + outs.emplace("File Path", plugin->filePath); + outs.merge(plugin->others); + size_t width = 10; + for (auto& [k, _] : outs) + width = std::max(width, k.length()); + for (auto& [k, v] : outs) { + if (k != "PluginType" && k != "PluginFilePath") + oss << "- §l" << std::setw(width) << std::left << k << "§r: " << v << std::endl; + } + auto text = oss.str(); + text.pop_back(); + output.success(text, {}); + } else { + output.trError("ll.cmd.pluginInfo.error.pluginNotFound", pluginName); + } +} + +void LLVersionCommand(CommandOutput& output) { + output.trSuccess("ll.cmd.version.msg", LL::getBdsVersion(), LL::getLoaderVersionString(), LL::getServerProtocolVersion()); +} + +void LLHelpCommand(CommandOutput& output) { + output.trSuccess("ll.cmd.help.msg"); +} + +void LLLoadPluginCommand(CommandOutput& output, const string& path) { + // if (!LL::isDebugMode()) + // return; + if (PluginManager::loadPlugin(path, true)) { + output.trSuccess("ll.cmd.loadPlugin.success", path); + } else { + output.trError("ll.cmd.loadPlugin.fail", path); + } +} + +void LLUnloadPluginCommand(CommandOutput& output, const string& pluginName) { + // if (!LL::isDebugMode()) + // return; + if (PluginManager::unloadPlugin(pluginName, true)) { + output.trSuccess("ll.cmd.unloadPlugin.success", pluginName); + } else { + output.trError("ll.cmd.unloadPlugin.fail", pluginName); + } +} + +void LLReloadPluginCommand(CommandOutput& output, const string& pluginName, bool reloadAll) { + // if (!LL::isDebugMode()) + // return; + if (!reloadAll) { + if (PluginManager::reloadPlugin(pluginName, true)) { + output.trSuccess("ll.cmd.reloadPlugin.success", pluginName); + } else { + output.trError("ll.cmd.reloadPlugin.fail", pluginName); + } + } else { + int cnt = PluginManager::reloadAllPlugins(true); + if (cnt > 0) { + output.trSuccess("ll.cmd.reloadAllPlugins.success", cnt); + } else { + output.trError("ll.cmd.reloadAllPlugins.fail"); + } + } +} + +class LLCommand : public Command { + + enum class Operation { + Version, + List, + Help, + Load, + Unload, + Reload + }; + + Operation operation; + bool hasUpgradeOption, hasPluginNameSet; + CommandRawText pluginNameToDoOperation; + +public: + void execute(CommandOrigin const& ori, CommandOutput& output) const override { + output.setLanguageCode(ori); + std::string pluginName = ""; + if (hasPluginNameSet) { + pluginName = pluginNameToDoOperation; + if (pluginName.size() > 1 && pluginName[0] == '"' && pluginName[pluginName.size() - 1] == '"' && pluginName[pluginName.size() - 2] != '\\') { + pluginName.erase(0, 1); + pluginName.pop_back(); + } + } + switch (operation) { + case Operation::Version: + LLVersionCommand(output); + break; + case Operation::List: + if (!hasPluginNameSet) + LLListPluginsCommand(output); + else + LLPluginInfoCommand(output, pluginName); + break; + case Operation::Load: + if (hasPluginNameSet) + LLLoadPluginCommand(output, pluginName); + else + output.trError("ll.cmd.error.noPathSpecified"); + break; + case Operation::Unload: + if (hasPluginNameSet) + LLUnloadPluginCommand(output, pluginName); + else + output.trError("ll.cmd.error.noNameSpecified"); + break; + case Operation::Reload: + if (hasPluginNameSet) + LLReloadPluginCommand(output, pluginName, false); + else + LLReloadPluginCommand(output, "", true); + break; + case Operation::Help: + LLHelpCommand(output); + break; + default: + break; + } + } + + static void setup(CommandRegistry* registry) { + // Register Cmd + registry->registerCommand("ll", "LiteLoaderBDS plugin operations", + CommandPermissionLevel::Console, {(CommandFlagValue)0}, {(CommandFlagValue)0x80}); + + // Register softenum + vector pluginList; + for (auto& [name, p] : LL::getAllPlugins()) { + pluginList.push_back(name); + } + registry->addSoftEnum("PluginName", pluginList); + + // ll version & help + registry->addEnum("Operation_Common", {{"version", Operation::Version}, + {"help", Operation::Help}}); + registry->registerOverload( + "ll", + makeMandatory(&LLCommand::operation, "Operation", "Operation_Common").addOptions((CommandParameterOption)1)); + + // ll load + registry->addEnum("Operation_FreeFilePath", { + {"load", Operation::Load}, + }); + registry->registerOverload( + "ll", + makeMandatory(&LLCommand::operation, "Operation", "Operation_FreeFilePath").addOptions((CommandParameterOption)1), + makeMandatory(&LLCommand::pluginNameToDoOperation, "pluginPath", nullptr, &LLCommand::hasPluginNameSet)); + + // ll unload + registry->addEnum("Operation_MustPluginName", { + {"unload", Operation::Unload}, + }); + registry->registerOverload( + "ll", + makeMandatory(&LLCommand::operation, "Operation", "Operation_MustPluginName").addOptions((CommandParameterOption)1), + makeMandatory((std::string LLCommand::*)&LLCommand::pluginNameToDoOperation, "pluginName", "PluginName", &LLCommand::hasPluginNameSet)); + + // ll list & reload + registry->addEnum("Operation_OptionalPluginName", { + {"list", Operation::List}, + {"plugins", Operation::List}, + {"reload", Operation::Reload}, + }); + registry->registerOverload( + "ll", + makeMandatory(&LLCommand::operation, "Operation", "Operation_OptionalPluginName").addOptions((CommandParameterOption)1), + makeOptional((std::string LLCommand::*)&LLCommand::pluginNameToDoOperation, "pluginName", "PluginName", &LLCommand::hasPluginNameSet)); + } +}; + +class VersionCommand : public Command { + +public: + void execute(CommandOrigin const& ori, CommandOutput& output) const override { + output.setLanguageCode(ori); +#ifdef DEBUG + Logger("CommandOrigin").warn(ori.serialize().toSNBT()); +#endif // DEBUG + LLVersionCommand(output); + } + + static void setup(CommandRegistry* registry) { + registry->registerCommand("version", "Get the version of this server", + CommandPermissionLevel::GameMasters, {(CommandFlagValue)0}, {(CommandFlagValue)0x80}); + registry->registerOverload("version"); + } +}; + +void RegisterCommands() { // Event::RegCmdEvent::subscribe([](Event::RegCmdEvent ev) { // Register commands // LLCommand::setup(ev.mCommandRegistry); // VersionCommand::setup(ev.mCommandRegistry); @@ -386,4 +386,4 @@ // } // return true; // }); -//} +} diff --git a/LiteLoader/Main/BuiltinUnlockCmd.cpp b/LiteLoader/Main/BuiltinUnlockCmd.cpp index 7fc6e45..51e65cf 100644 --- a/LiteLoader/Main/BuiltinUnlockCmd.cpp +++ b/LiteLoader/Main/BuiltinUnlockCmd.cpp @@ -1,35 +1,35 @@ -//#include "Global.h" -//#include
-//#include -//#include -///////////////////// Built in UnlockCmd /////////////////// -// -//bool isUnlockCmdEnabled = true; -// -//// ==> LiteLoader/Main/SimpleServerLogger.cpp -//void LogCommandRegistration(std::string const& name, char const* description, enum CommandPermissionLevel perm, short flag1, short flag2); -// -//TInstanceHook(void, "?registerCommand@CommandRegistry@@QEAAXAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@PEBDW4CommandPermissionLevel@@UCommandFlag@@3@Z", -// CommandRegistry, std::string const& name, char const* description, enum CommandPermissionLevel perm, short flag1, short flag2) { -// // For #643 -// if (name.find(' ') == std::string::npos) { // If no space inside -// // Check whether command is already exists before registering -// if (this->findCommand(name)) { -// // throw to prevent setup function, then this exception can be caught by event handler -// throw std::runtime_error("There is already a command named " + name); -// } -// } -// if (LL::globalConfig.enableUnlockCmd) { -// flag1 |= 0x80; -// } -// if (LL::globalConfig.debugMode) { -// LogCommandRegistration(name, description, perm, flag1, flag2); -// } -// return original(this, name, description, perm, flag1, flag2); -//} -// -//class CommandSelectorBase; -//class CommandOrigin; +#include "Global.h" +#include
+#include +#include +/////////////////// Built in UnlockCmd /////////////////// + +bool isUnlockCmdEnabled = true; + +// ==> LiteLoader/Main/SimpleServerLogger.cpp +void LogCommandRegistration(std::string const& name, char const* description, enum CommandPermissionLevel perm, short flag1, short flag2); + +TInstanceHook(void, "?registerCommand@CommandRegistry@@QEAAXAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@PEBDW4CommandPermissionLevel@@UCommandFlag@@3@Z", + CommandRegistry, std::string const& name, char const* description, enum CommandPermissionLevel perm, short flag1, short flag2) { + // For #643 + if (name.find(' ') == std::string::npos) { // If no space inside + // Check whether command is already exists before registering + if (this->findCommand(name)) { + // throw to prevent setup function, then this exception can be caught by event handler + throw std::runtime_error("There is already a command named " + name); + } + } + if (LL::globalConfig.enableUnlockCmd) { + flag1 |= 0x80; + } + if (LL::globalConfig.debugMode) { + LogCommandRegistration(name, description, perm, flag1, flag2); + } + return original(this, name, description, perm, flag1, flag2); +} + +class CommandSelectorBase; +class CommandOrigin; //TClasslessInstanceHook(bool, "?isExpansionAllowed@CommandSelectorBase@@AEBA_NAEBVCommandOrigin@@@Z", // CommandOrigin* a2) { // if (LL::globalConfig.enableUnlockCmd) { @@ -38,65 +38,65 @@ // } // return original(this, a2); //} -// -////#include -////#include -////#include -////#include -//// inline void tryChangeStringToRawText(CommandParameterData& data) -////{ -//// if (false /* config.xxxx*/ && data.tid.value == type_id().value) -//// { -//// data.tid = type_id(); -//// data.parser = CommandRegistry::getParseFn(); -//// } -////} -////// allowlist -//// TInstanceHook(CommandRegistry::Overload*, "??$_registerOverload@VAllowListCommand@@VCommandParameterData@@V2@@CommandRegistry@@AEAAPEAUOverload@0@PEBDVCommandVersion@@AEBVCommandParameterData@@2@Z", -//// CommandRegistry, char const* unk, class CommandVersion version, class CommandParameterData const& operationParam, class CommandParameterData& nameParam) -////{ -//// tryChangeStringToRawText(nameParam); -//// return original(this, unk, version, operationParam, nameParam); -//// } -////// op -//// TInstanceHook(CommandRegistry::Overload*, "??$_registerOverload@VOpCommand@@VCommandParameterData@@@CommandRegistry@@AEAAPEAUOverload@0@PEBDVCommandVersion@@AEBVCommandParameterData@@@Z", -//// CommandRegistry, char const* unk, class CommandVersion version, class CommandParameterData& nameParam) -////{ -//// tryChangeStringToRawText(nameParam); -//// return original(this, unk, version, nameParam); -//// } -////// deop -//// TInstanceHook(CommandRegistry::Overload*, "??$_registerOverload@VDeOpCommand@@VCommandParameterData@@@CommandRegistry@@AEAAPEAUOverload@0@PEBDVCommandVersion@@AEBVCommandParameterData@@@Z", -//// CommandRegistry, char const* unk, class CommandVersion version, class CommandParameterData& nameParam) -////{ -//// tryChangeStringToRawText(nameParam); -//// return original(this, unk, version, nameParam); -//// } -//// bool unlockNewExecute = true; -//// TClasslessInstanceHook(bool, "?isEnabled@FeatureToggles@@QEBA_NW4FeatureOptionID@@@Z", -//// int feature) -//// { -//// if (feature == 54 && unlockNewExecute) -//// return true; -//// return original(this, feature); -//// } -//// TClasslessInstanceHook(void, "?addSemanticConstraint@CommandRegistry@@AEAAXW4SemanticConstraint@@@Z", -//// enum SemanticConstraint) -////{ -//// return; -//// } -//TClasslessInstanceHook(void, "?addEnumValueConstraints@CommandRegistry@@QEAAXAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEBV?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@3@W4SemanticConstraint@@@Z", -// std::string const& enumName, std::vector const& enumValues, SemanticConstraint constraint) { -// if (!LL::globalConfig.enableUnlockCmd) -// return original(this, enumName, enumValues, constraint); -// if (constraint & SemanticConstraint::RequiresCheatsEnabled) { -// constraint = (SemanticConstraint)(constraint & (~SemanticConstraint::RequiresCheatsEnabled)); -// constraint = (SemanticConstraint)(constraint | SemanticConstraint::RequiresElevatedPermissions); + +//#include +//#include +//#include +//#include +// inline void tryChangeStringToRawText(CommandParameterData& data) +//{ +// if (false /* config.xxxx*/ && data.tid.value == type_id().value) +// { +// data.tid = type_id(); +// data.parser = CommandRegistry::getParseFn(); // } -// // if (constraint & SemanticConstraint::RequiresHostPermissions) -// //{ -// // constraint = (SemanticConstraint)(constraint & (~SemanticConstraint::RequiresHostPermissions)); -// // constraint = (SemanticConstraint)(constraint | SemanticConstraint::RequiresElevatedPermissions); -// // } -// return original(this, enumName, enumValues, constraint); -//} \ No newline at end of file +//} +//// allowlist +// TInstanceHook(CommandRegistry::Overload*, "??$_registerOverload@VAllowListCommand@@VCommandParameterData@@V2@@CommandRegistry@@AEAAPEAUOverload@0@PEBDVCommandVersion@@AEBVCommandParameterData@@2@Z", +// CommandRegistry, char const* unk, class CommandVersion version, class CommandParameterData const& operationParam, class CommandParameterData& nameParam) +//{ +// tryChangeStringToRawText(nameParam); +// return original(this, unk, version, operationParam, nameParam); +// } +//// op +// TInstanceHook(CommandRegistry::Overload*, "??$_registerOverload@VOpCommand@@VCommandParameterData@@@CommandRegistry@@AEAAPEAUOverload@0@PEBDVCommandVersion@@AEBVCommandParameterData@@@Z", +// CommandRegistry, char const* unk, class CommandVersion version, class CommandParameterData& nameParam) +//{ +// tryChangeStringToRawText(nameParam); +// return original(this, unk, version, nameParam); +// } +//// deop +// TInstanceHook(CommandRegistry::Overload*, "??$_registerOverload@VDeOpCommand@@VCommandParameterData@@@CommandRegistry@@AEAAPEAUOverload@0@PEBDVCommandVersion@@AEBVCommandParameterData@@@Z", +// CommandRegistry, char const* unk, class CommandVersion version, class CommandParameterData& nameParam) +//{ +// tryChangeStringToRawText(nameParam); +// return original(this, unk, version, nameParam); +// } +// bool unlockNewExecute = true; +// TClasslessInstanceHook(bool, "?isEnabled@FeatureToggles@@QEBA_NW4FeatureOptionID@@@Z", +// int feature) +// { +// if (feature == 54 && unlockNewExecute) +// return true; +// return original(this, feature); +// } +// TClasslessInstanceHook(void, "?addSemanticConstraint@CommandRegistry@@AEAAXW4SemanticConstraint@@@Z", +// enum SemanticConstraint) +//{ +// return; +// } +TClasslessInstanceHook(void, "?addEnumValueConstraints@CommandRegistry@@QEAAXAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEBV?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@3@W4SemanticConstraint@@@Z", + std::string const& enumName, std::vector const& enumValues, SemanticConstraint constraint) { + if (!LL::globalConfig.enableUnlockCmd) + return original(this, enumName, enumValues, constraint); + if (constraint & SemanticConstraint::RequiresCheatsEnabled) { + constraint = (SemanticConstraint)(constraint & (~SemanticConstraint::RequiresCheatsEnabled)); + constraint = (SemanticConstraint)(constraint | SemanticConstraint::RequiresElevatedPermissions); + } + // if (constraint & SemanticConstraint::RequiresHostPermissions) + //{ + // constraint = (SemanticConstraint)(constraint & (~SemanticConstraint::RequiresHostPermissions)); + // constraint = (SemanticConstraint)(constraint | SemanticConstraint::RequiresElevatedPermissions); + // } + return original(this, enumName, enumValues, constraint); +} \ No newline at end of file diff --git a/LiteLoader/Main/LiteLoader.cpp b/LiteLoader/Main/LiteLoader.cpp index 9f693f8..d72fc90 100644 --- a/LiteLoader/Main/LiteLoader.cpp +++ b/LiteLoader/Main/LiteLoader.cpp @@ -253,7 +253,7 @@ void LLMain() { LL::LoadLLConfig(); //Unzip packed Node Modules - UnzipNodeModules(); + //UnzipNodeModules(); //Decompress resource packs DecompressResourcePacks(); @@ -275,7 +275,7 @@ void LLMain() { FixPluginsLibDir(); // Check whether allowlist.json exists/is empty or not - FixAllowList(); + //FixAllowList(); // Init LL Logger Logger::setDefaultFile("logs/LiteLoader-latest.log", false); @@ -314,7 +314,7 @@ void LLMain() { LL::LoadMain(); // Register built-in commands - //RegisterCommands(); + RegisterCommands(); // Register simple server logger RegisterSimpleServerLogger(); diff --git a/LiteLoader/Main/Loader.cpp b/LiteLoader/Main/Loader.cpp index 1092d89..16a7730 100644 --- a/LiteLoader/Main/Loader.cpp +++ b/LiteLoader/Main/Loader.cpp @@ -1,4 +1,4 @@ -#include
+ #include
#include #include #include diff --git a/LiteLoader/Main/ModifyInfomation.cpp b/LiteLoader/Main/ModifyInfomation.cpp index c8b88d9..c3ca1b1 100644 --- a/LiteLoader/Main/ModifyInfomation.cpp +++ b/LiteLoader/Main/ModifyInfomation.cpp @@ -80,50 +80,50 @@ THook(void, "?log@BedrockLog@@YAXW4LogCategory@1@V?$bitset@$02@std@@W4LogRule@1@ return BedrockLog::log_va(a1, a2, a3, a4, a5, a6, a7, a8, va); } -//#include -//#include -//#include -//extern std::unordered_map resultOfOrigin; -//TClasslessInstanceHook(void*, "?send@CommandOutputSender@@UEAAXAEBVCommandOrigin@@AEBVCommandOutput@@@Z", -// class CommandOrigin const& origin, class CommandOutput const& output) { -// std::stringbuf tmpBuf; -// auto oldBuf = std::cout.rdbuf(); -// std::cout.rdbuf(&tmpBuf); -// auto rv = original(this, origin, output); -// std::cout.rdbuf(oldBuf); -// if (LL::isDebugMode() && LL::globalConfig.tickThreadId != std::this_thread::get_id()) { -// logger.warn("The thread executing the CommandOutputSender::send is not the \"MC_SERVER\" thread"); -// logger.warn("Output: {}", tmpBuf.str()); -// } -// -// auto it = resultOfOrigin.find(&origin); -// if (it != resultOfOrigin.end()) { -// try { -// // May crash for incomprehensible reasons -// it->second->assign(tmpBuf.str()); -// while (it->second->size() && (it->second->back() == '\n' || it->second->back() == '\r')) -// it->second->pop_back(); -// it->second = nullptr; -// resultOfOrigin.erase(it); -// return rv; -// } catch (...) { -// if (LL::isDebugMode()) { -// logger.warn("Output: {}", tmpBuf.str()); -// logger.warn("size of resultOfOrigin: {}", resultOfOrigin.size()); -// } -//#ifdef DEBUG -// __debugbreak(); -//#endif // DEBUG -// } -// } -// auto& log = output.getSuccessCount() > 0 ? serverLogger.info : serverLogger.error; -// std::istringstream iss(tmpBuf.str()); -// string line; -// while (getline(iss, line)) { -// if (LL::globalConfig.colorLog) -// log << ColorFormat::convertToConsole(line, false) << Logger::endl; -// else -// log << ColorFormat::removeColorCode(line) << Logger::endl; -// } -// return rv; -//} +#include +#include +#include +extern std::unordered_map resultOfOrigin; +TClasslessInstanceHook(void*, "?send@CommandOutputSender@@UEAAXAEBVCommandOrigin@@AEBVCommandOutput@@@Z", + class CommandOrigin const& origin, class CommandOutput const& output) { + std::stringbuf tmpBuf; + auto oldBuf = std::cout.rdbuf(); + std::cout.rdbuf(&tmpBuf); + auto rv = original(this, origin, output); + std::cout.rdbuf(oldBuf); + if (LL::isDebugMode() && LL::globalConfig.tickThreadId != std::this_thread::get_id()) { + logger.warn("The thread executing the CommandOutputSender::send is not the \"MC_SERVER\" thread"); + logger.warn("Output: {}", tmpBuf.str()); + } + + auto it = resultOfOrigin.find(&origin); + if (it != resultOfOrigin.end()) { + try { + // May crash for incomprehensible reasons + it->second->assign(tmpBuf.str()); + while (it->second->size() && (it->second->back() == '\n' || it->second->back() == '\r')) + it->second->pop_back(); + it->second = nullptr; + resultOfOrigin.erase(it); + return rv; + } catch (...) { + if (LL::isDebugMode()) { + logger.warn("Output: {}", tmpBuf.str()); + logger.warn("size of resultOfOrigin: {}", resultOfOrigin.size()); + } +#ifdef DEBUG + __debugbreak(); +#endif // DEBUG + } + } + auto& log = output.getSuccessCount() > 0 ? serverLogger.info : serverLogger.error; + std::istringstream iss(tmpBuf.str()); + string line; + while (getline(iss, line)) { + if (LL::globalConfig.colorLog) + log << ColorFormat::convertToConsole(line, false) << Logger::endl; + else + log << ColorFormat::removeColorCode(line) << Logger::endl; + } + return rv; +} diff --git a/LiteLoader/Main/SimpleServerLogger.cpp b/LiteLoader/Main/SimpleServerLogger.cpp index 1873c68..d4d062a 100644 --- a/LiteLoader/Main/SimpleServerLogger.cpp +++ b/LiteLoader/Main/SimpleServerLogger.cpp @@ -25,20 +25,20 @@ void RegisterSimpleServerLogger() { } #include -//TInstanceHook(void, "?setPermissions@Player@@QEAAXW4CommandPermissionLevel@@@Z", -// Player, CommandPermissionLevel perm) { -// if (LL::globalConfig.enableSimpleServerLogger) { -// static Logger logger("Permissions"); -// logger.info("<{}> {}({}) -> {}({})", -// getRealName(), magic_enum::enum_name(getCommandPermissionLevel()), (int)getCommandPermissionLevel(), magic_enum::enum_name(perm), (int)perm); -// } -// return original(this, perm); -//} +TInstanceHook(void, "?setPermissions@Player@@QEAAXW4CommandPermissionLevel@@@Z", + Player, CommandPermissionLevel perm) { + if (LL::globalConfig.enableSimpleServerLogger) { + static Logger logger("Permissions"); + logger.info("<{}> {}({}) -> {}({})", + getRealName(), magic_enum::enum_name(getCommandPermissionLevel()), (int)getCommandPermissionLevel(), magic_enum::enum_name(perm), (int)perm); + } + return original(this, perm); +} // ==> LiteLoader/Main/BuiltinUnlockCmd.cpp #include -//void LogCommandRegistration(std::string const& name, char const* description, enum CommandPermissionLevel perm, short flag1, short flag2) { -// static Logger logger("RegsterCommand"); -// logger.consoleLevel = logger.debug.level; -// logger.debug("{:<18} - {:<12} - {}", name, magic_enum::enum_name(perm), I18n::get(description)); -//} +void LogCommandRegistration(std::string const& name, char const* description, enum CommandPermissionLevel perm, short flag1, short flag2) { + static Logger logger("RegsterCommand"); + logger.consoleLevel = logger.debug.level; + logger.debug("{:<18} - {:<12} - {}", name, magic_enum::enum_name(perm), I18n::get(description)); +}