Compare commits

..

3 Commits

675 changed files with 13231 additions and 29529 deletions

View File

@ -22,7 +22,7 @@ jobs:
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
pm-version-major: "5"
pm-version-major: "4"
phpstan:
name: PHPStan analysis
@ -43,7 +43,7 @@ jobs:
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
pm-version-major: "5"
pm-version-major: "4"
- name: Install Composer
run: curl -sS https://getcomposer.org/installer | php
@ -82,7 +82,7 @@ jobs:
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
pm-version-major: "5"
pm-version-major: "4"
- name: Install Composer
run: curl -sS https://getcomposer.org/installer | php
@ -123,7 +123,7 @@ jobs:
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
pm-version-major: "5"
pm-version-major: "4"
- name: Install Composer
run: curl -sS https://getcomposer.org/installer | php
@ -162,7 +162,7 @@ jobs:
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
pm-version-major: "5"
pm-version-major: "4"
- name: Install Composer
run: curl -sS https://getcomposer.org/installer | php
@ -186,9 +186,6 @@ jobs:
- name: Regenerate KnownTranslation APIs
run: php build/generate-known-translation-apis.php
- name: Regenerate RuntimeEnum(De)serializer
run: php build/generate-runtime-enum-serializers.php
- name: Verify code is unchanged
run: |
git diff

View File

@ -1,197 +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\build\generate_block_serializer_consts;
use pocketmine\data\bedrock\block\BlockStateData;
use pocketmine\data\bedrock\block\BlockStateNames;
use pocketmine\data\bedrock\block\BlockStateStringValues;
use pocketmine\data\bedrock\block\BlockTypeNames;
use pocketmine\errorhandler\ErrorToExceptionHandler;
use pocketmine\nbt\NbtException;
use pocketmine\network\mcpe\convert\BlockStateDictionary;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\Utils;
use function array_values;
use function asort;
use function count;
use function dirname;
use function explode;
use function fclose;
use function file_get_contents;
use function fopen;
use function fwrite;
use function is_string;
use function ksort;
use function mb_strtoupper;
use function sort;
use function strrpos;
use function strtoupper;
use function substr;
use const SORT_STRING;
use const STDERR;
require dirname(__DIR__) . '/vendor/autoload.php';
class BlockPaletteReport{
/**
* @var string[]
* @phpstan-var array<string, string>
*/
public array $seenTypes = [];
/**
* @var string[][]
* @phpstan-var array<string, array<mixed, mixed>>
*/
public array $seenStateValues = [];
}
/**
* @param BlockStateData[] $states
* @phpstan-param list<BlockStateData> $states
*/
function generateBlockPaletteReport(array $states) : BlockPaletteReport{
$result = new BlockPaletteReport();
foreach($states as $stateData){
$name = $stateData->getName();
$result->seenTypes[$name] = $name;
foreach(Utils::stringifyKeys($stateData->getStates()) as $k => $v){
$result->seenStateValues[$k][$v->getValue()] = $v->getValue();
asort($result->seenStateValues[$k]);
}
}
ksort($result->seenTypes, SORT_STRING);
ksort($result->seenStateValues, SORT_STRING);
return $result;
}
function constifyMcId(string $id) : string{
return strtoupper(explode(":", $id, 2)[1]);
}
function generateClassHeader(string $className) : string{
$backslashPos = strrpos($className, "\\");
if($backslashPos === false){
throw new AssumptionFailedError("Expected a namespaced class FQN");
}
$namespace = substr($className, 0, $backslashPos);
$shortName = substr($className, $backslashPos + 1);
return <<<HEADER
<?php
declare(strict_types=1);
namespace $namespace;
/**
* This class is generated automatically from the block palette for the current version. Do not edit it manually.
*/
final class $shortName{
private function __construct(){
//NOOP
}
HEADER;
}
/**
* @phpstan-param list<string> $seenIds
*/
function generateBlockIds(array $seenIds) : void{
$output = ErrorToExceptionHandler::trapAndRemoveFalse(fn() => fopen(dirname(__DIR__) . '/src/data/bedrock/block/BlockTypeNames.php', 'wb'));
fwrite($output, generateClassHeader(BlockTypeNames::class));
foreach($seenIds as $id){
fwrite($output, "\tpublic const " . constifyMcId($id) . " = \"" . $id . "\";\n");
}
fwrite($output, "}\n");
fclose($output);
}
function generateBlockStateNames(BlockPaletteReport $data) : void{
$output = ErrorToExceptionHandler::trapAndRemoveFalse(fn() => fopen(dirname(__DIR__) . '/src/data/bedrock/block/BlockStateNames.php', 'wb'));
fwrite($output, generateClassHeader(BlockStateNames::class));
foreach(Utils::stringifyKeys($data->seenStateValues) as $state => $values){
$constName = mb_strtoupper($state, 'US-ASCII');
fwrite($output, "\tpublic const $constName = \"$state\";\n");
}
fwrite($output, "}\n");
fclose($output);
}
function generateBlockStringValues(BlockPaletteReport $data) : void{
$output = ErrorToExceptionHandler::trapAndRemoveFalse(fn() => fopen(dirname(__DIR__) . '/src/data/bedrock/block/BlockStateStringValues.php', 'wb'));
fwrite($output, generateClassHeader(BlockStateStringValues::class));
foreach(Utils::stringifyKeys($data->seenStateValues) as $stateName => $values){
$anyWritten = false;
sort($values, SORT_STRING);
foreach($values as $value){
if(!is_string($value)){
continue;
}
$anyWritten = true;
$constName = mb_strtoupper($stateName . "_" . $value, 'US-ASCII');
fwrite($output, "\tpublic const $constName = \"$value\";\n");
}
if($anyWritten){
fwrite($output, "\n");
}
}
fwrite($output, "}\n");
fclose($output);
}
if(count($argv) !== 2){
fwrite(STDERR, "This script regenerates BlockTypeNames, BlockStateNames and BlockStateStringValues from a given palette file\n");
fwrite(STDERR, "Required arguments: path to block palette file\n");
exit(1);
}
$palettePath = $argv[1];
$paletteRaw = file_get_contents($palettePath);
if($paletteRaw === false){
fwrite(STDERR, "Failed to read block palette file\n");
exit(1);
}
try{
$states = BlockStateDictionary::loadPaletteFromString($paletteRaw);
}catch(NbtException){
fwrite(STDERR, "Invalid block palette file $argv[1]\n");
exit(1);
}
$report = generateBlockPaletteReport($states);
generateBlockIds(array_values($report->seenTypes));
generateBlockStateNames($report);
generateBlockStringValues($report);
echo "Done. Don't forget to run CS fixup after generating code.\n";

View File

@ -1,97 +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\build\generate_item_serializer_ids;
use pocketmine\errorhandler\ErrorToExceptionHandler;
use pocketmine\network\mcpe\convert\ItemTypeDictionaryFromDataHelper;
use pocketmine\network\mcpe\protocol\serializer\ItemTypeDictionary;
use pocketmine\utils\Utils;
use function asort;
use function count;
use function dirname;
use function explode;
use function fclose;
use function file_get_contents;
use function fopen;
use function fwrite;
use function strtoupper;
use const SORT_STRING;
use const STDERR;
require dirname(__DIR__) . '/vendor/autoload.php';
function constifyMcId(string $id) : string{
return strtoupper(explode(":", $id, 2)[1]);
}
function generateItemIds(ItemTypeDictionary $dictionary) : void{
$ids = [];
foreach($dictionary->getEntries() as $entry){
if($entry->getNumericId() < 256){ //blockitems are serialized via BlockStateSerializer
continue;
}
$ids[$entry->getStringId()] = $entry->getStringId();
}
asort($ids, SORT_STRING);
$file = ErrorToExceptionHandler::trapAndRemoveFalse(fn() => fopen(dirname(__DIR__) . '/src/data/bedrock/item/ItemTypeNames.php', 'wb'));
fwrite($file, <<<'HEADER'
<?php
declare(strict_types=1);
namespace pocketmine\data\bedrock\item;
/**
* This class is generated automatically from the item type dictionary for the current version. Do not edit it manually.
*/
final class ItemTypeNames{
HEADER
);
foreach(Utils::stringifyKeys($ids) as $id){
fwrite($file, "\tpublic const " . constifyMcId($id) . " = \"" . $id . "\";\n");
}
fwrite($file, "}\n");
fclose($file);
}
if(count($argv) !== 2){
fwrite(STDERR, "This script regenerates ItemTypeNames from a given item dictionary file\n");
fwrite(STDERR, "Required argument: path to item type dictionary file\n");
exit(1);
}
$raw = file_get_contents($argv[1]);
if($raw === false){
fwrite(STDERR, "Failed to read item type dictionary file\n");
exit(1);
}
$dictionary = ItemTypeDictionaryFromDataHelper::loadFromString($raw);
generateItemIds($dictionary);
echo "Done. Don't forget to run CS fixup after generating code.\n";

View File

@ -1,263 +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\build\generate_runtime_enum_serializers;
use pocketmine\block\utils\BellAttachmentType;
use pocketmine\block\utils\CopperOxidation;
use pocketmine\block\utils\CoralType;
use pocketmine\block\utils\DirtType;
use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\FroglightType;
use pocketmine\block\utils\LeverFacing;
use pocketmine\block\utils\MushroomBlockType;
use pocketmine\block\utils\SkullType;
use pocketmine\block\utils\SlabType;
use pocketmine\item\MedicineType;
use pocketmine\item\PotionType;
use pocketmine\item\SuspiciousStewType;
use function array_key_first;
use function array_keys;
use function array_map;
use function ceil;
use function count;
use function dirname;
use function file_put_contents;
use function implode;
use function ksort;
use function lcfirst;
use function log;
use function ob_get_clean;
use function ob_start;
use const SORT_STRING;
require dirname(__DIR__) . '/vendor/autoload.php';
/**
* @param string[] $memberNames
* @phpstan-param list<string> $memberNames
*
* @return string[]
* @phpstan-return list<string>
*/
function buildWriterFunc(string $virtualTypeName, string $nativeTypeName, array $memberNames, string $functionName) : array{
$bits = getBitsRequired($memberNames);
$lines = [];
$lines[] = "public function $functionName(\\$nativeTypeName &\$value) : void{";
$lines[] = "\t\$this->writeInt($bits, match(\$value){";
foreach($memberNames as $key => $memberName){
$lines[] = "\t\t$memberName => $key,";
}
$lines[] = "\t\tdefault => throw new \pocketmine\utils\AssumptionFailedError(\"All $virtualTypeName cases should be covered\")";
$lines[] = "\t});";
$lines[] = "}";
return $lines;
}
/**
* @param string[] $memberNames
* @phpstan-param list<string> $memberNames
*
* @return string[]
* @phpstan-return list<string>
*/
function buildReaderFunc(string $virtualTypeName, string $nativeTypeName, array $memberNames, string $functionName) : array{
$bits = getBitsRequired($memberNames);
$lines = [];
$lines[] = "public function $functionName(\\$nativeTypeName &\$value) : void{";
$lines[] = "\t\$value = match(\$this->readInt($bits)){";
foreach($memberNames as $key => $memberName){
$lines[] = "\t\t$key => $memberName,";
}
$lines[] = "\t\tdefault => throw new InvalidSerializedRuntimeDataException(\"Invalid serialized value for $virtualTypeName\")";
$lines[] = "\t};";
$lines[] = "}";
return $lines;
}
function buildInterfaceFunc(string $nativeTypeName, string $functionName) : string{
return "public function $functionName(\\$nativeTypeName &\$value) : void;";
}
/**
* @param string[] $memberNames
* @phpstan-param list<string> $memberNames
*
* @return string[]
* @phpstan-return list<string>
*/
function buildSizeCalculationFunc(string $nativeTypeName, string $functionName, array $memberNames) : array{
$lines = [];
$lines[] = "public function $functionName(\\$nativeTypeName &\$value) : void{";
$lines[] = "\t\$this->addBits(" . getBitsRequired($memberNames) . ");";
$lines[] = "}";
return $lines;
}
/**
* @param mixed[] $members
*/
function getBitsRequired(array $members) : int{
return (int) ceil(log(count($members), 2));
}
/**
* @param object[] $members
* @phpstan-param array<string, object> $members
*
* @return string[]
* @phpstan-return list<string>
*/
function stringifyEnumMembers(array $members, string $enumClass) : array{
ksort($members, SORT_STRING);
return array_map(fn(string $enumCaseName) => "\\$enumClass::$enumCaseName()", array_keys($members));
}
$enumsUsed = [
BellAttachmentType::getAll(),
CopperOxidation::getAll(),
CoralType::getAll(),
DirtType::getAll(),
DyeColor::getAll(),
FroglightType::getAll(),
LeverFacing::getAll(),
MedicineType::getAll(),
MushroomBlockType::getAll(),
SkullType::getAll(),
SlabType::getAll(),
SuspiciousStewType::getAll(),
PotionType::getAll()
];
$readerFuncs = [
"" => [
"abstract protected function readInt(int \$bits) : int;"
]
];
$writerFuncs = [
"" => [
"abstract protected function writeInt(int \$bits, int \$value) : void;"
]
];
$interfaceFuncs = [];
$sizeCalculationFuncs = [
"" => [
"abstract protected function addBits(int \$bits) : void;"
]
];
foreach($enumsUsed as $enumMembers){
if(count($enumMembers) === 0){
throw new \InvalidArgumentException("Enum members cannot be empty");
}
$reflect = new \ReflectionClass($enumMembers[array_key_first($enumMembers)]);
$virtualTypeName = $reflect->getShortName();
$nativeTypeName = $reflect->getName();
$functionName = lcfirst($virtualTypeName);
$stringifiedMembers = stringifyEnumMembers($enumMembers, $nativeTypeName);
$writerFuncs[$functionName] = buildWriterFunc(
$virtualTypeName,
$nativeTypeName,
$stringifiedMembers,
$functionName
);
$readerFuncs[$functionName] = buildReaderFunc(
$virtualTypeName,
$nativeTypeName,
$stringifiedMembers,
$functionName
);
$interfaceFuncs[$functionName] = [buildInterfaceFunc(
$nativeTypeName,
$functionName
)];
$sizeCalculationFuncs[$functionName] = buildSizeCalculationFunc(
$nativeTypeName,
$functionName,
$stringifiedMembers
);
}
/**
* @param string[][] $functions
* @phpstan-param array<string, list<string>> $functions
*/
function printFunctions(array $functions, string $className, string $classType) : void{
ksort($functions, SORT_STRING);
ob_start();
echo <<<'HEADER'
<?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\runtime;
/**
* This class is auto-generated. Do not edit it manually.
* @see build/generate-runtime-enum-serializers.php
*/
HEADER;
echo "$classType $className{\n\n";
echo implode("\n\n", array_map(fn(array $functionLines) => "\t" . implode("\n\t", $functionLines), $functions));
echo "\n\n}\n";
file_put_contents(dirname(__DIR__) . '/src/data/runtime/' . $className . '.php', ob_get_clean());
}
printFunctions($writerFuncs, "RuntimeEnumSerializerTrait", "trait");
printFunctions($readerFuncs, "RuntimeEnumDeserializerTrait", "trait");
printFunctions($interfaceFuncs, "RuntimeEnumDescriber", "interface");
printFunctions($sizeCalculationFuncs, "RuntimeEnumSizeCalculatorTrait", "trait");
echo "Done. Don't forget to run CS fixup after generating code.\n";

View File

@ -20,3 +20,12 @@ Released 21st February 2023.
- Fixed dropped items not despawning when in non-ticking chunks.
- Fixed dropped items not despawning if an infinite pickup delay is set.
- Fixed infinite despawn delay (never despawn) being ignored for dropped items.
# 4.15.2
Released 24th February 2023.
## General
- Accept Minecraft: Bedrock Edition 1.19.63 (identical protocol to 1.19.62, but different version due to Mojang mixup).
## Fixes
- Fixed `World Population` timer sometimes not being stopped, causing strange results in timings reports.

File diff suppressed because it is too large Load Diff

View File

@ -22,7 +22,7 @@
"ext-openssl": "*",
"ext-pcre": "*",
"ext-phar": "*",
"ext-pthreads": "^5.1",
"ext-pthreads": "^4.0",
"ext-reflection": "*",
"ext-simplexml": "*",
"ext-sockets": "*",
@ -34,25 +34,24 @@
"adhocore/json-comment": "^1.1",
"fgrosse/phpasn1": "^2.3",
"netresearch/jsonmapper": "^4.0",
"pocketmine/bedrock-block-upgrade-schema": "^1.0.0",
"pocketmine/bedrock-data": "dev-modern-world-support@dev",
"pocketmine/bedrock-item-upgrade-schema": "^1.0.0",
"pocketmine/bedrock-protocol": "~19.3.0+bedrock-1.19.62",
"pocketmine/bedrock-data": "~1.14.0+bedrock-1.19.60",
"pocketmine/bedrock-protocol": "~19.2.0+bedrock-1.19.62",
"pocketmine/binaryutils": "^0.2.1",
"pocketmine/callback-validator": "^1.0.2",
"pocketmine/classloader": "^0.3.0",
"pocketmine/classloader": "^0.2.0",
"pocketmine/color": "^0.3.0",
"pocketmine/errorhandler": "^0.6.0",
"pocketmine/locale-data": "~2.19.0",
"pocketmine/locale-data": "~2.18.0",
"pocketmine/log": "^0.4.0",
"pocketmine/log-pthreads": "^0.5.0",
"pocketmine/log-pthreads": "^0.4.0",
"pocketmine/math": "^0.4.0",
"pocketmine/nbt": "^0.3.2",
"pocketmine/raklib": "^0.15.0",
"pocketmine/raklib-ipc": "^0.2.0",
"pocketmine/snooze": "^0.4.0",
"pocketmine/raklib": "^0.14.2",
"pocketmine/raklib-ipc": "^0.1.0",
"pocketmine/snooze": "^0.3.0",
"ramsey/uuid": "^4.1",
"symfony/filesystem": "^5.4"
"symfony/filesystem": "^5.4",
"webmozart/path-util": "^2.3"
},
"require-dev": {
"phpstan/phpstan": "1.9.18",

297
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": "ea992cf9b9be39c9d5251b7769f9d044",
"content-hash": "a6622fa16daeb7ba4d9a792579db468f",
"packages": [
{
"name": "adhocore/json-comment",
@ -248,44 +248,18 @@
},
"time": "2022-12-08T20:46:14+00:00"
},
{
"name": "pocketmine/bedrock-block-upgrade-schema",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockBlockUpgradeSchema.git",
"reference": "a05ce434eb7f8c11058d26833bc975fe635b23b4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockBlockUpgradeSchema/zipball/a05ce434eb7f8c11058d26833bc975fe635b23b4",
"reference": "a05ce434eb7f8c11058d26833bc975fe635b23b4",
"shasum": ""
},
"type": "library",
"notification-url": "https://packagist.org/downloads/",
"license": [
"CC0-1.0"
],
"description": "Schemas describing how to upgrade saved block data in older Minecraft: Bedrock Edition world saves",
"support": {
"issues": "https://github.com/pmmp/BedrockBlockUpgradeSchema/issues",
"source": "https://github.com/pmmp/BedrockBlockUpgradeSchema/tree/1.0.0"
},
"time": "2023-02-01T21:09:54+00:00"
},
{
"name": "pocketmine/bedrock-data",
"version": "dev-modern-world-support",
"version": "1.14.0+bedrock-1.19.60",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockData.git",
"reference": "27cb4d5133d6cbe30018b759eb97e3fdc7036c3b"
"reference": "7b06234ec6e1f4fb06ad4b2f177e606c25df9b46"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/27cb4d5133d6cbe30018b759eb97e3fdc7036c3b",
"reference": "27cb4d5133d6cbe30018b759eb97e3fdc7036c3b",
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/7b06234ec6e1f4fb06ad4b2f177e606c25df9b46",
"reference": "7b06234ec6e1f4fb06ad4b2f177e606c25df9b46",
"shasum": ""
},
"type": "library",
@ -296,48 +270,22 @@
"description": "Blobs of data generated from Minecraft: Bedrock Edition, used by PocketMine-MP",
"support": {
"issues": "https://github.com/pmmp/BedrockData/issues",
"source": "https://github.com/pmmp/BedrockData/tree/modern-world-support"
"source": "https://github.com/pmmp/BedrockData/tree/bedrock-1.19.60"
},
"time": "2023-02-08T18:33:49+00:00"
},
{
"name": "pocketmine/bedrock-item-upgrade-schema",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockItemUpgradeSchema.git",
"reference": "7e53f77ea34ba30b1f94d3c24e64e19d3c4296e7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockItemUpgradeSchema/zipball/7e53f77ea34ba30b1f94d3c24e64e19d3c4296e7",
"reference": "7e53f77ea34ba30b1f94d3c24e64e19d3c4296e7",
"shasum": ""
},
"type": "library",
"notification-url": "https://packagist.org/downloads/",
"license": [
"CC0-1.0"
],
"description": "JSON schemas for upgrading items found in older Minecraft: Bedrock world saves",
"support": {
"issues": "https://github.com/pmmp/BedrockItemUpgradeSchema/issues",
"source": "https://github.com/pmmp/BedrockItemUpgradeSchema/tree/1.0.0"
},
"time": "2023-02-01T22:50:02+00:00"
"time": "2023-02-08T18:32:01+00:00"
},
{
"name": "pocketmine/bedrock-protocol",
"version": "19.3.0+bedrock-1.19.62",
"version": "19.2.0+bedrock-1.19.62",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockProtocol.git",
"reference": "a5bf4753c7f30f781c4541918e238f5bb637e7ad"
"reference": "a156db582d0b1a6c20c9d9cc9b1df7ef907efd0b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/a5bf4753c7f30f781c4541918e238f5bb637e7ad",
"reference": "a5bf4753c7f30f781c4541918e238f5bb637e7ad",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/a156db582d0b1a6c20c9d9cc9b1df7ef907efd0b",
"reference": "a156db582d0b1a6c20c9d9cc9b1df7ef907efd0b",
"shasum": ""
},
"require": {
@ -369,9 +317,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/19.3.0+bedrock-1.19.62"
"source": "https://github.com/pmmp/BedrockProtocol/tree/19.2.0+bedrock-1.19.62"
},
"time": "2023-02-19T16:11:03+00:00"
"time": "2023-02-17T16:32:49+00:00"
},
{
"name": "pocketmine/binaryutils",
@ -467,20 +415,20 @@
},
{
"name": "pocketmine/classloader",
"version": "0.3.0",
"version": "0.2.0",
"source": {
"type": "git",
"url": "https://github.com/pmmp/ClassLoader.git",
"reference": "407caf521186ec1f03024f39031cc681ad491026"
"reference": "49ea303993efdfb39cd302e2156d50aa78209e78"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/ClassLoader/zipball/407caf521186ec1f03024f39031cc681ad491026",
"reference": "407caf521186ec1f03024f39031cc681ad491026",
"url": "https://api.github.com/repos/pmmp/ClassLoader/zipball/49ea303993efdfb39cd302e2156d50aa78209e78",
"reference": "49ea303993efdfb39cd302e2156d50aa78209e78",
"shasum": ""
},
"require": {
"ext-pthreads": "^5.0",
"ext-pthreads": "~3.2.0 || ^4.0",
"ext-reflection": "*",
"php": "^8.0"
},
@ -489,8 +437,8 @@
},
"require-dev": {
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "1.9.4",
"phpstan/phpstan-strict-rules": "^1.0",
"phpstan/phpstan": "0.12.99",
"phpstan/phpstan-strict-rules": "^0.12.4",
"phpunit/phpunit": "^9.5"
},
"type": "library",
@ -506,9 +454,9 @@
"description": "Ad-hoc autoloading components used by PocketMine-MP",
"support": {
"issues": "https://github.com/pmmp/ClassLoader/issues",
"source": "https://github.com/pmmp/ClassLoader/tree/0.3.0"
"source": "https://github.com/pmmp/ClassLoader/tree/0.2.0"
},
"time": "2023-01-23T19:46:53+00:00"
"time": "2021-11-01T20:17:27+00:00"
},
{
"name": "pocketmine/color",
@ -589,16 +537,16 @@
},
{
"name": "pocketmine/locale-data",
"version": "2.19.0",
"version": "2.18.3",
"source": {
"type": "git",
"url": "https://github.com/pmmp/Language.git",
"reference": "f47d1687f21f09d2858f040873184a11746b1cf7"
"reference": "da25bfe9ee4822a84feb9b7e620c56ad4000aed0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/Language/zipball/f47d1687f21f09d2858f040873184a11746b1cf7",
"reference": "f47d1687f21f09d2858f040873184a11746b1cf7",
"url": "https://api.github.com/repos/pmmp/Language/zipball/da25bfe9ee4822a84feb9b7e620c56ad4000aed0",
"reference": "da25bfe9ee4822a84feb9b7e620c56ad4000aed0",
"shasum": ""
},
"type": "library",
@ -606,9 +554,9 @@
"description": "Language resources used by PocketMine-MP",
"support": {
"issues": "https://github.com/pmmp/Language/issues",
"source": "https://github.com/pmmp/Language/tree/2.19.0"
"source": "https://github.com/pmmp/Language/tree/2.18.3"
},
"time": "2023-02-13T13:55:22+00:00"
"time": "2023-01-17T21:43:36+00:00"
},
{
"name": "pocketmine/log",
@ -653,21 +601,21 @@
},
{
"name": "pocketmine/log-pthreads",
"version": "0.5.0",
"version": "0.4.0",
"source": {
"type": "git",
"url": "https://github.com/pmmp/LogPthreads.git",
"reference": "0ecfea6dcfc9a9f5c86e126ac1661732de5c5666"
"reference": "61f709e8cf36bcc24e4efe02acded680a1ce23cd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/LogPthreads/zipball/0ecfea6dcfc9a9f5c86e126ac1661732de5c5666",
"reference": "0ecfea6dcfc9a9f5c86e126ac1661732de5c5666",
"url": "https://api.github.com/repos/pmmp/LogPthreads/zipball/61f709e8cf36bcc24e4efe02acded680a1ce23cd",
"reference": "61f709e8cf36bcc24e4efe02acded680a1ce23cd",
"shasum": ""
},
"require": {
"ext-pthreads": "^5.0",
"php": "^8.0",
"ext-pthreads": "~3.2.0 || ^4.0",
"php": "^7.4 || ^8.0",
"pocketmine/log": "^0.4.0"
},
"conflict": {
@ -675,8 +623,8 @@
},
"require-dev": {
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "1.8.11",
"phpstan/phpstan-strict-rules": "^1.0"
"phpstan/phpstan": "0.12.88",
"phpstan/phpstan-strict-rules": "^0.12.4"
},
"type": "library",
"autoload": {
@ -691,9 +639,9 @@
"description": "Logging components specialized for pthreads used by PocketMine-MP and related projects",
"support": {
"issues": "https://github.com/pmmp/LogPthreads/issues",
"source": "https://github.com/pmmp/LogPthreads/tree/0.5.0"
"source": "https://github.com/pmmp/LogPthreads/tree/0.4.0"
},
"time": "2023-01-23T19:52:12+00:00"
"time": "2021-11-01T21:42:09+00:00"
},
{
"name": "pocketmine/math",
@ -780,16 +728,16 @@
},
{
"name": "pocketmine/raklib",
"version": "0.15.0",
"version": "0.14.5",
"source": {
"type": "git",
"url": "https://github.com/pmmp/RakLib.git",
"reference": "1f490cff6bf5e9eb46ebdbf7a7994d62be2bd2c1"
"reference": "85b4e5cb7117d37e010eeadb3ff53b21276c6f48"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/1f490cff6bf5e9eb46ebdbf7a7994d62be2bd2c1",
"reference": "1f490cff6bf5e9eb46ebdbf7a7994d62be2bd2c1",
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/85b4e5cb7117d37e010eeadb3ff53b21276c6f48",
"reference": "85b4e5cb7117d37e010eeadb3ff53b21276c6f48",
"shasum": ""
},
"require": {
@ -801,7 +749,7 @@
"pocketmine/log": "^0.3.0 || ^0.4.0"
},
"require-dev": {
"phpstan/phpstan": "1.9.17",
"phpstan/phpstan": "1.7.7",
"phpstan/phpstan-strict-rules": "^1.0"
},
"type": "library",
@ -817,33 +765,33 @@
"description": "A RakNet server implementation written in PHP",
"support": {
"issues": "https://github.com/pmmp/RakLib/issues",
"source": "https://github.com/pmmp/RakLib/tree/0.15.0"
"source": "https://github.com/pmmp/RakLib/tree/0.14.5"
},
"time": "2023-02-13T12:56:35+00:00"
"time": "2022-08-25T16:16:44+00:00"
},
{
"name": "pocketmine/raklib-ipc",
"version": "0.2.0",
"version": "0.1.1",
"source": {
"type": "git",
"url": "https://github.com/pmmp/RakLibIpc.git",
"reference": "26ed56fa9db06e4ca6e8920c0ede2e01e219bb9c"
"reference": "922a6444b0c6c7daaa5aa5a832107e1ec4738aed"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/RakLibIpc/zipball/26ed56fa9db06e4ca6e8920c0ede2e01e219bb9c",
"reference": "26ed56fa9db06e4ca6e8920c0ede2e01e219bb9c",
"url": "https://api.github.com/repos/pmmp/RakLibIpc/zipball/922a6444b0c6c7daaa5aa5a832107e1ec4738aed",
"reference": "922a6444b0c6c7daaa5aa5a832107e1ec4738aed",
"shasum": ""
},
"require": {
"php": "^8.0",
"php": "^7.4 || ^8.0",
"php-64bit": "*",
"pocketmine/binaryutils": "^0.2.0",
"pocketmine/raklib": "^0.15.0"
"pocketmine/raklib": "^0.13.1 || ^0.14.0"
},
"require-dev": {
"phpstan/phpstan": "1.9.17",
"phpstan/phpstan-strict-rules": "^1.0.0"
"phpstan/phpstan": "0.12.81",
"phpstan/phpstan-strict-rules": "^0.12.2"
},
"type": "library",
"autoload": {
@ -858,32 +806,32 @@
"description": "Channel-based protocols for inter-thread/inter-process communication with RakLib",
"support": {
"issues": "https://github.com/pmmp/RakLibIpc/issues",
"source": "https://github.com/pmmp/RakLibIpc/tree/0.2.0"
"source": "https://github.com/pmmp/RakLibIpc/tree/0.1.1"
},
"time": "2023-02-13T13:40:40+00:00"
"time": "2021-09-22T17:01:12+00:00"
},
{
"name": "pocketmine/snooze",
"version": "0.4.0",
"version": "0.3.1",
"source": {
"type": "git",
"url": "https://github.com/pmmp/Snooze.git",
"reference": "6b1d6cc645d674590ff9be2438ac00032f9ee292"
"reference": "0ac8fc2a781c419a1f64ebca4d5835028f59e29b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/Snooze/zipball/6b1d6cc645d674590ff9be2438ac00032f9ee292",
"reference": "6b1d6cc645d674590ff9be2438ac00032f9ee292",
"url": "https://api.github.com/repos/pmmp/Snooze/zipball/0ac8fc2a781c419a1f64ebca4d5835028f59e29b",
"reference": "0ac8fc2a781c419a1f64ebca4d5835028f59e29b",
"shasum": ""
},
"require": {
"ext-pthreads": "^5.0",
"php-64bit": "^8.0"
"ext-pthreads": "~3.2.0 || ^4.0",
"php-64bit": "^7.3 || ^8.0"
},
"require-dev": {
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "1.9.14",
"phpstan/phpstan-strict-rules": "^1.0"
"phpstan/phpstan": "0.12.99",
"phpstan/phpstan-strict-rules": "^0.12.4"
},
"type": "library",
"autoload": {
@ -898,9 +846,9 @@
"description": "Thread notification management library for code using the pthreads extension",
"support": {
"issues": "https://github.com/pmmp/Snooze/issues",
"source": "https://github.com/pmmp/Snooze/tree/0.4.0"
"source": "https://github.com/pmmp/Snooze/tree/0.3.1"
},
"time": "2023-01-23T19:43:19+00:00"
"time": "2021-11-01T20:50:08+00:00"
},
{
"name": "ramsey/collection",
@ -1474,6 +1422,115 @@
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "webmozart/assert",
"version": "1.11.0",
"source": {
"type": "git",
"url": "https://github.com/webmozarts/assert.git",
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
"shasum": ""
},
"require": {
"ext-ctype": "*",
"php": "^7.2 || ^8.0"
},
"conflict": {
"phpstan/phpstan": "<0.12.20",
"vimeo/psalm": "<4.6.1 || 4.6.2"
},
"require-dev": {
"phpunit/phpunit": "^8.5.13"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.10-dev"
}
},
"autoload": {
"psr-4": {
"Webmozart\\Assert\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "Assertions to validate method input/output with nice error messages.",
"keywords": [
"assert",
"check",
"validate"
],
"support": {
"issues": "https://github.com/webmozarts/assert/issues",
"source": "https://github.com/webmozarts/assert/tree/1.11.0"
},
"time": "2022-06-03T18:03:27+00:00"
},
{
"name": "webmozart/path-util",
"version": "2.3.0",
"source": {
"type": "git",
"url": "https://github.com/webmozart/path-util.git",
"reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725",
"reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"webmozart/assert": "~1.0"
},
"require-dev": {
"phpunit/phpunit": "^4.6",
"sebastian/version": "^1.0.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.3-dev"
}
},
"autoload": {
"psr-4": {
"Webmozart\\PathUtil\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.",
"support": {
"issues": "https://github.com/webmozart/path-util/issues",
"source": "https://github.com/webmozart/path-util/tree/2.3.0"
},
"abandoned": "symfony/filesystem",
"time": "2015-12-17T08:42:14+00:00"
}
],
"packages-dev": [
@ -3369,9 +3426,7 @@
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
"pocketmine/bedrock-data": 20
},
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
@ -3392,7 +3447,7 @@
"ext-openssl": "*",
"ext-pcre": "*",
"ext-phar": "*",
"ext-pthreads": "^5.1",
"ext-pthreads": "^4.0",
"ext-reflection": "*",
"ext-simplexml": "*",
"ext-sockets": "*",

View File

@ -1,6 +1,7 @@
includes:
- tests/phpstan/analyse-for-current-php-version.neon.php
- tests/phpstan/configs/actual-problems.neon
- tests/phpstan/configs/gc-hacks.neon
- tests/phpstan/configs/impossible-generics.neon
- tests/phpstan/configs/php-bugs.neon
- tests/phpstan/configs/phpstan-bugs.neon

File diff suppressed because it is too large Load Diff

View File

@ -37,6 +37,4 @@ define('pocketmine\PATH', dirname(__DIR__) . '/');
define('pocketmine\RESOURCE_PATH', dirname(__DIR__) . '/resources/');
define('pocketmine\BEDROCK_DATA_PATH', dirname(__DIR__) . '/vendor/pocketmine/bedrock-data/');
define('pocketmine\LOCALE_DATA_PATH', dirname(__DIR__) . '/vendor/pocketmine/locale-data/');
define('pocketmine\BEDROCK_BLOCK_UPGRADE_SCHEMA_PATH', dirname(__DIR__) . '/vendor/pocketmine/bedrock-block-upgrade-schema/');
define('pocketmine\BEDROCK_ITEM_UPGRADE_SCHEMA_PATH', dirname(__DIR__) . '/vendor/pocketmine/bedrock-item-upgrade-schema/');
define('pocketmine\COMPOSER_AUTOLOADER_PATH', dirname(__DIR__) . '/vendor/autoload.php');

View File

@ -281,8 +281,10 @@ class MemoryManager{
/**
* Static memory dumper accessible from any thread.
*
* @param mixed $startingObject
*/
public static function dumpMemory(mixed $startingObject, string $outputFolder, int $maxNesting, int $maxStringSize, \Logger $logger) : void{
public static function dumpMemory($startingObject, string $outputFolder, int $maxNesting, int $maxStringSize, \Logger $logger) : void{
$hardLimit = Utils::assumeNotFalse(ini_get('memory_limit'), "memory_limit INI directive should always exist");
ini_set('memory_limit', '-1');
gc_disable();
@ -473,6 +475,7 @@ class MemoryManager{
}
/**
* @param mixed $from
* @param object[] $objects reference parameter
* @param int[] $refCounts reference parameter
*
@ -480,8 +483,10 @@ class MemoryManager{
* @phpstan-param array<string, int> $refCounts
* @phpstan-param-out array<string, object> $objects
* @phpstan-param-out array<string, int> $refCounts
*
* @return mixed
*/
private static function continueDump(mixed $from, array &$objects, array &$refCounts, int $recursion, int $maxNesting, int $maxStringSize) : mixed{
private static function continueDump($from, array &$objects, array &$refCounts, int $recursion, int $maxNesting, int $maxStringSize){
if($maxNesting <= 0){
return "(error) NESTING LIMIT REACHED";
}

View File

@ -122,8 +122,8 @@ namespace pocketmine {
if(substr_count($pthreads_version, ".") < 2){
$pthreads_version = "0.$pthreads_version";
}
if(version_compare($pthreads_version, "5.1.0") < 0 || version_compare($pthreads_version, "6.0.0") >= 0){
$messages[] = "pthreads ^5.0.0 is required, while you have $pthreads_version.";
if(version_compare($pthreads_version, "4.0.0") < 0 || version_compare($pthreads_version, "5.0.0") >= 0){
$messages[] = "pthreads ^4.0.0 is required, while you have $pthreads_version.";
}
}

View File

@ -491,7 +491,10 @@ class Server{
return $this->configGroup->getPropertyBool("player.save-player-data", true);
}
public function getOfflinePlayer(string $name) : Player|OfflinePlayer|null{
/**
* @return OfflinePlayer|Player
*/
public function getOfflinePlayer(string $name){
$name = strtolower($name);
$result = $this->getPlayerExact($name);
@ -580,7 +583,8 @@ class Server{
},
function() use ($playerPromiseResolver, $session) : void{
if($session->isConnected()){
$session->disconnectWithError(KnownTranslationFactory::pocketmine_disconnect_error_respawn());
//TODO: this needs to be localized - this might be reached if the spawn world was unloaded while the player was logging in
$session->disconnect("Failed to find a safe spawn location");
}
$playerPromiseResolver->reject();
}
@ -955,7 +959,7 @@ class Server{
$this->commandMap = new SimpleCommandMap($this);
$this->craftingManager = CraftingManagerFromDataHelper::make(Path::join(\pocketmine\BEDROCK_DATA_PATH, "recipes"));
$this->craftingManager = CraftingManagerFromDataHelper::make(Path::join(\pocketmine\BEDROCK_DATA_PATH, "recipes.json"));
$this->resourceManager = new ResourcePackManager(Path::join($this->getDataPath(), "resource_packs"), $this->logger);
@ -1351,7 +1355,6 @@ class Server{
return false;
}
$recipients = $ev->getTargets();
$packets = $ev->getPackets();
/** @var PacketBroadcaster[] $broadcasters */
$broadcasters = [];
@ -1526,7 +1529,7 @@ class Server{
* @param mixed[][]|null $trace
* @phpstan-param list<array<string, mixed>>|null $trace
*/
public function exceptionHandler(\Throwable $e, ?array $trace = null) : void{
public function exceptionHandler(\Throwable $e, $trace = null) : void{
while(@ob_end_flush()){}
global $lastError;

View File

@ -43,7 +43,12 @@ final class ServerConfigGroup{
private Config $serverProperties
){}
public function getProperty(string $variable, mixed $defaultValue = null) : mixed{
/**
* @param mixed $defaultValue
*
* @return mixed
*/
public function getProperty(string $variable, $defaultValue = null){
if(!array_key_exists($variable, $this->propertyCache)){
$v = getopt("", ["$variable::"]);
if(isset($v[$variable])){

View File

@ -31,9 +31,9 @@ use function str_repeat;
final class VersionInfo{
public const NAME = "PocketMine-MP";
public const BASE_VERSION = "5.0.0-ALPHA9";
public const BASE_VERSION = "4.15.2";
public const IS_DEVELOPMENT_BUILD = false;
public const BUILD_CHANNEL = "alpha";
public const BUILD_CHANNEL = "stable";
private function __construct(){
//NOOP

View File

@ -24,22 +24,17 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\inventory\AnvilInventory;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\block\utils\Fallable;
use pocketmine\block\utils\FallableTrait;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\entity\object\FallingBlock;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
use pocketmine\world\sound\AnvilFallSound;
use pocketmine\world\sound\Sound;
use function lcg_value;
use function round;
class Anvil extends Transparent implements Fallable{
use FallableTrait;
@ -51,12 +46,21 @@ class Anvil extends Transparent implements Fallable{
private int $damage = self::UNDAMAGED;
protected function describeType(RuntimeDataDescriber $w) : void{
$w->boundedInt(2, self::UNDAMAGED, self::VERY_DAMAGED, $this->damage);
protected function writeStateToMeta() : int{
return BlockDataSerializer::writeLegacyHorizontalFacing($this->facing) | ($this->damage << 2);
}
protected function describeState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing);
public function readStateFromData(int $id, int $stateMeta) : void{
$this->facing = BlockDataSerializer::readLegacyHorizontalFacing($stateMeta & 0x3);
$this->damage = BlockDataSerializer::readBoundedInt("damage", $stateMeta >> 2, self::UNDAMAGED, self::VERY_DAMAGED);
}
public function getStateBitmask() : int{
return 0b1111;
}
protected function writeStateToItemMeta() : int{
return $this->damage << 2;
}
public function getDamage() : int{ return $this->damage; }
@ -81,7 +85,7 @@ class Anvil extends Transparent implements Fallable{
return SupportType::NONE();
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player instanceof Player){
$player->setCurrentWindow(new AnvilInventory($this->position));
}
@ -96,18 +100,7 @@ class Anvil extends Transparent implements Fallable{
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function onHitGround(FallingBlock $blockEntity) : bool{
if(lcg_value() < 0.05 + (round($blockEntity->getFallDistance()) - 1) * 0.05){
if($this->damage !== self::VERY_DAMAGED){
$this->damage = $this->damage + 1;
}else{
return false;
}
}
return true;
}
public function getLandSound() : ?Sound{
return new AnvilFallSound();
public function tickFalling() : ?Block{
return null;
}
}

View File

@ -23,13 +23,12 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\event\block\StructureGrowEvent;
use pocketmine\item\Bamboo as ItemBamboo;
use pocketmine\item\Fertilizer;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
@ -55,10 +54,18 @@ class Bamboo extends Transparent{
protected bool $ready = false;
protected int $leafSize = self::NO_LEAVES;
protected function describeState(RuntimeDataDescriber $w) : void{
$w->boundedInt(2, self::NO_LEAVES, self::LARGE_LEAVES, $this->leafSize);
$w->bool($this->thick);
$w->bool($this->ready);
public function readStateFromData(int $id, int $stateMeta) : void{
$this->thick = ($stateMeta & BlockLegacyMetadata::BAMBOO_FLAG_THICK) !== 0;
$this->leafSize = BlockDataSerializer::readBoundedInt("leafSize", ($stateMeta >> BlockLegacyMetadata::BAMBOO_LEAF_SIZE_SHIFT) & BlockLegacyMetadata::BAMBOO_LEAF_SIZE_MASK, self::NO_LEAVES, self::LARGE_LEAVES);
$this->ready = ($stateMeta & BlockLegacyMetadata::BAMBOO_FLAG_READY) !== 0;
}
public function writeStateToMeta() : int{
return ($this->thick ? BlockLegacyMetadata::BAMBOO_FLAG_THICK : 0) | ($this->leafSize << BlockLegacyMetadata::BAMBOO_LEAF_SIZE_SHIFT) | ($this->ready ? BlockLegacyMetadata::BAMBOO_FLAG_READY : 0);
}
public function getStateBitmask() : int{
return 0b1111;
}
public function isThick() : bool{ return $this->thick; }
@ -121,11 +128,14 @@ class Bamboo extends Transparent{
}
private function canBeSupportedBy(Block $block) : bool{
//TODO: tags would be better for this
return
$block->getTypeId() === BlockTypeIds::GRAVEL ||
$block->hasTypeTag(BlockTypeTags::DIRT) ||
$block->hasTypeTag(BlockTypeTags::MUD) ||
$block->hasTypeTag(BlockTypeTags::SAND);
$block instanceof Dirt ||
$block instanceof Grass ||
$block instanceof Gravel ||
$block instanceof Sand ||
$block instanceof Mycelium ||
$block instanceof Podzol;
}
private function seekToTop() : Bamboo{
@ -137,7 +147,7 @@ class Bamboo extends Transparent{
return $top;
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($item instanceof Fertilizer){
$top = $this->seekToTop();
if($top->grow(self::getMaxHeight($top->position->getFloorX(), $top->position->getFloorZ()), mt_rand(1, 2), $player)){
@ -233,8 +243,4 @@ class Bamboo extends Transparent{
$world->setBlock($this->position, $this);
}
}
public function asItem() : Item{
return VanillaItems::BAMBOO();
}
}

View File

@ -23,23 +23,28 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\event\block\StructureGrowEvent;
use pocketmine\item\Bamboo as ItemBamboo;
use pocketmine\item\Fertilizer;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
final class BambooSapling extends Flowable{
private bool $ready = false;
protected function describeState(RuntimeDataDescriber $w) : void{
$w->bool($this->ready);
public function readStateFromData(int $id, int $stateMeta) : void{
$this->ready = ($stateMeta & BlockLegacyMetadata::BAMBOO_SAPLING_FLAG_READY) !== 0;
}
protected function writeStateToMeta() : int{
return $this->ready ? BlockLegacyMetadata::BAMBOO_SAPLING_FLAG_READY : 0;
}
public function getStateBitmask() : int{ return 0b1; }
public function isReady() : bool{ return $this->ready; }
/** @return $this */
@ -49,11 +54,14 @@ final class BambooSapling extends Flowable{
}
private function canBeSupportedBy(Block $block) : bool{
//TODO: tags would be better for this
return
$block->getTypeId() === BlockTypeIds::GRAVEL ||
$block->hasTypeTag(BlockTypeTags::DIRT) ||
$block->hasTypeTag(BlockTypeTags::MUD) ||
$block->hasTypeTag(BlockTypeTags::SAND);
$block instanceof Dirt ||
$block instanceof Grass ||
$block instanceof Gravel ||
$block instanceof Sand ||
$block instanceof Mycelium ||
$block instanceof Podzol;
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
@ -63,7 +71,7 @@ final class BambooSapling extends Flowable{
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($item instanceof Fertilizer || $item instanceof ItemBamboo){
if($this->grow($player)){
$item->pop();
@ -118,6 +126,6 @@ final class BambooSapling extends Flowable{
}
public function asItem() : Item{
return VanillaItems::BAMBOO();
return VanillaBlocks::BAMBOO()->asItem();
}
}

View File

@ -25,7 +25,7 @@ namespace pocketmine\block;
use pocketmine\block\tile\Barrel as TileBarrel;
use pocketmine\block\utils\AnyFacingTrait;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\item\Item;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
@ -38,9 +38,17 @@ class Barrel extends Opaque{
protected bool $open = false;
protected function describeState(RuntimeDataDescriber $w) : void{
$w->facing($this->facing);
$w->bool($this->open);
protected function writeStateToMeta() : int{
return BlockDataSerializer::writeFacing($this->facing) | ($this->open ? BlockLegacyMetadata::BARREL_FLAG_OPEN : 0);
}
public function readStateFromData(int $id, int $stateMeta) : void{
$this->facing = BlockDataSerializer::readFacing($stateMeta & 0x07);
$this->open = ($stateMeta & BlockLegacyMetadata::BARREL_FLAG_OPEN) === BlockLegacyMetadata::BARREL_FLAG_OPEN;
}
public function getStateBitmask() : int{
return 0b1111;
}
public function isOpen() : bool{
@ -73,7 +81,7 @@ class Barrel extends Opaque{
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player instanceof Player){
$barrel = $this->position->getWorld()->getTile($this->position);
if($barrel instanceof TileBarrel){

View File

@ -28,9 +28,9 @@ use pocketmine\block\utils\BannerPatternLayer;
use pocketmine\block\utils\ColoredTrait;
use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\SupportType;
use pocketmine\data\bedrock\DyeColorIdMap;
use pocketmine\item\Banner as ItemBanner;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
@ -48,20 +48,18 @@ abstract class BaseBanner extends Transparent{
*/
protected array $patterns = [];
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
$this->color = DyeColor::BLACK();
parent::__construct($idInfo, $name, $typeInfo);
parent::__construct($idInfo, $name, $breakInfo);
}
public function readStateFromWorld() : Block{
public function readStateFromWorld() : void{
parent::readStateFromWorld();
$tile = $this->position->getWorld()->getTile($this->position);
if($tile instanceof TileBanner){
$this->color = $tile->getBaseColor();
$this->setPatterns($tile->getPatterns());
}
return $this;
}
public function writeStateToWorld() : void{
@ -138,6 +136,10 @@ abstract class BaseBanner extends Transparent{
}
}
protected function writeStateToItemMeta() : int{
return DyeColorIdMap::getInstance()->toInvertedId($this->color);
}
public function getDropsForCompatibleTool(Item $item) : array{
$drop = $this->asItem();
if($drop instanceof ItemBanner && count($this->patterns) > 0){
@ -154,8 +156,4 @@ abstract class BaseBanner extends Transparent{
}
return $result;
}
public function asItem() : Item{
return VanillaItems::BANNER()->setColor($this->color);
}
}

View File

@ -1,89 +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\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, array &$returnedItems = []) : 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

@ -28,28 +28,34 @@ use pocketmine\block\utils\CoralTypeTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\event\block\BlockDeathEvent;
use pocketmine\item\Item;
use function mt_rand;
abstract class BaseCoral extends Transparent{
use CoralTypeTrait;
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
parent::__construct($idInfo, $name, $typeInfo);
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
parent::__construct($idInfo, $name, $breakInfo);
$this->coralType = CoralType::TUBE();
}
public function onNearbyBlockChange() : void{
if(!$this->dead){
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, mt_rand(40, 200));
}
}
$world = $this->position->getWorld();
public function onScheduledUpdate() : void{
if(!$this->dead && !$this->isCoveredWithWater()){
$ev = new BlockDeathEvent($this, $this->setDead(true));
$ev->call();
if(!$ev->isCancelled()){
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
$hasWater = false;
foreach($this->position->sides() as $vector3){
if($world->getBlock($vector3) instanceof Water){
$hasWater = true;
break;
}
}
//TODO: check water inside the block itself (not supported on the API yet)
if(!$hasWater){
$ev = new BlockDeathEvent($this, $this->setDead(true));
$ev->call();
if(!$ev->isCancelled()){
$world->setBlock($this->position, $ev->getNewState());
}
}
}
}
@ -64,21 +70,6 @@ abstract class BaseCoral extends Transparent{
public function isSolid() : bool{ return false; }
protected function isCoveredWithWater() : bool{
$world = $this->position->getWorld();
$hasWater = false;
foreach($this->position->sides() as $vector3){
if($world->getBlock($vector3) instanceof Water){
$hasWater = true;
break;
}
}
//TODO: check water inside the block itself (not supported on the API yet)
return $hasWater;
}
protected function recalculateCollisionBoxes() : array{ return []; }
public function getSupportType(int $facing) : SupportType{

View File

@ -1,63 +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\block;
use pocketmine\entity\Entity;
use pocketmine\entity\projectile\Arrow;
use pocketmine\event\entity\EntityCombustByBlockEvent;
use pocketmine\event\entity\EntityDamageByBlockEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\item\Item;
abstract class BaseFire extends Flowable{
public function hasEntityCollision() : bool{
return true;
}
public function canBeReplaced() : bool{
return true;
}
public function onEntityInside(Entity $entity) : bool{
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_FIRE, $this->getFireDamage());
$entity->attack($ev);
$ev = new EntityCombustByBlockEvent($this, $entity, 8);
if($entity instanceof Arrow){
$ev->cancel();
}
$ev->call();
if(!$ev->isCancelled()){
$entity->setOnFire($ev->getDuration());
}
return true;
}
abstract protected function getFireDamage() : int;
public function getDropsForCompatibleTool(Item $item) : array{
return [];
}
}

View File

@ -24,55 +24,35 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\tile\Sign as TileSign;
use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\SignText;
use pocketmine\block\utils\SupportType;
use pocketmine\block\utils\WoodType;
use pocketmine\block\utils\WoodTypeTrait;
use pocketmine\color\Color;
use pocketmine\event\block\SignChangeEvent;
use pocketmine\item\Dye;
use pocketmine\item\Item;
use pocketmine\item\ItemTypeIds;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\utils\TextFormat;
use pocketmine\world\BlockTransaction;
use pocketmine\world\sound\DyeUseSound;
use pocketmine\world\sound\InkSacUseSound;
use function array_map;
use function assert;
use function strlen;
abstract class BaseSign extends Transparent{
use WoodTypeTrait;
protected SignText $text;
protected ?int $editorEntityRuntimeId = null;
/** @var \Closure() : Item */
private \Closure $asItemCallback;
/**
* @param \Closure() : Item $asItemCallback
*/
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo, WoodType $woodType, \Closure $asItemCallback){
$this->woodType = $woodType;
parent::__construct($idInfo, $name, $typeInfo);
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
parent::__construct($idInfo, $name, $breakInfo);
$this->text = new SignText();
$this->asItemCallback = $asItemCallback;
}
public function readStateFromWorld() : Block{
public function readStateFromWorld() : void{
parent::readStateFromWorld();
$tile = $this->position->getWorld()->getTile($this->position);
if($tile instanceof TileSign){
$this->text = $tile->getText();
$this->editorEntityRuntimeId = $tile->getEditorEntityRuntimeId();
}
return $this;
}
public function writeStateToWorld() : void{
@ -105,7 +85,7 @@ abstract class BaseSign extends Transparent{
abstract protected function getSupportingFace() : int;
public function onNearbyBlockChange() : void{
if($this->getSide($this->getSupportingFace())->getTypeId() === BlockTypeIds::AIR){
if($this->getSide($this->getSupportingFace())->getId() === BlockLegacyIds::AIR){
$this->position->getWorld()->useBreakOn($this->position);
}
}
@ -117,55 +97,6 @@ abstract class BaseSign extends Transparent{
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
private function doSignChange(SignText $newText, Player $player, Item $item) : bool{
$ev = new SignChangeEvent($this, $player, $newText);
$ev->call();
if(!$ev->isCancelled()){
$this->text = $ev->getNewText();
$this->position->getWorld()->setBlock($this->position, $this);
$item->pop();
return true;
}
return false;
}
private function changeSignGlowingState(bool $glowing, Player $player, Item $item) : bool{
if($this->text->isGlowing() !== $glowing && $this->doSignChange(new SignText($this->text->getLines(), $this->text->getBaseColor(), $glowing), $player, $item)){
$this->position->getWorld()->addSound($this->position, new InkSacUseSound());
return true;
}
return false;
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player === null){
return false;
}
$dyeColor = $item instanceof Dye ? $item->getColor() : match($item->getTypeId()){
ItemTypeIds::BONE_MEAL => DyeColor::WHITE(),
ItemTypeIds::LAPIS_LAZULI => DyeColor::BLUE(),
ItemTypeIds::COCOA_BEANS => DyeColor::BROWN(),
default => null
};
if($dyeColor !== null){
$color = $dyeColor->equals(DyeColor::BLACK()) ? new Color(0, 0, 0) : $dyeColor->getRgbValue();
if($color->toARGB() === $this->text->getBaseColor()->toARGB()){
return false;
}
if($this->doSignChange(new SignText($this->text->getLines(), $color, $this->text->isGlowing()), $player, $item)){
$this->position->getWorld()->addSound($this->position, new DyeUseSound());
return true;
}
}elseif($item->getTypeId() === ItemTypeIds::INK_SAC){
return $this->changeSignGlowingState(false, $player, $item);
}elseif($item->getTypeId() === ItemTypeIds::GLOW_INK_SAC){
return $this->changeSignGlowingState(true, $player, $item);
}
return false;
}
/**
* Returns an object containing information about the sign text.
*/
@ -208,8 +139,4 @@ abstract class BaseSign extends Transparent{
return false;
}
public function asItem() : Item{
return ($this->asItemCallback)();
}
}

View File

@ -24,11 +24,12 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\tile\Bed as TileBed;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\block\utils\ColoredTrait;
use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\data\bedrock\DyeColorIdMap;
use pocketmine\entity\Entity;
use pocketmine\entity\Living;
use pocketmine\item\Item;
@ -48,26 +49,34 @@ class Bed extends Transparent{
protected bool $occupied = false;
protected bool $head = false;
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
$this->color = DyeColor::RED();
parent::__construct($idInfo, $name, $typeInfo);
parent::__construct($idInfo, $name, $breakInfo);
}
protected function describeState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing);
$w->bool($this->occupied);
$w->bool($this->head);
protected function writeStateToMeta() : int{
return BlockDataSerializer::writeLegacyHorizontalFacing($this->facing) |
($this->occupied ? BlockLegacyMetadata::BED_FLAG_OCCUPIED : 0) |
($this->head ? BlockLegacyMetadata::BED_FLAG_HEAD : 0);
}
public function readStateFromWorld() : Block{
public function readStateFromData(int $id, int $stateMeta) : void{
$this->facing = BlockDataSerializer::readLegacyHorizontalFacing($stateMeta & 0x03);
$this->occupied = ($stateMeta & BlockLegacyMetadata::BED_FLAG_OCCUPIED) !== 0;
$this->head = ($stateMeta & BlockLegacyMetadata::BED_FLAG_HEAD) !== 0;
}
public function getStateBitmask() : int{
return 0b1111;
}
public function readStateFromWorld() : void{
parent::readStateFromWorld();
//read extra state information from the tile - this is an ugly hack
$tile = $this->position->getWorld()->getTile($this->position);
if($tile instanceof TileBed){
$this->color = $tile->getColor();
}
return $this;
}
public function writeStateToWorld() : void{
@ -123,7 +132,7 @@ class Bed extends Transparent{
return null;
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){
$other = $this->getOtherHalf();
$playerPos = $player->getPosition();
@ -200,6 +209,10 @@ class Bed extends Transparent{
return [];
}
protected function writeStateToItemMeta() : int{
return DyeColorIdMap::getInstance()->toId($this->color);
}
public function getAffectedBlocks() : array{
if(($other = $this->getOtherHalf()) !== null){
return [$this, $other];
@ -211,6 +224,4 @@ class Bed extends Transparent{
private function canBeSupportedBy(Block $block) : bool{
return !$block->getSupportType(Facing::UP)->equals(SupportType::NONE());
}
public function getMaxStackSize() : int{ return 1; }
}

View File

@ -23,13 +23,20 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\data\runtime\RuntimeDataDescriber;
class Bedrock extends Opaque{
private bool $burnsForever = false;
protected function describeState(RuntimeDataDescriber $w) : void{
$w->bool($this->burnsForever);
public function readStateFromData(int $id, int $stateMeta) : void{
$this->burnsForever = ($stateMeta & BlockLegacyMetadata::BEDROCK_FLAG_INFINIBURN) !== 0;
}
protected function writeStateToMeta() : int{
return $this->burnsForever ? BlockLegacyMetadata::BEDROCK_FLAG_INFINIBURN : 0;
}
public function getStateBitmask() : int{
return 0b1;
}
public function burnsForever() : bool{

View File

@ -42,7 +42,7 @@ class Beetroot extends Crops{
];
}
public function asItem() : Item{
public function getPickedItem(bool $addUserData = false) : Item{
return VanillaItems::BEETROOT_SEEDS();
}
}

View File

@ -25,16 +25,16 @@ namespace pocketmine\block;
use pocketmine\block\tile\Bell as TileBell;
use pocketmine\block\utils\BellAttachmentType;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\InvalidBlockStateException;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\entity\projectile\Projectile;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\RayTraceResult;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\world\BlockTransaction;
use pocketmine\world\sound\BellRingSound;
@ -43,14 +43,41 @@ final class Bell extends Transparent{
private BellAttachmentType $attachmentType;
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
$this->attachmentType = BellAttachmentType::FLOOR();
parent::__construct($idInfo, $name, $typeInfo);
parent::__construct($idInfo, $name, $breakInfo);
}
protected function describeState(RuntimeDataDescriber $w) : void{
$w->bellAttachmentType($this->attachmentType);
$w->horizontalFacing($this->facing);
public function readStateFromData(int $id, int $stateMeta) : void{
$this->setFacing(BlockDataSerializer::readLegacyHorizontalFacing($stateMeta & 0x03));
$attachmentType = [
BlockLegacyMetadata::BELL_ATTACHMENT_FLOOR => BellAttachmentType::FLOOR(),
BlockLegacyMetadata::BELL_ATTACHMENT_CEILING => BellAttachmentType::CEILING(),
BlockLegacyMetadata::BELL_ATTACHMENT_ONE_WALL => BellAttachmentType::ONE_WALL(),
BlockLegacyMetadata::BELL_ATTACHMENT_TWO_WALLS => BellAttachmentType::TWO_WALLS()
][($stateMeta >> 2) & 0b11] ?? null;
if($attachmentType === null){
throw new InvalidBlockStateException("No such attachment type");
}
$this->setAttachmentType($attachmentType);
}
public function writeStateToMeta() : int{
$attachmentTypeMeta = [
BellAttachmentType::FLOOR()->id() => BlockLegacyMetadata::BELL_ATTACHMENT_FLOOR,
BellAttachmentType::CEILING()->id() => BlockLegacyMetadata::BELL_ATTACHMENT_CEILING,
BellAttachmentType::ONE_WALL()->id() => BlockLegacyMetadata::BELL_ATTACHMENT_ONE_WALL,
BellAttachmentType::TWO_WALLS()->id() => BlockLegacyMetadata::BELL_ATTACHMENT_TWO_WALLS
][$this->getAttachmentType()->id()] ?? null;
if($attachmentTypeMeta === null){
throw new AssumptionFailedError("Mapping should cover all cases");
}
return BlockDataSerializer::writeLegacyHorizontalFacing($this->getFacing()) | ($attachmentTypeMeta << 2);
}
public function getStateBitmask() : int{
return 0b1111;
}
protected function recalculateCollisionBoxes() : array{
@ -130,10 +157,17 @@ final class Bell extends Transparent{
}
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){
$faceHit = Facing::opposite($player->getHorizontalFacing());
if($this->isValidFaceToRing($faceHit)){
if(
$this->attachmentType->equals(BellAttachmentType::CEILING()) ||
($this->attachmentType->equals(BellAttachmentType::FLOOR()) && Facing::axis($faceHit) === Facing::axis($this->facing)) ||
(
($this->attachmentType->equals(BellAttachmentType::ONE_WALL()) || $this->attachmentType->equals(BellAttachmentType::TWO_WALLS())) &&
($faceHit === Facing::rotateY($this->facing, false) || $faceHit === Facing::rotateY($this->facing, true))
)
){
$this->ring($faceHit);
return true;
}
@ -142,13 +176,6 @@ final class Bell extends Transparent{
return false;
}
public function onProjectileHit(Projectile $projectile, RayTraceResult $hitResult) : void{
$faceHit = Facing::opposite($projectile->getHorizontalFacing());
if($this->isValidFaceToRing($faceHit)){
$this->ring($faceHit);
}
}
public function ring(int $faceHit) : void{
$world = $this->position->getWorld();
$world->addSound($this->position, new BellRingSound());
@ -157,15 +184,4 @@ final class Bell extends Transparent{
$world->broadcastPacketToViewers($this->position, $tile->createFakeUpdatePacket($faceHit));
}
}
private function isValidFaceToRing(int $faceHit) : bool{
return (
$this->attachmentType->equals(BellAttachmentType::CEILING()) ||
($this->attachmentType->equals(BellAttachmentType::FLOOR()) && Facing::axis($faceHit) === Facing::axis($this->facing)) ||
(
($this->attachmentType->equals(BellAttachmentType::ONE_WALL()) || $this->attachmentType->equals(BellAttachmentType::TWO_WALLS())) &&
($faceHit === Facing::rotateY($this->facing, false) || $faceHit === Facing::rotateY($this->facing, true))
)
);
}
}

View File

@ -28,61 +28,49 @@ namespace pocketmine\block;
use pocketmine\block\tile\Spawnable;
use pocketmine\block\tile\Tile;
use pocketmine\block\utils\InvalidBlockStateException;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\data\runtime\RuntimeDataReader;
use pocketmine\data\runtime\RuntimeDataSizeCalculator;
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;
use pocketmine\item\ItemFactory;
use pocketmine\math\Axis;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\RayTraceResult;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\player\Player;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\world\BlockTransaction;
use pocketmine\world\format\Chunk;
use pocketmine\world\Position;
use pocketmine\world\World;
use function assert;
use function count;
use function get_class;
use function dechex;
use const PHP_INT_MAX;
class Block{
public const INTERNAL_STATE_DATA_BITS = 9;
public const INTERNAL_STATE_DATA_MASK = ~(~0 << self::INTERNAL_STATE_DATA_BITS);
public const INTERNAL_METADATA_BITS = 4;
public const INTERNAL_METADATA_MASK = ~(~0 << self::INTERNAL_METADATA_BITS);
protected BlockIdentifier $idInfo;
protected string $fallbackName;
protected BlockTypeInfo $typeInfo;
protected BlockBreakInfo $breakInfo;
protected Position $position;
/** @var AxisAlignedBB[]|null */
protected ?array $collisionBoxes = null;
/**
* @var int[]
* @phpstan-var array<string, int>
*/
private static array $typeDataBits = [];
/**
* @var int[]
* @phpstan-var array<string, int>
*/
private static array $stateDataBits = [];
/**
* @param string $name English name of the block type (TODO: implement translations)
*/
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
if(($idInfo->getVariant() & $this->getStateBitmask()) !== 0){
throw new \InvalidArgumentException("Variant 0x" . dechex($idInfo->getVariant()) . " collides with state bitmask 0x" . dechex($this->getStateBitmask()));
}
$this->idInfo = $idInfo;
$this->fallbackName = $name;
$this->typeInfo = $typeInfo;
$this->breakInfo = $breakInfo;
$this->position = new Position(0, 0, 0, null);
}
@ -91,8 +79,8 @@ class Block{
}
/**
* Returns an object containing information about how to identify and store this block type, such as type ID and
* tile type (if any).
* Returns an object containing information about how to identify and store this block type, such as its legacy
* numeric ID(s), tile type (if any), and legacy variant metadata.
*/
public function getIdInfo() : BlockIdentifier{
return $this->idInfo;
@ -105,16 +93,25 @@ class Block{
return $this->fallbackName;
}
/**
* @deprecated
*
* Returns the legacy numeric Minecraft block ID.
*/
public function getId() : int{
return $this->idInfo->getBlockId();
}
/**
* @internal
*
* Returns the full blockstate ID of this block. This is a compact way of representing a blockstate used to store
* blocks in chunks at runtime.
*
* This ID can be used to later obtain a copy of this block using {@link RuntimeBlockStateRegistry::fromStateId()}.
* This ID can be used to later obtain a copy of this block using {@link BlockFactory::get()}.
*/
public function getStateId() : int{
return ($this->getTypeId() << self::INTERNAL_STATE_DATA_BITS) | $this->computeStateData();
public function getFullId() : int{
return ($this->getId() << self::INTERNAL_METADATA_BITS) | $this->getMeta();
}
/**
@ -123,102 +120,44 @@ class Block{
* Type information such as colour, wood type, etc. is preserved.
*/
public function asItem() : Item{
return new ItemBlock($this);
}
final public function getRequiredTypeDataBits() : int{
$class = get_class($this);
if(isset(self::$typeDataBits[$class])){
return self::$typeDataBits[$class];
}
$calculator = new RuntimeDataSizeCalculator();
$this->describeType($calculator);
return self::$typeDataBits[$class] = $calculator->getBitsUsed();
}
final public function getRequiredStateDataBits() : int{
$class = get_class($this);
if(isset(self::$stateDataBits[$class])){
return self::$stateDataBits[$class];
}
$calculator = new RuntimeDataSizeCalculator();
$this->describeState($calculator);
return self::$stateDataBits[$class] = $calculator->getBitsUsed();
return ItemFactory::getInstance()->get(
$this->idInfo->getItemId(),
$this->idInfo->getVariant() | $this->writeStateToItemMeta()
);
}
/**
* @internal
* @deprecated
*
* Returns the legacy Minecraft block meta value. This is a mixed-purpose value, which is used to store different
* things for different blocks.
*/
final public function decodeTypeData(int $data) : void{
$typeBits = $this->getRequiredTypeDataBits();
$givenBits = $typeBits;
$reader = new RuntimeDataReader($givenBits, $data);
public function getMeta() : int{
$stateMeta = $this->writeStateToMeta();
assert(($stateMeta & ~$this->getStateBitmask()) === 0);
return $this->idInfo->getVariant() | $stateMeta;
}
$this->describeType($reader);
$readBits = $reader->getOffset();
if($typeBits !== $readBits){
throw new \LogicException(get_class($this) . ": Exactly $typeBits bits of type data were provided, but $readBits were read");
}
protected function writeStateToItemMeta() : int{
return 0;
}
/**
* @internal
* Returns a bitmask used to extract state bits from block metadata.
* This is used to remove unwanted information from the legacy meta value when getting the block as an item.
*/
final public function decodeStateData(int $data) : void{
$typeBits = $this->getRequiredTypeDataBits();
$stateBits = $this->getRequiredStateDataBits();
$givenBits = $typeBits + $stateBits;
$reader = new RuntimeDataReader($givenBits, $data);
$this->decodeTypeData($reader->readInt($typeBits));
public function getStateBitmask() : int{
return 0;
}
$this->describeState($reader);
$readBits = $reader->getOffset() - $typeBits;
if($stateBits !== $readBits){
throw new \LogicException(get_class($this) . ": Exactly $stateBits bits of state data were provided, but $readBits were read");
}
protected function writeStateToMeta() : int{
return 0;
}
/**
* @internal
* @throws InvalidBlockStateException
*/
final public function computeTypeData() : int{
$typeBits = $this->getRequiredTypeDataBits();
$requiredBits = $typeBits;
$writer = new RuntimeDataWriter($requiredBits);
$this->describeType($writer);
$writtenBits = $writer->getOffset();
if($typeBits !== $writtenBits){
throw new \LogicException(get_class($this) . ": Exactly $typeBits bits of type data were expected, but $writtenBits were written");
}
return $writer->getValue();
}
/**
* @internal
*/
final public function computeStateData() : int{
$typeBits = $this->getRequiredTypeDataBits();
$stateBits = $this->getRequiredStateDataBits();
$requiredBits = $typeBits + $stateBits;
$writer = new RuntimeDataWriter($requiredBits);
$writer->writeInt($typeBits, $this->computeTypeData());
$this->describeState($writer);
$writtenBits = $writer->getOffset() - $typeBits;
if($stateBits !== $writtenBits){
throw new \LogicException(get_class($this) . ": Exactly $stateBits bits of state data were expected, but $writtenBits were written");
}
return $writer->getValue();
}
protected function describeType(RuntimeDataDescriber $w) : void{
//NOOP
}
protected function describeState(RuntimeDataDescriber $w) : void{
public function readStateFromData(int $id, int $stateMeta) : void{
//NOOP
}
@ -228,14 +167,9 @@ class Block{
*
* Clears any cached precomputed objects, such as bounding boxes. Remove any outdated precomputed things such as
* AABBs and force recalculation.
*
* A replacement block may be returned. This is useful if the block type changed due to reading of world data (e.g.
* data from a block entity).
*/
public function readStateFromWorld() : Block{
public function readStateFromWorld() : void{
$this->collisionBoxes = null;
return $this;
}
/**
@ -246,11 +180,7 @@ class Block{
*/
public function writeStateToWorld() : void{
$world = $this->position->getWorld();
$chunk = $world->getOrLoadChunkAtPosition($this->position);
if($chunk === null){
throw new AssumptionFailedError("World::setBlock() should have loaded the chunk before calling this method");
}
$chunk->setBlockStateId($this->position->x & Chunk::COORD_MASK, $this->position->y, $this->position->z & Chunk::COORD_MASK, $this->getStateId());
$world->getOrLoadChunkAtPosition($this->position)->setFullBlock($this->position->x & Chunk::COORD_MASK, $this->position->y, $this->position->z & Chunk::COORD_MASK, $this->getFullId());
$tileType = $this->idInfo->getTileClass();
$oldTile = $world->getTile($this->position);
@ -277,11 +207,14 @@ class Block{
* powered/unpowered, etc.
*/
public function getTypeId() : int{
return $this->idInfo->getBlockTypeId();
return ($this->idInfo->getBlockId() << Block::INTERNAL_METADATA_BITS) | $this->idInfo->getVariant();
}
/**
* Returns whether the given block has an equivalent type to this one. This compares the type IDs.
*
* Note: This ignores additional IDs used to represent additional states. This means that, for example, a lit
* furnace and unlit furnace are considered the same type.
*/
public function isSameType(Block $other) : bool{
return $this->getTypeId() === $other->getTypeId();
@ -291,26 +224,7 @@ class Block{
* Returns whether the given block has the same type and properties as this block.
*/
public function isSameState(Block $other) : bool{
return $this->getStateId() === $other->getStateId();
}
/**
* @return string[]
*/
public function getTypeTags() : array{
return $this->typeInfo->getTypeTags();
}
/**
* Returns whether this block type has the given type tag. Type tags are used as a dynamic way to tag blocks as
* having certain properties, allowing type checks which are more dynamic than hardcoding a bunch of IDs or a bunch
* of instanceof checks.
*
* For example, grass blocks, dirt, farmland, podzol and mycelium are all dirt-like blocks, and support the
* placement of blocks like flowers, so they have a common tag which allows them to be identified as such.
*/
public function hasTypeTag(string $tag) : bool{
return $this->typeInfo->hasTypeTag($tag);
return $this->getFullId() === $other->getFullId();
}
/**
@ -366,15 +280,13 @@ class Block{
* Returns an object containing information about the destruction requirements of this block.
*/
public function getBreakInfo() : BlockBreakInfo{
return $this->typeInfo->getBreakInfo();
return $this->breakInfo;
}
/**
* Do the actions needed so the block is broken with the Item
*
* @param Item[] &$returnedItems Items to be added to the target's inventory (or dropped, if full)
*/
public function onBreak(Item $item, ?Player $player = null, array &$returnedItems = []) : bool{
public function onBreak(Item $item, ?Player $player = null) : bool{
$world = $this->position->getWorld();
if(($t = $world->getTile($this->position)) !== null){
$t->onBlockDestroyed();
@ -414,10 +326,8 @@ class Block{
/**
* Do actions when interacted by Item. Returns if it has done anything
*
* @param Item[] &$returnedItems Items to be added to the target's inventory (or dropped, if the inventory is full)
*/
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
return false;
}
@ -509,7 +419,7 @@ class Block{
* @return Item[]
*/
public function getDrops(Item $item) : array{
if($this->getBreakInfo()->isToolCompatible($item)){
if($this->breakInfo->isToolCompatible($item)){
if($this->isAffectedBySilkTouch() && $item->hasEnchantment(VanillaEnchantments::SILK_TOUCH())){
return $this->getSilkTouchDrops($item);
}
@ -551,7 +461,7 @@ class Block{
* Returns how much XP will be dropped by breaking this block with the given item.
*/
public function getXpDropForTool(Item $item) : int{
if($item->hasEnchantment(VanillaEnchantments::SILK_TOUCH()) || !$this->getBreakInfo()->isToolCompatible($item)){
if($item->hasEnchantment(VanillaEnchantments::SILK_TOUCH()) || !$this->breakInfo->isToolCompatible($item)){
return 0;
}
@ -605,10 +515,6 @@ 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.
@ -698,7 +604,7 @@ class Block{
* @return string
*/
public function __toString(){
return "Block[" . $this->getName() . "] (" . $this->getTypeId() . ":" . $this->computeStateData() . ")";
return "Block[" . $this->getName() . "] (" . $this->getId() . ":" . $this->getMeta() . ")";
}
/**
@ -757,13 +663,6 @@ 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
}
/**
* Returns an array of collision bounding boxes for this block.
* These are used for:

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ToolTier;
use function get_class;
class BlockBreakInfo{
@ -53,22 +52,6 @@ class BlockBreakInfo{
$this->blastResistance = $blastResistance ?? $hardness * 5;
}
public static function tier(float $hardness, int $toolType, ToolTier $toolTier, ?float $blastResistance = null) : self{
return new self($hardness, $toolType, $toolTier->getHarvestLevel(), $blastResistance);
}
public static function pickaxe(float $hardness, ?ToolTier $toolTier = null, ?float $blastResistance = null) : self{
return new self($hardness, BlockToolType::PICKAXE, $toolTier?->getHarvestLevel() ?? 0, $blastResistance);
}
public static function shovel(float $hardness, ?ToolTier $toolTier = null, ?float $blastResistance = null) : self{
return new self($hardness, BlockToolType::SHOVEL, $toolTier?->getHarvestLevel() ?? 0, $blastResistance);
}
public static function axe(float $hardness, ?ToolTier $toolTier = null, ?float $blastResistance = null) : self{
return new self($hardness, BlockToolType::AXE, $toolTier?->getHarvestLevel() ?? 0, $blastResistance);
}
public static function instant(int $toolType = BlockToolType::NONE, int $toolHarvestLevel = 0) : self{
return new self(0.0, $toolType, $toolHarvestLevel, 0.0);
}

1090
src/block/BlockFactory.php Normal file

File diff suppressed because it is too large Load Diff

View File

@ -31,18 +31,34 @@ class BlockIdentifier{
* @phpstan-param class-string<Tile>|null $tileClass
*/
public function __construct(
private int $blockTypeId,
private int $blockId,
private int $variant,
private ?int $itemId = null,
private ?string $tileClass = null
){
if($blockTypeId < 0){
throw new \InvalidArgumentException("Block type ID may not be negative");
}
if($tileClass !== null){
Utils::testValidInstance($tileClass, Tile::class);
}
}
public function getBlockTypeId() : int{ return $this->blockTypeId; }
public function getBlockId() : int{
return $this->blockId;
}
/**
* @return int[]
*/
public function getAllBlockIds() : array{
return [$this->blockId];
}
public function getVariant() : int{
return $this->variant;
}
public function getItemId() : int{
return $this->itemId ?? ($this->blockId > 255 ? 255 - $this->blockId : $this->blockId);
}
/**
* @phpstan-return class-string<Tile>|null

View File

@ -0,0 +1,59 @@
<?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 function count;
class BlockIdentifierFlattened extends BlockIdentifier{
/** @var int[] */
private array $additionalIds;
/**
* @param int[] $additionalIds
*/
public function __construct(int $blockId, array $additionalIds, int $variant, ?int $itemId = null, ?string $tileClass = null){
if(count($additionalIds) === 0){
throw new \InvalidArgumentException("Expected at least 1 additional ID");
}
parent::__construct($blockId, $variant, $itemId, $tileClass);
$this->additionalIds = $additionalIds;
}
public function getAdditionalId(int $index) : int{
if(!isset($this->additionalIds[$index])){
throw new \InvalidArgumentException("No such ID at index $index");
}
return $this->additionalIds[$index];
}
public function getSecondId() : int{
return $this->getAdditionalId(0);
}
public function getAllBlockIds() : array{
return [$this->getBlockId(), ...$this->additionalIds];
}
}

View File

@ -24,270 +24,225 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\BlockIdentifier as BID;
use pocketmine\block\BlockTypeIds as Ids;
use pocketmine\block\BlockLegacyIds as Ids;
use pocketmine\block\tile\Sign as TileSign;
use pocketmine\block\utils\LeavesType;
use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\TreeType;
use pocketmine\block\utils\WoodType;
use pocketmine\item\VanillaItems;
use pocketmine\item\ItemIds;
use pocketmine\utils\AssumptionFailedError;
final class BlockLegacyIdHelper{
public static function getWoodenPlanksIdentifier(WoodType $type) : BID{
return new BID(match($type->id()){
WoodType::OAK()->id() => Ids::OAK_PLANKS,
WoodType::SPRUCE()->id() => Ids::SPRUCE_PLANKS,
WoodType::BIRCH()->id() => Ids::BIRCH_PLANKS,
WoodType::JUNGLE()->id() => Ids::JUNGLE_PLANKS,
WoodType::ACACIA()->id() => Ids::ACACIA_PLANKS,
WoodType::DARK_OAK()->id() => Ids::DARK_OAK_PLANKS,
WoodType::MANGROVE()->id() => Ids::MANGROVE_PLANKS,
WoodType::CRIMSON()->id() => Ids::CRIMSON_PLANKS,
WoodType::WARPED()->id() => Ids::WARPED_PLANKS,
default => throw new AssumptionFailedError("All tree types should be covered")
});
}
public static function getWoodenFenceIdentifier(WoodType $type) : BID{
return new BID(match($type->id()){
WoodType::OAK()->id() => Ids::OAK_FENCE,
WoodType::SPRUCE()->id() => Ids::SPRUCE_FENCE,
WoodType::BIRCH()->id() => Ids::BIRCH_FENCE,
WoodType::JUNGLE()->id() => Ids::JUNGLE_FENCE,
WoodType::ACACIA()->id() => Ids::ACACIA_FENCE,
WoodType::DARK_OAK()->id() => Ids::DARK_OAK_FENCE,
WoodType::MANGROVE()->id() => Ids::MANGROVE_FENCE,
WoodType::CRIMSON()->id() => Ids::CRIMSON_FENCE,
WoodType::WARPED()->id() => Ids::WARPED_FENCE,
default => throw new AssumptionFailedError("All tree types should be covered")
});
}
public static function getWoodenSlabIdentifier(WoodType $type) : BID{
return new BID(match($type->id()){
WoodType::OAK()->id() => Ids::OAK_SLAB,
WoodType::SPRUCE()->id() => Ids::SPRUCE_SLAB,
WoodType::BIRCH()->id() => Ids::BIRCH_SLAB,
WoodType::JUNGLE()->id() => Ids::JUNGLE_SLAB,
WoodType::ACACIA()->id() => Ids::ACACIA_SLAB,
WoodType::DARK_OAK()->id() => Ids::DARK_OAK_SLAB,
WoodType::MANGROVE()->id() => Ids::MANGROVE_SLAB,
WoodType::CRIMSON()->id() => Ids::CRIMSON_SLAB,
WoodType::WARPED()->id() => Ids::WARPED_SLAB,
default => throw new AssumptionFailedError("All tree types should be covered")
});
}
public static function getLogIdentifier(WoodType $treeType) : BID{
return new BID(match($treeType->id()){
WoodType::OAK()->id() => Ids::OAK_LOG,
WoodType::SPRUCE()->id() => Ids::SPRUCE_LOG,
WoodType::BIRCH()->id() => Ids::BIRCH_LOG,
WoodType::JUNGLE()->id() => Ids::JUNGLE_LOG,
WoodType::ACACIA()->id() => Ids::ACACIA_LOG,
WoodType::DARK_OAK()->id() => Ids::DARK_OAK_LOG,
WoodType::MANGROVE()->id() => Ids::MANGROVE_LOG,
WoodType::CRIMSON()->id() => Ids::CRIMSON_STEM,
WoodType::WARPED()->id() => Ids::WARPED_STEM,
default => throw new AssumptionFailedError("All tree types should be covered")
});
}
public static function getAllSidedLogIdentifier(WoodType $treeType) : BID{
return new BID(match($treeType->id()){
WoodType::OAK()->id() => Ids::OAK_WOOD,
WoodType::SPRUCE()->id() => Ids::SPRUCE_WOOD,
WoodType::BIRCH()->id() => Ids::BIRCH_WOOD,
WoodType::JUNGLE()->id() => Ids::JUNGLE_WOOD,
WoodType::ACACIA()->id() => Ids::ACACIA_WOOD,
WoodType::DARK_OAK()->id() => Ids::DARK_OAK_WOOD,
WoodType::MANGROVE()->id() => Ids::MANGROVE_WOOD,
WoodType::CRIMSON()->id() => Ids::CRIMSON_HYPHAE,
WoodType::WARPED()->id() => Ids::WARPED_HYPHAE,
default => throw new AssumptionFailedError("All tree types should be covered")
});
}
public static function getLeavesIdentifier(LeavesType $leavesType) : BID{
return new BID(match($leavesType->id()){
LeavesType::OAK()->id() => Ids::OAK_LEAVES,
LeavesType::SPRUCE()->id() => Ids::SPRUCE_LEAVES,
LeavesType::BIRCH()->id() => Ids::BIRCH_LEAVES,
LeavesType::JUNGLE()->id() => Ids::JUNGLE_LEAVES,
LeavesType::ACACIA()->id() => Ids::ACACIA_LEAVES,
LeavesType::DARK_OAK()->id() => Ids::DARK_OAK_LEAVES,
LeavesType::MANGROVE()->id() => Ids::MANGROVE_LEAVES,
LeavesType::AZALEA()->id() => Ids::AZALEA_LEAVES,
LeavesType::FLOWERING_AZALEA()->id() => Ids::FLOWERING_AZALEA_LEAVES,
default => throw new AssumptionFailedError("All leaves types should be covered")
});
}
public static function getSaplingIdentifier(TreeType $treeType) : BID{
return new BID(match($treeType->id()){
TreeType::OAK()->id() => Ids::OAK_SAPLING,
TreeType::SPRUCE()->id() => Ids::SPRUCE_SAPLING,
TreeType::BIRCH()->id() => Ids::BIRCH_SAPLING,
TreeType::JUNGLE()->id() => Ids::JUNGLE_SAPLING,
TreeType::ACACIA()->id() => Ids::ACACIA_SAPLING,
TreeType::DARK_OAK()->id() => Ids::DARK_OAK_SAPLING,
default => throw new AssumptionFailedError("All tree types should be covered")
});
}
/**
* @return BID[]|\Closure[]
* @phpstan-return array{BID, BID, \Closure() : \pocketmine\item\Item}
*/
public static function getWoodenSignInfo(WoodType $treeType) : array{
public static function getWoodenFloorSignIdentifier(TreeType $treeType) : BID{
switch($treeType->id()){
case WoodType::OAK()->id():
return [
new BID(Ids::OAK_SIGN, TileSign::class),
new BID(Ids::OAK_WALL_SIGN, TileSign::class),
fn() => VanillaItems::OAK_SIGN()
];
case WoodType::SPRUCE()->id():
return [
new BID(Ids::SPRUCE_SIGN, TileSign::class),
new BID(Ids::SPRUCE_WALL_SIGN, TileSign::class),
fn() => VanillaItems::SPRUCE_SIGN()
];
case WoodType::BIRCH()->id():
return [
new BID(Ids::BIRCH_SIGN, TileSign::class),
new BID(Ids::BIRCH_WALL_SIGN, TileSign::class),
fn() => VanillaItems::BIRCH_SIGN()
];
case WoodType::JUNGLE()->id():
return [
new BID(Ids::JUNGLE_SIGN, TileSign::class),
new BID(Ids::JUNGLE_WALL_SIGN, TileSign::class),
fn() => VanillaItems::JUNGLE_SIGN()
];
case WoodType::ACACIA()->id():
return [
new BID(Ids::ACACIA_SIGN, TileSign::class),
new BID(Ids::ACACIA_WALL_SIGN, TileSign::class),
fn() => VanillaItems::ACACIA_SIGN()
];
case WoodType::DARK_OAK()->id():
return [
new BID(Ids::DARK_OAK_SIGN, TileSign::class),
new BID(Ids::DARK_OAK_WALL_SIGN, TileSign::class),
fn() => VanillaItems::DARK_OAK_SIGN()
];
case WoodType::MANGROVE()->id():
return [
new BID(Ids::MANGROVE_SIGN, TileSign::class),
new BID(Ids::MANGROVE_WALL_SIGN, TileSign::class),
fn() => VanillaItems::MANGROVE_SIGN()
];
case WoodType::CRIMSON()->id():
return [
new BID(Ids::CRIMSON_SIGN, TileSign::class),
new BID(Ids::CRIMSON_WALL_SIGN, TileSign::class),
fn() => VanillaItems::CRIMSON_SIGN()
];
case WoodType::WARPED()->id():
return [
new BID(Ids::WARPED_SIGN, TileSign::class),
new BID(Ids::WARPED_WALL_SIGN, TileSign::class),
fn() => VanillaItems::WARPED_SIGN()
];
case TreeType::OAK()->id():
return new BID(Ids::SIGN_POST, 0, ItemIds::SIGN, TileSign::class);
case TreeType::SPRUCE()->id():
return new BID(Ids::SPRUCE_STANDING_SIGN, 0, ItemIds::SPRUCE_SIGN, TileSign::class);
case TreeType::BIRCH()->id():
return new BID(Ids::BIRCH_STANDING_SIGN, 0, ItemIds::BIRCH_SIGN, TileSign::class);
case TreeType::JUNGLE()->id():
return new BID(Ids::JUNGLE_STANDING_SIGN, 0, ItemIds::JUNGLE_SIGN, TileSign::class);
case TreeType::ACACIA()->id():
return new BID(Ids::ACACIA_STANDING_SIGN,0, ItemIds::ACACIA_SIGN, TileSign::class);
case TreeType::DARK_OAK()->id():
return new BID(Ids::DARKOAK_STANDING_SIGN, 0, ItemIds::DARKOAK_SIGN, TileSign::class);
}
throw new AssumptionFailedError("Switch should cover all wood types");
}
public static function getWoodenTrapdoorIdentifier(WoodType $treeType) : BlockIdentifier{
return new BID(match($treeType->id()){
WoodType::OAK()->id() => Ids::OAK_TRAPDOOR,
WoodType::SPRUCE()->id() => Ids::SPRUCE_TRAPDOOR,
WoodType::BIRCH()->id() => Ids::BIRCH_TRAPDOOR,
WoodType::JUNGLE()->id() => Ids::JUNGLE_TRAPDOOR,
WoodType::ACACIA()->id() => Ids::ACACIA_TRAPDOOR,
WoodType::DARK_OAK()->id() => Ids::DARK_OAK_TRAPDOOR,
WoodType::MANGROVE()->id() => Ids::MANGROVE_TRAPDOOR,
WoodType::CRIMSON()->id() => Ids::CRIMSON_TRAPDOOR,
WoodType::WARPED()->id() => Ids::WARPED_TRAPDOOR,
default => throw new AssumptionFailedError("All wood types should be covered")
});
public static function getWoodenWallSignIdentifier(TreeType $treeType) : BID{
switch($treeType->id()){
case TreeType::OAK()->id():
return new BID(Ids::WALL_SIGN, 0, ItemIds::SIGN, TileSign::class);
case TreeType::SPRUCE()->id():
return new BID(Ids::SPRUCE_WALL_SIGN, 0, ItemIds::SPRUCE_SIGN, TileSign::class);
case TreeType::BIRCH()->id():
return new BID(Ids::BIRCH_WALL_SIGN, 0, ItemIds::BIRCH_SIGN, TileSign::class);
case TreeType::JUNGLE()->id():
return new BID(Ids::JUNGLE_WALL_SIGN, 0, ItemIds::JUNGLE_SIGN, TileSign::class);
case TreeType::ACACIA()->id():
return new BID(Ids::ACACIA_WALL_SIGN, 0, ItemIds::ACACIA_SIGN, TileSign::class);
case TreeType::DARK_OAK()->id():
return new BID(Ids::DARKOAK_WALL_SIGN, 0, ItemIds::DARKOAK_SIGN, TileSign::class);
}
throw new AssumptionFailedError("Switch should cover all wood types");
}
public static function getWoodenButtonIdentifier(WoodType $treeType) : BlockIdentifier{
return new BID(match($treeType->id()){
WoodType::OAK()->id() => Ids::OAK_BUTTON,
WoodType::SPRUCE()->id() => Ids::SPRUCE_BUTTON,
WoodType::BIRCH()->id() => Ids::BIRCH_BUTTON,
WoodType::JUNGLE()->id() => Ids::JUNGLE_BUTTON,
WoodType::ACACIA()->id() => Ids::ACACIA_BUTTON,
WoodType::DARK_OAK()->id() => Ids::DARK_OAK_BUTTON,
WoodType::MANGROVE()->id() => Ids::MANGROVE_BUTTON,
WoodType::CRIMSON()->id() => Ids::CRIMSON_BUTTON,
WoodType::WARPED()->id() => Ids::WARPED_BUTTON,
default => throw new AssumptionFailedError("All wood types should be covered")
});
public static function getWoodenTrapdoorIdentifier(TreeType $treeType) : BlockIdentifier{
switch($treeType->id()){
case TreeType::OAK()->id():
return new BlockIdentifier(Ids::WOODEN_TRAPDOOR, 0);
case TreeType::SPRUCE()->id():
return new BlockIdentifier(Ids::SPRUCE_TRAPDOOR, 0);
case TreeType::BIRCH()->id():
return new BlockIdentifier(Ids::BIRCH_TRAPDOOR, 0);
case TreeType::JUNGLE()->id():
return new BlockIdentifier(Ids::JUNGLE_TRAPDOOR, 0);
case TreeType::ACACIA()->id():
return new BlockIdentifier(Ids::ACACIA_TRAPDOOR, 0);
case TreeType::DARK_OAK()->id():
return new BlockIdentifier(Ids::DARK_OAK_TRAPDOOR, 0);
}
throw new AssumptionFailedError("Switch should cover all wood types");
}
public static function getWoodenPressurePlateIdentifier(WoodType $treeType) : BlockIdentifier{
return new BID(match($treeType->id()){
WoodType::OAK()->id() => Ids::OAK_PRESSURE_PLATE,
WoodType::SPRUCE()->id() => Ids::SPRUCE_PRESSURE_PLATE,
WoodType::BIRCH()->id() => Ids::BIRCH_PRESSURE_PLATE,
WoodType::JUNGLE()->id() => Ids::JUNGLE_PRESSURE_PLATE,
WoodType::ACACIA()->id() => Ids::ACACIA_PRESSURE_PLATE,
WoodType::DARK_OAK()->id() => Ids::DARK_OAK_PRESSURE_PLATE,
WoodType::MANGROVE()->id() => Ids::MANGROVE_PRESSURE_PLATE,
WoodType::CRIMSON()->id() => Ids::CRIMSON_PRESSURE_PLATE,
WoodType::WARPED()->id() => Ids::WARPED_PRESSURE_PLATE,
default => throw new AssumptionFailedError("All wood types should be covered")
});
public static function getWoodenButtonIdentifier(TreeType $treeType) : BlockIdentifier{
switch($treeType->id()){
case TreeType::OAK()->id():
return new BlockIdentifier(Ids::WOODEN_BUTTON, 0);
case TreeType::SPRUCE()->id():
return new BlockIdentifier(Ids::SPRUCE_BUTTON, 0);
case TreeType::BIRCH()->id():
return new BlockIdentifier(Ids::BIRCH_BUTTON, 0);
case TreeType::JUNGLE()->id():
return new BlockIdentifier(Ids::JUNGLE_BUTTON, 0);
case TreeType::ACACIA()->id():
return new BlockIdentifier(Ids::ACACIA_BUTTON, 0);
case TreeType::DARK_OAK()->id():
return new BlockIdentifier(Ids::DARK_OAK_BUTTON, 0);
}
throw new AssumptionFailedError("Switch should cover all wood types");
}
public static function getWoodenDoorIdentifier(WoodType $treeType) : BlockIdentifier{
return new BID(match($treeType->id()){
WoodType::OAK()->id() => Ids::OAK_DOOR,
WoodType::SPRUCE()->id() => Ids::SPRUCE_DOOR,
WoodType::BIRCH()->id() => Ids::BIRCH_DOOR,
WoodType::JUNGLE()->id() => Ids::JUNGLE_DOOR,
WoodType::ACACIA()->id() => Ids::ACACIA_DOOR,
WoodType::DARK_OAK()->id() => Ids::DARK_OAK_DOOR,
WoodType::MANGROVE()->id() => Ids::MANGROVE_DOOR,
WoodType::CRIMSON()->id() => Ids::CRIMSON_DOOR,
WoodType::WARPED()->id() => Ids::WARPED_DOOR,
default => throw new AssumptionFailedError("All wood types should be covered")
});
public static function getWoodenPressurePlateIdentifier(TreeType $treeType) : BlockIdentifier{
switch($treeType->id()){
case TreeType::OAK()->id():
return new BlockIdentifier(Ids::WOODEN_PRESSURE_PLATE, 0);
case TreeType::SPRUCE()->id():
return new BlockIdentifier(Ids::SPRUCE_PRESSURE_PLATE, 0);
case TreeType::BIRCH()->id():
return new BlockIdentifier(Ids::BIRCH_PRESSURE_PLATE, 0);
case TreeType::JUNGLE()->id():
return new BlockIdentifier(Ids::JUNGLE_PRESSURE_PLATE, 0);
case TreeType::ACACIA()->id():
return new BlockIdentifier(Ids::ACACIA_PRESSURE_PLATE, 0);
case TreeType::DARK_OAK()->id():
return new BlockIdentifier(Ids::DARK_OAK_PRESSURE_PLATE, 0);
}
throw new AssumptionFailedError("Switch should cover all wood types");
}
public static function getWoodenFenceGateIdentifier(WoodType $treeType) : BlockIdentifier{
return new BID(match($treeType->id()){
WoodType::OAK()->id() => Ids::OAK_FENCE_GATE,
WoodType::SPRUCE()->id() => Ids::SPRUCE_FENCE_GATE,
WoodType::BIRCH()->id() => Ids::BIRCH_FENCE_GATE,
WoodType::JUNGLE()->id() => Ids::JUNGLE_FENCE_GATE,
WoodType::ACACIA()->id() => Ids::ACACIA_FENCE_GATE,
WoodType::DARK_OAK()->id() => Ids::DARK_OAK_FENCE_GATE,
WoodType::MANGROVE()->id() => Ids::MANGROVE_FENCE_GATE,
WoodType::CRIMSON()->id() => Ids::CRIMSON_FENCE_GATE,
WoodType::WARPED()->id() => Ids::WARPED_FENCE_GATE,
default => throw new AssumptionFailedError("All wood types should be covered")
});
public static function getWoodenDoorIdentifier(TreeType $treeType) : BlockIdentifier{
switch($treeType->id()){
case TreeType::OAK()->id():
return new BID(Ids::OAK_DOOR_BLOCK, 0, ItemIds::OAK_DOOR);
case TreeType::SPRUCE()->id():
return new BID(Ids::SPRUCE_DOOR_BLOCK, 0, ItemIds::SPRUCE_DOOR);
case TreeType::BIRCH()->id():
return new BID(Ids::BIRCH_DOOR_BLOCK, 0, ItemIds::BIRCH_DOOR);
case TreeType::JUNGLE()->id():
return new BID(Ids::JUNGLE_DOOR_BLOCK, 0, ItemIds::JUNGLE_DOOR);
case TreeType::ACACIA()->id():
return new BID(Ids::ACACIA_DOOR_BLOCK, 0, ItemIds::ACACIA_DOOR);
case TreeType::DARK_OAK()->id():
return new BID(Ids::DARK_OAK_DOOR_BLOCK, 0, ItemIds::DARK_OAK_DOOR);
}
throw new AssumptionFailedError("Switch should cover all wood types");
}
public static function getWoodenStairsIdentifier(WoodType $treeType) : BlockIdentifier{
return new BID(match($treeType->id()){
WoodType::OAK()->id() => Ids::OAK_STAIRS,
WoodType::SPRUCE()->id() => Ids::SPRUCE_STAIRS,
WoodType::BIRCH()->id() => Ids::BIRCH_STAIRS,
WoodType::JUNGLE()->id() => Ids::JUNGLE_STAIRS,
WoodType::ACACIA()->id() => Ids::ACACIA_STAIRS,
WoodType::DARK_OAK()->id() => Ids::DARK_OAK_STAIRS,
WoodType::MANGROVE()->id() => Ids::MANGROVE_STAIRS,
WoodType::CRIMSON()->id() => Ids::CRIMSON_STAIRS,
WoodType::WARPED()->id() => Ids::WARPED_STAIRS,
default => throw new AssumptionFailedError("All wood types should be covered")
});
public static function getWoodenFenceIdentifier(TreeType $treeType) : BlockIdentifier{
switch($treeType->id()){
case TreeType::OAK()->id():
return new BlockIdentifier(Ids::OAK_FENCE_GATE, 0);
case TreeType::SPRUCE()->id():
return new BlockIdentifier(Ids::SPRUCE_FENCE_GATE, 0);
case TreeType::BIRCH()->id():
return new BlockIdentifier(Ids::BIRCH_FENCE_GATE, 0);
case TreeType::JUNGLE()->id():
return new BlockIdentifier(Ids::JUNGLE_FENCE_GATE, 0);
case TreeType::ACACIA()->id():
return new BlockIdentifier(Ids::ACACIA_FENCE_GATE, 0);
case TreeType::DARK_OAK()->id():
return new BlockIdentifier(Ids::DARK_OAK_FENCE_GATE, 0);
}
throw new AssumptionFailedError("Switch should cover all wood types");
}
public static function getWoodenStairsIdentifier(TreeType $treeType) : BlockIdentifier{
switch($treeType->id()){
case TreeType::OAK()->id():
return new BlockIdentifier(Ids::OAK_STAIRS, 0);
case TreeType::SPRUCE()->id():
return new BlockIdentifier(Ids::SPRUCE_STAIRS, 0);
case TreeType::BIRCH()->id():
return new BlockIdentifier(Ids::BIRCH_STAIRS, 0);
case TreeType::JUNGLE()->id():
return new BlockIdentifier(Ids::JUNGLE_STAIRS, 0);
case TreeType::ACACIA()->id():
return new BlockIdentifier(Ids::ACACIA_STAIRS, 0);
case TreeType::DARK_OAK()->id():
return new BlockIdentifier(Ids::DARK_OAK_STAIRS, 0);
}
throw new AssumptionFailedError("Switch should cover all wood types");
}
public static function getStrippedLogIdentifier(TreeType $treeType) : BlockIdentifier{
switch($treeType->id()){
case TreeType::OAK()->id():
return new BlockIdentifier(Ids::STRIPPED_OAK_LOG, 0);
case TreeType::SPRUCE()->id():
return new BlockIdentifier(Ids::STRIPPED_SPRUCE_LOG, 0);
case TreeType::BIRCH()->id():
return new BlockIdentifier(Ids::STRIPPED_BIRCH_LOG, 0);
case TreeType::JUNGLE()->id():
return new BlockIdentifier(Ids::STRIPPED_JUNGLE_LOG, 0);
case TreeType::ACACIA()->id():
return new BlockIdentifier(Ids::STRIPPED_ACACIA_LOG, 0);
case TreeType::DARK_OAK()->id():
return new BlockIdentifier(Ids::STRIPPED_DARK_OAK_LOG, 0);
}
throw new AssumptionFailedError("Switch should cover all wood types");
}
public static function getGlazedTerracottaIdentifier(DyeColor $color) : BlockIdentifier{
switch($color->id()){
case DyeColor::WHITE()->id():
return new BlockIdentifier(Ids::WHITE_GLAZED_TERRACOTTA, 0);
case DyeColor::ORANGE()->id():
return new BlockIdentifier(Ids::ORANGE_GLAZED_TERRACOTTA, 0);
case DyeColor::MAGENTA()->id():
return new BlockIdentifier(Ids::MAGENTA_GLAZED_TERRACOTTA, 0);
case DyeColor::LIGHT_BLUE()->id():
return new BlockIdentifier(Ids::LIGHT_BLUE_GLAZED_TERRACOTTA, 0);
case DyeColor::YELLOW()->id():
return new BlockIdentifier(Ids::YELLOW_GLAZED_TERRACOTTA, 0);
case DyeColor::LIME()->id():
return new BlockIdentifier(Ids::LIME_GLAZED_TERRACOTTA, 0);
case DyeColor::PINK()->id():
return new BlockIdentifier(Ids::PINK_GLAZED_TERRACOTTA, 0);
case DyeColor::GRAY()->id():
return new BlockIdentifier(Ids::GRAY_GLAZED_TERRACOTTA, 0);
case DyeColor::LIGHT_GRAY()->id():
return new BlockIdentifier(Ids::SILVER_GLAZED_TERRACOTTA, 0);
case DyeColor::CYAN()->id():
return new BlockIdentifier(Ids::CYAN_GLAZED_TERRACOTTA, 0);
case DyeColor::PURPLE()->id():
return new BlockIdentifier(Ids::PURPLE_GLAZED_TERRACOTTA, 0);
case DyeColor::BLUE()->id():
return new BlockIdentifier(Ids::BLUE_GLAZED_TERRACOTTA, 0);
case DyeColor::BROWN()->id():
return new BlockIdentifier(Ids::BROWN_GLAZED_TERRACOTTA, 0);
case DyeColor::GREEN()->id():
return new BlockIdentifier(Ids::GREEN_GLAZED_TERRACOTTA, 0);
case DyeColor::RED()->id():
return new BlockIdentifier(Ids::RED_GLAZED_TERRACOTTA, 0);
case DyeColor::BLACK()->id():
return new BlockIdentifier(Ids::BLACK_GLAZED_TERRACOTTA, 0);
}
throw new AssumptionFailedError("Switch should cover all colours");
}
public static function getStoneSlabIdentifier(int $stoneSlabId, int $meta) : BlockIdentifierFlattened{
$id = [
1 => [Ids::STONE_SLAB, Ids::DOUBLE_STONE_SLAB],
2 => [Ids::STONE_SLAB2, Ids::DOUBLE_STONE_SLAB2],
3 => [Ids::STONE_SLAB3, Ids::DOUBLE_STONE_SLAB3],
4 => [Ids::STONE_SLAB4, Ids::DOUBLE_STONE_SLAB4]
][$stoneSlabId] ?? null;
if($id === null){
throw new \InvalidArgumentException("Stone slab type should be 1, 2, 3 or 4");
}
return new BlockIdentifierFlattened($id[0], [$id[1]], $meta);
}
}

View File

@ -0,0 +1,501 @@
<?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 BlockLegacyIds{
private function __construct(){
//NOOP
}
public const AIR = 0;
public const STONE = 1;
public const GRASS = 2;
public const DIRT = 3;
public const COBBLESTONE = 4;
public const PLANKS = 5, WOODEN_PLANKS = 5;
public const SAPLING = 6;
public const BEDROCK = 7;
public const FLOWING_WATER = 8;
public const STILL_WATER = 9, WATER = 9;
public const FLOWING_LAVA = 10;
public const LAVA = 11, STILL_LAVA = 11;
public const SAND = 12;
public const GRAVEL = 13;
public const GOLD_ORE = 14;
public const IRON_ORE = 15;
public const COAL_ORE = 16;
public const LOG = 17;
public const LEAVES = 18;
public const SPONGE = 19;
public const GLASS = 20;
public const LAPIS_ORE = 21;
public const LAPIS_BLOCK = 22;
public const DISPENSER = 23;
public const SANDSTONE = 24;
public const NOTEBLOCK = 25, NOTE_BLOCK = 25;
public const BED_BLOCK = 26;
public const GOLDEN_RAIL = 27, POWERED_RAIL = 27;
public const DETECTOR_RAIL = 28;
public const STICKY_PISTON = 29;
public const COBWEB = 30, WEB = 30;
public const TALLGRASS = 31, TALL_GRASS = 31;
public const DEADBUSH = 32, DEAD_BUSH = 32;
public const PISTON = 33;
public const PISTONARMCOLLISION = 34, PISTON_ARM_COLLISION = 34;
public const WOOL = 35;
public const ELEMENT_0 = 36;
public const DANDELION = 37, YELLOW_FLOWER = 37;
public const POPPY = 38, RED_FLOWER = 38;
public const BROWN_MUSHROOM = 39;
public const RED_MUSHROOM = 40;
public const GOLD_BLOCK = 41;
public const IRON_BLOCK = 42;
public const DOUBLE_STONE_SLAB = 43;
public const STONE_SLAB = 44;
public const BRICK_BLOCK = 45;
public const TNT = 46;
public const BOOKSHELF = 47;
public const MOSSY_COBBLESTONE = 48, MOSS_STONE = 48;
public const OBSIDIAN = 49;
public const TORCH = 50;
public const FIRE = 51;
public const MOB_SPAWNER = 52, MONSTER_SPAWNER = 52;
public const OAK_STAIRS = 53, WOODEN_STAIRS = 53;
public const CHEST = 54;
public const REDSTONE_WIRE = 55;
public const DIAMOND_ORE = 56;
public const DIAMOND_BLOCK = 57;
public const CRAFTING_TABLE = 58, WORKBENCH = 58;
public const WHEAT_BLOCK = 59;
public const FARMLAND = 60;
public const FURNACE = 61;
public const BURNING_FURNACE = 62, LIT_FURNACE = 62;
public const SIGN_POST = 63, STANDING_SIGN = 63;
public const OAK_DOOR_BLOCK = 64, WOODEN_DOOR_BLOCK = 64;
public const LADDER = 65;
public const RAIL = 66;
public const COBBLESTONE_STAIRS = 67, STONE_STAIRS = 67;
public const WALL_SIGN = 68;
public const LEVER = 69;
public const STONE_PRESSURE_PLATE = 70;
public const IRON_DOOR_BLOCK = 71;
public const WOODEN_PRESSURE_PLATE = 72;
public const REDSTONE_ORE = 73;
public const GLOWING_REDSTONE_ORE = 74, LIT_REDSTONE_ORE = 74;
public const UNLIT_REDSTONE_TORCH = 75;
public const LIT_REDSTONE_TORCH = 76, REDSTONE_TORCH = 76;
public const STONE_BUTTON = 77;
public const SNOW_LAYER = 78;
public const ICE = 79;
public const SNOW = 80, SNOW_BLOCK = 80;
public const CACTUS = 81;
public const CLAY_BLOCK = 82;
public const REEDS_BLOCK = 83, SUGARCANE_BLOCK = 83;
public const JUKEBOX = 84;
public const FENCE = 85;
public const PUMPKIN = 86;
public const NETHERRACK = 87;
public const SOUL_SAND = 88;
public const GLOWSTONE = 89;
public const PORTAL = 90;
public const JACK_O_LANTERN = 91, LIT_PUMPKIN = 91;
public const CAKE_BLOCK = 92;
public const REPEATER_BLOCK = 93, UNPOWERED_REPEATER = 93;
public const POWERED_REPEATER = 94;
public const INVISIBLEBEDROCK = 95, INVISIBLE_BEDROCK = 95;
public const TRAPDOOR = 96, WOODEN_TRAPDOOR = 96;
public const MONSTER_EGG = 97;
public const STONEBRICK = 98, STONE_BRICK = 98, STONE_BRICKS = 98;
public const BROWN_MUSHROOM_BLOCK = 99;
public const RED_MUSHROOM_BLOCK = 100;
public const IRON_BARS = 101;
public const GLASS_PANE = 102;
public const MELON_BLOCK = 103;
public const PUMPKIN_STEM = 104;
public const MELON_STEM = 105;
public const VINE = 106, VINES = 106;
public const FENCE_GATE = 107, OAK_FENCE_GATE = 107;
public const BRICK_STAIRS = 108;
public const STONE_BRICK_STAIRS = 109;
public const MYCELIUM = 110;
public const LILY_PAD = 111, WATERLILY = 111, WATER_LILY = 111;
public const NETHER_BRICK_BLOCK = 112;
public const NETHER_BRICK_FENCE = 113;
public const NETHER_BRICK_STAIRS = 114;
public const NETHER_WART_PLANT = 115;
public const ENCHANTING_TABLE = 116, ENCHANTMENT_TABLE = 116;
public const BREWING_STAND_BLOCK = 117;
public const CAULDRON_BLOCK = 118;
public const END_PORTAL = 119;
public const END_PORTAL_FRAME = 120;
public const END_STONE = 121;
public const DRAGON_EGG = 122;
public const REDSTONE_LAMP = 123;
public const LIT_REDSTONE_LAMP = 124;
public const DROPPER = 125;
public const ACTIVATOR_RAIL = 126;
public const COCOA = 127, COCOA_BLOCK = 127;
public const SANDSTONE_STAIRS = 128;
public const EMERALD_ORE = 129;
public const ENDER_CHEST = 130;
public const TRIPWIRE_HOOK = 131;
public const TRIPWIRE = 132, TRIP_WIRE = 132;
public const EMERALD_BLOCK = 133;
public const SPRUCE_STAIRS = 134;
public const BIRCH_STAIRS = 135;
public const JUNGLE_STAIRS = 136;
public const COMMAND_BLOCK = 137;
public const BEACON = 138;
public const COBBLESTONE_WALL = 139, STONE_WALL = 139;
public const FLOWER_POT_BLOCK = 140;
public const CARROTS = 141, CARROT_BLOCK = 141;
public const POTATOES = 142, POTATO_BLOCK = 142;
public const WOODEN_BUTTON = 143;
public const MOB_HEAD_BLOCK = 144, SKULL_BLOCK = 144;
public const ANVIL = 145;
public const TRAPPED_CHEST = 146;
public const LIGHT_WEIGHTED_PRESSURE_PLATE = 147;
public const HEAVY_WEIGHTED_PRESSURE_PLATE = 148;
public const COMPARATOR_BLOCK = 149, UNPOWERED_COMPARATOR = 149;
public const POWERED_COMPARATOR = 150;
public const DAYLIGHT_DETECTOR = 151, DAYLIGHT_SENSOR = 151;
public const REDSTONE_BLOCK = 152;
public const NETHER_QUARTZ_ORE = 153, QUARTZ_ORE = 153;
public const HOPPER_BLOCK = 154;
public const QUARTZ_BLOCK = 155;
public const QUARTZ_STAIRS = 156;
public const DOUBLE_WOODEN_SLAB = 157;
public const WOODEN_SLAB = 158;
public const STAINED_CLAY = 159, STAINED_HARDENED_CLAY = 159, TERRACOTTA = 159;
public const STAINED_GLASS_PANE = 160;
public const LEAVES2 = 161;
public const LOG2 = 162;
public const ACACIA_STAIRS = 163;
public const DARK_OAK_STAIRS = 164;
public const SLIME = 165, SLIME_BLOCK = 165;
public const GLOW_STICK = 166;
public const IRON_TRAPDOOR = 167;
public const PRISMARINE = 168;
public const SEALANTERN = 169, SEA_LANTERN = 169;
public const HAY_BALE = 170, HAY_BLOCK = 170;
public const CARPET = 171;
public const HARDENED_CLAY = 172;
public const COAL_BLOCK = 173;
public const PACKED_ICE = 174;
public const DOUBLE_PLANT = 175;
public const STANDING_BANNER = 176;
public const WALL_BANNER = 177;
public const DAYLIGHT_DETECTOR_INVERTED = 178, DAYLIGHT_SENSOR_INVERTED = 178;
public const RED_SANDSTONE = 179;
public const RED_SANDSTONE_STAIRS = 180;
public const DOUBLE_STONE_SLAB2 = 181;
public const STONE_SLAB2 = 182;
public const SPRUCE_FENCE_GATE = 183;
public const BIRCH_FENCE_GATE = 184;
public const JUNGLE_FENCE_GATE = 185;
public const DARK_OAK_FENCE_GATE = 186;
public const ACACIA_FENCE_GATE = 187;
public const REPEATING_COMMAND_BLOCK = 188;
public const CHAIN_COMMAND_BLOCK = 189;
public const HARD_GLASS_PANE = 190;
public const HARD_STAINED_GLASS_PANE = 191;
public const CHEMICAL_HEAT = 192;
public const SPRUCE_DOOR_BLOCK = 193;
public const BIRCH_DOOR_BLOCK = 194;
public const JUNGLE_DOOR_BLOCK = 195;
public const ACACIA_DOOR_BLOCK = 196;
public const DARK_OAK_DOOR_BLOCK = 197;
public const GRASS_PATH = 198;
public const FRAME_BLOCK = 199, ITEM_FRAME_BLOCK = 199;
public const CHORUS_FLOWER = 200;
public const PURPUR_BLOCK = 201;
public const COLORED_TORCH_RG = 202;
public const PURPUR_STAIRS = 203;
public const COLORED_TORCH_BP = 204;
public const UNDYED_SHULKER_BOX = 205;
public const END_BRICKS = 206;
public const FROSTED_ICE = 207;
public const END_ROD = 208;
public const END_GATEWAY = 209;
public const MAGMA = 213;
public const NETHER_WART_BLOCK = 214;
public const RED_NETHER_BRICK = 215;
public const BONE_BLOCK = 216;
public const SHULKER_BOX = 218;
public const PURPLE_GLAZED_TERRACOTTA = 219;
public const WHITE_GLAZED_TERRACOTTA = 220;
public const ORANGE_GLAZED_TERRACOTTA = 221;
public const MAGENTA_GLAZED_TERRACOTTA = 222;
public const LIGHT_BLUE_GLAZED_TERRACOTTA = 223;
public const YELLOW_GLAZED_TERRACOTTA = 224;
public const LIME_GLAZED_TERRACOTTA = 225;
public const PINK_GLAZED_TERRACOTTA = 226;
public const GRAY_GLAZED_TERRACOTTA = 227;
public const SILVER_GLAZED_TERRACOTTA = 228;
public const CYAN_GLAZED_TERRACOTTA = 229;
public const BLUE_GLAZED_TERRACOTTA = 231;
public const BROWN_GLAZED_TERRACOTTA = 232;
public const GREEN_GLAZED_TERRACOTTA = 233;
public const RED_GLAZED_TERRACOTTA = 234;
public const BLACK_GLAZED_TERRACOTTA = 235;
public const CONCRETE = 236;
public const CONCRETEPOWDER = 237, CONCRETE_POWDER = 237;
public const CHEMISTRY_TABLE = 238;
public const UNDERWATER_TORCH = 239;
public const CHORUS_PLANT = 240;
public const STAINED_GLASS = 241;
public const PODZOL = 243;
public const BEETROOT_BLOCK = 244;
public const STONECUTTER = 245;
public const GLOWINGOBSIDIAN = 246, GLOWING_OBSIDIAN = 246;
public const NETHERREACTOR = 247, NETHER_REACTOR = 247;
public const INFO_UPDATE = 248;
public const INFO_UPDATE2 = 249;
public const MOVINGBLOCK = 250, MOVING_BLOCK = 250;
public const OBSERVER = 251;
public const STRUCTURE_BLOCK = 252;
public const HARD_GLASS = 253;
public const HARD_STAINED_GLASS = 254;
public const RESERVED6 = 255;
public const PRISMARINE_STAIRS = 257;
public const DARK_PRISMARINE_STAIRS = 258;
public const PRISMARINE_BRICKS_STAIRS = 259;
public const STRIPPED_SPRUCE_LOG = 260;
public const STRIPPED_BIRCH_LOG = 261;
public const STRIPPED_JUNGLE_LOG = 262;
public const STRIPPED_ACACIA_LOG = 263;
public const STRIPPED_DARK_OAK_LOG = 264;
public const STRIPPED_OAK_LOG = 265;
public const BLUE_ICE = 266;
public const ELEMENT_1 = 267;
public const ELEMENT_2 = 268;
public const ELEMENT_3 = 269;
public const ELEMENT_4 = 270;
public const ELEMENT_5 = 271;
public const ELEMENT_6 = 272;
public const ELEMENT_7 = 273;
public const ELEMENT_8 = 274;
public const ELEMENT_9 = 275;
public const ELEMENT_10 = 276;
public const ELEMENT_11 = 277;
public const ELEMENT_12 = 278;
public const ELEMENT_13 = 279;
public const ELEMENT_14 = 280;
public const ELEMENT_15 = 281;
public const ELEMENT_16 = 282;
public const ELEMENT_17 = 283;
public const ELEMENT_18 = 284;
public const ELEMENT_19 = 285;
public const ELEMENT_20 = 286;
public const ELEMENT_21 = 287;
public const ELEMENT_22 = 288;
public const ELEMENT_23 = 289;
public const ELEMENT_24 = 290;
public const ELEMENT_25 = 291;
public const ELEMENT_26 = 292;
public const ELEMENT_27 = 293;
public const ELEMENT_28 = 294;
public const ELEMENT_29 = 295;
public const ELEMENT_30 = 296;
public const ELEMENT_31 = 297;
public const ELEMENT_32 = 298;
public const ELEMENT_33 = 299;
public const ELEMENT_34 = 300;
public const ELEMENT_35 = 301;
public const ELEMENT_36 = 302;
public const ELEMENT_37 = 303;
public const ELEMENT_38 = 304;
public const ELEMENT_39 = 305;
public const ELEMENT_40 = 306;
public const ELEMENT_41 = 307;
public const ELEMENT_42 = 308;
public const ELEMENT_43 = 309;
public const ELEMENT_44 = 310;
public const ELEMENT_45 = 311;
public const ELEMENT_46 = 312;
public const ELEMENT_47 = 313;
public const ELEMENT_48 = 314;
public const ELEMENT_49 = 315;
public const ELEMENT_50 = 316;
public const ELEMENT_51 = 317;
public const ELEMENT_52 = 318;
public const ELEMENT_53 = 319;
public const ELEMENT_54 = 320;
public const ELEMENT_55 = 321;
public const ELEMENT_56 = 322;
public const ELEMENT_57 = 323;
public const ELEMENT_58 = 324;
public const ELEMENT_59 = 325;
public const ELEMENT_60 = 326;
public const ELEMENT_61 = 327;
public const ELEMENT_62 = 328;
public const ELEMENT_63 = 329;
public const ELEMENT_64 = 330;
public const ELEMENT_65 = 331;
public const ELEMENT_66 = 332;
public const ELEMENT_67 = 333;
public const ELEMENT_68 = 334;
public const ELEMENT_69 = 335;
public const ELEMENT_70 = 336;
public const ELEMENT_71 = 337;
public const ELEMENT_72 = 338;
public const ELEMENT_73 = 339;
public const ELEMENT_74 = 340;
public const ELEMENT_75 = 341;
public const ELEMENT_76 = 342;
public const ELEMENT_77 = 343;
public const ELEMENT_78 = 344;
public const ELEMENT_79 = 345;
public const ELEMENT_80 = 346;
public const ELEMENT_81 = 347;
public const ELEMENT_82 = 348;
public const ELEMENT_83 = 349;
public const ELEMENT_84 = 350;
public const ELEMENT_85 = 351;
public const ELEMENT_86 = 352;
public const ELEMENT_87 = 353;
public const ELEMENT_88 = 354;
public const ELEMENT_89 = 355;
public const ELEMENT_90 = 356;
public const ELEMENT_91 = 357;
public const ELEMENT_92 = 358;
public const ELEMENT_93 = 359;
public const ELEMENT_94 = 360;
public const ELEMENT_95 = 361;
public const ELEMENT_96 = 362;
public const ELEMENT_97 = 363;
public const ELEMENT_98 = 364;
public const ELEMENT_99 = 365;
public const ELEMENT_100 = 366;
public const ELEMENT_101 = 367;
public const ELEMENT_102 = 368;
public const ELEMENT_103 = 369;
public const ELEMENT_104 = 370;
public const ELEMENT_105 = 371;
public const ELEMENT_106 = 372;
public const ELEMENT_107 = 373;
public const ELEMENT_108 = 374;
public const ELEMENT_109 = 375;
public const ELEMENT_110 = 376;
public const ELEMENT_111 = 377;
public const ELEMENT_112 = 378;
public const ELEMENT_113 = 379;
public const ELEMENT_114 = 380;
public const ELEMENT_115 = 381;
public const ELEMENT_116 = 382;
public const ELEMENT_117 = 383;
public const ELEMENT_118 = 384;
public const SEAGRASS = 385;
public const CORAL = 386;
public const CORAL_BLOCK = 387;
public const CORAL_FAN = 388;
public const CORAL_FAN_DEAD = 389;
public const CORAL_FAN_HANG = 390;
public const CORAL_FAN_HANG2 = 391;
public const CORAL_FAN_HANG3 = 392;
public const KELP = 393;
public const DRIED_KELP_BLOCK = 394;
public const ACACIA_BUTTON = 395;
public const BIRCH_BUTTON = 396;
public const DARK_OAK_BUTTON = 397;
public const JUNGLE_BUTTON = 398;
public const SPRUCE_BUTTON = 399;
public const ACACIA_TRAPDOOR = 400;
public const BIRCH_TRAPDOOR = 401;
public const DARK_OAK_TRAPDOOR = 402;
public const JUNGLE_TRAPDOOR = 403;
public const SPRUCE_TRAPDOOR = 404;
public const ACACIA_PRESSURE_PLATE = 405;
public const BIRCH_PRESSURE_PLATE = 406;
public const DARK_OAK_PRESSURE_PLATE = 407;
public const JUNGLE_PRESSURE_PLATE = 408;
public const SPRUCE_PRESSURE_PLATE = 409;
public const CARVED_PUMPKIN = 410;
public const SEA_PICKLE = 411;
public const CONDUIT = 412;
public const TURTLE_EGG = 414;
public const BUBBLE_COLUMN = 415;
public const BARRIER = 416;
public const STONE_SLAB3 = 417;
public const BAMBOO = 418;
public const BAMBOO_SAPLING = 419;
public const SCAFFOLDING = 420;
public const STONE_SLAB4 = 421;
public const DOUBLE_STONE_SLAB3 = 422;
public const DOUBLE_STONE_SLAB4 = 423;
public const GRANITE_STAIRS = 424;
public const DIORITE_STAIRS = 425;
public const ANDESITE_STAIRS = 426;
public const POLISHED_GRANITE_STAIRS = 427;
public const POLISHED_DIORITE_STAIRS = 428;
public const POLISHED_ANDESITE_STAIRS = 429;
public const MOSSY_STONE_BRICK_STAIRS = 430;
public const SMOOTH_RED_SANDSTONE_STAIRS = 431;
public const SMOOTH_SANDSTONE_STAIRS = 432;
public const END_BRICK_STAIRS = 433;
public const MOSSY_COBBLESTONE_STAIRS = 434;
public const NORMAL_STONE_STAIRS = 435;
public const SPRUCE_STANDING_SIGN = 436;
public const SPRUCE_WALL_SIGN = 437;
public const SMOOTH_STONE = 438;
public const RED_NETHER_BRICK_STAIRS = 439;
public const SMOOTH_QUARTZ_STAIRS = 440;
public const BIRCH_STANDING_SIGN = 441;
public const BIRCH_WALL_SIGN = 442;
public const JUNGLE_STANDING_SIGN = 443;
public const JUNGLE_WALL_SIGN = 444;
public const ACACIA_STANDING_SIGN = 445;
public const ACACIA_WALL_SIGN = 446;
public const DARKOAK_STANDING_SIGN = 447;
public const DARKOAK_WALL_SIGN = 448;
public const LECTERN = 449;
public const GRINDSTONE = 450;
public const BLAST_FURNACE = 451;
public const STONECUTTER_BLOCK = 452;
public const SMOKER = 453;
public const LIT_SMOKER = 454;
public const CARTOGRAPHY_TABLE = 455;
public const FLETCHING_TABLE = 456;
public const SMITHING_TABLE = 457;
public const BARREL = 458;
public const LOOM = 459;
public const BELL = 461;
public const SWEET_BERRY_BUSH = 462;
public const LANTERN = 463;
public const CAMPFIRE = 464;
public const LAVA_CAULDRON = 465;
public const JIGSAW = 466;
public const WOOD = 467;
public const COMPOSTER = 468;
public const LIT_BLAST_FURNACE = 469;
}

View File

@ -0,0 +1,303 @@
<?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;
/**
* Constants for legacy metadata for various blocks.
*/
final class BlockLegacyMetadata{
private function __construct(){
//NOOP
}
public const ANVIL_NORMAL = 0;
public const ANVIL_SLIGHTLY_DAMAGED = 4;
public const ANVIL_VERY_DAMAGED = 8;
public const BAMBOO_FLAG_THICK = 0x01;
public const BAMBOO_FLAG_READY = 0x08;
public const BAMBOO_LEAF_SIZE_SHIFT = 1;
public const BAMBOO_LEAF_SIZE_MASK = 0x03;
public const BAMBOO_SAPLING_FLAG_READY = 0x01;
public const BARREL_FLAG_OPEN = 0x08;
public const BED_FLAG_HEAD = 0x08;
public const BED_FLAG_OCCUPIED = 0x04;
public const BEDROCK_FLAG_INFINIBURN = 0x01;
public const BELL_ATTACHMENT_FLOOR = 0;
public const BELL_ATTACHMENT_CEILING = 1;
public const BELL_ATTACHMENT_ONE_WALL = 2;
public const BELL_ATTACHMENT_TWO_WALLS = 3;
public const BREWING_STAND_FLAG_EAST = 0x01;
public const BREWING_STAND_FLAG_SOUTHWEST = 0x02;
public const BREWING_STAND_FLAG_NORTHWEST = 0x04;
public const BUTTON_FLAG_POWERED = 0x08;
public const CHEMISTRY_COMPOUND_CREATOR = 0;
public const CHEMISTRY_MATERIAL_REDUCER = 4;
public const CHEMISTRY_ELEMENT_CONSTRUCTOR = 8;
public const CHEMISTRY_LAB_TABLE = 12;
public const COLORED_TORCH_BP_BLUE = 0;
public const COLORED_TORCH_BP_PURPLE = 8;
public const COLORED_TORCH_RG_RED = 0;
public const COLORED_TORCH_RG_GREEN = 8;
public const CORAL_BLOCK_FLAG_DEAD = 0x8;
public const CORAL_FAN_EAST_WEST = 0;
public const CORAL_FAN_NORTH_SOUTH = 1;
public const CORAL_FAN_TYPE_MASK = 0x7;
public const CORAL_FAN_HANG_FLAG_DEAD = 0x2;
public const CORAL_FAN_HANG_TUBE = 0;
public const CORAL_FAN_HANG_BRAIN = 1;
public const CORAL_FAN_HANG2_BUBBLE = 0;
public const CORAL_FAN_HANG2_FIRE = 1;
public const CORAL_FAN_HANG3_HORN = 0;
public const CORAL_FAN_HANG_TYPE_MASK = 0x1;
public const CORAL_VARIANT_TUBE = 0;
public const CORAL_VARIANT_BRAIN = 1;
public const CORAL_VARIANT_BUBBLE = 2;
public const CORAL_VARIANT_FIRE = 3;
public const CORAL_VARIANT_HORN = 4;
public const DIRT_FLAG_COARSE = 0x1;
public const DOOR_FLAG_TOP = 0x08;
public const DOOR_BOTTOM_FLAG_OPEN = 0x04;
public const DOOR_TOP_FLAG_RIGHT = 0x01;
public const DOOR_TOP_FLAG_POWERED = 0x02;
public const DOUBLE_PLANT_SUNFLOWER = 0;
public const DOUBLE_PLANT_LILAC = 1;
public const DOUBLE_PLANT_TALLGRASS = 2;
public const DOUBLE_PLANT_LARGE_FERN = 3;
public const DOUBLE_PLANT_ROSE_BUSH = 4;
public const DOUBLE_PLANT_PEONY = 5;
public const DOUBLE_PLANT_FLAG_TOP = 0x08;
public const END_PORTAL_FRAME_FLAG_EYE = 0x04;
public const FENCE_GATE_FLAG_OPEN = 0x04;
public const FENCE_GATE_FLAG_IN_WALL = 0x08;
public const FLOWER_POPPY = 0;
public const FLOWER_BLUE_ORCHID = 1;
public const FLOWER_ALLIUM = 2;
public const FLOWER_AZURE_BLUET = 3;
public const FLOWER_RED_TULIP = 4;
public const FLOWER_ORANGE_TULIP = 5;
public const FLOWER_WHITE_TULIP = 6;
public const FLOWER_PINK_TULIP = 7;
public const FLOWER_OXEYE_DAISY = 8;
public const FLOWER_CORNFLOWER = 9;
public const FLOWER_LILY_OF_THE_VALLEY = 10;
public const FLOWER_POT_FLAG_OCCUPIED = 0x01;
public const HOPPER_FLAG_POWERED = 0x08;
public const INFESTED_STONE = 0;
public const INFESTED_COBBLESTONE = 1;
public const INFESTED_STONE_BRICK = 2;
public const INFESTED_STONE_BRICK_MOSSY = 3;
public const INFESTED_STONE_BRICK_CRACKED = 4;
public const INFESTED_STONE_BRICK_CHISELED = 5;
public const ITEM_FRAME_FLAG_HAS_MAP = 0x04;
public const LANTERN_FLAG_HANGING = 0x01;
public const LEAVES_FLAG_NO_DECAY = 0x04;
public const LEAVES_FLAG_CHECK_DECAY = 0x08;
public const LECTERN_FLAG_POWERED = 0x04;
public const LEVER_FLAG_POWERED = 0x08;
public const LIQUID_FLAG_FALLING = 0x08;
public const MUSHROOM_BLOCK_ALL_PORES = 0;
public const MUSHROOM_BLOCK_CAP_NORTHWEST_CORNER = 1;
public const MUSHROOM_BLOCK_CAP_NORTH_SIDE = 2;
public const MUSHROOM_BLOCK_CAP_NORTHEAST_CORNER = 3;
public const MUSHROOM_BLOCK_CAP_WEST_SIDE = 4;
public const MUSHROOM_BLOCK_CAP_TOP_ONLY = 5;
public const MUSHROOM_BLOCK_CAP_EAST_SIDE = 6;
public const MUSHROOM_BLOCK_CAP_SOUTHWEST_CORNER = 7;
public const MUSHROOM_BLOCK_CAP_SOUTH_SIDE = 8;
public const MUSHROOM_BLOCK_CAP_SOUTHEAST_CORNER = 9;
public const MUSHROOM_BLOCK_STEM = 10;
//11, 12 and 13 appear the same as 0
public const MUSHROOM_BLOCK_ALL_CAP = 14;
public const MUSHROOM_BLOCK_ALL_STEM = 15;
public const NETHER_PORTAL_AXIS_X = 1;
public const NETHER_PORTAL_AXIS_Z = 2;
public const NETHER_REACTOR_INACTIVE = 0;
public const NETHER_REACTOR_ACTIVE = 1;
public const NETHER_REACTOR_USED = 2;
public const PRESSURE_PLATE_FLAG_POWERED = 0x01;
public const PRISMARINE_NORMAL = 0;
public const PRISMARINE_DARK = 1;
public const PRISMARINE_BRICKS = 2;
public const PURPUR_NORMAL = 0;
public const PURPUR_PILLAR = 2;
public const QUARTZ_NORMAL = 0;
public const QUARTZ_CHISELED = 1;
public const QUARTZ_PILLAR = 2;
public const QUARTZ_SMOOTH = 3;
public const RAIL_STRAIGHT_NORTH_SOUTH = 0;
public const RAIL_STRAIGHT_EAST_WEST = 1;
public const RAIL_ASCENDING_EAST = 2;
public const RAIL_ASCENDING_WEST = 3;
public const RAIL_ASCENDING_NORTH = 4;
public const RAIL_ASCENDING_SOUTH = 5;
public const RAIL_CURVE_SOUTHEAST = 6;
public const RAIL_CURVE_SOUTHWEST = 7;
public const RAIL_CURVE_NORTHWEST = 8;
public const RAIL_CURVE_NORTHEAST = 9;
public const REDSTONE_COMPARATOR_FLAG_SUBTRACT = 0x04;
public const REDSTONE_COMPARATOR_FLAG_POWERED = 0x08;
public const REDSTONE_RAIL_FLAG_POWERED = 0x08;
public const SANDSTONE_NORMAL = 0;
public const SANDSTONE_CHISELED = 1;
public const SANDSTONE_CUT = 2;
public const SANDSTONE_SMOOTH = 3;
public const SAPLING_FLAG_READY = 0x08;
public const SEA_PICKLE_FLAG_NOT_UNDERWATER = 0x04;
public const SKULL_FLAG_NO_DROPS = 0x08;
public const SLAB_FLAG_UPPER = 0x08;
public const SPONGE_FLAG_WET = 0x01;
public const STAIR_FLAG_UPSIDE_DOWN = 0x04;
public const STONE_NORMAL = 0;
public const STONE_GRANITE = 1;
public const STONE_POLISHED_GRANITE = 2;
public const STONE_DIORITE = 3;
public const STONE_POLISHED_DIORITE = 4;
public const STONE_ANDESITE = 5;
public const STONE_POLISHED_ANDESITE = 6;
public const STONE_BRICK_NORMAL = 0;
public const STONE_BRICK_MOSSY = 1;
public const STONE_BRICK_CRACKED = 2;
public const STONE_BRICK_CHISELED = 3;
public const STONE_SLAB_SMOOTH_STONE = 0;
public const STONE_SLAB_SANDSTONE = 1;
public const STONE_SLAB_FAKE_WOODEN = 2;
public const STONE_SLAB_COBBLESTONE = 3;
public const STONE_SLAB_BRICK = 4;
public const STONE_SLAB_STONE_BRICK = 5;
public const STONE_SLAB_QUARTZ = 6;
public const STONE_SLAB_NETHER_BRICK = 7;
public const STONE_SLAB2_RED_SANDSTONE = 0;
public const STONE_SLAB2_PURPUR = 1;
public const STONE_SLAB2_PRISMARINE = 2;
public const STONE_SLAB2_DARK_PRISMARINE = 3;
public const STONE_SLAB2_PRISMARINE_BRICKS = 4;
public const STONE_SLAB2_MOSSY_COBBLESTONE = 5;
public const STONE_SLAB2_SMOOTH_SANDSTONE = 6;
public const STONE_SLAB2_RED_NETHER_BRICK = 7;
public const STONE_SLAB3_END_STONE_BRICK = 0;
public const STONE_SLAB3_SMOOTH_RED_SANDSTONE = 1;
public const STONE_SLAB3_POLISHED_ANDESITE = 2;
public const STONE_SLAB3_ANDESITE = 3;
public const STONE_SLAB3_DIORITE = 4;
public const STONE_SLAB3_POLISHED_DIORITE = 5;
public const STONE_SLAB3_GRANITE = 6;
public const STONE_SLAB3_POLISHED_GRANITE = 7;
public const STONE_SLAB4_MOSSY_STONE_BRICK = 0;
public const STONE_SLAB4_SMOOTH_QUARTZ = 1;
public const STONE_SLAB4_STONE = 2;
public const STONE_SLAB4_CUT_SANDSTONE = 3;
public const STONE_SLAB4_CUT_RED_SANDSTONE = 4;
public const TALLGRASS_NORMAL = 1;
public const TALLGRASS_FERN = 2;
public const TNT_FLAG_UNSTABLE = 0x01;
public const TNT_FLAG_UNDERWATER = 0x02;
public const TRAPDOOR_FLAG_UPPER = 0x04;
public const TRAPDOOR_FLAG_OPEN = 0x08;
public const TRIPWIRE_FLAG_TRIGGERED = 0x01;
public const TRIPWIRE_FLAG_SUSPENDED = 0x02;
public const TRIPWIRE_FLAG_CONNECTED = 0x04;
public const TRIPWIRE_FLAG_DISARMED = 0x08;
public const TRIPWIRE_HOOK_FLAG_CONNECTED = 0x04;
public const TRIPWIRE_HOOK_FLAG_POWERED = 0x08;
public const VINE_FLAG_SOUTH = 0x01;
public const VINE_FLAG_WEST = 0x02;
public const VINE_FLAG_NORTH = 0x04;
public const VINE_FLAG_EAST = 0x08;
public const WALL_COBBLESTONE = 0;
public const WALL_MOSSY_COBBLESTONE = 1;
public const WALL_GRANITE = 2;
public const WALL_DIORITE = 3;
public const WALL_ANDESITE = 4;
public const WALL_SANDSTONE = 5;
public const WALL_BRICK = 6;
public const WALL_STONE_BRICK = 7;
public const WALL_MOSSY_STONE_BRICK = 8;
public const WALL_NETHER_BRICK = 9;
public const WALL_END_STONE_BRICK = 10;
public const WALL_PRISMARINE = 11;
public const WALL_RED_SANDSTONE = 12;
public const WALL_RED_NETHER_BRICK = 13;
public const WOOD_FLAG_STRIPPED = 0x8;
}

View File

@ -1,727 +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\block;
/**
* Enum of all the block runtime IDs used by PocketMine-MP. These IDs are specific to PocketMine-MP and have no
* relevance to any Minecraft vanilla things.
*
* WARNING: DO NOT STORE THESE IDS. They can and will change without warning.
* They should ONLY be used to IDENTIFY blocks at runtime.
*/
final class BlockTypeIds{
private function __construct(){
//NOOP
}
public const AIR = 10000;
public const ACACIA_BUTTON = 10001;
public const ACACIA_DOOR = 10002;
public const ACACIA_FENCE = 10003;
public const ACACIA_FENCE_GATE = 10004;
public const ACACIA_LEAVES = 10005;
public const ACACIA_LOG = 10006;
public const ACACIA_PLANKS = 10007;
public const ACACIA_PRESSURE_PLATE = 10008;
public const ACACIA_SAPLING = 10009;
public const ACACIA_SIGN = 10010;
public const ACACIA_SLAB = 10011;
public const ACACIA_STAIRS = 10012;
public const ACACIA_TRAPDOOR = 10013;
public const ACACIA_WALL_SIGN = 10014;
public const ACACIA_WOOD = 10015;
public const ACTIVATOR_RAIL = 10016;
public const ALL_SIDED_MUSHROOM_STEM = 10017;
public const ALLIUM = 10018;
public const ANDESITE = 10019;
public const ANDESITE_SLAB = 10020;
public const ANDESITE_STAIRS = 10021;
public const ANDESITE_WALL = 10022;
public const ANVIL = 10023;
public const AZURE_BLUET = 10024;
public const BAMBOO = 10025;
public const BAMBOO_SAPLING = 10026;
public const BANNER = 10027;
public const BARREL = 10028;
public const BARRIER = 10029;
public const BEACON = 10030;
public const BED = 10031;
public const BEDROCK = 10032;
public const BEETROOTS = 10033;
public const BELL = 10034;
public const BIRCH_BUTTON = 10035;
public const BIRCH_DOOR = 10036;
public const BIRCH_FENCE = 10037;
public const BIRCH_FENCE_GATE = 10038;
public const BIRCH_LEAVES = 10039;
public const BIRCH_LOG = 10040;
public const BIRCH_PLANKS = 10041;
public const BIRCH_PRESSURE_PLATE = 10042;
public const BIRCH_SAPLING = 10043;
public const BIRCH_SIGN = 10044;
public const BIRCH_SLAB = 10045;
public const BIRCH_STAIRS = 10046;
public const BIRCH_TRAPDOOR = 10047;
public const BIRCH_WALL_SIGN = 10048;
public const BIRCH_WOOD = 10049;
public const BLAST_FURNACE = 10051;
public const BLUE_ICE = 10053;
public const BLUE_ORCHID = 10054;
public const BLUE_TORCH = 10055;
public const BONE_BLOCK = 10056;
public const BOOKSHELF = 10057;
public const BREWING_STAND = 10058;
public const BRICK_SLAB = 10059;
public const BRICK_STAIRS = 10060;
public const BRICK_WALL = 10061;
public const BRICKS = 10062;
public const BROWN_MUSHROOM = 10064;
public const BROWN_MUSHROOM_BLOCK = 10065;
public const CACTUS = 10066;
public const CAKE = 10067;
public const CARPET = 10068;
public const CARROTS = 10069;
public const CARVED_PUMPKIN = 10070;
public const CHEMICAL_HEAT = 10071;
public const CHEST = 10072;
public const CHISELED_QUARTZ = 10073;
public const CHISELED_RED_SANDSTONE = 10074;
public const CHISELED_SANDSTONE = 10075;
public const CHISELED_STONE_BRICKS = 10076;
public const CLAY = 10077;
public const COAL = 10078;
public const COAL_ORE = 10079;
public const COBBLESTONE = 10080;
public const COBBLESTONE_SLAB = 10081;
public const COBBLESTONE_STAIRS = 10082;
public const COBBLESTONE_WALL = 10083;
public const COBWEB = 10084;
public const COCOA_POD = 10085;
public const COMPOUND_CREATOR = 10086;
public const CONCRETE = 10087;
public const CONCRETE_POWDER = 10088;
public const CORAL = 10089;
public const CORAL_BLOCK = 10090;
public const CORAL_FAN = 10091;
public const CORNFLOWER = 10092;
public const CRACKED_STONE_BRICKS = 10093;
public const CRAFTING_TABLE = 10094;
public const CUT_RED_SANDSTONE = 10095;
public const CUT_RED_SANDSTONE_SLAB = 10096;
public const CUT_SANDSTONE = 10097;
public const CUT_SANDSTONE_SLAB = 10098;
public const DANDELION = 10100;
public const DARK_OAK_BUTTON = 10101;
public const DARK_OAK_DOOR = 10102;
public const DARK_OAK_FENCE = 10103;
public const DARK_OAK_FENCE_GATE = 10104;
public const DARK_OAK_LEAVES = 10105;
public const DARK_OAK_LOG = 10106;
public const DARK_OAK_PLANKS = 10107;
public const DARK_OAK_PRESSURE_PLATE = 10108;
public const DARK_OAK_SAPLING = 10109;
public const DARK_OAK_SIGN = 10110;
public const DARK_OAK_SLAB = 10111;
public const DARK_OAK_STAIRS = 10112;
public const DARK_OAK_TRAPDOOR = 10113;
public const DARK_OAK_WALL_SIGN = 10114;
public const DARK_OAK_WOOD = 10115;
public const DARK_PRISMARINE = 10116;
public const DARK_PRISMARINE_SLAB = 10117;
public const DARK_PRISMARINE_STAIRS = 10118;
public const DAYLIGHT_SENSOR = 10119;
public const DEAD_BUSH = 10120;
public const DETECTOR_RAIL = 10121;
public const DIAMOND = 10122;
public const DIAMOND_ORE = 10123;
public const DIORITE = 10124;
public const DIORITE_SLAB = 10125;
public const DIORITE_STAIRS = 10126;
public const DIORITE_WALL = 10127;
public const DIRT = 10128;
public const DOUBLE_TALLGRASS = 10129;
public const DRAGON_EGG = 10130;
public const DRIED_KELP = 10131;
public const DYED_SHULKER_BOX = 10132;
public const ELEMENT_ACTINIUM = 10133;
public const ELEMENT_ALUMINUM = 10134;
public const ELEMENT_AMERICIUM = 10135;
public const ELEMENT_ANTIMONY = 10136;
public const ELEMENT_ARGON = 10137;
public const ELEMENT_ARSENIC = 10138;
public const ELEMENT_ASTATINE = 10139;
public const ELEMENT_BARIUM = 10140;
public const ELEMENT_BERKELIUM = 10141;
public const ELEMENT_BERYLLIUM = 10142;
public const ELEMENT_BISMUTH = 10143;
public const ELEMENT_BOHRIUM = 10144;
public const ELEMENT_BORON = 10145;
public const ELEMENT_BROMINE = 10146;
public const ELEMENT_CADMIUM = 10147;
public const ELEMENT_CALCIUM = 10148;
public const ELEMENT_CALIFORNIUM = 10149;
public const ELEMENT_CARBON = 10150;
public const ELEMENT_CERIUM = 10151;
public const ELEMENT_CESIUM = 10152;
public const ELEMENT_CHLORINE = 10153;
public const ELEMENT_CHROMIUM = 10154;
public const ELEMENT_COBALT = 10155;
public const ELEMENT_CONSTRUCTOR = 10156;
public const ELEMENT_COPERNICIUM = 10157;
public const ELEMENT_COPPER = 10158;
public const ELEMENT_CURIUM = 10159;
public const ELEMENT_DARMSTADTIUM = 10160;
public const ELEMENT_DUBNIUM = 10161;
public const ELEMENT_DYSPROSIUM = 10162;
public const ELEMENT_EINSTEINIUM = 10163;
public const ELEMENT_ERBIUM = 10164;
public const ELEMENT_EUROPIUM = 10165;
public const ELEMENT_FERMIUM = 10166;
public const ELEMENT_FLEROVIUM = 10167;
public const ELEMENT_FLUORINE = 10168;
public const ELEMENT_FRANCIUM = 10169;
public const ELEMENT_GADOLINIUM = 10170;
public const ELEMENT_GALLIUM = 10171;
public const ELEMENT_GERMANIUM = 10172;
public const ELEMENT_GOLD = 10173;
public const ELEMENT_HAFNIUM = 10174;
public const ELEMENT_HASSIUM = 10175;
public const ELEMENT_HELIUM = 10176;
public const ELEMENT_HOLMIUM = 10177;
public const ELEMENT_HYDROGEN = 10178;
public const ELEMENT_INDIUM = 10179;
public const ELEMENT_IODINE = 10180;
public const ELEMENT_IRIDIUM = 10181;
public const ELEMENT_IRON = 10182;
public const ELEMENT_KRYPTON = 10183;
public const ELEMENT_LANTHANUM = 10184;
public const ELEMENT_LAWRENCIUM = 10185;
public const ELEMENT_LEAD = 10186;
public const ELEMENT_LITHIUM = 10187;
public const ELEMENT_LIVERMORIUM = 10188;
public const ELEMENT_LUTETIUM = 10189;
public const ELEMENT_MAGNESIUM = 10190;
public const ELEMENT_MANGANESE = 10191;
public const ELEMENT_MEITNERIUM = 10192;
public const ELEMENT_MENDELEVIUM = 10193;
public const ELEMENT_MERCURY = 10194;
public const ELEMENT_MOLYBDENUM = 10195;
public const ELEMENT_MOSCOVIUM = 10196;
public const ELEMENT_NEODYMIUM = 10197;
public const ELEMENT_NEON = 10198;
public const ELEMENT_NEPTUNIUM = 10199;
public const ELEMENT_NICKEL = 10200;
public const ELEMENT_NIHONIUM = 10201;
public const ELEMENT_NIOBIUM = 10202;
public const ELEMENT_NITROGEN = 10203;
public const ELEMENT_NOBELIUM = 10204;
public const ELEMENT_OGANESSON = 10205;
public const ELEMENT_OSMIUM = 10206;
public const ELEMENT_OXYGEN = 10207;
public const ELEMENT_PALLADIUM = 10208;
public const ELEMENT_PHOSPHORUS = 10209;
public const ELEMENT_PLATINUM = 10210;
public const ELEMENT_PLUTONIUM = 10211;
public const ELEMENT_POLONIUM = 10212;
public const ELEMENT_POTASSIUM = 10213;
public const ELEMENT_PRASEODYMIUM = 10214;
public const ELEMENT_PROMETHIUM = 10215;
public const ELEMENT_PROTACTINIUM = 10216;
public const ELEMENT_RADIUM = 10217;
public const ELEMENT_RADON = 10218;
public const ELEMENT_RHENIUM = 10219;
public const ELEMENT_RHODIUM = 10220;
public const ELEMENT_ROENTGENIUM = 10221;
public const ELEMENT_RUBIDIUM = 10222;
public const ELEMENT_RUTHENIUM = 10223;
public const ELEMENT_RUTHERFORDIUM = 10224;
public const ELEMENT_SAMARIUM = 10225;
public const ELEMENT_SCANDIUM = 10226;
public const ELEMENT_SEABORGIUM = 10227;
public const ELEMENT_SELENIUM = 10228;
public const ELEMENT_SILICON = 10229;
public const ELEMENT_SILVER = 10230;
public const ELEMENT_SODIUM = 10231;
public const ELEMENT_STRONTIUM = 10232;
public const ELEMENT_SULFUR = 10233;
public const ELEMENT_TANTALUM = 10234;
public const ELEMENT_TECHNETIUM = 10235;
public const ELEMENT_TELLURIUM = 10236;
public const ELEMENT_TENNESSINE = 10237;
public const ELEMENT_TERBIUM = 10238;
public const ELEMENT_THALLIUM = 10239;
public const ELEMENT_THORIUM = 10240;
public const ELEMENT_THULIUM = 10241;
public const ELEMENT_TIN = 10242;
public const ELEMENT_TITANIUM = 10243;
public const ELEMENT_TUNGSTEN = 10244;
public const ELEMENT_URANIUM = 10245;
public const ELEMENT_VANADIUM = 10246;
public const ELEMENT_XENON = 10247;
public const ELEMENT_YTTERBIUM = 10248;
public const ELEMENT_YTTRIUM = 10249;
public const ELEMENT_ZERO = 10250;
public const ELEMENT_ZINC = 10251;
public const ELEMENT_ZIRCONIUM = 10252;
public const EMERALD = 10253;
public const EMERALD_ORE = 10254;
public const ENCHANTING_TABLE = 10255;
public const END_PORTAL_FRAME = 10256;
public const END_ROD = 10257;
public const END_STONE = 10258;
public const END_STONE_BRICK_SLAB = 10259;
public const END_STONE_BRICK_STAIRS = 10260;
public const END_STONE_BRICK_WALL = 10261;
public const END_STONE_BRICKS = 10262;
public const ENDER_CHEST = 10263;
public const FAKE_WOODEN_SLAB = 10264;
public const FARMLAND = 10265;
public const FERN = 10266;
public const FIRE = 10267;
public const FLETCHING_TABLE = 10268;
public const FLOWER_POT = 10269;
public const FROSTED_ICE = 10270;
public const FURNACE = 10271;
public const GLASS = 10272;
public const GLASS_PANE = 10273;
public const GLOWING_OBSIDIAN = 10274;
public const GLOWSTONE = 10275;
public const GOLD = 10276;
public const GOLD_ORE = 10277;
public const GRANITE = 10278;
public const GRANITE_SLAB = 10279;
public const GRANITE_STAIRS = 10280;
public const GRANITE_WALL = 10281;
public const GRASS = 10282;
public const GRASS_PATH = 10283;
public const GRAVEL = 10284;
public const GREEN_TORCH = 10287;
public const HARDENED_CLAY = 10288;
public const HARDENED_GLASS = 10289;
public const HARDENED_GLASS_PANE = 10290;
public const HAY_BALE = 10291;
public const HOPPER = 10292;
public const ICE = 10293;
public const INFESTED_CHISELED_STONE_BRICK = 10294;
public const INFESTED_COBBLESTONE = 10295;
public const INFESTED_CRACKED_STONE_BRICK = 10296;
public const INFESTED_MOSSY_STONE_BRICK = 10297;
public const INFESTED_STONE = 10298;
public const INFESTED_STONE_BRICK = 10299;
public const INFO_UPDATE = 10300;
public const INFO_UPDATE2 = 10301;
public const INVISIBLE_BEDROCK = 10302;
public const IRON = 10303;
public const IRON_BARS = 10304;
public const IRON_DOOR = 10305;
public const IRON_ORE = 10306;
public const IRON_TRAPDOOR = 10307;
public const ITEM_FRAME = 10308;
public const JUKEBOX = 10309;
public const JUNGLE_BUTTON = 10310;
public const JUNGLE_DOOR = 10311;
public const JUNGLE_FENCE = 10312;
public const JUNGLE_FENCE_GATE = 10313;
public const JUNGLE_LEAVES = 10314;
public const JUNGLE_LOG = 10315;
public const JUNGLE_PLANKS = 10316;
public const JUNGLE_PRESSURE_PLATE = 10317;
public const JUNGLE_SAPLING = 10318;
public const JUNGLE_SIGN = 10319;
public const JUNGLE_SLAB = 10320;
public const JUNGLE_STAIRS = 10321;
public const JUNGLE_TRAPDOOR = 10322;
public const JUNGLE_WALL_SIGN = 10323;
public const JUNGLE_WOOD = 10324;
public const LAB_TABLE = 10325;
public const LADDER = 10326;
public const LANTERN = 10327;
public const LAPIS_LAZULI = 10328;
public const LAPIS_LAZULI_ORE = 10329;
public const LARGE_FERN = 10330;
public const LAVA = 10331;
public const LECTERN = 10332;
public const LEGACY_STONECUTTER = 10333;
public const LEVER = 10334;
public const LILAC = 10337;
public const LILY_OF_THE_VALLEY = 10338;
public const LILY_PAD = 10339;
public const LIT_PUMPKIN = 10341;
public const LOOM = 10342;
public const MAGMA = 10344;
public const MATERIAL_REDUCER = 10345;
public const MELON = 10346;
public const MELON_STEM = 10347;
public const MOB_HEAD = 10348;
public const MONSTER_SPAWNER = 10349;
public const MOSSY_COBBLESTONE = 10350;
public const MOSSY_COBBLESTONE_SLAB = 10351;
public const MOSSY_COBBLESTONE_STAIRS = 10352;
public const MOSSY_COBBLESTONE_WALL = 10353;
public const MOSSY_STONE_BRICK_SLAB = 10354;
public const MOSSY_STONE_BRICK_STAIRS = 10355;
public const MOSSY_STONE_BRICK_WALL = 10356;
public const MOSSY_STONE_BRICKS = 10357;
public const MUSHROOM_STEM = 10358;
public const MYCELIUM = 10359;
public const NETHER_BRICK_FENCE = 10360;
public const NETHER_BRICK_SLAB = 10361;
public const NETHER_BRICK_STAIRS = 10362;
public const NETHER_BRICK_WALL = 10363;
public const NETHER_BRICKS = 10364;
public const NETHER_PORTAL = 10365;
public const NETHER_QUARTZ_ORE = 10366;
public const NETHER_REACTOR_CORE = 10367;
public const NETHER_WART = 10368;
public const NETHER_WART_BLOCK = 10369;
public const NETHERRACK = 10370;
public const NOTE_BLOCK = 10371;
public const OAK_BUTTON = 10372;
public const OAK_DOOR = 10373;
public const OAK_FENCE = 10374;
public const OAK_FENCE_GATE = 10375;
public const OAK_LEAVES = 10376;
public const OAK_LOG = 10377;
public const OAK_PLANKS = 10378;
public const OAK_PRESSURE_PLATE = 10379;
public const OAK_SAPLING = 10380;
public const OAK_SIGN = 10381;
public const OAK_SLAB = 10382;
public const OAK_STAIRS = 10383;
public const OAK_TRAPDOOR = 10384;
public const OAK_WALL_SIGN = 10385;
public const OAK_WOOD = 10386;
public const OBSIDIAN = 10387;
public const ORANGE_TULIP = 10389;
public const OXEYE_DAISY = 10390;
public const PACKED_ICE = 10391;
public const PEONY = 10392;
public const PINK_TULIP = 10394;
public const PODZOL = 10395;
public const POLISHED_ANDESITE = 10396;
public const POLISHED_ANDESITE_SLAB = 10397;
public const POLISHED_ANDESITE_STAIRS = 10398;
public const POLISHED_DIORITE = 10399;
public const POLISHED_DIORITE_SLAB = 10400;
public const POLISHED_DIORITE_STAIRS = 10401;
public const POLISHED_GRANITE = 10402;
public const POLISHED_GRANITE_SLAB = 10403;
public const POLISHED_GRANITE_STAIRS = 10404;
public const POPPY = 10405;
public const POTATOES = 10406;
public const POWERED_RAIL = 10407;
public const PRISMARINE = 10408;
public const PRISMARINE_BRICKS = 10409;
public const PRISMARINE_BRICKS_SLAB = 10410;
public const PRISMARINE_BRICKS_STAIRS = 10411;
public const PRISMARINE_SLAB = 10412;
public const PRISMARINE_STAIRS = 10413;
public const PRISMARINE_WALL = 10414;
public const PUMPKIN = 10415;
public const PUMPKIN_STEM = 10416;
public const PURPLE_TORCH = 10418;
public const PURPUR = 10419;
public const PURPUR_PILLAR = 10420;
public const PURPUR_SLAB = 10421;
public const PURPUR_STAIRS = 10422;
public const QUARTZ = 10423;
public const QUARTZ_PILLAR = 10424;
public const QUARTZ_SLAB = 10425;
public const QUARTZ_STAIRS = 10426;
public const RAIL = 10427;
public const RED_MUSHROOM = 10429;
public const RED_MUSHROOM_BLOCK = 10430;
public const RED_NETHER_BRICK_SLAB = 10431;
public const RED_NETHER_BRICK_STAIRS = 10432;
public const RED_NETHER_BRICK_WALL = 10433;
public const RED_NETHER_BRICKS = 10434;
public const RED_SAND = 10435;
public const RED_SANDSTONE = 10436;
public const RED_SANDSTONE_SLAB = 10437;
public const RED_SANDSTONE_STAIRS = 10438;
public const RED_SANDSTONE_WALL = 10439;
public const RED_TORCH = 10440;
public const RED_TULIP = 10441;
public const REDSTONE = 10442;
public const REDSTONE_COMPARATOR = 10443;
public const REDSTONE_LAMP = 10444;
public const REDSTONE_ORE = 10445;
public const REDSTONE_REPEATER = 10446;
public const REDSTONE_TORCH = 10447;
public const REDSTONE_WIRE = 10448;
public const RESERVED6 = 10449;
public const ROSE_BUSH = 10450;
public const SAND = 10451;
public const SANDSTONE = 10452;
public const SANDSTONE_SLAB = 10453;
public const SANDSTONE_STAIRS = 10454;
public const SANDSTONE_WALL = 10455;
public const SEA_LANTERN = 10456;
public const SEA_PICKLE = 10457;
public const SHULKER_BOX = 10458;
public const SLIME = 10459;
public const SMOKER = 10460;
public const SMOOTH_QUARTZ = 10461;
public const SMOOTH_QUARTZ_SLAB = 10462;
public const SMOOTH_QUARTZ_STAIRS = 10463;
public const SMOOTH_RED_SANDSTONE = 10464;
public const SMOOTH_RED_SANDSTONE_SLAB = 10465;
public const SMOOTH_RED_SANDSTONE_STAIRS = 10466;
public const SMOOTH_SANDSTONE = 10467;
public const SMOOTH_SANDSTONE_SLAB = 10468;
public const SMOOTH_SANDSTONE_STAIRS = 10469;
public const SMOOTH_STONE = 10470;
public const SMOOTH_STONE_SLAB = 10471;
public const SNOW = 10472;
public const SNOW_LAYER = 10473;
public const SOUL_SAND = 10474;
public const SPONGE = 10475;
public const SPRUCE_BUTTON = 10476;
public const SPRUCE_DOOR = 10477;
public const SPRUCE_FENCE = 10478;
public const SPRUCE_FENCE_GATE = 10479;
public const SPRUCE_LEAVES = 10480;
public const SPRUCE_LOG = 10481;
public const SPRUCE_PLANKS = 10482;
public const SPRUCE_PRESSURE_PLATE = 10483;
public const SPRUCE_SAPLING = 10484;
public const SPRUCE_SIGN = 10485;
public const SPRUCE_SLAB = 10486;
public const SPRUCE_STAIRS = 10487;
public const SPRUCE_TRAPDOOR = 10488;
public const SPRUCE_WALL_SIGN = 10489;
public const SPRUCE_WOOD = 10490;
public const STAINED_CLAY = 10491;
public const STAINED_GLASS = 10492;
public const STAINED_GLASS_PANE = 10493;
public const STAINED_HARDENED_GLASS = 10494;
public const STAINED_HARDENED_GLASS_PANE = 10495;
public const STONE = 10496;
public const STONE_BRICK_SLAB = 10497;
public const STONE_BRICK_STAIRS = 10498;
public const STONE_BRICK_WALL = 10499;
public const STONE_BRICKS = 10500;
public const STONE_BUTTON = 10501;
public const STONE_PRESSURE_PLATE = 10502;
public const STONE_SLAB = 10503;
public const STONE_STAIRS = 10504;
public const STONECUTTER = 10505;
public const SUGARCANE = 10518;
public const SUNFLOWER = 10519;
public const SWEET_BERRY_BUSH = 10520;
public const TALL_GRASS = 10521;
public const TNT = 10522;
public const TORCH = 10523;
public const TRAPPED_CHEST = 10524;
public const TRIPWIRE = 10525;
public const TRIPWIRE_HOOK = 10526;
public const UNDERWATER_TORCH = 10527;
public const VINES = 10528;
public const WALL_BANNER = 10529;
public const WALL_CORAL_FAN = 10530;
public const WATER = 10531;
public const WEIGHTED_PRESSURE_PLATE_HEAVY = 10532;
public const WEIGHTED_PRESSURE_PLATE_LIGHT = 10533;
public const WHEAT = 10534;
public const WHITE_TULIP = 10536;
public const WOOL = 10537;
public const GLAZED_TERRACOTTA = 10539;
public const AMETHYST = 10540;
public const ANCIENT_DEBRIS = 10541;
public const BASALT = 10542;
public const POLISHED_BASALT = 10543;
public const SMOOTH_BASALT = 10544;
public const BLACKSTONE = 10545;
public const BLACKSTONE_SLAB = 10546;
public const BLACKSTONE_STAIRS = 10547;
public const BLACKSTONE_WALL = 10548;
public const POLISHED_BLACKSTONE = 10549;
public const POLISHED_BLACKSTONE_BUTTON = 10550;
public const POLISHED_BLACKSTONE_PRESSURE_PLATE = 10551;
public const POLISHED_BLACKSTONE_SLAB = 10552;
public const POLISHED_BLACKSTONE_STAIRS = 10553;
public const POLISHED_BLACKSTONE_WALL = 10554;
public const CHISELED_POLISHED_BLACKSTONE = 10555;
public const POLISHED_BLACKSTONE_BRICKS = 10556;
public const POLISHED_BLACKSTONE_BRICK_SLAB = 10557;
public const POLISHED_BLACKSTONE_BRICK_STAIRS = 10558;
public const POLISHED_BLACKSTONE_BRICK_WALL = 10559;
public const CRACKED_POLISHED_BLACKSTONE_BRICKS = 10560;
public const LIGHT = 10561;
public const RAW_COPPER = 10562;
public const RAW_GOLD = 10563;
public const RAW_IRON = 10564;
public const CALCITE = 10565;
public const DEEPSLATE = 10566;
public const DEEPSLATE_BRICKS = 10567;
public const DEEPSLATE_BRICK_SLAB = 10568;
public const DEEPSLATE_BRICK_STAIRS = 10569;
public const DEEPSLATE_BRICK_WALL = 10570;
public const CRACKED_DEEPSLATE_BRICKS = 10571;
public const DEEPSLATE_TILES = 10572;
public const DEEPSLATE_TILE_SLAB = 10573;
public const DEEPSLATE_TILE_STAIRS = 10574;
public const DEEPSLATE_TILE_WALL = 10575;
public const CRACKED_DEEPSLATE_TILES = 10576;
public const COBBLED_DEEPSLATE = 10577;
public const COBBLED_DEEPSLATE_SLAB = 10578;
public const COBBLED_DEEPSLATE_STAIRS = 10579;
public const COBBLED_DEEPSLATE_WALL = 10580;
public const POLISHED_DEEPSLATE = 10581;
public const POLISHED_DEEPSLATE_SLAB = 10582;
public const POLISHED_DEEPSLATE_STAIRS = 10583;
public const POLISHED_DEEPSLATE_WALL = 10584;
public const QUARTZ_BRICKS = 10585;
public const CHISELED_DEEPSLATE = 10586;
public const CHISELED_NETHER_BRICKS = 10587;
public const CRACKED_NETHER_BRICKS = 10588;
public const TUFF = 10589;
public const SOUL_TORCH = 10590;
public const SOUL_LANTERN = 10591;
public const SOUL_SOIL = 10592;
public const SOUL_FIRE = 10593;
public const SHROOMLIGHT = 10594;
public const MANGROVE_PLANKS = 10595;
public const CRIMSON_PLANKS = 10596;
public const WARPED_PLANKS = 10597;
public const MANGROVE_FENCE = 10598;
public const CRIMSON_FENCE = 10599;
public const WARPED_FENCE = 10600;
public const MANGROVE_SLAB = 10601;
public const CRIMSON_SLAB = 10602;
public const WARPED_SLAB = 10603;
public const MANGROVE_LOG = 10604;
public const CRIMSON_STEM = 10605;
public const WARPED_STEM = 10606;
public const MANGROVE_WOOD = 10607;
public const CRIMSON_HYPHAE = 10608;
public const WARPED_HYPHAE = 10609;
public const MANGROVE_TRAPDOOR = 10610;
public const CRIMSON_TRAPDOOR = 10611;
public const WARPED_TRAPDOOR = 10612;
public const MANGROVE_BUTTON = 10613;
public const CRIMSON_BUTTON = 10614;
public const WARPED_BUTTON = 10615;
public const MANGROVE_PRESSURE_PLATE = 10616;
public const CRIMSON_PRESSURE_PLATE = 10617;
public const WARPED_PRESSURE_PLATE = 10618;
public const MANGROVE_DOOR = 10619;
public const CRIMSON_DOOR = 10620;
public const WARPED_DOOR = 10621;
public const MANGROVE_FENCE_GATE = 10622;
public const CRIMSON_FENCE_GATE = 10623;
public const WARPED_FENCE_GATE = 10624;
public const MANGROVE_STAIRS = 10625;
public const CRIMSON_STAIRS = 10626;
public const WARPED_STAIRS = 10627;
public const MANGROVE_SIGN = 10628;
public const CRIMSON_SIGN = 10629;
public const WARPED_SIGN = 10630;
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;
public const DEEPSLATE_EMERALD_ORE = 10638;
public const DEEPSLATE_LAPIS_LAZULI_ORE = 10639;
public const DEEPSLATE_REDSTONE_ORE = 10640;
public const DEEPSLATE_IRON_ORE = 10641;
public const DEEPSLATE_GOLD_ORE = 10642;
public const DEEPSLATE_COPPER_ORE = 10643;
public const COPPER_ORE = 10644;
public const NETHER_GOLD_ORE = 10645;
public const MUD = 10646;
public const MUD_BRICKS = 10647;
public const MUD_BRICK_SLAB = 10648;
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 SPORE_BLOSSOM = 10669;
public const CAULDRON = 10670;
public const WATER_CAULDRON = 10671;
public const LAVA_CAULDRON = 10672;
public const POTION_CAULDRON = 10673;
public const POWDER_SNOW_CAULDRON = 10674;
public const CHORUS_FLOWER = 10675;
public const CHORUS_PLANT = 10676;
public const MANGROVE_ROOTS = 10677;
public const MUDDY_MANGROVE_ROOTS = 10678;
public const FROGLIGHT = 10679;
public const TWISTING_VINES = 10680;
public const WEEPING_VINES = 10681;
public const CHAIN = 10682;
public const SCULK = 10683;
public const GLOWING_ITEM_FRAME = 10684;
public const MANGROVE_LEAVES = 10685;
public const AZALEA_LEAVES = 10686;
public const FLOWERING_AZALEA_LEAVES = 10687;
public const REINFORCED_DEEPSLATE = 10688;
public const FIRST_UNUSED_BLOCK_ID = 10689;
private static int $nextDynamicId = self::FIRST_UNUSED_BLOCK_ID;
/**
* Returns a new runtime block type ID, e.g. for use by a custom block.
*/
public static function newId() : int{
return self::$nextDynamicId++;
}
}

View File

@ -1,52 +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\block;
use function array_fill_keys;
use function array_keys;
final class BlockTypeInfo{
/**
* @var true[]
* @phpstan-var array<string, true>
*/
private array $typeTags;
/**
* @param string[] $typeTags
*/
public function __construct(
private BlockBreakInfo $breakInfo,
array $typeTags = []
){
$this->typeTags = array_fill_keys($typeTags, true);
}
public function getBreakInfo() : BlockBreakInfo{ return $this->breakInfo; }
/** @return string[] */
public function getTypeTags() : array{ return array_keys($this->typeTags); }
public function hasTypeTag(string $tag) : bool{ return isset($this->typeTags[$tag]); }
}

View File

@ -1,34 +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\block;
final class BlockTypeTags{
private const PREFIX = "pocketmine:";
public const DIRT = self::PREFIX . "dirt";
public const MUD = self::PREFIX . "mud";
public const SAND = self::PREFIX . "sand";
public const POTTABLE_PLANTS = self::PREFIX . "pottable";
public const FIRE = self::PREFIX . "fire";
}

View File

@ -23,8 +23,8 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\PillarRotationTrait;
use pocketmine\block\utils\PillarRotationInMetadataTrait;
class BoneBlock extends Opaque{
use PillarRotationTrait;
use PillarRotationInMetadataTrait;
}

View File

@ -26,7 +26,6 @@ namespace pocketmine\block;
use pocketmine\block\tile\BrewingStand as TileBrewingStand;
use pocketmine\block\utils\BrewingStandSlot;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
use pocketmine\math\Axis;
use pocketmine\math\AxisAlignedBB;
@ -43,8 +42,33 @@ class BrewingStand extends Transparent{
*/
protected array $slots = [];
protected function describeState(RuntimeDataDescriber $w) : void{
$w->brewingStandSlots($this->slots);
protected function writeStateToMeta() : int{
$flags = 0;
foreach([
BlockLegacyMetadata::BREWING_STAND_FLAG_EAST => BrewingStandSlot::EAST(),
BlockLegacyMetadata::BREWING_STAND_FLAG_NORTHWEST => BrewingStandSlot::NORTHWEST(),
BlockLegacyMetadata::BREWING_STAND_FLAG_SOUTHWEST => BrewingStandSlot::SOUTHWEST(),
] as $flag => $slot){
$flags |= (array_key_exists($slot->id(), $this->slots) ? $flag : 0);
}
return $flags;
}
public function readStateFromData(int $id, int $stateMeta) : void{
$this->slots = [];
foreach([
BlockLegacyMetadata::BREWING_STAND_FLAG_EAST => BrewingStandSlot::EAST(),
BlockLegacyMetadata::BREWING_STAND_FLAG_NORTHWEST => BrewingStandSlot::NORTHWEST(),
BlockLegacyMetadata::BREWING_STAND_FLAG_SOUTHWEST => BrewingStandSlot::SOUTHWEST(),
] as $flag => $slot){
if(($stateMeta & $flag) !== 0){
$this->slots[$slot->id()] = $slot;
}
}
}
public function getStateBitmask() : int{
return 0b111;
}
protected function recalculateCollisionBoxes() : array{
@ -94,7 +118,7 @@ class BrewingStand extends Transparent{
return $this;
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player instanceof Player){
$stand = $this->position->getWorld()->getTile($this->position);
if($stand instanceof TileBrewingStand && $stand->canOpenWith($item->getCustomName())){

View File

@ -24,7 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\AnyFacingTrait;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\item\Item;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
@ -38,9 +38,18 @@ abstract class Button extends Flowable{
protected bool $pressed = false;
protected function describeState(RuntimeDataDescriber $w) : void{
$w->facing($this->facing);
$w->bool($this->pressed);
protected function writeStateToMeta() : int{
return BlockDataSerializer::writeFacing($this->facing) | ($this->pressed ? BlockLegacyMetadata::BUTTON_FLAG_POWERED : 0);
}
public function readStateFromData(int $id, int $stateMeta) : void{
//TODO: in PC it's (6 - facing) for every meta except 0 (down)
$this->facing = BlockDataSerializer::readFacing($stateMeta & 0x07);
$this->pressed = ($stateMeta & BlockLegacyMetadata::BUTTON_FLAG_POWERED) !== 0;
}
public function getStateBitmask() : int{
return 0b1111;
}
public function isPressed() : bool{ return $this->pressed; }
@ -61,7 +70,7 @@ abstract class Button extends Flowable{
abstract protected function getActivationTime() : int;
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->pressed){
$this->pressed = true;
$world = $this->position->getWorld();

View File

@ -23,8 +23,8 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\entity\Entity;
use pocketmine\event\block\BlockGrowEvent;
use pocketmine\event\entity\EntityDamageByBlockEvent;
@ -41,8 +41,16 @@ class Cactus extends Transparent{
protected int $age = 0;
protected function describeState(RuntimeDataDescriber $w) : void{
$w->boundedInt(4, 0, self::MAX_AGE, $this->age);
protected function writeStateToMeta() : int{
return $this->age;
}
public function readStateFromData(int $id, int $stateMeta) : void{
$this->age = BlockDataSerializer::readBoundedInt("age", $stateMeta, 0, self::MAX_AGE);
}
public function getStateBitmask() : int{
return 0b1111;
}
public function getAge() : int{ return $this->age; }
@ -78,13 +86,10 @@ class Cactus extends Transparent{
return true;
}
private function canBeSupportedBy(Block $block) : bool{
return $block->isSameType($this) || $block->hasTypeTag(BlockTypeTags::SAND);
}
public function onNearbyBlockChange() : void{
$down = $this->getSide(Facing::DOWN);
$world = $this->position->getWorld();
if(!$this->canBeSupportedBy($this->getSide(Facing::DOWN))){
if($down->getId() !== BlockLegacyIds::SAND && !$down->isSameType($this)){
$world->useBreakOn($this->position);
}else{
foreach(Facing::HORIZONTAL as $side){
@ -110,7 +115,7 @@ class Cactus extends Transparent{
break;
}
$b = $world->getBlockAt($this->position->x, $this->position->y + $y, $this->position->z);
if($b->getTypeId() === BlockTypeIds::AIR){
if($b->getId() === BlockLegacyIds::AIR){
$ev = new BlockGrowEvent($b, VanillaBlocks::CACTUS());
$ev->call();
if($ev->isCancelled()){
@ -131,7 +136,8 @@ class Cactus extends Transparent{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->canBeSupportedBy($this->getSide(Facing::DOWN))){
$down = $this->getSide(Facing::DOWN);
if($down->getId() === BlockLegacyIds::SAND || $down->isSameType($this)){
foreach(Facing::HORIZONTAL as $side){
if($this->getSide($side)->isSolid()){
return false;

View File

@ -23,21 +23,33 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\block\utils\SupportType;
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 BaseCake{
class Cake extends Transparent implements FoodSource{
public const MAX_BITES = 6;
protected int $bites = 0;
protected function describeState(RuntimeDataDescriber $w) : void{
$w->boundedInt(3, 0, self::MAX_BITES, $this->bites);
protected function writeStateToMeta() : int{
return $this->bites;
}
public function readStateFromData(int $id, int $stateMeta) : void{
$this->bites = BlockDataSerializer::readBoundedInt("bites", $stateMeta, 0, self::MAX_BITES);
}
public function getStateBitmask() : int{
return 0b111;
}
/**
@ -52,6 +64,10 @@ class Cake extends BaseCake{
];
}
public function getSupportType(int $facing) : SupportType{
return SupportType::NONE();
}
public function getBites() : int{ return $this->bites; }
/** @return $this */
@ -63,27 +79,49 @@ class Cake extends BaseCake{
return $this;
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
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;
}
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->getId() !== BlockLegacyIds::AIR){
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
return parent::onInteract($item, $face, $clickVector, $player, $returnedItems);
return false;
}
public function getResidue() : Block{
public function onNearbyBlockChange() : void{
if($this->getSide(Facing::DOWN)->getId() === BlockLegacyIds::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);
}
return false;
}
public function getFoodRestore() : int{
return 2;
}
public function getSaturationRestore() : float{
return 0.4;
}
public function requiresHunger() : bool{
return true;
}
/**
* @return Block
*/
public function getResidue(){
$clone = clone $this;
$clone->bites++;
if($clone->bites > self::MAX_BITES){
@ -91,4 +129,15 @@ class Cake extends BaseCake{
}
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

@ -1,78 +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\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, array &$returnedItems = []) : bool{
if($this->onInteractCandle($item, $face, $clickVector, $player, $returnedItems)){
return true;
}
return parent::onInteract($item, $face, $clickVector, $player, $returnedItems);
}
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

@ -1,40 +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\block;
use pocketmine\block\utils\ColoredTrait;
use pocketmine\block\utils\DyeColor;
class CakeWithDyedCandle extends CakeWithCandle{
use ColoredTrait;
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
$this->color = DyeColor::WHITE();
parent::__construct($idInfo, $name, $typeInfo);
}
public function getCandle() : Candle{
return VanillaBlocks::DYED_CANDLE()->setColor($this->color);
}
}

View File

@ -1,126 +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\block;
use pocketmine\block\utils\CandleTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
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 {
describeState as encodeLitState;
getLightLevel as getBaseLightLevel;
}
public const MIN_COUNT = 1;
public const MAX_COUNT = 4;
private int $count = self::MIN_COUNT;
protected function describeState(RuntimeDataDescriber $w) : void{
$this->encodeLitState($w);
$w->boundedInt(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)
];
}
public function getSupportType(int $facing) : SupportType{
return SupportType::NONE();
}
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

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\ColoredTrait;
use pocketmine\block\utils\ColorInMetadataTrait;
use pocketmine\block\utils\DyeColor;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
@ -33,11 +33,11 @@ use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
class Carpet extends Flowable{
use ColoredTrait;
use ColorInMetadataTrait;
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
$this->color = DyeColor::WHITE();
parent::__construct($idInfo, $name, $typeInfo);
parent::__construct($idInfo, $name, $breakInfo);
}
public function isSolid() : bool{
@ -53,7 +53,7 @@ class Carpet extends Flowable{
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){
if($down->getId() !== BlockLegacyIds::AIR){
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
@ -61,7 +61,7 @@ class Carpet extends Flowable{
}
public function onNearbyBlockChange() : void{
if($this->getSide(Facing::DOWN)->getTypeId() === BlockTypeIds::AIR){
if($this->getSide(Facing::DOWN)->getId() === BlockLegacyIds::AIR){
$this->position->getWorld()->useBreakOn($this->position);
}
}

View File

@ -35,7 +35,7 @@ class Carrot extends Crops{
];
}
public function asItem() : Item{
public function getPickedItem(bool $addUserData = false) : Item{
return VanillaItems::CARROT();
}
}

View File

@ -1,44 +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\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, array &$returnedItems = []) : bool{
if($player !== null){
$player->setCurrentWindow(new CartographyTableInventory($this->position));
}
return true;
}
public function getFuelTime() : int{
return 300;
}
}

View File

@ -23,10 +23,23 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
use pocketmine\block\utils\HorizontalFacingTrait;
class CarvedPumpkin extends Opaque{
use FacesOppositePlacingPlayerTrait;
use HorizontalFacingTrait;
public function readStateFromData(int $id, int $stateMeta) : void{
$this->facing = BlockDataSerializer::readLegacyHorizontalFacing($stateMeta & 0x03);
}
protected function writeStateToMeta() : int{
return BlockDataSerializer::writeLegacyHorizontalFacing($this->facing);
}
public function getStateBitmask() : int{
return 0b11;
}
}

View File

@ -1,104 +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\block;
use pocketmine\block\tile\Cauldron as TileCauldron;
use pocketmine\block\utils\SupportType;
use pocketmine\item\Item;
use pocketmine\item\ItemTypeIds;
use pocketmine\item\Potion;
use pocketmine\item\PotionType;
use pocketmine\item\SplashPotion;
use pocketmine\item\VanillaItems;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use function assert;
final class Cauldron extends Transparent{
public function writeStateToWorld() : void{
parent::writeStateToWorld();
$tile = $this->position->getWorld()->getTile($this->position);
assert($tile instanceof TileCauldron);
//empty cauldrons don't use this information
$tile->setCustomWaterColor(null);
$tile->setPotionItem(null);
}
protected function recalculateCollisionBoxes() : array{
$result = [
AxisAlignedBB::one()->trim(Facing::UP, 11 / 16) //bottom of the cauldron
];
foreach(Facing::HORIZONTAL as $f){ //add the frame parts around the bowl
$result[] = AxisAlignedBB::one()->trim($f, 14 / 16);
}
return $result;
}
public function getSupportType(int $facing) : SupportType{
return $facing === Facing::UP ? SupportType::EDGE() : SupportType::NONE();
}
/**
* @param Item[] &$returnedItems
*/
private function fill(int $amount, FillableCauldron $result, Item $usedItem, Item $returnedItem, array &$returnedItems) : void{
$this->position->getWorld()->setBlock($this->position, $result->setFillLevel($amount));
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), $result->getFillSound());
$usedItem->pop();
$returnedItems[] = $returnedItem;
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item->getTypeId() === ItemTypeIds::WATER_BUCKET){
$this->fill(FillableCauldron::MAX_FILL_LEVEL, VanillaBlocks::WATER_CAULDRON(), $item, VanillaItems::BUCKET(), $returnedItems);
}elseif($item->getTypeId() === ItemTypeIds::LAVA_BUCKET){
$this->fill(FillableCauldron::MAX_FILL_LEVEL, VanillaBlocks::LAVA_CAULDRON(), $item, VanillaItems::BUCKET(), $returnedItems);
}elseif($item->getTypeId() === ItemTypeIds::POWDER_SNOW_BUCKET){
//TODO: powder snow cauldron
}elseif($item instanceof Potion || $item instanceof SplashPotion){ //TODO: lingering potion
if($item->getType()->equals(PotionType::WATER())){
$this->fill(WaterCauldron::WATER_BOTTLE_FILL_AMOUNT, VanillaBlocks::WATER_CAULDRON(), $item, VanillaItems::GLASS_BOTTLE(), $returnedItems);
}else{
$this->fill(PotionCauldron::POTION_FILL_AMOUNT, VanillaBlocks::POTION_CAULDRON()->setPotionItem($item), $item, VanillaItems::GLASS_BOTTLE(), $returnedItems);
}
}
return true;
}
public function onNearbyBlockChange() : void{
$world = $this->position->getWorld();
if($world->getBlock($this->position->up())->getTypeId() === BlockTypeIds::WATER){
$cauldron = VanillaBlocks::WATER_CAULDRON()->setFillLevel(FillableCauldron::MAX_FILL_LEVEL);
$world->setBlock($this->position, $cauldron);
$world->addSound($this->position->add(0.5, 0.5, 0.5), $cauldron->getFillSound());
}
}
}

View File

@ -1,48 +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\block;
use pocketmine\block\utils\PillarRotationTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\math\Axis;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
final class Chain extends Transparent{
use PillarRotationTrait;
public function getSupportType(int $facing) : SupportType{
return $this->axis === Axis::Y && Facing::axis($facing) === Axis::Y ? SupportType::CENTER() : SupportType::NONE();
}
protected function recalculateCollisionBoxes() : array{
$bb = AxisAlignedBB::one();
foreach([Axis::Y, Axis::Z, Axis::X] as $axis){
if($axis !== $this->axis){
$bb->squash($axis, 13 / 32);
}
}
return [$bb];
}
}

View File

@ -23,9 +23,11 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\item\Item;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
@ -33,7 +35,19 @@ final class ChemistryTable extends Opaque{
use FacesOppositePlacingPlayerTrait;
use HorizontalFacingTrait;
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
public function readStateFromData(int $id, int $stateMeta) : void{
$this->facing = Facing::opposite(BlockDataSerializer::readLegacyHorizontalFacing($stateMeta & 0x3));
}
protected function writeStateToMeta() : int{
return BlockDataSerializer::writeLegacyHorizontalFacing(Facing::opposite($this->facing));
}
public function getStateBitmask() : int{
return 0b0011;
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
//TODO
return false;
}

View File

@ -25,7 +25,7 @@ namespace pocketmine\block;
use pocketmine\block\tile\Chest as TileChest;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\NormalHorizontalFacingInMetadataTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\event\block\ChestPairEvent;
use pocketmine\item\Item;
@ -36,7 +36,7 @@ use pocketmine\player\Player;
class Chest extends Transparent{
use FacesOppositePlacingPlayerTrait;
use HorizontalFacingTrait;
use NormalHorizontalFacingInMetadataTrait;
/**
* @return AxisAlignedBB[]
@ -74,7 +74,7 @@ class Chest extends Transparent{
}
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player instanceof Player){
$chest = $this->position->getWorld()->getTile($this->position);

View File

@ -1,233 +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\block;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\entity\projectile\Projectile;
use pocketmine\event\block\StructureGrowEvent;
use pocketmine\item\Item;
use pocketmine\math\Axis;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\RayTraceResult;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
use pocketmine\world\Position;
use pocketmine\world\sound\ChorusFlowerDieSound;
use pocketmine\world\sound\ChorusFlowerGrowSound;
use pocketmine\world\World;
use function array_rand;
use function mt_rand;
final class ChorusFlower extends Flowable{
public const MIN_AGE = 0;
public const MAX_AGE = 5;
private const MAX_STEM_HEIGHT = 5;
private int $age = self::MIN_AGE;
protected function describeState(RuntimeDataDescriber $w) : void{
$w->boundedInt(3, self::MIN_AGE, self::MAX_AGE, $this->age);
}
public function getAge() : int{ return $this->age; }
/** @return $this */
public function setAge(int $age) : self{
if($age < self::MIN_AGE || $age > self::MAX_AGE){
throw new \InvalidArgumentException("Age must be in the range " . self::MIN_AGE . " ... " . self::MAX_AGE);
}
$this->age = $age;
return $this;
}
protected function recalculateCollisionBoxes() : array{
return [AxisAlignedBB::one()];
}
private function canBeSupportedAt(Position $position) : bool{
$world = $position->getWorld();
$down = $world->getBlock($position->down());
if($down->getTypeId() === BlockTypeIds::END_STONE || $down->getTypeId() === BlockTypeIds::CHORUS_PLANT){
return true;
}
$plantAdjacent = false;
foreach($position->sidesAroundAxis(Axis::Y) as $sidePosition){
$block = $world->getBlock($sidePosition);
if($block->getTypeId() === BlockTypeIds::CHORUS_PLANT){
if($plantAdjacent){ //at most one plant may be horizontally adjacent
return false;
}
$plantAdjacent = true;
}elseif($block->getTypeId() !== BlockTypeIds::AIR){
return false;
}
}
return $plantAdjacent;
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedAt($blockReplace->getPosition())){
return false;
}
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedAt($this->position)){
$this->position->getWorld()->useBreakOn($this->position);
}
}
public function onProjectileHit(Projectile $projectile, RayTraceResult $hitResult) : void{
$this->position->getWorld()->useBreakOn($this->position);
}
public function ticksRandomly() : bool{ return $this->age < self::MAX_AGE; }
/**
* @phpstan-return array{int, bool}
*/
private function scanStem() : array{
$world = $this->position->getWorld();
$stemHeight = 0;
$endStoneBelow = false;
for($yOffset = 0; $yOffset < self::MAX_STEM_HEIGHT; $yOffset++, $stemHeight++){
$down = $world->getBlock($this->position->down($yOffset + 1));
if($down->getTypeId() !== BlockTypeIds::CHORUS_PLANT){
if($down->getTypeId() === BlockTypeIds::END_STONE){
$endStoneBelow = true;
}
break;
}
}
return [$stemHeight, $endStoneBelow];
}
private function allHorizontalBlocksEmpty(World $world, Vector3 $position, ?int $except) : bool{
foreach($position->sidesAroundAxis(Axis::Y) as $facing => $sidePosition){
if($facing === $except){
continue;
}
if($world->getBlock($sidePosition)->getTypeId() !== BlockTypeIds::AIR){
return false;
}
}
return true;
}
private function canGrowUpwards(int $stemHeight, bool $endStoneBelow) : bool{
$world = $this->position->getWorld();
$up = $this->position->up();
if(
//the space above must be empty and writable
!$world->isInWorld($up->x, $up->y, $up->z) ||
$world->getBlock($up)->getTypeId() !== BlockTypeIds::AIR ||
(
//the space above that must be empty, but doesn't need to be writable
$world->isInWorld($up->x, $up->y + 1, $up->z) &&
$world->getBlock($up->up())->getTypeId() !== BlockTypeIds::AIR
)
){
return false;
}
if($this->getSide(Facing::DOWN)->getTypeId() !== BlockTypeIds::AIR){
if($stemHeight >= self::MAX_STEM_HEIGHT){
return false;
}
if($stemHeight > 1 && $stemHeight > mt_rand(0, $endStoneBelow ? 4 : 3)){ //chance decreases for each added block of chorus plant
return false;
}
}
return $this->allHorizontalBlocksEmpty($world, $up, null);
}
private function grow(int $facing, int $ageChange, ?BlockTransaction $tx) : BlockTransaction{
if($tx === null){
$tx = new BlockTransaction($this->position->getWorld());
}
$tx->addBlock($this->position->getSide($facing), (clone $this)->setAge($this->getAge() + $ageChange));
return $tx;
}
public function onRandomTick() : void{
$world = $this->position->getWorld();
if($this->age >= self::MAX_AGE){
return;
}
$tx = null;
[$stemHeight, $endStoneBelow] = $this->scanStem();
if($this->canGrowUpwards($stemHeight, $endStoneBelow)){
$tx = $this->grow(Facing::UP, 0, $tx);
}else{
$facingVisited = [];
for($attempts = 0, $maxAttempts = mt_rand(0, $endStoneBelow ? 4 : 3); $attempts < $maxAttempts; $attempts++){
$facing = Facing::HORIZONTAL[array_rand(Facing::HORIZONTAL)];
if(isset($facingVisited[$facing])){
continue;
}
$facingVisited[$facing] = true;
$sidePosition = $this->position->getSide($facing);
if(
$world->getBlock($sidePosition)->getTypeId() === BlockTypeIds::AIR &&
$world->getBlock($sidePosition->down())->getTypeId() === BlockTypeIds::AIR &&
$this->allHorizontalBlocksEmpty($world, $sidePosition, Facing::opposite($facing))
){
$tx = $this->grow($facing, 1, $tx);
}
}
}
if($tx !== null){
$tx->addBlock($this->position, VanillaBlocks::CHORUS_PLANT());
$ev = new StructureGrowEvent($this, $tx, null);
$ev->call();
if(!$ev->isCancelled() && $tx->apply()){
$world->addSound($this->position->add(0.5, 0.5, 0.5), new ChorusFlowerGrowSound());
}
}else{
$world->addSound($this->position->add(0.5, 0.5, 0.5), new ChorusFlowerDieSound());
$this->position->getWorld()->setBlock($this->position, $this->setAge(self::MAX_AGE));
}
}
}

View File

@ -1,102 +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\block;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use pocketmine\math\Axis;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
use pocketmine\world\Position;
use function mt_rand;
final class ChorusPlant extends Flowable{
protected function recalculateCollisionBoxes() : array{
$bb = AxisAlignedBB::one();
foreach($this->getAllSides() as $facing => $block){
$id = $block->getTypeId();
if($id !== BlockTypeIds::END_STONE && $id !== BlockTypeIds::CHORUS_FLOWER && !$block->isSameType($this)){
$bb->trim($facing, 2 / 16);
}
}
return [$bb];
}
private function canBeSupportedBy(Block $block) : bool{
return $block->isSameType($this) || $block->getTypeId() === BlockTypeIds::END_STONE;
}
private function canStay(Position $position) : bool{
$world = $position->getWorld();
$down = $world->getBlock($position->down());
$verticalAir = $down->getTypeId() === BlockTypeIds::AIR || $world->getBlock($position->up())->getTypeId() === BlockTypeIds::AIR;
foreach($position->sidesAroundAxis(Axis::Y) as $sidePosition){
$block = $world->getBlock($sidePosition);
if($block->getTypeId() === BlockTypeIds::CHORUS_PLANT){
if(!$verticalAir){
return false;
}
if($this->canBeSupportedBy($block->getSide(Facing::DOWN))){
return true;
}
}
}
if($this->canBeSupportedBy($down)){
return true;
}
return false;
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canStay($blockReplace->getPosition())){
return false;
}
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function onNearbyBlockChange() : void{
if(!$this->canStay($this->position)){
$this->position->getWorld()->useBreakOn($this->position);
}
}
public function getDropsForCompatibleTool(Item $item) : array{
if(mt_rand(0, 1) === 1){
return [VanillaItems::CHORUS_FRUIT()];
}
return [];
}
}

View File

@ -23,10 +23,10 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\block\utils\WoodType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\block\utils\TreeType;
use pocketmine\event\block\BlockGrowEvent;
use pocketmine\item\Fertilizer;
use pocketmine\item\Item;
@ -46,9 +46,17 @@ class CocoaBlock extends Transparent{
protected int $age = 0;
protected function describeState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing);
$w->boundedInt(2, 0, self::MAX_AGE, $this->age);
protected function writeStateToMeta() : int{
return BlockDataSerializer::writeLegacyHorizontalFacing(Facing::opposite($this->facing)) | ($this->age << 2);
}
public function readStateFromData(int $id, int $stateMeta) : void{
$this->facing = Facing::opposite(BlockDataSerializer::readLegacyHorizontalFacing($stateMeta & 0x03));
$this->age = BlockDataSerializer::readBoundedInt("age", $stateMeta >> 2, 0, self::MAX_AGE);
}
public function getStateBitmask() : int{
return 0b1111;
}
public function getAge() : int{ return $this->age; }
@ -81,7 +89,7 @@ class CocoaBlock extends Transparent{
}
private function canAttachTo(Block $block) : bool{
return $block instanceof Wood && $block->getWoodType()->equals(WoodType::JUNGLE());
return $block instanceof Wood && $block->getTreeType()->equals(TreeType::JUNGLE());
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
@ -93,7 +101,7 @@ class CocoaBlock extends Transparent{
return false;
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($item instanceof Fertilizer && $this->grow()){
$item->pop();
@ -139,7 +147,7 @@ class CocoaBlock extends Transparent{
];
}
public function asItem() : Item{
public function getPickedItem(bool $addUserData = false) : Item{
return VanillaItems::COCOA_BEANS();
}
}

View File

@ -23,14 +23,14 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\ColoredTrait;
use pocketmine\block\utils\ColorInMetadataTrait;
use pocketmine\block\utils\DyeColor;
class Concrete extends Opaque{
use ColoredTrait;
use ColorInMetadataTrait;
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
$this->color = DyeColor::WHITE();
parent::__construct($idInfo, $name, $typeInfo);
parent::__construct($idInfo, $name, $breakInfo);
}
}

View File

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\ColoredTrait;
use pocketmine\block\utils\ColorInMetadataTrait;
use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\Fallable;
use pocketmine\block\utils\FallableTrait;
@ -31,19 +31,19 @@ use pocketmine\event\block\BlockFormEvent;
use pocketmine\math\Facing;
class ConcretePowder extends Opaque implements Fallable{
use ColoredTrait;
use ColorInMetadataTrait;
use FallableTrait {
onNearbyBlockChange as protected startFalling;
}
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
$this->color = DyeColor::WHITE();
parent::__construct($idInfo, $name, $typeInfo);
parent::__construct($idInfo, $name, $breakInfo);
}
public function onNearbyBlockChange() : void{
if(($water = $this->getAdjacentWater()) !== null){
$ev = new BlockFormEvent($this, VanillaBlocks::CONCRETE()->setColor($this->color), $water);
if(($block = $this->checkAdjacentWater()) !== null){
$ev = new BlockFormEvent($this, $block);
$ev->call();
if(!$ev->isCancelled()){
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
@ -54,20 +54,16 @@ class ConcretePowder extends Opaque implements Fallable{
}
public function tickFalling() : ?Block{
if($this->getAdjacentWater() === null){
return null;
}
return VanillaBlocks::CONCRETE()->setColor($this->color);
return $this->checkAdjacentWater();
}
private function getAdjacentWater() : ?Water{
private function checkAdjacentWater() : ?Block{
foreach(Facing::ALL as $i){
if($i === Facing::DOWN){
continue;
}
$block = $this->getSide($i);
if($block instanceof Water){
return $block;
if($this->getSide($i) instanceof Water){
return VanillaBlocks::CONCRETE()->setColor($this->color);
}
}

View File

@ -1,30 +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\block;
use pocketmine\block\utils\CopperTrait;
class Copper extends Opaque{
use CopperTrait;
}

View File

@ -1,36 +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\block;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
final class CopperOre extends Opaque{
public function getDropsForCompatibleTool(Item $item) : array{
return [VanillaItems::RAW_COPPER()];
}
public function isAffectedBySilkTouch() : bool{ return true; }
}

View File

@ -1,30 +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\block;
use pocketmine\block\utils\CopperTrait;
class CopperSlab extends Slab{
use CopperTrait;
}

View File

@ -1,36 +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\block;
use pocketmine\block\utils\CopperOxidation;
use pocketmine\block\utils\CopperTrait;
class CopperStairs extends Stair{
use CopperTrait;
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
$this->oxidation = CopperOxidation::NONE();
parent::__construct($idInfo, $name, $typeInfo);
}
}

View File

@ -23,6 +23,8 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\InvalidBlockStateException;
use pocketmine\data\bedrock\CoralTypeIdMap;
use pocketmine\item\Item;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
@ -31,6 +33,38 @@ use pocketmine\world\BlockTransaction;
final class Coral extends BaseCoral{
public function readStateFromData(int $id, int $stateMeta) : void{
$coralType = CoralTypeIdMap::getInstance()->fromId($stateMeta);
if($coralType === null){
throw new InvalidBlockStateException("No such coral type");
}
$this->coralType = $coralType;
}
public function writeStateToMeta() : int{
return CoralTypeIdMap::getInstance()->toId($this->coralType);
}
protected function writeStateToItemMeta() : int{
return $this->writeStateToMeta();
}
public function getStateBitmask() : int{
return 0b0111;
}
public function readStateFromWorld() : void{
//TODO: this hack ensures correct state of coral plants, because they don't retain their dead flag in metadata
$world = $this->position->getWorld();
$this->dead = true;
foreach($this->position->sides() as $vector3){
if($world->getBlock($vector3) instanceof Water){
$this->dead = false;
break;
}
}
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedBy($tx->fetchBlock($blockReplace->getPosition()->down()))){
return false;

View File

@ -25,6 +25,8 @@ namespace pocketmine\block;
use pocketmine\block\utils\CoralType;
use pocketmine\block\utils\CoralTypeTrait;
use pocketmine\block\utils\InvalidBlockStateException;
use pocketmine\data\bedrock\CoralTypeIdMap;
use pocketmine\event\block\BlockDeathEvent;
use pocketmine\item\Item;
use function mt_rand;
@ -32,9 +34,30 @@ use function mt_rand;
final class CoralBlock extends Opaque{
use CoralTypeTrait;
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
$this->coralType = CoralType::TUBE();
parent::__construct($idInfo, $name, $typeInfo);
parent::__construct($idInfo, $name, $breakInfo);
}
public function readStateFromData(int $id, int $stateMeta) : void{
$coralType = CoralTypeIdMap::getInstance()->fromId($stateMeta & 0x7);
if($coralType === null){
throw new InvalidBlockStateException("No such coral type");
}
$this->coralType = $coralType;
$this->dead = ($stateMeta & BlockLegacyMetadata::CORAL_BLOCK_FLAG_DEAD) !== 0;
}
protected function writeStateToMeta() : int{
return ($this->dead ? BlockLegacyMetadata::CORAL_BLOCK_FLAG_DEAD : 0) | CoralTypeIdMap::getInstance()->toId($this->coralType);
}
protected function writeStateToItemMeta() : int{
return $this->writeStateToMeta();
}
public function getStateBitmask() : int{
return 0b1111;
}
public function onNearbyBlockChange() : void{

View File

@ -30,7 +30,7 @@ use pocketmine\player\Player;
class CraftingTable extends Opaque{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player instanceof Player){
$player->setCurrentWindow(new CraftingTableInventory($this->position));
}

View File

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\event\block\BlockGrowEvent;
use pocketmine\item\Fertilizer;
use pocketmine\item\Item;
@ -38,8 +38,16 @@ abstract class Crops extends Flowable{
protected int $age = 0;
protected function describeState(RuntimeDataDescriber $w) : void{
$w->boundedInt(3, 0, self::MAX_AGE, $this->age);
protected function writeStateToMeta() : int{
return $this->age;
}
public function readStateFromData(int $id, int $stateMeta) : void{
$this->age = BlockDataSerializer::readBoundedInt("age", $stateMeta, 0, self::MAX_AGE);
}
public function getStateBitmask() : int{
return 0b111;
}
public function getAge() : int{ return $this->age; }
@ -54,14 +62,14 @@ abstract class Crops extends Flowable{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($blockReplace->getSide(Facing::DOWN)->getTypeId() === BlockTypeIds::FARMLAND){
if($blockReplace->getSide(Facing::DOWN)->getId() === BlockLegacyIds::FARMLAND){
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
return false;
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->age < self::MAX_AGE && $item instanceof Fertilizer){
$block = clone $this;
$block->age += mt_rand(2, 5);
@ -83,7 +91,7 @@ abstract class Crops extends Flowable{
}
public function onNearbyBlockChange() : void{
if($this->getSide(Facing::DOWN)->getTypeId() !== BlockTypeIds::FARMLAND){
if($this->getSide(Facing::DOWN)->getId() !== BlockLegacyIds::FARMLAND){
$this->position->getWorld()->useBreakOn($this->position);
}
}

View File

@ -24,8 +24,8 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\AnalogRedstoneSignalEmitterTrait;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
@ -39,11 +39,30 @@ use const M_PI;
class DaylightSensor extends Transparent{
use AnalogRedstoneSignalEmitterTrait;
protected BlockIdentifierFlattened $idInfoFlattened;
protected bool $inverted = false;
protected function describeState(RuntimeDataDescriber $w) : void{
$w->boundedInt(4, 0, 15, $this->signalStrength);
$w->bool($this->inverted);
public function __construct(BlockIdentifierFlattened $idInfo, string $name, BlockBreakInfo $breakInfo){
$this->idInfoFlattened = $idInfo;
parent::__construct($idInfo, $name, $breakInfo);
}
public function getId() : int{
return $this->inverted ? $this->idInfoFlattened->getSecondId() : parent::getId();
}
protected function writeStateToMeta() : int{
return $this->signalStrength;
}
public function readStateFromData(int $id, int $stateMeta) : void{
$this->signalStrength = BlockDataSerializer::readBoundedInt("signalStrength", $stateMeta, 0, 15);
$this->inverted = $id === $this->idInfoFlattened->getSecondId();
}
public function getStateBitmask() : int{
return 0b1111;
}
public function isInverted() : bool{
@ -73,7 +92,7 @@ class DaylightSensor extends Transparent{
return SupportType::NONE();
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->inverted = !$this->inverted;
$this->signalStrength = $this->recalculateSignalStrength();
$this->position->getWorld()->setBlock($this->position, $this);

View File

@ -66,13 +66,12 @@ class DeadBush extends Flowable{
}
private function canBeSupportedBy(Block $block) : bool{
$blockId = $block->getTypeId();
return $blockId === BlockTypeIds::SAND
|| $blockId === BlockTypeIds::RED_SAND
|| $blockId === BlockTypeIds::PODZOL
|| $blockId === BlockTypeIds::MYCELIUM
|| $blockId === BlockTypeIds::DIRT
|| $blockId === BlockTypeIds::HARDENED_CLAY
|| $blockId === BlockTypeIds::STAINED_CLAY;
$blockId = $block->getId();
return $blockId === BlockLegacyIds::SAND
|| $blockId === BlockLegacyIds::PODZOL
|| $blockId === BlockLegacyIds::MYCELIUM
|| $blockId === BlockLegacyIds::DIRT
|| $blockId === BlockLegacyIds::HARDENED_CLAY
|| $blockId === BlockLegacyIds::STAINED_HARDENED_CLAY;
}
}

View File

@ -23,16 +23,9 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\data\runtime\RuntimeDataDescriber;
class DetectorRail extends StraightOnlyRail{
protected bool $activated = false;
protected function describeState(RuntimeDataDescriber $w) : void{
parent::describeState($w);
$w->bool($this->activated);
}
public function isActivated() : bool{ return $this->activated; }
/** @return $this */
@ -40,5 +33,19 @@ class DetectorRail extends StraightOnlyRail{
$this->activated = $activated;
return $this;
}
public function readStateFromData(int $id, int $stateMeta) : void{
parent::readStateFromData($id, $stateMeta & ~BlockLegacyMetadata::REDSTONE_RAIL_FLAG_POWERED);
$this->activated = ($stateMeta & BlockLegacyMetadata::REDSTONE_RAIL_FLAG_POWERED) !== 0;
}
protected function writeStateToMeta() : int{
return parent::writeStateToMeta() | ($this->activated ? BlockLegacyMetadata::REDSTONE_RAIL_FLAG_POWERED : 0);
}
public function getStateBitmask() : int{
return 0b1111;
}
//TODO
}

View File

@ -23,67 +23,50 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\DirtType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Fertilizer;
use pocketmine\item\Hoe;
use pocketmine\item\Item;
use pocketmine\item\Potion;
use pocketmine\item\PotionType;
use pocketmine\item\SplashPotion;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\sound\ItemUseOnBlockSound;
use pocketmine\world\sound\WaterSplashSound;
class Dirt extends Opaque{
protected DirtType $dirtType;
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
$this->dirtType = DirtType::NORMAL();
parent::__construct($idInfo, $name, $typeInfo);
protected bool $coarse = false;
public function readStateFromData(int $id, int $stateMeta) : void{
$this->coarse = ($stateMeta & BlockLegacyMetadata::DIRT_FLAG_COARSE) !== 0;
}
protected function describeType(RuntimeDataDescriber $w) : void{
$w->dirtType($this->dirtType);
protected function writeStateToMeta() : int{
return $this->coarse ? BlockLegacyMetadata::DIRT_FLAG_COARSE : 0;
}
public function getDirtType() : DirtType{ return $this->dirtType; }
protected function writeStateToItemMeta() : int{
return $this->writeStateToMeta();
}
public function getStateBitmask() : int{
return 0b1;
}
public function isCoarse() : bool{ return $this->coarse; }
/** @return $this */
public function setDirtType(DirtType $dirtType) : self{
$this->dirtType = $dirtType;
public function setCoarse(bool $coarse) : self{
$this->coarse = $coarse;
return $this;
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
$world = $this->position->getWorld();
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($face === Facing::UP && $item instanceof Hoe){
$item->applyDamage(1);
$newBlock = $this->dirtType->equals(DirtType::NORMAL()) ? VanillaBlocks::FARMLAND() : VanillaBlocks::DIRT();
$center = $this->position->add(0.5, 0.5, 0.5);
$world->addSound($center, new ItemUseOnBlockSound($newBlock));
$newBlock = $this->coarse ? VanillaBlocks::DIRT() : VanillaBlocks::FARMLAND();
$world = $this->position->getWorld();
$world->addSound($this->position->add(0.5, 0.5, 0.5), new ItemUseOnBlockSound($newBlock));
$world->setBlock($this->position, $newBlock);
if($this->dirtType->equals(DirtType::ROOTED())){
$world->dropItem($center, VanillaBlocks::HANGING_ROOTS()->asItem());
}
return true;
}elseif($this->dirtType->equals(DirtType::ROOTED()) && $item instanceof Fertilizer){
$down = $this->getSide(Facing::DOWN);
if($down->getTypeId() !== BlockTypeIds::AIR){
return true;
}
$item->pop();
$world->setBlock($down->position, VanillaBlocks::HANGING_ROOTS());
//TODO: bonemeal particles, growth sounds
}elseif(($item instanceof Potion || $item instanceof SplashPotion) && $item->getType()->equals(PotionType::WATER())){
$item->pop();
$world->setBlock($this->position, VanillaBlocks::MUD());
$world->addSound($this->position, new WaterSplashSound(0.5));
return true;
}

View File

@ -23,9 +23,10 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\PoweredByRedstoneTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
@ -36,19 +37,38 @@ use pocketmine\world\sound\DoorSound;
class Door extends Transparent{
use HorizontalFacingTrait;
use PoweredByRedstoneTrait;
protected bool $top = false;
protected bool $hingeRight = false;
protected bool $open = false;
protected function describeState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing);
$w->bool($this->top);
$w->bool($this->hingeRight);
$w->bool($this->open);
protected function writeStateToMeta() : int{
if($this->top){
return BlockLegacyMetadata::DOOR_FLAG_TOP |
($this->hingeRight ? BlockLegacyMetadata::DOOR_TOP_FLAG_RIGHT : 0) |
($this->powered ? BlockLegacyMetadata::DOOR_TOP_FLAG_POWERED : 0);
}
return BlockDataSerializer::writeLegacyHorizontalFacing(Facing::rotateY($this->facing, true)) | ($this->open ? BlockLegacyMetadata::DOOR_BOTTOM_FLAG_OPEN : 0);
}
public function readStateFromWorld() : Block{
public function readStateFromData(int $id, int $stateMeta) : void{
$this->top = ($stateMeta & BlockLegacyMetadata::DOOR_FLAG_TOP) !== 0;
if($this->top){
$this->hingeRight = ($stateMeta & BlockLegacyMetadata::DOOR_TOP_FLAG_RIGHT) !== 0;
$this->powered = ($stateMeta & BlockLegacyMetadata::DOOR_TOP_FLAG_POWERED) !== 0;
}else{
$this->facing = Facing::rotateY(BlockDataSerializer::readLegacyHorizontalFacing($stateMeta & 0x03), false);
$this->open = ($stateMeta & BlockLegacyMetadata::DOOR_BOTTOM_FLAG_OPEN) !== 0;
}
}
public function getStateBitmask() : int{
return 0b1111;
}
public function readStateFromWorld() : void{
parent::readStateFromWorld();
//copy door properties from other half
@ -59,10 +79,9 @@ class Door extends Transparent{
$this->open = $other->open;
}else{
$this->hingeRight = $other->hingeRight;
$this->powered = $other->powered;
}
}
return $this;
}
public function isTop() : bool{ return $this->top; }
@ -140,7 +159,7 @@ class Door extends Transparent{
return false;
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->open = !$this->open;
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
@ -31,10 +30,19 @@ use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
class DoublePlant extends Flowable{
protected bool $top = false;
protected function describeState(RuntimeDataDescriber $w) : void{
$w->bool($this->top);
protected function writeStateToMeta() : int{
return ($this->top ? BlockLegacyMetadata::DOUBLE_PLANT_FLAG_TOP : 0);
}
public function readStateFromData(int $id, int $stateMeta) : void{
$this->top = ($stateMeta & BlockLegacyMetadata::DOUBLE_PLANT_FLAG_TOP) !== 0;
}
public function getStateBitmask() : int{
return 0b1000;
}
public function isTop() : bool{ return $this->top; }
@ -46,8 +54,8 @@ class DoublePlant extends Flowable{
}
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->hasTypeTag(BlockTypeTags::DIRT) && $blockReplace->getSide(Facing::UP)->canBeReplaced()){
$id = $blockReplace->getSide(Facing::DOWN)->getId();
if(($id === BlockLegacyIds::GRASS || $id === BlockLegacyIds::DIRT) && $blockReplace->getSide(Facing::UP)->canBeReplaced()){
$top = clone $this;
$top->top = true;
$tx->addBlock($blockReplace->position, $this)->addBlock($blockReplace->position->getSide(Facing::UP), $top);
@ -71,8 +79,7 @@ class DoublePlant extends Flowable{
}
public function onNearbyBlockChange() : void{
$down = $this->getSide(Facing::DOWN);
if(!$this->isValidHalfPlant() || (!$this->top && !$down->hasTypeTag(BlockTypeTags::DIRT) && !$down->hasTypeTag(BlockTypeTags::MUD))){
if(!$this->isValidHalfPlant() || (!$this->top && $this->getSide(Facing::DOWN)->isTransparent())){
$this->position->getWorld()->useBreakOn($this->position);
}
}

View File

@ -44,7 +44,11 @@ class DragonEgg extends Transparent implements Fallable{
return 1;
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
public function tickFalling() : ?Block{
return null;
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->teleport();
return true;
}

View File

@ -1,42 +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\block;
use pocketmine\block\utils\ColoredTrait;
use pocketmine\block\utils\DyeColor;
class DyedCandle extends Candle{
use ColoredTrait;
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
$this->color = DyeColor::WHITE();
parent::__construct($idInfo, $name, $typeInfo);
}
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

@ -23,14 +23,14 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\ColoredTrait;
use pocketmine\block\utils\ColorInMetadataTrait;
use pocketmine\block\utils\DyeColor;
final class DyedShulkerBox extends ShulkerBox{
use ColoredTrait;
use ColorInMetadataTrait;
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
$this->color = DyeColor::WHITE();
parent::__construct($idInfo, $name, $typeInfo);
parent::__construct($idInfo, $name, $breakInfo);
}
}

View File

@ -27,12 +27,12 @@ class Element extends Opaque{
public function __construct(
BlockIdentifier $idInfo,
string $name,
BlockTypeInfo $typeInfo,
BlockBreakInfo $breakInfo,
private string $symbol,
private int $atomicWeight,
private int $group
){
parent::__construct($idInfo, $name, $typeInfo);
parent::__construct($idInfo, $name, $breakInfo);
}
public function getAtomicWeight() : int{

View File

@ -44,7 +44,7 @@ class EnchantingTable extends Transparent{
return SupportType::NONE();
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player instanceof Player){
//TODO lock

View File

@ -23,9 +23,9 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
@ -35,9 +35,17 @@ class EndPortalFrame extends Opaque{
protected bool $eye = false;
protected function describeState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing);
$w->bool($this->eye);
protected function writeStateToMeta() : int{
return BlockDataSerializer::writeLegacyHorizontalFacing($this->facing) | ($this->eye ? BlockLegacyMetadata::END_PORTAL_FRAME_FLAG_EYE : 0);
}
public function readStateFromData(int $id, int $stateMeta) : void{
$this->facing = BlockDataSerializer::readLegacyHorizontalFacing($stateMeta & 0x03);
$this->eye = ($stateMeta & BlockLegacyMetadata::END_PORTAL_FRAME_FLAG_EYE) !== 0;
}
public function getStateBitmask() : int{
return 0b111;
}
public function hasEye() : bool{ return $this->eye; }

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\AnyFacingTrait;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\item\Item;
use pocketmine\math\Axis;
use pocketmine\math\AxisAlignedBB;
@ -35,6 +36,27 @@ use pocketmine\world\BlockTransaction;
class EndRod extends Flowable{
use AnyFacingTrait;
protected function writeStateToMeta() : int{
$result = BlockDataSerializer::writeFacing($this->facing);
if(Facing::axis($this->facing) !== Axis::Y){
$result ^= 1; //TODO: in PC this is always the same as facing, just PE is stupid
}
return $result;
}
public function readStateFromData(int $id, int $stateMeta) : void{
if($stateMeta !== 0 && $stateMeta !== 1){
$stateMeta ^= 1;
}
$this->facing = BlockDataSerializer::readFacing($stateMeta);
}
public function getStateBitmask() : int{
return 0b111;
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->facing = $face;
if($blockClicked instanceof EndRod && $blockClicked->facing === $this->facing){

View File

@ -26,7 +26,7 @@ namespace pocketmine\block;
use pocketmine\block\inventory\EnderChestInventory;
use pocketmine\block\tile\EnderChest as TileEnderChest;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\NormalHorizontalFacingInMetadataTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
@ -36,7 +36,7 @@ use pocketmine\player\Player;
class EnderChest extends Transparent{
use FacesOppositePlacingPlayerTrait;
use HorizontalFacingTrait;
use NormalHorizontalFacingInMetadataTrait;
public function getLightLevel() : int{
return 7;
@ -54,7 +54,7 @@ class EnderChest extends Transparent{
return SupportType::NONE();
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player instanceof Player){
$enderChest = $this->position->getWorld()->getTile($this->position);
if($enderChest instanceof TileEnderChest && $this->getSide(Facing::UP)->isTransparent()){

View File

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\entity\Entity;
use pocketmine\entity\Living;
use pocketmine\event\entity\EntityTrampleFarmlandEvent;
@ -37,8 +37,16 @@ class Farmland extends Transparent{
protected int $wetness = 0; //"moisture" blockstate property in PC
protected function describeState(RuntimeDataDescriber $w) : void{
$w->boundedInt(3, 0, self::MAX_WETNESS, $this->wetness);
protected function writeStateToMeta() : int{
return $this->wetness;
}
public function readStateFromData(int $id, int $stateMeta) : void{
$this->wetness = BlockDataSerializer::readBoundedInt("wetness", $stateMeta, 0, self::MAX_WETNESS);
}
public function getStateBitmask() : int{
return 0b111;
}
public function getWetness() : int{ return $this->wetness; }

View File

@ -37,7 +37,7 @@ class Fence extends Transparent{
return 0.25;
}
public function readStateFromWorld() : Block{
public function readStateFromWorld() : void{
parent::readStateFromWorld();
foreach(Facing::HORIZONTAL as $facing){
@ -48,8 +48,6 @@ class Fence extends Transparent{
unset($this->connections[$facing]);
}
}
return $this;
}
/**

View File

@ -23,10 +23,9 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\block\utils\WoodTypeTrait;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
@ -36,16 +35,25 @@ use pocketmine\world\BlockTransaction;
use pocketmine\world\sound\DoorSound;
class FenceGate extends Transparent{
use WoodTypeTrait;
use HorizontalFacingTrait;
protected bool $open = false;
protected bool $inWall = false;
protected function describeState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing);
$w->bool($this->open);
$w->bool($this->inWall);
protected function writeStateToMeta() : int{
return BlockDataSerializer::writeLegacyHorizontalFacing($this->facing) |
($this->open ? BlockLegacyMetadata::FENCE_GATE_FLAG_OPEN : 0) |
($this->inWall ? BlockLegacyMetadata::FENCE_GATE_FLAG_IN_WALL : 0);
}
public function readStateFromData(int $id, int $stateMeta) : void{
$this->facing = BlockDataSerializer::readLegacyHorizontalFacing($stateMeta & 0x03);
$this->open = ($stateMeta & BlockLegacyMetadata::FENCE_GATE_FLAG_OPEN) !== 0;
$this->inWall = ($stateMeta & BlockLegacyMetadata::FENCE_GATE_FLAG_IN_WALL) !== 0;
}
public function getStateBitmask() : int{
return 0b1111;
}
public function isOpen() : bool{ return $this->open; }
@ -100,7 +108,7 @@ class FenceGate extends Transparent{
}
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->open = !$this->open;
if($this->open && $player !== null){
$playerFacing = $player->getHorizontalFacing();
@ -116,14 +124,14 @@ class FenceGate extends Transparent{
}
public function getFuelTime() : int{
return $this->woodType->isFlammable() ? 300 : 0;
return 300;
}
public function getFlameEncouragement() : int{
return $this->woodType->isFlammable() ? 5 : 0;
return 5;
}
public function getFlammability() : int{
return $this->woodType->isFlammable() ? 20 : 0;
return 20;
}
}

View File

@ -1,127 +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\block;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\world\sound\Sound;
use function min;
abstract class FillableCauldron extends Transparent{
public const MIN_FILL_LEVEL = 1;
public const MAX_FILL_LEVEL = 6;
private int $fillLevel = self::MIN_FILL_LEVEL;
protected function describeState(RuntimeDataDescriber $w) : void{
$w->boundedInt(3, self::MIN_FILL_LEVEL, self::MAX_FILL_LEVEL, $this->fillLevel);
}
public function getFillLevel() : int{ return $this->fillLevel; }
/** @return $this */
public function setFillLevel(int $fillLevel) : self{
if($fillLevel < self::MIN_FILL_LEVEL || $fillLevel > self::MAX_FILL_LEVEL){
throw new \InvalidArgumentException("Fill level must be in range " . self::MIN_FILL_LEVEL . " ... " . self::MAX_FILL_LEVEL);
}
$this->fillLevel = $fillLevel;
return $this;
}
protected function recalculateCollisionBoxes() : array{
$result = [
AxisAlignedBB::one()->trim(Facing::UP, 11 / 16) //bottom of the cauldron
];
foreach(Facing::HORIZONTAL as $f){ //add the frame parts around the bowl
$result[] = AxisAlignedBB::one()->trim($f, 14 / 16);
}
return $result;
}
public function getSupportType(int $facing) : SupportType{
return $facing === Facing::UP ? SupportType::EDGE() : SupportType::NONE();
}
protected function withFillLevel(int $fillLevel) : Block{
return $fillLevel === 0 ? VanillaBlocks::CAULDRON() : $this->setFillLevel(min(self::MAX_FILL_LEVEL, $fillLevel));
}
/**
* @param Item[] &$returnedItems
*/
protected function addFillLevels(int $amount, Item $usedItem, Item $returnedItem, array &$returnedItems) : void{
if($this->fillLevel >= self::MAX_FILL_LEVEL){
return;
}
$this->position->getWorld()->setBlock($this->position, $this->withFillLevel($this->fillLevel + $amount));
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), $this->getFillSound());
$usedItem->pop();
$returnedItems[] = $returnedItem;
}
/**
* @param Item[] &$returnedItems
*/
protected function removeFillLevels(int $amount, Item $usedItem, Item $returnedItem, array &$returnedItems) : void{
if($this->fillLevel < $amount){
return;
}
$this->position->getWorld()->setBlock($this->position, $this->withFillLevel($this->fillLevel - $amount));
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), $this->getEmptySound());
$usedItem->pop();
$returnedItems[] = $returnedItem;
}
/**
* Returns the sound played when adding levels to the cauldron liquid.
*/
abstract public function getFillSound() : Sound;
/**
* Returns the sound played when removing levels from the cauldron liquid.
*/
abstract public function getEmptySound() : Sound;
/**
* @param Item[] &$returnedItems
*/
protected function mix(Item $usedItem, Item $returnedItem, array &$returnedItems) : void{
$this->position->getWorld()->setBlock($this->position, VanillaBlocks::CAULDRON());
//TODO: sounds and particles
$usedItem->pop();
$returnedItems[] = $returnedItem;
}
public function asItem() : Item{
return VanillaBlocks::CAULDRON()->asItem();
}
}

View File

@ -23,9 +23,15 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\entity\Entity;
use pocketmine\entity\projectile\Arrow;
use pocketmine\event\block\BlockBurnEvent;
use pocketmine\event\block\BlockSpreadEvent;
use pocketmine\event\entity\EntityCombustByBlockEvent;
use pocketmine\event\entity\EntityDamageByBlockEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\item\Item;
use pocketmine\math\Facing;
use pocketmine\world\format\Chunk;
use pocketmine\world\World;
@ -34,13 +40,21 @@ use function max;
use function min;
use function mt_rand;
class Fire extends BaseFire{
class Fire extends Flowable{
public const MAX_AGE = 15;
protected int $age = 0;
protected function describeState(RuntimeDataDescriber $w) : void{
$w->boundedInt(4, 0, self::MAX_AGE, $this->age);
protected function writeStateToMeta() : int{
return $this->age;
}
public function readStateFromData(int $id, int $stateMeta) : void{
$this->age = BlockDataSerializer::readBoundedInt("age", $stateMeta, 0, self::MAX_AGE);
}
public function getStateBitmask() : int{
return 0b1111;
}
public function getAge() : int{ return $this->age; }
@ -54,16 +68,40 @@ class Fire extends BaseFire{
return $this;
}
protected function getFireDamage() : int{
return 1;
public function hasEntityCollision() : bool{
return true;
}
public function getLightLevel() : int{
return 15;
}
public function canBeReplaced() : bool{
return true;
}
public function onEntityInside(Entity $entity) : bool{
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_FIRE, 1);
$entity->attack($ev);
$ev = new EntityCombustByBlockEvent($this, $entity, 8);
if($entity instanceof Arrow){
$ev->cancel();
}
$ev->call();
if(!$ev->isCancelled()){
$entity->setOnFire($ev->getDuration());
}
return true;
}
public function getDropsForCompatibleTool(Item $item) : array{
return [];
}
public function onNearbyBlockChange() : void{
$world = $this->position->getWorld();
$down = $this->getSide(Facing::DOWN);
if(SoulFire::canBeSupportedBy($down)){
$world->setBlock($this->position, VanillaBlocks::SOUL_FIRE());
}elseif($down->isTransparent() && !$this->hasAdjacentFlammableBlocks()){
if($this->getSide(Facing::DOWN)->isTransparent() && !$this->hasAdjacentFlammableBlocks()){
$world->setBlock($this->position, VanillaBlocks::AIR());
}else{
$world->scheduleDelayedBlockUpdate($this->position, mt_rand(30, 40));
@ -189,7 +227,7 @@ class Fire extends BaseFire{
continue;
}
$block = $world->getBlockAt($targetX, $targetY, $targetZ);
if($block->getTypeId() !== BlockTypeIds::AIR){
if($block->getId() !== BlockLegacyIds::AIR){
continue;
}

View File

@ -33,6 +33,18 @@ use pocketmine\world\BlockTransaction;
final class FloorBanner extends BaseBanner{
use SignLikeRotationTrait;
public function readStateFromData(int $id, int $stateMeta) : void{
$this->rotation = $stateMeta;
}
protected function writeStateToMeta() : int{
return $this->rotation;
}
public function getStateBitmask() : int{
return 0b1111;
}
protected function getSupportingFace() : int{
return Facing::DOWN;
}

View File

@ -23,9 +23,11 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\block\utils\InvalidBlockStateException;
use pocketmine\data\bedrock\CoralTypeIdMap;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use pocketmine\item\ItemFactory;
use pocketmine\item\ItemIds;
use pocketmine\math\Axis;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
@ -35,10 +37,49 @@ use function atan2;
use function rad2deg;
final class FloorCoralFan extends BaseCoral{
protected BlockIdentifierFlattened $idInfoFlattened;
private int $axis = Axis::X;
protected function describeState(RuntimeDataDescriber $w) : void{
$w->horizontalAxis($this->axis);
public function __construct(BlockIdentifierFlattened $idInfo, string $name, BlockBreakInfo $breakInfo){
$this->idInfoFlattened = $idInfo;
parent::__construct($idInfo, $name, $breakInfo);
}
public function readStateFromData(int $id, int $stateMeta) : void{
$this->dead = $id === $this->idInfoFlattened->getSecondId();
$this->axis = ($stateMeta >> 3) === BlockLegacyMetadata::CORAL_FAN_EAST_WEST ? Axis::X : Axis::Z;
$coralType = CoralTypeIdMap::getInstance()->fromId($stateMeta & BlockLegacyMetadata::CORAL_FAN_TYPE_MASK);
if($coralType === null){
throw new InvalidBlockStateException("No such coral type");
}
$this->coralType = $coralType;
}
public function getId() : int{
return $this->dead ? $this->idInfoFlattened->getSecondId() : parent::getId();
}
public function asItem() : Item{
//TODO: HACK! workaround dead flag being lost when broken / blockpicked (original impl only uses first ID)
return ItemFactory::getInstance()->get(
$this->dead ? ItemIds::CORAL_FAN_DEAD : ItemIds::CORAL_FAN,
$this->writeStateToItemMeta()
);
}
protected function writeStateToMeta() : int{
return (($this->axis === Axis::X ? BlockLegacyMetadata::CORAL_FAN_EAST_WEST : BlockLegacyMetadata::CORAL_FAN_NORTH_SOUTH) << 3) |
CoralTypeIdMap::getInstance()->toId($this->coralType);
}
protected function writeStateToItemMeta() : int{
return CoralTypeIdMap::getInstance()->toId($this->coralType);
}
public function getStateBitmask() : int{
return 0b1111;
}
public function getAxis() : int{ return $this->axis; }
@ -67,9 +108,6 @@ final class FloorCoralFan extends BaseCoral{
$this->axis = Axis::Z;
}
}
$this->dead = !$this->isCoveredWithWater();
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
@ -86,7 +124,4 @@ final class FloorCoralFan extends BaseCoral{
return $block->getSupportType(Facing::UP)->hasCenterSupport();
}
public function asItem() : Item{
return VanillaItems::CORAL_FAN()->setCoralType($this->coralType)->setDead($this->dead);
}
}

View File

@ -33,6 +33,18 @@ use pocketmine\world\BlockTransaction;
final class FloorSign extends BaseSign{
use SignLikeRotationTrait;
public function readStateFromData(int $id, int $stateMeta) : void{
$this->rotation = $stateMeta;
}
protected function writeStateToMeta() : int{
return $this->rotation;
}
public function getStateBitmask() : int{
return 0b1111;
}
protected function getSupportingFace() : int{
return Facing::DOWN;
}

View File

@ -33,7 +33,7 @@ class Flower extends Flowable{
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->hasTypeTag(BlockTypeTags::DIRT) || $down->hasTypeTag(BlockTypeTags::MUD)){
if($down->getId() === BlockLegacyIds::GRASS || $down->getId() === BlockLegacyIds::DIRT || $down->getId() === BlockLegacyIds::FARMLAND){
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
@ -41,8 +41,7 @@ class Flower extends Flowable{
}
public function onNearbyBlockChange() : void{
$down = $this->getSide(Facing::DOWN);
if(!$down->hasTypeTag(BlockTypeTags::DIRT) && !$down->hasTypeTag(BlockTypeTags::MUD)){
if($this->getSide(Facing::DOWN)->isTransparent()){
$this->position->getWorld()->useBreakOn($this->position);
}
}

View File

@ -36,7 +36,16 @@ class FlowerPot extends Flowable{
protected ?Block $plant = null;
public function readStateFromWorld() : Block{
protected function writeStateToMeta() : int{
//TODO: HACK! this is just to make the client actually render the plant - we purposely don't read the flag back
return $this->plant !== null ? BlockLegacyMetadata::FLOWER_POT_FLAG_OCCUPIED : 0;
}
public function getStateBitmask() : int{
return 0b1;
}
public function readStateFromWorld() : void{
parent::readStateFromWorld();
$tile = $this->position->getWorld()->getTile($this->position);
if($tile instanceof TileFlowerPot){
@ -44,8 +53,6 @@ class FlowerPot extends Flowable{
}else{
$this->setPlant(null);
}
return $this;
}
public function writeStateToWorld() : void{
@ -79,7 +86,14 @@ class FlowerPot extends Flowable{
}
private function isValidPlant(Block $block) : bool{
return $block->hasTypeTag(BlockTypeTags::POTTABLE_PLANTS);
return
$block instanceof Cactus ||
$block instanceof DeadBush ||
$block instanceof Flower ||
$block instanceof RedMushroom ||
$block instanceof Sapling ||
($block instanceof TallGrass && $block->getIdInfo()->getVariant() === BlockLegacyMetadata::TALLGRASS_FERN); //TODO: clean up
//TODO: bamboo
}
/**
@ -107,7 +121,7 @@ class FlowerPot extends Flowable{
return $block->getSupportType(Facing::UP)->hasCenterSupport();
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$world = $this->position->getWorld();
$plant = $item->getBlock();
if($this->plant !== null){

View File

@ -1,53 +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\block;
use pocketmine\block\utils\FroglightType;
use pocketmine\data\runtime\RuntimeDataDescriber;
final class Froglight extends SimplePillar{
private FroglightType $froglightType;
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
$this->froglightType = FroglightType::OCHRE();
parent::__construct($idInfo, $name, $typeInfo);
}
protected function describeType(RuntimeDataDescriber $w) : void{
$w->froglightType($this->froglightType);
}
public function getFroglightType() : FroglightType{ return $this->froglightType; }
/** @return $this */
public function setFroglightType(FroglightType $froglightType) : self{
$this->froglightType = $froglightType;
return $this;
}
public function getLightLevel() : int{
return 15;
}
}

View File

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\event\block\BlockMeltEvent;
use function mt_rand;
@ -32,8 +32,16 @@ class FrostedIce extends Ice{
protected int $age = 0;
protected function describeState(RuntimeDataDescriber $w) : void{
$w->boundedInt(2, 0, self::MAX_AGE, $this->age);
public function readStateFromData(int $id, int $stateMeta) : void{
$this->age = BlockDataSerializer::readBoundedInt("age", $stateMeta, 0, self::MAX_AGE);
}
protected function writeStateToMeta() : int{
return $this->age;
}
public function getStateBitmask() : int{
return 0b11;
}
public function getAge() : int{ return $this->age; }

View File

@ -25,9 +25,7 @@ namespace pocketmine\block;
use pocketmine\block\tile\Furnace as TileFurnace;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\crafting\FurnaceType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\block\utils\NormalHorizontalFacingInMetadataTrait;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
@ -35,24 +33,26 @@ use function mt_rand;
class Furnace extends Opaque{
use FacesOppositePlacingPlayerTrait;
use HorizontalFacingTrait;
protected FurnaceType $furnaceType;
protected bool $lit = false;
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo, FurnaceType $furnaceType){
$this->furnaceType = $furnaceType;
parent::__construct($idInfo, $name, $typeInfo);
use NormalHorizontalFacingInMetadataTrait {
readStateFromData as readFacingStateFromData;
}
protected function describeState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing);
$w->bool($this->lit);
protected BlockIdentifierFlattened $idInfoFlattened;
protected bool $lit = false; //this is set based on the blockID
public function __construct(BlockIdentifierFlattened $idInfo, string $name, BlockBreakInfo $breakInfo){
$this->idInfoFlattened = $idInfo;
parent::__construct($idInfo, $name, $breakInfo);
}
public function getFurnaceType() : FurnaceType{
return $this->furnaceType;
public function getId() : int{
return $this->lit ? $this->idInfoFlattened->getSecondId() : parent::getId();
}
public function readStateFromData(int $id, int $stateMeta) : void{
$this->readFacingStateFromData($id, $stateMeta);
$this->lit = $id === $this->idInfoFlattened->getSecondId();
}
public function getLightLevel() : int{
@ -71,7 +71,7 @@ class Furnace extends Opaque{
return $this;
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player instanceof Player){
$furnace = $this->position->getWorld()->getTile($this->position);
if($furnace instanceof TileFurnace && $furnace->canOpenWith($item->getCustomName())){

View File

@ -1,41 +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\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

@ -23,18 +23,10 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\ColoredTrait;
use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\NormalHorizontalFacingInMetadataTrait;
class GlazedTerracotta extends Opaque{
use ColoredTrait;
use FacesOppositePlacingPlayerTrait;
use HorizontalFacingTrait;
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
$this->color = DyeColor::BLACK();
parent::__construct($idInfo, $name, $typeInfo);
}
use NormalHorizontalFacingInMetadataTrait;
}

View File

@ -1,36 +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\block;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
final class GoldOre extends Opaque{
public function getDropsForCompatibleTool(Item $item) : array{
return [VanillaItems::RAW_GOLD()];
}
public function isAffectedBySilkTouch() : bool{ return true; }
}

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\DirtType;
use pocketmine\event\block\BlockSpreadEvent;
use pocketmine\item\Fertilizer;
use pocketmine\item\Hoe;
@ -73,7 +72,7 @@ class Grass extends Opaque{
$b = $world->getBlockAt($x, $y, $z);
if(
!($b instanceof Dirt) ||
!$b->getDirtType()->equals(DirtType::NORMAL()) ||
$b->isCoarse() ||
$world->getFullLightAt($x, $y + 1, $z) < 4 ||
$world->getBlockAt($x, $y + 1, $z)->getLightFilter() >= 2
){
@ -89,7 +88,7 @@ class Grass extends Opaque{
}
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($face !== Facing::UP){
return false;
}
@ -106,7 +105,7 @@ class Grass extends Opaque{
$world->setBlock($this->position, $newBlock);
return true;
}elseif($item instanceof Shovel && $this->getSide(Facing::UP)->getTypeId() === BlockTypeIds::AIR){
}elseif($item instanceof Shovel && $this->getSide(Facing::UP)->getId() === BlockLegacyIds::AIR){
$item->applyDamage(1);
$newBlock = VanillaBlocks::GRASS_PATH();
$world->addSound($this->position->add(0.5, 0.5, 0.5), new ItemUseOnBlockSound($newBlock));

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