mirror of
https://github.com/soarqin/DSP_Mods.git
synced 2026-08-05 21:40:21 +08:00
222 lines
11 KiB
C#
222 lines
11 KiB
C#
using System.Collections.Generic;
|
|
using System.Reflection.Emit;
|
|
using BepInEx.Configuration;
|
|
using HarmonyLib;
|
|
using UnityEngine;
|
|
using UXAssist.Common.GameConstants;
|
|
using UXAssist.Common.ModFeatures;
|
|
|
|
namespace UniverseGenTweaks;
|
|
|
|
[ModFeature("UniverseGenGalaxyGen", Order = 11)]
|
|
public static class GalaxyGenSettingsPatch
|
|
{
|
|
internal static double MinDist = UniverseGenConstants.DefaultMinDist;
|
|
internal static double MinStep = UniverseGenConstants.DefaultMinStep;
|
|
internal static double MaxStep = UniverseGenConstants.DefaultMaxStep;
|
|
internal static double Flatten = UniverseGenConstants.DefaultFlatten;
|
|
|
|
internal static double GameMinDist = UniverseGenConstants.DefaultMinDist;
|
|
internal static double GameMinStep = UniverseGenConstants.DefaultMinStep;
|
|
internal static double GameMaxStep = UniverseGenConstants.DefaultMaxStep;
|
|
internal static double GameFlatten = UniverseGenConstants.DefaultFlatten;
|
|
|
|
private static Harmony _patch;
|
|
private static Harmony _permanentPatch;
|
|
|
|
public static void Init()
|
|
{
|
|
_permanentPatch ??= Harmony.CreateAndPatchAll(typeof(PermanentPatch));
|
|
MoreSettings.Enabled.SettingChanged += OnEnabledChanged;
|
|
Enable(MoreSettings.Enabled.Value);
|
|
}
|
|
|
|
public static void Uninit()
|
|
{
|
|
MoreSettings.Enabled.SettingChanged -= OnEnabledChanged;
|
|
Enable(false);
|
|
_permanentPatch?.UnpatchSelf();
|
|
_permanentPatch = null;
|
|
}
|
|
|
|
private static void OnEnabledChanged(object sender, System.EventArgs e)
|
|
{
|
|
Enable(MoreSettings.Enabled.Value);
|
|
}
|
|
|
|
internal static void Enable(bool on)
|
|
{
|
|
if (on)
|
|
{
|
|
_patch ??= Harmony.CreateAndPatchAll(typeof(Patch));
|
|
return;
|
|
}
|
|
_patch?.UnpatchSelf();
|
|
_patch = null;
|
|
}
|
|
|
|
private static class Patch
|
|
{
|
|
[HarmonyTranspiler]
|
|
[HarmonyPatch(typeof(UIGalaxySelect), nameof(UIGalaxySelect.OnStarCountSliderValueChange))]
|
|
private static IEnumerable<CodeInstruction> UIGalaxySelect_OnStarCountSliderValueChange_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
|
{
|
|
// Increase hard-coded maximum star count from 80 to MaxStarCount.Value
|
|
var matcher = new CodeMatcher(instructions, generator);
|
|
matcher.MatchForward(false,
|
|
new CodeMatch(ci => ci.opcode == OpCodes.Ldc_I4_S && ci.OperandIs(UniverseGenConstants.VanillaMaxStarCount))
|
|
).SetAndAdvance(OpCodes.Ldsfld, AccessTools.Field(typeof(MoreSettings), nameof(MoreSettings.MaxStarCount))).Insert(
|
|
new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(ConfigEntry<int>), nameof(ConfigEntry<int>.Value)))
|
|
);
|
|
return matcher.InstructionEnumeration();
|
|
}
|
|
}
|
|
|
|
private static class PermanentPatch
|
|
{
|
|
[HarmonyPrefix]
|
|
[HarmonyPatch(typeof(GameMain), nameof(GameMain.Start))]
|
|
private static void GameMain_Start_Prefix()
|
|
{
|
|
if (DSPGame.GameDesc != null)
|
|
{
|
|
if (GameMain.data != null) return;
|
|
GameMinDist = MinDist;
|
|
GameMinStep = MinStep;
|
|
GameMaxStep = MaxStep;
|
|
GameFlatten = Flatten;
|
|
}
|
|
else
|
|
{
|
|
GameMinDist = UniverseGenConstants.DefaultMinDist;
|
|
GameMinStep = UniverseGenConstants.DefaultMinStep;
|
|
GameMaxStep = UniverseGenConstants.DefaultMaxStep;
|
|
GameFlatten = UniverseGenConstants.DefaultFlatten;
|
|
}
|
|
}
|
|
|
|
[HarmonyTranspiler]
|
|
[HarmonyPatch(typeof(GalaxyData), MethodType.Constructor)]
|
|
private static IEnumerable<CodeInstruction> GalaxyData_Constructor_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
|
{
|
|
// 25700 -> 102500
|
|
var matcher = new CodeMatcher(instructions, generator);
|
|
matcher.MatchForward(false,
|
|
new CodeMatch(ci => ci.opcode == OpCodes.Ldc_I4 && ci.OperandIs(UniverseGenConstants.VanillaGalaxyCapacity))
|
|
);
|
|
matcher.Repeat(m => m.SetAndAdvance(OpCodes.Ldc_I4, UniverseGenConstants.ExpandedGalaxyCapacity));
|
|
return matcher.InstructionEnumeration();
|
|
}
|
|
|
|
[HarmonyTranspiler]
|
|
[HarmonyPatch(typeof(SectorModel), nameof(SectorModel.CreateGalaxyAstroBuffer))]
|
|
[HarmonyPatch(typeof(SpaceColliderLogic), nameof(SpaceColliderLogic.UpdateCollidersPose))]
|
|
private static IEnumerable<CodeInstruction> SectorModel_CreateGalaxyAstroBuffer_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
|
{
|
|
// 25600 -> 102500
|
|
var matcher = new CodeMatcher(instructions, generator);
|
|
matcher.MatchForward(false,
|
|
new CodeMatch(ci => ci.opcode == OpCodes.Ldc_I4 && ci.OperandIs(UniverseGenConstants.VanillaSectorCapacity))
|
|
);
|
|
matcher.Repeat(m => m.SetAndAdvance(OpCodes.Ldc_I4, UniverseGenConstants.ExpandedSectorCapacity));
|
|
return matcher.InstructionEnumeration();
|
|
}
|
|
|
|
[HarmonyTranspiler]
|
|
[HarmonyPatch(typeof(UniverseGen), nameof(UniverseGen.CreateGalaxy))]
|
|
private static IEnumerable<CodeInstruction> UniverseGen_CreateGalaxy_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
|
{
|
|
var matcher = new CodeMatcher(instructions, generator);
|
|
var b0 = generator.DefineLabel();
|
|
var b1 = generator.DefineLabel();
|
|
matcher.MatchForward(false,
|
|
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(UniverseGen), nameof(UniverseGen.GenerateTempPoses)))
|
|
).Advance(-4).RemoveInstructions(4).InsertAndAdvance(
|
|
new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(UIRoot), nameof(UIRoot.instance))),
|
|
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(UIRoot), nameof(UIRoot.galaxySelect))),
|
|
new CodeInstruction(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(ManualBehaviour), nameof(ManualBehaviour.active))),
|
|
new CodeInstruction(OpCodes.Brfalse, b0),
|
|
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(GalaxyGenSettingsPatch), nameof(MinDist))),
|
|
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(GalaxyGenSettingsPatch), nameof(MinStep))),
|
|
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(GalaxyGenSettingsPatch), nameof(MaxStep))),
|
|
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(GalaxyGenSettingsPatch), nameof(Flatten))),
|
|
new CodeInstruction(OpCodes.Br, b1),
|
|
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(GalaxyGenSettingsPatch), nameof(GameMinDist))).WithLabels(b0),
|
|
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(GalaxyGenSettingsPatch), nameof(GameMinStep))),
|
|
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(GalaxyGenSettingsPatch), nameof(GameMaxStep))),
|
|
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(GalaxyGenSettingsPatch), nameof(GameFlatten)))
|
|
);
|
|
matcher.Labels.Add(b1);
|
|
return matcher.InstructionEnumeration();
|
|
}
|
|
|
|
/* Patch `rand() * (maxStepLen - minStepLen) + minDist` to `rand() * (maxStepLen - minStepLen) + minStepLen`,
|
|
this should be a bugged line in original game code. */
|
|
[HarmonyTranspiler]
|
|
[HarmonyPatch(typeof(UniverseGen), nameof(UniverseGen.RandomPoses))]
|
|
private static IEnumerable<CodeInstruction> UniverseGen_RandomPoses_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
|
{
|
|
var matcher = new CodeMatcher(instructions, generator);
|
|
matcher.MatchForward(false,
|
|
new CodeMatch(OpCodes.Mul),
|
|
new CodeMatch(OpCodes.Ldarg_2)
|
|
);
|
|
matcher.Repeat(m => m.Advance(1).SetInstructionAndAdvance(new CodeInstruction(OpCodes.Ldarg_3)));
|
|
return matcher.InstructionEnumeration();
|
|
}
|
|
|
|
[HarmonyTranspiler]
|
|
[HarmonyPatch(typeof(UIVirtualStarmap), nameof(UIVirtualStarmap._OnLateUpdate))]
|
|
private static IEnumerable<CodeInstruction> UIVirtualStarmap__OnLateUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
|
{
|
|
var matcher = new CodeMatcher(instructions, generator);
|
|
var local1 = generator.DeclareLocal(typeof(UIVirtualStarmap.StarNode));
|
|
matcher.MatchForward(false,
|
|
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIVirtualStarmap.StarNode), nameof(UIVirtualStarmap.StarNode.nameText))),
|
|
new CodeMatch(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(UnityEngine.Component), nameof(UnityEngine.Component.gameObject))),
|
|
new CodeMatch(ci => ci.IsLdloc()),
|
|
new CodeMatch(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(GameObject), nameof(GameObject.SetActive)))
|
|
).InsertAndAdvance(
|
|
new CodeInstruction(OpCodes.Dup),
|
|
new CodeInstruction(OpCodes.Stloc, local1)
|
|
).Advance(3).Insert(
|
|
new CodeInstruction(OpCodes.Ldloc, local1),
|
|
Transpilers.EmitDelegate(bool (UIVirtualStarmap.StarNode starNode) =>
|
|
{
|
|
return starNode?.starData?.type switch
|
|
{
|
|
EStarType.NeutronStar or EStarType.BlackHole => true,
|
|
_ => false,
|
|
};
|
|
}),
|
|
new CodeInstruction(OpCodes.Or)
|
|
);
|
|
return matcher.InstructionEnumeration();
|
|
}
|
|
|
|
[HarmonyTranspiler]
|
|
[HarmonyPatch(typeof(UIGalaxySelect), nameof(UIGalaxySelect.UpdateUIDisplay))]
|
|
private static IEnumerable<CodeInstruction> UIGalaxySelect_UpdateUIDisplay_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
|
{
|
|
var matcher = new CodeMatcher(instructions, generator);
|
|
Label? b1 = null;
|
|
matcher.MatchForward(false,
|
|
new CodeMatch(OpCodes.Ldc_I4_0),
|
|
new CodeMatch(ci => ci.IsStloc()),
|
|
new CodeMatch(ci => ci.Branches(out b1)),
|
|
new CodeMatch(ci => ci.IsLdloc()),
|
|
new CodeMatch(ci => ci.IsLdloc()),
|
|
new CodeMatch(OpCodes.Ldelem_Ref),
|
|
new CodeMatch(ci => ci.IsStloc()),
|
|
new CodeMatch(ci => ci.IsLdloc())
|
|
).Advance(7);
|
|
var instr = matcher.InstructionAt(0);
|
|
matcher.Insert(
|
|
instr,
|
|
new CodeInstruction(OpCodes.Brfalse, b1!)
|
|
);
|
|
return matcher.InstructionEnumeration();
|
|
}
|
|
}
|
|
}
|