Compare commits

...

67 Commits

Author SHA1 Message Date
66f2116e57 Release 5.0.0-ALPHA2 2022-07-14 22:54:28 +01:00
c15c59ae0d changelog for 5.0.0-ALPHA2
[ci skip]
2022-07-14 22:52:07 +01:00
07786dc4bc RuntimeDataWriter: fixed doc comment 2022-07-14 22:51:12 +01:00
259f44e57c Merge branch 'next-minor' into next-major 2022-07-14 22:05:04 +01:00
93254523e6 Merge branch 'stable' into next-minor 2022-07-14 22:04:38 +01:00
2b61c025c2 Workaround items in blockentity NBT not being processed correctly in 1.19.10
closes #5154

this hack sends only the bare essential data to create the tiles in LevelChunkPacket,
and then separately sending the full tile data using BlockActorDataPacket afterwards.

This is necessary because the client doesn't handle items correctly in NBT when chunks are sent without using the SubChunkRequest system.
In 4.6 this is observed with incorrect items shown in item frames; in 5.0 it's seen with items simply not showing up at all (difference due to modernization of the serialization format in 5.0).
2022-07-14 21:54:01 +01:00
e5804df24b Merge branch 'next-minor' into next-major 2022-07-14 20:59:13 +01:00
e00f8e3a32 Merge branch 'stable' into next-minor 2022-07-14 20:59:06 +01:00
c8320fe849 Merge branch 'next-minor' into next-major 2022-07-14 20:50:49 +01:00
e2855aadff Simplify handling of broken transactions for crafting and friends
this allows stuff like smithing tables to work without needing any extra hacks.

Implementing enchanting or anvils would require some extra work, but I don't plan to implement those under the legacy transaction system anyway.
2022-07-14 20:50:06 +01:00
21ed5a450f Updated BlockFactory consistency check 2022-07-14 20:42:16 +01:00
ba2baba7cc Added netherite blocks and items 2022-07-14 20:39:09 +01:00
c7133bc2e6 InGamePacketHandler: don't kick the player out of inventory windows on actor events
this is sent when the player crafts something using an anvil.
2022-07-14 20:36:11 +01:00
d4f4fda442 Merge branch 'next-minor' into next-major 2022-07-14 19:54:50 +01:00
4d6ec66270 Merge branch 'stable' into next-minor 2022-07-14 19:54:38 +01:00
baf75089f5 Entity: cancel fire damage for fireproof entities 2022-07-14 19:53:25 +01:00
b4ce5ed515 ItemDeserializer: throw a more specific exception on unknown items 2022-07-14 19:16:15 +01:00
eb8fb63409 Added cartography and smithing tables
these have working inventories, and their crafting menus will 'just work' once the items for the associated recipes have been implemented (maps, netherite).
2022-07-14 18:01:47 +01:00
Ali
705df7d508 EffectManager: remove redundant check (#5153) 2022-07-14 17:56:18 +01:00
91719051e2 BlockStateToBlockObjectDeserializer: removed TODO mess
these were useful when writing the initial version from scratch; not so much for implementing random blocks
2022-07-14 16:50:08 +01:00
d321094081 Added hanging roots 2022-07-14 16:47:55 +01:00
323d31005f Added glowing item frames 2022-07-14 16:24:20 +01:00
0c7370e564 Added wither rose 2022-07-14 16:07:16 +01:00
3dd4c42fd3 Merge branch 'next-minor' into next-major 2022-07-14 16:06:35 +01:00
f1a63098bd Merge branch 'stable' into next-minor 2022-07-14 16:06:15 +01:00
75d7adfb2d WitherEffect: fixed incorrect damage interval 2022-07-14 16:05:35 +01:00
7dd8876515 TNT: remove the old unreliable way of ignition on burning arrow collide 2022-07-14 00:23:12 +01:00
d0067cfac5 TNT now ignites when hit by a burning projectile 2022-07-14 00:12:02 +01:00
eafc23c756 Added candles and cakes with candles 2022-07-13 23:54:41 +01:00
20cb67461f Block: add the current class to the exception messages for block runtime data serialization 2022-07-13 19:50:35 +01:00
8b2d941502 Offset integer ranges in runtime block data serialization
this is useful for stuff like snow layers where the range doesn't start at 0.
2022-07-13 19:49:30 +01:00
dea0207e4e Merge branch 'next-minor' into next-major 2022-07-13 17:06:04 +01:00
4b1052022c Merge branch 'stable' into next-minor 2022-07-13 17:00:58 +01:00
32f9fcd4e9 Ignore coral_hang_type_bit on coral_fan_hang3
it's always written, but never used.
2022-07-13 16:38:37 +01:00
9d535e2917 4.6.1 is next 2022-07-13 01:28:42 +01:00
3ccd288afd Release 4.6.0 2022-07-13 01:28:37 +01:00
06655bee78 Updated to 1.19.10 2022-07-13 00:59:49 +01:00
2ba51567d8 RuntimeBlockMapping: avoid keeping two copies of the same blockstate data in memory 2022-07-10 17:41:01 +01:00
14933a731b Implement copper waxing, unwaxing and scraping, minus particles
there is a LevelEvent for the particles, but it's both particle and sound, which doesn't integrate well with the existing API.
2022-07-10 01:00:13 +01:00
a22276e679 there's always one ... 2022-07-10 00:19:27 +01:00
260e54e4b1 Skeleton for copper blocks, stairs and slabs 2022-07-10 00:18:35 +01:00
a44c089f98 REEEEEEEEEEEEEE 2022-07-09 20:40:18 +01:00
5e70ae2066 Added lightning rods 2022-07-09 20:18:22 +01:00
ad7528e3f3 Added warped wart blocks, gilded blackstone and crying obsidian 2022-07-09 20:00:10 +01:00
99ff78a8a5 Updated BedrockData 2022-07-09 18:57:32 +01:00
9ffee7cfc3 always the CS ... 2022-07-09 16:30:59 +01:00
ccb3c3cb05 BlockStateData: use array<Tag> instead of CompoundTag to store state properties
this reduces the footprint of RuntimeBlockMapping by a further 1 MB, as well as simplifying various parts of the code, and solidifying the immutability guarantee of BlockStateData.
2022-07-09 16:03:51 +01:00
151f2c3f3a BlockStateDictionary: reduce memory footprint by 5 MB by deduplicating blockstate NBT keys and values 2022-07-08 21:51:44 +01:00
66d655731a Don't barf on air itemstacks found on disk
closes #5143

this is caused by bugs in PM4, where it saved air itemstacks when it wasn't supposed to.

These issues are now all addressed in PM5, since ItemSerializer won't accept air itemstacks.
2022-07-08 18:19:46 +01:00
54a773be0c SubChunk::__construct(): rename blocks to blockLayers 2022-07-07 20:04:16 +01:00
d894c5e97f Drop string ID -> legacy ID conversion tables
these are not used for anything anymore
2022-07-07 20:00:25 +01:00
419b21281d Fix Copilot mixup 2022-07-07 19:54:04 +01:00
56e6a55645 LegacyBlockStateMapper: provide a way to add custom upgrade mappings
this will be needed by plugin developers to upgrade old custom blocks from PM4.
2022-07-07 19:44:16 +01:00
c67e42a723 Add a hook to enable blocks to react to projectiles colliding with them
this enables implementing blocks such as the target block.
2022-07-07 01:44:13 +01:00
3e4f01d85e VanillaBlocks: fixed case of some names 2022-07-07 01:27:30 +01:00
da9937933b Implemented honey bottle 2022-07-07 01:06:17 +01:00
2142eb3cc9 VanillaItems: sort lines alphabetically 2022-07-07 01:01:05 +01:00
690efb09e3 Fixed ItemTypeIds::FIRST_UNUSED_ITEM_ID 2022-07-07 00:55:34 +01:00
e4d24e1edd Invert dependency between VanillaBlocks and BlockFactory 2022-07-07 00:22:08 +01:00
4d6fb2b925 Removed ItemFactory 2022-07-06 23:57:29 +01:00
0ad2985247 Update documentation for Item::__construct() 2022-07-06 23:54:29 +01:00
976502e3db Move item type initialization to VanillaItems
ItemFactory no longer has an obvious purpose, thanks to this ...
2022-07-06 23:47:51 +01:00
b0c76f4db5 Fixed botched unit tests 2022-07-06 23:28:08 +01:00
8886a023f1 Reduce the size of block_factory_consistency_check.json by improving the storage format
this reduces the size by 65%, but more importantly, doesn't cause several pages of flooding in git diff.
2022-07-06 23:20:13 +01:00
ae70c63798 Added tinted glass 2022-07-06 23:01:17 +01:00
986daab511 ItemFactory: remove dead TODO comment 2022-07-06 22:25:17 +01:00
eb404bddb4 5.0.0-ALPHA2 is next 2022-07-06 21:52:37 +01:00
125 changed files with 3596 additions and 3967 deletions

View File

@ -74,7 +74,7 @@ function generateBlockPaletteReport(array $states) : BlockPaletteReport{
foreach($states as $stateData){
$name = $stateData->getName();
$result->seenTypes[$name] = $name;
foreach($stateData->getStates() as $k => $v){
foreach(Utils::stringifyKeys($stateData->getStates()) as $k => $v){
$result->seenStateValues[$k][$v->getValue()] = $v->getValue();
asort($result->seenStateValues[$k]);
}

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\build\generate_runtime_enum_serializers;
use pocketmine\block\utils\BellAttachmentType;
use pocketmine\block\utils\CopperOxidation;
use pocketmine\block\utils\CoralType;
use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\LeverFacing;
@ -154,6 +155,7 @@ function buildEnumReaderFunc(array $enumMembers, string &$functionName) : array{
$enumsUsed = [
BellAttachmentType::getAll(),
CopperOxidation::getAll(),
CoralType::getAll(),
DyeColor::getAll(),
LeverFacing::getAll(),

14
changelogs/4.6.md Normal file
View File

@ -0,0 +1,14 @@
**For Minecraft: Bedrock Edition 1.19.10**
### Note about API versions
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
Plugin developers should **only** update their required API to this version if you need the changes in this build.
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
# 4.6.0
Released 13th July 2022.
## General
- Added support for Minecraft: Bedrock Edition 1.19.10.
- Removed support for older versions.

View File

@ -305,3 +305,118 @@ Again, it's acknowledged this is rather more cumbersome than it should be, but t
- The following classes have been added:
- `pocketmine\world\format\io\GlobalBlockStateHandlers`
- `pocketmine\world\format\io\GlobalItemDataHandlers`
# 5.0.0-ALPHA2
Released 14th July 2022.
## Core
- Reduced memory usage of the server on startup.
- Fixed error spam when loading item frames without items in them.
## Gameplay
### Blocks
- Added the following new blocks:
- Cakes with Candle & Dyed Candle
- Candle & Dyed Candle
- Cartography Table (not currently usable due to maps not being implemented)
- Copper block (random oxidation not yet implemented)
- Cut Copper block, stairs and slabs (random oxidation not yet implemented)
- Crying Obsidian
- Gilded Blackstone
- Glow Item Frame
- Hanging Roots
- Lightning Rod
- Netherite Block
- Smithing Table
- Tinted Glass
- Warped Wart Block
- Wither Rose
### Items
- Added the following new items:
- Honey Bottle
- Netherite Axe
- Netherite Boots
- Netherite Chestplate
- Netherite Helmet
- Netherite Ingot
- Netherite Leggings
- Netherite Pickaxe
- Netherite Scrap
- Netherite Shovel
- Netherite Sword
## API
### `pocketmine\block`
- Dependency between `BlockFactory` and `VanillaBlocks` has been inverted.
- Now, blocks are defined in `VanillaBlocks`, and automatically registered in `BlockFactory`.
- Manual registration in `BlockFactory` is still required for custom blocks.
- `BlockFactory` now has only one purpose, which is to map internal blockstate IDs to `Block` objects when reading blocks from chunks.
- The following new API methods have been added:
- `public Block->isFireProofAsItem()`
- `public Block->onProjectileHit()`
- `public ItemFrame->isGlowing()`
- `public ItemFrame->setGlowing()`
- The following new classes have been added:
- `BaseCake`
- `CakeWithCandle`
- `CakeWithDyedCandle`
- `Candle`
- `CartographyTable`
- `CopperSlab`
- `CopperStairs`
- `Copper`
- `DyedCandle`
- `GildedBlackstone`
- `HangingRoots`
- `LightningRod`
- `SmithingTable`
- `WitherRose`
- `utils\CandleTrait`
- `utils\CopperOxidation`
- `utils\CopperTrait`
### `pocketmine\crafting`
- JSON models have been updated to reflect updated crafting data format.
- The following enum classes have new members:
- `ShapelessRecipeType` has new members `CARTOGRAPHY` and `SMITHING`
### `pocketmine\data`
- `LegacyToStringBidirectionalIdMap` has been reduced to `LegacyToStringIdMap`.
- Since we never map from string ID to legacy ID, bidirectional mapping is no longer necessary.
- This affects the following subclasses:
- `LegacyBiomeIdToStringIdMap`
- `LegacyBlockIdToStringIdMap`
- `LegacyEntityIdToStringIdMap`
- `LegacyItemIdToStringIdMap`
- The following internal API methods have been added:
- `public LegacyToStringIdMap->add(string $string, int $legacy) : void` - adds a mapping from a custom legacy ID to custom string ID, needed for upgrading old saved data
- `public LegacyBlockStateMapper->addMapping(string $stringId, int $intId, int $meta, BlockStateData $stateData) : void` - adds a mapping from legacy block data to a modern blockstate, needed for upgrading old saved data
- `public BlockStateData->getState(string $name) : ?Tag`
- The following internal API methods have signature changes:
- `BlockStateData->__construct()` now accepts `array<string, Tag`> for `$states` instead of `CompoundTag`
- `BlockStateData->getStates()` now returns `array<string, Tag>` instead of `CompoundTag` (allows reducing memory usage)
- The following classes have been added:
- `UnsupportedItemTypeException`
### `pocketmine\item`
- `ItemFactory` has been removed.
- Vanilla item registration is now done via `VanillaItems`.
- The procedure for registering a custom item is the same as in ALPHA1, minus the `ItemFactory` step.
- The following API methods have been added:
- `public ArmorTypeInfo->getToughness() : int`
- `public ArmorTypeInfo->isFireProof() : bool`
- `public Item->isFireProof() : bool`
- The following API methods have signature changes:
- `ArmorTypeInfo->__construct()` now accepts optional parameters `int $toughness` and `bool $fireProof`
- The following classes have been added:
- `HoneyBottle`
- The following enums have new members:
- `ToolTier` has new member `NETHERITE`
### `pocketmine\world`
- The following API methods have signature changes:
- `SubChunk->__construct()` parameter `$blocks` has been renamed to `$blockLayers`.
- The following classes have been added:
- `CopperWaxApplySound`
- `CopperWaxRemoveSound`

View File

@ -37,7 +37,7 @@
"pocketmine/bedrock-block-upgrade-schema": "dev-master@dev",
"pocketmine/bedrock-data": "dev-modern-world-support@dev",
"pocketmine/bedrock-item-upgrade-schema": "dev-master",
"pocketmine/bedrock-protocol": "~10.0.0+bedrock-1.19.0",
"pocketmine/bedrock-protocol": "~11.0.0+bedrock-1.19.10",
"pocketmine/binaryutils": "^0.2.1",
"pocketmine/callback-validator": "^1.0.2",
"pocketmine/classloader": "^0.2.0",

24
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "f4dff5c2abe600c5aa22b7b357874cb0",
"content-hash": "dbdbe7338c5646763ad82e6eb47d70bd",
"packages": [
{
"name": "adhocore/json-comment",
@ -280,12 +280,12 @@
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockData.git",
"reference": "01948a627448395d9946c2e6a5e8332a8456eaa0"
"reference": "5d7add6b08c7168747c0dda1f5d3599b5c4aaca9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/01948a627448395d9946c2e6a5e8332a8456eaa0",
"reference": "01948a627448395d9946c2e6a5e8332a8456eaa0",
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/5d7add6b08c7168747c0dda1f5d3599b5c4aaca9",
"reference": "5d7add6b08c7168747c0dda1f5d3599b5c4aaca9",
"shasum": ""
},
"type": "library",
@ -298,7 +298,7 @@
"issues": "https://github.com/pmmp/BedrockData/issues",
"source": "https://github.com/pmmp/BedrockData/tree/modern-world-support"
},
"time": "2022-07-04T16:59:39+00:00"
"time": "2022-07-12T19:40:28+00:00"
},
{
"name": "pocketmine/bedrock-item-upgrade-schema",
@ -329,16 +329,16 @@
},
{
"name": "pocketmine/bedrock-protocol",
"version": "10.0.1+bedrock-1.19.0",
"version": "11.0.3+bedrock-1.19.10",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockProtocol.git",
"reference": "331fb0eb45c26daadf8cf01a3b6f20e909d7684b"
"reference": "18879218f9d05685ab6f8f68df4cb9c548978657"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/331fb0eb45c26daadf8cf01a3b6f20e909d7684b",
"reference": "331fb0eb45c26daadf8cf01a3b6f20e909d7684b",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/18879218f9d05685ab6f8f68df4cb9c548978657",
"reference": "18879218f9d05685ab6f8f68df4cb9c548978657",
"shasum": ""
},
"require": {
@ -352,7 +352,7 @@
"ramsey/uuid": "^4.1"
},
"require-dev": {
"phpstan/phpstan": "1.7.11",
"phpstan/phpstan": "1.8.0",
"phpstan/phpstan-phpunit": "^1.0.0",
"phpstan/phpstan-strict-rules": "^1.0.0",
"phpunit/phpunit": "^9.5"
@ -370,9 +370,9 @@
"description": "An implementation of the Minecraft: Bedrock Edition protocol in PHP",
"support": {
"issues": "https://github.com/pmmp/BedrockProtocol/issues",
"source": "https://github.com/pmmp/BedrockProtocol/tree/10.0.1+bedrock-1.19.0"
"source": "https://github.com/pmmp/BedrockProtocol/tree/11.0.3+bedrock-1.19.10"
},
"time": "2022-06-08T01:11:15+00:00"
"time": "2022-07-14T16:54:49+00:00"
},
{
"name": "pocketmine/binaryutils",

View File

@ -31,7 +31,7 @@ use function str_repeat;
final class VersionInfo{
public const NAME = "PocketMine-MP";
public const BASE_VERSION = "5.0.0-ALPHA1";
public const BASE_VERSION = "5.0.0-ALPHA2";
public const IS_DEVELOPMENT_BUILD = false;
public const BUILD_CHANNEL = "alpha";

View File

@ -54,7 +54,7 @@ class Anvil extends Transparent implements Fallable{
}
protected function encodeType(RuntimeDataWriter $w) : void{
$w->writeInt(2, $this->getDamage());
$w->writeBoundedInt(2, self::UNDAMAGED, self::VERY_DAMAGED, $this->getDamage());
}
public function getRequiredStateDataBits() : int{ return 2; }

View File

@ -65,7 +65,7 @@ class Bamboo extends Transparent{
}
protected function encodeState(RuntimeDataWriter $w) : void{
$w->writeInt(2, $this->getLeafSize());
$w->writeBoundedInt(2, self::NO_LEAVES, self::LARGE_LEAVES, $this->getLeafSize());
$w->writeBool($this->isThick());
$w->writeBool($this->isReady());
}

89
src/block/BaseCake.php Normal file
View File

@ -0,0 +1,89 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\SupportType;
use pocketmine\entity\effect\EffectInstance;
use pocketmine\entity\FoodSource;
use pocketmine\entity\Living;
use pocketmine\item\Item;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
abstract class BaseCake extends Transparent implements FoodSource{
public function getSupportType(int $facing) : SupportType{
return SupportType::NONE();
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$down = $this->getSide(Facing::DOWN);
if($down->getTypeId() !== BlockTypeIds::AIR){
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
return false;
}
public function onNearbyBlockChange() : void{
if($this->getSide(Facing::DOWN)->getTypeId() === BlockTypeIds::AIR){ //Replace with common break method
$this->position->getWorld()->useBreakOn($this->position);
}
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){
return $player->consumeObject($this);
}
return false;
}
public function getFoodRestore() : int{
return 2;
}
public function getSaturationRestore() : float{
return 0.4;
}
public function requiresHunger() : bool{
return true;
}
/**
* @return EffectInstance[]
*/
public function getAdditionalEffects() : array{
return [];
}
abstract public function getResidue() : Block;
public function onConsume(Living $consumer) : void{
$this->position->getWorld()->setBlock($this->position, $this->getResidue());
}
}

View File

@ -32,6 +32,7 @@ use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataReader;
use pocketmine\data\runtime\RuntimeDataWriter;
use pocketmine\entity\Entity;
use pocketmine\entity\projectile\Projectile;
use pocketmine\item\enchantment\VanillaEnchantments;
use pocketmine\item\Item;
use pocketmine\item\ItemBlock;
@ -46,6 +47,7 @@ use pocketmine\world\format\Chunk;
use pocketmine\world\Position;
use pocketmine\world\World;
use function count;
use function get_class;
use const PHP_INT_MAX;
class Block{
@ -108,7 +110,7 @@ class Block{
$this->decodeType($reader);
$readBits = $reader->getOffset();
if($typeBits !== $readBits){
throw new \LogicException("Exactly $typeBits bits of type data were provided, but $readBits were read");
throw new \LogicException(get_class($this) . ": Exactly $typeBits bits of type data were provided, but $readBits were read");
}
}
@ -125,7 +127,7 @@ class Block{
$this->decodeState($reader);
$readBits = $reader->getOffset() - $typeBits;
if($stateBits !== $readBits){
throw new \LogicException("Exactly $stateBits bits of state data were provided, but $readBits were read");
throw new \LogicException(get_class($this) . ": Exactly $stateBits bits of state data were provided, but $readBits were read");
}
}
@ -148,7 +150,7 @@ class Block{
$this->encodeType($writer);
$writtenBits = $writer->getOffset();
if($typeBits !== $writtenBits){
throw new \LogicException("Exactly $typeBits bits of type data were expected, but $writtenBits were written");
throw new \LogicException(get_class($this) . ": Exactly $typeBits bits of type data were expected, but $writtenBits were written");
}
return $writer->getValue();
@ -167,7 +169,7 @@ class Block{
$this->encodeState($writer);
$writtenBits = $writer->getOffset() - $typeBits;
if($stateBits !== $writtenBits){
throw new \LogicException("Exactly $stateBits bits of state data were expected, but $writtenBits were written");
throw new \LogicException(get_class($this) . ": Exactly $stateBits bits of state data were expected, but $writtenBits were written");
}
return $writer->getValue();
@ -502,6 +504,10 @@ class Block{
return 64;
}
public function isFireProofAsItem() : bool{
return false;
}
/**
* Returns the chance that the block will catch fire from nearby fire sources. Higher values lead to faster catching
* fire.
@ -626,6 +632,13 @@ class Block{
return null;
}
/**
* Called when a projectile collides with one of this block's collision boxes.
*/
public function onProjectileHit(Projectile $projectile, RayTraceResult $hitResult) : void{
//NOOP
}
/**
* @return AxisAlignedBB[]
*/

View File

@ -25,36 +25,7 @@ namespace pocketmine\block;
use pocketmine\block\BlockBreakInfo as BreakInfo;
use pocketmine\block\BlockIdentifier as BID;
use pocketmine\block\BlockToolType as ToolType;
use pocketmine\block\BlockTypeIds as Ids;
use pocketmine\block\tile\Banner as TileBanner;
use pocketmine\block\tile\Barrel as TileBarrel;
use pocketmine\block\tile\Beacon as TileBeacon;
use pocketmine\block\tile\Bed as TileBed;
use pocketmine\block\tile\Bell as TileBell;
use pocketmine\block\tile\BlastFurnace as TileBlastFurnace;
use pocketmine\block\tile\BrewingStand as TileBrewingStand;
use pocketmine\block\tile\Chest as TileChest;
use pocketmine\block\tile\Comparator as TileComparator;
use pocketmine\block\tile\DaylightSensor as TileDaylightSensor;
use pocketmine\block\tile\EnchantTable as TileEnchantingTable;
use pocketmine\block\tile\EnderChest as TileEnderChest;
use pocketmine\block\tile\FlowerPot as TileFlowerPot;
use pocketmine\block\tile\Hopper as TileHopper;
use pocketmine\block\tile\ItemFrame as TileItemFrame;
use pocketmine\block\tile\Jukebox as TileJukebox;
use pocketmine\block\tile\Lectern as TileLectern;
use pocketmine\block\tile\MonsterSpawner as TileMonsterSpawner;
use pocketmine\block\tile\NormalFurnace as TileNormalFurnace;
use pocketmine\block\tile\Note as TileNote;
use pocketmine\block\tile\ShulkerBox as TileShulkerBox;
use pocketmine\block\tile\Skull as TileSkull;
use pocketmine\block\tile\Smoker as TileSmoker;
use pocketmine\block\utils\TreeType;
use pocketmine\block\utils\WoodType;
use pocketmine\data\runtime\InvalidSerializedRuntimeDataException;
use pocketmine\item\Item;
use pocketmine\item\ToolTier;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\SingletonTrait;
use pocketmine\world\light\LightUpdate;
@ -102,741 +73,9 @@ class BlockFactory{
public array $blastResistance = [];
public function __construct(){
$railBreakInfo = new BlockBreakInfo(0.7);
$this->register(new ActivatorRail(new BID(Ids::ACTIVATOR_RAIL), "Activator Rail", $railBreakInfo));
$this->register(new Air(new BID(Ids::AIR), "Air", BreakInfo::indestructible(-1.0)));
$this->register(new Anvil(new BID(Ids::ANVIL), "Anvil", new BreakInfo(5.0, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 6000.0)));
$this->register(new Bamboo(new BID(Ids::BAMBOO), "Bamboo", new class(2.0 /* 1.0 in PC */, ToolType::AXE) extends BreakInfo{
public function getBreakTime(Item $item) : float{
if($item->getBlockToolType() === ToolType::SWORD){
return 0.0;
}
return parent::getBreakTime($item);
}
}));
$this->register(new BambooSapling(new BID(Ids::BAMBOO_SAPLING), "Bamboo Sapling", BreakInfo::instant()));
$bannerBreakInfo = new BreakInfo(1.0, ToolType::AXE);
$this->register(new FloorBanner(new BID(Ids::BANNER, TileBanner::class), "Banner", $bannerBreakInfo));
$this->register(new WallBanner(new BID(Ids::WALL_BANNER, TileBanner::class), "Wall Banner", $bannerBreakInfo));
$this->register(new Barrel(new BID(Ids::BARREL, TileBarrel::class), "Barrel", new BreakInfo(2.5, ToolType::AXE)));
$this->register(new Transparent(new BID(Ids::BARRIER), "Barrier", BreakInfo::indestructible()));
$this->register(new Beacon(new BID(Ids::BEACON, TileBeacon::class), "Beacon", new BreakInfo(3.0)));
$this->register(new Bed(new BID(Ids::BED, TileBed::class), "Bed Block", new BreakInfo(0.2)));
$this->register(new Bedrock(new BID(Ids::BEDROCK), "Bedrock", BreakInfo::indestructible()));
$this->register(new Beetroot(new BID(Ids::BEETROOTS), "Beetroot Block", BreakInfo::instant()));
$this->register(new Bell(new BID(Ids::BELL, TileBell::class), "Bell", new BreakInfo(5.0, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel())));
$this->register(new BlueIce(new BID(Ids::BLUE_ICE), "Blue Ice", new BreakInfo(2.8, ToolType::PICKAXE)));
$this->register(new BoneBlock(new BID(Ids::BONE_BLOCK), "Bone Block", new BreakInfo(2.0, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel())));
$this->register(new Bookshelf(new BID(Ids::BOOKSHELF), "Bookshelf", new BreakInfo(1.5, ToolType::AXE)));
$this->register(new BrewingStand(new BID(Ids::BREWING_STAND, TileBrewingStand::class), "Brewing Stand", new BreakInfo(0.5, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel())));
$bricksBreakInfo = new BreakInfo(2.0, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 30.0);
$this->register(new Stair(new BID(Ids::BRICK_STAIRS), "Brick Stairs", $bricksBreakInfo));
$this->register(new Opaque(new BID(Ids::BRICKS), "Bricks", $bricksBreakInfo));
$this->register(new BrownMushroom(new BID(Ids::BROWN_MUSHROOM), "Brown Mushroom", BreakInfo::instant()));
$this->register(new Cactus(new BID(Ids::CACTUS), "Cactus", new BreakInfo(0.4)));
$this->register(new Cake(new BID(Ids::CAKE), "Cake", new BreakInfo(0.5)));
$this->register(new Carrot(new BID(Ids::CARROTS), "Carrot Block", BreakInfo::instant()));
$chestBreakInfo = new BreakInfo(2.5, ToolType::AXE);
$this->register(new Chest(new BID(Ids::CHEST, TileChest::class), "Chest", $chestBreakInfo));
$this->register(new Clay(new BID(Ids::CLAY), "Clay Block", new BreakInfo(0.6, ToolType::SHOVEL)));
$this->register(new Coal(new BID(Ids::COAL), "Coal Block", new BreakInfo(5.0, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 30.0)));
$cobblestoneBreakInfo = new BreakInfo(2.0, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 30.0);
$this->register($cobblestone = new Opaque(new BID(Ids::COBBLESTONE), "Cobblestone", $cobblestoneBreakInfo));
$this->register(new Opaque(new BID(Ids::MOSSY_COBBLESTONE), "Mossy Cobblestone", $cobblestoneBreakInfo));
$this->register(new Stair(new BID(Ids::COBBLESTONE_STAIRS), "Cobblestone Stairs", $cobblestoneBreakInfo));
$this->register(new Stair(new BID(Ids::MOSSY_COBBLESTONE_STAIRS), "Mossy Cobblestone Stairs", $cobblestoneBreakInfo));
$this->register(new Cobweb(new BID(Ids::COBWEB), "Cobweb", new BreakInfo(4.0, ToolType::SWORD | ToolType::SHEARS, 1)));
$this->register(new CocoaBlock(new BID(Ids::COCOA_POD), "Cocoa Block", new BreakInfo(0.2, ToolType::AXE, 0, 15.0)));
$this->register(new CoralBlock(new BID(Ids::CORAL_BLOCK), "Coral Block", new BreakInfo(7.0, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel())));
$this->register(new CraftingTable(new BID(Ids::CRAFTING_TABLE), "Crafting Table", new BreakInfo(2.5, ToolType::AXE)));
$this->register(new DaylightSensor(new BID(Ids::DAYLIGHT_SENSOR, TileDaylightSensor::class), "Daylight Sensor", new BreakInfo(0.2, ToolType::AXE)));
$this->register(new DeadBush(new BID(Ids::DEAD_BUSH), "Dead Bush", BreakInfo::instant(ToolType::SHEARS, 1)));
$this->register(new DetectorRail(new BID(Ids::DETECTOR_RAIL), "Detector Rail", $railBreakInfo));
$this->register(new Opaque(new BID(Ids::DIAMOND), "Diamond Block", new BreakInfo(5.0, ToolType::PICKAXE, ToolTier::IRON()->getHarvestLevel(), 30.0)));
$this->register(new Dirt(new BID(Ids::DIRT), "Dirt", new BreakInfo(0.5, ToolType::SHOVEL)));
$this->register(new DoublePlant(new BID(Ids::SUNFLOWER), "Sunflower", BreakInfo::instant()));
$this->register(new DoublePlant(new BID(Ids::LILAC), "Lilac", BreakInfo::instant()));
$this->register(new DoublePlant(new BID(Ids::ROSE_BUSH), "Rose Bush", BreakInfo::instant()));
$this->register(new DoublePlant(new BID(Ids::PEONY), "Peony", BreakInfo::instant()));
$this->register(new DoubleTallGrass(new BID(Ids::DOUBLE_TALLGRASS), "Double Tallgrass", BreakInfo::instant(ToolType::SHEARS, 1)));
$this->register(new DoubleTallGrass(new BID(Ids::LARGE_FERN), "Large Fern", BreakInfo::instant(ToolType::SHEARS, 1)));
$this->register(new DragonEgg(new BID(Ids::DRAGON_EGG), "Dragon Egg", new BreakInfo(3.0, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel())));
$this->register(new DriedKelp(new BID(Ids::DRIED_KELP), "Dried Kelp Block", new BreakInfo(0.5, ToolType::NONE, 0, 12.5)));
$this->register(new Opaque(new BID(Ids::EMERALD), "Emerald Block", new BreakInfo(5.0, ToolType::PICKAXE, ToolTier::IRON()->getHarvestLevel(), 30.0)));
$this->register(new EnchantingTable(new BID(Ids::ENCHANTING_TABLE, TileEnchantingTable::class), "Enchanting Table", new BreakInfo(5.0, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 6000.0)));
$this->register(new EndPortalFrame(new BID(Ids::END_PORTAL_FRAME), "End Portal Frame", BreakInfo::indestructible()));
$this->register(new EndRod(new BID(Ids::END_ROD), "End Rod", BreakInfo::instant()));
$this->register(new Opaque(new BID(Ids::END_STONE), "End Stone", new BreakInfo(3.0, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 45.0)));
$endBrickBreakInfo = new BreakInfo(0.8, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 4.0);
$this->register(new Opaque(new BID(Ids::END_STONE_BRICKS), "End Stone Bricks", $endBrickBreakInfo));
$this->register(new Stair(new BID(Ids::END_STONE_BRICK_STAIRS), "End Stone Brick Stairs", $endBrickBreakInfo));
$this->register(new EnderChest(new BID(Ids::ENDER_CHEST, TileEnderChest::class), "Ender Chest", new BreakInfo(22.5, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 3000.0)));
$this->register(new Farmland(new BID(Ids::FARMLAND), "Farmland", new BreakInfo(0.6, ToolType::SHOVEL)));
$this->register(new Fire(new BID(Ids::FIRE), "Fire Block", BreakInfo::instant()));
$this->register(new FletchingTable(new BID(Ids::FLETCHING_TABLE), "Fletching Table", new BreakInfo(2.5, ToolType::AXE, 0, 2.5)));
$this->register(new Flower(new BID(Ids::DANDELION), "Dandelion", BreakInfo::instant()));
$this->register(new Flower(new BID(Ids::POPPY), "Poppy", BreakInfo::instant()));
$this->register(new Flower(new BID(Ids::ALLIUM), "Allium", BreakInfo::instant()));
$this->register(new Flower(new BID(Ids::AZURE_BLUET), "Azure Bluet", BreakInfo::instant()));
$this->register(new Flower(new BID(Ids::BLUE_ORCHID), "Blue Orchid", BreakInfo::instant()));
$this->register(new Flower(new BID(Ids::CORNFLOWER), "Cornflower", BreakInfo::instant()));
$this->register(new Flower(new BID(Ids::LILY_OF_THE_VALLEY), "Lily of the Valley", BreakInfo::instant()));
$this->register(new Flower(new BID(Ids::ORANGE_TULIP), "Orange Tulip", BreakInfo::instant()));
$this->register(new Flower(new BID(Ids::OXEYE_DAISY), "Oxeye Daisy", BreakInfo::instant()));
$this->register(new Flower(new BID(Ids::PINK_TULIP), "Pink Tulip", BreakInfo::instant()));
$this->register(new Flower(new BID(Ids::RED_TULIP), "Red Tulip", BreakInfo::instant()));
$this->register(new Flower(new BID(Ids::WHITE_TULIP), "White Tulip", BreakInfo::instant()));
$this->register(new FlowerPot(new BID(Ids::FLOWER_POT, TileFlowerPot::class), "Flower Pot", BreakInfo::instant()));
$this->register(new FrostedIce(new BID(Ids::FROSTED_ICE), "Frosted Ice", new BreakInfo(2.5, ToolType::PICKAXE)));
$this->register(new Furnace(new BID(Ids::FURNACE, TileNormalFurnace::class), "Furnace", new BreakInfo(3.5, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel())));
$this->register(new Furnace(new BID(Ids::BLAST_FURNACE, TileBlastFurnace::class), "Blast Furnace", new BreakInfo(3.5, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel())));
$this->register(new Furnace(new BID(Ids::SMOKER, TileSmoker::class), "Smoker", new BreakInfo(3.5, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel())));
$glassBreakInfo = new BreakInfo(0.3);
$this->register(new Glass(new BID(Ids::GLASS), "Glass", $glassBreakInfo));
$this->register(new GlassPane(new BID(Ids::GLASS_PANE), "Glass Pane", $glassBreakInfo));
$this->register(new GlowingObsidian(new BID(Ids::GLOWING_OBSIDIAN), "Glowing Obsidian", new BreakInfo(10.0, ToolType::PICKAXE, ToolTier::DIAMOND()->getHarvestLevel(), 50.0)));
$this->register(new Glowstone(new BID(Ids::GLOWSTONE), "Glowstone", new BreakInfo(0.3, ToolType::PICKAXE)));
$this->register(new Opaque(new BID(Ids::GOLD), "Gold Block", new BreakInfo(3.0, ToolType::PICKAXE, ToolTier::IRON()->getHarvestLevel(), 30.0)));
$grassBreakInfo = new BreakInfo(0.6, ToolType::SHOVEL);
$this->register(new Grass(new BID(Ids::GRASS), "Grass", $grassBreakInfo));
$this->register(new GrassPath(new BID(Ids::GRASS_PATH), "Grass Path", $grassBreakInfo));
$this->register(new Gravel(new BID(Ids::GRAVEL), "Gravel", new BreakInfo(0.6, ToolType::SHOVEL)));
$hardenedClayBreakInfo = new BreakInfo(1.25, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 21.0);
$this->register(new HardenedClay(new BID(Ids::HARDENED_CLAY), "Hardened Clay", $hardenedClayBreakInfo));
$hardenedGlassBreakInfo = new BreakInfo(10.0);
$this->register(new HardenedGlass(new BID(Ids::HARDENED_GLASS), "Hardened Glass", $hardenedGlassBreakInfo));
$this->register(new HardenedGlassPane(new BID(Ids::HARDENED_GLASS_PANE), "Hardened Glass Pane", $hardenedGlassBreakInfo));
$this->register(new HayBale(new BID(Ids::HAY_BALE), "Hay Bale", new BreakInfo(0.5)));
$this->register(new Hopper(new BID(Ids::HOPPER, TileHopper::class), "Hopper", new BreakInfo(3.0, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 15.0)));
$this->register(new Ice(new BID(Ids::ICE), "Ice", new BreakInfo(0.5, ToolType::PICKAXE)));
$updateBlockBreakInfo = new BreakInfo(1.0);
$this->register(new Opaque(new BID(Ids::INFO_UPDATE), "update!", $updateBlockBreakInfo));
$this->register(new Opaque(new BID(Ids::INFO_UPDATE2), "ate!upd", $updateBlockBreakInfo));
$this->register(new Transparent(new BID(Ids::INVISIBLE_BEDROCK), "Invisible Bedrock", BreakInfo::indestructible()));
$ironBreakInfo = new BreakInfo(5.0, ToolType::PICKAXE, ToolTier::STONE()->getHarvestLevel(), 30.0);
$this->register(new Opaque(new BID(Ids::IRON), "Iron Block", $ironBreakInfo));
$this->register(new Thin(new BID(Ids::IRON_BARS), "Iron Bars", $ironBreakInfo));
$ironDoorBreakInfo = new BreakInfo(5.0, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 25.0);
$this->register(new Door(new BID(Ids::IRON_DOOR), "Iron Door", $ironDoorBreakInfo));
$this->register(new Trapdoor(new BID(Ids::IRON_TRAPDOOR), "Iron Trapdoor", $ironDoorBreakInfo));
$this->register(new ItemFrame(new BID(Ids::ITEM_FRAME, TileItemFrame::class), "Item Frame", new BreakInfo(0.25)));
$this->register(new Jukebox(new BID(Ids::JUKEBOX, TileJukebox::class), "Jukebox", new BreakInfo(0.8, ToolType::AXE))); //TODO: in PC the hardness is 2.0, not 0.8, unsure if this is a MCPE bug or not
$this->register(new Ladder(new BID(Ids::LADDER), "Ladder", new BreakInfo(0.4, ToolType::AXE)));
$lanternBreakInfo = new BreakInfo(5.0, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel());
$this->register(new Lantern(new BID(Ids::LANTERN), "Lantern", $lanternBreakInfo, 15));
$this->register(new Lantern(new BID(Ids::SOUL_LANTERN), "Soul Lantern", $lanternBreakInfo, 10));
$this->register(new Opaque(new BID(Ids::LAPIS_LAZULI), "Lapis Lazuli Block", new BreakInfo(3.0, ToolType::PICKAXE, ToolTier::STONE()->getHarvestLevel())));
$this->register(new Lava(new BID(Ids::LAVA), "Lava", BreakInfo::indestructible(500.0)));
$this->register(new Lectern(new BID(Ids::LECTERN, TileLectern::class), "Lectern", new BreakInfo(2.0, ToolType::AXE)));
$this->register(new Lever(new BID(Ids::LEVER), "Lever", new BreakInfo(0.5)));
$this->register(new Loom(new BID(Ids::LOOM), "Loom", new BreakInfo(2.5, ToolType::AXE)));
$this->register(new Magma(new BID(Ids::MAGMA), "Magma Block", new BreakInfo(0.5, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel())));
$this->register(new Melon(new BID(Ids::MELON), "Melon Block", new BreakInfo(1.0, ToolType::AXE)));
$this->register(new MelonStem(new BID(Ids::MELON_STEM), "Melon Stem", BreakInfo::instant()));
$this->register(new MonsterSpawner(new BID(Ids::MONSTER_SPAWNER, TileMonsterSpawner::class), "Monster Spawner", new BreakInfo(5.0, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel())));
$this->register(new Mycelium(new BID(Ids::MYCELIUM), "Mycelium", new BreakInfo(0.6, ToolType::SHOVEL)));
$netherBrickBreakInfo = new BreakInfo(2.0, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 30.0);
$this->register(new Opaque(new BID(Ids::NETHER_BRICKS), "Nether Bricks", $netherBrickBreakInfo));
$this->register(new Opaque(new BID(Ids::RED_NETHER_BRICKS), "Red Nether Bricks", $netherBrickBreakInfo));
$this->register(new Fence(new BID(Ids::NETHER_BRICK_FENCE), "Nether Brick Fence", $netherBrickBreakInfo));
$this->register(new Stair(new BID(Ids::NETHER_BRICK_STAIRS), "Nether Brick Stairs", $netherBrickBreakInfo));
$this->register(new Stair(new BID(Ids::RED_NETHER_BRICK_STAIRS), "Red Nether Brick Stairs", $netherBrickBreakInfo));
$this->register(new Opaque(new BID(Ids::CHISELED_NETHER_BRICKS), "Chiseled Nether Bricks", $netherBrickBreakInfo));
$this->register(new Opaque(new BID(Ids::CRACKED_NETHER_BRICKS), "Cracked Nether Bricks", $netherBrickBreakInfo));
$this->register(new NetherPortal(new BID(Ids::NETHER_PORTAL), "Nether Portal", BreakInfo::indestructible(0.0)));
$this->register(new NetherReactor(new BID(Ids::NETHER_REACTOR_CORE), "Nether Reactor Core", new BreakInfo(3.0, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel())));
$this->register(new Opaque(new BID(Ids::NETHER_WART_BLOCK), "Nether Wart Block", new BreakInfo(1.0, ToolType::HOE)));
$this->register(new NetherWartPlant(new BID(Ids::NETHER_WART), "Nether Wart", BreakInfo::instant()));
$this->register(new Netherrack(new BID(Ids::NETHERRACK), "Netherrack", new BreakInfo(0.4, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel())));
$this->register(new Note(new BID(Ids::NOTE_BLOCK, TileNote::class), "Note Block", new BreakInfo(0.8, ToolType::AXE)));
$this->register(new Opaque(new BID(Ids::OBSIDIAN), "Obsidian", new BreakInfo(35.0 /* 50 in PC */, ToolType::PICKAXE, ToolTier::DIAMOND()->getHarvestLevel(), 6000.0)));
$this->register(new PackedIce(new BID(Ids::PACKED_ICE), "Packed Ice", new BreakInfo(0.5, ToolType::PICKAXE)));
$this->register(new Podzol(new BID(Ids::PODZOL), "Podzol", new BreakInfo(0.5, ToolType::SHOVEL)));
$this->register(new Potato(new BID(Ids::POTATOES), "Potato Block", BreakInfo::instant()));
$this->register(new PoweredRail(new BID(Ids::POWERED_RAIL), "Powered Rail", $railBreakInfo));
$prismarineBreakInfo = new BreakInfo(1.5, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 30.0);
$this->register(new Opaque(new BID(Ids::PRISMARINE), "Prismarine", $prismarineBreakInfo));
$this->register(new Opaque(new BID(Ids::DARK_PRISMARINE), "Dark Prismarine", $prismarineBreakInfo));
$this->register(new Opaque(new BID(Ids::PRISMARINE_BRICKS), "Prismarine Bricks", $prismarineBreakInfo));
$this->register(new Stair(new BID(Ids::PRISMARINE_BRICKS_STAIRS), "Prismarine Bricks Stairs", $prismarineBreakInfo));
$this->register(new Stair(new BID(Ids::DARK_PRISMARINE_STAIRS), "Dark Prismarine Stairs", $prismarineBreakInfo));
$this->register(new Stair(new BID(Ids::PRISMARINE_STAIRS), "Prismarine Stairs", $prismarineBreakInfo));
$pumpkinBreakInfo = new BreakInfo(1.0, ToolType::AXE);
$this->register(new Pumpkin(new BID(Ids::PUMPKIN), "Pumpkin", $pumpkinBreakInfo));
$this->register(new CarvedPumpkin(new BID(Ids::CARVED_PUMPKIN), "Carved Pumpkin", $pumpkinBreakInfo));
$this->register(new LitPumpkin(new BID(Ids::LIT_PUMPKIN), "Jack o'Lantern", $pumpkinBreakInfo));
$this->register(new PumpkinStem(new BID(Ids::PUMPKIN_STEM), "Pumpkin Stem", BreakInfo::instant()));
$purpurBreakInfo = new BreakInfo(1.5, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 30.0);
$this->register(new Opaque(new BID(Ids::PURPUR), "Purpur Block", $purpurBreakInfo));
$this->register(new SimplePillar(new BID(Ids::PURPUR_PILLAR), "Purpur Pillar", $purpurBreakInfo));
$this->register(new Stair(new BID(Ids::PURPUR_STAIRS), "Purpur Stairs", $purpurBreakInfo));
$quartzBreakInfo = new BreakInfo(0.8, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel());
$this->register(new Opaque(new BID(Ids::QUARTZ), "Quartz Block", $quartzBreakInfo));
$this->register(new SimplePillar(new BID(Ids::CHISELED_QUARTZ), "Chiseled Quartz Block", $quartzBreakInfo));
$this->register(new SimplePillar(new BID(Ids::QUARTZ_PILLAR), "Quartz Pillar", $quartzBreakInfo));
$this->register(new Opaque(new BID(Ids::SMOOTH_QUARTZ), "Smooth Quartz Block", $quartzBreakInfo));
$this->register(new Opaque(new BID(Ids::QUARTZ_BRICKS), "Quartz Bricks", $quartzBreakInfo));
$this->register(new Stair(new BID(Ids::QUARTZ_STAIRS), "Quartz Stairs", $quartzBreakInfo));
$this->register(new Stair(new BID(Ids::SMOOTH_QUARTZ_STAIRS), "Smooth Quartz Stairs", $quartzBreakInfo));
$this->register(new Rail(new BID(Ids::RAIL), "Rail", $railBreakInfo));
$this->register(new RedMushroom(new BID(Ids::RED_MUSHROOM), "Red Mushroom", BreakInfo::instant()));
$this->register(new Redstone(new BID(Ids::REDSTONE), "Redstone Block", new BreakInfo(5.0, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 30.0)));
$this->register(new RedstoneComparator(new BID(Ids::REDSTONE_COMPARATOR, TileComparator::class), "Redstone Comparator", BreakInfo::instant()));
$this->register(new RedstoneLamp(new BID(Ids::REDSTONE_LAMP), "Redstone Lamp", new BreakInfo(0.3)));
$this->register(new RedstoneRepeater(new BID(Ids::REDSTONE_REPEATER), "Redstone Repeater", BreakInfo::instant()));
$this->register(new RedstoneTorch(new BID(Ids::REDSTONE_TORCH), "Redstone Torch", BreakInfo::instant()));
$this->register(new RedstoneWire(new BID(Ids::REDSTONE_WIRE), "Redstone", BreakInfo::instant()));
$this->register(new Reserved6(new BID(Ids::RESERVED6), "reserved6", BreakInfo::instant()));
$sandBreakInfo = new BreakInfo(0.5, ToolType::SHOVEL);
$this->register(new Sand(new BID(Ids::SAND), "Sand", $sandBreakInfo));
$this->register(new Sand(new BID(Ids::RED_SAND), "Red Sand", $sandBreakInfo));
$this->register(new SeaLantern(new BID(Ids::SEA_LANTERN), "Sea Lantern", new BreakInfo(0.3)));
$this->register(new SeaPickle(new BID(Ids::SEA_PICKLE), "Sea Pickle", BreakInfo::instant()));
$this->register(new Skull(new BID(Ids::MOB_HEAD, TileSkull::class), "Mob Head", new BreakInfo(1.0)));
$this->register(new Slime(new BID(Ids::SLIME), "Slime Block", BreakInfo::instant()));
$this->register(new Snow(new BID(Ids::SNOW), "Snow Block", new BreakInfo(0.2, ToolType::SHOVEL, ToolTier::WOOD()->getHarvestLevel())));
$this->register(new SnowLayer(new BID(Ids::SNOW_LAYER), "Snow Layer", new BreakInfo(0.1, ToolType::SHOVEL, ToolTier::WOOD()->getHarvestLevel())));
$this->register(new SoulSand(new BID(Ids::SOUL_SAND), "Soul Sand", new BreakInfo(0.5, ToolType::SHOVEL)));
$this->register(new Sponge(new BID(Ids::SPONGE), "Sponge", new BreakInfo(0.6, ToolType::HOE)));
$shulkerBoxBreakInfo = new BreakInfo(2, ToolType::PICKAXE);
$this->register(new ShulkerBox(new BID(Ids::SHULKER_BOX, TileShulkerBox::class), "Shulker Box", $shulkerBoxBreakInfo));
$stoneBreakInfo = new BreakInfo(1.5, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 30.0);
$this->register(
$stone = new class(new BID(Ids::STONE), "Stone", $stoneBreakInfo) extends Opaque{
public function getDropsForCompatibleTool(Item $item) : array{
return [VanillaBlocks::COBBLESTONE()->asItem()];
}
public function isAffectedBySilkTouch() : bool{
return true;
}
}
);
$this->register(new Opaque(new BID(Ids::ANDESITE), "Andesite", $stoneBreakInfo));
$this->register(new Opaque(new BID(Ids::DIORITE), "Diorite", $stoneBreakInfo));
$this->register(new Opaque(new BID(Ids::GRANITE), "Granite", $stoneBreakInfo));
$this->register(new Opaque(new BID(Ids::POLISHED_ANDESITE), "Polished Andesite", $stoneBreakInfo));
$this->register(new Opaque(new BID(Ids::POLISHED_DIORITE), "Polished Diorite", $stoneBreakInfo));
$this->register(new Opaque(new BID(Ids::POLISHED_GRANITE), "Polished Granite", $stoneBreakInfo));
$this->register($stoneBrick = new Opaque(new BID(Ids::STONE_BRICKS), "Stone Bricks", $stoneBreakInfo));
$this->register($mossyStoneBrick = new Opaque(new BID(Ids::MOSSY_STONE_BRICKS), "Mossy Stone Bricks", $stoneBreakInfo));
$this->register($crackedStoneBrick = new Opaque(new BID(Ids::CRACKED_STONE_BRICKS), "Cracked Stone Bricks", $stoneBreakInfo));
$this->register($chiseledStoneBrick = new Opaque(new BID(Ids::CHISELED_STONE_BRICKS), "Chiseled Stone Bricks", $stoneBreakInfo));
$infestedStoneBreakInfo = new BreakInfo(0.75, ToolType::PICKAXE);
$this->register(new InfestedStone(new BID(Ids::INFESTED_STONE), "Infested Stone", $infestedStoneBreakInfo, $stone));
$this->register(new InfestedStone(new BID(Ids::INFESTED_STONE_BRICK), "Infested Stone Brick", $infestedStoneBreakInfo, $stoneBrick));
$this->register(new InfestedStone(new BID(Ids::INFESTED_COBBLESTONE), "Infested Cobblestone", $infestedStoneBreakInfo, $cobblestone));
$this->register(new InfestedStone(new BID(Ids::INFESTED_MOSSY_STONE_BRICK), "Infested Mossy Stone Brick", $infestedStoneBreakInfo, $mossyStoneBrick));
$this->register(new InfestedStone(new BID(Ids::INFESTED_CRACKED_STONE_BRICK), "Infested Cracked Stone Brick", $infestedStoneBreakInfo, $crackedStoneBrick));
$this->register(new InfestedStone(new BID(Ids::INFESTED_CHISELED_STONE_BRICK), "Infested Chiseled Stone Brick", $infestedStoneBreakInfo, $chiseledStoneBrick));
$this->register(new Stair(new BID(Ids::STONE_STAIRS), "Stone Stairs", $stoneBreakInfo));
$this->register(new Opaque(new BID(Ids::SMOOTH_STONE), "Smooth Stone", $stoneBreakInfo));
$this->register(new Stair(new BID(Ids::ANDESITE_STAIRS), "Andesite Stairs", $stoneBreakInfo));
$this->register(new Stair(new BID(Ids::DIORITE_STAIRS), "Diorite Stairs", $stoneBreakInfo));
$this->register(new Stair(new BID(Ids::GRANITE_STAIRS), "Granite Stairs", $stoneBreakInfo));
$this->register(new Stair(new BID(Ids::POLISHED_ANDESITE_STAIRS), "Polished Andesite Stairs", $stoneBreakInfo));
$this->register(new Stair(new BID(Ids::POLISHED_DIORITE_STAIRS), "Polished Diorite Stairs", $stoneBreakInfo));
$this->register(new Stair(new BID(Ids::POLISHED_GRANITE_STAIRS), "Polished Granite Stairs", $stoneBreakInfo));
$this->register(new Stair(new BID(Ids::STONE_BRICK_STAIRS), "Stone Brick Stairs", $stoneBreakInfo));
$this->register(new Stair(new BID(Ids::MOSSY_STONE_BRICK_STAIRS), "Mossy Stone Brick Stairs", $stoneBreakInfo));
$this->register(new StoneButton(new BID(Ids::STONE_BUTTON), "Stone Button", new BreakInfo(0.5, ToolType::PICKAXE)));
$this->register(new Stonecutter(new BID(Ids::STONECUTTER), "Stonecutter", new BreakInfo(3.5, ToolType::PICKAXE)));
$this->register(new StonePressurePlate(new BID(Ids::STONE_PRESSURE_PLATE), "Stone Pressure Plate", new BreakInfo(0.5, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel())));
//TODO: in the future this won't be the same for all the types
$stoneSlabBreakInfo = new BreakInfo(2.0, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 30.0);
foreach([
new Slab(new BID(Ids::BRICK_SLAB), "Brick", $stoneSlabBreakInfo),
new Slab(new BID(Ids::COBBLESTONE_SLAB), "Cobblestone", $stoneSlabBreakInfo),
new Slab(new BID(Ids::FAKE_WOODEN_SLAB), "Fake Wooden", $stoneSlabBreakInfo),
new Slab(new BID(Ids::NETHER_BRICK_SLAB), "Nether Brick", $stoneSlabBreakInfo),
new Slab(new BID(Ids::QUARTZ_SLAB), "Quartz", $stoneSlabBreakInfo),
new Slab(new BID(Ids::SANDSTONE_SLAB), "Sandstone", $stoneSlabBreakInfo),
new Slab(new BID(Ids::SMOOTH_STONE_SLAB), "Smooth Stone", $stoneSlabBreakInfo),
new Slab(new BID(Ids::STONE_BRICK_SLAB), "Stone Brick", $stoneSlabBreakInfo),
new Slab(new BID(Ids::DARK_PRISMARINE_SLAB), "Dark Prismarine", $stoneSlabBreakInfo),
new Slab(new BID(Ids::MOSSY_COBBLESTONE_SLAB), "Mossy Cobblestone", $stoneSlabBreakInfo),
new Slab(new BID(Ids::PRISMARINE_SLAB), "Prismarine", $stoneSlabBreakInfo),
new Slab(new BID(Ids::PRISMARINE_BRICKS_SLAB), "Prismarine Bricks", $stoneSlabBreakInfo),
new Slab(new BID(Ids::PURPUR_SLAB), "Purpur", $stoneSlabBreakInfo),
new Slab(new BID(Ids::RED_NETHER_BRICK_SLAB), "Red Nether Brick", $stoneSlabBreakInfo),
new Slab(new BID(Ids::RED_SANDSTONE_SLAB), "Red Sandstone", $stoneSlabBreakInfo),
new Slab(new BID(Ids::SMOOTH_SANDSTONE_SLAB), "Smooth Sandstone", $stoneSlabBreakInfo),
new Slab(new BID(Ids::ANDESITE_SLAB), "Andesite", $stoneSlabBreakInfo),
new Slab(new BID(Ids::DIORITE_SLAB), "Diorite", $stoneSlabBreakInfo),
new Slab(new BID(Ids::END_STONE_BRICK_SLAB), "End Stone Brick", $stoneSlabBreakInfo),
new Slab(new BID(Ids::GRANITE_SLAB), "Granite", $stoneSlabBreakInfo),
new Slab(new BID(Ids::POLISHED_ANDESITE_SLAB), "Polished Andesite", $stoneSlabBreakInfo),
new Slab(new BID(Ids::POLISHED_DIORITE_SLAB), "Polished Diorite", $stoneSlabBreakInfo),
new Slab(new BID(Ids::POLISHED_GRANITE_SLAB), "Polished Granite", $stoneSlabBreakInfo),
new Slab(new BID(Ids::SMOOTH_RED_SANDSTONE_SLAB), "Smooth Red Sandstone", $stoneSlabBreakInfo),
new Slab(new BID(Ids::CUT_RED_SANDSTONE_SLAB), "Cut Red Sandstone", $stoneSlabBreakInfo),
new Slab(new BID(Ids::CUT_SANDSTONE_SLAB), "Cut Sandstone", $stoneSlabBreakInfo),
new Slab(new BID(Ids::MOSSY_STONE_BRICK_SLAB), "Mossy Stone Brick", $stoneSlabBreakInfo),
new Slab(new BID(Ids::SMOOTH_QUARTZ_SLAB), "Smooth Quartz", $stoneSlabBreakInfo),
new Slab(new BID(Ids::STONE_SLAB), "Stone", $stoneSlabBreakInfo),
] as $slabType){
$this->register($slabType);
foreach(VanillaBlocks::getAll() as $block){
$this->register($block);
}
$this->register(new Opaque(new BID(Ids::LEGACY_STONECUTTER), "Legacy Stonecutter", new BreakInfo(3.5, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel())));
$this->register(new Sugarcane(new BID(Ids::SUGARCANE), "Sugarcane", BreakInfo::instant()));
$this->register(new SweetBerryBush(new BID(Ids::SWEET_BERRY_BUSH), "Sweet Berry Bush", BreakInfo::instant()));
$this->register(new TNT(new BID(Ids::TNT), "TNT", BreakInfo::instant()));
$this->register(new TallGrass(new BID(Ids::FERN), "Fern", BreakInfo::instant(ToolType::SHEARS, 1)));
$this->register(new TallGrass(new BID(Ids::TALL_GRASS), "Tall Grass", BreakInfo::instant(ToolType::SHEARS, 1)));
$this->register(new Torch(new BID(Ids::BLUE_TORCH), "Blue Torch", BreakInfo::instant()));
$this->register(new Torch(new BID(Ids::PURPLE_TORCH), "Purple Torch", BreakInfo::instant()));
$this->register(new Torch(new BID(Ids::RED_TORCH), "Red Torch", BreakInfo::instant()));
$this->register(new Torch(new BID(Ids::GREEN_TORCH), "Green Torch", BreakInfo::instant()));
$this->register(new Torch(new BID(Ids::TORCH), "Torch", BreakInfo::instant()));
$this->register(new TrappedChest(new BID(Ids::TRAPPED_CHEST, TileChest::class), "Trapped Chest", $chestBreakInfo));
$this->register(new Tripwire(new BID(Ids::TRIPWIRE), "Tripwire", BreakInfo::instant()));
$this->register(new TripwireHook(new BID(Ids::TRIPWIRE_HOOK), "Tripwire Hook", BreakInfo::instant()));
$this->register(new UnderwaterTorch(new BID(Ids::UNDERWATER_TORCH), "Underwater Torch", BreakInfo::instant()));
$this->register(new Vine(new BID(Ids::VINES), "Vines", new BreakInfo(0.2, ToolType::AXE)));
$this->register(new Water(new BID(Ids::WATER), "Water", BreakInfo::indestructible(500.0)));
$this->register(new WaterLily(new BID(Ids::LILY_PAD), "Lily Pad", BreakInfo::instant()));
$weightedPressurePlateBreakInfo = new BreakInfo(0.5, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel());
$this->register(new WeightedPressurePlateHeavy(new BID(Ids::WEIGHTED_PRESSURE_PLATE_HEAVY), "Weighted Pressure Plate Heavy", $weightedPressurePlateBreakInfo));
$this->register(new WeightedPressurePlateLight(new BID(Ids::WEIGHTED_PRESSURE_PLATE_LIGHT), "Weighted Pressure Plate Light", $weightedPressurePlateBreakInfo));
$this->register(new Wheat(new BID(Ids::WHEAT), "Wheat Block", BreakInfo::instant()));
$planksBreakInfo = new BreakInfo(2.0, ToolType::AXE, 0, 15.0);
$leavesBreakInfo = new class(0.2, ToolType::HOE) extends BreakInfo{
public function getBreakTime(Item $item) : float{
if($item->getBlockToolType() === ToolType::SHEARS){
return 0.0;
}
return parent::getBreakTime($item);
}
};
$signBreakInfo = new BreakInfo(1.0, ToolType::AXE);
$logBreakInfo = new BreakInfo(2.0, ToolType::AXE);
$woodenDoorBreakInfo = new BreakInfo(3.0, ToolType::AXE, 0, 15.0);
$woodenButtonBreakInfo = new BreakInfo(0.5, ToolType::AXE);
$woodenPressurePlateBreakInfo = new BreakInfo(0.5, ToolType::AXE);
foreach(TreeType::getAll() as $treeType){
$name = $treeType->getDisplayName();
$this->register(new Sapling(BlockLegacyIdHelper::getSaplingIdentifier($treeType), $name . " Sapling", BreakInfo::instant(), $treeType));
$this->register(new Leaves(BlockLegacyIdHelper::getLeavesIdentifier($treeType), $name . " Leaves", $leavesBreakInfo, $treeType));
}
foreach(WoodType::getAll() as $woodType){
$name = $woodType->getDisplayName();
$this->register(new Wood(BlockLegacyIdHelper::getLogIdentifier($woodType), $name . " " . ($woodType->getStandardLogSuffix() ?? "Log"), $logBreakInfo, $woodType));
$this->register(new Wood(BlockLegacyIdHelper::getAllSidedLogIdentifier($woodType), $name . " " . ($woodType->getAllSidedLogSuffix() ?? "Wood"), $logBreakInfo, $woodType));
$this->register(new Planks(BlockLegacyIdHelper::getWoodenPlanksIdentifier($woodType), $name . " Planks", $planksBreakInfo, $woodType));
$this->register(new WoodenFence(BlockLegacyIdHelper::getWoodenFenceIdentifier($woodType), $name . " Fence", $planksBreakInfo, $woodType));
$this->register(new WoodenSlab(BlockLegacyIdHelper::getWoodenSlabIdentifier($woodType), $name, $planksBreakInfo, $woodType));
$this->register(new FenceGate(BlockLegacyIdHelper::getWoodenFenceGateIdentifier($woodType), $name . " Fence Gate", $planksBreakInfo, $woodType));
$this->register(new WoodenStairs(BlockLegacyIdHelper::getWoodenStairsIdentifier($woodType), $name . " Stairs", $planksBreakInfo, $woodType));
$this->register(new WoodenDoor(BlockLegacyIdHelper::getWoodenDoorIdentifier($woodType), $name . " Door", $woodenDoorBreakInfo, $woodType));
$this->register(new WoodenButton(BlockLegacyIdHelper::getWoodenButtonIdentifier($woodType), $name . " Button", $woodenButtonBreakInfo, $woodType));
$this->register(new WoodenPressurePlate(BlockLegacyIdHelper::getWoodenPressurePlateIdentifier($woodType), $name . " Pressure Plate", $woodenPressurePlateBreakInfo, $woodType));
$this->register(new WoodenTrapdoor(BlockLegacyIdHelper::getWoodenTrapdoorIdentifier($woodType), $name . " Trapdoor", $woodenDoorBreakInfo, $woodType));
[$floorSignId, $wallSignId, $signAsItem] = BlockLegacyIdHelper::getWoodenSignInfo($woodType);
$this->register(new FloorSign($floorSignId, $name . " Sign", $signBreakInfo, $woodType, $signAsItem));
$this->register(new WallSign($wallSignId, $name . " Wall Sign", $signBreakInfo, $woodType, $signAsItem));
}
$sandstoneBreakInfo = new BreakInfo(0.8, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel());
$this->register(new Stair(new BID(Ids::RED_SANDSTONE_STAIRS), "Red Sandstone Stairs", $sandstoneBreakInfo));
$this->register(new Stair(new BID(Ids::SMOOTH_RED_SANDSTONE_STAIRS), "Smooth Red Sandstone Stairs", $sandstoneBreakInfo));
$this->register(new Opaque(new BID(Ids::RED_SANDSTONE), "Red Sandstone", $sandstoneBreakInfo));
$this->register(new Opaque(new BID(Ids::CHISELED_RED_SANDSTONE), "Chiseled Red Sandstone", $sandstoneBreakInfo));
$this->register(new Opaque(new BID(Ids::CUT_RED_SANDSTONE), "Cut Red Sandstone", $sandstoneBreakInfo));
$this->register(new Opaque(new BID(Ids::SMOOTH_RED_SANDSTONE), "Smooth Red Sandstone", $sandstoneBreakInfo));
$this->register(new Stair(new BID(Ids::SANDSTONE_STAIRS), "Sandstone Stairs", $sandstoneBreakInfo));
$this->register(new Stair(new BID(Ids::SMOOTH_SANDSTONE_STAIRS), "Smooth Sandstone Stairs", $sandstoneBreakInfo));
$this->register(new Opaque(new BID(Ids::SANDSTONE), "Sandstone", $sandstoneBreakInfo));
$this->register(new Opaque(new BID(Ids::CHISELED_SANDSTONE), "Chiseled Sandstone", $sandstoneBreakInfo));
$this->register(new Opaque(new BID(Ids::CUT_SANDSTONE), "Cut Sandstone", $sandstoneBreakInfo));
$this->register(new Opaque(new BID(Ids::SMOOTH_SANDSTONE), "Smooth Sandstone", $sandstoneBreakInfo));
$this->register(new GlazedTerracotta(new BID(Ids::GLAZED_TERRACOTTA), "Glazed Terracotta", new BreakInfo(1.4, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel())));
$this->register(new DyedShulkerBox(new BID(Ids::DYED_SHULKER_BOX, TileShulkerBox::class), "Dyed Shulker Box", $shulkerBoxBreakInfo));
$this->register(new StainedGlass(new BID(Ids::STAINED_GLASS), "Stained Glass", $glassBreakInfo));
$this->register(new StainedGlassPane(new BID(Ids::STAINED_GLASS_PANE), "Stained Glass Pane", $glassBreakInfo));
$this->register(new StainedHardenedClay(new BID(Ids::STAINED_CLAY), "Stained Clay", $hardenedClayBreakInfo));
$this->register(new StainedHardenedGlass(new BID(Ids::STAINED_HARDENED_GLASS), "Stained Hardened Glass", $hardenedGlassBreakInfo));
$this->register(new StainedHardenedGlassPane(new BID(Ids::STAINED_HARDENED_GLASS_PANE), "Stained Hardened Glass Pane", $hardenedGlassBreakInfo));
$this->register(new Carpet(new BID(Ids::CARPET), "Carpet", new BreakInfo(0.1)));
$this->register(new Concrete(new BID(Ids::CONCRETE), "Concrete", new BreakInfo(1.8, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel())));
$this->register(new ConcretePowder(new BID(Ids::CONCRETE_POWDER), "Concrete Powder", new BreakInfo(0.5, ToolType::SHOVEL)));
$this->register(new Wool(new BID(Ids::WOOL), "Wool", new class(0.8, ToolType::SHEARS) extends BreakInfo{
public function getBreakTime(Item $item) : float{
$time = parent::getBreakTime($item);
if($item->getBlockToolType() === ToolType::SHEARS){
$time *= 3; //shears break compatible blocks 15x faster, but wool 5x
}
return $time;
}
}));
//TODO: in the future these won't all have the same hardness; they only do now because of the old metadata crap
$wallBreakInfo = new BreakInfo(2.0, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 30.0);
$this->register(new Wall(new BID(Ids::COBBLESTONE_WALL), "Cobblestone Wall", $wallBreakInfo));
$this->register(new Wall(new BID(Ids::ANDESITE_WALL), "Andesite Wall", $wallBreakInfo));
$this->register(new Wall(new BID(Ids::BRICK_WALL), "Brick Wall", $wallBreakInfo));
$this->register(new Wall(new BID(Ids::DIORITE_WALL), "Diorite Wall", $wallBreakInfo));
$this->register(new Wall(new BID(Ids::END_STONE_BRICK_WALL), "End Stone Brick Wall", $wallBreakInfo));
$this->register(new Wall(new BID(Ids::GRANITE_WALL), "Granite Wall", $wallBreakInfo));
$this->register(new Wall(new BID(Ids::MOSSY_STONE_BRICK_WALL), "Mossy Stone Brick Wall", $wallBreakInfo));
$this->register(new Wall(new BID(Ids::MOSSY_COBBLESTONE_WALL), "Mossy Cobblestone Wall", $wallBreakInfo));
$this->register(new Wall(new BID(Ids::NETHER_BRICK_WALL), "Nether Brick Wall", $wallBreakInfo));
$this->register(new Wall(new BID(Ids::PRISMARINE_WALL), "Prismarine Wall", $wallBreakInfo));
$this->register(new Wall(new BID(Ids::RED_NETHER_BRICK_WALL), "Red Nether Brick Wall", $wallBreakInfo));
$this->register(new Wall(new BID(Ids::RED_SANDSTONE_WALL), "Red Sandstone Wall", $wallBreakInfo));
$this->register(new Wall(new BID(Ids::SANDSTONE_WALL), "Sandstone Wall", $wallBreakInfo));
$this->register(new Wall(new BID(Ids::STONE_BRICK_WALL), "Stone Brick Wall", $wallBreakInfo));
$this->registerElements();
$chemistryTableBreakInfo = new BreakInfo(2.5, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel());
$this->register(new ChemistryTable(new BID(Ids::COMPOUND_CREATOR), "Compound Creator", $chemistryTableBreakInfo));
$this->register(new ChemistryTable(new BID(Ids::ELEMENT_CONSTRUCTOR), "Element Constructor", $chemistryTableBreakInfo));
$this->register(new ChemistryTable(new BID(Ids::LAB_TABLE), "Lab Table", $chemistryTableBreakInfo));
$this->register(new ChemistryTable(new BID(Ids::MATERIAL_REDUCER), "Material Reducer", $chemistryTableBreakInfo));
$this->register(new ChemicalHeat(new BID(Ids::CHEMICAL_HEAT), "Heat Block", $chemistryTableBreakInfo));
$this->registerMushroomBlocks();
$this->register(new Coral(
new BID(Ids::CORAL),
"Coral",
BreakInfo::instant(),
));
$this->register(new FloorCoralFan(
new BID(Ids::CORAL_FAN),
"Coral Fan",
BreakInfo::instant(),
));
$this->register(new WallCoralFan(
new BID(Ids::WALL_CORAL_FAN),
"Wall Coral Fan",
BreakInfo::instant(),
));
$this->registerBlocksR13();
$this->registerBlocksR14();
$this->registerBlocksR16();
$this->registerBlocksR17();
$this->registerMudBlocks();
$this->registerOres();
}
private function registerMushroomBlocks() : void{
$mushroomBlockBreakInfo = new BreakInfo(0.2, ToolType::AXE);
$this->register(new BrownMushroomBlock(new BID(Ids::BROWN_MUSHROOM_BLOCK), "Brown Mushroom Block", $mushroomBlockBreakInfo));
$this->register(new RedMushroomBlock(new BID(Ids::RED_MUSHROOM_BLOCK), "Red Mushroom Block", $mushroomBlockBreakInfo));
//finally, the stems
$this->register(new MushroomStem(new BID(Ids::MUSHROOM_STEM), "Mushroom Stem", $mushroomBlockBreakInfo));
$this->register(new MushroomStem(new BID(Ids::ALL_SIDED_MUSHROOM_STEM), "All Sided Mushroom Stem", $mushroomBlockBreakInfo));
}
private function registerElements() : void{
$instaBreak = BreakInfo::instant();
$this->register(new Opaque(new BID(Ids::ELEMENT_ZERO), "???", $instaBreak));
$this->register(new Element(new BID(Ids::ELEMENT_HYDROGEN), "Hydrogen", $instaBreak, "h", 1, 5));
$this->register(new Element(new BID(Ids::ELEMENT_HELIUM), "Helium", $instaBreak, "he", 2, 7));
$this->register(new Element(new BID(Ids::ELEMENT_LITHIUM), "Lithium", $instaBreak, "li", 3, 0));
$this->register(new Element(new BID(Ids::ELEMENT_BERYLLIUM), "Beryllium", $instaBreak, "be", 4, 1));
$this->register(new Element(new BID(Ids::ELEMENT_BORON), "Boron", $instaBreak, "b", 5, 4));
$this->register(new Element(new BID(Ids::ELEMENT_CARBON), "Carbon", $instaBreak, "c", 6, 5));
$this->register(new Element(new BID(Ids::ELEMENT_NITROGEN), "Nitrogen", $instaBreak, "n", 7, 5));
$this->register(new Element(new BID(Ids::ELEMENT_OXYGEN), "Oxygen", $instaBreak, "o", 8, 5));
$this->register(new Element(new BID(Ids::ELEMENT_FLUORINE), "Fluorine", $instaBreak, "f", 9, 6));
$this->register(new Element(new BID(Ids::ELEMENT_NEON), "Neon", $instaBreak, "ne", 10, 7));
$this->register(new Element(new BID(Ids::ELEMENT_SODIUM), "Sodium", $instaBreak, "na", 11, 0));
$this->register(new Element(new BID(Ids::ELEMENT_MAGNESIUM), "Magnesium", $instaBreak, "mg", 12, 1));
$this->register(new Element(new BID(Ids::ELEMENT_ALUMINUM), "Aluminum", $instaBreak, "al", 13, 3));
$this->register(new Element(new BID(Ids::ELEMENT_SILICON), "Silicon", $instaBreak, "si", 14, 4));
$this->register(new Element(new BID(Ids::ELEMENT_PHOSPHORUS), "Phosphorus", $instaBreak, "p", 15, 5));
$this->register(new Element(new BID(Ids::ELEMENT_SULFUR), "Sulfur", $instaBreak, "s", 16, 5));
$this->register(new Element(new BID(Ids::ELEMENT_CHLORINE), "Chlorine", $instaBreak, "cl", 17, 6));
$this->register(new Element(new BID(Ids::ELEMENT_ARGON), "Argon", $instaBreak, "ar", 18, 7));
$this->register(new Element(new BID(Ids::ELEMENT_POTASSIUM), "Potassium", $instaBreak, "k", 19, 0));
$this->register(new Element(new BID(Ids::ELEMENT_CALCIUM), "Calcium", $instaBreak, "ca", 20, 1));
$this->register(new Element(new BID(Ids::ELEMENT_SCANDIUM), "Scandium", $instaBreak, "sc", 21, 2));
$this->register(new Element(new BID(Ids::ELEMENT_TITANIUM), "Titanium", $instaBreak, "ti", 22, 2));
$this->register(new Element(new BID(Ids::ELEMENT_VANADIUM), "Vanadium", $instaBreak, "v", 23, 2));
$this->register(new Element(new BID(Ids::ELEMENT_CHROMIUM), "Chromium", $instaBreak, "cr", 24, 2));
$this->register(new Element(new BID(Ids::ELEMENT_MANGANESE), "Manganese", $instaBreak, "mn", 25, 2));
$this->register(new Element(new BID(Ids::ELEMENT_IRON), "Iron", $instaBreak, "fe", 26, 2));
$this->register(new Element(new BID(Ids::ELEMENT_COBALT), "Cobalt", $instaBreak, "co", 27, 2));
$this->register(new Element(new BID(Ids::ELEMENT_NICKEL), "Nickel", $instaBreak, "ni", 28, 2));
$this->register(new Element(new BID(Ids::ELEMENT_COPPER), "Copper", $instaBreak, "cu", 29, 2));
$this->register(new Element(new BID(Ids::ELEMENT_ZINC), "Zinc", $instaBreak, "zn", 30, 2));
$this->register(new Element(new BID(Ids::ELEMENT_GALLIUM), "Gallium", $instaBreak, "ga", 31, 3));
$this->register(new Element(new BID(Ids::ELEMENT_GERMANIUM), "Germanium", $instaBreak, "ge", 32, 4));
$this->register(new Element(new BID(Ids::ELEMENT_ARSENIC), "Arsenic", $instaBreak, "as", 33, 4));
$this->register(new Element(new BID(Ids::ELEMENT_SELENIUM), "Selenium", $instaBreak, "se", 34, 5));
$this->register(new Element(new BID(Ids::ELEMENT_BROMINE), "Bromine", $instaBreak, "br", 35, 6));
$this->register(new Element(new BID(Ids::ELEMENT_KRYPTON), "Krypton", $instaBreak, "kr", 36, 7));
$this->register(new Element(new BID(Ids::ELEMENT_RUBIDIUM), "Rubidium", $instaBreak, "rb", 37, 0));
$this->register(new Element(new BID(Ids::ELEMENT_STRONTIUM), "Strontium", $instaBreak, "sr", 38, 1));
$this->register(new Element(new BID(Ids::ELEMENT_YTTRIUM), "Yttrium", $instaBreak, "y", 39, 2));
$this->register(new Element(new BID(Ids::ELEMENT_ZIRCONIUM), "Zirconium", $instaBreak, "zr", 40, 2));
$this->register(new Element(new BID(Ids::ELEMENT_NIOBIUM), "Niobium", $instaBreak, "nb", 41, 2));
$this->register(new Element(new BID(Ids::ELEMENT_MOLYBDENUM), "Molybdenum", $instaBreak, "mo", 42, 2));
$this->register(new Element(new BID(Ids::ELEMENT_TECHNETIUM), "Technetium", $instaBreak, "tc", 43, 2));
$this->register(new Element(new BID(Ids::ELEMENT_RUTHENIUM), "Ruthenium", $instaBreak, "ru", 44, 2));
$this->register(new Element(new BID(Ids::ELEMENT_RHODIUM), "Rhodium", $instaBreak, "rh", 45, 2));
$this->register(new Element(new BID(Ids::ELEMENT_PALLADIUM), "Palladium", $instaBreak, "pd", 46, 2));
$this->register(new Element(new BID(Ids::ELEMENT_SILVER), "Silver", $instaBreak, "ag", 47, 2));
$this->register(new Element(new BID(Ids::ELEMENT_CADMIUM), "Cadmium", $instaBreak, "cd", 48, 2));
$this->register(new Element(new BID(Ids::ELEMENT_INDIUM), "Indium", $instaBreak, "in", 49, 3));
$this->register(new Element(new BID(Ids::ELEMENT_TIN), "Tin", $instaBreak, "sn", 50, 3));
$this->register(new Element(new BID(Ids::ELEMENT_ANTIMONY), "Antimony", $instaBreak, "sb", 51, 4));
$this->register(new Element(new BID(Ids::ELEMENT_TELLURIUM), "Tellurium", $instaBreak, "te", 52, 4));
$this->register(new Element(new BID(Ids::ELEMENT_IODINE), "Iodine", $instaBreak, "i", 53, 6));
$this->register(new Element(new BID(Ids::ELEMENT_XENON), "Xenon", $instaBreak, "xe", 54, 7));
$this->register(new Element(new BID(Ids::ELEMENT_CESIUM), "Cesium", $instaBreak, "cs", 55, 0));
$this->register(new Element(new BID(Ids::ELEMENT_BARIUM), "Barium", $instaBreak, "ba", 56, 1));
$this->register(new Element(new BID(Ids::ELEMENT_LANTHANUM), "Lanthanum", $instaBreak, "la", 57, 8));
$this->register(new Element(new BID(Ids::ELEMENT_CERIUM), "Cerium", $instaBreak, "ce", 58, 8));
$this->register(new Element(new BID(Ids::ELEMENT_PRASEODYMIUM), "Praseodymium", $instaBreak, "pr", 59, 8));
$this->register(new Element(new BID(Ids::ELEMENT_NEODYMIUM), "Neodymium", $instaBreak, "nd", 60, 8));
$this->register(new Element(new BID(Ids::ELEMENT_PROMETHIUM), "Promethium", $instaBreak, "pm", 61, 8));
$this->register(new Element(new BID(Ids::ELEMENT_SAMARIUM), "Samarium", $instaBreak, "sm", 62, 8));
$this->register(new Element(new BID(Ids::ELEMENT_EUROPIUM), "Europium", $instaBreak, "eu", 63, 8));
$this->register(new Element(new BID(Ids::ELEMENT_GADOLINIUM), "Gadolinium", $instaBreak, "gd", 64, 8));
$this->register(new Element(new BID(Ids::ELEMENT_TERBIUM), "Terbium", $instaBreak, "tb", 65, 8));
$this->register(new Element(new BID(Ids::ELEMENT_DYSPROSIUM), "Dysprosium", $instaBreak, "dy", 66, 8));
$this->register(new Element(new BID(Ids::ELEMENT_HOLMIUM), "Holmium", $instaBreak, "ho", 67, 8));
$this->register(new Element(new BID(Ids::ELEMENT_ERBIUM), "Erbium", $instaBreak, "er", 68, 8));
$this->register(new Element(new BID(Ids::ELEMENT_THULIUM), "Thulium", $instaBreak, "tm", 69, 8));
$this->register(new Element(new BID(Ids::ELEMENT_YTTERBIUM), "Ytterbium", $instaBreak, "yb", 70, 8));
$this->register(new Element(new BID(Ids::ELEMENT_LUTETIUM), "Lutetium", $instaBreak, "lu", 71, 8));
$this->register(new Element(new BID(Ids::ELEMENT_HAFNIUM), "Hafnium", $instaBreak, "hf", 72, 2));
$this->register(new Element(new BID(Ids::ELEMENT_TANTALUM), "Tantalum", $instaBreak, "ta", 73, 2));
$this->register(new Element(new BID(Ids::ELEMENT_TUNGSTEN), "Tungsten", $instaBreak, "w", 74, 2));
$this->register(new Element(new BID(Ids::ELEMENT_RHENIUM), "Rhenium", $instaBreak, "re", 75, 2));
$this->register(new Element(new BID(Ids::ELEMENT_OSMIUM), "Osmium", $instaBreak, "os", 76, 2));
$this->register(new Element(new BID(Ids::ELEMENT_IRIDIUM), "Iridium", $instaBreak, "ir", 77, 2));
$this->register(new Element(new BID(Ids::ELEMENT_PLATINUM), "Platinum", $instaBreak, "pt", 78, 2));
$this->register(new Element(new BID(Ids::ELEMENT_GOLD), "Gold", $instaBreak, "au", 79, 2));
$this->register(new Element(new BID(Ids::ELEMENT_MERCURY), "Mercury", $instaBreak, "hg", 80, 2));
$this->register(new Element(new BID(Ids::ELEMENT_THALLIUM), "Thallium", $instaBreak, "tl", 81, 3));
$this->register(new Element(new BID(Ids::ELEMENT_LEAD), "Lead", $instaBreak, "pb", 82, 3));
$this->register(new Element(new BID(Ids::ELEMENT_BISMUTH), "Bismuth", $instaBreak, "bi", 83, 3));
$this->register(new Element(new BID(Ids::ELEMENT_POLONIUM), "Polonium", $instaBreak, "po", 84, 4));
$this->register(new Element(new BID(Ids::ELEMENT_ASTATINE), "Astatine", $instaBreak, "at", 85, 6));
$this->register(new Element(new BID(Ids::ELEMENT_RADON), "Radon", $instaBreak, "rn", 86, 7));
$this->register(new Element(new BID(Ids::ELEMENT_FRANCIUM), "Francium", $instaBreak, "fr", 87, 0));
$this->register(new Element(new BID(Ids::ELEMENT_RADIUM), "Radium", $instaBreak, "ra", 88, 1));
$this->register(new Element(new BID(Ids::ELEMENT_ACTINIUM), "Actinium", $instaBreak, "ac", 89, 9));
$this->register(new Element(new BID(Ids::ELEMENT_THORIUM), "Thorium", $instaBreak, "th", 90, 9));
$this->register(new Element(new BID(Ids::ELEMENT_PROTACTINIUM), "Protactinium", $instaBreak, "pa", 91, 9));
$this->register(new Element(new BID(Ids::ELEMENT_URANIUM), "Uranium", $instaBreak, "u", 92, 9));
$this->register(new Element(new BID(Ids::ELEMENT_NEPTUNIUM), "Neptunium", $instaBreak, "np", 93, 9));
$this->register(new Element(new BID(Ids::ELEMENT_PLUTONIUM), "Plutonium", $instaBreak, "pu", 94, 9));
$this->register(new Element(new BID(Ids::ELEMENT_AMERICIUM), "Americium", $instaBreak, "am", 95, 9));
$this->register(new Element(new BID(Ids::ELEMENT_CURIUM), "Curium", $instaBreak, "cm", 96, 9));
$this->register(new Element(new BID(Ids::ELEMENT_BERKELIUM), "Berkelium", $instaBreak, "bk", 97, 9));
$this->register(new Element(new BID(Ids::ELEMENT_CALIFORNIUM), "Californium", $instaBreak, "cf", 98, 9));
$this->register(new Element(new BID(Ids::ELEMENT_EINSTEINIUM), "Einsteinium", $instaBreak, "es", 99, 9));
$this->register(new Element(new BID(Ids::ELEMENT_FERMIUM), "Fermium", $instaBreak, "fm", 100, 9));
$this->register(new Element(new BID(Ids::ELEMENT_MENDELEVIUM), "Mendelevium", $instaBreak, "md", 101, 9));
$this->register(new Element(new BID(Ids::ELEMENT_NOBELIUM), "Nobelium", $instaBreak, "no", 102, 9));
$this->register(new Element(new BID(Ids::ELEMENT_LAWRENCIUM), "Lawrencium", $instaBreak, "lr", 103, 9));
$this->register(new Element(new BID(Ids::ELEMENT_RUTHERFORDIUM), "Rutherfordium", $instaBreak, "rf", 104, 2));
$this->register(new Element(new BID(Ids::ELEMENT_DUBNIUM), "Dubnium", $instaBreak, "db", 105, 2));
$this->register(new Element(new BID(Ids::ELEMENT_SEABORGIUM), "Seaborgium", $instaBreak, "sg", 106, 2));
$this->register(new Element(new BID(Ids::ELEMENT_BOHRIUM), "Bohrium", $instaBreak, "bh", 107, 2));
$this->register(new Element(new BID(Ids::ELEMENT_HASSIUM), "Hassium", $instaBreak, "hs", 108, 2));
$this->register(new Element(new BID(Ids::ELEMENT_MEITNERIUM), "Meitnerium", $instaBreak, "mt", 109, 2));
$this->register(new Element(new BID(Ids::ELEMENT_DARMSTADTIUM), "Darmstadtium", $instaBreak, "ds", 110, 2));
$this->register(new Element(new BID(Ids::ELEMENT_ROENTGENIUM), "Roentgenium", $instaBreak, "rg", 111, 2));
$this->register(new Element(new BID(Ids::ELEMENT_COPERNICIUM), "Copernicium", $instaBreak, "cn", 112, 2));
$this->register(new Element(new BID(Ids::ELEMENT_NIHONIUM), "Nihonium", $instaBreak, "nh", 113, 3));
$this->register(new Element(new BID(Ids::ELEMENT_FLEROVIUM), "Flerovium", $instaBreak, "fl", 114, 3));
$this->register(new Element(new BID(Ids::ELEMENT_MOSCOVIUM), "Moscovium", $instaBreak, "mc", 115, 3));
$this->register(new Element(new BID(Ids::ELEMENT_LIVERMORIUM), "Livermorium", $instaBreak, "lv", 116, 3));
$this->register(new Element(new BID(Ids::ELEMENT_TENNESSINE), "Tennessine", $instaBreak, "ts", 117, 6));
$this->register(new Element(new BID(Ids::ELEMENT_OGANESSON), "Oganesson", $instaBreak, "og", 118, 7));
}
private function registerOres() : void{
$stoneOreBreakInfo = fn(ToolTier $toolTier) => new BreakInfo(3.0, ToolType::PICKAXE, $toolTier->getHarvestLevel());
$this->register(new CoalOre(new BID(Ids::COAL_ORE), "Coal Ore", $stoneOreBreakInfo(ToolTier::WOOD())));
$this->register(new CopperOre(new BID(Ids::COPPER_ORE), "Copper Ore", $stoneOreBreakInfo(ToolTier::STONE())));
$this->register(new DiamondOre(new BID(Ids::DIAMOND_ORE), "Diamond Ore", $stoneOreBreakInfo(ToolTier::IRON())));
$this->register(new EmeraldOre(new BID(Ids::EMERALD_ORE), "Emerald Ore", $stoneOreBreakInfo(ToolTier::IRON())));
$this->register(new GoldOre(new BID(Ids::GOLD_ORE), "Gold Ore", $stoneOreBreakInfo(ToolTier::IRON())));
$this->register(new IronOre(new BID(Ids::IRON_ORE), "Iron Ore", $stoneOreBreakInfo(ToolTier::STONE())));
$this->register(new LapisOre(new BID(Ids::LAPIS_LAZULI_ORE), "Lapis Lazuli Ore", $stoneOreBreakInfo(ToolTier::STONE())));
$this->register(new RedstoneOre(new BID(Ids::REDSTONE_ORE), "Redstone Ore", $stoneOreBreakInfo(ToolTier::IRON())));
$deepslateOreBreakInfo = fn(ToolTier $toolTier) => new BreakInfo(4.5, ToolType::PICKAXE, $toolTier->getHarvestLevel());
$this->register(new CoalOre(new BID(Ids::DEEPSLATE_COAL_ORE), "Deepslate Coal Ore", $deepslateOreBreakInfo(ToolTier::WOOD())));
$this->register(new CopperOre(new BID(Ids::DEEPSLATE_COPPER_ORE), "Deepslate Copper Ore", $deepslateOreBreakInfo(ToolTier::STONE())));
$this->register(new DiamondOre(new BID(Ids::DEEPSLATE_DIAMOND_ORE), "Deepslate Diamond Ore", $deepslateOreBreakInfo(ToolTier::IRON())));
$this->register(new EmeraldOre(new BID(Ids::DEEPSLATE_EMERALD_ORE), "Deepslate Emerald Ore", $deepslateOreBreakInfo(ToolTier::IRON())));
$this->register(new GoldOre(new BID(Ids::DEEPSLATE_GOLD_ORE), "Deepslate Gold Ore", $deepslateOreBreakInfo(ToolTier::IRON())));
$this->register(new IronOre(new BID(Ids::DEEPSLATE_IRON_ORE), "Deepslate Iron Ore", $deepslateOreBreakInfo(ToolTier::STONE())));
$this->register(new LapisOre(new BID(Ids::DEEPSLATE_LAPIS_LAZULI_ORE), "Deepslate Lapis Lazuli Ore", $deepslateOreBreakInfo(ToolTier::STONE())));
$this->register(new RedstoneOre(new BID(Ids::DEEPSLATE_REDSTONE_ORE), "Deepslate Redstone Ore", $deepslateOreBreakInfo(ToolTier::IRON())));
$netherrackOreBreakInfo = new BreakInfo(3.0, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel());
$this->register(new NetherQuartzOre(new BID(Ids::NETHER_QUARTZ_ORE), "Nether Quartz Ore", $netherrackOreBreakInfo));
$this->register(new NetherGoldOre(new BID(Ids::NETHER_GOLD_ORE), "Nether Gold Ore", $netherrackOreBreakInfo));
}
private function registerBlocksR13() : void{
$this->register(new Light(new BID(Ids::LIGHT), "Light Block", BreakInfo::indestructible()));
}
private function registerBlocksR14() : void{
$this->register(new Opaque(new BID(Ids::HONEYCOMB), "Honeycomb Block", new BreakInfo(0.6)));
}
private function registerBlocksR16() : void{
//for some reason, slabs have weird hardness like the legacy ones
$slabBreakInfo = new BreakInfo(2.0, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 30.0);
$this->register(new Opaque(new BID(Ids::ANCIENT_DEBRIS), "Ancient Debris", new BreakInfo(30, ToolType::PICKAXE, ToolTier::DIAMOND()->getHarvestLevel(), 3600.0)));
$basaltBreakInfo = new BreakInfo(1.25, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 21.0);
$this->register(new SimplePillar(new BID(Ids::BASALT), "Basalt", $basaltBreakInfo));
$this->register(new SimplePillar(new BID(Ids::POLISHED_BASALT), "Polished Basalt", $basaltBreakInfo));
$this->register(new Opaque(new BID(Ids::SMOOTH_BASALT), "Smooth Basalt", $basaltBreakInfo));
$blackstoneBreakInfo = new BreakInfo(1.5, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 30.0);
$this->register(new Opaque(new BID(Ids::BLACKSTONE), "Blackstone", $blackstoneBreakInfo));
$this->register(new Slab(new BID(Ids::BLACKSTONE_SLAB), "Blackstone", $slabBreakInfo));
$this->register(new Stair(new BID(Ids::BLACKSTONE_STAIRS), "Blackstone Stairs", $blackstoneBreakInfo));
$this->register(new Wall(new BID(Ids::BLACKSTONE_WALL), "Blackstone Wall", $blackstoneBreakInfo));
//TODO: polished blackstone ought to have 2.0 hardness (as per java) but it's 1.5 in Bedrock (probably parity bug)
$prefix = fn(string $thing) => "Polished Blackstone" . ($thing !== "" ? " $thing" : "");
$this->register(new Opaque(new BID(Ids::POLISHED_BLACKSTONE), $prefix(""), $blackstoneBreakInfo));
$this->register(new StoneButton(new BID(Ids::POLISHED_BLACKSTONE_BUTTON), $prefix("Button"), new BreakInfo(0.5, ToolType::PICKAXE))); //same as regular stone button
$this->register(new StonePressurePlate(new BID(Ids::POLISHED_BLACKSTONE_PRESSURE_PLATE), $prefix("Pressure Plate"), new BreakInfo(0.5, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel()))); //same as regular stone pressure plate
$this->register(new Slab(new BID(Ids::POLISHED_BLACKSTONE_SLAB), $prefix(""), $slabBreakInfo));
$this->register(new Stair(new BID(Ids::POLISHED_BLACKSTONE_STAIRS), $prefix("Stairs"), $blackstoneBreakInfo));
$this->register(new Wall(new BID(Ids::POLISHED_BLACKSTONE_WALL), $prefix("Wall"), $blackstoneBreakInfo));
$this->register(new Opaque(new BID(Ids::CHISELED_POLISHED_BLACKSTONE), "Chiseled Polished Blackstone", $blackstoneBreakInfo));
$prefix = fn(string $thing) => "Polished Blackstone Brick" . ($thing !== "" ? " $thing" : "");
$this->register(new Opaque(new BID(Ids::POLISHED_BLACKSTONE_BRICKS), "Polished Blackstone Bricks", $blackstoneBreakInfo));
$this->register(new Slab(new BID(Ids::POLISHED_BLACKSTONE_BRICK_SLAB), "Polished Blackstone Brick", $slabBreakInfo));
$this->register(new Stair(new BID(Ids::POLISHED_BLACKSTONE_BRICK_STAIRS), $prefix("Stairs"), $blackstoneBreakInfo));
$this->register(new Wall(new BID(Ids::POLISHED_BLACKSTONE_BRICK_WALL), $prefix("Wall"), $blackstoneBreakInfo));
$this->register(new Opaque(new BID(Ids::CRACKED_POLISHED_BLACKSTONE_BRICKS), "Cracked Polished Blackstone Bricks", $blackstoneBreakInfo));
$this->register(new Torch(new BID(Ids::SOUL_TORCH), "Soul Torch", BreakInfo::instant()));
$this->register(new SoulFire(new BID(Ids::SOUL_FIRE), "Soul Fire", BreakInfo::instant()));
//TODO: soul soul ought to have 0.5 hardness (as per java) but it's 1.0 in Bedrock (probably parity bug)
$this->register(new Opaque(new BID(Ids::SOUL_SOIL), "Soul Soil", new BreakInfo(1.0, ToolType::SHOVEL)));
$this->register(new class(new BID(Ids::SHROOMLIGHT), "Shroomlight", new BreakInfo(1.0, ToolType::HOE)) extends Opaque{
public function getLightLevel() : int{ return 15; }
});
}
private function registerBlocksR17() : void{
//in java this can be acquired using any tool - seems to be a parity issue in bedrock
$this->register(new Opaque(new BID(Ids::AMETHYST), "Amethyst", new BreakInfo(1.5, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel())));
$this->register(new Opaque(new BID(Ids::CALCITE), "Calcite", new BreakInfo(0.75, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel())));
$this->register(new Opaque(new BID(Ids::TUFF), "Tuff", new BreakInfo(1.5, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 30.0)));
$this->register(new Opaque(new BID(Ids::RAW_COPPER), "Raw Copper Block", new BreakInfo(5, ToolType::PICKAXE, ToolTier::STONE()->getHarvestLevel(), 30.0)));
$this->register(new Opaque(new BID(Ids::RAW_GOLD), "Raw Gold Block", new BreakInfo(5, ToolType::PICKAXE, ToolTier::IRON()->getHarvestLevel(), 30.0)));
$this->register(new Opaque(new BID(Ids::RAW_IRON), "Raw Iron Block", new BreakInfo(5, ToolType::PICKAXE, ToolTier::STONE()->getHarvestLevel(), 30.0)));
$deepslateBreakInfo = new BreakInfo(3, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 18.0);
$this->register(new SimplePillar(new BID(Ids::DEEPSLATE), "Deepslate", $deepslateBreakInfo));
//TODO: parity issue here - in Java this has a hardness of 3.0, but in bedrock it's 3.5
$this->register(new Opaque(new BID(Ids::CHISELED_DEEPSLATE), "Chiseled Deepslate", new BreakInfo(3.5, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 18.0)));
$deepslateBrickBreakInfo = new BreakInfo(3.5, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 18.0);
$this->register(new Opaque(new BID(Ids::DEEPSLATE_BRICKS), "Deepslate Bricks", $deepslateBrickBreakInfo));
$this->register(new Slab(new BID(Ids::DEEPSLATE_BRICK_SLAB), "Deepslate Brick", $deepslateBrickBreakInfo));
$this->register(new Stair(new BID(Ids::DEEPSLATE_BRICK_STAIRS), "Deepslate Brick Stairs", $deepslateBrickBreakInfo));
$this->register(new Wall(new BID(Ids::DEEPSLATE_BRICK_WALL), "Deepslate Brick Wall", $deepslateBrickBreakInfo));
$this->register(new Opaque(new BID(Ids::CRACKED_DEEPSLATE_BRICKS), "Cracked Deepslate Bricks", $deepslateBrickBreakInfo));
$deepslateTilesBreakInfo = new BreakInfo(3.5, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 18.0);
$this->register(new Opaque(new BID(Ids::DEEPSLATE_TILES), "Deepslate Tiles", $deepslateTilesBreakInfo));
$this->register(new Slab(new BID(Ids::DEEPSLATE_TILE_SLAB), "Deepslate Tile", $deepslateTilesBreakInfo));
$this->register(new Stair(new BID(Ids::DEEPSLATE_TILE_STAIRS), "Deepslate Tile Stairs", $deepslateTilesBreakInfo));
$this->register(new Wall(new BID(Ids::DEEPSLATE_TILE_WALL), "Deepslate Tile Wall", $deepslateTilesBreakInfo));
$this->register(new Opaque(new BID(Ids::CRACKED_DEEPSLATE_TILES), "Cracked Deepslate Tiles", $deepslateTilesBreakInfo));
$cobbledDeepslateBreakInfo = new BreakInfo(3.5, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 18.0);
$this->register(new Opaque(new BID(Ids::COBBLED_DEEPSLATE), "Cobbled Deepslate", $cobbledDeepslateBreakInfo));
$this->register(new Slab(new BID(Ids::COBBLED_DEEPSLATE_SLAB), "Cobbled Deepslate", $cobbledDeepslateBreakInfo));
$this->register(new Stair(new BID(Ids::COBBLED_DEEPSLATE_STAIRS), "Cobbled Deepslate Stairs", $cobbledDeepslateBreakInfo));
$this->register(new Wall(new BID(Ids::COBBLED_DEEPSLATE_WALL), "Cobbled Deepslate Wall", $cobbledDeepslateBreakInfo));
$polishedDeepslateBreakInfo = new BreakInfo(3.5, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 18.0);
$this->register(new Opaque(new BID(Ids::POLISHED_DEEPSLATE), "Polished Deepslate", $polishedDeepslateBreakInfo));
$this->register(new Slab(new BID(Ids::POLISHED_DEEPSLATE_SLAB), "Polished Deepslate", $polishedDeepslateBreakInfo));
$this->register(new Stair(new BID(Ids::POLISHED_DEEPSLATE_STAIRS), "Polished Deepslate Stairs", $polishedDeepslateBreakInfo));
$this->register(new Wall(new BID(Ids::POLISHED_DEEPSLATE_WALL), "Polished Deepslate Wall", $polishedDeepslateBreakInfo));
}
private function registerMudBlocks() : void{
$mudBricksBreakInfo = new BreakInfo(2.0, ToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 30.0);
$this->register(new Opaque(new BID(Ids::MUD_BRICKS), "Mud Bricks", $mudBricksBreakInfo));
$this->register(new Slab(new BID(Ids::MUD_BRICK_SLAB), "Mud Brick", $mudBricksBreakInfo));
$this->register(new Stair(new BID(Ids::MUD_BRICK_STAIRS), "Mud Brick Stairs", $mudBricksBreakInfo));
$this->register(new Wall(new BID(Ids::MUD_BRICK_WALL), "Mud Brick Wall", $mudBricksBreakInfo));
}
/**

View File

@ -658,7 +658,7 @@ final class BlockTypeIds{
public const MANGROVE_WALL_SIGN = 10631;
public const CRIMSON_WALL_SIGN = 10632;
public const WARPED_WALL_SIGN = 10633;
public const TINTED_GLASS = 10634;
public const HONEYCOMB = 10635;
public const DEEPSLATE_COAL_ORE = 10636;
public const DEEPSLATE_DIAMOND_ORE = 10637;
@ -676,6 +676,23 @@ final class BlockTypeIds{
public const MUD_BRICK_STAIRS = 10649;
public const MUD_BRICK_WALL = 10650;
public const PACKED_MUD = 10651;
public const WARPED_WART_BLOCK = 10652;
public const CRYING_OBSIDIAN = 10653;
public const GILDED_BLACKSTONE = 10654;
public const LIGHTNING_ROD = 10655;
public const COPPER = 10656;
public const CUT_COPPER = 10657;
public const CUT_COPPER_SLAB = 10658;
public const CUT_COPPER_STAIRS = 10659;
public const CANDLE = 10660;
public const DYED_CANDLE = 10661;
public const CAKE_WITH_CANDLE = 10662;
public const CAKE_WITH_DYED_CANDLE = 10663;
public const WITHER_ROSE = 10664;
public const HANGING_ROOTS = 10665;
public const CARTOGRAPHY_TABLE = 10666;
public const SMITHING_TABLE = 10667;
public const NETHERITE = 10668;
public const FIRST_UNUSED_BLOCK_ID = 10652;
public const FIRST_UNUSED_BLOCK_ID = 10669;
}

View File

@ -49,7 +49,7 @@ class Cactus extends Transparent{
}
protected function encodeState(RuntimeDataWriter $w) : void{
$w->writeInt(4, $this->age);
$w->writeBoundedInt(4, 0, self::MAX_AGE, $this->age);
}
public function getAge() : int{ return $this->age; }

View File

@ -23,20 +23,16 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataReader;
use pocketmine\data\runtime\RuntimeDataWriter;
use pocketmine\entity\effect\EffectInstance;
use pocketmine\entity\FoodSource;
use pocketmine\entity\Living;
use pocketmine\item\Item;
use pocketmine\item\ItemBlock;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
class Cake extends Transparent implements FoodSource{
class Cake extends BaseCake{
public const MAX_BITES = 6;
protected int $bites = 0;
@ -48,7 +44,7 @@ class Cake extends Transparent implements FoodSource{
}
protected function encodeState(RuntimeDataWriter $w) : void{
$w->writeInt(3, $this->bites);
$w->writeBoundedInt(3, 0, self::MAX_BITES, $this->bites);
}
/**
@ -63,10 +59,6 @@ class Cake extends Transparent implements FoodSource{
];
}
public function getSupportType(int $facing) : SupportType{
return SupportType::NONE();
}
public function getBites() : int{ return $this->bites; }
/** @return $this */
@ -78,49 +70,27 @@ class Cake extends Transparent implements FoodSource{
return $this;
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$down = $this->getSide(Facing::DOWN);
if($down->getTypeId() !== BlockTypeIds::AIR){
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
return false;
}
public function onNearbyBlockChange() : void{
if($this->getSide(Facing::DOWN)->getTypeId() === BlockTypeIds::AIR){ //Replace with common break method
$this->position->getWorld()->setBlock($this->position, VanillaBlocks::AIR());
}
}
public function getDropsForCompatibleTool(Item $item) : array{
return [];
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){
return $player->consumeObject($this);
if($item instanceof ItemBlock){
$block = $item->getBlock();
$resultBlock = null;
if($block->getTypeId() === BlockTypeIds::CANDLE){
$resultBlock = VanillaBlocks::CAKE_WITH_CANDLE();
}elseif($block instanceof DyedCandle){
$resultBlock = VanillaBlocks::CAKE_WITH_DYED_CANDLE()->setColor($block->getColor());
}
if($resultBlock !== null){
$this->position->getWorld()->setBlock($this->position, $resultBlock);
$item->pop();
return true;
}
}
return false;
return parent::onInteract($item, $face, $clickVector, $player);
}
public function getFoodRestore() : int{
return 2;
}
public function getSaturationRestore() : float{
return 0.4;
}
public function requiresHunger() : bool{
return true;
}
/**
* @return Block
*/
public function getResidue(){
public function getResidue() : Block{
$clone = clone $this;
$clone->bites++;
if($clone->bites > self::MAX_BITES){
@ -128,15 +98,4 @@ class Cake extends Transparent implements FoodSource{
}
return $clone;
}
/**
* @return EffectInstance[]
*/
public function getAdditionalEffects() : array{
return [];
}
public function onConsume(Living $consumer) : void{
$this->position->getWorld()->setBlock($this->position, $this->getResidue());
}
}

View File

@ -0,0 +1,78 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\CandleTrait;
use pocketmine\entity\Living;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
class CakeWithCandle extends BaseCake{
use CandleTrait {
onInteract as onInteractCandle;
}
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{
return [
AxisAlignedBB::one()
->contract(1 / 16, 0, 1 / 16)
->trim(Facing::UP, 0.5) //TODO: not sure if the candle affects height
];
}
public function getCandle() : Candle{
return VanillaBlocks::CANDLE();
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->onInteractCandle($item, $face, $clickVector, $player)){
return true;
}
return parent::onInteract($item, $face, $clickVector, $player);
}
public function getDropsForCompatibleTool(Item $item) : array{
return [$this->getCandle()->asItem()];
}
public function getPickedItem(bool $addUserData = false) : Item{
return VanillaBlocks::CAKE()->getPickedItem($addUserData);
}
public function getResidue() : Block{
return VanillaBlocks::CAKE()->setBites(1);
}
public function onConsume(Living $consumer) : void{
parent::onConsume($consumer);
$this->position->getWorld()->dropItem($this->position->add(0.5, 0.5, 0.5), $this->getCandle()->asItem());
}
}

View File

@ -0,0 +1,34 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\ColoredTrait;
class CakeWithDyedCandle extends CakeWithCandle{
use ColoredTrait;
public function getCandle() : Candle{
return VanillaBlocks::DYED_CANDLE()->setColor($this->color);
}
}

132
src/block/Candle.php Normal file
View File

@ -0,0 +1,132 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\CandleTrait;
use pocketmine\data\runtime\RuntimeDataReader;
use pocketmine\data\runtime\RuntimeDataWriter;
use pocketmine\item\Item;
use pocketmine\math\Axis;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\world\BlockTransaction;
class Candle extends Transparent{
use CandleTrait {
decodeState as decodeLitState;
encodeState as encodeLitState;
getLightLevel as getBaseLightLevel;
}
public const MIN_COUNT = 1;
public const MAX_COUNT = 4;
private int $count = self::MIN_COUNT;
public function getRequiredStateDataBits() : int{
return 3;
}
protected function decodeState(RuntimeDataReader $r) : void{
$this->decodeLitState($r);
$this->count = $r->readBoundedInt(2, self::MIN_COUNT, self::MAX_COUNT);
}
protected function encodeState(RuntimeDataWriter $w) : void{
$this->encodeLitState($w);
$w->writeBoundedInt(2, self::MIN_COUNT, self::MAX_COUNT, $this->count);
}
public function getCount() : int{ return $this->count; }
/** @return $this */
public function setCount(int $count) : self{
if($count < self::MIN_COUNT || $count > self::MAX_COUNT){
throw new \InvalidArgumentException("Count must be in range " . self::MIN_COUNT . " ... " . self::MAX_COUNT);
}
$this->count = $count;
return $this;
}
public function getLightLevel() : int{
return $this->getBaseLightLevel() * $this->count;
}
protected function recalculateCollisionBoxes() : array{
return [
(match($this->count){
1 => AxisAlignedBB::one()
->squash(Axis::X, 7 / 16)
->squash(Axis::Z, 7 / 16),
2 => AxisAlignedBB::one()
->squash(Axis::X, 5 / 16)
->trim(Facing::NORTH, 7 / 16) //0.3 thick on the Z axis
->trim(Facing::SOUTH, 6 / 16),
3 => AxisAlignedBB::one()
->trim(Facing::WEST, 5 / 16)
->trim(Facing::EAST, 6 / 16)
->trim(Facing::NORTH, 6 / 16)
->trim(Facing::SOUTH, 5 / 16),
4 => AxisAlignedBB::one()
->squash(Axis::X, 5 / 16)
->trim(Facing::NORTH, 5 / 16)
->trim(Facing::SOUTH, 6 / 16),
default => throw new AssumptionFailedError("Unreachable")
})->trim(Facing::UP, 10 / 16)
];
}
protected function getCandleIfCompatibleType(Block $block) : ?Candle{
return $block instanceof Candle && $block->isSameType($this) ? $block : null;
}
public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, int $face, bool $isClickedBlock) : bool{
$candle = $this->getCandleIfCompatibleType($blockReplace);
return $candle !== null ? $candle->count < self::MAX_COUNT : parent::canBePlacedAt($blockReplace, $clickVector, $face, $isClickedBlock);
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$down = $blockReplace->getSide(Facing::DOWN);
if(!$down->getSupportType(Facing::UP)->hasCenterSupport()){
return false;
}
$existing = $this->getCandleIfCompatibleType($blockReplace);
if($existing !== null){
if($existing->count >= self::MAX_COUNT){
return false;
}
$this->count = $existing->count + 1;
$this->lit = $existing->lit;
}
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function getDropsForCompatibleTool(Item $item) : array{
return [$this->asItem()->setCount($this->count)];
}
}

View File

@ -0,0 +1,44 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\inventory\CartographyTableInventory;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
final class CartographyTable extends Opaque{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){
$player->setCurrentWindow(new CartographyTableInventory($this->position));
}
return true;
}
public function getFuelTime() : int{
return 300;
}
}

View File

@ -56,7 +56,7 @@ class CocoaBlock extends Transparent{
protected function encodeState(RuntimeDataWriter $w) : void{
$w->writeHorizontalFacing($this->facing);
$w->writeInt(2, $this->age);
$w->writeBoundedInt(2, 0, self::MAX_AGE, $this->age);
}
public function getAge() : int{ return $this->age; }

30
src/block/Copper.php Normal file
View File

@ -0,0 +1,30 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\CopperTrait;
class Copper extends Opaque{
use CopperTrait;
}

30
src/block/CopperSlab.php Normal file
View File

@ -0,0 +1,30 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\CopperTrait;
class CopperSlab extends Slab{
use CopperTrait;
}

View File

@ -0,0 +1,30 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\CopperTrait;
class CopperStairs extends Stair{
use CopperTrait;
}

View File

@ -46,7 +46,7 @@ abstract class Crops extends Flowable{
}
protected function encodeState(RuntimeDataWriter $w) : void{
$w->writeInt(3, $this->age);
$w->writeBoundedInt(3, 0, self::MAX_AGE, $this->age);
}
public function getAge() : int{ return $this->age; }

View File

@ -50,7 +50,7 @@ class DaylightSensor extends Transparent{
}
protected function encodeState(RuntimeDataWriter $w) : void{
$w->writeInt(4, $this->signalStrength);
$w->writeBoundedInt(4, 0, 15, $this->signalStrength);
$w->writeBool($this->inverted);
}

36
src/block/DyedCandle.php Normal file
View File

@ -0,0 +1,36 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\ColoredTrait;
class DyedCandle extends Candle{
use ColoredTrait;
protected function getCandleIfCompatibleType(Block $block) : ?Candle{
$result = parent::getCandleIfCompatibleType($block);
//different coloured candles can't be combined in the same block
return $result instanceof DyedCandle && $result->color->equals($this->color) ? $result : null;
}
}

View File

@ -45,7 +45,7 @@ class Farmland extends Transparent{
}
protected function encodeState(RuntimeDataWriter $w) : void{
$w->writeInt(3, $this->wetness);
$w->writeBoundedInt(3, 0, self::MAX_WETNESS, $this->wetness);
}
public function getWetness() : int{ return $this->wetness; }

View File

@ -47,7 +47,7 @@ class Fire extends BaseFire{
}
protected function encodeState(RuntimeDataWriter $w) : void{
$w->writeInt(4, $this->age);
$w->writeBoundedInt(4, 0, self::MAX_AGE, $this->age);
}
public function getAge() : int{ return $this->age; }

View File

@ -40,7 +40,7 @@ class FrostedIce extends Ice{
}
protected function encodeState(RuntimeDataWriter $w) : void{
$w->writeInt(2, $this->age);
$w->writeBoundedInt(2, 0, self::MAX_AGE, $this->age);
}
public function getAge() : int{ return $this->age; }

View File

@ -0,0 +1,41 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use function mt_rand;
final class GildedBlackstone extends Opaque{
public function getDropsForCompatibleTool(Item $item) : array{
if(mt_rand(1, 10) === 1){
return [VanillaItems::GOLD_NUGGET()->setCount(mt_rand(2, 5))];
}
return parent::getDropsForCompatibleTool($item);
}
public function isAffectedBySilkTouch() : bool{ return true; }
}

View File

@ -0,0 +1,58 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\enchantment\VanillaEnchantments;
use pocketmine\item\Item;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
final class HangingRoots extends Flowable{
private function canBeSupportedBy(Block $block) : bool{
return $block->isSolid(); //TODO: not sure if this is the correct logic
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$blockReplace->getSide(Facing::UP)->isSolid()){
return false;
}
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::UP))){
$this->position->getWorld()->useBreakOn($this->position);
}
}
public function getDropsForIncompatibleTool(Item $item) : array{
if($item->hasEnchantment(VanillaEnchantments::SILK_TOUCH())){
return $this->getDropsForCompatibleTool($item);
}
return [];
}
}

View File

@ -41,12 +41,24 @@ class ItemFrame extends Flowable{
public const ROTATIONS = 8;
protected bool $glowing = false;
protected bool $hasMap = false; //makes frame appear large if set
protected ?Item $framedItem = null;
protected int $itemRotation = 0;
protected float $itemDropChance = 1.0;
public function getRequiredTypeDataBits() : int{ return 1; }
protected function decodeType(RuntimeDataReader $r) : void{
$this->glowing = $r->readBool();
}
protected function encodeType(RuntimeDataWriter $w) : void{
$w->writeBool($this->glowing);
}
public function getRequiredStateDataBits() : int{ return 4; }
protected function decodeState(RuntimeDataReader $r) : void{
@ -133,6 +145,14 @@ class ItemFrame extends Flowable{
return $this;
}
public function isGlowing() : bool{ return $this->glowing; }
/** @return $this */
public function setGlowing(bool $glowing) : self{
$this->glowing = $glowing;
return $this;
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->framedItem !== null){
$this->itemRotation = ($this->itemRotation + 1) % self::ROTATIONS;

View File

@ -42,7 +42,7 @@ final class Light extends Flowable{
}
protected function encodeType(RuntimeDataWriter $w) : void{
$w->writeInt(4, $this->level);
$w->writeBoundedInt(4, self::MIN_LIGHT_LEVEL, self::MAX_LIGHT_LEVEL, $this->level);
}
public function getLightLevel() : int{ return $this->level; }

View File

@ -0,0 +1,55 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\AnyFacingTrait;
use pocketmine\item\Item;
use pocketmine\math\Axis;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
final class LightningRod extends Transparent{
use AnyFacingTrait;
protected function recalculateCollisionBoxes() : array{
$myAxis = Facing::axis($this->facing);
$result = AxisAlignedBB::one();
foreach([Axis::X, Axis::Y, Axis::Z] as $axis){
if($axis !== $myAxis){
$result->squash($axis, 6 / 16);
}
}
return [$result];
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->facing = $face;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
}

View File

@ -58,7 +58,7 @@ abstract class Liquid extends Transparent{
}
protected function encodeState(RuntimeDataWriter $w) : void{
$w->writeInt(3, $this->decay);
$w->writeBoundedInt(3, 0, self::MAX_DECAY, $this->decay);
$w->writeBool($this->falling);
$w->writeBool($this->still);
}

View File

@ -45,7 +45,7 @@ class NetherWartPlant extends Flowable{
}
protected function encodeState(RuntimeDataWriter $w) : void{
$w->writeInt(2, $this->age);
$w->writeBoundedInt(2, 0, self::MAX_AGE, $this->age);
}
public function getAge() : int{ return $this->age; }

View File

@ -48,13 +48,13 @@ class RedstoneRepeater extends Flowable{
protected function decodeState(RuntimeDataReader $r) : void{
$this->facing = $r->readHorizontalFacing();
$this->delay = $r->readBoundedInt(2, self::MIN_DELAY - 1, self::MAX_DELAY - 1) + 1;
$this->delay = $r->readBoundedInt(2, self::MIN_DELAY, self::MAX_DELAY);
$this->powered = $r->readBool();
}
protected function encodeState(RuntimeDataWriter $w) : void{
$w->writeHorizontalFacing($this->facing);
$w->writeInt(2, $this->delay - 1);
$w->writeBoundedInt(2, self::MIN_DELAY, self::MAX_DELAY, $this->delay);
$w->writeBool($this->powered);
}

View File

@ -42,12 +42,12 @@ class SeaPickle extends Transparent{
public function getRequiredStateDataBits() : int{ return 3; }
protected function decodeState(RuntimeDataReader $r) : void{
$this->count = $r->readBoundedInt(2, self::MIN_COUNT - 1, self::MAX_COUNT - 1) + 1;
$this->count = $r->readBoundedInt(2, self::MIN_COUNT, self::MAX_COUNT);
$this->underwater = $r->readBool();
}
protected function encodeState(RuntimeDataWriter $w) : void{
$w->writeInt(2, $this->count - 1);
$w->writeBoundedInt(2, self::MIN_COUNT, self::MAX_COUNT, $this->count);
$w->writeBool($this->underwater);
}

View File

@ -0,0 +1,44 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\inventory\SmithingTableInventory;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
final class SmithingTable extends Opaque{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){
$player->setCurrentWindow(new SmithingTableInventory($this->position));
}
return true;
}
public function getFuelTime() : int{
return 300;
}
}

View File

@ -50,11 +50,11 @@ class SnowLayer extends Flowable implements Fallable{
public function getRequiredStateDataBits() : int{ return 3; }
protected function decodeState(RuntimeDataReader $r) : void{
$this->layers = $r->readBoundedInt(3, self::MIN_LAYERS - 1, self::MAX_LAYERS - 1) + 1;
$this->layers = $r->readBoundedInt(3, self::MIN_LAYERS, self::MAX_LAYERS);
}
protected function encodeState(RuntimeDataWriter $w) : void{
$w->writeInt(3, $this->layers - 1);
$w->writeBoundedInt(3, self::MIN_LAYERS, self::MAX_LAYERS, $this->layers);
}
public function getLayers() : int{ return $this->layers; }

View File

@ -45,7 +45,7 @@ class Sugarcane extends Flowable{
}
protected function encodeState(RuntimeDataWriter $w) : void{
$w->writeInt(4, $this->age);
$w->writeBoundedInt(4, 0, self::MAX_AGE, $this->age);
}
private function grow() : bool{

View File

@ -53,7 +53,7 @@ class SweetBerryBush extends Flowable{
}
protected function encodeState(RuntimeDataWriter $w) : void{
$w->writeInt(3, $this->age);
$w->writeBoundedInt(3, self::STAGE_SAPLING, self::STAGE_MATURE, $this->age);
}
public function getAge() : int{ return $this->age; }

View File

@ -25,14 +25,14 @@ namespace pocketmine\block;
use pocketmine\data\runtime\RuntimeDataReader;
use pocketmine\data\runtime\RuntimeDataWriter;
use pocketmine\entity\Entity;
use pocketmine\entity\Location;
use pocketmine\entity\object\PrimedTNT;
use pocketmine\entity\projectile\Arrow;
use pocketmine\entity\projectile\Projectile;
use pocketmine\item\Durable;
use pocketmine\item\enchantment\VanillaEnchantments;
use pocketmine\item\FlintSteel;
use pocketmine\item\Item;
use pocketmine\math\RayTraceResult;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\utils\Random;
@ -101,18 +101,6 @@ class TNT extends Opaque{
return false;
}
public function hasEntityCollision() : bool{
return true;
}
public function onEntityInside(Entity $entity) : bool{
if($entity instanceof Arrow && $entity->isOnFire()){
$this->ignite();
return false;
}
return true;
}
public function ignite(int $fuse = 80) : void{
$this->position->getWorld()->setBlock($this->position, VanillaBlocks::AIR());
@ -138,4 +126,10 @@ class TNT extends Opaque{
public function onIncinerate() : void{
$this->ignite();
}
public function onProjectileHit(Projectile $projectile, RayTraceResult $hitResult) : void{
if($projectile->isOnFire()){
$this->ignite();
}
}
}

31
src/block/TintedGlass.php Normal file
View File

@ -0,0 +1,31 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
final class TintedGlass extends Transparent{
public function getLightFilter() : int{
return 15;
}
}

File diff suppressed because it is too large Load Diff

78
src/block/WitherRose.php Normal file
View File

@ -0,0 +1,78 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\entity\effect\EffectInstance;
use pocketmine\entity\effect\VanillaEffects;
use pocketmine\entity\Entity;
use pocketmine\entity\Living;
use pocketmine\item\Item;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
class WitherRose extends Flowable{
private function canBeSupportedBy(Block $block) : bool{
return match($block->getTypeId()){
BlockTypeIds::GRASS,
BlockTypeIds::DIRT,
BlockTypeIds::FARMLAND,
BlockTypeIds::MYCELIUM,
BlockTypeIds::PODZOL,
BlockTypeIds::NETHERRACK,
BlockTypeIds::SOUL_SAND,
BlockTypeIds::SOUL_SOIL => true,
//TODO: moss, mud, rooted dirt
default => false
};
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::DOWN))){
$this->position->getWorld()->useBreakOn($this->position);
}
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedBy($blockReplace->getSide(Facing::DOWN))){
return false;
}
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function hasEntityCollision() : bool{ return true; }
public function onEntityInside(Entity $entity) : bool{
if($entity instanceof Living && !$entity->getEffects()->has(VanillaEffects::WITHER())){
$entity->getEffects()->add(new EffectInstance(VanillaEffects::WITHER(), 40));
}
return true;
}
public function getFlameEncouragement() : int{ return 60; }
public function getFlammability() : int{ return 100; }
}

View File

@ -0,0 +1,37 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block\inventory;
use pocketmine\inventory\SimpleInventory;
use pocketmine\inventory\TemporaryInventory;
use pocketmine\world\Position;
final class CartographyTableInventory extends SimpleInventory implements BlockInventory, TemporaryInventory{
use BlockInventoryTrait;
public function __construct(Position $holder){
$this->holder = $holder;
parent::__construct(2);
}
}

View File

@ -0,0 +1,37 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block\inventory;
use pocketmine\inventory\SimpleInventory;
use pocketmine\inventory\TemporaryInventory;
use pocketmine\world\Position;
final class SmithingTableInventory extends SimpleInventory implements BlockInventory, TemporaryInventory{
use BlockInventoryTrait;
public function __construct(Position $holder){
$this->holder = $holder;
parent::__construct(2);
}
}

View File

@ -36,7 +36,7 @@ trait AnalogRedstoneSignalEmitterTrait{
}
protected function encodeState(RuntimeDataWriter $w) : void{
$w->writeInt(4, $this->signalStrength);
$w->writeBoundedInt(4, 0, 15, $this->signalStrength);
}
public function getOutputSignalStrength() : int{ return $this->signalStrength; }

View File

@ -0,0 +1,99 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block\utils;
use pocketmine\block\Block;
use pocketmine\data\runtime\RuntimeDataReader;
use pocketmine\data\runtime\RuntimeDataWriter;
use pocketmine\entity\projectile\Projectile;
use pocketmine\item\Durable;
use pocketmine\item\enchantment\VanillaEnchantments;
use pocketmine\item\Item;
use pocketmine\item\ItemTypeIds;
use pocketmine\math\RayTraceResult;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\sound\FireExtinguishSound;
use pocketmine\world\sound\FlintSteelSound;
trait CandleTrait{
private bool $lit = false;
public function getRequiredStateDataBits() : int{ return 1; }
protected function decodeState(RuntimeDataReader $r) : void{
$this->lit = $r->readBool();
}
protected function encodeState(RuntimeDataWriter $w) : void{
$w->writeBool($this->lit);
}
public function getLightLevel() : int{
return $this->lit ? 3 : 0;
}
public function isLit() : bool{ return $this->lit; }
/** @return $this */
public function setLit(bool $lit) : self{
$this->lit = $lit;
return $this;
}
/** @see Block::onInteract() */
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($item->getTypeId() === ItemTypeIds::FLINT_AND_STEEL || $item->hasEnchantment(VanillaEnchantments::FIRE_ASPECT())){
if($this->lit){
return true;
}
if($item instanceof Durable){
$item->applyDamage(1);
}
$this->position->getWorld()->addSound($this->position, new FlintSteelSound());
$this->position->getWorld()->setBlock($this->position, $this->setLit(true));
return true;
}
if($item->isNull()){ //candle can only be extinguished with an empty hand
if(!$this->lit){
return true;
}
$this->position->getWorld()->addSound($this->position, new FireExtinguishSound());
$this->position->getWorld()->setBlock($this->position, $this->setLit(false));
return true;
}
//yes, this is intentional! in vanilla, if the candle is not interacted with, a block is placed.
return false;
}
/** @see Block::onProjectileHit() */
public function onProjectileHit(Projectile $projectile, RayTraceResult $hitResult) : void{
if(!$this->lit && $projectile->isOnFire()){
$this->position->getWorld()->setBlock($this->position, $this->setLit(true));
}
}
}

View File

@ -0,0 +1,79 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block\utils;
use pocketmine\utils\EnumTrait;
/**
* This doc-block is generated automatically, do not modify it manually.
* This must be regenerated whenever registry members are added, removed or changed.
* @see build/generate-registry-annotations.php
* @generate-registry-docblock
*
* @method static CopperOxidation EXPOSED()
* @method static CopperOxidation NONE()
* @method static CopperOxidation OXIDIZED()
* @method static CopperOxidation WEATHERED()
*/
final class CopperOxidation{
use EnumTrait {
__construct as Enum___construct;
register as Enum_register;
}
protected static function setup() : void{
self::registerAll(
new self("none", 0),
new self("exposed", 1),
new self("weathered", 2),
new self("oxidized", 3)
);
}
protected static function register(self $member) : void{
self::Enum_register($member);
self::$levelMap[$member->value] = $member;
}
/**
* @var self[]
* @phpstan-var array<int, self>
*/
private static array $levelMap = [];
private function __construct(
string $name,
private int $value
){
$this->Enum___construct($name);
}
public function getPrevious() : ?self{
return self::$levelMap[$this->value - 1] ?? null;
}
public function getNext() : ?self{
return self::$levelMap[$this->value + 1] ?? null;
}
}

View File

@ -0,0 +1,104 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block\utils;
use pocketmine\data\runtime\RuntimeDataReader;
use pocketmine\data\runtime\RuntimeDataWriter;
use pocketmine\data\runtime\RuntimeEnumDeserializer;
use pocketmine\data\runtime\RuntimeEnumSerializer;
use pocketmine\item\Axe;
use pocketmine\item\Item;
use pocketmine\item\ItemTypeIds;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\sound\CopperWaxApplySound;
use pocketmine\world\sound\CopperWaxRemoveSound;
use pocketmine\world\sound\ItemUseOnBlockSound;
trait CopperTrait{
private CopperOxidation $oxidation;
private bool $waxed;
public function getRequiredTypeDataBits() : int{ return 3; }
protected function decodeType(RuntimeDataReader $r) : void{
$this->oxidation = RuntimeEnumDeserializer::readCopperOxidation($r);
$this->waxed = $r->readBool();
}
protected function encodeType(RuntimeDataWriter $w) : void{
RuntimeEnumSerializer::writeCopperOxidation($w, $this->oxidation);
$w->writeBool($this->waxed);
}
public function getOxidation() : CopperOxidation{ return $this->oxidation; }
/** @return $this */
public function setOxidation(CopperOxidation $oxidation) : self{
$this->oxidation = $oxidation;
return $this;
}
public function isWaxed() : bool{ return $this->waxed; }
/** @return $this */
public function setWaxed(bool $waxed) : self{
$this->waxed = $waxed;
return $this;
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->waxed && $item->getTypeId() === ItemTypeIds::HONEYCOMB){
$this->waxed = true;
$this->position->getWorld()->setBlock($this->position, $this);
//TODO: orange particles are supposed to appear when applying wax
$this->position->getWorld()->addSound($this->position, new CopperWaxApplySound());
$item->pop();
return true;
}
if($item instanceof Axe){
if($this->waxed){
$this->waxed = false;
$this->position->getWorld()->setBlock($this->position, $this);
//TODO: white particles are supposed to appear when removing wax
$this->position->getWorld()->addSound($this->position, new CopperWaxRemoveSound());
$item->applyDamage(1);
return true;
}
$previousOxidation = $this->oxidation->getPrevious();
if($previousOxidation !== null){
$this->oxidation = $previousOxidation;
$this->position->getWorld()->setBlock($this->position, $this);
//TODO: turquoise particles are supposed to appear when removing oxidation
$this->position->getWorld()->addSound($this->position, new ItemUseOnBlockSound($this));
$item->applyDamage(1);
return true;
}
}
return false;
}
}

View File

@ -38,7 +38,7 @@ trait SignLikeRotationTrait{
}
protected function encodeState(RuntimeDataWriter $w) : void{
$w->writeInt(4, $this->rotation);
$w->writeBoundedInt(4, 0, 15, $this->rotation);
}
public function getRotation() : int{ return $this->rotation; }

View File

@ -39,9 +39,6 @@ use pocketmine\data\SavedDataLoadingException;
use pocketmine\errorhandler\ErrorToExceptionHandler;
use pocketmine\item\Item;
use pocketmine\nbt\LittleEndianNbtSerializer;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\network\mcpe\convert\RuntimeBlockMapping;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\Utils;
use pocketmine\world\format\io\GlobalItemDataHandlers;
use Webmozart\PathUtil\Path;
@ -54,39 +51,6 @@ use function json_decode;
final class CraftingManagerFromDataHelper{
private static function deserializeItemStackFromNameMeta(string $name, int $meta) : ?Item{
$blockName = BlockItemIdMap::getInstance()->lookupBlockId($name);
if($blockName !== null){
$blockStateDictionary = RuntimeBlockMapping::getInstance()->getBlockStateDictionary();
$blockRuntimeId = $blockStateDictionary->lookupStateIdFromIdMeta($name, $meta === RecipeIngredientData::WILDCARD_META_VALUE ? 0 : $meta);
if($blockRuntimeId === null){
throw new SavedDataLoadingException("$blockName with meta $meta doesn't map to any known blockstate");
}
$blockStateData = $blockStateDictionary->getDataFromStateId($blockRuntimeId);
if($blockStateData === null){
throw new AssumptionFailedError("We just looked up the runtime ID for this state, so it can't possibly be null");
}
}else{
$blockStateData = null;
}
//TODO: for wildcards, we only need a way to check if the item serializer recognizes the ID; we don't need to
//deserialize the whole itemstack, which might give bogus results anyway if meta 0 isn't recognized
$itemTypeData = new SavedItemData(
$name,
$meta === RecipeIngredientData::WILDCARD_META_VALUE ? 0 : $meta,
$blockStateData,
null
);
try{
return GlobalItemDataHandlers::getDeserializer()->deserializeType($itemTypeData);
}catch(ItemTypeDeserializeException){
//probably unknown item
return null;
}
}
private static function deserializeIngredient(RecipeIngredientData $data) : ?RecipeIngredient{
if(isset($data->count) && $data->count !== 1){
//every case we've seen so far where this isn't the case, it's been a bug and the count was ignored anyway
@ -94,26 +58,50 @@ final class CraftingManagerFromDataHelper{
throw new SavedDataLoadingException("Recipe inputs should have a count of exactly 1");
}
$itemStack = self::deserializeItemStackFromNameMeta($data->name, $data->meta);
$meta = $data->meta ?? null;
if($meta === RecipeIngredientData::WILDCARD_META_VALUE){
//this could be an unimplemented item, but it doesn't really matter, since the item shouldn't be able to
//be obtained anyway - filtering unknown items is only really important for outputs, to prevent players
//obtaining them
return new MetaWildcardRecipeIngredient($data->name);
}
$itemStack = self::deserializeItemStackFromFields(
$data->name,
$meta,
$data->count ?? null,
$data->block_states ?? null,
null,
[],
[]
);
if($itemStack === null){
//probably unknown item
return null;
}
return $data->meta === RecipeIngredientData::WILDCARD_META_VALUE ?
new MetaWildcardRecipeIngredient($data->name) :
new ExactRecipeIngredient($itemStack);
return new ExactRecipeIngredient($itemStack);
}
public static function deserializeItemStack(ItemStackData $data) : ?Item{
//count, name, block_name, block_states, meta, nbt, can_place_on, can_destroy
$name = $data->name;
$meta = $data->meta ?? 0;
$count = $data->count ?? 1;
return self::deserializeItemStackFromFields(
$data->name,
$data->meta ?? null,
$data->count ?? null,
$data->block_states ?? null,
$data->nbt ?? null,
$data->can_place_on ?? [],
$data->can_destroy ?? []
);
}
$blockStatesRaw = $data->block_states ?? null;
$nbtRaw = $data->nbt ?? null;
$canPlaceOn = $data->can_place_on ?? [];
$canDestroy = $data->can_destroy ?? [];
/**
* @param string[] $canPlaceOn
* @param string[] $canDestroy
*/
private static function deserializeItemStackFromFields(string $name, ?int $meta, ?int $count, ?string $blockStatesRaw, ?string $nbtRaw, array $canPlaceOn, array $canDestroy) : ?Item{
$meta ??= 0;
$count ??= 1;
$blockName = BlockItemIdMap::getInstance()->lookupBlockId($name);
if($blockName !== null){
@ -121,10 +109,11 @@ final class CraftingManagerFromDataHelper{
throw new SavedDataLoadingException("Meta should not be specified for blockitems");
}
$blockStatesTag = $blockStatesRaw === null ?
CompoundTag::create() :
[] :
(new LittleEndianNbtSerializer())
->read(ErrorToExceptionHandler::trapAndRemoveFalse(fn() => base64_decode($blockStatesRaw, true)))
->mustGetCompoundTag();
->mustGetCompoundTag()
->getValue();
$blockStateData = new BlockStateData($blockName, $blockStatesTag, BlockStateData::CURRENT_VERSION);
}else{
$blockStateData = null;
@ -224,7 +213,8 @@ final class CraftingManagerFromDataHelper{
$recipeType = match($recipe->block){
"crafting_table" => ShapelessRecipeType::CRAFTING(),
"stonecutter" => ShapelessRecipeType::STONECUTTER(),
//TODO: Cartography Table
"smithing_table" => ShapelessRecipeType::SMITHING(),
"cartography_table" => ShapelessRecipeType::CARTOGRAPHY(),
default => null
};
if($recipeType === null){
@ -325,7 +315,11 @@ final class CraftingManagerFromDataHelper{
$inputId = $recipe->input_item_name;
$outputId = $recipe->output_item_name;
if(self::deserializeItemStackFromNameMeta($inputId, 0) === null || self::deserializeItemStackFromNameMeta($outputId, 0) === null){
//TODO: this is a really awful way to just check if an ID is recognized ...
if(
self::deserializeItemStackFromFields($inputId, null, null, null, null, [], []) === null ||
self::deserializeItemStackFromFields($outputId, null, null, null, null, [], []) === null
){
//unknown item
continue;
}

View File

@ -31,7 +31,9 @@ use pocketmine\utils\EnumTrait;
* @see build/generate-registry-annotations.php
* @generate-registry-docblock
*
* @method static ShapelessRecipeType CARTOGRAPHY()
* @method static ShapelessRecipeType CRAFTING()
* @method static ShapelessRecipeType SMITHING()
* @method static ShapelessRecipeType STONECUTTER()
*/
final class ShapelessRecipeType{
@ -40,7 +42,9 @@ final class ShapelessRecipeType{
protected static function setup() : void{
self::registerAll(
new self("crafting"),
new self("stonecutter")
new self("stonecutter"),
new self("smithing"),
new self("cartography")
);
}
}

View File

@ -28,13 +28,11 @@ final class RecipeIngredientData{
/** @required */
public string $name;
/** @required */
public int $meta;
public string $block_states;
public int $count;
public function __construct(string $name, int $meta){
public function __construct(string $name){
$this->name = $name;
$this->meta = $meta;
}
}

View File

@ -26,7 +26,7 @@ namespace pocketmine\data\bedrock;
use pocketmine\utils\SingletonTrait;
use Webmozart\PathUtil\Path;
final class LegacyBiomeIdToStringIdMap extends LegacyToStringBidirectionalIdMap{
final class LegacyBiomeIdToStringIdMap extends LegacyToStringIdMap{
use SingletonTrait;
public function __construct(){

View File

@ -26,7 +26,7 @@ namespace pocketmine\data\bedrock;
use pocketmine\utils\SingletonTrait;
use Webmozart\PathUtil\Path;
final class LegacyEntityIdToStringIdMap extends LegacyToStringBidirectionalIdMap{
final class LegacyEntityIdToStringIdMap extends LegacyToStringIdMap{
use SingletonTrait;
public function __construct(){

View File

@ -31,18 +31,13 @@ use function is_int;
use function is_string;
use function json_decode;
abstract class LegacyToStringBidirectionalIdMap{
abstract class LegacyToStringIdMap{
/**
* @var string[]
* @phpstan-var array<int, string>
*/
private array $legacyToString = [];
/**
* @var int[]
* @phpstan-var array<string, int>
*/
private array $stringToLegacy = [];
public function __construct(string $file){
$stringToLegacyId = json_decode(Utils::assumeNotFalse(file_get_contents($file), "Missing required resource file"), true);
@ -54,7 +49,6 @@ abstract class LegacyToStringBidirectionalIdMap{
throw new AssumptionFailedError("ID map should have string keys and int values");
}
$this->legacyToString[$legacyId] = $stringId;
$this->stringToLegacy[$stringId] = $legacyId;
}
}
@ -62,10 +56,6 @@ abstract class LegacyToStringBidirectionalIdMap{
return $this->legacyToString[$legacy] ?? null;
}
public function stringToLegacy(string $string) : ?int{
return $this->stringToLegacy[$string] ?? null;
}
/**
* @return string[]
* @phpstan-return array<int, string>
@ -74,11 +64,10 @@ abstract class LegacyToStringBidirectionalIdMap{
return $this->legacyToString;
}
/**
* @return int[]
* @phpstan-return array<string, int>
*/
public function getStringToLegacyMap() : array{
return $this->stringToLegacy;
public function add(string $string, int $legacy) : void{
if(isset($this->legacyToString[$legacy])){
throw new \InvalidArgumentException("Legacy ID $legacy is already mapped to string " . $this->legacyToString[$legacy]);
}
$this->legacyToString[$legacy] = $string;
}
}

View File

@ -25,6 +25,8 @@ namespace pocketmine\data\bedrock\block;
use pocketmine\nbt\NbtException;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\Tag;
use pocketmine\utils\Utils;
use function array_keys;
use function count;
use function implode;
@ -46,15 +48,27 @@ final class BlockStateData{
public const TAG_STATES = "states";
public const TAG_VERSION = "version";
/**
* @param Tag[] $states
* @phpstan-param array<string, Tag> $states
*/
public function __construct(
private string $name,
private CompoundTag $states,
private array $states,
private int $version
){}
public function getName() : string{ return $this->name; }
public function getStates() : CompoundTag{ return $this->states; }
/**
* @return Tag[]
* @phpstan-return array<string, Tag>
*/
public function getStates() : array{ return $this->states; }
public function getState(string $name) : ?Tag{
return $this->states[$name] ?? null;
}
public function getVersion() : int{ return $this->version; }
@ -76,20 +90,30 @@ final class BlockStateData{
throw new BlockStateDeserializeException("Unexpected extra keys: " . implode(", ", array_keys($allKeys)));
}
return new self($name, $states, $version);
return new self($name, $states->getValue(), $version);
}
public function toNbt() : CompoundTag{
$statesTag = CompoundTag::create();
foreach(Utils::stringifyKeys($this->states) as $key => $value){
$statesTag->setTag($key, $value);
}
return CompoundTag::create()
->setString(self::TAG_NAME, $this->name)
->setInt(self::TAG_VERSION, $this->version)
->setTag(self::TAG_STATES, $this->states);
->setTag(self::TAG_STATES, $statesTag);
}
public function equals(self $that) : bool{
return
$this->name === $that->name &&
$this->states->equals($that->states) &&
$this->version === $that->version;
if($this->name !== $that->name || count($this->states) !== count($that->states)){
return false;
}
foreach(Utils::stringifyKeys($this->states) as $k => $v){
if(!isset($that->states[$k]) || !$that->states[$k]->equals($v)){
return false;
}
}
return true;
}
}

View File

@ -23,6 +23,8 @@ declare(strict_types=1);
namespace pocketmine\data\bedrock\block;
use function count;
final class CachingBlockStateDeserializer implements DelegatingBlockStateDeserializer{
/**
@ -36,7 +38,7 @@ final class CachingBlockStateDeserializer implements DelegatingBlockStateDeseria
){}
public function deserialize(BlockStateData $stateData) : int{
if($stateData->getStates()->count() === 0){
if(count($stateData->getStates()) === 0){
//if a block has zero properties, we can keep a map of string ID -> internal blockstate ID
return $this->simpleCache[$stateData->getName()] ??= $this->realDeserializer->deserialize($stateData);
}

View File

@ -39,6 +39,9 @@ use pocketmine\block\BrownMushroomBlock;
use pocketmine\block\Button;
use pocketmine\block\Cactus;
use pocketmine\block\Cake;
use pocketmine\block\CakeWithCandle;
use pocketmine\block\CakeWithDyedCandle;
use pocketmine\block\Candle;
use pocketmine\block\Carpet;
use pocketmine\block\Carrot;
use pocketmine\block\CarvedPumpkin;
@ -47,6 +50,9 @@ use pocketmine\block\Chest;
use pocketmine\block\CocoaBlock;
use pocketmine\block\Concrete;
use pocketmine\block\ConcretePowder;
use pocketmine\block\Copper;
use pocketmine\block\CopperSlab;
use pocketmine\block\CopperStairs;
use pocketmine\block\Coral;
use pocketmine\block\CoralBlock;
use pocketmine\block\DaylightSensor;
@ -55,6 +61,7 @@ use pocketmine\block\Dirt;
use pocketmine\block\Door;
use pocketmine\block\DoublePlant;
use pocketmine\block\DoubleTallGrass;
use pocketmine\block\DyedCandle;
use pocketmine\block\DyedShulkerBox;
use pocketmine\block\EnderChest;
use pocketmine\block\EndPortalFrame;
@ -78,6 +85,7 @@ use pocketmine\block\Leaves;
use pocketmine\block\Lectern;
use pocketmine\block\Lever;
use pocketmine\block\Light;
use pocketmine\block\LightningRod;
use pocketmine\block\LitPumpkin;
use pocketmine\block\Loom;
use pocketmine\block\MelonStem;
@ -167,6 +175,7 @@ final class BlockObjectToBlockStateSerializer implements BlockStateSerializer{
private array $serializers = [];
public function __construct(){
$this->registerCandleSerializers();
$this->registerSerializers();
}
@ -238,6 +247,50 @@ final class BlockObjectToBlockStateSerializer implements BlockStateSerializer{
return $writer->getBlockStateData();
}
private function registerCandleSerializers() : void{
$this->map(Blocks::CANDLE(), fn(Candle $block) => Helper::encodeCandle($block, new Writer(Ids::CANDLE)));
$this->map(Blocks::DYED_CANDLE(), fn(DyedCandle $block) => Helper::encodeCandle($block, new Writer(match($block->getColor()){
DyeColor::BLACK() => Ids::BLACK_CANDLE,
DyeColor::BLUE() => Ids::BLUE_CANDLE,
DyeColor::BROWN() => Ids::BROWN_CANDLE,
DyeColor::CYAN() => Ids::CYAN_CANDLE,
DyeColor::GRAY() => Ids::GRAY_CANDLE,
DyeColor::GREEN() => Ids::GREEN_CANDLE,
DyeColor::LIGHT_BLUE() => Ids::LIGHT_BLUE_CANDLE,
DyeColor::LIGHT_GRAY() => Ids::LIGHT_GRAY_CANDLE,
DyeColor::LIME() => Ids::LIME_CANDLE,
DyeColor::MAGENTA() => Ids::MAGENTA_CANDLE,
DyeColor::ORANGE() => Ids::ORANGE_CANDLE,
DyeColor::PINK() => Ids::PINK_CANDLE,
DyeColor::PURPLE() => Ids::PURPLE_CANDLE,
DyeColor::RED() => Ids::RED_CANDLE,
DyeColor::WHITE() => Ids::WHITE_CANDLE,
DyeColor::YELLOW() => Ids::YELLOW_CANDLE,
default => throw new AssumptionFailedError("Unhandled DyeColor " . $block->getColor()->name())
})));
$this->map(Blocks::CAKE_WITH_CANDLE(), fn(CakeWithCandle $block) => Writer::create(Ids::CANDLE_CAKE)
->writeBool(StateNames::LIT, $block->isLit()));
$this->map(Blocks::CAKE_WITH_DYED_CANDLE(), fn(CakeWithDyedCandle $block) => Writer::create(match($block->getColor()){
DyeColor::BLACK() => Ids::BLACK_CANDLE_CAKE,
DyeColor::BLUE() => Ids::BLUE_CANDLE_CAKE,
DyeColor::BROWN() => Ids::BROWN_CANDLE_CAKE,
DyeColor::CYAN() => Ids::CYAN_CANDLE_CAKE,
DyeColor::GRAY() => Ids::GRAY_CANDLE_CAKE,
DyeColor::GREEN() => Ids::GREEN_CANDLE_CAKE,
DyeColor::LIGHT_BLUE() => Ids::LIGHT_BLUE_CANDLE_CAKE,
DyeColor::LIGHT_GRAY() => Ids::LIGHT_GRAY_CANDLE_CAKE,
DyeColor::LIME() => Ids::LIME_CANDLE_CAKE,
DyeColor::MAGENTA() => Ids::MAGENTA_CANDLE_CAKE,
DyeColor::ORANGE() => Ids::ORANGE_CANDLE_CAKE,
DyeColor::PINK() => Ids::PINK_CANDLE_CAKE,
DyeColor::PURPLE() => Ids::PURPLE_CANDLE_CAKE,
DyeColor::RED() => Ids::RED_CANDLE_CAKE,
DyeColor::WHITE() => Ids::WHITE_CANDLE_CAKE,
DyeColor::YELLOW() => Ids::YELLOW_CANDLE_CAKE,
default => throw new AssumptionFailedError("Unhandled DyeColor " . $block->getColor()->name())
})->writeBool(StateNames::LIT, $block->isLit()));
}
private function registerSerializers() : void{
$this->map(Blocks::ACACIA_BUTTON(), fn(WoodenButton $block) => Helper::encodeButton($block, new Writer(Ids::ACACIA_BUTTON)));
$this->map(Blocks::ACACIA_DOOR(), fn(WoodenDoor $block) => Helper::encodeDoor($block, new Writer(Ids::ACACIA_DOOR)));
@ -390,6 +443,7 @@ final class BlockObjectToBlockStateSerializer implements BlockStateSerializer{
->writeColor($block->getColor());
});
$this->map(Blocks::CARROTS(), fn(Carrot $block) => Helper::encodeCrops($block, new Writer(Ids::CARROTS)));
$this->mapSimple(Blocks::CARTOGRAPHY_TABLE(), Ids::CARTOGRAPHY_TABLE);
$this->map(Blocks::CARVED_PUMPKIN(), function(CarvedPumpkin $block) : Writer{
return Writer::create(Ids::CARVED_PUMPKIN)
->writeLegacyHorizontalFacing($block->getFacing());
@ -418,6 +472,80 @@ final class BlockObjectToBlockStateSerializer implements BlockStateSerializer{
$this->mapStairs(Blocks::COBBLESTONE_STAIRS(), Ids::STONE_STAIRS);
$this->map(Blocks::COBBLESTONE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_COBBLESTONE));
$this->mapSimple(Blocks::COBWEB(), Ids::WEB);
$this->map(Blocks::COPPER(), function(Copper $block) : Writer{
$oxidation = $block->getOxidation();
return new Writer($block->isWaxed() ?
Helper::selectCopperId($oxidation, Ids::WAXED_COPPER, Ids::WAXED_EXPOSED_COPPER, Ids::WAXED_WEATHERED_COPPER, Ids::WAXED_OXIDIZED_COPPER) :
Helper::selectCopperId($oxidation, Ids::COPPER_BLOCK, Ids::EXPOSED_COPPER, Ids::WEATHERED_COPPER, Ids::OXIDIZED_COPPER)
);
});
$this->map(Blocks::CUT_COPPER(), function(Copper $block) : Writer{
$oxidation = $block->getOxidation();
return new Writer($block->isWaxed() ?
Helper::selectCopperId($oxidation, Ids::WAXED_CUT_COPPER, Ids::WAXED_EXPOSED_CUT_COPPER, Ids::WAXED_WEATHERED_CUT_COPPER, Ids::WAXED_OXIDIZED_CUT_COPPER) :
Helper::selectCopperId($oxidation, Ids::CUT_COPPER, Ids::EXPOSED_CUT_COPPER, Ids::WEATHERED_CUT_COPPER, Ids::OXIDIZED_CUT_COPPER)
);
});
$this->map(Blocks::CUT_COPPER_SLAB(), function(CopperSlab $block) : Writer{
$oxidation = $block->getOxidation();
return Helper::encodeSlab(
$block,
($block->isWaxed() ?
Helper::selectCopperId(
$oxidation,
Ids::WAXED_CUT_COPPER_SLAB,
Ids::WAXED_EXPOSED_CUT_COPPER_SLAB,
Ids::WAXED_WEATHERED_CUT_COPPER_SLAB,
Ids::WAXED_OXIDIZED_CUT_COPPER_SLAB
) :
Helper::selectCopperId(
$oxidation,
Ids::CUT_COPPER_SLAB,
Ids::EXPOSED_CUT_COPPER_SLAB,
Ids::WEATHERED_CUT_COPPER_SLAB,
Ids::OXIDIZED_CUT_COPPER_SLAB
)
),
($block->isWaxed() ?
Helper::selectCopperId(
$oxidation,
Ids::WAXED_DOUBLE_CUT_COPPER_SLAB,
Ids::WAXED_EXPOSED_DOUBLE_CUT_COPPER_SLAB,
Ids::WAXED_WEATHERED_DOUBLE_CUT_COPPER_SLAB,
Ids::WAXED_OXIDIZED_DOUBLE_CUT_COPPER_SLAB
) :
Helper::selectCopperId(
$oxidation,
Ids::DOUBLE_CUT_COPPER_SLAB,
Ids::EXPOSED_DOUBLE_CUT_COPPER_SLAB,
Ids::WEATHERED_DOUBLE_CUT_COPPER_SLAB,
Ids::OXIDIZED_DOUBLE_CUT_COPPER_SLAB
)
)
);
});
$this->map(Blocks::CUT_COPPER_STAIRS(), function(CopperStairs $block) : Writer{
$oxidation = $block->getOxidation();
return Helper::encodeStairs(
$block,
new Writer($block->isWaxed() ?
Helper::selectCopperId(
$oxidation,
Ids::WAXED_CUT_COPPER_STAIRS,
Ids::WAXED_EXPOSED_CUT_COPPER_STAIRS,
Ids::WAXED_WEATHERED_CUT_COPPER_STAIRS,
Ids::WAXED_OXIDIZED_CUT_COPPER_STAIRS
) :
Helper::selectCopperId(
$oxidation,
Ids::CUT_COPPER_STAIRS,
Ids::EXPOSED_CUT_COPPER_STAIRS,
Ids::WEATHERED_CUT_COPPER_STAIRS,
Ids::OXIDIZED_CUT_COPPER_STAIRS
)
)
);
});
$this->map(Blocks::COCOA_POD(), function(CocoaBlock $block) : Writer{
return Writer::create(Ids::COCOA)
->writeInt(StateNames::AGE, $block->getAge())
@ -472,6 +600,7 @@ final class BlockObjectToBlockStateSerializer implements BlockStateSerializer{
$this->map(Blocks::CRIMSON_STEM(), fn(Wood $block) => Helper::encodeNewLog($block, Ids::CRIMSON_STEM, Ids::STRIPPED_CRIMSON_STEM));
$this->map(Blocks::CRIMSON_TRAPDOOR(), fn(Trapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::CRIMSON_TRAPDOOR)));
$this->map(Blocks::CRIMSON_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::CRIMSON_WALL_SIGN)));
$this->mapSimple(Blocks::CRYING_OBSIDIAN(), Ids::CRYING_OBSIDIAN);
$this->map(Blocks::CUT_RED_SANDSTONE(), fn() => Helper::encodeSandstone(Ids::RED_SANDSTONE, StringValues::SAND_STONE_TYPE_CUT));
$this->map(Blocks::CUT_RED_SANDSTONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab4($block, StringValues::STONE_SLAB_TYPE_4_CUT_RED_SANDSTONE));
$this->map(Blocks::CUT_SANDSTONE(), fn() => Helper::encodeSandstone(Ids::SANDSTONE, StringValues::SAND_STONE_TYPE_CUT));
@ -707,6 +836,7 @@ final class BlockObjectToBlockStateSerializer implements BlockStateSerializer{
->writeInt(StateNames::AGE, $block->getAge());
});
$this->map(Blocks::FURNACE(), fn(Furnace $block) => Helper::encodeFurnace($block, Ids::FURNACE, Ids::LIT_FURNACE));
$this->mapSimple(Blocks::GILDED_BLACKSTONE(), Ids::GILDED_BLACKSTONE);
$this->mapSimple(Blocks::GLASS(), Ids::GLASS);
$this->mapSimple(Blocks::GLASS_PANE(), Ids::GLASS_PANE);
$this->map(Blocks::GLAZED_TERRACOTTA(), function(GlazedTerracotta $block) : Writer{
@ -743,6 +873,7 @@ final class BlockObjectToBlockStateSerializer implements BlockStateSerializer{
$this->mapSimple(Blocks::GRASS_PATH(), Ids::GRASS_PATH);
$this->mapSimple(Blocks::GRAVEL(), Ids::GRAVEL);
$this->map(Blocks::GREEN_TORCH(), fn(Torch $block) => Helper::encodeColoredTorch($block, true, Writer::create(Ids::COLORED_TORCH_RG)));
$this->mapSimple(Blocks::HANGING_ROOTS(), Ids::HANGING_ROOTS);
$this->mapSimple(Blocks::HARDENED_CLAY(), Ids::HARDENED_CLAY);
$this->mapSimple(Blocks::HARDENED_GLASS(), Ids::HARD_GLASS);
$this->mapSimple(Blocks::HARDENED_GLASS_PANE(), Ids::HARD_GLASS_PANE);
@ -779,7 +910,7 @@ final class BlockObjectToBlockStateSerializer implements BlockStateSerializer{
$this->mapSimple(Blocks::IRON_ORE(), Ids::IRON_ORE);
$this->map(Blocks::IRON_TRAPDOOR(), fn(Trapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::IRON_TRAPDOOR)));
$this->map(Blocks::ITEM_FRAME(), function(ItemFrame $block) : Writer{
return Writer::create(Ids::FRAME)
return Writer::create($block->isGlowing() ? Ids::GLOW_FRAME : Ids::FRAME)
->writeBool(StateNames::ITEM_FRAME_MAP_BIT, $block->hasMap())
->writeBool(StateNames::ITEM_FRAME_PHOTO_BIT, false)
->writeFacingDirection($block->getFacing());
@ -840,6 +971,10 @@ final class BlockObjectToBlockStateSerializer implements BlockStateSerializer{
return Writer::create(Ids::LIGHT_BLOCK)
->writeInt(StateNames::BLOCK_LIGHT_LEVEL, $block->getLightLevel());
});
$this->map(Blocks::LIGHTNING_ROD(), function(LightningRod $block) : Writer{
return Writer::create(Ids::LIGHTNING_ROD)
->writeFacingDirection($block->getFacing());
});
$this->map(Blocks::LILAC(), fn(DoublePlant $block) => Helper::encodeDoublePlant($block, StringValues::DOUBLE_PLANT_TYPE_SYRINGA, Writer::create(Ids::DOUBLE_PLANT)));
$this->map(Blocks::LILY_OF_THE_VALLEY(), fn() => Helper::encodeRedFlower(StringValues::FLOWER_TYPE_LILY_OF_THE_VALLEY));
$this->mapSimple(Blocks::LILY_PAD(), Ids::WATERLILY);
@ -898,6 +1033,7 @@ final class BlockObjectToBlockStateSerializer implements BlockStateSerializer{
$this->map(Blocks::MUSHROOM_STEM(), fn() => Writer::create(Ids::BROWN_MUSHROOM_BLOCK)
->writeInt(StateNames::HUGE_MUSHROOM_BITS, BlockLegacyMetadata::MUSHROOM_BLOCK_STEM));
$this->mapSimple(Blocks::MYCELIUM(), Ids::MYCELIUM);
$this->mapSimple(Blocks::NETHERITE(), Ids::NETHERITE_BLOCK);
$this->mapSimple(Blocks::NETHERRACK(), Ids::NETHERRACK);
$this->mapSimple(Blocks::NETHER_BRICKS(), Ids::NETHER_BRICK);
$this->mapSimple(Blocks::NETHER_BRICK_FENCE(), Ids::NETHER_BRICK_FENCE);
@ -1071,6 +1207,7 @@ final class BlockObjectToBlockStateSerializer implements BlockStateSerializer{
$this->mapSimple(Blocks::SHROOMLIGHT(), Ids::SHROOMLIGHT);
$this->mapSimple(Blocks::SHULKER_BOX(), Ids::UNDYED_SHULKER_BOX);
$this->mapSimple(Blocks::SLIME(), Ids::SLIME);
$this->mapSimple(Blocks::SMITHING_TABLE(), Ids::SMITHING_TABLE);
$this->map(Blocks::SMOKER(), fn(Furnace $block) => Helper::encodeFurnace($block, Ids::SMOKER, Ids::LIT_SMOKER));
$this->mapSimple(Blocks::SMOOTH_BASALT(), Ids::SMOOTH_BASALT);
$this->map(Blocks::SMOOTH_QUARTZ(), fn() => Helper::encodeQuartz(StringValues::CHISEL_TYPE_SMOOTH, Axis::Y));
@ -1167,6 +1304,7 @@ final class BlockObjectToBlockStateSerializer implements BlockStateSerializer{
});
$this->map(Blocks::TALL_GRASS(), fn() => Writer::create(Ids::TALLGRASS)
->writeString(StateNames::TALL_GRASS_TYPE, StringValues::TALL_GRASS_TYPE_TALL));
$this->mapSimple(Blocks::TINTED_GLASS(), Ids::TINTED_GLASS);
$this->map(Blocks::TNT(), function(TNT $block) : Writer{
return Writer::create(Ids::TNT)
->writeBool(StateNames::ALLOW_UNDERWATER_BIT, $block->worksUnderwater())
@ -1231,6 +1369,7 @@ final class BlockObjectToBlockStateSerializer implements BlockStateSerializer{
$this->map(Blocks::WARPED_STEM(), fn(Wood $block) => Helper::encodeNewLog($block, Ids::WARPED_STEM, Ids::STRIPPED_WARPED_STEM));
$this->map(Blocks::WARPED_TRAPDOOR(), fn(Trapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::WARPED_TRAPDOOR)));
$this->map(Blocks::WARPED_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::WARPED_WALL_SIGN)));
$this->mapSimple(Blocks::WARPED_WART_BLOCK(), Ids::WARPED_WART_BLOCK);
$this->map(Blocks::WATER(), fn(Water $block) => Helper::encodeLiquid($block, Ids::WATER, Ids::FLOWING_WATER));
$this->map(Blocks::WEIGHTED_PRESSURE_PLATE_HEAVY(), function(WeightedPressurePlateHeavy $block) : Writer{
return Writer::create(Ids::HEAVY_WEIGHTED_PRESSURE_PLATE)
@ -1242,6 +1381,7 @@ final class BlockObjectToBlockStateSerializer implements BlockStateSerializer{
});
$this->map(Blocks::WHEAT(), fn(Wheat $block) => Helper::encodeCrops($block, new Writer(Ids::WHEAT)));
$this->map(Blocks::WHITE_TULIP(), fn() => Helper::encodeRedFlower(StringValues::FLOWER_TYPE_TULIP_WHITE));
$this->mapSimple(Blocks::WITHER_ROSE(), Ids::WITHER_ROSE);
$this->map(Blocks::WOOL(), function(Wool $block) : Writer{
return Writer::create(Ids::WOOL)
->writeColor($block->getColor());

View File

@ -25,6 +25,10 @@ namespace pocketmine\data\bedrock\block\convert;
use pocketmine\block\Block;
use pocketmine\block\Button;
use pocketmine\block\Candle;
use pocketmine\block\Copper;
use pocketmine\block\CopperSlab;
use pocketmine\block\CopperStairs;
use pocketmine\block\Crops;
use pocketmine\block\DaylightSensor;
use pocketmine\block\Door;
@ -32,6 +36,7 @@ use pocketmine\block\FenceGate;
use pocketmine\block\FloorCoralFan;
use pocketmine\block\FloorSign;
use pocketmine\block\GlazedTerracotta;
use pocketmine\block\ItemFrame;
use pocketmine\block\Liquid;
use pocketmine\block\RedMushroomBlock;
use pocketmine\block\RedstoneComparator;
@ -41,8 +46,10 @@ use pocketmine\block\Slab;
use pocketmine\block\Stair;
use pocketmine\block\Stem;
use pocketmine\block\Trapdoor;
use pocketmine\block\utils\CopperOxidation;
use pocketmine\block\utils\DyeColor;
use pocketmine\block\VanillaBlocks;
use pocketmine\block\VanillaBlocks as Blocks;
use pocketmine\block\Wall;
use pocketmine\block\WallCoralFan;
use pocketmine\block\WallSign;
@ -51,6 +58,7 @@ use pocketmine\block\Wood;
use pocketmine\data\bedrock\block\BlockLegacyMetadata;
use pocketmine\data\bedrock\block\BlockStateDeserializeException;
use pocketmine\data\bedrock\block\BlockStateNames;
use pocketmine\data\bedrock\block\BlockStateNames as StateNames;
use pocketmine\data\bedrock\block\BlockStateStringValues as StringValues;
use pocketmine\data\bedrock\MushroomBlockTypeIdMap;
use pocketmine\math\Axis;
@ -66,6 +74,13 @@ final class BlockStateDeserializerHelper{
->setPressed($in->readBool(BlockStateNames::BUTTON_PRESSED_BIT));
}
/** @throws BlockStateDeserializeException */
public static function decodeCandle(Candle $block, BlockStateReader $in) : Candle{
return $block
->setCount($in->readBoundedInt(StateNames::CANDLES, 0, 3) + 1)
->setLit($in->readBool(StateNames::LIT));
}
/**
* @phpstan-template TCrops of Crops
* @phpstan-param TCrops $block
@ -85,6 +100,30 @@ final class BlockStateDeserializerHelper{
->setSubtractMode($in->readBool(BlockStateNames::OUTPUT_SUBTRACT_BIT));
}
/**
* @phpstan-template TBlock of Copper|CopperSlab|CopperStairs
*
* @phpstan-param TBlock $block
* @phpstan-return TBlock
*/
public static function decodeCopper(Copper|CopperSlab|CopperStairs $block, CopperOxidation $oxidation) : Copper|CopperSlab|CopperStairs{
$block->setOxidation($oxidation);
$block->setWaxed(false);
return $block;
}
/**
* @phpstan-template TBlock of Copper|CopperSlab|CopperStairs
*
* @phpstan-param TBlock $block
* @phpstan-return TBlock
*/
public static function decodeWaxedCopper(Copper|CopperSlab|CopperStairs $block, CopperOxidation $oxidation) : Copper|CopperSlab|CopperStairs{
$block->setOxidation($oxidation);
$block->setWaxed(true);
return $block;
}
/** @throws BlockStateDeserializeException */
public static function decodeDaylightSensor(DaylightSensor $block, BlockStateReader $in) : DaylightSensor{
return $block
@ -133,6 +172,14 @@ final class BlockStateDeserializerHelper{
->setFacing($in->readHorizontalFacing());
}
public static function decodeItemFrame(BlockStateReader $in, bool $glowing) : ItemFrame{
$in->todo(StateNames::ITEM_FRAME_PHOTO_BIT); //TODO: not sure what the point of this is
return Blocks::ITEM_FRAME()
->setFacing($in->readFacingDirection())
->setHasMap($in->readBool(StateNames::ITEM_FRAME_MAP_BIT))
->setGlowing($glowing);
}
/** @throws BlockStateDeserializeException */
public static function decodeLiquid(Liquid $block, BlockStateReader $in, bool $still) : Liquid{
$fluidHeightState = $in->readBoundedInt(BlockStateNames::LIQUID_DEPTH, 0, 15);

View File

@ -38,6 +38,7 @@ use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\nbt\tag\Tag;
use pocketmine\utils\Utils;
use function get_class;
final class BlockStateReader{
@ -66,7 +67,7 @@ final class BlockStateReader{
/** @throws BlockStateDeserializeException */
public function readBool(string $name) : bool{
$this->usedStates[$name] = true;
$tag = $this->data->getStates()->getTag($name);
$tag = $this->data->getState($name);
if($tag instanceof ByteTag){
switch($tag->getValue()){
case 0: return false;
@ -80,7 +81,7 @@ final class BlockStateReader{
/** @throws BlockStateDeserializeException */
public function readInt(string $name) : int{
$this->usedStates[$name] = true;
$tag = $this->data->getStates()->getTag($name);
$tag = $this->data->getState($name);
if($tag instanceof IntTag){
return $tag->getValue();
}
@ -100,7 +101,7 @@ final class BlockStateReader{
public function readString(string $name) : string{
$this->usedStates[$name] = true;
//TODO: only allow a specific set of values (strings are primarily used for enums)
$tag = $this->data->getStates()->getTag($name);
$tag = $this->data->getState($name);
if($tag instanceof StringTag){
return $tag->getValue();
}
@ -314,7 +315,7 @@ final class BlockStateReader{
* Explicitly mark a property as unused, so it doesn't get flagged as an error when debug mode is enabled
*/
public function ignored(string $name) : void{
if($this->data->getStates()->getTag($name) !== null){
if($this->data->getState($name) !== null){
$this->usedStates[$name] = true;
}else{
throw $this->missingOrWrongTypeException($name, null);
@ -332,7 +333,7 @@ final class BlockStateReader{
* @throws BlockStateDeserializeException
*/
public function checkUnreadProperties() : void{
foreach($this->data->getStates() as $name => $tag){
foreach(Utils::stringifyKeys($this->data->getStates()) as $name => $tag){
if(!isset($this->usedStates[$name])){
throw new BlockStateDeserializeException("Unread property \"$name\"");
}

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\data\bedrock\block\convert;
use pocketmine\block\Button;
use pocketmine\block\Candle;
use pocketmine\block\ChemistryTable;
use pocketmine\block\Crops;
use pocketmine\block\Door;
@ -41,14 +42,17 @@ use pocketmine\block\Stair;
use pocketmine\block\Stem;
use pocketmine\block\Torch;
use pocketmine\block\Trapdoor;
use pocketmine\block\utils\CopperOxidation;
use pocketmine\block\utils\SlabType;
use pocketmine\block\Wall;
use pocketmine\block\WallSign;
use pocketmine\block\Wood;
use pocketmine\data\bedrock\block\BlockStateNames;
use pocketmine\data\bedrock\block\BlockStateNames as StateNames;
use pocketmine\data\bedrock\block\BlockTypeNames as Ids;
use pocketmine\data\bedrock\MushroomBlockTypeIdMap;
use pocketmine\math\Facing;
use pocketmine\utils\AssumptionFailedError;
final class BlockStateSerializerHelper{
@ -65,6 +69,12 @@ final class BlockStateSerializerHelper{
->writeBool(BlockStateNames::BUTTON_PRESSED_BIT, $block->isPressed());
}
public static function encodeCandle(Candle $block, BlockStateWriter $out) : BlockStateWriter{
return $out
->writeBool(StateNames::LIT, $block->isLit())
->writeInt(StateNames::CANDLES, $block->getCount() - 1);
}
public static function encodeChemistryTable(ChemistryTable $block, string $chemistryTableType, BlockStateWriter $out) : BlockStateWriter{
return $out
->writeString(BlockStateNames::CHEMISTRY_TABLE_TYPE, $chemistryTableType)
@ -81,6 +91,16 @@ final class BlockStateSerializerHelper{
->writeTorchFacing($block->getFacing());
}
public static function selectCopperId(CopperOxidation $oxidation, string $noneId, string $exposedId, string $weatheredId, string $oxidizedId) : string{
return match($oxidation){
CopperOxidation::NONE() => $noneId,
CopperOxidation::EXPOSED() => $exposedId,
CopperOxidation::WEATHERED() => $weatheredId,
CopperOxidation::OXIDIZED() => $oxidizedId,
default => throw new AssumptionFailedError("Unhandled copper oxidation " . $oxidation->name())
};
}
public static function encodeDoor(Door $block, BlockStateWriter $out) : BlockStateWriter{
return $out
->writeBool(BlockStateNames::UPPER_BLOCK_BIT, $block->isTop())

View File

@ -35,17 +35,22 @@ use pocketmine\data\bedrock\block\BlockStateSerializeException;
use pocketmine\data\bedrock\block\BlockStateStringValues as StringValues;
use pocketmine\math\Axis;
use pocketmine\math\Facing;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\nbt\tag\Tag;
final class BlockStateWriter{
private CompoundTag $states;
/**
* @var Tag[]
* @phpstan-var array<string, Tag>
*/
private array $states = [];
public function __construct(
private string $id
){
$this->states = CompoundTag::create();
}
){}
public static function create(string $id) : self{
return new self($id);
@ -53,19 +58,19 @@ final class BlockStateWriter{
/** @return $this */
public function writeBool(string $name, bool $value) : self{
$this->states->setByte($name, $value ? 1 : 0);
$this->states[$name] = new ByteTag($value ? 1 : 0);
return $this;
}
/** @return $this */
public function writeInt(string $name, int $value) : self{
$this->states->setInt($name, $value);
$this->states[$name] = new IntTag($value);
return $this;
}
/** @return $this */
public function writeString(string $name, string $value) : self{
$this->states->setString($name, $value);
$this->states[$name] = new StringTag($value);
return $this;
}

View File

@ -51,7 +51,7 @@ final class BlockDataUpgrader{
$blockStateData = $this->upgradeStringIdMeta($id, $data);
if($blockStateData === null){
//unknown block, invalid ID
$blockStateData = new BlockStateData(BlockTypeNames::INFO_UPDATE, CompoundTag::create(), BlockStateData::CURRENT_VERSION);
$blockStateData = new BlockStateData(BlockTypeNames::INFO_UPDATE, [], BlockStateData::CURRENT_VERSION);
}
}else{
//Modern (post-1.13) blockstate

View File

@ -23,15 +23,9 @@ declare(strict_types=1);
namespace pocketmine\data\bedrock\block\upgrade;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\Tag;
use pocketmine\utils\Utils;
final class BlockStateUpgradeSchemaBlockRemap{
public CompoundTag $oldState;
public CompoundTag $newState;
/**
* @param Tag[] $oldState
* @param Tag[] $newState
@ -39,17 +33,8 @@ final class BlockStateUpgradeSchemaBlockRemap{
* @phpstan-param array<string, Tag> $newState
*/
public function __construct(
array $oldState,
public array $oldState,
public string $newName,
array $newState
){
$this->oldState = CompoundTag::create();
$this->newState = CompoundTag::create();
foreach(Utils::stringifyKeys($oldState) as $k => $v){
$this->oldState->setTag($k, $v);
}
foreach(Utils::stringifyKeys($newState) as $k => $v){
$this->newState->setTag($k, $v);
}
}
public array $newState
){}
}

View File

@ -240,9 +240,9 @@ final class BlockStateUpgradeSchemaUtils{
foreach(Utils::stringifyKeys($schema->remappedStates) as $oldBlockName => $remaps){
foreach($remaps as $remap){
$result->remappedStates[$oldBlockName][] = new BlockStateUpgradeSchemaModelBlockRemap(
array_map(fn(Tag $tag) => self::tagToJsonModel($tag), $remap->oldState->getValue()),
array_map(fn(Tag $tag) => self::tagToJsonModel($tag), $remap->oldState),
$remap->newName,
array_map(fn(Tag $tag) => self::tagToJsonModel($tag), $remap->newState->getValue()),
array_map(fn(Tag $tag) => self::tagToJsonModel($tag), $remap->newState),
);
}
}

View File

@ -24,9 +24,9 @@ declare(strict_types=1);
namespace pocketmine\data\bedrock\block\upgrade;
use pocketmine\data\bedrock\block\BlockStateData;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\Tag;
use pocketmine\utils\Utils;
use function count;
use function ksort;
use const SORT_NUMERIC;
@ -68,12 +68,20 @@ final class BlockStateUpgrader{
}
foreach($schemas as $schema){
$oldName = $blockStateData->getName();
$oldState = $blockStateData->getStates();
if(isset($schema->remappedStates[$oldName])){
foreach($schema->remappedStates[$oldName] as $remap){
if($blockStateData->getStates()->equals($remap->oldState)){
$blockStateData = new BlockStateData($remap->newName, clone $remap->newState, $resultVersion);
continue 2;
if(count($oldState) !== count($remap->oldState)){
continue; //try next state
}
foreach(Utils::stringifyKeys($oldState) as $k => $v){
if(!isset($remap->oldState[$k]) || !$remap->oldState[$k]->equals($v)){
continue 2; //try next state
}
}
$blockStateData = new BlockStateData($remap->newName, $remap->newState, $resultVersion);
continue 2; //try next schema
}
}
$newName = $schema->renamedIds[$oldName] ?? null;
@ -96,42 +104,44 @@ final class BlockStateUpgrader{
return $blockStateData;
}
private function cloneIfNeeded(CompoundTag $states, int &$stateChanges) : CompoundTag{
if($stateChanges === 0){
$states = clone $states;
/**
* @param Tag[] $states
* @phpstan-param array<string, Tag> $states
*
* @return Tag[]
* @phpstan-return array<string, Tag>
*/
private function applyPropertyAdded(BlockStateUpgradeSchema $schema, string $oldName, array $states, int &$stateChanges) : array{
if(isset($schema->addedProperties[$oldName])){
foreach(Utils::stringifyKeys($schema->addedProperties[$oldName]) as $propertyName => $value){
if(!isset($states[$propertyName])){
$stateChanges++;
$states[$propertyName] = $value;
}
}
}
$stateChanges++;
return $states;
}
private function applyPropertyAdded(BlockStateUpgradeSchema $schema, string $oldName, CompoundTag $states, int &$stateChanges) : CompoundTag{
$newStates = $states;
if(isset($schema->addedProperties[$oldName])){
foreach(Utils::stringifyKeys($schema->addedProperties[$oldName]) as $propertyName => $value){
$oldValue = $states->getTag($propertyName);
if($oldValue === null){
$newStates = $this->cloneIfNeeded($newStates, $stateChanges);
$newStates->setTag($propertyName, $value);
}
}
}
return $newStates;
}
private function applyPropertyRemoved(BlockStateUpgradeSchema $schema, string $oldName, CompoundTag $states, int &$stateChanges) : CompoundTag{
$newStates = $states;
/**
* @param Tag[] $states
* @phpstan-param array<string, Tag> $states
*
* @return Tag[]
* @phpstan-return array<string, Tag>
*/
private function applyPropertyRemoved(BlockStateUpgradeSchema $schema, string $oldName, array $states, int &$stateChanges) : array{
if(isset($schema->removedProperties[$oldName])){
foreach($schema->removedProperties[$oldName] as $propertyName){
if($states->getTag($propertyName) !== null){
$newStates = $this->cloneIfNeeded($newStates, $stateChanges);
$newStates->removeTag($propertyName);
if(isset($states[$propertyName])){
$stateChanges++;
unset($states[$propertyName]);
}
}
}
return $newStates;
return $states;
}
private function locateNewPropertyValue(BlockStateUpgradeSchema $schema, string $oldName, string $oldPropertyName, Tag $oldValue) : Tag{
@ -146,18 +156,25 @@ final class BlockStateUpgrader{
return $oldValue;
}
private function applyPropertyRenamedOrValueChanged(BlockStateUpgradeSchema $schema, string $oldName, CompoundTag $states, int &$stateChanges) : CompoundTag{
/**
* @param Tag[] $states
* @phpstan-param array<string, Tag> $states
*
* @return Tag[]
* @phpstan-return array<string, Tag>
*/
private function applyPropertyRenamedOrValueChanged(BlockStateUpgradeSchema $schema, string $oldName, array $states, int &$stateChanges) : array{
if(isset($schema->renamedProperties[$oldName])){
foreach(Utils::stringifyKeys($schema->renamedProperties[$oldName]) as $oldPropertyName => $newPropertyName){
$oldValue = $states->getTag($oldPropertyName);
$oldValue = $states[$oldPropertyName] ?? null;
if($oldValue !== null){
$states = $this->cloneIfNeeded($states, $stateChanges);
$states->removeTag($oldPropertyName);
$stateChanges++;
unset($states[$oldPropertyName]);
//If a value remap is needed, we need to do it here, since we won't be able to locate the property
//after it's been renamed - value remaps are always indexed by old property name for the sake of
//being able to do changes in any order.
$states->setTag($newPropertyName, $this->locateNewPropertyValue($schema, $oldName, $oldPropertyName, $oldValue));
$states[$newPropertyName] = $this->locateNewPropertyValue($schema, $oldName, $oldPropertyName, $oldValue);
}
}
}
@ -165,15 +182,22 @@ final class BlockStateUpgrader{
return $states;
}
private function applyPropertyValueChanged(BlockStateUpgradeSchema $schema, string $oldName, CompoundTag $states, int &$stateChanges) : CompoundTag{
/**
* @param Tag[] $states
* @phpstan-param array<string, Tag> $states
*
* @return Tag[]
* @phpstan-return array<string, Tag>
*/
private function applyPropertyValueChanged(BlockStateUpgradeSchema $schema, string $oldName, array $states, int &$stateChanges) : array{
if(isset($schema->remappedPropertyValues[$oldName])){
foreach(Utils::stringifyKeys($schema->remappedPropertyValues[$oldName]) as $oldPropertyName => $remappedValues){
$oldValue = $states->getTag($oldPropertyName);
$oldValue = $states[$oldPropertyName] ?? null;
if($oldValue !== null){
$newValue = $this->locateNewPropertyValue($schema, $oldName, $oldPropertyName, $oldValue);
if($newValue !== $oldValue){
$states = $this->cloneIfNeeded($states, $stateChanges);
$states->setTag($oldPropertyName, $newValue);
$stateChanges++;
$states[$oldPropertyName] = $newValue;
}
}
}

View File

@ -23,11 +23,11 @@ declare(strict_types=1);
namespace pocketmine\data\bedrock\block\upgrade;
use pocketmine\data\bedrock\LegacyToStringBidirectionalIdMap;
use pocketmine\data\bedrock\LegacyToStringIdMap;
use pocketmine\utils\SingletonTrait;
use Webmozart\PathUtil\Path;
final class LegacyBlockIdToStringIdMap extends LegacyToStringBidirectionalIdMap{
final class LegacyBlockIdToStringIdMap extends LegacyToStringIdMap{
use SingletonTrait;
public function __construct(){

View File

@ -52,6 +52,18 @@ final class LegacyBlockStateMapper{
return $this->fromStringIdMeta($stringId, $meta);
}
/**
* Adds a mapping of legacy block ID and meta to modern blockstate data. This may be needed for upgrading data from
* stored custom blocks from older versions of PocketMine-MP.
*/
public function addMapping(string $stringId, int $intId, int $meta, BlockStateData $stateData) : void{
if(isset($this->mappingTable[$stringId][$meta])){
throw new \InvalidArgumentException("A mapping for $stringId:$meta already exists");
}
$this->mappingTable[$stringId][$meta] = $stateData;
$this->legacyNumericIdMap->add($stringId, $intId);
}
public static function loadFromString(string $data, LegacyBlockIdToStringIdMap $idMap, BlockStateUpgrader $blockStateUpgrader) : self{
$mappingTable = [];

View File

@ -30,6 +30,7 @@ use pocketmine\block\utils\TreeType;
use pocketmine\block\VanillaBlocks as Blocks;
use pocketmine\data\bedrock\block\BlockStateDeserializeException;
use pocketmine\data\bedrock\block\BlockStateDeserializer;
use pocketmine\data\bedrock\block\convert\UnsupportedBlockStateException;
use pocketmine\data\bedrock\CompoundTypeIds;
use pocketmine\data\bedrock\DyeColorIdMap;
use pocketmine\data\bedrock\EntityLegacyIds;
@ -71,6 +72,8 @@ final class ItemDeserializer{
//TODO: this is rough duct tape; we need a better way to deal with this
try{
$block = $this->blockStateDeserializer->deserialize($blockData);
}catch(UnsupportedBlockStateException $e){
throw new UnsupportedItemTypeException($e->getMessage(), 0, $e);
}catch(BlockStateDeserializeException $e){
throw new ItemTypeDeserializeException("Failed to deserialize item data: " . $e->getMessage(), 0, $e);
}
@ -80,7 +83,7 @@ final class ItemDeserializer{
}
$id = $data->getName();
if(!isset($this->deserializers[$id])){
throw new ItemTypeDeserializeException("No deserializer found for ID $id");
throw new UnsupportedItemTypeException("No deserializer found for ID $id");
}
return ($this->deserializers[$id])($data);
@ -345,7 +348,7 @@ final class ItemDeserializer{
//TODO: minecraft:flower_banner_pattern
$this->map(Ids::FLOWER_POT, fn() => Blocks::FLOWER_POT()->asItem());
//TODO: minecraft:fox_spawn_egg
$this->map(Ids::FRAME, fn() => Blocks::ITEM_FRAME()->asItem());
$this->map(Ids::FRAME, fn() => Blocks::ITEM_FRAME()->setGlowing(false)->asItem());
//TODO: minecraft:frog_spawn_egg
//TODO: minecraft:ghast_spawn_egg
$this->map(Ids::GHAST_TEAR, fn() => Items::GHAST_TEAR());
@ -353,7 +356,7 @@ final class ItemDeserializer{
$this->map(Ids::GLISTERING_MELON_SLICE, fn() => Items::GLISTERING_MELON());
//TODO: minecraft:globe_banner_pattern
//TODO: minecraft:glow_berries
//TODO: minecraft:glow_frame
$this->map(Ids::GLOW_FRAME, fn() => Blocks::ITEM_FRAME()->setGlowing(true)->asItem());
$this->map(Ids::GLOW_INK_SAC, fn() => Items::GLOW_INK_SAC());
//TODO: minecraft:glow_squid_spawn_egg
//TODO: minecraft:glow_stick
@ -380,7 +383,7 @@ final class ItemDeserializer{
$this->map(Ids::GUNPOWDER, fn() => Items::GUNPOWDER());
$this->map(Ids::HEART_OF_THE_SEA, fn() => Items::HEART_OF_THE_SEA());
//TODO: minecraft:hoglin_spawn_egg
//TODO: minecraft:honey_bottle
$this->map(Ids::HONEY_BOTTLE, fn() => Items::HONEY_BOTTLE());
$this->map(Ids::HONEYCOMB, fn() => Items::HONEYCOMB());
$this->map(Ids::HOPPER, fn() => Blocks::HOPPER()->asItem());
//TODO: minecraft:hopper_minecart
@ -455,17 +458,17 @@ final class ItemDeserializer{
$this->map(Ids::NETHER_STAR, fn() => Items::NETHER_STAR());
$this->map(Ids::NETHER_WART, fn() => Blocks::NETHER_WART()->asItem());
$this->map(Ids::NETHERBRICK, fn() => Items::NETHER_BRICK());
//TODO: minecraft:netherite_axe
//TODO: minecraft:netherite_boots
//TODO: minecraft:netherite_chestplate
//TODO: minecraft:netherite_helmet
//TODO: minecraft:netherite_hoe
//TODO: minecraft:netherite_ingot
//TODO: minecraft:netherite_leggings
//TODO: minecraft:netherite_pickaxe
//TODO: minecraft:netherite_scrap
//TODO: minecraft:netherite_shovel
//TODO: minecraft:netherite_sword
$this->map(Ids::NETHERITE_AXE, fn() => Items::NETHERITE_AXE());
$this->map(Ids::NETHERITE_BOOTS, fn() => Items::NETHERITE_BOOTS());
$this->map(Ids::NETHERITE_CHESTPLATE, fn() => Items::NETHERITE_CHESTPLATE());
$this->map(Ids::NETHERITE_HELMET, fn() => Items::NETHERITE_HELMET());
$this->map(Ids::NETHERITE_HOE, fn() => Items::NETHERITE_HOE());
$this->map(Ids::NETHERITE_INGOT, fn() => Items::NETHERITE_INGOT());
$this->map(Ids::NETHERITE_LEGGINGS, fn() => Items::NETHERITE_LEGGINGS());
$this->map(Ids::NETHERITE_PICKAXE, fn() => Items::NETHERITE_PICKAXE());
$this->map(Ids::NETHERITE_SCRAP, fn() => Items::NETHERITE_SCRAP());
$this->map(Ids::NETHERITE_SHOVEL, fn() => Items::NETHERITE_SHOVEL());
$this->map(Ids::NETHERITE_SWORD, fn() => Items::NETHERITE_SWORD());
//TODO: minecraft:npc_spawn_egg
$this->map(Ids::OAK_BOAT, fn() => Items::OAK_BOAT());
$this->map(Ids::OAK_SIGN, fn() => Blocks::OAK_SIGN()->asItem());

View File

@ -25,6 +25,7 @@ namespace pocketmine\data\bedrock\item;
use pocketmine\block\Bed;
use pocketmine\block\Block;
use pocketmine\block\ItemFrame;
use pocketmine\block\Skull;
use pocketmine\block\utils\DyeColor;
use pocketmine\block\VanillaBlocks as Blocks;
@ -233,7 +234,7 @@ final class ItemSerializer{
$this->mapBlock(Blocks::FLOWER_POT(), self::id(Ids::FLOWER_POT));
$this->mapBlock(Blocks::HOPPER(), self::id(Ids::HOPPER));
$this->mapBlock(Blocks::IRON_DOOR(), self::id(Ids::IRON_DOOR));
$this->mapBlock(Blocks::ITEM_FRAME(), self::id(Ids::FRAME));
$this->mapBlock(Blocks::ITEM_FRAME(), fn(ItemFrame $block) => new Data($block->isGlowing() ? Ids::GLOW_FRAME : Ids::FRAME));
$this->mapBlock(Blocks::JUNGLE_DOOR(), self::id(Ids::JUNGLE_DOOR));
$this->mapBlock(Blocks::MANGROVE_DOOR(), self::id(Ids::MANGROVE_DOOR));
$this->mapBlock(Blocks::NETHER_WART(), self::id(Ids::NETHER_WART));
@ -405,6 +406,7 @@ final class ItemSerializer{
$this->map(Items::GUNPOWDER(), self::id(Ids::GUNPOWDER));
$this->map(Items::HEART_OF_THE_SEA(), self::id(Ids::HEART_OF_THE_SEA));
$this->map(Items::HONEYCOMB(), self::id(Ids::HONEYCOMB));
$this->map(Items::HONEY_BOTTLE(), self::id(Ids::HONEY_BOTTLE));
$this->map(Items::INK_SAC(), self::id(Ids::INK_SAC));
$this->map(Items::IRON_AXE(), self::id(Ids::IRON_AXE));
$this->map(Items::IRON_BOOTS(), self::id(Ids::IRON_BOOTS));
@ -434,6 +436,17 @@ final class ItemSerializer{
$this->map(Items::MINECART(), self::id(Ids::MINECART));
$this->map(Items::MUSHROOM_STEW(), self::id(Ids::MUSHROOM_STEW));
$this->map(Items::NAUTILUS_SHELL(), self::id(Ids::NAUTILUS_SHELL));
$this->map(Items::NETHERITE_AXE(), self::id(Ids::NETHERITE_AXE));
$this->map(Items::NETHERITE_BOOTS(), self::id(Ids::NETHERITE_BOOTS));
$this->map(Items::NETHERITE_CHESTPLATE(), self::id(Ids::NETHERITE_CHESTPLATE));
$this->map(Items::NETHERITE_HELMET(), self::id(Ids::NETHERITE_HELMET));
$this->map(Items::NETHERITE_HOE(), self::id(Ids::NETHERITE_HOE));
$this->map(Items::NETHERITE_INGOT(), self::id(Ids::NETHERITE_INGOT));
$this->map(Items::NETHERITE_LEGGINGS(), self::id(Ids::NETHERITE_LEGGINGS));
$this->map(Items::NETHERITE_PICKAXE(), self::id(Ids::NETHERITE_PICKAXE));
$this->map(Items::NETHERITE_SCRAP(), self::id(Ids::NETHERITE_SCRAP));
$this->map(Items::NETHERITE_SHOVEL(), self::id(Ids::NETHERITE_SHOVEL));
$this->map(Items::NETHERITE_SWORD(), self::id(Ids::NETHERITE_SWORD));
$this->map(Items::NETHER_BRICK(), self::id(Ids::NETHERBRICK));
$this->map(Items::NETHER_QUARTZ(), self::id(Ids::QUARTZ));
$this->map(Items::NETHER_STAR(), self::id(Ids::NETHER_STAR));

View File

@ -23,6 +23,6 @@ declare(strict_types=1);
namespace pocketmine\data\bedrock\item;
final class ItemTypeDeserializeException extends \RuntimeException{
class ItemTypeDeserializeException extends \RuntimeException{
}

View File

@ -0,0 +1,28 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\data\bedrock\item;
final class UnsupportedItemTypeException extends ItemTypeDeserializeException{
}

View File

@ -116,7 +116,7 @@ final class ItemDataUpgrader{
/**
* @throws SavedDataLoadingException
*/
private function upgradeItemTypeNbt(CompoundTag $tag) : SavedItemData{
private function upgradeItemTypeNbt(CompoundTag $tag) : ?SavedItemData{
if(($nameIdTag = $tag->getTag(SavedItemData::TAG_NAME)) instanceof StringTag){
//Bedrock 1.6+
@ -124,6 +124,11 @@ final class ItemDataUpgrader{
}elseif(($idTag = $tag->getTag(self::TAG_LEGACY_ID)) instanceof ShortTag){
//Bedrock <= 1.5, PM <= 1.12
if($idTag->getValue() === 0){
//0 is a special case for air, which is not a valid item ID
//this isn't supposed to be saved, but this appears in some places due to bugs in older versions
return null;
}
$rawNameId = $this->legacyIntToStringIdMap->legacyToString($idTag->getValue());
if($rawNameId === null){
throw new SavedDataLoadingException("Legacy item ID " . $idTag->getValue() . " doesn't map to any modern string ID");
@ -182,8 +187,12 @@ final class ItemDataUpgrader{
/**
* @throws SavedDataLoadingException
*/
public function upgradeItemStackNbt(CompoundTag $tag) : SavedItemStackData{
public function upgradeItemStackNbt(CompoundTag $tag) : ?SavedItemStackData{
$savedItemData = $this->upgradeItemTypeNbt($tag);
if($savedItemData === null){
//air - this isn't supposed to be saved, but older versions of PM saved it in some places
return null;
}
try{
//required
$count = Binary::unsignByte($tag->getByte(SavedItemStackData::TAG_COUNT));

View File

@ -23,11 +23,11 @@ declare(strict_types=1);
namespace pocketmine\data\bedrock\item\upgrade;
use pocketmine\data\bedrock\LegacyToStringBidirectionalIdMap;
use pocketmine\data\bedrock\LegacyToStringIdMap;
use pocketmine\utils\SingletonTrait;
use Webmozart\PathUtil\Path;
final class LegacyItemIdToStringIdMap extends LegacyToStringBidirectionalIdMap{
final class LegacyItemIdToStringIdMap extends LegacyToStringIdMap{
use SingletonTrait;
public function __construct(){

View File

@ -49,7 +49,7 @@ final class RuntimeDataReader{
}
public function readBoundedInt(int $bits, int $min, int $max) : int{
$result = $this->readInt($bits);
$result = $this->readInt($bits) + $min;
if($result < $min || $result > $max){
throw new InvalidSerializedRuntimeDataException("Value is outside the range $min - $max");
}

View File

@ -52,6 +52,15 @@ final class RuntimeDataWriter{
return $this;
}
/** @return $this */
public function writeBoundedInt(int $bits, int $min, int $max, int $value) : self{
if($value < $min || $value > $max){
throw new \InvalidArgumentException("Value $value is outside the range $min - $max");
}
$this->writeInt($bits, $value - $min);
return $this;
}
/** @return $this */
public function writeBool(bool $value) : self{
return $this->writeInt(1, $value ? 1 : 0);
@ -104,7 +113,7 @@ final class RuntimeDataWriter{
public function writeWallConnections(array $connections) : self{
//TODO: we can pack this into 7 bits instead of 8
foreach(Facing::HORIZONTAL as $facing){
$this->writeInt(2, match($connections[$facing] ?? null){
$this->writeBoundedInt(2, 0, 2, match($connections[$facing] ?? null){
null => 0,
WallConnectionType::SHORT() => 1,
WallConnectionType::TALL() => 2,

View File

@ -39,6 +39,16 @@ final class RuntimeEnumDeserializer{
};
}
public static function readCopperOxidation(RuntimeDataReader $r) : \pocketmine\block\utils\CopperOxidation{
return match($r->readInt(2)){
0 => \pocketmine\block\utils\CopperOxidation::EXPOSED(),
1 => \pocketmine\block\utils\CopperOxidation::NONE(),
2 => \pocketmine\block\utils\CopperOxidation::OXIDIZED(),
3 => \pocketmine\block\utils\CopperOxidation::WEATHERED(),
default => throw new InvalidSerializedRuntimeDataException("Invalid serialized value for CopperOxidation")
};
}
public static function readCoralType(RuntimeDataReader $r) : \pocketmine\block\utils\CoralType{
return match($r->readInt(3)){
0 => \pocketmine\block\utils\CoralType::BRAIN(),

View File

@ -39,6 +39,16 @@ final class RuntimeEnumSerializer{
});
}
public static function writeCopperOxidation(RuntimeDataWriter $w, \pocketmine\block\utils\CopperOxidation $value) : void{
$w->writeInt(2, match($value){
\pocketmine\block\utils\CopperOxidation::EXPOSED() => 0,
\pocketmine\block\utils\CopperOxidation::NONE() => 1,
\pocketmine\block\utils\CopperOxidation::OXIDIZED() => 2,
\pocketmine\block\utils\CopperOxidation::WEATHERED() => 3,
default => throw new \pocketmine\utils\AssumptionFailedError("All CopperOxidation cases should be covered")
});
}
public static function writeCoralType(RuntimeDataWriter $w, \pocketmine\block\utils\CoralType $value) : void{
$w->writeInt(3, match($value){
\pocketmine\block\utils\CoralType::BRAIN() => 0,

View File

@ -493,6 +493,9 @@ abstract class Entity{
}
public function attack(EntityDamageEvent $source) : void{
if($this->isFireProof() && ($source->getCause() === EntityDamageEvent::CAUSE_FIRE || $source->getCause() === EntityDamageEvent::CAUSE_FIRE_TICK)){
$source->cancel();
}
$source->call();
if($source->isCancelled()){
return;
@ -1430,6 +1433,7 @@ abstract class Entity{
$this->location->pitch,
$this->location->yaw,
$this->location->yaw, //TODO: head yaw
$this->location->yaw, //TODO: body yaw (wtf mojang?)
array_map(function(Attribute $attr) : NetworkAttribute{
return new NetworkAttribute($attr->getId(), $attr->getMinValue(), $attr->getMaxValue(), $attr->getValue(), $attr->getDefaultValue());
}, $this->attributeMap->getAll()),

View File

@ -48,7 +48,6 @@ use pocketmine\nbt\tag\StringTag;
use pocketmine\network\mcpe\convert\SkinAdapterSingleton;
use pocketmine\network\mcpe\convert\TypeConverter;
use pocketmine\network\mcpe\protocol\AddPlayerPacket;
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
use pocketmine\network\mcpe\protocol\PlayerListPacket;
use pocketmine\network\mcpe\protocol\PlayerSkinPacket;
use pocketmine\network\mcpe\protocol\types\DeviceOS;
@ -58,6 +57,7 @@ use pocketmine\network\mcpe\protocol\types\entity\StringMetadataProperty;
use pocketmine\network\mcpe\protocol\types\GameMode;
use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper;
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
use pocketmine\network\mcpe\protocol\UpdateAbilitiesPacket;
use pocketmine\player\Player;
use pocketmine\utils\Limits;
use pocketmine\world\sound\TotemUseSound;
@ -454,7 +454,6 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
$player->getNetworkSession()->sendDataPacket(AddPlayerPacket::create(
$this->getUniqueId(),
$this->getName(),
$this->getId(), //TODO: actor unique ID
$this->getId(),
"",
$this->location->asVector3(),
@ -465,7 +464,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
ItemStackWrapper::legacy(TypeConverter::getInstance()->coreItemStackToNet($this->getInventory()->getItemInHand())),
GameMode::SURVIVAL,
$this->getAllNetworkData(),
AdventureSettingsPacket::create(0, 0, 0, 0, 0, $this->getId()), //TODO
UpdateAbilitiesPacket::create(0, 0, $this->getId() /* TODO: this should be unique ID */, []),
[], //TODO: entity links
"", //device ID (we intentionally don't send this - secvuln)
DeviceOS::UNKNOWN //we intentionally don't send this (secvuln)

View File

@ -82,14 +82,11 @@ class EffectManager{
$index = spl_object_id($effectType);
if(isset($this->effects[$index])){
$effect = $this->effects[$index];
$hasExpired = $effect->hasExpired();
$ev = new EntityEffectRemoveEvent($this->entity, $effect);
$ev->call();
if($ev->isCancelled()){
if($hasExpired && !$ev->getEffect()->hasExpired()){ //altered duration of an expired effect to make it not get removed
foreach($this->effectAddHooks as $hook){
$hook($ev->getEffect(), true);
}
foreach($this->effectAddHooks as $hook){
$hook($ev->getEffect(), true);
}
return;
}

View File

@ -30,7 +30,7 @@ use pocketmine\event\entity\EntityDamageEvent;
class WitherEffect extends Effect{
public function canTick(EffectInstance $instance) : bool{
if(($interval = (50 >> $instance->getAmplifier())) > 0){
if(($interval = (40 >> $instance->getAmplifier())) > 0){
return ($instance->getDuration() % $interval) === 0;
}
return true;

View File

@ -200,6 +200,10 @@ class ItemEntity extends Entity{
return $this->item;
}
public function isFireProof() : bool{
return $this->item->isFireProof();
}
public function canCollideWith(Entity $entity) : bool{
return false;
}

View File

@ -306,5 +306,6 @@ abstract class Projectile extends Entity{
*/
protected function onHitBlock(Block $blockHit, RayTraceResult $hitResult) : void{
$this->blockHit = $blockHit->getPosition()->asVector3();
$blockHit->onProjectileHit($this, $hitResult);
}
}

View File

@ -68,6 +68,10 @@ class Armor extends Durable{
return 1;
}
public function isFireProof() : bool{
return $this->armorInfo->isFireProof();
}
/**
* Returns the dyed colour of this armour piece. This generally only applies to leather armour.
*/

View File

@ -27,7 +27,9 @@ class ArmorTypeInfo{
public function __construct(
private int $defensePoints,
private int $maxDurability,
private int $armorSlot
private int $armorSlot,
private int $toughness = 0,
private bool $fireProof = false
){}
public function getDefensePoints() : int{
@ -41,4 +43,12 @@ class ArmorTypeInfo{
public function getArmorSlot() : int{
return $this->armorSlot;
}
public function getToughness() : int{
return $this->toughness;
}
public function isFireProof() : bool{
return $this->fireProof;
}
}

54
src/item/HoneyBottle.php Normal file
View File

@ -0,0 +1,54 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\entity\effect\VanillaEffects;
use pocketmine\entity\Living;
final class HoneyBottle extends Food{
public function getMaxStackSize() : int{
return 16;
}
public function requiresHunger() : bool{
return false;
}
public function getFoodRestore() : int{
return 6;
}
public function getSaturationRestore() : float{
return 1.2;
}
public function getResidue() : Item{
return VanillaItems::GLASS_BOTTLE();
}
public function onConsume(Living $consumer) : void{
$consumer->getEffects()->remove(VanillaEffects::POISON());
}
}

View File

@ -91,8 +91,9 @@ class Item implements \JsonSerializable{
* Constructs a new Item type. This constructor should ONLY be used when constructing a new item TYPE to register
* into the index.
*
* NOTE: This should NOT BE USED for creating items to set into an inventory. Use {@link ItemFactory#get} for that
* NOTE: This should NOT BE USED for creating items to set into an inventory. Use VanillaItems for that
* purpose.
* @see VanillaItems
*/
public function __construct(
private ItemIdentifier $identifier,
@ -466,6 +467,13 @@ class Item implements \JsonSerializable{
return $item;
}
/**
* Returns whether this item can survive being dropped into lava, or fire.
*/
public function isFireProof() : bool{
return false;
}
/**
* Returns how many points of damage this item will deal to an entity when used as a weapon.
*/
@ -633,6 +641,9 @@ class Item implements \JsonSerializable{
*/
public static function nbtDeserialize(CompoundTag $tag) : Item{
$itemData = GlobalItemDataHandlers::getUpgrader()->upgradeItemStackNbt($tag);
if($itemData === null){
return VanillaItems::AIR();
}
try{
return GlobalItemDataHandlers::getDeserializer()->deserializeStack($itemData);

View File

@ -63,6 +63,10 @@ final class ItemBlock extends Item{
return $this->getBlock()->getFuelTime();
}
public function isFireProof() : bool{
return $this->getBlock()->isFireProofAsItem();
}
public function getMaxStackSize() : int{
return $this->getBlock()->getMaxStackSize();
}

View File

@ -1,442 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\block\BlockFactory;
use pocketmine\block\utils\RecordType;
use pocketmine\block\utils\TreeType;
use pocketmine\block\VanillaBlocks as Blocks;
use pocketmine\entity\Entity;
use pocketmine\entity\Location;
use pocketmine\entity\Squid;
use pocketmine\entity\Villager;
use pocketmine\entity\Zombie;
use pocketmine\inventory\ArmorInventory;
use pocketmine\item\ItemIdentifier as IID;
use pocketmine\item\ItemTypeIds as Ids;
use pocketmine\math\Vector3;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\SingletonTrait;
use pocketmine\world\World;
/**
* Manages deserializing item types from their legacy ID/metadata.
* This is primarily needed for loading inventories saved in the world (or playerdata storage).
*/
class ItemFactory{
use SingletonTrait;
/** @var Item[] */
private array $list = [];
public function __construct(){
$this->registerArmorItems();
$this->registerSpawnEggs();
$this->registerTierToolItems();
$this->register(new Apple(new IID(Ids::APPLE), "Apple"));
$this->register(new Arrow(new IID(Ids::ARROW), "Arrow"));
$this->register(new BakedPotato(new IID(Ids::BAKED_POTATO), "Baked Potato"));
$this->register(new Bamboo(new IID(Ids::BAMBOO), "Bamboo"), true);
$this->register(new Beetroot(new IID(Ids::BEETROOT), "Beetroot"));
$this->register(new BeetrootSeeds(new IID(Ids::BEETROOT_SEEDS), "Beetroot Seeds"));
$this->register(new BeetrootSoup(new IID(Ids::BEETROOT_SOUP), "Beetroot Soup"));
$this->register(new BlazeRod(new IID(Ids::BLAZE_ROD), "Blaze Rod"));
$this->register(new Book(new IID(Ids::BOOK), "Book"));
$this->register(new Bow(new IID(Ids::BOW), "Bow"));
$this->register(new Bowl(new IID(Ids::BOWL), "Bowl"));
$this->register(new Bread(new IID(Ids::BREAD), "Bread"));
$this->register(new Bucket(new IID(Ids::BUCKET), "Bucket"));
$this->register(new Carrot(new IID(Ids::CARROT), "Carrot"));
$this->register(new ChorusFruit(new IID(Ids::CHORUS_FRUIT), "Chorus Fruit"));
$this->register(new Clock(new IID(Ids::CLOCK), "Clock"));
$this->register(new Clownfish(new IID(Ids::CLOWNFISH), "Clownfish"));
$this->register(new Coal(new IID(Ids::COAL), "Coal"));
$this->register(new CoralFan(new IID(Ids::CORAL_FAN)));
$this->register(new Coal(new IID(Ids::CHARCOAL), "Charcoal"));
$this->register(new CocoaBeans(new IID(Ids::COCOA_BEANS), "Cocoa Beans"));
$this->register(new Compass(new IID(Ids::COMPASS), "Compass"));
$this->register(new CookedChicken(new IID(Ids::COOKED_CHICKEN), "Cooked Chicken"));
$this->register(new CookedFish(new IID(Ids::COOKED_FISH), "Cooked Fish"));
$this->register(new CookedMutton(new IID(Ids::COOKED_MUTTON), "Cooked Mutton"));
$this->register(new CookedPorkchop(new IID(Ids::COOKED_PORKCHOP), "Cooked Porkchop"));
$this->register(new CookedRabbit(new IID(Ids::COOKED_RABBIT), "Cooked Rabbit"));
$this->register(new CookedSalmon(new IID(Ids::COOKED_SALMON), "Cooked Salmon"));
$this->register(new Cookie(new IID(Ids::COOKIE), "Cookie"));
$this->register(new DriedKelp(new IID(Ids::DRIED_KELP), "Dried Kelp"));
$this->register(new Egg(new IID(Ids::EGG), "Egg"));
$this->register(new EnderPearl(new IID(Ids::ENDER_PEARL), "Ender Pearl"));
$this->register(new ExperienceBottle(new IID(Ids::EXPERIENCE_BOTTLE), "Bottle o' Enchanting"));
$this->register(new Fertilizer(new IID(Ids::BONE_MEAL), "Bone Meal"));
$this->register(new FishingRod(new IID(Ids::FISHING_ROD), "Fishing Rod"));
$this->register(new FlintSteel(new IID(Ids::FLINT_AND_STEEL), "Flint and Steel"));
$this->register(new GlassBottle(new IID(Ids::GLASS_BOTTLE), "Glass Bottle"));
$this->register(new GoldenApple(new IID(Ids::GOLDEN_APPLE), "Golden Apple"));
$this->register(new GoldenAppleEnchanted(new IID(Ids::ENCHANTED_GOLDEN_APPLE), "Enchanted Golden Apple"));
$this->register(new GoldenCarrot(new IID(Ids::GOLDEN_CARROT), "Golden Carrot"));
$this->register(new Item(new IID(Ids::AMETHYST_SHARD), "Amethyst Shard"));
$this->register(new Item(new IID(Ids::BLAZE_POWDER), "Blaze Powder"));
$this->register(new Item(new IID(Ids::BLEACH), "Bleach")); //EDU
$this->register(new Item(new IID(Ids::BONE), "Bone"));
$this->register(new Item(new IID(Ids::BRICK), "Brick"));
$this->register(new Item(new IID(Ids::POPPED_CHORUS_FRUIT), "Popped Chorus Fruit"));
$this->register(new Item(new IID(Ids::CLAY), "Clay"));
$this->register(new Item(new IID(Ids::CHEMICAL_SALT), "Salt"));
$this->register(new Item(new IID(Ids::CHEMICAL_SODIUM_OXIDE), "Sodium Oxide"));
$this->register(new Item(new IID(Ids::CHEMICAL_SODIUM_HYDROXIDE), "Sodium Hydroxide"));
$this->register(new Item(new IID(Ids::CHEMICAL_MAGNESIUM_NITRATE), "Magnesium Nitrate"));
$this->register(new Item(new IID(Ids::CHEMICAL_IRON_SULPHIDE), "Iron Sulphide"));
$this->register(new Item(new IID(Ids::CHEMICAL_LITHIUM_HYDRIDE), "Lithium Hydride"));
$this->register(new Item(new IID(Ids::CHEMICAL_SODIUM_HYDRIDE), "Sodium Hydride"));
$this->register(new Item(new IID(Ids::CHEMICAL_CALCIUM_BROMIDE), "Calcium Bromide"));
$this->register(new Item(new IID(Ids::CHEMICAL_MAGNESIUM_OXIDE), "Magnesium Oxide"));
$this->register(new Item(new IID(Ids::CHEMICAL_SODIUM_ACETATE), "Sodium Acetate"));
$this->register(new Item(new IID(Ids::CHEMICAL_LUMINOL), "Luminol"));
$this->register(new Item(new IID(Ids::CHEMICAL_CHARCOAL), "Charcoal")); //??? maybe bug
$this->register(new Item(new IID(Ids::CHEMICAL_SUGAR), "Sugar")); //??? maybe bug
$this->register(new Item(new IID(Ids::CHEMICAL_ALUMINIUM_OXIDE), "Aluminium Oxide"));
$this->register(new Item(new IID(Ids::CHEMICAL_BORON_TRIOXIDE), "Boron Trioxide"));
$this->register(new Item(new IID(Ids::CHEMICAL_SOAP), "Soap"));
$this->register(new Item(new IID(Ids::CHEMICAL_POLYETHYLENE), "Polyethylene"));
$this->register(new Item(new IID(Ids::CHEMICAL_RUBBISH), "Rubbish"));
$this->register(new Item(new IID(Ids::CHEMICAL_MAGNESIUM_SALTS), "Magnesium Salts"));
$this->register(new Item(new IID(Ids::CHEMICAL_SULPHATE), "Sulphate"));
$this->register(new Item(new IID(Ids::CHEMICAL_BARIUM_SULPHATE), "Barium Sulphate"));
$this->register(new Item(new IID(Ids::CHEMICAL_POTASSIUM_CHLORIDE), "Potassium Chloride"));
$this->register(new Item(new IID(Ids::CHEMICAL_MERCURIC_CHLORIDE), "Mercuric Chloride"));
$this->register(new Item(new IID(Ids::CHEMICAL_CERIUM_CHLORIDE), "Cerium Chloride"));
$this->register(new Item(new IID(Ids::CHEMICAL_TUNGSTEN_CHLORIDE), "Tungsten Chloride"));
$this->register(new Item(new IID(Ids::CHEMICAL_CALCIUM_CHLORIDE), "Calcium Chloride"));
$this->register(new Item(new IID(Ids::CHEMICAL_WATER), "Water")); //???
$this->register(new Item(new IID(Ids::CHEMICAL_GLUE), "Glue"));
$this->register(new Item(new IID(Ids::CHEMICAL_HYPOCHLORITE), "Hypochlorite"));
$this->register(new Item(new IID(Ids::CHEMICAL_CRUDE_OIL), "Crude Oil"));
$this->register(new Item(new IID(Ids::CHEMICAL_LATEX), "Latex"));
$this->register(new Item(new IID(Ids::CHEMICAL_POTASSIUM_IODIDE), "Potassium Iodide"));
$this->register(new Item(new IID(Ids::CHEMICAL_SODIUM_FLUORIDE), "Sodium Fluoride"));
$this->register(new Item(new IID(Ids::CHEMICAL_BENZENE), "Benzene"));
$this->register(new Item(new IID(Ids::CHEMICAL_INK), "Ink"));
$this->register(new Item(new IID(Ids::CHEMICAL_HYDROGEN_PEROXIDE), "Hydrogen Peroxide"));
$this->register(new Item(new IID(Ids::CHEMICAL_AMMONIA), "Ammonia"));
$this->register(new Item(new IID(Ids::CHEMICAL_SODIUM_HYPOCHLORITE), "Sodium Hypochlorite"));
$this->register(new Item(new IID(Ids::DIAMOND), "Diamond"));
$this->register(new Item(new IID(Ids::DISC_FRAGMENT_5), "Disc Fragment (5)"));
$this->register(new Item(new IID(Ids::DRAGON_BREATH), "Dragon's Breath"));
$this->register(new Item(new IID(Ids::GLOW_INK_SAC), "Glow Ink Sac"));
$this->register(new Item(new IID(Ids::INK_SAC), "Ink Sac"));
$this->register(new Item(new IID(Ids::LAPIS_LAZULI), "Lapis Lazuli"));
$this->register(new Item(new IID(Ids::ECHO_SHARD), "Echo Shard"));
$this->register(new Item(new IID(Ids::EMERALD), "Emerald"));
$this->register(new Item(new IID(Ids::FEATHER), "Feather"));
$this->register(new Item(new IID(Ids::FERMENTED_SPIDER_EYE), "Fermented Spider Eye"));
$this->register(new Item(new IID(Ids::FLINT), "Flint"));
$this->register(new Item(new IID(Ids::GHAST_TEAR), "Ghast Tear"));
$this->register(new Item(new IID(Ids::GLISTERING_MELON), "Glistering Melon"));
$this->register(new Item(new IID(Ids::GLOWSTONE_DUST), "Glowstone Dust"));
$this->register(new Item(new IID(Ids::GOLD_INGOT), "Gold Ingot"));
$this->register(new Item(new IID(Ids::GOLD_NUGGET), "Gold Nugget"));
$this->register(new Item(new IID(Ids::GUNPOWDER), "Gunpowder"));
$this->register(new Item(new IID(Ids::HEART_OF_THE_SEA), "Heart of the Sea"));
$this->register(new Item(new IID(Ids::HONEYCOMB), "Honeycomb"));
$this->register(new Item(new IID(Ids::IRON_INGOT), "Iron Ingot"));
$this->register(new Item(new IID(Ids::IRON_NUGGET), "Iron Nugget"));
$this->register(new Item(new IID(Ids::LEATHER), "Leather"));
$this->register(new Item(new IID(Ids::MAGMA_CREAM), "Magma Cream"));
$this->register(new Item(new IID(Ids::NAUTILUS_SHELL), "Nautilus Shell"));
$this->register(new Item(new IID(Ids::NETHER_BRICK), "Nether Brick"));
$this->register(new Item(new IID(Ids::NETHER_QUARTZ), "Nether Quartz"));
$this->register(new Item(new IID(Ids::NETHER_STAR), "Nether Star"));
$this->register(new Item(new IID(Ids::PAPER), "Paper"));
$this->register(new Item(new IID(Ids::PRISMARINE_CRYSTALS), "Prismarine Crystals"));
$this->register(new Item(new IID(Ids::PRISMARINE_SHARD), "Prismarine Shard"));
$this->register(new Item(new IID(Ids::RABBIT_FOOT), "Rabbit's Foot"));
$this->register(new Item(new IID(Ids::RABBIT_HIDE), "Rabbit Hide"));
$this->register(new Item(new IID(Ids::SHULKER_SHELL), "Shulker Shell"));
$this->register(new Item(new IID(Ids::SLIMEBALL), "Slimeball"));
$this->register(new Item(new IID(Ids::SUGAR), "Sugar"));
$this->register(new Item(new IID(Ids::SCUTE), "Scute"));
$this->register(new Item(new IID(Ids::WHEAT), "Wheat"));
$this->register(new Item(new IID(Ids::COPPER_INGOT), "Copper Ingot"));
$this->register(new Item(new IID(Ids::RAW_COPPER), "Raw Copper"));
$this->register(new Item(new IID(Ids::RAW_IRON), "Raw Iron"));
$this->register(new Item(new IID(Ids::RAW_GOLD), "Raw Gold"));
$this->register(new Item(new IID(Ids::PHANTOM_MEMBRANE), "Phantom Membrane"));
//the meta values for buckets are intentionally hardcoded because block IDs will change in the future
$this->register(new LiquidBucket(new IID(Ids::WATER_BUCKET), "Water Bucket", Blocks::WATER()));
$this->register(new LiquidBucket(new IID(Ids::LAVA_BUCKET), "Lava Bucket", Blocks::LAVA()));
$this->register(new Melon(new IID(Ids::MELON), "Melon"));
$this->register(new MelonSeeds(new IID(Ids::MELON_SEEDS), "Melon Seeds"));
$this->register(new MilkBucket(new IID(Ids::MILK_BUCKET), "Milk Bucket"));
$this->register(new Minecart(new IID(Ids::MINECART), "Minecart"));
$this->register(new MushroomStew(new IID(Ids::MUSHROOM_STEW), "Mushroom Stew"));
$this->register(new PaintingItem(new IID(Ids::PAINTING), "Painting"));
$this->register(new PoisonousPotato(new IID(Ids::POISONOUS_POTATO), "Poisonous Potato"));
$this->register(new Potato(new IID(Ids::POTATO), "Potato"));
$this->register(new Pufferfish(new IID(Ids::PUFFERFISH), "Pufferfish"));
$this->register(new PumpkinPie(new IID(Ids::PUMPKIN_PIE), "Pumpkin Pie"));
$this->register(new PumpkinSeeds(new IID(Ids::PUMPKIN_SEEDS), "Pumpkin Seeds"));
$this->register(new RabbitStew(new IID(Ids::RABBIT_STEW), "Rabbit Stew"));
$this->register(new RawBeef(new IID(Ids::RAW_BEEF), "Raw Beef"));
$this->register(new RawChicken(new IID(Ids::RAW_CHICKEN), "Raw Chicken"));
$this->register(new RawFish(new IID(Ids::RAW_FISH), "Raw Fish"));
$this->register(new RawMutton(new IID(Ids::RAW_MUTTON), "Raw Mutton"));
$this->register(new RawPorkchop(new IID(Ids::RAW_PORKCHOP), "Raw Porkchop"));
$this->register(new RawRabbit(new IID(Ids::RAW_RABBIT), "Raw Rabbit"));
$this->register(new RawSalmon(new IID(Ids::RAW_SALMON), "Raw Salmon"));
$this->register(new Record(new IID(Ids::RECORD_13), RecordType::DISK_13(), "Record 13"));
$this->register(new Record(new IID(Ids::RECORD_CAT), RecordType::DISK_CAT(), "Record Cat"));
$this->register(new Record(new IID(Ids::RECORD_BLOCKS), RecordType::DISK_BLOCKS(), "Record Blocks"));
$this->register(new Record(new IID(Ids::RECORD_CHIRP), RecordType::DISK_CHIRP(), "Record Chirp"));
$this->register(new Record(new IID(Ids::RECORD_FAR), RecordType::DISK_FAR(), "Record Far"));
$this->register(new Record(new IID(Ids::RECORD_MALL), RecordType::DISK_MALL(), "Record Mall"));
$this->register(new Record(new IID(Ids::RECORD_MELLOHI), RecordType::DISK_MELLOHI(), "Record Mellohi"));
$this->register(new Record(new IID(Ids::RECORD_STAL), RecordType::DISK_STAL(), "Record Stal"));
$this->register(new Record(new IID(Ids::RECORD_STRAD), RecordType::DISK_STRAD(), "Record Strad"));
$this->register(new Record(new IID(Ids::RECORD_WARD), RecordType::DISK_WARD(), "Record Ward"));
$this->register(new Record(new IID(Ids::RECORD_11), RecordType::DISK_11(), "Record 11"));
$this->register(new Record(new IID(Ids::RECORD_WAIT), RecordType::DISK_WAIT(), "Record Wait"));
$this->register(new Redstone(new IID(Ids::REDSTONE_DUST), "Redstone"));
$this->register(new RottenFlesh(new IID(Ids::ROTTEN_FLESH), "Rotten Flesh"));
$this->register(new Shears(new IID(Ids::SHEARS), "Shears"));
$this->register(new ItemBlockWallOrFloor(new IID(Ids::OAK_SIGN), Blocks::OAK_SIGN(), Blocks::OAK_WALL_SIGN()));
$this->register(new ItemBlockWallOrFloor(new IID(Ids::SPRUCE_SIGN), Blocks::SPRUCE_SIGN(), Blocks::SPRUCE_WALL_SIGN()));
$this->register(new ItemBlockWallOrFloor(new IID(Ids::BIRCH_SIGN), Blocks::BIRCH_SIGN(), Blocks::BIRCH_WALL_SIGN()));
$this->register(new ItemBlockWallOrFloor(new IID(Ids::JUNGLE_SIGN), Blocks::JUNGLE_SIGN(), Blocks::JUNGLE_WALL_SIGN()));
$this->register(new ItemBlockWallOrFloor(new IID(Ids::ACACIA_SIGN), Blocks::ACACIA_SIGN(), Blocks::ACACIA_WALL_SIGN()));
$this->register(new ItemBlockWallOrFloor(new IID(Ids::DARK_OAK_SIGN), Blocks::DARK_OAK_SIGN(), Blocks::DARK_OAK_WALL_SIGN()));
$this->register(new ItemBlockWallOrFloor(new IID(Ids::MANGROVE_SIGN), Blocks::MANGROVE_SIGN(), Blocks::MANGROVE_WALL_SIGN()));
$this->register(new ItemBlockWallOrFloor(new IID(Ids::CRIMSON_SIGN), Blocks::CRIMSON_SIGN(), Blocks::CRIMSON_WALL_SIGN()));
$this->register(new ItemBlockWallOrFloor(new IID(Ids::WARPED_SIGN), Blocks::WARPED_SIGN(), Blocks::WARPED_WALL_SIGN()));
$this->register(new Snowball(new IID(Ids::SNOWBALL), "Snowball"));
$this->register(new SpiderEye(new IID(Ids::SPIDER_EYE), "Spider Eye"));
$this->register(new Spyglass(new IID(Ids::SPYGLASS), "Spyglass"));
$this->register(new Steak(new IID(Ids::STEAK), "Steak"));
$this->register(new Stick(new IID(Ids::STICK), "Stick"));
$this->register(new StringItem(new IID(Ids::STRING), "String"));
$this->register(new SweetBerries(new IID(Ids::SWEET_BERRIES), "Sweet Berries"));
$this->register(new Totem(new IID(Ids::TOTEM), "Totem of Undying"));
$this->register(new WheatSeeds(new IID(Ids::WHEAT_SEEDS), "Wheat Seeds"));
$this->register(new WritableBook(new IID(Ids::WRITABLE_BOOK), "Book & Quill"));
$this->register(new WrittenBook(new IID(Ids::WRITTEN_BOOK), "Written Book"));
//TODO: add interface to dye-colour objects
$this->register(new Dye(new IID(Ids::DYE), "Dye"));
$this->register(new Banner(
new IID(Ids::BANNER),
Blocks::BANNER(),
Blocks::WALL_BANNER()
));
$this->register(new Potion(new IID(Ids::POTION), "Potion"));
$this->register(new SplashPotion(new IID(Ids::SPLASH_POTION), "Splash Potion"));
foreach(TreeType::getAll() as $type){
//TODO: tree type should be dynamic in the future, but we're staying static for now for the sake of consistency
$this->register(new Boat(new IID(match($type){
TreeType::OAK() => Ids::OAK_BOAT,
TreeType::SPRUCE() => Ids::SPRUCE_BOAT,
TreeType::BIRCH() => Ids::BIRCH_BOAT,
TreeType::JUNGLE() => Ids::JUNGLE_BOAT,
TreeType::ACACIA() => Ids::ACACIA_BOAT,
TreeType::DARK_OAK() => Ids::DARK_OAK_BOAT,
default => throw new AssumptionFailedError("Unhandled tree type " . $type->name())
}), $type->getDisplayName() . " Boat", $type));
}
//region --- auto-generated TODOs ---
//TODO: minecraft:armor_stand
//TODO: minecraft:balloon
//TODO: minecraft:banner_pattern
//TODO: minecraft:campfire
//TODO: minecraft:carrotOnAStick
//TODO: minecraft:chest_minecart
//TODO: minecraft:command_block_minecart
//TODO: minecraft:crossbow
//TODO: minecraft:elytra
//TODO: minecraft:emptyMap
//TODO: minecraft:enchanted_book
//TODO: minecraft:end_crystal
//TODO: minecraft:ender_eye
//TODO: minecraft:fireball
//TODO: minecraft:fireworks
//TODO: minecraft:fireworksCharge
//TODO: minecraft:glow_stick
//TODO: minecraft:hopper_minecart
//TODO: minecraft:horsearmordiamond
//TODO: minecraft:horsearmorgold
//TODO: minecraft:horsearmoriron
//TODO: minecraft:horsearmorleather
//TODO: minecraft:ice_bomb
//TODO: minecraft:kelp
//TODO: minecraft:lead
//TODO: minecraft:lingering_potion
//TODO: minecraft:map
//TODO: minecraft:medicine
//TODO: minecraft:name_tag
//TODO: minecraft:phantom_membrane
//TODO: minecraft:rapid_fertilizer
//TODO: minecraft:record_pigstep
//TODO: minecraft:saddle
//TODO: minecraft:shield
//TODO: minecraft:sparkler
//TODO: minecraft:spawn_egg
//TODO: minecraft:tnt_minecart
//TODO: minecraft:trident
//TODO: minecraft:turtle_helmet
//endregion
}
private function registerSpawnEggs() : void{
//TODO: the meta values should probably be hardcoded; they won't change, but the EntityLegacyIds might
$this->register(new class(new IID(Ids::ZOMBIE_SPAWN_EGG), "Zombie Spawn Egg") extends SpawnEgg{
protected function createEntity(World $world, Vector3 $pos, float $yaw, float $pitch) : Entity{
return new Zombie(Location::fromObject($pos, $world, $yaw, $pitch));
}
});
$this->register(new class(new IID(Ids::SQUID_SPAWN_EGG), "Squid Spawn Egg") extends SpawnEgg{
public function createEntity(World $world, Vector3 $pos, float $yaw, float $pitch) : Entity{
return new Squid(Location::fromObject($pos, $world, $yaw, $pitch));
}
});
$this->register(new class(new IID(Ids::VILLAGER_SPAWN_EGG), "Villager Spawn Egg") extends SpawnEgg{
public function createEntity(World $world, Vector3 $pos, float $yaw, float $pitch) : Entity{
return new Villager(Location::fromObject($pos, $world, $yaw, $pitch));
}
});
}
private function registerTierToolItems() : void{
$this->register(new Axe(new IID(Ids::DIAMOND_AXE), "Diamond Axe", ToolTier::DIAMOND()));
$this->register(new Axe(new IID(Ids::GOLDEN_AXE), "Golden Axe", ToolTier::GOLD()));
$this->register(new Axe(new IID(Ids::IRON_AXE), "Iron Axe", ToolTier::IRON()));
$this->register(new Axe(new IID(Ids::STONE_AXE), "Stone Axe", ToolTier::STONE()));
$this->register(new Axe(new IID(Ids::WOODEN_AXE), "Wooden Axe", ToolTier::WOOD()));
$this->register(new Hoe(new IID(Ids::DIAMOND_HOE), "Diamond Hoe", ToolTier::DIAMOND()));
$this->register(new Hoe(new IID(Ids::GOLDEN_HOE), "Golden Hoe", ToolTier::GOLD()));
$this->register(new Hoe(new IID(Ids::IRON_HOE), "Iron Hoe", ToolTier::IRON()));
$this->register(new Hoe(new IID(Ids::STONE_HOE), "Stone Hoe", ToolTier::STONE()));
$this->register(new Hoe(new IID(Ids::WOODEN_HOE), "Wooden Hoe", ToolTier::WOOD()));
$this->register(new Pickaxe(new IID(Ids::DIAMOND_PICKAXE), "Diamond Pickaxe", ToolTier::DIAMOND()));
$this->register(new Pickaxe(new IID(Ids::GOLDEN_PICKAXE), "Golden Pickaxe", ToolTier::GOLD()));
$this->register(new Pickaxe(new IID(Ids::IRON_PICKAXE), "Iron Pickaxe", ToolTier::IRON()));
$this->register(new Pickaxe(new IID(Ids::STONE_PICKAXE), "Stone Pickaxe", ToolTier::STONE()));
$this->register(new Pickaxe(new IID(Ids::WOODEN_PICKAXE), "Wooden Pickaxe", ToolTier::WOOD()));
$this->register(new Shovel(new IID(Ids::DIAMOND_SHOVEL), "Diamond Shovel", ToolTier::DIAMOND()));
$this->register(new Shovel(new IID(Ids::GOLDEN_SHOVEL), "Golden Shovel", ToolTier::GOLD()));
$this->register(new Shovel(new IID(Ids::IRON_SHOVEL), "Iron Shovel", ToolTier::IRON()));
$this->register(new Shovel(new IID(Ids::STONE_SHOVEL), "Stone Shovel", ToolTier::STONE()));
$this->register(new Shovel(new IID(Ids::WOODEN_SHOVEL), "Wooden Shovel", ToolTier::WOOD()));
$this->register(new Sword(new IID(Ids::DIAMOND_SWORD), "Diamond Sword", ToolTier::DIAMOND()));
$this->register(new Sword(new IID(Ids::GOLDEN_SWORD), "Golden Sword", ToolTier::GOLD()));
$this->register(new Sword(new IID(Ids::IRON_SWORD), "Iron Sword", ToolTier::IRON()));
$this->register(new Sword(new IID(Ids::STONE_SWORD), "Stone Sword", ToolTier::STONE()));
$this->register(new Sword(new IID(Ids::WOODEN_SWORD), "Wooden Sword", ToolTier::WOOD()));
}
private function registerArmorItems() : void{
$this->register(new Armor(new IID(Ids::CHAINMAIL_BOOTS), "Chainmail Boots", new ArmorTypeInfo(1, 196, ArmorInventory::SLOT_FEET)));
$this->register(new Armor(new IID(Ids::DIAMOND_BOOTS), "Diamond Boots", new ArmorTypeInfo(3, 430, ArmorInventory::SLOT_FEET)));
$this->register(new Armor(new IID(Ids::GOLDEN_BOOTS), "Golden Boots", new ArmorTypeInfo(1, 92, ArmorInventory::SLOT_FEET)));
$this->register(new Armor(new IID(Ids::IRON_BOOTS), "Iron Boots", new ArmorTypeInfo(2, 196, ArmorInventory::SLOT_FEET)));
$this->register(new Armor(new IID(Ids::LEATHER_BOOTS), "Leather Boots", new ArmorTypeInfo(1, 66, ArmorInventory::SLOT_FEET)));
$this->register(new Armor(new IID(Ids::CHAINMAIL_CHESTPLATE), "Chainmail Chestplate", new ArmorTypeInfo(5, 241, ArmorInventory::SLOT_CHEST)));
$this->register(new Armor(new IID(Ids::DIAMOND_CHESTPLATE), "Diamond Chestplate", new ArmorTypeInfo(8, 529, ArmorInventory::SLOT_CHEST)));
$this->register(new Armor(new IID(Ids::GOLDEN_CHESTPLATE), "Golden Chestplate", new ArmorTypeInfo(5, 113, ArmorInventory::SLOT_CHEST)));
$this->register(new Armor(new IID(Ids::IRON_CHESTPLATE), "Iron Chestplate", new ArmorTypeInfo(6, 241, ArmorInventory::SLOT_CHEST)));
$this->register(new Armor(new IID(Ids::LEATHER_TUNIC), "Leather Tunic", new ArmorTypeInfo(3, 81, ArmorInventory::SLOT_CHEST)));
$this->register(new Armor(new IID(Ids::CHAINMAIL_HELMET), "Chainmail Helmet", new ArmorTypeInfo(2, 166, ArmorInventory::SLOT_HEAD)));
$this->register(new Armor(new IID(Ids::DIAMOND_HELMET), "Diamond Helmet", new ArmorTypeInfo(3, 364, ArmorInventory::SLOT_HEAD)));
$this->register(new Armor(new IID(Ids::GOLDEN_HELMET), "Golden Helmet", new ArmorTypeInfo(2, 78, ArmorInventory::SLOT_HEAD)));
$this->register(new Armor(new IID(Ids::IRON_HELMET), "Iron Helmet", new ArmorTypeInfo(2, 166, ArmorInventory::SLOT_HEAD)));
$this->register(new Armor(new IID(Ids::LEATHER_CAP), "Leather Cap", new ArmorTypeInfo(1, 56, ArmorInventory::SLOT_HEAD)));
$this->register(new Armor(new IID(Ids::CHAINMAIL_LEGGINGS), "Chainmail Leggings", new ArmorTypeInfo(4, 226, ArmorInventory::SLOT_LEGS)));
$this->register(new Armor(new IID(Ids::DIAMOND_LEGGINGS), "Diamond Leggings", new ArmorTypeInfo(6, 496, ArmorInventory::SLOT_LEGS)));
$this->register(new Armor(new IID(Ids::GOLDEN_LEGGINGS), "Golden Leggings", new ArmorTypeInfo(3, 106, ArmorInventory::SLOT_LEGS)));
$this->register(new Armor(new IID(Ids::IRON_LEGGINGS), "Iron Leggings", new ArmorTypeInfo(5, 226, ArmorInventory::SLOT_LEGS)));
$this->register(new Armor(new IID(Ids::LEATHER_PANTS), "Leather Pants", new ArmorTypeInfo(2, 76, ArmorInventory::SLOT_LEGS)));
}
/**
* Maps an item type to its corresponding ID. This is necessary to ensure that the item is correctly loaded when
* reading data from disk storage.
*
* NOTE: If you are registering a new item type, you will need to add it to the creative inventory yourself - it
* will not automatically appear there.
*
* @throws \RuntimeException if something attempted to override an already-registered item without specifying the
* $override parameter.
*/
public function register(Item $item, bool $override = false) : void{
$id = $item->getTypeId();
if(!$override && $this->isRegistered($id)){
throw new \RuntimeException("Trying to overwrite an already registered item");
}
$this->list[$id] = clone $item;
}
private static function itemToBlockId(int $id) : int{
if($id > 0){
throw new \InvalidArgumentException("ID $id is not a block ID");
}
return -$id;
}
/**
* @internal
*/
public function fromTypeId(int $typeId) : Item{
if(isset($this->list[$typeId])){
return clone $this->list[$typeId];
}
if($typeId <= 0){
return BlockFactory::getInstance()->fromTypeId(self::itemToBlockId($typeId))->asItem();
}
throw new \InvalidArgumentException("No item with type ID $typeId is registered");
}
/**
* Returns whether the specified item ID is already registered in the item factory.
*/
public function isRegistered(int $id) : bool{
if($id <= 0){
return BlockFactory::getInstance()->isRegistered(self::itemToBlockId($id));
}
return isset($this->list[$id]);
}
/**
* @return Item[]
*/
public function getAllKnownTypes() : array{
return $this->list;
}
}

View File

@ -293,6 +293,7 @@ final class ItemTypeIds{
public const RAW_IRON = 20254;
public const RAW_GOLD = 20255;
public const SPYGLASS = 20256;
public const NETHERITE_SCRAP = 20257;
public const FIRST_UNUSED_ITEM_ID = 20239;
public const FIRST_UNUSED_ITEM_ID = 20258;
}

View File

@ -25,6 +25,7 @@ namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\block\Light;
use pocketmine\block\utils\CopperOxidation;
use pocketmine\block\utils\CoralType;
use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\SkullType;
@ -50,6 +51,7 @@ final class StringToItemParser extends StringToTParser{
//wall and floor banner are the same item
$result->registerBlock($prefix("banner"), fn() => Blocks::BANNER()->setColor($color));
$result->registerBlock($prefix("bed"), fn() => Blocks::BED()->setColor($color));
$result->registerBlock($prefix("candle"), fn() => Blocks::DYED_CANDLE()->setColor($color));
$result->registerBlock($prefix("carpet"), fn() => Blocks::CARPET()->setColor($color));
$result->registerBlock($prefix("concrete"), fn() => Blocks::CONCRETE()->setColor($color));
$result->registerBlock($prefix("concrete_powder"), fn() => Blocks::CONCRETE_POWDER()->setColor($color));
@ -77,6 +79,18 @@ final class StringToItemParser extends StringToTParser{
$result->registerBlock("light_block_$i", fn() => Blocks::LIGHT()->setLightLevel($i));
}
foreach(CopperOxidation::getAll() as $oxidation){
$oxPrefix = $oxidation->equals(CopperOxidation::NONE()) ? "" : $oxidation->name() . "_";
foreach(["" => false, "waxed_" => true] as $waxedPrefix => $waxed){
$prefix = $waxedPrefix . $oxPrefix;
$result->registerBlock($prefix . "copper_block", fn() => Blocks::COPPER()->setOxidation($oxidation)->setWaxed($waxed));
$result->registerBlock($prefix . "cut_copper_block", fn() => Blocks::CUT_COPPER()->setOxidation($oxidation)->setWaxed($waxed));
$result->registerBlock($prefix . "cut_copper_stairs", fn() => Blocks::CUT_COPPER_STAIRS()->setOxidation($oxidation)->setWaxed($waxed));
$result->registerBlock($prefix . "cut_copper_slab", fn() => Blocks::CUT_COPPER_SLAB()->setOxidation($oxidation)->setWaxed($waxed));
}
}
$result->registerBlock("acacia_button", fn() => Blocks::ACACIA_BUTTON());
$result->registerBlock("acacia_door", fn() => Blocks::ACACIA_DOOR());
$result->registerBlock("acacia_door_block", fn() => Blocks::ACACIA_DOOR());
@ -168,6 +182,7 @@ final class StringToItemParser extends StringToTParser{
$result->registerBlock("cake", fn() => Blocks::CAKE());
$result->registerBlock("cake_block", fn() => Blocks::CAKE());
$result->registerBlock("calcite", fn() => Blocks::CALCITE());
$result->registerBlock("candle", fn() => Blocks::CANDLE());
$result->registerBlock("carpet", fn() => Blocks::CARPET());
$result->registerBlock("carrot_block", fn() => Blocks::CARROTS());
$result->registerBlock("carrots", fn() => Blocks::CARROTS());
@ -239,6 +254,7 @@ final class StringToItemParser extends StringToTParser{
$result->registerBlock("crimson_stairs", fn() => Blocks::CRIMSON_STAIRS());
$result->registerBlock("crimson_stem", fn() => Blocks::CRIMSON_STEM()->setStripped(false));
$result->registerBlock("crimson_trapdoor", fn() => Blocks::CRIMSON_TRAPDOOR());
$result->registerBlock("crying_obsidian", fn() => Blocks::CRYING_OBSIDIAN());
$result->registerBlock("cut_red_sandstone", fn() => Blocks::CUT_RED_SANDSTONE());
$result->registerBlock("cut_red_sandstone_slab", fn() => Blocks::CUT_RED_SANDSTONE_SLAB());
$result->registerBlock("cut_sandstone", fn() => Blocks::CUT_SANDSTONE());
@ -589,14 +605,17 @@ final class StringToItemParser extends StringToTParser{
$result->registerBlock("flower_pot_block", fn() => Blocks::FLOWER_POT());
$result->registerBlock("flowing_lava", fn() => Blocks::LAVA());
$result->registerBlock("flowing_water", fn() => Blocks::WATER());
$result->registerBlock("frame", fn() => Blocks::ITEM_FRAME());
$result->registerBlock("frame_block", fn() => Blocks::ITEM_FRAME());
$result->registerBlock("frame", fn() => Blocks::ITEM_FRAME()->setGlowing(false));
$result->registerBlock("frame_block", fn() => Blocks::ITEM_FRAME()->setGlowing(false));
$result->registerBlock("frosted_ice", fn() => Blocks::FROSTED_ICE());
$result->registerBlock("furnace", fn() => Blocks::FURNACE());
$result->registerBlock("gilded_blackstone", fn() => Blocks::GILDED_BLACKSTONE());
$result->registerBlock("glass", fn() => Blocks::GLASS());
$result->registerBlock("glass_pane", fn() => Blocks::GLASS_PANE());
$result->registerBlock("glass_panel", fn() => Blocks::GLASS_PANE());
$result->registerBlock("glazed_terracotta", fn() => Blocks::GLAZED_TERRACOTTA());
$result->registerBlock("glow_frame", fn() => Blocks::ITEM_FRAME()->setGlowing(true));
$result->registerBlock("glow_item_frame", fn() => Blocks::ITEM_FRAME()->setGlowing(true));
$result->registerBlock("glowing_obsidian", fn() => Blocks::GLOWING_OBSIDIAN());
$result->registerBlock("glowing_redstone_ore", fn() => Blocks::REDSTONE_ORE()->setLit(true));
$result->registerBlock("glowingobsidian", fn() => Blocks::GLOWING_OBSIDIAN());
@ -615,6 +634,7 @@ final class StringToItemParser extends StringToTParser{
$result->registerBlock("grass_path", fn() => Blocks::GRASS_PATH());
$result->registerBlock("gravel", fn() => Blocks::GRAVEL());
$result->registerBlock("green_torch", fn() => Blocks::GREEN_TORCH());
$result->registerBlock("hanging_roots", fn() => Blocks::HANGING_ROOTS());
$result->registerBlock("hard_glass", fn() => Blocks::HARDENED_GLASS());
$result->registerBlock("hard_glass_pane", fn() => Blocks::HARDENED_GLASS_PANE());
$result->registerBlock("hard_stained_glass", fn() => Blocks::STAINED_HARDENED_GLASS());
@ -651,8 +671,8 @@ final class StringToItemParser extends StringToTParser{
$result->registerBlock("iron_ore", fn() => Blocks::IRON_ORE());
$result->registerBlock("iron_pressure_plate", fn() => Blocks::WEIGHTED_PRESSURE_PLATE_HEAVY());
$result->registerBlock("iron_trapdoor", fn() => Blocks::IRON_TRAPDOOR());
$result->registerBlock("item_frame", fn() => Blocks::ITEM_FRAME());
$result->registerBlock("item_frame_block", fn() => Blocks::ITEM_FRAME());
$result->registerBlock("item_frame", fn() => Blocks::ITEM_FRAME()->setGlowing(false));
$result->registerBlock("item_frame_block", fn() => Blocks::ITEM_FRAME()->setGlowing(false));
$result->registerBlock("jack_o_lantern", fn() => Blocks::LIT_PUMPKIN());
$result->registerBlock("jukebox", fn() => Blocks::JUKEBOX());
$result->registerBlock("jungle_button", fn() => Blocks::JUNGLE_BUTTON());
@ -693,6 +713,7 @@ final class StringToItemParser extends StringToTParser{
$result->registerBlock("light", fn() => Blocks::LIGHT());
$result->registerBlock("light_block", fn() => Blocks::LIGHT());
$result->registerBlock("light_weighted_pressure_plate", fn() => Blocks::WEIGHTED_PRESSURE_PLATE_LIGHT());
$result->registerBlock("lightning_rod", fn() => Blocks::LIGHTNING_ROD());
$result->registerBlock("lilac", fn() => Blocks::LILAC());
$result->registerBlock("lily_of_the_valley", fn() => Blocks::LILY_OF_THE_VALLEY());
$result->registerBlock("lily_pad", fn() => Blocks::LILY_PAD());
@ -759,6 +780,7 @@ final class StringToItemParser extends StringToTParser{
$result->registerBlock("nether_wart", fn() => Blocks::NETHER_WART());
$result->registerBlock("nether_wart_block", fn() => Blocks::NETHER_WART_BLOCK());
$result->registerBlock("nether_wart_plant", fn() => Blocks::NETHER_WART());
$result->registerBlock("netherite_block", fn() => Blocks::NETHERITE());
$result->registerBlock("netherrack", fn() => Blocks::NETHERRACK());
$result->registerBlock("netherreactor", fn() => Blocks::NETHER_REACTOR_CORE());
$result->registerBlock("normal_stone_stairs", fn() => Blocks::STONE_STAIRS());
@ -995,6 +1017,7 @@ final class StringToItemParser extends StringToTParser{
$result->registerBlock("tall_grass", fn() => Blocks::TALL_GRASS());
$result->registerBlock("tallgrass", fn() => Blocks::FERN());
$result->registerBlock("terracotta", fn() => Blocks::STAINED_CLAY());
$result->registerBlock("tinted_glass", fn() => Blocks::TINTED_GLASS());
$result->registerBlock("tnt", fn() => Blocks::TNT());
$result->registerBlock("torch", fn() => Blocks::TORCH());
$result->registerBlock("trapdoor", fn() => Blocks::OAK_TRAPDOOR());
@ -1030,6 +1053,7 @@ final class StringToItemParser extends StringToTParser{
$result->registerBlock("warped_stairs", fn() => Blocks::WARPED_STAIRS());
$result->registerBlock("warped_stem", fn() => Blocks::WARPED_STEM()->setStripped(false));
$result->registerBlock("warped_trapdoor", fn() => Blocks::WARPED_TRAPDOOR());
$result->registerBlock("warped_wart_block", fn() => Blocks::WARPED_WART_BLOCK());
$result->registerBlock("water", fn() => Blocks::WATER());
$result->registerBlock("water_lily", fn() => Blocks::LILY_PAD());
$result->registerBlock("waterlily", fn() => Blocks::LILY_PAD());
@ -1038,6 +1062,7 @@ final class StringToItemParser extends StringToTParser{
$result->registerBlock("weighted_pressure_plate_light", fn() => Blocks::WEIGHTED_PRESSURE_PLATE_LIGHT());
$result->registerBlock("wheat_block", fn() => Blocks::WHEAT());
$result->registerBlock("white_tulip", fn() => Blocks::WHITE_TULIP());
$result->registerBlock("wither_rose", fn() => Blocks::WITHER_ROSE());
$result->registerBlock("wither_skeleton_skull", fn() => Blocks::MOB_HEAD()->setSkullType(SkullType::WITHER_SKELETON()));
$result->registerBlock("wood", fn() => Blocks::OAK_LOG()->setStripped(false));
$result->registerBlock("wood2", fn() => Blocks::ACACIA_LOG()->setStripped(false));
@ -1225,6 +1250,7 @@ final class StringToItemParser extends StringToTParser{
$result->register("healing_potion", fn() => Items::POTION()->setType(PotionType::HEALING()));
$result->register("healing_splash_potion", fn() => Items::SPLASH_POTION()->setType(PotionType::HEALING()));
$result->register("heart_of_the_sea", fn() => Items::HEART_OF_THE_SEA());
$result->register("honey_bottle", fn() => Items::HONEY_BOTTLE());
$result->register("honeycomb", fn() => Items::HONEYCOMB());
$result->register("ink_sac", fn() => Items::INK_SAC());
$result->register("invisibility_potion", fn() => Items::POTION()->setType(PotionType::INVISIBILITY()));
@ -1300,6 +1326,17 @@ final class StringToItemParser extends StringToTParser{
$result->register("nether_quartz", fn() => Items::NETHER_QUARTZ());
$result->register("nether_star", fn() => Items::NETHER_STAR());
$result->register("netherbrick", fn() => Items::NETHER_BRICK());
$result->register("netherite_axe", fn() => Items::NETHERITE_AXE());
$result->register("netherite_boots", fn() => Items::NETHERITE_BOOTS());
$result->register("netherite_chestplate", fn() => Items::NETHERITE_CHESTPLATE());
$result->register("netherite_helmet", fn() => Items::NETHERITE_HELMET());
$result->register("netherite_hoe", fn() => Items::NETHERITE_HOE());
$result->register("netherite_ingot", fn() => Items::NETHERITE_INGOT());
$result->register("netherite_leggings", fn() => Items::NETHERITE_LEGGINGS());
$result->register("netherite_pickaxe", fn() => Items::NETHERITE_PICKAXE());
$result->register("netherite_scrap", fn() => Items::NETHERITE_SCRAP());
$result->register("netherite_shovel", fn() => Items::NETHERITE_SHOVEL());
$result->register("netherite_sword", fn() => Items::NETHERITE_SWORD());
$result->register("netherstar", fn() => Items::NETHER_STAR());
$result->register("night_vision_potion", fn() => Items::POTION()->setType(PotionType::NIGHT_VISION()));
$result->register("night_vision_splash_potion", fn() => Items::SPLASH_POTION()->setType(PotionType::NIGHT_VISION()));

View File

@ -50,4 +50,8 @@ abstract class TieredTool extends Tool{
return 0;
}
public function isFireProof() : bool{
return $this->tier->equals(ToolTier::NETHERITE());
}
}

View File

@ -34,6 +34,7 @@ use pocketmine\utils\EnumTrait;
* @method static ToolTier DIAMOND()
* @method static ToolTier GOLD()
* @method static ToolTier IRON()
* @method static ToolTier NETHERITE()
* @method static ToolTier STONE()
* @method static ToolTier WOOD()
*/
@ -48,7 +49,8 @@ final class ToolTier{
new self("gold", 2, 33, 5, 12),
new self("stone", 3, 132, 6, 4),
new self("iron", 4, 251, 7, 6),
new self("diamond", 5, 1562, 8, 8)
new self("diamond", 5, 1562, 8, 8),
new self("netherite", 6, 2032, 9, 9)
);
}

View File

@ -23,9 +23,22 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\block\utils\RecordType;
use pocketmine\block\utils\TreeType;
use pocketmine\block\VanillaBlocks;
use pocketmine\block\VanillaBlocks as Blocks;
use pocketmine\entity\Entity;
use pocketmine\entity\Location;
use pocketmine\entity\Squid;
use pocketmine\entity\Villager;
use pocketmine\entity\Zombie;
use pocketmine\inventory\ArmorInventory;
use pocketmine\item\ItemIdentifier as IID;
use pocketmine\item\ItemTypeIds as Ids;
use pocketmine\math\Vector3;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\CloningRegistryTrait;
use pocketmine\world\World;
/**
* This doc-block is generated automatically, do not modify it manually.
@ -167,6 +180,7 @@ use pocketmine\utils\CloningRegistryTrait;
* @method static Item GUNPOWDER()
* @method static Item HEART_OF_THE_SEA()
* @method static Item HONEYCOMB()
* @method static HoneyBottle HONEY_BOTTLE()
* @method static Item INK_SAC()
* @method static Axe IRON_AXE()
* @method static Armor IRON_BOOTS()
@ -196,6 +210,17 @@ use pocketmine\utils\CloningRegistryTrait;
* @method static Minecart MINECART()
* @method static MushroomStew MUSHROOM_STEW()
* @method static Item NAUTILUS_SHELL()
* @method static Axe NETHERITE_AXE()
* @method static Armor NETHERITE_BOOTS()
* @method static Armor NETHERITE_CHESTPLATE()
* @method static Armor NETHERITE_HELMET()
* @method static Hoe NETHERITE_HOE()
* @method static Item NETHERITE_INGOT()
* @method static Armor NETHERITE_LEGGINGS()
* @method static Pickaxe NETHERITE_PICKAXE()
* @method static Item NETHERITE_SCRAP()
* @method static Shovel NETHERITE_SHOVEL()
* @method static Sword NETHERITE_SWORD()
* @method static Item NETHER_BRICK()
* @method static Item NETHER_QUARTZ()
* @method static Item NETHER_STAR()
@ -298,249 +323,301 @@ final class VanillaItems{
}
protected static function setup() : void{
$factory = ItemFactory::getInstance();
self::registerArmorItems();
self::registerSpawnEggs();
self::registerTierToolItems();
self::register("air", VanillaBlocks::AIR()->asItem()->setCount(0));
self::register("acacia_boat", $factory->fromTypeId(Ids::ACACIA_BOAT));
self::register("acacia_sign", $factory->fromTypeId(Ids::ACACIA_SIGN));
self::register("amethyst_shard", $factory->fromTypeId(Ids::AMETHYST_SHARD));
self::register("apple", $factory->fromTypeId(Ids::APPLE));
self::register("arrow", $factory->fromTypeId(Ids::ARROW));
self::register("baked_potato", $factory->fromTypeId(Ids::BAKED_POTATO));
self::register("bamboo", $factory->fromTypeId(Ids::BAMBOO));
self::register("banner", $factory->fromTypeId(Ids::BANNER));
self::register("beetroot", $factory->fromTypeId(Ids::BEETROOT));
self::register("beetroot_seeds", $factory->fromTypeId(Ids::BEETROOT_SEEDS));
self::register("beetroot_soup", $factory->fromTypeId(Ids::BEETROOT_SOUP));
self::register("birch_boat", $factory->fromTypeId(Ids::BIRCH_BOAT));
self::register("birch_sign", $factory->fromTypeId(Ids::BIRCH_SIGN));
self::register("blaze_powder", $factory->fromTypeId(Ids::BLAZE_POWDER));
self::register("blaze_rod", $factory->fromTypeId(Ids::BLAZE_ROD));
self::register("bleach", $factory->fromTypeId(Ids::BLEACH));
self::register("bone", $factory->fromTypeId(Ids::BONE));
self::register("bone_meal", $factory->fromTypeId(Ids::BONE_MEAL));
self::register("book", $factory->fromTypeId(Ids::BOOK));
self::register("bow", $factory->fromTypeId(Ids::BOW));
self::register("bowl", $factory->fromTypeId(Ids::BOWL));
self::register("bread", $factory->fromTypeId(Ids::BREAD));
self::register("brick", $factory->fromTypeId(Ids::BRICK));
self::register("bucket", $factory->fromTypeId(Ids::BUCKET));
self::register("carrot", $factory->fromTypeId(Ids::CARROT));
self::register("chainmail_boots", $factory->fromTypeId(Ids::CHAINMAIL_BOOTS));
self::register("chainmail_chestplate", $factory->fromTypeId(Ids::CHAINMAIL_CHESTPLATE));
self::register("chainmail_helmet", $factory->fromTypeId(Ids::CHAINMAIL_HELMET));
self::register("chainmail_leggings", $factory->fromTypeId(Ids::CHAINMAIL_LEGGINGS));
self::register("charcoal", $factory->fromTypeId(Ids::CHARCOAL));
self::register("chemical_aluminium_oxide", $factory->fromTypeId(Ids::CHEMICAL_ALUMINIUM_OXIDE));
self::register("chemical_ammonia", $factory->fromTypeId(Ids::CHEMICAL_AMMONIA));
self::register("chemical_barium_sulphate", $factory->fromTypeId(Ids::CHEMICAL_BARIUM_SULPHATE));
self::register("chemical_benzene", $factory->fromTypeId(Ids::CHEMICAL_BENZENE));
self::register("chemical_boron_trioxide", $factory->fromTypeId(Ids::CHEMICAL_BORON_TRIOXIDE));
self::register("chemical_calcium_bromide", $factory->fromTypeId(Ids::CHEMICAL_CALCIUM_BROMIDE));
self::register("chemical_calcium_chloride", $factory->fromTypeId(Ids::CHEMICAL_CALCIUM_CHLORIDE));
self::register("chemical_cerium_chloride", $factory->fromTypeId(Ids::CHEMICAL_CERIUM_CHLORIDE));
self::register("chemical_charcoal", $factory->fromTypeId(Ids::CHEMICAL_CHARCOAL));
self::register("chemical_crude_oil", $factory->fromTypeId(Ids::CHEMICAL_CRUDE_OIL));
self::register("chemical_glue", $factory->fromTypeId(Ids::CHEMICAL_GLUE));
self::register("chemical_hydrogen_peroxide", $factory->fromTypeId(Ids::CHEMICAL_HYDROGEN_PEROXIDE));
self::register("chemical_hypochlorite", $factory->fromTypeId(Ids::CHEMICAL_HYPOCHLORITE));
self::register("chemical_ink", $factory->fromTypeId(Ids::CHEMICAL_INK));
self::register("chemical_iron_sulphide", $factory->fromTypeId(Ids::CHEMICAL_IRON_SULPHIDE));
self::register("chemical_latex", $factory->fromTypeId(Ids::CHEMICAL_LATEX));
self::register("chemical_lithium_hydride", $factory->fromTypeId(Ids::CHEMICAL_LITHIUM_HYDRIDE));
self::register("chemical_luminol", $factory->fromTypeId(Ids::CHEMICAL_LUMINOL));
self::register("chemical_magnesium_nitrate", $factory->fromTypeId(Ids::CHEMICAL_MAGNESIUM_NITRATE));
self::register("chemical_magnesium_oxide", $factory->fromTypeId(Ids::CHEMICAL_MAGNESIUM_OXIDE));
self::register("chemical_magnesium_salts", $factory->fromTypeId(Ids::CHEMICAL_MAGNESIUM_SALTS));
self::register("chemical_mercuric_chloride", $factory->fromTypeId(Ids::CHEMICAL_MERCURIC_CHLORIDE));
self::register("chemical_polyethylene", $factory->fromTypeId(Ids::CHEMICAL_POLYETHYLENE));
self::register("chemical_potassium_chloride", $factory->fromTypeId(Ids::CHEMICAL_POTASSIUM_CHLORIDE));
self::register("chemical_potassium_iodide", $factory->fromTypeId(Ids::CHEMICAL_POTASSIUM_IODIDE));
self::register("chemical_rubbish", $factory->fromTypeId(Ids::CHEMICAL_RUBBISH));
self::register("chemical_salt", $factory->fromTypeId(Ids::CHEMICAL_SALT));
self::register("chemical_soap", $factory->fromTypeId(Ids::CHEMICAL_SOAP));
self::register("chemical_sodium_acetate", $factory->fromTypeId(Ids::CHEMICAL_SODIUM_ACETATE));
self::register("chemical_sodium_fluoride", $factory->fromTypeId(Ids::CHEMICAL_SODIUM_FLUORIDE));
self::register("chemical_sodium_hydride", $factory->fromTypeId(Ids::CHEMICAL_SODIUM_HYDRIDE));
self::register("chemical_sodium_hydroxide", $factory->fromTypeId(Ids::CHEMICAL_SODIUM_HYDROXIDE));
self::register("chemical_sodium_hypochlorite", $factory->fromTypeId(Ids::CHEMICAL_SODIUM_HYPOCHLORITE));
self::register("chemical_sodium_oxide", $factory->fromTypeId(Ids::CHEMICAL_SODIUM_OXIDE));
self::register("chemical_sugar", $factory->fromTypeId(Ids::CHEMICAL_SUGAR));
self::register("chemical_sulphate", $factory->fromTypeId(Ids::CHEMICAL_SULPHATE));
self::register("chemical_tungsten_chloride", $factory->fromTypeId(Ids::CHEMICAL_TUNGSTEN_CHLORIDE));
self::register("chemical_water", $factory->fromTypeId(Ids::CHEMICAL_WATER));
self::register("chorus_fruit", $factory->fromTypeId(Ids::CHORUS_FRUIT));
self::register("clay", $factory->fromTypeId(Ids::CLAY));
self::register("clock", $factory->fromTypeId(Ids::CLOCK));
self::register("clownfish", $factory->fromTypeId(Ids::CLOWNFISH));
self::register("coal", $factory->fromTypeId(Ids::COAL));
self::register("cocoa_beans", $factory->fromTypeId(Ids::COCOA_BEANS));
self::register("compass", $factory->fromTypeId(Ids::COMPASS));
self::register("cooked_chicken", $factory->fromTypeId(Ids::COOKED_CHICKEN));
self::register("cooked_fish", $factory->fromTypeId(Ids::COOKED_FISH));
self::register("cooked_mutton", $factory->fromTypeId(Ids::COOKED_MUTTON));
self::register("cooked_porkchop", $factory->fromTypeId(Ids::COOKED_PORKCHOP));
self::register("cooked_rabbit", $factory->fromTypeId(Ids::COOKED_RABBIT));
self::register("cooked_salmon", $factory->fromTypeId(Ids::COOKED_SALMON));
self::register("cookie", $factory->fromTypeId(Ids::COOKIE));
self::register("copper_ingot", $factory->fromTypeId(Ids::COPPER_INGOT));
self::register("coral_fan", $factory->fromTypeId(Ids::CORAL_FAN));
self::register("crimson_sign", $factory->fromTypeId(Ids::CRIMSON_SIGN));
self::register("dark_oak_boat", $factory->fromTypeId(Ids::DARK_OAK_BOAT));
self::register("dark_oak_sign", $factory->fromTypeId(Ids::DARK_OAK_SIGN));
self::register("diamond", $factory->fromTypeId(Ids::DIAMOND));
self::register("diamond_axe", $factory->fromTypeId(Ids::DIAMOND_AXE));
self::register("diamond_boots", $factory->fromTypeId(Ids::DIAMOND_BOOTS));
self::register("diamond_chestplate", $factory->fromTypeId(Ids::DIAMOND_CHESTPLATE));
self::register("diamond_helmet", $factory->fromTypeId(Ids::DIAMOND_HELMET));
self::register("diamond_hoe", $factory->fromTypeId(Ids::DIAMOND_HOE));
self::register("diamond_leggings", $factory->fromTypeId(Ids::DIAMOND_LEGGINGS));
self::register("diamond_pickaxe", $factory->fromTypeId(Ids::DIAMOND_PICKAXE));
self::register("diamond_shovel", $factory->fromTypeId(Ids::DIAMOND_SHOVEL));
self::register("diamond_sword", $factory->fromTypeId(Ids::DIAMOND_SWORD));
self::register("disc_fragment_5", $factory->fromTypeId(Ids::DISC_FRAGMENT_5));
self::register("dragon_breath", $factory->fromTypeId(Ids::DRAGON_BREATH));
self::register("dried_kelp", $factory->fromTypeId(Ids::DRIED_KELP));
self::register("dye", $factory->fromTypeId(Ids::DYE));
self::register("echo_shard", $factory->fromTypeId(Ids::ECHO_SHARD));
self::register("egg", $factory->fromTypeId(Ids::EGG));
self::register("emerald", $factory->fromTypeId(Ids::EMERALD));
self::register("enchanted_golden_apple", $factory->fromTypeId(Ids::ENCHANTED_GOLDEN_APPLE));
self::register("ender_pearl", $factory->fromTypeId(Ids::ENDER_PEARL));
self::register("experience_bottle", $factory->fromTypeId(Ids::EXPERIENCE_BOTTLE));
self::register("feather", $factory->fromTypeId(Ids::FEATHER));
self::register("fermented_spider_eye", $factory->fromTypeId(Ids::FERMENTED_SPIDER_EYE));
self::register("fishing_rod", $factory->fromTypeId(Ids::FISHING_ROD));
self::register("flint", $factory->fromTypeId(Ids::FLINT));
self::register("flint_and_steel", $factory->fromTypeId(Ids::FLINT_AND_STEEL));
self::register("ghast_tear", $factory->fromTypeId(Ids::GHAST_TEAR));
self::register("glass_bottle", $factory->fromTypeId(Ids::GLASS_BOTTLE));
self::register("glistering_melon", $factory->fromTypeId(Ids::GLISTERING_MELON));
self::register("glow_ink_sac", $factory->fromTypeId(Ids::GLOW_INK_SAC));
self::register("glowstone_dust", $factory->fromTypeId(Ids::GLOWSTONE_DUST));
self::register("gold_ingot", $factory->fromTypeId(Ids::GOLD_INGOT));
self::register("gold_nugget", $factory->fromTypeId(Ids::GOLD_NUGGET));
self::register("golden_apple", $factory->fromTypeId(Ids::GOLDEN_APPLE));
self::register("golden_axe", $factory->fromTypeId(Ids::GOLDEN_AXE));
self::register("golden_boots", $factory->fromTypeId(Ids::GOLDEN_BOOTS));
self::register("golden_carrot", $factory->fromTypeId(Ids::GOLDEN_CARROT));
self::register("golden_chestplate", $factory->fromTypeId(Ids::GOLDEN_CHESTPLATE));
self::register("golden_helmet", $factory->fromTypeId(Ids::GOLDEN_HELMET));
self::register("golden_hoe", $factory->fromTypeId(Ids::GOLDEN_HOE));
self::register("golden_leggings", $factory->fromTypeId(Ids::GOLDEN_LEGGINGS));
self::register("golden_pickaxe", $factory->fromTypeId(Ids::GOLDEN_PICKAXE));
self::register("golden_shovel", $factory->fromTypeId(Ids::GOLDEN_SHOVEL));
self::register("golden_sword", $factory->fromTypeId(Ids::GOLDEN_SWORD));
self::register("gunpowder", $factory->fromTypeId(Ids::GUNPOWDER));
self::register("heart_of_the_sea", $factory->fromTypeId(Ids::HEART_OF_THE_SEA));
self::register("honeycomb", $factory->fromTypeId(Ids::HONEYCOMB));
self::register("ink_sac", $factory->fromTypeId(Ids::INK_SAC));
self::register("iron_axe", $factory->fromTypeId(Ids::IRON_AXE));
self::register("iron_boots", $factory->fromTypeId(Ids::IRON_BOOTS));
self::register("iron_chestplate", $factory->fromTypeId(Ids::IRON_CHESTPLATE));
self::register("iron_helmet", $factory->fromTypeId(Ids::IRON_HELMET));
self::register("iron_hoe", $factory->fromTypeId(Ids::IRON_HOE));
self::register("iron_ingot", $factory->fromTypeId(Ids::IRON_INGOT));
self::register("iron_leggings", $factory->fromTypeId(Ids::IRON_LEGGINGS));
self::register("iron_nugget", $factory->fromTypeId(Ids::IRON_NUGGET));
self::register("iron_pickaxe", $factory->fromTypeId(Ids::IRON_PICKAXE));
self::register("iron_shovel", $factory->fromTypeId(Ids::IRON_SHOVEL));
self::register("iron_sword", $factory->fromTypeId(Ids::IRON_SWORD));
self::register("jungle_boat", $factory->fromTypeId(Ids::JUNGLE_BOAT));
self::register("jungle_sign", $factory->fromTypeId(Ids::JUNGLE_SIGN));
self::register("lapis_lazuli", $factory->fromTypeId(Ids::LAPIS_LAZULI));
self::register("lava_bucket", $factory->fromTypeId(Ids::LAVA_BUCKET));
self::register("leather", $factory->fromTypeId(Ids::LEATHER));
self::register("leather_boots", $factory->fromTypeId(Ids::LEATHER_BOOTS));
self::register("leather_cap", $factory->fromTypeId(Ids::LEATHER_CAP));
self::register("leather_pants", $factory->fromTypeId(Ids::LEATHER_PANTS));
self::register("leather_tunic", $factory->fromTypeId(Ids::LEATHER_TUNIC));
self::register("magma_cream", $factory->fromTypeId(Ids::MAGMA_CREAM));
self::register("mangrove_sign", $factory->fromTypeId(Ids::MANGROVE_SIGN));
self::register("melon", $factory->fromTypeId(Ids::MELON));
self::register("melon_seeds", $factory->fromTypeId(Ids::MELON_SEEDS));
self::register("milk_bucket", $factory->fromTypeId(Ids::MILK_BUCKET));
self::register("minecart", $factory->fromTypeId(Ids::MINECART));
self::register("mushroom_stew", $factory->fromTypeId(Ids::MUSHROOM_STEW));
self::register("nautilus_shell", $factory->fromTypeId(Ids::NAUTILUS_SHELL));
self::register("nether_brick", $factory->fromTypeId(Ids::NETHER_BRICK));
self::register("nether_quartz", $factory->fromTypeId(Ids::NETHER_QUARTZ));
self::register("nether_star", $factory->fromTypeId(Ids::NETHER_STAR));
self::register("oak_boat", $factory->fromTypeId(Ids::OAK_BOAT));
self::register("oak_sign", $factory->fromTypeId(Ids::OAK_SIGN));
self::register("painting", $factory->fromTypeId(Ids::PAINTING));
self::register("paper", $factory->fromTypeId(Ids::PAPER));
self::register("phantom_membrane", $factory->fromTypeId(Ids::PHANTOM_MEMBRANE));
self::register("poisonous_potato", $factory->fromTypeId(Ids::POISONOUS_POTATO));
self::register("popped_chorus_fruit", $factory->fromTypeId(Ids::POPPED_CHORUS_FRUIT));
self::register("potato", $factory->fromTypeId(Ids::POTATO));
self::register("potion", $factory->fromTypeId(Ids::POTION));
self::register("prismarine_crystals", $factory->fromTypeId(Ids::PRISMARINE_CRYSTALS));
self::register("prismarine_shard", $factory->fromTypeId(Ids::PRISMARINE_SHARD));
self::register("pufferfish", $factory->fromTypeId(Ids::PUFFERFISH));
self::register("pumpkin_pie", $factory->fromTypeId(Ids::PUMPKIN_PIE));
self::register("pumpkin_seeds", $factory->fromTypeId(Ids::PUMPKIN_SEEDS));
self::register("rabbit_foot", $factory->fromTypeId(Ids::RABBIT_FOOT));
self::register("rabbit_hide", $factory->fromTypeId(Ids::RABBIT_HIDE));
self::register("rabbit_stew", $factory->fromTypeId(Ids::RABBIT_STEW));
self::register("raw_beef", $factory->fromTypeId(Ids::RAW_BEEF));
self::register("raw_chicken", $factory->fromTypeId(Ids::RAW_CHICKEN));
self::register("raw_copper", $factory->fromTypeId(Ids::RAW_COPPER));
self::register("raw_fish", $factory->fromTypeId(Ids::RAW_FISH));
self::register("raw_gold", $factory->fromTypeId(Ids::RAW_GOLD));
self::register("raw_iron", $factory->fromTypeId(Ids::RAW_IRON));
self::register("raw_mutton", $factory->fromTypeId(Ids::RAW_MUTTON));
self::register("raw_porkchop", $factory->fromTypeId(Ids::RAW_PORKCHOP));
self::register("raw_rabbit", $factory->fromTypeId(Ids::RAW_RABBIT));
self::register("raw_salmon", $factory->fromTypeId(Ids::RAW_SALMON));
self::register("record_11", $factory->fromTypeId(Ids::RECORD_11));
self::register("record_13", $factory->fromTypeId(Ids::RECORD_13));
self::register("record_blocks", $factory->fromTypeId(Ids::RECORD_BLOCKS));
self::register("record_cat", $factory->fromTypeId(Ids::RECORD_CAT));
self::register("record_chirp", $factory->fromTypeId(Ids::RECORD_CHIRP));
self::register("record_far", $factory->fromTypeId(Ids::RECORD_FAR));
self::register("record_mall", $factory->fromTypeId(Ids::RECORD_MALL));
self::register("record_mellohi", $factory->fromTypeId(Ids::RECORD_MELLOHI));
self::register("record_stal", $factory->fromTypeId(Ids::RECORD_STAL));
self::register("record_strad", $factory->fromTypeId(Ids::RECORD_STRAD));
self::register("record_wait", $factory->fromTypeId(Ids::RECORD_WAIT));
self::register("record_ward", $factory->fromTypeId(Ids::RECORD_WARD));
self::register("redstone_dust", $factory->fromTypeId(Ids::REDSTONE_DUST));
self::register("rotten_flesh", $factory->fromTypeId(Ids::ROTTEN_FLESH));
self::register("scute", $factory->fromTypeId(Ids::SCUTE));
self::register("shears", $factory->fromTypeId(Ids::SHEARS));
self::register("shulker_shell", $factory->fromTypeId(Ids::SHULKER_SHELL));
self::register("slimeball", $factory->fromTypeId(Ids::SLIMEBALL));
self::register("snowball", $factory->fromTypeId(Ids::SNOWBALL));
self::register("spider_eye", $factory->fromTypeId(Ids::SPIDER_EYE));
self::register("splash_potion", $factory->fromTypeId(Ids::SPLASH_POTION));
self::register("spruce_boat", $factory->fromTypeId(Ids::SPRUCE_BOAT));
self::register("spruce_sign", $factory->fromTypeId(Ids::SPRUCE_SIGN));
self::register("spyglass", $factory->fromTypeId(Ids::SPYGLASS));
self::register("squid_spawn_egg", $factory->fromTypeId(Ids::SQUID_SPAWN_EGG));
self::register("steak", $factory->fromTypeId(Ids::STEAK));
self::register("stick", $factory->fromTypeId(Ids::STICK));
self::register("stone_axe", $factory->fromTypeId(Ids::STONE_AXE));
self::register("stone_hoe", $factory->fromTypeId(Ids::STONE_HOE));
self::register("stone_pickaxe", $factory->fromTypeId(Ids::STONE_PICKAXE));
self::register("stone_shovel", $factory->fromTypeId(Ids::STONE_SHOVEL));
self::register("stone_sword", $factory->fromTypeId(Ids::STONE_SWORD));
self::register("string", $factory->fromTypeId(Ids::STRING));
self::register("sugar", $factory->fromTypeId(Ids::SUGAR));
self::register("sweet_berries", $factory->fromTypeId(Ids::SWEET_BERRIES));
self::register("totem", $factory->fromTypeId(Ids::TOTEM));
self::register("villager_spawn_egg", $factory->fromTypeId(Ids::VILLAGER_SPAWN_EGG));
self::register("warped_sign", $factory->fromTypeId(Ids::WARPED_SIGN));
self::register("water_bucket", $factory->fromTypeId(Ids::WATER_BUCKET));
self::register("wheat", $factory->fromTypeId(Ids::WHEAT));
self::register("wheat_seeds", $factory->fromTypeId(Ids::WHEAT_SEEDS));
self::register("wooden_axe", $factory->fromTypeId(Ids::WOODEN_AXE));
self::register("wooden_hoe", $factory->fromTypeId(Ids::WOODEN_HOE));
self::register("wooden_pickaxe", $factory->fromTypeId(Ids::WOODEN_PICKAXE));
self::register("wooden_shovel", $factory->fromTypeId(Ids::WOODEN_SHOVEL));
self::register("wooden_sword", $factory->fromTypeId(Ids::WOODEN_SWORD));
self::register("writable_book", $factory->fromTypeId(Ids::WRITABLE_BOOK));
self::register("written_book", $factory->fromTypeId(Ids::WRITTEN_BOOK));
self::register("zombie_spawn_egg", $factory->fromTypeId(Ids::ZOMBIE_SPAWN_EGG));
self::register("acacia_sign", new ItemBlockWallOrFloor(new IID(Ids::ACACIA_SIGN), Blocks::ACACIA_SIGN(), Blocks::ACACIA_WALL_SIGN()));
self::register("amethyst_shard", new Item(new IID(Ids::AMETHYST_SHARD), "Amethyst Shard"));
self::register("apple", new Apple(new IID(Ids::APPLE), "Apple"));
self::register("arrow", new Arrow(new IID(Ids::ARROW), "Arrow"));
self::register("baked_potato", new BakedPotato(new IID(Ids::BAKED_POTATO), "Baked Potato"));
self::register("bamboo", new Bamboo(new IID(Ids::BAMBOO), "Bamboo"));
self::register("banner", new Banner(new IID(Ids::BANNER), Blocks::BANNER(), Blocks::WALL_BANNER()));
self::register("beetroot", new Beetroot(new IID(Ids::BEETROOT), "Beetroot"));
self::register("beetroot_seeds", new BeetrootSeeds(new IID(Ids::BEETROOT_SEEDS), "Beetroot Seeds"));
self::register("beetroot_soup", new BeetrootSoup(new IID(Ids::BEETROOT_SOUP), "Beetroot Soup"));
self::register("birch_sign", new ItemBlockWallOrFloor(new IID(Ids::BIRCH_SIGN), Blocks::BIRCH_SIGN(), Blocks::BIRCH_WALL_SIGN()));
self::register("blaze_powder", new Item(new IID(Ids::BLAZE_POWDER), "Blaze Powder"));
self::register("blaze_rod", new BlazeRod(new IID(Ids::BLAZE_ROD), "Blaze Rod"));
self::register("bleach", new Item(new IID(Ids::BLEACH), "Bleach"));
self::register("bone", new Item(new IID(Ids::BONE), "Bone"));
self::register("bone_meal", new Fertilizer(new IID(Ids::BONE_MEAL), "Bone Meal"));
self::register("book", new Book(new IID(Ids::BOOK), "Book"));
self::register("bow", new Bow(new IID(Ids::BOW), "Bow"));
self::register("bowl", new Bowl(new IID(Ids::BOWL), "Bowl"));
self::register("bread", new Bread(new IID(Ids::BREAD), "Bread"));
self::register("brick", new Item(new IID(Ids::BRICK), "Brick"));
self::register("bucket", new Bucket(new IID(Ids::BUCKET), "Bucket"));
self::register("carrot", new Carrot(new IID(Ids::CARROT), "Carrot"));
self::register("charcoal", new Coal(new IID(Ids::CHARCOAL), "Charcoal"));
self::register("chemical_aluminium_oxide", new Item(new IID(Ids::CHEMICAL_ALUMINIUM_OXIDE), "Aluminium Oxide"));
self::register("chemical_ammonia", new Item(new IID(Ids::CHEMICAL_AMMONIA), "Ammonia"));
self::register("chemical_barium_sulphate", new Item(new IID(Ids::CHEMICAL_BARIUM_SULPHATE), "Barium Sulphate"));
self::register("chemical_benzene", new Item(new IID(Ids::CHEMICAL_BENZENE), "Benzene"));
self::register("chemical_boron_trioxide", new Item(new IID(Ids::CHEMICAL_BORON_TRIOXIDE), "Boron Trioxide"));
self::register("chemical_calcium_bromide", new Item(new IID(Ids::CHEMICAL_CALCIUM_BROMIDE), "Calcium Bromide"));
self::register("chemical_calcium_chloride", new Item(new IID(Ids::CHEMICAL_CALCIUM_CHLORIDE), "Calcium Chloride"));
self::register("chemical_cerium_chloride", new Item(new IID(Ids::CHEMICAL_CERIUM_CHLORIDE), "Cerium Chloride"));
self::register("chemical_charcoal", new Item(new IID(Ids::CHEMICAL_CHARCOAL), "Charcoal"));
self::register("chemical_crude_oil", new Item(new IID(Ids::CHEMICAL_CRUDE_OIL), "Crude Oil"));
self::register("chemical_glue", new Item(new IID(Ids::CHEMICAL_GLUE), "Glue"));
self::register("chemical_hydrogen_peroxide", new Item(new IID(Ids::CHEMICAL_HYDROGEN_PEROXIDE), "Hydrogen Peroxide"));
self::register("chemical_hypochlorite", new Item(new IID(Ids::CHEMICAL_HYPOCHLORITE), "Hypochlorite"));
self::register("chemical_ink", new Item(new IID(Ids::CHEMICAL_INK), "Ink"));
self::register("chemical_iron_sulphide", new Item(new IID(Ids::CHEMICAL_IRON_SULPHIDE), "Iron Sulphide"));
self::register("chemical_latex", new Item(new IID(Ids::CHEMICAL_LATEX), "Latex"));
self::register("chemical_lithium_hydride", new Item(new IID(Ids::CHEMICAL_LITHIUM_HYDRIDE), "Lithium Hydride"));
self::register("chemical_luminol", new Item(new IID(Ids::CHEMICAL_LUMINOL), "Luminol"));
self::register("chemical_magnesium_nitrate", new Item(new IID(Ids::CHEMICAL_MAGNESIUM_NITRATE), "Magnesium Nitrate"));
self::register("chemical_magnesium_oxide", new Item(new IID(Ids::CHEMICAL_MAGNESIUM_OXIDE), "Magnesium Oxide"));
self::register("chemical_magnesium_salts", new Item(new IID(Ids::CHEMICAL_MAGNESIUM_SALTS), "Magnesium Salts"));
self::register("chemical_mercuric_chloride", new Item(new IID(Ids::CHEMICAL_MERCURIC_CHLORIDE), "Mercuric Chloride"));
self::register("chemical_polyethylene", new Item(new IID(Ids::CHEMICAL_POLYETHYLENE), "Polyethylene"));
self::register("chemical_potassium_chloride", new Item(new IID(Ids::CHEMICAL_POTASSIUM_CHLORIDE), "Potassium Chloride"));
self::register("chemical_potassium_iodide", new Item(new IID(Ids::CHEMICAL_POTASSIUM_IODIDE), "Potassium Iodide"));
self::register("chemical_rubbish", new Item(new IID(Ids::CHEMICAL_RUBBISH), "Rubbish"));
self::register("chemical_salt", new Item(new IID(Ids::CHEMICAL_SALT), "Salt"));
self::register("chemical_soap", new Item(new IID(Ids::CHEMICAL_SOAP), "Soap"));
self::register("chemical_sodium_acetate", new Item(new IID(Ids::CHEMICAL_SODIUM_ACETATE), "Sodium Acetate"));
self::register("chemical_sodium_fluoride", new Item(new IID(Ids::CHEMICAL_SODIUM_FLUORIDE), "Sodium Fluoride"));
self::register("chemical_sodium_hydride", new Item(new IID(Ids::CHEMICAL_SODIUM_HYDRIDE), "Sodium Hydride"));
self::register("chemical_sodium_hydroxide", new Item(new IID(Ids::CHEMICAL_SODIUM_HYDROXIDE), "Sodium Hydroxide"));
self::register("chemical_sodium_hypochlorite", new Item(new IID(Ids::CHEMICAL_SODIUM_HYPOCHLORITE), "Sodium Hypochlorite"));
self::register("chemical_sodium_oxide", new Item(new IID(Ids::CHEMICAL_SODIUM_OXIDE), "Sodium Oxide"));
self::register("chemical_sugar", new Item(new IID(Ids::CHEMICAL_SUGAR), "Sugar"));
self::register("chemical_sulphate", new Item(new IID(Ids::CHEMICAL_SULPHATE), "Sulphate"));
self::register("chemical_tungsten_chloride", new Item(new IID(Ids::CHEMICAL_TUNGSTEN_CHLORIDE), "Tungsten Chloride"));
self::register("chemical_water", new Item(new IID(Ids::CHEMICAL_WATER), "Water"));
self::register("chorus_fruit", new ChorusFruit(new IID(Ids::CHORUS_FRUIT), "Chorus Fruit"));
self::register("clay", new Item(new IID(Ids::CLAY), "Clay"));
self::register("clock", new Clock(new IID(Ids::CLOCK), "Clock"));
self::register("clownfish", new Clownfish(new IID(Ids::CLOWNFISH), "Clownfish"));
self::register("coal", new Coal(new IID(Ids::COAL), "Coal"));
self::register("cocoa_beans", new CocoaBeans(new IID(Ids::COCOA_BEANS), "Cocoa Beans"));
self::register("compass", new Compass(new IID(Ids::COMPASS), "Compass"));
self::register("cooked_chicken", new CookedChicken(new IID(Ids::COOKED_CHICKEN), "Cooked Chicken"));
self::register("cooked_fish", new CookedFish(new IID(Ids::COOKED_FISH), "Cooked Fish"));
self::register("cooked_mutton", new CookedMutton(new IID(Ids::COOKED_MUTTON), "Cooked Mutton"));
self::register("cooked_porkchop", new CookedPorkchop(new IID(Ids::COOKED_PORKCHOP), "Cooked Porkchop"));
self::register("cooked_rabbit", new CookedRabbit(new IID(Ids::COOKED_RABBIT), "Cooked Rabbit"));
self::register("cooked_salmon", new CookedSalmon(new IID(Ids::COOKED_SALMON), "Cooked Salmon"));
self::register("cookie", new Cookie(new IID(Ids::COOKIE), "Cookie"));
self::register("copper_ingot", new Item(new IID(Ids::COPPER_INGOT), "Copper Ingot"));
self::register("coral_fan", new CoralFan(new IID(Ids::CORAL_FAN)));
self::register("crimson_sign", new ItemBlockWallOrFloor(new IID(Ids::CRIMSON_SIGN), Blocks::CRIMSON_SIGN(), Blocks::CRIMSON_WALL_SIGN()));
self::register("dark_oak_sign", new ItemBlockWallOrFloor(new IID(Ids::DARK_OAK_SIGN), Blocks::DARK_OAK_SIGN(), Blocks::DARK_OAK_WALL_SIGN()));
self::register("diamond", new Item(new IID(Ids::DIAMOND), "Diamond"));
self::register("disc_fragment_5", new Item(new IID(Ids::DISC_FRAGMENT_5), "Disc Fragment (5)"));
self::register("dragon_breath", new Item(new IID(Ids::DRAGON_BREATH), "Dragon's Breath"));
self::register("dried_kelp", new DriedKelp(new IID(Ids::DRIED_KELP), "Dried Kelp"));
//TODO: add interface to dye-colour objects
self::register("dye", new Dye(new IID(Ids::DYE), "Dye"));
self::register("echo_shard", new Item(new IID(Ids::ECHO_SHARD), "Echo Shard"));
self::register("egg", new Egg(new IID(Ids::EGG), "Egg"));
self::register("emerald", new Item(new IID(Ids::EMERALD), "Emerald"));
self::register("enchanted_golden_apple", new GoldenAppleEnchanted(new IID(Ids::ENCHANTED_GOLDEN_APPLE), "Enchanted Golden Apple"));
self::register("ender_pearl", new EnderPearl(new IID(Ids::ENDER_PEARL), "Ender Pearl"));
self::register("experience_bottle", new ExperienceBottle(new IID(Ids::EXPERIENCE_BOTTLE), "Bottle o' Enchanting"));
self::register("feather", new Item(new IID(Ids::FEATHER), "Feather"));
self::register("fermented_spider_eye", new Item(new IID(Ids::FERMENTED_SPIDER_EYE), "Fermented Spider Eye"));
self::register("fishing_rod", new FishingRod(new IID(Ids::FISHING_ROD), "Fishing Rod"));
self::register("flint", new Item(new IID(Ids::FLINT), "Flint"));
self::register("flint_and_steel", new FlintSteel(new IID(Ids::FLINT_AND_STEEL), "Flint and Steel"));
self::register("ghast_tear", new Item(new IID(Ids::GHAST_TEAR), "Ghast Tear"));
self::register("glass_bottle", new GlassBottle(new IID(Ids::GLASS_BOTTLE), "Glass Bottle"));
self::register("glistering_melon", new Item(new IID(Ids::GLISTERING_MELON), "Glistering Melon"));
self::register("glow_ink_sac", new Item(new IID(Ids::GLOW_INK_SAC), "Glow Ink Sac"));
self::register("glowstone_dust", new Item(new IID(Ids::GLOWSTONE_DUST), "Glowstone Dust"));
self::register("gold_ingot", new Item(new IID(Ids::GOLD_INGOT), "Gold Ingot"));
self::register("gold_nugget", new Item(new IID(Ids::GOLD_NUGGET), "Gold Nugget"));
self::register("golden_apple", new GoldenApple(new IID(Ids::GOLDEN_APPLE), "Golden Apple"));
self::register("golden_carrot", new GoldenCarrot(new IID(Ids::GOLDEN_CARROT), "Golden Carrot"));
self::register("gunpowder", new Item(new IID(Ids::GUNPOWDER), "Gunpowder"));
self::register("heart_of_the_sea", new Item(new IID(Ids::HEART_OF_THE_SEA), "Heart of the Sea"));
self::register("honey_bottle", new HoneyBottle(new IID(Ids::HONEY_BOTTLE), "Honey Bottle"));
self::register("honeycomb", new Item(new IID(Ids::HONEYCOMB), "Honeycomb"));
self::register("ink_sac", new Item(new IID(Ids::INK_SAC), "Ink Sac"));
self::register("iron_ingot", new Item(new IID(Ids::IRON_INGOT), "Iron Ingot"));
self::register("iron_nugget", new Item(new IID(Ids::IRON_NUGGET), "Iron Nugget"));
self::register("jungle_sign", new ItemBlockWallOrFloor(new IID(Ids::JUNGLE_SIGN), Blocks::JUNGLE_SIGN(), Blocks::JUNGLE_WALL_SIGN()));
self::register("lapis_lazuli", new Item(new IID(Ids::LAPIS_LAZULI), "Lapis Lazuli"));
self::register("lava_bucket", new LiquidBucket(new IID(Ids::LAVA_BUCKET), "Lava Bucket", Blocks::LAVA()));
self::register("leather", new Item(new IID(Ids::LEATHER), "Leather"));
self::register("magma_cream", new Item(new IID(Ids::MAGMA_CREAM), "Magma Cream"));
self::register("mangrove_sign", new ItemBlockWallOrFloor(new IID(Ids::MANGROVE_SIGN), Blocks::MANGROVE_SIGN(), Blocks::MANGROVE_WALL_SIGN()));
self::register("melon", new Melon(new IID(Ids::MELON), "Melon"));
self::register("melon_seeds", new MelonSeeds(new IID(Ids::MELON_SEEDS), "Melon Seeds"));
self::register("milk_bucket", new MilkBucket(new IID(Ids::MILK_BUCKET), "Milk Bucket"));
self::register("minecart", new Minecart(new IID(Ids::MINECART), "Minecart"));
self::register("mushroom_stew", new MushroomStew(new IID(Ids::MUSHROOM_STEW), "Mushroom Stew"));
self::register("nautilus_shell", new Item(new IID(Ids::NAUTILUS_SHELL), "Nautilus Shell"));
self::register("nether_brick", new Item(new IID(Ids::NETHER_BRICK), "Nether Brick"));
self::register("nether_quartz", new Item(new IID(Ids::NETHER_QUARTZ), "Nether Quartz"));
self::register("nether_star", new Item(new IID(Ids::NETHER_STAR), "Nether Star"));
self::register("netherite_ingot", new class(new IID(Ids::NETHERITE_INGOT), "Netherite Ingot") extends Item{
public function isFireProof() : bool{ return true; }
});
self::register("netherite_scrap", new class(new IID(Ids::NETHERITE_SCRAP), "Netherite Scrap") extends Item{
public function isFireProof() : bool{ return true; }
});
self::register("oak_sign", new ItemBlockWallOrFloor(new IID(Ids::OAK_SIGN), Blocks::OAK_SIGN(), Blocks::OAK_WALL_SIGN()));
self::register("painting", new PaintingItem(new IID(Ids::PAINTING), "Painting"));
self::register("paper", new Item(new IID(Ids::PAPER), "Paper"));
self::register("phantom_membrane", new Item(new IID(Ids::PHANTOM_MEMBRANE), "Phantom Membrane"));
self::register("poisonous_potato", new PoisonousPotato(new IID(Ids::POISONOUS_POTATO), "Poisonous Potato"));
self::register("popped_chorus_fruit", new Item(new IID(Ids::POPPED_CHORUS_FRUIT), "Popped Chorus Fruit"));
self::register("potato", new Potato(new IID(Ids::POTATO), "Potato"));
self::register("potion", new Potion(new IID(Ids::POTION), "Potion"));
self::register("prismarine_crystals", new Item(new IID(Ids::PRISMARINE_CRYSTALS), "Prismarine Crystals"));
self::register("prismarine_shard", new Item(new IID(Ids::PRISMARINE_SHARD), "Prismarine Shard"));
self::register("pufferfish", new Pufferfish(new IID(Ids::PUFFERFISH), "Pufferfish"));
self::register("pumpkin_pie", new PumpkinPie(new IID(Ids::PUMPKIN_PIE), "Pumpkin Pie"));
self::register("pumpkin_seeds", new PumpkinSeeds(new IID(Ids::PUMPKIN_SEEDS), "Pumpkin Seeds"));
self::register("rabbit_foot", new Item(new IID(Ids::RABBIT_FOOT), "Rabbit's Foot"));
self::register("rabbit_hide", new Item(new IID(Ids::RABBIT_HIDE), "Rabbit Hide"));
self::register("rabbit_stew", new RabbitStew(new IID(Ids::RABBIT_STEW), "Rabbit Stew"));
self::register("raw_beef", new RawBeef(new IID(Ids::RAW_BEEF), "Raw Beef"));
self::register("raw_chicken", new RawChicken(new IID(Ids::RAW_CHICKEN), "Raw Chicken"));
self::register("raw_copper", new Item(new IID(Ids::RAW_COPPER), "Raw Copper"));
self::register("raw_fish", new RawFish(new IID(Ids::RAW_FISH), "Raw Fish"));
self::register("raw_gold", new Item(new IID(Ids::RAW_GOLD), "Raw Gold"));
self::register("raw_iron", new Item(new IID(Ids::RAW_IRON), "Raw Iron"));
self::register("raw_mutton", new RawMutton(new IID(Ids::RAW_MUTTON), "Raw Mutton"));
self::register("raw_porkchop", new RawPorkchop(new IID(Ids::RAW_PORKCHOP), "Raw Porkchop"));
self::register("raw_rabbit", new RawRabbit(new IID(Ids::RAW_RABBIT), "Raw Rabbit"));
self::register("raw_salmon", new RawSalmon(new IID(Ids::RAW_SALMON), "Raw Salmon"));
self::register("record_11", new Record(new IID(Ids::RECORD_11), RecordType::DISK_11(), "Record 11"));
self::register("record_13", new Record(new IID(Ids::RECORD_13), RecordType::DISK_13(), "Record 13"));
self::register("record_blocks", new Record(new IID(Ids::RECORD_BLOCKS), RecordType::DISK_BLOCKS(), "Record Blocks"));
self::register("record_cat", new Record(new IID(Ids::RECORD_CAT), RecordType::DISK_CAT(), "Record Cat"));
self::register("record_chirp", new Record(new IID(Ids::RECORD_CHIRP), RecordType::DISK_CHIRP(), "Record Chirp"));
self::register("record_far", new Record(new IID(Ids::RECORD_FAR), RecordType::DISK_FAR(), "Record Far"));
self::register("record_mall", new Record(new IID(Ids::RECORD_MALL), RecordType::DISK_MALL(), "Record Mall"));
self::register("record_mellohi", new Record(new IID(Ids::RECORD_MELLOHI), RecordType::DISK_MELLOHI(), "Record Mellohi"));
self::register("record_stal", new Record(new IID(Ids::RECORD_STAL), RecordType::DISK_STAL(), "Record Stal"));
self::register("record_strad", new Record(new IID(Ids::RECORD_STRAD), RecordType::DISK_STRAD(), "Record Strad"));
self::register("record_wait", new Record(new IID(Ids::RECORD_WAIT), RecordType::DISK_WAIT(), "Record Wait"));
self::register("record_ward", new Record(new IID(Ids::RECORD_WARD), RecordType::DISK_WARD(), "Record Ward"));
self::register("redstone_dust", new Redstone(new IID(Ids::REDSTONE_DUST), "Redstone"));
self::register("rotten_flesh", new RottenFlesh(new IID(Ids::ROTTEN_FLESH), "Rotten Flesh"));
self::register("scute", new Item(new IID(Ids::SCUTE), "Scute"));
self::register("shears", new Shears(new IID(Ids::SHEARS), "Shears"));
self::register("shulker_shell", new Item(new IID(Ids::SHULKER_SHELL), "Shulker Shell"));
self::register("slimeball", new Item(new IID(Ids::SLIMEBALL), "Slimeball"));
self::register("snowball", new Snowball(new IID(Ids::SNOWBALL), "Snowball"));
self::register("spider_eye", new SpiderEye(new IID(Ids::SPIDER_EYE), "Spider Eye"));
self::register("splash_potion", new SplashPotion(new IID(Ids::SPLASH_POTION), "Splash Potion"));
self::register("spruce_sign", new ItemBlockWallOrFloor(new IID(Ids::SPRUCE_SIGN), Blocks::SPRUCE_SIGN(), Blocks::SPRUCE_WALL_SIGN()));
self::register("spyglass", new Spyglass(new IID(Ids::SPYGLASS), "Spyglass"));
self::register("steak", new Steak(new IID(Ids::STEAK), "Steak"));
self::register("stick", new Stick(new IID(Ids::STICK), "Stick"));
self::register("string", new StringItem(new IID(Ids::STRING), "String"));
self::register("sugar", new Item(new IID(Ids::SUGAR), "Sugar"));
self::register("sweet_berries", new SweetBerries(new IID(Ids::SWEET_BERRIES), "Sweet Berries"));
self::register("totem", new Totem(new IID(Ids::TOTEM), "Totem of Undying"));
self::register("warped_sign", new ItemBlockWallOrFloor(new IID(Ids::WARPED_SIGN), Blocks::WARPED_SIGN(), Blocks::WARPED_WALL_SIGN()));
self::register("water_bucket", new LiquidBucket(new IID(Ids::WATER_BUCKET), "Water Bucket", Blocks::WATER()));
self::register("wheat", new Item(new IID(Ids::WHEAT), "Wheat"));
self::register("wheat_seeds", new WheatSeeds(new IID(Ids::WHEAT_SEEDS), "Wheat Seeds"));
self::register("writable_book", new WritableBook(new IID(Ids::WRITABLE_BOOK), "Book & Quill"));
self::register("written_book", new WrittenBook(new IID(Ids::WRITTEN_BOOK), "Written Book"));
foreach(TreeType::getAll() as $type){
//TODO: tree type should be dynamic in the future, but we're staying static for now for the sake of consistency
self::register($type->name() . "_boat", new Boat(new IID(match($type){
TreeType::OAK() => Ids::OAK_BOAT,
TreeType::SPRUCE() => Ids::SPRUCE_BOAT,
TreeType::BIRCH() => Ids::BIRCH_BOAT,
TreeType::JUNGLE() => Ids::JUNGLE_BOAT,
TreeType::ACACIA() => Ids::ACACIA_BOAT,
TreeType::DARK_OAK() => Ids::DARK_OAK_BOAT,
default => throw new AssumptionFailedError("Unhandled tree type " . $type->name())
}), $type->getDisplayName() . " Boat", $type));
}
}
private static function registerSpawnEggs() : void{
self::register("zombie_spawn_egg", new class(new IID(Ids::ZOMBIE_SPAWN_EGG), "Zombie Spawn Egg") extends SpawnEgg{
protected function createEntity(World $world, Vector3 $pos, float $yaw, float $pitch) : Entity{
return new Zombie(Location::fromObject($pos, $world, $yaw, $pitch));
}
});
self::register("squid_spawn_egg", new class(new IID(Ids::SQUID_SPAWN_EGG), "Squid Spawn Egg") extends SpawnEgg{
public function createEntity(World $world, Vector3 $pos, float $yaw, float $pitch) : Entity{
return new Squid(Location::fromObject($pos, $world, $yaw, $pitch));
}
});
self::register("villager_spawn_egg", new class(new IID(Ids::VILLAGER_SPAWN_EGG), "Villager Spawn Egg") extends SpawnEgg{
public function createEntity(World $world, Vector3 $pos, float $yaw, float $pitch) : Entity{
return new Villager(Location::fromObject($pos, $world, $yaw, $pitch));
}
});
}
private static function registerTierToolItems() : void{
self::register("diamond_axe", new Axe(new IID(Ids::DIAMOND_AXE), "Diamond Axe", ToolTier::DIAMOND()));
self::register("golden_axe", new Axe(new IID(Ids::GOLDEN_AXE), "Golden Axe", ToolTier::GOLD()));
self::register("iron_axe", new Axe(new IID(Ids::IRON_AXE), "Iron Axe", ToolTier::IRON()));
self::register("netherite_axe", new Axe(new IID(Ids::NETHERITE_AXE), "Netherite Axe", ToolTier::NETHERITE()));
self::register("stone_axe", new Axe(new IID(Ids::STONE_AXE), "Stone Axe", ToolTier::STONE()));
self::register("wooden_axe", new Axe(new IID(Ids::WOODEN_AXE), "Wooden Axe", ToolTier::WOOD()));
self::register("diamond_hoe", new Hoe(new IID(Ids::DIAMOND_HOE), "Diamond Hoe", ToolTier::DIAMOND()));
self::register("golden_hoe", new Hoe(new IID(Ids::GOLDEN_HOE), "Golden Hoe", ToolTier::GOLD()));
self::register("iron_hoe", new Hoe(new IID(Ids::IRON_HOE), "Iron Hoe", ToolTier::IRON()));
self::register("netherite_hoe", new Hoe(new IID(Ids::NETHERITE_HOE), "Netherite Hoe", ToolTier::NETHERITE()));
self::register("stone_hoe", new Hoe(new IID(Ids::STONE_HOE), "Stone Hoe", ToolTier::STONE()));
self::register("wooden_hoe", new Hoe(new IID(Ids::WOODEN_HOE), "Wooden Hoe", ToolTier::WOOD()));
self::register("diamond_pickaxe", new Pickaxe(new IID(Ids::DIAMOND_PICKAXE), "Diamond Pickaxe", ToolTier::DIAMOND()));
self::register("golden_pickaxe", new Pickaxe(new IID(Ids::GOLDEN_PICKAXE), "Golden Pickaxe", ToolTier::GOLD()));
self::register("iron_pickaxe", new Pickaxe(new IID(Ids::IRON_PICKAXE), "Iron Pickaxe", ToolTier::IRON()));
self::register("netherite_pickaxe", new Pickaxe(new IID(Ids::NETHERITE_PICKAXE), "Netherite Pickaxe", ToolTier::NETHERITE()));
self::register("stone_pickaxe", new Pickaxe(new IID(Ids::STONE_PICKAXE), "Stone Pickaxe", ToolTier::STONE()));
self::register("wooden_pickaxe", new Pickaxe(new IID(Ids::WOODEN_PICKAXE), "Wooden Pickaxe", ToolTier::WOOD()));
self::register("diamond_shovel", new Shovel(new IID(Ids::DIAMOND_SHOVEL), "Diamond Shovel", ToolTier::DIAMOND()));
self::register("golden_shovel", new Shovel(new IID(Ids::GOLDEN_SHOVEL), "Golden Shovel", ToolTier::GOLD()));
self::register("iron_shovel", new Shovel(new IID(Ids::IRON_SHOVEL), "Iron Shovel", ToolTier::IRON()));
self::register("netherite_shovel", new Shovel(new IID(Ids::NETHERITE_SHOVEL), "Netherite Shovel", ToolTier::NETHERITE()));
self::register("stone_shovel", new Shovel(new IID(Ids::STONE_SHOVEL), "Stone Shovel", ToolTier::STONE()));
self::register("wooden_shovel", new Shovel(new IID(Ids::WOODEN_SHOVEL), "Wooden Shovel", ToolTier::WOOD()));
self::register("diamond_sword", new Sword(new IID(Ids::DIAMOND_SWORD), "Diamond Sword", ToolTier::DIAMOND()));
self::register("golden_sword", new Sword(new IID(Ids::GOLDEN_SWORD), "Golden Sword", ToolTier::GOLD()));
self::register("iron_sword", new Sword(new IID(Ids::IRON_SWORD), "Iron Sword", ToolTier::IRON()));
self::register("netherite_sword", new Sword(new IID(Ids::NETHERITE_SWORD), "Netherite Sword", ToolTier::NETHERITE()));
self::register("stone_sword", new Sword(new IID(Ids::STONE_SWORD), "Stone Sword", ToolTier::STONE()));
self::register("wooden_sword", new Sword(new IID(Ids::WOODEN_SWORD), "Wooden Sword", ToolTier::WOOD()));
}
private static function registerArmorItems() : void{
self::register("chainmail_boots", new Armor(new IID(Ids::CHAINMAIL_BOOTS), "Chainmail Boots", new ArmorTypeInfo(1, 196, ArmorInventory::SLOT_FEET)));
self::register("diamond_boots", new Armor(new IID(Ids::DIAMOND_BOOTS), "Diamond Boots", new ArmorTypeInfo(3, 430, ArmorInventory::SLOT_FEET, 2)));
self::register("golden_boots", new Armor(new IID(Ids::GOLDEN_BOOTS), "Golden Boots", new ArmorTypeInfo(1, 92, ArmorInventory::SLOT_FEET)));
self::register("iron_boots", new Armor(new IID(Ids::IRON_BOOTS), "Iron Boots", new ArmorTypeInfo(2, 196, ArmorInventory::SLOT_FEET)));
self::register("leather_boots", new Armor(new IID(Ids::LEATHER_BOOTS), "Leather Boots", new ArmorTypeInfo(1, 66, ArmorInventory::SLOT_FEET)));
self::register("netherite_boots", new Armor(new IID(Ids::NETHERITE_BOOTS), "Netherite Boots", new ArmorTypeInfo(3, 482, ArmorInventory::SLOT_FEET, 3, true)));
self::register("chainmail_chestplate", new Armor(new IID(Ids::CHAINMAIL_CHESTPLATE), "Chainmail Chestplate", new ArmorTypeInfo(5, 241, ArmorInventory::SLOT_CHEST)));
self::register("diamond_chestplate", new Armor(new IID(Ids::DIAMOND_CHESTPLATE), "Diamond Chestplate", new ArmorTypeInfo(8, 529, ArmorInventory::SLOT_CHEST, 2)));
self::register("golden_chestplate", new Armor(new IID(Ids::GOLDEN_CHESTPLATE), "Golden Chestplate", new ArmorTypeInfo(5, 113, ArmorInventory::SLOT_CHEST)));
self::register("iron_chestplate", new Armor(new IID(Ids::IRON_CHESTPLATE), "Iron Chestplate", new ArmorTypeInfo(6, 241, ArmorInventory::SLOT_CHEST)));
self::register("leather_tunic", new Armor(new IID(Ids::LEATHER_TUNIC), "Leather Tunic", new ArmorTypeInfo(3, 81, ArmorInventory::SLOT_CHEST)));
self::register("netherite_chestplate", new Armor(new IID(Ids::NETHERITE_CHESTPLATE), "Netherite Chestplate", new ArmorTypeInfo(8, 593, ArmorInventory::SLOT_CHEST, 3, true)));
self::register("chainmail_helmet", new Armor(new IID(Ids::CHAINMAIL_HELMET), "Chainmail Helmet", new ArmorTypeInfo(2, 166, ArmorInventory::SLOT_HEAD)));
self::register("diamond_helmet", new Armor(new IID(Ids::DIAMOND_HELMET), "Diamond Helmet", new ArmorTypeInfo(3, 364, ArmorInventory::SLOT_HEAD, 2)));
self::register("golden_helmet", new Armor(new IID(Ids::GOLDEN_HELMET), "Golden Helmet", new ArmorTypeInfo(2, 78, ArmorInventory::SLOT_HEAD)));
self::register("iron_helmet", new Armor(new IID(Ids::IRON_HELMET), "Iron Helmet", new ArmorTypeInfo(2, 166, ArmorInventory::SLOT_HEAD)));
self::register("leather_cap", new Armor(new IID(Ids::LEATHER_CAP), "Leather Cap", new ArmorTypeInfo(1, 56, ArmorInventory::SLOT_HEAD)));
self::register("netherite_helmet", new Armor(new IID(Ids::NETHERITE_HELMET), "Netherite Helmet", new ArmorTypeInfo(3, 408, ArmorInventory::SLOT_HEAD, 3, true)));
self::register("chainmail_leggings", new Armor(new IID(Ids::CHAINMAIL_LEGGINGS), "Chainmail Leggings", new ArmorTypeInfo(4, 226, ArmorInventory::SLOT_LEGS)));
self::register("diamond_leggings", new Armor(new IID(Ids::DIAMOND_LEGGINGS), "Diamond Leggings", new ArmorTypeInfo(6, 496, ArmorInventory::SLOT_LEGS, 2)));
self::register("golden_leggings", new Armor(new IID(Ids::GOLDEN_LEGGINGS), "Golden Leggings", new ArmorTypeInfo(3, 106, ArmorInventory::SLOT_LEGS)));
self::register("iron_leggings", new Armor(new IID(Ids::IRON_LEGGINGS), "Iron Leggings", new ArmorTypeInfo(5, 226, ArmorInventory::SLOT_LEGS)));
self::register("leather_pants", new Armor(new IID(Ids::LEATHER_PANTS), "Leather Pants", new ArmorTypeInfo(2, 76, ArmorInventory::SLOT_LEGS)));
self::register("netherite_leggings", new Armor(new IID(Ids::NETHERITE_LEGGINGS), "Netherite Leggings", new ArmorTypeInfo(6, 556, ArmorInventory::SLOT_LEGS, 3, true)));
}
}

Some files were not shown because too many files have changed in this diff Show More