diff --git a/.vscode/settings.json b/.vscode/settings.json index 5563753..c982466 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,3 @@ { - "godotTools.editorPath.godot4": "c:\\Users\\danchie\\Documents\\Godot_v4.3\\Godot_v4.3-stable_win64.exe" + "godotTools.editorPath.godot4": "c:\\Program Files\\Godot_v4.3-stable_win64\\Godot_v4.3-stable_win64.exe" } \ No newline at end of file diff --git a/scenes/main.gd b/scenes/main.gd index 82d2758..64badf1 100644 --- a/scenes/main.gd +++ b/scenes/main.gd @@ -198,6 +198,9 @@ func set_action_state(new_state): ) ActionState.PUTTING: local_player_character.highlight_occupied_playerboard_slots() + # Make sure this is client-friendly + if not multiplayer.is_server(): + rpc_id(1, "notify_server_of_action_state", new_state) ActionState.RANDOMIZING: local_player_character.highlight_random_valid_cells() ActionState.ARRANGING: diff --git a/scenes/player.gd b/scenes/player.gd index b664382..6e50e11 100644 --- a/scenes/player.gd +++ b/scenes/player.gd @@ -523,6 +523,44 @@ func grab_item(grid_position: Vector2i = current_position) -> bool: return false +# func put_item(grid_position: Vector2i = current_position) -> bool: +# if not enhanced_gridmap or action_points <= 0 or selected_playerboard_slot == -1: +# return false + +# var cell = Vector3i(grid_position.x, 1, grid_position.y) +# if enhanced_gridmap.get_cell_item(cell) != -1: +# return false + +# # Check if position is adjacent or current position +# if grid_position != current_position: +# var is_adjacent = false +# var neighbors = enhanced_gridmap.get_neighbors(current_position, 0) +# for neighbor in neighbors: +# if neighbor.position == grid_position: +# is_adjacent = true +# break +# if not is_adjacent: +# return false + +# var item = playerboard[selected_playerboard_slot] +# if is_multiplayer_authority(): +# rpc("sync_grid_item", cell.x, cell.y, cell.z, item) +# playerboard[selected_playerboard_slot] = -1 +# rpc("sync_playerboard", playerboard) + +# has_performed_action = true +# consume_action_points(1) +# if not is_bot == true: +# clear_highlights() +# clear_playerboard_highlights() +# selected_playerboard_slot = -1 + +# var main = get_tree().get_root().get_node_or_null("Main") +# if main: +# main.set_action_state(main.ActionState.NONE) +# _after_action_completed() +# return true + func put_item(grid_position: Vector2i = current_position) -> bool: if not enhanced_gridmap or action_points <= 0 or selected_playerboard_slot == -1: return false @@ -542,24 +580,82 @@ func put_item(grid_position: Vector2i = current_position) -> bool: if not is_adjacent: return false + # Get the item to place first var item = playerboard[selected_playerboard_slot] - if is_multiplayer_authority(): + + # For clients, we need to RPC to the server first, then let the server RPC back + if is_multiplayer_authority() and not multiplayer.is_server(): + # Client requests server to perform the put operation + rpc_id(1, "request_server_put", grid_position, selected_playerboard_slot, cell.x, cell.y, cell.z, item) + + # We'll return true and let the server handle the actual operation + # The server will RPC back to update our state if successful + return true + elif is_multiplayer_authority() and multiplayer.is_server(): + # Server directly implements the change rpc("sync_grid_item", cell.x, cell.y, cell.z, item) playerboard[selected_playerboard_slot] = -1 rpc("sync_playerboard", playerboard) + + has_performed_action = true + consume_action_points(1) + if not is_bot == true: + clear_highlights() + clear_playerboard_highlights() + selected_playerboard_slot = -1 + + var main = get_tree().get_root().get_node_or_null("Main") + if main: + main.set_action_state(main.ActionState.NONE) + _after_action_completed() + return true + return false + +@rpc("any_peer", "reliable") +func request_server_put(grid_position: Vector2i, slot_index: int, x: int, y: int, z: int, item: int): + # This RPC should only be processed by the server + if not multiplayer.is_server(): + return + + # Verify that this request came from the authority of this player + if multiplayer.get_remote_sender_id() != get_multiplayer_authority(): + push_error("Security: Non-authority tried to put item!") + return + + # Server-side validation + var cell = Vector3i(x, y, z) + if enhanced_gridmap.get_cell_item(cell) != -1: + return # Cell not empty + + # Check if position is adjacent or current position + if grid_position != current_position: + var is_adjacent = false + var neighbors = enhanced_gridmap.get_neighbors(current_position, 0) + for neighbor in neighbors: + if neighbor.position == grid_position: + is_adjacent = true + break + if not is_adjacent: + return # Not adjacent + + # Verify player has the item + if playerboard[slot_index] != item: + push_error("Item mismatch! Player doesn't have claimed item") + return + + # Perform the put operation as the server + rpc("sync_grid_item", x, y, z, item) + playerboard[slot_index] = -1 + rpc("sync_playerboard", playerboard) + + # Update player state has_performed_action = true - consume_action_points(1) - if not is_bot == true: - clear_highlights() - clear_playerboard_highlights() + action_points -= 1 selected_playerboard_slot = -1 - var main = get_tree().get_root().get_node_or_null("Main") - if main: - main.set_action_state(main.ActionState.NONE) + # Notify about action completion _after_action_completed() - return true func handle_put_action(): var main = get_tree().get_root().get_node_or_null("Main") @@ -613,12 +709,27 @@ func handle_put_slot_selected(slot_index: int): var main = get_tree().get_root().get_node_or_null("Main") if not main or main.current_action_state != main.ActionState.PUTTING: return + + print("PUT slot selected: ", slot_index, ", item: ", playerboard[slot_index]) if slot_index in highlighted_cells and playerboard[slot_index] in goals: selected_playerboard_slot = slot_index clear_highlights() if not is_bot == true: highlight_empty_adjacent_cells() + + if playerboard[slot_index] != -1: # If slot has an item + selected_playerboard_slot = slot_index + + # Visual feedback of selection + clear_highlights() + + # Highlight valid put locations + highlight_empty_adjacent_cells() + + # Print debug info + print("Selected slot ", slot_index, " for PUT with item ", playerboard[slot_index]) + print("Highlighted cells: ", highlighted_cells) func arrange_playerboard_item(slot_index: int): @@ -771,9 +882,12 @@ func highlight_adjacent_cells(): highlight_cells_if_authorized(cells_to_highlight) func highlight_empty_adjacent_cells(): - if is_bot == true or is_in_group("Bots") or not is_multiplayer_authority(): + if is_bot == true or is_in_group("Bots"): return + # Debug print + print("Highlighting empty adjacent cells. Current position: ", current_position) + # Clear previous highlights clear_highlights() @@ -783,6 +897,7 @@ func highlight_empty_adjacent_cells(): highlighted_cells.append(current_position) enhanced_gridmap.set_cell_item(Vector3i(current_position.x, 0, current_position.y), enhanced_gridmap.hover_item) + print("Highlighted current position: ", current_position) # Highlight empty adjacent cells var neighbors = enhanced_gridmap.get_neighbors(current_position, 0) @@ -794,6 +909,13 @@ func highlight_empty_adjacent_cells(): highlighted_cells.append(cell_pos) enhanced_gridmap.set_cell_item(Vector3i(cell_pos.x, 0, cell_pos.y), enhanced_gridmap.hover_item) + print("Highlighted adjacent cell: ", cell_pos) + +@rpc("any_peer", "call_local") +func sync_action_points(points: int): + action_points = points + + func highlight_random_valid_cells(): if is_bot == true or is_in_group("Bots") or not is_multiplayer_authority(): @@ -969,7 +1091,20 @@ func sync_rotation(new_rotation: float): @rpc("any_peer", "call_local", "reliable") func sync_grid_item(x: int, y: int, z: int, item: int): if enhanced_gridmap: - enhanced_gridmap.set_cell_item(Vector3i(x, y, z), item) + var cell = Vector3i(x, y, z) + + # Log the change for debugging + print("Setting grid item at ", cell, " to ", item, " (called by ", multiplayer.get_remote_sender_id(), ")") + + # Make sure we set the cell reliably + enhanced_gridmap.set_cell_item(cell, item) + + # Double-check the cell was set + var check_value = enhanced_gridmap.get_cell_item(cell) + if check_value != item: + push_warning("Cell item didn't update correctly! Expected " + str(item) + " but got " + str(check_value)) + # Try once more + enhanced_gridmap.set_cell_item(cell, item) @rpc("any_peer", "call_local") func sync_goals(new_goals: Array):