This commit is contained in:
2025-02-19 17:33:03 +08:00
parent 46f1bdf8a8
commit f9e0c81aee
2 changed files with 6038 additions and 44 deletions
+79 -44
View File
@@ -26,6 +26,9 @@
# [ ] Reskin the 3D models with offline prototype assets
# [ ] Implement the statemachine animation for the character
# -------------------------------------------------------------------------------------
# [ ] Implement specialty character with unique ability
# [ ] Implement the sabotage meter
# -------------------------------------------------------------------------------------
extends Node3D
@@ -89,6 +92,8 @@ func _process(delta):
if multiplayer.is_server() and game_started:
if turn_based_mode:
rpc("sync_turn_index", current_turn_index)
# Sync all players' goals to the new peer
update_all_players_goals()
func setup_action_buttons():
move_button.pressed.connect(func(): set_action_state(ActionState.MOVING))
@@ -324,18 +329,37 @@ func _on_peer_connected(new_peer_id):
rpc_id(new_peer_id, "sync_game_state", players, bots, game_started, turn_based_mode)
# Then add players in correct order
for peer_id in connected_peer_ids:
rpc_id(new_peer_id, "add_player_character", peer_id)
for peer_id in players:
if peer_id != new_peer_id: # Don't add the new player yet
rpc_id(new_peer_id, "add_player_character", peer_id)
# Sync existing player's goals immediately
var player = get_node_or_null(str(peer_id))
if player:
rpc_id(new_peer_id, "sync_player_goals", peer_id, player.goals)
# Finally add the new player
add_player_character(new_peer_id)
rpc("add_newly_connected_player_character", new_peer_id)
replace_bot_with_player(new_peer_id)
# Sync all players' goals to the new peer
for player in get_tree().get_nodes_in_group("Players"):
var player_id = String(player.name).to_int() # Convert StringName to String first, then to int
rpc_id(new_peer_id, "sync_player_goals", player_id, player.goals)
# Get next available bot ID and replace it
if bots.size() > 0:
replace_bot_with_player(new_peer_id)
# Force sync all players' goals to everyone
for player in get_tree().get_nodes_in_group("Players"):
var player_id = String(player.name).to_int()
rpc("sync_player_goals", player_id, player.goals)
# Update everyone's UI
rpc("force_update_all_goals")
@rpc("call_local")
func force_update_all_goals():
# Force update the UI for all players
update_all_players_goals()
# Also update the boards
update_all_players_boards()
func _on_peer_disconnected(peer_id):
if multiplayer.is_server():
@@ -356,7 +380,6 @@ func add_player_character(peer_id):
add_child(player_character)
player_character.add_to_group("Players", true)
# Set goals based on player ID if server
if multiplayer.is_server():
var goal_index = peer_id - 1
@@ -665,56 +688,68 @@ func update_board_slot(board_ui: Node, slot_idx: int, value: int):
10: slot_node.get_node("TileCoin").show()
func update_all_players_goals():
if not game_started and not multiplayer.is_server():
# Only server/host should manage goals display
if not game_started:
return
var all_players = get_tree().get_nodes_in_group("Players")
# Fix: Convert name to string and handle potential scene-unique names properly
all_players.sort_custom(func(a, b):
var a_str = String(a.name).get_slice("@", 0) # Explicitly convert StringName to String
var a_str = String(a.name).get_slice("@", 0)
var b_str = String(b.name).get_slice("@", 0)
return int(a_str) < int(b_str)
)
# Force clear all goals first
for i in range(4): # 4 goal boards
var goals_grid = $AllPlayerGoals.get_child(i)
for slot_idx in range(9): # 9 slots per goal board
var slot = goals_grid.get_child(slot_idx)
for tile in ["TileHeart", "TileDiamond", "TileStar", "TileCoin"]:
slot.get_node(tile).hide()
# Then update with current player goals
for i in range(min(all_players.size(), 4)):
var player = all_players[i]
if player and player.goals.size() > 0:
_update_player_goals_ui(i, player.goals)
# If we're the host, update all goals and sync to clients
if multiplayer.is_server():
# Clear all goals first
for player_idx in range(4):
var goals_grid = $AllPlayerGoals.get_child(player_idx)
for slot_idx in range(9):
var slot = goals_grid.get_child(slot_idx)
for tile in ["TileHeart", "TileDiamond", "TileStar", "TileCoin"]:
slot.get_node(tile).hide()
# Update with current goals and gather goals data
var all_goals_data = []
for i in range(min(all_players.size(), 4)):
var player = all_players[i]
if player and player.goals.size() > 0:
_update_player_goals_ui(i, player.goals)
all_goals_data.append({"player_idx": i, "goals": player.goals.duplicate()})
else:
all_goals_data.append({"player_idx": i, "goals": []})
# Sync to clients
rpc("sync_all_goals_to_clients", all_goals_data)
@rpc("reliable")
func sync_all_goals_to_clients(all_goals_data: Array):
if not multiplayer.is_server(): # Only clients should process this
# Clear all goals first
for player_idx in range(4):
var goals_grid = $AllPlayerGoals.get_child(player_idx)
for slot_idx in range(9):
var slot = goals_grid.get_child(slot_idx)
for tile in ["TileHeart", "TileDiamond", "TileStar", "TileCoin"]:
slot.get_node(tile).hide()
# Apply received goals
for goal_data in all_goals_data:
var player_idx = goal_data["player_idx"]
var goals = goal_data["goals"]
if player_idx >= 0 and player_idx < 4 and goals.size() > 0:
_update_player_goals_ui(player_idx, goals)
@rpc("any_peer", "call_local")
func sync_player_goals(player_id: int, goals: Array):
# Update the player's goals first
# Update the player's goals in their node
var player = get_node_or_null(str(player_id))
if player:
player.goals = goals.duplicate()
# Get player index in current players list
var player_idx = -1
var sorted_players = get_tree().get_nodes_in_group("Players")
sorted_players.sort_custom(func(a, b):
return int(String(a.name).get_slice("@", 0)) < int(String(b.name).get_slice("@", 0))
)
for idx in range(sorted_players.size()):
if sorted_players[idx] == player:
player_idx = idx
break
if player_idx >= 0 and player_idx < 4:
_update_player_goals_ui(player_idx, goals)
# Update full UI if we're the server or if this is our local player
if multiplayer.is_server() or player_id == multiplayer.get_unique_id():
update_all_players_goals()
# Only server should update the UI directly
if multiplayer.is_server():
update_all_players_goals()
# Helper function to update specific player's goals UI
func _update_player_goals_ui(player_idx: int, goals: Array):