Local/non-global `Input`

Godot Version

4.4.dev7

Question

I’m making a server for my multiplayer game and i dispatch InputEvents received from clients to server-processed ServerPlayer classes (one per player; mainly does the physics and synchronizes relevant properties like velocity and position back to the corresponding player). Now, i want to use Input in ServerPlayer’s code because, well, why wouldn’t i, it’s so useful, but it’s global nature (in that it automatically processes all InputEvents the application receives) makes it impossible to use it per-player as the various inputs will get mixed into a meaningless amalgamation.

Is there a way to stop Input from automatically consuming everything it gets it’s hands on and no re-implement things like Input.get_vector? Thanks.

for the Input singleton you will have to wrap it’s calls in multiplayer.is_server() or is_multiplayer_authority(); for the function override _input you can disable processing this by authority with the set_process_input() function like so

set_process_input(is_multiplayer_authority())

Sorry, i didn’t make myself clear enough. I have a single process, the server, that deals with many players (and therefore many “sets”/“channels” of inputs, one per player). The problem is that the Input singleton is, well, a singleton, it’s global and cannot (as far as i can see) be used as a normal class that i can instantiate per-player. I can’t feed inputs of all players to the global Input singleton, because then i won’t be able to query per-player input data (it will all be mixed together).

Sounds like your server is entirely subverting the Input system then and it’s of no use to you.

For anyone reading this, i’ve opened a proposal: Make Input usable as a generic input processor · Issue #11581 · godotengine/godot-proposals · GitHub

I read your proposal, i appreciate the idea to allow the use of input on the remote server as independent processing. But it does not reduce anti-cheat in any way.

A down side of syncing inputevent objects is that it could open you up for remote code injections as objects are not decoded by default unless you allow it. It becomes a risky design pattern.

Another downside is the input objects are large and will eat bandwidth. You are better off compressing bitfields and vectors.

1 Like

Sending raw input over the network will become cumbersome if the packet is lost, delayed, or reordered over the network.

I like to collect the input on the player side. After the player input is processed locally. The resulting encapsulated data can be sent to the server and be sanitized. (E.g. Normalizing vectors)

The data for input state should also be sent repeatedly to make sure you aren’t losing input events, as using reliable packets is not a great option, and the server can detect when the input is lost to control fairness with the client. A raw input system would make this hard to do as you would not want to repeat events on server side, and you also wouldn’t want to sync the whole Input Singleton state.

This method requires you to uncouple input from the player character class, but this also has some benefits as it allows you to create AI actors to control a player character class. All they need to do is generate some encapsulated data for the player class to consume.

It also makes setting up authority much easier, as the input can be set on its own node attached to the player.

But it does not reduce anti-cheat in any way.

I believe any solution that doesn’t provide raw input data (be it via InputEvent or through custom formats) does limit how far you can go with an anti-cheat

A down side of syncing inputevent objects is that it could open you up for remote code injections as objects are not decoded by default unless you allow it. It becomes a risky design pattern.

Absolutely, i only used it as an example that everyone will understand

Another downside is the input objects are large and will eat bandwidth. You are better off compressing bitfields and vectors.

Also very true

I like to collect the input on the player side. After the player input is processed locally. The resulting encapsulated data can be sent to the server and be sanitized. (E.g. Normalizing vectors)

The data for input state should also be sent repeatedly to make sure you aren’t losing input events, as using reliable packets is not a great option, and the server can detect when the input is lost to control fairness with the client. A raw input system would make this hard to do as you would not want to repeat events on server side, and you also wouldn’t want to sync the whole Input Singleton state.

I didn’t think about this, i agree this is a big problem. Can you clarify a bit your solution? I don’t quite understand what pre-processing inputs on the client-side will do to make sure packets aren’t lost?

This method requires you to uncouple input from the player character class, but this also has some benefits as it allows you to create AI actors to control a player character class. All they need to do is generate some encapsulated data for the player class to consume.

This is absolutely a benefit, although i think it wouldn’t be too terrible to make a “easy-to-input-by-hand bot input” → “real inputevents or whichever” converter.

It also makes setting up authority much easier, as the input can be set on its own node attached to the player.

Are you talking about multiplayer authority? I’m sorry, i don’t quite understand…

Yes

I thought about it some more, so i guess it doesnt matter, it actually makes sense to do a stream of input events. You could potentially have multiple inputs per network frame so you would want to preserve the order.

You will want to put input into unreliable packets to avoid TCP like acknowledgements, delaying the input packet unnecessarily. Packets can be reordered so we want to label them with a frame number or time stamp. Packets can be lost so we will want to send multiple previous input events per packet. (The server can buffer input a few frames and hopefully catch the next packet and pull from the input event history any missing input frames ). (There are also probably many other techniques, Overwatch will slow down time by buffering more input for a client that is dropping input, then speed up again to get the client back to normal time.)