Skip to main content

Basic Concepts - Authority and RPC

By default, everything in RadGame has the Server as authority. The only (so far) Exception is the player_input script that is part of each player character - the client that's controlling the character has the multiplayer authority over his input script.

Movement

The player movement is handled in player.gd, which should have the server as authority. Here's how:

func _physics_process(delta) -> void:
    # movement
    if not is_dead:
        handle_movement(delta)
func handle_movement(delta: float) -> void:
    # jumping
    if input.jumping and is_on_floor():
        velocity.y = jump_velocity
    if not is_on_floor():
        velocity.y -= gravity * delta
    input.jumping = false
    var direction = (transform.basis * Vector3(input.direction.x, 0, input.direction.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()

In handle_movement, the direction gets read from the player_input.gd script, over which the player has authority. the player_input node in the player scene is actually a multiplayer synchronizer, and syncs the "direction" variable to the server, so movement can then happen on the server. here's how the input script does it:

func _process(_delta):
	movement_direction()
func movement_direction():
	# unrotated direction from input
	var direction_ur = Input.get_vector("move_left","move_right","move_forward","move_back")
	# set strafing
	var strafing_left = false
	var strafing_right = false
	if direction_ur.x < 0:
		strafing_left = true
	if direction_ur.x > 0:
		strafing_right = true
	rpc_id(1,"set_strafing",strafing_left,strafing_right)
	# set backpedaling
	var backwards = false
	if direction_ur.y > 0:
		backwards = true
	rpc_id(1,"set_backpedaling",backwards)
	# rotate input according to camera orientation
	direction = Vector2(cos(-$"../camera_rotation".rotation.y)*direction_ur.x -\
						sin(-$"../camera_rotation".rotation.y)*direction_ur.y, \
						sin(-$"../camera_rotation".rotation.y)*direction_ur.x +\
						cos(-$"../camera_rotation".rotation.y)*direction_ur.y)
	if Input.is_action_just_pressed("jump"):
		jump.rpc()

So the direction comes straight from the input and gets synced via the synchronizer, while states such as strafing and backpedaling use RPCs to sync animations.

Spells

while there is targeting and interaction functionality in player_input.gd, we don't care about these right now. let's find where spells happen: