How to get thing affected by facility from the facility?

Started by MAGGen, April 08, 2021, 05:28:31 PM

Previous topic - Next topic

MAGGen

I know that sounds weird but is there any way to get thing (and it's properties) with "affected by facility" comp from the facility thing that connected to it? I have a facility with job driver that need to change some props in "affected by facility" thing only after job done... I have no idea how to do it without using map.getComponent... And please, is there any metods that allows searching objects in area of current cell with structure like: cell(or thing).FindObj(integer_with_search_area_radius). Thank you in advance, and sorry for my bad english...
Also, Is there any xml documentation to existing rimworld code, where can I find it?

MAGGen

Well I just findout that all linked buildings is private in CompFacility...
Aaaaahhh.... Comon... I don't want to use reflection in my mod or override CompFacility class! Is ther any normal solutions to get this affected building without override?

MAGGen

Is it even posible to use reflection in rimworld? I have only nulls from fields...

MAGGen

Yes! Find the solution! 8) Pls, Tynan don't kill me for this kind of code! I hate reflection but somtimes it's the fastest way...

CompFacility t = TargetA.Thing.TryGetComp<CompFacility>();
List<Thing> l = (List<Thing>)t.GetType().GetField("linkedBuildings", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).GetValue(t);
l[0].Property_I_Need_To_Set = my_value;

RawCode

add null\length check just in case, this is not needed in this case, but very important when modding, because other mod may perform "lazy" object construction and you may hit NPE in main thread.

LWM

There are various ways to make this a faster calculation (if you need speed - and I don't think you do if it's something that only happens from time to time)

One is to cache the .GetField() result during setup in some static variable, and call only .GetValue() when you need it.

A much fancier approach is to write a dynamic method to call it directly (we do this in Project RimFactory to call NoStorageBlockersIn(), which can get called a lot) - it's harder to manage, but is also faster, so if anyone else needs that, it's an option.

In your case, you probably don't need anything more fancy :)  Except null checks - because weird things do happen when mods are involved  ::) (I ran into a Thing with a null ...thingClass? once; I didn't think it was possible and yet...)

RawCode

methods are jitted at runtime and properly made dynamic method equals to using pointers, but unlike pointers, dynamic method is never inlined and calling them have some overhead.

and yes, c# have restrictions on pointers for managed types, but they are not enforced at runtime (for mono, coreclr do enforce restrictions), using union type with all possible types packed into same offset will trick compiler.

LWM

I'm afraid you are referencing technical details that I'm not familiar with.  "Pointers" is a very avoided word in most C# literature, so I'm not sure what you mean?