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

Topics - Robostove

#1
Help / Problems detouring an internal class method
December 04, 2016, 09:04:00 PM
Here's my detour. The reflections are being found, selectedObjects is correctly being set to a Verse.WindowStack.
I'm getting a crash when objList tries to AddRange selectedObjects due to an access violation. This seems odd to me as before that line I have already interacted with both objList and selectedObjects. I guess the actual contents of selectedObjects are the problem? Is it actually possible to interact with an internal class or is this fruitless? Thanks.


    static class Detours_InspectGizmoGrid
    {
        //Reflect MainTabWindow_Inspect class (it is internal static)
        static Type _InspectGizmoGrid = Type.GetType("RimWorld.InspectGizmoGrid, Assembly-CSharp, Version=0.15.6089.4186, Culture=neutral, PublicKeyToken=null");//version determined using .NET IL Dissasembler

        //Reflect required fields from reflected class
        static List<object> objList =
            (List<object>)_InspectGizmoGrid
                .GetField("objList", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);

        static List<Gizmo> gizmoList =
            (List<Gizmo>)_InspectGizmoGrid
                .GetField("gizmoList", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);


        private static void DrawInspectGizmoGridFor(this MainTabWindow_Inspect _this, IEnumerable<object> selectedObjects)
        {

            if (_InspectGizmoGrid == null)
            {
                Log.Error("Reflected InspectGizmoGrid not found.");
                return;
            }
            if (objList == null)
            {
                Log.Error("Reflected objList not found.");
                return;
            }
            if (gizmoList == null)
            {
                Log.Error("Reflected gizmoList not found.");
                return;
            }

            try
            {
                Log.Message("Enter Draw Inspect");
                Log.Message($"{selectedObjects.ToString()}");
                if (selectedObjects == null)
                {
                    Log.Message("selectedObjects is null");
                }
                Log.Message("parameter accessed!");
                objList.Clear();
                Log.Message("objList cleared");
                objList.AddRange(selectedObjects); //CRASH here. Access violation due to read/write without permission.
                Log.Message("objList added selectedObjects");
                gizmoList.Clear();
                Log.Message("Start selectable");
                //...


Injecting this detour with RawCode's TryDetourFromTo:

    [StaticConstructorOnStartup]
    internal static class DetourInjector
    {
        static DetourInjector()
        {
            LongEventHandler.QueueLongEvent(Inject, "LibraryStartup", false, null);
        }

        public static void Inject()
        {
            if (InjectDetours()) Log.Message("Detour Core injected.");
            else Log.Error("Detour Core failed to get injected.");
        }

        public static bool InjectDetours()
        {
            if (!Detours.TryDetourFromTo(Detours_InspectGizmoGrid._InspectGizmoGrid.GetMethod("DrawInspectGizmoGridFor", BindingFlags.Static | BindingFlags.Public),
                typeof(Detours_InspectGizmoGrid).GetMethod("DrawInspectGizmoGridFor", BindingFlags.Static | BindingFlags.NonPublic)))
                return false;
           
            return true;
        }
    }

#2
I've created a ThingComp that overrides CompGetGizmosExtra() to add a "charges remaining" gizmo to a weapon. The gizmo is displayed when I select the item on the ground, but it doesn't display when the item is equipped by a drafted pawn.

How do I get it to show up?