Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

- Replacing component relations from an inherited view now preserves values which depend on the destination.
- Removing a relation tag or component now preserves query membership when the other relation still exists.
- Queries collecting component rows now resolve inherited components instead of raising `KeyError` for prefab instances.
- Relation components can now be copied between distinct keys in the same entity, instead of the assignment being silently ignored.
Expand Down
3 changes: 2 additions & 1 deletion tcod/ecs/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -1071,9 +1071,10 @@ def __setitem__(self, __key: ComponentKey[T], __values: Mapping[Entity, T], /) -
and __values.key == __key
):
return
items = tuple(__values.items()) # The input may inherit values from the mapping being replaced.
mapping: EntityComponentRelationMapping[T] = self[__key]
mapping.clear()
for target, component in __values.items():
for target, component in items:
mapping[target] = component

def __delitem__(self, key: ComponentKey[object]) -> None:
Expand Down
27 changes: 27 additions & 0 deletions tests/test_relations.py
Original file line number Diff line number Diff line change
Expand Up @@ -359,3 +359,30 @@ def test_overlapping_relation_queries(key: ComponentKey[int], remove_first: str)
else:
actor.relation_tags_many[key].remove(faction)
assert not any(queries)


@pytest.mark.parametrize("key", [int, ("affinity", int)])
@pytest.mark.parametrize("depth", [1, 3])
@pytest.mark.parametrize("override", [False, True])
def test_component_relation_assignment_from_inherited_view(
key: ComponentKey[int], depth: int, *, override: bool
) -> None:
world = tcod.ecs.Registry()
prefab = world["prefab"]
first, second = world["first"], world["second"]
prefab.relation_components[key] = {first: 10, second: 20}
instance = prefab
for _ in range(depth):
instance = instance.instantiate()
if override:
instance.relation_components[key][first] = 30
expected = {first: 30 if override else 10, second: 20}
query = world.Q.all_of(relations=[(key, second)])
assert prefab in query

prefab.relation_components[key] = instance.relation_components[key]

assert dict(prefab.relation_components[key]) == expected
assert dict(instance.relation_components[key]) == expected
assert prefab in query
assert instance in query
Loading