|
3 | 3 |
|
4 | 4 | namespace imperazim\custom\task; |
5 | 5 |
|
6 | | -use imperazim\custom\block\CustomBlockFactory; |
7 | | -use pmmp\thread\ThreadSafeArray; |
| 6 | +use pocketmine\block\Block; |
| 7 | +use pocketmine\block\RuntimeBlockStateRegistry; |
| 8 | +use pocketmine\data\bedrock\block\BlockStateData; |
| 9 | +use pocketmine\data\bedrock\block\convert\BlockStateReader; |
| 10 | +use pocketmine\data\bedrock\block\convert\BlockStateWriter; |
8 | 11 | use pocketmine\scheduler\AsyncTask; |
| 12 | +use pocketmine\world\format\io\GlobalBlockStateHandlers; |
9 | 13 |
|
10 | 14 | final class AsyncBlockRegistrationTask extends AsyncTask { |
11 | 15 |
|
12 | | - private ThreadSafeArray $blockFuncs; |
| 16 | + private string $cachePath; |
13 | 17 |
|
14 | | - /** |
15 | | - * @param Closure[] $blockFuncs |
16 | | - */ |
17 | | - public function __construct(array $blockFuncs) { |
18 | | - $this->blockFuncs = new ThreadSafeArray(); |
19 | | - foreach ($blockFuncs as $key => $func) { |
20 | | - $this->blockFuncs[$key] = $func; |
21 | | - } |
| 18 | + public function __construct(string $cachePath) { |
| 19 | + $this->cachePath = $cachePath; |
22 | 20 | } |
23 | 21 |
|
24 | 22 | public function onRun(): void { |
25 | | - foreach ($this->blockFuncs as $func) { |
26 | | - $func(); |
| 23 | + $raw = @file_get_contents($this->cachePath); |
| 24 | + if ($raw === false) { |
| 25 | + return; |
| 26 | + } |
| 27 | + /** @var array<string, array{blockData: string, states: list<array{name: string, statesNbt: string}>}> $cache */ |
| 28 | + $cache = igbinary_unserialize($raw); |
| 29 | + if (!is_array($cache)) { |
| 30 | + return; |
| 31 | + } |
| 32 | + |
| 33 | + $serializer = GlobalBlockStateHandlers::getSerializer(); |
| 34 | + $deserializer = GlobalBlockStateHandlers::getDeserializer(); |
| 35 | + $registry = RuntimeBlockStateRegistry::getInstance(); |
| 36 | + |
| 37 | + foreach ($cache as $identifier => $entry) { |
| 38 | + /** @var Block|null $block */ |
| 39 | + $block = igbinary_unserialize($entry['blockData']); |
| 40 | + if (!$block instanceof Block) { |
| 41 | + continue; |
| 42 | + } |
| 43 | + |
| 44 | + // Register the block in RuntimeBlockStateRegistry on this worker thread. |
| 45 | + try { |
| 46 | + $registry->register($block); |
| 47 | + } catch (\InvalidArgumentException) { |
| 48 | + // Already registered (shouldn't happen on fresh worker, but be safe). |
| 49 | + } |
| 50 | + |
| 51 | + // Register the serializer — maps Block typeId to BlockStateData. |
| 52 | + if (!$serializer->isRegistered($block)) { |
| 53 | + if (count($entry['states']) === 1) { |
| 54 | + // Simple block, no permutations. |
| 55 | + $serializer->map($block, BlockStateData::current($identifier, [])); |
| 56 | + } else { |
| 57 | + // Block with permutations — register a closure that builds state from block. |
| 58 | + $serializer->map($block, static function (Block $b) use ($identifier): BlockStateWriter { |
| 59 | + $writer = BlockStateWriter::create($identifier); |
| 60 | + if ($b instanceof \imperazim\custom\block\permutation\Permutable) { |
| 61 | + $b->serializeState($writer); |
| 62 | + } |
| 63 | + return $writer; |
| 64 | + }); |
| 65 | + } |
| 66 | + } |
| 67 | + |
| 68 | + // Register the deserializer — maps identifier string to Block factory. |
| 69 | + $deserializer->map($identifier, static function (BlockStateReader $in) use ($block, $identifier): Block { |
| 70 | + $b = clone $block; |
| 71 | + if ($b instanceof \imperazim\custom\block\permutation\Permutable) { |
| 72 | + $b->deserializeState($in); |
| 73 | + } |
| 74 | + return $b; |
| 75 | + }); |
27 | 76 | } |
28 | 77 | } |
29 | 78 | } |
0 commit comments