1
0
mirror of https://github.com/soarqin/DSP_Mods.git synced 2026-02-04 20:22:17 +08:00

Add an option to auto-config logistics

This commit is contained in:
2025-04-25 15:36:27 +08:00
parent bb18912155
commit b86825c645
4 changed files with 508 additions and 414 deletions

View File

@@ -62,6 +62,7 @@ public static class UIFunctions
}
}
#region ConfigWindow
public static void ToggleConfigWindow()
{
if (!_configWinInitialized)
@@ -81,34 +82,6 @@ public static class UIFunctions
}
}
private static readonly Sprite[] PlanetIcons = [
null,
null,
null,
null,
null,
null,
null,
Common.Util.LoadEmbeddedSprite("assets/planet_icon/07.png"),
null,
Common.Util.LoadEmbeddedSprite("assets/planet_icon/09.png"),
Common.Util.LoadEmbeddedSprite("assets/planet_icon/10.png"),
null,
null,
Common.Util.LoadEmbeddedSprite("assets/planet_icon/13.png"),
Common.Util.LoadEmbeddedSprite("assets/planet_icon/14.png"),
Common.Util.LoadEmbeddedSprite("assets/planet_icon/15.png"),
Common.Util.LoadEmbeddedSprite("assets/planet_icon/16.png"),
Common.Util.LoadEmbeddedSprite("assets/planet_icon/17.png"),
Common.Util.LoadEmbeddedSprite("assets/planet_icon/18.png"),
Common.Util.LoadEmbeddedSprite("assets/planet_icon/19.png"),
null,
Common.Util.LoadEmbeddedSprite("assets/planet_icon/21.png"),
Common.Util.LoadEmbeddedSprite("assets/planet_icon/22.png"),
Common.Util.LoadEmbeddedSprite("assets/planet_icon/23.png"),
Common.Util.LoadEmbeddedSprite("assets/planet_icon/24.png"),
Common.Util.LoadEmbeddedSprite("assets/planet_icon/25.png")
];
private static readonly int[] FilterPlanetThemes = [16, 23, 10, 15, 18, 22, 25, 21, 14, 17, 19, 7, 24, 9, 13];
public static void InitMenuButtons()
{
@@ -168,7 +141,69 @@ public static class UIFunctions
_buttonOnPlanetGlobe.SetActive(true);
}
}
InitStarmapButtons();
_initialized = true;
}
public static void RecreateConfigWindow()
{
if (!_configWinInitialized) return;
var wasActive = _configWin.active;
if (wasActive) _configWin._Close();
MyConfigWindow.DestroyInstance(_configWin);
_configWinInitialized = false;
if (wasActive) ToggleConfigWindow();
}
public static void UpdateGlobeButtonPosition(UIPlanetGlobe planetGlobe)
{
if (_buttonOnPlanetGlobe == null) return;
var rect = (RectTransform)_buttonOnPlanetGlobe.transform;
if (planetGlobe.dysonSphereSystemUnlocked || planetGlobe.logisticsSystemUnlocked)
{
rect.anchoredPosition3D = new Vector3(64f, -5f, 0f);
}
else
{
rect.anchoredPosition3D = new Vector3(128f, -100f, 0f);
}
}
#endregion
#region StarMapButtons
private static readonly Sprite[] PlanetIcons = [
null,
null,
null,
null,
null,
null,
null,
Common.Util.LoadEmbeddedSprite("assets/planet_icon/07.png"),
null,
Common.Util.LoadEmbeddedSprite("assets/planet_icon/09.png"),
Common.Util.LoadEmbeddedSprite("assets/planet_icon/10.png"),
null,
null,
Common.Util.LoadEmbeddedSprite("assets/planet_icon/13.png"),
Common.Util.LoadEmbeddedSprite("assets/planet_icon/14.png"),
Common.Util.LoadEmbeddedSprite("assets/planet_icon/15.png"),
Common.Util.LoadEmbeddedSprite("assets/planet_icon/16.png"),
Common.Util.LoadEmbeddedSprite("assets/planet_icon/17.png"),
Common.Util.LoadEmbeddedSprite("assets/planet_icon/18.png"),
Common.Util.LoadEmbeddedSprite("assets/planet_icon/19.png"),
null,
Common.Util.LoadEmbeddedSprite("assets/planet_icon/21.png"),
Common.Util.LoadEmbeddedSprite("assets/planet_icon/22.png"),
Common.Util.LoadEmbeddedSprite("assets/planet_icon/23.png"),
Common.Util.LoadEmbeddedSprite("assets/planet_icon/24.png"),
Common.Util.LoadEmbeddedSprite("assets/planet_icon/25.png")
];
public static void InitStarmapButtons()
{
var uiRoot = UIRoot.instance;
if (!uiRoot) return;
var rtrans = uiRoot.uiGame.starmap.transform as RectTransform;
var cornerComboBox = UI.MyCornerComboBox.CreateComboBox(135, 5, rtrans, true).WithItems("Show original name".Translate(), "Show distance".Translate(), "Show planet count".Translate(), "Show all information".Translate());
cornerComboBox.SetIndex(Functions.UIFunctions.CornerComboBoxIndex);
@@ -471,8 +506,6 @@ public static class UIFunctions
SetStarFilterEnabled(true);
}
}
_initialized = true;
}
private static void StarmapUpdateFilterValues()
{
@@ -573,30 +606,6 @@ public static class UIFunctions
}
}
public static void RecreateConfigWindow()
{
if (!_configWinInitialized) return;
var wasActive = _configWin.active;
if (wasActive) _configWin._Close();
MyConfigWindow.DestroyInstance(_configWin);
_configWinInitialized = false;
if (wasActive) ToggleConfigWindow();
}
public static void UpdateGlobeButtonPosition(UIPlanetGlobe planetGlobe)
{
if (_buttonOnPlanetGlobe == null) return;
var rect = (RectTransform)_buttonOnPlanetGlobe.transform;
if (planetGlobe.dysonSphereSystemUnlocked || planetGlobe.logisticsSystemUnlocked)
{
rect.anchoredPosition3D = new Vector3(64f, -5f, 0f);
}
else
{
rect.anchoredPosition3D = new Vector3(128f, -100f, 0f);
}
}
public static int CornerComboBoxIndex
{
get => _cornerComboBoxIndex;
@@ -665,4 +674,5 @@ public static class UIFunctions
return (nongas, total);
}
}
#endregion
}

View File

@@ -16,6 +16,7 @@ namespace UXAssist.Patches;
public static class LogisticsPatch
{
public static ConfigEntry<bool> AutoConfigLogisticsEnabled;
public static ConfigEntry<bool> AutoConfigLimitAutoReplenishCount;
// Dispenser config
public static ConfigEntry<int> AutoConfigDispenserChargePower; // 3~30, display as 300000.0 * value
public static ConfigEntry<int> AutoConfigDispenserCourierCount; // 0~10
@@ -50,6 +51,7 @@ public static class LogisticsPatch
public static void Init()
{
AutoConfigLogisticsEnabled.SettingChanged += (_, _) => AutoConfigLogistics.Enable(AutoConfigLogisticsEnabled.Value);
AutoConfigLimitAutoReplenishCount.SettingChanged += (_, _) => AutoConfigLogistics.ToggleLimitAutoReplenishCount();
LogisticsCapacityTweaksEnabled.SettingChanged += (_, _) => LogisticsCapacityTweaks.Enable(LogisticsCapacityTweaksEnabled.Value);
AllowOverflowInLogisticsEnabled.SettingChanged += (_, _) => AllowOverflowInLogistics.Enable(AllowOverflowInLogisticsEnabled.Value);
LogisticsConstrolPanelImprovementEnabled.SettingChanged += (_, _) => LogisticsConstrolPanelImprovement.Enable(LogisticsConstrolPanelImprovementEnabled.Value);
@@ -109,6 +111,76 @@ public static class LogisticsPatch
Warper = 1210,
}
protected override void OnEnable()
{
ToggleLimitAutoReplenishCount();
}
protected override void OnDisable()
{
ToggleLimitAutoReplenishCount();
}
public static void ToggleLimitAutoReplenishCount()
{
LimitAutoReplenishCount.Enable(AutoConfigLogisticsEnabled.Value && AutoConfigLimitAutoReplenishCount.Value);
}
private class LimitAutoReplenishCount : PatchImpl<LimitAutoReplenishCount>
{
[HarmonyTranspiler]
[HarmonyPatch(typeof(PlanetFactory), nameof(PlanetFactory.EntityAutoReplenishIfNeeded))]
[HarmonyPatch(typeof(PlanetFactory), nameof(PlanetFactory.StationAutoReplenishIfNeeded))]
private static IEnumerable<CodeInstruction> PlanetFactory_StationAutoReplenishIfNeeded_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
var matcher = new CodeMatcher(instructions, generator);
// Patch dispenser courier count
matcher.Start().MatchForward(false,
new CodeMatch(ci => ci.IsLdloc()),
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(DispenserComponent), nameof(DispenserComponent.workCourierDatas))),
new CodeMatch(OpCodes.Ldlen),
new CodeMatch(OpCodes.Conv_I4)
);
matcher.Repeat(m => m.Advance(4).InsertAndAdvance(
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(LogisticsPatch), nameof(AutoConfigDispenserCourierCount))),
new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(ConfigEntry<int>), nameof(ConfigEntry<int>.Value))),
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Math), nameof(Math.Min), [typeof(int), typeof(int)]))
));
// Patch PLS/ILS drone count
matcher.Start().MatchForward(false,
new CodeMatch(ci => ci.IsLdloc()),
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(StationComponent), nameof(StationComponent.workDroneDatas))),
new CodeMatch(OpCodes.Ldlen),
new CodeMatch(OpCodes.Conv_I4)
);
matcher.Repeat(m =>
{
var instr = m.Instruction;
m.Advance(4).InsertAndAdvance(
instr,
Transpilers.EmitDelegate((int x, StationComponent station)
=> Math.Min(x, station.isStellar ? AutoConfigILSDroneCount.Value : AutoConfigPLSDroneCount.Value))
);
});
// Patch ILS ship count
matcher.Start().MatchForward(false,
new CodeMatch(ci => ci.IsLdloc()),
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(StationComponent), nameof(StationComponent.workShipDatas))),
new CodeMatch(OpCodes.Ldlen),
new CodeMatch(OpCodes.Conv_I4)
);
UXAssist.Logger.LogDebug($"Patch ILS ship count: {matcher.Pos}");
matcher.Repeat(m => m.Advance(4).InsertAndAdvance(
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(LogisticsPatch), nameof(AutoConfigILSShipCount))),
new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(ConfigEntry<int>), nameof(ConfigEntry<int>.Value))),
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Math), nameof(Math.Min), [typeof(int), typeof(int)]))
));
return matcher.InstructionEnumeration();
}
}
private static void DoConfigStation(PlanetFactory factory, StationComponent station)
{
if (station.isCollector) return;
@@ -119,7 +191,8 @@ public static class LogisticsPatch
return;
}
int toFill;
if (!station.isStellar) {
if (!station.isStellar)
{
factory.powerSystem.consumerPool[station.pcId].workEnergyPerTick = (long)(50000.0 * (double)AutoConfigPLSChargePower.Value + 0.5);
station.tripRangeDrones = Math.Cos(AutoConfigPLSMaxTripDrone.Value / 180.0 * Math.PI);
station.deliveryDrones = AutoConfigPLSDroneMinDeliver.Value switch { 0 => 1, _ => AutoConfigPLSDroneMinDeliver.Value * 10 };
@@ -130,12 +203,14 @@ public static class LogisticsPatch
}
factory.powerSystem.consumerPool[station.pcId].workEnergyPerTick = (long)(250000.0 * (double)AutoConfigILSChargePower.Value + 0.5);
station.tripRangeDrones = Math.Cos(AutoConfigILSMaxTripDrone.Value / 180.0 * Math.PI);
station.tripRangeShips = AutoConfigILSMaxTripShip.Value switch {
station.tripRangeShips = AutoConfigILSMaxTripShip.Value switch
{
<= 20 => AutoConfigILSMaxTripShip.Value,
<= 40 => AutoConfigILSMaxTripShip.Value * 2 - 20,
_ => 10000,
} * 2400000.0;
station.warpEnableDist = AutoConfigILSWarperDistance.Value switch {
station.warpEnableDist = AutoConfigILSWarperDistance.Value switch
{
<= 7 => AutoConfigILSWarperDistance.Value * 0.5 - 0.5,
<= 16 => AutoConfigILSWarperDistance.Value - 4.0,
<= 20 => AutoConfigILSWarperDistance.Value * 2 - 20.0,
@@ -1073,8 +1148,12 @@ public static class LogisticsPatch
_iconRemotes[i].gameObject.SetActive(false);
_storageItems[i] = new StorageItemData
{
ItemId = -1, ItemCount = -1, ItemOrdered = -1, ItemMax = -1,
LocalState = ELogisticStorage.None, RemoteState = ELogisticStorage.None
ItemId = -1,
ItemCount = -1,
ItemOrdered = -1,
ItemMax = -1,
LocalState = ELogisticStorage.None,
RemoteState = ELogisticStorage.None
};
}

View File

@@ -82,17 +82,18 @@ public static class UIConfigWindow
I18N.Add("Build Tesla Tower and Wireless Power Tower alternately", "Build Tesla Tower and Wireless Power Tower alternately", "交替建造电力感应塔和无线输电塔");
I18N.Add("Belt signals for buy out dark fog items automatically", "Belt signals for buy out dark fog items automatically", "用于自动购买黑雾物品的传送带信号");
I18N.Add("Auto-config logistic stations", "Auto-config logistic stations", "自动配置物流设施");
I18N.Add("Limit auto-replenish count to values below", "Limit auto-replenish count to values below", "限制自动补给数量为下面配置的值");
I18N.Add("Dispenser", "Logistics Distributor", "物流配送器");
I18N.Add("PLS", "PLS", "行星物流站");
I18N.Add("ILS", "ILS", "星际物流站");
I18N.Add("Advanced Mining Machine", "Advanced Mining Machine", "大型采矿机");
I18N.Add("Max. Charging Power", "Max. Charging Power", "最大充能功率");
I18N.Add("Count of Bots auto-filled", "Count of Bots auto-filled", "自动填充的配送机数量");
I18N.Add("Count of Bots filled", "Count of Bots filled", "填充的配送机数量");
I18N.Add("Max. Charging Power", "Max. Charging Power", "最大充能功率");
I18N.Add("Drone transport range", "Drone transport range", "运输机最远路程");
I18N.Add("Min. Load of Drones", "Min. Load of Drones", "运输机起送量");
I18N.Add("Outgoing integration count", "Outgoing integration count", "输出货物集装数量");
I18N.Add("Count of Drones auto-filled", "Count of Drones auto-filled", "自动填充的运输机数量");
I18N.Add("Count of Drones filled", "Count of Drones filled", "填充的运输机数量");
I18N.Add("Max. Charging Power", "Max. Charging Power", "最大充能功率");
I18N.Add("Drone transport range", "Drone transport range", "运输机最远路程");
I18N.Add("Vessel transport range", "Vessel transport range", "运输船最远路程");
@@ -102,8 +103,8 @@ public static class UIConfigWindow
I18N.Add("Outgoing integration count", "Outgoing integration count", "输出货物集装数量");
I18N.Add("Include Orbital Collector", "Include Orbital Collector", "包含轨道采集器");
I18N.Add("Warpers required", "Warpers required", "翘曲器必备");
I18N.Add("Count of Drones auto-filled", "Count of Drones auto-filled", "自动填充的运输机数量");
I18N.Add("Count of Vessels auto-filled", "Count of Vessels auto-filled", "自动填充的运输船数量");
I18N.Add("Count of Drones filled", "Count of Drones filled", "填充的运输机数量");
I18N.Add("Count of Vessels filled", "Count of Vessels filled", "填充的运输船数量");
I18N.Add("Collecting Speed", "Collecting Speed", "开采速度");
I18N.Add("Min. Piler Value", "Outgoing integration count", "输出货物集装数量");
@@ -532,6 +533,8 @@ public static class UIConfigWindow
y += 36f;
wnd.AddCheckBox(x, y, tab3, LogisticsPatch.AutoConfigLogisticsEnabled, "Auto-config logistic stations");
y += 24f;
wnd.AddCheckBox(10f, y, tab3, LogisticsPatch.AutoConfigLimitAutoReplenishCount, "Limit auto-replenish count to values below", 13).WithSmallerBox();
y += 18f;
var maxWidth = 0f;
wnd.AddText2(10f, y, tab3, "Dispenser", 14, "text-dispenser");
y += 18f;
@@ -540,7 +543,7 @@ public static class UIConfigWindow
var textForMeasureTextWidth = wnd.AddText2(x, y, tab3, "Max. Charging Power", 13, "text-dispenser-max-charging-power");
maxWidth = Mathf.Max(maxWidth, textForMeasureTextWidth.preferredWidth);
y += 18f;
textForMeasureTextWidth = wnd.AddText2(x, y, tab3, "Count of Bots auto-filled", 13, "text-dispenser-count-of-bots-auto-filled");
textForMeasureTextWidth = wnd.AddText2(x, y, tab3, "Count of Bots filled", 13, "text-dispenser-count-of-bots-filled");
maxWidth = Mathf.Max(maxWidth, textForMeasureTextWidth.preferredWidth);
y += 18f;
wnd.AddText2(10f, y, tab3, "PLS", 14, "text-pls");
@@ -557,7 +560,7 @@ public static class UIConfigWindow
textForMeasureTextWidth = wnd.AddText2(x, y, tab3, "Outgoing integration count", 13, "text-pls-outgoing-integration-count");
maxWidth = Mathf.Max(maxWidth, textForMeasureTextWidth.preferredWidth);
y += 18f;
textForMeasureTextWidth = wnd.AddText2(x, y, tab3, "Count of Drones auto-filled", 13, "text-pls-count-of-drones-auto-filled");
textForMeasureTextWidth = wnd.AddText2(x, y, tab3, "Count of Drones filled", 13, "text-pls-count-of-drones-filled");
maxWidth = Mathf.Max(maxWidth, textForMeasureTextWidth.preferredWidth);
y += 18f;
wnd.AddText2(10f, y, tab3, "ILS", 14, "text-ils");
@@ -585,10 +588,10 @@ public static class UIConfigWindow
textForMeasureTextWidth = wnd.AddText2(x, y, tab3, "Outgoing integration count", 13, "text-ils-outgoing-integration-count");
maxWidth = Mathf.Max(maxWidth, textForMeasureTextWidth.preferredWidth);
y += 18f;
textForMeasureTextWidth = wnd.AddText2(x, y, tab3, "Count of Drones auto-filled", 13, "text-ils-count-of-drones-auto-filled");
textForMeasureTextWidth = wnd.AddText2(x, y, tab3, "Count of Drones filled", 13, "text-ils-count-of-drones-filled");
maxWidth = Mathf.Max(maxWidth, textForMeasureTextWidth.preferredWidth);
y += 18f;
textForMeasureTextWidth = wnd.AddText2(x, y, tab3, "Count of Vessels auto-filled", 13, "text-ils-count-of-vessels-auto-filled");
textForMeasureTextWidth = wnd.AddText2(x, y, tab3, "Count of Vessels filled", 13, "text-ils-count-of-vessels-filled");
maxWidth = Mathf.Max(maxWidth, textForMeasureTextWidth.preferredWidth);
y += 18f;
wnd.AddText2(10f, y, tab3, "Advanced Mining Machine", 14, "text-amm");

View File

@@ -138,13 +138,15 @@ public class UXAssist : BaseUnityPlugin, IModCanSave
"Dismantle blueprint selected buildings");
LogisticsPatch.AutoConfigLogisticsEnabled = Config.Bind("Factory", "AutoConfigLogistics", false,
"Auto-config logistic stations");
LogisticsPatch.AutoConfigLimitAutoReplenishCount = Config.Bind("Factory", "AutoConfigLimitAutoReplenishCount", false,
"Limit auto-replenish count to config values");
LogisticsPatch.AutoConfigDispenserChargePower = Config.Bind("Factory", "AutoConfigDispenserChargePower", 30, new ConfigDescription("LD: Max. Charging Power", new AcceptableValueRange<int>(3, 30)));
LogisticsPatch.AutoConfigDispenserCourierCount = Config.Bind("Factory", "AutoConfigDispenserCourierCount", 10, new ConfigDescription("LD: Count of Bots auto-filled", new AcceptableValueRange<int>(0, 10)));
LogisticsPatch.AutoConfigDispenserCourierCount = Config.Bind("Factory", "AutoConfigDispenserCourierCount", 10, new ConfigDescription("LD: Count of Bots filled", new AcceptableValueRange<int>(0, 10)));
LogisticsPatch.AutoConfigPLSChargePower = Config.Bind("Factory", "AutoConfigPLSChargePower", 4, new ConfigDescription("PLS: Max. Charging Power", new AcceptableValueRange<int>(2, 20)));
LogisticsPatch.AutoConfigPLSMaxTripDrone = Config.Bind("Factory", "AutoConfigPLSMaxTripDrone", 180, new ConfigDescription("PLS: Drone transport range", new AcceptableValueRange<int>(1, 180)));
LogisticsPatch.AutoConfigPLSDroneMinDeliver = Config.Bind("Factory", "AutoConfigPLSDroneMinDeliver", 10, new ConfigDescription("PLS: Min. Load of Drones", new AcceptableValueRange<int>(0, 10)));
LogisticsPatch.AutoConfigPLSMinPilerValue = Config.Bind("Factory", "AutoConfigPLSMinPilerValue", 0, new ConfigDescription("PLS: Outgoing integration count", new AcceptableValueRange<int>(0, 4)));
LogisticsPatch.AutoConfigPLSDroneCount = Config.Bind("Factory", "AutoConfigPLSDroneCount", 10, new ConfigDescription("PLS: Count of Drones auto-filled", new AcceptableValueRange<int>(0, 50)));
LogisticsPatch.AutoConfigPLSDroneCount = Config.Bind("Factory", "AutoConfigPLSDroneCount", 10, new ConfigDescription("PLS: Count of Drones filled", new AcceptableValueRange<int>(0, 50)));
LogisticsPatch.AutoConfigILSChargePower = Config.Bind("Factory", "AutoConfigILSChargePower", 4, new ConfigDescription("ILS: Max. Charging Power", new AcceptableValueRange<int>(2, 20)));
LogisticsPatch.AutoConfigILSMaxTripDrone = Config.Bind("Factory", "AutoConfigILSMaxTripDrone", 180, new ConfigDescription("ILS: Drone transport range", new AcceptableValueRange<int>(1, 180)));
LogisticsPatch.AutoConfigILSMaxTripShip = Config.Bind("Factory", "AutoConfigILSMaxTripShip", 41, new ConfigDescription("ILS: Vessel transport range", new AcceptableValueRange<int>(1, 41)));
@@ -156,8 +158,8 @@ public class UXAssist : BaseUnityPlugin, IModCanSave
"ILS: Include Orbital Collector");
LogisticsPatch.AutoConfigILSWarperNecessary = Config.Bind("Factory", "AutoConfigILSWarperNecessary", true,
"ILS: Warpers required");
LogisticsPatch.AutoConfigILSDroneCount = Config.Bind("Factory", "AutoConfigILSDroneCount", 20, new ConfigDescription("ILS: Count of Drones auto-filled", new AcceptableValueRange<int>(0, 100)));
LogisticsPatch.AutoConfigILSShipCount = Config.Bind("Factory", "AutoConfigILSShipCount", 10, new ConfigDescription("ILS: Count of Vessels auto-filled", new AcceptableValueRange<int>(0, 10)));
LogisticsPatch.AutoConfigILSDroneCount = Config.Bind("Factory", "AutoConfigILSDroneCount", 20, new ConfigDescription("ILS: Count of Drones filled", new AcceptableValueRange<int>(0, 100)));
LogisticsPatch.AutoConfigILSShipCount = Config.Bind("Factory", "AutoConfigILSShipCount", 10, new ConfigDescription("ILS: Count of Vessels filled", new AcceptableValueRange<int>(0, 10)));
LogisticsPatch.AutoConfigVeinCollectorHarvestSpeed = Config.Bind("Factory", "AutoConfigVeinCollectorHarvestSpeed", 20, new ConfigDescription("AMM: Collecting Speed", new AcceptableValueRange<int>(0, 20)));
LogisticsPatch.AutoConfigVeinCollectorMinPilerValue = Config.Bind("Factory", "AutoConfigVeinCollectorMinPilerValue", 0, new ConfigDescription("AMM: Outgoing integration count", new AcceptableValueRange<int>(0, 4)));
LogisticsPatch.LogisticsCapacityTweaksEnabled = Config.Bind("Factory", "LogisticsCapacityTweaks", true,