From f12d911871f1d0bb7d326053b6d46a46b4a33b26 Mon Sep 17 00:00:00 2001 From: "@Someone" <45270312+Someone-193@users.noreply.github.com> Date: Mon, 23 Jun 2025 14:44:42 -0400 Subject: [PATCH 1/5] Required fix (for me) --- ProjectMER.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/ProjectMER.csproj b/ProjectMER.csproj index 18ec451..cf39bfb 100644 --- a/ProjectMER.csproj +++ b/ProjectMER.csproj @@ -22,6 +22,7 @@ + From a8240c50010516ffc7cedeaf036e4c0eae3f0330 Mon Sep 17 00:00:00 2001 From: "@Someone" <45270312+Someone-193@users.noreply.github.com> Date: Sat, 6 Sep 2025 19:18:37 -0400 Subject: [PATCH 2/5] Add the actual features --- Features/Extensions/ExiledExtensions.cs | 135 ++++++++++++++++++ .../Schematics/SchematicBlockData.cs | 12 +- .../SerializableItemSpawnpoint.cs | 10 +- ProjectMER.cs | 4 + 4 files changed, 159 insertions(+), 2 deletions(-) create mode 100644 Features/Extensions/ExiledExtensions.cs diff --git a/Features/Extensions/ExiledExtensions.cs b/Features/Extensions/ExiledExtensions.cs new file mode 100644 index 0000000..651a613 --- /dev/null +++ b/Features/Extensions/ExiledExtensions.cs @@ -0,0 +1,135 @@ +using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using InventorySystem.Items.Pickups; +using LabApi.Features.Wrappers; +using LabApi.Loader; +using LabApi.Loader.Features.Plugins; +using UnityEngine; +namespace ProjectMER.Features.Extensions +{ + public static class ExiledExtensions + { + private static Assembly? ExiledLoaderAssembly; + + private static MethodInfo? CustomItemTrySpawnMethodInfo; + + private static MethodInfo? PickupGetBaseMethodInfo; + + public static Pickup? TrySpawn(string customItemName, Vector3 position, Quaternion rotation, Vector3 scale) + { + if (!TrySpawnCustomItem(customItemName, position, out Pickup? pickup)) + return null; + + pickup.Rotation = rotation; + pickup.Transform.localScale = scale; + + return pickup; + } + + internal static bool TrySpawnCustomItem(string name, Vector3 position, [NotNullWhen(true)] out Pickup? pickup) + { + pickup = null; + + if (CustomItemTrySpawnMethodInfo is null) + return false; + + object?[] args = [name, position, null]; + + CustomItemTrySpawnMethodInfo.Invoke(null, args); + + if (args[2] is null) + return false; + + pickup = GetPickupFromExiledPickup(args[2]!); + + return pickup is not null; + } + + + internal static Pickup? GetPickupFromExiledPickup(object pickup) + { + if (PickupGetBaseMethodInfo is null) + return null; + + object obj = PickupGetBaseMethodInfo.Invoke(pickup, []); + + if (obj is not ItemPickupBase pickupBase) + { + Logger.Warn("Failed to get ItemPickupBase from Exiled Pickup"); + return null; + } + + return Pickup.Get(pickupBase); + } + + internal static void TryInitialize() + { + const string ErrorMessage = "Failed to find a component of Exiled! This can be ignored if you do not use Exiled Custom Items in ProjectMER. Cause: "; + + KeyValuePair kvp = PluginLoader.Plugins.FirstOrDefault(kvp => kvp.Key.Name is "Exiled Loader"); + + if (kvp.Value is null) + { + // No debug in config :( + // not printed because ppl can just not use Exiled, but having Exiled.Loader and not API / CI is suspicious + // Logger.Debug(ErrorMessage + "Failed to get ExiledLoader Plugin"); + return; + } + + ExiledLoaderAssembly = kvp.Value; + + object? plugin = ExiledLoaderAssembly.GetType("Exiled.Loader.Loader")?.GetMethod("GetPlugin")?.Invoke(null, ["exiled_custom_items"]); + + if (plugin is null) + { + // It's possible people use Exiled without CI, so I'll leave this out too + // Logger.Debug(ErrorMessage + "Failed to get CustomItems Plugin"); + return; + } + + object? nullableAssembly = plugin.GetType().GetProperty("Assembly")?.GetValue(plugin); + + if (nullableAssembly is not Assembly customItemAssembly) + { + Logger.Warn(ErrorMessage + "Failed to get CustomItems Assembly"); + return; + } + + Type? customItem = customItemAssembly.GetType("Exiled.CustomItems.API.Features.CustomItem"); + + if (customItem is null) + { + Logger.Warn(ErrorMessage + "Failed to get CustomItem Type"); + return; + } + + CustomItemTrySpawnMethodInfo = customItem.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(method => method.Name is "TrySpawn" && method.GetParameters().Any(parameter => parameter.ParameterType == typeof(string))); + + if (CustomItemTrySpawnMethodInfo is null) + Logger.Warn(ErrorMessage + "Failed to get CustomItem.TrySpawn method"); + + Assembly? apiAssembly = PluginLoader.Dependencies.FirstOrDefault(assembly => assembly.GetName().Name is "Exiled.API"); + + if (apiAssembly is null) + { + Logger.Warn(ErrorMessage + "Failed to get Exiled.API Assembly"); + return; + } + + Type? pickupType = apiAssembly.GetType("Exiled.API.Features.Pickups.Pickup"); + + if (pickupType is null) + { + Logger.Warn(ErrorMessage + "Failed to get Pickup Type"); + return; + } + + PickupGetBaseMethodInfo = pickupType.GetProperty("Base")?.GetGetMethod(); + + if (PickupGetBaseMethodInfo is null) + { + Logger.Warn(ErrorMessage + "Failed to get Pickup::Base getter method"); + } + } + } +} \ No newline at end of file diff --git a/Features/Serializable/Schematics/SchematicBlockData.cs b/Features/Serializable/Schematics/SchematicBlockData.cs index 5e2ae64..1878fb1 100644 --- a/Features/Serializable/Schematics/SchematicBlockData.cs +++ b/Features/Serializable/Schematics/SchematicBlockData.cs @@ -143,7 +143,17 @@ private GameObject CreatePickup(SchematicObject schematicObject) if (Properties.TryGetValue("Chance", out object property) && UnityEngine.Random.Range(0, 101) > Convert.ToSingle(property)) return new("Empty Pickup"); - Pickup pickup = Pickup.Create((ItemType)Convert.ToInt32(Properties["ItemType"]), Vector3.zero)!; + Pickup? pickup = null; + if (Properties["CustomItem"] is string str && str != string.Empty) + { + ExiledExtensions.TrySpawnCustomItem(str, Vector3.zero, out pickup); + } + + pickup ??= Pickup.Create((ItemType)Convert.ToInt32(Properties["ItemType"]), Vector3.zero); + + if (pickup is null) + return new("Empty Pickup"); + if (Properties.ContainsKey("Locked")) PickupEventsHandler.ButtonPickups.Add(pickup.Serial, schematicObject); diff --git a/Features/Serializable/SerializableItemSpawnpoint.cs b/Features/Serializable/SerializableItemSpawnpoint.cs index d1eae85..f412c84 100644 --- a/Features/Serializable/SerializableItemSpawnpoint.cs +++ b/Features/Serializable/SerializableItemSpawnpoint.cs @@ -14,6 +14,7 @@ namespace ProjectMER.Features.Serializable; public class SerializableItemSpawnpoint : SerializableObject, IIndicatorDefinition { public ItemType ItemType { get; set; } = ItemType.Lantern; + public string CustomItem { get; set; } = string.Empty; public float Weight { get; set; } = -1; public string AttachmentsCode { get; set; } = "-1"; public uint NumberOfItems { get; set; } = 1; @@ -41,7 +42,14 @@ public class SerializableItemSpawnpoint : SerializableObject, IIndicatorDefiniti for (int i = 0; i < NumberOfItems; i++) { - Pickup pickup = Pickup.Create(ItemType, position, rotation, Scale)!; + Pickup? pickup = CustomItem != string.Empty ? ExiledExtensions.TrySpawn(CustomItem, position, rotation, Scale) : Pickup.Create(ItemType, position, rotation, Scale); + + if (pickup is null) + { + // there is no Debug config option? + // Logger.Debug($"Failed to spawn an item with CustomItem: {CustomItem}", true); + continue; + } pickup.Transform.parent = itemSpawnPoint.transform; if (Weight != -1) diff --git a/ProjectMER.cs b/ProjectMER.cs index 330c7bb..78b6521 100644 --- a/ProjectMER.cs +++ b/ProjectMER.cs @@ -8,6 +8,7 @@ using ProjectMER.Configs; using ProjectMER.Events.Handlers.Internal; using ProjectMER.Features; +using ProjectMER.Features.Extensions; namespace ProjectMER; @@ -90,6 +91,9 @@ public override void Enable() Logger.Debug("FileSystemWatcher enabled!"); } + + // plugin loading is synchronous (minus exiled delaying 1 tick), so after all plugins loaded, try checking for Exiled and Exiled CI + Timing.CallDelayed(1, ExiledExtensions.TryInitialize); } private void OnMapFileChanged(object _, FileSystemEventArgs ev) From 0b81c92cfac371ef24ce72de8654f66e77ed887a Mon Sep 17 00:00:00 2001 From: "@Someone" <45270312+Someone-193@users.noreply.github.com> Date: Sat, 6 Sep 2025 19:19:38 -0400 Subject: [PATCH 3/5] remove fix :( --- ProjectMER.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/ProjectMER.csproj b/ProjectMER.csproj index cf39bfb..18ec451 100644 --- a/ProjectMER.csproj +++ b/ProjectMER.csproj @@ -22,7 +22,6 @@ - From 26ac1053e84702d7984fa9ce7ea4d9c1bc74224e Mon Sep 17 00:00:00 2001 From: "@Someone" <45270312+Someone-193@users.noreply.github.com> Date: Sat, 6 Sep 2025 19:23:48 -0400 Subject: [PATCH 4/5] remove unnecessary static field --- Features/Extensions/ExiledExtensions.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Features/Extensions/ExiledExtensions.cs b/Features/Extensions/ExiledExtensions.cs index 651a613..00d65ff 100644 --- a/Features/Extensions/ExiledExtensions.cs +++ b/Features/Extensions/ExiledExtensions.cs @@ -9,8 +9,6 @@ namespace ProjectMER.Features.Extensions { public static class ExiledExtensions { - private static Assembly? ExiledLoaderAssembly; - private static MethodInfo? CustomItemTrySpawnMethodInfo; private static MethodInfo? PickupGetBaseMethodInfo; @@ -76,9 +74,9 @@ internal static void TryInitialize() return; } - ExiledLoaderAssembly = kvp.Value; + Assembly? exiledLoaderAssembly = kvp.Value; - object? plugin = ExiledLoaderAssembly.GetType("Exiled.Loader.Loader")?.GetMethod("GetPlugin")?.Invoke(null, ["exiled_custom_items"]); + object? plugin = exiledLoaderAssembly.GetType("Exiled.Loader.Loader")?.GetMethod("GetPlugin")?.Invoke(null, ["exiled_custom_items"]); if (plugin is null) { From 40e97f8fcdf2d250b2e941bf6c2764ee4d3f2563 Mon Sep 17 00:00:00 2001 From: "@Someone" <45270312+Someone-193@users.noreply.github.com> Date: Tue, 9 Dec 2025 12:04:20 -0500 Subject: [PATCH 5/5] Squashed commit of the following: commit f04e2684613cc570bd80dc741981d687dcb207ee Author: Michal78900 <75911188+Michal78900@users.noreply.github.com> Date: Sun Nov 2 12:54:54 2025 +0100 Bump commit 70072702ccba252e114672fd55a02ef4f68bb3ac Author: Michal78900 <75911188+Michal78900@users.noreply.github.com> Date: Wed Sep 17 14:26:36 2025 +0200 Bump --- ProjectMER.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ProjectMER.cs b/ProjectMER.cs index 78b6521..bf43646 100644 --- a/ProjectMER.cs +++ b/ProjectMER.cs @@ -135,7 +135,7 @@ public override void Disable() public override string Author => "Michal78900"; - public override Version Version => new Version(2025, 8, 4, 2); + public override Version Version => new Version(2025, 11, 2, 1); public override Version RequiredApiVersion => new Version(1, 0, 0, 0); }