fix: create local player on client so WASD movement works
client_main.gd: when server spawns our player, create a player node with authority - Camera follows local player from 3/4 overhead view - player.gd WASD input sends position to server via RPC - Server validates and broadcasts to all peers
This commit is contained in:
@@ -22,6 +22,10 @@ extends Node3D
|
||||
var remote_players: Dictionary = {}
|
||||
var connected: bool = false
|
||||
|
||||
# Our local player node (created when server spawns us)
|
||||
var _local_player: Node = null
|
||||
var _camera: Camera3D = null
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Lifecycle
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -45,8 +49,17 @@ func _connect_to_server() -> void:
|
||||
_connect_to_server()
|
||||
return
|
||||
|
||||
# Setup camera and lights
|
||||
_setup_scene()
|
||||
# Setup camera (fixed overhead until a player is spawned)
|
||||
_camera = _make_camera()
|
||||
add_child(_camera)
|
||||
|
||||
# Ambient light so we can see the box meshes
|
||||
var light := DirectionalLight3D.new()
|
||||
light.light_energy = 1.0
|
||||
light.shadow_enabled = true
|
||||
light.position = Vector3(10, 20, 10)
|
||||
add_child(light)
|
||||
light.look_at(Vector3.ZERO)
|
||||
|
||||
connected = true
|
||||
|
||||
@@ -57,31 +70,41 @@ func _connect_to_server() -> void:
|
||||
|
||||
print("[ClientMain] Connected to server. Peer ID: %d" % multiplayer.get_unique_id())
|
||||
|
||||
func _setup_scene() -> void:
|
||||
# Simple 3/4 top-down camera for Phase 0 testing
|
||||
var camera := Camera3D.new()
|
||||
camera.current = true
|
||||
camera.position = Vector3(0, 16, 12)
|
||||
camera.rotation_degrees.x = -55
|
||||
add_child(camera)
|
||||
|
||||
# Ambient light so we can see the box meshes
|
||||
var light := DirectionalLight3D.new()
|
||||
light.light_energy = 1.0
|
||||
light.shadow_enabled = true
|
||||
light.position = Vector3(10, 20, 10)
|
||||
add_child(light)
|
||||
light.look_at(Vector3.ZERO)
|
||||
func _make_camera() -> Camera3D:
|
||||
var cam := Camera3D.new()
|
||||
cam.current = true
|
||||
cam.position = Vector3(0, 16, 12)
|
||||
cam.rotation_degrees.x = -55
|
||||
return cam
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
# Make camera follow local player if we have one
|
||||
if _local_player and _camera:
|
||||
_camera.position = _local_player.position + Vector3(0, 16, 12)
|
||||
# Always look down at the player
|
||||
var look_target := _local_player.position
|
||||
look_target.y = _local_player.position.y + 2.0
|
||||
_camera.look_at(look_target)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Player replication handlers (called when server broadcasts via RPC)
|
||||
# ---------------------------------------------------------------------------
|
||||
func _on_remote_player_spawned(peer_id: int, pos: Vector3) -> void:
|
||||
if peer_id == multiplayer.get_unique_id():
|
||||
# This is OUR player — the server has authority over it,
|
||||
# but we don't need to create a duplicate. Our local player
|
||||
# node is managed by the server's authority system.
|
||||
# The player.gd script will handle input on this peer.
|
||||
# THIS IS OUR PLAYER — create a local player node and attach camera.
|
||||
# The player.gd script handles WASD input and sends position to server.
|
||||
if _local_player:
|
||||
push_warning("[ClientMain] Local player already exists, respawning")
|
||||
_local_player.queue_free()
|
||||
|
||||
_local_player = player_scene.instantiate()
|
||||
_local_player.name = "LocalPlayer"
|
||||
_local_player.position = pos
|
||||
# Set authority so player.gd detects is_local = true and enables input
|
||||
_local_player.set_multiplayer_authority(peer_id)
|
||||
add_child(_local_player, true)
|
||||
|
||||
print("[ClientMain] Spawned LOCAL player at (%.1f, %.1f)" % [pos.x, pos.z])
|
||||
return
|
||||
|
||||
if peer_id in remote_players:
|
||||
@@ -107,6 +130,11 @@ func _on_remote_player_spawned(peer_id: int, pos: Vector3) -> void:
|
||||
|
||||
func _on_remote_player_despawned(peer_id: int) -> void:
|
||||
if peer_id == multiplayer.get_unique_id():
|
||||
# Our player was despawned
|
||||
if _local_player:
|
||||
_local_player.queue_free()
|
||||
_local_player = null
|
||||
print("[ClientMain] Local player despawned")
|
||||
return
|
||||
|
||||
if peer_id in remote_players:
|
||||
@@ -118,7 +146,9 @@ func _exit_tree() -> void:
|
||||
if connected:
|
||||
NetworkManager.stop()
|
||||
|
||||
# Clean up any remaining remote players
|
||||
# Clean up any remaining players
|
||||
if _local_player:
|
||||
_local_player.queue_free()
|
||||
for p in remote_players.values():
|
||||
p.queue_free()
|
||||
remote_players.clear()
|
||||
|
||||
Reference in New Issue
Block a user