From b05011cace47dca4c5c21d486c2e84da4d9cae9f Mon Sep 17 00:00:00 2001 From: Discreater Date: Sat, 1 May 2021 02:29:28 +0800 Subject: [PATCH] chore: refactor --- .../jecalculation/algorithm/CostList.java | 66 +++--- .../jecalculation/data/Controller.java | 2 +- .../jecalculation/data/label/ILabel.java | 143 ++++++++++--- .../data/label/labels/LFluidStack.java | 7 +- .../data/label/labels/LItemStack.java | 73 ++++++- .../data/label/labels/LOreDict.java | 26 ++- .../data/label/labels/LPlaceholder.java | 4 +- .../data/label/labels/LString.java | 78 ------- .../jecalculation/data/structure/Recipe.java | 5 + .../towdium/jecalculation/gui/Resource.java | 194 ++++++++++++------ .../jecalculation/gui/drawables/WButton.java | 4 +- .../gui/drawables/WButtonIcon.java | 16 +- .../jecalculation/gui/drawables/WIcon.java | 12 +- .../jecalculation/gui/drawables/WLabel.java | 14 +- .../gui/drawables/WLabelGroup.java | 6 +- .../gui/drawables/WSwitcher.java | 20 +- .../jecalculation/gui/guis/GuiCalculator.java | 93 ++++++--- .../gui/guis/GuiDisambiguation.java | 8 +- .../jecalculation/gui/guis/GuiRecipe.java | 111 +++++----- .../jecalculation/gui/guis/GuiSearch.java | 4 +- .../gui/guis/pickers/PickerItemStack.java | 72 +++++++ .../gui/guis/pickers/PickerPlaceholder.java | 10 +- .../gui/guis/pickers/PickerSimple.java | 4 +- .../towdium/jecalculation/nei/NEIPlugin.java | 25 +++ .../jecalculation/textures/gui/resources.png | Bin 15402 -> 19138 bytes 25 files changed, 659 insertions(+), 338 deletions(-) delete mode 100644 src/main/java/me/towdium/jecalculation/data/label/labels/LString.java create mode 100644 src/main/java/me/towdium/jecalculation/gui/guis/pickers/PickerItemStack.java diff --git a/src/main/java/me/towdium/jecalculation/algorithm/CostList.java b/src/main/java/me/towdium/jecalculation/algorithm/CostList.java index de01d44..85f8341 100644 --- a/src/main/java/me/towdium/jecalculation/algorithm/CostList.java +++ b/src/main/java/me/towdium/jecalculation/algorithm/CostList.java @@ -8,6 +8,8 @@ import me.towdium.jecalculation.utils.wrappers.Pair; import java.util.*; import java.util.stream.Collectors; +import static me.towdium.jecalculation.data.structure.Recipe.enumIoType.OUTPUT; + public class CostList { List labels; @@ -15,31 +17,40 @@ public class CostList { labels = new ArrayList<>(); } + public CostList(ILabel label) { + labels = Collections.singletonList(label.copy().multiply(-1)); + } + public CostList(List labels) { - this.labels = labels.stream().map(ILabel::copy).collect(Collectors.toList()); + this.labels = labels.stream().map(i -> i.copy().multiply(-1)).collect(Collectors.toList()); } public CostList(List positive, List negative) { labels = positive.stream().map(ILabel::copy).collect(Collectors.toList()); negative.forEach(i -> { ILabel l = i.copy(); - labels.add(l.invertAmount()); + labels.add(l.multiply(-1)); }); } public CostList(Recipe recipe) { - this(Arrays.asList(recipe.getLabel(Recipe.enumIoType.OUTPUT)), - Arrays.asList(recipe.getLabel(Recipe.enumIoType.INPUT))); + this(Arrays.stream(recipe.getLabel(OUTPUT)).filter(i -> i != ILabel.EMPTY).collect(Collectors.toList()), + Arrays.stream(recipe.getLabel(Recipe.enumIoType.INPUT)).filter(i -> i != ILabel.EMPTY) + .collect(Collectors.toList())); } @SuppressWarnings("UnusedReturnValue") public CostList merge(CostList costList, boolean add, boolean strict) { CostList ret = copy(); - costList.labels.forEach(i -> ret.labels.add(add ? i.copy() : i.copy().invertAmount())); + costList.labels.forEach(i -> ret.labels.add(add ? i.copy() : i.copy().multiply(-1))); ret.cancel(strict); return ret; } + public void multiply(int i) { + labels = labels.stream().map(j -> j.multiply(i)).collect(Collectors.toList()); + } + private void cancel(boolean strict) { for (int i = 0; i < labels.size(); i++) { for (int j = 0; j < labels.size(); j++) { @@ -70,7 +81,8 @@ public class CostList { CostList c = (CostList) obj; CostList m = c.copy(); return m.merge(this, false, true).labels.isEmpty(); - } else return false; + } else + return false; } public CostList copy() { @@ -90,7 +102,7 @@ public class CostList { public Calculator calculate() { - return new Calculator(this); + return new Calculator(); } @Override @@ -101,33 +113,32 @@ public class CostList { return hash; } - public static class Calculator { - CostList start; - ArrayList> procedure; - List catalysts; + public class Calculator { + ArrayList> procedure = new ArrayList<>(); + ArrayList catalysts = new ArrayList<>(); private int index; - public Calculator(CostList cl) { + public Calculator() { HashSet set = new HashSet<>(); - start = cl; - set.add(start); - Recipe next = find(true); + set.add(CostList.this); + Pair next = find(true); while (next != null) { CostList original = getCurrent(); - CostList difference = new CostList(next); - CostList result = original.merge(difference, false, false); + CostList difference = new CostList(next.one); + difference.multiply(next.two); + CostList result = original.merge(difference, true, false); if (set.contains(result)) next = find(false); else { set.add(result); procedure.add(new Pair<>(result, difference)); - addCatalyst(next.getLabel(Recipe.enumIoType.CATALYST)); + addCatalyst(next.one.getLabel(Recipe.enumIoType.CATALYST)); next = find(true); } } } - private Recipe find(boolean reset) { + private Pair find(boolean reset) { if (reset) index = 0; List labels = getCurrent().labels; @@ -135,9 +146,9 @@ public class CostList { ILabel label = labels.get(index); if (label.getAmount() >= 0) continue; - Optional recipe = Controller.getRecipe(label, Recipe.enumIoType.OUTPUT); + Optional recipe = Controller.getRecipe(label, OUTPUT); if (recipe.isPresent()) - return recipe.get(); + return new Pair<>(recipe.get(), recipe.get().multiplier(label, OUTPUT)); } return null; } @@ -147,7 +158,7 @@ public class CostList { for (ILabel i : labels) { for (ILabel j : catalysts) { if (j.matches(i)) { - j.setAmount(j.getAmount() + i.getAmount()); + j.setAmount(Math.max(i.getAmount(), j.getAmount())); continue LOOP; } } @@ -156,7 +167,16 @@ public class CostList { } private CostList getCurrent() { - return procedure.isEmpty() ? start : procedure.get(procedure.size() - 1).one; + return procedure.isEmpty() ? CostList.this : procedure.get(procedure.size() - 1).one; + } + + public List getCatalysts() { + return catalysts; + } + + public List getInputs() { + return getCurrent().labels.stream().filter(i -> i.getAmount() < 0).map(i -> i.copy().multiply(-1)) + .collect(Collectors.toList()); } } } diff --git a/src/main/java/me/towdium/jecalculation/data/Controller.java b/src/main/java/me/towdium/jecalculation/data/Controller.java index 2968e93..3322da3 100644 --- a/src/main/java/me/towdium/jecalculation/data/Controller.java +++ b/src/main/java/me/towdium/jecalculation/data/Controller.java @@ -27,7 +27,7 @@ import java.util.stream.Collectors; * Date: 17-10-15. */ @SideOnly(Side.CLIENT) -public class Controller { +public class Controller { // TODO record calculate amount public static final String KEY_RECIPES = "recipes"; public static final String KEY_RECENTS = "recents"; static Recipes recipesClient; diff --git a/src/main/java/me/towdium/jecalculation/data/label/ILabel.java b/src/main/java/me/towdium/jecalculation/data/label/ILabel.java index ed5556d..0107f80 100644 --- a/src/main/java/me/towdium/jecalculation/data/label/ILabel.java +++ b/src/main/java/me/towdium/jecalculation/data/label/ILabel.java @@ -2,16 +2,21 @@ package me.towdium.jecalculation.data.label; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import me.towdium.jecalculation.data.label.labels.*; +import me.towdium.jecalculation.data.label.labels.LFluidStack; +import me.towdium.jecalculation.data.label.labels.LItemStack; +import me.towdium.jecalculation.data.label.labels.LOreDict; +import me.towdium.jecalculation.data.label.labels.LPlaceholder; import me.towdium.jecalculation.gui.IWPicker; import me.towdium.jecalculation.gui.JecaGui; -import me.towdium.jecalculation.gui.guis.pickers.PickerSimple; +import me.towdium.jecalculation.gui.guis.pickers.PickerItemStack; import me.towdium.jecalculation.gui.guis.pickers.PickerPlaceholder; +import me.towdium.jecalculation.gui.guis.pickers.PickerSimple; import me.towdium.jecalculation.polyfill.mc.client.renderer.GlStateManager; import me.towdium.jecalculation.utils.Utilities; import me.towdium.jecalculation.utils.Utilities.Relation; import me.towdium.jecalculation.utils.Utilities.ReversedIterator; import me.towdium.jecalculation.utils.wrappers.Pair; +import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.fluids.FluidRegistry; @@ -19,7 +24,10 @@ import net.minecraftforge.fluids.FluidStack; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -44,19 +52,26 @@ public interface ILabel { ILabel decreaseAmount(); - ILabel invertAmount(); - - int getAmount(); - static void initClient() { CONVERTER.register(LOreDict::guess); EDITOR.register(PickerSimple.FluidStack::new, "fluid_stack", new LFluidStack(1000, FluidRegistry.WATER)); EDITOR.register(PickerSimple.OreDict::new, "ore_dict", new LOreDict("ingotIron")); EDITOR.register(PickerPlaceholder::new, "placeholder", new LPlaceholder("example", 1, true)); + EDITOR.register(PickerItemStack::new, "item_stack", + new LItemStack(new ItemStack(Items.iron_pickaxe)).setFMeta(true)); MERGER.register("itemStack", "itemStack", LItemStack::merge); - MERGER.register("oreDict", "oreDict", LOreDict::mergeOreDict); + MERGER.register("oreDict", "oreDict", LOreDict::merge); + MERGER.register("itemStack", "oreDict", LOreDict::merge); } + int getAmount(); + + ILabel multiply(int i); + + boolean acceptPercent(); + + ILabel setPercent(boolean p); + static void initServer() { DESERIALIZER.register(LFluidStack.IDENTIFIER, LFluidStack::new); DESERIALIZER.register(LItemStack.IDENTIFIER, LItemStack::new); @@ -79,6 +94,7 @@ public interface ILabel { ILabel setAmount(int amount); + // test two labels are exactly same except amount boolean matches(Object l); @SideOnly(Side.CLIENT) @@ -170,14 +186,23 @@ public interface ILabel { } } + /** + * Provides support to convert between different types of labels. + * For example, guess oreDict from list of labels. + * It can also convert ItemStack or FluidStack to ILabel + */ class Converter { ArrayList, List>> handlers = new ArrayList<>(); public static ILabel from(@Nullable Object o) { - if (o == null) return ILabel.EMPTY; - else if (o instanceof ItemStack) return new LItemStack((ItemStack) o); - else if (o instanceof FluidStack) return new LFluidStack((FluidStack) o); - else throw new RuntimeException("Unrecognized ingredient type: " + o.getClass()); + if (o == null) + return ILabel.EMPTY; + else if (o instanceof ItemStack) + return new LItemStack((ItemStack) o); + else if (o instanceof FluidStack) + return new LFluidStack((FluidStack) o); + else + throw new RuntimeException("Unrecognized ingredient type: " + o.getClass()); } public void register(Function, List> handler) { @@ -246,10 +271,20 @@ public interface ILabel { } @Override - public ILabel invertAmount() { + public ILabel multiply(int i) { return this; } + @Override + public boolean acceptPercent() { + return false; + } + + @Override + public ILabel setPercent(boolean p) { + throw new UnsupportedOperationException(); + } + @Override public int getAmount() { return 0; @@ -296,7 +331,9 @@ public interface ILabel { abstract class Impl implements ILabel { public static final String KEY_AMOUNT = "amount"; + public static final String KEY_PERCENT = "percent"; protected int amount; + protected boolean percent; @Override public String toString() { @@ -305,14 +342,17 @@ public interface ILabel { public Impl(int amount) { this.amount = amount; + percent = false; } public Impl(Impl lsa) { - this(lsa.amount); + amount = lsa.amount; + percent = lsa.percent; } public Impl(NBTTagCompound nbt) { amount = nbt.getInteger(KEY_AMOUNT); + percent = nbt.getBoolean(KEY_PERCENT); } protected int getMultiplier() { @@ -335,7 +375,8 @@ public interface ILabel { @Override public ILabel decreaseAmount() { - if (getAmount() <= getMultiplier()) return ILabel.EMPTY; + if (getAmount() <= getMultiplier()) + return ILabel.EMPTY; else { setAmount(getAmount() - getMultiplier()); return this; @@ -343,23 +384,32 @@ public interface ILabel { } @Override - public ILabel invertAmount() { - setAmount(-getAmount()); + public ILabel multiply(int i) { + setAmount(i * getAmount()); return this; } @Override @SideOnly(Side.CLIENT) public void getToolTip(List existing, boolean detailed) { - if (detailed) existing.add(FORMAT_GREY + - Utilities.I18n.format("label.common.tooltip.amount", getAmountString())); + if (detailed) + existing.add(FORMAT_GREY + Utilities.I18n.format("label.common.tooltip.amount", getAmountString())); } - @Override - public NBTTagCompound toNBTTagCompound() { - NBTTagCompound nbt = new NBTTagCompound(); - nbt.setInteger(KEY_AMOUNT, amount); - return nbt; + protected static Optional merge(Impl a, Impl b, boolean add) { + Impl ret = a.copy(); + boolean p = a.percent || b.percent; + int amountA = a.amount; + int amountB = b.amount; + if (p) { + if (!a.percent) + amountA *= 100; + if (!b.percent) + amountB *= 100; + } + ret.amount = add ? amountA + amountB : amountA - amountB; + ret.percent = p; + return Optional.of(ret.amount == 0 ? ILabel.EMPTY : ret); } @Override @@ -369,15 +419,36 @@ public interface ILabel { @Override public ILabel setAmount(int amount) { - if (amount == 0) return ILabel.EMPTY; + if (amount == 0) + return ILabel.EMPTY; this.amount = amount; return this; } @Override - @SideOnly(Side.CLIENT) - public String getAmountString() { - return getAmount() == 0 ? "" : Utilities.cutNumber(getAmount(), 5); + public NBTTagCompound toNBTTagCompound() { + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setInteger(KEY_AMOUNT, amount); + nbt.setBoolean(KEY_PERCENT, percent); + return nbt; + } + + @Override + public boolean acceptPercent() { + return true; + } + + public ILabel setPercent(boolean p) { + if (!acceptPercent()) + throw new UnsupportedOperationException(); + if (p && !percent) { + amount *= 100; + percent = true; + } else if (!p && percent) { + amount = (amount + 99) / 100; + percent = false; + } + return this; } @Override @@ -385,6 +456,22 @@ public interface ILabel { return obj instanceof Impl && amount == ((Impl) obj).amount && matches(obj); } + @Override + @SideOnly(Side.CLIENT) + public String getAmountString() { + return getAmount() == 0 ? + "" : + (percent ? Utilities.cutNumber(getAmount(), 4) + "%" : Utilities.cutNumber(getAmount(), 5)); + } + + @Override + abstract public Impl copy(); + + @Override + public boolean matches(Object l) { + return l instanceof Impl && percent == ((Impl) l).percent; + } + abstract protected void drawLabel(JecaGui gui); } } diff --git a/src/main/java/me/towdium/jecalculation/data/label/labels/LFluidStack.java b/src/main/java/me/towdium/jecalculation/data/label/labels/LFluidStack.java index 051dfc5..0218d03 100644 --- a/src/main/java/me/towdium/jecalculation/data/label/labels/LFluidStack.java +++ b/src/main/java/me/towdium/jecalculation/data/label/labels/LFluidStack.java @@ -30,6 +30,11 @@ public class LFluidStack extends ILabel.Impl { NBTTagCompound nbt; FluidStack temp; + @Override + public boolean acceptPercent() { + return false; + } + public LFluidStack(FluidStack fs) { this(fs.amount, fs.getFluid(), fs.tag); } @@ -88,7 +93,7 @@ public class LFluidStack extends ILabel.Impl { } @Override - public ILabel copy() { + public LFluidStack copy() { return new LFluidStack(this); } diff --git a/src/main/java/me/towdium/jecalculation/data/label/labels/LItemStack.java b/src/main/java/me/towdium/jecalculation/data/label/labels/LItemStack.java index b700b36..cde1aa7 100644 --- a/src/main/java/me/towdium/jecalculation/data/label/labels/LItemStack.java +++ b/src/main/java/me/towdium/jecalculation/data/label/labels/LItemStack.java @@ -4,11 +4,11 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import me.towdium.jecalculation.data.label.ILabel; import me.towdium.jecalculation.gui.JecaGui; +import me.towdium.jecalculation.gui.Resource; import me.towdium.jecalculation.utils.Utilities; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; -import net.minecraftforge.oredict.OreDictionary; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; @@ -16,6 +16,8 @@ import java.util.List; import java.util.Objects; import java.util.Optional; +import static net.minecraftforge.oredict.OreDictionary.WILDCARD_VALUE; + /** * Author: towdium * Date: 8/11/17. @@ -26,10 +28,17 @@ public class LItemStack extends ILabel.Impl { public static final String KEY_ITEM = "item"; public static final String KEY_META = "meta"; public static final String KEY_NBT = "nbt"; + public static final String KEY_FUZZY = "fuzzy"; + public static final byte FUZZY_META = 0x1; + public static final byte FUZZY_CAP = 0x2; + public static final byte FUZZY_NBT = 0x4; Item item; int meta; NBTTagCompound nbt; + boolean fMeta; + boolean fNbt; + boolean fCap; transient ItemStack temp; public LItemStack(int amount, Item item, int meta, @Nullable NBTTagCompound nbt) { @@ -49,6 +58,7 @@ public class LItemStack extends ILabel.Impl { public LItemStack(NBTTagCompound nbt) { this(nbt.getInteger(KEY_AMOUNT), Objects.requireNonNull(Item.getItemById(nbt.getInteger(KEY_ITEM))), nbt.getInteger(KEY_META), nbt.hasKey(KEY_NBT) ? nbt.getCompoundTag(KEY_NBT) : null); + fromFuzzy(nbt.getByte(KEY_FUZZY)); } private LItemStack(LItemStack lis) { @@ -65,18 +75,44 @@ public class LItemStack extends ILabel.Impl { if (a instanceof LItemStack && b instanceof LItemStack) { LItemStack lisA = (LItemStack) a; LItemStack lisB = (LItemStack) b; - boolean wildcard = lisA.meta == OreDictionary.WILDCARD_VALUE || lisB.meta == OreDictionary.WILDCARD_VALUE; - if ((Objects.equals(lisA.nbt, lisB.nbt)) && (lisA.meta == lisB.meta || wildcard)) { - LItemStack ret = new LItemStack(lisA); - if (wildcard) - ret.meta = OreDictionary.WILDCARD_VALUE; - ret.amount = add ? lisA.amount + lisB.amount : lisA.amount - lisB.amount; - return Optional.of(ret.amount == 0 ? ILabel.EMPTY : ret); + + // check meta + int resultMeta = 0; + boolean checkedMeta = true; + if (lisA.meta == WILDCARD_VALUE || lisB.meta == WILDCARD_VALUE) + resultMeta = WILDCARD_VALUE; + else if (lisA.fMeta || lisB.fMeta || lisA.meta == lisB.meta) + resultMeta = lisA.meta; + else + checkedMeta = false; + + // check nbt and cap + boolean checkedNbt = (Objects.equals(lisA.nbt, lisB.nbt)) || lisA.fNbt || lisB.fNbt; + + if (lisA.item == lisB.item && checkedMeta && checkedNbt) { + LItemStack is = lisA.copy(); + is.meta = resultMeta; + return Impl.merge(is, lisB, add); } } return Optional.empty(); } + public ILabel setFMeta(boolean f) { + fMeta = f; + return this; + } + + public ILabel setFNbt(boolean f) { + fNbt = f; + return this; + } + + public ILabel setFCap(boolean f) { + fCap = f; + return this; + } + public ItemStack getRep() { return temp; } @@ -103,13 +139,15 @@ public class LItemStack extends ILabel.Impl { public boolean matches(Object l) { if (l instanceof LItemStack) { LItemStack lis = (LItemStack) l; - return (Objects.equals(nbt, lis.nbt)) && meta == lis.meta && item == lis.item; + return (Objects.equals(nbt, lis.nbt)) && meta == lis.meta && item == lis.item + && fNbt == lis.fNbt && super.matches(l) + && fCap == lis.fCap && fMeta == lis.fMeta; } else return false; } @Override - public ILabel copy() { + public LItemStack copy() { return new LItemStack(this); } @@ -123,13 +161,28 @@ public class LItemStack extends ILabel.Impl { ret.setInteger(KEY_ITEM, id); if (nbt != null) ret.setTag(KEY_NBT, nbt); + ret.setByte(KEY_FUZZY, toFuzzy()); return ret; } + private byte toFuzzy() { + return (byte) ((fMeta ? FUZZY_META : 0) | (fCap ? FUZZY_CAP : 0) | (fNbt ? FUZZY_NBT : 0)); + } + + private void fromFuzzy(byte i) { + fMeta = (i & FUZZY_META) != 0; + fCap = (i & FUZZY_CAP) != 0; + fNbt = (i & FUZZY_NBT) != 0; + } + @Override @SideOnly(Side.CLIENT) public void drawLabel(JecaGui gui) { gui.drawItemStack(0, 0, temp, false); + if (fCap || fNbt || fMeta) gui.drawResource(Resource.LBL_FRAME, 0, 0); + if (fCap) gui.drawResource(Resource.LBL_FR_LL, 0, 0); + if (fNbt) gui.drawResource(Resource.LBL_FR_UL, 0, 0); + if (fMeta) gui.drawResource(Resource.LBL_FR_UR, 0, 0); } @Override diff --git a/src/main/java/me/towdium/jecalculation/data/label/labels/LOreDict.java b/src/main/java/me/towdium/jecalculation/data/label/labels/LOreDict.java index 9bd78da..af7a0a5 100644 --- a/src/main/java/me/towdium/jecalculation/data/label/labels/LOreDict.java +++ b/src/main/java/me/towdium/jecalculation/data/label/labels/LOreDict.java @@ -59,13 +59,27 @@ public class LOreDict extends ILabel.Impl { return Utilities.I18n.format("label.ore_dict.name", name); } - public static Optional mergeOreDict(ILabel a, ILabel b, boolean add) { + public static Optional merge(ILabel a, ILabel b, boolean add) { if (a instanceof LOreDict && b instanceof LOreDict) { LOreDict lodA = (LOreDict) a; LOreDict lodB = (LOreDict) b; - if (lodA.getName().equals(lodB.getName())) - return Optional.of(new LOreDict(lodA.getName(), - add ? lodA.getAmount() + lodB.getAmount() : lodA.getAmount() - lodB.getAmount())); + if (lodA.getName().equals(lodB.getName())) { + return Impl.merge(lodA, lodB, add); + } + } else if ((a instanceof LOreDict && b instanceof LItemStack) + || a instanceof LItemStack && b instanceof LOreDict) { + LItemStack lis; + LOreDict lor; + if (a instanceof LOreDict) { + lis = (LItemStack) b; + lor = (LOreDict) a; + } else { + lis = (LItemStack) a; + lor = (LOreDict) b; + } + return OreDictionary.getOres(lor.name).stream().map(o -> Converter.from(o).multiply(lor.amount)) + .map(i -> LItemStack.merge(i, lis, add)).filter(Optional::isPresent) + .findAny().flatMap(i -> i); } return Optional.empty(); } @@ -126,7 +140,7 @@ public class LOreDict extends ILabel.Impl { @Override public boolean matches(Object l) { - return l instanceof LOreDict && name.equals(((LOreDict) l).name); + return l instanceof LOreDict && name.equals(((LOreDict) l).name) && super.matches(l); } @Override @@ -145,7 +159,7 @@ public class LOreDict extends ILabel.Impl { }); if(list.isEmpty()) return; long index = System.currentTimeMillis() / 1500; - gui.drawResource(Resource.LBL_ORE_DICT, 0, 0); + gui.drawResource(Resource.LBL_FRAME, 0, 0); GlStateManager.pushMatrix(); GlStateManager.translate(1, 1, 0); GlStateManager.scale(14f / 16, 14f / 16, 1); diff --git a/src/main/java/me/towdium/jecalculation/data/label/labels/LPlaceholder.java b/src/main/java/me/towdium/jecalculation/data/label/labels/LPlaceholder.java index 49e0646..13898fe 100644 --- a/src/main/java/me/towdium/jecalculation/data/label/labels/LPlaceholder.java +++ b/src/main/java/me/towdium/jecalculation/data/label/labels/LPlaceholder.java @@ -90,11 +90,11 @@ public class LPlaceholder extends ILabel.Impl { @Override public boolean matches(Object l) { - return l instanceof LPlaceholder && name.equals(((LPlaceholder) l).name); + return l instanceof LPlaceholder && name.equals(((LPlaceholder) l).name) && super.matches(l); } @Override - public ILabel copy() { + public LPlaceholder copy() { return new LPlaceholder(this); } diff --git a/src/main/java/me/towdium/jecalculation/data/label/labels/LString.java b/src/main/java/me/towdium/jecalculation/data/label/labels/LString.java deleted file mode 100644 index 1f0d341..0000000 --- a/src/main/java/me/towdium/jecalculation/data/label/labels/LString.java +++ /dev/null @@ -1,78 +0,0 @@ -package me.towdium.jecalculation.data.label.labels; - -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; -import me.towdium.jecalculation.gui.JecaGui; -import me.towdium.jecalculation.gui.Resource; -import me.towdium.jecalculation.data.label.ILabel; -import me.towdium.jecalculation.utils.Utilities; -import net.minecraft.nbt.NBTTagCompound; - -import javax.annotation.ParametersAreNonnullByDefault; - -/** - * Author: towdium - * Date: 17-9-28. - */ -@ParametersAreNonnullByDefault -public class LString extends ILabel.Impl { - public static final String KEY_NAME = "name"; - public static final String IDENTIFIER = "string"; - - String name; - - public LString(NBTTagCompound tag) { - super(tag); - this.name = tag.getString(KEY_NAME); - } - - public LString(String name, int amount) { - super(amount); - this.name = name; - } - - public LString(LString label) { - super(label); - name = label.name; - } - - @Override - @SideOnly(Side.CLIENT) - public String getDisplayName() { - return Utilities.I18n.format("label.universal.name", name); - } - - @Override - public String getIdentifier() { - return "string"; - } - - @Override - public boolean matches(Object l) { - return l instanceof LString && name.equals(((LString) l).name); - } - - @Override - public ILabel copy() { - return new LString(this); - } - - @Override - public NBTTagCompound toNBTTagCompound() { - NBTTagCompound nbt = super.toNBTTagCompound(); - nbt.setString(KEY_NAME, name); - return nbt; - } - - @Override - @SideOnly(Side.CLIENT) - public void drawLabel(JecaGui gui) { - gui.drawResource(Resource.LBL_UNIV_B, 0, 0); - gui.drawResource(Resource.LBL_UNIV_F, 0, 0, (name.hashCode() * 0x131723) & 0xFFFFFF); - } - - @Override - public int hashCode() { - return name.hashCode() ^ amount; - } -} diff --git a/src/main/java/me/towdium/jecalculation/data/structure/Recipe.java b/src/main/java/me/towdium/jecalculation/data/structure/Recipe.java index 82e3706..b146b7d 100644 --- a/src/main/java/me/towdium/jecalculation/data/structure/Recipe.java +++ b/src/main/java/me/towdium/jecalculation/data/structure/Recipe.java @@ -109,6 +109,11 @@ public class Recipe { return Arrays.stream(getLabel(type)).anyMatch(i -> ILabel.MERGER.merge(label, i, true).isPresent()); } + public int multiplier(ILabel label, enumIoType type) { + return Arrays.stream(getLabel(type)).filter(i -> ILabel.MERGER.merge(label, i, true).isPresent()).findAny() + .map(i -> (i.getAmount() + Math.abs(label.getAmount()) - 1) / i.getAmount()).orElse(0); + } + public enum enumIoType { INPUT, OUTPUT, CATALYST; diff --git a/src/main/java/me/towdium/jecalculation/gui/Resource.java b/src/main/java/me/towdium/jecalculation/gui/Resource.java index 8ec7a34..ca4c4ab 100644 --- a/src/main/java/me/towdium/jecalculation/gui/Resource.java +++ b/src/main/java/me/towdium/jecalculation/gui/Resource.java @@ -16,40 +16,57 @@ import javax.annotation.ParametersAreNonnullByDefault; public class Resource { public static final ResourceLocation location = new ResourceLocation( JustEnoughCalculation.Reference.MODID, "textures/gui/resources.png"); - public static final Resource BTN_LABEL_N = new Resource(0, 14, 14, 14); - public static final Resource BTN_LABEL_F = new Resource(0, 0, 14, 14); - public static final Resource BTN_NEW_N = new Resource(14, 14, 14, 14); - public static final Resource BTN_NEW_F = new Resource(14, 0, 14, 14); - public static final Resource BTN_SEARCH_N = new Resource(28, 14, 14, 14); - public static final Resource BTN_SEARCH_F = new Resource(28, 0, 14, 14); - public static final Resource BTN_SAVE_N = new Resource(42, 14, 14, 14); - public static final Resource BTN_SAVE_F = new Resource(42, 0, 14, 14); - public static final Resource BTN_COPY_N = new Resource(56, 14, 14, 14); - public static final Resource BTN_COPY_F = new Resource(56, 0, 14, 14); - public static final Resource BTN_COPY_D = new Resource(242, 14, 14, 14); - public static final Resource BTN_DEL_N = new Resource(70, 14, 14, 14); - public static final Resource BTN_DEL_F = new Resource(70, 0, 14, 14); - public static final Resource BTN_YES_N = new Resource(84, 14, 14, 14); - public static final Resource BTN_YES_F = new Resource(84, 0, 14, 14); - public static final Resource BTN_YES_D = new Resource(228, 14, 14, 14); - public static final Resource BTN_NO_N = new Resource(98, 14, 14, 14); - public static final Resource BTN_NO_F = new Resource(98, 0, 14, 14); - public static final Resource BTN_NO_D = new Resource(228, 0, 14, 14); - public static final Resource BTN_DISAMB_N = new Resource(112, 14, 14, 14); - public static final Resource BTN_DISAMB_F = new Resource(112, 0, 14, 14); - public static final Resource BTN_DISAMB_D = new Resource(242, 0, 14, 14); - public static final Resource BTN_IN_N = new Resource(126, 14, 14, 14); - public static final Resource BTN_IN_F = new Resource(126, 0, 14, 14); - public static final Resource BTN_IN_D = new Resource(200, 0, 14, 14); - public static final Resource BTN_OUT_N = new Resource(140, 14, 14, 14); - public static final Resource BTN_OUT_F = new Resource(140, 0, 14, 14); - public static final Resource BTN_OUT_D = new Resource(214, 0, 14, 14); - public static final Resource BTN_CAT_N = new Resource(154, 14, 14, 14); - public static final Resource BTN_CAT_F = new Resource(154, 0, 14, 14); - public static final Resource BTN_CAT_D = new Resource(200, 14, 14, 14); - public static final Resource BTN_LIST_N = new Resource(168, 14, 14, 14); - public static final Resource BTN_LIST_F = new Resource(168, 0, 14, 14); - public static final Resource BTN_LIST_D = new Resource(214, 14, 14, 14); + // letters abbr for button & icon: N - normal, F - focused, D - disabled + // letters abbr for fuzzy related: N - normal, F - fuzzy + public static final Resource BTN_LABEL_N = getIcon(0, 1); + public static final Resource BTN_LABEL_F = getIcon(0, 0); + public static final Resource BTN_NEW_N = getIcon(1, 1); + public static final Resource BTN_NEW_F = getIcon(1, 0); + public static final Resource BTN_SEARCH_N = getIcon(2, 1); + public static final Resource BTN_SEARCH_F = getIcon(2, 0); + public static final Resource BTN_SAVE_N = getIcon(3, 1); + public static final Resource BTN_SAVE_F = getIcon(3, 0); + public static final Resource BTN_COPY_N = getIcon(4, 1); + public static final Resource BTN_COPY_F = getIcon(4, 0); + public static final Resource BTN_COPY_D = getIcon(4, 2); + public static final Resource BTN_DEL_N = getIcon(5, 1); + public static final Resource BTN_DEL_F = getIcon(5, 0); + public static final Resource BTN_YES_N = getIcon(6, 1); + public static final Resource BTN_YES_F = getIcon(6, 0); + public static final Resource BTN_YES_D = getIcon(6, 2); + public static final Resource BTN_NO_N = getIcon(7, 1); + public static final Resource BTN_NO_F = getIcon(7, 0); + public static final Resource BTN_NO_D = getIcon(7, 2); + public static final Resource BTN_DISAMB_N = getIcon(8, 1); + public static final Resource BTN_DISAMB_F = getIcon(8, 0); + public static final Resource BTN_DISAMB_D = getIcon(8, 2); + public static final Resource BTN_IN_N = getIcon(9, 1); + public static final Resource BTN_IN_F = getIcon(9, 0); + public static final Resource BTN_IN_D = getIcon(9, 2); + public static final Resource BTN_OUT_N = getIcon(10, 1); + public static final Resource BTN_OUT_F = getIcon(10, 0); + public static final Resource BTN_OUT_D = getIcon(10, 2); + public static final Resource BTN_CAT_N = getIcon(11, 1); + public static final Resource BTN_CAT_F = getIcon(11, 0); + public static final Resource BTN_CAT_D = getIcon(11, 2); + public static final Resource BTN_LIST_N = getIcon(12, 1); + public static final Resource BTN_LIST_F = getIcon(12, 0); + public static final Resource BTN_LIST_D = getIcon(12, 2); + public static final Resource BTN_META_N_N = getIcon(14, 0); + public static final Resource BTN_META_N_F = getIcon(13, 0); + public static final Resource BTN_META_F_N = getIcon(16, 0); + public static final Resource BTN_META_F_F = getIcon(15, 0); + public static final Resource BTN_META_D = getIcon(17, 0); + public static final Resource BTN_NBT_N_N = getIcon(14, 1); + public static final Resource BTN_NBT_N_F = getIcon(13, 1); + public static final Resource BTN_NBT_F_N = getIcon(16, 1); + public static final Resource BTN_NBT_F_F = getIcon(15, 1); + public static final Resource BTN_NBT_D = getIcon(17, 1); + public static final Resource BTN_CAP_N_N = getIcon(14, 2); + public static final Resource BTN_CAP_N_F = getIcon(13, 2); + public static final Resource BTN_CAP_F_N = getIcon(16, 2); + public static final Resource BTN_CAP_F_F = getIcon(15, 2); + public static final Resource BTN_CAP_D = getIcon(17, 2); public static final Resource WGT_BUTTON_N = new Resource(40, 232, 20, 20); public static final Resource WGT_BUTTON_F = new Resource(60, 232, 20, 20); public static final Resource WGT_BUTTON_D = new Resource(80, 232, 20, 20); @@ -66,30 +83,66 @@ public class Resource { public static final Resource WGT_ARR_R_N = new Resource(167, 242, 7, 9); public static final Resource WGT_ARR_R_D = new Resource(174, 242, 7, 9); public static final Resource WGT_SCROLL = new Resource(181, 232, 12, 15); - public static final Resource ICN_RECENT_N = new Resource(0, 42, 14, 14); - public static final Resource ICN_RECENT_F = new Resource(0, 28, 14, 14); - public static final Resource ICN_INPUT_N = new Resource(14, 42, 14, 14); - public static final Resource ICN_INPUT_F = new Resource(14, 28, 14, 14); - public static final Resource ICN_OUTPUT_N = new Resource(28, 42, 14, 14); - public static final Resource ICN_OUTPUT_F = new Resource(28, 28, 14, 14); - public static final Resource ICN_CATALYST_N = new Resource(42, 42, 14, 14); - public static final Resource ICN_CATALYST_F = new Resource(42, 28, 14, 14); - public static final Resource ICN_LIST_N = new Resource(56, 42, 14, 14); - public static final Resource ICN_LIST_F = new Resource(56, 28, 14, 14); - public static final Resource ICN_LABEL_N = new Resource(70, 42, 14, 14); - public static final Resource ICN_LABEL_F = new Resource(70, 28, 14, 14); - public static final Resource ICN_HELP_N = new Resource(84, 42, 14, 14); - public static final Resource ICN_HELP_F = new Resource(84, 28, 14, 14); - public static final Resource ICN_STACK_N = new Resource(98, 42, 14, 14); - public static final Resource ICN_STACK_F = new Resource(98, 28, 14, 14); - public static final Resource ICN_TEXT_N = new Resource(112, 42, 14, 14); - public static final Resource ICN_TEXT_F = new Resource(112, 28, 14, 14); - public static final Resource ICN_MULTI_N = new Resource(126, 42, 14, 14); - public static final Resource ICN_MULTI_F = new Resource(126, 28, 14, 14); - public static final Resource LBL_ORE_DICT = new Resource(0, 56, 16, 16); - public static final Resource LBL_FLUID = new Resource(16, 56, 16, 16); - public static final Resource LBL_UNIV_B = new Resource(32, 56, 16, 16); - public static final Resource LBL_UNIV_F = new Resource(48, 56, 16, 16); + public static final Resource ICN_RECENT_N = getIcon(0, 4); + public static final Resource ICN_RECENT_F = getIcon(0, 3); + public static final Resource ICN_INPUT_N = getIcon(1, 4); + public static final Resource ICN_INPUT_F = getIcon(1, 3); + public static final Resource ICN_OUTPUT_N = getIcon(2, 4); + public static final Resource ICN_OUTPUT_F = getIcon(2, 3); + public static final Resource ICN_CATALYST_N = getIcon(3, 4); + public static final Resource ICN_CATALYST_F = getIcon(3, 3); + public static final Resource ICN_LIST_N = getIcon(4, 4); + public static final Resource ICN_LIST_F = getIcon(4, 3); + public static final Resource ICN_LABEL_N = getIcon(5, 4); + public static final Resource ICN_LABEL_F = getIcon(5, 3); + public static final Resource ICN_HELP_N = getIcon(6, 4); + public static final Resource ICN_HELP_F = getIcon(6, 3); + public static final Resource ICN_STACK_N = getIcon(7, 4); + public static final Resource ICN_STACK_F = getIcon(7, 3); + public static final Resource ICN_TEXT_N = getIcon(8, 4); + public static final Resource ICN_TEXT_F = getIcon(8, 3); + public static final Resource ICN_MULTI_N = getIcon(9, 4); + public static final Resource ICN_MULTI_F = getIcon(9, 3); + public static final Resource LBL_FRAME = getLabel(0); + public static final Resource LBL_FLUID = getLabel(1); + public static final Resource LBL_UNIV_B = getLabel(2); + public static final Resource LBL_UNIV_F = getLabel(3); + public static final Resource LBL_FR_UL = getLabel(4); + public static final Resource LBL_FR_UR = getLabel(5); + public static final Resource LBL_FR_LL = getLabel(6); + + public static final ResourceGroup BTN_LABEL = new ResourceGroup(BTN_LABEL_N, BTN_LABEL_F); + public static final ResourceGroup BTN_NEW = new ResourceGroup(BTN_NEW_N, BTN_NEW_F); + public static final ResourceGroup BTN_SEARCH = new ResourceGroup(BTN_SEARCH_N, BTN_SEARCH_F); + public static final ResourceGroup BTN_SAVE = new ResourceGroup(BTN_SAVE_N, BTN_SAVE_F); + public static final ResourceGroup BTN_COPY = new ResourceGroup(BTN_COPY_N, BTN_COPY_F, BTN_COPY_D); + public static final ResourceGroup BTN_DEL = new ResourceGroup(BTN_DEL_N, BTN_DEL_F); + public static final ResourceGroup BTN_YES = new ResourceGroup(BTN_YES_N, BTN_YES_F, BTN_YES_D); + public static final ResourceGroup BTN_NO = new ResourceGroup(BTN_NO_N, BTN_NO_F, BTN_NO_D); + public static final ResourceGroup BTN_DISAMB = new ResourceGroup(BTN_DISAMB_N, BTN_DISAMB_F, BTN_DISAMB_D); + public static final ResourceGroup BTN_IN = new ResourceGroup(BTN_IN_N, BTN_IN_F, BTN_IN_D); + public static final ResourceGroup BTN_OUT = new ResourceGroup(BTN_OUT_N, BTN_OUT_F, BTN_OUT_D); + public static final ResourceGroup BTN_CAT = new ResourceGroup(BTN_CAT_N, BTN_CAT_F, BTN_CAT_D); + public static final ResourceGroup BTN_LIST = new ResourceGroup(BTN_LIST_N, BTN_LIST_F, BTN_LIST_D); + public static final ResourceGroup BTN_META_N = new ResourceGroup(BTN_META_N_N, BTN_META_N_F, BTN_META_D); + public static final ResourceGroup BTN_CAP_N = new ResourceGroup(BTN_CAP_N_N, BTN_CAP_N_F, BTN_CAP_D); + public static final ResourceGroup BTN_NBT_N = new ResourceGroup(BTN_NBT_N_N, BTN_NBT_N_F, BTN_NBT_D); + public static final ResourceGroup BTN_META_F = new ResourceGroup(BTN_META_F_N, BTN_META_F_F, BTN_META_D); + public static final ResourceGroup BTN_CAP_F = new ResourceGroup(BTN_CAP_F_N, BTN_CAP_F_F, BTN_CAP_D); + public static final ResourceGroup BTN_NBT_F = new ResourceGroup(BTN_NBT_F_N, BTN_NBT_F_F, BTN_NBT_D); + public static final ResourceGroup WGT_ARR_L = new ResourceGroup(WGT_ARR_L_N, WGT_ARR_L_F, WGT_ARR_L_D); + public static final ResourceGroup WGT_ARR_R = new ResourceGroup(WGT_ARR_R_N, WGT_ARR_R_F, WGT_ARR_R_D); + public static final ResourceGroup ICN_RECENT = new ResourceGroup(ICN_RECENT_N, ICN_RECENT_F); + public static final ResourceGroup ICN_INPUT = new ResourceGroup(ICN_INPUT_N, ICN_INPUT_F); + public static final ResourceGroup ICN_OUTPUT = new ResourceGroup(ICN_OUTPUT_N, ICN_OUTPUT_F); + public static final ResourceGroup ICN_CATALYST = new ResourceGroup(ICN_CATALYST_N, ICN_CATALYST_F); + public static final ResourceGroup ICN_LIST = new ResourceGroup(ICN_LIST_N, ICN_LIST_F); + public static final ResourceGroup ICN_LABEL = new ResourceGroup(ICN_LABEL_N, ICN_LABEL_F); + public static final ResourceGroup ICN_HELP = new ResourceGroup(ICN_HELP_N, ICN_HELP_F); + public static final ResourceGroup ICN_STACK = new ResourceGroup(ICN_STACK_N, ICN_STACK_F); + public static final ResourceGroup ICN_TEXT = new ResourceGroup(ICN_TEXT_N, ICN_TEXT_F); + public static final ResourceGroup ICN_MULTI = new ResourceGroup(ICN_MULTI_N, ICN_MULTI_F); + protected int xPos, yPos, xSize, ySize; protected ResourceLocation rl; @@ -124,4 +177,29 @@ public class Resource { public ResourceLocation getResourceLocation() { return rl; } + + private static Resource getIcon(int x, int y) { + return new Resource(x * 14, y * 14, 14, 14); + } + + private static Resource getLabel(int x) { + return new Resource(x * 16, 70, 16, 16); + } + + public static class ResourceGroup { + public Resource normal; + public Resource focused; + public Resource disabled; + + public ResourceGroup(Resource normal, Resource focused, Resource disabled) { + this.normal = normal; + this.focused = focused; + this.disabled = disabled; + } + + public ResourceGroup(Resource normal, Resource focused) { + this.normal = normal; + this.focused = focused; + } + } } diff --git a/src/main/java/me/towdium/jecalculation/gui/drawables/WButton.java b/src/main/java/me/towdium/jecalculation/gui/drawables/WButton.java index 2c9d607..9494373 100644 --- a/src/main/java/me/towdium/jecalculation/gui/drawables/WButton.java +++ b/src/main/java/me/towdium/jecalculation/gui/drawables/WButton.java @@ -30,12 +30,12 @@ public abstract class WButton extends WTooltip { this.ySize = ySize; } - public WButton setListenerLeft(Runnable r) { + public WButton setLsnrLeft(Runnable r) { lsnrLeft = r; return this; } - public WButton setListenerRight(Runnable r) { + public WButton setLsnrRight(Runnable r) { lsnrRight = r; return this; } diff --git a/src/main/java/me/towdium/jecalculation/gui/drawables/WButtonIcon.java b/src/main/java/me/towdium/jecalculation/gui/drawables/WButtonIcon.java index f1b403e..274bcce 100644 --- a/src/main/java/me/towdium/jecalculation/gui/drawables/WButtonIcon.java +++ b/src/main/java/me/towdium/jecalculation/gui/drawables/WButtonIcon.java @@ -20,20 +20,16 @@ import java.util.List; public class WButtonIcon extends WButton { protected Resource rNormal, rFocused, rDisabled; - public WButtonIcon(int xPos, int yPos, int xSize, int ySize, Resource normal, Resource focused) { - this(xPos, yPos, xSize, ySize, normal, focused, null, null); + public WButtonIcon(int xPos, int yPos, int xSize, int ySize, Resource.ResourceGroup res, String name) { + this(xPos, yPos, xSize, ySize, res.normal, res.focused, res.disabled, name); } - public WButtonIcon(int xPos, int yPos, int xSize, int ySize, Resource normal, Resource focused, String name) { - this(xPos, yPos, xSize, ySize, normal, focused, null, name); + public WButtonIcon(int xPos, int yPos, int xSize, int ySize, Resource.ResourceGroup res) { + this(xPos, yPos, xSize, ySize, res.normal, res.focused, res.disabled, null); } - public WButtonIcon(int xPos, int yPos, int xSize, int ySize, Resource normal, Resource focused, Resource disabled) { - this(xPos, yPos, xSize, ySize, normal, focused, disabled, null); - } - - public WButtonIcon(int xPos, int yPos, int xSize, int ySize, Resource normal, Resource focused, - @Nullable Resource disabled, @Nullable String name) { + private WButtonIcon(int xPos, int yPos, int xSize, int ySize, Resource normal, Resource focused, + @Nullable Resource disabled, @Nullable String name) { super(xPos, yPos, xSize, ySize, name); this.rNormal = normal; this.rFocused = focused; diff --git a/src/main/java/me/towdium/jecalculation/gui/drawables/WIcon.java b/src/main/java/me/towdium/jecalculation/gui/drawables/WIcon.java index bfae207..ea4f62b 100644 --- a/src/main/java/me/towdium/jecalculation/gui/drawables/WIcon.java +++ b/src/main/java/me/towdium/jecalculation/gui/drawables/WIcon.java @@ -19,12 +19,16 @@ public class WIcon extends WTooltip { public int xPos, yPos, xSize, ySize; public Resource normal, focused; - public WIcon(int xPos, int yPos, int xSize, int ySize, Resource normal, Resource focused) { - this(xPos, yPos, xSize, ySize, normal, focused, null); + public WIcon(int xPos, int yPos, int xSize, int ySize, Resource.ResourceGroup res) { + this(xPos, yPos, xSize, ySize, res.normal, res.focused, null); } - public WIcon(int xPos, int yPos, int xSize, int ySize, - Resource normal, Resource focused, @Nullable String name) { + public WIcon(int xPos, int yPos, int xSize, int ySize, Resource.ResourceGroup res, String name) { + this(xPos, yPos, xSize, ySize, res.normal, res.focused, name); + } + + private WIcon(int xPos, int yPos, int xSize, int ySize, + Resource normal, Resource focused, @Nullable String name) { super(name); this.xPos = xPos; this.yPos = yPos; diff --git a/src/main/java/me/towdium/jecalculation/gui/drawables/WLabel.java b/src/main/java/me/towdium/jecalculation/gui/drawables/WLabel.java index 66bcbbe..4162b26 100644 --- a/src/main/java/me/towdium/jecalculation/gui/drawables/WLabel.java +++ b/src/main/java/me/towdium/jecalculation/gui/drawables/WLabel.java @@ -49,8 +49,6 @@ public class WLabel implements IWidget { public void setLabel(ILabel label) { this.label = label; - // if (mode == enumMode.EDITOR || mode == enumMode.SELECTOR) - // notifyLsnr(); } @Override @@ -185,17 +183,15 @@ public class WLabel implements IWidget { WLabel wl = new WLabel(w.xPos, w.yPos, w.xSize, w.ySize, enumMode.SELECTOR); wl.setLabel(w.getLabel()); WTextField wtf = new WTextField(xAlign + 10, w.yPos + w.ySize / 2 - WTextField.HEIGHT / 2, 50); - WButton wby = new WButtonIcon(xAlign + 60, w.yPos, 20, 20, Resource.BTN_YES_N, Resource.BTN_YES_F, - Resource.BTN_YES_D).setListenerLeft(() -> { + WButton wby = new WButtonIcon(xAlign + 60, w.yPos, 20, 20, Resource.BTN_YES).setLsnrLeft(() -> { w.setLabel(wl.getLabel().setAmount( wtf.getText().isEmpty() ? 0 : Integer.parseInt(wtf.getText()))); JecaGui.getCurrent().root.remove(this); }); - WButton wbn = new WButtonIcon(xAlign + 79, w.yPos, 20, 20, Resource.BTN_NO_N, Resource.BTN_NO_F) - .setListenerLeft(() -> { - w.setLabel(ILabel.EMPTY); - JecaGui.getCurrent().root.remove(this); - }); + WButton wbn = new WButtonIcon(xAlign + 79, w.yPos, 20, 20, Resource.BTN_NO).setLsnrLeft(() -> { + w.setLabel(ILabel.EMPTY); + JecaGui.getCurrent().root.remove(this); + }); wtf.setText(Integer.toString(w.getLabel().getAmount())); wtf.setLsnrText(i -> { try { diff --git a/src/main/java/me/towdium/jecalculation/gui/drawables/WLabelGroup.java b/src/main/java/me/towdium/jecalculation/gui/drawables/WLabelGroup.java index 001a9e0..5981916 100644 --- a/src/main/java/me/towdium/jecalculation/gui/drawables/WLabelGroup.java +++ b/src/main/java/me/towdium/jecalculation/gui/drawables/WLabelGroup.java @@ -57,8 +57,12 @@ public class WLabelGroup extends WContainer { return labels.stream().map(WLabel::getLabel).collect(Collectors.toList()); } + public void setLabel(ILabel label, int index) { + labels.get(index).setLabel(label); + } + public void setLabel(List labels, int start) { - Wrapper i = new Wrapper<>(start); + Wrapper i = new Wrapper<>(start); // TODO simplify this.labels.forEach(l -> l.setLabel(i.value < labels.size() ? labels.get(i.value++) : ILabel.EMPTY)); } diff --git a/src/main/java/me/towdium/jecalculation/gui/drawables/WSwitcher.java b/src/main/java/me/towdium/jecalculation/gui/drawables/WSwitcher.java index f3307f7..4999e02 100644 --- a/src/main/java/me/towdium/jecalculation/gui/drawables/WSwitcher.java +++ b/src/main/java/me/towdium/jecalculation/gui/drawables/WSwitcher.java @@ -41,19 +41,13 @@ public class WSwitcher extends WContainer { this.xSize = xSize; this.yPos = yPos; this.keys = keys; - left = new WButtonIcon(xPos, yPos, SIZE, SIZE, Resource.WGT_ARR_L_N, Resource.WGT_ARR_L_F, Resource.WGT_ARR_L_D) - .setListenerLeft(() -> { - if (temp == null) - move(false); - else - setTemp(null); - }); - right = new WButtonIcon(xPos + xSize - SIZE, yPos, SIZE, SIZE, Resource.WGT_ARR_R_N, Resource.WGT_ARR_R_F, - Resource.WGT_ARR_R_D).setListenerLeft(() -> { - if (temp == null) - move(true); - else - setTemp(null); + left = new WButtonIcon(xPos, yPos, SIZE, SIZE, Resource.WGT_ARR_L).setLsnrLeft(() -> { + if (temp == null) move(false); + else setTemp(null); + }); + right = new WButtonIcon(xPos + xSize - SIZE, yPos, SIZE, SIZE, Resource.WGT_ARR_R).setLsnrLeft(() -> { + if (temp == null) move(true); + else setTemp(null); }); wRect = new WRectangle(xPos + SIZE, yPos, xSize - 2 * SIZE, SIZE, JecaGui.COLOR_GUI_GREY); wText = new WText(xPos + SIZE, yPos, xSize - 2 * SIZE, SIZE, JecaGui.Font.DEFAULT_SHADOW, diff --git a/src/main/java/me/towdium/jecalculation/gui/guis/GuiCalculator.java b/src/main/java/me/towdium/jecalculation/gui/guis/GuiCalculator.java index 122a48f..ff0bb1b 100644 --- a/src/main/java/me/towdium/jecalculation/gui/guis/GuiCalculator.java +++ b/src/main/java/me/towdium/jecalculation/gui/guis/GuiCalculator.java @@ -2,6 +2,7 @@ package me.towdium.jecalculation.gui.guis; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import me.towdium.jecalculation.algorithm.CostList; import me.towdium.jecalculation.gui.JecaGui; import me.towdium.jecalculation.gui.Resource; import me.towdium.jecalculation.gui.drawables.*; @@ -9,6 +10,7 @@ import me.towdium.jecalculation.data.label.ILabel; import me.towdium.jecalculation.data.Controller; import javax.annotation.ParametersAreNonnullByDefault; +import java.util.ArrayList; import java.util.List; /** @@ -18,52 +20,95 @@ import java.util.List; @ParametersAreNonnullByDefault @SideOnly(Side.CLIENT) public class GuiCalculator extends WContainer { - WLabelGroup wRecent = new WLabelGroup(7, 31, 8, 1, WLabel.enumMode.PICKER); - WLabel wLabel = new WLabel(31, 7, 20, 20, WLabel.enumMode.SELECTOR); - WButton btnSteps = new WButtonIcon(64, 62, 20, 20, Resource.BTN_LIST_N, Resource.BTN_LIST_F, - Resource.BTN_LIST_D, "calculator.step").setListenerLeft(() -> setMode(enumMode.STEPS)); - WButton btnCatalyst = new WButtonIcon(45, 62, 20, 20, Resource.BTN_CAT_N, Resource.BTN_CAT_F, - Resource.BTN_CAT_D, "calculator.catalyst").setListenerLeft(() -> setMode(enumMode.CATALYST)); - WButton btnOutput = new WButtonIcon(26, 62, 20, 20, Resource.BTN_OUT_N, Resource.BTN_OUT_F, - Resource.BTN_OUT_D, "calculator.output").setListenerLeft(() -> setMode(enumMode.OUTPUT)); - WButton btnInput = new WButtonIcon(7, 62, 20, 20, Resource.BTN_IN_N, Resource.BTN_IN_F, - Resource.BTN_IN_D, "calculator.input").setListenerLeft(() -> setMode(enumMode.INPUT)); + enumMode mode = enumMode.INPUT; + CostList.Calculator calculator = null; + WLabelGroup lgRecent = new WLabelGroup(7, 31, 8, 1, WLabel.enumMode.PICKER); + WLabel lLabel = new WLabel(31, 7, 20, 20, WLabel.enumMode.SELECTOR); + WLabelScroll lsResult = new WLabelScroll(7, 87, 8, 4, WLabel.enumMode.RESULT, true); + WButton btnSteps = new WButtonIcon(64, 62, 20, 20, Resource.BTN_LIST, "calculator.step") + .setLsnrLeft(() -> setMode(enumMode.STEPS)); + WButton btnCatalyst = new WButtonIcon(45, 62, 20, 20, Resource.BTN_CAT, "calculator.catalyst") + .setLsnrLeft(() -> setMode(enumMode.CATALYST)); + WButton btnOutput = new WButtonIcon(26, 62, 20, 20, Resource.BTN_OUT, "calculator.output") + .setLsnrLeft(() -> setMode(enumMode.OUTPUT)); + WButton btnInput = new WButtonIcon(7, 62, 20, 20, Resource.BTN_IN, "calculator.input") + .setLsnrLeft(() -> setMode(enumMode.INPUT)); + WTextField tfAmount = new WTextField(60, 7, 65); public GuiCalculator() { - wLabel.setLsnrUpdate(() -> { - Controller.setRecent(wLabel.label); + lLabel.setLsnrUpdate(() -> { + Controller.setRecent(lLabel.label); refreshRecent(); + refreshCalculator(); }); - wRecent.setLsnrUpdate(l -> JecaGui.getCurrent().hand = wRecent.getLabelAt(l)); + lgRecent.setLsnrUpdate(l -> JecaGui.getCurrent().hand = lgRecent.getLabelAt(l)); + tfAmount.setLsnrText(s -> refreshCalculator()); add(new WPanel()); - add(new WTextField(61, 7, 64)); - add(new WButtonIcon(7, 7, 20, 20, Resource.BTN_LABEL_N, Resource.BTN_LABEL_F, "calculator.label") - .setListenerLeft(() -> JecaGui.displayGui(new GuiLabel(l -> { + add(new WButtonIcon(7, 7, 20, 20, Resource.BTN_LABEL, "calculator.label") + .setLsnrLeft(() -> JecaGui.displayGui(new GuiLabel(l -> { JecaGui.displayParent(); JecaGui.getCurrent().hand = l; })))); - add(new WButtonIcon(130, 7, 20, 20, Resource.BTN_NEW_N, Resource.BTN_NEW_F, "calculator.recipe") - .setListenerLeft(() -> JecaGui.displayGui(true, true, new GuiRecipe()))); - add(new WButtonIcon(149, 7, 20, 20, Resource.BTN_SEARCH_N, Resource.BTN_SEARCH_F, "calculator.search") - .setListenerLeft(() -> JecaGui.displayGui(new GuiSearch()))); + add(new WButtonIcon(130, 7, 20, 20, Resource.BTN_NEW, "calculator.recipe") + .setLsnrLeft(() -> JecaGui.displayGui(true, true, new GuiRecipe()))); + add(new WButtonIcon(149, 7, 20, 20, Resource.BTN_SEARCH, "calculator.search") + .setLsnrLeft(() -> JecaGui.displayGui(new GuiSearch()))); + add(new WText(53, 13, JecaGui.Font.DEFAULT_NO_SHADOW, "x")); add(new WLine(55)); - add(new WIcon(151, 31, 18, 18, Resource.ICN_RECENT_N, Resource.ICN_RECENT_F, "calculator.history")); - add(new WLabelScroll(7, 87, 8, 4, WLabel.enumMode.RESULT, true)); - addAll(wRecent, wLabel, btnInput, btnOutput, btnCatalyst, btnSteps); + add(new WIcon(151, 31, 18, 18, Resource.ICN_RECENT, "calculator.history")); + addAll(lgRecent, lLabel, btnInput, btnOutput, btnCatalyst, btnSteps, lsResult, tfAmount); refreshRecent(); setMode(enumMode.INPUT); + refreshCalculator(); } void setMode(enumMode mode) { + this.mode = mode; btnInput.setDisabled(mode == enumMode.INPUT); btnOutput.setDisabled(mode == enumMode.OUTPUT); btnCatalyst.setDisabled(mode == enumMode.CATALYST); btnSteps.setDisabled(mode == enumMode.STEPS); + refreshResult(); } void refreshRecent() { List recent = Controller.getRecent(); - if (recent.size() > 1) wRecent.setLabel(recent.subList(1, recent.size()), 0); + if (!recent.isEmpty()) lLabel.setLabel(recent.get(0)); + if (recent.size() > 1) lgRecent.setLabel(recent.subList(1, recent.size()), 0); + } + + void refreshCalculator() { + try { + String s = tfAmount.getText(); + int i = s.isEmpty() ? 1 : Integer.parseInt(tfAmount.getText()); + tfAmount.setColor(JecaGui.COLOR_TEXT_WHITE); + calculator = new CostList(lLabel.getLabel().copy().setAmount(i)).calculate(); + } catch (NumberFormatException e) { + tfAmount.setColor(JecaGui.COLOR_TEXT_RED); + calculator = null; + } + refreshResult(); + } + + void refreshResult() { + if (calculator == null) { + lsResult.setLabels(new ArrayList<>()); + } else { + switch (mode) { + case INPUT: + lsResult.setLabels(calculator.getInputs()); + break; + case OUTPUT: + lsResult.setLabels(new ArrayList<>()); + break; + case CATALYST: + lsResult.setLabels(calculator.getCatalysts()); + break; + case STEPS: + lsResult.setLabels(new ArrayList<>()); + break; + } + } } enum enumMode { diff --git a/src/main/java/me/towdium/jecalculation/gui/guis/GuiDisambiguation.java b/src/main/java/me/towdium/jecalculation/gui/guis/GuiDisambiguation.java index 3470378..2d537cb 100644 --- a/src/main/java/me/towdium/jecalculation/gui/guis/GuiDisambiguation.java +++ b/src/main/java/me/towdium/jecalculation/gui/guis/GuiDisambiguation.java @@ -31,11 +31,11 @@ public class GuiDisambiguation extends IWPicker.Impl { add(new WPanel()); add(switcher); - add(new WIcon(149, 24, 20, 20, Resource.ICN_HELP_N, Resource.ICN_HELP_F, "disambiguation.help")); - add(new WIcon(7, 48, 18, 54, Resource.ICN_LIST_N, Resource.ICN_LIST_F, "disambiguation.list")); - add(new WIcon(7, 105, 18, 54, Resource.ICN_LABEL_N, Resource.ICN_LABEL_F, "disambiguation.label")); + add(new WIcon(149, 24, 20, 20, Resource.ICN_HELP, "disambiguation.help")); + add(new WIcon(7, 48, 18, 54, Resource.ICN_LIST, "disambiguation.list")); + add(new WIcon(7, 105, 18, 54, Resource.ICN_LABEL, "disambiguation.label")); add(new WSearch(i -> { - if (callback != null) callback.accept(i); + if (callback != null) callback.accept(i.copy().increaseAmount()); }, tf, lsUp, lsDown)); setPage(0); diff --git a/src/main/java/me/towdium/jecalculation/gui/guis/GuiRecipe.java b/src/main/java/me/towdium/jecalculation/gui/guis/GuiRecipe.java index 8b429a4..4d7c8a6 100644 --- a/src/main/java/me/towdium/jecalculation/gui/guis/GuiRecipe.java +++ b/src/main/java/me/towdium/jecalculation/gui/guis/GuiRecipe.java @@ -8,14 +8,13 @@ import me.towdium.jecalculation.data.structure.Recipe; import me.towdium.jecalculation.gui.JecaGui; import me.towdium.jecalculation.gui.Resource; import me.towdium.jecalculation.gui.drawables.*; +import me.towdium.jecalculation.nei.NEIPlugin; import me.towdium.jecalculation.utils.Utilities; import me.towdium.jecalculation.utils.wrappers.Pair; import me.towdium.jecalculation.utils.wrappers.Triple; import net.minecraft.item.ItemStack; import java.util.*; -import java.util.function.BiConsumer; -import java.util.function.BiFunction; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -28,66 +27,59 @@ public class GuiRecipe extends WContainer { HashMap> disambiguation = new HashMap<>(); WSwitcher switcherGroup = new WSwitcher(7, 7, 162, Controller.getGroups()); WTextField textField = new WTextField(49, 33, 119); - WButton buttonCopy = new WButtonIcon(83, 33, 20, 20, Resource.BTN_COPY_N, Resource.BTN_COPY_F, - Resource.BTN_COPY_D, "recipe.copy").setDisabled(true).setListenerLeft(() -> { + WButton buttonCopy = new WButtonIcon(83, 33, 20, 20, Resource.BTN_COPY, "recipe.copy").setLsnrLeft(() -> { Controller.addRecipe(switcherGroup.getText(), toRecipe()); JecaGui.displayParent(); }); WLabelGroup groupCatalyst = new WLabelGroup(28, 87, 7, 1, 20, 20, WLabel.enumMode.EDITOR); - WButton buttonDisamb = new WButtonIcon(121, 33, 20, 20, Resource.BTN_DISAMB_N, - Resource.BTN_DISAMB_F, Resource.BTN_DISAMB_D, "recipe.disamb").setDisabled(true).setListenerLeft(() -> { + WButton buttonDisamb = new WButtonIcon(121, 33, 20, 20, Resource.BTN_DISAMB, "recipe.disamb").setLsnrLeft(() -> { if (disambiguation != null) JecaGui.displayGui(new GuiDisambiguation(new ArrayList<>(disambiguation.values())) .setCallback(l -> { JecaGui.displayParent(); JecaGui.getCurrent().hand = l; })); - }); - WLabelGroup groupInput = new WLabelGroup(28, 111, 7, 2, 20, 20, WLabel.enumMode.EDITOR).setLsnrUpdate(i -> { + }); WLabelGroup groupInput = new WLabelGroup(28, 111, 7, 2, 20, 20, WLabel.enumMode.EDITOR).setLsnrUpdate(i -> { disambiguation.remove(i); refresh(); }); WLabelGroup groupOutput = new WLabelGroup(28, 63, 7, 1, 20, 20, WLabel.enumMode.EDITOR).setLsnrUpdate(i -> { - disambiguation.remove(i + 14); + disambiguation.remove(i + 21); refresh(); }); - WButton buttonClear = new WButtonIcon(64, 33, 20, 20, Resource.BTN_DEL_N, Resource.BTN_DEL_F, "recipe.clear") - .setListenerLeft(this::clear); - WButton buttonLabel = new WButtonIcon(45, 33, 20, 20, Resource.BTN_LABEL_N, Resource.BTN_LABEL_F, "recipe.label") - .setListenerLeft(() -> JecaGui.displayGui(new GuiLabel((l) -> { + WButton buttonClear = new WButtonIcon(64, 33, 20, 20, Resource.BTN_DEL, "recipe.clear").setLsnrLeft(this::clear); + WButton buttonLabel = new WButtonIcon(45, 33, 20, 20, Resource.BTN_LABEL, "recipe.label") + .setLsnrLeft(() -> JecaGui.displayGui(new GuiLabel((l) -> { JecaGui.displayParent(); JecaGui.getCurrent().hand = l; }))); - WButton buttonSave = new WButtonIcon(26, 33, 20, 20, Resource.BTN_SAVE_N, Resource.BTN_SAVE_F, "recipe.save") - .setListenerLeft(() -> { - if (dest == null) - Controller.addRecipe(switcherGroup.getText(), toRecipe()); - else { - if (textField.getText().equals(dest.one)) - Controller.setRecipe(dest.one, dest.two, toRecipe()); - else { - Controller.removeRecipe(dest.one, dest.two); - Controller.addRecipe(switcherGroup.getText(), toRecipe()); - } - } - JecaGui.displayParent(); - }); + WButton buttonSave = new WButtonIcon(26, 33, 20, 20, Resource.BTN_SAVE, "recipe.save").setLsnrLeft(() -> { + if (dest == null) + Controller.addRecipe(switcherGroup.getText(), toRecipe()); + else { + if (textField.getText().equals(dest.one)) + Controller.setRecipe(dest.one, dest.two, toRecipe()); + else { + Controller.removeRecipe(dest.one, dest.two); + Controller.addRecipe(switcherGroup.getText(), toRecipe()); + } + } + JecaGui.displayParent(); + }); - WButton buttonNew = new WButtonIcon(7, 33, 20, 20, Resource.BTN_NEW_N, Resource.BTN_NEW_F, "recipe.new") - .setListenerLeft(() -> setModeNewGroup(true)); - WButton buttonDel = new WButtonIcon(102, 33, 20, 20, Resource.BTN_NO_N, Resource.BTN_NO_F, Resource.BTN_NO_D, - "recipe.delete").setDisabled(true).setListenerLeft(() -> { + WButton buttonDel = new WButtonIcon(102, 33, 20, 20, Resource.BTN_NO, "recipe.delete").setLsnrLeft(() -> { Controller.removeRecipe(dest.one, dest.two); JecaGui.displayParent(); }); - WButton buttonYes = new WButtonIcon(7, 33, 20, 20, Resource.BTN_YES_N, Resource.BTN_YES_F, "recipe.confirm") - .setListenerLeft(() -> { - switcherGroup.setTemp(textField.getText()); - textField.setText(""); - setModeNewGroup(false); - }); - WButton buttonNo = new WButtonIcon(26, 33, 20, 20, Resource.BTN_NO_N, Resource.BTN_NO_F, "recipe.cancel") - .setListenerLeft(() -> setModeNewGroup(false)); + WButton buttonNew = new WButtonIcon(7, 33, 20, 20, Resource.BTN_NEW, "recipe.new") + .setLsnrLeft(() -> setModeNewGroup(true)); + WButton buttonYes = new WButtonIcon(7, 33, 20, 20, Resource.BTN_YES, "recipe.confirm").setLsnrLeft(() -> { + switcherGroup.setTemp(textField.getText()); + textField.setText(""); + setModeNewGroup(false); + }); + WButton buttonNo = new WButtonIcon(26, 33, 20, 20, Resource.BTN_NO, "recipe.cancel") + .setLsnrLeft(() -> setModeNewGroup(false)); public GuiRecipe(String group, int index) { @@ -96,19 +88,20 @@ public class GuiRecipe extends WContainer { Recipe r = Controller.getRecipe(group, index); fromRecipe(r); switcherGroup.setIndex(Controller.getGroups().indexOf(group)); - buttonCopy.setDisabled(false); - buttonDel.setDisabled(false); } public GuiRecipe() { add(new WPanel()); - add(new WIcon(7, 63, 21, 20, Resource.ICN_OUTPUT_N, Resource.ICN_OUTPUT_F, "recipe.output")); - add(new WIcon(7, 87, 21, 20, Resource.ICN_CATALYST_N, Resource.ICN_CATALYST_F, "recipe.catalyst")); - add(new WIcon(7, 111, 21, 40, Resource.ICN_INPUT_N, Resource.ICN_INPUT_F, "recipe.input")); + add(new WIcon(7, 63, 21, 20, Resource.ICN_OUTPUT, "recipe.output")); + add(new WIcon(7, 87, 21, 20, Resource.ICN_CATALYST, "recipe.catalyst")); + add(new WIcon(7, 111, 21, 40, Resource.ICN_INPUT, "recipe.input")); add(new WLine(57)); addAll(groupInput, groupCatalyst, groupOutput, switcherGroup); if (switcherGroup.getTexts().isEmpty()) switcherGroup.setTemp(Utilities.I18n.format("common.default")); setModeNewGroup(false); + buttonCopy.setDisabled(true); + buttonDel.setDisabled(true); + buttonDisamb.setDisabled(true); } public void setModeNewGroup(boolean b) { @@ -142,23 +135,30 @@ public class GuiRecipe extends WContainer { ItemStack outputStack = recipe.getResultStack(recipeIndex).item; merge(output, Stream.of(outputStack).map(ILabel.Converter::from).collect(Collectors.toList())); + // catalyst ignore multiple catalyst + NEIPlugin.getCatalyst(recipe).map(ILabel.Converter::from).ifPresent(catalyst -> { + groupCatalyst.setLabel(catalyst, 0); + }); + groupInput.setLabel(sort(input, 0, true), 0); - groupOutput.setLabel(sort(output, 14, false), 0); + groupOutput.setLabel(sort(output, 21, false), 0); refresh(); } private void merge(ArrayList> dst, List list) { - if (list.isEmpty()) return; + if (list.isEmpty()) + return; dst.stream().filter(p -> { CostList cl = new CostList(list); if (p.three.equals(cl)) { ILabel.MERGER.merge(p.one, ILabel.CONVERTER.first(list), true).ifPresent(i -> p.one = i); p.two = p.two.merge(cl, true, true); return true; - } else return false; + } else + return false; }).findAny().orElseGet(() -> { - Triple ret = new Triple<>( - ILabel.CONVERTER.first(list), new CostList(list), new CostList(list)); + Triple ret = new Triple<>(ILabel.CONVERTER.first(list), new CostList(list), + new CostList(list)); dst.add(ret); return ret; }); @@ -180,12 +180,13 @@ public class GuiRecipe extends WContainer { } void fromRecipe(Recipe r) { - groupInput.setLabel(Arrays.stream(r.getLabel(Recipe.enumIoType.INPUT)) - .map(ILabel::copy).collect(Collectors.toList()), 0); - groupCatalyst.setLabel(Arrays.stream(r.getLabel(Recipe.enumIoType.CATALYST)) - .map(ILabel::copy).collect(Collectors.toList()), 0); - groupOutput.setLabel(Arrays.stream(r.getLabel(Recipe.enumIoType.OUTPUT)) - .map(ILabel::copy).collect(Collectors.toList()), 0); + groupInput.setLabel( + Arrays.stream(r.getLabel(Recipe.enumIoType.INPUT)).map(ILabel::copy).collect(Collectors.toList()), 0); + groupCatalyst.setLabel( + Arrays.stream(r.getLabel(Recipe.enumIoType.CATALYST)).map(ILabel::copy).collect(Collectors.toList()), + 0); + groupOutput.setLabel( + Arrays.stream(r.getLabel(Recipe.enumIoType.OUTPUT)).map(ILabel::copy).collect(Collectors.toList()), 0); } diff --git a/src/main/java/me/towdium/jecalculation/gui/guis/GuiSearch.java b/src/main/java/me/towdium/jecalculation/gui/guis/GuiSearch.java index e58a6ae..9e5be5d 100644 --- a/src/main/java/me/towdium/jecalculation/gui/guis/GuiSearch.java +++ b/src/main/java/me/towdium/jecalculation/gui/guis/GuiSearch.java @@ -27,8 +27,8 @@ public class GuiSearch extends WContainer { add(switcherGroup); add(new WSearch(i -> content.stream().filter(j -> j.one.getRep() == i).findFirst().ifPresent(j -> JecaGui.displayGui(false, true, new GuiRecipe(j.two, j.three))), new WTextField(25, 27, 90), labelScroll)); - add(new WIcon(149, 27, 20, 20, Resource.ICN_HELP_N, Resource.ICN_HELP_F, "search.help")); - add(new WIcon(7, 27, 20, 20, Resource.ICN_TEXT_N, Resource.ICN_TEXT_F, "search.text")); + add(new WIcon(149, 27, 20, 20, Resource.ICN_HELP, "search.help")); + add(new WIcon(7, 27, 20, 20, Resource.ICN_TEXT, "search.text")); refresh(); } diff --git a/src/main/java/me/towdium/jecalculation/gui/guis/pickers/PickerItemStack.java b/src/main/java/me/towdium/jecalculation/gui/guis/pickers/PickerItemStack.java new file mode 100644 index 0000000..2aa4e19 --- /dev/null +++ b/src/main/java/me/towdium/jecalculation/gui/guis/pickers/PickerItemStack.java @@ -0,0 +1,72 @@ +package me.towdium.jecalculation.gui.guis.pickers; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import me.towdium.jecalculation.data.label.ILabel; +import me.towdium.jecalculation.data.label.labels.LItemStack; +import me.towdium.jecalculation.gui.IWPicker; +import me.towdium.jecalculation.gui.Resource; +import me.towdium.jecalculation.gui.drawables.WButton; +import me.towdium.jecalculation.gui.drawables.WButtonIcon; +import me.towdium.jecalculation.gui.drawables.WLabel; + +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.function.Consumer; + +/** + * Author: Towdium + * Date: 18-9-18 + */ +@ParametersAreNonnullByDefault +@SideOnly(Side.CLIENT) +public class PickerItemStack extends IWPicker.Impl { + WLabel label = new WLabel(7, 7, 20, 20, WLabel.enumMode.SELECTOR).setLsnrUpdate(this::update); + WButton bConfirm = new WButtonIcon(149, 7, 20, 20, Resource.BTN_YES).setLsnrLeft(() -> callback.accept(label.getLabel())); + WButton bNbtF = new WButtonIcon(49, 7, 20, 20, Resource.BTN_NBT_F).setLsnrLeft(() -> setFNbt(false)); + WButton bBbtN = new WButtonIcon(49, 7, 20, 20, Resource.BTN_NBT_N).setLsnrLeft(() -> setFNbt(true)); + WButton bCapF = new WButtonIcon(68, 7, 20, 20, Resource.BTN_CAP_F).setLsnrLeft(() -> setFCap(false)); + WButton bCapN = new WButtonIcon(68, 7, 20, 20, Resource.BTN_CAP_N).setLsnrLeft(() -> setFCap(true)); + WButton bMetaF = new WButtonIcon(30, 7, 20, 20, Resource.BTN_META_F).setLsnrLeft(() -> setFMeta(false)); + WButton bMetaN = new WButtonIcon(30, 7, 20, 20, Resource.BTN_META_N).setLsnrLeft(() -> setFMeta(true)); + + public PickerItemStack() { + addAll(label, bConfirm); + add(bConfirm); + update(); + } + + public void update() { + setFCap(false); + setFMeta(false); + setFNbt(false); + boolean b = label.getLabel() == ILabel.EMPTY; + bBbtN.setDisabled(b); + bCapN.setDisabled(b); + bMetaN.setDisabled(b); + bConfirm.setDisabled(b); + } + + private void setFNbt(boolean b) { + setF(b, bBbtN, bNbtF, i -> i.setFNbt(b)); + } + + private void setFMeta(boolean b) { + setF(b, bMetaN, bMetaF, i -> i.setFMeta(b)); + } + + private void setFCap(boolean b) { + setF(b, bCapN, bCapF, i -> i.setFCap(b)); + } + + private void setF(boolean b, WButton be, WButton bd, Consumer c) { + if (b) { + remove(be); + add(bd); + } else { + remove(bd); + add(be); + } + ILabel l = this.label.getLabel(); + if (l instanceof LItemStack) c.accept((LItemStack) l); + } +} diff --git a/src/main/java/me/towdium/jecalculation/gui/guis/pickers/PickerPlaceholder.java b/src/main/java/me/towdium/jecalculation/gui/guis/pickers/PickerPlaceholder.java index 3024a1c..423ed53 100644 --- a/src/main/java/me/towdium/jecalculation/gui/guis/pickers/PickerPlaceholder.java +++ b/src/main/java/me/towdium/jecalculation/gui/guis/pickers/PickerPlaceholder.java @@ -24,12 +24,12 @@ public class PickerPlaceholder extends IWPicker.Impl { WTextField create = new WTextField(26, 7, 69); create.setLsnrText(s -> create.setColor(s.equals("") ? JecaGui.COLOR_TEXT_RED : JecaGui.COLOR_TEXT_WHITE)); add(new WSearch(l -> callback.accept(l), search, scroll)); - add(new WIcon(149, 45, 20, 20, Resource.ICN_HELP_N, Resource.ICN_HELP_F, "picker_placeholder.help_search")); - add(new WIcon(149, 7, 20, 20, Resource.ICN_HELP_N, Resource.ICN_HELP_F, "picker_placeholder.help_create")); - add(new WIcon(7, 45, 20, 20, Resource.ICN_TEXT_N, Resource.ICN_TEXT_F, "picker_placeholder.text_search")); - add(new WIcon(7, 7, 20, 20, Resource.ICN_TEXT_N, Resource.ICN_TEXT_F, "picker_placeholder.text_create")); + add(new WIcon(149, 45, 20, 20, Resource.ICN_HELP, "picker_placeholder.help_search")); + add(new WIcon(149, 7, 20, 20, Resource.ICN_HELP, "picker_placeholder.help_create")); + add(new WIcon(7, 45, 20, 20, Resource.ICN_TEXT, "picker_placeholder.text_search")); + add(new WIcon(7, 7, 20, 20, Resource.ICN_TEXT, "picker_placeholder.text_create")); add(new WLine(36)); - add(new WButtonIcon(95, 7, 20, 20, Resource.BTN_YES_N, Resource.BTN_YES_F).setListenerLeft(() -> { + add(new WButtonIcon(95, 7, 20, 20, Resource.BTN_YES).setLsnrLeft(() -> { if (!create.getText().equals("")) callback.accept(new LPlaceholder(create.getText(), 1)); })); add(create); diff --git a/src/main/java/me/towdium/jecalculation/gui/guis/pickers/PickerSimple.java b/src/main/java/me/towdium/jecalculation/gui/guis/pickers/PickerSimple.java index f1c0843..6bf1ab5 100644 --- a/src/main/java/me/towdium/jecalculation/gui/guis/pickers/PickerSimple.java +++ b/src/main/java/me/towdium/jecalculation/gui/guis/pickers/PickerSimple.java @@ -32,8 +32,8 @@ public class PickerSimple extends IWPicker.Impl { WLabelScroll ls = new WLabelScroll(7, 33, 8, 7, WLabel.enumMode.PICKER, true).setLabels(labels); WTextField tf = new WTextField(26, 7, 90); add(new WSearch(l -> callback.accept(l), tf, ls)); - add(new WIcon(149, 7, 20, 20, Resource.ICN_HELP_N, Resource.ICN_HELP_F, l18nKey + ".help")); - add(new WIcon(7, 7, 20, 20, Resource.ICN_TEXT_N, Resource.ICN_TEXT_F, l18nKey + ".text")); + add(new WIcon(149, 7, 20, 20, Resource.ICN_HELP, l18nKey + ".help")); + add(new WIcon(7, 7, 20, 20, Resource.ICN_TEXT, l18nKey + ".text")); } diff --git a/src/main/java/me/towdium/jecalculation/nei/NEIPlugin.java b/src/main/java/me/towdium/jecalculation/nei/NEIPlugin.java index c85e3f7..3d475f1 100644 --- a/src/main/java/me/towdium/jecalculation/nei/NEIPlugin.java +++ b/src/main/java/me/towdium/jecalculation/nei/NEIPlugin.java @@ -1,8 +1,16 @@ package me.towdium.jecalculation.nei; import codechicken.nei.guihook.GuiContainerManager; +import codechicken.nei.recipe.GuiRecipeTab; +import codechicken.nei.recipe.HandlerInfo; +import codechicken.nei.recipe.IRecipeHandler; +import codechicken.nei.recipe.TemplateRecipeHandler; import me.towdium.jecalculation.data.label.ILabel; import net.minecraft.item.ItemStack; +import scala.tools.cmd.Opt; + +import javax.annotation.Nonnull; +import java.util.Optional; public class NEIPlugin { @@ -20,4 +28,21 @@ public class NEIPlugin { public static void setLabelUnderMouse(ItemStack itemStack) { NEIPlugin.currentItemStack = itemStack; } + + public static Optional getCatalyst(@Nonnull IRecipeHandler handler) { + final String handlerName = handler.toString().split("@")[0]; + final String handlerID; + if(handler instanceof TemplateRecipeHandler) { + handlerID = (((TemplateRecipeHandler)handler).getOverlayIdentifier()); + } else { + handlerID = null; + } + HandlerInfo info = GuiRecipeTab.getHandlerInfo(handlerName, handlerID); + + if(info == null) { + return Optional.empty(); + } + ItemStack itemStack = info.getItemStack(); + return Optional.ofNullable(itemStack); + } } diff --git a/src/main/resources/assets/jecalculation/textures/gui/resources.png b/src/main/resources/assets/jecalculation/textures/gui/resources.png index 8dc55ecb112bdd636f8bbce1e7a458f3c02eed76..b1039fee9823fddc3f15f2a810f628d99ef3befe 100644 GIT binary patch literal 19138 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 BS+D>A literal 15402 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 Fe*h