Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
cn.nukkit.item.Item Maven / Gradle / Ivy
package cn.nukkit.item;
import cn.nukkit.Player;
import cn.nukkit.Server;
import cn.nukkit.api.*;
import cn.nukkit.block.Block;
import cn.nukkit.block.BlockID;
import cn.nukkit.block.BlockUnknown;
import cn.nukkit.blockproperty.UnknownRuntimeIdException;
import cn.nukkit.blockproperty.exception.BlockPropertyNotFoundException;
import cn.nukkit.blockproperty.exception.InvalidBlockPropertyMetaException;
import cn.nukkit.blockstate.BlockState;
import cn.nukkit.blockstate.BlockStateRegistry;
import cn.nukkit.blockstate.exception.InvalidBlockStateException;
import cn.nukkit.entity.Entity;
import cn.nukkit.inventory.Fuel;
import cn.nukkit.item.customitem.CustomItemDefinition;
import cn.nukkit.item.customitem.ItemCustom;
import cn.nukkit.item.enchantment.Enchantment;
import cn.nukkit.item.enchantment.sideeffect.SideEffect;
import cn.nukkit.item.randomitem.ItemEchoShard;
import cn.nukkit.level.Level;
import cn.nukkit.math.BlockFace;
import cn.nukkit.math.Vector3;
import cn.nukkit.nbt.NBTIO;
import cn.nukkit.nbt.tag.*;
import cn.nukkit.utils.Binary;
import cn.nukkit.utils.Config;
import cn.nukkit.utils.Utils;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import io.netty.util.internal.EmptyArrays;
import it.unimi.dsi.fastutil.ints.Int2IntArrayMap;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.nio.ByteOrder;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Log 4j2
public class Item implements Cloneable , BlockID , ItemID {
@PowerNukkitOnly
@Since ("1.4.0.0-PN" )
public static final Item[] EMPTY_ARRAY = new Item[0 ];
private static final Pattern ITEM_STRING_PATTERN = Pattern.compile(
"^(?:(?:([a-z_]\\w*):)?([a-z._]\\w*)(?::(-?\\d+))?|(-?\\d+)(?::(-?\\d+))?)$" );
protected static String UNKNOWN_STR = "Unknown" ;
public static Class[] list = null ;
private static Map itemIds = Arrays.stream(ItemID.class.getDeclaredFields())
.filter(field -> field.getModifiers() == (Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL))
.filter(field -> field.getType().equals(int .class))
.collect(Collectors.toMap(
field -> field.getName().toLowerCase(),
field -> {
try {
return field.getInt(null );
} catch (IllegalAccessException e) {
throw new InternalError(e);
}
},
(e1, e2) -> e1, LinkedHashMap::new
));
private static Map blockIds = Arrays.stream(BlockID.class.getDeclaredFields())
.filter(field -> field.getModifiers() == (Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL))
.filter(field -> field.getType().equals(int .class))
.collect(Collectors.toMap(
field -> field.getName().toLowerCase(),
field -> {
try {
int blockId = field.getInt(null );
if (blockId > 255 ) {
return 255 - blockId;
}
return blockId;
} catch (IllegalAccessException e) {
throw new InternalError(e);
}
},
(e1, e2) -> e1, LinkedHashMap::new
));
@PowerNukkitXOnly
@Since ("1.6.0.0-PNX" )
private static final HashMap> CUSTOM_ITEMS = new HashMap<>();
@PowerNukkitXOnly
@Since ("1.19.31-r1" )
private static final HashMap CUSTOM_ITEM_DEFINITIONS = new HashMap<>();
protected Block block = null ;
protected final int id;
protected int meta;
protected boolean hasMeta = true ;
private byte [] tags = EmptyArrays.EMPTY_BYTES;
private transient CompoundTag cachedNBT = null ;
public int count;
@Deprecated
@DeprecationDetails (since = "1.4.0.0-PN" , by = "PowerNukkit" , reason = "Unused" , replaceWith = "meta or getDamage()" )
protected int durability = 0 ;
protected String name;
public Item (int id) {
this (id, 0 , 1 , UNKNOWN_STR);
}
public Item (int id, Integer meta) {
this (id, meta, 1 , UNKNOWN_STR);
}
public Item (int id, Integer meta, int count) {
this (id, meta, count, UNKNOWN_STR);
}
public Item (int id, Integer meta, int count, String name) {
this .id = id;
if (meta != null && meta >= 0 ) {
this .meta = meta & 0xffff ;
} else {
this .hasMeta = false ;
}
this .count = count;
this .name = name != null ? name.intern() : null ;
}
public boolean hasMeta () {
return hasMeta;
}
public boolean canBeActivated () {
return false ;
}
public static void init () {
if (list == null ) {
list = new Class[65535 ];
list[IRON_SHOVEL] = ItemShovelIron.class;
list[IRON_PICKAXE] = ItemPickaxeIron.class;
list[IRON_AXE] = ItemAxeIron.class;
list[FLINT_AND_STEEL] = ItemFlintSteel.class;
list[APPLE] = ItemApple.class;
list[BOW] = ItemBow.class;
list[ARROW] = ItemArrow.class;
list[COAL] = ItemCoal.class;
list[DIAMOND] = ItemDiamond.class;
list[IRON_INGOT] = ItemIngotIron.class;
list[GOLD_INGOT] = ItemIngotGold.class;
list[IRON_SWORD] = ItemSwordIron.class;
list[WOODEN_SWORD] = ItemSwordWood.class;
list[WOODEN_SHOVEL] = ItemShovelWood.class;
list[WOODEN_PICKAXE] = ItemPickaxeWood.class;
list[WOODEN_AXE] = ItemAxeWood.class;
list[STONE_SWORD] = ItemSwordStone.class;
list[STONE_SHOVEL] = ItemShovelStone.class;
list[STONE_PICKAXE] = ItemPickaxeStone.class;
list[STONE_AXE] = ItemAxeStone.class;
list[DIAMOND_SWORD] = ItemSwordDiamond.class;
list[DIAMOND_SHOVEL] = ItemShovelDiamond.class;
list[DIAMOND_PICKAXE] = ItemPickaxeDiamond.class;
list[DIAMOND_AXE] = ItemAxeDiamond.class;
list[STICK] = ItemStick.class;
list[BOWL] = ItemBowl.class;
list[MUSHROOM_STEW] = ItemMushroomStew.class;
list[GOLD_SWORD] = ItemSwordGold.class;
list[GOLD_SHOVEL] = ItemShovelGold.class;
list[GOLD_PICKAXE] = ItemPickaxeGold.class;
list[GOLD_AXE] = ItemAxeGold.class;
list[STRING] = ItemString.class;
list[FEATHER] = ItemFeather.class;
list[GUNPOWDER] = ItemGunpowder.class;
list[WOODEN_HOE] = ItemHoeWood.class;
list[STONE_HOE] = ItemHoeStone.class;
list[IRON_HOE] = ItemHoeIron.class;
list[DIAMOND_HOE] = ItemHoeDiamond.class;
list[GOLD_HOE] = ItemHoeGold.class;
list[WHEAT_SEEDS] = ItemSeedsWheat.class;
list[WHEAT] = ItemWheat.class;
list[BREAD] = ItemBread.class;
list[LEATHER_CAP] = ItemHelmetLeather.class;
list[LEATHER_TUNIC] = ItemChestplateLeather.class;
list[LEATHER_PANTS] = ItemLeggingsLeather.class;
list[LEATHER_BOOTS] = ItemBootsLeather.class;
list[CHAIN_HELMET] = ItemHelmetChain.class;
list[CHAIN_CHESTPLATE] = ItemChestplateChain.class;
list[CHAIN_LEGGINGS] = ItemLeggingsChain.class;
list[CHAIN_BOOTS] = ItemBootsChain.class;
list[IRON_HELMET] = ItemHelmetIron.class;
list[IRON_CHESTPLATE] = ItemChestplateIron.class;
list[IRON_LEGGINGS] = ItemLeggingsIron.class;
list[IRON_BOOTS] = ItemBootsIron.class;
list[DIAMOND_HELMET] = ItemHelmetDiamond.class;
list[DIAMOND_CHESTPLATE] = ItemChestplateDiamond.class;
list[DIAMOND_LEGGINGS] = ItemLeggingsDiamond.class;
list[DIAMOND_BOOTS] = ItemBootsDiamond.class;
list[GOLD_HELMET] = ItemHelmetGold.class;
list[GOLD_CHESTPLATE] = ItemChestplateGold.class;
list[GOLD_LEGGINGS] = ItemLeggingsGold.class;
list[GOLD_BOOTS] = ItemBootsGold.class;
list[FLINT] = ItemFlint.class;
list[RAW_PORKCHOP] = ItemPorkchopRaw.class;
list[COOKED_PORKCHOP] = ItemPorkchopCooked.class;
list[PAINTING] = ItemPainting.class;
list[GOLDEN_APPLE] = ItemAppleGold.class;
list[SIGN] = ItemSign.class;
list[WOODEN_DOOR] = ItemDoorWood.class;
list[BUCKET] = ItemBucket.class;
list[MINECART] = ItemMinecart.class;
list[SADDLE] = ItemSaddle.class;
list[IRON_DOOR] = ItemDoorIron.class;
list[REDSTONE] = ItemRedstone.class;
list[SNOWBALL] = ItemSnowball.class;
list[BOAT] = ItemBoat.class;
list[LEATHER] = ItemLeather.class;
list[KELP] = ItemKelp.class;
list[BRICK] = ItemBrick.class;
list[CLAY] = ItemClay.class;
list[SUGARCANE] = ItemSugarcane.class;
list[PAPER] = ItemPaper.class;
list[BOOK] = ItemBook.class;
list[SLIMEBALL] = ItemSlimeball.class;
list[CHEST_MINECART] = ItemMinecartChest.class;
list[EGG] = ItemEgg.class;
list[COMPASS] = ItemCompass.class;
list[FISHING_ROD] = ItemFishingRod.class;
list[CLOCK] = ItemClock.class;
list[GLOWSTONE_DUST] = ItemGlowstoneDust.class;
list[RAW_FISH] = ItemFish.class;
list[COOKED_FISH] = ItemFishCooked.class;
list[DYE] = ItemDye.class;
list[BONE] = ItemBone.class;
list[SUGAR] = ItemSugar.class;
list[CAKE] = ItemCake.class;
list[BED] = ItemBed.class;
list[REPEATER] = ItemRedstoneRepeater.class;
list[COOKIE] = ItemCookie.class;
list[MAP] = ItemMap.class;
list[SHEARS] = ItemShears.class;
list[MELON] = ItemMelon.class;
list[PUMPKIN_SEEDS] = ItemSeedsPumpkin.class;
list[MELON_SEEDS] = ItemSeedsMelon.class;
list[RAW_BEEF] = ItemBeefRaw.class;
list[STEAK] = ItemSteak.class;
list[RAW_CHICKEN] = ItemChickenRaw.class;
list[COOKED_CHICKEN] = ItemChickenCooked.class;
list[ROTTEN_FLESH] = ItemRottenFlesh.class;
list[ENDER_PEARL] = ItemEnderPearl.class;
list[BLAZE_ROD] = ItemBlazeRod.class;
list[GHAST_TEAR] = ItemGhastTear.class;
list[GOLD_NUGGET] = ItemNuggetGold.class;
list[NETHER_WART] = ItemNetherWart.class;
list[POTION] = ItemPotion.class;
list[GLASS_BOTTLE] = ItemGlassBottle.class;
list[SPIDER_EYE] = ItemSpiderEye.class;
list[FERMENTED_SPIDER_EYE] = ItemSpiderEyeFermented.class;
list[BLAZE_POWDER] = ItemBlazePowder.class;
list[MAGMA_CREAM] = ItemMagmaCream.class;
list[BREWING_STAND] = ItemBrewingStand.class;
list[CAULDRON] = ItemCauldron.class;
list[ENDER_EYE] = ItemEnderEye.class;
list[GLISTERING_MELON] = ItemMelonGlistering.class;
list[SPAWN_EGG] = ItemSpawnEgg.class;
list[EXPERIENCE_BOTTLE] = ItemExpBottle.class;
list[FIRE_CHARGE] = ItemFireCharge.class;
list[BOOK_AND_QUILL] = ItemBookAndQuill.class;
list[WRITTEN_BOOK] = ItemBookWritten.class;
list[EMERALD] = ItemEmerald.class;
list[ITEM_FRAME] = ItemItemFrame.class;
list[FLOWER_POT] = ItemFlowerPot.class;
list[CARROT] = ItemCarrot.class;
list[POTATO] = ItemPotato.class;
list[BAKED_POTATO] = ItemPotatoBaked.class;
list[POISONOUS_POTATO] = ItemPotatoPoisonous.class;
list[EMPTY_MAP] = ItemEmptyMap.class;
list[GOLDEN_CARROT] = ItemCarrotGolden.class;
list[SKULL] = ItemSkull.class;
list[CARROT_ON_A_STICK] = ItemCarrotOnAStick.class;
list[NETHER_STAR] = ItemNetherStar.class;
list[PUMPKIN_PIE] = ItemPumpkinPie.class;
list[FIREWORKS] = ItemFirework.class;
list[FIREWORKSCHARGE] = ItemFireworkStar.class;
list[ENCHANTED_BOOK] = ItemBookEnchanted.class;
list[COMPARATOR] = ItemRedstoneComparator.class;
list[NETHER_BRICK] = ItemNetherBrick.class;
list[QUARTZ] = ItemQuartz.class;
list[TNT_MINECART] = ItemMinecartTNT.class;
list[HOPPER_MINECART] = ItemMinecartHopper.class;
list[PRISMARINE_SHARD] = ItemPrismarineShard.class;
list[HOPPER] = ItemHopper.class;
list[RAW_RABBIT] = ItemRabbitRaw.class;
list[COOKED_RABBIT] = ItemRabbitCooked.class;
list[RABBIT_STEW] = ItemRabbitStew.class;
list[RABBIT_FOOT] = ItemRabbitFoot.class;
list[RABBIT_HIDE] = ItemRabbitHide.class;
list[LEATHER_HORSE_ARMOR] = ItemHorseArmorLeather.class;
list[IRON_HORSE_ARMOR] = ItemHorseArmorIron.class;
list[GOLD_HORSE_ARMOR] = ItemHorseArmorGold.class;
list[DIAMOND_HORSE_ARMOR] = ItemHorseArmorDiamond.class;
list[LEAD] = ItemLead.class;
list[NAME_TAG] = ItemNameTag.class;
list[PRISMARINE_CRYSTALS] = ItemPrismarineCrystals.class;
list[RAW_MUTTON] = ItemMuttonRaw.class;
list[COOKED_MUTTON] = ItemMuttonCooked.class;
list[ARMOR_STAND] = ItemArmorStand.class;
list[END_CRYSTAL] = ItemEndCrystal.class;
list[SPRUCE_DOOR] = ItemDoorSpruce.class;
list[BIRCH_DOOR] = ItemDoorBirch.class;
list[JUNGLE_DOOR] = ItemDoorJungle.class;
list[ACACIA_DOOR] = ItemDoorAcacia.class;
list[DARK_OAK_DOOR] = ItemDoorDarkOak.class;
list[CHORUS_FRUIT] = ItemChorusFruit.class;
list[POPPED_CHORUS_FRUIT] = ItemChorusFruitPopped.class;
list[BANNER_PATTERN] = ItemBannerPattern.class;
list[DRAGON_BREATH] = ItemDragonBreath.class;
list[SPLASH_POTION] = ItemPotionSplash.class;
list[LINGERING_POTION] = ItemPotionLingering.class;
list[ELYTRA] = ItemElytra.class;
list[SHULKER_SHELL] = ItemShulkerShell.class;
list[BANNER] = ItemBanner.class;
list[TOTEM] = ItemTotem.class;
list[IRON_NUGGET] = ItemNuggetIron.class;
list[TRIDENT] = ItemTrident.class;
list[BEETROOT] = ItemBeetroot.class;
list[BEETROOT_SEEDS] = ItemSeedsBeetroot.class;
list[BEETROOT_SOUP] = ItemBeetrootSoup.class;
list[RAW_SALMON] = ItemSalmon.class;
list[CLOWNFISH] = ItemClownfish.class;
list[PUFFERFISH] = ItemPufferfish.class;
list[COOKED_SALMON] = ItemSalmonCooked.class;
list[DRIED_KELP] = ItemDriedKelp.class;
list[NAUTILUS_SHELL] = ItemNautilusShell.class;
list[GOLDEN_APPLE_ENCHANTED] = ItemAppleGoldEnchanted.class;
list[HEART_OF_THE_SEA] = ItemHeartOfTheSea.class;
list[SCUTE] = ItemScute.class;
list[TURTLE_SHELL] = ItemTurtleShell.class;
list[PHANTOM_MEMBRANE] = ItemPhantomMembrane.class;
list[CROSSBOW] = ItemCrossbow.class;
list[SPRUCE_SIGN] = ItemSpruceSign.class;
list[BIRCH_SIGN] = ItemBirchSign.class;
list[JUNGLE_SIGN] = ItemJungleSign.class;
list[ACACIA_SIGN] = ItemAcaciaSign.class;
list[DARKOAK_SIGN] = ItemDarkOakSign.class;
list[SWEET_BERRIES] = ItemSweetBerries.class;
list[RECORD_13] = ItemRecord13.class;
list[RECORD_CAT] = ItemRecordCat.class;
list[RECORD_BLOCKS] = ItemRecordBlocks.class;
list[RECORD_CHIRP] = ItemRecordChirp.class;
list[RECORD_FAR] = ItemRecordFar.class;
list[RECORD_MALL] = ItemRecordMall.class;
list[RECORD_MELLOHI] = ItemRecordMellohi.class;
list[RECORD_STAL] = ItemRecordStal.class;
list[RECORD_STRAD] = ItemRecordStrad.class;
list[RECORD_WARD] = ItemRecordWard.class;
list[RECORD_11] = ItemRecord11.class;
list[RECORD_WAIT] = ItemRecordWait.class;
list[SHIELD] = ItemShield.class;
list[GLOW_ITEM_FRAME] = ItemItemFrameGlow.class;
list[RECORD_OTHERSIDE] = ItemRecordOtherside.class;
list[ITEM_MANGROVE_DOOR] = ItemDoorMangrove.class;
list[MANGROVE_SIGN] = ItemMangroveSign.class;
list[RECORD_5] = ItemRecord5.class;
list[DISC_FRAGMENT_5] = ItemDiscFragment5.class;
list[OAK_CHEST_BOAT] = ItemChestBoatOak.class;
list[BIRCH_CHEST_BOAT] = ItemChestBoatBirch.class;
list[JUNGLE_CHEST_BOAT] = ItemChestBoatJungle.class;
list[SPRUCE_CHEST_BOAT] = ItemChestBoatSpruce.class;
list[ACACIA_CHEST_BOAT] = ItemChestBoatAcacia.class;
list[DARK_OAK_CHEST_BOAT] = ItemChestBoatDarkOak.class;
list[MANGROVE_CHEST_BOAT] = ItemChestBoatMangrove.class;
list[ECHO_SHARD] = ItemEchoShard.class;
list[GLOW_BERRIES] = ItemGlowBerries.class;
list[CAMPFIRE] = ItemCampfire.class;
list[SUSPICIOUS_STEW] = ItemSuspiciousStew.class;
list[HONEYCOMB] = ItemHoneycomb.class;
list[HONEY_BOTTLE] = ItemHoneyBottle.class;
list[LODESTONECOMPASS] = ItemCompassLodestone.class;
list[NETHERITE_INGOT] = ItemIngotNetherite.class;
list[NETHERITE_SWORD] = ItemSwordNetherite.class;
list[NETHERITE_SHOVEL] = ItemShovelNetherite.class;
list[NETHERITE_PICKAXE] = ItemPickaxeNetherite.class;
list[NETHERITE_AXE] = ItemAxeNetherite.class;
list[NETHERITE_HOE] = ItemHoeNetherite.class;
list[NETHERITE_HELMET] = ItemHelmetNetherite.class;
list[NETHERITE_CHESTPLATE] = ItemChestplateNetherite.class;
list[NETHERITE_LEGGINGS] = ItemLeggingsNetherite.class;
list[NETHERITE_BOOTS] = ItemBootsNetherite.class;
list[NETHERITE_SCRAP] = ItemScrapNetherite.class;
list[CRIMSON_SIGN] = ItemCrimsonSign.class;
list[WARPED_SIGN] = ItemWarpedSign.class;
list[CRIMSON_DOOR] = ItemDoorCrimson.class;
list[WARPED_DOOR] = ItemDoorWarped.class;
list[WARPED_FUNGUS_ON_A_STICK] = ItemWarpedFungusOnAStick.class;
list[CHAIN] = ItemChain.class;
list[RECORD_PIGSTEP] = ItemRecordPigstep.class;
list[NETHER_SPROUTS] = ItemNetherSprouts.class;
list[AMETHYST_SHARD] = ItemAmethystShard.class;
list[SPYGLASS] = ItemSpyglass.class;
list[SOUL_CAMPFIRE] = ItemCampfireSoul.class;
for (int i = 0 ; i < 256 ; ++i) {
if (Block.list[i] != null ) {
list[i] = Block.list[i];
}
}
RuntimeItemMapping runtimeMapping = RuntimeItems.getRuntimeMapping();
for (@SuppressWarnings ("unchecked" ) Class- aClass : list) {
if (!Item.class.equals(aClass)) {
continue ;
}
try {
Constructor- constructor = aClass.getConstructor();
Item item = constructor.newInstance();
runtimeMapping.registerNamespacedIdItem(item.getNamespaceId(), constructor);
}
catch (Exception e) {
log.warn("Failed to cache the namespaced id resolution of the item {}" , aClass, e);
}
}
runtimeMapping.registerNamespacedIdItem(ItemRawIron.class);
runtimeMapping.registerNamespacedIdItem(ItemRawGold.class);
runtimeMapping.registerNamespacedIdItem(ItemRawCopper.class);
runtimeMapping.registerNamespacedIdItem(ItemGlowInkSac.class);
runtimeMapping.registerNamespacedIdItem(ItemIngotCopper.class);
}
initCreativeItems();
}
private static List itemList;
@PowerNukkitOnly
@Since ("1.4.0.0-PN" )
public static List rebuildItemList () {
return itemList = Collections.unmodifiableList(Stream.of(
BlockStateRegistry.getPersistenceNames().stream()
.map(name -> name.substring(name.indexOf(':' ) + 1 )),
itemIds.keySet().stream()
).flatMap(Function.identity()).distinct().collect(Collectors.toList()));
}
@PowerNukkitOnly
@Since ("1.4.0.0-PN" )
public static List getItemList () {
List itemList = Item.itemList;
if (itemList == null ) {
return rebuildItemList();
}
return itemList;
}
private static final ArrayList- creative =
new ArrayList<>();
@SneakyThrows (IOException.class)
@SuppressWarnings ("unchecked" )
private static void initCreativeItems () {
clearCreativeItems();
Config config = new Config(Config.JSON);
try (InputStream resourceAsStream = Server.class.getModule().getResourceAsStream("creative_items.json" )) {
config.load(resourceAsStream);
}
List list = config.getMapList("items" );
for (Map map : list) {
try {
Item item = loadCreativeItemEntry(map);
if (item != null ) {
addCreativeItem(item);
}
} catch (Exception e) {
log.error("Error while registering a creative item {}" , map, e);
}
}
}
private static Item loadCreativeItemEntry (Map data) {
String nbt = (String) data.get("nbt_b64" );
byte [] nbtBytes = nbt != null ? Base64.getDecoder().decode(nbt) : EmptyArrays.EMPTY_BYTES;
if (data.containsKey("blockState" )) {
String blockStateId = data.get("blockState" ).toString();
try {
String[] stateParts = blockStateId.split(";" , 2 );
Integer blockId = BlockStateRegistry.getBlockId(stateParts[0 ]);
if (blockId != null && blockId > BlockID.DOUBLE_MANGROVE_SLAB) {
return Item.getBlock(BlockID.AIR);
}
BlockState state = BlockState.of(blockStateId);
Item item = state.asItemBlock();
item.setCompoundTag(nbtBytes);
return item;
} catch (BlockPropertyNotFoundException | UnknownRuntimeIdException e) {
int runtimeId = BlockStateRegistry.getKnownRuntimeIdByBlockStateId(blockStateId);
if (runtimeId == -1 ) {
log.warn("Unsupported block found in creativeitems.json: {}" , blockStateId);
return null ;
}
int blockId = BlockStateRegistry.getBlockIdByRuntimeId(runtimeId);
BlockState defaultBlockState = BlockState.of(blockId);
if (defaultBlockState.getProperties().equals(BlockUnknown.PROPERTIES)) {
log.warn("Unsupported block found in creativeitems.json: {}" , blockStateId);
return null ;
}
log.error("Failed to load the creative item with {}" , blockStateId, e);
return null ;
} catch (Exception e) {
log.error("Failed to load the creative item {}" , blockStateId, e);
return null ;
}
}
String id = data.get("id" ).toString();
Item item = null ;
if (data.containsKey("damage" )) {
int meta = Utils.toInt(data.get("damage" ));
item = fromString(id + ":" + meta);
} else if (data.containsKey("blockRuntimeId" )) {
int blockRuntimeId = -1 ;
try {
blockRuntimeId = ((Number) data.get("blockRuntimeId" )).intValue();
BlockState blockState = BlockStateRegistry.getBlockStateByRuntimeId(blockRuntimeId);
if (blockState != null ) {
item = blockState.asItemBlock();
} else {
log.warn("Block state not found for the creative item {} with runtimeId {}" , id, blockRuntimeId);
}
} catch (BlockPropertyNotFoundException e) {
log.warn("The block {} (runtime id:{}) is not supported yet!" , id, blockRuntimeId);
} catch (Throwable e) {
log.error("Error loading the creative item {} with runtimeId {}" , id, blockRuntimeId, e);
return null ;
}
}
if (item == null ) {
item = fromString(id);
}
item.setCompoundTag(nbtBytes);
return item;
}
@PowerNukkitXOnly
@Since ("1.6.0.0-PNX" )
public static void registerCustomItem (Class c) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
if (!Server.getInstance().isEnableExperimentMode() || Server.getInstance().getConfig("settings.waterdogpe" , false )) {
log.warn("The server does not have the experiment mode feature enabled. " + c.getName() + "Unable to register!" );
return ;
}
ItemCustom itemCustom = c.getDeclaredConstructor().newInstance();
if (CUSTOM_ITEMS.containsKey(itemCustom.getNamespaceId())) return ;
CUSTOM_ITEMS.put(itemCustom.getNamespaceId(), c);
CUSTOM_ITEM_DEFINITIONS.put(itemCustom.getNamespaceId(), itemCustom.getDefinition());
RuntimeItems.getRuntimeMapping().registerCustomItem(itemCustom);
addCreativeItem(itemCustom);
}
@PowerNukkitXOnly
@Since ("1.6.0.0-PNX" )
public static void registerCustomItem (@Nonnull List > itemClassList) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
if (!Server.getInstance().isEnableExperimentMode() || Server.getInstance().getConfig("settings.waterdogpe" , false )) {
log.warn("The server does not have the custom item feature enabled. Unable to register the customItemList!" );
return ;
}
for (var clazz : itemClassList) {
ItemCustom itemCustom = clazz.getDeclaredConstructor().newInstance();
if (CUSTOM_ITEMS.containsKey(itemCustom.getNamespaceId())) return ;
CUSTOM_ITEMS.put(itemCustom.getNamespaceId(), clazz);
CUSTOM_ITEM_DEFINITIONS.put(itemCustom.getNamespaceId(), itemCustom.getDefinition());
RuntimeItems.getRuntimeMapping().registerCustomItem(itemCustom);
addCreativeItem(itemCustom);
}
}
@PowerNukkitXOnly
@Since ("1.6.0.0-PNX" )
public static void deleteCustomItem (String namespaceId) {
if (CUSTOM_ITEMS.containsKey(namespaceId)) {
ItemCustom itemCustom = (ItemCustom) fromString(namespaceId);
removeCreativeItem(itemCustom);
CUSTOM_ITEMS.remove(namespaceId);
CUSTOM_ITEM_DEFINITIONS.remove(namespaceId);
RuntimeItems.getRuntimeMapping().deleteCustomItem(itemCustom);
}
}
@PowerNukkitXOnly
@Since ("1.6.0.0-PNX" )
public static void deleteAllCustomItem () {
for (String name : CUSTOM_ITEMS.keySet()) {
ItemCustom itemCustom = (ItemCustom) fromString(name);
removeCreativeItem(itemCustom);
CUSTOM_ITEMS.remove(name);
CUSTOM_ITEM_DEFINITIONS.remove(name);
RuntimeItems.getRuntimeMapping().deleteCustomItem(itemCustom);
}
}
@PowerNukkitXOnly
@Since ("1.6.0.0-PNX" )
public static HashMap> getCustomItems() {
return new HashMap<>(CUSTOM_ITEMS);
}
@PowerNukkitXOnly
@Since ("1.19.31-r1" )
public static HashMap getCustomItemDefinition () {
return new HashMap<>(CUSTOM_ITEM_DEFINITIONS);
}
public static void clearCreativeItems () {
Item.creative.clear();
}
public static ArrayList getCreativeItems () {
return new ArrayList<>(Item.creative);
}
public static void addCreativeItem (Item item) {
Item.creative.add(item.clone());
}
public static void removeCreativeItem (Item item) {
int index = getCreativeItemIndex(item);
if (index != -1 ) {
Item.creative.remove(index);
}
}
public static boolean isCreativeItem (Item item) {
for (Item aCreative : Item.creative) {
if (item.equals(aCreative, !item.isTool())) {
return true ;
}
}
return false ;
}
public static Item getCreativeItem (int index) {
return (index >= 0 && index < Item.creative.size()) ? Item.creative.get(index) : null ;
}
public static int getCreativeItemIndex (Item item) {
for (int i = 0 ; i < Item.creative.size(); i++) {
if (item.equals(Item.creative.get(i), !item.isTool())) {
return i;
}
}
return -1 ;
}
@PowerNukkitOnly
public static Item getBlock (int id) {
return getBlock(id, 0 );
}
@PowerNukkitOnly
public static Item getBlock (int id, Integer meta) {
return getBlock(id, meta, 1 );
}
@PowerNukkitOnly
public static Item getBlock (int id, Integer meta, int count) {
return getBlock(id, meta, count, EmptyArrays.EMPTY_BYTES);
}
@PowerNukkitOnly
public static Item getBlock (int id, Integer meta, int count, byte [] tags) {
if (id > 255 ) {
id = 255 - id;
}
return get(id, meta, count, tags);
}
public static Item get (int id) {
return get(id, 0 );
}
public static Item get (int id, Integer meta) {
return get(id, meta, 1 );
}
public static Item get (int id, Integer meta, int count) {
return get(id, meta, count, EmptyArrays.EMPTY_BYTES);
}
@PowerNukkitDifference (
info = "Prevents players from getting invalid items by limiting the return to the maximum damage defined in Block.getMaxItemDamage()" ,
since = "1.4.0.0-PN" )
public static Item get (int id, Integer meta, int count, byte [] tags) {
try {
Class c = null ;
if (id <= 255 - Block.MAX_BLOCK_ID) {
var customBlockItem = Block.get(255 - id).toItem();
customBlockItem.setCount(count);
customBlockItem.setDamage(meta);
customBlockItem.setCompoundTag(tags);
return customBlockItem;
} else if (id < 0 ) {
int blockId = 255 - id;
c = Block.list[blockId];
} else {
c = list[id];
}
Item item;
if (id < 256 ) {
int blockId = id < 0 ? 255 - id : id;
if (meta == 0 ) {
item = new ItemBlock(Block.get(blockId), 0 , count);
} else if (meta == -1 ) {
item = new ItemBlock(Block.get(blockId), -1 );
} else {
BlockState state = BlockState.of(blockId, meta);
try {
state.validate();
item = state.asItemBlock(count);
} catch (InvalidBlockPropertyMetaException | InvalidBlockStateException e) {
log.warn("Attempted to get an ItemBlock with invalid block state in memory: {}, trying to repair the block state..." , state);
log.catching(org.apache.logging.log4j.Level.DEBUG, e);
Block repaired = state.getBlockRepairing(null , 0 , 0 , 0 );
item = repaired.asItemBlock(count);
log.error("Attempted to get an illegal item block {}:{} ({}), the meta was changed to {}" ,
id, meta, blockId, item.getDamage(), e);
} catch (UnknownRuntimeIdException e) {
log.warn("Attempted to get an illegal item block {}:{} ({}), the runtime id was unknown and the meta was changed to 0" ,
id, meta, blockId, e);
item = BlockState.of(blockId).asItemBlock(count);
}
}
} else if (c == null ) {
item = new Item(id, meta, count);
} else {
if (meta == -1 ) {
item = ((Item) c.getConstructor(Integer.class, int .class).newInstance(0 , count)).createFuzzyCraftingRecipe();
} else {
item = ((Item) c.getConstructor(Integer.class, int .class).newInstance(meta, count));
}
}
if (tags.length != 0 ) {
item.setCompoundTag(tags);
}
return item;
} catch (Exception e) {
log.error("Error getting the item {}:{}{}! Returning an unsafe item stack!" ,
id, meta, id < 0 ? " (" + (255 - id) + ")" : "" , e);
return new Item(id, meta, count).setCompoundTag(tags);
}
}
@PowerNukkitDifference (since = "1.4.0.0-PN" , info = "Improve namespaced name handling and allows to get custom blocks by name" )
public static Item fromString (String str) {
String normalized = str.trim().replace(' ' , '_' ).toLowerCase();
Matcher matcher = ITEM_STRING_PATTERN.matcher(normalized);
if (!matcher.matches()) {
return get(AIR);
}
String name = matcher.group(2 );
OptionalInt meta = OptionalInt.empty();
String metaGroup;
if (name != null ) {
metaGroup = matcher.group(3 );
} else {
metaGroup = matcher.group(5 );
}
if (metaGroup != null ) {
meta = OptionalInt.of(Short.parseShort(metaGroup));
}
String numericIdGroup = matcher.group(4 );
if (name != null ) {
String namespaceGroup = matcher.group(1 );
String namespacedId;
if (namespaceGroup != null ) {
namespacedId = namespaceGroup + ":" + name;
} else {
namespacedId = "minecraft:" + name;
}
if (namespacedId.equals("minecraft:air" )) {
return get(AIR);
}
if (CUSTOM_ITEMS.containsKey(namespacedId)) {
var item = RuntimeItems.getRuntimeMapping().getItemByNamespaceId(namespacedId, 1 );
ItemCustom itemCustom;
if (item.getName() != null && item.getName().equals(Item.UNKNOWN_STR)) {
try {
itemCustom = (ItemCustom) CUSTOM_ITEMS.get(namespacedId).getDeclaredConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | InvocationTargetException |
NoSuchMethodException e) {
throw new RuntimeException(e);
}
} else itemCustom = (ItemCustom) item;
if (meta.isPresent()) {
int damage = meta.getAsInt();
if (damage < 0 ) {
itemCustom = (ItemCustom) itemCustom.createFuzzyCraftingRecipe();
} else {
itemCustom.setDamage(damage);
}
}
return itemCustom;
} else if (Block.CUSTOM_BLOCK_ID_MAP.containsKey(namespacedId)) {
ItemBlock customItemBlock = (ItemBlock) RuntimeItems.getRuntimeMapping().getItemByNamespaceId(namespacedId, 1 );
if (meta.isPresent()) {
int damage = meta.getAsInt();
if (damage < 0 ) {
customItemBlock = (ItemBlock) customItemBlock.createFuzzyCraftingRecipe();
} else {
customItemBlock.setDamage(damage);
}
}
return customItemBlock;
}
MinecraftItemID minecraftItemId = MinecraftItemID.getByNamespaceId(namespacedId);
if (minecraftItemId != null ) {
Item item = minecraftItemId.get(1 );
if (meta.isPresent()) {
int damage = meta.getAsInt();
if (damage < 0 ) {
item = item.createFuzzyCraftingRecipe();
} else {
item.setDamage(damage);
}
}
return item;
} else if (namespaceGroup != null && !namespaceGroup.equals("minecraft:" )) {
return get(AIR);
}
} else if (numericIdGroup != null ) {
int id = Integer.parseInt(numericIdGroup);
return get(id, meta.orElse(0 ));
}
if (name == null ) {
return get(AIR);
}
int id = 0 ;
try {
id = ItemID.class.getField(name.toUpperCase()).getInt(null );
} catch (Exception ignore1) {
try {
id = BlockID.class.getField(name.toUpperCase()).getInt(null );
if (id > 255 ) {
id = 255 - id;
}
} catch (Exception ignore2) {
}
}
return get(id, meta.orElse(0 ));
}
public static Item fromJson (Map data) {
return fromJson(data, false );
}
private static Item fromJson (Map data, boolean ignoreNegativeItemId) {
String nbt = (String) data.get("nbt_b64" );
byte [] nbtBytes;
if (nbt != null ) {
nbtBytes = Base64.getDecoder().decode(nbt);
} else {
nbt = (String) data.getOrDefault("nbt_hex" , null );
if (nbt == null ) {
nbtBytes = EmptyArrays.EMPTY_BYTES;
} else {
nbtBytes = Utils.parseHexBinary(nbt);
}
}
int id = Utils.toInt(data.get("id" ));
if (ignoreNegativeItemId && id < 0 ) return null ;
return get(id, Utils.toInt(data.getOrDefault("damage" , 0 )), Utils.toInt(data.getOrDefault("count" , 1 )), nbtBytes);
}
@PowerNukkitOnly
@Since ("1.4.0.0-PN" )
public static Item fromJsonNetworkId (Map data) {
String nbt = (String) data.get("nbt_b64" );
byte [] nbtBytes;
if (nbt != null ) {
nbtBytes = Base64.getDecoder().decode(nbt);
} else {
nbt = (String) data.getOrDefault("nbt_hex" , null );
if (nbt == null ) {
nbtBytes = EmptyArrays.EMPTY_BYTES;
} else {
nbtBytes = Utils.parseHexBinary(nbt);
}
}
int networkId = Utils.toInt(data.get("id" ));
RuntimeItemMapping mapping = RuntimeItems.getRuntimeMapping();
int legacyFullId = mapping.getLegacyFullId(networkId);
int id = RuntimeItems.getId(legacyFullId);
OptionalInt meta = RuntimeItems.hasData(legacyFullId) ? OptionalInt.of(RuntimeItems.getData(legacyFullId)) : OptionalInt.empty();
if (data.containsKey("damage" )) {
int jsonMeta = Utils.toInt(data.get("damage" ));
if (jsonMeta != Short.MAX_VALUE) {
if (meta.isPresent() && jsonMeta != meta.getAsInt()) {
throw new IllegalArgumentException(
"Conflicting damage value for " + mapping.getNamespacedIdByNetworkId(networkId) + ". " +
"From json: " + jsonMeta + ", from mapping: " + meta.getAsInt()
);
}
meta = OptionalInt.of(jsonMeta);
} else if (!meta.isPresent()) {
meta = OptionalInt.of(-1 );
}
}
return get(id, meta.orElse(0 ), Utils.toInt(data.getOrDefault("count" , 1 )), nbtBytes);
}
public static Item[] fromStringMultiple(String str) {
String[] b = str.split("," );
Item[] items = new Item[b.length - 1 ];
for (int i = 0 ; i < b.length; i++) {
items[i] = fromString(b[i]);
}
return items;
}
public Item setCompoundTag (CompoundTag tag) {
this .setNamedTag(tag);
return this ;
}
public Item setCompoundTag (byte [] tags) {
this .tags = tags;
this .cachedNBT = null ;
return this ;
}
public byte [] getCompoundTag() {
return tags;
}
public boolean hasCompoundTag () {
return this .tags != null && this .tags.length > 0 ;
}
@PowerNukkitOnly
@Since ("FUTURE" )
public boolean hasCustomCompoundTag () {
return hasCompoundTag();
}
@PowerNukkitOnly
@Since ("FUTURE" )
public byte [] getCustomCompoundTag() {
return getCompoundTag();
}
public boolean hasCustomBlockData () {
if (!this .hasCompoundTag()) {
return false ;
}
CompoundTag tag = this .getNamedTag();
return tag.contains("BlockEntityTag" ) && tag.get("BlockEntityTag" ) instanceof CompoundTag;
}
public Item clearCustomBlockData () {
if (!this .hasCompoundTag()) {
return this ;
}
CompoundTag tag = this .getNamedTag();
if (tag.contains("BlockEntityTag" ) && tag.get("BlockEntityTag" ) instanceof CompoundTag) {
tag.remove("BlockEntityTag" );
this .setNamedTag(tag);
}
return this ;
}
public Item setCustomBlockData (CompoundTag compoundTag) {
CompoundTag tags = compoundTag.copy();
tags.setName("BlockEntityTag" );
CompoundTag tag;
if (!this .hasCompoundTag()) {
tag = new CompoundTag();
} else {
tag = this .getNamedTag();
}
tag.putCompound("BlockEntityTag" , tags);
this .setNamedTag(tag);
return this ;
}
public CompoundTag getCustomBlockData () {
if (!this .hasCompoundTag()) {
return null ;
}
CompoundTag tag = this .getNamedTag();
if (tag.contains("BlockEntityTag" )) {
Tag bet = tag.get("BlockEntityTag" );
if (bet instanceof CompoundTag) {
return (CompoundTag) bet;
}
}
return null ;
}
@PowerNukkitXOnly
@Since ("1.6.0.0-PNX" )
public boolean applyEnchantments () {
return true ;
}
public boolean hasEnchantments () {
if (!this .hasCompoundTag()) {
return false ;
}
CompoundTag tag = this .getNamedTag();
if (tag.contains("ench" )) {
Tag enchTag = tag.get("ench" );
return enchTag instanceof ListTag;
}
return false ;
}
@PowerNukkitOnly
@Since ("1.4.0.0-PN" )
public int getEnchantmentLevel (int id) {
if (!this .hasEnchantments()) {
return 0 ;
}
for (CompoundTag entry : this .getNamedTag().getList("ench" , CompoundTag.class).getAll()) {
if (entry.getShort("id" ) == id) {
return entry.getShort("lvl" );
}
}
return 0 ;
}
public Enchantment getEnchantment (int id) {
return getEnchantment((short ) (id & 0xffff ));
}
public Enchantment getEnchantment (short id) {
if (!this .hasEnchantments()) {
return null ;
}
for (CompoundTag entry : this .getNamedTag().getList("ench" , CompoundTag.class).getAll()) {
if (entry.getShort("id" ) == id) {
Enchantment e = Enchantment.getEnchantment(entry.getShort("id" ));
if (e != null ) {
e.setLevel(entry.getShort("lvl" ), false );
return e;
}
}
}
return null ;
}
public void addEnchantment (Enchantment... enchantments) {
CompoundTag tag;
if (!this .hasCompoundTag()) {
tag = new CompoundTag();
} else {
tag = this .getNamedTag();
}
ListTag ench;
if (!tag.contains("ench" )) {
ench = new ListTag<>("ench" );
tag.putList(ench);
} else {
ench = tag.getList("ench" , CompoundTag.class);
}
for (Enchantment enchantment : enchantments) {
boolean found = false ;
for (int k = 0 ; k < ench.size(); k++) {
CompoundTag entry = ench.get(k);
if (entry.getShort("id" ) == enchantment.getId()) {
ench.add(k, new CompoundTag()
.putShort("id" , enchantment.getId())
.putShort("lvl" , enchantment.getLevel())
);
found = true ;
break ;
}
}
if (!found) {
ench.add(new CompoundTag()
.putShort("id" , enchantment.getId())
.putShort("lvl" , enchantment.getLevel())
);
}
}
this .setNamedTag(tag);
}
public Enchantment[] getEnchantments() {
if (!this .hasEnchantments()) {
return Enchantment.EMPTY_ARRAY;
}
List enchantments = new ArrayList<>();
ListTag ench = this .getNamedTag().getList("ench" , CompoundTag.class);
for (CompoundTag entry : ench.getAll()) {
Enchantment e = Enchantment.getEnchantment(entry.getShort("id" ));
if (e != null ) {
e.setLevel(entry.getShort("lvl" ), false );
enchantments.add(e);
}
}
return enchantments.toArray(Enchantment.EMPTY_ARRAY);
}
@Since ("1.4.0.0-PN" )
public boolean hasEnchantment (int id) {
return this .getEnchantmentLevel(id) > 0 ;
}
@PowerNukkitOnly
@Since ("1.5.1.0-PN" )
@Nonnull
public SideEffect[] getAttackSideEffects(@Nonnull Entity attacker, @Nonnull Entity entity) {
return Arrays.stream(getEnchantments())
.flatMap(enchantment -> Arrays.stream(enchantment.getAttackSideEffects(attacker, entity)))
.filter(Objects::nonNull)
.toArray(SideEffect[]::new )
;
}
@Since ("1.4.0.0-PN" )
public int getRepairCost () {
if (this .hasCompoundTag()) {
CompoundTag tag = this .getNamedTag();
if (tag.contains("RepairCost" )) {
Tag repairCost = tag.get("RepairCost" );
if (repairCost instanceof IntTag) {
return ((IntTag) repairCost).data;
}
}
}
return 0 ;
}
@Since ("1.4.0.0-PN" )
public Item setRepairCost (int cost) {
if (cost <= 0 && this .hasCompoundTag()) {
return this .setNamedTag(this .getNamedTag().remove("RepairCost" ));
}
CompoundTag tag;
if (!this .hasCompoundTag()) {
tag = new CompoundTag();
} else {
tag = this .getNamedTag();
}
return this .setNamedTag(tag.putInt("RepairCost" , cost));
}
public boolean hasCustomName () {
if (!this .hasCompoundTag()) {
return false ;
}
CompoundTag tag = this .getNamedTag();
if (tag.contains("display" )) {
Tag tag1 = tag.get("display" );
return tag1 instanceof CompoundTag && ((CompoundTag) tag1).contains("Name" ) && ((CompoundTag) tag1).get("Name" ) instanceof StringTag;
}
return false ;
}
public String getCustomName () {
if (!this .hasCompoundTag()) {
return "" ;
}
CompoundTag tag = this .getNamedTag();
if (tag.contains("display" )) {
Tag tag1 = tag.get("display" );
if (tag1 instanceof CompoundTag && ((CompoundTag) tag1).contains("Name" ) && ((CompoundTag) tag1).get("Name" ) instanceof StringTag) {
return ((CompoundTag) tag1).getString("Name" );
}
}
return "" ;
}
public Item setCustomName (String name) {
if (name == null || name.equals("" )) {
this .clearCustomName();
}
CompoundTag tag;
if (!this .hasCompoundTag()) {
tag = new CompoundTag();
} else {
tag = this .getNamedTag();
}
if (tag.contains("display" ) && tag.get("display" ) instanceof CompoundTag) {
tag.getCompound("display" ).putString("Name" , name);
} else {
tag.putCompound("display" , new CompoundTag("display" )
.putString("Name" , name)
);
}
this .setNamedTag(tag);
return this ;
}
public Item clearCustomName () {
if (!this .hasCompoundTag()) {
return this ;
}
CompoundTag tag = this .getNamedTag();
if (tag.contains("display" ) && tag.get("display" ) instanceof CompoundTag) {
tag.getCompound("display" ).remove("Name" );
if (tag.getCompound("display" ).isEmpty()) {
tag.remove("display" );
}
this .setNamedTag(tag);
}
return this ;
}
public String[] getLore() {
Tag tag = this .getNamedTagEntry("display" );
ArrayList lines = new ArrayList<>();
if (tag instanceof CompoundTag) {
CompoundTag nbt = (CompoundTag) tag;
ListTag lore = nbt.getList("Lore" , StringTag.class);
if (lore.size() > 0 ) {
for (StringTag stringTag : lore.getAll()) {
lines.add(stringTag.data);
}
}
}
return lines.toArray(EmptyArrays.EMPTY_STRINGS);
}
public Item setLore (String... lines) {
CompoundTag tag;
if (!this .hasCompoundTag()) {
tag = new CompoundTag();
} else {
tag = this .getNamedTag();
}
ListTag lore = new ListTag<>("Lore" );
for (String line : lines) {
lore.add(new StringTag("" , line));
}
if (!tag.contains("display" )) {
tag.putCompound("display" , new CompoundTag("display" ).putList(lore));
} else {
tag.getCompound("display" ).putList(lore);
}
this .setNamedTag(tag);
return this ;
}
public Tag getNamedTagEntry (String name) {
CompoundTag tag = this .getNamedTag();
if (tag != null ) {
return tag.contains(name) ? tag.get(name) : null ;
}
return null ;
}
public CompoundTag getNamedTag () {
if (!this .hasCompoundTag()) {
return null ;
}
if (this .cachedNBT == null ) {
this .cachedNBT = parseCompoundTag(this .tags);
}
if (this .cachedNBT != null ) {
this .cachedNBT.setName("" );
}
return this .cachedNBT;
}
public CompoundTag getOrCreateNamedTag () {
if (!hasCompoundTag()) {
return new CompoundTag();
}
return getNamedTag();
}
public Item setNamedTag (CompoundTag tag) {
if (tag.isEmpty()) {
return this .clearNamedTag();
}
tag.setName(null );
this .cachedNBT = tag;
this .tags = writeCompoundTag(tag);
return this ;
}
public Item clearNamedTag () {
return this .setCompoundTag(EmptyArrays.EMPTY_BYTES);
}
public static CompoundTag parseCompoundTag (byte [] tag) {
try {
return NBTIO.read(tag, ByteOrder.LITTLE_ENDIAN);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public byte [] writeCompoundTag(CompoundTag tag) {
try {
tag.setName("" );
return NBTIO.write(tag, ByteOrder.LITTLE_ENDIAN);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public int getCount () {
return count;
}
public void setCount (int count) {
this .count = count;
}
public boolean isNull () {
return this .count <= 0 || this .id == AIR || this .id == STRING_IDENTIFIED_ITEM && !(this instanceof StringItem);
}
final public String getName () {
return this .hasCustomName() ? this .getCustomName() : this .name;
}
final public boolean canBePlaced () {
return ((this .block != null ) && this .block.canBePlaced());
}
public Block getBlock () {
if (this .block != null ) {
return this .block.clone();
} else {
return Block.get(BlockID.AIR);
}
}
@Since ("1.4.0.0-PN" )
@API (definition = API.Definition.INTERNAL, usage = API.Usage.INCUBATING)
public Block getBlockUnsafe () {
return this .block;
}
public int getId () {
return id;
}
@PowerNukkitOnly
@Since ("1.4.0.0-PN" )
public final int getNetworkFullId () throws UnknownNetworkIdException {
try {
return RuntimeItems.getRuntimeMapping().getNetworkFullId(this );
} catch (IllegalArgumentException e) {
throw new UnknownNetworkIdException(this , e);
}
}
@PowerNukkitOnly
@Since ("1.4.0.0-PN" )
public String getNamespaceId () {
RuntimeItemMapping runtimeMapping = RuntimeItems.getRuntimeMapping();
return runtimeMapping.getNamespacedIdByNetworkId(
RuntimeItems.getNetworkId(runtimeMapping.getNetworkFullId(this ))
);
}
@PowerNukkitOnly
@Since ("1.4.0.0-PN" )
public int getBlockId () {
if (block != null ) {
return block.getId();
} else {
return -1 ;
}
}
public int getDamage () {
return meta;
}
public void setDamage (Integer meta) {
if (meta != null ) {
this .meta = meta & 0xffff ;
} else {
this .hasMeta = false ;
}
}
@PowerNukkitOnly
@Since ("1.4.0.0-PN" )
public Item createFuzzyCraftingRecipe () {
Item item = clone();
item.hasMeta = false ;
return item;
}
public int getMaxStackSize () {
return block == null ? 64 : block.getItemMaxStackSize();
}
final public Short getFuelTime () {
if (!Fuel.duration.containsKey(id)) {
return null ;
}
if (this .id != BUCKET || this .meta == 10 ) {
return Fuel.duration.get(this .id);
}
return null ;
}
public boolean useOn (Entity entity) {
return false ;
}
public boolean useOn (Block block) {
return false ;
}
public boolean isTool () {
return false ;
}
public int getMaxDurability () {
return -1 ;
}
public int getTier () {
return 0 ;
}
public boolean isPickaxe () {
return false ;
}
public boolean isAxe () {
return false ;
}
public boolean isSword () {
return false ;
}
public boolean isShovel () {
return false ;
}
public boolean isHoe () {
return false ;
}
public boolean isShears () {
return false ;
}
public boolean isArmor () {
return false ;
}
public boolean isHelmet () {
return false ;
}
public boolean isChestplate () {
return false ;
}
public boolean isLeggings () {
return false ;
}
public boolean isBoots () {
return false ;
}
public int getEnchantAbility () {
return 0 ;
}
public int getAttackDamage () {
return 1 ;
}
public int getArmorPoints () {
return 0 ;
}
public int getToughness () {
return 0 ;
}
public boolean isUnbreakable () {
return false ;
}
@PowerNukkitOnly
@Since ("1.4.0.0-PN" )
public boolean isLavaResistant () {
return false ;
}
@PowerNukkitXOnly
@Since ("1.19.21-r4" )
public boolean canBreakShield () {
return false ;
}
public boolean onUse (Player player, int ticksUsed) {
return false ;
}
public boolean onRelease (Player player, int ticksUsed) {
return false ;
}
@Override
final public String toString () {
return "Item " + this .name +
" (" + (this instanceof StringItem ? this .getNamespaceId() : this .id)
+ ":" + (!this .hasMeta ? "?" : this .meta)
+ ")x" + this .count
+ (this .hasCustomCompoundTag() ? " tags:0x" + Binary.bytesToHexString(this .getCustomCompoundTag()) : "" );
}
public int getDestroySpeed (Block block, Player player) {
return 1 ;
}
public boolean onActivate (Level level, Player player, Block block, Block target, BlockFace face, double fx, double fy, double fz) {
return false ;
}
@PowerNukkitOnly
@Since ("1.4.0.0-PN" )
public final Item decrement (int amount) {
return increment(-amount);
}
@PowerNukkitOnly
@Since ("1.4.0.0-PN" )
public final Item increment (int amount) {
if (count + amount <= 0 ) {
return getBlock(BlockID.AIR);
}
Item cloned = clone();
cloned.count += amount;
return cloned;
}
@Since ("1.4.0.0-PN" )
@PowerNukkitOnly
public boolean isFertilizer () {
return false ;
}
public boolean onClickAir (Player player, Vector3 directionVector) {
return false ;
}
@Override
public final boolean equals (Object item) {
return item instanceof Item && this .equals((Item) item, true );
}
public final boolean equals (Item item, boolean checkDamage) {
return equals(item, checkDamage, true );
}
public final boolean equals (Item item, boolean checkDamage, boolean checkCompound) {
if (this .getId() == item.getId() && (!checkDamage || this .getDamage() == item.getDamage())) {
if (checkCompound) {
if (Arrays.equals(this .getCompoundTag(), item.getCompoundTag())) {
return true ;
} else if (this .hasCompoundTag() && item.hasCompoundTag()) {
return this .getNamedTag().equals(item.getNamedTag());
}
} else {
return true ;
}
}
return false ;
}
public final boolean equalsExact (Item other) {
return this .equals(other, true , true ) && this .count == other.count;
}
@PowerNukkitOnly
@Since ("1.2.1.0-PN" )
public final boolean equalsIgnoringEnchantmentOrder (Item item, boolean checkDamage) {
if (!this .equals(item, checkDamage, false )) {
return false ;
}
if (Arrays.equals(this .getCompoundTag(), item.getCompoundTag())) {
return true ;
}
if (!this .hasCompoundTag() || !item.hasCompoundTag()) {
return false ;
}
CompoundTag thisTags = this .getNamedTag();
CompoundTag otherTags = item.getNamedTag();
if (thisTags.equals(otherTags)) {
return true ;
}
if (!thisTags.contains("ench" ) || !otherTags.contains("ench" )
|| !(thisTags.get("ench" ) instanceof ListTag)
|| !(otherTags.get("ench" ) instanceof ListTag)
|| thisTags.getList("ench" ).size() != otherTags.getList("ench" ).size()) {
return false ;
}
ListTag thisEnchantmentTags = thisTags.getList("ench" , CompoundTag.class);
ListTag otherEnchantmentTags = otherTags.getList("ench" , CompoundTag.class);
int size = thisEnchantmentTags.size();
Int2IntMap enchantments = new Int2IntArrayMap(size);
enchantments.defaultReturnValue(Integer.MIN_VALUE);
for (int i = 0 ; i < size; i++) {
CompoundTag tag = thisEnchantmentTags.get(i);
enchantments.put(tag.getShort("id" ), tag.getShort("lvl" ));
}
for (int i = 0 ; i < size; i++) {
CompoundTag tag = otherEnchantmentTags.get(i);
if (enchantments.get(tag.getShort("id" )) != tag.getShort("lvl" )) {
return false ;
}
}
return true ;
}
@Deprecated
public final boolean deepEquals (Item item) {
return equals(item, true );
}
@Deprecated
public final boolean deepEquals (Item item, boolean checkDamage) {
return equals(item, checkDamage, true );
}
@Deprecated
public final boolean deepEquals (Item item, boolean checkDamage, boolean checkCompound) {
return equals(item, checkDamage, checkCompound);
}
@Override
public Item clone () {
try {
Item item = (Item) super .clone();
item.tags = this .tags.clone();
item.cachedNBT = null ;
return item;
} catch (CloneNotSupportedException e) {
return null ;
}
}
@Since ("1.4.0.0-PN" )
public final int getNetworkId () throws UnknownNetworkIdException {
return RuntimeItems.getNetworkId(getNetworkFullId());
}
@PowerNukkitXOnly
@Since ("1.6.0.0-PNX" )
public void addCanPlaceOn (Block block) {
CompoundTag tag = getOrCreateNamedTag();
ListTag canPlaceOn = tag.getList("CanPlaceOn" , StringTag.class);
tag.putList(canPlaceOn.add(new StringTag("" , block.toItem().getNamespaceId())));
this .setCompoundTag(tag);
}
@PowerNukkitXOnly
@Since ("1.6.0.0-PNX" )
public void addCanPlaceOn (Block[] blocks) {
for (Block block : blocks) {
addCanPlaceOn(block);
}
}
@PowerNukkitXOnly
@Since ("1.6.0.0-PNX" )
public void setCanPlaceOn (Block[] blocks) {
CompoundTag tag = getOrCreateNamedTag();
ListTag canPlaceOn = new ListTag<>("CanPlaceOn" );
for (Block block : blocks) {
canPlaceOn.add(new StringTag("" , block.toItem().getNamespaceId()));
}
tag.putList(canPlaceOn);
this .setCompoundTag(tag);
}
@PowerNukkitXOnly
@Since ("1.6.0.0-PNX" )
public ListTag getCanPlaceOn () {
CompoundTag tag = getOrCreateNamedTag();
return tag.getList("CanPlaceOn" , StringTag.class);
}
@PowerNukkitXOnly
@Since ("1.6.0.0-PNX" )
public void addCanDestroy (Block block) {
CompoundTag tag = getOrCreateNamedTag();
ListTag canDestroy = tag.getList("CanDestroy" , StringTag.class);
tag.putList(canDestroy.add(new StringTag("" , block.toItem().getNamespaceId())));
this .setCompoundTag(tag);
}
@PowerNukkitXOnly
@Since ("1.6.0.0-PNX" )
public void addCanDestroy (Block[] blocks) {
for (Block block : blocks) {
addCanDestroy(block);
}
}
@PowerNukkitXOnly
@Since ("1.6.0.0-PNX" )
public void setCanDestroy (Block[] blocks) {
CompoundTag tag = getOrCreateNamedTag();
ListTag canDestroy = new ListTag<>("CanDestroy" );
for (Block block : blocks) {
canDestroy.add(new StringTag("" , block.toItem().getNamespaceId()));
}
tag.putList(canDestroy);
this .setCompoundTag(tag);
}
@PowerNukkitXOnly
@Since ("1.6.0.0-PNX" )
public ListTag getCanDestroy () {
CompoundTag tag = getOrCreateNamedTag();
return tag.getList("CanDestroy" , StringTag.class);
}
@PowerNukkitXOnly
@Since ("1.6.0.0-PNX" )
public enum ItemLockMode {
NONE,
LOCK_IN_SLOT,
LOCK_IN_INVENTORY
}
@PowerNukkitXOnly
@Since ("1.6.0.0-PNX" )
public void setItemLockMode (ItemLockMode mode) {
CompoundTag tag = getOrCreateNamedTag();
if (mode == ItemLockMode.NONE) {
tag.remove("minecraft:item_lock" );
} else {
tag.putByte("minecraft:item_lock" , mode.ordinal());
}
this .setCompoundTag(tag);
}
@PowerNukkitXOnly
@Since ("1.6.0.0-PNX" )
public ItemLockMode getItemLockMode () {
CompoundTag tag = getOrCreateNamedTag();
if (tag.contains("minecraft:item_lock" )) {
return ItemLockMode.values()[tag.getByte("minecraft:item_lock" )];
}
return ItemLockMode.NONE;
}
@PowerNukkitXOnly
@Since ("1.6.0.0-PNX" )
public void setKeepOnDeath (boolean keepOnDeath) {
CompoundTag tag = getOrCreateNamedTag();
if (keepOnDeath) {
tag.putByte("minecraft:keep_on_death" , 1 );
} else {
tag.remove("minecraft:keep_on_death" );
}
this .setCompoundTag(tag);
}
@PowerNukkitXOnly
@Since ("1.6.0.0-PNX" )
public boolean keepOnDeath () {
CompoundTag tag = getOrCreateNamedTag();
return tag.contains("minecraft:keep_on_death" );
}
@PowerNukkitXOnly
@Since ("1.6.0.0-PNX" )
public static class ItemJsonComponents {
private static Gson gson = new Gson();
public static class CanPlaceOn {
public String[] blocks;
}
public static class CanDestory {
public String[] blocks;
}
public static class ItemLock {
public static final String LOCK_IN_INVENTORY = "lock_in_inventory" ;
public static final String LOCK_IN_SLOT = "lock_in_slot" ;
String mode;
}
public static ItemJsonComponents fromJson (String json) {
return gson.fromJson(json, ItemJsonComponents.class);
}
public static class KeepOnDeath {
}
private ItemJsonComponents () {
}
@SerializedName (value = "minecraft:can_place_on" , alternate = {"can_place_on" })
public CanPlaceOn canPlaceOn;
@SerializedName (value = "minecraft:can_destroy" , alternate = {"can_destroy" })
public CanDestory canDestroy;
@SerializedName (value = "minecraft:item_lock" , alternate = {"item_lock" })
public ItemLock itemLock;
@SerializedName (value = "minecraft:keep_on_death" , alternate = {"keep_on_death" })
public KeepOnDeath keepOnDeath;
}
@PowerNukkitXOnly
@Since ("1.6.0.0-PNX" )
public void readItemJsonComponents (ItemJsonComponents components) {
if (components.canPlaceOn != null )
this .setCanPlaceOn(Arrays.stream(components.canPlaceOn.blocks).map(str -> Block.get(BlockStateRegistry.getBlockId(str.startsWith("minecraft:" ) ? str : "minecraft:" + str))).collect(Collectors.toList()).toArray(new Block[0 ]));
if (components.canDestroy != null )
this .setCanDestroy(Arrays.stream(components.canDestroy.blocks).map(str -> Block.get(BlockStateRegistry.getBlockId(str.startsWith("minecraft:" ) ? str : "minecraft:" + str))).collect(Collectors.toList()).toArray(new Block[0 ]));
if (components.itemLock != null )
this .setItemLockMode(switch (components.itemLock.mode) {
case ItemJsonComponents.ItemLock.LOCK_IN_SLOT -> Item.ItemLockMode.LOCK_IN_SLOT;
case ItemJsonComponents.ItemLock.LOCK_IN_INVENTORY -> Item.ItemLockMode.LOCK_IN_INVENTORY;
default -> Item.ItemLockMode.NONE;
});
if (components.keepOnDeath != null )
this .setKeepOnDeath(components.keepOnDeath != null );
}
}