/*
* Copyright (C) 2022 NotEnoughUpdates contributors
*
* This file is part of NotEnoughUpdates.
*
* NotEnoughUpdates is free software: you can redistribute it
* and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* NotEnoughUpdates is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with NotEnoughUpdates. If not, see .
*/
package io.github.moulberry.notenoughupdates.recipes;
import io.github.moulberry.notenoughupdates.NEUManager;
import io.github.moulberry.notenoughupdates.miscfeatures.EnchantingSolvers;
import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.inventory.GuiChest;
import net.minecraft.inventory.ContainerChest;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraftforge.client.event.GuiOpenEvent;
import net.minecraftforge.client.event.GuiScreenEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import org.lwjgl.input.Keyboard;
import java.util.function.BiConsumer;
public class CraftingOverlay {
private final NEUManager manager;
private CraftingRecipe currentRecipe = null;
public CraftingOverlay(NEUManager manager) {
this.manager = manager;
MinecraftForge.EVENT_BUS.register(this);
}
public void setShownRecipe(CraftingRecipe recipe) {
currentRecipe = recipe;
}
private void forEachSlot(ContainerChest chest, BiConsumer block) {
for (int i = 0; i < 9; i++) {
Ingredient recipeIngredient = currentRecipe.getInputs()[i];
Slot slot = chest.inventorySlots.get(10 + 9 * (i / 3) + (i % 3));
block.accept(recipeIngredient, slot);
}
}
private void forEachHoveredSlot(
GuiChest gui,
ContainerChest chest,
int mouseX,
int mouseY,
BiConsumer block
) {
forEachSlot(chest, (recipeIngredient, slot) -> {
if (Utils.isWithinRect(
mouseX, mouseY,
slot.xDisplayPosition + ((AccessorGuiContainer) gui).getGuiLeft(),
slot.yDisplayPosition + ((AccessorGuiContainer) gui).getGuiTop(),
16, 16
))
block.accept(recipeIngredient, slot);
});
}
private void runIfCraftingOverlayIsPresent(Gui gui, BiConsumer block) {
if (currentRecipe == null) return;
if (!(gui instanceof GuiChest)) return;
GuiChest guiChest = (GuiChest) gui;
ContainerChest chest = (ContainerChest) guiChest.inventorySlots;
IInventory chestInventory = chest.getLowerChestInventory();
if (!"Craft Item".equals(chestInventory.getDisplayName().getUnformattedText())) return;
block.accept(guiChest, chest);
}
@SubscribeEvent
public void onGuiOpen(GuiOpenEvent event) {
currentRecipe = null;
}
@SubscribeEvent
public void onRender(GuiScreenEvent.DrawScreenEvent.Post event) {
runIfCraftingOverlayIsPresent(event.gui, (guiChest, chest) -> {
renderSlots(guiChest, chest);
if (currentRecipe.getCraftText() != null) {
FontRenderer fontRenderer = Minecraft.getMinecraft().fontRendererObj;
fontRenderer.drawStringWithShadow(
currentRecipe.getCraftText(),
Utils.peekGuiScale().getScaledWidth() / 2f - fontRenderer.getStringWidth(currentRecipe.getCraftText()) / 2f,
((AccessorGuiContainer) guiChest).getGuiTop() - 15f, 0x808080
);
}
renderTooltip(guiChest, chest);
});
}
@SubscribeEvent
public void onKeyDown(GuiScreenEvent.KeyboardInputEvent.Pre event) {
if (!Keyboard.getEventKeyState() ||
(Keyboard.getEventKey() != Keyboard.KEY_U && Keyboard.getEventKey() != Keyboard.KEY_R))
return;
if (EnchantingSolvers.currentSolver != EnchantingSolvers.SolverType.NONE) return;
runIfCraftingOverlayIsPresent(event.gui, (guiChest, chest) -> {
int mouseX = Utils.getMouseX();
int mouseY = Utils.getMouseY();
forEachHoveredSlot(guiChest, chest, mouseX, mouseY, (recipeIngredient, slot) -> {
if (slot.getStack() == null && recipeIngredient != null) {
if (Keyboard.getEventKey() == Keyboard.KEY_R)
manager.showRecipe(recipeIngredient.getInternalItemId());
if (Keyboard.getEventKey() == Keyboard.KEY_U)
manager.displayGuiItemRecipe(recipeIngredient.getInternalItemId());
}
});
});
}
private void renderTooltip(GuiChest guiChest, ContainerChest chest) {
int mouseX = Utils.getMouseX();
int mouseY = Utils.getMouseY();
forEachHoveredSlot(guiChest, chest, mouseX, mouseY, (recipeIngredient, slot) -> {
ItemStack actualItem = slot.getStack();
if (actualItem == null && recipeIngredient != null) {
Utils.drawHoveringText(
recipeIngredient.getItemStack().getTooltip(Minecraft.getMinecraft().thePlayer, false),
mouseX, mouseY,
Utils.peekGuiScale().getScaledWidth(), Utils.peekGuiScale().getScaledHeight(), -1
);
}
});
}
private void renderSlots(GuiChest guiChest, ContainerChest chest) {
forEachSlot(chest, (recipeIngredient, slot) -> {
ItemStack actualItem = slot.getStack();
if (actualItem != null && (recipeIngredient == null ||
!recipeIngredient.getInternalItemId().equals(manager.getInternalNameForItem(actualItem)) ||
actualItem.stackSize < recipeIngredient.getCount())) {
drawItemStack(guiChest, slot, actualItem);
}
if (recipeIngredient != null && actualItem == null) {
drawItemStack(guiChest, slot, recipeIngredient.getItemStack());
}
});
}
private void drawItemStack(GuiChest gui, Slot slot, ItemStack item) {
int slotX = slot.xDisplayPosition + ((AccessorGuiContainer) gui).getGuiLeft();
int slotY = slot.yDisplayPosition + ((AccessorGuiContainer) gui).getGuiTop();
Gui.drawRect(slotX, slotY, slotX + 16, slotY + 16, 0x64ff0000);
if (item != null)
Utils.drawItemStack(item, slotX, slotY);
}
}