Prechádzať zdrojové kódy

Add restrictions to MultiplayerSynchronizer editor and documentation

Ninni Pipping 2 rokov pred
rodič
commit
f69fba0d65

+ 1 - 0
modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml

@@ -8,6 +8,7 @@
 		Visibility can be handled directly with [method set_visibility_for] or as-needed with [method add_visibility_filter] and [method update_visibility].
 		[MultiplayerSpawner]s will handle nodes according to visibility of synchronizers as long as the node at [member root_path] was spawned by one.
 		Internally, [MultiplayerSynchronizer] uses [method MultiplayerAPI.object_configuration_add] to notify synchronization start passing the [Node] at [member root_path] as the [code]object[/code] and itself as the [code]configuration[/code], and uses [method MultiplayerAPI.object_configuration_remove] to notify synchronization end in a similar way.
+		[b]Note:[/b] Synchronization is not supported for [Object] type properties, like [Resource]. Properties that are unique to each peer, like the instance IDs of [Object]s (see [method Object.get_instance_id]) or [RID]s, will also not work in synchronization.
 	</description>
 	<tutorials>
 	</tutorials>

+ 1 - 0
modules/multiplayer/doc_classes/SceneReplicationConfig.xml

@@ -14,6 +14,7 @@
 			<param index="1" name="index" type="int" default="-1" />
 			<description>
 				Adds the property identified by the given [param path] to the list of the properties being synchronized, optionally passing an [param index].
+				[b]Note:[/b] For details on restrictions and limitations on property synchronization, see [MultiplayerSynchronizer].
 			</description>
 		</method>
 		<method name="get_properties" qualifiers="const">

+ 69 - 0
modules/multiplayer/editor/replication_editor.cpp

@@ -195,6 +195,51 @@ ReplicationEditor::ReplicationEditor() {
 
 	prop_selector = memnew(PropertySelector);
 	add_child(prop_selector);
+	// Filter out properties that cannot be synchronized.
+	// * RIDs do not match across network.
+	// * Objects are too large for replication.
+	Vector<Variant::Type> types = {
+		Variant::BOOL,
+		Variant::INT,
+		Variant::FLOAT,
+		Variant::STRING,
+
+		Variant::VECTOR2,
+		Variant::VECTOR2I,
+		Variant::RECT2,
+		Variant::RECT2I,
+		Variant::VECTOR3,
+		Variant::VECTOR3I,
+		Variant::TRANSFORM2D,
+		Variant::VECTOR4,
+		Variant::VECTOR4I,
+		Variant::PLANE,
+		Variant::QUATERNION,
+		Variant::AABB,
+		Variant::BASIS,
+		Variant::TRANSFORM3D,
+		Variant::PROJECTION,
+
+		Variant::COLOR,
+		Variant::STRING_NAME,
+		Variant::NODE_PATH,
+		// Variant::RID,
+		// Variant::OBJECT,
+		Variant::SIGNAL,
+		Variant::DICTIONARY,
+		Variant::ARRAY,
+
+		Variant::PACKED_BYTE_ARRAY,
+		Variant::PACKED_INT32_ARRAY,
+		Variant::PACKED_INT64_ARRAY,
+		Variant::PACKED_FLOAT32_ARRAY,
+		Variant::PACKED_FLOAT64_ARRAY,
+		Variant::PACKED_STRING_ARRAY,
+		Variant::PACKED_VECTOR2_ARRAY,
+		Variant::PACKED_VECTOR3_ARRAY,
+		Variant::PACKED_COLOR_ARRAY
+	};
+	prop_selector->set_type_filter(types);
 	prop_selector->connect("selected", callable_mp(this, &ReplicationEditor::_pick_node_property_selected));
 
 	HBoxContainer *hb = memnew(HBoxContainer);
@@ -478,6 +523,24 @@ Ref<Texture2D> ReplicationEditor::_get_class_icon(const Node *p_node) {
 	return get_theme_icon(p_node->get_class(), "EditorIcons");
 }
 
+static bool can_sync(const Variant &p_var) {
+	switch (p_var.get_type()) {
+		case Variant::RID:
+		case Variant::OBJECT:
+			return false;
+		case Variant::ARRAY: {
+			const Array &arr = p_var;
+			if (arr.is_typed()) {
+				const uint32_t type = arr.get_typed_builtin();
+				return (type != Variant::RID) && (type != Variant::OBJECT);
+			}
+			return true;
+		}
+		default:
+			return true;
+	}
+}
+
 void ReplicationEditor::_add_property(const NodePath &p_property, bool p_spawn, bool p_sync, bool p_watch) {
 	String prop = String(p_property);
 	TreeItem *item = tree->create_item();
@@ -499,6 +562,12 @@ void ReplicationEditor::_add_property(const NodePath &p_property, bool p_spawn,
 		}
 		item->set_text(0, String(node->get_name()) + ":" + subpath);
 		icon = _get_class_icon(node);
+		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, icon);
 	item->add_button(4, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));