pandemonium_demo_projects/networking/multiplayer_bomber/gamestate.gd

189 lines
5.0 KiB
GDScript

extends Node
# Default game server port. Can be any number between 1024 and 49151.
# Not on the list of registered or common ports as of November 2020:
# https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
const DEFAULT_PORT = 10567
# Max number of players.
const MAX_PEERS = 12
var peer = null
# Name for my player.
var player_name = "The Warrior"
# Names for remote players in id:name format.
var players = {}
var players_ready = []
# 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(what)
# Callback from SceneTree.
func _player_connected(id):
# Registration of a client beings here, tell the connected player that we are here.
rpc_id(id, "register_player", player_name)
# Callback from SceneTree.
func _player_disconnected(id):
if has_node("/root/World"): # Game is in progress.
if get_tree().is_network_server():
emit_signal("game_error", "Player " + players[id] + " disconnected")
end_game()
else: # Game is not in progress.
# Unregister this player.
unregister_player(id)
# Callback from SceneTree, only for clients (not server).
func _connected_ok():
# We just connected to a server
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.
func register_player(new_player_name):
var id = get_tree().get_rpc_sender_id()
print(id)
players[id] = new_player_name
emit_signal("player_list_changed")
func unregister_player(id):
players.erase(id)
emit_signal("player_list_changed")
func pre_start_game(spawn_points):
# Change scene.
var world = load("res://world.tscn").instance()
get_tree().get_root().add_child(world)
get_tree().get_root().get_node("Lobby").hide()
var player_scene = load("res://player.tscn")
for p_id in spawn_points:
var spawn_pos = world.get_node("SpawnPoints/" + str(spawn_points[p_id])).position
var player = player_scene.instance()
player.set_name(str(p_id)) # Use unique ID as node name.
player.position=spawn_pos
player.set_network_master(p_id) #set unique id as master.
if p_id == get_tree().get_network_unique_id():
# If node for this peer id, set name.
player.set_player_name(player_name)
else:
# Otherwise set name from peer.
player.set_player_name(players[p_id])
world.get_node("Players").add_child(player)
# Set up score.
world.get_node("Score").add_player(get_tree().get_network_unique_id(), player_name)
for pn in players:
world.get_node("Score").add_player(pn, players[pn])
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()
func post_start_game():
get_tree().set_pause(false) # Unpause and unleash the game!
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):
player_name = new_player_name
peer = NetworkedMultiplayerENet.new()
peer.create_server(DEFAULT_PORT, MAX_PEERS)
get_tree().set_network_peer(peer)
func join_game(ip, new_player_name):
player_name = new_player_name
peer = NetworkedMultiplayerENet.new()
peer.create_client(ip, DEFAULT_PORT)
get_tree().set_network_peer(peer)
func get_player_list():
return players.values()
func get_player_name():
return player_name
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()
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")
rpc_config("register_player", MultiplayerAPI.RPC_MODE_REMOTE)
rpc_config("pre_start_game", MultiplayerAPI.RPC_MODE_REMOTE)
rpc_config("post_start_game", MultiplayerAPI.RPC_MODE_REMOTE)
rpc_config("ready_to_start", MultiplayerAPI.RPC_MODE_REMOTE)