diff --git a/ammo/component.py b/ammo/component.py index e998ed6..c0e8c7d 100755 --- a/ammo/component.py +++ b/ammo/component.py @@ -37,6 +37,7 @@ class Mod: fomod: bool = field(init=False, default=False) enabled: bool = field(init=False, default=False) conflict: bool = field(init=False, default=False) + obsolete: bool = field(init=False, default=True) files: list[Path] = field(default_factory=list, init=False) plugins: list[str] = field(default_factory=list, init=False) name: str = field(default_factory=str, init=False) diff --git a/ammo/mod_controller.py b/ammo/mod_controller.py index 9771984..6f33c00 100755 --- a/ammo/mod_controller.py +++ b/ammo/mod_controller.py @@ -236,7 +236,11 @@ def __str__(self) -> str: if mod.visible: priority = f"[{i}]" enabled = f"[{mod.enabled}]" - conflict = "*" if mod.conflict else " " + conflict = ( + "x" + if mod.enabled and mod.obsolete + else ("*" if mod.conflict else " ") + ) result += f"{priority:<7} {enabled:<9} {conflict:<1} {mod.name}\n" if len([i for i in self.plugins if i.visible]): @@ -424,6 +428,7 @@ def _stage(self) -> dict: # Iterate through enabled mods in order. for mod in self.mods: mod.conflict = False + mod.obsolete = True enabled_mods = [i for i in self.mods if i.enabled] for index, mod in enumerate(enabled_mods): # Iterate through the source files of the mod @@ -450,6 +455,13 @@ def _stage(self) -> dict: conflicting_mod[0].conflict = True result[dest] = (mod.name, src) + # Record whether a mod is obsolete (all files are overwritten by other mods). + for mod in enabled_mods: + for name, src in result.values(): + if name == mod.name: + mod.obsolete = False + break + plugin_names = [] for mod in self.mods: if mod.enabled: @@ -902,6 +914,7 @@ def move(self, component: ComponentEnum, index: int, new_index: int) -> None: raise Warning("Index out of range.") comp = components.pop(index) components.insert(new_index, comp) + self._stage() self.changes = True def commit(self) -> None: diff --git a/test/test_conflict_resolution.py b/test/test_conflict_resolution.py index 3c53525..04eb755 100755 --- a/test/test_conflict_resolution.py +++ b/test/test_conflict_resolution.py @@ -394,3 +394,34 @@ def test_collisions(): with pytest.raises(Warning) as warning: controller.collisions(normal_mod) assert warning.value.args == ("No conflicts.",) + + +def test_obsolete_init(): + """ + Test that mods are properly marked as obsolete on move/enable/disable. + """ + with AmmoController() as controller: + for mod in ["conflict_1", "conflict_2", "normal_mod"]: + install_mod(controller, mod) + + conflict_1 = [i.name for i in controller.mods].index("conflict_1") + conflict_2 = [i.name for i in controller.mods].index("conflict_2") + normal_mod = [i.name for i in controller.mods].index("normal_mod") + + assert controller.mods[conflict_1].obsolete is True + assert controller.mods[conflict_2].obsolete is False + assert controller.mods[normal_mod].obsolete is False + + # perform a move + controller.move(ComponentEnum.MOD, conflict_1, conflict_2) + # fix indices + conflict_1, conflict_2 = conflict_2, conflict_1 + + assert controller.mods[conflict_2].obsolete is True + assert controller.mods[conflict_1].obsolete is False + assert controller.mods[normal_mod].obsolete is False + + # Perform a deactivate + controller.deactivate(ComponentEnum.MOD, conflict_1) + assert controller.mods[conflict_2].obsolete is False + assert controller.mods[normal_mod].obsolete is False