ethod name="is_instance_of">
			<return type="bool" />
			<param index="0" name="value" type="Variant" />
			<param index="1" name="type" type="Variant" />
			<description>
				Returns [code]true[/code] if [param value] is an instance of [param type]. The [param type] value must be one of the following:
				- A constant from the [enum Variant.Type] enumeration, for example [constant TYPE_INT].
				- An [Object]-derived class which exists in [ClassDB], for example [Node].
				- A [Script] (you can use any class, including inner one).
				Unlike the right operand of the [code]is[/code] operator, [param type] can be a non-constant value. The [code]is[/code] operator supports more features (such as typed arrays). Use the operator instead of this method if you do not need dynamic type checking.
				[b]Examples:[/b]
				[codeblock]
				print(is_instance_of(a, TYPE_INT))
				print(is_instance_of(a, Node))
				print(is_instance_of(a, MyClass))
				print(is_instance_of(a, MyClass.InnerClass))
				[/codeblock]
				[b]Note:[/b] If [param value] and/or [param type] are freed objects (see [method @GlobalScope.is_instance_valid]), or [param type] is not one of the above options, this method will raise a runtime error.
				See also [method @GlobalScope.typeof], [method type_exists], [method Array.is_same_typed] (and other [Array] methods).
			</description>
		</method>
		<method name="len">
			<return type="int" />
			<param index="0" name="var" type="Variant" />
			<description>
				Returns the length of the given Variant [param var]. The length can be the character count of a [String] or [StringName], the element count of any array type, or the size of a [Dictionary]. For every other Variant type, a run-time error is generated and execution is stopped.
				[codeblock]
				var a = [1, 2, 3, 4]
				len(a) # Returns 4

				var b = "Hello!"
				len(b) # Returns 6
				[/codeblock]
			</description>
		</method>
		<method name="load">
			<return type="Resource" />
			<param index="0" name="path" type="String" />
			<description>
				Returns a [Resource] from the filesystem located at the absolute [param path]. Unless it's already referenced elsewhere (such as in another script or in the scene), the resource is loaded from disk on function call, which might cause a slight delay, especially when loading large scenes. To avoid unnecessary delays when loading something multiple times, either store the resource in a variable or use [method preload]. This method is equivalent of using [method ResourceLoader.load] with [constant ResourceLoader.CACHE_MODE_REUSE].
				[b]Note:[/b] Resource paths can be obtained by right-clicking on a resource in the FileSystem dock and choosing "Copy Path", or by dragging the file from the FileSystem dock into the current script.
				[codeblock]
				# Load a scene called "main" located in the root of the project directory and cache it in a variable.
				var main = load("res://main.tscn") # main will contain a PackedScene resource.
				[/codeblock]
				[b]Important:[/b] Relative paths are [i]not[/i] relative to the script calling this method, instead it is prefixed with [code]"res://"[/code]. Loading from relative paths might not work as expected.
				This function is a simplified version of [method ResourceLoader.load], which can be used for more advanced scenarios.
				[b]Note:[/b] Files have to be imported into the engine first to load them using this function. If you want to load [Image]s at run-time, you may use [method Image.load]. If you want to import audio files, you can use the snippet described in [member AudioStreamMP3.data].
				[b]Note:[/b] If [member ProjectSettings.editor/export/convert_text_resources_to_binary] is [code]true[/code], [method @GDScript.load] will not be able to read converted files in an exported project. If you rely on run-time loading of files present within the PCK, set [member ProjectSettings.editor/export/convert_text_resources_to_binary] to [code]false[/code].
			</description>
		</method>
		<method name="preload">
			<return type="Resource" />
			<param index="0" name="path" type="String" />
			<description>
				Returns a [Resource] from the filesystem located at [param path]. During run-time, the resource is loaded when the script is being parsed. This function effectively acts as a reference to that resource. Note that this function requires [param path] to be a constant [String]. If you want to load a resource from a dynamic/variable path, use [method load].
				[b]Note:[/b] Resource paths can be obtained by right-clicking on a resource in the Assets Panel and choosing "Copy Path", or by dragging the file from the FileSystem dock into the current script.
				[codeblock]
				# Create instance of a scene.
				var diamond = preload("res://diamond.tscn").instantiate()
				[/codeblock]
				[b]Note:[/b] [method preload] is a keyword, not a function. So you cannot access it as a [Callable].
			</description>
		</method>
		<method name="print_debug" qualifiers="vararg">
			<return type="void" />
			<description>
				Like [method @GlobalScope.print], but includes the current stack frame when running with the debugger turned on.
				The output in the console may look like the following:
				[codeblock lang=text]
				Test print
				At: res://test.gd:15:_process()
				[/codeblock]
				[b]Note:[/b] Calling this function from a [Thread] is not supported. Doing so will instead print the thread ID.
			</description>
		</method>
		<method name="print_stack">
			<return type="void" />
			<description>
				Prints a stack trace at the current code location. See also [method get_stack].
				The output in the console may look like the following:
				[codeblock lang=text]
				Frame 0 - res://test.gd:16 in function '_process'
				[/codeblock]
				[b]Note:[/b] This function only works if the running instance is connected to a debugging server (i.e. an editor instance). [method print_stack] will not work in projects exported in release mode, or in projects exported in debug mode if not connected to a debugging server.
				[b]Note:[/b] Calling this function from a [Thread] is not supported. Doing so will instead print the thread ID.
			</description>
		</method>
		<m


nnotations>
		<annotation name="@export">
			<return type="void" />
			<description>
				Mark the following property as exported (editable in the Inspector dock and saved to disk). To control the type of the exported property, use the type hint notation.
				[codeblock]
				extends Node

				enum Direction {LEFT, RIGHT, UP, DOWN}

				# Built-in types.
				@export var string = ""
				@export var int_number = 5
				@export var float_number: float = 5

				# Enums.
				@export var type: Variant.Type
				@export var format: Image.Format
				@export var direction: Direction

				# Resources.
				@export var image: Image
				@export var custom_resource: CustomResource

				# Nodes.
				@export var node: Node
				@export var custom_node: CustomNode

				# Typed arrays.
				@export var int_array: Array[int]
				@export var direction_array: Array[Direction]
				@export var image_array: Array[Image]
				@export var node_array: Array[Node]
				[/codeblock]
				[b]Note:[/b] Custom resources and nodes should be registered as global classes using [code]class_name[/code], since the Inspector currently only supports global classes. Otherwise, a less specific type will be exported instead.
				[b]Note:[/b] Node export is only supported in [Node]-derived classes and has a number of other limitations.
			</description>
		</annotation>
		<annotation name="@export_category">
			<return type="void" />
			<param index="0" name="name" type="String" />
			<description>
				Define a new category for the following exported properties. This helps to organize properties in the Inspector dock.
				See also [constant PROPERTY_USAGE_CATEGORY].
				[codeblock]
				@export_category("Statistics")
				@export var hp = 30
				@export var speed = 1.25
				[/codeblock]
				[b]Note:[/b] Categories in the Inspector dock's list usually divide properties coming from different classes (Node, Node2D, Sprite, etc.). For better clarity, it's recommended to use [annotation @export_group] and [annotation @export_subgroup], instead.
			</description>
		</annotation>
		<annotation name="@export_color_no_alpha">
			<return type="void" />
			<description>
				Export a [Color], [Array][lb][Color][rb], or [PackedColorArray] property without allowing its transparency ([member Color.a]) to be edited.
				See also [constant PROPERTY_HINT_COLOR_NO_ALPHA].
				[codeblock]
				@export_color_no_alpha var dye_color: Color
				@export_color_no_alpha var dye_colors: Array[Color]
				[/codeblock]
			</description>
		</annotation>
		<annotation name="@export_custom">
			<return type="void" />
			<param index="0" name="hint" type="int" enum="PropertyHint" />
			<param index="1" name="hint_string" type="String" />
			<param index="2" name="usage" type="int" enum="PropertyUsageFlags" is_bitfield="true" default="6" />
			<description>
				Allows you to set a custom hint, hint string, and usage flags for the exported property. Note that there's no validation done in GDScript, it will just pass the parameters to the editor.
				[codeblock]
				@export_custom(PROPERTY_HINT_NONE, "suffix:m") var suffix: Vector3
				[/codeblock]
				[b]Note:[/b] Regardless of the [param usage] value, the [constant PROPERTY_USAGE_SCRIPT_VARIABLE] flag is always added, as with any explicitly declared script variable.
			</description>
		</annotation>
		<annotation name="@export_dir">
			<return type="void" />
			<description>
				Export a [String], [Array][lb][String][rb], or [PackedStringArray] property as a path to a directory. The path will be limited to the project folder and its subfolders. See [annotation @export_global_dir] to allow picking from the entire filesystem.
				See also [constant PROPERTY_HINT_DIR].
				[codeblock]
				@export_dir var sprite_folder_path: String
				@export_dir var sprite_folder_paths: Array[String]
				[/codeblock]
			</description>
		</annotation>
		<annotation name="@export_enum" qualifiers="vararg">
			<return type="void" />
			<param index="0" name="names" type="String" />
			<description>
				Export an [int], [String], [Array][lb][int][rb], [Array][lb][String][rb], [PackedByteArray], [PackedInt32Array], [PackedInt64Array], or [PackedStringArray] property as an enumerated list of options (or an array of options). If the property is an [int], then the index of the value is stored, in the same order the values are provided. You can add explicit values using a colon. If the property is a [String], then the value is stored.
				See also [constant PROPERTY_HINT_ENUM].
				[codeblock]
				@export_enum("Warrior", "Magician", "Thief") var character_class: int
				@export_enum("Slow:30", "Average:60", "Very Fast:200") var character_speed: int
				@export_enum("Rebecca", "Mary", "Leah") var character_name: String

				@export_enum("Sword", "Spear", "Mace") var character_items: Array[int]
				@export_enum("double_jump", "climb", "dash") var character_skills: Array[String]
				[/codeblock]
				If you want to set an initial value, you must specify it explicitly:
				[codeblock]
				@export_enum("Rebecca", "Mary", "Leah") var character_name: String = "Rebecca"
				[/codeblock]
				If you want to use named GDScript enums, then use [annotation @export] instead:
				[codeblock]
				enum CharacterName {REBECCA, MARY, LEAH}
				@export var character_name: CharacterName

				enum CharacterItem {SWORD, SPEAR, MACE}
				@export var character_items: Array[CharacterItem]
				[/codeblock]
			</description>
		</annotation>
		<annotation name="@export_exp_easing" qualifiers="vararg">
			<return type="void" />
			<param index="0" name="hints" type="String" default="""" />
			<description>
				Export a floating-point property with an easing editor widget. Additional hints can be provided to adjust the behavior of the widget. [code]"attenuation"[/code] flips the curve, which makes it more intuitive for editing attenuation properties. [code]"positive_only"[/code] limits values to only be greater than or equal to zero.
				See also [constant PROPERTY_HINT_EXP_EASING].
				[codeblock]
				@export_exp_easing var transition_speed
				@export_exp_easing("attenuation") var fading_attenuation
				@export_exp_easing("positive_only") var effect_power
				@export_exp_easing var speeds: Array[float]
				[/codeblock]
			</description>
		</annotation>
		<annotation name="@export_file" qualifiers="vararg">
			<return type="void" />
			<param index="0" name="filter" type="String" default="""" />
			<description>
				Export a [String], [Array][lb][String][rb], or [PackedStringArray] property as a path to a file. The path will be limited to the project folder and its subfolders. See [annotation @export_global_file] to allow picking from the entire filesystem.
				If [param filter] is provided, only matching files will be available for picking.
				See also [constant PROPERTY_HINT_FILE].
				[codeblock]
				@export_file var sound_effect_path: String
				@export_file("*.txt") var notes_path: String
				@export_file var level_paths: Array[String]
				[/codeblock]
			</description>
		</annotation>
		<a


nnotation name="@export_group">
			<return type="void" />
			<param index="0" name="name" type="String" />
			<param index="1" name="prefix" type="String" default="""" />
			<description>
				Define a new group for the following exported properties. This helps to organize properties in the Inspector dock. Groups can be added with an optional [param prefix], which would make group to only consider properties that have this prefix. The grouping will break on the first property that doesn't have a prefix. The prefix is also removed from the property's name in the Inspector dock.
				If no [param prefix] is provided, then every following property will be added to the group. The group ends when then next group or category is defined. You can also force end a group by using this annotation with empty strings for parameters, [code]@export_group("", "")[/code].
				Groups cannot be nested, use [annotation @export_subgroup] to add subgroups within groups.
				See also [constant PROPERTY_USAGE_GROUP].
				[codeblock]
				@export_group("Racer Properties")
				@export var nickname = "Nick"
				@export var age = 26

				@export_group("Car Properties", "car_")
				@export var car_label = "Speedy"
				@export var car_number = 3

				@export_group("", "")
				@export var ungrouped_number = 3
				[/codeblock]
			</description>
		</annotation>
		<annotation name="@export_multiline">
			<return type="void" />
			<description>
				Export a [String], [Array][lb][String][rb], [PackedStringArray], [Dictionary] or [Array][lb][Dictionary][rb] property with a large [TextEdit] widget instead of a [LineEdit]. This adds support for multiline content and makes it easier to edit large amount of text stored in the property.
				See also [constant PROPERTY_HINT_MULTILINE_TEXT].
				[codeblock]
				@export_multiline var character_biography
				@export_multiline var npc_dialogs: Array[String]
				[/codeblock]
			</description>
		</annotation>
		<annotation name="@export_node_path" qualifiers="vararg">
			<return type="void" />
			<param index="0" name="type" type="String" default="""" />
			<description>
				Export a [NodePath] or [Array][lb][NodePath][rb] property with a filter for allowed node types.
				See also [constant PROPERTY_HINT_NODE_PATH_VALID_TYPES].
				[codeblock]
				@export_node_path("Button", "TouchScreenButton") var some_button
				@export_node_path("Button", "TouchScreenButton") var many_buttons: Array[NodePath]
				[/codeblock]
				[b]Note:[/b] The type must be a native class or a globally registered script (using the [code]class_name[/code] keyword) that inherits [Node].
			</description>
		</annotation>
		<annotation name="@export_placeholder">
			<return type="void" />
			<param index="0" name="placeholder" type="String" />
			<description>
				Export a [String], [Array][lb][String][rb], or [PackedStringArray] property with a placeholder text displayed in the editor widget when no value is present.
				See also [constant PROPERTY_HINT_PLACEHOLDER_TEXT].
				[codeblock]
				@export_placeholder("Name in lowercase") var character_id: String
				@export_placeholder("Name in lowercase") var friend_ids: Array[String]
				[/codeblock]
			</description>
		</annotation>
		<annotation name="@export_range" qualifiers="vararg">
			<return type="void" />
			<param index="0" name="min" type="float" />
			<param index="1" name="max" type="float" />
			<param index="2" name="step" type="float" default="1.0" />
			<param index="3" name="extra_hints" type="String" default="""" />
			<description>
				Export an [int], [float], [Array][lb][int][rb], [Array][lb][float][rb], [PackedByteArray], [PackedInt32Array], [PackedInt64Array], [PackedFloat32Array], or [PackedFloat64Array] property as a range value. The range must be defined by [param min] and [param max], as well as an optional [param step] and a variety of extra hints. The [param step] defaults to [code]1[/code] for integer properties. For floating-point numbers this value depends on your [member EditorSettings.interface/inspector/default_float_step] setting.
				If hints [code]"or_greater"[/code] and [code]"or_less"[/code] are provided, the editor widget will not cap the value at range boundaries. The [code]"exp"[/code] hint will make the edited values on range to change exponentially. The [code]"hide_slider"[/code] hint will hide the slider element of the editor widget.
				Hints also allow to indicate the units for the edited value. Using [code]"radians_as_degrees"[/code] you can specify that the actual value is in radians, but should be displayed in degrees in the Inspector dock (the range values are also in degrees). [code]"degrees"[/code] allows to add a degree sign as a unit suffix (the value is unchanged). Finally, a custom suffix can be provided using [code]"suffix:unit"[/code], where "unit" can be any string.
				See also [constant PROPERTY_HINT_RANGE].
				[codeblock]
				@export_range(0, 20) var number
				@export_range(-10, 20) var number
				@export_range(-10, 20, 0.2) var number: float
				@export_range(0, 20) var numbers: Array[float]

				@export_range(0, 100, 1, "or_greater") var power_percent
				@export_range(0, 100, 1, "or_greater", "or_less") var health_delta

				@export_range(-180, 180, 0.001, "radians_as_degrees") var angle_radians
				@export_range(0, 360, 1, "degrees") var angle_degrees
				@export_range(-8, 8, 2, "suffix:px") var target_offset
				[/codeblock]
			</description>
		</annotation>
		<annotation name="@export_storage">
			<return type="void" />
			<description>
				Export a property with [constant PROPERTY_USAGE_STORAGE] flag. The property is not displayed in the editor, but it is serialized and stored in the scene or resource file. This can be useful for [annotation @tool] scripts. Also the property value is copied when [method Resource.duplicate] or [method Node.duplicate] is called, unlike non-exported variables.
				[codeblock]
				var a # Not stored in the file, not displayed in the editor.
				@export_storage var b # Stored in the file, not displayed in the editor.
				@export var c: int # Stored in the file, displayed in the editor.
				[/codeblock]
			</description>
		</annotation>
		<annotation name="@export_subgroup">
			<return type="void" />
			<param index="0" name="name" type="String" />
			<param index="1" name="prefix" type="String" default="""" />
			<description>
				Define a new subgroup for the following exported properties. This helps to organize properties in the Inspector dock. Subgroups work exactly like groups, except they need a parent group to exist. See [annotation @export_group].
				See also [constant PROPERTY_USAGE_SUBGROUP].
				[codeblock]
				@export_group("Racer Properties")
				@export var nickname = "Nick"
				@export var age = 26

				@export_subgroup("Car Properties", "car_")
				@export var car_label = "Speedy"
				@export var car_number = 3
				[/codeblock]
				[b]Note:[/b] Subgroups cannot be nested, they only provide one extra level of depth. Just like the next group ends the previous group, so do the subsequent subgroups.
			</description>
		</annotation>
		<a


nnotation name="@export_tool_button">
			<return type="void" />
			<param index="0" name="text" type="String" />
			<param index="1" name="icon" type="String" default="""" />
			<description>
				Export a [Callable] property as a clickable button with the label [param text]. When the button is pressed, the callable is called.
				If [param icon] is specified, it is used to fetch an icon for the button via [method Control.get_theme_icon], from the [code]"EditorIcons"[/code] theme type. If [param icon] is omitted, the default [code]"Callable"[/code] icon is used instead.
				Consider using the [EditorUndoRedoManager] to allow the action to be reverted safely.
				See also [constant PROPERTY_HINT_TOOL_BUTTON].
				[codeblock]
				@tool
				extends Sprite2D

				@export_tool_button("Hello") var hello_action = hello
				@export_tool_button("Randomize the color!", "ColorRect")
				var randomize_color_action = randomize_color

				func hello():
				    print("Hello world!")

				func randomize_color():
				    var undo_redo = EditorInterface.get_editor_undo_redo()
				    undo_redo.create_action("Randomized Sprite2D Color")
				    undo_redo.add_do_property(self, &"self_modulate", Color(randf(), randf(), randf()))
				    undo_redo.add_undo_property(self, &"self_modulate", self_modulate)
				    undo_redo.commit_action()
				[/codeblock]
				[b]Note:[/b] The property is exported without the [constant PROPERTY_USAGE_STORAGE] flag because a [Callable] cannot be properly serialized and stored in a file.
				[b]Note:[/b] In an exported project neither [EditorInterface] nor [EditorUndoRedoManager] exist, which may cause some scripts to break. To prevent this, you can use [method Engine.get_singleton] and omit the static type from the variable declaration:
				[codeblock]
				var undo_redo = Engine.get_singleton(&"EditorInterface").get_editor_undo_redo()
				[/codeblock]
				[b]Note:[/b] Avoid storing lambda callables in member variables of [RefCounted]-based classes (e.g. resources), as this can lead to memory leaks. Use only method callables and optionally [method Callable.bind] or [method Callable.unbind].
			</description>
		</annotation>
		<annotation name="@icon">
			<return type="void" />
			<param index="0" name="icon_path" type="String" />
			<description>
				Add a custom icon to the current script. The icon specified at [param icon_path] is displayed in the Scene dock for every node of that class, as well as in various editor dialogs.
				[codeblock]
				@icon("res://path/to/class/icon.svg")
				[/codeblock]
				[b]Note:[/b] Only the script can have a custom icon. Inner classes are not supported.
				[b]Note:[/b] As annotations describe their subject, the [annotation @icon] annotation must be placed before the class definition and inheritance.
				[b]Note:[/b] Unlike other annotations, the argument of the [annotation @icon] annotation must be a string literal (constant expressions are not supported).
			</description>
		</annotation>
		<annotation name="@onready">
			<return type="void" />
			<description>
				Mark the following property as assigned when the [Node] is ready. Values for these properties are not assigned immediately when the node is initialized ([method Object._init]), and instead are computed and stored right before [method Node._ready].
				[codeblock]
				@onready var character_name: Label = $Label
				[/codeblock]
			</description>
		</annotation>
		<annotation name="@rpc">
			<return type="void" />
			<param index="0" name="mode" type="String" default=""authority"" />
			<param index="1" name="sync" type="String" default=""call_remote"" />
			<param index="2" name="transfer_mode" type="String" default=""unreliable"" />
			<param index="3" name="transfer_channel" type="int" default="0" />
			<description>
				Mark the following method for remote procedure calls. See [url=$DOCS_URL/tutorials/networking/high_level_multiplayer.html]High-level multiplayer[/url].
				If [param mode] is set as [code]"any_peer"[/code], allows any peer to call this RPC function. Otherwise, only the authority peer is allowed to call it and [param mode] should be kept as [code]"authority"[/code]. When configuring functions as RPCs with [method Node.rpc_config], each of these modes respectively corresponds to the [constant MultiplayerAPI.RPC_MODE_AUTHORITY] and [constant MultiplayerAPI.RPC_MODE_ANY_PEER] RPC modes. See [enum MultiplayerAPI.RPCMode]. If a peer that is not the authority tries to call a function that is only allowed for the authority, the function will not be executed. If the error can be detected locally (when the RPC configuration is consistent between the local and the remote peer), an error message will be displayed on the sender peer. Otherwise, the remote peer will detect the error and print an error there.
				If [param sync] is set as [code]"call_remote"[/code], the function will only be executed on the remote peer, but not locally. To run this function locally too, set [param sync] to [code]"call_local"[/code]. When configuring functions as RPCs with [method Node.rpc_config], this is equivalent to setting [code]call_local[/code] to [code]true[/code].
				The [param transfer_mode] accepted values are [code]"unreliable"[/code], [code]"unreliable_ordered"[/code], or [code]"reliable"[/code]. It sets the transfer mode of the underlying [MultiplayerPeer]. See [member MultiplayerPeer.transfer_mode].
				The [param transfer_channel] defines the channel of the underlying [MultiplayerPeer]. See [member MultiplayerPeer.transfer_channel].
				The order of [param mode], [param sync] and [param transfer_mode] does not matter, but values related to the same argument must not be used more than once. [param transfer_channel] always has to be the 4th argument (you must specify 3 preceding arguments).
				[codeblock]
				@rpc
				func fn(): pass

				@rpc("any_peer", "unreliable_ordered")
				func fn_update_pos(): pass

				@rpc("authority", "call_remote", "unreliable", 0) # Equivalent to @rpc
				func fn_default(): pass
				[/codeblock]
			</description>
		</annotation>
		<annotation name="@static_unload">
			<return type="void" />
			<description>
				Make a script with static variables to not persist after all references are lost. If the script is loaded again the static variables will revert to their default values.
				[b]Note:[/b] As annotations describe their subject, the [annotation @static_unload] annotation must be placed before the class definition and inheritance.
				[b]Warning:[/b] Currently, due to a bug, scripts are never freed, even if [annotation @static_unload] annotation is used.
			</description>
		</annotation>
		<annotation name="@tool">
			<return type="void" />
			<description>
				Mark the current script as a tool script, allowing it to be loaded and executed by the editor. See [url=$DOCS_URL/tutorials/plugins/running_code_in_the_editor.html]Running code in the editor[/url].
				[codeblock]
				@tool
				extends Node
				[/codeblock]
				[b]Note:[/b] As annotations describe their subject, the [annotation @tool] annotation must be placed before the class definition and inheritance.
			</description>
		</annotation>
		<annotation name="@warning_ignore" qualifiers="vararg">
			<return type="void" />
			<param index="0" name="warning" type="String" />
			<description>
				Mark the following statement to ignore the specified [param warning]. See [url=$DOCS_URL/tutorials/scripting/gdscript/warning_system.html]GDScript warning system[/url].
				[codeblock]
				func test():
				    print("hello")
				    return
				    @warning_ignore("unreachable_code")
				    print("unreachable")
				[/codeblock]
			</description>
		</annotation>
	</annotations>
</class>


# meta-description: Classic movement for gravity games (FPS, TPS, ...)

extends _BASE_

const SPEED = 5.0
const JUMP_VELOCITY = 4.5

func _physics_process(delta: float) -> void:
	# Add the gravity.
	if not is_on_floor():
		velocity += get_gravity() * delta

	# Handle jump.
	if Input.is_action_just_pressed("ui_accept") and is_on_floor():
		velocity.y = JUMP_VELOCITY

	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	var input_dir := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
	var direction := (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
	if direction:
		velocity.x = direction.x * SPEED
		velocity.z = direction.z * SPEED
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)
		velocity.z = move_toward(velocity.z, 0, SPEED)

	move_and_slide()


# meta-description: Classic movement for gravity games (platformer, ...)

extends _BASE_

const SPEED = 300.0
const JUMP_VELOCITY = -400.0

func _physics_process(delta: float) -> void:
	# Add the gravity.
	if not is_on_floor():
		velocity += get_gravity() * delta

	# Handle jump.
	if Input.is_action_just_pressed("ui_accept") and is_on_floor():
		velocity.y = JUMP_VELOCITY

	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	var direction := Input.get_axis("ui_left", "ui_right")
	if direction:
		velocity.x = direction * SPEED
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)

	move_and_slide()


<?xml version="1.0" encoding="UTF-8" ?>
<class name="GLTFNode" inherits="Resource" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
	<brief_description>
		glTF node class.
	</brief_description>
	<description>
		Represents a glTF node. glTF nodes may have names, transforms, children (other glTF nodes), and more specialized properties (represented by their own classes).
		glTF nodes generally exist inside of [GLTFState] which represents all data of a glTF file. Most of GLTFNode's properties are indices of other data in the glTF file. You can extend a glTF node with additional properties by using [method get_additional_data] and [method set_additional_data].
	</description>
	<tutorials>
		<link title="Runtime file loading and saving">$DOCS_URL/tutorials/io/runtime_file_loading_and_saving.html</link>
		<link title="glTF scene and node spec">https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_004_ScenesNodes.md"</link>
	</tutorials>
	<methods>
		<method name="append_child_index">
			<return type="void" />
			<param index="0" name="child_index" type="int" />
			<description>
				Appends the given child node index to the [member children] array.
			</description>
		</method>
		<method name="get_additional_data">
			<return type="Variant" />
			<param index="0" name="extension_name" type="StringName" />
			<description>
				Gets additional arbitrary data in this [GLTFNode] instance. This can be used to keep per-node state data in [GLTFDocumentExtension] classes, which is important because they are stateless.
				The argument should be the [GLTFDocumentExtension] name (does not have to match the extension name in the glTF file), and the return value can be anything you set. If nothing was set, the return value is null.
			</description>
		</method>
		<method name="set_additional_data">
			<return type="void" />
			<param index="0" name="extension_name" type="StringName" />
			<param index="1" name="additional_data" type="Variant" />
			<description>
				Sets additional arbitrary data in this [GLTFNode] instance. This can be used to keep per-node state data in [GLTFDocumentExtension] classes, which is important because they are stateless.
				The first argument should be the [GLTFDocumentExtension] name (does not have to match the extension name in the glTF file), and the second argument can be anything you want.
			</description>
		</method>
	</methods>
	<members>
		<member name="camera" type="int" setter="set_camera" getter="get_camera" default="-1">
			If this glTF node is a camera, the index of the [GLTFCamera] in the [GLTFState] that describes the camera's properties. If -1, this node is not a camera.
		</member>
		<member name="children" type="PackedInt32Array" setter="set_children" getter="get_children" default="PackedInt32Array()">
			The indices of the child nodes in the [GLTFState]. If this glTF node has no children, this will be an empty array.
		</member>
		<member name="height" type="int" setter="set_height" getter="get_height" default="-1">
			How deep into the node hierarchy this node is. A root node will have a height of 0, its children will have a height of 1, and so on. If -1, the height has not been calculated.
		</member>
		<member name="light" type="int" setter="set_light" getter="get_light" default="-1">
			If this glTF node is a light, the index of the [GLTFLight] in the [GLTFState] that describes the light's properties. If -1, this node is not a light.
		</member>
		<member name="mesh" type="int" setter="set_mesh" getter="get_mesh" default="-1">
			If this glTF node is a mesh, the index of the [GLTFMesh] in the [GLTFState] that describes the mesh's properties. If -1, this node is not a mesh.
		</member>
		<member name="original_name" type="String" setter="set_original_name" getter="get_original_name" default="""">
			The original name of the node.
		</member>
		<member name="parent" type="int" setter="set_parent" getter="get_parent" default="-1">
			The index of the parent node in the [GLTFState]. If -1, this node is a root node.
		</member>
		<member name="position" type="Vector3" setter="set_position" getter="get_position" default="Vector3(0, 0, 0)">
			The position of the glTF node relative to its parent.
		</member>
		<member name="rotation" type="Quaternion" setter="set_rotation" getter="get_rotation" default="Quaternion(0, 0, 0, 1)">
			The rotation of the glTF node relative to its parent.
		</member>
		<member name="scale" type="Vector3" setter="set_scale" getter="get_scale" default="Vector3(1, 1, 1)">
			The scale of the glTF node relative to its parent.
		</member>
		<member name="skeleton" type="int" setter="set_skeleton" getter="get_skeleton" default="-1">
			If this glTF node has a skeleton, the index of the [GLTFSkeleton] in the [GLTFState] that describes the skeleton's properties. If -1, this node does not have a skeleton.
		</member>
		<member name="skin" type="int" setter="set_skin" getter="get_skin" default="-1">
			If this glTF node has a skin, the index of the [GLTFSkin] in the [GLTFState] that describes the skin's properties. If -1, this node does not have a skin.
		</member>
		<member name="xform" type="Transform3D" setter="set_xform" getter="get_xform" default="Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)">
			The transform of the glTF node relative to its parent. This property is usually unused since the position, rotation, and scale properties are preferred.
		</member>
	</members>
</class>


<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <ProjectGuid>{AEBF0036-DA76-4341-B651-A3F2856AB2FA}</ProjectGuid>
    <OutputPath>bin/$(Configuration)</OutputPath>
    <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
    <RootNamespace>Godot</RootNamespace>
    <TargetFramework>net6.0</TargetFramework>
    <DocumentationFile>$(OutputPath)/$(AssemblyName).xml</DocumentationFile>
    <EnableDefaultItems>false</EnableDefaultItems>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
    <LangVersion>10</LangVersion>

    <AnalysisMode>Recommended</AnalysisMode>
  </PropertyGroup>
  <PropertyGroup>
    <Description>Godot C# Core API.</Description>
    <Authors>Godot Engine contributors</Authors>

    <PackageId>GodotSharp</PackageId>
    <Version>4.4.0</Version>
    <PackageVersion>$(PackageVersion_GodotSharp)</PackageVersion>
    <RepositoryUrl>https://github.com/godotengine/godot/tree/master/modules/mono/glue/GodotSharp/GodotSharp</RepositoryUrl>
    <PackageProjectUrl>$(RepositoryUrl)</PackageProjectUrl>
    <PackageLicenseExpression>MIT</PackageLicenseExpression>
    <Copyright>Copyright (c) Godot Engine contributors</Copyright>

    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
    <IncludeSymbols>true</IncludeSymbols>
    <SymbolPackageFormat>snupkg</SymbolPackageFormat>
  </PropertyGroup>
  <ItemGroup>
    <!-- SdkPackageVersions.props for easy access -->
    <None Include="$(GodotSdkPackageVersionsFilePath)">
      <Link>SdkPackageVersions.props</Link>
    </None>
  </ItemGroup>
  <PropertyGroup>
    <DefineConstants>$(DefineConstants);GODOT</DefineConstants>
    <DefineConstants Condition=" '$(GodotFloat64)' == 'true' ">REAL_T_IS_DOUBLE;$(DefineConstants)</DefineConstants>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="ReflectionAnalyzers" Version="0.1.22-dev" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers" />
    <!--PackageReference Include="IDisposableAnalyzers" Version="3.4.13" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers" /-->
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\Godot.SourceGenerators.Internal\Godot.SourceGenerators.Internal.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  </ItemGroup>
  <!-- Sources -->
  <ItemGroup>
    <Compile Include="Core\Aabb.cs" />
    <Compile Include="Core\Bridge\GodotSerializationInfo.cs" />
    <Compile Include="Core\Bridge\MethodInfo.cs" />
    <Compile Include="Core\Callable.generics.cs" />
    <Compile Include="Core\CustomGCHandle.cs" />
    <Compile Include="Core\Array.cs" />
    <Compile Include="Core\Attributes\AssemblyHasScriptsAttribute.cs" />
    <Compile Include="Core\Attributes\ExportAttribute.cs" />
    <Compile Include="Core\Attributes\ExportCategoryAttribute.cs" />
    <Compile Include="Core\Attributes\ExportGroupAttribute.cs" />
    <Compile Include="Core\Attributes\ExportSubgroupAttribute.cs" />
    <Compile Include="Core\Attributes\GlobalClassAttribute.cs" />
    <Compile Include="Core\Attributes\GodotClassNameAttribute.cs" />
    <Compile Include="Core\Attributes\IconAttribute.cs" />
    <Compile Include="Core\Attributes\MustBeVariantAttribute.cs" />
    <Compile Include="Core\Attributes\RpcAttribute.cs" />
    <Compile Include="Core\Attributes\ScriptPathAttribute.cs" />
    <Compile Include="Core\Attributes\SignalAttribute.cs" />
    <Compile Include="Core\Attributes\ToolAttribute.cs" />
    <Compile Include="Core\Basis.cs" />
    <Compile Include="Core\Bridge\CSharpInstanceBridge.cs" />
    <Compile Include="Core\Bridge\GCHandleBridge.cs" />
    <Compile Include="Core\Bridge\AlcReloadCfg.cs" />
    <Compile Include="Core\Bridge\ManagedCallbacks.cs" />
    <Compile Include="Core\Bridge\PropertyInfo.cs" />
    <Compile Include="Core\Bridge\ScriptManagerBridge.cs" />
    <Compile Include="Core\Bridge\ScriptManagerBridge.types.cs" />
    <Compile Include="Core\Callable.cs" />
    <Compile Include="Core\Color.cs" />
    <Compile Include="Core\Colors.cs" />
    <Compile Include="Core\DebuggingUtils.cs" />
    <Compile Include="Core\DebugView.cs" />
    <Compile Include="Core\DelegateUtils.cs" />
    <Compile Include="Core\Dictionary.cs" />
    <Compile Include="Core\Dispatcher.cs" />
    <Compile Include="Core\Extensions\GodotObjectExtensions.cs" />
    <Compile Include="Core\Extensions\NodeExtensions.cs" />
    <Compile Include="Core\Extensions\PackedSceneExtensions.cs" />
    <Compile Include="Core\Extensions\ResourceLoaderExtensions.cs" />
    <Compile Include="Core\GD.cs" />
    <Compile Include="Core\GodotObject.base.cs" />
    <Compile Include="Core\GodotObject.exceptions.cs" />
    <Compile Include="Core\GodotSynchronizationContext.cs" />
    <Compile Include="Core\GodotTaskScheduler.cs" />
    <Compile Include="Core\GodotTraceListener.cs" />
    <Compile Include="Core\GodotUnhandledExceptionEvent.cs" />
    <Compile Include="Core\DisposablesTracker.cs" />
    <Compile Include="Core\Interfaces\IAwaitable.cs" />
    <Compile Include="Core\Interfaces\IAwaiter.cs" />
    <Compile Include="Core\Interfaces\ISerializationListener.cs" />
    <Compile Include="Core\Mathf.cs" />
    <Compile Include="Core\MathfEx.cs" />
    <Compile Include="Core\NativeInterop\CustomUnsafe.cs" />
    <Compile Include="Core\NativeInterop\ExceptionUtils.cs" />
    <Compile Include="Core\NativeInterop\GodotDllImportResolver.cs" />
    <Compile Include="Core\NativeInterop\InteropUtils.cs" />
    <Compile Include="Core\NativeInterop\NativeFuncs.extended.cs" />
    <Compile Include="Core\NativeInterop\NativeVariantPtrArgs.cs" />
    <Compile Include="Core\NativeInterop\VariantUtils.cs" />
    <Compile Include="Core\NativeInterop\VariantUtils.generic.cs" />
    <Compile Include="Core\NodePath.cs" />
    <Compile Include="Core\Plane.cs" />
    <Compile Include="Core\Projection.cs" />
    <Compile Include="Core\Quaternion.cs" />
    <Compile Include="Core\Rect2.cs" />
    <Compile Include="Core\Rect2I.cs" />
    <Compile Include="Core\ReflectionUtils.cs" />
    <Compile Include="Core\Rid.cs" />
    <Compile Include="Core\NativeInterop\NativeFuncs.cs" />
    <Compile Include="Core\NativeInterop\InteropStructs.cs" />
    <Compile Include="Core\NativeInterop\Marshaling.cs" />
    <Compile Include="Core\Signal.cs" />
    <Compile Include="Core\SignalAwaiter.cs" />
    <Compile Include="Core\StringExtensions.cs" />
    <Compile Include="Core\StringName.cs" />
    <Compile Include="Core\Transform2D.cs" />
    <Compile Include="Core\Transform3D.cs" />
    <Compile Include="Core\Variant.cs" />
    <Compile Include="Core\Vector2.cs" />
    <Compile Include="Core\Vector2I.cs" />
    <Compile Include="Core\Vector3.cs" />
    <Compile Include="Core\Vector3I.cs" />
    <Compile Include="Core\Vector4.cs" />
    <Compile Include="Core\Vector4I.cs" />
    <Compile Include="GlobalUsings.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <!-- Compat Sources -->
  <ItemGroup Condition=" '$(GodotNoDeprecated)' == '' ">
    <Compile Include="Compat.cs" />
  </ItemGroup>
  <!--
  We import a props file with auto-generated includes. This works well with Rider.
  However, Visual Studio and MonoDevelop won't list them in the solution explorer.
  We can't use wildcards as there may be undesired old files still hanging around.
  Fortunately code completion, go to definition and such still work.
  -->
  <Import Condition=" '$(GodotSkipGenerated)' == '' " Project="Generated\GeneratedIncludes.props" />
</Project>


/**************************************************************************/
/*  multiplayer_spawner.h                                                 */
/**************************************************************************/
/*                         This file is part of:                          */
/*                             GODOT ENGINE                               */
/*                        https://godotengine.org                         */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */
/*                                                                        */
/* Permission is hereby granted, free of charge, to any person obtaining  */
/* a copy of this software and associated documentation files (the        */
/* "Software"), to deal in the Software without restriction, including    */
/* without limitation the rights to use, copy, modify, merge, publish,    */
/* distribute, sublicense, and/or sell copies of the Software, and to     */
/* permit persons to whom the Software is furnished to do so, subject to  */
/* the following conditions:                                              */
/*                                                                        */
/* The above copyright notice and this permission notice shall be         */
/* included in all copies or substantial portions of the Software.        */
/*                                                                        */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */
/**************************************************************************/

#ifndef MULTIPLAYER_SPAWNER_H
#define MULTIPLAYER_SPAWNER_H

#include "scene_replication_config.h"

#include "core/templates/local_vector.h"
#include "core/variant/typed_array.h"
#include "scene/main/node.h"
#include "scene/resources/packed_scene.h"

class MultiplayerSpawner : public Node {
	GDCLASS(MultiplayerSpawner, Node);

public:
	enum {
		INVALID_ID = 0xFF,
	};

private:
	struct SpawnableScene {
		String path;
		Ref<PackedScene> cache;
	};

	LocalVector<SpawnableScene> spawnable_scenes;

	HashSet<ResourceUID::ID> spawnable_ids;
	NodePath spawn_path;

	struct SpawnInfo {
		Variant args;
		int id = INVALID_ID;
		SpawnInfo(Variant p_args, int p_id) {
			id = p_id;
			args = p_args;
		}
		SpawnInfo() {}
	};

	ObjectID spawn_node;
	HashMap<ObjectID, SpawnInfo> tracked_nodes;
	uint32_t spawn_limit = 0;
	Callable spawn_function;

	void _update_spawn_node();
	void _track(Node *p_node, const Variant &p_argument, int p_scene_id = INVALID_ID);
	void _node_added(Node *p_node);
	void _node_exit(ObjectID p_id);
	void _spawn_notify(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:
	PackedStringArray get_configuration_warnings() const override;

	Node *get_spawn_node() const {
		return spawn_node.is_valid() ? Object::cast_to<Node>(ObjectDB::get_instance(spawn_node)) : nullptr;
	}

	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; }
	void set_spawn_limit(uint32_t p_limit) { spawn_limit = p_limit; }
	void set_spawn_function(Callable p_spawn_function) { spawn_function = p_spawn_function; }
	Callable get_spawn_function() const { return spawn_function; }

	const Variant get_spawn_argument(const ObjectID &p_id) 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);

	MultiplayerSpawner() {}
};

#endif // MULTIPLAYER_SPAWNER_H


/**************************************************************************/
/*  scene_multiplayer.h                                                   */
/**************************************************************************/
/*                         This file is part of:                          */
/*                             GODOT ENGINE                               */
/*                        https://godotengine.org                         */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */
/*                                                                        */
/* Permission is hereby granted, free of charge, to any person obtaining  */
/* a copy of this software and associated documentation files (the        */
/* "Software"), to deal in the Software without restriction, including    */
/* without limitation the rights to use, copy, modify, merge, publish,    */
/* distribute, sublicense, and/or sell copies of the Software, and to     */
/* permit persons to whom the Software is furnished to do so, subject to  */
/* the following conditions:                                              */
/*                                                                        */
/* The above copyright notice and this permission notice shall be         */
/* included in all copies or substantial portions of the Software.        */
/*                                                                        */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */
/**************************************************************************/

#ifndef SCENE_MULTIPLAYER_H
#define SCENE_MULTIPLAYER_H

#include "scene_cache_interface.h"
#include "scene_replication_interface.h"
#include "scene_rpc_interface.h"

#include "scene/main/multiplayer_api.h"

class OfflineMultiplayerPeer : public MultiplayerPeer {
	GDCLASS(OfflineMultiplayerPeer, MultiplayerPeer);

public:
	virtual int get_available_packet_count() const override { return 0; }
	virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) override {
		*r_buffer = nullptr;
		r_buffer_size = 0;
		return OK;
	}
	virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size) override { return OK; }
	virtual int get_max_packet_size() const override { return 0; }

	virtual void set_target_peer(int p_peer_id) override {}
	virtual int get_packet_peer() const override { return 0; }
	virtual TransferMode get_packet_mode() const override { return TRANSFER_MODE_RELIABLE; };
	virtual int get_packet_channel() const override { return 0; }
	virtual void disconnect_peer(int p_peer, bool p_force = false) override {}
	virtual bool is_server() const override { return true; }
	virtual void poll() override {}
	virtual void close() override {}
	virtual int get_unique_id() const override { return TARGET_PEER_SERVER; }
	virtual ConnectionStatus get_connection_status() const override { return CONNECTION_CONNECTED; };
};

class SceneMultiplayer : public MultiplayerAPI {
	GDCLASS(SceneMultiplayer, MultiplayerAPI);

public:
	enum NetworkCommands {
		NETWORK_COMMAND_REMOTE_CALL = 0,
		NETWORK_COMMAND_SIMPLIFY_PATH,
		NETWORK_COMMAND_CONFIRM_PATH,
		NETWORK_COMMAND_RAW,
		NETWORK_COMMAND_SPAWN,
		NETWORK_COMMAND_DESPAWN,
		NETWORK_COMMAND_SYNC,
		NETWORK_COMMAND_SYS,
	};

	enum SysCommands {
		SYS_COMMAND_AUTH,
		SYS_COMMAND_ADD_PEER,
		SYS_COMMAND_DEL_PEER,
		SYS_COMMAND_RELAY,
	};

	enum {
		SYS_CMD_SIZE = 6, // Command + sys command + peer_id (+ optional payload).
	};

	// For each command, the 4 MSB can contain custom flags, as defined by subsystems.
	enum {
		CMD_FLAG_0_SHIFT = 4,
		CMD_FLAG_1_SHIFT = 5,
		CMD_FLAG_2_SHIFT = 6,
		CMD_FLAG_3_SHIFT = 7,
	};

	// This is the mask that will be used to extract the command.
	enum {
		CMD_MASK = 7, // 0x7 -> 0b00000111
	};

private:
	struct PendingPeer {
		bool local = false;
		bool remote = false;
		uint64_t time = 0;
	};

	Ref<MultiplayerPeer> multiplayer_peer;
	MultiplayerPeer::ConnectionStatus last_connection_status = MultiplayerPeer::CONNECTION_DISCONNECTED;
	HashMap<int, PendingPeer> pending_peers; // true if locally finalized.
	Callable auth_callback;
	uint64_t auth_timeout = 3000;
	HashSet<int> connected_peers;
	int remote_sender_id = 0;
	int remote_sender_override = 0;

	Vector<uint8_t> packet_cache;

	NodePath root_path;
	bool allow_object_decoding = false;
	bool server_relay = true;
	Ref<StreamPeerBuffer> relay_buffer;

	Ref<SceneCacheInterface> cache;
	Ref<SceneReplicationInterface> replicator;
	Ref<SceneRPCInterface> rpc;

#ifdef DEBUG_ENABLED
	_FORCE_INLINE_ void _profile_bandwidth(const String &p_what, int p_value);
	_FORCE_INLINE_ Error _send(const uint8_t *p_packet, int p_packet_len); // Also profiles.
#else
	_FORCE_INLINE_ Error _send(const uint8_t *p_packet, int p_packet_len) {
		return multiplayer_peer->put_packet(p_packet, p_packet_len);
	}
#endif

protected:
	static void _bind_methods();

	void _process_packet(int p_from, const uint8_t *p_packet, int p_packet_len);
	void _process_raw(int p_from, const uint8_t *p_packet, int p_packet_len);
	void _process_sys(int p_from, const uint8_t *p_packet, int p_packet_len, MultiplayerPeer::TransferMode p_mode, int p_channel);

	void _add_peer(int p_id);
	void _admit_peer(int p_id);
	void _del_peer(int p_id);
	void _update_status();

public:
	virtual void set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer) override;
	virtual Ref<MultiplayerPeer> get_multiplayer_peer() override;

	virtual Error poll() override;
	virtual int get_unique_id() override;
	virtual Vector<int> get_peer_ids() override;
	virtual int get_remote_sender_id() override { return remote_sender_override ? remote_sender_override : remote_sender_id; }

	virtual Error rpcp(Object *p_obj, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) override;

	virtual Error object_configuration_add(Object *p_obj, Variant p_config) override;
	virtual Error object_configuration_remove(Object *p_obj, Variant p_config) override;

	void clear();

	// Usually from object_configuration_add/remove
	void set_root_path(const NodePath &p_path);
	NodePath get_root_path() const;

	void disconnect_peer(int p_id);

	Error send_auth(int p_to, Vector<uint8_t> p_bytes);
	Error complete_auth(int p_peer);
	void set_auth_callback(Callable p_callback);
	Callable get_auth_callback() const;
	void set_auth_timeout(double p_timeout);
	double get_auth_timeout() const;
	Vector<int> get_authenticating_peer_ids();

	Error send_command(int p_to, const uint8_t *p_packet, int p_packet_len); // Used internally to relay packets when needed.
	Error send_bytes(Vector<uint8_t> p_data, int p_to = MultiplayerPeer::TARGET_PEER_BROADCAST, MultiplayerPeer::TransferMode p_mode = MultiplayerPeer::TRANSFER_MODE_RELIABLE, int p_channel = 0);
	String get_rpc_md5(const Object *p_obj);

	const HashSet<int> get_connected_peers() const { return connected_peers; }

	void set_remote_sender_override(int p_id) { remote_sender_override = p_id; }
	void set_refuse_new_connections(bool p_refuse);
	bool is_refusing_new_connections() const;

	void set_allow_object_decoding(bool p_enable);
	bool is_object_decoding_allowed() const;

	void set_server_relay_enabled(bool p_enabled);
	bool is_server_relay_enabled() const;

	void set_max_sync_packet_size(int p_size);
	int get_max_sync_packet_size() const;

	void set_max_delta_packet_size(int p_size);
	int get_max_delta_packet_size() const;

	SceneMultiplayer();
	~SceneMultiplayer();
};

#endif // SCENE_MULTIPLAYER_H


/**************************************************************************/
/*  multiplayer_synchronizer.h                                            */
/**************************************************************************/
/*                         This file is part of:                          */
/*                             GODOT ENGINE                               */
/*                        https://godotengine.org                         */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */
/*                                                                        */
/* Permission is hereby granted, free of charge, to any person obtaining  */
/* a copy of this software and associated documentation files (the        */
/* "Software"), to deal in the Software without restriction, including    */
/* without limitation the rights to use, copy, modify, merge, publish,    */
/* distribute, sublicense, and/or sell copies of the Software, and to     */
/* permit persons to whom the Software is furnished to do so, subject to  */
/* the following conditions:                                              */
/*                                                                        */
/* The above copyright notice and this permission notice shall be         */
/* included in all copies or substantial portions of the Software.        */
/*                                                                        */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */
/**************************************************************************/

#ifndef MULTIPLAYER_SYNCHRONIZER_H
#define MULTIPLAYER_SYNCHRONIZER_H

#include "scene_replication_config.h"

#include "scene/main/node.h"

class MultiplayerSynchronizer : public Node {
	GDCLASS(MultiplayerSynchronizer, Node);

public:
	enum VisibilityUpdateMode {
		VISIBILITY_PROCESS_IDLE,
		VISIBILITY_PROCESS_PHYSICS,
		VISIBILITY_PROCESS_NONE,
	};

private:
	struct Watcher {
		NodePath prop;
		uint64_t last_change_usec = 0;
		Variant value;
	};

	Ref<SceneReplicationConfig> replication_config;
	NodePath root_path = NodePath(".."); // Start with parent, like with AnimationPlayer.
	uint64_t sync_interval_usec = 0;
	uint64_t delta_interval_usec = 0;
	VisibilityUpdateMode visibility_update_mode = VISIBILITY_PROCESS_IDLE;
	HashSet<Callable> visibility_filters;
	HashSet<int> peer_visibility;
	Vector<Watcher> watchers;
	uint64_t last_watch_usec = 0;

	ObjectID root_node_cache;
	uint64_t last_sync_usec = 0;
	uint16_t last_inbound_sync = 0;
	uint32_t net_id = 0;
	bool sync_started = false;

	static Object *_get_prop_target(Object *p_obj, const NodePath &p_prop);
	void _start();
	void _stop();
	void _update_process();
	Error _watch_changes(uint64_t p_usec);

protected:
	static void _bind_methods();
	void _notification(int p_what);

public:
	static Error get_state(const List<NodePath> &p_properties, Object *p_obj, Vector<Variant> &r_variant, Vector<const Variant *> &r_variant_ptrs);
	static Error set_state(const List<NodePath> &p_properties, Object *p_obj, const Vector<Variant> &p_state);

	void reset();
	Node *get_root_node();

	uint32_t get_net_id() const;
	void set_net_id(uint32_t p_net_id);

	bool update_outbound_sync_time(uint64_t p_usec);
	bool update_inbound_sync_time(uint16_t p_network_time);

	PackedStringArray get_configuration_warnings() const override;

	void set_replication_interval(double p_interval);
	double get_replication_interval() const;

	void set_delta_interval(double p_interval);
	double get_delta_interval() const;

	void set_replication_config(Ref<SceneReplicationConfig> p_config);
	Ref<SceneReplicationConfig> get_replication_config();

	void set_root_path(const NodePath &p_path);
	NodePath get_root_path() const;
	virtual void set_multiplayer_authority(int p_peer_id, bool p_recursive = true) override;

	bool is_visibility_public() const;
	void set_visibility_public(bool p_public);
	bool is_visible_to(int p_peer);
	void set_visibility_for(int p_peer, bool p_visible);
	bool get_visibility_for(int p_peer) const;
	void update_visibility(int p_for_peer);
	void set_visibility_update_mode(VisibilityUpdateMode p_mode);
	void add_visibility_filter(Callable p_callback);
	void remove_visibility_filter(Callable p_callback);
	VisibilityUpdateMode get_visibility_update_mode() const;

	List<Variant> get_delta_state(uint64_t p_cur_usec, uint64_t p_last_usec, uint64_t &r_indexes);
	List<NodePath> get_delta_properties(uint64_t p_indexes);
	SceneReplicationConfig *get_replication_config_ptr() const;

	MultiplayerSynchronizer();
};

VARIANT_ENUM_CAST(MultiplayerSynchronizer::VisibilityUpdateMode);

#endif // MULTIPLAYER_SYNCHRONIZER_H


/**************************************************************************/
/*  scene_replication_interface.h                                         */
/**************************************************************************/
/*                         This file is part of:                          */
/*                             GODOT ENGINE                               */
/*                        https://godotengine.org                         */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */
/*                                                                        */
/* Permission is hereby granted, free of charge, to any person obtaining  */
/* a copy of this software and associated documentation files (the        */
/* "Software"), to deal in the Software without restriction, including    */
/* without limitation the rights to use, copy, modify, merge, publish,    */
/* distribute, sublicense, and/or sell copies of the Software, and to     */
/* permit persons to whom the Software is furnished to do so, subject to  */
/* the following conditions:                                              */
/*                                                                        */
/* The above copyright notice and this permission notice shall be         */
/* included in all copies or substantial portions of the Software.        */
/*                                                                        */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */
/**************************************************************************/

#ifndef SCENE_REPLICATION_INTERFACE_H
#define SCENE_REPLICATION_INTERFACE_H

#include "multiplayer_spawner.h"
#include "multiplayer_synchronizer.h"

#include "core/object/ref_counted.h"

class SceneMultiplayer;
class SceneCacheInterface;

class SceneReplicationInterface : public RefCounted {
	GDCLASS(SceneReplicationInterface, RefCounted);

private:
	struct TrackedNode {
		ObjectID id;
		uint32_t net_id = 0;
		uint32_t remote_peer = 0;
		ObjectID spawner;
		HashSet<ObjectID> synchronizers;

		bool operator==(const ObjectID &p_other) { return id == p_other; }

		TrackedNode() {}
		TrackedNode(const ObjectID &p_id) { id = p_id; }
		TrackedNode(const ObjectID &p_id, uint32_t p_net_id) {
			id = p_id;
			net_id = p_net_id;
		}
	};

	struct PeerInfo {
		HashSet<ObjectID> sync_nodes;
		HashSet<ObjectID> spawn_nodes;
		HashMap<ObjectID, uint64_t> last_watch_usecs;
		HashMap<uint32_t, ObjectID> recv_sync_ids;
		HashMap<uint32_t, ObjectID> recv_nodes;
		uint16_t last_sent_sync = 0;
	};

	// Replication state.
	HashMap<int, PeerInfo> peers_info;
	uint32_t last_net_id = 0;
	HashMap<ObjectID, TrackedNode> tracked_nodes;
	HashSet<ObjectID> spawned_nodes;
	HashSet<ObjectID> sync_nodes;

	// Pending local spawn information (handles spawning nested nodes during ready).
	HashSet<ObjectID> spawn_queue;

	// Pending remote spawn information.
	ObjectID pending_spawn;
	int pending_spawn_remote = 0;
	const uint8_t *pending_buffer = nullptr;
	int pending_buffer_size = 0;
	List<uint32_t> pending_sync_net_ids;

	// Replicator config.
	SceneMultiplayer *multiplayer = nullptr;
	SceneCacheInterface *multiplayer_cache = nullptr;
	PackedByteArray packet_cache;
	int sync_mtu = 1350; // Highly dependent on underlying protocol.
	int delta_mtu = 65535;

	TrackedNode &_track(const ObjectID &p_id);
	void _untrack(const ObjectID &p_id);
	void _node_ready(const ObjectID &p_oid);

	bool _has_authority(const Node *p_node);
	bool _verify_synchronizer(int p_peer, MultiplayerSynchronizer *p_sync, uint32_t &r_net_id);
	MultiplayerSynchronizer *_find_synchronizer(int p_peer, uint32_t p_net_ida);

	void _send_sync(int p_peer, const HashSet<ObjectID> &p_synchronizers, uint16_t p_sync_net_time, uint64_t p_usec);
	void _send_delta(int p_peer, const HashSet<ObjectID> &p_synchronizers, uint64_t p_usec, const HashMap<ObjectID, uint64_t> &p_last_watch_usecs);
	Error _make_spawn_packet(Node *p_node, MultiplayerSpawner *p_spawner, int &r_len);
	Error _make_despawn_packet(Node *p_node, int &r_len);
	Error _send_raw(const uint8_t *p_buffer, int p_size, int p_peer, bool p_reliable);

	void _visibility_changed(int p_peer, ObjectID p_oid);
	Error _update_sync_visibility(int p_peer, MultiplayerSynchronizer *p_sync);
	Error _update_spawn_visibility(int p_peer, const ObjectID &p_oid);
	void _free_remotes(const PeerInfo &p_info);

	template <typename T>
	static T *get_id_as(const ObjectID &p_id) {
		return p_id.is_valid() ? Object::cast_to<T>(ObjectDB::get_instance(p_id)) : nullptr;
	}

#ifdef DEBUG_ENABLED
	_FORCE_INLINE_ void _profile_node_data(const String &p_what, ObjectID p_id, int p_size);
#endif

public:
	static void make_default();

	void on_reset();
	void on_peer_change(int p_id, bool p_connected);

	Error on_spawn(Object *p_obj, Variant p_config);
	Error on_despawn(Object *p_obj, Variant p_config);
	Error on_replication_start(Object *p_obj, Variant p_config);
	Error on_replication_stop(Object *p_obj, Variant p_config);
	void on_network_process();

	Error on_spawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len);
	Error on_despawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len);
	Error on_sync_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len);
	Error on_delta_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len);

	bool is_rpc_visible(const ObjectID &p_oid, int p_peer) const;

	void set_max_sync_packet_size(int p_size);
	int get_max_sync_packet_size() const;

	void set_max_delta_packet_size(int p_size);
	int get_max_delta_packet_size() const;

	SceneReplicationInterface(SceneMultiplayer *p_multiplayer, SceneCacheInterface *p_cache) {
		multiplayer = p_multiplayer;
		multiplayer_cache = p_cache;
	}
};

#endif // SCENE_REPLICATION_INTERFACE_H


<?xml version="1.0" encoding="UTF-8" ?>
<class name="MultiplayerSynchronizer" inherits="Node" keywords="network" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
	<brief_description>
		Synchronizes properties from the multiplayer authority to the remote peers.
	</brief_description>
	<description>
		By default, [MultiplayerSynchronizer] synchronizes configured properties to all peers.
		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>
	<methods>
		<method name="add_visibility_filter">
			<return type="void" />
			<param index="0" name="filter" type="Callable" />
			<description>
				Adds a peer visibility filter for this synchronizer.
				[param filter] should take a peer ID [int] and return a [bool].
			</description>
		</method>
		<method name="get_visibility_for" qualifiers="const">
			<return type="bool" />
			<param index="0" name="peer" type="int" />
			<description>
				Queries the current visibility for peer [param peer].
			</description>
		</method>
		<method name="remove_visibility_filter">
			<return type="void" />
			<param index="0" name="filter" type="Callable" />
			<description>
				Removes a peer visibility filter from this synchronizer.
			</description>
		</method>
		<method name="set_visibility_for">
			<return type="void" />
			<param index="0" name="peer" type="int" />
			<param index="1" name="visible" type="bool" />
			<description>
				Sets the visibility of [param peer] to [param visible]. If [param peer] is [code]0[/code], the value of [member public_visibility] will be updated instead.
			</description>
		</method>
		<method name="update_visibility">
			<return type="void" />
			<param index="0" name="for_peer" type="int" default="0" />
			<description>
				Updates the visibility of [param for_peer] according to visibility filters. If [param for_peer] is [code]0[/code] (the default), all peers' visibilties are updated.
			</description>
		</method>
	</methods>
	<members>
		<member name="delta_interval" type="float" setter="set_delta_interval" getter="get_delta_interval" default="0.0">
			Time interval between delta synchronizations. When set to [code]0.0[/code] (the default), delta synchronizations happen every network process frame.
		</member>
		<member name="public_visibility" type="bool" setter="set_visibility_public" getter="is_visibility_public" default="true">
			Whether synchronization should be visible to all peers by default. See [method set_visibility_for] and [method add_visibility_filter] for ways of configuring fine-grained visibility options.
		</member>
		<member name="replication_config" type="SceneReplicationConfig" setter="set_replication_config" getter="get_replication_config">
			Resource containing which properties to synchronize.
		</member>
		<member name="replication_interval" type="float" setter="set_replication_interval" getter="get_replication_interval" default="0.0">
			Time interval between synchronizations. When set to [code]0.0[/code] (the default), synchronizations happen every network process frame.
		</member>
		<member name="root_path" type="NodePath" setter="set_root_path" getter="get_root_path" default="NodePath("..")">
			Node path that replicated properties are relative to.
			If [member root_path] was spawned by a [MultiplayerSpawner], the node will be also be spawned and despawned based on this synchronizer visibility options.
		</member>
		<member name="visibility_update_mode" type="int" setter="set_visibility_update_mode" getter="get_visibility_update_mode" enum="MultiplayerSynchronizer.VisibilityUpdateMode" default="0">
			Specifies when visibility filters are updated (see [enum VisibilityUpdateMode] for options).
		</member>
	</members>
	<signals>
		<signal name="delta_synchronized">
			<description>
				Emitted when a new delta synchronization state is received by this synchronizer after the properties have been updated.
			</description>
		</signal>
		<signal name="synchronized">
			<description>
				Emitted when a new synchronization state is received by this synchronizer after the properties have been updated.
			</description>
		</signal>
		<signal name="visibility_changed">
			<param index="0" name="for_peer" type="int" />
			<description>
				Emitted when visibility of [param for_peer] is updated. See [method update_visibility].
			</description>
		</signal>
	</signals>
	<constants>
		<constant name="VISIBILITY_PROCESS_IDLE" value="0" enum="VisibilityUpdateMode">
			Visibility filters are updated during process frames (see [constant Node.NOTIFICATION_INTERNAL_PROCESS]).
		</constant>
		<constant name="VISIBILITY_PROCESS_PHYSICS" value="1" enum="VisibilityUpdateMode">
			Visibility filters are updated during physics frames (see [constant Node.NOTIFICATION_INTERNAL_PHYSICS_PROCESS]).
		</constant>
		<constant name="VISIBILITY_PROCESS_NONE" value="2" enum="VisibilityUpdateMode">
			Visibility filters are not updated automatically, and must be updated manually by calling [method update_visibility].
		</constant>
	</constants>
</class>


<?xml version="1.0" encoding="UTF-8" ?>
<class name="MultiplayerSpawner" inherits="Node" keywords="network" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
	<brief_description>
		Automatically replicates spawnable nodes from the authority to other multiplayer peers.
	</brief_description>
	<description>
		Spawnable scenes can be configured in the editor or through code (see [method add_spawnable_scene]).
		Also supports custom node spawns through [method spawn], calling [member spawn_function] on all peers.
		Internally, [MultiplayerSpawner] uses [method MultiplayerAPI.object_configuration_add] to notify spawns passing the spawned node as the [code]object[/code] and itself as the [code]configuration[/code], and [method MultiplayerAPI.object_configuration_remove] to notify despawns in a similar way.
	</description>
	<tutorials>
	</tutorials>
	<methods>
		<method name="add_spawnable_scene">
			<return type="void" />
			<param index="0" name="path" type="String" />
			<description>
				Adds a scene path to spawnable scenes, making it automatically replicated from the multiplayer authority to other peers when added as children of the node pointed by [member spawn_path].
			</description>
		</method>
		<method name="clear_spawnable_scenes">
			<return type="void" />
			<description>
				Clears all spawnable scenes. Does not despawn existing instances on remote peers.
			</description>
		</method>
		<method name="get_spawnable_scene" qualifiers="const">
			<return type="String" />
			<param index="0" name="index" type="int" />
			<description>
				Returns the spawnable scene path by index.
			</description>
		</method>
		<method name="get_spawnable_scene_count" qualifiers="const">
			<return type="int" />
			<description>
				Returns the count of spawnable scene paths.
			</description>
		</method>
		<method name="spawn">
			<return type="Node" />
			<param index="0" name="data" type="Variant" default="null" />
			<description>
				Requests a custom spawn, with [param data] passed to [member spawn_function] on all peers. Returns the locally spawned node instance already inside the scene tree, and added as a child of the node pointed by [member spawn_path].
				[b]Note:[/b] Spawnable scenes are spawned automatically. [method spawn] is only needed for custom spawns.
			</description>
		</method>
	</methods>
	<members>
		<member name="spawn_function" type="Callable" setter="set_spawn_function" getter="get_spawn_function">
			Method called on all peers when a custom [method spawn] is requested by the authority. Will receive the [code]data[/code] parameter, and should return a [Node] that is not in the scene tree.
			[b]Note:[/b] The returned node should [b]not[/b] be added to the scene with [method Node.add_child]. This is done automatically.
		</member>
		<member name="spawn_limit" type="int" setter="set_spawn_limit" getter="get_spawn_limit" default="0">
			Maximum number of nodes allowed to be spawned by this spawner. Includes both spawnable scenes and custom spawns.
			When set to [code]0[/code] (the default), there is no limit.
		</member>
		<member name="spawn_path" type="NodePath" setter="set_spawn_path" getter="get_spawn_path" default="NodePath("")">
			Path to the spawn root. Spawnable scenes that are added as direct children are replicated to other peers.
		</member>
	</members>
	<signals>
		<signal name="despawned">
			<param index="0" name="node" type="Node" />
			<description>
				Emitted when a spawnable scene or custom spawn was despawned by the multiplayer authority. Only called on remote peers.
			</description>
		</signal>
		<signal name="spawned">
			<param index="0" name="node" type="Node" />
			<description>
				Emitted when a spawnable scene or custom spawn was spawned by the multiplayer authority. Only called on remote peers.
			</description>
		</signal>
	</signals>
</class>


<?xml version="1.0" encoding="UTF-8" ?>
<class name="SceneMultiplayer" inherits="MultiplayerAPI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
	<brief_description>
		High-level multiplayer API implementation.
	</brief_description>
	<description>
		This class is the default implementation of [MultiplayerAPI], used to provide multiplayer functionalities in Godot Engine.
		This implementation supports RPCs via [method Node.rpc] and [method Node.rpc_id] and requires [method MultiplayerAPI.rpc] to be passed a [Node] (it will fail for other object types).
		This implementation additionally provide [SceneTree] replication via the [MultiplayerSpawner] and [MultiplayerSynchronizer] nodes, and the [SceneReplicationConfig] resource.
		[b]Note:[/b] The high-level multiplayer API protocol is an implementation detail and isn't meant to be used by non-Godot servers. It may change without notice.
		[b]Note:[/b] When exporting to Android, make sure to enable the [code]INTERNET[/code] permission in the Android export preset before exporting the project or using one-click deploy. Otherwise, network communication of any kind will be blocked by Android.
	</description>
	<tutorials>
	</tutorials>
	<methods>
		<method name="clear">
			<return type="void" />
			<description>
				Clears the current SceneMultiplayer network state (you shouldn't call this unless you know what you are doing).
			</description>
		</method>
		<method name="complete_auth">
			<return type="int" enum="Error" />
			<param index="0" name="id" type="int" />
			<description>
				Mark the authentication step as completed for the remote peer identified by [param id]. The [signal MultiplayerAPI.peer_connected] signal will be emitted for this peer once the remote side also completes the authentication. No further authentication messages are expected to be received from this peer.
				If a peer disconnects before completing authentication, either due to a network issue, the [member auth_timeout] expiring, or manually calling [method disconnect_peer], the [signal peer_authentication_failed] signal will be emitted instead of [signal MultiplayerAPI.peer_disconnected].
			</description>
		</method>
		<method name="disconnect_peer">
			<return type="void" />
			<param index="0" name="id" type="int" />
			<description>
				Disconnects the peer identified by [param id], removing it from the list of connected peers, and closing the underlying connection with it.
			</description>
		</method>
		<method name="get_authenticating_peers">
			<return type="PackedInt32Array" />
			<description>
				Returns the IDs of the peers currently trying to authenticate with this [MultiplayerAPI].
			</description>
		</method>
		<method name="send_auth">
			<return type="int" enum="Error" />
			<param index="0" name="id" type="int" />
			<param index="1" name="data" type="PackedByteArray" />
			<description>
				Sends the specified [param data] to the remote peer identified by [param id] as part of an authentication message. This can be used to authenticate peers, and control when [signal MultiplayerAPI.peer_connected] is emitted (and the remote peer accepted as one of the connected peers).
			</description>
		</method>
		<method name="send_bytes">
			<return type="int" enum="Error" />
			<param index="0" name="bytes" type="PackedByteArray" />
			<param index="1" name="id" type="int" default="0" />
			<param index="2" name="mode" type="int" enum="MultiplayerPeer.TransferMode" default="2" />
			<param index="3" name="channel" type="int" default="0" />
			<description>
				Sends the given raw [param bytes] to a specific peer identified by [param id] (see [method MultiplayerPeer.set_target_peer]). Default ID is [code]0[/code], i.e. broadcast to all peers.
			</description>
		</method>
	</methods>
	<members>
		<member name="allow_object_decoding" type="bool" setter="set_allow_object_decoding" getter="is_object_decoding_allowed" default="false">
			If [code]true[/code], the MultiplayerAPI will allow encoding and decoding of object during RPCs.
			[b]Warning:[/b] Deserialized objects can contain code which gets executed. Do not use this option if the serialized object comes from untrusted sources to avoid potential security threat such as remote code execution.
		</member>
		<member name="auth_callback" type="Callable" setter="set_auth_callback" getter="get_auth_callback" default="Callable()">
			The callback to execute when receiving authentication data sent via [method send_auth]. If the [Callable] is empty (default), peers will be automatically accepted as soon as they connect.
		</member>
		<member name="auth_timeout" type="float" setter="set_auth_timeout" getter="get_auth_timeout" default="3.0">
			If set to a value greater than [code]0.0[/code], the maximum duration in seconds peers can stay in the authenticating state, after which the authentication will automatically fail. See the [signal peer_authenticating] and [signal peer_authentication_failed] signals.
		</member>
		<member name="max_delta_packet_size" type="int" setter="set_max_delta_packet_size" getter="get_max_delta_packet_size" default="65535">
			Maximum size of each delta packet. Higher values increase the chance of receiving full updates in a single frame, but also the chance of causing networking congestion (higher latency, disconnections). See [MultiplayerSynchronizer].
		</member>
		<member name="max_sync_packet_size" type="int" setter="set_max_sync_packet_size" getter="get_max_sync_packet_size" default="1350">
			Maximum size of each synchronization packet. Higher values increase the chance of receiving full updates in a single frame, but also the chance of packet loss. See [MultiplayerSynchronizer].
		</member>
		<member name="refuse_new_connections" type="bool" setter="set_refuse_new_connections" getter="is_refusing_new_connections" default="false">
			If [code]true[/code], the MultiplayerAPI's [member MultiplayerAPI.multiplayer_peer] refuses new incoming connections.
		</member>
		<member name="root_path" type="NodePath" setter="set_root_path" getter="get_root_path" default="NodePath("")">
			The root path to use for RPCs and replication. Instead of an absolute path, a relative path will be used to find the node upon which the RPC should be executed.
			This effectively allows to have different branches of the scene tree to be managed by different MultiplayerAPI, allowing for example to run both client and server in the same scene.
		</member>
		<member name="server_relay" type="bool" setter="set_server_relay_enabled" getter="is_server_relay_enabled" default="true">
			Enable or disable the server feature that notifies clients of other peers' connection/disconnection, and relays messages between them. When this option is [code]false[/code], clients won't be automatically notified of other peers and won't be able to send them packets through the server.
			[b]Note:[/b] Changing this option while other peers are connected may lead to unexpected behaviors.
			[b]Note:[/b] Support for this feature may depend on the current [MultiplayerPeer] configuration. See [method MultiplayerPeer.is_server_relay_supported].
		</member>
	</members>


void canvas_item_set_clip(RID p_item, bool p_clip);
	void canvas_item_set_distance_field_mode(RID p_item, bool p_enable);
	void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect, const Rect2 &p_rect = Rect2());
	void canvas_item_set_modulate(RID p_item, const Color &p_color);
	void canvas_item_set_self_modulate(RID p_item, const Color &p_color);

	void canvas_item_set_draw_behind_parent(RID p_item, bool p_enable);

	void canvas_item_set_update_when_visible(RID p_item, bool p_update);

	void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = -1.0, bool p_antialiased = false);
	void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0, bool p_antialiased = false);
	void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0, bool p_antialiased = false);
	void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color, bool p_antialiased);
	void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color, bool p_antialiased);
	void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false);
	void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false);
	void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0, float p_scale = 1.0);
	void canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1));
	void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, RS::NinePatchAxisMode p_x_axis_mode = RS::NINE_PATCH_STRETCH, RS::NinePatchAxisMode p_y_axis_mode = RS::NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1));
	void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture);
	void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID());
	void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1);
	void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID());
	void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID());
	void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture);
	void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform);
	void canvas_item_add_clip_ignore(RID p_item, bool p_ignore);
	void canvas_item_add_animation_slice(RID p_item, double p_animation_length, double p_slice_begin, double p_slice_end, double p_offset);

	void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable);
	void canvas_item_set_z_index(RID p_item, int p_z);
	void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable);
	void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2 &p_rect);
	void canvas_item_attach_skeleton(RID p_item, RID p_skeleton);

	void canvas_item_clear(RID p_item);
	void canvas_item_set_draw_index(RID p_item, int p_index);

	void canvas_item_set_material(RID p_item, RID p_material);

	void canvas_item_set_use_parent_material(RID p_item, bool p_enable);

	void canvas_item_set_visibility_notifier(RID p_item, bool p_enable, const Rect2 &p_area, const Callable &p_enter_callable, const Callable &p_exit_callable);

	void canvas_item_set_canvas_group_mode(RID p_item, RS::CanvasGroupMode p_mode, float p_clear_margin = 5.0, bool p_fit_empty = false, float p_fit_margin = 0.0, bool p_blur_mipmaps = false);

	void canvas_item_set_debug_redraw(bool p_enabled);


inline static void XrQuaternionf_Multiply(XrQuaternionf* result, const XrQuaternionf* a, const XrQuaternionf* b) {
    result->x = (b->w * a->x) + (b->x * a->w) + (b->y * a->z) - (b->z * a->y);
    result->y = (b->w * a->y) - (b->x * a->z) + (b->y * a->w) + (b->z * a->x);
    result->z = (b->w * a->z) + (b->x * a->y) - (b->y * a->x) + (b->z * a->w);
    result->w = (b->w * a->w) - (b->x * a->x) - (b->y * a->y) - (b->z * a->z);
}

inline static void XrQuaternionf_Invert(XrQuaternionf* result, const XrQuaternionf* q) {
    result->x = -q->x;
    result->y = -q->y;
    result->z = -q->z;
    result->w = q->w;
}

inline static void XrQuaternionf_Normalize(XrQuaternionf* q) {
    const float lengthRcp = XrRcpSqrt(q->x * q->x + q->y * q->y + q->z * q->z + q->w * q->w);
    q->x *= lengthRcp;
    q->y *= lengthRcp;
    q->z *= lengthRcp;
    q->w *= lengthRcp;
}

inline static void XrQuaternionf_RotateVector3f(XrVector3f* result, const XrQuaternionf* a, const XrVector3f* v) {
    XrQuaternionf q = {v->x, v->y, v->z, 0.0f};
    XrQuaternionf aq;
    XrQuaternionf_Multiply(&aq, &q, a);
    XrQuaternionf aInv;
    XrQuaternionf_Invert(&aInv, a);
    XrQuaternionf aqaInv;
    XrQuaternionf_Multiply(&aqaInv, &aInv, &aq);

    result->x = aqaInv.x;
    result->y = aqaInv.y;
    result->z = aqaInv.z;
}

inline static void XrPosef_CreateIdentity(XrPosef* result) {
    XrQuaternionf_CreateIdentity(&result->orientation);
    XrVector3f_Set(&result->position, 0);
}

inline static void XrPosef_TransformVector3f(XrVector3f* result, const XrPosef* a, const XrVector3f* v) {
    XrVector3f r0;
    XrQuaternionf_RotateVector3f(&r0, &a->orientation, v);
    XrVector3f_Add(result, &r0, &a->position);
}

inline static void XrPosef_Multiply(XrPosef* result, const XrPosef* a, const XrPosef* b) {
    XrQuaternionf_Multiply(&result->orientation, &b->orientation, &a->orientation);
    XrPosef_TransformVector3f(&result->position, a, &b->position);
}

inline static void XrPosef_Invert(XrPosef* result, const XrPosef* a) {
    XrQuaternionf_Invert(&result->orientation, &a->orientation);
    XrVector3f aPosNeg;
    XrVector3f_Scale(&aPosNeg, &a->position, -1.0f);
    XrQuaternionf_RotateVector3f(&result->position, &result->orientation, &aPosNeg);
}

// Use left-multiplication to accumulate transformations.
inline static void XrMatrix4x4f_Multiply(XrMatrix4x4f* result, const XrMatrix4x4f* a, const XrMatrix4x4f* b) {
    result->m[0] = a->m[0] * b->m[0] + a->m[4] * b->m[1] + a->m[8] * b->m[2] + a->m[12] * b->m[3];
    result->m[1] = a->m[1] * b->m[0] + a->m[5] * b->m[1] + a->m[9] * b->m[2] + a->m[13] * b->m[3];
    result->m[2] = a->m[2] * b->m[0] + a->m[6] * b->m[1] + a->m[10] * b->m[2] + a->m[14] * b->m[3];
    result->m[3] = a->m[3] * b->m[0] + a->m[7] * b->m[1] + a->m[11] * b->m[2] + a->m[15] * b->m[3];

    result->m[4] = a->m[0] * b->m[4] + a->m[4] * b->m[5] + a->m[8] * b->m[6] + a->m[12] * b->m[7];
    result->m[5] = a->m[1] * b->m[4] + a->m[5] * b->m[5] + a->m[9] * b->m[6] + a->m[13] * b->m[7];
    result->m[6] = a->m[2] * b->m[4] + a->m[6] * b->m[5] + a->m[10] * b->m[6] + a->m[14] * b->m[7];
    result->m[7] = a->m[3] * b->m[4] + a->m[7] * b->m[5] + a->m[11] * b->m[6] + a->m[15] * b->m[7];

    result->m[8] = a->m[0] * b->m[8] + a->m[4] * b->m[9] + a->m[8] * b->m[10] + a->m[12] * b->m[11];
    result->m[9] = a->m[1] * b->m[8] + a->m[5] * b->m[9] + a->m[9] * b->m[10] + a->m[13] * b->m[11];
    result->m[10] = a->m[2] * b->m[8] + a->m[6] * b->m[9] + a->m[10] * b->m[10] + a->m[14] * b->m[11];
    result->m[11] = a->m[3] * b->m[8] + a->m[7] * b->m[9] + a->m[11] * b->m[10] + a->m[15] * b->m[11];

    result->m[12] = a->m[0] * b->m[12] + a->m[4] * b->m[13] + a->m[8] * b->m[14] + a->m[12] * b->m[15];
    result->m[13] = a->m[1] * b->m[12] + a->m[5] * b->m[13] + a->m[9] * b->m[14] + a->m[13] * b->m[15];
    result->m[14] = a->m[2] * b->m[12] + a->m[6] * b->m[13] + a->m[10] * b->m[14] + a->m[14] * b->m[15];
    result->m[15] = a->m[3] * b->m[12] + a->m[7] * b->m[13] + a->m[11] * b->m[14] + a->m[15] * b->m[15];
}

// Creates the transpose of the given matrix.