feat: Implement core game scene logic in main.gd and introduce goals_cycle_manager.gd for managing game goals and cycles.
This commit is contained in:
+4
-1
@@ -1463,7 +1463,10 @@ func sync_player_goals(player_id: int, goals: Array):
|
|||||||
call_deferred("_deferred_set_player_goals", player_id, goals)
|
call_deferred("_deferred_set_player_goals", player_id, goals)
|
||||||
|
|
||||||
func _deferred_set_player_goals(player_id: int, goals: Array):
|
func _deferred_set_player_goals(player_id: int, goals: Array):
|
||||||
await get_tree().create_timer(0.25).timeout
|
# Reduce delay to 0.05s for snappier updates (just enough to ensure nodes are in tree)
|
||||||
|
if not get_node_or_null(str(player_id)):
|
||||||
|
await get_tree().create_timer(0.1).timeout
|
||||||
|
|
||||||
var player = get_node_or_null(str(player_id))
|
var player = get_node_or_null(str(player_id))
|
||||||
if player and player.race_manager:
|
if player and player.race_manager:
|
||||||
player.goals = goals.duplicate()
|
player.goals = goals.duplicate()
|
||||||
|
|||||||
@@ -214,9 +214,60 @@ func sync_cycle_end():
|
|||||||
|
|
||||||
func on_goal_completed(player: Node, time_remaining: float):
|
func on_goal_completed(player: Node, time_remaining: float):
|
||||||
"""Called when a player completes their goal pattern."""
|
"""Called when a player completes their goal pattern."""
|
||||||
|
|
||||||
|
# 1. LOCAL OPTIMISTIC UPDATE (for smoothness)
|
||||||
|
if player.is_multiplayer_authority() and not multiplayer.is_server():
|
||||||
|
_handle_local_goal_completion(player, time_remaining)
|
||||||
|
return
|
||||||
|
|
||||||
if not multiplayer.is_server():
|
if not multiplayer.is_server():
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# SERVER LOGIC continues...
|
||||||
|
_process_goal_completion(player, time_remaining)
|
||||||
|
|
||||||
|
func _handle_local_goal_completion(player: Node, time_remaining: float):
|
||||||
|
print("[GoalsCycle] Client: Handling goal completion locally for smoothness.")
|
||||||
|
|
||||||
|
# Clear playerboard locally
|
||||||
|
player.playerboard.fill(-1)
|
||||||
|
|
||||||
|
# Generate new goals locally (optimistic)
|
||||||
|
var new_goals = GoalManager.initialize_random_goals(9, 7, 10, 1.0)
|
||||||
|
var int_goals: Array[int] = []
|
||||||
|
for g in new_goals:
|
||||||
|
int_goals.append(g)
|
||||||
|
player.goals = int_goals
|
||||||
|
|
||||||
|
# Update UI immediately
|
||||||
|
if main_scene and main_scene.ui_manager:
|
||||||
|
main_scene.ui_manager.update_playerboard_ui()
|
||||||
|
|
||||||
|
# Notify server to sync score and broadcast to others
|
||||||
|
rpc_id(1, "request_server_goal_completion", time_remaining, int_goals)
|
||||||
|
|
||||||
|
# Visual/Sfx
|
||||||
|
SfxManager.play("complete_mission")
|
||||||
|
|
||||||
|
@rpc("any_peer")
|
||||||
|
func request_server_goal_completion(time_remaining: float, client_generated_goals: Array):
|
||||||
|
if not multiplayer.is_server(): return
|
||||||
|
|
||||||
|
var sender_id = multiplayer.get_remote_sender_id()
|
||||||
|
# Bots call it locally, so sender_id might be 1 or 0
|
||||||
|
if sender_id == 0: sender_id = 1
|
||||||
|
|
||||||
|
var player_node = main_scene.get_node_or_null(str(sender_id))
|
||||||
|
if player_node:
|
||||||
|
# Use provided goals from client to ensure sync
|
||||||
|
var int_goals: Array[int] = []
|
||||||
|
for g in client_generated_goals: int_goals.append(g)
|
||||||
|
|
||||||
|
# Process completion with provided goals
|
||||||
|
_process_goal_completion(player_node, time_remaining, int_goals)
|
||||||
|
|
||||||
|
func _process_goal_completion(player: Node, time_remaining: float, provided_goals: Array = []):
|
||||||
|
"""Internal server-side logic for completion rewards and broadcasting."""
|
||||||
# Use name.to_int() for ID because bots share authority 1
|
# Use name.to_int() for ID because bots share authority 1
|
||||||
var peer_id = player.name.to_int()
|
var peer_id = player.name.to_int()
|
||||||
|
|
||||||
@@ -242,18 +293,23 @@ func on_goal_completed(player: Node, time_remaining: float):
|
|||||||
rpc("sync_player_score", peer_id, player_scores[peer_id])
|
rpc("sync_player_score", peer_id, player_scores[peer_id])
|
||||||
rpc("sync_goal_count", peer_id, player_goal_counts[peer_id])
|
rpc("sync_goal_count", peer_id, player_goal_counts[peer_id])
|
||||||
|
|
||||||
# Clear playerboard tiles (they convert to powerup bar reward)
|
# Clear playerboard tiles
|
||||||
player.playerboard.fill(-1)
|
player.playerboard.fill(-1)
|
||||||
# Use main scene's RPC which properly looks up player by ID on each client
|
|
||||||
if main_scene:
|
if main_scene:
|
||||||
main_scene.rpc("sync_playerboard", peer_id, player.playerboard)
|
main_scene.rpc("sync_playerboard", peer_id, player.playerboard)
|
||||||
|
|
||||||
# Regenerate goals for this player
|
# Regenerate goals for this player (or use provided ones)
|
||||||
regenerate_goals_for_player(player)
|
if provided_goals.size() > 0:
|
||||||
|
player.goals = provided_goals
|
||||||
|
if main_scene:
|
||||||
|
main_scene.rpc("sync_player_goals", peer_id, provided_goals)
|
||||||
|
else:
|
||||||
|
regenerate_goals_for_player(player)
|
||||||
|
|
||||||
# Randomize 9 tiles around player
|
# Randomize tiles around player
|
||||||
_randomize_tiles_around_player(player)
|
_randomize_tiles_around_player(player)
|
||||||
|
|
||||||
|
# Only play RPC if not already handled locally by that player
|
||||||
SfxManager.rpc("play_rpc", "complete_mission")
|
SfxManager.rpc("play_rpc", "complete_mission")
|
||||||
print("[GoalsCycle] Player %d completed goal! +%d points (base: %d, time bonus: %d)" % [peer_id, score_earned, BASE_SCORE, time_bonus])
|
print("[GoalsCycle] Player %d completed goal! +%d points (base: %d, time bonus: %d)" % [peer_id, score_earned, BASE_SCORE, time_bonus])
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user