# This file is part of sunder. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . class_name InputSynchronizer extends MultiplayerSynchronizer # synchronized properties @export var jetting:bool = false @export var skiing:bool = false @export var direction:Vector3 @export var rotation:Vector3 signal jump signal primary(pressed:bool) signal secondary(pressed:bool) signal throw(pressed:bool) signal cycle(shift:int) signal select(index:int) var history := Queue.new() @export var id := 0 # no registered inputs yet func sample() -> Dictionary: return { "id": id, "direction": direction, "rotation": rotation, "jetting": jetting, "skiing": skiing, } func _physics_process(delta: float) -> void: if is_multiplayer_authority(): id += 1 func _unhandled_input(event:InputEvent) -> void: if is_multiplayer_authority() and owner.is_alive(): var vec := Input.get_vector("left", "right", "forward", "backward") direction = Vector3(vec.x, .0, vec.y) jetting = Input.is_action_pressed("secondary") skiing = Input.is_action_pressed("ski") # handle mouse rotation if event is InputEventMouseMotion: if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED: # check to apply reverse y axis setting if Settings.get_value("controls", "inverted_y_axis", false): event.relative.y *= -1.0 # update rotation with new relative mouse position since last frame var mouse_sensitivity:float = Settings.get_value("controls", "mouse_sensitivity", .6) # clamp vertical rotation (head motion) rotation.x -= event.relative.y * mouse_sensitivity / 100 rotation.x = clamp(rotation.x, deg_to_rad(-90.0), deg_to_rad(90.0)) # wrap horizontal rotation (to prevent accumulation) rotation.y -= event.relative.x * mouse_sensitivity / 100 rotation.y = wrapf(rotation.y, deg_to_rad(0.0), deg_to_rad(360.0)) return if event.is_action("primary"): _primary.rpc(event.pressed) elif event.is_action_pressed("secondary"): _jump.rpc() elif event.is_action("throw") and not event.is_echo(): _throw.rpc(event.pressed) elif event.is_action_pressed("wheel_up"): _cycle.rpc(1) elif event.is_action_pressed("wheel_down"): _cycle.rpc(-1) elif event.is_action_pressed("inventory_slot_0"): _select.rpc(0) elif event.is_action_pressed("inventory_slot_1"): _select.rpc(1) elif event.is_action_pressed("inventory_slot_2"): _select.rpc(2) @rpc("authority", "call_local", "reliable") func _jump() -> void: jump.emit() @rpc("authority", "call_local", "reliable") func _throw(pressed:bool) -> void: throw.emit(pressed) @rpc("authority", "call_local", "reliable") func _primary(pressed: bool) -> void: primary.emit(pressed) @rpc("authority", "call_local", "reliable") func _cycle(shift:int) -> void: cycle.emit(shift) @rpc("authority", "call_local", "reliable") func _select(index:int) -> void: select.emit(index)