From 976c4c1dfe5b9b08f99ab9b892d4ff4aeb2da9f1 Mon Sep 17 00:00:00 2001 From: Mayberry Date: Fri, 30 Aug 2024 21:34:55 -0400 Subject: [PATCH 01/31] Refactor BRFLD --- .../formats/brfld.py | 45 ++++++++++--------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index 57575b0e..5939635e 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -17,16 +17,16 @@ class Brfld(BaseResource): def construct_class(cls, target_game: Game) -> construct.Construct: return standard_format.game_model("CScenario", "49.0.2") - def actors_for_layer(self, name: str) -> dict: - return self.raw.Root.pScenario.rEntitiesLayer.dctSublayers[name].dctActors + def actors_for_sublayer(self, sublayer_name: str, layer_name: str = "rEntitiesLayer") -> dict: + return self.raw.Root.pScenario[layer_name].dctSublayers[sublayer_name].dctActors - def all_layers(self) -> Iterator[str]: - yield from self.raw.Root.pScenario.rEntitiesLayer.dctSublayers.keys() + def sublayers_for_layer(self, layer_name: str) -> Iterator[str]: + yield from self.raw.Root.pScenario[layer_name].dctSublayers.keys() - def all_actors(self) -> Iterator[Tuple[str, str, construct.Container]]: - for layer_name, sublayer in self.raw.Root.pScenario.rEntitiesLayer.dctSublayers.items(): + def all_actors_in_layer(self, layer_name: str = "rEntitiesLayer") -> Iterator[Tuple[str, str, construct.Container]]: + for sublayer_name, sublayer in self.raw.Root.pScenario[layer_name].dctSublayers.items(): for actor_name, actor in sublayer.dctActors.items(): - yield layer_name, actor_name, actor + yield sublayer_name, actor_name, actor def follow_link(self, link: str): if link != "{EMPTY}": @@ -35,42 +35,43 @@ def follow_link(self, link: str): result = result[part] return result - def link_for_actor(self, actor_name: str, layer_name: str = "default") -> str: - return ":".join(["Root", "pScenario", "rEntitiesLayer", "dctSublayers", layer_name, "dctActors", actor_name]) + def link_for_actor(self, actor_name: str, sublayer_name: str = "default", layer_name: str = "rEntitiesLayer") -> str: + return ":".join(["Root", "pScenario", layer_name, "dctSublayers", sublayer_name, "dctActors", actor_name]) - def all_actor_groups(self) -> Iterator[str]: - yield from self.raw.Root.pScenario.rEntitiesLayer.dctActorGroups.keys() + def actor_groups_for_layer(self, layer_name: str = "rEntitiesLayer") -> Iterator[str]: + yield from self.raw.Root.pScenario[layer_name].dctActorGroups.keys() - def get_actor_group(self, group_name: str) -> List[str]: - return self.raw.Root.pScenario.rEntitiesLayer.dctActorGroups[group_name] + def get_actor_group(self, group_name: str, layer_name: str = "rEntitiesLayer") -> List[str]: + return self.raw.Root.pScenario[layer_name].dctActorGroups[group_name] - def is_actor_in_group(self, group_name: str, actor_name: str, layer_name: str = "default") -> bool: - return self.link_for_actor(actor_name, layer_name) in self.get_actor_group(group_name) + def is_actor_in_group(self, group_name: str, actor_name: str, sublayer_name: str = "default", layer_name: str = "rEntitiesLayer") -> bool: + return self.link_for_actor(actor_name, sublayer_name, layer_name) in self.get_actor_group(group_name) - def add_actor_to_group(self, group_name: str, actor_name: str, layer_name: str = "default"): + def add_actor_to_group(self, group_name: str, actor_name: str, sublayer_name: str = "default", layer_name: str = "rEntitiesLayer"): group = self.get_actor_group(group_name) - actor_link = self.link_for_actor(actor_name, layer_name) + actor_link = self.link_for_actor(actor_name, sublayer_name, layer_name) if actor_link not in group: group.append(actor_link) - def remove_actor_from_group(self, group_name: str, actor_name: str, layer_name: str = "default"): + def remove_actor_from_group(self, group_name: str, actor_name: str, sublayer_name: str = "default", layer_name: str = "rEntitiesLayer"): group = self.get_actor_group(group_name) - actor_link = self.link_for_actor(actor_name, layer_name) + actor_link = self.link_for_actor(actor_name, sublayer_name, layer_name) if actor_link in group: group.remove(actor_link) - def add_actor_to_entity_groups(self, collision_camera_name: str, actor_name: str, layer_name: str = "default"): + def add_actor_to_entity_groups(self, collision_camera_name: str, actor_name: str, sublayer_name: str = "default", layer_name: str = "rEntitiesLayer"): """ adds an actor to all entity groups starting with "eg_" + collision_camera_name param collision_camera_name: name of the collision camera group (prefix "eg_" is added to find the entity groups) param actor_name: name of the actor to add to the group - param layer_name: name of the layer the actor belongs to + param sublayer_name: name of the sublayer the actor belongs to + param layer_name: name of the layer the sublayer belongs to """ collision_camera_groups = [ group for group in self.all_actor_groups() if group.startswith(f"eg_{collision_camera_name}") ] for group in collision_camera_groups: logger.debug("Add actor %s to group %s", actor_name, group) - self.add_actor_to_group(group, actor_name, layer_name) + self.add_actor_to_group(group, actor_name, sublayer_name, layer_name) From ab062d41b1ae69ededb720928b9eb980093cd8b8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 31 Aug 2024 01:41:59 +0000 Subject: [PATCH 02/31] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../formats/brfld.py | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index 5939635e..0d548345 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -35,7 +35,9 @@ def follow_link(self, link: str): result = result[part] return result - def link_for_actor(self, actor_name: str, sublayer_name: str = "default", layer_name: str = "rEntitiesLayer") -> str: + def link_for_actor( + self, actor_name: str, sublayer_name: str = "default", layer_name: str = "rEntitiesLayer" + ) -> str: return ":".join(["Root", "pScenario", layer_name, "dctSublayers", sublayer_name, "dctActors", actor_name]) def actor_groups_for_layer(self, layer_name: str = "rEntitiesLayer") -> Iterator[str]: @@ -44,22 +46,34 @@ def actor_groups_for_layer(self, layer_name: str = "rEntitiesLayer") -> Iterator def get_actor_group(self, group_name: str, layer_name: str = "rEntitiesLayer") -> List[str]: return self.raw.Root.pScenario[layer_name].dctActorGroups[group_name] - def is_actor_in_group(self, group_name: str, actor_name: str, sublayer_name: str = "default", layer_name: str = "rEntitiesLayer") -> bool: + def is_actor_in_group( + self, group_name: str, actor_name: str, sublayer_name: str = "default", layer_name: str = "rEntitiesLayer" + ) -> bool: return self.link_for_actor(actor_name, sublayer_name, layer_name) in self.get_actor_group(group_name) - def add_actor_to_group(self, group_name: str, actor_name: str, sublayer_name: str = "default", layer_name: str = "rEntitiesLayer"): + def add_actor_to_group( + self, group_name: str, actor_name: str, sublayer_name: str = "default", layer_name: str = "rEntitiesLayer" + ): group = self.get_actor_group(group_name) actor_link = self.link_for_actor(actor_name, sublayer_name, layer_name) if actor_link not in group: group.append(actor_link) - def remove_actor_from_group(self, group_name: str, actor_name: str, sublayer_name: str = "default", layer_name: str = "rEntitiesLayer"): + def remove_actor_from_group( + self, group_name: str, actor_name: str, sublayer_name: str = "default", layer_name: str = "rEntitiesLayer" + ): group = self.get_actor_group(group_name) actor_link = self.link_for_actor(actor_name, sublayer_name, layer_name) if actor_link in group: group.remove(actor_link) - def add_actor_to_entity_groups(self, collision_camera_name: str, actor_name: str, sublayer_name: str = "default", layer_name: str = "rEntitiesLayer"): + def add_actor_to_entity_groups( + self, + collision_camera_name: str, + actor_name: str, + sublayer_name: str = "default", + layer_name: str = "rEntitiesLayer", + ): """ adds an actor to all entity groups starting with "eg_" + collision_camera_name From cfef4c3fd443130279f5d1666fb37566009b958f Mon Sep 17 00:00:00 2001 From: Mayberry Date: Mon, 7 Oct 2024 16:03:24 -0400 Subject: [PATCH 03/31] Rename layer to actor_layer and use enum for it --- .../formats/brfld.py | 63 ++++++++++++------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index 0d548345..b4a073b9 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -1,5 +1,6 @@ import functools import logging +from enum import Enum, auto from typing import Iterator, List, Tuple import construct @@ -11,20 +12,28 @@ logger = logging.getLogger(__name__) +class ActorLayer(Enum): + ENTITIES = auto + SOUNDS = auto + LIGHTS = auto + + class Brfld(BaseResource): @classmethod @functools.lru_cache def construct_class(cls, target_game: Game) -> construct.Construct: return standard_format.game_model("CScenario", "49.0.2") - def actors_for_sublayer(self, sublayer_name: str, layer_name: str = "rEntitiesLayer") -> dict: - return self.raw.Root.pScenario[layer_name].dctSublayers[sublayer_name].dctActors + def actors_for_sublayer(self, sublayer_name: str, actor_layer_name: ActorLayer = ActorLayer.ENTITIES) -> dict: + return self.raw.Root.pScenario[actor_layer_name].dctSublayers[sublayer_name].dctActors - def sublayers_for_layer(self, layer_name: str) -> Iterator[str]: - yield from self.raw.Root.pScenario[layer_name].dctSublayers.keys() + def sublayers_for_actor_layer(self, actor_layer_name: ActorLayer = ActorLayer.ENTITIES) -> Iterator[str]: + yield from self.raw.Root.pScenario[actor_layer_name].dctSublayers.keys() - def all_actors_in_layer(self, layer_name: str = "rEntitiesLayer") -> Iterator[Tuple[str, str, construct.Container]]: - for sublayer_name, sublayer in self.raw.Root.pScenario[layer_name].dctSublayers.items(): + def all_actors_in_actor_layer( + self, actor_layer_name: ActorLayer = ActorLayer.ENTITIES + ) -> Iterator[Tuple[str, str, construct.Container]]: + for sublayer_name, sublayer in self.raw.Root.pScenario[actor_layer_name].dctSublayers.items(): for actor_name, actor in sublayer.dctActors.items(): yield sublayer_name, actor_name, actor @@ -36,34 +45,46 @@ def follow_link(self, link: str): return result def link_for_actor( - self, actor_name: str, sublayer_name: str = "default", layer_name: str = "rEntitiesLayer" + self, actor_name: str, sublayer_name: str = "default", actor_layer_name: ActorLayer = ActorLayer.ENTITIES ) -> str: - return ":".join(["Root", "pScenario", layer_name, "dctSublayers", sublayer_name, "dctActors", actor_name]) + return ":".join(["Root", "pScenario", actor_layer_name, "dctSublayers", sublayer_name, "dctActors", actor_name]) - def actor_groups_for_layer(self, layer_name: str = "rEntitiesLayer") -> Iterator[str]: - yield from self.raw.Root.pScenario[layer_name].dctActorGroups.keys() + def actor_groups_for_actor_layer(self, actor_layer_name: ActorLayer = ActorLayer.ENTITIES) -> Iterator[str]: + yield from self.raw.Root.pScenario[actor_layer_name].dctActorGroups.keys() - def get_actor_group(self, group_name: str, layer_name: str = "rEntitiesLayer") -> List[str]: - return self.raw.Root.pScenario[layer_name].dctActorGroups[group_name] + def get_actor_group(self, group_name: str, actor_layer_name: ActorLayer = ActorLayer.ENTITIES) -> List[str]: + return self.raw.Root.pScenario[actor_layer_name].dctActorGroups[group_name] def is_actor_in_group( - self, group_name: str, actor_name: str, sublayer_name: str = "default", layer_name: str = "rEntitiesLayer" + self, + group_name: str, + actor_name: str, + sublayer_name: str = "default", + actor_layer_name: ActorLayer = ActorLayer.ENTITIES, ) -> bool: - return self.link_for_actor(actor_name, sublayer_name, layer_name) in self.get_actor_group(group_name) + return self.link_for_actor(actor_name, sublayer_name, actor_layer_name) in self.get_actor_group(group_name) def add_actor_to_group( - self, group_name: str, actor_name: str, sublayer_name: str = "default", layer_name: str = "rEntitiesLayer" + self, + group_name: str, + actor_name: str, + sublayer_name: str = "default", + actor_layer_name: ActorLayer = ActorLayer.ENTITIES, ): group = self.get_actor_group(group_name) - actor_link = self.link_for_actor(actor_name, sublayer_name, layer_name) + actor_link = self.link_for_actor(actor_name, sublayer_name, actor_layer_name) if actor_link not in group: group.append(actor_link) def remove_actor_from_group( - self, group_name: str, actor_name: str, sublayer_name: str = "default", layer_name: str = "rEntitiesLayer" + self, + group_name: str, + actor_name: str, + sublayer_name: str = "default", + actor_layer_name: ActorLayer = ActorLayer.ENTITIES, ): group = self.get_actor_group(group_name) - actor_link = self.link_for_actor(actor_name, sublayer_name, layer_name) + actor_link = self.link_for_actor(actor_name, sublayer_name, actor_layer_name) if actor_link in group: group.remove(actor_link) @@ -72,7 +93,7 @@ def add_actor_to_entity_groups( collision_camera_name: str, actor_name: str, sublayer_name: str = "default", - layer_name: str = "rEntitiesLayer", + actor_layer_name: ActorLayer = ActorLayer.ENTITIES, ): """ adds an actor to all entity groups starting with "eg_" + collision_camera_name @@ -81,11 +102,11 @@ def add_actor_to_entity_groups( (prefix "eg_" is added to find the entity groups) param actor_name: name of the actor to add to the group param sublayer_name: name of the sublayer the actor belongs to - param layer_name: name of the layer the sublayer belongs to + param actor_layer_name: the actor layer the sublayer belongs to """ collision_camera_groups = [ group for group in self.all_actor_groups() if group.startswith(f"eg_{collision_camera_name}") ] for group in collision_camera_groups: logger.debug("Add actor %s to group %s", actor_name, group) - self.add_actor_to_group(group, actor_name, sublayer_name, layer_name) + self.add_actor_to_group(group, actor_name, sublayer_name, actor_layer_name) From 2c49930255a03215221b5702a558e88af2e9bf2e Mon Sep 17 00:00:00 2001 From: Mayberry Date: Thu, 10 Oct 2024 21:59:35 -0400 Subject: [PATCH 04/31] Get actor group by actor layer in add/remove actor from group functions --- src/mercury_engine_data_structures/formats/brfld.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index b4a073b9..dbafaac9 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -71,7 +71,7 @@ def add_actor_to_group( sublayer_name: str = "default", actor_layer_name: ActorLayer = ActorLayer.ENTITIES, ): - group = self.get_actor_group(group_name) + group = self.get_actor_group(group_name, actor_layer_name) actor_link = self.link_for_actor(actor_name, sublayer_name, actor_layer_name) if actor_link not in group: group.append(actor_link) @@ -83,7 +83,7 @@ def remove_actor_from_group( sublayer_name: str = "default", actor_layer_name: ActorLayer = ActorLayer.ENTITIES, ): - group = self.get_actor_group(group_name) + group = self.get_actor_group(group_name, actor_layer_name) actor_link = self.link_for_actor(actor_name, sublayer_name, actor_layer_name) if actor_link in group: group.remove(actor_link) From 64d002ca07c58883c297f470cbb3b0ff7a176b34 Mon Sep 17 00:00:00 2001 From: Mayberry Date: Thu, 10 Oct 2024 22:01:42 -0400 Subject: [PATCH 05/31] Use strings in ActorLayer enum --- src/mercury_engine_data_structures/formats/brfld.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index dbafaac9..3a76a02b 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -13,9 +13,9 @@ class ActorLayer(Enum): - ENTITIES = auto - SOUNDS = auto - LIGHTS = auto + ENTITIES = "rEntitiesLayer" + SOUNDS = "rSoundsLayer" + LIGHTS = "rLightsLayer" class Brfld(BaseResource): From 96da27b2dc1e90667a039ea8dada398996105508 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 11 Oct 2024 02:01:50 +0000 Subject: [PATCH 06/31] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/mercury_engine_data_structures/formats/brfld.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index 3a76a02b..64bb0917 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -1,6 +1,6 @@ import functools import logging -from enum import Enum, auto +from enum import Enum from typing import Iterator, List, Tuple import construct From c37ecb2a37044ac877368be638ab6b7eb09bbf2f Mon Sep 17 00:00:00 2001 From: Mayberry Date: Sat, 12 Oct 2024 11:31:05 -0400 Subject: [PATCH 07/31] Add method to add actor to actor groups in other actor layers --- .../formats/brfld.py | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index 64bb0917..ad217f30 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -88,7 +88,7 @@ def remove_actor_from_group( if actor_link in group: group.remove(actor_link) - def add_actor_to_entity_groups( + def add_actor_to_actor_groups( self, collision_camera_name: str, actor_name: str, @@ -96,17 +96,31 @@ def add_actor_to_entity_groups( actor_layer_name: ActorLayer = ActorLayer.ENTITIES, ): """ - adds an actor to all entity groups starting with "eg_" + collision_camera_name + adds an actor to all actor groups starting with collision_camera_name param collision_camera_name: name of the collision camera group - (prefix "eg_" is added to find the entity groups) param actor_name: name of the actor to add to the group param sublayer_name: name of the sublayer the actor belongs to param actor_layer_name: the actor layer the sublayer belongs to """ collision_camera_groups = [ - group for group in self.all_actor_groups() if group.startswith(f"eg_{collision_camera_name}") + group for group in self.all_actor_groups() if group.startswith(collision_camera_name) ] for group in collision_camera_groups: logger.debug("Add actor %s to group %s", actor_name, group) self.add_actor_to_group(group, actor_name, sublayer_name, actor_layer_name) + + def add_actor_to_entity_groups( + self, + collision_camera_name: str, + actor_name: str, + sublayer_name: str = "default", + ): + """ + adds an actor to all entity groups starting with "eg_" + collision_camera_name + + param collision_camera_name: name of the collision camera group (prefix "eg_" is added) + param actor_name: name of the actor to add to the group + param sublayer_name: name of the sublayer the actor belongs to + """ + self.add_actor_to_actor_groups(f"eg_{collision_camera_name}", actor_name, sublayer_name, ActorLayer.ENTITIES) From 0ac279c802cf47683896e97b062c23349c78c8af Mon Sep 17 00:00:00 2001 From: Mayberry Date: Sat, 12 Oct 2024 11:31:19 -0400 Subject: [PATCH 08/31] Add test for adding actor to actor groups --- tests/formats/test_brfld.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tests/formats/test_brfld.py b/tests/formats/test_brfld.py index 8a2ad4a6..2a2dad0d 100644 --- a/tests/formats/test_brfld.py +++ b/tests/formats/test_brfld.py @@ -2,7 +2,7 @@ from tests.test_lib import parse_build_compare_editor from mercury_engine_data_structures import dread_data -from mercury_engine_data_structures.formats.brfld import Brfld +from mercury_engine_data_structures.formats.brfld import ActorLayer, Brfld bossrush_assets = [ "maps/levels/c10_samus/s201_bossrush_scorpius/s201_bossrush_scorpius.brfld", @@ -28,3 +28,24 @@ def test_dread_brfld_100(dread_tree_100, brfld_path): @pytest.mark.parametrize("brfld_path", bossrush_assets) def test_dread_brfld_210(dread_tree_210, brfld_path): parse_build_compare_editor(Brfld, dread_tree_210, brfld_path) + + +def test_add_actor_to_actor_groups(dread_tree_100): + scenario = dread_tree_100.get_file("maps/levels/c10_samus/s010_cave/s010_cave.brfld", Brfld) + + scenario.add_actor_to_entity_groups("collision_camera_000", "breakabletilegroup_000", "breakables") + assert scenario.is_actor_in_group("eg_collision_camera_000", "breakabletilegroup_000", "breakables") + + scenario.add_actor_to_actor_groups( + "ssg_collision_camera_000_Default", "Pos_C_LavaWindow_06", actor_layer_name=ActorLayer.SOUNDS + ) + assert scenario.is_actor_in_group( + "ssg_collision_camera_000_Default", "Pos_C_LavaWindow_06", actor_layer_name=ActorLayer.SOUNDS + ) + + scenario.add_actor_to_actor_groups( + "lg_collision_camera_000", "cubemap_006_1_bake", "emmy_006_light", ActorLayer.LIGHTS + ) + assert scenario.is_actor_in_group( + "lg_collision_camera_000", "cubemap_006_1_bake", "emmy_006_light", ActorLayer.LIGHTS + ) From 428922d49942d83c80e6bb619ffcb45be586ae63 Mon Sep 17 00:00:00 2001 From: Mayberry Date: Sat, 12 Oct 2024 11:50:12 -0400 Subject: [PATCH 09/31] Remove add_actor_to_entity_groups method --- .../formats/brfld.py | 15 --------------- tests/formats/test_brfld.py | 2 +- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index ad217f30..4ad7bce3 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -109,18 +109,3 @@ def add_actor_to_actor_groups( for group in collision_camera_groups: logger.debug("Add actor %s to group %s", actor_name, group) self.add_actor_to_group(group, actor_name, sublayer_name, actor_layer_name) - - def add_actor_to_entity_groups( - self, - collision_camera_name: str, - actor_name: str, - sublayer_name: str = "default", - ): - """ - adds an actor to all entity groups starting with "eg_" + collision_camera_name - - param collision_camera_name: name of the collision camera group (prefix "eg_" is added) - param actor_name: name of the actor to add to the group - param sublayer_name: name of the sublayer the actor belongs to - """ - self.add_actor_to_actor_groups(f"eg_{collision_camera_name}", actor_name, sublayer_name, ActorLayer.ENTITIES) diff --git a/tests/formats/test_brfld.py b/tests/formats/test_brfld.py index 2a2dad0d..02bcbec9 100644 --- a/tests/formats/test_brfld.py +++ b/tests/formats/test_brfld.py @@ -33,7 +33,7 @@ def test_dread_brfld_210(dread_tree_210, brfld_path): def test_add_actor_to_actor_groups(dread_tree_100): scenario = dread_tree_100.get_file("maps/levels/c10_samus/s010_cave/s010_cave.brfld", Brfld) - scenario.add_actor_to_entity_groups("collision_camera_000", "breakabletilegroup_000", "breakables") + scenario.add_actor_to_actor_groups("collision_camera_000", "breakabletilegroup_000", "breakables") assert scenario.is_actor_in_group("eg_collision_camera_000", "breakabletilegroup_000", "breakables") scenario.add_actor_to_actor_groups( From beeee14a05826a260967e173cef8e96bdd8fd62c Mon Sep 17 00:00:00 2001 From: Mayberry Date: Sat, 12 Oct 2024 15:08:49 -0400 Subject: [PATCH 10/31] Rename actor_layer_name to actor_layer --- .../formats/brfld.py | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index 4ad7bce3..09e6a6a4 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -24,16 +24,16 @@ class Brfld(BaseResource): def construct_class(cls, target_game: Game) -> construct.Construct: return standard_format.game_model("CScenario", "49.0.2") - def actors_for_sublayer(self, sublayer_name: str, actor_layer_name: ActorLayer = ActorLayer.ENTITIES) -> dict: - return self.raw.Root.pScenario[actor_layer_name].dctSublayers[sublayer_name].dctActors + def actors_for_sublayer(self, sublayer_name: str, actor_layer: ActorLayer = ActorLayer.ENTITIES) -> dict: + return self.raw.Root.pScenario[actor_layer].dctSublayers[sublayer_name].dctActors - def sublayers_for_actor_layer(self, actor_layer_name: ActorLayer = ActorLayer.ENTITIES) -> Iterator[str]: - yield from self.raw.Root.pScenario[actor_layer_name].dctSublayers.keys() + def sublayers_for_actor_layer(self, actor_layer: ActorLayer = ActorLayer.ENTITIES) -> Iterator[str]: + yield from self.raw.Root.pScenario[actor_layer].dctSublayers.keys() def all_actors_in_actor_layer( - self, actor_layer_name: ActorLayer = ActorLayer.ENTITIES + self, actor_layer: ActorLayer = ActorLayer.ENTITIES ) -> Iterator[Tuple[str, str, construct.Container]]: - for sublayer_name, sublayer in self.raw.Root.pScenario[actor_layer_name].dctSublayers.items(): + for sublayer_name, sublayer in self.raw.Root.pScenario[actor_layer].dctSublayers.items(): for actor_name, actor in sublayer.dctActors.items(): yield sublayer_name, actor_name, actor @@ -45,34 +45,34 @@ def follow_link(self, link: str): return result def link_for_actor( - self, actor_name: str, sublayer_name: str = "default", actor_layer_name: ActorLayer = ActorLayer.ENTITIES + self, actor_name: str, sublayer_name: str = "default", actor_layer: ActorLayer = ActorLayer.ENTITIES ) -> str: - return ":".join(["Root", "pScenario", actor_layer_name, "dctSublayers", sublayer_name, "dctActors", actor_name]) + return ":".join(["Root", "pScenario", actor_layer, "dctSublayers", sublayer_name, "dctActors", actor_name]) - def actor_groups_for_actor_layer(self, actor_layer_name: ActorLayer = ActorLayer.ENTITIES) -> Iterator[str]: - yield from self.raw.Root.pScenario[actor_layer_name].dctActorGroups.keys() + def actor_groups_for_actor_layer(self, actor_layer: ActorLayer = ActorLayer.ENTITIES) -> Iterator[str]: + yield from self.raw.Root.pScenario[actor_layer].dctActorGroups.keys() - def get_actor_group(self, group_name: str, actor_layer_name: ActorLayer = ActorLayer.ENTITIES) -> List[str]: - return self.raw.Root.pScenario[actor_layer_name].dctActorGroups[group_name] + def get_actor_group(self, group_name: str, actor_layer: ActorLayer = ActorLayer.ENTITIES) -> List[str]: + return self.raw.Root.pScenario[actor_layer].dctActorGroups[group_name] def is_actor_in_group( self, group_name: str, actor_name: str, sublayer_name: str = "default", - actor_layer_name: ActorLayer = ActorLayer.ENTITIES, + actor_layer: ActorLayer = ActorLayer.ENTITIES, ) -> bool: - return self.link_for_actor(actor_name, sublayer_name, actor_layer_name) in self.get_actor_group(group_name) + return self.link_for_actor(actor_name, sublayer_name, actor_layer) in self.get_actor_group(group_name) def add_actor_to_group( self, group_name: str, actor_name: str, sublayer_name: str = "default", - actor_layer_name: ActorLayer = ActorLayer.ENTITIES, + actor_layer: ActorLayer = ActorLayer.ENTITIES, ): - group = self.get_actor_group(group_name, actor_layer_name) - actor_link = self.link_for_actor(actor_name, sublayer_name, actor_layer_name) + group = self.get_actor_group(group_name, actor_layer) + actor_link = self.link_for_actor(actor_name, sublayer_name, actor_layer) if actor_link not in group: group.append(actor_link) @@ -81,10 +81,10 @@ def remove_actor_from_group( group_name: str, actor_name: str, sublayer_name: str = "default", - actor_layer_name: ActorLayer = ActorLayer.ENTITIES, + actor_layer: ActorLayer = ActorLayer.ENTITIES, ): - group = self.get_actor_group(group_name, actor_layer_name) - actor_link = self.link_for_actor(actor_name, sublayer_name, actor_layer_name) + group = self.get_actor_group(group_name, actor_layer) + actor_link = self.link_for_actor(actor_name, sublayer_name, actor_layer) if actor_link in group: group.remove(actor_link) @@ -93,7 +93,7 @@ def add_actor_to_actor_groups( collision_camera_name: str, actor_name: str, sublayer_name: str = "default", - actor_layer_name: ActorLayer = ActorLayer.ENTITIES, + actor_layer: ActorLayer = ActorLayer.ENTITIES, ): """ adds an actor to all actor groups starting with collision_camera_name @@ -101,11 +101,11 @@ def add_actor_to_actor_groups( param collision_camera_name: name of the collision camera group param actor_name: name of the actor to add to the group param sublayer_name: name of the sublayer the actor belongs to - param actor_layer_name: the actor layer the sublayer belongs to + param actor_layer: the actor layer the sublayer belongs to """ collision_camera_groups = [ group for group in self.all_actor_groups() if group.startswith(collision_camera_name) ] for group in collision_camera_groups: logger.debug("Add actor %s to group %s", actor_name, group) - self.add_actor_to_group(group, actor_name, sublayer_name, actor_layer_name) + self.add_actor_to_group(group, actor_name, sublayer_name, actor_layer) From f340a7d4ef6228fa2af023212bc573e545cf995a Mon Sep 17 00:00:00 2001 From: Mayberry Date: Sat, 12 Oct 2024 15:09:58 -0400 Subject: [PATCH 11/31] Get actor groups with correct method in add_actor_to_actor_groups --- src/mercury_engine_data_structures/formats/brfld.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index 09e6a6a4..8870b916 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -104,7 +104,7 @@ def add_actor_to_actor_groups( param actor_layer: the actor layer the sublayer belongs to """ collision_camera_groups = [ - group for group in self.all_actor_groups() if group.startswith(collision_camera_name) + group for group in self.actor_groups_for_actor_layer(actor_layer) if group.startswith(collision_camera_name) ] for group in collision_camera_groups: logger.debug("Add actor %s to group %s", actor_name, group) From a427581a372215a2f13e705295df4f7b82fff8c7 Mon Sep 17 00:00:00 2001 From: Mayberry Date: Sat, 12 Oct 2024 16:40:19 -0400 Subject: [PATCH 12/31] Missing argument when getting actor group in is_actor_in_group --- src/mercury_engine_data_structures/formats/brfld.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index 8870b916..d55ff1ac 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -62,7 +62,7 @@ def is_actor_in_group( sublayer_name: str = "default", actor_layer: ActorLayer = ActorLayer.ENTITIES, ) -> bool: - return self.link_for_actor(actor_name, sublayer_name, actor_layer) in self.get_actor_group(group_name) + return self.link_for_actor(actor_name, sublayer_name, actor_layer) in self.get_actor_group(group_name, actor_layer) def add_actor_to_group( self, From b7fb6e48c6c0ee5fac1d14a8620d26b28f70c62a Mon Sep 17 00:00:00 2001 From: Mayberry Date: Sat, 12 Oct 2024 16:41:04 -0400 Subject: [PATCH 13/31] Use enum value to access actor layers --- src/mercury_engine_data_structures/formats/brfld.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index d55ff1ac..a6e4e177 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -25,15 +25,15 @@ def construct_class(cls, target_game: Game) -> construct.Construct: return standard_format.game_model("CScenario", "49.0.2") def actors_for_sublayer(self, sublayer_name: str, actor_layer: ActorLayer = ActorLayer.ENTITIES) -> dict: - return self.raw.Root.pScenario[actor_layer].dctSublayers[sublayer_name].dctActors + return self.raw.Root.pScenario[actor_layer.value].dctSublayers[sublayer_name].dctActors def sublayers_for_actor_layer(self, actor_layer: ActorLayer = ActorLayer.ENTITIES) -> Iterator[str]: - yield from self.raw.Root.pScenario[actor_layer].dctSublayers.keys() + yield from self.raw.Root.pScenario[actor_layer.value].dctSublayers.keys() def all_actors_in_actor_layer( self, actor_layer: ActorLayer = ActorLayer.ENTITIES ) -> Iterator[Tuple[str, str, construct.Container]]: - for sublayer_name, sublayer in self.raw.Root.pScenario[actor_layer].dctSublayers.items(): + for sublayer_name, sublayer in self.raw.Root.pScenario[actor_layer.value].dctSublayers.items(): for actor_name, actor in sublayer.dctActors.items(): yield sublayer_name, actor_name, actor @@ -47,13 +47,13 @@ def follow_link(self, link: str): def link_for_actor( self, actor_name: str, sublayer_name: str = "default", actor_layer: ActorLayer = ActorLayer.ENTITIES ) -> str: - return ":".join(["Root", "pScenario", actor_layer, "dctSublayers", sublayer_name, "dctActors", actor_name]) + return ":".join(["Root", "pScenario", actor_layer.value, "dctSublayers", sublayer_name, "dctActors", actor_name]) def actor_groups_for_actor_layer(self, actor_layer: ActorLayer = ActorLayer.ENTITIES) -> Iterator[str]: - yield from self.raw.Root.pScenario[actor_layer].dctActorGroups.keys() + yield from self.raw.Root.pScenario[actor_layer.value].dctActorGroups.keys() def get_actor_group(self, group_name: str, actor_layer: ActorLayer = ActorLayer.ENTITIES) -> List[str]: - return self.raw.Root.pScenario[actor_layer].dctActorGroups[group_name] + return self.raw.Root.pScenario[actor_layer.value].dctActorGroups[group_name] def is_actor_in_group( self, From 8954d9b7e9dfa261aa2e47e669182e9d03d21951 Mon Sep 17 00:00:00 2001 From: Mayberry Date: Sat, 12 Oct 2024 16:41:29 -0400 Subject: [PATCH 14/31] Fix collision camera names in tests --- tests/formats/test_brfld.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/formats/test_brfld.py b/tests/formats/test_brfld.py index 02bcbec9..5910f35f 100644 --- a/tests/formats/test_brfld.py +++ b/tests/formats/test_brfld.py @@ -33,14 +33,14 @@ def test_dread_brfld_210(dread_tree_210, brfld_path): def test_add_actor_to_actor_groups(dread_tree_100): scenario = dread_tree_100.get_file("maps/levels/c10_samus/s010_cave/s010_cave.brfld", Brfld) - scenario.add_actor_to_actor_groups("collision_camera_000", "breakabletilegroup_000", "breakables") - assert scenario.is_actor_in_group("eg_collision_camera_000", "breakabletilegroup_000", "breakables") + scenario.add_actor_to_actor_groups("eg_collision_camera_000", "breakabletilegroup_000", "breakables") + assert scenario.is_actor_in_group("eg_collision_camera_000_Default", "breakabletilegroup_000", "breakables") scenario.add_actor_to_actor_groups( - "ssg_collision_camera_000_Default", "Pos_C_LavaWindow_06", actor_layer_name=ActorLayer.SOUNDS + "ssg_collision_camera_000", "Pos_C_LavaWindow_06", actor_layer=ActorLayer.SOUNDS ) assert scenario.is_actor_in_group( - "ssg_collision_camera_000_Default", "Pos_C_LavaWindow_06", actor_layer_name=ActorLayer.SOUNDS + "ssg_collision_camera_000_Default", "Pos_C_LavaWindow_06", actor_layer=ActorLayer.SOUNDS ) scenario.add_actor_to_actor_groups( From aec9a37f6de467cf8dad1eeef0b67e57ac1040ec Mon Sep 17 00:00:00 2001 From: Mayberry Date: Sat, 12 Oct 2024 17:09:19 -0400 Subject: [PATCH 15/31] Add missing type hints --- src/mercury_engine_data_structures/formats/brfld.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index a6e4e177..926665ef 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -1,7 +1,7 @@ import functools import logging from enum import Enum -from typing import Iterator, List, Tuple +from typing import Any, Iterator, List, Tuple import construct @@ -37,7 +37,7 @@ def all_actors_in_actor_layer( for actor_name, actor in sublayer.dctActors.items(): yield sublayer_name, actor_name, actor - def follow_link(self, link: str): + def follow_link(self, link: str) -> Any | None: if link != "{EMPTY}": result = self.raw for part in link.split(":"): @@ -70,7 +70,7 @@ def add_actor_to_group( actor_name: str, sublayer_name: str = "default", actor_layer: ActorLayer = ActorLayer.ENTITIES, - ): + ) -> None: group = self.get_actor_group(group_name, actor_layer) actor_link = self.link_for_actor(actor_name, sublayer_name, actor_layer) if actor_link not in group: @@ -82,7 +82,7 @@ def remove_actor_from_group( actor_name: str, sublayer_name: str = "default", actor_layer: ActorLayer = ActorLayer.ENTITIES, - ): + ) -> None: group = self.get_actor_group(group_name, actor_layer) actor_link = self.link_for_actor(actor_name, sublayer_name, actor_layer) if actor_link in group: @@ -94,7 +94,7 @@ def add_actor_to_actor_groups( actor_name: str, sublayer_name: str = "default", actor_layer: ActorLayer = ActorLayer.ENTITIES, - ): + ) -> None: """ adds an actor to all actor groups starting with collision_camera_name From eb364cef403256a9b0d968b84a75ec5bd840f40e Mon Sep 17 00:00:00 2001 From: Mayberry Date: Sat, 12 Oct 2024 17:09:30 -0400 Subject: [PATCH 16/31] Add and update docstrings --- .../formats/brfld.py | 69 +++++++++++++++++-- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index 926665ef..d81e3565 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -25,19 +25,40 @@ def construct_class(cls, target_game: Game) -> construct.Construct: return standard_format.game_model("CScenario", "49.0.2") def actors_for_sublayer(self, sublayer_name: str, actor_layer: ActorLayer = ActorLayer.ENTITIES) -> dict: + """ + Gets the actors in a sublayer + + param sublayer_name: the name of the sublayer to get the actors of + param actor_layer: the actor_layer the sublayer is in + returns: the actors in the sublayer""" return self.raw.Root.pScenario[actor_layer.value].dctSublayers[sublayer_name].dctActors def sublayers_for_actor_layer(self, actor_layer: ActorLayer = ActorLayer.ENTITIES) -> Iterator[str]: + """ + Iterably gets the names of every sublayer in an actor layer + + param actor_layer: the actor layer to get the sublayers of + returns: the name of each sublayer""" yield from self.raw.Root.pScenario[actor_layer.value].dctSublayers.keys() def all_actors_in_actor_layer( self, actor_layer: ActorLayer = ActorLayer.ENTITIES ) -> Iterator[Tuple[str, str, construct.Container]]: + """ + Iterably gets every actor in an actor layer + + param actor_layer: the actor layer to get the actors of + returns: each actor in the actor layer""" for sublayer_name, sublayer in self.raw.Root.pScenario[actor_layer.value].dctSublayers.items(): for actor_name, actor in sublayer.dctActors.items(): yield sublayer_name, actor_name, actor def follow_link(self, link: str) -> Any | None: + """ + Gets the object a link is referencing + + param link: the link to follow + returns: the part of the BRFLD link is referencing""" if link != "{EMPTY}": result = self.raw for part in link.split(":"): @@ -47,12 +68,30 @@ def follow_link(self, link: str) -> Any | None: def link_for_actor( self, actor_name: str, sublayer_name: str = "default", actor_layer: ActorLayer = ActorLayer.ENTITIES ) -> str: + """ + Builds a link for an actor + + param actor_name: the name of the actor + sublayer_name: the name of the sublayer the actor is in + actor_layer: the actor layer the actor is in + returns: a string representing where in the BRFLD the actor is""" return ":".join(["Root", "pScenario", actor_layer.value, "dctSublayers", sublayer_name, "dctActors", actor_name]) def actor_groups_for_actor_layer(self, actor_layer: ActorLayer = ActorLayer.ENTITIES) -> Iterator[str]: + """ + Iterably gets every actor group in an actor layer + + param actor_layer: the actor layer to get the actor groups of + returns: each actor group in the actor layer""" yield from self.raw.Root.pScenario[actor_layer.value].dctActorGroups.keys() def get_actor_group(self, group_name: str, actor_layer: ActorLayer = ActorLayer.ENTITIES) -> List[str]: + """ + Gets an actor group + + param group_name: the name of the actor group + param actor_layer: the actor layer the actor group is in + returns: a list of links to actors""" return self.raw.Root.pScenario[actor_layer.value].dctActorGroups[group_name] def is_actor_in_group( @@ -62,6 +101,14 @@ def is_actor_in_group( sublayer_name: str = "default", actor_layer: ActorLayer = ActorLayer.ENTITIES, ) -> bool: + """ + Checks if an actor is in an actor group + + param group_name: the name of the actor group + param actor_name: the name of the actor + param sublayer_name: the name of the sublayer the actor is in + param actor_layer: the actor layer the actor is in + returns: true if the actor is in the actor group, false otherwise""" return self.link_for_actor(actor_name, sublayer_name, actor_layer) in self.get_actor_group(group_name, actor_layer) def add_actor_to_group( @@ -71,6 +118,13 @@ def add_actor_to_group( sublayer_name: str = "default", actor_layer: ActorLayer = ActorLayer.ENTITIES, ) -> None: + """ + Adds an actor to an actor group + + param group_name: the name of the actor group + param actor_name: the name of the actor + param sublayer_name: the name of the sublayer the actor is in + param actor_layer: the actor layer the actor is in""" group = self.get_actor_group(group_name, actor_layer) actor_link = self.link_for_actor(actor_name, sublayer_name, actor_layer) if actor_link not in group: @@ -83,6 +137,13 @@ def remove_actor_from_group( sublayer_name: str = "default", actor_layer: ActorLayer = ActorLayer.ENTITIES, ) -> None: + """ + Removes an actor from an actor group + + param group_name: the name of the actor group + param actor_name: the name of the actor + param sublayer_name: the name of the sublayer the actor is in + param actor_layer: the actor layer the actor is in""" group = self.get_actor_group(group_name, actor_layer) actor_link = self.link_for_actor(actor_name, sublayer_name, actor_layer) if actor_link in group: @@ -96,11 +157,11 @@ def add_actor_to_actor_groups( actor_layer: ActorLayer = ActorLayer.ENTITIES, ) -> None: """ - adds an actor to all actor groups starting with collision_camera_name + Adds an actor to all actor groups starting with collision_camera_name - param collision_camera_name: name of the collision camera group - param actor_name: name of the actor to add to the group - param sublayer_name: name of the sublayer the actor belongs to + param collision_camera_name: the name of the collision camera group + param actor_name: the name of the actor to add to the group + param sublayer_name: the name of the sublayer the actor belongs to param actor_layer: the actor layer the sublayer belongs to """ collision_camera_groups = [ From 8bbc2ebf88cb210a747640f93b19a3a47b5dd811 Mon Sep 17 00:00:00 2001 From: Mayberry Date: Sat, 12 Oct 2024 17:10:51 -0400 Subject: [PATCH 17/31] Fix ruff errors --- src/mercury_engine_data_structures/formats/brfld.py | 8 ++++++-- tests/formats/test_brfld.py | 4 +--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index d81e3565..0fde64c1 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -75,7 +75,9 @@ def link_for_actor( sublayer_name: the name of the sublayer the actor is in actor_layer: the actor layer the actor is in returns: a string representing where in the BRFLD the actor is""" - return ":".join(["Root", "pScenario", actor_layer.value, "dctSublayers", sublayer_name, "dctActors", actor_name]) + return ":".join( + ["Root", "pScenario", actor_layer.value, "dctSublayers", sublayer_name, "dctActors", actor_name] + ) def actor_groups_for_actor_layer(self, actor_layer: ActorLayer = ActorLayer.ENTITIES) -> Iterator[str]: """ @@ -109,7 +111,9 @@ def is_actor_in_group( param sublayer_name: the name of the sublayer the actor is in param actor_layer: the actor layer the actor is in returns: true if the actor is in the actor group, false otherwise""" - return self.link_for_actor(actor_name, sublayer_name, actor_layer) in self.get_actor_group(group_name, actor_layer) + return self.link_for_actor(actor_name, sublayer_name, actor_layer) in self.get_actor_group( + group_name, actor_layer + ) def add_actor_to_group( self, diff --git a/tests/formats/test_brfld.py b/tests/formats/test_brfld.py index 5910f35f..c5db8dbb 100644 --- a/tests/formats/test_brfld.py +++ b/tests/formats/test_brfld.py @@ -36,9 +36,7 @@ def test_add_actor_to_actor_groups(dread_tree_100): scenario.add_actor_to_actor_groups("eg_collision_camera_000", "breakabletilegroup_000", "breakables") assert scenario.is_actor_in_group("eg_collision_camera_000_Default", "breakabletilegroup_000", "breakables") - scenario.add_actor_to_actor_groups( - "ssg_collision_camera_000", "Pos_C_LavaWindow_06", actor_layer=ActorLayer.SOUNDS - ) + scenario.add_actor_to_actor_groups("ssg_collision_camera_000", "Pos_C_LavaWindow_06", actor_layer=ActorLayer.SOUNDS) assert scenario.is_actor_in_group( "ssg_collision_camera_000_Default", "Pos_C_LavaWindow_06", actor_layer=ActorLayer.SOUNDS ) From 4e063d169e78c4d0177679e12b644d3a8d9f5a5d Mon Sep 17 00:00:00 2001 From: Mayberry Date: Sat, 12 Oct 2024 17:35:22 -0400 Subject: [PATCH 18/31] Add additional tests --- tests/formats/test_brfld.py | 44 +++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tests/formats/test_brfld.py b/tests/formats/test_brfld.py index c5db8dbb..e0847742 100644 --- a/tests/formats/test_brfld.py +++ b/tests/formats/test_brfld.py @@ -30,6 +30,50 @@ def test_dread_brfld_210(dread_tree_210, brfld_path): parse_build_compare_editor(Brfld, dread_tree_210, brfld_path) +def test_get_actors_methods(dread_tree_100): + scenario = dread_tree_100.get_file("maps/levels/c10_samus/s010_cave/s010_cave.brfld", Brfld) + + actors_for_sublayer_names = [] + + for sublayer in scenario.sublayers_for_actor_layer(): + actors_for_sublayer_names += scenario.actors_for_sublayer(sublayer).keys() + + all_actors_in_actor_layer_names = [ + actor_name for sublayer_name, actor_name, actor in scenario.all_actors_in_actor_layer() + ] + + assert actors_for_sublayer_names == all_actors_in_actor_layer_names + + +def test_follow_link(dread_tree_100): + scenario = dread_tree_100.get_file("maps/levels/c10_samus/s010_cave/s010_cave.brfld", Brfld) + + actor_link = scenario.link_for_actor("cubemap_fr.2_cave_ini", "cubes", ActorLayer.LIGHTS) + + assert scenario.follow_link(actor_link).sName == "cubemap_fr.2_cave_ini" + + +def test_remove_actor_from_actor_group(dread_tree_100): + scenario = dread_tree_100.get_file("maps/levels/c10_samus/s010_cave/s010_cave.brfld", Brfld) + + scenario.remove_actor_from_group("eg_collision_camera_000_Default", "breakabletilegroup_052", "breakables") + assert not scenario.is_actor_in_group("eg_collision_camera_000_Default", "breakabletilegroup_052", "breakables") + + scenario.remove_actor_from_group( + "ssg_collision_camera_000_Default", "Pos_C_Trees_R", actor_layer=ActorLayer.SOUNDS + ) + assert not scenario.is_actor_in_group( + "ssg_collision_camera_000_Default", "Pos_C_Trees_R", actor_layer=ActorLayer.SOUNDS + ) + + scenario.remove_actor_from_group( + "lg_collision_camera_000", "cave_000_light", "spot_000_1", ActorLayer.LIGHTS + ) + assert not scenario.is_actor_in_group( + "lg_collision_camera_000", "cave_000_light", "spot_000_1", ActorLayer.LIGHTS + ) + + def test_add_actor_to_actor_groups(dread_tree_100): scenario = dread_tree_100.get_file("maps/levels/c10_samus/s010_cave/s010_cave.brfld", Brfld) From b7d9c1d3b87a1273ba4392bbdcb2f82755e1c539 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 12 Oct 2024 21:35:30 +0000 Subject: [PATCH 19/31] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/formats/test_brfld.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/tests/formats/test_brfld.py b/tests/formats/test_brfld.py index e0847742..47b43d76 100644 --- a/tests/formats/test_brfld.py +++ b/tests/formats/test_brfld.py @@ -59,19 +59,13 @@ def test_remove_actor_from_actor_group(dread_tree_100): scenario.remove_actor_from_group("eg_collision_camera_000_Default", "breakabletilegroup_052", "breakables") assert not scenario.is_actor_in_group("eg_collision_camera_000_Default", "breakabletilegroup_052", "breakables") - scenario.remove_actor_from_group( - "ssg_collision_camera_000_Default", "Pos_C_Trees_R", actor_layer=ActorLayer.SOUNDS - ) + scenario.remove_actor_from_group("ssg_collision_camera_000_Default", "Pos_C_Trees_R", actor_layer=ActorLayer.SOUNDS) assert not scenario.is_actor_in_group( "ssg_collision_camera_000_Default", "Pos_C_Trees_R", actor_layer=ActorLayer.SOUNDS ) - scenario.remove_actor_from_group( - "lg_collision_camera_000", "cave_000_light", "spot_000_1", ActorLayer.LIGHTS - ) - assert not scenario.is_actor_in_group( - "lg_collision_camera_000", "cave_000_light", "spot_000_1", ActorLayer.LIGHTS - ) + scenario.remove_actor_from_group("lg_collision_camera_000", "cave_000_light", "spot_000_1", ActorLayer.LIGHTS) + assert not scenario.is_actor_in_group("lg_collision_camera_000", "cave_000_light", "spot_000_1", ActorLayer.LIGHTS) def test_add_actor_to_actor_groups(dread_tree_100): From 1ef9c697b83c5b12636333988e1e41562122baf4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 19:35:25 +0000 Subject: [PATCH 20/31] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/mercury_engine_data_structures/formats/brfld.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index 1850f03c..44574468 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -1,7 +1,7 @@ import functools import logging -from enum import Enum from collections.abc import Iterator +from enum import Enum import construct From 1bced76d0545763e0a0c7f78d3d5b5b41458b673 Mon Sep 17 00:00:00 2001 From: Mayberry Date: Mon, 14 Oct 2024 15:37:47 -0400 Subject: [PATCH 21/31] Re-add missing import --- src/mercury_engine_data_structures/formats/brfld.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index 44574468..f032d615 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -2,6 +2,7 @@ import logging from collections.abc import Iterator from enum import Enum +from typing import Any import construct From 9bc3a5d3c6c08a16613103bf693c9f304980c4c4 Mon Sep 17 00:00:00 2001 From: Mayberry Date: Wed, 16 Oct 2024 16:30:13 -0400 Subject: [PATCH 22/31] Make ActorLayer enum extend str --- .../formats/brfld.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index f032d615..7021da87 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -13,7 +13,7 @@ logger = logging.getLogger(__name__) -class ActorLayer(Enum): +class ActorLayer(str, Enum): ENTITIES = "rEntitiesLayer" SOUNDS = "rSoundsLayer" LIGHTS = "rLightsLayer" @@ -32,7 +32,7 @@ def actors_for_sublayer(self, sublayer_name: str, actor_layer: ActorLayer = Acto param sublayer_name: the name of the sublayer to get the actors of param actor_layer: the actor_layer the sublayer is in returns: the actors in the sublayer""" - return self.raw.Root.pScenario[actor_layer.value].dctSublayers[sublayer_name].dctActors + return self.raw.Root.pScenario[actor_layer].dctSublayers[sublayer_name].dctActors def sublayers_for_actor_layer(self, actor_layer: ActorLayer = ActorLayer.ENTITIES) -> Iterator[str]: """ @@ -40,7 +40,7 @@ def sublayers_for_actor_layer(self, actor_layer: ActorLayer = ActorLayer.ENTITIE param actor_layer: the actor layer to get the sublayers of returns: the name of each sublayer""" - yield from self.raw.Root.pScenario[actor_layer.value].dctSublayers.keys() + yield from self.raw.Root.pScenario[actor_layer].dctSublayers.keys() def all_actors_in_actor_layer( self, actor_layer: ActorLayer = ActorLayer.ENTITIES @@ -50,7 +50,7 @@ def all_actors_in_actor_layer( param actor_layer: the actor layer to get the actors of returns: each actor in the actor layer""" - for sublayer_name, sublayer in self.raw.Root.pScenario[actor_layer.value].dctSublayers.items(): + for sublayer_name, sublayer in self.raw.Root.pScenario[actor_layer].dctSublayers.items(): for actor_name, actor in sublayer.dctActors.items(): yield sublayer_name, actor_name, actor @@ -77,7 +77,7 @@ def link_for_actor( actor_layer: the actor layer the actor is in returns: a string representing where in the BRFLD the actor is""" return ":".join( - ["Root", "pScenario", actor_layer.value, "dctSublayers", sublayer_name, "dctActors", actor_name] + ["Root", "pScenario", actor_layer, "dctSublayers", sublayer_name, "dctActors", actor_name] ) def actor_groups_for_actor_layer(self, actor_layer: ActorLayer = ActorLayer.ENTITIES) -> Iterator[str]: @@ -86,7 +86,7 @@ def actor_groups_for_actor_layer(self, actor_layer: ActorLayer = ActorLayer.ENTI param actor_layer: the actor layer to get the actor groups of returns: each actor group in the actor layer""" - yield from self.raw.Root.pScenario[actor_layer.value].dctActorGroups.keys() + yield from self.raw.Root.pScenario[actor_layer].dctActorGroups.keys() def get_actor_group(self, group_name: str, actor_layer: ActorLayer = ActorLayer.ENTITIES) -> list[str]: """ @@ -95,7 +95,7 @@ def get_actor_group(self, group_name: str, actor_layer: ActorLayer = ActorLayer. param group_name: the name of the actor group param actor_layer: the actor layer the actor group is in returns: a list of links to actors""" - return self.raw.Root.pScenario[actor_layer.value].dctActorGroups[group_name] + return self.raw.Root.pScenario[actor_layer].dctActorGroups[group_name] def is_actor_in_group( self, From 5fe16d485f78943dbe9a0475df917998221a4553 Mon Sep 17 00:00:00 2001 From: Mayberry Date: Wed, 16 Oct 2024 17:09:58 -0400 Subject: [PATCH 23/31] Parametrize add/remove actor from group tests --- tests/formats/test_brfld.py | 44 +++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/tests/formats/test_brfld.py b/tests/formats/test_brfld.py index 47b43d76..9ee3387e 100644 --- a/tests/formats/test_brfld.py +++ b/tests/formats/test_brfld.py @@ -53,35 +53,31 @@ def test_follow_link(dread_tree_100): assert scenario.follow_link(actor_link).sName == "cubemap_fr.2_cave_ini" -def test_remove_actor_from_actor_group(dread_tree_100): - scenario = dread_tree_100.get_file("maps/levels/c10_samus/s010_cave/s010_cave.brfld", Brfld) +to_remove_from_actor_groups = [ + ["eg_collision_camera_000_Default", "breakabletilegroup_052", "breakables", ActorLayer.ENTITIES], + ["ssg_collision_camera_000_Default", "Pos_C_Trees_R", "default", ActorLayer.SOUNDS], + ["lg_collision_camera_000", "spot_000_1", "cave_000_light", ActorLayer.LIGHTS], +] - scenario.remove_actor_from_group("eg_collision_camera_000_Default", "breakabletilegroup_052", "breakables") - assert not scenario.is_actor_in_group("eg_collision_camera_000_Default", "breakabletilegroup_052", "breakables") - scenario.remove_actor_from_group("ssg_collision_camera_000_Default", "Pos_C_Trees_R", actor_layer=ActorLayer.SOUNDS) - assert not scenario.is_actor_in_group( - "ssg_collision_camera_000_Default", "Pos_C_Trees_R", actor_layer=ActorLayer.SOUNDS - ) +@pytest.mark.parametrize(["actor_group", "actor_name", "sublayer_name", "actor_layer"], to_remove_from_actor_groups) +def test_remove_actor_from_actor_group(dread_tree_100, actor_group, actor_name, sublayer_name, actor_layer): + scenario = dread_tree_100.get_file("maps/levels/c10_samus/s010_cave/s010_cave.brfld", Brfld) - scenario.remove_actor_from_group("lg_collision_camera_000", "cave_000_light", "spot_000_1", ActorLayer.LIGHTS) - assert not scenario.is_actor_in_group("lg_collision_camera_000", "cave_000_light", "spot_000_1", ActorLayer.LIGHTS) + scenario.remove_actor_from_group(actor_group, actor_name, sublayer_name, actor_layer) + assert not scenario.is_actor_in_group(actor_group, actor_name, sublayer_name, actor_layer) -def test_add_actor_to_actor_groups(dread_tree_100): - scenario = dread_tree_100.get_file("maps/levels/c10_samus/s010_cave/s010_cave.brfld", Brfld) +to_add_to_actor_groups = [ + ["eg_collision_camera_000_Default", "breakabletilegroup_000", "breakables", ActorLayer.ENTITIES], + ["ssg_collision_camera_000_Default", "Pos_C_LavaWindow_06", "default", ActorLayer.SOUNDS], + ["lg_collision_camera_000", "cubemap_006_1_bake", "emmy_006_light", ActorLayer.LIGHTS], +] - scenario.add_actor_to_actor_groups("eg_collision_camera_000", "breakabletilegroup_000", "breakables") - assert scenario.is_actor_in_group("eg_collision_camera_000_Default", "breakabletilegroup_000", "breakables") - scenario.add_actor_to_actor_groups("ssg_collision_camera_000", "Pos_C_LavaWindow_06", actor_layer=ActorLayer.SOUNDS) - assert scenario.is_actor_in_group( - "ssg_collision_camera_000_Default", "Pos_C_LavaWindow_06", actor_layer=ActorLayer.SOUNDS - ) +@pytest.mark.parametrize(["actor_group", "actor_name", "sublayer_name", "actor_layer"], to_add_to_actor_groups) +def test_add_actor_to_actor_group(dread_tree_100, actor_group, actor_name, sublayer_name, actor_layer): + scenario = dread_tree_100.get_file("maps/levels/c10_samus/s010_cave/s010_cave.brfld", Brfld) - scenario.add_actor_to_actor_groups( - "lg_collision_camera_000", "cubemap_006_1_bake", "emmy_006_light", ActorLayer.LIGHTS - ) - assert scenario.is_actor_in_group( - "lg_collision_camera_000", "cubemap_006_1_bake", "emmy_006_light", ActorLayer.LIGHTS - ) + scenario.add_actor_to_actor_groups(actor_group, actor_name, sublayer_name, actor_layer) + assert scenario.is_actor_in_group(actor_group, actor_name, sublayer_name, actor_layer) From d3907cc3783b5aee6e173de0d8136b39c082b68a Mon Sep 17 00:00:00 2001 From: Mayberry Date: Wed, 16 Oct 2024 17:11:08 -0400 Subject: [PATCH 24/31] Raise and test exception when adding/removing actor from group --- .../formats/brfld.py | 4 ++++ tests/formats/test_brfld.py | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index 7021da87..f07e55b2 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -134,6 +134,8 @@ def add_actor_to_group( actor_link = self.link_for_actor(actor_name, sublayer_name, actor_layer) if actor_link not in group: group.append(actor_link) + else: + raise ValueError(f"Actor {actor_link} is already in actor group {group_name}") def remove_actor_from_group( self, @@ -153,6 +155,8 @@ def remove_actor_from_group( actor_link = self.link_for_actor(actor_name, sublayer_name, actor_layer) if actor_link in group: group.remove(actor_link) + else: + raise ValueError(f"Actor {actor_link} is not in actor group {group_name}") def add_actor_to_actor_groups( self, diff --git a/tests/formats/test_brfld.py b/tests/formats/test_brfld.py index 9ee3387e..50ede507 100644 --- a/tests/formats/test_brfld.py +++ b/tests/formats/test_brfld.py @@ -68,6 +68,13 @@ def test_remove_actor_from_actor_group(dread_tree_100, actor_group, actor_name, assert not scenario.is_actor_in_group(actor_group, actor_name, sublayer_name, actor_layer) +def test_remove_actor_from_actor_group_raises_exception(dread_tree_100): + scenario = dread_tree_100.get_file("maps/levels/c10_samus/s010_cave/s010_cave.brfld", Brfld) + + with pytest.raises(ValueError, match=r"Actor .+ is not in actor group .+"): + scenario.remove_actor_from_group("eg_collision_camera_000_Default", "StartPoint0") + + to_add_to_actor_groups = [ ["eg_collision_camera_000_Default", "breakabletilegroup_000", "breakables", ActorLayer.ENTITIES], ["ssg_collision_camera_000_Default", "Pos_C_LavaWindow_06", "default", ActorLayer.SOUNDS], @@ -81,3 +88,10 @@ def test_add_actor_to_actor_group(dread_tree_100, actor_group, actor_name, subla scenario.add_actor_to_actor_groups(actor_group, actor_name, sublayer_name, actor_layer) assert scenario.is_actor_in_group(actor_group, actor_name, sublayer_name, actor_layer) + + +def test_add_actor_to_actor_group_raises_exception(dread_tree_100): + scenario = dread_tree_100.get_file("maps/levels/c10_samus/s010_cave/s010_cave.brfld", Brfld) + + with pytest.raises(ValueError, match=r"Actor .+ is already in actor group .+"): + scenario.add_actor_to_group("eg_collision_camera_000_Default", "PRP_DB_CV_006") From 8b20e2fad301adc77246b6e00ef2b947d986fc4a Mon Sep 17 00:00:00 2001 From: Mayberry Date: Wed, 16 Oct 2024 17:16:54 -0400 Subject: [PATCH 25/31] Use ActorLink alias when a method returns an actor link str --- src/mercury_engine_data_structures/formats/brfld.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index f07e55b2..137d8f44 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -12,6 +12,8 @@ logger = logging.getLogger(__name__) +ActorLink = str + class ActorLayer(str, Enum): ENTITIES = "rEntitiesLayer" @@ -68,7 +70,7 @@ def follow_link(self, link: str) -> Any | None: def link_for_actor( self, actor_name: str, sublayer_name: str = "default", actor_layer: ActorLayer = ActorLayer.ENTITIES - ) -> str: + ) -> ActorLink: """ Builds a link for an actor @@ -88,7 +90,7 @@ def actor_groups_for_actor_layer(self, actor_layer: ActorLayer = ActorLayer.ENTI returns: each actor group in the actor layer""" yield from self.raw.Root.pScenario[actor_layer].dctActorGroups.keys() - def get_actor_group(self, group_name: str, actor_layer: ActorLayer = ActorLayer.ENTITIES) -> list[str]: + def get_actor_group(self, group_name: str, actor_layer: ActorLayer = ActorLayer.ENTITIES) -> list[ActorLink]: """ Gets an actor group From ffef029f34c15dbb866cf351dace453b6f5a8d88 Mon Sep 17 00:00:00 2001 From: Mayberry Date: Wed, 16 Oct 2024 17:27:51 -0400 Subject: [PATCH 26/31] Fix ruff errors --- src/mercury_engine_data_structures/formats/brfld.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index 137d8f44..2d0f07ef 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -78,9 +78,7 @@ def link_for_actor( sublayer_name: the name of the sublayer the actor is in actor_layer: the actor layer the actor is in returns: a string representing where in the BRFLD the actor is""" - return ":".join( - ["Root", "pScenario", actor_layer, "dctSublayers", sublayer_name, "dctActors", actor_name] - ) + return ":".join(["Root", "pScenario", actor_layer, "dctSublayers", sublayer_name, "dctActors", actor_name]) def actor_groups_for_actor_layer(self, actor_layer: ActorLayer = ActorLayer.ENTITIES) -> Iterator[str]: """ From 1272f964dd92efb6c1fb3196675c927fc079ca7a Mon Sep 17 00:00:00 2001 From: Mayberry Date: Wed, 16 Oct 2024 17:31:26 -0400 Subject: [PATCH 27/31] Update all_actors_in_actor_layer returns docstring --- src/mercury_engine_data_structures/formats/brfld.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index 2d0f07ef..871c816c 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -51,7 +51,7 @@ def all_actors_in_actor_layer( Iterably gets every actor in an actor layer param actor_layer: the actor layer to get the actors of - returns: each actor in the actor layer""" + returns: for each actor in the actor layer: sublayer name, actor name, actor""" for sublayer_name, sublayer in self.raw.Root.pScenario[actor_layer].dctSublayers.items(): for actor_name, actor in sublayer.dctActors.items(): yield sublayer_name, actor_name, actor From 717c24bf981b7d21740032ccf57fc18640bba70a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 16 Oct 2024 21:37:13 +0000 Subject: [PATCH 28/31] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/mercury_engine_data_structures/formats/brfld.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index a3df06f3..44115358 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -4,7 +4,6 @@ import logging from collections.abc import Iterator from enum import Enum -from typing import Any from typing import TYPE_CHECKING, Any import construct From 6ee9314c8c1aa8a1ba9b350e0d574dfe39ac4736 Mon Sep 17 00:00:00 2001 From: Mayberry Date: Wed, 16 Oct 2024 19:04:12 -0400 Subject: [PATCH 29/31] Add name and level properties to BRFLD --- .../formats/brfld.py | 8 ++++++++ tests/formats/test_brfld.py | 16 ++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index 44115358..b26d70ba 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -35,6 +35,14 @@ class Brfld(BaseResource): def construct_class(cls, target_game: Game) -> construct.Construct: return standard_format.game_model("CScenario", "49.0.2") + @property + def level(self) -> str: + return self.raw.Root.pScenario.sLevelID + + @property + def name(self) -> str: + return self.raw.Root.pScenario.sScenarioID + def actors_for_sublayer(self, sublayer_name: str, actor_layer: ActorLayer = ActorLayer.ENTITIES) -> dict: """ Gets the actors in a sublayer diff --git a/tests/formats/test_brfld.py b/tests/formats/test_brfld.py index 665e9d51..1f7aea88 100644 --- a/tests/formats/test_brfld.py +++ b/tests/formats/test_brfld.py @@ -32,6 +32,22 @@ def test_dread_brfld_210(dread_tree_210, brfld_path): parse_build_compare_editor(Brfld, dread_tree_210, brfld_path) +@pytest.mark.parametrize("brfld_path", dread_data.all_files_ending_with(".brfld", bossrush_assets)) +def test_get_name(dread_tree_100, brfld_path): + scenario = dread_tree_100.get_file(brfld_path, Brfld) + scenario_name = brfld_path.split("/")[3] + + assert scenario.name == scenario_name + + +@pytest.mark.parametrize("brfld_path", dread_data.all_files_ending_with(".brfld", bossrush_assets)) +def test_get_level(dread_tree_100, brfld_path): + scenario = dread_tree_100.get_file(brfld_path, Brfld) + level_name = brfld_path.split("/")[2] + + assert scenario.level == level_name + + def test_get_actors_methods(dread_tree_100): scenario = dread_tree_100.get_file("maps/levels/c10_samus/s010_cave/s010_cave.brfld", Brfld) From 4e901009a58e134523b4644984bca538f8f2c11d Mon Sep 17 00:00:00 2001 From: Mayberry Date: Thu, 17 Oct 2024 13:58:36 -0400 Subject: [PATCH 30/31] Use optional regex for exceptions in BRFLD test --- tests/formats/test_brfld.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/formats/test_brfld.py b/tests/formats/test_brfld.py index 1f7aea88..37279dff 100644 --- a/tests/formats/test_brfld.py +++ b/tests/formats/test_brfld.py @@ -89,7 +89,7 @@ def test_remove_actor_from_actor_group(dread_tree_100, actor_group, actor_name, def test_remove_actor_from_actor_group_raises_exception(dread_tree_100): scenario = dread_tree_100.get_file("maps/levels/c10_samus/s010_cave/s010_cave.brfld", Brfld) - with pytest.raises(ValueError, match=r"Actor .+ is not in actor group .+"): + with pytest.raises(ValueError, match=r"Actor .+? is not in actor group .+?"): scenario.remove_actor_from_group("eg_collision_camera_000_Default", "StartPoint0") @@ -111,5 +111,5 @@ def test_add_actor_to_actor_group(dread_tree_100, actor_group, actor_name, subla def test_add_actor_to_actor_group_raises_exception(dread_tree_100): scenario = dread_tree_100.get_file("maps/levels/c10_samus/s010_cave/s010_cave.brfld", Brfld) - with pytest.raises(ValueError, match=r"Actor .+ is already in actor group .+"): + with pytest.raises(ValueError, match=r"Actor .+? is already in actor group .+?"): scenario.add_actor_to_group("eg_collision_camera_000_Default", "PRP_DB_CV_006") From 7f3b6f7a87a92180e6e9d984cae0c654c46ae7f4 Mon Sep 17 00:00:00 2001 From: Mayberry Date: Thu, 17 Oct 2024 14:02:47 -0400 Subject: [PATCH 31/31] Rename ActorLink to BrfldLink and hint it in follow_link argument --- src/mercury_engine_data_structures/formats/brfld.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mercury_engine_data_structures/formats/brfld.py b/src/mercury_engine_data_structures/formats/brfld.py index b26d70ba..fd9f6e54 100644 --- a/src/mercury_engine_data_structures/formats/brfld.py +++ b/src/mercury_engine_data_structures/formats/brfld.py @@ -20,7 +20,7 @@ logger = logging.getLogger(__name__) -ActorLink = str +BrfldLink = str class ActorLayer(str, Enum): @@ -72,7 +72,7 @@ def all_actors_in_actor_layer( for actor_name, actor in sublayer.dctActors.items(): yield sublayer_name, actor_name, actor - def follow_link(self, link: str) -> Any | None: + def follow_link(self, link: BrfldLink) -> Any | None: """ Gets the object a link is referencing @@ -86,7 +86,7 @@ def follow_link(self, link: str) -> Any | None: def link_for_actor( self, actor_name: str, sublayer_name: str = "default", actor_layer: ActorLayer = ActorLayer.ENTITIES - ) -> ActorLink: + ) -> BrfldLink: """ Builds a link for an actor @@ -104,7 +104,7 @@ def actor_groups_for_actor_layer(self, actor_layer: ActorLayer = ActorLayer.ENTI returns: each actor group in the actor layer""" yield from self.raw.Root.pScenario[actor_layer].dctActorGroups.keys() - def get_actor_group(self, group_name: str, actor_layer: ActorLayer = ActorLayer.ENTITIES) -> list[ActorLink]: + def get_actor_group(self, group_name: str, actor_layer: ActorLayer = ActorLayer.ENTITIES) -> list[BrfldLink]: """ Gets an actor group