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"

 

Comment

Final Blog Post for Senior Seminar

Well it’s been a long semester, but it’s time to wrap up.

In my Senior Seminar class, we focused a lot on current issues in the computer science field, discussing internet privacy, cryptocurrenices, and cybersecurity. We worked on improving our resumes and interpersonal skills, and put time into getting interviews for jobs and internships.  We obtained business connections and I developed my pitching skills substantially.

It’s almost time for me to head out into the world and face the real challenges life has to offer, and I feel like this class has helped me to prepare for that.

My advice to future students in this class is that if you’re interested in creating a startup or product, don’t wait until you graduate, start now! There are tons of opportunities to help you here at App, and Wilkes has lots of great advice you can take advantage of.

Comment

Reflections on CitizenFour viewing

In class we watched the CitizenFour documentary about Edward Snowden. It was a very eye-opening experience showing just how scary our own government can be.

I lost respect for Obama, since he was ok with the policies shown (even encouraging a lot of them) that invade our privacy.

I wasn’t aware before how careful Snowden had been with the release of the documents. I appreciate how he went to professional journalists who carefully vetted everything instead of just dumping it all on wikileaks.

Comment

Reflections on guest lecture by Doug Blaszczak

Doug Blaszczak, one of the developers at BB&T, came and spoke about some behind-the-scenes things.

I found the talk very enjoyable, I was actually familiar with some of the material they were discussing due to my time interning at Avast. They talked a lot about cryptography with symmetric and asymmetric encryption and decryption. There were also a couple graduates there who gave advice to us, mainly that learning to review others’ code is a very useful skill.

I would have liked to hear him talk more about accidents or mistakes that happened; I feel he gave the impression their security was perfect and no one ever got in.

Comment

Snooping Assignment reflection

Last week we were paired with a classmate and had to spy on them online to find as much as possible about them. My partner was a ghost online and I wasn’t able to find much besides a LinkedIn, an old address on voterrecords, and the names of a couple relatives.

After we discussed our findings in class, though I was surprised at just how much information you can find on other people. I hadn’t known that voterrecords were public until I did this task and that you can easily find someones current address through that. You can also find apartment floorplans by searching the address, which is someone creepy.

There were also multiple vectors to finding information about a person. Some people were very secretive online, but their relatives were not and classmates were able to find information about that person through their relative.

I found a need to keep a lot more of my info secret online.

Comment

The Last Lecture Thoughts

The main things I got out of The Last Lecture were what Randy Paush said about brick walls being a test to see how much you really want to something, and that those walls are just to keep everyone else out. Be aggressive and push hard to try to accomplish things.

I also was impressed by his optimism and constant complimenting others. This man had accomplished so much but always went out of his way to point out others’ accomplishments.

Comment

Privacy Policy reviews

In class we each went over a privacy policy from a website we used and discussed it in class.

It’s surprising how much is stored in privacy policies that we never think about; I wonder if some of the points were put right up front (such as how much data they sell to advertisers) on the website, would people still use them? I feel like some sites try to make their privacy policy difficult to use or understand because of this.

But other sites try to make it as easy as possible for users to understand. Such as how LinkedIn provides a video version for people. Maybe it’s because their users are smarter when it comes to legal things since it is a business platform.

We hear  a lot how websites track everything we do and that so much of our data is available online to advertisers, but it feels different to actually see it yourself by actually reading the privacy policy.

Comment

Hive Tracks and Bee Informed Partnership case study reflections

The last time my senior seminar class met, we discussed the Hive Tracks and Bee Informed Partnership. The main topic of discussion was data ownership: Who owns the data that volunteers give to these organizations? Also, does that change depending on if the data is from businesses or from individuals?

An interesting point brought up was what happens to data if one of the companies is sold. Someone may be okay with giving their data to these organizations, but not to another one that may end up buying them in the future.

Questions like these always need to be addressed right at the start.

It’s especially relevant to beekeepers though, since bees are so vulnerable. And giving out the data can be dangerous, as it would allow others to figure out beekeepers’ locations. It would be easy for competitors to damage each other’s production if data were to leak.

Comment

Career Development

I attended a career development workshop for class recently. The focus was on networking, interviewing, and following up. Since everyone in the class is a senior, it’s all very relevant to us.

For networking, it’s very important to use LinkedIn somewhat actively. Every time you meet someone, add them as a connection, and if you’ve worked with them, ask for a recommendation.

For interviewing, the speaker said it helps to do practice interviews, which my school offers. I don’t think this is that important though, as most interviewers would know they were speaking to college students with little experience of interviews and would let small mistakes slide. And, in my experience, it only takes one actual interview to become confident and  familiar with the process. My second interview ever went great (much better than my first), and I didn’t read any tips or get advice on what to do. It’s pretty intuitive.

As part of networking, the speaker said it’s very important to follow up with an email or LinkedIn message later on. LinkedIn messages are better, because they won’t get lost in the ’email abyss’ most people have. Just a simple ‘thank you’ or ‘it was great speaking to you’ can have a great impact. This is something I struggle with, but I know the power of it; people respond very favorably to it.

Comment

Personal Ethics

When making decisions on how to spend my time, I try to balance three things: health, experiences, and career.

I try to do everything with the long term in mind; what will make me the most happy when I’m 80? Obviously I don’t want to be wheelchair-bound and on a bunch of medication so I prioritize health first. Get enough sleep, eat right, and exercise regularly. I find this also makes it a lot easier to study and enjoy myself. My remaining time I budget between experiences and career. When I’m old, I don’t want to remember my youth being spent studying and working, but I also don’t want to be working a dead end job. I’d like to be comfortably retired. I make sure I go out and have fun, but also I work hard and keep grades up. Of course, it’s not necessary at all to have perfect grades; both a 90 and a 100 are A’s, getting those extra 10 points does nothing to improve your grade, so why try for it? Better to spend that time on gaining new experiences.

With careful management and good work ethic it’s possible to have high standards of work while also having time to enjoy yourself.

Comment