Skip to content

Commit

Permalink
Display an asterisk by conflicting mods
Browse files Browse the repository at this point in the history
Enabled mods that have conflicting files now display an asterisk in the
"activated" column.
  • Loading branch information
cyberrumor committed Feb 5, 2024
1 parent 92b582b commit 2fd8bea
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 47 deletions.
1 change: 1 addition & 0 deletions ammo/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class Mod:
install_dir: Path = field(init=False)
fomod: bool = field(init=False, default=False)
enabled: bool = field(init=False, default=False)
conflict: bool = field(init=False, default=False)
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)
Expand Down
8 changes: 3 additions & 5 deletions ammo/fomod_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,15 +168,15 @@ def _get_pages(self) -> list[Page]:
visibility_conditions=visibility_conditions,
)

for plugin_index, plugin in enumerate(group_of_plugins):
for i, plugin in enumerate(group_of_plugins):
name = plugin.get("name").strip()
description = plugin.findtext("description", default="").strip()
flags = {}
# Automatically mark the first option as selected when
# a selection is required.
selected = (
page.archtype in ["SelectExactlyOne", "SelectAtLeastOne"]
) and plugin_index == 0
) and i == 0

# Interpret on/off or 1/0 as true/false
if conditional_flags := plugin.find("conditionFlags"):
Expand All @@ -194,9 +194,7 @@ def _get_pages(self) -> list[Page]:
# unconditional install.
conditional = False

files = []
if plugin_files := plugin.find("files"):
files.extend(plugin_files)
files = plugin.find("files") or []

page.selections.append(
Selection(
Expand Down
63 changes: 42 additions & 21 deletions ammo/mod_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ def __init__(self, downloads_dir: Path, game: Game, *keywords):
self.downloads = downloads
self.changes = False
self.find(*self.keywords)
self._stage()

def __str__(self) -> str:
"""
Expand All @@ -230,22 +231,28 @@ def __str__(self) -> str:

for i, download in enumerate(self.downloads):
if download.visible:
index = f"[{i}]"
result += f"{index:<7} {download.name}\n"
priority = f"[{i}]"
result += f"{priority:<7} {download.name}\n"
result += "\n"

for index, components in enumerate([self.mods, self.plugins]):
result += (
f" index | Activated | {'Mod name' if index == 0 else 'Plugin name'}\n"
)
result += "-------|-----------|------------\n"
for i, component in enumerate(components):
if component.visible:
priority = f"[{i}]"
enabled = f"[{component.enabled}]"
result += f"{priority:<7} {enabled:<11} {component.name}\n"
if index == 0:
result += "\n"
result += " index | Activated | Mod name\n"
result += "-------|-----------|------------\n"
for i, mod in enumerate(self.mods):
if mod.visible:
priority = f"[{i}]"
enabled = f"[{mod.enabled}]"
conflict = "*" if mod.conflict else " "
result += f"{priority:<7} {enabled:<9} {conflict:<1} {mod.name}\n"

result += "\n"
result += " index | Activated | Plugin name\n"
result += "-------|-----------|------------\n"
for i, plugin in enumerate(self.plugins):
if plugin.visible:
priority = f"[{i}]"
enabled = f"[{plugin.enabled}]"
result += f"{priority:<7} {enabled:<11} {plugin.name}\n"

return result

def _prompt(self):
Expand Down Expand Up @@ -403,12 +410,16 @@ def _set_component_state(self, component: ComponentEnum, index: int, state: bool

def _stage(self) -> dict:
"""
Returns a dict containing the final symlinks that will be installed.
Responsible for assigning mod.conflict for the staged configuration.
Returns a dict containing the final symlinks that would be installed.
"""
# destination: (mod_name, source)
result = {}
# Iterate through enabled mods in order.
for mod in (i for i in self.mods if i.enabled):
for mod in self.mods:
mod.conflict = False
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
for src in mod.files:
# Get the sanitized full path relative to the game.directory.
Expand All @@ -420,8 +431,15 @@ def _stage(self) -> dict:
dest = mod.install_dir / corrected_name

# Add the sanitized full path to the stage, resolving
# conflicts.
# conflicts. Record whether a mod conflicting files.
dest = normalize(dest, self.game.directory)
if dest in result:
conflicting_mod = [
i for i in enabled_mods[:index] if i.name == result[dest][0]
]
if conflicting_mod and conflicting_mod[0].enabled:
mod.conflict = True
conflicting_mod[0].conflict = True
result[dest] = (mod.name, src)

return result
Expand Down Expand Up @@ -514,6 +532,7 @@ def activate(self, component: ComponentEnum, index: Union[int, str]) -> None:
except IndexError as e:
# Demote IndexErrors
raise Warning(e)
self._stage()

def deactivate(self, component: ComponentEnum, index: Union[int, str]) -> None:
"""
Expand All @@ -535,6 +554,7 @@ def deactivate(self, component: ComponentEnum, index: Union[int, str]) -> None:
except IndexError as e:
# Demote IndexErrors
raise Warning(e)
self._stage()

def sort(self) -> None:
"""
Expand Down Expand Up @@ -825,10 +845,10 @@ def install_download(index, download) -> None:

if index == "all":
errors = []
for index, download in enumerate(self.downloads):
for i, download in enumerate(self.downloads):
if download.visible:
try:
install_download(index, download)
install_download(i, download)
except Warning as e:
errors.append(str(e))
if errors:
Expand Down Expand Up @@ -866,6 +886,7 @@ def move(self, component: ComponentEnum, index: int, new_index: int) -> None:
comp = components.pop(index)
components.insert(new_index, comp)
self.changes = True
self._stage()

def commit(self) -> None:
"""
Expand All @@ -877,7 +898,7 @@ def commit(self) -> None:

count = len(stage)
skipped_files = []
for index, (dest, source) in enumerate(stage.items()):
for i, (dest, source) in enumerate(stage.items()):
(name, src) = source
assert dest.is_absolute()
assert src.is_absolute()
Expand All @@ -890,7 +911,7 @@ def commit(self) -> None:
{str(dest).split(str(self.game.directory))[-1].lstrip('/')}."
)
finally:
print(f"files processed: {index+1}/{count}", end="\r", flush=True)
print(f"files processed: {i+1}/{count}", end="\r", flush=True)

warn = ""
for skipped_file in skipped_files:
Expand Down
Loading

0 comments on commit 2fd8bea

Please sign in to comment.