summaryrefslogtreecommitdiffstats
path: root/scene
diff options
context:
space:
mode:
authorRémi Verschelde <rverschelde@gmail.com>2023-09-26 08:17:02 +0200
committerRémi Verschelde <rverschelde@gmail.com>2023-09-26 08:17:02 +0200
commit79805262f18bb1b00b84061994825db5afe94144 (patch)
treeaa67ea7c88399c84187ace71a537cabbae15a842 /scene
parent1aa2d8ba1981f3d266b16681a2e614127b5c6c83 (diff)
parenta5fe392b7812f62309e228959e8b7ea8c93013d8 (diff)
downloadredot-engine-79805262f18bb1b00b84061994825db5afe94144.tar.gz
Merge pull request #77829 from AThousandShips/mp_fix
Disallow nested custom multiplayers in `SceneTree`
Diffstat (limited to 'scene')
-rw-r--r--scene/main/scene_tree.cpp35
1 files changed, 29 insertions, 6 deletions
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);
}
}
}