extends Node3D var multiplayer_peer = ENetMultiplayerPeer.new() const PORT = 9999 const ADDRESS = "127.0.0.1" var connected_peer_ids = [] var local_player_character : CharacterBody3D var player_scene = preload("res://scenes/player.tscn") var current_turn_index = 0 @export var players = [] var game_started = false var max_message_input_char = 51 var max_players = 4 var bots = [] func _ready(): multiplayer_peer.peer_connected.connect(_on_peer_connected) multiplayer_peer.peer_disconnected.connect(_on_peer_disconnected) func _on_host_pressed(): $NetworkInfo/NetworkSideDisplay.text = "Server" $Menu.visible = false multiplayer_peer.create_server(PORT) multiplayer.multiplayer_peer = multiplayer_peer $NetworkInfo/UniquePeerID.text = str(multiplayer.get_unique_id()) add_player_character(1) players.append(1) # Add bots to fill remaining slots for i in range(2, max_players + 1): add_bot(i) start_game() func _on_join_pressed(): $NetworkInfo/NetworkSideDisplay.text = "Client" $Menu.visible = false multiplayer_peer.create_client(ADDRESS, PORT) multiplayer.multiplayer_peer = multiplayer_peer $NetworkInfo/UniquePeerID.text = str(multiplayer.get_unique_id()) func _on_peer_connected(new_peer_id): if multiplayer.is_server(): await get_tree().create_timer(1).timeout rpc("add_newly_connected_player_character", new_peer_id) rpc_id(new_peer_id, "add_previously_connected_player_characters", connected_peer_ids) add_player_character(new_peer_id) replace_bot_with_player(new_peer_id) func _on_peer_disconnected(peer_id): if multiplayer.is_server(): connected_peer_ids.erase(peer_id) players.erase(peer_id) add_bot(get_next_available_bot_id()) func add_player_character(peer_id): connected_peer_ids.append(peer_id) var player_character = player_scene.instantiate() player_character.set_multiplayer_authority(peer_id) add_child(player_character) player_character.add_to_group("Players", true) if peer_id == multiplayer.get_unique_id(): local_player_character = player_character func add_bot(bot_id): var bot_character = player_scene.instantiate() bot_character.set_multiplayer_authority(1) # Set server as authority for bots bot_character.name = str(bot_id) add_child(bot_character) bot_character.add_to_group("Players", true) bot_character.add_to_group("Bots", true) bots.append(bot_id) players.append(bot_id) func replace_bot_with_player(player_id): if bots.size() > 0: var bot_id = bots.pop_front() players.erase(bot_id) players.append(player_id) var bot_node = get_node(str(bot_id)) if bot_node: bot_node.queue_free() rpc("sync_players", players) func get_next_available_bot_id(): for i in range(2, max_players + 1): if not i in players: return i return -1 @rpc func add_newly_connected_player_character(new_peer_id): add_player_character(new_peer_id) @rpc func add_previously_connected_player_characters(peer_ids): for peer_id in peer_ids: add_player_character(peer_id) func _process(_delta): if multiplayer.is_server() and game_started: rpc("sync_turn_index", current_turn_index) func start_game(): if multiplayer.is_server(): game_started = true connected_peer_ids.sort() rpc("sync_game_start", connected_peer_ids) current_turn_index = -1 next_turn() @rpc func sync_game_start(peer_ids): connected_peer_ids = peer_ids game_started = true @rpc("reliable") func sync_turn_index(index): current_turn_index = index @rpc("reliable") func sync_players(new_players): players = new_players func next_turn(): if multiplayer.is_server(): current_turn_index += 1 if current_turn_index >= players.size(): current_turn_index = 0 rpc("set_current_turn", players[current_turn_index]) if players[current_turn_index] in bots: move_bot(players[current_turn_index]) func request_next_turn(): if multiplayer.is_server(): end_current_turn() else: rpc_id(1, "server_end_current_turn") @rpc("any_peer") func server_end_current_turn(): if multiplayer.is_server(): end_current_turn() @rpc("any_peer", "call_local") func set_current_turn(player_id): var players = get_tree().get_nodes_in_group("Players") for player in players: player.is_my_turn = (player.name == str(player_id)) if player.is_my_turn: player.start_turn() func end_current_turn(): if multiplayer.is_server(): next_turn() rpc("sync_turn_index", current_turn_index) func _on_message_input_text_submitted(new_text): if new_text.length() > max_message_input_char: new_text = new_text.substr(0, max_message_input_char) + " ... " local_player_character.rpc("display_message", new_text) $MessageInput.text = "" $MessageInput.release_focus() func move_bot(bot_id): if multiplayer.is_server(): var bot = get_node(str(bot_id)) if bot: var target_position = bot.find_random_valid_position() if target_position != bot.current_position: var path = bot.enhanced_gridmap.find_path(Vector2(bot.current_position), Vector2(target_position)) if path.size() > 1: path.pop_front() # Remove the starting position bot.move_bot_along_path(path) else: print("No valid path found for bot") end_current_turn() else: print("No new valid position found for bot") end_current_turn() else: print("Bot not found") end_current_turn()