mirror of
https://github.com/GTNewHorizons/NotEnoughItems.git
synced 2026-11-13 17:04:03 +00:00
* Add Drag&Drop (sorting items) in bookmarks * save recipes in bookmarks * Add possibility to extend bookmarks save/restore functions; in future supports GT++ fluids * change items sorting algorithm * add NBT support for different bookmarks * change saving recipe algorithm * save correct number type in bookmarks.ini Co-authored-by: Serghei Borovetchi <sborovetchi@estatim.com>
711 lines
26 KiB
Java
711 lines
26 KiB
Java
package codechicken.nei.recipe;
|
|
|
|
import codechicken.lib.gui.GuiDraw;
|
|
import codechicken.nei.GuiNEIButton;
|
|
import codechicken.nei.LayoutManager;
|
|
import codechicken.nei.NEIClientConfig;
|
|
import codechicken.nei.NEIClientUtils;
|
|
import codechicken.nei.PositionedStack;
|
|
import codechicken.nei.VisiblityData;
|
|
import codechicken.nei.api.IGuiContainerOverlay;
|
|
import codechicken.nei.api.INEIGuiHandler;
|
|
import codechicken.nei.api.IOverlayHandler;
|
|
import codechicken.nei.api.IRecipeOverlayRenderer;
|
|
import codechicken.nei.api.TaggedInventoryArea;
|
|
import codechicken.nei.drawable.DrawableBuilder;
|
|
import codechicken.nei.drawable.DrawableResource;
|
|
import codechicken.nei.guihook.GuiContainerManager;
|
|
import codechicken.nei.guihook.IContainerTooltipHandler;
|
|
import codechicken.nei.guihook.IGuiClientSide;
|
|
import codechicken.nei.guihook.IGuiHandleMouseWheel;
|
|
import codechicken.nei.recipe.StackInfo;
|
|
import net.minecraft.client.gui.GuiButton;
|
|
import net.minecraft.client.gui.GuiScreen;
|
|
import net.minecraft.client.gui.inventory.GuiContainer;
|
|
import net.minecraft.client.renderer.OpenGlHelper;
|
|
import net.minecraft.client.renderer.RenderHelper;
|
|
import net.minecraft.nbt.NBTTagCompound;
|
|
import net.minecraft.inventory.Slot;
|
|
import net.minecraft.item.ItemStack;
|
|
import net.minecraft.item.Item;
|
|
import org.lwjgl.input.Keyboard;
|
|
import org.lwjgl.opengl.GL11;
|
|
|
|
import java.awt.Point;
|
|
import java.awt.Rectangle;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
import java.util.Optional;
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.IntStream;
|
|
|
|
public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOverlay, IGuiClientSide, IGuiHandleMouseWheel, IContainerTooltipHandler, INEIGuiHandler {
|
|
// Background image calculations
|
|
private static final int BG_TOP_HEIGHT = 6;
|
|
private static final int BG_MIDDLE_HEIGHT = 154;
|
|
private static final int BG_BOTTOM_HEIGHT = 6;
|
|
|
|
private static final int BG_TOP_Y = 0;
|
|
private static final int BG_MIDDLE_Y = BG_TOP_Y + BG_TOP_HEIGHT;
|
|
private static final int BG_BOTTOM_Y = BG_MIDDLE_Y + BG_MIDDLE_HEIGHT;
|
|
|
|
// Button sizes
|
|
private static final int borderPadding = 6;
|
|
private static final int buttonWidth = 13;
|
|
private static final int buttonHeight = 12;
|
|
|
|
// Background image
|
|
final DrawableResource bgTop = new DrawableBuilder("nei:textures/gui/recipebg.png", 0, BG_TOP_Y, 176, BG_TOP_HEIGHT).build();
|
|
final DrawableResource bgMiddle = new DrawableBuilder("nei:textures/gui/recipebg.png", 0, BG_MIDDLE_Y, 176, BG_MIDDLE_HEIGHT).build();
|
|
final DrawableResource bgBottom = new DrawableBuilder("nei:textures/gui/recipebg.png", 0, BG_BOTTOM_Y, 176, BG_BOTTOM_HEIGHT).build();
|
|
|
|
public ArrayList<? extends IRecipeHandler> currenthandlers = new ArrayList<>();
|
|
|
|
public int page;
|
|
public int recipetype;
|
|
public ContainerRecipe slotcontainer;
|
|
public GuiContainer firstGui;
|
|
public GuiScreen prevGui;
|
|
public GuiButton nextpage;
|
|
public GuiButton prevpage;
|
|
private GuiButton nexttype;
|
|
private GuiButton prevtype;
|
|
|
|
private int OVERLAY_BUTTON_ID_START = 4;
|
|
private GuiButton[] overlayButtons;
|
|
|
|
private final Rectangle area = new Rectangle();
|
|
private final GuiRecipeTabs recipeTabs;
|
|
private IRecipeHandler handler;
|
|
private HandlerInfo handlerInfo;
|
|
|
|
private int yShift = 0;
|
|
|
|
protected GuiRecipe(GuiScreen prevgui) {
|
|
super(new ContainerRecipe());
|
|
recipeTabs = new GuiRecipeTabs(this);
|
|
slotcontainer = (ContainerRecipe) inventorySlots;
|
|
|
|
this.prevGui = prevgui;
|
|
if(prevgui instanceof GuiContainer)
|
|
this.firstGui = (GuiContainer)prevgui;
|
|
|
|
if (prevgui instanceof IGuiContainerOverlay)
|
|
this.firstGui = ((IGuiContainerOverlay) prevgui).getFirstScreen();
|
|
|
|
}
|
|
|
|
/**
|
|
* Many old mods assumed a fixed NEI window height of {@code 166} pixels. Now that this is no
|
|
* longer the case, their fluid mouseover handling is broken. This helper class fixes these old
|
|
* mods by hacking the {@link #height} property's value so that these old mods' calculations
|
|
* return the correct value for the new height.
|
|
*
|
|
* <p>This class is an {@link AutoCloseable} so that it can be used with try-with-resources,
|
|
* which will ensure that {@link #height} is returned to the correct value afterwards.
|
|
*/
|
|
private class HeightHack implements AutoCloseable {
|
|
private final int trueHeight;
|
|
|
|
private HeightHack() {
|
|
trueHeight = height;
|
|
|
|
if (NEIClientConfig.heightHackHandlers.contains(handler.getHandlerId())) {
|
|
// The old mods use the calculation ((height - 166) / 2) to compute the y-value of
|
|
// the top edge of the NEI window.
|
|
// guiTop is exactly that: the y-value of the top edge of the NEI window.
|
|
// So we set height to be equal to the inverse of this calculation, applied to
|
|
// guiTop, so that old mods get the right result back when they use this calculation.
|
|
height = (2 * guiTop) + 166;
|
|
|
|
// For reference, in case we ever need to modify width as well:
|
|
// the legacy calculation used for width is ((width - 176) / 2), which should
|
|
// evaluate to be equal to guiWidth (the x-value of the left edge of the NEI window).
|
|
// So if we wanted to override width as well, we'd do this:
|
|
// width = (2 * guiWidth) + 176;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void close() {
|
|
height = trueHeight;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
@SuppressWarnings("unchecked")
|
|
public void initGui() {
|
|
xSize = 176;
|
|
ySize = Math.min(Math.max(height - 68, 166), 370);
|
|
super.initGui();
|
|
guiTop = (height - ySize) / 2 + 10;
|
|
currenthandlers = getCurrentRecipeHandlers(); // Probably don't comment me out
|
|
|
|
if(handler == null)
|
|
setRecipePage(recipetype);
|
|
else
|
|
initOverlayButtons();
|
|
|
|
checkYShift();
|
|
|
|
final int rightButtonX = guiLeft + xSize - borderPadding - buttonWidth;
|
|
final int leftButtonX = guiLeft + borderPadding;
|
|
|
|
nexttype = new GuiNEIButton(0, leftButtonX, guiTop + 3, buttonWidth, buttonHeight, "<");
|
|
prevtype = new GuiNEIButton(1, rightButtonX, guiTop + 3, buttonWidth, buttonHeight, ">");
|
|
|
|
nextpage = new GuiNEIButton(2, leftButtonX, guiTop + 17, buttonWidth, buttonHeight, "<");
|
|
prevpage = new GuiNEIButton(3, rightButtonX, guiTop + 17, buttonWidth, buttonHeight, ">");
|
|
|
|
buttonList.addAll(Arrays.asList(nexttype, prevtype, nextpage, prevpage));
|
|
|
|
if (currenthandlers.size() == 1) {
|
|
nexttype.visible = false;
|
|
prevtype.visible = false;
|
|
}
|
|
|
|
recipeTabs.initLayout();
|
|
refreshPage();
|
|
}
|
|
|
|
@SuppressWarnings("unchecked")
|
|
private void initOverlayButtons() {
|
|
if (overlayButtons != null) {
|
|
buttonList.removeIf(Arrays.asList(overlayButtons)::contains);
|
|
}
|
|
|
|
final int recipesPerPage = getRecipesPerPage();
|
|
overlayButtons = new GuiButton[recipesPerPage];
|
|
for (int i = 0 ; i < recipesPerPage ; i++) {
|
|
overlayButtons[i] = new GuiNEIButton(
|
|
OVERLAY_BUTTON_ID_START + i,
|
|
(width / 2) + 65,
|
|
guiTop + 16 + (handlerInfo.getHeight() * (i+1)) - 2,
|
|
buttonWidth,
|
|
buttonHeight,
|
|
"?");
|
|
}
|
|
Collections.addAll(buttonList, overlayButtons);
|
|
itemPresenceCacheRecipe = -1;
|
|
|
|
}
|
|
|
|
private void checkYShift() {
|
|
yShift = handlerInfo == null ? 0 : handlerInfo.getYShift();
|
|
}
|
|
|
|
public void setRecipePage(int idx) {
|
|
setRecipePage(idx, 0);
|
|
}
|
|
|
|
public void setRecipePage(int idx, int position) {
|
|
recipetype = idx;
|
|
if (recipetype < 0) recipetype = currenthandlers.size() - 1;
|
|
else if (recipetype >= currenthandlers.size()) recipetype = 0;
|
|
|
|
handler = currenthandlers.get(recipetype);
|
|
handlerInfo = getHandlerInfo(handler);
|
|
page = Math.min(Math.max(0, position), handler.numRecipes() - 1) / getRecipesPerPage();
|
|
recipeTabs.calcPageNumber();
|
|
checkYShift();
|
|
initOverlayButtons();
|
|
}
|
|
|
|
public void openTargetRecipe(BookmarkRecipeId recipeId)
|
|
{
|
|
|
|
if (recipeId == null) {
|
|
return;
|
|
}
|
|
|
|
if (recipeId.recipetype == -1 || recipeId.position == -1) {
|
|
recipeId.recipetype = 0;
|
|
recipeId.position = 0;
|
|
|
|
if (recipeId.handlerName != null) {
|
|
|
|
for (int j = 0; j < currenthandlers.size(); j++) {
|
|
IRecipeHandler localHandler = currenthandlers.get(j);
|
|
HandlerInfo localHandlerInfo = getHandlerInfo(localHandler);
|
|
|
|
if (localHandlerInfo.getHandlerName().equals(recipeId.handlerName)) {
|
|
recipeId.recipetype = j;
|
|
|
|
if (!recipeId.ingredients.isEmpty()) {
|
|
for (int i = 0; i < localHandler.numRecipes(); i++) {
|
|
|
|
if (recipeId.equalsIngredients(localHandler.getIngredientStacks(i))) {
|
|
recipeId.position = i;
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
setRecipePage(recipeId.recipetype, recipeId.position);
|
|
}
|
|
|
|
public BookmarkRecipeId getFocusedRecipeId()
|
|
{
|
|
String handlerName = handlerInfo.getHandlerName();
|
|
Point mousePos = GuiDraw.getMousePosition();
|
|
int recipesPerPage = getRecipesPerPage();
|
|
|
|
for (int i = page * recipesPerPage; i < handler.numRecipes() && i < (page + 1) * recipesPerPage; i++) {
|
|
if (recipeInFocus(i)) {
|
|
return new BookmarkRecipeId(handlerName, handler.getIngredientStacks(i), recipetype, i);
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
protected Boolean recipeInFocus(int idx)
|
|
{
|
|
PositionedStack result = handler.getResultStack(idx);
|
|
if (result != null && isMouseOver(result, idx)) {
|
|
return true;
|
|
}
|
|
|
|
List<PositionedStack> stacks = handler.getOtherStacks(idx);
|
|
for (PositionedStack stack : stacks) {
|
|
if (isMouseOver(stack, idx)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public IRecipeHandler getHandler() {
|
|
return handler;
|
|
}
|
|
|
|
public List<Integer> getRecipeIndices() {
|
|
final int recipesPerPage = getRecipesPerPage();
|
|
int minIndex = page * recipesPerPage;
|
|
int maxIndex = Math.min(handler.numRecipes(), (page + 1) * recipesPerPage);
|
|
|
|
return IntStream.range(minIndex, maxIndex).boxed().collect(Collectors.toList());
|
|
}
|
|
|
|
@Override
|
|
public void keyTyped(char c, int i) {
|
|
if (i == Keyboard.KEY_ESCAPE) //esc
|
|
{
|
|
mc.displayGuiScreen(firstGui);
|
|
return;
|
|
}
|
|
if (GuiContainerManager.getManager(this).lastKeyTyped(i, c))
|
|
return;
|
|
|
|
try (HeightHack heightHack = new HeightHack()) {
|
|
for (int recipe : getRecipeIndices())
|
|
if (handler.keyTyped(this, c, i, recipe))
|
|
return;
|
|
}
|
|
|
|
if (i == mc.gameSettings.keyBindInventory.getKeyCode())
|
|
mc.displayGuiScreen(firstGui);
|
|
else if (i == NEIClientConfig.getKeyBinding("gui.back"))
|
|
mc.displayGuiScreen(prevGui);
|
|
else if (i == NEIClientConfig.getKeyBinding("gui.prev_machine"))
|
|
prevType();
|
|
else if (i == NEIClientConfig.getKeyBinding("gui.next_machine"))
|
|
nextType();
|
|
else if (i == NEIClientConfig.getKeyBinding("gui.prev_recipe"))
|
|
prevPage();
|
|
else if (i == NEIClientConfig.getKeyBinding("gui.next_recipe"))
|
|
nextPage();
|
|
|
|
}
|
|
|
|
@Override
|
|
protected void mouseClicked(int x, int y, int button) {
|
|
try (HeightHack heightHack = new HeightHack()) {
|
|
for (int recipe : getRecipeIndices())
|
|
if (handler.mouseClicked(this, button, recipe))
|
|
return;
|
|
}
|
|
|
|
if (recipeTabs.mouseClicked(x, y, button))
|
|
return;
|
|
|
|
super.mouseClicked(x, y, button);
|
|
}
|
|
|
|
@Override
|
|
public void mouseScrolled(int i) {
|
|
// Height hacking is not necessary here since mouse scrolling is a new feature, added in
|
|
// GTNH NEI. So no old mods will use this. Though not hacking the height here does mean that
|
|
// the value of the height field will be different from in other mouseover methods, which
|
|
// could be confusing...
|
|
|
|
for (int recipe : getRecipeIndices())
|
|
if (handler.mouseScrolled(this, i, recipe))
|
|
return;
|
|
|
|
if (new Rectangle(guiLeft, guiTop, xSize, ySize).contains(GuiDraw.getMousePosition())) {
|
|
if (i > 0) prevPage();
|
|
else nextPage();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void actionPerformed(GuiButton guibutton) {
|
|
super.actionPerformed(guibutton);
|
|
switch (guibutton.id) {
|
|
case 0:
|
|
prevType();
|
|
return;
|
|
case 1:
|
|
nextType();
|
|
return;
|
|
case 2:
|
|
prevPage();
|
|
return;
|
|
case 3:
|
|
nextPage();
|
|
return;
|
|
}
|
|
if (overlayButtons != null && guibutton.id >= OVERLAY_BUTTON_ID_START && guibutton.id < OVERLAY_BUTTON_ID_START + overlayButtons.length) {
|
|
overlayRecipe(page * getRecipesPerPage() + guibutton.id - OVERLAY_BUTTON_ID_START);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void updateScreen() {
|
|
super.updateScreen();
|
|
handler.onUpdate();
|
|
refreshPage();
|
|
}
|
|
|
|
@Override
|
|
public List<String> handleTooltip(GuiContainer gui, int mousex, int mousey, List<String> currenttip) {
|
|
try (HeightHack heightHack = new HeightHack()) {
|
|
for (int i : getRecipeIndices())
|
|
currenttip = handler.handleTooltip(this, currenttip, i);
|
|
}
|
|
recipeTabs.handleTooltip(mousex, mousey, currenttip);
|
|
return currenttip;
|
|
}
|
|
|
|
@Override
|
|
public List<String> handleItemTooltip(GuiContainer gui, ItemStack stack, int mousex, int mousey, List<String> currenttip) {
|
|
// Height hacking is probably not needed as it doesn't look like any mods check mouse
|
|
// position for this method.
|
|
for (int i : getRecipeIndices())
|
|
currenttip = handler.handleItemTooltip(this, stack, currenttip, i);
|
|
|
|
return currenttip;
|
|
}
|
|
|
|
@Override
|
|
public List<String> handleItemDisplayName(GuiContainer gui, ItemStack itemstack, List<String> currenttip) {
|
|
return currenttip;
|
|
}
|
|
|
|
private void nextPage() {
|
|
page++;
|
|
if (page > (handler.numRecipes() - 1) / getRecipesPerPage()) page = 0;
|
|
}
|
|
|
|
private void prevPage() {
|
|
page--;
|
|
if (page < 0) page = (handler.numRecipes() - 1) / getRecipesPerPage();
|
|
}
|
|
|
|
private void nextType() {
|
|
setRecipePage(++recipetype);
|
|
}
|
|
|
|
private void prevType() {
|
|
setRecipePage(--recipetype);
|
|
}
|
|
|
|
public HandlerInfo getHandlerInfo(IRecipeHandler handler) {
|
|
final String handlerID;
|
|
if(handler instanceof TemplateRecipeHandler) {
|
|
handlerID = (((TemplateRecipeHandler)handler).getOverlayIdentifier());
|
|
} else {
|
|
handlerID = null;
|
|
}
|
|
HandlerInfo info = GuiRecipeTab.getHandlerInfo(handler.getHandlerId(), handlerID);
|
|
|
|
if (info == null)
|
|
return GuiRecipeTab.DEFAULT_HANDLER_INFO;
|
|
|
|
return info;
|
|
}
|
|
|
|
private void overlayRecipe(int recipe) {
|
|
final IRecipeOverlayRenderer renderer = handler.getOverlayRenderer(firstGui, recipe);
|
|
final IOverlayHandler overlayHandler = handler.getOverlayHandler(firstGui, recipe);
|
|
final boolean shift = NEIClientUtils.shiftKey();
|
|
|
|
if (handler != null && (renderer == null || shift)) {
|
|
mc.displayGuiScreen(firstGui);
|
|
overlayHandler.overlayRecipe(firstGui, currenthandlers.get(recipetype), recipe, shift);
|
|
} else if (renderer != null) {
|
|
mc.displayGuiScreen(firstGui);
|
|
LayoutManager.overlayRenderer = renderer;
|
|
}
|
|
}
|
|
|
|
public void refreshPage() {
|
|
refreshSlots();
|
|
final int recipesPerPage = getRecipesPerPage();
|
|
final boolean multiplepages = handler.numRecipes() > recipesPerPage;
|
|
|
|
final int numRecipes = Math.min(handler.numRecipes() - (page * recipesPerPage), recipesPerPage);
|
|
|
|
area.width = handlerInfo.getWidth();
|
|
area.height = handlerInfo.getHeight() * numRecipes;
|
|
area.x = guiLeft - 2;
|
|
area.y = guiTop - 4 + yShift;
|
|
checkYShift();
|
|
|
|
nextpage.enabled = prevpage.enabled = multiplepages;
|
|
|
|
if(firstGui == null) {
|
|
for (GuiButton overlay : overlayButtons) {
|
|
overlay.visible = false;
|
|
}
|
|
} else {
|
|
for(int i = 0 ; i < overlayButtons.length ; i ++) {
|
|
if (i >= numRecipes) {
|
|
overlayButtons[i].visible = false;
|
|
} else {
|
|
final int curRecipe = page * recipesPerPage + i;
|
|
overlayButtons[i].visible = handler.hasOverlay(firstGui, firstGui.inventorySlots, curRecipe);
|
|
}
|
|
}
|
|
}
|
|
|
|
recipeTabs.refreshPage();
|
|
}
|
|
|
|
private void refreshSlots() {
|
|
slotcontainer.inventorySlots.clear();
|
|
final int recipesPerPage = getRecipesPerPage();
|
|
for (int i = page * recipesPerPage; i < handler.numRecipes() && i < (page + 1) * recipesPerPage; i++) {
|
|
Point p = getRecipePosition(i);
|
|
|
|
List<PositionedStack> stacks = handler.getIngredientStacks(i);
|
|
for (PositionedStack stack : stacks)
|
|
slotcontainer.addSlot(stack, p.x, p.y);
|
|
|
|
stacks = handler.getOtherStacks(i);
|
|
for (PositionedStack stack : stacks)
|
|
slotcontainer.addSlot(stack, p.x, p.y);
|
|
|
|
PositionedStack result = handler.getResultStack(i);
|
|
if (result != null)
|
|
slotcontainer.addSlot(result, p.x, p.y);
|
|
}
|
|
}
|
|
|
|
private int itemPresenceCacheRecipe = -1;
|
|
private ArrayList<Boolean> itemPresenceCacheSlots;
|
|
|
|
private void updateItemPresenceCache(int recipe) {
|
|
if (itemPresenceCacheSlots == null) {
|
|
itemPresenceCacheSlots = new ArrayList<>();
|
|
}
|
|
itemPresenceCacheRecipe = recipe;
|
|
itemPresenceCacheSlots.clear();
|
|
List<PositionedStack> ingredients = handler.getIngredientStacks(recipe);
|
|
ArrayList<ItemStack> invStacks = ((List<Slot>) firstGui.inventorySlots.inventorySlots).stream()
|
|
.filter(s -> s != null && s.getStack() != null && s.getStack().stackSize > 0 && s.isItemValid(s.getStack()) && s.canTakeStack(mc.thePlayer))
|
|
.map(s -> s.getStack().copy())
|
|
.collect(Collectors.toCollection(ArrayList::new));
|
|
for (PositionedStack stack : ingredients) {
|
|
Optional<ItemStack> used = invStacks.stream().filter(is -> is.stackSize > 0 && stack.contains(is)).findFirst();
|
|
itemPresenceCacheSlots.add(used.isPresent());
|
|
if (used.isPresent()) {
|
|
ItemStack is = used.get();
|
|
is.stackSize -= 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
|
|
GuiContainerManager.enable2DRender();
|
|
final int recipesPerPage = getRecipesPerPage();
|
|
String s = handler.getRecipeName().trim();
|
|
fontRendererObj.drawStringWithShadow(s, (xSize - fontRendererObj.getStringWidth(s)) / 2, 5, 0xffffff);
|
|
s = NEIClientUtils.translate("recipe.page", page + 1, (handler.numRecipes() - 1) / recipesPerPage + 1);
|
|
fontRendererObj.drawStringWithShadow(s, (xSize - fontRendererObj.getStringWidth(s)) / 2, 19, 0xffffff);
|
|
final boolean drawItemPresence = NEIClientConfig.isJEIStyleItemPresenceOverlayVisible();
|
|
|
|
GL11.glPushMatrix();
|
|
GL11.glTranslatef(5, 32 + yShift, 0);
|
|
try (HeightHack heightHack = new HeightHack()) {
|
|
for (int i = page * recipesPerPage; i < handler.numRecipes() && i < (page + 1) * recipesPerPage; i++) {
|
|
handler.drawForeground(i);
|
|
if (drawItemPresence && isMouseOverOverlayButton(i - page * recipesPerPage)
|
|
&& firstGui.inventorySlots != null) {
|
|
List<PositionedStack> ingredients = handler.getIngredientStacks(i);
|
|
if (itemPresenceCacheRecipe != i || itemPresenceCacheSlots == null || itemPresenceCacheSlots.size() != ingredients.size()) {
|
|
updateItemPresenceCache(i);
|
|
}
|
|
for (int j = 0; j < ingredients.size(); j++) {
|
|
PositionedStack stack = ingredients.get(j);
|
|
boolean isPresent = itemPresenceCacheSlots.get(j);
|
|
LayoutManager.drawItemPresenceOverlay(stack.relx, stack.rely, isPresent);
|
|
}
|
|
}
|
|
GL11.glTranslatef(0, handlerInfo.getHeight(), 0);
|
|
}
|
|
}
|
|
GL11.glPopMatrix();
|
|
}
|
|
|
|
@Override
|
|
protected void drawGuiContainerBackgroundLayer(float f, int mouseX, int mouseY) {
|
|
final int recipesPerPage = getRecipesPerPage();
|
|
GL11.glColor4f(1, 1, 1, 1);
|
|
final int j = (width - xSize) / 2;
|
|
final int k = guiTop;
|
|
|
|
drawBackgroundTiled(j, k);
|
|
|
|
drawRect(guiLeft + borderPadding + buttonWidth - 1,
|
|
nexttype.yPosition,
|
|
guiLeft + xSize - borderPadding - buttonWidth,
|
|
nexttype.yPosition + buttonHeight,
|
|
0x30000000);
|
|
drawRect(guiLeft + borderPadding + buttonWidth - 1,
|
|
nextpage.yPosition,
|
|
guiLeft + xSize - borderPadding - buttonWidth,
|
|
nextpage.yPosition + buttonHeight,
|
|
0x30000000);
|
|
|
|
if (NEIClientConfig.areJEIStyleTabsVisible()) {
|
|
RenderHelper.enableGUIStandardItemLighting();
|
|
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
|
|
recipeTabs.draw(mouseX, mouseY);
|
|
RenderHelper.disableStandardItemLighting();
|
|
}
|
|
|
|
GL11.glPushMatrix();
|
|
GL11.glTranslatef(j + 5, k + 32 + yShift, 0);
|
|
try (HeightHack heightHack = new HeightHack()) {
|
|
for (int i = page * recipesPerPage; i < handler.numRecipes() && i < (page + 1) * recipesPerPage; i++) {
|
|
handler.drawBackground(i);
|
|
GL11.glTranslatef(0, handlerInfo.getHeight(), 0);
|
|
}
|
|
}
|
|
GL11.glPopMatrix();
|
|
}
|
|
|
|
private void drawBackgroundTiled(int j, int k) {
|
|
// Draw the top
|
|
bgTop.draw(j, k + BG_TOP_Y);
|
|
|
|
// Maybe Tile the middle
|
|
final int tiledHeight = ySize - BG_TOP_HEIGHT - BG_BOTTOM_HEIGHT;
|
|
|
|
if (tiledHeight > 0) {
|
|
final int yTileCount = tiledHeight / BG_MIDDLE_HEIGHT;
|
|
final int yRemainder = tiledHeight - (yTileCount * BG_MIDDLE_HEIGHT);
|
|
final int yStart = k + BG_TOP_HEIGHT + tiledHeight;
|
|
|
|
for (int yTile = 0; yTile <= yTileCount; yTile++) {
|
|
final int tileHeight = (yTile == yTileCount) ? yRemainder : BG_MIDDLE_HEIGHT;
|
|
final int y = yStart - ((yTile + 1) * BG_MIDDLE_HEIGHT);
|
|
if (tileHeight > 0) {
|
|
bgMiddle.draw(j, y, BG_MIDDLE_HEIGHT - tileHeight, 0, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Draw the bottom
|
|
bgBottom.draw(j, k + ySize - BG_BOTTOM_HEIGHT);
|
|
}
|
|
|
|
@Override
|
|
public GuiContainer getFirstScreen() {
|
|
return firstGui;
|
|
}
|
|
|
|
public boolean isMouseOver(PositionedStack stack, int recipe) {
|
|
Slot stackSlot = slotcontainer.getSlotWithStack(stack, getRecipePosition(recipe).x, getRecipePosition(recipe).y);
|
|
Point mousepos = GuiDraw.getMousePosition();
|
|
Slot mouseoverSlot = getSlotAtPosition(mousepos.x, mousepos.y);
|
|
|
|
return stackSlot == mouseoverSlot;
|
|
}
|
|
|
|
private boolean isMouseOverOverlayButton(int buttonId) {
|
|
if(buttonId >= 0 && buttonId < overlayButtons.length) {
|
|
GuiButton button = overlayButtons[buttonId];
|
|
Point mousePos = GuiDraw.getMousePosition();
|
|
return button.visible && mousePos.x >= button.xPosition && mousePos.y >= button.yPosition
|
|
&& mousePos.x < button.xPosition + button.width && mousePos.y < button.yPosition + button.height;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private int getRecipesPerPage() {
|
|
return getRecipesPerPage(handlerInfo);
|
|
}
|
|
|
|
private int getRecipesPerPage(HandlerInfo handlerInfo) {
|
|
if(handlerInfo != null)
|
|
return Math.max(Math.min(((ySize - (buttonHeight*3)) / handlerInfo.getHeight()), handlerInfo.getMaxRecipesPerPage()), 1);
|
|
else
|
|
return (handler.recipiesPerPage());
|
|
}
|
|
|
|
public Point getRecipePosition(int recipe) {
|
|
return new Point(5, 32 + yShift + ((recipe % getRecipesPerPage()) * handlerInfo.getHeight()));
|
|
}
|
|
|
|
public abstract ArrayList<? extends IRecipeHandler> getCurrentRecipeHandlers();
|
|
|
|
@Override
|
|
public VisiblityData modifyVisiblity(GuiContainer gui, VisiblityData currentVisibility)
|
|
{
|
|
return currentVisibility;
|
|
}
|
|
|
|
@Override
|
|
public Iterable<Integer> getItemSpawnSlots(GuiContainer gui, ItemStack item) {
|
|
return Collections.emptyList();
|
|
}
|
|
|
|
|
|
@Override
|
|
public List<TaggedInventoryArea> getInventoryAreas(GuiContainer gui) {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public boolean handleDragNDrop(GuiContainer gui, int mousex, int mousey, ItemStack draggedStack, int button) {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean hideItemPanelSlot(GuiContainer gui, int x, int y, int w, int h) {
|
|
// Because some of the handlers *cough avaritia* are oversized
|
|
Rectangle rect = new Rectangle(area);
|
|
|
|
return rect.contains(x, y, w, h);
|
|
}
|
|
|
|
}
|