mirror of
https://github.com/soarqin/DSP_Mods.git
synced 2025-12-08 19:33:27 +08:00
Dustbin 1.3.0 WIP
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,3 +1,6 @@
|
|||||||
|
# C# project files
|
||||||
|
*.user
|
||||||
|
|
||||||
# Rider project files
|
# Rider project files
|
||||||
/.idea/
|
/.idea/
|
||||||
|
|
||||||
@@ -5,6 +8,9 @@
|
|||||||
bin/
|
bin/
|
||||||
obj/
|
obj/
|
||||||
|
|
||||||
|
# C++ build folders
|
||||||
|
build/
|
||||||
|
|
||||||
# packaged files
|
# packaged files
|
||||||
/*/package/*.zip
|
/*/package/*.zip
|
||||||
/*/package/patchers/
|
/*/package/patchers/
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LabOpt", "LabOpt\LabOpt.csp
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LabOptPreloader", "LabOptPreloader\LabOptPreloader.csproj", "{F2D5EBE8-7D9D-4572-9A3E-4DD1114FD99F}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LabOptPreloader", "LabOptPreloader\LabOptPreloader.csproj", "{F2D5EBE8-7D9D-4572-9A3E-4DD1114FD99F}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DustbinPreloader", "DustbinPreloader\DustbinPreloader.csproj", "{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -75,5 +77,9 @@ Global
|
|||||||
{F2D5EBE8-7D9D-4572-9A3E-4DD1114FD99F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{F2D5EBE8-7D9D-4572-9A3E-4DD1114FD99F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{F2D5EBE8-7D9D-4572-9A3E-4DD1114FD99F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{F2D5EBE8-7D9D-4572-9A3E-4DD1114FD99F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{F2D5EBE8-7D9D-4572-9A3E-4DD1114FD99F}.Release|Any CPU.Build.0 = Release|Any CPU
|
{F2D5EBE8-7D9D-4572-9A3E-4DD1114FD99F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|||||||
@@ -1,18 +1,23 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using BepInEx;
|
using BepInEx;
|
||||||
using crecheng.DSPModSave;
|
using crecheng.DSPModSave;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
|
using NebulaAPI;
|
||||||
|
|
||||||
namespace Dustbin;
|
namespace Dustbin;
|
||||||
|
|
||||||
[BepInPlugin(PluginInfo.PLUGIN_GUID, PluginInfo.PLUGIN_NAME, PluginInfo.PLUGIN_VERSION)]
|
[BepInPlugin(PluginInfo.PLUGIN_GUID, PluginInfo.PLUGIN_NAME, PluginInfo.PLUGIN_VERSION)]
|
||||||
[BepInDependency(DSPModSavePlugin.MODGUID)]
|
[BepInDependency(DSPModSavePlugin.MODGUID)]
|
||||||
public class Dustbin : BaseUnityPlugin, IModCanSave
|
[BepInDependency(NebulaModAPI.API_GUID)]
|
||||||
|
public class Dustbin : BaseUnityPlugin, IModCanSave, IMultiplayerMod
|
||||||
{
|
{
|
||||||
|
public string Version => PluginInfo.PLUGIN_VERSION;
|
||||||
|
|
||||||
private const ushort ModSaveVersion = 1;
|
private const ushort ModSaveVersion = 1;
|
||||||
|
|
||||||
public new static readonly BepInEx.Logging.ManualLogSource Logger =
|
public new static readonly BepInEx.Logging.ManualLogSource Logger =
|
||||||
BepInEx.Logging.Logger.CreateLogSource(PluginInfo.PLUGIN_NAME);
|
BepInEx.Logging.Logger.CreateLogSource(PluginInfo.PLUGIN_NAME);
|
||||||
|
|
||||||
@@ -20,6 +25,11 @@ public class Dustbin : BaseUnityPlugin, IModCanSave
|
|||||||
public static readonly int[] SandsFactors = { 0, 1, 5, 10, 100 };
|
public static readonly int[] SandsFactors = { 0, 1, 5, 10, 100 };
|
||||||
public static bool[] IsFluid;
|
public static bool[] IsFluid;
|
||||||
|
|
||||||
|
public bool CheckVersion(string hostVersion, string clientVersion)
|
||||||
|
{
|
||||||
|
return hostVersion.Equals(clientVersion);
|
||||||
|
}
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
_cfgEnabled = Config.Bind("General", "Enabled", _cfgEnabled, "enable/disable this plugin").Value;
|
_cfgEnabled = Config.Bind("General", "Enabled", _cfgEnabled, "enable/disable this plugin").Value;
|
||||||
@@ -31,6 +41,9 @@ public class Dustbin : BaseUnityPlugin, IModCanSave
|
|||||||
Harmony.CreateAndPatchAll(typeof(Dustbin));
|
Harmony.CreateAndPatchAll(typeof(Dustbin));
|
||||||
Harmony.CreateAndPatchAll(typeof(StoragePatch));
|
Harmony.CreateAndPatchAll(typeof(StoragePatch));
|
||||||
Harmony.CreateAndPatchAll(typeof(TankPatch));
|
Harmony.CreateAndPatchAll(typeof(TankPatch));
|
||||||
|
|
||||||
|
NebulaModAPI.RegisterPackets(Assembly.GetExecutingAssembly());
|
||||||
|
NebulaModAPI.OnPlanetLoadFinished += RequestPlanetDustbinData;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPrefix]
|
[HarmonyPrefix]
|
||||||
@@ -61,14 +74,97 @@ public class Dustbin : BaseUnityPlugin, IModCanSave
|
|||||||
public void Import(BinaryReader r)
|
public void Import(BinaryReader r)
|
||||||
{
|
{
|
||||||
var version = r.ReadUInt16();
|
var version = r.ReadUInt16();
|
||||||
if (version > 0)
|
if (version <= 0) return;
|
||||||
{
|
StoragePatch.Import(r);
|
||||||
StoragePatch.Import(r);
|
TankPatch.Import(r);
|
||||||
TankPatch.Import(r);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void IntoOtherSave()
|
public void IntoOtherSave()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static byte[] ExportData(PlanetFactory factory)
|
||||||
|
{
|
||||||
|
var planetId = factory.planetId;
|
||||||
|
var storageIds = new List<int>();
|
||||||
|
var tankIds = new List<int>();
|
||||||
|
|
||||||
|
var factoryStorage = factory.factoryStorage;
|
||||||
|
var storagePool = factoryStorage.storagePool;
|
||||||
|
for (var i = 1; i < factoryStorage.storageCursor; i++)
|
||||||
|
{
|
||||||
|
var storage = storagePool[i];
|
||||||
|
if (storage == null || storage.id != i) continue;
|
||||||
|
if ((bool)StoragePatch.IsDustbinField.GetValue(storage))
|
||||||
|
storageIds.Add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
var tankPool = factoryStorage.tankPool;
|
||||||
|
for (var i = 1; i < factoryStorage.tankCursor; i++)
|
||||||
|
{
|
||||||
|
ref var tank = ref tankPool[i];
|
||||||
|
if (tank.id != i) continue;
|
||||||
|
if ((bool)TankPatch.IsDustbinField.GetValue(tank))
|
||||||
|
tankIds.Add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
using var p = NebulaModAPI.GetBinaryWriter();
|
||||||
|
using var w = p.BinaryWriter;
|
||||||
|
w.Write(planetId);
|
||||||
|
w.Write(storageIds.Count);
|
||||||
|
foreach (var storageId in storageIds)
|
||||||
|
w.Write(storageId);
|
||||||
|
w.Write(tankIds.Count);
|
||||||
|
foreach (var tankId in tankIds)
|
||||||
|
w.Write(tankId);
|
||||||
|
return p.CloseAndGetBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ImportData(byte[] bytes)
|
||||||
|
{
|
||||||
|
using var p = NebulaModAPI.GetBinaryReader(bytes);
|
||||||
|
using var r = p.BinaryReader;
|
||||||
|
var planetId = r.ReadInt32();
|
||||||
|
var factory = GameMain.galaxy.PlanetById(planetId)?.factory;
|
||||||
|
if (factory == null) return;
|
||||||
|
|
||||||
|
var factoryStorage = factory.factoryStorage;
|
||||||
|
var count = r.ReadInt32();
|
||||||
|
var storagePool = factoryStorage.storagePool;
|
||||||
|
var cursor = factoryStorage.storageCursor;
|
||||||
|
for (var i = 1; i < cursor; i++)
|
||||||
|
{
|
||||||
|
var storage = storagePool[i];
|
||||||
|
if (storage == null || storage.id != i) continue;
|
||||||
|
StoragePatch.IsDustbinField.SetValue(storage, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
var id = r.ReadInt32();
|
||||||
|
StoragePatch.IsDustbinField.SetValue(storagePool[id], true);
|
||||||
|
}
|
||||||
|
|
||||||
|
count = r.ReadInt32();
|
||||||
|
var tankPool = factoryStorage.tankPool;
|
||||||
|
cursor = factoryStorage.tankCursor;
|
||||||
|
for (var i = 1; i < cursor; i++)
|
||||||
|
{
|
||||||
|
ref var tank = ref tankPool[i];
|
||||||
|
if (tank.id != i) continue;
|
||||||
|
StoragePatch.IsDustbinField.SetValueDirect(__makeref(tank), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
var id = r.ReadInt32();
|
||||||
|
StoragePatch.IsDustbinField.SetValueDirect(__makeref(tankPool[id]), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RequestPlanetDustbinData(int planetId)
|
||||||
|
{
|
||||||
|
if (NebulaModAPI.IsMultiplayerActive && NebulaModAPI.MultiplayerSession.LocalPlayer.IsClient)
|
||||||
|
NebulaModAPI.MultiplayerSession.Network.SendPacket(new NebulaSupport.Packet.ToggleEvent(planetId, 0, false));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<TargetFramework>net472</TargetFramework>
|
<TargetFramework>net472</TargetFramework>
|
||||||
<BepInExPluginGuid>org.soardev.dustbin</BepInExPluginGuid>
|
<BepInExPluginGuid>org.soardev.dustbin</BepInExPluginGuid>
|
||||||
<Description>DSP MOD - Dustbin</Description>
|
<Description>DSP MOD - Dustbin</Description>
|
||||||
<Version>1.2.1</Version>
|
<Version>1.3.0</Version>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<PackageId>Dustbin</PackageId>
|
<PackageId>Dustbin</PackageId>
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*" />
|
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*" />
|
||||||
<PackageReference Include="DysonSphereProgram.GameLibs" Version="*-r.*" />
|
<PackageReference Include="DysonSphereProgram.GameLibs" Version="*-r.*" />
|
||||||
<PackageReference Include="DysonSphereProgram.Modding.DSPModSave" Version="1.*" />
|
<PackageReference Include="DysonSphereProgram.Modding.DSPModSave" Version="1.*" />
|
||||||
|
<PackageReference Include="DysonSphereProgram.Modding.NebulaMultiplayerModApi" Version="1.3.1" />
|
||||||
<PackageReference Include="UnityEngine.Modules" Version="2018.4.12" IncludeAssets="compile" />
|
<PackageReference Include="UnityEngine.Modules" Version="2018.4.12" IncludeAssets="compile" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
@@ -23,7 +24,8 @@
|
|||||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
|
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||||
<Exec Command="del /F /Q package\$(ProjectName)-$(Version).zip
zip -9 -j package/$(ProjectName)-$(Version).zip $(TargetPath) package/icon.png package/manifest.json README.md" />
|
<Exec Command="del /F /Q package\$(ProjectName)-$(Version).zip
IF NOT EXIST package\plugins (mkdir package\plugins)
copy /y $(TargetPath) package\plugins\
zip -9 -j package/$(ProjectName)-$(Version).zip package/icon.png package/manifest.json README.md
cd package
zip -9 -r $(ProjectName)-$(Version).zip patchers plugins" />
|
||||||
</Target>
|
</Target>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using UnityEngine.UI;
|
|||||||
|
|
||||||
namespace Dustbin;
|
namespace Dustbin;
|
||||||
|
|
||||||
// MyCheckbox modified from LSTM: https://github.com/hetima/DSP_LSTM/blob/main/LSTM/LSTM.cs
|
// MyCheckBox modified from LSTM: https://github.com/hetima/DSP_LSTM/blob/main/LSTM/MyCheckBox.cs
|
||||||
public class MyCheckBox : MonoBehaviour
|
public class MyCheckBox : MonoBehaviour
|
||||||
{
|
{
|
||||||
public UIButton uiButton;
|
public UIButton uiButton;
|
||||||
@@ -27,14 +27,18 @@ public class MyCheckBox : MonoBehaviour
|
|||||||
|
|
||||||
public static MyCheckBox CreateCheckBox(bool check, Transform parent = null, float x = 0f, float y = 0f, string label = "", int fontSize = 15)
|
public static MyCheckBox CreateCheckBox(bool check, Transform parent = null, float x = 0f, float y = 0f, string label = "", int fontSize = 15)
|
||||||
{
|
{
|
||||||
UIBuildMenu buildMenu = UIRoot.instance.uiGame.buildMenu;
|
var buildMenu = UIRoot.instance.uiGame.buildMenu;
|
||||||
UIButton src = buildMenu.uxFacilityCheck;
|
var src = buildMenu.uxFacilityCheck;
|
||||||
|
|
||||||
GameObject go = GameObject.Instantiate(src.gameObject);
|
var go = Instantiate(src.gameObject);
|
||||||
|
var rect = go.transform as RectTransform;
|
||||||
|
if (rect == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
go.name = "my-checkbox";
|
go.name = "my-checkbox";
|
||||||
MyCheckBox cb = go.AddComponent<MyCheckBox>();
|
var cb = go.AddComponent<MyCheckBox>();
|
||||||
cb._checked = check;
|
cb._checked = check;
|
||||||
RectTransform rect = go.transform as RectTransform;
|
|
||||||
if (parent != null)
|
if (parent != null)
|
||||||
{
|
{
|
||||||
rect.SetParent(parent);
|
rect.SetParent(parent);
|
||||||
@@ -47,14 +51,11 @@ public class MyCheckBox : MonoBehaviour
|
|||||||
cb.rectTrans = rect;
|
cb.rectTrans = rect;
|
||||||
cb.uiButton = go.GetComponent<UIButton>();
|
cb.uiButton = go.GetComponent<UIButton>();
|
||||||
cb.checkImage = go.transform.Find("checked")?.GetComponent<Image>();
|
cb.checkImage = go.transform.Find("checked")?.GetComponent<Image>();
|
||||||
//ResetAnchor(cb.checkImage.rectTransform);
|
|
||||||
|
|
||||||
//text
|
var child = go.transform.Find("text");
|
||||||
Transform child = go.transform.Find("text");
|
|
||||||
if (child != null)
|
if (child != null)
|
||||||
{
|
{
|
||||||
//ResetAnchor(child as RectTransform);
|
DestroyImmediate(child.GetComponent<Localizer>());
|
||||||
GameObject.DestroyImmediate(child.GetComponent<Localizer>());
|
|
||||||
cb.labelText = child.GetComponent<Text>();
|
cb.labelText = child.GetComponent<Text>();
|
||||||
cb.labelText.fontSize = fontSize;
|
cb.labelText.fontSize = fontSize;
|
||||||
cb.SetLabelText(label);
|
cb.SetLabelText(label);
|
||||||
@@ -62,7 +63,10 @@ public class MyCheckBox : MonoBehaviour
|
|||||||
|
|
||||||
//value
|
//value
|
||||||
cb.uiButton.onClick += cb.OnClick;
|
cb.uiButton.onClick += cb.OnClick;
|
||||||
cb.checkImage.enabled = check;
|
if (cb.checkImage != null)
|
||||||
|
{
|
||||||
|
cb.checkImage.enabled = check;
|
||||||
|
}
|
||||||
|
|
||||||
return cb;
|
return cb;
|
||||||
}
|
}
|
||||||
|
|||||||
77
Dustbin/NebulaSupport/Packets.cs
Normal file
77
Dustbin/NebulaSupport/Packets.cs
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
using NebulaAPI;
|
||||||
|
|
||||||
|
namespace Dustbin.NebulaSupport
|
||||||
|
{
|
||||||
|
namespace 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)
|
||||||
|
{
|
||||||
|
var factory = GameMain.galaxy.PlanetById(packet.PlanetId)?.factory;
|
||||||
|
if (factory == null) return;
|
||||||
|
var storageId = packet.StorageId;
|
||||||
|
switch (storageId)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
NebulaModAPI.MultiplayerSession.Network.SendPacket(new SyncPlanetData(Dustbin.ExportData(factory)));
|
||||||
|
return;
|
||||||
|
case < 0:
|
||||||
|
{
|
||||||
|
var tankPool = factory.factoryStorage.tankPool;
|
||||||
|
TankPatch.IsDustbinField.SetValue(tankPool[-storageId], packet.Enable);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
var storagePool = factory.factoryStorage.storagePool;
|
||||||
|
StoragePatch.IsDustbinField.SetValue(storagePool[storageId], packet.Enable);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,11 @@
|
|||||||
|
|
||||||
## Updates
|
## Updates
|
||||||
|
|
||||||
|
* 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/).
|
||||||
|
* Adopted bug fixes from [ModFixerOne](https://dsp.thunderstore.io/package/starfi5h/ModFixerOne/) by [starfi5h](https://github.com/starfi5h/).
|
||||||
|
|
||||||
* 1.2.1
|
* 1.2.1
|
||||||
* Fix dynamic array bug in codes, which causes various bugs and errors.
|
* Fix dynamic array bug in codes, which causes various bugs and errors.
|
||||||
|
|
||||||
@@ -28,7 +33,6 @@
|
|||||||
* Can get sands from destroyed items (with factors configurable):
|
* Can get sands from destroyed items (with factors configurable):
|
||||||
* Get 10/100 sands from each silicon/fractal silicon ore
|
* Get 10/100 sands from each silicon/fractal silicon ore
|
||||||
* Get 1 sand from any other normal item but fluid
|
* Get 1 sand from any other normal item but fluid
|
||||||
* Known bug: Tank with some fluids inside cannot output to belts if turned into dusbin, you can put a dustbin upon a normal tank to resolve this problem.
|
|
||||||
|
|
||||||
## 使用说明
|
## 使用说明
|
||||||
|
|
||||||
@@ -37,4 +41,3 @@
|
|||||||
* 可以从移除的物品中获得沙子(可配置,下为默认值):
|
* 可以从移除的物品中获得沙子(可配置,下为默认值):
|
||||||
* 从硅石和分形硅石中获得10/100个沙子。
|
* 从硅石和分形硅石中获得10/100个沙子。
|
||||||
* 从普通物品中获得1个沙子,但液体不会给沙子。
|
* 从普通物品中获得1个沙子,但液体不会给沙子。
|
||||||
* 已知问题:装有液体的储液罐变为垃圾桶后无法输出液体,可以在普通储液罐上面叠一个垃圾桶来解决这个问题。
|
|
||||||
|
|||||||
@@ -1,23 +1,15 @@
|
|||||||
using System.Collections.Generic;
|
using System.IO;
|
||||||
using System.IO;
|
using System.Reflection;
|
||||||
using System.Reflection.Emit;
|
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
|
using NebulaAPI;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Dustbin;
|
namespace Dustbin;
|
||||||
|
|
||||||
public class StorageComponentWithDustbin : StorageComponent
|
|
||||||
{
|
|
||||||
public bool IsDusbin;
|
|
||||||
public StorageComponentWithDustbin(int size): base(size)
|
|
||||||
{
|
|
||||||
IsDusbin = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPatch]
|
[HarmonyPatch]
|
||||||
public static class StoragePatch
|
public static class StoragePatch
|
||||||
{
|
{
|
||||||
|
public static readonly FieldInfo IsDustbinField = AccessTools.Field(typeof(StorageComponent), "IsDustbin");
|
||||||
private static MyCheckBox _storageDustbinCheckBox;
|
private static MyCheckBox _storageDustbinCheckBox;
|
||||||
private static int _lastStorageId;
|
private static int _lastStorageId;
|
||||||
|
|
||||||
@@ -43,7 +35,7 @@ public static class StoragePatch
|
|||||||
for (var j = 1; j < cursor; j++)
|
for (var j = 1; j < cursor; j++)
|
||||||
{
|
{
|
||||||
if (storagePool[j] == null || storagePool[j].id != j) continue;
|
if (storagePool[j] == null || storagePool[j].id != j) continue;
|
||||||
if (storagePool[j] is not StorageComponentWithDustbin { IsDusbin: true }) continue;
|
if (!(bool)IsDustbinField.GetValue(storagePool[j])) continue;
|
||||||
tempWriter.Write(j);
|
tempWriter.Write(j);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
@@ -81,10 +73,9 @@ public static class StoragePatch
|
|||||||
for (var count = r.ReadInt32(); count > 0; count--)
|
for (var count = r.ReadInt32(); count > 0; count--)
|
||||||
{
|
{
|
||||||
var id = r.ReadInt32();
|
var id = r.ReadInt32();
|
||||||
if (id > 0 && id < storagePool.Length && storagePool[id] != null && storagePool[id].id == id &&
|
if (id > 0 && id < storagePool.Length && storagePool[id] != null && storagePool[id].id == id)
|
||||||
storagePool[id] is StorageComponentWithDustbin comp)
|
|
||||||
{
|
{
|
||||||
comp.IsDusbin = true;
|
IsDustbinField.SetValue(storagePool[id], true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,8 +93,11 @@ public static class StoragePatch
|
|||||||
if (storageId <= 0) return;
|
if (storageId <= 0) return;
|
||||||
var storagePool = window.factoryStorage.storagePool;
|
var storagePool = window.factoryStorage.storagePool;
|
||||||
if (storagePool[storageId].id != storageId) return;
|
if (storagePool[storageId].id != storageId) return;
|
||||||
if (storagePool[storageId] is not StorageComponentWithDustbin comp) return;
|
var enabled = _storageDustbinCheckBox.Checked;
|
||||||
comp.IsDusbin = _storageDustbinCheckBox.Checked;
|
IsDustbinField.SetValue(storagePool[storageId], enabled);
|
||||||
|
if (!NebulaModAPI.IsMultiplayerActive) return;
|
||||||
|
var planetId = window.factory.planetId;
|
||||||
|
NebulaModAPI.MultiplayerSession.Network.SendPacketToLocalStar(new NebulaSupport.Packet.ToggleEvent(planetId, storageId, enabled));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,8 +111,7 @@ public static class StoragePatch
|
|||||||
if (storageId <= 0) return;
|
if (storageId <= 0) return;
|
||||||
var storagePool = __instance.factoryStorage.storagePool;
|
var storagePool = __instance.factoryStorage.storagePool;
|
||||||
if (storagePool[storageId].id != storageId) return;
|
if (storagePool[storageId].id != storageId) return;
|
||||||
if (storagePool[storageId] is not StorageComponentWithDustbin comp) return;
|
_storageDustbinCheckBox.Checked = (bool)IsDustbinField.GetValue(storagePool[storageId]);
|
||||||
_storageDustbinCheckBox.Checked = comp.IsDusbin;
|
|
||||||
if (__instance.transform is RectTransform rectTrans)
|
if (__instance.transform is RectTransform rectTrans)
|
||||||
{
|
{
|
||||||
_storageDustbinCheckBox.rectTrans.anchoredPosition3D = new Vector3(50, 58 - rectTrans.sizeDelta.y, 0);
|
_storageDustbinCheckBox.rectTrans.anchoredPosition3D = new Vector3(50, 58 - rectTrans.sizeDelta.y, 0);
|
||||||
@@ -144,7 +137,7 @@ public static class StoragePatch
|
|||||||
private static bool StorageComponent_AddItem_Prefix(ref int __result, StorageComponent __instance, int itemId, int count, int inc,
|
private static bool StorageComponent_AddItem_Prefix(ref int __result, StorageComponent __instance, int itemId, int count, int inc,
|
||||||
ref int remainInc, bool useBan = false)
|
ref int remainInc, bool useBan = false)
|
||||||
{
|
{
|
||||||
if (__instance is not StorageComponentWithDustbin { IsDusbin: true }) return true;
|
if (!(bool)IsDustbinField.GetValue(__instance)) return true;
|
||||||
remainInc = inc;
|
remainInc = inc;
|
||||||
__result = count;
|
__result = count;
|
||||||
var fluidArr = Dustbin.IsFluid;
|
var fluidArr = Dustbin.IsFluid;
|
||||||
@@ -162,9 +155,6 @@ public static class StoragePatch
|
|||||||
var addCount = count * sandsPerItem;
|
var addCount = count * sandsPerItem;
|
||||||
player.sandCount += addCount;
|
player.sandCount += addCount;
|
||||||
GameMain.history.OnSandCountChange(player.sandCount, addCount);
|
GameMain.history.OnSandCountChange(player.sandCount, addCount);
|
||||||
/* Following line crashes game, seems that it should not be called in this working thread:
|
|
||||||
* UIRoot.instance.uiGame.OnSandCountChanged(player.sandCount, addCount);
|
|
||||||
*/
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,29 +163,9 @@ public static class StoragePatch
|
|||||||
[HarmonyPatch(typeof(StorageComponent), "Import")]
|
[HarmonyPatch(typeof(StorageComponent), "Import")]
|
||||||
private static void StorageComponent_Import_Postfix(StorageComponent __instance)
|
private static void StorageComponent_Import_Postfix(StorageComponent __instance)
|
||||||
{
|
{
|
||||||
if (__instance.bans >= 0 || __instance is not StorageComponentWithDustbin comp)
|
if (__instance.bans >= 0)
|
||||||
return;
|
return;
|
||||||
__instance.bans = -__instance.bans - 1;
|
__instance.bans = -__instance.bans - 1;
|
||||||
comp.IsDusbin = true;
|
IsDustbinField.SetValue(__instance, true);
|
||||||
}
|
|
||||||
|
|
||||||
/* Replace: new StorageComponent(int) => new StorageComponentWithDustbin(int) */
|
|
||||||
[HarmonyTranspiler]
|
|
||||||
[HarmonyPatch(typeof(FactoryStorage), "Import")]
|
|
||||||
[HarmonyPatch(typeof(FactoryStorage), "NewStorageComponent")]
|
|
||||||
private static IEnumerable<CodeInstruction> FactoryStorage_NewStorageComponent_Transpiler(
|
|
||||||
IEnumerable<CodeInstruction> instructions)
|
|
||||||
{
|
|
||||||
foreach (var instr in instructions)
|
|
||||||
{
|
|
||||||
if (instr.opcode == OpCodes.Newobj && instr.OperandIs(AccessTools.Constructor(typeof(StorageComponent), new [] { typeof(int) })))
|
|
||||||
{
|
|
||||||
yield return new CodeInstruction(OpCodes.Newobj, AccessTools.Constructor(typeof(StorageComponentWithDustbin), new [] { typeof(int) }));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
yield return instr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,138 +1,58 @@
|
|||||||
using System;
|
using System.IO;
|
||||||
using System.IO;
|
using System.Reflection;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using HarmonyLib.Tools;
|
using NebulaAPI;
|
||||||
|
|
||||||
namespace Dustbin;
|
namespace Dustbin;
|
||||||
|
|
||||||
using IsDustbinIndexer = DynamicObjectArray<DynamicObjectArray<DynamicValueArray<bool>>>;
|
|
||||||
|
|
||||||
public class DynamicValueArray<T> where T: struct
|
|
||||||
{
|
|
||||||
private T[] _store = new T[64];
|
|
||||||
|
|
||||||
public T this[int index]
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (index < 0 || index >= _store.Length) return default;
|
|
||||||
return _store[index];
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (index >= _store.Length)
|
|
||||||
{
|
|
||||||
var count = index | (index >> 1);
|
|
||||||
count |= count >> 2;
|
|
||||||
count |= count >> 4;
|
|
||||||
count |= count >> 8;
|
|
||||||
count |= count >> 16;
|
|
||||||
Array.Resize(ref _store, count + 1);
|
|
||||||
}
|
|
||||||
_store[index] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Reset()
|
|
||||||
{
|
|
||||||
_store = new T[16];
|
|
||||||
}
|
|
||||||
|
|
||||||
public delegate void ForEachFunc(int id, T value);
|
|
||||||
public void ForEach(ForEachFunc func)
|
|
||||||
{
|
|
||||||
var len = _store.Length;
|
|
||||||
for (var i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
func(i, _store[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DynamicObjectArray<T> where T: class, new()
|
|
||||||
{
|
|
||||||
private T[] _store = new T[16];
|
|
||||||
|
|
||||||
public T this[int index]
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (index < 0) return null;
|
|
||||||
if (index >= _store.Length)
|
|
||||||
{
|
|
||||||
var count = index | (index >> 1);
|
|
||||||
count |= count >> 2;
|
|
||||||
count |= count >> 4;
|
|
||||||
count |= count >> 8;
|
|
||||||
count |= count >> 16;
|
|
||||||
Array.Resize(ref _store, count + 1);
|
|
||||||
}
|
|
||||||
T result = _store[index];
|
|
||||||
if (result != null)
|
|
||||||
return result;
|
|
||||||
result = new T();
|
|
||||||
_store[index] = result;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Reset()
|
|
||||||
{
|
|
||||||
_store = new T[16];
|
|
||||||
}
|
|
||||||
|
|
||||||
public delegate void ForEachFunc(int id, T value);
|
|
||||||
public void ForEach(ForEachFunc func)
|
|
||||||
{
|
|
||||||
var len = _store.Length;
|
|
||||||
for (var i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
func(i, _store[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPatch]
|
[HarmonyPatch]
|
||||||
public static class TankPatch
|
public static class TankPatch
|
||||||
{
|
{
|
||||||
|
public static readonly FieldInfo IsDustbinField = AccessTools.Field(typeof(TankComponent), "IsDustbin");
|
||||||
private static MyCheckBox _tankDustbinCheckBox;
|
private static MyCheckBox _tankDustbinCheckBox;
|
||||||
private static int lastTankId;
|
private static int _lastTankId;
|
||||||
private static IsDustbinIndexer tankIsDustbin = new();
|
|
||||||
|
|
||||||
public static void Reset()
|
public static void Reset()
|
||||||
{
|
{
|
||||||
lastTankId = 0;
|
_lastTankId = 0;
|
||||||
tankIsDustbin.Reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Export(BinaryWriter w)
|
public static void Export(BinaryWriter w)
|
||||||
{
|
{
|
||||||
var tempStream = new MemoryStream();
|
var tempStream = new MemoryStream();
|
||||||
var tempWriter = new BinaryWriter(tempStream);
|
var tempWriter = new BinaryWriter(tempStream);
|
||||||
tankIsDustbin.ForEach((i, star) =>
|
|
||||||
{
|
|
||||||
star?.ForEach((j, planet) =>
|
|
||||||
{
|
|
||||||
var count = 0;
|
|
||||||
planet?.ForEach((id, v) =>
|
|
||||||
{
|
|
||||||
if (!v) return;
|
|
||||||
tempWriter.Write(id);
|
|
||||||
count++;
|
|
||||||
});
|
|
||||||
if (count == 0) return;
|
|
||||||
|
|
||||||
tempWriter.Flush();
|
var factories = GameMain.data.factories;
|
||||||
tempStream.Position = 0;
|
var factoryCount = GameMain.data.factoryCount;
|
||||||
w.Write((byte)2);
|
for (var i = 0; i < factoryCount; i++)
|
||||||
var planetId = i * 100 + j;
|
{
|
||||||
w.Write(planetId);
|
var factory = factories[i];
|
||||||
w.Write(count);
|
if (factory == null) continue;
|
||||||
/* FixMe: May BinaryWriter not sync with its BaseStream while subclass overrides Write()? */
|
var storage = factory.factoryStorage;
|
||||||
tempStream.CopyTo(w.BaseStream);
|
var tankPool = storage.tankPool;
|
||||||
tempStream.SetLength(0);
|
var cursor = storage.tankCursor;
|
||||||
});
|
var count = 0;
|
||||||
});
|
|
||||||
|
for (var j = 1; j < cursor; j++)
|
||||||
|
{
|
||||||
|
if (tankPool[j].id != j) continue;
|
||||||
|
if (!(bool)IsDustbinField.GetValue(tankPool[j])) continue;
|
||||||
|
tempWriter.Write(j);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 0) continue;
|
||||||
|
|
||||||
|
tempWriter.Flush();
|
||||||
|
tempStream.Position = 0;
|
||||||
|
w.Write((byte)2);
|
||||||
|
w.Write(factory.planetId);
|
||||||
|
w.Write(count);
|
||||||
|
/* FixMe: May BinaryWriter not sync with its BaseStream while subclass overrides Write()? */
|
||||||
|
tempStream.CopyTo(w.BaseStream);
|
||||||
|
tempStream.SetLength(0);
|
||||||
|
}
|
||||||
|
|
||||||
tempWriter.Dispose();
|
tempWriter.Dispose();
|
||||||
tempStream.Dispose();
|
tempStream.Dispose();
|
||||||
}
|
}
|
||||||
@@ -143,13 +63,25 @@ public static class TankPatch
|
|||||||
{
|
{
|
||||||
r.ReadByte();
|
r.ReadByte();
|
||||||
var planetId = r.ReadInt32();
|
var planetId = r.ReadInt32();
|
||||||
var data = tankIsDustbin[15];
|
var planet = GameMain.data.galaxy.PlanetById(planetId);
|
||||||
data[0][0] = true;
|
var tankPool = planet?.factory.factoryStorage.tankPool;
|
||||||
data = tankIsDustbin[20];
|
if (tankPool == null)
|
||||||
data[0][0] = true;
|
{
|
||||||
|
for (var count = r.ReadInt32(); count > 0; count--)
|
||||||
|
{
|
||||||
|
r.ReadInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (var count = r.ReadInt32(); count > 0; count--)
|
for (var count = r.ReadInt32(); count > 0; count--)
|
||||||
{
|
{
|
||||||
tankIsDustbin[planetId / 100][planetId % 100][r.ReadInt32()] = true;
|
var id = r.ReadInt32();
|
||||||
|
if (id > 0 && id < tankPool.Length && tankPool[id].id == id)
|
||||||
|
{
|
||||||
|
IsDustbinField.SetValueDirect(__makeref(tankPool[id]), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,91 +95,155 @@ public static class TankPatch
|
|||||||
_tankDustbinCheckBox.OnChecked += () =>
|
_tankDustbinCheckBox.OnChecked += () =>
|
||||||
{
|
{
|
||||||
var tankId = window.tankId;
|
var tankId = window.tankId;
|
||||||
if (tankId <= 0 || window.storage.tankPool[tankId].id != tankId) return;
|
if (tankId <= 0) return;
|
||||||
var planetId = window.storage.planet.id;
|
var tankPool = window.storage.tankPool;
|
||||||
tankIsDustbin[planetId / 100][planetId % 100][tankId] = _tankDustbinCheckBox.Checked;
|
if (tankPool[tankId].id != tankId) return;
|
||||||
|
var enabled = _tankDustbinCheckBox.Checked;
|
||||||
|
IsDustbinField.SetValueDirect(__makeref(tankPool[tankId]), enabled);
|
||||||
|
if (!NebulaModAPI.IsMultiplayerActive) return;
|
||||||
|
var planetId = window.factory.planetId;
|
||||||
|
NebulaModAPI.MultiplayerSession.Network.SendPacketToLocalStar(new NebulaSupport.Packet.ToggleEvent(planetId, -tankId, enabled));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPostfix]
|
[HarmonyPostfix]
|
||||||
[HarmonyPatch(typeof(UITankWindow), "_OnUpdate")]
|
[HarmonyPatch(typeof(UITankWindow), "_OnUpdate")]
|
||||||
private static void UITankWindow__OnUpdate_Postfix(UITankWindow __instance)
|
private static void UITankWindow__OnUpdate_Postfix(UITankWindow __instance)
|
||||||
{
|
{
|
||||||
var tankId = __instance.tankId;
|
var tankId = __instance.tankId;
|
||||||
if (lastTankId == tankId) return;
|
if (_lastTankId == tankId) return;
|
||||||
lastTankId = tankId;
|
_lastTankId = tankId;
|
||||||
if (tankId > 0 && __instance.storage.tankPool[tankId].id == tankId)
|
|
||||||
{
|
|
||||||
var planetId = __instance.storage.planet.id;
|
|
||||||
_tankDustbinCheckBox.Checked = tankIsDustbin[planetId / 100][planetId % 100][tankId];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private struct TankState
|
if (tankId <= 0) return;
|
||||||
{
|
var tankPool = __instance.storage.tankPool;
|
||||||
public int TankId;
|
if (tankPool[tankId].id != tankId) return;
|
||||||
public int FluidId;
|
_tankDustbinCheckBox.Checked = (bool)IsDustbinField.GetValue(tankPool[tankId]);
|
||||||
public int FluidCount;
|
|
||||||
public int FluidInc;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPrefix]
|
|
||||||
[HarmonyPatch(typeof(TankComponent), "GameTick")]
|
|
||||||
private static void TankComponent_GameTick_Prefix(ref TankComponent __instance, ref TankState __state, PlanetFactory factory)
|
|
||||||
{
|
|
||||||
var planetId = factory.planetId;
|
|
||||||
var data = tankIsDustbin[planetId / 100][planetId % 100];
|
|
||||||
ref var tank = ref __instance;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (data[tank.id])
|
|
||||||
{
|
|
||||||
__state.TankId = tank.id;
|
|
||||||
__state.FluidId = tank.fluidId;
|
|
||||||
__state.FluidCount = tank.fluidCount;
|
|
||||||
__state.FluidInc = tank.fluidInc;
|
|
||||||
tank.fluidId = tank.fluidCount = tank.fluidInc = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (tank.fluidCount < tank.fluidCapacity || tank.nextTankId <= 0)
|
|
||||||
{
|
|
||||||
__state.TankId = -1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var nextTankId = tank.nextTankId;
|
|
||||||
tank = ref factory.factoryStorage.tankPool[nextTankId];
|
|
||||||
if (tank.id == nextTankId) continue;
|
|
||||||
__state.TankId = -1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPostfix]
|
|
||||||
[HarmonyPatch(typeof(TankComponent), "GameTick")]
|
|
||||||
private static void TankComponent_GameTick_Postfix(ref TankComponent __instance, ref TankState __state, PlanetFactory factory)
|
|
||||||
{
|
|
||||||
if (__state.TankId < 0) return;
|
|
||||||
var tankId = __state.TankId;
|
|
||||||
if (__instance.id == tankId)
|
|
||||||
{
|
|
||||||
__instance.fluidId = __state.FluidId;
|
|
||||||
__instance.fluidCount = __state.FluidCount;
|
|
||||||
__instance.fluidInc = __state.FluidInc;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ref var tank = ref factory.factoryStorage.tankPool[tankId];
|
|
||||||
if (tank.id != tankId) return;
|
|
||||||
tank.fluidId = __state.FluidId;
|
|
||||||
tank.fluidCount = __state.FluidCount;
|
|
||||||
tank.fluidInc = __state.FluidInc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPrefix]
|
[HarmonyPrefix]
|
||||||
[HarmonyPatch(typeof(FactoryStorage), "RemoveTankComponent")]
|
[HarmonyPatch(typeof(TankComponent), "GameTick")]
|
||||||
private static void FactoryStorage_RemoveTankComponent_Prefix(FactoryStorage __instance, int id)
|
private static bool TankComponent_GameTick_Prefix(ref TankComponent __instance, PlanetFactory factory)
|
||||||
{
|
{
|
||||||
if (__instance.tankPool[id].id <= 0) return;
|
if (__instance.fluidInc < 0)
|
||||||
var planetId = __instance.planet.id;
|
__instance.fluidInc = 0;
|
||||||
tankIsDustbin[planetId / 100][planetId % 100][id] = false;
|
|
||||||
|
if (!__instance.isBottom)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var cargoTraffic = factory.cargoTraffic;
|
||||||
|
var tankPool = factory.factoryStorage.tankPool;
|
||||||
|
var 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;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private static void TankComponentUpdateBelt(ref TankComponent thisTank, int belt, bool isOutput, ref CargoTraffic cargoTraffic, ref TankComponent[] tankPool)
|
||||||
|
{
|
||||||
|
switch (isOutput)
|
||||||
|
{
|
||||||
|
case true when thisTank.outputSwitch:
|
||||||
|
{
|
||||||
|
if (thisTank.fluidId <= 0 || thisTank.fluidCount <= 0) return;
|
||||||
|
var inc = thisTank.fluidInc == 0 ? 0 : thisTank.fluidInc / thisTank.fluidCount;
|
||||||
|
if (!cargoTraffic.TryInsertItemAtHead(belt, thisTank.fluidId, 1, (byte)inc)) return;
|
||||||
|
thisTank.fluidCount--;
|
||||||
|
thisTank.fluidInc -= inc;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case false when thisTank.inputSwitch:
|
||||||
|
{
|
||||||
|
byte stack;
|
||||||
|
byte inc;
|
||||||
|
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.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;
|
||||||
|
thisTank.fluidId = count;
|
||||||
|
thisTank.fluidCount += stack;
|
||||||
|
thisTank.fluidInc += inc;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thisTank.fluidCount < thisTank.fluidCapacity || cargoTraffic.GetItemIdAtRear(belt) != thisTank.fluidId || thisTank.nextTankId <= 0) return;
|
||||||
|
ref var targetTank = ref tankPool[thisTank.nextTankId];
|
||||||
|
while (targetTank.fluidCount >= targetTank.fluidCapacity)
|
||||||
|
{
|
||||||
|
ref var lastTank = ref tankPool[targetTank.lastTankId];
|
||||||
|
if (targetTank.fluidId != lastTank.fluidId)
|
||||||
|
{
|
||||||
|
targetTank = ref lastTank;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!targetTank.inputSwitch)
|
||||||
|
{
|
||||||
|
targetTank = ref lastTank;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetTank.nextTankId <= 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
targetTank = ref tankPool[targetTank.nextTankId];
|
||||||
|
}
|
||||||
|
|
||||||
|
ref var lastTank2 = ref tankPool[targetTank.lastTankId];
|
||||||
|
if (!targetTank.inputSwitch)
|
||||||
|
{
|
||||||
|
targetTank = ref lastTank2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var fluidId = targetTank.fluidId;
|
||||||
|
if (fluidId != 0 && fluidId != lastTank2.fluidId)
|
||||||
|
{
|
||||||
|
targetTank = ref lastTank2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetTank.id == thisTank.id || targetTank.fluidCount >= targetTank.fluidCapacity || !lastTank2.outputSwitch ||
|
||||||
|
cargoTraffic.TryPickItemAtRear(belt, thisTank.fluidId, null, out stack, out inc) <= 0 || (bool)IsDustbinField.GetValue(targetTank)) return;
|
||||||
|
if (targetTank.fluidCount == 0)
|
||||||
|
{
|
||||||
|
targetTank.fluidId = thisTank.fluidId;
|
||||||
|
}
|
||||||
|
|
||||||
|
targetTank.fluidCount += stack;
|
||||||
|
targetTank.fluidInc += inc;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "Dustbin",
|
"name": "Dustbin",
|
||||||
"version_number": "1.2.1",
|
"version_number": "1.3.0",
|
||||||
"website_url": "https://github.com/soarqin/DSP_Mods/tree/master/Dustbin",
|
"website_url": "https://github.com/soarqin/DSP_Mods/tree/master/Dustbin",
|
||||||
"description": "Can turn Storages and Tanks into Dustbin(Destroy incoming items) / 储物仓和储液罐可以转变为垃圾桶(销毁送进的物品)",
|
"description": "Can turn Storages and Tanks into Dustbin(Destroy incoming items) / 储物仓和储液罐可以转变为垃圾桶(销毁送进的物品)",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
"xiaoye97-BepInEx-5.4.17",
|
"xiaoye97-BepInEx-5.4.17",
|
||||||
"CommonAPI-DSPModSave-1.1.4"
|
"CommonAPI-DSPModSave-1.1.4",
|
||||||
|
"nebula-NebulaMultiplayerModApi-1.3.1"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
44
DustbinPreloader/DustbinPreloader.cs
Normal file
44
DustbinPreloader/DustbinPreloader.cs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using BepInEx.Logging;
|
||||||
|
using Mono.Cecil;
|
||||||
|
|
||||||
|
namespace DustbinPreloader;
|
||||||
|
|
||||||
|
public static class Preloader
|
||||||
|
{
|
||||||
|
private static readonly ManualLogSource Logger = BepInEx.Logging.Logger.CreateLogSource("Dustbin Preloader");
|
||||||
|
public static IEnumerable<string> TargetDLLs { get; } = new[] { "Assembly-CSharp.dll" };
|
||||||
|
|
||||||
|
public static void Patch(AssemblyDefinition assembly)
|
||||||
|
{
|
||||||
|
var gameModule = assembly.MainModule;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Add field: int StorageComponent.IsDustbin;
|
||||||
|
gameModule.GetType("StorageComponent").AddFied("IsDustbin", gameModule.TypeSystem.Boolean);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Logger.LogError("Failed to add `bool StorageComponent.IsDustbin`!");
|
||||||
|
Logger.LogError(e);
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Add field: int TankComponent.IsDustbin;
|
||||||
|
gameModule.GetType("TankComponent").AddFied("IsDustbin", gameModule.TypeSystem.Boolean);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Logger.LogError("Failed to add `bool TankComponent.IsDustbin`!");
|
||||||
|
Logger.LogError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddFied(this TypeDefinition typeDefinition, string fieldName, TypeReference fieldType)
|
||||||
|
{
|
||||||
|
var newField = new FieldDefinition(fieldName, FieldAttributes.Public, fieldType);
|
||||||
|
typeDefinition.Fields.Add(newField);
|
||||||
|
Logger.LogDebug("Add " + newField);
|
||||||
|
}
|
||||||
|
}
|
||||||
26
DustbinPreloader/DustbinPreloader.csproj
Normal file
26
DustbinPreloader/DustbinPreloader.csproj
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net472</TargetFramework>
|
||||||
|
<AssemblyName>DustbinPreloader</AssemblyName>
|
||||||
|
<Description>DSP MOD - Prealoder for Dustbin</Description>
|
||||||
|
<Version>1.3.0</Version>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="BepInEx.Core" Version="5.*" />
|
||||||
|
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*" />
|
||||||
|
<PackageReference Include="DysonSphereProgram.GameLibs" Version="*-r.*" />
|
||||||
|
<PackageReference Include="UnityEngine.Modules" Version="2018.4.12" IncludeAssets="compile" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
|
||||||
|
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||||
|
<Exec Command="IF NOT EXIST ..\Dustbin\package\patchers (mkdir ..\Dustbin\package\patchers)
copy /y $(TargetPath) ..\Dustbin\package\patchers\" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
||||||
@@ -12,7 +12,7 @@ namespace LabOptPreloader;
|
|||||||
|
|
||||||
public static class Preloader
|
public static class Preloader
|
||||||
{
|
{
|
||||||
private static readonly ManualLogSource Logger = BepInEx.Logging.Logger.CreateLogSource("ModFixerOne Preloader");
|
private static readonly ManualLogSource Logger = BepInEx.Logging.Logger.CreateLogSource("LabOpt Preloader");
|
||||||
public static IEnumerable<string> TargetDLLs { get; } = new[] { "Assembly-CSharp.dll" };
|
public static IEnumerable<string> TargetDLLs { get; } = new[] { "Assembly-CSharp.dll" };
|
||||||
|
|
||||||
public static void Patch(AssemblyDefinition assembly)
|
public static void Patch(AssemblyDefinition assembly)
|
||||||
|
|||||||
Reference in New Issue
Block a user