Jump to content

[1.10.2] Key bind overflow?


JimiIT92

Recommended Posts

In my mod i'm registering different key bindings. However for some reason if i go to the Controls screen, to view the keys and re-map them, the game crashes with this error

java.lang.ArrayIndexOutOfBoundsException: 42
    at net.minecraft.client.gui.GuiKeyBindingList.<init>(GuiKeyBindingList.java:49)
    at net.minecraft.client.gui.GuiControls.initGui(GuiControls.java:38)
    at net.minecraft.client.gui.GuiScreen.setWorldAndResolution(GuiScreen.java:553)
    at net.minecraft.client.Minecraft.displayGuiScreen(Minecraft.java:1018)
    at net.minecraft.client.gui.GuiOptions.actionPerformed(GuiOptions.java:152)
    at net.minecraft.client.gui.GuiScreen.mouseClicked(GuiScreen.java:504)
    at net.minecraft.client.gui.GuiScreen.handleMouseInput(GuiScreen.java:619)
    at net.minecraft.client.gui.GuiScreen.handleInput(GuiScreen.java:585)
    at net.minecraft.client.Minecraft.runTick(Minecraft.java:1797)
    at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1118)
    at net.minecraft.client.Minecraft.run(Minecraft.java:406)
    at net.minecraft.client.main.Main.main(Main.java:118)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at net.minecraft.launchwrapper.Launch.launch(Launch.java:135)
    at net.minecraft.launchwrapper.Launch.main(Launch.java:28)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:97)
    at GradleStart.main(GradleStart.java:26)


These are my key bindings

	package com.rpg.core;
	import java.lang.reflect.Field;
	import org.lwjgl.input.Keyboard;
	import net.minecraft.client.settings.KeyBinding;
import net.minecraftforge.fml.client.registry.ClientRegistry;
	public class RPGKeys {
    public static KeyBinding KEY_GUILD;
    public static KeyBinding KEY_SHOP;
    public static KeyBinding KEY_SKILL_1;
    public static KeyBinding KEY_SKILLS;
    
    public static void addKeys() {
        KEY_GUILD = new KeyBinding("keys.guilds.description", Keyboard.KEY_G, "keys.guilds.category");
        KEY_SHOP = new KeyBinding("keys.shop.description", Keyboard.KEY_K, "keys.shop.category");
        KEY_SKILL_1 = new KeyBinding("keys.skills.description", Keyboard.KEY_Z, "keys.skills.category");
        KEY_SKILLS = new KeyBinding("keys.skills.skills", Keyboard.KEY_O, "keys.skills.category");
    }
    
    public static void registerKeys() {
        Field[] fields = RPGKeys.class.getFields();
        for (Field field : fields) {
            try {
                if (field.get(RPGKeys.class) != null) {
                    ClientRegistry.registerKeyBinding((KeyBinding) field.get(RPGKeys.class));
                }
            } catch (IllegalArgumentException | IllegalAccessException exception) {
                exception.printStackTrace();
            }
        }
    }
}

The keys works as intended, if i remove one key from here everything works fine. It's just in the Controls screen that the crash happen. What could be the cause of this? :/

Edited by JimiIT92

Don't blame me if i always ask for your help. I just want to learn to be better :)

Link to comment
Share on other sites

Why are you accessing the fields in your class in such a weird way with your getFields() method? Why aren't you just registering your fields directly? You wrote more lines of code to loop through than you actually had key bindings...

 

I'm not sure if your weird way of registering the fields is causing the issue, but I would try making that more simple first.

 

After that, if there is still an issue, you'll notice that the error occurs where the listEntries array is going out of bounds. The size of that array is set based on the number of keybindings in the GameSettings plus the number of categories in KeyBinding together. So it may be an issue with the fact that you're creating new keybinding categories. I have done keybinding before but frankly I always used existing categories, but maybe there is some trick or maybe even bug. I would trace through the execution in debug mode in Eclipse by setting a breakpoint in that loop and watching how the index is advancing.

 

 

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

Link to comment
Share on other sites

I've used new categories without problems.

 

		public static KeyBinding eventKey;

...
		eventKey = new KeyBinding("key." + Reference.MOD_ID + ".event", Keyboard.KEY_G, "key.categories." + Reference.MOD_ID);
		ClientRegistry.registerKeyBinding(eventKey);

 

Is addKeys() even called?  If so, you can register them at that point.

Link to comment
Share on other sites

Yes, the addKeys is called (as i said the keys itself works normally, if i press one of them they do what they've been registered for). I used the reflection method because i plan to add more keybinds and with this i just have to register it, but i'll try to register them manually and see what happens :/

Don't blame me if i always ask for your help. I just want to learn to be better :)

Link to comment
Share on other sites

Changing the registration method didn't solved the error, but i've noticed going into debug mode when i enter the controls screen that the key category for KEY_SKILLS and KEY_SKILL_1, wich is the same, is added twice in the key list, while other categories like normal vanilla keybinds categories are added once. Infact, if i move one of them to a new category everything works fine. This is how i register the key binds now

public static void registerKeys() {
        ClientRegistry.registerKeyBinding(KEY_GUILD);
        ClientRegistry.registerKeyBinding(KEY_SHOP);
        ClientRegistry.registerKeyBinding(KEY_SKILLS);
        ClientRegistry.registerKeyBinding(KEY_SKILL_1);
    }

So am i doing something wrong? And if so how can i register 2 keys within the same category? Or it's a Forge bug? 

Don't blame me if i always ask for your help. I just want to learn to be better :)

Link to comment
Share on other sites

Okay, if I look at the KeyBinding.KEYBIND_SET (which contains the categories) it turns out there is an add(category) called on that every time a key binding is constructed. Now technically a Java Set should not allow duplicates.

 

The category is a string, but the Java set properly uses the equals() method for comparison according to the "contract" of the method definition. 

 

So basically the category set will get the add() called every time, but it should not actually create any duplicates.

 

When tracing you should look at the contents of the KEYBIND_SET to see if there is actually an (apparent) duplicate added.

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

Link to comment
Share on other sites

I've looked at the listEntries array that is generated (and that gives the exception). As you can see there are 2 categories with the same name but different ID, and these are the categories that comes from the 2 keys with the same one

 

Cattura.PNG

Don't blame me if i always ask for your help. I just want to learn to be better :)

Link to comment
Share on other sites

Then you should trace through the constructor of the GuiKeyBindingList because it has a loop where it checks whether each category is unique before adding a category entry to listEntries.

 

Now that I look at it though, I think it is actually a bug. Because the way the loop works is that it has a "previous category" field called s and "current category" field called s1 and checks if they are equal. Basically it is checking if the category of the entry in this iteration of the loop is the same as the previous. However, that requires the categories to be sorted. There is a sort on the list, but I think maybe it is wrong because I think it is sorting the actual key bindings not necessarily just the categories.

 

Check if that is the problem.

 

So I think it might be a bug. You might be able to work around it by naming your keybinds so that the ones in the same category sort together, or something else that makes sure that the categories are processed consecutively.

 

Alternatively, you can override the whole gui by copying the class and fixing the bug and then handling the gui open event to put up your gui instead.

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

Link to comment
Share on other sites

Actually the sort method looks suspicious generally. It is sorting an array of KeyBinding which are cast to Object and I don't think KeyBinding class has a comparator interface to help the sorting. So I don't think the sort would be meaningful in terms of the keybinding unless the default Object sort is based on toString() and even then seems a bit sketchy.

 

Basically when the loop starts you need to see whether the two entries with the same category are right after each other. If not then the loop will probably fail. Or just monitor the s and s1 values during the loop. There is definitely potential for something wrong there I think.

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

Link to comment
Share on other sites

Yes in the first iteration the keys with the same category was not one after the other, meaning that when the game adds the second key the previous category was a different one and so it adds the duplicate. Fun fact: i've added more keys in the same category and now the controls screen appear and in the gui init the check on s and s1 is correct O_O 

Don't blame me if i always ask for your help. I just want to learn to be better :)

Link to comment
Share on other sites

This is how I registered my keybinds (https://github.com/KenLPham/ArcadeMod/blob/1.11.2/src/main/java/superhb/arcademod/util/KeyHandler.java) and I don't have any problems with it.

 

When do you call registerKeys? Copying your method worked, but I called registerKey in addKeys()

 

Also I think if you want to use your lang file for the Categories and Key Description you need to use I18n.format() (I'm guessing that's what you want to do considering what you've named it)

Edited by SuperHB
Link to comment
Share on other sites

Me too has no problem with the keys itself, it's just that if i have exactly 2 keys of the same category (not more) the Controls screen crash the game. And it looks like it's a bug in the Control GUI, because it doesn't make any sense that more keys within the same category doesn't give the same crash

Don't blame me if i always ask for your help. I just want to learn to be better :)

Link to comment
Share on other sites

24 minutes ago, JimiIT92 said:

Me too has no problem with the keys itself, it's just that if i have exactly 2 keys of the same category (not more) the Controls screen crash the game. And it looks like it's a bug in the Control GUI, because it doesn't make any sense that more keys within the same category doesn't give the same crash

I copied your code and was able to open the control screen. Where are you calling registerKey() though? I had it at the end of addKeys()

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.