Creating online games using Nakama and Defold

Does the browser developer console give any clues? Your should be able to see the connection attempt and WebSocket upgrade request.

All the output from the browser console is listed in my previous post. It seems the connection is immediately refused in a browser, and magically works when run from Defold with the same code.

I’m more interested in the output from the Network tab of the developer tools in Chrome (or similar for Firefox or Safari). Like this:

1 Like

Oh, that’s really handy! And there is definitely something going on:

The above results are with the same code, the only difference being that it’s connecting to different servers.

Update: Using this technique to get the network log from Chrome gives these events:

19160: HTTP_STREAM_JOB
http://142.93.41.41:7350/
Start Time: 2021-03-04 09:25:38.857

t=79026 [st=0] +HTTP_STREAM_JOB  [dt=0]
                --> expect_spdy = false
                --> original_url = "http://142.93.41.41:7350/"
                --> priority = "MEDIUM"
                --> source_dependency = 19159 (HTTP_STREAM_JOB_CONTROLLER)
                --> url = "http://142.93.41.41:7350/"
                --> using_quic = false
t=79026 [st=0]    HTTP_STREAM_JOB_WAITING  [dt=0]
                  --> should_wait = false
t=79026 [st=0]   +HTTP_STREAM_JOB_INIT_CONNECTION  [dt=0]
t=79026 [st=0]      TCP_CLIENT_SOCKET_POOL_REQUESTED_SOCKET
                    --> group_id = "pm/142.93.41.41:7350"
t=79026 [st=0]     +SOCKET_POOL  [dt=0]
t=79026 [st=0]        SOCKET_POOL_REUSED_AN_EXISTING_SOCKET
                      --> idle_ms = 0
t=79026 [st=0]        SOCKET_POOL_BOUND_TO_SOCKET
                      --> source_dependency = 19149 (SOCKET)
t=79026 [st=0]     -SOCKET_POOL
t=79026 [st=0]   -HTTP_STREAM_JOB_INIT_CONNECTION
t=79026 [st=0]    HTTP_STREAM_JOB_BOUND_TO_REQUEST
                  --> source_dependency = 19157 (URL_REQUEST)
t=79026 [st=0] -HTTP_STREAM_JOB 
19161: URL_REQUEST
ws://142.93.41.41/ws?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIzMTZlOGNmYS0xOWUwLTRiYzYtYTBiOC05NmE4ZTEzMzE0NjEiLCJ1c24iOiJRUUpwVkVUSFJiIiwiZXhwIjoxNjE0ODQ5OTk5fQ.9SiTdL6fFjrsO2dovSTDSFOqkws6CFxWkDpw__cQiKY
Start Time: 2021-03-04 09:25:38.928

t=79097 [st= 0] +REQUEST_ALIVE  [dt=24]
                 --> priority = "LOWEST"
                 --> traffic_annotation = 17188928
                 --> url = "ws://142.93.41.41/ws?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIzMTZlOGNmYS0xOWUwLTRiYzYtYTBiOC05NmE4ZTEzMzE0NjEiLCJ1c24iOiJRUUpwVkVUSFJiIiwiZXhwIjoxNjE0ODQ5OTk5fQ.9SiTdL6fFjrsO2dovSTDSFOqkws6CFxWkDpw__cQiKY"
t=79097 [st= 0]    NETWORK_DELEGATE_BEFORE_URL_REQUEST  [dt=0]
t=79097 [st= 0]   +URL_REQUEST_START_JOB  [dt=24]
                   --> initiator = "http://bullet_rain.totebo.com"
                   --> load_flags = 18 (BYPASS_CACHE | DISABLE_CACHE)
                   --> method = "GET"
                   --> network_isolation_key = "http://totebo.com http://totebo.com"
                   --> privacy_mode = "disabled"
                   --> site_for_cookies = "SiteForCookies: {scheme=http; registrable_domain=totebo.com; schemefully_same=true}"
                   --> url = "ws://142.93.41.41/ws?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIzMTZlOGNmYS0xOWUwLTRiYzYtYTBiOC05NmE4ZTEzMzE0NjEiLCJ1c24iOiJRUUpwVkVUSFJiIiwiZXhwIjoxNjE0ODQ5OTk5fQ.9SiTdL6fFjrsO2dovSTDSFOqkws6CFxWkDpw__cQiKY"
t=79097 [st= 0]      NETWORK_DELEGATE_BEFORE_START_TRANSACTION  [dt=0]
t=79097 [st= 0]      HTTP_CACHE_GET_BACKEND  [dt=0]
t=79097 [st= 0]     +HTTP_STREAM_REQUEST  [dt=24]
t=79097 [st= 0]        HTTP_STREAM_JOB_CONTROLLER_BOUND
                       --> source_dependency = 19162 (HTTP_STREAM_JOB_CONTROLLER)
t=79121 [st=24]        HTTP_STREAM_REQUEST_BOUND_TO_JOB
                       --> source_dependency = 19163 (HTTP_STREAM_JOB)
t=79121 [st=24]     -HTTP_STREAM_REQUEST
t=79121 [st=24]   -URL_REQUEST_START_JOB
                   --> net_error = -102 (ERR_CONNECTION_REFUSED)
t=79121 [st=24]    URL_REQUEST_DELEGATE_RESPONSE_STARTED  [dt=0]
t=79121 [st=24] -REQUEST_ALIVE
                 --> net_error = -102 (ERR_CONNECTION_REFUSED)
#### 19162: HTTP_STREAM_JOB_CONTROLLER

#### ws://142.93.41.41/ws?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIzMTZlOGNmYS0xOWUwLTRiYzYtYTBiOC05NmE4ZTEzMzE0NjEiLCJ1c24iOiJRUUpwVkVUSFJiIiwiZXhwIjoxNjE0ODQ5OTk5fQ.9SiTdL6fFjrsO2dovSTDSFOqkws6CFxWkDpw__cQiKY

Start Time: 2021-03-04 09:25:38.928

t=79097 [st= 0] +HTTP_STREAM_JOB_CONTROLLER [dt=24] --> is_preconnect = false --> url = "ws://142.93.41.41/ws?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIzMTZlOGNmYS0xOWUwLTRiYzYtYTBiOC05NmE4ZTEzMzE0NjEiLCJ1c24iOiJRUUpwVkVUSFJiIiwiZXhwIjoxNjE0ODQ5OTk5fQ.9SiTdL6fFjrsO2dovSTDSFOqkws6CFxWkDpw__cQiKY" t=79097 [st= 0] HTTP_STREAM_JOB_CONTROLLER_BOUND [ --> source_dependency = 19161 (URL_REQUEST)](https://netlog-viewer.appspot.com/#events&s=19161) t=79097 [st= 0] +PROXY_RESOLUTION_SERVICE [dt=0] t=79097 [st= 0] PROXY_RESOLUTION_SERVICE_RESOLVED_PROXY_LIST --> pac_string = "DIRECT" t=79097 [st= 0] -PROXY_RESOLUTION_SERVICE t=79097 [st= 0] HTTP_STREAM_JOB_CONTROLLER_PROXY_SERVER_RESOLVED --> proxy_server = "DIRECT" t=79097 [st= 0] HTTP_STREAM_REQUEST_STARTED_JOB [ --> source_dependency = 19163 (HTTP_STREAM_JOB)](https://netlog-viewer.appspot.com/#events&s=19163) t=79121 [st=24] -HTTP_STREAM_JOB_CONTROLLER
19163: HTTP_STREAM_JOB
ws://142.93.41.41/
Start Time: 2021-03-04 09:25:38.928

t=79097 [st= 0] +HTTP_STREAM_JOB  [dt=24]
                 --> expect_spdy = false
                 --> original_url = "ws://142.93.41.41/"
                 --> priority = "LOWEST"
                 --> source_dependency = 19162 (HTTP_STREAM_JOB_CONTROLLER)
                 --> url = "ws://142.93.41.41/"
                 --> using_quic = false
t=79097 [st= 0]    HTTP_STREAM_JOB_WAITING  [dt=0]
                   --> should_wait = false
t=79097 [st= 0]   +HTTP_STREAM_JOB_INIT_CONNECTION  [dt=24]
t=79097 [st= 0]      TCP_CLIENT_SOCKET_POOL_REQUESTED_SOCKET
                     --> group_id = "142.93.41.41:80"
t=79097 [st= 0]     +SOCKET_POOL  [dt=24]
t=79098 [st= 1]        SOCKET_POOL_BOUND_TO_CONNECT_JOB
                       --> source_dependency = 19164 (WEB_SOCKET_TRANSPORT_CONNECT_JOB)
t=79121 [st=24]     -SOCKET_POOL
                     --> net_error = -102 (ERR_CONNECTION_REFUSED)
t=79121 [st=24]   -HTTP_STREAM_JOB_INIT_CONNECTION
t=79121 [st=24]    HTTP_STREAM_JOB_BOUND_TO_REQUEST
                   --> source_dependency = 19161 (URL_REQUEST)
t=79121 [st=24] -HTTP_STREAM_JOB

The last one has a “group id” of 142.93.41.41:80. Maybe it’s something to do with it trying to connect to port 80 (as per this thread)? Over an ssl connection, the port would default to 443, which may explain why it works over ssl?

Yeah, there might be something going on with port 80 vs 7350.

1 Like

Confirmed! Changing the Nakama server and client to run on port 80 fixes the issue:

This will now allow me to continue developing this test game! :partying_face: Still, let me know if I can help figure out why the default Nakama port doesn’t work.

4 Likes

Happy to hear you managed to solve it by changing port. Perhaps @novabyte knows why port 7350 doesn’t work in an HTML5 build?

2 Likes

@britzl I have a simple question.

I would like to implement online multiplayer mode for my game but ONLY for testing purpose of the LOCAL multiplayer mode. The game is an arcade / action. I am planning to exchange only input and no game state (again, just for testing).

Is this example using Nakama suitable for my needs?

Thank you so much!

It feels like a pretty complicated way of testing local multiplayer, but yes, using Nakama should work!

Ahahah, It is just that I am alone at home (thank you corona virus!) and my art director and friend is in her house…

1 Like

To conclude on this, I can confirm that the latest update to the Websocket extension fixes this! :partying_face:

4 Likes

I also have trouble getting this example to work with my own server:

So far, nobody was able to help.

You have received a reply on the HeroicLabs forum a few hours ago: Ways to debug server code (Nakama Defold tictactoe XOXO example) - #8 by flavio - Heroic Labs

Thanks Britzl! Now it kinda works, but the bug with the default (Defold?) port for Nakama still persists. That is not fixed for me. I have the newest Defold and Nakama.

I added a PR for this change to the server. Please merge it for everyone else. Thanks!

Thanks. I’ll take a look soon.

Which bug is that?

When you run locally with the default nakama port both players win when one player wins.

I started my playtest with Nakama once again, now following this tutorial and found some issues. Here is my experience:

Nakama local server setup

Running Nakama server from Docker was flawless on Ubuntu following just this few commands (I already had docker installed, old, but enough), but the link in tutorial is not pointing directly to the page mentioned (correct link is now: Heroic Labs Documentation | Docker Compose):

$ docker --version
Docker version 20.10.24, build 297e128
$ git clone https://github.com/heroiclabs/nakama-project-template.git
Cloning into 'nakama-project-template'...
...
$ cd nakama-project-template/
$ docker compose up

You might want to need to run docker with sudo.

Then the server is booting up and a lot is printed in console and the last message is:

backend           | {"level":"info","ts":"2023-06-18T08:59:38.242Z","caller":"main.go:175","msg":"Startup done"}

If everything is ok (like it was for me) you can open server website/admin panel on any web browser at http://127.0.0.1:7351 and login with admin and password default credentials. It is a server you run locally, so perfect for testing.

Defold integration

Defold integration have a picture of used libraries - it would be great to put there links as well. After quick search you can find it of course, but it would be good to have them in tutorial. Newest versions are 3.1.0 and that’s what I used rn (version from tutorial is not compiling websocket native extension on this day).

image

Links:
https://github.com/heroiclabs/nakama-defold/archive/3.1.0.zip
https://github.com/defold/extension-websocket/archive/3.1.0.zip

Following the first few steps I have an initial code:

local defold = require "nakama.engine.defold"

-- The Nakama server configuration
local config = {}
config.host = "127.0.0.1" -- localhost, ie your own machine
config.port = 7351
config.use_ssl = (config.port == 443)
config.username = "admin" -- your Nakama server key, default is "defaultkey"
config.password = "password"
config.engine = defold -- Tell Nakama to use Defold (it can theoretically also work with other Lua based engines)


-- authentication using device id
local function device_login(client)
	-- login using the token and create an account if the user
	-- doesn't already exist
	local result = nakama.authenticate_device(client, defold.uuid(), nil, true)
	if result.token then
		-- store the token and use it when communicating with the server
		nakama.set_bearer_token(client, result.token)
		return true
	end	
	print("Unable to login")
	return false
end


function init(self)
	local client = nakama.create_client(config)
	device_login(client)
end

A small issue is that 127.0.0.1 is malformed number:
image

So I put it as a string. I don’t know yet, if this is wrong or not, but will probably find out! :smiley:

And here I am stopped at the moment, because:

image

Even though the extensions are fetched:

image

Can’t find any similar problem on forum, so I would love a help! :wink:


UPDATE 1:

Duck-debugging is always helpful, so after writing it down, I noticed in the code there is no require and nakama is not included in the namespace like e.g. defos is, but there is a Lua module named nakama, so I guess this is fixing the issue (but this is the issue after following tutorial, so I have to note it down, for improvement):

local nakama = require "nakama.nakama"

Next is that Nakama must be run from within a coroutine:

image


UPDATE 2:

So I put it in coroutine like this:

function init(self)
	local co = coroutine.create(function()
		local client = nakama.create_client(config)
		device_login(client)
	end)

	local ok, err = coroutine.resume(co)
end

And for now I am not able to log in, so will try to debug it:

image

But one user account is at least found in my local server admin dashboard:

But it’s a system user :sweat_smile:

By printing result I get:

image

So, I guess the user is not found, so can’t log in. Strange, because the call is to create the user
( @param create_bool () Register the account if the user does not already exist.)

2 Likes

Not entirely true. You can either run from within a coroutine to get nice looking synchronous code as in your example, but you could also use a callback:

local id = defold.uuid()
local vars = nil
local create = true
local username_str = nil
nakama.authenticate_device(client, id, vars, create_bool, username_str, function(result)
    if result.token then
		-- store the token and use it when communicating with the server
		nakama.set_bearer_token(client, result.token)
	end	
end)

That’s strange. No idea what’s going on there!

I think you need to set the username_str when creating the user.

1 Like

Yes, this is also working, good to know! (but I just noted what is an error that is given to user when following the tutorial).

From the code I understand the config.host actually should be string, so the tutorial should be corrected imho.

It didn’t help :confused: All the time I got response:

DEBUG:SCRIPT: Logging in,
{ --[[0x7f62429e2940]]
  message = "Not Found",
  error = true,
  code = 5
}

Socket creation

This also is problematic following the code from the tutorial, because there are simply no such functions in nakama Lua module:

local socket = nakama.create_socket(client)
local ok, err = nakama.socket_connect(socket)

Instead, I found those:

local nakama_socket = require "nakama.socket"
local socket = nakama_socket.create(client)
local ok, err = nakama_socket.connect(socket)

But it for now is not working for me, because of the previous problem, without any user, resulting in not heaving a correct bearer_token :confused:

True. I’ll see if I can update the tutorial to work with the latest version of Nakama!

1 Like