summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRémi Verschelde <rverschelde@gmail.com>2022-12-12 13:51:48 +0100
committerRémi Verschelde <rverschelde@gmail.com>2022-12-12 13:51:48 +0100
commitec8f52df8f2b5fb55ca5c9d37ab77927ea53477f (patch)
treee342a562b7a20852a4ea55dbf5e3b88979b3cc42
parent92dfa7901b61e43e275e50e4c5f2f91f6d250356 (diff)
parent194c1c44e0a20faa4463e3a41bb12cf93a71fc03 (diff)
Merge pull request #69629 from smix8/agent_wild_callback_pointer_4.x
Fix Navigation agent callback wild pointer crash
-rw-r--r--doc/classes/NavigationServer2D.xml6
-rw-r--r--doc/classes/NavigationServer3D.xml6
-rw-r--r--modules/navigation/godot_navigation_server.cpp6
-rw-r--r--modules/navigation/godot_navigation_server.h2
-rw-r--r--scene/2d/navigation_agent_2d.cpp6
-rw-r--r--scene/3d/navigation_agent_3d.cpp6
-rw-r--r--servers/navigation_server_2d.cpp8
-rw-r--r--servers/navigation_server_2d.h2
-rw-r--r--servers/navigation_server_3d.cpp2
-rw-r--r--servers/navigation_server_3d.h2
10 files changed, 21 insertions, 25 deletions
diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml
index ab59add092..230e58a12a 100644
--- a/doc/classes/NavigationServer2D.xml
+++ b/doc/classes/NavigationServer2D.xml
@@ -40,12 +40,12 @@
<method name="agent_set_callback" qualifiers="const">
<return type="void" />
<param index="0" name="agent" type="RID" />
- <param index="1" name="receiver" type="Object" />
+ <param index="1" name="object_id" type="int" />
<param index="2" name="method" type="StringName" />
<param index="3" name="userdata" type="Variant" default="null" />
<description>
- Callback called at the end of the RVO process. If a callback is created manually and the agent is placed on a navigation map it will calculate avoidance for the agent and dispatch the calculated [code]safe_velocity[/code] to the [param receiver] object with a signal to the chosen [param method] name.
- [b]Note:[/b] Created callbacks are always processed independently of the SceneTree state as long as the agent is on a navigation map and not freed. To disable the dispatch of a callback from an agent use [method agent_set_callback] again with a [code]null[/code] object as the [param receiver].
+ Sets the callback [param object_id] and [param method] that gets called after each avoidance processing step for the [param agent]. The calculated [code]safe_velocity[/code] will be dispatched with a signal to the object just before the physics calculations.
+ [b]Note:[/b] Created callbacks are always processed independently of the SceneTree state as long as the agent is on a navigation map and not freed. To disable the dispatch of a callback from an agent use [method agent_set_callback] again with a [code]0[/code] ObjectID as the [param object_id].
</description>
</method>
<method name="agent_set_map" qualifiers="const">
diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml
index 27a07eda90..c7da3b7b5b 100644
--- a/doc/classes/NavigationServer3D.xml
+++ b/doc/classes/NavigationServer3D.xml
@@ -40,12 +40,12 @@
<method name="agent_set_callback" qualifiers="const">
<return type="void" />
<param index="0" name="agent" type="RID" />
- <param index="1" name="receiver" type="Object" />
+ <param index="1" name="object_id" type="int" />
<param index="2" name="method" type="StringName" />
<param index="3" name="userdata" type="Variant" default="null" />
<description>
- Callback called at the end of the RVO process. If a callback is created manually and the agent is placed on a navigation map it will calculate avoidance for the agent and dispatch the calculated [code]safe_velocity[/code] to the [param receiver] object with a signal to the chosen [param method] name.
- [b]Note:[/b] Created callbacks are always processed independently of the SceneTree state as long as the agent is on a navigation map and not freed. To disable the dispatch of a callback from an agent use [method agent_set_callback] again with a [code]null[/code] object as the [param receiver].
+ Sets the callback [param object_id] and [param method] that gets called after each avoidance processing step for the [param agent]. The calculated [code]safe_velocity[/code] will be dispatched with a signal to the object just before the physics calculations.
+ [b]Note:[/b] Created callbacks are always processed independently of the SceneTree state as long as the agent is on a navigation map and not freed. To disable the dispatch of a callback from an agent use [method agent_set_callback] again with a [code]0[/code] ObjectID as the [param object_id].
</description>
</method>
<method name="agent_set_map" qualifiers="const">
diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp
index 0e40e5a4af..e5949c935b 100644
--- a/modules/navigation/godot_navigation_server.cpp
+++ b/modules/navigation/godot_navigation_server.cpp
@@ -704,14 +704,14 @@ bool GodotNavigationServer::agent_is_map_changed(RID p_agent) const {
return agent->is_map_changed();
}
-COMMAND_4(agent_set_callback, RID, p_agent, Object *, p_receiver, StringName, p_method, Variant, p_udata) {
+COMMAND_4(agent_set_callback, RID, p_agent, ObjectID, p_object_id, StringName, p_method, Variant, p_udata) {
RvoAgent *agent = agent_owner.get_or_null(p_agent);
ERR_FAIL_COND(agent == nullptr);
- agent->set_callback(p_receiver == nullptr ? ObjectID() : p_receiver->get_instance_id(), p_method, p_udata);
+ agent->set_callback(p_object_id, p_method, p_udata);
if (agent->get_map()) {
- if (p_receiver == nullptr) {
+ if (p_object_id == ObjectID()) {
agent->get_map()->remove_agent_as_controlled(agent);
} else {
agent->get_map()->set_agent_as_controlled(agent);
diff --git a/modules/navigation/godot_navigation_server.h b/modules/navigation/godot_navigation_server.h
index 08ad545b37..18431e39b8 100644
--- a/modules/navigation/godot_navigation_server.h
+++ b/modules/navigation/godot_navigation_server.h
@@ -172,7 +172,7 @@ public:
COMMAND_2(agent_set_position, RID, p_agent, Vector3, p_position);
COMMAND_2(agent_set_ignore_y, RID, p_agent, bool, p_ignore);
virtual bool agent_is_map_changed(RID p_agent) const override;
- COMMAND_4_DEF(agent_set_callback, RID, p_agent, Object *, p_receiver, StringName, p_method, Variant, p_udata, Variant());
+ COMMAND_4_DEF(agent_set_callback, RID, p_agent, ObjectID, p_object_id, StringName, p_method, Variant, p_udata, Variant());
COMMAND_1(free, RID, p_object);
diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp
index 1a62c9bb6c..904b6564bd 100644
--- a/scene/2d/navigation_agent_2d.cpp
+++ b/scene/2d/navigation_agent_2d.cpp
@@ -197,9 +197,9 @@ NavigationAgent2D::~NavigationAgent2D() {
void NavigationAgent2D::set_avoidance_enabled(bool p_enabled) {
avoidance_enabled = p_enabled;
if (avoidance_enabled) {
- NavigationServer2D::get_singleton()->agent_set_callback(agent, this, "_avoidance_done");
+ NavigationServer2D::get_singleton()->agent_set_callback(agent, get_instance_id(), "_avoidance_done");
} else {
- NavigationServer2D::get_singleton()->agent_set_callback(agent, nullptr, "_avoidance_done");
+ NavigationServer2D::get_singleton()->agent_set_callback(agent, ObjectID(), "_avoidance_done");
}
}
@@ -209,7 +209,7 @@ bool NavigationAgent2D::get_avoidance_enabled() const {
void NavigationAgent2D::set_agent_parent(Node *p_agent_parent) {
// remove agent from any avoidance map before changing parent or there will be leftovers on the RVO map
- NavigationServer2D::get_singleton()->agent_set_callback(agent, nullptr, "_avoidance_done");
+ NavigationServer2D::get_singleton()->agent_set_callback(agent, ObjectID(), "_avoidance_done");
if (Object::cast_to<Node2D>(p_agent_parent) != nullptr) {
// place agent on navigation map first or else the RVO agent callback creation fails silently later
agent_parent = Object::cast_to<Node2D>(p_agent_parent);
diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp
index 36350d251e..e907b9f66f 100644
--- a/scene/3d/navigation_agent_3d.cpp
+++ b/scene/3d/navigation_agent_3d.cpp
@@ -204,9 +204,9 @@ NavigationAgent3D::~NavigationAgent3D() {
void NavigationAgent3D::set_avoidance_enabled(bool p_enabled) {
avoidance_enabled = p_enabled;
if (avoidance_enabled) {
- NavigationServer3D::get_singleton()->agent_set_callback(agent, this, "_avoidance_done");
+ NavigationServer3D::get_singleton()->agent_set_callback(agent, get_instance_id(), "_avoidance_done");
} else {
- NavigationServer3D::get_singleton()->agent_set_callback(agent, nullptr, "_avoidance_done");
+ NavigationServer3D::get_singleton()->agent_set_callback(agent, ObjectID(), "_avoidance_done");
}
}
@@ -216,7 +216,7 @@ bool NavigationAgent3D::get_avoidance_enabled() const {
void NavigationAgent3D::set_agent_parent(Node *p_agent_parent) {
// remove agent from any avoidance map before changing parent or there will be leftovers on the RVO map
- NavigationServer3D::get_singleton()->agent_set_callback(agent, nullptr, "_avoidance_done");
+ NavigationServer3D::get_singleton()->agent_set_callback(agent, ObjectID(), "_avoidance_done");
if (Object::cast_to<Node3D>(p_agent_parent) != nullptr) {
// place agent on navigation map first or else the RVO agent callback creation fails silently later
agent_parent = Object::cast_to<Node3D>(p_agent_parent);
diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp
index bfe95ddef1..4ed998a77e 100644
--- a/servers/navigation_server_2d.cpp
+++ b/servers/navigation_server_2d.cpp
@@ -140,10 +140,6 @@ static Transform3D trf2_to_trf3(const Transform2D &d) {
return Transform3D(b, o);
}
-static Object *obj_to_obj(Object *d) {
- return d;
-}
-
static StringName sn_to_sn(const StringName &d) {
return d;
}
@@ -297,7 +293,7 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("agent_set_target_velocity", "agent", "target_velocity"), &NavigationServer2D::agent_set_target_velocity);
ClassDB::bind_method(D_METHOD("agent_set_position", "agent", "position"), &NavigationServer2D::agent_set_position);
ClassDB::bind_method(D_METHOD("agent_is_map_changed", "agent"), &NavigationServer2D::agent_is_map_changed);
- ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "receiver", "method", "userdata"), &NavigationServer2D::agent_set_callback, DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "object_id", "method", "userdata"), &NavigationServer2D::agent_set_callback, DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("free_rid", "rid"), &NavigationServer2D::free);
@@ -420,7 +416,7 @@ void FORWARD_2_C(agent_set_ignore_y, RID, p_agent, bool, p_ignore, rid_to_rid, b
bool FORWARD_1_C(agent_is_map_changed, RID, p_agent, rid_to_rid);
-void FORWARD_4_C(agent_set_callback, RID, p_agent, Object *, p_receiver, StringName, p_method, Variant, p_udata, rid_to_rid, obj_to_obj, sn_to_sn, var_to_var);
+void FORWARD_4_C(agent_set_callback, RID, p_agent, ObjectID, p_object_id, StringName, p_method, Variant, p_udata, rid_to_rid, id_to_id, sn_to_sn, var_to_var);
void FORWARD_1_C(free, RID, p_object, rid_to_rid);
diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h
index 4c78bc40c7..cf6011a0f9 100644
--- a/servers/navigation_server_2d.h
+++ b/servers/navigation_server_2d.h
@@ -226,7 +226,7 @@ public:
virtual bool agent_is_map_changed(RID p_agent) const;
/// Callback called at the end of the RVO process
- virtual void agent_set_callback(RID p_agent, Object *p_receiver, StringName p_method, Variant p_udata = Variant()) const;
+ virtual void agent_set_callback(RID p_agent, ObjectID p_object_id, StringName p_method, Variant p_udata = Variant()) const;
virtual void query_path(const Ref<NavigationPathQueryParameters2D> &p_query_parameters, Ref<NavigationPathQueryResult2D> p_query_result) const;
diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp
index 31e8b9a864..940dd61f67 100644
--- a/servers/navigation_server_3d.cpp
+++ b/servers/navigation_server_3d.cpp
@@ -113,7 +113,7 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("agent_set_target_velocity", "agent", "target_velocity"), &NavigationServer3D::agent_set_target_velocity);
ClassDB::bind_method(D_METHOD("agent_set_position", "agent", "position"), &NavigationServer3D::agent_set_position);
ClassDB::bind_method(D_METHOD("agent_is_map_changed", "agent"), &NavigationServer3D::agent_is_map_changed);
- ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "receiver", "method", "userdata"), &NavigationServer3D::agent_set_callback, DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "object_id", "method", "userdata"), &NavigationServer3D::agent_set_callback, DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("free_rid", "rid"), &NavigationServer3D::free);
diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h
index 31ae149aff..bf4c22be8a 100644
--- a/servers/navigation_server_3d.h
+++ b/servers/navigation_server_3d.h
@@ -241,7 +241,7 @@ public:
virtual bool agent_is_map_changed(RID p_agent) const = 0;
/// Callback called at the end of the RVO process
- virtual void agent_set_callback(RID p_agent, Object *p_receiver, StringName p_method, Variant p_udata = Variant()) const = 0;
+ virtual void agent_set_callback(RID p_agent, ObjectID p_object_id, StringName p_method, Variant p_udata = Variant()) const = 0;
/// Destroy the `RID`
virtual void free(RID p_object) const = 0;