cleaned Riivolution generation

This commit is contained in:
Faraphel 2022-08-27 18:58:09 +02:00
parent 6e032d4d1a
commit 6fe1223c8b
4 changed files with 90 additions and 67 deletions

View file

@ -108,6 +108,11 @@
"TESTING_MOD_SETTINGS": "Test mod settings", "TESTING_MOD_SETTINGS": "Test mod settings",
"SETTINGS_FILE": "Settings file", "SETTINGS_FILE": "Settings file",
"EXPORT_SETTINGS": "Export settings", "EXPORT_SETTINGS": "Export settings",
"IMPORT_SETTINGS": "Import settings" "IMPORT_SETTINGS": "Import settings",
"PREPARING_RIIVOLUTION": "Preparing for riivolution",
"CONVERTING_TO_RIIVOLUTION": "Converting to Riivolution patch",
"PATCHS": "patchs",
"PRE-PATCHS": "pre-patchs",
"CALCULATING_HASH_FOR": "Calculating hash for"
} }
} }

View file

@ -109,6 +109,11 @@
"TESTING_MOD_SETTINGS": "Paramètre de test", "TESTING_MOD_SETTINGS": "Paramètre de test",
"SETTINGS_FILE": "Fichier de paramètres", "SETTINGS_FILE": "Fichier de paramètres",
"EXPORT_SETTINGS": "Exporter les paramètres", "EXPORT_SETTINGS": "Exporter les paramètres",
"IMPORT_SETTINGS": "Importer les paramètres" "IMPORT_SETTINGS": "Importer les paramètres",
"PREPARING_RIIVOLUTION": "Préparation pour Riivolution",
"CONVERTING_TO_RIIVOLUTION": "Conversion en patch Riivolution",
"PATCHS": "patchs",
"PRE-PATCHS": "pre-patchs",
"CALCULATING_HASH_FOR": "Calcule du hash pour"
} }
} }

View file

@ -9,6 +9,7 @@ from source.mkw.ModConfig import ModConfig
from source.mkw.Patch.Patch import Patch from source.mkw.Patch.Patch import Patch
from source.mkw.collection.Extension import Extension from source.mkw.collection.Extension import Extension
from source.progress import Progress from source.progress import Progress
from source.utils import comp_dict_changes
from source.wt import szs, lec, wit from source.wt import szs, lec, wit
from source.wt.wstrt import StrPath from source.wt.wstrt import StrPath
from source.translation import translate as _ from source.translation import translate as _
@ -17,6 +18,9 @@ if TYPE_CHECKING:
from source.mkw.Game import Game from source.mkw.Game import Game
RIIVOLUTION_FOLDER_NAME: str = "riivolution"
class PathOutsideMod(Exception): class PathOutsideMod(Exception):
def __init__(self, forbidden_path: Path, allowed_range: Path): def __init__(self, forbidden_path: Path, allowed_range: Path):
super().__init__(_("PATH", ' "', forbidden_path, '" ', "OUTSIDE_ALLOWED_RANGE", ' "', allowed_range, '" ')) super().__init__(_("PATH", ' "', forbidden_path, '" ', "OUTSIDE_ALLOWED_RANGE", ' "', allowed_range, '" '))
@ -166,7 +170,7 @@ class ExtractedGame:
Used before the lecode patch is applied Used before the lecode patch is applied
:param mod_config: the mod to install :param mod_config: the mod to install
""" """
yield Progress(description=_("INSTALLING_ALL", " Pre-Patchs..."), determinate=False) yield Progress(description=_("INSTALLING_ALL", " ", "PRE-PATCHS", "..."), determinate=False)
yield from self._install_all_patch(mod_config, "_PREPATCH/") yield from self._install_all_patch(mod_config, "_PREPATCH/")
def install_all_patch(self, mod_config: ModConfig) -> Generator[Progress, None, None]: def install_all_patch(self, mod_config: ModConfig) -> Generator[Progress, None, None]:
@ -175,7 +179,7 @@ class ExtractedGame:
Used after the lecode patch is applied Used after the lecode patch is applied
:param mod_config: the mod to install :param mod_config: the mod to install
""" """
yield Progress(description=_("INSTALLING_ALL", " Patchs..."), determinate=False) yield Progress(description=_("INSTALLING_ALL", " ", "PATCHS", "..."), determinate=False)
yield from self._install_all_patch(mod_config, "_PATCH/") yield from self._install_all_patch(mod_config, "_PATCH/")
def convert_to(self, output_type: Extension) -> Generator[Progress, None, wit.WITPath | None]: def convert_to(self, output_type: Extension) -> Generator[Progress, None, wit.WITPath | None]:
@ -205,7 +209,67 @@ class ExtractedGame:
return converted_game return converted_game
def get_hash_map(self) -> dict[str, str]: def convert_to_riivolution(self, mod_config: ModConfig, old_hash_map: dict[str, str]
) -> Generator[Progress, None, None]:
"""
Convert the extracted game into a riivolution patch
:param mod_config: the mod configuration
:param old_hash_map: hash map of all the games files created before all the modifications
"""
new_hash_map = yield from self.get_hash_map()
yield Progress(description=_("CONVERTING_TO_RIIVOLUTION"), determinate=False)
# get the files difference between the original game and the patched game
diff_hash_map: dict[str, Path] = comp_dict_changes(old_hash_map, new_hash_map)
for file in filter(lambda file: file.is_file(), self.path.rglob("*")):
# if the file have not being patched, delete it
if str(file.relative_to(self.path)) not in diff_hash_map:
file.unlink()
# get riivolution configuration content
riivolution_config_content = "\n".join((
'<wiidisc version="1">',
' <id game="RMC" disc="0" version="0"> </id>',
'',
' <options>',
f' <section name="{str(mod_config)}">',
' <option id="CT" name="Custom Tracks" default="1">',
' <choice name="Enabled"> <patch id="mod"/> </choice>',
' </option>',
' <option id="save_SD" name="Save on SD" default="1">',
' <choice name="Enabled"> <patch id="save_SD"/> </choice>',
' </option>',
' <option id="my_stuff" name="My Stuff" default="1">',
' <choice name="Enabled"> <patch id="my_stuff"/> </choice>',
' </option>',
' </section>',
' </options>',
'',
' <patch id="mod">',
f' <folder disc="/" external="/{self.path.name}/files/" recursive="true" create="true"/>',
f' <folder disc="" external="/{self.path.name}/sys/" recursive="true" create="true"/>',
' </patch>',
'',
' <patch id="my_stuff">',
f' <folder external="/{RIIVOLUTION_FOLDER_NAME}/MyStuff/" recursive="false"/>',
f' <folder external="/{RIIVOLUTION_FOLDER_NAME}/MyStuff/" disc="/"/>',
' </patch>',
'',
' <patch id="save_SD">',
' <savegame clone="false"',
f' external="/{RIIVOLUTION_FOLDER_NAME}/save/{"{$__gameid}{$__region}"}{mod_config.variant}"/>',
' </patch>',
'</wiidisc>',
))
# get riivolution configuration path
riivolution_config_path: Path = self.path.parent / f"{RIIVOLUTION_FOLDER_NAME}/{str(mod_config)}.xml"
riivolution_config_path.parent.mkdir(parents=True, exist_ok=True)
riivolution_config_path.write_text(riivolution_config_content, encoding="utf-8")
def get_hash_map(self) -> Generator[Progress, None, dict[str, str]]:
""" """
Return a dictionary associating all the game subfiles to a hash Return a dictionary associating all the game subfiles to a hash
:return: a dictionary associating all the game subfiles to a hash :return: a dictionary associating all the game subfiles to a hash
@ -214,10 +278,13 @@ class ExtractedGame:
for fp in filter(lambda fp: fp.is_file(), self.path.rglob("*")): for fp in filter(lambda fp: fp.is_file(), self.path.rglob("*")):
hasher = hashlib.md5() hasher = hashlib.md5()
rel_path: str = str(fp.relative_to(self.path))
yield Progress(description=_(f"CALCULATING_HASH_FOR", ' "', rel_path, '"'))
with open(fp, "rb") as file: with open(fp, "rb") as file:
while block := file.read(file_block_size): while block := file.read(file_block_size):
hasher.update(block) hasher.update(block)
md5_map[str(fp.relative_to(self.path))] = hasher.hexdigest() md5_map[rel_path] = hasher.hexdigest()
return md5_map return md5_map

View file

@ -7,7 +7,6 @@ from source.mkw.collection.Extension import Extension
from source.mkw.collection.Region import Region from source.mkw.collection.Region import Region
from source.option import Options from source.option import Options
from source.progress import Progress from source.progress import Progress
from source.utils import comp_dict_changes
from source.wt.wit import WITPath from source.wt.wit import WITPath
from source.translation import translate as _ from source.translation import translate as _
@ -124,10 +123,11 @@ class Game:
yield Progress(title=_("EXTRACTION"), set_part=1) yield Progress(title=_("EXTRACTION"), set_part=1)
yield from self.extract(extracted_game.path) yield from self.extract(extracted_game.path)
# Riivolution hash map for the final comparaison # Get the original file hash map for comparaison with the post-patched game
yield Progress(title=_("PREPARING_RIIVOLUTION"), set_part=2, yield Progress(title=_("PREPARING_RIIVOLUTION"), set_part=2)
description=_("PREPARING_RIIVOLUTION"), determinate=False) riivolution_original_hash_map: dict[str, str] | None = None
if output_type.is_riivolution(): riivolution_original_hash_map = extracted_game.get_hash_map() if output_type.is_riivolution():
riivolution_original_hash_map = yield from extracted_game.get_hash_map()
# install mystuff # install mystuff
yield Progress(title=_("MYSTUFF"), set_part=3) yield Progress(title=_("MYSTUFF"), set_part=3)
@ -165,62 +165,8 @@ class Game:
yield from extracted_game.recreate_all_szs() yield from extracted_game.recreate_all_szs()
if output_type.is_riivolution(): if output_type.is_riivolution():
# Riivolution comparaison yield Progress(title=_("CONVERTING_TO_RIIVOLUTION"), set_part=8)
riivolution_patched_hash_map = extracted_game.get_hash_map() yield from extracted_game.convert_to_riivolution(mod_config, riivolution_original_hash_map)
riivolution_diff: dict[str, Path] = comp_dict_changes(
riivolution_original_hash_map,
riivolution_patched_hash_map
)
for file in filter(lambda file: file.is_file(), extracted_game.path.rglob("*")):
# if the file have not being patched, delete it
if str(file.relative_to(extracted_game.path)) not in riivolution_diff:
file.unlink()
# get riivolution configuration content
riivolution_config_content = f"""
<wiidisc version="1">
<id game="RMC" disc="0" version="0">
<region type="P"/>
<region type="J"/>
<region type="E"/>
<region type="K"/>
</id>
<options>
<section name="{str(mod_config)}">
<option id="CT" name="Custom Tracks" default="1">
<choice name="Enabled"> <patch id="mod"/> </choice>
</option>
<option id="save_SD" name="Save on SD" default="1">
<choice name="Enabled"> <patch id="save_SD"/> </choice>
</option>
<option id="my_stuff" name="My Stuff" default="1">
<choice name="Enabled"> <patch id="my_stuff"/> </choice>
</option>
</section>
</options>
<patch id="mod">
<folder disc="/" external="/{extracted_game.path.name}/files/" recursive="true" create="true"/>
<folder disc="" external="/{extracted_game.path.name}/sys/" recursive="true" create="true"/>
</patch>
<patch id="my_stuff">
<folder external="/riivolution/MyStuff/" recursive="false"/>
<folder external="/riivolution/MyStuff/" disc="/"/>
</patch>
<patch id="save_SD">
<savegame clone="false" external="/riivolution/save/{'{$__gameid}{$__region}'}{mod_config.variant}"/>
</patch>
</wiidisc>
"""
# get riivolution configuration path
riivolution_config_path = extracted_game.path.parent / f"riivolution/{str(mod_config)}.xml"
riivolution_config_path.parent.mkdir(parents=True, exist_ok=True)
riivolution_config_path.write_text(riivolution_config_content, encoding="utf8")
else: else:
# convert the extracted game into a file # convert the extracted game into a file