diff options
Diffstat (limited to 'modules/multiplayer')
-rw-r--r-- | modules/multiplayer/doc_classes/SceneReplicationConfig.xml | 38 | ||||
-rw-r--r-- | modules/multiplayer/editor/editor_network_profiler.cpp | 23 | ||||
-rw-r--r-- | modules/multiplayer/editor/replication_editor.cpp | 141 | ||||
-rw-r--r-- | modules/multiplayer/editor/replication_editor.h | 6 | ||||
-rw-r--r-- | modules/multiplayer/multiplayer_debugger.cpp | 4 | ||||
-rw-r--r-- | modules/multiplayer/multiplayer_spawner.cpp | 6 | ||||
-rw-r--r-- | modules/multiplayer/multiplayer_synchronizer.cpp | 10 | ||||
-rw-r--r-- | modules/multiplayer/scene_cache_interface.cpp | 14 | ||||
-rw-r--r-- | modules/multiplayer/scene_cache_interface.h | 1 | ||||
-rw-r--r-- | modules/multiplayer/scene_replication_config.cpp | 167 | ||||
-rw-r--r-- | modules/multiplayer/scene_replication_config.h | 24 | ||||
-rw-r--r-- | modules/multiplayer/scene_replication_interface.cpp | 28 | ||||
-rw-r--r-- | modules/multiplayer/scene_rpc_interface.cpp | 6 |
13 files changed, 276 insertions, 192 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/editor/editor_network_profiler.cpp b/modules/multiplayer/editor/editor_network_profiler.cpp index c2cb0a3d1a..a53eefc452 100644 --- a/modules/multiplayer/editor/editor_network_profiler.cpp +++ b/modules/multiplayer/editor/editor_network_profiler.cpp @@ -33,6 +33,7 @@ #include "core/os/os.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" +#include "editor/editor_string_names.h" void EditorNetworkProfiler::_bind_methods() { ADD_SIGNAL(MethodInfo("enable_profiling", PropertyInfo(Variant::BOOL, "enable"))); @@ -62,19 +63,19 @@ void EditorNetworkProfiler::_notification(int p_what) { void EditorNetworkProfiler::_update_theme_item_cache() { VBoxContainer::_update_theme_item_cache(); - theme_cache.node_icon = get_theme_icon(SNAME("Node"), SNAME("EditorIcons")); - theme_cache.stop_icon = get_theme_icon(SNAME("Stop"), SNAME("EditorIcons")); - theme_cache.play_icon = get_theme_icon(SNAME("Play"), SNAME("EditorIcons")); - theme_cache.clear_icon = get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")); + theme_cache.node_icon = get_theme_icon(SNAME("Node"), EditorStringName(EditorIcons)); + theme_cache.stop_icon = get_theme_icon(SNAME("Stop"), EditorStringName(EditorIcons)); + theme_cache.play_icon = get_theme_icon(SNAME("Play"), EditorStringName(EditorIcons)); + theme_cache.clear_icon = get_theme_icon(SNAME("Clear"), EditorStringName(EditorIcons)); - theme_cache.multiplayer_synchronizer_icon = get_theme_icon("MultiplayerSynchronizer", SNAME("EditorIcons")); - theme_cache.instance_options_icon = get_theme_icon(SNAME("InstanceOptions"), SNAME("EditorIcons")); + theme_cache.multiplayer_synchronizer_icon = get_theme_icon("MultiplayerSynchronizer", EditorStringName(EditorIcons)); + theme_cache.instance_options_icon = get_theme_icon(SNAME("InstanceOptions"), EditorStringName(EditorIcons)); - theme_cache.incoming_bandwidth_icon = get_theme_icon(SNAME("ArrowDown"), SNAME("EditorIcons")); - theme_cache.outgoing_bandwidth_icon = get_theme_icon(SNAME("ArrowUp"), SNAME("EditorIcons")); + theme_cache.incoming_bandwidth_icon = get_theme_icon(SNAME("ArrowDown"), EditorStringName(EditorIcons)); + theme_cache.outgoing_bandwidth_icon = get_theme_icon(SNAME("ArrowUp"), EditorStringName(EditorIcons)); - theme_cache.incoming_bandwidth_color = get_theme_color(SNAME("font_color"), SNAME("Editor")); - theme_cache.outgoing_bandwidth_color = get_theme_color(SNAME("font_color"), SNAME("Editor")); + theme_cache.incoming_bandwidth_color = get_theme_color(SNAME("font_color"), EditorStringName(Editor)); + theme_cache.outgoing_bandwidth_color = get_theme_color(SNAME("font_color"), EditorStringName(Editor)); } void EditorNetworkProfiler::_refresh() { @@ -128,7 +129,7 @@ void EditorNetworkProfiler::refresh_replication_data() { const NodeInfo &cfg_info = node_data[E.value.config]; node->set_text(0, root_info.path.get_file()); - node->set_icon(0, has_theme_icon(root_info.type, SNAME("EditorIcons")) ? get_theme_icon(root_info.type, SNAME("EditorIcons")) : theme_cache.node_icon); + node->set_icon(0, has_theme_icon(root_info.type, EditorStringName(EditorIcons)) ? get_theme_icon(root_info.type, EditorStringName(EditorIcons)) : theme_cache.node_icon); node->set_tooltip_text(0, root_info.path); node->set_text(1, sync_info.path.get_file()); diff --git a/modules/multiplayer/editor/replication_editor.cpp b/modules/multiplayer/editor/replication_editor.cpp index 04aa856bf9..eab1f5d51d 100644 --- a/modules/multiplayer/editor/replication_editor.cpp +++ b/modules/multiplayer/editor/replication_editor.cpp @@ -35,6 +35,7 @@ #include "editor/editor_node.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" +#include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/gui/scene_tree_editor.h" #include "editor/inspector_dock.h" @@ -111,9 +112,9 @@ void ReplicationEditor::_pick_node_filter_input(const Ref<InputEvent> &p_ie) { void ReplicationEditor::_pick_node_selected(NodePath p_path) { Node *root = current->get_node(current->get_root_path()); - ERR_FAIL_COND(!root); + ERR_FAIL_NULL(root); Node *node = get_node(p_path); - ERR_FAIL_COND(!node); + ERR_FAIL_NULL(node); NodePath path_to = root->get_path_to(node); adding_node_path = path_to; prop_selector->select_property_from_instance(node); @@ -176,11 +177,6 @@ ReplicationEditor::ReplicationEditor() { delete_dialog->connect("confirmed", callable_mp(this, &ReplicationEditor::_dialog_closed).bind(true)); add_child(delete_dialog); - error_dialog = memnew(AcceptDialog); - error_dialog->set_ok_button_text(TTR("Close")); - error_dialog->set_title(TTR("Error!")); - add_child(error_dialog); - VBoxContainer *vb = memnew(VBoxContainer); vb->set_v_size_flags(SIZE_EXPAND_FILL); add_child(vb); @@ -249,42 +245,45 @@ ReplicationEditor::ReplicationEditor() { add_pick_button->connect("pressed", callable_mp(this, &ReplicationEditor::_pick_new_property)); add_pick_button->set_text(TTR("Add property to sync...")); hb->add_child(add_pick_button); + VSeparator *vs = memnew(VSeparator); vs->set_custom_minimum_size(Size2(30 * EDSCALE, 0)); hb->add_child(vs); hb->add_child(memnew(Label(TTR("Path:")))); + np_line_edit = memnew(LineEdit); np_line_edit->set_placeholder(":property"); np_line_edit->set_h_size_flags(SIZE_EXPAND_FILL); + np_line_edit->connect("text_submitted", callable_mp(this, &ReplicationEditor::_np_text_submitted)); hb->add_child(np_line_edit); + add_from_path_button = memnew(Button); add_from_path_button->connect("pressed", callable_mp(this, &ReplicationEditor::_add_pressed)); add_from_path_button->set_text(TTR("Add from path")); hb->add_child(add_from_path_button); + vs = memnew(VSeparator); vs->set_custom_minimum_size(Size2(30 * EDSCALE, 0)); hb->add_child(vs); + pin = memnew(Button); - pin->set_flat(true); + pin->set_theme_type_variation("FlatButton"); pin->set_toggle_mode(true); hb->add_child(pin); tree = memnew(Tree); tree->set_hide_root(true); - tree->set_columns(5); + tree->set_columns(4); tree->set_column_titles_visible(true); tree->set_column_title(0, TTR("Properties")); tree->set_column_expand(0, true); tree->set_column_title(1, TTR("Spawn")); tree->set_column_expand(1, false); tree->set_column_custom_minimum_width(1, 100); - tree->set_column_title(2, TTR("Sync")); + tree->set_column_title(2, TTR("Replicate")); tree->set_column_custom_minimum_width(2, 100); - tree->set_column_title(3, TTR("Watch")); - tree->set_column_custom_minimum_width(3, 100); tree->set_column_expand(2, false); tree->set_column_expand(3, false); - tree->set_column_expand(4, false); tree->create_item(); tree->connect("button_clicked", callable_mp(this, &ReplicationEditor::_tree_button_pressed)); tree->connect("item_edited", callable_mp(this, &ReplicationEditor::_tree_item_edited)); @@ -292,7 +291,7 @@ ReplicationEditor::ReplicationEditor() { vb->add_child(tree); drop_label = memnew(Label); - drop_label->set_text(TTR("Add properties using the buttons above or\ndrag them them from the inspector and drop them here.")); + drop_label->set_text(TTR("Add properties using the options above, or\ndrag them them from the inspector and drop them here.")); drop_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); drop_label->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER); tree->add_child(drop_label); @@ -303,7 +302,7 @@ ReplicationEditor::ReplicationEditor() { void ReplicationEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_update_config"), &ReplicationEditor::_update_config); - ClassDB::bind_method(D_METHOD("_update_checked", "property", "column", "checked"), &ReplicationEditor::_update_checked); + ClassDB::bind_method(D_METHOD("_update_value", "property", "column", "value"), &ReplicationEditor::_update_value); } bool ReplicationEditor::_can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { @@ -365,25 +364,29 @@ void ReplicationEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - add_theme_style_override("panel", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox(SNAME("panel"), SNAME("Panel"))); - add_pick_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); - pin->set_icon(get_theme_icon(SNAME("Pin"), SNAME("EditorIcons"))); + add_theme_style_override("panel", EditorNode::get_singleton()->get_editor_theme()->get_stylebox(SNAME("panel"), SNAME("Panel"))); + add_pick_button->set_icon(get_theme_icon(SNAME("Add"), EditorStringName(EditorIcons))); + pin->set_icon(get_theme_icon(SNAME("Pin"), EditorStringName(EditorIcons))); } break; } } void ReplicationEditor::_add_pressed() { if (!current) { - error_dialog->set_text(TTR("Please select a MultiplayerSynchronizer first.")); - error_dialog->popup_centered(); + EditorNode::get_singleton()->show_warning(TTR("Please select a MultiplayerSynchronizer first.")); return; } if (current->get_root_path().is_empty()) { - error_dialog->set_text(TTR("The MultiplayerSynchronizer needs a root path.")); - error_dialog->popup_centered(); + EditorNode::get_singleton()->show_warning(TTR("The MultiplayerSynchronizer needs a root path.")); return; } String np_text = np_line_edit->get_text(); + + if (np_text.is_empty()) { + EditorNode::get_singleton()->show_warning(TTR("Property/path must not be empty.")); + return; + } + int idx = np_text.find(":"); if (idx == -1) { np_text = ".:" + np_text; @@ -391,46 +394,54 @@ void ReplicationEditor::_add_pressed() { np_text = "." + np_text; } NodePath path = NodePath(np_text); + if (path.is_empty()) { + EditorNode::get_singleton()->show_warning(vformat(TTR("Invalid property path: '%s'"), np_text)); + return; + } _add_sync_property(path); } +void ReplicationEditor::_np_text_submitted(const String &p_newtext) { + _add_pressed(); +} + void ReplicationEditor::_tree_item_edited() { TreeItem *ti = tree->get_edited(); if (!ti || config.is_null()) { return; } int column = tree->get_edited_column(); - ERR_FAIL_COND(column < 1 || column > 3); + ERR_FAIL_COND(column < 1 || column > 2); const NodePath prop = ti->get_metadata(0); EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); - bool value = ti->is_checked(column); - // We have a hard limit of 64 watchable properties per synchronizer. - if (column == 3 && value && config->get_watch_properties().size() > 64) { - error_dialog->set_text(TTR("Each MultiplayerSynchronizer can have no more than 64 watched properties.")); - error_dialog->popup_centered(); - ti->set_checked(column, false); - return; - } - String method; if (column == 1) { undo_redo->create_action(TTR("Set spawn property")); - method = "property_set_spawn"; + bool value = ti->is_checked(column); + undo_redo->add_do_method(config.ptr(), "property_set_spawn", prop, value); + undo_redo->add_undo_method(config.ptr(), "property_set_spawn", prop, !value); + undo_redo->add_do_method(this, "_update_value", prop, column, value ? 1 : 0); + undo_redo->add_undo_method(this, "_update_value", prop, column, value ? 1 : 0); + undo_redo->commit_action(); } else if (column == 2) { undo_redo->create_action(TTR("Set sync property")); - method = "property_set_sync"; - } else if (column == 3) { - undo_redo->create_action(TTR("Set watch property")); - method = "property_set_watch"; + int value = ti->get_range(column); + int old_value = config->property_get_replication_mode(prop); + // We have a hard limit of 64 watchable properties per synchronizer. + if (value == SceneReplicationConfig::REPLICATION_MODE_ON_CHANGE && config->get_watch_properties().size() >= 64) { + EditorNode::get_singleton()->show_warning(TTR("Each MultiplayerSynchronizer can have no more than 64 watched properties.")); + ti->set_range(column, old_value); + return; + } + undo_redo->add_do_method(config.ptr(), "property_set_replication_mode", prop, value); + undo_redo->add_undo_method(config.ptr(), "property_set_replication_mode", prop, old_value); + undo_redo->add_do_method(this, "_update_value", prop, column, value); + undo_redo->add_undo_method(this, "_update_value", prop, column, old_value); + undo_redo->commit_action(); } else { ERR_FAIL(); } - undo_redo->add_do_method(config.ptr(), method, prop, value); - undo_redo->add_undo_method(config.ptr(), method, prop, !value); - undo_redo->add_do_method(this, "_update_checked", prop, column, value); - undo_redo->add_undo_method(this, "_update_checked", prop, column, !value); - undo_redo->commit_action(); } void ReplicationEditor::_tree_button_pressed(Object *p_item, int p_column, int p_id, MouseButton p_button) { @@ -455,15 +466,13 @@ void ReplicationEditor::_dialog_closed(bool p_confirmed) { const NodePath prop = deleting; int idx = config->property_get_index(prop); bool spawn = config->property_get_spawn(prop); - bool sync = config->property_get_sync(prop); - bool watch = config->property_get_watch(prop); + SceneReplicationConfig::ReplicationMode mode = config->property_get_replication_mode(prop); EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); undo_redo->create_action(TTR("Remove Property")); undo_redo->add_do_method(config.ptr(), "remove_property", prop); undo_redo->add_undo_method(config.ptr(), "add_property", prop, idx); undo_redo->add_undo_method(config.ptr(), "property_set_spawn", prop, spawn); - undo_redo->add_undo_method(config.ptr(), "property_set_sync", prop, sync); - undo_redo->add_undo_method(config.ptr(), "property_set_watch", prop, watch); + undo_redo->add_undo_method(config.ptr(), "property_set_replication_mode", prop, mode); undo_redo->add_do_method(this, "_update_config"); undo_redo->add_undo_method(this, "_update_config"); undo_redo->commit_action(); @@ -471,14 +480,18 @@ void ReplicationEditor::_dialog_closed(bool p_confirmed) { deleting = NodePath(); } -void ReplicationEditor::_update_checked(const NodePath &p_prop, int p_column, bool p_checked) { +void ReplicationEditor::_update_value(const NodePath &p_prop, int p_column, int p_value) { if (!tree->get_root()) { return; } TreeItem *ti = tree->get_root()->get_first_child(); while (ti) { if (ti->get_metadata(0).operator NodePath() == p_prop) { - ti->set_checked(p_column, p_checked); + if (p_column == 1) { + ti->set_checked(p_column, p_value != 0); + } else if (p_column == 2) { + ti->set_range(p_column, p_value); + } return; } ti = ti->get_next(); @@ -499,7 +512,7 @@ void ReplicationEditor::_update_config() { } for (int i = 0; i < props.size(); i++) { const NodePath path = props[i]; - _add_property(path, config->property_get_spawn(path), config->property_get_sync(path), config->property_get_watch(path)); + _add_property(path, config->property_get_spawn(path), config->property_get_replication_mode(path)); } } @@ -517,10 +530,10 @@ void ReplicationEditor::edit(MultiplayerSynchronizer *p_sync) { } Ref<Texture2D> ReplicationEditor::_get_class_icon(const Node *p_node) { - if (!p_node || !has_theme_icon(p_node->get_class(), "EditorIcons")) { - return get_theme_icon(SNAME("ImportFail"), SNAME("EditorIcons")); + if (!p_node || !has_theme_icon(p_node->get_class(), EditorStringName(EditorIcons))) { + return get_theme_icon(SNAME("ImportFail"), EditorStringName(EditorIcons)); } - return get_theme_icon(p_node->get_class(), "EditorIcons"); + return get_theme_icon(p_node->get_class(), EditorStringName(EditorIcons)); } static bool can_sync(const Variant &p_var) { @@ -541,14 +554,13 @@ static bool can_sync(const Variant &p_var) { } } -void ReplicationEditor::_add_property(const NodePath &p_property, bool p_spawn, bool p_sync, bool p_watch) { +void ReplicationEditor::_add_property(const NodePath &p_property, bool p_spawn, SceneReplicationConfig::ReplicationMode p_mode) { String prop = String(p_property); TreeItem *item = tree->create_item(); item->set_selectable(0, false); item->set_selectable(1, false); item->set_selectable(2, false); item->set_selectable(3, false); - item->set_selectable(4, false); item->set_text(0, prop); item->set_metadata(0, prop); Node *root_node = current && !current->get_root_path().is_empty() ? current->get_node(current->get_root_path()) : nullptr; @@ -565,22 +577,23 @@ void ReplicationEditor::_add_property(const NodePath &p_property, bool p_spawn, bool valid = false; Variant value = node->get(subpath, &valid); if (valid && !can_sync(value)) { - item->set_icon(3, get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons"))); - item->set_tooltip_text(3, TTR("Property of this type not supported.")); + item->set_icon(0, get_theme_icon(SNAME("StatusWarning"), EditorStringName(EditorIcons))); + item->set_tooltip_text(0, TTR("Property of this type not supported.")); + } else { + item->set_icon(0, icon); } + } else { + item->set_icon(0, icon); } - item->set_icon(0, icon); - item->add_button(4, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); + item->add_button(3, get_theme_icon(SNAME("Remove"), EditorStringName(EditorIcons))); item->set_text_alignment(1, HORIZONTAL_ALIGNMENT_CENTER); item->set_cell_mode(1, TreeItem::CELL_MODE_CHECK); item->set_checked(1, p_spawn); item->set_editable(1, true); item->set_text_alignment(2, HORIZONTAL_ALIGNMENT_CENTER); - item->set_cell_mode(2, TreeItem::CELL_MODE_CHECK); - item->set_checked(2, p_sync); + item->set_cell_mode(2, TreeItem::CELL_MODE_RANGE); + item->set_range_config(2, 0, 2, 1); + item->set_text(2, "Never,Always,On Change"); + item->set_range(2, (int)p_mode); item->set_editable(2, true); - item->set_text_alignment(3, HORIZONTAL_ALIGNMENT_CENTER); - item->set_cell_mode(3, TreeItem::CELL_MODE_CHECK); - item->set_checked(3, p_watch); - item->set_editable(3, true); } diff --git a/modules/multiplayer/editor/replication_editor.h b/modules/multiplayer/editor/replication_editor.h index 208eaabff5..80c1892ec3 100644 --- a/modules/multiplayer/editor/replication_editor.h +++ b/modules/multiplayer/editor/replication_editor.h @@ -51,7 +51,6 @@ class ReplicationEditor : public VBoxContainer { private: MultiplayerSynchronizer *current = nullptr; - AcceptDialog *error_dialog = nullptr; ConfirmationDialog *delete_dialog = nullptr; Button *add_pick_button = nullptr; Button *add_from_path_button = nullptr; @@ -72,12 +71,13 @@ private: Ref<Texture2D> _get_class_icon(const Node *p_node); void _add_pressed(); + void _np_text_submitted(const String &p_newtext); void _tree_item_edited(); void _tree_button_pressed(Object *p_item, int p_column, int p_id, MouseButton p_button); - void _update_checked(const NodePath &p_prop, int p_column, bool p_checked); + void _update_value(const NodePath &p_prop, int p_column, int p_checked); void _update_config(); void _dialog_closed(bool p_confirmed); - void _add_property(const NodePath &p_property, bool p_spawn = true, bool p_sync = true, bool p_watch = false); + void _add_property(const NodePath &p_property, bool p_spawn, SceneReplicationConfig::ReplicationMode p_mode); void _pick_node_filter_text_changed(const String &p_newtext); void _pick_node_select_recursive(TreeItem *p_item, const String &p_filter, Vector<Node *> &p_select_candidates); diff --git a/modules/multiplayer/multiplayer_debugger.cpp b/modules/multiplayer/multiplayer_debugger.cpp index ea52741601..9b05fa884b 100644 --- a/modules/multiplayer/multiplayer_debugger.cpp +++ b/modules/multiplayer/multiplayer_debugger.cpp @@ -237,7 +237,7 @@ void MultiplayerDebugger::RPCProfiler::tick(double p_frame_time, double p_proces // ReplicationProfiler MultiplayerDebugger::SyncInfo::SyncInfo(MultiplayerSynchronizer *p_sync) { - ERR_FAIL_COND(!p_sync); + ERR_FAIL_NULL(p_sync); synchronizer = p_sync->get_instance_id(); if (p_sync->get_replication_config().is_valid()) { config = p_sync->get_replication_config()->get_instance_id(); @@ -305,7 +305,7 @@ void MultiplayerDebugger::ReplicationProfiler::add(const Array &p_data) { const ObjectID id = p_data[1]; const uint64_t size = p_data[2]; MultiplayerSynchronizer *sync = Object::cast_to<MultiplayerSynchronizer>(ObjectDB::get_instance(id)); - ERR_FAIL_COND(!sync); + ERR_FAIL_NULL(sync); if (!sync_data.has(id)) { sync_data[id] = SyncInfo(sync); } diff --git a/modules/multiplayer/multiplayer_spawner.cpp b/modules/multiplayer/multiplayer_spawner.cpp index 6c6aa28344..264a2e9c8e 100644 --- a/modules/multiplayer/multiplayer_spawner.cpp +++ b/modules/multiplayer/multiplayer_spawner.cpp @@ -268,7 +268,7 @@ void MultiplayerSpawner::_spawn_notify(ObjectID p_id) { void MultiplayerSpawner::_node_exit(ObjectID p_id) { Node *node = Object::cast_to<Node>(ObjectDB::get_instance(p_id)); - ERR_FAIL_COND(!node); + ERR_FAIL_NULL(node); if (tracked_nodes.has(p_id)) { tracked_nodes.erase(p_id); get_multiplayer()->object_configuration_remove(node, this); @@ -323,10 +323,10 @@ Node *MultiplayerSpawner::spawn(const Variant &p_data) { ERR_FAIL_COND_V_MSG(!spawn_function.is_valid(), nullptr, "Custom spawn requires the 'spawn_function' property to be a valid callable."); Node *parent = get_spawn_node(); - ERR_FAIL_COND_V_MSG(!parent, nullptr, "Cannot find spawn node."); + ERR_FAIL_NULL_V_MSG(parent, nullptr, "Cannot find spawn node."); Node *node = instantiate_custom(p_data); - ERR_FAIL_COND_V_MSG(!node, nullptr, "The 'spawn_function' callable must return a valid node."); + ERR_FAIL_NULL_V_MSG(node, nullptr, "The 'spawn_function' callable must return a valid node."); _track(node, p_data); parent->add_child(node, true); diff --git a/modules/multiplayer/multiplayer_synchronizer.cpp b/modules/multiplayer/multiplayer_synchronizer.cpp index 9c2d281f72..233f15c3a4 100644 --- a/modules/multiplayer/multiplayer_synchronizer.cpp +++ b/modules/multiplayer/multiplayer_synchronizer.cpp @@ -149,14 +149,14 @@ PackedStringArray MultiplayerSynchronizer::get_configuration_warnings() const { } Error MultiplayerSynchronizer::get_state(const List<NodePath> &p_properties, Object *p_obj, Vector<Variant> &r_variant, Vector<const Variant *> &r_variant_ptrs) { - ERR_FAIL_COND_V(!p_obj, ERR_INVALID_PARAMETER); + ERR_FAIL_NULL_V(p_obj, ERR_INVALID_PARAMETER); r_variant.resize(p_properties.size()); r_variant_ptrs.resize(r_variant.size()); int i = 0; for (const NodePath &prop : p_properties) { bool valid = false; const Object *obj = _get_prop_target(p_obj, prop); - ERR_FAIL_COND_V(!obj, FAILED); + ERR_FAIL_NULL_V(obj, FAILED); r_variant.write[i] = obj->get_indexed(prop.get_subnames(), &valid); r_variant_ptrs.write[i] = &r_variant[i]; ERR_FAIL_COND_V_MSG(!valid, ERR_INVALID_DATA, vformat("Property '%s' not found.", prop)); @@ -166,11 +166,11 @@ Error MultiplayerSynchronizer::get_state(const List<NodePath> &p_properties, Obj } Error MultiplayerSynchronizer::set_state(const List<NodePath> &p_properties, Object *p_obj, const Vector<Variant> &p_state) { - ERR_FAIL_COND_V(!p_obj, ERR_INVALID_PARAMETER); + ERR_FAIL_NULL_V(p_obj, ERR_INVALID_PARAMETER); int i = 0; for (const NodePath &prop : p_properties) { Object *obj = _get_prop_target(p_obj, prop); - ERR_FAIL_COND_V(!obj, FAILED); + ERR_FAIL_NULL_V(obj, FAILED); obj->set_indexed(prop.get_subnames(), p_state[i]); i += 1; } @@ -374,7 +374,7 @@ Error MultiplayerSynchronizer::_watch_changes(uint64_t p_usec) { return OK; } Node *node = get_root_node(); - ERR_FAIL_COND_V(!node, FAILED); + ERR_FAIL_NULL_V(node, FAILED); int idx = -1; Watcher *ptr = watchers.ptrw(); for (const NodePath &prop : props) { diff --git a/modules/multiplayer/scene_cache_interface.cpp b/modules/multiplayer/scene_cache_interface.cpp index 90e6ac7c2c..8d102ca981 100644 --- a/modules/multiplayer/scene_cache_interface.cpp +++ b/modules/multiplayer/scene_cache_interface.cpp @@ -53,7 +53,7 @@ void SceneCacheInterface::on_peer_change(int p_id, bool p_connected) { void SceneCacheInterface::process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len) { Node *root_node = SceneTree::get_singleton()->get_root()->get_node(multiplayer->get_root_path()); - ERR_FAIL_COND(!root_node); + ERR_FAIL_NULL(root_node); ERR_FAIL_COND_MSG(p_packet_len < 38, "Invalid packet received. Size too small."); int ofs = 1; @@ -74,7 +74,7 @@ void SceneCacheInterface::process_simplify_path(int p_from, const uint8_t *p_pac } Node *node = root_node->get_node(path); - ERR_FAIL_COND(node == nullptr); + ERR_FAIL_NULL(node); const bool valid_rpc_checksum = multiplayer->get_rpc_md5(node) == methods_md5; if (valid_rpc_checksum == false) { ERR_PRINT("The rpc node checksum failed. Make sure to have the same methods on both nodes. Node path: " + path); @@ -119,7 +119,7 @@ void SceneCacheInterface::process_confirm_path(int p_from, const uint8_t *p_pack } PathSentCache *psc = path_send_cache.getptr(path); - ERR_FAIL_COND_MSG(!psc, "Invalid packet received. Tries to confirm a path which was not found in cache."); + ERR_FAIL_NULL_MSG(psc, "Invalid packet received. Tries to confirm a path which was not found in cache."); HashMap<int, bool>::Iterator E = psc->confirmed_peers.find(p_from); ERR_FAIL_COND_MSG(!E, "Invalid packet received. Source peer was not found in cache for the given path."); @@ -165,7 +165,7 @@ Error SceneCacheInterface::_send_confirm_path(Node *p_node, NodePath p_path, Pat bool SceneCacheInterface::is_cache_confirmed(NodePath p_path, int p_peer) { const PathSentCache *psc = path_send_cache.getptr(p_path); - ERR_FAIL_COND_V(!psc, false); + ERR_FAIL_NULL_V(psc, false); HashMap<int, bool>::ConstIterator F = psc->confirmed_peers.find(p_peer); ERR_FAIL_COND_V(!F, false); // Should never happen. return F->value; @@ -173,7 +173,7 @@ bool SceneCacheInterface::is_cache_confirmed(NodePath p_path, int p_peer) { int SceneCacheInterface::make_object_cache(Object *p_obj) { Node *node = Object::cast_to<Node>(p_obj); - ERR_FAIL_COND_V(!node, -1); + ERR_FAIL_NULL_V(node, -1); NodePath for_path = multiplayer->get_root_path().rel_path_to(node->get_path()); // See if the path is cached. PathSentCache *psc = path_send_cache.getptr(for_path); @@ -188,7 +188,7 @@ int SceneCacheInterface::make_object_cache(Object *p_obj) { bool SceneCacheInterface::send_object_cache(Object *p_obj, int p_peer_id, int &r_id) { Node *node = Object::cast_to<Node>(p_obj); - ERR_FAIL_COND_V(!node, false); + ERR_FAIL_NULL_V(node, false); r_id = make_object_cache(p_obj); ERR_FAIL_COND_V(r_id < 0, false); @@ -233,7 +233,7 @@ bool SceneCacheInterface::send_object_cache(Object *p_obj, int p_peer_id, int &r Object *SceneCacheInterface::get_cached_object(int p_from, uint32_t p_cache_id) { Node *root_node = SceneTree::get_singleton()->get_root()->get_node(multiplayer->get_root_path()); - ERR_FAIL_COND_V(!root_node, nullptr); + ERR_FAIL_NULL_V(root_node, nullptr); HashMap<int, PathGetCache>::Iterator E = path_get_cache.find(p_from); ERR_FAIL_COND_V_MSG(!E, nullptr, vformat("No cache found for peer %d.", p_from)); diff --git a/modules/multiplayer/scene_cache_interface.h b/modules/multiplayer/scene_cache_interface.h index 9400417cdb..7a7304fde8 100644 --- a/modules/multiplayer/scene_cache_interface.h +++ b/modules/multiplayer/scene_cache_interface.h @@ -33,6 +33,7 @@ #include "scene/main/multiplayer_api.h" +class Node; class SceneMultiplayer; class SceneCacheInterface : public RefCounted { diff --git a/modules/multiplayer/scene_replication_config.cpp b/modules/multiplayer/scene_replication_config.cpp index af6af35219..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,22 +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); + dirty = true; } bool SceneReplicationConfig::has_property(const NodePath &p_path) const { @@ -195,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)); @@ -253,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 diff --git a/modules/multiplayer/scene_replication_interface.cpp b/modules/multiplayer/scene_replication_interface.cpp index 7f12fea4bf..e350f2f68b 100644 --- a/modules/multiplayer/scene_replication_interface.cpp +++ b/modules/multiplayer/scene_replication_interface.cpp @@ -155,7 +155,7 @@ Error SceneReplicationInterface::on_spawn(Object *p_obj, Variant p_config) { Node *node = Object::cast_to<Node>(p_obj); ERR_FAIL_COND_V(!node || p_config.get_type() != Variant::OBJECT, ERR_INVALID_PARAMETER); MultiplayerSpawner *spawner = Object::cast_to<MultiplayerSpawner>(p_config.get_validated_object()); - ERR_FAIL_COND_V(!spawner, ERR_INVALID_PARAMETER); + ERR_FAIL_NULL_V(spawner, ERR_INVALID_PARAMETER); // Track node. const ObjectID oid = node->get_instance_id(); TrackedNode &tobj = _track(oid); @@ -226,7 +226,7 @@ Error SceneReplicationInterface::on_replication_start(Object *p_obj, Variant p_c Node *node = Object::cast_to<Node>(p_obj); ERR_FAIL_COND_V(!node || p_config.get_type() != Variant::OBJECT, ERR_INVALID_PARAMETER); MultiplayerSynchronizer *sync = Object::cast_to<MultiplayerSynchronizer>(p_config.get_validated_object()); - ERR_FAIL_COND_V(!sync, ERR_INVALID_PARAMETER); + ERR_FAIL_NULL_V(sync, ERR_INVALID_PARAMETER); // Add to synchronizer list. TrackedNode &tobj = _track(p_obj->get_instance_id()); @@ -270,7 +270,7 @@ Error SceneReplicationInterface::on_replication_stop(Object *p_obj, Variant p_co Node *node = Object::cast_to<Node>(p_obj); ERR_FAIL_COND_V(!node || p_config.get_type() != Variant::OBJECT, ERR_INVALID_PARAMETER); MultiplayerSynchronizer *sync = Object::cast_to<MultiplayerSynchronizer>(p_config.get_validated_object()); - ERR_FAIL_COND_V(!sync, ERR_INVALID_PARAMETER); + ERR_FAIL_NULL_V(sync, ERR_INVALID_PARAMETER); sync->disconnect("visibility_changed", callable_mp(this, &SceneReplicationInterface::_visibility_changed)); // Untrack synchronizer. const ObjectID oid = node->get_instance_id(); @@ -291,9 +291,9 @@ Error SceneReplicationInterface::on_replication_stop(Object *p_obj, Variant p_co void SceneReplicationInterface::_visibility_changed(int p_peer, ObjectID p_sid) { MultiplayerSynchronizer *sync = get_id_as<MultiplayerSynchronizer>(p_sid); - ERR_FAIL_COND(!sync); // Bug. + ERR_FAIL_NULL(sync); // Bug. Node *node = sync->get_root_node(); - ERR_FAIL_COND(!node); // Bug. + ERR_FAIL_NULL(node); // Bug. const ObjectID oid = node->get_instance_id(); if (spawned_nodes.has(oid) && p_peer != multiplayer->get_unique_id()) { _update_spawn_visibility(p_peer, oid); @@ -341,7 +341,7 @@ bool SceneReplicationInterface::is_rpc_visible(const ObjectID &p_oid, int p_peer } Error SceneReplicationInterface::_update_sync_visibility(int p_peer, MultiplayerSynchronizer *p_sync) { - ERR_FAIL_COND_V(!p_sync, ERR_BUG); + ERR_FAIL_NULL_V(p_sync, ERR_BUG); if (!multiplayer->has_multiplayer_peer() || !p_sync->is_multiplayer_authority() || p_peer == multiplayer->get_unique_id()) { return OK; } @@ -380,7 +380,7 @@ Error SceneReplicationInterface::_update_sync_visibility(int p_peer, Multiplayer Error SceneReplicationInterface::_update_spawn_visibility(int p_peer, const ObjectID &p_oid) { const TrackedNode *tnode = tracked_nodes.getptr(p_oid); - ERR_FAIL_COND_V(!tnode, ERR_BUG); + ERR_FAIL_NULL_V(tnode, ERR_BUG); MultiplayerSpawner *spawner = get_id_as<MultiplayerSpawner>(tnode->spawner); Node *node = get_id_as<Node>(p_oid); ERR_FAIL_COND_V(!node || !spawner || !spawner->is_multiplayer_authority(), ERR_BUG); @@ -467,7 +467,7 @@ Error SceneReplicationInterface::_make_spawn_packet(Node *p_node, MultiplayerSpa const ObjectID oid = p_node->get_instance_id(); const TrackedNode *tnode = tracked_nodes.getptr(oid); - ERR_FAIL_COND_V(!tnode, ERR_INVALID_PARAMETER); + ERR_FAIL_NULL_V(tnode, ERR_INVALID_PARAMETER); uint32_t nid = tnode->net_id; ERR_FAIL_COND_V(!nid, ERR_UNCONFIGURED); @@ -549,7 +549,7 @@ Error SceneReplicationInterface::_make_spawn_packet(Node *p_node, MultiplayerSpa Error SceneReplicationInterface::_make_despawn_packet(Node *p_node, int &r_len) { const ObjectID oid = p_node->get_instance_id(); const TrackedNode *tnode = tracked_nodes.getptr(oid); - ERR_FAIL_COND_V(!tnode, ERR_INVALID_PARAMETER); + ERR_FAIL_NULL_V(tnode, ERR_INVALID_PARAMETER); MAKE_ROOM(5); uint8_t *ptr = packet_cache.ptrw(); ptr[0] = (uint8_t)SceneMultiplayer::NETWORK_COMMAND_DESPAWN; @@ -568,7 +568,7 @@ Error SceneReplicationInterface::on_spawn_receive(int p_from, const uint8_t *p_b uint32_t node_target = decode_uint32(&p_buffer[ofs]); ofs += 4; MultiplayerSpawner *spawner = Object::cast_to<MultiplayerSpawner>(multiplayer->get_path_cache()->get_cached_object(p_from, node_target)); - ERR_FAIL_COND_V(!spawner, ERR_DOES_NOT_EXIST); + ERR_FAIL_NULL_V(spawner, ERR_DOES_NOT_EXIST); ERR_FAIL_COND_V(p_from != spawner->get_multiplayer_authority(), ERR_UNAUTHORIZED); uint32_t net_id = decode_uint32(&p_buffer[ofs]); @@ -592,7 +592,7 @@ Error SceneReplicationInterface::on_spawn_receive(int p_from, const uint8_t *p_b // Check that we can spawn. Node *parent = spawner->get_node_or_null(spawner->get_spawn_path()); - ERR_FAIL_COND_V(!parent, ERR_UNCONFIGURED); + ERR_FAIL_NULL_V(parent, ERR_UNCONFIGURED); ERR_FAIL_COND_V(parent->has_node(name), ERR_INVALID_DATA); Node *node = nullptr; @@ -611,7 +611,7 @@ Error SceneReplicationInterface::on_spawn_receive(int p_from, const uint8_t *p_b // Scene based spawn. node = spawner->instantiate_scene(scene_id); } - ERR_FAIL_COND_V(!node, ERR_UNAUTHORIZED); + ERR_FAIL_NULL_V(node, ERR_UNAUTHORIZED); node->set_name(name); // Add and track remote @@ -656,13 +656,13 @@ Error SceneReplicationInterface::on_despawn_receive(int p_from, const uint8_t *p PeerInfo &pinfo = peers_info[p_from]; ERR_FAIL_COND_V(!pinfo.recv_nodes.has(net_id), ERR_UNAUTHORIZED); Node *node = get_id_as<Node>(pinfo.recv_nodes[net_id]); - ERR_FAIL_COND_V(!node, ERR_BUG); + ERR_FAIL_NULL_V(node, ERR_BUG); pinfo.recv_nodes.erase(net_id); const ObjectID oid = node->get_instance_id(); ERR_FAIL_COND_V(!tracked_nodes.has(oid), ERR_BUG); MultiplayerSpawner *spawner = get_id_as<MultiplayerSpawner>(tracked_nodes[oid].spawner); - ERR_FAIL_COND_V(!spawner, ERR_DOES_NOT_EXIST); + ERR_FAIL_NULL_V(spawner, ERR_DOES_NOT_EXIST); ERR_FAIL_COND_V(p_from != spawner->get_multiplayer_authority(), ERR_UNAUTHORIZED); if (node->get_parent() != nullptr) { diff --git a/modules/multiplayer/scene_rpc_interface.cpp b/modules/multiplayer/scene_rpc_interface.cpp index da1a044c9d..48e1d13f9c 100644 --- a/modules/multiplayer/scene_rpc_interface.cpp +++ b/modules/multiplayer/scene_rpc_interface.cpp @@ -134,7 +134,7 @@ _FORCE_INLINE_ bool _can_call_mode(Node *p_node, MultiplayerAPI::RPCMode mode, i String SceneRPCInterface::get_rpc_md5(const Object *p_obj) { const Node *node = Object::cast_to<Node>(p_obj); - ERR_FAIL_COND_V(!node, ""); + ERR_FAIL_NULL_V(node, ""); const RPCConfigCache cache = _get_node_config(node); String rpc_list; for (const KeyValue<uint16_t, RPCConfig> &config : cache.configs) { @@ -145,7 +145,7 @@ String SceneRPCInterface::get_rpc_md5(const Object *p_obj) { Node *SceneRPCInterface::_process_get_node(int p_from, const uint8_t *p_packet, uint32_t p_node_target, int p_packet_len) { Node *root_node = SceneTree::get_singleton()->get_root()->get_node(multiplayer->get_root_path()); - ERR_FAIL_COND_V(!root_node, nullptr); + ERR_FAIL_NULL_V(root_node, nullptr); Node *node = nullptr; if (p_node_target & 0x80000000) { @@ -225,7 +225,7 @@ void SceneRPCInterface::process_rpc(int p_from, const uint8_t *p_packet, int p_p } Node *node = _process_get_node(p_from, p_packet, node_target, p_packet_len); - ERR_FAIL_COND_MSG(node == nullptr, "Invalid packet received. Requested node was not found."); + ERR_FAIL_NULL_MSG(node, "Invalid packet received. Requested node was not found."); uint16_t name_id = 0; switch (name_id_compression) { |