mirror of
https://github.com/GTNewHorizons/NotEnoughItems.git
synced 2026-10-26 14:24:07 +00:00
Various CPU and RAM improvements (#1015)
Co-authored-by: Martin Robertz <dream-master@gmx.net>
This commit is contained in:
1 parent
866b796411
commit
3f38e6f39b
9 files changed
+236
-54
No files matched your search
@@ -19,6 +19,7 @@ import org.lwjgl.opengl.GL30;
|
||||
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.api.GuiInfo;
|
||||
import codechicken.nei.api.INEIGuiHandler;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.recipe.Recipe.RecipeId;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
@@ -348,16 +349,24 @@ public abstract class ItemsGrid<T extends ItemsGrid.ItemsGridSlot, M extends Ite
|
||||
}
|
||||
|
||||
public void setGridSize(int mleft, int mtop, int w, int h) {
|
||||
final int newWidth = Math.max(0, w);
|
||||
final int newHeight = Math.max(0, h);
|
||||
final boolean changed = marginLeft != mleft || marginTop != mtop || width != newWidth || height != newHeight;
|
||||
|
||||
marginLeft = mleft;
|
||||
marginTop = mtop;
|
||||
|
||||
width = Math.max(0, w);
|
||||
height = Math.max(0, h);
|
||||
width = newWidth;
|
||||
height = newHeight;
|
||||
|
||||
columns = width / SLOT_SIZE;
|
||||
rows = height / SLOT_SIZE;
|
||||
|
||||
paddingLeft = (width % SLOT_SIZE) / 2;
|
||||
|
||||
if (changed) {
|
||||
onGridChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public void shiftPage(int shift) {
|
||||
@@ -396,7 +405,10 @@ public abstract class ItemsGrid<T extends ItemsGrid.ItemsGridSlot, M extends Ite
|
||||
}
|
||||
|
||||
public void refresh(GuiContainer gui) {
|
||||
updateGuiOverlapSlots(gui);
|
||||
final int gridRenderingCacheMode = getGridRenderingCacheMode();
|
||||
if (gridRenderingCacheMode <= 0 || screenCapture == null || screenCapture.needRefresh(gridRenderingCacheMode)) {
|
||||
updateGuiOverlapSlots(gui);
|
||||
}
|
||||
shiftPage(0);
|
||||
}
|
||||
|
||||
@@ -409,11 +421,12 @@ public abstract class ItemsGrid<T extends ItemsGrid.ItemsGridSlot, M extends Ite
|
||||
perPage = columns * rows;
|
||||
|
||||
if (gui != null) {
|
||||
final INEIGuiHandler[] handlers = GuiInfo.getGuiHandlersSnapshot();
|
||||
if (NEIClientConfig.optimizeGuiOverlapComputation()) {
|
||||
checkGuiOverlap(gui, 0, columns - 2, 1);
|
||||
checkGuiOverlap(gui, columns - 1, 1, -1);
|
||||
checkGuiOverlap(gui, handlers, 0, columns - 2, 1);
|
||||
checkGuiOverlap(gui, handlers, columns - 1, 1, -1);
|
||||
} else {
|
||||
checkGuiOverlap(gui, 0, columns, 1);
|
||||
checkGuiOverlap(gui, handlers, 0, columns, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,7 +435,7 @@ public abstract class ItemsGrid<T extends ItemsGrid.ItemsGridSlot, M extends Ite
|
||||
}
|
||||
}
|
||||
|
||||
private void checkGuiOverlap(GuiContainer gui, int start, int end, int dir) {
|
||||
private void checkGuiOverlap(GuiContainer gui, INEIGuiHandler[] handlers, int start, int end, int dir) {
|
||||
boolean validColumn = false;
|
||||
|
||||
for (int c = start; c != end && (!NEIClientConfig.optimizeGuiOverlapComputation() || !validColumn); c += dir) {
|
||||
@@ -432,7 +445,7 @@ public abstract class ItemsGrid<T extends ItemsGrid.ItemsGridSlot, M extends Ite
|
||||
final int idx = columns * r + c;
|
||||
if (idx >= 0 && idx < invalidSlotMap.length
|
||||
&& !invalidSlotMap[idx]
|
||||
&& GuiInfo.hideItemPanelSlot(gui, getSlotRect(r, c))) {
|
||||
&& GuiInfo.hideItemPanelSlot(gui, getSlotRect(r, c), handlers)) {
|
||||
invalidSlotMap[idx] = true;
|
||||
validColumn = false;
|
||||
perPage--;
|
||||
|
||||
@@ -43,6 +43,7 @@ import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.client.gui.inventory.GuiContainerCreative;
|
||||
import net.minecraft.client.renderer.InventoryEffectRenderer;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
@@ -907,21 +908,37 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
changeTexture("textures/gui/widgets.png");
|
||||
drawTexturedModalRect(x, y, tx1, ty1, w1, h1); // top left
|
||||
drawTexturedModalRect(x, y2, tx1, ty2, w1, h2); // bottom left
|
||||
final Tessellator tessellator = Tessellator.instance;
|
||||
tessellator.startDrawingQuads();
|
||||
addTexturedModalRect(tessellator, x, y, tx1, ty1, w1, h1); // top left
|
||||
addTexturedModalRect(tessellator, x, y2, tx1, ty2, w1, h2); // bottom left
|
||||
|
||||
for (int tile = 0; tile < wTiles; tile++) {
|
||||
final int tileX = x + w1 + 50 * tile;
|
||||
drawTexturedModalRect(tileX, y, tx3, ty1, 50, h1); // top
|
||||
drawTexturedModalRect(tileX, y2, tx3, ty2, 50, h2); // bottom
|
||||
addTexturedModalRect(tessellator, tileX, y, tx3, ty1, 50, h1); // top
|
||||
addTexturedModalRect(tessellator, tileX, y2, tx3, ty2, 50, h2); // bottom
|
||||
}
|
||||
|
||||
drawTexturedModalRect(x2, y, tx2, ty1, w2, h1); // top right
|
||||
drawTexturedModalRect(x2, y2, tx2, ty2, w2, h2); // bottom right
|
||||
addTexturedModalRect(tessellator, x2, y, tx2, ty1, w2, h1); // top right
|
||||
addTexturedModalRect(tessellator, x2, y2, tx2, ty2, w2, h2); // bottom right
|
||||
tessellator.draw();
|
||||
|
||||
if (!is2DTexture) GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
private static void addTexturedModalRect(Tessellator tessellator, int x, int y, int textureX, int textureY,
|
||||
int width, int height) {
|
||||
final double z = GuiDraw.gui.getZLevel();
|
||||
final double u = textureX / 256D;
|
||||
final double v = textureY / 256D;
|
||||
final double maxU = (textureX + width) / 256D;
|
||||
final double maxV = (textureY + height) / 256D;
|
||||
tessellator.addVertexWithUV(x, y + height, z, u, maxV);
|
||||
tessellator.addVertexWithUV(x + width, y + height, z, maxU, maxV);
|
||||
tessellator.addVertexWithUV(x + width, y, z, maxU, v);
|
||||
tessellator.addVertexWithUV(x, y, z, u, v);
|
||||
}
|
||||
|
||||
public static void drawItemPresenceOverlay(int slotX, int slotY, boolean isPresent, boolean slotHighlight) {
|
||||
|
||||
if (slotHighlight) {
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.client.renderer.InventoryEffectRenderer;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.api.INEIGuiAdapter;
|
||||
|
||||
/**
|
||||
@@ -18,35 +14,37 @@ public class NEIPotionGuiHandler extends INEIGuiAdapter {
|
||||
|
||||
@Override
|
||||
public boolean hideItemPanelSlot(GuiContainer guiContainer, int slotX, int slotY, int slotW, int slotH) {
|
||||
if (NEIClientConfig.ignorePotionOverlap()) {
|
||||
if (!(guiContainer instanceof InventoryEffectRenderer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (guiContainer instanceof InventoryEffectRenderer) {
|
||||
int x = guiContainer.guiLeft - 124;
|
||||
int y = guiContainer.guiTop;
|
||||
Minecraft minecraft = guiContainer.mc;
|
||||
if (minecraft == null) {
|
||||
return false;
|
||||
}
|
||||
EntityPlayerSP player = minecraft.thePlayer;
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
Collection<PotionEffect> activePotionEffects = player.getActivePotionEffects();
|
||||
if (activePotionEffects.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
int height = 33;
|
||||
if (activePotionEffects.size() > 5) {
|
||||
height = 132 / (activePotionEffects.size() - 1);
|
||||
}
|
||||
Rectangle4i slotRect = new Rectangle4i(slotX, slotY, slotW, slotH);
|
||||
for (PotionEffect potioneffect : activePotionEffects) {
|
||||
Rectangle4i box = new Rectangle4i(x, y, 140, 32);
|
||||
if (box.intersects(slotRect)) return true;
|
||||
y += height;
|
||||
}
|
||||
int x = guiContainer.guiLeft - 124;
|
||||
if (slotX + slotW <= x || slotX >= x + 140) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Minecraft minecraft = guiContainer.mc;
|
||||
if (minecraft == null) {
|
||||
return false;
|
||||
}
|
||||
EntityPlayerSP player = minecraft.thePlayer;
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
int potionCount = player.getActivePotionEffects().size();
|
||||
if (potionCount == 0 || NEIClientConfig.ignorePotionOverlap()) {
|
||||
return false;
|
||||
}
|
||||
int height = 33;
|
||||
if (potionCount > 5) {
|
||||
height = 132 / (potionCount - 1);
|
||||
}
|
||||
return intersectsPotionEffects(slotY, slotH, guiContainer.guiTop, potionCount, height);
|
||||
}
|
||||
|
||||
static boolean intersectsPotionEffects(int slotY, int slotH, int effectY, int potionCount, int height) {
|
||||
for (int i = 0; i < potionCount; i++, effectY += height) {
|
||||
if (slotY + slotH > effectY && slotY < effectY + 32) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -51,20 +51,29 @@ public class GuiInfo {
|
||||
}
|
||||
|
||||
public static boolean hideItemPanelSlot(GuiContainer gui, Rectangle4i rect) {
|
||||
return hideItemPanelSlot(gui, rect, getGuiHandlersSnapshot());
|
||||
}
|
||||
|
||||
public static INEIGuiHandler[] getGuiHandlersSnapshot() {
|
||||
try {
|
||||
readLock.lock();
|
||||
if (guiHandlers.stream()
|
||||
.anyMatch(handler -> handler.hideItemPanelSlot(gui, rect.x, rect.y, rect.w, rect.h))) {
|
||||
return true;
|
||||
}
|
||||
return guiHandlers.toArray(new INEIGuiHandler[0]);
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hideItemPanelSlot(GuiContainer gui, Rectangle4i rect, INEIGuiHandler[] handlers) {
|
||||
for (INEIGuiHandler handler : handlers) {
|
||||
if (handler.hideItemPanelSlot(gui, rect.x, rect.y, rect.w, rect.h)) return true;
|
||||
}
|
||||
|
||||
for (Object item : gui.buttonList) {
|
||||
GuiButton button = (GuiButton) item;
|
||||
|
||||
if ((new Rectangle4i(button.xPosition, button.yPosition, button.width, button.height)).intersects(rect)) {
|
||||
if (button.xPosition + button.width > rect.x && button.xPosition < rect.x + rect.w
|
||||
&& button.yPosition + button.height > rect.y
|
||||
&& button.yPosition < rect.y + rect.h) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,7 +314,7 @@ public class GuiContainerManager {
|
||||
}
|
||||
|
||||
private static int modelviewDepth = -1;
|
||||
private static boolean contextEnabled = false;
|
||||
private static int contextDepth = 0;
|
||||
private static final ItemStackSet renderingErrorItems = new ItemStackSet();
|
||||
|
||||
public static void drawItem(int offsetX, int offsetY, ItemStack itemstack, FontRenderer fontRenderer,
|
||||
@@ -411,16 +411,15 @@ public class GuiContainerManager {
|
||||
}
|
||||
|
||||
public static void enableMatrixStackLogging() {
|
||||
if (!contextEnabled) {
|
||||
if (contextDepth == 0) {
|
||||
GL11.glPushAttrib(GL11.GL_ENABLE_BIT | GL11.GL_COLOR_BUFFER_BIT | GL11.GL_LIGHTING_BIT);
|
||||
modelviewDepth = GL11.glGetInteger(GL11.GL_MODELVIEW_STACK_DEPTH);
|
||||
contextEnabled = true;
|
||||
}
|
||||
contextDepth++;
|
||||
}
|
||||
|
||||
public static void disableMatrixStackLogging() {
|
||||
if (contextEnabled) {
|
||||
contextEnabled = false;
|
||||
if (contextDepth > 0 && --contextDepth == 0) {
|
||||
modelviewDepth = -1;
|
||||
GL11.glPopAttrib();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class ItemsGridTest {
|
||||
|
||||
@Test
|
||||
void synchronizesOverlapAndCaptureRefresh() {
|
||||
TestGrid grid = new TestGrid();
|
||||
ItemsGrid.ScreenCapture capture = mock(ItemsGrid.ScreenCapture.class);
|
||||
grid.screenCapture = capture;
|
||||
|
||||
grid.setGridSize(1, 2, 18, 18);
|
||||
grid.setGridSize(1, 2, 18, 18);
|
||||
verify(capture, times(1)).refreshBuffer();
|
||||
|
||||
when(capture.needRefresh(1)).thenReturn(false, true);
|
||||
grid.refresh(null);
|
||||
grid.refresh(null);
|
||||
assertEquals(1, grid.overlapRefreshes);
|
||||
}
|
||||
|
||||
private static final class TestGrid extends ItemsGrid<ItemsGrid.ItemsGridSlot, ItemsGrid.MouseContext> {
|
||||
|
||||
private int overlapRefreshes;
|
||||
|
||||
@Override
|
||||
protected int getGridRenderingCacheMode() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateGuiOverlapSlots(GuiContainer gui) {
|
||||
overlapRefreshes++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemsGrid.ItemsGridSlot> getMask() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ItemsGrid.MouseContext getMouseContext(int mousex, int mousey) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import net.minecraft.client.renderer.InventoryEffectRenderer;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class NEIPotionGuiHandlerTest {
|
||||
|
||||
@Test
|
||||
void preservesGapsBetweenPotionBoxes() {
|
||||
assertTrue(NEIPotionGuiHandler.intersectsPotionEffects(131, 1, 100, 2, 33));
|
||||
assertFalse(NEIPotionGuiHandler.intersectsPotionEffects(132, 1, 100, 2, 33));
|
||||
}
|
||||
|
||||
@Test
|
||||
void skipsConfigLookupOutsidePotionColumn() {
|
||||
InventoryEffectRenderer gui = mock(InventoryEffectRenderer.class);
|
||||
gui.guiLeft = 200;
|
||||
|
||||
assertFalse(new NEIPotionGuiHandler().hideItemPanelSlot(gui, 216, 100, 1, 1));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package codechicken.nei.api;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
|
||||
public class GuiInfoTest {
|
||||
|
||||
@Test
|
||||
void checksProvidedHandlerSnapshot() {
|
||||
GuiContainer gui = mock(GuiContainer.class);
|
||||
INEIGuiHandler handler = mock(INEIGuiHandler.class);
|
||||
when(handler.hideItemPanelSlot(gui, 1, 2, 3, 4)).thenReturn(true);
|
||||
|
||||
assertTrue(GuiInfo.hideItemPanelSlot(gui, new Rectangle4i(1, 2, 3, 4), new INEIGuiHandler[] { handler }));
|
||||
}
|
||||
|
||||
@Test
|
||||
void buttonEdgeContactDoesNotOverlap() {
|
||||
GuiContainer gui = mock(GuiContainer.class);
|
||||
gui.buttonList = Collections.singletonList(new GuiButton(0, 10, 10, 10, 10, ""));
|
||||
|
||||
assertTrue(GuiInfo.hideItemPanelSlot(gui, new Rectangle4i(19, 19, 1, 1), new INEIGuiHandler[0]));
|
||||
assertFalse(GuiInfo.hideItemPanelSlot(gui, new Rectangle4i(20, 10, 1, 1), new INEIGuiHandler[0]));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package codechicken.nei.guihook;
|
||||
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.times;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.mockito.MockedStatic;
|
||||
|
||||
public class GuiContainerManagerTest {
|
||||
|
||||
@Test
|
||||
void matrixStackLoggingSupportsNestedContexts() {
|
||||
try (MockedStatic<GL11> gl = mockStatic(GL11.class)) {
|
||||
GuiContainerManager.enableMatrixStackLogging();
|
||||
GuiContainerManager.enableMatrixStackLogging();
|
||||
GuiContainerManager.disableMatrixStackLogging();
|
||||
|
||||
gl.verify(() -> GL11.glPushAttrib(GL11.GL_ENABLE_BIT | GL11.GL_COLOR_BUFFER_BIT | GL11.GL_LIGHTING_BIT));
|
||||
gl.verify(GL11::glPopAttrib, times(0));
|
||||
|
||||
GuiContainerManager.disableMatrixStackLogging();
|
||||
gl.verify(GL11::glPopAttrib);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user