diff --git a/build/build.properties b/build/build.properties index acc6f422..98546009 100644 --- a/build/build.properties +++ b/build/build.properties @@ -1,5 +1,5 @@ -mc_version=1.7.2 -forge_version=10.12.0.1054 -ccl_version=1.1.0.77 -ccc_version=1.0.1 -mod_version=1.0 +mc_version=1.7.10 +forge_version=10.13.0.1151 +ccl_version=1.1.1.88 +ccc_version=1.0.1._ +mod_version=1.0.2 diff --git a/build/settings.gradle b/build/settings.gradle index 398e21f6..8cf9e37b 100644 --- a/build/settings.gradle +++ b/build/settings.gradle @@ -16,4 +16,4 @@ include 'api' include 'services:webservice' */ -rootProject.name = 'CodeChickenLib' +rootProject.name = 'NotEnoughItems' diff --git a/dev/net/minecraft/client/gui/inventory/GuiContainer.java b/dev/net/minecraft/client/gui/inventory/GuiContainer.java index c9906e4e..a9378736 100644 --- a/dev/net/minecraft/client/gui/inventory/GuiContainer.java +++ b/dev/net/minecraft/client/gui/inventory/GuiContainer.java @@ -360,10 +360,10 @@ public abstract class GuiContainer extends GuiScreen */ protected void mouseClicked(int par1, int par2, int par3) { - super.mouseClicked(par1, par2, par3); - if (manager.mouseClicked(par1, par2, par3)) return; + + super.mouseClicked(par1, par2, par3); boolean flag = par3 == this.mc.gameSettings.keyBindPickBlock.getKeyCode() + 100; Slot slot = this.getSlotAtPosition(par1, par2); diff --git a/resources/assets/nei/asm/blocks.asm b/resources/assets/nei/asm/blocks.asm index 83f9917c..610c1502 100644 --- a/resources/assets/nei/asm/blocks.asm +++ b/resources/assets/nei/asm/blocks.asm @@ -199,9 +199,6 @@ GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/ ALOAD 1 INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.renderSlotOverlay (Lnet/minecraft/inventory/Slot;)V -list n_mouseClicked -INVOKESPECIAL net/minecraft/client/gui/GuiScreen.func_73864_a (III)V - list mouseClicked ALOAD 0 GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; @@ -322,4 +319,55 @@ INVOKESPECIAL net/minecraft/client/gui/GuiScreen.func_73876_c ()V list updateScreen ALOAD 0 GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; -INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.updateScreen ()V \ No newline at end of file +INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.updateScreen ()V + + +#Other inventory modifications + +list renderTabTooltip +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; +ILOAD 2 +ILOAD 3 +INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.objectUnderMouse (II)Z +IFEQ LCONT +ICONST_0 +IRETURN +LCONT + +list handleTabClick +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; +ILOAD 2 +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.guiLeft : I +IADD +ILOAD 3 +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.guiTop : I +IADD +INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.objectUnderMouse (II)Z +IFEQ LCONT +ICONST_0 +IRETURN +LCONT + +list beaconButtonObscured +ALOAD 0 +GETFIELD BeaconButton.this$0 : Lnet/minecraft/client/gui/inventory/GuiBeacon; +DUP +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; +SWAP +DUP +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.guiLeft : I +ILOAD 1 +IADD +SWAP +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.guiTop : I +ILOAD 2 +IADD +INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.objectUnderMouse (II)Z +IFEQ LCONT +RETURN +LCONT + diff --git a/resources/assets/nei/lang/en_US.lang b/resources/assets/nei/lang/en_US.lang index 4cc1babe..520703a0 100644 --- a/resources/assets/nei/lang/en_US.lang +++ b/resources/assets/nei/lang/en_US.lang @@ -10,7 +10,7 @@ nei.inventory.options=Options nei.inventory.prev=Prev nei.inventory.next=Next nei.inventory.item_subsets=Item SubSets -nei.inventory.delete.all=DELETE ALL ITEMS from current inventory screen +nei.inventory.delete.inv=DELETE ALL ITEMS from current inventory screen nei.inventory.delete.one=Delete %s nei.inventory.delete.all=Delete ALL %s nei.inventory.delete.enable=Enable delete mode @@ -88,10 +88,15 @@ nei.options.inventory.layoutstyle=Layout Style nei.options.inventory.profileRecipes=Profile Recipes nei.options.inventory.profileRecipes.true=True nei.options.inventory.profileRecipes.false=False +nei.options.inventory.itemsort=Item Panel Sorting nei.options.inventory.itemIDs=Item IDs nei.options.inventory.itemIDs.0=Hidden nei.options.inventory.itemIDs.1=Auto nei.options.inventory.itemIDs.2=Shown +nei.options.inventory.searchmode=Search Mode +nei.options.inventory.searchmode.0=Plain +nei.options.inventory.searchmode.1=Extended +nei.options.inventory.searchmode.2=Regex nei.options.inventory.utilities=Utilities nei.options.inventory.utilities.tip=Select features for utility mode nei.options.inventory.utilities.time=Time @@ -113,7 +118,7 @@ nei.options.command=Commands nei.options.command.creative=Gamemode nei.options.command.creative.tip={0} = 1 for creative, 0 for survival, {1} = player nei.options.command.item=Item -nei.options.command.item.tip={0} = player, {1} = itemID, {2} = quantity, {3} = itemDamage +nei.options.command.item.tip={0} = player, {1} = id, {2} = amount, {3} = damage, {4} = nbt, {5} = name nei.options.command.time=Time nei.options.command.time.tip={0} = worldtime nei.options.command.rain=Rain @@ -165,4 +170,14 @@ nei.recipe.firework.tooltip1=Recolouring adds fade colours to the charge nei.recipe.firework.tooltip2=Multiple charges can be spawned from one rocket nei.recipe.brewing=Brewing nei.recipe.profiler.crafting=Crafting Profiling -nei.recipe.profiler.usage=Usage Profiling \ No newline at end of file +nei.recipe.profiler.usage=Usage Profiling + +nei.itemsort.minecraft=Minecraft +nei.itemsort.minecraft.tip=Sorts items from vanilla minecraft first +nei.itemsort.mod=Mod +nei.itemsort.mod.tip=Groups items in the same mod, sorted by mod name +nei.itemsort.id=Item ID +nei.itemsort.default=Default +nei.itemsort.default.tip=Leave the natural ordering of each item unchanged +nei.itemsort.damage=Item Damage +nei.itemsort.name=Display Name \ No newline at end of file diff --git a/resources/nei_at.cfg b/resources/nei_at.cfg index 4cee2211..aa65c54b 100644 --- a/resources/nei_at.cfg +++ b/resources/nei_at.cfg @@ -3,6 +3,8 @@ public net.minecraft.client.gui.inventory.GuiContainer field_146999_f #xSize public net.minecraft.client.gui.inventory.GuiContainer field_147000_g #ySize public net.minecraft.client.gui.inventory.GuiContainer field_147003_i #guiLeft public net.minecraft.client.gui.inventory.GuiContainer field_147009_r #guiTop +public net.minecraft.client.gui.inventory.GuiContainer field_147007_t #spreading +public net.minecraft.client.gui.inventory.GuiContainer field_147008_s #spreadingSlots public net.minecraft.client.gui.inventory.GuiContainer func_146975_c(II)Lnet/minecraft/inventory/Slot; #getSlotAtPosition public net.minecraft.client.gui.GuiScreen field_146292_n #buttonList diff --git a/src/codechicken/nei/Button.java b/src/codechicken/nei/Button.java index aefd9788..6a57e46f 100644 --- a/src/codechicken/nei/Button.java +++ b/src/codechicken/nei/Button.java @@ -1,76 +1,64 @@ package codechicken.nei; -import net.minecraft.client.audio.PositionedSoundRecord; -import net.minecraft.util.ResourceLocation; - import java.util.List; import static codechicken.lib.gui.GuiDraw.getStringWidth; public abstract class Button extends Widget { - public Button(String s) - { + public Button(String s) { label = s; } - - public Button() - { + + public Button() { label = ""; } - public int contentWidth() - { + public int contentWidth() { return getRenderIcon() == null ? getStringWidth(label) : getRenderIcon().width; } @Override - public void draw(int mousex, int mousey) - { + public void draw(int mousex, int mousey) { LayoutManager.getLayoutStyle().drawButton(this, mousex, mousey); } @Override - public boolean handleClick(int i, int j, int k) - { - if(k == 1 || k == 0) - if(onButtonPress(k == 1)) - NEIClientUtils.mc().getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F)); + public boolean handleClick(int mx, int my, int button) { + if (button == 1 || button == 0) + if (onButtonPress(button == 1)) + NEIClientUtils.playClickSound(); return true; } - + public abstract boolean onButtonPress(boolean rightclick); - public Image getRenderIcon() - { + public Image getRenderIcon() { return icon; } - + @Override - public List handleTooltip(int mx, int my, List tooltip) - { - if(!contains(mx, my)) + public List handleTooltip(int mx, int my, List tooltip) { + if (!contains(mx, my)) return tooltip; - + String tip = getButtonTip(); - if(tip != null) + if (tip != null) tooltip.add(tip); return tooltip; } - - public String getButtonTip() - { + + public String getButtonTip() { return null; } - - public String getRenderLabel() - { + + public String getRenderLabel() { return label; } public String label; public Image icon; - + /** * 0x4 = state flag, as opposed to 1 click * 0 = normal diff --git a/src/codechicken/nei/ClientHandler.java b/src/codechicken/nei/ClientHandler.java index 0db0f3e8..d751b9b8 100644 --- a/src/codechicken/nei/ClientHandler.java +++ b/src/codechicken/nei/ClientHandler.java @@ -108,18 +108,11 @@ public class ClientHandler } } - public static void load() { - try { - TMIUninstaller.deleteTMIUninstaller(); - if (TMIUninstaller.TMIInstalled()) { - TMIUninstaller.runTMIUninstaller(); - NEIClientUtils.mc().shutdownMinecraftApplet(); - } - } catch (Exception e) { - System.err.println("Error with TMI Uninstaller"); - e.printStackTrace(); - } + public static void preInit() { + ItemInfo.preInit(); + } + public static void load() { instance = new ClientHandler(); PacketCustom.assignHandler(NEICPH.channel, new NEICPH()); @@ -176,16 +169,16 @@ public class ClientHandler } - public void loadWorld(World world, boolean remote) { + public void loadWorld(World world, boolean fromServer) { if (world != lastworld) { SMPmagneticItems.clear(); WorldOverlayRenderer.reset(); - if (!remote) { + if (!fromServer) { NEIClientConfig.setHasSMPCounterPart(false); NEIClientConfig.setInternalEnabled(false); - if (!Minecraft.getMinecraft().isSingleplayer())//wait for server to initiate + if (!Minecraft.getMinecraft().isSingleplayer())//wait for server to initiate in singleplayer NEIClientConfig.loadWorld("remote/" + ClientUtils.getServerIP().replace(':', '~')); } diff --git a/src/codechicken/nei/FastTransferManager.java b/src/codechicken/nei/FastTransferManager.java index bbd14437..db0a0f60 100644 --- a/src/codechicken/nei/FastTransferManager.java +++ b/src/codechicken/nei/FastTransferManager.java @@ -94,7 +94,7 @@ public class FastTransferManager Integer fromZone = slotZoneMap.get(fromSlot); Integer toZone = slotZoneMap.get(toSlot); - if (fromZone == null || toZone == null || fromZone == toZone) + if (fromZone == null || toZone == null || fromZone.equals(toZone)) return; if (NEIClientUtils.getHeldItem() != null && !areStacksSameType(heldStack, NEIClientUtils.getHeldItem())) @@ -146,13 +146,10 @@ public class FastTransferManager ItemStack before = compareBefore.get(i); ItemStack after = compareAfter.get(i); - if (!areStacksIdentical(before, after) && after != null) { - if ((before == null && areStacksSameType(stack, after)) ||//transfered into this empty slot - (areStacksSameType(stack, after) && - after.stackSize - - before.stackSize > 0))//it added to this stack + if (!areStacksIdentical(before, after) && after != null) + if (before == null ? areStacksSameType(stack, after) ://transfered into this empty slot + areStacksSameType(stack, after) && after.stackSize - before.stackSize > 0)//it added to this stack return i; - } } return -1; diff --git a/src/codechicken/nei/GuiPotionCreator.java b/src/codechicken/nei/GuiPotionCreator.java index 4191b119..1b5257ac 100644 --- a/src/codechicken/nei/GuiPotionCreator.java +++ b/src/codechicken/nei/GuiPotionCreator.java @@ -14,6 +14,7 @@ import net.minecraft.potion.PotionEffect; import net.minecraft.util.StatCollector; import org.lwjgl.opengl.GL11; +import java.awt.*; import java.util.ArrayList; public class GuiPotionCreator extends GuiContainerWidget @@ -30,16 +31,17 @@ public class GuiPotionCreator extends GuiContainerWidget if (p != null) validPotions.add(p); setSmoothScroll(false); - setContentSize(x, y, height); + setMargins(0, 0, 0, 0); } @Override - public int getSlotHeight() { + public int getSlotHeight(int slot) { return 19; } @Override - public void drawSlotBox(float frame) { + public void drawBackground(float frame) { + super.drawBackground(frame); drawRect(x, y, x + width, y + height, 0xFF000000); } @@ -48,17 +50,19 @@ public class GuiPotionCreator extends GuiContainerWidget } @Override - public boolean drawLineGuide() { - return false; + public int scrollbarGuideAlignment() { + return 0; } @Override - public int getScrollBarWidth() { - return 7; + public Dimension scrollbarDim() { + Dimension dim = super.scrollbarDim(); + dim.width = 7; + return dim; } @Override - protected void drawSlot(int slot, int x, int y, int mx, int my, boolean selected, float frame) { + protected void drawSlot(int slot, int x, int y, int mx, int my, float frame) { GL11.glColor4f(1, 1, 1, 1); Potion potion = validPotions.get(slot); PotionEffect effect = getEffect(potion.id); @@ -68,13 +72,13 @@ public class GuiPotionCreator extends GuiContainerWidget int shade = selectedslot == slot ? 2 : blank ? 1 : 0; CCRenderState.changeTexture("textures/gui/container/enchanting_table.png"); - drawTexturedModalRect(x, y, 0, 166 + getSlotHeight() * shade, width - 30, getSlotHeight()); - drawTexturedModalRect(x + width - 30, y, width - 23, 166 + getSlotHeight() * shade, 30, getSlotHeight()); + drawTexturedModalRect(x, y, 0, 166 + getSlotHeight(slot) * shade, width - 30, getSlotHeight(slot)); + drawTexturedModalRect(x + width - 30, y, width - 23, 166 + getSlotHeight(slot) * shade, 30, getSlotHeight(slot)); if (potion.hasStatusIcon()) { CCRenderState.changeTexture("textures/gui/container/inventory.png"); int icon = potion.getStatusIconIndex(); - drawTexturedModalRect(x + 1, y + 1, 0 + icon % 8 * 18, 198 + icon / 8 * 18, 18, 18); + drawTexturedModalRect(x + 1, y + 1, icon % 8 * 18, 198 + icon / 8 * 18, 18, 18); } String name = StatCollector.translateToLocal(potion.getName()); @@ -111,12 +115,7 @@ public class GuiPotionCreator extends GuiContainerWidget } @Override - protected boolean isSlotSelected(int slot) { - return slot == selectedslot; - } - - @Override - protected void slotClicked(int slot, int button, int mx, int my, boolean doubleclick) { + protected void slotClicked(int slot, int button, int mx, int my, int count) { if (!enabled) return; diff --git a/src/codechicken/nei/ItemList.java b/src/codechicken/nei/ItemList.java index 138b0766..b1588855 100644 --- a/src/codechicken/nei/ItemList.java +++ b/src/codechicken/nei/ItemList.java @@ -1,74 +1,48 @@ package codechicken.nei; -import codechicken.nei.ItemPanel.ItemPanelObject; +import codechicken.nei.ThreadOperationTimer.TimeoutException; +import codechicken.nei.api.ItemFilter; +import codechicken.nei.api.ItemFilter.ItemFilterProvider; import codechicken.nei.api.ItemInfo; import codechicken.nei.guihook.GuiContainerManager; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ListMultimap; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.IIcon; -import java.io.PrintWriter; -import java.io.StringWriter; import java.util.ArrayList; import java.util.HashSet; -import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; public class ItemList { + /** + * Fields are replaced atomically and contents never modified. + */ public static List items = new ArrayList(); + /** + * Fields are replaced atomically and contents never modified. + */ public static ListMultimap itemMap = ArrayListMultimap.create(); + /** + * Updates to this should be synchronised on this + */ + public static final List itemFilterers = new LinkedList(); + public static final List loadCallbacks = new LinkedList(); - private static boolean matching = false; private static boolean loading = false; - private static boolean research = false; private static boolean reload = false; + + private static boolean filtering = false; + private static boolean refilter = false; + private static HashSet erroredItems = new HashSet(); + private static HashSet stackTraces = new HashSet(); - private static interface ItemMatcher - { - public boolean matches(ItemStack item); - } - - /*private static class SubsetItemMatcher implements ItemMatcher - { - final List tags; - - public SubsetItemMatcher(List tags) - { - this.tags = tags; - } - - @Override - public boolean matches(ItemStack item) - { - for(SubSetRangeTag tag : tags) - if(tag.isItemInRange(item.getItem(), item.getItemDamage())) - return true; - return false; - } - }*/ - - private static class PatternItemMatcher implements ItemMatcher - { - Pattern pattern; - - public PatternItemMatcher(Pattern pattern) { - this.pattern = pattern; - } - - @Override - public boolean matches(ItemStack item) { - return pattern.matcher(EnumChatFormatting.getTextWithoutFormattingCodes(GuiContainerManager.concatenatedDisplayName(item, true).toLowerCase())).find(); - } - } - - private static class EverythingItemMatcher implements ItemMatcher + public static class EverythingItemFilter implements ItemFilter { @Override public boolean matches(ItemStack item) { @@ -76,7 +50,7 @@ public class ItemList } } - private static class NothingItemMatcher implements ItemMatcher + public static class NothingItemFilter implements ItemFilter { @Override public boolean matches(ItemStack item) { @@ -84,287 +58,167 @@ public class ItemList } } - public static ItemMatcher getSearchMatcher() { - String matchstring = NEIClientConfig.getSearchExpression().toLowerCase(); - /*if(matchstring.startsWith("@") && matchstring.length() > 1) - { - LinkedList tags = new LinkedList(); - try - { - String pattern = matchstring.substring(1); - for(SubSetRangeTag tag : DropDownFile.dropDownInstance.allTags()) - if(CommonUtils.filterText(tag.qualifiedname).toLowerCase().contains(pattern)) - tags.add(tag); - if(tags.isEmpty()) - return new NothingItemMatcher(); - - return new SubsetItemMatcher(tags); - } - catch(PatternSyntaxException e) - { - return new NothingItemMatcher(); - } - }*/ - - { - matchstring = matchstring.replace(".", ""); - matchstring = matchstring.replace("?", "."); - matchstring = matchstring.replace("*", ".+?"); - Pattern pattern = null; - try { - pattern = Pattern.compile(matchstring); - } catch (PatternSyntaxException ignored) {} - if (pattern == null || pattern.toString().equals("")) - return new EverythingItemMatcher(); - - return new PatternItemMatcher(pattern); - } - } - - public static boolean itemMatchesSearch(ItemStack item) { - return getSearchMatcher().matches(item); - } - - public static interface IItemCounter + public static class PatternItemFilter implements ItemFilter { - public Item getItem(); + Pattern pattern; - public Thread getThread(); - } - - @SuppressWarnings("serial") - public static class TimeoutException extends RuntimeException - { - public final Item itemID; - - public TimeoutException(String msg, Item lastItem) { - super(msg); - itemID = lastItem; - } - } - - public static class ThreadLoadMonitor extends Thread - { - IItemCounter loadingThread; - - public ThreadLoadMonitor(IItemCounter handle) { - super("NEI Load Monitor"); - loadingThread = handle; - } - - @SuppressWarnings("deprecation") - @Override - public void run() { - if(true) return; - Item lastItem = null; - long lastTime = System.currentTimeMillis(); - while (loadingThread.getThread().isAlive()) { - if (lastItem != loadingThread.getItem()) { - lastTime = System.currentTimeMillis(); - lastItem = loadingThread.getItem(); - } else if (System.currentTimeMillis() - lastTime > 2000 && lastItem != null) { - loadingThread.getThread().stop(new TimeoutException("Took to long to advance item", lastItem)); - } - try { - Thread.sleep(2000); - } catch (InterruptedException ie) {} - } - } - } - - public static class ThreadMatchSearch extends Thread implements IItemCounter - { - private Item item; - - public ThreadMatchSearch() { - super("NEI Item Searching Thread"); - matching = true; + public PatternItemFilter(Pattern pattern) { + this.pattern = pattern; } @Override - public Item getItem() { - return item; - } - - @Override - public Thread getThread() { - return this; - } - - @Override - public void run() { - //new ThreadLoadMonitor(this).start(); - try { - startMatch: - while (matching) { - try { - ArrayList visibleitems = new ArrayList(); - ItemMatcher matcher = getSearchMatcher(); - for (ItemStack stack : items) { - item = stack.getItem(); - if (research) { - research = false; - continue startMatch; - } - - /*if(stack.hasTagCompound() ? NEIClientConfig.vishash.isItemHidden(item, stack.stackTagCompound) : NEIClientConfig.vishash.isItemHidden(item, stack.getItemDamage())) - continue;*/ - - if (NEIClientConfig.bannedBlocks.contains(stack)) - continue; - - if (matcher.matches(stack)) - visibleitems.add(new ItemPanelStack(stack)); - } - ItemPanel.visibleitems = visibleitems; - } catch (TimeoutException e) { - System.err.println("Removing itemID: " + e.itemID + " from list."); - e.printStackTrace(); - erroredItems.add(e.itemID); - loadItems(); - } - matching = false; - } - } - finally { - matching = false; - } + public boolean matches(ItemStack item) { + return pattern.matcher(ItemInfo.getSearchName(item)).find(); } } - private static HashSet stackTraces = new HashSet(); - - public static class ThreadLoadItems extends Thread implements IItemCounter + public static interface ItemsLoadedCallback { - private Item item; + public void itemsLoaded(); + } + public static boolean itemMatches(ItemStack item, List filters) { + for(ItemFilter filter : filters) + if(!filter.matches(item)) + return false; + + return true; + } + + public static boolean itemMatches(ItemStack item) { + return itemMatches(item, getItemFilters()); + } + + public static List getItemFilters() { + LinkedList filters = new LinkedList(); + synchronized (itemFilterers) { + for(ItemFilterProvider p : itemFilterers) + filters.add(p.getFilter()); + } + return filters; + } + + private static class ThreadLoadItems extends Thread + { public ThreadLoadItems() { - super("NEI Item Loading Thread"); - loading = true; + super("NEI Item Loading"); } - @Override - public Item getItem() { - return item; - } - - @Override - public Thread getThread() { - return this; + private void damageSearch(Item item, List permutations) { + HashSet damageIconSet = new HashSet(); + for (int damage = 0; damage < 16; damage++) + try { + ItemStack itemstack = new ItemStack(item, 1, damage); + IIcon icon = item.getIconIndex(itemstack); + String name = GuiContainerManager.concatenatedDisplayName(itemstack, false); + String s = name + "@" + (icon == null ? 0 : icon.hashCode()); + if (!damageIconSet.contains(s)) { + damageIconSet.add(s); + permutations.add(itemstack); + } + } + catch(TimeoutException t) { + throw t; + } + catch(Throwable t) { + NEIServerUtils.logOnce(t, stackTraces, "Ommiting "+item+":"+damage+" "+item.getClass().getSimpleName(), item.toString()); + } } @Override public void run() { - new ThreadLoadMonitor(this).start(); - startSearch: - while (loading) { - try { - ArrayList items = new ArrayList(); - ArrayList permutations = new ArrayList(); - ListMultimap itemMap = ArrayListMultimap.create(); + ThreadOperationTimer timer = ThreadOperationTimer.start(this, 500); + restart: + do { + reload = false; + LinkedList items = new LinkedList(); + LinkedList permutations = new LinkedList(); + ListMultimap itemMap = ArrayListMultimap.create(); - for (Item item : (Iterable) Item.itemRegistry) { - this.item = item; - if (reload) { - reload = false; - continue startSearch; - } + timer.setLimit(500); + for (Item item : (Iterable) Item.itemRegistry) { + if (reload) + continue restart; - if (item == null || ItemInfo.isHidden(item)) - continue; + if (item == null || erroredItems.contains(item)) + continue; + + try { + timer.reset(item); permutations.clear(); permutations.addAll(ItemInfo.getItemOverrides(item)); - if(permutations.isEmpty()) { - try { - item.getSubItems(item, null, permutations); - } catch (Exception e) { - System.err.println("Removing itemID: " + item + " from list."); - e.printStackTrace(); - erroredItems.add(item); - continue; - } - } - if(permutations.isEmpty()) { - HashSet damageIconSet = new HashSet(); - for (int damage = 0; damage < 16; damage++) { - ItemStack itemstack = new ItemStack(item, 1, damage); - try { - IIcon icon = item.getIconIndex(itemstack); - String name = GuiContainerManager.concatenatedDisplayName(itemstack, false); - String s = name + "@" + (icon == null ? 0 : icon.hashCode()); - if (!damageIconSet.contains(s)) { - damageIconSet.add(s); - permutations.add(itemstack); - } + if (permutations.isEmpty()) + item.getSubItems(item, null, permutations); - } catch (Throwable t) { - StringWriter sw = new StringWriter(); - t.printStackTrace(new PrintWriter(sw)); - String stackTrace = itemstack + sw.toString(); - if (!stackTraces.contains(stackTrace)) { - System.err.println("NEI: Omitting #" + this.item + ":" + damage + " " + item.getClass().getSimpleName()); - t.printStackTrace(); - stackTraces.add(stackTrace); - } - } - } - } + if (permutations.isEmpty()) + damageSearch(item, permutations); - for(Iterator it = permutations.iterator(); it.hasNext(); ) - if(ItemInfo.isHidden(it.next())) - it.remove(); + timer.reset(); items.addAll(permutations); itemMap.putAll(item, permutations); + } catch (Throwable t) { + NEIServerConfig.logger.error("Removing item: " + item + " from list.", t); + erroredItems.add(item); } - - item = null; - - /*DropDownFile dropDownInstance = DropDownFile.dropDownInstance; - dropDownInstance.resetHashes(); - for(ItemStack stack : items) - { - if(reload) - { - reload = false; - continue startSearch; - } - dropDownInstance.addItemIfInRange(stack.getItem(), stack.getItemDamage(), stack.stackTagCompound); - } - dropDownInstance.updateState();*/ - ItemList.items = items; - ItemList.itemMap = itemMap; - if (reload) { - reload = false; - continue; - } - loading = false; - } catch (TimeoutException e) { - System.err.println("Removing itemID: " + e.itemID + " from list."); - e.printStackTrace(); - erroredItems.add(e.itemID); } + + ItemList.items = items; + ItemList.itemMap = itemMap; + for(ItemsLoadedCallback callback : loadCallbacks) + callback.itemsLoaded(); + + updateFilter(); } - updateSearch(); + while (reload); + loading = false; } } - public static boolean isMatching() { - return matching; + public static class ThreadFilterItems extends Thread { + public ThreadFilterItems() { + super("NEI Item Filtering"); + } + + @Override + public void run() { + restart: + do { + refilter = false; + ArrayList filtered = new ArrayList(); + List filters = getItemFilters(); + for(ItemStack item : items) { + if(refilter) + continue restart; + + if(itemMatches(item, filters)) + filtered.add(item); + } + + ItemSorter.sort(filtered); + ItemPanel.updateItemList(filtered); + } + while(refilter); + filtering = false; + } } - public static void updateSearch() { - if (matching) - research = true; - else - new ThreadMatchSearch().start(); + public static void updateFilter() { + if (filtering) + refilter = true; + else { + filtering = true; + new ThreadFilterItems().start(); + } } public static void loadItems() { if (loading) reload = true; - else + else { + loading = true; new ThreadLoadItems().start(); + } } } diff --git a/src/codechicken/nei/ItemMobSpawner.java b/src/codechicken/nei/ItemMobSpawner.java index 11301a34..0181af97 100644 --- a/src/codechicken/nei/ItemMobSpawner.java +++ b/src/codechicken/nei/ItemMobSpawner.java @@ -26,7 +26,7 @@ public class ItemMobSpawner extends ItemBlock public static int idPig; private static boolean loaded; - public ItemMobSpawner(World world) { + public ItemMobSpawner() { super(Blocks.mob_spawner); hasSubtypes = true; @@ -34,7 +34,6 @@ public class ItemMobSpawner extends ItemBlock entityHashMap = new HashMap(); IDtoNameMap = new HashMap(); - loadSpawners(world); } /** @@ -73,26 +72,24 @@ public class ItemMobSpawner extends ItemBlock meta = idPig; } Entity e = getEntity(meta); - if (e == null) return; list.add("\u00A7" + (e instanceof IMob ? "4" : "3") + IDtoNameMap.get(meta)); } public static EntityLiving getEntity(int ID) { - EntityLiving entityliving = entityHashMap.get(ID); - if (entityliving == null) { + EntityLiving e = entityHashMap.get(ID); + if (e == null) { World world = NEIClientUtils.mc().theWorld; loadSpawners(world); + Class clazz = (Class) EntityList.IDtoClassMapping.get(ID); try { - Class class1 = (Class) EntityList.IDtoClassMapping.get(ID); - if (class1 != null && EntityLiving.class.isAssignableFrom(class1)) { - entityliving = (EntityLiving) class1.getConstructor(new Class[]{World.class}).newInstance(new Object[]{world}); - } + e = (EntityLiving) clazz.getConstructor(new Class[]{World.class}).newInstance(world); } catch (Throwable t) { - t.printStackTrace(); + NEIClientConfig.logger.error("Error creating instance of entity: " + clazz.getName(), t); + e = getEntity(idPig); } - entityHashMap.put(ID, entityliving); + entityHashMap.put(ID, e); } - return entityliving; + return e; } private void setDefaultTag(ItemStack itemstack) { @@ -103,31 +100,27 @@ public class ItemMobSpawner extends ItemBlock public static void loadSpawners(World world) { if (loaded) return; loaded = true; - try { - HashMap, String> classToStringMapping = (HashMap, String>) EntityList.classToStringMapping; - HashMap, Integer> classToIDMapping = (HashMap, Integer>) EntityList.classToIDMapping; - for (Class eclass : classToStringMapping.keySet()) { - if (!EntityLiving.class.isAssignableFrom(eclass)) + HashMap, String> classToStringMapping = (HashMap, String>) EntityList.classToStringMapping; + HashMap, Integer> classToIDMapping = (HashMap, Integer>) EntityList.classToIDMapping; + for (Class eclass : classToStringMapping.keySet()) { + if (!EntityLiving.class.isAssignableFrom(eclass)) + continue; + try { + EntityLiving entityliving = (EntityLiving) eclass.getConstructor(new Class[]{World.class}).newInstance(world); + entityliving.isChild(); + + int id = classToIDMapping.get(eclass); + String name = classToStringMapping.get(eclass); + + if (name.equals("EnderDragon")) continue; - try { - EntityLiving entityliving = (EntityLiving) eclass.getConstructor(new Class[]{World.class}).newInstance(new Object[]{world}); - entityliving.isChild(); - int id = classToIDMapping.get(eclass); - String name = classToStringMapping.get(eclass); + IDtoNameMap.put(id, name); - if (name.equals("EnderDragon")) - continue; - - IDtoNameMap.put(id, name); - - if (name.equals("Pig")) - idPig = id; - } catch (Throwable t) { - } + if (name.equals("Pig")) + idPig = id; + } catch (Throwable ignored) { } - } catch (Throwable t) { - t.printStackTrace(); } } diff --git a/src/codechicken/nei/ItemPanel.java b/src/codechicken/nei/ItemPanel.java index 40644797..7e50e163 100644 --- a/src/codechicken/nei/ItemPanel.java +++ b/src/codechicken/nei/ItemPanel.java @@ -12,294 +12,274 @@ import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; import java.util.ArrayList; -import java.util.List; import static codechicken.lib.gui.GuiDraw.drawRect; public class ItemPanel extends Widget { + public static ArrayList items = new ArrayList(); + /** + * Swapped into visible items on update + */ + private static ArrayList _items = items; + + public static void updateItemList(ArrayList newItems) { + _items = newItems; + } + public class ItemPanelSlot { - public ItemPanelObject contents; + public ItemStack item; public int slotIndex; - - public ItemPanelSlot(int index) - { - contents = visibleitems.get(index); + + public ItemPanelSlot(int index) { + item = items.get(index); slotIndex = index; } - - public ItemStack getItemStack() - { - return contents instanceof ItemPanelStack ? ((ItemPanelStack)contents).item : null; - } - } - - public static interface ItemPanelObject - { - void draw(int x, int y); - List handleTooltip(List tooltip); } - public void resize() - { - marginLeft = x + (width % 18) / 2; - marginTop = y + (height % 18) / 2; - columns = width / 18; - rows = height / 18; - + public ItemStack draggedStack; + public int mouseDownSlot = -1; + + private int marginLeft; + private int marginTop; + private int rows; + private int columns; + + private boolean[] validSlotMap; + private int firstIndex; + private int itemsPerPage; + + private int page; + private int numPages; + + public void resize() { + items = _items; + + marginLeft = x + (w % 18) / 2; + marginTop = y + (h % 18) / 2; + columns = w / 18; + rows = h / 18; + calculatePage(); updateValidSlots(); } - private void calculatePage() { - if(itemsPerPage == 0) - numPages = 0; - else - numPages = (int)Math.ceil((float)visibleitems.size() / (float)itemsPerPage); + private void calculatePage() { + if (itemsPerPage == 0) + numPages = 0; + else + numPages = (int) Math.ceil((float) items.size() / (float) itemsPerPage); - if(firstIndex >= visibleitems.size()) + if (firstIndex >= items.size()) firstIndex = 0; - if(numPages == 0) - page = 0; - else - page = firstIndex/itemsPerPage+1; + if (numPages == 0) + page = 0; + else + page = firstIndex / itemsPerPage + 1; } - + private void updateValidSlots() { - GuiContainer gui = NEIClientUtils.getGuiContainer(); - validSlotMap = new boolean[rows*columns]; - itemsPerPage = 0; - for(int i = 0; i < validSlotMap.length; i++) - if(slotValid(gui, i)) { - validSlotMap[i] = true; - itemsPerPage++; - } - } - + GuiContainer gui = NEIClientUtils.getGuiContainer(); + validSlotMap = new boolean[rows * columns]; + itemsPerPage = 0; + for (int i = 0; i < validSlotMap.length; i++) + if (slotValid(gui, i)) { + validSlotMap[i] = true; + itemsPerPage++; + } + } + private boolean slotValid(GuiContainer gui, int i) { - Rectangle4i rect = getSlotRect(i); - for(INEIGuiHandler handler : GuiInfo.guiHandlers) - if(handler.hideItemPanelSlot(gui, rect.x, rect.y, rect.w, rect.h)) - return false; - return true; + Rectangle4i rect = getSlotRect(i); + for (INEIGuiHandler handler : GuiInfo.guiHandlers) + if (handler.hideItemPanelSlot(gui, rect.x, rect.y, rect.w, rect.h)) + return false; + return true; } - + public Rectangle4i getSlotRect(int i) { - return getSlotRect(i/columns, i%columns); + return getSlotRect(i / columns, i % columns); } - + public Rectangle4i getSlotRect(int row, int column) { - return new Rectangle4i(marginLeft+column*18, marginTop+row*18, 18, 18); + return new Rectangle4i(marginLeft + column * 18, marginTop + row * 18, 18, 18); } @Override - public void draw(int mousex, int mousey) - { - if(itemsPerPage == 0) + public void draw(int mousex, int mousey) { + if (itemsPerPage == 0) return; GuiContainerManager.enableMatrixStackLogging(); int index = firstIndex; - for(int i = 0; i < rows*columns && index < visibleitems.size(); i++) { - if(validSlotMap[i]) { + for (int i = 0; i < rows * columns && index < items.size(); i++) { + if (validSlotMap[i]) { Rectangle4i rect = getSlotRect(i); - if(rect.contains(mousex, mousey)) + if (rect.contains(mousex, mousey)) drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555);//highlight - - visibleitems.get(index).draw(rect.x, rect.y); - + + GuiContainerManager.drawItem(rect.x + 1, rect.y + 1, items.get(index)); + index++; - } + } } GuiContainerManager.disableMatrixStackLogging(); } - + @Override - public void postDraw(int mousex, int mousey) - { - if(draggedStack != null) - { + public void postDraw(int mousex, int mousey) { + if (draggedStack != null) { GuiContainerManager.drawItems.zLevel += 100; GuiContainerManager.drawItem(mousex - 8, mousey - 8, draggedStack); GuiContainerManager.drawItems.zLevel -= 100; } } - + @Override - public void mouseDragged(int mousex, int mousey, int button, long heldTime) - { - if(mouseDownSlot >= 0 && draggedStack == null && NEIClientUtils.getHeldItem() == null) - { + public void mouseDragged(int mousex, int mousey, int button, long heldTime) { + if (mouseDownSlot >= 0 && draggedStack == null && NEIClientUtils.getHeldItem() == null && + NEIClientConfig.hasSMPCounterPart() && !GuiInfo.hasCustomSlots(NEIClientUtils.getGuiContainer())) { ItemPanelSlot mouseOverSlot = getSlotMouseOver(mousex, mousey); - ItemStack stack = new ItemPanelSlot(mouseDownSlot).getItemStack(); - if(stack != null && (mouseOverSlot == null || mouseOverSlot.slotIndex != mouseDownSlot || heldTime > 500)) - { + ItemStack stack = new ItemPanelSlot(mouseDownSlot).item; + if (stack != null && (mouseOverSlot == null || mouseOverSlot.slotIndex != mouseDownSlot || heldTime > 500)) { int amount = NEIClientConfig.getItemQuantity(); - if(amount == 0) + if (amount == 0) amount = stack.getMaxStackSize(); - + draggedStack = NEIServerUtils.copyStack(stack, amount); } } } @Override - public boolean handleClick(int mousex, int mousey, int button) - { - if(handleDraggedClick(mousex, mousey, button)) + public boolean handleClick(int mousex, int mousey, int button) { + if (handleDraggedClick(mousex, mousey, button)) return true; - - if(NEIClientUtils.getHeldItem() != null) - { - for(INEIGuiHandler handler : GuiInfo.guiHandlers) - if(handler.hideItemPanelSlot(NEIClientUtils.getGuiContainer(), mousex, mousey, 1, 1)) - return false; - - if(NEIClientConfig.canPerformAction("delete") && NEIClientConfig.canPerformAction("item")) - { - if(button == 1) + + if (NEIClientUtils.getHeldItem() != null) { + for (INEIGuiHandler handler : GuiInfo.guiHandlers) + if (handler.hideItemPanelSlot(NEIClientUtils.getGuiContainer(), mousex, mousey, 1, 1)) + return false; + + if (NEIClientConfig.canPerformAction("delete") && NEIClientConfig.canPerformAction("item")) + if (button == 1) NEIClientUtils.decreaseSlotStack(-999); else NEIClientUtils.deleteHeldItem(); - } else - { NEIClientUtils.dropHeldItem(); - } + return true; } - - ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey); - if(hoverSlot != null) - { - if(button == 2) - { - ItemStack stack = hoverSlot.getItemStack(); - if(stack != null) - { + + ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey); + if (hoverSlot != null) { + if (button == 2) { + ItemStack stack = hoverSlot.item; + if (stack != null) { int amount = NEIClientConfig.getItemQuantity(); - if(amount == 0) + if (amount == 0) amount = stack.getMaxStackSize(); - + draggedStack = NEIServerUtils.copyStack(stack, amount); } - } - else - { + } else { mouseDownSlot = hoverSlot.slotIndex; } return true; } return false; } - - private boolean handleDraggedClick(int mousex, int mousey, int button) - { - if(draggedStack == null) + + private boolean handleDraggedClick(int mousex, int mousey, int button) { + if (draggedStack == null) return false; - + GuiContainer gui = NEIClientUtils.getGuiContainer(); boolean handled = false; - for(INEIGuiHandler handler : GuiInfo.guiHandlers) - if(handler.handleDragNDrop(gui, mousex, mousey, draggedStack, button)) - { + for (INEIGuiHandler handler : GuiInfo.guiHandlers) + if (handler.handleDragNDrop(gui, mousex, mousey, draggedStack, button)) { handled = true; - if(draggedStack.stackSize == 0) - { + if (draggedStack.stackSize == 0) { draggedStack = null; return true; } } - - if(handled) + + if (handled) return true; - + Slot overSlot = gui.getSlotAtPosition(mousex, mousey); - if(overSlot != null && overSlot.isItemValid(draggedStack)) - { - if(NEIClientConfig.canPerformAction("item")) - { + if (overSlot != null && overSlot.isItemValid(draggedStack)) { + if (NEIClientConfig.canCheatItem(draggedStack)) { int contents = overSlot.getHasStack() ? overSlot.getStack().stackSize : 0; int add = button == 0 ? draggedStack.stackSize : 1; - if(overSlot.getHasStack() && !NEIServerUtils.areStacksSameType(draggedStack, overSlot.getStack())) + if (overSlot.getHasStack() && !NEIServerUtils.areStacksSameType(draggedStack, overSlot.getStack())) contents = 0; - int total = Math.min(contents+add, Math.min(overSlot.getSlotStackLimit(), draggedStack.getMaxStackSize())); - - if(total > contents) - { + int total = Math.min(contents + add, Math.min(overSlot.getSlotStackLimit(), draggedStack.getMaxStackSize())); + + if (total > contents) { NEIClientUtils.setSlotContents(overSlot.slotNumber, NEIServerUtils.copyStack(draggedStack, total), true); NEICPH.sendGiveItem(NEIServerUtils.copyStack(draggedStack, total), false, false); - draggedStack.stackSize-=total-contents; + draggedStack.stackSize -= total - contents; } - if(draggedStack.stackSize == 0) + if (draggedStack.stackSize == 0) draggedStack = null; - } - else - { + } else { draggedStack = null; } - } - else if(mousex < gui.guiLeft || mousey < gui.guiTop || mousex >= gui.guiLeft+gui.xSize || mousey >= gui.guiTop+gui.ySize) - { + } else if (mousex < gui.guiLeft || mousey < gui.guiTop || mousex >= gui.guiLeft + gui.xSize || mousey >= gui.guiTop + gui.ySize) { draggedStack = null; } - + return true; } - + @Override - public boolean handleClickExt(int mousex, int mousey, int button) - { + public boolean handleClickExt(int mousex, int mousey, int button) { return handleDraggedClick(mousex, mousey, button); } - + @Override - public void mouseUp(int mousex, int mousey, int button) - { - ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey); - if(hoverSlot != null && hoverSlot.slotIndex == mouseDownSlot && hoverSlot.getItemStack() != null && draggedStack == null) - { - ItemStack item = hoverSlot.getItemStack(); - if(NEIController.manager.window instanceof GuiRecipe || !NEIClientConfig.canPerformAction("item")) - { - if(button == 0) + public void mouseUp(int mousex, int mousey, int button) { + ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey); + if (hoverSlot != null && hoverSlot.slotIndex == mouseDownSlot && draggedStack == null) { + ItemStack item = hoverSlot.item; + if (NEIController.manager.window instanceof GuiRecipe || !NEIClientConfig.canCheatItem(item)) { + if (button == 0) GuiCraftingRecipe.openRecipeGui("item", item); - else if(button == 1) + else if (button == 1) GuiUsageRecipe.openRecipeGui("item", item); draggedStack = null; mouseDownSlot = -1; return; } - + NEIClientUtils.cheatItem(item, button, -1); } - + mouseDownSlot = -1; } @Override - public boolean onMouseWheel(int i, int mousex, int mousey) - { - if(!contains(mousex, mousey)) + public boolean onMouseWheel(int i, int mousex, int mousey) { + if (!contains(mousex, mousey)) return false; - + scroll(-i); return true; } - + @Override - public boolean handleKeyPress(int keyID, char keyChar) - { - if(keyID == NEIClientConfig.getKeyBinding("gui.next")) - { + public boolean handleKeyPress(int keyID, char keyChar) { + if (keyID == NEIClientConfig.getKeyBinding("gui.next")) { scroll(1); return true; } - if(keyID == NEIClientConfig.getKeyBinding("gui.prev")) - { + if (keyID == NEIClientConfig.getKeyBinding("gui.prev")) { scroll(-1); return true; } @@ -307,75 +287,55 @@ public class ItemPanel extends Widget } @Override - public ItemStack getStackMouseOver(int mousex, int mousey) - { + public ItemStack getStackMouseOver(int mousex, int mousey) { ItemPanelSlot slot = getSlotMouseOver(mousex, mousey); - return slot == null ? null : slot.getItemStack(); + return slot == null ? null : slot.item; } - - public ItemPanelSlot getSlotMouseOver(int mousex, int mousey) - { - int index = firstIndex; - for(int i = 0; i < rows*columns && index < visibleitems.size(); i++) - if(validSlotMap[i]) { - if(getSlotRect(i).contains(mousex, mousey)) - return new ItemPanelSlot(index); - index++; - } - + + public ItemPanelSlot getSlotMouseOver(int mousex, int mousey) { + int index = firstIndex; + for (int i = 0; i < rows * columns && index < items.size(); i++) + if (validSlotMap[i]) { + if (getSlotRect(i).contains(mousex, mousey)) + return new ItemPanelSlot(index); + index++; + } + return null; } - - @Override - public List handleTooltip(int mx, int my, List tooltip) - { - if(getSlotMouseOver(mx, my) == null) - return tooltip; - - return getSlotMouseOver(mx, my).contents.handleTooltip(tooltip); + + public void scroll(int i) { + if (itemsPerPage != 0) { + int oldIndex = firstIndex; + firstIndex += i * itemsPerPage; + if (firstIndex >= items.size()) + firstIndex = 0; + if (firstIndex < 0) + if (oldIndex > 0) + firstIndex = 0; + else + firstIndex = (items.size() - 1) / itemsPerPage * itemsPerPage; + + calculatePage(); + } } - - public void scroll(int i) - { - if(itemsPerPage != 0) { - int oldIndex = firstIndex; - firstIndex += i*itemsPerPage; - if(firstIndex >= visibleitems.size()) - firstIndex = 0; - if(firstIndex < 0) - if(oldIndex > 0) - firstIndex = 0; - else - firstIndex = (visibleitems.size()-1)/itemsPerPage*itemsPerPage; - - calculatePage(); - } - } - - public int getPage() - { + + public int getPage() { return page; } - - public int getNumPages() - { + + public int getNumPages() { return numPages; } - - public static ArrayList visibleitems = new ArrayList(); - - public ItemStack draggedStack; - public int mouseDownSlot = -1; - - private int marginLeft; - private int marginTop; - private int rows; - private int columns; - - private boolean[] validSlotMap; - private int firstIndex; - private int itemsPerPage; - - private int page; - private int numPages; + + @Override + public boolean contains(int px, int py) { + GuiContainer gui = NEIClientUtils.getGuiContainer(); + Rectangle4i rect = new Rectangle4i(px, py, 1, 1); + for (INEIGuiHandler handler : GuiInfo.guiHandlers) + if (handler.hideItemPanelSlot(gui, rect.x, rect.y, rect.w, rect.h)) + return false; + + return super.contains(px, py); + } } diff --git a/src/codechicken/nei/ItemPanelStack.java b/src/codechicken/nei/ItemPanelStack.java deleted file mode 100644 index 408c02d7..00000000 --- a/src/codechicken/nei/ItemPanelStack.java +++ /dev/null @@ -1,29 +0,0 @@ -package codechicken.nei; - -import codechicken.nei.ItemPanel.ItemPanelObject; -import codechicken.nei.guihook.GuiContainerManager; -import net.minecraft.item.ItemStack; - -import java.util.List; - -public class ItemPanelStack implements ItemPanelObject -{ - public ItemStack item; - - public ItemPanelStack(ItemStack itemstack) - { - item = itemstack; - } - - @Override - public void draw(int x, int y) - { - GuiContainerManager.drawItem(x+1, y+1, item); - } - - @Override - public List handleTooltip(List tooltip) - { - return tooltip; - } -} diff --git a/src/codechicken/nei/ItemQuantityField.java b/src/codechicken/nei/ItemQuantityField.java index 5bd8edbe..5d5d9d3f 100644 --- a/src/codechicken/nei/ItemQuantityField.java +++ b/src/codechicken/nei/ItemQuantityField.java @@ -2,55 +2,43 @@ package codechicken.nei; public class ItemQuantityField extends TextField { - public ItemQuantityField(String ident) - { + public ItemQuantityField(String ident) { super(ident); centered = true; } - + @Override - public boolean isValid(String string) - { - if(string.equals("")) + public boolean isValid(String string) { + if (string.equals("")) return true; - - try - { + + try { return Integer.parseInt(string) >= 0; - } - catch(NumberFormatException nfe) - { + } catch (NumberFormatException nfe) { return false; } } - - public int intValue() - { + + public int intValue() { return intValue(text()); } - - public int intValue(String s) - { - try - { + + public int intValue(String s) { + try { return Integer.parseInt(s); - } - catch(NumberFormatException nfe) - { + } catch (NumberFormatException nfe) { return 0; } } - + @Override - public void loseFocus() - { + public void loseFocus() { setText(Integer.toString(NEIClientConfig.getItemQuantity())); } @Override - public void onTextChange(String oldText) - { - if(intValue(oldText) != intValue())//hacky recursion stopper + public void onTextChange(String oldText) { + if (intValue(oldText) != intValue())//hacky recursion stopper NEIClientUtils.setItemQuantity(intValue()); } } diff --git a/src/codechicken/nei/ItemSorter.java b/src/codechicken/nei/ItemSorter.java new file mode 100644 index 00000000..13c5a396 --- /dev/null +++ b/src/codechicken/nei/ItemSorter.java @@ -0,0 +1,176 @@ +package codechicken.nei; + +import codechicken.lib.config.ConfigTagParent; +import codechicken.nei.ItemList.ItemsLoadedCallback; +import codechicken.nei.api.API; +import codechicken.nei.api.ItemInfo; +import codechicken.nei.config.GuiItemSorter; +import codechicken.nei.config.OptionOpenGui; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.StatCollector; + +import java.util.*; + +public class ItemSorter implements Comparator, ItemsLoadedCallback +{ + public static class SortEntry + { + public String name; + public Comparator comparator; + + public SortEntry(String name, Comparator comparator) { + this.name = name; + this.comparator = comparator; + } + + public String getLocalisedName() { + return StatCollector.translateToLocal(name); + } + + public String getTooltip() { + String tipname = name+".tip"; + String tip = StatCollector.translateToLocal(tipname); + return !tip.equals(tipname) ? tip : null; + } + } + + public static ArrayList entries = new ArrayList(); + public static ArrayList list = new ArrayList(); + public static ItemSorter instance = new ItemSorter(); + + //optimisations + public HashMap ordering = new HashMap(); + + public static void sort(ArrayList items) { + Collections.sort(items, instance); + } + + @Override + public int compare(ItemStack o1, ItemStack o2) { + for(SortEntry e : list) { + int c = e.comparator.compare(o1, o2); + if(c != 0) return c; + } + return 0; + } + + @Override + public void itemsLoaded() { + ordering.clear(); + int i = 0; + for(ItemStack stack : ItemList.items) + ordering.put(stack, i++); + } + + public static String getSaveString() { + StringBuilder sb = new StringBuilder(); + for(SortEntry e : list) { + if(sb.length() > 0) + sb.append(','); + sb.append(e.name); + } + return sb.toString(); + } + + public static SortEntry find(String name) { + for(SortEntry e : entries) + if(e.name.equals(name)) + return e; + + return null; + } + + public static int compareInt(int a, int b) { + return a == b ? 0 : a < b ? -1 : 1; + } + + public static void add(String name, Comparator comparator) { + SortEntry e = new SortEntry(name, comparator); + entries.add(e); + ArrayList nlist = new ArrayList(list); + nlist.add(e); + list = nlist;//concurrency + } + + public static void initConfig(ConfigTagParent tag) { + //minecraft, mod, id, default, meta, name + API.addSortOption("nei.itemsort.minecraft", new Comparator() + { + @Override + public int compare(ItemStack o1, ItemStack o2) { + boolean m1 = "minecraft".equals(ItemInfo.itemOwners.get(o1.getItem())); + boolean m2 = "minecraft".equals(ItemInfo.itemOwners.get(o2.getItem())); + return m1 == m2 ? 0 : m1 ? -1 : 1; + } + }); + API.addSortOption("nei.itemsort.mod", new Comparator() + { + @Override + public int compare(ItemStack o1, ItemStack o2) { + String mod1 = ItemInfo.itemOwners.get(o1.getItem()); + String mod2 = ItemInfo.itemOwners.get(o2.getItem()); + if(mod1 == null) return mod2 == null ? 0 : 1; + if(mod2 == null) return -1; + return mod1.compareTo(mod2); + } + }); + API.addSortOption("nei.itemsort.id", new Comparator() + { + @Override + public int compare(ItemStack o1, ItemStack o2) { + int id1 = Item.getIdFromItem(o1.getItem()); + int id2 = Item.getIdFromItem(o2.getItem()); + return compareInt(id1, id2); + } + }); + API.addSortOption("nei.itemsort.default", new Comparator() + { + @Override + public int compare(ItemStack o1, ItemStack o2) { + int order1 = instance.ordering.get(o1); + int order2 = instance.ordering.get(o2); + return compareInt(order1, order2); + } + }); + API.addSortOption("nei.itemsort.damage", new Comparator() + { + @Override + public int compare(ItemStack o1, ItemStack o2) { + int id1 = o1.getItemDamage(); + int id2 = o2.getItemDamage(); + return compareInt(id1, id2); + } + }); + API.addSortOption("nei.itemsort.name", new Comparator() + { + @Override + public int compare(ItemStack o1, ItemStack o2) { + String name1 = ItemInfo.getSearchName(o1); + String name2 = ItemInfo.getSearchName(o2); + return name1.compareTo(name2); + } + }); + tag.getTag("inventory.itemsort").setDefaultValue(getSaveString()); + API.addOption(new OptionOpenGui("inventory.itemsort", GuiItemSorter.class)); + ItemList.loadCallbacks.add(instance); + } + + public static void loadConfig() { + String s = NEIClientConfig.getStringSetting("inventory.itemsort"); + if(s == null) + list = new ArrayList(entries); + else { + ArrayList nlist = new ArrayList(); + for(String s2 : s.split(",")) { + SortEntry e = find(s2.trim()); + if(e != null) + nlist.add(e); + } + for(SortEntry e : entries) + if(!nlist.contains(e)) + nlist.add(e); + list = nlist; + } + } +} diff --git a/src/codechicken/nei/ItemStackMap.java b/src/codechicken/nei/ItemStackMap.java index a9ba6268..198ad1ce 100644 --- a/src/codechicken/nei/ItemStackMap.java +++ b/src/codechicken/nei/ItemStackMap.java @@ -17,7 +17,7 @@ import static net.minecraftforge.oredict.OreDictionary.WILDCARD_VALUE; /** * A maplike class for ItemStack keys with wildcard damage/NBT. Optimised for lookup */ -public class ItemStackMap +public class ItemStackMap { public static class StackMetaKey { @@ -38,9 +38,9 @@ public class ItemStackMap } public boolean equals(Object o) { - if(!(o instanceof StackMetaKey)) + if (!(o instanceof StackMetaKey)) return false; - StackMetaKey t = (StackMetaKey)o; + StackMetaKey t = (StackMetaKey) o; return damage == t.damage && Objects.equal(tag, t.tag); } } @@ -58,110 +58,137 @@ public class ItemStackMap public class DetailMap { - public T wildcard; - public HashMap damageMap; - public HashMap tagMap; - public HashMap metaMap; + private boolean hasWildcard; + private T wildcard; + private HashMap damageMap; + private HashMap tagMap; + private HashMap metaMap; + private int size; public T get(ItemStack key) { - if(wildcard != null) + if (wildcard != null) return wildcard; - if(damageMap != null) { + if (damageMap != null) { T ret = damageMap.get(actualDamage(key)); - if(ret != null) return ret; + if (ret != null) return ret; } - if(tagMap != null) { + if (tagMap != null) { T ret = tagMap.get(key.stackTagCompound); - if(ret != null) return ret; + if (ret != null) return ret; } - if(metaMap != null) + if (metaMap != null) return metaMap.get(new StackMetaKey(key)); return null; } - public void put(ItemStack key, T value) { - switch(getKeyType(actualDamage(key), key.stackTagCompound)) { - case 0: - if(metaMap == null) metaMap = new HashMap(); - metaMap.put(new StackMetaKey(key), value); - break; - case 1: - if(tagMap == null) tagMap = new HashMap(); - tagMap.put(key.stackTagCompound, value); - break; - case 2: - if(damageMap == null) damageMap = new HashMap(); - damageMap.put(actualDamage(key), value); - break; - case 3: - wildcard = value; - break; - } - } - - public T remove(ItemStack key) { - switch(getKeyType(actualDamage(key), key.stackTagCompound)) { - case 0: - return metaMap != null ? metaMap.remove(new StackMetaKey(key)) : null; - case 1: - return tagMap != null ? tagMap.remove(key.stackTagCompound) : null; - case 2: - return damageMap != null ? damageMap.remove(actualDamage(key)) : null; - case 3: - T ret = wildcard; - wildcard = null; - return ret; + public T put(ItemStack key, T value) { + try { + switch (getKeyType(actualDamage(key), key.stackTagCompound)) { + case 0: + if (metaMap == null) metaMap = new HashMap(); + return metaMap.put(new StackMetaKey(key), value); + case 1: + if (tagMap == null) tagMap = new HashMap(); + return tagMap.put(key.stackTagCompound, value); + case 2: + if (damageMap == null) damageMap = new HashMap(); + return damageMap.put(actualDamage(key), value); + case 3: + T ret = wildcard; + wildcard = value; + hasWildcard = true; + return ret; + } + } finally { + updateSize(); } return null; } + public T remove(ItemStack key) { + try { + switch (getKeyType(actualDamage(key), key.stackTagCompound)) { + case 0: + return metaMap != null ? metaMap.remove(new StackMetaKey(key)) : null; + case 1: + return tagMap != null ? tagMap.remove(key.stackTagCompound) : null; + case 2: + return damageMap != null ? damageMap.remove(actualDamage(key)) : null; + case 3: + T ret = wildcard; + wildcard = null; + hasWildcard = false; + return ret; + } + } finally { + updateSize(); + } + return null; + } + + private void updateSize() { + int newSize = (hasWildcard ? 1 : 0) + + (metaMap != null ? metaMap.size() : 0) + + (tagMap != null ? tagMap.size() : 0) + + (damageMap != null ? damageMap.size() : 0); + + if(newSize != size) { + ItemStackMap.this.size += newSize-size; + size = newSize; + } + } + public void addKeys(Item item, List list) { - if(wildcard != null) - list.add(newItemStack(item, 1, WILDCARD_VALUE, WILDCARD_TAG)); - if(damageMap != null) - for(int damage : damageMap.keySet()) + if (wildcard != null) + list.add(wildcard(item)); + if (damageMap != null) + for (int damage : damageMap.keySet()) list.add(newItemStack(item, 1, damage, WILDCARD_TAG)); - if(tagMap != null) - for(NBTTagCompound tag : tagMap.keySet()) + if (tagMap != null) + for (NBTTagCompound tag : tagMap.keySet()) list.add(newItemStack(item, 1, WILDCARD_VALUE, tag)); - if(metaMap != null) - for(StackMetaKey key : metaMap.keySet()) + if (metaMap != null) + for (StackMetaKey key : metaMap.keySet()) list.add(newItemStack(item, 1, key.damage, key.tag)); } public void addValues(List list) { - if(wildcard != null) + if (wildcard != null) list.add(wildcard); - if(damageMap != null) + if (damageMap != null) list.addAll(damageMap.values()); - if(tagMap != null) + if (tagMap != null) list.addAll(tagMap.values()); - if(metaMap != null) + if (metaMap != null) list.addAll(metaMap.values()); } public void addEntries(Item item, List> list) { - if(wildcard != null) + if (wildcard != null) list.add(new Entry(newItemStack(item, 1, WILDCARD_VALUE, WILDCARD_TAG), wildcard)); - if(damageMap != null) - for(Map.Entry entry : damageMap.entrySet()) + if (damageMap != null) + for (Map.Entry entry : damageMap.entrySet()) list.add(new Entry(newItemStack(item, 1, entry.getKey(), WILDCARD_TAG), entry.getValue())); - if(tagMap != null) - for(Map.Entry entry : tagMap.entrySet()) + if (tagMap != null) + for (Map.Entry entry : tagMap.entrySet()) list.add(new Entry(newItemStack(item, 1, WILDCARD_VALUE, entry.getKey()), entry.getValue())); - if(metaMap != null) - for(Map.Entry entry : metaMap.entrySet()) + if (metaMap != null) + for (Map.Entry entry : metaMap.entrySet()) list.add(new Entry(newItemStack(item, 1, entry.getKey().damage, entry.getKey().tag), entry.getValue())); } } public static int getKeyType(int damage, NBTTagCompound tag) { - int i = 0; - if(isWildcard(damage)) i = 1; - if(isWildcard(tag)) i |= 2; - return i; + int i = 0; + if (isWildcard(damage)) i = 1; + if (isWildcard(tag)) i |= 2; + return i; + } + + public static ItemStack wildcard(Item item) { + return newItemStack(item, 1, WILDCARD_VALUE, WILDCARD_TAG); } public static boolean isWildcard(int damage) { @@ -179,10 +206,11 @@ public class ItemStackMap WILDCARD_TAG.setBoolean("*", true); } - protected HashMap itemMap = new HashMap(); + private HashMap itemMap = new HashMap(); + private int size; public T get(ItemStack key) { - if(key == null || key.getItem() == null) + if (key == null || key.getItem() == null) return null; DetailMap map = itemMap.get(key.getItem()); @@ -190,11 +218,11 @@ public class ItemStackMap } public void put(ItemStack key, T value) { - if(key == null || key.getItem() == null) + if (key == null || key.getItem() == null) return; DetailMap map = itemMap.get(key.getItem()); - if(map == null) + if (map == null) itemMap.put(key.getItem(), map = new DetailMap()); map.put(key, value); } @@ -213,22 +241,30 @@ public class ItemStackMap public List keys() { LinkedList list = new LinkedList(); - for(Map.Entry entry : itemMap.entrySet()) + for (Map.Entry entry : itemMap.entrySet()) entry.getValue().addKeys(entry.getKey(), list); return list; } public List values() { LinkedList list = new LinkedList(); - for(DetailMap map : itemMap.values()) + for (DetailMap map : itemMap.values()) map.addValues(list); return list; } public List> entries() { LinkedList> list = new LinkedList>(); - for(Map.Entry entry : itemMap.entrySet()) + for (Map.Entry entry : itemMap.entrySet()) entry.getValue().addEntries(entry.getKey(), list); return list; } + + public int size() { + return size; + } + + public boolean isEmpty() { + return size == 0; + } } diff --git a/src/codechicken/nei/ItemStackSet.java b/src/codechicken/nei/ItemStackSet.java index 04a517e7..3f0dd655 100644 --- a/src/codechicken/nei/ItemStackSet.java +++ b/src/codechicken/nei/ItemStackSet.java @@ -1,14 +1,34 @@ package codechicken.nei; +import codechicken.nei.api.ItemFilter; +import net.minecraft.block.Block; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import java.util.List; -public class ItemStackSet +public class ItemStackSet implements ItemFilter { ItemStackMap underlying = new ItemStackMap(); + public ItemStackSet with(ItemStack... items) { + for(ItemStack item : items) + add(item); + return this; + } + + public ItemStackSet with(Item... items) { + for(Item item : items) + add(ItemStackMap.wildcard(item)); + return this; + } + + public ItemStackSet with(Block... blocks) { + for(Block block : blocks) + add(ItemStackMap.wildcard(Item.getItemFromBlock(block))); + return this; + } + public void add(ItemStack item) { underlying.put(item, new Object()); } @@ -22,7 +42,7 @@ public class ItemStackSet } public boolean containsAll(Item item) { - return underlying.itemMap.containsKey(item) && underlying.itemMap.get(item).wildcard != null; + return underlying.get(ItemStackMap.wildcard(item)) != null; } public List values() { @@ -32,4 +52,29 @@ public class ItemStackSet public void clear() { underlying.clear(); } + + @Override + public boolean matches(ItemStack item) { + return contains(item); + } + + public int size() { + return underlying.size(); + } + + public boolean isEmpty() { + return underlying.isEmpty(); + } + + public static ItemStackSet of(Block... blocks) { + return new ItemStackSet().with(blocks); + } + + public static ItemStackSet of(Item... items) { + return new ItemStackSet().with(items); + } + + public static ItemStackSet of(ItemStack... items) { + return new ItemStackSet().with(items); + } } diff --git a/src/codechicken/nei/LayoutManager.java b/src/codechicken/nei/LayoutManager.java index d400289f..346332ec 100644 --- a/src/codechicken/nei/LayoutManager.java +++ b/src/codechicken/nei/LayoutManager.java @@ -38,7 +38,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH private static TreeSet controlWidgets; public static ItemPanel itemPanel; - public static Button dropDown; + public static SubsetWidget dropDown; public static TextField searchField; public static Button options; @@ -121,11 +121,10 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH @Override public boolean objectUnderMouse(GuiContainer gui, int mousex, int mousey) { - if (!isHidden() && isEnabled()) { + if (!isHidden() && isEnabled()) for (Widget widget : controlWidgets) if (widget.contains(mousex, mousey)) return true; - } return false; } @@ -265,13 +264,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH private static void init() { itemPanel = new ItemPanel(); - dropDown = new Button("NEI Subsets") - { - @Override - public boolean onButtonPress(boolean rightclick) { - return false; - } - }; + dropDown = new SubsetWidget(); searchField = new SearchField("search"); options = new Button("Options") @@ -422,7 +415,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH public String getButtonTip() { if ((state & 0x3) != 2) { if (shiftKey()) - return translate("inventory.delete.all"); + return translate("inventory.delete.inv"); if (NEIController.canUseDeleteMode()) return getStateTip("delete", state); } @@ -580,11 +573,9 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH NEIController.load(gui); - if (checkCreativeInv(gui)) { - if (gui.mc.currentScreen instanceof GuiContainerCreative)//makes cycle transititions seemless. Only closes if we are opening from fresh - gui.mc.displayGuiScreen(null); - return; - } + if (checkCreativeInv(gui) && + gui.mc.currentScreen instanceof GuiContainerCreative)//makes cycle transitions seamless. Only closes if we are opening from fresh + gui.mc.displayGuiScreen(null); } @Override @@ -726,7 +717,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH @Override public void renderSlotOverlay(GuiContainer window, Slot slot) { ItemStack item = slot.getStack(); - if (world.nbt.getBoolean("searchinventories") && (item == null ? !getSearchExpression().equals("") : !ItemList.itemMatchesSearch(item))) { + if (world.nbt.getBoolean("searchinventories") && (item == null ? !getSearchExpression().equals("") : !ItemList.itemMatches(item))) { GL11.glDisable(GL11.GL_LIGHTING); GL11.glTranslatef(0, 0, 150); drawRect(slot.xDisplayPosition, slot.yDisplayPosition, 16, 16, 0x80000000); diff --git a/src/codechicken/nei/LayoutStyleDefault.java b/src/codechicken/nei/LayoutStyleDefault.java index 9fa995f1..7e553436 100644 --- a/src/codechicken/nei/LayoutStyleDefault.java +++ b/src/codechicken/nei/LayoutStyleDefault.java @@ -20,40 +20,40 @@ public abstract class LayoutStyleDefault extends LayoutStyle reset(); prev.y = 2; - prev.height = 16; - prev.width = containerLeft / 3; + prev.h = 16; + prev.w = containerLeft / 3; prev.x = (containerWidth + windowWidth) / 2 + 2; - next.x = windowWidth - prev.width - 2; + next.x = windowWidth - prev.w - 2; next.y = prev.y; - next.width = prev.width; - next.height = prev.height; + next.w = prev.w; + next.h = prev.h; pageLabel.x = containerLeft * 3 / 2 + containerWidth + 1; pageLabel.y = prev.y + 5; pageLabel.text = "(" + itemPanel.getPage() + "/" + itemPanel.getNumPages() + ")"; - itemPanel.y = prev.height + prev.y; + itemPanel.y = prev.h + prev.y; itemPanel.x = (containerWidth + windowWidth) / 2 + 3; - itemPanel.width = windowWidth - 3 - itemPanel.x; - itemPanel.height = windowHeight - 15 - itemPanel.y; + itemPanel.w = windowWidth - 3 - itemPanel.x; + itemPanel.h = windowHeight - 15 - itemPanel.y; if (!canPerformAction("item")) - itemPanel.height += 15; + itemPanel.h += 15; itemPanel.resize(); - more.width = more.height = less.width = less.height = 16; + more.w = more.h = less.w = less.h = 16; less.x = prev.x; - more.x = windowWidth - less.width - 2; - more.y = less.y = windowHeight - more.height - 2; + more.x = windowWidth - less.w - 2; + more.y = less.y = windowHeight - more.h - 2; - quantity.x = less.x + less.width + 2; + quantity.x = less.x + less.w + 2; quantity.y = less.y; - quantity.width = more.x - quantity.x - 2; - quantity.height = less.height; + quantity.w = more.x - quantity.x - 2; + quantity.h = less.h; options.x = isEnabled() ? 0 : 6; options.y = isEnabled() ? windowHeight - 22 : windowHeight - 28; - options.width = 80; - options.height = 22; + options.w = 80; + options.h = 22; delete.state = 0x4; if (NEIController.getDeleteMode()) @@ -101,13 +101,13 @@ public abstract class LayoutStyleDefault extends LayoutStyle if (canPerformAction("heal")) layoutButton(heal); - searchField.y = windowHeight - searchField.height - 2; + searchField.y = windowHeight - searchField.h - 2; - dropDown.height = 20; - dropDown.width = prev.x - dropDown.x - 3; - searchField.height = 20; - searchField.width = 150; - searchField.x = (windowWidth - searchField.width) / 2; + dropDown.h = 20; + dropDown.w = prev.x - dropDown.x - 3; + searchField.h = 20; + searchField.w = 150; + searchField.x = (windowWidth - searchField.w) / 2; if (!visiblity.showItemSection) { //TODO dropDown.setDropDown(0); @@ -116,8 +116,8 @@ public abstract class LayoutStyleDefault extends LayoutStyle int maxWidth = 0; for (int i = 0; i < 7; i++) { - deleteButtons[i].width = 16; - deleteButtons[i].height = 16; + deleteButtons[i].w = 16; + deleteButtons[i].h = 16; NBTTagCompound statelist = global.nbt.getCompoundTag("statename"); global.nbt.setTag("statename", statelist); @@ -140,11 +140,11 @@ public abstract class LayoutStyleDefault extends LayoutStyle for (int i = 0; i < 7; i++) { stateButtons[i].x = 0; stateButtons[i].y = 58 + i * 22; - stateButtons[i].height = 20; + stateButtons[i].h = 20; stateButtons[i].x = 0; - stateButtons[i].width = maxWidth; - deleteButtons[i].x = stateButtons[i].width + 3; + stateButtons[i].w = maxWidth; + deleteButtons[i].x = stateButtons[i].w + 3; deleteButtons[i].y = stateButtons[i].y + 2; } } diff --git a/src/codechicken/nei/LayoutStyleMinecraft.java b/src/codechicken/nei/LayoutStyleMinecraft.java index 22eb5625..57d3a152 100644 --- a/src/codechicken/nei/LayoutStyleMinecraft.java +++ b/src/codechicken/nei/LayoutStyleMinecraft.java @@ -48,8 +48,8 @@ public class LayoutStyleMinecraft extends LayoutStyleDefault clickButtonCount++; } - button.height = 17; - button.width = button.contentWidth() + 6; + button.h = 17; + button.w = button.contentWidth() + 6; } @Override @@ -65,25 +65,31 @@ public class LayoutStyleMinecraft extends LayoutStyleDefault tex = 2; else tex = 1; - LayoutManager.drawButtonBackground(b.x, b.y, b.width, b.height, true, tex); + LayoutManager.drawButtonBackground(b.x, b.y, b.w, b.h, true, tex); Image icon = b.getRenderIcon(); if (icon == null) { int colour = tex == 2 ? 0xffffa0 : tex == 0 ? 0x601010 : 0xe0e0e0; - drawStringC(b.getRenderLabel(), b.x + b.width / 2, b.y + (b.height - 8) / 2, colour); + drawStringC(b.getRenderLabel(), b.x + b.w / 2, b.y + (b.h - 8) / 2, colour); } else { GL11.glColor4f(1, 1, 1, 1); - int iconx = b.x + (b.width - icon.width) / 2; - int icony = b.y + (b.height - icon.height) / 2; + int iconx = b.x + (b.w - icon.width) / 2; + int icony = b.y + (b.h - icon.height) / 2; LayoutManager.drawIcon(iconx, icony, icon); } } @Override - public boolean texturedButtons() { - return true; + public void drawSubsetTag(String text, int x, int y, int w, int h, int state, boolean mouseover) { + if(state == 1) + GL11.glColor4f(0.65F, 0.65F, 0.65F, 1.0F); + else + GL11.glColor4f(1, 1, 1, 1); + LayoutManager.drawButtonBackground(x, y, w, h, false, state == 0 ? 0 : 1); + if(text != null) + drawStringC(text, x, y, w, h, state == 2 ? 0xFFE0E0E0 : 0xFFA0A0A0); } } diff --git a/src/codechicken/nei/LayoutStyleTMIOld.java b/src/codechicken/nei/LayoutStyleTMIOld.java index 3b748a8e..325990eb 100644 --- a/src/codechicken/nei/LayoutStyleTMIOld.java +++ b/src/codechicken/nei/LayoutStyleTMIOld.java @@ -4,6 +4,7 @@ import codechicken.nei.guihook.GuiContainerManager; import static codechicken.lib.gui.GuiDraw.drawRect; import static codechicken.lib.gui.GuiDraw.drawString; +import static codechicken.lib.gui.GuiDraw.drawStringC; import static codechicken.nei.LayoutManager.*; public class LayoutStyleTMIOld extends LayoutStyleDefault @@ -63,10 +64,10 @@ public class LayoutStyleTMIOld extends LayoutStyleDefault clickButtonCount++; } - button.height = 14; - button.width = button.contentWidth() + 2; + button.h = 14; + button.w = button.contentWidth() + 2; if((button.state & 0x4) != 0) - button.width += stateOff.width; + button.w += stateOff.width; } @Override @@ -88,10 +89,10 @@ public class LayoutStyleTMIOld extends LayoutStyleDefault int cwidth = b.contentWidth(); if((b.state & 0x4) != 0) cwidth += stateOff.width; - int textx = b.x + (b.width - cwidth) / 2; - int texty = b.y + (b.height - 8) / 2; + int textx = b.x + (b.w - cwidth) / 2; + int texty = b.y + (b.h - 8) / 2; - drawRect(b.x, b.y, b.width, b.height, b.contains(mousex, mousey) ? 0xee401008 : 0xee000000); + drawRect(b.x, b.y, b.w, b.h, b.contains(mousex, mousey) ? 0xee401008 : 0xee000000); Image icon = b.getRenderIcon(); if(icon == null) @@ -100,7 +101,7 @@ public class LayoutStyleTMIOld extends LayoutStyleDefault } else { - int icony = b.y + (b.height - icon.height) / 2; + int icony = b.y + (b.h - icon.height) / 2; LayoutManager.drawIcon(textx, icony, icon); if((b.state & 0x3) == 2) drawRect(textx, icony, icon.width, icon.height, 0x80000000); @@ -118,10 +119,17 @@ public class LayoutStyleTMIOld extends LayoutStyleDefault } } } - + @Override - public boolean texturedButtons() - { - return false; + public void drawSubsetTag(String text, int x, int y, int w, int h, int state, boolean mouseover) { + drawRect(x, y, w, h, mouseover ? 0xFF401008 : 0xFF000000); + if(text != null) { + int colour = -1; + if (state == 0) + colour = 0xFF601010; + else if (state == 1) + colour = 0xFF807070; + drawStringC(text, x, y, w, h, colour, state == 0); + } } } diff --git a/src/codechicken/nei/NEIActions.java b/src/codechicken/nei/NEIActions.java index 76371ce4..a1f30825 100644 --- a/src/codechicken/nei/NEIActions.java +++ b/src/codechicken/nei/NEIActions.java @@ -61,7 +61,6 @@ public class NEIActions addAction("magnet", true); addAction("enchant", true); addAction("potion", true); - addAction("itemnbt", "item", true); canDisable.add("dawn"); canDisable.add("noon"); diff --git a/src/codechicken/nei/NEICPH.java b/src/codechicken/nei/NEICPH.java index f16cc8a1..4ff7d46d 100644 --- a/src/codechicken/nei/NEICPH.java +++ b/src/codechicken/nei/NEICPH.java @@ -105,11 +105,11 @@ public class NEICPH implements IClientPacketHandler } else { try { ClientHandler.instance().loadWorld(world, true); - NEIClientConfig.loadWorld(getSaveName(worldName)); NEIClientConfig.setHasSMPCounterPart(true); + NEIClientConfig.loadWorld(getSaveName(worldName)); sendRequestLoginInfo(); - } catch (Exception nce) { - nce.printStackTrace(); + } catch (Exception e) { + NEIClientConfig.logger.error("Error handling SMP Check", e); } } } diff --git a/src/codechicken/nei/NEIClientConfig.java b/src/codechicken/nei/NEIClientConfig.java index e7f1c8db..4d38555e 100644 --- a/src/codechicken/nei/NEIClientConfig.java +++ b/src/codechicken/nei/NEIClientConfig.java @@ -8,7 +8,6 @@ import codechicken.nei.api.*; import codechicken.nei.config.*; import codechicken.nei.recipe.RecipeInfo; import codechicken.obfuscator.ObfuscationRun; -import net.minecraft.client.AnvilConverterException; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.item.ItemStack; @@ -39,8 +38,6 @@ public class NEIClientConfig new ConfigFile(new File(configDir, "client.cfg"))); public static ConfigSet world; - //public static ItemVisibilityHash vishash; - public static ItemStack creativeInv[]; private static boolean statesSaved[] = new boolean[7]; @@ -122,20 +119,26 @@ public class NEIClientConfig return true; } }); + + ItemSorter.initConfig(tag); + tag.getTag("inventory.itemIDs").getIntValue(1); API.addOption(new OptionCycled("inventory.itemIDs", 3, true)); + tag.getTag("inventory.searchmode").getIntValue(1); + API.addOption(new OptionCycled("inventory.searchmode", 3, true)); + tag.getTag("world.highlight_tips").getBooleanValue(false); tag.getTag("world.highlight_tips.x").getIntValue(5000); tag.getTag("world.highlight_tips.y").getIntValue(100); - API.addOption(new OptionHighlightTips("world.highlight_tips")); + API.addOption(new OptionOpenGui("world.highlight_tips", GuiHighlightTips.class)); tag.getTag("inventory.profileRecipes").getBooleanValue(false); API.addOption(new OptionToggleButton("inventory.profileRecipes", true)); tag.getTag("command.creative").setDefaultValue("/gamemode {0} {1}"); API.addOption(new OptionTextField("command.creative")); - tag.getTag("command.item").setDefaultValue("/give {0} {1} {2} {3}"); + tag.getTag("command.item").setDefaultValue("/give {0} {1} {2} {3} {4}"); API.addOption(new OptionTextField("command.item")); tag.getTag("command.time").setDefaultValue("/time set {0}"); API.addOption(new OptionTextField("command.time")); @@ -257,17 +260,18 @@ public class NEIClientConfig classDiscoverer.findClasses(); - for (Class class1 : classDiscoverer.classes) { + for (Class clazz : classDiscoverer.classes) { try { - IConfigureNEI config = (IConfigureNEI) class1.newInstance(); + IConfigureNEI config = (IConfigureNEI) clazz.newInstance(); config.loadConfig(); NEIModContainer.plugins.add(config); - logger.debug("Loaded " + class1.getName()); + logger.debug("Loaded " + clazz.getName()); } catch (Exception e) { - logger.error("Failed to Load " + class1.getName()); - e.printStackTrace(); + logger.error("Failed to Load " + clazz.getName(), e); } } + + ItemSorter.loadConfig(); } public static void loadStates() { @@ -328,10 +332,6 @@ public class NEIClientConfig return getSetting(s).getValue(); } - public static boolean canDump() { - return getBooleanSetting("ID dump.itemIDs") || getBooleanSetting("ID dump.blockIDs") || getBooleanSetting("ID dump.unused itemIDs") || getBooleanSetting("ID dump.unused blockIDs"); - } - public static boolean showIDs() { int i = getIntSetting("inventory.itemIDs"); return i == 2 || (i == 1 && isEnabled() && !isHidden()); @@ -462,6 +462,10 @@ public class NEIClientConfig enabledActions.clear(); } + public static boolean canCheatItem(ItemStack stack) { + return canPerformAction("item") && !bannedBlocks.contains(stack); + } + public static boolean canPerformAction(String name) { if (!isEnabled()) return false; @@ -512,16 +516,15 @@ public class NEIClientConfig try { saves = Minecraft.getMinecraft().getSaveLoader().getSaveList(); } catch (Exception e) { - e.printStackTrace(); + logger.error("Error loading saves", e); return; } HashSet saveFileNames = new HashSet(); for (SaveFormatComparator save : saves) saveFileNames.add(save.getFileName()); - for (File file : saveDir.listFiles()) { + for (File file : saveDir.listFiles()) if (file.isDirectory() && !saveFileNames.contains(file.getName())) ObfuscationRun.deleteDir(file, true); - } } } diff --git a/src/codechicken/nei/NEIClientUtils.java b/src/codechicken/nei/NEIClientUtils.java index c0f3f4cf..c668edd8 100644 --- a/src/codechicken/nei/NEIClientUtils.java +++ b/src/codechicken/nei/NEIClientUtils.java @@ -8,12 +8,15 @@ import codechicken.nei.api.INEIGuiHandler; import codechicken.nei.api.ItemInfo; import com.google.common.collect.Iterables; import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.Container; import net.minecraft.inventory.Slot; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.IChatComponent; +import net.minecraft.util.ResourceLocation; import org.lwjgl.input.Keyboard; import java.text.MessageFormat; @@ -96,36 +99,34 @@ public class NEIClientUtils extends NEIServerUtils } /** - * @param typeStack - * @param button * @param mode -1 = normal cheats, 0 = no infinites, 1 = replenish stack */ - public static void cheatItem(ItemStack typeStack, int button, int mode) { - if (!canPerformAction("item") || typeStack.hasTagCompound() && !canPerformAction("itemnbt")) + public static void cheatItem(ItemStack stack, int button, int mode) { + if (!canCheatItem(stack)) return; - if (mode == -1 && button == 0 && NEIClientUtils.shiftKey()) { + if (mode == -1 && button == 0 && shiftKey() && NEIClientConfig.hasSMPCounterPart()) { for (IInfiniteItemHandler handler : ItemInfo.infiniteHandlers) { - if (!handler.canHandleItem(typeStack)) + if (!handler.canHandleItem(stack)) continue; - ItemStack stack = handler.getInfiniteItem(typeStack); - if (stack != null) { - giveStack(stack, stack.stackSize, true); + ItemStack inf = handler.getInfiniteItem(stack); + if (inf != null) { + giveStack(inf, inf.stackSize, true); return; } } - cheatItem(typeStack, button, 0); + cheatItem(stack, button, 0); } else if (button == 1) { - giveStack(typeStack, 1); + giveStack(stack, 1); } else { - if (mode == 1 && typeStack.stackSize < typeStack.getMaxStackSize()) { - giveStack(typeStack, typeStack.getMaxStackSize() - typeStack.stackSize); + if (mode == 1 && stack.stackSize < stack.getMaxStackSize()) { + giveStack(stack, stack.getMaxStackSize() - stack.stackSize); } else { int amount = getItemQuantity(); if (amount == 0) - amount = typeStack.getMaxStackSize(); - giveStack(typeStack, amount); + amount = stack.getMaxStackSize(); + giveStack(stack, amount); } } } @@ -138,11 +139,11 @@ public class NEIClientUtils extends NEIServerUtils giveStack(itemstack, i, false); } - public static void giveStack(ItemStack itemstack, int i, boolean infinite) { - ItemStack itemstack1 = copyStack(itemstack, i); + public static void giveStack(ItemStack base, int i, boolean infinite) { + ItemStack stack = copyStack(base, i); if (hasSMPCounterPart()) { - ItemStack typestack = copyStack(itemstack1, 1); - if (!infinite && !canItemFitInInventory(mc().thePlayer, itemstack1) && (mc().currentScreen instanceof GuiContainer)) { + ItemStack typestack = copyStack(stack, 1); + if (!infinite && !canItemFitInInventory(mc().thePlayer, stack) && (mc().currentScreen instanceof GuiContainer)) { GuiContainer gui = getGuiContainer(); List> handlerSlots = new LinkedList>(); for(INEIGuiHandler handler : GuiInfo.guiHandlers) @@ -155,7 +156,7 @@ public class NEIClientUtils extends NEIServerUtils if(!slot.isItemValid(typestack) || !InventoryUtils.canStack(slot.getStack(), typestack)) continue; - int qty = Math.min(itemstack1.stackSize - given, increment); + int qty = Math.min(stack.stackSize - given, increment); int current = slot.getHasStack() ? slot.getStack().stackSize : 0; qty = Math.min(qty, slot.getSlotStackLimit() - current); @@ -163,49 +164,28 @@ public class NEIClientUtils extends NEIServerUtils slot.putStack(newStack); setSlotContents(slotNo, newStack, true); given += qty; - if(given >= itemstack1.stackSize) + if(given >= stack.stackSize) break; } if(given > 0) NEICPH.sendGiveItem(copyStack(typestack, given), false, false); } else - NEICPH.sendGiveItem(itemstack1, infinite, true); + NEICPH.sendGiveItem(stack, infinite, true); } else { - for (int given = 0; given < itemstack1.stackSize; ) { - int qty = Math.min(itemstack1.stackSize - given, itemstack1.getMaxStackSize()); - sendCommand(getStringSetting("command.item"), mc().thePlayer.getCommandSenderName(), itemstack1.getItem().getUnlocalizedName(), qty, itemstack1.getItemDamage()); + for (int given = 0; given < stack.stackSize; ) { + int qty = Math.min(stack.stackSize - given, stack.getMaxStackSize()); + sendCommand(getStringSetting("command.item"), + mc().thePlayer.getCommandSenderName(), + Item.getIdFromItem(stack.getItem()), + qty, + stack.getItemDamage(), + stack.hasTagCompound() ? stack.getTagCompound().toString() : "", + Item.itemRegistry.getNameForObject(stack.getItem())); given += qty; } } } - public static void updateUnlimitedItems() { - ItemStack itemstack = getHeldItem(); - if (itemstack != null && itemstack.stackSize > 64) - itemstack.stackSize = 1; - - ItemStack aitemstack[] = mc().thePlayer.inventory.mainInventory; - for (int slot = 0; slot < aitemstack.length; slot++) { - ItemStack itemstack1 = aitemstack[slot]; - if (itemstack1 == null) - continue; - - if (itemstack1.stackSize < 0 || itemstack1.stackSize > 64) - itemstack1.stackSize = 111; - - if (itemstack1.getItemDamage() > -32000 && itemstack1.getItemDamage() < -30000) - itemstack1.setItemDamage(-32000); - } - } - - public static boolean itemListContains(ItemStack test) { - for (ItemStack stack : ItemList.itemMap.get(test.getItem())) - if (areStacksIdentical(stack, test)) - return true; - - return false; - } - public static boolean canItemFitInInventory(EntityPlayer player, ItemStack itemstack) { return InventoryUtils.getInsertibleQuantity(new InventoryRange(player.inventory, 0, 36), itemstack) > 0; } @@ -368,4 +348,8 @@ public class NEIClientUtils extends NEIServerUtils public static boolean altKey() { return Keyboard.isKeyDown(Keyboard.KEY_LMENU) || Keyboard.isKeyDown(Keyboard.KEY_RMENU); } + + public static void playClickSound() { + mc().getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F)); + } } diff --git a/src/codechicken/nei/NEIController.java b/src/codechicken/nei/NEIController.java index a8c25ea4..7c93ac6a 100644 --- a/src/codechicken/nei/NEIController.java +++ b/src/codechicken/nei/NEIController.java @@ -28,6 +28,7 @@ public class NEIController implements IContainerSlotClickHandler, IContainerInpu private static IInfiniteItemHandler heldStackInfinite; private static int selectedItem; + private ItemStack firstheld; public static void load() { GuiContainerManager.addSlotClickHandler(instance); @@ -47,7 +48,9 @@ public class NEIController implements IContainerSlotClickHandler, IContainerInpu API.registerNEIGuiHandler((INEIGuiHandler) gui); } - ItemStack firstheld; + public static boolean isSpreading(GuiContainer gui) { + return gui.field_147007_t && gui.field_147008_s.size() > 1; + } public static void updateUnlimitedItems(InventoryPlayer inventory) { if (!NEIClientConfig.canPerformAction("item") || !NEIClientConfig.hasSMPCounterPart()) @@ -104,7 +107,9 @@ public class NEIController implements IContainerSlotClickHandler, IContainerInpu @Override public boolean handleSlotClick(GuiContainer gui, int slotIndex, int button, Slot slot, int modifier, boolean eventconsumed) { - if (eventconsumed || !NEIClientConfig.isEnabled()) + if (eventconsumed || + !NEIClientConfig.isEnabled() || + isSpreading(gui)) return eventconsumed; if (deleteMode && slotIndex >= 0 && slot != null) { @@ -127,6 +132,16 @@ public class NEIController implements IContainerSlotClickHandler, IContainerInpu return true; } + if (NEIClientUtils.controlKey() + && slot != null && slot.getStack() != null + && slot.isItemValid(slot.getStack())) { + NEIClientUtils.cheatItem(slot.getStack(), button, 1); + return true; + } + + if(GuiInfo.hasCustomSlots(gui)) + return false; + if (slotIndex >= 0 && NEIClientUtils.shiftKey() && NEIClientUtils.getHeldItem() != null && !slot.getHasStack()) { ItemStack held = NEIClientUtils.getHeldItem(); manager.handleSlotClick(slot.slotNumber, button, 0); @@ -136,14 +151,6 @@ public class NEIController implements IContainerSlotClickHandler, IContainerInpu return true; } - if (NEIClientUtils.controlKey() - && slot != null && slot.getStack() != null - && NEIClientConfig.canPerformAction("item") - && slot.isItemValid(slot.getStack())) { - NEIClientUtils.cheatItem(slot.getStack(), button, 1); - return true; - } - if (slotIndex == -999 && NEIClientUtils.shiftKey() && button == 0) { fastTransferManager.throwAll(gui, pickedUpFromSlot); return true; @@ -189,7 +196,9 @@ public class NEIController implements IContainerSlotClickHandler, IContainerInpu @Override public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyCode) { - if (!NEIClientConfig.isEnabled()) + if (!NEIClientConfig.isEnabled() || + GuiInfo.hasCustomSlots(gui) || + isSpreading(gui)) return false; Slot slot = GuiContainerManager.getSlotMouseOver(gui); @@ -211,7 +220,7 @@ public class NEIController implements IContainerSlotClickHandler, IContainerInpu @Override public boolean mouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) { - if (!NEIClientConfig.isEnabled()) + if (!NEIClientConfig.isEnabled() || GuiInfo.hasCustomSlots(gui)) return false; Point mousePos = getMousePosition(); diff --git a/src/codechicken/nei/NEIModContainer.java b/src/codechicken/nei/NEIModContainer.java index ff4a7681..b7638bbb 100644 --- a/src/codechicken/nei/NEIModContainer.java +++ b/src/codechicken/nei/NEIModContainer.java @@ -13,6 +13,7 @@ import cpw.mods.fml.common.LoadController; import cpw.mods.fml.common.MetadataCollection; import cpw.mods.fml.common.ModMetadata; import cpw.mods.fml.common.event.FMLInitializationEvent; +import cpw.mods.fml.common.event.FMLPreInitializationEvent; import cpw.mods.fml.common.versioning.ArtifactVersion; import cpw.mods.fml.common.versioning.VersionParser; import cpw.mods.fml.common.versioning.VersionRange; @@ -69,6 +70,12 @@ public class NEIModContainer extends DummyModContainer return true; } + @Subscribe + public void preInit(FMLPreInitializationEvent event) { + if (CommonUtils.isClient()) + ClientHandler.preInit(); + } + @Subscribe public void init(FMLInitializationEvent event) { if (CommonUtils.isClient()) diff --git a/src/codechicken/nei/NEIServerUtils.java b/src/codechicken/nei/NEIServerUtils.java index c55670f4..5a8dfe84 100644 --- a/src/codechicken/nei/NEIServerUtils.java +++ b/src/codechicken/nei/NEIServerUtils.java @@ -24,9 +24,9 @@ import net.minecraft.world.WorldServer; import net.minecraft.world.WorldSettings.GameType; import net.minecraftforge.oredict.OreDictionary; -import java.util.AbstractList; -import java.util.ArrayList; -import java.util.List; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.*; public class NEIServerUtils { @@ -128,10 +128,10 @@ public class NEIServerUtils * @return whether the two items are the same in terms of damage and itemID. */ public static boolean areStacksSameType(ItemStack stack1, ItemStack stack2) { - if (stack1 == null || stack2 == null) - return stack1 == stack2; - - return InventoryUtils.canStack(stack1, stack2); + return stack1 != null && stack2 != null && + (stack1.getItem() == stack2.getItem() && + (!stack2.getHasSubtypes() || stack2.getItemDamage() == stack1.getItemDamage()) && + ItemStack.areItemStackTagsEqual(stack2, stack1)); } /** @@ -142,10 +142,8 @@ public class NEIServerUtils * @return whether the two items are the same from the perspective of a crafting inventory. */ public static boolean areStacksSameTypeCrafting(ItemStack stack1, ItemStack stack2) { - if (stack1 == null || stack2 == null) - return false; - - return stack1.getItem() == stack2.getItem() && + return stack1 != null && stack2 != null && + stack1.getItem() == stack2.getItem() && (stack1.getItemDamage() == stack2.getItemDamage() || stack1.getItemDamage() == OreDictionary.WILDCARD_VALUE || stack2.getItemDamage() == OreDictionary.WILDCARD_VALUE || stack1.getItem().isDamageable()); } @@ -361,4 +359,18 @@ public class NEIServerUtils sb.deleteCharAt(sb.length()-1); return sb; } + + public static void logOnce(Throwable t, Set stackTraces, String message) { + logOnce(t, stackTraces, message, ""); + } + + public static void logOnce(Throwable t, Set stackTraces, String message, String identifier) { + StringWriter sw = new StringWriter(); + t.printStackTrace(new PrintWriter(sw)); + String stackTrace = identifier + sw.toString(); + if (!stackTraces.contains(stackTrace)) { + NEIServerConfig.logger.error(message, t); + stackTraces.add(stackTrace); + } + } } diff --git a/src/codechicken/nei/PlayerSave.java b/src/codechicken/nei/PlayerSave.java index 55e3fa69..01e75792 100644 --- a/src/codechicken/nei/PlayerSave.java +++ b/src/codechicken/nei/PlayerSave.java @@ -41,7 +41,7 @@ public class PlayerSave if (saveFile.length() > 0) nbt = CompressedStreamTools.read(saveFile); } catch (Exception e) { - e.printStackTrace(); + NEIClientConfig.logger.error("Error loading player save: "+username, e); } loadCreativeInv(); @@ -65,7 +65,7 @@ public class PlayerSave CompressedStreamTools.write(nbt, saveFile); isDirty = false; } catch (Exception e) { - e.printStackTrace(); + NEIClientConfig.logger.error("Error saving player: "+username, e); } } diff --git a/src/codechicken/nei/SaveLoadButton.java b/src/codechicken/nei/SaveLoadButton.java index 8a5daac5..5b589cd0 100644 --- a/src/codechicken/nei/SaveLoadButton.java +++ b/src/codechicken/nei/SaveLoadButton.java @@ -1,10 +1,7 @@ package codechicken.nei; -import net.minecraft.client.Minecraft; -import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.gui.GuiScreen; import net.minecraft.util.ChatAllowedCharacters; -import net.minecraft.util.ResourceLocation; import org.lwjgl.input.Keyboard; import static codechicken.lib.gui.GuiDraw.drawString; @@ -26,7 +23,7 @@ public abstract class SaveLoadButton extends Button label = ""; onTextChange(); focused = true; - Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F)); + NEIClientUtils.playClickSound(); return true; } return super.handleClick(mousex, mousey, button); @@ -106,7 +103,7 @@ public abstract class SaveLoadButton extends Button { super.draw(mousex, mousey); if(focused && (cursorCounter / 6) % 2 == 0) - drawString("_", x + (width + getStringWidth(getRenderLabel())) / 2, y + (height - 8) / 2, 0xFFFFFFFF); + drawString("_", x + (w + getStringWidth(getRenderLabel())) / 2, y + (h - 8) / 2, 0xFFFFFFFF); } @Override diff --git a/src/codechicken/nei/SearchField.java b/src/codechicken/nei/SearchField.java index fd59a1ea..a4429413 100644 --- a/src/codechicken/nei/SearchField.java +++ b/src/codechicken/nei/SearchField.java @@ -1,15 +1,40 @@ package codechicken.nei; +import codechicken.nei.ItemList.EverythingItemFilter; +import codechicken.nei.ItemList.PatternItemFilter; +import codechicken.nei.api.API; +import codechicken.nei.api.ItemFilter; +import codechicken.nei.api.ItemFilter.ItemFilterProvider; import net.minecraft.util.EnumChatFormatting; +import java.util.LinkedList; +import java.util.List; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + import static codechicken.lib.gui.GuiDraw.drawGradientRect; import static codechicken.lib.gui.GuiDraw.drawRect; import static codechicken.nei.NEIClientConfig.world; -public class SearchField extends TextField +public class SearchField extends TextField implements ItemFilterProvider { + /** + * Interface for returning a custom filter based on search field text + */ + public static interface ISearchProvider + { + /** + * Return null to ignore this provider and use the normal searching protocol + */ + public ItemFilter getFilter(String searchText); + } + public static List searchProviders = new LinkedList(); + + long lastclicktime; + public SearchField(String ident) { super(ident); + API.addItemFilter(this); } public static boolean searchInventories() { @@ -19,10 +44,10 @@ public class SearchField extends TextField @Override public void drawBox() { if (searchInventories()) - drawGradientRect(x, y, width, height, 0xFFFFFF00, 0xFFC0B000); + drawGradientRect(x, y, w, h, 0xFFFFFF00, 0xFFC0B000); else - drawRect(x, y, width, height, 0xffA0A0A0); - drawRect(x + 1, y + 1, width - 2, height - 2, 0xFF000000); + drawRect(x, y, w, h, 0xffA0A0A0); + drawRect(x + 1, y + 1, w - 2, h - 2, 0xFF000000); } @Override @@ -41,7 +66,7 @@ public class SearchField extends TextField @Override public void onTextChange(String oldText) { NEIClientConfig.setSearchExpression(text()); - ItemList.updateSearch(); + ItemList.updateFilter(); } @Override @@ -55,5 +80,35 @@ public class SearchField extends TextField return EnumChatFormatting.getTextWithoutFormattingCodes(s); } - long lastclicktime; + @Override + public ItemFilter getFilter() { + String s_filter = text().toLowerCase(); + + for(ISearchProvider p : searchProviders) { + ItemFilter filter = p.getFilter(s_filter); + if(filter != null) + return filter; + } + + switch(NEIClientConfig.getIntSetting("inventory.searchmode")) { + case 0://plain + s_filter = "\\Q"+s_filter+"\\E"; + break; + case 1: + s_filter = s_filter + .replace(".", "") + .replace("?", ".") + .replace("*", ".+?"); + break; + } + + Pattern pattern = null; + try { + pattern = Pattern.compile(s_filter); + } catch (PatternSyntaxException ignored) {} + if (pattern == null || pattern.toString().equals("")) + return new EverythingItemFilter(); + + return new PatternItemFilter(pattern); + } } diff --git a/src/codechicken/nei/SpawnerRenderer.java b/src/codechicken/nei/SpawnerRenderer.java index 79765567..ba643644 100644 --- a/src/codechicken/nei/SpawnerRenderer.java +++ b/src/codechicken/nei/SpawnerRenderer.java @@ -28,9 +28,8 @@ public class SpawnerRenderer implements IItemRenderer int meta = item.getItemDamage(); if(meta == 0) - { meta = ItemMobSpawner.idPig; - } + String bossName = BossStatus.bossName; int bossTimeout = BossStatus.statusBarTime; try @@ -42,21 +41,16 @@ public class SpawnerRenderer implements IItemRenderer GL11.glPushMatrix(); Entity entity = ItemMobSpawner.getEntity(meta); - if(entity != null) - { - entity.setWorld(world); - float f1 = 0.4375F; - if(entity.getShadowSize() > 1.5) - { - f1 = 0.1F; - } - GL11.glRotatef((float) (ClientUtils.getRenderTime()*10), 0.0F, 1.0F, 0.0F); - GL11.glRotatef(-20F, 1.0F, 0.0F, 0.0F); - GL11.glTranslatef(0.0F, -0.4F, 0.0F); - GL11.glScalef(f1, f1, f1); - entity.setLocationAndAngles(0, 0, 0, 0.0F, 0.0F); - RenderManager.instance.renderEntityWithPosYaw(entity, 0.0D, 0.0D, 0.0D, 0.0F, 0); - } + entity.setWorld(world); + float f1 = 0.4375F; + if(entity.getShadowSize() > 1.5) + f1 = 0.1F; + GL11.glRotatef((float) (ClientUtils.getRenderTime()*10), 0.0F, 1.0F, 0.0F); + GL11.glRotatef(-20F, 1.0F, 0.0F, 0.0F); + GL11.glTranslatef(0.0F, -0.4F, 0.0F); + GL11.glScalef(f1, f1, f1); + entity.setLocationAndAngles(0, 0, 0, 0.0F, 0.0F); + RenderManager.instance.renderEntityWithPosYaw(entity, 0.0D, 0.0D, 0.0D, 0.0F, 0); GL11.glPopMatrix(); GL11.glEnable(GL12.GL_RESCALE_NORMAL); diff --git a/src/codechicken/nei/SubsetWidget.java b/src/codechicken/nei/SubsetWidget.java new file mode 100644 index 00000000..d6374337 --- /dev/null +++ b/src/codechicken/nei/SubsetWidget.java @@ -0,0 +1,650 @@ +package codechicken.nei; + +import codechicken.core.gui.GuiScrollSlot; +import codechicken.lib.gui.GuiDraw; +import codechicken.lib.vec.Rectangle4i; +import codechicken.nei.ItemList.ItemsLoadedCallback; +import codechicken.nei.ItemList.NothingItemFilter; +import codechicken.nei.SearchField.ISearchProvider; +import codechicken.nei.api.API; +import codechicken.nei.api.ItemFilter; +import codechicken.nei.api.ItemFilter.ItemFilterProvider; +import codechicken.nei.guihook.GuiContainerManager; +import net.minecraft.client.Minecraft; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; + +import java.awt.*; +import java.util.*; +import java.util.List; + +public class SubsetWidget extends Button implements ItemFilterProvider, ItemsLoadedCallback, ISearchProvider +{ + public static class SubsetState + { + int state = 2; + ArrayList items = new ArrayList(); + } + + public static class SubsetTag + { + protected class SubsetSlot extends GuiScrollSlot + { + public SubsetSlot() { + super(0, 0, 0, 0); + setSmoothScroll(false); + } + + @Override + public int getSlotHeight(int slot) { + return 18; + } + + @Override + protected int getNumSlots() { + return children.size()+state.items.size(); + } + + @Override + protected void slotClicked(int slot, int button, int mx, int my, int count) { + if(slot < sorted.size()) { + SubsetTag tag = sorted.get(slot); + if (NEIClientUtils.shiftKey()) + LayoutManager.searchField.setText("@" + tag.fullname); + else if (count >= 2) + SubsetWidget.showOnly(tag); + else + SubsetWidget.setHidden(tag, button == 1); + } else + SubsetWidget.setHidden(state.items.get(slot-sorted.size()), button == 1); + } + + @Override + protected void drawSlot(int slot, int x, int y, int mx, int my, float frame) { + int w = windowBounds().width; + Rectangle4i r = new Rectangle4i(x, y, w, getSlotHeight(slot)); + if(slot < sorted.size()) { + SubsetTag tag = sorted.get(slot); + LayoutManager.getLayoutStyle().drawSubsetTag(tag.displayName(), x, y, r.w, r.h, tag.state.state, r.contains(mx, my)); + } + else { + ItemStack stack = state.items.get(slot-sorted.size()); + boolean hidden = SubsetWidget.isHidden(stack); + + int itemx = w/2-8; + int itemy = 1; + + LayoutManager.getLayoutStyle().drawSubsetTag(null, x, y, r.w, r.h, hidden ? 0 : 2, false); + + GuiContainerManager.drawItem(x+itemx, y+itemy, stack); + if(new Rectangle4i(itemx, itemy, 16, 16).contains(mx, my)) + SubsetWidget.hoverStack = stack; + } + } + + @Override + public void drawOverlay(float frame) { + } + + @Override + public void drawBackground(float frame) { + drawRect(x, y, x+width, y+height, 0xFF202020); + } + + @Override + public int scrollbarAlignment() { + return -1; + } + + @Override + public void drawScrollbar(float frame) { + if(hasScrollbar()) + super.drawScrollbar(frame); + } + + @Override + public int scrollbarGuideAlignment() { + return 0; + } + } + + public final String fullname; + public final ItemFilter filter; + public TreeMap children = new TreeMap(); + public List sorted = Collections.emptyList(); + private int childwidth; + + protected String displayName; + protected SubsetState state = new SubsetState(); + protected final SubsetSlot slot = new SubsetSlot(); + private SubsetTag selectedChild; + private int visible; + + public SubsetTag(String fullname) { + this(fullname, new NothingItemFilter()); + } + + public SubsetTag(String fullname, ItemFilter filter) { + assert filter != null : "Filter cannot be null"; + this.fullname = EnumChatFormatting.getTextWithoutFormattingCodes(fullname); + this.filter = filter; + + if(fullname != null) { + int idx = fullname.lastIndexOf('.'); + displayName = idx < 0 ? fullname : fullname.substring(idx + 1); + } + } + + public String displayName() { + return displayName; + } + + public String name() { + int idx = fullname.indexOf('.'); + return idx < 0 ? fullname : fullname.substring(idx+1); + } + + public String parent() { + int idx = fullname.lastIndexOf('.'); + return idx < 0 ? null : fullname.substring(0, idx); + } + + private SubsetTag getTag(String name) { + int idx = name.indexOf('.'); + String childname = idx > 0 ? name.substring(0, idx) : name; + SubsetTag child = children.get(childname.toLowerCase()); + if(child == null) + return null; + + return idx > 0 ? child.getTag(name.substring(idx+1)) : child; + } + + private void recacheChildren() { + sorted = new ArrayList(children.values()); + childwidth = 0; + for(SubsetTag tag : sorted) + childwidth = Math.max(childwidth, tag.nameWidth()+2); + } + + private void addTag(SubsetTag tag) { + String name = fullname == null ? tag.fullname : tag.fullname.substring(fullname.length()+1); + int idx = name.indexOf('.'); + + if(idx < 0) {//add or replace tag + SubsetTag prev = children.put(name.toLowerCase(), tag); + if(prev != null) {//replaced, load children + tag.children = prev.children; + tag.sorted = prev.sorted; + } + recacheChildren(); + } + else { + String childname = name.substring(0, idx); + SubsetTag child = children.get(childname.toLowerCase()); + if(child == null) + children.put(childname.toLowerCase(), child = new SubsetTag(fullname == null ? childname : fullname+'.'+childname)); + recacheChildren(); + child.addTag(tag); + } + } + + protected void cacheState() { + state = SubsetWidget.getState(this); + for(SubsetTag tag : sorted) + tag.cacheState(); + } + + public ItemFilter compositeFilter() { + final List filters = new LinkedList(); + if(filter != null) + filters.add(filter); + + for(SubsetTag child : sorted) + filters.add(child.compositeFilter()); + + return new ItemFilter() + { + @Override + public boolean matches(ItemStack item) { + for(ItemFilter filter : filters) + if(filter.matches(item)) + return true; + + return false; + } + }; + } + + public void updateVisiblity(int mx, int my) { + if(selectedChild != null) { + selectedChild.updateVisiblity(mx, my); + if(!selectedChild.isVisible()) + selectedChild = null; + } + + if(slot.contains(mx, my) && (selectedChild == null || !selectedChild.contains(mx, my))) { + int mslot = slot.getClickedSlot(my); + if(mslot >= 0 && mslot < sorted.size()) { + SubsetTag mtag = sorted.get(mslot); + if(mtag != null) { + if(mtag != selectedChild && selectedChild != null) + selectedChild.setHidden(); + selectedChild = mtag; + selectedChild.setVisible(); + } + } + + setVisible(); + } + + if(selectedChild == null) + countdownVisible(); + } + + public void setHidden() { + visible = 0; + slot.mouseMovedOrUp(0, 0, 0);//cancel any scrolling + if(selectedChild != null) { + selectedChild.setHidden(); + selectedChild = null; + } + } + + public void setVisible() { + visible = 10; + cacheState(); + } + + private void countdownVisible() { + if(visible > 0 && --visible == 0) + setHidden(); + } + + public void resize(int x, int pwidth, int y) { + int mheight = area.h; + int dheight = area.y2()-y; + int cheight = slot.contentHeight(); + int height = cheight; + if(cheight > mheight) { + y = area.y; + height = mheight; + } else if(cheight > dheight) { + y = area.y2() - cheight; + } + + height = height/slot.getSlotHeight(0)*slot.getSlotHeight(0);//floor to a multiple of slot height + + int width = childwidth; + if(!state.items.isEmpty()) + width = Math.max(childwidth, 18); + if(slot.contentHeight() > height) + width+=slot.scrollbarDim().width; + + if(pwidth >= 0 ? x+width+pwidth > area.x2() : x-width < area.x1()) + pwidth*=-1; + x += pwidth >= 0 ? pwidth : -width; + + slot.setSize(x, y, width, height); + slot.setMargins(slot.hasScrollbar() ? slot.scrollbarDim().width : 0, 0, 0, 0); + + if(selectedChild != null) { + y = slot.getSlotY(sorted.indexOf(selectedChild))-slot.scrolledPixels()+slot.y; + selectedChild.resize(x, pwidth >= 0 ? width : -width, y); + } + } + + protected int nameWidth() { + return Minecraft.getMinecraft().fontRenderer.getStringWidth(displayName()); + } + + public boolean isVisible() { + return visible > 0; + } + + public void draw(int mx, int my) { + slot.draw(mx, my, 0); + if(selectedChild != null) + selectedChild.draw(mx, my); + } + + public boolean contains(int px, int py) { + return slot.contains(px, py) || + selectedChild != null && selectedChild.contains(px, py); + } + + public void mouseClicked(int mx, int my, int button) { + if(selectedChild != null && selectedChild.contains(mx, my)) + selectedChild.mouseClicked(mx, my, button); + else if(slot.contains(mx, my)) + slot.mouseClicked(mx, my, button); + } + + public void mouseDragged(int mx, int my, int button, long heldTime) { + slot.mouseDragged(mx, my, button, heldTime); + if(selectedChild != null) + selectedChild.mouseDragged(mx, my, button, heldTime); + } + + public void mouseUp(int mx, int my, int button) { + slot.mouseMovedOrUp(mx, my, button); + if(selectedChild != null) + selectedChild.mouseUp(mx, my, button); + } + + public boolean mouseScrolled(int mx, int my, int scroll) { + if(slot.hasScrollbar() && slot.contains(mx, my)) { + slot.scroll(scroll); + return true; + } + + if(selectedChild != null && selectedChild.mouseScrolled(mx, my, scroll)) + return true; + + if(slot.hasScrollbar() && !contains(mx, my)) { + slot.scroll(scroll); + return true; + } + + return false; + } + + public boolean isScrolling() { + return slot.isScrolling() || + selectedChild != null && selectedChild.isScrolling(); + } + } + + protected static final SubsetTag root = new SubsetTag(null); + public static Rectangle4i area = new Rectangle4i(); + public static ItemStack hoverStack; + + private static HashMap subsetState = new HashMap(); + /** + * All operations on this variable should be synchronised. + */ + public static final ItemStackSet hiddenItems = new ItemStackSet(); + + public static SubsetState getState(SubsetTag tag) { + SubsetState state = subsetState.get(tag.fullname); + return state == null ? new SubsetState() : state; + } + + public static void addTag(SubsetTag tag) { + synchronized (root) { + root.addTag(tag); + updateState(true); + } + } + + public static SubsetTag getTag(String name) { + return name == null ? root : root.getTag(name); + } + + public static boolean isHidden(ItemStack item) { + synchronized (hiddenItems) { + return hiddenItems.contains(item); + } + } + + private static void _setHidden(SubsetTag tag, boolean hidden) { + for(ItemStack item : getState(tag).items) + _setHidden(item, hidden); + for(SubsetTag child : tag.sorted) + _setHidden(child, hidden); + } + + private static void _setHidden(ItemStack item, boolean hidden) { + if(hidden) + hiddenItems.add(item); + else + hiddenItems.remove(item); + } + + public static void showOnly(SubsetTag tag) { + synchronized (hiddenItems) { + for(ItemStack item : ItemList.items) + _setHidden(item, true); + setHidden(tag, false); + } + } + + public static void setHidden(SubsetTag tag, boolean hidden) { + synchronized (hiddenItems) { + _setHidden(tag, hidden); + updateState(false); + } + } + + public static void setHidden(ItemStack item, boolean hidden) { + synchronized (hiddenItems) { + _setHidden(item, hidden); + updateState(false); + } + } + + private long lastclicktime; + + public SubsetWidget() { + super("NEI Subsets"); + API.addItemFilter(this); + API.addSearchProvider(this); + ItemList.loadCallbacks.add(this); + } + + @Override + public void draw(int mx, int my) { + super.draw(mx, my); + + area.set(x, y + h, w, LayoutManager.searchField.y - h - y); //23 for the search box + + hoverStack = null; + if (root.isVisible()) { + root.resize(area.x, 0, area.y); + root.cacheState(); + root.draw(mx, my); + } + } + + @Override + public void update() { + Point mouse = GuiDraw.getMousePosition(); + updateVisiblity(mouse.x, mouse.y); + } + + private void updateVisiblity(int mx, int my) { + if(!root.isVisible() || root.isScrolling()) + return; + + root.updateVisiblity(mx, my); + + if(!root.isVisible() && bounds().contains(mx, my)) + root.setVisible(); + } + + @Override + public boolean contains(int px, int py) { + return super.contains(px, py) || + root.isVisible() && root.contains(px, py); + } + + @Override + public boolean handleClick(int mx, int my, int button) { + if(root.isVisible() && root.contains(mx, my)) { + root.mouseClicked(mx, my, button); + return true; + } + + if(button == 0) { + if(System.currentTimeMillis() - lastclicktime < 500) { + synchronized (hiddenItems) { + hiddenItems.clear(); + updateState(false); + } + } + else + root.setVisible(); + + NEIClientUtils.playClickSound(); + lastclicktime = System.currentTimeMillis(); + } + + return true; + } + + /** + * Not called + */ + @Override + public boolean onButtonPress(boolean rightclick) { + return false; + } + + @Override + public void mouseDragged(int mx, int my, int button, long heldTime) { + if(root.isVisible()) + root.mouseDragged(mx, my, button, heldTime); + } + + @Override + public void mouseUp(int mx, int my, int button) { + if(root.isVisible()) + root.mouseUp(mx, my, button); + } + + @Override + public boolean onMouseWheel(int i, int mx, int my) { + return root.isVisible() && root.mouseScrolled(mx, my, -i); + } + + @Override + public void onGuiClick(int mx, int my) { + if(!contains(mx, my)) + root.setHidden(); + } + + @Override + public ItemStack getStackMouseOver(int mx, int my) { + return hoverStack; + } + + @Override + public ItemFilter getFilter() { + return new ItemFilter()//synchronise access on hiddenItems + { + @Override + public boolean matches(ItemStack item) { + synchronized (hiddenItems) { + return !hiddenItems.matches(item); + } + } + }; + } + + @Override + public ItemFilter getFilter(String searchText) { + if(!searchText.startsWith("@")) + return null; + + SubsetTag tag = getTag(searchText.substring(1)); + return tag != null ? tag.compositeFilter() : null; + } + + @Override + public void itemsLoaded() { + updateState(true); + } + + private static boolean updatingState; + private static boolean reupdate; + private static boolean reallocate; + + private static class ThreadSubsetItems extends Thread + { + public ThreadSubsetItems() { + super("NEI Subset Item Allocation"); + } + + @Override + public void run() { + restart: + do { + reupdate = false; + HashMap state = new HashMap(); + List tags = new LinkedList(); + synchronized (root) { + cloneStates(root, tags, state); + } + + if(reallocate) { + for (ItemStack item : ItemList.items) { + if (reupdate) + continue restart; + + for (SubsetTag tag : tags) + if (tag.filter.matches(item)) + state.get(tag.fullname).items.add(item); + } + } + + synchronized (root) { + if (reupdate) + continue; + reallocate = false; + + calculateVisibility(root, state); + } + + subsetState = state; + } + while(reupdate); + updatingState = false; + } + + private void cloneStates(SubsetTag tag, List tags, HashMap state) { + for(SubsetTag child : tag.sorted) + cloneStates(child, tags, state); + + tags.add(tag); + SubsetState sstate = new SubsetState(); + if(!reallocate) + sstate.items = SubsetWidget.getState(tag).items; + state.put(tag.fullname, sstate); + } + + private void calculateVisibility(SubsetTag tag, Map state) { + SubsetState sstate = state.get(tag.fullname); + int hidden = 0; + for(SubsetTag child : tag.sorted) { + calculateVisibility(child, state); + int cstate = state.get(child.fullname).state; + if(cstate == 1) + sstate.state = 1; + else if(cstate == 0) + hidden++; + } + + if(sstate.state == 1) + return; + + List items = sstate.items; + for(ItemStack item : items) + if(isHidden(item)) + hidden++; + if(hidden == tag.sorted.size()+items.size()) + sstate.state = 0; + else if(hidden > 0) + sstate.state = 1; + } + } + + public static void updateState(boolean reallocate) { + SubsetWidget.reallocate = reallocate; + if (updatingState) + reupdate = true; + else { + updatingState = true; + new ThreadSubsetItems().start(); + } + ItemList.updateFilter(); + } +} diff --git a/src/codechicken/nei/TMIUninstaller.java b/src/codechicken/nei/TMIUninstaller.java deleted file mode 100644 index c298f1bc..00000000 --- a/src/codechicken/nei/TMIUninstaller.java +++ /dev/null @@ -1,279 +0,0 @@ -package codechicken.nei; - -import net.minecraft.client.Minecraft; - -import javax.swing.*; -import java.awt.*; -import java.awt.LayoutManager; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.*; -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import java.util.zip.ZipInputStream; -import java.util.zip.ZipOutputStream; - -public class TMIUninstaller -{ - public static class InstallerGui extends JFrame - { - private static final long serialVersionUID = 1L; - private JTextField labelInfo; - private static final String PREFERRED_LOOK_AND_FEEL = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"; - - public InstallerGui() { - setTitle("TMI Uninstaller"); - initComponents(); - } - - private class ResizeListener implements LayoutManager - { - public void addLayoutComponent(String name, Component comp) { - } - - public void layoutContainer(Container parent) { - int w = getContentPane().getWidth(); - labelInfo.setBounds(10, 45, w - 20, 20); - labelInfo.setScrollOffset(1000); - labelInfo.update(getGraphics()); - } - - public Dimension minimumLayoutSize(Container parent) { - return new Dimension(150, 100); - } - - public Dimension preferredLayoutSize(Container parent) { - return new Dimension(250, 120); - } - - - public void removeLayoutComponent(Component comp) { - } - } - - private void initComponents() { - setLayout(new ResizeListener()); - add(getLabelInfo()); - setSize(358, 270); - } - - public class InstallerListener implements ActionListener - { - public void actionPerformed(ActionEvent e) { - } - } - - public JTextField getLabelInfo() { - if (labelInfo == null) { - labelInfo = new JTextField(); - labelInfo.setFont(new Font("Tahoma", Font.PLAIN, 13)); - labelInfo.setHorizontalAlignment(SwingConstants.CENTER); - labelInfo.setEditable(false); - labelInfo.setText("Uninstalling TMI"); - } - return labelInfo; - } - - public static void installLnF() { - try { - String lnfClassname = UIManager.getCrossPlatformLookAndFeelClassName(); - UIManager.setLookAndFeel(lnfClassname); - } catch (Exception e) { - System.err.println("Cannot install " + PREFERRED_LOOK_AND_FEEL + " on this platform:" + e.getMessage()); - } - } - } - - private static File jarFile; - public static InstallerGui mainframe; - - public static void main(String[] args) { - jarFile = new File(args[0]); - - InstallerGui.installLnF(); - mainframe = new InstallerGui(); - mainframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - - mainframe.setLocationRelativeTo(null); - mainframe.pack(); - mainframe.setVisible(true); - - if (!jarFile.exists()) - mainframe.getLabelInfo().setText("Invalid Minecraft.jar"); - else - uninstall(); - } - - private static File getJarFile() { - URL url = Minecraft.class.getProtectionDomain().getCodeSource().getLocation(); - try { - if (url.getProtocol().equals("jar")) - url = new URL(url.getPath().substring(0, url.getPath().indexOf('!'))); - return new File(url.toURI()); - } catch (URISyntaxException e) { - return new File(url.getPath()); - } catch (MalformedURLException e) { - throw new RuntimeException(e); - } - } - - public static void deleteTMIUninstaller() throws IOException { - File file = new File(getJarFile().getParentFile(), "TMIUninstaller"); - if (file.exists()) { - NEIClientConfig.logger.info("Removing TMI Uninstaller"); - deleteDir(file, true); - } - } - - public static boolean TMIInstalled() { - File jarFile = getJarFile(); - if (!jarFile.getName().endsWith(".jar")) - return false; - - try { - ZipFile zip = new ZipFile(jarFile); - ZipEntry tmi = zip.getEntry("mod_TooManyItems.class"); - zip.close(); - return tmi != null; - } catch (Exception e) { - return false; - } - } - - public static void runTMIUninstaller() throws IOException { - File jarFile = getJarFile(); - File uninstDir = new File(jarFile.getParentFile(), "TMIUninstaller"); - if (!uninstDir.exists()) - uninstDir.mkdirs(); - - NEIClientConfig.logger.info("Installing Uninstaller: " + uninstDir.getPath()); - - FileInputStream fileinputstream = new FileInputStream(jarFile); - ZipInputStream zipinputstream = new ZipInputStream(fileinputstream); - do { - ZipEntry zipentry = zipinputstream.getNextEntry(); - if (zipentry == null) { - break; - } - String fullname = zipentry.getName().replace('\\', '/'); - if (!zipentry.isDirectory() && fullname.replace('/', '.').startsWith(TMIUninstaller.class.getCanonicalName())) { - File outFile = new File(uninstDir, fullname); - NEIClientConfig.logger.info("Extracting File: " + outFile.getPath()); - - if (!outFile.getParentFile().exists()) - outFile.getParentFile().mkdirs(); - - outFile.createNewFile(); - FileOutputStream fout = new FileOutputStream(outFile); - - byte[] buffer = new byte[65535]; - int read = 0; - while ((read = zipinputstream.read(buffer)) != -1)//write loop - { - fout.write(buffer, 0, read); - } - fout.close(); - } - } - while (true); - fileinputstream.close(); - - String javaBin = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java"; - - String classpath = uninstDir.getAbsolutePath(); - String className = TMIUninstaller.class.getCanonicalName(); - - String jarPath = jarFile.getPath(); - - NEIClientConfig.logger.info("Running Process: " + javaBin + " -cp \"" + classpath + "\" \"" + className + "\" \"" + jarPath + "\""); - - ProcessBuilder builder = new ProcessBuilder(javaBin, "-cp", classpath, className, jarPath); - builder.start(); - } - - public static void deleteDir(File directory, boolean remove) throws IOException { - NEIClientConfig.logger.debug("Deleting Dir: " + directory.getPath()); - if (!directory.exists()) { - if (!remove) - directory.mkdirs(); - - return; - } - for (File file : directory.listFiles()) { - if (file.isDirectory()) { - deleteDir(file, true); - } else { - if (!file.delete()) { - throw new IOException("Delete Failed: " + file); - } - } - } - if (remove) { - try { - if (!directory.delete()) { - throw new IOException("Delete Failed: " + directory); - } - } catch (SecurityException e) { - throw e; - } - } - } - - public static void uninstall() { - File backupfile = new File(jarFile.getParentFile(), jarFile.getName() + ".bak"); - try { - if (!backupfile.exists()) - backupfile.createNewFile(); - - FileOutputStream backout = new FileOutputStream(backupfile); - FileInputStream jarin = new FileInputStream(jarFile); - backout.getChannel().transferFrom(jarin.getChannel(), 0, jarFile.length()); - - backout.close(); - jarin.close(); - - ZipInputStream zipin = new ZipInputStream(new FileInputStream(backupfile)); - ZipOutputStream zipout = new ZipOutputStream(new FileOutputStream(jarFile)); - byte[] buffer = new byte[20000]; - int read = 0; - while (true) { - ZipEntry entry = zipin.getNextEntry(); - if (entry == null) { - break; - } - if (entry.isDirectory()) continue; - String name = entry.getName(); - if (name.startsWith("TMI") || name.startsWith("_tmi") || name.startsWith("tmi.png") || name.startsWith("mod_TooManyItems")) { - continue; - } - zipout.putNextEntry(new ZipEntry(name)); - InputStream in = zipin; - while ((read = in.read(buffer)) != -1) { - zipout.write(buffer, 0, read); - } - zipout.closeEntry(); - zipin.closeEntry(); - } - zipin.close(); - zipout.close(); - - mainframe.getLabelInfo().setText("Uninstall Completed. Close this and restart minecraft."); - } catch (Exception e) { - e.printStackTrace(); - mainframe.getLabelInfo().setText("Invalid Minecraft.jar"); - try { - FileInputStream backin = new FileInputStream(backupfile); - FileOutputStream jarout = new FileOutputStream(jarFile); - jarout.getChannel().transferFrom(backin.getChannel(), 0, backupfile.length()); - - backin.close(); - jarout.close(); - } catch (Exception e1) { - e1.printStackTrace(); - } - } - } -} diff --git a/src/codechicken/nei/TextField.java b/src/codechicken/nei/TextField.java index 2bf4e627..c1c32ed9 100644 --- a/src/codechicken/nei/TextField.java +++ b/src/codechicken/nei/TextField.java @@ -8,168 +8,129 @@ import static codechicken.lib.gui.GuiDraw.*; public abstract class TextField extends Widget { - public TextField(String ident) - { + public TextField(String ident) { identifier = ident; } - - public int getTextColour() - { + + public int getTextColour() { return focused() ? 0xFFE0E0E0 : 0xFF909090; } - - public void drawBox() - { - drawRect(x, y, width, height, 0xffA0A0A0); - drawRect(x + 1, y + 1, width - 2, height - 2, 0xFF000000); + + public void drawBox() { + drawRect(x, y, w, h, 0xffA0A0A0); + drawRect(x + 1, y + 1, w - 2, h - 2, 0xFF000000); } @Override - public void draw(int mousex, int mousey) - { + public void draw(int mousex, int mousey) { drawBox(); - + String drawtext = text; - - if(text.length() > getMaxTextLength()) - { - int startOffset = drawtext.length() - getMaxTextLength(); - if(startOffset < 0 || startOffset > drawtext.length()) - startOffset = 0; - drawtext = drawtext.substring(startOffset); - } - - if(focused() && (cursorCounter / 6) % 2 == 0) + + int textWidth; + while((textWidth = getStringWidth(drawtext)) > w - 14) + drawtext = drawtext.substring(1); + + if (focused() && (cursorCounter / 6) % 2 == 0) drawtext = drawtext + '_'; - - int textWidth = getStringWidth(text); - int textx = centered ? x+(width-textWidth)/2 : x + 4; - int texty = y + (height + 1) / 2 - 3; - + + int textx = centered ? x + (w - textWidth) / 2 : x + 4; + int texty = y + (h + 1) / 2 - 3; + drawString(drawtext, textx, texty, getTextColour()); } @Override - public void onGuiClick(int mousex, int mousey) - { - if(!contains(mousex, mousey)) + public void onGuiClick(int mousex, int mousey) { + if (!contains(mousex, mousey)) setFocus(false); } @Override - public boolean handleClick(int mousex, int mousey, int button) - { - if(button == 1) + public boolean handleClick(int mousex, int mousey, int button) { + if (button == 1) setText(""); setFocus(true); return true; } @Override - public boolean handleKeyPress(int keyID, char keyChar) - { - if(!focused()) + public boolean handleKeyPress(int keyID, char keyChar) { + if (!focused()) return false; - - if(keyID == Keyboard.KEY_BACK) - { - if(text.length() > 0) - { + + if (keyID == Keyboard.KEY_BACK) { + if (text.length() > 0) { setText(text.substring(0, text.length() - 1)); backdowntime = System.currentTimeMillis(); } - } - else if(keyID == Keyboard.KEY_RETURN || keyID == Keyboard.KEY_ESCAPE) - { + } else if (keyID == Keyboard.KEY_RETURN || keyID == Keyboard.KEY_ESCAPE) { setFocus(false); onExit(); - } - else if(keyChar == 22)//paste + } else if (keyChar == 22)//paste { String pastestring = GuiScreen.getClipboardString(); - if(pastestring == null) + if (pastestring == null) pastestring = ""; - - if(isValid(text + pastestring)) + + if (isValid(text + pastestring)) setText(text + pastestring); - } - else if(isValid(text+keyChar)) - setText(text+keyChar); - + } else if (isValid(text + keyChar)) + setText(text + keyChar); + return true; } - - public void onExit() - { + + public void onExit() { } public abstract void onTextChange(String oldText); - public boolean isValid(String string) - { + public boolean isValid(String string) { // Solve the problem that Minecraft can't post Chinese characters - return ChatAllowedCharacters.isAllowedCharacter(string.charAt(string.length()-1)); + return ChatAllowedCharacters.isAllowedCharacter(string.charAt(string.length() - 1)); } @Override - public void update() - { + public void update() { cursorCounter++; - if(backdowntime > 0) - { - if(Keyboard.isKeyDown(Keyboard.KEY_BACK) && text.length() > 0) - { - if(System.currentTimeMillis() - backdowntime > 200 / (1+backs * 0.3F)) - { + if (backdowntime > 0) { + if (Keyboard.isKeyDown(Keyboard.KEY_BACK) && text.length() > 0) { + if (System.currentTimeMillis() - backdowntime > 200 / (1 + backs * 0.3F)) { setText(text.substring(0, text.length() - 1)); backdowntime = System.currentTimeMillis(); backs++; } - } - else - { + } else { backdowntime = 0; backs = 0; } } } - - public void setText(String s) - { + + public void setText(String s) { String oldText = text; text = filterText(s); onTextChange(oldText); } - - public String filterText(String s) - { + + public String filterText(String s) { return s; } - - private int getMaxTextLength() - { - return width / 6 - 2; - } - - public void setFocus(boolean focus) - { - if(focus) - { + + public void setFocus(boolean focus) { + if (focus) { LayoutManager.setInputFocused(this); - } - else if(focused()) - { + } else if (focused()) { LayoutManager.setInputFocused(null); } } - - public boolean focused() - { + + public boolean focused() { return LayoutManager.getInputFocused() == this; } - - public String text() - { + + public String text() { return text; } diff --git a/src/codechicken/nei/ThreadOperationTimer.java b/src/codechicken/nei/ThreadOperationTimer.java new file mode 100644 index 00000000..fa774862 --- /dev/null +++ b/src/codechicken/nei/ThreadOperationTimer.java @@ -0,0 +1,72 @@ +package codechicken.nei; + +import com.google.common.base.Objects; +import cpw.mods.fml.common.FMLCommonHandler; + +public class ThreadOperationTimer extends Thread +{ + @SuppressWarnings("serial") + public static class TimeoutException extends RuntimeException + { + public final Object operation; + + public TimeoutException(String msg, Object op) { + super(msg); + operation = op; + } + } + + private Thread thread; + private Object operation; + private long opTime; + private long limit; + + private ThreadOperationTimer(Thread thread, int limit) { + super(thread.getName()+" Operation Timer"); + this.thread = thread; + this.limit = limit; + } + + public synchronized void setLimit(int limit) { + this.limit = limit; + } + + public void reset() { + reset(null); + } + + public synchronized void reset(Object op) { + operation = op; + opTime = System.currentTimeMillis(); + } + + public synchronized void update(Object op) { + if(!Objects.equal(operation, op)) { + operation = op; + opTime = System.currentTimeMillis(); + } + } + + @SuppressWarnings("deprecation") + @Override + public void run() { + if(FMLCommonHandler.instance().findContainerFor("NotEnoughItems").getVersion().contains("$")) + return;//don't run this thread in a source environment + + while (thread.isAlive()) { + synchronized (this) { + if (operation != null && System.currentTimeMillis() - opTime > limit) + thread.stop(new TimeoutException("Operation took too long", operation)); + } + try { + Thread.sleep(50); + } catch (InterruptedException ie) {} + } + } + + public static ThreadOperationTimer start(Thread thread, int limit) { + ThreadOperationTimer t = new ThreadOperationTimer(thread, limit); + t.start(); + return t; + } +} \ No newline at end of file diff --git a/src/codechicken/nei/Widget.java b/src/codechicken/nei/Widget.java index 77a56910..8ef60b31 100644 --- a/src/codechicken/nei/Widget.java +++ b/src/codechicken/nei/Widget.java @@ -1,5 +1,6 @@ package codechicken.nei; +import codechicken.lib.vec.Rectangle4i; import net.minecraft.item.ItemStack; import java.util.List; @@ -9,19 +10,19 @@ public abstract class Widget public Widget() { } - public abstract void draw(int mousex, int mousey); + public abstract void draw(int mx, int my); - public void postDraw(int mousex, int mousey) { + public void postDraw(int mx, int my) { } - public boolean handleClick(int mousex, int mousey, int button) { + public boolean handleClick(int mx, int my, int button) { return true; } - public void onGuiClick(int mousex, int mousey) { + public void onGuiClick(int mx, int my) { } - public void mouseUp(int mousex, int mousey, int button) { + public void mouseUp(int mx, int my, int button) { } @@ -32,22 +33,26 @@ public abstract class Widget public void lastKeyTyped(int keyID, char keyChar) { } - public boolean handleClickExt(int mousex, int mousey, int button) { + public boolean handleClickExt(int mx, int my, int button) { return false; } - public boolean onMouseWheel(int i, int mousex, int mousey) { + public boolean onMouseWheel(int i, int mx, int my) { return false; } public void update() { } - public boolean contains(int posx, int posy) { - return posx >= x && posx < x + width && posy >= y && posy < y + height; + public Rectangle4i bounds() { + return new Rectangle4i(x, y, w, h); } - public ItemStack getStackMouseOver(int mousex, int mousey) { + public boolean contains(int px, int py) { + return bounds().contains(px, py); + } + + public ItemStack getStackMouseOver(int mx, int my) { return null; } @@ -67,6 +72,6 @@ public abstract class Widget public int x; public int y; public int z; - public int width; - public int height; + public int w; + public int h; } diff --git a/src/codechicken/nei/api/API.java b/src/codechicken/nei/api/API.java index c26815ea..74caa4ce 100644 --- a/src/codechicken/nei/api/API.java +++ b/src/codechicken/nei/api/API.java @@ -1,19 +1,23 @@ package codechicken.nei.api; -import codechicken.nei.KeyManager; +import codechicken.nei.*; import codechicken.nei.KeyManager.KeyState; -import codechicken.nei.LayoutManager; -import codechicken.nei.NEIClientConfig; -import codechicken.nei.OffsetPositioner; +import codechicken.nei.SearchField.ISearchProvider; +import codechicken.nei.SubsetWidget.SubsetTag; +import codechicken.nei.api.ItemFilter.ItemFilterProvider; import codechicken.nei.config.Option; import codechicken.nei.config.OptionKeyBind; import codechicken.nei.recipe.*; import net.minecraft.block.Block; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.inventory.Slot; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import org.lwjgl.input.Keyboard; +import java.util.Collections; +import java.util.Comparator; + /** * This is the main class that handles item property configuration. * WARNING: DO NOT access this class until the world has been loaded @@ -122,6 +126,15 @@ public class API ItemInfo.itemOverrides.put(item.getItem(), item); } + /** + * Sets the item variants to appear in the item panel, overriding the default search pattern for a given item + */ + public static void setItemListEntries(Item item, Iterable items) { + if(items == null) + items = Collections.emptyList(); + ItemInfo.itemOverrides.replaceValues(item, items); + } + /** * Add a custom KeyBinding to be configured in the Controls menu. * @param ident An identifier for your key, eg "shoot" @@ -148,7 +161,6 @@ public class API /** * Registers a new Infinite Item Handler. - * * @param handler The handler to be registered. */ public static void addInfiniteItemHandler(IInfiniteItemHandler handler) { @@ -157,7 +169,6 @@ public class API /** * Registers a new Infinite Item Handler. - * * @param block The block to handle, null for all. * @param handler The handler to be registered. */ @@ -167,7 +178,6 @@ public class API /** * Tells NEI not to perform any Fast Transfer operations on slots of a particular class - * * @param slotClass The class of slot to be exempted */ public static void addFastTransferExemptSlot(Class slotClass) { @@ -176,8 +186,7 @@ public class API /** * Register a new text handler for the block highlight tooltip with a layout specification (HEADER, BODY or FOOTER). - * - * @param handler + * @param handler The handler to be registered. * @param layout A HUDAugmenterRegistry.Layout entry. HEADER is displayed before BODY which is displayed before FOOTER. */ public static void registerHighlightHandler(IHighlightHandler handler, ItemInfo.Layout... layout) { @@ -186,10 +195,62 @@ public class API /** * Register a mode handler for overriding NEI recipe/utility/cheat mode settings. - * - * @param handler + * @param handler The handler to be registered. */ public static void registerModeHandler(INEIModeHandler handler) { NEIInfo.modeHandlers.add(handler); } + + /** + * Register a filter provider for the item panel. + * @param filterProvider The filter provider to be registered. + */ + public static void addItemFilter(ItemFilterProvider filterProvider) { + synchronized (ItemList.itemFilterers) { + ItemList.itemFilterers.add(filterProvider); + } + } + + /** + * Adds a new tag to the item subset dropdown. + * @param name The fully qualified name, Eg Blocks.MobSpawners. NOT case sensitive + * @param filter A filter for matching items that fit in this subset + */ + public static void addSubset(String name, ItemFilter filter) { + addSubset(new SubsetTag(name, filter)); + } + + /** + * Adds a new tag to the item subset dropdown. + * @param name The fully qualified name, Eg Blocks.MobSpawners. NOT case sensitive + * @param items An iterable of itemstacks to be added as a subset + */ + public static void addSubset(String name, Iterable items) { + ItemStackSet filter = new ItemStackSet(); + for(ItemStack item : items) + filter.add(item); + addSubset(new SubsetTag(name, filter)); + } + + /** + * Adds a new tag to the item subset dropdown. + */ + public static void addSubset(SubsetTag tag) { + SubsetWidget.addTag(tag); + } + + /** + * Adds a new search provider to the search field + */ + public static void addSearchProvider(ISearchProvider provider) { + SearchField.searchProviders.add(provider); + } + + /** + * Adds a new sorting option to the item panel sort menu + * @param name A unique id for this sort option. Will be used in the config for saving and translated in the options gui. Note that if the translation key name.tip exists, it will be used for a tooltip + */ + public static void addSortOption(String name, Comparator comparator) { + ItemSorter.add(name, comparator); + } } diff --git a/src/codechicken/nei/api/GuiInfo.java b/src/codechicken/nei/api/GuiInfo.java index 11f71ee5..38883523 100644 --- a/src/codechicken/nei/api/GuiInfo.java +++ b/src/codechicken/nei/api/GuiInfo.java @@ -4,18 +4,22 @@ import codechicken.nei.NEIChestGuiHandler; import codechicken.nei.NEICreativeGuiHandler; import codechicken.nei.NEIDummySlotHandler; import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.gui.inventory.GuiContainerCreative; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; public class GuiInfo { public static LinkedList guiHandlers = new LinkedList(); + public static HashSet> customSlotGuis = new HashSet>(); public static void load() { API.registerNEIGuiHandler(new NEICreativeGuiHandler()); API.registerNEIGuiHandler(new NEIChestGuiHandler()); API.registerNEIGuiHandler(new NEIDummySlotHandler()); + customSlotGuis.add(GuiContainerCreative.class); } public static void clearGuiHandlers() { @@ -23,4 +27,8 @@ public class GuiInfo if (iterator.next() instanceof GuiContainer) iterator.remove(); } + + public static boolean hasCustomSlots(GuiContainer gui) { + return customSlotGuis.contains(gui.getClass()); + } } diff --git a/src/codechicken/nei/api/INEIGuiHandler.java b/src/codechicken/nei/api/INEIGuiHandler.java index 55b1111a..9ca8fb6c 100644 --- a/src/codechicken/nei/api/INEIGuiHandler.java +++ b/src/codechicken/nei/api/INEIGuiHandler.java @@ -38,6 +38,7 @@ public interface INEIGuiHandler /** * Used to prevent the item panel from drawing on top of other gui elements. + * This function will also be called with a 1x1 size rectangle on the mouse position for determining if the given coordinate should override item panel functions such as scrolling * @param x The x coordinate of the rectangle bounding the slot * @param y The y coordinate of the rectangle bounding the slot * @param w The w coordinate of the rectangle bounding the slot diff --git a/src/codechicken/nei/api/ItemFilter.java b/src/codechicken/nei/api/ItemFilter.java new file mode 100644 index 00000000..c22b99c7 --- /dev/null +++ b/src/codechicken/nei/api/ItemFilter.java @@ -0,0 +1,16 @@ +package codechicken.nei.api; + +import net.minecraft.item.ItemStack; + +public interface ItemFilter +{ + /** + * Provides an item filter. May be called from any thread. Returned filter should only reference objects with immutable state. + */ + public static interface ItemFilterProvider + { + public ItemFilter getFilter(); + } + + public boolean matches(ItemStack item); +} \ No newline at end of file diff --git a/src/codechicken/nei/api/ItemInfo.java b/src/codechicken/nei/api/ItemInfo.java index e0585b22..22cb5c04 100644 --- a/src/codechicken/nei/api/ItemInfo.java +++ b/src/codechicken/nei/api/ItemInfo.java @@ -2,13 +2,23 @@ package codechicken.nei.api; import codechicken.core.featurehack.GameDataManipulator; import codechicken.nei.*; +import codechicken.nei.ItemList.EverythingItemFilter; +import codechicken.nei.ItemList.ItemsLoadedCallback; +import codechicken.nei.api.ItemFilter.ItemFilterProvider; import codechicken.nei.config.ArrayDumper; import codechicken.nei.config.ItemPanelDumper; import codechicken.nei.config.RegistryDumper; import codechicken.nei.guihook.GuiContainerManager; +import codechicken.nei.recipe.BrewingRecipeHandler; import codechicken.nei.recipe.RecipeItemInputHandler; import com.google.common.collect.ArrayListMultimap; +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.ModContainer; +import cpw.mods.fml.common.registry.GameRegistry; +import cpw.mods.fml.common.registry.GameRegistry.UniqueIdentifier; import net.minecraft.block.Block; +import net.minecraft.client.resources.I18n; +import net.minecraft.creativetab.CreativeTabs; import net.minecraft.enchantment.Enchantment; import net.minecraft.entity.EntityList; import net.minecraft.entity.EntityList.EntityEggInfo; @@ -18,9 +28,9 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.inventory.Slot; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; +import net.minecraft.item.*; import net.minecraft.potion.Potion; +import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.RegistryNamespaced; import net.minecraft.world.World; @@ -30,6 +40,7 @@ import net.minecraftforge.common.IShearable; import net.minecraftforge.oredict.OreDictionary; import java.util.*; +import java.util.Map.Entry; /** * This is an internal class for storing information about items, to be accessed by the API @@ -41,7 +52,7 @@ public class ItemInfo HEADER, BODY, FOOTER } - public static final HashMap> highlightHandlers = new HashMap>(); + public static final ArrayListMultimap highlightHandlers = ArrayListMultimap.create(); public static final ItemStackMap nameOverrides = new ItemStackMap(); public static final ItemStackSet hiddenItems = new ItemStackSet(); public static final ItemStackSet finiteItems = new ItemStackSet(); @@ -53,10 +64,8 @@ public class ItemInfo public static final HashMap itemOwners = new HashMap(); - static { - for (Layout layout : Layout.values()) - ItemInfo.highlightHandlers.put(layout, new ArrayList()); - } + //lookup optimisation + public static final HashMap itemSearchNames = new HashMap(); public static boolean isHidden(ItemStack stack) { return hiddenItems.contains(stack); @@ -78,16 +87,47 @@ public class ItemInfo return itemOverrides.get(item); } + public static void preInit() { + addMobSpawnerItem(); + } + public static void load(World world) { addVanillaBlockProperties(); addDefaultDropDowns(); searchItems(); parseModItems(); - addMobSpawnerItem(world); + ItemMobSpawner.loadSpawners(world); addSpawnEggs(); addInfiniteHandlers(); addInputHandlers(); addIDDumps(); + addHiddenItemFilter(); + addSearchOptimisation(); + } + + private static void addSearchOptimisation() { + ItemList.loadCallbacks.add(new ItemsLoadedCallback() + { + @Override public void itemsLoaded() { + itemSearchNames.clear(); + } + }); + } + + private static void addHiddenItemFilter() { + API.addItemFilter(new ItemFilterProvider() + { + @Override + public ItemFilter getFilter() { + return new ItemFilter() + { + @Override + public boolean matches(ItemStack item) { + return !hiddenItems.contains(item); + } + }; + } + }); } private static void addIDDumps() { @@ -219,7 +259,29 @@ public class ItemInfo } private static void parseModItems() { - //TODO GameRegistry.findUniqueIdentifierFor() + HashMap modSubsets = new HashMap(); + for (Item item : (Iterable) Item.itemRegistry) { + UniqueIdentifier ident = GameRegistry.findUniqueIdentifierFor(item); + if(ident == null) { + NEIClientConfig.logger.error("Failed to find identifier for: "+item); + continue; + } + String modId = GameRegistry.findUniqueIdentifierFor(item).modId; + itemOwners.put(item, modId); + ItemStackSet itemset = modSubsets.get(modId); + if(itemset == null) + modSubsets.put(modId, itemset = new ItemStackSet()); + itemset.with(item); + } + + API.addSubset("Mod.Minecraft", modSubsets.remove("minecraft")); + for(Entry entry : modSubsets.entrySet()) { + ModContainer mc = FMLCommonHandler.instance().findContainerFor(entry.getKey()); + if(mc == null) + NEIClientConfig.logger.error("Missing container for "+entry.getKey()); + else + API.addSubset("Mod."+mc.getName(), entry.getValue()); + } } private static void addInputHandlers() { @@ -227,8 +289,8 @@ public class ItemInfo GuiContainerManager.addInputHandler(new PopupInputHandler()); } - private static void addMobSpawnerItem(World world) { - GameDataManipulator.replaceItem(Block.getIdFromBlock(Blocks.mob_spawner), new ItemMobSpawner(world)); + private static void addMobSpawnerItem() { + GameDataManipulator.replaceItem(Block.getIdFromBlock(Blocks.mob_spawner), new ItemMobSpawner()); } private static void addInfiniteHandlers() { @@ -251,45 +313,36 @@ public class ItemInfo } private static void addDefaultDropDowns() { - /*API.addSetRange("Blocks", new MultiItemRange("[0-32000]") + API.addSubset("Items", new EverythingItemFilter()); + API.addSubset("Blocks", new ItemFilter() { @Override - public void addItemIfInRange(int item, int damage, NBTTagCompound compound) { - if (item < Block.blocksList.length && (Block.blocksList[item] != null && Block.blocksList[item].blockMaterial != Material.air)) - super.addItemIfInRange(item, damage, compound); + public boolean matches(ItemStack item) { + return Block.getBlockFromItem(item.getItem()) != Blocks.air; } }); - API.addSetRange("Items", new MultiItemRange("[0-32000]") - { - @Override - public void addItemIfInRange(int item, int damage, NBTTagCompound compound) { - if (item >= Block.blocksList.length || Block.blocksList[item] == null || Block.blocksList[item].blockMaterial == Material.air) - super.addItemIfInRange(item, damage, compound); - } - }); - API.addSetRange("Blocks.MobSpawners", new MultiItemRange("[52]"));*/ + API.addSubset("Blocks.MobSpawners", ItemStackSet.of(Blocks.mob_spawner)); } - //TODO private static void searchItems() { - /*MultiItemRange tools = new MultiItemRange(); - MultiItemRange picks = new MultiItemRange(); - MultiItemRange shovels = new MultiItemRange(); - MultiItemRange axes = new MultiItemRange(); - MultiItemRange hoes = new MultiItemRange(); - MultiItemRange swords = new MultiItemRange(); - MultiItemRange chest = new MultiItemRange(); - MultiItemRange helmets = new MultiItemRange(); - MultiItemRange legs = new MultiItemRange(); - MultiItemRange boots = new MultiItemRange(); - MultiItemRange other = new MultiItemRange(); - MultiItemRange ranged = new MultiItemRange(); - MultiItemRange food = new MultiItemRange(); - MultiItemRange potioningredients = new MultiItemRange(); + ItemStackSet tools = new ItemStackSet(); + ItemStackSet picks = new ItemStackSet(); + ItemStackSet shovels = new ItemStackSet(); + ItemStackSet axes = new ItemStackSet(); + ItemStackSet hoes = new ItemStackSet(); + ItemStackSet swords = new ItemStackSet(); + ItemStackSet chest = new ItemStackSet(); + ItemStackSet helmets = new ItemStackSet(); + ItemStackSet legs = new ItemStackSet(); + ItemStackSet boots = new ItemStackSet(); + ItemStackSet other = new ItemStackSet(); + ItemStackSet ranged = new ItemStackSet(); + ItemStackSet food = new ItemStackSet(); + ItemStackSet potioningredients = new ItemStackSet(); - MultiItemRange[] creativeTabRanges = new MultiItemRange[CreativeTabs.creativeTabArray.length]; + ItemStackSet[] creativeTabRanges = new ItemStackSet[CreativeTabs.creativeTabArray.length]; for (CreativeTabs tab : CreativeTabs.creativeTabArray) - creativeTabRanges[tab.getTabIndex()] = new MultiItemRange(); + creativeTabRanges[tab.getTabIndex()] = new ItemStackSet(); for (Item item : (Iterable) Item.itemRegistry) { if (item == null) @@ -297,69 +350,77 @@ public class ItemInfo CreativeTabs itemTab = item.getCreativeTab(); if (itemTab != null) - creativeTabRanges[itemTab.getTabIndex()].add(item); + creativeTabRanges[itemTab.getTabIndex()].with(item); if (item.isDamageable()) { - tools.add(item); - if (item instanceof ItemPickaxe) { - picks.add(item); - } else if (item instanceof ItemSpade) { - shovels.add(item); - } else if (item instanceof ItemAxe) { - axes.add(item); - } else if (item instanceof ItemHoe) { - hoes.add(item); - } else if (item instanceof ItemSword) { - swords.add(item); - } else if (item instanceof ItemArmor) { + tools.with(item); + if (item instanceof ItemPickaxe) + picks.with(item); + else if (item instanceof ItemSpade) + shovels.with(item); + else if (item instanceof ItemAxe) + axes.with(item); + else if (item instanceof ItemHoe) + hoes.with(item); + else if (item instanceof ItemSword) + swords.with(item); + else if (item instanceof ItemArmor) switch (((ItemArmor) item).armorType) { case 0: - helmets.add(item); + helmets.with(item); break; case 1: - chest.add(item); + chest.with(item); break; case 2: - legs.add(item); + legs.with(item); break; case 3: - boots.add(item); + boots.with(item); break; } - } else if (item == Items.arrow || item == Items.bow) { - ranged.add(item); - } else if (item == Items.fishing_rod || item == Items.flint_and_steel || item == Items.shears) { - other.add(item); + else if (item == Items.arrow || item == Items.bow) + ranged.with(item); + else if (item == Items.fishing_rod || item == Items.flint_and_steel || item == Items.shears) + other.with(item); + } + + if (item instanceof ItemFood) + food.with(item); + + try { + LinkedList subItems = new LinkedList(); + item.getSubItems(item, null, subItems); + for(ItemStack stack : subItems) { + if (item.isPotionIngredient(stack)) { + BrewingRecipeHandler.ingredients.add(stack); + potioningredients.add(stack); + } } - } - if (item instanceof ItemFood) { - food.add(item); - } - - if (item.isPotionIngredient()) { - BrewingRecipeHandler.ingredients.add(item); - potioningredients.add(item); + } catch (Exception e) { + NEIClientConfig.logger.error("Error loading brewing ingredients for: "+item, e); } } - API.addSetRange("Items.Tools.Pickaxes", picks); - API.addSetRange("Items.Tools.Shovels", shovels); - API.addSetRange("Items.Tools.Axes", axes); - API.addSetRange("Items.Tools.Hoes", hoes); - API.addSetRange("Items.Tools.Other", other); - API.addSetRange("Items.Weapons.Swords", swords); - API.addSetRange("Items.Weapons.Ranged", ranged); - API.addSetRange("Items.Armor.ChestPlates", chest); - API.addSetRange("Items.Armor.Leggings", legs); - API.addSetRange("Items.Armor.Helmets", helmets); - API.addSetRange("Items.Armor.Boots", boots); - API.addSetRange("Items.Food", food); - API.addSetRange("Items.Potions.Ingredients", potioningredients); + API.addSubset("Items.Tools.Pickaxes", picks); + API.addSubset("Items.Tools.Shovels", shovels); + API.addSubset("Items.Tools.Axes", axes); + API.addSubset("Items.Tools.Hoes", hoes); + API.addSubset("Items.Tools.Other", other); + API.addSubset("Items.Weapons.Swords", swords); + API.addSubset("Items.Weapons.Ranged", ranged); + API.addSubset("Items.Armor.ChestPlates", chest); + API.addSubset("Items.Armor.Leggings", legs); + API.addSubset("Items.Armor.Helmets", helmets); + API.addSubset("Items.Armor.Boots", boots); + API.addSubset("Items.Food", food); + API.addSubset("Items.Potions.Ingredients", potioningredients); - for (CreativeTabs tab : CreativeTabs.creativeTabArray) { - if (creativeTabRanges[tab.getTabIndex()].ranges.size() > 0) - API.addSetRange("CreativeTabs." + LangUtil.translateG(tab.getTranslatedTabLabel()), creativeTabRanges[tab.getTabIndex()]); - }*/ + for (CreativeTabs tab : CreativeTabs.creativeTabArray) + if (!creativeTabRanges[tab.getTabIndex()].isEmpty()) + API.addSubset("CreativeTabs." + I18n.format(tab.getTranslatedTabLabel()), creativeTabRanges[tab.getTabIndex()]); + + BrewingRecipeHandler.searchPotions(); } private static void addSpawnEggs() @@ -428,4 +489,13 @@ public class ItemInfo return retString; } + + public static String getSearchName(ItemStack stack) { + String s = itemSearchNames.get(stack); + if(s == null) { + s = EnumChatFormatting.getTextWithoutFormattingCodes(GuiContainerManager.concatenatedDisplayName(stack, true).toLowerCase()); + itemSearchNames.put(stack, s); + } + return s; + } } diff --git a/src/codechicken/nei/api/LayoutStyle.java b/src/codechicken/nei/api/LayoutStyle.java index 11346b6f..b4667a9f 100644 --- a/src/codechicken/nei/api/LayoutStyle.java +++ b/src/codechicken/nei/api/LayoutStyle.java @@ -16,5 +16,5 @@ public abstract class LayoutStyle { } public abstract void drawButton(Button button, int mousex, int mousey); - public abstract boolean texturedButtons(); + public abstract void drawSubsetTag(String text, int x, int y, int w, int h, int state, boolean mouseover); } diff --git a/src/codechicken/nei/asm/NEITransformer.java b/src/codechicken/nei/asm/NEITransformer.java index 545a07f3..1fa16938 100644 --- a/src/codechicken/nei/asm/NEITransformer.java +++ b/src/codechicken/nei/asm/NEITransformer.java @@ -105,8 +105,8 @@ public class NEITransformer implements IClassTransformer //Replace default renderItem with delegate and slot overlay/underlay transformer.add(new MethodReplacer(new ObfMapping(GuiContainer, "func_146977_a", "(Lnet/minecraft/inventory/Slot;)V"), asmblocks.get("d_drawSlot"), asmblocks.get("drawSlot"))); - //Inject mouseClicked hook after super call in mouseClicked - transformer.add(new MethodInjector(new ObfMapping(GuiContainer, "func_73864_a", "(III)V"), asmblocks.get("n_mouseClicked"), asmblocks.get("mouseClicked"), false)); + //Inject mouseClicked hook at the start of mouseClicked + transformer.add(new MethodInjector(new ObfMapping(GuiContainer, "func_73864_a", "(III)V"), asmblocks.get("mouseClicked"), true)); //Replace general handleMouseClicked call with delegate transformer.add(new MethodReplacer(new ObfMapping(GuiContainer, "func_73864_a", "(III)V"), asmblocks.get("d_handleMouseClick"), asmblocks.get("handleMouseClick")));//mouseClicked @@ -152,6 +152,22 @@ public class NEITransformer implements IClassTransformer //Inject updateScreen hook after super call transformer.add(new MethodInjector(new ObfMapping(GuiContainer, "func_73876_c", "()V"), asmblocks.get("n_updateScreen"), asmblocks.get("updateScreen"), false)); + + //Cancel tab click calls when tabs are obscured + transformer.add(new MethodInjector(new ObfMapping("net/minecraft/client/gui/inventory/GuiContainerCreative", "func_147049_a", "(Lnet/minecraft/creativetab/CreativeTabs;II)Z"), + asmblocks.get("handleTabClick"), true)); + + //Cancel tab tooltip rendering when tabs are obscured + transformer.add(new MethodInjector(new ObfMapping("net/minecraft/client/gui/inventory/GuiContainerCreative", "func_147052_b", "(Lnet/minecraft/creativetab/CreativeTabs;II)Z"), + asmblocks.get("renderTabTooltip"), true)); + + String[] buttons = new String[]{"CancelButton", "ConfirmButton", "PowerButton"}; + for(String button : buttons) { + ObfMapping m = new ObfMapping("net/minecraft/client/gui/inventory/GuiBeacon$"+button, "func_146111_b", "(II)V"); + InsnListSection l = asmblocks.get("beaconButtonObscured").list.copy(); + ((FieldInsnNode)l.get(1)).owner = m.s_owner; + transformer.add(new MethodInjector(m, l.list, true)); + } } private void addProtectedForwarder(ObfMapping called, ObfMapping caller) { diff --git a/src/codechicken/nei/config/DataDumper.java b/src/codechicken/nei/config/DataDumper.java index 9b366121..cb42651c 100644 --- a/src/codechicken/nei/config/DataDumper.java +++ b/src/codechicken/nei/config/DataDumper.java @@ -4,11 +4,8 @@ import codechicken.core.CommonUtils; import codechicken.lib.vec.Rectangle4i; import codechicken.nei.LayoutManager; import codechicken.nei.NEIClientUtils; -import net.minecraft.client.Minecraft; -import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.util.ChatComponentTranslation; import net.minecraft.util.IChatComponent; -import net.minecraft.util.ResourceLocation; import org.lwjgl.opengl.GL11; import java.io.File; @@ -94,17 +91,17 @@ public abstract class DataDumper extends Option } public void drawPrefix() { - drawString(renderName(), 10, 8, -1); + drawString(renderName(), 10, 6, -1); } public Rectangle4i dumpButtonSize() { int width = 80; - return new Rectangle4i(slot.contentWidth() - width, 2, width, 20); + return new Rectangle4i(slot.slotWidth() - width, 0, width, 20); } public Rectangle4i modeButtonSize() { int width = 60; - return new Rectangle4i(slot.contentWidth() - width - 10 - dumpButtonSize().w, 2, width, 20); + return new Rectangle4i(slot.slotWidth() - width - 10 - dumpButtonSize().w, 0, width, 20); } public String dumpButtonText() { @@ -146,10 +143,10 @@ public abstract class DataDumper extends Option @Override public void mouseClicked(int mousex, int mousey, int button) { if (modeCount() > 1 && modeButtonSize().contains(mousex, mousey)) { - Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F)); + NEIClientUtils.playClickSound(); getTag().setIntValue((getMode() + 1) % modeCount()); } else if (dumpButtonSize().contains(mousex, mousey)) { - Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F)); + NEIClientUtils.playClickSound(); dumpFile(); } } diff --git a/src/codechicken/nei/config/GuiHighlightTips.java b/src/codechicken/nei/config/GuiHighlightTips.java index b2587f62..2d613429 100644 --- a/src/codechicken/nei/config/GuiHighlightTips.java +++ b/src/codechicken/nei/config/GuiHighlightTips.java @@ -22,10 +22,10 @@ public class GuiHighlightTips extends GuiScreenWidget { private String name; private GuiCCButton toggleButton; - private OptionHighlightTips opt; + private Option opt; private Point dragDown; - public GuiHighlightTips(OptionHighlightTips opt) { + public GuiHighlightTips(Option opt) { super(80, 20); this.opt = opt; name = opt.name; diff --git a/src/codechicken/nei/config/GuiItemSorter.java b/src/codechicken/nei/config/GuiItemSorter.java new file mode 100644 index 00000000..13257609 --- /dev/null +++ b/src/codechicken/nei/config/GuiItemSorter.java @@ -0,0 +1,170 @@ +package codechicken.nei.config; + +import codechicken.lib.math.MathHelper; +import codechicken.nei.*; +import codechicken.nei.ItemSorter.SortEntry; +import codechicken.nei.LayoutManager; +import net.minecraft.client.gui.GuiScreen; +import org.lwjgl.opengl.GL11; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +import static codechicken.lib.gui.GuiDraw.drawStringC; +import static codechicken.lib.gui.GuiDraw.getMousePosition; + +public class GuiItemSorter extends GuiOptionPane +{ + public class SortItem + { + public double ya; + public double y; + public SortEntry e; + + public SortItem(SortEntry e) { + this.e = e; + y = slotY(); + } + + public int slotY() { + return GuiItemSorter.this.slotY(ItemSorter.list.indexOf(e)); + } + + public void update(int my) { + ya = y; + if(dragging && this == dragged) + y = dragstarty+my-mouseclickedy; + else + y = MathHelper.approachExp(y, slotY(), 0.4, 20); + } + + public boolean contains(int my) { + my -= drawBounds().y; + return my >= y && my < y+20; + } + } + + public Option opt; + public List slots = new ArrayList(); + + boolean dragging; + public SortItem dragged; + public int mouseclickedy; + public double dragstarty; + + public GuiItemSorter(Option opt) { + this.opt = opt; + for(SortEntry e : ItemSorter.list) + slots.add(new SortItem(e)); + } + + public int slotY(int slot) { + return 2+slot*24; + } + + @Override + public int contentHeight() { + return ItemSorter.list.size()*24; + } + + @Override + public void drawContent(int mx, int my, float frame) { + Rectangle w = drawBounds(); + + for(SortItem item : slots) + if(item != dragged) + drawItem(w, item, mx, my, frame); + + if(dragged != null) + drawItem(w, dragged, mx, my, frame); + } + + public void drawItem(Rectangle w, SortItem item, int mx, int my, float frame) { + double y = MathHelper.interpolate(item.ya, item.y, frame); + GL11.glTranslated(0, y, 0); + Rectangle b = new Rectangle(w.x, w.y, w.width, 20); + boolean mouseOver = itemAt(w.x+mx, w.y+my) == item; + + GL11.glColor4f(1, 1, 1, 1); + LayoutManager.drawButtonBackground(b.x, b.y, b.width, b.height, true, mouseOver ? 2 : 1); + drawStringC(item.e.getLocalisedName(), b.x, b.y, b.width, b.height, mouseOver ? 0xFFFFFFA0 : 0xFFE0E0E0); + + GL11.glTranslated(0, -y, 0); + } + + @Override + public String getTitle() { + return opt.translateN(opt.name); + } + + @Override + public GuiScreen getParentScreen() { + return opt.slot.getGui(); + } + + @Override + public void updateScreen() { + super.updateScreen(); + + int my = getMousePosition().y; + for(SortItem item : slots) + item.update(my); + + if(dragging) { + int nslot = (int)MathHelper.clip((dragged.y-(2-12))/24, 0, slots.size()-1); + if(nslot != ItemSorter.list.indexOf(dragged.e)) { + ArrayList list = new ArrayList(ItemSorter.list); + list.remove(dragged.e); + list.add(nslot, dragged.e); + ItemSorter.list = list;//just to be safe with concurrency + opt.getTag().setValue(ItemSorter.getSaveString()); + } + } + } + + public SortItem itemAt(int mx, int my) { + if(!pane.windowBounds().contains(mx, my)) + return null; + + if(dragged != null && dragged.contains(my)) + return dragged; + + for(SortItem item : slots) + if(item.contains(my)) + return item; + + return null; + } + + @Override + protected void mouseClicked(int x, int y, int button) { + super.mouseClicked(x, y, button); + + if(!dragging && button == 0) { + SortItem item = itemAt(x, y); + if(item != null) { + dragging = true; + dragged = item; + mouseclickedy = y; + dragstarty = item.y; + } + } + } + + @Override + protected void mouseMovedOrUp(int x, int y, int button) { + if(button == 0) + dragging = false; + } + + @Override + public List handleTooltip(int mx, int my, List tooltip) { + if(!dragging) { + SortItem item = itemAt(mx, my); + if(item != null && item.e.getTooltip() != null) + tooltip.add(item.e.getTooltip()); + } + return tooltip; + } +} diff --git a/src/codechicken/nei/config/GuiOptionList.java b/src/codechicken/nei/config/GuiOptionList.java index 93295bc3..0e45bf37 100644 --- a/src/codechicken/nei/config/GuiOptionList.java +++ b/src/codechicken/nei/config/GuiOptionList.java @@ -6,11 +6,7 @@ import codechicken.core.gui.GuiScrollSlot; import codechicken.lib.vec.Rectangle4i; import codechicken.nei.LayoutManager; import net.minecraft.client.Minecraft; -import net.minecraft.client.audio.PositionedSoundRecord; -import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.util.ResourceLocation; import org.lwjgl.opengl.GL11; import java.awt.*; @@ -27,73 +23,55 @@ public class GuiOptionList extends GuiScreenWidget public class OptionScrollSlot extends GuiScrollSlot { public ArrayList