How to modify a static class from Verse?

Started by lost_RD, May 11, 2016, 05:47:09 AM

Previous topic - Next topic

lost_RD

#15
Quote from: skullywag on May 12, 2016, 01:20:40 PM
Are they clearing the stone then doing nothing?

The blueprints can exist on the stone but the pawns don't acknowledge the existence of the blueprints. I can't right click the blueprints either.

I'm looking into Verse.AI.ReservationUtility for its CanReserve and CanReserveAndReach methods.

Edit: the blueprint does not become a frame when it's placed on stone. I don't yet know the relationship between blueprints and frames but I suspect it is the key.

1000101

Quote from: lost_RDYou're right, I'm finding that most things are self-explanatory enough. I'm a problem solver by nature so I'll work most things out on my own.

Good to hear, I always prefer to show someone the basics and point them in the direction they need.

Quote from: lost_RDThe OP update didn't have any errors, everything is working as intended, more or less.

My mistake, I continued reading into the OP from edited portion.
(2*b)||!(2*b) - That is the question.
There are 10 kinds of people in this world - those that understand binary and those that don't.

Powered By

lost_RD

#17
I tracked the stack of two walls, one on stone and one on open ground. The stack was the same except for one extra call. The following is a reversed version of what came up in the Debug Log because I couldn't figure out a way to copy it. No, there's no log file in my RimWorld folder and I wonder if it's something to do with write permissions. I'll check later.


Verse.RootGameObject:Update()
Verse.RootMap:RootUpdate()
Verse.Map:MapUpdate()
Verse.TickManager:TickManagerUpdate()
Verse.TickManager:DoSingleTick()
Verse.Ticklist:TickManagerUpdate()
Verse.Pawn:TickManagerUpdate()
Verse.AI.Pawn_JobTracker:JobTrackerTick()
Verse.AI.Pawn_JobTracker:EndCurrentJob()
Verse.AI.Pawn_JobTracker:TryFindAndStartJob()
Verse.AI.Pawn_JobTracker:DetermineNextJob()
Verse.AI.ThinkNode_Priority:TryIssueJobPackage()
RimWorld.ThinkNode_Conditional:TryIssueJobPackage()
Verse.AI.ThinkNode_Priority:TryIssueJobPackage()
Verse.AI.ThinkNode_PrioritySorter:TryIssueJobPackage()
Verse.AI.ThinkNode_JobGiver:TryIssueJobPackage()
RimWorld.JobGiver_Work:TryGiveTerminalJob()
Verse.GenClosest:ClosestThingReachable()
Verse.GenClosest:RegionwiseBFSWorker()
Verse.RegionTraverser:BreadthFirstTraverse()
Verse.BFSWorker:BreadthFirstTraverseWork()
Verse.<RegionWiseBFSWorker>c__AnonStorey3CB:<>m__729()
RimWorld.<TryGiveTerminalJob>C__AnonStorey1F9:<>m__105()
RimWorld.WorkGiver_Scanner:HasJobOnThing()
RimWorld.WorkGiver_ConstructDeliverResourcesToBlueprints:JobOnThing() If wall is not on stone, skip next call and _CanConstruct returns true
RimWorld.WorkGiver_ConstructDeliverResources:ResourceDeliverJobFor() If wall is on stone, this call occurs and _CanConstruct returns false
BlueprintsEverywhere.Detour._GenConstruct:_CanConstruct()


Things get a bit murky here because in the code it looks like JobOnThing calls _CanConstruct and if _CanConstruct returns false, JobOnThing returns null, else it calls ResourceDeliverJobFor which returns a job but in the stack trace it looks like the opposite is happening?

Either way, I deconstructed CanConstruct and now know it fails when wall is designated on stone because blueprint.FirstBlockingThing(p, false) == null returns false in that case.

FirstBlockingThing contains a call to GenSpawn.BlocksFramePlacement and I'm already detouring GenSpawn. I'm going to place some log messages in all of the cases to see which is returning.

Edit: In BlocksFramePlacement(Blueprint blue, Thing t), t.def.Fillage is returning None because t has a fillPercent of 0. If t had a fillPercent of anything greater than 0, t.def.Fillage would return Partial and t.def.Fillage >= FillCategory.Partial would return true. For now, I'm replacing t.def.Fillage >= FillCategory.Partial with true to see if it works.

Edit 2: Wait, maybe BlocksFramePlacement is supposed to return false...

Edit 3: Yep... FailFish

lost_RD

#18
Another question about detours: it's been easy to detour public methods in public classes but I haven't had the same success with public overrides or private methods. Why is that? What must I do to detour a public override or a private method?

I'm trying to modify public class RimWorld.WorkGiver_ConstructDeliverResourcesToBlueprints. First I tried to detour public override Job JobOnThing but that wasn't working. Next I tried to detour private Job DeconstructExistingEdificeJob which is called in JobOnThing, again, no dice.

Error for private Job DeconstructExistingEdificeJob:

CCL :: Injection Controller :: Initialization :: Errors during injection
    Error :: Blueprints Everywhere :: Detours :: Source MethodInfo is null


Here's an example of two detours, the first works and the latter is the one that is currently erroring:

            // Detour Verse.GenSpawn.BlocksFramePlacement
            MethodInfo Verse_GenSpawn_BlocksFramePlacement = typeof( GenSpawn ).GetMethod( "BlocksFramePlacement", BindingFlags.Static | BindingFlags.Public );
            MethodInfo BE_GenSpawn_BlocksFramePlacement = typeof( Detour._GenSpawn ).GetMethod( "_BlocksFramePlacement", BindingFlags.Static | BindingFlags.NonPublic );
            if( !Detours.TryDetourFromTo( Verse_GenSpawn_BlocksFramePlacement, BE_GenSpawn_BlocksFramePlacement ) )
{
                return false;
}
           

            // Detour RimWorld.WorkGiver_ConstructDeliverResourcesToBlueprints
            MethodInfo RimWorld_WorkGiver_ConstructDeliverResourcesToBlueprints_DeconstructExistingEdificeJob = typeof( WorkGiver_ConstructDeliverResourcesToBlueprints ).GetMethod( "DeconstructExistingEdificeJob", BindingFlags.Static | BindingFlags.Public );
            MethodInfo BE_WorkGiver_ConstructDeliverResourcesToBlueprints_DeconstructExistingEdificeJob = typeof( Detour._WorkGiver_ConstructDeliverResourcesToBlueprints ).GetMethod( "_DeconstructExistingEdificeJob", BindingFlags.Static | BindingFlags.NonPublic );
            if( !Detours.TryDetourFromTo( RimWorld_WorkGiver_ConstructDeliverResourcesToBlueprints_DeconstructExistingEdificeJob, BE_WorkGiver_ConstructDeliverResourcesToBlueprints_DeconstructExistingEdificeJob ) )
{
                return false;
}
           


And here are the declarations of aforementioned methods and their classes:

namespace BlueprintsEverywhere.Detour
{
    internal static class _GenSpawn
    {
        internal static bool _BlocksFramePlacement(Blueprint blue, Thing t)
{


namespace BlueprintsEverywhere.Detour
{
internal class _WorkGiver_ConstructDeliverResourcesToBlueprints : WorkGiver_ConstructDeliverResources
{
public Job _DeconstructExistingEdificeJob(Pawn pawn, Blueprint blue)
{


When I try to detour public override Job _JobOnThing, the compiler spits out this error:

'BlueprintsEverywhere.Detour._WorkGiver_ConstructDeliverResourcesToBlueprints._JobOnThing(Verse.Pawn, Verse.Thing)': no suitable method found to override (CS0115)

Fixing this error would probably be the best course of action but I'm too new to OOP and C# to know the solution. I will google it though seeing as there's an error code.

Edit: the problem here is that _JobOnThing won't override JobOnThing because the names are different but that seems to be the standard convention for detouring with CCL so I still don't know how to resolve this situation. Do I just put in an override of my own and hope that it overrides the vanilla override? How would that differ from the detour concept?

Fluffy (l2032)

You're telling C# to look for a static method (BindingFlags.Static), but the method you want to detour is an instance method (note the absence of a static keyword on the method declaration). I haven't checked the rest of your code, but if you use BindingFlags.Instance instead, it'll probably work.

CCL is telling you this as well, the source methodInfo is null. Names are irrelevant, they're not meaningful for the compiler - it just helps to keep them similar for human comprehension.

RawCode

use this magical value as bindingflags
(BindingFlags)60

basically you should look at logic of tree\grass removal from objects and implement same routine for stone walls.

this will take more then one hook to implement.

Fluffy (l2032)

Quote from: RawCode on May 13, 2016, 05:32:06 AM
use this magical value as bindingflags
(BindingFlags)60

Yeah don't do that. Magic numbers are bad, m'kay.

RawCode


1000101

Never use a literal constant when a named constant exists for that purpose.

To help with the actual issue at hand - As they both correctly pointed out, it's your BindingFlags.
(2*b)||!(2*b) - That is the question.
There are 10 kinds of people in this world - those that understand binary and those that don't.

Powered By

RawCode

to avoid issues later on, always perform nullchecks and debug output literally after every line.


lost_RD

#25
Quote from: RawCode on May 14, 2016, 12:17:04 AM
to avoid issues later on, always perform nullchecks and debug output literally after every line.

I've noticed that Tynan does a lot of null checks and I'm logging messages all over the place to see what's passing in and out of functions so I'd call that mission accomplished.  ;)

Also, thanks all, BindingFlags are fixed and onward I go.