using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using MimesisItemSpawner; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(Core), "MimesisItemSpawner", "1.0.0", "corbyn.barker", null)] [assembly: MelonGame("ReLUGames", "MIMESIS")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("MimesisItemSpawner")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: AssemblyProduct("MimesisItemSpawner")] [assembly: AssemblyTitle("MimesisItemSpawner")] [assembly: AssemblyVersion("1.0.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 MimesisItemSpawner { public class Core : MelonMod { private MelonPreferences_Entry _toggleKeyPref; private MelonPreferences_Entry _reasonPref; private MelonPreferences_Entry _amountPref; private bool _open; private bool _itemsLoaded; private string _search = ""; private string _amountText = "1"; private string _status = "Press the toggle key in-game to open."; private Vector2 _scroll; private Rect _window = new Rect(40f, 40f, 480f, 600f); private readonly List _allItems = new List(); private readonly List _filtered = new List(); private string _lastSearch; private int _pendingSpawnId = -1; private const int MaxRows = 300; private const int WindowId = 1296651088; public override void OnInitializeMelon() { MelonPreferences_Category val = MelonPreferences.CreateCategory("MimesisItemSpawner"); _toggleKeyPref = val.CreateEntry("HotKey", "F6", "Toggle key (Input System key name, e.g. F6, Backquote, F1..F12)", (string)null, false, false, (ValueValidator)null, (string)null); _reasonPref = val.CreateEntry("ReasonOfSpawn", "Admin", "Spawn reason (None/Spawn/Admin/ItemSpawn/...)", (string)null, false, false, (ValueValidator)null, (string)null); _amountPref = val.CreateEntry("DefaultAmount", 1, "Default stack amount", (string)null, false, false, (ValueValidator)null, (string)null); _amountText = _amountPref.Value.ToString(); MelonLogger.Msg("MimesisItemSpawner loaded. Toggle key: " + _toggleKeyPref.Value); } public override void OnUpdate() { if (GameBridge.WasKeyPressed(_toggleKeyPref.Value)) { _open = !_open; if (_open && !_itemsLoaded) { TryLoadItems(); } } if (_pendingSpawnId >= 0) { int pendingSpawnId = _pendingSpawnId; _pendingSpawnId = -1; DoSpawn(pendingSpawnId); } } public override void OnGUI() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (_open) { _window = GUI.Window(1296651088, _window, new WindowFunction(DrawWindow), "Mimesis Item Spawner"); } } private void TryLoadItems() { if (!GameBridge.EnsureReady(out var error)) { _status = "Cannot load items: " + error; return; } try { _allItems.Clear(); _allItems.AddRange(GameBridge.GetAllItems()); _itemsLoaded = _allItems.Count > 0; _lastSearch = null; _status = (_itemsLoaded ? $"Loaded {_allItems.Count} items." : "Item table not ready yet (enter a session, then Refresh)."); } catch (Exception ex) { _status = "Error loading items: " + ex.Message; MelonLogger.Error((object)ex); } } private void RebuildFilter() { if (_lastSearch == _search) { return; } _lastSearch = _search; _filtered.Clear(); string text = _search?.Trim(); bool flag = string.IsNullOrEmpty(text); string value = (flag ? null : text.ToLowerInvariant()); foreach (GameBridge.ItemEntry allItem in _allItems) { if (flag || allItem.Id.ToString().Contains(text) || (allItem.Name != null && allItem.Name.ToLowerInvariant().Contains(value)) || (allItem.Display != null && allItem.Display.ToLowerInvariant().Contains(value))) { _filtered.Add(allItem); if (_filtered.Count >= 300) { break; } } } } private void DrawWindow(int id) { //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) GUILayout.Space(4f); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("Search:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }); _search = GUILayout.TextField(_search ?? "", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(250f) }); if (GUILayout.Button("Refresh", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) })) { TryLoadItems(); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("Amount:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }); _amountText = GUILayout.TextField(_amountText ?? "1", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }); GUILayout.FlexibleSpace(); GUILayout.Label(_itemsLoaded ? $"{_allItems.Count} items" : "not loaded", Array.Empty()); GUILayout.EndHorizontal(); GUILayout.Space(4f); GUILayout.Label(_status, Array.Empty()); GUILayout.Space(2f); RebuildFilter(); if (_filtered.Count >= 300) { GUILayout.Label($"Showing first {300} matches — refine search.", Array.Empty()); } _scroll = GUILayout.BeginScrollView(_scroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(440f) }); foreach (GameBridge.ItemEntry item in _filtered) { if (GUILayout.Button($"[{item.Id}] {item.Display}", Array.Empty())) { _pendingSpawnId = item.Id; _status = $"Spawning [{item.Id}] {item.Display} ..."; } } if (_filtered.Count == 0) { GUILayout.Label(_itemsLoaded ? "No matches." : "Open a session and press Refresh.", Array.Empty()); } GUILayout.EndScrollView(); GUILayout.Space(4f); GUILayout.BeginHorizontal(Array.Empty()); if (GUILayout.Button("Close", Array.Empty())) { _open = false; } GUILayout.EndHorizontal(); GUI.DragWindow(); } private void DoSpawn(int id) { int result = 1; int.TryParse(_amountText, out result); if (result < 1) { result = 1; } if (!GameBridge.EnsureReady(out var error)) { _status = "Not ready: " + error; return; } string message; bool flag = GameBridge.SpawnItem(id, result, _reasonPref.Value, out message); _status = message ?? (flag ? "Spawned." : "Spawn failed."); if (flag) { MelonLogger.Msg(message); } else { MelonLogger.Warning(message); } } } internal static class GameBridge { public struct ItemEntry { public int Id; public string Name; public string Display; } private const BindingFlags AnyInstance = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private const BindingFlags AnyStatic = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private static Assembly _gameAsm; private static Type _hubType; private static Type _ivroomType; private static Type _posWithRotType; private static Type _reasonType; private static bool _inputResolved; private static Type _keyboardType; private static Type _keyEnumType; private static PropertyInfo _keyboardCurrent; private static MethodInfo _keyboardIndexer; private static void ResolveInput() { if (_inputResolved) { return; } _inputResolved = true; Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "Unity.InputSystem"); if (!(assembly == null)) { _keyboardType = assembly.GetType("UnityEngine.InputSystem.Keyboard"); _keyEnumType = assembly.GetType("UnityEngine.InputSystem.Key"); if (!(_keyboardType == null) && !(_keyEnumType == null)) { _keyboardCurrent = _keyboardType.GetProperty("current", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); _keyboardIndexer = _keyboardType.GetMethod("get_Item", new Type[1] { _keyEnumType }); } } } public static bool WasKeyPressed(string keyName) { ResolveInput(); if (_keyboardCurrent == null || _keyboardIndexer == null) { return false; } try { object value = _keyboardCurrent.GetValue(null); if (value == null) { return false; } object obj; try { obj = Enum.Parse(_keyEnumType, keyName, ignoreCase: true); } catch { obj = Enum.Parse(_keyEnumType, "F6", ignoreCase: true); } object obj3 = _keyboardIndexer.Invoke(value, new object[1] { obj }); if (obj3 == null) { return false; } PropertyInfo property = obj3.GetType().GetProperty("wasPressedThisFrame", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); return property != null && (bool)property.GetValue(obj3); } catch { return false; } } public static bool EnsureReady(out string error) { error = null; if (_gameAsm == null) { _gameAsm = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "Assembly-CSharp"); if (_gameAsm == null) { error = "Assembly-CSharp not loaded yet."; return false; } } if ((object)_hubType == null) { _hubType = _gameAsm.GetType("Hub"); } if ((object)_ivroomType == null) { _ivroomType = _gameAsm.GetType("IVroom"); } if ((object)_posWithRotType == null) { _posWithRotType = _gameAsm.GetType("ReluProtocol.PosWithRot"); } if ((object)_reasonType == null) { _reasonType = _gameAsm.GetType("ReluProtocol.Enum.ReasonOfSpawn"); } if (_hubType == null) { error = "Hub type not found."; return false; } if (_ivroomType == null) { error = "IVroom type not found."; return false; } if (_posWithRotType == null) { error = "PosWithRot type not found."; return false; } if (_reasonType == null) { error = "ReasonOfSpawn type not found."; return false; } return true; } private static object GetHub() { return _hubType.GetField("s", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null); } private static object GetField(object obj, string name) { if (obj == null) { return null; } Type type = obj.GetType(); while (type != null) { FieldInfo field = type.GetField(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field.GetValue(obj); } type = type.BaseType; } return null; } private static object GetFieldOn(Type declaring, object obj, string name) { return declaring.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj); } private static object GetProp(object obj, string name) { if (obj == null) { return null; } Type type = obj.GetType(); while (type != null) { PropertyInfo property = type.GetProperty(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { return property.GetValue(obj); } type = type.BaseType; } return null; } private static object GetVWorld() { return GetField(GetHub(), "k__BackingField"); } private static int GetMyActorId(out object hub, out object pdata) { hub = GetHub(); pdata = GetField(hub, "pdata"); if (pdata == null) { return 0; } FieldInfo field = pdata.GetType().GetField("MyActorID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(field != null)) { return 0; } return (int)field.GetValue(pdata); } private static bool GetLocalRoomAndPlayer(out object room, out object player, out string error) { room = null; player = null; error = null; object vWorld = GetVWorld(); if (vWorld == null) { error = "Not in game yet (no VWorld). Join/host a session first."; return false; } object field = GetField(vWorld, "_vRoomManager"); if (field == null) { error = "No room manager (host the session to spawn)."; return false; } if (!(GetField(field, "_vrooms") is IDictionary { Count: not 0 } dictionary)) { error = "No active rooms found."; return false; } object hub; object pdata; int myActorId = GetMyActorId(out hub, out pdata); if (myActorId == 0) { error = "Local actor id is 0 (not spawned in a room yet)."; return false; } foreach (object value in dictionary.Values) { object fieldOn = GetFieldOn(_ivroomType, value, "_vPlayerDict"); if (fieldOn == null) { continue; } MethodInfo method = fieldOn.GetType().GetMethod("FindActor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(method == null)) { object obj = method.Invoke(fieldOn, new object[1] { myActorId }); if (obj != null) { room = value; player = obj; return true; } } } IEnumerator enumerator = dictionary.Values.GetEnumerator(); try { if (enumerator.MoveNext()) { object current2 = enumerator.Current; room = current2; } } finally { IDisposable disposable = enumerator as IDisposable; if (disposable != null) { disposable.Dispose(); } } if (room == null) { error = "Could not resolve a room for the local player."; return false; } return true; } public static List GetAllItems() { List list = new List(); object hub = GetHub(); object field = GetField(hub, "k__BackingField"); if (field == null) { return list; } object prop = GetProp(field, "ExcelDataManager"); if (prop == null) { return list; } if (!(GetProp(prop, "ItemInfoDict") is IEnumerable enumerable)) { return list; } object field2 = GetField(hub, "pdata"); MethodInfo methodInfo = field2?.GetType().GetMethod("GetItemDisplayName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo method = _hubType.GetMethod("GetL10NText", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (object item in enumerable) { Type type = item.GetType(); object obj = type.GetProperty("Key")?.GetValue(item); object obj2 = type.GetProperty("Value")?.GetValue(item); if (obj == null || obj2 == null) { continue; } int num = (int)obj; string text = (obj2.GetType().GetField("Name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj2) as string) ?? num.ToString(); string text2 = text; try { if (methodInfo != null) { string text3 = methodInfo.Invoke(field2, new object[2] { num, text }) as string; if (!string.IsNullOrEmpty(text3)) { text2 = text3; } } if (method != null) { string text4 = method.Invoke(null, new object[1] { text2 }) as string; if (!string.IsNullOrEmpty(text4)) { text2 = text4; } } } catch { } list.Add(new ItemEntry { Id = num, Name = text, Display = text2 }); } list.Sort((ItemEntry a, ItemEntry b) => a.Id.CompareTo(b.Id)); return list; } public static bool SpawnItem(int masterId, int qty, string reasonName, out string message) { message = null; try { if (!GetLocalRoomAndPlayer(out var room, out var player, out var error)) { message = error; return false; } MethodInfo method = _ivroomType.GetMethod("GetNewItemElement", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { message = "GetNewItemElement not found."; return false; } object obj = method.Invoke(room, new object[6] { masterId, false, Math.Max(1, qty), 0, 0, 0 }); if (obj == null) { message = $"Item {masterId} is invalid (GetNewItemElement returned null)."; return false; } object obj2 = Activator.CreateInstance(_posWithRotType); bool flag = false; if (player != null) { object prop = GetProp(player, "PositionVector"); if (prop != null) { _posWithRotType.GetMethod("set_pos", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(obj2, new object[1] { prop }); } if (GetProp(player, "IsIndoor") is bool flag2) { flag = flag2; } } object obj3; try { obj3 = Enum.Parse(_reasonType, reasonName, ignoreCase: true); } catch { obj3 = Enum.ToObject(_reasonType, 8); } MethodInfo method2 = _ivroomType.GetMethod("SpawnLootingObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method2 == null) { message = "SpawnLootingObject not found."; return false; } int num = ((method2.Invoke(room, new object[9] { obj, obj2, flag, obj3, 0, 0, 0L, false, false }) is int num2) ? num2 : 0); if (num == 0) { message = $"Spawn rejected by game for item {masterId}."; return false; } message = $"Spawned item {masterId} x{Math.Max(1, qty)} (objId {num})."; return true; } catch (Exception ex) { message = "Spawn error: " + ex.Message; MelonLogger.Error((object)ex); return false; } } } }