Merge branch 'stable' into next-minor

This commit is contained in:
Dylan K. Taylor 2020-02-10 11:40:08 +00:00
commit f08e411cad
539 changed files with 3706 additions and 6211 deletions

6
.gitmodules vendored
View File

@ -7,9 +7,9 @@
[submodule "tests/plugins/PocketMine-DevTools"]
path = tests/plugins/PocketMine-DevTools
url = https://github.com/pmmp/PocketMine-DevTools.git
[submodule "src/pocketmine/resources/vanilla"]
path = src/pocketmine/resources/vanilla
url = https://github.com/pmmp/BedrockData.git
[submodule "build/php"]
path = build/php
url = https://github.com/pmmp/php-build-scripts.git
[submodule "src/pocketmine/resources/vanilla"]
path = src/pocketmine/resources/vanilla
url = https://github.com/pmmp/BedrockData.git

View File

@ -5,6 +5,7 @@ php:
- 7.3
before_script:
- phpenv config-rm xdebug.ini
# - pecl install channel://pecl.php.net/pthreads-3.1.6
- echo | pecl install channel://pecl.php.net/yaml-2.0.4
- git clone https://github.com/pmmp/pthreads.git
@ -16,10 +17,18 @@ before_script:
- make install
- cd ..
- echo "extension=pthreads.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
- composer install
script:
- composer install --prefer-dist
- ./vendor/bin/phpstan analyze --no-progress --memory-limit=2G
- ./vendor/bin/phpunit --bootstrap vendor/autoload.php --fail-on-warning tests/phpunit
- composer install --no-dev --prefer-dist
- ./tests/travis.sh -t4
cache:
directories:
- $HOME/.composer/cache/files
- $HOME/.composer/cache/vcs
notifications:
email: false

38
BUILDING.md Normal file
View File

@ -0,0 +1,38 @@
# Building
## Pre-requisites
- A bash shell (git bash is sufficient for Windows)
- [`git`](https://git-scm.com) available in your shell
- PHP 7.2 or newer available in your shell
- [`composer`](https://getcomposer.org) available in your shell
## Custom PHP binaries
Because PocketMine-MP requires several non-standard PHP extensions and configuration, PMMP provides scripts to build custom binaries for running PocketMine-MP, as well as prebuilt binaries.
- [Prebuilt binaries](https://jenkins.pmmp.io/job/PHP-7.3-Aggregate)
- [Compile scripts](https://github.com/pmmp/php-build-scripts) are provided as a submodule in the path `build/php`
If you use a custom binary, you'll need to replace `composer` usages in this guide with `path/to/your/php path/to/your/composer.phar`.
## Setting up environment
1. `git clone --recursive https://github.com/pmmp/PocketMine-MP.git`
2. `composer install`
## Checking out a different branch to build
1. `git checkout <branch to checkout>`
2. `git submodule update --init`
3. Re-run `composer install` to synchronize dependencies.
## Optimizing for release builds
1. Add the flags `--no-dev --classmap-authoritative` to your `composer install` command. This will reduce build size and improve autoloading speed.
2. Preprocess the source code by running `build/preprocessor/PreProcessor.php`. Usage instructions are provided in `build/preprocessor/README.md`.
### Note
Preprocessor requires that the `cpp` (c preprocessor) is available in your PATH.
## Building `PocketMine-MP.phar`
Run `build/server.phar` using your preferred PHP binary. It'll drop a `PocketMine-MP.phar` into the current working directory.
You can also use the `--out` option to change the output filename.
## Running PocketMine-MP from source code
Run `src/pocketmine/PocketMine.php` using your preferred PHP binary.

View File

@ -13,10 +13,11 @@
## Discussion/Help
- [Forums](https://forums.pmmp.io/)
- [Community Discord](https://discord.gg/bmSAZBG)
- [Discord](https://discord.gg/bmSAZBG)
- [StackOverflow](https://stackoverflow.com/tags/pocketmine)
## For developers
* [Building and running from source](BUILDING.md)
* [Latest API documentation](https://jenkins.pmmp.io/job/PocketMine-MP-doc/doxygen/) - Doxygen documentation generated from development
* [DevTools](https://github.com/pmmp/PocketMine-DevTools/) - Development tools plugin for creating plugins
* [ExamplePlugin](https://github.com/pmmp/ExamplePlugin/) - Example plugin demonstrating some basic API features

View File

@ -21,14 +21,13 @@
declare(strict_types=1);
namespace pocketmine\build_script;
namespace pocketmine\build\make_release;
use pocketmine\utils\VersionString;
use function dirname;
use function fgets;
use function file_get_contents;
use function file_put_contents;
use function preg_quote;
use function preg_replace;
use function sleep;
use function sprintf;
@ -36,20 +35,8 @@ use function system;
use const pocketmine\BASE_VERSION;
use const STDIN;
require_once dirname(__DIR__) . '/src/pocketmine/VersionInfo.php';
require_once dirname(__DIR__) . '/vendor/autoload.php';
if(isset($argv[1])){
$currentVer = new VersionString($argv[1]);
}else{
$currentVer = new VersionString(BASE_VERSION);
}
$nextVer = new VersionString(sprintf(
"%u.%u.%u",
$currentVer->getMajor(),
$currentVer->getMinor(),
$currentVer->getPatch() + 1
));
function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev) : void{
$versionInfo = file_get_contents($versionInfoPath);
@ -60,22 +47,45 @@ function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev
);
$versionInfo = preg_replace(
'/^const IS_DEVELOPMENT_BUILD = (?:true|false);$/m',
'const IS_DEVELOPMENT_BUILD = ' . ($isDev ? 'true' : 'false'). ';',
'const IS_DEVELOPMENT_BUILD = ' . ($isDev ? 'true' : 'false') . ';',
$versionInfo
);
file_put_contents($versionInfoPath, $versionInfo);
}
$versionInfoPath = dirname(__DIR__) . '/src/pocketmine/VersionInfo.php';
replaceVersion($versionInfoPath, $currentVer->getBaseVersion(), false);
echo "please add appropriate notes to the changelog and press enter...";
fgets(STDIN);
system('git add "' . dirname(__DIR__) . '/changelogs"');
system('git commit -m "Release ' . $currentVer->getBaseVersion() . '" --include "' . $versionInfoPath . '"');
system('git tag ' . $currentVer->getBaseVersion());
replaceVersion($versionInfoPath, $nextVer->getBaseVersion(), true);
system('git add "' . $versionInfoPath . '"');
system('git commit -m "' . $nextVer->getBaseVersion() . ' is next" --include "' . $versionInfoPath . '"');
echo "pushing changes in 5 seconds\n";
sleep(5);
system('git push origin HEAD ' . $currentVer->getBaseVersion());
/**
* @param string[] $argv
* @phpstan-param list<string> $argv
*/
function main(array $argv) : void{
if(isset($argv[1])){
$currentVer = new VersionString($argv[1]);
}else{
$currentVer = new VersionString(BASE_VERSION);
}
$nextVer = new VersionString(sprintf(
"%u.%u.%u",
$currentVer->getMajor(),
$currentVer->getMinor(),
$currentVer->getPatch() + 1
));
$versionInfoPath = dirname(__DIR__) . '/src/pocketmine/VersionInfo.php';
replaceVersion($versionInfoPath, $currentVer->getBaseVersion(), false);
echo "please add appropriate notes to the changelog and press enter...";
fgets(STDIN);
system('git add "' . dirname(__DIR__) . '/changelogs"');
system('git commit -m "Release ' . $currentVer->getBaseVersion() . '" --include "' . $versionInfoPath . '"');
system('git tag ' . $currentVer->getBaseVersion());
replaceVersion($versionInfoPath, $nextVer->getBaseVersion(), true);
system('git add "' . $versionInfoPath . '"');
system('git commit -m "' . $nextVer->getBaseVersion() . ' is next" --include "' . $versionInfoPath . '"');
echo "pushing changes in 5 seconds\n";
sleep(5);
system('git push origin HEAD ' . $currentVer->getBaseVersion());
}
if(!defined('pocketmine\_PHPSTAN_ANALYSIS')){
main($argv);
}

170
build/server-phar.php Normal file
View File

@ -0,0 +1,170 @@
<?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\server_phar;
use pocketmine\utils\Git;
use function array_map;
use function count;
use function defined;
use function dirname;
use function file_exists;
use function getcwd;
use function getopt;
use function implode;
use function ini_get;
use function microtime;
use function preg_quote;
use function realpath;
use function round;
use function rtrim;
use function sprintf;
use function str_replace;
use function unlink;
require dirname(__DIR__) . '/vendor/autoload.php';
/**
* @param string[] $strings
*
* @return string[]
*/
function preg_quote_array(array $strings, string $delim = null) : array{
return array_map(function(string $str) use ($delim) : string{ return preg_quote($str, $delim); }, $strings);
}
/**
* @param string[] $includedPaths
* @param mixed[] $metadata
* @phpstan-param array<string, mixed> $metadata
*
* @return \Generator|string[]
*/
function buildPhar(string $pharPath, string $basePath, array $includedPaths, array $metadata, string $stub, int $signatureAlgo = \Phar::SHA1, ?int $compression = null){
$basePath = rtrim(str_replace("/", DIRECTORY_SEPARATOR, $basePath), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
$includedPaths = array_map(function(string $path) : string{
return rtrim(str_replace("/", DIRECTORY_SEPARATOR, $path), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
}, $includedPaths);
yield "Creating output file $pharPath";
if(file_exists($pharPath)){
yield "Phar file already exists, overwriting...";
try{
\Phar::unlinkArchive($pharPath);
}catch(\PharException $e){
//unlinkArchive() doesn't like dodgy phars
unlink($pharPath);
}
}
yield "Adding files...";
$start = microtime(true);
$phar = new \Phar($pharPath);
$phar->setMetadata($metadata);
$phar->setStub($stub);
$phar->setSignatureAlgorithm($signatureAlgo);
$phar->startBuffering();
//If paths contain any of these, they will be excluded
$excludedSubstrings = preg_quote_array([
realpath($pharPath), //don't add the phar to itself
], '/');
$folderPatterns = preg_quote_array([
DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR,
DIRECTORY_SEPARATOR . '.' //"Hidden" files, git dirs etc
], '/');
//Only exclude these within the basedir, otherwise the project won't get built if it itself is in a directory that matches these patterns
$basePattern = preg_quote(rtrim($basePath, DIRECTORY_SEPARATOR), '/');
foreach($folderPatterns as $p){
$excludedSubstrings[] = $basePattern . '.*' . $p;
}
$regex = sprintf('/^(?!.*(%s))^%s(%s).*/i',
implode('|', $excludedSubstrings), //String may not contain any of these substrings
preg_quote($basePath, '/'), //String must start with this path...
implode('|', preg_quote_array($includedPaths, '/')) //... and must be followed by one of these relative paths, if any were specified. If none, this will produce a null capturing group which will allow anything.
);
$directory = new \RecursiveDirectoryIterator($basePath, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS | \FilesystemIterator::CURRENT_AS_PATHNAME); //can't use fileinfo because of symlinks
$iterator = new \RecursiveIteratorIterator($directory);
$regexIterator = new \RegexIterator($iterator, $regex);
$count = count($phar->buildFromIterator($regexIterator, $basePath));
yield "Added $count files";
if($compression !== null){
yield "Compressing files...";
$phar->compressFiles($compression);
yield "Finished compression";
}
$phar->stopBuffering();
yield "Done in " . round(microtime(true) - $start, 3) . "s";
}
function main() : void{
if(ini_get("phar.readonly") == 1){
echo "Set phar.readonly to 0 with -dphar.readonly=0" . PHP_EOL;
exit(1);
}
$opts = getopt("", ["out:"]);
$gitHash = Git::getRepositoryStatePretty(dirname(__DIR__));
echo "Git hash detected as $gitHash" . PHP_EOL;
foreach(buildPhar(
$opts["out"] ?? getcwd() . DIRECTORY_SEPARATOR . "PocketMine-MP.phar",
dirname(__DIR__) . DIRECTORY_SEPARATOR,
[
'src',
'vendor'
],
[
'git' => $gitHash
],
<<<'STUB'
<?php
$tmpDir = sys_get_temp_dir();
if(!is_readable($tmpDir) or !is_writable($tmpDir)){
echo "ERROR: tmpdir $tmpDir is not accessible." . PHP_EOL;
echo "Check that the directory exists, and that the current user has read/write permissions for it." . PHP_EOL;
echo "Alternatively, set 'sys_temp_dir' to a different directory in your php.ini file." . PHP_EOL;
exit(1);
}
require("phar://" . __FILE__ . "/src/pocketmine/PocketMine.php");
__HALT_COMPILER();
STUB
,
\Phar::SHA1,
\Phar::GZ
) as $line){
echo $line . PHP_EOL;
}
}
if(!defined('pocketmine\_PHPSTAN_ANALYSIS')){
main();
}

View File

@ -11,4 +11,58 @@ Plugin developers should **only** update their required API to this version if y
- Removed compatibility with 1.13.0
# 3.11.1
- Fixed blocks with incorrect properties when placed or interacted with.
- Fixed blocks with incorrect properties when placed or interacted with.
# 3.11.2
## Core
- PHPStan 0.12.3 with level 5 is now used for automated static analysis.
- Fixed a possible crash when plugins override the `EnderChest` tile class with something incompatible.
- Fixed disconnected players being considered as never played.
- Fixed enchantments with IDs outside the range 0-255 in item NBT crashing the server.
- Fixed particles rendering incorrectly.
- Timings handlers are no longer able to underflow; they now throw exceptions when attempting to be stopped more times than they were started.
- Fixed explosion rays getting stuck in empty subchunks (possible incorrect behaviour in large caves).
- Fixed bad tile/entity NBT data being propagated from world providers in some cases.
- Fixed a possible crash when detecting timezone on CentOS.
- Fixed many cases of incorrectly documented types in the API found by PHPStan.
- Generation tasks no longer assume that generator instances stored in TLS are always valid, fixing a possible crash.
## Protocol
- Fixed skin animation image corruption in LoginPacket handling caused by incorrect data handling.
- Fixed skin animation extra data not being decoded from LoginPacket.
- `SkinImage` now throws `InvalidArgumentException` if it receives an unexpected amount of bytes for the given image heigh/width.
- Fixed broken code in `PlayerAuthInputPacket::create()`.
- Removed some dead constants from `NetworkInventoryAction`.
# 3.11.3
- Fixed some PHPStan false-positives in release builds.
- Git hash is now correctly detected for source builds when the working directory is not the repository root.
- Added a specialized build script `build/server-phar.php` for creating server phars.
- Fixed timings crashing the server.
- Timings chains now work correctly.
- Fixed some minor timing errors in chained timings.
- Forcing resource packs no longer causes removal of client-sided resource packs. If this behaviour is desired, use a vanilla resource pack at the bottom of your resource stack (as was necessary for non-forced packs).
- Added documentation to the API to clarify that effect durations are in ticks.
# 3.11.4
- Fixed performance issue in leaf decay.
- Fixed entity position desync when entities stop moving, but still have velocity on the client.
- Fixed a crash when encountering truncated `level.dat` files in LevelDB worlds.
- Core code is now analyzed using PHPStan level 6.
- The core constants `pocketmine\PATH` and `pocketmine\RESOURCE_PATH` are now unconditionally available when including the Composer autoloader.
- Populate type information in lots of places where it was previously missing; this will improve the quality of static analysis for plugins.
- `MainLogger::logException()` now logs previous exceptions recursively.
- `MainLogger::logException()` now always logs exceptions as `critical`.
# 3.11.5
- PHPStan and PHPUnit are now managed as Composer dev dependencies.
- Core code is now analyzed using PHPStan level 6 (full, including iterable types checking).
- Improved type information available to PHPStan in many areas.
- Mass-removal of useless PHPDoc.
- Fixed incorrect documentation of `Internet::getURL()`, `Internet::postURL()` and `Internet::simpleCurl()`.
- Fixed crash on use of case-mismatched recursive command aliases.
- Basic build instructions are now provided in `BUILDING.md`.
- `build/server-phar.php` now uses GZIP compression on created phars, providing a 75% size reduction.
- `ClientboundMapItemDataPacket` now uses `MapDecoration` objects for decorations instead of associative arrays.
- Updated Composer dependencies to get bug fixes in `pocketmine/nbt` and other libraries.
- Packages `pocketmine/classloader` and `pocketmine/log` are now required; these provide classes previously part of `pocketmine/spl`. This change has no effect on API compatibility.

View File

@ -24,20 +24,29 @@
"ext-yaml": ">=2.0.0",
"ext-zip": "*",
"ext-zlib": ">=1.2.11",
"pocketmine/raklib": "^0.12.5",
"pocketmine/spl": "^0.3.0",
"pocketmine/raklib": "^0.12.7",
"pocketmine/spl": "^0.4.0",
"pocketmine/binaryutils": "^0.1.9",
"pocketmine/nbt": "^0.2.10",
"pocketmine/math": "^0.2.0",
"pocketmine/snooze": "^0.1.0",
"pocketmine/classloader": "^0.1.0",
"pocketmine/log": "^0.1.0",
"daverandom/callback-validator": "dev-master",
"adhocore/json-comment": "^0.0.7"
"adhocore/json-comment": "^0.1.0"
},
"require-dev": {
"phpstan/phpstan": "^0.12.9",
"irstea/phpunit-shim": "^8.5",
"phpstan/phpstan-phpunit": "^0.12.6",
"phpstan/phpstan-strict-rules": "^0.12.2"
},
"autoload": {
"psr-4": {
"": ["src"]
},
"files": [
"src/pocketmine/CoreConstants.php",
"src/pocketmine/GlobalConstants.php",
"src/pocketmine/VersionInfo.php"
]
@ -46,31 +55,5 @@
"psr-4": {
"pocketmine\\": "tests/phpunit/"
}
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/pmmp/RakLib"
},
{
"type": "vcs",
"url": "https://github.com/pmmp/SPL"
},
{
"type": "vcs",
"url": "https://github.com/pmmp/BinaryUtils"
},
{
"type": "vcs",
"url": "https://github.com/pmmp/NBT"
},
{
"type": "vcs",
"url": "https://github.com/pmmp/Math"
},
{
"type": "vcs",
"url": "https://github.com/pmmp/Snooze"
}
]
}
}

414
composer.lock generated
View File

@ -4,27 +4,27 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "377d9e0ab5f1a9a4ef9b664706d26f5b",
"content-hash": "e22866a7924c444da73ff31b831b30cb",
"packages": [
{
"name": "adhocore/json-comment",
"version": "v0.0.7",
"version": "0.1.0",
"source": {
"type": "git",
"url": "https://github.com/adhocore/php-json-comment.git",
"reference": "135356c7e7336ef59924f1d921c770045f937a76"
"reference": "8448076039389f558f39ad0553aab87db3f81614"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/adhocore/php-json-comment/zipball/135356c7e7336ef59924f1d921c770045f937a76",
"reference": "135356c7e7336ef59924f1d921c770045f937a76",
"url": "https://api.github.com/repos/adhocore/php-json-comment/zipball/8448076039389f558f39ad0553aab87db3f81614",
"reference": "8448076039389f558f39ad0553aab87db3f81614",
"shasum": ""
},
"require": {
"php": ">=5.4"
},
"require-dev": {
"phpunit/phpunit": "^4.8 || ^5.7 || ^6.5"
"phpunit/phpunit": "^6.5 || ^7.5"
},
"type": "library",
"autoload": {
@ -48,7 +48,7 @@
"json",
"strip-comment"
],
"time": "2018-08-01T12:27:26+00:00"
"time": "2020-01-03T13:51:23+00:00"
},
{
"name": "daverandom/callback-validator",
@ -92,84 +92,159 @@
},
{
"name": "pocketmine/binaryutils",
"version": "0.1.10",
"version": "0.1.11",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BinaryUtils.git",
"reference": "435f2ee265bce75ef1aa9563f9b60ff36d705e80"
"reference": "e8cb65db1b7998eebb739b124f2a989fe87366eb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BinaryUtils/zipball/435f2ee265bce75ef1aa9563f9b60ff36d705e80",
"reference": "435f2ee265bce75ef1aa9563f9b60ff36d705e80",
"url": "https://api.github.com/repos/pmmp/BinaryUtils/zipball/e8cb65db1b7998eebb739b124f2a989fe87366eb",
"reference": "e8cb65db1b7998eebb739b124f2a989fe87366eb",
"shasum": ""
},
"require": {
"php": ">=7.2",
"php-64bit": "*"
},
"require-dev": {
"phpstan/phpstan": "^0.12.8"
},
"type": "library",
"autoload": {
"psr-4": {
"pocketmine\\utils\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-3.0"
],
"description": "Classes and methods for conveniently handling binary data",
"support": {
"source": "https://github.com/pmmp/BinaryUtils/tree/0.1.10",
"issues": "https://github.com/pmmp/BinaryUtils/issues"
},
"time": "2019-10-21T14:40:32+00:00"
"time": "2020-01-28T12:09:56+00:00"
},
{
"name": "pocketmine/math",
"version": "0.2.3",
"name": "pocketmine/classloader",
"version": "0.1.0",
"source": {
"type": "git",
"url": "https://github.com/pmmp/Math.git",
"reference": "68be8a79fd0169043ef514797c304517cb8a6071"
"url": "https://github.com/pmmp/ClassLoader.git",
"reference": "4ccdb30e48f030bfcad04bb0a208d198ec631993"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/Math/zipball/68be8a79fd0169043ef514797c304517cb8a6071",
"reference": "68be8a79fd0169043ef514797c304517cb8a6071",
"url": "https://api.github.com/repos/pmmp/ClassLoader/zipball/4ccdb30e48f030bfcad04bb0a208d198ec631993",
"reference": "4ccdb30e48f030bfcad04bb0a208d198ec631993",
"shasum": ""
},
"require": {
"ext-pthreads": "~3.2.0",
"ext-reflection": "*",
"php": ">=7.2.0"
},
"conflict": {
"pocketmine/spl": "<0.4"
},
"require-dev": {
"phpstan/phpstan": "^0.12.8"
},
"type": "library",
"autoload": {
"classmap": [
"./src"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-3.0"
],
"description": "Ad-hoc autoloading components used by PocketMine-MP",
"time": "2020-01-31T14:25:52+00:00"
},
{
"name": "pocketmine/log",
"version": "0.1.0",
"source": {
"type": "git",
"url": "https://github.com/pmmp/Log.git",
"reference": "62c1f0ea5a5c0ae4b308f9bd231fb11638ff866e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/Log/zipball/62c1f0ea5a5c0ae4b308f9bd231fb11638ff866e",
"reference": "62c1f0ea5a5c0ae4b308f9bd231fb11638ff866e",
"shasum": ""
},
"require": {
"ext-pthreads": "~3.2.0",
"php": ">=7.2"
},
"conflict": {
"pocketmine/spl": "<0.4"
},
"require-dev": {
"phpstan/phpstan": "^0.12.8"
},
"type": "library",
"autoload": {
"classmap": [
"./src"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-3.0"
],
"description": "Logging components used by PocketMine-MP and related projects",
"time": "2020-01-31T14:31:47+00:00"
},
{
"name": "pocketmine/math",
"version": "0.2.4",
"source": {
"type": "git",
"url": "https://github.com/pmmp/Math.git",
"reference": "b1c28b236df8b795d7b06cf8421f9962b12ac410"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/Math/zipball/b1c28b236df8b795d7b06cf8421f9962b12ac410",
"reference": "b1c28b236df8b795d7b06cf8421f9962b12ac410",
"shasum": ""
},
"require": {
"php": ">=7.2.0",
"php-64bit": "*"
},
"require-dev": {
"phpstan/phpstan": "^0.12.8"
},
"type": "library",
"autoload": {
"psr-4": {
"pocketmine\\math\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-3.0"
],
"description": "PHP library containing math related code used in PocketMine-MP",
"support": {
"source": "https://github.com/pmmp/Math/tree/0.2.3",
"issues": "https://github.com/pmmp/Math/issues"
},
"time": "2019-10-21T14:35:10+00:00"
"time": "2020-01-28T14:11:54+00:00"
},
{
"name": "pocketmine/nbt",
"version": "0.2.12",
"version": "0.2.13",
"source": {
"type": "git",
"url": "https://github.com/pmmp/NBT.git",
"reference": "b5777265329753b74dd40bb105eedabeefb98724"
"reference": "6fc56f864a5375471f6e2d0f9f89f2462a1d8433"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/NBT/zipball/b5777265329753b74dd40bb105eedabeefb98724",
"reference": "b5777265329753b74dd40bb105eedabeefb98724",
"url": "https://api.github.com/repos/pmmp/NBT/zipball/6fc56f864a5375471f6e2d0f9f89f2462a1d8433",
"reference": "6fc56f864a5375471f6e2d0f9f89f2462a1d8433",
"shasum": ""
},
"require": {
@ -178,39 +253,35 @@
"php-64bit": "*",
"pocketmine/binaryutils": "^0.1.9"
},
"require-dev": {
"irstea/phpunit-shim": "^7.5",
"phpstan/phpstan": "^0.12.8"
},
"type": "library",
"autoload": {
"psr-4": {
"pocketmine\\nbt\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"pocketmine\\nbt\\": "tests/phpunit/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-3.0"
],
"description": "PHP library for working with Named Binary Tags",
"support": {
"source": "https://github.com/pmmp/NBT/tree/0.2",
"issues": "https://github.com/pmmp/NBT/issues"
},
"time": "2019-12-01T08:20:26+00:00"
"time": "2020-01-28T17:03:46+00:00"
},
{
"name": "pocketmine/raklib",
"version": "0.12.6",
"version": "0.12.7",
"source": {
"type": "git",
"url": "https://github.com/pmmp/RakLib.git",
"reference": "18450e01185e6064790bda563ac672e7141c6992"
"reference": "01abb4e78e2ef69a83d50037d558e0b274f8245b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/18450e01185e6064790bda563ac672e7141c6992",
"reference": "18450e01185e6064790bda563ac672e7141c6992",
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/01abb4e78e2ef69a83d50037d558e0b274f8245b",
"reference": "01abb4e78e2ef69a83d50037d558e0b274f8245b",
"shasum": ""
},
"require": {
@ -221,8 +292,11 @@
"php-64bit": "*",
"php-ipv6": "*",
"pocketmine/binaryutils": "^0.1.9",
"pocketmine/snooze": "^0.1.0",
"pocketmine/spl": "^0.3.0"
"pocketmine/log": "^0.1.0",
"pocketmine/snooze": "^0.1.0"
},
"require-dev": {
"phpstan/phpstan": "^0.12.8"
},
"type": "library",
"autoload": {
@ -230,82 +304,278 @@
"raklib\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"GPL-3.0"
],
"description": "A RakNet server implementation written in PHP",
"support": {
"source": "https://github.com/pmmp/RakLib/tree/0.12.6",
"issues": "https://github.com/pmmp/RakLib/issues"
},
"time": "2019-12-07T13:43:34+00:00"
"time": "2020-01-31T15:33:05+00:00"
},
{
"name": "pocketmine/snooze",
"version": "0.1.1",
"version": "0.1.2",
"source": {
"type": "git",
"url": "https://github.com/pmmp/Snooze.git",
"reference": "b7bd231bdb75e69300cac89ccd515fc731c38c40"
"reference": "88420da3d9335dbcb3ee2decfd5e5453d057dcdf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/Snooze/zipball/b7bd231bdb75e69300cac89ccd515fc731c38c40",
"reference": "b7bd231bdb75e69300cac89ccd515fc731c38c40",
"url": "https://api.github.com/repos/pmmp/Snooze/zipball/88420da3d9335dbcb3ee2decfd5e5453d057dcdf",
"reference": "88420da3d9335dbcb3ee2decfd5e5453d057dcdf",
"shasum": ""
},
"require": {
"ext-pthreads": ">=3.1.7dev",
"php-64bit": ">=7.2.0"
},
"require-dev": {
"phpstan/phpstan": "^0.12.8"
},
"type": "library",
"autoload": {
"psr-4": {
"pocketmine\\snooze\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-3.0"
],
"description": "Thread notification management library for code using the pthreads extension",
"support": {
"source": "https://github.com/pmmp/Snooze/tree/0.1.1",
"issues": "https://github.com/pmmp/Snooze/issues"
},
"time": "2019-01-04T15:54:45+00:00"
"time": "2020-01-28T19:08:10+00:00"
},
{
"name": "pocketmine/spl",
"version": "0.3.3",
"version": "0.4.1",
"source": {
"type": "git",
"url": "https://github.com/pmmp/SPL.git",
"reference": "94d4df142fe837ba836e9348dd00209e4bdcc307"
"reference": "ff0579a0be41bbe65d3637607715c0f87728a838"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/SPL/zipball/94d4df142fe837ba836e9348dd00209e4bdcc307",
"reference": "94d4df142fe837ba836e9348dd00209e4bdcc307",
"url": "https://api.github.com/repos/pmmp/SPL/zipball/ff0579a0be41bbe65d3637607715c0f87728a838",
"reference": "ff0579a0be41bbe65d3637607715c0f87728a838",
"shasum": ""
},
"require": {
"php": ">=7.2"
},
"require-dev": {
"phpstan/phpstan": "^0.12.8"
},
"type": "library",
"autoload": {
"classmap": [
"./"
"./src"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-3.0"
],
"description": "Standard library files required by PocketMine-MP and related projects",
"support": {
"source": "https://github.com/pmmp/SPL/tree/0.3.3",
"issues": "https://github.com/pmmp/SPL/issues"
},
"time": "2019-10-28T11:41:20+00:00"
"time": "2020-01-31T16:18:03+00:00"
}
],
"packages-dev": [
{
"name": "irstea/phpunit-shim",
"version": "8.5.2",
"source": {
"type": "git",
"url": "https://gitlab.irstea.fr/pole-is/tools/phpunit-shim.git",
"reference": "39b6155954d6caec1110a9e78582c4816ab247bc"
},
"require": {
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-xml": "*",
"ext-xmlwriter": "*",
"php": "^7.2"
},
"replace": {
"phpunit/phpunit": "self.version"
},
"suggest": {
"ext-soap": "*",
"ext-xdebug": "*"
},
"bin": [
"phpunit"
],
"type": "library",
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Shim repository for phpunit/phpunit",
"homepage": "https://phpunit.de/",
"keywords": [
"phpunit",
"shim",
"testing",
"xunit"
],
"time": "2020-01-09T03:20:20+00:00"
},
{
"name": "phpstan/phpstan",
"version": "0.12.9",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
"reference": "297cb2458a96ea96d5e9d6ef38f1b7305c071f32"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/297cb2458a96ea96d5e9d6ef38f1b7305c071f32",
"reference": "297cb2458a96ea96d5e9d6ef38f1b7305c071f32",
"shasum": ""
},
"require": {
"php": "^7.1"
},
"bin": [
"phpstan",
"phpstan.phar"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "0.12-dev"
}
},
"autoload": {
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHPStan - PHP Static Analysis Tool",
"time": "2020-02-04T22:30:27+00:00"
},
{
"name": "phpstan/phpstan-phpunit",
"version": "0.12.6",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-phpunit.git",
"reference": "26394996368b6d033d012547d3197f4e07e23021"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/26394996368b6d033d012547d3197f4e07e23021",
"reference": "26394996368b6d033d012547d3197f4e07e23021",
"shasum": ""
},
"require": {
"php": "~7.1",
"phpstan/phpstan": "^0.12.4"
},
"conflict": {
"phpunit/phpunit": "<7.0"
},
"require-dev": {
"consistence/coding-standard": "^3.5",
"dealerdirect/phpcodesniffer-composer-installer": "^0.4.4",
"ergebnis/composer-normalize": "^2.0.2",
"jakub-onderka/php-parallel-lint": "^1.0",
"phing/phing": "^2.16.0",
"phpstan/phpstan-strict-rules": "^0.12",
"phpunit/phpunit": "^7.0",
"satooshi/php-coveralls": "^1.0",
"slevomat/coding-standard": "^4.7.2"
},
"type": "phpstan-extension",
"extra": {
"branch-alias": {
"dev-master": "0.12-dev"
},
"phpstan": {
"includes": [
"extension.neon",
"rules.neon"
]
}
},
"autoload": {
"psr-4": {
"PHPStan\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHPUnit extensions and rules for PHPStan",
"time": "2020-01-10T12:07:21+00:00"
},
{
"name": "phpstan/phpstan-strict-rules",
"version": "0.12.2",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-strict-rules.git",
"reference": "a670a59aff7cf96f75d21b974860ada10e25b2ee"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/a670a59aff7cf96f75d21b974860ada10e25b2ee",
"reference": "a670a59aff7cf96f75d21b974860ada10e25b2ee",
"shasum": ""
},
"require": {
"php": "~7.1",
"phpstan/phpstan": "^0.12.6"
},
"require-dev": {
"consistence/coding-standard": "^3.0.1",
"dealerdirect/phpcodesniffer-composer-installer": "^0.4.4",
"ergebnis/composer-normalize": "^2.0.2",
"jakub-onderka/php-parallel-lint": "^1.0",
"phing/phing": "^2.16.0",
"phpstan/phpstan-phpunit": "^0.12",
"phpunit/phpunit": "^7.0",
"slevomat/coding-standard": "^4.5.2"
},
"type": "phpstan-extension",
"extra": {
"branch-alias": {
"dev-master": "0.12-dev"
},
"phpstan": {
"includes": [
"rules.neon"
]
}
},
"autoload": {
"psr-4": {
"PHPStan\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Extra strict and opinionated rules for PHPStan",
"time": "2020-01-20T13:08:52+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {

View File

@ -1,42 +1,87 @@
includes:
- tests/phpstan/configs/debug-const-checks.neon
- tests/phpstan/configs/com-dotnet-magic.neon
- tests/phpstan/configs/custom-leveldb.neon
- tests/phpstan/configs/gc-hacks.neon
- tests/phpstan/configs/optional-com-dotnet.neon
- tests/phpstan/configs/optional-leveldb.neon
- tests/phpstan/configs/php-bugs.neon
- tests/phpstan/configs/phpstan-bugs.neon
- tests/phpstan/configs/phpunit-wiring-tests.neon
- tests/phpstan/configs/pthreads-bugs.neon
- tests/phpstan/configs/runtime-type-checks.neon
- vendor/phpstan/phpstan-phpunit/extension.neon
- vendor/phpstan/phpstan-phpunit/rules.neon
- vendor/phpstan/phpstan-strict-rules/rules.neon
parameters:
level: 5
level: 6
autoload_files:
- tests/phpstan/bootstrap.php
- src/pocketmine/PocketMine.php
- build/make-release.php
- build/server-phar.php
- vendor/irstea/phpunit-shim/phpunit
paths:
- src
- build/make-release.php
- build/server-phar.php
- tests/phpunit
dynamicConstantNames:
- pocketmine\IS_DEVELOPMENT_BUILD
- pocketmine\DEBUG
stubFiles:
- tests/phpstan/stubs/pthreads.stub
- tests/phpstan/stubs/chunkutils.stub
reportUnmatchedIgnoredErrors: false #no other way to silence platform-specific non-warnings
ignoreErrors:
-
message: "#^Instanceof between pocketmine\\\\plugin\\\\PluginManager and pocketmine\\\\plugin\\\\PluginManager will always evaluate to true\\.$#"
count: 1
path: src/pocketmine/CrashDump.php
-
message: "#^pocketmine\\\\Player\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\entity\\\\Human\\.$#"
count: 1
path: src/pocketmine/Player.php
-
message: "#^Cannot instantiate interface pocketmine\\\\level\\\\format\\\\io\\\\LevelProvider\\.$#"
count: 1
path: src/pocketmine/Server.php
-
message: "#^Instanceof between pocketmine\\\\plugin\\\\PluginManager and pocketmine\\\\plugin\\\\PluginManager will always evaluate to true\\.$#"
count: 1
path: src/pocketmine/Server.php
-
message: "#^Instanceof between pocketmine\\\\scheduler\\\\AsyncPool and pocketmine\\\\scheduler\\\\AsyncPool will always evaluate to true\\.$#"
count: 1
path: src/pocketmine/Server.php
-
message: "#^Instanceof between pocketmine\\\\command\\\\CommandReader and pocketmine\\\\command\\\\CommandReader will always evaluate to true\\.$#"
count: 1
path: src/pocketmine/Server.php
-
message: "#^Instanceof between pocketmine\\\\network\\\\Network and pocketmine\\\\network\\\\Network will always evaluate to true\\.$#"
count: 1
path: src/pocketmine/Server.php
-
message: "#^pocketmine\\\\block\\\\[A-Za-z\\d]+\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
path: src/pocketmine/block
-
message: "#^pocketmine\\\\block\\\\Block\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\level\\\\Position\\.$#"
count: 1
path: src/pocketmine/block/Block.php
-
message: "#^Call to an undefined method pocketmine\\\\command\\\\CommandSender\\:\\:teleport\\(\\)\\.$#"
count: 1
path: src/pocketmine/command/defaults/TeleportCommand.php
# comment: "not actually possible, but high cost to fix warning"
-
message: "#^Array \\(array\\<string\\>\\) does not accept pocketmine\\\\entity\\\\Entity\\.$#"
count: 2
path: src/pocketmine/entity/Entity.php
-
message: "#^Invalid array key type pocketmine\\\\entity\\\\Entity\\.$#"
count: 1
path: src/pocketmine/entity/Entity.php
-
message: "#^Method pocketmine\\\\event\\\\entity\\\\EntityDeathEvent\\:\\:getEntity\\(\\) should return pocketmine\\\\entity\\\\Living but returns pocketmine\\\\entity\\\\Entity\\.$#"
count: 1
@ -72,6 +117,31 @@ parameters:
count: 1
path: src/pocketmine/event/entity/ProjectileLaunchEvent.php
-
message: "#^pocketmine\\\\inventory\\\\DoubleChestInventory\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\inventory\\\\ChestInventory\\.$#"
count: 1
path: src/pocketmine/inventory/DoubleChestInventory.php
-
message: "#^pocketmine\\\\inventory\\\\EnderChestInventory\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\inventory\\\\ChestInventory\\.$#"
count: 1
path: src/pocketmine/inventory/EnderChestInventory.php
-
message: "#^pocketmine\\\\item\\\\GoldenAppleEnchanted\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\item\\\\GoldenApple\\.$#"
count: 1
path: src/pocketmine/item/GoldenAppleEnchanted.php
-
message: "#^pocketmine\\\\item\\\\WrittenBook\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\item\\\\WritableBook\\.$#"
count: 1
path: src/pocketmine/item/WrittenBook.php
-
message: "#^Variable property access on \\$this\\(pocketmine\\\\level\\\\generator\\\\PopulationTask\\)\\.$#"
count: 4
path: src/pocketmine/level/generator/PopulationTask.php
-
message: "#^Constructor of class pocketmine\\\\level\\\\generator\\\\hell\\\\Nether has an unused parameter \\$options\\.$#"
count: 1
@ -83,9 +153,9 @@ parameters:
path: src/pocketmine/level/generator/normal/Normal.php
-
message: "#^Used constant pocketmine\\\\RESOURCE_PATH not found\\.$#"
message: "#^Variable method call on pocketmine\\\\event\\\\Listener\\.$#"
count: 1
path: src/pocketmine/network/mcpe/protocol/StartGamePacket.php
path: src/pocketmine/plugin/MethodEventExecutor.php
-
message: "#^Constructor of class pocketmine\\\\scheduler\\\\TaskScheduler has an unused parameter \\$logger\\.$#"
@ -104,18 +174,10 @@ parameters:
message: "#^Constant pocketmine\\\\GIT_COMMIT not found\\.$#"
path: src
-
message: "#^Constant pocketmine\\\\PATH not found\\.$#"
path: src
-
message: "#^Constant pocketmine\\\\PLUGIN_PATH not found\\.$#"
path: src
-
message: "#^Constant pocketmine\\\\RESOURCE_PATH not found\\.$#"
path: src
-
message: "#^Constant pocketmine\\\\START_TIME not found\\.$#"
path: src

View File

@ -30,9 +30,7 @@ use pocketmine\utils\TextFormat;
* Handles the achievement list and a bit more
*/
abstract class Achievement{
/**
* @var array[]
*/
/** @var array[] */
public static $list = [
/*"openInventory" => array(
"name" => "Taking Inventory",
@ -106,13 +104,6 @@ abstract class Achievement{
];
/**
* @param Player $player
* @param string $achievementId
*
* @return bool
*/
public static function broadcast(Player $player, string $achievementId) : bool{
if(isset(Achievement::$list[$achievementId])){
$translation = new TranslationContainer("chat.type.achievement", [$player->getDisplayName(), TextFormat::GREEN . Achievement::$list[$achievementId]["name"] . TextFormat::RESET]);
@ -129,11 +120,7 @@ abstract class Achievement{
}
/**
* @param string $achievementId
* @param string $achievementName
* @param array $requires
*
* @return bool
* @param string[] $requires
*/
public static function add(string $achievementId, string $achievementName, array $requires = []) : bool{
if(!isset(Achievement::$list[$achievementId])){

View File

@ -25,12 +25,16 @@ namespace pocketmine;
abstract class Collectable extends \Threaded{
/** @var bool */
private $isGarbage = false;
public function isGarbage() : bool{
return $this->isGarbage;
}
/**
* @return void
*/
public function setGarbage(){
$this->isGarbage = true;
}

View File

@ -0,0 +1,33 @@
<?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;
// composer autoload doesn't use require_once and also pthreads can inherit things
if(defined('pocketmine\_CORE_CONSTANTS_INCLUDED')){
return;
}
define('pocketmine\_CORE_CONSTANTS_INCLUDED', true);
define('pocketmine\PATH', dirname(__DIR__, 2) . '/');
define('pocketmine\RESOURCE_PATH', __DIR__ . '/resources/');

View File

@ -96,8 +96,14 @@ class CrashDump{
/** @var Server */
private $server;
/** @var resource */
private $fp;
/** @var int */
private $time;
/**
* @var mixed[]
* @phpstan-var array<string, mixed>
*/
private $data = [];
/** @var string */
private $encodedData = "";
@ -134,15 +140,22 @@ class CrashDump{
return $this->path;
}
/**
* @return string
*/
public function getEncodedData(){
return $this->encodedData;
}
/**
* @return mixed[]
* @phpstan-return array<string, mixed>
*/
public function getData() : array{
return $this->data;
}
private function encodeData(){
private function encodeData() : void{
$this->addLine();
$this->addLine("----------------------REPORT THE DATA BELOW THIS LINE-----------------------");
$this->addLine();
@ -158,7 +171,7 @@ class CrashDump{
$this->addLine("===END CRASH DUMP===");
}
private function pluginsData(){
private function pluginsData() : void{
if($this->server->getPluginManager() instanceof PluginManager){
$this->addLine();
$this->addLine("Loaded plugins:");
@ -182,7 +195,7 @@ class CrashDump{
}
}
private function extraData(){
private function extraData() : void{
global $argv;
if($this->server->getProperty("auto-report.send-settings", true) !== false){
@ -209,7 +222,7 @@ class CrashDump{
}
}
private function baseCrash(){
private function baseCrash() : void{
global $lastExceptionError, $lastError;
if(isset($lastExceptionError)){
@ -317,7 +330,7 @@ class CrashDump{
return false;
}
private function generalData(){
private function generalData() : void{
$version = new VersionString(\pocketmine\BASE_VERSION, \pocketmine\IS_DEVELOPMENT_BUILD, \pocketmine\BUILD_NUMBER);
$this->data["general"] = [];
$this->data["general"]["name"] = $this->server->getName();
@ -340,10 +353,20 @@ class CrashDump{
$this->addLine("OS : " . PHP_OS . ", " . Utils::getOS());
}
/**
* @param string $line
*
* @return void
*/
public function addLine($line = ""){
fwrite($this->fp, $line . PHP_EOL);
}
/**
* @param string $str
*
* @return void
*/
public function add($str){
fwrite($this->fp, $str);
}

View File

@ -27,33 +27,21 @@ use pocketmine\permission\ServerOperator;
interface IPlayer extends ServerOperator{
/**
* @return bool
*/
public function isOnline() : bool;
/**
* @return string
*/
public function getName() : string;
/**
* @return bool
*/
public function isBanned() : bool;
/**
* @param bool $banned
* @return void
*/
public function setBanned(bool $banned);
/**
* @return bool
*/
public function isWhitelisted() : bool;
/**
* @param bool $value
* @return void
*/
public function setWhitelisted(bool $value);
@ -72,9 +60,6 @@ interface IPlayer extends ServerOperator{
*/
public function getLastPlayed();
/**
* @return bool
*/
public function hasPlayedBefore() : bool;
}

View File

@ -116,7 +116,7 @@ class MemoryManager{
$this->init();
}
private function init(){
private function init() : void{
$this->memoryLimit = ((int) $this->server->getProperty("memory.main-limit", 0)) * 1024 * 1024;
$defaultMemory = 1024;
@ -170,38 +170,25 @@ class MemoryManager{
gc_enable();
}
/**
* @return bool
*/
public function isLowMemory() : bool{
return $this->lowMemory;
}
/**
* @return bool
*/
public function canUseChunkCache() : bool{
return !$this->lowMemory or !$this->lowMemDisableChunkCache;
}
/**
* Returns the allowed chunk radius based on the current memory usage.
*
* @param int $distance
*
* @return int
*/
public function getViewDistance(int $distance) : int{
return ($this->lowMemory and $this->lowMemChunkRadiusOverride > 0) ? (int) min($this->lowMemChunkRadiusOverride, $distance) : $distance;
return ($this->lowMemory and $this->lowMemChunkRadiusOverride > 0) ? min($this->lowMemChunkRadiusOverride, $distance) : $distance;
}
/**
* Triggers garbage collection and cache cleanup to try and free memory.
*
* @param int $memory
* @param int $limit
* @param bool $global
* @param int $triggerCount
* @return void
*/
public function trigger(int $memory, int $limit, bool $global = false, int $triggerCount = 0){
$this->server->getLogger()->debug(sprintf("[Memory Manager] %sLow memory triggered, limit %gMB, using %gMB",
@ -231,6 +218,8 @@ class MemoryManager{
/**
* Called every tick to update the memory manager state.
*
* @return void
*/
public function check(){
Timings::$memoryManagerTimer->startTiming();
@ -269,9 +258,6 @@ class MemoryManager{
Timings::$memoryManagerTimer->stopTiming();
}
/**
* @return int
*/
public function triggerGarbageCollector() : int{
Timings::$garbageCollectorTimer->startTiming();
@ -295,9 +281,7 @@ class MemoryManager{
/**
* Dumps the server memory into the specified output folder.
*
* @param string $outputFolder
* @param int $maxNesting
* @param int $maxStringSize
* @return void
*/
public function dumpServerMemory(string $outputFolder, int $maxNesting, int $maxStringSize){
$this->server->getLogger()->notice("[Dump] After the memory dump is done, the server might crash");
@ -315,11 +299,8 @@ class MemoryManager{
* Static memory dumper accessible from any thread.
*
* @param mixed $startingObject
* @param string $outputFolder
* @param int $maxNesting
* @param int $maxStringSize
* @param \Logger $logger
*
* @return void
* @throws \ReflectionException
*/
public static function dumpMemory($startingObject, string $outputFolder, int $maxNesting, int $maxStringSize, \Logger $logger){
@ -357,7 +338,7 @@ class MemoryManager{
}
$staticCount++;
self::continueDump($property->getValue(), $staticProperties[$className][$property->getName()], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
$staticProperties[$className][$property->getName()] = self::continueDump($property->getValue(), $objects, $refCounts, 0, $maxNesting, $maxStringSize);
}
if(count($staticProperties[$className]) === 0){
@ -390,14 +371,14 @@ class MemoryManager{
}
$globalCount++;
self::continueDump($value, $globalVariables[$varName], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
$globalVariables[$varName] = self::continueDump($value, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
}
file_put_contents($outputFolder . "/globalVariables.js", json_encode($globalVariables, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
$logger->info("[Dump] Wrote $globalCount global variables");
}
self::continueDump($startingObject, $data, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
$data = self::continueDump($startingObject, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
do{
$continue = false;
@ -445,14 +426,13 @@ class MemoryManager{
$property->setAccessible(true);
}
self::continueDump($property->getValue($object), $info["properties"][$name], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
$info["properties"][$name] = self::continueDump($property->getValue($object), $objects, $refCounts, 0, $maxNesting, $maxStringSize);
}
}
fwrite($obData, "$hash@$className: " . json_encode($info, JSON_UNESCAPED_SLASHES) . "\n");
}
}while($continue);
$logger->info("[Dump] Wrote " . count($objects) . " objects");
@ -473,17 +453,14 @@ class MemoryManager{
/**
* @param mixed $from
* @param mixed &$data
* @param object[] &$objects
* @param int[] &$refCounts
* @param int $recursion
* @param int $maxNesting
* @param int $maxStringSize
* @param object[] $objects reference parameter
* @param int[] $refCounts reference parameter
*
* @return mixed
*/
private static function continueDump($from, &$data, array &$objects, array &$refCounts, int $recursion, int $maxNesting, int $maxStringSize){
private static function continueDump($from, array &$objects, array &$refCounts, int $recursion, int $maxNesting, int $maxStringSize){
if($maxNesting <= 0){
$data = "(error) NESTING LIMIT REACHED";
return;
return "(error) NESTING LIMIT REACHED";
}
--$maxNesting;
@ -499,12 +476,11 @@ class MemoryManager{
$data = "(object) $hash@" . get_class($from);
}elseif(is_array($from)){
if($recursion >= 5){
$data = "(error) ARRAY RECURSION LIMIT REACHED";
return;
return "(error) ARRAY RECURSION LIMIT REACHED";
}
$data = [];
foreach($from as $key => $value){
self::continueDump($value, $data[$key], $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize);
$data[$key] = self::continueDump($value, $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize);
}
}elseif(is_string($from)){
$data = "(string) len(" . strlen($from) . ") " . substr(Utils::printable($from), 0, $maxStringSize);
@ -513,5 +489,7 @@ class MemoryManager{
}else{
$data = $from;
}
return $data;
}
}

View File

@ -37,10 +37,6 @@ class OfflinePlayer implements IPlayer, Metadatable{
/** @var CompoundTag|null */
private $namedtag = null;
/**
* @param Server $server
* @param string $name
*/
public function __construct(Server $server, string $name){
$this->server = $server;
$this->name = $name;
@ -57,6 +53,9 @@ class OfflinePlayer implements IPlayer, Metadatable{
return $this->name;
}
/**
* @return Server
*/
public function getServer(){
return $this->server;
}

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine {
use pocketmine\utils\Git;
use pocketmine\utils\Internet;
use pocketmine\utils\MainLogger;
use pocketmine\utils\Process;
@ -37,6 +38,10 @@ namespace pocketmine {
const MIN_PHP_VERSION = "7.2.0";
/**
* @param string $message
* @return void
*/
function critical_error($message){
echo "[ERROR] $message" . PHP_EOL;
}
@ -118,6 +123,10 @@ namespace pocketmine {
return $messages;
}
/**
* @param \Logger $logger
* @return void
*/
function emit_performance_warnings(\Logger $logger){
if(extension_loaded("xdebug")){
$logger->warning("Xdebug extension is enabled. This has a major impact on performance.");
@ -133,6 +142,9 @@ namespace pocketmine {
}
}
/**
* @return void
*/
function set_ini_entries(){
ini_set("allow_url_fopen", '1');
ini_set("display_errors", '1');
@ -141,8 +153,11 @@ namespace pocketmine {
ini_set('assert.exception', '1');
}
/**
* @return void
*/
function server(){
if(!empty($messages = check_platform_dependencies())){
if(count($messages = check_platform_dependencies()) > 0){
echo PHP_EOL;
$binary = version_compare(PHP_VERSION, "5.4") >= 0 ? PHP_BINARY : "unknown";
critical_error("Selected PHP binary ($binary) does not satisfy some requirements.");
@ -158,17 +173,11 @@ namespace pocketmine {
error_reporting(-1);
set_ini_entries();
if(\Phar::running(true) !== ""){
define('pocketmine\PATH', \Phar::running(true) . "/");
}else{
define('pocketmine\PATH', dirname(__FILE__, 3) . DIRECTORY_SEPARATOR);
}
$opts = getopt("", ["bootstrap:"]);
if(isset($opts["bootstrap"])){
$bootstrap = realpath($opts["bootstrap"]) ?: $opts["bootstrap"];
$bootstrap = ($real = realpath($opts["bootstrap"])) !== false ? $real : $opts["bootstrap"];
}else{
$bootstrap = \pocketmine\PATH . 'vendor/autoload.php';
$bootstrap = dirname(__FILE__, 3) . '/vendor/autoload.php';
}
define('pocketmine\COMPOSER_AUTOLOADER_PATH', $bootstrap);
@ -188,12 +197,7 @@ namespace pocketmine {
$gitHash = str_repeat("00", 20);
if(\Phar::running(true) === ""){
if(Process::execute("git rev-parse HEAD", $out) === 0 and $out !== false and strlen($out = trim($out)) === 40){
$gitHash = trim($out);
if(Process::execute("git diff --quiet") === 1 or Process::execute("git diff --cached --quiet") === 1){ //Locally-modified
$gitHash .= "-dirty";
}
}
$gitHash = Git::getRepositoryStatePretty(\pocketmine\PATH);
}else{
$phar = new \Phar(\Phar::running(false));
$meta = $phar->getMetadata();
@ -204,8 +208,6 @@ namespace pocketmine {
define('pocketmine\GIT_COMMIT', $gitHash);
define('pocketmine\RESOURCE_PATH', \pocketmine\PATH . 'src' . DIRECTORY_SEPARATOR . 'pocketmine' . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR);
$opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-ansi", "disable-ansi"]);
define('pocketmine\DATA', isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR);
@ -263,7 +265,6 @@ namespace pocketmine {
//TODO: move this to a Server field
define('pocketmine\START_TIME', microtime(true));
ThreadManager::init();
/*
* We now use the Composer autoloader, but this autoloader is still for loading plugins.

File diff suppressed because it is too large Load Diff

View File

@ -33,12 +33,19 @@ abstract class Thread extends \Thread{
/** @var string|null */
protected $composerAutoloaderPath;
/** @var bool */
protected $isKilled = false;
/**
* @return \ClassLoader|null
*/
public function getClassLoader(){
return $this->classLoader;
}
/**
* @return void
*/
public function setClassLoader(\ClassLoader $loader = null){
$this->composerAutoloaderPath = \pocketmine\COMPOSER_AUTOLOADER_PATH;
@ -54,6 +61,8 @@ abstract class Thread extends \Thread{
* WARNING: This method MUST be called from any descendent threads' run() method to make autoloading usable.
* If you do not do this, you will not be able to use new classes that were not loaded when the thread was started
* (unless you are using a custom autoloader).
*
* @return void
*/
public function registerClassLoader(){
if($this->composerAutoloaderPath !== null){
@ -64,6 +73,11 @@ abstract class Thread extends \Thread{
}
}
/**
* @param int|null $options TODO: pthreads bug
*
* @return bool
*/
public function start(?int $options = \PTHREADS_INHERIT_ALL){
ThreadManager::getInstance()->add($this);
@ -75,6 +89,8 @@ abstract class Thread extends \Thread{
/**
* Stops the thread using the best way possible. Try to stop it yourself before calling this.
*
* @return void
*/
public function quit(){
$this->isKilled = true;

View File

@ -28,9 +28,13 @@ use function spl_object_hash;
class ThreadManager extends \Volatile{
/** @var ThreadManager */
/** @var ThreadManager|null */
private static $instance = null;
/**
* @deprecated
* @return void
*/
public static function init(){
self::$instance = new ThreadManager();
}
@ -39,24 +43,31 @@ class ThreadManager extends \Volatile{
* @return ThreadManager
*/
public static function getInstance(){
if(self::$instance === null){
self::$instance = new ThreadManager();
}
return self::$instance;
}
/**
* @param Worker|Thread $thread
*
* @return void
*/
public function add($thread){
if($thread instanceof Thread or $thread instanceof Worker){
$this->{spl_object_hash($thread)} = $thread;
$this[spl_object_hash($thread)] = $thread;
}
}
/**
* @param Worker|Thread $thread
*
* @return void
*/
public function remove($thread){
if($thread instanceof Thread or $thread instanceof Worker){
unset($this->{spl_object_hash($thread)});
unset($this[spl_object_hash($thread)]);
}
}

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine;
// composer autoload doesn't use require_once and also pthreads can inherit things
@ -28,8 +30,7 @@ if(defined('pocketmine\_VERSION_INFO_INCLUDED')){
}
const _VERSION_INFO_INCLUDED = true;
const NAME = "PocketMine-MP";
const BASE_VERSION = "3.11.2";
const BASE_VERSION = "3.11.6";
const IS_DEVELOPMENT_BUILD = true;
const BUILD_NUMBER = 0;

View File

@ -33,12 +33,19 @@ abstract class Worker extends \Worker{
/** @var string|null */
protected $composerAutoloaderPath;
/** @var bool */
protected $isKilled = false;
/**
* @return \ClassLoader|null
*/
public function getClassLoader(){
return $this->classLoader;
}
/**
* @return void
*/
public function setClassLoader(\ClassLoader $loader = null){
$this->composerAutoloaderPath = \pocketmine\COMPOSER_AUTOLOADER_PATH;
@ -54,6 +61,8 @@ abstract class Worker extends \Worker{
* WARNING: This method MUST be called from any descendent threads' run() method to make autoloading usable.
* If you do not do this, you will not be able to use new classes that were not loaded when the thread was started
* (unless you are using a custom autoloader).
*
* @return void
*/
public function registerClassLoader(){
if($this->composerAutoloaderPath !== null){
@ -64,6 +73,11 @@ abstract class Worker extends \Worker{
}
}
/**
* @param int|null $options TODO: pthreads bug
*
* @return bool
*/
public function start(?int $options = \PTHREADS_INHERIT_ALL){
ThreadManager::getInstance()->add($this);
@ -75,6 +89,8 @@ abstract class Worker extends \Worker{
/**
* Stops the thread using the best way possible. Try to stop it yourself before calling this.
*
* @return void
*/
public function quit(){
$this->isKilled = true;

View File

@ -26,7 +26,6 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
/**
* Air block
*/

View File

@ -78,7 +78,7 @@ class Anvil extends Fallable{
public function recalculateBoundingBox() : ?AxisAlignedBB{
$inset = 0.125;
if($this->meta & 0x01){ //east/west
if(($this->meta & 0x01) !== 0){ //east/west
return new AxisAlignedBB(
$this->x,
$this->y,

View File

@ -99,6 +99,11 @@ abstract class BaseRail extends Flowable{
return false;
}
/**
* @param int[] $connections
* @param int[][] $lookup
* @phpstan-param array<int, list<int>> $lookup
*/
protected static function searchState(array $connections, array $lookup) : int{
$meta = array_search($connections, $lookup, true);
if($meta === false){
@ -114,9 +119,7 @@ abstract class BaseRail extends Flowable{
/**
* Returns a meta value for the rail with the given connections.
*
* @param array $connections
*
* @return int
* @param int[] $connections
*
* @throws \InvalidArgumentException if no state matches the given connections
*/
@ -164,6 +167,12 @@ abstract class BaseRail extends Flowable{
return $connections;
}
/**
* @param int[] $constraints
*
* @return true[]
* @phpstan-return array<int, true>
*/
private function getPossibleConnectionDirections(array $constraints) : array{
switch(count($constraints)){
case 0:
@ -188,6 +197,10 @@ abstract class BaseRail extends Flowable{
}
}
/**
* @return true[]
* @phpstan-return array<int, true>
*/
protected function getPossibleConnectionDirectionsOneConstraint(int $constraint) : array{
$opposite = Vector3::getOppositeSide($constraint & ~self::FLAG_ASCEND);
@ -247,6 +260,9 @@ abstract class BaseRail extends Flowable{
}
}
/**
* @param int[] $connections
*/
private function updateState(array $connections) : void{
if(count($connections) === 1){
$connections[] = Vector3::getOppositeSide($connections[0] & ~self::FLAG_ASCEND);

View File

@ -69,13 +69,13 @@ class Bed extends Transparent{
return ($this->meta & self::BITFLAG_HEAD) !== 0;
}
/**
* @return bool
*/
public function isOccupied() : bool{
return ($this->meta & self::BITFLAG_OCCUPIED) !== 0;
}
/**
* @return void
*/
public function setOccupied(bool $occupied = true){
if($occupied){
$this->meta |= self::BITFLAG_OCCUPIED;
@ -90,12 +90,6 @@ class Bed extends Transparent{
}
}
/**
* @param int $meta
* @param bool $isHead
*
* @return int
*/
public static function getOtherHalfSide(int $meta, bool $isHead = false) : int{
$rotation = $meta & 0x03;
$side = -1;
@ -122,9 +116,6 @@ class Bed extends Transparent{
return $side;
}
/**
* @return Bed|null
*/
public function getOtherHalf() : ?Bed{
$other = $this->getSide(self::getOtherHalfSide($this->meta, $this->isHeadPart()));
if($other instanceof Bed and $other->getId() === $this->getId() and $other->isHeadPart() !== $this->isHeadPart() and (($other->getDamage() & 0x03) === ($this->getDamage() & 0x03))){

View File

@ -40,6 +40,7 @@ use pocketmine\network\mcpe\protocol\types\RuntimeBlockMapping;
use pocketmine\Player;
use pocketmine\plugin\Plugin;
use function array_merge;
use function count;
use function get_class;
use const PHP_INT_MAX;
@ -49,12 +50,6 @@ class Block extends Position implements BlockIds, Metadatable{
* Returns a new Block instance with the specified ID, meta and position.
*
* This function redirects to {@link BlockFactory#get}.
*
* @param int $id
* @param int $meta
* @param Position|null $pos
*
* @return Block
*/
public static function get(int $id, int $meta = 0, Position $pos = null) : Block{
return BlockFactory::get($id, $meta, $pos);
@ -72,7 +67,6 @@ class Block extends Position implements BlockIds, Metadatable{
/** @var AxisAlignedBB|null */
protected $boundingBox = null;
/** @var AxisAlignedBB[]|null */
protected $collisionBoxes = null;
@ -89,16 +83,10 @@ class Block extends Position implements BlockIds, Metadatable{
$this->itemId = $itemId;
}
/**
* @return string
*/
public function getName() : string{
return $this->fallbackName ?? "Unknown";
}
/**
* @return int
*/
final public function getId() : int{
return $this->id;
}
@ -106,8 +94,6 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* Returns the ID of the item form of the block.
* Used for drops for blocks (some blocks such as doors have a different item ID).
*
* @return int
*/
public function getItemId() : int{
return $this->itemId ?? $this->getId();
@ -115,22 +101,15 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* @internal
* @return int
*/
public function getRuntimeId() : int{
return RuntimeBlockMapping::toStaticRuntimeId($this->getId(), $this->getDamage());
}
/**
* @return int
*/
final public function getDamage() : int{
return $this->meta;
}
/**
* @param int $meta
*/
final public function setDamage(int $meta) : void{
if($meta < 0 or $meta > 0xf){
throw new \InvalidArgumentException("Block damage values must be 0-15, not $meta");
@ -144,8 +123,6 @@ class Block extends Position implements BlockIds, Metadatable{
*
* If your block should not have any meta value when it's dropped as an item, override this to return 0 in
* descendent classes.
*
* @return int
*/
public function getVariantBitmask() : int{
return -1;
@ -153,24 +130,18 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* Returns the block meta, stripped of non-variant flags.
* @return int
*/
public function getVariant() : int{
return $this->meta & $this->getVariantBitmask();
}
/**
* AKA: Block->isPlaceable
* @return bool
*/
public function canBePlaced() : bool{
return true;
}
/**
* @return bool
*/
public function canBeReplaced() : bool{
return false;
}
@ -181,15 +152,6 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* Places the Block, using block space and block target, and side. Returns if the block has been placed.
*
* @param Item $item
* @param Block $blockReplace
* @param Block $blockClicked
* @param int $face
* @param Vector3 $clickVector
* @param Player|null $player
*
* @return bool
*/
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
return $this->getLevel()->setBlock($this, $this, true, true);
@ -197,18 +159,11 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* Returns if the block can be broken with an specific Item
*
* @param Item $item
*
* @return bool
*/
public function isBreakable(Item $item) : bool{
return true;
}
/**
* @return int
*/
public function getToolType() : int{
return BlockToolType::TYPE_NONE;
}
@ -222,8 +177,6 @@ class Block extends Position implements BlockIds, Metadatable{
* Otherwise, 1 should be returned if a tool is required, 0 if not.
*
* @see Item::getBlockToolHarvestLevel()
*
* @return int
*/
public function getToolHarvestLevel() : int{
return 0;
@ -235,10 +188,6 @@ class Block extends Position implements BlockIds, Metadatable{
*
* In most cases this is also used to determine whether block drops should be created or not, except in some
* special cases such as vines.
*
* @param Item $tool
*
* @return bool
*/
public function isCompatibleWithTool(Item $tool) : bool{
if($this->getHardness() < 0){
@ -253,23 +202,14 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* Do the actions needed so the block is broken with the Item
*
* @param Item $item
* @param Player|null $player
*
* @return bool
*/
public function onBreak(Item $item, Player $player = null) : bool{
return $this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true, true);
}
/**
* Returns the seconds that this block takes to be broken using an specific Item
*
* @param Item $item
*
* @return float
* @throws \InvalidArgumentException if the item efficiency is not a positive number
*/
public function getBreakTime(Item $item) : float{
@ -299,8 +239,6 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* Returns whether random block updates will be done on this block.
*
* @return bool
*/
public function ticksRandomly() : bool{
return false;
@ -323,11 +261,6 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* Do actions when activated by Item. Returns if it has done anything
*
* @param Item $item
* @param Player|null $player
*
* @return bool
*/
public function onActivate(Item $item, Player $player = null) : bool{
return false;
@ -335,7 +268,6 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* Returns a base value used to compute block break times.
* @return float
*/
public function getHardness() : float{
return 10;
@ -343,15 +275,11 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* Returns the block's resistance to explosions. Usually 5x hardness.
* @return float
*/
public function getBlastResistance() : float{
return $this->getHardness() * 5;
}
/**
* @return float
*/
public function getFrictionFactor() : float{
return 0.6;
}
@ -379,16 +307,11 @@ class Block extends Position implements BlockIds, Metadatable{
* Examples of this behaviour include leaves and cobwebs.
*
* Light-diffusing blocks are included by the heightmap.
*
* @return bool
*/
public function diffusesSkyLight() : bool{
return false;
}
/**
* @return bool
*/
public function isTransparent() : bool{
return false;
}
@ -399,7 +322,6 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* AKA: Block->isFlowable
* @return bool
*/
public function canBeFlowedInto() : bool{
return false;
@ -415,21 +337,17 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* Returns whether entities can climb up this block.
* @return bool
*/
public function canClimb() : bool{
return false;
}
public function addVelocityToEntity(Entity $entity, Vector3 $vector) : void{
}
/**
* Sets the block position to a new Position object
*
* @param Position $v
*/
final public function position(Position $v) : void{
$this->x = (int) $v->x;
@ -442,8 +360,6 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* Returns an array of Item objects to be dropped
*
* @param Item $item
*
* @return Item[]
*/
public function getDrops(Item $item) : array{
@ -461,8 +377,6 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* Returns an array of Items to be dropped when the block is broken using the correct tool type.
*
* @param Item $item
*
* @return Item[]
*/
public function getDropsForCompatibleTool(Item $item) : array{
@ -474,8 +388,6 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* Returns an array of Items to be dropped when the block is broken using a compatible Silk Touch-enchanted tool.
*
* @param Item $item
*
* @return Item[]
*/
public function getSilkTouchDrops(Item $item) : array{
@ -486,10 +398,6 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* Returns how much XP will be dropped by breaking this block with the given item.
*
* @param Item $item
*
* @return int
*/
public function getXpDropForTool(Item $item) : int{
if($item->hasEnchantment(Enchantment::SILK_TOUCH) or !$this->isCompatibleWithTool($item)){
@ -501,8 +409,6 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* Returns how much XP this block will drop when broken with an appropriate tool.
*
* @return int
*/
protected function getXpDropAmount() : int{
return 0;
@ -511,8 +417,6 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* Returns whether Silk Touch enchanted tools will cause this block to drop as itself. Since most blocks drop
* themselves anyway, this is implicitly true.
*
* @return bool
*/
public function isAffectedBySilkTouch() : bool{
return true;
@ -520,7 +424,6 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* Returns the item that players will equip when middle-clicking on this block.
* @return Item
*/
public function getPickedItem() : Item{
return ItemFactory::get($this->getItemId(), $this->getVariant());
@ -528,7 +431,6 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* Returns the time in ticks which the block will fuel a furnace for.
* @return int
*/
public function getFuelTime() : int{
return 0;
@ -537,8 +439,6 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* Returns the chance that the block will catch fire from nearby fire sources. Higher values lead to faster catching
* fire.
*
* @return int
*/
public function getFlameEncouragement() : int{
return 0;
@ -546,8 +446,6 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* Returns the base flammability of this block. Higher values lead to the block burning away more quickly.
*
* @return int
*/
public function getFlammability() : int{
return 0;
@ -555,8 +453,6 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* Returns whether fire lit on this block will burn indefinitely.
*
* @return bool
*/
public function burnsForever() : bool{
return false;
@ -564,8 +460,6 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* Returns whether this block can catch fire.
*
* @return bool
*/
public function isFlammable() : bool{
return $this->getFlammability() > 0;
@ -581,9 +475,6 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* Returns the Block on the side $side, works like Vector3::getSide()
*
* @param int $side
* @param int $step
*
* @return Block
*/
public function getSide(int $side, int $step = 1){
@ -642,10 +533,6 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* Checks for collision against an AxisAlignedBB
*
* @param AxisAlignedBB $bb
*
* @return bool
*/
public function collidesWithBB(AxisAlignedBB $bb) : bool{
foreach($this->getCollisionBoxes() as $bb2){
@ -657,9 +544,6 @@ class Block extends Position implements BlockIds, Metadatable{
return false;
}
/**
* @param Entity $entity
*/
public function onEntityCollide(Entity $entity) : void{
}
@ -679,16 +563,13 @@ class Block extends Position implements BlockIds, Metadatable{
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{
if($bb = $this->recalculateBoundingBox()){
if(($bb = $this->recalculateBoundingBox()) !== null){
return [$bb];
}
return [];
}
/**
* @return AxisAlignedBB|null
*/
public function getBoundingBox() : ?AxisAlignedBB{
if($this->boundingBox === null){
$this->boundingBox = $this->recalculateBoundingBox();
@ -696,9 +577,6 @@ class Block extends Position implements BlockIds, Metadatable{
return $this->boundingBox;
}
/**
* @return AxisAlignedBB|null
*/
protected function recalculateBoundingBox() : ?AxisAlignedBB{
return new AxisAlignedBB(
$this->x,
@ -719,15 +597,9 @@ class Block extends Position implements BlockIds, Metadatable{
$this->collisionBoxes = null;
}
/**
* @param Vector3 $pos1
* @param Vector3 $pos2
*
* @return RayTraceResult|null
*/
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) : ?RayTraceResult{
$bbs = $this->getCollisionBoxes();
if(empty($bbs)){
if(count($bbs) === 0){
return null;
}

View File

@ -32,23 +32,47 @@ use function min;
* Manages block registration and instance creation
*/
class BlockFactory{
/** @var \SplFixedArray<Block> */
private static $fullList = null;
/**
* @var \SplFixedArray|Block[]
* @phpstan-var \SplFixedArray<Block>
*/
private static $fullList;
/** @var \SplFixedArray<bool> */
public static $solid = null;
/** @var \SplFixedArray<bool> */
public static $transparent = null;
/** @var \SplFixedArray<float> */
public static $hardness = null;
/** @var \SplFixedArray<int> */
public static $light = null;
/** @var \SplFixedArray<int> */
public static $lightFilter = null;
/** @var \SplFixedArray<bool> */
public static $diffusesSkyLight = null;
/** @var \SplFixedArray<float> */
public static $blastResistance = null;
/**
* @var \SplFixedArray|bool[]
* @phpstan-var \SplFixedArray<bool>
*/
public static $solid;
/**
* @var \SplFixedArray|bool[]
* @phpstan-var \SplFixedArray<bool>
*/
public static $transparent;
/**
* @var \SplFixedArray|float[]
* @phpstan-var \SplFixedArray<float>
*/
public static $hardness;
/**
* @var \SplFixedArray|int[]
* @phpstan-var \SplFixedArray<int>
*/
public static $light;
/**
* @var \SplFixedArray|int[]
* @phpstan-var \SplFixedArray<int>
*/
public static $lightFilter;
/**
* @var \SplFixedArray|bool[]
* @phpstan-var \SplFixedArray<bool>
*/
public static $diffusesSkyLight;
/**
* @var \SplFixedArray|float[]
* @phpstan-var \SplFixedArray<float>
*/
public static $blastResistance;
/**
* Initializes the block factory. By default this is called only once on server start, however you may wish to use
@ -334,7 +358,6 @@ class BlockFactory{
* NOTE: If you are registering a new block type, you will need to add it to the creative inventory yourself - it
* will not automatically appear there.
*
* @param Block $block
* @param bool $override Whether to override existing registrations
*
* @throws \RuntimeException if something attempted to override an already-registered block without specifying the
@ -364,12 +387,6 @@ class BlockFactory{
/**
* Returns a new Block instance with the specified ID, meta and position.
*
* @param int $id
* @param int $meta
* @param Position $pos
*
* @return Block
*/
public static function get(int $id, int $meta = 0, Position $pos = null) : Block{
if($meta < 0 or $meta > 0xf){
@ -398,7 +415,7 @@ class BlockFactory{
/**
* @internal
* @return \SplFixedArray
* @phpstan-return \SplFixedArray<Block>
*/
public static function getBlockStatesArray() : \SplFixedArray{
return self::$fullList;
@ -406,10 +423,6 @@ class BlockFactory{
/**
* Returns whether a specified block ID is already registered in the block factory.
*
* @param int $id
*
* @return bool
*/
public static function isRegistered(int $id) : bool{
$b = self::$fullList[$id << 4];
@ -419,11 +432,6 @@ class BlockFactory{
/**
* @internal
* @deprecated
*
* @param int $id
* @param int $meta
*
* @return int
*/
public static function toStaticRuntimeId(int $id, int $meta = 0) : int{
return RuntimeBlockMapping::toStaticRuntimeId($id, $meta);
@ -433,8 +441,6 @@ class BlockFactory{
* @deprecated
* @internal
*
* @param int $runtimeId
*
* @return int[] [id, meta]
*/
public static function fromStaticRuntimeId(int $runtimeId) : array{

View File

@ -116,7 +116,7 @@ class Chest extends Transparent{
if(
!$this->getSide(Vector3::SIDE_UP)->isTransparent() or
($chest->isPaired() and !$chest->getPair()->getBlock()->getSide(Vector3::SIDE_UP)->isTransparent()) or
(($pair = $chest->getPair()) !== null and !$pair->getBlock()->getSide(Vector3::SIDE_UP)->isTransparent()) or
!$chest->canOpenWith($item->getCustomName())
){
return true;

View File

@ -111,6 +111,9 @@ class CobblestoneWall extends Transparent{
);
}
/**
* @return bool
*/
public function canConnect(Block $block){
return $block instanceof static or $block instanceof FenceGate or ($block->isSolid() and !$block->isTransparent());
}

View File

@ -53,16 +53,10 @@ class ConcretePowder extends Fallable{
}
}
/**
* @return null|Block
*/
public function tickFalling() : ?Block{
return $this->checkAdjacentWater();
}
/**
* @return null|Block
*/
private function checkAdjacentWater() : ?Block{
for($i = 1; $i < 6; ++$i){ //Do not check underneath
if($this->getSide($i) instanceof Water){

View File

@ -41,7 +41,6 @@ abstract class Crops extends Flowable{
return false;
}
public function onActivate(Item $item, Player $player = null) : bool{
if($this->meta < 7 and $item->getId() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
$block = clone $this;

View File

@ -39,7 +39,6 @@ class Dandelion extends Flowable{
return "Dandelion";
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === Block::GRASS or $down->getId() === Block::DIRT or $down->getId() === Block::FARMLAND){

View File

@ -29,14 +29,13 @@ use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\Player;
abstract class Door extends Transparent{
public function isSolid() : bool{
return false;
}
private function getFullDamage(){
private function getFullDamage() : int{
$damage = $this->getDamage();
$isUp = ($damage & 0x08) > 0;

View File

@ -68,10 +68,9 @@ class DoublePlant extends Flowable{
/**
* Returns whether this double-plant has a corresponding other half.
* @return bool
*/
public function isValidHalfPlant() : bool{
if($this->meta & self::BITFLAG_TOP){
if(($this->meta & self::BITFLAG_TOP) !== 0){
$other = $this->getSide(Vector3::SIDE_DOWN);
}else{
$other = $this->getSide(Vector3::SIDE_UP);
@ -103,7 +102,7 @@ class DoublePlant extends Flowable{
}
public function getDrops(Item $item) : array{
if($this->meta & self::BITFLAG_TOP){
if(($this->meta & self::BITFLAG_TOP) !== 0){
if($this->isCompatibleWithTool($item)){
return parent::getDrops($item);
}

View File

@ -45,9 +45,6 @@ abstract class Fallable extends Solid{
}
}
/**
* @return null|Block
*/
public function tickFalling() : ?Block{
return null;
}

View File

@ -48,7 +48,6 @@ class Farmland extends Transparent{
return BlockToolType::TYPE_SHOVEL;
}
protected function recalculateBoundingBox() : ?AxisAlignedBB{
return new AxisAlignedBB(
$this->x,

View File

@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use function count;
abstract class Fence extends Transparent{
@ -85,7 +86,7 @@ abstract class Fence extends Transparent{
);
}
if(empty($bbs)){
if(count($bbs) === 0){
//centre post AABB (only needed if not connected on any axis - other BBs overlapping will do this if any connections are made)
return [
new AxisAlignedBB(
@ -102,6 +103,9 @@ abstract class Fence extends Transparent{
return $bbs;
}
/**
* @return bool
*/
public function canConnect(Block $block){
return $block instanceof static or $block instanceof FenceGate or ($block->isSolid() and !$block->isTransparent());
}

View File

@ -39,7 +39,6 @@ class FenceGate extends Transparent{
return BlockToolType::TYPE_AXE;
}
protected function recalculateBoundingBox() : ?AxisAlignedBB{
if(($this->getDamage() & 0x04) > 0){

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace pocketmine\block;
class Furnace extends BurningFurnace{
protected $id = self::FURNACE;

View File

@ -1,6 +1,5 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\TieredTool;
class GlowingObsidian extends Solid{

View File

@ -90,7 +90,6 @@ class Ladder extends Transparent{
);
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
if(!$blockClicked->isTransparent()){
$faces = [

View File

@ -39,6 +39,7 @@ class Leaves extends Transparent{
public const DARK_OAK = 1;
protected $id = self::LEAVES;
/** @var int */
protected $woodType = self::WOOD;
public function __construct(int $meta = 0){
@ -67,8 +68,11 @@ class Leaves extends Transparent{
return true;
}
protected function findLog(Block $pos, array $visited, int $distance, ?int $fromSide = null) : bool{
/**
* @param true[] $visited reference parameter
* @phpstan-param array<string, true> $visited
*/
protected function findLog(Block $pos, array &$visited, int $distance, ?int $fromSide = null) : bool{
$index = $pos->x . "." . $pos->y . "." . $pos->z;
if(isset($visited[$index])){
return false;
@ -168,7 +172,7 @@ class Leaves extends Transparent{
}
public function getDrops(Item $item) : array{
if($item->getBlockToolType() & BlockToolType::TYPE_SHEARS){
if(($item->getBlockToolType() & BlockToolType::TYPE_SHEARS) !== 0){
return $this->getDropsForCompatibleTool($item);
}

View File

@ -29,6 +29,7 @@ use pocketmine\item\ItemFactory;
class Leaves2 extends Leaves{
protected $id = self::LEAVES2;
/** @var int */
protected $woodType = self::WOOD2;
public function getName() : string{

View File

@ -38,6 +38,7 @@ use function min;
abstract class Liquid extends Transparent{
/** @var int */
public $adjacentSources = 0;
/** @var Vector3|null */
@ -90,6 +91,9 @@ abstract class Liquid extends Transparent{
abstract public function getBucketEmptySound() : int;
/**
* @return float
*/
public function getFluidHeightPercent(){
$d = $this->meta;
if($d >= 8){
@ -207,8 +211,6 @@ abstract class Liquid extends Transparent{
/**
* Returns how many liquid levels are lost per block flowed horizontally. Affects how far the liquid can flow.
*
* @return int
*/
public function getFlowDecayPerBlock() : int{
return 1;
@ -430,6 +432,9 @@ abstract class Liquid extends Transparent{
return ($decay >= 0 && $blockDecay >= $decay) ? $decay : $blockDecay;
}
/**
* @return void
*/
protected function checkForHarden(){
}

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace pocketmine\block;
class MossyCobblestone extends Cobblestone{
protected $id = self::MOSSY_COBBLESTONE;

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\event\block\BlockGrowEvent;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;

View File

@ -57,7 +57,6 @@ class SignPost extends Transparent{
return null;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
if($face !== Vector3::SIDE_DOWN){

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace pocketmine\block;
class Sponge extends Solid{
protected $id = self::SPONGE;

View File

@ -74,6 +74,9 @@ class TNT extends Solid{
}
}
/**
* @return void
*/
public function ignite(int $fuse = 80){
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);

View File

@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use function count;
abstract class Thin extends Transparent{
@ -77,7 +78,7 @@ abstract class Thin extends Transparent{
);
}
if(empty($bbs)){
if(count($bbs) === 0){
//centre post AABB (only needed if not connected on any axis - other BBs overlapping will do this if any connections are made)
return [
new AxisAlignedBB(

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace pocketmine\block;
abstract class Transparent extends Block{
public function isTransparent() : bool{

View File

@ -197,7 +197,7 @@ class Vine extends Flowable{
}
public function getDrops(Item $item) : array{
if($item->getBlockToolType() & BlockToolType::TYPE_SHEARS){
if(($item->getBlockToolType() & BlockToolType::TYPE_SHEARS) !== 0){
return $this->getDropsForCompatibleTool($item);
}

View File

@ -55,7 +55,6 @@ class WaterLily extends Flowable{
);
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
if($blockClicked instanceof Water){
$up = $blockClicked->getSide(Vector3::SIDE_UP);

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace pocketmine\block;
class Wood2 extends Wood{
public const ACACIA = 0;

View File

@ -50,9 +50,7 @@ abstract class Command{
/** @var string[] */
private $aliases = [];
/**
* @var string[]
*/
/** @var string[] */
private $activeAliases = [];
/** @var CommandMap|null */
@ -67,16 +65,13 @@ abstract class Command{
/** @var string|null */
private $permission = null;
/** @var string */
/** @var string|null */
private $permissionMessage = null;
/** @var TimingsHandler */
public $timings;
/** @var TimingsHandler|null */
public $timings = null;
/**
* @param string $name
* @param string $description
* @param string $usageMessage
* @param string[] $aliases
*/
public function __construct(string $name, string $description = "", string $usageMessage = null, array $aliases = []){
@ -88,18 +83,13 @@ abstract class Command{
}
/**
* @param CommandSender $sender
* @param string $commandLabel
* @param string[] $args
* @param string[] $args
*
* @return mixed
* @throws CommandException
*/
abstract public function execute(CommandSender $sender, string $commandLabel, array $args);
/**
* @return string
*/
public function getName() : string{
return $this->name;
}
@ -111,19 +101,13 @@ abstract class Command{
return $this->permission;
}
/**
* @param string|null $permission
* @return void
*/
public function setPermission(string $permission = null){
$this->permission = $permission;
}
/**
* @param CommandSender $target
*
* @return bool
*/
public function testPermission(CommandSender $target) : bool{
if($this->testPermissionSilent($target)){
return true;
@ -138,11 +122,6 @@ abstract class Command{
return false;
}
/**
* @param CommandSender $target
*
* @return bool
*/
public function testPermissionSilent(CommandSender $target) : bool{
if($this->permission === null or $this->permission === ""){
return true;
@ -157,9 +136,6 @@ abstract class Command{
return false;
}
/**
* @return string
*/
public function getLabel() : string{
return $this->label;
}
@ -181,10 +157,6 @@ abstract class Command{
/**
* Registers the command into a Command map
*
* @param CommandMap $commandMap
*
* @return bool
*/
public function register(CommandMap $commandMap) : bool{
if($this->allowChangesFrom($commandMap)){
@ -196,11 +168,6 @@ abstract class Command{
return false;
}
/**
* @param CommandMap $commandMap
*
* @return bool
*/
public function unregister(CommandMap $commandMap) : bool{
if($this->allowChangesFrom($commandMap)){
$this->commandMap = null;
@ -213,18 +180,10 @@ abstract class Command{
return false;
}
/**
* @param CommandMap $commandMap
*
* @return bool
*/
private function allowChangesFrom(CommandMap $commandMap) : bool{
return $this->commandMap === null or $this->commandMap === $commandMap;
}
/**
* @return bool
*/
public function isRegistered() : bool{
return $this->commandMap !== null;
}
@ -236,29 +195,22 @@ abstract class Command{
return $this->activeAliases;
}
/**
* @return string|null
*/
public function getPermissionMessage() : ?string{
return $this->permissionMessage;
}
/**
* @return string
*/
public function getDescription() : string{
return $this->description;
}
/**
* @return string
*/
public function getUsage() : string{
return $this->usageMessage;
}
/**
* @param string[] $aliases
*
* @return void
*/
public function setAliases(array $aliases){
$this->aliases = $aliases;
@ -268,30 +220,30 @@ abstract class Command{
}
/**
* @param string $description
* @return void
*/
public function setDescription(string $description){
$this->description = $description;
}
/**
* @param string $permissionMessage
* @return void
*/
public function setPermissionMessage(string $permissionMessage){
$this->permissionMessage = $permissionMessage;
}
/**
* @param string $usage
* @return void
*/
public function setUsage(string $usage){
$this->usageMessage = $usage;
}
/**
* @param CommandSender $source
* @param TextContainer|string $message
* @param bool $sendToSource
*
* @return void
*/
public static function broadcastCommandMessage(CommandSender $source, $message, bool $sendToSource = true){
if($message instanceof TextContainer){
@ -326,9 +278,6 @@ abstract class Command{
}
}
/**
* @return string
*/
public function __toString() : string{
return $this->name;
}

View File

@ -23,16 +23,10 @@ declare(strict_types=1);
namespace pocketmine\command;
interface CommandExecutor{
/**
* @param CommandSender $sender
* @param Command $command
* @param string $label
* @param string[] $args
*
* @return bool
*/
public function onCommand(CommandSender $sender, Command $command, string $label, array $args) : bool;

View File

@ -23,30 +23,17 @@ declare(strict_types=1);
namespace pocketmine\command;
interface CommandMap{
/**
* @param string $fallbackPrefix
* @param Command[] $commands
*
* @return void
*/
public function registerAll(string $fallbackPrefix, array $commands);
/**
* @param string $fallbackPrefix
* @param Command $command
* @param string|null $label
*
* @return bool
*/
public function register(string $fallbackPrefix, Command $command, string $label = null) : bool;
/**
* @param CommandSender $sender
* @param string $cmdLine
*
* @return bool
*/
public function dispatch(CommandSender $sender, string $cmdLine) : bool;
/**
@ -55,11 +42,8 @@ interface CommandMap{
public function clearCommands();
/**
* @param string $name
*
* @return Command|null
*/
public function getCommand(string $name);
}

View File

@ -54,7 +54,9 @@ class CommandReader extends Thread{
/** @var \Threaded */
protected $buffer;
/** @var bool */
private $shutdown = false;
/** @var int */
private $type = self::TYPE_STREAM;
/** @var SleeperNotifier|null */
@ -71,6 +73,9 @@ class CommandReader extends Thread{
}
}
/**
* @return void
*/
public function shutdown(){
$this->shutdown = true;
}
@ -94,7 +99,7 @@ class CommandReader extends Thread{
throw new \ThreadException($message);
}
private function initStdin(){
private function initStdin() : void{
if(is_resource(self::$stdin)){
fclose(self::$stdin);
}
@ -111,8 +116,6 @@ class CommandReader extends Thread{
* Checks if the specified stream is a FIFO pipe.
*
* @param resource $stream
*
* @return bool
*/
private function isPipe($stream) : bool{
return is_resource($stream) and (!stream_isatty($stream) or ((fstat($stream)["mode"] & 0170000) === 0010000));
@ -151,7 +154,7 @@ class CommandReader extends Thread{
case self::TYPE_PIPED:
if(($raw = fgets(self::$stdin)) === false){ //broken pipe or EOF
$this->initStdin();
$this->synchronized(function(){
$this->synchronized(function() : void{
$this->wait(200000);
}); //prevent CPU waste if it's end of pipe
return true; //loop back round
@ -185,6 +188,9 @@ class CommandReader extends Thread{
return null;
}
/**
* @return void
*/
public function run(){
$this->registerClassLoader();

View File

@ -31,6 +31,8 @@ interface CommandSender extends Permissible{
/**
* @param TextContainer|string $message
*
* @return void
*/
public function sendMessage($message);
@ -39,23 +41,18 @@ interface CommandSender extends Permissible{
*/
public function getServer();
/**
* @return string
*/
public function getName() : string;
/**
* Returns the line height of the command-sender's screen. Used for determining sizes for command output pagination
* such as in the /help command.
*
* @return int
*/
public function getScreenLineHeight() : int;
/**
* Sets the line height used for command output pagination for this command sender. `null` will reset it to default.
*
* @param int|null $height
* @return void
*/
public function setScreenLineHeight(int $height = null);
}

View File

@ -37,6 +37,7 @@ use const PHP_INT_MAX;
class ConsoleCommandSender implements CommandSender{
/** @var PermissibleBase */
private $perm;
/** @var int|null */
@ -48,8 +49,6 @@ class ConsoleCommandSender implements CommandSender{
/**
* @param Permission|string $name
*
* @return bool
*/
public function isPermissionSet($name) : bool{
return $this->perm->isPermissionSet($name);
@ -57,27 +56,16 @@ class ConsoleCommandSender implements CommandSender{
/**
* @param Permission|string $name
*
* @return bool
*/
public function hasPermission($name) : bool{
return $this->perm->hasPermission($name);
}
/**
* @param Plugin $plugin
* @param string $name
* @param bool $value
*
* @return PermissionAttachment
*/
public function addAttachment(Plugin $plugin, string $name = null, bool $value = null) : PermissionAttachment{
return $this->perm->addAttachment($plugin, $name, $value);
}
/**
* @param PermissionAttachment $attachment
*
* @return void
*/
public function removeAttachment(PermissionAttachment $attachment){
@ -104,6 +92,8 @@ class ConsoleCommandSender implements CommandSender{
/**
* @param TextContainer|string $message
*
* @return void
*/
public function sendMessage($message){
if($message instanceof TextContainer){
@ -117,22 +107,16 @@ class ConsoleCommandSender implements CommandSender{
}
}
/**
* @return string
*/
public function getName() : string{
return "CONSOLE";
}
/**
* @return bool
*/
public function isOp() : bool{
return true;
}
/**
* @param bool $value
* @return void
*/
public function setOp(bool $value){

View File

@ -32,10 +32,10 @@ use function strpos;
use function substr;
class FormattedCommandAlias extends Command{
/** @var string[] */
private $formatStrings = [];
/**
* @param string $alias
* @param string[] $formatStrings
*/
public function __construct(string $alias, array $formatStrings){
@ -65,10 +65,7 @@ class FormattedCommandAlias extends Command{
}
/**
* @param string $formatString
* @param array $args
*
* @return string
* @param string[] $args
*/
private function buildCommand(string $formatString, array $args) : string{
$index = strpos($formatString, '$');
@ -143,13 +140,6 @@ class FormattedCommandAlias extends Command{
return $formatString;
}
/**
* @param int $i
* @param int $j
* @param int $k
*
* @return bool
*/
private static function inRange(int $i, int $j, int $k) : bool{
return $i >= $j and $i <= $k;
}

View File

@ -34,10 +34,6 @@ class PluginCommand extends Command implements PluginIdentifiableCommand{
/** @var CommandExecutor */
private $executor;
/**
* @param string $name
* @param Plugin $owner
*/
public function __construct(string $name, Plugin $owner){
parent::__construct($name);
$this->owningPlugin = $owner;
@ -69,15 +65,12 @@ class PluginCommand extends Command implements PluginIdentifiableCommand{
}
/**
* @param CommandExecutor $executor
* @return void
*/
public function setExecutor(CommandExecutor $executor){
$this->executor = $executor;
}
/**
* @return Plugin
*/
public function getPlugin() : Plugin{
return $this->owningPlugin;
}

View File

@ -27,8 +27,5 @@ use pocketmine\plugin\Plugin;
interface PluginIdentifiableCommand{
/**
* @return Plugin
*/
public function getPlugin() : Plugin;
}

View File

@ -41,6 +41,9 @@ class RemoteConsoleCommandSender extends ConsoleCommandSender{
$this->messages .= trim($message, "\r\n") . "\n";
}
/**
* @return string
*/
public function getMessage(){
return $this->messages;
}

View File

@ -72,6 +72,7 @@ use function explode;
use function implode;
use function min;
use function preg_match_all;
use function strcasecmp;
use function stripslashes;
use function strpos;
use function strtolower;
@ -79,9 +80,7 @@ use function trim;
class SimpleCommandMap implements CommandMap{
/**
* @var Command[]
*/
/** @var Command[] */
protected $knownCommands = [];
/** @var Server */
@ -92,7 +91,7 @@ class SimpleCommandMap implements CommandMap{
$this->setDefaultCommands();
}
private function setDefaultCommands(){
private function setDefaultCommands() : void{
$this->registerAll("pocketmine", [
new BanCommand("ban"),
new BanIpCommand("ban-ip"),
@ -137,20 +136,12 @@ class SimpleCommandMap implements CommandMap{
]);
}
public function registerAll(string $fallbackPrefix, array $commands){
foreach($commands as $command){
$this->register($fallbackPrefix, $command);
}
}
/**
* @param string $fallbackPrefix
* @param Command $command
* @param string|null $label
*
* @return bool
*/
public function register(string $fallbackPrefix, Command $command, string $label = null) : bool{
if($label === null){
$label = $command->getName();
@ -177,11 +168,6 @@ class SimpleCommandMap implements CommandMap{
return $registered;
}
/**
* @param Command $command
*
* @return bool
*/
public function unregister(Command $command) : bool{
foreach($this->knownCommands as $lbl => $cmd){
if($cmd === $command){
@ -194,21 +180,13 @@ class SimpleCommandMap implements CommandMap{
return true;
}
/**
* @param Command $command
* @param bool $isAlias
* @param string $fallbackPrefix
* @param string $label
*
* @return bool
*/
private function registerAlias(Command $command, bool $isAlias, string $fallbackPrefix, string $label) : bool{
$this->knownCommands[$fallbackPrefix . ":" . $label] = $command;
if(($command instanceof VanillaCommand or $isAlias) and isset($this->knownCommands[$label])){
return false;
}
if(isset($this->knownCommands[$label]) and $this->knownCommands[$label]->getLabel() !== null and $this->knownCommands[$label]->getLabel() === $label){
if(isset($this->knownCommands[$label]) and $this->knownCommands[$label]->getLabel() === $label){
return false;
}
@ -226,8 +204,8 @@ class SimpleCommandMap implements CommandMap{
* This method is intended to provide capability for handling commands with spaces in their name.
* The referenced parameters will be modified accordingly depending on the resulting matched command.
*
* @param string &$commandName
* @param string[] &$args
* @param string $commandName reference parameter
* @param string[] $args reference parameter
*
* @return Command|null
*/
@ -296,7 +274,6 @@ class SimpleCommandMap implements CommandMap{
return $this->knownCommands;
}
/**
* @return void
*/
@ -318,22 +295,21 @@ class SimpleCommandMap implements CommandMap{
$commandName = "";
$command = $this->matchCommand($commandName, $args);
if($command === null){
$bad[] = $commandString;
}elseif($commandName === $alias){
}elseif(strcasecmp($commandName, $alias) === 0){
$recursive[] = $commandString;
}else{
$targets[] = $commandString;
}
}
if(!empty($recursive)){
if(count($recursive) > 0){
$this->server->getLogger()->warning($this->server->getLanguage()->translateString("pocketmine.command.alias.recursive", [$alias, implode(", ", $recursive)]));
continue;
}
if(!empty($bad)){
if(count($bad) > 0){
$this->server->getLogger()->warning($this->server->getLanguage()->translateString("pocketmine.command.alias.notFound", [$alias, implode(", ", $bad)]));
continue;
}

View File

@ -75,7 +75,7 @@ class BanIpCommand extends VanillaCommand{
return true;
}
private function processIPBan(string $ip, CommandSender $sender, string $reason){
private function processIPBan(string $ip, CommandSender $sender, string $reason) : void{
$sender->getServer()->getIPBans()->addBan($ip, $reason, null, $sender->getName());
foreach($sender->getServer()->getOnlinePlayers() as $player){

View File

@ -63,7 +63,7 @@ class BanListCommand extends VanillaCommand{
}
$list = $list->getEntries();
$message = implode(", ", array_map(function(BanEntry $entry){
$message = implode(", ", array_map(function(BanEntry $entry) : string{
return $entry->getName();
}, $list));

View File

@ -76,7 +76,7 @@ class EffectCommand extends VanillaCommand{
}
if($effect === null){
$sender->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.effect.notFound", [(string) $args[1]]));
$sender->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.effect.notFound", [$args[1]]));
return true;
}
@ -124,7 +124,6 @@ class EffectCommand extends VanillaCommand{
self::broadcastCommandMessage($sender, new TranslationContainer("%commands.effect.success", [$effect->getName(), $instance->getAmplifier(), $player->getDisplayName(), $instance->getDuration() / 20, $effect->getId()]));
}
return true;
}
}

View File

@ -88,7 +88,6 @@ class EnchantCommand extends VanillaCommand{
$item->addEnchantment(new EnchantmentInstance($enchantment, $level));
$player->getInventory()->setItemInHand($item);
self::broadcastCommandMessage($sender, new TranslationContainer("%commands.enchant.success", [$player->getName()]));
return true;
}

View File

@ -57,22 +57,22 @@ class HelpCommand extends VanillaCommand{
}
if(count($args) === 0){
$command = "";
$commandName = "";
$pageNumber = 1;
}elseif(is_numeric($args[count($args) - 1])){
$pageNumber = (int) array_pop($args);
if($pageNumber <= 0){
$pageNumber = 1;
}
$command = implode(" ", $args);
$commandName = implode(" ", $args);
}else{
$command = implode(" ", $args);
$commandName = implode(" ", $args);
$pageNumber = 1;
}
$pageHeight = $sender->getScreenLineHeight();
if($command === ""){
if($commandName === ""){
/** @var Command[][] $commands */
$commands = [];
foreach($sender->getServer()->getCommandMap()->getCommands() as $command){
@ -82,7 +82,7 @@ class HelpCommand extends VanillaCommand{
}
ksort($commands, SORT_NATURAL | SORT_FLAG_CASE);
$commands = array_chunk($commands, $pageHeight);
$pageNumber = (int) min(count($commands), $pageNumber);
$pageNumber = min(count($commands), $pageNumber);
if($pageNumber < 1){
$pageNumber = 1;
}
@ -95,7 +95,7 @@ class HelpCommand extends VanillaCommand{
return true;
}else{
if(($cmd = $sender->getServer()->getCommandMap()->getCommand(strtolower($command))) instanceof Command){
if(($cmd = $sender->getServer()->getCommandMap()->getCommand(strtolower($commandName))) instanceof Command){
if($cmd->testPermissionSilent($sender)){
$message = TextFormat::YELLOW . "--------- " . TextFormat::WHITE . " Help: /" . $cmd->getName() . TextFormat::YELLOW . " ---------\n";
$message .= TextFormat::GOLD . "Description: " . TextFormat::WHITE . $cmd->getDescription() . "\n";
@ -105,7 +105,7 @@ class HelpCommand extends VanillaCommand{
return true;
}
}
$sender->sendMessage(TextFormat::RED . "No help for " . strtolower($command));
$sender->sendMessage(TextFormat::RED . "No help for " . strtolower($commandName));
return true;
}

View File

@ -68,7 +68,6 @@ class KickCommand extends VanillaCommand{
$sender->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.generic.player.notFound"));
}
return true;
}
}

View File

@ -47,9 +47,9 @@ class ListCommand extends VanillaCommand{
return true;
}
$playerNames = array_map(function(Player $player){
$playerNames = array_map(function(Player $player) : string{
return $player->getName();
}, array_filter($sender->getServer()->getOnlinePlayers(), function(Player $player) use ($sender){
}, array_filter($sender->getServer()->getOnlinePlayers(), function(Player $player) use ($sender) : bool{
return $player->isOnline() and (!($sender instanceof Player) or $sender->canSee($player));
}));

View File

@ -119,7 +119,6 @@ class ParticleCommand extends VanillaCommand{
return true;
}
$sender->sendMessage(new TranslationContainer("commands.particle.success", [$name, $count]));
$random = new Random((int) (microtime(true) * 1000) + mt_rand());
@ -137,13 +136,6 @@ class ParticleCommand extends VanillaCommand{
}
/**
* @param string $name
* @param Vector3 $pos
* @param float $xd
* @param float $yd
* @param float $zd
* @param int|null $data
*
* @return Particle|null
*/
private function getParticle(string $name, Vector3 $pos, float $xd, float $yd, float $zd, int $data = null){

View File

@ -52,7 +52,7 @@ class TeleportCommand extends VanillaCommand{
return true;
}
$args = array_values(array_filter($args, function($arg){
$args = array_values(array_filter($args, function(string $arg) : bool{
return $arg !== "";
}));
if(count($args) < 1 or count($args) > 6){

View File

@ -85,7 +85,6 @@ class TimeCommand extends VanillaCommand{
return true;
}
if(count($args) < 2){
throw new InvalidCommandSyntaxException();
}

View File

@ -126,18 +126,25 @@ class TimingsCommand extends VanillaCommand{
/** @var string */
private $host;
/**
* @param string[] $data
* @phpstan-param array<string, string> $data
*/
public function __construct(CommandSender $sender, string $host, string $agent, array $data){
parent::__construct([
["page" => "https://$host?upload=true", "extraOpts" => [
CURLOPT_HTTPHEADER => [
"User-Agent: $agent",
"Content-Type: application/x-www-form-urlencoded"
],
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($data),
CURLOPT_AUTOREFERER => false,
CURLOPT_FOLLOWLOCATION => false
]]
[
"page" => "https://$host?upload=true",
"extraOpts" => [
CURLOPT_HTTPHEADER => [
"User-Agent: $agent",
"Content-Type: application/x-www-form-urlencoded"
],
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($data),
CURLOPT_AUTOREFERER => false,
CURLOPT_FOLLOWLOCATION => false
]
]
], $sender);
$this->host = $host;
}

View File

@ -21,10 +21,8 @@
declare(strict_types=1);
namespace pocketmine\command\defaults;
use pocketmine\command\CommandSender;
use pocketmine\command\utils\InvalidCommandSyntaxException;
use pocketmine\Player;

View File

@ -36,12 +36,7 @@ abstract class VanillaCommand extends Command{
public const MIN_COORD = -30000000;
/**
* @param CommandSender $sender
* @param mixed $value
* @param int $min
* @param int $max
*
* @return int
*/
protected function getInteger(CommandSender $sender, $value, int $min = self::MIN_COORD, int $max = self::MAX_COORD) : int{
$i = (int) $value;
@ -55,15 +50,6 @@ abstract class VanillaCommand extends Command{
return $i;
}
/**
* @param float $original
* @param CommandSender $sender
* @param string $input
* @param float $min
* @param float $max
*
* @return float
*/
protected function getRelativeDouble(float $original, CommandSender $sender, string $input, float $min = self::MIN_COORD, float $max = self::MAX_COORD) : float{
if($input[0] === "~"){
$value = $this->getDouble($sender, substr($input, 1));
@ -75,12 +61,7 @@ abstract class VanillaCommand extends Command{
}
/**
* @param CommandSender $sender
* @param mixed $value
* @param float $min
* @param float $max
*
* @return float
*/
protected function getDouble(CommandSender $sender, $value, float $min = self::MIN_COORD, float $max = self::MAX_COORD) : float{
$i = (double) $value;

View File

@ -84,7 +84,7 @@ class VersionCommand extends VanillaCommand{
return true;
}
private function describeToSender(Plugin $plugin, CommandSender $sender){
private function describeToSender(Plugin $plugin, CommandSender $sender) : void{
$desc = $plugin->getDescription();
$sender->sendMessage(TextFormat::DARK_GREEN . $desc->getName() . TextFormat::WHITE . " version " . TextFormat::DARK_GREEN . $desc->getVersion());

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace pocketmine\entity;
interface Ageable{
public function isBaby() : bool;
}

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace pocketmine\entity;
abstract class Animal extends Creature implements Ageable{
public function isBaby() : bool{

View File

@ -46,14 +46,22 @@ class Attribute{
public const HORSE_JUMP_STRENGTH = 14;
public const ZOMBIE_SPAWN_REINFORCEMENTS = 15;
/** @var int */
private $id;
/** @var float */
protected $minValue;
/** @var float */
protected $maxValue;
/** @var float */
protected $defaultValue;
/** @var float */
protected $currentValue;
/** @var string */
protected $name;
/** @var bool */
protected $shouldSend;
/** @var bool */
protected $desynchronized = true;
/** @var Attribute[] */
@ -79,15 +87,6 @@ class Attribute{
}
/**
* @param int $id
* @param string $name
* @param float $minValue
* @param float $maxValue
* @param float $defaultValue
* @param bool $shouldSend
*
* @return Attribute
*
* @throws \InvalidArgumentException
*/
public static function addAttribute(int $id, string $name, float $minValue, float $maxValue, float $defaultValue, bool $shouldSend = true) : Attribute{
@ -98,20 +97,10 @@ class Attribute{
return self::$attributes[$id] = new Attribute($id, $name, $minValue, $maxValue, $defaultValue, $shouldSend);
}
/**
* @param int $id
*
* @return Attribute|null
*/
public static function getAttribute(int $id) : ?Attribute{
return isset(self::$attributes[$id]) ? clone self::$attributes[$id] : null;
}
/**
* @param string $name
*
* @return Attribute|null
*/
public static function getAttributeByName(string $name) : ?Attribute{
foreach(self::$attributes as $a){
if($a->getName() === $name){
@ -137,6 +126,9 @@ class Attribute{
return $this->minValue;
}
/**
* @return $this
*/
public function setMinValue(float $minValue){
if($minValue > ($max = $this->getMaxValue())){
throw new \InvalidArgumentException("Minimum $minValue is greater than the maximum $max");
@ -153,6 +145,9 @@ class Attribute{
return $this->maxValue;
}
/**
* @return $this
*/
public function setMaxValue(float $maxValue){
if($maxValue < ($min = $this->getMinValue())){
throw new \InvalidArgumentException("Maximum $maxValue is less than the minimum $min");
@ -169,6 +164,9 @@ class Attribute{
return $this->defaultValue;
}
/**
* @return $this
*/
public function setDefaultValue(float $defaultValue){
if($defaultValue > $this->getMaxValue() or $defaultValue < $this->getMinValue()){
throw new \InvalidArgumentException("Default $defaultValue is outside the range " . $this->getMinValue() . " - " . $this->getMaxValue());
@ -190,10 +188,6 @@ class Attribute{
}
/**
* @param float $value
* @param bool $fit
* @param bool $forceSend
*
* @return $this
*/
public function setValue(float $value, bool $fit = false, bool $forceSend = false){

View File

@ -25,6 +25,9 @@ namespace pocketmine\entity;
use function array_filter;
/**
* @phpstan-implements \ArrayAccess<int, float>
*/
class AttributeMap implements \ArrayAccess{
/** @var Attribute[] */
private $attributes = [];
@ -33,11 +36,6 @@ class AttributeMap implements \ArrayAccess{
$this->attributes[$attribute->getId()] = $attribute;
}
/**
* @param int $id
*
* @return Attribute|null
*/
public function getAttribute(int $id) : ?Attribute{
return $this->attributes[$id] ?? null;
}
@ -53,19 +51,20 @@ class AttributeMap implements \ArrayAccess{
* @return Attribute[]
*/
public function needSend() : array{
return array_filter($this->attributes, function(Attribute $attribute){
return array_filter($this->attributes, function(Attribute $attribute) : bool{
return $attribute->isSyncable() and $attribute->isDesynchronized();
});
}
/**
* @param int $offset
*/
public function offsetExists($offset) : bool{
return isset($this->attributes[$offset]);
}
/**
* @param int $offset
*
* @return float
*/
public function offsetGet($offset) : float{
return $this->attributes[$offset]->getValue();
@ -79,6 +78,9 @@ class AttributeMap implements \ArrayAccess{
$this->attributes[$offset]->setValue($value);
}
/**
* @param int $offset
*/
public function offsetUnset($offset) : void{
throw new \RuntimeException("Could not unset an attribute from an attribute map");
}

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace pocketmine\entity;
abstract class Creature extends Living{
}

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace pocketmine\entity;
interface Damageable{
}

View File

@ -32,110 +32,68 @@ use function is_string;
class DataPropertyManager{
/**
* @var mixed[][]
* @phpstan-var array<int, array{0: int, 1: mixed}>
*/
private $properties = [];
/**
* @var mixed[][]
* @phpstan-var array<int, array{0: int, 1: mixed}>
*/
private $dirtyProperties = [];
public function __construct(){
}
/**
* @param int $key
*
* @return int|null
*/
public function getByte(int $key) : ?int{
$value = $this->getPropertyValue($key, Entity::DATA_TYPE_BYTE);
assert(is_int($value) or $value === null);
return $value;
}
/**
* @param int $key
* @param int $value
* @param bool $force
*/
public function setByte(int $key, int $value, bool $force = false) : void{
$this->setPropertyValue($key, Entity::DATA_TYPE_BYTE, $value, $force);
}
/**
* @param int $key
*
* @return int|null
*/
public function getShort(int $key) : ?int{
$value = $this->getPropertyValue($key, Entity::DATA_TYPE_SHORT);
assert(is_int($value) or $value === null);
return $value;
}
/**
* @param int $key
* @param int $value
* @param bool $force
*/
public function setShort(int $key, int $value, bool $force = false) : void{
$this->setPropertyValue($key, Entity::DATA_TYPE_SHORT, $value, $force);
}
/**
* @param int $key
*
* @return int|null
*/
public function getInt(int $key) : ?int{
$value = $this->getPropertyValue($key, Entity::DATA_TYPE_INT);
assert(is_int($value) or $value === null);
return $value;
}
/**
* @param int $key
* @param int $value
* @param bool $force
*/
public function setInt(int $key, int $value, bool $force = false) : void{
$this->setPropertyValue($key, Entity::DATA_TYPE_INT, $value, $force);
}
/**
* @param int $key
*
* @return float|null
*/
public function getFloat(int $key) : ?float{
$value = $this->getPropertyValue($key, Entity::DATA_TYPE_FLOAT);
assert(is_float($value) or $value === null);
return $value;
}
/**
* @param int $key
* @param float $value
* @param bool $force
*/
public function setFloat(int $key, float $value, bool $force = false) : void{
$this->setPropertyValue($key, Entity::DATA_TYPE_FLOAT, $value, $force);
}
/**
* @param int $key
*
* @return null|string
*/
public function getString(int $key) : ?string{
$value = $this->getPropertyValue($key, Entity::DATA_TYPE_STRING);
assert(is_string($value) or $value === null);
return $value;
}
/**
* @param int $key
* @param string $value
* @param bool $force
*/
public function setString(int $key, string $value, bool $force = false) : void{
$this->setPropertyValue($key, Entity::DATA_TYPE_STRING, $value, $force);
}
@ -150,87 +108,44 @@ class DataPropertyManager{
$this->setPropertyValue($key, Entity::DATA_TYPE_COMPOUND_TAG, $value, $force);
}
/**
* @param int $key
*
* @return null|Vector3
*/
public function getBlockPos(int $key) : ?Vector3{
$value = $this->getPropertyValue($key, Entity::DATA_TYPE_POS);
assert($value instanceof Vector3 or $value === null);
return $value;
}
/**
* @param int $key
* @param null|Vector3 $value
* @param bool $force
*/
public function setBlockPos(int $key, ?Vector3 $value, bool $force = false) : void{
$this->setPropertyValue($key, Entity::DATA_TYPE_POS, $value ? $value->floor() : null, $force);
$this->setPropertyValue($key, Entity::DATA_TYPE_POS, $value !== null ? $value->floor() : null, $force);
}
/**
* @param int $key
*
* @return int|null
*/
public function getLong(int $key) : ?int{
$value = $this->getPropertyValue($key, Entity::DATA_TYPE_LONG);
assert(is_int($value) or $value === null);
return $value;
}
/**
* @param int $key
* @param int $value
* @param bool $force
*/
public function setLong(int $key, int $value, bool $force = false) : void{
$this->setPropertyValue($key, Entity::DATA_TYPE_LONG, $value, $force);
}
/**
* @param int $key
*
* @return null|Vector3
*/
public function getVector3(int $key) : ?Vector3{
$value = $this->getPropertyValue($key, Entity::DATA_TYPE_VECTOR3F);
assert($value instanceof Vector3 or $value === null);
return $value;
}
/**
* @param int $key
* @param null|Vector3 $value
* @param bool $force
*/
public function setVector3(int $key, ?Vector3 $value, bool $force = false) : void{
$this->setPropertyValue($key, Entity::DATA_TYPE_VECTOR3F, $value ? $value->asVector3() : null, $force);
$this->setPropertyValue($key, Entity::DATA_TYPE_VECTOR3F, $value !== null ? $value->asVector3() : null, $force);
}
/**
* @param int $key
*/
public function removeProperty(int $key) : void{
unset($this->properties[$key]);
}
/**
* @param int $key
*
* @return bool
*/
public function hasProperty(int $key) : bool{
return isset($this->properties[$key]);
}
/**
* @param int $key
*
* @return int
*/
public function getPropertyType(int $key) : int{
if(isset($this->properties[$key])){
return $this->properties[$key][0];
@ -246,9 +161,6 @@ class DataPropertyManager{
}
/**
* @param int $key
* @param int $type
*
* @return mixed
*/
public function getPropertyValue(int $key, int $type){
@ -259,10 +171,7 @@ class DataPropertyManager{
}
/**
* @param int $key
* @param int $type
* @param mixed $value
* @param bool $force
*/
public function setPropertyValue(int $key, int $type, $value, bool $force = false) : void{
if(!$force){
@ -274,7 +183,8 @@ class DataPropertyManager{
/**
* Returns all properties.
*
* @return array
* @return mixed[][]
* @phpstan-return array<int, array{0: int, 1: mixed}>
*/
public function getAll() : array{
return $this->properties;
@ -283,7 +193,8 @@ class DataPropertyManager{
/**
* Returns properties that have changed and need to be broadcasted.
*
* @return array
* @return mixed[][]
* @phpstan-return array<int, array{0: int, 1: mixed}>
*/
public function getDirty() : array{
return $this->dirtyProperties;

View File

@ -93,27 +93,14 @@ class Effect{
self::registerEffect(new Effect(Effect::CONDUIT_POWER, "%potion.conduitPower", new Color(0x1d, 0xc2, 0xd1)));
}
/**
* @param Effect $effect
*/
public static function registerEffect(Effect $effect) : void{
self::$effects[$effect->getId()] = $effect;
}
/**
* @param int $id
*
* @return Effect|null
*/
public static function getEffect(int $id) : ?Effect{
return self::$effects[$id] ?? null;
}
/**
* @param string $name
*
* @return Effect|null
*/
public static function getEffectByName(string $name) : ?Effect{
$const = self::class . "::" . strtoupper($name);
if(defined($const)){
@ -154,7 +141,6 @@ class Effect{
/**
* Returns the effect ID as per Minecraft PE
* @return int
*/
public function getId() : int{
return $this->id;
@ -162,7 +148,6 @@ class Effect{
/**
* Returns the translation key used to translate this effect's name.
* @return string
*/
public function getName() : string{
return $this->name;
@ -170,7 +155,6 @@ class Effect{
/**
* Returns a Color object representing this effect's particle colour.
* @return Color
*/
public function getColor() : Color{
return clone $this->color;
@ -179,8 +163,6 @@ class Effect{
/**
* Returns whether this effect is harmful.
* TODO: implement inverse effect results for undead mobs
*
* @return bool
*/
public function isBad() : bool{
return $this->bad;
@ -188,15 +170,13 @@ class Effect{
/**
* Returns whether the effect is by default an instant effect.
* @return bool
*/
public function isInstantEffect() : bool{
return $this->defaultDuration <= 1;
}
/**
* Returns the default duration this effect will apply for if a duration is not specified.
* @return int
* Returns the default duration (in ticks) this effect will apply for if a duration is not specified.
*/
public function getDefaultDuration() : int{
return $this->defaultDuration;
@ -204,7 +184,6 @@ class Effect{
/**
* Returns whether this effect will give the subject potion bubbles.
* @return bool
*/
public function hasBubbles() : bool{
return $this->hasBubbles;
@ -212,10 +191,6 @@ class Effect{
/**
* Returns whether the effect will do something on the current tick.
*
* @param EffectInstance $instance
*
* @return bool
*/
public function canTick(EffectInstance $instance) : bool{
switch($this->id){
@ -248,12 +223,6 @@ class Effect{
/**
* Applies effect results to an entity. This will not be called unless canTick() returns true.
*
* @param Living $entity
* @param EffectInstance $instance
* @param float $potency
* @param null|Entity $source
* @param null|Entity $sourceOwner
*/
public function applyEffect(Living $entity, EffectInstance $instance, float $potency = 1.0, ?Entity $source = null, ?Entity $sourceOwner = null) : void{
switch($this->id){
@ -314,9 +283,6 @@ class Effect{
/**
* Applies effects to the entity when the effect is first added.
*
* @param Living $entity
* @param EffectInstance $instance
*/
public function add(Living $entity, EffectInstance $instance) : void{
switch($this->id){
@ -347,9 +313,6 @@ class Effect{
/**
* Removes the effect from the entity, resetting any changed values back to their original defaults.
*
* @param Living $entity
* @param EffectInstance $instance
*/
public function remove(Living $entity, EffectInstance $instance) : void{
switch($this->id){

View File

@ -47,12 +47,7 @@ class EffectInstance{
private $color;
/**
* @param Effect $effectType
* @param int|null $duration Passing null will use the effect type's default duration
* @param int $amplifier
* @param bool $visible
* @param bool $ambient
* @param null|Color $overrideColor
*/
public function __construct(Effect $effectType, ?int $duration = null, int $amplifier = 0, bool $visible = true, bool $ambient = false, ?Color $overrideColor = null){
$this->effectType = $effectType;
@ -67,22 +62,19 @@ class EffectInstance{
return $this->effectType->getId();
}
/**
* @return Effect
*/
public function getType() : Effect{
return $this->effectType;
}
/**
* @return int
* Returns the number of ticks remaining until the effect expires.
*/
public function getDuration() : int{
return $this->duration;
}
/**
* @param int $duration
* Sets the number of ticks remaining until the effect expires.
*
* @throws \InvalidArgumentException
*
@ -100,8 +92,6 @@ class EffectInstance{
/**
* Decreases the duration by the given number of ticks, without dropping below zero.
*
* @param int $ticks
*
* @return $this
*/
public function decreaseDuration(int $ticks) : EffectInstance{
@ -112,32 +102,23 @@ class EffectInstance{
/**
* Returns whether the duration has run out.
*
* @return bool
*/
public function hasExpired() : bool{
return $this->duration <= 0;
}
/**
* @return int
*/
public function getAmplifier() : int{
return $this->amplifier;
}
/**
* Returns the level of this effect, which is always one higher than the amplifier.
*
* @return int
*/
public function getEffectLevel() : int{
return $this->amplifier + 1;
}
/**
* @param int $amplifier
*
* @return $this
*/
public function setAmplifier(int $amplifier) : EffectInstance{
@ -148,16 +129,12 @@ class EffectInstance{
/**
* Returns whether this effect will produce some visible effect, such as bubbles or particles.
*
* @return bool
*/
public function isVisible() : bool{
return $this->visible;
}
/**
* @param bool $visible
*
* @return $this
*/
public function setVisible(bool $visible = true) : EffectInstance{
@ -170,16 +147,12 @@ class EffectInstance{
* Returns whether the effect originated from the ambient environment.
* Ambient effects can originate from things such as a Beacon's area of effect radius.
* If this flag is set, the amount of visible particles will be reduced by a factor of 5.
*
* @return bool
*/
public function isAmbient() : bool{
return $this->ambient;
}
/**
* @param bool $ambient
*
* @return $this
*/
public function setAmbient(bool $ambient = true) : EffectInstance{
@ -191,8 +164,6 @@ class EffectInstance{
/**
* Returns the particle colour of this effect instance. This can be overridden on a per-EffectInstance basis, so it
* is not reflective of the default colour of the effect.
*
* @return Color
*/
public function getColor() : Color{
return clone $this->color;
@ -200,10 +171,6 @@ class EffectInstance{
/**
* Sets the colour of this EffectInstance.
*
* @param Color $color
*
* @return EffectInstance
*/
public function setColor(Color $color) : EffectInstance{
$this->color = clone $color;
@ -213,8 +180,6 @@ class EffectInstance{
/**
* Resets the colour of this EffectInstance to the default specified by its type.
*
* @return EffectInstance
*/
public function resetColor() : EffectInstance{
$this->color = $this->effectType->getColor();

View File

@ -317,10 +317,17 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
public const DATA_PLAYER_FLAG_SLEEP = 1;
public const DATA_PLAYER_FLAG_DEAD = 2; //TODO: CHECK
/** @var int */
public static $entityCount = 1;
/** @var string[] */
/**
* @var string[]
* @phpstan-var array<int|string, class-string<Entity>>
*/
private static $knownEntities = [];
/** @var string[][] */
/**
* @var string[][]
* @phpstan-var array<class-string<Entity>, list<string>>
*/
private static $saveNames = [];
/**
@ -352,17 +359,12 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
PaintingMotive::init();
}
/**
* Creates an entity with the specified type, level and NBT, with optional additional arguments to pass to the
* entity's constructor
*
* @param int|string $type
* @param Level $level
* @param CompoundTag $nbt
* @param mixed ...$args
*
* @return Entity|null
*/
public static function createEntity($type, Level $level, CompoundTag $nbt, ...$args) : ?Entity{
if(isset(self::$knownEntities[$type])){
@ -380,15 +382,12 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
* @param string $className Class that extends Entity
* @param bool $force Force registration even if the entity does not have a valid network ID
* @param string[] $saveNames An array of save names which this entity might be saved under. Defaults to the short name of the class itself if empty.
* @phpstan-param class-string<Entity> $className
*
* NOTE: The first save name in the $saveNames array will be used when saving the entity to disk. The reflection
* name of the class will be appended to the end and only used if no other save names are specified.
*
* @return bool
*/
public static function registerEntity(string $className, bool $force = false, array $saveNames = []) : bool{
/** @var Entity $className */
$class = new \ReflectionClass($className);
if(is_a($className, Entity::class, true) and !$class->isAbstract()){
if($className::NETWORK_ID !== -1){
@ -416,13 +415,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* Helper function which creates minimal NBT needed to spawn an entity.
*
* @param Vector3 $pos
* @param Vector3|null $motion
* @param float $yaw
* @param float $pitch
*
* @return CompoundTag
*/
public static function createBaseNBT(Vector3 $pos, ?Vector3 $motion = null, float $yaw = 0.0, float $pitch = 0.0) : CompoundTag{
return new CompoundTag("", [
@ -432,9 +424,9 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
new DoubleTag("", $pos->z)
]),
new ListTag("Motion", [
new DoubleTag("", $motion ? $motion->x : 0.0),
new DoubleTag("", $motion ? $motion->y : 0.0),
new DoubleTag("", $motion ? $motion->z : 0.0)
new DoubleTag("", $motion !== null ? $motion->x : 0.0),
new DoubleTag("", $motion !== null ? $motion->y : 0.0),
new DoubleTag("", $motion !== null ? $motion->z : 0.0)
]),
new ListTag("Rotation", [
new FloatTag("", $yaw),
@ -443,9 +435,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
]);
}
/**
* @var Player[]
*/
/** @var Player[] */
protected $hasSpawned = [];
/** @var int */
@ -480,7 +470,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/** @var Vector3 */
public $temporalVector;
/** @var float */
public $lastYaw;
/** @var float */
@ -504,6 +493,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/** @var float */
private $health = 20.0;
/** @var int */
private $maxHealth = 20;
/** @var float */
@ -650,73 +640,42 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
}
/**
* @return string
*/
public function getNameTag() : string{
return $this->propertyManager->getString(self::DATA_NAMETAG);
}
/**
* @return bool
*/
public function isNameTagVisible() : bool{
return $this->getGenericFlag(self::DATA_FLAG_CAN_SHOW_NAMETAG);
}
/**
* @return bool
*/
public function isNameTagAlwaysVisible() : bool{
return $this->propertyManager->getByte(self::DATA_ALWAYS_SHOW_NAMETAG) === 1;
}
/**
* @param string $name
*/
public function setNameTag(string $name) : void{
$this->propertyManager->setString(self::DATA_NAMETAG, $name);
}
/**
* @param bool $value
*/
public function setNameTagVisible(bool $value = true) : void{
$this->setGenericFlag(self::DATA_FLAG_CAN_SHOW_NAMETAG, $value);
}
/**
* @param bool $value
*/
public function setNameTagAlwaysVisible(bool $value = true) : void{
$this->propertyManager->setByte(self::DATA_ALWAYS_SHOW_NAMETAG, $value ? 1 : 0);
}
/**
* @return string|null
*/
public function getScoreTag() : ?string{
return $this->propertyManager->getString(self::DATA_SCORE_TAG);
}
/**
* @param string $score
*/
public function setScoreTag(string $score) : void{
$this->propertyManager->setString(self::DATA_SCORE_TAG, $score);
}
/**
* @return float
*/
public function getScale() : float{
return $this->propertyManager->getFloat(self::DATA_SCALE);
}
/**
* @param float $value
*/
public function setScale(float $value) : void{
if($value <= 0){
throw new \InvalidArgumentException("Scale must be greater than 0");
@ -787,7 +746,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* Returns whether the entity is able to climb blocks such as ladders or vines.
* @return bool
*/
public function canClimb() : bool{
return $this->getGenericFlag(self::DATA_FLAG_CAN_CLIMB);
@ -795,8 +753,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* Sets whether the entity is able to climb climbable blocks.
*
* @param bool $value
*/
public function setCanClimb(bool $value = true) : void{
$this->setGenericFlag(self::DATA_FLAG_CAN_CLIMB, $value);
@ -804,8 +760,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* Returns whether this entity is climbing a block. By default this is only true if the entity is climbing a ladder or vine or similar block.
*
* @return bool
*/
public function canClimbWalls() : bool{
return $this->getGenericFlag(self::DATA_FLAG_WALLCLIMBING);
@ -813,8 +767,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* Sets whether the entity is climbing a block. If true, the entity can climb anything.
*
* @param bool $value
*/
public function setCanClimbWalls(bool $value = true) : void{
$this->setGenericFlag(self::DATA_FLAG_WALLCLIMBING, $value);
@ -822,7 +774,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* Returns the entity ID of the owning entity, or null if the entity doesn't have an owner.
* @return int|null
*/
public function getOwningEntityId() : ?int{
return $this->propertyManager->getLong(self::DATA_OWNER_EID);
@ -830,7 +781,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* Returns the owning entity, or null if the entity was not found.
* @return Entity|null
*/
public function getOwningEntity() : ?Entity{
$eid = $this->getOwningEntityId();
@ -844,8 +794,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* Sets the owner of the entity. Passing null will remove the current owner.
*
* @param Entity|null $owner
*
* @throws \InvalidArgumentException if the supplied entity is not valid
*/
public function setOwningEntity(?Entity $owner) : void{
@ -860,7 +808,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* Returns the entity ID of the entity's target, or null if it doesn't have a target.
* @return int|null
*/
public function getTargetEntityId() : ?int{
return $this->propertyManager->getLong(self::DATA_TARGET_EID);
@ -869,8 +816,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* Returns the entity's target entity, or null if not found.
* This is used for things like hostile mobs attacking entities, and for fishing rods reeling hit entities in.
*
* @return Entity|null
*/
public function getTargetEntity() : ?Entity{
$eid = $this->getTargetEntityId();
@ -884,8 +829,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* Sets the entity's target entity. Passing null will remove the current target.
*
* @param Entity|null $target
*
* @throws \InvalidArgumentException if the target entity is not valid
*/
public function setTargetEntity(?Entity $target) : void{
@ -900,7 +843,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* Returns whether this entity will be saved when its chunk is unloaded.
* @return bool
*/
public function canSaveWithChunk() : bool{
return $this->savedWithChunk;
@ -909,8 +851,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* Sets whether this entity will be saved when its chunk is unloaded. This can be used to prevent the entity being
* saved to disk.
*
* @param bool $value
*/
public function setCanSaveWithChunk(bool $value) : void{
$this->savedWithChunk = $value;
@ -918,8 +858,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* Returns the short save name
*
* @return string
*/
public function getSaveId() : string{
if(!isset(self::$saveNames[static::class])){
@ -966,8 +904,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
}
protected function initEntity() : void{
assert($this->namedtag instanceof CompoundTag);
if($this->namedtag->hasTag("CustomName", StringTag::class)){
$this->setNameTag($this->namedtag->getString("CustomName"));
@ -985,9 +921,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
}
/**
* @param EntityDamageEvent $source
*/
public function attack(EntityDamageEvent $source) : void{
$source->call();
if($source->isCancelled()){
@ -999,9 +932,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
$this->setHealth($this->getHealth() - $source->getFinalDamage());
}
/**
* @param EntityRegainHealthEvent $source
*/
public function heal(EntityRegainHealthEvent $source) : void{
$source->call();
if($source->isCancelled()){
@ -1018,10 +948,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* Called to tick entities while dead. Returns whether the entity should be flagged for despawn yet.
*
* @param int $tickDiff
*
* @return bool
*/
protected function onDeathUpdate(int $tickDiff) : bool{
return true;
@ -1031,17 +957,12 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
return $this->health > 0;
}
/**
* @return float
*/
public function getHealth() : float{
return $this->health;
}
/**
* Sets the health of the Entity. This won't send any update to the players
*
* @param float $amount
*/
public function setHealth(float $amount) : void{
if($amount == $this->health){
@ -1060,30 +981,18 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
}
}
/**
* @return int
*/
public function getMaxHealth() : int{
return $this->maxHealth;
}
/**
* @param int $amount
*/
public function setMaxHealth(int $amount) : void{
$this->maxHealth = $amount;
}
/**
* @param EntityDamageEvent $type
*/
public function setLastDamageCause(EntityDamageEvent $type) : void{
$this->lastDamageCause = $type;
}
/**
* @return EntityDamageEvent|null
*/
public function getLastDamageCause() : ?EntityDamageEvent{
return $this->lastDamageCause;
}
@ -1102,7 +1011,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
$this->justCreated = false;
$changedProperties = $this->propertyManager->getDirty();
if(!empty($changedProperties)){
if(count($changedProperties) > 0){
$this->sendData($this->hasSpawned, $changedProperties);
$this->propertyManager->clearDirtyProperties();
}
@ -1146,15 +1055,11 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
$this->setGenericFlag(self::DATA_FLAG_ONFIRE, $this->isOnFire());
}
/**
* @return int
*/
public function getFireTicks() : int{
return $this->fireTicks;
}
/**
* @param int $fireTicks
* @throws \InvalidArgumentException
*/
public function setFireTicks(int $fireTicks) : void{
@ -1210,15 +1115,19 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
}
protected function updateMovement(bool $teleport = false) : void{
//TODO: hack for client-side AI interference: prevent client sided movement when motion is 0
$this->setImmobile($this->motion->x == 0 and $this->motion->y == 0 and $this->motion->z == 0);
$diffPosition = ($this->x - $this->lastX) ** 2 + ($this->y - $this->lastY) ** 2 + ($this->z - $this->lastZ) ** 2;
$diffRotation = ($this->yaw - $this->lastYaw) ** 2 + ($this->pitch - $this->lastPitch) ** 2;
$diffMotion = $this->motion->subtract($this->lastMotion)->lengthSquared();
if($teleport or $diffPosition > 0.0001 or $diffRotation > 1.0){
$still = $this->motion->lengthSquared() == 0.0;
$wasStill = $this->lastMotion->lengthSquared() == 0.0;
if($wasStill !== $still){
//TODO: hack for client-side AI interference: prevent client sided movement when motion is 0
$this->setImmobile($still);
}
if($teleport or $diffPosition > 0.0001 or $diffRotation > 1.0 or (!$wasStill and $still)){
$this->lastX = $this->x;
$this->lastY = $this->y;
$this->lastZ = $this->z;
@ -1229,7 +1138,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
$this->broadcastMovement($teleport);
}
if($diffMotion > 0.0025 or ($diffMotion > 0.0001 and $this->motion->lengthSquared() <= 0.0001)){ //0.05 ** 2
if($diffMotion > 0.0025 or $wasStill !== $still){ //0.05 ** 2
$this->lastMotion = clone $this->motion;
$this->broadcastMotion();
@ -1391,9 +1300,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
return false;
}
/**
* @return int|null
*/
public function getDirection() : ?int{
$rotation = ($this->yaw - 90) % 360;
if($rotation < 0){
@ -1412,9 +1318,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
}
}
/**
* @return Vector3
*/
public function getDirectionVector() : Vector3{
$y = -sin(deg2rad($this->pitch));
$xz = cos(deg2rad($this->pitch));
@ -1452,7 +1355,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
return true;
}
$this->timings->startTiming();
if($this->hasMovementUpdate()){
@ -1481,7 +1383,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
$hasUpdate = $this->entityBaseTick($tickDiff);
Timings::$timerEntityBaseTick->stopTiming();
$this->timings->stopTiming();
//if($this->isStatic())
@ -1504,8 +1405,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* Flags the entity as needing a movement update on the next tick. Setting this forces a movement update even if the
* entity's motion is zero. Used to trigger movement updates when blocks change near entities.
*
* @param bool $value
*/
final public function setForceMovementUpdate(bool $value = true) : void{
$this->forceMovementUpdate = $value;
@ -1515,7 +1414,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* Returns whether the entity needs a movement update on the next tick.
* @return bool
*/
public function hasMovementUpdate() : bool{
return (
@ -1535,10 +1433,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
$this->fallDistance = 0.0;
}
/**
* @param float $distanceThisTick
* @param bool $onGround
*/
protected function updateFallState(float $distanceThisTick, bool $onGround) : void{
if($onGround){
if($this->fallDistance > 0){
@ -1552,8 +1446,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* Called when a falling entity hits the ground.
*
* @param float $fallDistance
*/
public function fall(float $fallDistance) : void{
@ -1619,7 +1511,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
$this->isCollided = $this->onGround;
$this->updateFallState($dy, $this->onGround);
Timings::$entityMoveTimer->stopTiming();
return true;
@ -1704,7 +1595,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
$this->boundingBox->offset(0, 0, $dz);
if($this->stepHeight > 0 and $fallingFlag and $this->ySize < 0.05 and ($movX != $dx or $movZ != $dz)){
$cx = $dx;
$cy = $dy;
@ -1817,8 +1707,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* Returns whether this entity can be moved by currents in liquids.
*
* @return bool
*/
public function canBeMovedByCurrents() : bool{
return true;
@ -1954,10 +1842,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* @param Vector3|Position|Location $pos
* @param float|null $yaw
* @param float|null $pitch
*
* @return bool
*/
public function teleport(Vector3 $pos, ?float $yaw = null, ?float $pitch = null) : bool{
if($pos instanceof Location){
@ -2026,8 +1910,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* Called by spawnTo() to send whatever packets needed to spawn the entity to the client.
*
* @param Player $player
*/
protected function sendSpawnPacket(Player $player) : void{
$pk = new AddActorPacket();
@ -2044,9 +1926,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
$player->dataPacket($pk);
}
/**
* @param Player $player
*/
public function spawnTo(Player $player) : void{
if(!isset($this->hasSpawned[$player->getLoaderId()]) and $this->chunk !== null and isset($player->usedChunks[Level::chunkHash($this->chunk->getX(), $this->chunk->getZ())])){
$this->hasSpawned[$player->getLoaderId()] = $player;
@ -2076,9 +1955,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* @deprecated WARNING: This function DOES NOT permanently hide the entity from the player. As soon as the entity or
* player moves, the player will once again be able to see the entity.
*
* @param Player $player
* @param bool $send
*/
public function despawnFrom(Player $player, bool $send = true) : void{
if(isset($this->hasSpawned[$player->getLoaderId()])){
@ -2115,7 +1991,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* Returns whether the entity has been "closed".
* @return bool
*/
public function isClosed() : bool{
return $this->closed;
@ -2155,12 +2030,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
}
}
/**
* @param int $propertyId
* @param int $flagId
* @param bool $value
* @param int $propertyType
*/
public function setDataFlag(int $propertyId, int $flagId, bool $value = true, int $propertyType = self::DATA_TYPE_LONG) : void{
if($this->getDataFlag($propertyId, $flagId) !== $value){
$flags = (int) $this->propertyManager->getPropertyValue($propertyId, $propertyType);
@ -2169,22 +2038,12 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
}
}
/**
* @param int $propertyId
* @param int $flagId
*
* @return bool
*/
public function getDataFlag(int $propertyId, int $flagId) : bool{
return (((int) $this->propertyManager->getPropertyValue($propertyId, -1)) & (1 << $flagId)) > 0;
}
/**
* Wrapper around {@link Entity#getDataFlag} for generic data flag reading.
*
* @param int $flagId
*
* @return bool
*/
public function getGenericFlag(int $flagId) : bool{
return $this->getDataFlag($flagId >= 64 ? self::DATA_FLAGS2 : self::DATA_FLAGS, $flagId % 64);
@ -2192,9 +2051,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* Wrapper around {@link Entity#setDataFlag} for generic data flag setting.
*
* @param int $flagId
* @param bool $value
*/
public function setGenericFlag(int $flagId, bool $value = true) : void{
$this->setDataFlag($flagId >= 64 ? self::DATA_FLAGS2 : self::DATA_FLAGS, $flagId % 64, $value, self::DATA_TYPE_LONG);
@ -2202,7 +2058,8 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* @param Player[]|Player $player
* @param array $data Properly formatted entity data, defaults to everything
* @param mixed[][] $data Properly formatted entity data, defaults to everything
* @phpstan-param array<int, array{0: int, 1: mixed}> $data
*/
public function sendData($player, ?array $data = null) : void{
if(!is_array($player)){
@ -2225,6 +2082,9 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
}
}
/**
* @param Player[]|null $players
*/
public function broadcastEntityEvent(int $eventId, ?int $eventData = null, ?array $players = null) : void{
$pk = new ActorEventPacket();
$pk->entityRuntimeId = $this->id;
@ -2279,6 +2139,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
* @param string $name
* @param mixed $value
*
* @return void
* @throws \ErrorException
* @throws \InvalidArgumentException
*/

View File

@ -23,8 +23,10 @@ declare(strict_types=1);
namespace pocketmine\entity;
interface Explosive{
/**
* @return void
*/
public function explode();
}

View File

@ -61,6 +61,7 @@ use function array_merge;
use function array_rand;
use function array_values;
use function ceil;
use function count;
use function in_array;
use function max;
use function min;
@ -80,6 +81,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
/** @var UUID */
protected $uuid;
/** @var string */
protected $rawUUID;
public $width = 0.6;
@ -89,10 +91,14 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
/** @var Skin */
protected $skin;
/** @var int */
protected $foodTickTimer = 0;
/** @var int */
protected $totalXp = 0;
/** @var int */
protected $xpSeed;
/** @var int */
protected $xpCooldown = 0;
protected $baseOffset = 1.62;
@ -110,9 +116,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
}
/**
* @param CompoundTag $skinTag
*
* @return Skin
* @throws \InvalidArgumentException
*/
protected static function deserializeSkinNBT(CompoundTag $skinTag) : Skin{
@ -131,32 +134,21 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
* @deprecated
*
* Checks the length of a supplied skin bitmap and returns whether the length is valid.
*
* @param string $skin
*
* @return bool
*/
public static function isValidSkin(string $skin) : bool{
return in_array(strlen($skin), Skin::ACCEPTED_SKIN_SIZES, true);
}
/**
* @return UUID|null
*/
public function getUniqueId() : ?UUID{
return $this->uuid;
}
/**
* @return string
*/
public function getRawUniqueId() : string{
return $this->rawUUID;
}
/**
* Returns a Skin object containing information about this human's skin.
* @return Skin
*/
public function getSkin() : Skin{
return $this->skin;
@ -165,8 +157,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
/**
* Sets the human's skin. This will not send any update to viewers, you need to do that manually using
* {@link sendSkin}.
*
* @param Skin $skin
*/
public function setSkin(Skin $skin) : void{
$skin->validate();
@ -204,8 +194,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
* WARNING: This method does not check if full and may throw an exception if out of bounds.
* Use {@link Human::addFood()} for this purpose
*
* @param float $new
*
* @throws \InvalidArgumentException
*/
public function setFood(float $new) : void{
@ -235,8 +223,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
/**
* Returns whether this Human may consume objects requiring hunger.
*
* @return bool
*/
public function isHungry() : bool{
return $this->getFood() < $this->getMaxFood();
@ -250,8 +236,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
* WARNING: This method does not check if saturated and may throw an exception if out of bounds.
* Use {@link Human::addSaturation()} for this purpose
*
* @param float $saturation
*
* @throws \InvalidArgumentException
*/
public function setSaturation(float $saturation) : void{
@ -270,8 +254,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
/**
* WARNING: This method does not check if exhausted and does not consume saturation/food.
* Use {@link Human::exhaust()} for this purpose.
*
* @param float $exhaustion
*/
public function setExhaustion(float $exhaustion) : void{
$this->attributeMap->getAttribute(Attribute::EXHAUSTION)->setValue($exhaustion);
@ -280,9 +262,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
/**
* Increases a human's exhaustion level.
*
* @param float $amount
* @param int $cause
*
* @return float the amount of exhaustion level increased
*/
public function exhaust(float $amount, int $cause = PlayerExhaustEvent::CAUSE_CUSTOM) : float{
@ -330,7 +309,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
/**
* Returns the player's experience level.
* @return int
*/
public function getXpLevel() : int{
return (int) $this->attributeMap->getAttribute(Attribute::EXPERIENCE_LEVEL)->getValue();
@ -338,10 +316,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
/**
* Sets the player's experience level. This does not affect their total XP or their XP progress.
*
* @param int $level
*
* @return bool
*/
public function setXpLevel(int $level) : bool{
return $this->setXpAndProgress($level, null);
@ -349,11 +323,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
/**
* Adds a number of XP levels to the player.
*
* @param int $amount
* @param bool $playSound
*
* @return bool
*/
public function addXpLevels(int $amount, bool $playSound = true) : bool{
$oldLevel = $this->getXpLevel();
@ -373,10 +342,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
/**
* Subtracts a number of XP levels from the player.
*
* @param int $amount
*
* @return bool
*/
public function subtractXpLevels(int $amount) : bool{
return $this->addXpLevels(-$amount);
@ -384,7 +349,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
/**
* Returns a value between 0.0 and 1.0 to indicate how far through the current level the player is.
* @return float
*/
public function getXpProgress() : float{
return $this->attributeMap->getAttribute(Attribute::EXPERIENCE)->getValue();
@ -392,10 +356,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
/**
* Sets the player's progress through the current level to a value between 0.0 and 1.0.
*
* @param float $progress
*
* @return bool
*/
public function setXpProgress(float $progress) : bool{
return $this->setXpAndProgress(null, $progress);
@ -403,7 +363,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
/**
* Returns the number of XP points the player has progressed into their current level.
* @return int
*/
public function getRemainderXp() : int{
return (int) (ExperienceUtils::getXpToCompleteLevel($this->getXpLevel()) * $this->getXpProgress());
@ -413,8 +372,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
* Returns the amount of XP points the player currently has, calculated from their current level and progress
* through their current level. This will be reduced by enchanting deducting levels and is used to calculate the
* amount of XP the player drops on death.
*
* @return int
*/
public function getCurrentTotalXp() : int{
return ExperienceUtils::getXpToReachLevel($this->getXpLevel()) + $this->getRemainderXp();
@ -423,10 +380,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
/**
* Sets the current total of XP the player has, recalculating their XP level and progress.
* Note that this DOES NOT update the player's lifetime total XP.
*
* @param int $amount
*
* @return bool
*/
public function setCurrentTotalXp(int $amount) : bool{
$newLevel = ExperienceUtils::getLevelFromXp($amount);
@ -438,10 +391,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
* Adds an amount of XP to the player, recalculating their XP level and progress. XP amount will be added to the
* player's lifetime XP.
*
* @param int $amount
* @param bool $playSound Whether to play level-up and XP gained sounds.
*
* @return bool
*/
public function addXp(int $amount, bool $playSound = true) : bool{
$this->totalXp += $amount;
@ -472,10 +422,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
/**
* Takes an amount of XP from the player, recalculating their XP level and progress.
*
* @param int $amount
*
* @return bool
*/
public function subtractXp(int $amount) : bool{
return $this->addXp(-$amount);
@ -508,8 +454,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
/**
* Returns the total XP the player has collected in their lifetime. Resets when the player dies.
* XP levels being removed in enchanting do not reduce this number.
*
* @return int
*/
public function getLifetimeTotalXp() : int{
return $this->totalXp;
@ -518,8 +462,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
/**
* Sets the lifetime total XP of the player. This does not recalculate their level or progress. Used for player
* score when they die. (TODO: add this when MCPE supports it)
*
* @param int $amount
*/
public function setLifetimeTotalXp(int $amount) : void{
if($amount < 0){
@ -531,7 +473,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
/**
* Returns whether the human can pickup XP orbs (checks cooldown time)
* @return bool
*/
public function canPickupXp() : bool{
return $this->xpCooldown === 0;
@ -548,13 +489,13 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
$equipment[$mainHandIndex] = $item;
}
//TODO: check offhand
foreach($this->armorInventory->getContents() as $k => $item){
if($item instanceof Durable and $item->hasEnchantment(Enchantment::MENDING)){
$equipment[$k] = $item;
foreach($this->armorInventory->getContents() as $k => $armorItem){
if($armorItem instanceof Durable and $armorItem->hasEnchantment(Enchantment::MENDING)){
$equipment[$k] = $armorItem;
}
}
if(!empty($equipment)){
if(count($equipment) > 0){
$repairItem = $equipment[$k = array_rand($equipment)];
if($repairItem->getDamage() > 0){
$repairAmount = min($repairItem->getDamage(), $xpValue * 2);
@ -575,8 +516,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
/**
* Sets the duration in ticks until the human can pick up another XP orb.
*
* @param int $value
*/
public function resetXpCooldown(int $value = 2) : void{
$this->xpCooldown = $value;
@ -585,7 +524,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
public function getXpDropAmount() : int{
//this causes some XP to be lost on death when above level 1 (by design), dropping at most enough points for
//about 7.5 levels of XP.
return (int) min(100, 7 * $this->getXpLevel());
return min(100, 7 * $this->getXpLevel());
}
/**
@ -896,10 +835,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
/**
* Wrapper around {@link Entity#getDataFlag} for player-specific data flag reading.
*
* @param int $flagId
*
* @return bool
*/
public function getPlayerFlag(int $flagId) : bool{
return $this->getDataFlag(self::DATA_PLAYER_FLAGS, $flagId);
@ -907,9 +842,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
/**
* Wrapper around {@link Entity#setDataFlag} for player-specific data flag setting.
*
* @param int $flagId
* @param bool $value
*/
public function setPlayerFlag(int $flagId, bool $value = true) : void{
$this->setDataFlag(self::DATA_PLAYER_FLAGS, $flagId, $value, self::DATA_TYPE_BYTE);

View File

@ -70,6 +70,7 @@ abstract class Living extends Entity implements Damageable{
protected $gravity = 0.08;
protected $drag = 0.02;
/** @var int */
protected $attackTime = 0;
/** @var int */
@ -77,6 +78,7 @@ abstract class Living extends Entity implements Damageable{
/** @var int */
protected $maxDeadTicks = 25;
/** @var float */
protected $jumpVelocity = 0.42;
/** @var EffectInstance[] */
@ -109,7 +111,7 @@ abstract class Living extends Entity implements Damageable{
$this->setHealth($health);
/** @var CompoundTag[]|ListTag $activeEffectsTag */
/** @var CompoundTag[]|ListTag|null */
$activeEffectsTag = $this->namedtag->getListTag("ActiveEffects");
if($activeEffectsTag !== null){
foreach($activeEffectsTag as $e){
@ -185,7 +187,6 @@ abstract class Living extends Entity implements Damageable{
}
}
public function hasLineOfSight(Entity $entity) : bool{
//TODO: head height
return true;
@ -211,8 +212,6 @@ abstract class Living extends Entity implements Damageable{
/**
* Removes the effect with the specified ID from the mob.
*
* @param int $effectId
*/
public function removeEffect(int $effectId) : void{
if(isset($this->effects[$effectId])){
@ -238,10 +237,6 @@ abstract class Living extends Entity implements Damageable{
/**
* Returns the effect instance active on this entity with the specified ID, or null if the mob does not have the
* effect.
*
* @param int $effectId
*
* @return EffectInstance|null
*/
public function getEffect(int $effectId) : ?EffectInstance{
return $this->effects[$effectId] ?? null;
@ -249,10 +244,6 @@ abstract class Living extends Entity implements Damageable{
/**
* Returns whether the specified effect is active on the mob.
*
* @param int $effectId
*
* @return bool
*/
public function hasEffect(int $effectId) : bool{
return isset($this->effects[$effectId]);
@ -260,10 +251,9 @@ abstract class Living extends Entity implements Damageable{
/**
* Returns whether the mob has any active effects.
* @return bool
*/
public function hasEffects() : bool{
return !empty($this->effects);
return count($this->effects) > 0;
}
/**
@ -271,8 +261,6 @@ abstract class Living extends Entity implements Damageable{
* If a weaker effect of the same type is already applied, it will be replaced.
* If a weaker or equal-strength effect is already applied but has a shorter duration, it will be replaced.
*
* @param EffectInstance $effect
*
* @return bool whether the effect has been successfully applied.
*/
public function addEffect(EffectInstance $effect) : bool{
@ -332,7 +320,7 @@ abstract class Living extends Entity implements Damageable{
}
}
if(!empty($colors)){
if(count($colors) > 0){
$this->propertyManager->setInt(Entity::DATA_POTION_COLOR, Color::mix(...$colors)->toARGB());
$this->propertyManager->setByte(Entity::DATA_POTION_AMBIENT, $ambient ? 1 : 0);
}else{
@ -343,8 +331,6 @@ abstract class Living extends Entity implements Damageable{
/**
* Sends the mob's potion effects to the specified player.
*
* @param Player $player
*/
public function sendPotionEffects(Player $player) : void{
foreach($this->effects as $effect){
@ -371,10 +357,6 @@ abstract class Living extends Entity implements Damageable{
/**
* Causes the mob to consume the given Consumable object, applying applicable effects, health bonuses, food bonuses,
* etc.
*
* @param Consumable $consumable
*
* @return bool
*/
public function consumeObject(Consumable $consumable) : bool{
foreach($consumable->getAdditionalEffects() as $effect){
@ -388,7 +370,6 @@ abstract class Living extends Entity implements Damageable{
/**
* Returns the initial upwards velocity of a jumping entity in blocks/tick, including additional velocity due to effects.
* @return float
*/
public function getJumpVelocity() : float{
return $this->jumpVelocity + ($this->hasEffect(Effect::JUMP) ? ($this->getEffect(Effect::JUMP)->getEffectLevel() / 10) : 0);
@ -415,8 +396,6 @@ abstract class Living extends Entity implements Damageable{
* Returns how many armour points this mob has. Armour points provide a percentage reduction to damage.
* For mobs which can wear armour, this should return the sum total of the armour points provided by their
* equipment.
*
* @return int
*/
public function getArmorPoints() : int{
$total = 0;
@ -429,10 +408,6 @@ abstract class Living extends Entity implements Damageable{
/**
* Returns the highest level of the specified enchantment on any armour piece that the entity is currently wearing.
*
* @param int $enchantmentId
*
* @return int
*/
public function getHighestArmorEnchantmentLevel(int $enchantmentId) : int{
$result = 0;
@ -443,9 +418,6 @@ abstract class Living extends Entity implements Damageable{
return $result;
}
/**
* @return ArmorInventory
*/
public function getArmorInventory() : ArmorInventory{
return $this->armorInventory;
}
@ -457,8 +429,6 @@ abstract class Living extends Entity implements Damageable{
/**
* Called prior to EntityDamageEvent execution to apply modifications to the event's damage, such as reduction due
* to effects or armour.
*
* @param EntityDamageEvent $source
*/
public function applyDamageModifiers(EntityDamageEvent $source) : void{
if($source->canBeReducedByArmor()){
@ -486,8 +456,6 @@ abstract class Living extends Entity implements Damageable{
* Called after EntityDamageEvent execution to apply post-hurt effects, such as reducing absorption or modifying
* armour durability.
* This will not be called by damage sources causing death.
*
* @param EntityDamageEvent $source
*/
protected function applyPostDamageEffects(EntityDamageEvent $source) : void{
$this->setAbsorption(max(0, $this->getAbsorption() + $source->getModifier(EntityDamageEvent::MODIFIER_ABSORPTION)));
@ -517,8 +485,6 @@ abstract class Living extends Entity implements Damageable{
/**
* Damages the worn armour according to the amount of damage given. Each 4 points (rounded down) deals 1 damage
* point to each armour piece, but never less than 1 total.
*
* @param float $damage
*/
public function damageArmor(float $damage) : void{
$durabilityRemoved = (int) max(floor($damage / 4), 1);
@ -712,15 +678,11 @@ abstract class Living extends Entity implements Damageable{
}
}
return !empty($this->effects);
return count($this->effects) > 0;
}
/**
* Ticks the entity's air supply, consuming it when underwater and regenerating it when out of water.
*
* @param int $tickDiff
*
* @return bool
*/
protected function doAirSupplyTick(int $tickDiff) : bool{
$ticks = $this->getAirSupplyTicks();
@ -756,7 +718,6 @@ abstract class Living extends Entity implements Damageable{
/**
* Returns whether the entity can currently breathe.
* @return bool
*/
public function canBreathe() : bool{
return $this->hasEffect(Effect::WATER_BREATHING) or $this->hasEffect(Effect::CONDUIT_POWER) or !$this->isUnderwater();
@ -764,7 +725,6 @@ abstract class Living extends Entity implements Damageable{
/**
* Returns whether the entity is currently breathing or not. If this is false, the entity's air supply will be used.
* @return bool
*/
public function isBreathing() : bool{
return $this->getGenericFlag(self::DATA_FLAG_BREATHING);
@ -773,8 +733,6 @@ abstract class Living extends Entity implements Damageable{
/**
* Sets whether the entity is currently breathing. If false, it will cause the entity's air supply to be used.
* For players, this also shows the oxygen bar.
*
* @param bool $value
*/
public function setBreathing(bool $value = true) : void{
$this->setGenericFlag(self::DATA_FLAG_BREATHING, $value);
@ -783,8 +741,6 @@ abstract class Living extends Entity implements Damageable{
/**
* Returns the number of ticks remaining in the entity's air supply. Note that the entity may survive longer than
* this amount of time without damage due to enchantments such as Respiration.
*
* @return int
*/
public function getAirSupplyTicks() : int{
return $this->propertyManager->getShort(self::DATA_AIR);
@ -792,8 +748,6 @@ abstract class Living extends Entity implements Damageable{
/**
* Sets the number of air ticks left in the entity's air supply.
*
* @param int $ticks
*/
public function setAirSupplyTicks(int $ticks) : void{
$this->propertyManager->setShort(self::DATA_AIR, $ticks);
@ -801,7 +755,6 @@ abstract class Living extends Entity implements Damageable{
/**
* Returns the maximum amount of air ticks the entity's air supply can contain.
* @return int
*/
public function getMaxAirSupplyTicks() : int{
return $this->propertyManager->getShort(self::DATA_MAX_AIR);
@ -809,8 +762,6 @@ abstract class Living extends Entity implements Damageable{
/**
* Sets the maximum amount of air ticks the air supply can hold.
*
* @param int $ticks
*/
public function setMaxAirSupplyTicks(int $ticks) : void{
$this->propertyManager->setShort(self::DATA_MAX_AIR, $ticks);
@ -834,16 +785,14 @@ abstract class Living extends Entity implements Damageable{
/**
* Returns the amount of XP this mob will drop on death.
* @return int
*/
public function getXpDropAmount() : int{
return 0;
}
/**
* @param int $maxDistance
* @param int $maxLength
* @param array $transparent
* @param true[] $transparent
* @phpstan-param array<int, true> $transparent
*
* @return Block[]
*/
@ -885,14 +834,12 @@ abstract class Living extends Entity implements Damageable{
}
/**
* @param int $maxDistance
* @param array $transparent
*
* @return Block|null
* @param true[] $transparent
* @phpstan-param array<int, true> $transparent
*/
public function getTargetBlock(int $maxDistance, array $transparent = []) : ?Block{
$line = $this->getLineOfSight($maxDistance, 1, $transparent);
if(!empty($line)){
if(count($line) > 0){
return array_shift($line);
}
@ -902,8 +849,6 @@ abstract class Living extends Entity implements Damageable{
/**
* Changes the entity's yaw and pitch to make it look at the specified Vector3 position. For mobs, this will cause
* their heads to turn.
*
* @param Vector3 $target
*/
public function lookAt(Vector3 $target) : void{
$horizontal = sqrt(($target->x - $this->x) ** 2 + ($target->z - $this->z) ** 2);

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace pocketmine\entity;
abstract class Monster extends Creature{
}

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace pocketmine\entity;
interface NPC{
}

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace pocketmine\entity;
interface Rideable{
}

View File

@ -57,7 +57,6 @@ class Skin{
/**
* @deprecated
* @return bool
*/
public function isValid() : bool{
try{
@ -85,37 +84,22 @@ class Skin{
//TODO: validate geometry
}
/**
* @return string
*/
public function getSkinId() : string{
return $this->skinId;
}
/**
* @return string
*/
public function getSkinData() : string{
return $this->skinData;
}
/**
* @return string
*/
public function getCapeData() : string{
return $this->capeData;
}
/**
* @return string
*/
public function getGeometryName() : string{
return $this->geometryName;
}
/**
* @return string
*/
public function getGeometryData() : string{
return $this->geometryData;
}

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