using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SpongePEAK.Core.Logging;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("sponge")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright (c) sponge")]
[assembly: AssemblyDescription("Pure library tier: logging, config, reflection and patching helpers. Registers no BepInEx plugin.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+ddcbf023fcb4c2065ad9b038910633cd4a3a93b0")]
[assembly: AssemblyProduct("SpongePEAKCore")]
[assembly: AssemblyTitle("com.sponge.peakcore")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[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 SpongePEAK.Core.Reflection
{
public static class ReflectionCache
{
private const BindingFlags AllInstance = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
private const BindingFlags AllStatic = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
private const BindingFlags All = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
private static readonly Dictionary<(Type, string), FieldInfo> Fields = new Dictionary<(Type, string), FieldInfo>();
private static readonly Dictionary<(Type, string), PropertyInfo> Properties = new Dictionary<(Type, string), PropertyInfo>();
private static readonly Dictionary<(Type, string), MethodInfo> Methods = new Dictionary<(Type, string), MethodInfo>();
public static FieldInfo Field(Type type, string name)
{
if (type == null || string.IsNullOrEmpty(name))
{
return null;
}
(Type, string) key = (type, name);
if (Fields.TryGetValue(key, out var value))
{
return value;
}
FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
Fields[key] = field;
return field;
}
public static PropertyInfo Property(Type type, string name)
{
if (type == null || string.IsNullOrEmpty(name))
{
return null;
}
(Type, string) key = (type, name);
if (Properties.TryGetValue(key, out var value))
{
return value;
}
PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
Properties[key] = property;
return property;
}
public static MethodInfo Method(Type type, string name)
{
if (type == null || string.IsNullOrEmpty(name))
{
return null;
}
(Type, string) key = (type, name);
if (Methods.TryGetValue(key, out var value))
{
return value;
}
MethodInfo methodInfo;
try
{
methodInfo = type.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
}
catch (AmbiguousMatchException)
{
methodInfo = null;
}
Methods[key] = methodInfo;
return methodInfo;
}
public static T GetField<T>(object instance, string name, T fallback = default(T))
{
if (instance == null)
{
return fallback;
}
FieldInfo fieldInfo = Field(instance.GetType(), name);
if (fieldInfo == null)
{
return fallback;
}
try
{
return (fieldInfo.GetValue(instance) is T val) ? val : fallback;
}
catch
{
return fallback;
}
}
public static bool SetField(object instance, string name, object value)
{
if (instance == null)
{
return false;
}
FieldInfo fieldInfo = Field(instance.GetType(), name);
if (fieldInfo == null)
{
return false;
}
try
{
fieldInfo.SetValue(instance, value);
return true;
}
catch
{
return false;
}
}
public static void Clear()
{
Fields.Clear();
Properties.Clear();
Methods.Clear();
}
}
}
namespace SpongePEAK.Core.Patching
{
public sealed class PatchHost : IDisposable
{
private readonly ModLog _log;
private Harmony _harmony;
public string Id { get; }
public int FailureCount { get; private set; }
public Harmony Harmony
{
get
{
//IL_0011: 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)
//IL_0018: Expected O, but got Unknown
//IL_001d: Expected O, but got Unknown
Harmony obj = _harmony;
if (obj == null)
{
Harmony val = new Harmony(Id);
Harmony val2 = val;
_harmony = val;
obj = val2;
}
return obj;
}
}
public PatchHost(string id, ModLog log)
{
if (string.IsNullOrEmpty(id))
{
throw new ArgumentException("Patch host id must not be empty.", "id");
}
Id = id;
_log = log;
}
public bool PatchAll(Assembly assembly)
{
if (assembly == null)
{
throw new ArgumentNullException("assembly");
}
try
{
Harmony.PatchAll(assembly);
_log?.Debug("Applied patches from " + assembly.GetName().Name + ".");
return true;
}
catch (Exception ex)
{
FailureCount++;
_log?.Exception("Failed to apply patches from " + assembly.GetName().Name, ex);
return false;
}
}
public bool PatchMethod(MethodBase target, MethodInfo prefix = null, MethodInfo postfix = null, MethodInfo transpiler = null, MethodInfo finalizer = null)
{
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
if (target == null)
{
FailureCount++;
_log?.Warning("Cannot patch a null method.");
return false;
}
try
{
_harmony.Patch(target, (prefix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(prefix), (postfix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(postfix), (transpiler == null) ? ((HarmonyMethod)null) : new HarmonyMethod(transpiler), (finalizer == null) ? ((HarmonyMethod)null) : new HarmonyMethod(finalizer), (HarmonyMethod)null);
_log?.Debug("Patched " + target.DeclaringType?.Name + "." + target.Name + ".");
return true;
}
catch (Exception ex)
{
FailureCount++;
_log?.Exception("Failed to patch " + target.DeclaringType?.Name + "." + target.Name, ex);
return false;
}
}
public bool PatchType(Type type)
{
if (type == null)
{
throw new ArgumentNullException("type");
}
try
{
Harmony.CreateClassProcessor(type).Patch();
_log?.Debug("Applied patches from " + type.Name + ".");
return true;
}
catch (Exception ex)
{
FailureCount++;
_log?.Exception("Failed to apply patches from " + type.Name, ex);
return false;
}
}
public void UnpatchAll()
{
if (_harmony == null)
{
return;
}
try
{
_harmony.UnpatchSelf();
_log?.Debug("Removed all patches.");
}
catch (Exception ex)
{
_log?.Exception("Failed to unpatch", ex);
}
}
public void Dispose()
{
UnpatchAll();
}
}
}
namespace SpongePEAK.Core.Logging
{
public sealed class ModLog
{
private readonly string _prefix;
private ManualLogSource _sink;
public bool IsAttached => _sink != null;
public ModLog(string prefix)
{
_prefix = (string.IsNullOrEmpty(prefix) ? "SpongePEAK" : prefix);
}
public void Attach(ManualLogSource sink)
{
_sink = sink;
}
public void Debug(object message)
{
Write((LogLevel)32, message);
}
public void Info(object message)
{
Write((LogLevel)16, message);
}
public void Message(object message)
{
Write((LogLevel)8, message);
}
public void Warning(object message)
{
Write((LogLevel)4, message);
}
public void Error(object message)
{
Write((LogLevel)2, message);
}
public void Fatal(object message)
{
Write((LogLevel)1, message);
}
public void Exception(string context, Exception ex)
{
Write((LogLevel)2, $"{context}: {ex}");
}
private void Write(LogLevel level, object message)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
ManualLogSource sink = _sink;
if (sink == null)
{
return;
}
try
{
sink.Log(level, (object)$"[{_prefix}] {message}");
}
catch
{
}
}
}
}
namespace SpongePEAK.Core.Game
{
public static class GameState
{
public static Character LocalCharacter => Character.localCharacter;
public static bool InRun => (Object)(object)Character.localCharacter != (Object)null;
public static List<Character> AllCharacters => Character.AllCharacters ?? new List<Character>();
public static List<Character> AllBots => Character.AllBotCharacters ?? new List<Character>();
public static int PlayerCount
{
get
{
List<Character> allCharacters = Character.AllCharacters;
if (allCharacters == null)
{
return 0;
}
int num = 0;
for (int i = 0; i < allCharacters.Count; i++)
{
Character val = allCharacters[i];
if ((Object)(object)val != (Object)null && !val.isBot)
{
num++;
}
}
return num;
}
}
public static List<Character> AllPlayers()
{
List<Character> list = new List<Character>();
List<Character> allCharacters = Character.AllCharacters;
if (allCharacters == null)
{
return list;
}
for (int i = 0; i < allCharacters.Count; i++)
{
Character val = allCharacters[i];
if ((Object)(object)val != (Object)null && !val.isBot)
{
list.Add(val);
}
}
return list;
}
}
}
namespace SpongePEAK.Core.Config
{
public sealed class FeatureToggle
{
private readonly ConfigEntry<bool> _entry;
public string Name { get; }
public bool Enabled => _entry?.Value ?? false;
public bool Applied { get; private set; }
public event Action<bool> Changed
{
add
{
if (_entry != null)
{
_entry.SettingChanged += delegate
{
value(_entry.Value);
};
}
}
remove
{
}
}
public void MarkApplied(bool applied)
{
Applied = applied;
}
public FeatureToggle(ConfigFile config, string section, string name, bool defaultValue, string description)
{
if (config == null)
{
throw new ArgumentNullException("config");
}
if (string.IsNullOrEmpty(name))
{
throw new ArgumentException("Feature name must not be empty.", "name");
}
Name = name;
_entry = config.Bind<bool>(section, name, defaultValue, description);
}
public override string ToString()
{
return Name + "=" + (Enabled ? "on" : "off");
}
}
}