Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ReviveAll v1.0.0
ReviveAll.dll
Decompiled 7 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using TMPro; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("ReviveAll")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ReviveAll")] [assembly: AssemblyTitle("ReviveAll")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ReviveAll { [BepInPlugin("reviveall", "Revive All", "1.6.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { internal static Plugin Instance; internal static ManualLogSource Log; internal const string ItemAssetName = "Item Revive All"; internal const string ItemDisplayName = "Revive"; internal const string StartHealthItemAssetName = "Item Revive Start Health"; internal const string StartHealthItemDisplayName = "Revive Start Health"; private const string TemplateItemName = "Item Upgrade Player Grab Range"; internal static ConfigEntry<int> MaxRevives; internal static ConfigEntry<int> ReviveHealth; internal static ConfigEntry<int> ShopPrice; internal static ConfigEntry<int> ShopPrice2; internal static ConfigEntry<string> TemplateItem; internal static ConfigEntry<string> ItemColor; internal static bool PromptOpen = false; internal static bool BypassPatch = false; internal static float IgnoreUntil = 0f; internal static object[] PendingArgs; internal static RunManager PendingRunManager; private const string UsedKey = "reviveAllUsed"; private const string BonusKey = "reviveAllBonus"; private const string StartHealthBonusKey = "reviveAllStartHealthBonus"; private static readonly Dictionary<string, int> fallbackStats = new Dictionary<string, int>(); internal static bool Cover = false; private static Texture2D blackTex; private float coverTimer; private float syncTimer; private int lastSentLeft = -1; private static GUIStyle smallStyle; private static GUIStyle bigStyle; private static GUIStyle infoStyle; private static Item reviveItem; private static Item startHealthItem; private static int registerAttempts; private static bool registering; private static bool boundLogged; private static bool startHealthBoundLogged; internal static int UsedRevives { get { return GetStat("reviveAllUsed"); } set { SetStat("reviveAllUsed", value); } } internal static int Bonus { get { return GetStat("reviveAllBonus"); } set { SetStat("reviveAllBonus", value); } } internal static int StartHealthBonus { get { return GetStat("reviveAllStartHealthBonus"); } set { SetStat("reviveAllStartHealthBonus", value); } } internal static int RevivesLeft => Mathf.Max(0, MaxRevives.Value + Bonus - UsedRevives); private static int GetStat(string key) { StatsManager instance = StatsManager.instance; if ((Object)(object)instance != (Object)null && instance.runStats != null) { if (!instance.runStats.TryGetValue(key, out var value)) { return 0; } return value; } if (!fallbackStats.TryGetValue(key, out var value2)) { return 0; } return value2; } private static void SetStat(string key, int value) { fallbackStats[key] = value; StatsManager instance = StatsManager.instance; if ((Object)(object)instance != (Object)null && instance.runStats != null) { instance.runStats[key] = value; ManualLogSource log = Log; if (log != null) { log.LogInfo((object)$"Run-Stat {key} = {value}"); } } } internal static void ResetCounter() { fallbackStats.Clear(); StatsManager instance = StatsManager.instance; if ((Object)(object)instance != (Object)null && instance.runStats != null) { instance.runStats.Remove("reviveAllUsed"); instance.runStats.Remove("reviveAllBonus"); instance.runStats.Remove("reviveAllStartHealthBonus"); } } private void Awake() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Expected O, but got Unknown //IL_011e: Unknown result type (might be due to invalid IL or missing references) Instance = this; Log = ((BaseUnityPlugin)this).Logger; MaxRevives = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxRevives", 3, "Mit so vielen Wiederbelebungen startet ein Run (im Shop kannst du weitere kaufen)."); ReviveHealth = ((BaseUnityPlugin)this).Config.Bind<int>("General", "ReviveHealth", 50, new ConfigDescription("Leben, mit dem ein Spieler wiederbelebt wird (wird auf die maximale Gesundheit begrenzt).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000), Array.Empty<object>())); ShopPrice = ((BaseUnityPlugin)this).Config.Bind<int>("Shop", "ShopPrice", 1, new ConfigDescription("Preis des Shop-Items in Tausend ($). 4 = $4K.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000), Array.Empty<object>())); ShopPrice2 = ((BaseUnityPlugin)this).Config.Bind<int>("Shop", "ShopPrice2", 1, new ConfigDescription("Preis des Shop-Items in Tausend ($). 4 = $4K.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000), Array.Empty<object>())); TemplateItem = ((BaseUnityPlugin)this).Config.Bind<string>("Shop", "TemplateItem", "Item Upgrade Player Grab Range", "Name des vorhandenen Items, das als Vorlage für das Shop-Item kopiert wird. Zum Testen z. B. 'Item Upgrade Player Grab Range'."); ItemColor = ((BaseUnityPlugin)this).Config.Bind<string>("Shop", "ItemColor", "#4DFF80", "Farbe des Shop-Items (Hex, z. B. #4DFF80). Leer lassen, um das Aussehen der Vorlage unverändert zu lassen."); new Harmony("reviveall").PatchAll(); ((MonoBehaviour)this).StartCoroutine(RegisterReviveItem()); Log.LogInfo((object)("Revive All 1.6.0 geladen. Config: " + ((BaseUnityPlugin)this).Config.ConfigFilePath)); } private void Update() { SyncRevives(); if (Input.GetKeyDown((KeyCode)290)) { try { DumpInfo(); } catch (Exception ex) { Log.LogError((object)("Dump fehlgeschlagen: " + ex)); } } if (Input.GetKeyDown((KeyCode)291)) { try { ExportTemplateTextures(); } catch (Exception ex2) { Log.LogError((object)("Textur-Export fehlgeschlagen: " + ex2)); } } if (Cover) { coverTimer += Time.deltaTime; if (coverTimer > 12f) { Cover = false; coverTimer = 0f; } } else { coverTimer = 0f; } if (PromptOpen) { if (Input.GetKeyDown((KeyCode)121) || Input.GetKeyDown((KeyCode)122)) { Accept(); } else if (Input.GetKeyDown((KeyCode)110)) { Decline(); } } } private static void EnsureStyles() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) if (bigStyle == null) { smallStyle = new GUIStyle(GUI.skin.label) { fontStyle = (FontStyle)1, alignment = (TextAnchor)4, richText = true }; bigStyle = new GUIStyle(GUI.skin.label) { fontStyle = (FontStyle)1, alignment = (TextAnchor)4, richText = true }; infoStyle = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, richText = true }; smallStyle.normal.textColor = new Color(1f, 0.35f, 0.35f); bigStyle.normal.textColor = Color.white; infoStyle.normal.textColor = Color.white; } } private void OnGUI() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) if ((int)Event.current.type == 7 && (Cover || PromptOpen)) { if ((Object)(object)blackTex == (Object)null) { blackTex = new Texture2D(1, 1); blackTex.SetPixel(0, 0, Color.black); blackTex.Apply(); } GUI.depth = -1000; GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)blackTex); if (PromptOpen) { EnsureStyles(); float num = Screen.width; float num2 = (float)Screen.height / 2f; float num3 = (float)Screen.height / 100f; smallStyle.fontSize = Mathf.RoundToInt(num3 * 3f); bigStyle.fontSize = Mathf.RoundToInt(num3 * 7f); infoStyle.fontSize = Mathf.RoundToInt(num3 * 3.5f); GUI.Label(new Rect(0f, num2 - num3 * 18f, num, num3 * 6f), "ALL PLAYERS ARE DEAD", smallStyle); GUI.Label(new Rect(0f, num2 - num3 * 10f, num, num3 * 10f), "Revive everyone?", bigStyle); GUI.Label(new Rect(0f, num2 + num3 * 2f, num, num3 * 6f), "Revives left: " + RevivesLeft, infoStyle); GUI.Label(new Rect(0f, num2 + num3 * 10f, num, num3 * 6f), "<color=#6cff6c>[Y]</color> Yes <color=#ff5050>[N]</color> No", infoStyle); } } } private void Accept() { if (PromptOpen) { PromptOpen = false; if (ReviveEveryone() == 0) { Log.LogError((object)"Niemand wiederbelebt, normaler Game-Over läuft."); RunOriginalChangeLevel(); } else { UsedRevives++; IgnoreUntil = Time.time + 5f; Log.LogInfo((object)$"Wiederbelebung benutzt, übrig: {RevivesLeft}"); } PendingArgs = null; PendingRunManager = null; } } private void Decline() { PromptOpen = false; ResetCounter(); RunOriginalChangeLevel(); PendingArgs = null; PendingRunManager = null; } private static void RunOriginalChangeLevel() { if ((Object)(object)PendingRunManager == (Object)null || PendingArgs == null) { return; } BypassPatch = true; try { AccessTools.Method(typeof(RunManager), "ChangeLevel", (Type[])null, (Type[])null).Invoke(PendingRunManager, PendingArgs); } finally { BypassPatch = false; } } private static int ReviveEveryone() { List<PlayerAvatar> list = new List<PlayerAvatar>(Object.FindObjectsOfType<PlayerAvatar>(true)); if (list.Count == 0) { try { object obj = AccessTools.Field(typeof(GameDirector), "instance")?.GetValue(null); List<PlayerAvatar> list2 = ((obj != null) ? (AccessTools.Field(typeof(GameDirector), "PlayerList")?.GetValue(obj) as List<PlayerAvatar>) : null); if (list2 != null) { list.AddRange(list2); } } catch (Exception ex) { Log.LogWarning((object)("GameDirector-Fallback fehlgeschlagen: " + ex.Message)); } } Log.LogInfo((object)$"Gefundene Spieler: {list.Count}"); if (list.Count > 0) { Cover = true; } int num = 0; foreach (PlayerAvatar item in list) { if (!((Object)(object)item == (Object)null)) { try { item.Revive(false); num++; Log.LogInfo((object)("Revive aufgerufen für " + ((Object)item).name)); } catch (Exception ex2) { Log.LogError((object)("Revive fehlgeschlagen: " + ex2)); } } } if (num > 0 && (Object)(object)Instance != (Object)null) { ((MonoBehaviour)Instance).StartCoroutine(TeleportWithCover(list)); } else { Cover = false; } return num; } private static bool TryGetTruckSpawn(out Vector3 pos, out Quaternion rot) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) pos = Vector3.zero; rot = Quaternion.identity; Assembly assembly = typeof(PlayerAvatar).Assembly; string[] array = new string[3] { "SpawnPoint", "PlayerSpawnPoint", "TruckSafetySpawnPoint" }; foreach (string text in array) { Type type = assembly.GetType(text); if (type == null || !typeof(Component).IsAssignableFrom(type)) { continue; } Object[] array2 = Resources.FindObjectsOfTypeAll(type); foreach (Object obj in array2) { Component val = (Component)(object)((obj is Component) ? obj : null); if (!((Object)(object)val == (Object)null)) { Scene scene = val.gameObject.scene; if (((Scene)(ref scene)).IsValid()) { pos = val.transform.position; rot = val.transform.rotation; Log.LogInfo((object)$"Spawnpunkt: {text} bei {pos}"); return true; } } } } Log.LogWarning((object)"Kein Truck-Spawnpunkt gefunden."); return false; } private static IEnumerator TeleportToTruck(List<PlayerAvatar> avatars) { if (!TryGetTruckSpawn(out var basePos, out var rot)) { yield break; } MethodInfo spawn = typeof(PlayerAvatar).GetMethod("Spawn", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2] { typeof(Vector3), typeof(Quaternion) }, null); if (spawn == null) { Log.LogError((object)"PlayerAvatar.Spawn(Vector3, Quaternion) nicht gefunden."); yield break; } HashSet<PlayerAvatar> done = new HashSet<PlayerAvatar>(); float timeout = Time.time + 10f; while (Time.time < timeout && done.Count < avatars.Count) { yield return (object)new WaitForSeconds(0.25f); int num = 0; foreach (PlayerAvatar avatar in avatars) { int num2 = num++; if (!((Object)(object)avatar == (Object)null) && !done.Contains(avatar)) { Vector3 val = basePos + new Vector3((float)(num2 % 2) * 1.2f, 0.2f, (float)(num2 / 2) * 1.2f); float num3 = Vector3.Distance(((Component)avatar).transform.position, val); if (num3 <= 3f) { done.Add(avatar); Log.LogInfo((object)$"Am Truck angekommen: {((Object)avatar).name} ({num3:F1} m)"); } else { spawn.Invoke(avatar, new object[2] { val, rot }); } } } } if (done.Count < avatars.Count) { Log.LogWarning((object)"Nicht alle Spieler konnten zum Truck gesetzt werden."); } } private static IEnumerator TeleportWithCover(List<PlayerAvatar> avatars) { yield return ((MonoBehaviour)Instance).StartCoroutine(TeleportToTruck(avatars)); yield return (object)new WaitForSeconds(0.4f); ApplyReviveHealth(avatars); Cover = false; } private static void ApplyReviveHealth(List<PlayerAvatar> avatars) { foreach (PlayerAvatar avatar in avatars) { if ((Object)(object)avatar == (Object)null) { continue; } try { object obj = AccessTools.Field(typeof(PlayerAvatar), "playerHealth")?.GetValue(avatar); if (obj == null) { Log.LogError((object)"PlayerAvatar.playerHealth nicht gefunden."); continue; } Type type = obj.GetType(); FieldInfo fieldInfo = AccessTools.Field(type, "health"); FieldInfo fieldInfo2 = AccessTools.Field(type, "maxHealth"); if (fieldInfo == null || fieldInfo.FieldType != typeof(int)) { Log.LogError((object)"Feld 'health' (int) nicht gefunden. Vorhandene Felder:"); FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo3 in fields) { Log.LogInfo((object)(" " + type.Name + "." + fieldInfo3.Name + " (" + fieldInfo3.FieldType.Name + ")")); } } else { int num = ((fieldInfo2 != null && fieldInfo2.FieldType == typeof(int)) ? ((int)fieldInfo2.GetValue(obj)) : int.MaxValue); int num2 = Mathf.Clamp(ReviveHealth.Value + StartHealthBonus, 1, num); fieldInfo.SetValue(obj, num2); Log.LogInfo((object)$"Leben gesetzt auf {num2} (max {num}) für {((Object)avatar).name}"); } } catch (Exception ex) { Log.LogError((object)("Leben setzen fehlgeschlagen: " + ex)); } } } private IEnumerator RegisterReviveItem() { float timeout = Time.realtimeSinceStartup + 180f; while (Time.realtimeSinceStartup < timeout) { if (TryRegister()) { yield break; } yield return (object)new WaitForSeconds(0.5f); } Log.LogError((object)"Shop-Item wurde nicht registriert (Timeout)."); } internal static bool TryRegister() { if (registering) { return false; } registering = true; try { StatsManager instance = StatsManager.instance; if ((Object)(object)instance == (Object)null) { return false; } if (!(AccessTools.Field(typeof(StatsManager), "itemDictionary")?.GetValue(instance) is IDictionary { Count: not 0 } dictionary)) { return false; } if ((Object)(object)reviveItem == (Object)null || (Object)(object)startHealthItem == (Object)null) { if (registerAttempts >= 5) { return false; } registerAttempts++; if ((Object)(object)reviveItem == (Object)null) { reviveItem = CreateShopItem(dictionary, "Item Revive All", "Revive", "Adds one revive for the whole team.", (float)ShopPrice.Value * 1000f, isStartHealthItem: false); } if ((Object)(object)startHealthItem == (Object)null) { startHealthItem = CreateShopItem(dictionary, "Item Revive Start Health", "Revive Start Health", "Adds 10 HP to the health players have when revived.", (float)ShopPrice2.Value * 1000f, isStartHealthItem: true); } if ((Object)(object)reviveItem == (Object)null || (Object)(object)startHealthItem == (Object)null) { return false; } } if (!AddToCatalog(dictionary, "Item Revive All", reviveItem)) { return false; } if (!AddToCatalog(dictionary, "Item Revive Start Health", startHealthItem)) { return false; } if (!boundLogged) { boundLogged = true; Log.LogInfo((object)"Shop-Item 'Revive' ist im Item-Katalog."); } if (!startHealthBoundLogged) { startHealthBoundLogged = true; Log.LogInfo((object)"Shop-Item 'Revive Start Health' ist im Item-Katalog."); } return true; } catch (Exception ex) { Log.LogError((object)("Shop-Item registrieren fehlgeschlagen: " + ex)); return false; } finally { registering = false; } } private static bool AddToCatalog(IDictionary dict, string assetName, Item item) { Item val = (Item)(dict.Contains(assetName) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)item) { Log.LogWarning((object)("Konflikt: Im Katalog liegt schon ein anderes Item namens " + assetName)); return false; } dict[assetName] = item; return true; } private static Item CreateShopItem(IDictionary dict, string assetName, string displayName, string description, float price, bool isStartHealthItem) { //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_0300: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Expected O, but got Unknown string value = TemplateItem.Value; Item val = (Item)(dict.Contains(value) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val == (Object)null) { Log.LogError((object)("Vorlage-Item nicht gefunden: " + value + ". Vorhandene Items:")); foreach (object key in dict.Keys) { Log.LogInfo((object)(" " + key)); } return null; } Log.LogInfo((object)("Vorlage-Item: " + value)); Item val2 = Object.Instantiate<Item>(val); ((Object)val2).name = assetName; SetMember(val2, "itemName", displayName); SetMember(val2, "itemNameLocalized", null); SetMember(val2, "description", description); SetMember(val2, "maxAmount", 99); SetMember(val2, "maxAmountInShop", 2); SetMember(val2, "minPlayerCount", 1); SetMember(val2, "disabled", false); SetMember(val2, "maxPurchase", false); SetMember(val2, "physicalItem", true); FieldInfo fieldInfo = AccessTools.Field(typeof(Item), "value"); object? obj = fieldInfo?.GetValue(val); Object val3 = (Object)((obj is Object) ? obj : null); if (val3 != (Object)null) { Log.LogInfo((object)string.Format("Vorlage-Preis: min {0} max {1}", GetMember(val3, "valueMin"), GetMember(val3, "valueMax"))); Object val4 = Object.Instantiate(val3); SetMember(val4, "valueMin", price); SetMember(val4, "valueMax", price); fieldInfo.SetValue(val2, val4); } else { Log.LogWarning((object)"Vorlage hat kein 'value', Preis bleibt wie bei der Vorlage."); } FieldInfo fieldInfo2 = AccessTools.Field(typeof(Item), "colorPreset"); object? obj2 = fieldInfo2?.GetValue(val); Object val5 = (Object)((obj2 is Object) ? obj2 : null); if (val5 != (Object)null) { Object val6 = Object.Instantiate(val5); SetMember(val6, "colorMain", (object)new Color(0.3f, 1f, 0.5f)); SetMember(val6, "colorLight", (object)new Color(0.3f, 1f, 0.5f)); SetMember(val6, "colorDark", (object)new Color(0.18f, 0.6f, 0.3f)); fieldInfo2.SetValue(val2, val6); } FieldInfo fieldInfo3 = AccessTools.Field(typeof(Item), "prefab"); GameObject prefabFromRef = GetPrefabFromRef(fieldInfo3?.GetValue(val)); if ((Object)(object)prefabFromRef == (Object)null) { Log.LogError((object)"Prefab der Vorlage nicht gefunden."); return null; } GameObject val7 = new GameObject("ReviveAll_PrefabHolder"); val7.SetActive(false); Object.DontDestroyOnLoad((Object)(object)val7); GameObject val8 = Object.Instantiate<GameObject>(prefabFromRef, val7.transform, false); val8.SetActive(true); ((Object)val8).name = assetName; ItemAttributes component = val8.GetComponent<ItemAttributes>(); if ((Object)(object)component == (Object)null) { Log.LogError((object)"Geklontes Prefab hat kein ItemAttributes."); return null; } SetMember(component, "item", val2); SetMember(component, "itemName", displayName); SetMember(component, "promptName", displayName); SetMember(component, "itemAssetName", assetName); ItemHealthPack component2 = val8.GetComponent<ItemHealthPack>(); if ((Object)(object)component2 != (Object)null) { SetMember(component2, "healAmount", 0); } if (!ApplyCardTexture(val8, isStartHealthItem)) { TintClone(val8, isStartHealthItem ? "#59B8FF" : ItemColor.Value); } MonoBehaviour[] components = val8.GetComponents<MonoBehaviour>(); foreach (MonoBehaviour val9 in components) { if (!((Object)(object)val9 == (Object)null)) { string name = ((object)val9).GetType().Name; if (name.StartsWith("ItemUpgrade", StringComparison.Ordinal)) { Log.LogInfo((object)("Entferne Upgrade-Komponente aus dem Klon: " + name)); Object.DestroyImmediate((Object)(object)val9); } } } MethodInfo methodInfo = AccessTools.TypeByName("REPOLib.Modules.Items")?.GetMethod("RegisterItem", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(ItemAttributes) }, null); if (methodInfo == null) { Log.LogError((object)"REPOLib.Modules.Items.RegisterItem(ItemAttributes) nicht gefunden."); return null; } List<Action> list = PreserveExistingStats(assetName); object obj3; try { obj3 = methodInfo.Invoke(null, new object[1] { component }); } finally { foreach (Action item in list) { item(); } } if (obj3 == null) { Log.LogError((object)"REPOLib hat keine PrefabRef geliefert."); return null; } fieldInfo3.SetValue(val2, obj3); Log.LogInfo((object)("Shop-Item '" + displayName + "' bei REPOLib registriert.")); return val2; } private static Texture2D LoadTexture(string path) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Expected O, but got Unknown Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true); MethodInfo methodInfo = AccessTools.TypeByName("UnityEngine.ImageConversion")?.GetMethod("LoadImage", new Type[2] { typeof(Texture2D), typeof(byte[]) }); if (methodInfo == null) { Log.LogError((object)"ImageConversion.LoadImage nicht gefunden."); return null; } if (!(bool)methodInfo.Invoke(null, new object[2] { val, File.ReadAllBytes(path) })) { Log.LogWarning((object)("Bild konnte nicht gelesen werden: " + path)); return null; } ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; return val; } private static void LogMaterials(GameObject clone) { Log.LogInfo((object)"Materialien des Klons:"); Renderer[] componentsInChildren = clone.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if ((Object)(object)val == (Object)null || ((object)val).GetType().Name == "ParticleSystemRenderer") { continue; } Material[] sharedMaterials = val.sharedMaterials; foreach (Material val2 in sharedMaterials) { if (!((Object)(object)val2 == (Object)null)) { Texture mainTexture = val2.mainTexture; Log.LogInfo((object)(" " + ((Object)val).name + ": Material '" + ((Object)val2).name + "' Shader '" + ((Object)val2.shader).name + "' Textur " + (((Object)(object)mainTexture != (Object)null) ? $"'{((Object)mainTexture).name}' {mainTexture.width}x{mainTexture.height}" : "-"))); } } } } private static bool ApplyCardTexture(GameObject clone, bool isStartHealthItem) { //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) LogMaterials(clone); string? directoryName = Path.GetDirectoryName(((BaseUnityPlugin)Instance).Info.Location); string path = (isStartHealthItem ? "revivestarthealth.png" : "revive.png"); string text = Path.Combine(directoryName, path); if (!File.Exists(text)) { Log.LogInfo((object)("Kein Kartenbild (optional): " + text)); return false; } Texture2D val = LoadTexture(text); if ((Object)(object)val == (Object)null) { return false; } bool flag = false; int num = 0; Renderer[] componentsInChildren = clone.GetComponentsInChildren<Renderer>(true); foreach (Renderer val2 in componentsInChildren) { if ((Object)(object)val2 == (Object)null || ((object)val2).GetType().Name == "ParticleSystemRenderer") { continue; } Material[] sharedMaterials = val2.sharedMaterials; foreach (Material val3 in sharedMaterials) { Texture val4 = (((Object)(object)val3 != (Object)null) ? val3.mainTexture : null); if (!((Object)(object)val4 == (Object)null)) { float num2 = (float)val4.height / (float)val4.width; if (num2 >= 1.25f && num2 <= 1.8f) { flag = true; } num = Mathf.Max(num, val4.width * val4.height); } } } int num3 = 0; componentsInChildren = clone.GetComponentsInChildren<Renderer>(true); foreach (Renderer val5 in componentsInChildren) { if ((Object)(object)val5 == (Object)null || ((object)val5).GetType().Name == "ParticleSystemRenderer") { continue; } Material[] materials = val5.materials; Material[] sharedMaterials = materials; foreach (Material val6 in sharedMaterials) { Texture val7 = (((Object)(object)val6 != (Object)null) ? val6.mainTexture : null); if ((Object)(object)val7 == (Object)null) { continue; } float num4 = (float)val7.height / (float)val7.width; bool num5; if (!flag) { num5 = val7.width * val7.height == num; } else { if (!(num4 >= 1.25f)) { continue; } num5 = num4 <= 1.8f; } if (num5) { val6.mainTexture = (Texture)(object)val; if (val6.HasProperty("_MainTex")) { val6.SetTexture("_MainTex", (Texture)(object)val); } if (val6.HasProperty("_BaseMap")) { val6.SetTexture("_BaseMap", (Texture)(object)val); } if (val6.HasProperty("_Color")) { val6.SetColor("_Color", Color.white); } if (val6.HasProperty("_BaseColor")) { val6.SetColor("_BaseColor", Color.white); } val6.mainTextureScale = Vector2.one; val6.mainTextureOffset = Vector2.zero; num3++; } } val5.materials = materials; } Log.LogInfo((object)("Kartenbild auf " + num3 + " Material(ien) gesetzt.")); return num3 > 0; } private static void TintClone(GameObject clone, string hex) { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(hex)) { return; } Color val = default(Color); if (!ColorUtility.TryParseHtmlString(hex, ref val)) { Log.LogWarning((object)("ItemColor ist keine gültige Hex-Farbe: " + hex)); return; } int num = 0; Renderer[] componentsInChildren = clone.GetComponentsInChildren<Renderer>(true); foreach (Renderer val2 in componentsInChildren) { if ((Object)(object)val2 == (Object)null || ((object)val2).GetType().Name == "ParticleSystemRenderer") { continue; } Material[] materials = val2.materials; Material[] array = materials; foreach (Material val3 in array) { if (!((Object)(object)val3 == (Object)null)) { if (val3.HasProperty("_Color")) { val3.SetColor("_Color", val); } if (val3.HasProperty("_BaseColor")) { val3.SetColor("_BaseColor", val); } if (val3.HasProperty("_EmissionColor")) { val3.SetColor("_EmissionColor", new Color(val.r * 0.6f, val.g * 0.6f, val.b * 0.6f, 1f)); } num++; } } val2.materials = materials; } Log.LogInfo((object)(num + " Materialien eingefärbt (" + hex + ").")); } private static List<Action> PreserveExistingStats(string itemName) { List<Action> list = new List<Action>(); StatsManager instance = StatsManager.instance; SortedDictionary<string, Dictionary<string, int>> sortedDictionary = (((Object)(object)instance != (Object)null) ? (AccessTools.Field(typeof(StatsManager), "dictionaryOfDictionaries")?.GetValue(instance) as SortedDictionary<string, Dictionary<string, int>>) : null); if (sortedDictionary == null) { return list; } foreach (KeyValuePair<string, Dictionary<string, int>> item in sortedDictionary) { if (!item.Key.StartsWith("item", StringComparison.Ordinal)) { continue; } Dictionary<string, int> data = item.Value; int old; bool existed = data.TryGetValue(itemName, out old); list.Add(delegate { if (existed) { data[itemName] = old; } else { data.Remove(itemName); } }); } return list; } private static GameObject GetPrefabFromRef(object r) { if (r == null) { return null; } Type type = r.GetType(); string[] array = new string[2] { "Prefab", "prefab" }; foreach (string text in array) { PropertyInfo property = type.GetProperty(text, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { object? value = property.GetValue(r); GameObject val = (GameObject)((value is GameObject) ? value : null); if (val != null) { return val; } } FieldInfo fieldInfo = AccessTools.Field(type, text); if (fieldInfo != null) { object? value2 = fieldInfo.GetValue(r); GameObject val2 = (GameObject)((value2 is GameObject) ? value2 : null); if (val2 != null) { return val2; } } } return null; } private static void SetMember(object target, string name, object value) { if (target == null) { return; } FieldInfo fieldInfo = AccessTools.Field(target.GetType(), name); if (fieldInfo == null) { Log.LogWarning((object)("Feld '" + name + "' nicht gefunden in " + target.GetType().Name)); return; } try { object value2 = value; if (value is IConvertible && fieldInfo.FieldType.IsPrimitive) { value2 = Convert.ChangeType(value, fieldInfo.FieldType); } fieldInfo.SetValue(target, value2); } catch (Exception ex) { Log.LogWarning((object)("Feld '" + name + "' setzen fehlgeschlagen: " + ex.Message)); } } private static object GetMember(object target, string name) { if (target == null) { return null; } return AccessTools.Field(target.GetType(), name)?.GetValue(target); } private static void ExportTemplateTextures() { //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Expected O, but got Unknown //IL_02bb: Unknown result type (might be due to invalid IL or missing references) StatsManager instance = StatsManager.instance; IDictionary dictionary = (((Object)(object)instance != (Object)null) ? (AccessTools.Field(typeof(StatsManager), "itemDictionary")?.GetValue(instance) as IDictionary) : null); string value = TemplateItem.Value; Item val = (Item)((dictionary != null && dictionary.Contains(value)) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val == (Object)null) { Log.LogError((object)("Vorlage-Item nicht gefunden: " + value)); return; } GameObject prefabFromRef = GetPrefabFromRef(AccessTools.Field(typeof(Item), "prefab")?.GetValue(val)); if ((Object)(object)prefabFromRef == (Object)null) { Log.LogError((object)"Prefab der Vorlage nicht gefunden."); return; } MethodInfo methodInfo = AccessTools.TypeByName("UnityEngine.ImageConversion")?.GetMethod("EncodeToPNG", new Type[1] { typeof(Texture2D) }); if (methodInfo == null) { Log.LogError((object)"ImageConversion.EncodeToPNG nicht gefunden."); return; } string text = Path.Combine(Paths.BepInExRootPath, "ReviveAll_textures"); Directory.CreateDirectory(text); HashSet<Texture> hashSet = new HashSet<Texture>(); int num = 0; Renderer[] componentsInChildren = prefabFromRef.GetComponentsInChildren<Renderer>(true); foreach (Renderer val2 in componentsInChildren) { if ((Object)(object)val2 == (Object)null || ((object)val2).GetType().Name == "ParticleSystemRenderer") { continue; } Material[] sharedMaterials = val2.sharedMaterials; foreach (Material val3 in sharedMaterials) { if ((Object)(object)val3 == (Object)null) { continue; } string[] texturePropertyNames = val3.GetTexturePropertyNames(); foreach (string text2 in texturePropertyNames) { Texture texture = val3.GetTexture(text2); if (!((Object)(object)texture == (Object)null) && texture.width >= 2 && texture.height >= 2 && hashSet.Add(texture)) { string text3 = Sanitize(value + "_" + ((Object)val2).name + "_" + ((Object)val3).name + "_" + text2 + "_" + ((Object)texture).name) + ".png"; string path = Path.Combine(text, text3); try { RenderTexture temporary = RenderTexture.GetTemporary(texture.width, texture.height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2); Graphics.Blit(texture, temporary); RenderTexture active = RenderTexture.active; RenderTexture.active = temporary; Texture2D val4 = new Texture2D(texture.width, texture.height, (TextureFormat)4, false); val4.ReadPixels(new Rect(0f, 0f, (float)texture.width, (float)texture.height), 0, 0); val4.Apply(); RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); File.WriteAllBytes(path, (byte[])methodInfo.Invoke(null, new object[1] { val4 })); Object.Destroy((Object)(object)val4); num++; Log.LogInfo((object)$"Textur exportiert: {text3} ({texture.width}x{texture.height}, Material '{((Object)val3).name}', Eigenschaft {text2})"); } catch (Exception ex) { Log.LogWarning((object)("Export fehlgeschlagen für " + ((Object)texture).name + ": " + ex.Message)); } } } } } Log.LogInfo((object)$"{num} Textur(en) nach {text} exportiert."); } private static string Sanitize(string name) { char[] invalidFileNameChars = Path.GetInvalidFileNameChars(); foreach (char oldChar in invalidFileNameChars) { name = name.Replace(oldChar, '_'); } if (name.Length <= 120) { return name; } return name.Substring(0, 120); } private static void DumpInfo() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("== Item-Status =="); stringBuilder.AppendLine("itemDictionary enthält 'Item Revive All': " + ((AccessTools.Field(typeof(StatsManager), "itemDictionary")?.GetValue(StatsManager.instance) as IDictionary)?.Contains("Item Revive All") ?? false)); stringBuilder.AppendLine("Verbrauchte: " + UsedRevives + " Gekaufte: " + Bonus + " Übrig: " + RevivesLeft); string[] array = new string[7] { "PrefabRef", "Value", "ItemToggle", "ItemEquippable", "ItemReviveItem", "REPOLib.Modules.Items", "REPOLib.Modules.NetworkPrefabs" }; foreach (string text in array) { DumpType(stringBuilder, AccessTools.TypeByName(text)); } stringBuilder.AppendLine(); stringBuilder.AppendLine("== REPOLib-Typen =="); Type type = AccessTools.TypeByName("REPOLib.Modules.Items"); if (type != null) { Type[] types = type.Assembly.GetTypes(); foreach (Type type2 in types) { if (type2.IsPublic) { stringBuilder.AppendLine(type2.FullName); } } } string text2 = Path.Combine(Paths.BepInExRootPath, "ReviveAll_dump.txt"); File.WriteAllText(text2, stringBuilder.ToString()); Log.LogInfo((object)("Diagnose geschrieben: " + text2)); } private static void DumpType(StringBuilder sb, Type t) { sb.AppendLine(); if (t == null) { sb.AppendLine("== (Typ nicht gefunden) =="); return; } sb.AppendLine("== " + t.FullName + " : " + ((t.BaseType != null) ? t.BaseType.Name : "-") + " =="); sb.AppendLine("-- Felder --"); FieldInfo[] fields = t.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { sb.AppendLine(" " + fieldInfo.FieldType.Name + " " + fieldInfo.Name); } sb.AppendLine("-- Methoden --"); MethodInfo[] methods = t.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!methodInfo.IsSpecialName) { sb.AppendLine(" " + methodInfo.ReturnType.Name + " " + methodInfo.Name + "(" + string.Join(", ", Array.ConvertAll(methodInfo.GetParameters(), (ParameterInfo p) => p.ParameterType.Name + " " + p.Name)) + ")"); } } } private void SyncRevives() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown //IL_0068: Expected O, but got Unknown syncTimer += Time.deltaTime; if (syncTimer < 1f) { return; } syncTimer = 0f; if (!PhotonNetwork.InRoom || !PhotonNetwork.IsMasterClient) { lastSentLeft = -1; return; } int revivesLeft = RevivesLeft; if (revivesLeft != lastSentLeft) { Hashtable val = new Hashtable(); ((Dictionary<object, object>)val).Add((object)"RA_Left", (object)revivesLeft); Hashtable val2 = val; PhotonNetwork.CurrentRoom.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null); lastSentLeft = revivesLeft; } } internal static bool GetDisplay(out int left) { left = 0; if (!PhotonNetwork.InRoom) { if (!SemiFunc.IsMasterClientOrSingleplayer()) { return false; } left = RevivesLeft; return true; } if (PhotonNetwork.IsMasterClient) { left = RevivesLeft; return true; } if (((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).TryGetValue((object)"RA_Left", out object value)) { left = (int)value; return true; } return false; } } [HarmonyPatch(typeof(StatsManager), "LoadItemsFromFolder")] internal static class CatalogAfterLoad { [HarmonyPostfix] private static void Postfix() { Plugin.TryRegister(); } } [HarmonyPatch] internal static class CatalogBeforeUse { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(ItemManager), "ItemsInitialize", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(ShopManager), "GetAllItemsFromStatsManager", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(ItemManager), "GetPurchasedItems", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(StatsManager), "LoadGame", (Type[])null, (Type[])null); } private static void Prefix() { Plugin.TryRegister(); } } [HarmonyPatch(typeof(StatsManager), "ItemPurchase")] internal static class ItemPurchasePatch { [HarmonyPostfix] private static void Postfix(StatsManager __instance, string itemName) { Plugin.Log.LogInfo((object)("ItemPurchase: " + itemName)); if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } if (itemName == "Item Revive All") { Plugin.Bonus++; Plugin.Log.LogInfo((object)$"Wiederbelebung gekauft, übrig: {Plugin.RevivesLeft}"); } else { if (!(itemName == "Item Revive Start Health")) { return; } Plugin.StartHealthBonus += 10; Plugin.Log.LogInfo((object)$"Revive Start Health gekauft. Zusätzlicher Revive-Startwert: +{Plugin.StartHealthBonus} HP"); } if (AccessTools.Field(typeof(StatsManager), "itemsPurchased")?.GetValue(__instance) is Dictionary<string, int> dictionary && dictionary.ContainsKey(itemName)) { dictionary[itemName] = 0; } } } [HarmonyPatch(typeof(RunManager), "ChangeLevel")] internal static class ChangeLevelPatch { [HarmonyPrefix] private static bool Prefix(RunManager __instance, bool _levelFailed, object[] __args) { if (Plugin.BypassPatch) { return true; } if (!_levelFailed) { return true; } if (Time.time < Plugin.IgnoreUntil) { return false; } if (!SemiFunc.IsMasterClientOrSingleplayer()) { return true; } if (Plugin.RevivesLeft <= 0) { Plugin.ResetCounter(); return true; } if (Plugin.PromptOpen) { return false; } Plugin.PendingRunManager = __instance; Plugin.PendingArgs = __args; Plugin.PromptOpen = true; return false; } } [HarmonyPatch(typeof(GoalUI), "Update")] internal static class GoalHudPatch { [HarmonyPostfix] private static void Postfix(ref TextMeshProUGUI ___Text) { if (!((Object)(object)___Text == (Object)null) && SemiFunc.RunIsLevel() && Plugin.GetDisplay(out var left)) { string text = ((left == 0) ? "#ff3c3c" : "#ff9600"); ((TMP_Text)___Text).text = "<line-height=75%>" + ((TMP_Text)___Text).text + "\n<color=" + text + "><size=28>Revives " + left + "</size></color>"; ((TMP_Text)___Text).alignment = (TextAlignmentOptions)260; } } } [HarmonyPatch(typeof(EnergyUI), "Update")] internal static class EnergyShopHudPatch { [HarmonyPostfix] private static void Postfix(ref TextMeshProUGUI ___Text) { if (!((Object)(object)___Text == (Object)null) && SemiFunc.RunIsShop() && Plugin.GetDisplay(out var left)) { string text = ((left == 0) ? "#ff3c3c" : "#ff9600"); ((TMP_Text)___Text).text = "<line-height=75%>" + ((TMP_Text)___Text).text + "\n<color=" + text + "><size=28>Revives " + left + "</size></color>"; } } } }