Files
DSP_Mods/UXAssist/Patches/Factory/RenderingPatch.cs
T

213 lines
9.1 KiB
C#

using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using HarmonyLib;
using UnityEngine;
using UXAssist.Common;
using GameLogicProc = UXAssist.Common.GameLogic;
namespace UXAssist.Patches.Factory;
internal static class RenderingPatch
{
public static void Enable(bool enable)
{
DoNotRenderEntities.Enable(enable);
NightLight.Enable(enable);
}
internal class DoNotRenderEntities : PatchImpl<DoNotRenderEntities>
{
[HarmonyPrefix]
[HarmonyPatch(typeof(ObjectRenderer), nameof(ObjectRenderer.Render))]
[HarmonyPatch(typeof(DynamicRenderer), nameof(DynamicRenderer.Render))]
private static bool ObjectRenderer_Render_Prefix()
{
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(LabRenderer), nameof(LabRenderer.Render))]
private static bool LabRenderer_Render_Prefix()
{
return false;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(GPUInstancingManager), nameof(GPUInstancingManager.Render))]
private static void FactoryModel_DrawInstancedBatches_Postfix(GPUInstancingManager __instance)
{
__instance.renderEntity = true;
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(RaycastLogic), nameof(RaycastLogic.GameTick))]
private static IEnumerable<CodeInstruction> RaycastLogic_GameTick_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
var matcher = new CodeMatcher(instructions, generator);
matcher.MatchForward(false,
new CodeMatch(OpCodes.Ldc_I4_0),
new CodeMatch(OpCodes.Brtrue));
var branch1 = (Label)matcher.Advance(1).Operand;
var branch2 = generator.DefineLabel();
matcher.Start().MatchForward(false,
new CodeMatch(OpCodes.Call),
new CodeMatch(ci => ci.IsStloc()),
new CodeMatch(OpCodes.Call),
new CodeMatch(ci => ci.IsStloc()),
new CodeMatch(OpCodes.Call),
new CodeMatch(ci => ci.IsStloc()),
new CodeMatch(ci => ci.IsLdloc()),
new CodeMatch(ci => ci.Branches(out _)),
new CodeMatch(OpCodes.Ldarg_0)
).Advance(8).InsertAndAdvance(
new CodeInstruction(OpCodes.Ldloc_S, 45),
new CodeInstruction(OpCodes.Brtrue, branch2),
new CodeInstruction(OpCodes.Ldarg_0),
new CodeInstruction(OpCodes.Ldloc_S, 33),
new CodeInstruction(OpCodes.Ldloc_S, 35),
Transpilers.EmitDelegate((RaycastLogic l, ColliderData[] colliderPool, int j) => l.factory.entityPool[colliderPool[j].objId].inserterId > 0),
new CodeInstruction(OpCodes.Brfalse, branch1)
);
matcher.Labels.Add(branch2);
return matcher.InstructionEnumeration();
}
}
internal class NightLight : PatchImpl<NightLight>
{
private static bool _nightlightInitialized;
private static bool _mechaOnEarth;
private static AnimationState _sail;
private static Light _sunlight;
protected override void OnEnable()
{
GameLogicProc.OnGameEnd += OnGameEnd;
}
protected override void OnDisable()
{
GameLogicProc.OnGameEnd -= OnGameEnd;
if (_sunlight)
{
_sunlight.transform.localEulerAngles = new Vector3(0f, 180f);
_sunlight = null;
}
_sail = null;
_mechaOnEarth = false;
_nightlightInitialized = false;
}
private static void OnGameEnd()
{
if (_sunlight)
{
_sunlight.transform.localEulerAngles = new Vector3(0f, 180f);
_sunlight = null;
}
_sail = null;
_mechaOnEarth = false;
_nightlightInitialized = false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void UpdateSunlightAngle()
{
if (!_sunlight) return;
_sunlight.transform.rotation =
Quaternion.LookRotation(-GameMain.mainPlayer.transform.up + GameMain.mainPlayer.transform.forward * FactoryPatch.NightLightAngleX.Value / 10f +
GameMain.mainPlayer.transform.right * FactoryPatch.NightLightAngleY.Value / 10f);
}
[HarmonyPostfix]
[HarmonyPatch(typeof(GameMain), nameof(GameMain.LateUpdate))]
public static void GameMain_LateUpdate_Postfix(GameMain __instance)
{
if (__instance.isMenuDemo || !__instance._running) return;
if (!_nightlightInitialized)
{
if (!GameMain.mainPlayer.controller.model.gameObject.activeInHierarchy) return;
if (_sail == null) _sail = GameMain.mainPlayer.animator.sails[GameMain.mainPlayer.animator.sailAnimIndex];
_nightlightInitialized = true;
}
var sailing = _sail && _sail.enabled;
if (_mechaOnEarth)
{
if (!sailing)
{
UpdateSunlightAngle();
return;
}
_mechaOnEarth = false;
if (!_sunlight) return;
_sunlight.transform.localEulerAngles = new Vector3(0f, 180f);
_sunlight = null;
return;
}
if (sailing) return;
_mechaOnEarth = true;
if (_sunlight == null)
{
_sunlight = GameMain.universeSimulator?.LocalStarSimulator()?.sunLight;
}
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(StarSimulator), nameof(StarSimulator.LateUpdate))]
private static IEnumerable<CodeInstruction> StarSimulator_LateUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
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(NightLight), nameof(_mechaOnEarth))),
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), nameof(PlanetSimulator.LateRefresh))]
private static IEnumerable<CodeInstruction> PlanetSimulator_LateRefresh_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.Stloc_1)
).Advance(1).InsertAndAdvance(
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(NightLight), nameof(_mechaOnEarth))),
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_2),
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();
}
}
}