2022-01-02 23:30:54 +02:00
|
|
|
package codechicken.nei;
|
|
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
import java.awt.Color;
|
2023-09-25 00:35:24 +02:00
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.Arrays;
|
|
|
|
|
import java.util.List;
|
2025-04-24 18:48:40 +03:00
|
|
|
import java.util.Objects;
|
2023-09-25 00:35:24 +02:00
|
|
|
|
2022-05-27 07:42:41 -04:00
|
|
|
import net.minecraft.client.Minecraft;
|
|
|
|
|
import net.minecraft.client.gui.ScaledResolution;
|
2022-01-02 23:30:54 +02:00
|
|
|
import net.minecraft.client.gui.inventory.GuiContainer;
|
2022-05-27 07:42:41 -04:00
|
|
|
import net.minecraft.client.renderer.OpenGlHelper;
|
|
|
|
|
import net.minecraft.client.renderer.Tessellator;
|
|
|
|
|
import net.minecraft.client.shader.Framebuffer;
|
2022-01-02 23:30:54 +02:00
|
|
|
import net.minecraft.item.ItemStack;
|
2023-09-25 00:35:24 +02:00
|
|
|
|
2022-05-27 07:42:41 -04:00
|
|
|
import org.lwjgl.opengl.GL11;
|
2023-09-25 00:34:42 +02:00
|
|
|
|
2023-09-25 00:35:24 +02:00
|
|
|
import codechicken.lib.vec.Rectangle4i;
|
|
|
|
|
import codechicken.nei.api.GuiInfo;
|
|
|
|
|
import codechicken.nei.guihook.GuiContainerManager;
|
2025-08-22 14:58:41 +03:00
|
|
|
import codechicken.nei.recipe.Recipe.RecipeId;
|
2023-09-25 00:35:24 +02:00
|
|
|
import codechicken.nei.recipe.StackInfo;
|
2023-01-28 17:55:51 -08:00
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
public abstract class ItemsGrid<T extends ItemsGrid.ItemsGridSlot, M extends ItemsGrid.MouseContext> {
|
2023-01-28 17:55:51 -08:00
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
protected static class ScreenCapture {
|
2025-01-16 07:23:16 +02:00
|
|
|
|
|
|
|
|
private long nextCacheRefresh = 0;
|
|
|
|
|
private Framebuffer framebuffer;
|
|
|
|
|
|
|
|
|
|
public ScreenCapture() {
|
|
|
|
|
this.framebuffer = new Framebuffer(1, 1, true);
|
|
|
|
|
this.framebuffer.setFramebufferColor(0.0F, 0.0F, 0.0F, 0.0F);
|
|
|
|
|
Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected int getGridRenderingCacheFPS(int mode) {
|
|
|
|
|
return mode == 1 ? NEIClientConfig.getIntSetting("inventory.gridRenderingCacheFPS") : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean needRefresh(int mode) {
|
2025-01-19 19:33:26 +02:00
|
|
|
final Minecraft minecraft = Minecraft.getMinecraft();
|
|
|
|
|
return this.nextCacheRefresh == 0 || this.framebuffer.framebufferWidth != minecraft.displayWidth
|
|
|
|
|
|| framebuffer.framebufferHeight != minecraft.displayHeight
|
2025-01-16 07:23:16 +02:00
|
|
|
|| getGridRenderingCacheFPS(mode) > 0 && this.nextCacheRefresh < System.currentTimeMillis();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void refreshBuffer() {
|
|
|
|
|
this.nextCacheRefresh = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void captureScreen(Runnable callback, int mode) {
|
2025-10-02 12:53:18 +02:00
|
|
|
GL11.glPushAttrib(GL11.GL_ENABLE_BIT | GL11.GL_COLOR_BUFFER_BIT | GL11.GL_LIGHTING_BIT);
|
2025-01-16 07:23:16 +02:00
|
|
|
|
|
|
|
|
resetFramebuffer();
|
|
|
|
|
this.framebuffer.bindFramebuffer(false);
|
|
|
|
|
|
|
|
|
|
/* Set up some rendering state needed for items to work correctly */
|
|
|
|
|
GL11.glDisable(GL11.GL_BLEND);
|
|
|
|
|
GL11.glDepthMask(true);
|
|
|
|
|
OpenGlHelper.glBlendFunc(
|
|
|
|
|
GL11.GL_SRC_ALPHA,
|
|
|
|
|
GL11.GL_ONE_MINUS_SRC_ALPHA,
|
|
|
|
|
GL11.GL_SRC_ALPHA,
|
|
|
|
|
GL11.GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
|
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
|
|
|
|
|
|
|
|
|
callback.run();
|
|
|
|
|
|
|
|
|
|
GL11.glPopAttrib();
|
|
|
|
|
|
|
|
|
|
Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
|
|
|
|
|
this.nextCacheRefresh = System.currentTimeMillis() + (1000 / Math.max(1, getGridRenderingCacheFPS(mode)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void resetFramebuffer() {
|
|
|
|
|
final Minecraft minecraft = Minecraft.getMinecraft();
|
|
|
|
|
|
|
|
|
|
if (this.framebuffer.framebufferWidth != minecraft.displayWidth
|
|
|
|
|
|| framebuffer.framebufferHeight != minecraft.displayHeight) {
|
|
|
|
|
this.framebuffer.createBindFramebuffer(minecraft.displayWidth, minecraft.displayHeight);
|
|
|
|
|
this.framebuffer.setFramebufferFilter(GL11.GL_NEAREST);
|
|
|
|
|
} else {
|
|
|
|
|
this.framebuffer.framebufferClear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void renderCapturedScreen() {
|
|
|
|
|
this.framebuffer.bindFramebufferTexture();
|
|
|
|
|
|
|
|
|
|
final Tessellator tessellator = Tessellator.instance;
|
|
|
|
|
final Minecraft minecraft = Minecraft.getMinecraft();
|
|
|
|
|
final ScaledResolution scaledresolution = new ScaledResolution(
|
|
|
|
|
minecraft,
|
|
|
|
|
minecraft.displayWidth,
|
|
|
|
|
minecraft.displayHeight);
|
|
|
|
|
|
|
|
|
|
/* Set up some rendering state needed for items to work correctly */
|
|
|
|
|
GL11.glEnable(GL11.GL_BLEND);
|
|
|
|
|
OpenGlHelper
|
|
|
|
|
.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
|
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
|
|
|
|
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
|
|
|
|
|
|
|
|
|
tessellator.startDrawingQuads();
|
|
|
|
|
|
|
|
|
|
tessellator.addVertexWithUV(0, scaledresolution.getScaledHeight_double(), 0.0, 0, 0);
|
|
|
|
|
tessellator.addVertexWithUV(
|
|
|
|
|
scaledresolution.getScaledWidth_double(),
|
|
|
|
|
scaledresolution.getScaledHeight_double(),
|
|
|
|
|
0.0,
|
|
|
|
|
1,
|
|
|
|
|
0);
|
|
|
|
|
tessellator.addVertexWithUV(scaledresolution.getScaledWidth_double(), 0, 0.0, 1, 1);
|
|
|
|
|
tessellator.addVertexWithUV(0, 0, 0, 0, 1);
|
|
|
|
|
|
|
|
|
|
tessellator.draw();
|
|
|
|
|
|
|
|
|
|
this.framebuffer.unbindFramebufferTexture();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
public static class ItemsGridSlot {
|
|
|
|
|
|
|
|
|
|
protected static final float DEFAULT_SLOT_SIZE = 18f;
|
|
|
|
|
protected static final float LINE_WIDTH = 0.75f;
|
|
|
|
|
|
|
|
|
|
public final ItemStack item;
|
|
|
|
|
public final int slotIndex;
|
|
|
|
|
public final int itemIndex;
|
|
|
|
|
|
|
|
|
|
public Color borderColor = Color.BLACK;
|
|
|
|
|
|
|
|
|
|
public boolean borderLeft = false;
|
|
|
|
|
public boolean borderTop = false;
|
|
|
|
|
public boolean borderRight = false;
|
|
|
|
|
public boolean borderBottom = false;
|
|
|
|
|
|
|
|
|
|
public ItemsGridSlot(int slotIndex, int itemIndex, ItemStack itemStack) {
|
|
|
|
|
this.slotIndex = slotIndex;
|
|
|
|
|
this.itemIndex = itemIndex;
|
|
|
|
|
this.item = itemStack;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ItemStack getItemStack() {
|
|
|
|
|
return this.item;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public <M extends MouseContext> void beforeDraw(Rectangle4i rect, M mouseContext) {
|
|
|
|
|
if (mouseContext != null && mouseContext.slotIndex == this.slotIndex) {
|
|
|
|
|
NEIClientUtils.drawRect(rect.x, rect.y, rect.w, rect.h, HIGHLIGHT_COLOR);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public <M extends MouseContext> void afterDraw(Rectangle4i rect, M mouseContext) {}
|
|
|
|
|
|
2025-08-22 14:58:41 +03:00
|
|
|
public RecipeId getRecipeId() {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
public void drawItem(Rectangle4i rect) {
|
|
|
|
|
drawItem(getItemStack(), rect);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void drawItem(ItemStack stack, Rectangle4i rect) {
|
|
|
|
|
|
|
|
|
|
if (rect.w != DEFAULT_SLOT_SIZE) {
|
|
|
|
|
final float panelFactor = (rect.w - 2) / (DEFAULT_SLOT_SIZE - 2);
|
|
|
|
|
GL11.glTranslatef(rect.x + 1, rect.y + 1, 0);
|
|
|
|
|
GL11.glScaled(panelFactor, panelFactor, 1);
|
|
|
|
|
|
|
|
|
|
GuiContainerManager.drawItem(0, 0, stack, true, "");
|
|
|
|
|
|
|
|
|
|
GL11.glScaled(1f / panelFactor, 1f / panelFactor, 1);
|
|
|
|
|
GL11.glTranslatef(-1 * (rect.x + 1), -1 * (rect.y + 1), 0);
|
|
|
|
|
} else {
|
|
|
|
|
GuiContainerManager.drawItem(rect.x + 1, rect.y + 1, stack, true, "");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void drawBorder(Rectangle4i rect) {
|
|
|
|
|
float halfLineWidth = LINE_WIDTH / 2f;
|
|
|
|
|
|
|
|
|
|
if (this.borderLeft) {
|
|
|
|
|
NEIClientUtils
|
|
|
|
|
.drawRect(rect.x - halfLineWidth, rect.y + halfLineWidth, LINE_WIDTH, rect.h, this.borderColor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.borderRight) {
|
|
|
|
|
NEIClientUtils.drawRect(
|
|
|
|
|
rect.x + rect.w - halfLineWidth,
|
|
|
|
|
rect.y - halfLineWidth,
|
|
|
|
|
LINE_WIDTH,
|
|
|
|
|
rect.h,
|
|
|
|
|
this.borderColor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.borderTop) {
|
|
|
|
|
NEIClientUtils
|
|
|
|
|
.drawRect(rect.x - halfLineWidth, rect.y - halfLineWidth, rect.w, LINE_WIDTH, this.borderColor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.borderBottom) {
|
|
|
|
|
NEIClientUtils.drawRect(
|
|
|
|
|
rect.x + halfLineWidth,
|
|
|
|
|
rect.y + rect.h - halfLineWidth,
|
|
|
|
|
rect.w,
|
|
|
|
|
LINE_WIDTH,
|
|
|
|
|
this.borderColor);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static class MouseContext {
|
|
|
|
|
|
|
|
|
|
public final int slotIndex;
|
|
|
|
|
public final int columnIndex;
|
|
|
|
|
public final int rowIndex;
|
|
|
|
|
|
|
|
|
|
public MouseContext(int slotIndex, int rowIndex, int columnIndex) {
|
|
|
|
|
this.slotIndex = slotIndex;
|
|
|
|
|
this.rowIndex = rowIndex;
|
|
|
|
|
this.columnIndex = columnIndex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public int hashCode() {
|
|
|
|
|
return Objects.hash(this.rowIndex, this.slotIndex, this.columnIndex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean equals(Object obj) {
|
|
|
|
|
|
|
|
|
|
if (obj instanceof MouseContext context) {
|
|
|
|
|
return this.columnIndex == context.columnIndex && this.rowIndex == context.rowIndex
|
|
|
|
|
&& this.slotIndex == context.slotIndex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int SLOT_SIZE = 18;
|
|
|
|
|
public static final Color HIGHLIGHT_COLOR = new Color(0xee555555, true);
|
2022-01-02 23:30:54 +02:00
|
|
|
|
|
|
|
|
protected int width;
|
|
|
|
|
protected int height;
|
|
|
|
|
|
|
|
|
|
protected int marginLeft;
|
|
|
|
|
protected int marginTop;
|
|
|
|
|
|
2022-05-06 22:41:45 +03:00
|
|
|
protected int paddingLeft;
|
|
|
|
|
|
2022-10-13 11:06:08 +03:00
|
|
|
protected ArrayList<ItemStack> realItems = new ArrayList<>();
|
2022-01-02 23:30:54 +02:00
|
|
|
|
|
|
|
|
protected int page;
|
|
|
|
|
protected int perPage;
|
|
|
|
|
|
|
|
|
|
protected int rows;
|
|
|
|
|
protected int columns;
|
|
|
|
|
|
|
|
|
|
protected boolean[] invalidSlotMap;
|
|
|
|
|
|
2025-01-16 07:23:16 +02:00
|
|
|
protected ScreenCapture screenCapture = null;
|
2022-05-27 07:42:41 -04:00
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
public ArrayList<ItemStack> getItems() {
|
2022-10-13 11:06:08 +03:00
|
|
|
return realItems;
|
2022-01-02 23:30:54 +02:00
|
|
|
}
|
|
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
public ItemStack getItem(int itemIndex) {
|
|
|
|
|
return realItems.get(itemIndex);
|
2022-01-02 23:30:54 +02:00
|
|
|
}
|
|
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
public int size() {
|
2022-01-02 23:30:54 +02:00
|
|
|
return realItems.size();
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-09 09:53:27 +02:00
|
|
|
public boolean isEmpty() {
|
|
|
|
|
return realItems.isEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
public int indexOf(ItemStack stackA, boolean useNBT) {
|
2022-01-02 23:30:54 +02:00
|
|
|
|
|
|
|
|
for (int idx = 0; idx < realItems.size(); idx++) {
|
2024-02-04 14:09:24 +02:00
|
|
|
if (StackInfo.equalItemAndNBT(stackA, realItems.get(idx), useNBT)) {
|
2022-01-02 23:30:54 +02:00
|
|
|
return idx;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-23 17:59:29 +08:00
|
|
|
public void setPage(int page) {
|
|
|
|
|
this.page = Math.max(0, Math.min(page, getNumPages() - 1));
|
|
|
|
|
onGridChanged();
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
public int getPage() {
|
2022-01-02 23:30:54 +02:00
|
|
|
return page + 1;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
public int getPerPage() {
|
2022-01-02 23:30:54 +02:00
|
|
|
return perPage;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
public int getNumPages() {
|
2022-06-23 01:03:29 +03:00
|
|
|
if (perPage > 0) {
|
|
|
|
|
return (int) Math.ceil((float) realItems.size() / (float) perPage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
2022-01-02 23:30:54 +02:00
|
|
|
}
|
|
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
public int getRows() {
|
2022-01-02 23:30:54 +02:00
|
|
|
return rows;
|
|
|
|
|
}
|
2022-06-24 12:32:13 +01:00
|
|
|
|
|
|
|
|
public int getColumns() {
|
2022-01-02 23:30:54 +02:00
|
|
|
return columns;
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-04 14:09:24 +02:00
|
|
|
public int getLastRowIndex() {
|
2025-04-24 18:48:40 +03:00
|
|
|
final List<T> mask = getMask();
|
|
|
|
|
|
|
|
|
|
return this.columns > 0 && !mask.isEmpty()
|
|
|
|
|
? (int) Math.ceil((float) (mask.get(mask.size() - 1).slotIndex + 1) / this.columns) - 1
|
|
|
|
|
: 0;
|
2024-02-04 14:09:24 +02:00
|
|
|
}
|
|
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
public void setGridSize(int mleft, int mtop, int w, int h) {
|
2022-02-17 09:28:48 +02:00
|
|
|
marginLeft = mleft;
|
|
|
|
|
marginTop = mtop;
|
2022-01-02 23:30:54 +02:00
|
|
|
|
2022-02-17 09:28:48 +02:00
|
|
|
width = Math.max(0, w);
|
|
|
|
|
height = Math.max(0, h);
|
2022-01-02 23:30:54 +02:00
|
|
|
|
2022-02-17 09:28:48 +02:00
|
|
|
columns = width / SLOT_SIZE;
|
|
|
|
|
rows = height / SLOT_SIZE;
|
2022-01-02 23:30:54 +02:00
|
|
|
|
2022-05-06 22:41:45 +03:00
|
|
|
paddingLeft = (width % SLOT_SIZE) / 2;
|
2022-01-02 23:30:54 +02:00
|
|
|
}
|
|
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
public void shiftPage(int shift) {
|
2022-01-02 23:30:54 +02:00
|
|
|
if (perPage == 0) {
|
|
|
|
|
page = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-23 01:03:29 +03:00
|
|
|
final int numPages = getNumPages();
|
|
|
|
|
final int oldPage = page;
|
2022-01-02 23:30:54 +02:00
|
|
|
page += shift;
|
|
|
|
|
|
|
|
|
|
if (page >= numPages) {
|
|
|
|
|
page = page - numPages;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (page < 0) {
|
|
|
|
|
page = numPages + page;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
page = Math.max(0, Math.min(page, numPages - 1));
|
2022-06-23 01:03:29 +03:00
|
|
|
|
|
|
|
|
if (page != oldPage) {
|
|
|
|
|
onGridChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
protected void onGridChanged() {
|
2025-01-16 07:23:16 +02:00
|
|
|
if (this.screenCapture != null) {
|
|
|
|
|
this.screenCapture.refreshBuffer();
|
|
|
|
|
}
|
2022-01-02 23:30:54 +02:00
|
|
|
}
|
|
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
public void onItemsChanged() {
|
2024-02-04 14:09:24 +02:00
|
|
|
onGridChanged();
|
2023-07-10 17:38:07 +01:00
|
|
|
}
|
|
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
public void refresh(GuiContainer gui) {
|
2022-01-02 23:30:54 +02:00
|
|
|
updateGuiOverlapSlots(gui);
|
|
|
|
|
shiftPage(0);
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
protected void updateGuiOverlapSlots(GuiContainer gui) {
|
2022-06-23 01:03:29 +03:00
|
|
|
final boolean[] oldSlotMap = invalidSlotMap;
|
|
|
|
|
final int oldRows = rows;
|
|
|
|
|
final int oldColumns = columns;
|
|
|
|
|
|
2022-01-02 23:30:54 +02:00
|
|
|
invalidSlotMap = new boolean[rows * columns];
|
|
|
|
|
perPage = columns * rows;
|
|
|
|
|
|
2024-07-26 18:44:54 +03:00
|
|
|
if (gui != null) {
|
|
|
|
|
if (NEIClientConfig.optimizeGuiOverlapComputation()) {
|
|
|
|
|
checkGuiOverlap(gui, 0, columns - 2, 1);
|
|
|
|
|
checkGuiOverlap(gui, columns - 1, 1, -1);
|
|
|
|
|
} else {
|
|
|
|
|
checkGuiOverlap(gui, 0, columns, 1);
|
|
|
|
|
}
|
2022-10-18 03:59:14 +09:00
|
|
|
}
|
2022-06-23 01:03:29 +03:00
|
|
|
|
|
|
|
|
if (oldRows != rows || oldColumns != columns || !Arrays.equals(oldSlotMap, invalidSlotMap)) {
|
|
|
|
|
onGridChanged();
|
2022-05-27 07:42:41 -04:00
|
|
|
}
|
2022-01-02 23:30:54 +02:00
|
|
|
}
|
|
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
private void checkGuiOverlap(GuiContainer gui, int start, int end, int dir) {
|
2022-01-02 23:30:54 +02:00
|
|
|
boolean validColumn = false;
|
|
|
|
|
|
2022-10-18 03:59:14 +09:00
|
|
|
for (int c = start; c != end && (!NEIClientConfig.optimizeGuiOverlapComputation() || !validColumn); c += dir) {
|
2022-01-02 23:30:54 +02:00
|
|
|
validColumn = true;
|
|
|
|
|
|
|
|
|
|
for (int r = 0; r < rows; r++) {
|
2022-01-04 21:46:46 -08:00
|
|
|
final int idx = columns * r + c;
|
2024-02-04 14:09:24 +02:00
|
|
|
if (idx >= 0 && idx < invalidSlotMap.length
|
|
|
|
|
&& !invalidSlotMap[idx]
|
|
|
|
|
&& GuiInfo.hideItemPanelSlot(gui, getSlotRect(r, c))) {
|
2022-01-04 21:46:46 -08:00
|
|
|
invalidSlotMap[idx] = true;
|
2022-01-02 23:30:54 +02:00
|
|
|
validColumn = false;
|
|
|
|
|
perPage--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
public T getSlotMouseOver(int mousex, int mousey) {
|
|
|
|
|
if (!contains(mousex, mousey)) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final int overRow = getRowIndex(mousey);
|
|
|
|
|
final int overColumn = getColumnIndex(mousex);
|
|
|
|
|
final int slt = columns * overRow + overColumn;
|
2022-08-19 15:03:42 +03:00
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
if (overRow >= rows || overColumn >= columns) {
|
|
|
|
|
return null;
|
2022-08-19 15:03:42 +03:00
|
|
|
}
|
|
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
return getSlotBySlotIndex(slt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public T getSlotBySlotIndex(int slotIndex) {
|
|
|
|
|
return getMask().stream().filter(item -> item.slotIndex == slotIndex).findAny().orElse(null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public T getSlotByItemIndex(int itemIndex) {
|
|
|
|
|
return getMask().stream().filter(item -> item.itemIndex == itemIndex).findAny().orElse(null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Rectangle4i getItemRect(int itemIndex) {
|
|
|
|
|
final T item = getSlotByItemIndex(itemIndex);
|
|
|
|
|
return item != null ? getSlotRect(item.slotIndex) : null;
|
2022-08-19 15:03:42 +03:00
|
|
|
}
|
|
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
public Rectangle4i getSlotRect(int slotIndex) {
|
|
|
|
|
return getSlotRect(slotIndex / columns, slotIndex % columns);
|
2022-01-02 23:30:54 +02:00
|
|
|
}
|
|
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
public Rectangle4i getSlotRect(int row, int column) {
|
|
|
|
|
return new Rectangle4i(
|
|
|
|
|
marginLeft + paddingLeft + column * SLOT_SIZE,
|
|
|
|
|
marginTop + row * SLOT_SIZE,
|
|
|
|
|
SLOT_SIZE,
|
|
|
|
|
SLOT_SIZE);
|
2022-01-02 23:30:54 +02:00
|
|
|
}
|
|
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
public int getRowIndex(int mousey) {
|
|
|
|
|
return (mousey - this.marginTop) / SLOT_SIZE;
|
2022-01-02 23:30:54 +02:00
|
|
|
}
|
|
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
public int getColumnIndex(int mousex) {
|
|
|
|
|
return (mousex - this.marginLeft - this.paddingLeft) / SLOT_SIZE;
|
|
|
|
|
}
|
2023-07-10 17:38:07 +01:00
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
public boolean isInvalidSlot(int index) {
|
|
|
|
|
return invalidSlotMap[index];
|
2023-07-10 17:38:07 +01:00
|
|
|
}
|
|
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
public abstract List<T> getMask();
|
2023-07-16 09:00:35 +01:00
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
protected abstract M getMouseContext(int mousex, int mousey);
|
2023-07-10 17:38:07 +01:00
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
protected void beforeDrawItems(int mousex, int mousey, M mouseContext) {
|
|
|
|
|
for (T item : getMask()) {
|
|
|
|
|
item.beforeDraw(getSlotRect(item.slotIndex), mouseContext);
|
2023-07-10 17:38:07 +01:00
|
|
|
}
|
2025-04-24 18:48:40 +03:00
|
|
|
for (T item : getMask()) {
|
|
|
|
|
item.drawBorder(getSlotRect(item.slotIndex));
|
2023-07-10 17:38:07 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
protected void afterDrawItems(int mousex, int mousey, M mouseContext) {
|
|
|
|
|
for (T item : getMask()) {
|
|
|
|
|
item.afterDraw(getSlotRect(item.slotIndex), mouseContext);
|
2022-06-23 01:03:29 +03:00
|
|
|
}
|
2022-05-27 07:42:41 -04:00
|
|
|
}
|
|
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
public void update() {}
|
2024-02-04 14:09:24 +02:00
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
protected void drawItems() {
|
2022-08-19 15:03:42 +03:00
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
for (T item : getMask()) {
|
|
|
|
|
item.drawItem(getSlotRect(item.slotIndex));
|
2022-08-19 15:03:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-16 07:23:16 +02:00
|
|
|
protected int getGridRenderingCacheMode() {
|
|
|
|
|
return NEIClientConfig.getGridRenderingCacheMode();
|
2024-02-04 14:09:24 +02:00
|
|
|
}
|
|
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
public void draw(int mousex, int mousey) {
|
2022-01-02 23:30:54 +02:00
|
|
|
if (getPerPage() == 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-16 07:23:16 +02:00
|
|
|
final int gridRenderingCacheMode = getGridRenderingCacheMode();
|
2025-04-24 18:48:40 +03:00
|
|
|
final M mouseContext = getMouseContext(mousex, mousey);
|
2025-01-16 07:23:16 +02:00
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
beforeDrawItems(mousex, mousey, mouseContext);
|
2025-01-16 07:23:16 +02:00
|
|
|
|
|
|
|
|
if (gridRenderingCacheMode > 0) {
|
|
|
|
|
|
|
|
|
|
if (this.screenCapture == null) {
|
|
|
|
|
this.screenCapture = new ScreenCapture();
|
|
|
|
|
}
|
2024-02-04 14:09:24 +02:00
|
|
|
|
2025-01-16 07:23:16 +02:00
|
|
|
if (this.screenCapture.needRefresh(gridRenderingCacheMode)) {
|
2025-04-24 18:48:40 +03:00
|
|
|
this.screenCapture.captureScreen(() -> {
|
|
|
|
|
GuiContainerManager.enableMatrixStackLogging();
|
|
|
|
|
drawItems();
|
|
|
|
|
GuiContainerManager.disableMatrixStackLogging();
|
|
|
|
|
}, gridRenderingCacheMode);
|
2022-01-02 23:30:54 +02:00
|
|
|
}
|
|
|
|
|
|
2025-01-16 07:23:16 +02:00
|
|
|
this.screenCapture.renderCapturedScreen();
|
2022-08-19 15:03:42 +03:00
|
|
|
} else {
|
2025-04-24 18:48:40 +03:00
|
|
|
GuiContainerManager.enableMatrixStackLogging();
|
2022-08-19 15:03:42 +03:00
|
|
|
drawItems();
|
2025-04-24 18:48:40 +03:00
|
|
|
GuiContainerManager.disableMatrixStackLogging();
|
2022-01-02 23:30:54 +02:00
|
|
|
}
|
|
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
afterDrawItems(mousex, mousey, mouseContext);
|
2023-07-10 17:38:07 +01:00
|
|
|
}
|
|
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
public boolean contains(int px, int py) {
|
2024-02-04 14:09:24 +02:00
|
|
|
final Rectangle4i rect = new Rectangle4i(
|
|
|
|
|
marginLeft + paddingLeft,
|
|
|
|
|
marginTop,
|
|
|
|
|
columns * SLOT_SIZE,
|
|
|
|
|
rows * SLOT_SIZE);
|
2022-01-02 23:30:54 +02:00
|
|
|
|
2024-02-04 14:09:24 +02:00
|
|
|
if (!rect.contains(px, py)) {
|
2022-01-02 23:30:54 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
return !isInvalidSlot(columns * getRowIndex(py) + getColumnIndex(px));
|
2022-01-02 23:30:54 +02:00
|
|
|
}
|
2022-08-31 17:43:22 +09:00
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
}
|