Help with Transpiler

Started by Rxzlion, September 10, 2020, 07:54:38 AM

Previous topic - Next topic

Rxzlion

I'm trying to changed the beauty of Hewn and Rough Stone.

I have found the corresponding class which is TerrainDefGenerator_Stone.

So I built my code:

       
        [HarmonyPatch(typeof(TerrainDefGenerator_Stone))]
        [HarmonyPatch("ImpliedTerrainDefs")]
        public static class TerrainDefGenerator_Stone_Patch
        {
            static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
            {
                int Index = -1;

                var codes = instructions.ToList();
                for (int i = 0; i < codes.Count; i++)
                {
                    Log.Message("First: " + codes[i].opcode);

                    if (codes[i].opcode == OpCodes.Ldsfld)
                    {
                        Log.Message("Second: " + codes[i].opcode);

                        var strOperand = codes[i].operand as String;
                        if (strOperand == "class RimWorld.StatDef RimWorld.StatDefOf::Beauty")
                        {
                            Log.Message("Detected: " + i);
                            Index = i;
                            break;
                        }
                    }


                }

                if (Index > -1)
                {
                    codes.RemoveAt(Index);
                    codes.Insert(Index, new CodeInstruction(OpCodes.Ldc_R4, -2));
                }
                return codes.AsEnumerable();
            }             
        }   


Harmony is working I verified that.
The code itself reaches the first Log.Message and I get 3 opcodes and that's it:


I tracked those in the IL code:


It seems I'm missing something to jump to another location in the code.
What am I missing here?

RawCode

implied defs are loaded into database just like normal defs, you do not need to inject custom code in order to change them.

actually this can be done with pure XML all you need is to know true name of implied def, then you can create def with said name and set whatever values you want manually.

code injection is very very last resort due to potential stability issues and somewhat unpredictable side effects when multiple mods try to inject same method.



Rxzlion

#2
Quote from: RawCode on September 10, 2020, 08:38:54 AM
implied defs are loaded into database just like normal defs, you do not need to inject custom code in order to change them.

actually this can be done with pure XML all you need is to know true name of implied def, then you can create def with said name and set whatever values you want manually.

code injection is very very last resort due to potential stability issues and somewhat unpredictable side effects when multiple mods try to inject same method.

I tried using XML like this:


<Operation Class="PatchOperationReplace">
<xpath>/Defs/TerrainDef[defName="Granite_Rough"]/statBases</xpath>
<value>
<statBases>
<Beauty>-2</Beauty>
</statBases>
</value>
</Operation>


but it always gave me this error:



I'm guessing my xpath is wrong but I have no idea how to find the correct one.
Also I looked at tutorials and they said that XML doesn't work for some type of definitions so I thought this is one of those.

If you can give me the right direction it will be real helpful.

Edit:
Wait should I just create my own def and it will overwrite the implied def instead of using xpath?

LWM

Another way to do it is to wait unto all defs are loaded ([StaticConstructorOnStartup]) and then in the static constructor go rifling through the DefsDatabase to change the settings you want.

I think the reason you're getting a confusing set of IL code is that it's an IEnumerable - those are always a bit weird to work with in transpilers.  To actually transpile it, you would have to find the anonymous function that does the actual work, grab its name, and transpile THAT.

But ...rifling through the defs database might be easier  ;D

--LWM

PS I can point to examples in my code that do that if you would find that useful.