diff --git a/.gitignore b/.gitignore index ffa747e..67eaeb6 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ pre-edited-cs/Profile* pre-edited-cs/window\.rect *Copy/ + +venv/ diff --git a/caver/patcher.py b/caver/patcher.py new file mode 100644 index 0000000..aa9d08f --- /dev/null +++ b/caver/patcher.py @@ -0,0 +1,60 @@ +from pathlib import Path +from typing import Optional +from lupa import LuaRuntime +import logging +import shutil +pre_edited_cs = __import__("pre-edited-cs") + + +CSVERSION = 3 + +def patch_files(patch_data: dict, output_dir: Path): + ensure_base_files_exist(output_dir) + + TscFile = LuaRuntime().eval(Path(__file__).parent.joinpath("tsc_file.lua").read_text()) + for mapname, mapdata in patch_data["maps"].items(): + patch_map(mapname, mapdata, TscFile, output_dir) + + patch_mychar(patch_data["mychar"], output_dir) + + patch_hash(patch_data["hash"], output_dir) + +def ensure_base_files_exist(output_dir: Path): + internal_copy = pre_edited_cs.get_path() + + version = output_dir.joinpath("data", "Stage", "_version.txt") + keep_existing_files = version.exists() and int(version.read_text()) >= CSVERSION + + def should_ignore(path: Path, names: list[str]): + if not keep_existing_files: + return [] + return [path.joinpath(name) for name in names if path.joinpath(name).exists() and path.joinpath(name).is_file()] + + shutil.copytree(internal_copy, output_dir, ignore=should_ignore) + +def patch_map(mapname: str, mapdata: dict[str, dict], TscFile, output_dir: Path): + mappath = output_dir.joinpath("data", "Stage", f"{mapname}.tsc") + tsc_file = TscFile.new({}, mappath.read_bytes(), logging.getLogger("caver")) + + for event, script in mapdata["pickups"].items(): + TscFile.placeItemAtLocation(tsc_file, script, event, mapname) + + for event, song in mapdata["music"].items(): + TscFile.placeSongAtCue(tsc_file, song["song_id"], event, song["original_id"], mapname) + + for event, script in mapdata["entrances"].items(): + TscFile.placeTraAtEntrance(tsc_file, script, event, mapname) + + mappath.write_bytes(TscFile.getText(tsc_file)) + output_dir.joinpath("data", "Plaintext", f"{mapname}.txt") + +def patch_mychar(mychar: Optional[str], output_dir: Path): + if mychar is None: + return + mychar_img = Path(mychar).read_bytes() + output_dir.joinpath("data", "MyChar.bmp").write_bytes(mychar_img) + +def patch_hash(hash: list[int], output_dir: Path): + hash_strings = [f"{num:04d}" for num in hash] + hash_string = ",".join(hash_strings) + output_dir.joinpath("data", "hash.txt").write_text(hash_string) \ No newline at end of file diff --git a/caver/tsc_file.lua b/caver/tsc_file.lua index 2213f51..cc40944 100644 --- a/caver/tsc_file.lua +++ b/caver/tsc_file.lua @@ -1,49 +1,33 @@ -local C = Class:extend() +local TscFile = {} --- local ITEM_DATA = require 'database.items' - -local OPTIONAL_REPLACES = { - 'Max health increased by ', - 'Max life increased by ', - '= 1 -end - -function C:placeItemAtLocation(item, location) +function TscFile:placeItemAtLocation(script, event, mapname) local wasChanged - self._text, wasChanged = self:_stringReplace(self._text, " pEnd then -- This is totally normal and can be ignored. - logDebug(('Found "%s", but was outside of label.'):format(needle, replacement)) + self.log.debug(('Found "%s", but was outside of label.'):format(needle, replacement)) return text, false end @@ -88,7 +72,7 @@ function C:_stringReplace(text, needle, replacement, label, overrides) return a .. replacement .. b, true end -function C:_getLabelPositionRange(label) +function TscFile:_getLabelPositionRange(label) local labelStart, labelEnd -- Recursive shit for when label is a table... @@ -128,7 +112,7 @@ function C:_getLabelPositionRange(label) end if labelStart == nil then - logError(("%s: Could not find label: %s"):format(self.mapName, label)) + self.log.error(("%s: Could not find label: %s"):format(self.mapName, label)) labelStart = 1 end @@ -139,18 +123,15 @@ function C:_getLabelPositionRange(label) return labelStart, labelEnd end -function C:writePlaintextTo(path) - logInfo('writing Plaintext TSC to: ' .. path) - U.writeFile(path, self._text) +function TscFile:getPlaintext() + return self._text end -function C:writeTo(path) - logInfo('writing TSC to: ' .. path) - local encoded = self:_codec(self._text, 'encode') - U.writeFile(path, encoded) +function TscFile:getText() + return self:_codec(self._text, 'encode') end -function C:_codec(text, mode) +function TscFile:_codec(text, mode) -- Create array of chars. local chars = {} text:gsub(".", function(c) table.insert(chars, c) end) @@ -166,9 +147,9 @@ function C:_codec(text, mode) error('Unknown codec mode: ' .. tostring(mode)) end - logDebug(" filesize", #chars) - logDebug(" encoding char:", encodingChar) - logDebug(" encoding char position:", encodingCharPosition) + self.log.debug(" filesize", #chars) + self.log.debug(" encoding char:", encodingChar) + self.log.debug(" encoding char position:", encodingCharPosition) -- Encode or decode. for pos, char in ipairs(chars) do @@ -182,4 +163,4 @@ function C:_codec(text, mode) return decoded end -return C +return TscFile diff --git a/pre-edited-cs/__init__.py b/pre-edited-cs/__init__.py index e69de29..25ba3ac 100644 --- a/pre-edited-cs/__init__.py +++ b/pre-edited-cs/__init__.py @@ -0,0 +1,5 @@ +from pathlib import Path + + +def get_path(): + return Path(__file__).parent