diff --git a/LabOpt/Functions.cs b/LabOpt/Functions.cs index 4e8af34..206501f 100644 --- a/LabOpt/Functions.cs +++ b/LabOpt/Functions.cs @@ -538,4 +538,27 @@ public static class LabOptPatchFunctions } return 0; } + + public static int PickFromLab(PlanetFactory factory, int labId, int filter, int[] needs) + { + var factorySystem = factory.factorySystem; + var products = factorySystem.labPool[labId].products; + if (products == null) return 0; + var produced = factorySystem.labPool[labId].produced; + if (produced == null) return 0; + lock (produced) + { + for (var j = 0; j < products.Length; j++) + { + if (produced[j] <= 0 || products[j] <= 0 || + (filter != 0 && filter != products[j]) || + (needs != null && needs[0] != products[j] && needs[1] != products[j] && + needs[2] != products[j] && needs[3] != products[j] && + needs[4] != products[j] && needs[5] != products[j])) continue; + produced[j]--; + return products[j]; + } + } + return 0; + } } diff --git a/LabOpt/LabOpt.cs b/LabOpt/LabOpt.cs index c0e6a0d..7f34bb8 100644 --- a/LabOpt/LabOpt.cs +++ b/LabOpt/LabOpt.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Reflection.Emit; -using System.Threading; using BepInEx; using HarmonyLib; @@ -144,11 +143,18 @@ public class LabOptPatch : BaseUnityPlugin } // Set rootLabId for LabComponent after loading game-save - [HarmonyPostfix] + [HarmonyTranspiler] [HarmonyPatch(typeof(FactorySystem), nameof(FactorySystem.Import))] - private static void FactorySystem_Import_Postfix(FactorySystem __instance) + private static IEnumerable FactorySystem_Import_Transpiler(IEnumerable instructions, ILGenerator generator) { - LabOptPatchFunctions.SetRootLabIdOnLoading(__instance); + var matcher = new CodeMatcher(instructions, generator); + matcher.End().MatchForward(false, + new CodeMatch(OpCodes.Ret) + ).Insert( + new CodeInstruction(OpCodes.Ldarg_0), + new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(LabOptPatchFunctions), nameof(LabOptPatchFunctions.SetRootLabIdOnLoading))) + ); + return matcher.InstructionEnumeration(); } // Redirect call of LabComponent.InternalUpdateAssemble() to InternalUpdateAssembleNew() @@ -269,24 +275,12 @@ public class LabOptPatch : BaseUnityPlugin return matcher.InstructionEnumeration(); } - // Change locks on PlanetFactory.InsertInto() + // Change locks on PlanetFactory.InsertInto(), by calling LabOptPatchFunctions.InsertIntoLab() [HarmonyTranspiler] [HarmonyPatch(typeof(PlanetFactory), nameof(PlanetFactory.InsertInto))] private static IEnumerable PlanetFactory_InsertInto_Transpiler(IEnumerable instructions, ILGenerator generator) { var matcher = new CodeMatcher(instructions, generator); - /* Remove following codes: - 465 0427 ldarg.0 - 466 0428 ldfld class Mutex[] PlanetFactory::entityMutexs - 467 042D ldarg.1 - 468 042E ldelem.ref - 469 042F stloc.s V_10 (10) - 470 0431 ldc.i4.0 - 471 0432 stloc.s V_11 (11) - 472 0434 ldloc.s V_10 (10) - 473 0436 ldloca.s V_11 (11) - 474 0438 call void [netstandard]System.Threading.Monitor::Enter(object, bool&) - */ matcher.MatchForward(false, new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(EntityData), nameof(EntityData.labId))) ).Advance(1).MatchForward(false, @@ -307,4 +301,29 @@ public class LabOptPatch : BaseUnityPlugin matcher.Instruction.labels.Clear(); return matcher.InstructionEnumeration(); } + + // Change locks on PlanetFactory.PickFrom(), by calling LabOptPatchFunctions.PickFromLab() + [HarmonyTranspiler] + [HarmonyPatch(typeof(PlanetFactory), nameof(PlanetFactory.PickFrom))] + private static IEnumerable PlanetFactory_PickFrom_Transpiler(IEnumerable instructions, ILGenerator generator) + { + var matcher = new CodeMatcher(instructions, generator); + matcher.MatchForward(false, + new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(EntityData), nameof(EntityData.labId))) + ).Advance(1).MatchForward(false, + new CodeMatch(OpCodes.Ble) + ).Advance(1); + var labels = matcher.Instruction.labels; + matcher.InsertAndAdvance( + new CodeInstruction(OpCodes.Ldarg_0).WithLabels(labels), + new CodeInstruction(OpCodes.Ldloc_S, 7), + new CodeInstruction(OpCodes.Ldarg_3), + new CodeInstruction(OpCodes.Ldarg_S, 4), + new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(LabOptPatchFunctions), nameof(LabOptPatchFunctions.PickFromLab))), + new CodeInstruction(OpCodes.Ret) + ); + matcher.Instruction.labels.Clear(); + return matcher.InstructionEnumeration(); + } + } diff --git a/LabOpt/LabOpt.csproj b/LabOpt/LabOpt.csproj index ea5ec4d..96b50de 100644 --- a/LabOpt/LabOpt.csproj +++ b/LabOpt/LabOpt.csproj @@ -5,7 +5,7 @@ LabOpt org.soardev.labopt DSP MOD - LabOpt - 0.3.2 + 0.3.3 true latest diff --git a/LabOpt/README.md b/LabOpt/README.md index dadc949..013ae21 100644 --- a/LabOpt/README.md +++ b/LabOpt/README.md @@ -1,4 +1,50 @@ -# HideTips +# LabOpt -#### Optimize Lab performance +#### Performance optimizations for Matrix Labs #### 优化研究站性能 + +## Updates +* 0.3.3 + * Add a lock to `PlanetFactory.PickFrom()` to avoid thread-conflicts. +* 0.3.2 + * Separate large block locks into small locks to improve performance. +* 0.3.1 + * Add some locks to avoid thread-conflicts. +* 0.3.0 + * Reverse changes of 0.2.0, and rewrite most of codes to make better performance with less patches. +* 0.2.0 + * New mechanism to update `LabComponent.needs()`. +* 0.1.0 + * Initial release. + +## Features +* Greatly reduce CPU usage of Matrix Labs without changing gameplay logic. +* Discard some calls on Matrix Labs that are stacked on others. + * Only keep calls of manufacturing and researching. +* All materials and products are stored in the base level of Matrix Labs. + * Thus this MOD discards all item pulling up and down actions. +* Manufacturing and researching uses items from base level and output to base level directly. +* UI on Matrix Labs shows count of items in base level always, but displays working progress for current level. +* Insert into or pick from any level of Matrix Labs apply to base level actually. +* Increased capacity input and output of Matrix Labs to 15 and 30, to avoid lack of supply or output jam. + +## Known issue +* In researching mode, you will find the progress circle runs faster on stacked Labs + * This is normal due to mechanism of calculation, it does not change the real consumptions and output hashes. + * Progress speed is multiplied by stacked levels indeed. + +## 功能 +* 在不改变游戏基础逻辑的前提下,大幅降低研究站的CPU消耗 +* 去除非底层研究站的许多调用 + * 只保留制造和研发的函数调用 +* 所有物品都存储在研究站的底层 + * 因此该MOD去除了所有的物品上下传输 +* 制造和研发使用底层的物品并将产物直接送到底层 +* 研究站的UI始终显示底层的物品数量,但显示当前层的工作进度 +* 向任意层放入或取出物品实际上都是对底层的操作 +* 增加研究站的输入和输出容量到15和30,以避免输入供应不足和输出堵塞 + +## 已知问题 +* 在研发模式下,你会发现堆叠研究站的进度圈运行得更快 + * 这是正常的,因为计算机制的原因,它并不会改变真实的消耗和产出 + * 进度速度实际上是乘了堆叠层数 diff --git a/LabOpt/package/icon.png b/LabOpt/package/icon.png index 6dcdb55..e556b1b 100644 Binary files a/LabOpt/package/icon.png and b/LabOpt/package/icon.png differ diff --git a/LabOpt/package/manifest.json b/LabOpt/package/manifest.json index c89d504..bf80b04 100644 --- a/LabOpt/package/manifest.json +++ b/LabOpt/package/manifest.json @@ -1,6 +1,6 @@ { "name": "LabOpt", - "version_number": "0.3.2", + "version_number": "0.3.3", "website_url": "https://github.com/soarqin/DSP_Mods/tree/master/LabOpt", "description": "Optimize Lab performance / 优化研究站性能", "dependencies": [ diff --git a/LabOptPreloader/README.md b/LabOptPreloader/README.md index dadc949..314a867 100644 --- a/LabOptPreloader/README.md +++ b/LabOptPreloader/README.md @@ -1,4 +1,3 @@ -# HideTips +# LabOptPreloader -#### Optimize Lab performance -#### 优化研究站性能 +#### Preloader for LabOpt diff --git a/README.md b/README.md index c0d68f2..103b655 100644 --- a/README.md +++ b/README.md @@ -42,5 +42,10 @@ Universe Generator Tweak # [MechaDronesTweaks](MechaDronesTweaks) -Some tweaks for mecha drones and build functions(Successor to FastDrones MOD) +Some tweaks for mecha drones and build functions(Successor to FastDrones MOD) 机甲建设机和建设功能调整(FastDrones MOD的后继者) + +# [LabOpt](LabOpt) + +Performance optimizations for Matrix Labs +优化研究站性能