// Removed useless files, to speed up build process and make it clearer. const path = require("path"); const fs = require("fs"); const readline = require("readline"); // cmdid current version const read_cmdid = "cmdid.csv"; const read_cmdid_output = "cmdid.json"; const read_cmdid_output_gc = "cmdid_gc.json"; const read_cmdid_output_gc_update = "cmdid_gc_update.json"; const read_cmdid_output_gc_nofound = "cmdid_gc_nofound.json"; const file_gc_needed = "gc_needed.json"; const file_gc_needed2 = "gc_needed2.json"; const write_op = "PacketOpcodes.java"; console.log(process.cwd()); //(TODO: add input file) // folder gc auto-generated proto const folder_proto_gc_gen = "../Grasscutter-Yuuki/src/generated/main/java/emu/grasscutter/net/proto/"; // file PacketOpcodes currently in use const read_cmdid_gc = "../Grasscutter-Yuuki/src/main/java/emu/grasscutter/net/packet/PacketOpcodes.java"; const folder_packet_gc = "../Grasscutter-Yuuki/src/main/java/emu/grasscutter/server/packet/"; const folder_gc_scan = "../Grasscutter-Yuuki/src/main/java/emu/grasscutter/"; //const read_cmdid = fs.readFileSync("cmdid.csv"); //const read_packetopcodes = fs.readFileSync("PacketOpcodes.java"); var data = []; var data_gc = []; var index_file_gen = 0; var index_file_cmdid = 0; var index_cmdid_gc = 0; var index_cmdid_gc_out = 0; function check_gen() { fs.readdir(folder_proto_gc_gen, function (err, files) { //handling error if (err) { return console.log("Unable to scan directory: " + err); } files.forEach(function (file) { index_file_gen++; }); console.log("file proto gen: " + index_file_gen); }); } // gen json file cmdid function get_cmdid_json() { const inputStreamcmdid = fs.createReadStream(read_cmdid); var lineReadercmdid = readline.createInterface({ input: inputStreamcmdid, terminal: false, }); lineReadercmdid.on("line", function (line) { var config = line.split(","); var subdata = new Object(); subdata["name"] = config[0]; subdata["id"] = parseInt(config[1]); data.push(subdata); index_file_cmdid++; }); lineReadercmdid.on("close", function () { console.log("found cmd id " + index_file_cmdid); save_json(data, read_cmdid_output); }); } // create cmdid from gc which comes from PacketOpcodes function get_cmdid_gc() { const inputStreamcmdid = fs.createReadStream(read_cmdid_gc); var lineReadercmdid = readline.createInterface({ input: inputStreamcmdid, terminal: false, }); lineReadercmdid.on("line", function (line) { var config = line.split(" = "); var name = config[0]; var id = parseInt(config[1]); if (name.includes("public static final int")) { name = name.replace("\tpublic static final int ", ""); // skip 0 ? if (id == 0) { return; } var subdata = new Object(); subdata["name"] = name; subdata["id"] = id; data_gc.push(subdata); //console.log(name); index_cmdid_gc++; } else { index_cmdid_gc_out++; } }); lineReadercmdid.on("close", function () { console.log( "found cmd id " + index_cmdid_gc + " | no need " + index_cmdid_gc_out ); save_json(data_gc, read_cmdid_output_gc); }); } var found_cmdid_new = 0; var nofound_cmdid_new = 0; var rename_name_cmdid = 0; var noneed_rename_name_cmdid = 0; var data_gc_cmdid_nofound = []; var check_dunp_id = []; function update_cmdid_gc() { const cmd_last = fs.readFileSync(read_cmdid_output); const cmd_old = fs.readFileSync(read_cmdid_output_gc); const json_cmdid_last = JSON.parse(cmd_last); const json_cmdid_old = JSON.parse(cmd_old); json_cmdid_old.forEach(function (s, index) { var id = s.id; var name = s.name.trim(); var found_id = json_cmdid_last.find((j) => j.id == id); if (found_id) { found_cmdid_new++; if (name == found_id.name) { noneed_rename_name_cmdid++; } else { rename_name_cmdid++; //console.log("Wow rename -> ID: "+id+" | Name: "+name+" > "+found_id.name); // rename json_cmdid_old s.replace = s.name; s.name = found_id.name; } } else { console.log("Wow nofound -> ID: " + id + " | Name: " + name); data_gc_cmdid_nofound.push(s); nofound_cmdid_new++; } // find dump by id var found_id = check_dunp_id.find((j) => j.id == id); if (found_id) { console.log( "Wow dup -> ID: " + id + " (ADD " + found_id.id + ") | Name Remove: " + name + " (ADD " + found_id.name + ")" ); // remove bad json_cmdid_old.splice(index, 1); } else { check_dunp_id.push(s); } }); check_dunp_id = []; // clear // I don't know why this happened but make sure to check again var check_dunp_name = []; json_cmdid_old.forEach(function (s, index) { var id = s.id; var name = s.name.trim(); var found_name = check_dunp_name.find((j) => j.name === name); if (found_name) { console.log( "Wow dup -> ID: " + id + " (ADD " + found_name.id + ") | Name Remove: " + name + " (ADD " + found_name.name + ")" ); // remove bad json_cmdid_old.splice(index, 1); } else { check_dunp_name.push(s); } var found_id = json_cmdid_last.find((j) => j.id == id); if (found_id) { if (name != found_id.name) { console.log( "Wow why? -> ID: " + id + " | Name: " + name + " > " + found_id.name ); s.name = found_id.name; } } }); check_dunp_name = []; // clear console.log( "found " + found_cmdid_new + " | no found " + nofound_cmdid_new + " | rename " + rename_name_cmdid + " | noneed rename " + noneed_rename_name_cmdid ); save_json(json_cmdid_old, read_cmdid_output_gc_update); save_json(data_gc_cmdid_nofound, read_cmdid_output_gc_nofound); } function read_json(file) { return JSON.parse(fs.readFileSync(file)); } // save json function save_json(raw, file) { var j = JSON.stringify(raw, null, 4); save(j, file); } function save(raw, file) { fs.writeFile(file, raw, "utf8", function (err) { if (err) { console.log("An error occured while writing to File."); return console.log(err); } console.log("File has been saved: " + file); }); } function cmdid_to_op() { let melon = "\ package emu.grasscutter.net.packet;\ \n\ \npublic class PacketOpcodes {\ \n// Empty\ \npublic static final int NONE = 0;\ \n\ \n// Opcodes\ "; const cmdidfix_raw = fs.readFileSync(read_cmdid_output_gc_update); const json_cmdidfix_raw = JSON.parse(cmdidfix_raw); json_cmdidfix_raw.forEach(function (s) { melon += "\npublic static final int " + s.name + " = " + s.id + ";"; }); melon += "\n}"; save(melon, write_op); // use "npx prettier --write PacketOpcodes.java" for better Formatter } var index_file_packet = 0; var index_file_packet_found = 0; var index_file_packet_nofound = 0; var index_file_packet_rename = 0; var index_file_packet_norename = 0; var index_file_packet_renamemulti = 0; var file_gc_need = []; function fix_packet(saveit = false) { const files = getAllFiles(folder_packet_gc); const json_cmdid_last = read_json(read_cmdid_output); const json_cmdid_old = read_json(read_cmdid_output_gc); const json_cmdidfix_raw = read_json(read_cmdid_output_gc_update); files.forEach(function (file) { //var f = path + "/" + file; const read = fs.readFileSync(file); var real = read.toString(); var name = getPacketOpcodes(real); if (!name) { console.log("no found"); return; } if (name === "NONE") { return; } var subdata = new Object(); subdata["name"] = name; file_gc_need.push(subdata); //var name = c[1]; //console.log(r); var found_old = json_cmdid_old.find((j) => j.name === name); if (found_old) { //console.log(found_old); index_file_packet_found++; var found_new = json_cmdid_last.find((j) => j.id == found_old.id); if (found_new) { if (found_new.name != found_old.name) { index_file_packet_rename++; console.log( "Found need rename: " + found_old.name + " > " + found_new.name ); // rename all json_cmdidfix_raw.forEach(function (s) { var r = s.replace; if (r) { // var notify = HomeNewUnlockedBgmIdListNotify.Unk2700_MEBFPBDNPGO_ServerNotify // var notify = Unk2700MEBFPBDNPGOServerNotify.HomeNewUnlockedBgmIdListNotify // Unk2700MEBFPBDNPGOServerNotify to HomeNewUnlockedBgmIdListNotifyOuterClass // Unk2700OGHMHELMBNNServerRsp to HomeChangeBgmRspOuterClass // - Need More Auto like - // addUnk2700ELJPLMIHNIP to addNewUnlockedBgmIdList (this should be found inside gen proto) // setUnk2700BJHAMKKECEI to setBgmId if (r.match("Unk")) { //console.log(r); var x = r.split("_"); var tr = x.join(""); var realneed = tr; if (tr.match("ServerNotify")) { //console.log("found: "+tr); let re = new RegExp(`${tr}`, "g"); tr = tr.replace(re, `${s.name}OuterClass`); //console.log("found: " + tr); } else if (tr.match("ServerRsp")) { let re = new RegExp(`${tr}`, "g"); tr = tr.replace(re, `${s.name}OuterClass`); } else { let re = new RegExp(`${tr}`, "g"); tr = tr.replace(re, s.name); //console.log("found: " + tr); } let re = new RegExp(`${realneed}`, "g"); real = real.replace(re, tr); } let re = new RegExp(`${r}`, "g"); real = real.replace(re, s.name); } }); // simpel rename //let re = new RegExp(`${found_old.name}`, "g"); //real = real.replace(re, found_new.name); //console.log(real); if (saveit) { save(real, f); } } } else { index_file_packet_norename++; //console.log("Same name "+name); } } else { index_file_packet_nofound++; console.log("No found " + name); } //return; index_file_packet++; }); save_json(file_gc_need, file_gc_needed); // This only applies to PacketOpcodes console.log( "Index file: " + index_file_packet + " | found " + index_file_packet_found + " | No found " + index_file_packet_nofound + " | Rename " + index_file_packet_rename + " | NoRename " + index_file_packet_norename ); } function isBlank(str) { return !!!str || /^\s*$/.test(str); } function getAllFiles(dirPath, arrayOfFiles) { files = fs.readdirSync(dirPath); arrayOfFiles = arrayOfFiles || []; files.forEach(function (file) { if (fs.statSync(dirPath + "/" + file).isDirectory()) { arrayOfFiles = getAllFiles(dirPath + "/" + file, arrayOfFiles); } else { arrayOfFiles.push(path.join(__dirname, dirPath, "/", file)); } }); return arrayOfFiles; } function getPacketOpcodes(raw) { var r = raw.match(/\(.*?\)/g).map((x) => x.replace(/[()]/g, "")); var name; r.forEach(function (s, index) { if (s.match("PacketOpcodes.")) { name = s.split("PacketOpcodes.")[1]; if (name.match(",")) { name = name.split(",")[0]; } return; } }); return name; } // C:\Users\Administrator\Desktop\Projek\Docker\GS\gs\Grasscutter-Yuuki\src\main\java\emu\grasscutter var file_toclean = []; var file_toaddmore = []; var found_noclean = 0; var found_needclean = 0; var found_maybe_related = 0; function clean_proto_gen() { //const files = getAllFiles(folder_proto_gc_gen); const files = getAllFiles("./proto"); const json_gc_needed = read_json(file_gc_needed); const json_gc_needed2 = read_json(file_gc_needed2); const json_gc_now = read_json(read_cmdid_output_gc); const json_gc_update = read_json(read_cmdid_output_gc_update); //AbilityInvokeArgument console.log( "File proto: " + files.length + " | Need " + json_gc_needed.length ); const regex = /\import "(.*?)\.proto"/g; // find all file import files.forEach(function (file) { // read file const read = fs.readFileSync(file); var rd = read.toString(); if (file.match("Unk")) { console.log("unk: " + file); } // find import while ((m = regex.exec(rd)) !== null) { // This is necessary to avoid infinite loops with zero-width matches if (m.index === regex.lastIndex) { regex.lastIndex++; } // The result can be accessed through the `m`-variable. m.forEach((match, groupIndex) => { // only index 1 grup if (groupIndex == 1) { var found_rt = file_toaddmore.find((j) => j.name === match); if (found_rt) { //console.log(`Skip ${match}`); } else { if (match.match("Unk") || file.match("Unk")) { console.log(file + " require " + match); } var subdata = new Object(); subdata["name"] = match; file_toaddmore.push(subdata); } } }); } }); // last try files.forEach(function (file) { var todoremove = false; // main file var found = json_gc_needed.find((j) => file.match(j.name)); if (found) { // skip } else { var found1 = file_toaddmore.find((j) => file.match(j.name)); // find import if (found1) { // skip //console.log("Files sub are required: "+file); found_maybe_related++; } else { if (file.match("Retcode")) { console.log("found"); } else { var found2 = json_gc_needed2.find((j) => file.match(j.name)); // find miss scan if (found2) { // skip found_maybe_related++; } else { todoremove = true; } } } } if (todoremove) { found_needclean++; console.log("Remove file: "+file); try { fs.unlinkSync(file); //file removed } catch (err) { console.error(err); } } else { found_noclean++; } }); //console.log(file_toaddmore); console.log( "No clean: " + found_noclean + " | Need to clean: " + found_needclean + " | Related " + found_maybe_related ); } var g_todump = []; function scan_gc() { const files = getAllFiles(folder_gc_scan); console.log("index file: " + files.length); const regex = /import emu.grasscutter.net.proto.(.*?);/g; files.forEach(function (file) { // read file const read = fs.readFileSync(file); var rd = read.toString(); // find import while ((m = regex.exec(rd)) !== null) { // This is necessary to avoid infinite loops with zero-width matches if (m.index === regex.lastIndex) { regex.lastIndex++; } // The result can be accessed through the `m`-variable. m.forEach((match, groupIndex) => { // only index 1 grup if (groupIndex == 1) { if (match === "*") { return; } if (match.match(".")) { match = match.split(".")[0]; } match = match.replace("OuterClass", ""); var found_rt = g_todump.find((j) => j.name === match); if (found_rt) { //found_maybe_related++; //console.log(`Skip ${match}`); } else { var subdata = new Object(); subdata["name"] = match; g_todump.push(subdata); } } }); } }); save_json(g_todump, file_gc_needed2); // This only applies to PacketOpcodes //console.log(g_todump); } //scan_gc(); clean_proto_gen(); //fix_packet(false); //cmdid_to_op(); //update_cmdid_gc(); //get_cmdid_gc(); //get_cmdid_json(); //check_gen();