package net.minecraft.world.inventory; import com.google.common.collect.ImmutableList; import java.util.List; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; import net.minecraft.core.HolderGetter; import net.minecraft.core.component.DataComponents; import net.minecraft.core.registries.Registries; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.tags.BannerPatternTags; import net.minecraft.tags.TagKey; import net.minecraft.world.Container; import net.minecraft.world.SimpleContainer; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.BannerItem; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.DyeItem; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.BannerPattern; import net.minecraft.world.level.block.entity.BannerPatternLayers; public class LoomMenu extends AbstractContainerMenu { private static final int PATTERN_NOT_SET = -1; private static final int INV_SLOT_START = 4; private static final int INV_SLOT_END = 31; private static final int USE_ROW_SLOT_START = 31; private static final int USE_ROW_SLOT_END = 40; private final ContainerLevelAccess access; final DataSlot selectedBannerPatternIndex = DataSlot.standalone(); private List> selectablePatterns = List.of(); Runnable slotUpdateListener = () -> {}; private final HolderGetter patternGetter; final Slot bannerSlot; final Slot dyeSlot; private final Slot patternSlot; private final Slot resultSlot; long lastSoundTime; private final Container inputContainer = new SimpleContainer(3) { @Override public void setChanged() { super.setChanged(); LoomMenu.this.slotsChanged(this); LoomMenu.this.slotUpdateListener.run(); } }; private final Container outputContainer = new SimpleContainer(1) { @Override public void setChanged() { super.setChanged(); LoomMenu.this.slotUpdateListener.run(); } }; public LoomMenu(int p_39856_, Inventory p_39857_) { this(p_39856_, p_39857_, ContainerLevelAccess.NULL); } public LoomMenu(int p_39859_, Inventory p_39860_, final ContainerLevelAccess p_39861_) { super(MenuType.LOOM, p_39859_); this.access = p_39861_; this.bannerSlot = this.addSlot(new Slot(this.inputContainer, 0, 13, 26) { @Override public boolean mayPlace(ItemStack p_39918_) { return p_39918_.getItem() instanceof BannerItem; } }); this.dyeSlot = this.addSlot(new Slot(this.inputContainer, 1, 33, 26) { @Override public boolean mayPlace(ItemStack p_39927_) { return p_39927_.getItem() instanceof DyeItem; } }); this.patternSlot = this.addSlot(new Slot(this.inputContainer, 2, 23, 45) { @Override public boolean mayPlace(ItemStack p_39936_) { return p_39936_.has(DataComponents.PROVIDES_BANNER_PATTERNS); } }); this.resultSlot = this.addSlot(new Slot(this.outputContainer, 0, 143, 57) { @Override public boolean mayPlace(ItemStack p_39950_) { return false; } @Override public void onTake(Player p_150617_, ItemStack p_150618_) { LoomMenu.this.bannerSlot.remove(1); LoomMenu.this.dyeSlot.remove(1); if (!LoomMenu.this.bannerSlot.hasItem() || !LoomMenu.this.dyeSlot.hasItem()) { LoomMenu.this.selectedBannerPatternIndex.set(-1); } p_39861_.execute((p_390778_, p_390779_) -> { long i = p_390778_.getGameTime(); if (LoomMenu.this.lastSoundTime != i) { p_390778_.playSound(null, p_390779_, SoundEvents.UI_LOOM_TAKE_RESULT, SoundSource.BLOCKS, 1.0F, 1.0F); LoomMenu.this.lastSoundTime = i; } }); super.onTake(p_150617_, p_150618_); } }); this.addStandardInventorySlots(p_39860_, 8, 84); this.addDataSlot(this.selectedBannerPatternIndex); this.patternGetter = p_39860_.player.registryAccess().lookupOrThrow(Registries.BANNER_PATTERN); } @Override public boolean stillValid(Player p_39865_) { return stillValid(this.access, p_39865_, Blocks.LOOM); } @Override public boolean clickMenuButton(Player p_39867_, int p_39868_) { if (p_39868_ >= 0 && p_39868_ < this.selectablePatterns.size()) { this.selectedBannerPatternIndex.set(p_39868_); this.setupResultSlot(this.selectablePatterns.get(p_39868_)); return true; } else { return false; } } private List> getSelectablePatterns(ItemStack p_219994_) { if (p_219994_.isEmpty()) { return this.patternGetter.get(BannerPatternTags.NO_ITEM_REQUIRED).map(ImmutableList::copyOf).orElse(ImmutableList.of()); } else { TagKey tagkey = p_219994_.get(DataComponents.PROVIDES_BANNER_PATTERNS); return (List>)(tagkey != null ? this.patternGetter.get(tagkey).map(ImmutableList::copyOf).orElse(ImmutableList.of()) : List.of()); } } private boolean isValidPatternIndex(int p_242850_) { return p_242850_ >= 0 && p_242850_ < this.selectablePatterns.size(); } @Override public void slotsChanged(Container p_39863_) { ItemStack itemstack = this.bannerSlot.getItem(); ItemStack itemstack1 = this.dyeSlot.getItem(); ItemStack itemstack2 = this.patternSlot.getItem(); if (!itemstack.isEmpty() && !itemstack1.isEmpty()) { int i = this.selectedBannerPatternIndex.get(); boolean flag = this.isValidPatternIndex(i); List> list = this.selectablePatterns; this.selectablePatterns = this.getSelectablePatterns(itemstack2); Holder holder; if (this.selectablePatterns.size() == 1) { this.selectedBannerPatternIndex.set(0); holder = this.selectablePatterns.get(0); } else if (!flag) { this.selectedBannerPatternIndex.set(-1); holder = null; } else { Holder holder1 = list.get(i); int j = this.selectablePatterns.indexOf(holder1); if (j != -1) { holder = holder1; this.selectedBannerPatternIndex.set(j); } else { holder = null; this.selectedBannerPatternIndex.set(-1); } } if (holder != null) { BannerPatternLayers bannerpatternlayers = itemstack.getOrDefault(DataComponents.BANNER_PATTERNS, BannerPatternLayers.EMPTY); boolean flag1 = bannerpatternlayers.layers().size() >= 6; if (flag1) { this.selectedBannerPatternIndex.set(-1); this.resultSlot.set(ItemStack.EMPTY); } else { this.setupResultSlot(holder); } } else { this.resultSlot.set(ItemStack.EMPTY); } this.broadcastChanges(); } else { this.resultSlot.set(ItemStack.EMPTY); this.selectablePatterns = List.of(); this.selectedBannerPatternIndex.set(-1); } } public List> getSelectablePatterns() { return this.selectablePatterns; } public int getSelectedBannerPatternIndex() { return this.selectedBannerPatternIndex.get(); } public void registerUpdateListener(Runnable p_39879_) { this.slotUpdateListener = p_39879_; } @Override public ItemStack quickMoveStack(Player p_39883_, int p_39884_) { ItemStack itemstack = ItemStack.EMPTY; Slot slot = this.slots.get(p_39884_); if (slot != null && slot.hasItem()) { ItemStack itemstack1 = slot.getItem(); itemstack = itemstack1.copy(); if (p_39884_ == this.resultSlot.index) { if (!this.moveItemStackTo(itemstack1, 4, 40, true)) { return ItemStack.EMPTY; } slot.onQuickCraft(itemstack1, itemstack); } else if (p_39884_ != this.dyeSlot.index && p_39884_ != this.bannerSlot.index && p_39884_ != this.patternSlot.index) { if (itemstack1.getItem() instanceof BannerItem) { if (!this.moveItemStackTo(itemstack1, this.bannerSlot.index, this.bannerSlot.index + 1, false)) { return ItemStack.EMPTY; } } else if (itemstack1.getItem() instanceof DyeItem) { if (!this.moveItemStackTo(itemstack1, this.dyeSlot.index, this.dyeSlot.index + 1, false)) { return ItemStack.EMPTY; } } else if (itemstack1.has(DataComponents.PROVIDES_BANNER_PATTERNS)) { if (!this.moveItemStackTo(itemstack1, this.patternSlot.index, this.patternSlot.index + 1, false)) { return ItemStack.EMPTY; } } else if (p_39884_ >= 4 && p_39884_ < 31) { if (!this.moveItemStackTo(itemstack1, 31, 40, false)) { return ItemStack.EMPTY; } } else if (p_39884_ >= 31 && p_39884_ < 40 && !this.moveItemStackTo(itemstack1, 4, 31, false)) { return ItemStack.EMPTY; } } else if (!this.moveItemStackTo(itemstack1, 4, 40, false)) { return ItemStack.EMPTY; } if (itemstack1.isEmpty()) { slot.setByPlayer(ItemStack.EMPTY); } else { slot.setChanged(); } if (itemstack1.getCount() == itemstack.getCount()) { return ItemStack.EMPTY; } slot.onTake(p_39883_, itemstack1); } return itemstack; } @Override public void removed(Player p_39881_) { super.removed(p_39881_); this.access.execute((p_39871_, p_39872_) -> this.clearContainer(p_39881_, this.inputContainer)); } private void setupResultSlot(Holder p_219992_) { ItemStack itemstack = this.bannerSlot.getItem(); ItemStack itemstack1 = this.dyeSlot.getItem(); ItemStack itemstack2 = ItemStack.EMPTY; if (!itemstack.isEmpty() && !itemstack1.isEmpty()) { itemstack2 = itemstack.copyWithCount(1); DyeColor dyecolor = ((DyeItem)itemstack1.getItem()).getDyeColor(); itemstack2.update( DataComponents.BANNER_PATTERNS, BannerPatternLayers.EMPTY, p_327092_ -> new BannerPatternLayers.Builder().addAll(p_327092_).add(p_219992_, dyecolor).build() ); } if (!ItemStack.matches(itemstack2, this.resultSlot.getItem())) { this.resultSlot.set(itemstack2); } } public Slot getBannerSlot() { return this.bannerSlot; } public Slot getDyeSlot() { return this.dyeSlot; } public Slot getPatternSlot() { return this.patternSlot; } public Slot getResultSlot() { return this.resultSlot; } }