Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Input usable as a generic input processor #11581

Open
elenakrittik opened this issue Jan 16, 2025 · 0 comments
Open

Make Input usable as a generic input processor #11581

elenakrittik opened this issue Jan 16, 2025 · 0 comments

Comments

@elenakrittik
Copy link

elenakrittik commented Jan 16, 2025

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 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_name Player extends Node

# Independent of the global `Input` singleton
var my_local_input_processor := InputProcessor.new()

func on_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.)

@Calinou Calinou changed the title Make Input usable as a generic input processor Make Input usable as a generic input processor Jan 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants