From bd5e991a8471211934f60130610592e74ccf160e Mon Sep 17 00:00:00 2001 From: slprime <31038811+slprime@users.noreply.github.com> Date: Thu, 29 Aug 2024 23:14:52 +0300 Subject: [PATCH] NEI Optimization (#519) * NEI Optimization * save setting after death --------- Co-authored-by: slprime --- .../java/codechicken/nei/BookmarkPanel.java | 22 +- .../java/codechicken/nei/ClientHandler.java | 190 ++++------- .../codechicken/nei/CollapsibleItems.java | 310 +++--------------- src/main/java/codechicken/nei/ItemList.java | 29 +- .../java/codechicken/nei/LayoutManager.java | 6 +- .../java/codechicken/nei/NEIClientConfig.java | 75 ++--- .../java/codechicken/nei/PresetsList.java | 69 +--- .../codechicken/nei/SearchTokenParser.java | 6 +- .../java/codechicken/nei/SubsetWidget.java | 2 - src/main/java/codechicken/nei/api/API.java | 9 + .../java/codechicken/nei/api/ItemInfo.java | 13 +- .../nei/config/preset/LeftPanel.java | 14 +- .../nei/config/preset/PresetItemsGrid.java | 2 +- .../nei/config/preset/RightPanel.java | 20 +- .../nei/guihook/GuiContainerManager.java | 14 +- .../nei/recipe/GuiCraftingRecipe.java | 23 +- .../nei/recipe/GuiUsageRecipe.java | 24 +- .../codechicken/nei/recipe/StackInfo.java | 43 +-- .../nei/recipe/TemplateRecipeHandler.java | 2 +- .../codechicken/nei/search/TooltipFilter.java | 24 +- .../nei/util/ItemStackFilterParser.java | 203 ++++++++++++ .../assets/nei/cfg/collapsibleitems.cfg | 21 +- .../assets/nei/{ => cfg}/guidfilters.cfg | 3 +- .../resources/assets/nei/cfg/hiddenitems.cfg | 24 ++ src/main/resources/assets/nei/lang/en_US.lang | 3 - src/main/resources/assets/nei/lang/ru_RU.lang | 3 - src/main/resources/assets/nei/lang/zh_CN.lang | 3 - 27 files changed, 514 insertions(+), 643 deletions(-) create mode 100644 src/main/java/codechicken/nei/util/ItemStackFilterParser.java rename src/main/resources/assets/nei/{ => cfg}/guidfilters.cfg (94%) create mode 100644 src/main/resources/assets/nei/cfg/hiddenitems.cfg diff --git a/src/main/java/codechicken/nei/BookmarkPanel.java b/src/main/java/codechicken/nei/BookmarkPanel.java index 25a3e11c3..e47ed9d9f 100644 --- a/src/main/java/codechicken/nei/BookmarkPanel.java +++ b/src/main/java/codechicken/nei/BookmarkPanel.java @@ -1763,7 +1763,12 @@ public int getNamespaceSize() { return namespaces.size(); } - public void setBookmarkFile(String worldPath) { + public void load() { + String worldPath = "global"; + + if (NEIClientConfig.getBooleanSetting("inventory.bookmarks.worldSpecific")) { + worldPath = NEIClientConfig.getWorldPath(); + } final File dir = new File(CommonUtils.getMinecraftDir(), "saves/NEI/" + worldPath); @@ -1781,16 +1786,15 @@ public void setBookmarkFile(String worldPath) { if (defaultBookmarks.exists()) { try { - bookmarkFile.createNewFile(); - - InputStream src = new FileInputStream(defaultBookmarks); - OutputStream dst = new FileOutputStream(bookmarkFile); + if (bookmarkFile.createNewFile()) { + InputStream src = new FileInputStream(defaultBookmarks); + OutputStream dst = new FileOutputStream(bookmarkFile); - IOUtils.copy(src, dst); - - src.close(); - dst.close(); + IOUtils.copy(src, dst); + src.close(); + dst.close(); + } } catch (IOException e) {} } } diff --git a/src/main/java/codechicken/nei/ClientHandler.java b/src/main/java/codechicken/nei/ClientHandler.java index 7931b61e2..586f65624 100644 --- a/src/main/java/codechicken/nei/ClientHandler.java +++ b/src/main/java/codechicken/nei/ClientHandler.java @@ -1,19 +1,19 @@ package codechicken.nei; -import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; -import java.io.InputStreamReader; -import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.Consumer; import java.util.regex.Pattern; import java.util.stream.Collectors; +import java.util.stream.Stream; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; @@ -30,17 +30,16 @@ import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.world.WorldEvent; -import org.apache.commons.csv.CSVFormat; -import org.apache.commons.csv.CSVParser; -import org.apache.commons.csv.CSVRecord; import org.apache.commons.io.IOUtils; import com.google.common.collect.Lists; +import codechicken.core.ClassDiscoverer; import codechicken.core.ClientUtils; import codechicken.core.GuiModListScroll; import codechicken.lib.packet.PacketCustom; import codechicken.nei.api.API; +import codechicken.nei.api.IConfigureNEI; import codechicken.nei.api.ItemInfo; import codechicken.nei.guihook.GuiContainerManager; import codechicken.nei.recipe.GuiRecipeTab; @@ -148,6 +147,7 @@ private void updateMagnetMode(World world, EntityPlayerSP player) { public static void preInit() { loadSerialHandlers(); + loadHiddenItems(); loadHeightHackHandlers(); loadHiddenHandlers(); loadEnableAutoFocus(); @@ -155,100 +155,69 @@ public static void preInit() { StackInfo.loadGuidFilters(); } - public static void loadSerialHandlers() { - File file = NEIClientConfig.serialHandlersFile; - if (!file.exists()) { - try (FileWriter writer = new FileWriter(file)) { - NEIClientConfig.logger.info("Creating default serial handlers list {}", file); - URL defaultSerialHandlersResource = ClientHandler.class - .getResource("/assets/nei/cfg/serialhandlers.cfg"); - if (defaultSerialHandlersResource != null) { - IOUtils.copy(defaultSerialHandlersResource.openStream(), writer); - } - } catch (IOException e) { - NEIClientConfig.logger.error("Failed to save default serial handlers list to file {}", file, e); + public static void loadSettingsFile(String resource, Consumer> callback) { + loadSettingsFile(resource, (file, writer) -> { + String folder = resource.substring(resource.lastIndexOf(".") + 1); + URL defaultResource = ClientHandler.class.getResource("/assets/nei/" + folder + "/" + resource); + + if (defaultResource != null) { + try { + IOUtils.copy(defaultResource.openStream(), writer); + } catch (IOException e) {} } - } - try (FileReader reader = new FileReader(file)) { - NEIClientConfig.logger.info("Loading serial handlers from file {}", file); - NEIClientConfig.serialHandlers = IOUtils.readLines(reader).stream().filter((line) -> !line.startsWith("#")) - .collect(Collectors.toCollection(HashSet::new)); - } catch (IOException e) { - NEIClientConfig.logger.error("Failed to load serial handlers from file {}", file, e); - } + }, callback); } - public static void loadHeightHackHandlers() { - File file = NEIClientConfig.heightHackHandlersFile; + public static void loadSettingsFile(String resource, BiConsumer createDefault, + Consumer> callback) { + File file = new File(NEIClientConfig.configDir, resource); + if (!file.exists()) { try (FileWriter writer = new FileWriter(file)) { - NEIClientConfig.logger.info("Creating default height hack handlers list {}", file); - URL defaultHeightHackHandlersResource = ClientHandler.class - .getResource("/assets/nei/cfg/heighthackhandlers.cfg"); - if (defaultHeightHackHandlersResource != null) { - IOUtils.copy(defaultHeightHackHandlersResource.openStream(), writer); - } + NEIClientConfig.logger.info("Creating default '{}' {}", resource, file); + createDefault.accept(file, writer); } catch (IOException e) { - NEIClientConfig.logger.error("Failed to save default height hack handlers list to file {}", file, e); + NEIClientConfig.logger.error("Failed to save default '{}' to file {}", resource, file, e); } } try (FileReader reader = new FileReader(file)) { - NEIClientConfig.logger.info("Loading height hack handlers from file {}", file); - NEIClientConfig.heightHackHandlerRegex = IOUtils.readLines(reader).stream() - .filter((line) -> !line.startsWith("#")).map(Pattern::compile) - .collect(Collectors.toCollection(HashSet::new)); + NEIClientConfig.logger.info("Loading '{}' file {}", resource, file); + callback.accept( + IOUtils.readLines(reader).stream().filter(line -> !line.startsWith("#") && !line.trim().isEmpty())); } catch (IOException e) { - NEIClientConfig.logger.error("Failed to load height hack handlers from file {}", file, e); + NEIClientConfig.logger.error("Failed to load '{}' file {}", resource, file, e); } } - public static void loadHiddenHandlers() { - File file = NEIClientConfig.hiddenHandlersFile; - if (!file.exists()) { - try (FileWriter writer = new FileWriter(file)) { - NEIClientConfig.logger.info("Creating default hidden handlers list {}", file); - URL defaultHeightHackHandlersResource = ClientHandler.class - .getResource("/assets/nei/cfg/hiddenhandlers.cfg"); - if (defaultHeightHackHandlersResource != null) { - IOUtils.copy(defaultHeightHackHandlersResource.openStream(), writer); - } - } catch (IOException e) { - NEIClientConfig.logger.error("Failed to save default hidden handlers list to file {}", file, e); - } - } + public static void loadSerialHandlers() { + loadSettingsFile( + "serialhandlers.cfg", + lines -> NEIClientConfig.serialHandlers = lines.collect(Collectors.toCollection(HashSet::new))); + } - try (FileReader reader = new FileReader(file)) { - NEIClientConfig.logger.info("Loading hidden handlers from file {}", file); - NEIClientConfig.hiddenHandlers = IOUtils.readLines(reader).stream().filter((line) -> !line.startsWith("#")) - .collect(Collectors.toCollection(HashSet::new)); - } catch (IOException e) { - NEIClientConfig.logger.error("Failed to load hidden handlers from file {}", file, e); - } + public static void loadHeightHackHandlers() { + loadSettingsFile( + "heighthackhandlers.cfg", + lines -> NEIClientConfig.heightHackHandlerRegex = lines.map(Pattern::compile) + .collect(Collectors.toCollection(HashSet::new))); + } + + public static void loadHiddenHandlers() { + loadSettingsFile( + "hiddenhandlers.cfg", + lines -> NEIClientConfig.hiddenHandlers = lines.collect(Collectors.toCollection(HashSet::new))); } public static void loadEnableAutoFocus() { - File file = NEIClientConfig.enableAutoFocusFile; - if (!file.exists()) { - try (FileWriter writer = new FileWriter(file)) { - NEIClientConfig.logger.info("Creating default enable auto focus list {}", file); - URL defaultEnableAutoFocusResource = ClientHandler.class - .getResource("/assets/nei/cfg/enableautofocus.cfg"); - if (defaultEnableAutoFocusResource != null) { - IOUtils.copy(defaultEnableAutoFocusResource.openStream(), writer); - } - } catch (IOException e) { - NEIClientConfig.logger.error("Failed to save default enable auto focus list to file {}", file, e); - } - } + loadSettingsFile( + "enableautofocus.cfg", + lines -> AutoFocusWidget.enableAutoFocusPrefixes = lines + .collect(Collectors.toCollection(ArrayList::new))); + } - try (FileReader reader = new FileReader(file)) { - NEIClientConfig.logger.info("Loading enable auto focus from file {}", file); - AutoFocusWidget.enableAutoFocusPrefixes = IOUtils.readLines(reader).stream() - .filter((line) -> !line.startsWith("#")).collect(Collectors.toCollection(ArrayList::new)); - } catch (IOException e) { - NEIClientConfig.logger.error("Failed to load enable auto focus from file {}", file, e); - } + public static void loadHiddenItems() { + loadSettingsFile("hiddenitems.cfg", lines -> lines.forEach(API::hideItem)); } public static void load() { @@ -266,54 +235,33 @@ public static void load() { public static void postInit() { loadHandlerOrdering(); + loadPluginsList(); GuiContainerManager.registerReloadResourceListener(); } public static void loadHandlerOrdering() { - File file = NEIClientConfig.handlerOrderingFile; - if (!file.exists()) { - try (FileWriter writer = new FileWriter(file)) { - NEIClientConfig.logger.info("Creating default handler ordering CSV {}", file); - - List toWrite = Lists.newArrayList(defaultHandlerOrdering); - GuiRecipeTab.handlerMap.keySet().stream().sorted() - .forEach(handlerId -> toWrite.add(String.format("%s,0", handlerId))); + final String COMMA_DELIMITER = ","; + loadSettingsFile("handlerordering.csv", (file, writer) -> { + List toWrite = Lists.newArrayList(defaultHandlerOrdering); + GuiRecipeTab.handlerMap.keySet().stream().sorted() + .forEach(handlerId -> toWrite.add(String.format("%s,0", handlerId))); + try { IOUtils.writeLines(toWrite, "\n", writer); - } catch (IOException e) { - NEIClientConfig.logger.error("Failed to save default handler ordering to file {}", file, e); - } - } - - URL url; - try { - url = file.toURI().toURL(); - } catch (MalformedURLException e) { - NEIClientConfig.logger.info("Invalid URL for handler ordering CSV."); - e.printStackTrace(); - return; - } - - try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()))) { - NEIClientConfig.logger.info("Loading handler ordering from file {}", file); - CSVParser csvParser = CSVFormat.EXCEL.builder().setCommentMarker('#').build().parse(reader); - for (CSVRecord record : csvParser) { - final String handlerId = record.get(0); + } catch (IOException e) {} + }, lines -> lines.map(line -> line.split(COMMA_DELIMITER)).filter(parts -> parts.length == 2).forEach(parts -> { + String handlerId = parts[0]; + int ordering = Integer.getInteger(parts[1], 0); + NEIClientConfig.handlerOrdering.put(handlerId, ordering); + })); + } - int ordering; - try { - ordering = Integer.parseInt(record.get(1)); - } catch (NumberFormatException e) { - NEIClientConfig.logger.error("Error parsing CSV record {}: {}", record, e); - continue; - } + public static void loadPluginsList() { + final ClassDiscoverer classDiscoverer = new ClassDiscoverer( + test -> test.startsWith("NEI") && test.endsWith("Config.class"), + IConfigureNEI.class); - NEIClientConfig.handlerOrdering.put(handlerId, ordering); - } - } catch (Exception e) { - NEIClientConfig.logger.info("Error parsing CSV"); - e.printStackTrace(); - } + NEIClientConfig.pluginsList.addAll(classDiscoverer.findClasses()); } @SubscribeEvent diff --git a/src/main/java/codechicken/nei/CollapsibleItems.java b/src/main/java/codechicken/nei/CollapsibleItems.java index 935a7044b..899b502fb 100644 --- a/src/main/java/codechicken/nei/CollapsibleItems.java +++ b/src/main/java/codechicken/nei/CollapsibleItems.java @@ -1,227 +1,33 @@ package codechicken.nei; import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.net.URL; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Predicate; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; import java.util.stream.Collectors; -import java.util.stream.IntStream; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTBase.NBTPrimitive; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.StatCollector; -import net.minecraftforge.oredict.OreDictionary; - -import org.apache.commons.io.IOUtils; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; -import codechicken.nei.ItemList.AllMultiItemFilter; import codechicken.nei.ItemList.AnyMultiItemFilter; import codechicken.nei.ItemList.EverythingItemFilter; -import codechicken.nei.ItemList.NegatedItemFilter; import codechicken.nei.ItemList.NothingItemFilter; import codechicken.nei.PresetsList.Preset; import codechicken.nei.PresetsList.PresetMode; import codechicken.nei.api.ItemFilter; -import cpw.mods.fml.common.registry.GameData; +import codechicken.nei.util.ItemStackFilterParser; public class CollapsibleItems { - protected static interface ISearchParserProvider { - - public ItemFilter getFilter(String searchText); - - default Predicate getMatcher(String searchText) { - - if (searchText.length() >= 3 && searchText.startsWith("r/") && searchText.endsWith("/")) { - - try { - Pattern pattern = Pattern.compile( - searchText.substring(2, searchText.length() - 1), - Pattern.MULTILINE | Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); - return value -> pattern.matcher(value).find(); - } catch (PatternSyntaxException ignored) {} - - } else if (!searchText.isEmpty()) { - return value -> value.toLowerCase().contains(searchText); - } - - return null; - } - - } - - protected static class GroupTokenParser { - - protected final HashMap searchProviders = new HashMap<>(); - - public void addProvider(char prefix, ISearchParserProvider provider) { - this.searchProviders.put(prefix, provider); - } - - public ItemFilter getFilter(String filterText) { - final String[] parts = filterText.toLowerCase().trim().split("\\|"); - final List searchTokens = Arrays.stream(parts).map(s -> parseSearchText(s)) - .filter(s -> s != null && !s.filters.isEmpty()).collect(Collectors.toCollection(ArrayList::new)); - - if (searchTokens.isEmpty()) { - return new EverythingItemFilter(); - } else if (searchTokens.size() == 1) { - return searchTokens.get(0); - } else { - return new AnyMultiItemFilter(searchTokens); - } - } - - private AllMultiItemFilter parseSearchText(String filterText) { - - if (filterText.isEmpty()) { - return null; - } - - final String[] tokens = filterText.split("\\s+"); - final AllMultiItemFilter searchTokens = new AllMultiItemFilter(); - - for (String token : tokens) { - token = token.trim(); - boolean ignore = token.startsWith("!"); - - if (ignore) { - token = token.substring(1); - } - - if (token.isEmpty()) { - continue; - } - - ISearchParserProvider provider = this.searchProviders.get(token.charAt(0)); - - if (provider != null) { - token = token.substring(1); - } else { - provider = this.searchProviders.get('\0'); - } - - ItemFilter filter = parseToken(ignore ? "!" + token : token, provider); - - if (filter != null) { - searchTokens.filters.add(filter); - } - } - - return searchTokens; - } - - private ItemFilter parseToken(String token, ISearchParserProvider provider) { - final String[] parts = token.split(","); - final AnyMultiItemFilter includeFilter = new AnyMultiItemFilter(); - final AnyMultiItemFilter expludeFilter = new AnyMultiItemFilter(); - final AllMultiItemFilter groupFilter = new AllMultiItemFilter(); - - for (String part : parts) { - boolean ignore = part.startsWith("!"); - - if (ignore) { - part = part.substring(1); - } - - ItemFilter filter = provider.getFilter(part); - - if (filter == null) { - continue; - } - - if (ignore) { - expludeFilter.filters.add(filter); - } else { - includeFilter.filters.add(filter); - } - } - - if (!includeFilter.filters.isEmpty()) { - groupFilter.filters.add(includeFilter); - } - - if (!expludeFilter.filters.isEmpty()) { - groupFilter.filters.add(new NegatedItemFilter(expludeFilter)); - } - - return groupFilter.filters.isEmpty() ? null : groupFilter; - } - } - - protected static class IdentifierFilter implements ISearchParserProvider { - - @Override - public ItemFilter getFilter(String searchText) { - - if (Pattern.matches("^\\d+(-\\d+)*$", searchText)) { - final Predicate filter = generateDamageFilter(searchText); - return (stack) -> filter.test(stack.getItemDamage()); - } - - Predicate matcher = getMatcher(searchText); - - if (matcher != null) { - return stack -> matcher.test(getStringIdentifier(stack)); - } - - return null; - } - - protected String getStringIdentifier(ItemStack stack) { - String name = GameData.getItemRegistry().getNameForObject(stack.getItem()); - return name == null || name.isEmpty() ? "Unknown:Unknown" : name; - } - - protected Predicate generateDamageFilter(String searchText) { - String[] range = searchText.split("-"); - - if (range.length == 1) { - final int damage = Integer.parseInt(range[0]); - return (dmg) -> dmg == damage; - } else { - final int damageStart = Integer.parseInt(range[0]); - final int damageEnd = Integer.parseInt(range[1]); - return (dmg) -> dmg >= damageStart && dmg <= damageEnd; - } - } - } - - protected static class OreDictionaryFilter implements ISearchParserProvider { - - @Override - public ItemFilter getFilter(String searchText) { - Predicate matcher = getMatcher(searchText); - - if (matcher != null) { - return stack -> matches(stack, matcher); - } - - return null; - } - - protected boolean matches(ItemStack stack, Predicate matcher) { - return IntStream.of(OreDictionary.getOreIDs(stack)) - .anyMatch(id -> matcher.test(OreDictionary.getOreName(id))); - } - } - protected static class GroupItem { public String guid; @@ -232,8 +38,8 @@ protected static class GroupItem { public GroupItem() {} public void setFilter(String filter) { - this.filter = CollapsibleItems.groupParser.getFilter(filter.trim()); - this.guid = UUID.nameUUIDFromBytes(filter.getBytes()).toString(); + this.filter = ItemStackFilterParser.parse(filter.trim()); + this.guid = this.filter != null ? UUID.nameUUIDFromBytes(filter.getBytes()).toString() : ""; } public void setFilter(ItemFilter filter, String guid) { @@ -246,17 +52,40 @@ public boolean matches(ItemStack stack) { } } + private static final String STATE_KEY = "collapsibleitems"; + protected File statesFile; - protected static final GroupTokenParser groupParser = new GroupTokenParser(); protected final List groups = new ArrayList<>(); protected final Map cache = new ConcurrentHashMap<>(); - static { - groupParser.addProvider('\0', new IdentifierFilter()); - groupParser.addProvider('$', new OreDictionaryFilter()); + public void load() { + try { + + if (NEIClientConfig.world.nbt.hasKey(STATE_KEY)) { + NBTTagCompound states = NEIClientConfig.world.nbt.getCompoundTag(STATE_KEY); + @SuppressWarnings("unchecked") + final Map list = (Map) states.tagMap; + final Map mapping = new HashMap<>(); + + for (GroupItem group : this.groups) { + mapping.put(group.guid, group); + } + + for (Map.Entry nbtEntry : list.entrySet()) { + if (mapping.containsKey(nbtEntry.getKey())) { + mapping.get(nbtEntry.getKey()).expanded = nbtEntry.getValue().func_150290_f() == 1; + } + } + } + + } catch (Exception e) { + NEIClientConfig.logger.error("Error loading collapsible items states", e); + } + + reloadGroups(); } - public void reload() { + public void reloadGroups() { this.groups.clear(); this.cache.clear(); @@ -271,49 +100,17 @@ public void reload() { } if (NEIClientConfig.enableCollapsibleItems()) { - loadCollapsibleItems(); - } - - loadStates(); - - if (ItemList.loadFinished) { - LayoutManager.markItemsDirty(); + ClientHandler.loadSettingsFile( + "collapsibleitems.cfg", + lines -> parseFile(lines.collect(Collectors.toCollection(ArrayList::new)))); } } - protected void loadCollapsibleItems() { - File file = NEIClientConfig.collapsibleItemsFile; - if (!file.exists()) { - try (FileWriter writer = new FileWriter(file)) { - NEIClientConfig.logger.info("Creating default collapsible items list {}", file); - URL defaultCollapsibleItemsResource = ClientHandler.class - .getResource("/assets/nei/cfg/collapsibleitems.cfg"); - if (defaultCollapsibleItemsResource != null) { - IOUtils.copy(defaultCollapsibleItemsResource.openStream(), writer); - } - } catch (IOException e) { - NEIClientConfig.logger.error("Failed to save default collapsible items list to file {}", file, e); - } - } - - try (FileReader reader = new FileReader(file)) { - NEIClientConfig.logger.info("Loading collapsible items from file {}", file); - parseFile(IOUtils.readLines(reader)); - } catch (IOException e) { - NEIClientConfig.logger.error("Failed to load collapsible items from file {}", file, e); - } - } - - public void parseFile(List itemStrings) { + private void parseFile(List itemStrings) { final JsonParser parser = new JsonParser(); GroupItem group = new GroupItem(); for (String itemStr : itemStrings) { - - if (itemStr.startsWith("#") || itemStr.trim().isEmpty()) { - continue; - } - try { if (itemStr.startsWith("; ")) { @@ -324,10 +121,10 @@ public void parseFile(List itemStrings) { } if (settings.get("unlocalizedName") != null) { - String displayName = StatCollector - .translateToLocal(settings.get("unlocalizedName").getAsString()); + String unlocalizedName = settings.get("unlocalizedName").getAsString(); + String displayName = StatCollector.translateToLocal(unlocalizedName); - if (!displayName.equals(settings.get("unlocalizedName").getAsString())) { + if (!displayName.equals(unlocalizedName)) { group.displayName = displayName; } } @@ -430,7 +227,7 @@ public void setExpanded(int groupIndex, boolean expanded) { public void toggleGroups(Boolean expanded) { if (expanded == null) { - expanded = !this.groups.stream().filter(g -> g.expanded).findAny().isPresent(); + expanded = this.groups.stream().noneMatch(g -> g.expanded); } for (GroupItem group : this.groups) { @@ -440,33 +237,6 @@ public void toggleGroups(Boolean expanded) { saveStates(); } - private void loadStates() { - - try { - - if (NEIClientConfig.world.nbt.hasKey("collapsibleitems")) { - NBTTagCompound states = NEIClientConfig.world.nbt.getCompoundTag("collapsibleitems"); - @SuppressWarnings("unchecked") - final Map list = (Map) states.tagMap; - final Map mapping = new HashMap<>(); - - for (GroupItem group : this.groups) { - mapping.put(group.guid, group); - } - - for (Map.Entry nbtEntry : list.entrySet()) { - if (mapping.containsKey(nbtEntry.getKey())) { - mapping.get(nbtEntry.getKey()).expanded = nbtEntry.getValue().func_150290_f() == 1; - } - } - } - - } catch (Exception e) { - NEIClientConfig.logger.error("Error loading collapsible items states", e); - } - - } - private void saveStates() { NBTTagCompound list = new NBTTagCompound(); @@ -474,7 +244,7 @@ private void saveStates() { list.setBoolean(group.guid, group.expanded); } - NEIClientConfig.world.nbt.setTag("collapsibleitems", list); + NEIClientConfig.world.nbt.setTag(STATE_KEY, list); } } diff --git a/src/main/java/codechicken/nei/ItemList.java b/src/main/java/codechicken/nei/ItemList.java index de1274a81..aec1ef956 100644 --- a/src/main/java/codechicken/nei/ItemList.java +++ b/src/main/java/codechicken/nei/ItemList.java @@ -6,7 +6,6 @@ import java.util.HashSet; import java.util.LinkedList; import java.util.List; -import java.util.StringJoiner; import java.util.concurrent.ExecutionException; import java.util.concurrent.ForkJoinPool; import java.util.regex.Pattern; @@ -105,7 +104,7 @@ public AllMultiItemFilter(List filters) { } public AllMultiItemFilter(ItemFilter... filters) { - this(Arrays.asList(filters)); + this(new LinkedList<>(Arrays.asList(filters))); } public AllMultiItemFilter() { @@ -139,7 +138,7 @@ public AnyMultiItemFilter() { @Override public boolean matches(ItemStack item) { for (ItemFilter filter : filters) try { - if (filter.matches(item)) return true; + if (filter != null && filter.matches(item)) return true; } catch (Exception e) { NEIClientConfig.logger.error("Exception filtering " + item + " with " + filter, e); } @@ -156,7 +155,7 @@ public static interface ItemsLoadedCallback { public static boolean itemMatchesAll(ItemStack item, List filters) { for (ItemFilter filter : filters) { try { - if (!filter.matches(item)) return false; + if (filter != null && !filter.matches(item)) return false; } catch (Exception e) { NEIClientConfig.logger.error("Exception filtering " + item + " with " + filter, e); } @@ -213,14 +212,7 @@ private void damageSearch(Item item, List permutations) { private String getTooltip(ItemStack stack) { try { - final List namelist = stack.getTooltip(Minecraft.getMinecraft().thePlayer, false); - final StringJoiner sb = new StringJoiner("\n"); - - for (String name : namelist) { - sb.add(name); - } - - return sb.toString(); + return String.join("\n", stack.getTooltip(Minecraft.getMinecraft().thePlayer, false)); } catch (Throwable ignored) {} return ""; @@ -261,8 +253,8 @@ private void updateOrdering(List items) { @Override @SuppressWarnings("unchecked") public void execute() { - // System.out.println("Executing NEI Item Loading"); ThreadOperationTimer timer = getTimer(NEIClientConfig.getItemLoadingTimeout()); + LayoutManager.itemsLoaded = true; loadFinished = false; List items = new LinkedList<>(); @@ -281,14 +273,21 @@ public void execute() { permutations.clear(); permutations.addAll(ItemInfo.itemOverrides.get(item)); - if (permutations.isEmpty()) item.getSubItems(item, null, permutations); + if (permutations.isEmpty()) { + item.getSubItems(item, null, permutations); + } - if (permutations.isEmpty()) damageSearch(item, permutations); + if (permutations.isEmpty()) { + damageSearch(item, permutations); + } permutations.addAll(ItemInfo.itemVariants.get(item)); timer.reset(); + permutations = permutations.stream().filter(stack -> !ItemInfo.isHidden(stack)) + .collect(Collectors.toCollection(ArrayList::new)); + items.addAll(permutations); itemMap.putAll(item, permutations); } catch (Throwable t) { diff --git a/src/main/java/codechicken/nei/LayoutManager.java b/src/main/java/codechicken/nei/LayoutManager.java index 2874c3350..eda28cb62 100644 --- a/src/main/java/codechicken/nei/LayoutManager.java +++ b/src/main/java/codechicken/nei/LayoutManager.java @@ -12,6 +12,7 @@ import static codechicken.nei.NEIClientConfig.isBookmarkPanelHidden; import static codechicken.nei.NEIClientConfig.isEnabled; import static codechicken.nei.NEIClientConfig.isHidden; +import static codechicken.nei.NEIClientConfig.isLoaded; import static codechicken.nei.NEIClientConfig.showIDs; import static codechicken.nei.NEIClientConfig.toggleBooleanSetting; import static codechicken.nei.NEIClientUtils.cycleGamemode; @@ -638,12 +639,11 @@ public void load(GuiContainer gui) { if (isEnabled()) { setInputFocused(null); - if (!itemsLoaded) { + if (!itemsLoaded && isLoaded()) { ItemList.loadItems.restart(); - itemsLoaded = true; } - overlayRenderer = null; + overlayRenderer = null; getLayoutStyle().init(); layout(gui); AutoFocusWidget.instance.load(gui); diff --git a/src/main/java/codechicken/nei/NEIClientConfig.java b/src/main/java/codechicken/nei/NEIClientConfig.java index 8bcce4657..80b37dbb4 100644 --- a/src/main/java/codechicken/nei/NEIClientConfig.java +++ b/src/main/java/codechicken/nei/NEIClientConfig.java @@ -6,6 +6,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.function.Function; import java.util.regex.Pattern; @@ -29,7 +30,6 @@ import com.google.gson.JsonParseException; import codechicken.core.CCUpdateChecker; -import codechicken.core.ClassDiscoverer; import codechicken.core.ClientUtils; import codechicken.core.CommonUtils; import codechicken.lib.config.ConfigFile; @@ -78,12 +78,6 @@ public class NEIClientConfig { public static ConfigSet world; public static final File handlerFile = new File(configDir, "handlers.csv"); public static final File catalystFile = new File(configDir, "catalysts.csv"); - public static final File serialHandlersFile = new File(configDir, "serialhandlers.cfg"); - public static final File heightHackHandlersFile = new File(configDir, "heighthackhandlers.cfg"); - public static final File handlerOrderingFile = new File(configDir, "handlerordering.csv"); - public static final File hiddenHandlersFile = new File(configDir, "hiddenhandlers.csv"); - public static final File enableAutoFocusFile = new File(configDir, "enableautofocus.cfg"); - public static final File collapsibleItemsFile = new File(configDir, "collapsibleitems.cfg"); @Deprecated public static File bookmarkFile; @@ -103,6 +97,8 @@ public class NEIClientConfig { // Any handler not in the map will be assigned to 0, and negative numbers are fine. public static HashMap handlerOrdering = new HashMap<>(); + public static final Set> pluginsList = new HashSet<>(); + // Function that extracts the handler ID from a handler, with special logic for // TemplateRecipeHandler: prefer using the overlay ID if it exists. public static final Function HANDLER_ID_FUNCTION = handler -> Objects @@ -265,7 +261,7 @@ public String getButtonText() { @Override public boolean onClick(int button) { super.onClick(button); - initBookmarkFile(worldPath); + ItemPanels.bookmarkPanel.load(); return true; } }); @@ -341,8 +337,10 @@ public boolean onClick(int button) { @Override public boolean onClick(int button) { + super.onClick(button); + ItemList.collapsibleItems.reloadGroups(); LayoutManager.markItemsDirty(); - return super.onClick(button); + return true; } }); @@ -445,18 +443,6 @@ public boolean isEnabled() { tag.getTag("command.heal").setDefaultValue(""); API.addOption(new OptionTextField("command.heal")); - tag.getTag("inventory.worldSpecificPresets").setComment("Global or world specific presets") - .getBooleanValue(false); - API.addOption(new OptionToggleButton("inventory.worldSpecificPresets", true) { - - @Override - public boolean onClick(int button) { - super.onClick(button); - initPresetsFile(worldPath); - return true; - } - }); - tag.getTag("inventory.showItemQuantityWidget").setComment("Show Item Quantity Widget").getBooleanValue(true); API.addOption(new OptionToggleButton("inventory.showItemQuantityWidget", true)); @@ -571,11 +557,11 @@ public static OptionList getOptionList() { } public static void loadWorld(String worldPath) { + unloadWorld(); NEIClientConfig.worldPath = worldPath; setInternalEnabled(true); logger.debug("Loading " + (Minecraft.getMinecraft().isSingleplayer() ? "Local" : "Remote") + " World"); - bootNEI(ClientUtils.getWorld()); final File specificDir = new File(CommonUtils.getMinecraftDir(), "saves/NEI/" + worldPath); final boolean newWorld = !specificDir.exists(); @@ -585,11 +571,15 @@ public static void loadWorld(String worldPath) { } world = new ConfigSet(new File(specificDir, "NEI.dat"), new ConfigFile(new File(specificDir, "NEI.cfg"))); - initBookmarkFile(worldPath); - initPresetsFile(worldPath); + bootNEI(ClientUtils.getWorld()); + ItemPanels.bookmarkPanel.load(); onWorldLoad(newWorld); } + public static String getWorldPath() { + return NEIClientConfig.worldPath; + } + private static void onWorldLoad(boolean newWorld) { world.config.setComment( "World based configuration of NEI.\nMost of these options can be changed ingame.\nDeleting any element will restore it to it's default value"); @@ -688,25 +678,20 @@ public static void bootNEI(World world) { @Override public void run() { - logger.debug("Started NEI plugin loading"); - ClassDiscoverer classDiscoverer = new ClassDiscoverer( - test -> test.startsWith("NEI") && test.endsWith("Config.class"), - IConfigureNEI.class); - - classDiscoverer.findClasses(); - for (Class clazz : classDiscoverer.classes) { + NEIClientConfig.pluginsList.parallelStream().forEach(clazz -> { try { IConfigureNEI config = (IConfigureNEI) clazz.getConstructor().newInstance(); config.loadConfig(); NEIModContainer.plugins.add(config); - logger.debug("Loaded " + clazz.getName()); + logger.debug("Loaded {}", clazz.getName()); } catch (Exception e) { - logger.error("Failed to Load " + clazz.getName(), e); + logger.error("Failed to Load {}", clazz.getName(), e); } - } + }); RecipeCatalysts.loadCatalystInfo(); + ItemSorter.loadConfig(); // Set pluginNEIConfigLoaded here before posting the NEIConfigsLoadedEvent. This used to be the other // way around, but apparently if your modpack includes 800 mods the event poster might not return in @@ -714,29 +699,11 @@ public void run() { // cause issues in case one of the event handler calls the (non-thread-safe) NEI API. I don't expect any // handler to do this, but who knows what modders have come up with... pluginNEIConfigLoaded = true; - logger.debug("NEI plugin loading finished"); MinecraftForge.EVENT_BUS.post(new NEIConfigsLoadedEvent()); + + ItemList.loadItems.restart(); } }.start(); - ItemSorter.loadConfig(); - } - - private static void initBookmarkFile(String worldPath) { - - if (!global.config.getTag("inventory.bookmarks.worldSpecific").getBooleanValue()) { - worldPath = "global"; - } - - ItemPanels.bookmarkPanel.setBookmarkFile(worldPath); - } - - private static void initPresetsFile(String worldPath) { - - if (!global.config.getTag("inventory.worldSpecificPresets").getBooleanValue()) { - worldPath = "global"; - } - - PresetsList.setPresetsFile(worldPath); } public static boolean isWorldSpecific(String setting) { diff --git a/src/main/java/codechicken/nei/PresetsList.java b/src/main/java/codechicken/nei/PresetsList.java index 40122feac..97cbbe6e8 100644 --- a/src/main/java/codechicken/nei/PresetsList.java +++ b/src/main/java/codechicken/nei/PresetsList.java @@ -4,8 +4,6 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashSet; @@ -145,62 +143,20 @@ public boolean matches(ItemStack stack) { } public static final List presets = new ArrayList<>(); - - protected static File presetsFile; protected static RecipesFilter recipeFilter = new RecipesFilter(); protected static ItemPanelFilter itemFilter = new ItemPanelFilter(); static { API.addItemFilter(itemFilter); API.addRecipeFilter(recipeFilter); - ItemList.loadCallbacks.add(PresetsList::itemsLoaded); } public static ItemFilter getItemFilter() { return itemFilter.getFilter(); } - public static void itemsLoaded() { - recipeFilter.cache = null; - itemFilter.cache = null; - ItemList.collapsibleItems.reload(); - } - - public static void setPresetsFile(String worldPath) { - final File dir = new File(CommonUtils.getMinecraftDir(), "saves/NEI/" + worldPath); - - if (!dir.exists()) { - dir.mkdirs(); - } - - presetsFile = new File(dir, "presets.ini"); - - if (!presetsFile.exists()) { - final File globalPresets = new File(CommonUtils.getMinecraftDir(), "saves/NEI/global/presets.ini"); - final File configPresets = new File(NEIClientConfig.configDir, "presets.ini"); - final File defaultBookmarks = configPresets.exists() ? configPresets : globalPresets; - - if (defaultBookmarks.exists()) { - - try { - presetsFile.createNewFile(); - - InputStream src = new FileInputStream(defaultBookmarks); - OutputStream dst = new FileOutputStream(presetsFile); - - IOUtils.copy(src, dst); - - src.close(); - dst.close(); - - } catch (IOException e) {} - } - } - - loadPresets(); - } - - protected static void loadPresets() { + public static void load() { + final File presetsFile = new File(CommonUtils.getMinecraftDir(), "saves/NEI/global/presets.ini"); if (presetsFile == null || !presetsFile.exists()) { return; @@ -236,15 +192,15 @@ protected static void loadPresets() { preset = new Preset(); } - if (settings.get("name") != null) { + if (settings.has("name")) { preset.name = settings.get("name").getAsString(); } - if (settings.get("enabled") != null) { + if (settings.has("enabled")) { preset.enabled = settings.get("enabled").getAsBoolean(); } - if (settings.get("mode") != null) { + if (settings.has("mode")) { preset.mode = PresetMode.valueOf(settings.get("mode").getAsString()); } @@ -260,17 +216,11 @@ protected static void loadPresets() { if (!preset.items.isEmpty()) { presets.add(preset); } - - itemsLoaded(); } public static void savePresets() { - - if (presetsFile == null) { - return; - } - - List strings = new ArrayList<>(); + final File presetsFile = new File(CommonUtils.getMinecraftDir(), "saves/NEI/global/presets.ini"); + final List strings = new ArrayList<>(); for (Preset preset : presets) { JsonObject settings = new JsonObject(); @@ -289,7 +239,10 @@ public static void savePresets() { NEIClientConfig.logger.error("Filed to save presets list to file {}", presetsFile, e); } - itemsLoaded(); + recipeFilter.cache = null; + itemFilter.cache = null; + ItemList.collapsibleItems.reloadGroups(); + LayoutManager.markItemsDirty(); } } diff --git a/src/main/java/codechicken/nei/SearchTokenParser.java b/src/main/java/codechicken/nei/SearchTokenParser.java index 68fb064b8..e45fce797 100644 --- a/src/main/java/codechicken/nei/SearchTokenParser.java +++ b/src/main/java/codechicken/nei/SearchTokenParser.java @@ -192,7 +192,11 @@ private ItemFilter parseToken(String firstChar, String token) { for (ISearchParserProvider _provider : getProviders()) { if (_provider.getSearchMode() == SearchMode.ALWAYS) { - filters.add(_provider.getFilter(token)); + ItemFilter filter = _provider.getFilter(token); + + if (filter != null) { + filters.add(filter); + } } } diff --git a/src/main/java/codechicken/nei/SubsetWidget.java b/src/main/java/codechicken/nei/SubsetWidget.java index 67c2a048e..d9cad8c2c 100644 --- a/src/main/java/codechicken/nei/SubsetWidget.java +++ b/src/main/java/codechicken/nei/SubsetWidget.java @@ -33,7 +33,6 @@ import codechicken.nei.api.API; import codechicken.nei.api.ItemFilter; import codechicken.nei.api.ItemFilter.ItemFilterProvider; -import codechicken.nei.api.ItemInfo; import codechicken.nei.guihook.GuiContainerManager; public class SubsetWidget extends Button implements ItemFilterProvider, ItemsLoadedCallback { @@ -641,7 +640,6 @@ public void execute() { if (reallocate) { for (ItemStack item : ItemList.items) { if (interrupted()) return; - if (ItemInfo.isHidden(item)) continue; for (SubsetTag tag : tags) if (tag.filter.matches(item)) state.get(tag.fullname).items.add(item); } } diff --git a/src/main/java/codechicken/nei/api/API.java b/src/main/java/codechicken/nei/api/API.java index 96c747cab..76f1180c8 100644 --- a/src/main/java/codechicken/nei/api/API.java +++ b/src/main/java/codechicken/nei/api/API.java @@ -42,6 +42,7 @@ import codechicken.nei.recipe.RecipeCatalysts; import codechicken.nei.recipe.RecipeInfo; import codechicken.nei.recipe.StackInfo; +import codechicken.nei.util.ItemStackFilterParser; /** * This is the main class that handles item property configuration. WARNING: DO NOT access this class until the world @@ -151,6 +152,14 @@ public static void hideItem(ItemStack item) { } } + public static void hideItem(String rule) { + ItemFilter filter = ItemStackFilterParser.parse(rule); + if (filter != null) { + ItemInfo.hiddenItemsRules.filters.add(filter); + LayoutManager.markItemsDirty(); + } + } + /** * Add or replace the name normally shown on the item tooltip */ diff --git a/src/main/java/codechicken/nei/api/ItemInfo.java b/src/main/java/codechicken/nei/api/ItemInfo.java index 4985fafd4..e47234edc 100644 --- a/src/main/java/codechicken/nei/api/ItemInfo.java +++ b/src/main/java/codechicken/nei/api/ItemInfo.java @@ -44,12 +44,14 @@ import codechicken.nei.InfiniteStackSizeHandler; import codechicken.nei.InfiniteToolHandler; import codechicken.nei.ItemList; +import codechicken.nei.ItemList.AnyMultiItemFilter; import codechicken.nei.ItemList.PatternItemFilter; import codechicken.nei.ItemMobSpawner; import codechicken.nei.ItemStackMap; import codechicken.nei.ItemStackSet; import codechicken.nei.NEIClientConfig; import codechicken.nei.PopupInputHandler; +import codechicken.nei.PresetsList; import codechicken.nei.SearchField.SearchParserProvider; import codechicken.nei.SearchTokenParser.SearchMode; import codechicken.nei.config.ArrayDumper; @@ -82,6 +84,7 @@ public static enum Layout { public static final ArrayListMultimap highlightHandlers = ArrayListMultimap.create(); public static final ItemStackMap nameOverrides = new ItemStackMap<>(); public static final ItemStackSet hiddenItems = new ItemStackSet(); + public static final AnyMultiItemFilter hiddenItemsRules = new AnyMultiItemFilter(); public static final ItemStackSet finiteItems = new ItemStackSet(); public static final ArrayListMultimap itemOverrides = ArrayListMultimap.create(); public static final ArrayListMultimap itemVariants = ArrayListMultimap.create(); @@ -93,9 +96,10 @@ public static enum Layout { public static final HashMap itemOwners = new HashMap<>(); public static boolean isHidden(ItemStack stack) { - return hiddenItems.contains(stack); + return hiddenItems.contains(stack) || hiddenItemsRules.matches(stack); } + @Deprecated public static boolean isHidden(Item item) { return hiddenItems.containsAll(item); } @@ -130,15 +134,12 @@ public static void load(World world) { addInfiniteHandlers(); addInputHandlers(); addIDDumps(); - addHiddenItemFilter(); addSearchProviders(); + PresetsList.load(); + ItemList.collapsibleItems.load(); ItemList.loadCallbacks.add(TooltipFilter::populateSearchMap); } - private static void addHiddenItemFilter() { - API.addItemFilter(() -> item -> !hiddenItems.contains(item)); - } - private static void addSearchProviders() { API.addSearchProvider( new SearchParserProvider('\0', "default", EnumChatFormatting.RESET, PatternItemFilter::new) { diff --git a/src/main/java/codechicken/nei/config/preset/LeftPanel.java b/src/main/java/codechicken/nei/config/preset/LeftPanel.java index 4d5928254..b2f267321 100644 --- a/src/main/java/codechicken/nei/config/preset/LeftPanel.java +++ b/src/main/java/codechicken/nei/config/preset/LeftPanel.java @@ -13,7 +13,6 @@ import codechicken.core.gui.GuiWidget; import codechicken.lib.gui.GuiDraw; import codechicken.lib.vec.Rectangle4i; -import codechicken.nei.ItemList.AllMultiItemFilter; import codechicken.nei.ItemPanel.ItemPanelSlot; import codechicken.nei.ItemsGrid; import codechicken.nei.Label; @@ -22,7 +21,6 @@ import codechicken.nei.PresetsList.PresetMode; import codechicken.nei.TextField; import codechicken.nei.api.ItemFilter; -import codechicken.nei.api.ItemInfo; import codechicken.nei.guihook.GuiContainerManager; import codechicken.nei.guihook.IContainerTooltipHandler; @@ -52,9 +50,7 @@ public MouseSelection(int slotIndex, Rectangle4i rec) { @Override protected ItemFilter getFilter() { Set identifiers = preset.items; - return new AllMultiItemFilter( - item -> !ItemInfo.hiddenItems.contains(item), - item -> identifiers.contains(Preset.getIdentifier(item))); + return item -> identifiers.contains(Preset.getIdentifier(item)); } @Override @@ -146,6 +142,7 @@ protected void onChange() { grid.restartFilter(); } + @Override public void mouseClicked(int x, int y, int button) { grid.mouseClicked(x, y, button); @@ -183,6 +180,7 @@ public void mouseClicked(int x, int y, int button) { protected void onItemsChanges() {} + @Override public void mouseMovedOrUp(int x, int y, int button) { nameField.mouseUp(x, y, button); @@ -203,6 +201,7 @@ public void mouseMovedOrUp(int x, int y, int button) { } } + @Override public void mouseDragged(int x, int y, int button, long time) { nameField.mouseDragged(x, y, button, time); @@ -233,6 +232,7 @@ public void mouseDragged(int x, int y, int button, long time) { } } + @Override public void update() { int CHECKBOX_WIDTH = (this.width - 12) / 3; nameLabel.x = this.x + 2; @@ -271,6 +271,7 @@ public void update() { grid.refresh(null); } + @Override public void draw(int mousex, int mousey, float frame) { nameLabel.draw(mousex, mousey); nameField.draw(mousex, mousey); @@ -305,7 +306,7 @@ public List handleTooltip(int mousex, int mousey, List tooltip) } } - if (tooltip.size() > 0) { + if (!tooltip.isEmpty()) { tooltip.set(0, tooltip.get(0) + GuiDraw.TOOLTIP_LINESPACE); // add space after 'title' } @@ -320,6 +321,7 @@ public List handleTooltip(int mousex, int mousey, List tooltip) return tooltip; } + @Override public void keyTyped(char c, int keycode) { nameField.handleKeyPress(keycode, c); } diff --git a/src/main/java/codechicken/nei/config/preset/PresetItemsGrid.java b/src/main/java/codechicken/nei/config/preset/PresetItemsGrid.java index b745fce45..a65e56288 100644 --- a/src/main/java/codechicken/nei/config/preset/PresetItemsGrid.java +++ b/src/main/java/codechicken/nei/config/preset/PresetItemsGrid.java @@ -56,7 +56,7 @@ public void execute() { } }; - public PresetItemsGrid() { + protected PresetItemsGrid() { pageLabel = new Label("0/0", true); diff --git a/src/main/java/codechicken/nei/config/preset/RightPanel.java b/src/main/java/codechicken/nei/config/preset/RightPanel.java index edfd07ead..6793fd8b8 100644 --- a/src/main/java/codechicken/nei/config/preset/RightPanel.java +++ b/src/main/java/codechicken/nei/config/preset/RightPanel.java @@ -28,7 +28,6 @@ import codechicken.nei.SearchField.GuiSearchField; import codechicken.nei.TextField; import codechicken.nei.api.ItemFilter; -import codechicken.nei.api.ItemInfo; import codechicken.nei.guihook.GuiContainerManager; import codechicken.nei.guihook.IContainerTooltipHandler; import codechicken.nei.util.TextHistory; @@ -55,11 +54,11 @@ public MouseSelection(int slotIndex, Rectangle4i rec, boolean ppnd) { } } - protected static abstract class PresetSearchField extends TextField { + protected abstract static class PresetSearchField extends TextField { private static final TextHistory history = new TextHistory(); - public PresetSearchField(String ident) { + protected PresetSearchField(String ident) { super(ident); } @@ -134,9 +133,7 @@ private boolean handleNavigateHistory(TextHistory.Direction direction) { @Override protected ItemFilter getFilter() { - AllMultiItemFilter filter = new AllMultiItemFilter(); - filter.filters.add(item -> !ItemInfo.hiddenItems.contains(item)); - filter.filters.add(searchField.getFilter()); + AllMultiItemFilter filter = new AllMultiItemFilter(searchField.getFilter()); if (enabledPresets.isChecked()) { AllMultiItemFilter andFilter = new AllMultiItemFilter(); @@ -162,7 +159,7 @@ protected ItemFilter getFilter() { protected boolean isSelected(ItemStack stack) { if (mouseSelection != null && mouseSelection.items.contains(stack)) { - return mouseSelection.append != false; + return mouseSelection.append; } return preset.items.contains(Preset.getIdentifier(stack)); @@ -206,6 +203,7 @@ protected void onChange() { grid.restartFilter(); } + @Override public void mouseClicked(int x, int y, int button) { grid.mouseClicked(x, y, button); @@ -231,6 +229,7 @@ public void mouseClicked(int x, int y, int button) { protected void onItemsChanges() {} + @Override public void mouseMovedOrUp(int x, int y, int button) { searchField.mouseUp(x, y, button); @@ -300,6 +299,7 @@ protected static String getModId(final ItemStack stack) { return null; } + @Override public void mouseDragged(int x, int y, int button, long time) { searchField.mouseDragged(x, y, button, time); @@ -330,6 +330,7 @@ public void mouseDragged(int x, int y, int button, long time) { } } + @Override public void update() { enabledPresets.w = 20; enabledPresets.h = INPUT_HEIGHT; @@ -345,6 +346,7 @@ public void update() { grid.refresh(null); } + @Override public void draw(int mousex, int mousey, float frame) { enabledPresets.draw(mousex, mousey); searchField.draw(mousex, mousey); @@ -372,7 +374,7 @@ public List handleTooltip(int mousex, int mousey, List tooltip) } } - if (tooltip.size() > 0) { + if (!tooltip.isEmpty()) { tooltip.set(0, tooltip.get(0) + GuiDraw.TOOLTIP_LINESPACE); // add space after 'title' } @@ -383,10 +385,12 @@ public List handleTooltip(int mousex, int mousey, List tooltip) return tooltip; } + @Override public void keyTyped(char c, int keycode) { searchField.handleKeyPress(keycode, c); } + @Override public void mouseScrolled(int x, int y, int scroll) { if (grid.contains(x, y)) { grid.shiftPage(-scroll); diff --git a/src/main/java/codechicken/nei/guihook/GuiContainerManager.java b/src/main/java/codechicken/nei/guihook/GuiContainerManager.java index 0841dd8f4..97226e2d3 100644 --- a/src/main/java/codechicken/nei/guihook/GuiContainerManager.java +++ b/src/main/java/codechicken/nei/guihook/GuiContainerManager.java @@ -155,13 +155,15 @@ public static List itemDisplayNameMultiline(ItemStack stack, GuiContaine namelist = stack.getTooltip( Minecraft.getMinecraft().thePlayer, includeHandlers && Minecraft.getMinecraft().gameSettings.advancedItemTooltips); - } catch (Throwable ignored) {} - - if (namelist == null) namelist = new ArrayList<>(); - - if (namelist.size() == 0) namelist.add("Unnamed"); + } catch (Throwable ignored) { + namelist = new ArrayList<>(); + } - if (namelist.get(0) == null || namelist.get(0).equals("")) namelist.set(0, "Unnamed"); + if (namelist.isEmpty()) { + namelist.add("Unnamed"); + } else if (namelist.get(0) == null || namelist.get(0).isEmpty()) { + namelist.set(0, "Unnamed"); + } if (includeHandlers) { for (IContainerTooltipHandler handler : tooltipHandlers) { diff --git a/src/main/java/codechicken/nei/recipe/GuiCraftingRecipe.java b/src/main/java/codechicken/nei/recipe/GuiCraftingRecipe.java index b7adc22d4..711e2877d 100644 --- a/src/main/java/codechicken/nei/recipe/GuiCraftingRecipe.java +++ b/src/main/java/codechicken/nei/recipe/GuiCraftingRecipe.java @@ -5,7 +5,9 @@ import java.awt.Point; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; @@ -24,6 +26,7 @@ public class GuiCraftingRecipe extends GuiRecipe { public static ArrayList craftinghandlers = new ArrayList<>(); public static ArrayList serialCraftingHandlers = new ArrayList<>(); + private static Set existingHandlers = new HashSet<>(); public static boolean openRecipeGui(String outputId, Object... results) { return createRecipeGui(outputId, true, results) != null; @@ -155,12 +158,24 @@ private GuiCraftingRecipe(ArrayList handlers, boolean limitToO public static void registerRecipeHandler(ICraftingHandler handler) { final String handlerId = handler.getHandlerId(); - if (craftinghandlers.stream().anyMatch(h -> h.getHandlerId().equals(handlerId)) - || serialCraftingHandlers.stream().anyMatch(h -> h.getHandlerId().equals(handlerId))) + if (existingHandlers.contains(handlerId)) { return; + } + + synchronized (existingHandlers) { + existingHandlers.add(handlerId); + } + + if (NEIClientConfig.serialHandlers.contains(handlerId)) { + synchronized (serialCraftingHandlers) { + serialCraftingHandlers.add(handler); + } + } else { + synchronized (craftinghandlers) { + craftinghandlers.add(handler); + } + } - if (NEIClientConfig.serialHandlers.contains(handlerId)) serialCraftingHandlers.add(handler); - else craftinghandlers.add(handler); } @Override diff --git a/src/main/java/codechicken/nei/recipe/GuiUsageRecipe.java b/src/main/java/codechicken/nei/recipe/GuiUsageRecipe.java index 6294e7fe2..6a629d931 100644 --- a/src/main/java/codechicken/nei/recipe/GuiUsageRecipe.java +++ b/src/main/java/codechicken/nei/recipe/GuiUsageRecipe.java @@ -2,6 +2,8 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; import net.minecraft.client.Minecraft; import net.minecraft.item.ItemStack; @@ -14,6 +16,7 @@ public class GuiUsageRecipe extends GuiRecipe { public static ArrayList usagehandlers = new ArrayList<>(); public static ArrayList serialUsageHandlers = new ArrayList<>(); + private static Set existingHandlers = new HashSet<>(); public static boolean openRecipeGui(String inputId, Object... ingredients) { @@ -65,12 +68,25 @@ private static ItemStack normalizeItemStack(ItemStack stack) { public static void registerUsageHandler(IUsageHandler handler) { final String handlerId = handler.getHandlerId(); - if (usagehandlers.stream().anyMatch(h -> h.getHandlerId().equals(handlerId)) - || serialUsageHandlers.stream().anyMatch(h -> h.getHandlerId().equals(handlerId))) + + if (existingHandlers.contains(handlerId)) { return; + } + + synchronized (existingHandlers) { + existingHandlers.add(handlerId); + } + + if (NEIClientConfig.serialHandlers.contains(handlerId)) { + synchronized (serialUsageHandlers) { + serialUsageHandlers.add(handler); + } + } else { + synchronized (usagehandlers) { + usagehandlers.add(handler); + } + } - if (NEIClientConfig.serialHandlers.contains(handlerId)) serialUsageHandlers.add(handler); - else usagehandlers.add(handler); } private static IUsageHandler getUsageOrCatalystHandler(IUsageHandler handler, String inputId, diff --git a/src/main/java/codechicken/nei/recipe/StackInfo.java b/src/main/java/codechicken/nei/recipe/StackInfo.java index 04d50815e..26587ab8a 100644 --- a/src/main/java/codechicken/nei/recipe/StackInfo.java +++ b/src/main/java/codechicken/nei/recipe/StackInfo.java @@ -1,15 +1,8 @@ package codechicken.nei.recipe; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import net.minecraft.item.ItemStack; @@ -20,10 +13,8 @@ import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.IFluidContainerItem; -import org.apache.commons.io.IOUtils; - +import codechicken.nei.ClientHandler; import codechicken.nei.ItemStackMap; -import codechicken.nei.NEIClientConfig; import codechicken.nei.api.IStackStringifyHandler; import codechicken.nei.recipe.stackinfo.DefaultStackStringifyHandler; import codechicken.nei.recipe.stackinfo.GTFluidStackStringifyHandler; @@ -189,37 +180,9 @@ public static String getItemStackGUID(ItemStack stack) { } public static void loadGuidFilters() { - guidfilters.clear(); - final File guidFlitersFile = new File(NEIClientConfig.configDir, "guidfilters.cfg"); - List itemStrings = new ArrayList<>(); - - if (guidFlitersFile.exists()) { - - try (FileReader reader = new FileReader(guidFlitersFile)) { - NEIClientConfig.logger.info("Loading guid filters from file {}", guidFlitersFile); - itemStrings = IOUtils.readLines(reader); - } catch (IOException e) { - NEIClientConfig.logger.error("Failed to load bookmarks from file {}", guidFlitersFile, e); - e.printStackTrace(); - } - - } else { - final URL filterUrl = StackInfo.class.getResource("/assets/nei/guidfilters.cfg"); - - try (BufferedReader reader = new BufferedReader(new InputStreamReader(filterUrl.openStream()))) { - itemStrings = IOUtils.readLines(reader); - } catch (IOException e) { - NEIClientConfig.logger.info("Error parsing guid filters"); - e.printStackTrace(); - } catch (Exception e) { - NEIClientConfig.logger.info("Error parsing guid filters"); - e.printStackTrace(); - } - } - - for (String guidStr : itemStrings) { + ClientHandler.loadSettingsFile("guidfilters.cfg", lines -> lines.forEach(guidStr -> { final String[] parts = guidStr.split(","); final HashMap rules = new HashMap<>(); @@ -228,7 +191,7 @@ public static void loadGuidFilters() { } guidfilters.put(parts[0], rules); - } + })); } public static ItemStack getItemStackWithMinimumDamage(ItemStack[] stacks) { diff --git a/src/main/java/codechicken/nei/recipe/TemplateRecipeHandler.java b/src/main/java/codechicken/nei/recipe/TemplateRecipeHandler.java index 818ba12c9..6d546327f 100644 --- a/src/main/java/codechicken/nei/recipe/TemplateRecipeHandler.java +++ b/src/main/java/codechicken/nei/recipe/TemplateRecipeHandler.java @@ -432,7 +432,7 @@ public TemplateRecipeHandler() { public static ItemFilter getItemFilter() { return new AllMultiItemFilter( - item -> !ItemInfo.hiddenItems.contains(item), + item -> !ItemInfo.isHidden(item), PresetsList.getItemFilter(), GuiRecipe.searchField != null ? GuiRecipe.searchField.getFilter() : null); } diff --git a/src/main/java/codechicken/nei/search/TooltipFilter.java b/src/main/java/codechicken/nei/search/TooltipFilter.java index a979c6110..af2439061 100644 --- a/src/main/java/codechicken/nei/search/TooltipFilter.java +++ b/src/main/java/codechicken/nei/search/TooltipFilter.java @@ -1,8 +1,6 @@ package codechicken.nei.search; -import java.util.HashSet; import java.util.List; -import java.util.StringJoiner; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; @@ -58,14 +56,13 @@ public boolean matches(ItemStack itemStack) { } public static void populateSearchMap() { - /* Create a snapshot of the current keys in the cache */ - HashSet oldItems = new HashSet<>(itemSearchNames.keySet()); + new Thread("NEI populate Tooltip Filter") { - for (ItemStack stack : ItemList.items) { - oldItems.remove(new ItemStackKey(stack)); - } - - itemSearchNames.keySet().removeAll(oldItems); + @Override + public void run() { + ItemList.items.parallelStream().forEach(TooltipFilter::getSearchTooltip); + } + }.start(); } protected static String getSearchTooltip(ItemStack stack) { @@ -74,14 +71,7 @@ protected static String getSearchTooltip(ItemStack stack) { private static String getTooltip(ItemStack itemstack) { final List list = GuiContainerManager.itemDisplayNameMultiline(itemstack, null, true); - final StringJoiner sb = new StringJoiner("\n"); - final int size = list.size(); - - for (int i = 1; i < size; i++) { - sb.add(list.get(i)); - } - - return EnumChatFormatting.getTextWithoutFormattingCodes(sb.toString()); + return EnumChatFormatting.getTextWithoutFormattingCodes(String.join("\n", list.subList(1, list.size()))); } } diff --git a/src/main/java/codechicken/nei/util/ItemStackFilterParser.java b/src/main/java/codechicken/nei/util/ItemStackFilterParser.java new file mode 100644 index 000000000..235d90edd --- /dev/null +++ b/src/main/java/codechicken/nei/util/ItemStackFilterParser.java @@ -0,0 +1,203 @@ +package codechicken.nei.util; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.IntPredicate; +import java.util.function.Predicate; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; +import java.util.stream.IntStream; + +import net.minecraft.item.Item; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.oredict.OreDictionary; + +import codechicken.nei.ItemList.AllMultiItemFilter; +import codechicken.nei.ItemList.AnyMultiItemFilter; +import codechicken.nei.ItemList.NegatedItemFilter; +import codechicken.nei.api.ItemFilter; +import cpw.mods.fml.common.registry.FMLControlledNamespacedRegistry; +import cpw.mods.fml.common.registry.GameData; + +/** + * @formatter:off + * + * parts: + * modname:itemid - identify + * $orename - ore dictionary + * tag.color=red - tag + * 0 or 0-12 - damage + * + * modifiers: + * ! - logical not. exclude items that match the following expression (!minecraft:portal) + * r/.../ - standard java regex (r/^m\w{6}ft$/ = minecraft) + * , - logical or in token (minecraft:potion 16384-16462,!16386) + * | - logical or multi-item search (wrench|hammer) + * + * + * example: minecraft:potion 16384-16462,!16386 | $oreiron | tag.color=red + */ +public class ItemStackFilterParser { + + private ItemStackFilterParser() {} + + public static ItemFilter parse(String filterText) { + final List searchTokens = new ArrayList<>(); + filterText = filterText.trim(); + + if (!filterText.isEmpty()) { + for (String part : filterText.split("\\s*\\|\\s*")) { + AllMultiItemFilter filter = parsePart(part); + if (!filter.filters.isEmpty()) { + searchTokens.add(filter); + } + } + } + + if (searchTokens.isEmpty()) { + return null; + } else if (searchTokens.size() == 1) { + return searchTokens.get(0); + } else { + return new AnyMultiItemFilter(searchTokens); + } + } + + private static AllMultiItemFilter parsePart(String part) { + final AllMultiItemFilter searchTokens = new AllMultiItemFilter(); + + for (String token : part.split("\\s+")) { + ItemFilter ruleFilter = parseRules(token); + + if (ruleFilter != null) { + searchTokens.filters.add(ruleFilter); + } + } + + return searchTokens; + } + + protected static ItemFilter parseRules(String token) { + final AnyMultiItemFilter orFilter = new AnyMultiItemFilter(); + final AnyMultiItemFilter orNotFilter = new AnyMultiItemFilter(); + final AllMultiItemFilter ruleFilter = new AllMultiItemFilter(); + + for (String rule : token.split(",")) { + boolean ignore = rule.startsWith("!"); + ItemFilter filter = null; + + if (ignore) { + rule = rule.substring(1); + } + + if (rule.startsWith("$")) { + filter = getOreDictFilter(rule.substring(1)); + } else if (rule.startsWith("tag.")) { + filter = getTagFilter(rule.substring(4)); + } else if (Pattern.matches("^\\d+(-\\d+)?$", rule)) { + filter = getDamageFilter(rule); + } else { + filter = getStringIdentifierFilter(rule); + } + + if (filter == null) { + continue; + } + + if (ignore) { + orNotFilter.filters.add(filter); + } else { + orFilter.filters.add(filter); + } + } + + if (!orFilter.filters.isEmpty()) { + ruleFilter.filters.add(orFilter); + } + + if (!orNotFilter.filters.isEmpty()) { + ruleFilter.filters.add(new NegatedItemFilter(orNotFilter)); + } + + return ruleFilter.filters.isEmpty() ? null : ruleFilter; + } + + protected static Predicate getMatcher(String searchText) { + + if (searchText.length() >= 3 && searchText.startsWith("r/") && searchText.endsWith("/")) { + + try { + Pattern pattern = Pattern.compile( + searchText.substring(2, searchText.length() - 1), + Pattern.MULTILINE | Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); + return value -> pattern.matcher(value).find(); + } catch (PatternSyntaxException ignored) {} + + } else if (!searchText.isEmpty()) { + final String lowerCase = searchText.toLowerCase(); + return value -> value.toLowerCase().contains(lowerCase); + } + + return null; + } + + protected static ItemFilter getOreDictFilter(String rule) { + final Predicate matcher = getMatcher(rule); + + if (matcher == null) { + return null; + } + + return stack -> IntStream.of(OreDictionary.getOreIDs(stack)) + .anyMatch(id -> matcher.test(OreDictionary.getOreName(id))); + } + + protected static ItemFilter getTagFilter(String rule) { + final String[] parts = rule.split("=", 2); + final String[] path = parts[0].split("\\."); + final Predicate value = getMatcher(parts[1]); + + return stack -> { + Object tag = stack.getTagCompound(); + + for (int i = 0; i < path.length && tag != null; i++) { + if (tag instanceof NBTTagCompound) { + tag = ((NBTTagCompound) tag).getTag(path[i]); + } else if (tag instanceof NBTTagList) { + tag = ((NBTTagList) tag).tagList.get(Integer.parseInt(path[i])); + } else { + tag = null; + } + } + + return tag == null ? value == null : value != null && value.test(tag.toString()); + }; + } + + protected static ItemFilter getDamageFilter(String rule) { + final String[] range = rule.split("-"); + final IntPredicate matcher; + + if (range.length == 1) { + final int damage = Integer.parseInt(range[0]); + matcher = dmg -> dmg == damage; + } else { + final int damageStart = Integer.parseInt(range[0]); + final int damageEnd = Integer.parseInt(range[1]); + matcher = dmg -> dmg >= damageStart && dmg <= damageEnd; + } + + return stack -> matcher.test(stack.getItemDamage()); + } + + protected static ItemFilter getStringIdentifierFilter(String rule) { + final FMLControlledNamespacedRegistry iItemRegistry = GameData.getItemRegistry(); + final Predicate matcher = getMatcher(rule); + + return stack -> { + String name = iItemRegistry.getNameForObject(stack.getItem()); + return name != null && !name.isEmpty() && matcher.test(name); + }; + } +} diff --git a/src/main/resources/assets/nei/cfg/collapsibleitems.cfg b/src/main/resources/assets/nei/cfg/collapsibleitems.cfg index 7c315ad0e..ac7b4de2e 100644 --- a/src/main/resources/assets/nei/cfg/collapsibleitems.cfg +++ b/src/main/resources/assets/nei/cfg/collapsibleitems.cfg @@ -2,15 +2,22 @@ # # One line - one group # Item added in first valid group -# | - logical or. multi-item search (wrench|hammer) -# $ - search by ore dictionary ($ore) -# ! - logical not. exclude items that match the following expression (-@minecraft) -# r/.../ - standard java regex (@r/m\w{6}ft/ = @minecraft) -# 0 - damage filter -# 0-12 - damage range filter -# , - logical or in token # # +# parts: +# modname:itemid - identify +# $orename - ore dictionary +# tag.color=red - tag +# 0 or 0-12 - damage +# +# modifiers: +# ! - logical not. exclude items that match the following expression (!minecraft:portal) +# r/.../ - standard java regex (r/^m\w{6}ft$/ = minecraft) +# , - logical or in token (minecraft:potion 16384-16462,!16386) +# | - logical or multi-item search (wrench|hammer) +# +# example: minecraft:potion 16384-16462,!16386 | $oreiron | tag.color=red +# minecraft:spawn_egg minecraft:mob_spawner minecraft:record_ diff --git a/src/main/resources/assets/nei/guidfilters.cfg b/src/main/resources/assets/nei/cfg/guidfilters.cfg similarity index 94% rename from src/main/resources/assets/nei/guidfilters.cfg rename to src/main/resources/assets/nei/cfg/guidfilters.cfg index c94f1605c..620162b21 100644 --- a/src/main/resources/assets/nei/guidfilters.cfg +++ b/src/main/resources/assets/nei/cfg/guidfilters.cfg @@ -53,4 +53,5 @@ miscutils:particleIon,Damage miscutils:personalHealingDevice tectech:item.em.debugContainer,tag.symbols tinkersdefense:Heater Shield,tag.InfiTool -tinkersdefense:Round Shield,tag.InfiTool \ No newline at end of file +tinkersdefense:Round Shield,tag.InfiTool +miscutils:itemCustomMetaCover.miscutils.GtMachineCasings,Damage \ No newline at end of file diff --git a/src/main/resources/assets/nei/cfg/hiddenitems.cfg b/src/main/resources/assets/nei/cfg/hiddenitems.cfg new file mode 100644 index 000000000..bb51d7a31 --- /dev/null +++ b/src/main/resources/assets/nei/cfg/hiddenitems.cfg @@ -0,0 +1,24 @@ +# Hidden Items Filters +# +# parts: +# modname:itemid - identify +# $orename - ore dictionary +# tag.color=red - tag +# 0 or 0-12 - damage +# +# modifiers: +# ! - logical not. exclude items that match the following expression (!minecraft:portal) +# r/.../ - standard java regex (r/^m\w{6}ft$/ = minecraft) +# , - logical or in token (minecraft:potion 16384-16462,!16386) +# | - logical or multi-item search (wrench|hammer) +# +# example: minecraft:potion 16384-16462,!16386 | $oreiron | tag.color=red +# +minecraft:portal +minecraft:end_portal +minecraft:fire +minecraft:lava +minecraft:mob_spawner +minecraft:anvil !0 +minecraft:flowing_water +minecraft:flowing_lava \ No newline at end of file diff --git a/src/main/resources/assets/nei/lang/en_US.lang b/src/main/resources/assets/nei/lang/en_US.lang index cdd722f61..20a3b04cc 100644 --- a/src/main/resources/assets/nei/lang/en_US.lang +++ b/src/main/resources/assets/nei/lang/en_US.lang @@ -190,9 +190,6 @@ nei.options.inventory.bookmarks.ignorePotionOverlap.false=No nei.options.inventory.bookmarks.worldSpecific=World Specific Bookmarks nei.options.inventory.bookmarks.worldSpecific.true=Yes nei.options.inventory.bookmarks.worldSpecific.false=No -nei.options.inventory.worldSpecificPresets=World Specific Presets -nei.options.inventory.worldSpecificPresets.true=Yes -nei.options.inventory.worldSpecificPresets.false=No nei.options.inventory.guirecipe=Recipes GUI nei.options.inventory.guirecipe.jeiStyleTabs=JEI Style Tabs nei.options.inventory.guirecipe.jeiStyleTabs.true=Yes diff --git a/src/main/resources/assets/nei/lang/ru_RU.lang b/src/main/resources/assets/nei/lang/ru_RU.lang index d7782cefa..e36108ad2 100644 --- a/src/main/resources/assets/nei/lang/ru_RU.lang +++ b/src/main/resources/assets/nei/lang/ru_RU.lang @@ -190,9 +190,6 @@ nei.options.inventory.bookmarks.ignorePotionOverlap.false=Нет nei.options.inventory.bookmarks.worldSpecific=Закладки для конкретного мира nei.options.inventory.bookmarks.worldSpecific.true=Да nei.options.inventory.bookmarks.worldSpecific.false=Нет -nei.options.inventory.worldSpecificPresets=Пресеты для конкретного мира -nei.options.inventory.worldSpecificPresets.true=Да -nei.options.inventory.worldSpecificPresets.false=Нет nei.options.inventory.guirecipe=Интерфейс рецептов nei.options.inventory.guirecipe.jeiStyleTabs=Вкладки в стиле JEI nei.options.inventory.guirecipe.jeiStyleTabs.true=Да diff --git a/src/main/resources/assets/nei/lang/zh_CN.lang b/src/main/resources/assets/nei/lang/zh_CN.lang index 4e6d21d8f..d8c84368e 100644 --- a/src/main/resources/assets/nei/lang/zh_CN.lang +++ b/src/main/resources/assets/nei/lang/zh_CN.lang @@ -131,9 +131,6 @@ nei.options.inventory=物品栏 nei.options.inventory.bookmarks.worldSpecific=书签存储位置 nei.options.inventory.bookmarks.worldSpecific.true=存档内 nei.options.inventory.bookmarks.worldSpecific.false=全局 -nei.options.inventory.worldSpecificPresets=预设存储位置 -nei.options.inventory.worldSpecificPresets.true=存档内 -nei.options.inventory.worldSpecificPresets.false=全局 nei.options.inventory.bookmarks.enabled=显示/隐藏书签页 nei.options.inventory.bookmarks.enabled.true=显示 nei.options.inventory.bookmarks.enabled.false=隐藏