how do i go about implementing multiplayer syncing for my mage system

Godot Version

4.4.1.stable

Question

How can I synchronize the position of each boulder across all players in a multiplayer environment, while allowing each player to summon and propel boulders that persist in the world and remain synced in real-time?

extends Node

# Resources
var boulder = preload("res://scenes/human/moulder class/boulder.tscn")

@onready var ray := $"../Head/Camera3D/interactRay"
@onready var cam := $"../Head/Camera3D"
@onready var hand := $"../Head/Camera3D/hand"
@onready var line := MeshInstance3D.new()

@export var pull := {
	"max_distance": 3.0,
	"max_force": 10.0,
	"min_size": 0.3,
	"max_size": 1.0
}
@export var hit := {
	"force": 15.0,
	"cooldown": 0.5
}
@export var shake := {
	"intensity": 0.2,
	"decay": 5.0,
	"max_offset": Vector3(0.3, 0.3, 0.0)
}

var pulling := false
var origin := Vector3.ZERO
var strength := 0.0
var trauma := 0.0
var can_hit := true
var noise := FastNoiseLite.new()

func _ready():
	noise.seed = randi()

func _physics_process(delta):
	handle_pull(delta)
	handle_hit()
	update_shake(delta)

func handle_pull(delta):
	if ray.is_colliding() and not pulling and Input.is_action_just_pressed("l_click"):
		start_pull(ray.get_collision_point())
	
	if pulling:
		strength = update_strength()
		
		if Input.is_action_just_released("l_click"):
			launch_boulder()

func handle_hit():
	if Input.is_action_just_pressed("r_click") and can_hit and ray.is_colliding():
		var body = ray.get_collider()
		if body.is_in_group("earth_body"):
			hit_body(body)
			can_hit = false
			await get_tree().create_timer(hit.cooldown).timeout
			can_hit = true

func start_pull(pos: Vector3):
	pulling = true
	origin = pos

func update_strength() -> float:
	var dist = hand.global_position.distance_to(origin)
	return clamp(dist / pull.max_distance, 0.0, 1.0)

func launch_boulder():
	var dir = (hand.global_position - origin).normalized()
	var force = strength * pull.max_force
	var size = lerp(pull.min_size, pull.max_size, strength)
	
	var b = boulder.instantiate()
	b.position = origin
	b.scale = Vector3.ONE * size
	get_tree().current_scene.add_child(b)
	
	await get_tree().physics_frame
	b.apply_central_impulse(dir * force)
	add_trauma(strength * shake.intensity * 2)
	
	pulling = false
	line.mesh = null

func hit_body(body: RigidBody3D):
	var dir = (body.global_position - cam.global_position).normalized()
	body.apply_central_impulse(dir * hit.force)
	add_trauma(0.4)

func add_trauma(amount: float):
	trauma = min(trauma + amount, 1.0)

func update_shake(delta):
	if trauma > 0:
		trauma = max(0, trauma - shake.decay * delta)
		var intensity = trauma * trauma
		cam.position = Vector3(
			shake.max_offset.x * intensity * noise.get_noise_1d(Time.get_ticks_msec() * 0.01),
			shake.max_offset.y * intensity * noise.get_noise_1d(Time.get_ticks_msec() * 0.01 + 100),
			0
		)
	elif cam.position != Vector3.ZERO:
		cam.position = cam.position.lerp(Vector3.ZERO, min(10 * delta, 1.0))

For multiplayer in godot you will need to designate an authority of the boulder. The default is the host and this is what i recommend, as handling one truth, while maintaining fairness, is easier when you have a central authority vs. a multiple truth peer-to-peer network model.

I also recommend the multiplayer nodes MultiplayerSpawner and MultiplayerSynchronizer. The spawner will replicate the boulder instantiation on all peers, while the synchronizer will sync the position, and other data, to the rest of the peers.

This is not a simple task and requires more setup beyond this script to get started.

I recommend some tutorials if you haven’t got the MultiplayerPeers setup to connect host and client.