Problems decompiling code

Started by Kilroy232, April 28, 2016, 10:48:06 PM

Previous topic - Next topic

Kilroy232

When decompiling C# code for the sunlamp I am getting sections that don't make any sense or simply do not work when I put them back into visual studios.

I understand that the software I use to view and decompile it doesn't read the Assembly-CSharp.ddl perfectly and that it is up to me to interpolate some of it but what can you do if you can't make sense of it?

I don't know that I can or should post the C# file that I retrieved from the Assembly-CSharp.ddl so I will start with this and see where people might suggest going

Crystalline Cat

I assume you're talking about Building_SunLamp, in particular GetGizmos() and/or MakeMatchingGrowingZone()?

Both methods were compiled into private inner classes by the compiler. To see those classes, you need to make sure you are in the appropriate visibility setting ("All Members" in the MonoDevelop assembly browser, not sure about VS). In ILSpy, you also need to switch from C# to IL mode, because ILSpy can only disassemble them, not decompile them.

The compiler generated code in those classes uses things that aren't legal in C#, such as <>$ in identifiers, so you can't directly copy and paste code from them, unless your decompiler manages to recognize such code and turn it into legal code.

Here's what MonoDevelop gives me for MakeMatchingGrowingZone():

private void MakeMatchingGrowZone ()
{
Designator_ZoneAdd_Growing designator = new Designator_ZoneAdd_Growing ();
designator.DesignateMultiCell (from tempCell in this.GrowableCells
where designator.CanDesignateCell (tempCell).Accepted
select tempCell);
}


It unfortunately doesn't manage to decompile GetGizmos() properly (decompiling methods with yield is a bit messy, because the compilation changes the structure of the method a lot), but I think the original code is something like this:

public override IEnumerable<Gizmo> GetGizmos ()
{
foreach (Gizmo baseGizmo in base.GetGizmos())
{
yield return baseGizmo;
}

makeGrowZone = new Command_Action ();
makeGrowZone.action = new Action (this.MakeMatchingGrowZone);
makeGrowZone.hotKey = KeyBindingDefOf.Misc2;
makeGrowZone.defaultDesc = "CommandSunLampMakeGrowingZoneDesc".Translate ();
makeGrowZone.icon = ContentFinder<Texture2D>.Get ("UI/Designators/ZoneCreate_Growing", true);
makeGrowZone.defaultLabel = "CommandSunLampMakeGrowingZoneLabel".Translate ();

yield return makeGrowZone;
}


I got the above code by cleaning up the MoveNext() method of inner class <GetGizmos>c__IteratorE7 of Building_SunLamp. I can go into more detail of how to do that, if you'd like.

RawCode

enumerations are compiled as separate private sealed classes, no free decompiler can provide usable code.

yield is syntax sugar, everything can be done without using it.


Kilroy232

Yes I am trying to look at the GetGizmo() section of the code and I did notice the [DebuggerHidden] but I didn't realize I could change the way the code was viewed by the ILSpy program.

As for what I see after I change the view, well I have no idea how you see what you have posted and I hope you don't mind but I am going to try and use it unless you are opposed to the idea.

I see something like this:

.method public hidebysig virtual
instance class [mscorlib]System.Collections.Generic.IEnumerable`1<class Verse.Gizmo> GetGizmos () cil managed
{
.custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x584f4
// Code size 23 (0x17)
.maxstack 3
.locals init (
[0] class RimWorld.Building_SunLamp/'<GetGizmos>c__IteratorE7'
)

IL_0000: newobj instance void RimWorld.Building_SunLamp/'<GetGizmos>c__IteratorE7'::.ctor()
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: ldarg.0
IL_0008: stfld class RimWorld.Building_SunLamp RimWorld.Building_SunLamp/'<GetGizmos>c__IteratorE7'::'<>f__this'
IL_000d: ldloc.0
IL_000e: dup
IL_000f: ldc.i4.s -2
IL_0011: stfld int32 RimWorld.Building_SunLamp/'<GetGizmos>c__IteratorE7'::$PC
IL_0016: ret
} // end of method Building_SunLamp::GetGizmos





skullywag

in ilspy go to view -> options and turn off decompile enumerators, now in the left pane find the class and expand whats inside it, click on the now viewable enumerator (getGizmos in your case) in the right panel you should see output a little easier to understand.
Skullywag modded to death.
I'd never met an iterator I liked....until Zhentar saved me.
Why Unity5, WHY do you forsake me?

Kilroy232

#5
I am sure I am driving you guys nuts but I think I just about have it.

So I have this:

using System;
using System.Text;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using UnityEngine;
using Verse;

namespace RimWorld
{
    internal class Building_SunLamp : Building
    {
        public IEnumerable<IntVec3> GrowableCells
        {
            get
            {
                return GenRadial.RadialCellsAround(base.Position, this.def.specialDisplayRadius, true);
            }
        }

        public Building_SunLamp()
        {
        }

        public override IEnumerable<Gizmo> GetGizmos()
        {
            foreach (Gizmo baseGizmo in base.GetGizmos())
            {
                yield return baseGizmo;
            }

            makeGrowZone = new Command_Action();
            makeGrowZone.action = new Action(this.MakeMatchingGrowZone);
            makeGrowZone.hotKey = KeyBindingDefOf.Misc2;
            makeGrowZone.defaultDesc = "CommandSunLampMakeGrowingZoneDesc".Translate();
            makeGrowZone.icon = ContentFinder<Texture2D>.Get("UI/Designators/ZoneCreate_Growing", true);
            makeGrowZone.defaultLabel = "CommandSunLampMakeGrowingZoneLabel".Translate();

            yield return makeGrowZone;
        }

        private void MakeMatchingGrowZone ()
{
Designator_ZoneAdd_Growing designator = new Designator_ZoneAdd_Growing ();
designator.DesignateMultiCell (from tempCell in this.GrowableCells
where designator.CanDesignateCell (tempCell).Accepted
select tempCell);
}
    }
}


The only thing left that is causing issues is the makeGrowZone. Visual Studio is telling me that "makeGrowZone" doesn't exist and I know that is normally fixed by using the correct references but I think I have about all the references I can have. I am having the same problem with a "GenDate" I am trying to use


...
Heres the deal, I am trying to make a sun lamp that turns off when the plants go into resting. I have code for when the plants stop growing and go into rest.

private bool Resting
        {
            get
            {
                if ((double)GenDate.CurrentDayPercent >= 0.25)
                    return (double)GenDate.CurrentDayPercent > 0.800000011920929;
                else
                    return true;
            }
        }


I am trying to get the sunlamp code so that I can basically duplicate it and add in a few lines of code that will make it turn off at the same times as the plants start resting... starting to think I do not know nearly enough about the way this games code works though

skullywag

you havent typed the makegrowzone variable:

Command_Action makeGrowZone = blah;
Skullywag modded to death.
I'd never met an iterator I liked....until Zhentar saved me.
Why Unity5, WHY do you forsake me?