Decompiled source of Mimesis PowerUps v0.9.0
Mods/MimesisPowerUps.dll
Decompiled 6 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using System.Threading; using Bifrost.ConstEnum; using Bifrost.Cooked; using DarkTonic.MasterAudio; using DunGen; using HarmonyLib; using MelonLoader; using MelonLoader.Utils; using MimesisPowerUps; using MimesisPowerUps.Core; using MimesisPowerUps.Integration; using MimesisPowerUps.UI; using Mimic; using Mimic.Actors; using Mimic.Audio; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Pathfinding; using ReluProtocol; using ReluProtocol.C2S; using ReluProtocol.Enum; using ReluServerBase.Threading; using Steamworks; using Unity.Cinemachine; using UnityEngine; using UnityEngine.Audio; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.Networking; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(ModEntry), "Mimesis Power-Ups", "0.9.0", "Mirou", null)] [assembly: MelonGame(null, "MIMESIS")] [assembly: AssemblyFileVersion("0.9.0.0")] [assembly: AssemblyVersion("0.9.0.0")] namespace MimesisPowerUps { public sealed class ModEntry : MelonMod { private SessionBridge session; private GuitarMusicController guitar; private DateTime nextError = DateTime.MinValue; public override void OnInitializeMelon() { session = new SessionBridge(delegate(string text2) { ((MelonBase)this).LoggerInstance.Msg(text2); }, ((MelonBase)this).HarmonyInstance); try { string text = Path.Combine(MelonEnvironment.UserDataDirectory, "MimesisPowerUps"); BundledGuitarSongs.Install(Path.GetDirectoryName(typeof(ModEntry).Assembly.Location), text, delegate(string text2) { ((MelonBase)this).LoggerInstance.Msg(text2); }); guitar = new GuitarMusicController(text, delegate(string text2) { ((MelonBase)this).LoggerInstance.Msg(text2); }, session.SendGuitarMessage); guitar.Install(((MelonBase)this).HarmonyInstance); session.GuitarMessageReceived = guitar.Receive; } catch (Exception ex) { if (guitar != null) { guitar.Dispose(); } guitar = null; ((MelonBase)this).LoggerInstance.Warning("Guitare Suno indisponible : " + ex.Message); } ((MelonBase)this).LoggerInstance.Msg("Mimesis Power-Ups 0.9.0 — Par Mirou, développé avec une IA. Cellules de Stats, Prop Hunt et guitare Suno."); } public override void OnUpdate() { try { if (session != null) { session.Update(); } if (guitar != null) { guitar.Update(); } } catch (Exception ex) { if (DateTime.UtcNow >= nextError) { ((MelonBase)this).LoggerInstance.Error(ex.ToString()); nextError = DateTime.UtcNow.AddSeconds(10.0); } } } public override void OnLateUpdate() { if (session != null) { session.LateUpdate(); } if (GameAdapter.Instance != null) { GameAdapter.Instance.EnforceInputCapture(); } } public override void OnGUI() { if (GameAdapter.Instance != null) { GameAdapter.Instance.EnforceInputCapture(); } if (session != null) { session.Draw(); } } public override void OnDeinitializeMelon() { try { if (guitar != null) { guitar.Dispose(); } } finally { if (session != null) { session.Dispose(); } } } } } namespace MimesisPowerUps.Integration { public static class BundledGuitarSongs { private static readonly string[] Names = new string[2] { "Primary Key Guitar.mp3", "Le bout du tunnel Guitar.mp3" }; private static readonly string[] Hashes = new string[2] { "46B3E395C50C7747D2D9FD322651D78FD09A4ED5AA08CBF04C67919D7ADD9C59", "603384832324A309345E37BFE99EF822712ED946F2BBBB20071C7AC42458828C" }; private const long MaximumBytes = 16777216L; public static int Install(string assemblyDirectory, string persistentDataRoot, Action<string> logger) { int num = 0; try { if (string.IsNullOrWhiteSpace(assemblyDirectory) || string.IsNullOrWhiteSpace(persistentDataRoot)) { return 0; } string text = Path.Combine(Path.GetFullPath(assemblyDirectory), "GuitarMusic", "Songs"); if (!Directory.Exists(text)) { return 0; } string text2 = Path.Combine(Path.GetFullPath(persistentDataRoot), "GuitarMusic", "Songs"); for (int i = 0; i < Names.Length; i++) { string text3 = null; try { string text4 = Path.Combine(text2, Names[i]); if (File.Exists(text4)) { continue; } string text5 = Path.Combine(text, Names[i]); if (!File.Exists(text5)) { continue; } FileInfo fileInfo = new FileInfo(text5); if ((fileInfo.Attributes & FileAttributes.ReparsePoint) != FileAttributes.None || fileInfo.Length == 0L || fileInfo.Length > 16777216) { throw new InvalidDataException("Ressource audio invalide."); } Directory.CreateDirectory(text2); text3 = Path.Combine(text2, ".bundled-song-" + Guid.NewGuid().ToString("N") + ".tmp"); File.Copy(text5, text3, overwrite: false); using (FileStream inputStream = new FileStream(text3, FileMode.Open, FileAccess.Read, FileShare.Read)) { using SHA256 sHA = SHA256.Create(); if (!string.Equals(BitConverter.ToString(sHA.ComputeHash(inputStream)).Replace("-", ""), Hashes[i], StringComparison.Ordinal)) { throw new InvalidDataException("Empreinte audio incorrecte."); } } File.Move(text3, text4); text3 = null; num++; } catch (Exception ex) { Log(logger, "Guitare : import du morceau fourni ignoré : " + Names[i] + " (" + ex.GetType().Name + ")."); } finally { if (text3 != null) { try { File.Delete(text3); } catch { } } } } if (num > 0) { Log(logger, "Guitare : " + num + " morceau(x) fourni(s) installé(s)."); } } catch (Exception ex2) { Log(logger, "Guitare : ressources fournies indisponibles (" + ex2.GetType().Name + ")."); } return num; } private static void Log(Action<string> logger, string text) { if (logger == null) { return; } try { logger(text); } catch { } } } internal static class CheatCommandParser { public static bool TryParse(string text, string localPlayerId, IList<PlayerRow> players, IList<CheatItemView> items, out CheatRequest request, out string error) { return TryParse(text, localPlayerId, players, items, null, out request, out error); } public static bool TryParse(string text, string localPlayerId, IList<PlayerRow> players, IList<CheatItemView> items, IList<CheatMonsterView> monsters, out CheatRequest request, out string error) { request = null; error = ""; if (string.IsNullOrWhiteSpace(text)) { error = "Saisis une commande : spawn, xp, stat, cellule ou monstre."; return false; } if (text.Length > 256) { error = "La commande est limitée à 256 caractères."; return false; } foreach (char c in text) { if (char.IsControl(c) && c != '\t') { error = "Utilise une seule ligne pour la commande."; return false; } } string text2 = text.Trim(); if (text2.StartsWith("/", StringComparison.Ordinal)) { text2 = text2.Substring(1); } if (!Tokenize(text2, out var tokens)) { error = "Ferme les guillemets autour des pseudos ou des noms d'objets."; return false; } if (tokens.Count == 0) { error = "Saisis une commande : spawn, xp, stat, cellule ou monstre."; return false; } string text3 = Normalize(tokens[0]); int num; switch (text3) { case "monstre": { if (tokens.Count < 2) { error = "Usage : monstre <identifiant ou nom> ; monstre stop pour revenir au joueur."; return false; } string text4 = string.Join(" ", tokens.GetRange(1, tokens.Count - 1).ToArray()); if (Normalize(text4) == "stop" || Normalize(text4) == "retour") { request = new CheatRequest { Kind = CheatCommandKind.StopMonsterControl }; return true; } if (!ResolveMonster(text4, monsters, out var id2, out error)) { return false; } request = new CheatRequest { Kind = CheatCommandKind.ControlMonster, MonsterId = id2 }; return true; } case "spawn": { if (tokens.Count < 2) { error = "Usage : spawn <identifiant ou nom d'objet>."; return false; } if (!ResolveItem(string.Join(" ", tokens.GetRange(1, tokens.Count - 1).ToArray()), items, out var id, out error)) { return false; } request = new CheatRequest { Kind = CheatCommandKind.SpawnItem, ItemId = id }; return true; } default: num = 3; break; case "stat": num = 4; break; } int num2 = num; if (text3 != "xp" && text3 != "stat" && text3 != "cellule") { error = "Commande inconnue. Utilise spawn, xp, stat, cellule ou monstre."; return false; } if ((text3 == "cellule") ? (tokens.Count < num2) : (tokens.Count != num2)) { error = ((text3 == "stat") ? "Usage : stat <moi, identifiant ou pseudo> <statistique> <valeur>." : ((text3 == "xp") ? "Usage : xp <moi, identifiant ou pseudo> <1 à 1 000 000>." : "Usage : cellule <moi, identifiant ou pseudo> <rareté>.")); error += " Mets un pseudo contenant des espaces entre guillemets."; return false; } if (!ResolvePlayer(tokens[1], localPlayerId, players, out var id3, out error)) { return false; } if (text3 == "xp") { if (!long.TryParse(tokens[2], NumberStyles.None, CultureInfo.InvariantCulture, out var result) || result < 1 || result > 1000000) { error = "L'XP doit être un nombre entier compris entre 1 et 1 000 000."; return false; } request = new CheatRequest { Kind = CheatCommandKind.GrantXp, PlayerId = id3, Xp = result }; return true; } if (text3 == "cellule") { int num3 = ParseRarity(string.Join(" ", tokens.GetRange(2, tokens.Count - 2).ToArray())); if (num3 < 0) { error = "Raretés : commune, peucommune, rare, epic ou legendaire."; return false; } request = new CheatRequest { Kind = CheatCommandKind.GiveCell, PlayerId = id3, RarityIndex = num3 }; return true; } int num4 = ParseStat(tokens[2]); if (num4 < 0) { error = "Statistiques : vie, force, endurance, radiation, vitesse ou capacite."; return false; } NumberStyles style = NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint; if ((!double.TryParse(tokens[3], style, CultureInfo.GetCultureInfo("fr-FR"), out var result2) && !double.TryParse(tokens[3], style, CultureInfo.InvariantCulture, out result2)) || double.IsNaN(result2) || double.IsInfinity(result2)) { error = "La valeur de statistique doit être un nombre fini, par exemple 105 ou 105,5."; return false; } Stat stat = (Stat)num4; double num5 = StatRules.Minimum(stat); double num6 = StatRules.Maximum(stat); if (result2 < num5 || result2 > num6) { error = StatRules.Label(stat) + " : valeur comprise entre " + num5.ToString("0.##", CultureInfo.GetCultureInfo("fr-FR")) + " et " + num6.ToString("0.##", CultureInfo.GetCultureInfo("fr-FR")) + "."; return false; } if (!StatRules.IsPercentage(stat) && result2 != Math.Truncate(result2)) { error = "Les emplacements d'objets utilisent des nombres entiers."; return false; } request = new CheatRequest { Kind = CheatCommandKind.SetStat, PlayerId = id3, StatIndex = num4, StatValue = result2 }; return true; } private static bool ResolvePlayer(string text, string localPlayerId, IList<PlayerRow> players, out string id, out string error) { id = ""; error = ""; string text2 = Normalize(text); bool flag = text2 == "moi"; HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); if (players != null) { foreach (PlayerRow player in players) { if (player != null && !string.IsNullOrEmpty(player.Id) && player.Id == (flag ? localPlayerId : text)) { id = player.Id; return true; } } if (!flag && text2.Length > 0) { foreach (PlayerRow player2 in players) { if (player2 != null && !string.IsNullOrEmpty(player2.Id) && Normalize(player2.Name) == text2) { hashSet.Add(player2.Id); } } } } if (hashSet.Count == 1) { foreach (string item in hashSet) { id = item; } return true; } error = ((hashSet.Count > 1) ? ("Plusieurs joueurs portent ce pseudo. Utilise leur identifiant : " + Sample(hashSet) + ".") : (flag ? "Ton joueur n'est pas encore présent dans la partie." : "Joueur introuvable. Utilise son identifiant ou son pseudo exact entre guillemets.")); return false; } private static bool ResolveItem(string text, IList<CheatItemView> items, out int id, out string error) { id = 0; error = ""; if (int.TryParse(text, NumberStyles.None, CultureInfo.InvariantCulture, out var result)) { if (result > 0 && items != null) { foreach (CheatItemView item in items) { if (item != null && item.Id == result) { id = result; return true; } } } error = "Identifiant d'objet introuvable dans le catalogue."; return false; } string text2 = Normalize(text); if (text2.Length == 0) { error = "Indique un identifiant ou un nom d'objet."; return false; } HashSet<int> hashSet = new HashSet<int>(); if (items != null) { foreach (CheatItemView item2 in items) { if (item2 != null && item2.Id > 0 && Normalize(item2.Name) == text2) { hashSet.Add(item2.Id); } } if (hashSet.Count == 0) { foreach (CheatItemView item3 in items) { if (item3 != null && item3.Id > 0 && Normalize(item3.Name).IndexOf(text2, StringComparison.Ordinal) >= 0) { hashSet.Add(item3.Id); } } } } if (hashSet.Count == 1) { foreach (int item4 in hashSet) { id = item4; } return true; } if (hashSet.Count > 1) { List<string> list = new List<string>(); foreach (int item5 in hashSet) { list.Add(item5.ToString(CultureInfo.InvariantCulture)); } error = "Plusieurs objets correspondent. Utilise un identifiant : " + Sample(list) + "."; } else { error = "Objet introuvable. Choisis un identifiant ou un nom dans le catalogue."; } return false; } private static bool ResolveMonster(string text, IList<CheatMonsterView> monsters, out int id, out string error) { List<CheatItemView> list = new List<CheatItemView>(); if (monsters != null) { foreach (CheatMonsterView monster in monsters) { if (monster != null && monster.Id > 0) { list.Add(new CheatItemView { Id = monster.Id, Name = monster.Name }); } } } if (!ResolveItem(text, list, out id, out error)) { error = error.Replace("objets", "monstres").Replace("objet", "monstre").Replace("Objet", "Monstre"); return false; } foreach (CheatMonsterView monster2 in monsters) { if (monster2 != null && monster2.Id == id && !monster2.CanControl) { id = 0; error = (string.IsNullOrWhiteSpace(monster2.UnavailableReason) ? "Ce monstre ne peut pas être contrôlé dans cette version." : monster2.UnavailableReason); return false; } } return true; } private static string Sample(IEnumerable<string> values) { List<string> list = new List<string>(values); list.Sort(StringComparer.Ordinal); string text = string.Join(", ", list.GetRange(0, Math.Min(3, list.Count)).ToArray()); if (list.Count <= 3) { return text; } return text + "…"; } private static int ParseStat(string value) { switch (Key(value)) { case "vie": case "pv": return 0; case "force": return 1; case "endurance": case "stam": return 2; case "radiation": case "radiations": case "radiationmax": case "radiationmaximale": case "contamination": return 3; case "vitesse": return 4; case "capacite": case "capacitedobjets": case "objets": return 5; default: return -1; } } private static int ParseRarity(string value) { switch (Key(value)) { case "commune": return 0; case "peucommune": return 1; case "rare": return 2; case "epic": case "epique": return 3; case "legendaire": return 4; default: return -1; } } private static string Key(string value) { return Normalize(value).Replace(" ", "").Replace("-", "").Replace("_", "") .Replace("'", "") .Replace("’", ""); } private static string Normalize(string value) { if (string.IsNullOrEmpty(value)) { return ""; } string text; try { text = value.Trim().Normalize(NormalizationForm.FormD); } catch (ArgumentException) { return value.Trim().ToLowerInvariant(); } StringBuilder stringBuilder = new StringBuilder(); string text2 = text; foreach (char c in text2) { UnicodeCategory unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c); if (unicodeCategory != UnicodeCategory.NonSpacingMark && unicodeCategory != UnicodeCategory.SpacingCombiningMark && unicodeCategory != UnicodeCategory.EnclosingMark) { stringBuilder.Append(char.ToLowerInvariant(c)); } } return stringBuilder.ToString().Normalize(NormalizationForm.FormC).Replace("œ", "oe"); } private static bool Tokenize(string text, out List<string> tokens) { tokens = new List<string>(); StringBuilder stringBuilder = new StringBuilder(); bool flag = false; bool flag2 = false; for (int i = 0; i < text.Length; i++) { char c = text[i]; if (c == '"') { flag = !flag; flag2 = true; } else if (c == '\\' && flag && i + 1 < text.Length && (text[i + 1] == '"' || text[i + 1] == '\\')) { stringBuilder.Append(text[++i]); flag2 = true; } else if (char.IsWhiteSpace(c) && !flag) { if (flag2) { tokens.Add(stringBuilder.ToString()); stringBuilder.Length = 0; flag2 = false; } } else { stringBuilder.Append(c); flag2 = true; } } if (flag) { return false; } if (flag2) { tokens.Add(stringBuilder.ToString()); } return true; } } public sealed class CheatItemEntry { public int Id; public string Name = ""; } internal static class CheatGameActions { private static readonly MethodInfo LocalizeItemName = typeof(Hub).GetMethod("GetL10NText", GameAdapter.All, null, new Type[2] { typeof(string), typeof(object[]) }, null); public static List<CheatItemEntry> GetItems() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) List<CheatItemEntry> list = new List<CheatItemEntry>(); try { GameAdapter instance = GameAdapter.Instance; VWorld world = NativeWorld(); if (instance == null || !IsCurrentHostContext(instance, world, instance.SaveKey)) { return list; } ExcelDataManager val = Data(); if (val == null || val.ItemInfoDict == null) { return list; } Enumerator<int, ItemMasterInfo> enumerator = val.ItemInfoDict.GetEnumerator(); try { while (enumerator.MoveNext()) { KeyValuePair<int, ItemMasterInfo> current = enumerator.Current; ItemMasterInfo value = current.Value; if (CanSpawn(value) && current.Key == value.MasterID) { list.Add(new CheatItemEntry { Id = value.MasterID, Name = DisplayName(value) }); } } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } list.Sort(delegate(CheatItemEntry a, CheatItemEntry b) { int num = StringComparer.CurrentCultureIgnoreCase.Compare(a.Name, b.Name); return (num == 0) ? a.Id.CompareTo(b.Id) : num; }); } catch { } return list; } public static void SpawnItem(string expectedSaveKey, int masterId, Action<bool, string> completed) { //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Expected O, but got Unknown int completedOnce = 0; Action<bool, string> finish = delegate(bool success, string message) { if (Interlocked.Exchange(ref completedOnce, 1) != 0 || completed == null) { return; } try { completed(success, message); } catch (Exception ex2) { try { MelonLogger.Warning("Power-Ups : retour de commande d'objet ignoré (" + ex2.GetType().Name + ")."); } catch { } } }; try { GameAdapter adapter = GameAdapter.Instance; VWorld world = NativeWorld(); if (!IsCurrentHostContext(adapter, world, expectedSaveKey)) { finish(arg1: false, "Commande réservée à l'hôte de la partie en cours."); return; } if (masterId <= 0) { finish(arg1: false, "Identifiant d'objet invalide."); return; } ExcelDataManager val = Data(); ItemMasterInfo val2 = ((val == null) ? null : val.GetItemInfo(masterId)); if (!CanSpawn(val2) || val2.MasterID != masterId) { finish(arg1: false, "Cet objet n'existe pas ou ne peut pas apparaître dans le monde."); return; } string actorId = adapter.LocalPlayerId; if (!ulong.TryParse(actorId, NumberStyles.None, CultureInfo.InvariantCulture, out var localSteamId) || localSteamId == 0L) { finish(arg1: false, "Identité de l'hôte indisponible."); return; } VRoomManager manager = world.VRoomManager; CommandExecutor val3 = (CommandExecutor)((manager == null) ? null : /*isinst with value type is only supported in some contexts*/); if (val3 == null) { finish(arg1: false, "Le serveur de la partie n'est pas prêt."); } else if (!val3.Invoke((Command)delegate { //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) try { if (!IsCurrentHostContext(adapter, world, expectedSaveKey) || adapter.LocalPlayerId != actorId) { finish(arg1: false, "La partie a changé. Relance la commande dans la nouvelle partie."); } else { VPlayer host = null; bool ambiguous = false; foreach (IVroom item in Rooms(world)) { item.IterateAllPlayer((Action<VPlayer>)delegate(VPlayer player) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 if (player != null && player.SteamID == localSteamId && player.IsHost && !player.Wasted && (int)((VCreature)player).LifeCycle == 1) { if (host != null && host != player) { ambiguous = true; } else { host = player; } } }); } if (host == null || ambiguous || ((VActor)host).VRoom == null || ((VActor)host).VRoom.RoomManager != manager) { finish(arg1: false, "L'hôte doit être vivant et présent dans une zone prête."); } else { ItemMasterInfo val4 = ((Data() == null) ? null : Data().GetItemInfo(masterId)); if (!CanSpawn(val4) || val4.MasterID != masterId) { finish(arg1: false, "Cet objet ne peut pas apparaître dans le monde."); } else { PosWithRot val5 = ((((VActor)host).Position == null) ? null : ((VActor)host).Position.Clone()); if (val5 == null || !Finite(val5.pos.x) || !Finite(val5.pos.y) || !Finite(val5.pos.z)) { finish(arg1: false, "Position de l'hôte indisponible."); } else { ItemElement newItemElement = ((VActor)host).VRoom.GetNewItemElement(masterId, false, 1, 0, 0, 0); if (newItemElement == null) { finish(arg1: false, "Le jeu n'a pas pu créer cet objet."); } else { int num = ((VActor)host).VRoom.SpawnLootingObject(newItemElement, val5, ((VActor)host).IsIndoor, (ReasonOfSpawn)8, 0, 0, 0L, false, false); finish(num != 0, (num == 0) ? "Le jeu a refusé l'apparition de l'objet." : ("Objet créé : " + DisplayName(val4) + " (" + masterId.ToString(CultureInfo.InvariantCulture) + ").")); } } } } } } catch (Exception ex2) { finish(arg1: false, "Apparition impossible (" + ex2.GetType().Name + ")."); } })) { finish(arg1: false, "Le serveur de la partie est arrêté."); } } catch (Exception ex) { finish(arg1: false, "Commande impossible (" + ex.GetType().Name + ")."); } } private static bool IsCurrentHostContext(GameAdapter adapter, VWorld world, string expectedSaveKey) { if (adapter != null && adapter == GameAdapter.Instance && world != null && world.Running && adapter.IsHost && !string.IsNullOrEmpty(expectedSaveKey) && adapter.SaveKey == expectedSaveKey && NativeWorld() == world) { object obj = GameAdapter.Read(adapter, "world"); return ((obj is VWorld) ? obj : null) == world; } return false; } private static VWorld NativeWorld() { if (!((Object)(object)Hub.s == (Object)null)) { object obj = GameAdapter.Read(Hub.s, "vworld"); return (VWorld)((obj is VWorld) ? obj : null); } return null; } private static ExcelDataManager Data() { if ((Object)(object)Hub.s == (Object)null) { return null; } object obj = GameAdapter.Read(Hub.s, "dataman"); DataManager val = (DataManager)((obj is DataManager) ? obj : null); if (!((Object)(object)val == (Object)null)) { return val.ExcelDataManager; } return null; } private static IEnumerable<IVroom> Rooms(VWorld world) { IDictionary dictionary = ((world == null || world.VRoomManager == null) ? null : (GameAdapter.Read(world.VRoomManager, "_vrooms") as IDictionary)); if (dictionary == null) { yield break; } foreach (DictionaryEntry item in dictionary) { object? value = item.Value; IVroom val = (IVroom)((value is IVroom) ? value : null); if (val != null && val.RoomManager == world.VRoomManager) { yield return val; } } } private static bool CanSpawn(ItemMasterInfo item) { if (item != null && item.MasterID > 0) { return !string.IsNullOrEmpty(item.LootingObjectID); } return false; } private static string DisplayName(ItemMasterInfo item) { string text = item.Name; try { object obj = (((Object)(object)Hub.s == (Object)null) ? null : GameAdapter.Read(Hub.s, "pdata")); if (obj != null) { MethodInfo method = obj.GetType().GetMethod("GetItemDisplayName", GameAdapter.All, null, new Type[2] { typeof(int), typeof(string) }, null); if (method != null) { text = method.Invoke(obj, new object[2] { item.MasterID, text }) as string; } } } catch { } string text2 = TranslateName(text); if (text2 != null) { return text2; } if (!string.Equals(text, item.Name, StringComparison.Ordinal)) { text2 = TranslateName(item.Name); if (text2 != null) { return text2; } } try { string text3 = item.LootingObjectID.Replace('\\', '/'); text3 = text3.Substring(text3.LastIndexOf('/') + 1); if (text3.EndsWith(".prefab", StringComparison.OrdinalIgnoreCase)) { text3 = text3.Substring(0, text3.Length - 7); } string[] array = new string[4] { "equipment_", "miscellnary_", "miscellany_", "consumable_" }; foreach (string text4 in array) { if (text3.StartsWith(text4, StringComparison.OrdinalIgnoreCase)) { text3 = text3.Substring(text4.Length); break; } } text3 = Regex.Replace(text3, "([a-z0-9])([A-Z])", "$1 $2"); text3 = Regex.Replace(text3, "[_\\s-]+", " ").Trim(); if (UsableName(text3) && Regex.IsMatch(text3, "[\\p{L}]")) { return char.ToUpper(text3[0], CultureInfo.CurrentCulture) + text3.Substring(1); } } catch { } int i = item.MasterID; return "Objet " + i.ToString(CultureInfo.InvariantCulture); } private static string TranslateName(string key) { if (string.IsNullOrWhiteSpace(key) || LocalizeItemName == null) { return null; } try { string text = LocalizeItemName.Invoke(null, new object[2] { key, new object[0] }) as string; return UsableName(text) ? Regex.Replace(text, "\\s+", " ").Trim() : null; } catch { return null; } } private static bool UsableName(string value) { if (string.IsNullOrWhiteSpace(value)) { return false; } string text = value.Trim(); if (!text.StartsWith("|L10N error", StringComparison.OrdinalIgnoreCase) && !text.StartsWith("STRING_", StringComparison.OrdinalIgnoreCase)) { return !text.StartsWith("NAME_", StringComparison.OrdinalIgnoreCase); } return false; } private static bool Finite(float value) { if (!float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } } internal static class CustomModeHazards { private static readonly object installGate = new object(); private static readonly FieldInfo levelObjects = AccessTools.Field(typeof(IVroom), "_levelObjects"); private static bool installed; private static bool clientActive; private static float nextClientScan; private static readonly Dictionary<TrapLevelObject, bool> hiddenTraps = new Dictionary<TrapLevelObject, bool>(); internal static bool ClientActive => clientActive; internal static void Install(Harmony harmony) { if (harmony == null) { throw new ArgumentNullException("harmony"); } lock (installGate) { if (installed) { return; } if (levelObjects == null || levelObjects.FieldType != typeof(Dictionary<int, ILevelObjectInfo>)) { throw new MissingFieldException("Native level-object registration changed."); } List<KeyValuePair<MethodInfo, MethodInfo>> list = new List<KeyValuePair<MethodInfo, MethodInfo>>(); try { Patch(harmony, list, typeof(IVroom), "InitLevel", "AfterInitLevel", postfix: true); Patch(harmony, list, typeof(IVroom), "LevelObjectEventInternal", "BeforeTrapEvent", postfix: false); Patch(harmony, list, typeof(IVroom), "ExecuteFieldSkillSpawn", "BeforeMapFieldSpawn", postfix: false); Patch(harmony, list, typeof(IVroom), "CreateFieldSkillObject", "BeforeFieldFactory", postfix: false); Patch(harmony, list, typeof(IVroom), "RunEventActionInternal", "BeforeMapAction", postfix: false); Patch(harmony, list, typeof(ItemElement), "CheckSpawnFieldSkill", "BeforeItemHazard", postfix: false); Patch(harmony, list, typeof(ItemElement), "CheckSpawnFieldSkillWaitPeriod", "BeforeItemHazard", postfix: false); Patch(harmony, list, typeof(TrapLevelObject), "OnAwake", "AfterTrapAwake", postfix: true); CustomModeLootLocks.Install(harmony); installed = true; } catch { foreach (KeyValuePair<MethodInfo, MethodInfo> item in list) { try { harmony.Unpatch((MethodBase)item.Key, item.Value); } catch { } } throw; } } } private static void Patch(Harmony harmony, List<KeyValuePair<MethodInfo, MethodInfo>> hooks, Type type, string name, string patchName, bool postfix) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.DeclaredMethod(type, name, (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.DeclaredMethod(typeof(CustomModeHazards), patchName, (Type[])null, (Type[])null); if (methodInfo == null || methodInfo.IsStatic || methodInfo2 == null) { throw new MissingMethodException("Native custom-room hazard entry changed: " + type.Name + "." + name); } hooks.Add(new KeyValuePair<MethodInfo, MethodInfo>(methodInfo, methodInfo2)); if (postfix) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private static void AfterInitLevel(IVroom __instance) { if (!SurvivalNativeWorld.IsSurvivalRoom(__instance) || !(levelObjects.GetValue(__instance) is Dictionary<int, ILevelObjectInfo> dictionary)) { return; } List<int> list = new List<int>(); foreach (KeyValuePair<int, ILevelObjectInfo> item in dictionary) { if (IsTrap(item.Value)) { list.Add(item.Key); } } foreach (int item2 in list) { dictionary.Remove(item2); } } private static bool IsTrap(ILevelObjectInfo value) { if (value != null) { return value.DataOrigin is TrapLevelObject; } return false; } private static bool BeforeTrapEvent(IVroom __instance, ILevelObjectInfo __0, ref MsgErrorCode __result) { if (!SurvivalNativeWorld.IsSurvivalRoom(__instance) || !IsTrap(__0)) { return true; } __result = (MsgErrorCode)10000001; return false; } private static bool BeforeMapFieldSpawn(IVroom __instance) { return !SurvivalNativeWorld.IsSurvivalRoom(__instance); } private static bool IsPlayerSource(IVroom room, VActor actor) { VPlayer val = (VPlayer)(object)((actor is VPlayer) ? actor : null); if (val != null && ((VActor)val).VRoom == room) { return ((VActor)val).IsAliveStatus(); } return false; } private static bool BeforeFieldFactory(IVroom __instance, ISkillContext __4, ref List<FieldSkillObject> __result) { if (!SurvivalNativeWorld.IsSurvivalRoom(__instance)) { return true; } if (__4 != null && __4.ContextInfo != null && IsPlayerSource(__instance, (VActor)(object)__4.ContextInfo.Creature)) { return true; } __result = new List<FieldSkillObject>(); return false; } private static bool BeforeItemHazard(IVroom __0, VActor __1) { if (SurvivalNativeWorld.IsSurvivalRoom(__0)) { return !(__1 is VLootingObject); } return true; } private static bool BeforeMapAction(IVroom __instance, IGameAction __0, ref bool __result) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) if (!SurvivalNativeWorld.IsSurvivalRoom(__instance)) { return true; } bool flag = __0 is GameActionInstantKill || __0 is GameActionAddAbnormal; GameActionChangeMutableStat val = (GameActionChangeMutableStat)(object)((__0 is GameActionChangeMutableStat) ? __0 : null); if (val != null) { flag |= IsHarmfulStat(val.StatType, val.Value, val.Value); } GameActionChangeMutableStatRandom val2 = (GameActionChangeMutableStatRandom)(object)((__0 is GameActionChangeMutableStatRandom) ? __0 : null); if (val2 != null) { flag |= IsHarmfulStat(val2.StatType, val2.MinValue, val2.MaxValue); } if (!flag) { return true; } __result = true; return false; } private static bool IsHarmfulStat(MutableStatType type, long min, long max) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 if ((int)type != 1 || min >= 0) { if ((int)type == 6) { return max > 0; } return false; } return true; } internal static bool AllowDamage(IVroom room, ApplyDamageArgs args) { if (!SurvivalNativeWorld.IsSurvivalRoom(room) || args == null) { return true; } VActor victim = args.Victim; VPlayer val = (VPlayer)(object)((victim is VPlayer) ? victim : null); if (val == null || ((VActor)val).VRoom != room) { return true; } if (IsPlayerSource(room, args.Attacker)) { return true; } VActor attacker = args.Attacker; FieldSkillObject val2 = (FieldSkillObject)(object)((attacker is FieldSkillObject) ? attacker : null); if (val2 != null && ((VActor)val2).VRoom == room) { return IsPlayerSource(room, val2.CasterActor); } return false; } internal static void UpdateClient(bool active) { if (!active) { clientActive = false; foreach (KeyValuePair<TrapLevelObject, bool> hiddenTrap in hiddenTraps) { if ((Object)(object)hiddenTrap.Key != (Object)null && (Object)(object)((Component)hiddenTrap.Key).gameObject != (Object)null) { ((Component)hiddenTrap.Key).gameObject.SetActive(hiddenTrap.Value); } } hiddenTraps.Clear(); nextClientScan = 0f; return; } bool num = !clientActive; clientActive = true; if (num || !(Time.unscaledTime < nextClientScan)) { nextClientScan = Time.unscaledTime + 1f; TrapLevelObject[] array = Object.FindObjectsOfType<TrapLevelObject>(); for (int i = 0; i < array.Length; i++) { HideTrap(array[i]); } } } private static void AfterTrapAwake(TrapLevelObject __instance) { if (clientActive) { HideTrap(__instance); } } private static void HideTrap(TrapLevelObject trap) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)trap == (Object)null || (Object)(object)((Component)trap).gameObject == (Object)null) { return; } Scene scene = ((Component)trap).gameObject.scene; if (((Scene)(ref scene)).IsValid()) { if (!hiddenTraps.ContainsKey(trap)) { hiddenTraps.Add(trap, ((Component)trap).gameObject.activeSelf); } ((Component)trap).gameObject.SetActive(false); } } } internal static class CustomModeLootLocks { private static readonly object installGate = new object(); private static bool installed; internal static void Install(Harmony harmony) { //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Expected O, but got Unknown if (harmony == null) { throw new ArgumentNullException("harmony"); } lock (installGate) { if (installed) { return; } List<KeyValuePair<MethodInfo, MethodInfo>> list = new List<KeyValuePair<MethodInfo, MethodInfo>>(); try { string[] array = new string[3] { "HandleGrapLootingObject", "HandleUnhangItem", "HandleHangItem" }; foreach (string text in array) { MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(VPlayer), text, new Type[2] { typeof(int), typeof(int) }, (Type[])null); MethodInfo methodInfo2 = AccessTools.DeclaredMethod(typeof(CustomModeLootLocks), "BeforePickup", (Type[])null, (Type[])null); if (methodInfo == null || methodInfo.IsStatic || methodInfo.ReturnType != typeof(MsgErrorCode)) { throw new MissingMethodException("Native custom-room pickup entry changed: " + text); } list.Add(new KeyValuePair<MethodInfo, MethodInfo>(methodInfo, methodInfo2)); harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo methodInfo3 = AccessTools.DeclaredMethod(typeof(LootingLevelObject), "CanGrap", new Type[1] { typeof(ProtoActor) }, (Type[])null); MethodInfo methodInfo4 = AccessTools.DeclaredMethod(typeof(CustomModeLootLocks), "BeforeClientPickup", (Type[])null, (Type[])null); if (methodInfo3 == null || methodInfo3.IsStatic || methodInfo3.ReturnType != typeof(bool)) { throw new MissingMethodException("Native loot interaction feedback changed."); } list.Add(new KeyValuePair<MethodInfo, MethodInfo>(methodInfo3, methodInfo4)); harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(methodInfo4), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); installed = true; } catch { foreach (KeyValuePair<MethodInfo, MethodInfo> item in list) { try { harmony.Unpatch((MethodBase)item.Key, item.Value); } catch { } } throw; } } } private static bool BeforePickup(VPlayer __instance, ref MsgErrorCode __result) { if (__instance == null || !SurvivalNativeWorld.IsSurvivalRoom(((VActor)__instance).VRoom)) { return true; } __result = (MsgErrorCode)20000023; return false; } private static bool BeforeClientPickup(ref bool __result) { if (!CustomModeHazards.ClientActive) { return true; } __result = false; return false; } } public sealed class GamePlayerInfo { public string Id; public string Name; public bool Alive; public bool IsHost; } public sealed class GameAdapter { private sealed class StatOwner { public string Id; } private sealed class SaveCreation { public VWorld World; public VRoomManager Manager; public int Slot; } private readonly IGameSink sink; private readonly object rosterGate = new object(); private readonly ConditionalWeakTable<object, StatOwner> statOwners = new ConditionalWeakTable<object, StatOwner>(); private readonly HashSet<string> diagnostics = new HashSet<string>(); private readonly HashSet<string> begunRooms = new HashSet<string>(); private readonly HashSet<string> endedRooms = new HashSet<string>(); private readonly HashSet<InventoryController> refreshingInventories = new HashSet<InventoryController>(); private readonly object generationGate = new object(); private readonly Dictionary<string, string> generations = new Dictionary<string, string>(); private readonly object runGate = new object(); private readonly HashSet<IVroom> retiredRunRooms = new HashSet<IVroom>(); private readonly HashSet<string> terminatedRoomKeys = new HashSet<string>(StringComparer.Ordinal); private SaveCreation pendingSaveCreation; private VWorld creationInspectedWorld; private VWorld explicitCreationPreviousWorld; private int explicitCreationSlot = -1; private int newGameRequestSlot = -1; private int newGameRequestDepth; private readonly object trainGate = new object(); private GameMainBase loadedTrainMain; private GameMainBase loadingUiMain; private bool trainMembersLoaded; private string trainTransition = ""; private string notifiedTrainTransition = ""; private string worldScope = Guid.NewGuid().ToString("N"); private List<GamePlayerInfo> serverRoster = new List<GamePlayerInfo>(); private readonly HashSet<VPlayer> initializedPlayers = new HashSet<VPlayer>(); private VWorld world; private bool inputCaptured; private bool monsterInputSuppressed; private CursorLockMode cursorBeforeOverlay; private bool cursorVisibleBeforeOverlay; private bool cursorLease; private NativeModalCursorLease nativeModalCursor; private float nextRoster; internal static readonly BindingFlags All = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; public static GameAdapter Instance { get; private set; } internal bool InputCaptured { get { if (!inputCaptured) { return monsterInputSuppressed; } return true; } } internal bool UiInputCaptured => inputCaptured; public bool IsHost { get { if (world != null) { return world.Running; } return false; } } public string LocalPlayerId { get { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) try { return SteamUser.GetSteamID().m_SteamID.ToString(CultureInfo.InvariantCulture); } catch { return ""; } } } public bool IsInShop { get { try { GameMainBase main = Hub.Main; if ((Object)(object)main == (Object)null) { return false; } string text = ((object)main).GetType().Name.ToLowerInvariant(); return text.Contains("maintenance") || text.Contains("maintenence"); } catch { return false; } } } public long Money { get { try { return (!((Object)(object)Hub.Main == (Object)null)) ? Hub.Main.CurrentCurrency : 0; } catch { return 0L; } } } public bool CanRenderModUi { get { try { GameMainBase main = Hub.Main; if ((Object)(object)main == (Object)null || (!(main is InTramWaitingScene) && !(main is GamePlayScene) && !(main is MaintenanceScene) && !(main is DeathMatchScene))) { return false; } if ((Object)(object)main == (Object)(object)loadingUiMain || !main.IsGameLogicStarted || main.IsCrashlandingLoading) { return false; } if ((bool)Read(main, "EnterExitingProcess") || (bool)Read(main, "goBackToMainMenuFlag") || (bool)Read(main, "_returningToMainMenu")) { return false; } UIManager val = (UIManager)(((Object)(object)Hub.s == (Object)null) ? null : /*isinst with value type is only supported in some contexts*/); if ((Object)(object)val == (Object)null) { return false; } UIPrefab_Scene_Loading ui_sceneloading = val.ui_sceneloading; if ((Object)(object)ui_sceneloading != (Object)null && ((Component)ui_sceneloading).gameObject.activeInHierarchy) { return false; } object obj = Read(val, "fadeInImage"); Image val2 = (Image)((obj is Image) ? obj : null); if ((Object)(object)val2 != (Object)null && ((Behaviour)val2).isActiveAndEnabled) { return false; } return true; } catch { return false; } } } public bool CanPresentRewards { get { try { GameMainBase main = Hub.Main; InTramWaitingScene val = (InTramWaitingScene)(object)((main is InTramWaitingScene) ? main : null); if ((Object)(object)val == (Object)null || (Object)(object)val != (Object)(object)loadedTrainMain || !((GameMainBase)val).IsGameLogicStarted) { return false; } if (!(Read(val, "EnteringCompleteAll") is bool) || !(bool)Read(val, "EnteringCompleteAll")) { return false; } if (Read(val, "EnterExitingProcess") is bool && (bool)Read(val, "EnterExitingProcess")) { return false; } if (Read(val, "goBackToMainMenuFlag") is bool && (bool)Read(val, "goBackToMainMenuFlag")) { return false; } if (!IsHost) { return true; } lock (trainGate) { return trainMembersLoaded; } } catch { return false; } } } public string SaveKey { get { try { if (world == null) { return ""; } string text = LocalPlayerId + "-slot-" + world.SaveSlotID.ToString(CultureInfo.InvariantCulture); return text + "-run-" + GetGeneration(text); } catch { return ""; } } } internal void SetMonsterInputSuppressed(bool suppressed) { monsterInputSuppressed = suppressed; } public GameAdapter(IGameSink target) { sink = target; Instance = this; } public void Initialize(Harmony harmony) { GamePatches.Install(harmony); TryFindWorld(); } private void TryFindWorld() { try { VWorld val = (VWorld)(((Object)(object)Hub.s == (Object)null) ? null : /*isinst with value type is only supported in some contexts*/); if (val != world) { RegisterWorld(val); } } catch (Exception ex) { WarnOnce("world", "Monde serveur indisponible : " + ex.Message); } } public void Update() { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown TryFindWorld(); ReconcileNativeModalCursor(); if (Time.unscaledTime >= nextRoster) { nextRoster = Time.unscaledTime + 0.35f; if (IsHost) { VWorld captured = world; try { captured.VRoomManager.Invoke((Command)delegate { SnapshotServerRoster(captured); }); } catch (Exception ex) { WarnOnce("roster", "Lecture des joueurs indisponible : " + ex.Message); } } } NotifyTrainReturnIfReady(); } public List<GamePlayerInfo> GetRoster() { List<GamePlayerInfo> list = new List<GamePlayerInfo>(); try { GameMainBase main = Hub.Main; if ((Object)(object)main != (Object)null) { foreach (ProtoActor allPlayer in main.GetAllPlayers()) { if (!((Object)(object)allPlayer == (Object)null) && allPlayer.steamID != 0L) { list.Add(new GamePlayerInfo { Id = allPlayer.steamID.ToString(CultureInfo.InvariantCulture), Name = allPlayer.nickName, Alive = !allPlayer.dead, IsHost = allPlayer.IsHost }); } } } } catch (Exception ex) { WarnOnce("client-roster", "Liste des joueurs : " + ex.Message); } if (list.Count == 0 && IsHost) { lock (rosterGate) { list = new List<GamePlayerInfo>(serverRoster); } } return (from p in list group p by p.Id into g select g.First()).ToList(); } private static IEnumerable<IVroom> Rooms(VWorld current) { IDictionary dictionary = ((current == null) ? null : (Read(current.VRoomManager, "_vrooms") as IDictionary)); if (dictionary == null) { yield break; } foreach (DictionaryEntry item in dictionary) { object? value = item.Value; IVroom val = (IVroom)((value is IVroom) ? value : null); if (val != null) { yield return val; } } } private void SnapshotServerRoster(VWorld captured) { if (captured == null || captured != world) { return; } List<GamePlayerInfo> list = new List<GamePlayerInfo>(); foreach (IVroom item in Rooms(captured)) { item.IterateAllPlayer((Action<VPlayer>)delegate(VPlayer p) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Invalid comparison between Unknown and I4 if (p.SteamID != 0L) { list.Add(new GamePlayerInfo { Id = Id(p), Name = ((VActor)p).ActorName, Alive = ((int)((VCreature)p).LifeCycle == 1 && !p.Wasted), IsHost = p.IsHost }); bool flag2; lock (rosterGate) { flag2 = !initializedPlayers.Contains(p); } if (flag2 && RefreshPlayer(p)) { lock (rosterGate) { initializedPlayers.Add(p); } } } }); } lock (rosterGate) { serverRoster = (from p in list group p by p.Id into g select g.First()).ToList(); } bool flag = false; foreach (IVroom item2 in Rooms(captured)) { VWaitingRoom val = (VWaitingRoom)(object)((item2 is VWaitingRoom) ? item2 : null); if (val != null) { flag = true; TrainMembersEntered(val); } } if (flag) { return; } lock (trainGate) { trainMembersLoaded = false; } } public void ApplyAllStats() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown VWorld captured = world; if (captured == null || !captured.Running) { return; } try { captured.VRoomManager.Invoke((Command)delegate { if (captured != world) { return; } foreach (IVroom item in Rooms(captured)) { item.IterateAllPlayer((Action<VPlayer>)delegate(VPlayer player) { RefreshPlayer(player); }); } }); } catch (Exception ex) { WarnOnce("apply-stats", "Application des statistiques : " + ex.Message); } } private bool RefreshPlayer(VPlayer player) { //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Invalid comparison between Unknown and I4 try { StatController statControlUnit = ((VActor)player).StatControlUnit; if (statControlUnit == null || ((VActor)player).InventoryControlUnit == null || Read(((VActor)player).InventoryControlUnit, "_inventorySlots") == null) { return false; } object obj = Read(statControlUnit, "StatManager"); RegisterStatManager(obj); object obj2 = Read(obj, "_totalStats"); CommonStats val = (CommonStats)((obj2 is CommonStats) ? obj2 : null); if (val != null) { val.AlteredStatTypes.Add((StatType)1); val.AlteredStatTypes.Add((StatType)7); val.AlteredStatTypes.Add((StatType)4); val.AlteredStatTypes.Add((StatType)5); RefreshRadiationMaximum(obj, val); } if ((int)((VCreature)player).LifeCycle == 1) { long num = Math.Min(statControlUnit.GetCurrentHP(), statControlUnit.GetSpecificStatValue((StatType)1)); long num2 = Math.Min(statControlUnit.GetCurrentStamina(), statControlUnit.GetSpecificStatValue((StatType)7)); Call(obj, "SetMutableStat", (object)(MutableStatType)1, num, null, null); Call(obj, "SetMutableStat", (object)(MutableStatType)7, num2, null, null); } statControlUnit.SyncChangedImmutableStats(); RefreshRadiationCurrent(obj, player); InventoryChanged(((VActor)player).InventoryControlUnit); ((VActor)player).InventoryControlUnit.OnChangeInventory(); return true; } catch (Exception ex) { WarnOnce("refresh-player", "Mise à jour d'un joueur : " + ex.Message); return false; } } public void TrySpend(string playerId, int amount, Action<bool> completed) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown VWorld captured = world; if (amount <= 0 || captured == null || !captured.Running) { completed(obj: false); return; } try { captured.VRoomManager.Invoke((Command)delegate { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Invalid comparison between Unknown and I4 if (captured != world || !captured.Running) { completed(obj: false); } else { bool obj2 = false; try { foreach (IVroom item in Rooms(captured)) { MaintenanceRoom val = (MaintenanceRoom)(object)((item is MaintenanceRoom) ? item : null); if (val != null && !((IVroom)val).IsSessionEnding) { VPlayer buyer = null; ((IVroom)val).IterateAllPlayer((Action<VPlayer>)delegate(VPlayer p) { if (Id(p) == playerId) { buyer = p; } }); if (buyer != null && (int)((VCreature)buyer).LifeCycle == 1 && !buyer.Wasted && ((IVroom)val).Currency >= amount) { val.AddCurrency(-amount); obj2 = true; break; } } } } catch (Exception ex) { WarnOnce("spend", "Achat refusé : " + ex.Message); } completed(obj2); } }); } catch { completed(obj: false); } } public void SetInputCaptured(bool captured) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) if (captured == inputCaptured) { if (captured) { EnforceInputCapture(); } return; } if (captured) { cursorBeforeOverlay = Cursor.lockState; cursorVisibleBeforeOverlay = Cursor.visible; cursorLease = true; inputCaptured = true; EnforceInputCapture(); return; } inputCaptured = false; if (cursorLease) { cursorLease = false; Cursor.lockState = cursorBeforeOverlay; Cursor.visible = cursorVisibleBeforeOverlay; } } public void EnforceInputCapture() { //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (inputCaptured) { if ((int)Cursor.lockState != 0) { Cursor.lockState = (CursorLockMode)0; } if (!Cursor.visible) { Cursor.visible = true; } } } internal void NativeInputCaptureRequested(bool captured) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (inputCaptured && cursorLease) { cursorBeforeOverlay = (CursorLockMode)(captured ? 1 : 0); cursorVisibleBeforeOverlay = !captured && Cursor.visible; } } internal void NativeModalCaptureRequested(bool captured) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (nativeModalCursor == null) { nativeModalCursor = new NativeModalCursorLease(); } nativeModalCursor.ObserveNativeCapture(captured, Hub.Main, (inputCaptured && cursorLease) ? cursorBeforeOverlay : Cursor.lockState, (inputCaptured && cursorLease) ? cursorVisibleBeforeOverlay : Cursor.visible); } internal void ReconcileNativeModalCursor() { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (nativeModalCursor == null) { nativeModalCursor = new NativeModalCursorLease(); } bool modal; bool flag = NativeModalCursorLease.TryReadNativeModal(out modal); if (nativeModalCursor.Reconcile(Hub.Main, flag && CanRenderModUi, Application.isFocused, modal, out var mode, out var shown)) { if (inputCaptured && cursorLease) { cursorBeforeOverlay = mode; cursorVisibleBeforeOverlay = shown; } else { NativeModalCursorLease.Apply(mode, shown); } } if (inputCaptured) { EnforceInputCapture(); } } public unsafe static bool UiKeyDown(KeyCode key) { //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) try { Keyboard current = Keyboard.current; if (current != null) { string text = ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString(); if (text == "Return") { text = "Enter"; } else if (text == "KeypadEnter") { text = "NumpadEnter"; } else if (text.StartsWith("Alpha", StringComparison.Ordinal)) { text = "Digit" + text.Substring(5); } else if (text.StartsWith("Keypad", StringComparison.Ordinal)) { text = "Numpad" + text.Substring(6); } else if (text == "LeftControl") { text = "LeftCtrl"; } else if (text == "RightControl") { text = "RightCtrl"; } if (Enum.TryParse<Key>(text, ignoreCase: true, out Key result) && (int)result != 0) { return ((ButtonControl)current[result]).wasPressedThisFrame; } } } catch { } try { return Input.GetKeyDown(key); } catch { return false; } } internal void RegisterWorld(VWorld value) { lock (runGate) { if (world != value) { retiredRunRooms.Clear(); terminatedRoomKeys.Clear(); lock (begunRooms) { begunRooms.Clear(); endedRooms.Clear(); } lock (rosterGate) { serverRoster.Clear(); initializedPlayers.Clear(); } worldScope = Guid.NewGuid().ToString("N"); lock (trainGate) { trainMembersLoaded = false; trainTransition = ""; notifiedTrainTransition = ""; } } world = value; } } private static string GenerationPath(string slot) { return Path.Combine(MelonEnvironment.UserDataDirectory, "MimesisPowerUps", "Runs", slot + ".run"); } private string GetGeneration(string slot) { lock (generationGate) { if (generations.TryGetValue(slot, out var value)) { return value; } value = "legacy"; string path = GenerationPath(slot); if (File.Exists(path)) { string text = File.ReadAllText(path).Trim(); if (Guid.TryParseExact(text, "N", out var _)) { value = text; } } generations[slot] = value; return value; } } internal void NewGameCreated(int slotID) { RotateGeneration(slotID); } internal void NewGameRequested(int slotID) { lock (runGate) { newGameRequestDepth++; newGameRequestSlot = slotID; } } internal void NewGameRequestEnded() { lock (runGate) { if (newGameRequestDepth > 0) { newGameRequestDepth--; } if (newGameRequestDepth == 0) { newGameRequestSlot = -1; } } } private static VWorld CurrentNativeWorld() { if (!((Object)(object)Hub.s == (Object)null)) { object obj = Read(Hub.s, "vworld"); return (VWorld)((obj is VWorld) ? obj : null); } return null; } internal void MenuRoomCreating() { lock (runGate) { explicitCreationSlot = ((newGameRequestDepth > 0) ? newGameRequestSlot : (-1)); explicitCreationPreviousWorld = CurrentNativeWorld(); } } internal void MaintenanceStarting(VRoomManager manager, int slotID, bool loadFromAutoSave) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Invalid comparison between Unknown and I4 try { lock (runGate) { VWorld val = CurrentNativeWorld(); if (val == null || manager != val.VRoomManager || slotID != val.SaveSlotID || val == creationInspectedWorld) { return; } creationInspectedWorld = val; pendingSaveCreation = null; object obj = Read(manager, "_gameSessionInfo"); GameSessionInfo val2 = (GameSessionInfo)((obj is GameSessionInfo) ? obj : null); if (!(val2 == null || (int)val2.GameSessionState != 1 || loadFromAutoSave) && MMSaveGameData.CheckSaveSlotID(slotID, false)) { PlatformMgr instance = MonoSingleton<PlatformMgr>.Instance; if (!((Object)(object)instance == (Object)null) && ((explicitCreationSlot == slotID && explicitCreationPreviousWorld != val) || !instance.IsSaveFileExist(MMSaveGameData.GetSaveFileName(slotID, false)))) { pendingSaveCreation = new SaveCreation { World = val, Manager = manager, Slot = slotID }; explicitCreationSlot = -1; } } } } catch (Exception ex) { WarnOnce("new-save-probe", "Détection de la nouvelle sauvegarde : " + ex.Message); } } internal void MaintenanceSaved(MaintenanceRoom room, int slotID, bool autoSave, MsgErrorCode result) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (room == null || autoSave || (int)result != 0) { return; } try { lock (runGate) { SaveCreation saveCreation = pendingSaveCreation; VWorld val = CurrentNativeWorld(); if (saveCreation != null && val == saveCreation.World && val.Running && slotID == saveCreation.Slot && slotID == val.SaveSlotID && ((IVroom)room).RoomManager == saveCreation.Manager && val.VRoomManager == saveCreation.Manager) { PlatformMgr instance = MonoSingleton<PlatformMgr>.Instance; if (!((Object)(object)instance == (Object)null) && instance.IsSaveFileExist(MMSaveGameData.GetSaveFileName(slotID, false)) && RotateGeneration(slotID)) { pendingSaveCreation = null; } } } } catch (Exception ex) { WarnOnce("new-save-commit", "Identification de la nouvelle sauvegarde : " + ex.Message); } } internal void NativeSaveLoaded(GameSessionInfo info) { lock (runGate) { if (pendingSaveCreation != null && info != null && Read(pendingSaveCreation.Manager, "_gameSessionInfo") == info) { pendingSaveCreation = null; } } } private bool RotateGeneration(int slotID) { string localPlayerId = LocalPlayerId; if (string.IsNullOrEmpty(localPlayerId)) { return false; } string text = localPlayerId + "-slot-" + slotID.ToString(CultureInfo.InvariantCulture); string text2 = Guid.NewGuid().ToString("N"); lock (generationGate) { generations[text] = text2; try { string text3 = GenerationPath(text); Directory.CreateDirectory(Path.GetDirectoryName(text3)); string text4 = text3 + ".tmp"; File.WriteAllText(text4, text2); if (File.Exists(text3)) { File.Replace(text4, text3, null); } else { File.Move(text4, text3); } } catch (Exception ex) { WarnOnce("new-save-generation", "Identification de la nouvelle partie : " + ex.Message); } } return true; } internal void RunTerminated(VRoomManager manager, RoomDrainInfo drain) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Invalid comparison between Unknown and I4 if (SurvivalNativeWorld.SuppressNormalRunResults) { return; } lock (runGate) { VWorld val = world; if (val == null || !val.Running || manager != val.VRoomManager || drain == null || drain.RoomID <= 0) { return; } object obj = Read(manager, "_gameSessionInfo"); GameSessionInfo val2 = (GameSessionInfo)((obj is GameSessionInfo) ? obj : null); if (val2 == null || (int)val2.GameSessionState != 7) { return; } IVroom val3 = Rooms(val).FirstOrDefault((Func<IVroom, bool>)((IVroom r) => r.RoomID == drain.RoomID)); if (!(val3 is DeathMatchRoom) || retiredRunRooms.Contains(val3)) { return; } string item = val2.CurrentSessionID.ToString(CultureInfo.InvariantCulture) + ":" + drain.RoomID.ToString(CultureInfo.InvariantCulture); if (terminatedRoomKeys.Contains(item) || !RotateGeneration(val.SaveSlotID)) { return; } pendingSaveCreation = null; terminatedRoomKeys.Add(item); foreach (IVroom item2 in Rooms(val)) { if (item2 is DungeonRoom || item2 is DeathMatchRoom) { retiredRunRooms.Add(item2); } } lock (begunRooms) { begunRooms.Clear(); endedRooms.Clear(); } worldScope = Guid.NewGuid().ToString("N"); lock (rosterGate) { initializedPlayers.Clear(); } lock (trainGate) { trainMembersLoaded = false; trainTransition = ""; notifiedTrainTransition = ""; } } } internal void RegisterStatManager(object manager) { if (manager == null) { return; } object obj = Read(manager, "_self"); VPlayer val = (VPlayer)((obj is VPlayer) ? obj : null); object obj2 = Read(manager, "_totalStats"); if (val == null || obj2 == null) { return; } string id; try { if (val.SteamID == 0L) { return; } id = Id(val); } catch { return; } statOwners.GetValue(obj2, (object key) => new StatOwner()).Id = id; } internal long ScaleStat(object totals, StatType type, long original) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Invalid comparison between Unknown and I4 if (!statOwners.TryGetValue(totals, out var value)) { return original; } Stat stat; if ((int)type == 1) { stat = Stat.Health; } else if ((int)type == 7) { stat = Stat.Stamina; } else { if ((int)type != 4 && (int)type != 5) { return original; } stat = Stat.Speed; } return Scale(original, Stats(value.Id).Get(stat)); } internal float ScaleStrength(object growth, float original) { object obj = Read(growth, "_self"); VPlayer val = (VPlayer)((obj is VPlayer) ? obj : null); if (val != null) { return original * (float)(Stats(Id(val)).Strength / 100.0); } return original; } internal long ScaleWeight(object growth, long original) { object obj = Read(growth, "_self"); VPlayer val = (VPlayer)((obj is VPlayer) ? obj : null); if (val != null) { return Scale(original, Stats(Id(val)).Strength); } return original; } private static long Scale(long original, double percent) { if (original <= 0) { return original; } double num = (double)original * percent / 100.0; return Math.Max(1L, (num >= 9.223372036854776E+18) ? long.MaxValue : ((long)Math.Round(num, MidpointRounding.AwayFromZero))); } private StatBlock Stats(string id) { return sink.GetStats(id) ?? new StatBlock(); } internal long ScaleRadiationMaximum(object context, long original) { try { object obj = Read((context is StatController) ? Read(context, "StatManager") : context, "_self"); VPlayer val = (VPlayer)((obj is VPlayer) ? obj : null); if (val == null || val.SteamID == 0L) { return original; } double radiationCapacity = Stats(Id(val)).RadiationCapacity; if (double.IsNaN(radiationCapacity) || double.IsInfinity(radiationCapacity)) { return original; } return Scale(original, Math.Max(50.0, Math.Min(150.0, radiationCapacity))); } catch { return original; } } private void RefreshRadiationMaximum(object manager, CommonStats totals) { DataManager val = (DataManager)(((Object)(object)Hub.s == (Object)null) ? null : /*isinst with value type is only supported in some contexts*/); if (totals != null && !((Object)(object)val == (Object)null) && val.ExcelDataManager != null && totals.elements.TryGetValue((StatType)6, out var value) && value != null) { long c_MaxContaValue = val.ExcelDataManager.Consts.C_MaxContaValue; value.Set(ScaleRadiationMaximum(manager, c_MaxContaValue)); totals.AlteredStatTypes.Add((StatType)6); } } private void RefreshRadiationCurrent(object manager, VPlayer player) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Invalid comparison between Unknown and I4 StatsElement val = (StatsElement)((!(Read(manager, "_mutableStats") is IDictionary dictionary)) ? null : /*isinst with value type is only supported in some contexts*/); if (val != null) { val.Sync(true); if ((int)((VCreature)player).LifeCycle == 1) { Call(manager, "OnChangeMutableStatValue", (object)(MutableStatType)6, val.Value, val.Value, null, null); } Call(manager, "SyncMutableStats"); } } internal static string Id(VPlayer player) { return player.SteamID.ToString(CultureInfo.InvariantCulture); } private bool OwnsRoom(IVroom room) { VWorld val = world; lock (runGate) { return room != null && !SurvivalNativeWorld.IsSurvivalRoom(room) && val != null && val.Running && room.RoomManager == val.VRoomManager && !retiredRunRooms.Contains(room); } } internal void Hit(ApplyDamageArgs args) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Invalid comparison between Unknown and I4 lock (runGate) { if (args != null && args.Damage > 0) { VActor victim = args.Victim; VMonster val = (VMonster)(object)((victim is VMonster) ? victim : null); VActor attacker = args.Attacker; VPlayer val2 = (VPlayer)(object)((attacker is VPlayer) ? attacker : null); if (val != null && val2 != null && val2.SteamID != 0L && !((VCreature)val).HarmBlocked && (int)((VCreature)val).LifeCycle == 1 && ((VActor)val).VRoom is DungeonRoom && OwnsRoom(((VActor)val).VRoom)) { sink.OnHit(MonsterKey(val), ((VActor)val).MasterID, Id(val2)); } } } } internal void MonsterDeath(VMonster monster, ActorDyingSig sig) { lock (runGate) { if (((VActor)monster).VRoom is DungeonRoom && OwnsRoom(((VActor)monster).VRoom)) { VPlayer val = ((sig == null) ? null : ((VActor)monster).VRoom.FindPlayerByObjectID(sig.attackerActorID)); sink.OnMonsterDeath(MonsterKey(monster), ((VActor)monster).MasterID, (val == null) ? null : Id(val)); } } } internal void PlayerDeath(VPlayer player) { lock (runGate) { if (player.SteamID != 0L && ((VActor)player).VRoom is DungeonRoom && OwnsRoom(((VActor)player).VRoom)) { sink.OnPlayerDeath(Id(player)); } } } private string RoomKey(IVroom room) { string text = worldScope; long roomID = room.RoomID; return text + ":" + roomID.ToString(CultureInfo.InvariantCulture); } private string MonsterKey(VMonster monster) { return RoomKey(((VActor)monster).VRoom) + ":" + ((VActor)monster).ObjectID.ToString(CultureInfo.InvariantCulture); } internal void RoomInitialized(DungeonRoom room, bool success) { lock (runGate) { if (!success || !OwnsRoom((IVroom)(object)room)) { return; } lock (trainGate) { trainMembersLoaded = false; } string text = RoomKey((IVroom)(object)room); lock (begunRooms) { if (!begunRooms.Add(text)) { return; } } object instance = Read(room, "_dungeonMasterInfo"); int num = Convert.ToInt32(Read(instance, "HazardLevel"), CultureInfo.InvariantCulture); int num2 = Convert.ToInt32(Read(instance, "RewardLevel"), CultureInfo.InvariantCulture); string text2 = Convert.ToString(Read(instance, "mapName"), CultureInfo.InvariantCulture) ?? ""; bool special = num == 0 && num2 == 0 && text2.IndexOf("JACKPOT", StringComparison.OrdinalIgnoreCase) >= 0; sink.OnExpeditionBegin(text, num, num2, special); } } internal void RoomEnding(DungeonRoom room, DungeonState next) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 lock (runGate) { if (((int)next != 2 && (int)next != 3) || !OwnsRoom((IVroom)(object)room)) { return; } string text = RoomKey((IVroom)(object)room); lock (begunRooms) { if (!endedRooms.Add(text)) { return; } } string[] aliveIds = (from p in ((IVroom)room).GetAlivePlayers() where !p.Wasted && p.SteamID != 0 select p).Select(Id).Distinct().ToArray(); sink.OnExpeditionEnd(text, aliveIds); } } internal void SceneLoading(GameMainBase main) { loadingUiMain = main; if ((Object)(object)main == (Object)(object)loadedTrainMain) { loadedTrainMain = null; } } internal void SceneLoadingEnded(GameMainBase main) { if ((Object)(object)main == (Object)(object)loadingUiMain) { loadingUiMain = null; } if (main is InTramWaitingScene) { loadedTrainMain = main; } } internal void TrainMembersEntered(VWaitingRoom room) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) lock (runGate) { if (!OwnsRoom((IVroom)(object)room)) { return; } bool flag = false; try { int roomTypeMemberCount = world.GetRoomTypeMemberCount(((IVroom)room).Property.vRoomType); HashSet<ulong> loaded = Read(room, "_levelLoadCompleteActorIDs") as HashSet<ulong>; object obj = Read(room, "_startNotified"); List<KeyValuePair<ulong, bool>> members = new List<KeyValuePair<ulong, bool>>(); ((IVroom)room).IterateAllPlayer((Action<VPlayer>)delegate(VPlayer player) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 if (player.SteamID != 0L) { members.Add(new KeyValuePair<ulong, bool>(player.SteamID, (int)((VCreature)player).LifeCycle == 1 && !player.Wasted)); } }); flag = TrainReturnReadiness.AreAllMembersReady(roomTypeMemberCount, loaded, members, obj is bool && (bool)obj, ((IVroom)room).IsSessionEnding); } catch (Exception ex) { WarnOnce("train-members", "Retour au train en attente : " + ex.Message); } string text = RoomKey((IVroom)(object)room) + ":" + ((IVroom)room).CurrentStage.ToString(CultureInfo.InvariantCulture) + ":" + ((IVroom)room).CurrentCycle.ToString(CultureInfo.InvariantCulture); lock (trainGate) { trainMembersLoaded = flag; trainTransition = text; } } } private void NotifyTrainReturnIfReady() { lock (runGate) { if (!IsHost || !CanPresentRewards) { return; } string transitionId; lock (trainGate) { if (!trainMembersLoaded || string.IsNullOrEmpty(trainTransition) || trainTransition == notifiedTrainTransition) { return; } transitionId = (notifiedTrainTransition = trainTransition); } sink.OnTrainReturnReady(transitionId); } } internal bool CanDepartTrain(VWaitingRoom room) { if (!OwnsRoom((IVroom)(object)room)) { return true; } try { return sink.CanDepartTrain(); } catch (Exception ex) { WarnOnce("train-departure", "Départ du train en attente : " + ex.Message); return false; } } internal bool CanUseDepartureLever(ProtoActor actor) { if ((Object)(object)actor == (Object)null || !actor.AmIAvatar() || !(Hub.Main is InTramWaitingScene)) { return true; } try { return sink.CanDepartTrain(); } catch (Exception ex) { WarnOnce("train-lever", "Levier du train en attente : " + ex.Message); return false; } } internal bool CanChangeDepartureLever(IVroom room, ILevelObjectInfo levelObject, int nextState) { VWaitingRoom val = (VWaitingRoom)(object)((room is VWaitingRoom) ? room : null); if (val == null || levelObject == null || !(levelObject.DataOrigin is NewTramLeverLevelObject) || (nextState != 1 && nextState != 2)) { return true; } return CanDepartTrain(val); } internal int AdjustSlotKind(int original, InventoryController inventory, int slot) { object obj = Read(inventory, "_self"); VPlayer val = (VPlayer)((obj is VPlayer) ? obj : null); if (val == null || slot <= 0 || slot == 5 || slot == 6) { return original; } int num = ((slot <= 4) ? slot : (slot - 2)); if (Read(inventory, "_inventorySlots") is IDictionary dictionary && dictionary.Contains(slot) && dictionary[slot] != null) { return 0; } if (num <= Stats(Id(val)).ItemCapacity) { return 0; } return 3; } internal bool IsInventorySlotBlocked(InventoryController inventory, int slot) { return AdjustSlotKind(0, inventory, slot) == 3; } internal int NativeGenericSlotCount(InventoryController inventory) { object obj = Read(inventory, "_self"); VPlayer val = (VPlayer)((obj is VPlayer) ? obj : null); if (val == null) { return 4; } bool flag = Read(inventory, "_inventorySlots") is IDictionary dictionary && dictionary.Contains(7) && dictionary[7] != null; if (!(Stats(Id(val)).ItemCapacity >= 5 || flag)) { return 4; } return 5; } internal bool IsSlotHidden(ProtoActor actor, int slot) { if ((Object)(object)actor == (Object)null || actor.steamID == 0L || slot < 0) { return false; } int num = slot + 1; if (num == 5 || num == 6) { return false; } if (Read(Read(actor, "inventory"), "slotItems") is IList list && slot < list.Count && list[slot] != null) { return false; } return ((num <= 4) ? num : (num - 2)) > Stats(actor.steamID.ToString(CultureInfo.InvariantCulture)).ItemCapacity; } private void RefreshInventory(InventoryController inventory) { if (inventory == null) { return; } object obj = Read(inventory, "_self"); VPlayer val = (VPlayer)((obj is VPlayer) ? obj : null); IDictionary dictionary = Read(inventory, "_inventorySlots") as IDictionary; if (val == null || dictionary == null) { return; } int itemCapacity = Stats(Id(val)).ItemCapacity; if (itemCapacity >= 5 && !dictionary.Contains(7)) { dictionary.Add(7, null); } object[] array = dictionary.Keys.Cast<object>().ToArray(); foreach (object obj2 in array) { int num = Convert.ToInt32(obj2, CultureInfo.InvariantCulture); if (num > 0 && num != 5 && num != 6) { int num2 = ((num <= 4) ? num : (num - 2)); object? obj3 = dictionary[obj2]; ItemElement val2 = (ItemElement)((obj3 is ItemElement) ? obj3 : null); if (num2 > itemCapacity && val2 != null && TryDropOverflow(inventory, val, val2)) { dictionary[obj2] = null; } } } Call(inventory, "SendUpdateInven"); } private bool TryDropOverflow(InventoryController inventory, VPlayer player, ItemElement item) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) if (item.ReserveDestroy || ((VActor)player).VRoom == null) { return false; } try { ((VActor)player).VRoom.CommunicationChannelController.CancelByItem(item.ItemID, (ReasonOfCommunicationChannelCancel)2); Call(inventory, "TurnOffItemElement", item); Call(inventory, "OnTurnOffItem", item); Vector3 val = ((VActor)player).PositionVector; if (world != null) { Vector3 val2 = world.FindNearestPoly(val, 1f); if (!float.IsNaN(val2.x) && !float.IsInfinity(val2.x) && Vector3.Distance(val2, val) < 2f) { val = val2; } } item.SetParent((InventoryController)null); PosWithRot val3 = new PosWithRot { pos = val, rot = Vector3.zero }; if (((VActor)player).VRoom.SpawnLootingObject(item, val3, ((VActor)player).IsIndoor, (ReasonOfSpawn)2, 0, 0, 0L, false, false) != 0) { return true; } item.SetParent(inventory); WarnOnce("overflow-drop", "Objet conservé dans son emplacement : dépôt au sol impossible."); return false; } catch { item.SetParent(inventory); throw; } } internal void InventoryChanged(InventoryController inventory) { object obj = Read(inventory, "_isRecalculatingSlots"); if (obj is bool && (bool)obj) { return; } lock (refreshingInventories) { if (!refreshingInventories.Add(inventory)) { return; } } try { RefreshInventory(inventory); } catch (Exception ex) { WarnOnce("inventory-capacity", "Capacité d'inventaire : " + ex.Message); } finally { lock (refreshingInventories) { refreshingInventories.Remove(inventory); } } } internal static object Read(object instance, string name) { if (instance == null) { return null; } Type type = instance.GetType(); FieldInfo fieldInfo = AccessTools.Field(type, name); if (fieldInfo != null) { return fieldInfo.GetValue(instance); } PropertyInfo propertyInfo = AccessTools.Property(type, name); if (!(propertyInfo == null)) { return propertyInfo.GetValue(instance, null); } return null; } internal static void Write(object instance, string name, object value) { FieldInfo fieldInfo = ((instance == null) ? null : AccessTools.Field(instance.GetType(), name)); if (fieldInfo != null) { fieldInfo.SetValue(instance, value); } } internal static object Call(object instance, string name, params object[] args) { if (instance == null) { return null; } MethodInfo? methodInfo = instance.GetType().GetMethods(All).FirstOrDefault((MethodInfo m) => m.Name == name && m.GetParameters().Length == args.Length); if (methodInfo == null) { throw new MissingMethodException(instance.GetType().FullName, name); } return methodInfo.Invoke(instance, args); } internal void WarnOnce(string key, string message) { lock (diagnostics) { if (!diagnostics.Add(key)) { return; } } MelonLogger.Warning("Power-Ups : " + message); } } internal static class GamePatches { private static int installed; private static GameAdapter Adapter => GameAdapter.Instance; internal static void Install(Harmony harmony) { Patch(harmony, typeof(VWorld), "Initialize", null, "WorldInitialized"); InstallSaveCreationHooks(harmony); try { MonsterAudioPerspective.Install(harmony); } catch (Exception ex) { MelonLogger.Error("Power-Ups : perspective audio du monstre indisponible : " + ex.Message); } try { MonsterSoundCleanup.Install(harmony, delegate(string text) { MelonLogger.Warning(text); }); } catch (Exception ex2) { MelonLogger.Error("Power-Ups : nettoyage audio du monstre indisponible : " + ex2.Message); } try { ShopDiscount.Install(harmony); } catch (Exception ex3) { MelonLogger.Error("Power-Ups : réduction de la boutique indisponible : " + ex3.Message); } Patch(harmony, typeof(StatManager), "LoadAllStat", "StatsLoading", "StatsLoaded"); Patch(harmony, typeof(CommonStats), "GetStatValue", null, "ReadStat"); string[] array = new string[5] { "IsContaExceeded", "ValidateAndClampMutableStat", "SyncMutableStats", "CalcImmutableStats", "InitMutableStats" }; foreach (string method in array) { Patch(harmony, typeof(StatManager), method, null, null, "RadiationMaximumTranspiler"); } Patch(harmony, typeof(StatController), "AdjustConta", null, null, "RadiationMaximumTranspiler"); Patch(harmony, typeof(IVroom), "RecoverAllMemberConta", null, null, "RadiationRecoveryTranspiler"); Patch(harmony, typeof(GrowthController), "GetDamageMultiplier", null, "DamageMultiplier"); Patch(harmony, typeof(GrowthController), "GetWeightSpeedReliefThreshold", null, "WeightThreshold"); Patch(harmony, typeof(StatManager), "OnDamaged", "Damaging", null); Patch(harmony, typeof(VMonster), "OnDying", "MonsterDying", null); Patch(harmony, typeof(VPlayer), "OnDying", "PlayerDying", null); Patch(harmony, typeof(DungeonRoom), "Initialize", null, "DungeonInitialized"); Patch(harmony, typeof(DungeonRoom), "SetDungeonState", "DungeonEnding", null); Patch(harmony, typeof(VRoomManager), "TerminateSession", "RunTerminated", null); Patch(harmony, typeof(VWaitingRoom), "OnAllMemberEntered", null, "TrainMembersEntered"); Patch(harmony, typeof(VWaitingRoom), "OnRequestStartGame", "TrainDeparture", null); Patch(harmony, typeof(VWaitingRoom), "OnRequestEndSession", "TrainDeparture", null); Patch(harmony, typeof(NewTramLeverLevelObject), "TryInteract", "LocalTrainLever", null); Patch(harmony, typeof(IVroom), "LevelObjectEventInternal", "ChangingTrainLever", null); Patch(harmony, typeof(GameMainBase), "StartSceneLoading", "SceneLoading", null); Patch(harmony, typeof(GameMainBase), "EndSceneLoading", null, "SceneLoadingEnded"); Patch(harmony, typeof(GamePlayScene), "IsCameraTargetOutdoor", null, "MonsterCameraOutdoor"); Patch(harmony, typeof(InventoryController), "RecalculateSlotCount", null, "InventoryRecalculated", "InventoryLayoutTranspiler"); Patch(harmony, typeof(InventoryController), "GetSlotKind", null, null, "SlotKindTranspiler"); Patch(harmony, typeof(InventoryController), "IsSlotAvailableFor", null, "InventorySlotAvailable"); Type nestedType = typeof(ProtoActor).GetNestedType("Inventory", BindingFlags.Public | BindingFlags.NonPublic); Patch(harmony, nestedType, "GetVisibleSlotIndices", null, "VisibleInventorySlots"); Type nestedType2 = typeof(ProtoActor).GetNestedType("FakeJumper", BindingFlags.Public | BindingFlags.NonPublic); Patch(harmony, nestedType2, "TryStartJumpByInput", "JumpInput", null); Patch(harmony, typeof(ProtoActor), "IsMoveInputBlocked", null, "MoveInputBlocked"); Patch(harmony, typeof(ProtoActor), "IsJumpInputBlocked", null, "MoveInputBlocked"); Type type = AccessTools.TypeByName("Mimic.InputSystem.InputManager"); Patch(harmony, type, "SetCapturing", "NativeCursorCapture", "NativeCursorUpdated"); Patch(harmony, typeof(UIManager), "OpenInGameMenu", null, "NativeCursorUpdated"); Patch(harmony, typeof(UIManager), "CloseInGameMenu", null, "NativeCursorUpdated"); Patch(harmony, type, "IsCapturing", "NativeInputIsCapturing", null); Patch(harmony, type, "isPressed", "InputButton", null); Patch(harmony, type, "wasPressedThisFrame", "InputButton", null); Patch(harmony, type, "wasRelesedThisFrame", "InputButton", null); Patch(harmony, type, "get_mouseMovement", null, "InputVector"); Patch(harmony, type, "get_gamepadLeftStick", null, "InputVector"); Patch(harmony, type, "get_gamepadRightStick", null, "InputVector"); MelonLogger.Msg("Power-Ups : " + installed + " points d'intégration du jeu chargés."); } private static void InstallSaveCreationHooks(Harmony harmony) { Patch(harmony, typeof(MainMenu), "CreateRoom", "MenuRoomCreating", null); Patch(harmony, typeof(VRoomManager), "InitMaintenenceRoom", "MaintenanceStarting", null); Patch(harmony, typeof(MaintenanceRoom), "SaveGameData", null, "MaintenanceSaved"); Patch(harmony, typeof(GameSessionInfo), "ApplyLoadedGameData", null, "NativeSaveLoaded"); MethodInfo[] methods = typeof(MainMenu).GetMethods(GameAdapter.All); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == "CreateNewGameInSlot") { try { harmony.Patch((MethodBase)methodInfo, Hook("NewGameRequested"), (HarmonyMethod)null, (HarmonyMethod)null, Hook("NewGameRequestEnded"), (HarmonyMethod)null); installed++; } catch (Exception ex) { MelonLogger.Warning("Power-Ups : détection nouvelle partie : " + ex.Message); } } } } private static void Patch(Harmony harmony, Type type, string method, string prefix, string postfix, string transpiler = null) { if (type == null) { MelonLogger.Warning("Power-Ups : type manquant pour " + method); return; } MethodInfo methodInfo = AccessTools.DeclaredMethod(type, method, (Type[])null, (Type[])null); if (methodInfo == null) { methodInfo = AccessTools.Method(type, method, (Type[])null, (Type[])null); } if (methodInfo == null) { MelonLogger.Warning("Power-Ups : méthode manquante " + type.FullName + "." + method); return; } try { harmony.Patch((MethodBase)methodInfo, Hook(prefix), Hook(postfix), Hook(transpiler), (HarmonyMethod)null, (HarmonyMethod)null); installed++; } catch (Exception ex) { MelonLogger.Error("Power-Ups : intégration impossible pour " + type.FullName + "." + method + " : " + ex.Message); } } private static HarmonyMethod Hook(string name) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown if (name != null) { return new HarmonyMethod(typeof(GamePatches), name, (Type[])null); } return null; } private static void WorldInitialized(VWorld __instance) { if (Adapter != null) { Adapter.RegisterWorld(__instance); } } private static void NewGameRequested(int __1) { if (Adapter != null) { Adapter.NewGameRequested(__1); } } private static Exception NewGameRequestEnded(Exception __exception) { if (Adapter != null) { Adapter.NewGameRequestEnded(); } return __exception; } private static void MenuRoomCreating() { if (Adapter != null) { Adapter.MenuRoomCreating(); } } private static void MaintenanceStarting(VRoomManager __instance, int __1, bool __2) { if (Adapter != null) { Adapter.MaintenanceStarting(__instance, __1, __2); } } private static void MaintenanceSaved(MaintenanceRoom __instance, int __0, bool __2, MsgErrorCode __result) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (Adapter != null) { Adapter.MaintenanceSaved(__instance, __0, __2, __result); } } private static void NativeSaveLoaded(GameSessionInfo __instance) { if (Adapter != null) { Adapter.NativeSaveLoaded(__instance); } } private static void StatsLoading(StatManager __instance) { if (Adapter != null) { Adapter.RegisterStatManager(__instance); } } private static void StatsLoaded(StatManager __instance) { if (Adapter != null) { Adapter.RegisterStatManager(__instance); } } private static void ReadStat(CommonStats __instance, StatType __0, ref long __result) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (Adapter != null) { __result = Adapter.ScaleStat(__instance, __0, __result); } } private static void DamageMultiplier(GrowthController __instance, ref float __result) { if (Adapter != null) { __result = Adapter.ScaleStrength(__instance, __result); } } private static void WeightThreshold(GrowthController __instance, ref long __result) { if (Adapter != null) { __result = Adapter.ScaleWeight(__instance, __result); } } private static void Damaging(ApplyDamageArgs __0) { if (Adapter != null) { Adapter.Hit(__0); } } private static void MonsterDying(VMonster __instance, ActorDyingSig __0) { if (Adapter != null) { Adapter.MonsterDeath(__instance, __0); } } private static void PlayerDying(VPlayer __instance) { if (Adapter != null) { Adapter.PlayerDeath(__instance); } } private static void DungeonInitialized(DungeonRoom __instance, bool __result) { if (Adapter != null) { Adapter.RoomInitialized(__instance, __result); } } private static void DungeonEnding(DungeonRoom __instance, DungeonState __0) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (Adapter != null) { Adapter.RoomEnding(__instance, __0); } } private static void RunTerminated(VRoomManager __instance, RoomDrainInfo __1) { if (Adapter != null) { Adapter.RunTerminated(__instance, __1); } } private static void TrainMembersEntered(VWaitingRoom __instance) { if (Adapter != null) { Adapter.TrainMembersEntered(__instance); } } private static void SceneLoading(GameMainBase __instance) { if (Adapter != null) { Adapter.SceneLoading(__instance); } } private static void SceneLoadingEnded(GameMainBase __instance) { if (Adapter != null) { Adapter.SceneLoadingEnded(__instance); } } private static bool TrainDeparture(VWaitingRoom __instance, ref MsgErrorCode __result) { if (Adapter == null || Adapter.CanDepartTrain(__instance)) { return true; } __result = (MsgErrorCode)20000024; return false; } private static bool LocalTrainLever(ProtoActor __0, ref bool __result) { if (Adapter == null || Adapter.CanUseDepartureLever(__0)) { return true; } __result = false; return false; } private static bool ChangingTrainLever(IVroom __instance, ILevelObjectInfo __0, int __3, ref MsgErrorCode __result) { if (Adapter == null || Adapter.CanChangeDepartureLever(__instance, __0, __3)) { return true; } __result = (MsgErrorCode)20000024; return false; } private static void InventoryRecalculated(InventoryController __instance) { if (Adapter != null) { Adapter.InventoryChanged(__instance); } } private static void InventorySlotAvailable(InventoryController __instance, int __0, ref bool __result) { if (__result && Adapter != null && Adapter.IsInventorySlotBlocked(__instance, __0)) { __result = false; } } private static IEnumerable<CodeInstruction> SlotKindTranspiler(IEnumerable<CodeInstruction> instructions) { MethodInfo adjust = AccessTools.Method(typeof(GamePatches), "AdjustSlotKind", (Type[])null, (Type[])null); foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Ret) { CodeInstruction val = new CodeInstruction(OpCodes.Ldarg_0, (object)null); MoveLabels(instruction, val); yield return val; yield return new CodeInstruction(OpCodes.Ldarg_1, (object)null); yield return new CodeInstruction(OpCodes.Call, (object)adjust); } yield return instruction; } } private static int AdjustSlotKind(int kind, InventoryController inventory, int slot) { if (Adapter != null) { return Adapter.AdjustSlotKind(kind, inventory, slot); } return kind; } private static void MoveLabels(CodeInstruction from, CodeInstruction to) { FieldInfo? field = typeof(CodeInstruction).GetField("labels"); IList list = field.GetValue(from) as IList; IList list2 = field.GetValue(to) as IList; if (list == null || list2 == null) { return; } foreach (object item in list) { list2.Add(item); } list.Clear(); } private static IEnumerable<CodeInstruction> InventoryLayoutTranspiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> codes = new List<CodeInstruction>(instructions); MethodInfo helper = AccessTools.Method(typeof(GamePatches), "NativeGenericSlotCount", (Type[])null, (Type[])null); bool replaced = false; for (int i = 0; i < codes.Count; i++) { if (!replaced && codes[i].opcode == OpCodes.Ldc_I4_4 && i + 2 < codes.Count && codes[i + 1].opcode == OpCodes.Ldarg_0) { MethodInfo methodInfo = codes[i + 2].operand as MethodInfo; if (methodInfo != null && methodInfo.Name == "GetDedicatedSlotCount") { CodeInstruction val = new CodeInstruction(OpCodes.Ldarg_0, (object)null); MoveLabels(codes[i], val); yield return val; yield return new CodeInstruction(OpCodes.Call, (object)helper); replaced = true; continue; } } yield return codes[i]; } if (!replaced) { MelonLogger.Warning("Power-Ups : disposition native de l'inventaire non reconnue; cinquième emplacement à vérifier."); } } private static int NativeGenericSlotCount(InventoryController inventory) { if (Adapter != null) { return Adapter.NativeGenericSlotCount(inventory); } return 4; } private static void VisibleInventorySlots(object __instance, ref List<int> __result) { if (Adapter == null || __result == null) { return; } object obj = GameAdapter.Read(__instance, "owner"); ProtoActor val = (ProtoActor)((obj is ProtoActor) ? obj : null); if ((Object)(object)val == (Object)null || val.steamID == 0L) { return; } List<int> list = new List<int>(); foreach (int item in __result) { if (!Adapter.IsSlotHidden(val, item)) {