Changed how blocks are registered, add API to allow registering custom blocks

This commit is contained in:
Dylan K. Taylor 2017-08-03 16:46:31 +01:00
parent ca3cf3e067
commit b912b9173c
3 changed files with 207 additions and 188 deletions

View File

@ -65,8 +65,14 @@ class Block extends Position implements BlockIds, Metadatable{
/** @var AxisAlignedBB */
public $boundingBox = null;
public static function init(){
if(self::$list === null){
/**
* Initializes the block factory. By default this is called only once on server start, however you may wish to use
* this if you need to reset the block factory back to its original defaults for whatever reason.
*
* @param bool $force
*/
public static function init(bool $force = false){
if(self::$list === null or $force){
self::$list = new \SplFixedArray(256);
self::$fullList = new \SplFixedArray(4096);
self::$light = new \SplFixedArray(256);
@ -76,214 +82,226 @@ class Block extends Position implements BlockIds, Metadatable{
self::$transparent = new \SplFixedArray(256);
self::$diffusesSkyLight = new \SplFixedArray(256);
self::$list[self::AIR] = Air::class;
self::$list[self::STONE] = Stone::class;
self::$list[self::GRASS] = Grass::class;
self::$list[self::DIRT] = Dirt::class;
self::$list[self::COBBLESTONE] = Cobblestone::class;
self::$list[self::PLANKS] = Planks::class;
self::$list[self::SAPLING] = Sapling::class;
self::$list[self::BEDROCK] = Bedrock::class;
self::$list[self::WATER] = Water::class;
self::$list[self::STILL_WATER] = StillWater::class;
self::$list[self::LAVA] = Lava::class;
self::$list[self::STILL_LAVA] = StillLava::class;
self::$list[self::SAND] = Sand::class;
self::$list[self::GRAVEL] = Gravel::class;
self::$list[self::GOLD_ORE] = GoldOre::class;
self::$list[self::IRON_ORE] = IronOre::class;
self::$list[self::COAL_ORE] = CoalOre::class;
self::$list[self::WOOD] = Wood::class;
self::$list[self::LEAVES] = Leaves::class;
self::$list[self::SPONGE] = Sponge::class;
self::$list[self::GLASS] = Glass::class;
self::$list[self::LAPIS_ORE] = LapisOre::class;
self::$list[self::LAPIS_BLOCK] = Lapis::class;
self::registerBlock(new Air());
self::registerBlock(new Stone());
self::registerBlock(new Grass());
self::registerBlock(new Dirt());
self::registerBlock(new Cobblestone());
self::registerBlock(new Planks());
self::registerBlock(new Sapling());
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 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 LapisOre());
self::registerBlock(new Lapis());
self::$list[self::SANDSTONE] = Sandstone::class;
self::$list[self::NOTE_BLOCK] = NoteBlock::class;
self::$list[self::BED_BLOCK] = Bed::class;
self::$list[self::POWERED_RAIL] = PoweredRail::class;
self::$list[self::DETECTOR_RAIL] = DetectorRail::class;
self::registerBlock(new Sandstone());
self::registerBlock(new NoteBlock());
self::registerBlock(new Bed());
self::registerBlock(new PoweredRail());
self::registerBlock(new DetectorRail());
self::$list[self::COBWEB] = Cobweb::class;
self::$list[self::TALL_GRASS] = TallGrass::class;
self::$list[self::DEAD_BUSH] = DeadBush::class;
self::registerBlock(new Cobweb());
self::registerBlock(new TallGrass());
self::registerBlock(new DeadBush());
self::$list[self::WOOL] = Wool::class;
self::registerBlock(new Wool());
self::$list[self::DANDELION] = Dandelion::class;
self::$list[self::RED_FLOWER] = Flower::class;
self::$list[self::BROWN_MUSHROOM] = BrownMushroom::class;
self::$list[self::RED_MUSHROOM] = RedMushroom::class;
self::$list[self::GOLD_BLOCK] = Gold::class;
self::$list[self::IRON_BLOCK] = Iron::class;
self::$list[self::DOUBLE_SLAB] = DoubleSlab::class;
self::$list[self::SLAB] = Slab::class;
self::$list[self::BRICKS_BLOCK] = Bricks::class;
self::$list[self::TNT] = TNT::class;
self::$list[self::BOOKSHELF] = Bookshelf::class;
self::$list[self::MOSS_STONE] = MossStone::class;
self::$list[self::OBSIDIAN] = Obsidian::class;
self::$list[self::TORCH] = Torch::class;
self::$list[self::FIRE] = Fire::class;
self::$list[self::MONSTER_SPAWNER] = MonsterSpawner::class;
self::$list[self::WOOD_STAIRS] = WoodStairs::class;
self::$list[self::CHEST] = Chest::class;
self::registerBlock(new Dandelion());
self::registerBlock(new Flower());
self::registerBlock(new BrownMushroom());
self::registerBlock(new RedMushroom());
self::registerBlock(new Gold());
self::registerBlock(new Iron());
self::registerBlock(new DoubleSlab());
self::registerBlock(new Slab());
self::registerBlock(new Bricks());
self::registerBlock(new TNT());
self::registerBlock(new Bookshelf());
self::registerBlock(new MossStone());
self::registerBlock(new Obsidian());
self::registerBlock(new Torch());
self::registerBlock(new Fire());
self::registerBlock(new MonsterSpawner());
self::registerBlock(new WoodStairs());
self::registerBlock(new Chest());
self::$list[self::DIAMOND_ORE] = DiamondOre::class;
self::$list[self::DIAMOND_BLOCK] = Diamond::class;
self::$list[self::WORKBENCH] = Workbench::class;
self::$list[self::WHEAT_BLOCK] = Wheat::class;
self::$list[self::FARMLAND] = Farmland::class;
self::$list[self::FURNACE] = Furnace::class;
self::$list[self::BURNING_FURNACE] = BurningFurnace::class;
self::$list[self::SIGN_POST] = SignPost::class;
self::$list[self::WOOD_DOOR_BLOCK] = WoodDoor::class;
self::$list[self::LADDER] = Ladder::class;
self::$list[self::RAIL] = Rail::class;
self::$list[self::COBBLESTONE_STAIRS] = CobblestoneStairs::class;
self::$list[self::WALL_SIGN] = WallSign::class;
self::$list[self::LEVER] = Lever::class;
self::$list[self::STONE_PRESSURE_PLATE] = StonePressurePlate::class;
self::$list[self::IRON_DOOR_BLOCK] = IronDoor::class;
self::$list[self::WOODEN_PRESSURE_PLATE] = WoodenPressurePlate::class;
self::$list[self::REDSTONE_ORE] = RedstoneOre::class;
self::$list[self::GLOWING_REDSTONE_ORE] = GlowingRedstoneOre::class;
self::$list[self::UNLIT_REDSTONE_TORCH] = RedstoneTorchUnlit::class;
self::$list[self::LIT_REDSTONE_TORCH] = RedstoneTorch::class;
self::$list[self::STONE_BUTTON] = StoneButton::class;
self::$list[self::SNOW_LAYER] = SnowLayer::class;
self::$list[self::ICE] = Ice::class;
self::$list[self::SNOW_BLOCK] = Snow::class;
self::$list[self::CACTUS] = Cactus::class;
self::$list[self::CLAY_BLOCK] = Clay::class;
self::$list[self::SUGARCANE_BLOCK] = Sugarcane::class;
self::registerBlock(new DiamondOre());
self::registerBlock(new Diamond());
self::registerBlock(new Workbench());
self::registerBlock(new Wheat());
self::registerBlock(new Farmland());
self::registerBlock(new Furnace());
self::registerBlock(new BurningFurnace());
self::registerBlock(new SignPost());
self::registerBlock(new WoodDoor());
self::registerBlock(new Ladder());
self::registerBlock(new Rail());
self::registerBlock(new CobblestoneStairs());
self::registerBlock(new WallSign());
self::registerBlock(new Lever());
self::registerBlock(new StonePressurePlate());
self::registerBlock(new IronDoor());
self::registerBlock(new WoodenPressurePlate());
self::registerBlock(new RedstoneOre());
self::registerBlock(new GlowingRedstoneOre());
self::registerBlock(new RedstoneTorchUnlit());
self::registerBlock(new RedstoneTorch());
self::registerBlock(new StoneButton());
self::registerBlock(new SnowLayer());
self::registerBlock(new Ice());
self::registerBlock(new Snow());
self::registerBlock(new Cactus());
self::registerBlock(new Clay());
self::registerBlock(new Sugarcane());
self::$list[self::FENCE] = Fence::class;
self::$list[self::PUMPKIN] = Pumpkin::class;
self::$list[self::NETHERRACK] = Netherrack::class;
self::$list[self::SOUL_SAND] = SoulSand::class;
self::$list[self::GLOWSTONE_BLOCK] = Glowstone::class;
self::registerBlock(new Fence());
self::registerBlock(new Pumpkin());
self::registerBlock(new Netherrack());
self::registerBlock(new SoulSand());
self::registerBlock(new Glowstone());
self::$list[self::LIT_PUMPKIN] = LitPumpkin::class;
self::$list[self::CAKE_BLOCK] = Cake::class;
self::registerBlock(new LitPumpkin());
self::registerBlock(new Cake());
self::$list[self::TRAPDOOR] = Trapdoor::class;
self::registerBlock(new Trapdoor());
self::$list[self::STONE_BRICKS] = StoneBricks::class;
self::registerBlock(new StoneBricks());
self::$list[self::IRON_BARS] = IronBars::class;
self::$list[self::GLASS_PANE] = GlassPane::class;
self::$list[self::MELON_BLOCK] = Melon::class;
self::$list[self::PUMPKIN_STEM] = PumpkinStem::class;
self::$list[self::MELON_STEM] = MelonStem::class;
self::$list[self::VINE] = Vine::class;
self::$list[self::FENCE_GATE] = FenceGate::class;
self::$list[self::BRICK_STAIRS] = BrickStairs::class;
self::$list[self::STONE_BRICK_STAIRS] = StoneBrickStairs::class;
self::$list[self::MYCELIUM] = Mycelium::class;
self::$list[self::WATER_LILY] = WaterLily::class;
self::$list[self::NETHER_BRICKS] = NetherBrick::class;
self::$list[self::NETHER_BRICK_FENCE] = NetherBrickFence::class;
self::$list[self::NETHER_BRICKS_STAIRS] = NetherBrickStairs::class;
self::registerBlock(new IronBars());
self::registerBlock(new GlassPane());
self::registerBlock(new Melon());
self::registerBlock(new PumpkinStem());
self::registerBlock(new MelonStem());
self::registerBlock(new Vine());
self::registerBlock(new FenceGate());
self::registerBlock(new BrickStairs());
self::registerBlock(new StoneBrickStairs());
self::registerBlock(new Mycelium());
self::registerBlock(new WaterLily());
self::registerBlock(new NetherBrick());
self::registerBlock(new NetherBrickFence());
self::registerBlock(new NetherBrickStairs());
self::$list[self::ENCHANTING_TABLE] = EnchantingTable::class;
self::$list[self::BREWING_STAND_BLOCK] = BrewingStand::class;
self::registerBlock(new EnchantingTable());
self::registerBlock(new BrewingStand());
self::$list[self::END_PORTAL_FRAME] = EndPortalFrame::class;
self::$list[self::END_STONE] = EndStone::class;
self::registerBlock(new EndPortalFrame());
self::registerBlock(new EndStone());
self::$list[self::REDSTONE_LAMP] = RedstoneLamp::class;
self::$list[self::LIT_REDSTONE_LAMP] = LitRedstoneLamp::class;
self::registerBlock(new RedstoneLamp());
self::registerBlock(new LitRedstoneLamp());
self::$list[self::ACTIVATOR_RAIL] = ActivatorRail::class;
self::$list[self::COCOA_BLOCK] = CocoaBlock::class;
self::$list[self::SANDSTONE_STAIRS] = SandstoneStairs::class;
self::$list[self::EMERALD_ORE] = EmeraldOre::class;
self::registerBlock(new ActivatorRail());
self::registerBlock(new CocoaBlock());
self::registerBlock(new SandstoneStairs());
self::registerBlock(new EmeraldOre());
self::$list[self::TRIPWIRE_HOOK] = TripwireHook::class;
self::$list[self::TRIPWIRE] = Tripwire::class;
self::$list[self::EMERALD_BLOCK] = Emerald::class;
self::$list[self::SPRUCE_WOOD_STAIRS] = SpruceWoodStairs::class;
self::$list[self::BIRCH_WOOD_STAIRS] = BirchWoodStairs::class;
self::$list[self::JUNGLE_WOOD_STAIRS] = JungleWoodStairs::class;
self::registerBlock(new TripwireHook());
self::registerBlock(new Tripwire());
self::registerBlock(new Emerald());
self::registerBlock(new SpruceWoodStairs());
self::registerBlock(new BirchWoodStairs());
self::registerBlock(new JungleWoodStairs());
self::$list[self::STONE_WALL] = StoneWall::class;
self::$list[self::FLOWER_POT_BLOCK] = FlowerPot::class;
self::$list[self::CARROT_BLOCK] = Carrot::class;
self::$list[self::POTATO_BLOCK] = Potato::class;
self::$list[self::WOODEN_BUTTON] = WoodenButton::class;
self::$list[self::MOB_HEAD_BLOCK] = MobHead::class;
self::$list[self::ANVIL] = Anvil::class;
self::$list[self::TRAPPED_CHEST] = TrappedChest::class;
self::$list[self::WEIGHTED_PRESSURE_PLATE_LIGHT] = WeightedPressurePlateLight::class;
self::$list[self::WEIGHTED_PRESSURE_PLATE_HEAVY] = WeightedPressurePlateHeavy::class;
self::registerBlock(new StoneWall());
self::registerBlock(new FlowerPot());
self::registerBlock(new Carrot());
self::registerBlock(new Potato());
self::registerBlock(new WoodenButton());
self::registerBlock(new MobHead());
self::registerBlock(new Anvil());
self::registerBlock(new TrappedChest());
self::registerBlock(new WeightedPressurePlateLight());
self::registerBlock(new WeightedPressurePlateHeavy());
self::$list[self::DAYLIGHT_SENSOR] = DaylightSensor::class;
self::$list[self::REDSTONE_BLOCK] = Redstone::class;
self::registerBlock(new DaylightSensor());
self::registerBlock(new Redstone());
self::$list[self::QUARTZ_BLOCK] = Quartz::class;
self::$list[self::QUARTZ_STAIRS] = QuartzStairs::class;
self::$list[self::DOUBLE_WOOD_SLAB] = DoubleWoodSlab::class;
self::$list[self::WOOD_SLAB] = WoodSlab::class;
self::$list[self::STAINED_CLAY] = StainedClay::class;
self::registerBlock(new Quartz());
self::registerBlock(new QuartzStairs());
self::registerBlock(new DoubleWoodSlab());
self::registerBlock(new WoodSlab());
self::registerBlock(new StainedClay());
self::$list[self::LEAVES2] = Leaves2::class;
self::$list[self::WOOD2] = Wood2::class;
self::$list[self::ACACIA_WOOD_STAIRS] = AcaciaWoodStairs::class;
self::$list[self::DARK_OAK_WOOD_STAIRS] = DarkOakWoodStairs::class;
self::registerBlock(new Leaves2());
self::registerBlock(new Wood2());
self::registerBlock(new AcaciaWoodStairs());
self::registerBlock(new DarkOakWoodStairs());
self::$list[self::IRON_TRAPDOOR] = IronTrapdoor::class;
self::$list[self::PRISMARINE] = Prismarine::class;
self::$list[self::SEA_LANTERN] = SeaLantern::class;
self::$list[self::HAY_BALE] = HayBale::class;
self::$list[self::CARPET] = Carpet::class;
self::$list[self::HARDENED_CLAY] = HardenedClay::class;
self::$list[self::COAL_BLOCK] = Coal::class;
self::$list[self::PACKED_ICE] = PackedIce::class;
self::$list[self::DOUBLE_PLANT] = DoublePlant::class;
self::registerBlock(new IronTrapdoor());
self::registerBlock(new Prismarine());
self::registerBlock(new SeaLantern());
self::registerBlock(new HayBale());
self::registerBlock(new Carpet());
self::registerBlock(new HardenedClay());
self::registerBlock(new Coal());
self::registerBlock(new PackedIce());
self::registerBlock(new DoublePlant());
self::$list[self::FENCE_GATE_SPRUCE] = FenceGateSpruce::class;
self::$list[self::FENCE_GATE_BIRCH] = FenceGateBirch::class;
self::$list[self::FENCE_GATE_JUNGLE] = FenceGateJungle::class;
self::$list[self::FENCE_GATE_DARK_OAK] = FenceGateDarkOak::class;
self::$list[self::FENCE_GATE_ACACIA] = FenceGateAcacia::class;
self::registerBlock(new FenceGateSpruce());
self::registerBlock(new FenceGateBirch());
self::registerBlock(new FenceGateJungle());
self::registerBlock(new FenceGateDarkOak());
self::registerBlock(new FenceGateAcacia());
self::$list[self::GRASS_PATH] = GrassPath::class;
self::$list[self::ITEM_FRAME_BLOCK] = ItemFrame::class;
self::registerBlock(new GrassPath());
self::registerBlock(new ItemFrame());
self::$list[self::PODZOL] = Podzol::class;
self::$list[self::BEETROOT_BLOCK] = Beetroot::class;
self::$list[self::STONECUTTER] = Stonecutter::class;
self::$list[self::GLOWING_OBSIDIAN] = GlowingObsidian::class;
foreach(self::$list as $id => $class){
if($class !== null){
/** @var Block $block */
$block = new $class();
for($data = 0; $data < 16; ++$data){
self::$fullList[($id << 4) | $data] = new $class($data);
}
}else{
$block = new UnknownBlock($id);
for($data = 0; $data < 16; ++$data){
self::$fullList[($id << 4) | $data] = new UnknownBlock($id, $data);
}
}
self::$solid[$id] = $block->isSolid();
self::$transparent[$id] = $block->isTransparent();
self::$hardness[$id] = $block->getHardness();
self::$light[$id] = $block->getLightLevel();
self::$lightFilter[$id] = $block->getLightFilter() + 1;
self::$diffusesSkyLight[$id] = $block->diffusesSkyLight();
}
self::registerBlock(new Podzol());
self::registerBlock(new Beetroot());
self::registerBlock(new Stonecutter());
self::registerBlock(new GlowingObsidian());
}
}
/**
* 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 registerBlock(Block $block, bool $override = false){
$id = $block->getId();
if(isset(self::$list[$id]) and !$override){
throw new \RuntimeException("Trying to overwrite an already registered block");
}
self::$list[$id] = clone $block;
for($meta = 0; $meta < 16; ++$meta){
$variant = clone $block;
$variant->setDamage($meta);
self::$fullList[($id << 4) | $meta] = $variant;
}
self::$solid[$id] = $block->isSolid();
self::$transparent[$id] = $block->isTransparent();
self::$hardness[$id] = $block->getHardness();
self::$light[$id] = $block->getLightLevel();
self::$lightFilter[$id] = $block->getLightFilter();
self::$diffusesSkyLight[$id] = $block->diffusesSkyLight();
}
/**
* @param int $id
* @param int $meta
@ -293,13 +311,14 @@ class Block extends Position implements BlockIds, Metadatable{
*/
public static function get($id, $meta = 0, Position $pos = null){
try{
$block = self::$list[$id];
$block = self::$fullList[($id << 4) | $meta];
if($block !== null){
$block = new $block($meta);
$block = clone $block;
}else{
$block = new UnknownBlock($id, $meta);
}
}catch(\RuntimeException $e){
//TODO: this probably should return null (out of bounds IDs may cause unexpected behaviour)
$block = new UnknownBlock($id, $meta);
}

View File

@ -912,7 +912,7 @@ class Level implements ChunkManager, Metadatable{
}
public function addRandomTickedBlock(int $id){
$this->randomTickBlocks[$id] = Block::$list[$id];
$this->randomTickBlocks[$id] = get_class(Block::$list[$id]);
}
public function removeRandomTickedBlock(int $id){

@ -1 +1 @@
Subproject commit b57891001a564f6513846e24844f2105fff7a8e1
Subproject commit 6f75fd9b5c2be8b8a281685df77cea472aa521ff