extends Node # Default game port const DEFAULT_PORT = 8128 # Max number of players const MAX_PLAYERS = 4 const MAX_PEERS = MAX_PLAYERS - 1 var world_scene = preload("res://scenes/game/world.tscn") var player_scene = preload("res://scenes/player/Player.tscn") var human_player_scene = preload("res://scenes/player/HumanPlayer.tscn") var bot_player_scene = preload("res://scenes/player/BotPlayer.tscn") # Name for my player var player_name = "Undefined" var player_color = Color("#000000") # Names for remote players in id:name format var players = {} # Signals to let lobby GUI know what's going on signal player_list_changed() signal connection_failed() signal connection_succeeded() signal game_ended() signal game_error(msg) # Callback from SceneTree func _player_connected(id): pass # Callback from SceneTree func _player_disconnected(id): if (get_tree().is_network_server()): if (has_node("/root/world")): # Game is in progress emit_signal("game_error", "Player " + players[id].name + " disconnected") end_game() else: # Game is not in progress # If we are the server, send to the new dude all the already registered players unregister_player(id) for p_id in players: # Erase in the server rpc_id(p_id, "unregister_player", id) # Callback from SceneTree, only for clients (not server) func _connected_ok(): # Registration of a client beings here, tell everyone that we are here rpc("register_player", get_tree().get_network_unique_id(), player_name, player_color) emit_signal("connection_succeeded") # Callback from SceneTree, only for clients (not server) func _server_disconnected(): emit_signal("game_error", "Server disconnected") end_game() # Callback from SceneTree, only for clients (not server) func _connected_fail(): get_tree().set_network_peer(null) # Remove peer emit_signal("connection_failed") # Lobby management functions remote func register_player(id, new_player_name, new_player_color): if (get_tree().is_network_server()): # If we are the server, let everyone know about the new player rpc_id(id, "register_player", 1, player_name, player_color) # Send myself to new dude for p_id in players: # Then, for each remote player rpc_id(id, "register_player", p_id, players[p_id].name, players[p_id].color) # Send player to new dude rpc_id(p_id, "register_player", id, new_player_name, new_player_color) # Send new dude to player players[id] = {"name" : new_player_name, "color" : new_player_color} emit_signal("player_list_changed") remote func unregister_player(id): players.erase(id) emit_signal("player_list_changed") remote func pre_start_game(spawn_points): # Change scene var world = world_scene.instance() get_tree().get_root().add_child(world) get_tree().get_root().get_node("lobby").hide() for p_id in spawn_points: var controls var player = player_scene.instance() player.set_network_master(p_id) player.set_name(str(p_id)) world.get_node("players").add_child(player) if (p_id == get_tree().get_network_unique_id()): # If node for this peer id, set name player.set_player_name(player_name) player.set_player_color(player_color) controls = human_player_scene.instance() controls.set_name("HumanControl_" + str(p_id)) world.add_child(controls) controls.set_player(player.get_path()) controls.set_network_master(p_id) else: # Otherwise set name from peer player.set_player_name(players[p_id].name) player.set_player_color(players[p_id].color) player.set_start(player.get_index()) var bots = false if bots: for index in range(4-spawn_points.size()): var bot_index = spawn_points.size() + index var player = player_scene.instance() player.set_name("bot_player" + str(bot_index)) world.get_node("players").add_child(player) player.add_to_group("bots") if get_tree().is_network_server(): var bot = bot_player_scene.instance() bot.set_name("bot" + str(bot_index)) world.add_child(bot) bot.set_player(player.get_path()) bot.set_network_master(get_tree().get_network_unique_id()) player.set_start(bot_index) if (not get_tree().is_network_server()): # Tell server we are ready to start rpc_id(1, "ready_to_start", get_tree().get_network_unique_id()) elif players.size() == 0: post_start_game() remote func post_start_game(): get_tree().set_pause(false) # Unpause and unleash the game! var players_ready = [] remote func ready_to_start(id): assert(get_tree().is_network_server()) if (not id in players_ready): players_ready.append(id) if (players_ready.size() == players.size()): for p in players: rpc_id(p, "post_start_game") post_start_game() func host_game(new_player_name, new_player_color): player_name = new_player_name player_color = new_player_color var host = NetworkedMultiplayerENet.new() host.create_server(DEFAULT_PORT, MAX_PEERS) get_tree().set_network_peer(host) func join_game(ip, new_player_name, new_player_color): player_name = new_player_name player_color = new_player_color var host = NetworkedMultiplayerENet.new() host.create_client(ip, DEFAULT_PORT) get_tree().set_network_peer(host) func get_player_list(): return players.values() func get_player_name(): return player_name func get_player_color(): return player_color func begin_game(): assert(get_tree().is_network_server()) # Create a dictionary with peer id and respective spawn points, could be improved by randomizing var spawn_points = {} spawn_points[1] = 0 # Server in spawn point 0 var spawn_point_idx = 1 for p in players: spawn_points[p] = spawn_point_idx spawn_point_idx += 1 # Call to pre-start game with the spawn points for p in players: rpc_id(p, "pre_start_game", spawn_points) pre_start_game(spawn_points) func end_game(): if (has_node("/root/world")): # Game is in progress # End it get_node("/root/world").queue_free() emit_signal("game_ended") players.clear() get_tree().set_network_peer(null) # End networking func _ready(): get_tree().connect("network_peer_connected", self, "_player_connected") get_tree().connect("network_peer_disconnected", self,"_player_disconnected") get_tree().connect("connected_to_server", self, "_connected_ok") get_tree().connect("connection_failed", self, "_connected_fail") get_tree().connect("server_disconnected", self, "_server_disconnected")