From 9a5c54bea858fc8e9e84878f3ac0a0f7bc190b46 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Tue, 31 Dec 2024 00:42:00 +0100 Subject: [PATCH] fix: Take into consideration when child is added to parent that is removed in the same tick (#3428) Currently we end up in a bad state if a child is added to a parent that is removed in the same tick, this PR fixes that by adding the child after the parent has been unmounted. Closes: #3416 --- packages/flame/lib/src/components/core/component.dart | 8 +++++++- packages/flame/test/components/component_test.dart | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/flame/lib/src/components/core/component.dart b/packages/flame/lib/src/components/core/component.dart index 5f410ac7d46..4fb0a4623b8 100644 --- a/packages/flame/lib/src/components/core/component.dart +++ b/packages/flame/lib/src/components/core/component.dart @@ -614,7 +614,7 @@ class Component { _clearRemovingBit(); } game.enqueueMove(child, this); - } else if (isMounted && !isRemoving && !child.isMounted) { + } else if (isMounted && !child.isMounted) { child._parent = this; game.enqueueAdd(child, this); } else { @@ -829,6 +829,12 @@ class Component { } else { if (parent.isMounted && !isLoading) { _startLoading(); + } else if (parent.isRemoved) { + // This case happens when the child is added to a parent that is being + // removed in the same tick. + _parent = parent; + parent.children.add(this); + return LifecycleEventStatus.done; } return LifecycleEventStatus.block; } diff --git a/packages/flame/test/components/component_test.dart b/packages/flame/test/components/component_test.dart index 3cc4f69e4c9..aede46b867b 100644 --- a/packages/flame/test/components/component_test.dart +++ b/packages/flame/test/components/component_test.dart @@ -646,7 +646,13 @@ void main() { // Timeout is added because processLifecycleEvents of ComponentTreeRoot // gets blocked in such cases. - expect(game.ready().timeout(const Duration(seconds: 2)), completes); + + // Expect the ready future to complete + await expectLater( + game.ready().timeout(const Duration(seconds: 2)), + completes, + ); + expect(game.hasLifecycleEvents, isFalse); // Adding the parent again should eventually mount the child as well. await game.add(parent);