mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-11 12:08:05 +00:00
Compare commits
95 Commits
Author | SHA1 | Date | |
---|---|---|---|
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 |
@ -6,11 +6,10 @@ php:
|
||||
|
||||
before_script:
|
||||
- phpenv config-rm xdebug.ini
|
||||
# - pecl install channel://pecl.php.net/pthreads-3.1.6
|
||||
- echo | pecl install channel://pecl.php.net/yaml-2.0.4
|
||||
- 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
|
||||
|
@ -30,9 +30,9 @@ If you use a custom binary, you'll need to replace `composer` usages in this gui
|
||||
Preprocessor requires that the `cpp` (c preprocessor) is available in your PATH.
|
||||
|
||||
## Building `PocketMine-MP.phar`
|
||||
Run `build/server.phar` using your preferred PHP binary. It'll drop a `PocketMine-MP.phar` into the current working directory.
|
||||
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.
|
||||
Run `src/pocketmine/PocketMine.php` using your preferred PHP binary.
|
||||
|
Submodule build/php updated: e145515864...d475b694e4
@ -9,3 +9,42 @@ Plugin developers should **only** update their required API to this version if y
|
||||
# 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.
|
||||
|
@ -37,10 +37,10 @@
|
||||
"adhocore/json-comment": "^0.1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^0.12.14",
|
||||
"irstea/phpunit-shim": "^8.5",
|
||||
"phpstan/phpstan": "^0.12.25",
|
||||
"phpstan/phpstan-phpunit": "^0.12.6",
|
||||
"phpstan/phpstan-strict-rules": "^0.12.2"
|
||||
"phpstan/phpstan-strict-rules": "^0.12.2",
|
||||
"phpunit/phpunit": "^8.5"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
1556
composer.lock
generated
1556
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,10 @@
|
||||
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
|
||||
@ -12,13 +15,12 @@ includes:
|
||||
- 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
|
||||
- vendor/irstea/phpunit-shim/phpunit
|
||||
paths:
|
||||
- src
|
||||
- build/make-release.php
|
||||
@ -33,158 +35,3 @@ parameters:
|
||||
reportUnmatchedIgnoredErrors: false #no other way to silence platform-specific non-warnings
|
||||
staticReflectionClassNamePatterns:
|
||||
- "#^COM$#"
|
||||
ignoreErrors:
|
||||
-
|
||||
message: "#^Instanceof between pocketmine\\\\plugin\\\\PluginManager and pocketmine\\\\plugin\\\\PluginManager will always evaluate to true\\.$#"
|
||||
count: 1
|
||||
path: src/pocketmine/CrashDump.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\Player\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\entity\\\\Human\\.$#"
|
||||
count: 1
|
||||
path: src/pocketmine/Player.php
|
||||
|
||||
-
|
||||
message: "#^Cannot instantiate interface pocketmine\\\\level\\\\format\\\\io\\\\LevelProvider\\.$#"
|
||||
count: 1
|
||||
path: src/pocketmine/Server.php
|
||||
|
||||
-
|
||||
message: "#^Instanceof between pocketmine\\\\plugin\\\\PluginManager and pocketmine\\\\plugin\\\\PluginManager will always evaluate to true\\.$#"
|
||||
count: 1
|
||||
path: src/pocketmine/Server.php
|
||||
|
||||
-
|
||||
message: "#^Instanceof between pocketmine\\\\scheduler\\\\AsyncPool and pocketmine\\\\scheduler\\\\AsyncPool will always evaluate to true\\.$#"
|
||||
count: 1
|
||||
path: src/pocketmine/Server.php
|
||||
|
||||
-
|
||||
message: "#^Instanceof between pocketmine\\\\command\\\\CommandReader and pocketmine\\\\command\\\\CommandReader will always evaluate to true\\.$#"
|
||||
count: 1
|
||||
path: src/pocketmine/Server.php
|
||||
|
||||
-
|
||||
message: "#^Instanceof between pocketmine\\\\network\\\\Network and pocketmine\\\\network\\\\Network will always evaluate to true\\.$#"
|
||||
count: 1
|
||||
path: src/pocketmine/Server.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\[A-Za-z\\d]+\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
path: src/pocketmine/block
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Block\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\level\\\\Position\\.$#"
|
||||
count: 1
|
||||
path: src/pocketmine/block/Block.php
|
||||
|
||||
-
|
||||
message: "#^Call to an undefined method pocketmine\\\\command\\\\CommandSender\\:\\:teleport\\(\\)\\.$#"
|
||||
count: 1
|
||||
path: src/pocketmine/command/defaults/TeleportCommand.php
|
||||
# comment: "not actually possible, but high cost to fix warning"
|
||||
|
||||
-
|
||||
message: "#^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: "#^pocketmine\\\\inventory\\\\DoubleChestInventory\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\inventory\\\\ChestInventory\\.$#"
|
||||
count: 1
|
||||
path: src/pocketmine/inventory/DoubleChestInventory.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\inventory\\\\EnderChestInventory\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\inventory\\\\ChestInventory\\.$#"
|
||||
count: 1
|
||||
path: src/pocketmine/inventory/EnderChestInventory.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\item\\\\GoldenAppleEnchanted\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\item\\\\GoldenApple\\.$#"
|
||||
count: 1
|
||||
path: src/pocketmine/item/GoldenAppleEnchanted.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\item\\\\WrittenBook\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\item\\\\WritableBook\\.$#"
|
||||
count: 1
|
||||
path: src/pocketmine/item/WrittenBook.php
|
||||
|
||||
-
|
||||
message: "#^Variable property access on \\$this\\(pocketmine\\\\level\\\\generator\\\\PopulationTask\\)\\.$#"
|
||||
count: 4
|
||||
path: src/pocketmine/level/generator/PopulationTask.php
|
||||
|
||||
-
|
||||
message: "#^Constructor of class pocketmine\\\\level\\\\generator\\\\hell\\\\Nether has an unused parameter \\$options\\.$#"
|
||||
count: 1
|
||||
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: "#^Variable method call on pocketmine\\\\event\\\\Listener\\.$#"
|
||||
count: 1
|
||||
path: src/pocketmine/plugin/MethodEventExecutor.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
|
||||
|
||||
|
@ -146,6 +146,7 @@ use pocketmine\network\mcpe\protocol\types\CommandEnum;
|
||||
use pocketmine\network\mcpe\protocol\types\CommandParameter;
|
||||
use pocketmine\network\mcpe\protocol\types\ContainerIds;
|
||||
use pocketmine\network\mcpe\protocol\types\DimensionIds;
|
||||
use pocketmine\network\mcpe\protocol\types\GameMode;
|
||||
use pocketmine\network\mcpe\protocol\types\PersonaPieceTintColor;
|
||||
use pocketmine\network\mcpe\protocol\types\PersonaSkinPiece;
|
||||
use pocketmine\network\mcpe\protocol\types\PlayerPermissions;
|
||||
@ -216,6 +217,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
public const SPECTATOR = 3;
|
||||
public const VIEW = Player::SPECTATOR;
|
||||
|
||||
private const RESOURCE_PACK_CHUNK_SIZE = 128 * 1024; //128KB
|
||||
|
||||
/**
|
||||
* Validates the given username.
|
||||
*/
|
||||
@ -261,6 +264,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
/** @var bool */
|
||||
public $loggedIn = false;
|
||||
|
||||
/** @var bool */
|
||||
private $seenLoginPacket = false;
|
||||
/** @var bool */
|
||||
private $resourcePacksDone = false;
|
||||
|
||||
@ -1331,12 +1336,13 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
* TODO: remove this when Spectator Mode gets added properly to MCPE
|
||||
*/
|
||||
public static function getClientFriendlyGamemode(int $gamemode) : int{
|
||||
$gamemode &= 0x03;
|
||||
if($gamemode === Player::SPECTATOR){
|
||||
return Player::CREATIVE;
|
||||
}
|
||||
|
||||
return $gamemode;
|
||||
static $map = [
|
||||
self::SURVIVAL => GameMode::SURVIVAL,
|
||||
self::CREATIVE => GameMode::CREATIVE,
|
||||
self::ADVENTURE => GameMode::ADVENTURE,
|
||||
self::SPECTATOR => GameMode::CREATIVE
|
||||
];
|
||||
return $map[$gamemode & 0x3];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1816,9 +1822,10 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
}
|
||||
|
||||
public function handleLogin(LoginPacket $packet) : bool{
|
||||
if($this->loggedIn){
|
||||
if($this->seenLoginPacket){
|
||||
return false;
|
||||
}
|
||||
$this->seenLoginPacket = true;
|
||||
|
||||
if($packet->protocol !== ProtocolInfo::CURRENT_PROTOCOL){
|
||||
if($packet->protocol < ProtocolInfo::CURRENT_PROTOCOL){
|
||||
@ -2065,7 +2072,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
|
||||
$pk = new ResourcePackDataInfoPacket();
|
||||
$pk->packId = $pack->getPackId();
|
||||
$pk->maxChunkSize = 1048576; //1MB
|
||||
$pk->maxChunkSize = self::RESOURCE_PACK_CHUNK_SIZE;
|
||||
$pk->chunkCount = (int) ceil($pack->getPackSize() / $pk->maxChunkSize);
|
||||
$pk->compressedPackSize = $pack->getPackSize();
|
||||
$pk->sha256 = $pack->getSha256();
|
||||
@ -2231,7 +2238,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
}
|
||||
|
||||
public function handleMovePlayer(MovePlayerPacket $packet) : bool{
|
||||
$newPos = $packet->position->subtract(0, $this->baseOffset, 0);
|
||||
$newPos = $packet->position->round(4)->subtract(0, $this->baseOffset, 0);
|
||||
|
||||
if($this->isTeleporting and $newPos->distanceSquared($this) > 1){ //Tolerate up to 1 block to avoid problems with client-sided physics when spawning in blocks
|
||||
$this->sendPosition($this, null, null, MovePlayerPacket::MODE_RESET);
|
||||
@ -2300,11 +2307,6 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
return false;
|
||||
}
|
||||
|
||||
if($this->isSpectator()){
|
||||
$this->sendAllInventories();
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @var InventoryAction[] $actions */
|
||||
$actions = [];
|
||||
foreach($packet->actions as $networkInventoryAction){
|
||||
@ -2398,7 +2400,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
|
||||
$this->setUsingItem(false);
|
||||
|
||||
if(!$this->canInteract($blockVector->add(0.5, 0.5, 0.5), 13) or $this->isSpectator()){
|
||||
if(!$this->canInteract($blockVector->add(0.5, 0.5, 0.5), 13)){
|
||||
}elseif($this->isCreative()){
|
||||
$item = $this->inventory->getItemInHand();
|
||||
if($this->level->useItemOn($blockVector, $item, $face, $packet->trData->clickPos, $this, true)){
|
||||
@ -2504,7 +2506,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
}
|
||||
|
||||
$ev = new PlayerInteractEvent($this, $item, null, $directionVector, $face, PlayerInteractEvent::RIGHT_CLICK_AIR);
|
||||
if($this->hasItemCooldown($item)){
|
||||
if($this->hasItemCooldown($item) or $this->isSpectator()){
|
||||
$ev->setCancelled();
|
||||
}
|
||||
|
||||
@ -2555,7 +2557,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
$heldItem = $this->inventory->getItemInHand();
|
||||
$oldItem = clone $heldItem;
|
||||
|
||||
if(!$this->canInteract($target, 8)){
|
||||
if(!$this->canInteract($target, 8) or $this->isSpectator()){
|
||||
$cancelled = true;
|
||||
}elseif($target instanceof Player){
|
||||
if(!$this->server->getConfigBool("pvp")){
|
||||
@ -3053,8 +3055,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
$pk = new ResourcePackChunkDataPacket();
|
||||
$pk->packId = $pack->getPackId();
|
||||
$pk->chunkIndex = $packet->chunkIndex;
|
||||
$pk->data = $pack->getPackChunk(1048576 * $packet->chunkIndex, 1048576);
|
||||
$pk->progress = (1048576 * $packet->chunkIndex);
|
||||
$pk->data = $pack->getPackChunk(self::RESOURCE_PACK_CHUNK_SIZE * $packet->chunkIndex, self::RESOURCE_PACK_CHUNK_SIZE);
|
||||
$pk->progress = (self::RESOURCE_PACK_CHUNK_SIZE * $packet->chunkIndex);
|
||||
$this->dataPacket($pk);
|
||||
return true;
|
||||
}
|
||||
@ -3075,14 +3077,26 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
$modifiedPages[] = $packet->pageNumber;
|
||||
break;
|
||||
case BookEditPacket::TYPE_ADD_PAGE:
|
||||
if(!$newBook->pageExists($packet->pageNumber)){
|
||||
//this may only come before a page which already exists
|
||||
//TODO: the client can send insert-before actions on trailing client-side pages which cause odd behaviour on the server
|
||||
return false;
|
||||
}
|
||||
$newBook->insertPage($packet->pageNumber, $packet->text);
|
||||
$modifiedPages[] = $packet->pageNumber;
|
||||
break;
|
||||
case BookEditPacket::TYPE_DELETE_PAGE:
|
||||
if(!$newBook->pageExists($packet->pageNumber)){
|
||||
return false;
|
||||
}
|
||||
$newBook->deletePage($packet->pageNumber);
|
||||
$modifiedPages[] = $packet->pageNumber;
|
||||
break;
|
||||
case BookEditPacket::TYPE_SWAP_PAGES:
|
||||
if(!$newBook->pageExists($packet->pageNumber) or !$newBook->pageExists($packet->secondaryPageNumber)){
|
||||
//the client will create pages on its own without telling us until it tries to switch them
|
||||
$newBook->addPage(max($packet->pageNumber, $packet->secondaryPageNumber));
|
||||
}
|
||||
$newBook->swapPages($packet->pageNumber, $packet->secondaryPageNumber);
|
||||
$modifiedPages = [$packet->pageNumber, $packet->secondaryPageNumber];
|
||||
break;
|
||||
@ -3738,6 +3752,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
$pk->headYaw = $yaw;
|
||||
$pk->yaw = $yaw;
|
||||
$pk->mode = $mode;
|
||||
$pk->onGround = $this->onGround;
|
||||
|
||||
if($targets !== null){
|
||||
$this->server->broadcastPacket($targets, $pk);
|
||||
|
@ -177,15 +177,14 @@ namespace pocketmine {
|
||||
}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']);
|
||||
|
||||
|
@ -1396,7 +1396,7 @@ class Server{
|
||||
Network::$BATCH_THRESHOLD = -1;
|
||||
}
|
||||
|
||||
$this->networkCompressionLevel = $this->getProperty("network.compression-level", 7);
|
||||
$this->networkCompressionLevel = (int) $this->getProperty("network.compression-level", 7);
|
||||
if($this->networkCompressionLevel < 1 or $this->networkCompressionLevel > 9){
|
||||
$this->logger->warning("Invalid network compression level $this->networkCompressionLevel set, setting to default 7");
|
||||
$this->networkCompressionLevel = 7;
|
||||
|
@ -33,6 +33,6 @@ if(defined('pocketmine\_VERSION_INFO_INCLUDED')){
|
||||
const _VERSION_INFO_INCLUDED = true;
|
||||
|
||||
const NAME = "PocketMine-MP";
|
||||
const BASE_VERSION = "3.12.0";
|
||||
const BASE_VERSION = "3.12.4";
|
||||
const IS_DEVELOPMENT_BUILD = false;
|
||||
const BUILD_NUMBER = 0;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -124,4 +124,12 @@ class DoublePlant extends Flowable{
|
||||
|
||||
return parent::getAffectedBlocks();
|
||||
}
|
||||
|
||||
public function getFlameEncouragement() : int{
|
||||
return 60;
|
||||
}
|
||||
|
||||
public function getFlammability() : int{
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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{
|
||||
|
@ -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;
|
||||
@ -204,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){
|
||||
|
@ -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,8 +311,12 @@ 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
|
||||
@ -1164,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);
|
||||
}
|
||||
@ -1927,7 +1934,12 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -436,6 +436,9 @@ abstract class Living extends Entity implements Damageable{
|
||||
* to effects or armour.
|
||||
*/
|
||||
public function applyDamageModifiers(EntityDamageEvent $source) : void{
|
||||
if($this->lastDamageCause !== null and $this->attackTime > 0){
|
||||
$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);
|
||||
@ -514,11 +517,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 (
|
||||
@ -550,20 +548,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());
|
||||
|
@ -111,7 +111,7 @@ class FallingBlock extends Entity{
|
||||
$this->flagForDespawn();
|
||||
|
||||
$block = $this->level->getBlock($pos);
|
||||
if(($block->isTransparent() and !$block->canBeReplaced()) or ($this->onGround and abs($this->y - $this->getFloorY()) > 0.001)){
|
||||
if(!$block->canBeReplaced() or ($this->onGround and abs($this->y - $this->getFloorY()) > 0.001)){
|
||||
//FIXME: anvils are supposed to destroy torches
|
||||
$this->getLevel()->dropItem($this, ItemFactory::get($this->getBlock(), $this->getDamage()));
|
||||
}else{
|
||||
|
@ -26,6 +26,7 @@ namespace pocketmine\event\entity;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\event\Cancellable;
|
||||
use function array_sum;
|
||||
use function max;
|
||||
|
||||
/**
|
||||
* Called when an entity takes damage.
|
||||
@ -40,6 +41,7 @@ class EntityDamageEvent extends EntityEvent implements Cancellable{
|
||||
public const MODIFIER_CRITICAL = 7;
|
||||
public const MODIFIER_TOTEM = 8;
|
||||
public const MODIFIER_WEAPON_ENCHANTMENTS = 9;
|
||||
public const MODIFIER_PREVIOUS_DAMAGE_COOLDOWN = 10;
|
||||
|
||||
public const CAUSE_CONTACT = 0;
|
||||
public const CAUSE_ENTITY_ATTACK = 1;
|
||||
@ -143,7 +145,7 @@ class EntityDamageEvent extends EntityEvent implements Cancellable{
|
||||
}
|
||||
|
||||
public function getFinalDamage() : float{
|
||||
return $this->baseDamage + array_sum($this->modifiers);
|
||||
return max(0, $this->baseDamage + array_sum($this->modifiers));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -24,7 +24,6 @@ declare(strict_types=1);
|
||||
namespace pocketmine\event\player;
|
||||
|
||||
use pocketmine\lang\TextContainer;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\Player;
|
||||
|
||||
/**
|
||||
|
@ -293,7 +293,12 @@ class InventoryTransaction{
|
||||
|
||||
$this->shuffleActions();
|
||||
|
||||
$this->validate();
|
||||
try{
|
||||
$this->validate();
|
||||
}catch(TransactionValidationException $e){
|
||||
$this->sendInventories();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
if(!$this->callExecuteEvent()){
|
||||
$this->sendInventories();
|
||||
|
@ -59,7 +59,6 @@ class Bow extends Tool{
|
||||
($player->yaw > 180 ? 360 : 0) - $player->yaw,
|
||||
-$player->pitch
|
||||
);
|
||||
$nbt->setShort("Fire", $player->isOnFire() ? 45 * 60 : 0);
|
||||
|
||||
$diff = $player->getItemUseDuration();
|
||||
$p = $diff / 20;
|
||||
@ -84,7 +83,7 @@ class Bow extends Tool{
|
||||
}
|
||||
$ev = new EntityShootBowEvent($player, $this, $entity, $baseForce * 3);
|
||||
|
||||
if($baseForce < 0.1 or $diff < 5){
|
||||
if($baseForce < 0.1 or $diff < 5 or $player->isSpectator()){
|
||||
$ev->setCancelled();
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ class WritableBook extends Item{
|
||||
*/
|
||||
public function getPageText(int $pageId) : ?string{
|
||||
$pages = $this->getNamedTag()->getListTag(self::TAG_PAGES);
|
||||
if($pages === null){
|
||||
if($pages === null or !$pages->isset($pageId)){
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -1856,17 +1856,17 @@ class Level implements ChunkManager, Metadatable{
|
||||
|
||||
if($player !== null){
|
||||
$ev = new PlayerInteractEvent($player, $item, $blockClicked, $clickVector, $face, PlayerInteractEvent::RIGHT_CLICK_BLOCK);
|
||||
if($this->checkSpawnProtection($player, $blockClicked)){
|
||||
if($this->checkSpawnProtection($player, $blockClicked) or $player->isSpectator()){
|
||||
$ev->setCancelled(); //set it to cancelled so plugins can bypass this
|
||||
}
|
||||
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
if(!$player->isSneaking() and $blockClicked->onActivate($item, $player)){
|
||||
if((!$player->isSneaking() or $item->isNull()) and $blockClicked->onActivate($item, $player)){
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!$player->isSneaking() and $item->onActivate($player, $blockReplace, $blockClicked, $face, $clickVector)){
|
||||
if($item->onActivate($player, $blockReplace, $blockClicked, $face, $clickVector)){
|
||||
return true;
|
||||
}
|
||||
}else{
|
||||
@ -1909,7 +1909,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
|
||||
if($player !== null){
|
||||
$ev = new BlockPlaceEvent($player, $hand, $blockReplace, $blockClicked, $item);
|
||||
if($this->checkSpawnProtection($player, $blockClicked)){
|
||||
if($this->checkSpawnProtection($player, $blockReplace) or $player->isSpectator()){
|
||||
$ev->setCancelled();
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ use function file_exists;
|
||||
use function file_get_contents;
|
||||
use function file_put_contents;
|
||||
use function mkdir;
|
||||
use function zlib_decode;
|
||||
|
||||
abstract class BaseLevelProvider implements LevelProvider{
|
||||
/** @var string */
|
||||
@ -53,8 +54,20 @@ abstract class BaseLevelProvider implements LevelProvider{
|
||||
}
|
||||
|
||||
protected function loadLevelData() : void{
|
||||
$compressedLevelData = @file_get_contents($this->getPath() . "level.dat");
|
||||
if($compressedLevelData === false){
|
||||
throw new LevelException("Failed to read level.dat (permission denied or doesn't exist)");
|
||||
}
|
||||
$rawLevelData = @zlib_decode($compressedLevelData);
|
||||
if($rawLevelData === false){
|
||||
throw new LevelException("Failed to decompress level.dat contents (probably corrupted)");
|
||||
}
|
||||
$nbt = new BigEndianNBTStream();
|
||||
$levelData = $nbt->readCompressed(file_get_contents($this->getPath() . "level.dat"));
|
||||
try{
|
||||
$levelData = $nbt->read($rawLevelData);
|
||||
}catch(\UnexpectedValueException $e){
|
||||
throw new LevelException("Failed to decode level.dat (" . $e->getMessage() . ")", 0, $e);
|
||||
}
|
||||
|
||||
if(!($levelData instanceof CompoundTag) or !$levelData->hasTag("Data", CompoundTag::class)){
|
||||
throw new LevelException("Invalid level.dat");
|
||||
|
@ -32,7 +32,7 @@ use pocketmine\utils\Random;
|
||||
abstract class Populator{
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @return void
|
||||
*/
|
||||
abstract public function populate(ChunkManager $level, int $chunkX, int $chunkZ, Random $random);
|
||||
}
|
||||
|
@ -34,17 +34,26 @@ abstract class LightUpdate{
|
||||
/** @var ChunkManager */
|
||||
protected $level;
|
||||
|
||||
/** @var int[][] blockhash => [x, y, z, new light level] */
|
||||
/**
|
||||
* @var int[][] blockhash => [x, y, z, new light level]
|
||||
* @phpstan-var array<int, array{int, int, int, int}>
|
||||
*/
|
||||
protected $updateNodes = [];
|
||||
|
||||
/** @var \SplQueue */
|
||||
protected $spreadQueue;
|
||||
/** @var bool[] */
|
||||
/**
|
||||
* @var true[]
|
||||
* @phpstan-var array<int, true>
|
||||
*/
|
||||
protected $spreadVisited = [];
|
||||
|
||||
/** @var \SplQueue */
|
||||
protected $removalQueue;
|
||||
/** @var bool[] */
|
||||
/**
|
||||
* @var true[]
|
||||
* @phpstan-var array<int, true>
|
||||
*/
|
||||
protected $removalVisited = [];
|
||||
/** @var SubChunkIteratorManager */
|
||||
protected $subChunkHandler;
|
||||
|
@ -37,6 +37,7 @@ use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\network\mcpe\protocol\types\CommandOriginData;
|
||||
use pocketmine\network\mcpe\protocol\types\EntityLink;
|
||||
use pocketmine\network\mcpe\protocol\types\GameRuleType;
|
||||
use pocketmine\network\mcpe\protocol\types\PersonaPieceTintColor;
|
||||
use pocketmine\network\mcpe\protocol\types\PersonaSkinPiece;
|
||||
use pocketmine\network\mcpe\protocol\types\SkinAnimation;
|
||||
@ -546,9 +547,9 @@ class NetworkBinaryStream extends BinaryStream{
|
||||
*/
|
||||
public function getVector3() : Vector3{
|
||||
return new Vector3(
|
||||
$this->getRoundedLFloat(4),
|
||||
$this->getRoundedLFloat(4),
|
||||
$this->getRoundedLFloat(4)
|
||||
$this->getLFloat(),
|
||||
$this->getLFloat(),
|
||||
$this->getLFloat()
|
||||
);
|
||||
}
|
||||
|
||||
@ -602,13 +603,13 @@ class NetworkBinaryStream extends BinaryStream{
|
||||
$type = $this->getUnsignedVarInt();
|
||||
$value = null;
|
||||
switch($type){
|
||||
case 1:
|
||||
case GameRuleType::BOOL:
|
||||
$value = $this->getBool();
|
||||
break;
|
||||
case 2:
|
||||
case GameRuleType::INT:
|
||||
$value = $this->getUnsignedVarInt();
|
||||
break;
|
||||
case 3:
|
||||
case GameRuleType::FLOAT:
|
||||
$value = $this->getLFloat();
|
||||
break;
|
||||
}
|
||||
@ -632,13 +633,13 @@ class NetworkBinaryStream extends BinaryStream{
|
||||
$this->putString($name);
|
||||
$this->putUnsignedVarInt($rule[0]);
|
||||
switch($rule[0]){
|
||||
case 1:
|
||||
case GameRuleType::BOOL:
|
||||
$this->putBool($rule[1]);
|
||||
break;
|
||||
case 2:
|
||||
case GameRuleType::INT:
|
||||
$this->putUnsignedVarInt($rule[1]);
|
||||
break;
|
||||
case 3:
|
||||
case GameRuleType::FLOAT:
|
||||
$this->putLFloat($rule[1]);
|
||||
break;
|
||||
}
|
||||
@ -671,7 +672,7 @@ class NetworkBinaryStream extends BinaryStream{
|
||||
$result->requestId = $this->getString();
|
||||
|
||||
if($result->type === CommandOriginData::ORIGIN_DEV_CONSOLE or $result->type === CommandOriginData::ORIGIN_TEST){
|
||||
$result->varlong1 = $this->getVarLong();
|
||||
$result->playerEntityUniqueId = $this->getVarLong();
|
||||
}
|
||||
|
||||
return $result;
|
||||
@ -683,7 +684,7 @@ class NetworkBinaryStream extends BinaryStream{
|
||||
$this->putString($data->requestId);
|
||||
|
||||
if($data->type === CommandOriginData::ORIGIN_DEV_CONSOLE or $data->type === CommandOriginData::ORIGIN_TEST){
|
||||
$this->putVarLong($data->varlong1);
|
||||
$this->putVarLong($data->playerEntityUniqueId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,9 +27,9 @@ use pocketmine\network\mcpe\protocol\LoginPacket;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\scheduler\AsyncTask;
|
||||
use pocketmine\Server;
|
||||
use function assert;
|
||||
use function base64_decode;
|
||||
use function chr;
|
||||
use function count;
|
||||
use function explode;
|
||||
use function json_decode;
|
||||
use function ltrim;
|
||||
@ -94,7 +94,11 @@ class VerifyLoginTask extends AsyncTask{
|
||||
* @throws VerifyLoginException if errors are encountered
|
||||
*/
|
||||
private function validateToken(string $jwt, ?string &$currentPublicKey, bool $first = false) : void{
|
||||
[$headB64, $payloadB64, $sigB64] = explode('.', $jwt);
|
||||
$rawParts = explode('.', $jwt);
|
||||
if(count($rawParts) !== 3){
|
||||
throw new VerifyLoginException("Wrong number of JWT parts, expected 3, got " . count($rawParts));
|
||||
}
|
||||
[$headB64, $payloadB64, $sigB64] = $rawParts;
|
||||
|
||||
$headers = json_decode(base64_decode(strtr($headB64, '-_', '+/'), true), true);
|
||||
|
||||
@ -111,7 +115,9 @@ class VerifyLoginTask extends AsyncTask{
|
||||
|
||||
//OpenSSL wants a DER-encoded signature, so we extract R and S from the plain signature and crudely serialize it.
|
||||
|
||||
assert(strlen($plainSignature) === 96);
|
||||
if(strlen($plainSignature) !== 96){
|
||||
throw new VerifyLoginException("Wrong signature length, expected 96, got " . strlen($plainSignature));
|
||||
}
|
||||
|
||||
[$rString, $sString] = str_split($plainSignature, 48);
|
||||
|
||||
|
@ -28,6 +28,7 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
use pocketmine\network\mcpe\protocol\types\DeviceOS;
|
||||
use pocketmine\network\mcpe\protocol\types\EntityLink;
|
||||
use pocketmine\utils\UUID;
|
||||
use function count;
|
||||
@ -84,7 +85,7 @@ class AddPlayerPacket extends DataPacket{
|
||||
/** @var string */
|
||||
public $deviceId = ""; //TODO: fill player's device ID (???)
|
||||
/** @var int */
|
||||
public $buildPlatform = -1;
|
||||
public $buildPlatform = DeviceOS::UNKNOWN;
|
||||
|
||||
protected function decodePayload(){
|
||||
$this->uuid = $this->getUUID();
|
||||
|
@ -35,8 +35,6 @@ use function json_decode;
|
||||
class LoginPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::LOGIN_PACKET;
|
||||
|
||||
public const EDITION_POCKET = 0;
|
||||
|
||||
/** @var string */
|
||||
public $username;
|
||||
/** @var int */
|
||||
|
@ -33,6 +33,7 @@ class MoveActorAbsolutePacket extends DataPacket{
|
||||
|
||||
public const FLAG_GROUND = 0x01;
|
||||
public const FLAG_TELEPORT = 0x02;
|
||||
public const FLAG_FORCE_MOVE_LOCAL_ENTITY = 0x04;
|
||||
|
||||
/** @var int */
|
||||
public $entityRuntimeId;
|
||||
|
@ -36,6 +36,9 @@ class MoveActorDeltaPacket extends DataPacket{
|
||||
public const FLAG_HAS_ROT_X = 0x08;
|
||||
public const FLAG_HAS_ROT_Y = 0x10;
|
||||
public const FLAG_HAS_ROT_Z = 0x20;
|
||||
public const FLAG_GROUND = 0x40;
|
||||
public const FLAG_TELEPORT = 0x80;
|
||||
public const FLAG_FORCE_MOVE_LOCAL_ENTITY = 0x100;
|
||||
|
||||
/** @var int */
|
||||
public $entityRuntimeId;
|
||||
|
@ -30,6 +30,13 @@ use pocketmine\network\mcpe\NetworkSession;
|
||||
class NpcRequestPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::NPC_REQUEST_PACKET;
|
||||
|
||||
public const REQUEST_SET_ACTIONS = 0;
|
||||
public const REQUEST_EXECUTE_ACTION = 1;
|
||||
public const REQUEST_EXECUTE_CLOSING_COMMANDS = 2;
|
||||
public const REQUEST_SET_NAME = 3;
|
||||
public const REQUEST_SET_SKIN = 4;
|
||||
public const REQUEST_SET_INTERACTION_TEXT = 5;
|
||||
|
||||
/** @var int */
|
||||
public $entityRuntimeId;
|
||||
/** @var int */
|
||||
|
@ -49,7 +49,7 @@ class PlayerActionPacket extends DataPacket{
|
||||
public const ACTION_STOP_GLIDE = 16;
|
||||
public const ACTION_BUILD_DENIED = 17;
|
||||
public const ACTION_CONTINUE_BREAK = 18;
|
||||
|
||||
public const ACTION_CHANGE_SKIN = 19;
|
||||
public const ACTION_SET_ENCHANTMENT_SEED = 20;
|
||||
public const ACTION_START_SWIMMING = 21;
|
||||
public const ACTION_STOP_SWIMMING = 22;
|
||||
|
@ -32,6 +32,7 @@ class SimpleEventPacket extends DataPacket{
|
||||
|
||||
public const TYPE_ENABLE_COMMANDS = 1;
|
||||
public const TYPE_DISABLE_COMMANDS = 2;
|
||||
public const TYPE_UNLOCK_WORLD_TEMPLATE_SETTINGS = 3;
|
||||
|
||||
/** @var int */
|
||||
public $eventType;
|
||||
|
@ -30,6 +30,10 @@ use pocketmine\nbt\NetworkLittleEndianNBTStream;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
use pocketmine\network\mcpe\NetworkBinaryStream;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
use pocketmine\network\mcpe\protocol\types\EducationEditionOffer;
|
||||
use pocketmine\network\mcpe\protocol\types\GameRuleType;
|
||||
use pocketmine\network\mcpe\protocol\types\GeneratorType;
|
||||
use pocketmine\network\mcpe\protocol\types\MultiplayerGameVisibility;
|
||||
use pocketmine\network\mcpe\protocol\types\PlayerPermissions;
|
||||
use pocketmine\network\mcpe\protocol\types\RuntimeBlockMapping;
|
||||
use function count;
|
||||
@ -65,7 +69,7 @@ class StartGamePacket extends DataPacket{
|
||||
/** @var int */
|
||||
public $dimension;
|
||||
/** @var int */
|
||||
public $generator = 1; //default infinite - 0 old, 1 infinite, 2 flat
|
||||
public $generator = GeneratorType::OVERWORLD;
|
||||
/** @var int */
|
||||
public $worldGamemode;
|
||||
/** @var int */
|
||||
@ -81,7 +85,7 @@ class StartGamePacket extends DataPacket{
|
||||
/** @var int */
|
||||
public $time = -1;
|
||||
/** @var int */
|
||||
public $eduEditionOffer = 0;
|
||||
public $eduEditionOffer = EducationEditionOffer::NONE;
|
||||
/** @var bool */
|
||||
public $hasEduFeaturesEnabled = false;
|
||||
/** @var float */
|
||||
@ -95,9 +99,9 @@ class StartGamePacket extends DataPacket{
|
||||
/** @var bool */
|
||||
public $hasLANBroadcast = true;
|
||||
/** @var int */
|
||||
public $xboxLiveBroadcastMode = 0; //TODO: find values
|
||||
public $xboxLiveBroadcastMode = MultiplayerGameVisibility::PUBLIC;
|
||||
/** @var int */
|
||||
public $platformBroadcastMode = 0;
|
||||
public $platformBroadcastMode = MultiplayerGameVisibility::PUBLIC;
|
||||
/** @var bool */
|
||||
public $commandsEnabled;
|
||||
/** @var bool */
|
||||
@ -107,7 +111,7 @@ class StartGamePacket extends DataPacket{
|
||||
* @phpstan-var array<string, array{0: int, 1: bool|int|float}>
|
||||
*/
|
||||
public $gameRules = [ //TODO: implement this
|
||||
"naturalregeneration" => [1, false] //Hack for client side regeneration
|
||||
"naturalregeneration" => [GameRuleType::BOOL, false] //Hack for client side regeneration
|
||||
];
|
||||
/** @var bool */
|
||||
public $hasBonusChestEnabled = false;
|
||||
|
@ -30,21 +30,25 @@ use pocketmine\network\mcpe\NetworkSession;
|
||||
class UpdateBlockSyncedPacket extends UpdateBlockPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::UPDATE_BLOCK_SYNCED_PACKET;
|
||||
|
||||
public const TYPE_NONE = 0;
|
||||
public const TYPE_CREATE = 1;
|
||||
public const TYPE_DESTROY = 2;
|
||||
|
||||
/** @var int */
|
||||
public $entityUniqueId = 0;
|
||||
public $entityUniqueId;
|
||||
/** @var int */
|
||||
public $uvarint64_2 = 0;
|
||||
public $updateType;
|
||||
|
||||
protected function decodePayload(){
|
||||
parent::decodePayload();
|
||||
$this->entityUniqueId = $this->getUnsignedVarLong();
|
||||
$this->uvarint64_2 = $this->getUnsignedVarLong();
|
||||
$this->updateType = $this->getUnsignedVarLong();
|
||||
}
|
||||
|
||||
protected function encodePayload(){
|
||||
parent::encodePayload();
|
||||
$this->putUnsignedVarLong($this->entityUniqueId);
|
||||
$this->putUnsignedVarLong($this->uvarint64_2);
|
||||
$this->putUnsignedVarLong($this->updateType);
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
|
@ -48,5 +48,5 @@ class CommandOriginData{
|
||||
public $requestId;
|
||||
|
||||
/** @var int */
|
||||
public $varlong1;
|
||||
public $playerEntityUniqueId;
|
||||
}
|
||||
|
44
src/pocketmine/network/mcpe/protocol/types/DeviceOS.php
Normal file
44
src/pocketmine/network/mcpe/protocol/types/DeviceOS.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\network\mcpe\protocol\types;
|
||||
|
||||
final class DeviceOS{
|
||||
|
||||
public const UNKNOWN = -1;
|
||||
public const ANDROID = 1;
|
||||
public const IOS = 2;
|
||||
public const OSX = 3;
|
||||
public const AMAZON = 4;
|
||||
public const GEAR_VR = 5;
|
||||
public const HOLOLENS = 6;
|
||||
public const WINDOWS_10 = 7;
|
||||
public const WIN32 = 8;
|
||||
public const DEDICATED = 9;
|
||||
public const TVOS = 10;
|
||||
public const PLAYSTATION = 11;
|
||||
public const NINTENDO = 12;
|
||||
public const XBOX = 13;
|
||||
public const WINDOWS_PHONE = 14;
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\network\mcpe\protocol\types;
|
||||
|
||||
final class EducationEditionOffer{
|
||||
|
||||
private function __construct(){
|
||||
//NOOP
|
||||
}
|
||||
|
||||
public const NONE = 0;
|
||||
public const EVERYWHERE_EXCEPT_CHINA = 1;
|
||||
public const CHINA = 2;
|
||||
}
|
38
src/pocketmine/network/mcpe/protocol/types/GameMode.php
Normal file
38
src/pocketmine/network/mcpe/protocol/types/GameMode.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\network\mcpe\protocol\types;
|
||||
|
||||
final class GameMode{
|
||||
|
||||
private function __construct(){
|
||||
//NOOP
|
||||
}
|
||||
|
||||
public const SURVIVAL = 0;
|
||||
public const CREATIVE = 1;
|
||||
public const ADVENTURE = 2;
|
||||
public const SURVIVAL_VIEWER = 3;
|
||||
public const CREATIVE_VIEWER = 4;
|
||||
public const DEFAULT = 5;
|
||||
}
|
35
src/pocketmine/network/mcpe/protocol/types/GameRuleType.php
Normal file
35
src/pocketmine/network/mcpe/protocol/types/GameRuleType.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\network\mcpe\protocol\types;
|
||||
|
||||
final class GameRuleType{
|
||||
|
||||
private function __construct(){
|
||||
//NOOP
|
||||
}
|
||||
|
||||
public const BOOL = 1;
|
||||
public const INT = 2;
|
||||
public const FLOAT = 3;
|
||||
}
|
37
src/pocketmine/network/mcpe/protocol/types/GeneratorType.php
Normal file
37
src/pocketmine/network/mcpe/protocol/types/GeneratorType.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\network\mcpe\protocol\types;
|
||||
|
||||
final class GeneratorType{
|
||||
|
||||
private function __construct(){
|
||||
//NOOP
|
||||
}
|
||||
|
||||
public const FINITE_OVERWORLD = 0;
|
||||
public const OVERWORLD = 1;
|
||||
public const FLAT = 2;
|
||||
public const NETHER = 3;
|
||||
public const THE_END = 4;
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\network\mcpe\protocol\types;
|
||||
|
||||
final class MultiplayerGameVisibility{
|
||||
|
||||
private function __construct(){
|
||||
//NOOP
|
||||
}
|
||||
|
||||
public const NONE = 0;
|
||||
public const INVITE = 1;
|
||||
public const FRIENDS = 2;
|
||||
public const FRIENDS_OF_FRIENDS = 3;
|
||||
public const PUBLIC = 4;
|
||||
}
|
@ -40,7 +40,7 @@ class PlayerListEntry{
|
||||
/** @var string */
|
||||
public $platformChatId = "";
|
||||
/** @var int */
|
||||
public $buildPlatform = -1;
|
||||
public $buildPlatform = DeviceOS::UNKNOWN;
|
||||
/** @var bool */
|
||||
public $isTeacher = false;
|
||||
/** @var bool */
|
||||
|
@ -49,11 +49,11 @@ class SkinImage{
|
||||
public static function fromLegacy(string $data) : SkinImage{
|
||||
switch(strlen($data)){
|
||||
case 64 * 32 * 4:
|
||||
return new self(64, 32, $data);
|
||||
return new self(32, 64, $data);
|
||||
case 64 * 64 * 4:
|
||||
return new self(64, 64, $data);
|
||||
case 128 * 64 * 4:
|
||||
return new self(128, 64, $data);
|
||||
return new self(64, 128, $data);
|
||||
case 128 * 128 * 4:
|
||||
return new self(128, 128, $data);
|
||||
}
|
||||
|
34
src/pocketmine/network/mcpe/protocol/types/UIProfile.php
Normal file
34
src/pocketmine/network/mcpe/protocol/types/UIProfile.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\network\mcpe\protocol\types;
|
||||
|
||||
final class UIProfile{
|
||||
|
||||
private function __construct(){
|
||||
//NOOP
|
||||
}
|
||||
|
||||
public const CLASSIC = 0;
|
||||
public const POCKET = 1;
|
||||
}
|
@ -116,7 +116,7 @@ class PermissionManager{
|
||||
$this->defaultPerms[$permission->getName()] = $permission;
|
||||
$this->dirtyPermissibles(false);
|
||||
}
|
||||
Timings::$permissionDefaultTimer->startTiming();
|
||||
Timings::$permissionDefaultTimer->stopTiming();
|
||||
}
|
||||
|
||||
private function dirtyPermissibles(bool $op) : void{
|
||||
|
@ -78,8 +78,8 @@ abstract class PluginBase implements Plugin{
|
||||
$this->loader = $loader;
|
||||
$this->server = $server;
|
||||
$this->description = $description;
|
||||
$this->dataFolder = rtrim($dataFolder, "\\/") . "/";
|
||||
$this->file = rtrim($file, "\\/") . "/";
|
||||
$this->dataFolder = rtrim($dataFolder, "/" . DIRECTORY_SEPARATOR) . "/";
|
||||
$this->file = rtrim($file, "/" . DIRECTORY_SEPARATOR) . "/";
|
||||
$this->configFile = $this->dataFolder . "config.yml";
|
||||
$this->logger = new PluginLogger($this);
|
||||
$this->scheduler = new TaskScheduler($this->logger, $this->getFullName());
|
||||
@ -169,7 +169,7 @@ abstract class PluginBase implements Plugin{
|
||||
* @return null|resource Resource data, or null
|
||||
*/
|
||||
public function getResource(string $filename){
|
||||
$filename = rtrim(str_replace("\\", "/", $filename), "/");
|
||||
$filename = rtrim(str_replace(DIRECTORY_SEPARATOR, "/", $filename), "/");
|
||||
if(file_exists($this->file . "resources/" . $filename)){
|
||||
return fopen($this->file . "resources/" . $filename, "rb");
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\resourcepacks;
|
||||
|
||||
use Ahc\Json\Comment as CommentedJsonDecoder;
|
||||
use function assert;
|
||||
use function count;
|
||||
use function fclose;
|
||||
use function feof;
|
||||
@ -35,6 +36,8 @@ use function fseek;
|
||||
use function gettype;
|
||||
use function hash_file;
|
||||
use function implode;
|
||||
use function preg_match;
|
||||
use function strlen;
|
||||
|
||||
class ZippedResourcePack implements ResourcePack{
|
||||
|
||||
@ -85,7 +88,22 @@ class ZippedResourcePack implements ResourcePack{
|
||||
}
|
||||
|
||||
if(($manifestData = $archive->getFromName("manifest.json")) === false){
|
||||
if($archive->locateName("pack_manifest.json") !== false){
|
||||
$manifestPath = null;
|
||||
$manifestIdx = null;
|
||||
for($i = 0; $i < $archive->numFiles; ++$i){
|
||||
$name = $archive->getNameIndex($i);
|
||||
if(
|
||||
($manifestPath === null or strlen($name) < strlen($manifestPath)) and
|
||||
preg_match('#.*/manifest.json$#', $name) === 1
|
||||
){
|
||||
$manifestPath = $name;
|
||||
$manifestIdx = $i;
|
||||
}
|
||||
}
|
||||
if($manifestIdx !== null){
|
||||
$manifestData = $archive->getFromIndex($manifestIdx);
|
||||
assert($manifestData !== false);
|
||||
}elseif($archive->locateName("pack_manifest.json") !== false){
|
||||
throw new ResourcePackException("Unsupported old pack format");
|
||||
}else{
|
||||
throw new ResourcePackException("manifest.json not found in the archive root");
|
||||
|
@ -130,7 +130,7 @@ chunk-ticking:
|
||||
|
||||
chunk-generation:
|
||||
#Max. amount of chunks in the waiting queue to be populated
|
||||
population-queue-size: 8
|
||||
population-queue-size: 32
|
||||
|
||||
ticks-per:
|
||||
autosave: 6000
|
||||
|
@ -36,7 +36,7 @@ class TaskScheduler{
|
||||
/** @var bool */
|
||||
private $enabled = true;
|
||||
|
||||
/** @var ReversePriorityQueue<Task> */
|
||||
/** @var ReversePriorityQueue<TaskHandler> */
|
||||
protected $queue;
|
||||
|
||||
/** @var TaskHandler[] */
|
||||
|
@ -94,8 +94,7 @@ class Random{
|
||||
$this->x = $this->y;
|
||||
$this->y = $this->z;
|
||||
$this->z = $this->w;
|
||||
$this->w = ($this->w ^ (($this->w >> 19) & 0x7fffffff)
|
||||
^ ($t ^ (($t >> 8) & 0x7fffffff))) & 0xffffffff;
|
||||
$this->w = ($this->w ^ (($this->w >> 19) & 0x7fffffff) ^ ($t ^ (($t >> 8) & 0x7fffffff))) & 0xffffffff;
|
||||
|
||||
return $this->w;
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ use function fopen;
|
||||
use function function_exists;
|
||||
use function getenv;
|
||||
use function is_array;
|
||||
use function sapi_windows_vt100_support;
|
||||
use function stream_isatty;
|
||||
|
||||
abstract class Terminal{
|
||||
|
@ -89,6 +89,7 @@ use function substr;
|
||||
use function sys_get_temp_dir;
|
||||
use function trim;
|
||||
use function xdebug_get_function_stack;
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
use const PHP_EOL;
|
||||
use const PHP_INT_MAX;
|
||||
use const PHP_INT_SIZE;
|
||||
@ -639,7 +640,7 @@ class Utils{
|
||||
* @return string
|
||||
*/
|
||||
public static function cleanPath($path){
|
||||
$result = str_replace(["\\", ".php", "phar://"], ["/", "", ""], $path);
|
||||
$result = str_replace([DIRECTORY_SEPARATOR, ".php", "phar://"], ["/", "", ""], $path);
|
||||
|
||||
//remove relative paths
|
||||
//TODO: make these paths dynamic so they can be unit-tested against
|
||||
@ -648,7 +649,7 @@ class Utils{
|
||||
\pocketmine\PATH => ""
|
||||
];
|
||||
foreach($cleanPaths as $cleanPath => $replacement){
|
||||
$cleanPath = rtrim(str_replace(["\\", "phar://"], ["/", ""], $cleanPath), "/");
|
||||
$cleanPath = rtrim(str_replace([DIRECTORY_SEPARATOR, "phar://"], ["/", ""], $cleanPath), "/");
|
||||
if(strpos($result, $cleanPath) === 0){
|
||||
$result = ltrim(str_replace($cleanPath, $replacement, $result), "/");
|
||||
}
|
||||
@ -662,7 +663,11 @@ class Utils{
|
||||
* @return string[] an array of tagName => tag value. If the tag has no value, an empty string is used as the value.
|
||||
*/
|
||||
public static function parseDocComment(string $docComment) : array{
|
||||
preg_match_all('/(*ANYCRLF)^[\t ]*\* @([a-zA-Z]+)(?:[\t ]+(.+))?[\t ]*$/m', $docComment, $matches);
|
||||
$rawDocComment = substr($docComment, 3, -2); //remove the opening and closing markers
|
||||
if($rawDocComment === false){ //usually empty doc comment, but this is safer and statically analysable
|
||||
return [];
|
||||
}
|
||||
preg_match_all('/(*ANYCRLF)^[\t ]*(?:\* )?@([a-zA-Z]+)(?:[\t ]+(.+?))?[\t ]*$/m', $rawDocComment, $matches);
|
||||
|
||||
return array_combine($matches[1], $matches[2]);
|
||||
}
|
||||
|
2
start.sh
2
start.sh
@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
DIR="$(cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd)"
|
||||
cd "$DIR"
|
||||
|
||||
|
@ -21,4 +21,12 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
define('pocketmine\_PHPSTAN_ANALYSIS', true);
|
||||
define('pocketmine\_PHPSTAN_ANALYSIS', true);
|
||||
|
||||
//TODO: these need to be defined properly or removed
|
||||
define('pocketmine\COMPOSER_AUTOLOADER_PATH', dirname(__DIR__, 2) . '/vendor/autoload.php');
|
||||
define('pocketmine\DATA', '');
|
||||
define('pocketmine\GIT_COMMIT', str_repeat('00', 20));
|
||||
define('pocketmine\PLUGIN_PATH', '');
|
||||
define('pocketmine\START_TIME', microtime(true));
|
||||
define('pocketmine\VERSION', '9.9.9');
|
||||
|
792
tests/phpstan/configs/actual-problems.neon
Normal file
792
tests/phpstan/configs/actual-problems.neon
Normal file
@ -0,0 +1,792 @@
|
||||
parameters:
|
||||
ignoreErrors:
|
||||
-
|
||||
message: "#^Instanceof between pocketmine\\\\plugin\\\\PluginManager and pocketmine\\\\plugin\\\\PluginManager will always evaluate to true\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/CrashDump.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\Player\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\entity\\\\Human\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/Player.php
|
||||
|
||||
-
|
||||
message: "#^Cannot instantiate interface pocketmine\\\\level\\\\format\\\\io\\\\LevelProvider\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/Server.php
|
||||
|
||||
-
|
||||
message: "#^Instanceof between pocketmine\\\\plugin\\\\PluginManager and pocketmine\\\\plugin\\\\PluginManager will always evaluate to true\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/Server.php
|
||||
|
||||
-
|
||||
message: "#^Instanceof between pocketmine\\\\scheduler\\\\AsyncPool and pocketmine\\\\scheduler\\\\AsyncPool will always evaluate to true\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/Server.php
|
||||
|
||||
-
|
||||
message: "#^Instanceof between pocketmine\\\\command\\\\CommandReader and pocketmine\\\\command\\\\CommandReader will always evaluate to true\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/Server.php
|
||||
|
||||
-
|
||||
message: "#^Instanceof between pocketmine\\\\network\\\\Network and pocketmine\\\\network\\\\Network will always evaluate to true\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/Server.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Air\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Air.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Anvil\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Anvil.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\BaseRail\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/BaseRail.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Bed\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Bed.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Bedrock\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Bedrock.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Beetroot\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Beetroot.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Block\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\level\\\\Position\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Block.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\BoneBlock\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/BoneBlock.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Bookshelf\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Bookshelf.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\BrewingStand\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/BrewingStand.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\BrickStairs\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/BrickStairs.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Bricks\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Bricks.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\BurningFurnace\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/BurningFurnace.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Button\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Button.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Cactus\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Cactus.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Cake\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Cake.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Carpet\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Carpet.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Carrot\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Carrot.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Chest\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Chest.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Clay\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Clay.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Coal\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Coal.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\CoalOre\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/CoalOre.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Cobblestone\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Cobblestone.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\CobblestoneStairs\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/CobblestoneStairs.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\CobblestoneWall\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/CobblestoneWall.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Cobweb\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Cobweb.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\CocoaBlock\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/CocoaBlock.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Concrete\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Concrete.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\ConcretePowder\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/ConcretePowder.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\CraftingTable\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/CraftingTable.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Dandelion\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Dandelion.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\DaylightSensor\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/DaylightSensor.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\DeadBush\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/DeadBush.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Diamond\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Diamond.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\DiamondOre\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/DiamondOre.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Dirt\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Dirt.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\DoublePlant\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/DoublePlant.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\DoubleSlab\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/DoubleSlab.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Emerald\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Emerald.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\EmeraldOre\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/EmeraldOre.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\EnchantingTable\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/EnchantingTable.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\EndPortalFrame\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/EndPortalFrame.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\EndRod\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/EndRod.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\EndStone\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/EndStone.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\EndStoneBricks\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/EndStoneBricks.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Farmland\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Farmland.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Fence\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Fence.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Fire\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Fire.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Flower\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Flower.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\FlowerPot\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/FlowerPot.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Glass\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Glass.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\GlassPane\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/GlassPane.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\GlowingObsidian\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/GlowingObsidian.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Glowstone\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Glowstone.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Gold\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Gold.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\GoldOre\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/GoldOre.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Grass\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Grass.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\GrassPath\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/GrassPath.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Gravel\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Gravel.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\HardenedClay\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/HardenedClay.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\HayBale\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/HayBale.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Ice\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Ice.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\InvisibleBedrock\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/InvisibleBedrock.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Iron\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Iron.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\IronBars\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/IronBars.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\IronDoor\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/IronDoor.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\IronOre\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/IronOre.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\ItemFrame\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/ItemFrame.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Ladder\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Ladder.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Lapis\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Lapis.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\LapisOre\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/LapisOre.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Lava\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Lava.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Leaves\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Leaves.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Lever\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Lever.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Magma\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Magma.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Melon\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Melon.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\MelonStem\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/MelonStem.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\MonsterSpawner\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/MonsterSpawner.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Mycelium\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Mycelium.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\NetherBrickStairs\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/NetherBrickStairs.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\NetherQuartzOre\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/NetherQuartzOre.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\NetherReactor\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/NetherReactor.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\NetherWartBlock\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/NetherWartBlock.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\NetherWartPlant\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/NetherWartPlant.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Netherrack\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Netherrack.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\NoteBlock\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/NoteBlock.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Obsidian\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Obsidian.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\PackedIce\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/PackedIce.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Planks\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Planks.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Podzol\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Podzol.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Potato\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Potato.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Prismarine\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Prismarine.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Pumpkin\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Pumpkin.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\PumpkinStem\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/PumpkinStem.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\PurpurStairs\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/PurpurStairs.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Quartz\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Quartz.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\QuartzStairs\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/QuartzStairs.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\RedMushroom\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/RedMushroom.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\RedMushroomBlock\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/RedMushroomBlock.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Redstone\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Redstone.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\RedstoneLamp\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/RedstoneLamp.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\RedstoneOre\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/RedstoneOre.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Sand\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Sand.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Sandstone\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Sandstone.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\SandstoneStairs\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/SandstoneStairs.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Sapling\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Sapling.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\SeaLantern\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/SeaLantern.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\SignPost\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/SignPost.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Skull\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Skull.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Slab\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Slab.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Snow\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Snow.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\SnowLayer\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/SnowLayer.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\SoulSand\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/SoulSand.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Sponge\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Sponge.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\StandingBanner\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/StandingBanner.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Stone\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Stone.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\StoneBrickStairs\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/StoneBrickStairs.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\StoneBricks\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/StoneBricks.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\StonePressurePlate\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/StonePressurePlate.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Stonecutter\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Stonecutter.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Sugarcane\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Sugarcane.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\TNT\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/TNT.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\TallGrass\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/TallGrass.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Torch\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Torch.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Trapdoor\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Trapdoor.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Tripwire\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Tripwire.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\TripwireHook\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/TripwireHook.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Vine\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Vine.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Water\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Water.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\WaterLily\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/WaterLily.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\WeightedPressurePlateLight\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/WeightedPressurePlateLight.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Wheat\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Wheat.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Wood\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Wood.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\block\\\\Wool\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\block\\\\Block\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Wool.php
|
||||
|
||||
-
|
||||
message: "#^Call to an undefined method pocketmine\\\\command\\\\CommandSender\\:\\:teleport\\(\\)\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/command/defaults/TeleportCommand.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: "#^pocketmine\\\\inventory\\\\DoubleChestInventory\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\inventory\\\\ChestInventory\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/inventory/DoubleChestInventory.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\inventory\\\\EnderChestInventory\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\inventory\\\\ChestInventory\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/inventory/EnderChestInventory.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\item\\\\GoldenAppleEnchanted\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\item\\\\GoldenApple\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/item/GoldenAppleEnchanted.php
|
||||
|
||||
-
|
||||
message: "#^pocketmine\\\\item\\\\WrittenBook\\:\\:__construct\\(\\) does not call parent constructor from pocketmine\\\\item\\\\WritableBook\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/item/WrittenBook.php
|
||||
|
||||
-
|
||||
message: "#^Variable property access on \\$this\\(pocketmine\\\\level\\\\generator\\\\PopulationTask\\)\\.$#"
|
||||
count: 4
|
||||
path: ../../../src/pocketmine/level/generator/PopulationTask.php
|
||||
|
||||
-
|
||||
message: "#^Constructor of class pocketmine\\\\level\\\\generator\\\\hell\\\\Nether has an unused parameter \\$options\\.$#"
|
||||
count: 1
|
||||
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: "#^Variable method call on pocketmine\\\\event\\\\Listener\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/plugin/MethodEventExecutor.php
|
||||
|
||||
-
|
||||
message: "#^Constructor of class pocketmine\\\\scheduler\\\\TaskScheduler has an unused parameter \\$logger\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/scheduler/TaskScheduler.php
|
||||
|
@ -1,6 +1,3 @@
|
||||
#cyclic refs in lots of objects prevent GC, causing increased memory pressure
|
||||
#the proper fix is to not have cycles, but in the meantime we have these hacks
|
||||
|
||||
parameters:
|
||||
ignoreErrors:
|
||||
-
|
||||
|
1582
tests/phpstan/configs/l7-baseline.neon
Normal file
1582
tests/phpstan/configs/l7-baseline.neon
Normal file
File diff suppressed because it is too large
Load Diff
2397
tests/phpstan/configs/l8-baseline.neon
Normal file
2397
tests/phpstan/configs/l8-baseline.neon
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,7 @@
|
||||
parameters:
|
||||
ignoreErrors:
|
||||
- "#^Method ReflectionMethod\\:\\:getClosure\\(\\) invoked with 0 parameters, 1 required\\.$#"
|
||||
-
|
||||
message: "#^Method ReflectionMethod\\:\\:getClosure\\(\\) invoked with 0 parameters, 1 required\\.$#"
|
||||
count: 1
|
||||
path: ../../phpunit/network/mcpe/StupidJsonDecodeTest.php
|
||||
|
||||
|
@ -1,55 +1,42 @@
|
||||
parameters:
|
||||
ignoreErrors:
|
||||
- "#^Call to function is_resource\\(\\) with resource will always evaluate to true\\.$#"
|
||||
-
|
||||
message: "#^Default value of the parameter \\#\\d+ \\$[A-Za-z\\d_]+ \\(\\-?\\d+\\) of method .+\\(\\) is incompatible with type float\\.$#"
|
||||
path: ../../../src
|
||||
|
||||
-
|
||||
message: "#^Offset string does not exist on array\\(\\)\\.$#"
|
||||
count: 3
|
||||
path: ../../../src/pocketmine/MemoryManager.php
|
||||
|
||||
-
|
||||
message: "#^Offset \\(int\\|string\\) does not exist on array\\(\\)\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/MemoryManager.php
|
||||
|
||||
-
|
||||
message: "#^Comparison operation \"\\>\\=\" between 0 and 2 is always false\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Liquid.php
|
||||
|
||||
-
|
||||
#adjacentSources comparison FP
|
||||
message: "#^If condition is always false\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Liquid.php
|
||||
|
||||
-
|
||||
#readline() may return false
|
||||
message: "#^Strict comparison using \\!\\=\\= between string and false will always evaluate to true\\.$#"
|
||||
count: 1
|
||||
message: "#^Call to function is_resource\\(\\) with resource will always evaluate to true\\.$#"
|
||||
count: 3
|
||||
path: ../../../src/pocketmine/command/CommandReader.php
|
||||
|
||||
-
|
||||
#generics corruption, this might show up in other forms too
|
||||
message: "#^Parameter \\#1 \\$offset \\(int\\) of method pocketmine\\\\entity\\\\AttributeMap\\:\\:offsetGet\\(\\) should be contravariant with parameter \\$offset \\(mixed\\) of method ArrayAccess\\<int,float\\>\\:\\:offsetGet\\(\\)$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/entity/AttributeMap.php
|
||||
|
||||
-
|
||||
message: "#^Call to function assert\\(\\) with false and 'unknown hit type' will always evaluate to false\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/entity/projectile/Projectile.php
|
||||
|
||||
-
|
||||
message: "#^Call to function is_resource\\(\\) with resource will always evaluate to true\\.$#"
|
||||
count: 2
|
||||
path: ../../../src/pocketmine/level/format/io/region/RegionLoader.php
|
||||
|
||||
-
|
||||
message: "#^Call to function method_exists\\(\\) with pocketmine\\\\network\\\\mcpe\\\\CachedEncapsulatedPacket and '__toString' will always evaluate to true\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/network/mcpe/protocol/DataPacket.php
|
||||
|
||||
-
|
||||
#phpstan doesn't understand that SplFixedArray may contain null
|
||||
message: "#^Strict comparison using \\=\\=\\= between string and false will always evaluate to false\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/utils/Utils.php
|
||||
|
||||
-
|
||||
message: "#^Call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertNotNull\\(\\) with int and string will always evaluate to true\\.$#"
|
||||
count: 1
|
||||
path: ../../../tests/phpunit/block/BlockTest.php
|
||||
path: ../../phpunit/block/BlockTest.php
|
||||
|
||||
|
@ -4,3 +4,4 @@ parameters:
|
||||
message: "#^Parameter \\#1 \\$class of static method pocketmine\\\\level\\\\format\\\\io\\\\LevelProviderManager\\:\\:addProvider\\(\\) expects class\\-string\\<pocketmine\\\\level\\\\format\\\\io\\\\LevelProvider\\>, string given\\.$#"
|
||||
count: 2
|
||||
path: ../../phpunit/level/format/io/LevelProviderManagerTest.php
|
||||
|
||||
|
@ -2,5 +2,6 @@ parameters:
|
||||
ignoreErrors:
|
||||
-
|
||||
message: "#^Variable \\$GLOBALS in isset\\(\\) always exists and is not nullable\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/MemoryManager.php
|
||||
|
||||
|
@ -1,12 +1,11 @@
|
||||
parameters:
|
||||
ignoreErrors:
|
||||
-
|
||||
message: "#^Call to function is_subclass_of\\(\\) with class\\-string\\<pocketmine\\\\level\\\\generator\\\\Generator\\> and 'pocketmine\\\\\\\\level…' will always evaluate to true\\.$#"
|
||||
message: "#^Call to function is_subclass_of\\(\\) with class\\-string\\<pocketmine\\\\level\\\\generator\\\\Generator\\> and 'pocketmine\\\\\\\\level\\\\\\\\generator\\\\\\\\Generator' will always evaluate to true\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/Server.php
|
||||
|
||||
-
|
||||
#::add() / ::remove() thread parameter
|
||||
message: "#^If condition is always true\\.$#"
|
||||
count: 2
|
||||
path: ../../../src/pocketmine/ThreadManager.php
|
||||
@ -22,38 +21,29 @@ parameters:
|
||||
path: ../../../src/pocketmine/event/HandlerList.php
|
||||
|
||||
-
|
||||
#jsonDeserialize(), not currently validated
|
||||
message: "#^Casting to int something that's already int\\.$#"
|
||||
count: 3
|
||||
path: ../../../src/pocketmine/item/Item.php
|
||||
|
||||
-
|
||||
#::get() tags parameter
|
||||
message: "#^If condition is always false\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/item/ItemFactory.php
|
||||
|
||||
-
|
||||
#::get() tags parameter
|
||||
message: "#^Strict comparison using \\!\\=\\= between null and null will always evaluate to false\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/item/ItemFactory.php
|
||||
|
||||
-
|
||||
#::get() tags parameter
|
||||
message: "#^Else branch is unreachable because ternary operator condition is always true\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/item/ItemFactory.php
|
||||
|
||||
-
|
||||
message: "#^Call to function is_object\\(\\) with \\*NEVER\\* will always evaluate to true\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/item/ItemFactory.php
|
||||
|
||||
-
|
||||
#->sendBlocks() blocks parameter
|
||||
message: "#^Else branch is unreachable because ternary operator condition is always true\\.$#"
|
||||
count: 2
|
||||
path: ../../../src/pocketmine/level/Level.php
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/item/ItemFactory.php
|
||||
|
||||
-
|
||||
message: "#^Instanceof between pocketmine\\\\math\\\\Vector3 and pocketmine\\\\math\\\\Vector3 will always evaluate to true\\.$#"
|
||||
@ -65,23 +55,28 @@ parameters:
|
||||
count: 2
|
||||
path: ../../../src/pocketmine/level/Level.php
|
||||
|
||||
-
|
||||
message: "#^Else branch is unreachable because ternary operator condition is always true\\.$#"
|
||||
count: 2
|
||||
path: ../../../src/pocketmine/level/Level.php
|
||||
|
||||
-
|
||||
message: "#^Call to function assert\\(\\) with bool will always evaluate to true\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/level/Level.php
|
||||
|
||||
-
|
||||
message: "#^Call to function is_subclass_of\\(\\) with class\\-string\\<pocketmine\\\\level\\\\generator\\\\Generator\\> and 'pocketmine\\\\\\\\level…' will always evaluate to true\\.$#"
|
||||
message: "#^Call to function is_subclass_of\\(\\) with class\\-string\\<pocketmine\\\\level\\\\generator\\\\Generator\\> and 'pocketmine\\\\\\\\level\\\\\\\\generator\\\\\\\\Generator' will always evaluate to true\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/level/generator/GeneratorManager.php
|
||||
|
||||
-
|
||||
#commands plugin.yml not currently validated, can't be sure
|
||||
message: "#^Call to function is_array\\(\\) with array\\<string, mixed\\> will always evaluate to true\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/plugin/PluginManager.php
|
||||
|
||||
-
|
||||
message: "#^Call to function is_subclass_of\\(\\) with class\\-string\\<pocketmine\\\\event\\\\Event\\> and 'pocketmine\\\\\\\\event…' will always evaluate to true\\.$#"
|
||||
message: "#^Call to function is_subclass_of\\(\\) with class\\-string\\<pocketmine\\\\event\\\\Event\\> and 'pocketmine\\\\\\\\event\\\\\\\\Event' will always evaluate to true\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/plugin/PluginManager.php
|
||||
|
||||
|
@ -63,6 +63,32 @@ class UtilsTest extends TestCase{
|
||||
self::assertEquals("HIGHEST", $tags["priority"]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][]
|
||||
* @phpstan-return list<array{string}>
|
||||
*/
|
||||
public function parseDocCommentOneLineProvider() : array{
|
||||
return [
|
||||
["/** @ignoreCancelled true dummy */"],
|
||||
["/**@ignoreCancelled true dummy*/"],
|
||||
["/** @ignoreCancelled true dummy */"]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider parseDocCommentOneLineProvider
|
||||
*/
|
||||
public function testParseOneLineDocComment(string $comment) : void{
|
||||
$tags = Utils::parseDocComment($comment);
|
||||
self::assertArrayHasKey("ignoreCancelled", $tags);
|
||||
self::assertEquals("true dummy", $tags["ignoreCancelled"]);
|
||||
}
|
||||
|
||||
public function testParseEmptyDocComment() : void{
|
||||
$tags = Utils::parseDocComment("");
|
||||
self::assertCount(0, $tags);
|
||||
}
|
||||
|
||||
public function testNamespacedNiceClosureName() : void{
|
||||
//be careful with this test. The closure has to be declared on the same line as the assertion.
|
||||
self::assertSame('closure@' . Utils::cleanPath(__FILE__) . '#L' . __LINE__, Utils::getNiceClosureName(function() : void{}));
|
||||
|
Reference in New Issue
Block a user