mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-09 03:06:55 +00:00
Compare commits
307 Commits
Author | SHA1 | Date | |
---|---|---|---|
c32026333f | |||
915224c8e5 | |||
734bc6c4a7 | |||
d36b24c518 | |||
d554d8060b | |||
b48243fd09 | |||
92cffc00d0 | |||
e87e974323 | |||
a3f6338626 | |||
21aef97ba7 | |||
ed0d1978aa | |||
d64561b0b1 | |||
d234d3e45e | |||
5056754cea | |||
2dc3cf8162 | |||
8c5a81cf5c | |||
2b58f2bafd | |||
5dadf12374 | |||
0d4e473bdd | |||
11cedc4011 | |||
3f2455f090 | |||
9d26a224a2 | |||
c4ad390463 | |||
42e14f749e | |||
3f07f06874 | |||
10279e11ed | |||
673e444456 | |||
89c49d77c6 | |||
c3a795e876 | |||
4199c3796f | |||
bf6af269c8 | |||
a29424f5b3 | |||
ff3af492f8 | |||
80b804f7aa | |||
3a78735982 | |||
ab32784c74 | |||
816234a379 | |||
b7bf92a5e9 | |||
dcca000ead | |||
c4ea51f985 | |||
8202bb1cd8 | |||
b75758e35e | |||
38a06f76f8 | |||
84f99ed418 | |||
fd63f19199 | |||
66d44aa814 | |||
f3089f577e | |||
9516ef1632 | |||
e982a57cb5 | |||
f57fa2252b | |||
02cc370855 | |||
0a5d14a840 | |||
3ec2994d7f | |||
786f416f2e | |||
a67d2ae978 | |||
089180fef4 | |||
fffa4b9501 | |||
71a8b0340c | |||
e544055bbc | |||
8f5db7c297 | |||
27f55e4c96 | |||
9b6b3f50a1 | |||
1fb0ba6fc0 | |||
f1d378468e | |||
25fb5140a2 | |||
f5a49b6d55 | |||
189f12a644 | |||
5a8917f6f2 | |||
f3e436592a | |||
35747874f6 | |||
59445902b8 | |||
2eb62c85f6 | |||
ad2a39bf13 | |||
0847358070 | |||
54f41dc145 | |||
ded45bddfe | |||
b044550475 | |||
a70fa15690 | |||
bd1d7b8d75 | |||
1513a0e092 | |||
c4150d4520 | |||
2f47597d75 | |||
ef97c8f99e | |||
84932ce908 | |||
6bfc309a0a | |||
06e8c6a3ad | |||
71271a0e03 | |||
b63ad032a9 | |||
d9b0e373bb | |||
32262d9bb5 | |||
4c1b10b24b | |||
61dc9d7f6b | |||
da9731ef59 | |||
e6f64c609e | |||
8c7fbf379b | |||
34a3e0d8b1 | |||
d42217ff57 | |||
39d02a67d2 | |||
77d45bf116 | |||
f79182852b | |||
a107ad7404 | |||
7a072931df | |||
f428a9bf52 | |||
2e720b48d9 | |||
a6e79bedf5 | |||
a5ba570fdf | |||
0d5164af02 | |||
534af770f8 | |||
79ed377c7a | |||
20f3030709 | |||
3aa58f54dc | |||
5c12a95151 | |||
5f07c5df1c | |||
5f33ef35e3 | |||
ec949840b2 | |||
e45e84b236 | |||
dfe68c9788 | |||
35b8f0bf25 | |||
d4dc1c8a0c | |||
517f9a3c3a | |||
636c35dcf1 | |||
d22f0da1de | |||
310de5a2b2 | |||
f84abcd1fe | |||
b5dd147ec7 | |||
0dd68e587f | |||
330e93e5e3 | |||
2020fcd18e | |||
456d9a722a | |||
344c980cff | |||
167492087f | |||
db215283a2 | |||
6a507bb149 | |||
a72e6ee706 | |||
89ea7f0a76 | |||
a6ca37429c | |||
4bf9fb278b | |||
15d81154e6 | |||
93e5c80962 | |||
7aa8bd18d3 | |||
53067c26d7 | |||
04581e2700 | |||
93597dcd50 | |||
778814a35e | |||
3cd1da196a | |||
365d4a1592 | |||
2d7f37ac47 | |||
50fcdd6e7e | |||
10317527e4 | |||
46ac4cbca1 | |||
cb9e79b398 | |||
2f1fad2745 | |||
44182dccbd | |||
2f3d2d4a0b | |||
8ac7f7f11f | |||
dbe7caab7b | |||
b581fab31a | |||
7b7dfc36d1 | |||
d63d6b73f6 | |||
a860ccd259 | |||
2bb497b716 | |||
613bd40601 | |||
398b636759 | |||
1257378198 | |||
758a68aa2c | |||
bfce478e72 | |||
681dd469a2 | |||
3edbea8545 | |||
ada8cbb545 | |||
0ac5e03ce9 | |||
9b02b8e51e | |||
6c7dada232 | |||
25bc95cd1e | |||
213bf8366a | |||
4e693e91e6 | |||
a1622fa345 | |||
0ec869932f | |||
79acaa3253 | |||
da3742b39e | |||
d26fcf7dee | |||
812424a619 | |||
1bdc61dd5f | |||
86fc33fe26 | |||
70eb41470c | |||
3a5709bf5e | |||
5ad66c3c9b | |||
7885b54824 | |||
532dc0fb6f | |||
54ccc330d5 | |||
e12618c705 | |||
7d5f2eac8d | |||
e964dd2ca8 | |||
dbb594f130 | |||
8f434b9edd | |||
34972c3327 | |||
037c34d961 | |||
4518d9d9ce | |||
1a5228e7a6 | |||
495bfda044 | |||
41b1fa7b48 | |||
e689fd545b | |||
889cd5e206 | |||
e1ddf90695 | |||
2f325b8c91 | |||
ac4f00be81 | |||
914450c30b | |||
25554f0d61 | |||
e1a61cb51a | |||
fe5620f097 | |||
faef4e8736 | |||
0d19f6c968 | |||
ecf662bf74 | |||
8cba2e0346 | |||
dfc8a6ffdd | |||
262728b091 | |||
4572ec8175 | |||
0f6949ac34 | |||
df8e0cf1f5 | |||
ad87c11ae1 | |||
fa82cb26d8 | |||
fd2a7797bd | |||
e5a2cfb65f | |||
b96bb7d824 | |||
896cca0778 | |||
59cf8e95f0 | |||
99038c752c | |||
88afedd1e8 | |||
c43e21235d | |||
3f7e7352fb | |||
32d6ea0fba | |||
28c787371a | |||
dba14c9f08 | |||
0e35ee8cb7 | |||
da5b7f47df | |||
d418dd7a09 | |||
f3209ccc33 | |||
4a4c28cd8c | |||
eba8d77034 | |||
13e4772f98 | |||
4bc2f28c6d | |||
663469dfa7 | |||
963abb718f | |||
1f2fb73297 | |||
ff55b520b9 | |||
cedd8abf0c | |||
496732999c | |||
6a8105f5a0 | |||
0a566f8218 | |||
829dd02eea | |||
b11c350b2b | |||
f624e36faf | |||
14ce9c10bb | |||
b27aaaeeb2 | |||
f1083bd9c4 | |||
199fa61aef | |||
af82a6bbe1 | |||
004f7ef82e | |||
89ebd2b880 | |||
799183e13e | |||
260ac47588 | |||
4ff4434a22 | |||
5d8bb84269 | |||
9eebfa7cc3 | |||
d3021c6281 | |||
9097d6c4d3 | |||
da43ae82fe | |||
60b405d944 | |||
92a752053d | |||
0537c66849 | |||
d94995e161 | |||
58bc08838b | |||
fc0619ee6e | |||
a5764b3ae9 | |||
8bf469f7fc | |||
3b9a5c5ccc | |||
4c36ca58e2 | |||
a67fa5c007 | |||
839a789180 | |||
e61c3e8bf6 | |||
7ce6c8aa13 | |||
9abcc99c10 | |||
5c8a625d88 | |||
259f0425a9 | |||
9cdea43794 | |||
e007fad5b8 | |||
5cf2fcbbb7 | |||
9e6cbb5b6a | |||
64b3d02974 | |||
640df1003c | |||
2b402e525a | |||
e2871fad8e | |||
41d02003c2 | |||
156ecd9bd8 | |||
fa7736efbb | |||
d71a7ff2fa | |||
8184a6b114 | |||
b8d44ff162 | |||
f6611a38bc | |||
24ed823d96 | |||
f624871b3f | |||
9cd6b3e1c7 | |||
aad1eb5b3e | |||
bff5bf25ae | |||
cda90fd7f1 | |||
9f44adf04a | |||
c4793241f5 | |||
7532c609fb |
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -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
|
||||
|
16
.travis.yml
16
.travis.yml
@ -5,21 +5,29 @@ php:
|
||||
- 7.3
|
||||
|
||||
before_script:
|
||||
# - pecl install channel://pecl.php.net/pthreads-3.1.6
|
||||
- echo | pecl install channel://pecl.php.net/yaml-2.0.4
|
||||
- phpenv config-rm xdebug.ini
|
||||
- echo | pecl install channel://pecl.php.net/yaml-2.1.0
|
||||
- git clone https://github.com/pmmp/pthreads.git
|
||||
- cd pthreads
|
||||
- git checkout 1b7da492b944146fa9680f6399bd9c6c6c6095e0
|
||||
- git checkout 646dac62ae0d48c1ada7b007e15575fb84f7d71d
|
||||
- phpize
|
||||
- ./configure
|
||||
- make
|
||||
- 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
38
BUILDING.md
Normal 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.php` 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.
|
@ -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
|
||||
|
@ -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;
|
||||
@ -38,17 +37,6 @@ use const STDIN;
|
||||
|
||||
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);
|
||||
@ -59,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);
|
||||
}
|
||||
|
Submodule build/php updated: 8308571448...d475b694e4
Submodule build/preprocessor updated: b01f50c50e...da363df5f1
@ -24,12 +24,28 @@ 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
|
||||
* @param string|null $delim
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
@ -38,19 +54,15 @@ function preg_quote_array(array $strings, string $delim = null) : array{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $pharPath
|
||||
* @param string $basePath
|
||||
* @param string[] $includedPaths
|
||||
* @param array $metadata
|
||||
* @param string $stub
|
||||
* @param int $signatureAlgo
|
||||
* @param int|null $compression
|
||||
* @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($path){
|
||||
$includedPaths = array_map(function(string $path) : string{
|
||||
return rtrim(str_replace("/", DIRECTORY_SEPARATOR, $path), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
||||
}, $includedPaths);
|
||||
yield "Creating output file $pharPath";
|
||||
@ -103,14 +115,9 @@ function buildPhar(string $pharPath, string $basePath, array $includedPaths, arr
|
||||
yield "Added $count files";
|
||||
|
||||
if($compression !== null){
|
||||
yield "Checking for compressible files...";
|
||||
foreach($phar as $file => $finfo){
|
||||
/** @var \PharFileInfo $finfo */
|
||||
if($finfo->getSize() > (1024 * 512)){
|
||||
yield "Compressing " . $finfo->getFilename();
|
||||
$finfo->compress($compression);
|
||||
}
|
||||
}
|
||||
yield "Compressing files...";
|
||||
$phar->compressFiles($compression);
|
||||
yield "Finished compression";
|
||||
}
|
||||
$phar->stopBuffering();
|
||||
|
||||
@ -123,9 +130,13 @@ function main() : void{
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$opts = getopt("", ["out:"]);
|
||||
$gitHash = Git::getRepositoryStatePretty(dirname(__DIR__));
|
||||
echo "Git hash detected as $gitHash" . PHP_EOL;
|
||||
$opts = getopt("", ["out:", "git:"]);
|
||||
if(isset($opts["git"])){
|
||||
$gitHash = $opts["git"];
|
||||
}else{
|
||||
$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,
|
||||
@ -136,7 +147,23 @@ function main() : void{
|
||||
[
|
||||
'git' => $gitHash
|
||||
],
|
||||
'<?php require("phar://" . __FILE__ . "/src/pocketmine/PocketMine.php"); __HALT_COMPILER();'
|
||||
<<<'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;
|
||||
}
|
||||
|
@ -53,3 +53,45 @@ Plugin developers should **only** update their required API to this version if y
|
||||
- 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.
|
||||
|
||||
# 3.11.6
|
||||
- Core code, tests and build scripts are now analyzed using `phpstan-strict-rules` and `phpstan-phpunit` rules.
|
||||
- Added more PHPStan-specific type annotations to improve static analysis.
|
||||
- Fixed more incorrect PHPDoc types.
|
||||
- Added a workaround for player movement not working since 1.14.30.
|
||||
- Fixed lava and water buckets being edible since 1.13.
|
||||
- `AutoUpdater` is now created before any plugins are loaded.
|
||||
- Fixed trees not generating below y=2 in custom generators.
|
||||
- Fixed crash when opening a chest improperly unpaired from its pair (destroyed, setBlock(), unloaded, etc.).
|
||||
- `ThreadManager` is now lazily initialized.
|
||||
- Removed raw NBT storage from `Item` internals. The following methods are now deprecated:
|
||||
- `Item::setCompoundTag()`
|
||||
|
||||
# 3.11.7
|
||||
- Build system: Fixed crash reports of Jenkins builds being rejected by the crash archive as invalid.
|
||||
- Introduced a new dependency on `pocketmine/log-pthreads`, which contains classes separated from `pocketmine/log`.
|
||||
- Fixed minimum composer stability preventing any newer version of `pocketmine/pocketmine-mp` being installed than 3.3.4 by replacing `daverandom/callback-validator` with [`pocketmine/callback-validator`](https://github.com/pmmp/CallbackValidator).
|
||||
- Fixed every player seeing eating particles when any player eats.
|
||||
- Fixed setting held item not working during `BlockBreakEvent`, `PlayerInteractEvent` and `EntityDamageEvent`.
|
||||
- Fixed some incorrect documented types in `PlayerQuitEvent` reported by PHPStan.
|
||||
- Fixed documentation of `Item->pop()` return value.
|
||||
- Fixed server crash on encountering corrupted compressed data stored in region files.
|
||||
- Protocol: Split screen header is now properly accounted for during decoding. Note that split screen is still not supported natively, but their packets can be decoded properly now.
|
||||
- Protocol: Fixed wrong order of fields in `UpdateTradePacket`.
|
||||
- Protocol: Fixed loss of `fullSkinId` when decoding network skins.
|
||||
- Fixed RCON not being able to bind to port after a fast server restart.
|
||||
|
||||
|
||||
|
53
changelogs/3.12.md
Normal file
53
changelogs/3.12.md
Normal file
@ -0,0 +1,53 @@
|
||||
**For Minecraft: Bedrock Edition 1.14.60**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 3.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 3.12.0
|
||||
- Added support for Minecraft: Bedrock Edition 1.14.60
|
||||
- Removed compatibility with 1.14.0-1.14.30
|
||||
|
||||
# 3.12.1
|
||||
- Fixed parsing of single-line doc comments for event handlers, e.g. `/** @ignoreCancelled */` should now work correctly.
|
||||
- The server will no longer crash on failure to load `level.dat` contents, but will gracefully shutdown instead without producing a crashdump.
|
||||
- Fixed some bugs in login verification that could cause undefined behaviour.
|
||||
- Fixed item-use behaviour when sneaking - sneaking and clicking a block with an empty hand, and sneaking and using an item, both now follow vanilla behaviour.
|
||||
- `start.sh` will now work on platforms where `/bin/bash` is not available, as long as `/usr/bin/env` knows where bash is.
|
||||
|
||||
# 3.12.2
|
||||
- Fixed permission default timings not being reported in timings reports (they were never stopped, only started).
|
||||
- Resource packs with a directory tree like `pack.zip/MyPack/manifest.json` are now supported. Note that the manifest closest to the root will be used.
|
||||
- Fixed `SkinImage` height and width being inverted at the protocol layer.
|
||||
- Fixed blocks being able to be placed inside the spawn protection radius by clicking the side of a block outside the radius.
|
||||
- Fixed server crash when `network.compression-level` is overridden by a CLI parameter.
|
||||
- Fixed moving entities spawning themselves to players registered on chunks when the players haven't received the chunk yet.
|
||||
- Cocoa pods now drop cocoa beans when broken instead of the block itself.
|
||||
|
||||
# 3.12.3
|
||||
- Core code is now analyzed using PHPStan level 8 (using baselines). While not all the code is level 8 compliant, this does mean that new code will be held to a higher standard, ensuring quality going forwards.
|
||||
- Players no longer burn when melee-attacked by other players. (vanilla parity)
|
||||
- Arrows shot by burning players are no longer on fire. (vanilla parity)
|
||||
- Fixed a crash that could occur with plugins on Unix filesystems that had backslashes in their names.
|
||||
- Cleaned up a whole bunch of unknowns in the protocol layer. Many new constants have been added.
|
||||
- Fixed player walking sounds.
|
||||
- Default generation queue size has been raised to 32 (previously 8). The previous default was selected in a time when PHP was much less performant than it is today, and in today's world it just needlessly slows things down.
|
||||
- Double plants are now burned away by fire.
|
||||
- Snow layers can now be stacked. (vanilla parity)
|
||||
- Resource pack sending chunk size has been reduced to 128 KB (previously 1 MB). This change was made after analyzing the effects that larger pack chunk sizes have on RakNet. Given the technical evidence, a smaller size, while slightly less bandwidth-efficient, should be more manageable for RakNet due to lower split reassembly overhead and reduced memory pressure.
|
||||
- Fixed "switching" (an exploit often complained about by PvP players). Now, the previous damage is subtracted from current damage when an entity is attacked while on cooldown. This means that attacking with a wooden sword and then diamond sword while attack cooldown is active will only deal as much damage as the diamond sword would have, instead of the combined total. This can be controlled using the `EntityDamageEvent::MODIFIER_PREVIOUS_DAMAGE_COOLDOWN` modifier. (vanilla parity)
|
||||
- Fixed projectiles knocking mobs back in unexpected directions on collision.
|
||||
- Fixed inventories not being synchronized on failed inventory transactions.
|
||||
- Vector3s decoded from packets are no longer rounded directly. Instead, the player movement handler takes responsibility for rounding the coordinates to prevent anti cheat doing something it's not supposed to.
|
||||
- `mobflame` particle can now be spawned using the `/particle` command.
|
||||
- Fixed several internal errors that could occur while modifying writable books.
|
||||
- Fixed swapping writable book pages not working in some cases.
|
||||
- `WritableBook->getPageText()` no longer throws an exception when the page doesn't exist, but returns null (as it was originally intended to).
|
||||
|
||||
# 3.12.4
|
||||
- Fixed absorption hearts not being consumed.
|
||||
|
||||
# 3.12.5
|
||||
- Fixed broken attack cooldowns.
|
@ -24,14 +24,23 @@
|
||||
"ext-yaml": ">=2.0.0",
|
||||
"ext-zip": "*",
|
||||
"ext-zlib": ">=1.2.11",
|
||||
"pocketmine/raklib": "^0.12.5",
|
||||
"pocketmine/spl": "^0.3.5",
|
||||
"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",
|
||||
"daverandom/callback-validator": "dev-master",
|
||||
"adhocore/json-comment": "^0.0.7"
|
||||
"pocketmine/classloader": "^0.1.0",
|
||||
"pocketmine/log": "^0.2.0",
|
||||
"pocketmine/log-pthreads": "^0.1.0",
|
||||
"pocketmine/callback-validator": "^1.0.1",
|
||||
"adhocore/json-comment": "^0.1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^0.12.25",
|
||||
"phpstan/phpstan-phpunit": "^0.12.6",
|
||||
"phpstan/phpstan-strict-rules": "^0.12.2",
|
||||
"phpunit/phpunit": "^8.5"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
@ -47,31 +56,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"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
1965
composer.lock
generated
1965
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,118 +1,37 @@
|
||||
includes:
|
||||
- tests/phpstan/configs/actual-problems.neon
|
||||
- tests/phpstan/configs/com-dotnet-magic.neon
|
||||
- tests/phpstan/configs/custom-leveldb.neon
|
||||
- tests/phpstan/configs/gc-hacks.neon
|
||||
- tests/phpstan/configs/l7-baseline.neon
|
||||
- tests/phpstan/configs/l8-baseline.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: 6
|
||||
level: 8
|
||||
autoload_files:
|
||||
- tests/phpstan/bootstrap.php
|
||||
- src/pocketmine/PocketMine.php
|
||||
- build/make-release.php
|
||||
- build/server-phar.php
|
||||
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
|
||||
checkMissingIterableValueType: false #TODO: pthreads Threaded base for too many things, fix this later
|
||||
ignoreErrors:
|
||||
-
|
||||
message: "#^Cannot instantiate interface pocketmine\\\\level\\\\format\\\\io\\\\LevelProvider\\.$#"
|
||||
count: 1
|
||||
path: src/pocketmine/Server.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
|
||||
path: src/pocketmine/event/entity/EntityDeathEvent.php
|
||||
|
||||
-
|
||||
message: "#^Method pocketmine\\\\event\\\\entity\\\\EntityShootBowEvent\\:\\:getEntity\\(\\) should return pocketmine\\\\entity\\\\Living but returns pocketmine\\\\entity\\\\Entity\\.$#"
|
||||
count: 1
|
||||
path: src/pocketmine/event/entity/EntityShootBowEvent.php
|
||||
|
||||
-
|
||||
message: "#^Property pocketmine\\\\event\\\\entity\\\\EntityShootBowEvent\\:\\:\\$projectile \\(pocketmine\\\\entity\\\\projectile\\\\Projectile\\) does not accept pocketmine\\\\entity\\\\Entity\\.$#"
|
||||
count: 1
|
||||
path: src/pocketmine/event/entity/EntityShootBowEvent.php
|
||||
|
||||
-
|
||||
message: "#^Method pocketmine\\\\event\\\\entity\\\\ItemDespawnEvent\\:\\:getEntity\\(\\) should return pocketmine\\\\entity\\\\object\\\\ItemEntity but returns pocketmine\\\\entity\\\\Entity\\.$#"
|
||||
count: 1
|
||||
path: src/pocketmine/event/entity/ItemDespawnEvent.php
|
||||
|
||||
-
|
||||
message: "#^Method pocketmine\\\\event\\\\entity\\\\ItemSpawnEvent\\:\\:getEntity\\(\\) should return pocketmine\\\\entity\\\\object\\\\ItemEntity but returns pocketmine\\\\entity\\\\Entity\\.$#"
|
||||
count: 1
|
||||
path: src/pocketmine/event/entity/ItemSpawnEvent.php
|
||||
|
||||
-
|
||||
message: "#^Method pocketmine\\\\event\\\\entity\\\\ProjectileHitEvent\\:\\:getEntity\\(\\) should return pocketmine\\\\entity\\\\projectile\\\\Projectile but returns pocketmine\\\\entity\\\\Entity\\.$#"
|
||||
count: 1
|
||||
path: src/pocketmine/event/entity/ProjectileHitEvent.php
|
||||
|
||||
-
|
||||
message: "#^Method pocketmine\\\\event\\\\entity\\\\ProjectileLaunchEvent\\:\\:getEntity\\(\\) should return pocketmine\\\\entity\\\\projectile\\\\Projectile but returns pocketmine\\\\entity\\\\Entity\\.$#"
|
||||
count: 1
|
||||
path: src/pocketmine/event/entity/ProjectileLaunchEvent.php
|
||||
|
||||
-
|
||||
message: "#^Constructor of class pocketmine\\\\level\\\\generator\\\\hell\\\\Nether has an unused parameter \\$options\\.$#"
|
||||
count: 1
|
||||
path: src/pocketmine/level/generator/hell/Nether.php
|
||||
|
||||
-
|
||||
message: "#^Constructor of class pocketmine\\\\level\\\\generator\\\\normal\\\\Normal has an unused parameter \\$options\\.$#"
|
||||
count: 1
|
||||
path: src/pocketmine/level/generator/normal/Normal.php
|
||||
|
||||
-
|
||||
message: "#^Constructor of class pocketmine\\\\scheduler\\\\TaskScheduler has an unused parameter \\$logger\\.$#"
|
||||
count: 1
|
||||
path: src/pocketmine/scheduler/TaskScheduler.php
|
||||
|
||||
-
|
||||
message: "#^Constant pocketmine\\\\COMPOSER_AUTOLOADER_PATH not found\\.$#"
|
||||
path: src
|
||||
|
||||
-
|
||||
message: "#^Constant pocketmine\\\\DATA not found\\.$#"
|
||||
path: src
|
||||
|
||||
-
|
||||
message: "#^Constant pocketmine\\\\GIT_COMMIT not found\\.$#"
|
||||
path: src
|
||||
|
||||
-
|
||||
message: "#^Constant pocketmine\\\\PLUGIN_PATH not found\\.$#"
|
||||
path: src
|
||||
|
||||
-
|
||||
message: "#^Constant pocketmine\\\\START_TIME not found\\.$#"
|
||||
path: src
|
||||
|
||||
-
|
||||
message: "#^Constant pocketmine\\\\VERSION not found\\.$#"
|
||||
path: src
|
||||
|
||||
staticReflectionClassNamePatterns:
|
||||
- "#^COM$#"
|
||||
|
@ -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])){
|
||||
|
@ -23,6 +23,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use function define;
|
||||
use function defined;
|
||||
use function dirname;
|
||||
|
||||
// composer autoload doesn't use require_once and also pthreads can inherit things
|
||||
if(defined('pocketmine\_CORE_CONSTANTS_INCLUDED')){
|
||||
return;
|
||||
@ -30,4 +34,4 @@ if(defined('pocketmine\_CORE_CONSTANTS_INCLUDED')){
|
||||
define('pocketmine\_CORE_CONSTANTS_INCLUDED', true);
|
||||
|
||||
define('pocketmine\PATH', dirname(__DIR__, 2) . '/');
|
||||
define('pocketmine\RESOURCE_PATH', __DIR__ . '/resources/');
|
||||
define('pocketmine\RESOURCE_PATH', __DIR__ . '/resources/');
|
||||
|
@ -100,7 +100,10 @@ class CrashDump{
|
||||
private $fp;
|
||||
/** @var int */
|
||||
private $time;
|
||||
/** @var mixed[] */
|
||||
/**
|
||||
* @var mixed[]
|
||||
* @phpstan-var array<string, mixed>
|
||||
*/
|
||||
private $data = [];
|
||||
/** @var string */
|
||||
private $encodedData = "";
|
||||
@ -144,6 +147,10 @@ class CrashDump{
|
||||
return $this->encodedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
* @phpstan-return array<string, mixed>
|
||||
*/
|
||||
public function getData() : array{
|
||||
return $this->data;
|
||||
}
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
// composer autoload doesn't use require_once and also pthreads can inherit things
|
||||
if(defined('pocketmine\_GLOBAL_CONSTANTS_INCLUDED')){
|
||||
return;
|
||||
|
@ -27,36 +27,20 @@ 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);
|
||||
@ -76,9 +60,6 @@ interface IPlayer extends ServerOperator{
|
||||
*/
|
||||
public function getLastPlayed();
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasPlayedBefore() : bool;
|
||||
|
||||
}
|
||||
|
@ -169,39 +169,24 @@ 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){
|
||||
@ -272,9 +257,6 @@ class MemoryManager{
|
||||
Timings::$memoryManagerTimer->stopTiming();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function triggerGarbageCollector() : int{
|
||||
Timings::$garbageCollectorTimer->startTiming();
|
||||
|
||||
@ -298,10 +280,6 @@ 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){
|
||||
@ -320,10 +298,6 @@ 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
|
||||
@ -363,7 +337,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){
|
||||
@ -396,14 +370,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;
|
||||
@ -451,14 +425,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");
|
||||
@ -479,17 +452,14 @@ class MemoryManager{
|
||||
|
||||
/**
|
||||
* @param mixed $from
|
||||
* @param mixed $data reference parameter
|
||||
* @param object[] $objects reference parameter
|
||||
* @param int[] $refCounts reference parameter
|
||||
* @param int $recursion
|
||||
* @param int $maxNesting
|
||||
* @param int $maxStringSize
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private static function continueDump($from, &$data, array &$objects, array &$refCounts, int $recursion, int $maxNesting, int $maxStringSize) : void{
|
||||
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;
|
||||
@ -505,12 +475,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);
|
||||
@ -519,5 +488,7 @@ class MemoryManager{
|
||||
}else{
|
||||
$data = $from;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -173,19 +173,18 @@ namespace pocketmine {
|
||||
|
||||
$opts = getopt("", ["bootstrap:"]);
|
||||
if(isset($opts["bootstrap"])){
|
||||
$bootstrap = realpath($opts["bootstrap"]) ?: $opts["bootstrap"];
|
||||
$bootstrap = ($real = realpath($opts["bootstrap"])) !== false ? $real : $opts["bootstrap"];
|
||||
}else{
|
||||
$bootstrap = dirname(__FILE__, 3) . '/vendor/autoload.php';
|
||||
}
|
||||
define('pocketmine\COMPOSER_AUTOLOADER_PATH', $bootstrap);
|
||||
|
||||
if(\pocketmine\COMPOSER_AUTOLOADER_PATH !== false and is_file(\pocketmine\COMPOSER_AUTOLOADER_PATH)){
|
||||
require_once(\pocketmine\COMPOSER_AUTOLOADER_PATH);
|
||||
}else{
|
||||
if($bootstrap === false or !is_file($bootstrap)){
|
||||
critical_error("Composer autoloader not found at " . $bootstrap);
|
||||
critical_error("Please install/update Composer dependencies or use provided builds.");
|
||||
exit(1);
|
||||
}
|
||||
define('pocketmine\COMPOSER_AUTOLOADER_PATH', $bootstrap);
|
||||
require_once(\pocketmine\COMPOSER_AUTOLOADER_PATH);
|
||||
|
||||
set_error_handler([Utils::class, 'errorExceptionHandler']);
|
||||
|
||||
@ -263,7 +262,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
@ -23,6 +23,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use const PTHREADS_INHERIT_ALL;
|
||||
|
||||
/**
|
||||
* This class must be extended by all custom threading classes
|
||||
*/
|
||||
@ -44,8 +46,6 @@ abstract class Thread extends \Thread{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \ClassLoader|null $loader
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setClassLoader(\ClassLoader $loader = null){
|
||||
@ -80,7 +80,7 @@ abstract class Thread extends \Thread{
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function start(?int $options = \PTHREADS_INHERIT_ALL){
|
||||
public function start(?int $options = PTHREADS_INHERIT_ALL){
|
||||
ThreadManager::getInstance()->add($this);
|
||||
|
||||
if($this->getClassLoader() === null){
|
||||
|
@ -28,10 +28,11 @@ 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(){
|
||||
@ -42,6 +43,9 @@ class ThreadManager extends \Volatile{
|
||||
* @return ThreadManager
|
||||
*/
|
||||
public static function getInstance(){
|
||||
if(self::$instance === null){
|
||||
self::$instance = new ThreadManager();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
@ -52,7 +56,7 @@ class ThreadManager extends \Volatile{
|
||||
*/
|
||||
public function add($thread){
|
||||
if($thread instanceof Thread or $thread instanceof Worker){
|
||||
$this->{spl_object_hash($thread)} = $thread;
|
||||
$this[spl_object_hash($thread)] = $thread;
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,7 +67,7 @@ class ThreadManager extends \Volatile{
|
||||
*/
|
||||
public function remove($thread){
|
||||
if($thread instanceof Thread or $thread instanceof Worker){
|
||||
unset($this->{spl_object_hash($thread)});
|
||||
unset($this[spl_object_hash($thread)]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use function defined;
|
||||
|
||||
// composer autoload doesn't use require_once and also pthreads can inherit things
|
||||
// TODO: drop this file and use a final class with constants
|
||||
if(defined('pocketmine\_VERSION_INFO_INCLUDED')){
|
||||
@ -30,8 +32,7 @@ if(defined('pocketmine\_VERSION_INFO_INCLUDED')){
|
||||
}
|
||||
const _VERSION_INFO_INCLUDED = true;
|
||||
|
||||
|
||||
const NAME = "PocketMine-MP";
|
||||
const BASE_VERSION = "3.11.4";
|
||||
const BASE_VERSION = "3.12.5";
|
||||
const IS_DEVELOPMENT_BUILD = false;
|
||||
const BUILD_NUMBER = 0;
|
||||
|
@ -23,6 +23,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use const PTHREADS_INHERIT_ALL;
|
||||
|
||||
/**
|
||||
* This class must be extended by all custom threading classes
|
||||
*/
|
||||
@ -44,8 +46,6 @@ abstract class Worker extends \Worker{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \ClassLoader|null $loader
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setClassLoader(\ClassLoader $loader = null){
|
||||
@ -80,7 +80,7 @@ abstract class Worker extends \Worker{
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function start(?int $options = \PTHREADS_INHERIT_ALL){
|
||||
public function start(?int $options = PTHREADS_INHERIT_ALL){
|
||||
ThreadManager::getInstance()->add($this);
|
||||
|
||||
if($this->getClassLoader() === null){
|
||||
|
@ -26,7 +26,6 @@ namespace pocketmine\block;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
|
||||
|
||||
/**
|
||||
* Air block
|
||||
*/
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -69,16 +69,11 @@ class Bed extends Transparent{
|
||||
return ($this->meta & self::BITFLAG_HEAD) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isOccupied() : bool{
|
||||
return ($this->meta & self::BITFLAG_OCCUPIED) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $occupied
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setOccupied(bool $occupied = true){
|
||||
@ -95,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;
|
||||
@ -127,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))){
|
||||
|
@ -50,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);
|
||||
@ -73,7 +67,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
/** @var AxisAlignedBB|null */
|
||||
protected $boundingBox = null;
|
||||
|
||||
|
||||
/** @var AxisAlignedBB[]|null */
|
||||
protected $collisionBoxes = null;
|
||||
|
||||
@ -90,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;
|
||||
}
|
||||
@ -107,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();
|
||||
@ -116,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");
|
||||
@ -145,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;
|
||||
@ -154,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;
|
||||
}
|
||||
@ -182,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);
|
||||
@ -198,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;
|
||||
}
|
||||
@ -223,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;
|
||||
@ -236,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){
|
||||
@ -254,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{
|
||||
@ -300,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;
|
||||
@ -324,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;
|
||||
@ -336,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;
|
||||
@ -344,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;
|
||||
}
|
||||
@ -380,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;
|
||||
}
|
||||
@ -400,7 +322,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
/**
|
||||
* AKA: Block->isFlowable
|
||||
* @return bool
|
||||
*/
|
||||
public function canBeFlowedInto() : bool{
|
||||
return false;
|
||||
@ -416,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;
|
||||
@ -443,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{
|
||||
@ -462,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{
|
||||
@ -475,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{
|
||||
@ -487,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)){
|
||||
@ -502,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;
|
||||
@ -512,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;
|
||||
@ -521,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());
|
||||
@ -529,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;
|
||||
@ -538,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;
|
||||
@ -547,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;
|
||||
@ -556,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;
|
||||
@ -565,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;
|
||||
@ -582,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){
|
||||
@ -643,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){
|
||||
@ -658,9 +544,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Entity $entity
|
||||
*/
|
||||
public function onEntityCollide(Entity $entity) : void{
|
||||
|
||||
}
|
||||
@ -680,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();
|
||||
@ -697,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,
|
||||
@ -720,12 +597,6 @@ 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(count($bbs) === 0){
|
||||
|
@ -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{
|
||||
|
@ -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;
|
||||
|
@ -112,8 +112,6 @@ class CobblestoneWall extends Transparent{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Block $block
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canConnect(Block $block){
|
||||
|
@ -23,6 +23,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\ItemIds;
|
||||
use function mt_rand;
|
||||
|
||||
class CocoaBlock extends Transparent{
|
||||
|
||||
protected $id = self::COCOA_BLOCK;
|
||||
@ -48,4 +53,14 @@ class CocoaBlock extends Transparent{
|
||||
public function isAffectedBySilkTouch() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get(ItemIds::DYE, 3, ($this->meta >> 2) === 2 ? mt_rand(2, 3) : 1)
|
||||
];
|
||||
}
|
||||
|
||||
public function getPickedItem() : Item{
|
||||
return ItemFactory::get(ItemIds::DYE, 3);
|
||||
}
|
||||
}
|
||||
|
@ -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){
|
||||
|
@ -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;
|
||||
@ -56,7 +55,7 @@ abstract class Crops extends Flowable{
|
||||
$this->getLevel()->setBlock($this, $ev->getNewState(), true, true);
|
||||
}
|
||||
|
||||
$item->count--;
|
||||
$item->pop();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -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){
|
||||
|
@ -29,7 +29,6 @@ use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
|
||||
abstract class Door extends Transparent{
|
||||
|
||||
public function isSolid() : bool{
|
||||
|
@ -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);
|
||||
}
|
||||
@ -125,4 +124,12 @@ class DoublePlant extends Flowable{
|
||||
|
||||
return parent::getAffectedBlocks();
|
||||
}
|
||||
|
||||
public function getFlameEncouragement() : int{
|
||||
return 60;
|
||||
}
|
||||
|
||||
public function getFlammability() : int{
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
|
@ -45,9 +45,6 @@ abstract class Fallable extends Solid{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|Block
|
||||
*/
|
||||
public function tickFalling() : ?Block{
|
||||
return null;
|
||||
}
|
||||
|
@ -48,7 +48,6 @@ class Farmland extends Transparent{
|
||||
return BlockToolType::TYPE_SHOVEL;
|
||||
}
|
||||
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
|
@ -104,8 +104,6 @@ abstract class Fence extends Transparent{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Block $block
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canConnect(Block $block){
|
||||
|
@ -39,7 +39,6 @@ class FenceGate extends Transparent{
|
||||
return BlockToolType::TYPE_AXE;
|
||||
}
|
||||
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
|
||||
if(($this->getDamage() & 0x04) > 0){
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
class Furnace extends BurningFurnace{
|
||||
|
||||
protected $id = self::FURNACE;
|
||||
|
@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
use pocketmine\item\TieredTool;
|
||||
|
||||
class GlowingObsidian extends Solid{
|
||||
|
@ -99,7 +99,7 @@ class Grass extends Solid{
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if($item->getId() === Item::DYE and $item->getDamage() === 0x0F){
|
||||
$item->count--;
|
||||
$item->pop();
|
||||
TallGrassObject::growGrass($this->getLevel(), $this, new Random(mt_rand()), 8, 2);
|
||||
|
||||
return true;
|
||||
|
@ -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 = [
|
||||
|
@ -68,7 +68,10 @@ class Leaves extends Transparent{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @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])){
|
||||
@ -169,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);
|
||||
}
|
||||
|
||||
|
@ -211,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;
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
class MossyCobblestone extends Cobblestone{
|
||||
|
||||
protected $id = self::MOSSY_COBBLESTONE;
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
use pocketmine\event\block\BlockGrowEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
|
@ -72,7 +72,7 @@ class Sapling extends Flowable{
|
||||
//TODO: change log type
|
||||
Tree::growTree($this->getLevel(), $this->x, $this->y, $this->z, new Random(mt_rand()), $this->getVariant());
|
||||
|
||||
$item->count--;
|
||||
$item->pop();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -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){
|
||||
|
||||
|
@ -42,7 +42,7 @@ class SnowLayer extends Flowable{
|
||||
}
|
||||
|
||||
public function canBeReplaced() : bool{
|
||||
return true;
|
||||
return $this->meta < 7; //8 snow layers
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
@ -57,9 +57,15 @@ class SnowLayer extends Flowable{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
private function canBeSupportedBy(Block $b) : bool{
|
||||
return $b->isSolid() or ($b->getId() === $this->getId() and $b->getDamage() === 7);
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
if($blockReplace->getSide(Vector3::SIDE_DOWN)->isSolid()){
|
||||
//TODO: fix placement
|
||||
if($blockReplace->getId() === $this->getId() and $blockReplace->getDamage() < 7){
|
||||
$this->setDamage($blockReplace->getDamage() + 1);
|
||||
}
|
||||
if($this->canBeSupportedBy($blockReplace->getSide(Vector3::SIDE_DOWN))){
|
||||
$this->getLevel()->setBlock($blockReplace, $this, true);
|
||||
|
||||
return true;
|
||||
@ -69,7 +75,7 @@ class SnowLayer extends Flowable{
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if(!$this->getSide(Vector3::SIDE_DOWN)->isSolid()){
|
||||
if(!$this->canBeSupportedBy($this->getSide(Vector3::SIDE_DOWN))){
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), false, false);
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
class Sponge extends Solid{
|
||||
|
||||
protected $id = self::SPONGE;
|
||||
|
@ -62,7 +62,7 @@ class Sugarcane extends Flowable{
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
}
|
||||
|
||||
$item->count--;
|
||||
$item->pop();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -75,8 +75,6 @@ class TNT extends Solid{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $fuse
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function ignite(int $fuse = 80){
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
abstract class Transparent extends Block{
|
||||
|
||||
public function isTransparent() : bool{
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -70,8 +70,6 @@ class Water extends Liquid{
|
||||
if($entity->isOnFire()){
|
||||
$entity->extinguish();
|
||||
}
|
||||
|
||||
$entity->resetFallDistance();
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
|
@ -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);
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
class Wood2 extends Wood{
|
||||
|
||||
public const ACACIA = 0;
|
||||
|
@ -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,21 +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;
|
||||
@ -140,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;
|
||||
@ -159,9 +136,6 @@ abstract class Command{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLabel() : string{
|
||||
return $this->label;
|
||||
}
|
||||
@ -183,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)){
|
||||
@ -198,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;
|
||||
@ -215,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;
|
||||
}
|
||||
@ -238,23 +195,14 @@ 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;
|
||||
}
|
||||
@ -272,8 +220,6 @@ abstract class Command{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $description
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setDescription(string $description){
|
||||
@ -281,8 +227,6 @@ abstract class Command{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $permissionMessage
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPermissionMessage(string $permissionMessage){
|
||||
@ -290,8 +234,6 @@ abstract class Command{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $usage
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUsage(string $usage){
|
||||
@ -299,9 +241,7 @@ abstract class Command{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CommandSender $source
|
||||
* @param TextContainer|string $message
|
||||
* @param bool $sendToSource
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
@ -338,9 +278,6 @@ abstract class Command{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString() : string{
|
||||
return $this->name;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -23,32 +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;
|
||||
|
||||
/**
|
||||
@ -57,11 +42,8 @@ interface CommandMap{
|
||||
public function clearCommands();
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return Command|null
|
||||
*/
|
||||
public function getCommand(string $name);
|
||||
|
||||
|
||||
}
|
||||
|
@ -116,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));
|
||||
@ -156,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
|
||||
|
@ -41,24 +41,17 @@ 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);
|
||||
|
@ -49,8 +49,6 @@ class ConsoleCommandSender implements CommandSender{
|
||||
|
||||
/**
|
||||
* @param Permission|string $name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isPermissionSet($name) : bool{
|
||||
return $this->perm->isPermissionSet($name);
|
||||
@ -58,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){
|
||||
@ -120,23 +107,15 @@ 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){
|
||||
|
@ -36,7 +36,6 @@ class FormattedCommandAlias extends Command{
|
||||
private $formatStrings = [];
|
||||
|
||||
/**
|
||||
* @param string $alias
|
||||
* @param string[] $formatStrings
|
||||
*/
|
||||
public function __construct(string $alias, array $formatStrings){
|
||||
@ -66,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, '$');
|
||||
@ -144,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;
|
||||
}
|
||||
|
@ -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,17 +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;
|
||||
}
|
||||
|
@ -27,8 +27,5 @@ use pocketmine\plugin\Plugin;
|
||||
|
||||
interface PluginIdentifiableCommand{
|
||||
|
||||
/**
|
||||
* @return Plugin
|
||||
*/
|
||||
public function getPlugin() : Plugin;
|
||||
}
|
||||
|
@ -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 */
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -296,7 +274,6 @@ class SimpleCommandMap implements CommandMap{
|
||||
return $this->knownCommands;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
@ -318,10 +295,9 @@ 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;
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -68,7 +68,6 @@ class KickCommand extends VanillaCommand{
|
||||
$sender->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.generic.player.notFound"));
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}));
|
||||
|
||||
|
@ -37,6 +37,7 @@ use pocketmine\level\particle\CriticalParticle;
|
||||
use pocketmine\level\particle\DustParticle;
|
||||
use pocketmine\level\particle\EnchantmentTableParticle;
|
||||
use pocketmine\level\particle\EnchantParticle;
|
||||
use pocketmine\level\particle\EntityFlameParticle;
|
||||
use pocketmine\level\particle\ExplodeParticle;
|
||||
use pocketmine\level\particle\FlameParticle;
|
||||
use pocketmine\level\particle\HappyVillagerParticle;
|
||||
@ -119,7 +120,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 +137,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){
|
||||
@ -212,7 +205,8 @@ class ParticleCommand extends VanillaCommand{
|
||||
return new AngryVillagerParticle($pos);
|
||||
case "forcefield":
|
||||
return new BlockForceFieldParticle($pos, $data ?? 0);
|
||||
|
||||
case "mobflame":
|
||||
return new EntityFlameParticle($pos);
|
||||
}
|
||||
|
||||
if(strpos($name, "iconcrack_") === 0){
|
||||
|
@ -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){
|
||||
|
@ -85,7 +85,6 @@ class TimeCommand extends VanillaCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if(count($args) < 2){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -21,10 +21,8 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace pocketmine\command\defaults;
|
||||
|
||||
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\Player;
|
||||
|
@ -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;
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\entity;
|
||||
|
||||
|
||||
interface Ageable{
|
||||
public function isBaby() : bool;
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\entity;
|
||||
|
||||
|
||||
abstract class Animal extends Creature implements Ageable{
|
||||
|
||||
public function isBaby() : bool{
|
||||
|
@ -87,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{
|
||||
@ -106,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){
|
||||
@ -146,8 +127,6 @@ class Attribute{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $minValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setMinValue(float $minValue){
|
||||
@ -167,8 +146,6 @@ class Attribute{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $maxValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setMaxValue(float $maxValue){
|
||||
@ -188,8 +165,6 @@ class Attribute{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $defaultValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setDefaultValue(float $defaultValue){
|
||||
@ -213,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){
|
||||
|
@ -36,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;
|
||||
}
|
||||
@ -56,15 +51,13 @@ 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
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function offsetExists($offset) : bool{
|
||||
return isset($this->attributes[$offset]);
|
||||
@ -72,18 +65,19 @@ class AttributeMap implements \ArrayAccess{
|
||||
|
||||
/**
|
||||
* @param int $offset
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function offsetGet($offset) : float{
|
||||
return $this->attributes[$offset]->getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $offset
|
||||
* @param float $value
|
||||
* @param int|null $offset
|
||||
* @param float $value
|
||||
*/
|
||||
public function offsetSet($offset, $value) : void{
|
||||
if($offset === null){
|
||||
throw new \InvalidArgumentException("Array push syntax is not supported");
|
||||
}
|
||||
$this->attributes[$offset]->setValue($value);
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\entity;
|
||||
|
||||
|
||||
abstract class Creature extends Living{
|
||||
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\entity;
|
||||
|
||||
|
||||
interface Damageable{
|
||||
|
||||
}
|
||||
|
@ -32,112 +32,68 @@ use function is_string;
|
||||
|
||||
class DataPropertyManager{
|
||||
|
||||
/** @var mixed[][] */
|
||||
/**
|
||||
* @var mixed[][]
|
||||
* @phpstan-var array<int, array{0: int, 1: mixed}>
|
||||
*/
|
||||
private $properties = [];
|
||||
|
||||
/** @var mixed[][] */
|
||||
/**
|
||||
* @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);
|
||||
}
|
||||
@ -152,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];
|
||||
@ -248,9 +161,6 @@ class DataPropertyManager{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $key
|
||||
* @param int $type
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPropertyValue(int $key, int $type){
|
||||
@ -261,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){
|
||||
@ -276,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;
|
||||
@ -285,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;
|
||||
|
@ -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)){
|
||||
@ -138,7 +125,7 @@ class Effect{
|
||||
/**
|
||||
* @param int $id Effect ID as per Minecraft PE
|
||||
* @param string $name Translation key used for effect name
|
||||
* @param Color $color
|
||||
* @param Color $color Color of bubbles given by this effect
|
||||
* @param bool $isBad Whether the effect is harmful
|
||||
* @param int $defaultDuration Duration in ticks the effect will last for by default if applied without a duration.
|
||||
* @param bool $hasBubbles Whether the effect has potion bubbles. Some do not (e.g. Instant Damage has its own particles instead of bubbles)
|
||||
@ -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,7 +170,6 @@ class Effect{
|
||||
|
||||
/**
|
||||
* Returns whether the effect is by default an instant effect.
|
||||
* @return bool
|
||||
*/
|
||||
public function isInstantEffect() : bool{
|
||||
return $this->defaultDuration <= 1;
|
||||
@ -196,8 +177,6 @@ class Effect{
|
||||
|
||||
/**
|
||||
* Returns the default duration (in ticks) this effect will apply for if a duration is not specified.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getDefaultDuration() : int{
|
||||
return $this->defaultDuration;
|
||||
@ -205,7 +184,6 @@ class Effect{
|
||||
|
||||
/**
|
||||
* Returns whether this effect will give the subject potion bubbles.
|
||||
* @return bool
|
||||
*/
|
||||
public function hasBubbles() : bool{
|
||||
return $this->hasBubbles;
|
||||
@ -213,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){
|
||||
@ -249,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){
|
||||
@ -315,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){
|
||||
@ -348,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){
|
||||
|
@ -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,17 +62,12 @@ class EffectInstance{
|
||||
return $this->effectType->getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Effect
|
||||
*/
|
||||
public function getType() : Effect{
|
||||
return $this->effectType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of ticks remaining until the effect expires.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getDuration() : int{
|
||||
return $this->duration;
|
||||
@ -86,8 +76,6 @@ class EffectInstance{
|
||||
/**
|
||||
* Sets the number of ticks remaining until the effect expires.
|
||||
*
|
||||
* @param int $duration
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return $this
|
||||
@ -104,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{
|
||||
@ -116,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{
|
||||
@ -152,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{
|
||||
@ -174,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{
|
||||
@ -195,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;
|
||||
@ -204,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;
|
||||
@ -217,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();
|
||||
|
@ -297,11 +297,11 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
public const DATA_FLAG_OVER_SCAFFOLDING = 69;
|
||||
public const DATA_FLAG_FALL_THROUGH_SCAFFOLDING = 70;
|
||||
public const DATA_FLAG_BLOCKING = 71; //shield
|
||||
public const DATA_FLAG_DISABLE_BLOCKING = 72;
|
||||
//73 is set when a player is attacked while using shield, unclear on purpose
|
||||
//74 related to shield usage, needs further investigation
|
||||
public const DATA_FLAG_TRANSITION_BLOCKING = 72;
|
||||
public const DATA_FLAG_BLOCKED_USING_SHIELD = 73;
|
||||
public const DATA_FLAG_BLOCKED_USING_DAMAGED_SHIELD = 74;
|
||||
public const DATA_FLAG_SLEEPING = 75;
|
||||
//76 related to sleeping, unclear usage
|
||||
public const DATA_FLAG_WANTS_TO_WAKE = 76;
|
||||
public const DATA_FLAG_TRADE_INTEREST = 77;
|
||||
public const DATA_FLAG_DOOR_BREAKER = 78; //...
|
||||
public const DATA_FLAG_BREAKING_OBSTRUCTION = 79;
|
||||
@ -311,17 +311,27 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
public const DATA_FLAG_ROARING = 83;
|
||||
public const DATA_FLAG_DELAYED_ATTACKING = 84;
|
||||
public const DATA_FLAG_AVOIDING_MOBS = 85;
|
||||
//86 used by RangedAttackGoal
|
||||
//87 used by NearestAttackableTargetGoal
|
||||
public const DATA_FLAG_FACING_TARGET_TO_RANGE_ATTACK = 86;
|
||||
public const DATA_FLAG_HIDDEN_WHEN_INVISIBLE = 87; //??????????????????
|
||||
public const DATA_FLAG_IS_IN_UI = 88;
|
||||
public const DATA_FLAG_STALKING = 89;
|
||||
public const DATA_FLAG_EMOTING = 90;
|
||||
public const DATA_FLAG_CELEBRATING = 91;
|
||||
|
||||
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 = [];
|
||||
|
||||
/**
|
||||
@ -353,17 +363,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])){
|
||||
@ -381,15 +386,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){
|
||||
@ -417,13 +419,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("", [
|
||||
@ -433,9 +428,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),
|
||||
@ -444,9 +439,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @var Player[]
|
||||
*/
|
||||
/** @var Player[] */
|
||||
protected $hasSpawned = [];
|
||||
|
||||
/** @var int */
|
||||
@ -481,7 +474,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
/** @var Vector3 */
|
||||
public $temporalVector;
|
||||
|
||||
|
||||
/** @var float */
|
||||
public $lastYaw;
|
||||
/** @var float */
|
||||
@ -652,73 +644,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");
|
||||
@ -789,7 +750,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);
|
||||
@ -797,8 +757,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);
|
||||
@ -806,8 +764,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);
|
||||
@ -815,8 +771,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);
|
||||
@ -824,7 +778,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);
|
||||
@ -832,7 +785,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();
|
||||
@ -846,8 +798,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{
|
||||
@ -862,7 +812,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);
|
||||
@ -871,8 +820,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();
|
||||
@ -886,8 +833,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{
|
||||
@ -902,7 +847,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;
|
||||
@ -911,8 +855,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;
|
||||
@ -920,8 +862,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])){
|
||||
@ -968,8 +908,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"));
|
||||
|
||||
@ -987,9 +925,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EntityDamageEvent $source
|
||||
*/
|
||||
public function attack(EntityDamageEvent $source) : void{
|
||||
$source->call();
|
||||
if($source->isCancelled()){
|
||||
@ -1001,9 +936,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()){
|
||||
@ -1020,10 +952,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;
|
||||
@ -1033,17 +961,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){
|
||||
@ -1062,30 +985,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;
|
||||
}
|
||||
@ -1148,15 +1059,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{
|
||||
@ -1261,6 +1168,9 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
if($teleport){
|
||||
$pk->flags |= MoveActorAbsolutePacket::FLAG_TELEPORT;
|
||||
}
|
||||
if($this->onGround){
|
||||
$pk->flags |= MoveActorAbsolutePacket::FLAG_GROUND;
|
||||
}
|
||||
|
||||
$this->level->broadcastPacketToViewers($this, $pk);
|
||||
}
|
||||
@ -1397,9 +1307,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){
|
||||
@ -1418,9 +1325,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));
|
||||
@ -1458,7 +1362,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
$this->timings->startTiming();
|
||||
|
||||
if($this->hasMovementUpdate()){
|
||||
@ -1487,7 +1390,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
$hasUpdate = $this->entityBaseTick($tickDiff);
|
||||
Timings::$timerEntityBaseTick->stopTiming();
|
||||
|
||||
|
||||
$this->timings->stopTiming();
|
||||
|
||||
//if($this->isStatic())
|
||||
@ -1510,8 +1412,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;
|
||||
@ -1521,7 +1421,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 (
|
||||
@ -1541,10 +1440,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){
|
||||
@ -1558,8 +1453,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{
|
||||
|
||||
@ -1625,7 +1518,6 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
$this->isCollided = $this->onGround;
|
||||
$this->updateFallState($dy, $this->onGround);
|
||||
|
||||
|
||||
Timings::$entityMoveTimer->stopTiming();
|
||||
|
||||
return true;
|
||||
@ -1710,7 +1602,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;
|
||||
@ -1823,8 +1714,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;
|
||||
@ -1960,10 +1849,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){
|
||||
@ -2032,8 +1917,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();
|
||||
@ -2050,11 +1933,13 @@ 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())])){
|
||||
if(
|
||||
!isset($this->hasSpawned[$player->getLoaderId()]) and
|
||||
$this->chunk !== null and
|
||||
isset($player->usedChunks[$chunkHash = Level::chunkHash($this->chunk->getX(), $this->chunk->getZ())]) and
|
||||
$player->usedChunks[$chunkHash] === true
|
||||
){
|
||||
$this->hasSpawned[$player->getLoaderId()] = $player;
|
||||
|
||||
$this->sendSpawnPacket($player);
|
||||
@ -2082,9 +1967,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()])){
|
||||
@ -2121,7 +2003,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;
|
||||
@ -2161,12 +2042,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);
|
||||
@ -2175,22 +2050,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);
|
||||
@ -2198,9 +2063,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);
|
||||
@ -2208,7 +2070,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)){
|
||||
@ -2231,6 +2094,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;
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\entity;
|
||||
|
||||
|
||||
interface Explosive{
|
||||
|
||||
/**
|
||||
|
@ -38,6 +38,7 @@ use pocketmine\item\Durable;
|
||||
use pocketmine\item\enchantment\Enchantment;
|
||||
use pocketmine\item\FoodSource;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\MaybeConsumable;
|
||||
use pocketmine\item\Totem;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\nbt\NBT;
|
||||
@ -50,6 +51,7 @@ use pocketmine\network\mcpe\protocol\ActorEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\AddPlayerPacket;
|
||||
use pocketmine\network\mcpe\protocol\LevelEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\MovePlayerPacket;
|
||||
use pocketmine\network\mcpe\protocol\PlayerListPacket;
|
||||
use pocketmine\network\mcpe\protocol\PlayerSkinPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
|
||||
@ -116,9 +118,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CompoundTag $skinTag
|
||||
*
|
||||
* @return Skin
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected static function deserializeSkinNBT(CompoundTag $skinTag) : Skin{
|
||||
@ -137,32 +136,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;
|
||||
@ -171,8 +159,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();
|
||||
@ -210,8 +196,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{
|
||||
@ -241,8 +225,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();
|
||||
@ -256,8 +238,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{
|
||||
@ -276,8 +256,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);
|
||||
@ -286,9 +264,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{
|
||||
@ -322,6 +297,10 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
||||
}
|
||||
|
||||
public function consumeObject(Consumable $consumable) : bool{
|
||||
if($consumable instanceof MaybeConsumable and !$consumable->canBeConsumed()){
|
||||
return false;
|
||||
}
|
||||
|
||||
if($consumable instanceof FoodSource){
|
||||
if($consumable->requiresHunger() and !$this->isHungry()){
|
||||
return false;
|
||||
@ -336,7 +315,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();
|
||||
@ -344,10 +322,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);
|
||||
@ -355,11 +329,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();
|
||||
@ -379,10 +348,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);
|
||||
@ -390,7 +355,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();
|
||||
@ -398,10 +362,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);
|
||||
@ -409,7 +369,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());
|
||||
@ -419,8 +378,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();
|
||||
@ -429,10 +386,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);
|
||||
@ -444,10 +397,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;
|
||||
@ -478,10 +428,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);
|
||||
@ -514,8 +460,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;
|
||||
@ -524,8 +468,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){
|
||||
@ -537,7 +479,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;
|
||||
@ -554,9 +495,9 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -581,8 +522,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;
|
||||
@ -591,7 +530,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());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -886,6 +825,23 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
||||
}
|
||||
}
|
||||
|
||||
public function broadcastMovement(bool $teleport = false) : void{
|
||||
//TODO: workaround 1.14.30 bug: MoveActor(Absolute|Delta)Packet don't work on players anymore :(
|
||||
$pk = new MovePlayerPacket();
|
||||
$pk->entityRuntimeId = $this->getId();
|
||||
$pk->position = $this->getOffsetPosition($this);
|
||||
$pk->yaw = $this->yaw;
|
||||
$pk->pitch = $this->pitch;
|
||||
$pk->headYaw = $this->yaw;
|
||||
$pk->mode = $teleport ? MovePlayerPacket::MODE_TELEPORT : MovePlayerPacket::MODE_NORMAL;
|
||||
|
||||
//we can't assume that everyone who is using our chunk wants to see this movement,
|
||||
//because this human might be a player who shouldn't be receiving his own movement.
|
||||
//this didn't matter when we were able to use MoveActorPacket because
|
||||
//the client just ignored MoveActor for itself, but it doesn't ignore MovePlayer for itself.
|
||||
$this->server->broadcastPacket($this->hasSpawned, $pk);
|
||||
}
|
||||
|
||||
public function close() : void{
|
||||
if(!$this->closed){
|
||||
if($this->inventory !== null){
|
||||
@ -902,10 +858,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);
|
||||
@ -913,9 +865,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);
|
||||
|
@ -37,6 +37,7 @@ use pocketmine\item\Consumable;
|
||||
use pocketmine\item\Durable;
|
||||
use pocketmine\item\enchantment\Enchantment;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\MaybeConsumable;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\math\VoxelRayTrace;
|
||||
use pocketmine\nbt\tag\ByteTag;
|
||||
@ -111,7 +112,7 @@ abstract class Living extends Entity implements Damageable{
|
||||
|
||||
$this->setHealth($health);
|
||||
|
||||
/** @var CompoundTag[]|ListTag $activeEffectsTag */
|
||||
/** @var CompoundTag[]|ListTag|null $activeEffectsTag */
|
||||
$activeEffectsTag = $this->namedtag->getListTag("ActiveEffects");
|
||||
if($activeEffectsTag !== null){
|
||||
foreach($activeEffectsTag as $e){
|
||||
@ -187,7 +188,6 @@ abstract class Living extends Entity implements Damageable{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function hasLineOfSight(Entity $entity) : bool{
|
||||
//TODO: head height
|
||||
return true;
|
||||
@ -213,8 +213,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])){
|
||||
@ -240,10 +238,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;
|
||||
@ -251,10 +245,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]);
|
||||
@ -262,7 +252,6 @@ abstract class Living extends Entity implements Damageable{
|
||||
|
||||
/**
|
||||
* Returns whether the mob has any active effects.
|
||||
* @return bool
|
||||
*/
|
||||
public function hasEffects() : bool{
|
||||
return count($this->effects) > 0;
|
||||
@ -273,8 +262,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{
|
||||
@ -345,8 +332,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){
|
||||
@ -373,12 +358,12 @@ 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{
|
||||
if($consumable instanceof MaybeConsumable and !$consumable->canBeConsumed()){
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach($consumable->getAdditionalEffects() as $effect){
|
||||
$this->addEffect($effect);
|
||||
}
|
||||
@ -390,7 +375,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);
|
||||
@ -417,8 +401,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;
|
||||
@ -431,10 +413,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;
|
||||
@ -445,9 +423,6 @@ abstract class Living extends Entity implements Damageable{
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ArmorInventory
|
||||
*/
|
||||
public function getArmorInventory() : ArmorInventory{
|
||||
return $this->armorInventory;
|
||||
}
|
||||
@ -459,10 +434,14 @@ 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($this->lastDamageCause !== null and $this->attackTime > 0){
|
||||
if($this->lastDamageCause->getBaseDamage() >= $source->getBaseDamage()){
|
||||
$source->setCancelled();
|
||||
}
|
||||
$source->setModifier(-$this->lastDamageCause->getBaseDamage(), EntityDamageEvent::MODIFIER_PREVIOUS_DAMAGE_COOLDOWN);
|
||||
}
|
||||
if($source->canBeReducedByArmor()){
|
||||
//MCPE uses the same system as PC did pre-1.9
|
||||
$source->setModifier(-$source->getFinalDamage() * $this->getArmorPoints() * 0.04, EntityDamageEvent::MODIFIER_ARMOR);
|
||||
@ -488,8 +467,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)));
|
||||
@ -519,8 +496,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);
|
||||
@ -545,11 +520,6 @@ abstract class Living extends Entity implements Damageable{
|
||||
public function attack(EntityDamageEvent $source) : void{
|
||||
if($this->noDamageTicks > 0){
|
||||
$source->setCancelled();
|
||||
}elseif($this->attackTime > 0){
|
||||
$lastCause = $this->getLastDamageCause();
|
||||
if($lastCause !== null and $lastCause->getBaseDamage() >= $source->getBaseDamage()){
|
||||
$source->setCancelled();
|
||||
}
|
||||
}
|
||||
|
||||
if($this->hasEffect(Effect::FIRE_RESISTANCE) and (
|
||||
@ -581,20 +551,15 @@ abstract class Living extends Entity implements Damageable{
|
||||
|
||||
$this->attackTime = $source->getAttackCooldown();
|
||||
|
||||
if($source instanceof EntityDamageByEntityEvent){
|
||||
$e = $source->getDamager();
|
||||
if($source instanceof EntityDamageByChildEntityEvent){
|
||||
$e = $source->getChild();
|
||||
}
|
||||
|
||||
if($source instanceof EntityDamageByChildEntityEvent){
|
||||
$e = $source->getChild();
|
||||
if($e !== null){
|
||||
$motion = $e->getMotion();
|
||||
$this->knockBack($e, $source->getBaseDamage(), $motion->x, $motion->z, $source->getKnockBack());
|
||||
}
|
||||
}elseif($source instanceof EntityDamageByEntityEvent){
|
||||
$e = $source->getDamager();
|
||||
if($e !== null){
|
||||
if((
|
||||
$source->getCause() === EntityDamageEvent::CAUSE_PROJECTILE or
|
||||
$source->getCause() === EntityDamageEvent::CAUSE_ENTITY_ATTACK
|
||||
) and $e->isOnFire()){
|
||||
$this->setOnFire(2 * $this->level->getDifficulty());
|
||||
}
|
||||
|
||||
$deltaX = $this->x - $e->x;
|
||||
$deltaZ = $this->z - $e->z;
|
||||
$this->knockBack($e, $source->getBaseDamage(), $deltaX, $deltaZ, $source->getKnockBack());
|
||||
@ -720,10 +685,6 @@ abstract class Living extends Entity implements Damageable{
|
||||
|
||||
/**
|
||||
* 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();
|
||||
@ -759,7 +720,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();
|
||||
@ -767,7 +727,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);
|
||||
@ -776,8 +735,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);
|
||||
@ -786,8 +743,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);
|
||||
@ -795,8 +750,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);
|
||||
@ -804,7 +757,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);
|
||||
@ -812,8 +764,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);
|
||||
@ -837,16 +787,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[]
|
||||
*/
|
||||
@ -888,10 +836,8 @@ 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);
|
||||
@ -905,8 +851,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);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user