From 96f160926cae8a7cc1dcd9c99ea8cc3986ecd837 Mon Sep 17 00:00:00 2001 From: Soar Qin Date: Mon, 10 Nov 2025 22:39:58 +0800 Subject: [PATCH] work in progress --- UXAssist/Functions/FactoryFunctions.cs | 15 +++-- UXAssist/ModsCompat/BlueprintTweaks.cs | 79 ++++++++++++++++++++++++++ UXAssist/Patches/PersistPatch.cs | 37 ++++++++++++ UXAssist/UXAssist.cs | 1 + 4 files changed, 128 insertions(+), 4 deletions(-) create mode 100644 UXAssist/ModsCompat/BlueprintTweaks.cs diff --git a/UXAssist/Functions/FactoryFunctions.cs b/UXAssist/Functions/FactoryFunctions.cs index 3756fc1..6d181d0 100644 --- a/UXAssist/Functions/FactoryFunctions.cs +++ b/UXAssist/Functions/FactoryFunctions.cs @@ -24,6 +24,13 @@ public static class FactoryFunctions cargoTraffic.AlterBeltConnections(beltId, 0, i0, i1, i2); } + public static bool ObjectIsBeltOrInserter(PlanetFactory factory, int objId) + { + if (objId == 0) return false; + ItemProto proto = LDB.items.Select(objId > 0 ? factory.entityPool[objId].protoId : factory.prebuildPool[-objId].protoId); + return proto != null && (proto.prefabDesc.isBelt || proto.prefabDesc.isInserter); + } + public static void DismantleBlueprintSelectedBuildings() { var player = GameMain.mainPlayer; @@ -50,7 +57,7 @@ public static class FactoryFunctions for (var j = 0; j < 2; j++) { factory.ReadObjectConn(objId, j, out _, out var connObjId, out _); - if (connObjId == 0 || factory.ObjectIsBelt(connObjId) || blueprintCopyTool.ObjectIsInserter(connObjId)) continue; + if (connObjId == 0 || ObjectIsBeltOrInserter(factory, connObjId)) continue; needCheck = true; break; } @@ -59,7 +66,7 @@ public static class FactoryFunctions for (var k = 0; k < 16; k++) { factory.ReadObjectConn(objId, k, out _, out var connObjId, out _); - if (connObjId != 0 && (index = buildPreviewsToRemove.BinarySearch(connObjId)) < 0 && (factory.ObjectIsBelt(connObjId) || blueprintCopyTool.ObjectIsInserter(connObjId))) + if (connObjId != 0 && (index = buildPreviewsToRemove.BinarySearch(connObjId)) < 0 && ObjectIsBeltOrInserter(factory, connObjId)) buildPreviewsToRemove.Insert(~index, connObjId); } } @@ -70,7 +77,7 @@ public static class FactoryFunctions for (var j = 0; j < 2; j++) { factory.ReadObjectConn(connObjId, j, out _, out var connObjId2, out _); - if (connObjId2 == 0 || (index = buildPreviewsToRemove.BinarySearch(connObjId2)) >= 0 || factory.ObjectIsBelt(connObjId2) || blueprintCopyTool.ObjectIsInserter(connObjId2)) continue; + if (connObjId2 == 0 || (index = buildPreviewsToRemove.BinarySearch(connObjId2)) >= 0 || ObjectIsBeltOrInserter(factory, connObjId2)) continue; buildPreviewsToRemove.Insert(~index, connObjId); break; } @@ -81,7 +88,7 @@ public static class FactoryFunctions for (var j = 0; j < 16; j++) { factory.ReadObjectConn(objId, j, out _, out var connObjId, out _); - if (connObjId != 0 && (index = buildPreviewsToRemove.BinarySearch(connObjId)) < 0 && (factory.ObjectIsBelt(connObjId) || blueprintCopyTool.ObjectIsInserter(connObjId))) + if (connObjId != 0 && (index = buildPreviewsToRemove.BinarySearch(connObjId)) < 0 && ObjectIsBeltOrInserter(factory, connObjId)) buildPreviewsToRemove.Insert(~index, connObjId); } } diff --git a/UXAssist/ModsCompat/BlueprintTweaks.cs b/UXAssist/ModsCompat/BlueprintTweaks.cs new file mode 100644 index 0000000..13c92bc --- /dev/null +++ b/UXAssist/ModsCompat/BlueprintTweaks.cs @@ -0,0 +1,79 @@ +using HarmonyLib; +using System.Collections.Generic; +using System.Reflection; +using UXAssist.Functions; + +namespace UXAssist.ModsCompat; + +class BlueprintTweaks +{ + public const string BlueprintTweaksGuid = "org.kremnev8.plugin.BlueprintTweaks"; + private static FieldInfo selectObjIdsField; + + public static bool Run(Harmony harmony) + { + if (!BepInEx.Bootstrap.Chainloader.PluginInfos.TryGetValue(BlueprintTweaksGuid, out var pluginInfo)) return false; + var assembly = pluginInfo.Instance.GetType().Assembly; + var classType = assembly.GetType("BlueprintTweaks.DragRemoveBuildTool"); + selectObjIdsField = AccessTools.Field(classType, "selectObjIds"); + harmony.Patch(AccessTools.Method(classType, "DeterminePreviews"), + new HarmonyMethod(AccessTools.Method(typeof(BlueprintTweaks), nameof(PatchDeterminePreviews)))); + return true; + } + + public static void PatchDeterminePreviews(object __instance) + { + var selectObjIds = (HashSet)selectObjIdsField.GetValue(__instance); + var buildTool = (BuildTool)__instance; + var factory = buildTool.factory; + HashSet extraObjIds = []; + foreach (var objId in selectObjIds) + { + var desc = buildTool.GetPrefabDesc(objId); + var isBelt = desc.isBelt; + var isInserter = desc.isInserter; + if (isInserter) continue; + if (isBelt) + { + var needCheck = false; + for (var j = 0; j < 2; j++) + { + factory.ReadObjectConn(objId, j, out _, out var connObjId, out _); + if (connObjId == 0 || FactoryFunctions.ObjectIsBeltOrInserter(factory, connObjId)) continue; + needCheck = true; + break; + } + if (needCheck) + { + for (var k = 0; k < 16; k++) + { + factory.ReadObjectConn(objId, k, out _, out var connObjId, out _); + if (connObjId != 0 && !selectObjIds.Contains(connObjId) && !extraObjIds.Contains(connObjId) && FactoryFunctions.ObjectIsBeltOrInserter(factory, connObjId)) + extraObjIds.Add(connObjId); + } + } + for (var m = 0; m < 4; m++) + { + factory.ReadObjectConn(objId, m, out _, out var connObjId, out _); + if (connObjId == 0 || !factory.ObjectIsBelt(connObjId) || selectObjIds.Contains(connObjId) || extraObjIds.Contains(connObjId)) continue; + for (var j = 0; j < 2; j++) + { + factory.ReadObjectConn(connObjId, j, out _, out var connObjId2, out _); + if (connObjId2 == 0 || selectObjIds.Contains(connObjId2) || extraObjIds.Contains(connObjId2) || FactoryFunctions.ObjectIsBeltOrInserter(factory, connObjId2)) continue; + extraObjIds.Add(connObjId); + break; + } + } + continue; + } + if (desc.addonType == EAddonType.Belt) continue; + for (var j = 0; j < 16; j++) + { + factory.ReadObjectConn(objId, j, out _, out var connObjId, out _); + if (connObjId != 0 && !selectObjIds.Contains(connObjId) && !extraObjIds.Contains(connObjId) && FactoryFunctions.ObjectIsBeltOrInserter(factory, connObjId)) + extraObjIds.Add(connObjId); + } + } + selectObjIds.UnionWith(extraObjIds); + } +} diff --git a/UXAssist/Patches/PersistPatch.cs b/UXAssist/Patches/PersistPatch.cs index 0256ee5..52a645f 100644 --- a/UXAssist/Patches/PersistPatch.cs +++ b/UXAssist/Patches/PersistPatch.cs @@ -4,6 +4,7 @@ using System.Reflection.Emit; using HarmonyLib; using UnityEngine; using UXAssist.Common; +using GameLogicProc = UXAssist.Common.GameLogic; namespace UXAssist.Patches; @@ -12,10 +13,12 @@ public class PersistPatch : PatchImpl public static void Start() { Enable(true); + GameLogicProc.OnGameBegin += GameMain_Begin_Postfix; } public static void Uninit() { + GameLogicProc.OnGameBegin -= GameMain_Begin_Postfix; Enable(false); } @@ -223,6 +226,8 @@ public class PersistPatch : PatchImpl return matcher.InstructionEnumeration(); } + private static long nextTimei = 0; + private static void EntityFastTakeOutAlt(PlanetFactory factory, int entityId, bool toPackage, out ItemBundle itemBundle, out bool full) { if (factory._tmp_items == null) @@ -235,6 +240,8 @@ public class PersistPatch : PatchImpl } itemBundle = factory._tmp_items; full = false; + if (GameMain.instance.timei < nextTimei) return; + nextTimei = GameMain.instance.timei + 12; if (entityId == 0 || factory.entityPool[entityId].id != entityId) { return; @@ -249,6 +256,31 @@ public class PersistPatch : PatchImpl var buffer = cargoPath.buffer; Dictionary takeOutItems = []; var mainPlayer = factory.gameData.mainPlayer; + var factorySystem = factory.factorySystem; + foreach (var beltId in cargoPath.belts) + { + ref var b = ref cargoTraffic.beltPool[beltId]; + if (b.id != beltId) return; + // From WriteObjectConn: Only slot 4 to 11 is used for belt <-> inserter connections (slot/otherSlot is -1 there) + for (int cidx = 4; cidx < 12; cidx++) + { + factory.ReadObjectConn(b.entityId, cidx, out var isOutput, out var otherObjId, out var otherSlot); + if (otherObjId <= 0) continue; + var inserterId = factory.entityPool[otherObjId].inserterId; + if (inserterId <= 0) continue; + ref var inserter = ref factorySystem.inserterPool[inserterId]; + if (inserter.id != inserterId) continue; + if (inserter.itemId > 0 && inserter.stackCount > 0) + { + takeOutItems[inserter.itemId] = (takeOutItems.TryGetValue(inserter.itemId, out var value) ? value : 0) + + ((long)inserter.itemCount | ((long)inserter.itemInc << 32)); + inserter.itemId = 0; + inserter.stackCount = 0; + inserter.itemCount = 0; + inserter.itemInc = 0; + } + } + } int i = 0; while (i <= end) { @@ -285,4 +317,9 @@ public class PersistPatch : PatchImpl } } } + + private static void GameMain_Begin_Postfix() + { + nextTimei = 0; + } } diff --git a/UXAssist/UXAssist.cs b/UXAssist/UXAssist.cs index e2cc379..2e94b61 100644 --- a/UXAssist/UXAssist.cs +++ b/UXAssist/UXAssist.cs @@ -56,6 +56,7 @@ public class UXAssist : BaseUnityPlugin, IModCanSave UXAssist() { ModsCompat.PlanetVeinUtilization.Run(_harmony); + ModsCompat.BlueprintTweaks.Run(_harmony); ModsCompat.CommonAPIWrapper.Run(_harmony); }