using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
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.3.3.0")]
[assembly: AssemblyInformationalVersion("1.3.3+e2d83ee3cba46207f73d983cb0fd76c6dd66618b")]
[assembly: AssemblyProduct("Dustbin")]
[assembly: AssemblyTitle("Dustbin")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.3.3.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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<int>[] _signalBelts;
private static int _signalBeltsCapacity;
private static bool _initialized;
private static AssetBundle _bundle;
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;
}
[HarmonyPostfix]
[HarmonyPriority(0)]
[HarmonyPatch(typeof(VFPreload), "InvokeOnLoadWorkEnded")]
private static void VFPreload_InvokeOnLoadWorkEnded_Postfix()
{
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: 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_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_008b: Expected O, but got Unknown
if (!_initialized)
{
_bundle = AssetBundle.LoadFromFile(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/dustbin.assetbundle");
SignalProtoSet signals = LDB._signals;
int value = ((ProtoSet<SignalProto>)(object)signals).dataArray.Length;
SignalProto val = new SignalProto
{
ID = 410,
Name = "DUSTBIN",
GridIndex = 3110,
IconPath = "Assets/signal-410.png",
_iconSprite = _bundle.LoadAsset<Sprite>("Assets/signal-410.png"),
SID = ""
};
((Proto)val).name = Localization.Translate(((Proto)val).Name);
((ProtoSet<SignalProto>)(object)signals).dataArray = CollectionExtensions.AddItem<SignalProto>((IEnumerable<SignalProto>)((ProtoSet<SignalProto>)(object)signals).dataArray, val).ToArray();
((ProtoSet<SignalProto>)(object)signals).dataIndices[((Proto)val).ID] = value;
_initialized = true;
}
}
private static void InitSignalBelts()
{
if (!GameMain.isRunning)
{
return;
}
_signalBelts = new HashSet<int>[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<int> GetOrCreateSignalBelts(int index)
{
if (index < 0)
{
return null;
}
HashSet<int> hashSet;
if (index >= _signalBeltsCapacity)
{
int num = _signalBeltsCapacity * 2;
HashSet<int>[] array = new HashSet<int>[num];
Array.Copy(_signalBelts, array, _signalBeltsCapacity);
_signalBelts = array;
_signalBeltsCapacity = num;
}
else
{
hashSet = _signalBelts[index];
if (hashSet != null)
{
return hashSet;
}
}
hashSet = new HashSet<int>();
_signalBelts[index] = hashSet;
return hashSet;
}
private static HashSet<int> 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);
}
}
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(GameData), "GameTick")]
public static IEnumerable<CodeInstruction> GameData_GameTick_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Expected O, but got Unknown
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Expected O, but got Unknown
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Expected O, but got Unknown
CodeMatcher val = new CodeMatcher(instructions, generator);
val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1]
{
new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(PerformanceMonitor), "EndSample", (Type[])null, (Type[])null), (string)null)
}).Advance(1).Insert((CodeInstruction[])(object)new CodeInstruction[1]
{
new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(BeltSignal), "ProcessBeltSignals", (Type[])null, (Type[])null))
});
return val.InstructionEnumeration();
}
public static void ProcessBeltSignals()
{
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<int> 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);
}
}
}
}
}
[BepInPlugin("org.soardev.dustbin", "Dustbin", "1.3.3")]
[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.3.3";
public bool CheckVersion(string hostVersion, string clientVersion)
{
return hostVersion.Equals(clientVersion);
}
private void Awake()
{
bool value = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "StorageDustbin", true, "Can turn storages into dustbins").Value;
bool value2 = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "TankDustbin", true, "Can turn tanks into dustbins").Value;
bool value3 = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "BeltSignalDustbin", true, "Add belt signal as dustbin").Value;
string[] array = ((BaseUnityPlugin)this).Config.Bind<string>("General", "SandsFactors", "", "Sands 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<int>)Delegate.Combine(NebulaModAPI.OnPlanetLoadFinished, new Action<int>(RequestPlanetDustbinData));
}
}
private void OnDestroy()
{
TankPatch.Enable(on: false);
StoragePatch.Enable(on: false);
BeltSignal.Enable(on: false);
NebulaModAPI.OnPlanetLoadFinished = (Action<int>)Delegate.Remove(NebulaModAPI.OnPlanetLoadFinished, new Action<int>(RequestPlanetDustbinData));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int CalcGetSands(int itemId, int count)
{
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<int> list = new List<int>();
List<int> list2 = new List<int>();
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<ToggleEvent>(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 @checked = _storageDustbinCheckBox.Checked;
storagePool[storageId].IsDustbin = @checked;
if (NebulaModAPI.IsMultiplayerActive)
{
int planetId = window.factory.planetId;
NebulaModAPI.MultiplayerSession.Network.SendPacketToLocalStar<ToggleEvent>(new ToggleEvent(planetId, storageId, @checked));
}
}
}
};
}
[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<CodeInstruction> StorageComponent_AddItem_HarmonyTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Expected O, but got Unknown
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Expected O, but got Unknown
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Expected O, but got Unknown
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Expected O, but got Unknown
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Expected O, but got Unknown
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Expected O, but got Unknown
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Expected O, but got Unknown
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: Expected O, but got Unknown
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
//IL_00d0: Expected O, but got Unknown
CodeMatcher val = new CodeMatcher(instructions, generator);
Label label = generator.DefineLabel();
val.Start().MatchForward(false, (CodeMatch[])(object)new CodeMatch[1]
{
new CodeMatch((OpCode?)OpCodes.Stind_I4, (object)null, (string)null)
}).Advance(1)
.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[7]
{
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_1, (object)null),
new CodeInstruction(OpCodes.Ldarg_2, (object)null),
new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Dustbin), "CalcGetSands", (Type[])null, (Type[])null)),
new CodeInstruction(OpCodes.Ret, (object)null)
});
val.Labels.Add(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 @checked = _tankDustbinCheckBox.Checked;
tankPool[tankId].IsDustbin = @checked;
if (NebulaModAPI.IsMultiplayerActive)
{
int planetId = window.factory.planetId;
NebulaModAPI.MultiplayerSession.Network.SendPacketToLocalStar<ToggleEvent>(new ToggleEvent(planetId, -tankId, @checked));
}
}
}
};
}
[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 (fluidId <= 0)
{
if (fluidId == 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;
}
return;
}
}
else if (thisTank.fluidCount < thisTank.fluidCapacity && cargoTraffic.TryPickItemAtRear(belt, thisTank.fluidId, (int[])null, ref b, ref b2) > 0 && !thisTank.IsDustbin)
{
thisTank.fluidCount += b;
thisTank.fluidInc += b2;
return;
}
if (thisTank.fluidCount < thisTank.fluidCapacity || cargoTraffic.GetItemIdAtRear(belt) != thisTank.fluidId || thisTank.nextTankId <= 0)
{
return;
}
ref TankComponent reference = ref tankPool[thisTank.nextTankId];
while (reference.fluidCount >= reference.fluidCapacity)
{
ref TankComponent reference2 = ref tankPool[reference.lastTankId];
if (reference.fluidId != reference2.fluidId)
{
if (reference2.id == thisTank.id || reference.fluidCount >= reference.fluidCapacity)
{
return;
}
reference = ref reference2;
break;
}
if (!reference.inputSwitch)
{
if (reference2.id == thisTank.id || reference.fluidCount >= reference.fluidCapacity)
{
return;
}
reference = ref reference2;
break;
}
if (reference.nextTankId <= 0)
{
break;
}
reference = ref tankPool[reference.nextTankId];
}
ref TankComponent reference3 = ref tankPool[reference.lastTankId];
if (!reference.inputSwitch)
{
reference = ref reference3;
}
else
{
int fluidId2 = reference.fluidId;
if (fluidId2 != 0 && fluidId2 != reference3.fluidId)
{
if (reference3.id == thisTank.id || reference.fluidCount >= reference.fluidCapacity)
{
return;
}
reference = ref reference3;
}
else if (!reference3.outputSwitch)
{
return;
}
}
if (cargoTraffic.TryPickItemAtRear(belt, thisTank.fluidId, (int[])null, ref b, ref b2) > 0 && !reference.IsDustbin)
{
if (reference.fluidCount == 0)
{
reference.fluidId = thisTank.fluidId;
}
reference.fluidCount += b;
reference.fluidInc += b2;
}
}
}
}
public static class PluginInfo
{
public const string PLUGIN_GUID = "org.soardev.dustbin";
public const string PLUGIN_NAME = "Dustbin";
public const string PLUGIN_VERSION = "1.3.3";
}
}
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<GameObject>(((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>();
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<UIButton>();
Transform obj = val.transform.Find("checked");
myCheckBox.checkImage = ((obj != null) ? ((Component)obj).GetComponent<Image>() : null);
Transform val3 = val.transform.Find("text");
if ((Object)(object)val3 != (Object)null)
{
Object.DestroyImmediate((Object)(object)((Component)val3).GetComponent<Localizer>());
myCheckBox.labelText = ((Component)val3).GetComponent<Text>();
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<SyncPlanetData>
{
public override void ProcessPacket(SyncPlanetData packet, INebulaConnection conn)
{
Dustbin.ImportData(packet.Data);
}
}
[RegisterPacketProcessor]
internal class ToggleEventProcessor : BasePacketProcessor<ToggleEvent>
{
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<SyncPlanetData>(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();
}
}
}
}