diff options
Diffstat (limited to 'scene/multiplayer')
-rw-r--r-- | scene/multiplayer/multiplayer_spawner.cpp | 126 | ||||
-rw-r--r-- | scene/multiplayer/multiplayer_spawner.h | 31 | ||||
-rw-r--r-- | scene/multiplayer/multiplayer_synchronizer.cpp | 2 | ||||
-rw-r--r-- | scene/multiplayer/multiplayer_synchronizer.h | 2 | ||||
-rw-r--r-- | scene/multiplayer/scene_cache_interface.cpp | 10 | ||||
-rw-r--r-- | scene/multiplayer/scene_replication_interface.cpp | 4 | ||||
-rw-r--r-- | scene/multiplayer/scene_replication_state.cpp | 4 | ||||
-rw-r--r-- | scene/multiplayer/scene_replication_state.h | 16 |
8 files changed, 149 insertions, 46 deletions
diff --git a/scene/multiplayer/multiplayer_spawner.cpp b/scene/multiplayer/multiplayer_spawner.cpp index a9b9ffa989..ddd01d0a43 100644 --- a/scene/multiplayer/multiplayer_spawner.cpp +++ b/scene/multiplayer/multiplayer_spawner.cpp @@ -35,12 +35,106 @@ #include "scene/main/window.h" #include "scene/scene_string_names.h" +#ifdef TOOLS_ENABLED +/* This is editor only */ +bool MultiplayerSpawner::_set(const StringName &p_name, const Variant &p_value) { + if (p_name == "_spawnable_scene_count") { + spawnable_scenes.resize(p_value); + notify_property_list_changed(); + return true; + } else { + String ns = p_name; + if (ns.begins_with("scenes/")) { + uint32_t index = ns.get_slicec('/', 1).to_int(); + ERR_FAIL_UNSIGNED_INDEX_V(index, spawnable_scenes.size(), false); + spawnable_scenes[index].path = p_value; + return true; + } + } + return false; +} + +bool MultiplayerSpawner::_get(const StringName &p_name, Variant &r_ret) const { + if (p_name == "_spawnable_scene_count") { + r_ret = spawnable_scenes.size(); + return true; + } else { + String ns = p_name; + if (ns.begins_with("scenes/")) { + uint32_t index = ns.get_slicec('/', 1).to_int(); + ERR_FAIL_UNSIGNED_INDEX_V(index, spawnable_scenes.size(), false); + r_ret = spawnable_scenes[index].path; + return true; + } + } + return false; +} + +void MultiplayerSpawner::_get_property_list(List<PropertyInfo> *p_list) const { + p_list->push_back(PropertyInfo(Variant::INT, "_spawnable_scene_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ARRAY, "Scenes,scenes/")); + List<String> exts; + ResourceLoader::get_recognized_extensions_for_type("PackedScene", &exts); + String ext_hint; + for (const String &E : exts) { + if (!ext_hint.is_empty()) { + ext_hint += ","; + } + ext_hint += "*." + E; + } + for (uint32_t i = 0; i < spawnable_scenes.size(); i++) { + p_list->push_back(PropertyInfo(Variant::STRING, "scenes/" + itos(i), PROPERTY_HINT_FILE, ext_hint, PROPERTY_USAGE_EDITOR)); + } +} +#endif +void MultiplayerSpawner::add_spawnable_scene(const String &p_path) { + SpawnableScene sc; + sc.path = p_path; + if (Engine::get_singleton()->is_editor_hint()) { + ERR_FAIL_COND(!FileAccess::exists(p_path)); + } else { + sc.cache = ResourceLoader::load(p_path); + ERR_FAIL_COND_MSG(sc.cache.is_null(), "Invalid spawnable scene: " + p_path); + } + spawnable_scenes.push_back(sc); +} +int MultiplayerSpawner::get_spawnable_scene_count() const { + return spawnable_scenes.size(); +} +String MultiplayerSpawner::get_spawnable_scene(int p_idx) const { + return spawnable_scenes[p_idx].path; +} +void MultiplayerSpawner::clear_spawnable_scenes() { + spawnable_scenes.clear(); +} + +Vector<String> MultiplayerSpawner::_get_spawnable_scenes() const { + Vector<String> ss; + ss.resize(spawnable_scenes.size()); + for (int i = 0; i < ss.size(); i++) { + ss.write[i] = spawnable_scenes[i].path; + } + return ss; +} + +void MultiplayerSpawner::_set_spawnable_scenes(const Vector<String> &p_scenes) { + clear_spawnable_scenes(); + for (int i = 0; i < p_scenes.size(); i++) { + add_spawnable_scene(p_scenes[i]); + } +} + void MultiplayerSpawner::_bind_methods() { - ClassDB::bind_method(D_METHOD("spawn", "data"), &MultiplayerSpawner::spawn, DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("add_spawnable_scene", "path"), &MultiplayerSpawner::add_spawnable_scene); + ClassDB::bind_method(D_METHOD("get_spawnable_scene_count"), &MultiplayerSpawner::get_spawnable_scene_count); + ClassDB::bind_method(D_METHOD("get_spawnable_scene", "path"), &MultiplayerSpawner::get_spawnable_scene); + ClassDB::bind_method(D_METHOD("clear_spawnable_scenes"), &MultiplayerSpawner::clear_spawnable_scenes); + + ClassDB::bind_method(D_METHOD("_get_spawnable_scenes"), &MultiplayerSpawner::_get_spawnable_scenes); + ClassDB::bind_method(D_METHOD("_set_spawnable_scenes", "scenes"), &MultiplayerSpawner::_set_spawnable_scenes); - ClassDB::bind_method(D_METHOD("get_spawnable_scenes"), &MultiplayerSpawner::get_spawnable_scenes); - ClassDB::bind_method(D_METHOD("set_spawnable_scenes", "scenes"), &MultiplayerSpawner::set_spawnable_scenes); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "replication", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "PackedScene"), (PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE)), "set_spawnable_scenes", "get_spawnable_scenes"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "_spawnable_scenes", PROPERTY_HINT_NONE, "", (PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL)), "_set_spawnable_scenes", "_get_spawnable_scenes"); + + ClassDB::bind_method(D_METHOD("spawn", "data"), &MultiplayerSpawner::spawn, DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("get_spawn_path"), &MultiplayerSpawner::get_spawn_path); ClassDB::bind_method(D_METHOD("set_spawn_path", "path"), &MultiplayerSpawner::set_spawn_path); @@ -118,7 +212,7 @@ void MultiplayerSpawner::_node_added(Node *p_node) { if (!parent || p_node->get_parent() != parent) { return; } - int id = get_scene_id(p_node->get_scene_file_path()); + int id = find_spawnable_scene_index_from_path(p_node->get_scene_file_path()); if (id == INVALID_ID) { return; } @@ -136,14 +230,6 @@ bool MultiplayerSpawner::is_auto_spawning() const { return auto_spawn; } -TypedArray<PackedScene> MultiplayerSpawner::get_spawnable_scenes() { - return spawnable_scenes; -} - -void MultiplayerSpawner::set_spawnable_scenes(TypedArray<PackedScene> p_scenes) { - spawnable_scenes = p_scenes; -} - NodePath MultiplayerSpawner::get_spawn_path() const { return spawn_path; } @@ -175,18 +261,16 @@ void MultiplayerSpawner::_node_exit(ObjectID p_id) { } } -int MultiplayerSpawner::get_scene_id(const String &p_scene) const { - for (int i = 0; i < spawnable_scenes.size(); i++) { - Ref<PackedScene> ps = spawnable_scenes[i]; - ERR_CONTINUE(ps.is_null()); - if (ps->get_path() == p_scene) { +int MultiplayerSpawner::find_spawnable_scene_index_from_path(const String &p_scene) const { + for (uint32_t i = 0; i < spawnable_scenes.size(); i++) { + if (spawnable_scenes[i].path == p_scene) { return i; } } return INVALID_ID; } -int MultiplayerSpawner::get_spawn_id(const ObjectID &p_id) const { +int MultiplayerSpawner::find_spawnable_scene_index_from_object(const ObjectID &p_id) const { const SpawnInfo *info = tracked_nodes.getptr(p_id); return info ? info->id : INVALID_ID; } @@ -198,8 +282,8 @@ const Variant MultiplayerSpawner::get_spawn_argument(const ObjectID &p_id) const Node *MultiplayerSpawner::instantiate_scene(int p_id) { ERR_FAIL_COND_V_MSG(spawn_limit && spawn_limit <= tracked_nodes.size(), nullptr, "Spawn limit reached!"); - ERR_FAIL_INDEX_V(p_id, spawnable_scenes.size(), nullptr); - Ref<PackedScene> scene = spawnable_scenes[p_id]; + ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_id, spawnable_scenes.size(), nullptr); + Ref<PackedScene> scene = spawnable_scenes[p_id].cache; ERR_FAIL_COND_V(scene.is_null(), nullptr); return scene->instantiate(); } diff --git a/scene/multiplayer/multiplayer_spawner.h b/scene/multiplayer/multiplayer_spawner.h index ac35df7ff3..e8abe702a0 100644 --- a/scene/multiplayer/multiplayer_spawner.h +++ b/scene/multiplayer/multiplayer_spawner.h @@ -33,6 +33,7 @@ #include "scene/main/node.h" +#include "core/templates/local_vector.h" #include "core/variant/typed_array.h" #include "scene/resources/packed_scene.h" #include "scene/resources/scene_replication_config.h" @@ -46,8 +47,14 @@ public: }; private: - TypedArray<PackedScene> spawnable_scenes; - RBSet<ResourceUID::ID> spawnable_ids; + struct SpawnableScene { + String path; + Ref<PackedScene> cache; + }; + + LocalVector<SpawnableScene> spawnable_scenes; + + HashSet<ResourceUID::ID> spawnable_ids; NodePath spawn_path; struct SpawnInfo { @@ -71,14 +78,26 @@ private: void _node_exit(ObjectID p_id); void _node_ready(ObjectID p_id); + Vector<String> _get_spawnable_scenes() const; + void _set_spawnable_scenes(const Vector<String> &p_scenes); + protected: static void _bind_methods(); void _notification(int p_what); +#ifdef TOOLS_ENABLED + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + void _get_property_list(List<PropertyInfo> *p_list) const; +#endif public: Node *get_spawn_node() const { return spawn_node.is_valid() ? Object::cast_to<Node>(ObjectDB::get_instance(spawn_node)) : nullptr; } - TypedArray<PackedScene> get_spawnable_scenes(); - void set_spawnable_scenes(TypedArray<PackedScene> p_scenes); + + void add_spawnable_scene(const String &p_path); + int get_spawnable_scene_count() const; + String get_spawnable_scene(int p_idx) const; + void clear_spawnable_scenes(); + NodePath get_spawn_path() const; void set_spawn_path(const NodePath &p_path); uint32_t get_spawn_limit() const { return spawn_limit; } @@ -87,8 +106,8 @@ public: void set_auto_spawning(bool p_enabled); const Variant get_spawn_argument(const ObjectID &p_id) const; - int get_spawn_id(const ObjectID &p_id) const; - int get_scene_id(const String &p_path) const; + int find_spawnable_scene_index_from_object(const ObjectID &p_id) const; + int find_spawnable_scene_index_from_path(const String &p_path) const; Node *spawn(const Variant &p_data = Variant()); Node *instantiate_custom(const Variant &p_data); Node *instantiate_scene(int p_idx); diff --git a/scene/multiplayer/multiplayer_synchronizer.cpp b/scene/multiplayer/multiplayer_synchronizer.cpp index 33e845a7a3..34d5abf9f6 100644 --- a/scene/multiplayer/multiplayer_synchronizer.cpp +++ b/scene/multiplayer/multiplayer_synchronizer.cpp @@ -96,7 +96,7 @@ void MultiplayerSynchronizer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_replication_config", "config"), &MultiplayerSynchronizer::set_replication_config); ClassDB::bind_method(D_METHOD("get_replication_config"), &MultiplayerSynchronizer::get_replication_config); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "SceneReplicationConfig"), "set_replication_config", "get_replication_config"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "congiruation", PROPERTY_HINT_RESOURCE_TYPE, "SceneReplicationConfig"), "set_replication_config", "get_replication_config"); } void MultiplayerSynchronizer::_notification(int p_what) { diff --git a/scene/multiplayer/multiplayer_synchronizer.h b/scene/multiplayer/multiplayer_synchronizer.h index e856745379..f61ef459da 100644 --- a/scene/multiplayer/multiplayer_synchronizer.h +++ b/scene/multiplayer/multiplayer_synchronizer.h @@ -40,7 +40,7 @@ class MultiplayerSynchronizer : public Node { private: Ref<SceneReplicationConfig> replication_config; - NodePath root_path; + NodePath root_path = NodePath(".."); // Start with parent, like with AnimationPlayer. uint64_t interval_msec = 0; static Object *_get_prop_target(Object *p_obj, const NodePath &p_prop); diff --git a/scene/multiplayer/scene_cache_interface.cpp b/scene/multiplayer/scene_cache_interface.cpp index a7e84b6bca..7c271341db 100644 --- a/scene/multiplayer/scene_cache_interface.cpp +++ b/scene/multiplayer/scene_cache_interface.cpp @@ -214,17 +214,17 @@ bool SceneCacheInterface::send_object_cache(Object *p_obj, NodePath p_path, int } } else { // Long and painful. - for (const RBSet<int>::Element *E = multiplayer->get_connected_peers().front(); E; E = E->next()) { - if (p_peer_id < 0 && E->get() == -p_peer_id) { + for (const int &E : multiplayer->get_connected_peers()) { + if (p_peer_id < 0 && E == -p_peer_id) { continue; // Continue, excluded. } - if (p_peer_id > 0 && E->get() != p_peer_id) { + if (p_peer_id > 0 && E != p_peer_id) { continue; // Continue, not for this peer. } - HashMap<int, bool>::Iterator F = psc->confirmed_peers.find(E->get()); + HashMap<int, bool>::Iterator F = psc->confirmed_peers.find(E); if (!F) { - peers_to_add.push_back(E->get()); // Need to also be notified. + peers_to_add.push_back(E); // Need to also be notified. has_all_peers = false; } else if (!F->value) { has_all_peers = false; diff --git a/scene/multiplayer/scene_replication_interface.cpp b/scene/multiplayer/scene_replication_interface.cpp index 55266c53ad..e4715ceb88 100644 --- a/scene/multiplayer/scene_replication_interface.cpp +++ b/scene/multiplayer/scene_replication_interface.cpp @@ -167,7 +167,7 @@ Error SceneReplicationInterface::_send_spawn(Node *p_node, MultiplayerSpawner *p uint32_t nid = rep_state->ensure_net_id(oid); // Prepare custom arg and scene_id - uint8_t scene_id = p_spawner->get_spawn_id(oid); + uint8_t scene_id = p_spawner->find_spawnable_scene_index_from_object(oid); bool is_custom = scene_id == MultiplayerSpawner::INVALID_ID; Variant spawn_arg = p_spawner->get_spawn_argument(oid); int spawn_arg_size = 0; @@ -316,7 +316,7 @@ Error SceneReplicationInterface::on_despawn_receive(int p_from, const uint8_t *p } void SceneReplicationInterface::_send_sync(int p_peer, uint64_t p_msec) { - const RBSet<ObjectID> &known = rep_state->get_known_nodes(p_peer); + const HashSet<ObjectID> &known = rep_state->get_known_nodes(p_peer); if (known.is_empty()) { return; } diff --git a/scene/multiplayer/scene_replication_state.cpp b/scene/multiplayer/scene_replication_state.cpp index e5cc57ff31..937b30cb36 100644 --- a/scene/multiplayer/scene_replication_state.cpp +++ b/scene/multiplayer/scene_replication_state.cpp @@ -93,8 +93,8 @@ bool SceneReplicationState::update_sync_time(const ObjectID &p_id, uint64_t p_ms return false; } -const RBSet<ObjectID> SceneReplicationState::get_known_nodes(int p_peer) { - ERR_FAIL_COND_V(!peers_info.has(p_peer), RBSet<ObjectID>()); +const HashSet<ObjectID> SceneReplicationState::get_known_nodes(int p_peer) { + ERR_FAIL_COND_V(!peers_info.has(p_peer), HashSet<ObjectID>()); return peers_info[p_peer].known_nodes; } diff --git a/scene/multiplayer/scene_replication_state.h b/scene/multiplayer/scene_replication_state.h index 33f72363ac..60a6c5d70c 100644 --- a/scene/multiplayer/scene_replication_state.h +++ b/scene/multiplayer/scene_replication_state.h @@ -62,27 +62,27 @@ private: }; struct PeerInfo { - RBSet<ObjectID> known_nodes; + HashSet<ObjectID> known_nodes; HashMap<uint32_t, ObjectID> recv_nodes; uint16_t last_sent_sync = 0; uint16_t last_recv_sync = 0; }; - RBSet<int> known_peers; + HashSet<int> known_peers; uint32_t last_net_id = 0; HashMap<ObjectID, TrackedNode> tracked_nodes; HashMap<int, PeerInfo> peers_info; - RBSet<ObjectID> spawned_nodes; - RBSet<ObjectID> path_only_nodes; + HashSet<ObjectID> spawned_nodes; + HashSet<ObjectID> path_only_nodes; TrackedNode &_track(const ObjectID &p_id); void _untrack(const ObjectID &p_id); bool is_tracked(const ObjectID &p_id) const { return tracked_nodes.has(p_id); } public: - const RBSet<int> get_peers() const { return known_peers; } - const RBSet<ObjectID> &get_spawned_nodes() const { return spawned_nodes; } - const RBSet<ObjectID> &get_path_only_nodes() const { return path_only_nodes; } + const HashSet<int> get_peers() const { return known_peers; } + const HashSet<ObjectID> &get_spawned_nodes() const { return spawned_nodes; } + const HashSet<ObjectID> &get_path_only_nodes() const { return path_only_nodes; } MultiplayerSynchronizer *get_synchronizer(const ObjectID &p_id) { return tracked_nodes.has(p_id) ? tracked_nodes[p_id].get_synchronizer() : nullptr; } MultiplayerSpawner *get_spawner(const ObjectID &p_id) { return tracked_nodes.has(p_id) ? tracked_nodes[p_id].get_spawner() : nullptr; } @@ -90,7 +90,7 @@ public: bool update_last_node_sync(const ObjectID &p_id, uint16_t p_time); bool update_sync_time(const ObjectID &p_id, uint64_t p_msec); - const RBSet<ObjectID> get_known_nodes(int p_peer); + const HashSet<ObjectID> get_known_nodes(int p_peer); uint32_t get_net_id(const ObjectID &p_id) const; void set_net_id(const ObjectID &p_id, uint32_t p_net_id); uint32_t ensure_net_id(const ObjectID &p_id); |