diff options
author | Fabio Alessandrelli <fabio.alessandrelli@gmail.com> | 2023-08-27 11:35:56 +0200 |
---|---|---|
committer | Fabio Alessandrelli <fabio.alessandrelli@gmail.com> | 2023-08-30 15:00:39 +0200 |
commit | 711e96edc46fb357ca721913dcfd0dcac97a3fb0 (patch) | |
tree | 400e52cfa094954eb764e4df932824f6f1f9f75f | |
parent | bc88dca176cef6b8943ded58c68a60f7c127baea (diff) | |
download | redot-engine-711e96edc46fb357ca721913dcfd0dcac97a3fb0.tar.gz |
[MP] Make replication mode an enum + optimizations
REPLICATION_MODE_ALWAYS (sync) and REPLICATION_MODE_ON_CHANGE (watch)
are now mutually exclusive.
Prevent invalid NodePath from being added to the config.
Optimize the replication config loading by composing the lists on
demand.
-rw-r--r-- | modules/multiplayer/doc_classes/SceneReplicationConfig.xml | 38 | ||||
-rw-r--r-- | modules/multiplayer/scene_replication_config.cpp | 168 | ||||
-rw-r--r-- | modules/multiplayer/scene_replication_config.h | 24 |
3 files changed, 149 insertions, 81 deletions
diff --git a/modules/multiplayer/doc_classes/SceneReplicationConfig.xml b/modules/multiplayer/doc_classes/SceneReplicationConfig.xml index b976eea30b..1a51e4b6e9 100644 --- a/modules/multiplayer/doc_classes/SceneReplicationConfig.xml +++ b/modules/multiplayer/doc_classes/SceneReplicationConfig.xml @@ -37,6 +37,13 @@ Finds the index of the given [param path]. </description> </method> + <method name="property_get_replication_mode"> + <return type="int" enum="SceneReplicationConfig.ReplicationMode" /> + <param index="0" name="path" type="NodePath" /> + <description> + Returns the replication mode for the property identified by the given [param path]. See [enum ReplicationMode]. + </description> + </method> <method name="property_get_spawn"> <return type="bool" /> <param index="0" name="path" type="NodePath" /> @@ -44,18 +51,28 @@ Returns whether the property identified by the given [param path] is configured to be synchronized on spawn. </description> </method> - <method name="property_get_sync"> + <method name="property_get_sync" is_deprecated="true"> <return type="bool" /> <param index="0" name="path" type="NodePath" /> <description> Returns whether the property identified by the given [param path] is configured to be synchronized on process. + [i]Deprecated.[/i] Use [method property_get_replication_mode] instead. </description> </method> - <method name="property_get_watch"> + <method name="property_get_watch" is_deprecated="true"> <return type="bool" /> <param index="0" name="path" type="NodePath" /> <description> Returns whether the property identified by the given [param path] is configured to be reliably synchronized when changes are detected on process. + [i]Deprecated.[/i] Use [method property_get_replication_mode] instead. + </description> + </method> + <method name="property_set_replication_mode"> + <return type="void" /> + <param index="0" name="path" type="NodePath" /> + <param index="1" name="mode" type="int" enum="SceneReplicationConfig.ReplicationMode" /> + <description> + Sets the synchronization mode for the property identified by the given [param path]. See [enum ReplicationMode]. </description> </method> <method name="property_set_spawn"> @@ -66,20 +83,22 @@ Sets whether the property identified by the given [param path] is configured to be synchronized on spawn. </description> </method> - <method name="property_set_sync"> + <method name="property_set_sync" is_deprecated="true"> <return type="void" /> <param index="0" name="path" type="NodePath" /> <param index="1" name="enabled" type="bool" /> <description> Sets whether the property identified by the given [param path] is configured to be synchronized on process. + [i]Deprecated.[/i] Use [method property_set_replication_mode] with [constant REPLICATION_MODE_ALWAYS] instead. </description> </method> - <method name="property_set_watch"> + <method name="property_set_watch" is_deprecated="true"> <return type="void" /> <param index="0" name="path" type="NodePath" /> <param index="1" name="enabled" type="bool" /> <description> Sets whether the property identified by the given [param path] is configured to be reliably synchronized when changes are detected on process. + [i]Deprecated.[/i] Use [method property_set_replication_mode] with [constant REPLICATION_MODE_ON_CHANGE] instead. </description> </method> <method name="remove_property"> @@ -90,4 +109,15 @@ </description> </method> </methods> + <constants> + <constant name="REPLICATION_MODE_NEVER" value="0" enum="ReplicationMode"> + Do not keep the given property synchronized. + </constant> + <constant name="REPLICATION_MODE_ALWAYS" value="1" enum="ReplicationMode"> + Replicate the given property on process by constantly sending updates using unreliable transfer mode. + </constant> + <constant name="REPLICATION_MODE_ON_CHANGE" value="2" enum="ReplicationMode"> + Replicate the given property on process by sending updates using reliable transfer mode when its value changes. + </constant> + </constants> </class> diff --git a/modules/multiplayer/scene_replication_config.cpp b/modules/multiplayer/scene_replication_config.cpp index db615f8c20..836fa1014d 100644 --- a/modules/multiplayer/scene_replication_config.cpp +++ b/modules/multiplayer/scene_replication_config.cpp @@ -47,38 +47,26 @@ bool SceneReplicationConfig::_set(const StringName &p_name, const Variant &p_val add_property(path); return true; } - ERR_FAIL_COND_V(p_value.get_type() != Variant::BOOL, false); ERR_FAIL_INDEX_V(idx, properties.size(), false); ReplicationProperty &prop = properties[idx]; - if (what == "sync") { - if ((bool)p_value == prop.sync) { - return true; - } - prop.sync = p_value; - if (prop.sync) { - sync_props.push_back(prop.name); - } else { - sync_props.erase(prop.name); - } + if (what == "replication_mode") { + ERR_FAIL_COND_V(p_value.get_type() != Variant::INT, false); + ReplicationMode mode = (ReplicationMode)p_value.operator int(); + ERR_FAIL_COND_V(mode < REPLICATION_MODE_NEVER || mode > REPLICATION_MODE_ON_CHANGE, false); + property_set_replication_mode(prop.name, mode); return true; - } else if (what == "spawn") { - if ((bool)p_value == prop.spawn) { - return true; - } - prop.spawn = p_value; - if (prop.spawn) { - spawn_props.push_back(prop.name); - } else { - spawn_props.erase(prop.name); - } + } + ERR_FAIL_COND_V(p_value.get_type() != Variant::BOOL, false); + if (what == "spawn") { + property_set_spawn(prop.name, p_value); + return true; + } else if (what == "sync") { + // Deprecated. + property_set_sync(prop.name, p_value); return true; } else if (what == "watch") { - prop.watch = p_value; - if (prop.watch) { - watch_props.push_back(prop.name); - } else { - watch_props.erase(prop.name); - } + // Deprecated. + property_set_watch(prop.name, p_value); return true; } } @@ -96,14 +84,11 @@ bool SceneReplicationConfig::_get(const StringName &p_name, Variant &r_ret) cons if (what == "path") { r_ret = prop.name; return true; - } else if (what == "sync") { - r_ret = prop.sync; - return true; } else if (what == "spawn") { r_ret = prop.spawn; return true; - } else if (what == "watch") { - r_ret = prop.watch; + } else if (what == "replication_mode") { + r_ret = prop.mode; return true; } } @@ -114,8 +99,7 @@ void SceneReplicationConfig::_get_property_list(List<PropertyInfo> *p_list) cons for (int i = 0; i < properties.size(); i++) { p_list->push_back(PropertyInfo(Variant::STRING, "properties/" + itos(i) + "/path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(Variant::STRING, "properties/" + itos(i) + "/spawn", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); - p_list->push_back(PropertyInfo(Variant::STRING, "properties/" + itos(i) + "/sync", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); - p_list->push_back(PropertyInfo(Variant::STRING, "properties/" + itos(i) + "/watch", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::INT, "properties/" + itos(i) + "/replication_mode", PROPERTY_HINT_ENUM, "Never,Always,On Change", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); } } @@ -129,11 +113,11 @@ TypedArray<NodePath> SceneReplicationConfig::get_properties() const { void SceneReplicationConfig::add_property(const NodePath &p_path, int p_index) { ERR_FAIL_COND(properties.find(p_path)); + ERR_FAIL_COND(p_path == NodePath()); if (p_index < 0 || p_index == properties.size()) { properties.push_back(ReplicationProperty(p_path)); - sync_props.push_back(p_path); - spawn_props.push_back(p_path); + dirty = true; return; } @@ -146,23 +130,12 @@ void SceneReplicationConfig::add_property(const NodePath &p_path, int p_index) { c++; } properties.insert_before(I, ReplicationProperty(p_path)); - sync_props.clear(); - spawn_props.clear(); - for (const ReplicationProperty &prop : properties) { - if (prop.sync) { - sync_props.push_back(prop.name); - } - if (prop.spawn) { - spawn_props.push_back(prop.name); - } - } + dirty = true; } void SceneReplicationConfig::remove_property(const NodePath &p_path) { properties.erase(p_path); - sync_props.erase(p_path); - spawn_props.erase(p_path); - watch_props.clear(); + dirty = true; } bool SceneReplicationConfig::has_property(const NodePath &p_path) const { @@ -196,56 +169,99 @@ void SceneReplicationConfig::property_set_spawn(const NodePath &p_path, bool p_e return; } E->get().spawn = p_enabled; - spawn_props.clear(); - for (const ReplicationProperty &prop : properties) { - if (prop.spawn) { - spawn_props.push_back(prop.name); - } - } + dirty = true; } bool SceneReplicationConfig::property_get_sync(const NodePath &p_path) { List<ReplicationProperty>::Element *E = properties.find(p_path); ERR_FAIL_COND_V(!E, false); - return E->get().sync; + return E->get().mode == REPLICATION_MODE_ALWAYS; } void SceneReplicationConfig::property_set_sync(const NodePath &p_path, bool p_enabled) { - List<ReplicationProperty>::Element *E = properties.find(p_path); - ERR_FAIL_COND(!E); - if (E->get().sync == p_enabled) { - return; - } - E->get().sync = p_enabled; - sync_props.clear(); - for (const ReplicationProperty &prop : properties) { - if (prop.sync) { - sync_props.push_back(prop.name); - } + if (p_enabled) { + property_set_replication_mode(p_path, REPLICATION_MODE_ALWAYS); + } else if (property_get_replication_mode(p_path) == REPLICATION_MODE_ALWAYS) { + property_set_replication_mode(p_path, REPLICATION_MODE_NEVER); } } bool SceneReplicationConfig::property_get_watch(const NodePath &p_path) { List<ReplicationProperty>::Element *E = properties.find(p_path); ERR_FAIL_COND_V(!E, false); - return E->get().watch; + return E->get().mode == REPLICATION_MODE_ON_CHANGE; } void SceneReplicationConfig::property_set_watch(const NodePath &p_path, bool p_enabled) { + if (p_enabled) { + property_set_replication_mode(p_path, REPLICATION_MODE_ON_CHANGE); + } else if (property_get_replication_mode(p_path) == REPLICATION_MODE_ON_CHANGE) { + property_set_replication_mode(p_path, REPLICATION_MODE_NEVER); + } +} + +SceneReplicationConfig::ReplicationMode SceneReplicationConfig::property_get_replication_mode(const NodePath &p_path) { + List<ReplicationProperty>::Element *E = properties.find(p_path); + ERR_FAIL_COND_V(!E, REPLICATION_MODE_NEVER); + return E->get().mode; +} + +void SceneReplicationConfig::property_set_replication_mode(const NodePath &p_path, ReplicationMode p_mode) { List<ReplicationProperty>::Element *E = properties.find(p_path); ERR_FAIL_COND(!E); - if (E->get().watch == p_enabled) { + if (E->get().mode == p_mode) { return; } - E->get().watch = p_enabled; + E->get().mode = p_mode; + dirty = true; +} + +void SceneReplicationConfig::_update() { + if (!dirty) { + return; + } + dirty = false; + sync_props.clear(); + spawn_props.clear(); watch_props.clear(); for (const ReplicationProperty &prop : properties) { - if (prop.watch) { - watch_props.push_back(p_path); + if (prop.spawn) { + spawn_props.push_back(prop.name); + } + switch (prop.mode) { + case REPLICATION_MODE_ALWAYS: + sync_props.push_back(prop.name); + break; + case REPLICATION_MODE_ON_CHANGE: + watch_props.push_back(prop.name); + break; + default: + break; } } } +const List<NodePath> &SceneReplicationConfig::get_spawn_properties() { + if (dirty) { + _update(); + } + return spawn_props; +} + +const List<NodePath> &SceneReplicationConfig::get_sync_properties() { + if (dirty) { + _update(); + } + return sync_props; +} + +const List<NodePath> &SceneReplicationConfig::get_watch_properties() { + if (dirty) { + _update(); + } + return watch_props; +} + void SceneReplicationConfig::_bind_methods() { ClassDB::bind_method(D_METHOD("get_properties"), &SceneReplicationConfig::get_properties); ClassDB::bind_method(D_METHOD("add_property", "path", "index"), &SceneReplicationConfig::add_property, DEFVAL(-1)); @@ -254,6 +270,14 @@ void SceneReplicationConfig::_bind_methods() { ClassDB::bind_method(D_METHOD("property_get_index", "path"), &SceneReplicationConfig::property_get_index); ClassDB::bind_method(D_METHOD("property_get_spawn", "path"), &SceneReplicationConfig::property_get_spawn); ClassDB::bind_method(D_METHOD("property_set_spawn", "path", "enabled"), &SceneReplicationConfig::property_set_spawn); + ClassDB::bind_method(D_METHOD("property_get_replication_mode", "path"), &SceneReplicationConfig::property_get_replication_mode); + ClassDB::bind_method(D_METHOD("property_set_replication_mode", "path", "mode"), &SceneReplicationConfig::property_set_replication_mode); + + BIND_ENUM_CONSTANT(REPLICATION_MODE_NEVER); + BIND_ENUM_CONSTANT(REPLICATION_MODE_ALWAYS); + BIND_ENUM_CONSTANT(REPLICATION_MODE_ON_CHANGE); + + // Deprecated. ClassDB::bind_method(D_METHOD("property_get_sync", "path"), &SceneReplicationConfig::property_get_sync); ClassDB::bind_method(D_METHOD("property_set_sync", "path", "enabled"), &SceneReplicationConfig::property_set_sync); ClassDB::bind_method(D_METHOD("property_get_watch", "path"), &SceneReplicationConfig::property_get_watch); diff --git a/modules/multiplayer/scene_replication_config.h b/modules/multiplayer/scene_replication_config.h index 44f8259904..3f870ba2d8 100644 --- a/modules/multiplayer/scene_replication_config.h +++ b/modules/multiplayer/scene_replication_config.h @@ -39,12 +39,18 @@ class SceneReplicationConfig : public Resource { OBJ_SAVE_TYPE(SceneReplicationConfig); RES_BASE_EXTENSION("repl"); +public: + enum ReplicationMode { + REPLICATION_MODE_NEVER, + REPLICATION_MODE_ALWAYS, + REPLICATION_MODE_ON_CHANGE, + }; + private: struct ReplicationProperty { NodePath name; bool spawn = true; - bool sync = true; - bool watch = false; + ReplicationMode mode = REPLICATION_MODE_ALWAYS; bool operator==(const ReplicationProperty &p_to) { return name == p_to.name; @@ -61,6 +67,9 @@ private: List<NodePath> spawn_props; List<NodePath> sync_props; List<NodePath> watch_props; + bool dirty = false; + + void _update(); protected: static void _bind_methods(); @@ -86,11 +95,16 @@ public: bool property_get_watch(const NodePath &p_path); void property_set_watch(const NodePath &p_path, bool p_enabled); - const List<NodePath> &get_spawn_properties() { return spawn_props; } - const List<NodePath> &get_sync_properties() { return sync_props; } - const List<NodePath> &get_watch_properties() { return watch_props; } + ReplicationMode property_get_replication_mode(const NodePath &p_path); + void property_set_replication_mode(const NodePath &p_path, ReplicationMode p_mode); + + const List<NodePath> &get_spawn_properties(); + const List<NodePath> &get_sync_properties(); + const List<NodePath> &get_watch_properties(); SceneReplicationConfig() {} }; +VARIANT_ENUM_CAST(SceneReplicationConfig::ReplicationMode); + #endif // SCENE_REPLICATION_CONFIG_H |