2014-04-29 10:54:20 +10:00
|
|
|
package codechicken.nei;
|
|
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
2025-09-04 16:59:51 +03:00
|
|
|
import java.util.Arrays;
|
2025-01-04 15:03:53 +01:00
|
|
|
import java.util.Comparator;
|
2024-07-26 18:44:54 +03:00
|
|
|
import java.util.HashMap;
|
2014-04-29 10:54:20 +10:00
|
|
|
import java.util.HashSet;
|
2014-06-29 20:31:37 +10:00
|
|
|
import java.util.LinkedList;
|
2014-04-29 10:54:20 +10:00
|
|
|
import java.util.List;
|
2025-04-24 18:48:40 +03:00
|
|
|
import java.util.Map;
|
2020-01-01 11:14:02 -08:00
|
|
|
import java.util.concurrent.ExecutionException;
|
|
|
|
|
import java.util.concurrent.ForkJoinPool;
|
2024-10-04 21:46:29 +02:00
|
|
|
import java.util.concurrent.ForkJoinWorkerThread;
|
2025-09-04 16:59:51 +03:00
|
|
|
import java.util.regex.Pattern;
|
2021-01-17 12:03:33 -08:00
|
|
|
import java.util.stream.Collectors;
|
2025-01-16 22:12:26 +02:00
|
|
|
import java.util.stream.StreamSupport;
|
2023-01-28 17:55:51 -08:00
|
|
|
|
2024-06-27 18:03:50 +03:00
|
|
|
import net.minecraft.client.Minecraft;
|
2023-09-25 00:35:24 +02:00
|
|
|
import net.minecraft.item.Item;
|
|
|
|
|
import net.minecraft.item.ItemStack;
|
2025-09-04 16:59:51 +03:00
|
|
|
import net.minecraft.util.EnumChatFormatting;
|
2023-09-25 00:35:24 +02:00
|
|
|
import net.minecraft.util.IIcon;
|
2025-10-02 07:15:28 +02:00
|
|
|
import net.minecraftforge.fluids.IFluidContainerItem;
|
2023-09-25 00:35:24 +02:00
|
|
|
|
|
|
|
|
import com.google.common.collect.ArrayListMultimap;
|
|
|
|
|
import com.google.common.collect.ListMultimap;
|
|
|
|
|
|
|
|
|
|
import codechicken.nei.ThreadOperationTimer.TimeoutException;
|
|
|
|
|
import codechicken.nei.api.ItemFilter;
|
|
|
|
|
import codechicken.nei.api.ItemFilter.ItemFilterProvider;
|
|
|
|
|
import codechicken.nei.api.ItemInfo;
|
2025-08-16 07:24:40 -04:00
|
|
|
import codechicken.nei.recipe.InformationHandler;
|
2025-01-16 22:12:26 +02:00
|
|
|
import codechicken.nei.search.TooltipFilter;
|
2025-09-17 15:42:35 +03:00
|
|
|
import codechicken.nei.util.ItemUntranslator;
|
2025-10-02 07:15:28 +02:00
|
|
|
import cpw.mods.fml.common.FMLLog;
|
2023-09-25 00:35:24 +02:00
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
public class ItemList {
|
2023-01-28 17:55:51 -08:00
|
|
|
|
2014-06-29 20:31:37 +10:00
|
|
|
/**
|
|
|
|
|
* Fields are replaced atomically and contents never modified.
|
|
|
|
|
*/
|
2022-06-24 12:32:13 +01:00
|
|
|
public static volatile List<ItemStack> items = new ArrayList<>();
|
2014-06-29 20:31:37 +10:00
|
|
|
/**
|
|
|
|
|
* Fields are replaced atomically and contents never modified.
|
|
|
|
|
*/
|
2014-07-25 14:45:45 +10:00
|
|
|
public static volatile ListMultimap<Item, ItemStack> itemMap = ArrayListMultimap.create();
|
2014-06-29 20:31:37 +10:00
|
|
|
/**
|
|
|
|
|
* Updates to this should be synchronised on this
|
|
|
|
|
*/
|
2019-12-30 20:19:16 -08:00
|
|
|
public static final List<ItemFilterProvider> itemFilterers = new LinkedList<>();
|
|
|
|
|
public static final List<ItemsLoadedCallback> loadCallbacks = new LinkedList<>();
|
2014-04-29 10:54:20 +10:00
|
|
|
|
2019-12-30 20:19:16 -08:00
|
|
|
private static final HashSet<Item> erroredItems = new HashSet<>();
|
|
|
|
|
private static final HashSet<String> stackTraces = new HashSet<>();
|
2025-04-24 18:48:40 +03:00
|
|
|
private static Map<ItemStack, Integer> ordering = new HashMap<>();
|
2022-08-31 17:43:22 +09:00
|
|
|
/**
|
|
|
|
|
* Unlike {@link LayoutManager#itemsLoaded}, this indicates whether item loading is actually finished or not.
|
|
|
|
|
*/
|
|
|
|
|
public static boolean loadFinished;
|
2014-04-29 10:54:20 +10:00
|
|
|
|
2025-09-04 16:59:51 +03:00
|
|
|
public static class EverythingItemFilter implements ItemFilter {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean matches(ItemStack item) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static class NothingItemFilter implements ItemFilter {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean matches(ItemStack item) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static class NegatedItemFilter implements ItemFilter {
|
|
|
|
|
|
|
|
|
|
public ItemFilter filter;
|
|
|
|
|
|
|
|
|
|
public NegatedItemFilter(ItemFilter filter) {
|
|
|
|
|
this.filter = filter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean matches(ItemStack item) {
|
|
|
|
|
return this.filter == null || !this.filter.matches(item);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static class PatternItemFilter implements ItemFilter {
|
|
|
|
|
|
|
|
|
|
public Pattern pattern;
|
|
|
|
|
|
|
|
|
|
public PatternItemFilter(Pattern pattern) {
|
|
|
|
|
this.pattern = pattern;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean matches(ItemStack item) {
|
|
|
|
|
String displayName = EnumChatFormatting.getTextWithoutFormattingCodes(item.getDisplayName());
|
|
|
|
|
|
|
|
|
|
if (displayName != null && !displayName.isEmpty() && this.pattern.matcher(displayName).find()) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-17 15:42:35 +03:00
|
|
|
displayName = ItemUntranslator.getInstance().getItemStackDisplayName(item);
|
|
|
|
|
|
|
|
|
|
if (!displayName.isEmpty() && this.pattern.matcher(displayName).find()) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-04 16:59:51 +03:00
|
|
|
if (item.hasDisplayName()) {
|
|
|
|
|
displayName = EnumChatFormatting
|
|
|
|
|
.getTextWithoutFormattingCodes(item.getItem().getItemStackDisplayName(item));
|
|
|
|
|
|
|
|
|
|
return displayName != null && !displayName.isEmpty() && this.pattern.matcher(displayName).find();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static class AllMultiItemFilter implements ItemFilter {
|
|
|
|
|
|
|
|
|
|
public List<ItemFilter> filters;
|
|
|
|
|
|
|
|
|
|
public AllMultiItemFilter(List<ItemFilter> filters) {
|
|
|
|
|
this.filters = filters;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public AllMultiItemFilter(ItemFilter... filters) {
|
|
|
|
|
this(new LinkedList<>(Arrays.asList(filters)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public AllMultiItemFilter() {
|
|
|
|
|
this(new LinkedList<>());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean matches(ItemStack item) {
|
|
|
|
|
for (ItemFilter filter : filters) try {
|
|
|
|
|
if (filter != null && !filter.matches(item)) return false;
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
NEIClientConfig.logger
|
|
|
|
|
.error("Exception filtering " + item + " with " + filter + " (" + e.getMessage() + ")", e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static class AnyMultiItemFilter implements ItemFilter {
|
|
|
|
|
|
|
|
|
|
public List<ItemFilter> filters;
|
|
|
|
|
|
|
|
|
|
public AnyMultiItemFilter(List<ItemFilter> filters) {
|
|
|
|
|
this.filters = filters;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public AnyMultiItemFilter() {
|
|
|
|
|
this(new LinkedList<>());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean matches(ItemStack item) {
|
|
|
|
|
for (ItemFilter filter : filters) try {
|
|
|
|
|
if (filter != null && filter.matches(item)) return true;
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
NEIClientConfig.logger
|
|
|
|
|
.error("Exception filtering " + item + " with " + filter + " (" + e.getMessage() + ")", e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
public static interface ItemsLoadedCallback {
|
2023-01-28 17:55:51 -08:00
|
|
|
|
2014-06-29 20:31:37 +10:00
|
|
|
public void itemsLoaded();
|
2014-04-29 10:54:20 +10:00
|
|
|
}
|
|
|
|
|
|
2014-12-09 13:42:14 +10:00
|
|
|
public static boolean itemMatchesAll(ItemStack item, List<ItemFilter> filters) {
|
2022-06-24 12:32:13 +01:00
|
|
|
for (ItemFilter filter : filters) {
|
2014-12-09 13:42:14 +10:00
|
|
|
try {
|
2024-08-29 23:14:52 +03:00
|
|
|
if (filter != null && !filter.matches(item)) return false;
|
2014-12-09 13:42:14 +10:00
|
|
|
} catch (Exception e) {
|
2024-11-17 17:31:10 +02:00
|
|
|
NEIClientConfig.logger
|
|
|
|
|
.error("Exception filtering " + item + " with " + filter + " (" + e.getMessage() + ")", e);
|
2014-12-09 13:42:14 +10:00
|
|
|
}
|
|
|
|
|
}
|
2014-04-29 10:54:20 +10:00
|
|
|
|
2014-06-29 20:31:37 +10:00
|
|
|
return true;
|
2014-04-29 10:54:20 +10:00
|
|
|
}
|
|
|
|
|
|
2014-12-14 17:10:00 +10:00
|
|
|
/**
|
|
|
|
|
* @deprecated use getItemListFilter().matches(item)
|
|
|
|
|
*/
|
|
|
|
|
@Deprecated
|
2014-06-29 20:31:37 +10:00
|
|
|
public static boolean itemMatches(ItemStack item) {
|
2014-12-14 17:10:00 +10:00
|
|
|
return getItemListFilter().matches(item);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static ItemFilter getItemListFilter() {
|
|
|
|
|
return new AllMultiItemFilter(getItemFilters());
|
2014-04-29 10:54:20 +10:00
|
|
|
}
|
|
|
|
|
|
2014-06-29 20:31:37 +10:00
|
|
|
public static List<ItemFilter> getItemFilters() {
|
2019-12-30 20:19:16 -08:00
|
|
|
LinkedList<ItemFilter> filters = new LinkedList<>();
|
2014-06-29 20:31:37 +10:00
|
|
|
synchronized (itemFilterers) {
|
2024-06-27 18:03:50 +03:00
|
|
|
for (ItemFilterProvider p : itemFilterers) {
|
|
|
|
|
filters.add(p.getFilter());
|
|
|
|
|
}
|
2014-04-29 10:54:20 +10:00
|
|
|
}
|
2014-06-29 20:31:37 +10:00
|
|
|
return filters;
|
2014-04-29 10:54:20 +10:00
|
|
|
}
|
|
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
public static final RestartableTask loadItems = new RestartableTask("NEI Item Loading") {
|
2023-01-28 17:55:51 -08:00
|
|
|
|
2014-06-29 20:31:37 +10:00
|
|
|
private void damageSearch(Item item, List<ItemStack> permutations) {
|
2019-12-30 20:19:16 -08:00
|
|
|
HashSet<String> damageIconSet = new HashSet<>();
|
2014-06-29 20:31:37 +10:00
|
|
|
for (int damage = 0; damage < 16; damage++) try {
|
|
|
|
|
ItemStack itemstack = new ItemStack(item, 1, damage);
|
|
|
|
|
IIcon icon = item.getIconIndex(itemstack);
|
2024-06-27 18:03:50 +03:00
|
|
|
String name = getTooltip(itemstack);
|
2014-06-29 20:31:37 +10:00
|
|
|
String s = name + "@" + (icon == null ? 0 : icon.hashCode());
|
2025-04-24 18:48:40 +03:00
|
|
|
if (damageIconSet.add(s)) {
|
2014-06-29 20:31:37 +10:00
|
|
|
permutations.add(itemstack);
|
|
|
|
|
}
|
2022-06-24 12:32:13 +01:00
|
|
|
} catch (TimeoutException t) {
|
2023-01-28 17:55:51 -08:00
|
|
|
throw t;
|
2022-06-24 12:32:13 +01:00
|
|
|
} catch (Throwable t) {
|
|
|
|
|
NEIServerUtils.logOnce(
|
2023-01-28 17:55:51 -08:00
|
|
|
t,
|
2022-06-24 12:32:13 +01:00
|
|
|
stackTraces,
|
|
|
|
|
"Ommiting " + item + ":" + damage + " " + item.getClass().getSimpleName(),
|
|
|
|
|
item.toString());
|
2023-01-28 17:55:51 -08:00
|
|
|
}
|
2014-04-29 10:54:20 +10:00
|
|
|
}
|
|
|
|
|
|
2024-06-27 18:03:50 +03:00
|
|
|
private String getTooltip(ItemStack stack) {
|
|
|
|
|
try {
|
2024-08-29 23:14:52 +03:00
|
|
|
return String.join("\n", stack.getTooltip(Minecraft.getMinecraft().thePlayer, false));
|
2024-06-27 18:03:50 +03:00
|
|
|
} catch (Throwable ignored) {}
|
|
|
|
|
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-26 18:44:54 +03:00
|
|
|
private void updateOrdering(List<ItemStack> items) {
|
2025-04-24 18:48:40 +03:00
|
|
|
final Map<ItemStack, Integer> newOrdering = new HashMap<>();
|
2024-07-26 18:44:54 +03:00
|
|
|
ItemSorter.sort(items);
|
|
|
|
|
|
2024-12-05 21:25:17 +02:00
|
|
|
if (!CollapsibleItems.isEmpty()) {
|
2025-04-24 18:48:40 +03:00
|
|
|
final HashMap<Integer, Integer> groups = new HashMap<>();
|
2024-07-26 18:44:54 +03:00
|
|
|
int orderIndex = 0;
|
|
|
|
|
|
|
|
|
|
for (ItemStack stack : items) {
|
2024-12-05 21:25:17 +02:00
|
|
|
final int groupIndex = CollapsibleItems.getGroupIndex(stack);
|
2024-07-26 18:44:54 +03:00
|
|
|
|
|
|
|
|
if (groupIndex == -1) {
|
2025-01-04 15:03:53 +01:00
|
|
|
newOrdering.put(stack, orderIndex++);
|
2024-07-26 18:44:54 +03:00
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
if (!groups.containsKey(groupIndex)) {
|
|
|
|
|
groups.put(groupIndex, orderIndex++);
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-04 15:03:53 +01:00
|
|
|
newOrdering.put(stack, groups.get(groupIndex));
|
2024-07-26 18:44:54 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
int orderIndex = 0;
|
|
|
|
|
|
|
|
|
|
for (ItemStack stack : items) {
|
2025-01-04 15:03:53 +01:00
|
|
|
newOrdering.put(stack, orderIndex++);
|
2024-07-26 18:44:54 +03:00
|
|
|
}
|
|
|
|
|
}
|
2025-01-04 15:03:53 +01:00
|
|
|
|
|
|
|
|
ItemList.ordering = newOrdering;
|
2024-07-26 18:44:54 +03:00
|
|
|
}
|
|
|
|
|
|
2025-01-16 22:12:26 +02:00
|
|
|
private List<ItemStack> getPermutations(Item item) {
|
|
|
|
|
final List<ItemStack> permutations = new LinkedList<>(ItemInfo.itemOverrides.get(item));
|
|
|
|
|
|
|
|
|
|
if (permutations.isEmpty()) {
|
|
|
|
|
item.getSubItems(item, null, permutations);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (permutations.isEmpty()) {
|
|
|
|
|
damageSearch(item, permutations);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
permutations.addAll(ItemInfo.itemVariants.get(item));
|
|
|
|
|
|
|
|
|
|
return permutations.stream()
|
|
|
|
|
.filter(
|
|
|
|
|
stack -> stack.getItem() != null && stack.getItem().delegate.name() != null
|
|
|
|
|
&& !ItemInfo.isHidden(stack))
|
2025-01-25 21:16:28 +02:00
|
|
|
.collect(Collectors.toList());
|
2025-01-16 22:12:26 +02:00
|
|
|
}
|
|
|
|
|
|
2025-10-02 07:15:28 +02:00
|
|
|
private void runChecked(ItemStack stack, Runnable action, String reason) {
|
|
|
|
|
int hashOld = 0;
|
|
|
|
|
if (stack.hasTagCompound()) {
|
|
|
|
|
hashOld = stack.stackTagCompound.hashCode();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
action.run();
|
|
|
|
|
|
|
|
|
|
if (stack.hasTagCompound() && hashOld != stack.stackTagCompound.hashCode()) {
|
|
|
|
|
FMLLog.warning("NEI: Forced tag update with reason (" + reason + ") for " + stack);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void forceTagCompoundInitialization(ItemStack stack) {
|
|
|
|
|
Item item = stack.getItem();
|
|
|
|
|
if (item == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (item instanceof IFluidContainerItem) {
|
|
|
|
|
IFluidContainerItem fluidItem = (IFluidContainerItem) item;
|
|
|
|
|
runChecked(stack, () -> fluidItem.getFluid(stack), "getFluid");
|
|
|
|
|
}
|
|
|
|
|
runChecked(stack, () -> item.isDamaged(stack), "isDamaged");
|
|
|
|
|
runChecked(stack, () -> item.getDamage(stack), "getDamage");
|
|
|
|
|
runChecked(stack, () -> item.showDurabilityBar(stack), "showDurabilityBar");
|
|
|
|
|
runChecked(stack, () -> item.getAttributeModifiers(stack), "getAttributeModifiers");
|
|
|
|
|
runChecked(stack, () -> item.getDurabilityForDisplay(stack), "getDurabilityForDisplay");
|
|
|
|
|
runChecked(stack, () -> item.getItemStackLimit(stack), "getItemStackLimit");
|
|
|
|
|
runChecked(stack, () -> item.getToolClasses(stack), "getToolClasses");
|
|
|
|
|
runChecked(stack, () -> item.getUnlocalizedNameInefficiently(stack), "getUnlocalizedNameInefficiently");
|
|
|
|
|
runChecked(stack, () -> item.hasEffect(stack), "hasEffect");
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* unused... for now runChecked(stack, () -> GameRegistry.getFuelValue(stack), "getFuelValue");
|
|
|
|
|
* runChecked(stack, () -> item.getUnlocalizedName(stack), "getUnlocalizedName"); runChecked(stack, () ->
|
|
|
|
|
* item.doesContainerItemLeaveCraftingGrid(stack), "doesContainerItemLeaveCraftingGrid"); runChecked(stack,
|
|
|
|
|
* () -> item.getItemUseAction(stack), "getItemUseAction"); runChecked(stack, () ->
|
|
|
|
|
* item.getMaxItemUseDuration(stack), "getMaxItemUseDuration"); runChecked(stack, () ->
|
|
|
|
|
* item.getPotionEffect(stack), "getPotionEffect"); runChecked(stack, () -> item.isPotionIngredient(stack),
|
|
|
|
|
* "isPotionIngredient"); runChecked(stack, () -> item.getRarity(stack), "getRarity"); runChecked(stack, ()
|
|
|
|
|
* -> item.hasCustomEntity(stack), "hasCustomEntity"); runChecked(stack, () ->
|
|
|
|
|
* item.getSmeltingExperience(stack), "getSmeltingExperience"); runChecked(stack, () ->
|
|
|
|
|
* item.getMaxDamage(stack), "getMaxDamage"); runChecked(stack, () -> item.getDamage(stack), "getDamage");
|
|
|
|
|
* runChecked(stack, stack::isItemDamaged, "isItemDamaged"); runChecked(stack, () -> item.hasEffect(stack,
|
|
|
|
|
* 0), "hasEffect"); runChecked(stack, () -> item.getItemEnchantability(stack), "getItemEnchantability");
|
|
|
|
|
* runChecked(stack, () -> item.isBeaconPayment(stack), "isBeaconPayment"); runChecked(stack, () ->
|
|
|
|
|
* item.getDamage(stack), "getDamage"); runChecked(stack, () -> item.getDamage(stack), "getDamage");
|
|
|
|
|
* runChecked(stack, () -> item.getDamage(stack), "getDamage");
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-16 07:24:40 -04:00
|
|
|
// Generate itemlist, permutations, orders, collapsibleitems, and informationhandler stacks
|
2014-04-29 10:54:20 +10:00
|
|
|
@Override
|
2021-04-10 15:32:59 -07:00
|
|
|
@SuppressWarnings("unchecked")
|
2014-07-23 21:03:03 +10:00
|
|
|
public void execute() {
|
2025-08-16 03:38:24 +03:00
|
|
|
if (!NEIClientConfig.isEnabled() || NEIClientUtils.mc().thePlayer == null) return;
|
2025-01-16 22:12:26 +02:00
|
|
|
|
2021-10-16 06:07:25 +02:00
|
|
|
ThreadOperationTimer timer = getTimer(NEIClientConfig.getItemLoadingTimeout());
|
2024-08-29 23:14:52 +03:00
|
|
|
LayoutManager.itemsLoaded = true;
|
2022-08-31 17:43:22 +09:00
|
|
|
loadFinished = false;
|
2014-04-29 10:54:20 +10:00
|
|
|
|
2025-01-16 22:12:26 +02:00
|
|
|
SearchField.searchParser.clearCache();
|
|
|
|
|
ItemSorter.instance.ordering.clear();
|
|
|
|
|
CollapsibleItems.clearCache();
|
|
|
|
|
TooltipFilter.clearCache();
|
2025-08-16 07:24:40 -04:00
|
|
|
InformationHandler.clearCache();
|
2025-01-16 22:12:26 +02:00
|
|
|
|
|
|
|
|
List<ItemStack> items = new ArrayList<>();
|
2014-07-23 21:03:03 +10:00
|
|
|
ListMultimap<Item, ItemStack> itemMap = ArrayListMultimap.create();
|
2025-01-16 22:12:26 +02:00
|
|
|
ItemStackSet unique = new ItemStackSet();
|
2014-04-29 10:54:20 +10:00
|
|
|
|
2025-01-16 22:12:26 +02:00
|
|
|
StreamSupport.stream(((Iterable<Item>) Item.itemRegistry).spliterator(), true).forEach(item -> {
|
|
|
|
|
if (item == null || item.delegate.name() == null || erroredItems.contains(item)) return;
|
2014-07-23 21:03:03 +10:00
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
timer.reset(item);
|
2025-01-16 22:12:26 +02:00
|
|
|
List<ItemStack> permutations = getPermutations(item);
|
|
|
|
|
timer.reset();
|
2014-07-23 21:03:03 +10:00
|
|
|
|
2025-01-16 22:12:26 +02:00
|
|
|
for (ItemStack stack : permutations) {
|
|
|
|
|
if (!unique.contains(stack)) {
|
2014-07-23 21:03:03 +10:00
|
|
|
|
2025-01-16 22:12:26 +02:00
|
|
|
synchronized (unique) {
|
|
|
|
|
unique.add(stack);
|
|
|
|
|
}
|
2015-09-01 10:57:14 +10:00
|
|
|
|
2025-01-16 22:12:26 +02:00
|
|
|
synchronized (items) {
|
|
|
|
|
items.add(stack);
|
|
|
|
|
}
|
2014-07-23 21:03:03 +10:00
|
|
|
|
2025-10-02 07:15:28 +02:00
|
|
|
forceTagCompoundInitialization(stack);
|
|
|
|
|
|
2025-01-16 22:12:26 +02:00
|
|
|
CollapsibleItems.putItem(stack);
|
2025-04-24 18:48:40 +03:00
|
|
|
TooltipFilter.getSearchTooltip(stack);
|
2025-08-16 07:24:40 -04:00
|
|
|
InformationHandler.populateStacks(stack);
|
2025-01-16 22:12:26 +02:00
|
|
|
}
|
|
|
|
|
}
|
2024-08-29 23:14:52 +03:00
|
|
|
|
2025-01-16 22:12:26 +02:00
|
|
|
synchronized (itemMap) {
|
|
|
|
|
itemMap.putAll(item, permutations);
|
|
|
|
|
}
|
2014-07-23 21:03:03 +10:00
|
|
|
} catch (Throwable t) {
|
2025-01-16 22:12:26 +02:00
|
|
|
NEIServerConfig.logger.error("Removing item: {} from list.", item, t);
|
2014-07-23 21:03:03 +10:00
|
|
|
erroredItems.add(item);
|
|
|
|
|
}
|
2025-01-16 22:12:26 +02:00
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
int index = 0;
|
|
|
|
|
for (Item item : (Iterable<Item>) Item.itemRegistry) {
|
|
|
|
|
for (ItemStack stack : itemMap.get(item)) {
|
|
|
|
|
ItemSorter.instance.ordering.put(stack, index++);
|
|
|
|
|
}
|
2014-06-29 20:31:37 +10:00
|
|
|
}
|
2014-04-29 10:54:20 +10:00
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
if (interrupted()) return;
|
2014-07-23 21:03:03 +10:00
|
|
|
ItemList.items = items;
|
|
|
|
|
ItemList.itemMap = itemMap;
|
2022-06-24 12:32:13 +01:00
|
|
|
for (ItemsLoadedCallback callback : loadCallbacks) callback.itemsLoaded();
|
2014-07-23 21:03:03 +10:00
|
|
|
|
2024-07-26 18:44:54 +03:00
|
|
|
if (interrupted()) return;
|
2025-01-16 22:12:26 +02:00
|
|
|
updateOrdering(ItemList.items);
|
|
|
|
|
|
2022-08-31 17:43:22 +09:00
|
|
|
loadFinished = true;
|
2025-01-16 22:12:26 +02:00
|
|
|
|
|
|
|
|
SubsetWidget.updateHiddenItems();
|
2025-04-24 18:48:40 +03:00
|
|
|
ItemPanels.bookmarkPanel.load();
|
2024-07-26 18:44:54 +03:00
|
|
|
updateFilter.restart();
|
2014-04-29 10:54:20 +10:00
|
|
|
}
|
2014-07-23 21:03:03 +10:00
|
|
|
};
|
2014-04-29 10:54:20 +10:00
|
|
|
|
2024-10-04 21:46:29 +02:00
|
|
|
public static ForkJoinPool forkJoinPool;
|
2020-01-01 11:14:02 -08:00
|
|
|
|
2024-10-04 21:46:29 +02:00
|
|
|
static {
|
|
|
|
|
final ForkJoinPool.ForkJoinWorkerThreadFactory factory = new ForkJoinPool.ForkJoinWorkerThreadFactory() {
|
|
|
|
|
|
|
|
|
|
private int workerId;
|
2020-01-01 11:14:02 -08:00
|
|
|
|
2024-10-04 21:46:29 +02:00
|
|
|
@Override
|
|
|
|
|
public ForkJoinWorkerThread newThread(ForkJoinPool pool) {
|
|
|
|
|
final ForkJoinWorkerThread worker = ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool);
|
|
|
|
|
worker.setName("NEI-worker-thread-" + workerId++);
|
|
|
|
|
return worker;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
int poolSize = Runtime.getRuntime().availableProcessors() * 2 / 3;
|
|
|
|
|
if (poolSize < 1) poolSize = 1;
|
|
|
|
|
forkJoinPool = new ForkJoinPool(poolSize, factory, null, false);
|
|
|
|
|
}
|
2020-01-01 11:14:02 -08:00
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
public static final RestartableTask updateFilter = new RestartableTask("NEI Item Filtering") {
|
2023-01-28 17:55:51 -08:00
|
|
|
|
2014-04-29 10:54:20 +10:00
|
|
|
@Override
|
2014-07-23 21:03:03 +10:00
|
|
|
public void execute() {
|
2025-01-04 15:03:53 +01:00
|
|
|
|
2024-07-26 18:44:54 +03:00
|
|
|
if (!loadFinished) return;
|
2014-12-14 17:10:00 +10:00
|
|
|
ItemFilter filter = getItemListFilter();
|
2024-07-26 18:44:54 +03:00
|
|
|
ArrayList<ItemStack> filtered;
|
2019-12-24 13:37:41 -08:00
|
|
|
|
2020-01-01 11:14:02 -08:00
|
|
|
try {
|
2022-06-24 12:32:13 +01:00
|
|
|
filtered = ItemList.forkJoinPool.submit(
|
2024-02-04 14:09:24 +02:00
|
|
|
() -> items.parallelStream().filter(filter::matches)
|
2022-06-24 12:32:13 +01:00
|
|
|
.collect(Collectors.toCollection(ArrayList::new)))
|
|
|
|
|
.get();
|
2020-01-01 11:14:02 -08:00
|
|
|
} catch (InterruptedException | ExecutionException e) {
|
2021-01-17 12:03:33 -08:00
|
|
|
filtered = new ArrayList<>();
|
2020-01-01 11:14:02 -08:00
|
|
|
e.printStackTrace();
|
|
|
|
|
stop();
|
|
|
|
|
}
|
2014-07-23 21:03:03 +10:00
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
if (interrupted()) return;
|
2025-01-04 15:03:53 +01:00
|
|
|
|
2025-04-24 18:48:40 +03:00
|
|
|
filtered.sort(Comparator.comparingInt(ItemList.ordering::get));
|
2025-01-04 15:03:53 +01:00
|
|
|
|
2022-06-24 12:32:13 +01:00
|
|
|
if (interrupted()) return;
|
2025-01-04 15:03:53 +01:00
|
|
|
|
2019-12-30 20:19:16 -08:00
|
|
|
ItemPanel.updateItemList(filtered);
|
2014-04-29 10:54:20 +10:00
|
|
|
}
|
2014-07-23 21:03:03 +10:00
|
|
|
};
|
2014-04-29 10:54:20 +10:00
|
|
|
|
2014-07-23 21:03:03 +10:00
|
|
|
/**
|
|
|
|
|
* @deprecated Use updateFilter.restart()
|
|
|
|
|
*/
|
|
|
|
|
@Deprecated
|
2014-06-29 20:31:37 +10:00
|
|
|
public static void updateFilter() {
|
2014-07-23 21:03:03 +10:00
|
|
|
updateFilter.restart();
|
2014-04-29 10:54:20 +10:00
|
|
|
}
|
|
|
|
|
|
2014-07-23 21:03:03 +10:00
|
|
|
/**
|
|
|
|
|
* @deprecated Use loadItems.restart()
|
|
|
|
|
*/
|
|
|
|
|
@Deprecated
|
2014-04-29 10:54:20 +10:00
|
|
|
public static void loadItems() {
|
2014-07-23 21:03:03 +10:00
|
|
|
loadItems.restart();
|
2014-04-29 10:54:20 +10:00
|
|
|
}
|
|
|
|
|
}
|