#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() { Event::RegCmdEvent::subscribe([](Event::RegCmdEvent ev) { // Register commands LLCommand::setup(ev.mCommandRegistry); VersionCommand::setup(ev.mCommandRegistry); if (LL::globalConfig.enableTpdimCommand) { TeleportDimensionCommand::setup(ev.mCommandRegistry); } return true; }); }