mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-18 18:20:39 +08:00
@@ -8,7 +8,7 @@
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 5054)
|
||||
#pragma warning(disable: 5054)
|
||||
#elif defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"
|
||||
@@ -27,43 +27,71 @@
|
||||
#endif
|
||||
#include <meojson/json.hpp>
|
||||
|
||||
static inline void ltrim(std::string& s)
|
||||
inline static void ltrim(std::string& s)
|
||||
{
|
||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); }));
|
||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
|
||||
return !std::isspace(ch);
|
||||
}));
|
||||
}
|
||||
|
||||
// trim from end (in place)
|
||||
static inline void rtrim(std::string& s)
|
||||
inline static void rtrim(std::string& s)
|
||||
{
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end());
|
||||
s.erase(
|
||||
std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); })
|
||||
.base(),
|
||||
s.end());
|
||||
}
|
||||
|
||||
// trim from both ends (in place)
|
||||
static inline void trim(std::string& s)
|
||||
inline static void trim(std::string& s)
|
||||
{
|
||||
ltrim(s);
|
||||
rtrim(s);
|
||||
}
|
||||
|
||||
bool update_items_data(const std::filesystem::path& input_dir, const std::filesystem::path& output_dir,
|
||||
bool with_imgs = true);
|
||||
bool cvt_single_item_template(const std::filesystem::path& input, const std::filesystem::path& output);
|
||||
bool update_infrast_data(const std::filesystem::path& input_dir, const std::filesystem::path& output_dir);
|
||||
bool update_stages_data(const std::filesystem::path& input_dir, const std::filesystem::path& output_dir);
|
||||
bool update_roguelike_recruit(const std::filesystem::path& input_dir, const std::filesystem::path& output_dir,
|
||||
const std::filesystem::path& solution_dir);
|
||||
bool update_levels_json(const std::filesystem::path& input_file, const std::filesystem::path& output_dir);
|
||||
bool update_infrast_templates(const std::filesystem::path& input_dir, const std::filesystem::path& output_dir);
|
||||
bool generate_english_roguelike_stage_name_replacement(const std::filesystem::path& ch_file,
|
||||
const std::filesystem::path& en_file);
|
||||
bool update_battle_chars_info(const std::filesystem::path& input_dir, const std::filesystem::path& overseas_dir,
|
||||
const std::filesystem::path& output_dir);
|
||||
bool update_recruitment_data(const std::filesystem::path& input_dir, const std::filesystem::path& output, bool is_base);
|
||||
bool check_roguelike_replace_for_overseas(const std::filesystem::path& input_dir,
|
||||
const std::filesystem::path& tasks_path,
|
||||
const std::filesystem::path& base_dir,
|
||||
const std::filesystem::path& output_dir);
|
||||
bool update_version_info(const std::filesystem::path& input_dir, const std::filesystem::path& output_dir);
|
||||
bool update_items_data(
|
||||
const std::filesystem::path& input_dir,
|
||||
const std::filesystem::path& output_dir,
|
||||
bool with_imgs = true);
|
||||
bool cvt_single_item_template(
|
||||
const std::filesystem::path& input,
|
||||
const std::filesystem::path& output);
|
||||
bool update_infrast_data(
|
||||
const std::filesystem::path& input_dir,
|
||||
const std::filesystem::path& output_dir);
|
||||
bool update_stages_data(
|
||||
const std::filesystem::path& input_dir,
|
||||
const std::filesystem::path& output_dir);
|
||||
bool update_roguelike_recruit(
|
||||
const std::filesystem::path& input_dir,
|
||||
const std::filesystem::path& output_dir,
|
||||
const std::filesystem::path& solution_dir);
|
||||
bool update_levels_json(
|
||||
const std::filesystem::path& input_file,
|
||||
const std::filesystem::path& output_dir);
|
||||
bool update_infrast_templates(
|
||||
const std::filesystem::path& input_dir,
|
||||
const std::filesystem::path& output_dir);
|
||||
bool generate_english_roguelike_stage_name_replacement(
|
||||
const std::filesystem::path& ch_file,
|
||||
const std::filesystem::path& en_file);
|
||||
bool update_battle_chars_info(
|
||||
const std::filesystem::path& input_dir,
|
||||
const std::filesystem::path& overseas_dir,
|
||||
const std::filesystem::path& output_dir);
|
||||
bool update_recruitment_data(
|
||||
const std::filesystem::path& input_dir,
|
||||
const std::filesystem::path& output,
|
||||
bool is_base);
|
||||
bool check_roguelike_replace_for_overseas(
|
||||
const std::filesystem::path& input_dir,
|
||||
const std::filesystem::path& tasks_path,
|
||||
const std::filesystem::path& base_dir,
|
||||
const std::filesystem::path& output_dir);
|
||||
bool update_version_info(
|
||||
const std::filesystem::path& input_dir,
|
||||
const std::filesystem::path& output_dir);
|
||||
|
||||
int main([[maybe_unused]] int argc, char** argv)
|
||||
{
|
||||
@@ -97,7 +125,9 @@ int main([[maybe_unused]] int argc, char** argv)
|
||||
|
||||
// Update levels.json from ArknightsGameResource
|
||||
std::cout << "------- Update levels.json for Official -------" << std::endl;
|
||||
if (!update_levels_json(official_data_dir / "levels.json", resource_dir / "Arknights-Tile-Pos")) {
|
||||
if (!update_levels_json(
|
||||
official_data_dir / "levels.json",
|
||||
resource_dir / "Arknights-Tile-Pos")) {
|
||||
std::cerr << "update levels.json failed" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
@@ -107,8 +137,8 @@ int main([[maybe_unused]] int argc, char** argv)
|
||||
|
||||
// 这个 en_levels.json 是自己手动生成放进去的
|
||||
// Will never work without en_levels.json in proj_dir, commented for now
|
||||
// generate_english_roguelike_stage_name_replacement(official_data_dir / "levels.json", cur_path /
|
||||
// "en_levels.json");
|
||||
// generate_english_roguelike_stage_name_replacement(official_data_dir / "levels.json", cur_path
|
||||
// / "en_levels.json");
|
||||
|
||||
// Update infrast data from ArknightsGameResource
|
||||
std::cout << "------- Update infrast data for Official -------" << std::endl;
|
||||
@@ -122,7 +152,9 @@ int main([[maybe_unused]] int argc, char** argv)
|
||||
|
||||
// Update infrast templates from ArknightsGameResource
|
||||
std::cout << "------- Update infrast templates for Official -------" << std::endl;
|
||||
if (!update_infrast_templates(official_data_dir / "building_skill", resource_dir / "template" / "infrast")) {
|
||||
if (!update_infrast_templates(
|
||||
official_data_dir / "building_skill",
|
||||
resource_dir / "template" / "infrast")) {
|
||||
std::cerr << "Update infrast templates failed" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
@@ -151,7 +183,10 @@ int main([[maybe_unused]] int argc, char** argv)
|
||||
|
||||
// Update battle chars info for all clients
|
||||
std::cout << "------- Update battle chars info for all clients -------" << std::endl;
|
||||
if (!update_battle_chars_info(official_data_dir / "gamedata" / "excel", overseas_data_dir, resource_dir)) {
|
||||
if (!update_battle_chars_info(
|
||||
official_data_dir / "gamedata" / "excel",
|
||||
overseas_data_dir,
|
||||
resource_dir)) {
|
||||
std::cerr << "Update battle chars info failed" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
@@ -161,7 +196,10 @@ int main([[maybe_unused]] int argc, char** argv)
|
||||
|
||||
// Update recruitment data from ArknightsGameResource
|
||||
std::cout << "------- Update recruitment data for Official -------" << std::endl;
|
||||
if (!update_recruitment_data(official_data_dir / "gamedata" / "excel", resource_dir / "recruitment.json", true)) {
|
||||
if (!update_recruitment_data(
|
||||
official_data_dir / "gamedata" / "excel",
|
||||
resource_dir / "recruitment.json",
|
||||
true)) {
|
||||
std::cerr << "Update recruitment data failed" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
@@ -172,8 +210,10 @@ int main([[maybe_unused]] int argc, char** argv)
|
||||
// Update recruitment data from ArknightsGameData_YoStar
|
||||
for (const auto& [in, out] : global_dirs) {
|
||||
std::cout << "------- Update recruitment data for " << out << "------- " << std::endl;
|
||||
if (!update_recruitment_data(overseas_data_dir / in / "gamedata" / "excel",
|
||||
resource_dir / "global" / out / "resource" / "recruitment.json", false)) {
|
||||
if (!update_recruitment_data(
|
||||
overseas_data_dir / in / "gamedata" / "excel",
|
||||
resource_dir / "global" / out / "resource" / "recruitment.json",
|
||||
false)) {
|
||||
std::cerr << "Update recruitment data failed" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
@@ -194,9 +234,12 @@ int main([[maybe_unused]] int argc, char** argv)
|
||||
|
||||
// Update items template and json from ArknightsGameData_YoStar
|
||||
for (const auto& [in, out] : global_dirs) {
|
||||
std::cout << "------- Update items template and json for " << out << "------- " << std::endl;
|
||||
if (!update_items_data(overseas_data_dir / in / "gamedata" / "excel",
|
||||
resource_dir / "global" / out / "resource", false)) {
|
||||
std::cout << "------- Update items template and json for " << out << "------- "
|
||||
<< std::endl;
|
||||
if (!update_items_data(
|
||||
overseas_data_dir / in / "gamedata" / "excel",
|
||||
resource_dir / "global" / out / "resource",
|
||||
false)) {
|
||||
std::cerr << "Update items json failed" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
@@ -208,9 +251,11 @@ int main([[maybe_unused]] int argc, char** argv)
|
||||
// Update roguelike replace for overseas from ArknightsGameData_YoStar
|
||||
for (const auto& [in, out] : global_dirs) {
|
||||
std::cout << "------- Update roguelike replace for " << out << "------- " << std::endl;
|
||||
if (!check_roguelike_replace_for_overseas(overseas_data_dir / in / "gamedata" / "excel",
|
||||
resource_dir / "global" / out / "resource" / "tasks.json",
|
||||
official_data_dir / "gamedata" / "excel", cur_path / in)) {
|
||||
if (!check_roguelike_replace_for_overseas(
|
||||
overseas_data_dir / in / "gamedata" / "excel",
|
||||
resource_dir / "global" / out / "resource" / "tasks.json",
|
||||
official_data_dir / "gamedata" / "excel",
|
||||
cur_path / in)) {
|
||||
std::cerr << "Update roguelike replace for overseas failed" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
@@ -231,8 +276,9 @@ int main([[maybe_unused]] int argc, char** argv)
|
||||
// Update global version info from ArknightsGameData_Yostar
|
||||
for (const auto& [in, out] : global_dirs) {
|
||||
std::cout << "------- Update version info for " << out << "------- " << std::endl;
|
||||
if (!update_version_info(overseas_data_dir / in / "gamedata" / "excel",
|
||||
resource_dir / "global" / out / "resource")) {
|
||||
if (!update_version_info(
|
||||
overseas_data_dir / in / "gamedata" / "excel",
|
||||
resource_dir / "global" / out / "resource")) {
|
||||
std::cerr << "Update version info failed" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
@@ -247,10 +293,13 @@ int main([[maybe_unused]] int argc, char** argv)
|
||||
|
||||
// ---- METHODS DEFINITIONS ----
|
||||
|
||||
bool update_items_data(const std::filesystem::path& input_dir, const std::filesystem::path& output_dir, bool with_imgs)
|
||||
bool update_items_data(
|
||||
const std::filesystem::path& input_dir,
|
||||
const std::filesystem::path& output_dir,
|
||||
bool with_imgs)
|
||||
{
|
||||
const auto input_json_path =
|
||||
with_imgs ? input_dir / "gamedata" / "excel" / "item_table.json" : input_dir / "item_table.json";
|
||||
const auto input_json_path = with_imgs ? input_dir / "gamedata" / "excel" / "item_table.json"
|
||||
: input_dir / "item_table.json";
|
||||
|
||||
auto parse_ret = json::open(input_json_path);
|
||||
if (!parse_ret) {
|
||||
@@ -270,8 +319,8 @@ bool update_items_data(const std::filesystem::path& input_dir, const std::filesy
|
||||
"renamingCard", // 改名卡
|
||||
"ap_item_", // 干员发邮件送的东西
|
||||
"ap_supply_lt_100_202", // 干员发邮件送的理智(注意前半段id是理智小样,不能全过滤)
|
||||
"clue_", // 火蓝之心活动的扭蛋什么的
|
||||
"2020recruitment10", // 周年自选券
|
||||
"clue_", // 火蓝之心活动的扭蛋什么的
|
||||
"2020recruitment10", // 周年自选券
|
||||
"2021recruitment10",
|
||||
"2022recruitment10",
|
||||
"2023recruitment10",
|
||||
@@ -337,7 +386,9 @@ bool update_items_data(const std::filesystem::path& input_dir, const std::filesy
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cvt_single_item_template(const std::filesystem::path& input, const std::filesystem::path& output)
|
||||
bool cvt_single_item_template(
|
||||
const std::filesystem::path& input,
|
||||
const std::filesystem::path& output)
|
||||
{
|
||||
cv::Mat src = cv::imread(input.string(), -1);
|
||||
if (src.empty()) {
|
||||
@@ -382,15 +433,18 @@ bool cvt_single_item_template(const std::filesystem::path& input, const std::fil
|
||||
cv::minMaxLoc(matched, &min_val, &max_val, &min_loc, &max_loc);
|
||||
|
||||
if (max_val > 0.95) {
|
||||
std::cout << "Same item templ, skip: " << output.string() << ", score: " << max_val << std::endl;
|
||||
std::cout << "Same item templ, skip: " << output.string() << ", score: " << max_val
|
||||
<< std::endl;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
std::cout << "Update item templ: " << output.string() << ", score: " << max_val << std::endl;
|
||||
std::cout << "Update item templ: " << output.string() << ", score: " << max_val
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::cout << "Update item templ: " << output.string() << " because sizes are different." << std::endl;
|
||||
std::cout << "Update item templ: " << output.string() << " because sizes are different."
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -448,7 +502,9 @@ void remove_xml(std::string& text)
|
||||
text.erase(next_iter, text.end());
|
||||
}
|
||||
|
||||
bool update_infrast_data(const std::filesystem::path& input_dir, const std::filesystem::path& output_dir)
|
||||
bool update_infrast_data(
|
||||
const std::filesystem::path& input_dir,
|
||||
const std::filesystem::path& output_dir)
|
||||
{
|
||||
const auto input_file = input_dir / "building_data.json";
|
||||
const auto output_file = output_dir / "infrast.json";
|
||||
@@ -540,7 +596,9 @@ bool update_infrast_data(const std::filesystem::path& input_dir, const std::file
|
||||
return true;
|
||||
}
|
||||
|
||||
bool update_stages_data(const std::filesystem::path& input_dir, const std::filesystem::path& output_dir)
|
||||
bool update_stages_data(
|
||||
const std::filesystem::path& input_dir,
|
||||
const std::filesystem::path& output_dir)
|
||||
{
|
||||
// 国内访问可以改成 .cn 的域名
|
||||
const std::string PenguinAPI = R"(https://penguin-stats.io/PenguinStats/api/v2/stages?server=)";
|
||||
@@ -552,14 +610,21 @@ bool update_stages_data(const std::filesystem::path& input_dir, const std::files
|
||||
{
|
||||
std::string item_id;
|
||||
std::string drop_type;
|
||||
bool operator<(const DropInfo& rhs) const { return item_id + drop_type < rhs.item_id + drop_type; }
|
||||
bool operator==(const DropInfo& rhs) const { return item_id == rhs.item_id && drop_type == rhs.drop_type; }
|
||||
bool operator<(const DropInfo& rhs) const
|
||||
{
|
||||
return item_id + drop_type < rhs.item_id + drop_type;
|
||||
}
|
||||
bool operator==(const DropInfo& rhs) const
|
||||
{
|
||||
return item_id == rhs.item_id && drop_type == rhs.drop_type;
|
||||
}
|
||||
};
|
||||
|
||||
std::map<std::string, std::set<DropInfo>> drop_infos;
|
||||
std::map<std::string, json::value> stage_basic_infos;
|
||||
for (const auto& server : PenguinServers) {
|
||||
int stage_request_ret = system(("curl -o \"" + TempFile.string() + "\" " + PenguinAPI + server).c_str());
|
||||
int stage_request_ret =
|
||||
system(("curl -o \"" + TempFile.string() + "\" " + PenguinAPI + server).c_str());
|
||||
if (stage_request_ret != 0) {
|
||||
std::cerr << "Request Penguin Stats failed" << std::endl;
|
||||
return false;
|
||||
@@ -617,7 +682,9 @@ bool update_stages_data(const std::filesystem::path& input_dir, const std::files
|
||||
return true;
|
||||
}
|
||||
|
||||
bool update_infrast_templates(const std::filesystem::path& input_dir, const std::filesystem::path& output_dir)
|
||||
bool update_infrast_templates(
|
||||
const std::filesystem::path& input_dir,
|
||||
const std::filesystem::path& output_dir)
|
||||
{
|
||||
for (auto&& entry : std::filesystem::directory_iterator(input_dir)) {
|
||||
if (entry.path().extension() != ".png") {
|
||||
@@ -625,7 +692,10 @@ bool update_infrast_templates(const std::filesystem::path& input_dir, const std:
|
||||
}
|
||||
const std::string& stem = entry.path().stem().string();
|
||||
|
||||
const std::vector<std::string> BlackList = { "[style]", "bskill_dorm", "bskill_train", "bskill_ws" };
|
||||
const std::vector<std::string> BlackList = { "[style]",
|
||||
"bskill_dorm",
|
||||
"bskill_train",
|
||||
"bskill_ws" };
|
||||
|
||||
bool is_blacklist = false;
|
||||
for (const auto& bl : BlackList) {
|
||||
@@ -666,15 +736,18 @@ bool update_infrast_templates(const std::filesystem::path& input_dir, const std:
|
||||
cv::minMaxLoc(matched, &min_val, &max_val, &min_loc, &max_loc);
|
||||
|
||||
if (max_val > 0.95) {
|
||||
std::cout << "Same infrast templ, skip: " << out_file << ", score: " << max_val << std::endl;
|
||||
std::cout << "Same infrast templ, skip: " << out_file << ", score: " << max_val
|
||||
<< std::endl;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
std::cout << "Update infrast templ: " << out_file << ", score: " << max_val << std::endl;
|
||||
std::cout << "Update infrast templ: " << out_file << ", score: " << max_val
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::cout << "Update infrast templ: " << out_file << " because sizes are different." << std::endl;
|
||||
std::cout << "Update infrast templ: " << out_file << " because sizes are different."
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -685,14 +758,16 @@ bool update_infrast_templates(const std::filesystem::path& input_dir, const std:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool update_roguelike_recruit(const std::filesystem::path& input_dir, const std::filesystem::path& output_dir,
|
||||
const std::filesystem::path& solution_dir)
|
||||
bool update_roguelike_recruit(
|
||||
const std::filesystem::path& input_dir,
|
||||
const std::filesystem::path& output_dir,
|
||||
const std::filesystem::path& solution_dir)
|
||||
{
|
||||
std::string python_cmd;
|
||||
std::filesystem::path python_file =
|
||||
solution_dir / "tools" / "RoguelikeResourceUpdater" / "generate_roguelike_recruit.py";
|
||||
python_cmd = "python " + python_file.string() + " --input=\"" + input_dir.string() + "\" --output=\"" +
|
||||
output_dir.string() + "\"";
|
||||
python_cmd = "python " + python_file.string() + " --input=\"" + input_dir.string()
|
||||
+ "\" --output=\"" + output_dir.string() + "\"";
|
||||
int python_ret = system(python_cmd.c_str());
|
||||
if (python_ret != 0) {
|
||||
return false;
|
||||
@@ -700,7 +775,9 @@ bool update_roguelike_recruit(const std::filesystem::path& input_dir, const std:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool update_levels_json(const std::filesystem::path& input_file, const std::filesystem::path& output_dir)
|
||||
bool update_levels_json(
|
||||
const std::filesystem::path& input_file,
|
||||
const std::filesystem::path& output_dir)
|
||||
{
|
||||
auto json_opt = json::open(input_file);
|
||||
if (!json_opt) {
|
||||
@@ -713,7 +790,8 @@ bool update_levels_json(const std::filesystem::path& input_file, const std::file
|
||||
json::value overview = json::open(overview_path).value_or(json::value());
|
||||
|
||||
for (auto& stage_info : root.as_array()) {
|
||||
std::string stem = stage_info["stageId"].as_string() + "-" + stage_info["levelId"].as_string();
|
||||
std::string stem =
|
||||
stage_info["stageId"].as_string() + "-" + stage_info["levelId"].as_string();
|
||||
std::string filename = stem + ".json";
|
||||
asst::utils::string_replace_all_in_place(filename, "/", "-");
|
||||
auto filepath = output_dir / filename;
|
||||
@@ -741,8 +819,9 @@ bool update_levels_json(const std::filesystem::path& input_file, const std::file
|
||||
return true;
|
||||
}
|
||||
|
||||
bool generate_english_roguelike_stage_name_replacement(const std::filesystem::path& ch_file,
|
||||
const std::filesystem::path& en_file)
|
||||
bool generate_english_roguelike_stage_name_replacement(
|
||||
const std::filesystem::path& ch_file,
|
||||
const std::filesystem::path& en_file)
|
||||
{
|
||||
auto ch_opt = json::open(ch_file);
|
||||
auto en_opt = json::open(en_file);
|
||||
@@ -786,8 +865,10 @@ bool generate_english_roguelike_stage_name_replacement(const std::filesystem::pa
|
||||
return true;
|
||||
}
|
||||
|
||||
bool update_battle_chars_info(const std::filesystem::path& official_dir, const std::filesystem::path& overseas_dir,
|
||||
const std::filesystem::path& output_dir)
|
||||
bool update_battle_chars_info(
|
||||
const std::filesystem::path& official_dir,
|
||||
const std::filesystem::path& overseas_dir,
|
||||
const std::filesystem::path& output_dir)
|
||||
{
|
||||
std::string to_char_json = "gamedata/excel/character_table.json";
|
||||
|
||||
@@ -798,25 +879,28 @@ bool update_battle_chars_info(const std::filesystem::path& official_dir, const s
|
||||
auto chars_kr_opt = json::open(overseas_dir / "ko_KR" / to_char_json);
|
||||
auto chars_tw_opt = json::open(overseas_dir / "zh_TW" / to_char_json);
|
||||
|
||||
if (!chars_cn_opt || !chars_en_opt || !chars_jp_opt || !chars_kr_opt || !chars_tw_opt || !range_opt) {
|
||||
if (!chars_cn_opt || !chars_en_opt || !chars_jp_opt || !chars_kr_opt || !chars_tw_opt
|
||||
|| !range_opt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& range_json = range_opt.value();
|
||||
|
||||
std::vector<std::pair<json::value, std::string>> chars_json = { { chars_cn_opt.value(), "name" },
|
||||
{ chars_en_opt.value(), "name_en" },
|
||||
{ chars_jp_opt.value(), "name_jp" },
|
||||
{ chars_kr_opt.value(), "name_kr" },
|
||||
{ chars_tw_opt.value(), "name_tw" } };
|
||||
std::vector<std::pair<json::value, std::string>> chars_json = {
|
||||
{ chars_cn_opt.value(), "name" },
|
||||
{ chars_en_opt.value(), "name_en" },
|
||||
{ chars_jp_opt.value(), "name_jp" },
|
||||
{ chars_kr_opt.value(), "name_kr" },
|
||||
{ chars_tw_opt.value(), "name_tw" }
|
||||
};
|
||||
|
||||
json::value result;
|
||||
auto& range = result["ranges"].as_object();
|
||||
for (auto& [id, range_data] : range_json.as_object()) {
|
||||
if (int direction = range_data["direction"].as_integer(); direction != 1) {
|
||||
// 现在都是 1,朝右的,以后不知道会不会改,加个warning,真遇到再说
|
||||
std::cerr << "!!!Warning!!! range_id: " << id << " 's direction is " << std::to_string(direction)
|
||||
<< std::endl;
|
||||
std::cerr << "!!!Warning!!! range_id: " << id << " 's direction is "
|
||||
<< std::to_string(direction) << std::endl;
|
||||
}
|
||||
json::array points;
|
||||
for (auto& grids : range_data["grids"].as_array()) {
|
||||
@@ -889,14 +973,21 @@ bool update_battle_chars_info(const std::filesystem::path& official_dir, const s
|
||||
return true;
|
||||
}
|
||||
|
||||
bool update_recruitment_data(const std::filesystem::path& input_dir, const std::filesystem::path& output, bool is_base)
|
||||
bool update_recruitment_data(
|
||||
const std::filesystem::path& input_dir,
|
||||
const std::filesystem::path& output,
|
||||
bool is_base)
|
||||
{
|
||||
using asst::ranges::find_if, asst::ranges::range;
|
||||
using asst::utils::string_replace_all_in_place;
|
||||
using asst::views::filter, asst::views::split, asst::views::transform, asst::views::drop_while;
|
||||
|
||||
auto not_empty = []<range Rng>(Rng str) -> bool { return !str.empty(); };
|
||||
auto make_string_view = []<range Rng>(Rng str) -> std::string_view { return asst::utils::make_string_view(str); };
|
||||
auto not_empty = []<range Rng>(Rng str) -> bool {
|
||||
return !str.empty();
|
||||
};
|
||||
auto make_string_view = []<range Rng>(Rng str) -> std::string_view {
|
||||
return asst::utils::make_string_view(str);
|
||||
};
|
||||
|
||||
auto recruitment_opt = json::open(input_dir / "gacha_table.json");
|
||||
auto operators_opt = json::open(input_dir / "character_table.json");
|
||||
@@ -916,15 +1007,21 @@ bool update_recruitment_data(const std::filesystem::path& input_dir, const std::
|
||||
// 按照 ★ 分割
|
||||
recruitment_details | split(star_delim) | filter(not_empty) | transform(make_string_view) |
|
||||
// 忽略 Lancet-2 之前的东西
|
||||
drop_while([&](std::string_view str) { return str.find("Lancet-2") == std::string_view::npos; }) |
|
||||
drop_while(
|
||||
[&](std::string_view str) { return str.find("Lancet-2") == std::string_view::npos; })
|
||||
|
|
||||
// 按照 \n 分割,若非空则取第一个元素
|
||||
transform([&](auto str) { return str | split('\n') | filter(not_empty); }) | filter(not_empty) |
|
||||
transform([&](auto strs) { return make_string_view(strs.front()); });
|
||||
transform([&](auto str) { return str | split('\n') | filter(not_empty); })
|
||||
| filter(not_empty) | transform([&](auto strs) { return make_string_view(strs.front()); });
|
||||
|
||||
for (std::string_view s : items) {
|
||||
for (std::string_view n : s | split('/') | filter(not_empty) | transform(make_string_view)) {
|
||||
for (std::string_view n :
|
||||
s | split('/') | filter(not_empty) | transform(make_string_view)) {
|
||||
std::string name(n);
|
||||
string_replace_all_in_place(name, " ", " "); // " " is full-width space, replacing with common " "
|
||||
string_replace_all_in_place(
|
||||
name,
|
||||
" ",
|
||||
" "); // " " is full-width space, replacing with common " "
|
||||
trim(name);
|
||||
if (name == "Justice Knight") {
|
||||
name = "'Justice Knight'";
|
||||
@@ -1033,10 +1130,11 @@ bool update_recruitment_data(const std::filesystem::path& input_dir, const std::
|
||||
return true;
|
||||
}
|
||||
|
||||
bool check_roguelike_replace_for_overseas(const std::filesystem::path& input_dir,
|
||||
const std::filesystem::path& tasks_path,
|
||||
const std::filesystem::path& base_dir,
|
||||
const std::filesystem::path& output_dir)
|
||||
bool check_roguelike_replace_for_overseas(
|
||||
const std::filesystem::path& input_dir,
|
||||
const std::filesystem::path& tasks_path,
|
||||
const std::filesystem::path& base_dir,
|
||||
const std::filesystem::path& output_dir)
|
||||
{
|
||||
static std::unordered_map</*id*/ std::string, /*base_name*/ std::string> base_stage_names;
|
||||
static std::unordered_map</*id*/ std::string, /*base_name*/ std::string> base_item_names;
|
||||
@@ -1070,7 +1168,8 @@ bool check_roguelike_replace_for_overseas(const std::filesystem::path& input_dir
|
||||
// very complicated way to reduce dupes. Will probably brake sooner or later.
|
||||
if (id.ends_with("_enter")) {
|
||||
if (!id.starts_with("scene_ro3_rest")) {
|
||||
if (!id.starts_with("scene_ro3_portal") || id.starts_with("scene_ro3_portalsample")) {
|
||||
if (!id.starts_with("scene_ro3_portal")
|
||||
|| id.starts_with("scene_ro3_portalsample")) {
|
||||
base_encounter_names.emplace(id, encounter_obj["title"].as_string());
|
||||
}
|
||||
}
|
||||
@@ -1126,11 +1225,15 @@ bool check_roguelike_replace_for_overseas(const std::filesystem::path& input_dir
|
||||
// very complicated way to reduce dupes. Will probably break sooner or later.
|
||||
if (id.ends_with("_enter")) {
|
||||
if (!id.starts_with("scene_ro3_rest")) {
|
||||
if (!id.starts_with("scene_ro3_portal") || id.starts_with("scene_ro3_portalsample")) {
|
||||
if (!id.starts_with("scene_ro3_portal")
|
||||
|| id.starts_with("scene_ro3_portalsample")) {
|
||||
encounter_nospace = encounter_obj["title"].as_string();
|
||||
if (input_dir.string().ends_with("ko_KR\\gamedata\\excel")) {
|
||||
encounter_nospace.erase(
|
||||
std::remove(encounter_nospace.begin(), encounter_nospace.end(), ' '),
|
||||
std::remove(
|
||||
encounter_nospace.begin(),
|
||||
encounter_nospace.end(),
|
||||
' '),
|
||||
encounter_nospace.end());
|
||||
}
|
||||
encounter_names.emplace(id, encounter_nospace);
|
||||
@@ -1159,8 +1262,10 @@ bool check_roguelike_replace_for_overseas(const std::filesystem::path& input_dir
|
||||
}
|
||||
auto& task_json = task_opt.value();
|
||||
|
||||
auto proc = [&output_dir](json::array& replace_array, const std::unordered_map<std::string, std::string>& base_map,
|
||||
const std::unordered_map<std::string, std::string>& cur_map) {
|
||||
auto proc = [&output_dir](
|
||||
json::array& replace_array,
|
||||
const std::unordered_map<std::string, std::string>& base_map,
|
||||
const std::unordered_map<std::string, std::string>& cur_map) {
|
||||
std::unordered_map<std::string, std::string> exists_replace;
|
||||
for (const auto& replace : replace_array) {
|
||||
exists_replace.emplace(replace.as_array()[1], replace.as_array()[0]);
|
||||
@@ -1186,8 +1291,14 @@ bool check_roguelike_replace_for_overseas(const std::filesystem::path& input_dir
|
||||
|
||||
proc(task_json["BattleStageName"]["ocrReplace"].as_array(), base_stage_names, stage_names);
|
||||
proc(task_json["CharsNameOcrReplace"]["ocrReplace"].as_array(), base_char_names, char_names);
|
||||
proc(task_json["RoguelikeTraderShoppingOcr"]["ocrReplace"].as_array(), base_item_names, item_names);
|
||||
proc(task_json["Roguelike@StageEncounterOcr"]["ocrReplace"].as_array(), base_encounter_names, encounter_names);
|
||||
proc(
|
||||
task_json["RoguelikeTraderShoppingOcr"]["ocrReplace"].as_array(),
|
||||
base_item_names,
|
||||
item_names);
|
||||
proc(
|
||||
task_json["Roguelike@StageEncounterOcr"]["ocrReplace"].as_array(),
|
||||
base_encounter_names,
|
||||
encounter_names);
|
||||
|
||||
std::ofstream ofs(tasks_path, std::ios::out);
|
||||
ofs << task_json.format() << std::endl;
|
||||
@@ -1196,7 +1307,9 @@ bool check_roguelike_replace_for_overseas(const std::filesystem::path& input_dir
|
||||
return true;
|
||||
}
|
||||
|
||||
bool update_version_info(const std::filesystem::path& input_dir, const std::filesystem::path& output_dir)
|
||||
bool update_version_info(
|
||||
const std::filesystem::path& input_dir,
|
||||
const std::filesystem::path& output_dir)
|
||||
{
|
||||
uint64_t current_time = (unsigned long)time(NULL);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user