Merge branch 'feature/networked-star-system'
This commit is contained in:
@ -8,8 +8,15 @@
|
||||
properties/0/path = NodePath(".:position")
|
||||
properties/0/spawn = true
|
||||
properties/0/replication_mode = 1
|
||||
properties/1/path = NodePath(".:linear_velocity")
|
||||
properties/1/spawn = true
|
||||
properties/1/replication_mode = 1
|
||||
properties/2/path = NodePath(".:rotation")
|
||||
properties/2/spawn = true
|
||||
properties/2/replication_mode = 1
|
||||
|
||||
[node name="3dTestShip" type="RigidBody3D" unique_id=246037729]
|
||||
physics_interpolation_mode = 1
|
||||
script = ExtResource("1_ktv2t")
|
||||
physics_mode = 1
|
||||
base_mass = 10000.0
|
||||
@ -543,9 +550,6 @@ physics_mode = 2
|
||||
transform = Transform3D(0.99989736, 0, 0.014328662, -0.014328662, -4.371139e-08, 0.99989736, 6.263257e-10, -1, -4.37069e-08, -1.5009866, -1.4999988, 1.9908428)
|
||||
physics_mode = 2
|
||||
|
||||
[node name="Spawner" parent="." unique_id=6714366 instance=ExtResource("3_ism2t")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 2)
|
||||
|
||||
[node name="OmniLight3D" type="OmniLight3D" parent="." unique_id=1071155008]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.4, 1, -3)
|
||||
|
||||
@ -562,5 +566,8 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.4, 1, 4)
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 3)
|
||||
current = true
|
||||
|
||||
[node name="Spawner" parent="." unique_id=6714366 instance=ExtResource("3_ism2t")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 2)
|
||||
|
||||
[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="." unique_id=2096937457]
|
||||
replication_config = SubResource("SceneReplicationConfig_ism2t")
|
||||
|
||||
22
src/scenes/celestial_bodies/barycenter.tscn
Normal file
22
src/scenes/celestial_bodies/barycenter.tscn
Normal file
@ -0,0 +1,22 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://b7bh45nrtdom5"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://b2hb3bwrlh40c" path="res://scenes/celestial_bodies/barycenter.gd" id="1_e776o"]
|
||||
|
||||
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_e776o"]
|
||||
properties/0/path = NodePath(".:linear_velocity")
|
||||
properties/0/spawn = true
|
||||
properties/0/replication_mode = 1
|
||||
properties/1/path = NodePath(".:position")
|
||||
properties/1/spawn = true
|
||||
properties/1/replication_mode = 1
|
||||
|
||||
[node name="Barycenter" type="RigidBody3D" unique_id=1389317234]
|
||||
script = ExtResource("1_e776o")
|
||||
metadata/_custom_type_script = "uid://wlm40n8ywr"
|
||||
|
||||
[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="." unique_id=717759965]
|
||||
replication_config = SubResource("SceneReplicationConfig_e776o")
|
||||
|
||||
[node name="MultiplayerSpawner" type="MultiplayerSpawner" parent="." unique_id=2061784354]
|
||||
_spawnable_scenes = PackedStringArray("uid://dv18eg4xrlefe")
|
||||
spawn_path = NodePath("..")
|
||||
@ -2,11 +2,12 @@ class_name CelestialBody extends OrbitalBody3D
|
||||
|
||||
# --- Set in corresponding scene ---
|
||||
# var auto_proxy_gravity = false
|
||||
@export var radius: float = 100.0
|
||||
|
||||
func set_radius(value: float):
|
||||
@export var radius: float = 100.0:
|
||||
set(value):
|
||||
radius = value
|
||||
_set_radi()
|
||||
|
||||
func _set_radi():
|
||||
if $Surface.mesh is SphereMesh:
|
||||
$Surface.mesh.radius = radius
|
||||
$Surface.mesh.height = radius * 2.0
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
[gd_scene load_steps=5 format=3 uid="uid://dv18eg4xrlefe"]
|
||||
[gd_scene load_steps=6 format=3 uid="uid://dv18eg4xrlefe"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://dok35h0q4pseh" path="res://scenes/celestial_bodies/celestial_body.gd" id="1_uxu4s"]
|
||||
[ext_resource type="Material" uid="uid://de0xnmjf12ted" path="res://scenes/celestial_bodies/materials/sun_mat.tres" id="2_vi0nt"]
|
||||
@ -11,18 +11,38 @@ height = 4000.0
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_uxu4s"]
|
||||
|
||||
[node name="CelestialBody" type="RigidBody3D"]
|
||||
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_vi0nt"]
|
||||
properties/0/path = NodePath(".:position")
|
||||
properties/0/spawn = true
|
||||
properties/0/replication_mode = 1
|
||||
properties/1/path = NodePath(".:rotation")
|
||||
properties/1/spawn = true
|
||||
properties/1/replication_mode = 1
|
||||
properties/2/path = NodePath(".:linear_velocity")
|
||||
properties/2/spawn = true
|
||||
properties/2/replication_mode = 1
|
||||
properties/3/path = NodePath(".:angular_velocity")
|
||||
properties/3/spawn = true
|
||||
properties/3/replication_mode = 1
|
||||
properties/4/path = NodePath(".:radius")
|
||||
properties/4/spawn = true
|
||||
properties/4/replication_mode = 1
|
||||
|
||||
[node name="CelestialBody" type="RigidBody3D" unique_id=345490070]
|
||||
script = ExtResource("1_uxu4s")
|
||||
auto_proxy_gravity = false
|
||||
metadata/_custom_type_script = "uid://dok35h0q4pseh"
|
||||
|
||||
[node name="Surface" type="MeshInstance3D" parent="."]
|
||||
[node name="Surface" type="MeshInstance3D" parent="." unique_id=193823349]
|
||||
mesh = SubResource("SphereMesh_vi0nt")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=232085687]
|
||||
shape = SubResource("SphereShape3D_uxu4s")
|
||||
|
||||
[node name="OmniLight3D" type="OmniLight3D" parent="."]
|
||||
[node name="OmniLight3D" type="OmniLight3D" parent="." unique_id=1965995953]
|
||||
light_color = Color(0.958646, 0.7997282, 0.55087835, 1)
|
||||
omni_range = 200000.0
|
||||
omni_attenuation = 2.0
|
||||
|
||||
[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="." unique_id=2090029903]
|
||||
replication_config = SubResource("SceneReplicationConfig_vi0nt")
|
||||
|
||||
@ -17,8 +17,8 @@ var _pitch_yaw_input: Vector2 = Vector2.ZERO
|
||||
|
||||
## Rotation Variables
|
||||
@onready var camera_anchor: Marker3D = $CameraAnchor
|
||||
@onready var camera_pivot: Node3D = $CameraPivot
|
||||
@onready var camera: Camera3D = $CameraPivot/SpringArm/Camera3D
|
||||
@onready var camera_pivot: Node3D = $CameraAnchor/CameraPivot
|
||||
@onready var camera: Camera3D = $CameraAnchor/CameraPivot/SpringArm/Camera3D
|
||||
@export_range(0.1, PI / 2.0) var max_yaw_rad: float = deg_to_rad(80.0)
|
||||
@export_range(-PI / 2.0 + 0.01, 0) var min_pitch_rad: float = deg_to_rad(-75.0)
|
||||
@export_range(0, PI / 2.0 - 0.01) var max_pitch_rad: float = deg_to_rad(60.0)
|
||||
@ -52,7 +52,7 @@ func _ready():
|
||||
else:
|
||||
printerr("GripDetector Area3D node not found on CharacterPawn!")
|
||||
|
||||
if is_multiplayer_authority():
|
||||
if name == str(multiplayer.get_unique_id()):
|
||||
camera.make_current()
|
||||
camera.process_mode = Node.PROCESS_MODE_ALWAYS
|
||||
|
||||
@ -66,14 +66,25 @@ func _physics_process(_delta: float):
|
||||
|
||||
_reset_inputs()
|
||||
|
||||
|
||||
func _integrate_forces(state: PhysicsDirectBodyState3D):
|
||||
# Let the active movement controller apply its forces
|
||||
if not is_multiplayer_authority(): return
|
||||
super (state)
|
||||
|
||||
|
||||
# print("Integrating forces for pawn %s" % name)
|
||||
# print(" Move Input: %s, Vertical Input: %f, Roll Input: %f" % [_move_input, _vertical_input, _roll_input])
|
||||
|
||||
# Zero-G Movement
|
||||
if zero_g_movemement_component:
|
||||
# We pass the physics state
|
||||
zero_g_movemement_component.process_movement(state, _move_input, _vertical_input, _roll_input, _l_click_input, _r_click_input)
|
||||
|
||||
# EVA Suit Movement
|
||||
if eva_suit_component and zero_g_movemement_component.movement_state == ZeroGMovementComponent.MovementState.IDLE:
|
||||
eva_suit_component.process_eva_movement(state, _move_input, _vertical_input, _roll_input, _r_click_input)
|
||||
|
||||
|
||||
# --- Universal Rotation ---
|
||||
func _apply_mouse_rotation():
|
||||
if _pitch_yaw_input != Vector2.ZERO:
|
||||
@ -120,7 +131,8 @@ func _reset_head_yaw(delta: float):
|
||||
# Smoothly apply the reset target to the actual pivot rotation
|
||||
camera_anchor.rotation.y = lerpf(camera_anchor.rotation.y, 0.0, delta * head_turn_lerp_speed)
|
||||
|
||||
func _notification(what: int) -> void:
|
||||
match what:
|
||||
NOTIFICATION_ENTER_TREE:
|
||||
set_multiplayer_authority(int(name))
|
||||
# TODO: Re-enable when multiplayer authority per pawn is functional
|
||||
# func _notification(what: int) -> void:
|
||||
# match what:
|
||||
# NOTIFICATION_ENTER_TREE:
|
||||
# set_multiplayer_authority(int(name))
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
[gd_scene load_steps=9 format=3 uid="uid://7yc6a07xoccy"]
|
||||
[gd_scene load_steps=10 format=3 uid="uid://7yc6a07xoccy"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://cdmmiixa75f3x" path="res://scenes/character/character_pawn_3d.gd" id="1_4frsu"]
|
||||
[ext_resource type="PackedScene" uid="uid://bm1rbv4tuppbc" path="res://scenes/character/eva_suit_controller.tscn" id="3_gnddn"]
|
||||
@ -9,6 +9,10 @@
|
||||
|
||||
[sub_resource type="CapsuleMesh" id="CapsuleMesh_6vm80"]
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_673rh"]
|
||||
radius = 0.1
|
||||
height = 1.0
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_gnddn"]
|
||||
radius = 1.0
|
||||
|
||||
@ -19,11 +23,19 @@ properties/0/replication_mode = 1
|
||||
properties/1/path = NodePath(".:rotation")
|
||||
properties/1/spawn = true
|
||||
properties/1/replication_mode = 1
|
||||
properties/2/path = NodePath("CameraPivot:rotation")
|
||||
properties/2/path = NodePath("CameraAnchor:rotation")
|
||||
properties/2/spawn = true
|
||||
properties/2/replication_mode = 2
|
||||
properties/2/replication_mode = 1
|
||||
properties/3/path = NodePath(".:linear_velocity")
|
||||
properties/3/spawn = false
|
||||
properties/3/replication_mode = 0
|
||||
properties/4/path = NodePath(".:angular_velocity")
|
||||
properties/4/spawn = false
|
||||
properties/4/replication_mode = 0
|
||||
|
||||
[node name="CharacterPawn3D" type="RigidBody3D" unique_id=288275840]
|
||||
physics_interpolation_mode = 1
|
||||
top_level = true
|
||||
script = ExtResource("1_4frsu")
|
||||
metadata/_custom_type_script = "uid://cdmmiixa75f3x"
|
||||
|
||||
@ -34,16 +46,17 @@ shape = SubResource("CapsuleShape3D_6vm80")
|
||||
mesh = SubResource("CapsuleMesh_6vm80")
|
||||
|
||||
[node name="CameraAnchor" type="Marker3D" parent="." unique_id=462168232]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.7000000000000001, 0)
|
||||
|
||||
[node name="CameraPivot" type="Node3D" parent="." unique_id=794640520]
|
||||
[node name="CameraPivot" type="Node3D" parent="CameraAnchor" unique_id=794640520]
|
||||
physics_interpolation_mode = 1
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.75, 0)
|
||||
top_level = true
|
||||
|
||||
[node name="SpringArm" type="SpringArm3D" parent="CameraPivot" unique_id=1399441728]
|
||||
spring_length = 3.0
|
||||
[node name="SpringArm" type="SpringArm3D" parent="CameraAnchor/CameraPivot" unique_id=1399441728]
|
||||
shape = SubResource("CapsuleShape3D_673rh")
|
||||
spring_length = 2.0
|
||||
margin = 0.1
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="CameraPivot/SpringArm" unique_id=1779046272]
|
||||
[node name="Camera3D" type="Camera3D" parent="CameraAnchor/CameraPivot/SpringArm" unique_id=1779046272]
|
||||
far = 200000.0
|
||||
|
||||
[node name="GripDetector" type="Area3D" parent="." unique_id=734413990]
|
||||
@ -60,8 +73,9 @@ script = ExtResource("4_8jhjh")
|
||||
metadata/_custom_type_script = "uid://y3vo40i16ek3"
|
||||
|
||||
[node name="EVAMovementComponent" parent="." unique_id=1806288315 instance=ExtResource("3_gnddn")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.13939085347041424, 0.5148942200402955)
|
||||
|
||||
[node name="PlayerController3d" parent="." unique_id=1450011826 instance=ExtResource("4_bcy3l")]
|
||||
|
||||
[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="." unique_id=732324183]
|
||||
replication_config = SubResource("SceneReplicationConfig_gnddn")
|
||||
|
||||
[node name="PlayerController3d" parent="." unique_id=1450011826 instance=ExtResource("4_bcy3l")]
|
||||
|
||||
@ -70,7 +70,6 @@ func _apply_floating_movement(state: PhysicsDirectBodyState3D, move_input: Vecto
|
||||
_is_auto_orienting = false # Cancel auto-orientation if rolling manually
|
||||
|
||||
var roll_acceleration = state.transform.basis.z * (-roll_input) * roll_torque_acceleration
|
||||
|
||||
# Apply the global torque vector using the pawn's helper function
|
||||
state.apply_torque(roll_acceleration)
|
||||
|
||||
|
||||
@ -1,6 +1,12 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://bm1rbv4tuppbc"]
|
||||
[gd_scene load_steps=3 format=3 uid="uid://bm1rbv4tuppbc"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://d4jka2etva22s" path="res://scenes/character/eva_movement_component.gd" id="1_mb22m"]
|
||||
|
||||
[node name="EVASuitController" type="Node3D"]
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_rlk1u"]
|
||||
size = Vector3(1, 1, 0.4)
|
||||
|
||||
[node name="EVASuitController" type="Node3D" unique_id=241443807]
|
||||
script = ExtResource("1_mb22m")
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="." unique_id=1434211019]
|
||||
mesh = SubResource("BoxMesh_rlk1u")
|
||||
|
||||
@ -8,6 +8,7 @@ class_name PlayerController3D
|
||||
@export var mouse_sensitivity: float = 0.002 # Radians per pixel motion
|
||||
var _mouse_motion_input: Vector2 = Vector2.ZERO
|
||||
|
||||
|
||||
class KeyInput:
|
||||
var pressed: bool = false
|
||||
var held: bool = false
|
||||
@ -18,9 +19,26 @@ class KeyInput:
|
||||
held = _h
|
||||
released = _r
|
||||
|
||||
func _to_dict():
|
||||
return {
|
||||
"pressed": pressed,
|
||||
"held": held,
|
||||
"released": released
|
||||
}
|
||||
|
||||
static func from_dict(dict: Dictionary) -> KeyInput:
|
||||
return KeyInput.new(dict.get("pressed", false), dict.get("held", false), dict.get("released", false))
|
||||
|
||||
func _ready():
|
||||
# If we are spawned dynamically, the owner_id might be set by GameManager.
|
||||
# Fallback: assume the pawn's name is the player ID (common pattern).
|
||||
if get_parent().name.is_valid_int():
|
||||
set_multiplayer_authority(int(get_parent().name))
|
||||
|
||||
func _unhandled_input(event: InputEvent):
|
||||
|
||||
# Check if THIS client is the owner of this controller
|
||||
if not is_multiplayer_authority() or not is_instance_valid(possessed_pawn):
|
||||
# print("Peer ID: %s, Node Authority: %s" % [multiplayer.get_unique_id(), get_multiplayer_authority()])
|
||||
return
|
||||
|
||||
# Handle mouse motion input directly here
|
||||
@ -28,6 +46,7 @@ func _unhandled_input(event: InputEvent):
|
||||
_mouse_motion_input += Vector2(event.relative.x, -event.relative.y)
|
||||
|
||||
func _physics_process(_delta):
|
||||
# Check if THIS client is the owner
|
||||
if not is_multiplayer_authority() or not is_instance_valid(possessed_pawn):
|
||||
return
|
||||
|
||||
@ -36,7 +55,7 @@ func _physics_process(_delta):
|
||||
var sensitivity_modified_mouse_input = Vector2(_mouse_motion_input.x, _mouse_motion_input.y) * mouse_sensitivity
|
||||
|
||||
# Send rotation input via RPC immediately
|
||||
server_process_rotation_input.rpc_id(multiplayer.get_unique_id(), sensitivity_modified_mouse_input)
|
||||
server_process_rotation_input.rpc_id(1, sensitivity_modified_mouse_input)
|
||||
|
||||
# Reset the buffer
|
||||
_mouse_motion_input = Vector2.ZERO
|
||||
@ -50,29 +69,29 @@ func _physics_process(_delta):
|
||||
var l_input = KeyInput.new(Input.is_action_just_pressed("left_click"), Input.is_action_pressed("left_click"), Input.is_action_just_released("left_click"))
|
||||
var r_input = KeyInput.new(Input.is_action_just_pressed("right_click"), Input.is_action_pressed("right_click"), Input.is_action_just_released("right_click"))
|
||||
|
||||
server_process_movement_input.rpc_id(multiplayer.get_unique_id(), move_vec, roll_input, vertical_input)
|
||||
server_process_interaction_input.rpc_id(multiplayer.get_unique_id(), interact_input)
|
||||
server_process_clicks.rpc_id(multiplayer.get_unique_id(), l_input, r_input)
|
||||
server_process_movement_input.rpc_id(1, move_vec, roll_input, vertical_input)
|
||||
server_process_interaction_input.rpc_id(1, interact_input._to_dict())
|
||||
server_process_clicks.rpc_id(1, l_input._to_dict(), r_input._to_dict())
|
||||
|
||||
@rpc("authority", "call_local")
|
||||
@rpc("any_peer", "call_local")
|
||||
func server_process_movement_input(move: Vector2, roll: float, vertical: float):
|
||||
if is_instance_valid(possessed_pawn):
|
||||
possessed_pawn.set_movement_input(move, roll, vertical)
|
||||
|
||||
@rpc("authority", "call_local")
|
||||
func server_process_interaction_input(interact_input: KeyInput):
|
||||
@rpc("any_peer", "call_local")
|
||||
func server_process_interaction_input(interact_input: Dictionary):
|
||||
if is_instance_valid(possessed_pawn):
|
||||
possessed_pawn.set_interaction_input(interact_input)
|
||||
possessed_pawn.set_interaction_input(KeyInput.from_dict(interact_input))
|
||||
|
||||
@rpc("authority", "call_local")
|
||||
@rpc("any_peer", "call_local")
|
||||
func server_process_rotation_input(input: Vector2):
|
||||
if is_instance_valid(possessed_pawn):
|
||||
possessed_pawn.set_rotation_input(input)
|
||||
|
||||
@rpc("authority", "call_local")
|
||||
func server_process_clicks(l_action: KeyInput, r_action: KeyInput):
|
||||
@rpc("any_peer", "call_local")
|
||||
func server_process_clicks(l_action: Dictionary, r_action: Dictionary):
|
||||
if is_instance_valid(possessed_pawn):
|
||||
possessed_pawn.set_click_input(l_action, r_action)
|
||||
possessed_pawn.set_click_input(KeyInput.from_dict(l_action), KeyInput.from_dict(r_action))
|
||||
|
||||
func possess(pawn_to_control: CharacterPawn3D):
|
||||
possessed_pawn = pawn_to_control
|
||||
|
||||
@ -55,7 +55,7 @@ func _scan_and_weld_neighbors():
|
||||
_create_weld_to(other_piece)
|
||||
|
||||
func _create_weld_to(neighbor: StructuralPiece):
|
||||
print("Welding %s to %s" % [self.name, neighbor.name])
|
||||
# print("Welding %s to %s" % [self.name, neighbor.name])
|
||||
|
||||
# 1. Create the Joint
|
||||
var joint = Generic6DOFJoint3D.new()
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
extends Area3D
|
||||
class_name Spawner
|
||||
class_name Spawner extends Area3D
|
||||
|
||||
@onready var mp_spawner: MultiplayerSpawner = $MultiplayerSpawner
|
||||
@export var disabled: bool = false
|
||||
@ -10,6 +9,7 @@ func _ready():
|
||||
# We wait one frame to ensure singletons are ready.
|
||||
await get_tree().process_frame
|
||||
GameManager.register_spawner(self)
|
||||
mp_spawner.spawn_path = get_parent().get_path()
|
||||
|
||||
func can_spawn() -> bool:
|
||||
return false if disabled else get_overlapping_bodies().is_empty()
|
||||
|
||||
@ -5,12 +5,12 @@
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_lldyu"]
|
||||
radius = 1.0
|
||||
|
||||
[node name="Spawner" type="Area3D"]
|
||||
[node name="Spawner" type="Area3D" unique_id=1511371555]
|
||||
script = ExtResource("1_lldyu")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=1330579270]
|
||||
shape = SubResource("SphereShape3D_lldyu")
|
||||
|
||||
[node name="MultiplayerSpawner" type="MultiplayerSpawner" parent="."]
|
||||
[node name="MultiplayerSpawner" type="MultiplayerSpawner" parent="." unique_id=1624471299]
|
||||
_spawnable_scenes = PackedStringArray("uid://7yc6a07xoccy")
|
||||
spawn_path = NodePath("..")
|
||||
|
||||
@ -1,11 +1,14 @@
|
||||
extends Node
|
||||
|
||||
var port = 42069
|
||||
var default_ip = "127.0.0.1"
|
||||
|
||||
func create_server() -> void:
|
||||
print(multiplayer.multiplayer_peer)
|
||||
print("Starting Server on port %d..." % port)
|
||||
var peer = ENetMultiplayerPeer.new()
|
||||
|
||||
# Ensure we disconnect old signals if any
|
||||
_disconnect_signals()
|
||||
setup_connections()
|
||||
|
||||
var error = peer.create_server(port)
|
||||
@ -14,37 +17,66 @@ func create_server() -> void:
|
||||
return
|
||||
|
||||
multiplayer.multiplayer_peer = peer
|
||||
|
||||
print("Server Unique ID: ", multiplayer.get_unique_id())
|
||||
|
||||
func create_client() -> void:
|
||||
func create_client(ip: String = "") -> void:
|
||||
var target_ip = ip if not ip.is_empty() else default_ip
|
||||
print("Connecting to Server at %s:%d..." % [target_ip, port])
|
||||
|
||||
_disconnect_signals()
|
||||
setup_connections()
|
||||
|
||||
var peer = ENetMultiplayerPeer.new()
|
||||
var error = peer.create_client("127.0.0.1", port)
|
||||
var error = peer.create_client(target_ip, port)
|
||||
if error:
|
||||
push_error(error)
|
||||
return
|
||||
|
||||
multiplayer.multiplayer_peer = peer
|
||||
print("Client Unique ID: ", multiplayer.get_unique_id())
|
||||
print("Client waiting for connection...")
|
||||
|
||||
func close_connection():
|
||||
if multiplayer.multiplayer_peer:
|
||||
multiplayer.multiplayer_peer.close()
|
||||
multiplayer.multiplayer_peer = null
|
||||
print("Connection closed.")
|
||||
_disconnect_signals()
|
||||
|
||||
func setup_connections():
|
||||
if not multiplayer.peer_connected.is_connected(on_peer_connected):
|
||||
multiplayer.peer_connected.connect(on_peer_connected)
|
||||
if not multiplayer.peer_disconnected.is_connected(on_peer_disconnected):
|
||||
multiplayer.peer_disconnected.connect(on_peer_disconnected)
|
||||
if not multiplayer.connected_to_server.is_connected(on_connected_to_server):
|
||||
multiplayer.connected_to_server.connect(on_connected_to_server)
|
||||
if not multiplayer.server_disconnected.is_connected(on_server_disconnected):
|
||||
multiplayer.server_disconnected.connect(on_server_disconnected)
|
||||
|
||||
func _disconnect_signals():
|
||||
if multiplayer.peer_connected.is_connected(on_peer_connected):
|
||||
multiplayer.peer_connected.disconnect(on_peer_connected)
|
||||
if multiplayer.peer_disconnected.is_connected(on_peer_disconnected):
|
||||
multiplayer.peer_disconnected.disconnect(on_peer_disconnected)
|
||||
if multiplayer.connected_to_server.is_connected(on_connected_to_server):
|
||||
multiplayer.connected_to_server.disconnect(on_connected_to_server)
|
||||
if multiplayer.server_disconnected.is_connected(on_server_disconnected):
|
||||
multiplayer.server_disconnected.disconnect(on_server_disconnected)
|
||||
|
||||
func on_peer_connected(peer_id: int) -> void:
|
||||
print("Peer %s recieved connection: %s" % [multiplayer.get_unique_id(), peer_id])
|
||||
|
||||
# For each peer that connects, we put them in the queue to spawn
|
||||
print("Peer %s received connection: %s" % [multiplayer.get_unique_id(), peer_id])
|
||||
if multiplayer.is_server():
|
||||
GameManager.queue_spawn_player(peer_id)
|
||||
|
||||
|
||||
func on_peer_disconnected(peer_id: int) -> void:
|
||||
print("Peer %s lost connection to: %s" % [multiplayer.get_unique_id(), peer_id])
|
||||
print(multiplayer.get_peers())
|
||||
# TODO: GameManager should cleanup the player's pawn
|
||||
|
||||
func on_connected_to_server() -> void:
|
||||
print("%s connected to server!" % multiplayer.get_unique_id())
|
||||
# If we are in the main menu, this is the trigger to switch scenes
|
||||
if get_tree().current_scene.name == "MainMenu":
|
||||
get_tree().change_scene_to_file("res://main.tscn")
|
||||
|
||||
func on_server_disconnected() -> void:
|
||||
print("Disconnected from server.")
|
||||
get_tree().change_scene_to_file("res://scenes/UI/main_menu.tscn")
|
||||
@ -42,7 +42,7 @@ func _ready():
|
||||
if physics_mode == PhysicsMode.ANCHORED:
|
||||
_update_gravity_proxy()
|
||||
linear_velocity = gravity_proxy_parent.linear_velocity if is_instance_valid(gravity_proxy_parent) else Vector3.ZERO
|
||||
print(name, " initialized as ANCHORED with gravity proxy: ", gravity_proxy_parent)
|
||||
# print(name, " initialized as ANCHORED with gravity proxy: ", gravity_proxy_parent)
|
||||
|
||||
func _notification(what):
|
||||
# Automatically update gravity proxy when the scene hierarchy changes
|
||||
@ -68,10 +68,10 @@ func _update_gravity_proxy():
|
||||
# 2. Assign the proxy
|
||||
if new_proxy != gravity_proxy_parent:
|
||||
gravity_proxy_parent = new_proxy
|
||||
if new_proxy:
|
||||
print(name, " auto-parented gravity proxy to: ", new_proxy.name)
|
||||
else:
|
||||
print(name, " detached from gravity proxy (Independent Mode).")
|
||||
# if new_proxy:
|
||||
# print(name, " auto-parented gravity proxy to: ", new_proxy.name)
|
||||
# else:
|
||||
# print(name, " detached from gravity proxy (Independent Mode).")
|
||||
|
||||
# --- PUBLIC FORCE APPLICATION METHODS ---
|
||||
|
||||
@ -86,6 +86,7 @@ func _update_mass_and_inertia():
|
||||
|
||||
|
||||
func _integrate_forces(state: PhysicsDirectBodyState3D):
|
||||
# if not is_multiplayer_authority(): return
|
||||
# Safety Check for Division by Zero
|
||||
if mass <= 0.0:
|
||||
accumulated_force = Vector3.ZERO
|
||||
|
||||
@ -58,16 +58,17 @@ func _try_spawn_waiting_player():
|
||||
var player_id = waiting_players.pop_back()
|
||||
|
||||
print("GameManager: Spawner is now available. Spawning waiting player %d." % player_id)
|
||||
var spawn_point = find_available_spawner()
|
||||
var spawn_point: Spawner = find_available_spawner()
|
||||
|
||||
if spawn_point:
|
||||
_spawn_player_pawn(player_id)
|
||||
|
||||
var pawn = player_pawns[player_id]
|
||||
|
||||
pawn.set_multiplayer_authority(player_id)
|
||||
# pawn.set_multiplayer_authority(player_id)
|
||||
|
||||
spawn_point.add_child(pawn)
|
||||
get_node(spawn_point.mp_spawner.spawn_path).add_child(pawn)
|
||||
pawn.global_transform = spawn_point.global_transform
|
||||
|
||||
# Traverse up to find the physics body (Ship/Module) we just spawned inside
|
||||
var parent_body = _get_orbital_body_ancestor(spawn_point)
|
||||
@ -96,7 +97,7 @@ func _spawn_player_pawn(player_id: int):
|
||||
|
||||
player_pawns[player_id] = pawn
|
||||
|
||||
pawn.set_multiplayer_authority(player_id)
|
||||
# pawn.set_multiplayer_authority(player_id)
|
||||
|
||||
print("GameManager: Spawned 3D Pawn for player %d" % player_id)
|
||||
|
||||
|
||||
@ -4,16 +4,33 @@ extends Node3D
|
||||
|
||||
@export_group("System Metadata")
|
||||
@export var system_name: String = "Kepler-186"
|
||||
@export var system_seed: int = 0
|
||||
@export var galactic_coordinates: Vector2i = Vector2i.ZERO
|
||||
|
||||
var system_data: SystemData
|
||||
|
||||
func _ready():
|
||||
# 1. Create the generator tool.
|
||||
|
||||
if multiplayer.is_server():
|
||||
if system_seed == 0:
|
||||
system_seed = randi()
|
||||
seed(system_seed)
|
||||
print("StarSystem (Server): Generating system with seed: %d" % system_seed)
|
||||
|
||||
var generator = StarSystemGenerator.new()
|
||||
system_data = generator.generate(self)
|
||||
|
||||
# At this point, the generator has added children to 'self'.
|
||||
# Because we have a MultiplayerSpawner watching 'self', these new children
|
||||
# will automatically be replicated to connected clients!
|
||||
else:
|
||||
print("StarSystem (Client): Waiting for planets from server...")
|
||||
# The client does NOT generate. It just waits for the Spawner to do its job.
|
||||
# We can reconstruct 'system_data' by scanning children if needed,
|
||||
# or just let GameManager find them via 'get_children()'.
|
||||
|
||||
# 2. Tell the generator to build the system within this StarSystem node.
|
||||
system_data = generator.generate(self)
|
||||
|
||||
# 3. Register the completed system with the GameManager.
|
||||
GameManager.register_star_system(self)
|
||||
|
||||
15
src/scripts/star_system.tscn
Normal file
15
src/scripts/star_system.tscn
Normal file
@ -0,0 +1,15 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://b554pkth6hox4"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bkcouefvi7iup" path="res://scripts/star_system.gd" id="1_gbrlo"]
|
||||
|
||||
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_gbrlo"]
|
||||
|
||||
[node name="StarSystem" type="Node3D" unique_id=1547322980]
|
||||
script = ExtResource("1_gbrlo")
|
||||
|
||||
[node name="MultiplayerSpawner" type="MultiplayerSpawner" parent="." unique_id=1117979460]
|
||||
_spawnable_scenes = PackedStringArray("uid://dv18eg4xrlefe", "uid://b7bh45nrtdom5", "uid://bkwogkfqk2uxo")
|
||||
spawn_path = NodePath("..")
|
||||
|
||||
[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="." unique_id=801189521]
|
||||
replication_config = SubResource("SceneReplicationConfig_gbrlo")
|
||||
@ -11,6 +11,7 @@ const MAX_PLANETS = 8
|
||||
const MAX_MOONS_PER_PLANET = 5
|
||||
const ORBIT_SAFETY_FACTOR = 5
|
||||
|
||||
var BarycenterScene: PackedScene = preload("res://scenes/celestial_bodies/barycenter.tscn")
|
||||
var CelestialBodyScene: PackedScene = preload("res://scenes/celestial_bodies/celestial_body.tscn")
|
||||
|
||||
func generate(star_system: StarSystem) -> SystemData:
|
||||
@ -20,7 +21,7 @@ func generate(star_system: StarSystem) -> SystemData:
|
||||
|
||||
system_data.star = star
|
||||
star.name = "Star"
|
||||
star.set_radius(2000.0)
|
||||
star.radius = 2000.0
|
||||
star.base_mass = STAR_MASS
|
||||
star_system.add_child(star)
|
||||
|
||||
@ -28,12 +29,12 @@ func generate(star_system: StarSystem) -> SystemData:
|
||||
var current_orbit_radius = 15000.0
|
||||
|
||||
for i in range(num_planets):
|
||||
var planet_barycenter = Barycenter.new()
|
||||
var planet_barycenter = BarycenterScene.instantiate()
|
||||
planet_barycenter.name = "PlanetSystem_%d" % (i + 1)
|
||||
star_system.add_child(planet_barycenter)
|
||||
|
||||
var planet: CelestialBody = CelestialBodyScene.instantiate()
|
||||
planet.set_radius(randf_range(50.0, 200.0))
|
||||
planet.radius = randf_range(50.0, 200.0)
|
||||
system_data.planets.append(planet)
|
||||
planet.name = "Planet_%d" % (i + 1)
|
||||
planet.base_mass = randf_range(PLANET_MASS * 0.2, PLANET_MASS * 5.0)
|
||||
@ -69,7 +70,7 @@ func _generate_moons(planet: OrbitalBody3D, planet_barycenter: Barycenter, syste
|
||||
|
||||
for i in range(num_moons):
|
||||
var moon = CelestialBodyScene.instantiate()
|
||||
moon.set_radius(10.0)
|
||||
moon.radius = 10.0
|
||||
system_data.moons.append(moon)
|
||||
planet_barycenter.add_child(moon)
|
||||
planet_barycenter.recalculate_total_mass()
|
||||
|
||||
Reference in New Issue
Block a user