Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of VargheimGate v0.2.0
VargheimGate.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] [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 VargheimGate { [BepInPlugin("digi.vargheim.gate", "VargheimGate", "0.2.0")] public class Plugin : BaseUnityPlugin { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static PopupButtonCallback <>9__34_0; public static PopupButtonCallback <>9__34_1; internal void <Update>b__34_0() { UnifiedPopup.Pop(); Accept(); } internal void <Update>b__34_1() { UnifiedPopup.Pop(); Decline("chose No"); } } public const string PluginGuid = "digi.vargheim.gate"; public const string PluginName = "VargheimGate"; public const string PluginVersion = "0.2.0"; private const string LogFile = "vargheim-gate-log.txt"; internal static Plugin Instance; private ConfigEntry<bool> _enabled; private ConfigEntry<string> _seasonId; private ConfigEntry<int> _skillCap; private ConfigEntry<int> _nemesisScore; private ConfigEntry<bool> _requireMod; private ConfigEntry<string> _exempt; private static readonly ConditionalWeakTable<ZRpc, object> s_hello = new ConditionalWeakTable<ZRpc, object>(); private static bool s_active; private static string s_season = string.Empty; private static int s_cap = 25; private static float s_nemesis = 5000f; private static ZRpc s_serverRpc; private static bool s_checked; private static bool s_pending; private static float s_pendingSince; private const float AnswerSeconds = 180f; private static readonly string[] s_clearFields = new string[6] { "m_knownRecipes", "m_knownStations", "m_knownMaterial", "m_trophies", "m_uniques", "m_knownBiome" }; private const string NemesisScoreKey = "SLS_NEM_SCORE"; private const string NemesisDataKey = "SLS_NEM_SCOREDATA"; private void Awake() { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Expected O, but got Unknown //IL_0105: Unknown result type (might be due to invalid IL or missing references) Instance = this; try { _enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Server", "Enabled", true, "Server only. Master switch for the season gate."); _seasonId = ((BaseUnityPlugin)this).Config.Bind<string>("Server", "SeasonId", "S2", "Server only. Short label for this season. A character is reset once per label; changing the label makes every character go through the gate again."); _skillCap = ((BaseUnityPlugin)this).Config.Bind<int>("Server", "SkillCap", 25, new ConfigDescription("Server only. Skills above this level are lowered to it when a character goes through the gate.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); _requireMod = ((BaseUnityPlugin)this).Config.Bind<bool>("Server", "RequireMod", true, "Server only. Turn away players who join without this mod (they see the game's 'incompatible version' message). When false, players without the mod can join and are NOT gated."); _nemesisScore = ((BaseUnityPlugin)this).Config.Bind<int>("Server", "NemesisScore", 5000, new ConfigDescription("Server only. The Star Level System Nemesis score every character is set back to when it goes through the gate (its fight history from earlier seasons is forgotten too). Use the NeutralScore from NemesisSettings.yaml.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100000), Array.Empty<object>())); _exempt = ((BaseUnityPlugin)this).Config.Bind<string>("Server", "ExemptIds", "", "Server only. Steam ids, separated by commas, that are never gated (for an admin test character)."); new Harmony("digi.vargheim.gate").PatchAll(typeof(Patches)); ((BaseUnityPlugin)this).Logger.LogInfo((object)"VargheimGate 0.2.0 loaded."); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("VargheimGate: startup failed, mod inactive: " + ex)); } } internal static void Note(string s) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)("VargheimGate: " + s)); } } internal static void Warn(string s) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)("VargheimGate: " + s)); } } internal static void OnNewConnection(ZNet znet, ZNetPeer peer) { if ((Object)(object)Instance == (Object)null || peer == null || peer.m_rpc == null) { return; } if (znet.IsServer()) { if (znet.IsDedicated()) { ZRpc rpc = peer.m_rpc; rpc.Register<string>("VG_Hello", (Action<ZRpc, string>)Instance.Server_Hello); rpc.Register<string, string>("VG_Report", (Action<ZRpc, string, string>)Instance.Server_Report); } } else { ClearClient(); s_serverRpc = peer.m_rpc; peer.m_rpc.Register<string, int, int>("VG_Settings", (Action<ZRpc, string, int, int>)Client_Settings); peer.m_rpc.Invoke("VG_Hello", new object[1] { "0.2.0" }); } } private static void ClearClient() { s_active = false; s_season = string.Empty; s_serverRpc = null; s_checked = false; s_pending = false; } internal static void OnZNetGone() { ClearClient(); } private static string HostOf(ZRpc rpc) { try { return rpc.GetSocket().GetHostName() ?? string.Empty; } catch { return string.Empty; } } private void Server_Hello(ZRpc rpc, string version) { if (!_enabled.Value) { return; } string text = HostOf(rpc); if (version != "0.2.0") { Warn("player " + text + " has gate version '" + Rules.LogSafe(version) + "', server has 0.2.0."); return; } if (!s_hello.TryGetValue(rpc, out var _)) { s_hello.Add(rpc, new object()); } if (Rules.Ids(_exempt.Value).Contains(text)) { Note("player " + text + " is exempt; not gated."); return; } rpc.Invoke("VG_Settings", new object[3] { Rules.CleanSeason(_seasonId.Value), _skillCap.Value, _nemesisScore.Value }); } internal static bool Server_AllowPeerNote(ZNet znet, ZRpc rpc) { if ((Object)(object)Instance == (Object)null || !znet.IsServer() || !znet.IsDedicated() || !Instance._enabled.Value || !Instance._requireMod.Value) { return true; } if (s_hello.TryGetValue(rpc, out var _)) { return true; } Warn("refused " + HostOf(rpc) + ": joined without VargheimGate 0.2.0."); rpc.Invoke("Error", new object[1] { 3 }); return false; } private void Server_Report(ZRpc rpc, string what, string details) { string text = HostOf(rpc); if (what == "forget") { ForgetProfessions(text, details); } string text2 = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture) + "|" + Rules.LogSafe(text) + "|" + Rules.LogSafe(what) + "|" + Rules.LogSafe(details); Note(text2); try { File.AppendAllText(Path.Combine(Paths.ConfigPath, "vargheim-gate-log.txt"), text2 + "\n"); } catch (Exception ex) { Warn("could not write vargheim-gate-log.txt: " + ex.Message); } } private static void ForgetProfessions(string host, string name) { try { Type type = AccessTools.TypeByName("VargheimProfessions.Plugin"); MethodInfo methodInfo = ((type != null) ? type.GetMethod("Forget", BindingFlags.Static | BindingFlags.Public) : null); if (methodInfo == null) { Note("professions: Vargheim Professions 0.5.15+ not found, " + Rules.LogSafe(name) + " keeps its record."); return; } object obj = methodInfo.Invoke(null, new object[2] { host, name }); Note("professions: " + Rules.LogSafe(name) + " (" + host + ") " + ((obj is bool && (bool)obj) ? "record cleared." : "had no record.")); } catch (Exception ex) { Warn("professions: could not clear " + Rules.LogSafe(name) + ": " + ex.Message); } } private static void Client_Settings(ZRpc rpc, string season, int cap, int nemesis) { if (rpc == s_serverRpc && !((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsServer()) { s_season = Rules.CleanSeason(season); s_cap = Mathf.Clamp(cap, 0, 100); s_nemesis = Mathf.Clamp(nemesis, 0, 100000); s_active = true; s_checked = false; Note("this server runs the season gate (season " + s_season + ", skill cap " + s_cap + ")."); } } internal static bool BlockInput() { return s_pending; } private void Update() { //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Expected O, but got Unknown //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Expected O, but got Unknown //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Expected O, but got Unknown if (!s_active || (Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer()) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } try { if (s_pending) { if (Time.unscaledTime - s_pendingSince > 180f) { Decline("no answer"); } } else { if (s_checked) { return; } s_checked = true; if (localPlayer.m_customData.TryGetValue("vargheim.gate", out var value) && value == s_season) { Report("returning", localPlayer.GetPlayerName()); return; } float num = 0f; foreach (Skill skill in ((Character)localPlayer).GetSkills().GetSkillList()) { num += skill.m_level; } int count = ((ICollection)Need(localPlayer, "m_knownStations")).Count; if (Rules.LooksNew(num, count)) { Apply(localPlayer, "new character"); return; } string[] array = s_clearFields; foreach (string field in array) { Need(localPlayer, field); } if (!UnifiedPopup.IsAvailable()) { throw new InvalidOperationException("the game's question window is not available"); } s_pending = true; s_pendingSince = Time.unscaledTime; string text = "This character has not entered Vargheim season " + s_season + " yet.\n\nIf you continue, it is changed for good, on this PC and in every world:\n- everything it carries and wears is removed\n- all recipes, build pieces and other unlocks are forgotten\n- skills above " + s_cap + " are lowered to " + s_cap + "\n- its professions and its Nemesis record on this server start over\n\nThis cannot be undone. To keep this character as it is, choose No and join with a new or copied character.\n\nEnter the season with this character?"; object obj = <>c.<>9__34_0; if (obj == null) { PopupButtonCallback val = delegate { UnifiedPopup.Pop(); Accept(); }; <>c.<>9__34_0 = val; obj = (object)val; } object obj2 = <>c.<>9__34_1; if (obj2 == null) { PopupButtonCallback val2 = delegate { UnifiedPopup.Pop(); Decline("chose No"); }; <>c.<>9__34_1 = val2; obj2 = (object)val2; } UnifiedPopup.Push((PopupBase)new YesNoPopup("Vargheim season gate", text, (PopupButtonCallback)obj, (PopupButtonCallback)obj2, false, false)); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("VargheimGate: gate check failed, nothing was changed, leaving the server: " + ex)); Decline("gate error: " + ex.GetType().Name); } } private static void Accept() { s_pending = false; Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || !s_active) { return; } try { Apply(localPlayer, "existing character"); } catch (Exception ex) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("VargheimGate: reset failed part way: " + ex)); } } } private static void Decline(string why) { s_pending = false; s_active = false; Report("declined", why); try { if (UnifiedPopup.IsVisible()) { UnifiedPopup.Pop(); } } catch { } if ((Object)(object)Game.instance != (Object)null) { Game.instance.Logout(true, true); } } private static void Report(string what, string details) { try { if (s_serverRpc != null && s_serverRpc.IsConnected()) { s_serverRpc.Invoke("VG_Report", new object[2] { what, details }); } } catch { } } private static object Need(Player p, string field) { FieldInfo fieldInfo = AccessTools.Field(typeof(Player), field); object obj = ((fieldInfo != null) ? fieldInfo.GetValue(p) : null); if (obj == null || (!(obj is ICollection) && !(obj.GetType().GetMethod("Clear", Type.EmptyTypes) != null)) || obj.GetType().GetMethod("Clear", Type.EmptyTypes) == null) { throw new MissingFieldException("Player." + field); } return obj; } private static void Apply(Player p, string kind) { List<object> list = new List<object>(); string[] array = s_clearFields; foreach (string field in array) { list.Add(Need(p, field)); } List<Skill> skillList = ((Character)p).GetSkills().GetSkillList(); int count = ((Humanoid)p).GetInventory().GetAllItems().Count; ((Humanoid)p).UnequipAllItems(); ((Humanoid)p).GetInventory().RemoveAll(); foreach (object item in list) { item.GetType().GetMethod("Clear", Type.EmptyTypes).Invoke(item, null); } p.SetGuardianPower(string.Empty); p.m_guardianPowerCooldown = 0f; p.ClearFood(); int num = 0; foreach (Skill item2 in skillList) { if (Rules.Cap(item2.m_level, s_cap, out var capped)) { item2.m_level = capped; item2.m_accumulator = 0f; num++; } } string text = ResetNemesis(p); ((Humanoid)p).GiveDefaultItems(); p.m_customData["vargheim.gate"] = s_season; ((Character)p).Message((MessageType)2, "You enter Vargheim season " + s_season + " with empty hands.", 0, (Sprite)null, false); Note("gate applied (" + kind + "): " + count + " item stacks removed, " + num + " skills lowered to " + s_cap + ", " + text + "."); Report("reset", p.GetPlayerName() + ", " + kind + ", " + count + " item stacks removed, " + num + " skills lowered to " + s_cap + ", " + text); Report("forget", p.GetPlayerName()); } private static string ResetNemesis(Player p) { try { bool flag = p.m_customData.Remove("SLS_NEM_SCOREDATA"); ZNetView component = ((Component)p).GetComponent<ZNetView>(); ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null); if (val != null) { val.Set("SLS_NEM_SCORE", s_nemesis); } Type type = AccessTools.TypeByName("StarLevelSystem.modules.NemesisSystem.NemesisSystem"); if (type != null) { FieldInfo fieldInfo = AccessTools.Field(type, "PlayerScore"); if (fieldInfo != null) { Type type2 = AccessTools.TypeByName("StarLevelSystem.common.DataObjects+ScoreData"); fieldInfo.SetValue(null, (type2 != null) ? Activator.CreateInstance(type2) : null); } FieldInfo fieldInfo2 = AccessTools.Field(type, "CachedPlayerScore"); if (fieldInfo2 != null && fieldInfo2.FieldType == typeof(float)) { fieldInfo2.SetValue(null, s_nemesis); } } return "nemesis score set to " + s_nemesis + (flag ? " (history cleared)" : ""); } catch (Exception ex) { Warn("nemesis reset: " + ex.Message); return "nemesis reset failed"; } } } [HarmonyPatch] internal static class Patches { [HarmonyPatch(typeof(ZNet), "OnNewConnection")] [HarmonyPostfix] private static void ZNet_OnNewConnection(ZNet __instance, ZNetPeer peer) { try { Plugin.OnNewConnection(__instance, peer); } catch (Exception ex) { Plugin.Warn("connection hook failed: " + ex.Message); } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] [HarmonyPrefix] [HarmonyPriority(800)] private static bool ZNet_RPC_PeerNote(ZNet __instance, ZRpc rpc) { try { return Plugin.Server_AllowPeerNote(__instance, rpc); } catch (Exception ex) { Plugin.Warn("join check failed, player let in: " + ex.Message); return true; } } [HarmonyPatch(typeof(ZNet), "OnDestroy")] [HarmonyPostfix] private static void ZNet_OnDestroy() { Plugin.OnZNetGone(); } [HarmonyPatch(typeof(Player), "TakeInput")] [HarmonyPostfix] private static void Player_TakeInput(ref bool __result) { if (Plugin.BlockInput()) { __result = false; } } [HarmonyPatch(typeof(InventoryGui), "Show")] [HarmonyPrefix] private static bool InventoryGui_Show() { return !Plugin.BlockInput(); } } public static class Rules { public const string MarkerKey = "vargheim.gate"; public static bool Cap(float level, float cap, out float capped) { if (cap < 0f) { cap = 0f; } if (level > cap) { capped = cap; return true; } capped = level; return false; } public static HashSet<string> Ids(string text) { HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); StringBuilder stringBuilder = new StringBuilder(); string text2 = (text ?? string.Empty) + ","; foreach (char c in text2) { if (char.IsLetterOrDigit(c) || c == '_') { stringBuilder.Append(c); } else if (stringBuilder.Length > 0) { hashSet.Add(stringBuilder.ToString()); stringBuilder.Length = 0; } } return hashSet; } public static string CleanSeason(string s) { StringBuilder stringBuilder = new StringBuilder(); string text = (s ?? string.Empty).Trim(); foreach (char c in text) { if ((char.IsLetterOrDigit(c) && c < '\u0080') || c == '-' || c == '_') { stringBuilder.Append(c); } } string text2 = stringBuilder.ToString(); if (text2.Length > 24) { text2 = text2.Substring(0, 24); } if (text2.Length != 0) { return text2; } return "S2"; } public static bool LooksNew(float totalSkillLevels, int knownStations) { if (totalSkillLevels < 1f) { return knownStations == 0; } return false; } public static string LogSafe(string s) { s = (s ?? string.Empty).Replace('\r', ' ').Replace('\n', ' ').Replace('|', '/'); if (s.Length > 120) { return s.Substring(0, 120); } return s; } } }