blockID mapping tables /** @var int[]|\SplObjectStorage $woodenStairIds */ $woodenStairIds = new \SplObjectStorage(); $woodenStairIds[TreeType::OAK()] = BlockLegacyIds::OAK_STAIRS; $woodenStairIds[TreeType::SPRUCE()] = BlockLegacyIds::SPRUCE_STAIRS; $woodenStairIds[TreeType::BIRCH()] = BlockLegacyIds::BIRCH_STAIRS; $woodenStairIds[TreeType::JUNGLE()] = BlockLegacyIds::JUNGLE_STAIRS; $woodenStairIds[TreeType::ACACIA()] = BlockLegacyIds::ACACIA_STAIRS; $woodenStairIds[TreeType::DARK_OAK()] = BlockLegacyIds::DARK_OAK_STAIRS; /** @var int[]|\SplObjectStorage $fenceGateIds */ $fenceGateIds = new \SplObjectStorage(); $fenceGateIds[TreeType::OAK()] = BlockLegacyIds::OAK_FENCE_GATE; $fenceGateIds[TreeType::SPRUCE()] = BlockLegacyIds::SPRUCE_FENCE_GATE; $fenceGateIds[TreeType::BIRCH()] = BlockLegacyIds::BIRCH_FENCE_GATE; $fenceGateIds[TreeType::JUNGLE()] = BlockLegacyIds::JUNGLE_FENCE_GATE; $fenceGateIds[TreeType::ACACIA()] = BlockLegacyIds::ACACIA_FENCE_GATE; $fenceGateIds[TreeType::DARK_OAK()] = BlockLegacyIds::DARK_OAK_FENCE_GATE; /** @var BID[]|\SplObjectStorage $woodenDoorIds */ $woodenDoorIds = new \SplObjectStorage(); $woodenDoorIds[TreeType::OAK()] = new BID(BlockLegacyIds::OAK_DOOR_BLOCK, 0, ItemIds::OAK_DOOR); $woodenDoorIds[TreeType::SPRUCE()] = new BID(BlockLegacyIds::SPRUCE_DOOR_BLOCK, 0, ItemIds::SPRUCE_DOOR); $woodenDoorIds[TreeType::BIRCH()] = new BID(BlockLegacyIds::BIRCH_DOOR_BLOCK, 0, ItemIds::BIRCH_DOOR); $woodenDoorIds[TreeType::JUNGLE()] = new BID(BlockLegacyIds::JUNGLE_DOOR_BLOCK, 0, ItemIds::JUNGLE_DOOR); $woodenDoorIds[TreeType::ACACIA()] = new BID(BlockLegacyIds::ACACIA_DOOR_BLOCK, 0, ItemIds::ACACIA_DOOR); $woodenDoorIds[TreeType::DARK_OAK()] = new BID(BlockLegacyIds::DARK_OAK_DOOR_BLOCK, 0, ItemIds::DARK_OAK_DOOR); /** @var int[]|\SplObjectStorage $woodenPressurePlateIds */ $woodenPressurePlateIds = new \SplObjectStorage(); $woodenPressurePlateIds[TreeType::OAK()] = BlockLegacyIds::WOODEN_PRESSURE_PLATE; $woodenPressurePlateIds[TreeType::SPRUCE()] = BlockLegacyIds::SPRUCE_PRESSURE_PLATE; $woodenPressurePlateIds[TreeType::BIRCH()] = BlockLegacyIds::BIRCH_PRESSURE_PLATE; $woodenPressurePlateIds[TreeType::JUNGLE()] = BlockLegacyIds::JUNGLE_PRESSURE_PLATE; $woodenPressurePlateIds[TreeType::ACACIA()] = BlockLegacyIds::ACACIA_PRESSURE_PLATE; $woodenPressurePlateIds[TreeType::DARK_OAK()] = BlockLegacyIds::DARK_OAK_PRESSURE_PLATE; /** @var int[]|\SplObjectStorage $woodenButtonIds */ $woodenButtonIds = new \SplObjectStorage(); $woodenButtonIds[TreeType::OAK()] = BlockLegacyIds::WOODEN_BUTTON; $woodenButtonIds[TreeType::SPRUCE()] = BlockLegacyIds::SPRUCE_BUTTON; $woodenButtonIds[TreeType::BIRCH()] = BlockLegacyIds::BIRCH_BUTTON; $woodenButtonIds[TreeType::JUNGLE()] = BlockLegacyIds::JUNGLE_BUTTON; $woodenButtonIds[TreeType::ACACIA()] = BlockLegacyIds::ACACIA_BUTTON; $woodenButtonIds[TreeType::DARK_OAK()] = BlockLegacyIds::DARK_OAK_BUTTON; /** @var int[]|\SplObjectStorage $woodenTrapdoorIds */ $woodenTrapdoorIds = new \SplObjectStorage(); $woodenTrapdoorIds[TreeType::OAK()] = BlockLegacyIds::WOODEN_TRAPDOOR; $woodenTrapdoorIds[TreeType::SPRUCE()] = BlockLegacyIds::SPRUCE_TRAPDOOR; $woodenTrapdoorIds[TreeType::BIRCH()] = BlockLegacyIds::BIRCH_TRAPDOOR; $woodenTrapdoorIds[TreeType::JUNGLE()] = BlockLegacyIds::JUNGLE_TRAPDOOR; $woodenTrapdoorIds[TreeType::ACACIA()] = BlockLegacyIds::ACACIA_TRAPDOOR; $woodenTrapdoorIds[TreeType::DARK_OAK()] = BlockLegacyIds::DARK_OAK_TRAPDOOR; /** @var BlockIdentifierFlattened[]|\SplObjectStorage $woodenSignIds */ $woodenSignIds = new \SplObjectStorage(); $woodenSignIds[TreeType::OAK()] = new BlockIdentifierFlattened(BlockLegacyIds::SIGN_POST, BlockLegacyIds::WALL_SIGN, 0, ItemIds::SIGN, \pocketmine\tile\Sign::class); $woodenSignIds[TreeType::SPRUCE()] = new BlockIdentifierFlattened(BlockLegacyIds::SPRUCE_STANDING_SIGN, BlockLegacyIds::SPRUCE_WALL_SIGN, 0, ItemIds::SPRUCE_SIGN, \pocketmine\tile\Sign::class); $woodenSignIds[TreeType::BIRCH()] = new BlockIdentifierFlattened(BlockLegacyIds::BIRCH_STANDING_SIGN, BlockLegacyIds::BIRCH_WALL_SIGN, 0, ItemIds::BIRCH_SIGN, \pocketmine\tile\Sign::class); $woodenSignIds[TreeType::JUNGLE()] = new BlockIdentifierFlattened(BlockLegacyIds::JUNGLE_STANDING_SIGN, BlockLegacyIds::JUNGLE_WALL_SIGN, 0, ItemIds::JUNGLE_SIGN, \pocketmine\tile\Sign::class); $woodenSignIds[TreeType::ACACIA()] = new BlockIdentifierFlattened(BlockLegacyIds::ACACIA_STANDING_SIGN, BlockLegacyIds::ACACIA_WALL_SIGN, 0, ItemIds::ACACIA_SIGN, \pocketmine\tile\Sign::class); $woodenSignIds[TreeType::DARK_OAK()] = new BlockIdentifierFlattened(BlockLegacyIds::DARKOAK_STANDING_SIGN, BlockLegacyIds::DARKOAK_WALL_SIGN, 0, ItemIds::DARKOAK_SIGN, \pocketmine\tile\Sign::class); //endregion foreach(TreeType::getAll() as $treeType){ $magicNumber = $treeType->getMagicNumber(); $name = $treeType->getDisplayName(); self::register(new Planks(new BID(BlockLegacyIds::PLANKS, $magicNumber), $name . " Planks")); self::register(new Sapling(new BID(BlockLegacyIds::SAPLING, $magicNumber), $name . " Sapling", $treeType)); self::register(new WoodenFence(new BID(BlockLegacyIds::FENCE, $magicNumber), $name . " Fence")); self::register(new WoodenSlab(new BlockIdentifierFlattened(BlockLegacyIds::WOODEN_SLAB, BlockLegacyIds::DOUBLE_WOODEN_SLAB, $treeType->getMagicNumber()), $treeType->getDisplayName())); //TODO: find a better way to deal with this split self::register(new Leaves(new BID($magicNumber >= 4 ? BlockLegacyIds::LEAVES2 : BlockLegacyIds::LEAVES, $magicNumber & 0x03), $name . " Leaves", $treeType)); self::register(new Log(new BID($magicNumber >= 4 ? BlockLegacyIds::LOG2 : BlockLegacyIds::LOG, $magicNumber & 0x03), $name . " Log", $treeType)); //TODO: the old bug-block needs to be remapped to the new dedicated block self::register(new Wood(new BID($magicNumber >= 4 ? BlockLegacyIds::LOG2 : BlockLegacyIds::LOG, ($magicNumber & 0x03) | 0b1100), $name . " Wood", $treeType)); self::register(new Wood(new BID(BlockLegacyIds::WOOD, $magicNumber), $name . " Wood", $treeType)); self::register(new FenceGate(new BID($fenceGateIds[$treeType]), $treeType->getDisplayName() . " Fence Gate")); self::register(new WoodenStairs(new BID($woodenStairIds[$treeType]), $treeType->getDisplayName() . " Stairs")); self::register(new WoodenDoor($woodenDoorIds[$treeType], $treeType->getDisplayName() . " Door")); self::register(new WoodenButton(new BID($woodenButtonIds[$treeType]), $treeType->getDisplayName() . " Button")); self::register(new WoodenPressurePlate(new BID($woodenPressurePlateIds[$treeType]), $treeType->getDisplayName() . " Pressure Plate")); self::register(new WoodenTrapdoor(new BID($woodenTrapdoorIds[$treeType]), $treeType->getDisplayName() . " Trapdoor")); self::register(new Sign($woodenSignIds[$treeType], $treeType->getDisplayName() . " Sign")); } static $sandstoneTypes = [ BlockLegacyMetadata::SANDSTONE_NORMAL => "", BlockLegacyMetadata::SANDSTONE_CHISELED => "Chiseled ", BlockLegacyMetadata::SANDSTONE_CUT => "Cut ", BlockLegacyMetadata::SANDSTONE_SMOOTH => "Smooth " ]; foreach($sandstoneTypes as $variant => $prefix){ self::register(new Sandstone(new BID(BlockLegacyIds::SANDSTONE, $variant), $prefix . "Sandstone")); self::register(new Sandstone(new BID(BlockLegacyIds::RED_SANDSTONE, $variant), $prefix . "Red Sandstone")); } //region ugly glazed-terracotta colour -> ID mapping table /** @var int[]|\SplObjectStorage $glazedTerracottaIds */ $glazedTerracottaIds = new \SplObjectStorage(); $glazedTerracottaIds[DyeColor::WHITE()] = BlockLegacyIds::WHITE_GLAZED_TERRACOTTA; $glazedTerracottaIds[DyeColor::ORANGE()] = BlockLegacyIds::ORANGE_GLAZED_TERRACOTTA; $glazedTerracottaIds[DyeColor::MAGENTA()] = BlockLegacyIds::MAGENTA_GLAZED_TERRACOTTA; $glazedTerracottaIds[DyeColor::LIGHT_BLUE()] = BlockLegacyIds::LIGHT_BLUE_GLAZED_TERRACOTTA; $glazedTerracottaIds[DyeColor::YELLOW()] = BlockLegacyIds::YELLOW_GLAZED_TERRACOTTA; $glazedTerracottaIds[DyeColor::LIME()] = BlockLegacyIds::LIME_GLAZED_TERRACOTTA; $glazedTerracottaIds[DyeColor::PINK()] = BlockLegacyIds::PINK_GLAZED_TERRACOTTA; $glazedTerracottaIds[DyeColor::GRAY()] = BlockLegacyIds::GRAY_GLAZED_TERRACOTTA; $glazedTerracottaIds[DyeColor::LIGHT_GRAY()] = BlockLegacyIds::SILVER_GLAZED_TERRACOTTA; $glazedTerracottaIds[DyeColor::CYAN()] = BlockLegacyIds::CYAN_GLAZED_TERRACOTTA; $glazedTerracottaIds[DyeColor::PURPLE()] = BlockLegacyIds::PURPLE_GLAZED_TERRACOTTA; $glazedTerracottaIds[DyeColor::BLUE()] = BlockLegacyIds::BLUE_GLAZED_TERRACOTTA; $glazedTerracottaIds[DyeColor::BROWN()] = BlockLegacyIds::BROWN_GLAZED_TERRACOTTA; $glazedTerracottaIds[DyeColor::GREEN()] = BlockLegacyIds::GREEN_GLAZED_TERRACOTTA; $glazedTerracottaIds[DyeColor::RED()] = BlockLegacyIds::RED_GLAZED_TERRACOTTA; $glazedTerracottaIds[DyeColor::BLACK()] = BlockLegacyIds::BLACK_GLAZED_TERRACOTTA; //endregion foreach(DyeColor::getAll() as $color){ self::register(new Carpet(new BID(BlockLegacyIds::CARPET, $color->getMagicNumber()), $color->getDisplayName() . " Carpet")); self::register(new Concrete(new BID(BlockLegacyIds::CONCRETE, $color->getMagicNumber()), $color->getDisplayName() . " Concrete")); self::register(new ConcretePowder(new BID(BlockLegacyIds::CONCRETE_POWDER, $color->getMagicNumber()), $color->getDisplayName() . " Concrete Powder")); self::register(new Glass(new BID(BlockLegacyIds::STAINED_GLASS, $color->getMagicNumber()), $color->getDisplayName() . " Stained Glass")); self::register(new GlassPane(new BID(BlockLegacyIds::STAINED_GLASS_PANE, $color->getMagicNumber()), $color->getDisplayName() . " Stained Glass Pane")); self::register(new GlazedTerracotta(new BID($glazedTerracottaIds[$color]), $color->getDisplayName() . " Glazed Terracotta")); self::register(new HardenedClay(new BID(BlockLegacyIds::STAINED_CLAY, $color->getMagicNumber()), $color->getDisplayName() . " Stained Clay")); self::register(new HardenedGlass(new BID(BlockLegacyIds::HARD_STAINED_GLASS, $color->getMagicNumber()), "Hardened " . $color->getDisplayName() . " Stained Glass")); self::register(new HardenedGlassPane(new BID(BlockLegacyIds::HARD_STAINED_GLASS_PANE, $color->getMagicNumber()), "Hardened " . $color->getDisplayName() . " Stained Glass Pane")); self::register(new Wool(new BID(BlockLegacyIds::WOOL, $color->getMagicNumber()), $color->getDisplayName() . " Wool")); } static $wallTypes = [ BlockLegacyMetadata::WALL_ANDESITE => "Andesite", BlockLegacyMetadata::WALL_BRICK => "Brick", BlockLegacyMetadata::WALL_DIORITE => "Diorite", BlockLegacyMetadata::WALL_END_STONE_BRICK => "End Stone Brick", BlockLegacyMetadata::WALL_GRANITE => "Granite", BlockLegacyMetadata::WALL_MOSSY_STONE_BRICK => "Mossy Stone Brick", BlockLegacyMetadata::WALL_MOSSY_COBBLESTONE => "Mossy Cobblestone", BlockLegacyMetadata::WALL_NETHER_BRICK => "Nether Brick", BlockLegacyMetadata::WALL_COBBLESTONE => "Cobblestone", BlockLegacyMetadata::WALL_PRISMARINE => "Prismarine", BlockLegacyMetadata::WALL_RED_NETHER_BRICK => "Red Nether Brick", BlockLegacyMetadata::WALL_RED_SANDSTONE => "Red Sandstone", BlockLegacyMetadata::WALL_SANDSTONE => "Sandstone", BlockLegacyMetadata::WALL_STONE_BRICK => "Stone Brick" ]; foreach($wallTypes as $magicNumber => $prefix){ self::register(new Wall(new BID(BlockLegacyIds::COBBLESTONE_WALL, $magicNumber), $prefix . " Wall")); } //region --- auto-generated TODOs --- //TODO: minecraft:andesite_stairs //TODO: minecraft:bamboo //TODO: minecraft:bamboo_sapling //TODO: minecraft:barrel //TODO: minecraft:beacon //TODO: minecraft:bell //TODO: minecraft:blast_furnace //TODO: minecraft:bubble_column //TODO: minecraft:campfire //TODO: minecraft:cartography_table //TODO: minecraft:carved_pumpkin //TODO: minecraft:cauldron //TODO: minecraft:chain_command_block //TODO: minecraft:chemical_heat //TODO: minecraft:chemistry_table //TODO: minecraft:chorus_flower //TODO: minecraft:chorus_plant //TODO: minecraft:command_block //TODO: minecraft:composter //TODO: minecraft:conduit //TODO: minecraft:coral //TODO: minecraft:coral_block //TODO: minecraft:coral_fan //TODO: minecraft:coral_fan_dead //TODO: minecraft:coral_fan_hang //TODO: minecraft:coral_fan_hang2 //TODO: minecraft:coral_fan_hang3 //TODO: minecraft:dark_prismarine_stairs //TODO: minecraft:diorite_stairs //TODO: minecraft:dispenser //TODO: minecraft:dried_kelp_block //TODO: minecraft:dropper //TODO: minecraft:element_0 //TODO: minecraft:element_1 //TODO: minecraft:element_10 //TODO: minecraft:element_100 //TODO: minecraft:element_101 //TODO: minecraft:element_102 //TODO: minecraft:element_103 //TODO: minecraft:element_104 //TODO: minecraft:element_105 //TODO: minecraft:element_106 //TODO: minecraft:element_107 //TODO: minecraft:element_108 //TODO: minecraft:element_109 //TODO: minecraft:element_11 //TODO: minecraft:element_110 //TODO: minecraft:element_111 //TODO: minecraft:element_112 //TODO: minecraft:element_113 //TODO: minecraft:element_114 //TODO: minecraft:element_115 //TODO: minecraft:element_116 //TODO: minecraft:element_117 //TODO: minecraft:element_118 //TODO: minecraft:element_12 //TODO: minecraft:element_13 //TODO: minecraft:element_14 //TODO: minecraft:element_15 //TODO: minecraft:element_16 //TODO: minecraft:element_17 //TODO: minecraft:element_18 //TODO: minecraft:element_19 //TODO: minecraft:element_2 //TODO: minecraft:element_20 //TODO: minecraft:element_21 //TODO: minecraft:element_22 //TODO: minecraft:element_23 //TODO: minecraft:element_24 //TODO: minecraft:element_25 //TODO: minecraft:element_26 //TODO: minecraft:element_27 //TODO: minecraft:element_28 //TODO: minecraft:element_29 //TODO: minecraft:element_3 //TODO: minecraft:element_30 //TODO: minecraft:element_31 //TODO: minecraft:element_32 //TODO: minecraft:element_33 //TODO: minecraft:element_34 //TODO: minecraft:element_35 //TODO: minecraft:element_36 //TODO: minecraft:element_37 //TODO: minecraft:element_38 //TODO: minecraft:element_39 //TODO: minecraft:element_4 //TODO: minecraft:element_40 //TODO: minecraft:element_41 //TODO: minecraft:element_42 //TODO: minecraft:element_43 //TODO: minecraft:element_44 //TODO: minecraft:element_45 //TODO: minecraft:element_46 //TODO: minecraft:element_47 //TODO: minecraft:element_48 //TODO: minecraft:element_49 //TODO: minecraft:element_5 //TODO: minecraft:element_50 //TODO: minecraft:element_51 //TODO: minecraft:element_52 //TODO: minecraft:element_53 //TODO: minecraft:element_54 //TODO: minecraft:element_55 //TODO: minecraft:element_56 //TODO: minecraft:element_57 //TODO: minecraft:element_58 //TODO: minecraft:element_59 //TODO: minecraft:element_6 //TODO: minecraft:element_60 //TODO: minecraft:element_61 //TODO: minecraft:element_62 //TODO: minecraft:element_63 //TODO: minecraft:element_64 //TODO: minecraft:element_65 //TODO: minecraft:element_66 //TODO: minecraft:element_67 //TODO: minecraft:element_68 //TODO: minecraft:element_69 //TODO: minecraft:element_7 //TODO: minecraft:element_70 //TODO: minecraft:element_71 //TODO: minecraft:element_72 //TODO: minecraft:element_73 //TODO: minecraft:element_74 //TODO: minecraft:element_75 //TODO: minecraft:element_76 //TODO: minecraft:element_77 //TODO: minecraft:element_78 //TODO: minecraft:element_79 //TODO: minecraft:element_8 //TODO: minecraft:element_80 //TODO: minecraft:element_81 //TODO: minecraft:element_82 //TODO: minecraft:element_83 //TODO: minecraft:element_84 //TODO: minecraft:element_85 //TODO: minecraft:element_86 //TODO: minecraft:element_87 //TODO: minecraft:element_88 //TODO: minecraft:element_89 //TODO: minecraft:element_9 //TODO: minecraft:element_90 //TODO: minecraft:element_91 //TODO: minecraft:element_92 //TODO: minecraft:element_93 //TODO: minecraft:element_94 //TODO: minecraft:element_95 //TODO: minecraft:element_96 //TODO: minecraft:element_97 //TODO: minecraft:element_98 //TODO: minecraft:element_99 //TODO: minecraft:end_brick_stairs //TODO: minecraft:end_gateway //TODO: minecraft:end_portal //TODO: minecraft:fletching_table //TODO: minecraft:granite_stairs //TODO: minecraft:grindstone //TODO: minecraft:hopper //TODO: minecraft:jigsaw //TODO: minecraft:jukebox //TODO: minecraft:kelp //TODO: minecraft:lantern //TODO: minecraft:lava_cauldron //TODO: minecraft:lectern //TODO: minecraft:lit_blast_furnace //TODO: minecraft:lit_smoker //TODO: minecraft:loom //TODO: minecraft:mossy_cobblestone_stairs //TODO: minecraft:mossy_stone_brick_stairs //TODO: minecraft:movingBlock //TODO: minecraft:normal_stone_stairs //TODO: minecraft:observer //TODO: minecraft:piston //TODO: minecraft:pistonArmCollision //TODO: minecraft:polished_andesite_stairs //TODO: minecraft:polished_diorite_stairs //TODO: minecraft:polished_granite_stairs //TODO: minecraft:prismarine_bricks_stairs //TODO: minecraft:prismarine_stairs //TODO: minecraft:red_nether_brick_stairs //TODO: minecraft:repeating_command_block //TODO: minecraft:scaffolding //TODO: minecraft:seagrass //TODO: minecraft:shulker_box //TODO: minecraft:slime //TODO: minecraft:smithing_table //TODO: minecraft:smoker //TODO: minecraft:smooth_quartz_stairs //TODO: minecraft:smooth_red_sandstone_stairs //TODO: minecraft:smooth_sandstone_stairs //TODO: minecraft:smooth_stone //TODO: minecraft:sticky_piston //TODO: minecraft:stonecutter_block //TODO: minecraft:stripped_acacia_log //TODO: minecraft:stripped_birch_log //TODO: minecraft:stripped_dark_oak_log //TODO: minecraft:stripped_jungle_log //TODO: minecraft:stripped_oak_log //TODO: minecraft:stripped_spruce_log //TODO: minecraft:structure_block //TODO: minecraft:sweet_berry_bush //TODO: minecraft:turtle_egg //TODO: minecraft:undyed_shulker_box //endregion } public static function isInit() : bool{ return self::$fullList !== null; } /** * Registers a block type into the index. Plugins may use this method to register new block types or override * existing ones. * * NOTE: If you are registering a new block type, you will need to add it to the creative inventory yourself - it * will not automatically appear there. * * @param Block $block * @param bool $override Whether to override existing registrations * * @throws \RuntimeException if something attempted to override an already-registered block without specifying the * $override parameter. */ public static function register(Block $block, bool $override = false) : void{ $variant = $block->getIdInfo()->getVariant(); $stateMask = $block->getStateBitmask(); if(($variant & $stateMask) !== 0){ throw new \InvalidArgumentException("Block variant collides with state bitmask"); } foreach($block->getIdInfo()->getAllBlockIds() as $id){ if(!$override and self::isRegistered($id, $variant)){ throw new \InvalidArgumentException("Block registration $id:$variant conflicts with an existing block"); } for($m = $variant; $m <= ($variant | $stateMask); ++$m){ if(($m & ~$stateMask) !== $variant){ continue; } if(!$override and self::isRegistered($id, $m)){ throw new \InvalidArgumentException("Block registration " . get_class($block) . " has states which conflict with other blocks"); } $index = ($id << 4) | $m; $v = clone $block; try{ $v->readStateFromData($id, $m & $stateMask); if($v->getMeta() !== $m){ throw new InvalidBlockStateException("Corrupted meta"); //don't register anything that isn't the same when we read it back again } }catch(InvalidBlockStateException $e){ //invalid property combination continue; } self::fillStaticArrays($index, $v); } if(!self::isRegistered($id, $variant)){ self::fillStaticArrays(($id << 4) | $variant, $block); //register default state mapped to variant, for blocks which don't use 0 as valid state } } } private static function fillStaticArrays(int $index, Block $block) : void{ self::$fullList[$index] = $block; self::$lightFilter[$index] = min(15, $block->getLightFilter() + 1); //opacity plus 1 standard light filter self::$diffusesSkyLight[$index] = $block->diffusesSkyLight(); self::$blastResistance[$index] = $block->getBreakInfo()->getBlastResistance(); } /** * Returns a new Block instance with the specified ID, meta and position. * * @param int $id * @param int $meta * @param Position $pos * * @return Block */ public static function get(int $id, int $meta = 0, ?Position $pos = null) : Block{ if($meta < 0 or $meta > 0xf){ throw new \InvalidArgumentException("Block meta value $meta is out of bounds"); } /** @var Block|null $block */ $block = null; try{ $index = ($id << 4) | $meta; if(self::$fullList[$index] !== null){ $block = clone self::$fullList[$index]; } }catch(\RuntimeException $e){ throw new \InvalidArgumentException("Block ID $id is out of bounds"); } if($block === null){ $block = new UnknownBlock(new BID($id, $meta)); } if($pos !== null){ $block->position($pos->getWorld(), $pos->getFloorX(), $pos->getFloorY(), $pos->getFloorZ()); } return $block; } public static function fromFullBlock(int $fullState, ?Position $pos = null) : Block{ return self::get($fullState >> 4, $fullState & 0xf, $pos); } /** * Returns whether a specified block state is already registered in the block factory. * * @param int $id * @param int $meta * * @return bool */ public static function isRegistered(int $id, int $meta = 0) : bool{ $b = self::$fullList[($id << 4) | $meta]; return $b !== null and !($b instanceof UnknownBlock); } /** * @return Block[] */ public static function getAllKnownStates() : array{ return array_filter(self::$fullList->toArray(), function(?Block $v) : bool{ return $v !== null; }); } }