diff --git a/UXAssist/ModsCompat/CommonAPIWrapper.cs b/UXAssist/ModsCompat/CommonAPIWrapper.cs new file mode 100644 index 0000000..a3e7291 --- /dev/null +++ b/UXAssist/ModsCompat/CommonAPIWrapper.cs @@ -0,0 +1,20 @@ +using BepInEx.Bootstrap; +using CommonAPI; +using HarmonyLib; + +namespace UXAssist.ModsCompat; + +public static class CommonAPIWrapper +{ + public static void Run(Harmony harmony) + { + if (!Chainloader.PluginInfos.TryGetValue(CommonAPIPlugin.GUID, out var commonAPIPlugin) || + commonAPIPlugin.Metadata.Version > new System.Version(1, 6, 7, 0)) return; + harmony.Patch(AccessTools.Method(typeof(GameOption), nameof(GameOption.InitKeys)), new HarmonyMethod(typeof(CommonAPIWrapper), nameof(PatchInitKeys))); + } + + public static bool PatchInitKeys(GameOption __instance) + { + return __instance.overrideKeys == null; + } +} diff --git a/UXAssist/Patches/PersistPatch.cs b/UXAssist/Patches/PersistPatch.cs index d5170b3..0256ee5 100644 --- a/UXAssist/Patches/PersistPatch.cs +++ b/UXAssist/Patches/PersistPatch.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Reflection.Emit; using HarmonyLib; using UnityEngine; @@ -169,4 +170,119 @@ public class PersistPatch : PatchImpl { return false; } + + [HarmonyTranspiler] + [HarmonyPatch(typeof(VFInput), nameof(VFInput._fastTransferWithEntityDown), MethodType.Getter)] + [HarmonyPatch(typeof(VFInput), nameof(VFInput._fastTransferWithEntityPress), MethodType.Getter)] + private static IEnumerable VFInput_fastTransferWithEntityDown_Transpiler(IEnumerable instructions, ILGenerator generator) + { + var matcher = new CodeMatcher(instructions, generator); + matcher.MatchForward(false, + new CodeMatch(OpCodes.Ldsfld, AccessTools.Field(typeof(VFInput), nameof(VFInput.shift))), + new CodeMatch(ci => ci.opcode == OpCodes.Brtrue || ci.opcode == OpCodes.Brtrue_S) + ); + var lables = matcher.Labels; + matcher.RemoveInstructions(2); + matcher.Labels.AddRange(lables); + return matcher.InstructionEnumeration(); + } + + [HarmonyTranspiler] + [HarmonyPatch(typeof(PlayerAction_Inspect), nameof(PlayerAction_Inspect.GameTick))] + private static IEnumerable PlayerAction_Inspect_GameTick_Transpiler(IEnumerable instructions, ILGenerator generator) + { + var matcher = new CodeMatcher(instructions, generator); + matcher.MatchForward(false, + new CodeMatch(OpCodes.Ldc_I4_1), + new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(PlayerAction_Inspect), nameof(PlayerAction_Inspect.fastFillIn))) + ); + matcher.SetAndAdvance(OpCodes.Ldsfld, AccessTools.Field(typeof(VFInput), nameof(VFInput.shift))).Insert( + new CodeInstruction(OpCodes.Ldc_I4_0), + new CodeInstruction(OpCodes.Ceq) + ); + + var label0 = generator.DefineLabel(); + var label1 = generator.DefineLabel(); + matcher.Start().MatchForward(false, + new CodeMatch(ci => ci.IsStloc()), + new CodeMatch(OpCodes.Ldc_I4_0), + new CodeMatch(ci => ci.IsStloc()), + new CodeMatch(OpCodes.Ldloc_0), + new CodeMatch(ci => ci.IsLdloc()), + new CodeMatch(ci => ci.IsLdloc()), + new CodeMatch(ci => ci.IsLdloc()), + new CodeMatch(ci => ci.IsLdloc()), + new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(PlanetFactory), nameof(PlanetFactory.EntityFastTakeOut))) + ).Advance(8).InsertAndAdvance( + new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(VFInput), nameof(VFInput.shift))), + new CodeInstruction(OpCodes.Brfalse_S, label0), + new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(PersistPatch), nameof(PersistPatch.EntityFastTakeOutAlt))), + new CodeInstruction(OpCodes.Br, label1) + ).Labels.Add(label0); + matcher.Advance(1).Labels.Add(label1); + return matcher.InstructionEnumeration(); + } + + private static void EntityFastTakeOutAlt(PlanetFactory factory, int entityId, bool toPackage, out ItemBundle itemBundle, out bool full) + { + if (factory._tmp_items == null) + { + factory._tmp_items = new ItemBundle(); + } + else + { + factory._tmp_items.Clear(); + } + itemBundle = factory._tmp_items; + full = false; + if (entityId == 0 || factory.entityPool[entityId].id != entityId) + { + return; + } + ref var entityData = ref factory.entityPool[entityId]; + if (entityData.beltId <= 0) return; + var cargoTraffic = factory.cargoTraffic; + ref var belt = ref cargoTraffic.beltPool[entityData.beltId]; + if (belt.id != entityData.beltId) return; + var cargoPath = cargoTraffic.GetCargoPath(belt.segPathId); + var end = cargoPath.bufferLength - 1; + var buffer = cargoPath.buffer; + Dictionary takeOutItems = []; + var mainPlayer = factory.gameData.mainPlayer; + int i = 0; + while (i <= end) + { + if (buffer[i] >= 246) + { + i += 250 - buffer[i]; + var index = buffer[i + 1] - 1 + (buffer[i + 2] - 1) * 100 + (buffer[i + 3] - 1) * 10000 + (buffer[i + 4] - 1) * 1000000; + ref var cargo = ref cargoPath.cargoContainer.cargoPool[index]; + var item = cargo.item; + var stack = cargo.stack; + var inc = cargo.inc; + takeOutItems[item] = (takeOutItems.TryGetValue(item, out var value) ? value : 0) + + ((long)stack | ((long)inc << 32)); + Array.Clear(buffer, i - 4, 10); + i += 10; + if (cargoPath.updateLen < i) cargoPath.updateLen = i; + cargoPath.cargoContainer.RemoveCargo(index); + } + else + { + i += 5; + if (i > end && i < end + 5) + { + i = end; + } + } + } + foreach (var kvp in takeOutItems) + { + var added = mainPlayer.TryAddItemToPackage(kvp.Key, (int)(kvp.Value & 0xFFFFFFFF), (int)(kvp.Value >> 32), true, entityId); + if (added > 0) + { + UIItemup.Up(kvp.Key, added); + } + } + } }