This repository has been archived by the owner on Jun 20, 2024. It is now read-only.
forked from pmmp/PocketMine-MP
-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
creation of the ds blockcustom and itemcustom api
- Loading branch information
1 parent
0113fa9
commit 56879c5
Showing
21 changed files
with
1,454 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
<?php | ||
|
||
/* | ||
* | ||
* _____ _ | ||
* / ___| | | | ||
* \ `--. _ _ _ __ ___ _ __ | |_ _ | ||
* `--. \ | | | '_ ` _ \| '_ \| | | | | | ||
* /\__/ / |_| | | | | | | |_) | | |_| | | ||
* \____/ \__, |_| |_| |_| .__/|_|\__, | | ||
* __/ | | | __/ | | ||
* |___/ |_| |___/ | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Lesser General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* @author Symply Team | ||
* @link http://www.symplymc.com/ | ||
* | ||
* | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace symply\behavior; | ||
|
||
use pmmp\thread\ThreadSafeArray; | ||
use pocketmine\scheduler\AsyncTask; | ||
use ReflectionException; | ||
|
||
class AsyncRegisterBlocksTask extends AsyncTask | ||
{ | ||
|
||
private ThreadSafeArray $asyncTransmitter; | ||
public function __construct() | ||
{ | ||
$this->asyncTransmitter = new ThreadSafeArray(); | ||
|
||
foreach (SymplyBlockFactory::getInstance()->getAsyncTransmitter() as $closure){ | ||
$this->asyncTransmitter[] = $closure; | ||
} | ||
} | ||
|
||
/** | ||
* @inheritDoc | ||
* @throws ReflectionException | ||
*/ | ||
public function onRun() : void | ||
{ | ||
foreach ($this->asyncTransmitter as $closure){ | ||
SymplyBlockFactory::getInstanceModeAsync()->register($closure); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
<?php | ||
|
||
/* | ||
* | ||
* _____ _ | ||
* / ___| | | | ||
* \ `--. _ _ _ __ ___ _ __ | |_ _ | ||
* `--. \ | | | '_ ` _ \| '_ \| | | | | | ||
* /\__/ / |_| | | | | | | |_) | | |_| | | ||
* \____/ \__, |_| |_| |_| .__/|_|\__, | | ||
* __/ | | | __/ | | ||
* |___/ |_| |___/ | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Lesser General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* @author Symply Team | ||
* @link http://www.symplymc.com/ | ||
* | ||
* | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace symply\behavior; | ||
|
||
use Closure; | ||
use pocketmine\block\Block; | ||
use pocketmine\block\RuntimeBlockStateRegistry; | ||
use pocketmine\data\bedrock\block\convert\BlockStateReader; | ||
use pocketmine\data\bedrock\block\convert\BlockStateWriter; | ||
use pocketmine\network\mcpe\convert\BlockStateDictionary; | ||
use pocketmine\network\mcpe\convert\BlockTranslator; | ||
use pocketmine\network\mcpe\convert\TypeConverter; | ||
use pocketmine\network\mcpe\protocol\types\BlockPaletteEntry; | ||
use pocketmine\network\mcpe\protocol\types\CacheableNbt; | ||
use pocketmine\utils\SingletonTrait; | ||
use pocketmine\world\format\io\GlobalBlockStateHandlers; | ||
use ReflectionException; | ||
use symply\behavior\block\BlockCustom; | ||
use symply\behavior\block\Permutation; | ||
use function array_values; | ||
use function assert; | ||
use function hash; | ||
use function ksort; | ||
|
||
class SymplyBlockFactory | ||
{ | ||
use SingletonTrait; | ||
|
||
public function __construct(private readonly bool $asyncMode = false) | ||
{ | ||
} | ||
|
||
/** @var array<string, BlockCustom> */ | ||
private array $blocks = []; | ||
|
||
/** @var BlockPaletteEntry[] */ | ||
private array $blockPaletteEntries = []; | ||
|
||
/** @var Closure[] */ | ||
private array $asyncTransmitter = []; | ||
|
||
/** | ||
* @param Closure(): BlockCustom $blockClosure | ||
* @throws ReflectionException | ||
*/ | ||
public function register(Closure $blockClosure) : void | ||
{ | ||
$blockCustom = $blockClosure(); | ||
$identifier = $blockCustom->getIdInfo()->getNamespaceId(); | ||
if (isset($this->blocks[$identifier])){ | ||
throw new \InvalidArgumentException("Block ID {$blockCustom->getIdInfo()->getNamespaceId()} is already used by another block"); | ||
} | ||
RuntimeBlockStateRegistry::getInstance()->register($blockCustom); | ||
$this->blocks[$identifier] = $blockCustom; | ||
if ($blockCustom instanceof Permutation){ | ||
$serializer = static function() use ($blockCustom) : BlockStateWriter{ | ||
$writer = BlockStateWriter::create($blockCustom->getIdInfo()->getNamespaceId()); | ||
$blockCustom->serializeState($writer); | ||
return $writer; | ||
}; | ||
$deserializer = static function(BlockStateReader $reader) use($identifier) : Block{ | ||
$block = SymplyBlockFactory::getInstance()->getBlock($reader->readString($identifier)); | ||
assert($block instanceof Permutation); | ||
$block->deserializeState($reader); | ||
return $block; | ||
}; | ||
}else{ | ||
$serializer = static fn() => BlockStateWriter::create($blockCustom->getIdInfo()->getNamespaceId()); | ||
$deserializer = static fn() => $blockCustom; | ||
} | ||
GlobalBlockStateHandlers::getSerializer()->map($blockCustom, $serializer); | ||
GlobalBlockStateHandlers::getDeserializer()->map($blockCustom->getIdInfo()->getNamespaceId(), $deserializer); | ||
if (!$this->asyncMode) { | ||
$this->blockPaletteEntries[] = new BlockPaletteEntry($identifier, new CacheableNbt($blockCustom->toPacket())); | ||
$this->asyncTransmitter[] = $blockClosure; | ||
} | ||
$this->initializePalette($blockCustom); | ||
} | ||
|
||
/** | ||
* @throws ReflectionException | ||
*/ | ||
private function initializePalette(BlockCustom $blockCustom) : void | ||
{ | ||
$typeConverter = TypeConverter::getInstance(); | ||
$identifier = $blockCustom->getIdInfo()->getNamespaceId(); | ||
$tags = array_values($typeConverter->getBlockTranslator()->getBlockStateDictionary()->getStates()); | ||
|
||
$oldBlockId = $blockCustom->getIdInfo()->getOldBlockId(); | ||
foreach ($blockCustom->toBlockStateDictionaryEntry() as $blockStateData){ | ||
GlobalBlockStateHandlers::getUpgrader()->getBlockIdMetaUpgrader()->addIdMetaToStateMapping($identifier, $blockStateData->getMeta(), $blockStateData->generateStateData()); | ||
GlobalBlockStateHandlers::getUpgrader()->getBlockIdMetaUpgrader()->addIntIdToStringIdMapping($oldBlockId, $identifier); | ||
$tags[] = $blockStateData; | ||
} | ||
foreach ($tags as $state) { | ||
$listStates[hash("fnv164", $state->getStateName(), true)][] = $state; | ||
} | ||
ksort($listStates); | ||
$sortedStates = []; | ||
$n = 0; | ||
foreach ($listStates as $states) { | ||
foreach ($states as $state) { | ||
$sortedStates[$n++] = $state; | ||
} | ||
} | ||
$blockTranslatorProperty = new \ReflectionProperty($typeConverter, "blockTranslator"); | ||
$blockTranslatorProperty->setValue($typeConverter, new BlockTranslator( | ||
new BlockStateDictionary($sortedStates), | ||
GlobalBlockStateHandlers::getSerializer() | ||
)); | ||
} | ||
|
||
/** | ||
* @return Closure[] | ||
*/ | ||
public function getAsyncTransmitter() : array | ||
{ | ||
return $this->asyncTransmitter; | ||
} | ||
|
||
public function getBlocks() : array | ||
{ | ||
return $this->blocks; | ||
} | ||
|
||
public function getBlock(string $identifier) : ?BlockCustom{ | ||
return $this->blocks[$identifier] ?? null; | ||
} | ||
|
||
public static function getInstanceModeAsync() : self{ | ||
return self::getInstance(true); | ||
} | ||
|
||
public static function getInstance(bool $asyncMode = false) : self | ||
{ | ||
if (self::$instance === null){ | ||
self::$instance = new self($asyncMode); | ||
} | ||
return self::$instance; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
<?php | ||
|
||
/* | ||
* | ||
* _____ _ | ||
* / ___| | | | ||
* \ `--. _ _ _ __ ___ _ __ | |_ _ | ||
* `--. \ | | | '_ ` _ \| '_ \| | | | | | ||
* /\__/ / |_| | | | | | | |_) | | |_| | | ||
* \____/ \__, |_| |_| |_| .__/|_|\__, | | ||
* __/ | | | __/ | | ||
* |___/ |_| |___/ | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Lesser General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* @author Symply Team | ||
* @link http://www.symplymc.com/ | ||
* | ||
* | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace symply\behavior\block; | ||
|
||
use Generator; | ||
use pocketmine\block\Block; | ||
use pocketmine\block\BlockTypeInfo; | ||
use pocketmine\math\Vector3; | ||
use pocketmine\nbt\tag\CompoundTag; | ||
use pocketmine\network\mcpe\convert\BlockStateDictionaryEntry; | ||
use symply\behavior\block\component\IComponent; | ||
use symply\behavior\block\component\ModelComponent; | ||
use symply\behavior\block\component\sub\HitBoxSubComponent; | ||
use symply\behavior\block\component\sub\MaterialSubComponent; | ||
use symply\behavior\block\component\TransformationComponent; | ||
use symply\behavior\commun\info\CreativeInfo; | ||
use function assert; | ||
|
||
abstract class BlockCustom extends Block | ||
{ | ||
|
||
/** @var IComponent[] */ | ||
private array $components = []; | ||
|
||
private CreativeInfo $creativeInfo; | ||
|
||
public function __construct( | ||
BlockCustomIdentifier $idInfo, | ||
CreativeInfo $creativeInfo, | ||
string $name, | ||
BlockTypeInfo $typeInfo | ||
) | ||
{ | ||
$this->creativeInfo = $creativeInfo; | ||
parent::__construct($idInfo, $name, $typeInfo); | ||
} | ||
|
||
public function getIdInfo() : BlockCustomIdentifier | ||
{ | ||
$idInfo = parent::getIdInfo(); | ||
assert($idInfo instanceof BlockCustomIdentifier); | ||
return $idInfo; | ||
} | ||
|
||
public function getCreativeCategory() : CreativeInfo | ||
{ | ||
return $this->creativeInfo; | ||
} | ||
|
||
public function setCreativeCategory(CreativeInfo $creativeInfo) : self | ||
{ | ||
$this->creativeInfo = $creativeInfo; | ||
return $this; | ||
} | ||
|
||
public function getComponents() : array | ||
{ | ||
return $this->components; | ||
} | ||
|
||
public function addComponent(IComponent $component) : self | ||
{ | ||
$this->components[] = $component; | ||
return $this; | ||
} | ||
|
||
/** | ||
* @param MaterialSubComponent[] $materials | ||
* @return $this | ||
*/ | ||
public function setModalComponent(array $materials, ?string $geometry = null, ?HitBoxSubComponent $collisionBox = null, ?HitBoxSubComponent $selectionBox = null) : self | ||
{ | ||
return $this->addComponent(new ModelComponent($materials, $geometry, $collisionBox, $selectionBox)); | ||
} | ||
|
||
public function setTransformationComponent(?Vector3 $rotation = null, ?Vector3 $scale = null, ?Vector3 $translation = null) : self{ | ||
return $this->addComponent(new TransformationComponent($rotation ?? Vector3::zero(), $scale ?? Vector3::zero(), $translation ?? Vector3::zero())); | ||
} | ||
|
||
public function setComponents(array $components) : self | ||
{ | ||
$this->components = $components; | ||
return $this; | ||
} | ||
|
||
public function toPacket() : CompoundTag | ||
{ | ||
return $this->getPropertiesTag()->setTag('components', $this->getComponentsTag())->setInt("molangVersion", 1); | ||
} | ||
|
||
public function getPropertiesTag() : CompoundTag | ||
{ | ||
$property = CompoundTag::create(); | ||
return $property->merge($this->getCreativeCategory()->toNbt()); | ||
} | ||
|
||
public function getComponentsTag() : CompoundTag | ||
{ | ||
$componentsTags = CompoundTag::create() | ||
->setTag("minecraft:light_emission", CompoundTag::create() | ||
->setByte("emission", $this->getLightLevel())) | ||
->setTag("minecraft:light_dampening", CompoundTag::create() | ||
->setByte("lightLevel", $this->getLightFilter())) | ||
->setTag("minecraft:destructible_by_mining", CompoundTag::create() | ||
->setFloat("value", $this->getBreakInfo()->getHardness())) | ||
->setTag("minecraft:friction", CompoundTag::create() | ||
->setFloat("value", 1 - $this->getFrictionFactor())); | ||
foreach ($this->components as $component) { | ||
$componentsTags->merge($component->toNbt()); | ||
} | ||
foreach ($this->getTypeTags() as $tag){ | ||
$componentsTags->setTag("tag:$tag", CompoundTag::create()); | ||
} | ||
return $componentsTags; | ||
} | ||
|
||
/** | ||
* @return Generator<BlockStateDictionaryEntry> | ||
*/ | ||
public function toBlockStateDictionaryEntry() : Generator | ||
{ | ||
yield new BlockStateDictionaryEntry($this->getIdInfo()->getNamespaceId(), [], 0); | ||
} | ||
} |
Oops, something went wrong.