mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-07 10:22:56 +00:00
Nuke Block->meta, split into variant and state properties, lots of cleanup
This is a major change to the way block metadata is handled within the PM core. This separates variant metadata (which really ought to be part of the ID) from state metadata, and in a couple of cases flattens separate states of blocks together. The result of this is that invalid variants can be much more easily detected, and additionally state handling is much cleaner since meta is only needed at the serialize layer instead of throughout the code.
This commit is contained in:
@ -23,6 +23,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\Color;
|
||||
use pocketmine\block\utils\WoodType;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Position;
|
||||
|
||||
@ -32,6 +34,8 @@ use pocketmine\level\Position;
|
||||
class BlockFactory{
|
||||
/** @var \SplFixedArray<Block> */
|
||||
private static $fullList = null;
|
||||
/** @var \SplFixedArray|\Closure[] */
|
||||
private static $getInterceptors = null;
|
||||
|
||||
/** @var \SplFixedArray<int> */
|
||||
public static $lightFilter = null;
|
||||
@ -40,6 +44,9 @@ class BlockFactory{
|
||||
/** @var \SplFixedArray<float> */
|
||||
public static $blastResistance = null;
|
||||
|
||||
/** @var \SplFixedArray|int[] */
|
||||
public static $stateMasks = null;
|
||||
|
||||
/** @var int[] */
|
||||
public static $staticRuntimeIdMap = [];
|
||||
|
||||
@ -55,56 +62,138 @@ class BlockFactory{
|
||||
*/
|
||||
public static function init() : void{
|
||||
self::$fullList = new \SplFixedArray(4096);
|
||||
self::$getInterceptors = new \SplFixedArray(4096);
|
||||
|
||||
self::$lightFilter = \SplFixedArray::fromArray(array_fill(0, 256, 1));
|
||||
self::$diffusesSkyLight = \SplFixedArray::fromArray(array_fill(0, 256, false));
|
||||
self::$blastResistance = \SplFixedArray::fromArray(array_fill(0, 256, 0));
|
||||
|
||||
self::$stateMasks = \SplFixedArray::fromArray(array_fill(0, 256, 0));
|
||||
|
||||
self::registerBlock(new Air());
|
||||
self::registerBlock(new Stone());
|
||||
|
||||
//TODO: give smooth stone its own class (different drops)
|
||||
self::registerBlock(new Stone(Block::STONE, Stone::NORMAL, "Stone"));
|
||||
self::registerBlock(new Stone(Block::STONE, Stone::GRANITE, "Granite"));
|
||||
self::registerBlock(new Stone(Block::STONE, Stone::POLISHED_GRANITE, "Polished Granite"));
|
||||
self::registerBlock(new Stone(Block::STONE, Stone::DIORITE, "Diorite"));
|
||||
self::registerBlock(new Stone(Block::STONE, Stone::POLISHED_DIORITE, "Polished Diorite"));
|
||||
self::registerBlock(new Stone(Block::STONE, Stone::ANDESITE, "Andesite"));
|
||||
self::registerBlock(new Stone(Block::STONE, Stone::POLISHED_ANDESITE, "Polished Andesite"));
|
||||
|
||||
self::registerBlock(new Grass());
|
||||
self::registerBlock(new Dirt());
|
||||
|
||||
//TODO: split these into separate classes
|
||||
self::registerBlock(new Dirt(Block::DIRT, Dirt::NORMAL, "Dirt"));
|
||||
self::registerBlock(new Dirt(Block::DIRT, Dirt::COARSE, "Coarse Dirt"));
|
||||
|
||||
self::registerBlock(new Cobblestone());
|
||||
self::registerBlock(new Planks());
|
||||
self::registerBlock(new Sapling());
|
||||
|
||||
foreach(WoodType::ALL as $type){
|
||||
self::registerBlock(new Planks(Block::PLANKS, $type, WoodType::NAMES[$type] . " Planks"));
|
||||
self::registerBlock(new Sapling(Block::SAPLING, $type, WoodType::NAMES[$type] . " Sapling"));
|
||||
self::registerBlock(new WoodenFence(Block::FENCE, $type, WoodType::NAMES[$type] . " Fence"));
|
||||
}
|
||||
|
||||
foreach(WoodType::ALL as $type){
|
||||
//TODO: find a better way to deal with this split
|
||||
self::registerBlock(new Wood($type >= 4 ? Block::WOOD2 : Block::WOOD, $type & 0x03, WoodType::NAMES[$type] . " Wood"));
|
||||
self::registerBlock(new Leaves($type >= 4 ? Block::LEAVES2 : Block::LEAVES, $type & 0x03, $type, WoodType::NAMES[$type] . " Leaves"));
|
||||
}
|
||||
|
||||
self::registerBlock(new Bedrock());
|
||||
self::registerBlock(new Water());
|
||||
self::registerBlock(new StillWater());
|
||||
self::registerBlock(new Lava());
|
||||
self::registerBlock(new StillLava());
|
||||
self::registerBlock(new Sand());
|
||||
|
||||
self::registerBlock(new Sand(Block::SAND, 0, "Sand"));
|
||||
self::registerBlock(new Sand(Block::SAND, 1, "Red Sand"));
|
||||
|
||||
self::registerBlock(new Gravel());
|
||||
self::registerBlock(new GoldOre());
|
||||
self::registerBlock(new IronOre());
|
||||
self::registerBlock(new CoalOre());
|
||||
self::registerBlock(new Wood());
|
||||
self::registerBlock(new Leaves());
|
||||
self::registerBlock(new Sponge());
|
||||
self::registerBlock(new Glass());
|
||||
self::registerBlock(new Glass(Block::GLASS, 0, "Glass"));
|
||||
self::registerBlock(new LapisOre());
|
||||
self::registerBlock(new Lapis());
|
||||
//TODO: DISPENSER
|
||||
self::registerBlock(new Sandstone());
|
||||
|
||||
static $sandstoneTypes = [
|
||||
Sandstone::NORMAL => "",
|
||||
Sandstone::CHISELED => "Chiseled ",
|
||||
Sandstone::SMOOTH => "Smooth "
|
||||
];
|
||||
foreach($sandstoneTypes as $variant => $prefix){
|
||||
self::registerBlock(new Sandstone(Block::SANDSTONE, $variant, $prefix . "Sandstone"));
|
||||
self::registerBlock(new Sandstone(Block::RED_SANDSTONE, $variant, $prefix . "Red Sandstone"));
|
||||
}
|
||||
|
||||
self::registerBlock(new NoteBlock());
|
||||
self::registerBlock(new Bed());
|
||||
self::registerBlock(new PoweredRail());
|
||||
self::registerBlock(new DetectorRail());
|
||||
//TODO: STICKY_PISTON
|
||||
self::registerBlock(new Cobweb());
|
||||
self::registerBlock(new TallGrass());
|
||||
|
||||
self::registerBlock(new TallGrass(Block::TALL_GRASS, 0, "Fern"));
|
||||
self::registerBlock(new TallGrass(Block::TALL_GRASS, 1, "Tall Grass"));
|
||||
self::registerBlock(new TallGrass(Block::TALL_GRASS, 2, "Fern"));
|
||||
self::registerBlock(new TallGrass(Block::TALL_GRASS, 3, "Fern"));
|
||||
|
||||
self::registerBlock(new DeadBush());
|
||||
//TODO: PISTON
|
||||
//TODO: PISTONARMCOLLISION
|
||||
self::registerBlock(new Wool());
|
||||
|
||||
foreach(Color::ALL as $color){
|
||||
self::registerBlock(new Wool(Block::WOOL, $color, Color::NAMES[$color] . " Wool"));
|
||||
self::registerBlock(new HardenedClay(Block::STAINED_CLAY, $color, Color::NAMES[$color] . " Stained Clay"));
|
||||
self::registerBlock(new Glass(Block::STAINED_GLASS, $color, Color::NAMES[$color] . " Stained Glass"));
|
||||
self::registerBlock(new GlassPane(Block::STAINED_GLASS_PANE, $color, Color::NAMES[$color] . " Stained Glass Pane"));
|
||||
self::registerBlock(new Carpet(Block::CARPET, $color, Color::NAMES[$color] . " Carpet"));
|
||||
self::registerBlock(new Concrete(Block::CONCRETE, $color, Color::NAMES[$color] . " Concrete"));
|
||||
self::registerBlock(new ConcretePowder(Block::CONCRETE_POWDER, $color, Color::NAMES[$color] . " Concrete Powder"));
|
||||
}
|
||||
|
||||
self::registerBlock(new Dandelion());
|
||||
self::registerBlock(new Flower());
|
||||
|
||||
self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_POPPY, "Poppy"));
|
||||
self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_BLUE_ORCHID, "Blue Orchid"));
|
||||
self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_ALLIUM, "Allium"));
|
||||
self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_AZURE_BLUET, "Azure Bluet"));
|
||||
self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_RED_TULIP, "Red Tulip"));
|
||||
self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_ORANGE_TULIP, "Orange Tulip"));
|
||||
self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_WHITE_TULIP, "White Tulip"));
|
||||
self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_PINK_TULIP, "Pink Tulip"));
|
||||
self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_OXEYE_DAISY, "Oxeye Daisy"));
|
||||
|
||||
self::registerBlock(new BrownMushroom());
|
||||
self::registerBlock(new RedMushroom());
|
||||
self::registerBlock(new Gold());
|
||||
self::registerBlock(new Iron());
|
||||
self::registerBlock(new DoubleStoneSlab());
|
||||
self::registerBlock(new StoneSlab());
|
||||
|
||||
/** @var Slab[] $slabTypes */
|
||||
$slabTypes = [
|
||||
new StoneSlab(Block::STONE_SLAB, Block::DOUBLE_STONE_SLAB, 0, "Stone"),
|
||||
new StoneSlab(Block::STONE_SLAB, Block::DOUBLE_STONE_SLAB, 1, "Sandstone"),
|
||||
new StoneSlab(Block::STONE_SLAB, Block::DOUBLE_STONE_SLAB, 2, "Fake Wooden"),
|
||||
new StoneSlab(Block::STONE_SLAB, Block::DOUBLE_STONE_SLAB, 3, "Cobblestone"),
|
||||
new StoneSlab(Block::STONE_SLAB, Block::DOUBLE_STONE_SLAB, 4, "Brick"),
|
||||
new StoneSlab(Block::STONE_SLAB, Block::DOUBLE_STONE_SLAB, 5, "Stone Brick"),
|
||||
new StoneSlab(Block::STONE_SLAB, Block::DOUBLE_STONE_SLAB, 6, "Quartz"),
|
||||
new StoneSlab(Block::STONE_SLAB, Block::DOUBLE_STONE_SLAB, 7, "Nether Brick"),
|
||||
new StoneSlab(Block::STONE_SLAB2, Block::DOUBLE_STONE_SLAB2, 0, "Red Sandstone"),
|
||||
new StoneSlab(Block::STONE_SLAB2, Block::DOUBLE_STONE_SLAB2, 1, "Purpur")
|
||||
];
|
||||
foreach(WoodType::ALL as $woodType){
|
||||
$slabTypes[] = new WoodenSlab($woodType);
|
||||
}
|
||||
foreach($slabTypes as $type){
|
||||
self::registerBlock($type);
|
||||
self::registerBlock(new DoubleSlab($type->getDoubleSlabId(), $type->getId(), $type->getVariant()));
|
||||
}
|
||||
|
||||
self::registerBlock(new Bricks());
|
||||
self::registerBlock(new TNT());
|
||||
self::registerBlock(new Bookshelf());
|
||||
@ -121,8 +210,16 @@ class BlockFactory{
|
||||
self::registerBlock(new CraftingTable());
|
||||
self::registerBlock(new Wheat());
|
||||
self::registerBlock(new Farmland());
|
||||
|
||||
self::registerBlock(new Furnace());
|
||||
self::registerBlock(new BurningFurnace());
|
||||
self::addGetInterceptor(Block::BURNING_FURNACE, 0, function() : Block{
|
||||
$block = self::get(Block::FURNACE);
|
||||
if($block instanceof Furnace){
|
||||
$block->setLit();
|
||||
}
|
||||
return $block;
|
||||
});
|
||||
|
||||
self::registerBlock(new SignPost());
|
||||
self::registerBlock(new WoodenDoor(Block::OAK_DOOR_BLOCK, 0, "Oak Door", Item::OAK_DOOR));
|
||||
self::registerBlock(new Ladder());
|
||||
@ -134,9 +231,23 @@ class BlockFactory{
|
||||
self::registerBlock(new IronDoor());
|
||||
self::registerBlock(new WoodenPressurePlate());
|
||||
self::registerBlock(new RedstoneOre());
|
||||
self::registerBlock(new GlowingRedstoneOre());
|
||||
self::registerBlock(new RedstoneTorchUnlit());
|
||||
self::addGetInterceptor(Block::GLOWING_REDSTONE_ORE, 0, function() : Block{
|
||||
$block = self::get(Block::REDSTONE_ORE);
|
||||
if($block instanceof RedstoneOre){
|
||||
$block->setLit();
|
||||
}
|
||||
return $block;
|
||||
});
|
||||
|
||||
self::registerBlock(new RedstoneTorch());
|
||||
self::addGetInterceptor(Block::UNLIT_REDSTONE_TORCH, 0, function() : Block{
|
||||
$block = self::get(Block::REDSTONE_TORCH);
|
||||
if($block instanceof RedstoneTorch){
|
||||
$block->setLit(false); //default state is lit
|
||||
}
|
||||
return $block;
|
||||
});
|
||||
|
||||
self::registerBlock(new StoneButton());
|
||||
self::registerBlock(new SnowLayer());
|
||||
self::registerBlock(new Ice());
|
||||
@ -145,7 +256,7 @@ class BlockFactory{
|
||||
self::registerBlock(new Clay());
|
||||
self::registerBlock(new Sugarcane());
|
||||
//TODO: JUKEBOX
|
||||
self::registerBlock(new WoodenFence());
|
||||
|
||||
self::registerBlock(new Pumpkin());
|
||||
self::registerBlock(new Netherrack());
|
||||
self::registerBlock(new SoulSand());
|
||||
@ -158,11 +269,16 @@ class BlockFactory{
|
||||
//TODO: INVISIBLEBEDROCK
|
||||
self::registerBlock(new Trapdoor());
|
||||
//TODO: MONSTER_EGG
|
||||
self::registerBlock(new StoneBricks());
|
||||
|
||||
self::registerBlock(new StoneBricks(Block::STONE_BRICKS, StoneBricks::NORMAL, "Stone Bricks"));
|
||||
self::registerBlock(new StoneBricks(Block::STONE_BRICKS, StoneBricks::MOSSY, "Mossy Stone Bricks"));
|
||||
self::registerBlock(new StoneBricks(Block::STONE_BRICKS, StoneBricks::CRACKED, "Cracked Stone Bricks"));
|
||||
self::registerBlock(new StoneBricks(Block::STONE_BRICKS, StoneBricks::CHISELED, "Chiseled Stone Bricks"));
|
||||
|
||||
self::registerBlock(new BrownMushroomBlock());
|
||||
self::registerBlock(new RedMushroomBlock());
|
||||
self::registerBlock(new IronBars());
|
||||
self::registerBlock(new GlassPane());
|
||||
self::registerBlock(new GlassPane(Block::GLASS_PANE, 0, "Glass Pane"));
|
||||
self::registerBlock(new Melon());
|
||||
self::registerBlock(new PumpkinStem());
|
||||
self::registerBlock(new MelonStem());
|
||||
@ -184,7 +300,14 @@ class BlockFactory{
|
||||
self::registerBlock(new EndStone());
|
||||
//TODO: DRAGON_EGG
|
||||
self::registerBlock(new RedstoneLamp());
|
||||
self::registerBlock(new LitRedstoneLamp());
|
||||
self::addGetInterceptor(Block::LIT_REDSTONE_LAMP, 0, function() : Block{
|
||||
$block = self::get(Block::REDSTONE_LAMP);
|
||||
if($block instanceof RedstoneLamp){
|
||||
$block->setLit();
|
||||
}
|
||||
return $block;
|
||||
});
|
||||
|
||||
//TODO: DROPPER
|
||||
self::registerBlock(new ActivatorRail());
|
||||
self::registerBlock(new CocoaBlock());
|
||||
@ -199,50 +322,76 @@ class BlockFactory{
|
||||
self::registerBlock(new WoodenStairs(Block::JUNGLE_STAIRS, 0, "Jungle Stairs"));
|
||||
//TODO: COMMAND_BLOCK
|
||||
//TODO: BEACON
|
||||
self::registerBlock(new CobblestoneWall());
|
||||
|
||||
self::registerBlock(new CobblestoneWall(Block::COBBLESTONE_WALL, CobblestoneWall::NONE_MOSSY_WALL, "Cobblestone Wall"));
|
||||
self::registerBlock(new CobblestoneWall(Block::COBBLESTONE_WALL, CobblestoneWall::MOSSY_WALL, "Mossy Cobblestone Wall"));
|
||||
|
||||
self::registerBlock(new FlowerPot());
|
||||
self::registerBlock(new Carrot());
|
||||
self::registerBlock(new Potato());
|
||||
self::registerBlock(new WoodenButton());
|
||||
self::registerBlock(new Skull());
|
||||
self::registerBlock(new Anvil());
|
||||
|
||||
self::registerBlock(new Anvil(Block::ANVIL, Anvil::TYPE_NORMAL, "Anvil"));
|
||||
self::registerBlock(new Anvil(Block::ANVIL, Anvil::TYPE_SLIGHTLY_DAMAGED, "Slightly Damaged Anvil"));
|
||||
self::registerBlock(new Anvil(Block::ANVIL, Anvil::TYPE_VERY_DAMAGED, "Very Damaged Anvil"));
|
||||
|
||||
self::registerBlock(new TrappedChest());
|
||||
self::registerBlock(new WeightedPressurePlateLight());
|
||||
self::registerBlock(new WeightedPressurePlateHeavy());
|
||||
//TODO: COMPARATOR_BLOCK
|
||||
//TODO: POWERED_COMPARATOR
|
||||
self::registerBlock(new DaylightSensor());
|
||||
self::addGetInterceptor(Block::DAYLIGHT_SENSOR_INVERTED, 0, function() : Block{
|
||||
$block = self::get(Block::DAYLIGHT_SENSOR);
|
||||
if($block instanceof DaylightSensor){
|
||||
$block->setInverted();
|
||||
}
|
||||
return $block;
|
||||
});
|
||||
|
||||
self::registerBlock(new Redstone());
|
||||
self::registerBlock(new NetherQuartzOre());
|
||||
//TODO: HOPPER_BLOCK
|
||||
self::registerBlock(new Quartz());
|
||||
|
||||
self::registerBlock(new Quartz(Block::QUARTZ_BLOCK, Quartz::NORMAL, "Quartz Block"));
|
||||
self::registerBlock(new Quartz(Block::QUARTZ_BLOCK, Quartz::CHISELED, "Chiseled Quartz Block"));
|
||||
self::registerBlock(new Quartz(Block::QUARTZ_BLOCK, Quartz::PILLAR, "Quartz Pillar"));
|
||||
|
||||
self::registerBlock(new Purpur(Block::PURPUR_BLOCK, Purpur::NORMAL, "Purpur Block"));
|
||||
self::registerBlock(new Purpur(Block::PURPUR_BLOCK, Purpur::PILLAR, "Purpur Pillar"));
|
||||
|
||||
self::registerBlock(new QuartzStairs());
|
||||
self::registerBlock(new DoubleWoodenSlab());
|
||||
self::registerBlock(new WoodenSlab());
|
||||
self::registerBlock(new StainedClay());
|
||||
self::registerBlock(new StainedGlassPane());
|
||||
self::registerBlock(new Leaves2());
|
||||
self::registerBlock(new Wood2());
|
||||
|
||||
self::registerBlock(new WoodenStairs(Block::ACACIA_STAIRS, 0, "Acacia Stairs"));
|
||||
self::registerBlock(new WoodenStairs(Block::DARK_OAK_STAIRS, 0, "Dark Oak Stairs"));
|
||||
//TODO: SLIME
|
||||
|
||||
self::registerBlock(new IronTrapdoor());
|
||||
self::registerBlock(new Prismarine());
|
||||
|
||||
self::registerBlock(new Prismarine(Block::PRISMARINE, Prismarine::NORMAL, "Prismarine"));
|
||||
self::registerBlock(new Prismarine(Block::PRISMARINE, Prismarine::DARK, "Dark Prismarine"));
|
||||
self::registerBlock(new Prismarine(Block::PRISMARINE, Prismarine::BRICKS, "Prismarine Bricks"));
|
||||
|
||||
self::registerBlock(new SeaLantern());
|
||||
self::registerBlock(new HayBale());
|
||||
self::registerBlock(new Carpet());
|
||||
self::registerBlock(new HardenedClay());
|
||||
|
||||
self::registerBlock(new HardenedClay(Block::HARDENED_CLAY, 0, "Hardened Clay"));
|
||||
self::registerBlock(new Coal());
|
||||
self::registerBlock(new PackedIce());
|
||||
self::registerBlock(new DoublePlant());
|
||||
|
||||
self::registerBlock(new DoublePlant(Block::DOUBLE_PLANT, 0, "Sunflower"));
|
||||
self::registerBlock(new DoublePlant(Block::DOUBLE_PLANT, 1, "Lilac"));
|
||||
//TODO: double tallgrass and large fern have different behaviour than the others, so they should get their own classes
|
||||
self::registerBlock(new DoublePlant(Block::DOUBLE_PLANT, 2, "Double Tallgrass"));
|
||||
self::registerBlock(new DoublePlant(Block::DOUBLE_PLANT, 3, "Large Fern"));
|
||||
self::registerBlock(new DoublePlant(Block::DOUBLE_PLANT, 4, "Rose Bush"));
|
||||
self::registerBlock(new DoublePlant(Block::DOUBLE_PLANT, 5, "Peony"));
|
||||
|
||||
self::registerBlock(new StandingBanner());
|
||||
self::registerBlock(new WallBanner());
|
||||
//TODO: DAYLIGHT_DETECTOR_INVERTED
|
||||
self::registerBlock(new RedSandstone());
|
||||
|
||||
self::registerBlock(new RedSandstoneStairs());
|
||||
self::registerBlock(new DoubleStoneSlab2());
|
||||
self::registerBlock(new StoneSlab2());
|
||||
self::registerBlock(new FenceGate(Block::SPRUCE_FENCE_GATE, 0, "Spruce Fence Gate"));
|
||||
self::registerBlock(new FenceGate(Block::BIRCH_FENCE_GATE, 0, "Birch Fence Gate"));
|
||||
self::registerBlock(new FenceGate(Block::JUNGLE_FENCE_GATE, 0, "Jungle Fence Gate"));
|
||||
@ -259,7 +408,6 @@ class BlockFactory{
|
||||
self::registerBlock(new GrassPath());
|
||||
self::registerBlock(new ItemFrame());
|
||||
//TODO: CHORUS_FLOWER
|
||||
self::registerBlock(new Purpur());
|
||||
|
||||
self::registerBlock(new PurpurStairs());
|
||||
|
||||
@ -292,11 +440,8 @@ class BlockFactory{
|
||||
self::registerBlock(new GlazedTerracotta(Block::GREEN_GLAZED_TERRACOTTA, 0, "Green Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::RED_GLAZED_TERRACOTTA, 0, "Red Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::BLACK_GLAZED_TERRACOTTA, 0, "Black Glazed Terracotta"));
|
||||
self::registerBlock(new Concrete());
|
||||
self::registerBlock(new ConcretePowder());
|
||||
|
||||
//TODO: CHORUS_PLANT
|
||||
self::registerBlock(new StainedGlass());
|
||||
|
||||
self::registerBlock(new Podzol());
|
||||
self::registerBlock(new Beetroot());
|
||||
@ -327,20 +472,17 @@ class BlockFactory{
|
||||
*/
|
||||
public static function registerBlock(Block $block, bool $override = false) : void{
|
||||
$id = $block->getId();
|
||||
$variant = $block->getVariant();
|
||||
|
||||
if(!$override and self::isRegistered($id)){
|
||||
if(!$override and self::isRegistered($id, $variant)){
|
||||
throw new \RuntimeException("Trying to overwrite an already registered block");
|
||||
}
|
||||
|
||||
for($meta = 0; $meta < 16; ++$meta){
|
||||
$variant = clone $block;
|
||||
$variant->setDamage($meta);
|
||||
self::$fullList[($id << 4) | $meta] = $variant;
|
||||
self::$fullList[($id << 4) | $variant] = clone $block;
|
||||
if($variant === 0){
|
||||
//TODO: allow these to differ for different variants
|
||||
self::fillStaticArrays($id, $block);
|
||||
}
|
||||
|
||||
self::$lightFilter[$id] = min(15, $block->getLightFilter() + 1); //opacity plus 1 standard light filter
|
||||
self::$diffusesSkyLight[$id] = $block->diffusesSkyLight();
|
||||
self::$blastResistance[$id] = $block->getBlastResistance();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -357,16 +499,34 @@ class BlockFactory{
|
||||
throw new \InvalidArgumentException("Block meta value $meta is out of bounds");
|
||||
}
|
||||
|
||||
if(self::$stateMasks[$id] === null){
|
||||
$variant = 0;
|
||||
$state = $meta;
|
||||
}else{
|
||||
$variant = $meta & ~self::$stateMasks[$id];
|
||||
$state = $meta & self::$stateMasks[$id];
|
||||
}
|
||||
|
||||
$index = ($id << 4) | $variant;
|
||||
|
||||
/** @var Block|null $block */
|
||||
$block = null;
|
||||
try{
|
||||
if(self::$fullList[($id << 4) | $meta] !== null){
|
||||
$block = clone self::$fullList[($id << 4) | $meta];
|
||||
}else{
|
||||
$block = new UnknownBlock($id, $meta);
|
||||
if(self::$getInterceptors[$index] !== null){
|
||||
$block = (self::$getInterceptors[$index])();
|
||||
}elseif(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->readStateFromMeta($state);
|
||||
}else{
|
||||
$block = new UnknownBlock($id, $meta);
|
||||
}
|
||||
|
||||
if($pos !== null){
|
||||
$block->x = $pos->getFloorX();
|
||||
$block->y = $pos->getFloorY();
|
||||
@ -377,22 +537,32 @@ class BlockFactory{
|
||||
return $block;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @return \SplFixedArray
|
||||
*/
|
||||
public static function getBlockStatesArray() : \SplFixedArray{
|
||||
return self::$fullList;
|
||||
public static function addGetInterceptor(int $id, int $variant, \Closure $interceptor) : void{
|
||||
$block = $interceptor();
|
||||
if(!($block instanceof Block)){
|
||||
throw new \InvalidArgumentException("Interceptor must return an instance of " . Block::class);
|
||||
}
|
||||
self::$getInterceptors[($id << 4) | $variant] = $interceptor;
|
||||
self::fillStaticArrays($id, $block);
|
||||
}
|
||||
|
||||
private static function fillStaticArrays(int $id, Block $block) : void{
|
||||
self::$lightFilter[$id] = min(15, $block->getLightFilter() + 1); //opacity plus 1 standard light filter
|
||||
self::$diffusesSkyLight[$id] = $block->diffusesSkyLight();
|
||||
self::$blastResistance[$id] = $block->getBlastResistance();
|
||||
self::$stateMasks[$id] = $block->getStateBitmask();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a specified block ID is already registered in the block factory.
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $variant
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isRegistered(int $id) : bool{
|
||||
$b = self::$fullList[$id << 4];
|
||||
public static function isRegistered(int $id, int $variant = 0) : bool{
|
||||
$b = self::$fullList[($id << 4) | $variant];
|
||||
return $b !== null and !($b instanceof UnknownBlock);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user