禁用模组逻辑
-
单机启用按钮 -> 触发
Terraria.ModLoader.UI.Enable方法1 2 3 4 5 6internal void Enable() { if (_mod.Enabled) { return; } _mod.Enabled = true; UpdateUIForEnabledChange(); }_mod类型是internal Terraria.ModLoader.Core.LocalMod,其中Enabled是一个属性1 2 3 4public bool Enabled { get => ModLoader.IsEnabled(Name); set => ModLoader.SetModEnabled(Name, value); }其调用
ModLoader的IsEnabled / SetModEnabled方法1 2 3internal static bool IsEnabled(string modName) => EnabledMods.Contains(modName); internal static void EnableMod(string modName) => SetModEnabled(modName, true); internal static void DisableMod(string modName) => SetModEnabled(modName, false);1 2 3 4 5 6 7 8 9 10 11 12 13internal static void SetModEnabled(string modName, bool active) { if (active == IsEnabled(modName)) return; Logging.tML.Info($"{(active ? "Enabling" : "Disabling")} Mod: {modName}"); if (active) EnabledMods.Add(modName); else EnabledMods.Remove(modName); ModOrganizer.SaveEnabledMods(); }
UIMods实例在那里?
-
Terraria.ModLoader.UI.Interface注意 此类访问修饰符为internal1internal static UIMods modsMenu = new UIMods(); -
获取此实例
- 获取类
1 2 3Type type = typeof(Main) .Assembly.GetTypes() .FirstOrDefault(type => type.FullName.Contains("Terraria.ModLoader.UI.Interface"));- 通过类获取实例,因为是静态成员,直接获取即可
1 2FieldInfo field = type.GetField("modsMenu", BindingFlags.NonPublic | BindingFlags.Static); object modsMenu = field.GetValue(null); -
UIMods包含什么?
- 启用全部模组
- 禁用全部模组
- 重新加载模组
如何在自己模组被加载时,禁用其他模组?
-
通过调用
ModLoader.DisableMod方法,可以禁用模组,但是在加载完成后需要进入模组管理重新加载我们可以在静态构造 / Mod主类的
Load()执行代码1 2typeof(ModLoader).GetMethod("DisableMod", BindingFlags.NonPublic | BindingFlags.Static) .Invoke(null, ["模组名称"]); -
我们可以这样禁用后,通过反射调用重新加载,让禁用生效
重新加载应该在最后阶段调用
PostSetupContentModSystem / Mod1 2 3 4 5 6 7BindingFlags BSN = BindingFlags.Static | BindingFlags.NonPublic; //反射过滤 Type type = typeof(ModLoader);//获取类型 type.GetMethod("DisableMod", BSN).Invoke(null, ["模组名称"]);//禁用模组 if (ModLoader.TryGetMod("目标模组名", out _)) {//重加载 type.GetField("isLoading", BSN).SetValue(null, false); type.GetMethod("Load", BSN).Invoke(null, [null]); }