Exemplo n.º 1
0
        // todo support methods with arguments (currently there has been no need for it)
        public static SyncDelegate RegisterSyncDelegate(Type inType, string nestedType, string methodName, string[] fields, Type[] args = null)
        {
            string typeName = $"{inType}+{nestedType}";
            Type   type     = MpReflection.GetTypeByName(typeName);

            if (type == null)
            {
                throw new Exception($"Couldn't find type {typeName}");
            }

            MethodInfo method = AccessTools.Method(type, methodName, args);

            if (method == null)
            {
                throw new Exception($"Couldn't find method {typeName}::{methodName}");
            }

            MpUtil.MarkNoInlining(method);

            SyncDelegate handler = new SyncDelegate(type, method, fields);

            syncMethods[handler.method] = handler;
            handlers.Add(handler);

            PatchMethodForSync(method);

            return(handler);
        }
        static void PatchIfExists(string typeName, string methodName, HarmonyMethod prefix = null, HarmonyMethod postfix = null, HarmonyMethod transpiler = null)
        {
            var type = MpReflection.GetTypeByName(typeName);

            if (type == null)
            {
                return;
            }

            var method = AccessTools.Method(type, methodName);

            if (method == null)
            {
                return;
            }

            Multiplayer.harmony.Patch(method, prefix, postfix, transpiler);
        }
        public static void Init()
        {
            var harmony = Multiplayer.harmony;

            // Compat with Fluffy's mod loader
            var fluffysModButtonType = MpReflection.GetTypeByName("ModManager.ModButton_Installed");

            if (fluffysModButtonType != null)
            {
                harmony.Patch(
                    fluffysModButtonType.GetMethod("DoModButton"),
                    new HarmonyMethod(typeof(PageModsPatch), nameof(PageModsPatch.ModManager_ButtonPrefix)),
                    new HarmonyMethod(typeof(PageModsPatch), nameof(PageModsPatch.Postfix))
                    );
            }

            var cancelForArbiter = new HarmonyMethod(typeof(CancelForArbiter), "Prefix");

            // Fix PrisonLabor breaking the arbiter
            {
                PatchIfExists("PrisonLabor.Behaviour_MotivationIcon", "Update", cancelForArbiter);
                PatchIfExists("PrisonLabor.Core.GUI_Components.PawnIcons", "MapComponentTick", cancelForArbiter);
                PatchIfExists("PrisonLabor.MapComponent_Icons", "MapComponentTick", cancelForArbiter);
            }

            // PawnsAreCapable compat
            // Replace workSettings.SetPriority(def, p) with (workSettings.priorities[def] = p)
            // Minimizes side effects and goes around syncing
            // Also cache the dictionary to improve performance
            {
                var pawnsAreCapablePatch = new HarmonyMethod(typeof(ModPatches), nameof(PawnsAreCapable_FloatMenu_Patch_Transpiler));
                PatchIfExists("PawnsAreCapable.FloatMenuMakerMap_ChoicesAtFor", "Prefix", transpiler: pawnsAreCapablePatch);
                PatchIfExists("PawnsAreCapable.FloatMenuMakerMap_ChoicesAtFor", "Postfix", transpiler: pawnsAreCapablePatch);
            }

            var randPatchPrefix  = new HarmonyMethod(typeof(RandPatches), "Prefix");
            var randPatchPostfix = new HarmonyMethod(typeof(RandPatches), "Postfix");

            // Facial Stuff compat
            {
                PatchIfExists("FacialStuff.Harmony.HarmonyPatchesFS", "TryInteractWith_Postfix", randPatchPrefix, randPatchPostfix);
            }
        }