81 lines
3.4 KiB
C#
81 lines
3.4 KiB
C#
/*
|
|
Copyright 2025 Maciej Pawłowski
|
|
|
|
This file is part of "Table Eating Toggle".
|
|
|
|
"Table Eating Toggle" is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
|
|
"Table Eating Toggle" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along with "Table Eating Toggle". If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Reflection.Emit;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Text.RegularExpressions;
|
|
using HarmonyLib;
|
|
using RimWorld;
|
|
using Verse;
|
|
|
|
namespace TableToggle;
|
|
|
|
[HarmonyPatch]
|
|
public static class BaseChairValidator_Patch
|
|
{
|
|
[HarmonyTranspiler]
|
|
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
|
{
|
|
CodeMatcher codeMatcher = new(instructions, generator);
|
|
try
|
|
{
|
|
codeMatcher.Start();
|
|
codeMatcher.MatchStartForward(
|
|
[
|
|
CodeMatch.LoadsField(typeof(Thing).GetField(nameof(Thing.def))),
|
|
CodeMatch.LoadsField(typeof(ThingDef).GetField(nameof(ThingDef.surfaceType))),
|
|
CodeMatch.LoadsConstant(),
|
|
CodeMatch.Branches()
|
|
]
|
|
)
|
|
.ThrowIfInvalid("Could not find SurfaceType check");
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.Error(e.Message);
|
|
return instructions;
|
|
}
|
|
CodeInstruction[] replace = [
|
|
new(OpCodes.Call, AccessTools.Method(typeof(ThingWithComps), nameof(ThingWithComps.GetComp), null, [typeof(EatableComp)])),
|
|
new(OpCodes.Stloc_3),
|
|
new(OpCodes.Ldloc_3),
|
|
new(OpCodes.Brfalse_S, (Label)codeMatcher.InstructionAt(3).operand),
|
|
new(OpCodes.Ldloc_3),
|
|
new(OpCodes.Ldfld, typeof(EatableComp).GetField(nameof(EatableComp.EatableFrom))),
|
|
new(OpCodes.Brfalse_S, (Label)codeMatcher.InstructionAt(3).operand)
|
|
];
|
|
codeMatcher.RemoveInstructions(4);
|
|
codeMatcher.Insert(replace);
|
|
return codeMatcher.Instructions().AsEnumerable();
|
|
}
|
|
|
|
[HarmonyTargetMethod]
|
|
private static MethodBase TargetMethod()
|
|
{
|
|
MethodInfo method = typeof(Toils_Ingest).GetMethods(BindingFlags.NonPublic | BindingFlags.Static)
|
|
.FirstOrDefault(m => m.GetCustomAttribute<CompilerGeneratedAttribute>() != null && Regex.IsMatch(m.Name, $@"^<CarryIngestibleToChewSpot>g__BaseChairValidator\|\d+(_\d+)?"));
|
|
|
|
if (method is not null) return method;
|
|
|
|
IEnumerable<Type> nestedTypes = typeof(Toils_Ingest).GetNestedTypes(BindingFlags.NonPublic).Where(t => t.GetCustomAttribute<CompilerGeneratedAttribute>() != null);
|
|
foreach(Type nested in nestedTypes)
|
|
{
|
|
method = nested.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(m => Regex.IsMatch(m.Name, $@"^<CarryIngestibleToChewSpot>g__BaseChairValidator\|\d+(_\d+)?"));
|
|
if (method is not null) return method;
|
|
}
|
|
return null;
|
|
}
|
|
}
|