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 SharedExploration v1.1.1
plugins/SharedExploration.dll
Decompiled a day agousing System; using System.Collections; 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 BepInEx; using BepInEx.Configuration; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("SharedExploration")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.1.0")] [assembly: AssemblyInformationalVersion("1.1.1+d033a2820f76aef7e0f9dd2fe17218f922a31337")] [assembly: AssemblyProduct("SharedExploration")] [assembly: AssemblyTitle("SharedExploration")] [assembly: AssemblyVersion("1.1.1.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 SharedExploration { [BepInPlugin("Tie.SharedExploration", "SharedExploration", "1.1.1")] public sealed class SharedExplorationPlugin : BaseUnityPlugin { public const string Guid = "Tie.SharedExploration"; private const string OldGuid = "local.sharedexploration"; public const string Version = "1.1.1"; private const int SharedMapVersion = 3; private const int Header = 8; private ConfigEntry<bool> _enabled; private ConfigEntry<float> _sampleInterval; private ConfigEntry<float> _tableInterval; private ConfigEntry<float> _exploreRadius; private int _size; private float _pixelSize; private float _gameRadius; private byte[] _explored; private int _revision; private int _savedRevision; private string _saveFile; private string[] _tablePrefabs; private readonly Dictionary<ZDOID, (uint DataRevision, int Revision)> _tables = new Dictionary<ZDOID, (uint, int)>(); private float _sampleTimer; private float _tableTimer; private bool _updating; private int _tableCount; private int _written; private void Awake() { //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Expected O, but got Unknown //IL_00fb: Unknown result type (might be due to invalid IL or missing references) string text = Path.Combine(Paths.ConfigPath, "local.sharedexploration.cfg"); if (File.Exists(text) && !File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath)) { try { File.Move(text, ((BaseUnityPlugin)this).Config.ConfigFilePath); ((BaseUnityPlugin)this).Config.Reload(); } catch (IOException) { } } _enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Add the areas players explore to every map table."); _sampleInterval = ((BaseUnityPlugin)this).Config.Bind<float>("General", "SampleIntervalSeconds", 2f, "How often player positions are recorded (the game explores every 2 s)."); _tableInterval = ((BaseUnityPlugin)this).Config.Bind<float>("General", "MapTableUpdateSeconds", 30f, "How often map tables are updated with the recorded areas."); _exploreRadius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ExploreRadius", 0f, "Radius in metres revealed around each player. 0 = the game's own radius."); new ConsoleCommand("mapexplore", "[update] - shared exploration status; 'update' writes map tables now; use through 'server mapexplore'", new ConsoleEvent(Run), false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private void Update() { if (_enabled.Value && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && ZDOMan.instance != null && !((Object)(object)ZNetScene.instance == (Object)null) && (_explored != null || Init())) { _sampleTimer += Time.deltaTime; if (_sampleTimer >= Mathf.Max(0.5f, _sampleInterval.Value)) { _sampleTimer = 0f; Sample(); } _tableTimer += Time.deltaTime; if (_tableTimer >= Mathf.Max(5f, _tableInterval.Value) && !_updating) { _tableTimer = 0f; ((MonoBehaviour)this).StartCoroutine(UpdateTables()); } } } private bool Init() { Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null) { return false; } _size = instance.m_textureSize; _pixelSize = instance.m_pixelSize; _gameRadius = instance.m_exploreRadius; _tablePrefabs = (from p in ZNetScene.instance.m_prefabs where (Object)(object)p != (Object)null && (Object)(object)p.GetComponent<MapTable>() != (Object)null select ((Object)p).name).ToArray(); _explored = new byte[_size * _size]; string text = string.Concat(ZNet.instance.GetWorldName().Split(Path.GetInvalidFileNameChars())); _saveFile = Path.Combine(Paths.ConfigPath, "SharedExploration", text + ".explored.gz"); Load(); ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("Map {0}x{1} px at {2} m/px, explore radius {3} m, map tables: {4}", _size, _size, _pixelSize, Radius(), string.Join(", ", _tablePrefabs))); return true; } private float Radius() { if (!(_exploreRadius.Value > 0f)) { return _gameRadius; } return _exploreRadius.Value; } private void Sample() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (!((ZDOID)(ref peer.m_characterID)).IsNone()) { Explore(peer.m_refPos, Radius()); } } } private void Explore(Vector3 p, float radius) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_0082: Unknown result type (might be due to invalid IL or missing references) int num = (int)Mathf.Ceil(radius / _pixelSize); int num2 = _size / 2; int num3 = Utils.RoundToInt(p.x / _pixelSize + (float)num2); int num4 = Utils.RoundToInt(p.z / _pixelSize + (float)num2); bool flag = false; for (int i = num4 - num; i <= num4 + num; i++) { if (i < 0 || i >= _size) { continue; } for (int j = num3 - num; j <= num3 + num; j++) { if (j < 0 || j >= _size) { continue; } Vector2 val = new Vector2((float)(j - num3), (float)(i - num4)); if (!(((Vector2)(ref val)).magnitude > (float)num)) { int num5 = i * _size + j; if (_explored[num5] == 0) { _explored[num5] = 1; flag = true; } } } } if (flag) { _revision++; } } private IEnumerator UpdateTables() { _updating = true; try { List<ZDO> zdos = new List<ZDO>(); string[] tablePrefabs = _tablePrefabs; foreach (string prefab in tablePrefabs) { int index = 0; while (!ZDOMan.instance.GetAllZDOsWithPrefabIterative(prefab, zdos, ref index)) { yield return null; } } _tableCount = zdos.Count; _written = 0; for (int i = 0; i < 2; i++) { foreach (ZDO item in zdos) { if (item.IsValid() && UpdateTable(item)) { yield return null; } } } foreach (ZDOID item2 in _tables.Keys.Where((ZDOID id) => !zdos.Any((ZDO z) => z.m_uid == id)).ToList()) { _tables.Remove(item2); } if (_written > 0) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Updated {_written} of {zdos.Count} map table(s); {Explored():N0} explored map pixels shared."); } Save(); } finally { _updating = false; } } private bool UpdateTable(ZDO zdo) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: 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) if (_tables.TryGetValue(zdo.m_uid, out (uint, int) value) && value.Item1 == zdo.DataRevision && value.Item2 == _revision) { return false; } int num = _size * _size; byte[] byteArray = zdo.GetByteArray(ZDOVars.s_data, (byte[])null); byte[] array; if (byteArray == null) { array = new byte[8 + num + 4]; BitConverter.GetBytes(3).CopyTo(array, 0); BitConverter.GetBytes(num).CopyTo(array, 4); } else { array = Utils.Decompress(byteArray); int num2 = ((array.Length >= 8) ? BitConverter.ToInt32(array, 0) : (-1)); int num3 = ((array.Length >= 8) ? BitConverter.ToInt32(array, 4) : (-1)); if (num2 != 3 || num3 != num || array.Length < 8 + num) { ((BaseUnityPlugin)this).Logger.LogWarning((object)$"Map table at {zdo.GetPosition():F0}: unsupported data (version {num2}, {num3} px); left unchanged."); _tables[zdo.m_uid] = (zdo.DataRevision, _revision); return true; } } bool flag = false; bool flag2 = false; for (int i = 0; i < num; i++) { if (array[8 + i] != 0) { if (_explored[i] == 0) { _explored[i] = 1; flag = true; } } else if (_explored[i] != 0) { array[8 + i] = 1; flag2 = true; } } if (flag) { _revision++; } if (flag2) { zdo.Set(ZDOVars.s_data, Utils.Compress(array)); _written++; } _tables[zdo.m_uid] = (zdo.DataRevision, _revision); return true; } private void Load() { try { if (File.Exists(_saveFile)) { byte[] array = Utils.Decompress(File.ReadAllBytes(_saveFile)); if (array.Length != _explored.Length) { ((BaseUnityPlugin)this).Logger.LogWarning((object)$"{_saveFile} is for a {Mathf.Sqrt((float)array.Length):0} px map; ignored."); return; } array.CopyTo(_explored, 0); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Loaded {Explored():N0} explored map pixels from {_saveFile}"); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Could not load " + _saveFile + ": " + ex.Message)); } } private void Save() { if (_explored == null || _savedRevision == _revision) { return; } try { Directory.CreateDirectory(Path.GetDirectoryName(_saveFile)); string text = _saveFile + ".tmp"; File.WriteAllBytes(text, Utils.Compress(_explored)); if (File.Exists(_saveFile)) { File.Delete(_saveFile); } File.Move(text, _saveFile); _savedRevision = _revision; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Could not save " + _saveFile + ": " + ex.Message)); } } private void OnDestroy() { Save(); } private int Explored() { int num = 0; byte[] explored = _explored; foreach (byte b in explored) { num += b; } return num; } private void Run(ConsoleEventArgs args) { Terminal context = args.Context; if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { Print(context, "mapexplore must run on the server: type 'server mapexplore' instead."); return; } if (_explored == null) { Print(context, "Shared exploration has not started yet (disabled, or the world is still loading)."); return; } if (args.Args.Skip(1).Any((string a) => a.Equals("update", StringComparison.OrdinalIgnoreCase))) { _tableTimer = float.MaxValue; Print(context, "Map tables will be updated within a second."); } Print(context, $"Shared exploration: {(double)Explored() * 100.0 / (double)_explored.Length:0.00}% of the map explored, {_tableCount} map table(s), updated every {_tableInterval.Value:0} s."); } private static void Print(Terminal output, string text) { object obj = ((object)output) ?? ((object)Console.instance); if (obj != null) { ((Terminal)obj).AddString(text); } } } }