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 SeedSeer v1.0.0
SeedSeer.dll
Decompiled 4 days agousing 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; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Splatform; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Jubaroo")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © 2026 Jubaroo")] [assembly: AssemblyDescription("Logs the world seed on server startup so you always know what seed your dedicated server is running — by Jubaroo")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("SeedSeer")] [assembly: AssemblyTitle("SeedSeer")] [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.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] [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] [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 SeedSeer { [BepInPlugin("com.jubaroo.seedseer", "SeedSeer", "1.0.0")] public class Plugin : BaseUnityPlugin { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__10_0; internal void <Awake>b__10_0(ConsoleEventArgs args) { Console instance = Console.instance; if (instance != null) { ((Terminal)instance).AddString(SeedText); } if ((Object)(object)MessageHud.instance != (Object)null) { MessageHud.instance.ShowMessage((MessageType)1, SeedText, 0, (Sprite)null, false, true); } } } public const string PluginGuid = "com.jubaroo.seedseer"; public const string PluginName = "SeedSeer"; public const string PluginVersion = "1.0.0"; public static ManualLogSource Log = null; public static string WorldSeedName = ""; public static int WorldSeedHash; public static ConfigEntry<bool> ShowOnSpawn = null; public static ConfigEntry<bool> AdminOnlyCommand = null; public static string SeedText { get { if (!string.IsNullOrEmpty(WorldSeedName)) { return $"World seed: \"{WorldSeedName}\" (hash: {WorldSeedHash})"; } return "World seed: unknown (world not loaded yet)"; } } private void Awake() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0078: 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) //IL_0083: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; ShowOnSpawn = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowOnSpawn", true, "Client-side: show the world seed as an in-game message the first time your character spawns into a world."); AdminOnlyCommand = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AdminOnlyCommand", false, "Server-side: when true, only players listed in adminlist.txt receive a reply to the /seed chat command. When false, any player can request the seed."); new Harmony("com.jubaroo.seedseer").PatchAll(); object obj = <>c.<>9__10_0; if (obj == null) { ConsoleEvent val = delegate { Console instance = Console.instance; if (instance != null) { ((Terminal)instance).AddString(SeedText); } if ((Object)(object)MessageHud.instance != (Object)null) { MessageHud.instance.ShowMessage((MessageType)1, SeedText, 0, (Sprite)null, false, true); } }; <>c.<>9__10_0 = val; obj = (object)val; } new ConsoleCommand("seed", "Shows the current world seed (SeedSeer)", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); string[] commandLineArgs = Environment.GetCommandLineArgs(); for (int num = 0; num < commandLineArgs.Length - 1; num++) { if (commandLineArgs[num].Equals("-seed", StringComparison.OrdinalIgnoreCase)) { Log.LogInfo((object)("Launch argument -seed detected: " + commandLineArgs[num + 1])); } } } } [HarmonyPatch(typeof(WorldGenerator), "Initialize")] public static class WorldGeneratorInitializePatch { private static void Postfix(World world) { Plugin.WorldSeedName = world.m_seedName; Plugin.WorldSeedHash = world.m_seed; SeedSpawnMessagePatch.ShownForCurrentWorld = false; string text = "[SeedSeer] " + Plugin.SeedText; ZLog.Log((object)text); Plugin.Log.LogInfo((object)text); } } [HarmonyPatch(typeof(Player), "OnSpawned")] public static class SeedSpawnMessagePatch { public static bool ShownForCurrentWorld; private static void Postfix() { if (!ShownForCurrentWorld && Plugin.ShowOnSpawn.Value && !((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsServer() && !((Object)(object)MessageHud.instance == (Object)null) && !string.IsNullOrEmpty(Plugin.WorldSeedName)) { ShownForCurrentWorld = true; MessageHud.instance.ShowMessage((MessageType)1, "[SeedSeer] " + Plugin.SeedText, 0, (Sprite)null, false, true); } } } [HarmonyPatch(typeof(ZRoutedRpc), "RouteRPC")] public static class SeedChatCommandPatch { private static readonly int SayHash = StringExtensionMethods.GetStableHashCode("Say"); private static readonly int ChatMessageHash = StringExtensionMethods.GetStableHashCode("ChatMessage"); private static readonly Dictionary<long, (string Text, float Time)> _recentCommands = new Dictionary<long, (string, float)>(); private static void Postfix(RoutedRPCData rpcData) { //IL_00e6: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || (rpcData.m_methodHash != SayHash && rpcData.m_methodHash != ChatMessageHash)) { return; } Vector3 pos; string text; try { ExtractMessage(rpcData, out text, out pos); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Failed to read chat payload: " + ex.Message)); return; } text = text?.Trim() ?? ""; if (text.Equals("/seed", StringComparison.OrdinalIgnoreCase) || text.Equals("!seed", StringComparison.OrdinalIgnoreCase)) { long senderPeerID = rpcData.m_senderPeerID; float realtimeSinceStartup = Time.realtimeSinceStartup; if (!_recentCommands.TryGetValue(senderPeerID, out (string, float) value) || !(value.Item1 == text) || !(realtimeSinceStartup - value.Item2 < 1f)) { _recentCommands[senderPeerID] = (text, realtimeSinceStartup); ReplyWithSeed(senderPeerID, pos); } } } private static void ExtractMessage(RoutedRPCData rpcData, out string text, out Vector3 pos) { //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_001d: 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_008c: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) ZPackage parameters = rpcData.m_parameters; parameters.SetPos(0); if (rpcData.m_methodHash == ChatMessageHash) { pos = parameters.ReadVector3(); parameters.ReadInt(); } else { parameters.ReadInt(); pos = Vector3.zero; if (!((ZDOID)(ref rpcData.m_targetZDO)).IsNone()) { ZDO zDO = ZDOMan.instance.GetZDO(rpcData.m_targetZDO); ZNetView val = ((zDO != null) ? ZNetScene.instance.FindInstance(zDO) : null); if ((Object)(object)val != (Object)null) { pos = ((Component)val).transform.position; } } } new UserInfo().Deserialize(ref parameters); text = parameters.ReadString(); } private static void ReplyWithSeed(long senderPeerId, Vector3 pos) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) ZNet instance = ZNet.instance; ZNetPeer peer = instance.GetPeer(senderPeerId); if (peer != null) { string hostName = peer.m_socket.GetHostName(); PlatformUserID val = default(PlatformUserID); ((PlatformUserID)(ref val))..ctor(hostName); if (!Plugin.AdminOnlyCommand.Value || instance.PlayerIsAdmin(val) || instance.IsAdmin(hostName)) { string text = "[SeedSeer] " + Plugin.SeedText; ZRoutedRpc.instance.InvokeRoutedRPC(senderPeerId, "ChatMessage", new object[4] { pos, 0, (object)new UserInfo { Name = "SeedSeer", UserId = val }, text }); ZLog.Log((object)$"[SeedSeer] Sent world seed to peer {senderPeerId} ({peer.m_playerName})"); } } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }