Exemplo n.º 1
0
 def wrapped(self: MemoryHook, *args, **kwargs):
     try:
         with PACKAGE_PATH("__address_cache__").open("rb") as f:
             self._address_cache = pickle.load(f)
     except (FileNotFoundError, EOFError, ValueError):
         self._address_cache = {}
     result = func(self, *args, **kwargs)
     with PACKAGE_PATH("__address_cache__").open("wb") as f:
         pickle.dump(self._address_cache, f)
     return result
Exemplo n.º 2
0
def _temp_lua_path(content, as_bytes=False, encoding=None, set_cwd=False):
    temp = PACKAGE_PATH("ai/lua/temp")
    if set_cwd:
        previous_cwd = os.getcwd()
        os.chdir(str(temp.parent))
    else:
        previous_cwd = None
    with temp.open(mode="wb" if as_bytes else "w", encoding=encoding) as f:
        f.write(content)
    yield temp
    try:
        os.remove(str(PACKAGE_PATH("ai/lua/temp")))
    except FileNotFoundError:
        pass
    if previous_cwd:
        os.chdir(previous_cwd)
Exemplo n.º 3
0
    def __init__(self, paramdef_bnd_source=None):
        """BND container with all the `ParamDef` definitions for a given game.

        The latest versions of these files are included with Soulstruct for some games, and can be loaded simply by
        passing the game name to this constructor. They will also be loaded automatically when needed by `Param`
        instances.

        If you want to modify a `ParamDefBND`, you are far too powerful a modder for Soulstruct, and I cannot make that
        journey with you at this time.
        """
        if paramdef_bnd_source is None:
            paramdef_bnd_source = self.GAME
        elif isinstance(paramdef_bnd_source, str):
            try:
                paramdef_bnd_source = get_game(paramdef_bnd_source)
            except ValueError:
                # Will try to use as a path.
                pass
        if isinstance(paramdef_bnd_source, Game):
            # Load vanilla ParamDefBND bundled with Soulstruct (easiest).
            if not paramdef_bnd_source.bundled_paramdef_path:
                raise NotImplementedError(
                    f"Soulstruct does not have a bundled `paramdefbnd` file for game {paramdef_bnd_source.name}."
                )
            paramdef_bnd_source = PACKAGE_PATH(
                paramdef_bnd_source.bundled_paramdef_path)
            if not paramdef_bnd_source.is_file():
                raise FileNotFoundError(
                    f"Could not find bundled `paramdefbnd` file for game {paramdef_bnd_source.name} in Soulstruct.\n"
                    "Update/reinstall Soulstruct or copy the ParamDef files in yourself."
                )

        self._bnd = BND(paramdef_bnd_source)

        self.paramdefs = {}  # type: dict[str, ParamDef]
        for entry in self.bnd.entries:
            try:
                paramdef = self.PARAMDEF_CLASS(entry)
            except Exception:
                _LOGGER.error(
                    f"Could not load ParamDefBND entry {entry.name}.")
                raise
            if paramdef.param_type in self.paramdefs:
                raise KeyError(
                    f"ParamDef type {paramdef.param_type} was loaded more than once in ParamDefBND."
                )
            self.paramdefs[paramdef.param_type] = paramdef
Exemplo n.º 4
0
 def restore_game_backup(self, backup_path=None):
     """Restore game files from the given folder, which defaults to 'soulstruct-backup' in your game directory.
     Create these backup files with `create_game_backup(backup_dir)`."""
     if backup_path is None:
         backup_path = self.game_root / "soulstruct-backup"
     with PACKAGE_PATH("project/files.json").open("rb") as f:
         game_files = json.load(f)[self.GAME.name]
     for file_path_parts in traverse_path_tree(game_files):
         backup_file_path = backup_path / Path(*file_path_parts)
         if not backup_file_path.is_file():
             raise FileNotFoundError(
                 f"Could not find backup file to restore: "
                 f"{str(backup_file_path)}")
         game_file_path = Path(self.game_root, *file_path_parts)
         game_file_path.parent.mkdir(parents=True, exist_ok=True)
         shutil.copy2(str(backup_file_path), str(game_file_path))
Exemplo n.º 5
0
 def create_game_backup(self, backup_path=None):
     """Copy existing game files (that can be edited with Soulstruct) to a backup directory, which defaults to
     'soulstruct-backup' in your game directory. Use `restore_game_backup(backup_dir)` to restore those files."""
     if backup_path is None:
         backup_path = self.game_root / "soulstruct-backup"
     else:
         backup_path = Path(backup_path)
     with PACKAGE_PATH("project/files.json").open("r") as f:
         game_files = json.load(f)[self.GAME.name]
     for file_path_parts in traverse_path_tree(game_files):
         game_file_path = self.game_root / Path(*file_path_parts)
         if not game_file_path.is_file():
             raise FileNotFoundError(
                 f"Could not find file in game directory to back up: "
                 f"{str(game_file_path)}")
         backup_file_path = Path(backup_path, *file_path_parts)
         backup_file_path.parent.mkdir(parents=True, exist_ok=True)
         shutil.copy2(str(game_file_path), str(backup_file_path))
Exemplo n.º 6
0
 def get_empty_talkesdbnd():
     """Get empty pickled `.talkesdbnd` file for Dark Souls 1 (either version)."""
     with PACKAGE_PATH("project/resources/empty_talkesdbnd.ds1").open(
             "rb") as f:
         return pickle.load(f)
Exemplo n.º 7
0
    args_ = []
    type_hints_ = []
    for arg_hint in args_with_type_hints:
        if not arg_hint:
            continue
        if ":" in arg_hint:
            arg, type_hint = [a.strip() for a in arg_hint.split(":")]
            args_.append(arg)
            type_hints_.append(type_hint)
        else:
            args_.append(arg_hint)
            type_hints_.append(None)
    return name_, tuple(args_), tuple(type_hints_)


_stubs_path = PACKAGE_PATH("esd/functions.pyi")
with open(_stubs_path) as f:
    _stub_lines = f.readlines()
i = 0
while i < len(_stub_lines) - 1:
    command_match = re.match(_COMMAND_RE, _stub_lines[i])
    if command_match is not None:
        esd_type, bank, f_id = command_match.group(1, 2, 3)
        i += 1
        COMMANDS[esd_type].setdefault(int(bank),
                                      {})[int(f_id)] = _parse_function_def(
                                          i, _stub_lines[i])
        i += 1
        continue
    test_match = re.match(_TEST_RE, _stub_lines[i])
    if test_match is not None:
Exemplo n.º 8
0
    args_ = []
    type_hints_ = []
    for arg_hint in args_with_type_hints:
        if not arg_hint:
            continue
        if ":" in arg_hint:
            arg, type_hint = [a.strip() for a in arg_hint.split(":")]
            args_.append(arg)
            type_hints_.append(type_hint)
        else:
            args_.append(arg_hint)
            type_hints_.append(None)
    return name_, tuple(args_), tuple(type_hints_)


_stubs_path = PACKAGE_PATH("base/ezstate/esd/functions.pyi")
with open(_stubs_path) as f:
    _stub_lines = f.readlines()
i = 0
while i < len(_stub_lines) - 1:
    command_match = re.match(_COMMAND_RE, _stub_lines[i])
    if command_match is not None:
        esd_type, bank, f_id = command_match.group(1, 2, 3)
        i += 1
        COMMANDS[ESDType(esd_type)].setdefault(int(bank), {})[int(f_id)] = _parse_function_def(i, _stub_lines[i])
        i += 1
        continue
    test_match = re.match(_TEST_RE, _stub_lines[i])
    if test_match is not None:
        esd_type, f_id = test_match.group(1, 2)
        i += 1
Exemplo n.º 9
0
import struct
import subprocess
from contextlib import contextmanager
from copy import deepcopy
from pathlib import Path
from typing import List

from soulstruct.containers.bnd import BND, BNDEntry
from soulstruct.utilities import read_chars_from_buffer, create_bak, PACKAGE_PATH, get_startupinfo, unpack_from_buffer
from soulstruct.utilities.binary_struct import BinaryStruct

from .exceptions import LuaError, LuaCompileError, LuaDecompileError

_LOGGER = logging.getLogger(__name__)

COMPILER_x64 = str(PACKAGE_PATH("ai/lua/x64/LuaC.exe"))
COMPILER_x86 = str(PACKAGE_PATH("ai/lua/x86/luac50.exe"))
DECOMPILER_x64 = str(PACKAGE_PATH("ai/lua/x64/DSLuaDecompiler.exe"))
# No x86 decompiler.

_SNAKE_CASE_RE = re.compile(r"(?<!^)(?=[A-Z])")
_GOAL_SCRIPT_RE = re.compile(r"^(\d{6})_(battle|logic)\.lua$")
_LUA_SCRIPT_RE = re.compile(r"(.*)\.lua$")


class LuaBND:
    """Automatically loads all scripts, LuaInfo, and LuaGNL objects."""
    def __init__(self,
                 luabnd_path,
                 sort_goals=True,
                 require_luainfo=False,
Exemplo n.º 10
0
    default_game_path=DES_PATH,
    executable_name="EBOOT.BIN",
)
DEMONS_SOULS_REMAKE = Game(
    "Demon's Souls Remake",
    aliases=("demonssoulsremake", "desr"),
    uses_dcx=False,  # TODO: Unknown.
    default_game_path=DESR_PATH,
)
DARK_SOULS_PTDE = Game(
    "Dark Souls Prepare to Die Edition",
    subpackage_name="darksouls1ptde",
    aliases=("darksoulspreparetodieedition", "darksoulsptde", "ptde",
             "darksouls1ptde"),
    uses_dcx=False,
    bundled_paramdef_path=PACKAGE_PATH(
        "darksouls1ptde/params/resources/darksouls1ptde.paramdefbnd"),
    steam_appid=211420,
    default_game_path=PTDE_PATH,
    generic_game_path=
    "C:/Program Files (x86)/Steam/steamapps/common/Dark Souls Prepare to Die Edition/DATA",
    save_file_path=Path("~/Documents/NBGI/DarkSouls").expanduser(),
    executable_name="DARKSOULS.exe",
    gadget_name="DS Gadget.exe",
    default_file_paths={
        "AIDirectory": "script",
        "DrawParamDirectory": "param/DrawParam",
        "EMEVDDirectory": "event",
        "GameParamBND": "param/GameParam/GameParam.parambnd",
        "MapStudioDirectory": "map/MapStudio",
        "MSGDirectory": "msg/ENGLISH",
        "ParamDefBND": "paramdef/paramdef.paramdefbnd",