Skip to content

Commit

Permalink
Fix in-game changes to blacklist and hidden ingredients
Browse files Browse the repository at this point in the history
  • Loading branch information
mezz committed Apr 16, 2018
1 parent e694844 commit b8a4506
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 91 deletions.
Expand Up @@ -2,7 +2,6 @@

import mezz.jei.api.ingredients.IIngredientHelper;
import mezz.jei.config.Config;
import mezz.jei.util.ErrorUtil;

import java.util.HashSet;
import java.util.List;
Expand All @@ -22,12 +21,11 @@ public <V> void removeIngredientFromBlacklist(V ingredient, IIngredientHelper<V>
}

public <V> boolean isIngredientBlacklisted(V ingredient, IIngredientHelper<V> ingredientHelper) {
ErrorUtil.checkNotNull(ingredient, "ingredient");

if (isIngredientBlacklistedByApi(ingredient, ingredientHelper)) {
return true;
}
return isIngredientBlacklistedByApi(ingredient, ingredientHelper) ||
Config.isIngredientOnConfigBlacklist(ingredient, ingredientHelper);
}

public <V> boolean isIngredientBlacklistedByConfig(V ingredient, IIngredientHelper<V> ingredientHelper) {
return Config.isIngredientOnConfigBlacklist(ingredient, ingredientHelper);
}

Expand Down
106 changes: 72 additions & 34 deletions src/main/java/mezz/jei/ingredients/IngredientFilter.java
Expand Up @@ -20,13 +20,13 @@
import mezz.jei.config.EditModeToggleEvent;
import mezz.jei.gui.ingredients.IIngredientListElement;
import mezz.jei.gui.overlay.IngredientListOverlay;
import mezz.jei.runtime.JeiHelpers;
import mezz.jei.runtime.JeiRuntime;
import mezz.jei.startup.PlayerJoinedWorldEvent;
import mezz.jei.suffixtree.CombinedSearchTrees;
import mezz.jei.suffixtree.GeneralizedSuffixTree;
import mezz.jei.suffixtree.ISearchTree;
import mezz.jei.util.ErrorUtil;
import mezz.jei.util.Log;
import mezz.jei.util.Translator;
import net.minecraft.util.NonNullList;
import net.minecraftforge.fml.common.ProgressManager;
Expand All @@ -38,12 +38,12 @@ public class IngredientFilter implements IIngredientFilter {
private static final Pattern QUOTE_PATTERN = Pattern.compile("\"");
private static final Pattern FILTER_SPLIT_PATTERN = Pattern.compile("(-?\".*?(?:\"|$)|\\S+)");

private final JeiHelpers helpers;
private final IngredientBlacklistInternal blacklist;
/**
* indexed list of ingredients for use with the suffix trees
* includes all elements (even hidden ones) for use when rebuilding
*/
private final List<IIngredientListElement> elementList;
private final NonNullList<IIngredientListElement> elementList;
private final GeneralizedSuffixTree searchTree;
private final TCharObjectMap<PrefixedSearchTree> prefixedSearchTrees = new TCharObjectHashMap<>();
private final IngredientFilterBackgroundBuilder backgroundBuilder;
Expand All @@ -53,9 +53,9 @@ public class IngredientFilter implements IIngredientFilter {
private String filterCached;
private List<IIngredientListElement> ingredientListCached = Collections.emptyList();

public IngredientFilter(JeiHelpers helpers) {
this.helpers = helpers;
this.elementList = new ArrayList<>();
public IngredientFilter(IngredientBlacklistInternal blacklist) {
this.blacklist = blacklist;
this.elementList = NonNullList.create();
this.searchTree = new GeneralizedSuffixTree();
createPrefixedSearchTree('@', Config::getModNameSearchMode, IIngredientListElement::getModNameStrings);
createPrefixedSearchTree('#', Config::getTooltipSearchMode, IIngredientListElement::getTooltipStrings);
Expand Down Expand Up @@ -95,14 +95,32 @@ public void addIngredients(NonNullList<IIngredientListElement> ingredients) {
ProgressManager.pop(progressBar);
}

private <V> void addIngredient(IIngredientListElement<V> element) {
V ingredient = element.getIngredient();

IngredientBlacklist ingredientBlacklist = helpers.getIngredientBlacklist();
if (ingredientBlacklist.isIngredientBlacklisted(ingredient)) {
return;
public void addIngredientsAtRuntime(NonNullList<IIngredientListElement> ingredients) {
for (IIngredientListElement<?> element : ingredients) {
List<IIngredientListElement> matchingElements = findMatchingElements(element);
if (!matchingElements.isEmpty()) {
updateHiddenStates(matchingElements);
if (Config.isDebugModeEnabled()) {
Log.get().debug("addIngredientsAtRuntime Updated ingredient: {}", getErrorInfo(element));
}
} else {
addIngredient(element);
if (Config.isDebugModeEnabled()) {
Log.get().debug("addIngredientsAtRuntime Added ingredient: {}", getErrorInfo(element));
}
}
}
filterCached = null;
}

private static <V> String getErrorInfo(IIngredientListElement<V> element) {
IIngredientHelper<V> ingredientHelper = element.getIngredientHelper();
V ingredient = element.getIngredient();
return ingredientHelper.getErrorInfo(ingredient);
}

private <V> void addIngredient(IIngredientListElement<V> element) {
updateHiddenState(element);
final int index = elementList.size();
elementList.add(element);
searchTree.put(Translator.toLowercaseWithLocale(element.getDisplayName()), index);
Expand All @@ -118,36 +136,51 @@ private <V> void addIngredient(IIngredientListElement<V> element) {
}
}

public void removeIngredients(NonNullList<IIngredientListElement> ingredients) {
public void removeIngredientsAtRuntime(NonNullList<IIngredientListElement> ingredients) {
for (IIngredientListElement<?> element : ingredients) {
removeIngredient(element);
removeIngredientAtRuntime(element);
}
filterCached = null;
}

private <V> void removeIngredient(IIngredientListElement<V> element) {
private <V> void removeIngredientAtRuntime(IIngredientListElement<V> element) {
List<IIngredientListElement> matchingElements = findMatchingElements(element);
if (matchingElements.isEmpty()) {
IIngredientHelper<V> ingredientHelper = element.getIngredientHelper();
V ingredient = element.getIngredient();
String errorInfo = ingredientHelper.getErrorInfo(ingredient);
Log.get().error("Could not find any matching ingredients to remove: {}", errorInfo);
} else if (Config.isDebugModeEnabled()) {
Log.get().debug("removeIngredientsAtRuntime Removed ingredient: {}", getErrorInfo(element));
}
for (IIngredientListElement matchingElement : matchingElements) {
matchingElement.setVisible(false);
}
}

private <V> List<IIngredientListElement> findMatchingElements(IIngredientListElement<V> element) {
final IIngredientHelper<V> ingredientHelper = element.getIngredientHelper();
final V ingredient = element.getIngredient();
final String ingredientUid = ingredientHelper.getUniqueId(ingredient);
//noinspection unchecked
@SuppressWarnings("unchecked")
final Class<? extends V> ingredientClass = (Class<? extends V>) ingredient.getClass();

final List<IIngredientListElement> matchingElements = new ArrayList<>();
final TIntSet matchingIndexes = searchTree.search(Translator.toLowercaseWithLocale(element.getDisplayName()));
final TIntIterator iterator = matchingIndexes.iterator();
while (iterator.hasNext()) {
int index = iterator.next();
IIngredientListElement matchingElement = this.elementList.get(index);
if (matchingElement != null) {
Object matchingIngredient = matchingElement.getIngredient();
if (ingredientClass.isInstance(matchingIngredient)) {
V castMatchingIngredient = ingredientClass.cast(matchingIngredient);
String matchingUid = ingredientHelper.getUniqueId(castMatchingIngredient);
if (ingredientUid.equals(matchingUid)) {
this.elementList.set(index, null);
}
Object matchingIngredient = matchingElement.getIngredient();
if (ingredientClass.isInstance(matchingIngredient)) {
V castMatchingIngredient = ingredientClass.cast(matchingIngredient);
String matchingUid = ingredientHelper.getUniqueId(castMatchingIngredient);
if (ingredientUid.equals(matchingUid)) {
matchingElements.add(matchingElement);
}
}
}
return matchingElements;
}

public void modesChanged() {
Expand All @@ -169,19 +202,24 @@ public void onPlayerJoinedWorldEvent(PlayerJoinedWorldEvent event) {
}

private void updateHidden() {
for (IIngredientListElement<?> element : elementList) {
if (element != null) {
updateHiddenState(element);
}
updateHiddenStates(elementList);
}

private void updateHiddenStates(Iterable<IIngredientListElement> elements) {
for (IIngredientListElement<?> element : elements) {
updateHiddenState(element);
}
}

private static <V> void updateHiddenState(IIngredientListElement<V> element) {
private <V> void updateHiddenState(IIngredientListElement<V> element) {
V ingredient = element.getIngredient();
IIngredientHelper<V> ingredientHelper = element.getIngredientHelper();
boolean visible = !Config.isIngredientOnConfigBlacklist(ingredient, ingredientHelper) &&
ingredientHelper.isIngredientOnServer(ingredient);
element.setVisible(visible);
if (blacklist.isIngredientBlacklistedByApi(ingredient, ingredientHelper) || !ingredientHelper.isIngredientOnServer(ingredient)) {
element.setVisible(false);
} else {
boolean visible = Config.isEditModeEnabled() || !blacklist.isIngredientBlacklistedByConfig(ingredient, ingredientHelper);
element.setVisible(visible);
}
}

public List<IIngredientListElement> getIngredientList() {
Expand Down Expand Up @@ -243,7 +281,7 @@ private List<IIngredientListElement> getIngredientListUncached(String filterText

if (matches == null) {
for (IIngredientListElement element : elementList) {
if (element != null && (element.isVisible() || Config.isEditModeEnabled())) {
if (element.isVisible()) {
matchingIngredients.add(element);
}
}
Expand All @@ -252,7 +290,7 @@ private List<IIngredientListElement> getIngredientListUncached(String filterText
Arrays.sort(matchesList);
for (Integer match : matchesList) {
IIngredientListElement<?> element = elementList.get(match);
if (element != null && (element.isVisible() || Config.isEditModeEnabled())) {
if (element.isVisible()) {
matchingIngredients.add(element);
}
}
Expand Down
Expand Up @@ -5,19 +5,19 @@
import mezz.jei.gui.ingredients.IIngredientListElement;
import mezz.jei.suffixtree.GeneralizedSuffixTree;
import net.minecraft.client.Minecraft;
import net.minecraft.util.NonNullList;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import net.minecraftforge.fml.relauncher.Side;

import java.util.Collection;
import java.util.List;

public class IngredientFilterBackgroundBuilder {
private final TCharObjectMap<PrefixedSearchTree> prefixedSearchTrees;
private final List<IIngredientListElement> elementList;
private final NonNullList<IIngredientListElement> elementList;

public IngredientFilterBackgroundBuilder(TCharObjectMap<PrefixedSearchTree> prefixedSearchTrees, List<IIngredientListElement> elementList) {
public IngredientFilterBackgroundBuilder(TCharObjectMap<PrefixedSearchTree> prefixedSearchTrees, NonNullList<IIngredientListElement> elementList) {
this.prefixedSearchTrees = prefixedSearchTrees;
this.elementList = elementList;
}
Expand Down Expand Up @@ -49,14 +49,12 @@ private boolean run(final int timeoutMs) {
GeneralizedSuffixTree tree = prefixedTree.getTree();
for (int i = tree.getHighestIndex() + 1; i < this.elementList.size(); i++) {
IIngredientListElement element = elementList.get(i);
if (element != null) {
Collection<String> strings = stringsGetter.getStrings(element);
if (strings.isEmpty()) {
tree.put("", i);
} else {
for (String string : strings) {
tree.put(string, i);
}
Collection<String> strings = stringsGetter.getStrings(element);
if (strings.isEmpty()) {
tree.put("", i);
} else {
for (String string : strings) {
tree.put(string, i);
}
}
if (System.currentTimeMillis() - startTime >= timeoutMs) {
Expand Down
37 changes: 10 additions & 27 deletions src/main/java/mezz/jei/ingredients/IngredientRegistry.java
Expand Up @@ -7,7 +7,6 @@
import mezz.jei.api.ingredients.IIngredientRegistry;
import mezz.jei.api.ingredients.IIngredientRenderer;
import mezz.jei.gui.ingredients.IIngredientListElement;
import mezz.jei.runtime.JeiHelpers;
import mezz.jei.startup.IModIdHelper;
import mezz.jei.util.ErrorUtil;
import mezz.jei.util.IngredientSet;
Expand All @@ -26,7 +25,6 @@

public class IngredientRegistry implements IIngredientRegistry {
private final IModIdHelper modIdHelper;
private final IngredientBlacklistInternal ingredientBlacklistInternal;
private final Map<Class, IngredientSet> ingredientsMap;
private final ImmutableMap<Class, IIngredientHelper> ingredientHelperMap;
private final ImmutableMap<Class, IIngredientRenderer> ingredientRendererMap;
Expand All @@ -35,13 +33,11 @@ public class IngredientRegistry implements IIngredientRegistry {

public IngredientRegistry(
IModIdHelper modIdHelper,
IngredientBlacklistInternal ingredientBlacklistInternal,
Map<Class, IngredientSet> ingredientsMap,
ImmutableMap<Class, IIngredientHelper> ingredientHelperMap,
ImmutableMap<Class, IIngredientRenderer> ingredientRendererMap
) {
this.modIdHelper = modIdHelper;
this.ingredientBlacklistInternal = ingredientBlacklistInternal;
this.ingredientsMap = ingredientsMap;
this.ingredientHelperMap = ingredientHelperMap;
this.ingredientRendererMap = ingredientRendererMap;
Expand Down Expand Up @@ -167,72 +163,59 @@ public List<ItemStack> getPotionIngredients() {

@Override
public <V> void addIngredientsAtRuntime(Class<V> ingredientClass, List<V> ingredients) {
ErrorUtil.assertMainThread();
addIngredientsAtRuntime(ingredientClass, ingredients, Internal.getIngredientFilter());
}

@Override
public <V> void addIngredientsAtRuntime(Class<V> ingredientClass, Collection<V> ingredients) {
ErrorUtil.assertMainThread();
addIngredientsAtRuntime(ingredientClass, ingredients, Internal.getIngredientFilter());
}

public <V> void addIngredientsAtRuntime(Class<V> ingredientClass, Collection<V> ingredients, IngredientFilter ingredientFilter) {
ErrorUtil.assertMainThread();
ErrorUtil.checkNotNull(ingredientClass, "ingredientClass");
ErrorUtil.checkNotEmpty(ingredients, "ingredients");

Log.get().info("Ingredients are being added at runtime: {} {}", ingredients.size(), ingredientClass.getName());

IIngredientHelper<V> ingredientHelper = getIngredientHelper(ingredientClass);
//noinspection unchecked
Set<V> set = ingredientsMap.computeIfAbsent(ingredientClass, k -> IngredientSet.create(ingredientClass, ingredientHelper));
List<V> newIngredients = new ArrayList<>(ingredients.size());
for (V ingredient : ingredients) {
if (set.add(ingredient)) {
newIngredients.add(ingredient);
}
set.add(ingredient);
if (ingredient instanceof ItemStack) {
getStackProperties((ItemStack) ingredient);
}
}

if (!newIngredients.isEmpty()) {
NonNullList<IIngredientListElement> ingredientListElements = IngredientListElementFactory.createList(this, ingredientClass, newIngredients, modIdHelper);
ingredientFilter.addIngredients(ingredientListElements);

for (V ingredient : newIngredients) {
ingredientBlacklistInternal.removeIngredientFromBlacklist(ingredient, ingredientHelper);
}
}
NonNullList<IIngredientListElement> ingredientListElements = IngredientListElementFactory.createList(this, ingredientClass, ingredients, modIdHelper);
ingredientFilter.addIngredientsAtRuntime(ingredientListElements);
}

@Override
public <V> void removeIngredientsAtRuntime(Class<V> ingredientClass, List<V> ingredients) {
ErrorUtil.assertMainThread();
removeIngredientsAtRuntime(ingredientClass, ingredients, Internal.getIngredientFilter());
}

@Override
public <V> void removeIngredientsAtRuntime(Class<V> ingredientClass, Collection<V> ingredients) {
ErrorUtil.assertMainThread();
removeIngredientsAtRuntime(ingredientClass, ingredients, Internal.getIngredientFilter());
}

public <V> void removeIngredientsAtRuntime(Class<V> ingredientClass, Collection<V> ingredients, IngredientFilter ingredientFilter) {
ErrorUtil.assertMainThread();
ErrorUtil.checkNotNull(ingredientClass, "ingredientClass");
ErrorUtil.checkNotEmpty(ingredients, "ingredients");

Log.get().info("Ingredients are being removed at runtime: {} {}", ingredients.size(), ingredientClass.getName());

//noinspection unchecked
IngredientSet<V> set = ingredientsMap.get(ingredientClass);
if (set != null) {
set.removeAll(ingredients);
}

NonNullList<IIngredientListElement> ingredientListElements = IngredientListElementFactory.createList(this, ingredientClass, ingredients, modIdHelper);
ingredientFilter.removeIngredients(ingredientListElements);

IIngredientHelper<V> ingredientHelper = getIngredientHelper(ingredientClass);
// blacklist items so they stay hidden after a reload
for (V ingredient : ingredients) {
ingredientBlacklistInternal.addIngredientToBlacklist(ingredient, ingredientHelper);
}
ingredientFilter.removeIngredientsAtRuntime(ingredientListElements);
}
}
@@ -1,13 +1,14 @@
package mezz.jei.plugins.jei.ingredients;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public final class DebugIngredientListFactory {
private DebugIngredientListFactory() {
}

public static List<DebugIngredient> create() {
public static Collection<DebugIngredient> create() {
List<DebugIngredient> ingredients = new ArrayList<>();
for (int i = 0; i < 10; i++) {
DebugIngredient debugIngredient = new DebugIngredient(i);
Expand Down

0 comments on commit b8a4506

Please sign in to comment.