269 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			269 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| package net.minecraft.client.gui.screens.inventory;
 | |
| 
 | |
| import com.mojang.blaze3d.platform.Lighting;
 | |
| import java.util.List;
 | |
| import net.fabricmc.api.EnvType;
 | |
| import net.fabricmc.api.Environment;
 | |
| import net.minecraft.client.Minecraft;
 | |
| import net.minecraft.client.gui.GuiGraphics;
 | |
| import net.minecraft.client.model.geom.ModelLayers;
 | |
| import net.minecraft.client.model.geom.ModelPart;
 | |
| import net.minecraft.client.renderer.RenderPipelines;
 | |
| import net.minecraft.client.renderer.Sheets;
 | |
| import net.minecraft.client.renderer.texture.TextureAtlasSprite;
 | |
| import net.minecraft.client.resources.sounds.SimpleSoundInstance;
 | |
| import net.minecraft.core.Holder;
 | |
| import net.minecraft.core.component.DataComponents;
 | |
| import net.minecraft.network.chat.Component;
 | |
| import net.minecraft.resources.ResourceLocation;
 | |
| import net.minecraft.sounds.SoundEvents;
 | |
| import net.minecraft.util.Mth;
 | |
| import net.minecraft.world.entity.player.Inventory;
 | |
| import net.minecraft.world.inventory.LoomMenu;
 | |
| import net.minecraft.world.inventory.Slot;
 | |
| import net.minecraft.world.item.BannerItem;
 | |
| import net.minecraft.world.item.DyeColor;
 | |
| import net.minecraft.world.item.ItemStack;
 | |
| import net.minecraft.world.level.block.entity.BannerPattern;
 | |
| import net.minecraft.world.level.block.entity.BannerPatternLayers;
 | |
| import org.jetbrains.annotations.Nullable;
 | |
| 
 | |
| @Environment(EnvType.CLIENT)
 | |
| public class LoomScreen extends AbstractContainerScreen<LoomMenu> {
 | |
| 	private static final ResourceLocation BANNER_SLOT_SPRITE = ResourceLocation.withDefaultNamespace("container/slot/banner");
 | |
| 	private static final ResourceLocation DYE_SLOT_SPRITE = ResourceLocation.withDefaultNamespace("container/slot/dye");
 | |
| 	private static final ResourceLocation PATTERN_SLOT_SPRITE = ResourceLocation.withDefaultNamespace("container/slot/banner_pattern");
 | |
| 	private static final ResourceLocation SCROLLER_SPRITE = ResourceLocation.withDefaultNamespace("container/loom/scroller");
 | |
| 	private static final ResourceLocation SCROLLER_DISABLED_SPRITE = ResourceLocation.withDefaultNamespace("container/loom/scroller_disabled");
 | |
| 	private static final ResourceLocation PATTERN_SELECTED_SPRITE = ResourceLocation.withDefaultNamespace("container/loom/pattern_selected");
 | |
| 	private static final ResourceLocation PATTERN_HIGHLIGHTED_SPRITE = ResourceLocation.withDefaultNamespace("container/loom/pattern_highlighted");
 | |
| 	private static final ResourceLocation PATTERN_SPRITE = ResourceLocation.withDefaultNamespace("container/loom/pattern");
 | |
| 	private static final ResourceLocation ERROR_SPRITE = ResourceLocation.withDefaultNamespace("container/loom/error");
 | |
| 	private static final ResourceLocation BG_LOCATION = ResourceLocation.withDefaultNamespace("textures/gui/container/loom.png");
 | |
| 	private static final int PATTERN_COLUMNS = 4;
 | |
| 	private static final int PATTERN_ROWS = 4;
 | |
| 	private static final int SCROLLER_WIDTH = 12;
 | |
| 	private static final int SCROLLER_HEIGHT = 15;
 | |
| 	private static final int PATTERN_IMAGE_SIZE = 14;
 | |
| 	private static final int SCROLLER_FULL_HEIGHT = 56;
 | |
| 	private static final int PATTERNS_X = 60;
 | |
| 	private static final int PATTERNS_Y = 13;
 | |
| 	private static final float BANNER_PATTERN_TEXTURE_SIZE = 64.0F;
 | |
| 	private static final float BANNER_PATTERN_WIDTH = 21.0F;
 | |
| 	private static final float BANNER_PATTERN_HEIGHT = 40.0F;
 | |
| 	private ModelPart flag;
 | |
| 	@Nullable
 | |
| 	private BannerPatternLayers resultBannerPatterns;
 | |
| 	private ItemStack bannerStack = ItemStack.EMPTY;
 | |
| 	private ItemStack dyeStack = ItemStack.EMPTY;
 | |
| 	private ItemStack patternStack = ItemStack.EMPTY;
 | |
| 	private boolean displayPatterns;
 | |
| 	private boolean hasMaxPatterns;
 | |
| 	private float scrollOffs;
 | |
| 	private boolean scrolling;
 | |
| 	private int startRow;
 | |
| 
 | |
| 	public LoomScreen(LoomMenu menu, Inventory playerInventory, Component title) {
 | |
| 		super(menu, playerInventory, title);
 | |
| 		menu.registerUpdateListener(this::containerChanged);
 | |
| 		this.titleLabelY -= 2;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	protected void init() {
 | |
| 		super.init();
 | |
| 		this.flag = this.minecraft.getEntityModels().bakeLayer(ModelLayers.STANDING_BANNER_FLAG).getChild("flag");
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
 | |
| 		super.render(guiGraphics, mouseX, mouseY, partialTick);
 | |
| 		this.renderTooltip(guiGraphics, mouseX, mouseY);
 | |
| 	}
 | |
| 
 | |
| 	private int totalRowCount() {
 | |
| 		return Mth.positiveCeilDiv(this.menu.getSelectablePatterns().size(), 4);
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	protected void renderBg(GuiGraphics guiGraphics, float partialTick, int mouseX, int mouseY) {
 | |
| 		int i = this.leftPos;
 | |
| 		int j = this.topPos;
 | |
| 		guiGraphics.blit(RenderPipelines.GUI_TEXTURED, BG_LOCATION, i, j, 0.0F, 0.0F, this.imageWidth, this.imageHeight, 256, 256);
 | |
| 		Slot slot = this.menu.getBannerSlot();
 | |
| 		Slot slot2 = this.menu.getDyeSlot();
 | |
| 		Slot slot3 = this.menu.getPatternSlot();
 | |
| 		Slot slot4 = this.menu.getResultSlot();
 | |
| 		if (!slot.hasItem()) {
 | |
| 			guiGraphics.blitSprite(RenderPipelines.GUI_TEXTURED, BANNER_SLOT_SPRITE, i + slot.x, j + slot.y, 16, 16);
 | |
| 		}
 | |
| 
 | |
| 		if (!slot2.hasItem()) {
 | |
| 			guiGraphics.blitSprite(RenderPipelines.GUI_TEXTURED, DYE_SLOT_SPRITE, i + slot2.x, j + slot2.y, 16, 16);
 | |
| 		}
 | |
| 
 | |
| 		if (!slot3.hasItem()) {
 | |
| 			guiGraphics.blitSprite(RenderPipelines.GUI_TEXTURED, PATTERN_SLOT_SPRITE, i + slot3.x, j + slot3.y, 16, 16);
 | |
| 		}
 | |
| 
 | |
| 		int k = (int)(41.0F * this.scrollOffs);
 | |
| 		ResourceLocation resourceLocation = this.displayPatterns ? SCROLLER_SPRITE : SCROLLER_DISABLED_SPRITE;
 | |
| 		guiGraphics.blitSprite(RenderPipelines.GUI_TEXTURED, resourceLocation, i + 119, j + 13 + k, 12, 15);
 | |
| 		if (this.resultBannerPatterns != null && !this.hasMaxPatterns) {
 | |
| 			DyeColor dyeColor = ((BannerItem)slot4.getItem().getItem()).getColor();
 | |
| 			int l = i + 141;
 | |
| 			int m = j + 8;
 | |
| 			guiGraphics.submitBannerPatternRenderState(this.flag, dyeColor, this.resultBannerPatterns, l, m, l + 20, m + 40);
 | |
| 		} else if (this.hasMaxPatterns) {
 | |
| 			guiGraphics.blitSprite(RenderPipelines.GUI_TEXTURED, ERROR_SPRITE, i + slot4.x - 5, j + slot4.y - 5, 26, 26);
 | |
| 		}
 | |
| 
 | |
| 		if (this.displayPatterns) {
 | |
| 			int n = i + 60;
 | |
| 			int l = j + 13;
 | |
| 			List<Holder<BannerPattern>> list = this.menu.getSelectablePatterns();
 | |
| 
 | |
| 			label64:
 | |
| 			for (int o = 0; o < 4; o++) {
 | |
| 				for (int p = 0; p < 4; p++) {
 | |
| 					int q = o + this.startRow;
 | |
| 					int r = q * 4 + p;
 | |
| 					if (r >= list.size()) {
 | |
| 						break label64;
 | |
| 					}
 | |
| 
 | |
| 					int s = n + p * 14;
 | |
| 					int t = l + o * 14;
 | |
| 					boolean bl = mouseX >= s && mouseY >= t && mouseX < s + 14 && mouseY < t + 14;
 | |
| 					ResourceLocation resourceLocation2;
 | |
| 					if (r == this.menu.getSelectedBannerPatternIndex()) {
 | |
| 						resourceLocation2 = PATTERN_SELECTED_SPRITE;
 | |
| 					} else if (bl) {
 | |
| 						resourceLocation2 = PATTERN_HIGHLIGHTED_SPRITE;
 | |
| 					} else {
 | |
| 						resourceLocation2 = PATTERN_SPRITE;
 | |
| 					}
 | |
| 
 | |
| 					guiGraphics.blitSprite(RenderPipelines.GUI_TEXTURED, resourceLocation2, s, t, 14, 14);
 | |
| 					TextureAtlasSprite textureAtlasSprite = Sheets.getBannerMaterial((Holder<BannerPattern>)list.get(r)).sprite();
 | |
| 					this.renderBannerOnButton(guiGraphics, s, t, textureAtlasSprite);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		Minecraft.getInstance().gameRenderer.getLighting().setupFor(Lighting.Entry.ITEMS_3D);
 | |
| 	}
 | |
| 
 | |
| 	private void renderBannerOnButton(GuiGraphics guiGraphics, int x, int y, TextureAtlasSprite sprite) {
 | |
| 		guiGraphics.pose().pushMatrix();
 | |
| 		guiGraphics.pose().translate(x + 4, y + 2);
 | |
| 		float f = sprite.getU0();
 | |
| 		float g = f + (sprite.getU1() - sprite.getU0()) * 21.0F / 64.0F;
 | |
| 		float h = sprite.getV1() - sprite.getV0();
 | |
| 		float i = sprite.getV0() + h / 64.0F;
 | |
| 		float j = i + h * 40.0F / 64.0F;
 | |
| 		int k = 5;
 | |
| 		int l = 10;
 | |
| 		guiGraphics.fill(0, 0, 5, 10, DyeColor.GRAY.getTextureDiffuseColor());
 | |
| 		guiGraphics.blit(sprite.atlasLocation(), 0, 0, 5, 10, f, g, i, j);
 | |
| 		guiGraphics.pose().popMatrix();
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public boolean mouseClicked(double mouseX, double mouseY, int button) {
 | |
| 		this.scrolling = false;
 | |
| 		if (this.displayPatterns) {
 | |
| 			int i = this.leftPos + 60;
 | |
| 			int j = this.topPos + 13;
 | |
| 
 | |
| 			for (int k = 0; k < 4; k++) {
 | |
| 				for (int l = 0; l < 4; l++) {
 | |
| 					double d = mouseX - (i + l * 14);
 | |
| 					double e = mouseY - (j + k * 14);
 | |
| 					int m = k + this.startRow;
 | |
| 					int n = m * 4 + l;
 | |
| 					if (d >= 0.0 && e >= 0.0 && d < 14.0 && e < 14.0 && this.menu.clickMenuButton(this.minecraft.player, n)) {
 | |
| 						Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_LOOM_SELECT_PATTERN, 1.0F));
 | |
| 						this.minecraft.gameMode.handleInventoryButtonClick(this.menu.containerId, n);
 | |
| 						return true;
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			i = this.leftPos + 119;
 | |
| 			j = this.topPos + 9;
 | |
| 			if (mouseX >= i && mouseX < i + 12 && mouseY >= j && mouseY < j + 56) {
 | |
| 				this.scrolling = true;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return super.mouseClicked(mouseX, mouseY, button);
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public boolean mouseDragged(double mouseX, double mouseY, int button, double dragX, double dragY) {
 | |
| 		int i = this.totalRowCount() - 4;
 | |
| 		if (this.scrolling && this.displayPatterns && i > 0) {
 | |
| 			int j = this.topPos + 13;
 | |
| 			int k = j + 56;
 | |
| 			this.scrollOffs = ((float)mouseY - j - 7.5F) / (k - j - 15.0F);
 | |
| 			this.scrollOffs = Mth.clamp(this.scrollOffs, 0.0F, 1.0F);
 | |
| 			this.startRow = Math.max((int)(this.scrollOffs * i + 0.5), 0);
 | |
| 			return true;
 | |
| 		} else {
 | |
| 			return super.mouseDragged(mouseX, mouseY, button, dragX, dragY);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public boolean mouseScrolled(double mouseX, double mouseY, double scrollX, double scrollY) {
 | |
| 		if (super.mouseScrolled(mouseX, mouseY, scrollX, scrollY)) {
 | |
| 			return true;
 | |
| 		} else {
 | |
| 			int i = this.totalRowCount() - 4;
 | |
| 			if (this.displayPatterns && i > 0) {
 | |
| 				float f = (float)scrollY / i;
 | |
| 				this.scrollOffs = Mth.clamp(this.scrollOffs - f, 0.0F, 1.0F);
 | |
| 				this.startRow = Math.max((int)(this.scrollOffs * i + 0.5F), 0);
 | |
| 			}
 | |
| 
 | |
| 			return true;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	protected boolean hasClickedOutside(double mouseX, double mouseY, int guiLeft, int guiTop, int mouseButton) {
 | |
| 		return mouseX < guiLeft || mouseY < guiTop || mouseX >= guiLeft + this.imageWidth || mouseY >= guiTop + this.imageHeight;
 | |
| 	}
 | |
| 
 | |
| 	private void containerChanged() {
 | |
| 		ItemStack itemStack = this.menu.getResultSlot().getItem();
 | |
| 		if (itemStack.isEmpty()) {
 | |
| 			this.resultBannerPatterns = null;
 | |
| 		} else {
 | |
| 			this.resultBannerPatterns = itemStack.getOrDefault(DataComponents.BANNER_PATTERNS, BannerPatternLayers.EMPTY);
 | |
| 		}
 | |
| 
 | |
| 		ItemStack itemStack2 = this.menu.getBannerSlot().getItem();
 | |
| 		ItemStack itemStack3 = this.menu.getDyeSlot().getItem();
 | |
| 		ItemStack itemStack4 = this.menu.getPatternSlot().getItem();
 | |
| 		BannerPatternLayers bannerPatternLayers = itemStack2.getOrDefault(DataComponents.BANNER_PATTERNS, BannerPatternLayers.EMPTY);
 | |
| 		this.hasMaxPatterns = bannerPatternLayers.layers().size() >= 6;
 | |
| 		if (this.hasMaxPatterns) {
 | |
| 			this.resultBannerPatterns = null;
 | |
| 		}
 | |
| 
 | |
| 		if (!ItemStack.matches(itemStack2, this.bannerStack) || !ItemStack.matches(itemStack3, this.dyeStack) || !ItemStack.matches(itemStack4, this.patternStack)) {
 | |
| 			this.displayPatterns = !itemStack2.isEmpty() && !itemStack3.isEmpty() && !this.hasMaxPatterns && !this.menu.getSelectablePatterns().isEmpty();
 | |
| 		}
 | |
| 
 | |
| 		if (this.startRow >= this.totalRowCount()) {
 | |
| 			this.startRow = 0;
 | |
| 			this.scrollOffs = 0.0F;
 | |
| 		}
 | |
| 
 | |
| 		this.bannerStack = itemStack2.copy();
 | |
| 		this.dyeStack = itemStack3.copy();
 | |
| 		this.patternStack = itemStack4.copy();
 | |
| 	}
 | |
| }
 |