JobDriver/JobGiver: Could not load type 'System.Action' from assembly 'toilets'

Started by rubenwardy, July 19, 2016, 10:16:08 PM

Previous topic - Next topic

rubenwardy

First question (now answered)

See other question in post below

Hello all! This is my first post on the forums. I've been playing this game for a year or so, but only recently felt the need to make a mod.

I've got a bladder need set up which works well. I'm trying to make a job driver which triggers after a while at being at bladder=0

Using the decompiler (MonoDevelop), I've added a jobdriver_accident class which is based on the vomit driver


using System;
using RimWorld;
using System.Collections.Generic;
using System.Diagnostics;
using Verse;
using Verse.AI;

namespace toilets
{
public class JobDriver_Accident : JobDriver
{
//
// Fields
//
private int ticksLeft;

//
// Methods
//
public override void ExposeData ()
{
base.ExposeData ();
Scribe_Values.LookValue<int> (ref this.ticksLeft, "ticksLeft", 0, false);
}


protected override IEnumerable<Toil> MakeNewToils ()
{
JobDriver_Accident.<MakeNewToils>c__Iterator3B <MakeNewToils>c__Iterator3B = new JobDriver_Accident.<MakeNewToils>c__Iterator3B ();
<MakeNewToils>c__Iterator3B.<>f__this = this;
JobDriver_Accident.<MakeNewToils>c__Iterator3B expr_0E = <MakeNewToils>c__Iterator3B;
expr_0E.$PC = -2;
return expr_0E;
}
}
}


I don't understand what that syntax in  IEnumerable<Toil> MakeNewToils () is, it looks like decompiler rubbish from the yield statements. I've tried googling it, but the only result is a stack traceback. I can't see a toil which spawns a thingdef.

<?xml version="1.0" encoding="utf-8" ?>
<ThingDefs>
<ThingDef ParentName="BaseFilth">
<defName>FilthFeces</defName>
<label>feces</label>
<statBases>
<Beauty>-40</Beauty>
<Cleanliness>-15</Cleanliness>
</statBases>
<graphicData>
<texPath>Things/Filth/Spatter</texPath>
<color>(201, 204, 143, 180)</color>
</graphicData>
<filth>
<rainWashes>true</rainWashes>
<cleaningWorkToReduceThickness>70</cleaningWorkToReduceThickness>
<canFilthAttach>true</canFilthAttach>
</filth>
</ThingDef>
</ThingDefs>


MonoDevelop doesn't support .NET 3.5, so I've had to use 4.0. My Need_Bladder.cs and ThoughtWorker_Bladder.cs work fine.

I've tried googling for spawning thingdef/filth in job drivers, and for copies of jobdriver_vomit which are unedited.

So my question is, how would I create a job like vomit which spawns that thing def? And how would I trigger it on low bladder after a while?
Computer science student, game developer, and open source contributor. Twitter

1000101

JobDrivers are always "fun" to write and the enumerable returns are always garbage when viewed in a decompiler.

My Prisoners & Slaves mod has a number of WorkGivers and JobDrivers and the source (WIP) can be found in my ESM repo (temporary home) which will probably provide a better example than decompiled sources (only because it's the original source).

Also, my Smooth Wall mod spawns a new thing (a wall, duh?) which may help you with that part.

Feel free to take a look at my source and how I do it.

https://github.com/ForsakenShell/Es-Small-Mods
(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

rubenwardy

Quote from: 1000101 on July 19, 2016, 10:29:43 PM
Also, my Smooth Wall mod spawns a new thing (a wall, duh?) which may help you with that part.

Thank you for your help! Can you see any problems with this? If all is ok, I just need to implement my JobGiver now.

protected override IEnumerable<Toil> MakeNewToils ()
{
Toil toil = new Toil {
defaultCompleteMode = ToilCompleteMode.Never,
initAction = new Action(() =>
{
ticksLeft = 100;
}),
tickAction = new Action(() =>
{
ticksLeft--;
})
};

toil.endConditions.Add((Func<JobCondition>)(() => {
return (ticksLeft > 0) ? JobCondition.Ongoing : JobCondition.Succeeded;
}));

toil.AddFinishAction (new Action (() => {
ThingDef fecesThingDef = DefDatabase<ThingDef>.GetNamed ("FilthFeces", true);
var thing = ThingMaker.MakeThing(fecesThingDef);
if (thing != null) {
var splat = GenSpawn.Spawn(thing, TargetA.Cell);
if (splat != null) {
splat.SetFaction( Faction.OfPlayer );
}
}
}));

yield return toil;
}
Computer science student, game developer, and open source contributor. Twitter

RawCode

Enumetation, yeld, method references, iteration, lambda, events, delegates and few other things are constructed into "stuff", that is not decompiled correctly by popular decompilers.

You should enable "compiler generated code" to see generated stuff, but, under normal conditions, you should switch to rawIL for such methods.

1000101

That looks ok, but until you compile it and execute it you won't know for sure if there are any problems.
(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

rubenwardy

Second Question / Problem

I'm unsure of the etiquette on this forum, so I'll post a second follow up question here

I'm now getting this error:

Exception in SetupToil(pawn=Kimmy, job=Accident): System.TypeLoadException: Could not load type 'System.Action' from assembly 'toilets'.
    at Verse.AI.JobDriver.SetupToils()
Verse.Log:Error(string)
Verse.AI.JobDriver:SetupToil()
Verse.AI.Pawn_JobTracker:StatJob(Job, JobCondition, ThinkNode, Boolean, Boolean, ThinkTreeDef)
Verse.AI.Pawn_JobTracker:TryFindAndStartJob()
Verse.AI.Pawn_JobTracter:EndCurrentJob(JobCondition)
...


My JobDriver is as above. This is my job giver:

using System;
using RimWorld;
using Verse;
using Verse.AI;

namespace toilets
{
public class JobGiver_Accident : ThinkNode_JobGiver
{
protected override Job TryGiveJob(Pawn pawn)
{
return new Job(DefDatabase<JobDef>.GetNamed("Accident"), null);
}
}
}


My job def:

<?xml version="1.0" encoding="utf-8" ?>
<JobDefs>
<JobDef>
<defName>Accident</defName>
<driverClass>toilets.JobDriver_Accident</driverClass>
<playerInterruptible>false</playerInterruptible>
<casualInterruptible>false</casualInterruptible>
<reportString>having an accident.</reportString>
<suspendable>false</suspendable>
</JobDef>
</JobDefs>


and my think tree defs:

<?xml version="1.0" encoding="utf-8" ?>
<ThinkTrees>
<ThinkTreeDef>
<defName>HaveAccident</defName>
<insertTag>Humanlike_PostDuty</insertTag>
<insertPriority>100</insertPriority>
<thinkRoot Class="ThinkNode_ConditionalNeedPercentageAbove">
<need>Bladder</need>
<threshold>0.01</threshold>
<invert>true</invert>
<subNodes>
<li Class="ThinkNode_Priority">
<subNodes>
<li Class="toilets.JobGiver_Accident" />
</subNodes>
</li>
</subNodes>
</thinkRoot>
</ThinkTreeDef>
</ThinkTrees>


I'm using MonoDevelop. I rebuilt the project after the update today. The build was successful, and I only get errors when the pawns should be having accidents. I also get the following error:

Kimmy started 10 jobs in one tick .....

Which I guess is self explanatory. (it fails to start the accident job, so tries the think tree again

Here is my full source code: https://github.com/rubenwardy/rimworld-toilets
Computer science student, game developer, and open source contributor. Twitter

rubenwardy

Referencing all libraries in RimWorld/RimWorldLinux_Data/Managed/ except for mscorlib doesn't fix it. Disabling the default referencing of mscorlib, and using mscorlib.dll causes an "type forwarder for type System.Action in assembly mscorlib has circular dependency" error. This could be related to the fact that I'm using .NET 4.0, however other forum topics say that this is fine as long as I only use language features in 3.0 (and in the project settings I've set it so the language version is 3.0)
Computer science student, game developer, and open source contributor. Twitter

skullywag

I have always used 3.5, I have been told by others to NOT use anything other than 3.5, make of this what you will, just stating what ive been told.
Skullywag modded to death.
I'd never met an iterator I liked....until Zhentar saved me.
Why Unity5, WHY do you forsake me?

rubenwardy

Quote from: skullywag on July 20, 2016, 11:33:25 AM
I have always used 3.5, I have been told by others to NOT use anything other than 3.5, make of this what you will, just stating what ive been told.

Can anyone tell me how to set up 3.5 in MonoDevelop on Linux (Ubuntu based)? .NET 3.5 support has been removed since Mono 4.0.
I've tried compiling Mono 3.12.1 from source, but I get errors which lead to nothing helpful when Googled:

  CC       libmini_static_la-exceptions-amd64.lo
  CC       libmini_static_la-tramp-amd64.lo
  CC       libmini_static_la-mini-posix.lo
  CXXLD    libmini.la
ar: `u' modifier ignored since `D' is the default (see `U')
  CCLD     libmonosgen-2.0.la
ar: `u' modifier ignored since `D' is the default (see `U')
  CXXLD    libmini-static.la
ar: `u' modifier ignored since `D' is the default (see `U')
  CC       mono_sgen-main-sgen.o
  CCLD     mono-sgen
./.libs/libmini-static.a(libmini_static_la-mini.o): In function `mono_get_jit_tls_offset':
/home/ruben/Downloads/tmp/mono-3.12.1/mono/mini/mini.c:2649: undefined reference to `mono_jit_tls'
/home/ruben/Downloads/tmp/mono-3.12.1/mono/mini/mini.c:2649: undefined reference to `mono_jit_tls'
../../mono/metadata/.libs/libmonoruntimesgen-static.a(libmonoruntimesgen_static_la-sgen-alloc.o): In function `create_allocator':
/home/ruben/Downloads/tmp/mono-3.12.1/mono/metadata/sgen-alloc.c:759: undefined reference to `tlab_next_addr'
collect2: error: ld returned 1 exit status
Makefile:1336: recipe for target 'mono-sgen' failed
make[4]: *** [mono-sgen] Error 1
make[4]: Leaving directory '/home/ruben/Downloads/tmp/mono-3.12.1/mono/mini'
Makefile:1161: recipe for target 'all' failed
make[3]: *** [all] Error 2
make[3]: Leaving directory '/home/ruben/Downloads/tmp/mono-3.12.1/mono/mini'
Makefile:434: recipe for target 'all-recursive' failed
make[2]: *** [all-recursive] Error 1
make[2]: Leaving directory '/home/ruben/Downloads/tmp/mono-3.12.1/mono'
Makefile:518: recipe for target 'all-recursive' failed
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory '/home/ruben/Downloads/tmp/mono-3.12.1'
Makefile:445: recipe for target 'all' failed
make: *** [all] Error 2



wget http://download.mono-project.com/sources/mono/mono-3.12.1.tar.bz2
tar -xvf mono-3.12.1.tar.bz2
./configure --prefix=/usr/local --disable-boehm

make -j3
# ^-- error in make


Here is my ./configure output: https://gist.github.com/rubenwardy/e9c95fac663b3c10d7ce032605e64da8

There's one warning there:

WARNING: Could not find libX11.so. Do you have X.org or XFree86 installed? Assuming libX11.so.6...
Computer science student, game developer, and open source contributor. Twitter

1000101

Yes, you need to use 3.5.  It's a 3.5 program referencing 3.5 libraries.  Version is very important in dotNet.

You'll need to find an older version of MonoDevelop or setup Windows in VM so you can run a different compiler and do your development in that.

Also, you are referencing TargetA in your toil:
var splat = GenSpawn.Spawn(thing, TargetA.Cell);

But, you don't set TargetA in your JobGiver:
return new Job(DefDatabase<JobDef>.GetNamed("Accident"), null);

Optimization tip:  Don't constantly access the def database, it's bad for performance.  Make a static field which get's your Def once and use the static field.

static JobDef AccidentDef = DefDatabase<JobDef>.GetNamed("Accident");
...
return new Job(AccidentDef, pawn.Position);
(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

rubenwardy

Okay, thanks. How would I set targetA to be the current player's position?

Yeah, I'm aware of caching through static variables. I wanted to get it to work first before doing so.
Computer science student, game developer, and open source contributor. Twitter

rubenwardy

Reverting to Mono 3.12.1 worked! It no longer crashes, the pawns just keep doing the "having an accident job" forever, but I guess that's the fault of the job driver
Computer science student, game developer, and open source contributor. Twitter

jihwaja

 did you success to build Mono 3.12.1 on your Ubuntu? I got same error?
how did you do that?

1000101

(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