Completely Lost in Harmony Patches

Started by cory3573, December 02, 2021, 08:07:48 PM

Previous topic - Next topic

cory3573

I can't seem to figure out how to use harmony for nearly anything...
My code is here:

using HarmonyLib;
using RimWorld;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Verse;

namespace FastDecompose
{
    [StaticConstructorOnStartup]
    class HarmonyPatches
    {
        static HarmonyPatches()
        {
            var harmony = new Harmony("rimworld.wazzcarp.fastdecompose");
            Log.Message($"!!!FastDecompose!!! Rotten corpse patch attempt.");
            Harmony.DEBUG = true;
            harmony.PatchAll(Assembly.GetExecutingAssembly());
        }
    }


    [HarmonyPatch(typeof(CompProperties_Rottable), "rotDamagePerDay", MethodType.Setter)]
    static class RotTimePatch
    {
        static void Postfix(ref float __result)
        {
            __result *= 2;
            Log.Message($"!FastDecompose! Rotten corpse decompose damage multiplier is now 2.");
        }
    }

    [HarmonyPatch(typeof(CompProperties_Rottable), "dessicatedDamagePerDay", MethodType.Setter)]
    static class DessicatedTimePatch
    {
        static void Postfix(ref float __result)
        {
            __result = 160;
            Log.Message($"!FastDecompose! Dessicated corpse decompose damage multiplier is now 4.");
        }
    }
}


I keep getting all kinds of errors from better loading no matter what I try to change, anyone who knows how harmony works and can tell me what I'm doing wrong would be awesome.
The most recent error is

[BetterLoading] Exception occurred processing mod finalize events! Details: System.TypeInitializationException: The type initializer for 'FastDecompose.HarmonyPatches' threw an exception. ---> HarmonyLib.HarmonyException: Patching exception in method null ---> System.NullReferenceException: Object reference not set to an instance of an object
  at HarmonyLib.PatchTools.GetOriginalMethod (HarmonyLib.HarmonyMethod attr) [0x000b3] in <0dff4ff9ce7a4af99336d09823a08cb2>:0
  at HarmonyLib.PatchClassProcessor.PatchWithAttributes (System.Reflection.MethodBase& lastOriginal) [0x0001c] in <0dff4ff9ce7a4af99336d09823a08cb2>:0
  at HarmonyLib.PatchClassProcessor.Patch () [0x00057] in <0dff4ff9ce7a4af99336d09823a08cb2>:0
   --- End of inner exception stack trace ---
  at HarmonyLib.PatchClassProcessor.ReportException (System.Exception exception, System.Reflection.MethodBase original) [0x00127] in <0dff4ff9ce7a4af99336d09823a08cb2>:0
  at HarmonyLib.PatchClassProcessor.Patch () [0x00082] in <0dff4ff9ce7a4af99336d09823a08cb2>:0
  at HarmonyLib.Harmony.<PatchAll>b__10_0 (System.Type type) [0x00007] in <0dff4ff9ce7a4af99336d09823a08cb2>:0
  at HarmonyLib.CollectionExtensions.Do[T] (System.Collections.Generic.IEnumerable`1[T] sequence, System.Action`1[T] action) [0x00014] in <0dff4ff9ce7a4af99336d09823a08cb2>:0
  at HarmonyLib.Harmony.PatchAll (System.Reflection.Assembly assembly) [0x00006] in <0dff4ff9ce7a4af99336d09823a08cb2>:0
  at FastDecompose.HarmonyPatches..cctor () [0x00020] in <3c4df6f36b2244be9fcd2c0fda64dab3>:0
   --- End of inner exception stack trace ---
  at (wrapper managed-to-native) System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(intptr)
  at (wrapper dynamic-method) System.Runtime.CompilerServices.RuntimeHelpers.System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor_Patch1(System.RuntimeTypeHandle)
  at BetterLoading.Stage.InitialLoad.StageRunStaticCctors+<StaticConstructAll>d__16.MoveNext () [0x00074] in <0db29cd9154f4d018b9bc84feb9aff6b>:0
Verse.Log:Verse.Log.Error_Patch2(String, Boolean)
BetterLoading.Stage.InitialLoad.<StaticConstructAll>d__16:MoveNext()
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)

cory35733

Why did I get banned for trying to edit the above post to have the code actually inside code tags?

Canute

Noone would ban you for that.
Must be another reason or a mistake.

cory3573

I found out I can login on my phone but my computer says I'm banned very strange I'll take a closer look when I get home

cory3573

Super strange behavior. Clearing the cookies on my computer only allows me to browse the forum until I attempt to interact with this post then it says I'm banned again. Using incognito mode works fine so far...
Correction while posting: incognito works long enough to read the page I selected, no posting. Edit Again: can post for about a minute then it says I'm banned.

In terms of code I'm beyond lost, I've been copy pasting for days and not a thing works for me I don't understand. I'm attempting to make corpses rot faster by postfixing their damage since UltimateRaids is sending 500+ pawns after me and I can't clean up after the thousands of corpses littered across my map. It lags my game severely when a large mass is in frame for some reason so I'd rather they rot faster and go away instead of using dev commands to fix my TPS every raid.
Current code is this:

using HarmonyLib;
using RimWorld;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Verse;

namespace FastDecompose
{
    [StaticConstructorOnStartup]
    class HarmonyPatches
    {
        static HarmonyPatches()
        {
            var harmony = new Harmony("rimworld.wazzcarp.fastdecompose");
            //Log.Message($"!!!FastDecompose!!! Rotten corpse patch attempt.");
            Harmony.DEBUG = true;
            harmony.PatchAll();
        }
    }


    [HarmonyPatch(typeof(CompProperties_Rottable))]
    [HarmonyPatch("rotDamagePerDay", MethodType.Getter)]
    public class RotTimePatch
    {
        [HarmonyPostfix]
        static void PatchRotDamage(ref float __result)
        {
            float old;
            old = __result;
            __result *= 2f;
            Log.Message($"!FastDecompose! rotDamagePerDay (" + old + ") is now (" + __result + ").");
        }
    }

    [HarmonyPatch(typeof(CompProperties_Rottable))]
    [HarmonyPatch("dessicatedDamagePerDay", MethodType.Getter)]
    static class DessicatedTimePatch
    {
        [HarmonyPostfix]
        static void PatchDesDamage(ref float __result)
        {
            float old2;
            old2 = __result;
            __result += 160f;
            Log.Message($"!FastDecompose! dessicatedDamagePerDay (" + old2 + ") is now (" + __result + ").");
        }
    }
}

Harmony tells me it is unable to find the property.

AccessTools.DeclaredProperty: Could not find property for type RimWorld.CompProperties_Rottable and name rotDamagePerDay
### Exception from user "rimworld.wazzcarp.fastdecompose", Harmony v2.0.4.0
### Original: NULL
### Patch class: FastDecompose.RotTimePatch
### System.NullReferenceException: Object reference not set to an instance of an object
###   at HarmonyLib.PatchTools.GetOriginalMethod (HarmonyLib.HarmonyMethod attr) [0x00087] in <0dff4ff9ce7a4af99336d09823a08cb2>:0
###   at HarmonyLib.PatchClassProcessor.PatchWithAttributes (System.Reflection.MethodBase& lastOriginal) [0x0001c] in <0dff4ff9ce7a4af99336d09823a08cb2>:0
###   at HarmonyLib.PatchClassProcessor.Patch () [0x00057] in <0dff4ff9ce7a4af99336d09823a08cb2>:0

Yet here it is in ILSpy

// RimWorld.CompProperties_Rottable
using System.Collections.Generic;
using RimWorld;
using UnityEngine;
using Verse;

public class CompProperties_Rottable : CompProperties
{
public float daysToRotStart = 2f;

public bool rotDestroys;

---->public float rotDamagePerDay = 40f;<----

public float daysToDessicated = 999f;

---->public float dessicatedDamagePerDay;<----
. . .more code

If any glorious soul knows the answer as to why I see harmony as ignoring this property, I would greatly appreciate it.

Ramsis

#5
Hi Cory what is the "ban" message you're seeing exactly? I'm pretty much the only active forum mod at this point and I haven't handed out a ban in about a year, lol I just delete bot accounts and slap people.

Edit: found the issue, your account got tagged for some reason but I removed it. Will look into why it happened but for now you should be fine. I'm so sorry that happened but know it wasn't because you did anything wrong it seems just this dang old forum script that's painfully... innefficient and buggy.
Ugh... I have SO MANY MESSES TO CLEAN UP. Oh also I slap people around who work on mods <3

"Back off man, I'm a scientist."
- Egon Stetmann


Awoo~

cory3573

The message is below. It appears to still be affecting me until I cleared my cookies, hopefully it stays good.

An Error Has Occurred!
Sorry cory3573, you are banned from using this forum!
Goodbye.
This ban is not set to expire.

cory3573

Still getting the same error but I was trying it out with a transpiler this time. As far as I can copy paste, this is correct but I still get the exact same "null type of" error from harmony. Why must this be so convoluted :/

using HarmonyLib;
using RimWorld;
using System.Reflection;
using Verse;


    [StaticConstructorOnStartup]
    class HarmonyPatches
    {
        static HarmonyPatches()
        {
            var harmony = new Harmony("rimworld.wazzcarp.fastdecompose");
            //Log.Message($"!!!FastDecompose!!! Rotten corpse patch attempt.");
            Harmony.DEBUG = true;
            harmony.PatchAll();
        }
    }

    [HarmonyPatch(typeof(CompProperties_Rottable))]
    //Dude just target this shit wtf.
    internal class RotTimePatch
    {
        public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
        {
            FieldInfo rotDamagePerDay = AccessTools.Field(typeof(CompProperties_Rottable), "rotDamagePerDay");
            FieldInfo dessicatedDamagePerDay = AccessTools.Field(typeof(CompProperties_Rottable), "dessicatedDamagePerDay");
            foreach(CodeInstruction instr in instructions)
            {
                if (CodeInstructionExtensions.StoresField(instr, rotDamagePerDay))
                {
                    float flVal = (float)Convert.ChangeType(rotDamagePerDay.GetRawConstantValue(), typeof(float));
                    flVal += 160f;
                    rotDamagePerDay.SetValue(rotDamagePerDay, Convert.ChangeType(flVal, typeof(object)));
                    Log.Message($"!FastDecompose! rotDamagePerDay (" + (flVal-160f) + ") is now (" + flVal + ").");
                    yield return instr;
                }
                else if (CodeInstructionExtensions.StoresField(instr, dessicatedDamagePerDay))
                {
                    float flVal = (float)Convert.ChangeType(dessicatedDamagePerDay.GetRawConstantValue(), typeof(float));
                    flVal *= 2f;
                    rotDamagePerDay.SetValue(dessicatedDamagePerDay, Convert.ChangeType(flVal, typeof(object)));
                    Log.Message($"!FastDecompose! dessicatedDamagePerDay (" + (flVal * 2f) + ") is now (" + flVal + ").");
                    yield return instr;
                }
                else
                {
                    yield return instr;
                }
            }
        }   
    }

The error in Harmony logs.

### Exception from user "rimworld.wazzcarp.fastdecompose", Harmony v2.0.4.0
### Original: NULL
### Patch class: RotTimePatch
### System.ArgumentException: Undefined target method for patch method static System.Collections.Generic.IEnumerable`1<HarmonyLib.CodeInstruction> RotTimePatch::Transpiler(System.Collections.Generic.IEnumerable`1<HarmonyLib.CodeInstruction> instructions)
###   at HarmonyLib.PatchClassProcessor.PatchWithAttributes (System.Reflection.MethodBase& lastOriginal) [0x00047] in <0dff4ff9ce7a4af99336d09823a08cb2>:0
###   at HarmonyLib.PatchClassProcessor.Patch () [0x00057] in <0dff4ff9ce7a4af99336d09823a08cb2>:0

cory3573

Figured out I need to to change my patch starter if I'm targeting the base constructor from this post https://github.com/pardeike/Harmony/issues/116

Before    [HarmonyPatch(typeof(CompProperties_Rottable))]

After      [HarmonyPatch(typeof(CompProperties_Rottable), MethodType.Constructor)]

Now I've got the mod working but I'm still changing my targets around until I get better info tab(and rot speed) behavior, the corpses are rotting very(way too) quickly though!