mirror of
https://github.com/GTNewHorizons/NotEnoughItems.git
synced 2026-11-08 12:34:46 +00:00
769 lines
28 KiB
Java
769 lines
28 KiB
Java
package codechicken.nei.recipe.debug;
|
|
|
|
import java.awt.Point;
|
|
import java.io.File;
|
|
import java.io.FileOutputStream;
|
|
import java.io.IOException;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.LinkedHashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.function.BiConsumer;
|
|
import java.util.function.Consumer;
|
|
import java.util.function.IntPredicate;
|
|
import java.util.regex.Matcher;
|
|
import java.util.stream.Collectors;
|
|
|
|
import net.minecraft.client.gui.inventory.GuiContainer;
|
|
import net.minecraft.util.EnumChatFormatting;
|
|
|
|
import org.apache.commons.io.IOUtils;
|
|
import org.lwjgl.input.Keyboard;
|
|
import org.lwjgl.opengl.GL11;
|
|
|
|
import codechicken.lib.gui.GuiDraw;
|
|
import codechicken.lib.vec.Rectangle4i;
|
|
import codechicken.nei.Button;
|
|
import codechicken.nei.ClientHandler;
|
|
import codechicken.nei.NEIClientConfig;
|
|
import codechicken.nei.NEIClientUtils;
|
|
import codechicken.nei.Widget;
|
|
import codechicken.nei.api.API;
|
|
import codechicken.nei.drawable.DrawableBuilder;
|
|
import codechicken.nei.drawable.DrawableResource;
|
|
import codechicken.nei.guihook.GuiContainerManager;
|
|
import codechicken.nei.guihook.IContainerTooltipHandler;
|
|
import codechicken.nei.recipe.GuiRecipe;
|
|
import codechicken.nei.recipe.GuiRecipeButton;
|
|
import codechicken.nei.recipe.GuiRecipeTab;
|
|
import codechicken.nei.recipe.HandlerInfo;
|
|
import codechicken.nei.recipe.IRecipeHandler;
|
|
import codechicken.nei.recipe.RecipeHandlerRef;
|
|
import codechicken.nei.recipe.ShapedRecipeHandler;
|
|
import codechicken.nei.recipe.TemplateRecipeHandler;
|
|
import codechicken.nei.recipe.TemplateRecipeHandler.RecipeTransferRect;
|
|
import codechicken.nei.recipe.widget.RecipeWidget;
|
|
import codechicken.nei.scroll.ScrollContainer;
|
|
|
|
public class DebugHandlerWidget extends Widget implements IContainerTooltipHandler {
|
|
|
|
private static class HandlerInfoRecord {
|
|
|
|
public HandlerInfo info;
|
|
public String handlerKey;
|
|
public int yShift;
|
|
public int width;
|
|
public int height;
|
|
public boolean multiWidgets;
|
|
public int order;
|
|
public boolean allowOverflowX;
|
|
public boolean allowOverflowY;
|
|
public boolean showFavorites;
|
|
public boolean showOverlay;
|
|
public boolean showBadge;
|
|
|
|
private String csvLine;
|
|
|
|
public HandlerInfoRecord(String handlerKey, HandlerInfo info) {
|
|
this.info = info;
|
|
this.handlerKey = handlerKey;
|
|
this.yShift = info.getYShift();
|
|
this.width = info.getWidth();
|
|
this.height = info.getHeight();
|
|
this.multiWidgets = info.isMultipleWidgetsAllowed();
|
|
this.order = NEIClientConfig.handlerOrdering.getOrDefault(handlerKey, 0);
|
|
this.allowOverflowX = info.isAllowOverflowX();
|
|
this.allowOverflowY = info.isAllowOverflowY();
|
|
this.showFavorites = info.getShowFavoritesButton();
|
|
this.showOverlay = info.getShowOverlayButton();
|
|
this.showBadge = info.getShowBadge();
|
|
this.csvLine = toCsvLine();
|
|
}
|
|
|
|
public void apply() {
|
|
this.info.setYShift(this.yShift);
|
|
this.info.setHandlerDimensions(this.width, this.height);
|
|
this.info.setMultipleWidgetsAllowed(this.multiWidgets);
|
|
this.info.setAllowOverflowX(this.allowOverflowX);
|
|
this.info.setAllowOverflowY(this.allowOverflowY);
|
|
this.info.setShowFavoritesButton(this.showFavorites);
|
|
this.info.setShowOverlayButton(this.showOverlay);
|
|
this.info.setShowBadge(this.showBadge);
|
|
NEIClientConfig.handlerOrdering.put(this.handlerKey, this.order);
|
|
}
|
|
|
|
public void apply(String csvLine) {
|
|
final String[] parts = csvLine.split(",");
|
|
|
|
this.yShift = intOrDefault(parts[1], this.yShift);
|
|
this.height = intOrDefault(parts[2], this.height);
|
|
this.width = intOrDefault(parts[3], this.width);
|
|
this.multiWidgets = intOrDefault(parts[4], this.multiWidgets ? 1 : 0) == 1;
|
|
this.order = intOrDefault(parts[5], this.order);
|
|
this.allowOverflowX = intOrDefault(parts[6], this.allowOverflowX ? 1 : 0) == 1;
|
|
this.allowOverflowY = intOrDefault(parts[7], this.allowOverflowY ? 1 : 0) == 1;
|
|
this.showFavorites = intOrDefault(parts[8], this.showFavorites ? 1 : 0) == 1;
|
|
this.showOverlay = intOrDefault(parts[9], this.showOverlay ? 1 : 0) == 1;
|
|
this.showBadge = intOrDefault(parts[10], this.showBadge ? 1 : 0) == 1;
|
|
|
|
apply();
|
|
}
|
|
|
|
public String toCsvLine() {
|
|
return String.join(
|
|
",",
|
|
this.handlerKey,
|
|
String.valueOf(this.yShift),
|
|
String.valueOf(this.height),
|
|
String.valueOf(this.width),
|
|
String.valueOf(this.multiWidgets ? 1 : 0),
|
|
String.valueOf(this.order),
|
|
String.valueOf(this.allowOverflowX ? 1 : 0),
|
|
String.valueOf(this.allowOverflowY ? 1 : 0),
|
|
String.valueOf(this.showFavorites ? 1 : 0),
|
|
String.valueOf(this.showOverlay ? 1 : 0),
|
|
String.valueOf(this.showBadge ? 1 : 0));
|
|
}
|
|
|
|
public boolean isUnmodified() {
|
|
return this.csvLine.equals(this.toCsvLine());
|
|
}
|
|
|
|
private int intOrDefault(String str, int defaultValue) {
|
|
if (str == null || str.isEmpty()) return defaultValue;
|
|
try {
|
|
return Integer.parseInt(str);
|
|
} catch (NumberFormatException e) {
|
|
return defaultValue;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static final int WINDOW_WIDTH = 176;
|
|
private static final int LINE_HEIGHT = 16;
|
|
private static final int INLINE_PADDING = 6;
|
|
private static final int LABEL_WIDTH = 50;
|
|
|
|
private static final String TOOLTIP_PREFIX = "debug.RecipeHandler.";
|
|
private static final String HEADER = "HandlerId,YShift,Height,Width,MultiWidgets,Order,AllowOverflowX,AllowOverflowY,ShowFavorites,ShowOverlay,ShowBadge";
|
|
private final int[] COLORS = new int[] { 0x2200FF00, 0x22FF0000, 0x220000FF, 0x2200FFFF, 0x22FF00FF, 0x22FFFF00 };
|
|
|
|
public static DebugHandlerWidget instance = new DebugHandlerWidget();
|
|
|
|
private ScrollContainer container = new ScrollContainer();
|
|
private final Map<String, IUpdatableWidget> values = new LinkedHashMap<>();
|
|
private Map<String, HandlerInfoRecord> patches = new HashMap<>();
|
|
|
|
private HandlerInfoRecord record;
|
|
private RecipeWidget hoveredRecipe;
|
|
private boolean duplicatesOnly = false;
|
|
private String duplicatesHandlerId;
|
|
|
|
private Point dragPoint = null;
|
|
private boolean showWidget = false;
|
|
private Button resetButton;
|
|
|
|
private final DrawableResource BG_TEXTURE = new DrawableBuilder(
|
|
"nei:textures/gui/recipebg.png",
|
|
0,
|
|
0,
|
|
176 + TRANSPARENCY_BORDER * 2,
|
|
166 + TRANSPARENCY_BORDER * 2)
|
|
.setSlices(
|
|
BORDER_PADDING + TRANSPARENCY_BORDER,
|
|
BORDER_PADDING + TRANSPARENCY_BORDER,
|
|
BORDER_PADDING + TRANSPARENCY_BORDER,
|
|
BORDER_PADDING + TRANSPARENCY_BORDER)
|
|
.build();
|
|
private static final int BORDER_PADDING = 6;
|
|
private static final int TRANSPARENCY_BORDER = 4;
|
|
|
|
protected DebugHandlerWidget() {
|
|
GuiContainerManager.addTooltipHandler(this);
|
|
|
|
this.w = WINDOW_WIDTH;
|
|
this.x = 10;
|
|
this.y = 50;
|
|
this.z = 4;
|
|
|
|
this.container.x = this.x + INLINE_PADDING;
|
|
this.container.y = this.y + 5 + LINE_HEIGHT;
|
|
this.container.w = this.w - INLINE_PADDING * 2;
|
|
|
|
int y = 0;
|
|
y = addInfoWidget("Name", y);
|
|
y = addInfoWidget("Id", y);
|
|
y = addInfoWidget("Key", y);
|
|
y = addInfoWidget("HHack", y);
|
|
y = addInfoWidget("ModName", y);
|
|
y = addInfoWidget("ModId", y);
|
|
y = addOverrideInfoWidget("Override", y);
|
|
|
|
y = addTextFieldWidget("Order", 0, (field, oldText) -> {
|
|
record.order = field.getInteger();
|
|
saveHandlerInfoPatch();
|
|
}, null, y);
|
|
|
|
y = addTextFieldWidget("yShift", 0, (field, oldText) -> {
|
|
record.yShift = field.getInteger();
|
|
saveHandlerInfoPatch();
|
|
}, null, y);
|
|
|
|
y = addCheckboxWidget("MultiWidgets", button -> {
|
|
record.multiWidgets = button.value;
|
|
saveHandlerInfoPatch();
|
|
}, y);
|
|
|
|
final LabelWidget readonly = new LabelWidget(0xffffff, true);
|
|
|
|
readonly.y = y;
|
|
readonly.w = 57;
|
|
readonly.x = this.w - INLINE_PADDING * 2 - readonly.w;
|
|
this.values.put("height_readonly", readonly);
|
|
|
|
y = addTextFieldWidget("Height", HandlerInfo.DEFAULT_HEIGHT, (field, oldText) -> {
|
|
record.height = field.getInteger();
|
|
saveHandlerInfoPatch();
|
|
}, newValue -> newValue > 0, y);
|
|
|
|
y = addTextFieldWidget("Width", HandlerInfo.DEFAULT_WIDTH, (field, oldText) -> {
|
|
record.width = field.getInteger();
|
|
saveHandlerInfoPatch();
|
|
}, newValue -> newValue >= HandlerInfo.DEFAULT_WIDTH, y);
|
|
|
|
y = addCheckboxWidget("AllowOverflowX", button -> {
|
|
record.allowOverflowX = button.value;
|
|
saveHandlerInfoPatch();
|
|
}, y);
|
|
|
|
y = addCheckboxWidget("AllowOverflowY", button -> {
|
|
record.allowOverflowY = button.value;
|
|
saveHandlerInfoPatch();
|
|
}, y);
|
|
|
|
y = addCheckboxWidget("ShowFavorites", button -> {
|
|
record.showFavorites = button.value;
|
|
saveHandlerInfoPatch();
|
|
}, y);
|
|
|
|
y = addCheckboxWidget("ShowOverlay", button -> {
|
|
record.showOverlay = button.value;
|
|
saveHandlerInfoPatch();
|
|
}, y);
|
|
|
|
y = addCheckboxWidget("ShowBadge", button -> {
|
|
record.showBadge = button.value;
|
|
saveHandlerInfoPatch();
|
|
}, y);
|
|
|
|
if (Boolean.getBoolean("nei.recipeOrigins")) {
|
|
y = addCheckboxWidget("DuplicatesOnly", button -> {
|
|
this.duplicatesOnly = button.value;
|
|
|
|
if (NEIClientUtils.getGuiContainer() instanceof GuiRecipe<?>recipe) {
|
|
this.duplicatesHandlerId = getHandlerID(recipe.getHandler());
|
|
recipe.forceRefreshPage();
|
|
}
|
|
}, y + LINE_HEIGHT / 2);
|
|
|
|
// only the handler the checkbox was toggled on is filtered, so switching handlers does not pay for a rescan
|
|
API.addRecipeFilter(() -> this.duplicatesOnly ? this::isDuplicate : null);
|
|
}
|
|
|
|
this.h = 10 + LINE_HEIGHT + y;
|
|
this.container.h = this.h - INLINE_PADDING * 2 - LINE_HEIGHT;
|
|
}
|
|
|
|
private int addInfoWidget(String key, int y) {
|
|
final LabelWidget label = new LabelWidget(0x888888, false);
|
|
final LabelWidget value = new LabelWidget(0xffffff, true);
|
|
|
|
label.y = value.y = y;
|
|
label.w = LABEL_WIDTH;
|
|
value.x = LABEL_WIDTH + 5;
|
|
value.w = this.w - INLINE_PADDING * 2 - value.x;
|
|
|
|
label.updateValue(NEIClientUtils.translate(TOOLTIP_PREFIX + key));
|
|
|
|
this.container.addWidget(label);
|
|
this.container.addWidget(value);
|
|
this.values.put(key.toLowerCase(), value);
|
|
|
|
return y + value.h + 1;
|
|
}
|
|
|
|
private int addTextFieldWidget(String key, int defaultValue, BiConsumer<IntegerField, String> onChange,
|
|
IntPredicate validator, int y) {
|
|
final LabelWidget label = new LabelWidget(0x888888, false);
|
|
final IntegerField value = new IntegerField(key, onChange, validator, defaultValue);
|
|
|
|
label.y = value.y = y;
|
|
value.w = 60;
|
|
value.x = this.w - INLINE_PADDING * 2 - value.w;
|
|
label.w = value.x;
|
|
|
|
label.updateValue(NEIClientUtils.translate(TOOLTIP_PREFIX + key));
|
|
|
|
this.container.addWidget(label);
|
|
this.container.addWidget(value);
|
|
|
|
this.values.put(key.toLowerCase(), value);
|
|
|
|
return y + value.h + 1;
|
|
}
|
|
|
|
private int addCheckboxWidget(String key, Consumer<CheckboxWidget> onChange, int y) {
|
|
final LabelWidget label = new LabelWidget(0x888888, false);
|
|
final CheckboxWidget value = new CheckboxWidget(onChange);
|
|
|
|
label.y = value.y = y;
|
|
value.w = 58;
|
|
value.x = this.w - INLINE_PADDING * 2 - value.w - 1;
|
|
label.w = value.x;
|
|
|
|
label.updateValue(NEIClientUtils.translate(TOOLTIP_PREFIX + key));
|
|
|
|
this.container.addWidget(label);
|
|
this.container.addWidget(value);
|
|
this.values.put(key.toLowerCase(), value);
|
|
|
|
return y + value.h + 1;
|
|
}
|
|
|
|
private int addOverrideInfoWidget(String key, int y) {
|
|
final LabelWidget label = new LabelWidget(0x888888, false);
|
|
final LabelWidget value = new LabelWidget(0xffffff, true);
|
|
this.resetButton = new Button(NEIClientUtils.translate("debug.RecipeHandler.reset")) {
|
|
|
|
@Override
|
|
public boolean onButtonPress(boolean rightclick) {
|
|
if (record != null) {
|
|
record.apply(record.csvLine);
|
|
saveHandlerInfoPatch();
|
|
record = null;// force update of button state
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public void draw(int mousex, int mousey) {
|
|
this.state = record != null && record.isUnmodified() ? 2 : 0;
|
|
super.draw(mousex, mousey);
|
|
}
|
|
};
|
|
|
|
this.resetButton.w = 58;
|
|
this.resetButton.h = 16;
|
|
this.resetButton.y = label.y = value.y = y;
|
|
this.resetButton.x = this.w - INLINE_PADDING * 2 - this.resetButton.w - 1;
|
|
|
|
label.w = LABEL_WIDTH;
|
|
value.x = LABEL_WIDTH + 5;
|
|
value.w = this.resetButton.x - value.x - 2;
|
|
|
|
label.updateValue(NEIClientUtils.translate(TOOLTIP_PREFIX + key));
|
|
|
|
this.container.addWidget(label);
|
|
this.container.addWidget(value);
|
|
this.values.put(key.toLowerCase(), value);
|
|
|
|
this.container.addWidget(this.resetButton);
|
|
|
|
return y + value.h + 1;
|
|
}
|
|
|
|
@Override
|
|
public void draw(int mx, int my) {
|
|
|
|
if (this.record != null) {
|
|
GL11.glColor4f(1F, 1F, 1F, 1F);
|
|
GL11.glScaled(1, 1, 2f);
|
|
GL11.glDisable(GL11.GL_DEPTH_TEST);
|
|
BG_TEXTURE.draw(
|
|
this.x - TRANSPARENCY_BORDER,
|
|
this.y - TRANSPARENCY_BORDER,
|
|
this.w + TRANSPARENCY_BORDER * 2,
|
|
this.h + TRANSPARENCY_BORDER * 2);
|
|
GuiDraw.drawRect(
|
|
this.x + INLINE_PADDING,
|
|
this.y + BORDER_PADDING,
|
|
this.w - INLINE_PADDING * 2,
|
|
12,
|
|
0x30000000);
|
|
GuiDraw.drawStringC(
|
|
NEIClientUtils.translate("debug.RecipeHandler.title"),
|
|
this.x + this.w / 2,
|
|
this.y + BORDER_PADDING + 2,
|
|
0xffffff);
|
|
|
|
this.container.draw(mx, my);
|
|
|
|
GL11.glScaled(1, 1, 1 / 2f);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void update() {
|
|
final GuiContainer gui = NEIClientUtils.getGuiContainer();
|
|
|
|
if (this.showWidget && gui instanceof GuiRecipe<?>recipe) {
|
|
|
|
if (this.record == null || !this.record.handlerKey.equals(getHandlerID(recipe.getHandler()))) {
|
|
final IRecipeHandler handler = recipe.getHandler();
|
|
this.record = this.patches.computeIfAbsent(
|
|
getHandlerID(handler),
|
|
handlerKey -> new HandlerInfoRecord(handlerKey, GuiRecipeTab.getHandlerInfo(handler)));
|
|
final boolean isHeightHackApplied = NEIClientConfig.heightHackHandlerRegex.stream()
|
|
.map(pattern -> pattern.matcher(handler.getHandlerId())).anyMatch(Matcher::matches);
|
|
|
|
this.values.get("name").updateValue(handler.getRecipeName());
|
|
this.values.get("id").updateValue(handler.getOverlayIdentifier());
|
|
this.values.get("key").updateValue(handler.getHandlerId());
|
|
this.values.get("hhack").updateValue(
|
|
isHeightHackApplied ? NEIClientUtils.translate("debug.RecipeHandler.yes")
|
|
: NEIClientUtils.translate("debug.RecipeHandler.no"));
|
|
this.values.get("modname").updateValue(this.record.info.getModName());
|
|
this.values.get("modid").updateValue(this.record.info.getModId());
|
|
|
|
this.values.get("order").updateValue(String.valueOf(this.record.order));
|
|
this.values.get("yshift").updateValue(String.valueOf(this.record.yShift));
|
|
this.values.get("height").updateValue(String.valueOf(this.record.height));
|
|
this.values.get("height_readonly").updateValue(String.valueOf(this.record.height));
|
|
this.values.get("width").updateValue(String.valueOf(this.record.width));
|
|
|
|
this.values.get("multiwidgets").updateValue(String.valueOf(this.record.multiWidgets));
|
|
this.values.get("allowoverflowx").updateValue(String.valueOf(this.record.allowOverflowX));
|
|
this.values.get("allowoverflowy").updateValue(String.valueOf(this.record.allowOverflowY));
|
|
|
|
this.values.get("showfavorites").updateValue(String.valueOf(this.record.showFavorites));
|
|
this.values.get("showoverlay").updateValue(String.valueOf(this.record.showOverlay));
|
|
this.values.get("showbadge").updateValue(String.valueOf(this.record.showBadge));
|
|
|
|
updateOverride();
|
|
|
|
if (this.values.get("duplicatesonly") instanceof CheckboxWidget duplicates) {
|
|
duplicates.state = handler instanceof ShapedRecipeHandler ? 0 : 2;
|
|
resetDuplicatesOnly();
|
|
}
|
|
|
|
this.container.removeIf(
|
|
widget -> this.values.get("height") == widget || this.values.get("height_readonly") == widget);
|
|
if (handler.getRecipeHeight(0) > 0) {
|
|
this.container.addWidget((Widget) this.values.get("height_readonly"));
|
|
} else {
|
|
this.container.addWidget((Widget) this.values.get("height"));
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
this.record = null;
|
|
this.showWidget = false;
|
|
resetDuplicatesOnly();
|
|
}
|
|
|
|
this.container.update();
|
|
}
|
|
|
|
private void resetDuplicatesOnly() {
|
|
if (!this.duplicatesOnly) return;
|
|
|
|
this.duplicatesOnly = false;
|
|
|
|
if (this.values.get("duplicatesonly") instanceof CheckboxWidget duplicates) {
|
|
duplicates.updateValue("false");
|
|
}
|
|
|
|
if (NEIClientUtils.getGuiContainer() instanceof GuiRecipe<?>recipe) {
|
|
recipe.forceRefreshPage();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public List<String> handleTooltip(int mx, int my, List<String> tooltip) {
|
|
return this.record != null ? this.container.handleTooltip(mx, my, tooltip) : tooltip;
|
|
}
|
|
|
|
@Override
|
|
public Map<String, String> handleHotkeys(int mousex, int mousey, Map<String, String> hotkeys) {
|
|
return this.record != null ? this.container.handleHotkeys(mousex, mousey, hotkeys) : hotkeys;
|
|
}
|
|
|
|
@Override
|
|
public boolean handleKeyPress(int keyID, char keyChar) {
|
|
|
|
if (NEIClientConfig.getBooleanSetting("inventory.guirecipe.handlerInfo") && keyID == Keyboard.KEY_D
|
|
&& NEIClientUtils.shiftKey()) {
|
|
this.showWidget = !this.showWidget;
|
|
return true;
|
|
} else if (this.record != null) {
|
|
|
|
if (this.container.handleKeyPress(keyID, keyChar)) {
|
|
return true;
|
|
}
|
|
|
|
this.container.lastKeyTyped(keyID, keyChar);
|
|
|
|
return this.container.isFocused();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean onHotkeyPressed() {
|
|
return this.record != null && this.container.onHotkeyPressed();
|
|
}
|
|
|
|
@Override
|
|
public void onGuiClick(int mx, int my) {
|
|
if (this.record != null) {
|
|
this.container.onGuiClick(mx, my);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean handleClick(int mx, int my, int button) {
|
|
|
|
if (this.record != null) {
|
|
|
|
if (new Rectangle4i(this.x + INLINE_PADDING, this.y + BORDER_PADDING, this.w - INLINE_PADDING * 2, 12)
|
|
.contains(mx, my)) {
|
|
this.dragPoint = new Point(mx, my);
|
|
}
|
|
|
|
this.container.handleClick(mx, my, button);
|
|
}
|
|
|
|
return this.record != null;
|
|
}
|
|
|
|
@Override
|
|
public boolean contains(int px, int py) {
|
|
return this.record != null && super.contains(px, py);
|
|
}
|
|
|
|
@Override
|
|
public void mouseUp(int mx, int my, int button) {
|
|
this.dragPoint = null;
|
|
|
|
if (this.record != null) {
|
|
this.container.mouseUp(mx, my, button);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean onMouseWheel(int scrolled, int mousex, int mousey) {
|
|
|
|
if (this.record != null && contains(mousex, mousey)) {
|
|
this.container.onMouseWheel(scrolled, mousex, mousey);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean handleClickExt(int mx, int my, int button) {
|
|
return this.record != null && this.container.handleClickExt(mx, my, button);
|
|
}
|
|
|
|
@Override
|
|
public void mouseDragged(int mx, int my, int button, long heldTime) {
|
|
if (this.dragPoint != null) {
|
|
this.x -= this.dragPoint.x - mx;
|
|
this.y -= this.dragPoint.y - my;
|
|
|
|
this.container.y = this.y + INLINE_PADDING + LINE_HEIGHT;
|
|
this.container.x = this.x + INLINE_PADDING;
|
|
|
|
this.dragPoint.move(mx, my);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public List<String> handleTooltip(GuiContainer gui, int mousex, int mousey, List<String> tooltip) {
|
|
final RecipeWidget widget = this.hoveredRecipe;
|
|
this.hoveredRecipe = null;
|
|
|
|
if (widget == null || !this.showWidget || !tooltip.isEmpty()) {
|
|
return tooltip;
|
|
}
|
|
|
|
final RecipeHandlerRef ref = widget.getRecipeHandlerRef();
|
|
|
|
for (List<String> origin : RecipeOrigins.findOrigins(ref.handler, ref.recipeIndex)) {
|
|
addOriginLines(tooltip, origin);
|
|
}
|
|
|
|
return tooltip;
|
|
}
|
|
|
|
private static void addOriginLines(List<String> tooltip, List<String> lines) {
|
|
tooltip.add(
|
|
EnumChatFormatting.WHITE + NEIClientUtils.translate("debug.RecipeHandler.RegisteredBy", lines.get(0))
|
|
+ GuiDraw.TOOLTIP_LINESPACE);
|
|
|
|
for (int i = 1; i < lines.size(); i++) {
|
|
tooltip.add(EnumChatFormatting.GRAY + lines.get(i));
|
|
}
|
|
|
|
tooltip.add("");
|
|
}
|
|
|
|
// only the handler the checkbox was toggled on is filtered
|
|
private boolean isDuplicate(IRecipeHandler handler, int recipeIndex) {
|
|
return !getHandlerID(handler).equals(this.duplicatesHandlerId)
|
|
|| RecipeOrigins.hasDuplicates(handler, recipeIndex);
|
|
}
|
|
|
|
public void drawGuiPlaceholder(RecipeWidget widget) {
|
|
if (!this.showWidget) return;
|
|
|
|
final Point mouse = GuiDraw.getMousePosition();
|
|
if (widget.getRecipeHandlerRef().handler instanceof ShapedRecipeHandler && widget.contains(mouse.x, mouse.y)
|
|
&& widget.getStackMouseOver(mouse.x, mouse.y) == null) {
|
|
this.hoveredRecipe = widget;
|
|
}
|
|
|
|
NEIClientUtils.gl2DRenderContext(() -> {
|
|
|
|
// background
|
|
GuiDraw.drawRect(
|
|
widget.x,
|
|
widget.y,
|
|
widget.w,
|
|
widget.h,
|
|
COLORS[widget.getRecipeHandlerRef().recipeIndex % COLORS.length]);
|
|
|
|
// center cross
|
|
GuiDraw.drawRect(widget.x + widget.w / 2 - 1, widget.y, 1, widget.h, 0x88ffffff);
|
|
GuiDraw.drawRect(widget.x, widget.y + widget.h / 2 - 1, widget.w, 1, 0x88ffffff);
|
|
|
|
// blue-line-top (grid-top)
|
|
GuiDraw.drawRect(widget.x + 14, widget.y + 5, widget.w - 38, 1, 0xff0000aa);
|
|
|
|
// blue-line-bottom {grid-bottom}
|
|
GuiDraw.drawRect(widget.x + 14, widget.y + widget.h - 7, widget.w - 38, 1, 0xff0000aa);
|
|
|
|
// blue-left (grid start)
|
|
GuiDraw.drawRect(widget.x + 24, widget.y + (widget.h - 16) / 2, 1, 16, 0xffaa00aa);
|
|
|
|
// purple (before favorite)
|
|
GuiDraw.drawRect(
|
|
widget.x + Math.min(168, widget.w) - 27,
|
|
widget.y + widget.h - 6 - GuiRecipeButton.BUTTON_HEIGHT * 2 - 4,
|
|
GuiRecipeButton.BUTTON_WIDTH,
|
|
1,
|
|
0xffaa00aa);
|
|
|
|
// green ()
|
|
GuiDraw.drawRect(
|
|
widget.x + Math.min(168, widget.w) - 35,
|
|
widget.y + widget.h - 6 - GuiRecipeButton.BUTTON_HEIGHT - 3,
|
|
20,
|
|
1,
|
|
0xff00aa00);
|
|
|
|
// purple space before bottom grid
|
|
GuiDraw.drawRect(
|
|
widget.x + 14,
|
|
widget.y + widget.h - 7 - GuiRecipeButton.BUTTON_WIDTH / 2,
|
|
38,
|
|
1,
|
|
0xffaa00aa);
|
|
|
|
if (widget.getRecipeHandlerRef().handler instanceof TemplateRecipeHandler handler) {
|
|
int yShift = widget.getHandlerInfo().getYShift();
|
|
|
|
for (RecipeTransferRect rect : handler.transferRects) {
|
|
GuiDraw.drawRect(
|
|
widget.x + rect.getRect().x,
|
|
widget.y + yShift + rect.getRect().y,
|
|
rect.getRect().width,
|
|
rect.getRect().height,
|
|
0x40ff0000);
|
|
}
|
|
}
|
|
|
|
});
|
|
}
|
|
|
|
public void loadHandlerInfoPatch() {
|
|
|
|
ClientHandler.loadSettingsFile("handlers.patch", lines -> {
|
|
final List<String> linesList = lines.collect(Collectors.toCollection(ArrayList::new));
|
|
|
|
if (linesList.isEmpty() || !HEADER.equals(linesList.get(0))) {
|
|
return;
|
|
}
|
|
|
|
linesList.remove(0);
|
|
|
|
for (String line : linesList) {
|
|
final String[] parts = line.split(",");
|
|
final String handlerKey = parts[0];
|
|
final HandlerInfoRecord record = patches.computeIfAbsent(
|
|
handlerKey,
|
|
key -> new HandlerInfoRecord(
|
|
key,
|
|
GuiRecipeTab.handlerMap.getOrDefault(key, GuiRecipeTab.DEFAULT_HANDLER_INFO)));
|
|
record.apply((line + ",null,null,null,null,null,null,null,null,null,null"));
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
private void saveHandlerInfoPatch() {
|
|
final List<String> lines = new ArrayList<>();
|
|
lines.add(HEADER);
|
|
|
|
for (HandlerInfoRecord record : patches.values()) {
|
|
if (!record.csvLine.equals(record.toCsvLine())) {
|
|
lines.add(record.toCsvLine());
|
|
}
|
|
}
|
|
|
|
final File path = new File(NEIClientConfig.configDir, "handlers.patch");
|
|
|
|
try (FileOutputStream output = new FileOutputStream(path)) {
|
|
IOUtils.writeLines(lines, "\n", output, StandardCharsets.UTF_8);
|
|
} catch (IOException e) {}
|
|
|
|
if (this.record != null) {
|
|
updateOverride();
|
|
record.apply();
|
|
}
|
|
|
|
if (NEIClientUtils.getGuiContainer() instanceof GuiRecipe<?>recipe) {
|
|
recipe.forceRefreshPage();
|
|
}
|
|
}
|
|
|
|
private void updateOverride() {
|
|
this.container.removeIf(widget -> widget == this.resetButton);
|
|
|
|
if (this.record.isUnmodified()) {
|
|
this.values.get("override").updateValue(NEIClientUtils.translate("debug.RecipeHandler.no"));
|
|
} else {
|
|
this.values.get("override")
|
|
.updateValue(EnumChatFormatting.RED + NEIClientUtils.translate("debug.RecipeHandler.yes"));
|
|
this.container.addWidget(this.resetButton);
|
|
}
|
|
}
|
|
|
|
private String getHandlerID(IRecipeHandler handler) {
|
|
|
|
if (!GuiRecipeTab.handlerMap.containsKey(handler.getHandlerId()) && handler instanceof TemplateRecipeHandler
|
|
&& handler.getOverlayIdentifier() != null) {
|
|
return handler.getOverlayIdentifier();
|
|
}
|
|
|
|
return handler.getHandlerId();
|
|
}
|
|
|
|
}
|