Skip to content

Commit

Permalink
Merge pull request #78 from cdqtzrc/fabric/1.21.x
Browse files Browse the repository at this point in the history
假人背包快速移动物品逻辑适配客户端
  • Loading branch information
Gu-ZT authored Nov 2, 2024
2 parents 5b295a0 + 8c8347f commit a4dd056
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package dev.dubhe.gugle.carpet.mixin;

import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;

@Mixin(AbstractContainerMenu.class)
public interface AbstractContainerMenuAccessor {
@Invoker("moveItemStackTo")
boolean invokerMoveItemStackTo(ItemStack itemStack, int i, int j, boolean bl);
}
53 changes: 53 additions & 0 deletions src/main/java/dev/dubhe/gugle/carpet/mixin/ChestMenuMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package dev.dubhe.gugle.carpet.mixin;

import dev.dubhe.gugle.carpet.api.menu.control.Button;
import dev.dubhe.gugle.carpet.tools.FakePlayerInventoryMenu;
import dev.dubhe.gugle.carpet.tools.SlotIcon;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.Container;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.ChestMenu;
import net.minecraft.world.inventory.InventoryMenu;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.component.CustomData;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
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;

@Mixin(ChestMenu.class)
public abstract class ChestMenuMixin {
@Unique
private final ChestMenu thisMenu = (ChestMenu) (Object) this;

@Inject(method = "<init>(Lnet/minecraft/world/inventory/MenuType;ILnet/minecraft/world/entity/player/Inventory;Lnet/minecraft/world/Container;I)V", at = @At("RETURN"))
private void init(MenuType<?> menuType, int i, Inventory inventory, Container container, int j, CallbackInfo ci) {
((SlotIcon) thisMenu.getSlot(1)).setIcon(InventoryMenu.EMPTY_ARMOR_SLOT_HELMET);
((SlotIcon) thisMenu.getSlot(2)).setIcon(InventoryMenu.EMPTY_ARMOR_SLOT_CHESTPLATE);
((SlotIcon) thisMenu.getSlot(3)).setIcon(InventoryMenu.EMPTY_ARMOR_SLOT_LEGGINGS);
((SlotIcon) thisMenu.getSlot(4)).setIcon(InventoryMenu.EMPTY_ARMOR_SLOT_BOOTS);
((SlotIcon) thisMenu.getSlot(7)).setIcon(InventoryMenu.EMPTY_ARMOR_SLOT_SHIELD);
}

@Inject(method = "quickMoveStack", at = @At("HEAD"), cancellable = true)
private void quickMove(Player player, int i, CallbackInfoReturnable<ItemStack> cir) {
if (this.isFakePlayerMenu()) {
cir.setReturnValue(FakePlayerInventoryMenu.quickMove(thisMenu, i));
}
}

@Unique
private boolean isFakePlayerMenu() {
ItemStack itemStack = thisMenu.getSlot(0).getItem();
if (itemStack.is(Items.STRUCTURE_VOID)) {
CustomData customData = itemStack.get(DataComponents.CUSTOM_DATA);
return customData != null && customData.copyTag().get(Button.GCA_CLEAR) != null;
}
return false;
}
}
33 changes: 33 additions & 0 deletions src/main/java/dev/dubhe/gugle/carpet/mixin/SlotMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package dev.dubhe.gugle.carpet.mixin;

import com.mojang.datafixers.util.Pair;
import dev.dubhe.gugle.carpet.tools.SlotIcon;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.inventory.InventoryMenu;
import net.minecraft.world.inventory.Slot;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@SuppressWarnings("AddedMixinMembersNamePattern")
@Mixin(Slot.class)
public class SlotMixin implements SlotIcon {
@Unique
private Pair<ResourceLocation, ResourceLocation> pair;

@Inject(method = "getNoItemIcon", at = @At("HEAD"), cancellable = true)
private void getNoItemIcon(CallbackInfoReturnable<Pair<ResourceLocation, ResourceLocation>> cir) {
if (this.pair != null) {
cir.setReturnValue(this.pair);
}
}

@Override
public void setIcon(ResourceLocation resource) {
if (resource != null) {
this.pair = Pair.of(InventoryMenu.BLOCK_ATLAS, resource);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dev.dubhe.gugle.carpet.tools;

import dev.dubhe.gugle.carpet.mixin.AbstractContainerMenuAccessor;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.Container;
import net.minecraft.world.entity.player.Inventory;
Expand All @@ -9,6 +10,7 @@
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.ArmorItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import org.jetbrains.annotations.NotNull;

public class FakePlayerInventoryMenu extends ChestMenu {
Expand All @@ -18,27 +20,42 @@ public FakePlayerInventoryMenu(int i, Inventory inventory, Container container)

@Override
public @NotNull ItemStack quickMoveStack(@NotNull Player player, int slotIndex) {
return quickMove(this, slotIndex);
}

public static ItemStack quickMove(ChestMenu chestMenu, int slotIndex) {
ItemStack remainingItem = ItemStack.EMPTY;
Slot slot = this.slots.get(slotIndex);
Slot slot = chestMenu.slots.get(slotIndex);
if (slot.hasItem()) {
ItemStack slotStack = slot.getItem();
remainingItem = slotStack.copy();
if (slotIndex < 54) {
if (!this.moveItemStackTo(slotStack, 54, this.slots.size(), true)) {
AbstractContainerMenuAccessor accessor = (AbstractContainerMenuAccessor) (chestMenu);
if (!accessor.invokerMoveItemStackTo(slotStack, 54, chestMenu.slots.size(), true)) {
return ItemStack.EMPTY;
}
} else if (slotStack.getItem() instanceof ArmorItem armorItem) {
// 如果是盔甲,移动到盔甲槽
int ordinal = armorItem.getType().ordinal();
if (moveToArmor(slotStack, ordinal) || moveToInventory(slotStack)) {
if (FakePlayerInventoryMenu.moveToArmor(chestMenu, slotStack, ordinal) || moveToInventory(chestMenu, slotStack)) {
return ItemStack.EMPTY;
}
} else if (slotStack.is(Items.ELYTRA)) {
// 如果是鞘翅,移动到盔甲槽
if (FakePlayerInventoryMenu.moveToArmor(chestMenu, slotStack, 1) || moveToInventory(chestMenu, slotStack)) {
return ItemStack.EMPTY;
}
} else if (slotStack.has(DataComponents.FOOD)) {
// 如果是食物,移动到副手
if (moveToOffHand(slotStack) || (moveToInventory(slotStack))) {
if (FakePlayerInventoryMenu.moveToOffHand(chestMenu, slotStack) || moveToInventory(chestMenu, slotStack)) {
return ItemStack.EMPTY;
}
} else if (moveToInventory(chestMenu, slotStack)) {
// 物品栏没有剩余空间了,移动到盔甲和副手
AbstractContainerMenuAccessor accessor = (AbstractContainerMenuAccessor) (chestMenu);
if (accessor.invokerMoveItemStackTo(slotStack, 1, 8, false)) {
return ItemStack.EMPTY;
}
} else if (moveToInventory(slotStack)) {
// 其它物品移动的物品栏中
return ItemStack.EMPTY;
}
Expand All @@ -52,17 +69,20 @@ public FakePlayerInventoryMenu(int i, Inventory inventory, Container container)
}

// 移动到副手
private boolean moveToOffHand(ItemStack slotStack) {
return this.moveItemStackTo(slotStack, 7, 8, false);
private static boolean moveToOffHand(ChestMenu chestMenu, ItemStack slotStack) {
AbstractContainerMenuAccessor accessor = (AbstractContainerMenuAccessor) (chestMenu);
return accessor.invokerMoveItemStackTo(slotStack, 7, 8, false);
}

// 移动到盔甲槽
private boolean moveToArmor(ItemStack slotStack, int ordinal) {
return this.moveItemStackTo(slotStack, ordinal + 1, ordinal + 2, false);
private static boolean moveToArmor(ChestMenu chestMenu, ItemStack slotStack, int ordinal) {
AbstractContainerMenuAccessor accessor = (AbstractContainerMenuAccessor) (chestMenu);
return accessor.invokerMoveItemStackTo(slotStack, ordinal + 1, ordinal + 2, false);
}

// 将物品移动的物品栏
private boolean moveToInventory(ItemStack slotStack) {
return !this.moveItemStackTo(slotStack, 18, 54, false);
private static boolean moveToInventory(ChestMenu chestMenu, ItemStack slotStack) {
AbstractContainerMenuAccessor accessor = (AbstractContainerMenuAccessor) (chestMenu);
return !accessor.invokerMoveItemStackTo(slotStack, 18, 54, false);
}
}
7 changes: 7 additions & 0 deletions src/main/java/dev/dubhe/gugle/carpet/tools/SlotIcon.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package dev.dubhe.gugle.carpet.tools;

import net.minecraft.resources.ResourceLocation;

public interface SlotIcon {
void setIcon(ResourceLocation resource);
}
5 changes: 4 additions & 1 deletion src/main/resources/gca.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
"package": "dev.dubhe.gugle.carpet.mixin",
"compatibilityLevel": "JAVA_17",
"mixins": [
"AbstractContainerMenuAccessor",
"AbstractContainerMenuMixin",
"APAccessor",
"AxeItemMixin",
"ChestMenuMixin",
"CommandsMixin",
"EntityInvoker",
"EntityPlayerMPFakeInvoker",
Expand All @@ -19,7 +21,8 @@
"PlayerMixin",
"ServerLevelMixin",
"ServerPlaceRecipeMixin",
"SignBlockMixin"
"SignBlockMixin",
"SlotMixin"
],
"server": [
],
Expand Down

0 comments on commit a4dd056

Please sign in to comment.