mirror of
https://github.com/GTNewHorizons/NotEnoughItems.git
synced 2026-10-25 20:32:20 +00:00
Refactoring Chain Tooltip (#1044)
This commit is contained in:
1 parent
939845a9ed
commit
0ec87a8b9e
13 files changed
+478
-419
No files matched your search
@@ -0,0 +1,101 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.lib.gui.GuiDraw.ITooltipLineHandler;
|
||||
|
||||
public abstract class CompositeTooltipLineHandler implements ITooltipLineHandler {
|
||||
|
||||
protected static final int SCREEN_MARGIN = 8 * 2 + 10;
|
||||
protected static final int RESERVED_HEIGHT = 40;
|
||||
|
||||
protected final List<ItemsTooltipLineHandler> lines = new ArrayList<>();
|
||||
protected final Dimension size = new Dimension();
|
||||
|
||||
protected boolean created = false;
|
||||
protected int screenHeight = 0;
|
||||
|
||||
protected abstract void createLines();
|
||||
|
||||
protected boolean needsUpdate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getSize() {
|
||||
ensureCreated();
|
||||
return this.size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int x, int y) {
|
||||
if (this.size.height == 0) return;
|
||||
|
||||
for (ItemsTooltipLineHandler line : this.lines) {
|
||||
line.draw(x, y);
|
||||
y += line.getSize().height;
|
||||
}
|
||||
}
|
||||
|
||||
protected void ensureCreated() {
|
||||
boolean update = needsUpdate();
|
||||
update = this.screenHeight != (this.screenHeight = GuiDraw.displaySize().height) || update;
|
||||
|
||||
if (this.created && !update) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.created = true;
|
||||
this.lines.clear();
|
||||
this.size.setSize(0, 0);
|
||||
|
||||
createLines();
|
||||
fitToScreen();
|
||||
|
||||
for (ItemsTooltipLineHandler line : this.lines) {
|
||||
this.size.width = Math.max(this.size.width, line.getSize().width);
|
||||
this.size.height += line.getSize().height;
|
||||
}
|
||||
}
|
||||
|
||||
protected void fitToScreen() {
|
||||
if (this.lines.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final List<ItemsTooltipLineHandler> ordered = new ArrayList<>(this.lines);
|
||||
ordered.sort(Comparator.comparingInt(ItemsTooltipLineHandler::getRows));
|
||||
|
||||
int budget = availableHeight() / ItemsTooltipLineHandler.SLOT_SIZE;
|
||||
int rest = ordered.size();
|
||||
|
||||
for (ItemsTooltipLineHandler line : ordered) {
|
||||
final int fair = Math.max(1, budget / rest);
|
||||
|
||||
if (line.getRows() > fair) {
|
||||
line.setMaxRows(fair);
|
||||
}
|
||||
|
||||
budget -= line.getRows();
|
||||
rest--;
|
||||
}
|
||||
}
|
||||
|
||||
protected int availableHeight() {
|
||||
return GuiDraw.displaySize().height - SCREEN_MARGIN
|
||||
- RESERVED_HEIGHT
|
||||
- this.lines.size() * ItemsTooltipLineHandler.headerHeight();
|
||||
}
|
||||
|
||||
protected static int maxLineRows() {
|
||||
final int height = GuiDraw.displaySize().height - SCREEN_MARGIN
|
||||
- RESERVED_HEIGHT
|
||||
- ItemsTooltipLineHandler.headerHeight();
|
||||
return Math.max(1, height / ItemsTooltipLineHandler.SLOT_SIZE);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.fontRenderer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.renderer.RenderHelper;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
|
||||
public class ItemsListTooltipLineHandler extends ItemsTooltipLineHandler {
|
||||
|
||||
protected static final int NAME_MARGIN = 2;
|
||||
|
||||
protected final List<String> names = new ArrayList<>();
|
||||
protected int tailCount = 0;
|
||||
|
||||
public ItemsListTooltipLineHandler(String label, List<ItemStack> items, int maxRows) {
|
||||
super(label, items, true, maxRows);
|
||||
|
||||
this.rows = Math.min(maxRows, this.length);
|
||||
this.count = this.length > this.rows ? this.rows - 1 : this.length;
|
||||
|
||||
int width = fontRenderer.getStringWidth(this.label) + 15;
|
||||
|
||||
for (int index = 0; index < this.count; index++) {
|
||||
final String name = this.items.get(index).getDisplayName();
|
||||
this.names.add(name);
|
||||
width = Math.max(width, SLOT_SIZE + NAME_MARGIN + fontRenderer.getStringWidth(name));
|
||||
}
|
||||
|
||||
if (this.count < this.length) {
|
||||
final int tail = this.length - this.count;
|
||||
width = Math.max(width, Math.min(tail, MAX_COLUMNS) * SLOT_SIZE);
|
||||
|
||||
final int fit = width / SLOT_SIZE;
|
||||
|
||||
if (tail <= fit) {
|
||||
this.tailCount = tail;
|
||||
} else {
|
||||
final String text = "+" + (tail - fit);
|
||||
this.tailCount = Math
|
||||
.max(0, fit - (int) Math.ceil((float) (fontRenderer.getStringWidth(text) - 2) / SLOT_SIZE));
|
||||
}
|
||||
}
|
||||
|
||||
this.size.width = this.length > 0 ? width : 0;
|
||||
this.size.height = this.length > 0 ? this.rows * SLOT_SIZE + fontRenderer.FONT_HEIGHT + 2 + MARGIN_TOP : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLabel(String label) {
|
||||
this.label = label;
|
||||
this.size.width = Math.max(this.size.width, fontRenderer.getStringWidth(this.label) + 15);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int x, int y) {
|
||||
if (this.length == 0) return;
|
||||
|
||||
y += MARGIN_TOP;
|
||||
|
||||
fontRenderer.drawStringWithShadow(this.labelColor + this.label + ":", x, y, 0);
|
||||
|
||||
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
|
||||
|
||||
GL11.glPushAttrib(GL11.GL_ENABLE_BIT | GL11.GL_COLOR_BUFFER_BIT | GL11.GL_LIGHTING_BIT);
|
||||
RenderHelper.enableGUIStandardItemLighting();
|
||||
|
||||
final int xTranslation = x;
|
||||
final int yTranslation = y + fontRenderer.FONT_HEIGHT + 2;
|
||||
final int zTranslation = GuiContainerManager.TOOLTIP_Z_OFFSET;
|
||||
GL11.glTranslatef(xTranslation, yTranslation, zTranslation);
|
||||
|
||||
for (int index = 0; index < this.count; index++) {
|
||||
drawSlot(0, index * SLOT_SIZE, index);
|
||||
}
|
||||
|
||||
for (int index = 0; index < this.tailCount; index++) {
|
||||
drawSlot(index * SLOT_SIZE, this.count * SLOT_SIZE, this.count + index);
|
||||
}
|
||||
|
||||
NEIClientUtils.gl2DRenderContext(() -> {
|
||||
final int textShift = ICON_OFFSET + Math.round((ICON_SIZE - fontRenderer.FONT_HEIGHT) / 2f);
|
||||
|
||||
for (int index = 0; index < this.count; index++) {
|
||||
fontRenderer.drawStringWithShadow(
|
||||
EnumChatFormatting.GRAY + this.names.get(index),
|
||||
SLOT_SIZE + NAME_MARGIN,
|
||||
index * SLOT_SIZE + textShift,
|
||||
0xFFFFFF);
|
||||
}
|
||||
|
||||
final int hidden = this.length - this.count - this.tailCount;
|
||||
|
||||
if (hidden > 0) {
|
||||
final String text = "+" + hidden;
|
||||
fontRenderer.drawStringWithShadow(
|
||||
EnumChatFormatting.GRAY + text,
|
||||
this.size.width - fontRenderer.getStringWidth(text) - 2,
|
||||
this.count * SLOT_SIZE + textShift,
|
||||
0xFFFFFF);
|
||||
}
|
||||
});
|
||||
|
||||
GL11.glTranslatef(-xTranslation, -yTranslation, -zTranslation);
|
||||
GL11.glPopAttrib();
|
||||
}
|
||||
|
||||
protected void drawSlot(int x, int y, int index) {
|
||||
if (this.activeStackIndex == index) {
|
||||
NEIClientUtils.gl2DRenderContext(() -> GuiDraw.drawRect(x, y, SLOT_SIZE, SLOT_SIZE, 0x66555555));
|
||||
}
|
||||
|
||||
drawStackWithAmount(x, y, index);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -150,10 +150,14 @@ public class ItemsTooltipLineHandler implements ITooltipLineHandler {
|
||||
protected static final int ICON_OFFSET = 1;
|
||||
protected static final int MAX_COLUMNS = 11;
|
||||
protected static final int MARGIN_TOP = 2;
|
||||
protected static final int LABEL_MARGIN = 15;
|
||||
protected static final int NAME_MARGIN = 2;
|
||||
protected static final int DEFAULT_MAX_ROWS = 5;
|
||||
protected static final int FLUID_STACK_SIZE = 144;
|
||||
|
||||
protected final List<ItemStack> items;
|
||||
protected final List<Long> amounts = new ArrayList<>();
|
||||
protected final List<String> names = new ArrayList<>();
|
||||
|
||||
protected AmountRenderer amountRenderer;
|
||||
|
||||
@@ -163,40 +167,115 @@ public class ItemsTooltipLineHandler implements ITooltipLineHandler {
|
||||
protected int activeStackIndex = -1;
|
||||
protected Dimension size = new Dimension();
|
||||
|
||||
protected int columns = 0;
|
||||
protected int count = 0;
|
||||
protected int rows = 0;
|
||||
protected final boolean showNames;
|
||||
|
||||
protected int length = 0;
|
||||
protected int rows = 0;
|
||||
protected int nameRows = 0;
|
||||
protected int gridColumns = 0;
|
||||
protected int gridCount = 0;
|
||||
|
||||
public static ItemsTooltipLineHandler grid(String label, List<ItemStack> items, int maxRows) {
|
||||
return new ItemsTooltipLineHandler(label, items, true, maxRows, false);
|
||||
}
|
||||
|
||||
public static ItemsTooltipLineHandler list(String label, List<ItemStack> items, int maxRows) {
|
||||
return new ItemsTooltipLineHandler(label, items, true, maxRows, true);
|
||||
}
|
||||
|
||||
public ItemsTooltipLineHandler(String label, List<ItemStack> items) {
|
||||
this(label, items, true, 5);
|
||||
this(label, items, true, DEFAULT_MAX_ROWS, false);
|
||||
}
|
||||
|
||||
public ItemsTooltipLineHandler(String label, List<ItemStack> items, boolean saveStackSize, int maxRows) {
|
||||
this(label, items, saveStackSize, maxRows, false);
|
||||
}
|
||||
|
||||
protected ItemsTooltipLineHandler(String label, List<ItemStack> items, boolean saveStackSize, int maxRows,
|
||||
boolean showNames) {
|
||||
this.label = label;
|
||||
this.items = groupingItemStacks(items);
|
||||
this.amountRenderer = saveStackSize ? new TotalAmountRenderer() : new NoAmountRenderer();
|
||||
this.length = this.items.size();
|
||||
this.showNames = showNames;
|
||||
|
||||
if (this.length > 0) {
|
||||
this.columns = Math.min(MAX_COLUMNS, this.length);
|
||||
this.rows = Math.min(maxRows, (int) Math.ceil((float) this.length / this.columns));
|
||||
setMaxRows(maxRows);
|
||||
}
|
||||
|
||||
this.size.width = Math.max(this.columns * SLOT_SIZE, fontRenderer.getStringWidth(this.label) + 15);
|
||||
this.size.height = this.rows * SLOT_SIZE + fontRenderer.FONT_HEIGHT + 2 + MARGIN_TOP;
|
||||
protected static int headerHeight() {
|
||||
return fontRenderer.FONT_HEIGHT + 2 + MARGIN_TOP;
|
||||
}
|
||||
|
||||
this.count = Math.min(
|
||||
this.length,
|
||||
Math.min(
|
||||
this.columns * this.rows,
|
||||
this.length > MAX_COLUMNS * maxRows ? (MAX_COLUMNS * maxRows) : Integer.MAX_VALUE));
|
||||
public ItemsTooltipLineHandler setMaxRows(int maxRows) {
|
||||
if (this.length == 0) {
|
||||
return this;
|
||||
}
|
||||
|
||||
if (this.items.size() > this.count) {
|
||||
String text = "+" + (this.items.size() - this.count);
|
||||
this.count -= (int) Math.ceil((float) (fontRenderer.getStringWidth(text) - 2) / SLOT_SIZE);
|
||||
this.names.clear();
|
||||
this.nameRows = 0;
|
||||
|
||||
if (!this.showNames || !layoutWithNames(maxRows)) {
|
||||
layoutAsGrid(maxRows);
|
||||
}
|
||||
|
||||
this.size.height = this.rows * SLOT_SIZE + headerHeight();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getRows() {
|
||||
return this.rows;
|
||||
}
|
||||
|
||||
protected boolean layoutWithNames(int maxRows) {
|
||||
final int maxNames = this.length <= maxRows ? this.length : maxRows - 1;
|
||||
final int[] lineWidth = new int[maxNames + 1];
|
||||
lineWidth[0] = labelWidth();
|
||||
|
||||
for (int index = 0; index < maxNames; index++) {
|
||||
final String name = this.items.get(index).getDisplayName();
|
||||
this.names.add(name);
|
||||
lineWidth[index + 1] = Math
|
||||
.max(lineWidth[index], SLOT_SIZE + NAME_MARGIN + fontRenderer.getStringWidth(name));
|
||||
}
|
||||
|
||||
for (int named = maxNames; named >= 0; named--) {
|
||||
final int rest = this.length - named;
|
||||
final int width = Math.max(lineWidth[named], Math.min(rest, MAX_COLUMNS) * SLOT_SIZE);
|
||||
final int columns = Math.max(1, width / SLOT_SIZE);
|
||||
final int restRows = (int) Math.ceil((float) rest / columns);
|
||||
|
||||
if (named + restRows <= maxRows) {
|
||||
this.nameRows = named;
|
||||
this.gridColumns = columns;
|
||||
this.gridCount = rest;
|
||||
this.rows = named + restRows;
|
||||
this.size.width = width;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
this.names.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void layoutAsGrid(int maxRows) {
|
||||
this.gridColumns = Math.min(MAX_COLUMNS, this.length);
|
||||
this.rows = Math.min(maxRows, (int) Math.ceil((float) this.length / this.gridColumns));
|
||||
this.gridCount = Math.min(this.length, this.gridColumns * this.rows);
|
||||
this.size.width = Math.max(this.gridColumns * SLOT_SIZE, labelWidth());
|
||||
|
||||
if (this.gridCount < this.length) {
|
||||
this.gridCount -= reservedColumns(this.length - this.gridCount);
|
||||
}
|
||||
}
|
||||
|
||||
protected int labelWidth() {
|
||||
return fontRenderer.getStringWidth(this.label) + LABEL_MARGIN;
|
||||
}
|
||||
|
||||
protected int reservedColumns(int hidden) {
|
||||
return (int) Math.ceil((float) (fontRenderer.getStringWidth("+" + hidden) - 2) / SLOT_SIZE);
|
||||
}
|
||||
|
||||
public ItemsTooltipLineHandler setAmountRenderer(AmountRenderer amountRenderer) {
|
||||
@@ -233,7 +312,7 @@ public class ItemsTooltipLineHandler implements ITooltipLineHandler {
|
||||
|
||||
public void setLabel(String label) {
|
||||
this.label = label;
|
||||
this.size.width = Math.max(this.columns * SLOT_SIZE, fontRenderer.getStringWidth(this.label) + 15);
|
||||
this.size.width = Math.max(this.size.width, labelWidth());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -254,40 +333,62 @@ public class ItemsTooltipLineHandler implements ITooltipLineHandler {
|
||||
final int zTranslation = GuiContainerManager.TOOLTIP_Z_OFFSET;
|
||||
GL11.glTranslatef(xTranslation, yTranslation, zTranslation);
|
||||
|
||||
int indexShift = 0;
|
||||
final int gridShift = gridIndexShift();
|
||||
|
||||
if (this.activeStackIndex != -1) {
|
||||
indexShift = Math.max(0, Math.min(this.items.size() - this.count, this.activeStackIndex - this.count + 2));
|
||||
for (int index = 0; index < this.nameRows; index++) {
|
||||
drawSlot(0, index * SLOT_SIZE, index);
|
||||
}
|
||||
|
||||
for (int index = 0; index < this.count && index + indexShift < this.items.size(); index++) {
|
||||
int col = index % this.columns;
|
||||
int row = index / this.columns;
|
||||
for (int index = 0; index < this.gridCount; index++) {
|
||||
drawSlot(
|
||||
(index % this.gridColumns) * SLOT_SIZE,
|
||||
(this.nameRows + index / this.gridColumns) * SLOT_SIZE,
|
||||
this.nameRows + gridShift + index);
|
||||
}
|
||||
|
||||
if (this.activeStackIndex == index + indexShift) {
|
||||
NEIClientUtils.gl2DRenderContext(
|
||||
() -> GuiDraw.drawRect(col * SLOT_SIZE, row * SLOT_SIZE, SLOT_SIZE, SLOT_SIZE, 0x66555555));
|
||||
NEIClientUtils.gl2DRenderContext(() -> {
|
||||
final int textShift = ICON_OFFSET + Math.round((ICON_SIZE - fontRenderer.FONT_HEIGHT) / 2f);
|
||||
|
||||
for (int index = 0; index < this.nameRows; index++) {
|
||||
fontRenderer.drawStringWithShadow(
|
||||
EnumChatFormatting.GRAY + this.names.get(index),
|
||||
SLOT_SIZE + NAME_MARGIN,
|
||||
index * SLOT_SIZE + textShift,
|
||||
0xFFFFFF);
|
||||
}
|
||||
|
||||
drawStackWithAmount(col * SLOT_SIZE, row * SLOT_SIZE, index + indexShift);
|
||||
}
|
||||
final int hidden = this.length - this.nameRows - this.gridCount;
|
||||
|
||||
if (this.count < this.items.size()) {
|
||||
final String text = "+" + (this.items.size() - this.count);
|
||||
|
||||
NEIClientUtils.gl2DRenderContext(() -> {
|
||||
if (hidden > 0) {
|
||||
final String text = "+" + hidden;
|
||||
fontRenderer.drawStringWithShadow(
|
||||
text,
|
||||
MAX_COLUMNS * SLOT_SIZE - fontRenderer.getStringWidth(text) - 2,
|
||||
(this.rows - 1) * SLOT_SIZE + (SLOT_SIZE - fontRenderer.FONT_HEIGHT) / 2,
|
||||
0xee555555);
|
||||
});
|
||||
}
|
||||
EnumChatFormatting.GRAY + text,
|
||||
this.size.width - fontRenderer.getStringWidth(text) - 2,
|
||||
(this.rows - 1) * SLOT_SIZE + textShift,
|
||||
0xFFFFFF);
|
||||
}
|
||||
});
|
||||
|
||||
GL11.glTranslatef(-xTranslation, -yTranslation, -zTranslation);
|
||||
GL11.glPopAttrib();
|
||||
}
|
||||
|
||||
protected int gridIndexShift() {
|
||||
if (this.nameRows > 0 || this.activeStackIndex == -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Math.max(0, Math.min(this.length - this.gridCount, this.activeStackIndex - this.gridCount + 2));
|
||||
}
|
||||
|
||||
protected void drawSlot(int x, int y, int index) {
|
||||
if (this.activeStackIndex == index) {
|
||||
NEIClientUtils.gl2DRenderContext(() -> GuiDraw.drawRect(x, y, SLOT_SIZE, SLOT_SIZE, 0x66555555));
|
||||
}
|
||||
|
||||
drawStackWithAmount(x, y, index);
|
||||
}
|
||||
|
||||
protected void drawStackWithAmount(int x, int y, int index) {
|
||||
this.amountRenderer.draw(x + ICON_OFFSET, y + ICON_OFFSET, this.items.get(index), this.amounts.get(index));
|
||||
}
|
||||
|
||||
@@ -212,9 +212,6 @@ public class NEIClientConfig {
|
||||
.getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.bookmarks.showRecipeHandlerIcon", true));
|
||||
|
||||
tag.getTag("inventory.bookmarks.recipeChainDir").getIntValue(1);
|
||||
API.addOption(new OptionCycled("inventory.bookmarks.recipeChainDir", 2, true));
|
||||
|
||||
tag.getTag("inventory.bookmarks.ignorePotionOverlap").setComment("Ignore overlap with potion effect HUD")
|
||||
.getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.bookmarks.ignorePotionOverlap", true));
|
||||
@@ -1153,10 +1150,6 @@ public class NEIClientConfig {
|
||||
return getBooleanSetting("inventory.bookmarks.ignorePotionOverlap");
|
||||
}
|
||||
|
||||
public static int recipeChainDir() {
|
||||
return getIntSetting("inventory.bookmarks.recipeChainDir");
|
||||
}
|
||||
|
||||
public static boolean optimizeGuiOverlapComputation() {
|
||||
return getBooleanSetting("inventory.optimize_gui_overlap_computation");
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
@@ -116,7 +115,7 @@ public class GuiCraftingTree extends GuiContainer implements INEIGuiHandler, IGu
|
||||
private static final int PADDING = 9;
|
||||
private static final int PADDING_TOP = 22;
|
||||
|
||||
private static LRUCache<String, String> handlerTitleCache = new LRUCache<>(100);
|
||||
private final LRUCache<String, String> handlerTitleCache = new LRUCache<>(100);
|
||||
|
||||
private GuiScreen prevGui;
|
||||
private boolean isFirstScreen = true;
|
||||
@@ -919,15 +918,8 @@ public class GuiCraftingTree extends GuiContainer implements INEIGuiHandler, IGu
|
||||
super.keyTyped(typedChar, keyCode);
|
||||
}
|
||||
|
||||
private static String getHandlerTitle(String handlerName) {
|
||||
return handlerTitleCache.computeIfAbsent(
|
||||
handlerName,
|
||||
hname -> Stream
|
||||
.concat(
|
||||
GuiCraftingRecipe.craftinghandlers.stream(),
|
||||
GuiCraftingRecipe.serialCraftingHandlers.stream())
|
||||
.filter(handler -> hname.equals(GuiRecipeTab.getHandlerInfo(handler).getHandlerName()))
|
||||
.findFirst().map(handler -> handler.getRecipeName().trim()).orElse(hname));
|
||||
private String getHandlerTitle(String handlerName) {
|
||||
return this.handlerTitleCache.computeIfAbsent(handlerName, GuiRecipeTab::getHandlerTitle);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,6 +3,7 @@ package codechicken.nei.bookmark.tree;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -122,7 +123,7 @@ class StatsPanel extends ScrollContainer {
|
||||
|
||||
GL11.glPushMatrix();
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
GL11.glTranslatef(badgeX, y - 6 * scale, 3.0f);
|
||||
GL11.glTranslatef(badgeX, y - 6 * scale, 10.0f);
|
||||
GL11.glScalef(scale, scale, 1.0f);
|
||||
|
||||
if (this.info.hasImageOrItem()) {
|
||||
@@ -715,8 +716,14 @@ class StatsPanel extends ScrollContainer {
|
||||
private List<Widget> collectHandlers(RecipeChainMath math) {
|
||||
final Map<String, HandlerStats> handlerStats = new HashMap<>();
|
||||
final List<Widget> widgets = new ArrayList<>();
|
||||
final Set<RecipeId> countedRecipes = new HashSet<>();
|
||||
|
||||
for (BookmarkItem item : math.recipeResults) {
|
||||
// a recipe adds one result item per output, count it only once
|
||||
if (!countedRecipes.add(item.recipeId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final HandlerStats stats = handlerStats
|
||||
.computeIfAbsent(item.recipeId.getHandlerName(), k -> new HandlerStats());
|
||||
stats.iterations += item.getMultiplier();
|
||||
|
||||
@@ -262,11 +262,8 @@ public class GuiOverlayButton extends GuiRecipeButton {
|
||||
.map(state -> state.getSlot().item).collect(Collectors.toList());
|
||||
|
||||
if (!items.isEmpty()) {
|
||||
this.missedMaterialsTooltipLineHandler = new ItemsTooltipLineHandler(
|
||||
NEIClientUtils.translate("recipe.overlay.missing"),
|
||||
items,
|
||||
true,
|
||||
Integer.MAX_VALUE);
|
||||
this.missedMaterialsTooltipLineHandler = ItemsTooltipLineHandler
|
||||
.grid(NEIClientUtils.translate("recipe.overlay.missing"), items, Integer.MAX_VALUE);
|
||||
} else {
|
||||
this.missedMaterialsTooltipLineHandler = null;
|
||||
}
|
||||
|
||||
@@ -181,6 +181,24 @@ public abstract class GuiRecipeTab extends Widget {
|
||||
return res;
|
||||
}
|
||||
|
||||
public static String getHandlerTitle(String handlerName) {
|
||||
String title = findRecipeName(GuiCraftingRecipe.craftinghandlers, handlerName);
|
||||
if (title == null) title = findRecipeName(GuiCraftingRecipe.serialCraftingHandlers, handlerName);
|
||||
if (title == null) title = findRecipeName(GuiUsageRecipe.usagehandlers, handlerName);
|
||||
if (title == null) title = findRecipeName(GuiUsageRecipe.serialUsageHandlers, handlerName);
|
||||
|
||||
return title != null ? title : handlerName;
|
||||
}
|
||||
|
||||
private static String findRecipeName(List<? extends IRecipeHandler> handlers, String handlerName) {
|
||||
for (int index = 0; index < handlers.size(); index++) {
|
||||
final IRecipeHandler handler = handlers.get(index);
|
||||
if (handlerName.equals(getHandlerInfo(handler).getHandlerName())) return handler.getRecipeName().trim();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getHandlerMod(String name, String name2) {
|
||||
HandlerInfo info = getHandlerInfo(name, name2);
|
||||
if (info == null) return "Unknown";
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
@@ -16,10 +15,9 @@ import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw.ITooltipLineHandler;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.CompositeTooltipLineHandler;
|
||||
import codechicken.nei.ItemStackAmount;
|
||||
import codechicken.nei.ItemsListTooltipLineHandler;
|
||||
import codechicken.nei.ItemsTooltipLineHandler;
|
||||
import codechicken.nei.ItemsTooltipLineHandler.StacksAmountRenderer;
|
||||
import codechicken.nei.ItemsTooltipLineHandler.TotalAmountRenderer;
|
||||
@@ -30,7 +28,7 @@ import codechicken.nei.recipe.Recipe.RecipeId;
|
||||
import codechicken.nei.recipe.Recipe.RecipeIngredient;
|
||||
import codechicken.nei.util.ReadableNumberConverter;
|
||||
|
||||
public class RecipeItemsTooltipLineHandler implements ITooltipLineHandler {
|
||||
public class RecipeItemsTooltipLineHandler extends CompositeTooltipLineHandler {
|
||||
|
||||
protected static class ChanceTotalAmountRenderer extends TotalAmountRenderer {
|
||||
|
||||
@@ -86,16 +84,10 @@ public class RecipeItemsTooltipLineHandler implements ITooltipLineHandler {
|
||||
}
|
||||
}
|
||||
|
||||
protected static final int MAX_ROWS = 15;
|
||||
|
||||
protected final RecipeId recipeId;
|
||||
protected final long multiplier;
|
||||
protected boolean useInventory = false;
|
||||
|
||||
protected final List<ItemsTooltipLineHandler> lines = new ArrayList<>();
|
||||
protected final Dimension size = new Dimension();
|
||||
protected String title = "";
|
||||
protected boolean created = false;
|
||||
|
||||
public RecipeItemsTooltipLineHandler(RecipeId recipeId, long multiplier) {
|
||||
this.recipeId = recipeId;
|
||||
@@ -125,37 +117,12 @@ public class RecipeItemsTooltipLineHandler implements ITooltipLineHandler {
|
||||
return this.title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getSize() {
|
||||
ensureCreated();
|
||||
return this.size;
|
||||
}
|
||||
|
||||
protected void ensureCreated() {
|
||||
if (!this.created) {
|
||||
this.created = true;
|
||||
createLines();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int x, int y) {
|
||||
if (this.size.height == 0) return;
|
||||
|
||||
for (ItemsTooltipLineHandler line : this.lines) {
|
||||
line.draw(x, y);
|
||||
y += line.getSize().height;
|
||||
}
|
||||
}
|
||||
|
||||
protected static int getIngredientOrder(ItemStack stack) {
|
||||
return StackInfo.isFluidDisplayItem(stack) ? 2 : stack.stackSize == 0 ? 0 : 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createLines() {
|
||||
this.lines.clear();
|
||||
this.size.setSize(0, 0);
|
||||
|
||||
final RecipeHandlerRef handlerRef = RecipeHandlerRef.of(this.recipeId);
|
||||
|
||||
if (handlerRef == null) {
|
||||
@@ -188,25 +155,17 @@ public class RecipeItemsTooltipLineHandler implements ITooltipLineHandler {
|
||||
addNeededLine(
|
||||
needed,
|
||||
approximateIngredients,
|
||||
needed.size() == 1 || ingredientsAmount.size() + neededAmount.size() <= MAX_ROWS);
|
||||
needed.size() == 1 || ingredientsAmount.size() + neededAmount.size() <= maxLineRows());
|
||||
}
|
||||
}
|
||||
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
for (ItemsTooltipLineHandler line : this.lines) {
|
||||
width = Math.max(width, line.getSize().width);
|
||||
height += line.getSize().height;
|
||||
}
|
||||
|
||||
this.size.setSize(width, height);
|
||||
}
|
||||
|
||||
protected void addResultLine(List<ItemStack> items, Set<NBTTagCompound> approximate) {
|
||||
final String label = NEIClientUtils.translate("recipe.items.results");
|
||||
final ItemsTooltipLineHandler line = items.size() == 1 ? new ItemsListTooltipLineHandler(label, items, MAX_ROWS)
|
||||
: new ItemsTooltipLineHandler(label, items);
|
||||
final ItemsTooltipLineHandler line = items.size() == 1
|
||||
? ItemsTooltipLineHandler.list(label, items, maxLineRows())
|
||||
: ItemsTooltipLineHandler.grid(label, items, maxLineRows());
|
||||
|
||||
if (line.isEmpty()) {
|
||||
return;
|
||||
@@ -229,7 +188,7 @@ public class RecipeItemsTooltipLineHandler implements ITooltipLineHandler {
|
||||
|
||||
protected void addRequiredLine(List<ItemStack> items, Set<NBTTagCompound> approximate) {
|
||||
final String label = NEIClientUtils.translate("recipe.items.ingredients");
|
||||
final ItemsTooltipLineHandler line = new ItemsListTooltipLineHandler(label, items, MAX_ROWS);
|
||||
final ItemsTooltipLineHandler line = ItemsTooltipLineHandler.list(label, items, maxLineRows());
|
||||
|
||||
if (line.isEmpty()) {
|
||||
return;
|
||||
@@ -252,8 +211,8 @@ public class RecipeItemsTooltipLineHandler implements ITooltipLineHandler {
|
||||
|
||||
protected void addNeededLine(List<ItemStack> items, Set<NBTTagCompound> approximate, boolean vertical) {
|
||||
final String label = NEIClientUtils.translate("recipe.items.ingredients_needed");
|
||||
final ItemsTooltipLineHandler line = vertical ? new ItemsListTooltipLineHandler(label, items, MAX_ROWS)
|
||||
: new ItemsTooltipLineHandler(label, items);
|
||||
final ItemsTooltipLineHandler line = vertical ? ItemsTooltipLineHandler.list(label, items, maxLineRows())
|
||||
: ItemsTooltipLineHandler.grid(label, items, maxLineRows());
|
||||
|
||||
if (line.isEmpty()) {
|
||||
return;
|
||||
|
||||
@@ -1,30 +1,123 @@
|
||||
package codechicken.nei.recipe.chain;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.lib.gui.GuiDraw.ITooltipLineHandler;
|
||||
import codechicken.nei.ColorUtils;
|
||||
import codechicken.nei.CompositeTooltipLineHandler;
|
||||
import codechicken.nei.ItemSorter;
|
||||
import codechicken.nei.ItemStackAmount;
|
||||
import codechicken.nei.ItemsTooltipLineHandler;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.ItemsTooltipLineHandler.AmountRenderer;
|
||||
import codechicken.nei.ItemsTooltipLineHandler.StacksAmountRenderer;
|
||||
import codechicken.nei.ItemsTooltipLineHandler.TotalAmountRenderer;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.bookmark.BookmarkItem;
|
||||
import codechicken.nei.drawable.DrawableResource;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.recipe.AutoCraftingManager;
|
||||
import codechicken.nei.recipe.GuiRecipe;
|
||||
import codechicken.nei.recipe.GuiRecipeTab;
|
||||
import codechicken.nei.recipe.HandlerInfo;
|
||||
import codechicken.nei.recipe.Recipe.RecipeId;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
|
||||
public class RecipeChainTooltipLineHandler implements ITooltipLineHandler {
|
||||
public class RecipeChainTooltipLineHandler extends CompositeTooltipLineHandler {
|
||||
|
||||
protected static class MissingStacksAmountRenderer extends StacksAmountRenderer {
|
||||
|
||||
protected static final int MISSING_COLOR = 0xFF5555;
|
||||
|
||||
protected final Set<NBTTagCompound> missing;
|
||||
private final Map<ItemStack, Boolean> cache = new IdentityHashMap<>();
|
||||
|
||||
public MissingStacksAmountRenderer(Set<NBTTagCompound> missing) {
|
||||
this.missing = missing;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getColor(ItemStack stack) {
|
||||
return this.cache.computeIfAbsent(stack, key -> this.missing.contains(StackInfo.itemStackToNBT(key, false)))
|
||||
? MISSING_COLOR
|
||||
: super.getColor(stack);
|
||||
}
|
||||
}
|
||||
|
||||
protected static class HandlerIconRenderer extends TotalAmountRenderer {
|
||||
|
||||
protected static final int ICON_SIZE = 16;
|
||||
protected static final float BADGE_SCALE = 0.6f;
|
||||
protected static final float BADGE_OFFSET = 3f;
|
||||
// slots are drawn edge to edge, so the badge has to clear the 3d model of the neighbour slot
|
||||
protected static final float BADGE_Z = 10f;
|
||||
|
||||
protected final Map<NBTTagCompound, HandlerInfo> handlers;
|
||||
private final Map<ItemStack, HandlerInfo> cache = new IdentityHashMap<>();
|
||||
private final Map<String, String> titleCache = new HashMap<>();
|
||||
|
||||
public HandlerIconRenderer(Map<NBTTagCompound, HandlerInfo> handlers) {
|
||||
this.handlers = handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int x, int y, ItemStack stack, long amount) {
|
||||
super.draw(x, y, stack, amount);
|
||||
drawHandlerBadge(
|
||||
x,
|
||||
y,
|
||||
this.cache.computeIfAbsent(stack, key -> this.handlers.get(StackInfo.itemStackToNBT(key, false))));
|
||||
}
|
||||
|
||||
protected void drawHandlerBadge(int x, int y, HandlerInfo handlerInfo) {
|
||||
if (handlerInfo == null) return;
|
||||
|
||||
GL11.glPushMatrix();
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
GL11.glTranslatef(x - BADGE_OFFSET * BADGE_SCALE, y - BADGE_OFFSET * BADGE_SCALE, BADGE_Z);
|
||||
GL11.glScalef(BADGE_SCALE, BADGE_SCALE, 1.0f);
|
||||
|
||||
if (handlerInfo.hasImageOrItem()) {
|
||||
final DrawableResource image = handlerInfo.getImage();
|
||||
|
||||
if (image != null) {
|
||||
NEIClientUtils.gl2DRenderContext(() -> image.draw(0, 0));
|
||||
} else {
|
||||
GuiContainerManager.drawItem(0, 0, handlerInfo.getItemStack(), true, "");
|
||||
}
|
||||
|
||||
} else {
|
||||
drawBadgeText(handlerInfo.getHandlerName());
|
||||
}
|
||||
|
||||
GL11.glPopMatrix();
|
||||
}
|
||||
|
||||
protected void drawBadgeText(String handlerName) {
|
||||
final String title = this.titleCache.computeIfAbsent(handlerName, GuiRecipeTab::getHandlerTitle);
|
||||
final String text = title.isEmpty() ? "??" : title.substring(0, Math.min(2, title.length()));
|
||||
|
||||
NEIClientUtils.gl2DRenderContext(
|
||||
() -> GuiDraw.fontRenderer.drawStringWithShadow(
|
||||
text,
|
||||
(ICON_SIZE - GuiDraw.fontRenderer.getStringWidth(text)) / 2,
|
||||
(ICON_SIZE - GuiDraw.fontRenderer.FONT_HEIGHT) / 2,
|
||||
ColorUtils.buttonLabelNormal.getColor()));
|
||||
}
|
||||
}
|
||||
|
||||
public final int groupId;
|
||||
public final boolean crafting;
|
||||
@@ -32,16 +125,9 @@ public class RecipeChainTooltipLineHandler implements ITooltipLineHandler {
|
||||
protected final List<BookmarkItem> initialItems;
|
||||
protected final Map<RecipeId, Long> outputRecipes;
|
||||
|
||||
protected ItemsTooltipLineHandler available;
|
||||
protected ItemsTooltipLineHandler inputs;
|
||||
protected ItemsTooltipLineHandler outputs;
|
||||
protected ItemsTooltipLineHandler remainder;
|
||||
protected ItemsTooltipLineHandler craftingNeeded;
|
||||
protected boolean lastShiftKey = false;
|
||||
protected boolean lastControlKey = false;
|
||||
|
||||
protected Dimension size = new Dimension();
|
||||
|
||||
public RecipeChainTooltipLineHandler(int groupId, boolean crafting, RecipeChainMath math) {
|
||||
this.groupId = groupId;
|
||||
this.crafting = crafting;
|
||||
@@ -50,20 +136,32 @@ public class RecipeChainTooltipLineHandler implements ITooltipLineHandler {
|
||||
this.outputRecipes = new HashMap<>(this.math.outputRecipes);
|
||||
}
|
||||
|
||||
private void onUpdate() {
|
||||
@Override
|
||||
protected boolean needsUpdate() {
|
||||
final boolean shiftChanged = this.lastShiftKey != (this.lastShiftKey = NEIClientUtils.shiftKey());
|
||||
return this.lastControlKey != (this.lastControlKey = NEIClientUtils.controlKey()) || shiftChanged;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createLines() {
|
||||
if (this.outputRecipes.isEmpty() && !this.lastShiftKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
final List<ItemStack> available = new ArrayList<>();
|
||||
final List<ItemStack> inputs = new ArrayList<>();
|
||||
final List<ItemStack> outputs = new ArrayList<>();
|
||||
final List<ItemStack> remainder = new ArrayList<>();
|
||||
final List<ItemStack> craftingNeeded = new ArrayList<>();
|
||||
final Map<NBTTagCompound, HandlerInfo> craftingHandlers = new HashMap<>();
|
||||
final ItemStackAmount inventory = new ItemStackAmount();
|
||||
final GuiContainer currentGui = NEIClientUtils.getGuiContainer();
|
||||
|
||||
if (this.lastShiftKey && !(currentGui instanceof GuiRecipe<?>)) {
|
||||
if (this.lastShiftKey && currentGui != null && !(currentGui instanceof GuiRecipe<?>)) {
|
||||
inventory.putAll(AutoCraftingManager.getInventoryItems(currentGui));
|
||||
}
|
||||
|
||||
if (!this.math.outputRecipes.isEmpty()) {
|
||||
if (!this.outputRecipes.isEmpty()) {
|
||||
this.math.initialItems.clear();
|
||||
this.math.outputRecipes.clear();
|
||||
this.math.outputRecipes.putAll(this.outputRecipes);
|
||||
@@ -105,7 +203,7 @@ public class RecipeChainTooltipLineHandler implements ITooltipLineHandler {
|
||||
}
|
||||
|
||||
} else {
|
||||
this.math.initialItems.addAll(initialItems);
|
||||
this.math.initialItems.addAll(this.initialItems);
|
||||
}
|
||||
|
||||
this.math.refresh();
|
||||
@@ -138,26 +236,24 @@ public class RecipeChainTooltipLineHandler implements ITooltipLineHandler {
|
||||
if (amount > 0) {
|
||||
if (math.outputRecipes.containsKey(item.recipeId)) {
|
||||
outputs.add(item.getItemStack(amount));
|
||||
} else if (this.lastShiftKey) {
|
||||
} else {
|
||||
remainder.add(item.getItemStack(amount));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.lastShiftKey) {
|
||||
for (ItemStack stack : math.containerItemsInventory) {
|
||||
if (stack != null) {
|
||||
remainder.add(stack.copy());
|
||||
}
|
||||
for (ItemStack stack : math.containerItemsInventory) {
|
||||
if (stack != null) {
|
||||
remainder.add(stack.copy());
|
||||
}
|
||||
for (ItemStack stack : math.containerItemsCrafting) {
|
||||
if (stack != null) {
|
||||
remainder.add(stack.copy());
|
||||
}
|
||||
}
|
||||
for (ItemStack stack : math.containerItemsCrafting) {
|
||||
if (stack != null) {
|
||||
remainder.add(stack.copy());
|
||||
}
|
||||
}
|
||||
|
||||
} else if (this.lastShiftKey) {
|
||||
} else {
|
||||
|
||||
for (BookmarkItem item : this.math.initialItems) {
|
||||
if (inventory.contains(item.itemStack)) {
|
||||
@@ -175,161 +271,100 @@ public class RecipeChainTooltipLineHandler implements ITooltipLineHandler {
|
||||
inputs.add(item.getItemStack());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (this.lastShiftKey) {
|
||||
for (Map.Entry<BookmarkItem, Long> item : this.math.requiredAmount.entrySet()) {
|
||||
if (item.getKey().type == BookmarkItem.BookmarkItemType.RESULT && item.getValue() != 0)
|
||||
craftingNeeded.add(item.getKey().getItemStack(item.getValue()));
|
||||
if (item.getKey().type == BookmarkItem.BookmarkItemType.RESULT && item.getValue() != 0) {
|
||||
final ItemStack stack = item.getKey().getItemStack(item.getValue());
|
||||
|
||||
craftingNeeded.add(stack);
|
||||
putHandlerInfo(craftingHandlers, stack, item.getKey().recipeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inputs.sort(
|
||||
Comparator.comparing((ItemStack stack) -> StackInfo.getFluid(stack) != null)
|
||||
.thenComparingInt(stack -> -1 * stack.stackSize).thenComparing(ItemSorter.instance));
|
||||
outputs.sort(
|
||||
Comparator.comparing((ItemStack stack) -> StackInfo.getFluid(stack) != null)
|
||||
.thenComparingInt(stack -> -1 * stack.stackSize).thenComparing(ItemSorter.instance));
|
||||
remainder.sort(
|
||||
Comparator.comparing((ItemStack stack) -> StackInfo.getFluid(stack) != null)
|
||||
.thenComparingInt(stack -> -1 * stack.stackSize).thenComparing(ItemSorter.instance));
|
||||
|
||||
this.inputs = new ItemsTooltipLineHandler(
|
||||
this.lastShiftKey ? NEIClientUtils.translate("bookmark.crafting_chain.missing")
|
||||
: NEIClientUtils.translate("bookmark.crafting_chain.input"),
|
||||
inputs,
|
||||
true,
|
||||
Integer.MAX_VALUE);
|
||||
|
||||
this.available = new ItemsTooltipLineHandler(
|
||||
NEIClientUtils.translate("bookmark.crafting_chain.available"),
|
||||
available,
|
||||
true,
|
||||
Integer.MAX_VALUE);
|
||||
|
||||
this.outputs = new ItemsTooltipLineHandler(
|
||||
NEIClientUtils.translate("bookmark.crafting_chain.output"),
|
||||
outputs,
|
||||
true,
|
||||
Integer.MAX_VALUE);
|
||||
|
||||
this.remainder = new ItemsTooltipLineHandler(
|
||||
NEIClientUtils.translate("bookmark.crafting_chain.remainder"),
|
||||
remainder,
|
||||
true,
|
||||
Integer.MAX_VALUE);
|
||||
|
||||
this.craftingNeeded = new ItemsTooltipLineHandler(
|
||||
NEIClientUtils.translate("bookmark.crafting_chain.needed"),
|
||||
craftingNeeded,
|
||||
true,
|
||||
Integer.MAX_VALUE);
|
||||
final Set<NBTTagCompound> missing = new HashSet<>();
|
||||
|
||||
if (this.lastShiftKey) {
|
||||
this.inputs.setLabelColor(EnumChatFormatting.RED);
|
||||
this.available.setLabelColor(EnumChatFormatting.GREEN);
|
||||
this.craftingNeeded.setLabelColor(EnumChatFormatting.BLUE);
|
||||
}
|
||||
|
||||
this.size.height = this.size.width = 0;
|
||||
|
||||
if (!this.inputs.isEmpty() || !this.outputs.isEmpty()
|
||||
|| !this.remainder.isEmpty()
|
||||
|| !this.available.isEmpty()) {
|
||||
|
||||
if (!this.math.outputRecipes.isEmpty()) {
|
||||
this.size.height = 2 + GuiDraw.fontRenderer.FONT_HEIGHT;
|
||||
for (ItemStack stack : inputs) {
|
||||
missing.add(StackInfo.itemStackToNBT(stack, false));
|
||||
}
|
||||
this.size.width = Math.max(
|
||||
this.inputs.getSize().width,
|
||||
Math.max(
|
||||
this.outputs.getSize().width,
|
||||
Math.max(
|
||||
this.remainder.getSize().width,
|
||||
Math.max(this.available.getSize().width, this.craftingNeeded.getSize().width))));
|
||||
|
||||
this.size.height += this.inputs.getSize().height + this.outputs.getSize().height
|
||||
+ this.remainder.getSize().height
|
||||
+ this.available.getSize().height
|
||||
+ this.craftingNeeded.getSize().height;
|
||||
}
|
||||
|
||||
// items with a shortage are already in the inputs list, holding the missing amount instead of the required one
|
||||
final List<ItemStack> covered = new ArrayList<>();
|
||||
|
||||
for (ItemStack stack : available) {
|
||||
if (!missing.contains(StackInfo.itemStackToNBT(stack, false))) {
|
||||
covered.add(stack);
|
||||
}
|
||||
}
|
||||
|
||||
final Comparator<ItemStack> comparator = Comparator
|
||||
.comparing((ItemStack stack) -> StackInfo.getFluid(stack) != null)
|
||||
.thenComparingInt(stack -> -1 * stack.stackSize).thenComparing(ItemSorter.instance);
|
||||
|
||||
inputs.sort(comparator);
|
||||
covered.sort(comparator);
|
||||
outputs.sort(comparator);
|
||||
remainder.sort(comparator);
|
||||
|
||||
// missing items stay on top of the list
|
||||
inputs.addAll(covered);
|
||||
|
||||
if (this.lastShiftKey) {
|
||||
outputs.addAll(remainder);
|
||||
}
|
||||
|
||||
addLine(
|
||||
NEIClientUtils.translate("bookmark.crafting_chain"),
|
||||
outputs,
|
||||
outputs.size() == 1,
|
||||
EnumChatFormatting.AQUA,
|
||||
new TotalAmountRenderer());
|
||||
|
||||
addLine(
|
||||
NEIClientUtils.translate("bookmark.crafting_chain.needed"),
|
||||
craftingNeeded,
|
||||
false,
|
||||
EnumChatFormatting.BLUE,
|
||||
new HandlerIconRenderer(craftingHandlers));
|
||||
|
||||
addLine(
|
||||
NEIClientUtils.translate("bookmark.crafting_chain.input"),
|
||||
inputs,
|
||||
this.lastShiftKey,
|
||||
EnumChatFormatting.YELLOW,
|
||||
this.lastShiftKey ? new MissingStacksAmountRenderer(missing) : new TotalAmountRenderer());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getSize() {
|
||||
boolean update = this.outputs == null;
|
||||
update = this.lastShiftKey != (this.lastShiftKey = NEIClientUtils.shiftKey()) || update;
|
||||
update = this.lastControlKey != (this.lastControlKey = NEIClientUtils.controlKey()) || update;
|
||||
|
||||
if (update) {
|
||||
onUpdate();
|
||||
protected static void putHandlerInfo(Map<NBTTagCompound, HandlerInfo> handlers, ItemStack stack,
|
||||
RecipeId recipeId) {
|
||||
if (recipeId == null) {
|
||||
return;
|
||||
}
|
||||
return this.size;
|
||||
|
||||
final HandlerInfo handlerInfo = GuiRecipeTab.getHandlerInfo(recipeId.getHandlerName(), null);
|
||||
|
||||
handlers.put(
|
||||
StackInfo.itemStackToNBT(stack, false),
|
||||
handlerInfo != null ? handlerInfo : GuiRecipeTab.DEFAULT_HANDLER_INFO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int x, int y) {
|
||||
if (this.size.height == 0) return;
|
||||
protected void addLine(String label, List<ItemStack> items, boolean vertical, EnumChatFormatting labelColor,
|
||||
AmountRenderer amountRenderer) {
|
||||
final ItemsTooltipLineHandler line = vertical ? ItemsTooltipLineHandler.list(label, items, maxLineRows())
|
||||
: ItemsTooltipLineHandler.grid(label, items, maxLineRows());
|
||||
|
||||
if (!this.math.outputRecipes.isEmpty()) {
|
||||
GuiDraw.fontRenderer.drawStringWithShadow(
|
||||
EnumChatFormatting.AQUA + NEIClientUtils.translate("bookmark.crafting_chain"),
|
||||
x,
|
||||
y + 2,
|
||||
0xee555555);
|
||||
|
||||
y += 2 + GuiDraw.fontRenderer.FONT_HEIGHT;
|
||||
if (line.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (NEIClientConfig.recipeChainDir() == 0) {
|
||||
if (!this.inputs.isEmpty()) {
|
||||
this.inputs.draw(x, y);
|
||||
y += this.inputs.getSize().height;
|
||||
}
|
||||
|
||||
if (!this.available.isEmpty()) {
|
||||
this.available.draw(x, y);
|
||||
y += this.available.getSize().height;
|
||||
}
|
||||
|
||||
if (!this.craftingNeeded.isEmpty()) {
|
||||
this.craftingNeeded.draw(x, y);
|
||||
y += this.craftingNeeded.getSize().height;
|
||||
}
|
||||
|
||||
if (!this.outputs.isEmpty()) {
|
||||
this.outputs.draw(x, y);
|
||||
y += this.outputs.getSize().height;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (!this.outputs.isEmpty()) {
|
||||
this.outputs.draw(x, y);
|
||||
y += this.outputs.getSize().height;
|
||||
}
|
||||
|
||||
if (!this.inputs.isEmpty()) {
|
||||
this.inputs.draw(x, y);
|
||||
y += this.inputs.getSize().height;
|
||||
}
|
||||
|
||||
if (!this.craftingNeeded.isEmpty()) {
|
||||
this.craftingNeeded.draw(x, y);
|
||||
y += this.craftingNeeded.getSize().height;
|
||||
}
|
||||
|
||||
if (!this.available.isEmpty()) {
|
||||
this.available.draw(x, y);
|
||||
y += this.available.getSize().height;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.remainder.isEmpty()) {
|
||||
this.remainder.draw(x, y);
|
||||
}
|
||||
line.setLabelColor(labelColor);
|
||||
line.setAmountRenderer(amountRenderer);
|
||||
|
||||
this.lines.add(line);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -48,11 +48,7 @@ nei.bookmark.recipe.toggle_collapse=Toggle Collapse/Expand
|
||||
nei.bookmark.recipe.chat_link=Send Recipe to Chat
|
||||
nei.bookmark.crafting_chain=Crafting Chain
|
||||
nei.bookmark.crafting_chain.input=Ingredients
|
||||
nei.bookmark.crafting_chain.missing=Missing Items
|
||||
nei.bookmark.crafting_chain.output=Results
|
||||
nei.bookmark.crafting_chain.remainder=Remainders
|
||||
nei.bookmark.crafting_chain.needed=Required Crafts
|
||||
nei.bookmark.crafting_chain.available=Available Items
|
||||
nei.bookmark.tree.title=Crafting Tree
|
||||
nei.bookmark.tree.empty=No crafting chain to display
|
||||
nei.bookmark.tree.overlay=Use for recipe tree
|
||||
@@ -284,9 +280,6 @@ nei.options.inventory.bookmarks.enabled.false=Hidden
|
||||
nei.options.inventory.bookmarks.animation=REI Style Animation in Bookmarks
|
||||
nei.options.inventory.bookmarks.animation.true=Yes
|
||||
nei.options.inventory.bookmarks.animation.false=No
|
||||
nei.options.inventory.bookmarks.recipeChainDir=Crafting Chain Info Direction
|
||||
nei.options.inventory.bookmarks.recipeChainDir.0=Input First
|
||||
nei.options.inventory.bookmarks.recipeChainDir.1=Output First
|
||||
nei.options.inventory.bookmarks.recipeTooltipsMode=Show Recipe Tooltips in Bookmarks
|
||||
nei.options.inventory.bookmarks.recipeTooltipsMode.0=None
|
||||
nei.options.inventory.bookmarks.recipeTooltipsMode.1=In Horizontal View
|
||||
|
||||
@@ -23,8 +23,6 @@ nei.bookmark.group.pull_items_shift=Переместить недостающи
|
||||
nei.bookmark.group.chat_link=Отправить группу в чат
|
||||
nei.bookmark.crafting_chain=Цепочка крафта
|
||||
nei.bookmark.crafting_chain.input=Ингредиенты
|
||||
nei.bookmark.crafting_chain.output=Результаты
|
||||
nei.bookmark.crafting_chain.remainder=Остатки
|
||||
|
||||
nei.itempanel.quantity.default=Одна стопка
|
||||
nei.itempanel.loading=Загрузка списка предметов...
|
||||
@@ -184,9 +182,6 @@ nei.options.inventory.bookmarks.enabled.false=Скрытая
|
||||
nei.options.inventory.bookmarks.animation=Анимация в стиле REI в закладках
|
||||
nei.options.inventory.bookmarks.animation.true=Да
|
||||
nei.options.inventory.bookmarks.animation.false=Нет
|
||||
nei.options.inventory.bookmarks.recipeChainDir=Направление информации о цепочке крафта
|
||||
nei.options.inventory.bookmarks.recipeChainDir.0=Сначала ингредиенты
|
||||
nei.options.inventory.bookmarks.recipeChainDir.1=Сначала результат
|
||||
nei.options.inventory.bookmarks.recipeTooltipsMode=Показывать подсказки рецептов в закладках
|
||||
nei.options.inventory.bookmarks.recipeTooltipsMode.0=Нет
|
||||
nei.options.inventory.bookmarks.recipeTooltipsMode.1=В горизонтальном виде
|
||||
|
||||
@@ -47,11 +47,7 @@ nei.bookmark.recipe.toggle_collapse=Згорнути/Розгорнути
|
||||
nei.bookmark.recipe.chat_link=Надіслати рецепт у чат
|
||||
nei.bookmark.crafting_chain=Ланцюжок крафту
|
||||
nei.bookmark.crafting_chain.input=Інгредієнти
|
||||
nei.bookmark.crafting_chain.missing=Відсутні предмети
|
||||
nei.bookmark.crafting_chain.output=Результати
|
||||
nei.bookmark.crafting_chain.remainder=Залишки
|
||||
nei.bookmark.crafting_chain.needed=Необхідні крафти
|
||||
nei.bookmark.crafting_chain.available=Доступні предмети
|
||||
nei.inventory.search.placeholder=Пошук...
|
||||
nei.itempanel.quantity.default=Один стек
|
||||
nei.itempanel.loading=Завантаження списку предметів...
|
||||
@@ -236,9 +232,6 @@ nei.options.inventory.bookmarks.enabled.false=Прихована
|
||||
nei.options.inventory.bookmarks.animation=Анімація закладок у стилі REI
|
||||
nei.options.inventory.bookmarks.animation.true=Так
|
||||
nei.options.inventory.bookmarks.animation.false=Ні
|
||||
nei.options.inventory.bookmarks.recipeChainDir=Напрямок ланцюжка крафту
|
||||
nei.options.inventory.bookmarks.recipeChainDir.0=Спочатку інгредієнти
|
||||
nei.options.inventory.bookmarks.recipeChainDir.1=Спочатку результат
|
||||
nei.options.inventory.bookmarks.recipeTooltipsMode=Показувати підказки рецептів у закладках
|
||||
nei.options.inventory.bookmarks.recipeTooltipsMode.0=Ніколи
|
||||
nei.options.inventory.bookmarks.recipeTooltipsMode.1=У горизонтальному вигляді
|
||||
|
||||
Reference in new issue
Block a user