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 HostOwner v0.1.0
HostOwner.dll
Decompiled 3 days agousing System; using System.Collections.Generic; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using BepInEx; using BepInEx.Configuration; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace HostOwner; public static class HostOwnerApi { internal static readonly HashSet<string> Prefabs = new HashSet<string>(StringComparer.Ordinal); internal static readonly HashSet<string> Components = new HashSet<string>(StringComparer.Ordinal); public static void AddPrefab(string prefabName) { if (!string.IsNullOrEmpty(prefabName) && Prefabs.Add(prefabName.Trim())) { HostOwnerPlugin.Invalidate(); } } public static void AddComponent(string typeName) { if (!string.IsNullOrEmpty(typeName) && Components.Add(typeName.Trim())) { HostOwnerPlugin.Invalidate(); } } public static bool IsOwnedKind(int prefabHash) { HostOwnerPlugin instance = HostOwnerPlugin.Instance; if ((Object)(object)instance != (Object)null) { return instance.IsWanted(prefabHash); } return false; } } [BepInPlugin("j1ga.hostowner", "Host Owner", "0.1.0")] public class HostOwnerPlugin : BaseUnityPlugin { public const string Guid = "j1ga.hostowner"; public const string Name = "Host Owner"; public const string Version = "0.1.0"; private const int MaxErrors = 25; private ConfigEntry<bool> _cfgEnabled; private ConfigEntry<bool> _cfgDebug; private ConfigEntry<float> _cfgInterval; private ConfigEntry<float> _cfgYield; private ConfigEntry<bool> _cfgStations; private ConfigEntry<bool> _cfgBosses; private ConfigEntry<string> _cfgComponents; private ConfigEntry<string> _cfgPrefabs; private static readonly Type[] StationTypes = new Type[5] { typeof(Smelter), typeof(CookingStation), typeof(Beehive), typeof(SapCollector), typeof(Fermenter) }; private readonly HashSet<string> _warned = new HashSet<string>(); public static HostOwnerPlugin Instance; private readonly Dictionary<int, string> _wanted = new Dictionary<int, string>(); private ZNetScene _indexedScene; private bool _indexDirty; private readonly List<ZDO> _near = new List<ZDO>(); private float _nextPass; private readonly Dictionary<ZDOID, int> _held = new Dictionary<ZDOID, int>(); private readonly Dictionary<ZDOID, float> _yielded = new Dictionary<ZDOID, float>(); private readonly List<ZDOID> _expired = new List<ZDOID>(); private ZNetScene _recordsScene; private int _lastWanted; private int _lastOwned; private int _lastClaimed; private int _lastYielded; private int _claimedTotal; private int _yieldedTotal; private int _passes; private int _errorCount; private bool _disabledByErrors; private readonly HashSet<string> _loggedErrors = new HashSet<string>(); private bool Hosting { get { ZNet instance = ZNet.instance; if ((Object)(object)instance != (Object)null && instance.IsServer() && !instance.IsDedicated() && (Object)(object)Player.m_localPlayer != (Object)null && ZDOMan.instance != null) { return (Object)(object)ZNetScene.instance != (Object)null; } return false; } } internal bool IsWanted(int prefabHash) { return _wanted.ContainsKey(prefabHash); } private void RegisterCommands() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) new ConsoleCommand("hostowner", "Host Owner. 'hostowner status' - what the host owns; 'hostowner list' - the kinds; 'hostowner now' - a pass right away", (ConsoleEvent)delegate(ConsoleEventArgs args) { RunCommand(args); }, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private static void Say(ConsoleEventArgs args, string text) { if (args != null && (Object)(object)args.Context != (Object)null) { args.Context.AddString(text); } } private void RunCommand(ConsoleEventArgs args) { try { switch ((args.Args.Length > 1) ? args.Args[1].ToLowerInvariant() : "") { case "status": Say(args, StatusText()); break; case "list": Say(args, _wanted.Count + " kinds: " + KindList(0)); break; case "now": if (!Hosting) { Say(args, "Not hosting a world with a player; nothing to do."); break; } _indexedScene = null; _nextPass = Time.time + _cfgInterval.Value; Pass(); Say(args, StatusText()); break; default: Say(args, "hostowner status | list | now"); break; } } catch (Exception ex) { Say(args, "hostowner: " + ex.Message); Fail("command", ex); } } private string StatusText() { if (_disabledByErrors) { return "Host Owner is inert after errors, see the log."; } if (!_cfgEnabled.Value) { return "Host Owner is disabled in the config."; } ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null) { return "Host Owner: no world loaded."; } if (!instance.IsServer()) { return "Host Owner: this client is not the host, nothing is taken over here."; } if (instance.IsDedicated()) { return "Host Owner: a dedicated server has no player and no active area, nothing is taken over here."; } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(_wanted.Count).Append(" kinds; last pass: ").Append(_lastWanted) .Append(" such objects in the active area, ") .Append(_lastOwned) .Append(" owned by the host, ") .Append(_lastClaimed) .Append(" taken just now, ") .Append(_lastYielded) .Append(" left to a player who claimed them back; ") .Append(_claimedTotal) .Append(" taken and ") .Append(_yieldedTotal) .Append(" yielded in ") .Append(_passes) .Append(" passes, every ") .Append(F(_cfgInterval.Value)) .Append(" s."); return stringBuilder.ToString(); } private void BindConfig() { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected O, but got Unknown _cfgEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("01 General", "Enabled", true, "Master switch. Off: objects already taken stay with the host until it walks away, as with any owner."); _cfgDebug = ((BaseUnityPlugin)this).Config.Bind<bool>("01 General", "Debug", false, "Log every object taken over."); _cfgInterval = ((BaseUnityPlugin)this).Config.Bind<float>("01 General", "Interval", 2f, new ConfigDescription("Seconds between two passes over the host's active area. Vanilla hands ownership out every 2 s.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 30f), new object[0])); _cfgYield = ((BaseUnityPlugin)this).Config.Bind<float>("01 General", "YieldSeconds", 30f, new ConfigDescription("When a player's client takes an object back right after the host took it - a mod or the game claiming it on purpose, e.g. a taunt pulling a monster or a player using a cart - leave that object alone for this many seconds instead of fighting over it. 0: never yield.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 600f), new object[0])); _cfgStations = ((BaseUnityPlugin)this).Config.Bind<bool>("02 Objects", "Stations", true, "Every prefab with a Smelter (smelter, blast furnace, charcoal kiln, spinning wheel, windmill, eitr refinery), CookingStation (cooking stations, oven), Beehive, SapCollector or Fermenter component, from any mod too."); _cfgBosses = ((BaseUnityPlugin)this).Config.Bind<bool>("02 Objects", "Bosses", false, "Every creature flagged as a boss (Character.m_boss). Its AI then runs on the host, and mods that read the boss on its owner see every hit."); _cfgComponents = ((BaseUnityPlugin)this).Config.Bind<string>("02 Objects", "Components", "", "Component type names from the game, comma separated: every prefab carrying one of them is taken over. Example: Plant,Fireplace,Tameable. Unknown names are reported in the log once."); _cfgPrefabs = ((BaseUnityPlugin)this).Config.Bind<string>("02 Objects", "Prefabs", "", "Prefab names, comma separated, on top of the groups above. Example: piece_bathtub,Eikthyr. Players are never taken, whatever is listed."); ((BaseUnityPlugin)this).Config.SettingChanged += delegate { _indexDirty = true; }; } private static IEnumerable<string> Split(string text) { if (string.IsNullOrEmpty(text)) { yield break; } try { string[] array = text.Split(','); foreach (string raw in array) { string s = raw.Trim(); if (s.Length > 0) { yield return s; } } } finally { } } private Type ResolveComponent(string name) { Type type = typeof(ZNetView).Assembly.GetType(name) ?? Type.GetType(name); if (type == null || !typeof(Component).IsAssignableFrom(type)) { if (_warned.Add("type:" + name)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Component type '" + name + "' was not found in the game; ignored.")); } return null; } return type; } private void BuildIndex(ZNetScene zs) { _wanted.Clear(); if ((Object)(object)zs != (Object)(object)_recordsScene) { ForgetWorld(); _recordsScene = zs; } _indexedScene = zs; if (zs.m_prefabs == null) { return; } HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); foreach (string item in Split(_cfgPrefabs.Value)) { hashSet.Add(item); } foreach (string prefab in HostOwnerApi.Prefabs) { hashSet.Add(prefab); } List<Type> list = new List<Type>(); if (_cfgStations.Value) { list.AddRange(StationTypes); } foreach (string item2 in Split(_cfgComponents.Value)) { Type type = ResolveComponent(item2); if (type != null && !list.Contains(type)) { list.Add(type); } } foreach (string component2 in HostOwnerApi.Components) { Type type2 = ResolveComponent(component2); if (type2 != null && !list.Contains(type2)) { list.Add(type2); } } HashSet<string> hashSet2 = new HashSet<string>(StringComparer.Ordinal); foreach (GameObject prefab2 in zs.m_prefabs) { if ((Object)(object)prefab2 == (Object)null) { continue; } hashSet2.Add(((Object)prefab2).name); if ((Object)(object)prefab2.GetComponent<Player>() != (Object)null) { continue; } bool flag = hashSet.Contains(((Object)prefab2).name); if (!flag) { foreach (Type item3 in list) { if ((Object)(object)prefab2.GetComponent(item3) != (Object)null) { flag = true; break; } } } if (!flag && _cfgBosses.Value) { Character component = prefab2.GetComponent<Character>(); flag = (Object)(object)component != (Object)null && component.m_boss; } if (flag) { _wanted[zs.GetPrefabHash(prefab2)] = ((Object)prefab2).name; } } foreach (string item4 in hashSet) { if (!hashSet2.Contains(item4) && _warned.Add("prefab:" + item4)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Prefab '" + item4 + "' is not registered in this world; ignored.")); } } ((BaseUnityPlugin)this).Logger.LogInfo((object)(_wanted.Count + " kinds of objects to own on the host: " + KindList(12))); } private string KindList(int max) { List<string> list = new List<string>(_wanted.Values); list.Sort(StringComparer.Ordinal); if (list.Count == 0) { return "none"; } if (max > 0 && list.Count > max) { int num = list.Count - max; list.RemoveRange(max, num); return string.Join(", ", list.ToArray()) + " and " + num + " more"; } return string.Join(", ", list.ToArray()); } private void Awake() { try { Instance = this; BindConfig(); RegisterCommands(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Host Owner 0.1.0 loaded. No Harmony patches are applied."); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Awake failed, mod is inert: " + ex)); _disabledByErrors = true; } } private void Update() { if (_disabledByErrors) { return; } try { if (_indexDirty) { _indexDirty = false; _indexedScene = null; } if (!(Time.time < _nextPass)) { _nextPass = Time.time + _cfgInterval.Value; Pass(); } } catch (Exception e) { Fail("Update", e); } } private void OnDestroy() { if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } internal static void Invalidate() { if ((Object)(object)Instance != (Object)null) { Instance._indexDirty = true; } } private void Pass() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) if (!_cfgEnabled.Value || !Hosting) { return; } ZNet instance = ZNet.instance; ZDOMan instance2 = ZDOMan.instance; ZNetScene instance3 = ZNetScene.instance; if ((Object)(object)instance3 != (Object)(object)_indexedScene) { BuildIndex(instance3); } if (_wanted.Count == 0) { return; } Vector3 referencePosition = instance.GetReferencePosition(); Vector2s zone = ZoneSystem.GetZone(referencePosition); SimulationDistance syncedSimulationDistance = instance.GetSyncedSimulationDistance(); _near.Clear(); instance2.FindSectorObjects(zone, new SimulationDistance(((SimulationDistance)(ref syncedSimulationDistance)).NearSimulationDistance, 0, ((SimulationDistance)(ref syncedSimulationDistance)).IsClassic), _near, (List<ZDO>)null); long sessionID = ZDOMan.GetSessionID(); float time = Time.time; int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; foreach (ZDO item in _near) { if (item == null || !item.Persistent || !_wanted.TryGetValue(item.GetPrefab(), out var value)) { continue; } num++; ZDOID uid = item.m_uid; long owner = item.GetOwner(); if (owner == sessionID) { num2++; if (_held.ContainsKey(uid)) { _held[uid] = _passes; } continue; } if (_yielded.TryGetValue(uid, out var value2)) { if (time < value2) { num4++; continue; } _yielded.Remove(uid); } if (owner != 0 && _cfgYield.Value > 0f && _held.TryGetValue(uid, out var value3) && value3 == _passes - 1) { _yielded[uid] = time + _cfgYield.Value; _held.Remove(uid); num4++; _yieldedTotal++; if (_cfgDebug.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)(value + " " + Pos(item.GetPosition()) + ": claimed back by " + PeerName(instance, owner) + ", left alone for " + F(_cfgYield.Value) + " s")); } } else if (ZNetScene.InActiveArea(item.GetPosition(), zone)) { item.SetOwner(sessionID); _held[uid] = _passes; num3++; if (_cfgDebug.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)(value + " " + Pos(item.GetPosition()) + ": taken from " + PeerName(instance, owner))); } } } _near.Clear(); Prune(time); _lastWanted = num; _lastOwned = num2 + num3; _lastClaimed = num3; _lastYielded = num4; _claimedTotal += num3; _passes++; } private void Prune(float now) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) _expired.Clear(); foreach (KeyValuePair<ZDOID, int> item in _held) { if (item.Value < _passes - 1) { _expired.Add(item.Key); } } foreach (ZDOID item2 in _expired) { _held.Remove(item2); } _expired.Clear(); foreach (KeyValuePair<ZDOID, float> item3 in _yielded) { if (now >= item3.Value) { _expired.Add(item3.Key); } } foreach (ZDOID item4 in _expired) { _yielded.Remove(item4); } _expired.Clear(); } private void ForgetWorld() { _held.Clear(); _yielded.Clear(); } private static string PeerName(ZNet znet, long uid) { if (uid == 0) { return "nobody"; } ZNetPeer peer = znet.GetPeer(uid); if (peer != null && !string.IsNullOrEmpty(peer.m_playerName)) { return peer.m_playerName; } return "peer " + uid; } private static string Pos(Vector3 p) { return "(" + p.x.ToString("0", CultureInfo.InvariantCulture) + ", " + p.y.ToString("0", CultureInfo.InvariantCulture) + ", " + p.z.ToString("0", CultureInfo.InvariantCulture) + ")"; } private static string F(float v) { return v.ToString("0.##", CultureInfo.InvariantCulture); } private void Fail(string where, Exception e) { string text = where + ": " + e.GetType().Name + ": " + e.Message; if (_loggedErrors.Add(text)) { ((BaseUnityPlugin)this).Logger.LogError((object)(text + "\n" + e.StackTrace)); } if (++_errorCount >= 25 && !_disabledByErrors) { _disabledByErrors = true; ((BaseUnityPlugin)this).Logger.LogError((object)"Too many errors, Host Owner is now inert until the game restarts."); } } }