Ship mostly works #10

Merged
chrisbell merged 60 commits from feature/ship-syncing into develop 2024-12-29 04:35:51 +00:00
14 changed files with 370 additions and 131 deletions

View File

@ -3,25 +3,26 @@
importer="texture" importer="texture"
type="CompressedTexture2D" type="CompressedTexture2D"
uid="uid://fwub8fvl2u4i" uid="uid://fwub8fvl2u4i"
path="res://.godot/imported/ps1hagrid.png-c23425fa4ddfd6de7aebcbcf4a03083a.ctex" path.s3tc="res://.godot/imported/ps1hagrid.png-c23425fa4ddfd6de7aebcbcf4a03083a.s3tc.ctex"
metadata={ metadata={
"vram_texture": false "imported_formats": ["s3tc_bptc"],
"vram_texture": true
} }
[deps] [deps]
source_file="res://addons/ingameconsole/ps1hagrid.png" source_file="res://addons/ingameconsole/ps1hagrid.png"
dest_files=["res://.godot/imported/ps1hagrid.png-c23425fa4ddfd6de7aebcbcf4a03083a.ctex"] dest_files=["res://.godot/imported/ps1hagrid.png-c23425fa4ddfd6de7aebcbcf4a03083a.s3tc.ctex"]
[params] [params]
compress/mode=0 compress/mode=2
compress/high_quality=false compress/high_quality=false
compress/lossy_quality=0.7 compress/lossy_quality=0.7
compress/hdr_compression=1 compress/hdr_compression=1
compress/normal_map=0 compress/normal_map=0
compress/channel_pack=0 compress/channel_pack=0
mipmaps/generate=false mipmaps/generate=true
mipmaps/limit=-1 mipmaps/limit=-1
roughness/mode=0 roughness/mode=0
roughness/src_normal="" roughness/src_normal=""
@ -31,4 +32,4 @@ process/normal_map_invert_y=false
process/hdr_as_srgb=false process/hdr_as_srgb=false
process/hdr_clamp_exposure=false process/hdr_clamp_exposure=false
process/size_limit=0 process/size_limit=0
detect_3d/compress_to=1 detect_3d/compress_to=0

View File

@ -1,19 +1,15 @@
class_name ShipHelm class_name ShipHelm
extends Interactable extends Interactable
var parent_ship: Ship @export var parent_ship: Ship
func _ready():
parent_ship = get_parent() #sets the parent ship to the ship that the helm is placed on
func interact(): func interact():
if !parent_ship.ship_is_piloted: if player_reference.is_network_authority:
player_reference.set_is_piloting(true) if !parent_ship.ship_is_piloted:
parent_ship.ship_is_piloted = true player_reference.set_is_piloting(true)
parent_ship.set_piloting_player(player_reference)
elif parent_ship.ship_is_piloted:
player_reference.set_is_piloting(false)
parent_ship.remove_piloting_player()
elif parent_ship.ship_is_piloted:
player_reference.set_is_piloting(false)
parent_ship.ship_is_piloted = false

View File

@ -17,6 +17,7 @@ var steam_id: int = 0
var steam_username: String = "" var steam_username: String = ""
var avatar_texture_cache: Dictionary = {} var avatar_texture_cache: Dictionary = {}
var is_host: bool = false var is_host: bool = false
var host_id: int
var uuid_counter: int = 0 var uuid_counter: int = 0
@ -203,6 +204,7 @@ func host_lobby():
if lobby_id == 0: if lobby_id == 0:
Steam.createLobby(lobby_type, lobby_members_max) Steam.createLobby(lobby_type, lobby_members_max)
is_host = true is_host = true
host_id = steam_id
else: else:
printerr("Cannot host lobby, already in a lobby") printerr("Cannot host lobby, already in a lobby")
@ -211,12 +213,14 @@ func join_lobby(this_lobby_id: int):
print("Attempting to join lobby: " + str(this_lobby_id)) print("Attempting to join lobby: " + str(this_lobby_id))
lobby_members.clear() lobby_members.clear()
Steam.joinLobby(this_lobby_id) Steam.joinLobby(this_lobby_id)
host_id = Steam.getLobbyOwner(this_lobby_id)
func leave_lobby(): func leave_lobby():
if lobby_id != 0: if lobby_id != 0:
Steam.leaveLobby(lobby_id) Steam.leaveLobby(lobby_id)
lobby_id = 0 lobby_id = 0
host_id = 0
for this_member in lobby_members: for this_member in lobby_members:
if this_member["steam_id"] != steam_id: if this_member["steam_id"] != steam_id:
@ -270,8 +274,14 @@ func send_p2p_packet(target: int, packet_data: Dictionary) -> void:
if this_member['steam_id'] != steam_id: if this_member['steam_id'] != steam_id:
Steam.sendP2PPacket(this_member['steam_id'], this_data, send_type, channel) Steam.sendP2PPacket(this_member['steam_id'], this_data, send_type, channel)
#print("Sent packet to %s." % this_member['steam_name']) #print("Sent packet to %s." % this_member['steam_name'])
# If sending a packet to everyone except the host
# Else send it to someone specific elif target == 1:
if lobby_members.size() > 1:
# Loop through all members that aren't the host
for this_member in lobby_members:
if this_member['steam_id'] != host_id:
Steam.sendP2PPacket(this_member['steam_id'], this_data, send_type, channel)
# Else send it to someone specific
else: else:
Steam.sendP2PPacket(target, this_data, send_type, channel) Steam.sendP2PPacket(target, this_data, send_type, channel)
@ -318,7 +328,6 @@ func read_p2p_packet() -> void:
if "message" in readable_data and readable_data["message"] == "property_update": if "message" in readable_data and readable_data["message"] == "property_update":
if "node_id" in readable_data and "property_name" in readable_data and "value" in readable_data: if "node_id" in readable_data and "property_name" in readable_data and "value" in readable_data:
emit_signal("property_update_received", readable_data["node_id"], readable_data["property_name"], readable_data["value"]) emit_signal("property_update_received", readable_data["node_id"], readable_data["property_name"], readable_data["value"])
#print("Received property update packet for node %d: %s = %s" % [readable_data["node_id"], readable_data["property_name"], readable_data["value"]])
func register_node(node: Node) -> String: func register_node(node: Node) -> String:
@ -379,6 +388,7 @@ func _on_game_started():
var player: Player = player_scene.instantiate() var player: Player = player_scene.instantiate()
player.name = "Player_" + str(member["steam_id"]) player.name = "Player_" + str(member["steam_id"])
player.username = Steam.getFriendPersonaName(member["steam_id"]) player.username = Steam.getFriendPersonaName(member["steam_id"])
player.steam_id = member["steam_id"]
if member["steam_id"] == steam_id: if member["steam_id"] == steam_id:
player.is_network_authority = true player.is_network_authority = true
@ -388,8 +398,21 @@ func _on_game_started():
level.add_child(player) level.add_child(player)
func sync_property(node_id: String, property_name: String, value: Variant): func sync_property_to_host(node_id: String, property_name: String, value: Variant):
var packet_data = {"message":"property_update", "node_id": node_id, "property_name": property_name, "value": value}
send_p2p_packet(host_id, packet_data)
func sync_property_to_peer(node_id: String, property_name: String, value: Variant, target_peer: int):
var packet_data = {"message":"property_update", "node_id": node_id, "property_name": property_name, "value": value}
send_p2p_packet(target_peer, packet_data)
func sync_property_to_all(node_id: String, property_name: String, value: Variant):
var packet_data = {"message":"property_update", "node_id": node_id, "property_name":property_name, "value":value} var packet_data = {"message":"property_update", "node_id": node_id, "property_name":property_name, "value":value}
send_p2p_packet(0, packet_data) send_p2p_packet(0, packet_data)
func sync_property_to_all_except_host(node_id: String, property_name: String, value: Variant):
var packet_data = {"message":"property_update", "node_id": node_id, "property_name":property_name, "value":value}
send_p2p_packet(1, packet_data)

View File

@ -1,6 +1,7 @@
[gd_scene load_steps=11 format=3 uid="uid://c6w0ivy4hetrl"] [gd_scene load_steps=12 format=3 uid="uid://c6w0ivy4hetrl"]
[ext_resource type="Script" path="res://assets/core/player-controller/scripts/player.gd" id="1_bv7t4"] [ext_resource type="Script" path="res://assets/core/player-controller/scripts/player.gd" id="1_bv7t4"]
[ext_resource type="Texture2D" uid="uid://fwub8fvl2u4i" path="res://addons/ingameconsole/ps1hagrid.png" id="2_omgn1"]
[ext_resource type="Script" path="res://assets/core/player-controller/scripts/player_interacter.gd" id="2_wvu3d"] [ext_resource type="Script" path="res://assets/core/player-controller/scripts/player_interacter.gd" id="2_wvu3d"]
[ext_resource type="Script" path="res://assets/core/player-controller/scripts/player_hud.gd" id="3_02ne1"] [ext_resource type="Script" path="res://assets/core/player-controller/scripts/player_hud.gd" id="3_02ne1"]
[ext_resource type="Shader" path="res://assets/core/player-controller/scenes/inverted_crosshair.gdshader" id="3_rakxt"] [ext_resource type="Shader" path="res://assets/core/player-controller/scenes/inverted_crosshair.gdshader" id="3_rakxt"]
@ -8,13 +9,14 @@
[sub_resource type="CapsuleMesh" id="CapsuleMesh_v7b3h"] [sub_resource type="CapsuleMesh" id="CapsuleMesh_v7b3h"]
radius = 0.35 radius = 0.35
height = 1.5
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_qlkab"] [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_qlkab"]
radius = 0.35 radius = 0.35
[sub_resource type="CameraAttributesPractical" id="CameraAttributesPractical_fqbrh"] [sub_resource type="SphereMesh" id="SphereMesh_vu2l8"]
auto_exposure_enabled = true radius = 0.35
auto_exposure_max_sensitivity = 700.0 height = 0.7
[sub_resource type="ShaderMaterial" id="ShaderMaterial_wmxrr"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_wmxrr"]
shader = ExtResource("3_rakxt") shader = ExtResource("3_rakxt")
@ -22,10 +24,15 @@ shader = ExtResource("3_rakxt")
[sub_resource type="ShaderMaterial" id="ShaderMaterial_0n7pd"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_0n7pd"]
shader = ExtResource("3_rakxt") shader = ExtResource("3_rakxt")
[node name="Player" type="CharacterBody3D" node_paths=PackedStringArray("camera")] [node name="Player" type="CharacterBody3D" node_paths=PackedStringArray("camera", "neck", "player_avatar_face", "body", "head", "player_hud")]
collision_mask = 242 collision_mask = 242
script = ExtResource("1_bv7t4") script = ExtResource("1_bv7t4")
camera = NodePath("Neck/Camera3D") camera = NodePath("Neck/Camera3D")
neck = NodePath("Neck")
player_avatar_face = NodePath("Neck/Camera3D/PlayerAvatarFace")
body = NodePath("Body")
head = NodePath("Neck/Head")
player_hud = NodePath("PlayerHUD")
[node name="PlayerTag" type="Label3D" parent="."] [node name="PlayerTag" type="Label3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.26654, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.26654, 0)
@ -34,7 +41,8 @@ visibility_range_end = 15.0
billboard = 1 billboard = 1
text = "username" text = "username"
[node name="MeshInstance3D" type="MeshInstance3D" parent="."] [node name="Body" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.5, 0)
mesh = SubResource("CapsuleMesh_v7b3h") mesh = SubResource("CapsuleMesh_v7b3h")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."] [node name="CollisionShape3D" type="CollisionShape3D" parent="."]
@ -44,7 +52,6 @@ shape = SubResource("CapsuleShape3D_qlkab")
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.65, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.65, 0)
[node name="Camera3D" type="Camera3D" parent="Neck"] [node name="Camera3D" type="Camera3D" parent="Neck"]
attributes = SubResource("CameraAttributesPractical_fqbrh")
[node name="RayCast3D" type="RayCast3D" parent="Neck/Camera3D" node_paths=PackedStringArray("player")] [node name="RayCast3D" type="RayCast3D" parent="Neck/Camera3D" node_paths=PackedStringArray("player")]
target_position = Vector3(0, 0, -2.5) target_position = Vector3(0, 0, -2.5)
@ -52,6 +59,16 @@ collision_mask = 256
script = ExtResource("2_wvu3d") script = ExtResource("2_wvu3d")
player = NodePath("../../..") player = NodePath("../../..")
[node name="PlayerAvatarFace" type="Sprite3D" parent="Neck/Camera3D"]
transform = Transform3D(-0.1, 0, -8.74228e-09, 0, 0.1, 0, 8.74228e-09, 0, -0.1, 0, 0, -0.349588)
flip_h = true
shaded = true
double_sided = false
texture = ExtResource("2_omgn1")
[node name="Head" type="MeshInstance3D" parent="Neck"]
mesh = SubResource("SphereMesh_vu2l8")
[node name="PlayerHUD" type="CanvasLayer" parent="." node_paths=PackedStringArray("fps_label")] [node name="PlayerHUD" type="CanvasLayer" parent="." node_paths=PackedStringArray("fps_label")]
script = ExtResource("3_02ne1") script = ExtResource("3_02ne1")
fps_label = NodePath("Debug/HBoxContainer/VBoxContainer/MarginContainer/FPSLabel") fps_label = NodePath("Debug/HBoxContainer/VBoxContainer/MarginContainer/FPSLabel")

View File

@ -16,6 +16,12 @@ var steam_id: int = 0
@export_range(0.1, 3.0, 0.1, "or_greater") var camera_sens: float = 1.0 @export_range(0.1, 3.0, 0.1, "or_greater") var camera_sens: float = 1.0
@export_range(0.1, 3.0, 0.1, "or_greater") var joystick_camera_sens_multiplier: float = 5.0 @export_range(0.1, 3.0, 0.1, "or_greater") var joystick_camera_sens_multiplier: float = 5.0
@export var camera: Camera3D @export var camera: Camera3D
@export var neck: Node3D
@export var player_avatar_face: Sprite3D
@export var body: MeshInstance3D
@export var head: MeshInstance3D
@export var player_hud: CanvasLayer
var jumping: bool = false var jumping: bool = false
var is_using_joystick: bool = false var is_using_joystick: bool = false
@ -31,6 +37,9 @@ var current_ship: Ship
var previous_global_position: Vector3 var previous_global_position: Vector3
var previous_global_rotation: Vector3 var previous_global_rotation: Vector3
var previous_head_vert_rotation: Vector3
var neck_rotation_sync: Vector3
func _ready() -> void: func _ready() -> void:
@ -39,22 +48,16 @@ func _ready() -> void:
player_tag = get_node("PlayerTag") player_tag = get_node("PlayerTag")
player_tag.text = username player_tag.text = username
player_avatar_face.texture = await NetworkManager.get_player_avatar(steam_id)
if is_network_authority: if is_network_authority:
camera.make_current() camera.make_current()
body.hide()
head.hide()
func _unhandled_input(event: InputEvent) -> void: player_avatar_face.hide()
if !is_network_authority: return Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED: else:
if event is InputEventMouseMotion: player_hud.hide()
is_using_joystick = false
look_dir = event.relative * 0.001
_rotate_camera()
elif event is InputEventJoypadMotion:
is_using_joystick = true
if Input.is_action_just_pressed("jump") and !is_piloting:
jumping = true
func _input(event): func _input(event):
@ -64,11 +67,21 @@ func _input(event):
elif event.is_action_pressed("esc") and not Input.mouse_mode == Input.MOUSE_MODE_CAPTURED: elif event.is_action_pressed("esc") and not Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
capture_mouse() capture_mouse()
if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
if event is InputEventMouseMotion:
is_using_joystick = false
look_dir = event.relative * 0.001
_rotate_camera()
elif event is InputEventJoypadMotion:
is_using_joystick = true
if Input.is_action_just_pressed("jump") and !is_piloting:
jumping = true
func _physics_process(delta: float) -> void: func _physics_process(delta: float) -> void:
if !is_network_authority: return if !is_network_authority: return
if is_piloting and current_ship != null: if is_piloting and current_ship != null:
global_rotation.y = current_ship.global_rotation.y
velocity = Vector3.ZERO + _gravity(delta) velocity = Vector3.ZERO + _gravity(delta)
else: else:
velocity = walk(delta) + _gravity(delta) + _jump(delta) velocity = walk(delta) + _gravity(delta) + _jump(delta)
@ -86,12 +99,17 @@ func _process(delta: float) -> void:
# If the global_position has changed, notify the NetworkManager # If the global_position has changed, notify the NetworkManager
if previous_global_position != global_position: if previous_global_position != global_position:
NetworkManager.sync_property(network_uuid, "global_position", global_position) NetworkManager.sync_property_to_all(network_uuid, "global_position", global_position)
previous_global_position = global_position previous_global_position = global_position
if previous_global_rotation != global_rotation: if previous_global_rotation != global_rotation:
NetworkManager.sync_property(network_uuid, "global_rotation", global_rotation) NetworkManager.sync_property_to_all(network_uuid, "global_rotation", global_rotation)
previous_global_rotation = global_rotation previous_global_rotation = global_rotation
if previous_head_vert_rotation != neck.rotation:
NetworkManager.sync_property_to_all(network_uuid, "neck_rotation_sync", neck_rotation_sync)
previous_global_rotation = neck.rotation
func capture_mouse() -> void: func capture_mouse() -> void:
if !is_network_authority: return if !is_network_authority: return
@ -109,8 +127,9 @@ func _rotate_camera(sens_mod: float = 1.0) -> void:
if is_using_joystick: if is_using_joystick:
camera_sens_final = camera_sens * joystick_camera_sens_multiplier camera_sens_final = camera_sens * joystick_camera_sens_multiplier
camera.rotation.y -= look_dir.x * camera_sens_final * sens_mod rotation.y -= look_dir.x * camera_sens_final * sens_mod
camera.rotation.x = clamp(camera.rotation.x - look_dir.y * camera_sens_final * sens_mod, -1.5, 1.5) neck.rotation.x = clamp(neck.rotation.x - look_dir.y * camera_sens_final * sens_mod, -1.5, 1.5)
neck_rotation_sync = neck.rotation
func _handle_joypad_camera_rotation(delta: float, sens_mod: float = 1.0) -> void: func _handle_joypad_camera_rotation(delta: float, sens_mod: float = 1.0) -> void:
@ -124,7 +143,7 @@ func _handle_joypad_camera_rotation(delta: float, sens_mod: float = 1.0) -> void
func walk(delta: float) -> Vector3: func walk(delta: float) -> Vector3:
if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED: if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
move_dir = Input.get_vector("move_left", "move_right", "move_forwards", "move_backwards") move_dir = Input.get_vector("move_left", "move_right", "move_forwards", "move_backwards")
var _forward: Vector3 = camera.global_transform.basis * Vector3(move_dir.x, 0, move_dir.y) var _forward: Vector3 = neck.global_transform.basis * Vector3(move_dir.x, 0, move_dir.y)
var walk_dir: Vector3 = Vector3(_forward.x, 0, _forward.z).normalized() var walk_dir: Vector3 = Vector3(_forward.x, 0, _forward.z).normalized()
walk_vel = walk_vel.move_toward(walk_dir * speed * move_dir.length(), acceleration * delta) walk_vel = walk_vel.move_toward(walk_dir * speed * move_dir.length(), acceleration * delta)
return walk_vel return walk_vel
@ -174,7 +193,10 @@ func ship_exited():
func _on_property_update(node_id: String, property_name: String, value: Variant) -> void: func _on_property_update(node_id: String, property_name: String, value: Variant) -> void:
if NetworkManager.node_map.has(node_id): if NetworkManager.node_map.has(node_id):
var node = NetworkManager.node_map[node_id] if property_name == "neck_rotation_sync" and !is_network_authority:
node.set(property_name, value) neck.rotation = value
else:
var node = NetworkManager.node_map[node_id]
node.set(property_name, value)
else: else:
printerr("Received property update but node_id is wrong? Expected " + str(network_uuid) + " but got " + str(node_id)) printerr("Received property update but node_id is wrong? Expected " + str(network_uuid) + " but got " + str(node_id))

View File

@ -3,89 +3,166 @@ class_name Ship
extends RigidBody3D extends RigidBody3D
@export var player_detection_area: Area3D @export var player_detection_area: Area3D
@export var helm_location_marker: Marker3D
@export var base_turn_speed: float = 50.0
@export var max_turn_speed: float = 50.0
@export var base_lift_speed: float = 50.0
@export var top_speed: float = 50.0
@export var move_speed: float = 50.0
@export var acceleration: float = 5.0 # Increased acceleration for smoother interpolation
@export var interpolation_damp: float = 0.1 # Damping for smoother rotation
var ship_helm_scene: PackedScene = load("res://assets/core/interactables/ship-helm/ship-helm.tscn")
var ship_helm: ShipHelm
var piloting_player: Player = null var piloting_player: Player = null
var ship_id: int = 0
var ship_is_piloted: bool = false var ship_is_piloted: bool = false
var current_level var target_position: Vector3 = Vector3.ZERO
var target_rotation: Quaternion = Quaternion()
var _ignore_next_call := false var predicted_position: Vector3
var predicted_rotation: Quaternion
@export_range(0.01, 1.0, 0.01) var base_turn_speed: float = 0.35 var last_input_time: float = 0.0
@export var max_turn_speed: float = 0.5
@export_range(0.01, 1.0, 0.01) var base_lift_speed: float = 2.0
@export var top_speed: float = 5.0
@export var move_speed: float = 1.0
@export var acceleration: float = 0.1
var network_uuid: String = ""
func _ready(): func _ready():
#connect signals network_uuid = NetworkManager.register_node(self)
player_detection_area.body_entered.connect(_on_area_3d_body_entered) NetworkManager.property_update_received.connect(_on_property_update)
player_detection_area.body_exited.connect(_on_area_3d_body_exited)
_add_ship_helm(ship_helm_scene) #TEMPORARY TEST # Preserve current position and rotation at the start
target_position = global_position
target_rotation = global_transform.basis.get_rotation_quaternion()
predicted_position = global_position
predicted_rotation = global_transform.basis.get_rotation_quaternion()
ship_id = randi_range(1000, 9999) #assign a random id to the ship as a unique identifier player_detection_area.body_entered.connect(_on_player_entered)
GameConsole.log_debug("Ship ID: " + str(ship_id)) player_detection_area.body_exited.connect(_on_player_exited)
func _process(delta: float):
func _physics_process(delta):
if ship_is_piloted: if ship_is_piloted:
var turn_speed = base_turn_speed / max(mass, 1) if piloting_player.steam_id == NetworkManager.steam_id:
var lift_speed = base_lift_speed / max(mass, 1) # This player is piloting
handle_input(delta)
if Input.is_action_pressed("move_left"): send_network_update()
angular_velocity.y += turn_speed
elif Input.is_action_pressed("move_right"):
angular_velocity.y -= turn_speed
else: else:
global_rotation.z = lerpf(global_rotation.z, 0, 0.8) # Another player is piloting, interpolate
interpolate_position_and_rotation(delta)
else:
# No one is piloting, just interpolate
interpolate_position_and_rotation(delta)
if Input.is_action_pressed("jump"): func handle_input(delta: float):
linear_velocity.y += lift_speed var forward_input = 0.0
elif Input.is_action_pressed("crouch"): var turn_input = 0.0
linear_velocity.y -= lift_speed var vertical_input = 0.0
var target_velocity = Vector3.ZERO # Forward and backward movement
if Input.is_action_pressed("move_forwards"): if Input.is_action_pressed("move_forwards"):
target_velocity = -transform.basis.z * top_speed forward_input += 1
elif Input.is_action_pressed("move_backwards"): if Input.is_action_pressed("move_backwards"):
target_velocity = transform.basis.z * top_speed forward_input -= 1
var acceleration = (target_velocity - linear_velocity) * acceleration
apply_central_force(acceleration * mass)
if linear_velocity.length() > top_speed:
linear_velocity = linear_velocity.normalized() * top_speed
angular_velocity.y = clamp(angular_velocity.y, -max_turn_speed, max_turn_speed) # Left and right turning
if Input.is_action_pressed("move_left"):
turn_input += 1
if Input.is_action_pressed("move_right"):
turn_input -= 1
# Self level slowly # Up and down movement
global_rotation.x = lerpf(global_rotation.x, 0, 0.1) if Input.is_action_pressed("jump"):
global_rotation.z = lerpf(global_rotation.z, 0, 0.1) vertical_input += 1
if Input.is_action_pressed("crouch"):
vertical_input -= 1
# Apply torque for turning
if turn_input != 0:
var torque = Vector3.UP * turn_input * base_turn_speed
apply_torque(torque)
func _on_area_3d_body_entered(body: Node3D) -> void: # Clamp the angular velocity to the maximum turn speed
if angular_velocity.length() > max_turn_speed:
angular_velocity = angular_velocity.normalized() * max_turn_speed
# Apply force for forward and backward movement
if forward_input != 0:
var forward_direction = -global_transform.basis.z.normalized()
var forward_force = forward_direction * forward_input * move_speed
apply_central_force(forward_force)
# Apply force for vertical movement
if vertical_input != 0:
var vertical_force = Vector3.UP * vertical_input * base_lift_speed
apply_central_force(vertical_force)
# Update predicted state
predicted_position = predict_position(delta)
predicted_rotation = predict_rotation(delta)
last_input_time = Time.get_ticks_msec()
func predict_position(delta: float):
var velocity = linear_velocity
return global_position + velocity * delta
func predict_rotation(delta: float):
var angular_velocity_quat = Quaternion(Vector3.UP, angular_velocity.y * delta)
return global_transform.basis.get_rotation_quaternion() * angular_velocity_quat
func interpolate_position_and_rotation(delta: float):
# Smooth interpolation with damping
global_position = lerp(global_position, target_position, 1.0 - exp(-acceleration * delta))
global_transform.basis = Basis(slerp_damp(global_transform.basis.get_rotation_quaternion(), target_rotation, interpolation_damp, 1.0))
func slerp_damp(from: Quaternion, to: Quaternion, damping: float, dt: float):
var t = 1.0 - exp(-damping * dt)
return from.slerp(to, t)
func send_network_update():
if NetworkManager.is_host and ship_is_piloted and piloting_player.steam_id == NetworkManager.steam_id:
# Host is piloting, synchronize with clients
NetworkManager.sync_property_to_all_except_host(network_uuid, "global_position", predicted_position)
NetworkManager.sync_property_to_all_except_host(network_uuid, "global_rotation", predicted_rotation)
elif !NetworkManager.is_host and ship_is_piloted and piloting_player.steam_id == NetworkManager.steam_id:
# Client is piloting, send updates to the host
NetworkManager.sync_property_to_all_except_host(network_uuid, "global_position", predicted_position)
NetworkManager.sync_property_to_all_except_host(network_uuid, "global_rotation", predicted_rotation)
func receive_global_position_update(value: Vector3):
target_position = value
func receive_global_rotation_update(value: Quaternion):
target_rotation = value
func _on_player_entered(body):
if body is Player and body.get_parent() != self: if body is Player and body.get_parent() != self:
if !body.is_network_authority: return
body.call_deferred("reparent", self, true)
body.ship_entered(self) body.ship_entered(self)
piloting_player = body print("Player entered the ship area.")
body.call_deferred("reparent", self, true) #reparents player onto self (RigidBody3D)
print("ENTERED")
func _on_player_exited(body):
func _on_area_3d_body_exited(body: Node3D) -> void:
if body is Player and body.get_parent() != get_node("/root/DevLevel/"): if body is Player and body.get_parent() != get_node("/root/DevLevel/"):
if !body.is_network_authority: return
body.call_deferred("reparent", get_node("/root/DevLevel/"), true)
body.ship_exited() body.ship_exited()
ship_is_piloted = false print("Player exited the ship area.")
piloting_player = null
body.call_deferred("reparent", get_node("/root/DevLevel/"), true) #reparents player back onto world node
print("EXITED")
func set_piloting_player(player: Player):
piloting_player = player
ship_is_piloted = piloting_player != null
if piloting_player:
print("Player", piloting_player.username, "is now piloting the ship.")
else:
print("The ship is no longer piloted.")
func _add_ship_helm(_ship_helm_scene: PackedScene): func remove_piloting_player():
var ship_helm = _ship_helm_scene.instantiate() piloting_player = null
add_child(ship_helm) ship_is_piloted = false
ship_helm = get_node("ShipHelm") print("The ship is no longer piloted.")
func _on_property_update(node_id: String, property_name: String, value: Variant) -> void:
if NetworkManager.node_map.has(node_id) and node_id == network_uuid:
if property_name == "global_position":
receive_global_position_update(value)
elif property_name == "global_rotation":
receive_global_rotation_update(value)
else:
var node = NetworkManager.node_map[node_id]
node.set(property_name, value)

View File

@ -1,7 +1,8 @@
[gd_scene load_steps=7 format=3 uid="uid://y0xb2vktsr1k"] [gd_scene load_steps=8 format=3 uid="uid://y0xb2vktsr1k"]
[ext_resource type="Script" path="res://assets/core/ships/ship_script.gd" id="1_ghft7"] [ext_resource type="Script" path="res://assets/core/ships/ship_script.gd" id="1_ghft7"]
[ext_resource type="Texture2D" uid="uid://gymb0tju4y67" path="res://addons/kennysprototypetextures/Dark/texture_black (1).png" id="2_3koq8"] [ext_resource type="Texture2D" uid="uid://gymb0tju4y67" path="res://addons/kennysprototypetextures/Dark/texture_black (1).png" id="2_3koq8"]
[ext_resource type="PackedScene" uid="uid://dm31ddavxv5gt" path="res://assets/core/interactables/ship-helm/ship-helm.tscn" id="3_eyiku"]
[sub_resource type="BoxShape3D" id="BoxShape3D_6gbwt"] [sub_resource type="BoxShape3D" id="BoxShape3D_6gbwt"]
size = Vector3(5, 0.15, 20) size = Vector3(5, 0.15, 20)
@ -16,13 +17,15 @@ size = Vector3(5, 0.15, 20)
[sub_resource type="BoxShape3D" id="BoxShape3D_7o08p"] [sub_resource type="BoxShape3D" id="BoxShape3D_7o08p"]
size = Vector3(4.99609, 3.11252, 20.0022) size = Vector3(4.99609, 3.11252, 20.0022)
[node name="ShuttleClass" type="RigidBody3D" node_paths=PackedStringArray("player_detection_area")] [node name="ShuttleClass" type="RigidBody3D" node_paths=PackedStringArray("player_detection_area", "helm_location_marker")]
collision_layer = 8 collision_layer = 8
collision_mask = 200 collision_mask = 200
mass = 700.0 mass = 700.0
gravity_scale = 0.0 gravity_scale = 0.0
script = ExtResource("1_ghft7") script = ExtResource("1_ghft7")
player_detection_area = NodePath("PlayerDetectionArea") player_detection_area = NodePath("PlayerDetectionArea")
helm_location_marker = NodePath("HelmLocationMarker")
base_lift_speed = 5.0
[node name="ShipToShipCol" type="CollisionShape3D" parent="."] [node name="ShipToShipCol" type="CollisionShape3D" parent="."]
shape = SubResource("BoxShape3D_6gbwt") shape = SubResource("BoxShape3D_6gbwt")
@ -44,3 +47,10 @@ shape = SubResource("BoxShape3D_6gbwt")
[node name="PlayerDetectionAreaCol" type="CollisionShape3D" parent="PlayerDetectionArea"] [node name="PlayerDetectionAreaCol" type="CollisionShape3D" parent="PlayerDetectionArea"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.47652, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.47652, 0)
shape = SubResource("BoxShape3D_7o08p") shape = SubResource("BoxShape3D_7o08p")
[node name="HelmLocationMarker" type="Marker3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0)
[node name="ShipHelm" parent="." node_paths=PackedStringArray("parent_ship") instance=ExtResource("3_eyiku")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -7.54699)
parent_ship = NodePath("..")

View File

@ -3,7 +3,7 @@
[ext_resource type="Script" path="res://assets/core/ships/test-ship/test_ship.gd" id="1_yql7r"] [ext_resource type="Script" path="res://assets/core/ships/test-ship/test_ship.gd" id="1_yql7r"]
[ext_resource type="PackedScene" uid="uid://dm31ddavxv5gt" path="res://assets/core/interactables/ship-helm/ship-helm.tscn" id="3_3wdac"] [ext_resource type="PackedScene" uid="uid://dm31ddavxv5gt" path="res://assets/core/interactables/ship-helm/ship-helm.tscn" id="3_3wdac"]
[ext_resource type="PackedScene" uid="uid://f7xy5w0gmpwj" path="res://assets/core/ships/test-ship/airship_raft.glb" id="3_h6lyp"] [ext_resource type="PackedScene" uid="uid://f7xy5w0gmpwj" path="res://assets/core/ships/test-ship/airship_raft.glb" id="3_h6lyp"]
[ext_resource type="Material" uid="uid://ctemnr3tq0iu0" path="res://assets/core/ships/test-ship/new_standard_material_3d.tres" id="4_hhywo"] [ext_resource type="Material" path="res://assets/core/ships/test-ship/new_standard_material_3d.tres" id="4_hhywo"]
[sub_resource type="BoxShape3D" id="BoxShape3D_kbheo"] [sub_resource type="BoxShape3D" id="BoxShape3D_kbheo"]
size = Vector3(12.0762, 9.20947, 45.9958) size = Vector3(12.0762, 9.20947, 45.9958)
@ -20,10 +20,8 @@ script = ExtResource("1_yql7r")
ship_area = NodePath("Area3D") ship_area = NodePath("Area3D")
ship_helm = NodePath("ShipHelm") ship_helm = NodePath("ShipHelm")
[node name="ShipHelm" parent="." node_paths=PackedStringArray("parent_ship", "helm_lock_pos") instance=ExtResource("3_3wdac")] [node name="ShipHelm" parent="." instance=ExtResource("3_3wdac")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.47976, -10.9455) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.47976, -10.9455)
parent_ship = NodePath("..")
helm_lock_pos = NodePath("HelmLockPos")
[node name="HelmLockPos" type="Marker3D" parent="ShipHelm"] [node name="HelmLockPos" type="Marker3D" parent="ShipHelm"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.345567, 1) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.345567, 1)

View File

@ -7,6 +7,7 @@ extends RigidBody3D
var ship_id: int = 0 var ship_id: int = 0
var ship_is_piloted: bool = false var ship_is_piloted: bool = false
var base_turn_speed: float = 1 var base_turn_speed: float = 1
var top_turn_speed: float = 50.0
var ship_lift_speed: float = 20 # Adjust this value as needed var ship_lift_speed: float = 20 # Adjust this value as needed
var acceleration: float = 50 var acceleration: float = 50
var deceleration: float = acceleration * 0.5 var deceleration: float = acceleration * 0.5
@ -25,11 +26,11 @@ func _ready():
func _physics_process(delta): func _physics_process(delta):
global_rotation.x = lerpf(global_rotation.x, 0, 0.01) global_rotation.x = lerpf(global_rotation.x, 0, 0.5)
global_rotation.z = lerpf(global_rotation.z, 0, 0.01) global_rotation.z = lerpf(global_rotation.z, 0, 0.5)
if ship_is_piloted: if ship_is_piloted:
var turn_speed = base_turn_speed / max(mass, 1) var turn_speed = base_turn_speed / max(mass, 1) # changes speeds based on how THICC the ship is
if Input.is_action_pressed("move_left"): if Input.is_action_pressed("move_left"):
angular_velocity.y += turn_speed angular_velocity.y += turn_speed
elif Input.is_action_pressed("move_right"): elif Input.is_action_pressed("move_right"):
@ -52,11 +53,7 @@ func _physics_process(delta):
if Input.is_action_pressed("crouch"): if Input.is_action_pressed("crouch"):
apply_impulse(Vector3.DOWN * ship_lift_speed) apply_impulse(Vector3.DOWN * ship_lift_speed)
angular_velocity.y = clamp(angular_velocity.y, -0.5, 0.5) angular_velocity.y = clamp(angular_velocity.y, -top_turn_speed, top_turn_speed)
if piloting_player != null and ship_helm.is_being_piloted:
piloting_player.global_position = ship_helm.helm_lock_pos.global_position
func _on_area_3d_body_entered(body): func _on_area_3d_body_entered(body):

33
deleteme.txt Normal file
View File

@ -0,0 +1,33 @@
Player 1: Host
Player 2: Pilot
Player 3: Neither
FOR SENDING UPDATES:
if host is pilot or no pilot, host sends ship state
if pilot, pilot sends ship state not the host
FOR RECEIVING UPDATES:
if no pilot and not host, receive updates
if no pilot and is host, do not receive updates - host is sending updates
if pilot, do not receive updates
if host and there is a pilot, receive updates from pilot
func send():
if (host == pilot or no_pilot) {
// host sends ship state
} else if (pilot) {
// pilot sends ship state
}
func receive():
if (no_pilot and not host) {
// receive updates from host
} else if (no_pilot and is_host) {
// do not receive updates - host is sending updates
} else if (pilot) {
// do not receive updates - sending updates as pilot
} else if (host and there is a pilot) {
// receive updates from pilot - receiving updates as host from pilot
}

View File

@ -37,3 +37,68 @@ unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\"
ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash
kill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\") kill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\")
rm -rf \"{temp_dir}\"" rm -rf \"{temp_dir}\""
[preset.1]
name="Windows Desktop"
platform="Windows Desktop"
runnable=true
advanced_options=false
dedicated_server=false
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path="C:/Users/wisen/Downloads/Steamforged Skies.exe"
encryption_include_filters=""
encryption_exclude_filters=""
encrypt_pck=false
encrypt_directory=false
script_export_mode=2
[preset.1.options]
custom_template/debug=""
custom_template/release=""
debug/export_console_wrapper=1
binary_format/embed_pck=true
texture_format/s3tc_bptc=true
texture_format/etc2_astc=false
binary_format/architecture="x86_64"
codesign/enable=false
codesign/timestamp=true
codesign/timestamp_server_url=""
codesign/digest_algorithm=1
codesign/description=""
codesign/custom_options=PackedStringArray()
application/modify_resources=true
application/icon="res://assets/icon.png"
application/console_wrapper_icon=""
application/icon_interpolation=4
application/file_version="0.0.0.1"
application/product_version="0.0.0.1"
application/company_name="Bellsworne Games"
application/product_name="Steamforged Skies"
application/file_description="A steampunk airship survival game"
application/copyright=""
application/trademarks=""
application/export_angle=0
application/export_d3d12=0
application/d3d12_agility_sdk_multiarch=true
ssh_remote_deploy/enabled=false
ssh_remote_deploy/host="user@host_ip"
ssh_remote_deploy/port="22"
ssh_remote_deploy/extra_args_ssh=""
ssh_remote_deploy/extra_args_scp=""
ssh_remote_deploy/run_script="Expand-Archive -LiteralPath '{temp_dir}\\{archive_name}' -DestinationPath '{temp_dir}'
$action = New-ScheduledTaskAction -Execute '{temp_dir}\\{exe_name}' -Argument '{cmd_args}'
$trigger = New-ScheduledTaskTrigger -Once -At 00:00
$settings = New-ScheduledTaskSettingsSet
$task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings
Register-ScheduledTask godot_remote_debug -InputObject $task -Force:$true
Start-ScheduledTask -TaskName godot_remote_debug
while (Get-ScheduledTask -TaskName godot_remote_debug | ? State -eq running) { Start-Sleep -Milliseconds 100 }
Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue"
ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debug -ErrorAction:SilentlyContinue
Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue
Remove-Item -Recurse -Force '{temp_dir}'"

View File

@ -11,7 +11,7 @@ config_version=5
[application] [application]
config/name="Steamforged Skies" config/name="Steamforged Skies"
run/main_scene="res://assets/scenes/main.tscn" run/main_scene="res://assets/core/networking/scenes/lobby.tscn"
config/features=PackedStringArray("4.3", "Forward Plus") config/features=PackedStringArray("4.3", "Forward Plus")
config/icon="res://assets/icon.png" config/icon="res://assets/icon.png"