diff --git a/Config.cs b/Config.cs index 2640880..4de1b49 100644 --- a/Config.cs +++ b/Config.cs @@ -18,12 +18,14 @@ namespace CustomCosmeticLoader public const string PROPERTY_SKIN_NAME_TO_HIJACK = "skinNameToHijack"; public const string PROPERTY_IN_MAIN_MENU = "inMainMenu"; public const string PROPERTY_IN_COSMETIC_MENU = "inCosmeticMenu"; + public const string PROPERTY_OTHER_PLAYERS = "otherPlayers"; public static bool enabled = true; public static string currentSkin; public static string skinNameToHijack = "Swirl_M"; // Mirage, simple skin with nice properties public static bool inMainMenu = true; public static bool inCosmeticMenu = false; + public static Dictionary otherPlayers = new Dictionary(); public static Dictionary skins = new Dictionary(); @@ -75,6 +77,25 @@ namespace CustomCosmeticLoader if (data[PROPERTY_IN_COSMETIC_MENU] != null) inCosmeticMenu = data[PROPERTY_IN_COSMETIC_MENU].AsBool; + + if (data[PROPERTY_OTHER_PLAYERS] != null) + { + JSONClass otherPlayersData = data[PROPERTY_OTHER_PLAYERS].AsObject; + if (otherPlayersData != null) + { + foreach (KeyValuePair node in otherPlayersData) + { + string nickname = node.Key; + string skinName = node.Value.Value; + Debug.Log("Other player: " + nickname + " | " + skinName); + if (skins.ContainsKey(skinName)) + { + Debug.Log("Skin found, adding other player!"); + otherPlayers.Add(nickname, skinName); + } + } + } + } } public static void SaveConfig() @@ -88,6 +109,12 @@ namespace CustomCosmeticLoader { PROPERTY_IN_COSMETIC_MENU, inCosmeticMenu ? "true" : "false" }, }; + JSONNode otherPlayersData = new JSONClass(); + foreach (KeyValuePair otherPlayer in otherPlayers) + otherPlayersData.Add(otherPlayer.Key, otherPlayer.Value); + + node.Add(PROPERTY_OTHER_PLAYERS, otherPlayersData); + File.WriteAllText(GetConfigPath(), node.ToString()); } diff --git a/Patches/MarbleHolderPatches.cs b/Patches/MarbleHolderPatches.cs index 730ac7b..e93e52f 100644 --- a/Patches/MarbleHolderPatches.cs +++ b/Patches/MarbleHolderPatches.cs @@ -1,10 +1,23 @@ using HarmonyLib; +using Parse.Common.Internal; using System; using System.Reflection; using UnityEngine; namespace CustomCosmeticLoader.Patches { + internal static class MarbleHolderValues + { + private static FieldInfo _mbcField = typeof(MarbleHolder).GetField("mbc", BindingFlags.NonPublic | BindingFlags.Instance); + public static FieldInfo MbcField + { + get + { + return _mbcField; + } + } + } + [HarmonyPatch(typeof(MarbleHolder), nameof(MarbleHolder.SetMarble))] internal class MarbleHolderSetMarblePatch { @@ -19,15 +32,22 @@ namespace CustomCosmeticLoader.Patches if (!Config.inCosmeticMenu && __instance == CosmeticPanel.cosmHolder) return; - // If this is a networked game, ONLY apply to my marble and not anyone else happening to use our SkinToHijack + Texture2D skin = null; + if (NetworkManager.IsMultiplayer) { - MarbleController controller = __instance.GetComponentInParent(); - if (!controller.isMyClientMarble()) + MarbleController controller = MarbleHolderValues.MbcField.GetValue(__instance) as MarbleController; + if (controller == null) return; + if (!controller.isMyClientMarble()) + { + if (!Config.otherPlayers.ContainsKey(controller.nickname)) + return; + skin = Config.skins[Config.otherPlayers[controller.nickname]]; + } } - Shared.ApplyCustomTexture(__instance.currentMarble); + Shared.ApplyCustomTexture(__instance.currentMarble, skin); } } @@ -42,12 +62,19 @@ namespace CustomCosmeticLoader.Patches if (!NetworkManager.IsMultiplayer) return; - FieldInfo mbcField = typeof(MarbleHolder).GetField("mbc", BindingFlags.NonPublic | BindingFlags.Instance); - MarbleController controller = mbcField.GetValue(__instance) as MarbleController; + MarbleController controller = MarbleHolderValues.MbcField.GetValue(__instance) as MarbleController; if (controller == null) return; + Debug.Log("========= MarbleHolder.CheckSet with nickname " + controller.nickname); + + if (!controller.isMyClientMarble()) + { + if (!Config.otherPlayers.ContainsKey(controller.nickname)) + return; + } + // Don't hijack the soccer ball or zombie skins if (cs.skin == "SoccerBall_V4" || cs.skin == "Zombie") return; diff --git a/Shared.cs b/Shared.cs index 34e7a8c..9220fbe 100644 --- a/Shared.cs +++ b/Shared.cs @@ -37,14 +37,17 @@ namespace CustomCosmeticLoader } } - public static void ApplyCustomTexture(GameObject marbleObject) + public static void ApplyCustomTexture(GameObject marbleObject, Texture2D skin = null) { + if (skin == null) + skin = Config.skins[Config.currentSkin]; + MeshRenderer[] componentsInChildren = marbleObject.GetComponentsInChildren(); for (int i = 0; i < componentsInChildren.Length; i++) { Material[] materials = componentsInChildren[i].materials; foreach (Material material in materials) - material.mainTexture = Config.skins[Config.currentSkin]; + material.mainTexture = skin; } } }