feat: Implement Nakama serialization, Realtime API, and a comprehensive lobby system with UI and player management.
This commit is contained in:
+50
-6
@@ -13,7 +13,20 @@ var powerup_manager
|
||||
var score: int = 0
|
||||
|
||||
# Display name (synced across network)
|
||||
var display_name: String = ""
|
||||
var _display_name: String = ""
|
||||
var display_name: String:
|
||||
set(value):
|
||||
_display_name = value
|
||||
# Update label if it exists
|
||||
var name_label = get_node_or_null("Name")
|
||||
if name_label:
|
||||
name_label.text = _display_name
|
||||
|
||||
# Sync to other peers if we are authority
|
||||
if is_multiplayer_authority() and is_inside_tree():
|
||||
rpc("sync_display_name", _display_name)
|
||||
get:
|
||||
return _display_name
|
||||
|
||||
# Special effect states
|
||||
var is_frozen: bool = false
|
||||
@@ -262,6 +275,11 @@ func _ready():
|
||||
rpc("sync_position", current_position)
|
||||
else:
|
||||
target_visual_position = global_position
|
||||
# If random spawn is enabled, do NOT broadcast (0,0). Wait for set_spawn_position.
|
||||
|
||||
# Prevent visual "jump" by hiding until spawn position is confirmed
|
||||
if LobbyManager.get_randomize_spawn() and not spawn_point_selected:
|
||||
visible = false
|
||||
|
||||
func _init_managers():
|
||||
movement_manager = load("res://scripts/managers/player_movement_manager.gd").new()
|
||||
@@ -588,8 +606,9 @@ func sync_bot_status(is_bot_status: bool):
|
||||
@rpc("any_peer", "call_local", "reliable")
|
||||
func sync_display_name(new_name: String) -> void:
|
||||
"""Sync display name across network."""
|
||||
display_name = new_name
|
||||
$Name.text = display_name
|
||||
_display_name = new_name
|
||||
if has_node("Name"):
|
||||
$Name.text = _display_name
|
||||
|
||||
@rpc("any_peer", "call_local", "reliable")
|
||||
func sync_modulate(color: Color) -> void:
|
||||
@@ -893,6 +912,11 @@ func activate_powerup(effect_id: int):
|
||||
|
||||
|
||||
func _process(delta):
|
||||
# Failsafe: Ensure player is visible if spawn point is selected and random spawn is active
|
||||
# This handles race conditions where set_spawn_position might be called before _ready finishes hiding
|
||||
if LobbyManager.get_randomize_spawn() and spawn_point_selected and not visible:
|
||||
visible = true
|
||||
|
||||
if is_multiplayer_authority():
|
||||
# Visual debugging - show display name with connection status
|
||||
$Name.text = display_name if not display_name.is_empty() else str(name)
|
||||
@@ -906,8 +930,11 @@ func _process(delta):
|
||||
# Client-side visual smoothing
|
||||
# Only interpolate if NOT running a movement tween, OR if the drift is large (teleport/snap)
|
||||
if not is_player_moving:
|
||||
# Snap to target if very close (prevents micro-jitter)
|
||||
if global_position.distance_squared_to(target_visual_position) < 0.001:
|
||||
var dist_sq = global_position.distance_squared_to(target_visual_position)
|
||||
|
||||
if dist_sq > 4.0: # If distance > 2.0 units (teleport/spawn), snap immediately
|
||||
global_position = target_visual_position
|
||||
elif dist_sq < 0.001: # Prevent micro-jitter
|
||||
global_position = target_visual_position
|
||||
else:
|
||||
# Interpolate towards the target position received from authority
|
||||
@@ -1157,6 +1184,12 @@ func start_movement_along_path(path: Array, clear_visual: bool = true):
|
||||
is_player_moving = true
|
||||
if path.size() > 0:
|
||||
target_position = Vector2i(path[-1].x, path[-1].y)
|
||||
|
||||
# FORCE SNAP START: Ensure we start animating from our actual grid position
|
||||
# This prevents "jumps" if the visual node drifted or was set via global_position vs position mismatch
|
||||
var start_world_pos = grid_to_world(current_position)
|
||||
if global_position.distance_squared_to(start_world_pos) > 0.001:
|
||||
global_position = start_world_pos
|
||||
|
||||
var tween = create_tween()
|
||||
tween.set_trans(Tween.TRANS_LINEAR)
|
||||
@@ -1167,7 +1200,8 @@ func start_movement_along_path(path: Array, clear_visual: bool = true):
|
||||
step_duration = step_duration / movement_manager.speed_multiplier
|
||||
|
||||
for point in path:
|
||||
tween.tween_property(self, "position", grid_to_world(Vector2i(point.x, point.y)), step_duration)
|
||||
# Use global_position for consistency
|
||||
tween.tween_property(self, "global_position", grid_to_world(Vector2i(point.x, point.y)), step_duration)
|
||||
|
||||
tween.tween_callback(func():
|
||||
current_position = Vector2i(path[-1].x, path[-1].y)
|
||||
@@ -1739,6 +1773,13 @@ func update_visual_position():
|
||||
@rpc("any_peer", "call_local")
|
||||
func sync_position(pos: Vector2i):
|
||||
current_position = pos
|
||||
|
||||
# If random spawn is active, receiving a position sync essentially confirms a valid spawn
|
||||
if LobbyManager.get_randomize_spawn():
|
||||
spawn_point_selected = true
|
||||
if not visible:
|
||||
visible = true
|
||||
|
||||
# Always update the visual position after position sync
|
||||
var new_pos = Vector3(
|
||||
current_position.x * cell_size.x + cell_size.x * 0.5,
|
||||
@@ -1767,6 +1808,9 @@ func set_spawn_position(pos: Vector2i):
|
||||
|
||||
global_position = new_pos
|
||||
target_visual_position = new_pos
|
||||
|
||||
# Reveal character now that it's in the correct position
|
||||
visible = true
|
||||
|
||||
|
||||
@rpc("any_peer", "call_local", "reliable")
|
||||
|
||||
Reference in New Issue
Block a user