using HarmonyLib; using MIU; using System.Collections.Generic; using System.Reflection; using UnityEngine; namespace CustomCosmeticLoader.Patches { /* * Private fields/values for MarbleHolder to be used in the patches */ internal static class MarbleHolderValues { internal static FieldInfo mbcField = typeof(MarbleHolder).GetField("mbc", BindingFlags.NonPublic | BindingFlags.Instance); } /* * In multiplayer and Replays, hijack the current marble and set it to be the marble we're hijacking, then apply the skin */ [HarmonyPatch(typeof(MarbleHolder), nameof(MarbleHolder.CheckSet))] internal class MarbleHolderCheckSetPatch { static void Postfix(MarbleHolder __instance, Cosmetic.Set cs) { if (!Config.enabled) return; if (!NetworkManager.IsMultiplayer && !MarbleManager.Replaying) return; // Don't hijack the soccer ball or zombie skins if (cs.skin == "SoccerBall_V4" || cs.skin == "Zombie") return; MarbleController controller = MarbleHolderValues.mbcField.GetValue(__instance) as MarbleController; if (controller == null) return; Texture2D skin = null; if (NetworkManager.IsMultiplayer) { if (controller.isMyClientMarble()) { skin = Config.skins[Config.currentSkin]; } else { if (Config.otherPlayers.ContainsKey(controller.nickname)) skin = Config.skins[Config.otherPlayers[controller.nickname]]; } } else if (MarbleManager.Replaying) // Should always be true { string replayName = null; GamePlayManager.Get().GetCurrentReplays(delegate (List replays) { if (replays.Count > 0) replayName = replays[0].Player; }); Shared.Log("MarbleHolderCheckSetPatch Replay name: " + replayName); if (replayName == Player.Current.Name) { skin = Config.skins[Config.currentSkin]; } else { if (Config.otherPlayers.ContainsKey(replayName)) skin = Config.skins[Config.otherPlayers[replayName]]; } } if (skin == null) return; __instance.SetMarble(Shared.SkinToHijack); Shared.ApplyCustomTexture(__instance.currentMarble, skin); // Reset this to what it should be incase it's used later __instance.CosmeticSet.skin = cs.skin; } } }