extends Node signal players_changed signal player_joined(player: Player) func _ready(): reset_players() multiplayer.connected_to_server.connect(_on_connected_to_server) multiplayer.server_disconnected.connect(_on_disconnected_from_server) #multiplayer.peer_connected.connect(_on_peer_connected) #multiplayer.peer_disconnected.connect(_on_peer_disconnected) multiplayer.allow_object_decoding = true func host_game(port) -> Error: var peer = ENetMultiplayerPeer.new() var error = peer.create_server(int(port)) if error != OK: return error multiplayer.multiplayer_peer = peer Client.player.id = multiplayer.get_unique_id() return error func join_game(ip, port): var peer = ENetMultiplayerPeer.new() var error = peer.create_client(ip, int(port)) if error != OK: return error multiplayer.multiplayer_peer = peer Client.player.id = multiplayer.get_unique_id() func close_game(): multiplayer.multiplayer_peer.close() multiplayer.multiplayer_peer = OfflineMultiplayerPeer.new() reset_players() await GameLobby.request_post("/close") GameLobby.current_game_id = "" GameLobby.current_secret = "" func _on_connected_to_server(): print(multiplayer.get_unique_id(), ": connected to server") func _on_disconnected_from_server(): print("disconnected from server") close_game() func _on_peer_connected(id: int): print(multiplayer.get_unique_id(), ": peer connected: ", id) add_to_players.rpc_id(id, inst_to_dict(Client.player)) # TODO: check why bug and adds more players than intended #ask_game_running.rpc_id(id) #is_game_running.connect(func(is_running: bool): #if not is_running: #add_to_players.rpc_id(id, inst_to_dict(Client.player)) #elif is_running: #get_tree().change_scene_to_file("res://UI/Start.tscn") #) func _on_peer_disconnected(id: int): print(multiplayer.get_unique_id(), ": peer disconnected: ", id) remove_player(id) if id == 1: # if host disconnected go back to Start get_tree().change_scene_to_file("res://UI/Start.tscn") func reset_players(): for node in %Players.get_children(): %Players.remove_child(node) %Players.add_child(preload("res://Game/Player.tscn").instantiate()) func get_player(id: int) -> Player: if %Players.get_child_count() == 1: return %Players.get_child(0) return %Players.get_node(str(id)) func get_players() -> Array[Node]: return %Players.get_children() func get_ordered_player_ids(players = get_players()) -> Array: var keys = players.map(func(item: Player): return item.id ) keys.sort_custom(func(a: int, b: int): return int(str(a).substr(0, 8)) < int(str(b).substr(0, 8)) ) return keys func remove_player(id: int): var player = get_player(id) if player: %Players.remove_child(player) players_changed.emit() signal is_game_running(is_running: bool) @rpc("any_peer") func ask_game_running(): var is_running = get_tree().current_scene is Stage receive_game_running.rpc_id(multiplayer.get_remote_sender_id(), is_running) @rpc("any_peer") func receive_game_running(is_running: bool): is_game_running.emit(is_running) @rpc("any_peer") func add_to_players(remote_data: Dictionary): var id = multiplayer.get_remote_sender_id() var player = preload("res://Game/Player.tscn").instantiate() player.id = id player.username = remote_data.username %Players.add_child(player) player_joined.emit(player) players_changed.emit() @rpc("any_peer", "call_local") func update_player(id: int, remote_data: Dictionary): var player = get_player(id) for property in remote_data: if typeof(player[property]) == TYPE_INT: player[property] += remote_data[property] else: player[property] = remote_data[property] players_changed.emit() @rpc("any_peer") func destroy_tower(remote_data: Dictionary): var data: Tower.NetworkData = dict_to_inst(remote_data) var remote_tower = Tower.from_network_data(data) var player = get_player(remote_tower.owner_id) var tower = player.towers.get(remote_tower.global_position) Client.current_stage.destroy_tower(tower) @rpc("any_peer") func update_tower(remote_tower_node_path: NodePath, remote_data: Dictionary): var data: Tower.NetworkData = dict_to_inst(remote_data) var tower: Tower = get_tree().current_scene.get_node_or_null(remote_tower_node_path) if tower: tower.update_with_network_data(data) @rpc("any_peer") func remove_unit(remote_unit_node_path: NodePath): var unit = get_tree().current_scene.get_node_or_null(remote_unit_node_path) if unit: unit.queue_free() @rpc("any_peer") func update_unit(remote_unit_node_path: NodePath, remote_data: Dictionary): var data: Unit.NetworkData = dict_to_inst(remote_data) var unit: Unit = get_tree().current_scene.get_node_or_null(remote_unit_node_path) if unit: unit.update_with_network_data(data)