Initial commit with nexus updates and streamlined UI

This commit is contained in:
jschantli committed 2026-09-21 19:01:19 -07:00
commit f780daecad
41 files changed
+4668

No files matched your search

+70
View File
@@ -0,0 +1,70 @@
import hashlib
import os
import struct
import tempfile
import unittest
import zipfile
from pathlib import Path
from mhwmm.core.paks import path_hash, pak_name
from mhwmm.core.paths import Paths
def snapshot(root: Path) -> dict:
"""Byte-level picture of a tree: files by hash, symlinks by target, and directories."""
snap = {}
for dirpath, dirnames, filenames in os.walk(root):
for n in dirnames + filenames:
p = Path(dirpath) / n
rel = str(p.relative_to(root))
if p.is_symlink():
snap[rel] = ("l", os.readlink(p))
elif p.is_dir():
snap[rel] = ("d",)
else:
snap[rel] = ("f", hashlib.sha256(p.read_bytes()).hexdigest())
return snap
def make_game(root: Path, ceiling: int = 15) -> Path:
game = root / "game"
game.mkdir()
for chain in ("main", "sub"):
for n in range(1, ceiling + 1):
(game / pak_name(chain, n)).write_bytes(f"vanilla-{chain}-{n}".encode())
(game / "re_chunk_000.pak").write_bytes(b"base")
(game / "MonsterHunterWilds.exe").write_bytes(b"exe")
return game
def write_tree(root: Path, files: dict[str, bytes | str]) -> Path:
for rel, data in files.items():
p = root / rel
p.parent.mkdir(parents=True, exist_ok=True)
p.write_bytes(data if isinstance(data, bytes) else data.encode())
return root
def make_kpka(paths: list[str]) -> bytes:
"""Minimal KPKA with entries keyed by the path hashes of `paths`."""
out = b"KPKA" + struct.pack("<BBHII", 4, 0, 0, len(paths), 0)
for p in paths:
lo, up = path_hash(p)
out += struct.pack("<IIQQQQQ", lo, up, 0, 0, 0, 0, 0)
return out
def make_zip(path: Path, files: dict[str, bytes | str]) -> Path:
with zipfile.ZipFile(path, "w") as zf:
for name, data in files.items():
zf.writestr(name, data)
return path
class TmpCase(unittest.TestCase):
def setUp(self):
self._td = tempfile.TemporaryDirectory()
self.addCleanup(self._td.cleanup)
self.tmp = Path(self._td.name)
self.paths = Paths(self.tmp / "data", self.tmp / "config")
self.paths.ensure()