Hello all, So I know these tutorials are a bit poop at the moment. However, I am trying to getting around to update them a bit, make them more clear. Just give me some, I have been super busy lately. I'll update them when I can.
Today we're going to learn how to make a custom key bind that shows up in the options menu, which you can change in the options menu, and use for any boolean in your code.
*Note that these are currently for 1.6.4. If you would like to have this for 1.7.2, scroll down, some of the old concepts can be used with the 1.7.2 update tutorial, if you do it right.
Normal Keybind:
Lets start in our main mod file.
In our @Init method, we declare our button like so:
Note that the parameters can be changed to your liking.
Now we are going to create our TutorialKeyBind class. Its set up like a ticking class:
package package.name
import java.util.EnumSet;
import java.util.Iterator;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.world.EnumSkyBlock;
import net.minecraft.world.World;
import cpw.mods.fml.client.registry.KeyBindingRegistry.KeyHandler;
import cpw.mods.fml.common.TickType;
class TutorialKeyBind extends KeyHandler
{
private EnumSet tickTypes = EnumSet.of(TickType.CLIENT);
public TutorialKeyBind(KeyBinding[] keyBindings, boolean[] repeatings)
{
super(keyBindings, repeatings);
}
@Override
public String getLabel()
{
return "TutorialKey";
}
@Override
public void keyDown(EnumSet<TickType> types, KeyBinding kb, boolean tickEnd, boolean isRepeat)
{
//what to do when key is pressed/down
}
@Override
public void keyUp(EnumSet<TickType> types, KeyBinding kb, boolean tickEnd)
{
//What to do when key is released/up
}
@Override
public EnumSet<TickType> ticks()
{
return tickTypes;
}
}
And that's all! Simply change the comments for what you want your keybind to toggle. Sometimes, I'll create a boolean elsewhere, such as an item class, and call check for it in my tick class.
Applying to gui's
Ok, so i'm assuming you have a working gui, and you want a block/item to open it. You also need a working keybind (look above)
Head over to your keybind class and declare a variable:
public static boolean keyPressed = false;
Now add this to your keyDown method:
keyPressed = true;
and then this to your keyUp method:
keyPressed = false;
This is simple logic to check if your key is pressed or not. Now, simply check in your classes for it.
Applying to Items:
Add this to your item class:
public void onUpdate(ItemStack par1ItemStack, World par2World, Entity par3Entity, int par4, boolean par5)
{
EntityPlayer player = (EntityPlayer)par3Entity;
if(KeyBindSE.keyPressed)
{
// code for opening gui.
//if your not sure, use player.openGui(MAINMODCLASS.instance, YOURGUIID, player.worldObj, (int) player.posX, (int) player.posY, (int) player.posZ);
}
Applying to Block:
Add this method in block class:
public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
{
if(keyPressed)
{
//Gui opening code
}
}
Simply add your gui opening code in the if statement.
If your having trouble opening gui's, consult the gui tutorials all over the web.
Doing various things to player when key is pressed (basically just getting EntityPlayer object)
First, make a working keybind like the one used in the GUI tutorial.
Then, your going to need a PlayerTickHandler class:
package monkeys.bananas;
import java.util.EnumSet;
import sobiohazardous.crazyfoods.TutorialKeyBind;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.world.World;
import cpw.mods.fml.common.ITickHandler;
import cpw.mods.fml.common.TickType;
public class PlayerTickHandler implements ITickHandler
{
private final EnumSet<TickType> ticksToGet;
/*
* This Tick Handler will fire for whatever TickType's you construct and register it with.
*/
public PlayerTickHandler(EnumSet<TickType> ticksToGet)
{
this.ticksToGet = ticksToGet;
}
/*
* I suggest putting all your tick Logic in EITHER of these, but staying in one
*/
@Override
public void tickStart(EnumSet<TickType> type, Object... tickData)
{
playerTick((EntityPlayer)tickData[0]);
}
@Override
public void tickEnd(EnumSet<TickType> type, Object... tickData)
{
}
@Override
public EnumSet<TickType> ticks()
{
return ticksToGet;
}
@Override
public String getLabel()
{
return "TutorialPlayerTick";
}
public static void playerTick(EntityPlayer player)
{
if(TutorialKeyBind.keyPressed)
{
//Code for when the key is pressed. Notice how you have the player parameter
}
}
}
Don't forget to register it like so in your @Init method:
And there you go! Notice the comment in the PlayerTickHandler class, that is how you have access to the player object.
Making it so the key must be "tapped" and not just held down (Thanks to Thobro)
Basically, this is for something like switching modes of an item, ect.
Please read the previous sections, as some of the code is missing in this section.
First, you need to modify your keyDown(*) and keyUp(*) method so it looks similar to this in your keybind class:
Now from previous sections of this tutorial, you can call
if (KeyBind.keyPressed) {
KeyBind.keyPressed = false;
//Insert other code
}
Now the code should only happen once when the key is pressed and held down.
If you're getting any problems, view the other sections. This correlates heavily with the above sections.
Updating to 1.7.2
So forge has changed a lot in 1.7.2, if you hadn't noticed, so they have completely removed the keybinding class, it just uses key handler now.
Make a new class, I called mine KeyHandlerTutorial.
public class KeyHandlerTutorial // note that before we extended KeyHandler, but that class no longer exists
{
/** Key index for easy handling */
public static final int CUSTOM_INV = 0;
/** Key descriptions; use a language file to localize the description later */
private static final String[] desc = {"key.tut_inventory.desc"};
/** Default key values */
private static final int[] keyValues = {Keyboard.KEY_P};
private final KeyBinding[] keys;
public KeyHandler() {
keys = new KeyBinding[desc.length];
for (int i = 0; i < desc.length; ++i) {
keys[i] = new KeyBinding(desc[i], keyValues[i], "key.tutorial.category");
ClientRegistry.registerKeyBinding(keys[i]);
}
}
/**
* KeyInputEvent is in the FML package, so we must register to the FML event bus
*/
@SubscribeEvent
public void onKeyInput(KeyInputEvent event) {
// FMLClientHandler.instance().getClient().inGameHasFocus
if (!FMLClientHandler.instance().isGUIOpen(GuiChat.class)) {
if (keys[CUSTOM_INV].isPressed()) {
TutorialMain.packetPipeline.sendToServer(new OpenGuiPacket(TutorialMain.GUI_CUSTOM_INV));
}
}
}
}
The comments along the way should help you figure it out.
Be sure to register the class as an event!
Thank you! I've been wanting to do this for a long time! Can you do a GUI tutorial? Like a seperate item inventory that you open with the pre-defined key?
Thank you! I've been wanting to do this for a long time! Can you do a GUI tutorial? Like a seperate item inventory that you open with the pre-defined key?
Thank you! I've been wanting to do this for a long time! Can you do a GUI tutorial? Like a seperate item inventory that you open with the pre-defined key?
Great tutorial. Just one problem I have is that the server is crashing because it's not finding the Keybind class from the client. Any way to make it Client only?
Great tutorial. Just one problem I have is that the server is crashing because it's not finding the Keybind class from the client. Any way to make it Client only?
---
Hm ... maybe an example would be better. I use it like this:
@Override
public void keyUp(EnumSet<TickType> types, KeyBinding kb, boolean tickEnd) {
final Side side = FMLCommonHandler.instance().getEffectiveSide();
if (tickEnd && side == Side.CLIENT) {
isKeyPressed = !isKeyPressed;
System.out.println(isKeyPressed); // Syso ist just used for testing purposes
}
}
---
Hm ... maybe an example would be better. I use it like this:
@Override
public void keyUp(EnumSet<TickType> types, KeyBinding kb, boolean tickEnd) {
final Side side = FMLCommonHandler.instance().getEffectiveSide();
if (tickEnd && side == Side.CLIENT) {
isKeyPressed = !isKeyPressed;
System.out.println(isKeyPressed); // Syso ist just used for testing purposes
}
}
sorry for my English, I'm Italian, however, no, I want to know if you would know how to add effects, but directly to the player xD
Well this is just a hunch, but you should be able to change TickType.CLIENT to TickType.PLAYER, then in keyUp or keyDown, use types.whatever to add player effects and such. This is just a guess, haven't had time to play around with it.
You said i could "use the types parameter for player functions" if i change the ticktypes thing.
I did that.
Now i want a variable of the type "EntityPlayer" of the player who pressed the key.
It doesn't work with a cast to entityPlayer
public static EntityPlayer keyPlayer;
keyPlayer = (EntityPlayer) types;
Ok, sorry fella's, but I figured it out. First, create a KeyBind class to match the one in the GUI tutorial:
Then, we need a PlayerTickHandler to tick when the player is alive. Make it like so:
package sobiohazardous.crazyfoods.handler;
import java.util.EnumSet;
import sobiohazardous.crazyfoods.TutorialKeyBind;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.world.World;
import cpw.mods.fml.common.ITickHandler;
import cpw.mods.fml.common.TickType;
public class PlayerTickHandler implements ITickHandler
{
private final EnumSet<TickType> ticksToGet;
/*
* This Tick Handler will fire for whatever TickType's you construct and register it with.
*/
public PlayerTickHandler(EnumSet<TickType> ticksToGet)
{
this.ticksToGet = ticksToGet;
}
/*
* I suggest putting all your tick Logic in EITHER of these, but staying in one
*/
@Override
public void tickStart(EnumSet<TickType> type, Object... tickData)
{
playerTick((EntityPlayer)tickData[0]);
}
@Override
public void tickEnd(EnumSet<TickType> type, Object... tickData)
{
}
@Override
public EnumSet<TickType> ticks()
{
return ticksToGet;
}
@Override
public String getLabel()
{
return "CoolHatsServerTick";
}
public static void playerTick(EntityPlayer player)
{
if(TutorialKeyBind.keyPressed)
{
//What you want to happen when the key is pressed, just use the player parameter
}
}
}
Now, in playerTick method, you are able to do something when the key is pressed and still have the EntityPlayer object.
I'm like my code simple and organized, and I want multiple keybindings but I'm not too happy with my current result.
Are there anyone here who has a good suggestion on how to do this more cleanly?
public class ModKeybindings {
public static MazKeyBind PowerKey;
public static MazKeyBind SomeKey;
public static void registerKeyBindings(){
boolean[] repeat = {false};
KeyBinding[] some = {new KeyBinding("SomeKey", Keyboard.KEY_NUMPAD5)};
SomeKey = new MazKeyBind(some, repeat);
KeyBindingRegistry.registerKeyBinding(SomeKey);
KeyBinding[] power = {new KeyBinding("Toggle Power", Keyboard.KEY_G)};
PowerKey = new MazKeyBind(power, repeat);
KeyBindingRegistry.registerKeyBinding(PowerKey);
}
As you can see it's quite bulky and ugly, I know I could have done it in some other ways but all I came up with earlier tonight was inefficient and bulky. Does you guys have any suggestions?
So I know these tutorials are a bit poop at the moment. However, I am trying to getting around to update them a bit, make them more clear. Just give me some, I have been super busy lately. I'll update them when I can.
Today we're going to learn how to make a custom key bind that shows up in the options menu, which you can change in the options menu, and use for any boolean in your code.
*Note that these are currently for 1.6.4. If you would like to have this for 1.7.2, scroll down, some of the old concepts can be used with the 1.7.2 update tutorial, if you do it right.
Normal Keybind:
Lets start in our main mod file.
In our @Init method, we declare our button like so:
Note that the parameters can be changed to your liking.
Now we are going to create our TutorialKeyBind class. Its set up like a ticking class:
And that's all! Simply change the comments for what you want your keybind to toggle. Sometimes, I'll create a boolean elsewhere, such as an item class, and call check for it in my tick class.
Applying to gui's
Ok, so i'm assuming you have a working gui, and you want a block/item to open it. You also need a working keybind (look above)
Head over to your keybind class and declare a variable:
Now add this to your keyDown method:
and then this to your keyUp method:
This is simple logic to check if your key is pressed or not. Now, simply check in your classes for it.
Applying to Items:
Add this to your item class:
Applying to Block:
Add this method in block class:
Simply add your gui opening code in the if statement.
If your having trouble opening gui's, consult the gui tutorials all over the web.
Doing various things to player when key is pressed (basically just getting EntityPlayer object)
First, make a working keybind like the one used in the GUI tutorial.
Then, your going to need a PlayerTickHandler class:
Don't forget to register it like so in your @Init method:
And there you go! Notice the comment in the PlayerTickHandler class, that is how you have access to the player object.
Making it so the key must be "tapped" and not just held down (Thanks to Thobro)
Basically, this is for something like switching modes of an item, ect.
Please read the previous sections, as some of the code is missing in this section.
First, you need to modify your keyDown(*) and keyUp(*) method so it looks similar to this in your keybind class:
Now from previous sections of this tutorial, you can call
Now the code should only happen once when the key is pressed and held down.
If you're getting any problems, view the other sections. This correlates heavily with the above sections.
Updating to 1.7.2
So forge has changed a lot in 1.7.2, if you hadn't noticed, so they have completely removed the keybinding class, it just uses key handler now.
Make a new class, I called mine KeyHandlerTutorial.
The comments along the way should help you figure it out.
Be sure to register the class as an event!
Carry over and then delete your old keybinding code. You should be good to go.
Special thanks to coolAlias
Tips
Need the world object?
That is a variable of the type World that should help you if you are in a pinch.
Also, here is some examples of various keybind things by coolAlias.
Leave reply's if help is needed.
Leave a If this helped you!
Find out how I generate....coolAlias...world structure generation and rotation tool...
Thanks!
Sure! I'll do a "applying to gui's" tutorial.
Keyboard.KEY_G
Eclipse show me a error (Cannot be resolved)
Fixed.
Woah woah!
I just added it if you want to take a look
If only the above code would work lol
Hmmm, I'll work on something.
I put it in the client proxy. It works there.
Oh thanks. i believe that works.
Can you be more specific please? What are you trying to accomplish?
In your keybind class, you should be able to change
To
Then in your keyUp or keyDown method you can use the types parameter for player functions.
Do the same thing above just change the tick type.
I'm not sure what you mean.
I'm having trouble understanding. Your saying you want to show me how to add effects? If so, that'd be great.
Well this is just a hunch, but you should be able to change TickType.CLIENT to TickType.PLAYER, then in keyUp or keyDown, use types.whatever to add player effects and such. This is just a guess, haven't had time to play around with it.
Ok, sorry fella's, but I figured it out. First, create a KeyBind class to match the one in the GUI tutorial:
Then, we need a PlayerTickHandler to tick when the player is alive. Make it like so:
Now, in playerTick method, you are able to do something when the key is pressed and still have the EntityPlayer object.
Make sure you register it in @Init using:
Don't forget to registry the KeyBind as well.
I'm like my code simple and organized, and I want multiple keybindings but I'm not too happy with my current result.
Are there anyone here who has a good suggestion on how to do this more cleanly?
As you can see it's quite bulky and ugly, I know I could have done it in some other ways but all I came up with earlier tonight was inefficient and bulky. Does you guys have any suggestions?
TickTypes.SERVER
?