fix the instance of player
This commit is contained in:
+283
-28
@@ -40,6 +40,7 @@ const ADDRESS = "127.0.0.1"
|
||||
@export var enable_bots: bool = true # Add this line
|
||||
|
||||
var connected_peer_ids = []
|
||||
var _connection_check_timer: float = 0.0
|
||||
var local_player_character : CharacterBody3D
|
||||
var player_scene = preload("res://scenes/player.tscn")
|
||||
var current_turn_index = 0
|
||||
@@ -94,6 +95,28 @@ func _process(delta):
|
||||
rpc("sync_turn_index", current_turn_index)
|
||||
# Sync all players' goals to the new peer
|
||||
update_all_players_goals()
|
||||
|
||||
# Also periodically verify client connections
|
||||
_connection_check_timer += delta
|
||||
if _connection_check_timer >= 5.0:
|
||||
_connection_check_timer = 0.0
|
||||
verify_all_connections()
|
||||
|
||||
func verify_all_connections():
|
||||
if multiplayer.is_server():
|
||||
for peer_id in players:
|
||||
if peer_id != 1: # Skip server
|
||||
# Ping each client
|
||||
rpc_id(peer_id, "connection_verify", players)
|
||||
|
||||
@rpc
|
||||
func connection_verify(expected_players: Array):
|
||||
# Client checks if it has all expected players
|
||||
for peer_id in expected_players:
|
||||
if peer_id != multiplayer.get_unique_id() and not has_node(str(peer_id)):
|
||||
# Missing a player - request it
|
||||
rpc_id(1, "request_specific_player_data", peer_id)
|
||||
print("Requesting missing player: ", peer_id)
|
||||
|
||||
func setup_action_buttons():
|
||||
move_button.pressed.connect(func(): set_action_state(ActionState.MOVING))
|
||||
@@ -319,49 +342,251 @@ func _on_join_pressed():
|
||||
multiplayer_peer.create_client(ADDRESS, PORT)
|
||||
multiplayer.multiplayer_peer = multiplayer_peer
|
||||
$NetworkInfo/UniquePeerID.text = str(multiplayer.get_unique_id())
|
||||
# After connection is established
|
||||
await get_tree().create_timer(2.0).timeout
|
||||
rpc_id(1, "request_full_player_sync", multiplayer.get_unique_id())
|
||||
|
||||
#func _on_peer_connected(new_peer_id):
|
||||
#if multiplayer.is_server():
|
||||
## Increase delay to ensure scene is ready
|
||||
#await get_tree().create_timer(1.5).timeout
|
||||
#
|
||||
## First sync game state
|
||||
#rpc_id(new_peer_id, "sync_game_state", players, bots, game_started, turn_based_mode)
|
||||
#rpc_id(new_peer_id, "sync_preset_goals", preset_goals)
|
||||
#
|
||||
## Wait a bit for the client to process state
|
||||
#await get_tree().create_timer(0.5).timeout
|
||||
#
|
||||
## Then sync all existing players in order
|
||||
#var sorted_players = players.duplicate()
|
||||
#sorted_players.sort()
|
||||
#for peer_id in sorted_players:
|
||||
#if peer_id != new_peer_id:
|
||||
## First ensure player exists
|
||||
#var player = get_node_or_null(str(peer_id))
|
||||
#if player:
|
||||
## Sync player's full state
|
||||
#var player_data = {
|
||||
#"position": player.current_position,
|
||||
#"goals": player.goals,
|
||||
#"playerboard": player.playerboard
|
||||
#}
|
||||
#rpc_id(new_peer_id, "sync_existing_player", peer_id, player_data)
|
||||
#await get_tree().create_timer(0.1).timeout # Small delay between players
|
||||
#
|
||||
## Finally add the new player
|
||||
#await get_tree().create_timer(0.5).timeout
|
||||
#add_player_character(new_peer_id)
|
||||
#rpc("add_newly_connected_player_character", new_peer_id)
|
||||
#
|
||||
## Replace bot if needed
|
||||
#if bots.size() > 0:
|
||||
#replace_bot_with_player(new_peer_id)
|
||||
#
|
||||
## Final sync of all goals
|
||||
#await get_tree().create_timer(0.5).timeout
|
||||
#rpc("force_update_all_goals")
|
||||
|
||||
func _on_peer_connected(new_peer_id):
|
||||
if multiplayer.is_server():
|
||||
# Increase delay to ensure scene is ready
|
||||
# Create a more robust state sync process
|
||||
await get_tree().create_timer(1.5).timeout
|
||||
|
||||
# First sync game state
|
||||
rpc_id(new_peer_id, "sync_game_state", players, bots, game_started, turn_based_mode)
|
||||
rpc_id(new_peer_id, "sync_preset_goals", preset_goals)
|
||||
# First sync complete game state
|
||||
var complete_state = {
|
||||
"players": players,
|
||||
"bots": bots,
|
||||
"game_started": game_started,
|
||||
"turn_based": turn_based_mode,
|
||||
"preset_goals": preset_goals,
|
||||
"player_states": {}
|
||||
}
|
||||
|
||||
# Wait a bit for the client to process state
|
||||
await get_tree().create_timer(0.5).timeout
|
||||
# Gather all existing player states
|
||||
for peer_id in players:
|
||||
var player = get_node_or_null(str(peer_id))
|
||||
if player:
|
||||
complete_state["player_states"][peer_id] = {
|
||||
"position": player.current_position,
|
||||
"goals": player.goals,
|
||||
"playerboard": player.playerboard,
|
||||
"is_bot": player.is_bot || player.is_in_group("Bots")
|
||||
}
|
||||
|
||||
# Then sync all existing players in order
|
||||
var sorted_players = players.duplicate()
|
||||
sorted_players.sort()
|
||||
for peer_id in sorted_players:
|
||||
if peer_id != new_peer_id:
|
||||
# First ensure player exists
|
||||
var player = get_node_or_null(str(peer_id))
|
||||
if player:
|
||||
# Sync player's full state
|
||||
var player_data = {
|
||||
"position": player.current_position,
|
||||
"goals": player.goals,
|
||||
"playerboard": player.playerboard
|
||||
}
|
||||
rpc_id(new_peer_id, "sync_existing_player", peer_id, player_data)
|
||||
await get_tree().create_timer(0.1).timeout # Small delay between players
|
||||
# Send complete state in one RPC
|
||||
rpc_id(new_peer_id, "receive_complete_game_state", complete_state)
|
||||
|
||||
# Finally add the new player
|
||||
await get_tree().create_timer(0.5).timeout
|
||||
add_player_character(new_peer_id)
|
||||
rpc("add_newly_connected_player_character", new_peer_id)
|
||||
|
||||
# Replace bot if needed
|
||||
if bots.size() > 0:
|
||||
replace_bot_with_player(new_peer_id)
|
||||
# Make sure all clients know about all players
|
||||
rpc("sync_complete_player_list", players)
|
||||
|
||||
## Replace bot if needed
|
||||
#if bots.size() > 0:
|
||||
#replace_bot_with_player(new_peer_id)
|
||||
#
|
||||
# Final sync of all goals
|
||||
await get_tree().create_timer(0.5).timeout
|
||||
rpc("force_update_all_goals")
|
||||
|
||||
@rpc("reliable")
|
||||
func sync_complete_player_list(player_list: Array):
|
||||
# Ensure we have all players in our list
|
||||
players = player_list.duplicate()
|
||||
|
||||
# Check which players we don't have nodes for
|
||||
for peer_id in players:
|
||||
if not has_node(str(peer_id)) and peer_id != multiplayer.get_unique_id():
|
||||
# Request this specific player's data from server
|
||||
rpc_id(1, "request_specific_player_data", peer_id)
|
||||
|
||||
@rpc("any_peer")
|
||||
func request_specific_player_data(requested_peer_id: int):
|
||||
if multiplayer.is_server():
|
||||
var player = get_node_or_null(str(requested_peer_id))
|
||||
if player:
|
||||
var player_data = {
|
||||
"peer_id": requested_peer_id,
|
||||
"position": player.current_position,
|
||||
"goals": player.goals,
|
||||
"playerboard": player.playerboard,
|
||||
"is_bot": player.is_bot || player.is_in_group("Bots")
|
||||
}
|
||||
|
||||
# Send to the requesting client only
|
||||
rpc_id(multiplayer.get_remote_sender_id(), "create_specific_player", player_data)
|
||||
|
||||
@rpc("any_peer")
|
||||
func request_full_player_sync(requesting_peer_id):
|
||||
if multiplayer.is_server():
|
||||
print("Full sync requested by: ", requesting_peer_id)
|
||||
|
||||
# Send the complete list of players
|
||||
rpc_id(requesting_peer_id, "sync_complete_player_list", players)
|
||||
|
||||
# Send each player's data
|
||||
for peer_id in players:
|
||||
var player = get_node_or_null(str(peer_id))
|
||||
if player:
|
||||
var player_data = {
|
||||
"peer_id": peer_id,
|
||||
"position": player.current_position,
|
||||
"goals": player.goals,
|
||||
"playerboard": player.playerboard,
|
||||
"is_bot": player.is_bot || player.is_in_group("Bots")
|
||||
}
|
||||
rpc_id(requesting_peer_id, "create_specific_player", player_data)
|
||||
|
||||
# Allow a short delay between player creations
|
||||
await get_tree().create_timer(0.1).timeout
|
||||
|
||||
@rpc("reliable")
|
||||
func create_specific_player(data: Dictionary):
|
||||
var peer_id = data["peer_id"]
|
||||
|
||||
# Don't create if already exists
|
||||
if has_node(str(peer_id)):
|
||||
return
|
||||
|
||||
# Create the player
|
||||
var player_character = player_scene.instantiate()
|
||||
player_character.set_multiplayer_authority(peer_id)
|
||||
player_character.name = str(peer_id)
|
||||
|
||||
# Set properties before adding to tree
|
||||
player_character.current_position = data["position"]
|
||||
|
||||
# Add to scene
|
||||
add_child(player_character)
|
||||
|
||||
# Apply properties after adding
|
||||
player_character.add_to_group("Players", true)
|
||||
if data["is_bot"]:
|
||||
player_character.add_to_group("Bots", true)
|
||||
player_character.is_bot = true
|
||||
player_character.rpc("sync_bot_status", true)
|
||||
|
||||
# Apply data
|
||||
player_character.goals = data["goals"].duplicate()
|
||||
player_character.playerboard = data["playerboard"].duplicate()
|
||||
|
||||
# Force position sync
|
||||
player_character.global_position = Vector3(
|
||||
data["position"].x * 2 + 1,
|
||||
1.0,
|
||||
data["position"].y * 2 + 1
|
||||
)
|
||||
player_character.rpc("sync_position", data["position"])
|
||||
|
||||
# Update UI
|
||||
update_all_players_goals()
|
||||
update_all_players_boards()
|
||||
|
||||
@rpc("reliable")
|
||||
func force_update_all_goals():
|
||||
# This is called but might be getting lost in the sequence
|
||||
# Make sure it's called after all players are created
|
||||
await get_tree().create_timer(0.2).timeout
|
||||
update_all_players_goals()
|
||||
update_all_players_boards()
|
||||
|
||||
# Set
|
||||
@rpc("reliable")
|
||||
func receive_complete_game_state(state):
|
||||
# Apply complete game state
|
||||
players = state["players"]
|
||||
bots = state["bots"]
|
||||
game_started = state["game_started"]
|
||||
turn_based_mode = state["turn_based"]
|
||||
preset_goals = state["preset_goals"]
|
||||
|
||||
# Process each player state in a consistent order
|
||||
var sorted_peers = state["player_states"].keys()
|
||||
sorted_peers.sort()
|
||||
|
||||
for peer_id in sorted_peers:
|
||||
var player_data = state["player_states"][peer_id]
|
||||
|
||||
# Create player if doesn't exist
|
||||
if not has_node(str(peer_id)):
|
||||
var player_character = player_scene.instantiate()
|
||||
player_character.set_multiplayer_authority(peer_id)
|
||||
player_character.name = str(peer_id)
|
||||
|
||||
# Set basic properties before adding to scene tree
|
||||
player_character.current_position = player_data["position"]
|
||||
|
||||
# Add to scene
|
||||
add_child(player_character)
|
||||
|
||||
# Apply state after adding to tree
|
||||
player_character.add_to_group("Players", true)
|
||||
if player_data["is_bot"]:
|
||||
player_character.add_to_group("Bots", true)
|
||||
player_character.is_bot = true
|
||||
player_character.rpc("sync_bot_status", true)
|
||||
|
||||
player_character.goals = player_data["goals"].duplicate()
|
||||
player_character.playerboard = player_data["playerboard"].duplicate()
|
||||
|
||||
# Ensure proper grid-aligned positioning
|
||||
player_character.global_position = Vector3(
|
||||
player_data["position"].x * 2 + 1,
|
||||
1.0,
|
||||
player_data["position"].y * 2 + 1
|
||||
)
|
||||
|
||||
# Force position sync
|
||||
player_character.rpc("sync_position", player_data["position"])
|
||||
|
||||
# Force UI updates
|
||||
update_all_players_goals()
|
||||
update_all_players_boards()
|
||||
|
||||
@rpc("reliable")
|
||||
func sync_existing_player(peer_id: int, player_data: Dictionary):
|
||||
# Create player if doesn't exist
|
||||
@@ -404,10 +629,13 @@ func _on_peer_disconnected(peer_id):
|
||||
|
||||
@rpc("any_peer", "call_local")
|
||||
func add_player_character(peer_id):
|
||||
# Check if player already exists
|
||||
# First check if this player already exists
|
||||
if has_node(str(peer_id)):
|
||||
print("Player already exists: ", peer_id)
|
||||
return
|
||||
|
||||
|
||||
print("Adding player: ", peer_id)
|
||||
|
||||
connected_peer_ids.append(peer_id)
|
||||
var player_character = player_scene.instantiate()
|
||||
player_character.set_multiplayer_authority(peer_id)
|
||||
@@ -428,7 +656,14 @@ func add_player_character(peer_id):
|
||||
add_child(player_character)
|
||||
player_character.add_to_group("Players", true)
|
||||
|
||||
# Force position sync after adding to tree
|
||||
# Wait for the node to be properly added to the scene
|
||||
await get_tree().process_frame
|
||||
|
||||
# Ensure the player list is updated
|
||||
if not peer_id in players:
|
||||
players.append(peer_id)
|
||||
|
||||
# Finish setup and sync position
|
||||
if multiplayer.is_server():
|
||||
await get_tree().create_timer(0.1).timeout
|
||||
player_character.rpc("sync_position", player_character.current_position)
|
||||
@@ -560,6 +795,26 @@ func replace_bot_with_player(player_id):
|
||||
rpc("remove_bot_keep_board", bot_id)
|
||||
rpc("sync_players", players)
|
||||
|
||||
@rpc("call_local")
|
||||
func remove_bot_keep_board(bot_id):
|
||||
# This RPC is called but not implemented in your code
|
||||
var bot_node = get_node_or_null(str(bot_id))
|
||||
if bot_node:
|
||||
# Don't immediately queue_free - this can cause timing issues
|
||||
# Instead, mark for removal and remove after a short delay
|
||||
bot_node.visible = false # Hide immediately
|
||||
bot_node.set_process(false)
|
||||
bot_node.set_physics_process(false)
|
||||
|
||||
# Disable all input and behavior
|
||||
var behavior_tree = bot_node.get_node_or_null("BehaviorTree")
|
||||
if behavior_tree:
|
||||
behavior_tree.enabled = false
|
||||
|
||||
# Remove after a short delay
|
||||
await get_tree().create_timer(0.5).timeout
|
||||
if is_instance_valid(bot_node) and bot_node.get_parent() == self:
|
||||
bot_node.queue_free()
|
||||
|
||||
@rpc("call_local")
|
||||
func remove_bot(bot_id):
|
||||
|
||||
Reference in New Issue
Block a user