getMagicNumber(), $skullType->getDisplayName(), $skullType)); } /** @var int[]|\SplObjectStorage $dyeMap */ $dyeMap = new \SplObjectStorage(); $dyeMap[DyeColor::BLACK()] = 16; $dyeMap[DyeColor::BROWN()] = 17; $dyeMap[DyeColor::BLUE()] = 18; $dyeMap[DyeColor::WHITE()] = 19; foreach(DyeColor::getAll() as $color){ //TODO: use colour object directly //TODO: add interface to dye-colour objects self::register(new Dye(ItemIds::DYE, $dyeMap[$color] ?? $color->getInvertedMagicNumber(), $color->getDisplayName() . " Dye", $color)); self::register(new Bed(ItemIds::BED, $color->getMagicNumber(), $color->getDisplayName() . " Bed", $color)); self::register(new Banner(ItemIds::BANNER, $color->getInvertedMagicNumber(), $color->getDisplayName() . " Banner", $color)); } foreach(Potion::ALL as $type){ self::register(new Potion(ItemIds::POTION, $type, "Potion")); self::register(new SplashPotion(ItemIds::SPLASH_POTION, $type, "Splash Potion")); } foreach(EntityFactory::getKnownTypes() as $className){ /** @var Living|string $className */ if(is_a($className, Living::class, true) and $className::NETWORK_ID !== -1){ self::register(new SpawnEgg(ItemIds::SPAWN_EGG, $className::NETWORK_ID, "Spawn Egg", $className)); } } foreach(TreeType::getAll() as $type){ self::register(new Boat(ItemIds::BOAT, $type->getMagicNumber(), $type->getDisplayName() . " Boat", $type)); } //region --- auto-generated TODOs --- //TODO: minecraft:armor_stand //TODO: minecraft:balloon //TODO: minecraft:banner_pattern //TODO: minecraft:campfire //TODO: minecraft:carrotOnAStick //TODO: minecraft:chest_minecart //TODO: minecraft:command_block_minecart //TODO: minecraft:crossbow //TODO: minecraft:elytra //TODO: minecraft:emptyMap //TODO: minecraft:enchanted_book //TODO: minecraft:end_crystal //TODO: minecraft:ender_eye //TODO: minecraft:fireball //TODO: minecraft:fireworks //TODO: minecraft:fireworksCharge //TODO: minecraft:glow_stick //TODO: minecraft:hopper_minecart //TODO: minecraft:horsearmordiamond //TODO: minecraft:horsearmorgold //TODO: minecraft:horsearmoriron //TODO: minecraft:horsearmorleather //TODO: minecraft:ice_bomb //TODO: minecraft:kelp //TODO: minecraft:lead //TODO: minecraft:lingering_potion //TODO: minecraft:map //TODO: minecraft:medicine //TODO: minecraft:name_tag //TODO: minecraft:phantom_membrane //TODO: minecraft:rapid_fertilizer //TODO: minecraft:record_11 //TODO: minecraft:record_13 //TODO: minecraft:record_blocks //TODO: minecraft:record_cat //TODO: minecraft:record_chirp //TODO: minecraft:record_far //TODO: minecraft:record_mall //TODO: minecraft:record_mellohi //TODO: minecraft:record_stal //TODO: minecraft:record_strad //TODO: minecraft:record_wait //TODO: minecraft:record_ward //TODO: minecraft:saddle //TODO: minecraft:shield //TODO: minecraft:sparkler //TODO: minecraft:spawn_egg //TODO: minecraft:sweet_berries //TODO: minecraft:tnt_minecart //TODO: minecraft:trident //TODO: minecraft:turtle_helmet //endregion } /** * Registers an item type into the index. Plugins may use this method to register new item types or override existing * ones. * * NOTE: If you are registering a new item type, you will need to add it to the creative inventory yourself - it * will not automatically appear there. * * @param Item $item * @param bool $override * * @throws \RuntimeException if something attempted to override an already-registered item without specifying the * $override parameter. */ public static function register(Item $item, bool $override = false) : void{ $id = $item->getId(); $variant = $item->getMeta(); if(!$override and self::isRegistered($id, $variant)){ throw new \RuntimeException("Trying to overwrite an already registered item"); } self::$list[self::getListOffset($id, $variant)] = clone $item; } /** * Returns an instance of the Item with the specified id, meta, count and NBT. * * @param int $id * @param int $meta * @param int $count * @param CompoundTag|null $tags * * @return Item * @throws \InvalidArgumentException */ public static function get(int $id, int $meta = 0, int $count = 1, ?CompoundTag $tags = null) : Item{ /** @var Item $item */ $item = null; if($meta !== -1){ if(isset(self::$list[$offset = self::getListOffset($id, $meta)])){ $item = clone self::$list[$offset]; }elseif(isset(self::$list[$zero = self::getListOffset($id, 0)]) and self::$list[$zero] instanceof Durable){ /** @var Durable $item */ $item = clone self::$list[$zero]; $item->setDamage($meta); }elseif($id < 256){ //intentionally includes negatives, for extended block IDs $item = new ItemBlock($id, $meta); } } if($item === null){ //negative damage values will fallthru to here, to avoid crazy shit with crafting wildcard hacks $item = new Item($id, $meta); } $item->setCount($count); if($tags !== null){ $item->setNamedTag($tags); } return $item; } /** * Tries to parse the specified string into Item types. * * Example accepted formats: * - `diamond_pickaxe:5` * - `minecraft:string` * - `351:4 (lapis lazuli ID:meta)` * * @param string $str * * @return Item * * @throws \InvalidArgumentException if the given string cannot be parsed as an item identifier */ public static function fromString(string $str) : Item{ $b = explode(":", str_replace([" ", "minecraft:"], ["_", ""], trim($str))); if(!isset($b[1])){ $meta = 0; }elseif(is_numeric($b[1])){ $meta = (int) $b[1]; }else{ throw new \InvalidArgumentException("Unable to parse \"" . $b[1] . "\" from \"" . $str . "\" as a valid meta value"); } if(is_numeric($b[0])){ $item = self::get((int) $b[0], $meta); }elseif(defined(ItemIds::class . "::" . strtoupper($b[0]))){ $item = self::get(constant(ItemIds::class . "::" . strtoupper($b[0])), $meta); }else{ throw new \InvalidArgumentException("Unable to resolve \"" . $str . "\" to a valid item"); } return $item; } public static function air() : Item{ return self::$air ?? (self::$air = self::get(ItemIds::AIR, 0, 0)); } /** * Returns whether the specified item ID is already registered in the item factory. * * @param int $id * @param int $variant * * @return bool */ public static function isRegistered(int $id, int $variant = 0) : bool{ if($id < 256){ return BlockFactory::isRegistered($id); } return isset(self::$list[self::getListOffset($id, $variant)]); } private static function getListOffset(int $id, int $variant) : int{ if($id < -0x8000 or $id > 0x7fff){ throw new \InvalidArgumentException("ID must be in range " . -0x8000 . " - " . 0x7fff); } return (($id & 0xffff) << 16) | ($variant & 0xffff); } /** * @return Item[] */ public static function getAllRegistered() : array{ return self::$list; } }