Skip to content

Commit 78426ee

Browse files
Prevent mapping areas with invalid IDs for Area2D/3D
This occurs when areas are created directly from the servers, and no instance is linked.
1 parent 8ccae16 commit 78426ee

4 files changed

Lines changed: 64 additions & 2 deletions

File tree

doc/classes/Area2D.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
<description>
77
[Area2D] is a region of 2D space defined by one or multiple [CollisionShape2D] or [CollisionPolygon2D] child nodes. It detects when other [CollisionObject2D]s enter or exit it, and it also keeps track of which collision objects haven't exited it yet (i.e. which one are overlapping it).
88
This node can also locally alter or override physics parameters (gravity, damping) and route audio to custom audio buses.
9+
[b]Note:[/b] Areas and bodies created with [PhysicsServer2D] might not interact as expected with [Area2D]s, and might not emit signals or track objects correctly.
910
</description>
1011
<tutorials>
1112
<link title="Using Area2D">$DOCS_URL/tutorials/physics/using_area_2d.html</link>

doc/classes/Area3D.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
<description>
77
[Area3D] is a region of 3D space defined by one or multiple [CollisionShape3D] or [CollisionPolygon3D] child nodes. It detects when other [CollisionObject3D]s enter or exit it, and it also keeps track of which collision objects haven't exited it yet (i.e. which one are overlapping it).
88
This node can also locally alter or override physics parameters (gravity, damping) and route audio to custom audio buses.
9+
[b]Note:[/b] Areas and bodies created with [PhysicsServer3D] might not interact as expected with [Area3D]s, and might not emit signals or track objects correctly.
910
[b]Warning:[/b] Using a [ConcavePolygonShape3D] inside a [CollisionShape3D] child of this node (created e.g. by using the [b]Create Trimesh Collision Sibling[/b] option in the [b]Mesh[/b] menu that appears when selecting a [MeshInstance3D] node) may give unexpected results, since this collision shape is hollow. If this is not desired, it has to be split into multiple [ConvexPolygonShape3D]s or primitive shapes like [BoxShape3D], or in some cases it may be replaceable by a [CollisionPolygon3D].
1011
</description>
1112
<tutorials>

scene/2d/area_2d.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,21 @@ void Area2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
166166
bool body_in = p_status == PhysicsServer2D::AREA_BODY_ADDED;
167167
ObjectID objid = p_instance;
168168

169+
// Exit early if instance is invalid.
170+
if (objid.is_null()) {
171+
// Emit the appropriate signals.
172+
lock_callback();
173+
locked = true;
174+
if (body_in) {
175+
emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, (Node *)nullptr, p_body_shape, p_area_shape);
176+
} else {
177+
emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, (Node *)nullptr, p_body_shape, p_area_shape);
178+
}
179+
locked = false;
180+
unlock_callback();
181+
return;
182+
}
183+
169184
Object *obj = ObjectDB::get_instance(objid);
170185
Node *node = Object::cast_to<Node>(obj);
171186

@@ -262,6 +277,21 @@ void Area2D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i
262277
bool area_in = p_status == PhysicsServer2D::AREA_BODY_ADDED;
263278
ObjectID objid = p_instance;
264279

280+
// Exit early if instance is invalid.
281+
if (objid.is_null()) {
282+
// Emit the appropriate signals.
283+
lock_callback();
284+
locked = true;
285+
if (area_in) {
286+
emit_signal(SceneStringNames::get_singleton()->area_shape_entered, p_area, (Node *)nullptr, p_area_shape, p_self_shape);
287+
} else {
288+
emit_signal(SceneStringNames::get_singleton()->area_shape_exited, p_area, (Node *)nullptr, p_area_shape, p_self_shape);
289+
}
290+
locked = false;
291+
unlock_callback();
292+
return;
293+
}
294+
265295
Object *obj = ObjectDB::get_instance(objid);
266296
Node *node = Object::cast_to<Node>(obj);
267297

scene/3d/area_3d.cpp

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,21 @@ void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
223223
bool body_in = p_status == PhysicsServer3D::AREA_BODY_ADDED;
224224
ObjectID objid = p_instance;
225225

226+
// Exit early if instance is invalid.
227+
if (objid.is_null()) {
228+
lock_callback();
229+
locked = true;
230+
// Emit the appropriate signals.
231+
if (body_in) {
232+
emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, (Node *)nullptr, p_body_shape, p_area_shape);
233+
} else {
234+
emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, (Node *)nullptr, p_body_shape, p_area_shape);
235+
}
236+
locked = false;
237+
unlock_callback();
238+
return;
239+
}
240+
226241
Object *obj = ObjectDB::get_instance(objid);
227242
Node *node = Object::cast_to<Node>(obj);
228243

@@ -254,7 +269,7 @@ void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
254269
E->value.shapes.insert(ShapePair(p_body_shape, p_area_shape));
255270
}
256271

257-
if (E->value.in_tree) {
272+
if (!node || E->value.in_tree) {
258273
emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, node, p_body_shape, p_area_shape);
259274
}
260275

@@ -276,7 +291,7 @@ void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
276291
}
277292
}
278293
}
279-
if (node && in_tree) {
294+
if (!node || in_tree) {
280295
emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, obj, p_body_shape, p_area_shape);
281296
}
282297
}
@@ -414,6 +429,21 @@ void Area3D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i
414429
bool area_in = p_status == PhysicsServer3D::AREA_BODY_ADDED;
415430
ObjectID objid = p_instance;
416431

432+
// Exit if instance is invalid.
433+
if (objid.is_null()) {
434+
lock_callback();
435+
locked = true;
436+
// Emit the appropriate signals.
437+
if (area_in) {
438+
emit_signal(SceneStringNames::get_singleton()->area_shape_entered, p_area, (Node *)nullptr, p_area_shape, p_self_shape);
439+
} else {
440+
emit_signal(SceneStringNames::get_singleton()->area_shape_exited, p_area, (Node *)nullptr, p_area_shape, p_self_shape);
441+
}
442+
locked = false;
443+
unlock_callback();
444+
return;
445+
}
446+
417447
Object *obj = ObjectDB::get_instance(objid);
418448
Node *node = Object::cast_to<Node>(obj);
419449

0 commit comments

Comments
 (0)