diff --git a/Dustbin/Dustbin.cs b/Dustbin/Dustbin.cs index 43070aa..97a1316 100644 --- a/Dustbin/Dustbin.cs +++ b/Dustbin/Dustbin.cs @@ -95,7 +95,7 @@ public class Dustbin : BaseUnityPlugin, IModCanSave, IMultiplayerMod { var storage = storagePool[i]; if (storage == null || storage.id != i) continue; - if ((bool)StoragePatch.IsDustbinField.GetValue(storage)) + if (storage.IsDustbin) storageIds.Add(i); } @@ -104,7 +104,7 @@ public class Dustbin : BaseUnityPlugin, IModCanSave, IMultiplayerMod { ref var tank = ref tankPool[i]; if (tank.id != i) continue; - if ((bool)TankPatch.IsDustbinField.GetValue(tank)) + if (tank.IsDustbin) tankIds.Add(i); } @@ -136,13 +136,13 @@ public class Dustbin : BaseUnityPlugin, IModCanSave, IMultiplayerMod { var storage = storagePool[i]; if (storage == null || storage.id != i) continue; - StoragePatch.IsDustbinField.SetValue(storage, false); + storage.IsDustbin = false; } for (var i = 0; i < count; i++) { var id = r.ReadInt32(); - StoragePatch.IsDustbinField.SetValue(storagePool[id], true); + storagePool[id].IsDustbin = true; } count = r.ReadInt32(); @@ -152,13 +152,16 @@ public class Dustbin : BaseUnityPlugin, IModCanSave, IMultiplayerMod { ref var tank = ref tankPool[i]; if (tank.id != i) continue; - StoragePatch.IsDustbinField.SetValueDirect(__makeref(tank), false); + tank.IsDustbin = false; } for (var i = 0; i < count; i++) { var id = r.ReadInt32(); - StoragePatch.IsDustbinField.SetValueDirect(__makeref(tankPool[id]), true); + if (id >= cursor) continue; + ref var tank = ref tankPool[id]; + if (tank.id != id) continue; + tank.IsDustbin = true; } } diff --git a/Dustbin/Dustbin.csproj b/Dustbin/Dustbin.csproj index 0204429..e1e06a7 100644 --- a/Dustbin/Dustbin.csproj +++ b/Dustbin/Dustbin.csproj @@ -24,6 +24,16 @@ + + + + + + + + assemblies\Assembly-CSharp.dll + + diff --git a/Dustbin/NebulaSupport/Packets.cs b/Dustbin/NebulaSupport/Packets.cs index 8a95145..2d530b3 100644 --- a/Dustbin/NebulaSupport/Packets.cs +++ b/Dustbin/NebulaSupport/Packets.cs @@ -6,7 +6,7 @@ namespace Dustbin.NebulaSupport { public class SyncPlanetData { - public byte[] Data { get; set; } + public byte[] Data { get; } public SyncPlanetData() { @@ -20,9 +20,9 @@ namespace Dustbin.NebulaSupport public class ToggleEvent { - public int PlanetId { get; set; } - public int StorageId { get; set; } - public bool Enable { get; set; } + public int PlanetId { get; } + public int StorageId { get; } + public bool Enable { get; } public ToggleEvent() { @@ -61,13 +61,13 @@ namespace Dustbin.NebulaSupport case < 0: { var tankPool = factory.factoryStorage.tankPool; - TankPatch.IsDustbinField.SetValue(tankPool[-storageId], packet.Enable); + tankPool[-storageId].IsDustbin = packet.Enable; return; } default: { var storagePool = factory.factoryStorage.storagePool; - StoragePatch.IsDustbinField.SetValue(storagePool[storageId], packet.Enable); + storagePool[storageId].IsDustbin = packet.Enable; return; } } diff --git a/Dustbin/README.md b/Dustbin/README.md index 2b95c6a..547a6f2 100644 --- a/Dustbin/README.md +++ b/Dustbin/README.md @@ -3,8 +3,7 @@ #### Can turn Storages and Tanks into Dustbin(Destroy incoming items) #### 储物仓和储液罐可以转变为垃圾桶(销毁送进的物品) -## Updates - +## Changelog * 1.3.0 * Reworked dustbin support for Tanks, to improve performance and resolve known bugs. * Support for [Nebula Mupltiplayer Mod](https://dsp.thunderstore.io/package/nebula/NebulaMultiplayerMod/). diff --git a/Dustbin/StoragePatch.cs b/Dustbin/StoragePatch.cs index 286ecbe..5273b3f 100644 --- a/Dustbin/StoragePatch.cs +++ b/Dustbin/StoragePatch.cs @@ -1,5 +1,7 @@ -using System.IO; -using System.Reflection; +using System.Collections.Generic; +using System.IO; +using System.Reflection.Emit; +using System.Runtime.CompilerServices; using HarmonyLib; using NebulaAPI; using UnityEngine; @@ -9,7 +11,6 @@ namespace Dustbin; [HarmonyPatch] public static class StoragePatch { - public static readonly FieldInfo IsDustbinField = AccessTools.Field(typeof(StorageComponent), "IsDustbin"); private static UI.MyCheckBox _storageDustbinCheckBox; private static int _lastStorageId; @@ -35,7 +36,7 @@ public static class StoragePatch for (var j = 1; j < cursor; j++) { if (storagePool[j] == null || storagePool[j].id != j) continue; - if (!(bool)IsDustbinField.GetValue(storagePool[j])) continue; + if (!storagePool[j].IsDustbin) continue; tempWriter.Write(j); count++; } @@ -75,7 +76,7 @@ public static class StoragePatch var id = r.ReadInt32(); if (id > 0 && id < storagePool.Length && storagePool[id] != null && storagePool[id].id == id) { - IsDustbinField.SetValue(storagePool[id], true); + storagePool[id].IsDustbin = true; } } } @@ -94,7 +95,7 @@ public static class StoragePatch var storagePool = window.factoryStorage.storagePool; if (storagePool[storageId].id != storageId) return; var enabled = _storageDustbinCheckBox.Checked; - IsDustbinField.SetValue(storagePool[storageId], enabled); + storagePool[storageId].IsDustbin = enabled; if (!NebulaModAPI.IsMultiplayerActive) return; var planetId = window.factory.planetId; NebulaModAPI.MultiplayerSession.Network.SendPacketToLocalStar(new NebulaSupport.Packet.ToggleEvent(planetId, storageId, enabled)); @@ -111,7 +112,7 @@ public static class StoragePatch if (storageId <= 0) return; var storagePool = __instance.factoryStorage.storagePool; if (storagePool[storageId].id != storageId) return; - _storageDustbinCheckBox.Checked = (bool)IsDustbinField.GetValue(storagePool[storageId]); + _storageDustbinCheckBox.Checked = storagePool[storageId].IsDustbin; if (__instance.transform is RectTransform rectTrans) { _storageDustbinCheckBox.rectTrans.anchoredPosition3D = new Vector3(50, 58 - rectTrans.sizeDelta.y, 0); @@ -127,21 +128,11 @@ public static class StoragePatch _lastStorageId = 0; // Refresh UI to reposition button on client side } - [HarmonyPrefix] - [HarmonyPatch(typeof(StorageComponent), "AddItem", - new[] { typeof(int), typeof(int), typeof(int), typeof(int), typeof(bool) }, - new[] - { - ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Out, ArgumentType.Normal - })] - private static bool StorageComponent_AddItem_Prefix(ref int __result, StorageComponent __instance, int itemId, int count, int inc, - ref int remainInc, bool useBan = false) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int DustbinAddItem(int itemId, int count) { - if (!(bool)IsDustbinField.GetValue(__instance)) return true; - remainInc = inc; - __result = count; var fluidArr = Dustbin.IsFluid; - var sandsPerItem = Dustbin.SandsFactors[itemId < fluidArr.Length && fluidArr[itemId] + var sandIndex = itemId < fluidArr.Length && fluidArr[itemId] ? 0 : itemId switch { @@ -149,13 +140,36 @@ public static class StoragePatch 1003 => 3, 1013 => 4, _ => 1, - }]; - if (sandsPerItem <= 0) return false; + }; + var sandsPerItem = Dustbin.SandsFactors[sandIndex]; + if (sandsPerItem <= 0) return count; var player = GameMain.mainPlayer; var addCount = count * sandsPerItem; player.sandCount += addCount; GameMain.history.OnSandCountChange(player.sandCount, addCount); - return false; + return count; + } + + [HarmonyTranspiler] + [HarmonyPatch(typeof(StorageComponent), "AddItem", new[] { typeof(int), typeof(int), typeof(int), typeof(int), typeof(bool) }, + new[] { ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Out, ArgumentType.Normal })] + private static IEnumerable StorageComponent_AddItem_HarmonyTranspiler(IEnumerable instructions, ILGenerator generator) + { + var matcher = new CodeMatcher(instructions, generator); + var label1 = generator.DefineLabel(); + matcher.Start().MatchForward(false, + new CodeMatch(OpCodes.Stind_I4) + ).Advance(1).InsertAndAdvance( + new CodeInstruction(OpCodes.Ldarg_0), + new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(StorageComponent), nameof(StorageComponent.IsDustbin))), + new CodeInstruction(OpCodes.Brfalse, label1), + new CodeInstruction(OpCodes.Ldarg_1), + new CodeInstruction(OpCodes.Ldarg_2), + new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(StoragePatch), nameof(StoragePatch.DustbinAddItem))), + new CodeInstruction(OpCodes.Ret) + ); + matcher.Labels.Add(label1); + return matcher.InstructionEnumeration(); } /* We keep this to make MOD compatible with older version */ @@ -166,6 +180,6 @@ public static class StoragePatch if (__instance.bans >= 0) return; __instance.bans = -__instance.bans - 1; - IsDustbinField.SetValue(__instance, true); + __instance.IsDustbin = true; } } diff --git a/Dustbin/TankPatch.cs b/Dustbin/TankPatch.cs index c549f8c..43dc4c4 100644 --- a/Dustbin/TankPatch.cs +++ b/Dustbin/TankPatch.cs @@ -9,7 +9,6 @@ namespace Dustbin; [HarmonyPatch] public static class TankPatch { - public static readonly FieldInfo IsDustbinField = AccessTools.Field(typeof(TankComponent), "IsDustbin"); private static UI.MyCheckBox _tankDustbinCheckBox; private static int _lastTankId; @@ -37,7 +36,7 @@ public static class TankPatch for (var j = 1; j < cursor; j++) { if (tankPool[j].id != j) continue; - if (!(bool)IsDustbinField.GetValue(tankPool[j])) continue; + if (!tankPool[j].IsDustbin) continue; tempWriter.Write(j); count++; } @@ -81,7 +80,7 @@ public static class TankPatch var id = r.ReadInt32(); if (id > 0 && id < tankPool.Length && tankPool[id].id == id) { - IsDustbinField.SetValueDirect(__makeref(tankPool[id]), true); + tankPool[id].IsDustbin = true; } } } @@ -100,7 +99,7 @@ public static class TankPatch var tankPool = window.storage.tankPool; if (tankPool[tankId].id != tankId) return; var enabled = _tankDustbinCheckBox.Checked; - IsDustbinField.SetValueDirect(__makeref(tankPool[tankId]), enabled); + tankPool[tankId].IsDustbin = enabled; if (!NebulaModAPI.IsMultiplayerActive) return; var planetId = window.factory.planetId; NebulaModAPI.MultiplayerSession.Network.SendPacketToLocalStar(new NebulaSupport.Packet.ToggleEvent(planetId, -tankId, enabled)); @@ -117,8 +116,9 @@ public static class TankPatch if (tankId <= 0) return; var tankPool = __instance.storage.tankPool; - if (tankPool[tankId].id != tankId) return; - _tankDustbinCheckBox.Checked = (bool)IsDustbinField.GetValue(tankPool[tankId]); + ref var tank = ref tankPool[tankId]; + if (tank.id != tankId) return; + _tankDustbinCheckBox.Checked = tank.IsDustbin; } [HarmonyPrefix] @@ -181,14 +181,14 @@ public static class TankPatch switch (thisTank.fluidId) { case > 0 when thisTank.fluidCount < thisTank.fluidCapacity && cargoTraffic.TryPickItemAtRear(belt, thisTank.fluidId, null, out stack, out inc) > 0 && - !(bool)IsDustbinField.GetValue(thisTank): + !thisTank.IsDustbin: thisTank.fluidCount += stack; thisTank.fluidInc += inc; return; case 0: { var count = cargoTraffic.TryPickItemAtRear(belt, 0, ItemProto.fluids, out stack, out inc); - if (count <= 0 || (bool)IsDustbinField.GetValue(thisTank)) return; + if (count <= 0 || thisTank.IsDustbin) return; thisTank.fluidId = count; thisTank.fluidCount += stack; thisTank.fluidInc += inc; @@ -242,7 +242,7 @@ public static class TankPatch } } - if (cargoTraffic.TryPickItemAtRear(belt, thisTank.fluidId, null, out stack, out inc) <= 0 || (bool)IsDustbinField.GetValue(targetTank)) return; + if (cargoTraffic.TryPickItemAtRear(belt, thisTank.fluidId, null, out stack, out inc) <= 0 || targetTank.IsDustbin) return; if (targetTank.fluidCount == 0) { targetTank.fluidId = thisTank.fluidId; diff --git a/Dustbin/assemblies/Assembly-CSharp.dll b/Dustbin/assemblies/Assembly-CSharp.dll new file mode 100644 index 0000000..1d22e24 Binary files /dev/null and b/Dustbin/assemblies/Assembly-CSharp.dll differ