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_disconneted_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): var peer = ENetMultiplayerPeer.new() peer.create_server(int(port)) multiplayer.multiplayer_peer = peer Client.player.id = multiplayer.get_unique_id() func join_game(ip, port): var peer = ENetMultiplayerPeer.new() peer.create_client(ip, int(port)) multiplayer.multiplayer_peer = peer Client.player.id = multiplayer.get_unique_id() func _on_connected_to_server(): print(multiplayer.get_unique_id(), ": connected to server") func _on_disconneted_from_server(): print("disconnected from server") multiplayer.multiplayer_peer = OfflineMultiplayerPeer.new() reset_players() func _on_peer_connected(id): print(multiplayer.get_unique_id(), ": peer connected: ", id) add_to_players.rpc_id(id, inst_to_dict(Client.player)) # TODO: add existing towers to new peers func _on_peer_disconnected(id): print(multiplayer.get_unique_id(), ": peer disconnected: ", id) %Players.remove_child(get_player(id)) # TODO: move towers owned by peer to host if id == 1: # if host disconnected go back to Lobby 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 @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_tower: Dictionary): func destroy_tower(position: Vector2): var owner_id = multiplayer.get_remote_sender_id() var player = get_player(owner_id) var tower = player.towers.get(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): 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, data): var unit: Unit = get_tree().current_scene.get_node_or_null(remote_unit_node_path) if unit: if "hp" in data: unit.hp = data.hp if "position" in data: unit.position = data.position if "sprite" in data: unit.get_node("Sprite2D").self_modulate = data.sprite.self_modulate if "current_path" in data: unit.current_path = data.current_path unit.line.points = PackedVector2Array(data.current_path) if "current_path_idx" in data: unit.current_path_idx = data.current_path_idx