mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-08 19:02:59 +00:00
Compare commits
151 Commits
5.0.0-ALPH
...
4.13.0
Author | SHA1 | Date | |
---|---|---|---|
cb1aac3cd4 | |||
3dd1a14fb7 | |||
63c3127248 | |||
96c32d24ba | |||
d64a9d8b52 | |||
92c29b8172 | |||
0ac9584bbb | |||
fe12e8d944 | |||
7529953f0a | |||
00dbb6855a | |||
7eca3e8081 | |||
b58d7fc82a | |||
ceea8220a9 | |||
18013e9551 | |||
bd3e9e1cad | |||
6173471cca | |||
644881372d | |||
a12aac71fd | |||
608fcd6cd7 | |||
ce9b25e97a | |||
f948cb0086 | |||
6c52723d97 | |||
d5b7bf77b0 | |||
b1a5b02d3a | |||
74e052de51 | |||
a5397d55fe | |||
65ef929d22 | |||
441919c5e3 | |||
448aeec780 | |||
78aea5c34c | |||
d7f40f75d2 | |||
b47035fbab | |||
f0925ff9dc | |||
d9324b9951 | |||
1d9336ed67 | |||
d37142af4b | |||
7c068101b7 | |||
217f9aea02 | |||
2f5e08067d | |||
a8556dff02 | |||
664089861a | |||
edb8f19a0c | |||
6c0254c1eb | |||
0bb9fb09cc | |||
ab21fcdd67 | |||
ad6a423d12 | |||
b03df4f1e6 | |||
0a2a6e2b3a | |||
0eb751c1c9 | |||
b59b1e491e | |||
95e8c68fde | |||
7e16f9be8f | |||
768650cee0 | |||
c2c529e2da | |||
289e86e899 | |||
7d59bafd83 | |||
1bbe053848 | |||
2ed48c8469 | |||
d786ed5ebf | |||
a9f06fc5f4 | |||
dff3f45d22 | |||
1e17d86421 | |||
ba18a81e88 | |||
329c2a6c0f | |||
39218017ca | |||
fc487b17be | |||
91ac47ecba | |||
f4a1d69075 | |||
cbeae906e1 | |||
b25e8e26f0 | |||
a79be994de | |||
e26c8b9e9f | |||
4e9c3e101d | |||
d295e1be54 | |||
2f3fcef97c | |||
4df1f7f502 | |||
d74719704e | |||
c5056e0a43 | |||
a47aa50477 | |||
5021096bdd | |||
f7930a3a0b | |||
bb7df60a4d | |||
992cb06da6 | |||
bb3f87f862 | |||
d2eddf9d33 | |||
81ca0c8fbf | |||
fc77b14760 | |||
52b6f1a492 | |||
0233e74f4f | |||
dd355c58d8 | |||
267032cff9 | |||
d4b8c47a65 | |||
4a3d9f8f83 | |||
1c96e7936c | |||
6cecd690b2 | |||
91e38d1f97 | |||
653178c1fd | |||
eb06535ed1 | |||
f9bcc8e862 | |||
ece49f011c | |||
f43ca405d4 | |||
d146175d27 | |||
3baa5ab712 | |||
e647e8c933 | |||
c02bead12b | |||
e9ca25c1cb | |||
a513cca582 | |||
9a47c1d401 | |||
433f5451d7 | |||
64e505defb | |||
33d1755eae | |||
fc63c54116 | |||
db07976aab | |||
0e4b79ea77 | |||
588c9b114b | |||
b095f606c1 | |||
b312e93176 | |||
172ce659b8 | |||
61933624d2 | |||
0d31b25fba | |||
90beaeaeb4 | |||
466f7e98ed | |||
59be901efe | |||
0d169b4e80 | |||
b1c0eae1f6 | |||
80832ff763 | |||
f7d0d16eb3 | |||
6375139d0b | |||
567bd8abb5 | |||
3d038b28ff | |||
0c9b6a6797 | |||
639f089c55 | |||
9010b2743c | |||
4c91c4aaf1 | |||
17125ce0e3 | |||
3987ee6cb2 | |||
51a684c0ea | |||
43e69041fc | |||
5d2b0acfc8 | |||
7d1d62042c | |||
2a33c9ed3b | |||
b03733442b | |||
9c9929ff39 | |||
566a8a261f | |||
a9e5f92958 | |||
17dde140a5 | |||
ee7d4728d8 | |||
923dcec4e7 | |||
1e5597f0d5 | |||
aebcfc516f | |||
97ef209c5f |
6
.github/dependabot.yml
vendored
6
.github/dependabot.yml
vendored
@ -6,6 +6,12 @@ updates:
|
||||
interval: daily
|
||||
time: "10:00"
|
||||
open-pull-requests-limit: 10
|
||||
ignore:
|
||||
#only allow patch updates for locale-data - this has to be updated manually due to codegen
|
||||
- dependency-name: pocketmine/locale-data
|
||||
update-types:
|
||||
- "version-update:semver-major"
|
||||
- "version-update:semver-minor"
|
||||
|
||||
- package-ecosystem: gitsubmodule
|
||||
directory: "/"
|
||||
|
8
.github/workflows/build-docker-image.yml
vendored
8
.github/workflows/build-docker-image.yml
vendored
@ -46,7 +46,7 @@ jobs:
|
||||
run: echo ::set-output name=NAME::$(echo "${GITHUB_REPOSITORY,,}")
|
||||
|
||||
- name: Build image for tag
|
||||
uses: docker/build-push-action@v3.2.0
|
||||
uses: docker/build-push-action@v3.3.0
|
||||
with:
|
||||
push: true
|
||||
context: ./pocketmine-mp
|
||||
@ -59,7 +59,7 @@ jobs:
|
||||
|
||||
- name: Build image for major tag
|
||||
if: steps.channel.outputs.CHANNEL == 'stable'
|
||||
uses: docker/build-push-action@v3.2.0
|
||||
uses: docker/build-push-action@v3.3.0
|
||||
with:
|
||||
push: true
|
||||
context: ./pocketmine-mp
|
||||
@ -72,7 +72,7 @@ jobs:
|
||||
|
||||
- name: Build image for minor tag
|
||||
if: steps.channel.outputs.CHANNEL == 'stable'
|
||||
uses: docker/build-push-action@v3.2.0
|
||||
uses: docker/build-push-action@v3.3.0
|
||||
with:
|
||||
push: true
|
||||
context: ./pocketmine-mp
|
||||
@ -85,7 +85,7 @@ jobs:
|
||||
|
||||
- name: Build image for latest tag
|
||||
if: steps.channel.outputs.CHANNEL == 'stable'
|
||||
uses: docker/build-push-action@v3.2.0
|
||||
uses: docker/build-push-action@v3.3.0
|
||||
with:
|
||||
push: true
|
||||
context: ./pocketmine-mp
|
||||
|
2
.github/workflows/discord-release-notify.yml
vendored
2
.github/workflows/discord-release-notify.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup PHP and tools
|
||||
uses: shivammathur/setup-php@2.22.0
|
||||
uses: shivammathur/setup-php@2.24.0
|
||||
with:
|
||||
php-version: 8.0
|
||||
|
||||
|
5
.github/workflows/draft-release.yml
vendored
5
.github/workflows/draft-release.yml
vendored
@ -18,7 +18,7 @@ jobs:
|
||||
submodules: true
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@2.22.0
|
||||
uses: shivammathur/setup-php@2.24.0
|
||||
with:
|
||||
php-version: 8.0
|
||||
|
||||
@ -55,6 +55,7 @@ jobs:
|
||||
echo ::set-output name=MCPE_VERSION::$(php -r 'require "vendor/autoload.php"; echo \pocketmine\network\mcpe\protocol\ProtocolInfo::MINECRAFT_VERSION_NETWORK;')
|
||||
echo ::set-output name=PM_VERSION_SHORT::$(php -r 'require "vendor/autoload.php"; $v = explode(".", \pocketmine\VersionInfo::BASE_VERSION); array_pop($v); echo implode(".", $v);')
|
||||
echo ::set-output name=PM_VERSION_MD::$(php -r 'require "vendor/autoload.php"; echo str_replace(".", "", \pocketmine\VersionInfo::BASE_VERSION);')
|
||||
echo ::set-output name=CHANGELOG_SUFFIX::$(php -r 'require "vendor/autoload.php"; echo \pocketmine\VersionInfo::BUILD_CHANNEL === "stable" ? "" : "-" . \pocketmine\VersionInfo::BUILD_CHANNEL;')
|
||||
|
||||
- name: Generate build info
|
||||
run: php build/generate-build-info-json.php ${{ github.sha }} ${{ steps.get-pm-version.outputs.PM_VERSION }} ${{ github.repository }} ${{ steps.build-number.outputs.BUILD_NUMBER }} ${{ github.run_id }} > build_info.json
|
||||
@ -80,4 +81,4 @@ jobs:
|
||||
body: |
|
||||
**For Minecraft: Bedrock Edition ${{ steps.get-pm-version.outputs.MCPE_VERSION }}**
|
||||
|
||||
Please see the [changelogs](${{ github.server_url }}/${{ github.repository }}/blob/${{ steps.get-pm-version.outputs.PM_VERSION }}/changelogs/${{ steps.get-pm-version.outputs.PM_VERSION_SHORT }}.md#${{ steps.get-pm-version.outputs.PM_VERSION_MD }}) for details.
|
||||
Please see the [changelogs](${{ github.server_url }}/${{ github.repository }}/blob/${{ steps.get-pm-version.outputs.PM_VERSION }}/changelogs/${{ steps.get-pm-version.outputs.PM_VERSION_SHORT }}${{ steps.get-pm-version.outputs.CHANGELOG_SUFFIX }}.md#${{ steps.get-pm-version.outputs.PM_VERSION_MD }}) for details.
|
||||
|
33
.github/workflows/main.yml
vendored
33
.github/workflows/main.yml
vendored
@ -9,18 +9,20 @@ jobs:
|
||||
build-php:
|
||||
name: Prepare PHP
|
||||
runs-on: ${{ matrix.image }}
|
||||
concurrency: php-build-${{ matrix.php }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: [8.0.23, 8.1.10]
|
||||
php: [8.0.27, 8.1.14, 8.2.1]
|
||||
|
||||
steps:
|
||||
- name: Build and prepare PHP cache
|
||||
uses: pmmp/setup-php-action@82a44d659bf5046612c69f036af3e14dc32e3fa8
|
||||
uses: pmmp/setup-php-action@6dd74c145250109942b08fc63cd5118edd2fd256
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
install-path: "./bin"
|
||||
pm-version-major: "4"
|
||||
|
||||
phpstan:
|
||||
name: PHPStan analysis
|
||||
@ -31,16 +33,17 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: [8.0.23, 8.1.10]
|
||||
php: [8.0.27, 8.1.14, 8.2.1]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@82a44d659bf5046612c69f036af3e14dc32e3fa8
|
||||
uses: pmmp/setup-php-action@6dd74c145250109942b08fc63cd5118edd2fd256
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
install-path: "./bin"
|
||||
pm-version-major: "4"
|
||||
|
||||
- name: Install Composer
|
||||
run: curl -sS https://getcomposer.org/installer | php
|
||||
@ -69,16 +72,17 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: [8.0.23, 8.1.10]
|
||||
php: [8.0.27, 8.1.14, 8.2.1]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@82a44d659bf5046612c69f036af3e14dc32e3fa8
|
||||
uses: pmmp/setup-php-action@6dd74c145250109942b08fc63cd5118edd2fd256
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
install-path: "./bin"
|
||||
pm-version-major: "4"
|
||||
|
||||
- name: Install Composer
|
||||
run: curl -sS https://getcomposer.org/installer | php
|
||||
@ -107,7 +111,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: [8.0.23, 8.1.10]
|
||||
php: [8.0.27, 8.1.14, 8.2.1]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@ -115,10 +119,11 @@ jobs:
|
||||
submodules: true
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@82a44d659bf5046612c69f036af3e14dc32e3fa8
|
||||
uses: pmmp/setup-php-action@6dd74c145250109942b08fc63cd5118edd2fd256
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
install-path: "./bin"
|
||||
pm-version-major: "4"
|
||||
|
||||
- name: Install Composer
|
||||
run: curl -sS https://getcomposer.org/installer | php
|
||||
@ -147,16 +152,17 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: [8.0.23, 8.1.10]
|
||||
php: [8.0.27, 8.1.14, 8.2.1]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@82a44d659bf5046612c69f036af3e14dc32e3fa8
|
||||
uses: pmmp/setup-php-action@6dd74c145250109942b08fc63cd5118edd2fd256
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
install-path: "./bin"
|
||||
pm-version-major: "4"
|
||||
|
||||
- name: Install Composer
|
||||
run: curl -sS https://getcomposer.org/installer | php
|
||||
@ -180,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
|
||||
@ -198,10 +201,12 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup PHP and tools
|
||||
uses: shivammathur/setup-php@2.22.0
|
||||
uses: shivammathur/setup-php@2.24.0
|
||||
with:
|
||||
php-version: 8.0
|
||||
tools: php-cs-fixer:3.11
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Run PHP-CS-Fixer
|
||||
run: php-cs-fixer fix --dry-run --diff --ansi
|
||||
|
3
.github/workflows/update-php-versions.php
vendored
3
.github/workflows/update-php-versions.php
vendored
@ -23,7 +23,8 @@ declare(strict_types=1);
|
||||
|
||||
const VERSIONS = [
|
||||
"8.0",
|
||||
"8.1"
|
||||
"8.1",
|
||||
"8.2"
|
||||
];
|
||||
|
||||
$workflowFile = file_get_contents(__DIR__ . '/main.yml');
|
||||
|
@ -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";
|
@ -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";
|
@ -36,8 +36,8 @@ use function ksort;
|
||||
use function mb_strtoupper;
|
||||
use function preg_match;
|
||||
use function sprintf;
|
||||
use function str_ends_with;
|
||||
use function str_replace;
|
||||
use function substr;
|
||||
use const SORT_STRING;
|
||||
use const STDERR;
|
||||
|
||||
@ -121,7 +121,7 @@ require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
if(is_dir($argv[1])){
|
||||
/** @var string $file */
|
||||
foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($argv[1], \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::CURRENT_AS_PATHNAME)) as $file){
|
||||
if(substr($file, -4) !== ".php"){
|
||||
if(!str_ends_with($file, ".php")){
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1,249 +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\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 = [];
|
||||
|
||||
$functionName = lcfirst($virtualTypeName);
|
||||
$lines[] = "public function $functionName(\\$nativeTypeName \$value) : void{";
|
||||
$lines[] = "\t\$this->int($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 = [];
|
||||
|
||||
$functionName = lcfirst($virtualTypeName);
|
||||
$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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object[] $enumMembers
|
||||
* @phpstan-param array<string, object> $enumMembers
|
||||
*
|
||||
* @return string[]
|
||||
* @phpstan-return list<string>
|
||||
*/
|
||||
function buildEnumWriterFunc(array $enumMembers, string &$functionName) : array{
|
||||
$reflect = new \ReflectionClass($enumMembers[array_key_first($enumMembers)]);
|
||||
return buildWriterFunc(
|
||||
$reflect->getShortName(),
|
||||
$reflect->getName(),
|
||||
stringifyEnumMembers($enumMembers, $reflect->getName()),
|
||||
$functionName
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object[] $enumMembers
|
||||
* @phpstan-param array<string, object> $enumMembers
|
||||
*
|
||||
* @return string[]
|
||||
* @phpstan-return list<string>
|
||||
*/
|
||||
function buildEnumReaderFunc(array $enumMembers, string &$functionName) : array{
|
||||
if(count($enumMembers) === 0){
|
||||
throw new \InvalidArgumentException("Enum members cannot be empty");
|
||||
}
|
||||
$reflect = new \ReflectionClass($enumMembers[array_key_first($enumMembers)]);
|
||||
return buildReaderFunc(
|
||||
$reflect->getShortName(),
|
||||
$reflect->getName(),
|
||||
stringifyEnumMembers($enumMembers, $reflect->getName()),
|
||||
$functionName
|
||||
);
|
||||
}
|
||||
|
||||
$enumsUsed = [
|
||||
BellAttachmentType::getAll(),
|
||||
CopperOxidation::getAll(),
|
||||
CoralType::getAll(),
|
||||
DirtType::getAll(),
|
||||
DyeColor::getAll(),
|
||||
FroglightType::getAll(),
|
||||
LeverFacing::getAll(),
|
||||
MushroomBlockType::getAll(),
|
||||
SkullType::getAll(),
|
||||
SlabType::getAll(),
|
||||
SuspiciousStewType::getAll(),
|
||||
PotionType::getAll()
|
||||
];
|
||||
|
||||
$readerFuncs = [
|
||||
"" => [
|
||||
"abstract protected function readInt(int \$bits) : int;"
|
||||
]
|
||||
];
|
||||
$writerFuncs = [
|
||||
"" => [
|
||||
"abstract public function int(int \$bits, int \$value) : void;"
|
||||
]
|
||||
];
|
||||
$functionName = "";
|
||||
|
||||
foreach($enumsUsed as $enumMembers){
|
||||
$writerF = buildEnumWriterFunc($enumMembers, $functionName);
|
||||
/** @var string $functionName */
|
||||
$writerFuncs[$functionName] = $writerF;
|
||||
$readerF = buildEnumReaderFunc($enumMembers, $functionName);
|
||||
/** @var string $functionName */
|
||||
$readerFuncs[$functionName] = $readerF;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[][] $functions
|
||||
* @phpstan-param array<string, list<string>> $functions
|
||||
*/
|
||||
function printFunctions(array $functions, string $className) : 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 "trait $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");
|
||||
printFunctions($readerFuncs, "RuntimeEnumDeserializerTrait");
|
||||
|
||||
echo "Done. Don't forget to run CS fixup after generating code.\n";
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\build\make_release;
|
||||
|
||||
use pocketmine\utils\Filesystem;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\utils\VersionString;
|
||||
use pocketmine\VersionInfo;
|
||||
@ -30,7 +31,6 @@ use function array_keys;
|
||||
use function array_map;
|
||||
use function dirname;
|
||||
use function fgets;
|
||||
use function file_get_contents;
|
||||
use function file_put_contents;
|
||||
use function fwrite;
|
||||
use function getopt;
|
||||
@ -50,7 +50,7 @@ use const STR_PAD_LEFT;
|
||||
require_once dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev, string $channel) : void{
|
||||
$versionInfo = Utils::assumeNotFalse(file_get_contents($versionInfoPath), $versionInfoPath . " should always exist");
|
||||
$versionInfo = Filesystem::fileGetContents($versionInfoPath);
|
||||
$versionInfo = preg_replace(
|
||||
$pattern = '/^([\t ]*public )?const BASE_VERSION = "(\d+)\.(\d+)\.(\d+)(?:-(.*))?";$/m',
|
||||
'$1const BASE_VERSION = "' . $newVersion . '";',
|
||||
|
Submodule build/php updated: 6b605ed7c4...c6585061ca
@ -30,3 +30,90 @@ Released 15th December 2022.
|
||||
|
||||
## Dependencies
|
||||
- Updated BedrockProtocol to [17.1.0](https://github.com/pmmp/BedrockProtocol/releases/tag/17.1.0+bedrock-1.19.50). This adds some missing `LevelSoundEvent` constants and fixes the values for `ContainerUIIds`.
|
||||
|
||||
# 4.12.3
|
||||
Released 28th December 2022.
|
||||
|
||||
## Fixes
|
||||
- Fixed unauthenticated connections taking up player count slots, preventing players from joining.
|
||||
- Fixed a possible crash in `World->tickChunk()` when plugins unload chunks during some events.
|
||||
- `/gamemode` will now report a failure to change game mode if the player is already in the requested game mode.
|
||||
|
||||
# 4.12.4
|
||||
Released 3rd January 2023.
|
||||
|
||||
## Fixes
|
||||
- Added workarounds for an active exploit being used to deny service to servers.
|
||||
|
||||
# 4.12.5
|
||||
Released 6th January 2023.
|
||||
|
||||
## Fixes
|
||||
- Removed a workaround for an old client bug in custom form responses. The code contained a denial-of-service vulnerability.
|
||||
|
||||
# 4.12.6
|
||||
Released 7th January 2023.
|
||||
|
||||
## Changes
|
||||
- Added a new security measure to `NetworkSession` to detect and ban players who flood the server with packets.
|
||||
|
||||
# 4.12.7
|
||||
Released 8th January 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed players getting kicked when the server lags for too long.
|
||||
- Fixed players getting kicked when a debugging session is active and a breakpoint is hit.
|
||||
|
||||
# 4.12.8
|
||||
Released 9th January 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed players getting kicked during PvP.
|
||||
- Fixed players randomly getting kicked on Windows (improper rate limit handling wrt. 15ms timer resolution).
|
||||
|
||||
# 4.12.9
|
||||
Released 16th January 2023.
|
||||
|
||||
## Improvements
|
||||
### Timings
|
||||
- Added new timers:
|
||||
- `Server Mid-Tick Processing` - time spent processing Snooze interrupts between ticks (e.g. incoming network packets)
|
||||
- `Server Tick Update Cycle` - time spent processing regular per-tick updates (e.g. entity movement, world updates, etc.) (`Server->tick()`)
|
||||
- `Full Server Tick` timer now counts the total of `Server Mid-Tick Processing` and `Server Tick Update Cycle`, which generates more accurate performance metrics.
|
||||
- Previously, this timer only counted the time spent during regular per-tick updates, and the time recorded by `Server Mid-Tick Processing` was not included in the report at all.
|
||||
|
||||
## Fixes
|
||||
- Fixed blocks such as pressure plates being able to be placed without the correct supporting blocks if the clicked block was solid.
|
||||
- Pressure plates now self-destruct when the block below them is removed.
|
||||
- Fixed being unable to place blocks by clicking on the side of a bell (when the click doesn't result in ringing the bell).
|
||||
- Fixed various rotation-aware blocks (e.g. stairs) behaving incorrectly when placed by clicking on the side of a replaceable block (e.g. tall grass).
|
||||
- Fixed banners being able to be placed on top of blocks such as skulls.
|
||||
- Fixed server-side collision boxes of walls and glass (which should connect, but didn't). Note that wall connections still don't show client side - this just fixes the collision boxes.
|
||||
- Fixed `PlayerInteractEvent` with `LEFT_CLICK` sometimes firing before `BlockBreakEvent` when breaking blocks.
|
||||
|
||||
## Other changes
|
||||
- Increased packet batch budget for player sessions.
|
||||
|
||||
# 4.12.10
|
||||
Released 18th January 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed reported server load not including the time spent processing Snooze interrupts between ticks (e.g. incoming network packets).
|
||||
- Fixed `Connection Handler` entry in timings report not including time spent receiving packets.
|
||||
|
||||
## Note about server load & performance
|
||||
This version will report higher apparent server load than previous versions. The actual performance of the server is unchanged; the previous reported load was inaccurate.
|
||||
These bugs have been present for nearly 5 years (ever since the first introduction of Snooze in 3.0.0).
|
||||
|
||||
# 4.12.11
|
||||
Released 22nd January 2023.
|
||||
|
||||
## General
|
||||
- Code is now tested and analysed using PHP 8.2 in addition to 8.1 and 8.0.
|
||||
|
||||
## Fixes
|
||||
- Fixed pthreads 5.0.0 incorrectly being treated as compatible.
|
||||
- Fixed deprecation errors on PHP 8.2.
|
||||
|
||||
## Documentation
|
||||
- Updated documentation in `PlayerPreLoginEvent`.
|
||||
|
94
changelogs/4.13-beta.md
Normal file
94
changelogs/4.13-beta.md
Normal file
@ -0,0 +1,94 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.50**
|
||||
|
||||
This is a minor feature release for PocketMine-MP, introducing some new features and improvements.
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 4.13.0-BETA1
|
||||
Released 18th January 2023.
|
||||
|
||||
## Gameplay
|
||||
- Death message is now shown on the death screen when a player dies.
|
||||
- Armour damage is now only increased if the armour reduced the damage taken.
|
||||
- Implemented Swift Sneak enchantment.
|
||||
- Fixed incorrect collision box calculation of walls and glass/bars when connected. Note: Client-side, wall connections are still broken; this only fixes projectile flight server-side.
|
||||
|
||||
## Performance
|
||||
- Improved performance of chunk selection for chunk random ticking using a cache. This improves performance of chunk random ticking by 10-20%.
|
||||
|
||||
## Localization
|
||||
- Added localized description for the `/dumpmemory` command.
|
||||
|
||||
## Permissions
|
||||
- Added the following new core permissions:
|
||||
- `pocketmine.command.effect.other` - allows the player to use the `/effect` command on other players (default operator only)
|
||||
- `pocketmine.command.effect.self` - allows the player to use the `/effect` command on themselves (default operator only)
|
||||
- `pocketmine.command.enchant.other` - allows the player to use the `/enchant` command on other players (default operator only)
|
||||
- `pocketmine.command.enchant.self` - allows the player to use the `/enchant` command on themselves (default operator only)
|
||||
- `pocketmine.command.gamemode.other` - allows the player to use the `/gamemode` command on other players (default operator only)
|
||||
- `pocketmine.command.gamemode.self` - allows the player to use the `/gamemode` command on themselves (default operator only)
|
||||
- `pocketmine.command.give.other` - allows the player to use the `/give` command on other players (default operator only)
|
||||
- `pocketmine.command.give.self` - allows the player to use the `/give` command on themselves (default operator only)
|
||||
- `pocketmine.command.spawnpoint.other` - allows the player to use the `/spawnpoint` command on other players (default operator only)
|
||||
- `pocketmine.command.spawnpoint.self` - allows the player to use the `/spawnpoint` command on themselves (default operator only)
|
||||
- `pocketmine.command.teleport.other` - allows the player to use the `/teleport` command on other players (default operator only)
|
||||
- `pocketmine.command.teleport.self` - allows the player to use the `/teleport` command on themselves (default operator only)
|
||||
- `pocketmine.command.title.other` - allows the player to use the `/title` command on other players (default operator only)
|
||||
- `pocketmine.command.title.self` - allows the player to use the `/title` command on themselves (default operator only)
|
||||
|
||||
## Internals
|
||||
- Decoupled `Player->sendMessage()` and `Player->sendTranslation()`.
|
||||
- Refactored resource pack loading in `ResourcePackManager` to make it easier to understand.
|
||||
- Client-aware translation processing has been moved to `NetworkSession` due to being client-specific.
|
||||
- Replaced hardcoded strings with constants in various places.
|
||||
- `NetworkSession` destructive cleanup is now deferred to the next session tick. This fixes various `InventoryManager` crashes when kicking players during events.
|
||||
- Updated code using `strpos()` to use `str_starts_with()`, `str_ends_with()` and `str_contains()` where appropriate.
|
||||
- Added documentation for some internal methods.
|
||||
|
||||
## API
|
||||
### `pocketmine\command`
|
||||
- The following new API methods have been added:
|
||||
- `protected VanillaCommand->fetchPermittedPlayerTarget(...) : ?Player` - fetches a player target according to the given sender permissions, or null if not found or not permitted
|
||||
|
||||
### `pocketmine\entity`
|
||||
- The following new API methods have been added:
|
||||
- `public Living->getDisplayName() : string` - the name of the entity to be shown in death messages, commands etc.
|
||||
|
||||
### `pocketmine\event\world`
|
||||
- The following new classes have been added:
|
||||
- `WorldSoundEvent` - called when a sound is played in a world
|
||||
- `WorldParticleEvent` - called when a particle is spawned in a world
|
||||
|
||||
### `pocketmine\item`
|
||||
- The following new API methods have been added:
|
||||
- `public Item->onInteractEntity(Player $player, Entity $entity, Vector3 $clickVector) : bool` - called when a player interacts with an entity with this item in hand
|
||||
|
||||
### `pocketmine\lang`
|
||||
- `Language->translate()` and `Language->translateString()` no longer parse nested translation in the "base text". This was never intended behaviour, and didn't work beyond the first level anyway.
|
||||
|
||||
### `pocketmine\player`
|
||||
- The following new interfaces have been added:
|
||||
- `PlayerDataProvider` - implemented by classes which want to offer storage for player data
|
||||
- The following new classes have been added:
|
||||
- `DatFilePlayerDataProvider` - the default player data provider, which stores `.dat` files in the `players` folder
|
||||
- `PlayerDataLoadException` - thrown when an error occurs while loading player data
|
||||
- `PlayerDataSaveException` - thrown when an error occurs while saving player data
|
||||
- The following API methods have been deprecated:
|
||||
- `Player->sendTranslation()` - use `Player->sendMessage()` instead with a `Translatable` message
|
||||
|
||||
### `pocketmine\resourcepacks`
|
||||
- The following new API methods have been added:
|
||||
- `public ResourcePackManager->setResourceStack(list<ResourcePack> $resourceStack) : void` - sets the list of resource packs to be applied by players
|
||||
- `public ResourcePackManager->setPackEncryptionKey(string $id, ?string $key) : void` - sets the encryption key to be used for a resource pack
|
||||
|
||||
### `pocketmine\utils`
|
||||
- The following new API methods have been added:
|
||||
- `public static Filesystem::fileGetContents(...) : string` - a wrapper around `file_get_contents()` which throws an exception on failure
|
||||
|
||||
### `pocketmine\world`
|
||||
- The following new API methods have been added:
|
||||
- `public World->requestSafeSpawn(?Vector3 $spawn = null) : Promise<Position>` - an async version of `getSafeSpawn()` which generates all the needed chunks before returning
|
94
changelogs/4.13.md
Normal file
94
changelogs/4.13.md
Normal file
@ -0,0 +1,94 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.50**
|
||||
|
||||
This is a minor feature release for PocketMine-MP, introducing some new features and improvements.
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 4.13.0
|
||||
Released 30th January 2023.
|
||||
|
||||
## Gameplay
|
||||
- Death message is now shown on the death screen when a player dies.
|
||||
- Armour damage is now only increased if the armour reduced the damage taken.
|
||||
- Implemented Swift Sneak enchantment.
|
||||
- Fixed incorrect collision box calculation of walls and glass/bars when connected. Note: Client-side, wall connections are still broken; this only fixes projectile flight server-side.
|
||||
|
||||
## Performance
|
||||
- Improved performance of chunk selection for chunk random ticking using a cache. This improves performance of chunk random ticking by 10-20%.
|
||||
|
||||
## Localization
|
||||
- Added localized description for the `/dumpmemory` command.
|
||||
|
||||
## Permissions
|
||||
- Added the following new core permissions:
|
||||
- `pocketmine.command.effect.other` - allows the player to use the `/effect` command on other players (default operator only)
|
||||
- `pocketmine.command.effect.self` - allows the player to use the `/effect` command on themselves (default operator only)
|
||||
- `pocketmine.command.enchant.other` - allows the player to use the `/enchant` command on other players (default operator only)
|
||||
- `pocketmine.command.enchant.self` - allows the player to use the `/enchant` command on themselves (default operator only)
|
||||
- `pocketmine.command.gamemode.other` - allows the player to use the `/gamemode` command on other players (default operator only)
|
||||
- `pocketmine.command.gamemode.self` - allows the player to use the `/gamemode` command on themselves (default operator only)
|
||||
- `pocketmine.command.give.other` - allows the player to use the `/give` command on other players (default operator only)
|
||||
- `pocketmine.command.give.self` - allows the player to use the `/give` command on themselves (default operator only)
|
||||
- `pocketmine.command.spawnpoint.other` - allows the player to use the `/spawnpoint` command on other players (default operator only)
|
||||
- `pocketmine.command.spawnpoint.self` - allows the player to use the `/spawnpoint` command on themselves (default operator only)
|
||||
- `pocketmine.command.teleport.other` - allows the player to use the `/teleport` command on other players (default operator only)
|
||||
- `pocketmine.command.teleport.self` - allows the player to use the `/teleport` command on themselves (default operator only)
|
||||
- `pocketmine.command.title.other` - allows the player to use the `/title` command on other players (default operator only)
|
||||
- `pocketmine.command.title.self` - allows the player to use the `/title` command on themselves (default operator only)
|
||||
|
||||
## Internals
|
||||
- Decoupled `Player->sendMessage()` and `Player->sendTranslation()`.
|
||||
- Refactored resource pack loading in `ResourcePackManager` to make it easier to understand.
|
||||
- Client-aware translation processing has been moved to `NetworkSession` due to being client-specific.
|
||||
- Replaced hardcoded strings with constants in various places.
|
||||
- `NetworkSession` destructive cleanup is now deferred to the next session tick. This fixes various `InventoryManager` crashes when kicking players during events.
|
||||
- Updated code using `strpos()` to use `str_starts_with()`, `str_ends_with()` and `str_contains()` where appropriate.
|
||||
- Added documentation for some internal methods.
|
||||
|
||||
## API
|
||||
### `pocketmine\command`
|
||||
- The following new API methods have been added:
|
||||
- `protected VanillaCommand->fetchPermittedPlayerTarget(...) : ?Player` - fetches a player target according to the given sender permissions, or null if not found or not permitted
|
||||
|
||||
### `pocketmine\entity`
|
||||
- The following new API methods have been added:
|
||||
- `public Living->getDisplayName() : string` - the name of the entity to be shown in death messages, commands etc.
|
||||
|
||||
### `pocketmine\event\world`
|
||||
- The following new classes have been added:
|
||||
- `WorldSoundEvent` - called when a sound is played in a world
|
||||
- `WorldParticleEvent` - called when a particle is spawned in a world
|
||||
|
||||
### `pocketmine\item`
|
||||
- The following new API methods have been added:
|
||||
- `public Item->onInteractEntity(Player $player, Entity $entity, Vector3 $clickVector) : bool` - called when a player interacts with an entity with this item in hand
|
||||
|
||||
### `pocketmine\lang`
|
||||
- `Language->translate()` and `Language->translateString()` no longer parse nested translation in the "base text". This was never intended behaviour, and didn't work beyond the first level anyway.
|
||||
|
||||
### `pocketmine\player`
|
||||
- The following new interfaces have been added:
|
||||
- `PlayerDataProvider` - implemented by classes which want to offer storage for player data
|
||||
- The following new classes have been added:
|
||||
- `DatFilePlayerDataProvider` - the default player data provider, which stores `.dat` files in the `players` folder
|
||||
- `PlayerDataLoadException` - thrown when an error occurs while loading player data
|
||||
- `PlayerDataSaveException` - thrown when an error occurs while saving player data
|
||||
- The following API methods have been deprecated:
|
||||
- `Player->sendTranslation()` - use `Player->sendMessage()` instead with a `Translatable` message
|
||||
|
||||
### `pocketmine\resourcepacks`
|
||||
- The following new API methods have been added:
|
||||
- `public ResourcePackManager->setResourceStack(list<ResourcePack> $resourceStack) : void` - sets the list of resource packs to be applied by players
|
||||
- `public ResourcePackManager->setPackEncryptionKey(string $id, ?string $key) : void` - sets the encryption key to be used for a resource pack
|
||||
|
||||
### `pocketmine\utils`
|
||||
- The following new API methods have been added:
|
||||
- `public static Filesystem::fileGetContents(...) : string` - a wrapper around `file_get_contents()` which throws an exception on failure
|
||||
|
||||
### `pocketmine\world`
|
||||
- The following new API methods have been added:
|
||||
- `public World->requestSafeSpawn(?Vector3 $spawn = null) : Promise<Position>` - an async version of `getSafeSpawn()` which generates all the needed chunks before returning
|
@ -1,739 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.0**
|
||||
|
||||
# 5.0.0-ALPHA1
|
||||
Released 6th July 2022.
|
||||
|
||||
This is a development snapshot of 5.0.0, an upcoming major update to PocketMine-MP. This version includes many new improvements, including support for Bedrock worlds from 1.13 onwards, a large array of new blocks, and various changes to the plugin API.
|
||||
|
||||
## WARNING
|
||||
**This is an ALPHA release.** It is an early development snapshot of the upcoming 5.0.0 release.
|
||||
This means it is LIKELY to be unstable, and/or have performance issues not found in the latest stable releases.
|
||||
|
||||
**BACK UP your data before testing this.** This version will work with worlds and player data from 4.x, **BUT** any world or player data loaded in 5.0.0 **will not work in 4.x** due to backwards-incompatible storage format changes.
|
||||
|
||||
In addition, there are a number of breaking API changes. Plugins for 4.x may require code changes to run on this version.
|
||||
|
||||
The API is **not finalized**. You should expect further changes in later alphas.
|
||||
|
||||
## Core
|
||||
- Worlds are now saved according to the Bedrock 1.19.0 format.
|
||||
- Worlds generated by Bedrock from 1.13.0 and up are now supported (previously, only worlds up to 1.12 were supported).
|
||||
- `/particle` now accepts strings for particle data instead of integers.
|
||||
- `/particle` no longer accepts integers for block or item IDs.
|
||||
- The usage of `blockcrack`, `iconcrack` and `blockdust` particle types in `/particle` now follows the same pattern as other particle types, with the data for each being passed in the `data` parameter instead of being baked into the particle name.
|
||||
|
||||
## Tools
|
||||
- The following tool scripts have been added:
|
||||
- `generate-block-palette-spec.php` - generates a JSON file with a readable overview of blocks, their state properties, and their possible values
|
||||
- `generate-blockstate-upgrade-schema.php` - generates JSON blockstate upgrade schemas like those found in [BedrockBlockUpgradeSchema](https://github.com/pmmp/BedrockBlockUpgradeSchema)
|
||||
- `generate-item-upgrade-schema.php` - generates JSON item ID/meta upgrade schemas like those found in [BedrockItemUpgradeSchema](https://github.com/pmmp/BedrockItemUpgradeSchema)
|
||||
|
||||
## Gameplay
|
||||
### Blocks
|
||||
- Added the following new blocks:
|
||||
- Amethyst Block
|
||||
- Ancient Debris
|
||||
- Basalt
|
||||
- Blackstone blocks, slabs, stairs, and walls
|
||||
- Calcite
|
||||
- Chiseled Deepslate
|
||||
- Chiseled Nether Bricks
|
||||
- Chiseled Polished Blackstone
|
||||
- Cobbled Deepslate blocks, slabs, stairs, and walls
|
||||
- Copper Ore
|
||||
- Cracked Deepslate Bricks
|
||||
- Crached Deepslate Tiles
|
||||
- Cracked Nether Bricks
|
||||
- Cracked Polished Blackstone Bricks
|
||||
- Crimson buttons, doors, fences, fence gates, hyphae, planks, pressure plates, signs, slabs, stairs, stems, and trapdoors
|
||||
- Deepslate
|
||||
- Deepslate Bricks blocks, slabs, stairs, and walls
|
||||
- Deepslate Ores (coal, copper, diamond, emerald, gold, iron, lapis lazuli, redstone)
|
||||
- Deepslate Tiles blocks, slabs, stairs, and walls
|
||||
- Honeycomb Block
|
||||
- Light Block
|
||||
- Mangrove buttons, doors, fences, fence gates, logs, planks, pressure plates, signs, slabs, stairs, trapdoors, and wood
|
||||
- Mud Bricks blocks, slabs, stairs, and walls
|
||||
- Nether Gold Ore
|
||||
- Polished Basalt
|
||||
- Polished Blackstone blocks, buttons, pressure plates, slabs, stairs, and walls
|
||||
- Polished Blackstone Bricks blocks, slabs, stairs, and walls
|
||||
- Polished Deepslate blocks, slabs, stairs, and walls
|
||||
- Quartz Bricks
|
||||
- Shroomlight
|
||||
- Smooth Basalt
|
||||
- Soul Fire
|
||||
- Soul Lantern
|
||||
- Soul Soil
|
||||
- Soul Torch
|
||||
- Tuff
|
||||
- Warped buttons, doors, fences, fence gates, hyphae, planks, pressure plates, signs, slabs, stairs, stems, and trapdoors
|
||||
- Added support for basalt generators
|
||||
- Iron Ore and Gold Ore now drop Raw Iron and Raw Gold respectively, instead of the ore blocks.
|
||||
- Item frames can now be placed on the top and bottom of blocks.
|
||||
- All-sided logs ("wood", for want of a better name) can now be placed in X, Y, and Z orientations.
|
||||
- Walls now connect when placed, following the pre-1.16 logic. (1.16 logic is planned to be implemented, but currently low priority.)
|
||||
- Stripping logs by right-clicking them with an axe is now supported.
|
||||
|
||||
### Items
|
||||
- Added the following new items:
|
||||
- Amethyst Shard
|
||||
- Copper Ingot
|
||||
- Disc Fragment (5)
|
||||
- Echo Shard
|
||||
- Glow Ink Sac
|
||||
- Honeycomb
|
||||
- Phantom Membrane
|
||||
- Raw Copper
|
||||
- Raw Gold
|
||||
- Raw Iron
|
||||
- Spyglass
|
||||
|
||||
## API
|
||||
### General
|
||||
- Protected and public properties now use native property types wherever possible.
|
||||
- Parameter and return typehints have been applied in many places where it wasn't previously possible.
|
||||
|
||||
### `pocketmine\block`
|
||||
#### Runtime block representation
|
||||
- Blocks no longer use internal Minecraft IDs and metadata to identify themselves. All APIs associated with legacy IDs and meta have been removed.
|
||||
- A new set of runtime IDs generated from `VanillaBlocks` is used to identify block types. These IDs are defined in `BlockTypeIds`.
|
||||
- These new IDs are used for runtime representation of blocks on chunks, and for type comparison purposes.
|
||||
- Block type IDs are used at **runtime only**. They should **NOT** be stored in configs or databases, as they are subject to change without warning.
|
||||
- Block state properties (e.g. facing, colour, etc.) are now represented by PM-specific state data instead of legacy metadata. The state data consists of:
|
||||
- Dynamic type data - this is retained by items when the block is broken (colour, wet/dry, coral type, etc.) - handled by `Block->decodeType()` and `Block->encodeType()`
|
||||
- State data - this is discarded when the block is broken (facing direction, lit/unlit, powered/unpowered, etc.) - handled by `Block->decodeState()` and `Block->encodeState()`
|
||||
|
||||
**Block type IDs, and state/type data, are intended for use at RUNTIME only. The values of type IDs and state data may change without warning. They should NOT be saved in configs or databases.**
|
||||
|
||||
#### Implementing new blocks
|
||||
To register a new block, the following changes are now required:
|
||||
|
||||
- Add a new type ID to `BlockTypeIds`
|
||||
- Register the block in `BlockFactory`
|
||||
- Amend `VanillaBlocks` to include the new block
|
||||
- Amend `BlockStateToBlockObjectDeserializer` to deserialize the block from disk
|
||||
- Amend `BlockObjectToBlockStateSerializer` to serialize the block for disk
|
||||
- Optionally, amend `StringToItemParser` to add string alias(es) for the block, so that it can be given via `/give`
|
||||
|
||||
This is admittedly rather more of a hassle than in the old days, but that's the price of abstraction. Research is underway for ways to improve this without spaghettifying the code again.
|
||||
|
||||
#### Change list
|
||||
- The following classes have been removed:
|
||||
- `BlockIdentifierFlattened`
|
||||
- `BlockLegacyIds`
|
||||
- `BlockLegacyMetadata`
|
||||
- `utils\ColorInMetadataTrait` - `utils\ColoredTrait` now implements colour type data serialization uniformly
|
||||
- `utils\InvalidBlockStateException` - this has been superseded by `pocketmine\data\runtime\InvalidSerializedRuntimeDataException`
|
||||
- `utils\NormalHorizontalFacingInMetadataTrait` - `utils\HorizontalFacingTrait` now implements facing type data serialization uniformly
|
||||
- `utils\PillarRotationInMetadataTrait` - `utils\PillarRotationTrait` now implements rotation type data serialization uniformly
|
||||
- `utils\BlockDataSerializer`
|
||||
- The following classes have been added:
|
||||
- `BaseFire`
|
||||
- `SoulFire`
|
||||
- `BlockTypeIds`
|
||||
- This is a generated enum of PocketMine-MP-specific block type IDs
|
||||
- There is one for every entry in `VanillaBlocks`
|
||||
- Do NOT save these IDs in a config or database, as they may change without warning
|
||||
- Block type IDs are intended for comparison purposes only
|
||||
- Block type IDs cannot be negative
|
||||
- `CopperOre`
|
||||
- `GoldOre`
|
||||
- `IronOre`
|
||||
- `Light`
|
||||
- `NetherGoldOre`
|
||||
- `utils\WallConnectionType` - enum of all possible wall connection types
|
||||
- `utils\WoodType` - enum of all possible wood types, used for wood material blocks like planks and logs
|
||||
- `utils\WoodTypeTrait`
|
||||
- The following API methods have been removed:
|
||||
- `Block->getId()` - for type comparisons, use `Block->getTypeId()` instead
|
||||
- `Block->getMeta()` - for state comparisons, use `Block->getStateId()` instead
|
||||
- `Block->readStateFromData()`
|
||||
- `Block->writeStateToMeta()`
|
||||
- `Block->writeStateToItemMeta()`
|
||||
- `Block->getStateBitmask()`
|
||||
- `BlockFactory->get()`
|
||||
- To get a block at runtime, e.g. stone, use `VanillaBlocks::STONE()`
|
||||
- To load a block from old config or database data:
|
||||
1. Use `GlobalBlockStateHandlers::getUpgrader()->upgradeIntIdMeta()` to convert it to modern data
|
||||
2. Pass the data to `GlobalBlockStateHandlers::getDeserializer()` to get a blockstate ID
|
||||
3. Pass the blockstate ID to `BlockFactory::fromStateId()` to get a `Block` instance
|
||||
- `BlockIdentifier->getBlockId()`
|
||||
- `BlockIdentifier->getAllBlockIds()`
|
||||
- `BlockIdentifier->getVariant()`
|
||||
- `BlockIdentifier->getItemId()`
|
||||
- `Door->isPowered()`
|
||||
- `Door->setPowered()`
|
||||
- `Skull->isNoDrops()`
|
||||
- `Skull->setNoDrops()`
|
||||
- `VanillaBlocks::*_GLAZED_TERRACOTTA()` - use `VanillaBlocks::GLAZED_TERRACOTTA()->setColor(DyeColor::WHATEVER())` instead
|
||||
- `utils\FallableTrait->getId()` is no longer required
|
||||
- `utils\FallableTrait->getMeta()` is no longer required
|
||||
- The following constants have been renamed:
|
||||
- `Block::INTERNAL_METADATA_BITS` -> `Block::INTERNAL_STATE_DATA_BITS`
|
||||
- `Block::INTERNAL_METADATA_MASK` -> `Block::INTERNAL_STATE_DATA_MASK`
|
||||
- The following API methods have been renamed:
|
||||
- `Block->getFullId()` -> `Block->getStateId()`
|
||||
- The following API methods have signature changes:
|
||||
- `BlockIdentifier->__construct()` now accepts `int $blockTypeId`, and no longer accepts `int $blockId, int $variant, ?int $itemId`
|
||||
- `ItemFrame->getFacing()` may now return `Facing::UP` and `Facing::DOWN`
|
||||
- `ItemFrame->setFacing()` now accepts `Facing::UP` and `Facing::DOWN`
|
||||
- The following API methods have been added:
|
||||
- `protected Block->decodeState()` - encodes the block's state properties, e.g. facing, powered/unpowered, etc.
|
||||
- `protected Block->decodeType()` - encodes the block's type properties, e.g. colour, wet/dry, coral type, etc.
|
||||
- `public Block->getRequiredStateDataBits()` - returns the number of bits required to encode the block's state data
|
||||
- `public Block->getRequiredTypeDataBits()` - returns the number of bits required to encode the block's type data
|
||||
- `public BlockIdentifier->getBlockTypeId()` - returns the block's type ID according to `BlockTypeIds`
|
||||
- `public GlazedTerracotta->getColor()` (from `ColoredTrait`) - this was previously unsupported due to legacy limitations
|
||||
- `public GlazedTerracotta->setColor()` (from `ColoredTrait`) - this was previously unsupported due to legacy limitations
|
||||
- `public Wall->getConnections()` - returns the wall's connections and their types (see `utils\WallConnectionType`)
|
||||
- `public Wall->setConnections()` - sets the wall's connections and their types (see `utils\WallConnectionType`)
|
||||
- `public Wall->getConnection()`
|
||||
- `public Wall->setConnection()`
|
||||
- `public Wall->isPost()`
|
||||
- `public Wall->setPost()`
|
||||
- `public Wood->isStripped()`
|
||||
- `public Wood->setStripped()`
|
||||
- The following classes now use new traits, adding API methods and/or properties:
|
||||
- `FenceGate` uses `utils\WoodTypeTrait`
|
||||
- `GlazedTerracotta` uses `utils\ColoredTrait`
|
||||
- `Planks` uses `utils\WoodTypeTrait`
|
||||
- `Wood` uses `utils\WoodTypeTrait`
|
||||
- `WoodenButton` uses `utils\WoodTypeTrait`
|
||||
- `WoodenDoor` uses `utils\WoodTypeTrait`
|
||||
- `WoodenFence` uses `utils\WoodTypeTrait`
|
||||
- `WoodenPressurePlate` uses `utils\WoodTypeTrait`
|
||||
- `WoodenSlab` uses `utils\WoodTypeTrait`
|
||||
- `WoodenStairs` uses `utils\WoodTypeTrait`
|
||||
- `WoodenTrapdoor` uses `utils\WoodTypeTrait`
|
||||
|
||||
### `pocketmine\crafting`
|
||||
- The following classes have been added:
|
||||
- `RecipeIngredient` interface
|
||||
- `ExactRecipeIngredient` - matches an exact item
|
||||
- `MetaWildcardRecipeIngredient` - matches an item with the given legacy Minecraft ID, but any metadata value
|
||||
- The following API methods have signature changes:
|
||||
- `FurnaceRecipe->__construct()` now accepts `RecipeIngredient` instead of `Item`
|
||||
- `FurnaceRecipe->getInput()` now returns `RecipeIngredient` instead of `Item`
|
||||
- `PotionContainerChangeRecipe->__construct()` now accepts `string, RecipeIngredient, string` (using Minecraft string IDs instead of legacy integers).
|
||||
- `PotionContainerChangeRecipe->getIngredient()` now returns `RecipeIngredient` instead of `Item`.
|
||||
- `PotionContainerChangeRecipe->getInputItemId()` now returns `string` (using Minecraft string IDs instead of legacy integers).
|
||||
- `PotionContainerChangeRecipe->getOutputItemId()` now returns `string` (using Minecraft string IDs instead of legacy integers).
|
||||
- `PotionTypeRecipe->__construct()` now accepts `RecipeIngredient` instead of `Item`
|
||||
- `PotionTypeRecipe->getIngredient()` now returns `RecipeIngredient` instead of `Item`
|
||||
- `PotionTypeRecipe->getInput()` now returns `RecipeIngredient` instead of `Item`
|
||||
- `ShapedRecipe->__construct()` now accepts `RecipeIngredient` instead of `Item`
|
||||
- `ShapedRecipe->getIngredient()` now returns `?RecipeIngredient` instead of `?Item`
|
||||
- `ShapedRecipe->getIngredientList()` now returns `RecipeIngredient[]` instead of `Item[]`
|
||||
- `ShapedRecipe->getIngredientMap()` now returns `RecipeIngredient[][]` instead of `Item[][]`
|
||||
- `ShapelessRecipe->__construct()` now accepts `RecipeIngredient` instead of `Item`
|
||||
- `ShapelessRecipe->getIngredientList()` now returns `RecipeIngredient[]` instead of `Item[]`
|
||||
|
||||
### `pocketmine\entity`
|
||||
- `Entity` now declares new abstract methods which must be implemented by subclasses:
|
||||
- `public Entity->getInitialDragMultiplier()`
|
||||
- `public Entity->getInitialGravity()`
|
||||
|
||||
### `pocketmine\item`
|
||||
#### Runtime item representation
|
||||
- Items no longer use internal Minecraft string IDs and metadata to identify themselves. All APIs associated with legacy IDs and/or meta have been removed.
|
||||
- A new set of runtime item IDs generated from `VanillaItems` is now used to identify item types. These IDs are defined in `ItemTypeIds`.
|
||||
- These new IDs are primarily intended for type comparison purposes.
|
||||
- Item type IDs are used at **runtime only**. They should **NOT** be stored in configs or databases, as they are not guaranteed to remain the same between versions.
|
||||
- In some cases, items may have additional "type data" which provides extra type information about an item. This replaces item metadata in some cases.
|
||||
- Type data may be used to store dynamic type information such as dye colour, potion type, etc.
|
||||
- Items must have the same type ID **and** type data in order to be stackable.
|
||||
- Blocks, when represented as items:
|
||||
- retain their block type data, but not state data (for example, different colours of concrete don't stack, but things like facing don't affect stackability)
|
||||
- use the negative of their block type ID (e.g. a block with type ID `1` will have an item type ID of `-1`).
|
||||
- Durable items (e.g. tools, armour) now use NBT `Damage` tag to store durability (like Minecraft 1.13+), instead of legacy meta values.
|
||||
|
||||
**Item type IDs and type data are intended for RUNTIME use only. The values of type IDs and/or type data may change without warning. They should NOT be saved in configs or databases.**
|
||||
|
||||
#### Implementing new items
|
||||
To register a new item, the following changes are now required:
|
||||
|
||||
- Add a new ID to `ItemTypeIds`
|
||||
- Register the item in `ItemFactory`
|
||||
- Amend `VanillaItems` to add the item
|
||||
- Amend `ItemDeserializer` to add a deserializer for loading the item from disk
|
||||
- Amend `ItemSerializer` to add a serializer for saving the item to disk
|
||||
- Optionally, amend `StringToItemParser` to add string alias(es) for the item, so it can be given via `/give`
|
||||
|
||||
Again, it's acknowledged this is rather more cumbersome than it should be, but this is an ongoing process.
|
||||
|
||||
#### Change list
|
||||
- `Item` is no longer `json_encode()`-able.
|
||||
- The original purpose of this was to allow items to be serialized to JSON for crafting data generated from `CraftingDataPacket`. Due to changes in the generation methodology, bypassing `Item`s entirely, this is no longer necessary.
|
||||
- `jsonSerialize()` requires the item to know about the method by which it will be serialized, creating a cyclic dependency between the `Item` implementation and its serialization method.
|
||||
- It's relatively easy to write a replacement method to encode items to JSON as you desire.
|
||||
- The following classes have been removed:
|
||||
- `ItemIds`
|
||||
- `Skull`
|
||||
- `Bed`
|
||||
- The following classes have been added:
|
||||
- `CoralFan`
|
||||
- `Spyglass`
|
||||
- The following API methods have been added:
|
||||
- `public Dye->setColor()`
|
||||
- `public ItemIdentifer->getTypeId()`
|
||||
- `public static ItemIdentifier::fromBlock()`
|
||||
- `public Potion->setType()`
|
||||
- `public SplashPotion->setType()`
|
||||
- The following API methods have been removed:
|
||||
- `Item->getId()` - for type comparisons, use `Item->getTypeId()` instead
|
||||
- `Item->getMeta()` - use the item's specific API methods to compare information such as colour, potion type etc.
|
||||
- `Item->hasAnyDamageValue()` - for meta wildcard recipe ingredients, use `pocketmine\crafting\MetaWildcardRecipeIngredient` instead
|
||||
- `ItemFactory->get()`
|
||||
- To get an item at runtime, e.g. iron ingot, use `VanillaItems::IRON_INGOT()`
|
||||
- To get a block as an item, e.g. stone, use `VanillaBlocks::STONE()->asItem()`
|
||||
- To load an item from legacy ID and meta:
|
||||
1. Use `GlobalItemDataHandlers::getUpgrader()->upgradeItemTypeDataInt()` to convert the legacy ID and meta to `ItemStackData`
|
||||
2. Pass the itemstack data to `GlobalItemDataHandlers::getDeserializer()` to get an `Item` instance
|
||||
- `ItemFactory->remap()`
|
||||
- `ItemIdentifier->getId()`
|
||||
- `ItemIdentifier->getMeta()`
|
||||
- The following API methods have been renamed:
|
||||
- `Item::jsonDeserialize()` -> `Item::legacyJsonDeserialize()`
|
||||
- `ItemFactory->getAllRegistered()` -> `ItemFactory->getAllKnownTypes()`
|
||||
- The following API methods have signature changes:
|
||||
- `ItemFactory->isRegistered()` no longer accepts a `$variant` parameter, and now expects an item type ID for the ID parameter
|
||||
- `ItemIdentifier->__construct()` no longer accepts a `$variant` parameter, and now expects an item type ID for the ID parameter
|
||||
- `LegacyStringToItemParser->addMapping()` now accepts a string for ID, instead of an integer
|
||||
|
||||
### `pocketmine\world`
|
||||
- The following classes have been added:
|
||||
- `pocketmine\world\format\io\GlobalBlockStateHandlers`
|
||||
- `pocketmine\world\format\io\GlobalItemDataHandlers`
|
||||
|
||||
# 5.0.0-ALPHA2
|
||||
Released 14th July 2022.
|
||||
|
||||
## Core
|
||||
- Reduced memory usage of the server on startup.
|
||||
- Fixed error spam when loading item frames without items in them.
|
||||
|
||||
## Gameplay
|
||||
### Blocks
|
||||
- Added the following new blocks:
|
||||
- Cakes with Candle & Dyed Candle
|
||||
- Candle & Dyed Candle
|
||||
- Cartography Table (not currently usable due to maps not being implemented)
|
||||
- Copper block (random oxidation not yet implemented)
|
||||
- Cut Copper block, stairs and slabs (random oxidation not yet implemented)
|
||||
- Crying Obsidian
|
||||
- Gilded Blackstone
|
||||
- Glow Item Frame
|
||||
- Hanging Roots
|
||||
- Lightning Rod
|
||||
- Netherite Block
|
||||
- Smithing Table
|
||||
- Tinted Glass
|
||||
- Warped Wart Block
|
||||
- Wither Rose
|
||||
|
||||
### Items
|
||||
- Added the following new items:
|
||||
- Honey Bottle
|
||||
- Netherite Axe
|
||||
- Netherite Boots
|
||||
- Netherite Chestplate
|
||||
- Netherite Helmet
|
||||
- Netherite Ingot
|
||||
- Netherite Leggings
|
||||
- Netherite Pickaxe
|
||||
- Netherite Scrap
|
||||
- Netherite Shovel
|
||||
- Netherite Sword
|
||||
|
||||
## API
|
||||
### `pocketmine\block`
|
||||
- Dependency between `BlockFactory` and `VanillaBlocks` has been inverted.
|
||||
- Now, blocks are defined in `VanillaBlocks`, and automatically registered in `BlockFactory`.
|
||||
- Manual registration in `BlockFactory` is still required for custom blocks.
|
||||
- `BlockFactory` now has only one purpose, which is to map internal blockstate IDs to `Block` objects when reading blocks from chunks.
|
||||
- The following new API methods have been added:
|
||||
- `public Block->isFireProofAsItem()`
|
||||
- `public Block->onProjectileHit()`
|
||||
- `public ItemFrame->isGlowing()`
|
||||
- `public ItemFrame->setGlowing()`
|
||||
- The following new classes have been added:
|
||||
- `BaseCake`
|
||||
- `CakeWithCandle`
|
||||
- `CakeWithDyedCandle`
|
||||
- `Candle`
|
||||
- `CartographyTable`
|
||||
- `CopperSlab`
|
||||
- `CopperStairs`
|
||||
- `Copper`
|
||||
- `DyedCandle`
|
||||
- `GildedBlackstone`
|
||||
- `HangingRoots`
|
||||
- `LightningRod`
|
||||
- `SmithingTable`
|
||||
- `WitherRose`
|
||||
- `utils\CandleTrait`
|
||||
- `utils\CopperOxidation`
|
||||
- `utils\CopperTrait`
|
||||
|
||||
### `pocketmine\crafting`
|
||||
- JSON models have been updated to reflect updated crafting data format.
|
||||
- The following enum classes have new members:
|
||||
- `ShapelessRecipeType` has new members `CARTOGRAPHY` and `SMITHING`
|
||||
|
||||
### `pocketmine\data`
|
||||
- `LegacyToStringBidirectionalIdMap` has been reduced to `LegacyToStringIdMap`.
|
||||
- Since we never map from string ID to legacy ID, bidirectional mapping is no longer necessary.
|
||||
- This affects the following subclasses:
|
||||
- `LegacyBiomeIdToStringIdMap`
|
||||
- `LegacyBlockIdToStringIdMap`
|
||||
- `LegacyEntityIdToStringIdMap`
|
||||
- `LegacyItemIdToStringIdMap`
|
||||
- The following internal API methods have been added:
|
||||
- `public LegacyToStringIdMap->add(string $string, int $legacy) : void` - adds a mapping from a custom legacy ID to custom string ID, needed for upgrading old saved data
|
||||
- `public LegacyBlockStateMapper->addMapping(string $stringId, int $intId, int $meta, BlockStateData $stateData) : void` - adds a mapping from legacy block data to a modern blockstate, needed for upgrading old saved data
|
||||
- `public BlockStateData->getState(string $name) : ?Tag`
|
||||
- The following internal API methods have signature changes:
|
||||
- `BlockStateData->__construct()` now accepts `array<string, Tag`> for `$states` instead of `CompoundTag`
|
||||
- `BlockStateData->getStates()` now returns `array<string, Tag>` instead of `CompoundTag` (allows reducing memory usage)
|
||||
- The following classes have been added:
|
||||
- `UnsupportedItemTypeException`
|
||||
|
||||
### `pocketmine\item`
|
||||
- `ItemFactory` has been removed.
|
||||
- Vanilla item registration is now done via `VanillaItems`.
|
||||
- The procedure for registering a custom item is the same as in ALPHA1, minus the `ItemFactory` step.
|
||||
- The following API methods have been added:
|
||||
- `public ArmorTypeInfo->getToughness() : int`
|
||||
- `public ArmorTypeInfo->isFireProof() : bool`
|
||||
- `public Item->isFireProof() : bool`
|
||||
- The following API methods have signature changes:
|
||||
- `ArmorTypeInfo->__construct()` now accepts optional parameters `int $toughness` and `bool $fireProof`
|
||||
- The following classes have been added:
|
||||
- `HoneyBottle`
|
||||
- The following enums have new members:
|
||||
- `ToolTier` has new member `NETHERITE`
|
||||
|
||||
### `pocketmine\world`
|
||||
- The following API methods have signature changes:
|
||||
- `SubChunk->__construct()` parameter `$blocks` has been renamed to `$blockLayers`.
|
||||
- The following classes have been added:
|
||||
- `CopperWaxApplySound`
|
||||
- `CopperWaxRemoveSound`
|
||||
|
||||
# 5.0.0-ALPHA3
|
||||
Released 14th August 2022.
|
||||
|
||||
## Core
|
||||
- Support for Bedrock 1.19.20.
|
||||
- Dropped support for Bedrock versions older than 1.19.20.
|
||||
- Improved performance of dropping block inventory contents when the block is destroyed.
|
||||
|
||||
## Fixes
|
||||
- Fixed errors when loading air itemstacks from PM4 worlds. These weren't supposed to exist (vanilla doesn't save them), but they were present in older PM worlds due to a bug in older versions.
|
||||
- Fixed server crash when discovering unknown blocks in non-leveldb worlds during conversion.
|
||||
- Fixed crimson / warped planks being usable as furnace fuel.
|
||||
|
||||
## Gameplay
|
||||
### Blocks
|
||||
- Added the following new blocks:
|
||||
- Cauldron
|
||||
- Chorus Flower
|
||||
- Chorus Plant
|
||||
- Froglight (pearlescent, verdant, ochre)
|
||||
- Mangrove Roots
|
||||
- Muddy Mangrove Roots
|
||||
- Rooted Dirt
|
||||
- Spore Blossom
|
||||
- Fixed lava setting entities on fire for an incorrect duration (Java vs Bedrock inconsistency).
|
||||
|
||||
### Items
|
||||
- Glass bottles can now be filled with water by clicking on a water source block.
|
||||
|
||||
## API
|
||||
### `pocketmine\block`
|
||||
#### Highlights
|
||||
- Introduced "type tags" concept, which allows marking certain blocks as having certain behaviours.
|
||||
- The idea for this system was borrowed from the Minecraft Java tags system.
|
||||
- It's still in very early concept stage, but is currently used for deciding which types of blocks plants can be placed on without needing to enumerate every single ID in every class, eliminating a bunch of boilerplate code and improving consistency.
|
||||
- All `Block` descendents now accept `BlockTypeInfo` in the constructor, instead of `BlockBreakInfo`.
|
||||
- This allows for future additions without needing to change dozens of overridden constructors.
|
||||
- Dynamic type and state property serialization now each use a single, unified method (`describeType` and `describeState` respectively) which accept `RuntimeDataReader|RuntimeDataWriter`, instead of separate decode/encode methods.
|
||||
- This simplifies implementing new blocks and avoids duplication of information.
|
||||
- `&$returnedItems` reference parameter is now used in some places to enable actions to return items to players without caring about whether they are in creative or anything else.
|
||||
- This eliminates boilerplate code of deciding whether to set the player's held item or not, as well as automatically dropping any overflow items that don't fit into the inventory.
|
||||
- This is currently used when filling/emptying cauldrons using buckets or glass bottles.
|
||||
- `BlockTypeIds` now exposes `newId()` static method to ease addition of custom blocks.
|
||||
|
||||
#### Changes
|
||||
- The following API methods have signature changes:
|
||||
- `Block->onInteract()` now accepts `array<Item> &$returnedItems` reference parameter.
|
||||
- `Block->onBreak()` now accepts `array<Item> &$returnedItems` reference parameter.
|
||||
- `Block->readStateFromWorld()` now returns `Block`.
|
||||
- This allows blocks to replace themselves with a different block entirely based on world conditions.
|
||||
- The following new classes have been added:
|
||||
- `BlockTypeInfo`
|
||||
- `BlockTypeTags`
|
||||
- The following new API methods have been added:
|
||||
- `protected Block->describeState(RuntimeDataReader|RuntimeDataWriter $w) : void` - describes to a runtime data reader/writer how to read/write the block's state properties
|
||||
- `protected Block->describeType(RuntimeDataReader|RuntimeDataWriter $w) : void` - describes to a runtime data reader/writer how to read/write the block's dynamic type properties
|
||||
- `public Block->getTypeTags() : array<string>`
|
||||
- `public Block->hasTypeTag(string $tag) : bool`
|
||||
- `public Spawnable->getRenderUpdateBugWorkaroundStateProperties(Block $block) : array<string, Tag>` - allows spawnable tiles to spoof block state properties to work around client-side rendering bugs without actually changing the block server-side
|
||||
- `public static BlockBreakInfo::axe(float $hardness, ?ToolTier $toolTier = null, ?float $blastResistance = null) : BlockBreakInfo`
|
||||
- `public static BlockBreakInfo::pickaxe(float $hardness, ?ToolTier $toolTier = null, ?float $blastResistance = null) : BlockBreakInfo`
|
||||
- `public static BlockBreakInfo::shovel(float $hardness, ?ToolTier $toolTier = null, ?float $blastResistance = null) : BlockBreakInfo`
|
||||
- `public static BlockBreakInfo::tier(float $hardness, int $toolType, ToolTier $toolTier, ?float $blastResistance = null) : BlockBreakInfo`
|
||||
- `public static BlockTypeIds::newId() : int` - returns a new dynamic block type ID for use by custom blocks
|
||||
|
||||
### `pocketmine\data`
|
||||
- The following classes have been renamed:
|
||||
- `LegacyBlockStateMapper` -> `BlockIdMetaUpgrader`
|
||||
- The following API methods have been added:
|
||||
- `public BlockDataUpgrader->getIdMetaUpgrader() : BlockIdMetaUpgrader`
|
||||
- `public BlockIdMetaUpgrader->addIdMetaToStateMapping(string $stringId, int $meta, BlockStateData $stateData) : void`
|
||||
- `public BlockIdMetaUpgrader->addIntIdToStringIdMapping(int $intId, string $stringId) : void`
|
||||
- The following API methods have been removed:
|
||||
- `BlockIdMetaUpgrader->addMapping()` - use `addIdMetaToStateMapping()` (and `addIntIdToStringIdMapping()` if necessary) instead
|
||||
- `LegacyToStringMap` no longer throws exceptions when adding the same mapping twice if the addition would have no effect.
|
||||
|
||||
### `pocketmine\item`
|
||||
#### Highlights
|
||||
- `&$returnedItems` reference parameter is now used in some places to enable actions to return items to players without caring about whether they are in creative or anything else.
|
||||
- This eliminates boilerplate code of deciding whether to set the player's held item or not, as well as automatically dropping any overflow items that don't fit into the inventory.
|
||||
- This is used for things like filling/emptying buckets and bottles, and equipping armor.
|
||||
|
||||
#### Changes
|
||||
- The following new API methods have been added:
|
||||
- `public Armor->clearCustomColor() : $this` - clears the custom color of an armor item
|
||||
- `public static ItemTypeIds::newId() : int` - returns a new dynamic item type ID for use by custom items
|
||||
- The following API methods have signature changes:
|
||||
- `Item->onAttackEntity()` now accepts `array<Item> &$returnedItems` reference parameter.
|
||||
- `Item->onClickAir()` now accepts `array<Item> &$returnedItems` reference parameter.
|
||||
- `Item->onDestroyBlock()` now accepts `array<Item> &$returnedItems` reference parameter.
|
||||
- `Item->onInteractBlock()` now accepts `array<Item> &$returnedItems` reference parameter.
|
||||
- `Item->onReleaseUsing()` now accepts `array<Item> &$returnedItems` reference parameter.
|
||||
|
||||
# 5.0.0-ALPHA4
|
||||
Released 24th September 2022.
|
||||
|
||||
## Core
|
||||
- Now targeting Minecraft: Bedrock 1.19.30.
|
||||
- All tests and static analysis are now being run on PHP 8.1 as well as PHP 8.0.
|
||||
- Silenced warning about Xdebug when it's loaded but disabled by `xdebug.mode` configuration.
|
||||
- A new `console.enable-input` option has been added to `pocketmine.yml`, which allows disabling the console reader in environments where it's not needed (e.g. a Docker container). This can be useful to save processor and memory resources.
|
||||
- Console reader polling is now done on the main thread. Since the console reader communication is now done via sockets, there's no longer any reason for it to have its own thread.
|
||||
- Crashdumps now include JIT mode information for use by the Crash Archive.
|
||||
- Improved handling of "UI" inventories in network `InventoryManager`. Their contents are now synced correctly.
|
||||
- Fixed cartography table recipes pretending to be smithing table recipes in `CraftingDataPacket`.
|
||||
- Fixed incorrect key being used for saving entity type IDs in save data.
|
||||
|
||||
## API
|
||||
### General
|
||||
- Plugin dependents are now always disabled before their dependencies on shutdown, to ensure that the dependents can finish what they are doing correctly.
|
||||
|
||||
### `pocketmine\block`
|
||||
- The following new API methods have been added:
|
||||
- `public SignText->isGlowing() : bool`
|
||||
- `public SignText->getBaseColor() : pocketmine\color\Color`
|
||||
- The following API methods have signature changes:
|
||||
- `SignText::fromBlob()` now accepts two new optional parameters: `?Color $baseColor` and `bool $glowing`
|
||||
- `SignText::__construct()` now accepts two new optional parameters: `?Color $baseColor` and `bool $glowing`
|
||||
- The following API methods have been removed:
|
||||
- `TreeType::fromMagicNumber()`
|
||||
- `TreeType->getMagicNumber()`
|
||||
|
||||
### `pocketmine\command`
|
||||
- Command permissions are now always checked by the server when running a command.
|
||||
- This only affects commands implemented by extending `Command`. Plugins using `PluginBase->onCommand()` are not affected by this change, since they already had permissions checked by the server anyway.
|
||||
- Previously, direct inheritors of `Command` were responsible for checking permissions, which required developers to duplicate the same code in every command, and opened lots of potential for security vulnerabilities.
|
||||
- If you want to do something on permission denied (e.g. sending a special message, or audit logging), you can do so by overriding `Command->testPermission()`, instead of baking the code directly into `Command->execute()`.
|
||||
- If you don't want to use permissions at all, just create a permission with a default of `true` (or belonging to `pocketmine.group.user`) and assign that.
|
||||
|
||||
### `pocketmine\data`
|
||||
#### Highlights
|
||||
- Introduced an experimental, mostly unified item (de)serializer registrar, `ItemSerializerDeserializerRegistrar`.
|
||||
- This class includes helper methods to register symmetric serializer and deserializer callbacks into an `ItemSerializer` and `ItemDeserializer`.
|
||||
- This halves the amount of code needed to register new items in the vast majority of cases.
|
||||
- This is currently used to register all currently implemented items.
|
||||
|
||||
#### Other changes
|
||||
- The following classes have been renamed:
|
||||
- `BlockObjectToBlockStateSerializer` -> `BlockObjectToStateSerializer`
|
||||
- `BlockStateToBlockObjectDeserializer` -> `BlockStateToObjectDeserializer`
|
||||
- The following classes have been removed:
|
||||
- `CachingBlockStateDeserializer`
|
||||
- `CachingBlockStateSerializer`
|
||||
- `DelegatingBlockStateDeserializer`
|
||||
- `DelegatingBlockStateSerializer`
|
||||
- The following new API methods have been added:
|
||||
- `public BlockStateToObjectDeserializer->mapSimple(string $stringId, \Closure() : Block $getBlock) : void` - for symmetry with the serializer
|
||||
|
||||
### `pocketmine\event`
|
||||
- `BlockFormEvent` now includes information about the block which caused the event.
|
||||
- Added `public BlockFormEvent->getCausingBlock() : Block`
|
||||
|
||||
### `pocketmine\inventory`
|
||||
- Introduced a new `TransactionBuilder` class, which considerably simplifies the process of constructing an `InventoryTransaction` from generic `setItem()` calls.
|
||||
- This is currently used to build server-side transactions for evicting the contents of the crafting grid when closing the main inventory.
|
||||
- This is planned for use with the new Minecraft Bedrock item stack request system.
|
||||
- Improved PHPStan type information available for `Inventory` and `BaseInventory`.
|
||||
|
||||
### `pocketmine\item`
|
||||
- The following API methods have been changed:
|
||||
- `Item->encodeType(RuntimeDataWriter $w) : void` -> `Item->describeType(RuntimeDataReader|RuntimeDataWriter $w) : void`
|
||||
- The following new classes have been added:
|
||||
- `SuspiciousStew`
|
||||
- `SuspiciousStewType`
|
||||
|
||||
### `pocketmine\utils`
|
||||
- The following new API methods have been added:
|
||||
- `public static Utils::getOpcacheJitMode() : int`
|
||||
|
||||
### `pocketmine\world`
|
||||
- The following new classes have been added:
|
||||
- `sound\DyeUseSound`
|
||||
- `sound\InkSacUseSound`
|
||||
- The following API methods have changed signatures:
|
||||
- `GlobalBlockStateHandlers::getSerializer()` now returns `BlockObjectToStateSerializer` directly instead of `BlockStateSerializer`.
|
||||
- `GlobalBlockStateHandlers::getDeserializer()` now returns `BlockStateToObjectDeserializer` directly instead of `BlockStateDeserializer`.
|
||||
|
||||
## Gameplay
|
||||
### General
|
||||
- Spectator players are no longer able to acquire blocks by block picking that they don't already have in their inventories. The behaviour is now the same as survival mode.
|
||||
|
||||
### Blocks
|
||||
- Coral and coral fans now behave correctly when placed out of water (they no longer immediately die).
|
||||
- Added support for dyeing sign text and making it glow.
|
||||
- Fixed dead bush being able to be placed on some invalid blocks (e.g. stone).
|
||||
- TNT can now be ignited by fire charges.
|
||||
- Vines can now only be placed on the side of full-cube blocks.
|
||||
- Fixed sugarcane not being able to be placed on some blocks.
|
||||
|
||||
### Items
|
||||
- Added the following new items:
|
||||
- Fire Charge
|
||||
- Suspicious Stew
|
||||
|
||||
### Effects
|
||||
- Updated damage modifier amounts for Instant Damage to be more in line with vanilla.
|
||||
- Updated duration modifier amounts for Regeneration to be more like vanilla.
|
||||
|
||||
# 5.0.0-ALPHA5
|
||||
Released 13th November 2022.
|
||||
|
||||
**This release includes changes from [4.11.0-BETA2](https://github.com/pmmp/PocketMine-MP/releases/4.11.0-BETA2) and earlier, which may not be listed here.**
|
||||
|
||||
## General
|
||||
- Added support for Minecraft: Bedrock 1.19.40.
|
||||
- Removed support for earlier versions.
|
||||
|
||||
## API
|
||||
### `pocketmine\block`
|
||||
- `FallableTrait` now includes a default implementation of `tickFalling()`.
|
||||
|
||||
### `pocketmine\event`
|
||||
- The following API methods have been removed:
|
||||
- `PlayerCommandPreprocessEvent`
|
||||
- The following API methods have been added:
|
||||
- `public DataPacketSendEvent->setPackets(list<ClientboundPacket> $packets) : void`
|
||||
|
||||
## Gameplay
|
||||
### General
|
||||
- Fixed dyeing leather armour in cauldrons.
|
||||
|
||||
### Blocks
|
||||
- Copper blocks now play the correct scrape sound when using an axe on them.
|
||||
|
||||
## Internals
|
||||
- Moved command timings to `Timings`.
|
||||
|
||||
# 5.0.0-ALPHA6
|
||||
Released 19th December 2022.
|
||||
|
||||
**This release includes changes from the following releases, which may not be mentioned:**
|
||||
- [4.10.2](https://github.com/pmmp/PocketMine-MP/releases/tag/4.10.2)
|
||||
- [4.11.0](https://github.com/pmmp/PocketMine-MP/releases/tag/4.11.0)
|
||||
- [4.12.0](https://github.com/pmmp/PocketMine-MP/releases/tag/4.12.0)
|
||||
- [4.12.1](https://github.com/pmmp/PocketMine-MP/releases/tag/4.12.1)
|
||||
- [4.12.2](https://github.com/pmmp/PocketMine-MP/releases/tag/4.12.2)
|
||||
|
||||
## General
|
||||
- Fixed the Bedrock client asking to upgrade worlds exported from PocketMine-MP to Bedrock (missing level.dat fields).
|
||||
- Added support for 1.19.40 and newer Bedrock worlds.
|
||||
- Commands are now enabled by default in worlds exported from PocketMine-MP to Bedrock.
|
||||
|
||||
## Gameplay
|
||||
### Blocks
|
||||
- Added the following new blocks:
|
||||
- Twisting Vines
|
||||
- Weeping Vines
|
||||
- Anvils are now damaged when they hit the ground after falling.
|
||||
- Added missing sounds for anvils hitting the ground after falling.
|
||||
- Fixed missing sounds when a projectile strikes an amethyst block.
|
||||
- Fixed some blocks being incorrectly able to be placed on top of a candle cake.
|
||||
|
||||
### Items
|
||||
- Added the following new items:
|
||||
- Music Disc (5)
|
||||
- Music Disc (Otherside)
|
||||
- Music Disc (Pigstep)
|
||||
- Implemented Swift Sneak enchantment.
|
||||
- Armour durability is now only reduced when the wearer receives a type of damage that the armour can protect against.
|
||||
|
||||
## API
|
||||
### General
|
||||
- Union and mixed native parameter, return and property types are now used where appropriate.
|
||||
|
||||
### `pocketmine\block`
|
||||
- The following new API methods have been added:
|
||||
- `public Furnace->getType() : utils\FurnaceType`
|
||||
- The following interfaces have new requirements:
|
||||
- `utils\Fallable` now requires `onHitGround()` to be implemented (although filled by default implementation in `FallableTrait`).
|
||||
- `utils\Fallable` now requires `getLandSound()` to be implemented (although filled by default implementation in `FallableTrait`).
|
||||
- The following new API constants have been added:
|
||||
- `public BlockTypeTags::FIRE` - used by fire and soul fire
|
||||
|
||||
### `pocketmine\crafting`
|
||||
- The `$type` parameter of `ShapelessRecipe->__construct()` is now mandatory.
|
||||
|
||||
### `pocketmine\entity`
|
||||
- The following new API methods have been added:
|
||||
- `public Living->getDisplayName() : string`
|
||||
- The following API methods have changed signatures:
|
||||
- `EntityFactory->register()` no longer accepts a `$legacyMcpeSaveId` parameter (now handled by internal conversions instead).
|
||||
|
||||
### `pocketmine\event`
|
||||
- The following classes have been renamed:
|
||||
- `entity\ExplosionPrimeEvent` -> `entity\EntityPreExplodeEvent`
|
||||
- The following new classes have been added:
|
||||
- `world\WorldParticleEvent` - called when a particle is spawned in a world
|
||||
- `world\WorldSoundEvent` - called when a sound is played in a world
|
||||
- The following API methods have changed signatures:
|
||||
- `entity\EntityPreExplodeEvent->__construct()` has the `$force` parameter renamed to `$radius`
|
||||
- `entity\EntityPreExplodeEvent->getForce() : float` -> `entity\EntityPreExplodeEvent->getRadius() : float`
|
||||
- `entity\EntityPreExplodeEvent->setForce(float $force) : void` -> `entity\EntityPreExplodeEvent->setRadius(float $radius) : void`
|
||||
|
||||
### `pocketmine\item`
|
||||
- The following new API methods have been added:
|
||||
- `public Item->keepOnDeath() : bool` - returns whether this item will be retained when a player carrying it dies
|
||||
- `public Item->onInteractEntity(Player $player, Entity $entity, Vector3 $clickPos) : bool` - called when a player interacts with an entity with this item in their hand
|
||||
- `public Item->setKeepOnDeath(bool $keepOnDeath) : void` - sets whether this item will be retained when a player carrying it dies
|
||||
- `public StringToItemParser->lookupAliases(Item $item) : list<string>` - returns a list of all registered aliases for the given item
|
||||
- `public StringToItemParser->lookupBlockAliases(Block $block) : list<string>` - returns a list of all registered aliases for the given block
|
||||
|
||||
### `pocketmine\resourcepacks`
|
||||
- The following new API methods have been added:
|
||||
- `public ResourcePackManager->setPackEncryptionKey(string $id, ?string $key) : void` - sets the encryption key to be used for the resource pack identified by the given UUID
|
||||
- `public ResourcePackManager->setResourceStack(list<ResourcePack> $resourceStack) : void` - sets the resource stack to be used by the server
|
||||
|
||||
### `pocketmine\world`
|
||||
- The following API methods have changed signatures:
|
||||
- `Explosion->__construct()` has the `$size` parameter renamed to `$radius`
|
||||
- The following public properties have been renamed:
|
||||
- `Explosion->size` -> `Explosion->radius`
|
||||
|
||||
## Internals
|
||||
- `EntityLegacyIds` has been removed. Legacy entity IDs found during world loading are now converted via `LegacyEntityIdToStringIdMap`.
|
||||
- All usages of NBT keys now use class constants instead of hardcoded strings (except for an occasional overlooked one).
|
||||
- All members of `BlockTypeTags` now have a `pocketmine:` prefix on the value. This does not affect constant usages.
|
@ -34,16 +34,14 @@
|
||||
"adhocore/json-comment": "^1.1",
|
||||
"fgrosse/phpasn1": "^2.3",
|
||||
"netresearch/jsonmapper": "^4.0",
|
||||
"pocketmine/bedrock-block-upgrade-schema": "dev-master@dev",
|
||||
"pocketmine/bedrock-data": "dev-modern-world-support@dev",
|
||||
"pocketmine/bedrock-item-upgrade-schema": "dev-master",
|
||||
"pocketmine/bedrock-protocol": "~17.1.0+bedrock-1.19.50",
|
||||
"pocketmine/bedrock-data": "~1.13.0+bedrock-1.19.50",
|
||||
"pocketmine/bedrock-protocol": "~18.1.0+bedrock-1.19.50",
|
||||
"pocketmine/binaryutils": "^0.2.1",
|
||||
"pocketmine/callback-validator": "^1.0.2",
|
||||
"pocketmine/classloader": "^0.2.0",
|
||||
"pocketmine/color": "^0.2.0",
|
||||
"pocketmine/color": "^0.3.0",
|
||||
"pocketmine/errorhandler": "^0.6.0",
|
||||
"pocketmine/locale-data": "~2.11.0",
|
||||
"pocketmine/locale-data": "~2.18.0",
|
||||
"pocketmine/log": "^0.4.0",
|
||||
"pocketmine/log-pthreads": "^0.4.0",
|
||||
"pocketmine/math": "^0.4.0",
|
||||
@ -52,10 +50,11 @@
|
||||
"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.4",
|
||||
"phpstan/phpstan": "1.9.14",
|
||||
"phpstan/phpstan-phpunit": "^1.1.0",
|
||||
"phpstan/phpstan-strict-rules": "^1.2.0",
|
||||
"phpunit/phpunit": "^9.2"
|
||||
|
404
composer.lock
generated
404
composer.lock
generated
@ -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": "2d4da4bb4787764fbe706a04311c3cbf",
|
||||
"content-hash": "2c0f273b515174abfdcef4fc4ad3c262",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/json-comment",
|
||||
@ -248,45 +248,18 @@
|
||||
},
|
||||
"time": "2022-12-08T20:46:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-block-upgrade-schema",
|
||||
"version": "dev-master",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BedrockBlockUpgradeSchema.git",
|
||||
"reference": "63f5f5e02e952ffa196a4c0671d7fcf8b8cdd9a4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockBlockUpgradeSchema/zipball/63f5f5e02e952ffa196a4c0671d7fcf8b8cdd9a4",
|
||||
"reference": "63f5f5e02e952ffa196a4c0671d7fcf8b8cdd9a4",
|
||||
"shasum": ""
|
||||
},
|
||||
"default-branch": true,
|
||||
"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/master"
|
||||
},
|
||||
"time": "2022-08-07T19:29:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-data",
|
||||
"version": "dev-modern-world-support",
|
||||
"version": "1.13.0+bedrock-1.19.50",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BedrockData.git",
|
||||
"reference": "d64617faab77300d828debcd1e3597b3403b63b7"
|
||||
"reference": "57337ddc9433a0e245a1ce48c51af05f0573d58d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/d64617faab77300d828debcd1e3597b3403b63b7",
|
||||
"reference": "d64617faab77300d828debcd1e3597b3403b63b7",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/57337ddc9433a0e245a1ce48c51af05f0573d58d",
|
||||
"reference": "57337ddc9433a0e245a1ce48c51af05f0573d58d",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
@ -297,49 +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.50"
|
||||
},
|
||||
"time": "2022-12-02T13:01:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-item-upgrade-schema",
|
||||
"version": "dev-master",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BedrockItemUpgradeSchema.git",
|
||||
"reference": "d984d2ee7283bc52e8733e7c7da1d0f6b6dc501f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockItemUpgradeSchema/zipball/d984d2ee7283bc52e8733e7c7da1d0f6b6dc501f",
|
||||
"reference": "d984d2ee7283bc52e8733e7c7da1d0f6b6dc501f",
|
||||
"shasum": ""
|
||||
},
|
||||
"default-branch": true,
|
||||
"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/master"
|
||||
},
|
||||
"time": "2022-06-08T13:47:48+00:00"
|
||||
"time": "2022-11-30T16:19:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-protocol",
|
||||
"version": "17.1.0+bedrock-1.19.50",
|
||||
"version": "18.1.0+bedrock-1.19.50",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BedrockProtocol.git",
|
||||
"reference": "c572706cf5e3202718dd35a35dd30fe08cd671de"
|
||||
"reference": "c34f22847a1cc362a3f1c45698576d30d1e8392f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/c572706cf5e3202718dd35a35dd30fe08cd671de",
|
||||
"reference": "c572706cf5e3202718dd35a35dd30fe08cd671de",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/c34f22847a1cc362a3f1c45698576d30d1e8392f",
|
||||
"reference": "c34f22847a1cc362a3f1c45698576d30d1e8392f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -347,13 +293,13 @@
|
||||
"netresearch/jsonmapper": "^4.0",
|
||||
"php": "^8.0",
|
||||
"pocketmine/binaryutils": "^0.2.0",
|
||||
"pocketmine/color": "^0.2.0",
|
||||
"pocketmine/color": "^0.2.0 || ^0.3.0",
|
||||
"pocketmine/math": "^0.3.0 || ^0.4.0",
|
||||
"pocketmine/nbt": "^0.3.0",
|
||||
"ramsey/uuid": "^4.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "1.9.3",
|
||||
"phpstan/phpstan": "1.9.13",
|
||||
"phpstan/phpstan-phpunit": "^1.0.0",
|
||||
"phpstan/phpstan-strict-rules": "^1.0.0",
|
||||
"phpunit/phpunit": "^9.5"
|
||||
@ -371,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/17.1.0+bedrock-1.19.50"
|
||||
"source": "https://github.com/pmmp/BedrockProtocol/tree/18.1.0+bedrock-1.19.50"
|
||||
},
|
||||
"time": "2022-12-15T20:34:49+00:00"
|
||||
"time": "2023-01-20T12:35:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/binaryutils",
|
||||
@ -514,24 +460,24 @@
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/color",
|
||||
"version": "0.2.0",
|
||||
"version": "0.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/Color.git",
|
||||
"reference": "09be6ea6d76f2e33d6813c39d29c22c46c17e1d2"
|
||||
"reference": "8cb346d0a21ad3287cc8d7175e4b643416607249"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/Color/zipball/09be6ea6d76f2e33d6813c39d29c22c46c17e1d2",
|
||||
"reference": "09be6ea6d76f2e33d6813c39d29c22c46c17e1d2",
|
||||
"url": "https://api.github.com/repos/pmmp/Color/zipball/8cb346d0a21ad3287cc8d7175e4b643416607249",
|
||||
"reference": "8cb346d0a21ad3287cc8d7175e4b643416607249",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0"
|
||||
"php": "^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "0.12.59",
|
||||
"phpstan/phpstan-strict-rules": "^0.12.2"
|
||||
"phpstan/phpstan": "1.9.4",
|
||||
"phpstan/phpstan-strict-rules": "^1.2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
@ -546,9 +492,9 @@
|
||||
"description": "Color handling library used by PocketMine-MP and related projects",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/Color/issues",
|
||||
"source": "https://github.com/pmmp/Color/tree/0.2.0"
|
||||
"source": "https://github.com/pmmp/Color/tree/0.3.0"
|
||||
},
|
||||
"time": "2020-12-11T01:24:32+00:00"
|
||||
"time": "2022-12-18T19:49:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/errorhandler",
|
||||
@ -591,16 +537,16 @@
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/locale-data",
|
||||
"version": "2.11.0",
|
||||
"version": "2.18.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/Language.git",
|
||||
"reference": "4b33d8fa53eda53d9662a7478806ebae2e4a5c53"
|
||||
"reference": "da25bfe9ee4822a84feb9b7e620c56ad4000aed0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/Language/zipball/4b33d8fa53eda53d9662a7478806ebae2e4a5c53",
|
||||
"reference": "4b33d8fa53eda53d9662a7478806ebae2e4a5c53",
|
||||
"url": "https://api.github.com/repos/pmmp/Language/zipball/da25bfe9ee4822a84feb9b7e620c56ad4000aed0",
|
||||
"reference": "da25bfe9ee4822a84feb9b7e620c56ad4000aed0",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
@ -608,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.11.0"
|
||||
"source": "https://github.com/pmmp/Language/tree/2.18.3"
|
||||
},
|
||||
"time": "2022-11-25T14:24:34+00:00"
|
||||
"time": "2023-01-17T21:43:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/log",
|
||||
@ -906,42 +852,53 @@
|
||||
},
|
||||
{
|
||||
"name": "ramsey/collection",
|
||||
"version": "1.2.2",
|
||||
"version": "1.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ramsey/collection.git",
|
||||
"reference": "cccc74ee5e328031b15640b51056ee8d3bb66c0a"
|
||||
"reference": "ad7475d1c9e70b190ecffc58f2d989416af339b4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ramsey/collection/zipball/cccc74ee5e328031b15640b51056ee8d3bb66c0a",
|
||||
"reference": "cccc74ee5e328031b15640b51056ee8d3bb66c0a",
|
||||
"url": "https://api.github.com/repos/ramsey/collection/zipball/ad7475d1c9e70b190ecffc58f2d989416af339b4",
|
||||
"reference": "ad7475d1c9e70b190ecffc58f2d989416af339b4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.3 || ^8",
|
||||
"php": "^7.4 || ^8.0",
|
||||
"symfony/polyfill-php81": "^1.23"
|
||||
},
|
||||
"require-dev": {
|
||||
"captainhook/captainhook": "^5.3",
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
|
||||
"ergebnis/composer-normalize": "^2.6",
|
||||
"fakerphp/faker": "^1.5",
|
||||
"hamcrest/hamcrest-php": "^2",
|
||||
"jangregor/phpstan-prophecy": "^0.8",
|
||||
"mockery/mockery": "^1.3",
|
||||
"captainhook/plugin-composer": "^5.3",
|
||||
"ergebnis/composer-normalize": "^2.28.3",
|
||||
"fakerphp/faker": "^1.21",
|
||||
"hamcrest/hamcrest-php": "^2.0",
|
||||
"jangregor/phpstan-prophecy": "^1.0",
|
||||
"mockery/mockery": "^1.5",
|
||||
"php-parallel-lint/php-console-highlighter": "^1.0",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.3",
|
||||
"phpcsstandards/phpcsutils": "^1.0.0-rc1",
|
||||
"phpspec/prophecy-phpunit": "^2.0",
|
||||
"phpstan/extension-installer": "^1",
|
||||
"phpstan/phpstan": "^0.12.32",
|
||||
"phpstan/phpstan-mockery": "^0.12.5",
|
||||
"phpstan/phpstan-phpunit": "^0.12.11",
|
||||
"phpunit/phpunit": "^8.5 || ^9",
|
||||
"psy/psysh": "^0.10.4",
|
||||
"slevomat/coding-standard": "^6.3",
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
"vimeo/psalm": "^4.4"
|
||||
"phpstan/extension-installer": "^1.2",
|
||||
"phpstan/phpstan": "^1.9",
|
||||
"phpstan/phpstan-mockery": "^1.1",
|
||||
"phpstan/phpstan-phpunit": "^1.3",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"psalm/plugin-mockery": "^1.1",
|
||||
"psalm/plugin-phpunit": "^0.18.4",
|
||||
"ramsey/coding-standard": "^2.0.3",
|
||||
"ramsey/conventional-commits": "^1.3",
|
||||
"vimeo/psalm": "^5.4"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"captainhook": {
|
||||
"force-install": true
|
||||
},
|
||||
"ramsey/conventional-commits": {
|
||||
"configFile": "conventional-commits.json"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Ramsey\\Collection\\": "src/"
|
||||
@ -969,7 +926,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/ramsey/collection/issues",
|
||||
"source": "https://github.com/ramsey/collection/tree/1.2.2"
|
||||
"source": "https://github.com/ramsey/collection/tree/1.3.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -981,27 +938,27 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-10-10T03:01:02+00:00"
|
||||
"time": "2022-12-27T19:12:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ramsey/uuid",
|
||||
"version": "4.6.0",
|
||||
"version": "4.7.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ramsey/uuid.git",
|
||||
"reference": "ad63bc700e7d021039e30ce464eba384c4a1d40f"
|
||||
"reference": "433b2014e3979047db08a17a205f410ba3869cf2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ramsey/uuid/zipball/ad63bc700e7d021039e30ce464eba384c4a1d40f",
|
||||
"reference": "ad63bc700e7d021039e30ce464eba384c4a1d40f",
|
||||
"url": "https://api.github.com/repos/ramsey/uuid/zipball/433b2014e3979047db08a17a205f410ba3869cf2",
|
||||
"reference": "433b2014e3979047db08a17a205f410ba3869cf2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"brick/math": "^0.8.8 || ^0.9 || ^0.10",
|
||||
"ext-json": "*",
|
||||
"php": "^8.0",
|
||||
"ramsey/collection": "^1.0"
|
||||
"ramsey/collection": "^1.2 || ^2.0"
|
||||
},
|
||||
"replace": {
|
||||
"rhumsaa/uuid": "self.version"
|
||||
@ -1061,7 +1018,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/ramsey/uuid/issues",
|
||||
"source": "https://github.com/ramsey/uuid/tree/4.6.0"
|
||||
"source": "https://github.com/ramsey/uuid/tree/4.7.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1073,20 +1030,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-11-05T23:03:38+00:00"
|
||||
"time": "2023-01-12T18:13:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
"version": "v5.4.13",
|
||||
"version": "v5.4.19",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/filesystem.git",
|
||||
"reference": "ac09569844a9109a5966b9438fc29113ce77cf51"
|
||||
"reference": "648bfaca6a494f3e22378123bcee2894045dc9d8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/ac09569844a9109a5966b9438fc29113ce77cf51",
|
||||
"reference": "ac09569844a9109a5966b9438fc29113ce77cf51",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/648bfaca6a494f3e22378123bcee2894045dc9d8",
|
||||
"reference": "648bfaca6a494f3e22378123bcee2894045dc9d8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1121,7 +1078,7 @@
|
||||
"description": "Provides basic utilities for the filesystem",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/filesystem/tree/v5.4.13"
|
||||
"source": "https://github.com/symfony/filesystem/tree/v5.4.19"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1137,7 +1094,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-09-21T19:53:16+00:00"
|
||||
"time": "2023-01-14T19:14:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
@ -1465,35 +1422,144 @@
|
||||
}
|
||||
],
|
||||
"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": [
|
||||
{
|
||||
"name": "doctrine/instantiator",
|
||||
"version": "1.4.1",
|
||||
"version": "1.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/instantiator.git",
|
||||
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc"
|
||||
"reference": "0a0fa9780f5d4e507415a065172d26a98d02047b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc",
|
||||
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc",
|
||||
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b",
|
||||
"reference": "0a0fa9780f5d4e507415a065172d26a98d02047b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^9",
|
||||
"doctrine/coding-standard": "^9 || ^11",
|
||||
"ext-pdo": "*",
|
||||
"ext-phar": "*",
|
||||
"phpbench/phpbench": "^0.16 || ^1",
|
||||
"phpstan/phpstan": "^1.4",
|
||||
"phpstan/phpstan-phpunit": "^1",
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
|
||||
"vimeo/psalm": "^4.22"
|
||||
"vimeo/psalm": "^4.30 || ^5.4"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
@ -1520,7 +1586,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/doctrine/instantiator/issues",
|
||||
"source": "https://github.com/doctrine/instantiator/tree/1.4.1"
|
||||
"source": "https://github.com/doctrine/instantiator/tree/1.5.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1536,7 +1602,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-03T08:28:38+00:00"
|
||||
"time": "2022-12-30T00:15:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "myclabs/deep-copy",
|
||||
@ -1599,16 +1665,16 @@
|
||||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
"version": "v4.15.2",
|
||||
"version": "v4.15.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nikic/PHP-Parser.git",
|
||||
"reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc"
|
||||
"reference": "570e980a201d8ed0236b0a62ddf2c9cbb2034039"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc",
|
||||
"reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/570e980a201d8ed0236b0a62ddf2c9cbb2034039",
|
||||
"reference": "570e980a201d8ed0236b0a62ddf2c9cbb2034039",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1649,9 +1715,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nikic/PHP-Parser/issues",
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.2"
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.3"
|
||||
},
|
||||
"time": "2022-11-12T15:38:23+00:00"
|
||||
"time": "2023-01-16T22:05:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phar-io/manifest",
|
||||
@ -1766,16 +1832,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "1.9.4",
|
||||
"version": "1.9.14",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "d03bccee595e2146b7c9d174486b84f4dc61b0f2"
|
||||
"reference": "e5fcc96289cf737304286a9b505fbed091f02e58"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/d03bccee595e2146b7c9d174486b84f4dc61b0f2",
|
||||
"reference": "d03bccee595e2146b7c9d174486b84f4dc61b0f2",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/e5fcc96289cf737304286a9b505fbed091f02e58",
|
||||
"reference": "e5fcc96289cf737304286a9b505fbed091f02e58",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1805,7 +1871,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/phpstan/issues",
|
||||
"source": "https://github.com/phpstan/phpstan/tree/1.9.4"
|
||||
"source": "https://github.com/phpstan/phpstan/tree/1.9.14"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1821,20 +1887,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-12-17T13:33:52+00:00"
|
||||
"time": "2023-01-19T10:47:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-phpunit",
|
||||
"version": "1.3.2",
|
||||
"version": "1.3.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan-phpunit.git",
|
||||
"reference": "cd9c6938f8bbfcb6da3ed5a3c7ea60873825d088"
|
||||
"reference": "54a24bd23e9e80ee918cdc24f909d376c2e273f7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/cd9c6938f8bbfcb6da3ed5a3c7ea60873825d088",
|
||||
"reference": "cd9c6938f8bbfcb6da3ed5a3c7ea60873825d088",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/54a24bd23e9e80ee918cdc24f909d376c2e273f7",
|
||||
"reference": "54a24bd23e9e80ee918cdc24f909d376c2e273f7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1871,27 +1937,27 @@
|
||||
"description": "PHPUnit extensions and rules for PHPStan",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/phpstan-phpunit/issues",
|
||||
"source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.2"
|
||||
"source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.3"
|
||||
},
|
||||
"time": "2022-12-13T15:08:22+00:00"
|
||||
"time": "2022-12-21T15:25:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-strict-rules",
|
||||
"version": "1.4.4",
|
||||
"version": "1.4.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan-strict-rules.git",
|
||||
"reference": "23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6"
|
||||
"reference": "361f75b06066f3fdaba87c1f57bdb1ffc28d6f1d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6",
|
||||
"reference": "23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/361f75b06066f3fdaba87c1f57bdb1ffc28d6f1d",
|
||||
"reference": "361f75b06066f3fdaba87c1f57bdb1ffc28d6f1d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0",
|
||||
"phpstan/phpstan": "^1.8.6"
|
||||
"phpstan/phpstan": "^1.9.7"
|
||||
},
|
||||
"require-dev": {
|
||||
"nikic/php-parser": "^4.13.0",
|
||||
@ -1919,22 +1985,22 @@
|
||||
"description": "Extra strict and opinionated rules for PHPStan",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/phpstan-strict-rules/issues",
|
||||
"source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.4.4"
|
||||
"source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.4.5"
|
||||
},
|
||||
"time": "2022-09-21T11:38:17+00:00"
|
||||
"time": "2023-01-11T14:16:29+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
"version": "9.2.22",
|
||||
"version": "9.2.24",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
||||
"reference": "e4bf60d2220b4baaa0572986b5d69870226b06df"
|
||||
"reference": "2cf940ebc6355a9d430462811b5aaa308b174bed"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/e4bf60d2220b4baaa0572986b5d69870226b06df",
|
||||
"reference": "e4bf60d2220b4baaa0572986b5d69870226b06df",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2cf940ebc6355a9d430462811b5aaa308b174bed",
|
||||
"reference": "2cf940ebc6355a9d430462811b5aaa308b174bed",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1990,7 +2056,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.22"
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.24"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1998,7 +2064,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-12-18T16:40:55+00:00"
|
||||
"time": "2023-01-26T08:26:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-file-iterator",
|
||||
@ -2243,20 +2309,20 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "9.5.27",
|
||||
"version": "9.5.28",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "a2bc7ffdca99f92d959b3f2270529334030bba38"
|
||||
"reference": "954ca3113a03bf780d22f07bf055d883ee04b65e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a2bc7ffdca99f92d959b3f2270529334030bba38",
|
||||
"reference": "a2bc7ffdca99f92d959b3f2270529334030bba38",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/954ca3113a03bf780d22f07bf055d883ee04b65e",
|
||||
"reference": "954ca3113a03bf780d22f07bf055d883ee04b65e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/instantiator": "^1.3.1",
|
||||
"doctrine/instantiator": "^1.3.1 || ^2",
|
||||
"ext-dom": "*",
|
||||
"ext-json": "*",
|
||||
"ext-libxml": "*",
|
||||
@ -2325,7 +2391,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.27"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.28"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -2341,7 +2407,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-12-09T07:31:23+00:00"
|
||||
"time": "2023-01-14T12:32:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/cli-parser",
|
||||
@ -3360,11 +3426,7 @@
|
||||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": {
|
||||
"pocketmine/bedrock-block-upgrade-schema": 20,
|
||||
"pocketmine/bedrock-data": 20,
|
||||
"pocketmine/bedrock-item-upgrade-schema": 20
|
||||
},
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
|
@ -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
@ -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');
|
||||
|
@ -69,6 +69,10 @@ use const JSON_UNESCAPED_SLASHES;
|
||||
use const SORT_NUMERIC;
|
||||
|
||||
class MemoryManager{
|
||||
private const DEFAULT_CHECK_RATE = Server::TARGET_TICKS_PER_SECOND;
|
||||
private const DEFAULT_CONTINUOUS_TRIGGER_RATE = Server::TARGET_TICKS_PER_SECOND * 2;
|
||||
private const DEFAULT_TICKS_PER_GC = 30 * 60 * Server::TARGET_TICKS_PER_SECOND;
|
||||
|
||||
private int $memoryLimit;
|
||||
private int $globalMemoryLimit;
|
||||
private int $checkRate;
|
||||
@ -113,20 +117,12 @@ class MemoryManager{
|
||||
if($m <= 0){
|
||||
$defaultMemory = 0;
|
||||
}else{
|
||||
switch(mb_strtoupper($matches[2])){
|
||||
case "K":
|
||||
$defaultMemory = intdiv($m, 1024);
|
||||
break;
|
||||
case "M":
|
||||
$defaultMemory = $m;
|
||||
break;
|
||||
case "G":
|
||||
$defaultMemory = $m * 1024;
|
||||
break;
|
||||
default:
|
||||
$defaultMemory = $m;
|
||||
break;
|
||||
}
|
||||
$defaultMemory = match(mb_strtoupper($matches[2])){
|
||||
"K" => intdiv($m, 1024),
|
||||
"M" => $m,
|
||||
"G" => $m * 1024,
|
||||
default => $m,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,11 +135,11 @@ class MemoryManager{
|
||||
}
|
||||
|
||||
$this->globalMemoryLimit = $config->getPropertyInt("memory.global-limit", 0) * 1024 * 1024;
|
||||
$this->checkRate = $config->getPropertyInt("memory.check-rate", 20);
|
||||
$this->checkRate = $config->getPropertyInt("memory.check-rate", self::DEFAULT_CHECK_RATE);
|
||||
$this->continuousTrigger = $config->getPropertyBool("memory.continuous-trigger", true);
|
||||
$this->continuousTriggerRate = $config->getPropertyInt("memory.continuous-trigger-rate", 30);
|
||||
$this->continuousTriggerRate = $config->getPropertyInt("memory.continuous-trigger-rate", self::DEFAULT_CONTINUOUS_TRIGGER_RATE);
|
||||
|
||||
$this->garbageCollectionPeriod = $config->getPropertyInt("memory.garbage-collection.period", 36000);
|
||||
$this->garbageCollectionPeriod = $config->getPropertyInt("memory.garbage-collection.period", self::DEFAULT_TICKS_PER_GC);
|
||||
$this->garbageCollectionTrigger = $config->getPropertyBool("memory.garbage-collection.low-memory-trigger", true);
|
||||
$this->garbageCollectionAsync = $config->getPropertyBool("memory.garbage-collection.collect-async-worker", true);
|
||||
|
||||
@ -285,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();
|
||||
@ -477,6 +475,7 @@ class MemoryManager{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $from
|
||||
* @param object[] $objects reference parameter
|
||||
* @param int[] $refCounts reference parameter
|
||||
*
|
||||
@ -484,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";
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ namespace pocketmine {
|
||||
if(substr_count($pthreads_version, ".") < 2){
|
||||
$pthreads_version = "0.$pthreads_version";
|
||||
}
|
||||
if(version_compare($pthreads_version, "4.0.0") < 0 || version_compare($pthreads_version, "5.0.0") > 0){
|
||||
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.";
|
||||
}
|
||||
}
|
||||
|
206
src/Server.php
206
src/Server.php
@ -49,10 +49,7 @@ use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\Language;
|
||||
use pocketmine\lang\LanguageNotFoundException;
|
||||
use pocketmine\lang\Translatable;
|
||||
use pocketmine\nbt\BigEndianNbtSerializer;
|
||||
use pocketmine\nbt\NbtDataException;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\TreeRoot;
|
||||
use pocketmine\network\mcpe\compression\CompressBatchPromise;
|
||||
use pocketmine\network\mcpe\compression\CompressBatchTask;
|
||||
use pocketmine\network\mcpe\compression\Compressor;
|
||||
@ -72,9 +69,13 @@ use pocketmine\network\query\QueryInfo;
|
||||
use pocketmine\network\upnp\UPnPNetworkInterface;
|
||||
use pocketmine\permission\BanList;
|
||||
use pocketmine\permission\DefaultPermissions;
|
||||
use pocketmine\player\DatFilePlayerDataProvider;
|
||||
use pocketmine\player\GameMode;
|
||||
use pocketmine\player\OfflinePlayer;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\player\PlayerDataLoadException;
|
||||
use pocketmine\player\PlayerDataProvider;
|
||||
use pocketmine\player\PlayerDataSaveException;
|
||||
use pocketmine\player\PlayerInfo;
|
||||
use pocketmine\plugin\PharPluginLoader;
|
||||
use pocketmine\plugin\Plugin;
|
||||
@ -105,17 +106,18 @@ use pocketmine\utils\SignalHandler;
|
||||
use pocketmine\utils\Terminal;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\world\format\Chunk;
|
||||
use pocketmine\world\format\io\WorldProviderManager;
|
||||
use pocketmine\world\format\io\WritableWorldProviderManagerEntry;
|
||||
use pocketmine\world\generator\Generator;
|
||||
use pocketmine\world\generator\GeneratorManager;
|
||||
use pocketmine\world\generator\InvalidGeneratorOptionsException;
|
||||
use pocketmine\world\Position;
|
||||
use pocketmine\world\World;
|
||||
use pocketmine\world\WorldCreationOptions;
|
||||
use pocketmine\world\WorldManager;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
use Symfony\Component\Filesystem\Path;
|
||||
use function array_fill;
|
||||
use function array_sum;
|
||||
use function base64_encode;
|
||||
use function cli_set_process_title;
|
||||
@ -124,7 +126,6 @@ use function count;
|
||||
use function date;
|
||||
use function fclose;
|
||||
use function file_exists;
|
||||
use function file_get_contents;
|
||||
use function file_put_contents;
|
||||
use function filemtime;
|
||||
use function fopen;
|
||||
@ -161,12 +162,9 @@ use function time;
|
||||
use function touch;
|
||||
use function trim;
|
||||
use function yaml_parse;
|
||||
use function zlib_decode;
|
||||
use function zlib_encode;
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
use const PHP_EOL;
|
||||
use const PHP_INT_MAX;
|
||||
use const ZLIB_ENCODING_GZIP;
|
||||
|
||||
/**
|
||||
* The class that manages everything
|
||||
@ -184,9 +182,30 @@ class Server{
|
||||
public const DEFAULT_PORT_IPV6 = 19133;
|
||||
public const DEFAULT_MAX_VIEW_DISTANCE = 16;
|
||||
|
||||
/**
|
||||
* Worlds, network, commands and most other things are polled this many times per second on average.
|
||||
* Between ticks, the server will sleep to ensure that the average tick rate is maintained.
|
||||
* It may wake up between ticks if a Snooze notification source is triggered (e.g. to process network packets).
|
||||
*/
|
||||
public const TARGET_TICKS_PER_SECOND = 20;
|
||||
/**
|
||||
* The average time between ticks, in seconds.
|
||||
*/
|
||||
public const TARGET_SECONDS_PER_TICK = 1 / self::TARGET_TICKS_PER_SECOND;
|
||||
public const TARGET_NANOSECONDS_PER_TICK = 1_000_000_000 / self::TARGET_TICKS_PER_SECOND;
|
||||
|
||||
/**
|
||||
* The TPS threshold below which the server will generate log warnings.
|
||||
*/
|
||||
private const TPS_OVERLOAD_WARNING_THRESHOLD = self::TARGET_TICKS_PER_SECOND * 0.6;
|
||||
|
||||
private const TICKS_PER_WORLD_CACHE_CLEAR = 5 * self::TARGET_TICKS_PER_SECOND;
|
||||
private const TICKS_PER_TPS_OVERLOAD_WARNING = 5 * self::TARGET_TICKS_PER_SECOND;
|
||||
private const TICKS_PER_STATS_REPORT = 300 * self::TARGET_TICKS_PER_SECOND;
|
||||
|
||||
private static ?Server $instance = null;
|
||||
|
||||
private SleeperHandler $tickSleeper;
|
||||
private TimeTrackingSleeperHandler $tickSleeper;
|
||||
|
||||
private BanList $banByName;
|
||||
|
||||
@ -202,7 +221,7 @@ class Server{
|
||||
|
||||
private PluginManager $pluginManager;
|
||||
|
||||
private float $profilingTickRate = 20;
|
||||
private float $profilingTickRate = self::TARGET_TICKS_PER_SECOND;
|
||||
|
||||
private UpdateChecker $updater;
|
||||
|
||||
@ -212,10 +231,10 @@ class Server{
|
||||
private int $tickCounter = 0;
|
||||
private float $nextTick = 0;
|
||||
/** @var float[] */
|
||||
private array $tickAverage = [20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20];
|
||||
private array $tickAverage;
|
||||
/** @var float[] */
|
||||
private array $useAverage = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
private float $currentTPS = 20;
|
||||
private array $useAverage;
|
||||
private float $currentTPS = self::TARGET_TICKS_PER_SECOND;
|
||||
private float $currentUse = 0;
|
||||
private float $startTime;
|
||||
|
||||
@ -251,6 +270,8 @@ class Server{
|
||||
private string $dataPath;
|
||||
private string $pluginPath;
|
||||
|
||||
private PlayerDataProvider $playerDataProvider;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
* @phpstan-var array<string, string>
|
||||
@ -470,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);
|
||||
|
||||
@ -481,49 +505,22 @@ class Server{
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function getPlayerDataPath(string $username) : string{
|
||||
return Path::join($this->getDataPath(), 'players', strtolower($username) . '.dat');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the server has stored any saved data for this player.
|
||||
*/
|
||||
public function hasOfflinePlayerData(string $name) : bool{
|
||||
return file_exists($this->getPlayerDataPath($name));
|
||||
}
|
||||
|
||||
private function handleCorruptedPlayerData(string $name) : void{
|
||||
$path = $this->getPlayerDataPath($name);
|
||||
rename($path, $path . '.bak');
|
||||
$this->logger->error($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_data_playerCorrupted($name)));
|
||||
return $this->playerDataProvider->hasData($name);
|
||||
}
|
||||
|
||||
public function getOfflinePlayerData(string $name) : ?CompoundTag{
|
||||
return Timings::$syncPlayerDataLoad->time(function() use ($name) : ?CompoundTag{
|
||||
$name = strtolower($name);
|
||||
$path = $this->getPlayerDataPath($name);
|
||||
|
||||
if(file_exists($path)){
|
||||
$contents = @file_get_contents($path);
|
||||
if($contents === false){
|
||||
throw new \RuntimeException("Failed to read player data file \"$path\" (permission denied?)");
|
||||
}
|
||||
$decompressed = @zlib_decode($contents);
|
||||
if($decompressed === false){
|
||||
$this->logger->debug("Failed to decompress raw player data for \"$name\"");
|
||||
$this->handleCorruptedPlayerData($name);
|
||||
return null;
|
||||
}
|
||||
|
||||
try{
|
||||
return (new BigEndianNbtSerializer())->read($decompressed)->mustGetCompoundTag();
|
||||
}catch(NbtDataException $e){ //corrupt data
|
||||
$this->logger->debug("Failed to decode NBT data for \"$name\": " . $e->getMessage());
|
||||
$this->handleCorruptedPlayerData($name);
|
||||
return null;
|
||||
}
|
||||
try{
|
||||
return $this->playerDataProvider->loadData($name);
|
||||
}catch(PlayerDataLoadException $e){
|
||||
$this->logger->debug("Failed to load player data for $name: " . $e->getMessage());
|
||||
$this->logger->error($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_data_playerCorrupted($name)));
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@ -537,11 +534,9 @@ class Server{
|
||||
|
||||
if(!$ev->isCancelled()){
|
||||
Timings::$syncPlayerDataSave->time(function() use ($name, $ev) : void{
|
||||
$nbt = new BigEndianNbtSerializer();
|
||||
$contents = Utils::assumeNotFalse(zlib_encode($nbt->write(new TreeRoot($ev->getSaveData())), ZLIB_ENCODING_GZIP), "zlib_encode() failed unexpectedly");
|
||||
try{
|
||||
Filesystem::safeFilePutContents($this->getPlayerDataPath($name), $contents);
|
||||
}catch(\RuntimeException $e){
|
||||
$this->playerDataProvider->saveData($name, $ev->getSaveData());
|
||||
}catch(PlayerDataSaveException $e){
|
||||
$this->logger->critical($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_data_saveError($name, $e->getMessage())));
|
||||
$this->logger->logException($e);
|
||||
}
|
||||
@ -559,49 +554,45 @@ class Server{
|
||||
|
||||
if($offlinePlayerData !== null && ($world = $this->worldManager->getWorldByName($offlinePlayerData->getString(Player::TAG_LEVEL, ""))) !== null){
|
||||
$playerPos = EntityDataHelper::parseLocation($offlinePlayerData, $world);
|
||||
$spawn = $playerPos->asVector3();
|
||||
}else{
|
||||
$world = $this->worldManager->getDefaultWorld();
|
||||
if($world === null){
|
||||
throw new AssumptionFailedError("Default world should always be loaded");
|
||||
}
|
||||
$playerPos = null;
|
||||
$spawn = $world->getSpawnLocation();
|
||||
}
|
||||
/** @phpstan-var PromiseResolver<Player> $playerPromiseResolver */
|
||||
$playerPromiseResolver = new PromiseResolver();
|
||||
$world->requestChunkPopulation($spawn->getFloorX() >> Chunk::COORD_BIT_SIZE, $spawn->getFloorZ() >> Chunk::COORD_BIT_SIZE, null)->onCompletion(
|
||||
function() use ($playerPromiseResolver, $class, $session, $playerInfo, $authenticated, $world, $playerPos, $spawn, $offlinePlayerData) : void{
|
||||
if(!$session->isConnected()){
|
||||
$playerPromiseResolver->reject();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Stick with the original spawn at the time of generation request, even if it changed since then.
|
||||
* This is because we know for sure that that chunk will be generated, but the one at the new location
|
||||
* might not be, and it would be much more complex to go back and redo the whole thing.
|
||||
*
|
||||
* TODO: this relies on the assumption that getSafeSpawn() will only alter the Y coordinate of the
|
||||
* provided position. If this assumption is broken, we'll start seeing crashes in here.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see Player::__construct()
|
||||
* @var Player $player
|
||||
*/
|
||||
$player = new $class($this, $session, $playerInfo, $authenticated, $playerPos ?? Location::fromObject($world->getSafeSpawn($spawn), $world), $offlinePlayerData);
|
||||
if(!$player->hasPlayedBefore()){
|
||||
$player->onGround = true; //TODO: this hack is needed for new players in-air ticks - they don't get detected as on-ground until they move
|
||||
}
|
||||
$playerPromiseResolver->resolve($player);
|
||||
},
|
||||
static function() use ($playerPromiseResolver, $session) : void{
|
||||
if($session->isConnected()){
|
||||
$session->disconnect("Spawn terrain generation failed");
|
||||
}
|
||||
$playerPromiseResolver->reject();
|
||||
$createPlayer = function(Location $location) use ($playerPromiseResolver, $class, $session, $playerInfo, $authenticated, $offlinePlayerData) : void{
|
||||
$player = new $class($this, $session, $playerInfo, $authenticated, $location, $offlinePlayerData);
|
||||
if(!$player->hasPlayedBefore()){
|
||||
$player->onGround = true; //TODO: this hack is needed for new players in-air ticks - they don't get detected as on-ground until they move
|
||||
}
|
||||
);
|
||||
$playerPromiseResolver->resolve($player);
|
||||
};
|
||||
|
||||
if($playerPos === null){ //new player or no valid position due to world not being loaded
|
||||
$world->requestSafeSpawn()->onCompletion(
|
||||
function(Position $spawn) use ($createPlayer, $playerPromiseResolver, $session, $world) : void{
|
||||
if(!$session->isConnected()){
|
||||
$playerPromiseResolver->reject();
|
||||
return;
|
||||
}
|
||||
$createPlayer(Location::fromObject($spawn, $world));
|
||||
},
|
||||
function() use ($playerPromiseResolver, $session) : void{
|
||||
if($session->isConnected()){
|
||||
//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();
|
||||
}
|
||||
);
|
||||
}else{ //returning player with a valid position - safe spawn not required
|
||||
$createPlayer($playerPos);
|
||||
}
|
||||
|
||||
return $playerPromiseResolver->getPromise();
|
||||
}
|
||||
|
||||
@ -777,8 +768,11 @@ class Server{
|
||||
}
|
||||
self::$instance = $this;
|
||||
$this->startTime = microtime(true);
|
||||
$this->tickAverage = array_fill(0, self::TARGET_TICKS_PER_SECOND, self::TARGET_TICKS_PER_SECOND);
|
||||
$this->useAverage = array_fill(0, self::TARGET_TICKS_PER_SECOND, 0);
|
||||
|
||||
$this->tickSleeper = new SleeperHandler();
|
||||
Timings::init();
|
||||
$this->tickSleeper = new TimeTrackingSleeperHandler(Timings::$serverInterrupts);
|
||||
|
||||
$this->signalHandler = new SignalHandler(function() : void{
|
||||
$this->logger->info("Received signal interrupt, stopping the server");
|
||||
@ -803,7 +797,7 @@ class Server{
|
||||
$this->logger->info("Loading server configuration");
|
||||
$pocketmineYmlPath = Path::join($this->dataPath, "pocketmine.yml");
|
||||
if(!file_exists($pocketmineYmlPath)){
|
||||
$content = Utils::assumeNotFalse(file_get_contents(Path::join(\pocketmine\RESOURCE_PATH, "pocketmine.yml")), "Missing required resource file");
|
||||
$content = Filesystem::fileGetContents(Path::join(\pocketmine\RESOURCE_PATH, "pocketmine.yml"));
|
||||
if(VersionInfo::IS_DEVELOPMENT_BUILD){
|
||||
$content = str_replace("preferred-channel: stable", "preferred-channel: beta", $content);
|
||||
}
|
||||
@ -958,15 +952,14 @@ class Server{
|
||||
)));
|
||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_license($this->getName())));
|
||||
|
||||
Timings::init();
|
||||
TimingsHandler::setEnabled($this->configGroup->getPropertyBool("settings.enable-profiling", false));
|
||||
$this->profilingTickRate = $this->configGroup->getPropertyInt("settings.profile-report-trigger", 20);
|
||||
$this->profilingTickRate = $this->configGroup->getPropertyInt("settings.profile-report-trigger", self::TARGET_TICKS_PER_SECOND);
|
||||
|
||||
DefaultPermissions::registerCorePermissions();
|
||||
|
||||
$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);
|
||||
|
||||
@ -976,7 +969,7 @@ class Server{
|
||||
copy(Path::join(\pocketmine\RESOURCE_PATH, 'plugin_list.yml'), $graylistFile);
|
||||
}
|
||||
try{
|
||||
$pluginGraylist = PluginGraylist::fromArray(yaml_parse(file_get_contents($graylistFile)));
|
||||
$pluginGraylist = PluginGraylist::fromArray(yaml_parse(Filesystem::fileGetContents($graylistFile)));
|
||||
}catch(\InvalidArgumentException $e){
|
||||
$this->logger->emergency("Failed to load $graylistFile: " . $e->getMessage());
|
||||
$this->forceShutdownExit();
|
||||
@ -998,12 +991,14 @@ class Server{
|
||||
|
||||
$this->worldManager = new WorldManager($this, Path::join($this->dataPath, "worlds"), $providerManager);
|
||||
$this->worldManager->setAutoSave($this->configGroup->getConfigBool("auto-save", $this->worldManager->getAutoSave()));
|
||||
$this->worldManager->setAutoSaveInterval($this->configGroup->getPropertyInt("ticks-per.autosave", 6000));
|
||||
$this->worldManager->setAutoSaveInterval($this->configGroup->getPropertyInt("ticks-per.autosave", $this->worldManager->getAutoSaveInterval()));
|
||||
|
||||
$this->updater = new UpdateChecker($this, $this->configGroup->getPropertyString("auto-updater.host", "update.pmmp.io"));
|
||||
|
||||
$this->queryInfo = new QueryInfo($this);
|
||||
|
||||
$this->playerDataProvider = new DatFilePlayerDataProvider(Path::join($this->dataPath, "players"));
|
||||
|
||||
register_shutdown_function([$this, "crashDump"]);
|
||||
|
||||
$loadErrorCount = 0;
|
||||
@ -1036,7 +1031,7 @@ class Server{
|
||||
}
|
||||
|
||||
if($this->configGroup->getPropertyBool("anonymous-statistics.enabled", true)){
|
||||
$this->sendUsageTicker = 6000;
|
||||
$this->sendUsageTicker = self::TICKS_PER_STATS_REPORT;
|
||||
$this->sendUsage(SendUsageTask::TYPE_OPEN);
|
||||
}
|
||||
|
||||
@ -1360,7 +1355,6 @@ class Server{
|
||||
return false;
|
||||
}
|
||||
$recipients = $ev->getTargets();
|
||||
$packets = $ev->getPackets();
|
||||
|
||||
/** @var PacketBroadcaster[] $broadcasters */
|
||||
$broadcasters = [];
|
||||
@ -1535,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;
|
||||
|
||||
@ -1819,11 +1813,11 @@ class Server{
|
||||
$this->network->tick();
|
||||
Timings::$connection->stopTiming();
|
||||
|
||||
if(($this->tickCounter % 20) === 0){
|
||||
if(($this->tickCounter % self::TARGET_TICKS_PER_SECOND) === 0){
|
||||
if($this->doTitleTick){
|
||||
$this->titleTick();
|
||||
}
|
||||
$this->currentTPS = 20;
|
||||
$this->currentTPS = self::TARGET_TICKS_PER_SECOND;
|
||||
$this->currentUse = 0;
|
||||
|
||||
$queryRegenerateEvent = new QueryRegenerateEvent(new QueryInfo($this));
|
||||
@ -1835,18 +1829,18 @@ class Server{
|
||||
}
|
||||
|
||||
if($this->sendUsageTicker > 0 && --$this->sendUsageTicker === 0){
|
||||
$this->sendUsageTicker = 6000;
|
||||
$this->sendUsageTicker = self::TICKS_PER_STATS_REPORT;
|
||||
$this->sendUsage(SendUsageTask::TYPE_STATUS);
|
||||
}
|
||||
|
||||
if(($this->tickCounter % 100) === 0){
|
||||
if(($this->tickCounter % self::TICKS_PER_WORLD_CACHE_CLEAR) === 0){
|
||||
foreach($this->worldManager->getWorlds() as $world){
|
||||
$world->clearCache();
|
||||
}
|
||||
}
|
||||
|
||||
if($this->getTicksPerSecondAverage() < 12){
|
||||
$this->logger->warning($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_tickOverload()));
|
||||
}
|
||||
if(($this->tickCounter % self::TICKS_PER_TPS_OVERLOAD_WARNING) === 0 && $this->getTicksPerSecondAverage() < self::TPS_OVERLOAD_WARNING_THRESHOLD){
|
||||
$this->logger->warning($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_tickOverload()));
|
||||
}
|
||||
|
||||
$this->getMemoryManager()->check();
|
||||
@ -1863,19 +1857,21 @@ class Server{
|
||||
Timings::$serverTick->stopTiming();
|
||||
|
||||
$now = microtime(true);
|
||||
$this->currentTPS = min(20, 1 / max(0.001, $now - $tickTime));
|
||||
$this->currentUse = min(1, ($now - $tickTime) / 0.05);
|
||||
$totalTickTimeSeconds = $now - $tickTime + ($this->tickSleeper->getNotificationProcessingTime() / 1_000_000_000);
|
||||
$this->currentTPS = min(self::TARGET_TICKS_PER_SECOND, 1 / max(0.001, $totalTickTimeSeconds));
|
||||
$this->currentUse = min(1, $totalTickTimeSeconds / self::TARGET_SECONDS_PER_TICK);
|
||||
|
||||
TimingsHandler::tick($this->currentTPS <= $this->profilingTickRate);
|
||||
|
||||
$idx = $this->tickCounter % 20;
|
||||
$idx = $this->tickCounter % self::TARGET_TICKS_PER_SECOND;
|
||||
$this->tickAverage[$idx] = $this->currentTPS;
|
||||
$this->useAverage[$idx] = $this->currentUse;
|
||||
$this->tickSleeper->resetNotificationProcessingTime();
|
||||
|
||||
if(($this->nextTick - $tickTime) < -1){
|
||||
$this->nextTick = $tickTime;
|
||||
}else{
|
||||
$this->nextTick += 0.05;
|
||||
$this->nextTick += self::TARGET_SECONDS_PER_TICK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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])){
|
||||
|
64
src/TimeTrackingSleeperHandler.php
Normal file
64
src/TimeTrackingSleeperHandler.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?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;
|
||||
|
||||
use pocketmine\snooze\SleeperHandler;
|
||||
use pocketmine\timings\TimingsHandler;
|
||||
use function hrtime;
|
||||
|
||||
/**
|
||||
* Custom Snooze sleeper handler which captures notification processing time.
|
||||
* @internal
|
||||
*/
|
||||
final class TimeTrackingSleeperHandler extends SleeperHandler{
|
||||
|
||||
private int $notificationProcessingTimeNs = 0;
|
||||
|
||||
public function __construct(
|
||||
private TimingsHandler $timings
|
||||
){
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time in nanoseconds spent processing notifications since the last reset.
|
||||
*/
|
||||
public function getNotificationProcessingTime() : int{ return $this->notificationProcessingTimeNs; }
|
||||
|
||||
/**
|
||||
* Resets the notification processing time tracker to zero.
|
||||
*/
|
||||
public function resetNotificationProcessingTime() : void{ $this->notificationProcessingTimeNs = 0; }
|
||||
|
||||
public function processNotifications() : void{
|
||||
$startTime = hrtime(true);
|
||||
$this->timings->startTiming();
|
||||
try{
|
||||
parent::processNotifications();
|
||||
}finally{
|
||||
$this->notificationProcessingTimeNs += hrtime(true) - $startTime;
|
||||
$this->timings->stopTiming();
|
||||
}
|
||||
}
|
||||
}
|
@ -31,9 +31,9 @@ use function str_repeat;
|
||||
|
||||
final class VersionInfo{
|
||||
public const NAME = "PocketMine-MP";
|
||||
public const BASE_VERSION = "5.0.0-ALPHA6";
|
||||
public const BASE_VERSION = "4.13.0";
|
||||
public const IS_DEVELOPMENT_BUILD = false;
|
||||
public const BUILD_CHANNEL = "alpha";
|
||||
public const BUILD_CHANNEL = "stable";
|
||||
|
||||
private function __construct(){
|
||||
//NOOP
|
||||
|
@ -24,23 +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\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
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;
|
||||
@ -52,16 +46,21 @@ class Anvil extends Transparent implements Fallable{
|
||||
|
||||
private int $damage = self::UNDAMAGED;
|
||||
|
||||
public function getRequiredTypeDataBits() : int{ return 2; }
|
||||
|
||||
protected function describeType(RuntimeDataReader|RuntimeDataWriter $w) : void{
|
||||
$w->boundedInt(2, self::UNDAMAGED, self::VERY_DAMAGED, $this->damage);
|
||||
protected function writeStateToMeta() : int{
|
||||
return BlockDataSerializer::writeLegacyHorizontalFacing($this->facing) | ($this->damage << 2);
|
||||
}
|
||||
|
||||
public function getRequiredStateDataBits() : int{ return 2; }
|
||||
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);
|
||||
}
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $w) : void{
|
||||
$w->horizontalFacing($this->facing);
|
||||
public function getStateBitmask() : int{
|
||||
return 0b1111;
|
||||
}
|
||||
|
||||
protected function writeStateToItemMeta() : int{
|
||||
return $this->damage << 2;
|
||||
}
|
||||
|
||||
public function getDamage() : int{ return $this->damage; }
|
||||
@ -86,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));
|
||||
}
|
||||
@ -101,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;
|
||||
}
|
||||
}
|
||||
|
@ -23,14 +23,12 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\BlockDataSerializer;
|
||||
use pocketmine\block\utils\SupportType;
|
||||
use pocketmine\data\runtime\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
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;
|
||||
@ -56,12 +54,18 @@ class Bamboo extends Transparent{
|
||||
protected bool $ready = false;
|
||||
protected int $leafSize = self::NO_LEAVES;
|
||||
|
||||
public function getRequiredStateDataBits() : int{ return 4; }
|
||||
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;
|
||||
}
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $w) : void{
|
||||
$w->boundedInt(2, self::NO_LEAVES, self::LARGE_LEAVES, $this->leafSize);
|
||||
$w->bool($this->thick);
|
||||
$w->bool($this->ready);
|
||||
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; }
|
||||
@ -124,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{
|
||||
@ -140,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)){
|
||||
@ -236,8 +243,4 @@ class Bamboo extends Transparent{
|
||||
$world->setBlock($this->position, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function asItem() : Item{
|
||||
return VanillaItems::BAMBOO();
|
||||
}
|
||||
}
|
||||
|
@ -23,26 +23,28 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\data\runtime\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
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;
|
||||
|
||||
public function getRequiredStateDataBits() : int{ return 1; }
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $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 */
|
||||
@ -52,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{
|
||||
@ -66,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();
|
||||
@ -121,6 +126,6 @@ final class BambooSapling extends Flowable{
|
||||
}
|
||||
|
||||
public function asItem() : Item{
|
||||
return VanillaItems::BAMBOO();
|
||||
return VanillaBlocks::BAMBOO()->asItem();
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\tile\Barrel as TileBarrel;
|
||||
use pocketmine\block\utils\AnyFacingTrait;
|
||||
use pocketmine\data\runtime\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
use pocketmine\block\utils\BlockDataSerializer;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
@ -39,11 +38,17 @@ class Barrel extends Opaque{
|
||||
|
||||
protected bool $open = false;
|
||||
|
||||
public function getRequiredStateDataBits() : int{ return 4; }
|
||||
protected function writeStateToMeta() : int{
|
||||
return BlockDataSerializer::writeFacing($this->facing) | ($this->open ? BlockLegacyMetadata::BARREL_FLAG_OPEN : 0);
|
||||
}
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $w) : void{
|
||||
$w->facing($this->facing);
|
||||
$w->bool($this->open);
|
||||
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{
|
||||
@ -76,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){
|
||||
|
@ -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{
|
||||
@ -114,7 +112,14 @@ abstract class BaseBanner extends Transparent{
|
||||
return SupportType::NONE();
|
||||
}
|
||||
|
||||
private function canBeSupportedBy(Block $block) : bool{
|
||||
return $block->isSolid();
|
||||
}
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if(!$this->canBeSupportedBy($blockReplace->getSide($this->getSupportingFace()))){
|
||||
return false;
|
||||
}
|
||||
if($item instanceof ItemBanner){
|
||||
$this->color = $item->getColor();
|
||||
$this->setPatterns($item->getPatterns());
|
||||
@ -126,11 +131,15 @@ abstract class BaseBanner extends Transparent{
|
||||
abstract protected function getSupportingFace() : int;
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->getSide($this->getSupportingFace())->getTypeId() === BlockTypeIds::AIR){
|
||||
if(!$this->canBeSupportedBy($this->getSide($this->getSupportingFace()))){
|
||||
$this->position->getWorld()->useBreakOn($this->position);
|
||||
}
|
||||
}
|
||||
|
||||
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){
|
||||
@ -147,8 +156,4 @@ abstract class BaseBanner extends Transparent{
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function asItem() : Item{
|
||||
return VanillaItems::BANNER()->setColor($this->color);
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
@ -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{
|
||||
|
@ -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 [];
|
||||
}
|
||||
}
|
@ -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)();
|
||||
}
|
||||
}
|
||||
|
@ -24,12 +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\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
use pocketmine\data\bedrock\DyeColorIdMap;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\entity\Living;
|
||||
use pocketmine\item\Item;
|
||||
@ -49,28 +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);
|
||||
}
|
||||
|
||||
public function getRequiredStateDataBits() : int{ return 4; }
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $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{
|
||||
@ -126,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();
|
||||
@ -203,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];
|
||||
@ -214,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; }
|
||||
}
|
||||
|
@ -23,16 +23,20 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\data\runtime\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
|
||||
class Bedrock extends Opaque{
|
||||
|
||||
private bool $burnsForever = false;
|
||||
|
||||
public function getRequiredStateDataBits() : int{ return 1; }
|
||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||
$this->burnsForever = ($stateMeta & BlockLegacyMetadata::BEDROCK_FLAG_INFINIBURN) !== 0;
|
||||
}
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $w) : void{
|
||||
$w->bool($this->burnsForever);
|
||||
protected function writeStateToMeta() : int{
|
||||
return $this->burnsForever ? BlockLegacyMetadata::BEDROCK_FLAG_INFINIBURN : 0;
|
||||
}
|
||||
|
||||
public function getStateBitmask() : int{
|
||||
return 0b1;
|
||||
}
|
||||
|
||||
public function burnsForever() : bool{
|
||||
|
@ -42,7 +42,7 @@ class Beetroot extends Crops{
|
||||
];
|
||||
}
|
||||
|
||||
public function asItem() : Item{
|
||||
public function getPickedItem(bool $addUserData = false) : Item{
|
||||
return VanillaItems::BEETROOT_SEEDS();
|
||||
}
|
||||
}
|
||||
|
@ -25,15 +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\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use pocketmine\world\sound\BellRingSound;
|
||||
|
||||
@ -42,16 +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);
|
||||
}
|
||||
|
||||
public function getRequiredStateDataBits() : int{ return 4; }
|
||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||
$this->setFacing(BlockDataSerializer::readLegacyHorizontalFacing($stateMeta & 0x03));
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $w) : void{
|
||||
$w->bellAttachmentType($this->attachmentType);
|
||||
$w->horizontalFacing($this->facing);
|
||||
$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{
|
||||
@ -88,14 +114,13 @@ final class Bell extends Transparent{
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function canBeSupportedBy(Block $block) : bool{
|
||||
//TODO: this isn't the actual logic, but it's the closest approximation we can support for now
|
||||
return $block->isSolid();
|
||||
private function canBeSupportedBy(Block $block, int $face) : bool{
|
||||
return !$block->getSupportType($face)->equals(SupportType::NONE());
|
||||
}
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($face === Facing::UP){
|
||||
if(!$this->canBeSupportedBy($tx->fetchBlock($this->position->down()))){
|
||||
if(!$this->canBeSupportedBy($tx->fetchBlock($this->position->down()), Facing::UP)){
|
||||
return false;
|
||||
}
|
||||
if($player !== null){
|
||||
@ -103,18 +128,18 @@ final class Bell extends Transparent{
|
||||
}
|
||||
$this->setAttachmentType(BellAttachmentType::FLOOR());
|
||||
}elseif($face === Facing::DOWN){
|
||||
if(!$this->canBeSupportedBy($tx->fetchBlock($this->position->up()))){
|
||||
if(!$this->canBeSupportedBy($tx->fetchBlock($this->position->up()), Facing::DOWN)){
|
||||
return false;
|
||||
}
|
||||
$this->setAttachmentType(BellAttachmentType::CEILING());
|
||||
}else{
|
||||
$this->setFacing($face);
|
||||
if($this->canBeSupportedBy($tx->fetchBlock($this->position->getSide(Facing::opposite($face))))){
|
||||
if($this->canBeSupportedBy($tx->fetchBlock($this->position->getSide(Facing::opposite($face))), $face)){
|
||||
$this->setAttachmentType(BellAttachmentType::ONE_WALL());
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
if($this->canBeSupportedBy($tx->fetchBlock($this->position->getSide($face)))){
|
||||
if($this->canBeSupportedBy($tx->fetchBlock($this->position->getSide($face)), Facing::opposite($face))){
|
||||
$this->setAttachmentType(BellAttachmentType::TWO_WALLS());
|
||||
}
|
||||
}
|
||||
@ -123,33 +148,32 @@ final class Bell extends Transparent{
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if(
|
||||
($this->attachmentType->equals(BellAttachmentType::CEILING()) && !$this->canBeSupportedBy($this->getSide(Facing::UP))) ||
|
||||
($this->attachmentType->equals(BellAttachmentType::FLOOR()) && !$this->canBeSupportedBy($this->getSide(Facing::DOWN))) ||
|
||||
($this->attachmentType->equals(BellAttachmentType::ONE_WALL()) && !$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)))) ||
|
||||
($this->attachmentType->equals(BellAttachmentType::TWO_WALLS()) && (!$this->canBeSupportedBy($this->getSide($this->facing)) || !$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)))))
|
||||
($this->attachmentType->equals(BellAttachmentType::CEILING()) && !$this->canBeSupportedBy($this->getSide(Facing::UP), Facing::DOWN)) ||
|
||||
($this->attachmentType->equals(BellAttachmentType::FLOOR()) && !$this->canBeSupportedBy($this->getSide(Facing::DOWN), Facing::UP)) ||
|
||||
($this->attachmentType->equals(BellAttachmentType::ONE_WALL()) && !$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)), $this->facing)) ||
|
||||
($this->attachmentType->equals(BellAttachmentType::TWO_WALLS()) && (!$this->canBeSupportedBy($this->getSide($this->facing), Facing::opposite($this->facing)) || !$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)), $this->facing)))
|
||||
){
|
||||
$this->position->getWorld()->useBreakOn($this->position);
|
||||
}
|
||||
}
|
||||
|
||||
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->attachmentType->equals(BellAttachmentType::CEILING())){
|
||||
$this->ring($faceHit);
|
||||
}
|
||||
if($this->attachmentType->equals(BellAttachmentType::FLOOR()) && Facing::axis($faceHit) === Facing::axis($this->facing)){
|
||||
$this->ring($faceHit);
|
||||
}
|
||||
if(
|
||||
($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->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;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public function ring(int $faceHit) : void{
|
||||
|
@ -28,14 +28,12 @@ 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\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\entity\projectile\Projectile;
|
||||
use pocketmine\item\enchantment\VanillaEnchantments;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemBlock;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\math\Axis;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\RayTraceResult;
|
||||
@ -46,17 +44,18 @@ 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 */
|
||||
@ -65,10 +64,13 @@ class Block{
|
||||
/**
|
||||
* @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);
|
||||
}
|
||||
|
||||
@ -77,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;
|
||||
@ -91,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 BlockFactory::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();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -109,86 +120,44 @@ class Block{
|
||||
* Type information such as colour, wood type, etc. is preserved.
|
||||
*/
|
||||
public function asItem() : Item{
|
||||
return new ItemBlock($this);
|
||||
}
|
||||
|
||||
public function getRequiredTypeDataBits() : int{ return 0; }
|
||||
|
||||
public function getRequiredStateDataBits() : int{ return 0; }
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final public function decodeTypeData(int $data) : void{
|
||||
$typeBits = $this->getRequiredTypeDataBits();
|
||||
$givenBits = $typeBits;
|
||||
$reader = new RuntimeDataReader($givenBits, $data);
|
||||
|
||||
$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");
|
||||
}
|
||||
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 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 getMeta() : int{
|
||||
$stateMeta = $this->writeStateToMeta();
|
||||
assert(($stateMeta & ~$this->getStateBitmask()) === 0);
|
||||
return $this->idInfo->getVariant() | $stateMeta;
|
||||
}
|
||||
|
||||
$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 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 computeTypeData() : int{
|
||||
$typeBits = $this->getRequiredTypeDataBits();
|
||||
$requiredBits = $typeBits;
|
||||
$writer = new RuntimeDataWriter($requiredBits);
|
||||
public function getStateBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
$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();
|
||||
protected function writeStateToMeta() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @throws InvalidBlockStateException
|
||||
*/
|
||||
final public function computeStateData() : int{
|
||||
$typeBits = $this->getRequiredTypeDataBits();
|
||||
$stateBits = $this->getRequiredStateDataBits();
|
||||
$requiredBits = $typeBits + $stateBits;
|
||||
$writer = new RuntimeDataWriter($requiredBits);
|
||||
$writer->int($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(RuntimeDataReader|RuntimeDataWriter $w) : void{
|
||||
//NOOP
|
||||
}
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $w) : void{
|
||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||
//NOOP
|
||||
}
|
||||
|
||||
@ -198,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;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -216,7 +180,7 @@ class Block{
|
||||
*/
|
||||
public function writeStateToWorld() : void{
|
||||
$world = $this->position->getWorld();
|
||||
$world->getOrLoadChunkAtPosition($this->position)->setFullBlock($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);
|
||||
@ -243,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();
|
||||
@ -257,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();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -305,6 +253,14 @@ class Block{
|
||||
* Generates a block transaction to set all blocks affected by placing this block. Usually this is just the block
|
||||
* itself, but may be multiple blocks in some cases (such as doors).
|
||||
*
|
||||
* @param BlockTransaction $tx Blocks to be set should be added to this transaction (do not modify thr world directly)
|
||||
* @param Item $item Item used to place the block
|
||||
* @param Block $blockReplace Block expected to be replaced
|
||||
* @param Block $blockClicked Block that was clicked using the item
|
||||
* @param int $face Face of the clicked block which was clicked
|
||||
* @param Vector3 $clickVector Exact position inside the clicked block where the click occurred, relative to the block's position
|
||||
* @param Player|null $player Player who placed the block, or null if it was not a player
|
||||
*
|
||||
* @return bool whether the placement should go ahead
|
||||
*/
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
@ -324,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();
|
||||
@ -372,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;
|
||||
}
|
||||
|
||||
@ -467,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);
|
||||
}
|
||||
@ -509,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;
|
||||
}
|
||||
|
||||
@ -563,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.
|
||||
@ -656,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() . ")";
|
||||
}
|
||||
|
||||
/**
|
||||
@ -715,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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
59
src/block/BlockIdentifierFlattened.php
Normal file
59
src/block/BlockIdentifierFlattened.php
Normal 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];
|
||||
}
|
||||
}
|
@ -24,266 +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\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(TreeType $treeType) : BID{
|
||||
return new BID(match($treeType->id()){
|
||||
TreeType::OAK()->id() => Ids::OAK_LEAVES,
|
||||
TreeType::SPRUCE()->id() => Ids::SPRUCE_LEAVES,
|
||||
TreeType::BIRCH()->id() => Ids::BIRCH_LEAVES,
|
||||
TreeType::JUNGLE()->id() => Ids::JUNGLE_LEAVES,
|
||||
TreeType::ACACIA()->id() => Ids::ACACIA_LEAVES,
|
||||
TreeType::DARK_OAK()->id() => Ids::DARK_OAK_LEAVES,
|
||||
default => throw new AssumptionFailedError("All tree 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);
|
||||
}
|
||||
}
|
||||
|
501
src/block/BlockLegacyIds.php
Normal file
501
src/block/BlockLegacyIds.php
Normal 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;
|
||||
|
||||
}
|
303
src/block/BlockLegacyMetadata.php
Normal file
303
src/block/BlockLegacyMetadata.php
Normal 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;
|
||||
}
|
@ -1,720 +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 FIRST_UNUSED_BLOCK_ID = 10682;
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
@ -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]); }
|
||||
}
|
@ -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";
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -26,8 +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\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Axis;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
@ -44,10 +42,33 @@ class BrewingStand extends Transparent{
|
||||
*/
|
||||
protected array $slots = [];
|
||||
|
||||
public function getRequiredStateDataBits() : int{ return 3; }
|
||||
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;
|
||||
}
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $w) : void{
|
||||
$w->brewingStandSlots($this->slots);
|
||||
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{
|
||||
@ -97,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())){
|
||||
|
@ -24,8 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\AnyFacingTrait;
|
||||
use pocketmine\data\runtime\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
use pocketmine\block\utils\BlockDataSerializer;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
@ -39,11 +38,18 @@ abstract class Button extends Flowable{
|
||||
|
||||
protected bool $pressed = false;
|
||||
|
||||
public function getRequiredStateDataBits() : int{ return 4; }
|
||||
protected function writeStateToMeta() : int{
|
||||
return BlockDataSerializer::writeFacing($this->facing) | ($this->pressed ? BlockLegacyMetadata::BUTTON_FLAG_POWERED : 0);
|
||||
}
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $w) : void{
|
||||
$w->facing($this->facing);
|
||||
$w->bool($this->pressed);
|
||||
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; }
|
||||
@ -55,7 +61,7 @@ abstract class Button extends Flowable{
|
||||
}
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($this->canBeSupportedBy($blockClicked, $face)){
|
||||
if($this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face)){
|
||||
$this->facing = $face;
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
@ -64,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();
|
||||
|
@ -23,9 +23,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\BlockDataSerializer;
|
||||
use pocketmine\block\utils\SupportType;
|
||||
use pocketmine\data\runtime\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\event\block\BlockGrowEvent;
|
||||
use pocketmine\event\entity\EntityDamageByBlockEvent;
|
||||
@ -42,10 +41,16 @@ class Cactus extends Transparent{
|
||||
|
||||
protected int $age = 0;
|
||||
|
||||
public function getRequiredStateDataBits() : int{ return 4; }
|
||||
protected function writeStateToMeta() : int{
|
||||
return $this->age;
|
||||
}
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $w) : void{
|
||||
$w->boundedInt(4, 0, self::MAX_AGE, $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; }
|
||||
@ -81,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){
|
||||
@ -113,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()){
|
||||
@ -134,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;
|
||||
|
@ -23,24 +23,33 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\data\runtime\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
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;
|
||||
|
||||
public function getRequiredStateDataBits() : int{ return 3; }
|
||||
protected function writeStateToMeta() : int{
|
||||
return $this->bites;
|
||||
}
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $w) : void{
|
||||
$w->boundedInt(3, 0, self::MAX_BITES, $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;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -55,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 */
|
||||
@ -66,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){
|
||||
@ -94,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());
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -1,131 +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\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Axis;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
|
||||
class Candle extends Transparent{
|
||||
use CandleTrait {
|
||||
describeState as encodeLitState;
|
||||
getLightLevel as getBaseLightLevel;
|
||||
}
|
||||
|
||||
public const MIN_COUNT = 1;
|
||||
public const MAX_COUNT = 4;
|
||||
|
||||
private int $count = self::MIN_COUNT;
|
||||
|
||||
public function getRequiredStateDataBits() : int{
|
||||
return 3;
|
||||
}
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $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)];
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ class Carrot extends Crops{
|
||||
];
|
||||
}
|
||||
|
||||
public function asItem() : Item{
|
||||
public function getPickedItem(bool $addUserData = false) : Item{
|
||||
return VanillaItems::CARROT();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -1,236 +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\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
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;
|
||||
|
||||
public function getRequiredStateDataBits() : int{ return 3; }
|
||||
|
||||
protected function describeState(RuntimeDataWriter|RuntimeDataReader $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));
|
||||
}
|
||||
}
|
||||
}
|
@ -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 [];
|
||||
}
|
||||
}
|
@ -23,11 +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\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
use pocketmine\block\utils\TreeType;
|
||||
use pocketmine\event\block\BlockGrowEvent;
|
||||
use pocketmine\item\Fertilizer;
|
||||
use pocketmine\item\Item;
|
||||
@ -47,11 +46,17 @@ class CocoaBlock extends Transparent{
|
||||
|
||||
protected int $age = 0;
|
||||
|
||||
public function getRequiredStateDataBits() : int{ return 4; }
|
||||
protected function writeStateToMeta() : int{
|
||||
return BlockDataSerializer::writeLegacyHorizontalFacing(Facing::opposite($this->facing)) | ($this->age << 2);
|
||||
}
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $w) : void{
|
||||
$w->horizontalFacing($this->facing);
|
||||
$w->boundedInt(2, 0, self::MAX_AGE, $this->age);
|
||||
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; }
|
||||
@ -84,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{
|
||||
@ -96,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();
|
||||
|
||||
@ -142,7 +147,7 @@ class CocoaBlock extends Transparent{
|
||||
];
|
||||
}
|
||||
|
||||
public function asItem() : Item{
|
||||
public function getPickedItem(bool $addUserData = false) : Item{
|
||||
return VanillaItems::COCOA_BEANS();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
@ -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; }
|
||||
}
|
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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{
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -23,8 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\data\runtime\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
use pocketmine\block\utils\BlockDataSerializer;
|
||||
use pocketmine\event\block\BlockGrowEvent;
|
||||
use pocketmine\item\Fertilizer;
|
||||
use pocketmine\item\Item;
|
||||
@ -39,10 +38,16 @@ abstract class Crops extends Flowable{
|
||||
|
||||
protected int $age = 0;
|
||||
|
||||
public function getRequiredStateDataBits() : int{ return 3; }
|
||||
protected function writeStateToMeta() : int{
|
||||
return $this->age;
|
||||
}
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $w) : void{
|
||||
$w->boundedInt(3, 0, self::MAX_AGE, $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; }
|
||||
@ -57,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);
|
||||
@ -86,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);
|
||||
}
|
||||
}
|
||||
|
@ -24,9 +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\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
@ -40,13 +39,30 @@ use const M_PI;
|
||||
class DaylightSensor extends Transparent{
|
||||
use AnalogRedstoneSignalEmitterTrait;
|
||||
|
||||
protected BlockIdentifierFlattened $idInfoFlattened;
|
||||
|
||||
protected bool $inverted = false;
|
||||
|
||||
public function getRequiredStateDataBits() : int{ return 5; }
|
||||
public function __construct(BlockIdentifierFlattened $idInfo, string $name, BlockBreakInfo $breakInfo){
|
||||
$this->idInfoFlattened = $idInfo;
|
||||
parent::__construct($idInfo, $name, $breakInfo);
|
||||
}
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $w) : void{
|
||||
$w->boundedInt(4, 0, 15, $this->signalStrength);
|
||||
$w->bool($this->inverted);
|
||||
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{
|
||||
@ -76,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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -23,19 +23,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\data\runtime\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
|
||||
class DetectorRail extends StraightOnlyRail{
|
||||
protected bool $activated = false;
|
||||
|
||||
public function getRequiredStateDataBits() : int{ return 4; }
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $w) : void{
|
||||
parent::describeState($w);
|
||||
$w->bool($this->activated);
|
||||
}
|
||||
|
||||
public function isActivated() : bool{ return $this->activated; }
|
||||
|
||||
/** @return $this */
|
||||
@ -43,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
|
||||
}
|
||||
|
@ -23,70 +23,50 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\DirtType;
|
||||
use pocketmine\data\runtime\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
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;
|
||||
}
|
||||
|
||||
public function getRequiredTypeDataBits() : int{ return 2; }
|
||||
|
||||
protected function describeType(RuntimeDataReader|RuntimeDataWriter $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;
|
||||
}
|
||||
|
||||
|
@ -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\PoweredByRedstoneTrait;
|
||||
use pocketmine\block\utils\SupportType;
|
||||
use pocketmine\data\runtime\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
@ -37,21 +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;
|
||||
|
||||
public function getRequiredStateDataBits() : int{ return 5; }
|
||||
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);
|
||||
}
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $w) : void{
|
||||
$w->horizontalFacing($this->facing);
|
||||
$w->bool($this->top);
|
||||
$w->bool($this->hingeRight);
|
||||
$w->bool($this->open);
|
||||
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
|
||||
@ -62,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; }
|
||||
@ -143,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);
|
||||
|
@ -23,8 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\data\runtime\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
@ -32,12 +30,19 @@ use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
|
||||
class DoublePlant extends Flowable{
|
||||
|
||||
protected bool $top = false;
|
||||
|
||||
public function getRequiredStateDataBits() : int{ return 1; }
|
||||
protected function writeStateToMeta() : int{
|
||||
return ($this->top ? BlockLegacyMetadata::DOUBLE_PLANT_FLAG_TOP : 0);
|
||||
}
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $w) : void{
|
||||
$w->bool($this->top);
|
||||
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; }
|
||||
@ -49,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);
|
||||
@ -74,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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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{
|
||||
|
@ -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
|
||||
|
||||
|
@ -23,10 +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\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
|
||||
@ -36,11 +35,17 @@ class EndPortalFrame extends Opaque{
|
||||
|
||||
protected bool $eye = false;
|
||||
|
||||
public function getRequiredStateDataBits() : int{ return 3; }
|
||||
protected function writeStateToMeta() : int{
|
||||
return BlockDataSerializer::writeLegacyHorizontalFacing($this->facing) | ($this->eye ? BlockLegacyMetadata::END_PORTAL_FRAME_FLAG_EYE : 0);
|
||||
}
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $w) : void{
|
||||
$w->horizontalFacing($this->facing);
|
||||
$w->bool($this->eye);
|
||||
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; }
|
||||
|
@ -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){
|
||||
|
@ -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()){
|
||||
|
@ -23,8 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\data\runtime\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
use pocketmine\block\utils\BlockDataSerializer;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\entity\Living;
|
||||
use pocketmine\event\entity\EntityTrampleFarmlandEvent;
|
||||
@ -38,10 +37,16 @@ class Farmland extends Transparent{
|
||||
|
||||
protected int $wetness = 0; //"moisture" blockstate property in PC
|
||||
|
||||
public function getRequiredStateDataBits() : int{ return 3; }
|
||||
protected function writeStateToMeta() : int{
|
||||
return $this->wetness;
|
||||
}
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $w) : void{
|
||||
$w->boundedInt(3, 0, self::MAX_WETNESS, $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; }
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -23,11 +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\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
@ -37,18 +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;
|
||||
|
||||
public function getRequiredStateDataBits() : int{ return 4; }
|
||||
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);
|
||||
}
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $w) : void{
|
||||
$w->horizontalFacing($this->facing);
|
||||
$w->bool($this->open);
|
||||
$w->bool($this->inWall);
|
||||
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; }
|
||||
@ -103,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();
|
||||
@ -119,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;
|
||||
}
|
||||
}
|
||||
|
@ -1,132 +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\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
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;
|
||||
|
||||
public function getRequiredStateDataBits() : int{
|
||||
return 3;
|
||||
}
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $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();
|
||||
}
|
||||
}
|
@ -23,10 +23,15 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\data\runtime\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
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;
|
||||
@ -35,15 +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;
|
||||
|
||||
public function getRequiredStateDataBits() : int{ return 4; }
|
||||
protected function writeStateToMeta() : int{
|
||||
return $this->age;
|
||||
}
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $w) : void{
|
||||
$w->boundedInt(4, 0, self::MAX_AGE, $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; }
|
||||
@ -57,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));
|
||||
@ -192,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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -23,10 +23,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\data\runtime\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
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;
|
||||
@ -36,12 +37,49 @@ use function atan2;
|
||||
use function rad2deg;
|
||||
|
||||
final class FloorCoralFan extends BaseCoral{
|
||||
|
||||
protected BlockIdentifierFlattened $idInfoFlattened;
|
||||
|
||||
private int $axis = Axis::X;
|
||||
|
||||
public function getRequiredStateDataBits() : int{ return parent::getRequiredStateDataBits() + 1; }
|
||||
public function __construct(BlockIdentifierFlattened $idInfo, string $name, BlockBreakInfo $breakInfo){
|
||||
$this->idInfoFlattened = $idInfo;
|
||||
parent::__construct($idInfo, $name, $breakInfo);
|
||||
}
|
||||
|
||||
protected function describeState(RuntimeDataReader|RuntimeDataWriter $w) : void{
|
||||
$w->horizontalAxis($this->axis);
|
||||
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; }
|
||||
@ -70,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);
|
||||
}
|
||||
|
||||
@ -89,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);
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user