Jump to content

[1.10.2] Keybind Change Event


Izzy Axel

Recommended Posts

I'm pretty sure there isn't, but is there a Forge event or a light way to detect the player making keybinding changes?

If the KeyEvent gets called when the player is in the Gui you could just check if the current gui is an instance of the KeyBind Changing gui.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

I'm pretty sure there isn't, but is there a Forge event or a light way to detect the player making keybinding changes?

If the KeyEvent gets called when the player is in the Gui you could just check if the current gui is an instance of the KeyBind Changing gui.

 

 

The problem with that is GuiKeyBindingList doesnt inherit from GuiScreen, so both checking Minecraft#currentScreen and using the KeyboardInputEvent and checking GuiScreenEvent#getGui() don't work.

Link to comment
Share on other sites

I'm pretty sure there isn't, but is there a Forge event or a light way to detect the player making keybinding changes?

If the KeyEvent gets called when the player is in the Gui you could just check if the current gui is an instance of the KeyBind Changing gui.

 

 

The problem with that is GuiKeyBindingList doesnt inherit from GuiScreen, so both checking Minecraft#currentScreen and using the KeyboardInputEvent and checking GuiScreenEvent#getGui() don't work.

I believe it is actually GuiControls.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

That works for the keyboard, but not for binding things to the mouse...

 

 

[edit] Actually it doesn't work quite right anyway:

 

 

	@SubscribeEvent
public void changeKeybind(GuiScreenEvent.KeyboardInputEvent.Post event)
{
	if(event.getGui() instanceof GuiControls)
	{
		Sapphire.LOGGER.info("Sapphire: ", "Keybind changed");
	}
}

It prints twice, and it'll activate when a key is pressed on the screen in general, not just when a keybind is changed.  This will fire a series of packets, so I want to minimize how often this is triggered to only when necessary.  It would be ideal to have it only happen when a keybind is changed to a key different to the one it is atm, and for the event to provide the keybind name and new key, so only that info would have to be sent in a single packet.

Link to comment
Share on other sites

The server should do nothing with keybinds, ever.

 

 

Its there for the user of the API to check against, and nothing more.

Save it client side and not server side.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

No matter who does it or what for: Keybinds have no business on the server. The server merely gets told by the client "hey, the user pressed the key with function X" (not: "the user pressed the key labeled 'l'", but "the user pressed the key that turns on the flashlight").

I was just saying that he should save it client side if anything.

That works for the keyboard, but not for binding things to the mouse...

 

 

[edit] Actually it doesn't work quite right anyway:

 

 

	@SubscribeEvent
public void changeKeybind(GuiScreenEvent.KeyboardInputEvent.Post event)
{
	if(event.getGui() instanceof GuiControls)
	{
		Sapphire.LOGGER.info("Sapphire: ", "Keybind changed");
	}
}

It prints twice, and it'll activate when a key is pressed on the screen in general, not just when a keybind is changed.  This will fire a series of packets, so I want to minimize how often this is triggered to only when necessary.  It would be ideal to have it only happen when a keybind is changed to a key different to the one it is atm, and for the event to provide the keybind name and new key, so only that info would have to be sent in a single packet.

Sadly to accomplish this you would need access to what keybind they are changing , which I can not think of a way to do this without a specific event. You would need to submit a pull request for it.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

I suspect you could, on the client side, somehow associate raw key presses with the keybindings being generated to figure out what the current association is. Then if really desired on the server you could send a custom packet to sync server.

 

However, as mentioned by other people this is a very odd use case. The whole point of keybinding is to allow user to use keys without the server caring about it.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

The server still doesn't *care* about it, it's for the end user of the API to check against, my original design was to keep an array of structs on the server of each player's keystates and current keybinding info, to make it very easy to query keypresses, only requiring a player's entity ID and the current desired keybinding's keycode, which is why I wanted to store keybinding info server-side.

 

 

The idea was for keystate info to be available to the dev using the API, server-side, with no "boilerplate" code involved, but I'm currently evaluating moving it to a callback event system instead, where the user registers an implementing class instance for a key or set of keys. (Frankly I'm not sure why I'm doing that, other than I don't want to deal with dogmatic preaching about how bad and wrong, it is, I guess.  The original system works beautifully on both SSP and SMP, btw, and is sterile.)

 

 

Without the keybind change event, I had to resort to sending update packets on entity construction and at intervals, so I wanted to make sure I couldn't make it more efficient.  That's what this question was about/why it was asked and the background on what it's used for.  If I go through with the callback route, I won't need to do this anymore.

 

 

Here's a bit of an excerpt from an example jetpack I made, to show you what it does in practice: Example

Link to comment
Share on other sites

You could create a store of the current keybindings when the game starts up and then every 10 frames or so, check to see if the current keybindings are different to when the game started up. If they are, you could do whatever you need to do with that information and then update the store of keybindings so that the check isn't triggered unintentionally.

I love solving puzzles and also coding. What a great combo! I also want to have a career in programming when I have gone through university. 9GAG and Quora stand in the way of me ascending from mediocre programmer to ...meh programmer and beyond!

 

I am always looking for fun projects to look at and maybe be a part of. If you have a project and want to co-operate, email me via jamesyeoman10@gmail.com

 

Keep coding :)

Link to comment
Share on other sites

You could create a store of the current keybindings when the game starts up and then every 10 frames or so, check to see if the current keybindings are different to when the game started up. If they are, you could do whatever you need to do with that information and then update the store of keybindings so that the check isn't triggered unintentionally.

 

 

I think that's much too frequent, I had the updates at 30 second intervals (I don't think people don't change their keybinds that much lol) and I have a config option for it, bounded at min 10 seconds.

Link to comment
Share on other sites

Here's a bit of an excerpt from an example jetpack I made, to show you what it does in practice: Example

 

While that looks elegant, that's really not how things should work (i.e. the server knowing about keypresses).

In reality what that API should do is take the packets sent from the client about when the client presses buttons, and store that information.

 

What I did in 1.7.10 was rather hacky as all I was trying to do was work around an issue with liquids and not being able to jump out of them, but on the client side of things I listened for "is the player trying to jump and are they in water?" and if so, tell the server "hey, this player is swimming."

 

So then on the server:

https://github.com/Draco18s/HarderStuff/blob/master/src/main/java/com/draco18s/hazards/HazardsEventHandler.java#L88-L90

 

You'd essentially do the same thing: "Hey this player is doing the thingamajig" and the server goes "ok, I can remember that."  The server gives no fucks about keybinds instead it cares about what the player is doing.  You can still refer to it like a keybind, but it's not.  Instead it's the client saying "the player is giving me [x input]."  No listening to keybind changes necessary.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

The server still doesn't *care* about it, it's for the end user of the API to check against, my original design was to keep an array of structs on the server of each player's keystates and current keybinding info, to make it very easy to query keypresses, only requiring a player's entity ID and the current desired keybinding's keycode, which is why I wanted to store keybinding info server-side.

 

I guess I'm still confused as to your purpose. Why would "end user of the API" want to check this?

 

The whole point of keybinding is to allow users to map keys without anyone else needing to know about it. And if you mean you want to allow another mod to know about it, well they can have their client-side code check out the keybinds directly.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

The server still doesn't *care* about it, it's for the end user of the API to check against, my original design was to keep an array of structs on the server of each player's keystates and current keybinding info, to make it very easy to query keypresses, only requiring a player's entity ID and the current desired keybinding's keycode, which is why I wanted to store keybinding info server-side.

 

I guess I'm still confused as to your purpose. Why would "end user of the API" want to check this?

 

The whole point of keybinding is to allow users to map keys without anyone else needing to know about it. And if you mean you want to allow another mod to know about it, well they can have their client-side code check out the keybinds directly.

 

 

Yes, they can do that client side.  The core idea of Sapphire is to reduce the work other mods have to do to a minimum while retaining flexibility.  The keybindings map is to counteract moving user-level (API user that is) keyhandling to the server.  On the client side, its really easy to check the current keycode for x action, so if I'm moving those interactions to the server to get rid of all the code normally written to send packets to the server and act on them in a standard keyhandling system, I want to retain how easy it is to check if the key is down, and for that I need the given user's current keybinding layout. (and lets be honest here, this system also takes out the possibility of the user doing some really messy, overwrought, bad things, and sending way too many packets)

 

 

Its just...I have yet to get an answer that holds water as to why storing and updating keystates on the server like this is a legitimate problem, so it just sounds like dogma to me.

Link to comment
Share on other sites

Its just...I have yet to get an answer that holds water as to why storing and updating keystates on the server like this is a legitimate problem, so it just sounds like dogma to me.

 

In a way it is, but it is dogma that is based on experience. Now maybe it doesn't matter so much in Minecraft which is only keyboard-controlled. But when I'm programming my own games I usually want to provide options where controls coming into the server can come from end users who are either local, remote, and using either gamepad controller or keyboard. In that case, it is easier to maintain a scheme where the server just receives functional commands ("move left", "strafe right", "jump") and the clients convert whatever the user happens to prefer for input to those commands.

 

Technically though you can certainly do the conversion on the server.

 

I think my main argument to you would be that people who play minecraft may play across multiple servers but prefer to have same keybindings on each. In other words, it is logically a setting that carries along with the client. So makes more sense to handle it in the client, store it as a preference on the client machine, and so forth. If the master information on keybindings was stored on the server, then user would have to go through extra work to configure on each server, and that might be a (minor) pain.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

Its just...I have yet to get an answer that holds water as to why storing and updating keystates on the server like this is a legitimate problem, so it just sounds like dogma to me.

 

In a way it is, but it is dogma that is based on experience. Now maybe it doesn't matter so much in Minecraft which is only keyboard-controlled. But when I'm programming my own games I usually want to provide options where controls coming into the server can come from end users who are either local, remote, and using either gamepad controller or keyboard. In that case, it is easier to maintain a scheme where the server just receives functional commands ("move left", "strafe right", "jump") and the clients convert whatever the user happens to prefer for input to those commands.

 

Technically though you can certainly do the conversion on the server.

 

I think my main argument to you would be that people who play minecraft may play across multiple servers but prefer to have same keybindings on each. In other words, it is logically a setting that carries along with the client. So makes more sense to handle it in the client, store it as a preference on the client machine, and so forth. If the master information on keybindings was stored on the server, then user would have to go through extra work to configure on each server, and that might be a (minor) pain.

 

 

The server doesn't change keybindings at all, it only keeps a record of the clients current keybinding and polls it lazily, if the user changes his keybindings outside a server, the next time he logs onto the server, the server's record will be updated, not the other way around.  And this isn't persistent data, the server doesn't save any of this info to a file, there's no reason to, its all generated dynamically.

 

 

I do get that reasoning, and I wouldn't do this if it made switching control types harder/break, but my system works entirely off of Minecraft's GameSettings#keyBindings, I never do anything with raw LWJGL keyboard input.  That's why I need the Keybinding map on the server, so a user of the API can ask for "JUMP" and "FORWARD" and "SLOT_6" and "ATTACK" enums, and it'll give them the correct key's state no matter what the player sets it to.  This keeps things generic and modular, if that's the right word; there's no hardcoding.

Link to comment
Share on other sites

The core idea of Sapphire is to reduce the work other mods have to do to a minimum while retaining flexibility.

 

So I'm moving those interactions to the server to get rid of all the code normally written to send packets to the server and act on them in a standard keyhandling system

 

This is stupid.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

my system works entirely off of Minecraft's GameSettings#keyBindings, I never do anything with raw LWJGL keyboard input.  That's why I need the Keybinding map on the server, so a user of the API can ask for "JUMP" and "FORWARD" and "SLOT_6" and "ATTACK" enums, and it'll give them the correct key's state no matter what the player sets it to.  This keeps things generic and modular, if that's the right word; there's no hardcoding.

 

Okay, if you really want to do this...shouldn't be too hard.

 

GameSettings and KeyBinding classes are only client side. So if you really want to get that information over to the server, I suppose I'd just copy those classes into custom classes that exist on the server, then both at beginning of session with player and also any time player exits the gui that allows keybinding changes, I would send a custom packet to the server that contains sufficient information to populate the server side version.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

KeyHandler

 

 

Ok, now what?  This seems like way too thin a wrapper, and the things a player could want to do with a key handling packet are so varied, arbitrary, and limited to what can be realistically serialized...there's no way I could create a generic or templated packet that's of any use to anyone.  Please, point it out if I'm derping, but I'm not seeing anything else helpful I can do for the user with this system.  Put it all together, and this system just seems to be worthless in it's existence in comparison to what the keystate map system does for the API user.

Link to comment
Share on other sites

As others have said, the server should handle the actions of the keybinds rather than the keybinds themselves. Solutions involving working with keybinds on the server are not really solutions at all because they just cause more problems.

 

 

And what problems would those be?  As stated before the server doesn't alter the keypresses, it's storing a map of booleans.

 

 

Anyway, updated to callback on whole groups at once when any of them are pressed:

 

 

New Keyhandler

Link to comment
Share on other sites

The way I would design this:

 

- Server has a set of actions that can be performed by keys. It does not know the keys.

- Client also has this set but on here each action is bound to a Keybinding.

- Instead of transmitting "key X is pressed!" you transmit "action XYZ is triggered!".

- API on the server stays the same, you just substitute "key" for "action".

 

 

That alone would be restrictive to whatever the API has previously defined, that'd need to be an add-on to the primary "freeform" functionality.  It'd be fine to offer a set of prebuilt actions, but I'm not sure what else beyond the standard "space for jetpack" would be useful to add?

 

 

The system I have atm is starting to feel less pointless though since you can register a cluster of keys to one class and be informed of the state of all of them when one is pressed.  That change was made because I realized when making an example jetpack, simply changing the player's motionY value makes horizontal movement silly levels of slow, so I had to simultaneously monitor the cardinal movement keys and "reimplement" ground movement in the air with that info.

Link to comment
Share on other sites

I did not say anything about prebuilt actions. Make the user create an action object and register it with a ResourceLocation. Hell, you can even use FMLs registry system for this so you will get automatically assigned integer IDs for fast network communication.

 

 

Oh...derp, I've already done something similar with the API's action scheduling system, not sure why I didn't get what you meant :P

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.