From 20973a8c3cd21991ae73785997f4346ab848abf4 Mon Sep 17 00:00:00 2001 From: TwistedAsylumMC Date: Sat, 24 Sep 2022 12:59:29 +0100 Subject: [PATCH 1/6] Use a Closure to register blocks --- src/block/CustomiesBlockFactory.php | 65 +++++++++++++--------------- src/task/AsyncRegisterBlocksTask.php | 10 ++--- 2 files changed, 36 insertions(+), 39 deletions(-) diff --git a/src/block/CustomiesBlockFactory.php b/src/block/CustomiesBlockFactory.php index 530b302..d0ca811 100644 --- a/src/block/CustomiesBlockFactory.php +++ b/src/block/CustomiesBlockFactory.php @@ -3,6 +3,7 @@ namespace customiesdevs\customies\block; +use Closure; use customiesdevs\customies\item\CreativeInventoryInfo; use customiesdevs\customies\item\CustomiesItemFactory; use customiesdevs\customies\task\AsyncRegisterBlocksTask; @@ -10,9 +11,7 @@ use InvalidArgumentException; use OutOfRangeException; use pocketmine\block\Block; -use pocketmine\block\BlockBreakInfo; use pocketmine\block\BlockFactory; -use pocketmine\block\BlockIdentifier; use pocketmine\inventory\CreativeInventory; use pocketmine\nbt\tag\CompoundTag; use pocketmine\network\mcpe\convert\GlobalItemTypeDictionary; @@ -25,7 +24,6 @@ use pocketmine\network\mcpe\protocol\types\CacheableNbt; use pocketmine\Server; use pocketmine\utils\SingletonTrait; -use pocketmine\utils\Utils; use ReflectionClass; use RuntimeException; use SplFixedArray; @@ -40,10 +38,10 @@ final class CustomiesBlockFactory { private const NEW_BLOCK_FACTORY_SIZE = 2048 << Block::INTERNAL_METADATA_BITS; /** - * @var Block[] - * @phpstan-var array + * @var Closure[] + * @phpstan-var array */ - private array $customBlocks = []; + private array $blockFuncs = []; /** @var BlockPaletteEntry[] */ private array $blockPaletteEntries = []; /** @var R12ToCurrentBlockMapEntry[] */ @@ -68,10 +66,10 @@ public function increaseBlockFactoryLimits(): void { $array->setSize(self::NEW_BLOCK_FACTORY_SIZE); $property->setValue($instance, $array); } - $instance->light = SplFixedArray::fromArray(array_merge($instance->light->toArray(), array_fill(count($instance->light), self::NEW_BLOCK_FACTORY_SIZE, 0))); - $instance->lightFilter = SplFixedArray::fromArray(array_merge($instance->lightFilter->toArray(), array_fill(count($instance->lightFilter), self::NEW_BLOCK_FACTORY_SIZE, 1))); - $instance->blocksDirectSkyLight = SplFixedArray::fromArray(array_merge($instance->blocksDirectSkyLight->toArray(), array_fill(count($instance->blocksDirectSkyLight), self::NEW_BLOCK_FACTORY_SIZE, false))); - $instance->blastResistance = SplFixedArray::fromArray(array_merge($instance->blastResistance->toArray(), array_fill(count($instance->blastResistance), self::NEW_BLOCK_FACTORY_SIZE, 0.0))); + $instance->light = SplFixedArray::fromArray(array_merge($instance->light->toArray(), array_fill(count($instance->light), self::NEW_BLOCK_FACTORY_SIZE, 0))); + $instance->lightFilter = SplFixedArray::fromArray(array_merge($instance->lightFilter->toArray(), array_fill(count($instance->lightFilter), self::NEW_BLOCK_FACTORY_SIZE, 1))); + $instance->blocksDirectSkyLight = SplFixedArray::fromArray(array_merge($instance->blocksDirectSkyLight->toArray(), array_fill(count($instance->blocksDirectSkyLight), self::NEW_BLOCK_FACTORY_SIZE, false))); + $instance->blastResistance = SplFixedArray::fromArray(array_merge($instance->blastResistance->toArray(), array_fill(count($instance->blastResistance), self::NEW_BLOCK_FACTORY_SIZE, 0.0))); } /** @@ -80,7 +78,7 @@ public function increaseBlockFactoryLimits(): void { * can result in massive issues with almost every block showing as the wrong thing and causing lag to clients. */ public function addWorkerInitHook(): void { - $blocks = serialize($this->customBlocks); + $blocks = serialize($this->blockFuncs); $server = Server::getInstance(); $server->getAsyncPool()->addWorkerStartHook(static function (int $worker) use ($server, $blocks): void { $server->getAsyncPool()->submitTaskToWorker(new AsyncRegisterBlocksTask($blocks), $worker); @@ -109,16 +107,15 @@ public function getBlockPaletteEntries(): array { /** * Register a block to the BlockFactory and all the required mappings. - * @phpstan-param class-string $className + * @phpstan-param (Closure(int): Block) $blockFunc */ - public function registerBlock(string $className, string $identifier, string $name, BlockBreakInfo $breakInfo, ?Model $model = null, ?CreativeInventoryInfo $creativeInfo = null): void { - if($className !== Block::class) { - Utils::testValidInstance($className, Block::class); + public function registerBlock(Closure $blockFunc, string $identifier, ?Model $model = null, ?CreativeInventoryInfo $creativeInfo = null): void { + $id = $this->getNextAvailableId(); + $block = $blockFunc($id); + if(!$block instanceof Block) { + throw new InvalidArgumentException("Class returned from closure is not a Block"); } - /** @var Block $block */ - $block = new $className(new BlockIdentifier($this->getNextAvailableId(), 0), $name, $breakInfo); - if(BlockFactory::getInstance()->isRegistered($block->getId())) { throw new InvalidArgumentException("Block with ID " . $block->getId() . " is already registered"); } @@ -131,20 +128,20 @@ public function registerBlock(string $className, string $identifier, string $nam BlockPalette::getInstance()->insertState($blockState); $propertiesTag = CompoundTag::create(); - $components = CompoundTag::create() - ->setTag("minecraft:light_emission", CompoundTag::create() - ->setByte("emission", $block->getLightLevel())) - ->setTag("minecraft:block_light_filter", CompoundTag::create() - ->setByte("lightLevel", $block->getLightFilter())) - ->setTag("minecraft:destructible_by_mining", CompoundTag::create() - ->setFloat("value", $block->getBreakInfo()->getHardness()))//Says seconds_to_destroy in docs - ->setTag("minecraft:destructible_by_explosion", CompoundTag::create() - ->setFloat("value", $block->getBreakInfo()->getBlastResistance()))//Uses explosion_resistance in docs - ->setTag("minecraft:friction", CompoundTag::create() - ->setFloat("value", $block->getFrictionFactor())) - ->setTag("minecraft:flammable", CompoundTag::create() - ->setInt("catch_chance_modifier", $block->getFlameEncouragement()) - ->setInt("destroy_chance_modifier", $block->getFlammability())); + $components = CompoundTag::create() + ->setTag("minecraft:light_emission", CompoundTag::create() + ->setByte("emission", $block->getLightLevel())) + ->setTag("minecraft:block_light_filter", CompoundTag::create() + ->setByte("lightLevel", $block->getLightFilter())) + ->setTag("minecraft:destructible_by_mining", CompoundTag::create() + ->setFloat("value", $block->getBreakInfo()->getHardness()))//Says seconds_to_destroy in docs + ->setTag("minecraft:destructible_by_explosion", CompoundTag::create() + ->setFloat("value", $block->getBreakInfo()->getBlastResistance()))//Uses explosion_resistance in docs + ->setTag("minecraft:friction", CompoundTag::create() + ->setFloat("value", $block->getFrictionFactor())) + ->setTag("minecraft:flammable", CompoundTag::create() + ->setInt("catch_chance_modifier", $block->getFlameEncouragement()) + ->setInt("destroy_chance_modifier", $block->getFlammability())); if($model !== null) { foreach($model->toNBT() as $tagName => $tag){ @@ -164,7 +161,7 @@ public function registerBlock(string $className, string $identifier, string $nam $this->blockPaletteEntries[] = new BlockPaletteEntry($identifier, new CacheableNbt($propertiesTag)); - $this->customBlocks[$identifier] = $block; + $this->blockFuncs[$identifier] = $block; LegacyBlockIdToStringIdMap::getInstance()->registerMapping($identifier, $block->getId()); } @@ -172,7 +169,7 @@ public function registerBlock(string $className, string $identifier, string $nam * Returns the next available custom block id, an exception will be thrown if the block factory is full. */ private function getNextAvailableId(): int { - $id = 1000 + count($this->customBlocks); + $id = 1000 + count($this->blockFuncs); if($id > (self::NEW_BLOCK_FACTORY_SIZE / 16)) { throw new OutOfRangeException("All custom block ids are used up"); } diff --git a/src/task/AsyncRegisterBlocksTask.php b/src/task/AsyncRegisterBlocksTask.php index 01e88e6..070b74d 100644 --- a/src/task/AsyncRegisterBlocksTask.php +++ b/src/task/AsyncRegisterBlocksTask.php @@ -13,12 +13,12 @@ public function __construct(private string $blocks) { } public function onRun(): void { - /** @phpstan-var array $blocks */ + /** @phpstan-var array $blocks */ $blocks = unserialize($this->blocks); - foreach($blocks as $identifier => $block){ - /** @phpstan-var class-string $className */ - $className = get_class($block); - CustomiesBlockFactory::getInstance()->registerBlock($className, $identifier, $block->getName(), $block->getBreakInfo()); + foreach($blocks as $identifier => $blockFunc){ + // We do not care about the model or creative inventory data in other threads since it is unused outside of + // the main thread. + CustomiesBlockFactory::getInstance()->registerBlock($blockFunc, $identifier); } CustomiesBlockFactory::getInstance()->registerCustomRuntimeMappings(); } From ed0d6e46e130e8c7c2d0929f1bc5b797410c0463 Mon Sep 17 00:00:00 2001 From: TwistedAsylumMC Date: Sat, 24 Sep 2022 13:17:53 +0100 Subject: [PATCH 2/6] Store block funcs instead --- src/block/CustomiesBlockFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/block/CustomiesBlockFactory.php b/src/block/CustomiesBlockFactory.php index d0ca811..158e61f 100644 --- a/src/block/CustomiesBlockFactory.php +++ b/src/block/CustomiesBlockFactory.php @@ -161,7 +161,7 @@ public function registerBlock(Closure $blockFunc, string $identifier, ?Model $mo $this->blockPaletteEntries[] = new BlockPaletteEntry($identifier, new CacheableNbt($propertiesTag)); - $this->blockFuncs[$identifier] = $block; + $this->blockFuncs[$identifier] = $blockFunc; LegacyBlockIdToStringIdMap::getInstance()->registerMapping($identifier, $block->getId()); } From 63b5f34c4da24a8957ad9b59e7033abcf464fdef Mon Sep 17 00:00:00 2001 From: TwistedAsylumMC Date: Sat, 24 Sep 2022 13:34:33 +0100 Subject: [PATCH 3/6] This should work --- src/block/CustomiesBlockFactory.php | 2 +- src/task/AsyncRegisterBlocksTask.php | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/block/CustomiesBlockFactory.php b/src/block/CustomiesBlockFactory.php index 158e61f..047d59f 100644 --- a/src/block/CustomiesBlockFactory.php +++ b/src/block/CustomiesBlockFactory.php @@ -78,8 +78,8 @@ public function increaseBlockFactoryLimits(): void { * can result in massive issues with almost every block showing as the wrong thing and causing lag to clients. */ public function addWorkerInitHook(): void { - $blocks = serialize($this->blockFuncs); $server = Server::getInstance(); + $blocks = $this->blockFuncs; $server->getAsyncPool()->addWorkerStartHook(static function (int $worker) use ($server, $blocks): void { $server->getAsyncPool()->submitTaskToWorker(new AsyncRegisterBlocksTask($blocks), $worker); }); diff --git a/src/task/AsyncRegisterBlocksTask.php b/src/task/AsyncRegisterBlocksTask.php index 070b74d..b9aac33 100644 --- a/src/task/AsyncRegisterBlocksTask.php +++ b/src/task/AsyncRegisterBlocksTask.php @@ -3,19 +3,29 @@ namespace customiesdevs\customies\task; +use Closure; use customiesdevs\customies\block\CustomiesBlockFactory; use pocketmine\block\Block; use pocketmine\scheduler\AsyncTask; +use Threaded; final class AsyncRegisterBlocksTask extends AsyncTask { - public function __construct(private string $blocks) { + private Threaded $blockFuncs; + + /** + * @param Closure[] $blockFuncs + * @phpstan-param array $blockFuncs + */ + public function __construct(array $blockFuncs) { + $this->blockFuncs = new Threaded(); + foreach($blockFuncs as $identifier => $blockFunc) { + $this->blockFuncs[$identifier] = $blockFunc; + } } public function onRun(): void { - /** @phpstan-var array $blocks */ - $blocks = unserialize($this->blocks); - foreach($blocks as $identifier => $blockFunc){ + foreach($this->blockFuncs as $identifier => $blockFunc){ // We do not care about the model or creative inventory data in other threads since it is unused outside of // the main thread. CustomiesBlockFactory::getInstance()->registerBlock($blockFunc, $identifier); From eb05e01f8f434341c35fc24e6f254e8303f0e7e4 Mon Sep 17 00:00:00 2001 From: TwistedAsylumMC Date: Sat, 24 Sep 2022 18:41:06 +0100 Subject: [PATCH 4/6] Update to support latest tags --- src/block/Model.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/block/Model.php b/src/block/Model.php index 47ae195..c9a8d42 100644 --- a/src/block/Model.php +++ b/src/block/Model.php @@ -42,7 +42,19 @@ public function toNBT(): array { ->setTag("materials", $materials), "minecraft:geometry" => CompoundTag::create() ->setString("value", $this->geometry), - "minecraft:pick_collision" => CompoundTag::create() + "minecraft:collision_box" => CompoundTag::create() + ->setByte("enabled", 1) + ->setTag("origin", new ListTag([ + new FloatTag($this->origin->getX()), + new FloatTag($this->origin->getY()), + new FloatTag($this->origin->getZ()) + ])) + ->setTag("size", new ListTag([ + new FloatTag($this->size->getX()), + new FloatTag($this->size->getY()), + new FloatTag($this->size->getZ()) + ])), + "minecraft:selection_box" => CompoundTag::create() ->setByte("enabled", 1) ->setTag("origin", new ListTag([ new FloatTag($this->origin->getX()), From 6cfadc5d07332521358197616a876f52b388901c Mon Sep 17 00:00:00 2001 From: TwistedAsylumMC Date: Sat, 24 Sep 2022 18:41:37 +0100 Subject: [PATCH 5/6] Bump version --- plugin.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin.yml b/plugin.yml index 4593abb..bb19983 100644 --- a/plugin.yml +++ b/plugin.yml @@ -3,7 +3,7 @@ description: A PocketMine-MP plugin that implements support for custom blocks, i main: customiesdevs\customies\Customies src-namespace-prefix: customiesdevs\customies -version: 1.0.7 +version: 1.1.0 api: 4.0.0 authors: From 5fe413d9cf27ac92d4f91f3a8bf2b7599edf69ad Mon Sep 17 00:00:00 2001 From: Nick Date: Sun, 25 Sep 2022 22:51:44 +0300 Subject: [PATCH 6/6] Formatting fixes while we're at it --- src/entity/CustomiesEntityFactory.php | 4 ++-- src/task/AsyncRegisterBlocksTask.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/entity/CustomiesEntityFactory.php b/src/entity/CustomiesEntityFactory.php index 6015212..faa0138 100644 --- a/src/entity/CustomiesEntityFactory.php +++ b/src/entity/CustomiesEntityFactory.php @@ -26,8 +26,8 @@ class CustomiesEntityFactory { */ public function registerEntity(string $className, string $identifier, ?Closure $creationFunc = null): void { EntityFactory::getInstance()->register($className, $creationFunc ?? static function (World $world, CompoundTag $nbt) use ($className): Entity { - return new $className(EntityDataHelper::parseLocation($nbt, $world), $nbt); - }, [$identifier]); + return new $className(EntityDataHelper::parseLocation($nbt, $world), $nbt); + }, [$identifier]); $this->updateStaticPacketCache($identifier); } diff --git a/src/task/AsyncRegisterBlocksTask.php b/src/task/AsyncRegisterBlocksTask.php index b9aac33..e5e23ed 100644 --- a/src/task/AsyncRegisterBlocksTask.php +++ b/src/task/AsyncRegisterBlocksTask.php @@ -19,7 +19,7 @@ final class AsyncRegisterBlocksTask extends AsyncTask { */ public function __construct(array $blockFuncs) { $this->blockFuncs = new Threaded(); - foreach($blockFuncs as $identifier => $blockFunc) { + foreach($blockFuncs as $identifier => $blockFunc){ $this->blockFuncs[$identifier] = $blockFunc; } }