Decompiled source of LycansRoles v1.0.2
plugins/LycansMod.Roles.dll
Decompiled an hour 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.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Logging; using Fusion; using LycansMods.Shared; using Microsoft.CodeAnalysis; using On; using TMPro; using UnityEngine; using UnityEngine.Localization; using UnityEngine.Localization.Settings; using UnityEngine.Localization.Tables; using UnityEngine.Networking; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("LycansMod.Roles")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("LycansMod.Roles")] [assembly: AssemblyTitle("LycansMod.Roles")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } [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 LycansMods.Shared { public static class ActionRequests { private const string HandlersKey = "lycans.mods.actions.handlers"; private const string SendKey = "lycans.mods.actions.send"; public static void Register(string action, Action<PlayerController, int, Vector3> handler) { Handlers()[ModProposals.Hash(action)] = handler; } public static bool Request(string action, PlayerController actor, int value, Vector3 position = default(Vector3)) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) return Send(broadcast: false, action, actor, value, position); } public static bool Broadcast(string action, PlayerController actor, int value, Vector3 position = default(Vector3)) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) return Send(broadcast: true, action, actor, value, position); } public static bool ShouldSendFrom(PlayerController actor) { if ((Object)(object)actor != (Object)null && ((SimulationBehaviour)actor).HasInputAuthority && (Object)(object)((SimulationBehaviour)actor).Runner != (Object)null) { return ((SimulationBehaviour)actor).Runner.IsForward; } return false; } public static void PublishSender(Action<bool, int, int, int, Vector3> send) { AppDomain.CurrentDomain.SetData("lycans.mods.actions.send", send); } public static void Dispatch(int hash, int actorIndex, int value, Vector3 position) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) if (!Handlers().TryGetValue(hash, out var value2)) { Log.Warning("[ActionRequests] Action inconnue (" + hash + ") : mod absent chez ce joueur ?"); return; } PlayerController actor = null; PlayerRegistry.ForEach((Action<PlayerController>)delegate(PlayerController p) { if ((Object)(object)actor == (Object)null && (Object)(object)p != (Object)null && p.Index == actorIndex) { actor = p; } }); try { value2(actor, value, position); } catch (Exception ex) { Log.Error("[ActionRequests] Action en erreur : " + ex); } } private static bool Send(bool broadcast, string action, PlayerController actor, int value, Vector3 position) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) if (!(AppDomain.CurrentDomain.GetData("lycans.mods.actions.send") is Action<bool, int, int, int, Vector3> action2)) { Log.Warning("[ActionRequests] « " + action + " » ignorée : mod_core absent."); return false; } action2(broadcast, ModProposals.Hash(action), ((Object)(object)actor != (Object)null) ? actor.Index : (-1), value, position); return true; } private static Dictionary<int, Action<PlayerController, int, Vector3>> Handlers() { if (AppDomain.CurrentDomain.GetData("lycans.mods.actions.handlers") is Dictionary<int, Action<PlayerController, int, Vector3>> result) { return result; } Dictionary<int, Action<PlayerController, int, Vector3>> dictionary = new Dictionary<int, Action<PlayerController, int, Vector3>>(); AppDomain.CurrentDomain.SetData("lycans.mods.actions.handlers", dictionary); return dictionary; } } public static class AdminCommands { private const string Key = "lycans.mods.admin.commands"; public static void Register(string category, string label, Action run, Func<bool> available = null) { List<object[]> list = All(); lock (list) { list.Add(new object[4] { category, label, run, available }); } } public static List<object[]> All() { if (AppDomain.CurrentDomain.GetData("lycans.mods.admin.commands") is List<object[]> result) { return result; } List<object[]> list = new List<object[]>(); AppDomain.CurrentDomain.SetData("lycans.mods.admin.commands", list); return list; } } public static class AudioBank { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static hook_Spawned <>9__3_0; internal void <LoadEmbedded>b__3_0(orig_Spawned orig, GameManager self) { orig.Invoke(self); if (_loaded) { return; } _loaded = true; string[] manifestResourceNames = _assembly.GetManifestResourceNames(); foreach (string text in manifestResourceNames) { if (text.StartsWith("LycansAudio.", StringComparison.Ordinal)) { ((MonoBehaviour)self).StartCoroutine(Load(text)); } } } } public const string ResourcePrefix = "LycansAudio."; private static Assembly _assembly; private static bool _loaded; public static void LoadEmbedded(Assembly assembly) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown if (_assembly != null) { return; } _assembly = assembly; object obj = <>c.<>9__3_0; if (obj == null) { hook_Spawned val = delegate(orig_Spawned orig, GameManager self) { orig.Invoke(self); if (!_loaded) { _loaded = true; string[] manifestResourceNames = _assembly.GetManifestResourceNames(); foreach (string text in manifestResourceNames) { if (text.StartsWith("LycansAudio.", StringComparison.Ordinal)) { ((MonoBehaviour)self).StartCoroutine(Load(text)); } } } }; <>c.<>9__3_0 = val; obj = (object)val; } GameManager.Spawned += (hook_Spawned)obj; } private static IEnumerator Load(string resource) { string fileName = resource.Substring("LycansAudio.".Length); string text2; try { string text = Path.Combine(Path.GetTempPath(), "LycansModsAudio"); Directory.CreateDirectory(text); text2 = Path.Combine(text, fileName); using Stream stream = _assembly.GetManifestResourceStream(resource); using FileStream destination = File.Create(text2); stream.CopyTo(destination); } catch (Exception ex) { Log.Error("[AudioBank] Extraction impossible de " + fileName + " : " + ex.Message); yield break; } string name = Path.GetFileNameWithoutExtension(fileName); bool split = name.EndsWith("__split", StringComparison.OrdinalIgnoreCase); UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip("file://" + text2.Replace("\\", "/"), TypeOf(text2)); try { if (split) { DownloadHandler downloadHandler = request.downloadHandler; DownloadHandlerAudioClip val = (DownloadHandlerAudioClip)(object)((downloadHandler is DownloadHandlerAudioClip) ? downloadHandler : null); if (val != null) { val.streamAudio = false; } } yield return request.SendWebRequest(); if ((int)request.result != 1) { Log.Error("[AudioBank] Lecture impossible de " + fileName + " : " + request.error); yield break; } AudioClip content = DownloadHandlerAudioClip.GetContent(request); AudioManager instance = AudioManager.Instance; if ((Object)(object)content == (Object)null || instance?.soundBank?.dictionary == null) { Log.Error("[AudioBank] " + fileName + " : son ou banque de sons du jeu indisponible."); yield break; } if (split) { AddSplit(instance, content, name.Substring(0, name.Length - "__split".Length).ToUpperInvariant()); yield break; } string text3 = (((Object)content).name = name.ToUpperInvariant()); instance.soundBank.dictionary[text3] = content; Log.Info("[AudioBank] Son « " + text3 + " » ajouté."); } finally { ((IDisposable)request)?.Dispose(); } } private static void AddSplit(AudioManager audio, AudioClip clip, string baseKey) { int num = Math.Max(1, clip.channels); float[] array = new float[clip.samples * num]; clip.GetData(array, 0); List<int[]> list = DetectSegments(array, num, clip.frequency); if (list.Count == 0) { ((Object)clip).name = baseKey; audio.soundBank.dictionary[baseKey] = clip; Log.Warning("[AudioBank] « " + baseKey + " » : aucun segment, son entier ajouté."); return; } for (int i = 0; i < list.Count; i++) { int num2 = list[i][0]; int num3 = list[i][1] - list[i][0]; float[] array2 = new float[num3 * num]; Array.Copy(array, num2 * num, array2, 0, num3 * num); string text = baseKey + "_" + (i + 1); AudioClip val = AudioClip.Create(text, num3, num, clip.frequency, false); val.SetData(array2, 0); audio.soundBank.dictionary[text] = val; } Log.Info("[AudioBank] « " + baseKey + " » découpé en " + list.Count + " son(s)."); } private static List<int[]> DetectSegments(float[] data, int channels, int frequency) { int num = data.Length / channels; float num2 = 0f; foreach (float num3 in data) { num2 = Mathf.Max(num2, Mathf.Abs(num3)); } float num4 = Mathf.Max(0.02f, num2 * 0.08f); int num5 = Mathf.Max(1, (int)((float)frequency * 0.12f)); int minSegment = Mathf.Max(1, (int)((float)frequency * 0.05f)); int pad = (int)((float)frequency * 0.02f); List<int[]> list = new List<int[]>(); bool flag = false; int start = 0; int num6 = 0; for (int j = 0; j < num; j++) { float num7 = 0f; for (int k = 0; k < channels; k++) { num7 = Mathf.Max(num7, Mathf.Abs(data[j * channels + k])); } if (num7 >= num4) { if (!flag) { flag = true; start = j; } num6 = 0; } else if (flag && ++num6 >= num5) { AddSegment(list, start, j - num6 + 1, num, minSegment, pad); flag = false; } } if (flag) { AddSegment(list, start, num, num, minSegment, pad); } return list; } private static void AddSegment(List<int[]> segments, int start, int end, int frames, int minSegment, int pad) { start = Math.Max(0, start - pad); end = Math.Min(frames, end + pad); if (end - start >= minSegment) { segments.Add(new int[2] { start, end }); } } private static AudioType TypeOf(string path) { return (AudioType)(Path.GetExtension(path).ToLowerInvariant() switch { ".mp3" => 13, ".ogg" => 14, ".wav" => 20, _ => 0, }); } } public enum CanMoveDecision { NoOpinion, Allow, Deny } public static class CanMoveRules { public const string Method = "PlayerController.IsCanMove"; private const string DecisionKey = "decision"; private static readonly object[] Boxed = new object[3] { 0, 1, 2 }; public static void Decide(int priority, string owner, Func<PlayerController, CanMoveDecision> step) { HookPipeline.Register("PlayerController.IsCanMove", priority, owner, HookPhase.Before, delegate(IDictionary<string, object> data) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown CanMoveDecision canMoveDecision = step((PlayerController)data["player"]); if (canMoveDecision != CanMoveDecision.NoOpinion) { data["decision"] = Boxed[(int)canMoveDecision]; data["cancel"] = HookPipeline.True; } }); } public static IDictionary<string, object> NewData() { return new Dictionary<string, object>(); } public static int Run(IDictionary<string, object> data, PlayerController player) { data["player"] = player; data["decision"] = Boxed[0]; data["cancel"] = HookPipeline.False; HookPipeline.RunBefore("PlayerController.IsCanMove", data); return (int)data["decision"]; } } public static class CursorControl { private const string CountKey = "lycans.mods.cursor.count"; private const string PreviousKey = "lycans.mods.cursor.previous"; private static readonly object Lock = new object(); private static int Count { get { object data = AppDomain.CurrentDomain.GetData("lycans.mods.cursor.count"); if (data is int) { return (int)data; } return 0; } } public static void Request() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Invalid comparison between Unknown and I4 lock (Lock) { int count = Count; if (count == 0) { AppDomain.CurrentDomain.SetData("lycans.mods.cursor.previous", new bool[2] { Cursor.visible, (int)Cursor.lockState == 1 }); Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; Log.Info("[CursorControl] Curseur libéré (premier panneau ouvert)."); } AppDomain.CurrentDomain.SetData("lycans.mods.cursor.count", count + 1); } } public static void Release() { lock (Lock) { int num = Math.Max(0, Count - 1); AppDomain.CurrentDomain.SetData("lycans.mods.cursor.count", num); if (num == 0) { if (AppDomain.CurrentDomain.GetData("lycans.mods.cursor.previous") is bool[] array && array.Length == 2) { Cursor.visible = array[0]; Cursor.lockState = (CursorLockMode)(array[1] ? 1 : 0); } Log.Info("[CursorControl] Curseur restauré (dernier panneau fermé)."); } } } } public static class CustomAnimations { private const string DefinitionsKey = "lycans.mods.animations.definitions"; private const string AnimatorsKey = "lycans.mods.animations.animators"; private const string PlayKey = "lycans.mods.animations.play"; private const string StopKey = "lycans.mods.animations.stop"; private const string PlayingKey = "lycans.mods.animations.playing"; public static IEnumerable<string> Ids => Definitions().Keys; public static void Define(string id, AnimationClip[] clips, int holdIndex = -1) { if (string.IsNullOrEmpty(id) || clips == null || clips.Length == 0 || Array.IndexOf(clips, null) >= 0) { Log.Warning("[CustomAnimations] « " + id + " » ignorée : clip manquant."); return; } Definitions()[id] = new object[2] { clips, holdIndex }; } public static void Play(PlayerController player, string id) { if ((Object)(object)player != (Object)null && AppDomain.CurrentDomain.GetData("lycans.mods.animations.play") is Action<PlayerController, string> action) { action(player, id); } } public static void Stop(PlayerController player) { if ((Object)(object)player != (Object)null && AppDomain.CurrentDomain.GetData("lycans.mods.animations.stop") is Action<PlayerController> action) { action(player); } } public static bool IsPlaying(PlayerController player) { if ((Object)(object)player != (Object)null && AppDomain.CurrentDomain.GetData("lycans.mods.animations.playing") is Func<PlayerController, bool> func) { return func(player); } return false; } public static void RegisterExtraAnimator(string key, Func<PlayerController, Animator> animator) { Animators()[key] = animator; } public static void PublishImplementation(Action<PlayerController, string> play, Action<PlayerController> stop, Func<PlayerController, bool> playing) { AppDomain.CurrentDomain.SetData("lycans.mods.animations.play", play); AppDomain.CurrentDomain.SetData("lycans.mods.animations.stop", stop); AppDomain.CurrentDomain.SetData("lycans.mods.animations.playing", playing); } public static SortedDictionary<string, object[]> Definitions() { return GetOrCreate<SortedDictionary<string, object[]>>("lycans.mods.animations.definitions"); } public static Dictionary<string, Func<PlayerController, Animator>> Animators() { return GetOrCreate<Dictionary<string, Func<PlayerController, Animator>>>("lycans.mods.animations.animators"); } private static T GetOrCreate<T>(string key) where T : class, new() { if (AppDomain.CurrentDomain.GetData(key) is T result) { return result; } T val = new T(); AppDomain.CurrentDomain.SetData(key, val); return val; } } public static class CustomEffects { private const string DefinitionsKey = "lycans.mods.effects.definitions"; private const string ApplyKey = "lycans.mods.effects.apply"; public static void Define(string key, Type effectType, Func<bool> enabled, Func<float> duration, Action<PlayerController, bool> onDrink = null) { Definitions()[key] = new object[4] { effectType, enabled, duration, onDrink }; } public static void Apply(string key, PlayerController target, float duration) { if ((Object)(object)target != (Object)null && AppDomain.CurrentDomain.GetData("lycans.mods.effects.apply") is Action<string, PlayerController, float> action) { action(key, target, duration); } } public static void PublishApply(Action<string, PlayerController, float> apply) { AppDomain.CurrentDomain.SetData("lycans.mods.effects.apply", apply); } public static SortedDictionary<string, object[]> Definitions() { if (AppDomain.CurrentDomain.GetData("lycans.mods.effects.definitions") is SortedDictionary<string, object[]> result) { return result; } SortedDictionary<string, object[]> sortedDictionary = new SortedDictionary<string, object[]>(StringComparer.Ordinal); AppDomain.CurrentDomain.SetData("lycans.mods.effects.definitions", sortedDictionary); return sortedDictionary; } } public sealed class PotionPoolContext { private readonly IDictionary<string, object> _data; public List<Effect> NativeEffects => (List<Effect>)_data["native"]; internal PotionPoolContext(IDictionary<string, object> data) { _data = data; } } public static class PotionRules { public const string Method = "GameManager.GenerateEffects"; public static void Before(int priority, string owner, Action<PotionPoolContext> step) { HookPipeline.Register("GameManager.GenerateEffects", priority, owner, HookPhase.Before, delegate(IDictionary<string, object> data) { step(new PotionPoolContext(data)); }); } public static IDictionary<string, object> NewData(List<Effect> native) { return new Dictionary<string, object> { ["native"] = native, ["cancel"] = HookPipeline.False }; } } public static class CustomItems { private const string DefinitionsKey = "lycans.mods.items.definitions"; private const string SpawnKey = "lycans.mods.items.spawn"; public static void Define(string key, Type itemType, Func<GameObject> visual, float visualScale, Func<bool> enabled) { Definitions()[key] = new object[4] { itemType, visual, visualScale, enabled }; } public static Item Spawn(string key, Vector3 position, Quaternion rotation) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (!(AppDomain.CurrentDomain.GetData("lycans.mods.items.spawn") is Func<string, Vector3, Quaternion, Item> func)) { return null; } return func(key, position, rotation); } public static string KeyOf(Item item) { if ((Object)(object)item == (Object)null) { return null; } foreach (KeyValuePair<string, object[]> item2 in Definitions()) { if ((Type)item2.Value[0] == ((object)item).GetType()) { return item2.Key; } } return null; } public static void PublishSpawn(Func<string, Vector3, Quaternion, Item> spawn) { AppDomain.CurrentDomain.SetData("lycans.mods.items.spawn", spawn); } public static SortedDictionary<string, object[]> Definitions() { if (AppDomain.CurrentDomain.GetData("lycans.mods.items.definitions") is SortedDictionary<string, object[]> result) { return result; } SortedDictionary<string, object[]> sortedDictionary = new SortedDictionary<string, object[]>(StringComparer.Ordinal); AppDomain.CurrentDomain.SetData("lycans.mods.items.definitions", sortedDictionary); return sortedDictionary; } } public static class DevMode { private const string LoadedDevKey = "lycans.mods.devmode.loaded"; private const string SkippedKey = "lycans.mods.devmode.skipped"; private static bool? _enabled; public static bool Enabled { get { if (_enabled.HasValue) { return _enabled.Value; } _enabled = false; try { string path = Path.Combine(Paths.ConfigPath, "lycans.core.cfg"); if (File.Exists(path)) { string[] array = File.ReadAllLines(path); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { '=' }); if (array2.Length == 2 && array2[0].Trim() == "ModeDev") { _enabled = array2[1].Trim().Equals("true", StringComparison.OrdinalIgnoreCase); } } } } catch (Exception ex) { Log.Warning("[DevMode] Lecture de lycans.core.cfg impossible : " + ex.Message); } return _enabled.Value; } } public static IReadOnlyCollection<string> Skipped => List("lycans.mods.devmode.skipped"); public static bool IsDevOnly(string status) { if (!(status == "dev")) { return status == "private"; } return true; } public static bool Guard(BaseUnityPlugin plugin, string modName, string status) { KeepAlive(plugin); if (!IsDevOnly(status)) { return true; } if (!Enabled) { List("lycans.mods.devmode.skipped").Add(modName); ((Behaviour)plugin).enabled = false; Log.Info("[DevMode] « " + modName + " » (" + status + ") non chargé : mode DEV désactivé (ModeDev dans lycans.core.cfg)."); return false; } List("lycans.mods.devmode.loaded").Add(modName); return true; } private static void KeepAlive(BaseUnityPlugin plugin) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 if (!((Object)(object)plugin == (Object)null)) { GameObject gameObject = ((Component)plugin).gameObject; if ((int)((Object)gameObject).hideFlags != 61) { ((Object)gameObject).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)gameObject); } } } public static bool IsLoadedDevMod(string modName) { return List("lycans.mods.devmode.loaded").Contains(modName); } private static HashSet<string> List(string key) { if (AppDomain.CurrentDomain.GetData(key) is HashSet<string> result) { return result; } HashSet<string> hashSet = new HashSet<string>(); AppDomain.CurrentDomain.SetData(key, hashSet); return hashSet; } } public static class Disease { private const string EnabledKey = "lycans.mods.disease.enabled"; private const string InfectKey = "lycans.mods.disease.infect"; private const string CureKey = "lycans.mods.disease.cure"; private const string StageKey = "lycans.mods.disease.stage"; public static bool IsEnabled { get { if (AppDomain.CurrentDomain.GetData("lycans.mods.disease.enabled") is Func<bool> func) { return func(); } return false; } } public static void PublishImplementation(Func<bool> enabled, Action<PlayerController> infect, Action<PlayerController> cure, Func<PlayerController, int> stage) { AppDomain.CurrentDomain.SetData("lycans.mods.disease.enabled", enabled); AppDomain.CurrentDomain.SetData("lycans.mods.disease.infect", infect); AppDomain.CurrentDomain.SetData("lycans.mods.disease.cure", cure); AppDomain.CurrentDomain.SetData("lycans.mods.disease.stage", stage); } public static void Infect(PlayerController player) { if (AppDomain.CurrentDomain.GetData("lycans.mods.disease.infect") is Action<PlayerController> action) { action(player); } } public static void Cure(PlayerController player) { if (AppDomain.CurrentDomain.GetData("lycans.mods.disease.cure") is Action<PlayerController> action) { action(player); } } public static int Stage(PlayerController player) { if (!(AppDomain.CurrentDomain.GetData("lycans.mods.disease.stage") is Func<PlayerController, int> func)) { return 0; } return func(player); } } public enum ExtendedRole { Villager, Alchemist, Hunter, Wolf, Porcupines, Knight, Alpha, Snake, LittleGirl, Rat, None, Maire, BigWolf, Chef } public static class ExtendedRoles { private const string GetKey = "lycans.mods.roles.get"; private const string SetKey = "lycans.mods.roles.set"; private const string SlotCountKey = "lycans.mods.roles.slotcount"; private const string DisplayKey = "lycans.mods.roles.display"; public static bool IsAvailable => AppDomain.CurrentDomain.GetData("lycans.mods.roles.get") != null; public static int SlotCount { get { object data = AppDomain.CurrentDomain.GetData("lycans.mods.roles.slotcount"); if (data is int) { return (int)data; } return 0; } } public static void PublishImplementation(Func<int, ExtendedRole> get, Action<int, ExtendedRole> set, int slotCount) { AppDomain.CurrentDomain.SetData("lycans.mods.roles.get", (Func<int, int>)((int index) => (int)get(index))); AppDomain.CurrentDomain.SetData("lycans.mods.roles.set", (Action<int, int>)delegate(int index, int role) { set(index, (ExtendedRole)role); }); AppDomain.CurrentDomain.SetData("lycans.mods.roles.slotcount", slotCount); } public static ExtendedRole Get(int playerIndex) { if (AppDomain.CurrentDomain.GetData("lycans.mods.roles.get") is Func<int, int> func) { return (ExtendedRole)func(playerIndex); } return ExtendedRole.None; } public static ExtendedRole Get(PlayerController player) { if (!((Object)(object)player != (Object)null)) { return ExtendedRole.None; } return Get((int)player.Index); } public static void RegisterDisplay(ExtendedRole role, string translationKey, Color color, bool wolfTeam, Func<bool> showMates = null, Func<string> suffix = null) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) Displays()[(int)role] = new object[5] { translationKey, color, wolfTeam, showMates, suffix }; } public static bool TryGetDisplay(ExtendedRole role, out string translationKey, out Color color, out bool wolfTeam, out Func<bool> showMates, out Func<string> suffix) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //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 (Displays().TryGetValue((int)role, out var value)) { translationKey = (string)value[0]; color = (Color)value[1]; wolfTeam = (bool)value[2]; showMates = (Func<bool>)value[3]; suffix = (Func<string>)value[4]; return true; } translationKey = null; color = Color.white; wolfTeam = false; showMates = null; suffix = null; return false; } public static bool IsWolfTeam(PlayerController player) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 if ((Object)(object)player == (Object)null) { return false; } if ((int)player.Role == 1) { return true; } string translationKey; Color color; bool wolfTeam; Func<bool> showMates; Func<string> suffix; return TryGetDisplay(Get(player), out translationKey, out color, out wolfTeam, out showMates, out suffix) && wolfTeam; } private static Dictionary<int, object[]> Displays() { if (AppDomain.CurrentDomain.GetData("lycans.mods.roles.display") is Dictionary<int, object[]> result) { return result; } Dictionary<int, object[]> dictionary = new Dictionary<int, object[]>(); AppDomain.CurrentDomain.SetData("lycans.mods.roles.display", dictionary); return dictionary; } public static void Set(int playerIndex, ExtendedRole role) { if (AppDomain.CurrentDomain.GetData("lycans.mods.roles.set") is Action<int, int> action) { action(playerIndex, (int)role); } else { Log.Warning("[ExtendedRoles] Set ignoré : mod_roles non chargé."); } } } public static class GamePhases { private static NetworkRunner Runner => ((SimulationBehaviour)(GameManager.Instance?)).Runner; private static bool InPlay { get { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 //IL_0045: 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) if ((Object)(object)Runner != (Object)null && Runner.IsServer && (Object)(object)GameManager.State != (Object)null && (int)GameManager.State.Current == 2 && (Object)(object)GameManager.LightingManager != (Object)null && !NetworkBool.op_Implicit(GameManager.LightingManager.IsTransition)) { return !NetworkBool.op_Implicit(GameManager.Instance.IsFinished); } return false; } } public static bool CanStartNight { get { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (InPlay) { return !NetworkBool.op_Implicit(GameManager.LightingManager.IsNight); } return false; } } public static bool CanStartDawn { get { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (InPlay) { return NetworkBool.op_Implicit(GameManager.LightingManager.IsNight); } return false; } } public static bool CanEndVote { get { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 if ((Object)(object)Runner != (Object)null && Runner.IsServer && (Object)(object)GameManager.State != (Object)null) { return (int)GameManager.State.Current == 4; } return false; } } public static void Transition() { //IL_0018: 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) if (InPlay) { GameManager.Rpc_Transition(Runner); GameManager.LightingManager.IsTransition = NetworkBool.op_Implicit(true); Log.Info("[GamePhases] Transition forcée (" + (NetworkBool.op_Implicit(GameManager.LightingManager.IsNight) ? "aube" : "tombée de la nuit") + ")."); } } public static void StartNight() { if (CanStartNight) { Transition(); } } public static void EndVote() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) if (CanEndVote) { GameManager.Instance.VoteTimer = TickTimer.CreateFromSeconds(Runner, 0.1f); Log.Info("[GamePhases] Fin du vote forcée."); } } } public sealed class StateEnterContext { private readonly IDictionary<string, object> _data; public EGameState Entered => (EGameState)_data["entered"]; public EGameState From => (EGameState)_data["from"]; public bool IsServer => (bool)_data["server"]; public bool IsPlayer => (bool)_data["player"]; public bool Cancel { get { return HookPipeline.IsCancelled(_data); } set { _data["cancel"] = HookPipeline.Box(value); } } internal StateEnterContext(IDictionary<string, object> data) { _data = data; } } public static class GameStateRules { public unsafe static string Method(EGameState state) { return "GameState.Enter." + ((object)(*(EGameState*)(&state))/*cast due to .constrained prefix*/).ToString(); } public static void BeforeEnter(EGameState state, int priority, string owner, Action<StateEnterContext> step) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) HookPipeline.Register(Method(state), priority, owner, HookPhase.Before, delegate(IDictionary<string, object> data) { step(new StateEnterContext(data)); }); } public static void AfterEnter(EGameState state, int priority, string owner, Action<StateEnterContext> step) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) HookPipeline.Register(Method(state), priority, owner, HookPhase.After, delegate(IDictionary<string, object> data) { step(new StateEnterContext(data)); }); } public static void OnRoundStartServer(int priority, string owner, Action step) { AfterEnter((EGameState)2, priority, owner, delegate(StateEnterContext ctx) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 if (ctx.IsServer && (int)ctx.From == 1) { step(); } }); } public static IDictionary<string, object> NewData(EGameState entered, EGameState from, bool isServer, bool isPlayer) { //IL_000b: 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) return new Dictionary<string, object> { ["entered"] = entered, ["from"] = from, ["server"] = HookPipeline.Box(isServer), ["player"] = HookPipeline.Box(isPlayer), ["cancel"] = HookPipeline.False }; } } public enum HookPhase { Before, After } public static class HookPipeline { public const string CancelKey = "cancel"; public static readonly object True = true; public static readonly object False = false; private const string StepsKey = "lycans.mods.hooks.steps"; private const string ConflictsKey = "lycans.mods.hooks.conflicts"; private const string CacheKey = "lycans.mods.hooks.cache"; private static readonly object Lock = new object(); public static IReadOnlyList<string> ConflictMessages { get { lock (Lock) { return Conflicts().ToArray(); } } } public static void Register(string method, int priority, string owner, HookPhase phase, Action<IDictionary<string, object>> step) { lock (Lock) { Dictionary<string, List<Tuple<int, string, int, Action<IDictionary<string, object>>>>> dictionary = Steps(); if (!dictionary.TryGetValue(method, out var value)) { value = (dictionary[method] = new List<Tuple<int, string, int, Action<IDictionary<string, object>>>>()); } value.RemoveAll((Tuple<int, string, int, Action<IDictionary<string, object>>> s) => s.Item1 == priority && s.Item2 == owner); Tuple<int, string, int, Action<IDictionary<string, object>>> tuple = value.Find((Tuple<int, string, int, Action<IDictionary<string, object>>> s) => s.Item1 == priority); if (tuple != null) { string text = method + " : priorité " + priority + " demandée par « " + owner + " » mais déjà prise par « " + tuple.Item2 + " ». Les deux étapes sont désactivées — change la priorité de l'un des deux mods."; Conflicts().Add(text); Log.Error("[HookPipeline] " + text); } value.Add(Tuple.Create(priority, owner, (int)phase, step)); value.Sort((Tuple<int, string, int, Action<IDictionary<string, object>>> a, Tuple<int, string, int, Action<IDictionary<string, object>>> b) => a.Item1.CompareTo(b.Item1)); Cache().Clear(); } } public static bool RunBefore(string method, IDictionary<string, object> data) { Tuple<int, string, int, Action<IDictionary<string, object>>>[] array = Active(method, HookPhase.Before); foreach (Tuple<int, string, int, Action<IDictionary<string, object>>> tuple in array) { try { tuple.Item4(data); } catch (Exception ex) { Log.Error("[HookPipeline] " + method + " / « " + tuple.Item2 + " » (priorité " + tuple.Item1 + ") en erreur : " + ex); } if (IsCancelled(data)) { return true; } } return false; } public static void RunAfter(string method, IDictionary<string, object> data) { Tuple<int, string, int, Action<IDictionary<string, object>>>[] array = Active(method, HookPhase.After); foreach (Tuple<int, string, int, Action<IDictionary<string, object>>> tuple in array) { try { tuple.Item4(data); } catch (Exception ex) { Log.Error("[HookPipeline] " + method + " / « " + tuple.Item2 + " » (priorité " + tuple.Item1 + ") en erreur : " + ex); } } } public static bool IsCancelled(IDictionary<string, object> data) { bool flag = default(bool); int num; if (data.TryGetValue("cancel", out var value)) { if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } public static object Box(bool value) { if (!value) { return False; } return True; } public static IReadOnlyList<string> Describe(string method) { lock (Lock) { List<string> list = new List<string>(); if (Steps().TryGetValue(method, out var value)) { foreach (Tuple<int, string, int, Action<IDictionary<string, object>>> item in value) { list.Add(item.Item1 + " · " + item.Item2 + " · " + ((HookPhase)item.Item3/*cast due to .constrained prefix*/).ToString() + (IsDuplicate(value, item.Item1) ? " · CONFLIT (désactivée)" : "")); } } return list; } } private static Tuple<int, string, int, Action<IDictionary<string, object>>>[] Active(string method, HookPhase phase) { lock (Lock) { Dictionary<string, Tuple<int, string, int, Action<IDictionary<string, object>>>[][]> dictionary = Cache(); if (!dictionary.TryGetValue(method, out var value)) { value = (dictionary[method] = new Tuple<int, string, int, Action<IDictionary<string, object>>>[2][]); } if (value[(int)phase] != null) { return value[(int)phase]; } List<Tuple<int, string, int, Action<IDictionary<string, object>>>> list = new List<Tuple<int, string, int, Action<IDictionary<string, object>>>>(); if (Steps().TryGetValue(method, out var value2)) { foreach (Tuple<int, string, int, Action<IDictionary<string, object>>> item in value2) { if (item.Item3 == (int)phase && !IsDuplicate(value2, item.Item1)) { list.Add(item); } } } value[(int)phase] = list.ToArray(); return value[(int)phase]; } } private static bool IsDuplicate(List<Tuple<int, string, int, Action<IDictionary<string, object>>>> list, int priority) { return list.FindAll((Tuple<int, string, int, Action<IDictionary<string, object>>> s) => s.Item1 == priority).Count > 1; } private static Dictionary<string, List<Tuple<int, string, int, Action<IDictionary<string, object>>>>> Steps() { return GetOrCreate<Dictionary<string, List<Tuple<int, string, int, Action<IDictionary<string, object>>>>>>("lycans.mods.hooks.steps"); } private static List<string> Conflicts() { return GetOrCreate<List<string>>("lycans.mods.hooks.conflicts"); } private static Dictionary<string, Tuple<int, string, int, Action<IDictionary<string, object>>>[][]> Cache() { return GetOrCreate<Dictionary<string, Tuple<int, string, int, Action<IDictionary<string, object>>>[][]>>("lycans.mods.hooks.cache"); } private static T GetOrCreate<T>(string key) where T : class, new() { if (AppDomain.CurrentDomain.GetData(key) is T result) { return result; } T val = new T(); AppDomain.CurrentDomain.SetData(key, val); return val; } } public sealed class InteractRayContext { private readonly IDictionary<string, object> _data; public PlayerController Player => (PlayerController)_data["player"]; public float Distance { get { return ((float[])_data["values"])[0]; } set { ((float[])_data["values"])[0] = value; } } public bool IsMeeting => (int)GameManager.LocalGameState == 4; internal InteractRayContext(IDictionary<string, object> data) { _data = data; } } public static class InteractRayRules { public const string Method = "PlayerInteract.Update"; public static void AdjustDistance(int priority, string owner, Action<InteractRayContext> step) { HookPipeline.Register("PlayerInteract.Update", priority, owner, HookPhase.Before, delegate(IDictionary<string, object> data) { step(new InteractRayContext(data)); }); } public static IDictionary<string, object> NewData() { return new Dictionary<string, object> { ["values"] = new float[1] }; } public static void Reset(IDictionary<string, object> data, PlayerController player, float distance) { data["player"] = player; data["cancel"] = HookPipeline.False; ((float[])data["values"])[0] = distance; } } public sealed class InteractContext { private readonly IDictionary<string, object> _data; public PlayerController Player => (PlayerController)_data["player"]; public bool IsPrimary => (bool)_data["primary"]; public GameObject Target => (GameObject)_data["target"]; public PlayerController TargetPlayer { get { if (!((Object)(object)Target != (Object)null)) { return null; } return Target.GetComponentInParent<PlayerController>(); } } public bool Handled { get { return HookPipeline.IsCancelled(_data); } set { _data["cancel"] = HookPipeline.Box(value); } } internal InteractContext(IDictionary<string, object> data) { _data = data; } } public static class InteractRules { public const string Method = "PlayerController.Interact"; public static void Before(int priority, string owner, Action<InteractContext> step) { HookPipeline.Register("PlayerController.Interact", priority, owner, HookPhase.Before, delegate(IDictionary<string, object> data) { step(new InteractContext(data)); }); } public static void After(int priority, string owner, Action<InteractContext> step) { HookPipeline.Register("PlayerController.Interact", priority, owner, HookPhase.After, delegate(IDictionary<string, object> data) { step(new InteractContext(data)); }); } public static IDictionary<string, object> NewData(PlayerController player, bool isPrimary) { return new Dictionary<string, object> { ["player"] = player, ["primary"] = HookPipeline.Box(isPrimary), ["target"] = player._targetObject, ["cancel"] = HookPipeline.False }; } } public sealed class ItemSpawnContext { private readonly IDictionary<string, object> _data; public GameManager Game => (GameManager)_data["game"]; public List<Item> Prefabs => (List<Item>)_data["prefabs"]; public Dictionary<string, Action<Vector3, Quaternion>> CustomItems => (Dictionary<string, Action<Vector3, Quaternion>>)_data["custom"]; public bool BulletsAllowed { get { return (bool)_data["bullets"]; } set { _data["bullets"] = HookPipeline.Box(value); } } internal ItemSpawnContext(IDictionary<string, object> data) { _data = data; } } public static class ItemSpawnRules { public const string Method = "GameManager.SpawnRandomItems"; public static void Before(int priority, string owner, Action<ItemSpawnContext> step) { HookPipeline.Register("GameManager.SpawnRandomItems", priority, owner, HookPhase.Before, delegate(IDictionary<string, object> data) { step(new ItemSpawnContext(data)); }); } public static IDictionary<string, object> NewData(GameManager game) { return new Dictionary<string, object> { ["game"] = game, ["prefabs"] = new List<Item>(game.spawnableItemPrefabs), ["custom"] = new Dictionary<string, Action<Vector3, Quaternion>>(), ["bullets"] = HookPipeline.True, ["cancel"] = HookPipeline.False }; } } public sealed class LightingContext { private readonly IDictionary<string, object> _data; public LightingManager Manager => (LightingManager)_data["manager"]; public float TimeOfDay => Manager._localTimeOfDay; public bool IsNightTime { get { if (!(TimeOfDay >= 18f)) { return TimeOfDay < 6f; } return true; } } public bool IsServer { get { if ((Object)(object)((SimulationBehaviour)Manager).Runner != (Object)null) { return ((SimulationBehaviour)Manager).Runner.IsServer; } return false; } } public bool FlatAmbient { get { return (bool)_data["flat"]; } set { _data["flat"] = HookPipeline.Box(value); } } internal LightingContext(IDictionary<string, object> data) { _data = data; } } public static class LightingRules { public const string UpdateMethod = "LightingManager.UpdateLighting"; public const string NightMethod = "LightingManager.NightChanged"; public const string AmbientMethod = "LightingManager.FlatAmbient"; public static void OnUpdate(int priority, string owner, Action<LightingContext> step) { HookPipeline.Register("LightingManager.UpdateLighting", priority, owner, HookPhase.After, delegate(IDictionary<string, object> data) { step(new LightingContext(data)); }); } public static void OnNightChanged(int priority, string owner, Action<LightingContext> step) { HookPipeline.Register("LightingManager.NightChanged", priority, owner, HookPhase.After, delegate(IDictionary<string, object> data) { step(new LightingContext(data)); }); } public static void ForceFlatAmbient(int priority, string owner, Func<LightingContext, bool> wantsFlat) { HookPipeline.Register("LightingManager.FlatAmbient", priority, owner, HookPhase.After, delegate(IDictionary<string, object> data) { LightingContext lightingContext = new LightingContext(data); if (!lightingContext.FlatAmbient && wantsFlat(lightingContext)) { lightingContext.FlatAmbient = true; } }); } public static IDictionary<string, object> NewData() { return new Dictionary<string, object>(); } public static void Reset(IDictionary<string, object> data, LightingManager manager) { data["manager"] = manager; data["flat"] = HookPipeline.False; data["cancel"] = HookPipeline.False; } } public static class Log { private static ManualLogSource _source; private static readonly Dictionary<string, float> _lastThrottled = new Dictionary<string, float>(); public static void Use(ManualLogSource source) { _source = source; } public static void Info(string message) { if (_source != null) { _source.LogInfo((object)message); } else { Console.WriteLine("[Info] " + message); } } public static void Warning(string message) { if (_source != null) { _source.LogWarning((object)message); } else { Console.WriteLine("[Warning] " + message); } } public static void Error(string message) { if (_source != null) { _source.LogError((object)message); } else { Console.WriteLine("[Error] " + message); } } public static void Throttled(string key, float intervalSeconds, string message) { float unscaledTime = Time.unscaledTime; if (!_lastThrottled.TryGetValue(key, out var value) || !(unscaledTime - value < intervalSeconds)) { _lastThrottled[key] = unscaledTime; Info(message); } } } public sealed class LootCollectContext { private readonly IDictionary<string, object> _data; public PlayerController Player => (PlayerController)_data["player"]; public Loot Loot => (Loot)_data["loot"]; public int Score { get { return (int)_data["score"]; } set { _data["score"] = value; } } public int Hunger { get { return (int)_data["hunger"]; } set { _data["hunger"] = value; } } public bool Cancel { get { return HookPipeline.IsCancelled(_data); } set { _data["cancel"] = HookPipeline.Box(value); } } internal LootCollectContext(IDictionary<string, object> data) { _data = data; } } public static class LootRules { public const string Method = "Loot.Rpc_Collect"; public static void Before(int priority, string owner, Action<LootCollectContext> step) { HookPipeline.Register("Loot.Rpc_Collect", priority, owner, HookPhase.Before, delegate(IDictionary<string, object> data) { step(new LootCollectContext(data)); }); } public static void After(int priority, string owner, Action<LootCollectContext> step) { HookPipeline.Register("Loot.Rpc_Collect", priority, owner, HookPhase.After, delegate(IDictionary<string, object> data) { step(new LootCollectContext(data)); }); } public static IDictionary<string, object> NewData(PlayerController player, Loot loot) { return new Dictionary<string, object> { ["player"] = player, ["loot"] = loot, ["score"] = loot.ScoreValue, ["hunger"] = loot.HungerValue, ["cancel"] = HookPipeline.False }; } } public static class ModAssets { private static readonly Dictionary<string, AssetBundle> Bundles = new Dictionary<string, AssetBundle>(); private static readonly Dictionary<string, Sprite> Icons = new Dictionary<string, Sprite>(); public static AssetBundle Bundle(Assembly assembly, string fileName) { if (Bundles.TryGetValue(fileName, out var value) && (Object)(object)value != (Object)null) { return value; } byte[] array = Read(assembly, "LycansBundle." + fileName); if (array == null) { return null; } AssetBundle val = AssetBundle.LoadFromMemory(array); if ((Object)(object)val == (Object)null) { foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles()) { if ((Object)(object)allLoadedAssetBundle != (Object)null && string.Equals(((Object)allLoadedAssetBundle).name, Path.GetFileNameWithoutExtension(fileName), StringComparison.OrdinalIgnoreCase)) { val = allLoadedAssetBundle; } } } if ((Object)(object)val == (Object)null) { Log.Warning("[ModAssets] Bundle illisible : " + fileName); } Bundles[fileName] = val; return val; } public static GameObject FirstPrefab(Assembly assembly, string fileName) { AssetBundle val = Bundle(assembly, fileName); GameObject[] array = (((Object)(object)val != (Object)null) ? val.LoadAllAssets<GameObject>() : null); if (array == null || array.Length == 0) { return null; } return array[0]; } public static T FirstAsset<T>(Assembly assembly, string fileName) where T : Object { AssetBundle val = Bundle(assembly, fileName); T[] array = (((Object)(object)val != (Object)null) ? val.LoadAllAssets<T>() : null); if (array == null || array.Length == 0) { Log.Warning("[ModAssets] Aucun " + typeof(T).Name + " dans " + fileName); return default(T); } return array[0]; } public static Sprite Icon(Assembly assembly, string fileName) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) if (Icons.TryGetValue(fileName, out var value) && (Object)(object)value != (Object)null) { return value; } byte[] array = Read(assembly, "LycansIcon." + fileName); if (array == null) { return null; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!ImageConversion.LoadImage(val, array)) { Log.Warning("[ModAssets] Icône illisible : " + fileName); return null; } Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); Icons[fileName] = val2; return val2; } private static byte[] Read(Assembly assembly, string resource) { using Stream stream = assembly.GetManifestResourceStream(resource); if (stream == null) { Log.Warning("[ModAssets] Ressource absente de la DLL : " + resource); return null; } MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); return memoryStream.ToArray(); } } public static class ModConfigPanel { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static hook_Spawned <>9__7_0; internal void <EnsureInstalled>b__7_0(orig_Spawned orig, GameManager self) { orig.Invoke(self); CreateCarrierIfNeeded(); } } private const string HookInstalledKey = "lycans.mods.config.panelhookinstalled"; private const string ReplacedKey = "lycans.mods.config.panelreplaced"; private static readonly object Lock = new object(); private static GameObject _carrier; public static bool Replaced { get { object data = AppDomain.CurrentDomain.GetData("lycans.mods.config.panelreplaced"); bool flag = default(bool); int num; if (data is bool) { flag = (bool)data; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } set { AppDomain.CurrentDomain.SetData("lycans.mods.config.panelreplaced", value); } } public static void EnsureInstalled() { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown lock (Lock) { object data = AppDomain.CurrentDomain.GetData("lycans.mods.config.panelhookinstalled"); bool flag = default(bool); int num; if (data is bool) { flag = (bool)data; num = 1; } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) != 0) { return; } AppDomain.CurrentDomain.SetData("lycans.mods.config.panelhookinstalled", true); object obj = <>c.<>9__7_0; if (obj == null) { hook_Spawned val = delegate(orig_Spawned orig, GameManager self) { orig.Invoke(self); CreateCarrierIfNeeded(); }; <>c.<>9__7_0 = val; obj = (object)val; } GameManager.Spawned += (hook_Spawned)obj; Log.Info("[ModConfigPanel] Hook GameManager.Spawned installé, carrier créé au premier démarrage de partie."); } } private static void CreateCarrierIfNeeded() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown if (!((Object)(object)_carrier != (Object)null)) { _carrier = new GameObject("LycansModConfigPanel"); Object.DontDestroyOnLoad((Object)(object)_carrier); _carrier.AddComponent<ModConfigPanelBehaviour>(); Log.Info("[ModConfigPanel] Carrier créé (" + ((Object)_carrier).name + ")."); } } } internal sealed class ModConfigPanelBehaviour : MonoBehaviour { private const KeyCode ToggleKey = (KeyCode)290; private const string CouncilTabId = "\0council"; private bool _open; private bool _loggedFirstOnGui; private Rect _rect = new Rect(20f, 20f, 560f, 440f); private Vector2 _tabScroll; private Vector2 _contentScroll; private string _search = ""; private string _selectedMod; private static GUIStyle _richLabel; private static GUIStyle RichLabel { get { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown object obj = _richLabel; if (obj == null) { GUIStyle val = new GUIStyle(GUI.skin.label) { richText = true, wordWrap = true }; _richLabel = val; obj = (object)val; } return (GUIStyle)obj; } } private void Awake() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) Log.Info("[ModConfigPanel] Awake : composant créé, en attente de " + ((object)(KeyCode)290/*cast due to .constrained prefix*/).ToString() + "."); } private void OnEnable() { Log.Info("[ModConfigPanel] OnEnable."); } private void OnDisable() { Log.Info("[ModConfigPanel] OnDisable (le composant vient d'être désactivé !)."); } private void OnDestroy() { Log.Info("[ModConfigPanel] OnDestroy (le composant vient d'être détruit !)."); if (_open) { CursorControl.Release(); } } private void Update() { //IL_0078: Unknown result type (might be due to invalid IL or missing references) string reason; bool flag = CanConfigure(out reason); Log.Throttled("modconfigpanel.state", 3f, "[ModConfigPanel] CanConfigure=" + flag + " (" + reason + ")"); if (ModConfigPanel.Replaced) { SetOpen(value: false); return; } if (Input.GetKeyDown((KeyCode)290)) { Log.Info("[ModConfigPanel] " + ((object)(KeyCode)290/*cast due to .constrained prefix*/).ToString() + " détecté (appui). CanConfigure=" + flag + " (" + reason + ")"); if (flag) { SetOpen(!_open); } else { Log.Info("[ModConfigPanel] Touche ignorée : condition non remplie (" + reason + ")."); } } if (!flag) { SetOpen(value: false); } } private void SetOpen(bool value) { if (_open != value) { _open = value; if (value) { CursorControl.Request(); } else { CursorControl.Release(); } } } private static bool CanConfigure(out string reason) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Invalid comparison between Unknown and I4 GameManager instance = GameManager.Instance; if ((Object)(object)instance == (Object)null) { reason = "GameManager.Instance == null (pas en partie ?)"; return false; } if ((Object)(object)((SimulationBehaviour)instance).Runner == (Object)null) { reason = "Runner == null"; return false; } if (!((SimulationBehaviour)instance).Runner.IsRunning) { reason = "Runner.IsRunning == false"; return false; } if ((int)GameManager.LocalGameState != 1) { reason = "état de partie = " + ((object)Unsafe.As<EGameState, EGameState>(ref GameManager.LocalGameState)/*cast due to .constrained prefix*/).ToString() + " (attendu Pregame)"; return false; } reason = "ok"; return true; } private static bool IsHost() { GameManager instance = GameManager.Instance; if (instance == null) { return false; } NetworkRunner runner = ((SimulationBehaviour)instance).Runner; return ((runner != null) ? new bool?(runner.IsServer) : ((bool?)null)) == true; } private void OnGUI() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) if (!_loggedFirstOnGui) { _loggedFirstOnGui = true; Log.Info("[ModConfigPanel] OnGUI appelé pour la première fois (Unity invoque bien ce composant)."); } if (_open) { string text = (IsHost() ? "hôte" : "joueur — tes changements deviennent des propositions"); _rect = GUILayout.Window(113755157, _rect, new WindowFunction(DrawWindow), "Configuration des mods · " + text + " (" + ((object)(KeyCode)290/*cast due to .constrained prefix*/).ToString() + " pour fermer)", Array.Empty<GUILayoutOption>()); } } private void DrawWindow(int id) { //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) IReadOnlyList<ModConfigSection> sections = ModConfigRegistry.Sections; IReadOnlyList<string> conflictMessages = HookPipeline.ConflictMessages; if (conflictMessages.Count > 0) { Color color = GUI.color; GUI.color = new Color(1f, 0.35f, 0.35f); foreach (string item in conflictMessages) { GUILayout.Label("ERREUR — " + item, Array.Empty<GUILayoutOption>()); } GUI.color = color; GUILayout.Space(6f); } GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(170f) }); GUILayout.Label("Recherche", Array.Empty<GUILayoutOption>()); _search = GUILayout.TextField(_search, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(160f) }); GUILayout.Space(6f); _tabScroll = GUILayout.BeginScrollView(_tabScroll, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(170f), GUILayout.Height(330f) }); string text = _search.Trim().ToLowerInvariant(); foreach (ModConfigSection item2 in sections) { if (text.Length <= 0 || item2.ModName.ToLowerInvariant().IndexOf(text, StringComparison.Ordinal) >= 0) { DrawTabButton(item2.ModName, item2.ModName); } } GUILayout.EndScrollView(); GUILayout.Space(6f); DrawTabButton("\0council", "Conseil"); GUILayout.EndVertical(); GUILayout.Space(10f); GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); _contentScroll = GUILayout.BeginScrollView(_contentScroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(380f) }); DrawSelectedContent(sections); GUILayout.EndScrollView(); GUILayout.EndVertical(); GUILayout.EndHorizontal(); GUI.DragWindow(new Rect(0f, 0f, 10000f, 20f)); } private void DrawTabButton(string id, string label) { bool flag = _selectedMod == id; if (GUILayout.Toggle(flag, label, GUIStyle.op_Implicit("Button"), Array.Empty<GUILayoutOption>())) { _selectedMod = id; } else if (flag) { _selectedMod = null; } } private void DrawSelectedContent(IReadOnlyList<ModConfigSection> sections) { if (_selectedMod == null) { GUILayout.Label("Choisis un mod à gauche (ou cherche son nom).", Array.Empty<GUILayoutOption>()); return; } if (_selectedMod == "\0council") { DrawCouncil(); return; } ModConfigSection modConfigSection = null; foreach (ModConfigSection section in sections) { if (section.ModName == _selectedMod) { modConfigSection = section; break; } } if (modConfigSection == null) { GUILayout.Label("Ce mod n'est plus chargé.", Array.Empty<GUILayoutOption>()); return; } bool flag = modConfigSection.GetEnabled(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); bool flag2 = GUILayout.Toggle(flag, "", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(20f) }); GUILayout.Label("<b>" + modConfigSection.ModName + "</b>", RichLabel, Array.Empty<GUILayoutOption>()); GUILayout.EndHorizontal(); if (flag2 != flag) { modConfigSection.SetEnabled?.Invoke(flag2); } if (!flag2) { GUILayout.Label("Mod désactivé.", Array.Empty<GUILayoutOption>()); return; } if (!IsHost()) { GUILayout.Label("Tu n'es pas l'hôte : tes changements ci-dessous deviennent des propositions envoyées au Conseil (onglet à gauche).", RichLabel, Array.Empty<GUILayoutOption>()); GUILayout.Space(6f); } GUILayout.Space(8f); foreach (ModConfigField field in modConfigSection.Fields) { DrawField(modConfigSection.ModName, field); } } private static void DrawField(string modName, ModConfigField field) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Space(20f); GUILayout.Label(field.Label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) }); object obj = field.Get(); float oldValueRaw = ToRaw(field.Type, obj); object obj2 = obj; switch (field.Type) { case ModConfigFieldType.Bool: obj2 = GUILayout.Toggle((bool)obj, "", Array.Empty<GUILayoutOption>()); break; case ModConfigFieldType.Int: { float num3 = GUILayout.HorizontalSlider((float)(int)obj, field.Min, field.Max, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) }); GUILayout.Label(((int)num3).ToString(), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(32f) }); obj2 = (int)num3; break; } case ModConfigFieldType.Float: { float num2 = GUILayout.HorizontalSlider((float)obj, field.Min, field.Max, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) }); GUILayout.Label(num2.ToString("0.0"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) }); obj2 = num2; break; } case ModConfigFieldType.Choice: { string[] options = field.Options; int num = ((options == null) ? 1 : options.Length); if (GUILayout.Button(field.Format((int)obj), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(160f) })) { obj2 = ((int)obj + 1) % num; } break; } } GUILayout.EndHorizontal(); if (!object.Equals(obj2, obj)) { if (IsHost()) { field.Set(obj2); return; } float newValueRaw = ToRaw(field.Type, obj2); ModProposals.Submit(modName, field.Label, oldValueRaw, newValueRaw); Log.Info("[ModConfigPanel] Proposition envoyée : " + modName + " / " + field.Label); } } private static float ToRaw(ModConfigFieldType type, object value) { return type switch { ModConfigFieldType.Bool => ((bool)value) ? 1f : 0f, ModConfigFieldType.Int => (int)value, ModConfigFieldType.Choice => (int)value, ModConfigFieldType.Float => (float)value, _ => 0f, }; } private void DrawCouncil() { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) GUILayout.Label("<b>Conseil</b>", RichLabel, Array.Empty<GUILayoutOption>()); GUILayout.Space(6f); if (!ModProposals.IsAvailable) { GUILayout.Label("Indisponible : le mod « Lycans Council » n'est pas chargé.", Array.Empty<GUILayoutOption>()); return; } IReadOnlyList<ProposalSlot> readOnlyList = ModProposals.List(); if (readOnlyList.Count == 0) { GUILayout.Label("Aucune proposition en cours.", Array.Empty<GUILayoutOption>()); return; } bool isHost = IsHost(); int num; if (!((Object)(object)PlayerController.Local != (Object)null)) { num = -1; } else { PlayerRef val = PlayerController.Local.Ref; num = ((PlayerRef)(ref val)).PlayerId; } int localPlayerId = num; foreach (ProposalSlot item in readOnlyList) { DrawProposal(item, isHost, localPlayerId); } } private static void DrawProposal(ProposalSlot slot, bool isHost, int localPlayerId) { GUILayout.BeginVertical(GUIStyle.op_Implicit("Box"), Array.Empty<GUILayoutOption>()); GUILayout.Label("<b>" + slot.ModName + " / " + slot.FieldLabel + "</b> — " + DescribeStatus(slot.Status), RichLabel, Array.Empty<GUILayoutOption>()); string[] obj = new string[6] { "Proposé par le joueur #", null, null, null, null, null }; int authorPlayerId = slot.AuthorPlayerId; obj[1] = authorPlayerId.ToString(); obj[2] = " : "; float oldValueRaw = slot.OldValueRaw; obj[3] = oldValueRaw.ToString("0.##"); obj[4] = " → "; oldValueRaw = slot.NewValueRaw; obj[5] = oldValueRaw.ToString("0.##"); GUILayout.Label(string.Concat(obj), Array.Empty<GUILayoutOption>()); switch (slot.Status) { case ProposalStatus.PendingHost: if (isHost) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Ouvrir le vote", Array.Empty<GUILayoutOption>())) { ModProposals.HostDecide(slot.Index, approve: true); } if (GUILayout.Button("Rejeter", Array.Empty<GUILayoutOption>())) { ModProposals.HostDecide(slot.Index, approve: false); } GUILayout.EndHorizontal(); } else { GUILayout.Label("En attente de l'hôte.", Array.Empty<GUILayoutOption>()); } break; case ProposalStatus.Voting: { string[] obj2 = new string[5] { "Votes : ", null, null, null, null }; authorPlayerId = slot.VotesFor; obj2[1] = authorPlayerId.ToString(); obj2[2] = " pour / "; authorPlayerId = slot.VotesAgainst; obj2[3] = authorPlayerId.ToString(); obj2[4] = " contre"; GUILayout.Label(string.Concat(obj2), Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (localPlayerId >= 0) { if (GUILayout.Button("Voter pour", Array.Empty<GUILayoutOption>())) { ModProposals.Vote(slot.Index, voteFor: true); } if (GUILayout.Button("Voter contre", Array.Empty<GUILayoutOption>())) { ModProposals.Vote(slot.Index, voteFor: false); } } if (isHost && GUILayout.Button("Clôturer le vote", Array.Empty<GUILayoutOption>())) { ModProposals.HostCloseVote(slot.Index); } GUILayout.EndHorizontal(); break; } case ProposalStatus.Accepted: GUILayout.Label("Acceptée — en cours d'application.", Array.Empty<GUILayoutOption>()); break; case ProposalStatus.Rejected: GUILayout.Label("Rejetée.", Array.Empty<GUILayoutOption>()); break; } GUILayout.EndVertical(); GUILayout.Space(6f); } private static string DescribeStatus(ProposalStatus status) { return status switch { ProposalStatus.PendingHost => "en attente de l'hôte", ProposalStatus.Voting => "au vote", ProposalStatus.Accepted => "acceptée", ProposalStatus.Rejected => "rejetée", _ => status.ToString(), }; } } public enum ModConfigFieldType { Bool, Int, Float, Choice } public static class ModChapters { public const string Roles = "roles"; public const string Potions = "potions"; public const string Items = "items"; public const string World = "world"; public const string Rules = "rules"; public const string Players = "players"; public const string NativeGroup = "native"; public static readonly string[] All = new string[6] { "roles", "potions", "items", "world", "rules", "players" }; } public sealed class ModConfigField { private readonly object[] _raw; public string Label => (string)_raw[0]; public ModConfigFieldType Type => (ModConfigFieldType)(int)_raw[1]; public Func<object> Get => (Func<object>)_raw[2]; public Action<object> Set => (Action<object>)_raw[3]; public float Min => (float)_raw[4]; public float Max => (float)_raw[5]; public string Description { get { if (_raw.Length <= 6) { return null; } return _raw[6] as string; } } public string[] Options { get { if (_raw.Length <= 7) { return null; } return _raw[7] as string[]; } } internal ModConfigField(object[] raw) { _raw = raw; } public float GetRaw() { object obj = Get(); switch (Type) { case ModConfigFieldType.Bool: if (!(bool)obj) { return 0f; } return 1f; case ModConfigFieldType.Int: case ModConfigFieldType.Choice: return (int)obj; default: return (float)obj; } } public void SetRaw(float raw) { switch (Type) { case ModConfigFieldType.Bool: Set(raw != 0f); break; case ModConfigFieldType.Int: case ModConfigFieldType.Choice: Set((int)Math.Round(raw)); break; default: Set(raw); break; } } public string Format(float raw) { switch (Type) { case ModConfigFieldType.Bool: if (raw == 0f) { return Translations.Text("Non", "No", "Nein", "No", "Hayır", "No"); } return Translations.Text("Oui", "Yes", "Ja", "Sí", "Evet", "Sì"); case ModConfigFieldType.Int: return ((int)Math.Round(raw)).ToString(); case ModConfigFieldType.Choice: { int num = (int)Math.Round(raw); string[] options = Options; if (options == null || num < 0 || num >= options.Length) { return num.ToString(); } return options[num]; } default: return raw.ToString("0.##"); } } } public sealed class ModConfigSection { private readonly object[] _raw; public string ModName => (string)_raw[0]; public Func<bool> GetEnabled => (Func<bool>)_raw[1]; public Action<bool> SetEnabled => (Action<bool>)_raw[2]; private List<object[]> RawFields => (List<object[]>)_raw[3]; public string ChapterId => (_raw[4] as string) ?? "rules"; public string Description => _raw[5] as string; public string WikiText { get { if (_raw.Length <= 6 || !(_raw[6] is string[] array)) { return null; } return Translations.Text(array[0], array[1], array[2], array[3], array[4], array[5]); } } public string Group { get { if (_raw.Length <= 7) { return null; } return _raw[7] as string; } } public string RoleKey { get { if (_raw.Length <= 8) { return null; } return _raw[8] as string; } } public bool IsInfo { get { bool flag = default(bool); int num; if (_raw.Length > 9) { object obj = _raw[9]; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } } public string DisplayName { get { if (!ModName.StartsWith("Lycans ", StringComparison.Ordinal)) { return ModName; } return ModName.Substring(7); } } public IReadOnlyList<ModConfigField> Fields => RawFields.Select((object[] f) => new ModConfigField(f)).ToArray(); internal ModConfigSection(object[] raw) { _raw = raw; } public ModConfigSection ForRole(string roleKey) { _raw[8] = roleKey; return this; } public ModConfigSection InGroup(string group) { _raw[7] = group; return this; } public ModConfigSection Chapter(string chapterId, string description = null) { _raw[4] = chapterId; _raw[5] = description; return this; } public ModConfigSection Wiki(string fr, string en = null, string de = null, string es = null, string tr = null, string it = null) { _raw[6] = new string[6] { fr, en, de, es, tr, it }; return this; } public ModConfigSection AddBool(string label, Func<bool> get, Action<bool> set, string description = null) { return Add(label, ModConfigFieldType.Bool, () => get(), delegate(object v) { set((bool)v); }, 0f, 1f, description, null); } public ModConfigSection AddInt(string label, Func<int> get, Action<int> set, int min, int max, string description = null) { return Add(label, ModConfigFieldType.Int, () => get(), delegate(object v) { set((int)v); }, min, max, description, null); } public ModConfigSection AddFloat(string label, Func<float> get, Action<float> set, float min, float max, string description = null) { return Add(label, ModConfigFieldType.Float, () => get(), delegate(object v) { set((float)v); }, min, max, description, null); } public ModConfigSection AddChoice(string label, string[] options, Func<int> get, Action<int> set, string description = null) { return Add(label, ModConfigFieldType.Choice, () => get(), delegate(object v) { set((int)v); }, 0f, options.Length - 1, description, options); } private ModConfigSection Add(string label, ModConfigFieldType type, Func<object> get, Action<object> set, float min, float max, string description, string[] options) { RawFields.Add(new object[8] { label, (int)type, get, set, min, max, description, options }); return this; } } public static class ModConfigRegistry { private const string SectionsKey = "lycans.mods.config.sections.v2"; private static readonly object Lock = new object(); public static IReadOnlyList<ModConfigSection> Sections { get { lock (Lock) { return (from s in GetOrCreate() orderby (string)s[0] select new ModConfigSection(s)).ToArray(); } } } public static ModConfigSection RegisterMod(string modName, Func<bool> getEnabled, Action<bool> setEnabled) { lock (Lock) { List<object[]> orCreate = GetOrCreate(); object[] array = orCreate.FirstOrDefault((object[] s) => (string)s[0] == modName); if (array != null) { return new ModConfigSection(array); } object[] array2 = new object[10] { modName, getEnabled, setEnabled, new List<object[]>(), null, null, null, null, null, false }; orCreate.Add(array2); return new ModConfigSection(array2); } } public static ModConfigSection RegisterInfo(string name) { ModConfigSection result = RegisterMod(name, () => true, null); lock (Lock) { GetOrCreate().First((object[] s) => (string)s[0] == name)[9] = true; return result; } } private static List<object[]> GetOrCreate() { if (AppDomain.CurrentDomain.GetData("lycans.mods.config.sections.v2") is List<object[]> result) { return result; } List<object[]> list = new List<object[]>(); AppDomain.CurrentDomain.SetData("lycans.mods.config.sections.v2", list); return list; } } public static class ModFiles { private static readonly Dictionary<string, string> Cache = new Dictionary<string, string>(); public static string ModDirectory => Path.GetDirectoryName(typeof(ModFiles).Assembly.Location) ?? Paths.PluginPath; public static string Resolve(string relativePath) { if (Path.IsPathRooted(relativePath)) { if (!File.Exists(relativePath)) { return null; } return relativePath; } if (Cache.TryGetValue(relativePath, out var value) && File.Exists(value)) { return value; } foreach (string item in Roots()) { string path = Path.Combine(item, relativePath); if (File.Exists(path)) { return Cache[relativePath] = Path.GetFullPath(path); } } return null; } private static IEnumerable<string> Roots() { yield return ModDirectory; yield return Paths.PluginPath; string[] array; try { array = Directory.GetDirectories(Paths.PluginPath); } catch (Exception) { array = new string[0]; } string[] array2 = array; for (int i = 0; i < array2.Length; i++) { yield return array2[i]; } yield return Paths.GameRootPath; yield return Paths.BepInExRootPath; } } public static class ModNetworkHub { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Func<Type, string> <>9__9_0; public static Func<string, string> <>9__9_1; public static hook_Awake <>9__12_0; public static hook_Spawned <>9__12_1; internal string <get_RegisteredTypeNames>b__9_0(Type t) { return t.FullName; } internal string <get_RegisteredTypeNames>b__9_1(string n) { return n; } internal void <InstallSpawnHookOnce>b__12_0(orig_Awake orig, GameManager self) { try { EnsureRegisteredInPrefabTable(); } catch (Exception ex) { Log.Error("[ModNetworkHub] Échec de l'enregistrement du préfab du carrier : " + ex); } orig.Invoke(self); } internal void <InstallSpawnHookOnce>b__12_1(orig_Spawned orig, GameManager self) { orig.Invoke(self); try { OnGameManagerSpawned(self); } catch (Exception ex) { Log.Error("[ModNetworkHub] Échec de la mise en place du carrier réseau : " + ex); } } } private const string RegisteredTypesKey = "lycans.mods.network.types"; private const string HookInstalledKey = "lycans.mods.network.hookinstalled"; private const string CarrierKey = "lycans.mods.network.carrier"; private const string PrefabIdKey = "lycans.mods.network.prefabid"; private const string CarrierObjectName = "LycansModNetworkCarrier"; private static readonly object Lock = new object(); private static float _nextLookup; public static IReadOnlyList<string> RegisteredTypeNames { get { lock (Lock) { return (from t in GetOrCreate<List<Type>>("lycans.mods.network.types") select t.FullName).OrderBy<string, string>((string n) => n, StringComparer.Ordinal).ToArray(); } } } public static NetworkObject Carrier { get { object? data = AppDomain.CurrentDomain.GetData("lycans.mods.network.carrier"); NetworkObject val = (NetworkObject)((data is NetworkObject) ? data : null); if ((Object)(object)val != (Object)null) { return val; } if (Time.unscaledTime < _nextLookup) { return null; } _nextLookup = Time.unscaledTime + 0.5f; NetworkObject[] array = Object.FindObjectsOfType<NetworkObject>(); foreach (NetworkObject val2 in array) { if ((Object)(object)val2 != (Object)null && val2.IsValid && ((Object)val2).name.StartsWith("LycansModNetworkCarrier", StringComparison.Ordinal)) { AppDomain.CurrentDomain.SetData("lycans.mods.network.carrier", val2); return val2; } } return null; } } public static void Register<T>() where T : NetworkBehaviour { lock (Lock) { List<Type> orCreate = GetOrCreate<List<Type>>("lycans.mods.network.types"); if (!orCreate.Contains(typeof(T))) { orCreate.Add(typeof(T)); } InstallSpawnHookOnce(); } } private static void InstallSpawnHookOnce() { //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_005c: Expected O, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown object data = AppDomain.CurrentDomain.GetData("lycans.mods.network.hookinstalled"); bool flag = default(bool); int num; if (data is bool) { flag = (bool)data; num = 1; } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) != 0) { return; } AppDomain.CurrentDomain.SetData("lycans.mods.network.hookinstalled", true); object obj = <>c.<>9__12_0; if (obj == null) { hook_Awake val = delegate(orig_Awake orig, GameManager self) { try { EnsureRegisteredInPrefabTable(); } catch (Exception ex) { Log.Error("[ModNetworkHub] Échec de l'enregistrement du préfab du carrier : " + ex); } orig.Invoke(self); }; <>c.<>9__12_0 = val; obj = (object)val; } GameManager.Awake += (hook_Awake)obj; object obj2 = <>c.<>9__12_1; if (obj2 == null) { hook_Spawned val2 = delegate(orig_Spawned orig, GameManager self) { orig.Invoke(self); try { OnGameManagerSpawned(self); } catch (Exception ex) { Log.Error("[ModNetworkHub] Échec de la mise en place du carrier réseau : " + ex); } }; <>c.<>9__12_1 = val2; obj2 = (object)val2; } GameManager.Spawned += (hook_Spawned)obj2; } private static void OnGameManagerSpawned(GameManager self) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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) if (((SimulationBehaviour)self).Runner.SessionInfo.IsOpen && ((SimulationBehaviour)self).Runner.IsServer) { EnsureRegisteredInPrefabTable(); NetworkPrefabId val = (NetworkPrefabId)AppDomain.CurrentDomain.GetData("lycans.mods.network.prefabid"); NetworkObject data = ((SimulationBehaviour)self).Runner.Spawn(val, (Vector3?)Vector3.zero, (Quaternion?)Quaternion.identity, (PlayerRef?)null, (OnBeforeSpawned)null, (NetworkObjectPredictionKey?)null, true, (NetworkObject)null); AppDomain.CurrentDomain.SetData("lycans.mods.network.carrier", data); Log.Info("[ModNetworkHub] Carrier réseau spawn côté hôte avec " + GetOrCreate<List<Type>>("lycans.mods.network.types").Count + " composant(s) de mod."); } } private static void EnsureRegisteredInPrefabTable() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: 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_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown //IL_00b7: 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) if (AppDomain.CurrentDomain.GetData("lycans.mods.network.prefabid") != null) { return; } GameObject val = new GameObject("LycansModNetworkCarrier"); val.AddComponent<NetworkObject>(); foreach (Type item in GetOrCreate<List<Type>>("lycans.mods.network.types")) { val.AddComponent(item); } Object.DontDestroyOnLoad((Object)(object)val); NetworkObject component = val.GetComponent<NetworkObject>(); component.NetworkedBehaviours = val.GetComponents<NetworkBehaviour>(); component.NetworkGuid = new NetworkObjectGuid(ToGuid("LycansModNetworkCarrier").ToString()); NetworkPrefabSourceStatic val2 = new NetworkPrefabSourceStatic { PrefabReference = component }; NetworkPrefabId val3 = default(NetworkPrefabId); if (!NetworkProjectConfig.Global.PrefabTable.TryAdd(component.NetworkGuid, (INetworkPrefabSource)(object)val2, ref val3)) { throw new InvalidOperationException("[ModNetworkHub] Carrier déjà présent dans la table de préfabs Fusion."); } AppDomain.CurrentDomain.SetData("lycans.mods.network.prefabid", val3); } private static Guid ToGuid(string value) { using MD5 mD = MD5.Create(); return new Guid(mD.ComputeHash(Encoding.UTF8.GetBytes(value))); } private static T GetOrCreate<T>(string key) where T : class, new() { if (AppDomain.CurrentDomain.GetData(key) is T result) { return result; } T val = new T(); AppDomain.CurrentDomain.SetData(key, val); return val; } } public enum ProposalStatus { Empty, PendingHost, Voting, Accepted, Rejected } public readonly struct ProposalSlot { public readonly int Index; public readonly ProposalStatus Status; public readonly string ModName; public readonly string FieldLabel; public readonly float OldValueRaw; public readonly float NewValueRaw; public readonly int AuthorPlayerId; public readonly int VotesFor; public readonly int VotesAgainst; public ProposalSlot(int index, ProposalStatus status, string modName, string fieldLabel, float oldValueRaw, float newValueRaw, int authorPlayerId, int votesFor, int votesAgainst) { Index = index; Status = status; ModName = modName; FieldLabel = fieldLabel; OldValueRaw = oldValueRaw; NewValueRaw = newValueRaw; AuthorPlayerId = authorPlayerId; VotesFor = votesFor; VotesAgainst = votesAgainst; } } public static class ModProposals { public const string EnabledField = "Activé"; private const string SubmitKey = "lycans.mods.proposals.submit"; private const string VoteKey = "lycans.mods.proposals.vote"; private const string DecideKey = "lycans.mods.proposals.decide"; private const string CloseKey = "lycans.mods.proposals.close"; private const string ListKey = "lycans.mods.proposals.list"; public static bool IsAvailable => AppDomain.CurrentDomain.GetData("lycans.mods.proposals.list") != null; public static void PublishImplementation(Action<int, int, float, float> submit, Action<int, bool> vote, Action<int, bool> hostDecide, Action<int> hostCloseVote, Func<IReadOnlyList<ProposalSlot>> list) { AppDomain.CurrentDomain.SetData("lycans.mods.proposals.submit", submit); AppDomain.CurrentDomain.SetData("lycans.mods.proposals.vote", vote); AppDomain.CurrentDomain.SetData("lycans.mods.proposals.decide", hostDecide); AppDomain.CurrentDomain.SetData("lycans.mods.proposals.close", hostCloseVote); AppDomain.CurrentDomain.SetData("lycans.mods.proposals.list", (Func<object[][]>)delegate { IReadOnlyList<ProposalSlot> readOnlyList = list(); object[][] array = new object[readOnlyList.Count][]; for (int i = 0; i < readOnlyList.Count; i++) { ProposalSlot proposalSlot = readOnlyList[i]; array[i] = new object[9] { proposalSlot.Index, (int)proposalSlot.Status, proposalSlot.ModName, proposalSlot.FieldLabel, proposalSlot.OldValueRaw, proposalSlot.NewValueRaw, proposalSlot.AuthorPlayerId, proposalSlot.VotesFor, proposalSlot.VotesAgainst }; } return array; }); } public static void Submit(string modName, string fieldLabel, float oldValueRaw, float newValueRaw) { if (AppDomain.CurrentDomain.GetData("lycans.mods.proposals.submit") is Action<int, int, float, float> action) { action(Hash(modName), Hash(fieldLabel), oldValueRaw, newValueRaw); } else { Log.Info("[ModProposals] Submit ignoré : mod_council non chargé."); } } public static void Vote(int slotIndex, bool voteFor) { if (AppDomain.CurrentDomain.GetData("lycans.mods.proposals.vote") is Action<int, bool> action) { action(slotIndex, voteFor); } } public static void HostDecide(int slotIndex, bool approve) { if (AppDomain.CurrentDomain.GetData("lycans.mods.proposals.decide") is Action<int, bool> action) { action(slotIndex, approve); } } public static void HostCloseVote(int slotIndex) { if (AppDomain.CurrentDomain.GetData("lycans.mods.proposals.close") is Action<int> action) { action(slotIndex); } } public static IReadOnlyList<ProposalSlot> List() { if (!(AppDomain.CurrentDomain.GetData("lycans.mods.proposals.list") is Func<object[][]> func)) { return Array.Empty<ProposalSlot>(); } object[][] array = func(); ProposalSlot[] array2 = new ProposalSlot[array.Length]; for (int i = 0; i < array.Length; i++) { object[] array3 = array[i]; array2[i] = new ProposalSlot((int)array3[0], (ProposalStatus)(int)array3[1], (string)array3[2], (string)array3[3], (float)array3[4], (float)array3[5], (int)array3[6], (int)array3[7], (int)array3[8]); } return array2; } public static int Hash(string value) { uint num = 2166136261u; foreach (char c in value) { num ^= c; num *= 16777619; } return (int)num; } } public static class ModRegistry { private const string CapabilitiesKey = "lycans.mods.capabilities"; private const string SubscribersKey = "lycans.mods.subscribers"; private static readonly object Lock = new object(); public static void Register(string modGuid, params string[] capabilities) { lock (Lock) { HashSet<string> orCreate = GetOrCreate<HashSet<string>>("lycans.mods.capabilities"); foreach (string item in capabilities) { orCreate.Add(item); } } } public static bool Has(string capability) { lock (Lock) { return GetOrCreate<HashSet<string>>("lycans.mods.capabilities").Contains(capability); } } public static IReadOnlyCollection<string> AllCapabilities() { lock (Lock) { return (IReadOnlyCollection<string>)(object)GetOrCreate<HashSet<string>>("lycans.mods.capabilities").ToArray(); } } public static void Subscribe<T>(Action<T> handler) { lock (Lock) { GetOrCreate<Dictionary<Type, List<Delegate>>>("lycans.mods.subscribers").GetOrAdd(typeof(T)).Add(handler); } } public static void Unsubscribe<T>(Action<T> handler) { lock (Lock) { if (GetOrCreate<Dictionary<Type, List<Delegate>>>("lycans.mods.subscribers").TryGetValue(typeof(T), out var value)) { value.Remove(handler); } } } public static void Publish<T>(T payload) { Delegate[] array; lock (Lock) { if (!GetOrCreate<Dictionary<Type, List<Delegate>>>("lycans.mods.subscribers").TryGetValue(typeof(T), out var value)) { return; } array = value.ToArray(); } Delegate[] array2 = array; foreach (Delegate obj in array2) { try { ((Action<T>)obj)(payload); } catch (Exception ex) { Log.Error("[ModRegistry] Abonné en erreur pour " + typeof(T).Name + " : " + ex); } } } private static T GetOrCreate<T>(string key) where T : class, new() { if (AppDomain.CurrentDomain.GetData(key) is T result) { return result; } T val = new T(); AppDomain.CurrentDomain.SetData(key, val); return val; } private static List<Delegate> GetOrAdd(this Dictionary<Type, List<Delegate>> dict, Type key) { if (!dict.TryGetValue(key, out var value)) { value = (dict[key] = new List<Delegate>()); } return value; } } public sealed class MovementContext { private readonly IDictionary<string, object> _data; private float[] Values => (float[])_data["values"]; public PlayerController Player => (PlayerController)_data["player"]; public CharacterMovementHandler Handler => (CharacterMovementHandler)_data["handler"]; public float X { get { return Values[0]; } set { Values[0] = value; } } public float Y { get { return Values[1]; } set { Values[1] = value; } } public float Speed { get { return Values[2]; } set { Values[2] = value; } } public bool Teleported => (bool)_data["teleported"]; public bool Cancel { get { return HookPipeline.IsCancelled(_data); } set { _data["cancel"] = HookPipeline.Box(value); } } internal MovementContext(IDictionary<string, object> data) { _data = data; } } public static class MovementRules { public const string Method = "CharacterMovementHandler.FixedUpdateNetwork"; public static void Before(int priority, string owner, Action<MovementContext> step) { HookPipeline.Register("CharacterMovementHandler.FixedUpdateNetwork", priority, owner, HookPhase.Before, delegate(IDictionary<string, object> data) { step(new MovementContext(data)); }); } public static void After(int priority, string owner, Action<MovementContext> step) { HookPipeline.Register("CharacterMovementHandler.FixedUpdateNetwork", priority, owner, HookPhase.After, delegate(IDictionary<string, object> data) { step(new MovementContext(data)); }); } public static IDictionary<string, object> NewData() { return new Dictionary<string, object> { ["values"] = new float[3] }; } public static void Reset(IDictionary<string, object> data, CharacterMovementHandler handler, PlayerController player, float x, float y, float speed, bool teleported) { data["handler"] = handler; data["player"] = player; data["teleported"] = HookPipeline.Box(teleported); data["cancel"] = HookPipeline.False; float[] obj = (float[])data["values"]; obj[0] = x; obj[1] = y; obj[2] = speed; } } public static class NetworkedWeaving { public unsafe static bool GetBool(int* ptr, int word) { return *CheckedPtr(ptr, word) != 0; } public unsafe static void SetBool(int* ptr, int word, bool value) { *CheckedPtr(ptr, word) = (value ? 1 : 0); } public unsafe static int GetInt(int* ptr, int word) { return *CheckedPtr(ptr, word); } public unsafe static void SetInt(int* ptr, int word, int value) { *CheckedPtr(ptr, word) = value; } public unsafe static float GetFloat(int* ptr, int word) { return *(float*)CheckedPtr(ptr, word); } public unsafe static void SetFloat(int* ptr, int word, float value) { *(float*)CheckedPtr(ptr, word) = value; } private unsafe static int* CheckedPtr(int* ptr, int word) { if (ptr == null) { throw new InvalidOperationException("Champ réseau lu avant Spawned() : les propriétés [Networked] ne sont valides qu'une fois l'objet spawn."); } return ptr + word; } } public sealed class ObjectTargetContext { private readonly IDictionary<string, object> _data; public PlayerController Player => (PlayerController)_data["player"]; public GameObject Target { get { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown return (GameObject)_data["target"]; } set { _data["target"] = value; } } public float Distance => (float)_data["distance"]; public bool Offered => (bool)_data["offered"]; internal ObjectTargetContext(IDictionary<string, object> data) { _data = data; } } public static class ObjectTargetRules { public const string Method = "PlayerController.UpdateRayCast"; public static void Offer(int priority, string owner, Func<ObjectTargetContext, bool> offer) { HookPipeline.Register("PlayerController.UpdateRayCast", priority, owner, HookPhase.Before, delegate(IDictionary<string, object> data) { if (!(bool)data["offered"] && offer(new ObjectTargetContext(data))) { data["offered"] = HookPipeline.True; } }); } public static IDictionary<string, object> NewData() { return new Dictionary<string, object>(); } public static void Reset(IDictionary<string, object> data, PlayerController player, GameObject target, float distance) { data["player"] = player; data["target"] = target; data["distance"] = distance; data["offered"] = HookPipeline.False; data["cancel"] = HookPipeline.False; } } public static class PlayerColors { private const string GetKey = "lycans.mods.colors.get"; private const string SetKey = "lycans.mods.colors.set"; private const string CountKey = "lycans.mods.colors.count"; public static bool IsAvailable => AppDomain.CurrentDomain.GetData("lycans.mods.colors.get") != null; public static int Count { get { if (!(AppDomain.CurrentDomain.GetData("lycans.mods.colors.count") is Func<int> func)) { return 0; } return func(); } } public static void PublishImplementation(Func<int, int> get, Action<int, int> set, Func<int> count) { AppDomain.CurrentDomain.SetData("lycans.mods.colors.get", get); AppDomain.CurrentDomain.SetData("lycans.mods.colors.set", set); AppDomain.CurrentDomain.SetData("lycans.mods.colors.count", count); } public static int Get(PlayerController player) { if ((Object)(object)player == (Object)null) { return 0; } if (!(AppDomain.CurrentDomain.GetData("lycans.mods.colors.get") is Func<int, int> func)) { return player.Index; } return func(player.Index); } public static void Set(Playe