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 Ratatoskr v0.2.2
plugins/Ratatoskr.dll
Decompiled a week agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using Microsoft.CodeAnalysis; using UnityEngine; using ValheimRcon; using ValheimRcon.Commands; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_guiutils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Ratatoskr { internal sealed class Args { public readonly List<string> Positional = new List<string>(); public Vector3? NearCenter; public float NearRadius; public int Offset; public bool All; public string Player; public float Days; public long Since; public string Text => string.Join(" ", Positional).Trim(); public Args(IReadOnlyList<string> raw) { //IL_009a: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < raw.Count; i++) { switch (raw[i]) { case "-near": NearCenter = new Vector3(F(raw, i + 1), 0f, F(raw, i + 2)); NearRadius = F(raw, i + 3); i += 3; break; case "-offset": Offset = Mathf.Max(0, (int)F(raw, i + 1)); i++; break; case "-player": if (i + 1 >= raw.Count) { throw new ArgumentException("-player needs a name"); } Player = raw[i + 1]; i++; break; case "-days": Days = F(raw, i + 1); i++; break; case "-since": { if (!long.TryParse((i + 1 < raw.Count) ? raw[i + 1] : "", out var result)) { throw new ArgumentException("-since needs a number"); } Since = result; i++; break; } case "-all": All = true; break; default: Positional.Add(raw[i]); break; } } } public static string WithoutOffset(string raw) { return Regex.Replace(raw, "(^|\\s)-offset\\s+\\S+", "").Trim(); } public bool InRange(Vector3 p) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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) if (!NearCenter.HasValue) { return true; } Vector3 value = NearCenter.Value; float num = p.x - value.x; float num2 = p.z - value.z; return num * num + num2 * num2 <= NearRadius * NearRadius; } private static float F(IReadOnlyList<string> raw, int i) { if (i >= raw.Count || !float.TryParse(raw[i], NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { throw new ArgumentException("bad or missing number at argument " + i); } return result; } } internal static class Events { private const int Capacity = 1000; private static readonly LinkedList<(long Seq, string Json)> Ring = new LinkedList<(long, string)>(); public static readonly string Boot = Guid.NewGuid().ToString("N").Substring(0, 8); public static long Seq { get; private set; } public static long Now => DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); public static void Add(string type, Action<Json> props = null) { Json json = new Json().Obj().Prop("seq", ++Seq).Prop("t", Now) .Prop("type", type); props?.Invoke(json); Ring.AddLast((Seq, json.EndObj().ToString())); while (Ring.Count > 1000) { Ring.RemoveFirst(); } } public static List<string> Since(long seq) { List<string> list = new List<string>(); foreach (var item in Ring) { if (item.Seq > seq) { list.Add(item.Json); } } return list; } } internal sealed class Contents { public uint Revision; public int Slots; public readonly Dictionary<string, (string Label, string English, int Count)> Items = new Dictionary<string, (string, string, int)>(); } internal static class InventoryCache { private static readonly Dictionary<ZDOID, Contents> Cache = new Dictionary<ZDOID, Contents>(); public static Contents Get(ZDO zdo, Container container) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) if (Cache.TryGetValue(zdo.m_uid, out var value) && value.Revision == zdo.DataRevision) { return value; } Inventory obj = (((Object)(object)container != (Object)null) ? World.LoadInventory(zdo, container) : World.LoadTombInventory(zdo)); value = new Contents { Revision = zdo.DataRevision }; foreach (ItemData allItem in obj.GetAllItems()) { value.Slots++; PlayerNames.Learn(allItem.m_crafterID, allItem.m_crafterName); string key = World.ItemId(allItem); value.Items.TryGetValue(key, out (string, string, int) value2); value.Items[key] = (World.ItemLabel(allItem), World.ItemEnglish(allItem), value2.Item3 + allItem.m_stack); } Cache[zdo.m_uid] = value; return value; } public static void Prune(List<ZDOID> storage, List<ZDOID> tombs) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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) HashSet<ZDOID> hashSet = new HashSet<ZDOID>(storage); hashSet.UnionWith(tombs); List<ZDOID> list = new List<ZDOID>(); foreach (ZDOID key in Cache.Keys) { if (!hashSet.Contains(key)) { list.Add(key); } } foreach (ZDOID item in list) { Cache.Remove(item); } } } internal sealed class Json { private readonly StringBuilder _sb = new StringBuilder(); private readonly Stack<bool> _first = new Stack<bool>(); private bool _skipNext; public Json Obj() { Sep(); _sb.Append('{'); _first.Push(item: true); return this; } public Json EndObj() { _sb.Append('}'); _first.Pop(); return this; } public Json Arr() { Sep(); _sb.Append('['); _first.Push(item: true); return this; } public Json EndArr() { _sb.Append(']'); _first.Pop(); return this; } public Json Key(string key) { Sep(); Str(key); _sb.Append(':'); _skipNext = true; return this; } public Json Val(string v) { Sep(); if (v == null) { _sb.Append("null"); } else { Str(v); } return this; } public Json Val(long v) { Sep(); _sb.Append(v.ToString(CultureInfo.InvariantCulture)); return this; } public Json Val(double v) { Sep(); _sb.Append(Math.Round(v, 2).ToString(CultureInfo.InvariantCulture)); return this; } public Json Val(bool v) { Sep(); _sb.Append(v ? "true" : "false"); return this; } public Json Null() { Sep(); _sb.Append("null"); return this; } public Json Raw(string json) { Sep(); _sb.Append(json); return this; } public Json Pos(Vector3 p) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) return Arr().Val(p.x).Val(p.y).Val(p.z) .EndArr(); } public Json Prop(string k, string v) { return Key(k).Val(v); } public Json Prop(string k, long v) { return Key(k).Val(v); } public Json Prop(string k, double v) { return Key(k).Val(v); } public Json Prop(string k, bool v) { return Key(k).Val(v); } private void Sep() { if (_skipNext) { _skipNext = false; } else if (_first.Count != 0) { if (_first.Peek()) { _first.Pop(); _first.Push(item: false); } else { _sb.Append(','); } } } private void Str(string s) { _sb.Append('"'); foreach (char c in s) { switch (c) { case '"': _sb.Append("\\\""); continue; case '\\': _sb.Append("\\\\"); continue; case '\n': _sb.Append("\\n"); continue; case '\r': _sb.Append("\\r"); continue; case '\t': _sb.Append("\\t"); continue; } if (c < ' ') { _sb.AppendFormat("\\u{0:x4}", (int)c); } else { _sb.Append(c); } } _sb.Append('"'); } public override string ToString() { return _sb.ToString(); } } internal static class Pager { private const int Budget = 3800; public static string Page(IList<string> items, int offset, string extraProps = null) { StringBuilder stringBuilder = new StringBuilder(); int num = 0; int i; for (i = offset; i < items.Count; i++) { int num2 = Encoding.UTF8.GetByteCount(items[i]) + 1; if (i > offset && num + num2 > 3680) { break; } if (i > offset) { stringBuilder.Append(','); } stringBuilder.Append(items[i]); num += num2; } StringBuilder stringBuilder2 = new StringBuilder(); stringBuilder2.Append("{\"total\":").Append(items.Count).Append(",\"offset\":") .Append(offset) .Append(",\"next\":") .Append((i < items.Count) ? i.ToString() : "null"); if (!string.IsNullOrEmpty(extraProps)) { stringBuilder2.Append(',').Append(extraProps); } stringBuilder2.Append(",\"items\":[").Append((object?)stringBuilder).Append("]}"); return stringBuilder2.ToString(); } } internal static class PlayerNames { private static readonly Dictionary<long, string> Names = new Dictionary<long, string>(); private static bool _dirty; private static string FilePath => Path.Combine(Paths.ConfigPath, "ratatoskr.players.tsv"); public static void Load() { if (!File.Exists(FilePath)) { return; } string[] array = File.ReadAllLines(FilePath); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { '\t' }); if (array2.Length == 2 && long.TryParse(array2[0], out var result)) { Names[result] = array2[1]; } } } public static void Learn(long id, string name) { if (id != 0L && !string.IsNullOrEmpty(name) && (!Names.TryGetValue(id, out var value) || !(value == name))) { Names[id] = name; _dirty = true; } } public static string Get(long id) { if (!Names.TryGetValue(id, out var value)) { return null; } return value; } public static void LearnOnline() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null || ZDOMan.instance == null) { return; } foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { ZDO zDO = ZDOMan.instance.GetZDO(peer.m_characterID); if (zDO != null) { Learn(zDO.GetLong(ZDOVars.s_playerID, 0L), zDO.GetString(ZDOVars.s_playerName, "")); } } Save(); } public static void Save() { if (!_dirty) { return; } List<string> list = new List<string>(); foreach (KeyValuePair<long, string> name in Names) { list.Add(name.Key + "\t" + name.Value.Replace('\t', ' ')); } File.WriteAllLines(FilePath, list); _dirty = false; } } [BepInPlugin("dev.tiene.ratatoskr", "Ratatoskr", "0.2.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string Guid = "dev.tiene.ratatoskr"; public const string Name = "Ratatoskr"; public const string Version = "0.2.2"; private float _nextLearn; private float _nextTick; private bool _tickFailed; private void Awake() { Translations.Load(((BaseUnityPlugin)this).Config.Bind<string>("General", "Language", "English", "Language for item names in replies (a column of the game's localization, e.g. French, German). Queries match this language, English and prefab names.").Value); PlayerNames.Load(); RconCommandsUtil.RegisterAllCommands(Assembly.GetExecutingAssembly()); } private void Update() { float time = Time.time; if (time >= _nextTick) { _nextTick = time + 2f; try { Tracker.Tick(); _tickFailed = false; } catch (Exception ex) { if (!_tickFailed) { ((BaseUnityPlugin)this).Logger.LogError((object)ex); } _tickFailed = true; } } if (!(time < _nextLearn)) { _nextLearn = time + 60f; PlayerNames.LearnOnline(); } } private void OnDestroy() { Tracker.Shutdown(); } } internal sealed class Store { private readonly string _path; public bool Exists => File.Exists(_path); public Store(string name) { _path = Path.Combine(Paths.ConfigPath, name); } public void Append(params object[] fields) { string[] array = new string[fields.Length]; for (int i = 0; i < fields.Length; i++) { array[i] = (fields[i]?.ToString() ?? "").Replace('\t', ' ').Replace('\n', ' '); } File.AppendAllText(_path, string.Join("\t", array) + "\n"); } public List<string[]> Read(int max = 0) { List<string[]> list = new List<string[]>(); if (!File.Exists(_path)) { return list; } string[] array = File.ReadAllLines(_path); for (int i = ((max > 0) ? Math.Max(0, array.Length - max) : 0); i < array.Length; i++) { if (array[i].Length > 0) { list.Add(array[i].Split(new char[1] { '\t' })); } } return list; } } internal sealed class JournalEntry { public long T; public string Player; public int Delta; public string Item; public string Label; public string Container; public string ContainerLabel; public float X; public float Z; } internal sealed class Session { public long PlayerId; public string Name; public long Start; public long End; } internal static class Tracker { private sealed class PlayerState { public string Name; public long PlayerId; public long JoinedAt; public ZDOID DeadFor = ZDOID.None; } private const int JournalInMemory = 5000; private static readonly Store BiomeStore = new Store("ratatoskr.biomes.tsv"); private static readonly Store SessionStore = new Store("ratatoskr.sessions.tsv"); private static readonly Store JournalStore = new Store("ratatoskr.journal.tsv"); private static readonly Dictionary<long, PlayerState> Online = new Dictionary<long, PlayerState>(); private static readonly Dictionary<ZDOID, (uint Rev, Dictionary<string, int> Counts)> Chests = new Dictionary<ZDOID, (uint, Dictionary<string, int>)>(); private static HashSet<string> _knownBiomes; private static HashSet<string> _keys; private static string _raid; private static bool _started; public static readonly List<JournalEntry> Journal = new List<JournalEntry>(); public static readonly List<Session> Sessions = new List<Session>(); public static IEnumerable<Session> OpenSessions() { return Online.Values.Select((PlayerState p) => new Session { PlayerId = p.PlayerId, Name = p.Name, Start = p.JoinedAt, End = Events.Now }); } public static void Tick() { if (!((Object)(object)ZNet.instance == (Object)null) && ZDOMan.instance != null && !((Object)(object)ZoneSystem.instance == (Object)null) && !((Object)(object)EnvMan.instance == (Object)null)) { if (!_started) { Start(); } TrackPlayers(); TrackKeys(); TrackRaid(); TrackChests(); } } public static void Shutdown() { foreach (Session item in OpenSessions()) { SessionStore.Append(item.PlayerId, item.Name, item.Start, item.End); } Online.Clear(); } private static void Start() { //IL_022b: Unknown result type (might be due to invalid IL or missing references) _started = true; foreach (string[] item in SessionStore.Read()) { if (item.Length >= 4 && long.TryParse(item[0], out var result) && long.TryParse(item[2], out var result2) && long.TryParse(item[3], out var result3)) { Sessions.Add(new Session { PlayerId = result, Name = item[1], Start = result2, End = result3 }); } } foreach (string[] item2 in JournalStore.Read(5000)) { if (item2.Length >= 9 && long.TryParse(item2[0], out var result4) && int.TryParse(item2[2], out var result5)) { Journal.Add(new JournalEntry { T = result4, Player = item2[1], Delta = result5, Item = item2[3], Label = item2[4], Container = item2[5], ContainerLabel = ((item2[6].Length > 0) ? item2[6] : null), X = float.Parse(item2[7], CultureInfo.InvariantCulture), Z = float.Parse(item2[8], CultureInfo.InvariantCulture) }); } } _knownBiomes = new HashSet<string>(from r in BiomeStore.Read() select r[0]); if (!BiomeStore.Exists) { SeedBiomes(); } _keys = new HashSet<string>(ZoneSystem.instance.GetGlobalKeys()); _raid = CurrentRaid()?.m_name; foreach (ZDO item3 in WorldIndex.Containers()) { World.PrefabInfo info = World.Info(item3); if (World.IsStorage(item3, info, all: false)) { Chests[item3.m_uid] = (item3.DataRevision, Counts(item3, info)); } } } private static void SeedBiomes() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) foreach (ZDO item in World.All()) { World.PrefabInfo prefabInfo = World.Info(item); if (item.GetLong(ZDOVars.s_creator, 0L) != 0L || prefabInfo.IsTombstone || prefabInfo.IsPortal) { string text = World.Biome(item.GetPosition()); if (text != null && _knownBiomes.Add(text)) { BiomeStore.Append(text, "", Events.Now); } } } } private static void TrackPlayers() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) HashSet<long> seen = new HashSet<long>(); foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer.m_characterID == ZDOID.None) { if (Online.ContainsKey(peer.m_uid)) { seen.Add(peer.m_uid); } continue; } seen.Add(peer.m_uid); if (!Online.TryGetValue(peer.m_uid, out var st)) { st = new PlayerState { Name = peer.m_playerName, JoinedAt = Events.Now }; Online[peer.m_uid] = st; bool first = Sessions.All((Session s) => s.Name != st.Name); Events.Add("join", delegate(Json j) { j.Prop("player", st.Name).Prop("first", first); }); } ZDO zDO = ZDOMan.instance.GetZDO(peer.m_characterID); if (zDO == null) { continue; } st.PlayerId = zDO.GetLong(ZDOVars.s_playerID, 0L); PlayerNames.Learn(st.PlayerId, st.Name); Vector3 pos = zDO.GetPosition(); string biome = World.Biome(pos); if (zDO.GetBool(ZDOVars.s_dead, false) && st.DeadFor != peer.m_characterID) { st.DeadFor = peer.m_characterID; Events.Add("death", delegate(Json j) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) j.Prop("player", st.Name).Key("pos").Pos(pos) .Prop("biome", biome); }); } if (biome != null && biome != "None" && _knownBiomes.Add(biome)) { BiomeStore.Append(biome, st.Name, Events.Now); Events.Add("biome", delegate(Json j) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) j.Prop("player", st.Name).Prop("biome", biome).Key("pos") .Pos(pos); }); } } foreach (long item in Online.Keys.Where((long u) => !seen.Contains(u)).ToList()) { PlayerState st2 = Online[item]; Online.Remove(item); Session session = new Session { PlayerId = st2.PlayerId, Name = st2.Name, Start = st2.JoinedAt, End = Events.Now }; Sessions.Add(session); SessionStore.Append(session.PlayerId, session.Name, session.Start, session.End); Events.Add("leave", delegate(Json j) { j.Prop("player", st2.Name).Prop("seconds", (session.End - session.Start) / 1000); }); } } private static void TrackKeys() { foreach (string key in ZoneSystem.instance.GetGlobalKeys()) { if (_keys.Add(key) && key.StartsWith("defeated_")) { string names = string.Join(", ", Online.Values.Select((PlayerState p) => p.Name)); Events.Add("boss", delegate(Json j) { j.Prop("key", key).Prop("online", names); }); } } } private static RandomEvent CurrentRaid() { RandEventSystem instance = RandEventSystem.instance; object obj; if (!((Object)(object)instance == (Object)null)) { obj = instance.GetCurrentRandomEvent(); if (obj == null) { return instance.m_forcedEvent; } } else { obj = null; } return (RandomEvent)obj; } private static void TrackRaid() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) RandomEvent val = CurrentRaid(); string name = val?.m_name; if (name == _raid) { return; } if (name != null) { Vector3 pos = val.m_pos; object obj = Translations.Get(val.m_startMessage); if (obj == null) { Localization instance = Localization.instance; obj = ((instance != null) ? instance.Localize(val.m_startMessage) : null); } string message = (string)obj; Events.Add("raid", delegate(Json j) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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) j.Prop("raid", name).Prop("message", message).Key("pos") .Pos(pos) .Prop("biome", World.Biome(pos)) .Prop("label", World.LabelFor(pos, WorldIndex.Signs(), 40f)); }); } else { string ended = _raid; Events.Add("raidEnd", delegate(Json j) { j.Prop("raid", ended); }); } _raid = name; } private static Dictionary<string, int> Counts(ZDO zdo, World.PrefabInfo info) { return InventoryCache.Get(zdo, info.Container).Items.ToDictionary((KeyValuePair<string, (string Label, string English, int Count)> kv) => kv.Key, (KeyValuePair<string, (string Label, string English, int Count)> kv) => kv.Value.Count); } private static void TrackChests() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) foreach (ZDO item2 in WorldIndex.Containers()) { World.PrefabInfo info = World.Info(item2); if (!World.IsStorage(item2, info, all: false)) { continue; } uint dataRevision = item2.DataRevision; if (!Chests.TryGetValue(item2.m_uid, out (uint, Dictionary<string, int>) value)) { Chests[item2.m_uid] = (dataRevision, Counts(item2, info)); } else { if (value.Item1 == dataRevision) { continue; } Contents contents = InventoryCache.Get(item2, info.Container); Dictionary<string, int> dictionary = contents.Items.ToDictionary((KeyValuePair<string, (string Label, string English, int Count)> kv) => kv.Key, (KeyValuePair<string, (string Label, string English, int Count)> kv) => kv.Value.Count); Chests[item2.m_uid] = (dataRevision, dictionary); List<(string Item, string Label, int Delta)> changes = new List<(string, string, int)>(); foreach (string id in dictionary.Keys.Union(value.Item2.Keys)) { dictionary.TryGetValue(id, out var value2); value.Item2.TryGetValue(id, out var value3); if (value2 == value3) { continue; } object obj; if (contents.Items.TryGetValue(id, out (string, string, int) value4)) { (obj, _, _) = value4; } else { obj = Journal.LastOrDefault((JournalEntry e) => e.Item == id)?.Label ?? id; } string item = (string)obj; changes.Add((id, item, value2 - value3)); } if (changes.Count == 0) { continue; } long owner = item2.GetOwner(); string who = ZNet.instance.GetPeer(owner)?.m_playerName ?? ((owner == ZDOMan.GetSessionID()) ? "server" : "?"); Vector3 pos = item2.GetPosition(); string chestLabel = World.LabelFor(pos, WorldIndex.Signs()); foreach (var item3 in changes) { JournalEntry journalEntry = new JournalEntry { T = Events.Now, Player = who, Delta = item3.Delta, Item = item3.Item, Label = item3.Label, Container = info.Name, ContainerLabel = chestLabel, X = pos.x, Z = pos.z }; Journal.Add(journalEntry); JournalStore.Append(journalEntry.T, journalEntry.Player, journalEntry.Delta, journalEntry.Item, journalEntry.Label, journalEntry.Container, journalEntry.ContainerLabel, journalEntry.X.ToString("0.#", CultureInfo.InvariantCulture), journalEntry.Z.ToString("0.#", CultureInfo.InvariantCulture)); } if (Journal.Count > 5000) { Journal.RemoveRange(0, Journal.Count - 5000); } Events.Add("chest", delegate(Json j) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) j.Prop("player", who).Prop("container", info.Name).Prop("label", chestLabel) .Key("pos") .Pos(pos) .Key("changes") .Arr(); foreach (var item4 in changes) { j.Obj().Prop("item", item4.Item).Prop("name", item4.Label) .Prop("delta", item4.Delta) .EndObj(); } j.EndArr(); }); } } } } internal static class Translations { private static Dictionary<string, string> _words; public static string Language { get; private set; } = "English"; public static void Load(string language) { Language = (string.IsNullOrWhiteSpace(language) ? "English" : language.Trim()); _words = null; } public static string Get(string token) { if (string.IsNullOrEmpty(token) || token[0] != '$') { return null; } if (_words == null) { _words = Build(Language); } if (!_words.TryGetValue(token.Substring(1), out var value)) { return null; } return value; } private static Dictionary<string, string> Build(string language) { Dictionary<string, string> dictionary = new Dictionary<string, string>(); Localization instance = Localization.instance; LocalizationSettings localizationSettings = Localization.m_localizationSettings; if (instance == null || (Object)(object)localizationSettings == (Object)null) { return dictionary; } foreach (TextAsset localization in localizationSettings.Localizations) { if ((Object)(object)localization == (Object)null) { continue; } StringReader stringReader = new StringReader(localization.text); string[] array = stringReader.ReadLine()?.Split(new char[1] { ',' }); if (array == null) { continue; } int num = -1; for (int i = 0; i < array.Length; i++) { if (array[i].Trim(new char[1] { '"' }) == language) { num = i; break; } } if (num < 0) { continue; } foreach (List<string> item in instance.DoQuoteLineSplit(stringReader)) { if (item.Count > num && item[0].Length != 0 && !item[0].StartsWith("//")) { string text = item[num].Trim(); if (text.Length > 0 && text[0] != '\r') { dictionary[item[0]] = text; } } } } return dictionary; } } internal static class World { internal sealed class PrefabInfo { public string Name; public Container Container; public bool IsSign; public bool IsPortal; public bool IsTombstone; } internal struct SignText { public Vector3 Pos; public string Text; } private static readonly Dictionary<int, PrefabInfo> Prefabs = new Dictionary<int, PrefabInfo>(); private static readonly Regex Tags = new Regex("<[^>]*>", RegexOptions.Compiled); public static IEnumerable<ZDO> All() { return ZDOMan.instance.m_objectsByID.Values; } public static PrefabInfo Info(ZDO zdo) { int prefab = zdo.GetPrefab(); if (Prefabs.TryGetValue(prefab, out var value)) { return value; } value = new PrefabInfo(); GameObject val = (Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.GetPrefab(prefab) : null); if ((Object)(object)val != (Object)null) { value.Name = ((Object)val).name; value.Container = val.GetComponentInChildren<Container>(); value.IsSign = (Object)(object)val.GetComponent<Sign>() != (Object)null; value.IsPortal = (Object)(object)val.GetComponent<TeleportWorld>() != (Object)null; value.IsTombstone = (Object)(object)val.GetComponent<TombStone>() != (Object)null; } else { value.Name = prefab.ToString(); } Prefabs[prefab] = value; return value; } public static bool IsStorage(ZDO zdo, PrefabInfo info, bool all) { if ((Object)(object)info.Container == (Object)null || info.IsTombstone) { return false; } if (!all) { return zdo.GetLong(ZDOVars.s_creator, 0L) != 0; } return true; } public static Inventory LoadInventory(ZDO zdo, Container c) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown Inventory val = new Inventory(c.m_name, (Sprite)null, c.m_width, c.m_height); byte[] byteArray = zdo.GetByteArray(ZDOVars.s_items, (byte[])null); if (byteArray != null) { val.Load(new ZPackage(byteArray)); } return val; } public static Inventory LoadTombInventory(ZDO zdo) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown Inventory val = new Inventory("tomb", (Sprite)null, 8, 8); byte[] byteArray = zdo.GetByteArray(ZDOVars.s_items, (byte[])null); if (byteArray != null) { val.Load(new ZPackage(byteArray)); } return val; } public static string ItemId(ItemData item) { if (!((Object)(object)item.m_dropPrefab != (Object)null)) { return item.m_shared.m_name; } return ((Object)item.m_dropPrefab).name; } public static string ItemEnglish(ItemData item) { string name = item.m_shared.m_name; if (Localization.instance == null) { return name; } return Localization.instance.Localize(name); } public static string ItemLabel(ItemData item) { return Translations.Get(item.m_shared.m_name) ?? ItemEnglish(item); } public static string Biome(Vector3 pos) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (WorldGenerator.instance == null) { return null; } return ((object)WorldGenerator.instance.GetBiome(pos)/*cast due to .constrained prefix*/).ToString(); } public static string Clean(string s) { if (!string.IsNullOrEmpty(s)) { return Tags.Replace(s, "").Trim(); } return s; } public static string LabelFor(Vector3 pos, List<SignText> signs, float range = 3f) { //IL_0018: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) string result = null; float num = range * range; foreach (SignText sign in signs) { Vector3 val = sign.Pos - pos; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; result = sign.Text; } } return result; } } internal static class WorldIndex { public const float MaxAge = 30f; private static readonly List<ZDOID> StorageIds = new List<ZDOID>(); private static readonly List<ZDOID> TombIds = new List<ZDOID>(); private static readonly List<ZDOID> PortalIds = new List<ZDOID>(); private static List<World.SignText> _signs = new List<World.SignText>(); private static float _builtAt = float.NegativeInfinity; public static double LastScanMs { get; private set; } public static void EnsureFresh() { if (Time.time - _builtAt >= 30f) { Rebuild(); } } public static void Rebuild() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) Stopwatch stopwatch = Stopwatch.StartNew(); StorageIds.Clear(); TombIds.Clear(); PortalIds.Clear(); List<World.SignText> list = new List<World.SignText>(); foreach (ZDO item in World.All()) { World.PrefabInfo prefabInfo = World.Info(item); if (prefabInfo.IsTombstone) { TombIds.Add(item.m_uid); } else if ((Object)(object)prefabInfo.Container != (Object)null) { StorageIds.Add(item.m_uid); } else if (prefabInfo.IsPortal) { PortalIds.Add(item.m_uid); } else if (prefabInfo.IsSign) { string text = World.Clean(item.GetString(ZDOVars.s_text, "")); if (!string.IsNullOrEmpty(text)) { list.Add(new World.SignText { Pos = item.GetPosition(), Text = text }); } } } _signs = list; _builtAt = Time.time; LastScanMs = stopwatch.Elapsed.TotalMilliseconds; InventoryCache.Prune(StorageIds, TombIds); } public static IEnumerable<ZDO> Containers() { EnsureFresh(); return Live(StorageIds); } public static IEnumerable<ZDO> Tombs() { EnsureFresh(); return Live(TombIds); } public static IEnumerable<ZDO> Portals() { EnsureFresh(); return Live(PortalIds); } public static List<World.SignText> Signs() { EnsureFresh(); return _signs; } private static IEnumerable<ZDO> Live(List<ZDOID> ids) { ZDOMan man = ZDOMan.instance; foreach (ZDOID id in ids) { ZDO zDO = man.GetZDO(id); if (zDO != null) { yield return zDO; } } } } } namespace Ratatoskr.Commands { internal class Tombs : PagedCommand { public override string Command => "rtTombs"; public override string Description => "Player tombstones with position, biome, in-game day of death and most valuable items. Usage: rtTombs [player] [-offset n]"; protected override Result Produce(Args args) { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) string text = args.Text; List<(DateTime?, string)> list = new List<(DateTime?, string)>(); foreach (ZDO item2 in WorldIndex.Tombs()) { string text2 = item2.GetString(ZDOVars.s_ownerName, ""); if (text.Length > 0 && text2.IndexOf(text, StringComparison.OrdinalIgnoreCase) < 0) { continue; } PlayerNames.Learn(item2.GetLong(ZDOVars.s_owner, 0L), text2); long num = item2.GetLong(ZDOVars.s_timeOfDeath, 0L); DateTime? item = ((num > 0) ? new DateTime?(new DateTime(num)) : ((DateTime?)null)); Vector3 position = item2.GetPosition(); Json json = new Json().Obj().Prop("id", ((object)Unsafe.As<ZDOID, ZDOID>(ref item2.m_uid)/*cast due to .constrained prefix*/).ToString()).Prop("owner", text2) .Key("pos") .Pos(position) .Prop("biome", World.Biome(position)) .Key("diedDay"); if (item.HasValue && (Object)(object)EnvMan.instance != (Object)null) { json.Val(EnvMan.instance.GetDay((item.Value - DateTime.MinValue).TotalSeconds)); } else { json.Null(); } Inventory val = World.LoadTombInventory(item2); json.Prop("stacks", val.NrOfItems()).Key("top").Arr(); foreach (ItemData item3 in (from i in val.GetAllItems() orderby i.m_shared.m_value * i.m_stack + i.m_quality descending select i).Take(5)) { json.Val(World.ItemLabel(item3) + ((item3.m_stack > 1) ? (" x" + item3.m_stack) : "")); } list.Add((item, json.EndArr().EndObj().ToString())); } PlayerNames.Save(); return new Result { Items = (from t in list orderby t.When ?? DateTime.MinValue descending select t.Json).ToList() }; } } internal class Portals : PagedCommand { public override string Command => "rtPortals"; public override string Description => "Portals grouped by tag; flags unpaired ones. Usage: rtPortals [-offset n]"; protected override Result Produce(Args args) { List<(ZDO, World.PrefabInfo, string)> source = (from z in WorldIndex.Portals() select (Zdo: z, Info: World.Info(z), Tag: z.GetString(ZDOVars.s_tag, ""))).ToList(); Dictionary<string, int> byTag = (from p in source group p by p.Tag).ToDictionary((IGrouping<string, (ZDO Zdo, World.PrefabInfo Info, string Tag)> g) => g.Key, (IGrouping<string, (ZDO Zdo, World.PrefabInfo Info, string Tag)> g) => g.Count()); return new Result { Items = source.OrderBy<(ZDO, World.PrefabInfo, string), string>(((ZDO Zdo, World.PrefabInfo Info, string Tag) p) => p.Tag).Select<(ZDO, World.PrefabInfo, string), string>(delegate((ZDO Zdo, World.PrefabInfo Info, string Tag) p) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) Vector3 position = p.Zdo.GetPosition(); return new Json().Obj().Prop("tag", p.Tag).Prop("prefab", p.Info.Name) .Key("pos") .Pos(position) .Prop("biome", World.Biome(position)) .Prop("paired", byTag[p.Tag] == 2) .Prop("sameTag", byTag[p.Tag]) .EndObj() .ToString(); }).ToList() }; } } internal class Builds : PagedCommand { public override string Command => "rtBuilds"; public override string Description => "Build pieces per creator (name when known). Usage: rtBuilds [-near x z r] [-offset n]"; protected override Result Produce(Args args) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) Dictionary<long, int> dictionary = new Dictionary<long, int>(); foreach (ZDO item in World.All()) { long num = item.GetLong(ZDOVars.s_creator, 0L); if (num != 0L && args.InRange(item.GetPosition())) { dictionary.TryGetValue(num, out var value); dictionary[num] = value + 1; } } return new Result { Items = (from kv in dictionary orderby kv.Value descending select new Json().Obj().Prop("playerId", kv.Key).Prop("name", PlayerNames.Get(kv.Key)) .Prop("pieces", kv.Value) .EndObj() .ToString()).ToList() }; } } internal abstract class RtCommand : RconCommand { protected override string OnHandle(CommandArgs args) { if (ZDOMan.instance == null || (Object)(object)ZNet.instance == (Object)null) { return new Json().Obj().Prop("error", "world not loaded").EndObj() .ToString(); } try { return Handle(new Args(args.Arguments), string.Join(" ", args.Arguments)); } catch (Exception ex) { return new Json().Obj().Prop("error", ex.Message).EndObj() .ToString(); } } protected abstract string Handle(Args args, string raw); } internal sealed class Result { public List<string> Items = new List<string>(); public string Extra; } internal abstract class PagedCommand : RtCommand { private static readonly Dictionary<string, (float At, Result R)> Snapshots = new Dictionary<string, (float, Result)>(); protected override string Handle(Args args, string raw) { string key = ((RconCommand)this).Command + " " + Args.WithoutOffset(raw); Result result; if (args.Offset == 0 || !Snapshots.TryGetValue(key, out (float, Result) value) || Time.time - value.Item1 > 60f) { result = Produce(args); foreach (string item in (from kv in Snapshots where Time.time - kv.Value.At > 60f select kv.Key).ToList()) { Snapshots.Remove(item); } Snapshots[key] = (Time.time, result); } else { result = value.Item2; } return Pager.Page(result.Items, args.Offset, result.Extra); } protected abstract Result Produce(Args args); } internal sealed class Stored { public ZDO Zdo; public World.PrefabInfo Info; public string Label; public Contents Contents; public static List<Stored> Scan(Args args) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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) List<World.SignText> signs = WorldIndex.Signs(); List<Stored> list = new List<Stored>(); foreach (ZDO item in WorldIndex.Containers()) { World.PrefabInfo prefabInfo = World.Info(item); if (World.IsStorage(item, prefabInfo, args.All)) { Vector3 position = item.GetPosition(); if (args.InRange(position)) { list.Add(new Stored { Zdo = item, Info = prefabInfo, Label = World.LabelFor(position, signs), Contents = InventoryCache.Get(item, prefabInfo.Container) }); } } } PlayerNames.Save(); return list; } public static bool Matches(string id, (string Label, string English, int Count) item, string query) { if (!Has(id, query) && !Has(item.Label, query)) { return Has(item.English, query); } return true; } public static bool Has(string s, string q) { if (s != null) { return s.IndexOf(q, StringComparison.OrdinalIgnoreCase) >= 0; } return false; } public Json Head(Json j) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) return j.Prop("id", ((object)Unsafe.As<ZDOID, ZDOID>(ref Zdo.m_uid)/*cast due to .constrained prefix*/).ToString()).Prop("prefab", Info.Name).Prop("label", Label) .Key("pos") .Pos(Zdo.GetPosition()); } } internal class Containers : PagedCommand { public override string Command => "rtContainers"; public override string Description => "Player storage (chests, carts, ships) with label from the nearest sign. Usage: rtContainers [-near x z r] [-all] [-offset n]"; protected override Result Produce(Args args) { return new Result { Items = (from s in Stored.Scan(args) orderby s.Label == null, s.Label select s.Head(new Json().Obj()).Prop("slots", s.Contents.Slots).Prop("capacity", s.Info.Container.m_width * s.Info.Container.m_height) .EndObj() .ToString()).ToList() }; } } internal class ContainerContents : PagedCommand { public override string Command => "rtContainer"; public override string Description => "Contents of one container, aggregated by item. Usage: rtContainer <id|sign text> [-offset n]"; protected override Result Produce(Args args) { string key = args.Text; if (key.Length == 0) { throw new ArgumentException("usage: rtContainer <id|sign text>"); } List<Stored> source = Stored.Scan(new Args(new string[1] { "-all" })); Stored stored = source.FirstOrDefault((Stored x) => ((object)Unsafe.As<ZDOID, ZDOID>(ref x.Zdo.m_uid)/*cast due to .constrained prefix*/).ToString() == key) ?? source.FirstOrDefault((Stored x) => Stored.Has(x.Label, key)) ?? throw new ArgumentException("no container matching " + key); return new Result { Items = (from kv in stored.Contents.Items orderby kv.Value.Count descending select new Json().Obj().Prop("item", kv.Key).Prop("name", kv.Value.Label) .Prop("count", kv.Value.Count) .EndObj() .ToString()).ToList(), Extra = "\"container\":" + stored.Head(new Json().Obj()).EndObj() }; } } internal class Find : PagedCommand { public override string Command => "rtFind"; public override string Description => "Containers holding an item (substring of prefab, translated or English name), biggest stacks first. Usage: rtFind <query> [-near x z r] [-offset n]"; protected override Result Produce(Args args) { string q = args.Text; if (q.Length == 0) { throw new ArgumentException("usage: rtFind <query>"); } List<(Stored, List<KeyValuePair<string, (string, string, int)>>, int)> list = new List<(Stored, List<KeyValuePair<string, (string, string, int)>>, int)>(); foreach (Stored item in Stored.Scan(args)) { List<KeyValuePair<string, (string, string, int)>> list2 = item.Contents.Items.Where((KeyValuePair<string, (string Label, string English, int Count)> kv) => Stored.Matches(kv.Key, kv.Value, q)).ToList(); if (list2.Count > 0) { list.Add((item, list2, list2.Sum<KeyValuePair<string, (string, string, int)>>((KeyValuePair<string, (string Label, string English, int Count)> kv) => kv.Value.Count))); } } Json json = new Json().Obj(); foreach (IGrouping<string, KeyValuePair<string, (string, string, int)>> item2 in from kv in list.SelectMany<(Stored, List<KeyValuePair<string, (string, string, int)>>, int), KeyValuePair<string, (string, string, int)>>(((Stored S, List<KeyValuePair<string, (string Label, string English, int Count)>> Items, int Total) h) => h.Items) group kv by kv.Key) { json.Prop(item2.First().Value.Item1, item2.Sum<KeyValuePair<string, (string, string, int)>>((KeyValuePair<string, (string Label, string English, int Count)> kv) => kv.Value.Count)); } return new Result { Items = list.OrderByDescending<(Stored, List<KeyValuePair<string, (string, string, int)>>, int), int>(((Stored S, List<KeyValuePair<string, (string Label, string English, int Count)>> Items, int Total) h) => h.Total).Select<(Stored, List<KeyValuePair<string, (string, string, int)>>, int), string>(delegate((Stored S, List<KeyValuePair<string, (string Label, string English, int Count)>> Items, int Total) h) { Json json2 = h.S.Head(new Json().Obj()).Key("items").Arr(); foreach (KeyValuePair<string, (string, string, int)> item3 in h.Items.OrderByDescending((KeyValuePair<string, (string Label, string English, int Count)> kv) => kv.Value.Count)) { json2.Obj().Prop("item", item3.Key).Prop("name", item3.Value.Item1) .Prop("count", item3.Value.Item3) .EndObj(); } return json2.EndArr().EndObj().ToString(); }).ToList(), Extra = "\"totals\":" + json.EndObj() }; } } internal class Stock : PagedCommand { public override string Command => "rtStock"; public override string Description => "Total of every item across player storage, largest first. Usage: rtStock [query] [-near x z r] [-offset n]"; protected override Result Produce(Args args) { string text = args.Text; Dictionary<string, (string, int, int)> dictionary = new Dictionary<string, (string, int, int)>(); foreach (Stored item in Stored.Scan(args)) { foreach (KeyValuePair<string, (string, string, int)> item2 in item.Contents.Items) { if (text.Length <= 0 || Stored.Matches(item2.Key, item2.Value, text)) { dictionary.TryGetValue(item2.Key, out var value); dictionary[item2.Key] = (item2.Value.Item1, value.Item2 + item2.Value.Item3, value.Item3 + 1); } } } return new Result { Items = (from kv in dictionary orderby kv.Value.Count descending select new Json().Obj().Prop("item", kv.Key).Prop("name", kv.Value.Label) .Prop("count", kv.Value.Count) .Prop("containers", kv.Value.Containers) .EndObj() .ToString()).ToList() }; } } internal class JournalCommand : PagedCommand { public override string Command => "rtJournal"; public override string Description => "Chest journal, newest first: who added/took what. Usage: rtJournal [item or chest] [-player name] [-near x z r] [-days n] [-offset n]"; protected override Result Produce(Args args) { //IL_0092: Unknown result type (might be due to invalid IL or missing references) string text = args.Text; long num = ((args.Days > 0f) ? (Events.Now - (long)(args.Days * 86400000f)) : 0); List<string> list = new List<string>(); for (int num2 = Tracker.Journal.Count - 1; num2 >= 0; num2--) { JournalEntry journalEntry = Tracker.Journal[num2]; if (journalEntry.T < num) { break; } if ((args.Player == null || string.Equals(journalEntry.Player, args.Player, StringComparison.OrdinalIgnoreCase)) && args.InRange(new Vector3(journalEntry.X, 0f, journalEntry.Z)) && (text.Length <= 0 || Stored.Has(journalEntry.Item, text) || Stored.Has(journalEntry.Label, text) || Stored.Has(journalEntry.ContainerLabel, text))) { list.Add(new Json().Obj().Prop("t", journalEntry.T).Prop("player", journalEntry.Player) .Prop("delta", journalEntry.Delta) .Prop("item", journalEntry.Item) .Prop("name", journalEntry.Label) .Prop("container", journalEntry.Container) .Prop("label", journalEntry.ContainerLabel) .Key("pos") .Arr() .Val(journalEntry.X) .Val(journalEntry.Z) .EndArr() .EndObj() .ToString()); } } return new Result { Items = list }; } } internal class WorldInfo : RtCommand { public override string Command => "rtWorld"; public override string Description => "World overview as JSON: day, time, active raid, global keys, players online. Usage: rtWorld"; protected override string Handle(Args args, string raw) { Json json = new Json().Obj(); if ((Object)(object)EnvMan.instance != (Object)null) { int num = (int)(EnvMan.instance.GetDayFraction() * 24f * 60f); json.Prop("day", EnvMan.instance.GetDay()).Prop("time", $"{num / 60:00}:{num % 60:00}"); } RandEventSystem instance = RandEventSystem.instance; RandomEvent val = (((Object)(object)instance != (Object)null) ? (instance.GetCurrentRandomEvent() ?? instance.m_forcedEvent) : null); json.Key("raid"); if (val != null) { json.Val(val.m_name); } else { json.Null(); } json.Key("globalKeys").Arr(); foreach (string globalKey in ZoneSystem.instance.GetGlobalKeys()) { json.Val(globalKey); } json.EndArr(); json.Prop("players", ZNet.instance.GetPeers().Count).Prop("objects", ZDOMan.instance.m_objectsByID.Count).Prop("indexScanMs", WorldIndex.LastScanMs) .Prop("boot", Events.Boot) .Prop("seq", Events.Seq) .EndObj(); return json.ToString(); } } internal class Players : PagedCommand { public override string Command => "rtPlayers"; public override string Description => "Online players as JSON with position, biome and health. Usage: rtPlayers"; protected override Result Produce(Args args) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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) //IL_0093: Unknown result type (might be due to invalid IL or missing references) List<string> list = new List<string>(); foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { ZDO zDO = ZDOMan.instance.GetZDO(peer.m_characterID); Vector3 val = ((zDO != null) ? zDO.GetPosition() : peer.m_refPos); Json json = new Json().Obj().Prop("name", peer.m_playerName); ISocket socket = peer.m_socket; Json json2 = json.Prop("host", (socket != null) ? socket.GetHostName() : null).Key("pos").Pos(val) .Prop("biome", World.Biome(val)); if (zDO != null) { long num = zDO.GetLong(ZDOVars.s_playerID, 0L); PlayerNames.Learn(num, zDO.GetString(ZDOVars.s_playerName, "")); json2.Prop("playerId", num).Prop("health", zDO.GetFloat(ZDOVars.s_health, 0f)).Prop("dead", zDO.GetBool(ZDOVars.s_dead, false)); } list.Add(json2.EndObj().ToString()); } return new Result { Items = list }; } } internal class Prefabs : PagedCommand { public override string Command => "rtPrefabs"; public override string Description => "Object counts by prefab, most frequent first. Usage: rtPrefabs [-near x z radius] [-offset n]"; protected override Result Produce(Args args) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) Dictionary<string, int> dictionary = new Dictionary<string, int>(); foreach (ZDO item in World.All()) { if (args.InRange(item.GetPosition())) { string name = World.Info(item).Name; dictionary.TryGetValue(name, out var value); dictionary[name] = value + 1; } } return new Result { Items = (from kv in dictionary orderby kv.Value descending select new Json().Obj().Prop("prefab", kv.Key).Prop("count", kv.Value) .EndObj() .ToString()).ToList() }; } } internal class EventsCommand : RtCommand { public override string Command => "rtEvents"; public override string Description => "World events after a sequence number (join, leave, death, biome, boss, raid, raidEnd, chest). Usage: rtEvents [-since seq]"; protected override string Handle(Args args, string raw) { return Pager.Page(Events.Since(args.Since), 0, $"\"boot\":\"{Events.Boot}\",\"seq\":{Events.Seq}"); } } internal class Playtime : PagedCommand { public override string Command => "rtPlaytime"; public override string Description => "Play time per player (closed + ongoing sessions). Usage: rtPlaytime [-days n] [-offset n]"; protected override Result Produce(Args args) { long now = Events.Now; long cutoff = ((args.Days > 0f) ? (now - (long)(args.Days * 86400000f)) : 0); IOrderedEnumerable<(string, long, int, long)> source = from s in Tracker.Sessions.Concat(Tracker.OpenSessions()) where s.End > cutoff group s by s.Name into g select (Name: g.Key, Seconds: g.Sum((Session s) => (s.End - Math.Max(s.Start, cutoff)) / 1000), Sessions: g.Count(), LastSeen: g.Max((Session s) => s.End)) into r orderby r.Seconds descending select r; return new Result { Items = source.Select<(string, long, int, long), string>(((string Name, long Seconds, int Sessions, long LastSeen) r) => new Json().Obj().Prop("name", r.Name).Prop("seconds", r.Seconds) .Prop("sessions", r.Sessions) .Prop("lastSeen", r.LastSeen) .EndObj() .ToString()).ToList() }; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }