diff --git a/plugin.yml b/plugin.yml index e1d59501..76895f84 100644 --- a/plugin.yml +++ b/plugin.yml @@ -13,3 +13,5 @@ contributors: - JackNoordhuis - Unickorn - abimek + - DrakzoSurYT # fix craft customies + - jujujustin69 # fix craft customies diff --git a/src/block/BlockComponents.php b/src/Blocks/BlockComponents.php similarity index 84% rename from src/block/BlockComponents.php rename to src/Blocks/BlockComponents.php index 8994af03..b4c2a435 100644 --- a/src/block/BlockComponents.php +++ b/src/Blocks/BlockComponents.php @@ -1,8 +1,8 @@ setFloat("value", $this->explosionResistance); + ->setFloat("explosion_resistance", $this->explosionResistance); } } \ No newline at end of file diff --git a/src/block/component/DestructibleByMiningComponent.php b/src/Blocks/Components/DestructibleByMiningComponent.php similarity index 80% rename from src/block/component/DestructibleByMiningComponent.php rename to src/Blocks/Components/DestructibleByMiningComponent.php index 458a44cb..296811c6 100644 --- a/src/block/component/DestructibleByMiningComponent.php +++ b/src/Blocks/Components/DestructibleByMiningComponent.php @@ -1,8 +1,8 @@ setFloat("value", $this->secondsToDestroy); + ->setFloat("seconds_to_destroy", $this->secondsToDestroy); } } \ No newline at end of file diff --git a/src/block/component/DisplayNameComponent.php b/src/Blocks/Components/DisplayNameComponent.php similarity index 85% rename from src/block/component/DisplayNameComponent.php rename to src/Blocks/Components/DisplayNameComponent.php index b145b0a2..c684de66 100644 --- a/src/block/component/DisplayNameComponent.php +++ b/src/Blocks/Components/DisplayNameComponent.php @@ -1,8 +1,8 @@ origin = $origin; + $this->size = $size; + } + + public function getName(): string { + return "minecraft:pick_collision"; + } + + public function getValue(): CompoundTag + { + return CompoundTag::create() + ->setTag("origin", new ListTag([ + new FloatTag($this->origin[0]), + new FloatTag($this->origin[1]), + new FloatTag($this->origin[2]) + ])) + ->setTag("size", new ListTag([ + new FloatTag($this->size[0]), + new FloatTag($this->size[1]), + new FloatTag($this->size[2]) + ])); + } +} \ No newline at end of file diff --git a/src/Blocks/Components/SelectionBoxComponent.php b/src/Blocks/Components/SelectionBoxComponent.php new file mode 100644 index 00000000..cdb1a27d --- /dev/null +++ b/src/Blocks/Components/SelectionBoxComponent.php @@ -0,0 +1,46 @@ +useSelectionBox = $useSelectionBox; + $this->origin = $origin; + $this->size = $size; + } + + public function getName(): string { + return "minecraft:selection_box"; + } + + public function getValue(): CompoundTag { + return CompoundTag::create() + ->setByte("enabled", $this->useSelectionBox ? 1 : 0) + ->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()) + ])); + } +} \ No newline at end of file diff --git a/src/Blocks/CustomCrop.php b/src/Blocks/CustomCrop.php new file mode 100644 index 00000000..2ddc97ed --- /dev/null +++ b/src/Blocks/CustomCrop.php @@ -0,0 +1,166 @@ +ageMax)) + ]; + } + + public function getPermutations(): array + { + $permutations = []; + + foreach (range(0, $this->ageMax) as $i) { + $geometry = "{$this->baseGeo}_$i"; + $texture = "{$this->baseTex}_$i"; + $condition = "q.block_property('minecraft:age') == {$i}"; + + $permutations[] = (new Permutation($condition)) + ->withComponent("minecraft:geometry", CompoundTag::create() + ->setString("identifier", $geometry)) + ->withComponent("minecraft:material_instances", CompoundTag::create() + ->setTag("mappings", CompoundTag::create()) + ->setTag("materials", CompoundTag::create() + ->setTag("*", CompoundTag::create() + ->setString("texture", $texture) + ->setString("render_method", Material::RENDER_METHOD_ALPHA_TEST) + ->setByte("face_dimming", 1) + ->setByte("ambient_occlusion", 1) + ) + ) + ); + } + return $permutations; + } + + public function getCurrentBlockProperties(): array + { + return ["minecraft:age" => $this->age]; + } + + public function serializeState(BlockStateWriter $out): void + { + $out->writeInt("minecraft:age", $this->age); + } + + public function deserializeState(BlockStateReader $in): void + { + $this->age = $in->readInt("minecraft:age"); + } + + public function describeBlockOnlyState(RuntimeDataDescriber $w): void + { + if ($this->age < 0 || $this->age > $this->getMaxStage()) { + $newStage = min($this->getStage(), $this->getMaxStage()); + $w->boundedIntAuto(0, $this->ageMax, $newStage); + return; + } + $w->boundedIntAuto(0, $this->ageMax, $this->age); + } + + protected function writeStateToMeta(): int + { + return $this->age; + } + + public function getStage(): int + { + return $this->age; + } + + public function setStage(int $stage): void + { + if ($stage < 0 || $stage > $this->getMaxStage()) { + return; + } + $this->age = $stage; + } + + public function getMaxStage(): int + { + return $this->ageMax; + } + + public function setStageMax(int $max): void + { + $this->ageMax = $max; + } + + public function setBaseGeometry(string $geo): void + { + $this->baseGeo = $geo; + } + + public function setBaseTexture(string $texture): void + { + $this->baseTex = $texture; + } + + public function withStage(int $stage): self + { + $clone = clone $this; + + if ($stage <= $this->getMaxStage()) { + $clone->setStage($stage); + } + return $clone; + } + + public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []): bool + { + if ($item instanceof Fertilizer && $this->getStage() < $this->getMaxStage()) { + // $this->getPosition()->getWorld()->addParticle($this->getPosition(), new particle); + $rand = mt_rand(0, 5); + + if ($rand === 0) { + $newStage = min($this->getStage() + 1, $this->getMaxStage()); + + $newBlock = $this->withStage($newStage); + + $this->position->getWorld()->setBlock($this->position, $newBlock, false); + return true; + } + $item->pop(); + $player->getInventory()->setItemInHand($item); + return false; + } + return false; + } + + public function onRandomTick(): void + { + if ($this->getStage() < $this->getMaxStage()) { + $newStage = min($this->getStage() + 1, $this->getMaxStage()); + + $newBlock = $this->withStage($newStage); + + $this->position->getWorld()->setBlock($this->position, $newBlock, false); + } + } +} \ No newline at end of file diff --git a/src/Blocks/CustomLadder.php b/src/Blocks/CustomLadder.php new file mode 100644 index 00000000..09fddeea --- /dev/null +++ b/src/Blocks/CustomLadder.php @@ -0,0 +1,5 @@ + + */ + private array $blockFuncs = []; + /** @var BlockPaletteEntry[] */ + public array $blockPaletteEntries = []; + /** @var array */ + private array $customBlocks = []; + + public static int $blockIdNext = 10000; + + /** + * Adds a worker initialize hook to the async pool to sync the BlockFactory for every thread worker that is created. + * It is especially important for the workers that deal with chunk encoding, as using the wrong runtime ID mappings + * can result in massive issues with almost every block showing as the wrong thing and causing lag to clients. + */ + public function addWorkerInitHook(string $cachePath): void { + $server = Server::getInstance(); + $blocks = $this->blockFuncs; + $server->getAsyncPool()->addWorkerStartHook(static function (int $worker) use ($cachePath, $server, $blocks): void { + $server->getAsyncPool()->submitTaskToWorker(new AsyncRegisterBlocksTask($cachePath, $blocks), $worker); + }); + } + + /** + * Get a custom block from its identifier. An exception will be thrown if the block is not registered. + */ + public function get(string $identifier): Block { + return clone ( + $this->customBlocks[$identifier] ?? + throw new InvalidArgumentException("Custom block $identifier is not registered") + ); + } + + /** + * @return Block[] + */ + public function GetAll(): array { + return $this->customBlocks; + } + + /** + * Returns all the block palette entries that need to be sent to the client. + * @return BlockPaletteEntry[] + */ + public function getBlockPaletteEntries(): array { + return $this->blockPaletteEntries; + } + + /** + * Register a block to the BlockFactory and all the required mappings. A custom stateReader and stateWriter can be + * provided to allow for custom block state serialization. + * @phpstan-param (Closure(): Block) $blockFunc + * @phpstan-param null|(Closure(BlockStateWriter): Block) $serializer + * @phpstan-param null|(Closure(Block): BlockStateReader) $deserializer + */ + public function registerBlock(Closure $blockFunc, string $identifier, ?Model $model = null, ?CreativeInventoryInfo $creativeInfo = null, ?Closure $serializer = null, ?Closure $deserializer = null, ?string $vanillaName = ""): void { + $block = $blockFunc(); + if(!$block instanceof Block) { + throw new InvalidArgumentException("Class returned from closure is not a Block"); + } + + $this->customBlocks[$identifier] = $block; + RuntimeBlockStateRegistry::getInstance()->register($block); + + + $propertiesTag = CompoundTag::create(); + $components = CompoundTag::create() + ->setTag("minecraft:light_emission", CompoundTag::create() + ->setByte("emission", $block->getLightLevel())) + ->setTag("minecraft:light_dampening", CompoundTag::create() + ->setByte("lightLevel", $block->getLightFilter())) + ->setTag("minecraft:destructible_by_mining", CompoundTag::create() + ->setFloat("value", $block->getBreakInfo()->getHardness())) + ->setTag("minecraft:friction", CompoundTag::create() + ->setFloat("value", 1 - $block->getFrictionFactor())); + + if($model !== null) { + foreach($model->toNBT() as $tagName => $tag){ + $components->setTag($tagName, $tag); + } + } + + if($block instanceof Permutable) { + $blockPropertyNames = $blockPropertyValues = $blockProperties = []; + foreach($block->getBlockProperties() as $blockProperty){ + $blockPropertyNames[] = $blockProperty->getName(); + $blockPropertyValues[] = $blockProperty->getValues(); + $blockProperties[] = $blockProperty->toNBT(); + } + $permutations = array_map(static fn(Permutation $permutation) => $permutation->toNBT(), $block->getPermutations()); + + // The 'minecraft:on_player_placing' component is required for the client to predict block placement, making + // it a smoother experience for the end-user. + $components->setTag("minecraft:on_player_placing", CompoundTag::create()); + $propertiesTag + ->setTag("permutations", new ListTag($permutations)) + ->setTag("properties", new ListTag(array_reverse($blockProperties))); // fix client-side order + + foreach(Permutations::getCartesianProduct($blockPropertyValues) as $meta => $permutations){ + // We need to insert states for every possible permutation to allow for all blocks to be used and to + // keep in sync with the client's block palette. + $states = CompoundTag::create(); + foreach($permutations as $i => $value){ + $states->setTag($blockPropertyNames[$i], NBT::getTagType($value)); + } + $blockState = CompoundTag::create() + ->setString(BlockStateData::TAG_NAME, $identifier) + ->setTag(BlockStateData::TAG_STATES, $states); + BlockPalette::getInstance()->insertState($blockState, $meta); + } + + $serializer ??= static function (Permutable $block) use ($identifier, $blockPropertyNames) : BlockStateWriter { + $b = BlockStateWriter::create($identifier); + $block->serializeState($b); + return $b; + }; + $deserializer ??= static function (BlockStateReader $in) use ($block, $identifier, $blockPropertyNames) : Permutable { + $b = CustomiesBlockFactory::getInstance()->get($identifier); + assert($b instanceof Permutable); + $b->deserializeState($in); + return $b; + }; + } else { + // If a block does not contain any permutations we can just insert the one state. + $blockState = CompoundTag::create() + ->setString(BlockStateData::TAG_NAME, $identifier) + ->setTag(BlockStateData::TAG_STATES, CompoundTag::create()); + BlockPalette::getInstance()->insertState($blockState); + $serializer ??= static fn() => new BlockStateWriter($identifier); + $deserializer ??= static fn(BlockStateReader $in) => $block; + } + + $creativeInfo ??= CreativeInventoryInfo::DEFAULT(); + $components->setTag("minecraft:creative_category", CompoundTag::create() + ->setString("category", $creativeInfo->getCategory()) + ->setString("group", $creativeInfo->getGroup())); + $propertiesTag + ->setTag("components", + $components->setTag("minecraft:creative_category", CompoundTag::create() + ->setString("category", $creativeInfo->getCategory()) + ->setString("group", $creativeInfo->getGroup()))) + ->setTag("menu_category", CompoundTag::create() + ->setString("category", $creativeInfo->getCategory() ?? "") + ->setString("group", $creativeInfo->getGroup() ?? "") + ->setInt("molangVersion", 12)); + + $this->blockPaletteEntries[] = $entry = new BlockPaletteEntry($identifier, new CacheableNbt($propertiesTag)); + $this->blockFuncs[$identifier] = [$blockFunc, $serializer, $deserializer, $entry]; + + $vanillaBlockId = self::$blockIdNext++; + $itemId = 255 - $vanillaBlockId; + foreach ($this->blockPaletteEntries as $i => $entry) { + if ($entry->getName() === $identifier) { + $this->blockPaletteEntries[$i] = new BlockPaletteEntry($identifier, new CacheableNbt($this->toPacket($entry->getStates()->getRoot(), $vanillaBlockId))); + } + } + + $entry = new ItemTypeEntry($identifier, $itemId, false, 2, new CacheableNbt(new CompoundTag())); + CustomiesItemFactory::getInstance()->registerBlockItem($entry); + + GlobalBlockStateHandlers::getSerializer()->map($block, $serializer); + GlobalBlockStateHandlers::getDeserializer()->map($identifier, $deserializer); + StringToItemParser::getInstance()->registerBlock($identifier, fn() => $block); + + CreativeItemManager::getInstance()->AddItemOnGroup($block->asItem(), $creativeInfo); + } + + public function iniBlock(): void + { + uksort($this->blockPaletteEntries, static function(string $a, string $b) : int { + return strcmp(hash("fnv164", $a), hash("fnv164", $b)); + }); + foreach($this->blockFuncs as $identifier => $blockBuilder) { + $vanillaBlockId = self::$blockIdNext++; + $itemId = 255 - $vanillaBlockId; + foreach ($this->blockPaletteEntries as $i => $entry) { + if ($entry->getName() === $identifier) { + $this->blockPaletteEntries[$i] = new BlockPaletteEntry($identifier, new CacheableNbt($this->toPacket($blockBuilder[3]->getStates()->getRoot(), $vanillaBlockId))); + } + } + + $entry = new ItemTypeEntry($identifier, $itemId, false, 2, new CacheableNbt(new CompoundTag())); + CustomiesItemFactory::getInstance()->registerBlockItem($entry); + + LegacyItemIdToStringIdMap::getInstance()->add($identifier, $itemId); + LegacyBlockIdToStringIdMap::getInstance()->add($identifier, $vanillaBlockId); + + } + } + + public function toPacket(CompoundTag $nbt,int $vanillaBlockId) : CompoundTag + { + return $nbt + ->setInt("molangVersion", 12) + ->setTag("vanilla_block_data", CompoundTag::create() + ->setInt("block_id", $vanillaBlockId)); + } +} diff --git a/src/block/Material.php b/src/Blocks/Material.php similarity index 96% rename from src/block/Material.php rename to src/Blocks/Material.php index 59db55d2..34ab07e1 100644 --- a/src/block/Material.php +++ b/src/Blocks/Material.php @@ -1,7 +1,7 @@ materials = $materials; + $this->geometry = $geometry; + $this->origin = $origin ?? Vector3::zero(); + $this->size = $size ?? Vector3::zero(); + $this->flowable = $flowable; + $this->selection_box = $selection_box; + } + + /** + * Returns the model in the correct NBT format supported by the client. + * @return CompoundTag[] + */ + public function toNBT(): array { + $materials = CompoundTag::create(); + foreach($this->materials as $material){ + $materials->setTag($material->getTarget(), $material->toNBT()); + } + + $material = [ + "minecraft:material_instances" => CompoundTag::create() + ->setTag("mappings", CompoundTag::create()) // What is this? The client will crash if it is not sent. + ->setTag("materials", $materials), + ]; + if($this->geometry === null) { + $material["minecraft:unit_cube"] = CompoundTag::create(); + + } else { + $material["minecraft:geometry"] = CompoundTag::create() + ->setString("identifier", $this->geometry); + $material["minecraft:collision_box"] = CompoundTag::create() + ->setByte($this->flowable ? "disable" : "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()) + ])); + $material["minecraft:selection_box"] = CompoundTag::create() + ->setByte($this->selection_box ? "enabled" : "disabled", 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()) + ])); + } + return $material; + } +} diff --git a/src/block/permutations/BlockProperty.php b/src/Blocks/Permutations/BlockProperty.php similarity index 90% rename from src/block/permutations/BlockProperty.php rename to src/Blocks/Permutations/BlockProperty.php index 6550c432..bb19139e 100644 --- a/src/block/permutations/BlockProperty.php +++ b/src/Blocks/Permutations/BlockProperty.php @@ -1,9 +1,9 @@ components; + return $x; + } + /** * Returns the permutation in the correct NBT format supported by the client. */ diff --git a/src/block/permutations/Permutations.php b/src/Blocks/Permutations/Permutations.php similarity index 92% rename from src/block/permutations/Permutations.php rename to src/Blocks/Permutations/Permutations.php index 96d7b2f0..b5a381fd 100644 --- a/src/block/permutations/Permutations.php +++ b/src/Blocks/Permutations/Permutations.php @@ -1,9 +1,9 @@ withComponent("minecraft:transformation", CompoundTag::create() ->setInt("RX", 0) ->setInt("RY", 0) @@ -42,7 +42,7 @@ public function getPermutations(): array { ->setFloat("TX", 0.0) ->setFloat("TY", 0.0) ->setFloat("TZ", 0.0)), - (new Permutation("q.block_property('customies:rotation') == 3")) + (new Permutation("q.block_property('minecraft:rotation') == 3")) ->withComponent("minecraft:transformation", CompoundTag::create() ->setInt("RX", 0) ->setInt("RY", 2) @@ -53,7 +53,7 @@ public function getPermutations(): array { ->setFloat("TX", 0.0) ->setFloat("TY", 0.0) ->setFloat("TZ", 0.0)), - (new Permutation("q.block_property('customies:rotation') == 4")) + (new Permutation("q.block_property('minecraft:rotation') == 4")) ->withComponent("minecraft:transformation", CompoundTag::create() ->setInt("RX", 0) ->setInt("RY", 1) @@ -64,7 +64,7 @@ public function getPermutations(): array { ->setFloat("TX", 0.0) ->setFloat("TY", 0.0) ->setFloat("TZ", 0.0)), - (new Permutation("q.block_property('customies:rotation') == 5")) + (new Permutation("q.block_property('minecraft:rotation') == 5")) ->withComponent("minecraft:transformation", CompoundTag::create() ->setInt("RX", 0) ->setInt("RY", 3) @@ -103,10 +103,10 @@ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Blo } public function serializeState(BlockStateWriter $out): void { - $out->writeInt("customies:rotation", $this->facing); + $out->writeInt("minecraft:rotation", $this->facing); } public function deserializeState(BlockStateReader $in): void { - $this->facing = $in->readInt("customies:rotation"); + $this->facing = $in->readInt("minecraft:rotation"); } } \ No newline at end of file diff --git a/src/Customies.php b/src/Customies.php index 4ce46398..a5b9e188 100644 --- a/src/Customies.php +++ b/src/Customies.php @@ -3,7 +3,7 @@ namespace customiesdevs\customies; -use customiesdevs\customies\block\CustomiesBlockFactory; +use customiesdevs\customies\Blocks\CustomiesBlockFactory; use pocketmine\plugin\PluginBase; use pocketmine\scheduler\ClosureTask; @@ -14,8 +14,6 @@ protected function onEnable(): void { $cachePath = $this->getDataFolder() . "idcache"; $this->getScheduler()->scheduleDelayedTask(new ClosureTask(static function () use ($cachePath): void { - // This task is scheduled with a 0-tick delay so it runs as soon as the server has started. Plugins should - // register their custom blocks and entities in onEnable() before this is executed. CustomiesBlockFactory::getInstance()->addWorkerInitHook($cachePath); }), 0); } diff --git a/src/CustomiesListener.php b/src/CustomiesListener.php index 4ade1464..3d096f8a 100644 --- a/src/CustomiesListener.php +++ b/src/CustomiesListener.php @@ -5,6 +5,7 @@ use customiesdevs\customies\block\CustomiesBlockFactory; use pocketmine\event\Listener; +use pocketmine\event\player\PlayerCreationEvent; use pocketmine\event\server\DataPacketSendEvent; use pocketmine\network\mcpe\protocol\ResourcePackStackPacket; use pocketmine\network\mcpe\protocol\StartGamePacket; @@ -19,8 +20,6 @@ final class CustomiesListener implements Listener { public function __construct() { $this->experiments = new Experiments([ - // "data_driven_items" is required for custom blocks to render in-game. With this disabled, they will be - // shown as the UPDATE texture block. "data_driven_items" => true, ], true); } @@ -29,8 +28,6 @@ public function onDataPacketSend(DataPacketSendEvent $event): void { foreach($event->getPackets() as $packet){ if($packet instanceof StartGamePacket) { if(count($this->cachedBlockPalette) === 0) { - // Wait for the data to be needed before it is actually cached. Allows for all blocks and items to be - // registered before they are cached for the rest of the runtime. $this->cachedBlockPalette = CustomiesBlockFactory::getInstance()->getBlockPaletteEntries(); } $packet->levelSettings->experiments = $this->experiments; @@ -40,4 +37,9 @@ public function onDataPacketSend(DataPacketSendEvent $event): void { } } } + + public function onPlayerCreation(PlayerCreationEvent $event): void + { + $event->setPlayerClass(CustomiesPlayer::class); + } } diff --git a/src/CustomiesPlayer.php b/src/CustomiesPlayer.php new file mode 100644 index 00000000..ae6606bd --- /dev/null +++ b/src/CustomiesPlayer.php @@ -0,0 +1,105 @@ +displayName; + if ($this->hasSpace($name)){ + $name = str_replace(" ", "_", $name); + $this->displayName = $name; + $this->setDisplayName($name); + return $name; + } + + return $name; + } + + public function getName(): string + { + $name = $this->username; + if ($this->hasSpace($name)){ + $name = str_replace(" ", "_", $name); + return $name; + } + + return $name; + } + + public function hasSpace(string $string): bool + { + return str_contains($string, ' '); + } + + protected ?SurvivalBlockBreakHandler $blockBreakHandlerCustom = null; + + public function attackBlock(Vector3 $pos, int|Facing $face): bool { + if ($pos->distanceSquared($this->location) > 10000) { + return false; + } + + $target = $this->getWorld()->getBlock($pos); + + $ev = new PlayerInteractEvent($this, $this->getInventory()->getItemInHand(), $target, null, $face, PlayerInteractEvent::LEFT_CLICK_BLOCK); + + if ($this->isSpectator()) { + $ev->cancel(); + } + + $ev->call(); + if ($ev->isCancelled()) { + return false; + } + $this->broadcastAnimation(new ArmSwingAnimation($this), $this->getViewers()); + + if ($target->onAttack($this->getInventory()->getItemInHand(), $face, $this)) { + return true; + } + + $block = $target->getSide($face); + if ($block->getTypeId() === VanillaBlocks::FIRE()->getTypeId()) { + $this->getWorld()->setBlock($block->getPosition(), VanillaBlocks::AIR()); + $this->getWorld()->addSound($block->getPosition()->add(0.5, 0.5, 0.5), new FireExtinguishSound()); + return true; + } + + if (!$this->isCreative() || !$block->getBreakInfo()->breaksInstantly()) { + $this->blockBreakHandlerCustom = new SurvivalBlockBreakHandler($this, $pos, $target, $face, 16); + } + + return true; + } + + public function continueBreakBlock(Vector3 $pos, int $face): void { + if ($this->blockBreakHandlerCustom !== null && $this->blockBreakHandlerCustom->getBlockPos()->distanceSquared($pos) < 0.0001) { + $this->blockBreakHandlerCustom->setTargetedFace($face); + if (($this->blockBreakHandlerCustom->getBreakProgress() + $this->blockBreakHandlerCustom->getBreakSpeed()) >= 0.80) { + $pos = $this->blockBreakHandlerCustom->getBlockPos(); + $this->breakBlock($pos); + } + } + } + + public function stopBreakBlock(Vector3 $pos): void { + if ($this->blockBreakHandlerCustom !== null && $this->blockBreakHandlerCustom->getBlockPos()->distanceSquared($pos) < 0.0001) { + $this->blockBreakHandlerCustom = null; + } else parent::stopBreakBlock($pos); + } + + public function onUpdate(int $currentTick): bool { + if ($this->blockBreakHandlerCustom !== null && !$this->blockBreakHandlerCustom->update()) { + $this->blockBreakHandlerCustom = null; + } + return parent::onUpdate($currentTick); + } +} \ No newline at end of file diff --git a/src/Entity/CustomiesEntityFactory.php b/src/Entity/CustomiesEntityFactory.php new file mode 100644 index 00000000..a5cdc737 --- /dev/null +++ b/src/Entity/CustomiesEntityFactory.php @@ -0,0 +1,44 @@ +register($entityClass, $customClosure, [$identifier]); + if($isCustomEntity){ + $this->registerAvailableActorIdentifiers($identifier); + } + } + + public function registerAvailableActorIdentifiers(string $networkId) : void{ + StaticPacketCache::getInstance()->getAvailableActorIdentifiers()->identifiers->getRoot()->getListTag("idlist")->push(CompoundTag::create() + ->setByte("hasspawnegg", 1) + ->setString("id", $networkId) + ->setInt("rid", self::$ID++) + ->setByte("summonable", 1)); + } +} \ No newline at end of file diff --git a/src/item/component/AllowOffHandComponent.php b/src/Items/Components/AllowOffHandComponent.php similarity index 56% rename from src/item/component/AllowOffHandComponent.php rename to src/Items/Components/AllowOffHandComponent.php index 337f8a02..c6324229 100644 --- a/src/item/component/AllowOffHandComponent.php +++ b/src/Items/Components/AllowOffHandComponent.php @@ -1,16 +1,12 @@ offHand = $offHand; } diff --git a/src/Items/Components/ArmorComponent.php b/src/Items/Components/ArmorComponent.php new file mode 100644 index 00000000..e95c3fef --- /dev/null +++ b/src/Items/Components/ArmorComponent.php @@ -0,0 +1,40 @@ +protection = $protection; + $this->textureType = $textureType; + } + + public function getName(): string { + return "minecraft:armor"; + } + + public function getValue(): array { + return [ + "protection" => $this->protection, + "texture_type" => $this->textureType + ]; + } + + public function isProperty(): bool { + return false; + } +} \ No newline at end of file diff --git a/src/Items/Components/BlockPlacerComponent.php b/src/Items/Components/BlockPlacerComponent.php new file mode 100644 index 00000000..55803145 --- /dev/null +++ b/src/Items/Components/BlockPlacerComponent.php @@ -0,0 +1,31 @@ +blockIdentifier = $blockIdentifier; + $this->useBlockDescription = $useBlockDescription; + } + + public function getName(): string { + return "minecraft:block_placer"; + } + + public function getValue(): array { + return [ + "block" => $this->blockIdentifier, + "use_block_description" => $this->useBlockDescription + ]; + } + + public function isProperty(): bool { + return false; + } +} diff --git a/src/Items/Components/BundleInteractionComponent.php b/src/Items/Components/BundleInteractionComponent.php new file mode 100644 index 00000000..e9a484a6 --- /dev/null +++ b/src/Items/Components/BundleInteractionComponent.php @@ -0,0 +1,32 @@ +numViewableSlots = $numViewableSlots; + } + + public function getName(): string { + return "minecraft:bundle_interaction"; + } + + public function getValue(): array { + return [ + "num_viewable_slots" => $this->numViewableSlots + ]; + } + + public function isProperty(): bool { + return false; + } +} \ No newline at end of file diff --git a/src/Items/Components/CanDestroyInCreativeComponent.php b/src/Items/Components/CanDestroyInCreativeComponent.php new file mode 100644 index 00000000..b9395d24 --- /dev/null +++ b/src/Items/Components/CanDestroyInCreativeComponent.php @@ -0,0 +1,25 @@ +canDestroyInCreative = $canDestroyInCreative; + } + + public function getName(): string { + return "can_destroy_in_creative"; + } + + public function getValue(): bool { + return $this->canDestroyInCreative; + } + + public function isProperty(): bool { + return true; + } +} diff --git a/src/Items/Components/ChargeableComponent.php b/src/Items/Components/ChargeableComponent.php new file mode 100644 index 00000000..a7cd6c06 --- /dev/null +++ b/src/Items/Components/ChargeableComponent.php @@ -0,0 +1,27 @@ +movementModifier = $movementModifier; + } + + public function getName(): string { + return "minecraft:chargeable"; + } + + public function getValue(): array { + return [ + "movement_modifier" => $this->movementModifier + ]; + } + + public function isProperty(): bool { + return false; + } +} \ No newline at end of file diff --git a/src/Items/Components/CooldownComponent.php b/src/Items/Components/CooldownComponent.php new file mode 100644 index 00000000..631ede8f --- /dev/null +++ b/src/Items/Components/CooldownComponent.php @@ -0,0 +1,30 @@ +category = $category; + $this->duration = $duration; + } + + public function getName(): string { + return "minecraft:cooldown"; + } + + public function getValue(): array { + return [ + "category" => $this->category, + "duration" => $this->duration + ]; + } + + public function isProperty(): bool { + return false; + } +} \ No newline at end of file diff --git a/src/Items/Components/DamageAbsorptionComponent.php b/src/Items/Components/DamageAbsorptionComponent.php new file mode 100644 index 00000000..8d4c6f7f --- /dev/null +++ b/src/Items/Components/DamageAbsorptionComponent.php @@ -0,0 +1,32 @@ +absorbableCauses = $absorbableCauses; + } + + public function getName(): string { + return "minecraft:damage_absorption"; + } + + public function getValue(): array { + return [ + "absorbable_causes" => $this->absorbableCauses + ]; + } + + public function isProperty(): bool { + return false; + } +} \ No newline at end of file diff --git a/src/Items/Components/DamageComponent.php b/src/Items/Components/DamageComponent.php new file mode 100644 index 00000000..739886e2 --- /dev/null +++ b/src/Items/Components/DamageComponent.php @@ -0,0 +1,23 @@ +damage = $damage; + } + + public function getName(): string { + return "damage"; + } + + public function getValue(): int { + return $this->damage; + } + + public function isProperty(): bool { + return true; + } +} \ No newline at end of file diff --git a/src/Items/Components/DiggerComponent.php b/src/Items/Components/DiggerComponent.php new file mode 100644 index 00000000..ab4b1f0d --- /dev/null +++ b/src/Items/Components/DiggerComponent.php @@ -0,0 +1,55 @@ +efficiency = $efficiency; + } + + public function getName(): string { + return "minecraft:digger"; + } + + public function getValue(): array { + return [ + "use_efficiency" => $this->efficiency, + "destroy_speeds" => $this->destroySpeeds + ]; + } + + public function isProperty(): bool { + return false; + } + + public function withBlocks(int $speed, Block ...$blocks): DiggerComponent { + foreach($blocks as $block){ + $this->destroySpeeds[] = [ + "block" => GlobalBlockStateHandlers::getSerializer()->serialize($block->getStateId())->getName(), + "speed" => $speed + ]; + } + return $this; + } + + public function withTags(int $speed, string ...$tags): DiggerComponent { + $this->destroySpeeds[] = [ + "block" => [ + "tags" => "query.any_tag(" . implode(",", array_map(fn($tag) => "'" . $tag . "'", $tags)) . ")" + ], + "speed" => $speed + ]; + return $this; + } +} \ No newline at end of file diff --git a/src/item/component/DisplayNameComponent.php b/src/Items/Components/DisplayNameComponent.php similarity index 50% rename from src/item/component/DisplayNameComponent.php rename to src/Items/Components/DisplayNameComponent.php index 28ad340b..fa8d5819 100644 --- a/src/item/component/DisplayNameComponent.php +++ b/src/Items/Components/DisplayNameComponent.php @@ -1,17 +1,12 @@ name = $name; } diff --git a/src/Items/Components/DurabilityComponent.php b/src/Items/Components/DurabilityComponent.php new file mode 100644 index 00000000..924f6e30 --- /dev/null +++ b/src/Items/Components/DurabilityComponent.php @@ -0,0 +1,27 @@ +maxDurability = $maxDurability; + } + + public function getName(): string { + return "minecraft:durability"; + } + + public function getValue(): array { + return [ + "max_durability" => $this->maxDurability + ]; + } + + public function isProperty(): bool { + return false; + } +} \ No newline at end of file diff --git a/src/Items/Components/DyeableComponent.php b/src/Items/Components/DyeableComponent.php new file mode 100644 index 00000000..b6e536c0 --- /dev/null +++ b/src/Items/Components/DyeableComponent.php @@ -0,0 +1,27 @@ +hex = $hex; + } + + public function getName(): string { + return "minecraft:dyeable"; + } + + public function getValue(): array { + return [ + "default_color" => $this->hex + ]; + } + + public function isProperty(): bool { + return false; + } +} \ No newline at end of file diff --git a/src/Items/Components/EnchantableSlotComponent.php b/src/Items/Components/EnchantableSlotComponent.php new file mode 100644 index 00000000..91f5f460 --- /dev/null +++ b/src/Items/Components/EnchantableSlotComponent.php @@ -0,0 +1,48 @@ +slot = $slot; + } + + public function getName(): string { + return "enchantable_slot"; + } + + public function getValue(): string { + return $this->slot; + } + + public function isProperty(): bool { + return true; + } +} \ No newline at end of file diff --git a/src/Items/Components/EnchantableValueComponent.php b/src/Items/Components/EnchantableValueComponent.php new file mode 100644 index 00000000..223d7d46 --- /dev/null +++ b/src/Items/Components/EnchantableValueComponent.php @@ -0,0 +1,47 @@ +value = $value; + } + + public function getName(): string { + return "enchantable_value"; + } + + public function getValue(): int { + return $this->value; + } + + public function isProperty(): bool { + return true; + } +} \ No newline at end of file diff --git a/src/Items/Components/FoilComponent.php b/src/Items/Components/FoilComponent.php new file mode 100644 index 00000000..0dc80d40 --- /dev/null +++ b/src/Items/Components/FoilComponent.php @@ -0,0 +1,25 @@ +foil = $foil; + } + + public function getName(): string { + return "foil"; + } + + public function getValue(): bool { + return $this->foil; + } + + public function isProperty(): bool { + return true; + } +} \ No newline at end of file diff --git a/src/Items/Components/FoodComponent.php b/src/Items/Components/FoodComponent.php new file mode 100644 index 00000000..d056f060 --- /dev/null +++ b/src/Items/Components/FoodComponent.php @@ -0,0 +1,27 @@ +canAlwaysEat = $canAlwaysEat; + } + + public function getName(): string { + return "minecraft:food"; + } + + public function getValue(): array { + return [ + "can_always_eat" => $this->canAlwaysEat + ]; + } + + public function isProperty(): bool { + return false; + } +} \ No newline at end of file diff --git a/src/Items/Components/FrameCountComponent.php b/src/Items/Components/FrameCountComponent.php new file mode 100644 index 00000000..8ba8d52c --- /dev/null +++ b/src/Items/Components/FrameCountComponent.php @@ -0,0 +1,28 @@ +framecount = $framecount; + } + + public function getName(): string + { + return "minecraft:frame_count"; + } + + public function getValue(): int + { + return $this->framecount; + } + + public function isProperty(): bool + { + return true; + } +} \ No newline at end of file diff --git a/src/item/component/FuelComponent.php b/src/Items/Components/FuelComponent.php similarity index 57% rename from src/item/component/FuelComponent.php rename to src/Items/Components/FuelComponent.php index f86e8554..e64185f8 100644 --- a/src/item/component/FuelComponent.php +++ b/src/Items/Components/FuelComponent.php @@ -1,16 +1,12 @@ duration = $duration; } diff --git a/src/item/component/HandEquippedComponent.php b/src/Items/Components/HandEquippedComponent.php similarity index 59% rename from src/item/component/HandEquippedComponent.php rename to src/Items/Components/HandEquippedComponent.php index dad02413..7e84f0c8 100644 --- a/src/item/component/HandEquippedComponent.php +++ b/src/Items/Components/HandEquippedComponent.php @@ -1,16 +1,12 @@ handEquipped = $handEquipped; } diff --git a/src/Items/Components/HoverTextColorComponent.php b/src/Items/Components/HoverTextColorComponent.php new file mode 100644 index 00000000..b37a4479 --- /dev/null +++ b/src/Items/Components/HoverTextColorComponent.php @@ -0,0 +1,26 @@ +value = $value; + } + + public function getName(): string { + return "hover_text_color"; + } + + public function getValue(): string { + return $this->value; + } + + public function isProperty(): bool { + return true; + } +} \ No newline at end of file diff --git a/src/Items/Components/IconComponent.php b/src/Items/Components/IconComponent.php new file mode 100644 index 00000000..592a09d4 --- /dev/null +++ b/src/Items/Components/IconComponent.php @@ -0,0 +1,29 @@ +texture = $texture; + } + + public function getName(): string { + return "minecraft:icon"; + } + + public function getValue(): array { + return [ + "textures" => [ + "default" => $this->texture + ] + ]; + } + + public function isProperty(): bool { + return true; + } +} diff --git a/src/Items/Components/InteractButtonComponent.php b/src/Items/Components/InteractButtonComponent.php new file mode 100644 index 00000000..9ab1e886 --- /dev/null +++ b/src/Items/Components/InteractButtonComponent.php @@ -0,0 +1,36 @@ +interactButton = "action.interact.use"; + }else{ + $this->interactButton = (string) $interactButton; + } + } + + public function getName(): string { + return "minecraft:interact_button"; + } + + public function getValue(): array { + return [ + "interact_text" => (string) $this->interactButton, + "requires_interact" => 1 + ]; + } + + public function isProperty(): bool { + return false; + } +} \ No newline at end of file diff --git a/src/Items/Components/ItemComponentBase.php b/src/Items/Components/ItemComponentBase.php new file mode 100644 index 00000000..7f7d4eee --- /dev/null +++ b/src/Items/Components/ItemComponentBase.php @@ -0,0 +1,12 @@ +components[$component->getName()] = $component; + } + + /** + * @param array $components + */ + public function hasComponent(ItemComponentBase|string $component): bool + { + return isset($this->components[$component->getName()]); + } + + public function getComponents(): CompoundTag + { + $components = CompoundTag::create(); + $properties = CompoundTag::create(); + foreach($this->components as $component){ + $tag = NBT::getTagType($component->getValue()); + if($tag === null) { + throw new RuntimeException("Failed to get tag type for component " . $component->getName()); + } + if($component->isProperty()) { + $properties->setTag($component->getName(), $tag); + continue; + } + $components->setTag($component->getName(), $tag); + } + $components->setTag("item_properties", $properties); + return CompoundTag::create() + ->setTag("components", $components); + } + + public function initComponent(string $texture, CreativeInventoryInfo $creativeInventoryInfo): void + { + CreativeItemManager::getInstance()->AddItemOnGroup($this, $creativeInventoryInfo); + $this->addComponent(new IconComponent($texture)); + $this->addComponent(new DisplayNameComponent($this->getName())); + $count = $this->getMaxStackSize(); + $this->addComponent(new MaxStackSizeComponent($count)); + $this->addComponent(new CanDestroyInCreativeComponent(true)); + + + //NE PAS TOUCHER !!! + if ( + $this instanceof Axe || + $this instanceof Pickaxe || + $this instanceof Shovel || + $this instanceof Hoe + ) { + $this->addComponent(new HandEquippedComponent(true)); + } + if ($this instanceof Sword) { + $this->addComponent(new CanDestroyInCreativeComponent(false)); + $this->addComponent(new HandEquippedComponent(true)); + } + if ($this instanceof CustomArmor) { + $this->addComponent(new ArmorComponent($this->getDefensePoints())); + $this->addComponent(new WearableComponent($this->getArmor(), $this->getDefensePoints(), $this->getToughness())); + } + + if ($this instanceof Durable) { + $this->addComponent(new DurabilityComponent($this->getMaxDurability())); + } + + if (!$this->getFuelTime() <= 0) { + $this->addComponent(new FuelComponent($this->getFuelTime())); + } + + if($this instanceof ProjectileItem) { + $this->addComponent(new ProjectileComponent("projectile")); + $this->addComponent(new ThrowableComponent(true)); + } + + if($this instanceof Consumable) { + if(($food = $this instanceof Food)) { + $this->addComponent(new FoodComponent(!$this->requiresHunger())); + } + $this->addComponent(new UseAnimationComponent($food ? UseAnimationComponent::ANIMATION_EAT : UseAnimationComponent::ANIMATION_DRINK)); + } + } +} \ No newline at end of file diff --git a/src/Items/Components/KnockbackResistanceComponent.php b/src/Items/Components/KnockbackResistanceComponent.php new file mode 100644 index 00000000..7a8c87b6 --- /dev/null +++ b/src/Items/Components/KnockbackResistanceComponent.php @@ -0,0 +1,27 @@ +protection = $protection; + } + + public function getName(): string { + return "minecraft:knockback_resistance"; + } + + public function getValue(): array { + return [ + "protection" => $this->protection + ]; + } + + public function isProperty(): bool { + return false; + } +} \ No newline at end of file diff --git a/src/Items/Components/LiquidClippedComponent.php b/src/Items/Components/LiquidClippedComponent.php new file mode 100644 index 00000000..6f7f3ae9 --- /dev/null +++ b/src/Items/Components/LiquidClippedComponent.php @@ -0,0 +1,29 @@ +liquidClipped = $liquidClipped; + } + + public function getName(): string { + return "liquid_clipped"; + } + + public function getValue(): bool { + return $this->liquidClipped; + } + + public function isProperty(): bool { + return true; + } +} \ No newline at end of file diff --git a/src/item/component/MaxStackSizeComponent.php b/src/Items/Components/MaxStackSizeComponent.php similarity index 50% rename from src/item/component/MaxStackSizeComponent.php rename to src/Items/Components/MaxStackSizeComponent.php index 4d2327a1..9d48c650 100644 --- a/src/item/component/MaxStackSizeComponent.php +++ b/src/Items/Components/MaxStackSizeComponent.php @@ -1,17 +1,13 @@ maxStackSize = $maxStackSize; } diff --git a/src/Items/Components/ProjectileComponent.php b/src/Items/Components/ProjectileComponent.php new file mode 100644 index 00000000..50ca2694 --- /dev/null +++ b/src/Items/Components/ProjectileComponent.php @@ -0,0 +1,27 @@ +projectileEntity = $projectileEntity; + } + + public function getName(): string { + return "minecraft:projectile"; + } + + public function getValue(): array { + return [ + "projectile_entity" => $this->projectileEntity + ]; + } + + public function isProperty(): bool { + return false; + } +} \ No newline at end of file diff --git a/src/Items/Components/RarityComponent.php b/src/Items/Components/RarityComponent.php new file mode 100644 index 00000000..37a1ee35 --- /dev/null +++ b/src/Items/Components/RarityComponent.php @@ -0,0 +1,27 @@ +rarity = $rarity; + } + + public function getName(): string { + return "minecraft:rarity"; //common, uncommon, rare, epic + } + + public function getValue(): array { + return [ + "value" => $this->rarity + ]; + } + + public function isProperty(): bool { + return false; + } +} \ No newline at end of file diff --git a/src/Items/Components/RecordComponent.php b/src/Items/Components/RecordComponent.php new file mode 100644 index 00000000..a5911559 --- /dev/null +++ b/src/Items/Components/RecordComponent.php @@ -0,0 +1,35 @@ +cs = $cs; + $this->duration = $duration; + $this->sound = $sound; + } + + public function getName(): string { + return "minecraft:record"; + } + + public function getValue(): array { + return [ + "comparator_signal" => $this->cs, + "duration" => $this->duration, + "sound_event" => $this->sound + ]; + } + + public function isProperty(): bool { + return false; + } +} \ No newline at end of file diff --git a/src/Items/Components/RenderOffsetsComponent.php b/src/Items/Components/RenderOffsetsComponent.php new file mode 100644 index 00000000..9fa07190 --- /dev/null +++ b/src/Items/Components/RenderOffsetsComponent.php @@ -0,0 +1,48 @@ +textureSize = $textureSize; + } + + public function getName(): string { + return "minecraft:render_offsets"; + } + + public function getValue(): array { + $textureSize = $this->textureSize; + $mainHand_fp = round(0.039 * 16 / $textureSize, 8); + $offhand_fp = round(0.065 * 16 / $textureSize, 8); + $mainHand_tp = $offhand_tp = round(0.0965 * 16 / $textureSize, 8); + + return [ + "main_hand" => [ + "first_person" => [ + "scale" => [$mainHand_fp, $mainHand_fp, $mainHand_fp], + ], + "third_person" => [ + "scale" => [$mainHand_tp, $mainHand_tp, $mainHand_tp] + ] + ], + "off_hand" => [ + "first_person" => [ + "scale" => [$offhand_fp, $offhand_fp, $offhand_fp], + ], + "third_person" => [ + "scale" => [$offhand_tp, $offhand_tp, $offhand_tp] + ] + ] + ]; + } + + public function isProperty(): bool { + return false; + } +} \ No newline at end of file diff --git a/src/Items/Components/ShooterComponent.php b/src/Items/Components/ShooterComponent.php new file mode 100644 index 00000000..62c7cd35 --- /dev/null +++ b/src/Items/Components/ShooterComponent.php @@ -0,0 +1,61 @@ +item = $item; + $this->useOffhand = $useOffhand; + $this->searchInventory = $searchInventory; + $this->useInCreative = $useInCreative; + $this->chargeOnDraw = $chargeOnDraw; + $this->maxDrawDuration = $maxDrawDuration; + $this->scalePowerByDrawDuration = $scalePowerByDrawDuration; + } + + public function getName(): string { + return "minecraft:shooter"; + } + + public function getValue(): array { + return [ + "ammunition" => [ + [ + "item" => $this->item, + "use_offhand" => $this->useOffhand, + "search_inventory" => $this->searchInventory, + "use_in_creative" => $this->useInCreative + ] + ], + "charge_on_draw" => $this->chargeOnDraw, + "max_draw_duration" => $this->maxDrawDuration, + "launch_power_scale" => $this->scalePowerByDrawDuration + ]; + } + + public function isProperty(): bool { + return false; + } +} \ No newline at end of file diff --git a/src/Items/Components/ShouldDespawnComponent.php b/src/Items/Components/ShouldDespawnComponent.php new file mode 100644 index 00000000..455dca3b --- /dev/null +++ b/src/Items/Components/ShouldDespawnComponent.php @@ -0,0 +1,29 @@ +shouldDespawn = $shouldDespawn; + } + + public function getName(): string { + return "should_despawn"; + } + + public function getValue(): bool { + return $this->shouldDespawn; + } + + public function isProperty(): bool { + return true; + } +} \ No newline at end of file diff --git a/src/Items/Components/StorageItemComponent.php b/src/Items/Components/StorageItemComponent.php new file mode 100644 index 00000000..8832e139 --- /dev/null +++ b/src/Items/Components/StorageItemComponent.php @@ -0,0 +1,38 @@ +maxslots = $maxslots; + $this->ansi = $ansi; + $this->banned_items = $banned_items; + } + + public function getName(): string { + return "minecraft:storage_item"; //common, uncommon, rare, epic + } + + + public function getValue(): array { + return [ + "value" => [ + "max_slots" => $this->maxslots, + "allow_nested_storage_items"=> $this->ansi, + "banned_items"=> $this->banned_items + ] + ]; + } + + public function isProperty(): bool { + return true; + } +} \ No newline at end of file diff --git a/src/Items/Components/ThrowableComponent.php b/src/Items/Components/ThrowableComponent.php new file mode 100644 index 00000000..deeee64c --- /dev/null +++ b/src/Items/Components/ThrowableComponent.php @@ -0,0 +1,27 @@ +doSwingAnimation = $doSwingAnimation; + } + + public function getName(): string { + return "minecraft:throwable"; + } + + public function getValue(): array { + return [ + "do_swing_animation" => $this->doSwingAnimation + ]; + } + + public function isProperty(): bool { + return false; + } +} \ No newline at end of file diff --git a/src/Items/Components/TrimmableComponent.php b/src/Items/Components/TrimmableComponent.php new file mode 100644 index 00000000..6992478c --- /dev/null +++ b/src/Items/Components/TrimmableComponent.php @@ -0,0 +1,22 @@ + + ["minecraft:trimmable_armors"] + ]; + } + + public function isProperty(): bool { + return false; + } +} \ No newline at end of file diff --git a/src/Items/Components/UseAnimationComponent.php b/src/Items/Components/UseAnimationComponent.php new file mode 100644 index 00000000..5d9a84bc --- /dev/null +++ b/src/Items/Components/UseAnimationComponent.php @@ -0,0 +1,28 @@ +animation = $animation; + } + + public function getName(): string { + return "use_animation"; + } + + public function getValue(): mixed { + return $this->animation; + } + + public function isProperty(): bool { + return true; + } +} \ No newline at end of file diff --git a/src/Items/Components/UseDurationComponent.php b/src/Items/Components/UseDurationComponent.php new file mode 100644 index 00000000..3978a44f --- /dev/null +++ b/src/Items/Components/UseDurationComponent.php @@ -0,0 +1,25 @@ +duration = $duration; + } + + public function getName(): string { + return "use_duration"; + } + + public function getValue(): int { + return $this->duration; + } + + public function isProperty(): bool { + return true; + } +} \ No newline at end of file diff --git a/src/Items/Components/UseModifiersComponent.php b/src/Items/Components/UseModifiersComponent.php new file mode 100644 index 00000000..001a9404 --- /dev/null +++ b/src/Items/Components/UseModifiersComponent.php @@ -0,0 +1,35 @@ +useDuration = $useDuration; + $this->movementModifier = $movementModifier; + } + + public function getName(): string { + return "minecraft:use_modifiers"; + } + + public function getValue(): array { + return [ + "movement_modifier" => $this->movementModifier, + "use_duration" => $this->useDuration + ]; + } + + public function isProperty(): bool { + return false; + } +} \ No newline at end of file diff --git a/src/item/component/WearableComponent.php b/src/Items/Components/WearableComponent.php similarity index 59% rename from src/item/component/WearableComponent.php rename to src/Items/Components/WearableComponent.php index 29a25ae8..ade8058e 100644 --- a/src/item/component/WearableComponent.php +++ b/src/Items/Components/WearableComponent.php @@ -1,9 +1,9 @@ slot = $slot; - $this->protection = $protection; - $this->dispensable = $dispensable; + $this->protection = $protection; + $this->toughness = $toughness; } public function getName(): string { @@ -43,8 +38,8 @@ public function getName(): string { public function getValue(): array { return [ "slot" => $this->slot, - "protection" => $this->protection, - "dispensable" => $this->dispensable + "protection" => $this->protection, + "toughness" => $this->toughness ]; } diff --git a/src/Items/CustomArmor.php b/src/Items/CustomArmor.php new file mode 100644 index 00000000..754c6232 --- /dev/null +++ b/src/Items/CustomArmor.php @@ -0,0 +1,13 @@ +itemTableEntries); + } + + public function getAll(): array + { + return $this->items; + } + + public function get(string $identifier): Item + { + $item = StringToItemParser::getInstance()->parse($identifier); + if ($item === null) { + return VanillaBlocks::DIRT()->asItem(); + } + return $item; + } + + public function registerItem(string $className, string $identifier, string $name): void { + if($className !== Item::class) { + Utils::testValidInstance($className, Item::class); + } + + $itemId = ItemTypeIds::newId(); + $itemIdentifier = new ItemIdentifier($itemId); + + $item = new $className($itemIdentifier, $name); + + /*if ($item instanceof Tool && $item instanceof ItemComponents) { + $item->addComponent(new HandEquippedComponent(true)); + }*/ + + $nbt = ($componentBased = $item instanceof ItemComponents) ? $item->getComponents() + ->setInt("id", $itemId) + ->setString("name", $identifier) : CompoundTag::create(); + + $this->itemTableEntries[$identifier] = $entry = new ItemTypeEntry($identifier, $itemId, $componentBased, $componentBased ? 1 : 0, new CacheableNbt($nbt)); + $this->registerCustomItemMapping($entry); + + GlobalItemDataHandlers::getDeserializer()->map($identifier, fn() => clone $item); + GlobalItemDataHandlers::getSerializer()->map($item, fn() => new SavedItemData($identifier)); + + StringToItemParser::getInstance()->register($identifier, fn() => clone $item); + + //Servers::$customItems[] = $item; + $this->items[] = $item; + + $this->count++; + } + + public function registerCustomItemMapping(ItemTypeEntry $itemTypeEntry) : void { + $dictionary = TypeConverter::getInstance()->getItemTypeDictionary(); + $reflection = new ReflectionClass($dictionary); + + $intToString = $reflection->getProperty("intToStringIdMap"); + /** @var int[] $value */ + $value = $intToString->getValue($dictionary); + $intToString->setValue($dictionary, $value + [$itemTypeEntry->getNumericId() => $itemTypeEntry->getStringId()]); + + $stringToInt = $reflection->getProperty("stringToIntMap"); + /** @var int[] $value */ + $value = $stringToInt->getValue($dictionary); + $stringToInt->setValue($dictionary, $value + [$itemTypeEntry->getStringId() => $itemTypeEntry->getNumericId()]); + $itemTypesProperty = $reflection->getProperty('itemTypes'); + $itemTypesProperty->setValue($dictionary, array_merge($itemTypesProperty->getValue($dictionary), [$itemTypeEntry])); + } + + public function getRegisteredItemCount(): int { + return $this->count; + } + + public function registerBlockItem(ItemTypeEntry $entry): void { + $this->registerCustomItemMapping($entry); + $blockItemIdMap = BlockItemIdMap::getInstance(); + $reflection = new \ReflectionClass($blockItemIdMap); + + $itemToBlockId = $reflection->getProperty("itemToBlockId"); + /** @var string[] $value */ + $value = $itemToBlockId->getValue($blockItemIdMap); + $itemToBlockId->setValue($blockItemIdMap, $value + [$entry->getStringId() => $entry->getStringId()]); + } +} \ No newline at end of file diff --git a/src/SurvivalBlockBreakHandler.php b/src/SurvivalBlockBreakHandler.php new file mode 100644 index 00000000..4d4ebcaf --- /dev/null +++ b/src/SurvivalBlockBreakHandler.php @@ -0,0 +1,122 @@ +breakSpeed = $this->calculateBreakProgressPerTick(); + if ($this->breakSpeed > 0) { + $this->player->getWorld()->broadcastPacketToViewers( + $this->blockPos, + LevelEventPacket::create(LevelEvent::BLOCK_START_BREAK, (int)(65535 * $this->breakSpeed), $this->blockPos) + ); + } + } + + /** + * Returns the calculated break speed as percentage progress per game tick. + */ + private function calculateBreakProgressPerTick(): float + { + if (!$this->block->getBreakInfo()->isBreakable()) { + return 0.0; + } + $breakTimePerTick = $this->block->getBreakInfo()->getBreakTime($this->player->getInventory()->getItemInHand()) * 30; + + if ($breakTimePerTick > 0) { + return 1 / $breakTimePerTick; + } + return 1; + } + + public function update(): bool + { + if($this->player->getPosition()->distanceSquared($this->blockPos->add(0.5, 0.5, 0.5)) > $this->maxPlayerDistance ** 2){ + return false; + } + + $newBreakSpeed = $this->calculateBreakProgressPerTick(); + if(abs($newBreakSpeed - $this->breakSpeed) > 0.0001){ + $this->breakSpeed = $newBreakSpeed; + //TODO: sync with client + } + + $this->breakProgress += $this->breakSpeed; + + if(($this->fxTicker++ % $this->fxTickInterval) === 0){ + $this->player->getWorld()->addSound($this->blockPos, new BlockPunchSound($this->block)); + $this->player->getWorld()->addParticle($this->blockPos, new BlockPunchParticle($this->block, $this->targetedFace)); + $this->player->broadcastAnimation(new ArmSwingAnimation($this->player), $this->player->getViewers()); + } + + if ($this->breakProgress >= 1) { + $this->player->breakBlock($this->blockPos); + return false; + } + + return true; + } + + public function getBlockPos(): Vector3 + { + return $this->blockPos; + } + + public function getTargetedFace(): int + { + return $this->targetedFace; + } + + public function setTargetedFace(int $face): void + { + Facing::validate($face); + $this->targetedFace = $face; + } + + public function getBreakSpeed(): float + { + return $this->breakSpeed; + } + + public function getBreakProgress(): float + { + return $this->breakProgress; + } + + public function __destruct() + { + if ($this->player->getWorld()->isInLoadedTerrain($this->blockPos)) { + $this->player->getWorld()->broadcastPacketToViewers( + $this->blockPos, + LevelEventPacket::create(LevelEvent::BLOCK_STOP_BREAK, 0, $this->blockPos) + ); + } + } + +} \ No newline at end of file diff --git a/src/Tasks/AsyncRegisterBlocksTask.php b/src/Tasks/AsyncRegisterBlocksTask.php new file mode 100644 index 00000000..39b08fec --- /dev/null +++ b/src/Tasks/AsyncRegisterBlocksTask.php @@ -0,0 +1,43 @@ + $blockFuncs + */ + public function __construct(private string $cachePath, array $blockFuncs) { + $this->blockFuncs = new ThreadSafeArray(); + $this->serializer = new ThreadSafeArray(); + $this->deserializer = new ThreadSafeArray(); + + foreach($blockFuncs as $identifier => [$blockFunc, $serializer, $deserializer]){ + $this->blockFuncs[$identifier] = $blockFunc; + $this->serializer[$identifier] = $serializer; + $this->deserializer[$identifier] = $deserializer; + } + } + + public function onRun(): void { + foreach($this->blockFuncs as $identifier => $blockFunc){ + CustomiesBlockFactory::getInstance()->iniBlock(); + + CustomiesBlockFactory::getInstance()->registerBlock($blockFunc, $identifier, serializer: $this->serializer[$identifier], deserializer: $this->deserializer[$identifier]); + } + } +} \ No newline at end of file diff --git a/src/Utils/CreativeInventoryInfo.php b/src/Utils/CreativeInventoryInfo.php new file mode 100644 index 00000000..93a4ff6f --- /dev/null +++ b/src/Utils/CreativeInventoryInfo.php @@ -0,0 +1,125 @@ +category; + } + + /** + * Returns the numeric representation of the category the item is part of. + */ + public function getNumericCategory(): int { + return match ($this->getCategory()) { + self::CATEGORY_CONSTRUCTION => 1, + self::CATEGORY_NATURE => 2, + self::CATEGORY_EQUIPMENT => 3, + self::CATEGORY_ITEMS => 4, + default => 0 + }; + } + + /** + * Returns the group the item is part of, if any. + */ + public function getGroup(): string { + return $this->group; + } +} \ No newline at end of file diff --git a/src/Utils/CreativeItemManager.php b/src/Utils/CreativeItemManager.php new file mode 100644 index 00000000..ee23ce17 --- /dev/null +++ b/src/Utils/CreativeItemManager.php @@ -0,0 +1,60 @@ +getContentChangedCallbacks()->add(function() : void{ + }); + } + + private function loadGroups() : void{ + if($this->groups !== []){ + return; + } + foreach(CreativeInventory::getInstance()->getAllEntries() as $entry){ + $group = $entry->getGroup(); + if($group !== null){ + $this->groups[$group->getName()->getText()] = $group; + } + } + } + + public function AddItemOnGroup(Item $item, CreativeInventoryInfo $creativeInfo) : void{ + $this->loadGroups(); + if($creativeInfo->getCategory() === CreativeInventoryInfo::CATEGORY_ALL || $creativeInfo->getCategory() === CreativeInventoryInfo::CATEGORY_COMMANDS){ + return; + } + $group = $this->groups[$creativeInfo->getGroup()] ?? ($creativeInfo->getGroup() !== "" && $creativeInfo->getGroup() !== CreativeInventoryInfo::NONE ? new CreativeGroup( + new Translatable($creativeInfo->getGroup()), + $item + ) : null); + if($group !== null){ + $this->groups[$group->getName()->getText()] = $group; + } + if ($creativeInfo->getCategory() === CreativeInventoryInfo::NONE) { + return; + } + $category = match ($creativeInfo->getCategory()) { //wait, can we add existing groups in different categories here? + CreativeInventoryInfo::CATEGORY_CONSTRUCTION => CreativeCategory::CONSTRUCTION, + CreativeInventoryInfo::CATEGORY_ITEMS => CreativeCategory::ITEMS, + CreativeInventoryInfo::CATEGORY_NATURE => CreativeCategory::NATURE, + CreativeInventoryInfo::CATEGORY_EQUIPMENT => CreativeCategory::EQUIPMENT, + /*, + default => throw new AssumptionFailedError("Unknown category")*/ + }; + CreativeInventory::getInstance()->remove($item); + CreativeInventory::getInstance()->add($item, $category, $group); + } +} \ No newline at end of file diff --git a/src/util/NBT.php b/src/Utils/NBT.php similarity index 97% rename from src/util/NBT.php rename to src/Utils/NBT.php index 0ef9cadc..c98902de 100644 --- a/src/util/NBT.php +++ b/src/Utils/NBT.php @@ -1,7 +1,7 @@ - */ - private array $blockFuncs = []; - /** @var BlockPaletteEntry[] */ - private array $blockPaletteEntries = []; - /** @var array */ - private array $customBlocks = []; - private array $groups = []; - - /** - * Adds a worker initialize hook to the async pool to sync the BlockFactory for every thread worker that is created. - * It is especially important for the workers that deal with chunk encoding, as using the wrong runtime ID mappings - * can result in massive issues with almost every block showing as the wrong thing and causing lag to clients. - */ - public function addWorkerInitHook(string $cachePath): void { - $server = Server::getInstance(); - $blocks = $this->blockFuncs; - $server->getAsyncPool()->addWorkerStartHook(static function (int $worker) use ($cachePath, $server, $blocks): void { - $server->getAsyncPool()->submitTaskToWorker(new AsyncRegisterBlocksTask($cachePath, $blocks), $worker); - }); - } - - /** - * Get a custom block from its identifier. An exception will be thrown if the block is not registered. - */ - public function get(string $identifier): Block { - return clone ( - $this->customBlocks[$identifier] ?? - throw new InvalidArgumentException("Custom block $identifier is not registered") - ); - } - - private function loadGroups() : void { - if($this->groups !== []){ - return; - } - foreach(CreativeInventory::getInstance()->getAllEntries() as $entry){ - $group = $entry->getGroup(); - if($group !== null){ - $this->groups[$group->getName()->getText()] = $group; - } - } - } - - /** - * Returns all the block palette entries that need to be sent to the client. - * @return BlockPaletteEntry[] - */ - public function getBlockPaletteEntries(): array { - return $this->blockPaletteEntries; - } - - /** - * Register a block to the BlockFactory and all the required mappings. A custom stateReader and stateWriter can be - * provided to allow for custom block state serialization. - * @phpstan-param (Closure(): Block) $blockFunc - * @phpstan-param null|(Closure(BlockStateWriter): Block) $serializer - * @phpstan-param null|(Closure(Block): BlockStateReader) $deserializer - */ - public function registerBlock(Closure $blockFunc, string $identifier, ?CreativeInventoryInfo $creativeInfo = null, ?Closure $serializer = null, ?Closure $deserializer = null): void { - $block = $blockFunc(); - if(!$block instanceof Block) { - throw new InvalidArgumentException("Class returned from closure is not a Block"); - } - - RuntimeBlockStateRegistry::getInstance()->register($block); - CustomiesItemFactory::getInstance()->registerBlockItem($identifier, $block); - $this->customBlocks[$identifier] = $block; - - $propertiesTag = CompoundTag::create(); - $components = CompoundTag::create(); - if($block instanceof BlockComponents) { - foreach ($block->getComponents() as $component) { - $components->setTag($component->getName(), $component->getValue()); - } - } - - if($block instanceof Permutable) { - $blockPropertyNames = $blockPropertyValues = $blockProperties = []; - foreach($block->getBlockProperties() as $blockProperty){ - $blockPropertyNames[] = $blockProperty->getName(); - $blockPropertyValues[] = $blockProperty->getValues(); - $blockProperties[] = $blockProperty->toNBT(); - } - $permutations = array_map(static fn(Permutation $permutation) => $permutation->toNBT(), $block->getPermutations()); - - // The 'minecraft:on_player_placing' component is required for the client to predict block placement, making - // it a smoother experience for the end-user. - $components->setTag("minecraft:on_player_placing", CompoundTag::create()); - $propertiesTag - ->setTag("permutations", new ListTag($permutations)) - ->setTag("properties", new ListTag(array_reverse($blockProperties))); // fix client-side order - - foreach(Permutations::getCartesianProduct($blockPropertyValues) as $meta => $permutations){ - // We need to insert states for every possible permutation to allow for all blocks to be used and to - // keep in sync with the client's block palette. - $states = CompoundTag::create(); - foreach($permutations as $i => $value){ - $states->setTag($blockPropertyNames[$i], NBT::getTagType($value)); - } - $blockState = CompoundTag::create() - ->setString(BlockStateData::TAG_NAME, $identifier) - ->setTag(BlockStateData::TAG_STATES, $states); - BlockPalette::getInstance()->insertState($blockState, $meta); - } - - $serializer ??= static function (Permutable $block) use ($identifier, $blockPropertyNames) : BlockStateWriter { - $b = BlockStateWriter::create($identifier); - $block->serializeState($b); - return $b; - }; - $deserializer ??= static function (BlockStateReader $in) use ($block, $identifier, $blockPropertyNames) : Permutable { - $b = CustomiesBlockFactory::getInstance()->get($identifier); - assert($b instanceof Permutable); - $b->deserializeState($in); - return $b; - }; - } else { - // If a block does not contain any permutations we can just insert the one state. - $blockState = CompoundTag::create() - ->setString(BlockStateData::TAG_NAME, $identifier) - ->setTag(BlockStateData::TAG_STATES, CompoundTag::create()); - BlockPalette::getInstance()->insertState($blockState); - $serializer ??= static fn() => new BlockStateWriter($identifier); - $deserializer ??= static fn(BlockStateReader $in) => $block; - } - GlobalBlockStateHandlers::getSerializer()->map($block, $serializer); - GlobalBlockStateHandlers::getDeserializer()->map($identifier, $deserializer); - - $creativeInfo ??= CreativeInventoryInfo::DEFAULT(); - $propertiesTag - ->setTag("components", - $components->setTag("minecraft:creative_category", CompoundTag::create() - ->setString("category", $creativeInfo->getCategory()) - ->setString("group", $creativeInfo->getGroup()))) - ->setTag("menu_category", CompoundTag::create() - ->setString("category", $creativeInfo->getCategory() ?? "") - ->setString("group", $creativeInfo->getGroup() ?? "")) - ->setInt("molangVersion", 1); - - if($creativeInfo !== null){ - $this->loadGroups(); - if($creativeInfo->getCategory() === CreativeInventoryInfo::CATEGORY_ALL || $creativeInfo->getCategory() === CreativeInventoryInfo::CATEGORY_COMMANDS){ - return; - } - - $group = $this->groups[$creativeInfo->getGroup()] ?? ($creativeInfo->getGroup() !== "" && $creativeInfo->getGroup() !== CreativeInventoryInfo::NONE ? new CreativeGroup( - new Translatable($creativeInfo->getGroup()), - $block->asItem() - ) : null); - - if($group !== null){ - $this->groups[$group->getName()->getText()] = $group; - } - - $category = match ($creativeInfo->getCategory()) { - CreativeInventoryInfo::CATEGORY_CONSTRUCTION => CreativeCategory::CONSTRUCTION, - CreativeInventoryInfo::CATEGORY_ITEMS => CreativeCategory::ITEMS, - CreativeInventoryInfo::CATEGORY_NATURE => CreativeCategory::NATURE, - CreativeInventoryInfo::CATEGORY_EQUIPMENT => CreativeCategory::EQUIPMENT, - default => throw new AssumptionFailedError("Unknown category") - }; - - CreativeInventory::getInstance()->add($block->asItem(), $category, $group); - } - - $this->blockPaletteEntries[] = new BlockPaletteEntry($identifier, new CacheableNbt($propertiesTag)); - $this->blockFuncs[$identifier] = [$blockFunc, $serializer, $deserializer]; - - // 1.20.60 added a new "block_id" field which depends on the order of the block palette entries. Every time we - // insert a new block, we need to re-sort the block palette entries to keep in sync with the client. - usort($this->blockPaletteEntries, static function(BlockPaletteEntry $a, BlockPaletteEntry $b): int { - return strcmp(hash("fnv164", $a->getName()), hash("fnv164", $b->getName())); - }); - foreach($this->blockPaletteEntries as $i => $entry) { - $root = $entry->getStates()->getRoot() - ->setTag("vanilla_block_data", CompoundTag::create() - ->setInt("block_id", 10000 + $i)); - $this->blockPaletteEntries[$i] = new BlockPaletteEntry($entry->getName(), new CacheableNbt($root)); - } - } -} diff --git a/src/block/component/SelectionBoxComponent.php b/src/block/component/SelectionBoxComponent.php deleted file mode 100644 index 2f0ebce6..00000000 --- a/src/block/component/SelectionBoxComponent.php +++ /dev/null @@ -1,46 +0,0 @@ -useSelectionBox = $useSelectionBox; - $this->origin = $origin; - $this->size = $size; - } - - public function getName(): string { - return "minecraft:selection_box"; - } - - public function getValue(): CompoundTag { - return CompoundTag::create() - ->setByte("enabled", $this->useSelectionBox ? 1 : 0) - ->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()) - ])); - } -} \ No newline at end of file diff --git a/src/entity/CustomiesEntityFactory.php b/src/entity/CustomiesEntityFactory.php deleted file mode 100644 index e6da13ac..00000000 --- a/src/entity/CustomiesEntityFactory.php +++ /dev/null @@ -1,47 +0,0 @@ - $className - * @phpstan-param Closure(World $world, CompoundTag $nbt) : Entity $creationFunc - */ - public function registerEntity(string $className, string $identifier, ?Closure $creationFunc = null, string $behaviourId = ""): void { - EntityFactory::getInstance()->register($className, $creationFunc ?? static function (World $world, CompoundTag $nbt) use ($className): Entity { - return new $className(EntityDataHelper::parseLocation($nbt, $world), $nbt); - }, [$identifier]); - $this->updateStaticPacketCache($identifier, $behaviourId); - } - - private function updateStaticPacketCache(string $identifier, string $behaviourId): void { - $instance = StaticPacketCache::getInstance(); - $property = (new ReflectionClass($instance))->getProperty("availableActorIdentifiers"); - /** @var AvailableActorIdentifiersPacket $packet */ - $packet = $property->getValue($instance); - /** @var CompoundTag $root */ - $root = $packet->identifiers->getRoot(); - ($root->getListTag("idlist") ?? new ListTag())->push(CompoundTag::create() - ->setString("id", $identifier) - ->setString("bid", $behaviourId)); - $packet->identifiers = new CacheableNbt($root); - } -} diff --git a/src/item/CreativeInventoryInfo.php b/src/item/CreativeInventoryInfo.php deleted file mode 100644 index 9b1eb5da..00000000 --- a/src/item/CreativeInventoryInfo.php +++ /dev/null @@ -1,125 +0,0 @@ -category; - } - - /** - * Returns the numeric representation of the category the item is part of. - */ - public function getNumericCategory(): int { - return match ($this->getCategory()) { - self::CATEGORY_CONSTRUCTION => 1, - self::CATEGORY_NATURE => 2, - self::CATEGORY_EQUIPMENT => 3, - self::CATEGORY_ITEMS => 4, - default => 0 - }; - } - - /** - * Returns the group the item is part of, if any. - */ - public function getGroup(): string { - return $this->group; - } -} \ No newline at end of file diff --git a/src/item/CustomiesItemFactory.php b/src/item/CustomiesItemFactory.php deleted file mode 100644 index 69275125..00000000 --- a/src/item/CustomiesItemFactory.php +++ /dev/null @@ -1,194 +0,0 @@ -parse($identifier); - if($item === null) { - throw new InvalidArgumentException("Custom item " . $identifier . " is not registered"); - } - return $item->setCount($amount); - } - - private function loadGroups() : void { - if($this->groups !== []){ - return; - } - foreach(CreativeInventory::getInstance()->getAllEntries() as $entry){ - $group = $entry->getGroup(); - if($group !== null){ - $this->groups[$group->getName()->getText()] = $group; - } - } - } - - /** - * Returns custom item entries - * @return ItemTypeEntry[] - */ - public function getItemTableEntries(): array { - return array_values($this->itemTableEntries); - } - - /** - * Registers the item to the item factory and assigns it an ID. It also updates the required mappings and stores the - * item components if present. - * @phpstan-param class-string $className - */ - public function registerItem(Closure $itemFunc, string $identifier, ?CreativeInventoryInfo $creativeInfo = null): void { - $item = $itemFunc(); - if(!$item instanceof Item) { - throw new InvalidArgumentException("Class returned from closure is not a Item"); - } - $itemId = $item->getTypeId(); - - GlobalItemDataHandlers::getDeserializer()->map($identifier, fn() => clone $item); - GlobalItemDataHandlers::getSerializer()->map($item, fn() => new SavedItemData($identifier)); - - StringToItemParser::getInstance()->register($identifier, fn() => clone $item); - - // This is where the components are added to the item - $componentBased = $item instanceof ItemComponents; - $nbt = $this->createItemNbt($item, $identifier, $itemId, $creativeInfo); - - if($creativeInfo !== null){ - $this->loadGroups(); - if($creativeInfo->getCategory() === CreativeInventoryInfo::CATEGORY_ALL || $creativeInfo->getCategory() === CreativeInventoryInfo::CATEGORY_COMMANDS){ - return; - } - - $group = $this->groups[$creativeInfo->getGroup()] ?? ($creativeInfo->getGroup() !== "" && $creativeInfo->getGroup() !== CreativeInventoryInfo::NONE ? new CreativeGroup( - new Translatable($creativeInfo->getGroup()), - $item - ) : null); - - if($group !== null){ - $this->groups[$group->getName()->getText()] = $group; - } - - $category = match ($creativeInfo->getCategory()) { - CreativeInventoryInfo::CATEGORY_CONSTRUCTION => CreativeCategory::CONSTRUCTION, - CreativeInventoryInfo::CATEGORY_ITEMS => CreativeCategory::ITEMS, - CreativeInventoryInfo::CATEGORY_NATURE => CreativeCategory::NATURE, - CreativeInventoryInfo::CATEGORY_EQUIPMENT => CreativeCategory::EQUIPMENT, - default => throw new AssumptionFailedError("Unknown category") - }; - - CreativeInventory::getInstance()->add($item, $category, $group); - } - - $this->itemTableEntries[$identifier] = $entry = new ItemTypeEntry($identifier, $itemId, $componentBased, $componentBased ? 1 : 0, new CacheableNbt($nbt)); - $this->registerCustomItemMapping($identifier, $itemId, $entry); - } - - /** - * Creates the NBT data for the item. - */ - private function createItemNbt(Item $item, string $identifier, int $itemId, ?CreativeInventoryInfo $creativeInfo): CompoundTag { - $components = CompoundTag::create(); - $properties = CompoundTag::create(); - - if ($item instanceof ItemComponents) { - foreach ($item->getComponents() as $component) { - $tag = NBT::getTagType($component->getValue()); - if ($tag === null) { - throw new RuntimeException("Failed to get tag type for component " . $component->getName()); - } - if ($component->isProperty()) { - $properties->setTag($component->getName(), $tag); - continue; - } - $components->setTag($component->getName(), $tag); - } - if ($creativeInfo !== null) { - $properties->setTag("creative_category", NBT::getTagType($creativeInfo->getNumericCategory())); - $properties->setTag("creative_group", NBT::getTagType($creativeInfo->getGroup())); - } - $components->setTag("item_properties", $properties); - return CompoundTag::create() - ->setTag("components", $components) - ->setInt("id", $itemId) - ->setString("name", $identifier); - } - return CompoundTag::create(); - } - - /** - * Registers a custom item ID to the required mappings in the global ItemTypeDictionary instance. - */ - private function registerCustomItemMapping(string $identifier, int $itemId, ItemTypeEntry $entry): void { - $dictionary = TypeConverter::getInstance()->getItemTypeDictionary(); - $reflection = new ReflectionClass($dictionary); - - $intToString = $reflection->getProperty("intToStringIdMap"); - /** @var int[] $value */ - $value = $intToString->getValue($dictionary); - $intToString->setValue($dictionary, $value + [$itemId => $identifier]); - - $stringToInt = $reflection->getProperty("stringToIntMap"); - /** @var int[] $value */ - $value = $stringToInt->getValue($dictionary); - $stringToInt->setValue($dictionary, $value + [$identifier => $itemId]); - - $itemTypes = $reflection->getProperty("itemTypes"); - $value = $itemTypes->getValue($dictionary); - $value[] = $entry; - $itemTypes->setValue($dictionary, $value); - } - - /** - * Registers the required mappings for the block to become an item that can be placed etc. It is assigned an ID that - * correlates to its block ID. - */ - public function registerBlockItem(string $identifier, Block $block): void { - $itemId = $block->getIdInfo()->getBlockTypeId(); - StringToItemParser::getInstance()->registerBlock($identifier, fn() => clone $block); - $this->itemTableEntries[] = $entry = new ItemTypeEntry($identifier, $itemId, false, 2, new CacheableNbt(CompoundTag::create())); - $this->registerCustomItemMapping($identifier, $itemId, $entry); - - $blockItemIdMap = BlockItemIdMap::getInstance(); - $reflection = new ReflectionClass($blockItemIdMap); - - $itemToBlockId = $reflection->getProperty("itemToBlockId"); - /** @var string[] $value */ - $value = $itemToBlockId->getValue($blockItemIdMap); - $itemToBlockId->setValue($blockItemIdMap, $value + [$identifier => $identifier]); - } -} diff --git a/src/item/ItemComponents.php b/src/item/ItemComponents.php deleted file mode 100644 index cb3c60d7..00000000 --- a/src/item/ItemComponents.php +++ /dev/null @@ -1,30 +0,0 @@ -components[$component->getName()] = $component; - } - - public function hasComponent(string $name): bool { - return isset($this->components[$name]); - } - - /** - * @return ItemComponent[] - */ - public function getComponents(): array { - return $this->components; - } - - /** - * Initializes the item with default components that are required for the item to function correctly. - */ - protected function initComponent(string $texture): void { - $this->addComponent(new IconComponent($texture)); - $this->addComponent(new CanDestroyInCreativeComponent()); - $this->addComponent(new MaxStackSizeComponent($this->getMaxStackSize())); - - if($this instanceof Armor) { - $slot = match ($this->getArmorSlot()) { - ArmorInventory::SLOT_HEAD => WearableComponent::SLOT_ARMOR_HEAD, - ArmorInventory::SLOT_CHEST => WearableComponent::SLOT_ARMOR_CHEST, - ArmorInventory::SLOT_LEGS => WearableComponent::SLOT_ARMOR_LEGS, - ArmorInventory::SLOT_FEET => WearableComponent::SLOT_ARMOR_FEET, - default => WearableComponent::SLOT_ARMOR - }; - $this->addComponent(new WearableComponent($slot, $this->getDefensePoints())); - } - - if($this instanceof Consumable) { - if(($food = $this instanceof Food)) { - $this->addComponent(new FoodComponent(!$this->requiresHunger())); - } - $this->addComponent(new UseAnimationComponent($food ? UseAnimationComponent::ANIMATION_EAT : UseAnimationComponent::ANIMATION_DRINK)); - $this->setUseDuration(20); - } - - if($this instanceof Durable) { - $this->addComponent(new DurabilityComponent($this->getMaxDurability())); - } - - if($this instanceof ProjectileItem) { - $this->addComponent(new ProjectileComponent(1.25, "projectile")); - $this->addComponent(new ThrowableComponent(true)); - } - - if($this->getName() !== "Unknown") { - $this->addComponent(new DisplayNameComponent($this->getName())); - } - - if($this->getFuelTime() > 0) { - $this->addComponent(new FuelComponent($this->getFuelTime())); - } - - if($this->getAttackPoints() > 0) { - $this->addComponent(new DamageComponent($this->getAttackPoints())); - } - - if($this instanceof Tool) { - $this->addComponent(new HandEquippedComponent()); - if ($this instanceof Sword) { - $this->addComponent(new CanDestroyInCreativeComponent(false)); - } - } - } -} diff --git a/src/item/component/BlockPlacerComponent.php b/src/item/component/BlockPlacerComponent.php deleted file mode 100644 index 2a0953ba..00000000 --- a/src/item/component/BlockPlacerComponent.php +++ /dev/null @@ -1,49 +0,0 @@ -block = $block; - } - - public function getName(): string { - return "minecraft:block_placer"; - } - - public function getValue(): array { - return [ - "block" => GlobalBlockStateHandlers::getSerializer()->serialize($this->block->getStateId())->getName(), - "use_on" => $this->useOn - ]; - } - - public function isProperty(): bool { - return false; - } - - /** - * Add blocks to the `use_on` array in the required format. - * @param Block ...$blocks - */ - public function useOn(Block ...$blocks): self{ - foreach($blocks as $block){ - $this->useOn[] = [ - "name" => GlobalBlockStateHandlers::getSerializer()->serialize($block->getStateId())->getName() - ]; - } - return $this; - } -} \ No newline at end of file diff --git a/src/item/component/BundleInteractionComponent.php b/src/item/component/BundleInteractionComponent.php deleted file mode 100644 index 79e446fc..00000000 --- a/src/item/component/BundleInteractionComponent.php +++ /dev/null @@ -1,32 +0,0 @@ -numViewableSlots = $numViewableSlots; - } - - public function getName(): string { - return "minecraft:bundle_interaction"; - } - - public function getValue(): array { - return [ - "num_viewable_slots" => $this->numViewableSlots - ]; - } - - public function isProperty(): bool { - return false; - } -} \ No newline at end of file diff --git a/src/item/component/CanDestroyInCreativeComponent.php b/src/item/component/CanDestroyInCreativeComponent.php deleted file mode 100644 index 0c7c6d5f..00000000 --- a/src/item/component/CanDestroyInCreativeComponent.php +++ /dev/null @@ -1,29 +0,0 @@ -canDestroyInCreative = $canDestroyInCreative; - } - - public function getName(): string { - return "can_destroy_in_creative"; - } - - public function getValue(): bool { - return $this->canDestroyInCreative; - } - - public function isProperty(): bool { - return true; - } -} diff --git a/src/item/component/CooldownComponent.php b/src/item/component/CooldownComponent.php deleted file mode 100644 index 54f025a4..00000000 --- a/src/item/component/CooldownComponent.php +++ /dev/null @@ -1,42 +0,0 @@ -category = $category; - $this->duration = $duration; - } - - public function getName(): string { - return "minecraft:cooldown"; - } - - public function getValue(): array { - return [ - "category" => $this->category, - "duration" => $this->duration - ]; - } - - public function isProperty(): bool { - return false; - } -} \ No newline at end of file diff --git a/src/item/component/DamageAbsorptionComponent.php b/src/item/component/DamageAbsorptionComponent.php deleted file mode 100644 index 0acd6270..00000000 --- a/src/item/component/DamageAbsorptionComponent.php +++ /dev/null @@ -1,32 +0,0 @@ -absorbableCauses = $absorbableCauses; - } - - public function getName(): string { - return "minecraft:damage_absorption"; - } - - public function getValue(): array { - return [ - "absorbable_causes" => $this->absorbableCauses - ]; - } - - public function isProperty(): bool { - return false; - } -} \ No newline at end of file diff --git a/src/item/component/DamageComponent.php b/src/item/component/DamageComponent.php deleted file mode 100644 index 95a22a6e..00000000 --- a/src/item/component/DamageComponent.php +++ /dev/null @@ -1,29 +0,0 @@ -damage = $damage; - } - - public function getName(): string { - return "damage"; - } - - public function getValue(): int { - return $this->damage; - } - - public function isProperty(): bool { - return true; - } -} \ No newline at end of file diff --git a/src/item/component/DiggerComponent.php b/src/item/component/DiggerComponent.php deleted file mode 100644 index 2f2e761c..00000000 --- a/src/item/component/DiggerComponent.php +++ /dev/null @@ -1,71 +0,0 @@ -useEfficiency = $useEfficiency; - } - - public function getName(): string { - return "minecraft:digger"; - } - - public function getValue(): array { - return [ - "use_efficiency" => $this->useEfficiency, - "destroy_speeds" => $this->destroySpeeds - ]; - } - - public function isProperty(): bool { - return false; - } - - /** - * Add blocks to the `destroy_speeds` array in the required format. - * @param int $speed Digging speed for the correlating block(s) - * @param Block ...$blocks A list of blocks to dig with correlating speeds of digging - */ - public function withBlocks(int $speed, Block ...$blocks): DiggerComponent { - foreach($blocks as $block){ - $this->destroySpeeds[] = [ - "block" => [ - "name" => GlobalBlockStateHandlers::getSerializer()->serialize($block->getStateId())->getName() - ], - "speed" => $speed - ]; - } - return $this; - } - - /** - * Add blocks to the `destroy_speeds` array in the required format. - * @param int $speed Digging speed for the correlating block(s) - * @param string ...$tags A list of blocks to dig with correlating speeds of digging - */ - public function withTags(int $speed, string ...$tags): DiggerComponent { - $query = implode(",", array_map(fn($tag) => "'" . $tag . "'", $tags)); - $this->destroySpeeds[] = [ - "block" => [ - "tags" => "query.any_tag(" . $query . ")" - ], - "speed" => $speed - ]; - return $this; - } -} \ No newline at end of file diff --git a/src/item/component/DurabilityComponent.php b/src/item/component/DurabilityComponent.php deleted file mode 100644 index 3cc9847e..00000000 --- a/src/item/component/DurabilityComponent.php +++ /dev/null @@ -1,41 +0,0 @@ -maxDurability = $maxDurability; - $this->minDamageChance = $minDamageChance; - $this->maxDamageChance = $maxDamageChance; - } - - public function getName(): string { - return "minecraft:durability"; - } - - public function getValue(): array { - return [ - "damage_chance" => [ - "min" => $this->minDamageChance, - "max" => $this->maxDamageChance - ], - "max_durability" => $this->maxDurability - ]; - } - - public function isProperty(): bool { - return false; - } -} \ No newline at end of file diff --git a/src/item/component/DyeableComponent.php b/src/item/component/DyeableComponent.php deleted file mode 100644 index 563c0ec8..00000000 --- a/src/item/component/DyeableComponent.php +++ /dev/null @@ -1,31 +0,0 @@ -hex = $hex; - } - - public function getName(): string { - return "minecraft:dyeable"; - } - - public function getValue(): array { - return [ - "default_color" => $this->hex - ]; - } - - public function isProperty(): bool { - return false; - } -} \ No newline at end of file diff --git a/src/item/component/EnchantableSlotComponent.php b/src/item/component/EnchantableSlotComponent.php deleted file mode 100644 index f97b520b..00000000 --- a/src/item/component/EnchantableSlotComponent.php +++ /dev/null @@ -1,48 +0,0 @@ -slot = $slot; - } - - public function getName(): string { - return "enchantable_slot"; - } - - public function getValue(): string { - return $this->slot; - } - - public function isProperty(): bool { - return true; - } -} \ No newline at end of file diff --git a/src/item/component/EnchantableValueComponent.php b/src/item/component/EnchantableValueComponent.php deleted file mode 100644 index 80963464..00000000 --- a/src/item/component/EnchantableValueComponent.php +++ /dev/null @@ -1,47 +0,0 @@ -value = $value; - } - - public function getName(): string { - return "enchantable_value"; - } - - public function getValue(): int { - return $this->value; - } - - public function isProperty(): bool { - return true; - } -} \ No newline at end of file diff --git a/src/item/component/FoodComponent.php b/src/item/component/FoodComponent.php deleted file mode 100644 index a06a855b..00000000 --- a/src/item/component/FoodComponent.php +++ /dev/null @@ -1,45 +0,0 @@ -canAlwaysEat = $canAlwaysEat; - $this->nutrition = $nutrition; - $this->saturationModifier = $saturationModifier; - $this->usingConvertsTo = $usingConvertsTo; - } - - public function getName(): string { - return "minecraft:food"; - } - - public function getValue(): array { - return [ - "can_always_eat" => $this->canAlwaysEat, - "nutrition" => $this->nutrition, - "saturation_modifier" => $this->saturationModifier, - "using_converts_to" => [ - "name" => $this->usingConvertsTo - ] - ]; - } - - public function isProperty(): bool { - return false; - } -} \ No newline at end of file diff --git a/src/item/component/GlintComponent.php b/src/item/component/GlintComponent.php deleted file mode 100644 index 5a9b2c19..00000000 --- a/src/item/component/GlintComponent.php +++ /dev/null @@ -1,29 +0,0 @@ -glint = $glint; - } - - public function getName(): string { - return "foil"; - } - - public function getValue(): bool { - return $this->glint; - } - - public function isProperty(): bool { - return true; - } -} \ No newline at end of file diff --git a/src/item/component/HoverTextColorComponent.php b/src/item/component/HoverTextColorComponent.php deleted file mode 100644 index 2947145f..00000000 --- a/src/item/component/HoverTextColorComponent.php +++ /dev/null @@ -1,30 +0,0 @@ -hoverTextColor = $hoverTextColor; - } - - public function getName(): string { - return "hover_text_color"; - } - - public function getValue(): string { - return $this->hoverTextColor; - } - - public function isProperty(): bool { - return true; - } -} \ No newline at end of file diff --git a/src/item/component/IconComponent.php b/src/item/component/IconComponent.php deleted file mode 100644 index dd92a950..00000000 --- a/src/item/component/IconComponent.php +++ /dev/null @@ -1,42 +0,0 @@ -default_texture = $default_texture; - $this->dyed_texture = $dyed_texture; - $this->trim_texture = $trim_texture; - } - - public function getName(): string { - return "minecraft:icon"; - } - - public function getValue(): array { - return [ - "texture" => $this->default_texture, - "textures" => [ - "default" => $this->default_texture, - "dyed" => $this->dyed_texture, - "icon_trim" => $this->trim_texture - ] - ]; - } - - public function isProperty(): bool { - return true; - } -} \ No newline at end of file diff --git a/src/item/component/InteractButtonComponent.php b/src/item/component/InteractButtonComponent.php deleted file mode 100644 index fa24a019..00000000 --- a/src/item/component/InteractButtonComponent.php +++ /dev/null @@ -1,36 +0,0 @@ -interactButton = "action.interact.use"; - }else{ - $this->interactButton = (string) $interactButton; - } - } - - public function getName(): string { - return "minecraft:interact_button"; - } - - public function getValue(): array { - return [ - "interact_text" => (string) $this->interactButton, - "requires_interact" => 1 - ]; - } - - public function isProperty(): bool { - return false; - } -} \ No newline at end of file diff --git a/src/item/component/ItemComponent.php b/src/item/component/ItemComponent.php deleted file mode 100644 index 4f50fa56..00000000 --- a/src/item/component/ItemComponent.php +++ /dev/null @@ -1,13 +0,0 @@ -liquidClipped = $liquidClipped; - } - - public function getName(): string { - return "liquid_clipped"; - } - - public function getValue(): bool { - return $this->liquidClipped; - } - - public function isProperty(): bool { - return true; - } -} \ No newline at end of file diff --git a/src/item/component/ProjectileComponent.php b/src/item/component/ProjectileComponent.php deleted file mode 100644 index 215ad273..00000000 --- a/src/item/component/ProjectileComponent.php +++ /dev/null @@ -1,37 +0,0 @@ -minimumCriticalPower = $minimumCriticalPower; - $this->projectileEntity = $projectileEntity; - } - - public function getName(): string { - return "minecraft:projectile"; - } - - public function getValue(): array { - return [ - "minimum_critical_power" => $this->minimumCriticalPower, - "projectile_entity" => $this->projectileEntity - ]; - } - - public function isProperty(): bool { - return false; - } -} \ No newline at end of file diff --git a/src/item/component/RarityComponent.php b/src/item/component/RarityComponent.php deleted file mode 100644 index 7ee3a185..00000000 --- a/src/item/component/RarityComponent.php +++ /dev/null @@ -1,37 +0,0 @@ -rarity = $rarity; - } - - public function getName(): string { - return "minecraft:rarity"; - } - - public function getValue(): array { - return [ - "value" => $this->rarity - ]; - } - - public function isProperty(): bool { - return false; - } -} \ No newline at end of file diff --git a/src/item/component/RecordComponent.php b/src/item/component/RecordComponent.php deleted file mode 100644 index 7728d9d4..00000000 --- a/src/item/component/RecordComponent.php +++ /dev/null @@ -1,39 +0,0 @@ -comparatorSignal = $comparatorSignal; - $this->duration = $duration; - $this->soundEvent = $soundEvent; - } - - public function getName(): string { - return "minecraft:record"; - } - - public function getValue(): array { - return [ - "comparator_signal" => $this->comparatorSignal, - "duration" => $this->duration, - "sound_event" => $this->soundEvent - ]; - } - - public function isProperty(): bool { - return false; - } -} \ No newline at end of file diff --git a/src/item/component/ShooterComponent.php b/src/item/component/ShooterComponent.php deleted file mode 100644 index 14f0e813..00000000 --- a/src/item/component/ShooterComponent.php +++ /dev/null @@ -1,61 +0,0 @@ -item = $item; - $this->useOffhand = $useOffhand; - $this->searchInventory = $searchInventory; - $this->useInCreative = $useInCreative; - $this->chargeOnDraw = $chargeOnDraw; - $this->maxDrawDuration = $maxDrawDuration; - $this->scalePowerByDrawDuration = $scalePowerByDrawDuration; - } - - public function getName(): string { - return "minecraft:shooter"; - } - - public function getValue(): array { - return [ - "ammunition" => [ - [ - "item" => $this->item, - "use_offhand" => $this->useOffhand, - "search_inventory" => $this->searchInventory, - "use_in_creative" => $this->useInCreative - ] - ], - "charge_on_draw" => $this->chargeOnDraw, - "max_draw_duration" => $this->maxDrawDuration, - "scale_power_by_draw_duration" => $this->scalePowerByDrawDuration - ]; - } - - public function isProperty(): bool { - return false; - } -} \ No newline at end of file diff --git a/src/item/component/ShouldDespawnComponent.php b/src/item/component/ShouldDespawnComponent.php deleted file mode 100644 index 126f8d54..00000000 --- a/src/item/component/ShouldDespawnComponent.php +++ /dev/null @@ -1,29 +0,0 @@ -shouldDespawn = $shouldDespawn; - } - - public function getName(): string { - return "should_despawn"; - } - - public function getValue(): bool { - return $this->shouldDespawn; - } - - public function isProperty(): bool { - return true; - } -} \ No newline at end of file diff --git a/src/item/component/StackedByDataComponent.php b/src/item/component/StackedByDataComponent.php deleted file mode 100644 index 1eddb16f..00000000 --- a/src/item/component/StackedByDataComponent.php +++ /dev/null @@ -1,30 +0,0 @@ -stackedByData = $stackedByData; - } - - public function getName(): string { - return "stacked_by_data"; - } - - public function getValue(): bool { - return $this->stackedByData; - } - - public function isProperty(): bool { - return true; - } -} \ No newline at end of file diff --git a/src/item/component/ThrowableComponent.php b/src/item/component/ThrowableComponent.php deleted file mode 100644 index 8edcc94d..00000000 --- a/src/item/component/ThrowableComponent.php +++ /dev/null @@ -1,51 +0,0 @@ -doSwingAnimation = $doSwingAnimation; - $this->launchPowerScale = $launchPowerScale; - $this->maxDrawDuration = $maxDrawDuration; - $this->maxLaunchPower = $maxLaunchPower; - $this->minDrawDuration = $minDrawDuration; - $this->scalePowerByDrawDuration = $scalePowerByDrawDuration; - } - - public function getName(): string { - return "minecraft:throwable"; - } - - public function getValue(): array { - return [ - "do_swing_animation" => $this->doSwingAnimation, - "launch_power_scale" => $this->launchPowerScale, - "max_draw_duration" => $this->maxDrawDuration, - "max_launch_power" => $this->maxLaunchPower, - "min_draw_duration" => $this->minDrawDuration, - "scale_power_by_draw_duration" => $this->scalePowerByDrawDuration - ]; - } - - public function isProperty(): bool { - return false; - } -} \ No newline at end of file diff --git a/src/item/component/UseAnimationComponent.php b/src/item/component/UseAnimationComponent.php deleted file mode 100644 index deafdffc..00000000 --- a/src/item/component/UseAnimationComponent.php +++ /dev/null @@ -1,40 +0,0 @@ -animation = $animation; - } - - public function getName(): string { - return "use_animation"; - } - - public function getValue(): int { - return $this->animation; - } - - public function isProperty(): bool { - return true; - } -} \ No newline at end of file diff --git a/src/item/component/UseDurationComponent.php b/src/item/component/UseDurationComponent.php deleted file mode 100644 index 5c8b654e..00000000 --- a/src/item/component/UseDurationComponent.php +++ /dev/null @@ -1,29 +0,0 @@ -duration = $duration; - } - - public function getName(): string { - return "use_duration"; - } - - public function getValue(): int { - return $this->duration; - } - - public function isProperty(): bool { - return true; - } -} \ No newline at end of file diff --git a/src/item/component/UseModifiersComponent.php b/src/item/component/UseModifiersComponent.php deleted file mode 100644 index a4a6b11a..00000000 --- a/src/item/component/UseModifiersComponent.php +++ /dev/null @@ -1,35 +0,0 @@ -useDuration = $useDuration; - $this->movementModifier = $movementModifier; - } - - public function getName(): string { - return "minecraft:use_modifiers"; - } - - public function getValue(): array { - return [ - "movement_modifier" => $this->movementModifier, - "use_duration" => $this->useDuration - ]; - } - - public function isProperty(): bool { - return false; - } -} \ No newline at end of file diff --git a/src/task/AsyncRegisterBlocksTask.php b/src/task/AsyncRegisterBlocksTask.php deleted file mode 100644 index 1600d837..00000000 --- a/src/task/AsyncRegisterBlocksTask.php +++ /dev/null @@ -1,42 +0,0 @@ - $blockFuncs - */ - public function __construct(private string $cachePath, array $blockFuncs) { - $this->blockFuncs = new ThreadSafeArray(); - $this->serializer = new ThreadSafeArray(); - $this->deserializer = new ThreadSafeArray(); - - foreach($blockFuncs as $identifier => [$blockFunc, $serializer, $deserializer]){ - $this->blockFuncs[$identifier] = $blockFunc; - $this->serializer[$identifier] = $serializer; - $this->deserializer[$identifier] = $deserializer; - } - } - - public function onRun(): void { - 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, serializer: $this->serializer[$identifier], deserializer: $this->deserializer[$identifier]); - } - } -}