The Bug:
You can continue using items while opening your inventory.
Steps to Reproduce:
Obtain a shield.
Use the shield and at the same time, open your inventory.
If you didn’t continue using your shield when your inventory is opened, repeat step 2.
Observed Behavior:
You can continue using items while opening your inventory.
Expected Behavior:
You would stop using items when your inventory is opened.
Code Analysis:
The following is based on a decompiled version of Minecraft 26.3 Snapshot 4 using Mojang mappings.
Each key binding remembers two separate things, whether the key is currently held down, and how many presses are queued up waiting to be acted on by consumeClick. When a screen is opened, Gui.setScreen releases every key binding, which is meant to clear both.
net.minecraft.client.KeyMapping.java
protected void release() {
this.clickCount = 0;
this.setDown(false);
}net.minecraft.client.ToggleKeyMapping.java
@Override
protected void release() {
if (this.needsToggle.getAsBoolean() && this.isDown() || this.releasedByScreenWhenDown) {
this.releasedByScreenWhenDown = true;
}
this.reset();
}
protected void reset() {
super.setDown(false);
}If we look at the above classes, we can see that ToggleKeyMapping replaces the ordinary release behavior with its own and only clears the held state. The queued presses are left untouched. This matters because the use key is a ToggleKeyMapping, so the queued right click survives the inventory being opened.
net.minecraft.client.Minecraft.java
private void handleKeybinds() {
...
while (this.options.keyInventory.consumeClick()) {
...
this.gui.setScreen(new InventoryScreen(this.player));
}
...
while (this.options.keyUse.consumeClick()) {
this.startUseItem();
}
...
}The inventory is opened partway through this method, and the method then carries on to the part that acts on queued use presses. Since the queued press was never cleared, the item starts being used at that point, with the inventory already open. Nothing then stops it, as this method is not called again while a screen is open.
This is also why the report needs the two actions to happen at the same time. Both presses have to be queued together for the inventory press to be handled first and the use press to be left over.
The attack key is also a ToggleKeyMapping, so a queued attack survives in the same way.
Fixed Code:
net.minecraft.client.KeyMapping.java
protected void clearClickCount() {
this.clickCount = 0;
}net.minecraft.client.ToggleKeyMapping.java
@Override
protected void release() {
if (this.needsToggle.getAsBoolean() && this.isDown() || this.releasedByScreenWhenDown) {
this.releasedByScreenWhenDown = true;
}
this.clearClickCount();
this.reset();
}The above makes releasing a toggle key binding clear its queued presses as well, which is what the ordinary key binding release already does. With nothing left queued, the leftover press no longer starts using the item after the inventory has opened.
Calling the ordinary release method instead would not work here, as it clears the held state through setDown, which ToggleKeyMapping overrides to do nothing while the toggle option is turned on. That is what reset exists for, so the queued presses need clearing separately.
This change was applied to a modified client and tested against the steps above, and the item is no longer left in use.
Reproduced in 26.1-snapshot-5