mirror of
https://github.com/quizhizhe/LiteLoaderBDS-1.16.40.git
synced 2025-06-05 03:43:40 +00:00
390 lines
16 KiB
C++
390 lines
16 KiB
C++
#include <filesystem>
|
|
#include <EventAPI.h>
|
|
#include <LLAPI.h>
|
|
#include <ServerAPI.h>
|
|
#include <RegCommandAPI.h>
|
|
#include <MC/CommandOrigin.hpp>
|
|
#include <MC/CommandOutput.hpp>
|
|
#include <MC/CommandPosition.hpp>
|
|
#include <MC/CommandRegistry.hpp>
|
|
#include <MC/Packet.hpp>
|
|
#include <MC/ServerPlayer.hpp>
|
|
#include <MC/VanillaDimensions.hpp>
|
|
#include <Main/Config.h>
|
|
#include <Main/PluginManager.h>
|
|
#include "../ScriptEngine/Main/Configs.h"
|
|
|
|
using namespace RegisterCommandHelper;
|
|
using namespace LL;
|
|
|
|
//static_assert(sizeof(CommandSelector<Player>) == 200);
|
|
|
|
class TeleportDimensionCommand : public Command {
|
|
|
|
enum class DimensionType {
|
|
OverWorld,
|
|
Nether,
|
|
TheEnd,
|
|
} DimensionId;
|
|
CommandSelector<Actor> 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<Actor>& 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>("DimensionType",
|
|
{
|
|
{"overworld", DimensionType::OverWorld},
|
|
{"o", DimensionType::OverWorld},
|
|
{"nether", DimensionType::Nether},
|
|
{"n", DimensionType::Nether},
|
|
{"end", DimensionType::TheEnd},
|
|
{"e", DimensionType::TheEnd},
|
|
});
|
|
auto dimensionTypeParam = makeMandatory<CommandParameterDataType::ENUM>(&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<TeleportDimensionCommand>(
|
|
"tpdim", victimParam, dimensionTypeParam, positionParam);
|
|
registry->registerOverload<TeleportDimensionCommand>(
|
|
"tpdim", victimParam, dimensionIdParam, positionParam);
|
|
// registry->registerOverload<TeleportDimensionCommand>(
|
|
// "tpdim", dimensionTypeParam, positionParam);
|
|
registry->registerOverload<TeleportDimensionCommand>(
|
|
"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<std::string, std::string> 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<string> pluginList;
|
|
for (auto& [name, p] : LL::getAllPlugins()) {
|
|
pluginList.push_back(name);
|
|
}
|
|
registry->addSoftEnum("PluginName", pluginList);
|
|
|
|
// ll version & help
|
|
registry->addEnum<Operation>("Operation_Common", {{"version", Operation::Version},
|
|
{"help", Operation::Help}});
|
|
registry->registerOverload<LLCommand>(
|
|
"ll",
|
|
makeMandatory<CommandParameterDataType::ENUM>(&LLCommand::operation, "Operation", "Operation_Common").addOptions((CommandParameterOption)1));
|
|
|
|
// ll load
|
|
registry->addEnum<Operation>("Operation_FreeFilePath", {
|
|
{"load", Operation::Load},
|
|
});
|
|
registry->registerOverload<LLCommand>(
|
|
"ll",
|
|
makeMandatory<CommandParameterDataType::ENUM>(&LLCommand::operation, "Operation", "Operation_FreeFilePath").addOptions((CommandParameterOption)1),
|
|
makeMandatory<CommandParameterDataType::NORMAL>(&LLCommand::pluginNameToDoOperation, "pluginPath", nullptr, &LLCommand::hasPluginNameSet));
|
|
|
|
// ll unload
|
|
registry->addEnum<Operation>("Operation_MustPluginName", {
|
|
{"unload", Operation::Unload},
|
|
});
|
|
registry->registerOverload<LLCommand>(
|
|
"ll",
|
|
makeMandatory<CommandParameterDataType::ENUM>(&LLCommand::operation, "Operation", "Operation_MustPluginName").addOptions((CommandParameterOption)1),
|
|
makeMandatory<CommandParameterDataType::SOFT_ENUM>((std::string LLCommand::*)&LLCommand::pluginNameToDoOperation, "pluginName", "PluginName", &LLCommand::hasPluginNameSet));
|
|
|
|
// ll list & reload
|
|
registry->addEnum<Operation>("Operation_OptionalPluginName", {
|
|
{"list", Operation::List},
|
|
{"plugins", Operation::List},
|
|
{"reload", Operation::Reload},
|
|
});
|
|
registry->registerOverload<LLCommand>(
|
|
"ll",
|
|
makeMandatory<CommandParameterDataType::ENUM>(&LLCommand::operation, "Operation", "Operation_OptionalPluginName").addOptions((CommandParameterOption)1),
|
|
makeOptional<CommandParameterDataType::SOFT_ENUM>((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<VersionCommand>("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;
|
|
});
|
|
}
|