Godot Tutorial: Simple Chat Room using Multiplayer API

In this tutorial you’ll make a simple chat room in Godot using Godot’s multiplayer API.

Start by making a scene set up like so:

IpEnter is a LineEdit node where you enter the ip of the server, it is initialized to 127.0.0.1, the local ip address of your pc.

LeaveButton is hidden and will be shown when you enter a room.

ChatInput is another LineEdit where you will enter chat messages. ChatDisplay is a TextEdit node with ReadOnly and  ShowLineNumbers checked, this will be used to display everyones’ messages.

Now add a script to the root node ChatRoom and set up the following base functions:

extends Control

func _ready():
    pass

func host_room():
    pass

func join_room():
    pass

func enter_room():
    $SetUp/LeaveButton.show()
    $SetUp/JoinButton.hide()
    $SetUp/HostButton.hide()
    $SetUp/IpEnter.hide()

func leave_room():
    $SetUp/LeaveButton.hide()
    $SetUp/JoinButton.show()
    $SetUp/HostButton.show()
    $SetUp/IpEnter.show()

Connect button_up signals on each button to their respective functions: LeaveButton to leave_room, JoinButton to join_room, and HostButton to host_room.

Now for the actual multiplayer stuff. Modify the functions with this:

const PORT = 3000
const MAX_USERS = 4 #not including host

func _ready():
    get_tree().connect("connected_to_server", self, "enter_room")

func host_room():
    var host = NetworkedMultiplayerENet.new()
    host.create_server(PORT, MAX_USERS)
    get_tree().set_network_peer(host)
    enter_room()

func join_room():
    var ip = $SetUp/IpEnter.text
    var host = NetworkedMultiplayerENet.new()
    host.create_client(ip, PORT)
    get_tree().set_network_peer(host)

Code explanation: If you host a room, create the server and enter the room. If you join, get the ip address you entered and attempt to enter. If entering is successful, the “connected_to_server” signal is emitted and enter_room is called.

Next let’s add some notifications, like welcome messages or letting other players know you entered.

I add in these lines to easily access the UI:

onready var chat_display = $RoomUI/ChatDisplay
onready var chat_input = $RoomUI/ChatInput

Then I add to the end of the host_room() function:

chat_display.text = "Room Created\n"

To enter_room():

chat_display.text = "Successfully Joined Room\n"

And to leave_room():

chat_display.text += "Left Room\n"
get_tree().set_network_peer(null

Next, for user enter and exit notifications add this to ready():

get_tree().connect("network_peer_connected", self, "user_entered")
get_tree().connect("network_peer_disconnected", self, "user_exited")

Then create the user_entered and user_exited functions:

func user_entered(id):
    chat_display.text += str(id) + " joined the room\n"

func user_exited(id):
    chat_display.text += str(id) + " left the room\n"

To test the notifications out you’ll have to export the game so you can run several instances of it.

A unique id is generated for each player when they join, the host is always 1.

Here’s the current code:

extends Control

const PORT = 3000
const MAX_USERS = 4 #not including host

onready var chat_display = $RoomUI/ChatDisplay
onready var chat_input = $RoomUI/ChatInput

func _ready():
    get_tree().connect("connected_to_server", self, "enter_room")
    get_tree().connect("network_peer_connected", self, "user_entered")
    get_tree().connect("network_peer_disconnected", self, "user_exited")

func user_entered(id):
    chat_display.text += str(id) + " joined the room\n"

func user_exited(id):
    chat_display.text += str(id) + " left the room\n"

func host_room():
    var host = NetworkedMultiplayerENet.new()
    host.create_server(PORT, MAX_USERS)
    get_tree().set_network_peer(host)
    enter_room()
    chat_display.text = "Room Created\n"

func join_room():
    var ip = $SetUp/IpEnter.text
    var host = NetworkedMultiplayerENet.new()
    host.create_client(ip, PORT)
    get_tree().set_network_peer(host)

func enter_room():
    chat_display.text = "Successfully joined room\n"
    $SetUp/LeaveButton.show()
    $SetUp/JoinButton.hide()
    $SetUp/HostButton.hide()
    $SetUp/IpEnter.hide()

func leave_room():
    get_tree().set_network_peer(null)
    chat_display.text += "Left Room\n"
    
    $SetUp/LeaveButton.hide()
    $SetUp/JoinButton.show()
    $SetUp/HostButton.show()
    $SetUp/IpEnter.show()

Now let’s add messaging. I’ll add a send_message and receive_message function and set up _input:

func _input(event):
    if event is InputEventKey:
        if event.pressed and event.scancode == KEY_ENTER:
            send_message()

func send_message():
    var msg = chat_input.text
    chat_input.text = ""
    var id = get_tree().get_network_unique_id()
    rpc("receive_message", id, msg)

sync func receive_message(id, msg):
    chat_display.text += str(id) + ": " + msg + "\n"

send_message() takes your chat input, clears it, then does a remote procedure call (rpc) to receive_message, sending the message and our id.

receive_message has ‘sync’ before ‘func’ which means it gets called on everyone in the network when there’s a rpc to it.

Finally, I’ll add a notification if you get disconnected from the server.

I’ll add to ready()

get_tree().connect("server_disconnected", self, "_server_disconnected")

And create the _server_disconnected() function:

func _server_disconnected():
    chat_display.text += "Disconnected from Server\n"
    leave_room()

Here’s the final state of the project:

The final code:

extends Control

const PORT = 3000
const MAX_USERS = 4 #not including host

onready var chat_display = $RoomUI/ChatDisplay
onready var chat_input = $RoomUI/ChatInput

func _ready():
    get_tree().connect("connected_to_server", self, "enter_room")
    get_tree().connect("network_peer_connected", self, "user_entered")
    get_tree().connect("network_peer_disconnected", self, "user_exited")
    get_tree().connect("server_disconnected", self, "_server_disconnected")

func _server_disconnected():
    chat_display.text += "Disconnected from Server\n"
    leave_room()

func user_entered(id):
    chat_display.text += str(id) + " joined the room\n"

func user_exited(id):
    chat_display.text += str(id) + " left the room\n"

func host_room():
    var host = NetworkedMultiplayerENet.new()
    host.create_server(PORT, MAX_USERS)
    get_tree().set_network_peer(host)
    enter_room()
    chat_display.text = "Room Created\n"

func join_room():
    var ip = $SetUp/IpEnter.text
    var host = NetworkedMultiplayerENet.new()
    host.create_client(ip, PORT)
    get_tree().set_network_peer(host)

func enter_room():
    chat_display.text = "Successfully joined room\n"
    $SetUp/LeaveButton.show()
    $SetUp/JoinButton.hide()
    $SetUp/HostButton.hide()
    $SetUp/IpEnter.hide()

func leave_room():
    get_tree().set_network_peer(null)
    chat_display.text += "Left Room\n"
    
    $SetUp/LeaveButton.hide()
    $SetUp/JoinButton.show()
    $SetUp/HostButton.show()
    $SetUp/IpEnter.show()

func _input(event):
    if event is InputEventKey:
        if event.pressed and event.scancode == KEY_ENTER:
            send_message()

func send_message():
    var msg = chat_input.text
    chat_input.text = ""
    var id = get_tree().get_network_unique_id()
    rpc("receive_message", id, msg)

sync func receive_message(id, msg):
    chat_display.text += str(id) + ": " + msg + "\n"

 

Leave a Reply

Your email address will not be published. Required fields are marked *