Files
NotEnoughItems/src/main/java/codechicken/nei/api/ItemInfo.java
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

504 lines
21 KiB
Java
Raw Normal View History

2014-04-29 10:54:20 +10:00
package codechicken.nei.api;
2023-09-25 00:35:24 +02:00
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
2014-04-29 10:54:20 +10:00
import net.minecraft.block.Block;
import net.minecraft.client.resources.I18n;
import net.minecraft.creativetab.CreativeTabs;
2014-04-29 10:54:20 +10:00
import net.minecraft.enchantment.Enchantment;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.EntityList.EntityEggInfo;
import net.minecraft.entity.monster.EntityIronGolem;
import net.minecraft.entity.monster.EntitySnowman;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.inventory.Slot;
2019-12-30 20:19:16 -08:00
import net.minecraft.item.Item;
import net.minecraft.item.ItemArmor;
import net.minecraft.item.ItemAxe;
import net.minecraft.item.ItemFood;
import net.minecraft.item.ItemHoe;
import net.minecraft.item.ItemPickaxe;
import net.minecraft.item.ItemSpade;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemSword;
2014-04-29 10:54:20 +10:00
import net.minecraft.potion.Potion;
import net.minecraft.util.EnumChatFormatting;
2014-04-29 10:54:20 +10:00
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.RegistryNamespaced;
import net.minecraft.world.World;
import net.minecraft.world.biome.BiomeGenBase;
import net.minecraftforge.common.BiomeDictionary;
import net.minecraftforge.common.IShearable;
import net.minecraftforge.oredict.OreDictionary;
2023-09-25 00:35:24 +02:00
import com.google.common.collect.ArrayListMultimap;
import codechicken.core.featurehack.GameDataManipulator;
import codechicken.nei.InfiniteStackSizeHandler;
import codechicken.nei.InfiniteToolHandler;
import codechicken.nei.ItemList;
2024-08-29 23:14:52 +03:00
import codechicken.nei.ItemList.AnyMultiItemFilter;
2024-06-27 18:03:50 +03:00
import codechicken.nei.ItemList.PatternItemFilter;
2023-09-25 00:35:24 +02:00
import codechicken.nei.ItemMobSpawner;
import codechicken.nei.ItemStackMap;
import codechicken.nei.ItemStackSet;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.PopupInputHandler;
2024-08-29 23:14:52 +03:00
import codechicken.nei.PresetsList;
2024-06-27 18:03:50 +03:00
import codechicken.nei.SearchField.SearchParserProvider;
import codechicken.nei.SearchTokenParser.SearchMode;
2023-09-25 00:35:24 +02:00
import codechicken.nei.config.ArrayDumper;
import codechicken.nei.config.HandlerDumper;
import codechicken.nei.config.ItemPanelDumper;
import codechicken.nei.config.RegistryDumper;
import codechicken.nei.guihook.GuiContainerManager;
import codechicken.nei.recipe.BrewingRecipeHandler;
import codechicken.nei.recipe.RecipeItemInputHandler;
2024-06-27 18:03:50 +03:00
import codechicken.nei.search.IdentifierFilter;
import codechicken.nei.search.ModNameFilter;
import codechicken.nei.search.OreDictionaryFilter;
import codechicken.nei.search.TooltipFilter;
2023-09-25 00:35:24 +02:00
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.registry.GameRegistry.UniqueIdentifier;
2014-04-29 10:54:20 +10:00
/**
* This is an internal class for storing information about items, to be accessed by the API
*/
public class ItemInfo {
public static enum Layout {
HEADER,
BODY,
FOOTER
2014-04-29 10:54:20 +10:00
}
public static final ArrayListMultimap<Layout, IHighlightHandler> highlightHandlers = ArrayListMultimap.create();
2019-12-30 20:19:16 -08:00
public static final ItemStackMap<String> nameOverrides = new ItemStackMap<>();
2014-04-29 10:54:20 +10:00
public static final ItemStackSet hiddenItems = new ItemStackSet();
2024-08-29 23:14:52 +03:00
public static final AnyMultiItemFilter hiddenItemsRules = new AnyMultiItemFilter();
2014-04-29 10:54:20 +10:00
public static final ItemStackSet finiteItems = new ItemStackSet();
public static final ArrayListMultimap<Item, ItemStack> itemOverrides = ArrayListMultimap.create();
public static final ArrayListMultimap<Item, ItemStack> itemVariants = ArrayListMultimap.create();
2014-04-29 10:54:20 +10:00
2019-12-30 20:19:16 -08:00
public static final LinkedList<IInfiniteItemHandler> infiniteHandlers = new LinkedList<>();
2014-04-29 10:54:20 +10:00
public static final ArrayListMultimap<Block, IHighlightHandler> highlightIdentifiers = ArrayListMultimap.create();
2019-12-30 20:19:16 -08:00
public static final HashSet<Class<? extends Slot>> fastTransferExemptions = new HashSet<>();
2014-04-29 10:54:20 +10:00
2019-12-30 20:19:16 -08:00
public static final HashMap<Item, String> itemOwners = new HashMap<>();
2014-04-29 10:54:20 +10:00
public static boolean isHidden(ItemStack stack) {
2024-08-29 23:14:52 +03:00
return hiddenItems.contains(stack) || hiddenItemsRules.matches(stack);
2014-04-29 10:54:20 +10:00
}
2024-08-29 23:14:52 +03:00
@Deprecated
2014-04-29 10:54:20 +10:00
public static boolean isHidden(Item item) {
return hiddenItems.containsAll(item);
}
public static String getNameOverride(ItemStack stack) {
return nameOverrides.get(stack);
}
public static boolean canBeInfinite(ItemStack stack) {
return !finiteItems.contains(stack);
}
/**
* @deprecated Use field directly
*/
@Deprecated
2014-04-29 10:54:20 +10:00
public static List<ItemStack> getItemOverrides(Item item) {
return itemOverrides.get(item);
}
public static void preInit() {
addMobSpawnerItem();
}
2014-04-29 10:54:20 +10:00
public static void load(World world) {
addVanillaBlockProperties();
addDefaultDropDowns();
searchItems();
parseModItems();
ItemMobSpawner.loadSpawners(world);
2014-04-29 10:54:20 +10:00
addSpawnEggs();
addInfiniteHandlers();
addInputHandlers();
addIDDumps();
2024-06-27 18:03:50 +03:00
addSearchProviders();
2024-08-29 23:14:52 +03:00
PresetsList.load();
ItemList.collapsibleItems.load();
2024-06-27 18:03:50 +03:00
ItemList.loadCallbacks.add(TooltipFilter::populateSearchMap);
}
2024-06-27 18:03:50 +03:00
private static void addSearchProviders() {
API.addSearchProvider(
new SearchParserProvider('\0', "default", EnumChatFormatting.RESET, PatternItemFilter::new) {
2024-06-27 18:03:50 +03:00
@Override
public SearchMode getSearchMode() {
return SearchMode.ALWAYS;
}
2024-06-27 18:03:50 +03:00
});
API.addSearchProvider(
new SearchParserProvider('@', "modName", EnumChatFormatting.LIGHT_PURPLE, ModNameFilter::new));
2024-06-27 18:03:50 +03:00
API.addSearchProvider(
new SearchParserProvider('$', "oreDict", EnumChatFormatting.AQUA, OreDictionaryFilter::new));
API.addSearchProvider(new SearchParserProvider('#', "tooltip", EnumChatFormatting.YELLOW, TooltipFilter::new));
2024-06-27 18:03:50 +03:00
API.addSearchProvider(
new SearchParserProvider('&', "identifier", EnumChatFormatting.GOLD, IdentifierFilter::new));
2014-04-29 10:54:20 +10:00
}
private static void addIDDumps() {
API.addOption(new RegistryDumper<Item>("tools.dump.item") {
2014-04-29 10:54:20 +10:00
@Override
public String[] header() {
return new String[] { "Name", "ID", "Has Block", "Mod", "Class", "Display Name" };
2014-04-29 10:54:20 +10:00
}
@Override
public String[] dump(Item item, int id, String name) {
return new String[] { name, Integer.toString(id),
Boolean.toString(Block.getBlockFromItem(item) != Blocks.air), ItemInfo.itemOwners.get(item),
item.getClass().getCanonicalName(), EnumChatFormatting.getTextWithoutFormattingCodes(
GuiContainerManager.itemDisplayNameShort(new ItemStack(item))) };
2014-04-29 10:54:20 +10:00
}
@Override
public RegistryNamespaced registry() {
return Item.itemRegistry;
}
});
API.addOption(new RegistryDumper<Block>("tools.dump.block") {
2014-04-29 10:54:20 +10:00
@Override
public String[] header() {
return new String[] { "Name", "ID", "Has Item", "Mod", "Class", "Display Name" };
2014-04-29 10:54:20 +10:00
}
@Override
public String[] dump(Block block, int id, String name) {
final Item item = Item.getItemFromBlock(block);
return new String[] { name, Integer.toString(id), Boolean.toString(item != null),
2024-08-29 20:07:14 +02:00
ItemInfo.itemOwners.get(item), block.getClass().getCanonicalName(),
item != null ? EnumChatFormatting.getTextWithoutFormattingCodes(
GuiContainerManager.itemDisplayNameShort(new ItemStack(item))) : "null" };
2014-04-29 10:54:20 +10:00
}
@Override
public RegistryNamespaced registry() {
return Block.blockRegistry;
}
});
API.addOption(new ArrayDumper<Potion>("tools.dump.potion") {
2014-04-29 10:54:20 +10:00
public String[] header() {
return new String[] { "ID", "Unlocalised name", "Class" };
2014-04-29 10:54:20 +10:00
}
@Override
public String[] dump(Potion potion, int id) {
return new String[] { Integer.toString(id), potion.getName(), potion.getClass().getCanonicalName() };
2014-04-29 10:54:20 +10:00
}
@Override
public Potion[] array() {
return Potion.potionTypes;
}
});
API.addOption(new ArrayDumper<Enchantment>("tools.dump.enchantment") {
2014-04-29 10:54:20 +10:00
public String[] header() {
return new String[] { "ID", "Unlocalised name", "Type", "Min Level", "Max Level", "Class" };
2014-04-29 10:54:20 +10:00
}
@Override
public String[] dump(Enchantment ench, int id) {
return new String[] { Integer.toString(id), ench.getName(), ench.type.toString(),
Integer.toString(ench.getMinLevel()), Integer.toString(ench.getMaxLevel()),
ench.getClass().getCanonicalName() };
2014-04-29 10:54:20 +10:00
}
@Override
public Enchantment[] array() {
return Enchantment.enchantmentsList;
}
});
API.addOption(new ArrayDumper<BiomeGenBase>("tools.dump.biome") {
2014-04-29 10:54:20 +10:00
@Override
public String[] header() {
return new String[] { "ID", "Name", "Temperature", "Rainfall", "Spawn Chance", "Root Height",
"Height Variation", "Types", "Class" };
2014-04-29 10:54:20 +10:00
}
@Override
public String[] dump(BiomeGenBase biome, int id) {
BiomeDictionary.Type[] types = BiomeDictionary.getTypesForBiome(biome);
StringBuilder s_types = new StringBuilder();
for (BiomeDictionary.Type t : types) {
if (s_types.length() > 0) s_types.append(", ");
2014-04-29 10:54:20 +10:00
s_types.append(t.name());
}
return new String[] { Integer.toString(id), biome.biomeName,
Float.toString(biome.getFloatTemperature(0, 0, 0)), Float.toString(biome.getFloatRainfall()),
Float.toString(biome.getSpawningChance()), Float.toString(biome.rootHeight),
Float.toString(biome.heightVariation), s_types.toString(),
biome.getClass().getCanonicalName() };
2014-04-29 10:54:20 +10:00
}
@Override
public BiomeGenBase[] array() {
return BiomeGenBase.getBiomeGenArray();
}
});
API.addOption(new ItemPanelDumper("tools.dump.itempanel"));
2021-03-20 22:38:46 -07:00
API.addOption(new HandlerDumper("tools.dump.handlers"));
2014-04-29 10:54:20 +10:00
}
2021-04-10 15:32:59 -07:00
@SuppressWarnings("unchecked")
2014-04-29 10:54:20 +10:00
private static void parseModItems() {
2019-12-30 20:19:16 -08:00
HashMap<String, ItemStackSet> modSubsets = new HashMap<>();
for (Item item : (Iterable<Item>) Item.itemRegistry) {
UniqueIdentifier ident = null;
try {
ident = GameRegistry.findUniqueIdentifierFor(item);
} catch (Exception ignored) {}
if (ident == null) {
NEIClientConfig.logger.error("Failed to find identifier for: " + item);
continue;
}
String modId = ident.modId;
itemOwners.put(item, modId);
ItemStackSet itemset = modSubsets.get(modId);
if (itemset == null) modSubsets.put(modId, itemset = new ItemStackSet());
itemset.with(item);
}
API.addSubset("Mod.Minecraft", modSubsets.remove("minecraft"));
for (Entry<String, ItemStackSet> entry : modSubsets.entrySet()) {
ModContainer mc = FMLCommonHandler.instance().findContainerFor(entry.getKey());
if (mc == null) NEIClientConfig.logger.error("Missing container for " + entry.getKey());
else API.addSubset("Mod." + mc.getName(), entry.getValue());
}
2014-04-29 10:54:20 +10:00
}
private static void addInputHandlers() {
GuiContainerManager.addInputHandler(new RecipeItemInputHandler());
GuiContainerManager.addInputHandler(new PopupInputHandler());
}
private static void addMobSpawnerItem() {
GameDataManipulator.replaceItem(Block.getIdFromBlock(Blocks.mob_spawner), new ItemMobSpawner());
2014-04-29 10:54:20 +10:00
}
private static void addInfiniteHandlers() {
API.addInfiniteItemHandler(new InfiniteStackSizeHandler());
API.addInfiniteItemHandler(new InfiniteToolHandler());
}
private static void addVanillaBlockProperties() {
API.setOverrideName(new ItemStack(Blocks.flowing_water), "Water Source");
API.setOverrideName(new ItemStack(Blocks.water), "Water Still");
API.setOverrideName(new ItemStack(Blocks.flowing_lava), "Lava Source");
API.setOverrideName(new ItemStack(Blocks.lava), "Lava Still");
API.setOverrideName(new ItemStack(Blocks.end_portal), "End Portal");
API.setOverrideName(new ItemStack(Blocks.end_portal_frame), "End Portal Frame");
API.hideItem(new ItemStack(Blocks.double_stone_slab, 1, OreDictionary.WILDCARD_VALUE));
API.hideItem(new ItemStack(Blocks.double_wooden_slab, 1, OreDictionary.WILDCARD_VALUE));
API.hideItem(new ItemStack(Blocks.carrots));
API.hideItem(new ItemStack(Blocks.potatoes));
API.hideItem(new ItemStack(Blocks.cocoa));
}
private static void addDefaultDropDowns() {
2019-12-30 20:19:16 -08:00
API.addSubset("Items", item -> Block.getBlockFromItem(item.getItem()) == Blocks.air);
API.addSubset("Blocks", item -> Block.getBlockFromItem(item.getItem()) != Blocks.air);
API.addSubset("Blocks.MobSpawners", ItemStackSet.of(Blocks.mob_spawner));
2014-04-29 10:54:20 +10:00
}
2021-04-10 15:32:59 -07:00
@SuppressWarnings("unchecked")
2014-04-29 10:54:20 +10:00
private static void searchItems() {
ItemStackSet tools = new ItemStackSet();
ItemStackSet picks = new ItemStackSet();
ItemStackSet shovels = new ItemStackSet();
ItemStackSet axes = new ItemStackSet();
ItemStackSet hoes = new ItemStackSet();
ItemStackSet swords = new ItemStackSet();
ItemStackSet chest = new ItemStackSet();
ItemStackSet helmets = new ItemStackSet();
ItemStackSet legs = new ItemStackSet();
ItemStackSet boots = new ItemStackSet();
ItemStackSet other = new ItemStackSet();
ItemStackSet ranged = new ItemStackSet();
ItemStackSet food = new ItemStackSet();
ItemStackSet potioningredients = new ItemStackSet();
2019-12-30 20:19:16 -08:00
ArrayList<ItemStackSet> creativeTabRanges = new ArrayList<>(CreativeTabs.creativeTabArray.length);
List<ItemStack> stackList = new LinkedList<>();
2014-04-29 10:54:20 +10:00
for (Item item : (Iterable<Item>) Item.itemRegistry) {
if (item == null) continue;
2014-04-29 10:54:20 +10:00
for (CreativeTabs itemTab : item.getCreativeTabs()) {
if (itemTab != null) {
while (itemTab.getTabIndex() >= creativeTabRanges.size()) creativeTabRanges.add(null);
ItemStackSet set = creativeTabRanges.get(itemTab.getTabIndex());
if (set == null) creativeTabRanges.set(itemTab.getTabIndex(), set = new ItemStackSet());
try {
stackList.clear();
item.getSubItems(item, itemTab, stackList);
for (ItemStack stack : stackList) set.add(stack);
} catch (Exception e) {
NEIClientConfig.logger
.error("Error loading sub-items for: " + item + ". Tab: " + itemTab.getTabLabel(), e);
}
}
}
2014-04-29 10:54:20 +10:00
if (item.isDamageable()) {
tools.with(item);
if (item instanceof ItemPickaxe) picks.with(item);
else if (item instanceof ItemSpade) shovels.with(item);
else if (item instanceof ItemAxe) axes.with(item);
else if (item instanceof ItemHoe) hoes.with(item);
else if (item instanceof ItemSword) swords.with(item);
2014-04-29 10:54:20 +10:00
else if (item instanceof ItemArmor) switch (((ItemArmor) item).armorType) {
case 0:
helmets.with(item);
2014-04-29 10:54:20 +10:00
break;
case 1:
chest.with(item);
2014-04-29 10:54:20 +10:00
break;
case 2:
legs.with(item);
2014-04-29 10:54:20 +10:00
break;
case 3:
boots.with(item);
2014-04-29 10:54:20 +10:00
break;
}
else if (item == Items.arrow || item == Items.bow) ranged.with(item);
else if (item == Items.fishing_rod || item == Items.flint_and_steel || item == Items.shears)
other.with(item);
2014-04-29 10:54:20 +10:00
}
if (item instanceof ItemFood) food.with(item);
2014-04-29 10:54:20 +10:00
try {
2019-12-30 20:19:16 -08:00
LinkedList<ItemStack> subItems = new LinkedList<>();
item.getSubItems(item, null, subItems);
for (ItemStack stack : subItems) {
if (item.isPotionIngredient(stack) && item.getPotionEffect(stack) != null) {
BrewingRecipeHandler.ingredients.add(stack);
potioningredients.add(stack);
}
}
} catch (Exception e) {
NEIClientConfig.logger.error("Error loading brewing ingredients for: " + item, e);
2014-04-29 10:54:20 +10:00
}
}
API.addSubset("Items.Tools.Pickaxes", picks);
API.addSubset("Items.Tools.Shovels", shovels);
API.addSubset("Items.Tools.Axes", axes);
API.addSubset("Items.Tools.Hoes", hoes);
API.addSubset("Items.Tools.Other", other);
API.addSubset("Items.Weapons.Swords", swords);
API.addSubset("Items.Weapons.Ranged", ranged);
2015-04-25 23:41:18 +10:00
API.addSubset("Items.Armor.Chestplates", chest);
API.addSubset("Items.Armor.Leggings", legs);
API.addSubset("Items.Armor.Helmets", helmets);
API.addSubset("Items.Armor.Boots", boots);
API.addSubset("Items.Food", food);
API.addSubset("Items.Potions.Ingredients", potioningredients);
for (CreativeTabs tab : CreativeTabs.creativeTabArray) {
if (tab.getTabIndex() >= creativeTabRanges.size()) continue;
ItemStackSet set = creativeTabRanges.get(tab.getTabIndex());
if (set != null && !set.isEmpty())
API.addSubset("CreativeTabs." + I18n.format(tab.getTranslatedTabLabel()), set);
}
BrewingRecipeHandler.searchPotions();
2014-04-29 10:54:20 +10:00
}
private static void addSpawnEggs() {
2014-04-29 10:54:20 +10:00
addEntityEgg(EntitySnowman.class, 0xEEFFFF, 0xffa221);
addEntityEgg(EntityIronGolem.class, 0xC5C2C1, 0xffe1cc);
}
private static void addEntityEgg(Class<?> entity, int i, int j) {
int id = (Integer) EntityList.classToIDMapping.get(entity);
2014-04-29 10:54:20 +10:00
EntityList.entityEggs.put(id, new EntityEggInfo(id, i, j));
}
public static ArrayList<ItemStack> getIdentifierItems(World world, EntityPlayer player, MovingObjectPosition hit) {
int x = hit.blockX;
int y = hit.blockY;
int z = hit.blockZ;
Block mouseoverBlock = world.getBlock(x, y, z);
2019-12-30 20:19:16 -08:00
ArrayList<ItemStack> items = new ArrayList<>();
2014-04-29 10:54:20 +10:00
2019-12-30 20:19:16 -08:00
ArrayList<IHighlightHandler> handlers = new ArrayList<>();
if (highlightIdentifiers.containsKey(null)) handlers.addAll(highlightIdentifiers.get(null));
if (highlightIdentifiers.containsKey(mouseoverBlock)) handlers.addAll(highlightIdentifiers.get(mouseoverBlock));
2014-04-29 10:54:20 +10:00
for (IHighlightHandler ident : handlers) {
ItemStack item = ident.identifyHighlight(world, player, hit);
if (item != null) items.add(item);
2014-04-29 10:54:20 +10:00
}
if (items.size() > 0) return items;
2014-04-29 10:54:20 +10:00
ItemStack pick = mouseoverBlock.getPickBlock(hit, world, x, y, z, player);
if (pick != null) items.add(pick);
2014-04-29 10:54:20 +10:00
try {
items.addAll(mouseoverBlock.getDrops(world, x, y, z, world.getBlockMetadata(x, y, z), 0));
} catch (Exception ignored) {}
2014-04-29 10:54:20 +10:00
if (mouseoverBlock instanceof IShearable) {
IShearable shearable = (IShearable) mouseoverBlock;
if (shearable.isShearable(new ItemStack(Items.shears), world, x, y, z))
items.addAll(shearable.onSheared(new ItemStack(Items.shears), world, x, y, z, 0));
}
if (items.size() == 0) items.add(0, new ItemStack(mouseoverBlock, 1, world.getBlockMetadata(x, y, z)));
2014-04-29 10:54:20 +10:00
return items;
}
public static void registerHighlightHandler(IHighlightHandler handler, ItemInfo.Layout... layouts) {
for (ItemInfo.Layout layout : layouts) ItemInfo.highlightHandlers.get(layout).add(handler);
}
public static List<String> getText(ItemStack itemStack, World world, EntityPlayer player,
MovingObjectPosition mop) {
2019-12-30 20:19:16 -08:00
List<String> retString = new ArrayList<>();
2014-04-29 10:54:20 +10:00
for (ItemInfo.Layout layout : ItemInfo.Layout.values())
for (IHighlightHandler handler : ItemInfo.highlightHandlers.get(layout))
retString = handler.handleTextData(itemStack, world, player, mop, retString, layout);
return retString;
}
2024-06-27 18:03:50 +03:00
@Deprecated
public static String getSearchName(ItemStack stack) {
2024-06-27 18:03:50 +03:00
return GuiContainerManager.concatenatedDisplayName(stack, true);
}
2014-04-29 10:54:20 +10:00
}