Move RecipeTransferRectHandler out of TemplateRecipeHandler and tidy up PositionedStack (#1106)

This commit is contained in:
slprime authored and GitHub committed 2026-11-03 20:35:40 +02:00
1 parent ae0d6c6108
commit 9411541fd8
9 files changed
+216 -196

No files matched your search

@@ -207,6 +207,33 @@ public class ItemList {
return filters;
}
public static ItemStack[] expandPermutations(ItemStack[] items) {
List<ItemStack> stacks = new ArrayList<>();
for (ItemStack item : items) {
if (item == null || item.getItem() == null) continue;
if (item.getItemDamage() == Short.MAX_VALUE) {
List<ItemStack> permutations = itemMap.get(item.getItem());
if (!permutations.isEmpty()) {
for (ItemStack stack : permutations) {
ItemStack toAdd = stack.copy();
toAdd.stackSize = item.stackSize;
stacks.add(toAdd);
}
} else {
ItemStack base = new ItemStack(item.getItem(), item.stackSize);
base.stackTagCompound = item.stackTagCompound;
stacks.add(base);
}
continue;
}
stacks.add(item.copy());
}
return stacks.toArray(new ItemStack[0]);
}
public static ForkJoinPool forkJoinPool;
static {
@@ -14,12 +14,8 @@ import net.minecraft.util.EnumChatFormatting;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.oredict.OreDictionary;
import org.lwjgl.opengl.GL11;
import codechicken.nei.api.ItemFilter;
import codechicken.nei.api.ItemInfo;
import codechicken.nei.drawable.DrawableBuilder;
import codechicken.nei.drawable.DrawableResource;
import codechicken.nei.guihook.GuiContainerManager;
import codechicken.nei.item.FluidDrawer;
import codechicken.nei.item.FluidDrawer.FillDirection;
@@ -70,31 +66,11 @@ public class PositionedStack implements Cloneable {
public void generatePermutations() {
if (permutated) return;
List<ItemStack> stacks = new ArrayList<>();
for (ItemStack item : items) {
if (item == null || item.getItem() == null) continue;
items = ItemList.expandPermutations(items);
if (item.getItemDamage() == Short.MAX_VALUE) {
List<ItemStack> permutations = ItemList.itemMap.get(item.getItem());
if (!permutations.isEmpty()) {
for (ItemStack stack : permutations) {
ItemStack toAdd = stack.copy();
toAdd.stackSize = item.stackSize;
stacks.add(toAdd);
}
} else {
ItemStack base = new ItemStack(item.getItem(), item.stackSize);
base.stackTagCompound = item.stackTagCompound;
stacks.add(base);
}
continue;
}
stacks.add(item.copy());
if (items.length == 0) {
items = new ItemStack[] { new ItemStack(Blocks.fire) };
}
items = stacks.toArray(new ItemStack[0]);
if (items.length == 0) items = new ItemStack[] { new ItemStack(Blocks.fire) };
permutated = true;
setPermutationToRender(0);
@@ -112,20 +88,23 @@ public class PositionedStack implements Cloneable {
return this.acceptsLabel;
}
public void setBadges(List<Badge> badges) {
public PositionedStack setBadges(List<Badge> badges) {
this.badges = badges;
return this;
}
public List<Badge> getBadges() {
return this.badges;
}
public void setTooltip(List<String> tooltip) {
public PositionedStack setTooltip(List<String> tooltip) {
this.tooltip = tooltip == null ? null : item -> tooltip;
return this;
}
public void setTooltipProvider(Function<ItemStack, List<String>> provider) {
public PositionedStack setTooltipProvider(Function<ItemStack, List<String>> provider) {
this.tooltip = provider;
return this;
}
public List<String> getTooltip() {
@@ -136,8 +115,9 @@ public class PositionedStack implements Cloneable {
return this.chance;
}
public void setChance(int chance) {
public PositionedStack setChance(int chance) {
this.chance = chance;
return this;
}
public PositionedStack copy() {
@@ -263,7 +243,6 @@ public class PositionedStack implements Cloneable {
protected int capacity = 0;
protected boolean flowingTexture = false;
protected FillDirection fillDirection = FillDirection.AUTO;
protected DrawableResource overlay;
private ItemStack cachedFluidItem;
private FluidStack cachedFluidStack;
@@ -310,19 +289,6 @@ public class PositionedStack implements Cloneable {
return this;
}
public DrawableResource getOverlay() {
return this.overlay;
}
public Tank setOverlay(String resourceLocation, int u, int v, int width, int height) {
return setOverlay(new DrawableBuilder(resourceLocation, u, v, width, height).build());
}
public Tank setOverlay(DrawableResource overlay) {
this.overlay = overlay;
return this;
}
protected FluidStack getFluidStack() {
if (this.item != this.cachedFluidItem) {
@@ -339,7 +305,7 @@ public class PositionedStack implements Cloneable {
final List<String> customTooltip = super.getTooltip();
final FluidStack fluidStack = getFluidStack();
if (fluidStack != null) {
if (fluidStack != null && this.capacity > 0) {
tooltip.add(
EnumChatFormatting.GRAY + NEIClientUtils
.translate("recipe.fluid.tank.amount", NEIClientUtils.formatFluid(fluidStack.amount)));
@@ -370,15 +336,6 @@ public class PositionedStack implements Cloneable {
fluidStack,
this.flowingTexture,
this.fillDirection);
if (this.overlay != null) {
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glDisable(GL11.GL_LIGHTING);
this.overlay.draw(this.relx, this.rely);
GL11.glEnable(GL11.GL_LIGHTING);
GL11.glDisable(GL11.GL_BLEND);
}
}
}
}
@@ -55,6 +55,10 @@ public abstract class Widget {
return bounds().contains(px, py);
}
public boolean isVisible() {
return true;
}
public ItemStack getStackMouseOver(int mx, int my) {
return null;
}
@@ -56,7 +56,7 @@ public class WidgetContainer extends Widget {
final Rectangle4i bounds = bounds();
for (Widget widget : this.widgets) {
if (widget.bounds().intersects(bounds)) {
if (widget.isVisible() && widget.bounds().intersects(bounds)) {
widget.draw(mousex, mousey);
}
}
@@ -80,7 +80,7 @@ public class WidgetContainer extends Widget {
for (int index = this.widgets.size() - 1; index >= 0; index--) {
final Widget widget = this.widgets.get(index);
if (widget.contains(mousex, mousey)) {
if (widget.isVisible() && widget.contains(mousex, mousey)) {
return widget;
}
}
@@ -113,7 +113,8 @@ public class WidgetContainer extends Widget {
for (int index = this.widgets.size() - 1; index >= 0; index--) {
final Widget widget = this.widgets.get(index);
if (!widget.contains(mousex, mousey) && widget.handleClickExt(mousex, mousey, button)) {
if (widget.isVisible() && !widget.contains(mousex, mousey)
&& widget.handleClickExt(mousex, mousey, button)) {
return true;
}
}
@@ -126,7 +127,7 @@ public class WidgetContainer extends Widget {
for (int index = this.widgets.size() - 1; index >= 0; index--) {
final Widget widget = this.widgets.get(index);
widget.mouseDragged(mousex, mousey, button, heldTime);
if (widget.isVisible()) widget.mouseDragged(mousex, mousey, button, heldTime);
}
}
@@ -135,7 +136,7 @@ public class WidgetContainer extends Widget {
for (int index = this.widgets.size() - 1; index >= 0; index--) {
final Widget widget = this.widgets.get(index);
widget.mouseUp(mousex, mousey, button);
if (widget.isVisible()) widget.mouseUp(mousex, mousey, button);
}
}
@@ -144,7 +145,7 @@ public class WidgetContainer extends Widget {
for (int index = this.widgets.size() - 1; index >= 0; index--) {
final Widget widget = this.widgets.get(index);
if (widget.handleKeyPress(keyCode, keyChar)) {
if (widget.isVisible() && widget.handleKeyPress(keyCode, keyChar)) {
return true;
}
}
@@ -157,7 +158,7 @@ public class WidgetContainer extends Widget {
for (int index = this.widgets.size() - 1; index >= 0; index--) {
final Widget widget = this.widgets.get(index);
widget.lastKeyTyped(keyID, keyChar);
if (widget.isVisible()) widget.lastKeyTyped(keyID, keyChar);
}
}
@@ -227,7 +228,7 @@ public class WidgetContainer extends Widget {
public void postDraw(int mousex, int mousey) {
for (Widget widget : this.widgets) {
widget.postDraw(mousex, mousey);
if (widget.isVisible()) widget.postDraw(mousex, mousey);
}
}
@@ -237,7 +238,7 @@ public class WidgetContainer extends Widget {
for (int index = this.widgets.size() - 1; index >= 0; index--) {
final Widget widget = this.widgets.get(index);
widget.onGuiClick(mousex, mousey);
if (widget.isVisible()) widget.onGuiClick(mousex, mousey);
}
}
@@ -253,6 +254,17 @@ public class WidgetContainer extends Widget {
return tooltip;
}
@Override
public List<String> handleItemTooltip(ItemStack itemstack, int mousex, int mousey, List<String> tooltip) {
final Widget widget = getWidgetUnderMouse(mousex, mousey);
if (widget != null) {
return widget.handleItemTooltip(itemstack, mousex, mousey, tooltip);
}
return tooltip;
}
@Override
public Map<String, String> handleHotkeys(int mousex, int mousey, Map<String, String> hotkeys) {
final Widget widget = getWidgetUnderMouse(mousex, mousey);
@@ -4,7 +4,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIClientUtils;
import codechicken.nei.api.IRecipeFilter;
import codechicken.nei.recipe.IRecipeHandler;
@@ -30,7 +30,10 @@ public class AllMultiRecipeFilter implements IRecipeFilter {
try {
if (filter != null && !filter.matches(handler, recipeIndex)) return false;
} catch (Exception e) {
NEIClientConfig.logger.error("Exception filtering " + handler + " with " + filter, e);
NEIClientUtils.errorOnce(
"filter:" + handler.getHandlerId() + ":" + filter.getClass().getName(),
"Exception filtering " + handler.getHandlerId() + " with " + filter,
e);
}
}
return true;
@@ -4,7 +4,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIClientUtils;
import codechicken.nei.api.IRecipeFilter;
import codechicken.nei.recipe.IRecipeHandler;
@@ -30,7 +30,10 @@ public class AnyMultiRecipeFilter implements IRecipeFilter {
try {
if (filter != null && filter.matches(handler, recipeIndex)) return true;
} catch (Exception e) {
NEIClientConfig.logger.error("Exception filtering " + handler + " with " + filter, e);
NEIClientUtils.errorOnce(
"filter:" + handler.getHandlerId() + ":" + filter.getClass().getName(),
"Exception filtering " + handler.getHandlerId() + " with " + filter,
e);
}
}
@@ -263,13 +263,12 @@ public abstract class GuiRecipeTab extends Widget {
NEIClientConfig.logger.info("Error setting handler dimensions for " + handler);
}
final boolean allowOverflow = record.isSet("useCustomScroll")
&& Boolean.parseBoolean(record.get("useCustomScroll"));
info.setAllowOverflowX(
record.isSet("allowOverflowX") ? Boolean.parseBoolean(record.get("allowOverflowX")) : true);
info.setAllowOverflowY(
record.isSet("allowOverflowY") ? Boolean.parseBoolean(record.get("allowOverflowY"))
: allowOverflow);
final boolean allowOverflow = booleanOrDefault(record, "useCustomScroll", false);
info.setAllowOverflowX(booleanOrDefault(record, "allowOverflowX", true));
info.setAllowOverflowY(booleanOrDefault(record, "allowOverflowY", allowOverflow));
info.setShowFavoritesButton(booleanOrDefault(record, "showFavorites", true));
info.setShowOverlayButton(booleanOrDefault(record, "showOverlay", true));
info.setShowBadge(booleanOrDefault(record, "showBadge", false));
handlerMap.put(handler, info);
NEIClientConfig.logger.info("Loaded " + handler);
}
@@ -306,6 +305,11 @@ public abstract class GuiRecipeTab extends Widget {
return info;
}
private static boolean booleanOrDefault(CSVRecord record, String name, boolean defaultValue) {
final String str = record.isSet(name) ? record.get(name) : null;
return str == null || str.isEmpty() ? defaultValue : Boolean.parseBoolean(str);
}
private static int intOrDefault(String str, int defaultValue) {
if (str == null || str.equals("")) return defaultValue;
try {
@@ -0,0 +1,108 @@
package codechicken.nei.recipe;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import net.minecraft.client.gui.inventory.GuiContainer;
import codechicken.nei.guihook.GuiContainerManager;
import codechicken.nei.guihook.IContainerInputHandler;
import codechicken.nei.guihook.IContainerTooltipHandler;
import codechicken.nei.recipe.TemplateRecipeHandler.RecipeTransferRect;
public class RecipeTransferRectHandler implements IContainerInputHandler, IContainerTooltipHandler {
private static final Map<Class<? extends GuiContainer>, Set<RecipeTransferRect>> guiMap = new ConcurrentHashMap<>();
static {
final RecipeTransferRectHandler handler = new RecipeTransferRectHandler();
GuiContainerManager.addInputHandler(handler);
GuiContainerManager.addTooltipHandler(handler);
}
public static void registerRectsToGuis(List<Class<? extends GuiContainer>> classes,
List<RecipeTransferRect> rects) {
if (classes == null) return;
for (Class<? extends GuiContainer> clazz : classes) {
guiMap.computeIfAbsent(clazz, k -> new LinkedHashSet<>()).addAll(rects);
}
}
public boolean canHandle(GuiContainer gui) {
return guiMap.containsKey(gui.getClass());
}
@Override
public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyCode) {
return false;
}
@Override
public boolean onHotkeyPressed(GuiContainer gui) {
return false;
}
@Override
public boolean mouseClicked(GuiContainer gui, int mousex, int mousey, int button) {
if (!canHandle(gui)) return false;
if (button == 0) {
return transferRect(gui, false);
} else if (button == 1) {
return transferRect(gui, true);
}
return false;
}
private boolean transferRect(GuiContainer gui, boolean usage) {
final int[] offset = RecipeInfo.getGuiOffset(gui);
return TemplateRecipeHandler.transferRect(gui, guiMap.get(gui.getClass()), offset[0], offset[1], usage);
}
@Override
public void onKeyTyped(GuiContainer gui, char keyChar, int keyID) {}
@Override
public void onMouseClicked(GuiContainer gui, int mousex, int mousey, int button) {}
@Override
public void onMouseUp(GuiContainer gui, int mousex, int mousey, int button) {}
@Override
public boolean keyTyped(GuiContainer gui, char keyChar, int keyID) {
return false;
}
@Override
public boolean mouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) {
return false;
}
@Override
public void onMouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) {}
@Override
public List<String> handleTooltip(GuiContainer gui, int mousex, int mousey, List<String> currenttip) {
if (!canHandle(gui)) return currenttip;
if (GuiContainerManager.shouldShowTooltip(gui) && currenttip.size() == 0) {
int[] offset = RecipeInfo.getGuiOffset(gui);
currenttip = TemplateRecipeHandler
.transferRectTooltip(gui, guiMap.get(gui.getClass()), offset[0], offset[1], currenttip);
}
return currenttip;
}
@Override
public Map<String, String> handleHotkeys(GuiContainer gui, int mousex, int mousey, Map<String, String> hotkeys) {
return hotkeys;
}
@Override
public void onMouseDragged(GuiContainer gui, int mousex, int mousey, int button, long heldTime) {}
}
@@ -8,10 +8,8 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
@@ -41,8 +39,6 @@ import codechicken.nei.api.IOverlayHandler;
import codechicken.nei.api.IRecipeOverlayRenderer;
import codechicken.nei.api.IStackPositioner;
import codechicken.nei.guihook.GuiContainerManager;
import codechicken.nei.guihook.IContainerInputHandler;
import codechicken.nei.guihook.IContainerTooltipHandler;
import cpw.mods.fml.common.FMLLog;
/**
@@ -273,114 +269,26 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
return rect;
}
Rectangle rect;
String outputId;
Object[] results;
public boolean contains(GuiContainer gui, int offsetx, int offsety) {
final Point pos = GuiDraw.getMousePosition();
return rect.contains(pos.x - gui.guiLeft - offsetx, pos.y - gui.guiTop - offsety);
}
public boolean open(boolean usage) {
return usage ? GuiUsageRecipe.openRecipeGui(outputId, results)
: GuiCraftingRecipe.openRecipeGui(outputId, results);
}
public Rectangle rect;
public String outputId;
public Object[] results;
}
public static class RecipeTransferRectHandler implements IContainerInputHandler, IContainerTooltipHandler {
private static final Map<Class<? extends GuiContainer>, HashSet<RecipeTransferRect>> guiMap = new ConcurrentHashMap<>();
public static void registerRectsToGuis(List<Class<? extends GuiContainer>> classes,
List<RecipeTransferRect> rects) {
if (classes == null) return;
for (Class<? extends GuiContainer> clazz : classes) {
HashSet<RecipeTransferRect> set = guiMap.computeIfAbsent(clazz, k -> new HashSet<>());
set.addAll(rects);
}
}
public boolean canHandle(GuiContainer gui) {
return guiMap.containsKey(gui.getClass());
}
@Override
public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyCode) {
return false;
}
@Override
public boolean onHotkeyPressed(GuiContainer gui) {
if (!canHandle(gui)) return false;
if (KeyManager.isKeyDown("recipe.recipe")) {
return transferRect(gui, false);
} else if (KeyManager.isKeyDown("recipe.usage")) {
return transferRect(gui, true);
}
return false;
}
@Override
public boolean mouseClicked(GuiContainer gui, int mousex, int mousey, int button) {
if (!canHandle(gui)) return false;
if (button == 0) return transferRect(gui, false);
else if (button == 1) return transferRect(gui, true);
return false;
}
private boolean transferRect(GuiContainer gui, boolean usage) {
int[] offset = RecipeInfo.getGuiOffset(gui);
return TemplateRecipeHandler.transferRect(gui, guiMap.get(gui.getClass()), offset[0], offset[1], usage);
}
@Override
public void onKeyTyped(GuiContainer gui, char keyChar, int keyID) {}
@Override
public void onMouseClicked(GuiContainer gui, int mousex, int mousey, int button) {}
@Override
public void onMouseUp(GuiContainer gui, int mousex, int mousey, int button) {}
@Override
public boolean keyTyped(GuiContainer gui, char keyChar, int keyID) {
return false;
}
@Override
public boolean mouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) {
return false;
}
@Override
public void onMouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) {}
@Override
public List<String> handleTooltip(GuiContainer gui, int mousex, int mousey, List<String> currenttip) {
if (!canHandle(gui)) return currenttip;
if (GuiContainerManager.shouldShowTooltip(gui) && currenttip.size() == 0) {
int[] offset = RecipeInfo.getGuiOffset(gui);
currenttip = TemplateRecipeHandler
.transferRectTooltip(gui, guiMap.get(gui.getClass()), offset[0], offset[1], currenttip);
}
return currenttip;
}
@Override
public List<String> handleItemDisplayName(GuiContainer gui, ItemStack itemstack, List<String> currenttip) {
return currenttip;
}
@Override
public List<String> handleItemTooltip(GuiContainer gui, ItemStack itemstack, int mousex, int mousey,
List<String> currenttip) {
return currenttip;
}
@Override
public void onMouseDragged(GuiContainer gui, int mousex, int mousey, int button, long heldTime) {}
}
static {
GuiContainerManager.addInputHandler(new RecipeTransferRectHandler());
GuiContainerManager.addTooltipHandler(new RecipeTransferRectHandler());
/**
* @deprecated moved to {@link codechicken.nei.recipe.RecipeTransferRectHandler}
*/
@Deprecated
public static class RecipeTransferRectHandler extends codechicken.nei.recipe.RecipeTransferRectHandler {
}
/**
@@ -730,25 +638,19 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
return transferRect(gui, transferRects, offset.x, offset.y, usage);
}
private static boolean transferRect(GuiContainer gui, Collection<RecipeTransferRect> transferRects, int offsetx,
static boolean transferRect(GuiContainer gui, Collection<RecipeTransferRect> transferRects, int offsetx,
int offsety, boolean usage) {
Point pos = GuiDraw.getMousePosition();
Point relMouse = new Point(pos.x - gui.guiLeft - offsetx, pos.y - gui.guiTop - offsety);
for (RecipeTransferRect rect : transferRects) {
if (rect.rect.contains(relMouse) && (usage ? GuiUsageRecipe.openRecipeGui(rect.outputId, rect.results)
: GuiCraftingRecipe.openRecipeGui(rect.outputId, rect.results)))
return true;
if (rect.contains(gui, offsetx, offsety) && rect.open(usage)) return true;
}
return false;
}
private static List<String> transferRectTooltip(GuiContainer gui, Collection<RecipeTransferRect> transferRects,
int offsetx, int offsety, List<String> currenttip) {
Point pos = GuiDraw.getMousePosition();
Point relMouse = new Point(pos.x - gui.guiLeft - offsetx, pos.y - gui.guiTop - offsety);
static List<String> transferRectTooltip(GuiContainer gui, Collection<RecipeTransferRect> transferRects, int offsetx,
int offsety, List<String> currenttip) {
for (RecipeTransferRect rect : transferRects) {
if (rect.rect.contains(relMouse)) {
if (rect.contains(gui, offsetx, offsety)) {
currenttip.add(NEIClientUtils.translate("recipe.tooltip"));
break;
}