using System; using System.Collections.Generic; using ShrinkContext; using UnityEngine; namespace ShrinkModFramework { public sealed class ShrinkModContext { private readonly ShrinkModRegistryManager _registryManager; private readonly IReadOnlyDictionary _loadedMods; private readonly bool _verboseLogging; private readonly ShrinkCtx _effectContext; internal ShrinkModContext(ShrinkModInfo modInfo, ShrinkModRegistryManager registryManager, IReadOnlyDictionary loadedMods, bool verboseLogging, ShrinkCtx effectContext = null) { ModInfo = modInfo; _registryManager = registryManager; _loadedMods = loadedMods; _verboseLogging = verboseLogging; _effectContext = effectContext; } public ShrinkModInfo ModInfo { get; } public IReadOnlyDictionary LoadedMods => _loadedMods; public bool IsContextManaged => _effectContext != null; public IReadOnlyShrinkModRegistry GetRegistry(string name) => _registryManager.GetOrCreateRegistry(name); public bool TryGetRegistry(string name, out IReadOnlyShrinkModRegistry registry) => _registryManager.TryGetRegistry(name, out registry); /// 用当前 ModId 作为 namespace 注册内容,并返回最终完整键。 public string RegisterContent(string registryName, string localKey, T value) => _registryManager.GetOrCreateMutableRegistry(registryName) .RegisterNamespaced(ModInfo.ModId, localKey, value); /// 以当前模组为 owner 覆盖已有内容;同目标、同优先级冲突会直接失败。 public void OverrideContent(string registryName, string targetKey, int priority, T value) => _registryManager.GetOrCreateMutableRegistry(registryName) .RegisterOverride(ModInfo.ModId, targetKey, priority, value); public bool IsModLoaded(string modId) => !string.IsNullOrWhiteSpace(modId) && _loadedMods.ContainsKey(modId); public bool TryGetLoadedMod(string modId, out ShrinkModHandle handle) { if (!string.IsNullOrWhiteSpace(modId)) return _loadedMods.TryGetValue(modId, out handle); handle = null; return false; } /// /// 在模组组件上下文中执行前向动作并就地登记逆操作。逆操作随 fiber 卸载按 LIFO 执行。 /// 旧 ShrinkModLoader 路径没有可逆上下文,调用本 API 会明确失败而不是静默丢失 cleanup。 /// public void Effect(Action forward, Action inverse) { if (_effectContext == null) throw new InvalidOperationException( "ShrinkModContext.Effect requires ShrinkModContextHost. The legacy ShrinkModLoader cannot track inverses."); _effectContext.Effect(forward, inverse); } /// 为已完成的前向动作登记同步逆操作。 public void EffectInverse(Action inverse) { if (inverse == null) throw new ArgumentNullException(nameof(inverse)); Effect(() => { }, inverse); } public void Log(string message) { if (_verboseLogging) Debug.Log($"[ShrinkMod:{ModInfo.ModId}] {message}"); } public void RegisterNetworkHandler(string channel, System.Action handler) => ShrinkModNetworkManager.RegisterHandler(ModInfo.ModId, channel, handler); public void SendToServer(string channel, T payload, string senderPeerId = null) => ShrinkModNetworkManager.SendToServer(ModInfo.ModId, channel, payload, senderPeerId); public void SendToAllClients(string channel, T payload, string senderPeerId = null) => ShrinkModNetworkManager.SendToAllClients(ModInfo.ModId, channel, payload, senderPeerId); public void SendToClient(string channel, T payload, string targetPeerId, string senderPeerId = null) => ShrinkModNetworkManager.SendToClient(ModInfo.ModId, channel, payload, targetPeerId, senderPeerId); public void LogWarning(string message) => Debug.LogWarning($"[ShrinkMod:{ModInfo.ModId}] {message}"); public void LogError(string message) => Debug.LogError($"[ShrinkMod:{ModInfo.ModId}] {message}"); } }