tModLoader 禁用给定模组

禁用模组逻辑

  1. 单机启用按钮 -> 触发Terraria.ModLoader.UI.Enable方法

    1
    2
    3
    4
    5
    6
    
    internal void Enable()
    {
    	if (_mod.Enabled) { return; }
    	_mod.Enabled = true;
    	UpdateUIForEnabledChange();
    }
    

    _mod类型是internal Terraria.ModLoader.Core.LocalMod,其中Enabled是一个属性

    1
    2
    3
    4
    
    public bool Enabled {
    	get => ModLoader.IsEnabled(Name);
    	set => ModLoader.SetModEnabled(Name, value);
    }
    

    其调用ModLoader的IsEnabled / SetModEnabled方法

    1
    2
    3
    
    internal 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
    13
    
    internal 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实例在那里?

  1. Terraria.ModLoader.UI.Interface 注意 此类访问修饰符为internal

    1
    
    internal static UIMods modsMenu = new UIMods();
    
  2. 获取此实例

    • 获取类
    1
    2
    3
    
    Type type = typeof(Main)
        .Assembly.GetTypes()
        .FirstOrDefault(type => type.FullName.Contains("Terraria.ModLoader.UI.Interface"));
    
    • 通过类获取实例,因为是静态成员,直接获取即可
    1
    2
    
    FieldInfo field = type.GetField("modsMenu", BindingFlags.NonPublic | BindingFlags.Static);
    object modsMenu = field.GetValue(null);
    
  3. UIMods包含什么?

    • 启用全部模组
    • 禁用全部模组
    • 重新加载模组

如何在自己模组被加载时,禁用其他模组?

  1. 通过调用ModLoader.DisableMod方法,可以禁用模组,但是在加载完成后需要进入模组管理重新加载

    我们可以在静态构造 / Mod主类的Load() 执行代码

    1
    2
    
    typeof(ModLoader).GetMethod("DisableMod", BindingFlags.NonPublic | BindingFlags.Static)
        	.Invoke(null, ["模组名称"]);
    
  2. 我们可以这样禁用后,通过反射调用重新加载,让禁用生效

    重新加载应该在最后阶段调用PostSetupContent ModSystem / Mod

    1
    2
    3
    4
    5
    6
    7
    
    BindingFlags 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]);
    }
    
使用 Hugo 构建
主题 StackJimmy 设计