Authenticating players

In this part, we will write the code to authenticate players.

It couldn't be simpler! W4's add-on provides a method named login_device_auto() that logs in a user without asking them anything. We can call it to authenticate a user.

You can find this function in the module W4GD.auth.

Because we are dealing with server communication, most functions in the W4 add-on are asynchronous and return a Request object. Any of these requests can result in an error. For example, if the player's internet connection is temporarily unavailable.

Because of that, we always want to store errors in our code.

Let's start by defining two variables we'll use to store the last error message in case we need to display it to players.

Add the following code to game_state.gd. You can find the script at autoloads/game_state.gd:

# If there was an error in the last server request, we will save the error message here.
var last_error := ""

# This will return true if there was an error in our last server request.
var has_error := false:
    get:
        return last_error != ""

Now, we can define the login() function. While we'll store error messages, we'll also design our functions to return true if the request succeeded. That way, we won't have to check for errors separately each time we make a server request.

func login() -> bool:
    # In case there was an error previously, we clear it.
    last_error = ""
    # We make an authentication request to W4 Cloud and wait for the result.
    var login_result = await W4GD.auth.login_device_auto().async()
    # We check for errors; if there's any, we store the error message.
    if login_result.is_error():
        last_error = login_result.as_error().message
        return false
    return true

Notice how we call the login_device_auto() of the W4 Auth class method:

await W4GD.auth.login_device_auto().async()

This illustrates a pattern you'll see often in communicating with W4. Most methods will return a Request object, which resolves later. This object is similar to promises in other programming languages.

Calling async() on this Request object allows you to use await to pause the function's execution and wait for the result.

The result from W4GD's API is a variant type, so we can't use static type inference with it. However, in practice, it's almost always a Result object.

All Result objects have an is_error() method to check if something went wrong. We store that in a variable that can be read outside the GameState autoload (to display errors to the user in the game's main menu, for example).

Note

What does login_device_auto() do?

All player authentication methods require an ID and a password. You can provide one manually with the login_device() method:

await W4GD.auth.login_device(login_uuid, login_key).async()

The login_device_auto() method wraps over it by generating a unique user id, a user key, and saving them in a config file for reuse.

Of course, if you'd like to use other authentication methods, such as email and password, you can!

And that's it for authentication!