Skip to content

Instantly share code, notes, and snippets.

@tonytins
Last active January 3, 2019 18:54
Show Gist options
  • Save tonytins/86781a355efc1a52f14a3302e7adecb4 to your computer and use it in GitHub Desktop.
Save tonytins/86781a355efc1a52f14a3302e7adecb4 to your computer and use it in GitHub Desktop.
Multiplayer lobby example from Godot documentation
# Typical lobby implementation, imagine this being in /root/lobby
extends Node
# Connect all functions
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")
# Player info, associate ID to data
var player_info = {}
# Info we send to other players
var my_info = { name = "Johnson Magenta", favorite_color = Color8(255, 0, 255) }
func _player_connected(id):
pass # Will go unused, not useful here
func _player_disconnected(id):
player_info.erase(id) # Erase player from info
func _connected_ok():
# Only called on clients, not server. Send my ID and info to all the other peers
rpc("register_player", get_tree().get_network_unique_id(), my_info)
func _server_disconnected():
pass # Server kicked us, show error and abort
func _connected_fail():
pass # Could not even connect to server, abort
# This keyword has two main uses. The first is to let Godot know that
# this function can be called from RPC. If no keywords are added Godot
# will block any attempts to call functions for security. This makes
# security work a lot easier (so a client can’t call a function to
# delete a file on another client’s system).
remote func register_player(id, info):
# Store the info
player_info[id] = info
# If I'm the server, let the new guy know about existing players
if get_tree().is_network_server():
# Send my info to new player
rpc_id(id, "register_player", 1, my_info)
# Send the info of existing players
for peer_id in player_info:
rpc_id(id, "register_player", peer_id, player_info[peer_id])
# Call function to update lobby UI here
# In most games, each player will likely have its own scene. Remember that this is a
# multiplayer game, so in every peer you need to instance one scene for each player
# connected to it. For a 4 player game, each peer needs to instance 4 player nodes.
#
# So, how to name such nodes? In Godot nodes need to have an unique name. It must
# also be relatively easy for a player to tell which nodes represent each player ID.
#
# The solution is to simply name the root nodes of the instanced player scenes as
# their network ID. This way, they will be the same in every peer and
# RPC will work great! Here is an example:
remote func pre_configure_game():
var selfPeerID = get_tree().get_network_unique_id()
# Load world
var world = load(which_level).instance()
get_node("/root").add_child(world)
# Load my player
var my_player = preload("res://player.tscn").instance()
my_player.set_name(str(selfPeerID))
my_player.set_network_master(selfPeerID) # Will be explained later
get_node("/root/world/players").add_child(my_player)
# Load other players
for p in player_info:
var player = preload("res://player.tscn").instance()
player.set_name(str(p))
get_node("/root/world/players").add_child(player)
# Tell server (remember, server is always ID=1) that this peer is done pre-configuring
rpc_id(1, "done_preconfiguring", selfPeerID)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment