209 lines
		
	
	
	
		
			8.5 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			209 lines
		
	
	
	
		
			8.5 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| package net.minecraft.client.gui.screens.inventory;
 | |
| 
 | |
| 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.renderer.RenderPipelines;
 | |
| import net.minecraft.client.resources.sounds.SimpleSoundInstance;
 | |
| import net.minecraft.network.chat.Component;
 | |
| import net.minecraft.resources.ResourceLocation;
 | |
| import net.minecraft.sounds.SoundEvents;
 | |
| import net.minecraft.util.Mth;
 | |
| import net.minecraft.util.context.ContextMap;
 | |
| import net.minecraft.world.entity.player.Inventory;
 | |
| import net.minecraft.world.inventory.StonecutterMenu;
 | |
| import net.minecraft.world.item.crafting.SelectableRecipe;
 | |
| import net.minecraft.world.item.crafting.StonecutterRecipe;
 | |
| import net.minecraft.world.item.crafting.display.SlotDisplay;
 | |
| import net.minecraft.world.item.crafting.display.SlotDisplayContext;
 | |
| 
 | |
| @Environment(EnvType.CLIENT)
 | |
| public class StonecutterScreen extends AbstractContainerScreen<StonecutterMenu> {
 | |
| 	private static final ResourceLocation SCROLLER_SPRITE = ResourceLocation.withDefaultNamespace("container/stonecutter/scroller");
 | |
| 	private static final ResourceLocation SCROLLER_DISABLED_SPRITE = ResourceLocation.withDefaultNamespace("container/stonecutter/scroller_disabled");
 | |
| 	private static final ResourceLocation RECIPE_SELECTED_SPRITE = ResourceLocation.withDefaultNamespace("container/stonecutter/recipe_selected");
 | |
| 	private static final ResourceLocation RECIPE_HIGHLIGHTED_SPRITE = ResourceLocation.withDefaultNamespace("container/stonecutter/recipe_highlighted");
 | |
| 	private static final ResourceLocation RECIPE_SPRITE = ResourceLocation.withDefaultNamespace("container/stonecutter/recipe");
 | |
| 	private static final ResourceLocation BG_LOCATION = ResourceLocation.withDefaultNamespace("textures/gui/container/stonecutter.png");
 | |
| 	private static final int SCROLLER_WIDTH = 12;
 | |
| 	private static final int SCROLLER_HEIGHT = 15;
 | |
| 	private static final int RECIPES_COLUMNS = 4;
 | |
| 	private static final int RECIPES_ROWS = 3;
 | |
| 	private static final int RECIPES_IMAGE_SIZE_WIDTH = 16;
 | |
| 	private static final int RECIPES_IMAGE_SIZE_HEIGHT = 18;
 | |
| 	private static final int SCROLLER_FULL_HEIGHT = 54;
 | |
| 	private static final int RECIPES_X = 52;
 | |
| 	private static final int RECIPES_Y = 14;
 | |
| 	private float scrollOffs;
 | |
| 	/**
 | |
| 	 * Is {@code true} if the player clicked on the scroll wheel in the GUI.
 | |
| 	 */
 | |
| 	private boolean scrolling;
 | |
| 	/**
 | |
| 	 * The index of the first recipe to display.
 | |
| 	 * The number of recipes displayed at any time is 12 (4 recipes per row, and 3 rows). If the player scrolled down one row, this value would be 4 (representing the index of the first slot on the second row).
 | |
| 	 */
 | |
| 	private int startIndex;
 | |
| 	private boolean displayRecipes;
 | |
| 
 | |
| 	public StonecutterScreen(StonecutterMenu menu, Inventory playerInventory, Component title) {
 | |
| 		super(menu, playerInventory, title);
 | |
| 		menu.registerUpdateListener(this::containerChanged);
 | |
| 		this.titleLabelY--;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
 | |
| 		super.render(guiGraphics, mouseX, mouseY, partialTick);
 | |
| 		this.renderTooltip(guiGraphics, mouseX, mouseY);
 | |
| 	}
 | |
| 
 | |
| 	@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);
 | |
| 		int k = (int)(41.0F * this.scrollOffs);
 | |
| 		ResourceLocation resourceLocation = this.isScrollBarActive() ? SCROLLER_SPRITE : SCROLLER_DISABLED_SPRITE;
 | |
| 		guiGraphics.blitSprite(RenderPipelines.GUI_TEXTURED, resourceLocation, i + 119, j + 15 + k, 12, 15);
 | |
| 		int l = this.leftPos + 52;
 | |
| 		int m = this.topPos + 14;
 | |
| 		int n = this.startIndex + 12;
 | |
| 		this.renderButtons(guiGraphics, mouseX, mouseY, l, m, n);
 | |
| 		this.renderRecipes(guiGraphics, l, m, n);
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	protected void renderTooltip(GuiGraphics guiGraphics, int x, int y) {
 | |
| 		super.renderTooltip(guiGraphics, x, y);
 | |
| 		if (this.displayRecipes) {
 | |
| 			int i = this.leftPos + 52;
 | |
| 			int j = this.topPos + 14;
 | |
| 			int k = this.startIndex + 12;
 | |
| 			SelectableRecipe.SingleInputSet<StonecutterRecipe> singleInputSet = this.menu.getVisibleRecipes();
 | |
| 
 | |
| 			for (int l = this.startIndex; l < k && l < singleInputSet.size(); l++) {
 | |
| 				int m = l - this.startIndex;
 | |
| 				int n = i + m % 4 * 16;
 | |
| 				int o = j + m / 4 * 18 + 2;
 | |
| 				if (x >= n && x < n + 16 && y >= o && y < o + 18) {
 | |
| 					ContextMap contextMap = SlotDisplayContext.fromLevel(this.minecraft.level);
 | |
| 					SlotDisplay slotDisplay = ((SelectableRecipe.SingleInputEntry)singleInputSet.entries().get(l)).recipe().optionDisplay();
 | |
| 					guiGraphics.setTooltipForNextFrame(this.font, slotDisplay.resolveForFirstStack(contextMap), x, y);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	private void renderButtons(GuiGraphics guiGraphics, int mouseX, int mouseY, int x, int y, int lastVisibleElementIndex) {
 | |
| 		for (int i = this.startIndex; i < lastVisibleElementIndex && i < this.menu.getNumberOfVisibleRecipes(); i++) {
 | |
| 			int j = i - this.startIndex;
 | |
| 			int k = x + j % 4 * 16;
 | |
| 			int l = j / 4;
 | |
| 			int m = y + l * 18 + 2;
 | |
| 			ResourceLocation resourceLocation;
 | |
| 			if (i == this.menu.getSelectedRecipeIndex()) {
 | |
| 				resourceLocation = RECIPE_SELECTED_SPRITE;
 | |
| 			} else if (mouseX >= k && mouseY >= m && mouseX < k + 16 && mouseY < m + 18) {
 | |
| 				resourceLocation = RECIPE_HIGHLIGHTED_SPRITE;
 | |
| 			} else {
 | |
| 				resourceLocation = RECIPE_SPRITE;
 | |
| 			}
 | |
| 
 | |
| 			guiGraphics.blitSprite(RenderPipelines.GUI_TEXTURED, resourceLocation, k, m - 1, 16, 18);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	private void renderRecipes(GuiGraphics guiGraphics, int x, int y, int startIndex) {
 | |
| 		SelectableRecipe.SingleInputSet<StonecutterRecipe> singleInputSet = this.menu.getVisibleRecipes();
 | |
| 		ContextMap contextMap = SlotDisplayContext.fromLevel(this.minecraft.level);
 | |
| 
 | |
| 		for (int i = this.startIndex; i < startIndex && i < singleInputSet.size(); i++) {
 | |
| 			int j = i - this.startIndex;
 | |
| 			int k = x + j % 4 * 16;
 | |
| 			int l = j / 4;
 | |
| 			int m = y + l * 18 + 2;
 | |
| 			SlotDisplay slotDisplay = ((SelectableRecipe.SingleInputEntry)singleInputSet.entries().get(i)).recipe().optionDisplay();
 | |
| 			guiGraphics.renderItem(slotDisplay.resolveForFirstStack(contextMap), k, m);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public boolean mouseClicked(double mouseX, double mouseY, int button) {
 | |
| 		this.scrolling = false;
 | |
| 		if (this.displayRecipes) {
 | |
| 			int i = this.leftPos + 52;
 | |
| 			int j = this.topPos + 14;
 | |
| 			int k = this.startIndex + 12;
 | |
| 
 | |
| 			for (int l = this.startIndex; l < k; l++) {
 | |
| 				int m = l - this.startIndex;
 | |
| 				double d = mouseX - (i + m % 4 * 16);
 | |
| 				double e = mouseY - (j + m / 4 * 18);
 | |
| 				if (d >= 0.0 && e >= 0.0 && d < 16.0 && e < 18.0 && this.menu.clickMenuButton(this.minecraft.player, l)) {
 | |
| 					Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_STONECUTTER_SELECT_RECIPE, 1.0F));
 | |
| 					this.minecraft.gameMode.handleInventoryButtonClick(this.menu.containerId, l);
 | |
| 					return true;
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			i = this.leftPos + 119;
 | |
| 			j = this.topPos + 9;
 | |
| 			if (mouseX >= i && mouseX < i + 12 && mouseY >= j && mouseY < j + 54) {
 | |
| 				this.scrolling = true;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return super.mouseClicked(mouseX, mouseY, button);
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public boolean mouseDragged(double mouseX, double mouseY, int button, double dragX, double dragY) {
 | |
| 		if (this.scrolling && this.isScrollBarActive()) {
 | |
| 			int i = this.topPos + 14;
 | |
| 			int j = i + 54;
 | |
| 			this.scrollOffs = ((float)mouseY - i - 7.5F) / (j - i - 15.0F);
 | |
| 			this.scrollOffs = Mth.clamp(this.scrollOffs, 0.0F, 1.0F);
 | |
| 			this.startIndex = (int)(this.scrollOffs * this.getOffscreenRows() + 0.5) * 4;
 | |
| 			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 {
 | |
| 			if (this.isScrollBarActive()) {
 | |
| 				int i = this.getOffscreenRows();
 | |
| 				float f = (float)scrollY / i;
 | |
| 				this.scrollOffs = Mth.clamp(this.scrollOffs - f, 0.0F, 1.0F);
 | |
| 				this.startIndex = (int)(this.scrollOffs * i + 0.5) * 4;
 | |
| 			}
 | |
| 
 | |
| 			return true;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	private boolean isScrollBarActive() {
 | |
| 		return this.displayRecipes && this.menu.getNumberOfVisibleRecipes() > 12;
 | |
| 	}
 | |
| 
 | |
| 	protected int getOffscreenRows() {
 | |
| 		return (this.menu.getNumberOfVisibleRecipes() + 4 - 1) / 4 - 3;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Called every time this screen's container is changed (is marked as dirty).
 | |
| 	 */
 | |
| 	private void containerChanged() {
 | |
| 		this.displayRecipes = this.menu.hasInputItem();
 | |
| 		if (!this.displayRecipes) {
 | |
| 			this.scrollOffs = 0.0F;
 | |
| 			this.startIndex = 0;
 | |
| 		}
 | |
| 	}
 | |
| }
 |