diff --git a/CheatEnabler/CheatEnabler.csproj b/CheatEnabler/CheatEnabler.csproj index 69e9706..00b179c 100644 --- a/CheatEnabler/CheatEnabler.csproj +++ b/CheatEnabler/CheatEnabler.csproj @@ -5,7 +5,7 @@ net472 org.soardev.cheatenabler DSP MOD - CheatEnabler - 2.3.7 + 2.3.8 true latest CheatEnabler diff --git a/CheatEnabler/FactoryPatch.cs b/CheatEnabler/FactoryPatch.cs index 349a4b4..0a248f4 100644 --- a/CheatEnabler/FactoryPatch.cs +++ b/CheatEnabler/FactoryPatch.cs @@ -79,7 +79,7 @@ public static class FactoryPatch { var imm = ImmediateEnabled.Value; var architect = ArchitectModeEnabled.Value; - if (!imm && !architect) return; + if ((!imm && !architect) || GameMain.gameScenario == null) return; var prebuilds = factory.prebuildPool; if (imm) factory.BeginFlattenTerrain(); for (var i = factory.prebuildCursor - 1; i > 0; i--) diff --git a/CheatEnabler/README.md b/CheatEnabler/README.md index 9bbc9b7..6613a8b 100644 --- a/CheatEnabler/README.md +++ b/CheatEnabler/README.md @@ -4,6 +4,9 @@ #### 添加一些作弊功能,同时屏蔽异常检测 ## Changlog +* 2.3.8 + + Fix a crash on starting new games while `Finish build immediately` is enabled. + + Fix UI button width. * 2.3.7 + Support game version 0.10.28.20759 + Fix belt signal that items' generation speed is not fit to number set sometimes. @@ -115,6 +118,9 @@ * [Multifunction_mod](https://github.com/blacksnipebiu/Multifunction_mod): Some cheat functions ## 更新日志 +* 2.3.8 + + 修复了启用`建造秒完成`时开新游戏可能导致崩溃的问题 + + 修复了UI按钮宽度 * 2.3.7 + 支持游戏版本0.10.28.20759 + 修复了传送带信号有时候物品生成速度和设置不匹配的问题 diff --git a/CheatEnabler/UIConfigWindow.cs b/CheatEnabler/UIConfigWindow.cs index bf7cd96..cebdc6c 100644 --- a/CheatEnabler/UIConfigWindow.cs +++ b/CheatEnabler/UIConfigWindow.cs @@ -136,11 +136,11 @@ public static class UIConfigWindow MyCheckBox.CreateCheckBox(x, y, tab3, PlanetPatch.TerraformAnywayEnabled, "Terraform without enough sands"); x = 400f; y = 10f; - wnd.AddButton(x, y, tab3, "矿物掩埋标题", 16, "button-bury-all", () => { PlanetFunctions.BuryAllVeins(true); }); + wnd.AddButton(x, y, 200f, tab3, "矿物掩埋标题", 16, "button-bury-all", () => { PlanetFunctions.BuryAllVeins(true); }); y += 36f; - wnd.AddButton(x, y, tab3, "矿物还原标题", 16, "button-bury-restore-all", () => { PlanetFunctions.BuryAllVeins(false); }); + wnd.AddButton(x, y, 200f, tab3, "矿物还原标题", 16, "button-bury-restore-all", () => { PlanetFunctions.BuryAllVeins(false); }); y += 36f; - wnd.AddButton(x, y, tab3, "铺满地基提示", 16, "button-reform-all", () => + wnd.AddButton(x, y, 200f, tab3, "铺满地基提示", 16, "button-reform-all", () => { var player = GameMain.mainPlayer; if (player == null) return; @@ -150,7 +150,7 @@ public static class UIConfigWindow GameMain.localPlanet.factory.PlanetReformAll(reformTool.brushType, reformTool.brushColor, reformTool.buryVeins); }); y += 36f; - wnd.AddButton(x, y, tab3, "还原地形提示", 16, "button-reform-revert-all", () => + wnd.AddButton(x, y, 200f, tab3, "还原地形提示", 16, "button-reform-revert-all", () => { var factory = GameMain.localPlanet?.factory; if (factory == null) return; diff --git a/CheatEnabler/package/manifest.json b/CheatEnabler/package/manifest.json index baab843..89f0086 100644 --- a/CheatEnabler/package/manifest.json +++ b/CheatEnabler/package/manifest.json @@ -1,6 +1,6 @@ { "name": "CheatEnabler", - "version_number": "2.3.7", + "version_number": "2.3.8", "website_url": "https://github.com/soarqin/DSP_Mods/tree/master/CheatEnabler", "description": "Add various cheat functions while disabling abnormal determinants / 添加一些作弊功能,同时屏蔽异常检测", "dependencies": [ diff --git a/CompressSave/CompressSave.csproj b/CompressSave/CompressSave.csproj index ea3e9d5..eac343c 100644 --- a/CompressSave/CompressSave.csproj +++ b/CompressSave/CompressSave.csproj @@ -5,7 +5,7 @@ CompressSave org.soardev.compresssave DSP MOD - CompressSave - 1.3.4 + 1.3.5 true latest net472 diff --git a/CompressSave/I18N.cs b/CompressSave/I18N.cs index 150388c..eaa43cb 100644 --- a/CompressSave/I18N.cs +++ b/CompressSave/I18N.cs @@ -1,15 +1,11 @@ using System; using System.Collections.Generic; -using System.Linq; using HarmonyLib; -namespace CompressSave; - public static class I18N { private static bool _initialized; - - public static Action OnInitialized; + private static bool _dirty; public static void Init() { @@ -17,88 +13,116 @@ public static class I18N } public static bool Initialized() => _initialized; - private struct Translation - { - public string Key; - public string English; - public string Chinese; - } - private static readonly List StringsToAdd = []; + private static readonly List> Keys = []; + private static readonly Dictionary> Strings = []; + public static void Add(string key, string enus, string zhcn = null) { if (zhcn == null && key == enus) return; - var strProto = new Translation + Keys.Add(Tuple.Create(key, enus, -1)); + if (Strings.TryGetValue(2052, out var zhcnList)) { - Key = key, - English = enus, - Chinese = string.IsNullOrEmpty(zhcn) ? enus : zhcn - }; - StringsToAdd.Add(strProto); + zhcnList.Add(string.IsNullOrEmpty(zhcn) ? enus : zhcn); + } + else + { + Strings.Add(2052, [string.IsNullOrEmpty(zhcn) ? enus : zhcn]); + } + _dirty = true; + } + + private static void ApplyIndexers() + { + var indexer = Localization.namesIndexer; + var index = indexer.Count; + var len = Keys.Count; + for (var i = 0; i < len; i++) + { + var (key, def, value) = Keys[i]; + if (value >= 0) continue; + if (indexer.TryGetValue(key, out var idx)) + { + Keys[i] = Tuple.Create(key, def, idx); + continue; + } + indexer[key] = index; + Keys[i] = Tuple.Create(key, def, index); + index++; + } + _dirty = false; + var strings = Localization.strings; + if (strings == null) return; + var len2 = strings.Length; + for (var i = 0; i < len2; i++) + { + ApplyLanguage(i); + if (i != Localization.currentLanguageIndex) continue; + Localization.currentStrings = Localization.strings[i]; + Localization.currentFloats = Localization.floats[i]; + } + } + + private static void ApplyLanguage(int index) + { + var indexerLength = Localization.namesIndexer.Count; + var strs = Localization.strings[index]; + if (strs == null) return; + if (strs.Length < indexerLength) + { + var newStrs = new string[indexerLength]; + Array.Copy(strs, newStrs, strs.Length); + strs = newStrs; + Localization.strings[index] = strs; + } + var floats = Localization.floats[index]; + if (floats != null) + { + if (floats.Length < indexerLength) + { + var newFloats = new float[indexerLength]; + Array.Copy(floats, newFloats, floats.Length); + floats = newFloats; + Localization.floats[index] = floats; + } + } + + var keyLength = Keys.Count; + if (Strings.TryGetValue(Localization.Languages[index].lcId, out var list)) + { + for (var j = 0; j < keyLength; j++) + { + strs[Keys[j].Item3] = list[j]; + } + } + else + { + for (var j = 0; j < keyLength; j++) + { + strs[Keys[j].Item3] = Keys[j].Item2; + } + } } public static void Apply() { if (!_initialized) return; - var indexer = Localization.namesIndexer; - var enIdx = -1; - var zhIdx = -1; - var llen = 0; - for (var i = 0; i < Localization.strings.Length; i++) - { - switch (Localization.Languages[i].lcId) - { - case Localization.LCID_ENUS: - if (!Localization.LanguageLoaded(i) && Localization.Loaded) - { - Localization.LoadLanguage(i); - } - enIdx = i; - break; - case Localization.LCID_ZHCN: - if (!Localization.LanguageLoaded(i) && Localization.Loaded) - { - Localization.LoadLanguage(i); - } - zhIdx = i; - llen = Localization.strings[i].Length; - break; - } - } - var enus = new string[StringsToAdd.Count]; - var zhcn = new string[StringsToAdd.Count]; - for (var i = 0; i < StringsToAdd.Count; i++) - { - var str = StringsToAdd[i]; - enus[i] = str.English; - zhcn[i] = str.Chinese; - indexer[str.Key] = llen + i; - } - - Localization.strings[enIdx] = Localization.strings[enIdx].Concat(enus).ToArray(); - if (enIdx == Localization.currentLanguageIndex) - { - Localization.currentStrings = Localization.strings[enIdx]; - } - Localization.strings[zhIdx] = Localization.strings[zhIdx].Concat(zhcn).ToArray(); - if (zhIdx == Localization.currentLanguageIndex) - { - Localization.currentStrings = Localization.strings[zhIdx]; - } - StringsToAdd.Clear(); + if (Keys.Count == 0) return; + if (!_dirty) return; + ApplyIndexers(); } - [HarmonyPostfix, HarmonyPriority(Priority.Last), HarmonyPatch(typeof(VFPreload), "InvokeOnLoadWorkEnded")] - private static void VFPreload_InvokeOnLoadWorkEnded_Postfix() + [HarmonyPostfix, HarmonyPriority(Priority.Last), HarmonyPatch(typeof(Localization), nameof(Localization.LoadSettings))] + private static void Localization_LoadSettings_Postfix() { if (_initialized) return; _initialized = true; - if (StringsToAdd.Count == 0) - { - OnInitialized?.Invoke(); - return; - } - Apply(); - OnInitialized?.Invoke(); + } + + [HarmonyPostfix, HarmonyPriority(Priority.Last), HarmonyPatch(typeof(Localization), nameof(Localization.LoadLanguage))] + private static void Localization_LoadLanguage_Postfix(int index) + { + if (!_initialized) return; + ApplyLanguage(index); } } \ No newline at end of file diff --git a/CompressSave/README.md b/CompressSave/README.md index 2ca2342..86f84de 100644 --- a/CompressSave/README.md +++ b/CompressSave/README.md @@ -7,6 +7,9 @@ ## Changelog +### 1.3.5 +* Fix a crash issue on choosing language other than English and Chinese. + ### 1.3.4 * Support for game version 0.10.28.20759. @@ -140,6 +143,9 @@ ## 更新日志 +### 1.3.5 +* 修复了选择英文和中文以外的语言时的崩溃问题。 + ### 1.3.4 * 支持游戏版本 0.10.28.20759。 diff --git a/CompressSave/package/manifest.json b/CompressSave/package/manifest.json index d4dba01..a7515b3 100644 --- a/CompressSave/package/manifest.json +++ b/CompressSave/package/manifest.json @@ -1,6 +1,6 @@ { "name": "CompressSave", - "version_number": "1.3.4", + "version_number": "1.3.5", "website_url": "https://github.com/soarqin/DSP_Mods/tree/master/CompressSave", "description": "Compress game saves to reduce space use and boost save speed / 压缩游戏存档以降低空间使用并提升保存速度", "dependencies": ["xiaoye97-BepInEx-5.4.17"] diff --git a/UXAssist/Common/I18N.cs b/UXAssist/Common/I18N.cs index c031551..efd833f 100644 --- a/UXAssist/Common/I18N.cs +++ b/UXAssist/Common/I18N.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using HarmonyLib; namespace UXAssist.Common; @@ -8,6 +7,7 @@ namespace UXAssist.Common; public static class I18N { private static bool _initialized; + private static bool _dirty; public static Action OnInitialized; @@ -17,88 +17,123 @@ public static class I18N } public static bool Initialized() => _initialized; - private struct Translation - { - public string Key; - public string English; - public string Chinese; - } - private static readonly List StringsToAdd = []; + private static readonly List> Keys = []; + private static readonly Dictionary> Strings = []; + public static void Add(string key, string enus, string zhcn = null) { if (zhcn == null && key == enus) return; - var strProto = new Translation + Keys.Add(Tuple.Create(key, enus, -1)); + if (Strings.TryGetValue(2052, out var zhcnList)) { - Key = key, - English = enus, - Chinese = string.IsNullOrEmpty(zhcn) ? enus : zhcn - }; - StringsToAdd.Add(strProto); + zhcnList.Add(string.IsNullOrEmpty(zhcn) ? enus : zhcn); + } + else + { + Strings.Add(2052, [string.IsNullOrEmpty(zhcn) ? enus : zhcn]); + } + _dirty = true; + } + + private static void ApplyIndexers() + { + var indexer = Localization.namesIndexer; + var index = indexer.Count; + var len = Keys.Count; + for (var i = 0; i < len; i++) + { + var (key, def, value) = Keys[i]; + if (value >= 0) continue; + if (indexer.TryGetValue(key, out var idx)) + { + Keys[i] = Tuple.Create(key, def, idx); + continue; + } + indexer[key] = index; + Keys[i] = Tuple.Create(key, def, index); + index++; + } + _dirty = false; + var strings = Localization.strings; + if (strings == null) return; + var len2 = strings.Length; + for (var i = 0; i < len2; i++) + { + ApplyLanguage(i); + if (i != Localization.currentLanguageIndex) continue; + Localization.currentStrings = Localization.strings[i]; + Localization.currentFloats = Localization.floats[i]; + } + } + + private static void ApplyLanguage(int index) + { + var indexerLength = Localization.namesIndexer.Count; + var strs = Localization.strings[index]; + if (strs == null) return; + if (strs.Length < indexerLength) + { + var newStrs = new string[indexerLength]; + Array.Copy(strs, newStrs, strs.Length); + strs = newStrs; + Localization.strings[index] = strs; + } + var floats = Localization.floats[index]; + if (floats != null) + { + if (floats.Length < indexerLength) + { + var newFloats = new float[indexerLength]; + Array.Copy(floats, newFloats, floats.Length); + floats = newFloats; + Localization.floats[index] = floats; + } + } + + var keyLength = Keys.Count; + if (Strings.TryGetValue(Localization.Languages[index].lcId, out var list)) + { + for (var j = 0; j < keyLength; j++) + { + strs[Keys[j].Item3] = list[j]; + } + } + else + { + for (var j = 0; j < keyLength; j++) + { + strs[Keys[j].Item3] = Keys[j].Item2; + } + } } public static void Apply() { if (!_initialized) return; - var indexer = Localization.namesIndexer; - var enIdx = -1; - var zhIdx = -1; - var llen = 0; - for (var i = 0; i < Localization.strings.Length; i++) - { - switch (Localization.Languages[i].lcId) - { - case Localization.LCID_ENUS: - if (!Localization.LanguageLoaded(i) && Localization.Loaded) - { - Localization.LoadLanguage(i); - } - enIdx = i; - break; - case Localization.LCID_ZHCN: - if (!Localization.LanguageLoaded(i) && Localization.Loaded) - { - Localization.LoadLanguage(i); - } - zhIdx = i; - llen = Localization.strings[i].Length; - break; - } - } - var enus = new string[StringsToAdd.Count]; - var zhcn = new string[StringsToAdd.Count]; - for (var i = 0; i < StringsToAdd.Count; i++) - { - var str = StringsToAdd[i]; - enus[i] = str.English; - zhcn[i] = str.Chinese; - indexer[str.Key] = llen + i; - } - - Localization.strings[enIdx] = Localization.strings[enIdx].Concat(enus).ToArray(); - if (enIdx == Localization.currentLanguageIndex) - { - Localization.currentStrings = Localization.strings[enIdx]; - } - Localization.strings[zhIdx] = Localization.strings[zhIdx].Concat(zhcn).ToArray(); - if (zhIdx == Localization.currentLanguageIndex) - { - Localization.currentStrings = Localization.strings[zhIdx]; - } - StringsToAdd.Clear(); + if (Keys.Count == 0) return; + if (!_dirty) return; + ApplyIndexers(); } - [HarmonyPostfix, HarmonyPriority(Priority.Last), HarmonyPatch(typeof(VFPreload), "InvokeOnLoadWorkEnded")] - private static void VFPreload_InvokeOnLoadWorkEnded_Postfix() + [HarmonyPostfix, HarmonyPriority(Priority.Last), HarmonyPatch(typeof(Localization), nameof(Localization.LoadSettings))] + private static void Localization_LoadSettings_Postfix() { if (_initialized) return; _initialized = true; - if (StringsToAdd.Count == 0) - { - OnInitialized?.Invoke(); - return; - } - Apply(); + } + + [HarmonyPostfix, HarmonyPriority(Priority.Last), HarmonyPatch(typeof(Localization), nameof(Localization.LoadLanguage))] + private static void Localization_LoadLanguage_Postfix(int index) + { + if (!_initialized) return; + ApplyLanguage(index); + } + + [HarmonyPostfix, HarmonyPriority(Priority.Last), HarmonyPatch(typeof(Localization), nameof(Localization.NotifyLanguageChange))] + private static void Localization_NotifyLanguageChange_Postfix() + { + if (!_initialized) return; OnInitialized?.Invoke(); } } \ No newline at end of file diff --git a/UXAssist/GamePatch.cs b/UXAssist/GamePatch.cs index 7499907..c3f6107 100644 --- a/UXAssist/GamePatch.cs +++ b/UXAssist/GamePatch.cs @@ -181,6 +181,7 @@ public static class GamePatch private static class ConvertSavesFromPeace { private static Harmony _patch; + private static bool _needConvert; public static void Enable(bool on) { if (on) @@ -192,24 +193,37 @@ public static class GamePatch _patch = null; } - [HarmonyTranspiler] + [HarmonyPostfix] [HarmonyPatch(typeof(GameDesc), nameof(GameDesc.Import))] - private static IEnumerable GameDesc_Import_Transpiler(IEnumerable instructions, ILGenerator generator) + private static void GameDesc_Import_Postfix(GameDesc __instance) + { + if (DSPGame.IsMenuDemo || !__instance.isPeaceMode) return; + __instance.combatSettings = UIRoot.instance.galaxySelect.uiCombat.combatSettings; + __instance.isPeaceMode = false; + _needConvert = true; + } + + [HarmonyTranspiler] + [HarmonyPatch(typeof(GameData), nameof(GameData.Import))] + private static IEnumerable GameData_Import_Transpiler(IEnumerable instructions, ILGenerator generator) { var matcher = new CodeMatcher(instructions, generator); - matcher.MatchForward(false, - new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(CombatSettings), nameof(CombatSettings.SetDefault))) - ).Advance(-1).RemoveInstructions(2).Insert( - new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(UIRoot), nameof(UIRoot.instance))), - new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(UIRoot), nameof(UIRoot.galaxySelect))), - new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(UIGalaxySelect), nameof(UIGalaxySelect.uiCombat))), - new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(UICombatSettingsDF), nameof(UICombatSettingsDF.combatSettings))), - new CodeInstruction(OpCodes.Stfld, AccessTools.Field(typeof(GameDesc), nameof(GameDesc.combatSettings))), - new CodeInstruction(OpCodes.Ldarg_0), - new CodeInstruction(OpCodes.Ldc_I4_0), - new CodeInstruction(OpCodes.Stfld, AccessTools.Field(typeof(GameDesc), nameof(GameDesc.isPeaceMode))) + matcher.Start().MatchForward(false, + new CodeMatch(instr => (instr.opcode == OpCodes.Ldc_I4 || instr.opcode == OpCodes.Ldc_I4_S) && instr.OperandIs(0x1B)), + new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(PerformanceMonitor), nameof(PerformanceMonitor.EndData))) + ); + matcher.Advance(2).Opcode = OpCodes.Brfalse; + matcher.Insert( + new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(ConvertSavesFromPeace), nameof(ConvertSavesFromPeace._needConvert))) ); return matcher.InstructionEnumeration(); } + + [HarmonyPostfix] + [HarmonyPatch(typeof(GameData), nameof(GameData.Import))] + private static void GameData_Import_Postfix() + { + _needConvert = false; + } } } \ No newline at end of file diff --git a/UXAssist/README.md b/UXAssist/README.md index c8e613e..84e46e7 100644 --- a/UXAssist/README.md +++ b/UXAssist/README.md @@ -4,8 +4,11 @@ #### 一些提升用户体验的功能和补丁 ## Changlog +* 1.0.7 + + Fix a crash issue on choosing language other than English and Chinese + + Games saved in Peace-Mode after Dark-Forg update can also be loaded as Combat-Mode now. * 1.0.6 - + Convert old saves to Combat Mode on loading + + Convert old saves to Combat-Mode on loading * 1.0.5 + Support game version 0.10.28.20759 + Sort blueprint structures before saving, to reduce generated blueprint data size a little. @@ -42,7 +45,7 @@ + General - Enable game window resize - Remember window position and size on last exit - - Convert old saves to Combat Mode on loading + - Convert Peace-Mode saves to Combat-Mode on loading + Planet/Factory - Unlimited interactive range - Sunlight at night @@ -73,6 +76,9 @@ * [OffGridConstruction](https://github.com/Velociraptor115-DSPModding/OffGridConstruction): Off-grid building & stepped rotation implementations ## 更新日志 +* 1.0.7 + + 修复了选择英文和中文以外的语言时的崩溃问题 + + 黑雾更新后使用和平模式保存的存档现在也可以转换为战斗模式了 * 1.0.6 + 在加载旧存档时将其转换为战斗模式 * 1.0.5 @@ -111,7 +117,7 @@ + 通用 - 可调整游戏窗口大小(可最大化和拖动边框) - 记住上次退出时的窗口位置和大小 - - 在加载旧存档时将其转换为战斗模式 + - 在加载和平模式存档时将其转换为战斗模式 + 行星/工厂 - 无限交互距离 - 夜间日光灯 diff --git a/UXAssist/UXAssist.csproj b/UXAssist/UXAssist.csproj index c9674af..0a7a75c 100644 --- a/UXAssist/UXAssist.csproj +++ b/UXAssist/UXAssist.csproj @@ -4,7 +4,7 @@ net472 org.soardev.uxassist DSP MOD - UXAssist - 1.0.6 + 1.0.7 true latest UXAssist diff --git a/UXAssist/package/manifest.json b/UXAssist/package/manifest.json index b6fa470..96b00be 100644 --- a/UXAssist/package/manifest.json +++ b/UXAssist/package/manifest.json @@ -1,6 +1,6 @@ { "name": "UXAssist", - "version_number": "1.0.6", + "version_number": "1.0.7", "website_url": "https://github.com/soarqin/DSP_Mods/tree/master/UXAssist", "description": "Some functions and patches for better user experience / 一些提升用户体验的功能和补丁", "dependencies": [