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:
Yogi Wiguna
2026-03-23 17:45:16 +08:00
parent 7f1ae0f757
commit 75a636c97c
2 changed files with 65 additions and 6 deletions
+61 -5
View File
@@ -214,9 +214,60 @@ func sync_cycle_end():
func on_goal_completed(player: Node, time_remaining: float):
"""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():
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
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_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)
# Use main scene's RPC which properly looks up player by ID on each client
if main_scene:
main_scene.rpc("sync_playerboard", peer_id, player.playerboard)
# Regenerate goals for this player
regenerate_goals_for_player(player)
# Regenerate goals for this player (or use provided ones)
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)
# Only play RPC if not already handled locally by that player
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])