mirror of
https://github.com/soarqin/DSP_Mods.git
synced 2025-12-08 21:33:28 +08:00
finished new mechanism for blueprint building sorting
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace UXAssist.Functions;
|
||||
|
||||
@@ -135,4 +136,117 @@ public static class FactoryFunctions
|
||||
blueprintCopyTool.RefreshBlueprintData();
|
||||
blueprintCopyTool.DeterminePreviews();
|
||||
}
|
||||
|
||||
private struct BPBuildingData
|
||||
{
|
||||
public BlueprintBuilding building;
|
||||
public int itemType;
|
||||
public double offset;
|
||||
}
|
||||
|
||||
private struct BPBeltData
|
||||
{
|
||||
public BlueprintBuilding building;
|
||||
public double offset;
|
||||
}
|
||||
|
||||
private static HashSet<int> _itemIsBelt = null;
|
||||
private static Dictionary<int, int> _upgradeTypes = null;
|
||||
|
||||
public static void SortBlueprintData(BlueprintData blueprintData)
|
||||
{
|
||||
// Initialize itemIsBelt and upgradeTypes
|
||||
if (_itemIsBelt == null)
|
||||
{
|
||||
_itemIsBelt = [];
|
||||
_upgradeTypes = [];
|
||||
foreach (var proto in LDB.items.dataArray)
|
||||
{
|
||||
if (proto.prefabDesc?.isBelt ?? false)
|
||||
{
|
||||
_itemIsBelt.Add(proto.ID);
|
||||
continue;
|
||||
}
|
||||
if (proto.Upgrades != null && proto.Upgrades.Length > 0)
|
||||
{
|
||||
var minUpgrade = proto.Upgrades.Min(u => u);
|
||||
if (minUpgrade != 0 && minUpgrade != proto.ID)
|
||||
{
|
||||
_upgradeTypes.Add(proto.ID, minUpgrade);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Separate belt and non-belt buildings
|
||||
List<BPBuildingData> bpBuildings = [];
|
||||
Dictionary<BlueprintBuilding, BPBeltData> bpBelts = [];
|
||||
foreach (var building in blueprintData.buildings)
|
||||
{
|
||||
var offset = building.areaIndex * 1073741824.0 + building.localOffset_y * 262144.0 + building.localOffset_x * 1024.0 + building.localOffset_z;
|
||||
if (_itemIsBelt.Contains(building.itemId))
|
||||
{
|
||||
bpBelts.Add(building, new BPBeltData { building = building, offset = offset });
|
||||
}
|
||||
else
|
||||
{
|
||||
var itemType = _upgradeTypes.TryGetValue(building.itemId, out var upgradeType) ? upgradeType : building.itemId;
|
||||
bpBuildings.Add(new BPBuildingData { building = building, itemType = itemType, offset = offset });
|
||||
}
|
||||
}
|
||||
var beltsWithInput = bpBelts.Select(pair => pair.Value.building.outputObj).ToHashSet();
|
||||
var beltHeads = bpBelts.Where(pair => !beltsWithInput.Contains(pair.Value.building)).ToDictionary(pair => pair.Key, pair => pair.Value);
|
||||
// Sort belt buildings
|
||||
List<BlueprintBuilding> sortedBpBelts = [];
|
||||
// Deal with non-cycle belt paths
|
||||
foreach (var pair in beltHeads.OrderByDescending(pair => pair.Value.offset))
|
||||
{
|
||||
var building = pair.Key;
|
||||
while (building != null)
|
||||
{
|
||||
if (!bpBelts.Remove(building)) break;
|
||||
sortedBpBelts.Add(building);
|
||||
building = building.outputObj;
|
||||
}
|
||||
}
|
||||
// Deal with cycle belt paths
|
||||
foreach (var pair in bpBelts.OrderByDescending(pair => pair.Value.offset))
|
||||
{
|
||||
var building = pair.Key;
|
||||
while (building != null)
|
||||
{
|
||||
if (!bpBelts.Remove(building)) break;
|
||||
sortedBpBelts.Add(building);
|
||||
building = building.outputObj;
|
||||
}
|
||||
}
|
||||
|
||||
// Sort non-belt buildings
|
||||
bpBuildings.Sort((a, b) =>
|
||||
{
|
||||
var sign = b.itemType.CompareTo(a.itemType);
|
||||
if (sign != 0) return sign;
|
||||
|
||||
sign = b.building.modelIndex.CompareTo(a.building.modelIndex);
|
||||
if (sign != 0) return sign;
|
||||
|
||||
sign = b.building.recipeId.CompareTo(a.building.recipeId);
|
||||
if (sign != 0) return sign;
|
||||
|
||||
sign = a.building.areaIndex.CompareTo(b.building.areaIndex);
|
||||
if (sign != 0) return sign;
|
||||
|
||||
return b.offset.CompareTo(a.offset);
|
||||
});
|
||||
|
||||
// Concatenate sorted belts and non-belt buildings
|
||||
sortedBpBelts.Reverse();
|
||||
blueprintData.buildings = [.. bpBuildings.Select(b => b.building), .. sortedBpBelts];
|
||||
var buildings = blueprintData.buildings;
|
||||
|
||||
for (var i = buildings.Length - 1; i >= 0; i--)
|
||||
{
|
||||
buildings[i].index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -764,8 +764,15 @@ public static class LogisticsPatch
|
||||
|
||||
public static void Enable(bool on)
|
||||
{
|
||||
if (_stationTipsRoot)
|
||||
_stationTipsRoot.SetActive(on);
|
||||
if (_stationTipsRoot == null) return;
|
||||
if (!on)
|
||||
{
|
||||
_stationTipsRoot.SetActive(false);
|
||||
return;
|
||||
}
|
||||
if (DSPGame.IsMenuDemo || !GameMain.isRunning) return;
|
||||
_lastPlanet = GameMain.localPlanet;
|
||||
_stationTipsRoot.SetActive(on && _lastPlanet != null);
|
||||
}
|
||||
|
||||
public static void EnableBars(bool on)
|
||||
|
||||
@@ -88,126 +88,29 @@ public class PersistPatch : PatchImpl<PersistPatch>
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
// Sort blueprint structures by item id, model index, recipe id, area index, and position before saving
|
||||
private struct BPBuildingData
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(BuildTool_BlueprintCopy), nameof(BuildTool_BlueprintCopy.UseToPasteNow))]
|
||||
private static IEnumerable<CodeInstruction> BuildTool_BlueprintCopy_UseToPasteNow_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
public BlueprintBuilding building;
|
||||
public int itemType;
|
||||
public double offset;
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldarg_0),
|
||||
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(BuildTool_BlueprintCopy), nameof(BuildTool_BlueprintCopy.RefreshBlueprintData)))
|
||||
).Advance(2).Insert(
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(BuildTool_BlueprintCopy), nameof(BuildTool_BlueprintCopy.blueprint))),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Functions.FactoryFunctions), nameof(Functions.FactoryFunctions.SortBlueprintData)))
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
private struct BPBeltData
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(BlueprintData), nameof(BlueprintData.SaveBlueprintData))]
|
||||
private static void BlueprintData_SaveBlueprintData_Prefix(BlueprintData __instance)
|
||||
{
|
||||
public BlueprintBuilding building;
|
||||
public double offset;
|
||||
}
|
||||
|
||||
private static HashSet<int> _itemIsBelt = null;
|
||||
private static Dictionary<int, int> _upgradeTypes = null;
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(BlueprintUtils), nameof(BlueprintUtils.GenerateBlueprintData))]
|
||||
private static void BlueprintUtils_GenerateBlueprintData_Postfix(BlueprintData _blueprintData)
|
||||
{
|
||||
// Initialize itemIsBelt and upgradeTypes
|
||||
if (_itemIsBelt == null)
|
||||
{
|
||||
_itemIsBelt = [];
|
||||
_upgradeTypes = [];
|
||||
foreach (var proto in LDB.items.dataArray)
|
||||
{
|
||||
if (proto.prefabDesc?.isBelt ?? false)
|
||||
{
|
||||
_itemIsBelt.Add(proto.ID);
|
||||
continue;
|
||||
}
|
||||
if (proto.Upgrades != null && proto.Upgrades.Length > 0)
|
||||
{
|
||||
var minUpgrade = proto.Upgrades.Min(u => u);
|
||||
if (minUpgrade != 0 && minUpgrade != proto.ID)
|
||||
{
|
||||
_upgradeTypes.Add(proto.ID, minUpgrade);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Separate belt and non-belt buildings
|
||||
List<BPBuildingData> bpBuildings = [];
|
||||
Dictionary<BlueprintBuilding, BPBeltData> bpBelts = [];
|
||||
for (var i = 0; i < _blueprintData.buildings.Length; i++)
|
||||
{
|
||||
var building = _blueprintData.buildings[i];
|
||||
var offset = building.localOffset_y * 262144.0 + building.localOffset_x * 1024.0 + building.localOffset_z;
|
||||
if (_itemIsBelt.Contains(building.itemId))
|
||||
{
|
||||
bpBelts.Add(building, new BPBeltData { building = building, offset = offset });
|
||||
}
|
||||
else
|
||||
{
|
||||
var itemType = _upgradeTypes.TryGetValue(building.itemId, out var upgradeType) ? upgradeType : building.itemId;
|
||||
bpBuildings.Add(new BPBuildingData { building = building, itemType = itemType, offset = offset });
|
||||
}
|
||||
}
|
||||
Dictionary<BlueprintBuilding, BPBeltData> beltHeads = new(bpBelts);
|
||||
foreach (var building in bpBelts.Keys)
|
||||
{
|
||||
var next = building.outputObj;
|
||||
if (next == null) continue;
|
||||
beltHeads.Remove(next);
|
||||
}
|
||||
// Sort belt buildings
|
||||
List<BlueprintBuilding> sortedBpBelts = [];
|
||||
// Deal with non-cycle belt paths
|
||||
foreach (var pair in beltHeads.OrderByDescending(pair => pair.Value.offset))
|
||||
{
|
||||
var building = pair.Key;
|
||||
while (building != null)
|
||||
{
|
||||
if (!bpBelts.Remove(building)) break;
|
||||
sortedBpBelts.Add(building);
|
||||
building = building.outputObj;
|
||||
}
|
||||
}
|
||||
// Deal with cycle belt paths
|
||||
while (bpBelts.Count > 0)
|
||||
{
|
||||
var building = bpBelts.OrderByDescending(pair => pair.Value.offset).First().Key;
|
||||
while (building != null)
|
||||
{
|
||||
if (!bpBelts.Remove(building)) break;
|
||||
sortedBpBelts.Add(building);
|
||||
building = building.outputObj;
|
||||
}
|
||||
}
|
||||
|
||||
// Sort non-belt buildings
|
||||
bpBuildings.Sort((a, b) =>
|
||||
{
|
||||
var sign = b.itemType.CompareTo(a.itemType);
|
||||
if (sign != 0) return sign;
|
||||
|
||||
sign = b.building.modelIndex.CompareTo(a.building.modelIndex);
|
||||
if (sign != 0) return sign;
|
||||
|
||||
sign = b.building.recipeId.CompareTo(a.building.recipeId);
|
||||
if (sign != 0) return sign;
|
||||
|
||||
sign = a.building.areaIndex.CompareTo(b.building.areaIndex);
|
||||
if (sign != 0) return sign;
|
||||
|
||||
return b.offset.CompareTo(a.offset);
|
||||
});
|
||||
|
||||
// Concatenate sorted belts and non-belt buildings
|
||||
sortedBpBelts.Reverse();
|
||||
_blueprintData.buildings = [.. bpBuildings.Select(b => b.building), .. sortedBpBelts];
|
||||
var buildings = _blueprintData.buildings;
|
||||
|
||||
for (var i = buildings.Length - 1; i >= 0; i--)
|
||||
{
|
||||
buildings[i].index = i;
|
||||
}
|
||||
if (!__instance.isValid) return;
|
||||
Functions.FactoryFunctions.SortBlueprintData(__instance);
|
||||
}
|
||||
|
||||
// Increase maximum value of property realizing, 2000 -> 20000
|
||||
|
||||
Reference in New Issue
Block a user