1
0
mirror of https://github.com/soarqin/DSP_Mods.git synced 2025-12-09 02:53:29 +08:00

CheatEnabler v2.2.0

This commit is contained in:
2023-09-19 23:12:45 +08:00
parent 103309df6d
commit 1cb9cb8e96
9 changed files with 1386 additions and 978 deletions

View File

@@ -1,790 +0,0 @@
using System;
using System.Collections.Generic;
using System.Reflection.Emit;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
namespace CheatEnabler;
public static class BuildPatch
{
public static ConfigEntry<bool> ImmediateEnabled;
public static ConfigEntry<bool> ArchitectModeEnabled;
public static ConfigEntry<bool> NoConditionEnabled;
public static ConfigEntry<bool> NoCollisionEnabled;
public static ConfigEntry<bool> BeltSignalGeneratorEnabled;
private static Harmony _patch;
private static Harmony _noConditionPatch;
public static void Init()
{
if (_patch != null) return;
ImmediateEnabled.SettingChanged += (_, _) => ImmediateValueChanged();
ArchitectModeEnabled.SettingChanged += (_, _) => ArchitectModeValueChanged();
NoConditionEnabled.SettingChanged += (_, _) => NoConditionValueChanged();
NoCollisionEnabled.SettingChanged += (_, _) => NoCollisionValueChanged();
BeltSignalGeneratorEnabled.SettingChanged += (_, _) => BeltSignalGeneratorValueChanged();
ImmediateValueChanged();
ArchitectModeValueChanged();
NoConditionValueChanged();
NoCollisionValueChanged();
BeltSignalGeneratorValueChanged();
_patch = Harmony.CreateAndPatchAll(typeof(BuildPatch));
}
public static void Uninit()
{
if (_patch != null)
{
_patch.UnpatchSelf();
_patch = null;
}
if (_noConditionPatch != null)
{
_noConditionPatch.UnpatchSelf();
_noConditionPatch = null;
}
ImmediateBuild.Enable(false);
ArchitectMode.Enable(false);
BeltSignalGenerator.Enable(false);
NightLightEnd();
}
private static void ImmediateValueChanged()
{
ImmediateBuild.Enable(ImmediateEnabled.Value);
}
private static void ArchitectModeValueChanged()
{
ArchitectMode.Enable(ArchitectModeEnabled.Value);
NightLightUpdateState();
}
private static void NoConditionValueChanged()
{
if (NoConditionEnabled.Value)
{
if (_noConditionPatch != null)
{
return;
}
_noConditionPatch = Harmony.CreateAndPatchAll(typeof(NoConditionBuild));
}
else if (_noConditionPatch != null)
{
_noConditionPatch.UnpatchSelf();
_noConditionPatch = null;
}
}
private static void NoCollisionValueChanged()
{
var coll = ColliderPool.instance;
if (coll == null) return;
var obj = coll.gameObject;
if (obj == null) return;
obj.gameObject.SetActive(!NoCollisionEnabled.Value);
}
private static void BeltSignalGeneratorValueChanged()
{
BeltSignalGenerator.Enable(BeltSignalGeneratorEnabled.Value);
}
public static void ArrivePlanet(PlanetFactory factory)
{
var imm = ImmediateEnabled.Value;
var architect = ArchitectModeEnabled.Value;
if (!imm && !architect) return;
var prebuilds = factory.prebuildPool;
if (imm) factory.BeginFlattenTerrain();
for (var i = factory.prebuildCursor - 1; i > 0; i--)
{
if (prebuilds[i].id != i) continue;
if (prebuilds[i].itemRequired > 0)
{
if (!architect) continue;
prebuilds[i].itemRequired = 0;
if (imm)
factory.BuildFinally(GameMain.mainPlayer, i, false);
else
factory.AlterPrebuildModelState(i);
}
else
{
if (imm)
factory.BuildFinally(GameMain.mainPlayer, i, false);
}
}
if (imm) factory.EndFlattenTerrain();
}
[HarmonyPostfix]
[HarmonyPatch(typeof(PlanetData), nameof(PlanetData.NotifyFactoryLoaded))]
private static void PlanetData_NotifyFactoryLoaded_Postfix(PlanetData __instance)
{
ArrivePlanet(__instance.factory);
}
/* Night Light Begin */
private const float NightLightAngleX = -8;
private const float NightLightAngleY = -2;
public static bool NightlightEnabled;
private static bool _nightlightInitialized;
private static bool _mechaOnEarth;
private static AnimationState _sail;
private static Light _sunlight;
private static void NightLightUpdateState()
{
if (ArchitectModeEnabled.Value)
{
NightlightEnabled = _mechaOnEarth;
return;
}
NightlightEnabled = false;
if (_sunlight == null) return;
_sunlight.transform.localEulerAngles = new Vector3(0f, 180f);
}
public static void NightLightLateUpdate()
{
switch (_nightlightInitialized)
{
case false:
NightLightReady();
break;
case true:
NightLightGo();
break;
}
}
private static void NightLightReady()
{
if (!GameMain.isRunning || !GameMain.mainPlayer.controller.model.gameObject.activeInHierarchy) return;
if (_sail == null)
{
_sail = GameMain.mainPlayer.animator.sails[GameMain.mainPlayer.animator.sailAnimIndex];
}
_nightlightInitialized = true;
}
private static void NightLightGo()
{
if (!GameMain.isRunning)
{
NightLightEnd();
return;
}
if (_sail.enabled)
{
_mechaOnEarth = false;
NightlightEnabled = false;
if (_sunlight == null) return;
_sunlight.transform.localEulerAngles = new Vector3(0f, 180f);
_sunlight = null;
return;
}
if (!_mechaOnEarth)
{
if (_sunlight == null)
{
_sunlight = GameMain.universeSimulator.LocalStarSimulator().sunLight;
if (_sunlight == null) return;
}
_mechaOnEarth = true;
NightlightEnabled = ArchitectModeEnabled.Value;
}
if (NightlightEnabled)
{
_sunlight.transform.rotation =
Quaternion.LookRotation(-GameMain.mainPlayer.transform.up + GameMain.mainPlayer.transform.forward * NightLightAngleX / 10f +
GameMain.mainPlayer.transform.right * NightLightAngleY / 10f);
}
}
private static void NightLightEnd()
{
_mechaOnEarth = false;
NightlightEnabled = false;
if (_sunlight != null)
{
_sunlight.transform.localEulerAngles = new Vector3(0f, 180f);
_sunlight = null;
}
_sail = null;
_nightlightInitialized = false;
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(StarSimulator), "LateUpdate")]
private static IEnumerable<CodeInstruction> StarSimulator_LateUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
// var vec = NightlightEnabled ? GameMain.mainPlayer.transform.up : __instance.transform.forward;
var matcher = new CodeMatcher(instructions, generator);
var label1 = generator.DefineLabel();
var label2 = generator.DefineLabel();
matcher.MatchForward(false,
new CodeMatch(OpCodes.Ldarg_0),
new CodeMatch(OpCodes.Call, AccessTools.PropertyGetter(typeof(Component), nameof(Component.transform)))
).InsertAndAdvance(
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(BuildPatch), nameof(BuildPatch.NightlightEnabled))),
new CodeInstruction(OpCodes.Brfalse_S, label1),
new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(GameMain), nameof(GameMain.mainPlayer))),
new CodeInstruction(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(Player), nameof(Player.transform))),
new CodeInstruction(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(Transform), nameof(Transform.up))),
new CodeInstruction(OpCodes.Stloc_0),
new CodeInstruction(OpCodes.Br_S, label2)
);
matcher.Labels.Add(label1);
matcher.MatchForward(false,
new CodeMatch(OpCodes.Stloc_0)
).Advance(1).Labels.Add(label2);
return matcher.InstructionEnumeration();
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(PlanetSimulator), "LateUpdate")]
private static IEnumerable<CodeInstruction> PlanetSimulator_LateUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
// var vec = (NightlightEnabled ? GameMain.mainPlayer.transform.up : (Quaternion.Inverse(localPlanet.runtimeRotation) * (__instance.planetData.star.uPosition - __instance.planetData.uPosition).normalized));
var matcher = new CodeMatcher(instructions, generator);
var label1 = generator.DefineLabel();
var label2 = generator.DefineLabel();
matcher.MatchForward(false,
new CodeMatch(OpCodes.Pop)
).Advance(1).InsertAndAdvance(
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(BuildPatch), nameof(BuildPatch.NightlightEnabled))),
new CodeInstruction(OpCodes.Brfalse_S, label1),
new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(GameMain), nameof(GameMain.mainPlayer))),
new CodeInstruction(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(Player), nameof(Player.transform))),
new CodeInstruction(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(Transform), nameof(Transform.up))),
new CodeInstruction(OpCodes.Stloc_1),
new CodeInstruction(OpCodes.Br_S, label2)
);
matcher.Labels.Add(label1);
matcher.MatchForward(false,
new CodeMatch(OpCodes.Ldsfld, AccessTools.Field(typeof(FactoryModel), nameof(FactoryModel.whiteMode0)))
).Labels.Add(label2);
return matcher.InstructionEnumeration();
}
/* Night Light End */
private static class ImmediateBuild
{
private static Harmony _immediatePatch;
public static void Enable(bool enable)
{
if (enable)
{
if (_immediatePatch != null)
{
return;
}
var factory = GameMain.mainPlayer?.factory;
if (factory != null)
{
ArrivePlanet(factory);
}
_immediatePatch = Harmony.CreateAndPatchAll(typeof(ImmediateBuild));
}
else if (_immediatePatch != null)
{
_immediatePatch.UnpatchSelf();
_immediatePatch = null;
}
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(BuildTool_Addon), nameof(BuildTool_Addon.CreatePrebuilds))]
[HarmonyPatch(typeof(BuildTool_BlueprintPaste), nameof(BuildTool_BlueprintPaste.CreatePrebuilds))]
[HarmonyPatch(typeof(BuildTool_Click), nameof(BuildTool_Click.CreatePrebuilds))]
[HarmonyPatch(typeof(BuildTool_Inserter), nameof(BuildTool_Inserter.CreatePrebuilds))]
[HarmonyPatch(typeof(BuildTool_Path), nameof(BuildTool_Path.CreatePrebuilds))]
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
var matcher = new CodeMatcher(instructions, generator);
matcher.MatchForward(false,
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(GC), nameof(GC.Collect)))
).Insert(
new CodeInstruction(OpCodes.Ldarg_0),
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(BuildTool), nameof(BuildTool.factory))),
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(BuildPatch), nameof(ArrivePlanet)))
);
return matcher.InstructionEnumeration();
}
}
private static class ArchitectMode
{
private static Harmony _architectPatch;
private static bool[] _canBuildItems;
public static void Enable(bool enable)
{
if (enable)
{
if (_architectPatch != null)
{
return;
}
var factory = GameMain.mainPlayer?.factory;
if (factory != null)
{
ArrivePlanet(factory);
}
_architectPatch = Harmony.CreateAndPatchAll(typeof(ArchitectMode));
}
else if (_architectPatch != null)
{
_architectPatch.UnpatchSelf();
_architectPatch = null;
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(StorageComponent), nameof(StorageComponent.TakeTailItems), new[] { typeof(int), typeof(int), typeof(int), typeof(bool) },
new[] { ArgumentType.Ref, ArgumentType.Ref, ArgumentType.Out, ArgumentType.Normal })]
[HarmonyPatch(typeof(StorageComponent), nameof(StorageComponent.TakeTailItems), new[] { typeof(int), typeof(int), typeof(int[]), typeof(int), typeof(bool) },
new[] { ArgumentType.Ref, ArgumentType.Ref, ArgumentType.Normal, ArgumentType.Out, ArgumentType.Normal })]
public static bool TakeTailItemsPatch(StorageComponent __instance, int itemId)
{
if (__instance == null || __instance.id != GameMain.mainPlayer.package.id) return true;
if (itemId <= 0) return true;
if (_canBuildItems == null)
{
DoInit();
}
return itemId >= 12000 || !_canBuildItems[itemId];
}
[HarmonyPostfix]
[HarmonyPatch(typeof(StorageComponent), "GetItemCount", new Type[] { typeof(int) })]
public static void GetItemCountPatch(StorageComponent __instance, int itemId, ref int __result)
{
if (__result > 99) return;
if (__instance == null || __instance.id != GameMain.mainPlayer.package.id) return;
if (itemId <= 0) return;
if (_canBuildItems == null)
{
DoInit();
}
if (itemId < 12000 && _canBuildItems[itemId]) __result = 100;
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(PlayerAction_Inspect), nameof(PlayerAction_Inspect.GetObjectSelectDistance))]
private static IEnumerable<CodeInstruction> PlayerAction_Inspect_GetObjectSelectDistance_Transpiler(IEnumerable<CodeInstruction> instructions)
{
yield return new CodeInstruction(OpCodes.Ldc_R4, 10000f);
yield return new CodeInstruction(OpCodes.Ret);
}
private static void DoInit()
{
_canBuildItems = new bool[12000];
foreach (var ip in LDB.items.dataArray)
{
if (ip.CanBuild && ip.ID < 12000) _canBuildItems[ip.ID] = true;
}
}
}
private static class NoConditionBuild
{
[HarmonyTranspiler]
[HarmonyPatch(typeof(BuildTool_Addon), nameof(BuildTool_Addon.CheckBuildConditions))]
// [HarmonyPatch(typeof(BuildTool_Click), nameof(BuildTool_Click.CheckBuildConditions))]
[HarmonyPatch(typeof(BuildTool_Inserter), nameof(BuildTool_Inserter.CheckBuildConditions))]
[HarmonyPatch(typeof(BuildTool_Path), nameof(BuildTool_Path.CheckBuildConditions))]
private static IEnumerable<CodeInstruction> BuildTool_CheckBuildConditions_Transpiler(IEnumerable<CodeInstruction> instructions)
{
yield return new CodeInstruction(OpCodes.Ldc_I4_1);
yield return new CodeInstruction(OpCodes.Ret);
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(BuildTool_Click), nameof(BuildTool_Click.CheckBuildConditions))]
private static IEnumerable<CodeInstruction> BuildTool_Click_CheckBuildConditions_Transpiler(IEnumerable<CodeInstruction> instructions)
{
yield return new CodeInstruction(OpCodes.Ldarg_0);
yield return new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(NoConditionBuild), nameof(CheckForMiner)));
yield return new CodeInstruction(OpCodes.Ret);
}
public static bool CheckForMiner(BuildTool tool)
{
var previews = tool.buildPreviews;
foreach (var preview in previews)
{
var desc = preview?.item?.prefabDesc;
if (desc == null) continue;
if (desc.veinMiner || desc.oilMiner) return false;
}
return true;
}
}
private static class BeltSignalGenerator
{
private static Harmony _beltSignalPatch;
private static Dictionary<int, BeltSignal>[] _signalBelts;
private static Dictionary<long, int> _portalFrom;
private static Dictionary<int, HashSet<long>> _portalTo;
private static int _signalBeltsCapacity;
private static bool _initialized;
private class BeltSignal
{
public int SignalId;
public int SpeedLimit;
public byte Stack;
public byte Inc;
public int Progress;
}
public static void Enable(bool on)
{
if (on)
{
InitSignalBelts();
_beltSignalPatch ??= Harmony.CreateAndPatchAll(typeof(BeltSignalGenerator));
}
else
{
_beltSignalPatch?.UnpatchSelf();
_initialized = false;
_signalBelts = null;
_signalBeltsCapacity = 0;
}
}
private static void InitSignalBelts()
{
if (!GameMain.isRunning) return;
_signalBelts = new Dictionary<int, BeltSignal>[64];
_signalBeltsCapacity = 64;
_portalFrom = new Dictionary<long, int>();
_portalTo = new Dictionary<int, HashSet<long>>();
foreach (var factory in GameMain.data.factories)
{
var entitySignPool = factory?.entitySignPool;
if (entitySignPool == null) continue;
var cargoTraffic = factory.cargoTraffic;
var beltPool = cargoTraffic.beltPool;
for (var i = cargoTraffic.beltCursor - 1; i > 0; i--)
{
if (beltPool[i].id != i) continue;
ref var signal = ref entitySignPool[beltPool[i].entityId];
var signalId = signal.iconId0;
if (signalId == 0U) continue;
var number = Mathf.RoundToInt(signal.count0);
switch (signalId)
{
case 404:
SetSignalBelt(factory.index, i, (int)signalId, 0);
continue;
case >= 1000 and < 20000:
if (number > 0)
SetSignalBelt(factory.index, i, (int)signalId, number);
continue;
case 600:
if (number > 0)
SetSignalBelt(factory.index, i, (int)signalId, number);
continue;
case >= 601 and <= 609:
if (number > 0)
SetSignalBeltPortalTo(factory.index, i, (int)signalId, number);
continue;
}
}
}
_initialized = true;
}
private static Dictionary<int, BeltSignal> GetOrCreateSignalBelts(int index)
{
Dictionary<int, BeltSignal> obj;
if (index < 0) return null;
if (index >= _signalBeltsCapacity)
{
var newCapacity = _signalBeltsCapacity * 2;
var newSignalBelts = new Dictionary<int, BeltSignal>[newCapacity];
Array.Copy(_signalBelts, newSignalBelts, _signalBeltsCapacity);
_signalBelts = newSignalBelts;
_signalBeltsCapacity = newCapacity;
}
else
{
obj = _signalBelts[index];
if (obj != null) return obj;
}
obj = new Dictionary<int, BeltSignal>();
_signalBelts[index] = obj;
return obj;
}
private static Dictionary<int, BeltSignal> GetSignalBelts(int index)
{
return index >= 0 && index < _signalBeltsCapacity ? _signalBelts[index] : null;
}
private static void SetSignalBelt(int factory, int beltId, int signalId, int number)
{
int stack;
int inc;
int speedLimit;
if (signalId >= 1000)
{
stack = Mathf.Clamp(number % 10, 1, 4);
inc = number / 10 % 10 * stack;
speedLimit = number / 100 % 4000;
}
else
{
stack = 0;
inc = 0;
speedLimit = number;
}
GetOrCreateSignalBelts(factory)[beltId] = new BeltSignal { SignalId = signalId, SpeedLimit = speedLimit, Stack = (byte)stack, Inc = (byte)inc, Progress = 0 };
}
private static void SetSignalBeltPortalTo(int factory, int beltId, int signalId, int number)
{
var v = ((long)factory << 32) | (long)beltId;
_portalFrom[v] = number;
if (!_portalTo.TryGetValue(number, out var set))
{
set = new HashSet<long>();
_portalTo[number] = set;
}
set.Add(v);
}
private static void RemoveSignalBelt(int factory, int beltId)
{
GetSignalBelts(factory)?.Remove(beltId);
}
private static void RemoveSignalBeltPortalEnd(int factory, int beltId)
{
var v = ((long)factory << 32) | (long)beltId;
if (!_portalFrom.TryGetValue(v, out var number)) return;
_portalFrom.Remove(beltId);
if (!_portalTo.TryGetValue(number, out var set)) return;
set.Remove(v);
}
[HarmonyPostfix]
[HarmonyPatch(typeof(GameMain), nameof(GameMain.Begin))]
private static void GameMain_Begin_Postfix()
{
InitSignalBelts();
}
[HarmonyPrefix]
[HarmonyPatch(typeof(CargoTraffic), nameof(CargoTraffic.RemoveBeltComponent))]
public static void CargoTraffic_RemoveBeltComponent_Prefix(int id)
{
if (!_initialized) return;
var planet = GameMain.localPlanet;
if (planet == null) return;
RemoveSignalBeltPortalEnd(planet.factoryIndex, id);
RemoveSignalBelt(planet.factoryIndex, id);
}
[HarmonyPostfix]
[HarmonyPatch(typeof(CargoTraffic), nameof(CargoTraffic.SetBeltSignalIcon))]
public static void CargoTraffic_SetBeltSignalIcon_Postfix(CargoTraffic __instance, int signalId, int entityId)
{
if (!_initialized) return;
var planet = GameMain.localPlanet;
if (planet == null) return;
var factory = __instance.factory;
int number;
var needAdd = false;
switch (signalId)
{
case 404:
number = 0;
needAdd = true;
break;
case >= 1000 and < 20000:
number = Mathf.RoundToInt(factory.entitySignPool[entityId].count0);
if (number > 0)
needAdd = true;
break;
case 600:
number = Mathf.RoundToInt(factory.entitySignPool[entityId].count0);
if (number > 0)
needAdd = true;
break;
case >= 601 and <= 609:
number = Mathf.RoundToInt(factory.entitySignPool[entityId].count0);
var factoryIndex = planet.factoryIndex;
var beltId = factory.entityPool[entityId].beltId;
if (number > 0)
SetSignalBeltPortalTo(factoryIndex, beltId, signalId, number);
RemoveSignalBelt(factoryIndex, beltId);
return;
default:
number = 0;
break;
}
{
var factoryIndex = planet.factoryIndex;
var beltId = factory.entityPool[entityId].beltId;
if (needAdd)
{
SetSignalBelt(factoryIndex, beltId, signalId, number);
}
else
{
RemoveSignalBelt(factoryIndex, beltId);
}
RemoveSignalBeltPortalEnd(factoryIndex, beltId);
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(CargoTraffic), nameof(CargoTraffic.SetBeltSignalNumber))]
public static void CargoTraffic_SetBeltSignalNumber_Postfix(CargoTraffic __instance, float number, int entityId)
{
if (!_initialized) return;
var planet = GameMain.localPlanet;
if (planet == null) return;
var factory = __instance.factory;
var entitySignPool = factory.entitySignPool;
uint signalId;
if (entitySignPool[entityId].iconType == 0U || (signalId = entitySignPool[entityId].iconId0) == 0U) return;
switch (signalId)
{
case 404:
return;
case 600:
case >= 1000 and < 20000:
break;
case >= 601 and <= 609:
var factoryIndex = planet.factoryIndex;
var beltId = factory.entityPool[entityId].beltId;
RemoveSignalBeltPortalEnd(factoryIndex, beltId);
SetSignalBeltPortalTo(factoryIndex, beltId, (int)signalId, Mathf.RoundToInt(number));
return;
default:
return;
}
{
var factoryIndex = planet.factoryIndex;
var beltId = factory.entityPool[entityId].beltId;
var n = Mathf.RoundToInt(number);
if (n == 0)
{
RemoveSignalBelt(factoryIndex, beltId);
}
else
{
SetSignalBelt(factoryIndex, beltId, (int)signalId, n);
}
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(GameData), "GameTick")]
public static void GameData_GameTick_Prefix()
{
if (!_initialized) return;
var factories = GameMain.data?.factories;
if (factories == null) return;
foreach (var factory in factories)
{
if (factory == null) continue;
var belts = GetSignalBelts(factory.index);
if (belts == null) continue;
foreach (var pair in belts)
{
var beltSignal = pair.Value;
var signalId = beltSignal.SignalId;
switch (signalId)
{
case 404:
{
var beltId = pair.Key;
var cargoTraffic = factory.cargoTraffic;
var belt = cargoTraffic.beltPool[beltId];
var cargoPath = cargoTraffic.GetCargoPath(belt.segPathId);
cargoPath.TryPickItem(belt.segIndex + belt.segPivotOffset - 5, 12, out _, out _);
continue;
}
case 600:
{
if (!_portalTo.TryGetValue(beltSignal.SpeedLimit, out var set)) continue;
var cargoTraffic = factory.cargoTraffic;
var beltId = pair.Key;
ref var belt = ref cargoTraffic.beltPool[beltId];
var cargoPath = cargoTraffic.GetCargoPath(belt.segPathId);
var segIndex = belt.segIndex + belt.segPivotOffset;
if (!cargoPath.GetCargoAtIndex(segIndex, out var cargo, out var cargoId, out var offset)) break;
var itemId = cargo.item;
var cargoPool = cargoPath.cargoContainer.cargoPool;
var inc = cargoPool[cargoId].inc;
var stack = cargoPool[cargoId].stack;
foreach (var n in set)
{
var cargoTraffic1 = factories[(int)(n >> 32)].cargoTraffic;
ref var belt1 = ref cargoTraffic1.beltPool[(int)(n & 0x7FFFFFFF)];
if (!cargoTraffic1.GetCargoPath(belt1.segPathId).TryInsertItem(belt1.segIndex + belt1.segPivotOffset, itemId, stack, inc)) continue;
cargoPath.TryPickItem(segIndex - 5, 12, out var stack1, out var inc1);
if (inc1 != inc || stack1 != stack)
cargoPath.TryPickItem(segIndex - 5, 12, out _, out _);
break;
}
continue;
}
case >= 1000 and < 20000:
{
if (beltSignal.SpeedLimit > 0)
{
beltSignal.Progress += beltSignal.SpeedLimit;
if (beltSignal.Progress < 3600) continue;
beltSignal.Progress -= 3600;
}
var beltId = pair.Key;
var cargoTraffic = factory.cargoTraffic;
ref var belt = ref cargoTraffic.beltPool[beltId];
var stack = beltSignal.Stack;
var inc = beltSignal.Inc;
cargoTraffic.GetCargoPath(belt.segPathId).TryInsertItem(belt.segIndex + belt.segPivotOffset, signalId, stack, inc);
continue;
}
}
}
}
}
}
}

View File

@@ -32,16 +32,32 @@ public class CheatEnabler : BaseUnityPlugin
"disable all abnormal checks");
TechPatch.Enabled = Config.Bind("General", "UnlockTech", false,
"Unlock clicked tech by holding key-modifilers(Shift/Alt/Ctrl)");
BuildPatch.ImmediateEnabled = Config.Bind("Build", "ImmediateBuild", false,
FactoryPatch.ImmediateEnabled = Config.Bind("Build", "ImmediateBuild", false,
"Build immediately");
BuildPatch.ArchitectModeEnabled = Config.Bind("Build", "Architect", false,
FactoryPatch.ArchitectModeEnabled = Config.Bind("Build", "Architect", false,
"Architect Mode");
BuildPatch.NoConditionEnabled = Config.Bind("Build", "BuildWithoutCondition", false,
FactoryPatch.UnlimitInteractiveEnabled = Config.Bind("Build", "UnlimitInteractive", false,
"Unlimit interactive range");
FactoryPatch.NoConditionEnabled = Config.Bind("Build", "BuildWithoutCondition", false,
"Build without condition");
BuildPatch.NoCollisionEnabled = Config.Bind("Build", "NoCollision", false,
FactoryPatch.NoCollisionEnabled = Config.Bind("Build", "NoCollision", false,
"No collision");
BuildPatch.BeltSignalGeneratorEnabled = Config.Bind("Build", "BeltSignalGenerator", false,
FactoryPatch.BeltSignalGeneratorEnabled = Config.Bind("Build", "BeltSignalGenerator", false,
"Belt signal generator");
FactoryPatch.BeltSignalCountRecipeEnabled = Config.Bind("Build", "BeltSignalCountRecipe", false,
"Belt signal count all raws and intermediates in statistics");
FactoryPatch.NightLightEnabled = Config.Bind("Build", "NightLight", false,
"Night light");
FactoryPatch.RemovePowerSpaceLimitEnabled = Config.Bind("Build", "RemovePowerDistanceLimit", false,
"Remove distance limit for wind turbines and geothermals");
FactoryPatch.BoostWindPowerEnabled = Config.Bind("Build", "BoostWindPower", false,
"Boost wind power");
FactoryPatch.BoostSolarPowerEnabled = Config.Bind("Build", "BoostSolarPower", false,
"Boost solar power");
FactoryPatch.BoostFuelPowerEnabled = Config.Bind("Build", "BoostFuelPower", false,
"Boost fuel power");
FactoryPatch.BoostGeothermalPowerEnabled = Config.Bind("Build", "BoostGeothermalPower", false,
"Boost geothermal power");
ResourcePatch.InfiniteEnabled = Config.Bind("Planet", "AlwaysInfiniteResource", false,
"always infinite natural resource");
ResourcePatch.FastEnabled = Config.Bind("Planet", "FastMining", false,
@@ -94,8 +110,7 @@ public class CheatEnabler : BaseUnityPlugin
DevShortcuts.Init();
AbnormalDisabler.Init();
TechPatch.Init();
BuildPatch.Init();
PlanetFunctions.Init();
FactoryPatch.Init();
ResourcePatch.Init();
WaterPumperPatch.Init();
TerraformPatch.Init();
@@ -110,8 +125,7 @@ public class CheatEnabler : BaseUnityPlugin
TerraformPatch.Uninit();
WaterPumperPatch.Uninit();
ResourcePatch.Uninit();
PlanetFunctions.Uninit();
BuildPatch.Uninit();
FactoryPatch.Uninit();
TechPatch.Uninit();
AbnormalDisabler.Uninit();
DevShortcuts.Uninit();
@@ -134,7 +148,7 @@ public class CheatEnabler : BaseUnityPlugin
private void LateUpdate()
{
BuildPatch.NightLightLateUpdate();
FactoryPatch.NightLight.LateUpdate();
}
[HarmonyPostfix, HarmonyPatch(typeof(UIRoot), nameof(UIRoot.OpenMainMenuUI))]
@@ -240,6 +254,7 @@ public class CheatEnabler : BaseUnityPlugin
{
if (!_configWinInitialized)
{
if (!I18N.Initialized()) return;
_configWinInitialized = true;
_configWin = UIConfigWindow.CreateInstance();
}

View File

@@ -5,7 +5,7 @@
<TargetFramework>net472</TargetFramework>
<BepInExPluginGuid>org.soardev.cheatenabler</BepInExPluginGuid>
<Description>DSP MOD - CheatEnabler</Description>
<Version>2.1.0</Version>
<Version>2.2.0</Version>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>latest</LangVersion>
<PackageId>CheatEnabler</PackageId>

1276
CheatEnabler/FactoryPatch.cs Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@ using HarmonyLib;
namespace CheatEnabler;
public class I18N
public static class I18N
{
private static bool _initialized;
@@ -15,6 +15,8 @@ public class I18N
{
Harmony.CreateAndPatchAll(typeof(I18N));
}
public static bool Initialized() => _initialized;
private static int _nextID = 1;
private static readonly List<StringProto> StringsToAdd = new();
public static void Add(string key, string enus, string zhcn = null, string frfr = null)

View File

@@ -8,8 +8,8 @@ using Random = UnityEngine.Random;
namespace CheatEnabler;
public static class PlanetFunctions
{
/*
private static Harmony _patch;
private static readonly Dictionary<int, ItemSource> ItemSources = new();
private static PumpSource[] _pumpItemSources = new PumpSource[16];
private static int _pumpItemSourcesLength = 16;
@@ -44,6 +44,16 @@ public static class PlanetFunctions
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(PlanetFactory), nameof(PlanetFactory.Init))]
private static void PlanetFactory_Init_Postfix(PlanetFactory __instance)
{
const int waterItemId = 6006;
__instance.planet.waterItemId = waterItemId;
CheatEnabler.Logger.LogDebug($"Init PlanetFactory with waterItemId {waterItemId}");
UpdatePumpItemSources(__instance);
}
private static void UpdatePumpItemSources(PlanetFactory factory)
{
var index = factory.index;
@@ -96,164 +106,7 @@ public static class PlanetFunctions
pump.Items = items;
pump.Progress = progress;
}
/* Pump item calculation */
private class ItemSource
{
public float Count;
public Dictionary<int, float> From;
public Dictionary<int, float> Extra;
}
private static void InitItemSources()
{
ItemSources.Clear();
foreach (var vein in LDB.veins.dataArray)
{
ItemSources[vein.MiningItem] = new ItemSource { Count = 1 };
}
foreach (var ip in LDB.items.dataArray)
{
if (!string.IsNullOrEmpty(ip.MiningFrom))
{
ItemSources[ip.ID] = new ItemSource { Count = 1 };
}
}
ItemSources[1208] = new ItemSource { Count = 1 };
var recipes = LDB.recipes.dataArray;
foreach (var recipe in recipes)
{
if (!recipe.Explicit || recipe.ID == 58 || recipe.ID == 121) continue;
var res = recipe.Results;
var rescnt = recipe.ResultCounts;
var len = res.Length;
for (var i = 0; i < len; i++)
{
if (ItemSources.ContainsKey(res[i])) continue;
var rs = new ItemSource { Count = rescnt[i], From = new Dictionary<int, float>() };
var it = recipe.Items;
var itcnt = recipe.ItemCounts;
var len2 = it.Length;
for (var j = 0; j < len2; j++)
{
rs.From[it[j]] = itcnt[j];
}
if (len > 1)
{
rs.Extra = new Dictionary<int, float>();
for (var k = 0; k < len; k++)
{
if (i != k)
{
rs.Extra[res[k]] = rescnt[k];
}
}
}
ItemSources[res[i]] = rs;
}
}
foreach (var recipe in recipes)
{
if (recipe.Explicit) continue;
var res = recipe.Results;
var rescnt = recipe.ResultCounts;
var len = res.Length;
for (var i = 0; i < len; i++)
{
if (ItemSources.ContainsKey(res[i])) continue;
var rs = new ItemSource { Count = rescnt[i], From = new Dictionary<int, float>() };
var it = recipe.Items;
var itcnt = recipe.ItemCounts;
var len2 = it.Length;
for (var j = 0; j < len2; j++)
{
rs.From[it[j]] = itcnt[j];
}
if (len > 1)
{
rs.Extra = new Dictionary<int, float>();
for (var k = 0; k < len; k++)
{
if (i != k)
{
rs.Extra[res[k]] = rescnt[k];
}
}
}
ItemSources[res[i]] = rs;
}
}
}
public static void CalculateAllProductions(Dictionary<int, float> result, Dictionary<int, float> extra, int itemId, float count = 0f)
{
if (!ItemSources.TryGetValue(itemId, out var itemSource))
{
if (count <= 0) return;
result.TryGetValue(itemId, out var oldCount);
result[itemId] = oldCount + count;
return;
}
var times = 1f;
if (count == 0f)
{
count = itemSource.Count;
}
else if (Math.Abs(count - itemSource.Count) > 0.000001f)
{
times = count / itemSource.Count;
}
{
result.TryGetValue(itemId, out var oldCount);
result[itemId] = oldCount + count;
}
if (itemSource.Extra != null)
{
foreach (var p in itemSource.Extra)
{
extra.TryGetValue(p.Key, out var oldCount);
extra[p.Key] = oldCount + times * p.Value;
}
}
if (itemSource.From == null) return;
foreach (var p in itemSource.From)
{
CalculateAllProductions(result, extra, p.Key, times * p.Value);
}
}
public static void CalculateAllProductions(Dictionary<int, float> result, int itemId, float count = 0f)
{
var extra = new Dictionary<int, float>();
CalculateAllProductions(result, extra, itemId, count);
foreach (var k in extra.Keys.ToArray())
{
if (!result.TryGetValue(k, out var cnt)) continue;
var cnt2 = extra[k];
if (Math.Abs(cnt - cnt2) < 0.000001f)
{
result.Remove(k);
extra.Remove(k);
continue;
}
if (cnt > cnt2)
{
result[k] = cnt - cnt2;
extra.Remove(k);
continue;
}
result.Remove(k);
extra[k] = cnt2 - cnt;
}
}
/* Pump item calculation */
*/
public static void DismantleAll(bool toBag)
{

View File

@@ -4,6 +4,10 @@
#### 添加一些作弊功能,同时屏蔽异常检测
## Changlog
* 2.2.0
+ Add some power related functions
+ Add a subfunction to belt signal item generation, which simulates production process of raws and intermediates on statistics
+ Split some functions from Architect mode
* 2.1.0
+ Belt signal item generation
+ Fix window display priority which may cause tips to be covered by main window
@@ -24,12 +28,17 @@
+ Enable Dev Shortcuts (check config panel for usage)
+ Disable Abnormal Checks
+ Unlock techs with key-modifiers (Ctrl/Alt/Shift)
+ Build:
+ Factory:
+ Finish build immediately
+ Architect mode (Infinite buildings + Interactive without distance limit + Sunlight at night)
+ Architect mode (Infinite buildings)
+ Unlimited interactive range
+ Build without condition
+ No collision
+ Belt signal item generation
+ Count all raws and intermediates in statistics
+ Sunlight at night
+ Remove space limit between wind turbines and solar panels
+ Boost power generations for kinds of power generators
+ Planet:
+ Infinite Natural Resources
+ Fast Mining
@@ -56,6 +65,10 @@
* [LSTM](https://github.com/hetima/DSP_LSTM) & [PlanetFinder](https://github.com/hetima/DSP_PlanetFinder): UI implementations
## 更新日志
* 2.2.0
+ 添加了一些发电相关功能
+ 为传送带信号物品生成添加了一个子功能,在统计面板模拟了原材料和中间产物的生产过程
+ 从建筑师模式中分离了一些功能
* 2.1.0
+ 传送带信号物品生成
+ 修复窗口显示优先级可能导致提示信息被主窗口遮挡的问题
@@ -76,12 +89,16 @@
+ 启用开发模式快捷键(使用说明见设置面板)
+ 屏蔽异常检测
+ 使用组合键解锁科技Ctrl/Alt/Shift
+ 建造
+ 工厂
+ 建造秒完成
+ 建筑师模式(无限建筑+无视距离操作+夜间日光灯)
+ 建筑师模式(无限建筑)
+ 无限交互距离
+ 无条件建造
+ 无碰撞
+ 传送带信号物品生成
+ 夜间日光灯
+ 风力发电机和太阳能板无间距限制
+ 提升各种发电设备发电量
+ 行星:
+ 自然资源采集不消耗
+ 高速采集

View File

@@ -22,12 +22,21 @@ public class UIConfigWindow : UI.MyWindowWithTabs
I18N.Add("Unlock Tech with Key-Modifiers Tips",
"Click tech on tree while holding:\n Shift: Tech level + 1\n Ctrl: Tech level + 10\n Ctrl + Shift: Tech level + 100\n Alt: Tech level to MAX\n\nNote: all direct prerequisites will be unlocked as well.",
"按住以下组合键点击科技树:\n Shift科技等级+1\n Ctrl科技等级+10\n Ctrl+Shift科技等级+100\n Alt科技等级升到最大\n\n注意所有直接前置科技也会被解锁");
I18N.Add("Build", "Build", "建造");
I18N.Add("Factory", "Factory", "工厂");
I18N.Add("Finish build immediately", "Finish build immediately", "建造秒完成");
I18N.Add("Architect mode", "Architect mode", "建筑师模式");
I18N.Add("Unlimited interactive range", "Unlimited interactive range", "无限交互距离");
I18N.Add("Build without condition", "Build without condition check", "无条件建造");
I18N.Add("No collision", "No collision", "无碰撞");
I18N.Add("Belt signal generator", "Belt signal generator", "传送带信号物品生成");
I18N.Add("Count all raws and intermediates in statistics","Count all raw materials in statistics", "统计信息里计算所有原料和中间产物");
I18N.Add("Night Light", "Sunlight at night", "夜间日光灯");
I18N.Add("Remove power space limit", "Remove space limit for winds and geothermals", "移除风力发电和地热发电的间距限制");
I18N.Add("Boost wind power", "Boost wind power(x100,000)", "提升风力发电(x100,000)");
I18N.Add("Boost solar power", "Boost solar power(x100,000)", "提升太阳能发电(x100,000)");
I18N.Add("Boost fuel power", "Boost fuel power(x50,000)", "提升燃料发电(x50,000)");
I18N.Add("Boost fuel power 2", "(x20,000 for deuteron, x10,000 for antimatter)", "(氘核燃料棒x20,000反物质燃料棒x10,000)");
I18N.Add("Boost geothermal power", "Boost geothermal power(x50,000)", "提升地热发电(x50,000)");
I18N.Add("Planet", "Planet", "行星");
I18N.Add("Infinite Natural Resources", "Infinite Natural Resources", "自然资源采集不消耗");
I18N.Add("Fast Mining", "Fast Mining", "高速采集");
@@ -66,7 +75,7 @@ public class UIConfigWindow : UI.MyWindowWithTabs
public override void _OnCreate()
{
_windowTrans = GetComponent<RectTransform>();
_windowTrans.sizeDelta = new Vector2(580f, 331f);
_windowTrans.sizeDelta = new Vector2(580f, 400f);
CreateUI();
}
@@ -82,7 +91,7 @@ public class UIConfigWindow : UI.MyWindowWithTabs
UI.MyCheckBox.CreateCheckBox(x, y, tab1, AbnormalDisabler.Enabled, "Disable Abnormal Checks");
y += 36f;
UI.MyCheckBox.CreateCheckBox(x, y, tab1, TechPatch.Enabled, "Unlock Tech with Key-Modifiers");
y += 50f;
y += 118f;
UI.MyKeyBinder.CreateKeyBinder(x, y, tab1, CheatEnabler.Hotkey, "Hotkey");
x = 156f;
y = 16f;
@@ -91,18 +100,44 @@ public class UIConfigWindow : UI.MyWindowWithTabs
y += 72f;
AddTipsButton(x, y, tab1, "Unlock Tech with Key-Modifiers", "Unlock Tech with Key-Modifiers Tips", "unlock-tech-tips");
var tab2 = AddTab(136f, 1, _windowTrans, "Build");
var tab2 = AddTab(136f, 1, _windowTrans, "Factory");
x = 0f;
y = 10f;
UI.MyCheckBox.CreateCheckBox(x, y, tab2, BuildPatch.ImmediateEnabled, "Finish build immediately");
UI.MyCheckBox.CreateCheckBox(x, y, tab2, FactoryPatch.ImmediateEnabled, "Finish build immediately");
y += 36f;
UI.MyCheckBox.CreateCheckBox(x, y, tab2, BuildPatch.ArchitectModeEnabled, "Architect mode");
UI.MyCheckBox.CreateCheckBox(x, y, tab2, FactoryPatch.ArchitectModeEnabled, "Architect mode");
y += 36f;
UI.MyCheckBox.CreateCheckBox(x, y, tab2, BuildPatch.NoConditionEnabled, "Build without condition");
UI.MyCheckBox.CreateCheckBox(x, y, tab2, FactoryPatch.UnlimitInteractiveEnabled, "Unlimited interactive range");
y += 36f;
UI.MyCheckBox.CreateCheckBox(x, y, tab2, BuildPatch.NoCollisionEnabled, "No collision");
UI.MyCheckBox.CreateCheckBox(x, y, tab2, FactoryPatch.NoConditionEnabled, "Build without condition");
y += 36f;
UI.MyCheckBox.CreateCheckBox(x, y, tab2, BuildPatch.BeltSignalGeneratorEnabled, "Belt signal generator");
UI.MyCheckBox.CreateCheckBox(x, y, tab2, FactoryPatch.NoCollisionEnabled, "No collision");
y += 36f;
UI.MyCheckBox.CreateCheckBox(x, y, tab2, FactoryPatch.NightLightEnabled, "Night Light");
y += 36f;
UI.MyCheckBox.CreateCheckBox(x, y, tab2, FactoryPatch.BeltSignalGeneratorEnabled, "Belt signal generator");
y += 26f;
x += 26f;
var cb = UI.MyCheckBox.CreateCheckBox(x, y, tab2, FactoryPatch.BeltSignalCountRecipeEnabled, "Count all raws and intermediates in statistics", 13);
cb.gameObject.SetActive(FactoryPatch.BeltSignalGeneratorEnabled.Value);
FactoryPatch.BeltSignalGeneratorEnabled.SettingChanged += (_, _) =>
{
cb.gameObject.SetActive(FactoryPatch.BeltSignalGeneratorEnabled.Value);
};
x = 240f;
y = 10f;
UI.MyCheckBox.CreateCheckBox(x, y, tab2, FactoryPatch.RemovePowerSpaceLimitEnabled, "Remove power space limit");
y += 36f;
UI.MyCheckBox.CreateCheckBox(x, y, tab2, FactoryPatch.BoostWindPowerEnabled, "Boost wind power");
y += 36f;
UI.MyCheckBox.CreateCheckBox(x, y, tab2, FactoryPatch.BoostSolarPowerEnabled, "Boost solar power");
y += 36f;
UI.MyCheckBox.CreateCheckBox(x, y, tab2, FactoryPatch.BoostGeothermalPowerEnabled, "Boost geothermal power");
y += 36f;
UI.MyCheckBox.CreateCheckBox(x, y, tab2, FactoryPatch.BoostFuelPowerEnabled, "Boost fuel power");
x += 32f;
y += 26f;
AddText(x, y, tab2, "Boost fuel power 2", 13);
// Planet Tab
var tab3 = AddTab(236f, 2, _windowTrans, "Planet");
@@ -191,14 +226,14 @@ public class UIConfigWindow : UI.MyWindowWithTabs
UI.MyCheckBox.CreateCheckBox(x, y, tab5, BirthPlanetPatch.FractalOnBirthPlanet, "Fractal silicon on birth planet");
y += 36f;
UI.MyCheckBox.CreateCheckBox(x, y, tab5, BirthPlanetPatch.OrganicOnBirthPlanet, "Organic crystal on birth planet");
x = 200f;
y = 10f;
y += 36f;
UI.MyCheckBox.CreateCheckBox(x, y, tab5, BirthPlanetPatch.OpticalOnBirthPlanet, "Optical grating crystal on birth planet");
y += 36f;
UI.MyCheckBox.CreateCheckBox(x, y, tab5, BirthPlanetPatch.SpiniformOnBirthPlanet, "Spiniform stalagmite crystal on birth planet");
y += 36f;
UI.MyCheckBox.CreateCheckBox(x, y, tab5, BirthPlanetPatch.UnipolarOnBirthPlanet, "Unipolar magnet on birth planet");
y += 36f;
x = 200f;
y = 10f;
UI.MyCheckBox.CreateCheckBox(x, y, tab5, BirthPlanetPatch.FlatBirthPlanet, "Birth planet is solid flat (no water at all)");
y += 36f;
UI.MyCheckBox.CreateCheckBox(x, y, tab5, BirthPlanetPatch.HighLuminosityBirthStar, "Birth star has high luminosity");

View File

@@ -1,6 +1,6 @@
{
"name": "CheatEnabler",
"version_number": "2.1.0",
"version_number": "2.2.0",
"website_url": "https://github.com/soarqin/DSP_Mods/tree/master/CheatEnabler",
"description": "Add various cheat functions while disabling abnormal determinants / 添加一些作弊功能,同时屏蔽异常检测",
"dependencies": [