diff --git a/Game/Genshin/Patch/HexUtility.cs b/Game/Genshin/Patch/HexUtility.cs new file mode 100644 index 0000000..f368700 --- /dev/null +++ b/Game/Genshin/Patch/HexUtility.cs @@ -0,0 +1,62 @@ +public class HexUtility +{ + public static bool EqualsBytes(byte[] b1, params byte[] b2) + { + if (b1.Length != b2.Length) + return false; + for (int i = 0; i < b1.Length; i++) + { + if (b1[i] != b2[i]) + return false; + } + return true; + } + + public static byte[] Replace(byte[] sourceByteArray, List replaces) + { + byte[] newByteArray = new byte[sourceByteArray.Length]; + Buffer.BlockCopy(sourceByteArray, 0, newByteArray, 0, sourceByteArray.Length); + int offset = 0; + foreach (HexReplaceEntity rep in replaces) + { + if (EqualsBytes(rep.oldValue, rep.newValue)) + { + continue; + } + + for (; offset < sourceByteArray.Length; offset++) + { + if (sourceByteArray[offset] == rep.oldValue[0]) + { + if (sourceByteArray.Length - offset < rep.oldValue.Length) + break; + + bool find = true; + for (int i = 1; i < rep.oldValue.Length - 1; i++) + { + if (sourceByteArray[offset + i] != rep.oldValue[i]) + { + find = false; + break; + } + } + if (find) + { + Buffer.BlockCopy(rep.newValue, 0, newByteArray, offset, rep.newValue.Length); + offset += (rep.newValue.Length - 1); + break; + } + } + } + } + return newByteArray; + } +} + +public class HexReplaceEntity +{ + public byte[] oldValue { get; set; } + + public byte[] newValue { get; set; } + +} \ No newline at end of file diff --git a/Game/Genshin/Patch/UserAssembly.cs b/Game/Genshin/Patch/UserAssembly.cs index ff74c8d..5efd863 100644 --- a/Game/Genshin/Patch/UserAssembly.cs +++ b/Game/Genshin/Patch/UserAssembly.cs @@ -1,5 +1,4 @@ using System.Text; -using YuukiPS_Launcher.patch; namespace YuukiPS_Launcher.Game.Genshin.Patch { @@ -11,30 +10,57 @@ public static class UserAssembly public static string Do(string original_file, string patch_file, string keynopatch, string keypatch) { + //Console.WriteLine("KeyNopatch" + "\n" + keynopatch); + //Console.WriteLine("KeyPatch" + "\n" + keypatch); + if (!File.Exists(original_file)) { return "UserAssembly file not found"; } - byte[] data = File.ReadAllBytes(original_file); - int count = 0; - string str; + byte[] UA_Original = Encoding.ASCII.GetBytes(keynopatch); + byte[] UA_key = Encoding.ASCII.GetBytes(keypatch); + + // Get Byte file original + byte[] UA = File.ReadAllBytes(original_file); - data = Methods.ReplaceBytes(data, ToUABytes(keynopatch), ToUABytes(keypatch), ref count); + int Offset = 0; + int DataLength; - if (count != 0) + List UA_list = new List(); + + while ((DataLength = UA_Original.Length - Offset) > 0) { - str = ""; - FileStream stream = File.Create(patch_file); - stream.Write(data, 0, data.Length); - stream.Close(); + if (DataLength > 8) + DataLength = 8; + + HexReplaceEntity hexReplaceEntity = new HexReplaceEntity(); + + hexReplaceEntity.oldValue = new byte[8]; + Buffer.BlockCopy(UA_Original, Offset, hexReplaceEntity.oldValue, 0, DataLength); + + hexReplaceEntity.newValue = new byte[8]; + Buffer.BlockCopy(UA_key, Offset, hexReplaceEntity.newValue, 0, DataLength); + + UA_list.Add(hexReplaceEntity); + Offset += DataLength; } - else + + byte[] UA_OS_patched = HexUtility.Replace(UA, UA_list); + + if (!HexUtility.EqualsBytes(UA, UA_OS_patched)) { - str = "Patch UserAssembly Failed"; + try + { + File.WriteAllBytes(patch_file, UA_OS_patched); + return ""; + } + catch (IOException e) + { + return e.Message + "\n Cannot write to file."; + } } - - return str; + return "Patch UserAssembly Failed"; } public static byte[] ToUABytes(string key) diff --git a/Json/GS.cs b/Json/GameClient/Cient.cs similarity index 95% rename from Json/GS.cs rename to Json/GameClient/Cient.cs index 16e44d8..2994dad 100644 --- a/Json/GS.cs +++ b/Json/GameClient/Cient.cs @@ -1,4 +1,4 @@ -namespace YuukiPS_Launcher.Json +namespace YuukiPS_Launcher.Json.GameClient { public class Data { @@ -27,7 +27,7 @@ public class DeprecatedPackage public class Diff { public string name { get; set; } - public string version { get; set; } + public string version { get; set; } = "0.0.0"; public string path { get; set; } public string size { get; set; } public string md5 { get; set; } @@ -72,7 +72,7 @@ public class Plugin2 public string entry { get; set; } } - public class GS + public class Cient { public int retcode { get; set; } public string message { get; set; } diff --git a/Json/GameClient/Patch.cs b/Json/GameClient/Patch.cs new file mode 100644 index 0000000..cbd1075 --- /dev/null +++ b/Json/GameClient/Patch.cs @@ -0,0 +1,56 @@ +namespace YuukiPS_Launcher.Json.GameClient +{ + public class Cn + { + public string userassembly { get; set; } + public string metadata { get; set; } + } + + public class KeyFind + { + public string cn { get; set; } + public string os { get; set; } + } + + public class Md5Check + { + public Os os { get; set; } + public Cn cn { get; set; } + } + + public class Md5Vaild + { + public string os { get; set; } + public string cn { get; set; } + } + + public class Original + { + public string resources { get; set; } + public KeyFind key_find { get; set; } + public Md5Check md5_check { get; set; } + } + + public class Os + { + public string userassembly { get; set; } + public string metadata { get; set; } + } + + public class Patched + { + public string metode { get; set; } + public string resources { get; set; } + public string key_patch { get; set; } + public Md5Vaild md5_vaild { get; set; } + } + + public class Patch + { + public string version { get; set; } = "0.0.0"; + public string channel { get; set; } = "Global"; + public string release { get; set; } = "Official"; + public Patched? patched { get; set; } + public Original? original { get; set; } + } +} diff --git a/Main.cs b/Main.cs index a8c58b8..0b18c78 100644 --- a/Main.cs +++ b/Main.cs @@ -4,6 +4,7 @@ using System.Net.NetworkInformation; using System.Reflection; using YuukiPS_Launcher.Json; +using YuukiPS_Launcher.Json.GameClient; using YuukiPS_Launcher.Yuuki; namespace YuukiPS_Launcher @@ -43,7 +44,8 @@ public partial class Main : Form // Game public Game.Genshin.Settings settings_genshin; - KeyGS key; + //KeyGS key; + Patch get_version; public void LoadConfig() { @@ -238,7 +240,7 @@ public bool CheckVersionGame() string Game_LOC_Original_MD5 = Tool.CalculateMD5(PathfileGame); // Check MD5 in Server API - VersionGenshin get_version = API.GetMD5VersionGS(Game_LOC_Original_MD5); + get_version = API.GetMD5Game(Game_LOC_Original_MD5); if (get_version == null) { //0.0.0 @@ -265,6 +267,9 @@ public bool CheckVersionGame() return false; } + var get_channel = get_version.channel; + var get_metode = get_version.patched.metode; + // Set Folder Patch Set_Metadata_Folder.Text = PathMetadata; Set_UA_Folder.Text = PathUA; @@ -275,21 +280,40 @@ public bool CheckVersionGame() // Set Version Get_LA_Version.Text = "Version: " + get_version.version; - Get_LA_CH.Text = "Channel: " + get_version.channel; + Get_LA_CH.Text = "Channel: " + get_channel; Get_LA_REL.Text = "Release: " + get_version.release; - Get_LA_Metode.Text = "Metode: " + get_version.metode; - Get_LA_MD5.Text = "MD5: " + get_version.md5; + Get_LA_Metode.Text = "Metode: " + get_metode; + + var md5_ori = "??"; // Pilih Metode - if (get_version.metode == "Metadata") + if (get_metode == "Metadata") { GameMetode = 1; + if (get_channel == "Chinese") + { + md5_ori = get_version.original.md5_check.cn.metadata; + } + if (get_channel == "Global") + { + md5_ori = get_version.original.md5_check.os.metadata; + } } - else if (get_version.metode == "UserAssembly") + else if (get_metode == "UserAssembly") { GameMetode = 2; + if (get_channel == "Chinese") + { + md5_ori = get_version.original.md5_check.cn.userassembly; + } + if (get_channel == "Global") + { + md5_ori = get_version.original.md5_check.os.userassembly; + } } + Get_LA_MD5.Text = "MD5: " + md5_ori; + Console.WriteLine("Currently using version game " + VersionGame); Console.WriteLine("Folder PathMetadata: " + PathMetadata); @@ -313,9 +337,9 @@ public string PatchGame(bool patchit = true, bool online = true, int metode = 1, return "No game folder found (2)"; } - if (key == null) + if (get_version == null) { - return "Can't find key, try clicking 'Get Key' in config tab"; + return "Can't find version, try clicking 'Get Key' in config tab"; } // Check version @@ -324,35 +348,53 @@ public string PatchGame(bool patchit = true, bool online = true, int metode = 1, return "This Game Version is not compatible with this method patch"; } + if (get_version.patched == null) + { + return "Can't find config patch cloud"; + } + + var use_metode = get_version.patched.metode; + var use_release = get_version.release; + // API string MD5_UA_API_Original; string MD5_UA_API_Patched; string MD5_Metadata_API_Original; string MD5_Metadata_API_Patched; - // Select CH - var cno = "Global"; - if (ch == 1) + + var key_to_patch = ""; + var key_to_find = ""; + + // Select Metode (via API Cloud) + //var cno = "Global"; + if (use_release == "Global") { - // Global - MD5_UA_API_Original = key.Original.UserAssembly.md5_os.ToUpper(); - MD5_UA_API_Patched = key.Patched.UserAssembly.md5_os.ToUpper(); - MD5_Metadata_API_Original = key.Original.MetaData.md5_os.ToUpper(); - MD5_Metadata_API_Patched = key.Patched.MetaData.md5_os.ToUpper(); + MD5_UA_API_Original = get_version.original.md5_check.os.userassembly.ToUpper(); + MD5_UA_API_Patched = get_version.patched.md5_vaild.os.ToUpper(); + + MD5_Metadata_API_Original = get_version.original.md5_check.os.metadata; + MD5_Metadata_API_Patched = get_version.patched.md5_vaild.os.ToUpper(); + + key_to_patch = get_version.patched.key_patch; + key_to_find = get_version.original.key_find.os; } - else if (ch == 2) + else if (use_release == "Chinese") { - // Chinese - MD5_UA_API_Original = key.Original.UserAssembly.md5_cn.ToUpper(); - MD5_UA_API_Patched = key.Patched.UserAssembly.md5_cn.ToUpper(); - MD5_Metadata_API_Original = key.Original.MetaData.md5_cn.ToUpper(); - MD5_Metadata_API_Patched = key.Patched.MetaData.md5_cn.ToUpper(); - cno = "Chinese"; + MD5_UA_API_Original = get_version.original.md5_check.cn.userassembly.ToUpper(); + MD5_UA_API_Patched = get_version.patched.md5_vaild.cn.ToUpper(); + + MD5_Metadata_API_Original = get_version.original.md5_check.cn.metadata; + MD5_Metadata_API_Patched = get_version.patched.md5_vaild.cn.ToUpper(); + + key_to_patch = get_version.patched.key_patch; + key_to_find = get_version.original.key_find.cn; } else { return "This Game Version is not compatible with Method Patch UserAssembly"; } - var DL_Patch = API.API_DL_OW + "api/public/dl/ZOrLF1E5/GenshinImpact/Data/PC/" + VersionGame + "/" + cno + "/Patch/"; + + var DL_Patch = API.API_DL_OW + "api/public/dl/ZOrLF1E5/GenshinImpact/Data/PC/" + VersionGame + "/" + use_metode + "/Patch/"; if (metode == 2) { @@ -571,16 +613,7 @@ public string PatchGame(bool patchit = true, bool online = true, int metode = 1, } } - var ManualUA = "???"; - // Select CH - if (ch == 1) - { - ManualUA = Game.Genshin.Patch.UserAssembly.Do(PathfileUA_Currently, PathfileUA_Patched, key.Original.MetaData.key2_os, key.Patched.UserAssembly.key2); - } - else if (ch == 2) - { - ManualUA = Game.Genshin.Patch.UserAssembly.Do(PathfileUA_Currently, PathfileUA_Patched, key.Original.MetaData.key2_cn, key.Patched.UserAssembly.key2); - } + var ManualUA = Game.Genshin.Patch.UserAssembly.Do(PathfileUA_Currently, PathfileUA_Patched, key_to_find, key_to_patch); if (!String.IsNullOrEmpty(ManualUA)) { return "Error Patch UserAssembly: " + ManualUA; @@ -870,11 +903,11 @@ public string PatchGame(bool patchit = true, bool online = true, int metode = 1, // Select CH if (ch == 1) { - ManualMetadata = Game.Genshin.Patch.Metadata.Do(PathfileMetadata_Currently, PathfileMetadata_Patched, key.Original.MetaData.key1, key.Patched.MetaData.key1, key.Original.MetaData.key2_os, key.Patched.MetaData.key2); + ManualMetadata = Game.Genshin.Patch.Metadata.Do(PathfileMetadata_Currently, PathfileMetadata_Patched, "ORIKEY1", "PATCHKEY1", "ORIKEY2", "PATCHKEY2"); } else if (ch == 2) { - ManualMetadata = Game.Genshin.Patch.Metadata.Do(PathfileMetadata_Currently, PathfileMetadata_Patched, key.Original.MetaData.key1, key.Patched.MetaData.key1, key.Original.MetaData.key2_cn, key.Patched.MetaData.key2); + ManualMetadata = Game.Genshin.Patch.Metadata.Do(PathfileMetadata_Currently, PathfileMetadata_Patched, "ORIKEY1", "PATCHKEY1", "ORIKEY2", "PATCHKEY2"); } if (!String.IsNullOrEmpty(ManualMetadata)) { @@ -1745,22 +1778,22 @@ private void bt_GetKey_Click(object sender, EventArgs e) public string UpdateKey() { - key = API.GSKEY(); - if (key == null) + //key = API.GSKEY(); + if (get_version == null) { return "Maybe your internet has problems or there is an active proxy"; } else { //MA - DEV_MA_Set_Key1_NoPatch.Text = key.Original.MetaData.key1; - DEV_MA_Set_Key2_NoPatch.Text = key.Original.MetaData.key2_os; - DEV_MA_Set_Key1_Patch.Text = key.Patched.MetaData.key1; - DEV_MA_Set_Key2_Patch.Text = key.Patched.MetaData.key2; + DEV_MA_Set_Key1_NoPatch.Text = ""; + DEV_MA_Set_Key2_NoPatch.Text = ""; + DEV_MA_Set_Key1_Patch.Text = ""; + DEV_MA_Set_Key2_Patch.Text = ""; //UA - DEV_UA_Set_Key1_NoPatch.Text = key.Original.MetaData.key2_os; - DEV_UA_Set_Key2_Patch.Text = key.Patched.UserAssembly.key2; + DEV_UA_Set_Key1_NoPatch.Text = get_version.original.key_find.os; + DEV_UA_Set_Key2_Patch.Text = get_version.patched.key_patch; } return "Successfully got Key, you can see update in developer tab"; } diff --git a/Yuuki/API.cs b/Yuuki/API.cs index b58c22b..b2c1af1 100644 --- a/Yuuki/API.cs +++ b/Yuuki/API.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Net; using YuukiPS_Launcher.Json; +using YuukiPS_Launcher.Json.GameClient; namespace YuukiPS_Launcher.Yuuki { @@ -14,17 +15,17 @@ public class API public static string API_GITHUB_YuukiPS = "https://api.github.com/repos/akbaryahya/YuukiPS-Launcher/"; public static string API_GITHUB_Akebi = "https://api.github.com/repos/Taiga74164/Akebi-GC/"; - public static GS GS_DL(string dl = "os") + public static Cient GS_DL(string dl = "os") { var client = new RestClient(API_DL_WB); var request = new RestRequest("genshin/download/latest/" + dl); var response = client.Execute(request); var getme = response.StatusCode == HttpStatusCode.OK ? response.Content : response.StatusCode.ToString(); - return JsonConvert.DeserializeObject(getme); + return JsonConvert.DeserializeObject(getme); } - public static VersionGenshin? GetMD5VersionGS(string md5) + public static VersionGenshin GetMD5VersionGS(string md5) { var client = new RestClient(API_DL_WB); var request = new RestRequest("genshin/version?md5=" + md5.ToUpper()); @@ -55,6 +56,37 @@ public static GS GS_DL(string dl = "os") return null; } + public static Patch GetMD5Game(string md5) + { + var client = new RestClient(API_DL_WB); + var request = new RestRequest("genshin/patch/" + md5.ToUpper()); + + var response = client.Execute(request); + if (response.StatusCode == HttpStatusCode.OK) + { + try + { + if (response.Content != null) + { + var tes = JsonConvert.DeserializeObject(response.Content); + if (tes != null) + { + return tes; + } + } + } + catch (Exception ex) + { + Console.WriteLine("Error: ", ex); + } + } + else + { + Console.WriteLine("Error: " + response.StatusCode); + } + return null; + } + public static KeyGS? GSKEY() { var client = new RestClient(API_DL_WB); diff --git a/YuukiPS Launcher.csproj b/YuukiPS Launcher.csproj index ef1c58b..adc4036 100644 --- a/YuukiPS Launcher.csproj +++ b/YuukiPS Launcher.csproj @@ -12,8 +12,8 @@ Properties\app.manifest - 2022.10.31.1510 - 2022.10.31.1510 + 2022.11.2.0608 + 2022.11.2.0608 true YuukiPS