You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm working on a dedicated server for a multiplayer game, both made in Godot.
Describe the problem or limitation you are having in your project
In single player games and multiplayer games where peers independently process and share their player's state (i.e. those where peers fully trust each other), the Input singleton is simply an awesome way to track input information. However, when you need to process multiple players' inputs in one Godot application instance, such as when making dedicated authoritative servers for multiplayer games, Input being a singleton becomes a problem, as you can't simply feed all of the players' inputs to it and then retrieve input data for each individual player (doing so will result in a completely useless Input state).
Describe the feature / enhancement and how it helps to overcome the problem or limitation
My proposal is to extract the "pure processing" part of Input into a separate class and make Input wrap/inherit it for compatibility.
This will allow to create one InputProcessor (or whatever we decide to call the "processing" part) instance per player and thus avoid mingling inputs of different players together, allowing to process and query different players' inputs independently.
One important thing to note is that this new class will purely focus on processing InputEvents fed to it (through parse_input_event): it will not invoke _input calls, it should not know about DisplayServers, etc.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
The interface should be as simple as:
class_namePlayerextendsNode# Independent of the global `Input` singletonvarmy_local_input_processor:=InputProcessor.new()
funcon_player_input_received_over_network(event: InputEvent) ->void:
self.my_local_input_processor.parse_input_event(event) # feed the input to the processor
If this enhancement will not be used often, can it be worked around with a few lines of script?
Negative* **, as you can't reset Input's state (other than wait a frame? (though that'd be a terrible "solution")).
But even if we could, there are still major problems:
We can't feed InputEvents to Input as they reach the server over the network (because, again, by the time you query Input it will be less than worthless), so we need to create an input buffer array for each player and push the InputEvents there.
Once we get to the point where we process a particular player, we need to Input.reset() and then re-fill it with the InputEvents from the corresponding buffer, which means instead of processing being spread out it is forced into a small window.
Input still being shared means that we won't be able to parallelize player processing.
*As was noted on Reddit by u/BrastenXBL, it's possible to work this around by adding a variable for every action (effectively "caching" InputEvents received over network for later consumption) and then using the event.is_action_pressed etc. methods instesd of methods on Input.
**As was noted on Reddit by u/jamopian, it's possible to work this around for the specific use case of authoritative servers by pre-processing InputEvents client-side into a simpler format before sending. For example, instead of sending an InputEventKey with .key == KEY_SPACE, one could send a custom enum variant ClientInputAction.WANT_TO_JUMP. However, this will, like all solutions that don't send raw input to the server, limit the potential effectiveness of an anti-cheat system.
Is there a reason why this should be core and not an add-on in the asset library?
This requires refactoring Input's code to decouple the "singleton" part from the "normal class" part. (As an example, the constructor currently sets singleton = this regardless of whether singleton == nullptr or not, which will lead to an overwrite when trying to simply create a subclass of Input and instantiate it. Similar story with the deconstructor.)
The text was updated successfully, but these errors were encountered:
Describe the project you are working on
I'm working on a dedicated server for a multiplayer game, both made in Godot.
Describe the problem or limitation you are having in your project
In single player games and multiplayer games where peers independently process and share their player's state (i.e. those where peers fully trust each other), the
Input
singleton is simply an awesome way to track input information. However, when you need to process multiple players' inputs in one Godot application instance, such as when making dedicated authoritative servers for multiplayer games,Input
being a singleton becomes a problem, as you can't simply feed all of the players' inputs to it and then retrieve input data for each individual player (doing so will result in a completely uselessInput
state).Describe the feature / enhancement and how it helps to overcome the problem or limitation
My proposal is to extract the "pure processing" part of
Input
into a separate class and makeInput
wrap/inherit it for compatibility.This will allow to create one
InputProcessor
(or whatever we decide to call the "processing" part) instance per player and thus avoid mingling inputs of different players together, allowing to process and query different players' inputs independently.One important thing to note is that this new class will purely focus on processing
InputEvent
s fed to it (throughparse_input_event
): it will not invoke_input
calls, it should not know aboutDisplayServer
s, etc.Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
The interface should be as simple as:
If this enhancement will not be used often, can it be worked around with a few lines of script?
Negative* **, as you can't reset
Input
's state (other than wait a frame? (though that'd be a terrible "solution")).But even if we could, there are still major problems:
InputEvent
s toInput
as they reach the server over the network (because, again, by the time you queryInput
it will be less than worthless), so we need to create an input buffer array for each player and push theInputEvent
s there.Input.reset()
and then re-fill it with theInputEvent
s from the corresponding buffer, which means instead of processing being spread out it is forced into a small window.Input
still being shared means that we won't be able to parallelize player processing.*As was noted on Reddit by u/BrastenXBL, it's possible to work this around by adding a variable for every action (effectively "caching"
InputEvent
s received over network for later consumption) and then using theevent.is_action_pressed
etc. methods instesd of methods onInput
.**As was noted on Reddit by u/jamopian, it's possible to work this around for the specific use case of authoritative servers by pre-processing
InputEvent
s client-side into a simpler format before sending. For example, instead of sending anInputEventKey
with.key == KEY_SPACE
, one could send a custom enum variantClientInputAction.WANT_TO_JUMP
. However, this will, like all solutions that don't send raw input to the server, limit the potential effectiveness of an anti-cheat system.Is there a reason why this should be core and not an add-on in the asset library?
This requires refactoring
Input
's code to decouple the "singleton" part from the "normal class" part. (As an example, the constructor currently setssingleton = this
regardless of whethersingleton == nullptr
or not, which will lead to an overwrite when trying to simply create a subclass ofInput
and instantiate it. Similar story with the deconstructor.)The text was updated successfully, but these errors were encountered: