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 JarOfDirt ServerPlugin v1.1.1
plugins/JarOfDirt_ServerPlugin.dll
Decompiled 3 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("JarOfDirt_ServerPlugin")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("JarOfDirt_ServerPlugin")] [assembly: AssemblyTitle("JarOfDirt_ServerPlugin")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace JarOfDirtPlugin { [BepInPlugin("jarofdirt.ServerPlugin", "JarOfDirt Server Plugin", "1.1.1")] public class ServerPlugin : BaseUnityPlugin { public const string PluginGUID = "jarofdirt.ServerPlugin"; public const string PluginName = "JarOfDirt Server Plugin"; public const string PluginVersion = "1.1.1"; public const string ModpackHash = "4ef40130e9478ce0"; private static ManualLogSource _log; private static Harmony _harmony; private static readonly HashSet<string> BalrondClayPieces = new HashSet<string> { "clay_stair_bal", "ClayBeam_bal", "ClayCube_bal", "ClayPole_bal", "clayr_arch_bal", "ClayWall_bal", "clay_floor_2x2_bal" }; private static readonly HashSet<long> ValidatedPeers = new HashSet<long>(); private static readonly HashSet<long> ModpackVerifiedPeers = new HashSet<long>(); private static readonly HashSet<string> BlockedAdmins = new HashSet<string>(); private static readonly Dictionary<long, string> PeerSteamIds = new Dictionary<long, string>(); private static readonly HashSet<string> BlockedCommands = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "spawn", "give", "god", "ghost", "heal", "puke", "hair", "beard", "model", "raiseskill", "resetskill", "resetcharacter", "event", "stopevent", "randomevent", "exploremap", "resetmap", "goto", "pos", "tame", "hatch", "location", "genloc", "setpower", "resetenv", "wind", "resetwind", "freefly", "ffsmooth", "dpsdebug", "save" }; private void Awake() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Expected O, but got Unknown //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Expected O, but got Unknown _log = ((BaseUnityPlugin)this).Logger; _harmony = new Harmony("jarofdirt.ServerPlugin"); _harmony.Patch((MethodBase)AccessTools.Method(typeof(ZNet), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(ServerPlugin), "ZNetAwake_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _harmony.Patch((MethodBase)AccessTools.Method(typeof(ZNet), "RPC_PeerInfo", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(ServerPlugin), "RPC_PeerInfo_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo methodInfo = AccessTools.Method(typeof(Terminal), "InputText", (Type[])null, (Type[])null); if (methodInfo != null) { _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(ServerPlugin), "Terminal_InputText_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo methodInfo2 = AccessTools.Method(typeof(ZNet), "Disconnect", new Type[1] { typeof(ZNetPeer) }, (Type[])null); if (methodInfo2 != null) { _harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(ServerPlugin), "ZNet_Disconnect_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } _harmony.Patch((MethodBase)AccessTools.Method(typeof(ZNetScene), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(ServerPlugin), "ZNetScene_Awake_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _log.LogInfo((object)"JarOfDirt Server Plugin v1.1.1 loaded (modpack hash: 4ef40130e9478ce0)"); } private static void ZNetAwake_Postfix(ZNet __instance) { ValidatedPeers.Clear(); ModpackVerifiedPeers.Clear(); BlockedAdmins.Clear(); PeerSteamIds.Clear(); ZRoutedRpc.instance.Register<string>("JOD_Validate", (Action<long, string>)RPC_ServerOnValidate); bool flag = __instance.IsServer(); _log.LogInfo((object)$"ZNet initialized (server={flag})"); if (!flag) { ((MonoBehaviour)__instance).StartCoroutine(ClientSendValidation()); } } private static IEnumerator ClientSendValidation() { for (float waited = 0f; waited < 30f; waited += 1f) { if ((Object)(object)ZNet.instance == (Object)null) { yield break; } ZNetPeer serverPeer = ZNet.instance.GetServerPeer(); if (serverPeer != null && serverPeer.IsReady()) { break; } yield return (object)new WaitForSeconds(1f); } yield return (object)new WaitForSeconds(3f); if ((Object)(object)ZNet.instance != (Object)null && ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC("JOD_Validate", new object[1] { "4ef40130e9478ce0" }); _log.LogInfo((object)"Sent JOD_Validate to server (hash: 4ef40130e9478ce0)"); } } private static void RPC_ServerOnValidate(long sender, string clientHash) { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } ValidatedPeers.Add(sender); bool flag = string.Equals(clientHash, "4ef40130e9478ce0", StringComparison.OrdinalIgnoreCase); if (flag) { ModpackVerifiedPeers.Add(sender); _log.LogInfo((object)$"Peer {sender} validated - plugin present, modpack hash MATCHES"); } else { _log.LogWarning((object)string.Format("Peer {0} validated - plugin present, but modpack hash MISMATCH (client: {1}, server: {2})", sender, clientHash, "4ef40130e9478ce0")); try { ZRoutedRpc.instance.InvokeRoutedRPC(sender, "ShowMessage", new object[2] { 2, "Your modpack is outdated! Please update JarOfDirt_Valheim in your mod manager." }); } catch { } if (PeerSteamIds.TryGetValue(sender, out var value)) { BlockedAdmins.Add(value); _log.LogWarning((object)("Admin blocked for " + value + " due to modpack mismatch")); } } if (flag && PeerSteamIds.TryGetValue(sender, out var value2) && BlockedAdmins.Remove(value2)) { _log.LogInfo((object)("Late validation from " + value2 + " - restoring admin access")); } } private static void RPC_PeerInfo_Postfix(ZRpc rpc, ZNet __instance) { if (!__instance.IsServer()) { return; } ZNetPeer val = null; foreach (ZNetPeer peer in __instance.GetPeers()) { if (peer.m_rpc == rpc) { val = peer; break; } } if (val == null) { return; } string hostName = val.m_socket.GetHostName(); long uid = val.m_uid; PeerSteamIds[uid] = hostName; _log.LogInfo((object)$"Peer connected: UID={uid}, SteamID={hostName}"); try { object value = Traverse.Create((object)__instance).Field("m_adminList").GetValue(); if (value != null) { MethodInfo method = value.GetType().GetMethod("Contains", BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(string) }, null); if (method != null && (bool)method.Invoke(value, new object[1] { hostName })) { _log.LogInfo((object)$"Peer {uid} ({hostName}) is admin - starting validation timer"); ((MonoBehaviour)__instance).StartCoroutine(ValidateAdminPeer(uid, hostName)); } } } catch (Exception ex) { _log.LogError((object)("Error checking admin list: " + ex.Message)); } } private static IEnumerator ValidateAdminPeer(long uid, string steamId) { yield return (object)new WaitForSeconds(20f); if (!ValidatedPeers.Contains(uid)) { _log.LogWarning((object)$"Admin peer {uid} ({steamId}) has NO JarOfDirt plugin - blocking admin"); BlockedAdmins.Add(steamId); try { ZRoutedRpc.instance.InvokeRoutedRPC(uid, "ShowMessage", new object[2] { 2, "Admin access requires JarOfDirt modpack. Install the modpack to receive admin." }); yield break; } catch { yield break; } } if (!ModpackVerifiedPeers.Contains(uid)) { _log.LogWarning((object)$"Admin peer {uid} ({steamId}) has outdated modpack - admin blocked"); } else { _log.LogInfo((object)$"Admin peer {uid} ({steamId}) fully validated - plugin present, modpack current"); } } private static void ZNet_Disconnect_Prefix(ZNetPeer peer) { if (peer != null) { long uid = peer.m_uid; ValidatedPeers.Remove(uid); ModpackVerifiedPeers.Remove(uid); if (PeerSteamIds.TryGetValue(uid, out var value)) { BlockedAdmins.Remove(value); PeerSteamIds.Remove(uid); } } } private static bool Terminal_InputText_Prefix(Terminal __instance) { if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { return true; } try { object value = Traverse.Create((object)__instance).Field("m_input").GetValue(); if (value == null) { return true; } PropertyInfo property = value.GetType().GetProperty("text"); if (property == null) { return true; } string text = (string)property.GetValue(value); if (string.IsNullOrEmpty(text)) { return true; } string text2 = text.Trim(); if (text2.StartsWith("/")) { text2 = text2.Substring(1); } text2 = text2.Split(new char[1] { ' ' })[0].ToLower(); if (BlockedCommands.Contains(text2)) { __instance.AddString("<color=orange>[JarOfDirt]</color> <color=red>Command '" + text2 + "' is restricted by server policy.</color>"); PropertyInfo property2 = value.GetType().GetProperty("text"); if (property2 != null) { property2.SetValue(value, ""); } return false; } } catch (Exception ex) { _log.LogError((object)("Error in command filter: " + ex.Message)); } return true; } private static void ZNetScene_Awake_Postfix(ZNetScene __instance) { if (!((Object)(object)__instance == (Object)null)) { ((MonoBehaviour)__instance).StartCoroutine(DelayedRemoveBalrondClay(__instance)); } } private static IEnumerator DelayedRemoveBalrondClay(ZNetScene scene) { yield return null; yield return null; yield return null; if ((Object)(object)scene == (Object)null) { yield break; } int num = 0; int num2 = scene.m_prefabs.RemoveAll((GameObject prefab) => (Object)(object)prefab != (Object)null && BalrondClayPieces.Contains(((Object)prefab).name)); try { Dictionary<int, GameObject> value = Traverse.Create((object)scene).Field("m_namedPrefabs").GetValue<Dictionary<int, GameObject>>(); if (value != null) { List<int> list = new List<int>(); foreach (KeyValuePair<int, GameObject> item in value) { if ((Object)(object)item.Value != (Object)null && BalrondClayPieces.Contains(((Object)item.Value).name)) { list.Add(item.Key); } } foreach (int item2 in list) { value.Remove(item2); } } } catch { } foreach (GameObject prefab in scene.m_prefabs) { if ((Object)(object)prefab == (Object)null) { continue; } ItemDrop component = prefab.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null) { continue; } PieceTable val = component.m_itemData?.m_shared?.m_buildPieces; if (!((Object)(object)val == (Object)null)) { int num3 = val.m_pieces.RemoveAll((GameObject piece) => (Object)(object)piece != (Object)null && BalrondClayPieces.Contains(((Object)piece).name)); num += num3; } } if (num2 > 0 || num > 0) { _log.LogInfo((object)$"Removed Balrond clay pieces: {num2} from ZNetScene, {num} from PieceTables"); } else { _log.LogInfo((object)"Balrond clay piece removal: none found (already removed or not loaded)"); } } } }