You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

87 lines
2.6 KiB
GDScript

extends CharacterBody3D
# We don't actually want to fully interpolate between states
# since it may result in "jumpy" transitions
const STATE_INTERP_MIN = 0.2
const STATE_INTERP_MAX = 0.8
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
var sync_state := PackedByteArray(): get = _get_sync_state, set = _set_sync_state
@export var speed := 5.0
@export var jump_speed := 5.0
@onready var gametag := $Gametag
@onready var target_origin := global_transform.origin
var last_snapshot_tag := 0
var snapshot_interp_start := 0.0
var snapshot_interp_end := 0.0
func _process(_delta):
gametag.text = "[%s %d]" % [name, get_multiplayer_authority()]
func _physics_process(delta):
if is_multiplayer_authority():
velocity.y += -gravity * delta
var input := Input.get_vector("left", "right", "forward", "backward")
var direction := transform.basis * Vector3(input.x, 0, input.y)
velocity.x = direction.x * speed
velocity.z = direction.z * speed
move_and_slide()
if is_on_floor() and Input.is_action_just_pressed("jump"):
velocity.y = jump_speed
else:
var interp_value = remap_range(
Time.get_ticks_msec(),
snapshot_interp_start,
snapshot_interp_end,
STATE_INTERP_MIN,
STATE_INTERP_MAX
)
if interp_value >= 0.0 and interp_value <= 1.0:
global_transform.origin = global_transform.origin.slerp(
target_origin, interp_value
)
else:
global_transform.origin = target_origin
func _enter_tree():
if name == str(multiplayer.get_unique_id()):
set_multiplayer_authority(multiplayer.get_unique_id())
func _get_sync_state():
var encoder := PackedByteArray()
encoder.resize(20)
encoder.encode_u64(0, Time.get_ticks_msec())
encoder.encode_float(8, transform.origin.x)
encoder.encode_float(12, transform.origin.y)
encoder.encode_float(16, transform.origin.z)
return encoder
func _set_sync_state(value):
assert(
typeof(value) == TYPE_PACKED_BYTE_ARRAY and value.size() == 20,
"Invalid `sync_state` array type or size (must be TYPE_RAW_ARRAY of size 20)"
)
var time_tag: int = value.decode_u64(0)
if time_tag > last_snapshot_tag:
var snapshot_time_diff = time_tag - last_snapshot_tag
if global_transform:
global_transform.origin = target_origin # Override last origin
snapshot_interp_start = Time.get_ticks_msec()
snapshot_interp_end = Time.get_ticks_msec() + snapshot_time_diff
last_snapshot_tag = time_tag
target_origin = Vector3(
value.decode_float(8),
value.decode_float(12),
value.decode_float(16),
)
func remap_range(value, in_a, in_b, out_a, out_b):
return (value - in_a) / (in_b - in_a) * (out_b - out_a) + out_a