mirror of
https://github.com/godotengine/godot.git
synced 2024-12-03 09:52:18 +08:00
Merge pull request #77829 from AThousandShips/mp_fix
Disallow nested custom multiplayers in `SceneTree`
This commit is contained in:
commit
79805262f1
@ -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.
|
||||
|
@ -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">
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user