Skip to content

Commit

Permalink
Prep for SR editor
Browse files Browse the repository at this point in the history
  • Loading branch information
ThanatosGit committed Aug 10, 2023
1 parent a85eb75 commit 67eaf71
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 26 deletions.
6 changes: 3 additions & 3 deletions src/mercury_engine_data_structures/formats/bmsad.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def find_charclass_for_type(type_name: str):
return as_char

return find_charclass_for_type(
type_lib.get_parent_for(type_name),
type_lib.get_parent_for(Game.DREAD, type_name),
)


Expand Down Expand Up @@ -124,7 +124,7 @@ def DreadDependencies():

def component_type(this):
for component_type in component_dependencies.keys():
if type_lib.is_child_of(this.type, component_type):
if type_lib.is_child_of(Game.DREAD, this.type, component_type):
return component_type
return None

Expand Down Expand Up @@ -165,7 +165,7 @@ def component_type(this):
)
),
extra_fields=construct.If(
lambda this: type_lib.is_child_of(this.type, "CComponent"),
lambda this: type_lib.is_child_of(Game.DREAD, this.type, "CComponent"),
ExtraFields,
),
functions=Functions,
Expand Down
11 changes: 11 additions & 0 deletions src/mercury_engine_data_structures/formats/bmsld.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from typing import Iterator
import construct
from construct import Array, Const, Construct, Flag, Float32l, Hex, Int32ul, Struct

Expand Down Expand Up @@ -172,3 +173,13 @@ class Bmsld(BaseResource):
@classmethod
def construct_class(cls, target_game: Game) -> Construct:
return BMSLD

def all_actor_groups(self) -> Iterator[str]:
for area in self.raw.sub_areas:
yield area.name

def is_actor_in_group(self, group_name: str, actor_name: str, layer_name: str = "default") -> bool:
generator = (area for area in self.raw.sub_areas if area.name == group_name)
for area in generator:
return actor_name in area.names
return False
5 changes: 3 additions & 2 deletions src/mercury_engine_data_structures/formats/standard_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from mercury_engine_data_structures import type_lib
from mercury_engine_data_structures.formats.property_enum import PropertyEnum
from mercury_engine_data_structures.game_check import Game


def create(name: str, version: int, root_name: Optional[str] = None, explicit_root: bool = False):
Expand All @@ -14,10 +15,10 @@ def create(name: str, version: int, root_name: Optional[str] = None, explicit_ro
root = construct.FocusedSeq(
"root",
"type" / construct.Rebuild(PropertyEnum, name),
"root" / type_lib.GetTypeConstruct(lambda this: this._.type)
"root" / type_lib.GetTypeConstruct(Game.DREAD, lambda this: this._.type)
)
else:
root = type_lib.get_type(root_name).construct
root = type_lib.get_type(Game.DREAD, root_name).construct

result = construct.Struct(
_class_crc=construct.Const(name, PropertyEnum),
Expand Down
4 changes: 3 additions & 1 deletion src/mercury_engine_data_structures/samus_returns_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@

@functools.lru_cache
def get_raw_types() -> Dict[str, typing.Any]:
raise NotImplementedError()
path = Path(__file__).parent.joinpath("samus_returns_types.json")
with path.open() as f:
return json.load(f)


@functools.lru_cache
Expand Down
62 changes: 62 additions & 0 deletions src/mercury_engine_data_structures/samus_returns_types.json
Original file line number Diff line number Diff line change
Expand Up @@ -1347,5 +1347,67 @@
"kind":"struct",
"parent": "CZetaAttack",
"fields": {}
},
"ProperActor": {
"kind": "struct",
"parent": "CGameObject",
"fields": {
"type": "base::global::StrId",
"x": "float",
"y": "float",
"z": "float",
"unk05": "unsigned",
"unk06": "unsigned",
"unk07": "unsigned",
"components": "base::global::CRntVector<Component>"
}
},
"CGameObject": {
"kind": "struct",
"parent": "base::core::CBaseObject",
"fields": {}
},
"Component": {
"kind": "struct",
"parent": "CGameObject",
"fields": {
"component_type": "base::global::StrId",
"command": "base::global::StrId",
"arguments": "base::global::CRntVector<FunctionArgument>"
}
},
"FunctionArgument": {
"kind": "struct",
"parent": "CGameObject",
"fields": {
"type": "base::global::StrId",
"value": "base::global::StrId"
}
},
"base::global::StrId": {
"kind": "primitive",
"primitive_kind": "string"
},
"base::core::CBaseObject": {
"kind": "struct",
"parent": null,
"fields": {}
},
"base::global::CRntVector<Component>": {
"kind": "vector",
"value_type": "Component"
},

"base::global::CRntVector<FunctionArgument>": {
"kind": "vector",
"value_type": "FunctionArgument"
},
"float": {
"kind": "primitive",
"primitive_kind": "float"
},
"unsigned": {
"kind": "primitive",
"primitive_kind": "uint"
}
}
2 changes: 1 addition & 1 deletion src/mercury_engine_data_structures/sr_resource_names.json
Original file line number Diff line number Diff line change
Expand Up @@ -11613,7 +11613,7 @@
"packs/cutscenes/intrometroidboss_discardables.pkg": 1759505438,
"packs/cutscenes/intrometroidlarvasurface.pkg": 366587959,
"packs/cutscenes/intrometroidlarvasurface_discardables.pkg": 4046021773,
"packs/cutscenes/introomega.pkg": 723017427,
"packs/cutscenes/introomega.pkg": 3477018848,
"packs/cutscenes/introomega_discardables.pkg": 682647711,
"packs/cutscenes/introqueen.pkg": 803003252,
"packs/cutscenes/introqueen_discardables.pkg": 2787700573,
Expand Down
41 changes: 22 additions & 19 deletions src/mercury_engine_data_structures/type_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import construct

from mercury_engine_data_structures import dread_data
from mercury_engine_data_structures import samus_returns_data
from mercury_engine_data_structures.game_check import Game, is_dread

# from mercury_engine_data_structures.construct_extensions.misc import ErrorWithMessage

Expand Down Expand Up @@ -203,47 +205,48 @@ def decode_type(name: str, data: dict) -> BaseType:


@functools.lru_cache
def all_types() -> Dict[str, BaseType]:
def all_types(game: Game) -> Dict[str, BaseType]:
data = dread_data if is_dread(game) else samus_returns_data
return {
name: decode_type(name, data)
for name, data in dread_data.get_raw_types().items()
for name, data in data.get_raw_types().items()
}


@functools.lru_cache
def all_constructs() -> Dict[str, construct.Construct]:
def all_constructs(game: Game) -> Dict[str, construct.Construct]:
return {
name: type.construct
for name, type in all_types().items()
for name, type in all_types(game).items()
}


def get_type(type_name: str, *, follow_typedef: bool = True) -> BaseType:
result = all_types()[type_name]
def get_type(game: Game, type_name: str, *, follow_typedef: bool = True) -> BaseType:
result = all_types(game)[type_name]

if follow_typedef and result.kind == TypeKind.TYPEDEF:
assert isinstance(result, TypedefType)
return get_type(result.alias, follow_typedef=follow_typedef)
return get_type(game, result.alias, follow_typedef=follow_typedef)

return result


def GetTypeConstruct(keyfunc, follow_typedef: bool = True) -> construct.Construct:
def GetTypeConstruct(game: Game, keyfunc, follow_typedef: bool = True) -> construct.Construct:
return construct.FocusedSeq(
"switch",
"key" / construct.Computed(keyfunc),
"type" / construct.Computed(lambda this: get_type(this.key, follow_typedef=follow_typedef).name),
"type" / construct.Computed(lambda this: get_type(game, this.key, follow_typedef=follow_typedef).name),
"switch" / construct.Switch(
lambda this: this.type,
all_constructs(),
all_constructs(game),
construct.Error
# ErrorWithMessage(lambda this: f"Unknown type: {this.type}", construct.SwitchError)
)
)


def get_parent_for(type_name: str) -> Optional[str]:
data = get_type(type_name)
def get_parent_for(game: Game, type_name: str) -> Optional[str]:
data = get_type(game, type_name)

if data.kind == TypeKind.STRUCT:
assert isinstance(data, StructType)
Expand All @@ -252,7 +255,7 @@ def get_parent_for(type_name: str) -> Optional[str]:
return None


def is_child_of(type_name: Optional[str], parent_name: str) -> bool:
def is_child_of(game: Game, type_name: Optional[str], parent_name: str) -> bool:
"""
Checks if the type_name is a direct or indirect child of the type parent_name
"""
Expand All @@ -262,24 +265,24 @@ def is_child_of(type_name: Optional[str], parent_name: str) -> bool:
if type_name is None:
return False

return is_child_of(get_parent_for(type_name), parent_name)
return is_child_of(game, get_parent_for(game, type_name), parent_name)


@functools.lru_cache
def all_direct_children() -> Dict[str, Set[str]]:
def all_direct_children(game: Game) -> Dict[str, Set[str]]:
"""
Returns a mapping of type names to all their direct children.
"""
result = collections.defaultdict(set)

for type_name in all_types().keys():
if (parent := get_parent_for(type_name)) is not None:
for type_name in all_types(game).keys():
if (parent := get_parent_for(game, type_name)) is not None:
result[parent].add(type_name)

return dict(result)


def get_all_children_for(type_name: str) -> Set[str]:
def get_all_children_for(game: Game, type_name: str) -> Set[str]:
"""
Get all direct and indirect children for a given type.
"""
Expand All @@ -293,6 +296,6 @@ def get_all_children_for(type_name: str) -> Set[str]:
continue
result.add(next_type)

types_to_check.update(all_direct_children().get(next_type, set()))
types_to_check.update(all_direct_children(game).get(next_type, set()))

return result

0 comments on commit 67eaf71

Please sign in to comment.