Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - bionicjoethehat

#1
Releases / Re: [B18] RandomPlus for B18
June 12, 2019, 02:47:56 PM
Privet! Yes, I've tried but couldn't contact him (I think it's him?) when I had troubles with porting his mod but now that it works perfectly, there is no point in doing that and I have no fixes or changes to include into the original project because my goal was just to provide support for B18. And I think you should fork his project; it would probably be much easier than convincing him to include your changes (What if he refuses to include them?).
#2
Thanks for your suggestion!

The label is now added properly.
#3
Releases / Re: [B18] RandomPlus for B18
June 10, 2019, 07:10:31 AM
Can anyone test it please?
#4
I downgraded a mod from 1.0 to to the cozy B18 which I play :P

https://ludeon.com/forums/index.php?topic=48959.msg460267#msg460267
#5
Releases / [B18] RandomPlus for B18
June 10, 2019, 06:44:38 AM
Description:
This is a B18 port of mastertea's mod that allows users to set minimum specifications for pawn generation when using the randomize button. It will keep rerolling until the minimum specification is meet or the max reroll limit is passed.

Author:
mastertea, bionicjoethehat (porting)

Special thanks:
Mehni

License:
MIT

#6
Yay! The port is now fully working! I've been using it for two days now and I absolutely enjoy having it in B18!
#7
Solved the problem with "IL_003c: stloc.1"
#8
Quoteoh ffs -- I only now realise it. You're downgrading a mod?
Yes, and I've said that both in my messages and in the title which is shown next to each message here.
Quotewell screw the transpiler then -- who cares about compatibility within B18. Just prefix it and return false. Amount of users affected: You.
At least I care and that fact is enough for me to port this mod though I think more that just me will find it interesting, but you're right, not many.

In the end of the day, I am free to spend my time and energy however I want (in a good way) and if something is useful for at least one person or even more people, I don't see why it shouldn't exist.

I appreciate your help, Mehni and I've already included you in the credits section of this mod but I still need to make it work and would appreciate any help from anyone.
#9
This is the link to the playground I"m using.

https://sharplab.io/#v2:C4LglgNgNAJiDUAfAAgJgIwFgBQPkGYACNQgYUIG8dCbCBIAwsAO2EIGMBXAJwAUBDAO7MA3NVriaDIgCMA9nIiEAghAhzBydKgAUWgAyFm/ALYBTAJSVJtWzWQB2QsG6czY7HdoBfGzenEACyEAHJywGAAZgCeAPoAogBuZqx66IbG5lZUnl52Nra+uTT+jCxsAEr8zDByJmAAXmYAksy8EPzsZjrlhAAOQszZBbQMTgPCHnmERbalsgpKpAAWZuwA1gLCzQDOAMr8ETuRYGYwOsPFdmPOru4jNLMSV3R93GCJh2ZBhFU1dY0zKQeFtmBccHQ6DlIXQooQdABCYDLMA7AB0qnUmm0OgARH9avUmqDcRYLBDIdCYY4PDCijDatZsDCaMjUWiuHxBoQALzOFHogkApqtdqdb46Nnozmgiy0yEzQiCFEQCVIgVolZrTaDXYHI4nM4XOUUuhStFhCIxBLJVL46qEwEkk3MuhPEovNCoJnTIpFHAAegAVBS3h8vj8hUSgSDBuDXVTYZF4QiACqcYBybhaDFqDRaXT2/7R53k11Q01jeVu03mmXcvl7YD8bgRZgAc1BAFUIhAwMBomio4DRR0upKNfXhC6YenM9n0BbwlE4kkUsA8cPiYNSfKikGA0A==

And this is my current code:
using Harmony;
using RimWorld;
using Verse;
using UnityEngine;
using System.Collections.Generic;
using System.Reflection.Emit;
using System;
using System.Reflection;

namespace RandomPlus
{
[HarmonyPatch (typeof(Page_ConfigureStartingPawns), "RandomizeCurPawn")]
class Patch_RandomizeMethod
{
static void Prefix ()
{
RandomSettings.ResetRerollCounter ();
}

static IEnumerable<CodeInstruction> Transpiler (IEnumerable<CodeInstruction> instructions)
{
var curPawnFieldInfo = typeof(Page_ConfigureStartingPawns)
.GetField ("curPawn", BindingFlags.NonPublic | BindingFlags.Instance);
var randomizeInPlaceMethodInfo = typeof(StartingPawnUtility)
.GetMethod ("RandomizeInPlace", BindingFlags.Public | BindingFlags.Static);
var checkPawnIsSatisfiedMethodInfo = typeof(RandomSettings)
.GetMethod ("CheckPawnIsSatisfied", BindingFlags.Public | BindingFlags.Static);

var codes = new List<CodeInstruction> (instructions);

var appropriatePlace = 6;

/* Removing the following code in its IL form */

// this.curPawn = StartingPawnUtility.RandomizeInPlace(this.curPawn);

codes.RemoveRange (appropriatePlace, 5);

/* Adding the following code in its IL form: */

// do {
//   this.curPawn = StartingPawnUtility.RandomizeInPlace (this.curPawn);
// } while (!RandomSettings.CheckPawnIsSatisfiedMethodInfo);

//
// // loop start (head: IL_0016)
// IL_0016: nop
// IL_0017: ldarg.0
// IL_0018: ldarg.0
// IL_0019: ldarg.0
// IL_001a: ldfld int32 C::curPawn
// IL_001f: call instance int32 C::RandomizeInPlace(int32)
// IL_0024: stfld int32 C::curPawn
// IL_0029: nop
// IL_002a: ldarg.0
// IL_002b: call instance bool C::CheckPawnIsSatisfied()
// IL_0030: ldc.i4.0
// IL_0031: ceq
// IL_0033: stloc.1
// // sequence point: hidden
// IL_0034: ldloc.1
// IL_0035: brtrue.s IL_0016
// // end loop

List <CodeInstruction> newCodes = new List<CodeInstruction> {
new CodeInstruction (OpCodes.Nop),
new CodeInstruction (OpCodes.Ldarg_0),
new CodeInstruction (OpCodes.Ldarg_0),
new CodeInstruction (OpCodes.Ldarg_0),
new CodeInstruction (OpCodes.Ldfld, curPawnFieldInfo),
new CodeInstruction (OpCodes.Call, randomizeInPlaceMethodInfo),
new CodeInstruction (OpCodes.Stfld, curPawnFieldInfo),
new CodeInstruction (OpCodes.Nop),
new CodeInstruction (OpCodes.Ldarg_0),
new CodeInstruction (OpCodes.Call, checkPawnIsSatisfiedMethodInfo),
new CodeInstruction (OpCodes.Ldc_I4_0),
new CodeInstruction (OpCodes.Ceq),
new CodeInstruction (OpCodes.Stloc_1),
new CodeInstruction (OpCodes.Ldloc_1),
};

newCodes [0].labels.Add (new Label ());

var nopLabel = newCodes [0].labels [0];

newCodes.Add (new CodeInstruction (OpCodes.Brtrue_S, nopLabel));

codes.InsertRange (appropriatePlace, newCodes);

for (var i = 0; i < codes.Count; i++) {
Log.Message (codes [i].ToString ());
}

return codes;
}
}
}


And the text of the error:
Could not execute post-long-event action. Exception: System.TypeInitializationException: An exception was thrown by the type initializer for RandomPlus.HarmonyPatches ---> System.FormatException: Method RimWorld.Page_ConfigureStartingPawns.RandomizeCurPawn() cannot be patched. Reason: Invalid IL code in (wrapper dynamic-method) RimWorld.Page_ConfigureStartingPawns:RandomizeCurPawn_Patch1 (object): IL_003c: stloc.1   


  at Harmony.PatchFunctions.UpdateWrapper (System.Reflection.MethodBase original, Harmony.PatchInfo patchInfo, System.String instanceID) [0x00000] in <filename unknown>:0
  at Harmony.PatchProcessor.Patch () [0x00000] in <filename unknown>:0
  at Harmony.HarmonyInstance.<PatchAll>b__7_0 (System.Type type) [0x00000] in <filename unknown>:0
  at Harmony.CollectionExtensions.Do[Type] (IEnumerable`1 sequence, System.Action`1 action) [0x00000] in <filename unknown>:0
  at Harmony.HarmonyInstance.PatchAll (System.Reflection.Assembly assembly) [0x00000] in <filename unknown>:0
  at RandomPlus.HarmonyPatches..cctor () [0x00000] in <filename unknown>:0
  --- End of inner exception stack trace ---
  at (wrapper managed-to-native) System.Runtime.CompilerServices.RuntimeHelpers:RunClassConstructor (intptr)
  at System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor (RuntimeTypeHandle type) [0x00000] in <filename unknown>:0
  at Verse.StaticConstructorOnStartupUtility.CallAll () [0x00000] in <filename unknown>:0
  at Verse.PlayDataLoader.<DoPlayLoad>m__2 () [0x00000] in <filename unknown>:0
  at Verse.LongEventHandler.ExecuteToExecuteWhenFinished () [0x00000] in <filename unknown>:0
Verse.Log:Error(String)
Verse.LongEventHandler:ExecuteToExecuteWhenFinished()
Verse.LongEventHandler:UpdateCurrentAsynchronousEvent()
Verse.LongEventHandler:LongEventsUpdate(Boolean&)
Verse.Root:Update()
Verse.Root_Entry:Update()
#10
using Harmony;
using RimWorld;
using Verse;
using UnityEngine;
using System.Collections.Generic;
using System.Reflection.Emit;
using System;
using System.Reflection;

namespace RandomPlus
{
[HarmonyPatch (typeof(Page_ConfigureStartingPawns), "RandomizeCurPawn")]
class Patch_RandomizeMethod
{
static void Prefix ()
{
RandomSettings.ResetRerollCounter ();
}

static IEnumerable<CodeInstruction> Transpiler (IEnumerable<CodeInstruction> instructions)
{
var curPawnFieldInfo = typeof(Page_ConfigureStartingPawns)
.GetField ("curPawn", BindingFlags.NonPublic | BindingFlags.Instance);
var randomizeInPlaceMethodInfo = typeof(StartingPawnUtility)
.GetMethod ("RandomizeInPlace", BindingFlags.Public | BindingFlags.Static);
var checkPawnIsSatisfiedMethodInfo = typeof(RandomSettings)
.GetMethod ("CheckPawnIsSatisfied", BindingFlags.Public | BindingFlags.Static);

var codes = new List<CodeInstruction> (instructions);

var appropriatePlace = 6;

/* Removing the following code in its IL form */

// this.curPawn = StartingPawnUtility.RandomizeInPlace(this.curPawn);

codes.RemoveRange (appropriatePlace, 5);

/* Adding the following code in its IL form: */

// do {
//  this.curPawn = StartingPawnUtility.RandomizeInPlace (this.curPawn);
// } while (!RandomSettings.CheckPawnIsSatisfiedMethodInfo);

List <CodeInstruction> newCodes = new List<CodeInstruction> {
new CodeInstruction (OpCodes.Nop), // I need to give this instruction a label
new CodeInstruction (OpCodes.Ldarg_0),
new CodeInstruction (OpCodes.Ldarg_0),
new CodeInstruction (OpCodes.Call, randomizeInPlaceMethodInfo),
new CodeInstruction (OpCodes.Stfld, curPawnFieldInfo),
new CodeInstruction (OpCodes.Nop),
new CodeInstruction (OpCodes.Ldarg_0),
new CodeInstruction (OpCodes.Call, checkPawnIsSatisfiedMethodInfo),
new CodeInstruction (OpCodes.Ldc_I4_0),
new CodeInstruction (OpCodes.Ceq),
new CodeInstruction (OpCodes.Stloc_0),
new CodeInstruction (OpCodes.Ldloc_0),
};

newCodes [0].labels.Add (new Label ());

var nopLabel = newCodes [0].labels [0];

newCodes.Add (new CodeInstruction (OpCodes.Brfalse_S, nopLabel));

codes.InsertRange (appropriatePlace, newCodes);

// for (var i = 0; i < labels.Count; i++) {
// Log.Message (labels[i].ToString());
// }

// for (var i = 0; i < codes.Count; i++) {
// Log.Message (codes [i].ToString ());
// }

return codes;
}
}
}

Managed to assign a label but there is another error shown:

Could not execute post-long-event action. Exception: System.TypeInitializationException: An exception was thrown by the type initializer for RandomPlus.HarmonyPatches ---> System.FormatException: Method RimWorld.Page_ConfigureStartingPawns.RandomizeCurPawn() cannot be patched. Reason: Invalid IL code in (wrapper dynamic-method) RimWorld.Page_ConfigureStartingPawns:RandomizeCurPawn_Patch1 (object): IL_0036: stloc.0   


  at Harmony.PatchFunctions.UpdateWrapper (System.Reflection.MethodBase original, Harmony.PatchInfo patchInfo, System.String instanceID) [0x00000] in <filename unknown>:0
  at Harmony.PatchProcessor.Patch () [0x00000] in <filename unknown>:0
  at Harmony.HarmonyInstance.<PatchAll>b__7_0 (System.Type type) [0x00000] in <filename unknown>:0
  at Harmony.CollectionExtensions.Do[Type] (IEnumerable`1 sequence, System.Action`1 action) [0x00000] in <filename unknown>:0
  at Harmony.HarmonyInstance.PatchAll (System.Reflection.Assembly assembly) [0x00000] in <filename unknown>:0
  at RandomPlus.HarmonyPatches..cctor () [0x00000] in <filename unknown>:0
  --- End of inner exception stack trace ---
  at (wrapper managed-to-native) System.Runtime.CompilerServices.RuntimeHelpers:RunClassConstructor (intptr)
  at System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor (RuntimeTypeHandle type) [0x00000] in <filename unknown>:0
  at Verse.StaticConstructorOnStartupUtility.CallAll () [0x00000] in <filename unknown>:0
  at Verse.PlayDataLoader.<DoPlayLoad>m__2 () [0x00000] in <filename unknown>:0
  at Verse.LongEventHandler.ExecuteToExecuteWhenFinished () [0x00000] in <filename unknown>:0
Verse.Log:Error(String)
Verse.LongEventHandler:ExecuteToExecuteWhenFinished()
Verse.LongEventHandler:UpdateCurrentAsynchronousEvent()
Verse.LongEventHandler:LongEventsUpdate(Boolean&)
Verse.Root:Update()
Verse.Root_Entry:Update()
#11
So, I need to figure out how to jump to a certain instruction, but how?
#12
Your first code is taken from 1.0 but I am adapting a 1.0 mod for B18.

Here is the code of RandomizeCurPaw in B18:
private void RandomizeCurPawn()
{
if (!TutorSystem.AllowAction("RandomizePawn"))
{
return;
}
this.curPawn = StartingPawnUtility.RandomizeInPlace(this.curPawn);
TutorSystem.Notify_Event("RandomizePawn");
}

As you can see, it doesn't have a loop.

And here is what I currently have:
using Harmony;
using RimWorld;
using Verse;
using UnityEngine;
using System.Collections.Generic;
using System.Reflection.Emit;
using System;
using System.Reflection;

namespace RandomPlus
{
[HarmonyPatch (typeof(Page_ConfigureStartingPawns), "RandomizeCurPawn")]
class Patch_RandomizeMethod
{
static void Prefix ()
{
RandomSettings.ResetRerollCounter ();
}

static IEnumerable<CodeInstruction> Transpiler (IEnumerable<CodeInstruction> instructions)
{
var curPawnFieldInfo = typeof(Page_ConfigureStartingPawns)
.GetField ("curPawn", BindingFlags.NonPublic | BindingFlags.Instance);
var randomizeInPlaceMethodInfo = typeof(StartingPawnUtility)
.GetMethod ("RandomizeInPlace", BindingFlags.Public | BindingFlags.Static);
var checkPawnIsSatisfiedMethodInfo = typeof(RandomSettings)
.GetMethod ("CheckPawnIsSatisfied", BindingFlags.Public | BindingFlags.Static);

var codes = new List<CodeInstruction> (instructions);

var appropriatePlace = 5;

/* Removing following code in its IL form */

// this.curPawn = StartingPawnUtility.RandomizeInPlace(this.curPawn);

codes.RemoveRange (appropriatePlace, 5);

/* Adding following code in its IL form: */

// do {
//  this.curPawn = StartingPawnUtility.RandomizeInPlace (this.curPawn);
  // } while (!RandomSettings.CheckPawnIsSatisfiedMethodInfo);

List <CodeInstruction> newCodes = new List<CodeInstruction> {
new CodeInstruction (OpCodes.Nop), // I need to give this instruction a label
new CodeInstruction (OpCodes.Ldarg_0),
new CodeInstruction (OpCodes.Ldarg_0),
new CodeInstruction (OpCodes.Call, randomizeInPlaceMethodInfo),
new CodeInstruction (OpCodes.Stfld, curPawnFieldInfo),
new CodeInstruction (OpCodes.Nop),
new CodeInstruction (OpCodes.Ldarg_0),
new CodeInstruction (OpCodes.Call, checkPawnIsSatisfiedMethodInfo),
new CodeInstruction (OpCodes.Ldc_I4_0),
new CodeInstruction (OpCodes.Ceq),
new CodeInstruction (OpCodes.Stloc_0),
new CodeInstruction (OpCodes.Ldloc_0),
new CodeInstruction (OpCodes.Brfalse_S /* and use it here */),
};

codes.InsertRange (appropriatePlace, newCodes);

return codes;
}
}
}
#13
Found an online C# -> IL converter and here is what it showed:

        // loop start (head: IL_0001)
            IL_0001: nop
            IL_0002: ldarg.0
            IL_0003: ldarg.0
            IL_0004: call instance int32 C::B()
            IL_0009: stfld int32 C::curPawn
            IL_000e: nop
            IL_000f: ldarg.0
            IL_0010: call instance bool C::A()
            IL_0015: ldc.i4.0
            IL_0016: ceq
            IL_0018: stloc.0
            // sequence point: hidden
            IL_0019: ldloc.0
            IL_001a: brtrue.s IL_0001


The last thing left to do is to assign a label to an instruction IL_0001 so it can be used by IL_001a but I can't find how you can do it online.
#14
1.0 does have a loop indeed, but I'm porting a mod from 1.0 to B18 which doesn't and I have already written an envision in my previous post but to translate it to IL, I would either need to write something in C# use a decompiler which for some reason I can't install right now (but soon will) or to write IL code from scratch which I can't do. :P

So, would you please use your decompiler and post the instructions for:
do
{
this.curPawn = StartingPawnUtility.RandomizeInPlace(this.curPawn);
}
while (!RandomSettings.CheckPawnIsSatisfiedMethodInfo);

?

Would you also answer my question regarding referring to other instructions in IL? Like in:
Brfalse ???
What would you write instead of the question marks?
#15
Please, correct me if I'm wrong but it should be something like this, right?
ldarg.0

IL_0019: ldfld class Verse.Pawn RimWorld.Page_ConfigureStartingPawns::curPawn
IL_001e: call class Verse.Pawn Verse.StartingPawnUtility::RandomizeInPlace(class Verse.Pawn)
IL_0023: stfld class Verse.Pawn RimWorld.Page_ConfigureStartingPawns::curPawn

callvirt / CheckPawnIsSatisfiedMethodInfo
Brfalse => goto first line

I don't know how to refer to another instruction in Brfalse and I also don't think the rest of the code would work. :D How do I write it in proper IL?