Decompiled source of Chrysalis v2.0.45
plugins/SamUtils.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Unity.IL2CPP; using BepInEx.Unity.IL2CPP.Hook; using CellMenu; using DropServer; using DropServer.BoosterImplants; using DropServer.VanityItems; using GTFO.API; using GameData; using HarmonyLib; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppInterop.Runtime.Runtime; using Il2CppSystem.Collections.Generic; using Il2CppSystem.Threading.Tasks; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("SamUtils")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("SamUtils")] [assembly: AssemblyTitle("SamUtils")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace SamUtils; internal class InventoryPatches { public unsafe delegate void UpdateItems(IntPtr _this, IntPtr data, Il2CppMethodInfo* methodInfo); [HarmonyPatch(typeof(DropServerClientAPIViaPlayFab), "GetInventoryPlayerDataAsync")] public static class DropServerClientAPI_GetInventoryPlayerDataAsync_Patch { public static bool Prefix(GetInventoryPlayerDataRequest request, ref Task<GetInventoryPlayerDataResult> __result) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown VanityItemPlayerData val = new VanityItemPlayerData(ClassInjector.DerivedConstructorPointer<VanityItemPlayerData>()); val.Items = new Il2CppReferenceArray<VanityItem>(0L); BoosterImplantPlayerData val2 = new BoosterImplantPlayerData(ClassInjector.DerivedConstructorPointer<BoosterImplantPlayerData>()); val2.Advanced = EmptyCat(); val2.Basic = EmptyCat(); val2.Specialized = EmptyCat(); GetInventoryPlayerDataResult val3 = new GetInventoryPlayerDataResult(ClassInjector.DerivedConstructorPointer<GetInventoryPlayerDataResult>()) { Boosters = val2, VanityItems = val }; __result = Task.FromResult<GetInventoryPlayerDataResult>(val3); return false; } } internal List<INativeDetour> _detours = new List<INativeDetour>(); private UpdateItems _patchMethod; private UpdateItems _originalUpdateItems; internal unsafe void ApplyNative() { _patchMethod = UpdateItemsPatch; _detours.Add(INativeDetour.CreateAndApply<UpdateItems>((IntPtr)(nint)Il2CppAPI.GetIl2CppMethod<VanityItemInventory>("UpdateItems", typeof(void).FullName, false, new string[1] { typeof(VanityItemPlayerData).FullName }), _patchMethod, ref _originalUpdateItems)); } public unsafe void UpdateItemsPatch(IntPtr _this, IntPtr data, Il2CppMethodInfo* methodInfo) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) _originalUpdateItems(_this, data, methodInfo); VanityItemInventory val = new VanityItemInventory(_this); if (val.m_backednItems == null) { val.m_backednItems = new List<VanityItem>(0); } foreach (VanityItemsTemplateDataBlock allBlock in GameDataBlockBase<VanityItemsTemplateDataBlock>.GetAllBlocks()) { VanityItem val2 = new VanityItem(ClassInjector.DerivedConstructorPointer<VanityItem>()); val2.publicName = allBlock.publicName; val2.type = allBlock.type; val2.prefab = allBlock.prefab; val2.flags = (VanityItemFlags)3; val2.id = ((GameDataBlockBase<VanityItemsTemplateDataBlock>)(object)allBlock).persistentID; val.m_backednItems.Add(val2); } } private static Category EmptyCat() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown return new Category(ClassInjector.DerivedConstructorPointer<Category>()) { Inventory = new Il2CppReferenceArray<BoosterImplantInventoryItem>(0L) }; } } internal static class LobbyPatches { [HarmonyPatch(typeof(CM_PlayerLobbyBar), "SetupFromPage")] public static class CM_PlayerLobbyBar_SetupFromPage_Patch { public static void Postfix(CM_PlayerLobbyBar __instance) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) __instance.m_boosterImplantAlign.position = new Vector3(10000f, 0f, 0f); } } } [BepInPlugin("samutils", "SamUtils", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BasePlugin { public const string PLUGIN_GUID = "samutils"; public const string PLUGIN_NAME = "SamUtils"; public const string PLUGIN_VERSION = "1.0.0"; private static Plugin _instance; private readonly Harmony _harmony = new Harmony("samutils"); private static InventoryPatches _patches; public override void Load() { _instance = this; _patches = new InventoryPatches(); _patches.ApplyNative(); _harmony.PatchAll(typeof(LobbyPatches.CM_PlayerLobbyBar_SetupFromPage_Patch)); _harmony.PatchAll(typeof(InventoryPatches.DropServerClientAPI_GetInventoryPlayerDataAsync_Patch)); } internal static void LogMsg(string v) { ((BasePlugin)_instance).Log.LogMessage((object)v); } }
plugins/Oxygen.dll
Decompiled a day agousing System; 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.Text.Json; using System.Text.Json.Serialization; using AK; using Agents; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using BepInEx.Unity.IL2CPP.Hook; using CellMenu; using DropServer; using DropServer.BoosterImplants; using DropServer.VanityItems; using GTFO.API; using GTFO.API.Utilities; using GameData; using GameEvent; using HarmonyLib; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppInterop.Runtime.Runtime; using Il2CppSystem.Collections.Generic; using Il2CppSystem.Threading.Tasks; using LevelGeneration; using Localization; using MTFO.Managers; using Microsoft.CodeAnalysis; using Oxygen.Components; using Oxygen.Config; using Oxygen.Utils; using Oxygen.Utils.PartialData; using Player; using SNetwork; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Oxygen")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Oxygen")] [assembly: AssemblyTitle("Oxygen")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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 Oxygen { [BepInPlugin("Inas.Oxygen", "Oxygen", "1.2.1")] [BepInProcess("GTFO.exe")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BasePlugin { [CompilerGenerated] private static class <>O { public static Action <0>__Setup; public static Action <1>__OnBuildDone; public static Action <2>__OnLevelCleanup; public static Action <3>__Setup; public static Action <4>__OnLevelCleanup; public static Action <5>__OnBuildStart; public static Action <6>__OnLevelCleanup; public static LiveEditEventHandler <7>__Listener_FileChanged1; } public const string MODNAME = "Oxygen"; public const string AUTHOR = "Inas"; public const string GUID = "Inas.Oxygen"; public const string VERSION = "1.2.1"; public static readonly string OXYGEN_CONFIG_PATH = Path.Combine(ConfigManager.CustomPath, "Oxygen"); public static Dictionary<uint, OxygenBlock> lookup = new Dictionary<uint, OxygenBlock>(); private static LiveEditListener listener = null; public override void Load() { //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Expected O, but got Unknown if (!Directory.Exists(OXYGEN_CONFIG_PATH)) { Directory.CreateDirectory(OXYGEN_CONFIG_PATH); StreamWriter streamWriter = File.CreateText(Path.Combine(OXYGEN_CONFIG_PATH, "Template.json")); streamWriter.WriteLine(ConfigManager.Serialize(new OxygenConfig())); streamWriter.Flush(); streamWriter.Close(); } ClassInjector.RegisterTypeInIl2Cpp<AirManager>(); LevelAPI.OnBuildStart += AirManager.Setup; LevelAPI.OnBuildDone += AirManager.OnBuildDone; LevelAPI.OnLevelCleanup += AirManager.OnLevelCleanup; ClassInjector.RegisterTypeInIl2Cpp<AirBar>(); LevelAPI.OnBuildStart += AirBar.Setup; LevelAPI.OnLevelCleanup += AirBar.OnLevelCleanup; ClassInjector.RegisterTypeInIl2Cpp<AirPlane>(); LevelAPI.OnBuildStart += AirPlane.OnBuildStart; LevelAPI.OnLevelCleanup += AirPlane.OnLevelCleanup; new Harmony("Inas.Oxygen").PatchAll(); foreach (string item in Directory.EnumerateFiles(OXYGEN_CONFIG_PATH, "*.json", SearchOption.AllDirectories)) { ConfigManager.Load<OxygenConfig>(item, out var config); foreach (OxygenBlock block in config.Blocks) { foreach (uint fogSetting in block.FogSettings) { if (!lookup.ContainsKey(fogSetting)) { lookup.Add(fogSetting, block); } } } } listener = LiveEdit.CreateListener(OXYGEN_CONFIG_PATH, "*.json", true); LiveEditListener obj = listener; object obj2 = <>O.<7>__Listener_FileChanged1; if (obj2 == null) { LiveEditEventHandler val = Listener_FileChanged1; <>O.<7>__Listener_FileChanged1 = val; obj2 = (object)val; } obj.FileChanged += (LiveEditEventHandler)obj2; } private static void Listener_FileChanged1(LiveEditEventArgs e) { Log.Warning("LiveEdit File Changed: " + e.FullPath + "."); LiveEdit.TryReadFileContent(e.FullPath, (Action<string>)delegate(string content) { foreach (OxygenBlock block in ConfigManager.Deserialize<OxygenConfig>(content).Blocks) { foreach (uint fogSetting in block.FogSettings) { if (lookup.ContainsKey(fogSetting)) { lookup.Remove(fogSetting); } lookup.Add(fogSetting, block); Log.Warning($"Replaced OxygenConfig for FogSetting: {fogSetting}."); } } if (GameStateManager.IsInExpedition) { AirManager.Current.UpdateAirConfig(AirManager.Current.FogSetting(), LiveEditForceUpdate: true); } }); } } } namespace Oxygen.Utils { internal static class Extension { public static T Instantiate<T>(this GameObject gameObject, string name) where T : Component { GameObject obj = Object.Instantiate<GameObject>(gameObject, gameObject.transform.parent, false); ((Object)obj).name = name; return obj.GetComponent<T>(); } } internal class LocalizedTextConverter : JsonConverter<LocalizedText> { public override bool HandleNull => false; public override LocalizedText Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { //IL_0018: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown switch (reader.TokenType) { case JsonTokenType.String: { string @string = reader.GetString(); return new LocalizedText { Id = 0u, UntranslatedText = @string }; } case JsonTokenType.Number: return new LocalizedText { Id = reader.GetUInt32(), UntranslatedText = null }; default: throw new JsonException($"LocalizedTextJson type: {reader.TokenType} is not implemented!"); } } public override void Write(Utf8JsonWriter writer, LocalizedText value, JsonSerializerOptions options) { JsonSerializer.Serialize<LocalizedText>(writer, value, options); } } internal static class Log { private static ManualLogSource source; static Log() { source = Logger.CreateLogSource("Oxygen"); } public static void Debug(object msg) { source.LogDebug(msg); } public static void Error(object msg) { source.LogError(msg); } public static void Fatal(object msg) { source.LogFatal(msg); } public static void Info(object msg) { source.LogInfo(msg); } public static void Message(object msg) { source.LogMessage(msg); } public static void Warning(object msg) { source.LogWarning(msg); } } } namespace Oxygen.Utils.PartialData { public static class MTFOPartialDataUtil { public const string PLUGIN_GUID = "MTFO.Extension.PartialBlocks"; public static JsonConverter PersistentIDConverter { get; private set; } public static JsonConverter LocalizedTextConverter { get; private set; } public static bool IsLoaded { get; private set; } public static bool Initialized { get; private set; } public static string PartialDataPath { get; private set; } public static string ConfigPath { get; private set; } static MTFOPartialDataUtil() { PersistentIDConverter = null; LocalizedTextConverter = null; IsLoaded = false; Initialized = false; PartialDataPath = string.Empty; ConfigPath = string.Empty; if (!((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.TryGetValue("MTFO.Extension.PartialBlocks", out var value)) { return; } try { Assembly obj = ((value == null) ? null : value.Instance?.GetType()?.Assembly) ?? null; if ((object)obj == null) { throw new Exception("Assembly is Missing!"); } Type[] types = obj.GetTypes(); Type type = types.First((Type t) => t.Name == "PersistentIDConverter"); if ((object)type == null) { throw new Exception("Unable to Find PersistentIDConverter Class"); } Type type2 = types.First((Type t) => t.Name == "LocalizedTextConverter"); if ((object)type2 == null) { throw new Exception("Unable to Find LocalizedTextConverter Class"); } Type obj2 = types.First((Type t) => t.Name == "PartialDataManager") ?? throw new Exception("Unable to Find PartialDataManager Class"); PropertyInfo property = obj2.GetProperty("Initialized", BindingFlags.Static | BindingFlags.Public); PropertyInfo property2 = obj2.GetProperty("PartialDataPath", BindingFlags.Static | BindingFlags.Public); PropertyInfo? property3 = obj2.GetProperty("ConfigPath", BindingFlags.Static | BindingFlags.Public); if ((object)property == null) { throw new Exception("Unable to Find Property: Initialized"); } if ((object)property2 == null) { throw new Exception("Unable to Find Property: PartialDataPath"); } if ((object)property3 == null) { throw new Exception("Unable to Find Field: ConfigPath"); } Initialized = (bool)property.GetValue(null); PartialDataPath = (string)property2.GetValue(null); ConfigPath = (string)property3.GetValue(null); PersistentIDConverter = (JsonConverter)Activator.CreateInstance(type); LocalizedTextConverter = (JsonConverter)Activator.CreateInstance(type2); IsLoaded = true; } catch (Exception value2) { Log.Error($"Exception thrown while reading data from MTFO_Extension_PartialData:\n{value2}"); } } } public static class MTFOUtil { public const string PLUGIN_GUID = "com.dak.MTFO"; public const BindingFlags PUBLIC_STATIC = BindingFlags.Static | BindingFlags.Public; public static string GameDataPath { get; private set; } public static string CustomPath { get; private set; } public static bool HasCustomContent { get; private set; } public static bool IsLoaded { get; private set; } static MTFOUtil() { GameDataPath = string.Empty; CustomPath = string.Empty; HasCustomContent = false; IsLoaded = false; if (!((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.TryGetValue("com.dak.MTFO", out var value)) { return; } try { Assembly obj = ((value == null) ? null : value.Instance?.GetType()?.Assembly) ?? null; if ((object)obj == null) { throw new Exception("Assembly is Missing!"); } Type obj2 = obj.GetTypes().First((Type t) => t.Name == "ConfigManager") ?? throw new Exception("Unable to Find ConfigManager Class"); FieldInfo field = obj2.GetField("GameDataPath", BindingFlags.Static | BindingFlags.Public); FieldInfo field2 = obj2.GetField("CustomPath", BindingFlags.Static | BindingFlags.Public); FieldInfo? field3 = obj2.GetField("HasCustomContent", BindingFlags.Static | BindingFlags.Public); if ((object)field == null) { throw new Exception("Unable to Find Field: GameDataPath"); } if ((object)field2 == null) { throw new Exception("Unable to Find Field: CustomPath"); } if ((object)field3 == null) { throw new Exception("Unable to Find Field: HasCustomContent"); } GameDataPath = (string)field.GetValue(null); CustomPath = (string)field2.GetValue(null); HasCustomContent = (bool)field3.GetValue(null); IsLoaded = true; } catch (Exception value2) { Log.Error($"Exception thrown while reading path from DataDumper (MTFO): \n{value2}"); } } } } namespace Oxygen.Patches { [HarmonyPatch] internal class Patches_Dam_PlayerDamageLocal { [HarmonyPrefix] [HarmonyPatch(typeof(Dam_PlayerDamageLocal), "ReceiveNoAirDamage")] public static bool Pre_ReceiveNoAirDamage(Dam_PlayerDamageLocal __instance, pMiniDamageData data) { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) float num = ((UFloat16)(ref data.damage)).Get(((Dam_SyncedDamageBase)__instance).HealthMax); ((Dam_PlayerDamageBase)__instance).m_nextRegen = Clock.Time + ((Dam_PlayerDamageBase)__instance).Owner.PlayerData.healthRegenStartDelayAfterDamage; if (((Agent)((Dam_PlayerDamageBase)__instance).Owner).IsLocallyOwned) { DramaManager.CurrentState.OnLocalDamage(num); GameEventManager.PostEvent((eGameEvent)13, ((Dam_PlayerDamageBase)__instance).Owner, num, "", (Dictionary<string, string>)null); } else { DramaManager.CurrentState.OnTeammatesDamage(num); } if (((Dam_PlayerDamageBase)__instance).IgnoreAllDamage) { return false; } if (SNet.IsMaster && !((Dam_SyncedDamageBase)__instance).RegisterDamage(num)) { ((Dam_SyncedDamageBase)__instance).SendSetHealth(((Dam_SyncedDamageBase)__instance).Health); } __instance.Hitreact(((UFloat16)(ref data.damage)).Get(((Dam_SyncedDamageBase)__instance).HealthMax), Vector3.zero, true, false, false); return false; } [HarmonyPostfix] [HarmonyPatch(typeof(Dam_PlayerDamageLocal), "ReceiveBulletDamage")] public static void Post_ReceiveBulletDamage() { AirManager.Current.ResetHealthToRegen(); } [HarmonyPostfix] [HarmonyPatch(typeof(Dam_PlayerDamageLocal), "ReceiveMeleeDamage")] public static void Post_ReceiveMeleeDamage() { AirManager.Current.ResetHealthToRegen(); } [HarmonyPostfix] [HarmonyPatch(typeof(Dam_PlayerDamageLocal), "ReceiveFireDamage")] public static void Post_ReceiveFireDamage() { AirManager.Current.ResetHealthToRegen(); } [HarmonyPostfix] [HarmonyPatch(typeof(Dam_PlayerDamageLocal), "ReceiveShooterProjectileDamage")] public static void Post_ReceiveShooterProjectileDamage() { AirManager.Current.ResetHealthToRegen(); } [HarmonyPostfix] [HarmonyPatch(typeof(Dam_PlayerDamageLocal), "ReceiveTentacleAttackDamage")] public static void Post_ReceiveTentacleAttackDamage() { AirManager.Current.ResetHealthToRegen(); } [HarmonyPostfix] [HarmonyPatch(typeof(Dam_PlayerDamageLocal), "ReceivePushDamage")] public static void Post_ReceivePushDamage() { AirManager.Current.ResetHealthToRegen(); } [HarmonyPostfix] [HarmonyPatch(typeof(Dam_PlayerDamageLocal), "ReceiveSetDead")] public static void Post_ReceiveSetDead() { AirManager.Current.ResetHealthToRegen(); } } [HarmonyPatch(typeof(EnvironmentStateManager), "UpdateFog")] internal class EnvironmentStateManager_UpdateFog { public static void Prefix(EnvironmentStateManager __instance) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_0039: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)AirManager.Current == (Object)null) { return; } FogState val = ((Il2CppArrayBase<FogState>)(object)__instance.m_stateReplicator.State.FogStates)[__instance.m_latestKnownLocalDimensionCreationIndex]; if (val.FogDataID != 0) { AirManager.Current.UpdateAirConfig(val.FogDataID); if (!AirManager.Current.HasAirConfig()) { AirManager.Current.StopInfectionLoop(); } } } } [HarmonyPatch(typeof(FogRepeller_Sphere), "StartRepelling")] internal class FogRepeller_Sphere_StartRepelling { public static void Postfix(ref FogRepeller_Sphere __instance) { if (__instance.m_infectionShield != null) { EffectVolumeManager.UnregisterVolume((EffectVolume)(object)__instance.m_infectionShield); ((EffectVolume)__instance.m_infectionShield).contents = (eEffectVolumeContents)0; EffectVolumeManager.RegisterVolume((EffectVolume)(object)__instance.m_infectionShield); } } } [HarmonyPatch(typeof(LocalPlayerAgentSettings), "UpdateBlendTowardsTargetFogSetting")] internal class LocalPlayerAgentSettings_UpdateBlendTowardsTargetFogSetting { public static void Postfix(LocalPlayerAgentSettings __instance, float amount) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) if (!AirManager.Current.HasAirConfig()) { AirPlane.Current.Unregister(); } else { if (__instance.m_targetFogSettings == null || !SNet.LocalPlayer.HasPlayerAgent) { return; } PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent(); if ((Object)(object)localPlayerAgent.FPSCamera == (Object)null) { return; } AirPlane current = AirPlane.Current; if (!((Object)(object)current == (Object)null) && RundownManager.ExpeditionIsStarted) { float num = 0f; Dimension val = default(Dimension); if (Dimension.GetDimension(((Agent)localPlayerAgent).DimensionIndex, ref val)) { num = val.GroundY; } PreLitVolume prelitVolume = localPlayerAgent.FPSCamera.PrelitVolume; ((EffectVolume)current.airPlane).invert = (double)prelitVolume.m_densityHeightMaxBoost > (double)prelitVolume.m_fogDensity; ((EffectVolume)current.airPlane).contents = (eEffectVolumeContents)1; ((EffectVolume)current.airPlane).modification = (eEffectVolumeModification)0; ((EffectVolume)current.airPlane).modificationScale = AirManager.Current.AirLoss(); current.airPlane.lowestAltitude = prelitVolume.m_densityHeightAltitude + num; current.airPlane.highestAltitude = prelitVolume.m_densityHeightAltitude + prelitVolume.m_densityHeightRange + num; AirPlane.Current.Register(); } } } } [HarmonyPatch(typeof(PlayerAgent), "ReceiveModification")] internal class PlayerAgent_ReceiveModification { public static void Prefix(PlayerAgent __instance, ref EV_ModificationData data) { if (AirManager.Current.HasAirConfig()) { if ((double)data.health != 0.0) { AirManager.Current.RemoveAir(data.health); } else { AirManager.Current.AddAir(); } data.health = 0f; } } } } namespace Oxygen.Config { public class ConfigManager { private static readonly JsonSerializerOptions s_SerializerOptions; public static T Deserialize<T>(string json) { return JsonSerializer.Deserialize<T>(json, s_SerializerOptions); } public static string Serialize<T>(T value) { return JsonSerializer.Serialize(value, s_SerializerOptions); } static ConfigManager() { s_SerializerOptions = new JsonSerializerOptions { AllowTrailingCommas = true, ReadCommentHandling = JsonCommentHandling.Skip, PropertyNameCaseInsensitive = true, WriteIndented = true }; s_SerializerOptions.Converters.Add(new JsonStringEnumConverter()); if (MTFOPartialDataUtil.IsLoaded && MTFOPartialDataUtil.Initialized) { s_SerializerOptions.Converters.Add(MTFOPartialDataUtil.PersistentIDConverter); s_SerializerOptions.Converters.Add(MTFOPartialDataUtil.LocalizedTextConverter); Log.Message("PartialData Support Found!"); } else { s_SerializerOptions.Converters.Add(new LocalizedTextConverter()); } } public static void Load<T>(string file, out T config) where T : new() { if (file.Length < ".json".Length) { config = default(T); return; } if (file.Substring(file.Length - ".json".Length) != ".json") { file += ".json"; } file = File.ReadAllText(Path.Combine(ConfigManager.CustomPath, "Oxygen", file)); config = Deserialize<T>(file); } } public class AirText { public float x { get; set; } public float y { get; set; } public LocalizedText Text { get; set; } } public class OxygenConfig { public List<OxygenBlock> Blocks { get; set; } = new List<OxygenBlock> { new OxygenBlock() }; } public class OxygenBlock { public float AirLoss { get; set; } public float AirGain { get; set; } = 1f; public float DamageTime { get; set; } = 1f; public float DamageAmount { get; set; } public bool ShatterGlass { get; set; } public float ShatterAmount { get; set; } public float DamageThreshold { get; set; } = 0.1f; public bool AlwaysDisplayAirBar { get; set; } public float HealthRegenProportion { get; set; } = 1f; public float TimeToStartHealthRegen { get; set; } = 3f; public float TimeToCompleteHealthRegen { get; set; } = 5f; public AirText AirText { get; set; } public List<uint> FogSettings { get; set; } = new List<uint> { 0u }; } } namespace Oxygen.Components { public class AirBar : MonoBehaviour { public static AirBar Current; private TextMeshPro m_airText; private TextMeshPro m_airTextLocalization; private float m_airTextX; private float m_airTextY; private float m_airTextZ; private RectTransform m_air1; private RectTransform m_air2; private SpriteRenderer m_airBar1; private SpriteRenderer m_airBar2; private float m_airWidth = 100f; private float m_barHeightMin = 3f; private float m_barHeightMax = 9f; private Color m_airLow = new Color(0f, 0.5f, 0.5f); private Color m_airHigh = new Color(0f, 0.3f, 0.8f); public AirBar(IntPtr value) : base(value) { }//IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) public static void Setup() { if ((Object)(object)Current == (Object)null) { Current = ((Component)GuiManager.Current.m_playerLayer.m_playerStatus).gameObject.AddComponent<AirBar>(); Current.Init(); } } private void Init() { //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)m_airText == (Object)null) { m_airText = ((Component)GuiManager.Current.m_playerLayer.m_playerStatus.m_healthText).gameObject.Instantiate<TextMeshPro>("AirText"); TextMeshPro airText = m_airText; ((TMP_Text)airText).fontSize = ((TMP_Text)airText).fontSize / 1.25f; m_airText.transform.Translate(0f, -30f, 0f); } if ((Object)(object)m_airTextLocalization == (Object)null) { m_airTextLocalization = ((Component)GuiManager.Current.m_playerLayer.m_playerStatus.m_pulseText).gameObject.Instantiate<TextMeshPro>("AirText Localization"); ((Behaviour)m_airTextLocalization).enabled = true; m_airTextLocalization.transform.Translate(300f - m_airWidth, -45f, 0f); m_airTextX = m_airTextLocalization.transform.position.x; m_airTextY = m_airTextLocalization.transform.position.y; m_airTextZ = m_airTextLocalization.transform.position.z; } if ((Object)(object)m_air1 == (Object)null) { m_air1 = ((Component)((Component)GuiManager.Current.m_playerLayer.m_playerStatus.m_health1).gameObject.transform.parent).gameObject.Instantiate<RectTransform>("AirFill Right"); ((Component)m_air1).transform.Translate(0f, -30f, 0f); SpriteRenderer component = ((Component)((Transform)m_air1).GetChild(0)).GetComponent<SpriteRenderer>(); component.size = new Vector2(m_airWidth, component.size.y); m_airBar1 = ((Component)((Transform)m_air1).GetChild(1)).GetComponent<SpriteRenderer>(); ((Renderer)((Component)((Transform)m_air1).GetChild(2)).GetComponent<SpriteRenderer>()).enabled = false; } if ((Object)(object)m_air2 == (Object)null) { m_air2 = ((Component)((Component)GuiManager.Current.m_playerLayer.m_playerStatus.m_health2).gameObject.transform.parent).gameObject.Instantiate<RectTransform>("AirFill Left"); ((Component)m_air2).transform.Translate(0f, 30f, 0f); SpriteRenderer component2 = ((Component)((Transform)m_air2).GetChild(0)).GetComponent<SpriteRenderer>(); component2.size = new Vector2(m_airWidth, component2.size.y); m_airBar2 = ((Component)((Transform)m_air2).GetChild(1)).GetComponent<SpriteRenderer>(); ((Renderer)((Component)((Transform)m_air2).GetChild(2)).GetComponent<SpriteRenderer>()).enabled = false; } UpdateAirBar(1f); SetVisible(vis: false); } public void UpdateAirBar(float air) { SetAirPercentageText(air); SetAirBar(m_airBar1, air); SetAirBar(m_airBar2, air); } private void SetAirBar(SpriteRenderer bar, float val) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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: Unknown result type (might be due to invalid IL or missing references) bar.size = new Vector2(val * m_airWidth, Mathf.Lerp(m_barHeightMin, m_barHeightMax, val)); bar.color = Color.Lerp(m_airLow, m_airHigh, val); } private void SetAirPercentageText(float val) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) Color color = Color.Lerp(m_airLow, m_airHigh, val); ((TMP_Text)m_airText).text = "O<size=75%>2</size>"; ((Graphic)m_airText).color = color; ((TMP_Text)m_airText).ForceMeshUpdate(true, false); ((Graphic)m_airTextLocalization).color = color; ((TMP_Text)m_airTextLocalization).ForceMeshUpdate(true, false); } public void UpdateAirText(OxygenBlock config) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) if (config != null) { string text = LocalizedText.op_Implicit(config.AirText.Text); float x = config.AirText.x; float y = config.AirText.y; ((TMP_Text)m_airTextLocalization).text = text; ((TMP_Text)m_airTextLocalization).ForceMeshUpdate(true, false); CoroutineManager.BlinkIn(((Component)m_airTextLocalization).gameObject, 0f); m_airTextLocalization.transform.SetPositionAndRotation(new Vector3(m_airTextX + x, m_airTextY + y, m_airTextZ), m_airTextLocalization.transform.rotation); } } public void SetVisible(bool vis) { ((Component)m_airText).gameObject.SetActive(vis); ((Component)m_airTextLocalization).gameObject.SetActive(vis); ((Component)m_air1).gameObject.SetActive(vis); ((Component)m_air2).gameObject.SetActive(vis); } public static void OnLevelCleanup() { if (!((Object)(object)Current == (Object)null)) { Current.SetVisible(vis: false); } } } public class AirManager : MonoBehaviour { public static AirManager Current; public PlayerAgent m_playerAgent; private HUDGlassShatter m_hudGlass; private Dam_PlayerDamageBase Damage; public OxygenBlock config; private uint fogSetting; private FogSettingsDataBlock fogSettingDB; private float airAmount = 1f; private float damageTick; private float glassShatterAmount; private bool m_isInInfectionLoop; private bool isRegeningHealth; private float healthToRegen; private float healthRegenTick; private float tickUntilHealthRegenHealthStart; private readonly float regenHealthTickInterval = 0.25f; private float healthRegenAmountPerInterval; internal bool PlayerShouldCough; private readonly float CoughPerLoss = 0.1f; private float CoughLoss; public AirManager(IntPtr value) : base(value) { } public static void Setup() { if ((Object)(object)Current == (Object)null) { Current = ((Component)PlayerManager.Current.m_localPlayerAgentInLevel).gameObject.AddComponent<AirManager>(); } } public static void OnBuildDone() { if (!((Object)(object)Current == (Object)null)) { Current.m_playerAgent = PlayerManager.GetLocalPlayerAgent(); Current.m_hudGlass = ((Component)Current.m_playerAgent.FPSCamera).GetComponent<HUDGlassShatter>(); Current.Damage = ((Component)Current.m_playerAgent).gameObject.GetComponent<Dam_PlayerDamageBase>(); Current.UpdateAirConfig(RundownManager.ActiveExpedition.Expedition.FogSettings); AirBar.Current.UpdateAirText(Current.config); } } public static void OnLevelCleanup() { if (!((Object)(object)Current == (Object)null)) { if (Current.m_isInInfectionLoop) { Current.StopInfectionLoop(); } Current.config = null; Current.fogSetting = 0u; Current.fogSettingDB = null; Current.airAmount = 0f; Current.damageTick = 0f; Current.glassShatterAmount = 0f; Current.healthToRegen = 0f; Current.m_playerAgent = null; Current.m_hudGlass = null; Current.Damage = null; } } private void Update() { if (!RundownManager.ExpeditionIsStarted) { return; } if (!HasAirConfig()) { AirBar.Current.SetVisible(vis: false); return; } if (airAmount == 1f) { if (config.AlwaysDisplayAirBar) { AirBar.Current.SetVisible(vis: true); } else { AirBar.Current.SetVisible(vis: false); } } else { AirBar.Current.SetVisible(vis: true); } if (airAmount <= config.DamageThreshold) { damageTick += Time.deltaTime; if (damageTick > config.DamageTime && ((Dam_SyncedDamageBase)Damage).Health > 0f && ((Agent)m_playerAgent).Alive) { AirDamage(); } isRegeningHealth = false; } else if (healthToRegen > 0f) { tickUntilHealthRegenHealthStart += Time.deltaTime; if (tickUntilHealthRegenHealthStart > config.TimeToStartHealthRegen) { if (healthRegenAmountPerInterval == 0f) { healthRegenAmountPerInterval = healthToRegen * (regenHealthTickInterval / config.TimeToCompleteHealthRegen); } RegenHealth(); if (!isRegeningHealth) { Damage.m_nextRegen = Clock.Time + config.TimeToStartHealthRegen + config.TimeToCompleteHealthRegen; isRegeningHealth = true; } } } else { isRegeningHealth = false; } } public void AddAir() { if (HasAirConfig()) { float airGain = config.AirGain; airAmount = Mathf.Clamp01(airAmount + airGain); AirBar.Current.UpdateAirBar(airAmount); if (fogSettingDB.Infection <= 0f && m_isInInfectionLoop) { StopInfectionLoop(); } } } public void RemoveAir(float amount) { if (HasAirConfig()) { amount = config.AirLoss; airAmount = Mathf.Clamp01(airAmount - amount); AirBar.Current.UpdateAirBar(airAmount); if (fogSettingDB.Infection <= 0f && amount > 0f) { StartInfectionLoop(); } } } public void AirDamage() { float health = ((Dam_SyncedDamageBase)Damage).Health; float num = config.DamageAmount; if (num > health) { num = ((health > 0f) ? (health - 0.001f) : 0f); } ((Dam_SyncedDamageBase)Damage).NoAirDamage(num); if (config.ShatterGlass) { glassShatterAmount += config.ShatterAmount; m_hudGlass.SetGlassShatterProgression(glassShatterAmount); } damageTick = 0f; tickUntilHealthRegenHealthStart = 0f; healthRegenAmountPerInterval = 0f; healthToRegen += num * config.HealthRegenProportion; CoughLoss += num; if (CoughLoss > CoughPerLoss) { PlayerShouldCough = true; CoughLoss = 0f; } } public void RegenHealth() { if (healthToRegen <= 0f) { return; } tickUntilHealthRegenHealthStart = config.TimeToStartHealthRegen; healthRegenTick += Time.deltaTime; if (healthRegenTick > regenHealthTickInterval) { float num = healthRegenAmountPerInterval; if (num >= healthToRegen) { num = healthToRegen; healthToRegen = 0f; tickUntilHealthRegenHealthStart = 0f; healthRegenAmountPerInterval = 0f; isRegeningHealth = false; } else { healthToRegen -= num; } ((Dam_SyncedDamageBase)Damage).AddHealth(num, (Agent)(object)m_playerAgent); healthRegenTick = 0f; } } public void UpdateAirConfig(uint fogsetting, bool LiveEditForceUpdate = false) { if (fogsetting != 0 && (fogsetting != fogSetting || LiveEditForceUpdate)) { if (Plugin.lookup.ContainsKey(fogsetting)) { config = Plugin.lookup[fogsetting]; } else if (Plugin.lookup.ContainsKey(0u)) { config = Plugin.lookup[0u]; } else { config = null; airAmount = 1f; } fogSetting = fogsetting; fogSettingDB = GameDataBlockBase<FogSettingsDataBlock>.GetBlock(fogsetting); if (GameStateManager.IsInExpedition) { AirBar.Current.UpdateAirText(config); } } } public void ResetHealthToRegen() { healthRegenTick = 0f; healthToRegen = 0f; tickUntilHealthRegenHealthStart = 0f; } public float AirLoss() { if (config != null) { return config.AirLoss; } return 0f; } public bool AlwaysDisplayAirBar() { if (config != null) { return config.AlwaysDisplayAirBar; } return false; } public uint FogSetting() { return fogSetting; } public float HealthToRegen() { return healthToRegen; } public string AirText() { return LocalizedText.op_Implicit((config == null) ? null : config.AirText.Text); } public float AirTextX() { if (config != null) { return config.AirText.x; } return 0f; } public float AirTextY() { if (config != null) { return config.AirText.y; } return 0f; } public bool HasAirConfig() { return config != null; } public void StartInfectionLoop() { if (!m_isInInfectionLoop) { m_playerAgent.Sound.Post(EVENTS.INFECTION_EFFECT_LOOP_START, true); m_isInInfectionLoop = true; } } public void StopInfectionLoop() { if (m_isInInfectionLoop) { if ((Object)(object)m_playerAgent != (Object)null && m_playerAgent.Sound != null) { m_playerAgent.Sound.Post(EVENTS.INFECTION_EFFECT_LOOP_STOP, true); } m_isInInfectionLoop = false; } } } public class AirPlane : MonoBehaviour { public static AirPlane Current; public EV_Plane airPlane; private bool isAirPlaneRegistered; public AirPlane(IntPtr value) : base(value) { } public static void OnBuildStart() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown if ((Object)(object)Current == (Object)null) { Current = ((Component)LocalPlayerAgentSettings.Current).gameObject.AddComponent<AirPlane>(); } Current.airPlane = new EV_Plane(); uint num = RundownManager.ActiveExpedition.Expedition.FogSettings; if (num == 0) { num = 21u; } OxygenBlock oxygenBlock = (Plugin.lookup.ContainsKey(num) ? Plugin.lookup[num] : ((!Plugin.lookup.ContainsKey(0u)) ? null : Plugin.lookup[0u])); FogSettingsDataBlock block = GameDataBlockBase<FogSettingsDataBlock>.GetBlock(num); ((EffectVolume)Current.airPlane).invert = block.DensityHeightMaxBoost > block.FogDensity; ((EffectVolume)Current.airPlane).contents = (eEffectVolumeContents)1; ((EffectVolume)Current.airPlane).modification = (eEffectVolumeModification)0; Current.airPlane.lowestAltitude = block.DensityHeightAltitude; Current.airPlane.highestAltitude = block.DensityHeightAltitude + block.DensityHeightRange; if (oxygenBlock != null) { ((EffectVolume)Current.airPlane).modificationScale = oxygenBlock.AirLoss; Current.Register(); } } public static void OnLevelCleanup() { if (!((Object)(object)Current == (Object)null)) { Current.Unregister(); Current.isAirPlaneRegistered = false; Current.airPlane = null; } } public void Register() { if (airPlane != null && !isAirPlaneRegistered) { EffectVolumeManager.RegisterVolume((EffectVolume)(object)airPlane); isAirPlaneRegistered = true; } } public void Unregister() { if (airPlane != null && isAirPlaneRegistered) { EffectVolumeManager.UnregisterVolume((EffectVolume)(object)airPlane); isAirPlaneRegistered = false; } } } } namespace Oxygen.Utils.SU { internal class InventoryPatches { public unsafe delegate void UpdateItems(IntPtr _this, IntPtr data, Il2CppMethodInfo* methodInfo); [HarmonyPatch(typeof(DropServerClientAPIViaPlayFab), "GetInventoryPlayerDataAsync")] public static class DropServerClientAPI_GetInventoryPlayerDataAsync_Patch { public static bool Prefix(GetInventoryPlayerDataRequest request, ref Task<GetInventoryPlayerDataResult> __result) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown VanityItemPlayerData val = new VanityItemPlayerData(ClassInjector.DerivedConstructorPointer<VanityItemPlayerData>()); val.Items = new Il2CppReferenceArray<VanityItem>(0L); BoosterImplantPlayerData val2 = new BoosterImplantPlayerData(ClassInjector.DerivedConstructorPointer<BoosterImplantPlayerData>()); val2.Advanced = EmptyCat(); val2.Basic = EmptyCat(); val2.Specialized = EmptyCat(); GetInventoryPlayerDataResult val3 = new GetInventoryPlayerDataResult(ClassInjector.DerivedConstructorPointer<GetInventoryPlayerDataResult>()) { Boosters = val2, VanityItems = val }; __result = Task.FromResult<GetInventoryPlayerDataResult>(val3); return false; } } internal List<INativeDetour> _detours = new List<INativeDetour>(); private UpdateItems _patchMethod; private UpdateItems _originalUpdateItems; internal unsafe void ApplyNative() { _patchMethod = UpdateItemsPatch; _detours.Add(INativeDetour.CreateAndApply<UpdateItems>((IntPtr)(nint)Il2CppAPI.GetIl2CppMethod<VanityItemInventory>("UpdateItems", typeof(void).FullName, false, new string[1] { typeof(VanityItemPlayerData).FullName }), _patchMethod, ref _originalUpdateItems)); } public unsafe void UpdateItemsPatch(IntPtr _this, IntPtr data, Il2CppMethodInfo* methodInfo) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) _originalUpdateItems(_this, data, methodInfo); VanityItemInventory val = new VanityItemInventory(_this); if (val.m_backednItems == null) { val.m_backednItems = new List<VanityItem>(0); } foreach (VanityItemsTemplateDataBlock allBlock in GameDataBlockBase<VanityItemsTemplateDataBlock>.GetAllBlocks()) { VanityItem val2 = new VanityItem(ClassInjector.DerivedConstructorPointer<VanityItem>()); val2.publicName = allBlock.publicName; val2.type = allBlock.type; val2.prefab = allBlock.prefab; val2.flags = (VanityItemFlags)3; val2.id = ((GameDataBlockBase<VanityItemsTemplateDataBlock>)(object)allBlock).persistentID; val.m_backednItems.Add(val2); } } private static Category EmptyCat() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown return new Category(ClassInjector.DerivedConstructorPointer<Category>()) { Inventory = new Il2CppReferenceArray<BoosterImplantInventoryItem>(0L) }; } } internal static class LobbyPatches { [HarmonyPatch(typeof(CM_PlayerLobbyBar), "SetupFromPage")] public static class CM_PlayerLobbyBar_SetupFromPage_Patch { public static void Postfix(CM_PlayerLobbyBar __instance) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) __instance.m_boosterImplantAlign.position = new Vector3(10000f, 0f, 0f); } } } [BepInPlugin("sameutils", "SamUtils", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BasePlugin { public const string PLUGIN_GUID = "sameutils"; public const string PLUGIN_NAME = "SamUtils"; public const string PLUGIN_VERSION = "1.0.0"; private static Plugin _instance; private readonly Harmony _harmony = new Harmony("sameutils"); private static InventoryPatches _patches; private static bool _initialLoad = true; public override void Load() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown _instance = this; if (_initialLoad) { _harmony.Patch((MethodBase)typeof(GameDataInit).GetMethod("Initialize"), (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin).GetMethod("OnAfterGameDataInit")), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _initialLoad = false; return; } _patches = new InventoryPatches(); _patches.ApplyNative(); _harmony.PatchAll(typeof(LobbyPatches.CM_PlayerLobbyBar_SetupFromPage_Patch)); _harmony.PatchAll(typeof(InventoryPatches.DropServerClientAPI_GetInventoryPlayerDataAsync_Patch)); } public static void OnAfterGameDataInit() { if (!((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.Any((KeyValuePair<string, PluginInfo> p) => p.Value.Metadata.GUID == "samutils")) { ((BasePlugin)_instance).Load(); } } internal static void LogMsg(string v) { ((BasePlugin)_instance).Log.LogMessage((object)v); } } }
plugins/CustomRundownLabels.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text.Json; using BepInEx; using BepInEx.Unity.IL2CPP; using GameData; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using TMPro; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")] [assembly: AssemblyCompany("CustomRundownLabels")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("CustomRundownLabels")] [assembly: AssemblyTitle("CustomRundownLabels")] [assembly: AssemblyVersion("1.0.0.0")] namespace CustomRundownLabels; public class ConfigSerializer<T> where T : new() { private string JsonPath; private T JsonSettings; private FileStream JsonFile; private JsonSerializerOptions JsonOptions; public T Settings => JsonSettings; public ConfigSerializer(string jsonName) { JsonPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), jsonName + ".json"); JsonSettings = new T(); JsonOptions = new JsonSerializerOptions { AllowTrailingCommas = true, WriteIndented = true }; if (File.Exists(JsonPath)) { JsonFile = File.OpenRead(JsonPath); JsonSettings = JsonSerializer.Deserialize<T>(JsonFile, JsonOptions); } else { JsonFile = File.OpenWrite(JsonPath); JsonSerializer.Serialize(JsonFile, JsonSettings, JsonOptions); } JsonFile.Close(); } } [BepInPlugin("me.bro.customrundownlabels", "CustomRundownLabels", "1.0.0")] public class EntryPoint : BasePlugin { public ConfigSerializer<fucking> Fucking; public override void Load() { PlayFabManager.OnTitleDataUpdated += Action.op_Implicit((Action)Setup); } public void Setup() { Fucking = new ConfigSerializer<fucking>("CustomRundownName"); int num = 0; Enumerator<CM_RundownSelection> enumerator = MainMenuGuiLayer.Current.PageRundownNew.m_rundownSelections.GetEnumerator(); while (enumerator.MoveNext()) { CM_RundownSelection current = enumerator.Current; if ((Object)(object)current.m_altText != (Object)null) { Object.Destroy((Object)(object)((Component)current.m_altText).gameObject); } ((TMP_Text)current.m_rundownText).text = Fucking.Settings.Labels[num]; num++; } } } public class fucking { public bool UseCustomNames { get; set; } public List<string> Labels { get; set; } public fucking() { Labels = new List<string> { "R1", "R7", "R2", "R3", "R4", "R5", "R6", "R8" }; } private void nextfucking() { Enumerator<CM_RundownSelection> enumerator = MainMenuGuiLayer.Current.PageRundownNew.m_rundownSelections.GetEnumerator(); while (enumerator.MoveNext()) { CM_RundownSelection current = enumerator.Current; uint num = uint.Parse(current.RundownKey.Substring("Local_".Length)); if (GameDataBlockBase<RundownDataBlock>.s_blockByID != null && GameDataBlockBase<RundownDataBlock>.s_blockByID.ContainsKey(num)) { RundownDataBlock val = GameDataBlockBase<RundownDataBlock>.s_blockByID[num]; string untranslatedText = val.StorytellingData.Title.UntranslatedText; Labels.Add(untranslatedText); } } } }
plugins/GTFO-API.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Linq; using System.Net.Http; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using System.Text.RegularExpressions; using AIGraph; using AssetShards; using BepInEx; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using BepInEx.Unity.IL2CPP.Hook; using BepInEx.Unity.IL2CPP.Utils; using GTFO.API.Attributes; using GTFO.API.Components; using GTFO.API.Extensions; using GTFO.API.Impl; using GTFO.API.JSON; using GTFO.API.JSON.Converters; using GTFO.API.Native; using GTFO.API.Resources; using GTFO.API.Utilities; using GTFO.API.Utilities.Impl; using GTFO.API.Wrappers; using GameData; using Gear; using Globals; using HarmonyLib; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.Attributes; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppInterop.Runtime.Runtime; using Il2CppInterop.Runtime.Runtime.VersionSpecific.Class; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using Il2CppSystem.Reflection; using ItemSetup; using LevelGeneration; using Localization; using Microsoft.CodeAnalysis; using Player; using SNetwork; using UnityEngine; using UnityEngine.Analytics; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("GTFO-API")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.4.1")] [assembly: AssemblyInformationalVersion("0.4.1+git1e8fe81-main")] [assembly: AssemblyProduct("GTFO-API")] [assembly: AssemblyTitle("GTFO-API")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.4.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.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 GTFO.API { internal static class APILogger { private static readonly ManualLogSource _logger; static APILogger() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown _logger = new ManualLogSource("GTFO-API"); Logger.Sources.Add((ILogSource)(object)_logger); } private static string Format(string module, object msg) { return $"[{module}]: {msg}"; } public static void Info(string module, object data) { _logger.LogMessage((object)Format(module, data)); } public static void Verbose(string module, object data) { } public static void Debug(string module, object data) { _logger.LogDebug((object)Format(module, data)); } public static void Warn(string module, object data) { _logger.LogWarning((object)Format(module, data)); } public static void Error(string module, object data) { _logger.LogError((object)Format(module, data)); } } [API("Asset")] public static class AssetAPI { internal static ConcurrentDictionary<string, Object> s_RegistryCache = new ConcurrentDictionary<string, Object>(); public static ApiStatusInfo Status => APIStatus.Asset; public static event Action OnStartupAssetsLoaded; public static event Action OnAssetBundlesLoaded; public static event Action OnImplReady; public static bool ContainsAsset(string assetName) { string text = assetName.ToUpper(); if (!APIStatus.Asset.Ready) { return s_RegistryCache.ContainsKey(text); } return AssetShardManager.s_loadedAssetsLookup.ContainsKey(text); } public static Object GetLoadedAsset(string path) { string text = path.ToUpper(); APILogger.Verbose("Asset", "Requested Asset: " + text); try { if (!APIStatus.Asset.Ready && s_RegistryCache.TryGetValue(text, out var value)) { return value; } return AssetShardManager.GetLoadedAsset(text, false); } catch { return null; } } public static TAsset GetLoadedAsset<TAsset>(string path) where TAsset : Object { Object loadedAsset = GetLoadedAsset(path); if (loadedAsset == null) { return default(TAsset); } return ((Il2CppObjectBase)loadedAsset).Cast<TAsset>(); } public static void RegisterAsset(string name, Object gameObject) { string text = name.ToUpper(); if (!APIStatus.Asset.Ready) { if (s_RegistryCache.ContainsKey(text)) { throw new ArgumentException("The asset with " + text + " has already been registered.", "name"); } s_RegistryCache.TryAdd(text, gameObject); } else { AssetAPI_Impl.Instance.RegisterAsset(text, gameObject); } } public static void RegisterAssetBundle(AssetBundle bundle) { string[] array = Il2CppArrayBase<string>.op_Implicit((Il2CppArrayBase<string>)(object)bundle.AllAssetNames()); APILogger.Verbose("Asset", "Bundle names: [" + string.Join(", ", array) + "]"); string[] array2 = array; foreach (string text in array2) { Object val = bundle.LoadAsset(text); if (val != (Object)null) { RegisterAsset(text, val); } else { APILogger.Warn("Asset", "Skipping asset " + text); } } } public static void LoadAndRegisterAssetBundle(string pathToBundle) { AssetBundle obj = AssetBundle.LoadFromFile(pathToBundle); if ((Object)(object)obj == (Object)null) { throw new Exception("Failed to load asset bundle"); } RegisterAssetBundle(obj); } public static void LoadAndRegisterAssetBundle(byte[] bundleBytes) { AssetBundle obj = AssetBundle.LoadFromMemory(Il2CppStructArray<byte>.op_Implicit(bundleBytes)); if ((Object)(object)obj == (Object)null) { throw new Exception("Failed to load asset bundle"); } RegisterAssetBundle(obj); } public static Object InstantiateAsset(string assetName, string copyName) { if (ContainsAsset(copyName)) { throw new ArgumentException("The asset you're trying to copy into is already registered", "copyName"); } RegisterAsset(copyName, Object.Instantiate(GetLoadedAsset(assetName) ?? throw new ArgumentException("Couldn't find an asset with the name '" + assetName + "'", "assetName"))); return GetLoadedAsset(copyName); } public static TAsset InstantiateAsset<TAsset>(string assetName, string copyName) where TAsset : Object { Object obj = InstantiateAsset(assetName, copyName); if (obj == null) { return default(TAsset); } return ((Il2CppObjectBase)obj).Cast<TAsset>(); } public static bool TryInstantiateAsset<TAsset>(string assetName, string copyName, out TAsset clonedObj) where TAsset : Object { Object obj = InstantiateAsset(assetName, copyName); clonedObj = ((obj != null) ? ((Il2CppObjectBase)obj).TryCast<TAsset>() : default(TAsset)); return (Object)(object)clonedObj != (Object)null; } private static void OnAssetsLoaded() { if (!APIStatus.Asset.Created) { APIStatus.CreateApi<AssetAPI_Impl>("Asset"); } AssetAPI.OnStartupAssetsLoaded?.Invoke(); } internal static void InvokeImplReady() { AssetAPI.OnImplReady?.Invoke(); } internal static void Setup() { EventAPI.OnAssetsLoaded += OnAssetsLoaded; OnImplReady += LoadAssetBundles; } private static void LoadAssetBundles() { string assetBundlesDir = Path.Combine(Paths.BepInExRootPath, "Assets", "AssetBundles"); string assetBundlesDir2 = Path.Combine(Paths.ConfigPath, "Assets", "AssetBundles"); if (LoadAssetBundles(assetBundlesDir) | LoadAssetBundles(assetBundlesDir2, outdated: true)) { AssetAPI.OnAssetBundlesLoaded?.Invoke(); } } private static bool LoadAssetBundles(string assetBundlesDir, bool outdated = false) { if (outdated) { if (!Directory.Exists(assetBundlesDir)) { return false; } APILogger.Warn("AssetAPI", "Storing asset bundles in the config path is deprecated and will be removed in a future version of GTFO-API. The path has been moved to 'BepInEx\\Assets\\AssetBundles'."); } if (!Directory.Exists(assetBundlesDir)) { Directory.CreateDirectory(assetBundlesDir); return false; } string[] array = (from x in Directory.GetFiles(assetBundlesDir, "*", SearchOption.AllDirectories) where !x.EndsWith(".manifest", StringComparison.InvariantCultureIgnoreCase) select x).ToArray(); if (array.Length == 0) { return false; } for (int i = 0; i < array.Length; i++) { try { LoadAndRegisterAssetBundle(array[i]); } catch (Exception ex) { APILogger.Warn("AssetAPI", $"Failed to load asset bundle '{array[i]}' ({ex.Message})"); } } return true; } } [API("Event")] public static class EventAPI { public static ApiStatusInfo Status => APIStatus.Event; public static event Action OnManagersSetup; public static event Action OnExpeditionStarted; public static event Action OnAssetsLoaded; internal static void Setup() { Global.OnAllManagersSetup += Action.op_Implicit((Action)ManagersSetup); AssetShardManager.OnStartupAssetsLoaded += Action.op_Implicit((Action)AssetsLoaded); RundownManager.OnExpeditionGameplayStarted += Action.op_Implicit((Action)ExpeditionStarted); } private static void ManagersSetup() { EventAPI.OnManagersSetup?.Invoke(); } private static void ExpeditionStarted() { EventAPI.OnExpeditionStarted?.Invoke(); } private static void AssetsLoaded() { EventAPI.OnAssetsLoaded?.Invoke(); } } [API("GameData")] public class GameDataAPI { public static ApiStatusInfo Status => APIStatus.GameData; public static event Action OnGameDataInitialized; static GameDataAPI() { Status.Created = true; Status.Ready = true; } internal static void InvokeGameDataInit() { GameDataAPI.OnGameDataInitialized?.Invoke(); } } [API("Il2Cpp")] public static class Il2CppAPI { public static ApiStatusInfo Status => APIStatus.Il2Cpp; static Il2CppAPI() { Status.Created = true; Status.Ready = true; } public unsafe static void InjectWithInterface<T>() where T : Il2CppObjectBase { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown List<INativeClassStruct> list = new List<INativeClassStruct>(); foreach (Il2CppInterfaceAttribute item in GetCustomAttributesInType<T, Il2CppInterfaceAttribute>()) { Il2CppClass* ptr = (Il2CppClass*)(void*)(IntPtr)typeof(Il2CppClassPointerStore<>).MakeGenericType(item.Type).GetField("NativeClassPtr").GetValue(null); IL2CPP.il2cpp_runtime_class_init((IntPtr)ptr); list.Add(UnityVersionHandler.Wrap(ptr)); } RegisterTypeOptions val = new RegisterTypeOptions(); val.set_LogSuccess(true); val.set_Interfaces(Il2CppInterfaceCollection.op_Implicit(list.ToArray())); ClassInjector.RegisterTypeInIl2Cpp<T>(val); } public unsafe static void* GetIl2CppMethod<T>(string methodName, string returnTypeName, bool isGeneric, params string[] argTypes) where T : Il2CppObjectBase { void** ptr = (void**)IL2CPP.GetIl2CppMethod(Il2CppClassPointerStore<T>.NativeClassPtr, isGeneric, methodName, returnTypeName, argTypes).ToPointer(); if (ptr == null) { return ptr; } return *ptr; } public unsafe static TDelegate GetIl2CppMethod<T, TDelegate>(string methodName, string returnTypeName, bool isGeneric, params string[] argTypes) where T : Il2CppObjectBase where TDelegate : Delegate { void* il2CppMethod = GetIl2CppMethod<T>(methodName, returnTypeName, isGeneric, argTypes); if (il2CppMethod == null) { return null; } return Marshal.GetDelegateForFunctionPointer<TDelegate>((IntPtr)il2CppMethod); } public unsafe static INativeDetour CreateGenericDetour<TClass, TDelegate>(string methodName, string returnType, string[] paramTypes, Type[] genericArguments, TDelegate to, out TDelegate original) where TClass : Object where TDelegate : Delegate { //IL_0042: Unknown result type (might be due to invalid IL or missing references) IntPtr nativeClassPtr = Il2CppClassPointerStore<TClass>.NativeClassPtr; if (nativeClassPtr == IntPtr.Zero) { throw new ArgumentException(typeof(TClass).Name + " does not exist in il2cpp domain"); } return INativeDetour.CreateAndApply<TDelegate>(UnityVersionHandler.Wrap((Il2CppMethodInfo*)(void*)IL2CPP.il2cpp_method_get_from_reflection(((Il2CppObjectBase)new MethodInfo(IL2CPP.il2cpp_method_get_object(IL2CPP.GetIl2CppMethod(nativeClassPtr, true, methodName, returnType, paramTypes), nativeClassPtr)).MakeGenericMethod(((IEnumerable<Type>)genericArguments).Select((Func<Type, Type>)Il2CppType.From).ToArray())).Pointer)).MethodPointer, to, ref original); } private static IEnumerable<TAttribute> GetCustomAttributesInType<T, TAttribute>() where TAttribute : Attribute { Type attributeType = typeof(TAttribute); return typeof(T).GetCustomAttributes(attributeType, inherit: true).Union(typeof(T).GetInterfaces().SelectMany((Type interfaceType) => interfaceType.GetCustomAttributes(attributeType, inherit: true))).Distinct() .Cast<TAttribute>(); } } public delegate void LevelDataUpdateEvent(ActiveExpedition activeExp, ExpeditionInTierData expData); public delegate void LevelSelectedEvent(eRundownTier expTier, int expIndexInTier, ExpeditionInTierData expData); [API("Level")] public static class LevelAPI { private static eRundownTier s_LatestExpTier = (eRundownTier)99; private static int s_LatestExpIndex = -1; public static ApiStatusInfo Status => APIStatus.Level; public static event LevelDataUpdateEvent OnLevelDataUpdated; public static event LevelSelectedEvent OnLevelSelected; public static event Action OnBuildStart; public static event Action OnBuildDone; public static event Action OnEnterLevel; public static event Action OnLevelCleanup; internal static void Setup() { Status.Created = true; Status.Ready = true; EventAPI.OnExpeditionStarted += EnterLevel; } internal static void ExpeditionUpdated(pActiveExpedition activeExp, ExpeditionInTierData expData) { //IL_0018: 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_0025: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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) LevelAPI.OnLevelDataUpdated?.Invoke(ActiveExpedition.CreateFrom(activeExp), expData); eRundownTier tier = activeExp.tier; int expeditionIndex = activeExp.expeditionIndex; if (tier != s_LatestExpTier || expeditionIndex != s_LatestExpIndex) { LevelAPI.OnLevelSelected?.Invoke(tier, expeditionIndex, expData); s_LatestExpTier = tier; s_LatestExpIndex = expeditionIndex; } } internal static void BuildStart() { LevelAPI.OnBuildStart?.Invoke(); } internal static void BuildDone() { LevelAPI.OnBuildDone?.Invoke(); } internal static void EnterLevel() { LevelAPI.OnEnterLevel?.Invoke(); } internal static void LevelCleanup() { LevelAPI.OnLevelCleanup?.Invoke(); } } public struct ActiveExpedition { public pPlayer player; public eRundownKey rundownType; public string rundownKey; public eRundownTier tier; public int expeditionIndex; public int hostIDSeed; public int sessionSeed; public static ActiveExpedition CreateFrom(pActiveExpedition pActiveExp) { ActiveExpedition result = default(ActiveExpedition); result.CopyFrom(pActiveExp); return result; } public void CopyFrom(pActiveExpedition pActiveExp) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) player = pActiveExp.player; rundownType = pActiveExp.rundownType; rundownKey = pActiveExp.rundownKey.data; tier = pActiveExp.tier; expeditionIndex = pActiveExp.expeditionIndex; hostIDSeed = pActiveExp.hostIDSeed; sessionSeed = pActiveExp.sessionSeed; } } [API("Localization")] public static class LocalizationAPI { private sealed class Entry { private readonly string?[] m_ValuesByLanguage = new string[12]; private TextDBOptions m_Options; public uint? TextBlockId { get; private set; } private bool TryGetStringInAnyLanguage([NotNullWhen(true)] out string? value) { for (int i = 0; i < m_ValuesByLanguage.Length; i++) { value = m_ValuesByLanguage[i]; if (value != null) { return true; } } value = null; return false; } private bool TryGetStringInLanguage(Language language, [NotNullWhen(true)] out string? value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Expected I4, but got Unknown int num = language - 1; value = m_ValuesByLanguage[num]; return value != null; } public bool TryGetString(Language language, FallbackValueOptions options, [NotNullWhen(true)] out string? value) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (TryGetStringInLanguage(language, out value)) { return true; } if (options.UseFallbackLanguage && TryGetStringInLanguage(options.FallbackLanguage.Value, out value)) { return true; } if (options.UseAnyLanguage && TryGetStringInAnyLanguage(out value)) { return true; } value = null; return false; } private string GetStringForTextDB(Language language, string key, FallbackValueOptions options) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (TryGetString(language, options, out string value)) { return value; } ValidateUseKey(key, language, options, "GenerateTextDB"); return key; } [MemberNotNull("TextBlockId")] public void GenerateTextDataBlock(string key, TextDBOptions options, bool force = false) { m_Options = options; GenerateTextDataBlock(key, force); } [MemberNotNull("TextBlockId")] public void GenerateTextDataBlock(string key, bool force = false) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Expected O, but got Unknown //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Expected O, but got Unknown //IL_018e: Expected O, but got Unknown if (!TextBlockId.HasValue || force) { FallbackValueOptions options = m_Options.FallbackOptions ?? FallbackValueOptions.AnyLangOrKey; TextDataBlock val = new TextDataBlock { CharacterMetaData = (m_Options.CharacterMetadataId ?? 1) }; ((GameDataBlockBase<TextDataBlock>)val).internalEnabled = true; val.ExportVersion = 1; val.ImportVersion = 1; val.Description = string.Empty; val.English = GetStringForTextDB((Language)1, key, options); val.French = LanguageData.op_Implicit(GetStringForTextDB((Language)2, key, options)); val.Italian = LanguageData.op_Implicit(GetStringForTextDB((Language)3, key, options)); val.German = LanguageData.op_Implicit(GetStringForTextDB((Language)4, key, options)); val.Spanish = LanguageData.op_Implicit(GetStringForTextDB((Language)5, key, options)); val.Russian = LanguageData.op_Implicit(GetStringForTextDB((Language)6, key, options)); val.Portuguese_Brazil = LanguageData.op_Implicit(GetStringForTextDB((Language)7, key, options)); val.Polish = LanguageData.op_Implicit(GetStringForTextDB((Language)8, key, options)); val.Japanese = LanguageData.op_Implicit(GetStringForTextDB((Language)9, key, options)); val.Korean = LanguageData.op_Implicit(GetStringForTextDB((Language)10, key, options)); val.Chinese_Traditional = LanguageData.op_Implicit(GetStringForTextDB((Language)11, key, options)); val.Chinese_Simplified = LanguageData.op_Implicit(GetStringForTextDB((Language)12, key, options)); ((GameDataBlockBase<TextDataBlock>)val).name = key; val.MachineTranslation = false; val.SkipLocalization = false; ((GameDataBlockBase<TextDataBlock>)val).persistentID = 0u; TextDataBlock val2 = val; GameDataBlockBase<TextDataBlock>.AddBlock(val2, -1); TextBlockId = ((GameDataBlockBase<TextDataBlock>)(object)val2).persistentID; } } public bool TryGetString(Language language, string key, FallbackValueOptions options, out string? value) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) if (TryGetString(language, options, out value)) { return true; } if (options.UseKey) { value = key; return true; } value = null; return false; } public string GetString(Language language, string key, FallbackValueOptions options) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (TryGetString(language, options, out string value)) { return value; } ValidateUseKey(key, language, options, "GetString"); return key; } public string FormatString(Language language, string key, FallbackValueOptions options, object?[] args) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (TryGetString(language, options, out string value)) { return string.Format(value, args); } ValidateUseKey(key, language, options, "FormatString"); return key; } public bool HasValueInLanguage(Language language) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) ValidateLanguage(language, "language"); return m_ValuesByLanguage[language - 1] != null; } public void AddValue(Language language, string value, bool force = false) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected I4, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) ArgumentNullException.ThrowIfNull(value, "value"); int num = language - 1; if (num < 0 || num >= m_ValuesByLanguage.Length) { throw new ArgumentOutOfRangeException("language"); } ref string reference = ref m_ValuesByLanguage[num]; if (reference != null && !force) { return; } reference = value; if (TextBlockId.HasValue) { TextDataBlock block = GameDataBlockBase<TextDataBlock>.GetBlock(TextBlockId.Value); if (block != null) { UpdateTextDataBlock(block, language, reference); } } } } [Flags] public enum FallbackValueFlags { None = 0, FallbackLanguage = 1, AnyLanguage = 2, Key = 4, FallbackOrAnyLanguage = 3, FallbackLanguageOrKey = 5, AnyLanguageOrKey = 6, FallbackOrAnyLanguageOrKey = 7 } public readonly struct FallbackValueOptions : IEquatable<FallbackValueOptions> { public static readonly FallbackValueOptions None = default(FallbackValueOptions); public static readonly FallbackValueOptions Key = new FallbackValueOptions(FallbackValueFlags.Key); public static readonly FallbackValueOptions AnyLang = new FallbackValueOptions(FallbackValueFlags.AnyLanguage); public static readonly FallbackValueOptions AnyLangOrKey = new FallbackValueOptions(FallbackValueFlags.AnyLanguageOrKey); public FallbackValueFlags Flags { get; } public Language? FallbackLanguage { get; } public bool UseKey => Flags.HasFlag(FallbackValueFlags.Key); [MemberNotNullWhen(true, "FallbackLanguage")] public bool UseFallbackLanguage { [MemberNotNullWhen(true, "FallbackLanguage")] get { return Flags.HasFlag(FallbackValueFlags.FallbackLanguage); } } public bool UseAnyLanguage => Flags.HasFlag(FallbackValueFlags.AnyLanguage); public FallbackValueOptions(FallbackValueFlags flags, Language? fallbackLanguage = null) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (flags.HasFlag(FallbackValueFlags.FallbackLanguage)) { if (!fallbackLanguage.HasValue) { throw new ArgumentNullException("fallbackLanguage", "A fallback language is required if specifying the flag FallbackLanguage"); } ValidateLanguage(fallbackLanguage.Value, "fallbackLanguage"); } Flags = flags; FallbackLanguage = fallbackLanguage; } public override int GetHashCode() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) return HashCode.Combine<FallbackValueFlags, Language>(Flags, FallbackLanguage.GetValueOrDefault()); } public override bool Equals([NotNullWhen(true)] object? obj) { if (obj is FallbackValueOptions other) { return Equals(other); } return false; } public bool Equals(FallbackValueOptions other) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (Flags == other.Flags) { return FallbackLanguage == other.FallbackLanguage; } return false; } public FallbackValueOptions IncludeKey() { return new FallbackValueOptions(Flags | FallbackValueFlags.Key, FallbackLanguage); } public FallbackValueOptions ExcludeKey() { return new FallbackValueOptions(Flags & ~FallbackValueFlags.Key, FallbackLanguage); } public FallbackValueOptions IncludeFallbackLanguage(Language language) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) ValidateLanguage(language, "language"); return new FallbackValueOptions(Flags | FallbackValueFlags.FallbackLanguage, language); } public FallbackValueOptions ExcludeFallbackLanguage() { return new FallbackValueOptions(Flags & ~FallbackValueFlags.FallbackLanguage); } public FallbackValueOptions IncludeAnyLanguage() { return new FallbackValueOptions(Flags | FallbackValueFlags.AnyLanguage, FallbackLanguage); } public FallbackValueOptions ExcludeAnyLanguage() { return new FallbackValueOptions(Flags & ~FallbackValueFlags.AnyLanguage, FallbackLanguage); } public FallbackValueOptions Combine(FallbackValueOptions other) { return new FallbackValueOptions(Flags | other.Flags, FallbackLanguage ?? other.FallbackLanguage); } public static bool operator ==(FallbackValueOptions left, FallbackValueOptions right) { return left.Equals(right); } public static bool operator !=(FallbackValueOptions left, FallbackValueOptions right) { return !(left == right); } public static FallbackValueOptions FallbackLang(Language fallbackLanguage) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return new FallbackValueOptions(FallbackValueFlags.FallbackLanguage, fallbackLanguage); } public static FallbackValueOptions FallbackOrAnyLang(Language fallbackLanguage) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return new FallbackValueOptions(FallbackValueFlags.FallbackOrAnyLanguage, fallbackLanguage); } public static FallbackValueOptions FallbackLangOrKey(Language fallbackLanguage) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return new FallbackValueOptions(FallbackValueFlags.FallbackLanguageOrKey, fallbackLanguage); } public static FallbackValueOptions FallbackOrAnyLangOrKey(Language fallbackLanguage) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return new FallbackValueOptions(FallbackValueFlags.FallbackOrAnyLanguageOrKey, fallbackLanguage); } } public struct TextDBOptions { private FallbackValueOptions? m_FallbackOptions; private uint? m_CharacterMetadataId; public uint? CharacterMetadataId { readonly get { return m_CharacterMetadataId; } set { m_CharacterMetadataId = value; } } public FallbackValueOptions? FallbackOptions { readonly get { return m_FallbackOptions; } set { m_FallbackOptions = value; } } } private static readonly Dictionary<string, Entry> s_Entries = new Dictionary<string, Entry>(); private static readonly List<string> s_EntriesToGenerateTextDBs = new List<string>(); private static bool s_GameDataInitialized = false; private static readonly string STR_NoValueFoundExceptionMsg = "No localization value exists for key '{1}' in language '{0}'."; private static readonly string STR_UseKeyGeneric = "{2}: No localization value exists for key '{1}' in language '{0}', defaulting to key."; public static ApiStatusInfo Status => APIStatus.Localization; public static Language CurrentLanguage => Text.TextLocalizationService.CurrentLanguage; public static event Action? OnLanguageChange; internal static void Setup() { GameDataAPI.OnGameDataInitialized += OnGameDataInitialized; EventAPI.OnAssetsLoaded += OnGameAssetsLoaded; Status.Created = true; } internal static void OnGameDataInitialized() { s_GameDataInitialized = true; foreach (string s_EntriesToGenerateTextDB in s_EntriesToGenerateTextDBs) { if (s_Entries.TryGetValue(s_EntriesToGenerateTextDB, out Entry value)) { value.GenerateTextDataBlock(s_EntriesToGenerateTextDB, force: true); } } } internal static void OnGameAssetsLoaded() { Status.Ready = true; } internal static void LanguageChanged() { LocalizationAPI.OnLanguageChange?.Invoke(); } public static string FormatString(string key, params object?[] args) { return FormatString(key, FallbackValueOptions.None, args); } public static string FormatString(string key, Language fallbackLanguage, params object?[] args) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return FormatString(key, FallbackValueOptions.FallbackLang(fallbackLanguage), args); } public static string FormatString(string key, FallbackValueOptions options, params object?[] args) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) ValidateLocalizationKey(key, "key"); Language currentLanguage = CurrentLanguage; if (!s_Entries.TryGetValue(key, out Entry value)) { ValidateUseKey(key, currentLanguage, options, "FormatString"); return key; } return value.FormatString(currentLanguage, key, options, args); } public static string GetString(string key) { return GetString(key, FallbackValueOptions.None); } public static string GetString(string key, Language fallbackLanguage) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return GetString(key, FallbackValueOptions.FallbackLang(fallbackLanguage)); } public static string GetString(string key, FallbackValueOptions options) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) ValidateLocalizationKey(key, "key"); Language currentLanguage = CurrentLanguage; if (!s_Entries.TryGetValue(key, out Entry value)) { ValidateUseKey(key, currentLanguage, options, "GetString"); return key; } return value.GetString(currentLanguage, key, options); } public static bool TryGetString(string key, [NotNullWhen(true)] out string? value) { return TryGetString(key, FallbackValueOptions.None, out value); } public static bool TryGetString(string key, Language fallbackLanguage, [NotNullWhen(true)] out string? value) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return TryGetString(key, FallbackValueOptions.FallbackLang(fallbackLanguage), out value); } public static bool TryGetString(string key, FallbackValueOptions options, [NotNullWhen(true)] out string? value) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) ValidateLocalizationKey(key, "key"); if (!s_Entries.TryGetValue(key, out Entry value2)) { if (options.UseKey) { value = key; return false; } value = null; return false; } return value2.TryGetString(CurrentLanguage, key, options, out value); } public static bool HasKey([NotNullWhen(true)] string? key) { if (!string.IsNullOrWhiteSpace(key)) { return s_Entries.ContainsKey(key); } return false; } public static bool HasLocalizedValue([NotNullWhen(true)] string? key, Language language) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrWhiteSpace(key) && s_Entries.TryGetValue(key, out Entry value)) { return value.HasValueInLanguage(language); } return false; } public static uint GenerateTextBlock(string key, TextDBOptions? textDataBlockOptions = null) { ValidateLocalizationKey(key, "key"); Entry entry = s_Entries[key]; if (entry.TextBlockId.HasValue) { return entry.TextBlockId.Value; } if (textDataBlockOptions.HasValue) { entry.GenerateTextDataBlock(key, textDataBlockOptions.Value); } else { entry.GenerateTextDataBlock(key); } s_EntriesToGenerateTextDBs.Add(key); return entry.TextBlockId.Value; } public static bool TryGetTextBlockId(string key, out uint blockId) { ValidateLocalizationKey(key, "key"); if (!s_Entries.TryGetValue(key, out Entry value) || !value.TextBlockId.HasValue) { blockId = 0u; return false; } blockId = value.TextBlockId.Value; return true; } public static void AddEntry(string key, Language language, string value, TextDBOptions? textDataBlockOptions = null) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) ValidateLocalizationKey(key, "key"); ValidateLanguage(language, "language"); if (value == null) { value = string.Empty; } bool exists; ref Entry valueRefOrAddDefault = ref CollectionsMarshal.GetValueRefOrAddDefault(s_Entries, key, out exists); if (valueRefOrAddDefault == null) { valueRefOrAddDefault = new Entry(); } valueRefOrAddDefault.AddValue(language, value); if (textDataBlockOptions.HasValue && !exists) { s_EntriesToGenerateTextDBs.Add(key); if (s_GameDataInitialized) { valueRefOrAddDefault.GenerateTextDataBlock(key, textDataBlockOptions.Value); } } } public static void LoadFromResources(string baseName, TextDBOptions? textDataBlockOptions = null) { LoadFromResources(baseName, Assembly.GetCallingAssembly(), textDataBlockOptions); } public static void LoadFromResources(string baseName, Assembly assembly, TextDBOptions? textDataBlockOptions = null) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) ResourceManager resourceManager = new ResourceManager(baseName, assembly); List<Exception> list = new List<Exception>(); CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.AllCultures); foreach (CultureInfo cultureInfo in cultures) { bool isNeutralCulture = cultureInfo.IsNeutralCulture; Language language = GetLanguage(cultureInfo); if ((int)language == 0) { continue; } ResourceSet resourceSet; try { resourceSet = resourceManager.GetResourceSet(cultureInfo, createIfNotExists: true, tryParents: true); } catch (MissingManifestResourceException) { continue; } catch (Exception item) { list.Add(item); continue; } if (resourceSet == null) { continue; } foreach (DictionaryEntry item2 in resourceSet) { if (!(item2.Key is string text) || !(item2.Value is string value)) { continue; } bool exists; ref Entry valueRefOrAddDefault = ref CollectionsMarshal.GetValueRefOrAddDefault(s_Entries, text, out exists); if (valueRefOrAddDefault == null) { valueRefOrAddDefault = new Entry(); } valueRefOrAddDefault.AddValue(language, value, isNeutralCulture); if (textDataBlockOptions.HasValue && !exists) { s_EntriesToGenerateTextDBs.Add(text); if (s_GameDataInitialized) { valueRefOrAddDefault.GenerateTextDataBlock(text, textDataBlockOptions.Value); } } } } resourceManager.ReleaseAllResources(); if (list.Count > 0) { throw new AggregateException(list); } } private static void ValidateLocalizationKey([NotNull] string key, [CallerArgumentExpression("key")] string? paramName = null) { ArgumentNullException.ThrowIfNull(key, paramName); if (string.IsNullOrWhiteSpace(paramName)) { throw new ArgumentException("Localization key cannot be empty/whitespace", paramName ?? "key"); } } private static void ValidateLanguage(Language language, [CallerArgumentExpression("language")] string? paramName = null) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (!Enum.IsDefined<Language>(language)) { throw new ArgumentException($"'{language}' is not a valid language", paramName ?? "language"); } } private static void ValidateUseKey(string key, Language language, FallbackValueOptions options, string useCategory) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (!options.UseKey) { throw new KeyNotFoundException(string.Format(STR_NoValueFoundExceptionMsg, language, key)); } APILogger.Warn("LocalizationAPI", string.Format(STR_UseKeyGeneric, language, key, useCategory)); } private static Language GetLanguage(CultureInfo info) { //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) while (!info.IsNeutralCulture) { info = info.Parent; if (string.IsNullOrEmpty(info.Name)) { return (Language)0; } } return (Language)(info.Name switch { "en" => 1, "fr" => 2, "it" => 3, "de" => 4, "es" => 5, "ru" => 6, "pt" => 7, "pl" => 8, "ja" => 9, "ko" => 10, "zh-Hans" => 12, "zh-Hant" => 11, _ => 0, }); } private static void UpdateTextDataBlock(TextDataBlock block, Language language, string text) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected I4, but got Unknown switch (language - 1) { case 0: block.English = text; break; case 1: block.French = LanguageData.op_Implicit(text); break; case 2: block.Italian = LanguageData.op_Implicit(text); break; case 3: block.German = LanguageData.op_Implicit(text); break; case 4: block.Spanish = LanguageData.op_Implicit(text); break; case 5: block.Russian = LanguageData.op_Implicit(text); break; case 6: block.Portuguese_Brazil = LanguageData.op_Implicit(text); break; case 7: block.Polish = LanguageData.op_Implicit(text); break; case 8: block.Japanese = LanguageData.op_Implicit(text); break; case 9: block.Korean = LanguageData.op_Implicit(text); break; case 10: block.Chinese_Traditional = LanguageData.op_Implicit(text); break; case 11: block.Chinese_Simplified = LanguageData.op_Implicit(text); break; } } } [API("Network")] public static class NetworkAPI { internal class CachedEvent { public string EventName { get; set; } public Type PayloadType { get; set; } public object OnReceive { get; set; } public bool IsFreeSize { get; set; } } internal static ConcurrentDictionary<string, CachedEvent> s_EventCache = new ConcurrentDictionary<string, CachedEvent>(); public static ApiStatusInfo Status => APIStatus.Network; public static bool IsEventRegistered(string eventName) { return NetworkAPI_Impl.Instance.EventExists(eventName); } public static void RegisterEvent<T>(string eventName, Action<ulong, T> onReceive) where T : struct { if (!APIStatus.Network.Ready) { if (s_EventCache.ContainsKey(eventName)) { throw new ArgumentException("An event with the name " + eventName + " has already been registered.", "eventName"); } s_EventCache.TryAdd(eventName, new CachedEvent { EventName = eventName, PayloadType = typeof(T), OnReceive = onReceive, IsFreeSize = false }); } else { NetworkAPI_Impl.Instance.RegisterEvent(eventName, onReceive); } } public static void InvokeEvent<T>(string eventName, T payload, SNet_ChannelType channelType = 2) where T : struct { //IL_0019: 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) SNet_SendGroup val = default(SNet_SendGroup); SNet_SendQuality val2 = default(SNet_SendQuality); int num = default(int); SNet.GetSendSettings(ref channelType, ref val, ref val2, ref num); SNet.Core.SendBytes(MakeBytes(eventName, payload), val, val2, num); } public static void InvokeEvent<T>(string eventName, T payload, SNet_Player target, SNet_ChannelType channelType = 2) where T : struct { //IL_0019: Unknown result type (might be due to invalid IL or missing references) SNet_SendGroup val = default(SNet_SendGroup); SNet_SendQuality val2 = default(SNet_SendQuality); int num = default(int); SNet.GetSendSettings(ref channelType, ref val, ref val2, ref num); SNet.Core.SendBytes(MakeBytes(eventName, payload), val2, num, target); } public static void InvokeEvent<T>(string eventName, T payload, List<SNet_Player> targets, SNet_ChannelType channelType = 2) where T : struct { //IL_0019: Unknown result type (might be due to invalid IL or missing references) SNet_SendGroup val = default(SNet_SendGroup); SNet_SendQuality val2 = default(SNet_SendQuality); int num = default(int); SNet.GetSendSettings(ref channelType, ref val, ref val2, ref num); SNet.Core.SendBytes(MakeBytes(eventName, payload), val2, num, targets.ToIl2Cpp()); } public static void RegisterFreeSizedEvent(string eventName, Action<ulong, byte[]> onReceiveBytes) { if (!APIStatus.Network.Ready) { if (s_EventCache.ContainsKey(eventName)) { throw new ArgumentException("An event with the name " + eventName + " has already been registered.", "eventName"); } s_EventCache.TryAdd(eventName, new CachedEvent { EventName = eventName, PayloadType = null, OnReceive = onReceiveBytes, IsFreeSize = true }); } else { NetworkAPI_Impl.Instance.RegisterFreeSizedEvent(eventName, onReceiveBytes); } } public static void InvokeFreeSizedEvent(string eventName, byte[] payload, SNet_ChannelType channelType = 2) { //IL_0019: 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) SNet_SendGroup val = default(SNet_SendGroup); SNet_SendQuality val2 = default(SNet_SendQuality); int num = default(int); SNet.GetSendSettings(ref channelType, ref val, ref val2, ref num); SNet.Core.SendBytes(MakeBytes(eventName, payload), val, val2, num); } public static void InvokeFreeSizedEvent(string eventName, byte[] payload, SNet_Player target, SNet_ChannelType channelType = 2) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) SNet_SendGroup val = default(SNet_SendGroup); SNet_SendQuality val2 = default(SNet_SendQuality); int num = default(int); SNet.GetSendSettings(ref channelType, ref val, ref val2, ref num); SNet.Core.SendBytes(MakeBytes(eventName, payload), val2, num, target); } public static void InvokeFreeSizedEvent(string eventName, byte[] payload, IEnumerable<SNet_Player> targets, SNet_ChannelType channelType = 2) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) SNet_SendGroup val = default(SNet_SendGroup); SNet_SendQuality val2 = default(SNet_SendQuality); int num = default(int); SNet.GetSendSettings(ref channelType, ref val, ref val2, ref num); SNet.Core.SendBytes(MakeBytes(eventName, payload), val2, num, targets.ToList().ToIl2Cpp()); } private static Il2CppStructArray<byte> MakeBytes<T>(string eventName, T payload) where T : struct { return Il2CppStructArray<byte>.op_Implicit(NetworkAPI_Impl.Instance.MakePacketBytes(eventName, payload)); } private static Il2CppStructArray<byte> MakeBytes(string eventName, byte[] payload) { return Il2CppStructArray<byte>.op_Implicit(NetworkAPI_Impl.Instance.MakeFreeSizedPacketBytes(eventName, payload)); } } [API("Prefab")] public static class PrefabAPI { private static Shader s_CustomGearShader; private static readonly Dictionary<uint, Action<SyringeFirstPerson>> s_SyringeActions = new Dictionary<uint, Action<SyringeFirstPerson>>(); public static ApiStatusInfo Status => APIStatus.Prefab; private static Shader CustomGearShader { get { if ((Object)(object)s_CustomGearShader == (Object)null) { s_CustomGearShader = Shader.Find("Cell/Player/CustomGearShader"); } return s_CustomGearShader; } } public static void CreateConsumable(string assetName, bool enableEmissive = false) { Object loadedAsset = AssetAPI.GetLoadedAsset(assetName); GameObject val = ((loadedAsset != null) ? ((Il2CppObjectBase)loadedAsset).TryCast<GameObject>() : null) ?? null; if ((Object)(object)val == (Object)null) { throw new ArgumentException("Couldn't find a game object asset with the name " + assetName, "assetName"); } ItemEquippable obj = val.AddComponent<ItemEquippable>(); obj.m_isFirstPerson = false; ((Item)obj).m_itemModelHolder = val.transform; ReplaceShaderInAssetMaterials(val, CustomGearShader, enableEmissive ? "ENABLE_EMISSIVE" : null); } public static void CreateConsumablePickup(string assetName, bool enableEmissive = false) { Object loadedAsset = AssetAPI.GetLoadedAsset(assetName); GameObject val = ((loadedAsset != null) ? ((Il2CppObjectBase)loadedAsset).TryCast<GameObject>() : null) ?? null; if ((Object)(object)val == (Object)null) { throw new ArgumentException("Couldn't find a game object asset with the name " + assetName, "assetName"); } BoxCollider componentInChildren = val.GetComponentInChildren<BoxCollider>(); if ((Object)(object)componentInChildren == (Object)null) { throw new Exception("The Consumable Pickup prefab doesn't contain a BoxCollider for interaction"); } GameObject gameObject = ((Component)componentInChildren).gameObject; gameObject.layer = LayerMask.NameToLayer("Interaction"); Interact_Pickup_PickupItem val2 = gameObject.AddComponent<Interact_Pickup_PickupItem>(); ((Interact_Base)val2).m_colliderToOwn = (Collider)(object)componentInChildren; ConsumablePickup_Core obj = val.AddComponent<ConsumablePickup_Core>(); obj.m_syncComp = (Component)(object)val.AddComponent<LG_PickupItem_Sync>(); obj.m_interactComp = (Component)(object)val2; ReplaceShaderInAssetMaterials(val, CustomGearShader, enableEmissive ? "ENABLE_EMISSIVE" : null); } public static void CreateConsumableInstance<T>(string assetName) where T : ConsumableInstance { Object loadedAsset = AssetAPI.GetLoadedAsset(assetName); GameObject obj = ((loadedAsset != null) ? ((Il2CppObjectBase)loadedAsset).TryCast<GameObject>() : null) ?? null; if ((Object)(object)obj == (Object)null) { throw new ArgumentException("Couldn't find a game object asset with the name " + assetName, "assetName"); } if (!ClassInjector.IsTypeRegisteredInIl2Cpp<T>()) { ClassInjector.RegisterTypeInIl2Cpp<T>(); } obj.layer = LayerMask.NameToLayer("Debris"); Rigidbody component = obj.GetComponent<Rigidbody>(); obj.AddComponent<ColliderMaterial>().PhysicsBody = component ?? throw new Exception("The Consumable Instance prefab doesn't contain a Rigidbody"); obj.AddComponent<T>(); } public static void CreateGearComponent(string assetName, bool enableEmissive = false) { Object loadedAsset = AssetAPI.GetLoadedAsset(assetName); GameObject obj = ((loadedAsset != null) ? ((Il2CppObjectBase)loadedAsset).TryCast<GameObject>() : null) ?? null; if ((Object)(object)obj == (Object)null) { throw new ArgumentException("Couldnt find a game object asset with the name " + assetName, "assetName"); } obj.layer = LayerMask.NameToLayer("FirstPersonItem"); ReplaceShaderInAssetMaterials(obj, CustomGearShader, "ENABLE_FPS_RENDERING", enableEmissive ? "ENABLE_EMISSIVE" : null); } public static void CreateSyringe(uint itemPersistentId, Action<SyringeFirstPerson> onUse) { if (s_SyringeActions.ContainsKey(itemPersistentId)) { throw new ArgumentException($"{itemPersistentId} is already registered with a syringe action."); } s_SyringeActions.Add(itemPersistentId, onUse); } internal static bool OnSyringeUsed(SyringeFirstPerson syringe) { if (s_SyringeActions.TryGetValue(((GameDataBlockBase<ItemDataBlock>)(object)((Item)syringe).ItemDataBlock).persistentID, out var value)) { value(syringe); return true; } return false; } private static void ReplaceShaderInAssetMaterials(GameObject asset, Shader newShader, params string[] addedKeywords) { addedKeywords = addedKeywords.Where((string x) => !string.IsNullOrEmpty(x)).ToArray(); foreach (MeshRenderer componentsInChild in asset.GetComponentsInChildren<MeshRenderer>(true)) { foreach (Material item in (Il2CppArrayBase<Material>)(object)((Renderer)componentsInChild).materials) { item.shader = newShader; if (addedKeywords.Length != 0) { string[] array = Il2CppArrayBase<string>.op_Implicit((Il2CppArrayBase<string>)(object)item.shaderKeywords); int num = array.Length; Array.Resize(ref array, array.Length + addedKeywords.Length); for (int i = 0; i < addedKeywords.Length; i++) { array[num + i] = addedKeywords[i]; } item.shaderKeywords = Il2CppStringArray.op_Implicit(array); } } } } } [API("SoundBank")] public static class SoundBankAPI { public static ApiStatusInfo Status => APIStatus.SoundBank; public static event Action OnSoundBanksLoaded; internal static void Setup() { EventAPI.OnManagersSetup += OnLoadSoundBanks; } private static void OnLoadSoundBanks() { FileInfo[] array = (from file in Directory.CreateDirectory(Path.Combine(Paths.BepInExRootPath, "Assets", "SoundBank")).EnumerateFiles() where file.Extension.Contains(".bnk") select file).ToArray(); CollectionExtensions.Do<FileInfo>((IEnumerable<FileInfo>)array, (Action<FileInfo>)LoadBank); if (array.Any()) { SoundBankAPI.OnSoundBanksLoaded?.Invoke(); } } private unsafe static void LoadBank(FileInfo file) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Invalid comparison between Unknown and I4 //IL_00e2: Unknown result type (might be due to invalid IL or missing references) using FileStream fileStream = file.OpenRead(); uint num = (uint)fileStream.Length; byte[] array = new byte[num]; if (fileStream.Read(array, 0, (int)num) != 0) { void* intPtr = NativeMemory.AlignedAlloc(num, 16u); Unsafe.CopyBlock(ref Unsafe.AsRef<byte>(intPtr), ref array[0], num); uint value = default(uint); AKRESULT val = AkSoundEngine.LoadBank((IntPtr)(nint)intPtr, num, ref value); if ((int)val == 1) { APILogger.Info("SoundBankAPI", $"Loaded sound bank '{file.Name}' (bankId: {value:X2})"); } else { APILogger.Error("SoundBankAPI", $"Error while loading sound bank '{file.Name}' ({val})"); } } } } [BepInPlugin("dev.gtfomodding.gtfo-api", "GTFO-API", "0.4.1")] internal class EntryPoint : BasePlugin { private Harmony m_Harmony; public override void Load() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown APILogger.Verbose("Core", "Registering API Implementations"); ClassInjector.RegisterTypeInIl2Cpp<NetworkAPI_Impl>(); ClassInjector.RegisterTypeInIl2Cpp<AssetAPI_Impl>(); APILogger.Verbose("Core", "Registering Wrappers"); ClassInjector.RegisterTypeInIl2Cpp<ItemWrapped>(); APILogger.Verbose("Core", "Registering Utilities Implementations"); ClassInjector.RegisterTypeInIl2Cpp<ThreadDispatcher_Impl>(); ClassInjector.RegisterTypeInIl2Cpp<CoroutineDispatcher_Impl>(); APILogger.Verbose("Core", "Applying Patches"); m_Harmony = new Harmony("dev.gtfomodding.gtfo-api"); m_Harmony.PatchAll(); EventAPI.Setup(); AssetAPI.Setup(); SoundBankAPI.Setup(); LevelAPI.Setup(); LocalizationAPI.Setup(); APILogger.Verbose("Core", "Plugin Load Complete"); APILogger.Warn("GTFO-API", "Syringes are currently disabled in this version"); } } [GeneratedCode("VersionInfoGenerator", "2.0.0+git50a4b1a-master")] [CompilerGenerated] internal static class VersionInfo { public const string RootNamespace = "GTFO.API"; public const string Version = "0.4.1"; public const string VersionPrerelease = null; public const string VersionMetadata = "git1e8fe81-main"; public const string SemVer = "0.4.1+git1e8fe81-main"; public const string GitRevShort = "1e8fe81"; public const string GitRevLong = "1e8fe816dac645ea837fe046d35f0b1ec044f6db"; public const string GitBranch = "main"; public const string GitTag = "0.4.0"; public const bool GitIsDirty = false; } } namespace GTFO.API.Wrappers { public class ItemWrapped : Item { private static readonly Item__Get_pItemData Get_pItemDataBase = Il2CppAPI.GetIl2CppMethod<Item, Item__Get_pItemData>("Get_pItemData", "Player.pItemData", isGeneric: false, Array.Empty<string>()); private static readonly Item__Set_pItemData Set_pItemDataBase = Il2CppAPI.GetIl2CppMethod<Item, Item__Set_pItemData>("Set_pItemData", "System.Void", isGeneric: false, new string[1] { "Player.pItemData" }); private static readonly Item__GetCustomData GetCustomDataBase = Il2CppAPI.GetIl2CppMethod<Item, Item__GetCustomData>("GetCustomData", "Player.pItemData_Custom", isGeneric: false, Array.Empty<string>()); private static readonly Item__SetCustomData SetCustomDataBase = Il2CppAPI.GetIl2CppMethod<Item, Item__SetCustomData>("SetCustomData", "System.Void", isGeneric: false, new string[2] { "Player.pItemData_Custom", "System.Boolean" }); private static readonly Item__OnCustomDataUpdated OnCustomDataUpdatedBase = Il2CppAPI.GetIl2CppMethod<Item, Item__OnCustomDataUpdated>("OnCustomDataUpdated", "System.Void", isGeneric: false, new string[1] { "Player.pItemData_Custom" }); private static readonly Item__Awake AwakeBase = Il2CppAPI.GetIl2CppMethod<Item, Item__Awake>("Awake", "System.Void", isGeneric: false, Array.Empty<string>()); private static readonly Item__OnDespawn OnDespawnBase = Il2CppAPI.GetIl2CppMethod<Item, Item__OnDespawn>("OnDespawn", "System.Void", isGeneric: false, Array.Empty<string>()); private static readonly Item__Setup SetupBase = Il2CppAPI.GetIl2CppMethod<Item, Item__Setup>("Setup", "System.Void", isGeneric: false, new string[1] { "GameData.ItemDataBlock" }); private static readonly Item__OnGearSpawnComplete OnGearSpawnCompleteBase = Il2CppAPI.GetIl2CppMethod<Item, Item__OnGearSpawnComplete>("OnGearSpawnComplete", "System.Void", isGeneric: false, Array.Empty<string>()); private static readonly Item__OnPickUp OnPickUpBase = Il2CppAPI.GetIl2CppMethod<Item, Item__OnPickUp>("OnPickUp", "System.Void", isGeneric: false, new string[1] { "Player.PlayerAgent" }); private static readonly Item__SetupBaseModel SetupBaseModelBase = Il2CppAPI.GetIl2CppMethod<Item, Item__SetupBaseModel>("SetupBaseModel", "System.Void", isGeneric: false, new string[1] { "ItemSetup.ItemModelSetup" }); private static readonly Item__SyncedTurnOn SyncedTurnOnBase = Il2CppAPI.GetIl2CppMethod<Item, Item__SyncedTurnOn>("SyncedTurnOn", "System.Void", isGeneric: false, new string[2] { "Player.PlayerAgent", "AIGraph.AIG_CourseNode" }); private static readonly Item__SyncedTurnOff SyncedTurnOffBase = Il2CppAPI.GetIl2CppMethod<Item, Item__SyncedTurnOff>("SyncedTurnOff", "System.Void", isGeneric: false, new string[1] { "Player.PlayerAgent" }); private static readonly Item__SyncedTrigger SyncedTriggerBase = Il2CppAPI.GetIl2CppMethod<Item, Item__SyncedTrigger>("SyncedTrigger", "System.Void", isGeneric: false, new string[1] { "Player.PlayerAgent" }); private static readonly Item__SyncedTriggerSecondary SyncedTriggerSecondaryBase = Il2CppAPI.GetIl2CppMethod<Item, Item__SyncedTriggerSecondary>("SyncedTriggerSecondary", "System.Void", isGeneric: false, new string[1] { "Player.PlayerAgent" }); private static readonly Item__SyncedThrow SyncedThrowBase = Il2CppAPI.GetIl2CppMethod<Item, Item__SyncedThrow>("SyncedThrow", "System.Void", isGeneric: false, new string[1] { "Player.PlayerAgent" }); private static readonly Item__SyncedPickup SyncedPickupBase = Il2CppAPI.GetIl2CppMethod<Item, Item__SyncedPickup>("SyncedPickup", "System.Void", isGeneric: false, new string[1] { "Player.PlayerAgent" }); private static readonly Item__SyncedSetKeyValue SyncedSetKeyValueBase = Il2CppAPI.GetIl2CppMethod<Item, Item__SyncedSetKeyValue>("SyncedSetKeyValue", "System.Void", isGeneric: false, new string[2] { "System.Int32", "System.Single" }); private static readonly Item__GetPickupInteraction GetPickupInteractionBase = Il2CppAPI.GetIl2CppMethod<Item, Item__GetPickupInteraction>("GetPickupInteraction", "Interact_Base", isGeneric: false, Array.Empty<string>()); private static readonly Item__GetItem GetItemBase = Il2CppAPI.GetIl2CppMethod<Item, Item__GetItem>("GetItem", "Item", isGeneric: false, Array.Empty<string>()); public ItemWrapped(IntPtr hdl) : base(hdl) { } public unsafe override pItemData Get_pItemData() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) pItemData* retstr = (pItemData*)stackalloc pItemData[1]; return *Get_pItemDataBase(retstr, ((Il2CppObjectBase)this).Pointer.ToPointer()); } public unsafe override void Set_pItemData(pItemData data) { Set_pItemDataBase(((Il2CppObjectBase)this).Pointer.ToPointer(), &data); } public unsafe override pItemData_Custom GetCustomData() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) return *GetCustomDataBase(((Il2CppObjectBase)this).Pointer.ToPointer()); } public unsafe override void SetCustomData(pItemData_Custom custom, bool sync) { SetCustomDataBase(((Il2CppObjectBase)this).Pointer.ToPointer(), &custom, sync); } public unsafe override void OnCustomDataUpdated(pItemData_Custom customDataCopy) { OnCustomDataUpdatedBase(((Il2CppObjectBase)this).Pointer.ToPointer(), &customDataCopy); } public unsafe override void Awake() { AwakeBase(((Il2CppObjectBase)this).Pointer.ToPointer()); } public unsafe override void OnDespawn() { OnDespawnBase(((Il2CppObjectBase)this).Pointer.ToPointer()); } public unsafe override void Setup(ItemDataBlock data) { SetupBase(((Il2CppObjectBase)this).Pointer.ToPointer(), ((Il2CppObjectBase)data).Pointer.ToPointer()); } public unsafe override void OnGearSpawnComplete() { OnGearSpawnCompleteBase(((Il2CppObjectBase)this).Pointer.ToPointer()); } public unsafe override void OnPickUp(PlayerAgent player) { OnPickUpBase(((Il2CppObjectBase)this).Pointer.ToPointer(), ((Il2CppObjectBase)player).Pointer.ToPointer()); } public unsafe override void SetupBaseModel(ItemModelSetup setup) { SetupBaseModelBase(((Il2CppObjectBase)this).Pointer.ToPointer(), ((Il2CppObjectBase)setup).Pointer.ToPointer()); } public unsafe override void SyncedTurnOn(PlayerAgent agent, AIG_CourseNode courseNode) { SyncedTurnOnBase(((Il2CppObjectBase)this).Pointer.ToPointer(), ((Il2CppObjectBase)agent).Pointer.ToPointer(), ((Il2CppObjectBase)courseNode).Pointer.ToPointer()); } public unsafe override void SyncedTurnOff(PlayerAgent agent) { SyncedTurnOffBase(((Il2CppObjectBase)this).Pointer.ToPointer(), ((Il2CppObjectBase)agent).Pointer.ToPointer()); } public unsafe override void SyncedTrigger(PlayerAgent agent) { SyncedTriggerBase(((Il2CppObjectBase)this).Pointer.ToPointer(), ((Il2CppObjectBase)agent).Pointer.ToPointer()); } public unsafe override void SyncedTriggerSecondary(PlayerAgent agent) { SyncedTriggerSecondaryBase(((Il2CppObjectBase)this).Pointer.ToPointer(), ((Il2CppObjectBase)agent).Pointer.ToPointer()); } public unsafe override void SyncedThrow(PlayerAgent agent) { SyncedThrowBase(((Il2CppObjectBase)this).Pointer.ToPointer(), ((Il2CppObjectBase)agent).Pointer.ToPointer()); } public unsafe override void SyncedPickup(PlayerAgent agent) { SyncedPickupBase(((Il2CppObjectBase)this).Pointer.ToPointer(), ((Il2CppObjectBase)agent).Pointer.ToPointer()); } public unsafe override void SyncedSetKeyValue(int key, float value) { SyncedSetKeyValueBase(((Il2CppObjectBase)this).Pointer.ToPointer(), key, value); } public unsafe override Interact_Base GetPickupInteraction() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown return new Interact_Base((IntPtr)GetPickupInteractionBase(((Il2CppObjectBase)this).Pointer.ToPointer())); } public unsafe override Item GetItem() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown return new Item((IntPtr)GetItemBase(((Il2CppObjectBase)this).Pointer.ToPointer())); } } public unsafe delegate pItemData* Item__Get_pItemData(pItemData* retstr, void* _this); public unsafe delegate void Item__Set_pItemData(void* _this, void* data); public unsafe delegate pItemData_Custom* Item__GetCustomData(void* _this); public unsafe delegate void Item__SetCustomData(void* _this, pItemData_Custom* custom, bool sync); public unsafe delegate void Item__OnCustomDataUpdated(void* _this, pItemData_Custom* customDataCopy); public unsafe delegate void Item__Awake(void* _this); public unsafe delegate void Item__OnDespawn(void* _this); public unsafe delegate void Item__Setup(void* _this, void* data); public unsafe delegate void Item__OnGearSpawnComplete(void* _this); public unsafe delegate void Item__OnPickUp(void* _this, void* player); public unsafe delegate void Item__SetupBaseModel(void* _this, void* setup); public unsafe delegate void Item__SyncedTurnOn(void* _this, void* agent, void* courseNode); public unsafe delegate void Item__SyncedTurnOff(void* _this, void* agent); public unsafe delegate void Item__SyncedTrigger(void* _this, void* agent); public unsafe delegate void Item__SyncedTriggerSecondary(void* _this, void* agent); public unsafe delegate void Item__SyncedThrow(void* _this, void* agent); public unsafe delegate void Item__SyncedPickup(void* _this, void* agent); public unsafe delegate void Item__SyncedSetKeyValue(void* _this, int key, float value); public unsafe delegate void* Item__GetPickupInteraction(void* _this); public unsafe delegate void* Item__GetItem(void* _this); [Il2CppInterface(typeof(iTerminalItem))] public interface iTerminalItemWrapper { uint TerminalItemId { get; set; } string TerminalItemKey { get; set; } string OverrideCode { get; set; } Vector3 LocatorBeaconPosition { get; set; } AIG_CourseNode SpawnNode { get; set; } bool ShowInFloorInventory { get; set; } string FloorItemLocation { get; set; } eFloorInventoryObjectType FloorItemType { get; set; } eFloorInventoryObjectStatus FloorItemStatus { get; set; } Func<List<string>, List<string>> OnWantDetailedInfo { get; set; } void Setup(string key); List<string> GetDetailedInfo(List<string> defaultDetails); void PlayPing(); } [Il2CppInterface(typeof(iResourcePackReceiver))] public interface iResourcePackReceiverWrapper { bool IsLocallyOwned { get; } string InteractionName { get; } bool NeedHealth(); bool NeedDisinfection(); bool NeedWeaponAmmo(); bool NeedToolAmmo(); void GiveAmmoRel(float ammoStandardRel, float ammoSpecialRel, float ammoClassRel); void GiveHealth(float health); void GiveDisinfection(float disinfection); } [Il2CppInterface(typeof(iPlayerPingTarget))] public interface iPlayerPingTargetWrapper { eNavMarkerStyle PingTargetStyle { get; set; } } [Il2CppInterface(typeof(iWardenObjectiveItem))] public interface iWardenObjectiveItemWrapper { LG_LayerType OriginLayer { get; } AIG_CourseNode SpawnNode { get; } string PublicName { get; } Transform transform { get; } bool ObjectiveItemSolved { get; } ePickupItemStatus PickupItemStatus { get; } PlayerAgent PickedUpByPlayer { get; } void ActivateWardenObjectiveItem(); void DeactivateWardenObjectiveItem(); } } namespace GTFO.API.Utilities { public static class CoroutineDispatcher { public static Coroutine StartCoroutine(IEnumerator routine) { return CoroutineDispatcher_Impl.Instance.RunCoroutine(routine); } public static Coroutine StartInLevelCoroutine(IEnumerator routine) { return CoroutineDispatcher_Impl.Instance.RunInLevelCoroutine(routine); } } public delegate void LiveEditEventHandler(LiveEditEventArgs e); public class LiveEditEventArgs { public LiveEditEventType Type { get; set; } public string FullPath { get; set; } public string FileName { get; set; } } public enum LiveEditEventType { Created, Deleted, Renamed, Changed } public static class LiveEdit { internal const int RETRY_COUNT = 5; internal const float RETRY_INTERVAL = 0.1f; internal static readonly List<LiveEditListener> s_Listeners = new List<LiveEditListener>(); public static LiveEditListener CreateListener(string path, string filter, bool includeSubDir) { LiveEditListener liveEditListener = new LiveEditListener(path, filter, includeSubDir); s_Listeners.Add(liveEditListener); return liveEditListener; } public static void TryReadFileContent(string filepath, Action<string> onReaded) { CoroutineDispatcher.StartCoroutine(GetFileStream(filepath, 5, 0.1f, delegate(FileStream stream) { try { using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8); onReaded?.Invoke(streamReader.ReadToEnd()); } catch { } })); } private static IEnumerator GetFileStream(string filepath, int retryCount, float retryInterval, Action<FileStream> onFileStreamOpened) { retryCount = Math.Max(retryCount, 1); retryInterval = Math.Max(retryInterval, 0f); WaitForSecondsRealtime wait = new WaitForSecondsRealtime(retryInterval); for (int i = 0; i < retryCount; i++) { try { FileStream fileStream = new FileStream(filepath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite); onFileStreamOpened?.Invoke(fileStream); fileStream.Close(); break; } catch { } yield return wait; } } } public sealed class LiveEditListener : IDisposable { private FileSystemWatcher m_Watcher; private bool m_Allocated = true; private float m_ChangedCooldownTimer; public float FileChangedEventCooldown { get; set; } = 0.05f; public event LiveEditEventHandler FileChanged; public event LiveEditEventHandler FileDeleted; public event LiveEditEventHandler FileCreated; public event LiveEditEventHandler FileRenamed; private LiveEditListener() { } internal LiveEditListener(string path, string filter, bool includeSubDir) { LiveEditListener liveEditListener = this; m_Watcher = new FileSystemWatcher { Path = path, Filter = filter, IncludeSubdirectories = includeSubDir, NotifyFilter = (NotifyFilters.FileName | NotifyFilters.LastWrite | NotifyFilters.CreationTime) }; m_Watcher.Deleted += delegate(object sender, FileSystemEventArgs e) { FileSystemEventArgs e5 = e; ThreadDispatcher.Dispatch(delegate { liveEditListener.FileDeleted?.Invoke(CreateArgs(e5, LiveEditEventType.Deleted)); }); }; m_Watcher.Created += delegate(object sender, FileSystemEventArgs e) { FileSystemEventArgs e4 = e; ThreadDispatcher.Dispatch(delegate { liveEditListener.FileCreated?.Invoke(CreateArgs(e4, LiveEditEventType.Created)); }); }; m_Watcher.Renamed += delegate(object sender, RenamedEventArgs e) { RenamedEventArgs e3 = e; ThreadDispatcher.Dispatch(delegate { liveEditListener.FileRenamed?.Invoke(CreateArgs(e3, LiveEditEventType.Renamed)); }); }; m_Watcher.Changed += delegate(object sender, FileSystemEventArgs e) { FileSystemEventArgs e2 = e; ThreadDispatcher.Dispatch(delegate { float time = Time.time; if (!(liveEditListener.m_ChangedCooldownTimer > time)) { liveEditListener.m_ChangedCooldownTimer = time + liveEditListener.FileChangedEventCooldown; liveEditListener.FileChanged?.Invoke(CreateArgs(e2, LiveEditEventType.Changed)); } }); }; m_Watcher.Error += delegate(object sender, ErrorEventArgs e) { APILogger.Error("LiveEdit", $"Path: {path} error reported! - {e.GetException()}"); }; StartListen(); } private static LiveEditEventArgs CreateArgs(FileSystemEventArgs args, LiveEditEventType type) { return new LiveEditEventArgs { FullPath = args.FullPath, FileName = Path.GetFileName(args.FullPath), Type = type }; } public void Dispose() { if (m_Allocated) { LiveEdit.s_Listeners.Remove(this); m_Allocated = false; } if (m_Watcher != null) { StopListen(); this.FileChanged = null; this.FileDeleted = null; this.FileCreated = null; this.FileRenamed = null; m_Watcher.Dispose(); } m_Watcher = null; } public void StopListen() { if (m_Watcher != null) { m_Watcher.EnableRaisingEvents = false; } } public void StartListen() { if (m_Watcher != null) { m_Watcher.EnableRaisingEvents = true; } } } internal static class MemoryUtils { private static byte[] _trampolineShellcode = new byte[12] { 72, 184, 0, 0, 0, 0, 0, 0, 0, 0, 255, 208 }; public unsafe static void* FindSignatureInBlock(void* block, ulong blockSize, string pattern, string mask, ulong sigOffset = 0uL) { return FindSignatureInBlock(block, blockSize, pattern.ToCharArray(), mask.ToCharArray(), sigOffset); } public unsafe static void* FindSignatureInBlock(void* block, ulong blockSize, char[] pattern, char[] mask, ulong sigOffset = 0uL) { for (ulong num = 0uL; num < blockSize; num++) { bool flag = true; for (uint num2 = 0u; num2 < mask.Length; num2++) { if (*(byte*)((long)num + (long)block + num2) != (byte)pattern[num2] && mask[num2] != '?') { flag = false; break; } } if (flag) { return (void*)((ulong)((long)num + (long)block) + sigOffset); } } return null; } public unsafe static byte[] MakeTrampoline(void* destination) { byte[] array = new byte[_trampolineShellcode.Length]; Array.Copy(_trampolineShellcode, 0, array, 0, _trampolineShellcode.Length); fixed (byte* ptr = array) { *(long*)(ptr + 2) = (long)destination; } return array; } public unsafe static void CreateTrampolineBetween(void* start, void* end, void* destination) { ulong num = (ulong)end - (ulong)start; if (num < (ulong)_trampolineShellcode.Length) { throw new Exception("Trampoline block size is not enough to create."); } uint flNewProtect = default(uint); if (!Kernel32.VirtualProtect(start, num, 64u, &flNewProtect)) { throw new Exception("Failed to change protection of trampoline block."); } APILogger.Verbose("MemoryUtils", "NOPing trampoline block"); for (ulong num2 = 0uL; num2 < num; num2++) { *(sbyte*)((ulong)start + num2) = -112; } APILogger.Verbose("MemoryUtils", "Creating trampoline shellcode"); byte[] array = MakeTrampoline(destination); APILogger.Verbose("MemoryUtils", "Writing trampoline shellcode"); for (ulong num3 = 0uL; num3 < (ulong)array.Length; num3++) { *(byte*)((ulong)start + num3) = array[num3]; } if (!Kernel32.VirtualProtect(start, num, flNewProtect, &flNewProtect)) { throw new Exception("Failed to revert trampoline block protection."); } } } public class PersistentData<T> where T : PersistentData<T>, new() { private const string VERSION_REGEX = "\"PersistentDataVersion\": \"(.+?)\""; private static T s_CurrentData; public static T CurrentData { get { if (s_CurrentData != null) { return s_CurrentData; } s_CurrentData = Load(); return s_CurrentData; } set { s_CurrentData = value; } } protected static string persistentPath => Path.Combine(Paths.BepInExRootPath, "GameData", "PersistentData", typeof(T).Assembly.GetName().Name, typeof(T).Name + ".json"); public virtual string PersistentDataVersion { get; set; } = "1.0.0"; public static T Load() { return Load(persistentPath); } public static T Load(string path) { T val = new T(); if (File.Exists(path)) { string text = File.ReadAllText(path); T val2; try { val2 = GTFO.API.JSON.JsonSerializer.Deserialize<T>(text); } catch (JsonException) { APILogger.Warn("JSON", "Failed to deserialize " + typeof(T).Name + ", replacing with default"); string text2 = "FAILED"; Match match = Regex.Match(text, "\"PersistentDataVersion\": \"(.+?)\""); if (match.Success) { text2 = match.Groups[1].Value + "-FAILED"; } File.WriteAllText(Path.ChangeExtension(path, null) + "-" + text2 + ".json", text); val2 = new T(); val2.Save(path); } if (val2.PersistentDataVersion != val.PersistentDataVersion) { val2.Save(Path.ChangeExtension(path, null) + "-" + val2.PersistentDataVersion + ".json"); val.Save(path); } else { val = val2; } } else { val.Save(path); } return val; } public void Save() { Save(persistentPath); } public void Save(string path) { string contents = GTFO.API.JSON.JsonSerializer.Serialize((T)this); string directoryName = Path.GetDirectoryName(path); if (!Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } File.WriteAllText(path, contents); } } public static class RegexUtils { private static readonly Regex s_VectorRegex = new Regex("-?[0-9.]+"); public static bool TryParseVectorString(string input, out float[] vectorArray) { try { MatchCollection matchCollection = s_VectorRegex.Matches(input); int count = matchCollection.Count; if (count < 1) { throw new Exception(); } vectorArray = new float[count]; for (int i = 0; i < count; i++) { Match match = matchCollection[i]; vectorArray[i] = float.Parse(match.Value, CultureInfo.InvariantCulture); } return true; } catch { vectorArray = null; return false; } } } public static class StringUtils { private static readonly uint[] _lookup32 = ((Func<uint[]>)delegate { uint[] array = new uint[256]; for (int i = 0; i < 256; i++) { string text = i.ToString("X2"); if (BitConverter.IsLittleEndian) { array[i] = text[0] + ((uint)text[1] << 16); } else { array[i] = text[1] + ((uint)text[0] << 16); } } return array; })(); private unsafe static readonly uint* _lookup32Ptr = (uint*)(void*)GCHandle.Alloc(_lookup32, GCHandleType.Pinned).AddrOfPinnedObject(); public unsafe static string FromByteArrayAsHex(byte[] bytes) { char[] array = new char[bytes.Length * 2]; fixed (byte* ptr3 = bytes) { fixed (char* ptr = array) { uint* ptr2 = (uint*)ptr; for (int i = 0; i < bytes.Length; i++) { ptr2[i] = _lookup32Ptr[(int)ptr3[i]]; } } } return new string(array); } } public static class ThreadDispatcher { public static void Dispatch(Action action) { ThreadDispatcher_Impl.Instance.EnqueueAction(action); } } } namespace GTFO.API.Utilities.Impl { internal class CoroutineDispatcher_Impl : MonoBehaviour { private bool m_HasInLevelCoroutines; private readonly List<Coroutine> m_InLevelCoroutines; private static CoroutineDispatcher_Impl s_Instance; public static CoroutineDispatcher_Impl Instance { get { if ((Object)(object)s_Instance == (Object)null) { CoroutineDispatcher_Impl coroutineDispatcher_Impl = Object.FindObjectOfType<CoroutineDispatcher_Impl>(); if ((Object)(object)coroutineDispatcher_Impl != (Object)null) { s_Instance = coroutineDispatcher_Impl; } } return s_Instance; } } static CoroutineDispatcher_Impl() { AssetAPI.OnStartupAssetsLoaded += OnAssetsLoaded; } private static void OnAssetsLoaded() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown if (!((Object)(object)s_Instance != (Object)null)) { GameObject val = new GameObject(); CoroutineDispatcher_Impl coroutineDispatcher_Impl = val.AddComponent<CoroutineDispatcher_Impl>(); ((Object)val).name = "GTFO-API Coroutine Dispatcher"; ((Object)val).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)val); s_Instance = coroutineDispatcher_Impl; } } private void Update() { if (m_HasInLevelCoroutines && !GameStateManager.IsInExpedition) { m_InLevelCoroutines.ForEach(delegate(Coroutine coroutine) { ((MonoBehaviour)this).StopCoroutine(coroutine); }); m_HasInLevelCoroutines = false; } } [HideFromIl2Cpp] internal Coroutine RunCoroutine(IEnumerator routine) { return MonoBehaviourExtensions.StartCoroutine((MonoBehaviour)(object)this, routine); } [HideFromIl2Cpp] internal Coroutine RunInLevelCoroutine(IEnumerator routine) { if (!GameStateManager.IsInExpedition) { APILogger.Error("CoroutineDispatcher", "Cannot run InLevelCoroutine while you're not in level!"); return null; } Coroutine val = MonoBehaviourExtensions.StartCoroutine((MonoBehaviour)(object)this, routine); m_InLevelCoroutines.Add(val); m_HasInLevelCoroutines = true; return val; } } internal class ThreadDispatcher_Impl : MonoBehaviour { private readonly Queue<Action> s_ActionQueue = new Queue<Action>(); private static ThreadDispatcher_Impl s_Instance; public static ThreadDispatcher_Impl Instance { get { if ((Object)(object)s_Instance == (Object)null) { ThreadDispatcher_Impl threadDispatcher_Impl = Object.FindObjectOfType<ThreadDispatcher_Impl>(); if ((Object)(object)threadDispatcher_Impl != (Object)null) { s_Instance = threadDispatcher_Impl; } } return s_Instance; } } public ThreadDispatcher_Impl(IntPtr intPtr) : base(intPtr) { } static ThreadDispatcher_Impl() { AssetAPI.OnStartupAssetsLoaded += OnAssetsLoaded; } private static void OnAssetsLoaded() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown if (!((Object)(object)s_Instance != (Object)null)) { GameObject val = new GameObject(); ThreadDispatcher_Impl threadDispatcher_Impl = val.AddComponent<ThreadDispatcher_Impl>(); ((Object)val).name = "GTFO-API Thread Dispatcher"; ((Object)val).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)val); s_Instance = threadDispatcher_Impl; } } [HideFromIl2Cpp] internal void EnqueueAction(Action action) { lock (s_ActionQueue) { s_ActionQueue.Enqueue(action); } } internal void Update() { lock (s_ActionQueue) { while (s_ActionQueue.Count > 0) { s_ActionQueue.Dequeue()?.Invoke(); } } } } } namespace GTFO.API.Resources { public class ApiStatusInfo { public bool Created { get; internal set; } public bool Ready { get; internal set; } } public static class APIStatus { private static GameObject s_ScriptHolder; public static ApiStatusInfo Asset { get; internal set; } = new ApiStatusInfo(); public static ApiStatusInfo Event { get; internal set; } = new ApiStatusInfo(); public static ApiStatusInfo GameData { get; internal set; } = new ApiStatusInfo(); public static ApiStatusInfo Localization { get; internal set; } = new ApiStatusInfo(); public static ApiStatusInfo Il2Cpp { get; internal set; } = new ApiStatusInfo(); public static ApiStatusInfo Level { get; internal set; } = new ApiStatusInfo(); public static ApiStatusInfo Network { get; internal set; } = new ApiStatusInfo(); public static ApiStatusInfo Prefab { get; internal set; } = new ApiStatusInfo(); public static ApiStatusInfo SoundBank { get; internal set; } = new ApiStatusInfo(); internal static GameObject ScriptHolder { get { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown if ((Object)(object)s_ScriptHolder == (Object)null) { s_ScriptHolder = new GameObject(); ((Object)s_ScriptHolder).name = "GTFO-API Script Holder"; ((Object)s_ScriptHolder).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)s_ScriptHolder); } return s_ScriptHolder; } } internal static void CreateApi<T>(string apiName) where T : Component { ApiStatusInfo apiStatusInfo = (ApiStatusInfo)(typeof(APIStatus).GetProperty(apiName)?.GetValue(null)); if (apiStatusInfo == null) { throw new ArgumentException("Couldn't find API status for " + apiName, "apiName"); } if (!apiStatusInfo.Created && !((Object)(object)ScriptHolder.GetComponent<T>() != (Object)null)) { APILogger.Verbose("Core", "Creating API " + apiName); ScriptHolder.AddComponent<T>(); apiStatusInfo.Created = true; } } } internal static class RuntimeData { public static Dictionary<InventorySlot, string[]> BotFavorites; } public static class ShaderConstants { public const string CUSTOM_GEAR_SHADER = "Cell/Player/CustomGearShader"; } public static class NetworkConstants { public const string Magic = "GAPI_KSQK"; public const byte MagicSize = 9; public const ulong VersionSignature = 18374688171108015565uL; } } namespace GTFO.API.Patches { [HarmonyPatch(typeof(CellSettingsApply), "ApplyLanguage")] internal static class ApplyLanguage_Patches { private static bool s_LanguageChanged; [HarmonyWrapSafe] public static void Prefix(int value) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 s_LanguageChanged = (int)Text.TextLocalizationService.CurrentLanguage != value; } [HarmonyWrapSafe] public static void Postfix() { if (s_LanguageChanged) { LocalizationAPI.LanguageChanged(); } } } [HarmonyPatch(typeof(AssetShardManager))] internal class AssetShardManager_Patches { [HarmonyPatch("Setup")] [HarmonyWrapSafe] [HarmonyPostfix] public static void Setup_Postfix() { if (!APIStatus.Asset.Created) { APIStatus.CreateApi<AssetAPI_Impl>("Asset"); } } } [HarmonyPatch(typeof(Builder))] internal class Builder_Patches { [HarmonyPatch("Build")] [HarmonyWrapSafe] [HarmonyPostfix] private static void BuildStart_Postfix() { LevelAPI.BuildStart(); } [HarmonyPatch("BuildDone")] [HarmonyWrapSafe] [HarmonyPostfix] private static void BuildDone_Postfix() { LevelAPI.BuildDone(); } } [HarmonyPatch(typeof(GameDataInit))] internal class GameDataInit_Patches { private struct PluginWhitelistInfo { public string GUID; public string Name; public string Version; public string Checksum; } private static PluginWhitelistInfo[] FetchPluginWhitelist() { using HttpClient httpClient = new HttpClient(); using Stream stream = httpClient.GetStreamAsync("https://raw.githubusercontent.com/GTFO-Modding/GTFO-API-PluginWhitelist/main/whitelist.txt").GetAwaiter().GetResult(); using StreamReader streamReader = new StreamReader(stream); string[] array = streamReader.ReadToEnd().Split('\n', StringSplitOptions.RemoveEmptyEntries); PluginWhitelistInfo[] array2 = new PluginWhitelistInfo[array.Length]; for (int i = 0; i < array2.Length; i++) { string[] array3 = array[i].Split(":"); array2[i] = new PluginWhitelistInfo { GUID = array3[0], Name = array3[1], Version = array3[2], Checksum = array3[3].TrimEnd('\r') }; } return array2; } [HarmonyPatch("Initialize")] [HarmonyWrapSafe] [HarmonyPostfix] public static void Initialize_Postfix() { Analytics.enabled = false; GameDataAPI.InvokeGameDataInit(); if (!APIStatus.Network.Created) { APIStatus.CreateApi<NetworkAPI_Impl>("Network"); } } private static void RemoveRequirementFromList(List<ExpeditionInTierData> list) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 Enumerator<ExpeditionInTierData> enumerator = list.GetEnumerator(); while (enumerator.MoveNext()) { ExpeditionInTierData current = enumerator.Current; if (current.Enabled) { eExpeditionAccessibility accessibility = current.Accessibility; if ((int)accessibility == 0 || accessibility - 4 <= 1) { current.Accessibility = (eExpeditionAccessibility)2; } } } } } [HarmonyPatch(typeof(GearManager))] internal static class GearManager_Patches { private unsafe delegate IntPtr ReadFromDiskDelegate(IntPtr path, byte* createNew, Il2CppMethodInfo* methodInfo); private unsafe delegate void SaveToDiskDelegate(IntPtr path, IntPtr obj, Il2CppMethodInfo* methodInfo); private static bool m_PatchApplied; private static INativeDetour s_ReadFromDiskDetour; private static ReadFromDiskDelegate s_ReadFromDiskOriginal; private static INativeDetour s_SaveToDiskDetour; private static SaveToDiskDelegate s_SaveToDiskOriginal; private static string FavoritesDirectory => Path.Combine(Paths.BepInExRootPath, "GameData", "Favorites"); private static string FavoritePath => Path.Combine(FavoritesDirectory, "Gear.json"); private static string BotFavoritePath => Path.Combine(FavoritesDirectory, "BotGear.json"); [HarmonyPatch("Setup")] [HarmonyWrapSafe] [HarmonyPrefix] private unsafe static void Setup_Prefix() { if (!m_PatchApplied) { if (!Directory.Exists(FavoritesDirectory)) { Directory.CreateDirectory(FavoritesDirectory); } string methodName = "SaveToDisk"; APILogger.Verbose("GearManager_Patches", "Applying ReadFromDisk Patch"); s_ReadFromDiskDetour = Il2CppAPI.CreateGenericDetour<CellJSON, ReadFromDiskDelegate>("ReadFromDisk", "T", new string[2] { typeof(string).FullName, typeof(bool).MakeByRefType().FullName }, new Type[1] { typeof(GearFavoritesData) }, (ReadFromDiskDelegate)Patch_ReadFromDisk, out s_ReadFromDiskOriginal); APILogger.Verbose("GearManager_Patches", "Applying SaveToDisk Patch"); s_SaveToDiskDetour = Il2CppAPI.CreateGenericDetour<CellJSON, SaveToDiskDelegate>(methodName, typeof(void).FullName, new string[2] { typeof(string).FullName, "T" }, new Type[1] { typeof(GearFavoritesData) }, (SaveToDiskDelegate)Patch_SaveToDisk, out s_SaveToDiskOriginal); m_PatchApplied = true; } } private unsafe static IntPtr Patch_ReadFromDisk(IntPtr path, byte* createNew, Il2CppMethodInfo* methodInfo) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown string text = String.op_Implicit(new String(path)); if (text.EndsWith("GTFO_Favorites.txt", StringComparison.OrdinalIgnoreCase)) { return s_ReadFromDiskOriginal(IL2CPP.ManagedStringToIl2Cpp(FavoritePath), createNew, methodInfo); } if (text.EndsWith("GTFO_BotFavorites.txt", StringComparison.OrdinalIgnoreCase)) { return s_ReadFromDiskOriginal(IL2CPP.ManagedStringToIl2Cpp(BotFavoritePath), createNew, methodInfo); } return s_ReadFromDiskOriginal(path, createNew, methodInfo); } private unsafe static void Patch_SaveToDisk(IntPtr path, IntPtr favData, Il2CppMethodInfo* methodInfo) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown string text = String.op_Implicit(new String(path)); if (text.EndsWith("GTFO_Favorites.txt", StringComparison.OrdinalIgnoreCase)) { s_SaveToDiskOriginal(IL2CPP.ManagedStringToIl2Cpp(FavoritePath), favData, methodInfo); } else if (text.EndsWith("GTFO_BotFavorites.txt", StringComparison.OrdinalIgnoreCase)) { s_SaveToDiskOriginal(IL2CPP.ManagedStringToIl2Cpp(BotFavoritePath), favData, methodInfo); if (File.Exists(text)) { File.Delete(text); } } else { s_SaveToDiskOriginal(path, favData, methodInfo); } } } [HarmonyPatch(typeof(Global))] internal class Global_Patches { [HarmonyPatch("OnLevelCleanup")] [HarmonyWrapSafe] [HarmonyPostfix] private static void LevelCleanup_Postfix() { LevelAPI.LevelCleanup(); } } [HarmonyPatch(typeof(RundownManager))] internal class RundownManager_Patches { [HarmonyPatch("SetActiveExpedition")] [HarmonyWrapSafe] [HarmonyPostfix] private static void SetActiveExpedition_Postfix(pActiveExpedition expPackage, ExpeditionInTierData expTierData) { LevelAPI.ExpeditionUpdated(expPackage, expTierData); } } [HarmonyPatch(typeof(SNet_Replication))] internal class SNet_Replication_Patches { [HarmonyPatch("RecieveBytes")] [HarmonyWrapSafe] [HarmonyPrefix] public static bool RecieveBytes_Prefix(Il2CppStructArray<byte> bytes, uint size, ulong messagerID) { if (size < 12) { return true; } byte[] array = Il2CppArrayBase<byte>.op_Implicit((Il2CppArrayBase<byte>)(object)bytes); ushort num = BitConverter.ToUInt16(array, 0); if (NetworkAPI_Impl.Instance.m_ReplicatorKey == num) { string @string = Encoding.ASCII.GetString(array, 2, 9); if (@string != "GAPI_KSQK") { APILogger.Verbose("NetworkApi", $"Received invalid magic from {messagerID} ({@string} != {9})."); return true; } ulong num2 = BitConverter.ToUInt64(array, 11); if ((num2 & 0xFF00000000000000uL) != 18374686479671623680uL) { APILogger.Verbose("NetworkApi", $"Received invalid version signature from {messagerID}."); return true; } if (num2 != NetworkAPI_Impl.Instance.m_Signature) { APILogger.Error("NetworkApi", $"Received incompatible version signature, cannot unmask packet. Is {messagerID} on the same version?. ({num2} != {NetworkAPI_Impl.Instance.m_Signature})"); return false; } ushort num3 = BitConverter.ToUInt16(array, 19); string string2 = Encoding.UTF8.GetString(array, 21, num3); if (!NetworkAPI.IsEventRegistered(string2)) { APILogger.Error("NetworkApi", $"{messagerID} invoked an event {string2} which isn't registered."); return false; } NetworkAPI_Impl.Instance.HandlePacket(string2, messagerID, array, 21 + num3); return false; } return true; } } } namespace GTFO.API.Patches.Native { internal class SyringeFirstPerson_Patch : NativePatch<SyringeFirstPerson_Patch.SyringeUsedDelegate> { [UnmanagedFunctionPointer(CallingConvention.FastCall)] public unsafe delegate eSyringeType SyringeUsedDelegate(void* pSyringe); public unsafe override void* MethodPtr => Il2CppAPI.GetIl2CppMethod<_ApplySyringe_d__18>("MoveNext", "System.Boolean", isGeneric: false, Array.Empty<string>()); public override string JmpStartSig => "Æ\u0081\u00b4\0\0\0\u0001\u008b\u0087Ð\u0001\0\0\u0085À"; public override string JmpStartMask => "xxxxxxxxxxxxxxx"; public override byte[] CodeCave => new byte[10] { 198, 129, 180, 0, 0, 0, 1, 72, 137, 249 }; public override uint TrampolineSize => 13u; public unsafe override SyringeUsedDelegate To => OnSyringeApplyEffect; public unsafe static eSyringeType OnSyringeApplyEffect(void* pSyringe) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0017: Unknown result type (might be due to invalid IL or missing references) SyringeFirstPerson val = new SyringeFirstPerson(new IntPtr(pSyringe)); if (PrefabAPI.OnSyringeUsed(val)) { return (eSyringeType)(-1); } return val.m_type; } } } namespace GTFO.API.Native { internal static class Kernel32 { [DllImport("kernel32.dll")] public unsafe static extern void* VirtualAlloc(void* lpAddress, ulong dwSize, uint flAllocationType, uint flProtect); [DllImport("kernel32.dll")] public unsafe static extern bool VirtualProtect(void* lpAddress, ulong dwSize, uint flNewProtect, uint* lpflOldProtect); } internal static class MSVCRT { [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] public unsafe static extern void* memcpy(void* destination, void* source, long num); } public abstract class NativePatch<T> where T : Delegate { private static readonly byte[] s_CodeCaveHeader = new byte[4] { 72, 131, 236, 40 }; private static readonly byte[] s_CodeCaveFooter = new byte[17] { 72, 184, 0, 0, 0, 0, 0, 0, 0, 0, 255, 208, 72, 131,
plugins/Inas07.ThermalSights.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text.Json.Serialization; using AssetShards; using BepInEx; using BepInEx.Unity.IL2CPP; using ChainedPuzzles; using ExtraObjectiveSetup.BaseClasses; using ExtraObjectiveSetup.Expedition.Gears; using ExtraObjectiveSetup.Utils; using FirstPersonItem; using GTFO.API; using GTFO.API.Utilities; using GameData; using HarmonyLib; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem; using Microsoft.CodeAnalysis; using ThermalSights.Definition; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("Inas07.ThermalSights")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Inas07.ThermalSights")] [assembly: AssemblyTitle("Inas07.ThermalSights")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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 ThermalSights { [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("Inas.ThermalSights", "ThermalSights", "1.0.0")] public class EntryPoint : BasePlugin { public const string AUTHOR = "Inas"; public const string PLUGIN_NAME = "ThermalSights"; public const string VERSION = "1.0.0"; private Harmony m_Harmony; public override void Load() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown SetupManagers(); m_Harmony = new Harmony("ThermalSights"); m_Harmony.PatchAll(); EOSLogger.Log("ThermalSights loaded."); } private void SetupManagers() { AssetShardManager.OnStartupAssetsLoaded += Action.op_Implicit((Action)delegate { ((GenericDefinitionManager<TSADefinition>)TSAManager.Current).Init(); }); } } public class TSAManager : GenericDefinitionManager<TSADefinition> { public class PuzzleVisualWrapper { public GameObject GO { get; set; } public Renderer Renderer { get; set; } public float Intensity { get; set; } public float BehindWallIntensity { get; set; } public void SetIntensity(float t) { if (GO.active) { if (Intensity > 0f) { Renderer.material.SetFloat("_Intensity", Intensity * t); } if (BehindWallIntensity > 0f) { Renderer.material.SetFloat("_BehindWallIntensity", BehindWallIntensity * t); } } } } private const bool OUTPUT_THERMAL_SHADER_SETTINGS_ON_WIELD = false; public static TSAManager Current { get; } protected override string DEFINITION_NAME => "ThermalSight"; private Dictionary<uint, Renderer[]> InLevelGearThermals { get; } = new Dictionary<uint, Renderer[]>(); private HashSet<uint> ModifiedInLevelGearThermals { get; } = new HashSet<uint>(); private HashSet<uint> ThermalOfflineGears { get; } = new HashSet<uint>(); public uint CurrentGearPID { get; private set; } private List<PuzzleVisualWrapper> PuzzleVisuals { get; } = new List<PuzzleVisualWrapper>(); protected override void FileChanged(LiveEditEventArgs e) { base.FileChanged(e); InitThermalOfflineGears(); CleanupInLevelGearThermals(keepCurrentGear: true); TrySetThermalSightRenderer(CurrentGearPID); } public override void Init() { InitThermalOfflineGears(); } private void InitThermalOfflineGears() { ThermalOfflineGears.Clear(); foreach (PlayerOfflineGearDataBlock allBlock in GameDataBlockBase<PlayerOfflineGearDataBlock>.GetAllBlocks()) { if (((GameDataBlockBase<PlayerOfflineGearDataBlock>)(object)allBlock).name.ToLowerInvariant().EndsWith("_t")) { ThermalOfflineGears.Add(((GameDataBlockBase<PlayerOfflineGearDataBlock>)(object)allBlock).persistentID); } } EOSLogger.Debug($"Found OfflineGear with thermal sight, count: {ThermalOfflineGears.Count}"); } private bool TryGetInLevelGearThermalRenderersFromItem(ItemEquippable item, uint gearPID, out Renderer[] renderers) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) renderers = null; if (item.GearIDRange == null) { return false; } if (gearPID == 0) { gearPID = ExpeditionGearManager.GetOfflineGearPID(item.GearIDRange); } if (gearPID == 0 || !IsGearWithThermal(gearPID)) { return false; } bool flag = false; if (!InLevelGearThermals.ContainsKey(gearPID)) { flag = true; } else { try { _ = ((Component)InLevelGearThermals[gearPID][0]).gameObject.transform.position; flag = false; } catch { ModifiedInLevelGearThermals.Remove(gearPID); flag = true; } } if (flag) { renderers = (from x in ((IEnumerable<Renderer>)((Component)item).GetComponentsInChildren<Renderer>(true))?.Where((Renderer x) => (Object)(object)x.sharedMaterial != (Object)null && (Object)(object)x.sharedMaterial.shader != (Object)null) where ((Object)x.sharedMaterial.shader).name.ToLower().Contains("Thermal".ToLower()) select x).ToArray() ?? null; if (renderers != null) { if (renderers.Length != 1) { EOSLogger.Warning(((Item)item).PublicName + " contains more than 1 thermal renderers!"); } InLevelGearThermals[gearPID] = renderers; return true; } EOSLogger.Debug(((Item)item).PublicName + ": thermal renderer not found"); return false; } renderers = InLevelGearThermals[gearPID]; return true; } internal bool TrySetThermalSightRenderer(uint gearPID = 0u) { //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Expected O, but got Unknown //IL_0190: Unknown result type (might be due to invalid IL or missing references) if (gearPID == 0) { gearPID = CurrentGearPID; } if (!IsGearWithThermal(gearPID)) { return false; } if (ModifiedInLevelGearThermals.Contains(gearPID)) { return true; } if (base.definitions.TryGetValue(gearPID, out var value) && InLevelGearThermals.TryGetValue(gearPID, out var value2)) { TSShader shader = value.Definition.Shader; Renderer[] array = value2; foreach (Renderer val in array) { PropertyInfo[] properties = shader.GetType().GetProperties(); foreach (PropertyInfo propertyInfo in properties) { Type type = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType; string text = "_" + propertyInfo.Name; if (type == typeof(float)) { val.material.SetFloat(text, (float)propertyInfo.GetValue(shader)); } else if (type == typeof(EOSColor)) { EOSColor val2 = (EOSColor)propertyInfo.GetValue(shader); val.material.SetVector(text, Color.op_Implicit(val2.ToUnityColor())); } else if (type == typeof(bool)) { bool flag = (bool)propertyInfo.GetValue(shader); val.material.SetFloat(text, flag ? 1f : 0f); } else if (type == typeof(Vec4)) { Vec4 val3 = (Vec4)propertyInfo.GetValue(shader); val.material.SetVector(text, val3.ToVector4()); } } } ModifiedInLevelGearThermals.Add(gearPID); return true; } return false; } internal void OnPlayerItemWielded(FirstPersonItemHolder fpsItemHolder, ItemEquippable item) { if (item.GearIDRange == null) { CurrentGearPID = 0u; return; } CurrentGearPID = ExpeditionGearManager.GetOfflineGearPID(item.GearIDRange); TryGetInLevelGearThermalRenderersFromItem(item, CurrentGearPID, out var _); TrySetThermalSightRenderer(CurrentGearPID); } public bool IsGearWithThermal(uint gearPID) { return ThermalOfflineGears.Contains(gearPID); } private void CleanupInLevelGearThermals(bool keepCurrentGear = false) { if (!keepCurrentGear || !InLevelGearThermals.ContainsKey(CurrentGearPID)) { InLevelGearThermals.Clear(); } else { Renderer[] value = InLevelGearThermals[CurrentGearPID]; InLevelGearThermals.Clear(); InLevelGearThermals[CurrentGearPID] = value; } ModifiedInLevelGearThermals.Clear(); } internal void SetCurrentThermalSightSettings(float t) { if (InLevelGearThermals.TryGetValue(CurrentGearPID, out var value) && base.definitions.TryGetValue(CurrentGearPID, out var value2)) { Renderer[] array = value; foreach (Renderer obj in array) { float zoom = value2.Definition.Shader.Zoom; float offAimPixelZoom = value2.Definition.OffAimPixelZoom; float num = Mathf.Lerp(zoom, offAimPixelZoom, t); obj.material.SetFloat("_Zoom", num); } } } private void Clear() { CurrentGearPID = 0u; CleanupInLevelGearThermals(); CleanupPuzzleVisuals(); } private TSAManager() { LevelAPI.OnBuildStart += Clear; LevelAPI.OnLevelCleanup += Clear; } static TSAManager() { Current = new TSAManager(); } public void RegisterPuzzleVisual(CP_Bioscan_Core core) { Il2CppArrayBase<Renderer> componentsInChildren = ((Component)core).gameObject.GetComponentsInChildren<Renderer>(true); if (componentsInChildren == null) { return; } foreach (Renderer item2 in ((IEnumerable<Renderer>)componentsInChildren).Where((Renderer comp) => ((Object)((Component)comp).gameObject).name.Equals("Zone")).ToList()) { GameObject gameObject = ((Component)item2).gameObject; float @float = item2.material.GetFloat("_Intensity"); float float2 = item2.material.GetFloat("_BehindWallIntensity"); PuzzleVisualWrapper item = new PuzzleVisualWrapper { GO = gameObject, Renderer = item2, Intensity = @float, BehindWallIntensity = float2 }; PuzzleVisuals.Add(item); } } public void RegisterPuzzleVisual(PuzzleVisualWrapper wrapper) { PuzzleVisuals.Add(wrapper); } internal void SetPuzzleVisualsIntensity(float t) { PuzzleVisuals.ForEach(delegate(PuzzleVisualWrapper v) { v.SetIntensity(t); }); } private void CleanupPuzzleVisuals() { PuzzleVisuals.Clear(); } } } namespace ThermalSights.Patches { internal static class CP_Bioscan_Core_Setup { [HarmonyPostfix] [HarmonyPatch(typeof(CP_Bioscan_Core), "Setup")] private static void Post_CaptureBioscanVisual(CP_Bioscan_Core __instance) { TSAManager.Current.RegisterPuzzleVisual(__instance); } } [HarmonyPatch] internal static class FirstPersonItemHolder_SetWieldedItem { public static event Action<FirstPersonItemHolder, ItemEquippable> OnItemWielded; [HarmonyPostfix] [HarmonyPatch(typeof(FirstPersonItemHolder), "SetWieldedItem")] private static void Post_SetWieldedItem(FirstPersonItemHolder __instance, ItemEquippable item) { TSAManager.Current.OnPlayerItemWielded(__instance, item); TSAManager.Current.SetPuzzleVisualsIntensity(1f); TSAManager.Current.SetCurrentThermalSightSettings(1f); FirstPersonItemHolder_SetWieldedItem.OnItemWielded?.Invoke(__instance, item); } } [HarmonyPatch] internal static class FPIS_Aim_Update { public static event Action<FPIS_Aim, float> OnAimUpdate; [HarmonyPostfix] [HarmonyPatch(typeof(FPIS_Aim), "Update")] private static void Post_Aim_Update(FPIS_Aim __instance) { if (!((Object)(object)((FPItemState)__instance).Holder.WieldedItem == (Object)null)) { float num = 1f - FirstPersonItemHolder.m_transitionDelta; if (!TSAManager.Current.IsGearWithThermal(TSAManager.Current.CurrentGearPID)) { num = Math.Max(0.05f, num); } else { TSAManager.Current.SetCurrentThermalSightSettings(num); } TSAManager.Current.SetPuzzleVisualsIntensity(num); FPIS_Aim_Update.OnAimUpdate?.Invoke(__instance, num); } } } } namespace ThermalSights.Definition { public class TSADefinition { public float OffAimPixelZoom { get; set; } = 1f; public TSShader Shader { get; set; } = new TSShader(); } public class TSShader { [JsonPropertyName("DistanceFalloff")] [Range(0.0, 1.0)] public float HeatFalloff { get; set; } = 0.01f; [Range(0.0, 1.0)] public float FogFalloff { get; set; } = 0.1f; [JsonPropertyName("PixelZoom")] [Range(0.0, 1.0)] public float Zoom { get; set; } = 0.8f; [JsonPropertyName("AspectRatioAdjust")] [Range(0.0, 2.0)] public float RatioAdjust { get; set; } = 1f; [Range(0.0, 1.0)] public float DistortionCenter { get; set; } = 0.5f; public float DistortionScale { get; set; } = 1f; public float DistortionSpeed { get; set; } = 1f; public float DistortionSignalSpeed { get; set; } = 0.025f; [Range(0.0, 1.0)] public float DistortionMin { get; set; } = 0.01f; [Range(0.0, 1.0)] public float DistortionMax { get; set; } = 0.4f; [JsonPropertyName("AmbientTemperature")] [Range(0.0, 1.0)] public float AmbientTemp { get; set; } = 0.15f; [JsonPropertyName("BackgroundTemperature")] [Range(0.0, 1.0)] public float BackgroundTemp { get; set; } = 0.05f; [Range(0.0, 10.0)] public float AlbedoColorFactor { get; set; } = 0.5f; [Range(0.0, 10.0)] public float AmbientColorFactor { get; set; } = 5f; public float OcclusionHeat { get; set; } = 0.5f; public float BodyOcclusionHeat { get; set; } = 2.5f; [Range(0.0, 1.0)] public float ScreenIntensity { get; set; } = 0.2f; [Range(0.0, 1.0)] public float OffAngleFade { get; set; } = 0.95f; [Range(0.0, 1.0)] public float Noise { get; set; } = 0.1f; [JsonPropertyName("MinShadowEnemyDistortion")] [Range(0.0, 1.0)] public float DistortionMinShadowEnemies { get; set; } = 0.2f; [JsonPropertyName("MaxShadowEnemyDistortion")] [Range(0.0, 1.0)] public float DistortionMaxShadowEnemies { get; set; } = 1f; [Range(0.0, 1.0)] public float DistortionSignalSpeedShadowEnemies { get; set; } = 1f; public float ShadowEnemyFresnel { get; set; } = 10f; [Range(0.0, 1.0)] public float ShadowEnemyHeat { get; set; } = 0.1f; public EOSColor ReticuleColorA { get; set; } = new EOSColor { r = 1f, g = 1f, b = 1f, a = 1f }; public EOSColor ReticuleColorB { get; set; } = new EOSColor { r = 1f, g = 1f, b = 1f, a = 1f }; public EOSColor ReticuleColorC { get; set; } = new EOSColor { r = 1f, g = 1f, b = 1f, a = 1f }; [Range(0.0, 20.0)] public float SightDirt { get; set; } public bool LitGlass { get; set; } public bool ClipBorders { get; set; } = true; public Vec4 AxisX { get; set; } = new Vec4(); public Vec4 AxisY { get; set; } = new Vec4(); public Vec4 AxisZ { get; set; } = new Vec4(); public bool Flip { get; set; } = true; [JsonPropertyName("Distance1")] [Range(0.0, 100.0)] public float ProjDist1 { get; set; } = 100f; [JsonPropertyName("Distance2")] [Range(0.0, 100.0)] public float ProjDist2 { get; set; } = 66f; [JsonPropertyName("Distance3")] [Range(0.0, 100.0)] public float ProjDist3 { get; set; } = 33f; [JsonPropertyName("Size1")] [Range(0.0, 3.0)] public float ProjSize1 { get; set; } = 1f; [JsonPropertyName("Size2")] [Range(0.0, 3.0)] public float ProjSize2 { get; set; } = 1f; [JsonPropertyName("Size3")] [Range(0.0, 3.0)] public float ProjSize3 { get; set; } = 1f; [JsonPropertyName("Zeroing")] [Range(-1.0, 1.0)] public float ZeroOffset { get; set; } } }