Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

Keyboard input


EducationalPurposes
 Share

Recommended Posts

Hi,

 

As the title says I need to know if a player presses a key or not. Luckily, we got lwjgl, so that is not really a problem for me.

But I dont know how to follow a player's keystrokes. For example, currently I have setup a system, that adds the players to a list who do a certain thing, but I am really unsure how to follow that specific player's key stuff.

 

I know you must follow the keystrokes client side, but I dont know how I can get on someone's client side or anything.

 

So a recap:how can I get into a player's client?

 

Im not expecting the practical work-out, but I do really like to see some theory what steps I should follow. Not in great detail or anything, but just something that you guys point me in the right direction.

 

Thanks, EducationalPurposes

 

I am fairly new to Java and modding, so my answers are not always 100% correct. Sorry for that!

Link to comment
Share on other sites

That is a really good tutorial about keybinding, thanks for that. But what Im looking for is for every key on your keyboard, and then keybinding isnt a real good idea.

 

Thanks for the effort though!

I am fairly new to Java and modding, so my answers are not always 100% correct. Sorry for that!

Link to comment
Share on other sites

Hi

 

If I understand you right, you know how to read keypresses from Keyboard, but you're not sure how to get them from each client to the server?

 

You need to use a custom packet for that - each time the client presses your key of interest, you need to read that on the client (eg in a tick handler), send a packet to the server, then have the server process the packet.

 

http://www.minecraftforge.net/wiki/Packet_Handling

 

-TGG

 

PS this link might also be useful

http://greyminecraftcoder.blogspot.com.au/2013/10/user-input.html

Link to comment
Share on other sites

Hi

 

If I understand you right, you know how to read keypresses from Keyboard, but you're not sure how to get them from each client to the server?

 

You need to use a custom packet for that - each time the client presses your key of interest, you need to read that on the client (eg in a tick handler), send a packet to the server, then have the server process the packet.

 

http://www.minecraftforge.net/wiki/Packet_Handling

 

-TGG

 

PS this link might also be useful

http://greyminecraftcoder.blogspot.com.au/2013/10/user-input.html

 

That helped quite a bit, thank you for that. But I dont get how you can the actual key input of the client.

I have my tick handler implement ITickHandler, but Im very unsure how to do custom stuff to the actual client.

 

If I understand that, I think I get a big part of minecraft modding, since I never use  those sided Proxies and stuff.

I am fairly new to Java and modding, so my answers are not always 100% correct. Sorry for that!

Link to comment
Share on other sites

Hi

 

The code would look something like

 

boolean myKeyOfInterestIsDown = false;

[code]MyClientTickHandlerMethod() {
  boolean newKeyDown = Keyboard.isKeyDown(MY_KEY_OF_INTEREST);
  if (newKeyDown) {
    if (!myKeyOfInterestIsDown) {
       //send a custom packet to the server to say "I have just received a keypress for MY_KEY_OF_INTEREST" - i.e. when the key goes from up to down
    }
  }
  myKeyOfInterestIsDown = newKeyDown;
}

[/code]

 

look at the start of KeyBoard for the suitable keycodes

eg

public static final int KEY_Q              = 0x10;

 

-->Keyboard.isKeyDown(KEY_Q);

 

There are two main ways I've found helpful when interacting with the vanilla code.

The first is to use one of the many Forge registries or hooks, to add custom blocks, items, or get called when particular things happen.  This is very common.  Unfortunately the documentation is a bit patchy so it's not always easy to know what's available.  A typical strategy I use is to identify an item or block or whatever that does something similar to what I need.  Then I'll look at the vanilla code and trace it through until I figure out how it works, and usually I will stumble over a forge hook or event along the way.

 

The second strategy which is harder and less robust is to override an existing vanilla class and replace any references to it from other vanilla code.  For example, you can overwrite GameSettings.keyBindForward with your own class derived from KeyBinding.  This is usually not necessary and is often not possible.

 

A third strategy which I haven't had to use yet is to edit the base classes to overwrite the vanilla.  ("base mod")  This will probably break everytime Minecraft is updated.

 

A fourth strategy you will hear occasionally is reflection / ASM.  I would avoid this like the plague because it is fragile and very hard to debug.  I had my fill of self-modifying code back in my days of programming assembly and am not keen to go back!!

 

-TGG

 

 

 

 

 

Link to comment
Share on other sites

I'd recommend using KeyHandler, for compatibility, ease of use, and auto registration of keys into the controls menu, for player convenience.

 

@TheGreyGhost:

Your second, third and fourth strategies would basically break compatibility the same way. They do roughly the same thing.

But reflection is different from ASM.

Reflection is a powerful type of code to make mods compatible between each other without dependency. A practical example is the Forge annotations, those are loaded with reflection. Manipulating classes at runtime, that is the goal of reflection.

ASM is an extremely powerful tool (to break everything without knowing :P) relying on bytecode (read: manipulating lines of code, at an "internal" level). If you master it, you can change as much things as Forge without shipping Minecraft code.

A practical example is the Forge event system, which use @ForgeSubscribe in a mod class to hook with reflection, then apply changes with ASM.

Link to comment
Share on other sites

Hi

 

I'd recommend using KeyHandler, for compatibility, ease of use, and auto registration of keys into the controls menu, for player convenience.

Wish I'd heard of that before.  Do you have a link with more information on it, and where/how it's called from the vanilla code?

 

@TheGreyGhost:

Your second, third and fourth strategies would basically break compatibility the same way. They do roughly the same thing.

Well, the difference to my mind is that the second strategy (overriding a single method) is less likely to be broken if the vanilla classes are updated, compared with overwriting the entire class with a modified copy, or god forbid relying on the bytecode being the same.  But I agree it's not as robust as using the forge methods.

 

But reflection is different from ASM.

Reflection is a powerful type of code to make mods compatible between each other without dependency. A practical example is the Forge annotations, those are loaded with reflection. Manipulating classes at runtime, that is the goal of reflection.

ASM is an extremely powerful tool (to break everything without knowing ) relying on bytecode (read: manipulating lines of code, at an "internal" level). If you master it, you can change as much things as Forge without shipping Minecraft code.

A practical example is the Forge event system, which use @ForgeSubscribe in a mod class to hook with reflection, then apply changes with ASM.

I agree with you that both ASM and reflection are very powerful tools in the hands of the Java uebercoder, unfortunately those ranks don't include me :-)  I also doubt that the extra flexibility is really necessary unless you're doing forge-like magic, i.e. you need to link in other classes at runtime and you don't know in advance what they are.  (I understand the ethical objections against shipping even small parts of the Minecraft code, to be honest I really doubt that the Mojang folks would care that much given how long Forge was doing it).

 

At the end of the day I prefer to use chainsaws for cutting trees rather than trimming my nails, and I struggle enough with getting my code to work as it is without trying to get my mind around the extra runtime complexity :-).  Maybe once I've got a couple years Java experience I'll think differently...

 

-TGG

 

 

 

Link to comment
Share on other sites

Well the KeyHandler is a ready-to-use class implementing a client tick handler.

Its use is basically explained in ThePocketSoul linked tutorial, now that i look at it.

 

@TheGreyGhost

You should consider trying reflection first, it is just "normal" code really. If you know java rules of coding, you are good to go ;)

 

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
 Share



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • update Forge to the latest version and do not put your server on OneDrive
    • It occurred to me. Can I get the data I want by getting the parameters of the event instantiation.
    • I just checked the description of "LivingHurtEvent" and he tells me that the event does not return results and if I instantiate the event/class and then call his method, I can't get the return value (amount,source). Do I have to get the return value I want in some other way. Here is the code for the "LivingHurtEvent" event /* * Copyright (c) Forge Development LLC and contributors * SPDX-License-Identifier: LGPL-2.1-only */ package net.minecraftforge.event.entity.living; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.LivingEntity; import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.eventbus.api.Cancelable; /** * LivingHurtEvent is fired when an Entity is set to be hurt. <br> * This event is fired whenever an Entity is hurt in * {@code LivingEntity#actuallyHurt(DamageSource, float)} and * {@code Player#actuallyHurt(DamageSource, float)}.<br> * <br> * This event is fired via the {@link ForgeHooks#onLivingHurt(LivingEntity, DamageSource, float)}.<br> * <br> * {@link #source} contains the DamageSource that caused this Entity to be hurt. <br> * {@link #amount} contains the amount of damage dealt to the Entity that was hurt. <br> * <br> * This event is {@link Cancelable}.<br> * If this event is canceled, the Entity is not hurt.<br> * <br> * This event does not have a result. {@link HasResult}<br> * <br> * This event is fired on the {@link MinecraftForge#EVENT_BUS}. * @see LivingDamageEvent **/ @net.minecraftforge.eventbus.api.Cancelable public class LivingHurtEvent extends LivingEvent { private final DamageSource source; private float amount; public LivingHurtEvent(LivingEntity entity, DamageSource source, float amount) { super(entity); this.source = source; this.amount = amount; } public DamageSource getSource() { return source; } public float getAmount() { return amount; } public void setAmount(float amount) { this.amount = amount; } } I'm wondering if the 'forge' event is only used as a 'forge' listener and not for other purposes. That is, after these events are instantiated, the method is called and cannot provide any return value, or after instantiation, the method is called and cannot change the data, because the events/classes are only used to listen to minecraft/forge.
    • Posted 21 hours ago C:\Users\trodd\OneDrive\Desktop\server for 35>java -Xmx5G -Xms5G -jar forge-1.16.5-36.2.2.jar nogui 2022-05-27 09:49:55,394 main WARN Advanced terminal features are not available in this environment [09:49:55] [main/INFO] [cp.mo.mo.Launcher/MODLAUNCHER]: ModLauncher running: args [--gameDir, ., --launchTarget, fmlserver, --fml.forgeVersion, 36.2.2, --fml.mcpVersion, 20210115.111550, --fml.mcVersion, 1.16.5, --fml.forgeGroup, net.minecraftforge, nogui] [09:49:55] [main/INFO] [cp.mo.mo.Launcher/MODLAUNCHER]: ModLauncher 8.0.9+86+master.3cf110c starting: java version 1.8.0_333 by Oracle Corporation [09:49:56] [main/INFO] [ne.mi.fm.lo.FixSSL/CORE]: Added Lets Encrypt root certificates as additional trust [09:49:56] [main/INFO] [mixin/]: SpongePowered MIXIN Subsystem Version=0.8.2 Source=file:/C:/Users/trodd/OneDrive/Desktop/server%20for%2035/libraries/org/spongepowered/mixin/0.8.2/mixin-0.8.2.jar Service=ModLauncher Env=SERVER [09:49:57] [main/INFO] [STDERR/]: [org.antlr.v4.runtime.ConsoleErrorListener:syntaxError:38]: line 1:0 token recognition error at: '~' Exception in thread "main" [09:49:57] [main/INFO] [STDERR/]: [java.lang.ThreadGroup:uncaughtException:-1]: java.lang.NoSuchMethodError: sun.security.util.ManifestEntryVerifier.<init>(Ljava/util/jar/Manifest;)V [09:49:57] [main/INFO] [STDERR/]: [java.lang.ThreadGroup:uncaughtException:-1]:         at cpw.mods.modlauncher.SecureJarHandler.createCodeSource(SecureJarHandler.java:66) [09:49:57] [main/INFO] [STDERR/]: [java.lang.ThreadGroup:uncaughtException:-1]:         at cpw.mods.modlauncher.TransformingClassLoader$DelegatedClassLoader.findClass(TransformingClassLoader.java:275) [09:49:57] [main/INFO] [STDERR/]: [java.lang.ThreadGroup:uncaughtException:-1]:         at cpw.mods.modlauncher.TransformingClassLoader.loadClass(TransformingClassLoader.java:136) [09:49:57] [main/INFO] [STDERR/]: [java.lang.ThreadGroup:uncaughtException:-1]:         at cpw.mods.modlauncher.TransformingClassLoader.loadClass(TransformingClassLoader.java:98) [09:49:57] [main/INFO] [STDERR/]: [java.lang.ThreadGroup:uncaughtException:-1]:         at java.lang.ClassLoader.loadClass(Unknown Source) [09:49:57] [main/INFO] [STDERR/]: [java.lang.ThreadGroup:uncaughtException:-1]:         at java.lang.Class.forName0(Native Method) [09:49:57] [main/INFO] [STDERR/]: [java.lang.ThreadGroup:uncaughtException:-1]:         at java.lang.Class.forName(Unknown Source) [09:49:57] [main/INFO] [STDERR/]: [java.lang.ThreadGroup:uncaughtException:-1]:         at org.spongepowered.asm.service.modlauncher.ModLauncherClassProvider.findClass(ModLauncherClassProvider.java:57) [09:49:57] [main/INFO] [STDERR/]: [java.lang.ThreadGroup:uncaughtException:-1]:         at org.spongepowered.asm.launch.platform.MixinConnectorManager.loadConnectors(MixinConnectorManager.java:71) [09:49:57] [main/INFO] [STDERR/]: [java.lang.ThreadGroup:uncaughtException:-1]:         at org.spongepowered.asm.launch.platform.MixinConnectorManager.inject(MixinConnectorManager.java:60) [09:49:57] [main/INFO] [STDERR/]: [java.lang.ThreadGroup:uncaughtException:-1]:         at org.spongepowered.asm.launch.platform.MixinPlatformManager.inject(MixinPlatformManager.java:197) [09:49:57] [main/INFO] [STDERR/]: [java.lang.ThreadGroup:uncaughtException:-1]:         at org.spongepowered.asm.launch.MixinBootstrap.inject(MixinBootstrap.java:190) [09:49:57] [main/INFO] [STDERR/]: [java.lang.ThreadGroup:uncaughtException:-1]:         at org.spongepowered.asm.launch.MixinLaunchPlugin.initializeLaunch(MixinLaunchPlugin.java:196) [09:49:57] [main/INFO] [STDERR/]: [java.lang.ThreadGroup:uncaughtException:-1]:         at cpw.mods.modlauncher.LaunchPluginHandler.lambda$announceLaunch$9(LaunchPluginHandler.java:97) [09:49:57] [main/INFO] [STDERR/]: [java.lang.ThreadGroup:uncaughtException:-1]:         at java.util.HashMap.forEach(Unknown Source) [09:49:57] [main/INFO] [STDERR/]: [java.lang.ThreadGroup:uncaughtException:-1]:         at cpw.mods.modlauncher.LaunchPluginHandler.announceLaunch(LaunchPluginHandler.java:97) [09:49:57] [main/INFO] [STDERR/]: [java.lang.ThreadGroup:uncaughtException:-1]:         at cpw.mods.modlauncher.LaunchServiceHandler.launch(LaunchServiceHandler.java:52) [09:49:57] [main/INFO] [STDERR/]: [java.lang.ThreadGroup:uncaughtException:-1]:         at cpw.mods.modlauncher.LaunchServiceHandler.launch(LaunchServiceHandler.java:72) [09:49:57] [main/INFO] [STDERR/]: [java.lang.ThreadGroup:uncaughtException:-1]:         at cpw.mods.modlauncher.Launcher.run(Launcher.java:82) [09:49:57] [main/INFO] [STDERR/]: [java.lang.ThreadGroup:uncaughtException:-1]:         at cpw.mods.modlauncher.Launcher.main(Launcher.java:66) [09:49:57] [main/INFO] [STDERR/]: [java.lang.ThreadGroup:uncaughtException:-1]:         at net.minecraftforge.server.ServerMain$Runner.runLauncher(ServerMain.java:63) [09:49:57] [main/INFO] [STDERR/]: [java.lang.ThreadGroup:uncaughtException:-1]:         at net.minecraftforge.server.ServerMain$Runner.access$100(ServerMain.java:60) [09:49:57] [main/INFO] [STDERR/]: [java.lang.ThreadGroup:uncaughtException:-1]:         at net.minecraftforge.server.ServerMain.main(ServerMain.java:57) C:\Users\trodd\OneDrive\Desktop\server for 35>PAUSE Press any key to continue . . .
    • You can, but it won't do anything useful. The event instance is already given to you as a parameter.
  • Topics

×
×
  • Create New...

Important Information

By using this site, you agree to our Privacy Policy.