using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Logging; using Dustbin.NebulaSupport.Packet; using Dustbin.UI; using HarmonyLib; using Microsoft.CodeAnalysis; using NebulaAPI; using NebulaAPI.Interfaces; using NebulaAPI.Networking; using NebulaAPI.Packets; using UnityEngine; using UnityEngine.UI; using crecheng.DSPModSave; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("Dustbin")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("DSP MOD - Dustbin")] [assembly: AssemblyFileVersion("1.4.1.0")] [assembly: AssemblyInformationalVersion("1.4.1+d37f5009265ff7d1edacbd140e3b2d84ecc480b2")] [assembly: AssemblyProduct("Dustbin")] [assembly: AssemblyTitle("Dustbin")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.4.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Dustbin { public static class BeltSignal { private static HashSet[] _signalBelts; private static int _signalBeltsCapacity; private static bool _initialized; private static Harmony _patch; public static void Enable(bool on) { if (on) { if (_patch == null) { _patch = Harmony.CreateAndPatchAll(typeof(BeltSignal), (string)null); } InitSignalBelts(); return; } Harmony patch = _patch; if (patch != null) { patch.UnpatchSelf(); } _patch = null; _signalBelts = null; _signalBeltsCapacity = 0; } private static byte[] LoadEmbeddedResource(string path, Assembly assembly = null) { if (assembly == null) { assembly = Assembly.GetCallingAssembly(); } string name = assembly.GetName().Name; using Stream stream = assembly.GetManifestResourceStream(name + "." + path.Replace('/', '.')); byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); return array; } private static Texture2D LoadEmbeddedTexture(string path, Assembly assembly = null) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0018: Expected O, but got Unknown byte[] array = LoadEmbeddedResource(path, assembly); Texture2D val = new Texture2D(2, 2); ImageConversion.LoadImage(val, array); return val; } private static Sprite LoadEmbeddedSprite(string path, Assembly assembly = null) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) Texture2D val = LoadEmbeddedTexture(path, assembly); return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); } [HarmonyPostfix] [HarmonyPriority(0)] [HarmonyPatch(typeof(VFPreload), "InvokeOnLoadWorkEnded")] private static void VFPreload_InvokeOnLoadWorkEnded_Postfix() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown if (!_initialized) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); SignalProtoSet signals = LDB._signals; int value = ((ProtoSet)(object)signals).dataArray.Length; SignalProto val = new SignalProto { ID = 410, Name = "DUSTBIN", GridIndex = 3110, IconPath = "Assets/signal-410.png", _iconSprite = LoadEmbeddedSprite("assets/icon/signal-410.png", executingAssembly), SID = "" }; ((Proto)val).name = Localization.Translate(((Proto)val).Name); List list = new List(); list.AddRange(CollectionExtensions.AddItem((IEnumerable)((ProtoSet)(object)signals).dataArray, val)); ((ProtoSet)(object)signals).dataArray = list.ToArray(); ((ProtoSet)(object)signals).dataIndices[((Proto)val).ID] = value; _initialized = true; } } private static void InitSignalBelts() { if (!GameMain.isRunning) { return; } _signalBelts = new HashSet[64]; _signalBeltsCapacity = 64; PlanetFactory[] array = GameMain.data?.factories; if (array == null) { return; } PlanetFactory[] array2 = array; foreach (PlanetFactory val in array2) { SignData[] array3 = val?.entitySignPool; if (array3 == null) { continue; } CargoTraffic cargoTraffic = val.cargoTraffic; BeltComponent[] beltPool = cargoTraffic.beltPool; for (int num = cargoTraffic.beltCursor - 1; num > 0; num--) { if (beltPool[num].id == num && array3[beltPool[num].entityId].iconId0 == 410) { SetSignalBelt(val.index, num); } } } } private static void SetSignalBelt(int factory, int beltId) { GetOrCreateSignalBelts(factory).Add(beltId); } private static HashSet GetOrCreateSignalBelts(int index) { if (index < 0) { return null; } HashSet hashSet; if (index >= _signalBeltsCapacity) { int num = _signalBeltsCapacity * 2; HashSet[] array = new HashSet[num]; Array.Copy(_signalBelts, array, _signalBeltsCapacity); _signalBelts = array; _signalBeltsCapacity = num; } else { hashSet = _signalBelts[index]; if (hashSet != null) { return hashSet; } } hashSet = new HashSet(); _signalBelts[index] = hashSet; return hashSet; } private static HashSet GetSignalBelts(int index) { if (index < 0 || index >= _signalBeltsCapacity) { return null; } return _signalBelts[index]; } private static void RemoveSignalBelt(int factory, int beltId) { GetSignalBelts(factory)?.Remove(beltId); } private static void RemovePlanetSignalBelts(int factory) { GetSignalBelts(factory)?.Clear(); } [HarmonyPostfix] [HarmonyPatch(/*Could not decode attribute arguments.*/)] private static void DigitalSystem_Constructor_Postfix(PlanetData _planet) { if (GameMain.mainPlayer != null) { PlanetFactory val = _planet?.factory; if (val != null) { RemovePlanetSignalBelts(val.index); } } } [HarmonyPostfix] [HarmonyPatch(typeof(GameMain), "Begin")] private static void GameMain_Begin_Postfix() { InitSignalBelts(); } [HarmonyPrefix] [HarmonyPatch(typeof(CargoTraffic), "RemoveBeltComponent")] public static void CargoTraffic_RemoveBeltComponent_Prefix(int id) { PlanetData localPlanet = GameMain.localPlanet; if (localPlanet != null) { RemoveSignalBelt(localPlanet.factoryIndex, id); } } [HarmonyPostfix] [HarmonyPatch(typeof(CargoTraffic), "SetBeltSignalIcon")] public static void CargoTraffic_SetBeltSignalIcon_Postfix(CargoTraffic __instance, int signalId, int entityId) { PlanetData localPlanet = GameMain.localPlanet; if (localPlanet != null) { PlanetFactory factory = __instance.factory; int factoryIndex = localPlanet.factoryIndex; int beltId = factory.entityPool[entityId].beltId; if (signalId == 410) { SetSignalBelt(factoryIndex, beltId); } else { RemoveSignalBelt(factoryIndex, beltId); } } } [HarmonyPostfix] [HarmonyPatch(typeof(GameLogic), "TrashSystemGameTick")] public static void GameLogic_TrashSystemGameTick_Postfix() { PlanetFactory[] array = GameMain.data?.factories; if (array == null) { return; } PlanetFactory[] array2 = array; byte b = default(byte); byte b2 = default(byte); foreach (PlanetFactory val in array2) { if (val == null) { continue; } int index = val.index; HashSet signalBelts = GetSignalBelts(index); if (signalBelts == null || signalBelts.Count == 0) { continue; } int[] consumeRegister = GameMain.statistics.production.factoryStatPool[index].consumeRegister; CargoTraffic cargoTraffic = val.cargoTraffic; foreach (int item in signalBelts) { ref BeltComponent reference = ref cargoTraffic.beltPool[item]; CargoPath cargoPath = cargoTraffic.GetCargoPath(reference.segPathId); int num; if (cargoPath != null && (num = cargoPath.TryPickItem(reference.segIndex + reference.segPivotOffset - 5, 12, ref b, ref b2)) > 0) { consumeRegister[num] += b; Dustbin.CalcGetSands(num, b, 0); } } } } } [BepInPlugin("org.soardev.dustbin", "Dustbin", "1.4.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Dustbin : BaseUnityPlugin, IModCanSave, IMultiplayerMod { public static readonly ManualLogSource Logger = Logger.CreateLogSource("Dustbin"); private static readonly int[] SandsFactors = new int[12001]; private const ushort ModSaveVersion = 1; public string Version => "1.4.1"; public bool CheckVersion(string hostVersion, string clientVersion) { return hostVersion.Equals(clientVersion); } private void Awake() { bool value = ((BaseUnityPlugin)this).Config.Bind("General", "StorageDustbin", true, "Can turn storages into dustbins").Value; bool value2 = ((BaseUnityPlugin)this).Config.Bind("General", "TankDustbin", true, "Can turn tanks into dustbins").Value; bool value3 = ((BaseUnityPlugin)this).Config.Bind("General", "BeltSignalDustbin", true, "Add belt signal as dustbin").Value; string[] array = ((BaseUnityPlugin)this).Config.Bind("General", "SandsFactors", "", "Soil piles get from different items\nFormat: id1:value1|id2:value2|...").Value.Split(new char[1] { '|' }); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { ':' }); if (array2.Length >= 2 && int.TryParse(array2[0], out var result) && result <= 12000 && int.TryParse(array2[1], out var result2)) { SandsFactors[result] = result2; } } if (value) { StoragePatch.Enable(on: true); } if (value2) { TankPatch.Enable(on: true); } if (value3) { BeltSignal.Enable(on: true); } if (Chainloader.PluginInfos.ContainsKey("dsp.nebula-multiplayer") && (value || value2)) { NebulaModAPI.RegisterPackets(Assembly.GetExecutingAssembly()); NebulaModAPI.OnPlanetLoadFinished = (Action)Delegate.Combine(NebulaModAPI.OnPlanetLoadFinished, new Action(RequestPlanetDustbinData)); } } private void OnDestroy() { TankPatch.Enable(on: false); StoragePatch.Enable(on: false); BeltSignal.Enable(on: false); NebulaModAPI.OnPlanetLoadFinished = (Action)Delegate.Remove(NebulaModAPI.OnPlanetLoadFinished, new Action(RequestPlanetDustbinData)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int CalcGetSands(int itemId, int count, int inc) { int num = ((itemId <= 12000) ? SandsFactors[itemId] : 0); if (num <= 0) { return count; } Player mainPlayer = GameMain.mainPlayer; int num2 = count * num; mainPlayer.sandCount += num2; return count; } public void Export(BinaryWriter w) { w.Write((ushort)1); StoragePatch.Export(w); TankPatch.Export(w); } public void Import(BinaryReader r) { if (r.ReadUInt16() > 0) { StoragePatch.Import(r); TankPatch.Import(r); } } public void IntoOtherSave() { } public static byte[] ExportData(PlanetFactory factory) { int planetId = factory.planetId; List list = new List(); List list2 = new List(); FactoryStorage factoryStorage = factory.factoryStorage; StorageComponent[] storagePool = factoryStorage.storagePool; for (int i = 1; i < factoryStorage.storageCursor; i++) { StorageComponent val = storagePool[i]; if (val != null && val.id == i && val.IsDustbin) { list.Add(i); } } TankComponent[] tankPool = factoryStorage.tankPool; for (int j = 1; j < factoryStorage.tankCursor; j++) { ref TankComponent reference = ref tankPool[j]; if (reference.id == j && reference.IsDustbin) { list2.Add(j); } } IWriterProvider binaryWriter = NebulaModAPI.GetBinaryWriter(); try { using BinaryWriter binaryWriter2 = binaryWriter.BinaryWriter; binaryWriter2.Write(planetId); binaryWriter2.Write(list.Count); foreach (int item in list) { binaryWriter2.Write(item); } binaryWriter2.Write(list2.Count); foreach (int item2 in list2) { binaryWriter2.Write(item2); } return binaryWriter.CloseAndGetBytes(); } finally { ((IDisposable)binaryWriter)?.Dispose(); } } public static void ImportData(byte[] bytes) { IReaderProvider binaryReader = NebulaModAPI.GetBinaryReader(bytes); try { using BinaryReader binaryReader2 = binaryReader.BinaryReader; int num = binaryReader2.ReadInt32(); PlanetFactory val = GameMain.galaxy.PlanetById(num)?.factory; if (val == null) { return; } FactoryStorage factoryStorage = val.factoryStorage; int num2 = binaryReader2.ReadInt32(); StorageComponent[] storagePool = factoryStorage.storagePool; int storageCursor = factoryStorage.storageCursor; for (int i = 1; i < storageCursor; i++) { StorageComponent val2 = storagePool[i]; if (val2 != null && val2.id == i) { val2.IsDustbin = false; } } for (int j = 0; j < num2; j++) { int num3 = binaryReader2.ReadInt32(); storagePool[num3].IsDustbin = true; } num2 = binaryReader2.ReadInt32(); TankComponent[] tankPool = factoryStorage.tankPool; storageCursor = factoryStorage.tankCursor; for (int k = 1; k < storageCursor; k++) { ref TankComponent reference = ref tankPool[k]; if (reference.id == k) { reference.IsDustbin = false; } } for (int l = 0; l < num2; l++) { int num4 = binaryReader2.ReadInt32(); if (num4 < storageCursor) { ref TankComponent reference2 = ref tankPool[num4]; if (reference2.id == num4) { reference2.IsDustbin = true; } } } } finally { ((IDisposable)binaryReader)?.Dispose(); } } public void RequestPlanetDustbinData(int planetId) { if (NebulaModAPI.IsMultiplayerActive && NebulaModAPI.MultiplayerSession.IsClient) { NebulaModAPI.MultiplayerSession.Network.SendPacket(new ToggleEvent(planetId, 0, enable: false)); } } } [HarmonyPatch] public static class StoragePatch { private static MyCheckBox _storageDustbinCheckBox; private static int _lastStorageId; private static Harmony _patch; public static void Enable(bool on) { if (on) { if (_patch == null) { _patch = Harmony.CreateAndPatchAll(typeof(StoragePatch), (string)null); } return; } Harmony patch = _patch; if (patch != null) { patch.UnpatchSelf(); } _patch = null; } public static void Reset() { _lastStorageId = 0; } public static void Export(BinaryWriter w) { MemoryStream memoryStream = new MemoryStream(); BinaryWriter binaryWriter = new BinaryWriter(memoryStream); PlanetFactory[] factories = GameMain.data.factories; int factoryCount = GameMain.data.factoryCount; for (int i = 0; i < factoryCount; i++) { PlanetFactory val = factories[i]; FactoryStorage val2 = val?.factoryStorage; StorageComponent[] array = val2?.storagePool; if (array == null) { continue; } int storageCursor = val2.storageCursor; int num = 0; for (int j = 1; j < storageCursor; j++) { if (array[j] != null && array[j].id == j && array[j].IsDustbin) { binaryWriter.Write(j); num++; } } if (num != 0) { binaryWriter.Flush(); memoryStream.Position = 0L; w.Write((byte)1); w.Write(val.planetId); w.Write(num); memoryStream.CopyTo(w.BaseStream); memoryStream.SetLength(0L); } } binaryWriter.Dispose(); memoryStream.Dispose(); } public static void Import(BinaryReader r) { while (r.PeekChar() == 1) { r.ReadByte(); int num = r.ReadInt32(); StorageComponent[] array = GameMain.data.galaxy.PlanetById(num)?.factory?.factoryStorage?.storagePool; if (array == null) { for (int num2 = r.ReadInt32(); num2 > 0; num2--) { r.ReadInt32(); } continue; } for (int num3 = r.ReadInt32(); num3 > 0; num3--) { int num4 = r.ReadInt32(); if (num4 > 0 && num4 < array.Length && array[num4] != null && array[num4].id == num4) { array[num4].IsDustbin = true; } } } } [HarmonyPrefix] [HarmonyPatch(typeof(GameMain), "Start")] private static void GameMain_Start_Prefix() { Reset(); } [HarmonyPostfix] [HarmonyPatch(typeof(UIStorageWindow), "_OnCreate")] private static void UIStorageWindow__OnCreate_Postfix(UIStorageWindow __instance) { _storageDustbinCheckBox = MyCheckBox.CreateCheckBox(check: false, ((Component)__instance).transform, 50f, 50f, (Localization.CurrentLanguageLCID == 2052) ? "垃圾桶" : "Dustbin"); UIStorageWindow window = __instance; _storageDustbinCheckBox.OnChecked += delegate { int storageId = window.storageId; if (storageId > 0) { StorageComponent[] storagePool = window.factoryStorage.storagePool; if (storagePool[storageId].id == storageId) { bool flag = _storageDustbinCheckBox.Checked; storagePool[storageId].IsDustbin = flag; if (NebulaModAPI.IsMultiplayerActive) { int planetId = window.factory.planetId; NebulaModAPI.MultiplayerSession.Network.SendPacketToLocalStar(new ToggleEvent(planetId, storageId, flag)); } } } }; } [HarmonyPostfix] [HarmonyPatch(typeof(UIStorageWindow), "_OnUpdate")] private static void UIStorageWindow__OnUpdate_Postfix(UIStorageWindow __instance) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) int storageId = __instance.storageId; if (_lastStorageId == storageId) { return; } _lastStorageId = storageId; if (storageId <= 0) { return; } StorageComponent[] storagePool = __instance.factoryStorage.storagePool; if (storagePool[storageId].id == storageId) { _storageDustbinCheckBox.Checked = storagePool[storageId].IsDustbin; Transform transform = ((Component)__instance).transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); if (val != null) { _storageDustbinCheckBox.rectTrans.anchoredPosition3D = new Vector3(190f, 57f - val.sizeDelta.y, 0f); } } } [HarmonyPostfix] [HarmonyPatch(typeof(UIStorageGrid), "OnStorageSizeChanged")] private static void UIStorageGrid_OnStorageSizeChanged_Postfix() { _lastStorageId = 0; } [HarmonyTranspiler] [HarmonyPatch(/*Could not decode attribute arguments.*/)] private static IEnumerable StorageComponent_AddItem_HarmonyTranspiler(IEnumerable instructions, ILGenerator generator) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Expected O, but got Unknown //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Expected O, but got Unknown //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Expected O, but got Unknown //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Expected O, but got Unknown //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Expected O, but got Unknown //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Expected O, but got Unknown CodeMatcher val = new CodeMatcher((IEnumerable)new List(instructions), generator); val.Start(); Label label = generator.DefineLabel(); val.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[17] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Brfalse, (object)label), new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(StorageComponent), "IsDustbin")), new CodeInstruction(OpCodes.Brfalse, (object)label), new CodeInstruction(OpCodes.Ldarg_2, (object)null), new CodeInstruction(OpCodes.Ldc_I4_0, (object)null), new CodeInstruction(OpCodes.Ble, (object)label), new CodeInstruction(OpCodes.Ldarg_1, (object)null), new CodeInstruction(OpCodes.Ldarg_2, (object)null), new CodeInstruction(OpCodes.Ldarg_3, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Dustbin), "CalcGetSands", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Ldarg, (object)4), new CodeInstruction(OpCodes.Ldc_I4_0, (object)null), new CodeInstruction(OpCodes.Stind_I4, (object)null), new CodeInstruction(OpCodes.Ret, (object)null), CodeInstructionExtensions.WithLabels(new CodeInstruction(OpCodes.Nop, (object)null), new Label[1] { label }) }); return val.InstructionEnumeration(); } [HarmonyPostfix] [HarmonyPatch(typeof(StorageComponent), "Import")] private static void StorageComponent_Import_Postfix(StorageComponent __instance) { if (__instance.bans < 0) { __instance.bans = -__instance.bans - 1; __instance.IsDustbin = true; } } } [HarmonyPatch] public static class TankPatch { private static MyCheckBox _tankDustbinCheckBox; private static int _lastTankId; private static Harmony _patch; public static void Enable(bool on) { if (on) { if (_patch == null) { _patch = Harmony.CreateAndPatchAll(typeof(TankPatch), (string)null); } return; } Harmony patch = _patch; if (patch != null) { patch.UnpatchSelf(); } _patch = null; } public static void Reset() { _lastTankId = 0; } public static void Export(BinaryWriter w) { MemoryStream memoryStream = new MemoryStream(); BinaryWriter binaryWriter = new BinaryWriter(memoryStream); PlanetFactory[] factories = GameMain.data.factories; int factoryCount = GameMain.data.factoryCount; for (int i = 0; i < factoryCount; i++) { PlanetFactory val = factories[i]; if (val == null) { continue; } FactoryStorage factoryStorage = val.factoryStorage; TankComponent[] tankPool = factoryStorage.tankPool; int tankCursor = factoryStorage.tankCursor; int num = 0; for (int j = 1; j < tankCursor; j++) { if (tankPool[j].id == j && tankPool[j].IsDustbin) { binaryWriter.Write(j); num++; } } if (num != 0) { binaryWriter.Flush(); memoryStream.Position = 0L; w.Write((byte)2); w.Write(val.planetId); w.Write(num); memoryStream.CopyTo(w.BaseStream); memoryStream.SetLength(0L); } } binaryWriter.Dispose(); memoryStream.Dispose(); } public static void Import(BinaryReader r) { while (r.PeekChar() == 2) { r.ReadByte(); int num = r.ReadInt32(); TankComponent[] array = GameMain.data.galaxy.PlanetById(num)?.factory.factoryStorage.tankPool; if (array == null) { for (int num2 = r.ReadInt32(); num2 > 0; num2--) { r.ReadInt32(); } continue; } for (int num3 = r.ReadInt32(); num3 > 0; num3--) { int num4 = r.ReadInt32(); if (num4 > 0 && num4 < array.Length && array[num4].id == num4) { array[num4].IsDustbin = true; } } } } [HarmonyPrefix] [HarmonyPatch(typeof(GameMain), "Start")] private static void GameMain_Start_Prefix() { Reset(); } [HarmonyPostfix] [HarmonyPatch(typeof(UITankWindow), "_OnCreate")] private static void UITankWindow__OnCreate_Postfix(UITankWindow __instance) { _tankDustbinCheckBox = MyCheckBox.CreateCheckBox(check: false, ((Component)__instance).transform, 120f, 20f, (Localization.CurrentLanguageLCID == 2052) ? "垃圾桶" : "Dustbin"); UITankWindow window = __instance; _tankDustbinCheckBox.OnChecked += delegate { int tankId = window.tankId; if (tankId > 0) { TankComponent[] tankPool = window.storage.tankPool; if (tankPool[tankId].id == tankId) { bool flag = _tankDustbinCheckBox.Checked; tankPool[tankId].IsDustbin = flag; if (NebulaModAPI.IsMultiplayerActive) { int planetId = window.factory.planetId; NebulaModAPI.MultiplayerSession.Network.SendPacketToLocalStar(new ToggleEvent(planetId, -tankId, flag)); } } } }; } [HarmonyPostfix] [HarmonyPatch(typeof(UITankWindow), "_OnUpdate")] private static void UITankWindow__OnUpdate_Postfix(UITankWindow __instance) { int tankId = __instance.tankId; if (_lastTankId == tankId) { return; } _lastTankId = tankId; if (tankId > 0) { ref TankComponent reference = ref __instance.storage.tankPool[tankId]; if (reference.id == tankId) { _tankDustbinCheckBox.Checked = reference.IsDustbin; } } } [HarmonyPrefix] [HarmonyPatch(typeof(TankComponent), "GameTick")] private static bool TankComponent_GameTick_Prefix(ref TankComponent __instance, PlanetFactory factory) { if (__instance.fluidInc < 0) { __instance.fluidInc = 0; } if (!__instance.isBottom) { return false; } CargoTraffic cargoTraffic = factory.cargoTraffic; TankComponent[] tankPool = factory.factoryStorage.tankPool; int belt = __instance.belt0; if (belt > 0) { TankComponentUpdateBelt(ref __instance, belt, __instance.isOutput0, ref cargoTraffic, ref tankPool); } belt = __instance.belt1; if (belt > 0) { TankComponentUpdateBelt(ref __instance, belt, __instance.isOutput1, ref cargoTraffic, ref tankPool); } belt = __instance.belt2; if (belt > 0) { TankComponentUpdateBelt(ref __instance, belt, __instance.isOutput2, ref cargoTraffic, ref tankPool); } belt = __instance.belt3; if (belt > 0) { TankComponentUpdateBelt(ref __instance, belt, __instance.isOutput3, ref cargoTraffic, ref tankPool); } return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void TankComponentUpdateBelt(ref TankComponent thisTank, int belt, bool isOutput, ref CargoTraffic cargoTraffic, ref TankComponent[] tankPool) { if (isOutput) { if (thisTank.outputSwitch && thisTank.fluidId > 0 && thisTank.fluidCount > 0) { int num = ((thisTank.fluidInc != 0) ? (thisTank.fluidInc / thisTank.fluidCount) : 0); if (cargoTraffic.TryInsertItemAtHead(belt, thisTank.fluidId, (byte)1, (byte)num)) { thisTank.fluidCount--; thisTank.fluidInc -= num; } } } else { if (!thisTank.inputSwitch) { return; } int fluidId = thisTank.fluidId; byte b = default(byte); byte b2 = default(byte); if (thisTank.fluidCount <= 0) { int num2 = cargoTraffic.TryPickItemAtRear(belt, 0, ItemProto.fluids, ref b, ref b2); if (num2 > 0 && !thisTank.IsDustbin) { thisTank.fluidId = num2; thisTank.fluidCount = b; thisTank.fluidInc = b2; } } else if (thisTank.fluidCount < thisTank.fluidCapacity || thisTank.IsDustbin) { if (cargoTraffic.GetItemIdAtRear(belt) == fluidId && thisTank.nextTankId > 0 && cargoTraffic.TryPickItemAtRear(belt, fluidId, (int[])null, ref b, ref b2) > 0 && !thisTank.IsDustbin) { thisTank.fluidCount += b; thisTank.fluidInc += b2; } } else { if (thisTank.nextTankId <= 0) { return; } ref TankComponent reference = ref tankPool[thisTank.nextTankId]; while (true) { if (reference.fluidCount < reference.fluidCapacity || reference.IsDustbin) { if (!reference.inputSwitch) { break; } int fluidId2 = reference.fluidId; if ((fluidId2 == 0 || fluidId2 == fluidId) && cargoTraffic.TryPickItemAtRear(belt, fluidId, (int[])null, ref b, ref b2) > 0 && !reference.IsDustbin) { if (reference.fluidCount <= 0) { reference.fluidId = fluidId; reference.fluidCount = b; reference.fluidInc = b2; } else { reference.fluidCount += b; reference.fluidInc += b2; } } break; } if (reference.nextTankId <= 0) { break; } reference = ref tankPool[reference.nextTankId]; } } } } } public static class PluginInfo { public const string PLUGIN_GUID = "org.soardev.dustbin"; public const string PLUGIN_NAME = "Dustbin"; public const string PLUGIN_VERSION = "1.4.1"; } } namespace Dustbin.UI { public class MyCheckBox : MonoBehaviour { public UIButton uiButton; public Image checkImage; public RectTransform rectTrans; public Text labelText; private bool _checked; public bool Checked { get { return _checked; } set { _checked = value; ((Behaviour)checkImage).enabled = value; } } public event Action OnChecked; public static MyCheckBox CreateCheckBox(bool check, Transform parent = null, float x = 0f, float y = 0f, string label = "", int fontSize = 15) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate(((Component)UIRoot.instance.uiGame.buildMenu.uxFacilityCheck).gameObject); Transform transform = val.transform; RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val2 == (Object)null) { return null; } ((Object)val).name = "my-checkbox"; MyCheckBox myCheckBox = val.AddComponent(); myCheckBox._checked = check; if ((Object)(object)parent != (Object)null) { ((Transform)val2).SetParent(parent); } val2.anchorMax = new Vector2(0f, 1f); val2.anchorMin = new Vector2(0f, 1f); val2.pivot = new Vector2(0f, 1f); val2.anchoredPosition3D = new Vector3(x, 0f - y, 0f); myCheckBox.rectTrans = val2; myCheckBox.uiButton = val.GetComponent(); Transform obj = val.transform.Find("checked"); myCheckBox.checkImage = ((obj != null) ? ((Component)obj).GetComponent() : null); Transform val3 = val.transform.Find("text"); if ((Object)(object)val3 != (Object)null) { Object.DestroyImmediate((Object)(object)((Component)val3).GetComponent()); myCheckBox.labelText = ((Component)val3).GetComponent(); myCheckBox.labelText.fontSize = fontSize; myCheckBox.SetLabelText(label); } myCheckBox.uiButton.onClick += myCheckBox.OnClick; if ((Object)(object)myCheckBox.checkImage != (Object)null) { ((Behaviour)myCheckBox.checkImage).enabled = check; } return myCheckBox; } public void SetLabelText(string val) { if ((Object)(object)labelText != (Object)null) { labelText.text = val; } } public void OnClick(int obj) { _checked = !_checked; ((Behaviour)checkImage).enabled = _checked; this.OnChecked?.Invoke(); } } } namespace Dustbin.NebulaSupport.Packet { public class SyncPlanetData { public byte[] Data { get; set; } public SyncPlanetData() { } public SyncPlanetData(byte[] data) { Data = data; } } public class ToggleEvent { public int PlanetId { get; set; } public int StorageId { get; set; } public bool Enable { get; set; } public ToggleEvent() { } public ToggleEvent(int planetId, int storageId, bool enable) { PlanetId = planetId; StorageId = storageId; Enable = enable; } } [RegisterPacketProcessor] internal class SyncPlanetDataProcessor : BasePacketProcessor { public override void ProcessPacket(SyncPlanetData packet, INebulaConnection conn) { Dustbin.ImportData(packet.Data); } } [RegisterPacketProcessor] internal class ToggleEventProcessor : BasePacketProcessor { public override void ProcessPacket(ToggleEvent packet, INebulaConnection conn) { PlanetFactory val = GameMain.galaxy.PlanetById(packet.PlanetId)?.factory; if (val == null) { return; } int storageId = packet.StorageId; if (storageId >= 0) { if (storageId == 0) { NebulaModAPI.MultiplayerSession.Network.SendPacket(new SyncPlanetData(Dustbin.ExportData(val))); return; } val.factoryStorage.storagePool[storageId].IsDustbin = packet.Enable; StoragePatch.Reset(); } else { val.factoryStorage.tankPool[-storageId].IsDustbin = packet.Enable; TankPatch.Reset(); } } } }