fix: handle the click event before NEI,

- support find recipe and usage for fluid.
- avoid NPE for get fluid's mod name.
- optimize NEI item click logic
This commit is contained in:
Discreater committed 2021-05-04 01:06:13 +08:00
1 parent dd20d0eb1a
commit f141891b3e
9 files changed
+187 -54

No files matched your search

@@ -96,12 +96,12 @@ public class JecaGui extends GuiContainer {
if (diff != 0)
gui.root.onScroll(gui, mouseX, mouseY, diff);
} else if (Mouse.getEventButtonState()) {
if (gui.root.onClicked(gui, mouseX, mouseY, button))
if (gui.root.onClicked(gui, mouseX, mouseY, button)) {
return true;
else if (gui.hand != ILabel.EMPTY) {
gui.hand = ILabel.EMPTY;
} else if (gui.hand != ILabel.EMPTY) {
gui.hand = button == 0 ? NEIPlugin.getLabelUnderMouse() : ILabel.EMPTY;
return true;
} else {
} else if (button == 0) {
ILabel e = NEIPlugin.getLabelUnderMouse();
if (e != ILabel.EMPTY) {
gui.hand = e;
@@ -171,8 +171,7 @@ public class JecaGui extends GuiContainer {
public static JecaGui getCurrent() {
GuiScreen gui = Minecraft.getMinecraft().currentScreen;
JecaGui ret = gui instanceof JecaGui ? (JecaGui) gui : null;
Objects.requireNonNull(ret);
return ret;
return Objects.requireNonNull(ret);
}
private static void displayGuiUnsafe(boolean updateParent, boolean acceptsTransfer, IGui root) {
@@ -267,6 +266,7 @@ public class JecaGui extends GuiContainer {
@Override
// modified from vanilla
public void drawHoveringText(List lines, int x, int y, FontRenderer font) {
//noinspection unchecked
List<String> textLines = (List<String>) lines;
if (!textLines.isEmpty()) {
GlStateManager.disableRescaleNormal();
@@ -347,11 +347,12 @@ public class JecaGui extends GuiContainer {
}
public void drawFluid(Fluid f, int xPos, int yPos, int xSize, int ySize) {
IIcon fluidStillIcon = f.getStillIcon();
IIcon fluidIcon = f.getFlowingIcon();
if(fluidIcon == null) fluidIcon = f.getStillIcon();
mc.renderEngine.bindTexture(TextureMap.locationBlocksTexture);
setColor(f.getColor() & 0x00FFFFFF);
if (fluidStillIcon != null)
drawTexturedModelRectFromIcon(xPos, yPos, fluidStillIcon, xSize, ySize);
if (fluidIcon != null)
drawTexturedModelRectFromIcon(xPos, yPos, fluidIcon, xSize, ySize);
}
public void drawRectangle(int xPos, int yPos, int xSize, int ySize, int color) {
@@ -366,10 +367,10 @@ public class JecaGui extends GuiContainer {
GlStateManager.color(f, f1, f2, f3);
GlStateManager.disableAlpha();
tessellator.startDrawingQuads();
tessellator.addVertex((double) xPos, (double) bottom, 0.0D);
tessellator.addVertex((double) right, (double) bottom, 0.0D);
tessellator.addVertex((double) right, (double) yPos, 0.0D);
tessellator.addVertex((double) xPos, (double) yPos, 0.0D);
tessellator.addVertex(xPos, bottom, 0.0D);
tessellator.addVertex(right, bottom, 0.0D);
tessellator.addVertex(right, yPos, 0.0D);
tessellator.addVertex(xPos, yPos, 0.0D);
tessellator.draw();
GlStateManager.enableAlpha();
GlStateManager.enableTexture2D();
@@ -1,5 +1,6 @@
package me.towdium.jecalculation.gui.guis;
import codechicken.nei.PositionedStack;
import codechicken.nei.recipe.IRecipeHandler;
import me.towdium.jecalculation.data.Controller;
import me.towdium.jecalculation.data.label.ILabel;
@@ -55,8 +56,8 @@ public class GuiRecipe extends WContainer implements IGui {
Controller.addRecipe(group.getText(), toRecipe());
JecaGui.displayParent();
});
WButton label = new WButtonIcon(45, 32, 20, 20, BTN_LABEL, "recipe.label")
.setListener(i -> JecaGui.displayGui(new GuiLabel((l) -> {
WButton label = new WButtonIcon(45, 32, 20, 20, BTN_LABEL, "recipe.label").setListener(
i -> JecaGui.displayGui(new GuiLabel((l) -> {
JecaGui.displayParent();
JecaGui.getCurrent().hand = l;
})));
@@ -147,19 +148,22 @@ public class GuiRecipe extends WContainer implements IGui {
disambCache = new HashMap<>();
// input
recipe.getIngredientStacks(recipeIndex).stream()
.map((positionedStack) -> positionedStack.items)
.forEach(i -> merge(input, Arrays.asList(i), recipe));
recipe.getIngredientStacks(recipeIndex)
.stream()
.map((positionedStack) -> positionedStack.items)
.forEach(i -> merge(input, Arrays.asList(i), recipe));
// output
merge(output, Arrays.asList(recipe.getResultStack(recipeIndex).items), recipe);
PositionedStack resultStack = recipe.getResultStack(recipeIndex);
if (resultStack != null)
merge(output, Arrays.asList(resultStack.items), recipe);
// catalyst. Ignore multiple catalyst
NEIPlugin.getCatalyst(recipe).map(ILabel.Converter::from).ifPresent(catalyst -> {
this.catalyst.setLabel(catalyst, 0);
});
NEIPlugin.getCatalyst(recipe)
.map(ILabel.Converter::from)
.ifPresent(catalyst -> this.catalyst.setLabel(catalyst, 0));
// other. Unused. For example fuel in furnaces.
recipe.getOtherStacks(recipeIndex).stream();
// recipe.getOtherStacks(recipeIndex).stream();
this.input.setLabel(sort(input, 0), 0);
this.output.setLabel(sort(output, 21), 0);
@@ -167,7 +171,9 @@ public class GuiRecipe extends WContainer implements IGui {
}
private void merge(ArrayList<Trio<ILabel, CostList, CostList>> dst, List<ItemStack> gi, IRecipeHandler context) {
List<ILabel> list = gi.stream().map(ILabel.Converter::from).filter(i -> i != ILabel.EMPTY)
List<ILabel> list = gi.stream()
.map(ILabel.Converter::from)
.filter(i -> i != ILabel.EMPTY)
.collect(Collectors.toList());
if (list.isEmpty())
return;
@@ -2,20 +2,22 @@ package me.towdium.jecalculation.gui.guis.pickers;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import me.towdium.jecalculation.gui.Resource;
import me.towdium.jecalculation.gui.guis.IGui;
import me.towdium.jecalculation.gui.widgets.*;
import me.towdium.jecalculation.data.label.ILabel;
import me.towdium.jecalculation.data.label.labels.LFluidStack;
import me.towdium.jecalculation.data.label.labels.LOreDict;
import me.towdium.jecalculation.gui.guis.IGui;
import me.towdium.jecalculation.gui.widgets.WIcon;
import me.towdium.jecalculation.gui.widgets.WLabel;
import me.towdium.jecalculation.gui.widgets.WLabelScroll;
import me.towdium.jecalculation.gui.widgets.WSearch;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.oredict.OreDictionary;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import static me.towdium.jecalculation.gui.Resource.ICN_TEXT;
/**
@@ -26,11 +28,12 @@ import static me.towdium.jecalculation.gui.Resource.ICN_TEXT;
@SideOnly(Side.CLIENT)
public class PickerSimple extends IPicker.Impl implements IGui {
/**
* @param labels label to be displayed for selection
* @param labels label to be displayed for selection
*/
public PickerSimple(List<ILabel> labels) {
WLabelScroll ls = new WLabelScroll(7, 33, 8, 7, WLabel.Mode.PICKER, true).setLabels(labels)
.setListener((i, v) -> notifyLsnr(i.get(v)));
.setListener((i, v) -> notifyLsnr(
i.get(v)));
add(new WSearch(26, 7, 90, ls));
add(new WIcon(7, 7, 20, 20, ICN_TEXT, "common.search"));
add(ls);
@@ -39,8 +42,13 @@ public class PickerSimple extends IPicker.Impl implements IGui {
public static class FluidStack extends PickerSimple {
public FluidStack() {
super(FluidRegistry.getRegisteredFluids().entrySet().stream()
.map(e -> new LFluidStack(1000, e.getValue())).collect(Collectors.toList()));
super(FluidRegistry.getRegisteredFluids()
.values()
.stream()
// filter the fluid with no icon
.filter(fluid -> fluid.getStillIcon() != null || fluid.getFlowingIcon() != null)
.map(fluid -> new LFluidStack(1000, fluid))
.collect(Collectors.toList()));
}
}
@@ -52,7 +60,8 @@ public class PickerSimple extends IPicker.Impl implements IGui {
static List<ILabel> generate() {
return Arrays.stream(OreDictionary.getOreNames())
.filter(i -> !OreDictionary.getOres(i).isEmpty())
.map(LOreDict::new).collect(Collectors.toList());
.map(LOreDict::new)
.collect(Collectors.toList());
}
}
}
@@ -5,11 +5,14 @@ import codechicken.nei.recipe.GuiCraftingRecipe;
import codechicken.nei.recipe.GuiUsageRecipe;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import me.towdium.jecalculation.JustEnoughCalculation;
import me.towdium.jecalculation.data.label.ILabel;
import me.towdium.jecalculation.gui.JecaGui;
import me.towdium.jecalculation.gui.Resource;
import me.towdium.jecalculation.utils.IllegalPositionException;
import me.towdium.jecalculation.utils.Utilities;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
@@ -118,16 +121,19 @@ public class WLabel implements IWidget {
} else
return false;
case RESULT:
// open NEI
// open NEI recipe gui
Object item = label.getRepresentation();
if (item != null) {
if ((item instanceof ItemStack || item instanceof FluidStack)) {
String id = item instanceof ItemStack ? "item" : "liquid";
if (button == 0) {
GuiCraftingRecipe.openRecipeGui("item", item);
GuiCraftingRecipe.openRecipeGui(id, item);
return true;
} else if (button == 1) {
GuiUsageRecipe.openRecipeGui("item", item);
GuiUsageRecipe.openRecipeGui(id, item);
return true;
}
} else if (item != null) {
JustEnoughCalculation.logger.warn("unknown label representation " + item);
}
return false;
case PICKER:
@@ -5,16 +5,22 @@ import codechicken.nei.api.IConfigureNEI;
import me.towdium.jecalculation.JustEnoughCalculation;
import me.towdium.jecalculation.gui.JecaGui;
import java.util.stream.Stream;
public class NEICalculatorConfig implements IConfigureNEI {
@Override
public void loadConfig() {
System.out.println("loaded nei config");
String [] recipeType = new String[]{ "crafting", "crafting2x2", "smelting", "fuel", "brewing"};
for (String ident : recipeType) {
API.registerGuiOverlay(JecaGui.class, ident);
API.registerGuiOverlayHandler(JecaGui.class, new JecaOverlayHandler(), ident);
}
String[] baseOverlayIdentifiers = new String[]{"crafting", "crafting2x2", "smelting", "fuel", "brewing"};
String[] ae2OverlayIdentifiers = new String[]{"inscriber", "grindstone"};
/* For the recipeHandlers which extend `TemplateRecipeHandler` without override the `getOverlayIdentifier` function */
String[] nullOverlayIdentifiers = new String[]{null};
Stream.of(baseOverlayIdentifiers, ae2OverlayIdentifiers, nullOverlayIdentifiers)
.flatMap(Stream::of)
.forEach(ident -> {
API.registerGuiOverlay(JecaGui.class, ident);
API.registerGuiOverlayHandler(JecaGui.class, new JecaOverlayHandler(), ident);
});
}
@Override
@@ -0,0 +1,59 @@
package me.towdium.jecalculation.utils;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
@ParametersAreNonnullByDefault
final public class OptionalEither<L, R> {
public static <L, R> OptionalEither<L, R> left(L value) {
return new OptionalEither<>(Optional.of(value), Optional.empty());
}
public static <L, R> OptionalEither<L, R> right(R value) {
return new OptionalEither<>(Optional.empty(), Optional.of(value));
}
public static <L, R> OptionalEither<L, R> empty() {
return new OptionalEither<>(Optional.empty(), Optional.empty());
}
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
private final Optional<L> left;
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
private final Optional<R> right;
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
private OptionalEither(Optional<L> l, Optional<R> r) {
left = l;
right = r;
}
public <T> Optional<T> map(Function<? super L, ? extends T> lFunc, Function<? super R, ? extends T> rFunc) {
if(left.isPresent()){
return left.map(lFunc);
} else if(right.isPresent()){
return right.map(rFunc);
} else {
return Optional.empty();
}
}
public <T> OptionalEither<T, R> mapLeft(Function<? super L, ? extends T> lFunc) {
return new OptionalEither<>(left.map(lFunc), right);
}
public <T> OptionalEither<L, T> mapRight(Function<? super R, ? extends T> rFunc) {
return new OptionalEither<>(left, right.map(rFunc));
}
public void apply(Consumer<? super L> lFunc, Consumer<? super R> rFunc) {
left.ifPresent(lFunc);
right.ifPresent(rFunc);
}
public boolean isPresent() {
return left.isPresent() || right.isPresent();
}
}
@@ -4,6 +4,7 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.registry.GameData;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
@@ -17,9 +18,11 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.IIcon;
import net.minecraftforge.fluids.Fluid;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.text.WordUtils;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
@@ -77,7 +80,8 @@ public class Utilities {
public static String repeat(String s, int n) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) sb.append(s);
for (int i = 0; i < n; i++)
sb.append(s);
return sb.toString();
}
@@ -89,13 +93,46 @@ public class Utilities {
return id.equals("minecraft") ? "Minecraft" : Loader.instance().getIndexedModList().get(id).getName();
}
/**
* If fluid is lava or water, return 'Minecraft'.
* If has still icon or flowing icon, get the icon name, or return 'unknown';
* The icon name should be similar to 'modId:fluidId', then get the modId.
* Use the mod id to find in mod list, if not found, use the capitalized mod id to find in mod list;
* If still not found, return the capitalized mod id
* @param fluid fluid
* @return mod name
*/
public static String getModName(Fluid fluid) {
String name = fluid.getName();
if (name.equals("lava") || name.equals("water"))
return "Minecraft";
else
return Loader.instance().getIndexedModList().get(fluid.getStillIcon().getIconName().split(":")[0])
.getName();
else {
IIcon icon = getFluidIcon(fluid);
if (icon == null) {
return "Unknown";
}
String iconName = icon.getIconName();
String modId = iconName.split(":")[0];
Map<String, ModContainer> indexedModList = Loader.instance().getIndexedModList();
ModContainer modContainer = indexedModList.get(modId);
if(modContainer == null) {
String capitalizedModId =WordUtils.capitalize(modId);
modContainer = indexedModList.get(capitalizedModId);
if(modContainer == null) {
return capitalizedModId;
}
}
return modContainer.getName();
}
}
private static IIcon getFluidIcon(Fluid fluid) {
IIcon icon = fluid.getFlowingIcon();
if(icon == null) {
icon = fluid.getStillIcon();
}
return icon;
}
public static NBTTagCompound getTag(ItemStack is) {
@@ -114,7 +151,8 @@ public class Utilities {
@Nullable
public V get(K a, K b) {
V ret = data.get(new Pair<>(a, b));
if (ret == null) ret = data.get(new Pair<>(b, a));
if (ret == null)
ret = data.get(new Pair<>(b, a));
return ret;
}
}
@@ -318,10 +356,12 @@ public class Utilities {
}
public boolean push(T obj, boolean replace) {
if (replace) data.pop();
if (replace)
data.pop();
boolean ret = data.removeIf(t -> tester != null ? tester.test(t, obj) : t.equals(obj));
data.addFirst(obj);
if (data.size() > limit) data.removeLast();
if (data.size() > limit)
data.removeLast();
return ret;
}
@@ -423,6 +463,7 @@ public class Utilities {
w.sb.append('[');
if (wrap)
w.indent++;
//noinspection unchecked
for (NBTBase i : (List<NBTBase>) tags.tagList) {
if (first)
first = false;
@@ -467,4 +508,10 @@ public class Utilities {
else
return new Locale(parts[0], parts[1], parts[2]);
}
public static String[] mergeStringArrays(String[] ...arrays){
return Stream.of(arrays)
.flatMap(Stream::of)
.toArray(String[]::new);
}
}