diff options
-rw-r--r-- | doc/classes/Node.xml | 1 | ||||
-rw-r--r-- | doc/classes/SceneTree.xml | 5 | ||||
-rw-r--r-- | scene/main/scene_tree.cpp | 35 |
3 files changed, 32 insertions, 9 deletions
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index c9c94eff36..8da2f0b86b 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -851,6 +851,7 @@ </member> <member name="multiplayer" type="MultiplayerAPI" setter="" getter="get_multiplayer"> The [MultiplayerAPI] instance associated with this node. See [method SceneTree.get_multiplayer]. + [b]Note:[/b] Renaming the node, or moving it in the tree, will not move the [MultiplayerAPI] to the new path, you will have to update this manually. </member> <member name="name" type="StringName" setter="set_name" getter="get_name"> The name of the node. This name is unique among the siblings (other child nodes from the same parent). When set to an existing name, the node will be automatically renamed. diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml index 5086b68f24..da23eadfd1 100644 --- a/doc/classes/SceneTree.xml +++ b/doc/classes/SceneTree.xml @@ -110,8 +110,7 @@ <return type="MultiplayerAPI" /> <param index="0" name="for_path" type="NodePath" default="NodePath("")" /> <description> - Return the [MultiplayerAPI] configured for the given path, or the default one if [param for_path] is empty. - [b]Note:[/b] Only one [MultiplayerAPI] may be configured for any subpath. If one is configured for [code]"/root/Foo"[/code] then calling this for [code]"/root/Foo/Bar"[/code] will return the one configured for [code]"/root/Foo"[/code], regardless if one is configured for that path. + Searches for the [MultiplayerAPI] configured for the given path, if one does not exist it searches the parent paths until one is found. If the path is empty, or none is found, the default one is returned. See [method set_multiplayer]. </description> </method> <method name="get_node_count" qualifiers="const"> @@ -211,7 +210,7 @@ <param index="1" name="root_path" type="NodePath" default="NodePath("")" /> <description> Sets a custom [MultiplayerAPI] with the given [param root_path] (controlling also the relative subpaths), or override the default one if [param root_path] is empty. - [b]Note:[/b] Only one [MultiplayerAPI] may be configured for any subpath. If one is configured for [code]"/root/Foo"[/code] setting one for [code]"/root/Foo/Bar"[/code] will be ignored. See [method get_multiplayer]. + [b]Note:[/b] No [MultiplayerAPI] must be configured for the subpath containing [param root_path], nested custom multiplayers are not allowed. I.e. if one is configured for [code]"/root/Foo"[/code] setting one for [code]"/root/Foo/Bar"[/code] will cause an error. </description> </method> <method name="unload_current_scene"> diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index ba11084d3b..d357e35c1d 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -1483,15 +1483,18 @@ TypedArray<Tween> SceneTree::get_processed_tweens() { Ref<MultiplayerAPI> SceneTree::get_multiplayer(const NodePath &p_for_path) const { ERR_FAIL_COND_V_MSG(!Thread::is_main_thread(), Ref<MultiplayerAPI>(), "Multiplayer can only be manipulated from the main thread."); - Ref<MultiplayerAPI> out = multiplayer; + if (p_for_path.is_empty()) { + return multiplayer; + } + + const Vector<StringName> tnames = p_for_path.get_names(); + const StringName *nptr = tnames.ptr(); for (const KeyValue<NodePath, Ref<MultiplayerAPI>> &E : custom_multiplayers) { const Vector<StringName> snames = E.key.get_names(); - const Vector<StringName> tnames = p_for_path.get_names(); if (tnames.size() < snames.size()) { continue; } const StringName *sptr = snames.ptr(); - const StringName *nptr = tnames.ptr(); bool valid = true; for (int i = 0; i < snames.size(); i++) { if (sptr[i] != nptr[i]) { @@ -1500,11 +1503,11 @@ Ref<MultiplayerAPI> SceneTree::get_multiplayer(const NodePath &p_for_path) const } } if (valid) { - out = E.value; - break; + return E.value; } } - return out; + + return multiplayer; } void SceneTree::set_multiplayer(Ref<MultiplayerAPI> p_multiplayer, const NodePath &p_root_path) { @@ -1519,10 +1522,30 @@ void SceneTree::set_multiplayer(Ref<MultiplayerAPI> p_multiplayer, const NodePat } else { if (custom_multiplayers.has(p_root_path)) { custom_multiplayers[p_root_path]->object_configuration_remove(nullptr, p_root_path); + } else if (p_multiplayer.is_valid()) { + const Vector<StringName> tnames = p_root_path.get_names(); + const StringName *nptr = tnames.ptr(); + for (const KeyValue<NodePath, Ref<MultiplayerAPI>> &E : custom_multiplayers) { + const Vector<StringName> snames = E.key.get_names(); + if (tnames.size() < snames.size()) { + continue; + } + const StringName *sptr = snames.ptr(); + bool valid = true; + for (int i = 0; i < snames.size(); i++) { + if (sptr[i] != nptr[i]) { + valid = false; + break; + } + } + ERR_FAIL_COND_MSG(valid, "Multiplayer is already configured for a parent of this path: '" + p_root_path + "' in '" + E.key + "'."); + } } if (p_multiplayer.is_valid()) { custom_multiplayers[p_root_path] = p_multiplayer; p_multiplayer->object_configuration_add(nullptr, p_root_path); + } else { + custom_multiplayers.erase(p_root_path); } } } |