using System; using System.Linq; using System.Reflection; using ShrinkEventBus; using UnityEngine; namespace ShrinkModFramework { internal static class ShrinkModOptionalRuntimeIntegration { public static IDisposable RegisterModInstance(IShrinkMod modInstance, ShrinkModInfo modInfo, bool verboseLogging) { if (modInstance == null || modInfo == null) return null; var modType = modInstance.GetType(); var eventBinding = TryAttachEventBusInstance(modType, modInstance, modInfo.ModId, verboseLogging); TryRegisterCommandInstance(modType, modInstance, modInfo.ModId, verboseLogging); TryRegisterNetworkInstance(modType, modInstance, modInfo.ModId, verboseLogging); return eventBinding; } public static void RefreshGlobalBindings(bool verboseLogging) { TryRefreshNetworkEventBusBridge(verboseLogging); } public static IDisposable TryAttachEventBusInstance(Type modType, object modInstance, string modId, bool verboseLogging) { if (modInstance is not IShrinkGeneratedSubscriber) return null; try { var busKey = ShrinkBusKey.Mod(modId); EventBus.GetOrCreateBus(busKey, ShrinkBusOptions.DedicatedThread()); var binding = EventBus.Attach(modInstance, busKey); if (verboseLogging) Debug.Log($"[ShrinkModFramework] 模组 {modId} 已接入 ShrinkEventBus 实例订阅。"); return binding; } catch (Exception ex) { Debug.LogWarning($"[ShrinkModFramework] 模组 {modId} 接入 ShrinkEventBus 失败:{ex.Message}"); return null; } } private static void TryRegisterCommandInstance(Type modType, object modInstance, string modId, bool verboseLogging) { if (!HasAttribute(modType, "ShrinkCommand.ShrinkCommandSubscriberAttribute", "ShrinkCommand.Runtime")) return; try { var runtimeType = FindType("ShrinkCommand.ShrinkCommandRuntime", "ShrinkCommand.Runtime"); var service = runtimeType?.GetProperty("Default", BindingFlags.Public | BindingFlags.Static)?.GetValue(null); var registerMethod = service?.GetType().GetMethod("RegisterCommands", BindingFlags.Public | BindingFlags.Instance, null, new[] { typeof(object) }, null); if (registerMethod == null) return; registerMethod.Invoke(service, new[] { modInstance }); if (verboseLogging) Debug.Log($"[ShrinkModFramework] 模组 {modId} 已接入 ShrinkCommand 默认服务。"); } catch (Exception ex) { Debug.LogWarning($"[ShrinkModFramework] 模组 {modId} 接入 ShrinkCommand 失败:{ex.Message}"); } } private static void TryRegisterNetworkInstance(Type modType, object modInstance, string modId, bool verboseLogging) { if (!HasAttribute(modType, "ShrinkNetwork.ShrinkNetworkSubscriberAttribute", "ShrinkNetwork.Runtime")) return; try { var runtimeType = FindType("ShrinkNetwork.ShrinkNetworkRuntime", "ShrinkNetwork.Runtime"); var service = runtimeType?.GetProperty("Default", BindingFlags.Public | BindingFlags.Static)?.GetValue(null); var registerMethod = service?.GetType().GetMethod("RegisterHandlers", BindingFlags.Public | BindingFlags.Instance, null, new[] { typeof(object) }, null); if (registerMethod == null) return; registerMethod.Invoke(service, new[] { modInstance }); if (verboseLogging) Debug.Log($"[ShrinkModFramework] 模组 {modId} 已接入 ShrinkNetwork 默认服务。"); } catch (Exception ex) { Debug.LogWarning($"[ShrinkModFramework] 模组 {modId} 接入 ShrinkNetwork 失败:{ex.Message}"); } } private static void TryRefreshNetworkEventBusBridge(bool verboseLogging) { try { var bridgeType = FindType("ShrinkNetwork.Integration.ShrinkNetworkEventBusBridge", "ShrinkNetwork.Integration.EventBus"); var refreshMethod = bridgeType?.GetMethod("RefreshBindings", BindingFlags.Public | BindingFlags.Static, null, Type.EmptyTypes, null); if (refreshMethod == null) return; refreshMethod.Invoke(null, null); if (verboseLogging) Debug.Log("[ShrinkModFramework] 已刷新 ShrinkNetwork.Integration.EventBus 绑定。"); } catch (Exception ex) { Debug.LogWarning($"[ShrinkModFramework] 刷新 ShrinkNetwork.Integration.EventBus 绑定失败:{ex.Message}"); } } private static bool HasAttribute(Type targetType, string attributeFullName, string assemblyName) { var attributeType = FindType(attributeFullName, assemblyName); return attributeType != null && targetType.GetCustomAttribute(attributeType, false) != null; } private static Type FindType(string fullName, string assemblyName) { return Type.GetType($"{fullName}, {assemblyName}", false) ?? AppDomain.CurrentDomain.GetAssemblies() .Where(assembly => string.Equals(assembly.GetName().Name, assemblyName, StringComparison.Ordinal)) .Select(assembly => assembly.GetType(fullName, false)) .FirstOrDefault(type => type != null); } } }