How to handle private state?

I have a Godot+Lua authoritative server. There are some backend variables that are specific to a match, but should not be shown to the client. For example, you should not send the positions of other players to a client in an FPS, or they can wall hack. So you cannot put them in the state variable returned by the match handlers.

How do you handle such variables? You could use storage, sure, but that’s not match-specific, and possibly a performance drain. It seems that variables inside the match_handler module (and their includes) are match specific, so is it okay to use them? Anyhow, that’s what I’m using as of now.

And as a side note, what happens to the variables inside modules with registered functions, such as RPCs? Do they persist for the duration of the server, or only the duration of the RPC call?

Finally, I would suggest noting in the authoritative multiplayer docs page that you should not put state accessible to the players in the state variable. That was unclear to me until I discovered the received_match_state signal.

Hi @Bobit,

I’m not sure I understand the issue - the match state is not directly accessible to the outside world unless you make it so in your custom code, if you want to omit specific variables you should just return a subset in your match signal implementation, the same applies to messages that you send as part of your match loop, am I missing something?

As for RPCs, the variable lifetime depends on their scope, but the best practice is to scope them to the RPC, meaning they won’t persist across calls. If you’re using the Go runtime, you can set global variables but this is bad practice, requires careful synchronization logic, and won’t work in a clustered setting. Anything that needs to be persisted across calls should go to the database. For the Lua runtime specifically, never use globally scoped variables, you won’t observe correct behavior because Nakama pools Lua VMs for performance, meaning the global variables are per VM and not per Nakama server. The exception would be authoritative matches, which run a single Lua VM per running match, but even there avoid global variable and use the provided match state to mutate/propagate it across ticks.

Hope this clarifies.

1 Like