Ship mostly works #10

Merged
chrisbell merged 60 commits from feature/ship-syncing into develop 2024-12-29 04:35:51 +00:00
Showing only changes of commit b50bdb52ec - Show all commits

View File

@ -8,11 +8,11 @@ var delta_time: float = 0.0
var ship_helm_scene: PackedScene = load("res://assets/core/interactables/ship-helm/ship-helm.tscn")
var ship_helm: ShipHelm
var ship_helm: ShipHelm = null
var piloting_player: Player = null
var ship_id: int = 0
#var ship_id: int = random_int() # Generate a random ship ID
var ship_is_piloted: bool = false
var current_level
var current_level: Node = null
var network_uuid: String = ""
var old_global_rotation_cache: Vector3
@ -32,36 +32,31 @@ var sync_interval: float = 0.1 # Sync every 0.1 seconds
var predicted_position: Vector3
var predicted_rotation: Quaternion
func _ready():
# Register the ship with the NetworkManager for P2P communication
network_uuid = NetworkManager.register_node(self)
NetworkManager.property_update_received.connect(_on_property_update)
# Connect to NetworkManager signals
NetworkManager.on_property_update.connect(_on_property_update)
# Connect signals
# Connect signals for player interaction
player_detection_area.body_entered.connect(_on_area_3d_body_entered)
player_detection_area.body_exited.connect(_on_area_3d_body_exited)
_add_ship_helm(ship_helm_scene) # TEMPORARY TEST
ship_id = randi_range(1000, 9999) # Assign a random ID to the ship
GameConsole.log_debug("Ship ID: " + str(ship_id))
# Spawn the ship helm visually (optional based on your design)
_add_ship_helm(ship_helm_scene)
# Initialize predicted values
predicted_position = global_position
predicted_rotation = Quaternion.from_euler(global_rotation)
predicted_rotation = Quaternion.from_euler(global_rotation).normalized()
func _process(delta: float) -> void:
delta_time = delta
func _physics_process(_delta) -> void:
func _physics_process(_delta):
# Predict movement only for non-authority clients
if not piloting_player or piloting_player.is_network_authority:
_predict_movement(_delta)
else:
# Apply predicted values until server correction arrives
# Apply predicted values until peer correction arrives
global_position = predicted_position
global_rotation = predicted_rotation.get_euler()
@ -73,9 +68,9 @@ func _physics_process(_delta) -> void:
global_rotation.x = lerpf(global_rotation.x, 0, 0.1)
global_rotation.z = lerpf(global_rotation.z, 0, 0.1)
# Send network updates periodically
_send_ship_sync()
func _predict_movement(_delta):
# Simple linear prediction
var predicted_velocity = linear_velocity
@ -87,9 +82,8 @@ func _predict_movement(_delta):
var predicted_rotation_delta = Quaternion(predicted_angular_velocity, _delta)
predicted_rotation = predicted_rotation * predicted_rotation_delta
func _apply_local_input(_delta):
if piloting_player == null or not piloting_player.is_network_authority:
if piloting_player == null or not piloting_player.is_network_authority or not piloting_player.is_piloting:
return
var turn_speed = base_turn_speed / max(mass, 1)
@ -112,39 +106,38 @@ func _apply_local_input(_delta):
target_velocity = -transform.basis.z * top_speed
elif Input.is_action_pressed("move_backwards"):
target_velocity = transform.basis.z * top_speed
var current_acceleration = (target_velocity - linear_velocity) * acceleration
apply_central_force(current_acceleration * mass)
# Clamp velocity to prevent excessive speed
if linear_velocity.length() > top_speed:
linear_velocity = linear_velocity.normalized() * top_speed
# Clamp angular velocity to prevent excessive turning
angular_velocity.y = clamp(angular_velocity.y, -max_turn_speed, max_turn_speed)
func _on_area_3d_body_entered(body: Node3D) -> void:
if body is Player and body.get_parent() != self:
body.ship_entered(self)
piloting_player = body
body.call_deferred("reparent", self, true) # Reparents player onto self (RigidBody3D)
print("ENTERED")
_sync_piloting_state() # Update piloting state on the network
body.call_deferred("reparent", self, true) # Reparents player onto the ship
ship_is_piloted = true
_sync_piloting_state() # Update piloting state for other clients
func _on_area_3d_body_exited(body: Node3D) -> void:
if body is Player and body.get_parent() != get_node("/root/DevLevel/"):
body.ship_exited()
ship_is_piloted = false
piloting_player = null
body.call_deferred("reparent", get_node("/root/DevLevel/"), true) # Reparents player back onto world node
print("EXITED")
_sync_piloting_state() # Update piloting state on the network
body.call_deferred("reparent", get_node("/root/DevLevel/"), true) # Reparents player back to the world
_sync_piloting_state() # Update piloting state for other clients
func _add_ship_helm(_ship_helm_scene: PackedScene):
var ship_helm_instance = _ship_helm_scene.instantiate()
helm_location_marker.add_child(ship_helm_instance)
ship_helm_instance = helm_location_marker.get_node("ShipHelm")
ship_helm = helm_location_marker.get_node("ShipHelm") # Assuming "ShipHelm" is the node name
func _on_property_update(uuid: String, property_name: String, value: Variant):
if NetworkManager.node_map.has(uuid):
var node = NetworkManager.node_map[uuid]
@ -154,21 +147,21 @@ func _on_property_update(uuid: String, property_name: String, value: Variant):
elif property_name == "global_rotation":
_handle_ship_sync_rotation(value)
elif property_name == "ship_is_piloted":
node.ship_is_piloted = value
ship_is_piloted = value
elif property_name == "piloting_player":
# Handle piloting player updates (e.g., update references)
if value != "":
# Find the player by network UUID
var player_node = NetworkManager.node_map[value]
node.piloting_player = player_node
# Find the Player object based on the network_uuid
for child in get_parent().get_children():
if child is Player and child.network_uuid == value:
piloting_player = child
break
else:
node.piloting_player = null
piloting_player = null
else:
node.set(property_name, value)
else:
printerr("Received property update but node_id is wrong? Expected " + str(uuid) + " but got " + str(uuid))
func _sync_piloting_state():
NetworkManager.sync_property(network_uuid, "ship_is_piloted", ship_is_piloted)
if piloting_player != null:
@ -176,13 +169,14 @@ func _sync_piloting_state():
else:
NetworkManager.sync_property(network_uuid, "piloting_player", "")
func _send_ship_sync():
if Time.get_ticks_msec() - last_sync_time > sync_interval * 1000:
last_sync_time = Time.get_ticks_msec()
NetworkManager.sync_property(network_uuid, "global_position", global_position)
NetworkManager.sync_property(network_uuid, "global_rotation", global_rotation)
NetworkManager.sync_property(network_uuid, "linear_velocity", linear_velocity)
NetworkManager.sync_property(network_uuid, "angular_velocity", angular_velocity)
func _handle_ship_sync_position(pos: Vector3):
if piloting_player and not piloting_player.is_network_authority:
# Correct prediction with server data only if the difference is significant
@ -190,7 +184,6 @@ func _handle_ship_sync_position(pos: Vector3):
predicted_position = pos
linear_velocity = (pos - global_position) / delta_time
func _handle_ship_sync_rotation(rot: Vector3):
if piloting_player and not piloting_player.is_network_authority:
# Correct prediction with server data only if the difference is significant
@ -199,6 +192,6 @@ func _handle_ship_sync_rotation(rot: Vector3):
if delta_rot.length() > 0.1:
predicted_rotation = received_rotation
angular_velocity = delta_rot.get_euler() / delta_time
# Apply server rotation directly
global_rotation = Quaternion.from_euler(rot).get_euler()
global_rotation = Quaternion.from_euler(rot).get_euler()