diff --git a/src/main/java/com/kasetoatz/biggerhotbar/accessor/SlotAccessor.java b/src/main/java/com/kasetoatz/biggerhotbar/accessor/SlotAccessor.java new file mode 100644 index 0000000..7380ff5 --- /dev/null +++ b/src/main/java/com/kasetoatz/biggerhotbar/accessor/SlotAccessor.java @@ -0,0 +1,7 @@ +package com.kasetoatz.biggerhotbar.accessor; + +public interface SlotAccessor +{ + void setY(int y); + int get_original_y(); +} diff --git a/src/main/java/com/kasetoatz/biggerhotbar/mixin/GenericContainerScreenHandlerMixin.java b/src/main/java/com/kasetoatz/biggerhotbar/mixin/GenericContainerScreenHandlerMixin.java new file mode 100644 index 0000000..fe0479d --- /dev/null +++ b/src/main/java/com/kasetoatz/biggerhotbar/mixin/GenericContainerScreenHandlerMixin.java @@ -0,0 +1,48 @@ +package com.kasetoatz.biggerhotbar.mixin; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.item.ItemStack; +import net.minecraft.registry.Registries; +import net.minecraft.screen.GenericContainerScreenHandler; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.screen.slot.SlotActionType; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyArg; + +import java.util.OptionalInt; + +import static com.kasetoatz.biggerhotbar.state.StateManager.isFlipped; + +@Mixin(GenericContainerScreenHandler.class) +public class GenericContainerScreenHandlerMixin +{ + @ModifyArg(method="quickMove", at= @At(value = "INVOKE", target = "Lnet/minecraft/screen/GenericContainerScreenHandler;insertItem(Lnet/minecraft/item/ItemStack;IIZ)Z", ordinal = 0), index = 0) + public ItemStack quickMove(ItemStack stack) + { + ClientPlayerEntity player = MinecraftClient.getInstance().player; + ClientPlayerInteractionManager manager = MinecraftClient.getInstance().interactionManager; + if (isFlipped() || player == null || manager == null || stack.isEmpty()) + { + return stack; + } + int slot = player.getInventory().getMatchingSlot(Registries.ITEM.getEntry(stack.getItem()), stack); + if (slot < 0 || slot > 8) + { + return stack; + } + for (int i = 35; i > 26; i--) + { + OptionalInt index = player.currentScreenHandler.getSlotIndex(player.getInventory(), i); + if (index.isEmpty() || !player.currentScreenHandler.getSlot(index.getAsInt()).getStack().isEmpty()) + { + continue; + } + manager.clickSlot(player.currentScreenHandler.syncId, index.getAsInt(), slot, SlotActionType.SWAP, player); + break; + } + return stack; + } +} diff --git a/src/main/java/com/kasetoatz/biggerhotbar/mixin/HandledScreenMixin.java b/src/main/java/com/kasetoatz/biggerhotbar/mixin/HandledScreenMixin.java index a6fd596..f993588 100644 --- a/src/main/java/com/kasetoatz/biggerhotbar/mixin/HandledScreenMixin.java +++ b/src/main/java/com/kasetoatz/biggerhotbar/mixin/HandledScreenMixin.java @@ -1,9 +1,14 @@ package com.kasetoatz.biggerhotbar.mixin; +import com.kasetoatz.biggerhotbar.accessor.SlotAccessor; +import com.llamalad7.mixinextras.sugar.Local; +import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen; import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.entity.player.PlayerInventory; import net.minecraft.screen.slot.Slot; import net.minecraft.screen.slot.SlotActionType; +import net.minecraft.util.Pair; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -16,108 +21,98 @@ import static com.kasetoatz.biggerhotbar.state.StateManager.isFlipped; @Mixin(HandledScreen.class) public abstract class HandledScreenMixin { - @Shadow @Nullable protected Slot focusedSlot; @Shadow protected abstract void onMouseClick(Slot slot, int slotId, int button, SlotActionType actionType); @Unique - private Slot customSlot(Slot slot) + private boolean isValidInventory() { - if (isFlipped()) + if ((Object)this instanceof CreativeInventoryScreen inventory) { - if ((Object)this instanceof CreativeInventoryScreen) - { - return slot; - } - int index = slot.getIndex(); - if (index < 9) - { - return new Slot(slot.inventory, index, slot.x, slot.y - 22); - } - if (index > 26 && index < 36) - { - return new Slot(slot.inventory, index, slot.x, slot.y + 22); - } + return inventory.isInventoryTabSelected(); } - return slot; + return true; } @Unique - private int highlightY(int y) + private Pair getHotbarBounds() { - if (isFlipped() && focusedSlot != null) + int hotbarStart = -1; + int hotbarEnd = 9; + if ((Object)this instanceof CreativeInventoryScreen) { - if ((Object)this instanceof CreativeInventoryScreen) + hotbarStart = 35; + hotbarEnd = 45; + } + return new Pair<>(hotbarStart, hotbarEnd); + } + + @Unique + private void modifySlot(Slot slot) + { + if (!(slot.inventory instanceof PlayerInventory) || !isValidInventory()) + { + return; + } + SlotAccessor accessor = (SlotAccessor)slot; + int y = accessor.get_original_y(); + if (isFlipped()) + { + Pair bounds = getHotbarBounds(); + int index = slot.getIndex(); + if (index > bounds.getLeft() && index < bounds.getRight()) { - return y; + y -= 22; } - int index = focusedSlot.getIndex(); - if (index < 9) + else if (index > 26 && index < 36) { - return y - 22; - } - if (index > 26 && index < 36) - { - return y + 22; + y += 22; } } - return y; + accessor.setY(y); } @ModifyVariable(method="drawSlot", at=@At("HEAD"), argsOnly=true) - public Slot drawSlot(Slot slot) + public Slot drawSlot(Slot slot, @Local(argsOnly = true) DrawContext context) { - return customSlot(slot); + modifySlot(slot); + return slot; } @ModifyVariable(method="isPointOverSlot", at=@At("HEAD"), argsOnly=true) public Slot isPointOverSlot(Slot slot) { - return customSlot(slot); - } - - @ModifyArg(method="drawSlotHighlightBack", at=@At(value="INVOKE", target="Lnet/minecraft/client/gui/DrawContext;drawGuiTexture(Lcom/mojang/blaze3d/pipeline/RenderPipeline;Lnet/minecraft/util/Identifier;IIII)V"), index=3) - public int highlightBackY(int y) - { - return highlightY(y); - } - - @ModifyArg(method="drawSlotHighlightFront", at=@At(value="INVOKE", target="Lnet/minecraft/client/gui/DrawContext;drawGuiTexture(Lcom/mojang/blaze3d/pipeline/RenderPipeline;Lnet/minecraft/util/Identifier;IIII)V"), index=3) - public int highlightFrontY(int y) - { - return highlightY(y); + modifySlot(slot); + return slot; } @ModifyArgs(method="handleHotbarKeyPressed", at=@At(value="INVOKE", target="Lnet/minecraft/client/gui/screen/ingame/HandledScreen;onMouseClick(Lnet/minecraft/screen/slot/Slot;IILnet/minecraft/screen/slot/SlotActionType;)V", ordinal=1)) public void keypress(Args args) { - if ((Object)this instanceof CreativeInventoryScreen) + if (!isFlipped()) { return; } - if (isFlipped()) + int src = args.get(1); + int dest = args.get(2); + args.set(0, null); + args.set(2, 0); + args.set(3, SlotActionType.PICKUP); + int source, destination; + if (src > 35 && src < 45) { - int src = args.get(1); - int dest = args.get(2); - args.set(0, null); - args.set(2, 0); - args.set(3, SlotActionType.PICKUP); - int source, destination; - if (src > 35 && src < 45) - { - source = dest + 27; - destination = src; - } - else - { - source = src; - destination = dest + 27; - } - onMouseClick(null, source, 0, SlotActionType.PICKUP); - if (source != destination) - { - onMouseClick(null, destination, 0, SlotActionType.PICKUP); - } - args.set(1, source); + source = dest + 27; + destination = src; } + else + { + source = src; + destination = dest + 27; + } + onMouseClick(null, source, 0, SlotActionType.PICKUP); + if (source != destination) + { + onMouseClick(null, destination, 0, SlotActionType.PICKUP); + } + args.set(1, source); } } diff --git a/src/main/java/com/kasetoatz/biggerhotbar/mixin/MinecraftClientMixin.java b/src/main/java/com/kasetoatz/biggerhotbar/mixin/MinecraftClientMixin.java new file mode 100644 index 0000000..c56605e --- /dev/null +++ b/src/main/java/com/kasetoatz/biggerhotbar/mixin/MinecraftClientMixin.java @@ -0,0 +1,23 @@ +package com.kasetoatz.biggerhotbar.mixin; + +import net.minecraft.client.MinecraftClient; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import static com.kasetoatz.biggerhotbar.Biggerhotbar.flipItems; +import static com.kasetoatz.biggerhotbar.state.StateManager.isFlipped; + +@Mixin(MinecraftClient.class) +public class MinecraftClientMixin +{ + @Inject(method="handleInputEvents", at=@At(value="INVOKE", target="Lnet/minecraft/entity/player/PlayerInventory;setSelectedSlot(I)V", shift=At.Shift.AFTER)) + public void keypress(CallbackInfo ci) + { + if (isFlipped()) + { + flipItems(); + } + } +} diff --git a/src/main/java/com/kasetoatz/biggerhotbar/mixin/PlayerInventoryMixin.java b/src/main/java/com/kasetoatz/biggerhotbar/mixin/ScreenHandlerMixin.java similarity index 65% rename from src/main/java/com/kasetoatz/biggerhotbar/mixin/PlayerInventoryMixin.java rename to src/main/java/com/kasetoatz/biggerhotbar/mixin/ScreenHandlerMixin.java index 55723a1..3259798 100644 --- a/src/main/java/com/kasetoatz/biggerhotbar/mixin/PlayerInventoryMixin.java +++ b/src/main/java/com/kasetoatz/biggerhotbar/mixin/ScreenHandlerMixin.java @@ -3,31 +3,33 @@ package com.kasetoatz.biggerhotbar.mixin; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.ClientPlayerInteractionManager; -import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.ItemStack; +import net.minecraft.registry.Registries; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.screen.slot.Slot; import net.minecraft.screen.slot.SlotActionType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import static com.kasetoatz.biggerhotbar.state.StateManager.isFlipped; -@Mixin(PlayerInventory.class) -public abstract class PlayerInventoryMixin +@Mixin(ScreenHandler.class) +public abstract class ScreenHandlerMixin { - @Shadow public abstract ItemStack getStack(int slot); + @Shadow public abstract Slot getSlot(int index); - @Inject(method="addStack(ILnet/minecraft/item/ItemStack;)I", at=@At(value ="INVOKE", target="Lnet/minecraft/entity/player/PlayerInventory;setStack(ILnet/minecraft/item/ItemStack;)V", shift=At.Shift.AFTER)) - public void addStack(int slot, ItemStack stack, CallbackInfoReturnable cir) + @Inject(method="setStackInSlot", at=@At("HEAD")) + public void setStackInSlot(int slot, int revision, ItemStack stack, CallbackInfo ci) { - boolean flipped = isFlipped() && slot < 9; - if ((slot > 8 && slot < 27) || flipped) + if ((slot > 8 && slot < 27) || (isFlipped() && slot > 35 && slot < 45)) { for (int i = 27; i < 36; i++) { - if (getStack(i).isEmpty()) + if (getSlot(i).getStack().isEmpty()) { ClientPlayerEntity player = MinecraftClient.getInstance().player; ClientPlayerInteractionManager manager = MinecraftClient.getInstance().interactionManager; @@ -35,7 +37,7 @@ public abstract class PlayerInventoryMixin { return; } - manager.clickSlot(player.playerScreenHandler.syncId, flipped ? slot + 36 : slot, 0, SlotActionType.PICKUP, player); + manager.clickSlot(player.playerScreenHandler.syncId, slot, 0, SlotActionType.PICKUP, player); manager.clickSlot(player.playerScreenHandler.syncId, i, 0, SlotActionType.PICKUP, player); return; } diff --git a/src/main/java/com/kasetoatz/biggerhotbar/mixin/SlotMixin.java b/src/main/java/com/kasetoatz/biggerhotbar/mixin/SlotMixin.java new file mode 100644 index 0000000..cfa8bfc --- /dev/null +++ b/src/main/java/com/kasetoatz/biggerhotbar/mixin/SlotMixin.java @@ -0,0 +1,32 @@ +package com.kasetoatz.biggerhotbar.mixin; + +import com.kasetoatz.biggerhotbar.accessor.SlotAccessor; +import net.minecraft.screen.slot.Slot; +import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(Slot.class) +public abstract class SlotMixin implements SlotAccessor +{ + @Shadow @Final public int y; + @Unique private int originalY; + + @Inject(method="", at=@At("TAIL")) + public void init(CallbackInfo ci) + { + originalY = y; + } + + @Mutable + @Accessor("y") + public abstract void setY(int y); + + @Override + public int get_original_y() + { + return originalY; + } +} diff --git a/src/main/resources/biggerhotbar.mixins.json b/src/main/resources/biggerhotbar.mixins.json index 269a575..6f6ee4a 100644 --- a/src/main/resources/biggerhotbar.mixins.json +++ b/src/main/resources/biggerhotbar.mixins.json @@ -6,8 +6,11 @@ "client": [ "HandledScreenMixin", "InGameHudMixin", + "MinecraftClientMixin", "MouseMixin", - "PlayerInventoryMixin" + "ScreenHandlerMixin", + "SlotMixin", + "GenericContainerScreenHandlerMixin" ], "injectors": { "defaultRequire": 1