From bcae58e4daf46cb72d2d9ce8d19d818c32763e34 Mon Sep 17 00:00:00 2001 From: Tsubasa6848 Date: Wed, 28 Feb 2024 03:32:04 +0800 Subject: [PATCH] feat: add forms --- src/Command.cpp | 19 +++++ src/Config.h | 6 ++ src/Entry.cpp | 53 +++--------- src/Forms.cpp | 177 +++++++++++++++++++++++++++++++++++++++++ src/Forms.h | 10 +++ src/Global.h | 7 +- src/Initialization.cpp | 20 +++++ src/InventoryCheck.cpp | 1 + src/Language.h | 38 +++++++++ 9 files changed, 289 insertions(+), 42 deletions(-) create mode 100644 src/Command.cpp create mode 100644 src/Config.h create mode 100644 src/Forms.cpp create mode 100644 src/Forms.h create mode 100644 src/Initialization.cpp create mode 100644 src/InventoryCheck.cpp create mode 100644 src/Language.h diff --git a/src/Command.cpp b/src/Command.cpp new file mode 100644 index 0000000..57f1ce0 --- /dev/null +++ b/src/Command.cpp @@ -0,0 +1,19 @@ +#include "Forms.h" +#include "Global.h" + +void RegisterCommand() { + auto& cmd = ll::command::CommandRegistrar::getInstance().getOrCreateCommand( + "inventorycheck", + tr("command.inventorycheck.desc"), + CommandPermissionLevel::GameDirectors + ); + ll::service::getCommandRegistry()->registerAlias("inventorycheck", "ic"); + cmd.overload().execute<[&](CommandOrigin const& origin, CommandOutput& output) { + auto entity = (GMLIB_Actor*)origin.getEntity(); + if (entity && entity->isPlayer()) { + auto pl = (Player*)entity; + return mainForm(*pl); + } + return output.error(tr("command.error.console")); + }>(); +} \ No newline at end of file diff --git a/src/Config.h b/src/Config.h new file mode 100644 index 0000000..d70b8db --- /dev/null +++ b/src/Config.h @@ -0,0 +1,6 @@ +#pragma once +#include "Global.h" + +std::string defaultConfig = R"({ + "language": "en_US" +})"; \ No newline at end of file diff --git a/src/Entry.cpp b/src/Entry.cpp index b618983..ea7402b 100644 --- a/src/Entry.cpp +++ b/src/Entry.cpp @@ -1,13 +1,6 @@ #include "Entry.h" #include "Global.h" -#include -#include -#include -#include -#include -#include -#include -#include + ll::Logger logger(PLUGIN_NAME); namespace InventoryCheck { @@ -17,47 +10,22 @@ namespace { std::unique_ptr> selfPluginInstance; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -auto disable(ll::plugin::NativePlugin& /*self*/) -> bool { - logger.info("disabling..."); - - // Your code here. - - logger.info("disabled"); - - return true; -} +auto disable(ll::plugin::NativePlugin& /*self*/) -> bool { return true; } auto enable(ll::plugin::NativePlugin& /*self*/) -> bool { - logger.info("enabling..."); - - logger.info("enabled"); - + RegisterCommand(); return true; } auto load(ll::plugin::NativePlugin& self) -> bool { - logger.info("loading..."); - selfPluginInstance = std::make_unique>(self); - - // Your code here. - - logger.info("loaded"); - + GMLIB::Server::UserCache::enableUserCache(); + initPlugin(); return true; } auto unload(ll::plugin::NativePlugin& self) -> bool { - auto& logger = self.getLogger(); - - logger.info("unloading..."); - selfPluginInstance.reset(); - - // Your code here. - - logger.info("unloaded"); - return true; } @@ -67,7 +35,6 @@ auto getSelfPluginInstance() -> ll::plugin::NativePlugin& { if (!selfPluginInstance) { throw std::runtime_error("selfPluginInstance is null"); } - return *selfPluginInstance; } @@ -77,7 +44,11 @@ extern "C" { _declspec(dllexport) auto ll_plugin_disable(ll::plugin::NativePlugin& self) -> bool { return InventoryCheck::disable(self); } -_declspec(dllexport) auto ll_plugin_enable(ll::plugin::NativePlugin& self) -> bool { return InventoryCheck::enable(self); } -_declspec(dllexport) auto ll_plugin_load(ll::plugin::NativePlugin& self) -> bool { return InventoryCheck::load(self); } -_declspec(dllexport) auto ll_plugin_unload(ll::plugin::NativePlugin& self) -> bool { return InventoryCheck::unload(self); } +_declspec(dllexport) auto ll_plugin_enable(ll::plugin::NativePlugin& self) -> bool { + return InventoryCheck::enable(self); +} +_declspec(dllexport) auto ll_plugin_load(ll::plugin::NativePlugin& self) -> bool { return InventoryCheck::load(self); } +_declspec(dllexport) auto ll_plugin_unload(ll::plugin::NativePlugin& self) -> bool { + return InventoryCheck::unload(self); +} } diff --git a/src/Forms.cpp b/src/Forms.cpp new file mode 100644 index 0000000..739525c --- /dev/null +++ b/src/Forms.cpp @@ -0,0 +1,177 @@ +#include "Forms.h" + +void mainForm(Player& pl) { + auto fm = ll::form::SimpleForm(tr("form.main.title"), tr("form.main.content")); + fm.appendButton(tr("form.main.checkOnline"), [](Player& pl) { return checkOnlineForm(pl); }); + fm.appendButton(tr("form.main.checkAll"), [](Player& pl) { return checkAllForm(pl); }); + fm.appendButton(tr("form.main.searchPlayer"), [](Player& pl) { return searchPlayerForm(pl); }); + fm.appendButton(tr("form.main.resumeInventory"), [](Player& pl) { return; }); + fm.sendTo(pl); +} + +void checkOnlineForm(Player& pl) { + auto fm = ll::form::SimpleForm(tr("form.checkList.title"), tr("form.checkList.content")); + std::unordered_map onlineList; + GMLIB_Level::getLevel()->forEachPlayer([&onlineList](Player& pl) -> bool { + if (!pl.isSimulated()) { + onlineList[pl.getUuid()] = pl.getRealName(); + } + return true; + }); + for (auto& [uuid, name] : onlineList) { + fm.appendButton(name, [uuid](Player& pl) { return checkPlayerForm(pl, uuid); }); + } + fm.sendTo(pl, [](Player& pl, int index) { + if (index == -1) { + return mainForm(pl); + } + }); +} + +std::string getNameFormUuid(mce::UUID& uuid) { + auto player = GMLIB_Level::getLevel()->getPlayer(uuid); + std::string name; + if (player) { + name = player->getRealName(); + } else { + auto strUuid = uuid.asString(); + auto cachename = GMLIB::Server::UserCache::getNameByUuid(strUuid); + if (cachename.has_value()) { + name = cachename.value(); + } else { + name = strUuid; + } + } + return name; +} + +std::unordered_map generateUuidMap() { + auto allUuids = GMLIB_Player::getAllUuids(); + std::unordered_map allList; + for (auto& strUuid : allUuids) { + auto uuid = mce::UUID::fromString(strUuid); + auto name = getNameFormUuid(uuid); + allList[uuid] = name; + } + return std::move(allList); +} + +void checkAllForm(Player& pl) { + auto fm = ll::form::SimpleForm(tr("form.checkList.title"), tr("form.checkList.content")); + auto allList = generateUuidMap(); + for (auto& [uuid, name] : allList) { + fm.appendButton(name, [uuid](Player& pl) { return checkPlayerForm(pl, uuid); }); + } + fm.sendTo(pl, [](Player& pl, int index) { + if (index == -1) { + return mainForm(pl); + } + }); +} + +void searchPlayerForm(Player& pl) { + auto fm = ll::form::CustomForm(tr("form.searchPlayer.title")); + fm.appendLabel(tr("form.searchPlayer.description")); + fm.appendInput("name", tr("form.searchPlayer.input"), tr("form.searchPlayer.inputName")); + fm.appendDropdown( + "mode", + tr("form.searchForm.searchMode"), + {tr("form.searchPlayer.fuzzySearch"), tr("form.searchPlayer.preciseSearch")}, + 0 + ); + fm.sendTo(pl, [](Player& pl, const ll::form::CustomFormResult& result) { + if (result.empty()) { + return mainForm(pl); + } + std::string inputName; + if (std::holds_alternative(result.at("name"))) { + inputName = std::get(result.at("name")); + } + auto searchMode = std::get(result.at("mode")); + if (inputName.empty()) { + return invalidInputForm(pl); + } + auto allList = generateUuidMap(); + if (searchMode == tr("form.searchPlayer.preciseSearch")) { + for (auto& [uuid, name] : allList) { + if (name == inputName) { + return checkPlayerForm(pl, uuid); + } + } + } else { + std::unordered_map resultList; + for (auto& [uuid, name] : allList) { + if (name.find(inputName) != std::string::npos) { + resultList[uuid] = name; + } + } + if (!resultList.empty()) { + return searchResultForm(pl, resultList); + } + } + return searchNotFoundForm(pl, inputName); + }); +} + +void searchResultForm(Player& pl, std::unordered_map resultList) { + auto fm = ll::form::SimpleForm(tr("form.checkList.title"), tr("form.checkList.content")); + for (auto& [uuid, name] : resultList) { + fm.appendButton(name, [&uuid](Player& pl) { checkPlayerForm(pl, uuid); }); + } + fm.sendTo(pl, [](Player& pl, int index) { + if (index == -1) { + return searchPlayerForm(pl); + } + }); +} + +void searchNotFoundForm(Player& pl, std::string& name) { + auto fm = ll::form::ModalForm( + tr("form.notFound.title"), + tr("form.notFound.content", {name}), + tr("form.notFound.returnSearch"), + tr("form.returnMainForm") + ); + fm.sendTo(pl, [](Player& pl, ll::form::ModalForm::SelectedButton result) { + if (result == ll::form::ModalForm::SelectedButton::Upper) { + return searchPlayerForm(pl); + } + return mainForm(pl); + }); +} + +void checkPlayerForm(Player& pl, mce::UUID uuid) { + std::string name = getNameFormUuid(uuid); + auto fm = ll::form::SimpleForm(tr("form.checkPlayer.title"), tr("form.checkPlayer.content", {name})); + fm.appendButton(tr("form.checkPlayer.copyInventory"), [uuid](Player& pl) { + auto nbt = GMLIB_Player::getPlayerNbt(uuid); + auto self = (GMLIB_Player*)(&pl); + self->setPlayerNbtTags(pl.getUuid(), *nbt, {"Offhand", "Inventory", "Armor", "EnderChestInventory"}); + }); + fm.appendButton(tr("form.checkPlayer.writeInventory"), [uuid](Player& pl) { + // + }); + fm.appendButton(tr("form.checkPlayer.deleteData"), [uuid](Player& pl) { + // + }); + fm.sendTo(pl, [](Player& pl, int index) { + if (index == -1) { + return mainForm(pl); + } + }); +} + +void invalidInputForm(Player& pl) { + auto fm = ll::form::ModalForm( + tr("form.invalidInput.title"), + tr("form.invalidInput.content"), + tr("form.invalidInput.returnSearch"), + tr("form.returnMainForm") + ); + fm.sendTo(pl, [](Player& pl, ll::form::ModalForm::SelectedButton result) { + if (result == ll::form::ModalForm::SelectedButton::Upper) { + return searchPlayerForm(pl); + } + return mainForm(pl); + }); +} \ No newline at end of file diff --git a/src/Forms.h b/src/Forms.h new file mode 100644 index 0000000..e8e44d8 --- /dev/null +++ b/src/Forms.h @@ -0,0 +1,10 @@ +#include "Global.h" + +extern void mainForm(Player& pl) ; +extern void checkOnlineForm(Player& pl); +extern void checkAllForm(Player& pl) ; +extern void searchPlayerForm(Player& pl); +extern void searchResultForm(Player& pl, std::unordered_map resultList); +extern void searchNotFoundForm(Player& pl, std::string& name) ; +extern void checkPlayerForm(Player& pl, mce::UUID uuid); +extern void invalidInputForm(Player& pl); \ No newline at end of file diff --git a/src/Global.h b/src/Global.h index 0a3e7cd..af1e947 100644 --- a/src/Global.h +++ b/src/Global.h @@ -3,4 +3,9 @@ #define PLUGIN_NAME "InventoryCheck" -extern ll::Logger logger; \ No newline at end of file +extern ll::Logger logger; + +extern std::string tr(std::string key, std::vector data = {}); + +extern void initPlugin(); +extern void RegisterCommand(); \ No newline at end of file diff --git a/src/Initialization.cpp b/src/Initialization.cpp new file mode 100644 index 0000000..005f39e --- /dev/null +++ b/src/Initialization.cpp @@ -0,0 +1,20 @@ +#include "Config.h" +#include "Global.h" +#include "Language.h" + +GMLIB::Files::JsonConfig* Config = nullptr; +GMLIB::Files::I18n::LangI18n* Language = nullptr; + +void initPlugin() { + Config = new GMLIB::Files::JsonConfig("./plugins/InventoryCheck/config/config.json", defaultConfig); + Config->init(); + std::string langPath = "./plugins/InventoryCheck/language/"; + std::string languageCode = Config->getValue({"language"}, "en_US"); + Language = new GMLIB::Files::I18n::LangI18n(langPath, languageCode); + Language->updateOrCreateLanguage("en_US", defaultLanguage_en_US); + Language->updateOrCreateLanguage("zh_CN", defaultLanguage_zh_CN); + Language->loadAllLanguages(); + Language->chooseLanguage(languageCode); +} + +std::string tr(std::string key, std::vector data) { return Language->translate(key, data); } diff --git a/src/InventoryCheck.cpp b/src/InventoryCheck.cpp new file mode 100644 index 0000000..61e8f7a --- /dev/null +++ b/src/InventoryCheck.cpp @@ -0,0 +1 @@ +#include "Global.h" \ No newline at end of file diff --git a/src/Language.h b/src/Language.h new file mode 100644 index 0000000..5bc43d3 --- /dev/null +++ b/src/Language.h @@ -0,0 +1,38 @@ +#pragma once +#include "Global.h" + +std::string defaultLanguage_en_US = R"( + +)"; + +std::string defaultLanguage_zh_CN = R"( + form.main.title=查询玩家背包 + form.main.content=请选择查询模式 + form.main.checkOnline=查询在线玩家 + form.main.checkAll=查询全部玩家 + form.main.searchPlayer=搜索玩家 + form.main.resumeInventory=恢复查包前背包 + form.checkList.title=玩家列表 + form.checkList.content=请选择你要查询的玩家 + form.searchPlayer.title=搜索玩家 + form.searchPlayer.description=请输入玩家名进行搜索 + form.searchPlayer.input=玩家名 + form.searchPlayer.inputName=请输入玩家名称信息 + form.searchForm.searchMode=搜索模式 + form.searchPlayer.fuzzySearch=模糊搜索 + form.searchPlayer.preciseSearch=精确搜索 + form.notFound.title=未找到匹配结果 + form.notFound.content=没有找到和 %s 匹配的玩家数据 + form.notFound.returnSearch=返回搜索菜单 + form.returnMainForm=返回主菜单 + form.checkPlayer.title=查询玩家背包 + form.checkPlayer.content=你正在查询玩家 %s 的背包\n请选择操作模式 + form.checkPlayer.copyInventory=将玩家背包复制到自身背包 + form.checkPlayer.writeInventory=用自身背包覆盖玩家背包 + form.checkPlayer.deleteData=删除玩家全部数据(不仅仅是背包) + form.invalidInput.title=非法的输入 + form.invalidInput.content=输入的玩家名不能为空! + form.invalidInput.returnSearch=重新搜索 + command.error.console=该命令只能由玩家执行 + command.inventorycheck.desc=查询玩家背包 +)";