Decompiled source of 9KCheatMode v1.0.0

_9KCheatMode.dll

Decompiled 2 months ago
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.Json;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using CheatSystem;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using MainMenuUI;
using Microsoft.CodeAnalysis;
using UnityEngine;
using Utils.Injection;
using Utils.Logger;
using Utils.Settings;
using _9KCheatMode.Behaviors;
using _9KCheatMode.Settings;
using _9KCheatMode.Systems;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("_9KCheatMode")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("9KCheatMode is a mod designed for the game 9 Kings, providing advanced configuration options and cheat functionalities to enhance and test gameplay. The mod includes features such as automatic castle shooting, UI toggling, invincibility mode, infinite lives, perks activation, and more. It also supports dynamic settings reload and customization through keybinds.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+fb885c1a4031a6e3f2c88dca742bea19852369af")]
[assembly: AssemblyProduct("_9KCheatMode")]
[assembly: AssemblyTitle("_9KCheatMode")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Utils.Settings
{
	public class Config
	{
		public static string PluginGUID;

		public static string PluginFolderPath;

		internal static ConfigFile cfg;

		private static readonly List<Action> configActions = new List<Action>();

		public static ConfigElement<T> Bind<T>(string section, string key, T defaultValue, string description)
		{
			return new ConfigElement<T>(cfg.Bind<T>(section, key, defaultValue, description), section, key, defaultValue, description);
		}

		public static void Save()
		{
			cfg.Save();
		}

		public static void Reload()
		{
			cfg.Reload();
		}

		public static void Setup(string pluginGUID, ConfigFile config, int skipCaller = 4, params Action[] actions)
		{
			PluginGUID = pluginGUID;
			cfg = config;
			PluginFolderPath = Paths.ConfigPath + "\\" + PluginGUID;
			if (!Directory.Exists(PluginFolderPath))
			{
				Directory.CreateDirectory(PluginFolderPath);
			}
			ENV.Debug.Setup(skipCaller);
			AddConfigActions(actions);
		}

		public static void Load()
		{
			if (configActions == null || configActions.Count == 0)
			{
				return;
			}
			foreach (Action configAction in configActions)
			{
				configAction();
			}
		}

		public static void AddConfigActions(params Action[] actions)
		{
			configActions.AddRange(actions);
		}
	}
	public class ConfigElement<T>
	{
		public List<Action<T>> OnValueChanged;

		public readonly ConfigEntry<T> OriginalConfig;

		public string Section { get; }

		public string Key { get; }

		public string Description { get; }

		public Type ElementType => typeof(T);

		public T DefaultValue { get; }

		public T Value
		{
			get
			{
				return GetValue();
			}
			set
			{
				SetValue(value);
			}
		}

		public ConfigElement(ConfigEntry<T> original, string section, string key, T defaultValue, string description)
		{
			Section = section;
			Key = key;
			Description = description;
			OnValueChanged = new List<Action<T>>();
			OriginalConfig = original;
			DefaultValue = defaultValue;
			base..ctor();
		}

		public T ValueFromConfig()
		{
			Config.Reload();
			return Value;
		}

		private T GetValue()
		{
			return OriginalConfig.Value;
		}

		private void SetValue(T value)
		{
			if ((Value == null && value == null) || (Value != null && Value.Equals(value)))
			{
				return;
			}
			OriginalConfig.Value = value;
			foreach (Action<T> item in OnValueChanged)
			{
				item?.Invoke(value);
			}
		}
	}
	public static class ENV
	{
		public class Debug
		{
			private static string debugSection = "\ud83e\udeb2Debug";

			private static ConfigElement<bool> DebugLogOnTempFile;

			private static ConfigElement<bool> DebugEnableTraceLogs;

			public static void Setup(int skipCaller)
			{
				Config.AddConfigActions(delegate
				{
					load(skipCaller);
				});
			}

			private static void load(int skipCaller)
			{
				if (enableDebugConfigs(skipCaller))
				{
					DebugLogOnTempFile = Config.Bind(debugSection, "LogOnTempFile", defaultValue: false, "Enabled, will log every plugin log on a temp file");
					DebugEnableTraceLogs = Config.Bind(debugSection, "EnableTraceLogs", defaultValue: false, "Enabled, will print Trace logs (Debug output in BepInEx)");
				}
				validateValues();
			}

			private static void validateValues()
			{
				if (DebugLogOnTempFile != null)
				{
					LogOnTempFile = DebugLogOnTempFile.Value;
				}
				if (DebugEnableTraceLogs != null)
				{
					EnableTraceLogs = DebugEnableTraceLogs.Value;
				}
				Config.cfg.Save();
			}

			private static bool enableDebugConfigs(int skipCaller)
			{
				return new StackTrace().GetFrame(skipCaller).GetMethod().DeclaringType.Assembly.GetCustomAttribute<AssemblyConfigurationAttribute>()?.Configuration != "Release";
			}
		}

		public static bool LogOnTempFile;

		public static bool EnableTraceLogs;
	}
}
namespace Utils.Logger
{
	public class Config
	{
		internal static ManualLogSource logger;

		private static string tempLogFile;

		public static void Setup(ManualLogSource logger, string worldType = "")
		{
			Config.logger = logger;
			string value = "";
			if (worldType != "")
			{
				value = "-" + worldType;
			}
			tempLogFile = $"{Utils.Settings.Config.PluginFolderPath}\\{Utils.Settings.Config.PluginGUID}{value}.txt";
			Log.Start("Using \"" + tempLogFile + "\" to save logs.");
		}

		public static void TestSetup()
		{
		}

		internal static void logFile(object data, string level, string prefix = "")
		{
			if (Utils.Settings.ENV.LogOnTempFile)
			{
				using (StreamWriter streamWriter = File.AppendText(tempLogFile))
				{
					string value = $"{prefix}{DateTime.Now.ToString("hh:mm:ss")} [{level} {Utils.Settings.Config.PluginGUID}]: {data}";
					streamWriter.WriteLine(value);
				}
			}
		}
	}
	public class Log
	{
		private static ConcurrentDictionary<string, long> timedLog = new ConcurrentDictionary<string, long>();

		private static List<string> firstLog = new List<string>();

		public static void Info(object data)
		{
			Config.logger.LogInfo(data);
			Config.logFile(data, "Info:   ");
		}

		public static void Error(object data)
		{
			Config.logger.LogError(data);
			Config.logFile(data, "Error:  ");
		}

		public static void Debug(object data)
		{
			Config.logger.LogDebug(data);
			Config.logFile(data, "Debug:  ");
		}

		public static void Fatal(object data)
		{
			Config.logger.LogFatal(data);
			Config.logFile(data, "Fatal:  ");
		}

		public static void Warning(object data)
		{
			Config.logger.LogWarning(data);
			Config.logFile(data, "Warning:");
		}

		public static void Message(object data)
		{
			Config.logger.LogMessage(data);
			Config.logFile(data, "Message:");
		}

		public static void Start(object data)
		{
			Config.logger.LogMessage(data);
			Config.logFile(data, "Start:  ", "\n");
		}

		public static void Trace(object data)
		{
			if (Utils.Settings.ENV.EnableTraceLogs)
			{
				Config.logger.LogDebug(data);
				Config.logFile(data, "Trace:  ");
			}
		}

		public static void Struct<T>(T data)
		{
			if (Utils.Settings.ENV.EnableTraceLogs)
			{
				string text = structToString(data);
				Config.logger.LogDebug((object)text);
				Config.logFile(text, "Struct: ");
			}
		}

		public static void Timed(Action action, int ms, string id = "")
		{
			if (!blocked(ms, id))
			{
				action();
			}
		}

		public static void First(Action action, string id = "")
		{
			if (first(id))
			{
				action();
			}
		}

		private static string structToString<T>(T data)
		{
			Type type = data.GetType();
			FieldInfo[] fields = type.GetFields();
			PropertyInfo[] properties = type.GetProperties();
			Dictionary<string, object> values = new Dictionary<string, object>();
			Array.ForEach(properties, delegate(PropertyInfo property)
			{
				values.TryAdd(property.Name, property.GetValue(data));
			});
			Array.ForEach(fields, delegate(FieldInfo field)
			{
				values.TryAdd(field.Name, field.GetValue(data));
			});
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, object> item in values)
			{
				list.Add($"\"{item.Key}\":\"{item.Value}\"");
			}
			return "\"" + type.ToString() + "\": {" + string.Join(",", list) + "}";
		}

		private static bool first(string id)
		{
			if (firstLog.Contains(id))
			{
				return false;
			}
			firstLog.Add(id);
			return true;
		}

		private static bool blocked(int ms, string id)
		{
			long num = DateTimeOffset.Now.ToUnixTimeMilliseconds();
			if (!timedLog.TryGetValue(id, out var value))
			{
				long newTimestamp = DateTimeOffset.Now.AddMilliseconds(ms).ToUnixTimeMilliseconds();
				timedLog.AddOrUpdate(id, newTimestamp, (string key, long oldValue) => newTimestamp);
				return true;
			}
			if (num < value)
			{
				return true;
			}
			timedLog.TryRemove(id, out var _);
			return false;
		}
	}
}
namespace Utils.Injection
{
	public static class IL2CPP
	{
		public static void Unregister<T>() where T : class
		{
			try
			{
				if (!ClassInjector.IsTypeRegisteredInIl2Cpp<T>())
				{
					return;
				}
				(typeof(ClassInjector).GetField("InjectedTypes", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null) as HashSet<string>)?.Remove(typeof(T).FullName);
				object value = typeof(ClassInjector).Assembly.GetType("Il2CppInterop.Runtime.Injection.InjectorHelpers").GetField("s_ClassNameLookup", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);
				Dictionary<(string _namespace, string _class, IntPtr imagePtr), IntPtr> s_ClassNameLookup = value as Dictionary<(string, string, IntPtr), IntPtr>;
				if (s_ClassNameLookup != null)
				{
					Type typeFromHandle = typeof(T);
					string className = typeFromHandle.Name;
					string namespaceName = typeFromHandle.Namespace ?? string.Empty;
					s_ClassNameLookup.Keys.Where(((string _namespace, string _class, IntPtr imagePtr) key) => key._class == className && key._namespace == namespaceName).ToList().ForEach(delegate((string _namespace, string _class, IntPtr imagePtr) key)
					{
						s_ClassNameLookup.Remove(key);
					});
				}
			}
			catch (Exception ex)
			{
				Log.Warning("Failed to unregister behavior " + typeof(T).FullName + ": " + ex.Message);
			}
		}
	}
}
namespace Utils.Database
{
	public static class Cache
	{
		public static ConcurrentDictionary<string, long> LastUpdate = new ConcurrentDictionary<string, long>();

		public static ConcurrentDictionary<string, bool> Cached = new ConcurrentDictionary<string, bool>();

		public static bool IsBlocked(string key, long blockedDuration)
		{
			long now = DateTimeOffset.Now.ToUnixTimeMilliseconds();
			if (LastUpdate.TryGetValue(key, out var value) && now - value < blockedDuration)
			{
				return true;
			}
			LastUpdate.AddOrUpdate(key, now, (string _, long _) => now);
			return false;
		}

		public static bool Key(string key, bool cache = true)
		{
			if (!cache)
			{
				return false;
			}
			return Cached.AddOrUpdate(key, addValue: true, (string _, bool _) => true);
		}

		public static bool Exists(string key)
		{
			if (Cached.TryGetValue(key, out var value) && value)
			{
				return true;
			}
			return false;
		}

		public static bool RemoveKey(string key)
		{
			bool value;
			return Cached.TryRemove(key, out value);
		}

		public static void Clear()
		{
			Cached.Clear();
			LastUpdate.Clear();
		}
	}
	public static class DB
	{
		private static JsonSerializerOptions JSONOptions = new JsonSerializerOptions
		{
			WriteIndented = false,
			IncludeFields = false
		};

		private static JsonSerializerOptions Pretty_JSON_options = new JsonSerializerOptions
		{
			WriteIndented = true,
			IncludeFields = true
		};

		private static List<Action> loadActions = new List<Action>();

		private static List<Action> saveActions = new List<Action>();

		private static List<Action> cleanActions = new List<Action>();

		public static void Setup(List<Action> load, List<Action> save, List<Action> clean)
		{
			if (load != null)
			{
				loadActions.AddRange(load);
			}
			if (save != null)
			{
				saveActions.AddRange(save);
			}
			if (clean != null)
			{
				cleanActions.AddRange(clean);
			}
		}

		public static void Load()
		{
			if (loadActions == null)
			{
				return;
			}
			foreach (Action loadAction in loadActions)
			{
				loadAction();
			}
			Log.Info($"All({loadActions.Count}) database actions loaded.");
		}

		public static void Save()
		{
			if (saveActions == null)
			{
				return;
			}
			foreach (Action saveAction in saveActions)
			{
				saveAction();
			}
			Log.Info($"All({saveActions.Count}) database actions saved.");
		}

		public static void Clean()
		{
			if (cleanActions == null)
			{
				return;
			}
			foreach (Action cleanAction in cleanActions)
			{
				cleanAction();
			}
			Log.Info($"All({cleanActions.Count}) database actions cleaned.");
		}

		public static void AddLoadActions(params Action[] actions)
		{
			loadActions.AddRange(actions);
		}

		public static void AddSaveActions(params Action[] actions)
		{
			saveActions.AddRange(actions);
		}

		public static void AddCleanActions(params Action[] actions)
		{
			cleanActions.AddRange(actions);
		}

		public static void saveFile<T>(string fileName, T data, bool pretty = false, string extension = ".json")
		{
			JsonSerializerOptions options = JSONOptions;
			if (pretty)
			{
				options = Pretty_JSON_options;
			}
			File.WriteAllText(Utils.Settings.Config.PluginFolderPath + "\\" + fileName + extension, JsonSerializer.Serialize(data, options));
		}

		public static void loadFile<T>(string fileName, ref T data, string extension = ".json") where T : new()
		{
			string path = Utils.Settings.Config.PluginFolderPath + "\\" + fileName + extension;
			if (!File.Exists(path))
			{
				File.Create(path).Dispose();
			}
			string json = File.ReadAllText(path);
			try
			{
				data = JsonSerializer.Deserialize<T>(json);
				Log.Trace(fileName + " DB Populated");
			}
			catch
			{
				data = new T();
				Log.Trace(fileName + " DB Created");
			}
		}
	}
}
namespace _9KCheatMode
{
	[BepInPlugin("_9KCheatMode", "_9KCheatMode", "1.0.0")]
	public class Plugin : BasePlugin
	{
		public static readonly Harmony Harmony = new Harmony("_9KCheatMode");

		private static KeyBinds keyBindsBehaviour;

		public override void Load()
		{
			_9KCheatMode.Settings.Config.Load(((BasePlugin)this).Config, ((BasePlugin)this).Log, "Client");
			IL2CPP.Unregister<KeyBinds>();
			keyBindsBehaviour = ((BasePlugin)this).AddComponent<KeyBinds>();
			Log.Trace("Patching harmony");
			Harmony.PatchAll();
			Log.Info("Plugin _9KCheatMode v1.0.0 loaded!");
		}

		public override bool Unload()
		{
			CheatSystem.Disable();
			Log.Trace("Unpatching harmony");
			Harmony.UnpatchSelf();
			Object.Destroy((Object)(object)keyBindsBehaviour);
			IL2CPP.Unregister<KeyBinds>();
			Log.Info("Plugin _9KCheatMode v1.0.0 unloaded!");
			return true;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "_9KCheatMode";

		public const string PLUGIN_NAME = "_9KCheatMode";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace _9KCheatMode.Systems
{
	public class CheatSystem
	{
		public static void Enable()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			try
			{
				CheatsManager.EnableGodlike(_9KCheatMode.Settings.ENV.EnableGodLike.Value);
				CheatsManager.Apply(new EnabledCheats
				{
					GodLike = _9KCheatMode.Settings.ENV.EnableGodLike.Value,
					InfinityLifes = _9KCheatMode.Settings.ENV.EnableInfinityLifes.Value,
					OIIAIOIIIAI = _9KCheatMode.Settings.ENV.EnableOIIAIOIIIAI.Value,
					PerksEnabled = _9KCheatMode.Settings.ENV.EnablePerks.Value,
					CastleAutoshoot = _9KCheatMode.Settings.ENV.EnableCastleAutoShoot.Value,
					DisableUI = _9KCheatMode.Settings.ENV.EnableDisableUI.Value
				});
				Log.Info("Cheats enabled");
			}
			catch
			{
			}
		}

		public static void Disable()
		{
			CheatsManager.EnableGodlike(false);
			CheatsManager.Apply(EnabledCheats.Default);
			Log.Info("Cheats disabled");
		}
	}
}
namespace _9KCheatMode.Settings
{
	public class Config
	{
		public static void Load(ConfigFile configFile, ManualLogSource logger, string worldType)
		{
			ENV.Settings.Setup();
			Utils.Settings.Config.Setup("_9KCheatMode", configFile, 4);
			Utils.Settings.Config.Load();
			Utils.Logger.Config.Setup(logger, worldType);
		}
	}
	public static class ENV
	{
		public static class Settings
		{
			public static void Setup()
			{
				Utils.Settings.Config.AddConfigActions(Load);
			}

			public static void Reload()
			{
				Utils.Settings.Config.Reload();
				Log.Info("Settings reloaded!");
			}

			private static void Load()
			{
				Utils.Settings.Config.Save();
			}
		}

		private static readonly string general = "\ud83d\udd79\ufe0f General";

		private static readonly string settings = "⚙\ufe0f Settings";

		public static readonly ConfigElement<bool> EnableCastleAutoShoot = Utils.Settings.Config.Bind(general, "EnableCastleAutoShoot", defaultValue: true, "Enable Castle Auto Shoot");

		public static readonly ConfigElement<bool> EnableDisableUI = Utils.Settings.Config.Bind(general, "EnableDisableUI", defaultValue: true, "Enable Disable UI");

		public static readonly ConfigElement<bool> EnableGodLike = Utils.Settings.Config.Bind(general, "EnableGodLike", defaultValue: true, "Enable God Like");

		public static readonly ConfigElement<bool> EnableInfinityLifes = Utils.Settings.Config.Bind(general, "EnableInfinityLifes", defaultValue: true, "Enable Infinity Lifes");

		public static readonly ConfigElement<bool> EnableOIIAIOIIIAI = Utils.Settings.Config.Bind(general, "EnableOIIAIOIIIAI", defaultValue: true, "Enable OIIAIOIIIAI");

		public static readonly ConfigElement<bool> EnablePerks = Utils.Settings.Config.Bind(general, "EnablePerks", defaultValue: true, "Enable Perks");

		public static readonly ConfigElement<KeyCode> ReloadSettings = Utils.Settings.Config.Bind<KeyCode>(settings, "ReloadSettings", (KeyCode)286, "Reload Settings KeyBind");
	}
}
namespace _9KCheatMode.Hooks
{
	[Harmony]
	public class CheatsManagerPatch
	{
		[HarmonyPatch(typeof(MainMenuUI), "OnEnable")]
		public class EnableGodlikePatch
		{
			public static void Postfix()
			{
				CheatSystem.Enable();
			}
		}
	}
}
namespace _9KCheatMode.Behaviors
{
	public class KeyBinds : MonoBehaviour
	{
		public KeyBinds(IntPtr handle)
			: base(handle)
		{
		}

		public void Update()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown(_9KCheatMode.Settings.ENV.ReloadSettings.Value))
			{
				CheatSystem.Disable();
				_9KCheatMode.Settings.ENV.Settings.Reload();
				CheatSystem.Enable();
			}
		}
	}
}