diff --git a/src/mercury_engine_data_structures/formats/__init__.py b/src/mercury_engine_data_structures/formats/__init__.py index 39b9ca83..af35457e 100644 --- a/src/mercury_engine_data_structures/formats/__init__.py +++ b/src/mercury_engine_data_structures/formats/__init__.py @@ -29,6 +29,7 @@ from mercury_engine_data_structures.formats.bsmat import Bsmat from mercury_engine_data_structures.formats.gui_files import Bmscp, Bmssk, Bmsss from mercury_engine_data_structures.formats.ini import Ini +from mercury_engine_data_structures.formats.lua import Lua from mercury_engine_data_structures.formats.pkg import Pkg from mercury_engine_data_structures.formats.toc import Toc from mercury_engine_data_structures.formats.txt import Txt @@ -68,6 +69,7 @@ "TOC": Toc, "TXT": Txt, "INI": Ini, + "LUA": Lua, } diff --git a/src/mercury_engine_data_structures/formats/lua.py b/src/mercury_engine_data_structures/formats/lua.py new file mode 100644 index 00000000..fe2ea088 --- /dev/null +++ b/src/mercury_engine_data_structures/formats/lua.py @@ -0,0 +1,33 @@ +from __future__ import annotations + +import typing + +import construct + +from mercury_engine_data_structures.common_types import StrId +from mercury_engine_data_structures.formats import BaseResource +from mercury_engine_data_structures.game_check import Game + +if typing.TYPE_CHECKING: + import typing_extensions + + from mercury_engine_data_structures.file_tree_editor import FileTreeEditor + +LUA = construct.Struct( + lua_text = StrId, +) + + +class Lua(BaseResource): + @classmethod + def parse(cls, data: bytes, target_game: Game, editor: FileTreeEditor | None = None) -> typing_extensions.Self: + raise ValueError("Lua files cannot be parsed because it requires decompilation") + + def build(self) -> bytes: + if self.target_game == Game.SAMUS_RETURNS: + import randovania_lupa.lua51_sr as lupa + else: # self.target_game == Game.DREAD + import randovania_lupa.lua51_dread as lupa + lua = lupa.LuaRuntime() + byte_ret = lua.compile_to_byes(self._raw["lua_text"]) + return byte_ret diff --git a/tests/formats/test_lua.py b/tests/formats/test_lua.py new file mode 100644 index 00000000..7b9c68e9 --- /dev/null +++ b/tests/formats/test_lua.py @@ -0,0 +1,48 @@ +from construct import Container + +from mercury_engine_data_structures.formats.lua import Lua +from mercury_engine_data_structures.game_check import Game + +_COMPILED_LUA = (b'\x1bLuaQ\x00\x01\x04\x04\x04\x04\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x02\x03\x11\x00\x00\x00\x05\x00\x00' + b'\x00\x06@@\x00A\x80\x00\x00\x82\x00\x00\x00\x1c@\x80\x01\x05\xc0' + b'\x00\x00\x1a@\x00\x00\x16\x00\x00\x80\n\x00\x00\x00\x07\xc0\x00' + b'\x00\x05\xc0\x00\x00d\x00\x00\x00\t@\x00\x82\x05\xc0\x00\x00d@' + b'\x00\x00\t@\x80\x82\x1e\x00\x80\x00\x06\x00\x00\x00\x04\x05\x00' + b'\x00\x00Game\x00\x04\x0e\x00\x00\x00ImportLibrary\x00\x04<\x00\x00' + b'\x00actors/items/randomizerpowerup/scripts/randomizerpowerup.lc\x00' + b'\x04\x18\x00\x00\x00RandomizerBabyHatchling\x00\x04\x05\x00\x00' + b'\x00main\x00\x04\x0b\x00\x00\x00OnPickedUp\x00\x02\x00\x00\x00' + b'\x00\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x02' + b'\x01\x00\x00\x00\x1e\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06' + b'\x00\x00\x00\n\x00\x00\x00\x00\x01\x00\x04\x16\x00\x00\x00E\x00\x00' + b'\x00F@\xc0\x00\x80\x00\x00\x00\\@\x00\x01E\x80\x00\x00F\xc0\xc0\x00' + b'\x81\x00\x01\x00\\\x80\x00\x01F@\xc1\x00K\x80\xc1\x00\\@\x00\x01E\x80' + b'\x00\x00F\xc0\xc1\x00\x81\x00\x02\x00\\\x80\x00\x01\x85\x80\x00\x00\x86' + b'\xc0@\x01\xc1\x00\x01\x00\x9c\x80\x00\x01\x86@B\x01I\x80\x80\x84\x1e\x00' + b'\x80\x00\n\x00\x00\x00\x04\x12\x00\x00\x00RandomizerPowerup\x00\x04\x0b' + b'\x00\x00\x00OnPickedUp\x00\x04\x05\x00\x00\x00Game\x00\x04\x11\x00\x00' + b'\x00GetDefaultPlayer\x00\x04\x06\x00\x00\x00Samus\x00\x04\x16\x00\x00' + b'\x00BABYHATCHLINGCREATION\x00\x04\n\x00\x00\x00SpawnBaby\x00\x04\n\x00\x00' + b'\x00GetEntity\x00\x04\x0f\x00\x00\x00Baby Hatchling\x00\x04\x05\x00\x00\x00vPos' + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00' + ) + +lua_str ="""Game.ImportLibrary("actors/items/randomizerpowerup/scripts/randomizerpowerup.lc", false) +RandomizerBabyHatchling = RandomizerBabyHatchling or {} +function RandomizerBabyHatchling.main() +end + +function RandomizerBabyHatchling.OnPickedUp(progression) + RandomizerPowerup.OnPickedUp(progression) + Game.GetDefaultPlayer("Samus").BABYHATCHLINGCREATION:SpawnBaby() + Game.GetEntity("Baby Hatchling").vPos = Game.GetDefaultPlayer("Samus").vPos +end +""" +def test_build_lua(): + lua = Lua(Container(lua_text=lua_str), Game.SAMUS_RETURNS) + assert lua.build() == _COMPILED_LUA + +