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,