//#include "AddonsHelper.h" //#include
//#include //#include //#include //#include //#include //#include //#include //#include //#include //#include //#include //#include //#include //#include
//#include //#include //#include //#include //#include //#include //#include //using namespace std; //using namespace RegisterCommandHelper; // //Logger addonLogger("AddonHelper"); //std::vector addons; // //bool AutoInstallAddons(string path); // //// Helper //std::string GetAddonJsonFile(Addon::Type type) { // string addonListFile = Level::getCurrentLevelPath(); // switch (type) { // case Addon::Type::BehaviorPack: // return addonListFile + "/world_behavior_packs.json"; // break; // case Addon::Type::ResourcePack: // return addonListFile + "/world_resource_packs.json"; // break; // default: // break; // } // return ""; //} // //inline bool isManifestFile(std::string const& filename) { // return filename == "manifest.json" || filename == "pack_manifest.json"; //} // //#include //inline std::string FixMojangJson(std::string const& content) { // Json::Value value; // JsonHelpers::parseJson(content, value); // return JsonHelpers::serialize(value); //} // //std::optional parseAddonFromPath(std::filesystem::path addonPath) { // try { // auto manifestPath = addonPath; // manifestPath.append("manifest.json"); // if (!filesystem::exists(manifestPath)) { // manifestPath = addonPath; // manifestPath.append("pack_manifest.json"); // } // auto manifestFile = ReadAllFile(UTF82String(manifestPath.u8string())); // if (!manifestFile || manifestFile->empty()) // throw std::exception("manifest.json not found!"); // std::string content = FixMojangJson(*manifestFile); // // auto manifest = nlohmann::json::parse(content, nullptr, true, true); // auto header = manifest["header"]; // auto uuid = header["uuid"]; // Addon addon; // addon.name = header["name"]; // addon.description = header["description"]; // addon.uuid = uuid; // addon.directory = UTF82String(addonPath.u8string()); // // auto ver = header["version"]; // addon.version = LL::Version(ver[0], ver[1], ver[2]); // // string type = manifest["modules"][0]["type"]; // if (type == "resources") // addon.type = Addon::Type::ResourcePack; // else if (type == "data" || type == "script") // addon.type = Addon::Type::BehaviorPack; // else // throw std::exception("Unknown type of addon pack!"); // // return addon; // } catch (const seh_exception& e) { // addonLogger.error("Uncaught SEH Exception Detected!"); // addonLogger.error("In " __FUNCTION__ " " + UTF82String(addonPath.u8string())); // addonLogger.error("Error: Code[{}] {}", e.code(), TextEncoding::toUTF8(e.what())); // } catch (const std::exception& e) { // addonLogger.error("Uncaught C++ Exception Detected!"); // addonLogger.error("In " __FUNCTION__ " " + UTF82String(addonPath.u8string())); // addonLogger.error("Error: Code[{}] {}", -1, TextEncoding::toUTF8(e.what())); // } catch (...) { // addonLogger.error("Uncaught Exception Detected!"); // addonLogger.error("In " __FUNCTION__ " " + UTF82String(addonPath.u8string())); // } // return std::nullopt; //} // //bool RemoveAddonFromList(Addon& addon) { // auto jsonFile = GetAddonJsonFile(addon.type); // if (!filesystem::exists(str2wstr(jsonFile))) { // addonLogger.error(tr("ll.addonsHelper.error.addonConfigNotFound")); // return false; // } // // auto addonJsonContent = ReadAllFile(jsonFile); // if (!addonJsonContent || addonJsonContent->empty()) { // addonLogger.error(tr("ll.addonsHelper.error.addonConfigNotFound")); // return false; // } // auto addonJson = fifo_json::parse(*addonJsonContent, nullptr, true, true); // int id = 0; // for (auto item : addonJson) { // if (item["pack_id"] == addon.uuid) { // addonJson.erase(id); // bool res = WriteAllFile(jsonFile, addonJson.dump(4)); // if (!res) { // addonLogger.error(tr("ll.addonsHelper.removeAddonFromList.fail", addon.getPrintName())); // return false; // } // addonLogger.info(tr("ll.addonsHelper.removeAddonFromList.success", addon.getPrintName())); // return true; // } // ++id; // } // addonLogger.error(tr("ll.addonsHelper.error.addonNotFound", addon.getPrintName())); // return false; //} // //bool AddAddonToList(Addon& addon) { // string addonListFile = GetAddonJsonFile(addon.type); // if (!filesystem::exists(str2wstr(addonListFile))) { // ofstream fout(addonListFile); // fout << "[]" << flush; // } // // try { // // bool exists = false; // auto addonList = nlohmann::json::parse(*ReadAllFile(addonListFile), nullptr, false, true); // // Auto fix Addon List File // if (!addonList.is_array()) { // auto backupPath = UTF82String(filesystem::path(str2wstr(addonListFile)).stem().u8string()) + "_error.json"; // addonLogger.error(tr("ll.addonsHelper.addAddonToList.invalidList", addonListFile, backupPath)); // std::error_code ec; // std::filesystem::rename(str2wstr(addonListFile), filesystem::path(addonListFile).remove_filename().append(str2wstr(backupPath)), ec); // addonList = "[]"_json; // } // for (auto& addonData : addonList) { // if (addonData["pack_id"] == addon.uuid) { // addonData["version"] = {addon.version.major, addon.version.minor, addon.version.revision}; // exists = true; // break; // } // } // if (!exists) { // auto newAddonData = nlohmann::json::object(); // newAddonData["pack_id"] = addon.uuid; // newAddonData["version"] = {addon.version.major, addon.version.minor, addon.version.revision}; // addonList.push_back(newAddonData); // } // bool res = WriteAllFile(addonListFile, addonList.dump(4)); // if (!res) // throw std::exception("Fail to write data back to addon list file!"); // addonLogger.info(tr("ll.addonsHelper.addAddonToList.success", addon.getPrintName())); // return true; // } catch (const std::exception& e) { // addonLogger.error(tr("ll.addonsHelper.addAddonToList.fail", addon.getPrintName(), addonListFile)); // addonLogger.error(tr("ll.addonsHelper.displayError", TextEncoding::toUTF8(e.what()))); // addonLogger.error(tr("ll.addonsHelper.error.installationAborted")); // return false; // } //} //bool InstallAddonToLevel(std::string addonDir, std::string addonName) { // auto addon = parseAddonFromPath(str2wstr(addonDir)); // if (!addon.has_value()) // return false; // std::string subPath; // if (addon->type == Addon::Type::ResourcePack) // subPath = "/resource_packs"; // else if (addon->type == Addon::Type::BehaviorPack) // subPath = "/behavior_packs"; // // // // copy files // string levelPath = Level::getCurrentLevelPath(); // string toPath = levelPath + subPath + "/" + addonName; // // // Avoid duplicate names or update addon if same uuid // while (filesystem::exists(str2wstr(toPath))) { // auto tmp = parseAddonFromPath(str2wstr(toPath)); // if (tmp.has_value() && tmp->uuid != addon->uuid) { // toPath += "_"; // } else { // std::error_code ec; // filesystem::remove_all(str2wstr(toPath), ec); // break; // } // } // std::error_code ec; // filesystem::create_directories(str2wstr(toPath), ec); // filesystem::copy(str2wstr(addonDir), str2wstr(toPath), filesystem::copy_options::recursive, ec); // // // add addon to list file // return AddAddonToList(*addon); //} // //void FindManifest(vector& result, const string& path) { // filesystem::directory_iterator ent(str2wstr(path)); // // bool foundManifest = false; // for (auto& file : ent) { // auto path = file.path(); // if (isManifestFile(UTF82String(path.filename().u8string()))) { // result.push_back(UTF82String(filesystem::canonical(path).parent_path().u8string())); // foundManifest = true; // break; // } // } // if (!foundManifest) { // // No manifest file // if (!AutoInstallAddons(path)) { // filesystem::directory_iterator ent2(str2wstr(path)); // for (auto& file : ent2) // if (file.is_directory()) // FindManifest(result, UTF82String(file.path().u8string())); // } // } // return; //} // //std::string Addon::getPrintName() const { // if (LL::globalConfig.colorLog) // return ColorFormat::convertToConsole(std::string(name)); // else // return ColorFormat::removeColorCode(std::string(name)); //} // //bool AddonsManager::install(std::string packPath) { // try { // if (!filesystem::exists(str2wstr(packPath))) { // addonLogger.error(tr("ll.addonsHelper.error.addonFileNotFound", packPath)); // return false; // } // if (VALID_ADDON_FILE_EXTENSION.find(UTF82String(filesystem::path(str2wstr(packPath)).extension().u8string())) == VALID_ADDON_FILE_EXTENSION.end()) { // addonLogger.error(tr("ll.addonsHelper.error.unsupportedFileType")); // return false; // } // // string name = UTF82String(filesystem::path(str2wstr(packPath)).filename().u8string()); // addonLogger.warn(tr("ll.addonsHelper.install.installing", name)); // // std::error_code ec; // if (EndsWith(packPath, ".mcpack")) { // string newPath = packPath; // ReplaceStr(newPath, ".mcpack", ".zip"); // filesystem::rename(str2wstr(packPath), str2wstr(newPath), ec); // packPath = newPath; // } // if (EndsWith(packPath, ".mcaddon")) { // string newPath = packPath; // ReplaceStr(newPath, ".mcaddon", ".zip"); // filesystem::rename(str2wstr(packPath), str2wstr(newPath), ec); // packPath = newPath; // } // // name = UTF82String(filesystem::path(str2wstr(packPath)).filename().u8string()); // // // filesystem::remove_all(ADDON_INSTALL_TEMP_DIR + name + "/", ec); //? // // filesystem::create_directories(ADDON_INSTALL_TEMP_DIR + name + "/", ec); // // auto res = NewProcessSync(fmt::format("{} x \"{}\" -o{} -aoa", ZIP_PROGRAM_PATH, packPath, "\"" ADDON_INSTALL_TEMP_DIR + name + "/\""), ADDON_INSTALL_MAX_WAIT); // if (res.first != 0) { // addonLogger.error(tr("ll.addonsHelper.install.error.failToUncompress.msg", name)); // addonLogger.error(tr("ll.addonsHelper.install.error.failToUncompress.exitCode"), res.first); // addonLogger.error(tr("ll.addonsHelper.install.error.failToUncompress.programOutput"), res.second); // addonLogger.error(tr("ll.addonsHelper.error.installationAborted")); // filesystem::remove_all(ADDON_INSTALL_TEMP_DIR + name + "/", ec); // return false; // } // // vector paths; // FindManifest(paths, ADDON_INSTALL_TEMP_DIR + name + "/"); // // for (auto& dir : paths) { // string addonName = UTF82String(filesystem::path(str2wstr(dir)).filename().u8string()); // if (addonName.empty() || addonName == "Temp") // addonName = UTF82String(filesystem::path(str2wstr(packPath)).stem().u8string()); // if (!InstallAddonToLevel(dir, addonName)) // throw std::exception("Error in Install Addon To Level "); // } // // filesystem::remove_all(ADDON_INSTALL_TEMP_DIR + name + "/", ec); // filesystem::remove_all(str2wstr(packPath), ec); // return true; // } catch (const seh_exception& e) { // addonLogger.error("Uncaught SEH Exception Detected!"); // addonLogger.error("In " __FUNCTION__); // addonLogger.error("Error: Code[{}] {}", e.code(), TextEncoding::toUTF8(e.what())); // } catch (const std::exception& e) { // addonLogger.error("Uncaught C++ Exception Detected!"); // addonLogger.error("In " __FUNCTION__); // addonLogger.error("Error: Code[{}] {}", -1, TextEncoding::toUTF8(e.what())); // } catch (...) { // addonLogger.error("Uncaught Exception Detected!"); // addonLogger.error("In " __FUNCTION__); // } // return false; //} // //bool AddonsManager::disable(std::string nameOrUuid) { // try { // auto addon = findAddon(nameOrUuid, true); // if (!addon) // return false; // if (RemoveAddonFromList(*addon)) { // addon->enable = false; // return true; // } // // } catch (...) {} // return false; //} // //bool AddonsManager::enable(std::string nameOrUuid) { // try { // auto addon = findAddon(nameOrUuid, true); // if (!addon) // return false; // if (AddAddonToList(*addon)) { // addon->enable = true; // return true; // } // // } catch (...) {} // return false; //} // //bool AddonsManager::uninstall(std::string nameOrUuid) { // try { // auto addon = findAddon(nameOrUuid, true); // if (!addon) { // addonLogger.error(tr("ll.addonsHelper.error.addonNotFound")); // return false; // } // RemoveAddonFromList(*addon); // std::error_code ec; // filesystem::remove_all(str2wstr(addon->directory), ec); // for (auto i = addons.begin(); i != addons.end(); ++i) // if (i->uuid == addon->uuid) { // addons.erase(i); // break; // } // addonLogger.info(tr("ll.addonsHelper.uninstall.success", addon->getPrintName())); // } catch (...) {} // return false; //} // //std::vector AddonsManager::getAllAddons() { // std::vector res; // for (auto& addon : addons) // res.push_back(&addon); // return res; //} // //Addon* AddonsManager::findAddon(std::string nameOrUuid, bool fuzzy) { // Addon* possible = nullptr; // bool multiMatch = false; // for (auto& addon : addons) { // if (addon.uuid == nameOrUuid) // return &addon; // std::string addonName = addon.name; // std::string targetName = nameOrUuid; // if (ColorFormat::removeColorCode(addonName) == ColorFormat::removeColorCode(targetName)) // return &addon; // if (!fuzzy) // continue; // // Simple fuzzy matching // std::transform(addonName.begin(), addonName.end(), addonName.begin(), ::tolower); // std::transform(targetName.begin(), targetName.end(), targetName.begin(), ::tolower); // if (StartsWith(addonName, targetName)) { // if (possible) // multiMatch = true; // else // possible = &addon; // } // } // if (multiMatch) // return nullptr; // else // return possible; //} // //void ListAllAddons(CommandOutput& output) { // if (addons.empty()) { // output.trSuccess("ll.addonsHelper.error.noAddonInstalled"); // return; // } // // output.trSuccess("ll.addonsHelper.cmd.output.list.overview", addons.size()); // for (auto index = 0; index < addons.size(); ++index) { // auto& addon = addons[index]; // string addonName = addon.name; // if (addonName.find("§") == string::npos) // addonName = "§b" + addonName; // string desc = addon.description; // if (desc.find("§") == string::npos) // desc = "§7" + desc; // // std::string addonType = (addon.type == Addon::Type::ResourcePack ? "ResourcePack" : "BehaviorPack"); // if (addon.enable) { // output.success(fmt::format("§e{:>2}§r: {} §a[v{}] §8({})", index + 1, addonName, addon.version.toString(), addonType)); // output.success(fmt::format(" {}", desc)); // } else { // output.success(fmt::format("§e{:>2}§r: §8{} [v{}] ({})", index + 1, ColorFormat::removeColorCode(addonName), addon.version.toString(), addonType)); // output.success(fmt::format(" §8Disabled")); // } // } //} // //void ShowAddon(CommandOutput& output, Addon& addon) { // std::ostringstream oss; // oss << "Addon <" << addon.name << "§r>" << (addon.enable ? " §aEnabled" : " §cDisabled") << "\n\n"; // oss << "- §aName§r: " << addon.name << "\n"; // oss << "- §aUUID§r: " << addon.uuid << "\n"; // oss << "- §aDescription§r: " << addon.description << "\n"; // oss << "- §aVersion§r: v" << addon.version.toString(true) << "\n"; // oss << "- §aType§r: " << magic_enum::enum_name(addon.type) << "\n"; // oss << "- §aDirectory§r: " << addon.directory << "\n"; // output.success(oss.str()); //} // //class AddonsCommand : public Command { // enum class Operation { // List, // Install, // Uninstall, // Enable, // Disable // }; // // Operation operation = static_cast(-1); // std::string target; // int index = -1; // bool target_isSet = false; // bool index_isSet = false; // // inline Addon* getSelectedAddon(CommandOutput& output) const { // Addon* addon = nullptr; // if (target_isSet) { // auto addon = AddonsManager::findAddon(target, true); // if (addon) { // return addon; // } else { // output.trError("ll.addonsHelper.error.addonNotfound", target); // } // } else { // auto addons = AddonsManager::getAllAddons(); // if (index - 1 >= 0 && index - 1 < static_cast(addons.size())) // return addons[index - 1]; // else // output.trError("ll.addonsHelper.error.outOfRange", index); // } // return nullptr; // } // //public: // void execute(CommandOrigin const& ori, CommandOutput& output) const override { // output.setLanguageCode(ori); // switch (operation) { // case Operation::List: // if (target_isSet || index_isSet) { // if (auto addon = getSelectedAddon(output)) // ShowAddon(output, *addon); // } else // ListAllAddons(output); // break; // case Operation::Install: // if (AddonsManager::install(target)) // filesystem::remove_all(ADDON_INSTALL_TEMP_DIR); // output.success(); // break; // case Operation::Uninstall: { // auto addon = getSelectedAddon(output); // if (addon && AddonsManager::uninstall(addon->uuid)) // output.success(); // break; // } // case Operation::Enable: { // auto addon = getSelectedAddon(output); // if (addon && AddonsManager::enable(addon->uuid)) // output.success(); // break; // } // case Operation::Disable: { // auto addon = getSelectedAddon(output); // if (addon && AddonsManager::disable(addon->uuid)) // output.success(); // break; // } // default: // break; // } // } // // static void setup(CommandRegistry* registry) { // registry->registerCommand("addons", "LiteLoaderBDS Addons Helper (Restart required after addon changes)", // CommandPermissionLevel::GameMasters, {(CommandFlagValue)0}, {(CommandFlagValue)0x80}); // // vector addonsList; // for (auto& addon : addons) // addonsList.push_back(addon.name); // registry->addSoftEnum("AddonName", addonsList); // // // addons list // registry->addEnum("Operation_Addons_List", {{"list", Operation::List}}); // registry->registerOverload( // "addons", // makeMandatory(&AddonsCommand::operation, "operation", "Operation_Addons_List").addOptions((CommandParameterOption)1), // makeOptional(&AddonsCommand::target, "addonName", "AddonName", &AddonsCommand::target_isSet)); // registry->registerOverload( // "addons", // makeMandatory(&AddonsCommand::operation, "operation", "Operation_Addons_List").addOptions((CommandParameterOption)1), // makeOptional(&AddonsCommand::index, "addonIndex", nullptr, &AddonsCommand::index_isSet)); // // // addons install // registry->addEnum("Operation_Addons_Install", {{"install", Operation::Install}}); // registry->registerOverload( // "addons", // makeMandatory(&AddonsCommand::operation, "operation", "Operation_Addons_Install").addOptions((CommandParameterOption)1), // makeMandatory(&AddonsCommand::target, "addonName")); // // // addons uninstall // // registry->addEnum("Operation_Addons_Others", { // {"uninstall", Operation::Uninstall}, // {"remove", Operation::Uninstall}, // {"enable", Operation::Enable}, // {"disable", Operation::Disable}, // }); // registry->registerOverload( // "addons", // makeMandatory(&AddonsCommand::operation, "operation", "Operation_Addons_Others").addOptions((CommandParameterOption)1), // makeMandatory(&AddonsCommand::target, "addonName", "AddonName", &AddonsCommand::target_isSet)); // registry->registerOverload( // "addons", // makeMandatory(&AddonsCommand::operation, "operation", "Operation_Addons_Others").addOptions((CommandParameterOption)1), // makeMandatory(&AddonsCommand::index, "addonIndex", nullptr, &AddonsCommand::index_isSet)); // } //}; // //void FindAddons(string jsonPath, string packsDir) { // try { // if (!filesystem::exists(str2wstr(jsonPath)) && !filesystem::exists(str2wstr(packsDir))) // return; // if (!filesystem::exists(str2wstr(jsonPath))) // WriteAllFile(jsonPath, "[]"); // if (!filesystem::exists(str2wstr(packsDir))) // filesystem::create_directories(str2wstr(packsDir)); // // auto content = ReadAllFile(jsonPath); // if (!content || content->empty()) { // WriteAllFile(jsonPath, "[]"); // content = "[]"; // } // std::set validPackIDs; // try { // auto addonList = nlohmann::json::parse(*content, nullptr, true, true); // for (auto addon : addonList) { // std::string pktid = addon["pack_id"]; // validPackIDs.insert(pktid); // } // } catch (const std::exception&) { // addonLogger.error(tr("ll.addonsHelper.error.parsingEnabledAddonsList")); // } // // filesystem::directory_iterator ent(str2wstr(packsDir)); // for (auto& dir : ent) { // if (!dir.is_directory()) // continue; // auto addon = parseAddonFromPath(dir); // if (!addon) // continue; // if (validPackIDs.find(addon->uuid) != validPackIDs.end()) // addon->enable = true; // addons.emplace_back(std::move(*addon)); // } // } catch (...) { // return; // } //} // //void BuildAddonsList() { // string levelPath = Level::getCurrentLevelPath(); // // FindAddons(levelPath + "/world_behavior_packs.json", levelPath + "/behavior_packs"); // FindAddons(levelPath + "/world_resource_packs.json", levelPath + "/resource_packs"); // // std::sort(addons.begin(), addons.end(), // [](Addon const& _Left, Addon const& _Right) { // if (_Left.enable && !_Right.enable) // return true; // if (_Left.type == Addon::Type::ResourcePack && _Right.type == Addon::Type::BehaviorPack) // return true; // return false; // }); //} // //bool AutoInstallAddons(string path) { // std::error_code ec; // if (!filesystem::exists(str2wstr(path))) { // filesystem::create_directories(str2wstr(path), ec); // addonLogger.info(tr("ll.addonsHelper.autoInstall.tip.dirCreated", LL::globalConfig.addonsInstallPath)); // return false; // } // std::vector toInstallList; // // filesystem::directory_iterator ent(str2wstr(path)); // for (auto& file : ent) { // if (!file.is_regular_file()) // continue; // // if (VALID_ADDON_FILE_EXTENSION.count(UTF82String(file.path().extension().u8string())) > 0) { // toInstallList.push_back(UTF82String(file.path().lexically_normal().u8string())); // } // } // // if (toInstallList.empty()) // return false; // // addonLogger.info(tr("ll.addonsHelper.autoInstall.working", toInstallList.size())); // int cnt = 0; // for (auto& path : toInstallList) { // addonLogger.debug("Installing \"{}\"...", path); // if (!AddonsManager::install(path)) { // // filesystem::remove_all(ADDON_INSTALL_TEMP_DIR, ec); // break; // } else { // ++cnt; // addonLogger.info(tr("ll.addonsHelper.autoInstall.installed", path)); // } // } // // if (cnt == 0) { // addonLogger.error(tr("ll.addonsHelper.error.noAddonInstalled")); // } else { // addonLogger.info(tr("ll.addonsHelper.autoInstall.installedCount", cnt)); // } // return true; //} // //void InitAddonsHelper() { // if (LL::isDebugMode()) // addonLogger.consoleLevel = addonLogger.debug.level; // // filesystem::remove_all(ADDON_INSTALL_TEMP_DIR); // filesystem::create_directories(ADDON_INSTALL_TEMP_DIR); // // AutoInstallAddons(LL::globalConfig.addonsInstallPath); // BuildAddonsList(); // // filesystem::remove_all(ADDON_INSTALL_TEMP_DIR); // // Event::RegCmdEvent::subscribe([](Event::RegCmdEvent ev) { // Register commands // AddonsCommand::setup(ev.mCommandRegistry); // return true; // }); //}