started implementing Game and wit for the game file manipulation, and modifying ModConfig syntax

This commit is contained in:
Faraphel 2022-06-09 22:47:13 +02:00
parent f0476381da
commit 9d97326f4b
6 changed files with 205 additions and 134 deletions

View file

@ -2,65 +2,12 @@
"version":"0.11", "version":"0.11",
"name":"Mario Kart Wii Faraphel", "name":"Mario Kart Wii Faraphel",
"nickname":"MKWF", "nickname":"MKWF",
"game_variant":"60", "variant":"60",
"region":5500, "region":{
"cheat_region":20061, "default": 5500,
"tags_prefix":[ "cheat": 20061
"Wii U", },
"3DS", "tags_prefix":{
"DS",
"GCN",
"GBA",
"SNES",
"N64",
"MKT",
"RMX",
"GP",
"MSRDS",
"CTR",
"CTTR",
"CNR",
"DKR",
"LCP",
"LEGO-R",
"MP9",
"MSUSA",
"FZMV",
"KAR",
"KO",
"FZ",
"RV",
"SADX",
"SCR",
"SH",
"SM64",
"SMB1",
"SMB2",
"SSBB",
"SMS",
"SMO",
"VVVVVV",
"WF",
"WP",
"Zelda OoT",
"Zelda TP",
"Zelda WW",
"PMWR",
"SHR",
"SK64",
"SMG",
"Spyro 1",
"Wii Shop",
"UT",
"GK2",
"GK3",
"GK7",
"FGKR"
],
"tags_suffix":[
"Boost"
],
"tags_color":{
"MSRDS": "green", "MSRDS": "green",
"CTR": "YOR4", "CTR": "YOR4",
"CTTR": "YOR5", "CTTR": "YOR5",
@ -106,17 +53,17 @@
"RMX": "YOR4", "RMX": "YOR4",
"MKT": "YOR5", "MKT": "YOR5",
"GP": "YOR6", "GP": "YOR6",
"Boost":"YOR3",
"Wii Shop": "blue1", "Wii Shop": "blue1",
"UT": "red3", "UT": "red3",
"FGKR":"YOR5",
"GK2": "green", "GK2": "green",
"GK3": "green", "GK3": "green",
"GK7":"green" "GK7": "green",
"FGKR": "YOR5"
}, },
"tags_suffix": {
"tag_retro":"Retro", "Boost": "orange"
},
"tags_cups": ["Switch", "3DS", "DS", "GCN", "GBA", "N64", "SNES", "MKT", "DX"],
"default_track":{ "default_track":{
"music":"T32", "music":"T32",
"special":"T32", "special":"T32",
@ -219,6 +166,7 @@
"since_version":"0.11", "since_version":"0.11",
"score":4, "score":4,
"tags":[ "tags":[
"Retro",
"Wii U" "Wii U"
] ]
}, },
@ -232,6 +180,7 @@
"since_version":"0.11", "since_version":"0.11",
"score":3, "score":3,
"tags":[ "tags":[
"Retro",
"Wii U" "Wii U"
], ],
"note":"some collision (like the plane) are buggy, and the texture feel a bit too dark" "note":"some collision (like the plane) are buggy, and the texture feel a bit too dark"
@ -265,6 +214,7 @@
"since_version":"0.11", "since_version":"0.11",
"score":5, "score":5,
"tags":[ "tags":[
"Retro",
"Wii U" "Wii U"
] ]
}, },
@ -278,6 +228,7 @@
"since_version":"0.11", "since_version":"0.11",
"score":5, "score":5,
"tags":[ "tags":[
"Retro",
"Wii U" "Wii U"
] ]
}, },
@ -291,6 +242,7 @@
"since_version":"0.11", "since_version":"0.11",
"score":5, "score":5,
"tags":[ "tags":[
"Retro",
"Wii U" "Wii U"
] ]
}, },
@ -839,6 +791,7 @@
"since_version":"0.11", "since_version":"0.11",
"score":2, "score":2,
"tags":[ "tags":[
"Retro",
"GCN" "GCN"
] ]
}, },
@ -952,6 +905,7 @@
"since_version":"0.11", "since_version":"0.11",
"score":4, "score":4,
"tags":[ "tags":[
"Retro",
"GCN" "GCN"
] ]
} }
@ -1399,6 +1353,7 @@
"since_version":"0.11", "since_version":"0.11",
"score":5, "score":5,
"tags":[ "tags":[
"Retro",
"N64" "N64"
] ]
}, },
@ -1440,6 +1395,7 @@
"since_version":"0.11", "since_version":"0.11",
"score":5, "score":5,
"tags":[ "tags":[
"Retro",
"N64" "N64"
] ]
} }
@ -1812,6 +1768,7 @@
"since_version":"0.11", "since_version":"0.11",
"score":4, "score":4,
"tags":[ "tags":[
"Retro",
"RMX" "RMX"
] ]
}, },
@ -1825,6 +1782,7 @@
"since_version":"0.11", "since_version":"0.11",
"score":3, "score":3,
"tags":[ "tags":[
"Retro",
"RMX" "RMX"
] ]
}, },
@ -1874,6 +1832,7 @@
"since_version":"0.11", "since_version":"0.11",
"score":5, "score":5,
"tags":[ "tags":[
"Retro",
"MKT" "MKT"
] ]
}, },
@ -1887,6 +1846,7 @@
"since_version":"0.11", "since_version":"0.11",
"score":5, "score":5,
"tags":[ "tags":[
"Retro",
"MKT" "MKT"
] ]
} }
@ -1955,7 +1915,6 @@
] ]
} }
], ],
"tracks":[ "tracks":[
{ {
"name":"4IT Clown's Road", "name":"4IT Clown's Road",

View file

@ -0,0 +1,4 @@
# class that represent a mario kart wii cup
class Cup:
def __init__(self, track1: "Track" = None, track2: "Track" = None, track3: "Track" = None, track4: "Track" = None):
self._tracks = [track1, track2, track3, track4]

View file

@ -0,0 +1,73 @@
import enum
from pathlib import Path
from source.wt.wit import WITPath
class Extension(enum.Enum):
"""
Enum for game extension
"""
FST = ".dol"
WBFS = ".wbfs"
ISO = ".iso"
@classmethod
def _missing_(cls, value: str) -> "Extension | None":
"""
if not found, search for the same value with lower case
:param value: value to search for
:return: None if nothing found, otherwise the found value
"""
value = value.lower()
for member in filter(lambda m: m.value == value, cls): return member
return None
class Region(enum.Enum):
"""
Enum for game region
"""
PAL = "PAL"
USA = "USA"
EUR = "EUR"
KOR = "KOR"
class Game:
def __init__(self, path: Path | str):
self.path = Path(path) if isinstance(path, str) else path
@property
def extension(self) -> Extension:
"""
Returns the extension of the game
:return: the extension of the game
"""
return Extension(self.path.suffix)
@property
def id(self) -> str:
"""
Return the id of the game (RMCP01, RMCK01, ...)
:return: the id of the game
"""
return WITPath(self.path).analyze()["id6"]
@property
def region(self) -> Region:
"""
Return the region of the game (PAL, USA, EUR, ...)
:return: the region of the game
"""
return Region(WITPath(self.path).analyze()["dol_region"])
def is_mkw(self) -> bool:
"""
Return True if the game is Mario Kart Wii, else otherwise
:return: is the game a MKW game
"""
return WITPath(self.path).analyze()["dol_is_mkw"] == 1
def is_vanilla(self) -> bool:
...

View file

@ -8,15 +8,16 @@ import json
# representation of the configuration of a mod # representation of the configuration of a mod
class ModConfig: class ModConfig:
__slots__ = ("name", "nickname", "variant", "region", "tags_prefix", "tags_suffix", "tag_retro", __slots__ = ("name", "nickname", "variant", "region", "tags_prefix", "tags_suffix",
"default_track", "_tracks", "version", "original_track_prefix", "swap_original_order", "default_track", "_tracks", "version", "original_track_prefix", "swap_original_order",
"keep_original_track", "enable_random_cup") "keep_original_track", "enable_random_cup", "tags_cups")
def __init__(self, name: str, nickname: str = None, version: str = None, variant: str = None, def __init__(self, name: str, nickname: str = None, version: str = None, variant: str = None,
tags_prefix: dict[Tag, Color] = None, tags_suffix: dict[Tag, Color] = None, tags_prefix: dict[Tag, Color] = None, tags_suffix: dict[Tag, Color] = None,
region: dict[int] | int = None, tag_retro: Tag = None, default_track: "Track | TrackGroup" = None, tags_cups: list[Tag] = None, region: dict[int] | int = None,
tracks: list["Track | TrackGroup"] = None, original_track_prefix: bool = None, default_track: "Track | TrackGroup" = None, tracks: list["Track | TrackGroup"] = None,
swap_original_order: bool = None, keep_original_track: bool = None, enable_random_cup: bool = None): original_track_prefix: bool = None, swap_original_order: bool = None,
keep_original_track: bool = None, enable_random_cup: bool = None):
self.name: str = name self.name: str = name
self.nickname: str = nickname if nickname is not None else name self.nickname: str = nickname if nickname is not None else name
@ -24,9 +25,9 @@ class ModConfig:
self.variant: str = variant if variant is not None else "01" self.variant: str = variant if variant is not None else "01"
self.region: dict[int] | int = region if region is not None else 0 self.region: dict[int] | int = region if region is not None else 0
self.tags_prefix: dict[str] = tags_prefix if tags_prefix is not None else {} self.tags_prefix: dict[Tag] = tags_prefix if tags_prefix is not None else {}
self.tags_suffix: dict[str] = tags_suffix if tags_suffix is not None else {} self.tags_suffix: dict[Tag] = tags_suffix if tags_suffix is not None else {}
self.tag_retro: str = tag_retro if tag_retro is None else "Retro" self.tags_cups: dict[Tag] = tags_cups if tags_cups is not None else {}
self.default_track: "Track | TrackGroup" = default_track if default_track is not None else None self.default_track: "Track | TrackGroup" = default_track if default_track is not None else None
self._tracks: list["Track | TrackGroup"] = tracks if tracks is not None else [] self._tracks: list["Track | TrackGroup"] = tracks if tracks is not None else []
@ -44,18 +45,16 @@ class ModConfig:
:return: ModConfig :return: ModConfig
""" """
kwargs = {
attr: config_dict.get(attr)
for attr in ["nickname", "version", "variant", "tags_prefix", "tags_suffix", "tags_cups",
"original_track_prefix", "swap_original_order", "keep_original_track", "enable_random_cup"]
}
return cls( return cls(
name=config_dict["name"], name=config_dict["name"],
nickname=config_dict.get("nickname"),
version=config_dict.get("version"), **kwargs,
variant=config_dict.get("variant"),
tags_prefix=config_dict.get("tags_prefix"),
tags_suffix=config_dict.get("tags_suffix"),
tag_retro=config_dict.get("tag_retro"),
original_track_prefix=config_dict.get("original_track_prefix"),
swap_original_order=config_dict.get("swap_original_order"),
keep_original_track=config_dict.get("keep_original_track"),
enable_random_cup=config_dict.get("enable_random_cup"),
default_track=Track.from_dict(config_dict.get("default_track", {})), default_track=Track.from_dict(config_dict.get("default_track", {})),
tracks=[Track.from_dict(track) for track in config_dict.get("tracks", [])], tracks=[Track.from_dict(track) for track in config_dict.get("tracks", [])],

View file

@ -1,7 +1,7 @@
from source.wt import * from source.wt import *
from source.wt import _run, _run_dict from source.wt import _run, _run_dict
tools_path = tools_szs_dir / "wszst.exe" tools_path = tools_szs_dir / ("wszst.exe" if system == "win64" else "wszst")
class SZSPath: class SZSPath:

36
source/wt/wit.py Normal file
View file

@ -0,0 +1,36 @@
from source.wt import *
from source.wt import _run, _run_dict
tools_path = tools_wit_dir / ("wit.exe" if system == "win64" else "wit")
class WITPath:
__slots__ = ("path",)
def __init__(self, path: Path):
self.path = path
@better_error(tools_path)
def _run(self, *args) -> bytes:
"""
Return a command with wit and return the output
:param args: command arguments
:return: the output of the command
"""
return _run(tools_path, *args)
@better_error(tools_path)
def _run_dict(self, *args) -> dict:
"""
Return a dictionary of a command that return value associated to a key with a equal sign
:param args: others arguments
:return: the dictionary
"""
return _run_dict(tools_path, *args)
def analyze(self) -> dict:
"""
Return the analyze of the file
:return: dictionnary of key and value of the analyze
"""
return self._run_dict("ANALYZE", self.path)