Merge branch 'stable' into master

# Conflicts:
#	composer.lock
#	resources/vanilla
#	src/entity/Living.php
#	src/pocketmine/Player.php
#	src/pocketmine/VersionInfo.php
#	src/pocketmine/block/Potato.php
#	src/pocketmine/block/Sugarcane.php
#	src/pocketmine/entity/Entity.php
#	src/pocketmine/item/Item.php
#	src/pocketmine/level/format/Chunk.php
#	src/pocketmine/level/format/io/leveldb/LevelDB.php
#	src/world/generator/GeneratorRegisterTask.php
#	tests/phpstan/configs/check-explicit-mixed-baseline.neon
#	tests/phpstan/configs/l7-baseline.neon
#	tests/phpstan/configs/l8-baseline.neon
#	tests/plugins/TesterPlugin/src/pmmp/TesterPlugin/tests/AsyncTaskMainLoggerTest.php
#	tests/plugins/TesterPlugin/src/pmmp/TesterPlugin/tests/AsyncTaskMemoryLeakTest.php
#	tests/plugins/TesterPlugin/src/pmmp/TesterPlugin/tests/AsyncTaskPublishProgressRaceTest.php
This commit is contained in:
Dylan K. Taylor 2020-09-04 01:43:52 +01:00
commit 0aee39027e
18 changed files with 126 additions and 66 deletions

11
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1,11 @@
blank_issues_enabled: false
contact_links:
- name: Help & support on Discord
url: https://discord.gg/bmSAZBG
about: We don't accept support requests on the issue tracker. Please try asking on Discord instead.
- name: Help & support on forums
url: https://forums.pmmp.io
about: We don't accept support requests on the issue tracker. Please try asking on forums instead.
- name: Documentation
url: https://pmmp.rtfd.io
about: PocketMine-MP documentation

View File

@ -1,14 +0,0 @@
---
name: Help & support
about: We don't accept support requests here. Try the links on the README.
title: ''
labels: Support request
assignees: ''
---
We don't accept support requests on the issue tracker. Please try the following links instead:
Documentation: http://pmmp.rtfd.io
Forums: https://forums.pmmp.io
Discord: https://discord.gg/bmSAZBG

View File

@ -1,12 +0,0 @@
---
name: Security/DoS vulnerability
about: 'Bug or exploit that can be used to attack servers (hint: don''t report it
on a public issue tracker)'
title: ''
labels: 'Auto: Spam'
assignees: ''
---
Please DO NOT report security vulnerabilities here.
Instead, send an email to team@pmmp.io or contact a developer directly, IN PRIVATE.

33
SECURITY.md Normal file
View File

@ -0,0 +1,33 @@
# Security Policy
## Supported Versions
The following release lines are currently receiving active security updates and bug fixes:
| Version | Supported |
| -------- | ------------------ |
| 3.15.x | :white_check_mark: |
| < 3.15.0 | :x: |
## Reporting a Vulnerability
**DO NOT report vulnerabilities on the GitHub issue tracker.**
GitHub is public and anyone can see the issues you post on the issue tracker, including people who would exploit vulnerabilities for their own gain.
**WARNING: You may put live servers at risk by reporting a vulnerability on the GitHub issue tracker.**
**Contact us** by sending an email to [**team@pmmp.io**](mailto:team@pmmp.io?subject=Security%20Vulnerability%20in%20PocketMine-MP). Include the following information:
- Version of PocketMine-MP
- Detailed description of the vulnerability (e.g. how to exploit it, what the effects are)
Please note that we can't guarantee a reply to every email.
## FAQ
### Do you offer a bug bounty?
No.
### How soon can I expect a fix for a vulnerability I've reported?
This depends on the nature of the problem. We can't provide any general ETA (nor would it be wise to provide one).
In general, it depends on when developers have time to look into the problem, how complex the problem is to fix, and how many users it impacts.
When a fix for a severe vulnerability is pushed, a patch release for the target version will usually be released within 24 hours so that users can update.

View File

@ -15,3 +15,15 @@ Plugin developers should **only** update their required API to this version if y
- Pumpkin and melon stems may not connect to their corresponding pumpkin/melon
- New blocks, items & mobs aren't implemented
- Nether doesn't exist
# 3.15.1
- Fixed various PHP 7.4 compatibility issues in Composer dependencies (primarily callback-validator).
- Fixed LevelDB worlds with corrupted `level.dat` crashing the server instead of failing gracefully.
- Fixed error spam when using strings for layers in flatworld presets (`e.g. bedrock,3xdirt,grass`).
- Fixed blocks not getting updated properly on explosions.
- Fixed `BlockGrowEvent` not being called when sugarcane grows.
- Potato crops now drop poisonous potatoes when harvested.
- Fixed the wrong number of potatoes being dropped when harvesting potato crops.
- Players no longer get pullbacks when sprinting on slabs, stairs and various other blocks when `player.anti-cheat.allow-movement-cheats` is set to `false`. (This bug has been around for over 5 years, so many of you will be used to its existence.)
- Fixed entity collision box calculation not taking clip distance into account.
- Entities now step up the correct height of the target block, instead of jumping into the air 0.6 blocks and falling back down.

View File

@ -50,7 +50,7 @@
"respect/validation": "^2.0"
},
"require-dev": {
"phpstan/phpstan": "0.12.37",
"phpstan/phpstan": "0.12.42",
"phpstan/phpstan-phpunit": "^0.12.6",
"phpstan/phpstan-strict-rules": "^0.12.2",
"phpunit/phpunit": "^9.2"

12
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "3a8f754965da97b4e3237fd32168a6aa",
"content-hash": "adc74d30203a9378694bc478baf7a142",
"packages": [
{
"name": "adhocore/json-comment",
@ -1443,16 +1443,16 @@
},
{
"name": "phpstan/phpstan",
"version": "0.12.37",
"version": "0.12.42",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
"reference": "5e16d83e6eb2dd784fbdaeaece5e2bca72e4f68a"
"reference": "7c43b7c2d5ca6554f6231e82e342a710163ac5f4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/5e16d83e6eb2dd784fbdaeaece5e2bca72e4f68a",
"reference": "5e16d83e6eb2dd784fbdaeaece5e2bca72e4f68a",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/7c43b7c2d5ca6554f6231e82e342a710163ac5f4",
"reference": "7c43b7c2d5ca6554f6231e82e342a710163ac5f4",
"shasum": ""
},
"require": {
@ -1495,7 +1495,7 @@
"type": "tidelift"
}
],
"time": "2020-08-09T14:32:41+00:00"
"time": "2020-09-02T13:14:53+00:00"
},
{
"name": "phpstan/phpstan-phpunit",

View File

@ -24,6 +24,8 @@ parameters:
checkExplicitMixed: true
bootstrapFiles:
- tests/phpstan/bootstrap.php
scanDirectories:
- tests/plugins/TesterPlugin
scanFiles:
- src/PocketMine.php
- build/make-release.php
@ -34,6 +36,7 @@ parameters:
- build/make-release.php
- build/server-phar.php
- tests/phpunit
- tests/plugins/TesterPlugin
dynamicConstantNames:
- pocketmine\VersionInfo::IS_DEVELOPMENT_BUILD
- pocketmine\DEBUG

View File

@ -30,9 +30,13 @@ use function mt_rand;
class Potato extends Crops{
public function getDropsForCompatibleTool(Item $item) : array{
return [
VanillaItems::POTATO()->setCount($this->age >= 7 ? mt_rand(1, 4) : 1)
$result = [
VanillaItems::POTATO()->setCount($this->age >= 7 ? mt_rand(1, 5) : 1)
];
if($this->age >= 7 && mt_rand(0, 49) === 0){
$result[] = VanillaItems::POISONOUS_POTATO();
}
return $result;
}
public function getPickedItem(bool $addUserData = false) : Item{

View File

@ -98,7 +98,12 @@ class Sugarcane extends Flowable{
for($y = 1; $y < 3; ++$y){
$b = $this->pos->getWorld()->getBlockAt($this->pos->x, $this->pos->y + $y, $this->pos->z);
if($b->getId() === BlockLegacyIds::AIR){
$this->pos->getWorld()->setBlock($b->pos, VanillaBlocks::SUGARCANE());
$ev = new BlockGrowEvent($b, VanillaBlocks::SUGARCANE());
$ev->call();
if($ev->isCancelled()){
break;
}
$this->pos->getWorld()->setBlock($b->pos, $ev->getNewState());
break;
}
}

View File

@ -75,6 +75,7 @@ use const M_PI_2;
abstract class Entity{
public const MOTION_THRESHOLD = 0.00001;
protected const STEP_CLIP_MULTIPLIER = 0.4;
/** @var int */
private static $entityCount = 1;
@ -137,6 +138,8 @@ abstract class Entity{
/** @var int */
private $maxHealth = 20;
/** @var float */
protected $ySize = 0.0;
/** @var float */
protected $stepHeight = 0.0;
/** @var bool */
@ -329,10 +332,10 @@ abstract class Entity{
$this->boundingBox = new AxisAlignedBB(
$this->location->x - $halfWidth,
$this->location->y,
$this->location->y + $this->ySize,
$this->location->z - $halfWidth,
$this->location->x + $halfWidth,
$this->location->y + $this->height,
$this->location->y + $this->height + $this->ySize,
$this->location->z + $halfWidth
);
}
@ -1081,6 +1084,7 @@ abstract class Entity{
if($this->keepMovement){
$this->boundingBox->offset($dx, $dy, $dz);
}else{
$this->ySize *= self::STEP_CLIP_MULTIPLIER;
/*
if($this->isColliding){ //With cobweb?
@ -1175,7 +1179,12 @@ abstract class Entity{
$stepBB->offset(0, 0, $dz);
//TODO: here we need to shift back down on the Y-axis to the top of the target block (we don't want to jump into the air when walking onto carpet)
$reverseDY = -$dy;
foreach($list as $bb){
$reverseDY = $bb->calculateYOffset($stepBB, $reverseDY);
}
$dy += $reverseDY;
$stepBB->offset(0, $reverseDY, 0);
if(($cx ** 2 + $cz ** 2) >= ($dx ** 2 + $dz ** 2)){
$dx = $cx;
@ -1183,6 +1192,7 @@ abstract class Entity{
$dz = $cz;
}else{
$moveBB = $stepBB;
$this->ySize += $dy;
}
}
@ -1190,7 +1200,7 @@ abstract class Entity{
}
$this->location->x = ($this->boundingBox->minX + $this->boundingBox->maxX) / 2;
$this->location->y = $this->boundingBox->minY;
$this->location->y = $this->boundingBox->minY - $this->ySize;
$this->location->z = ($this->boundingBox->minZ + $this->boundingBox->maxZ) / 2;
$this->checkChunks();
@ -1420,6 +1430,7 @@ abstract class Entity{
if($ev->isCancelled()){
return false;
}
$this->ySize = 0;
$pos = $ev->getTo();
$this->setMotion(new Vector3(0, 0, 0));

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\entity\utils;
use pocketmine\math\Math;
use pocketmine\utils\AssumptionFailedError;
use function max;
abstract class ExperienceUtils{
@ -59,6 +60,9 @@ abstract class ExperienceUtils{
* This returns a floating-point number, the decimal part being the progress through the resulting level.
*/
public static function getLevelFromXp(int $xp) : float{
if($xp < 0){
throw new \InvalidArgumentException("XP must be at least 0");
}
if($xp <= self::getXpToReachLevel(16)){
$a = 1;
$b = 6;
@ -74,6 +78,9 @@ abstract class ExperienceUtils{
}
$x = Math::solveQuadratic($a, $b, $c - $xp);
if(count($x) === 0){
throw new AssumptionFailedError("Expected at least 1 solution");
}
return max($x); //we're only interested in the positive solution
}

View File

@ -2207,6 +2207,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
$this->networkSession->syncMovement($pos, $yaw, $pitch, $mode);
$this->forceMoveSync = $pos->asVector3();
$this->ySize = 0;
}
/**

View File

@ -115,11 +115,6 @@ parameters:
count: 1
path: ../../../src/command/defaults/SetWorldSpawnCommand.php
-
message: "#^Parameter \\#1 \\$name of method pocketmine\\\\Server\\:\\:getPlayer\\(\\) expects string, string\\|null given\\.$#"
count: 1
path: ../../../src/command/defaults/TellCommand.php
-
message: "#^Cannot call method getTime\\(\\) on pocketmine\\\\world\\\\World\\|null\\.$#"
count: 1
@ -417,11 +412,6 @@ parameters:
-
message: "#^Parameter \\#1 \\$str of function trim expects string, string\\|null given\\.$#"
count: 4
path: ../../../src/permission/BanEntry.php
-
message: "#^Parameter \\#1 \\$date of static method pocketmine\\\\permission\\\\BanEntry\\:\\:parseDate\\(\\) expects string, string\\|null given\\.$#"
count: 1
path: ../../../src/permission/BanEntry.php
@ -961,7 +951,7 @@ parameters:
path: ../../phpunit/event/HandlerListManagerTest.php
-
message: "#^Property pocketmine\\\\network\\\\mcpe\\\\handler\\\\StupidJsonDecodeTest\\:\\:\\$stupidJsonDecodeFunc \\(Closure\\) does not accept Closure\\|null\\.$#"
message: "#^Cannot call method cancel\\(\\) on pocketmine\\\\scheduler\\\\TaskHandler\\|null\\.$#"
count: 1
path: ../../phpunit/network/mcpe/handler/StupidJsonDecodeTest.php
path: ../../plugins/TesterPlugin/src/pmmp/TesterPlugin/CheckTestCompletionTask.php

View File

@ -10,3 +10,8 @@ parameters:
count: 1
path: ../../phpunit/network/mcpe/handler/StupidJsonDecodeTest.php
-
message: "#^Property pocketmine\\\\network\\\\mcpe\\\\handler\\\\StupidJsonDecodeTest\\:\\:\\$stupidJsonDecodeFunc \\(Closure\\(string, bool\\)\\: mixed\\) does not accept Closure\\|null\\.$#"
count: 1
path: ../../phpunit/network/mcpe/handler/StupidJsonDecodeTest.php

View File

@ -26,7 +26,10 @@ namespace pocketmine\network\mcpe\handler;
use PHPUnit\Framework\TestCase;
class StupidJsonDecodeTest extends TestCase{
/** @var \Closure */
/**
* @var \Closure
* @phpstan-var \Closure(string $json, bool $assoc=) : mixed
*/
private $stupidJsonDecodeFunc;
public function setUp() : void{

View File

@ -38,14 +38,14 @@ class Main extends PluginBase implements Listener{
/** @var int */
protected $currentTestNumber = 0;
public function onEnable(){
public function onEnable() : void{
$this->getServer()->getPluginManager()->registerEvents($this, $this);
$this->getScheduler()->scheduleRepeatingTask(new CheckTestCompletionTask($this), 10);
$this->waitingTests = [];
}
public function onServerCommand(CommandEvent $event){
public function onServerCommand(CommandEvent $event) : void{
//The CI will send this command as a failsafe to prevent the build from hanging if the tester plugin failed to
//run. However, if the plugin loaded successfully we don't want to allow this to stop the server as there may
//be asynchronous tests running. Instead we cancel this and stop the server of our own accord once all tests
@ -55,10 +55,7 @@ class Main extends PluginBase implements Listener{
}
}
/**
* @return Test|null
*/
public function getCurrentTest(){
public function getCurrentTest() : ?Test{
return $this->currentTest;
}
@ -73,7 +70,7 @@ class Main extends PluginBase implements Listener{
return false;
}
public function onTestCompleted(Test $test){
public function onTestCompleted(Test $test) : void{
$message = "Finished test #" . $this->currentTestNumber . " (" . $test->getName() . "): ";
switch($test->getResult()){
case Test::RESULT_OK:
@ -99,7 +96,7 @@ class Main extends PluginBase implements Listener{
$this->currentTest = null;
}
public function onAllTestsCompleted(){
public function onAllTestsCompleted() : void{
$this->getLogger()->notice("All tests finished, stopping the server");
$this->getServer()->shutdown();
}

View File

@ -29,9 +29,13 @@ abstract class Test{
const RESULT_FAILED = 1;
const RESULT_ERROR = 2;
/** @var Main */
private $plugin;
/** @var int */
private $result = Test::RESULT_WAITING;
/** @var int */
private $startTime;
/** @var int */
private $timeout = 60; //seconds
public function __construct(Main $plugin){
@ -42,7 +46,7 @@ abstract class Test{
return $this->plugin;
}
final public function start(){
final public function start() : void{
$this->startTime = time();
try{
$this->run();
@ -55,11 +59,11 @@ abstract class Test{
}
}
public function tick(){
public function tick() : void{
}
abstract public function run();
abstract public function run() : void;
public function isFinished() : bool{
return $this->result !== Test::RESULT_WAITING;
@ -69,7 +73,7 @@ abstract class Test{
return !$this->isFinished() and time() - $this->timeout > $this->startTime;
}
protected function setTimeout(int $timeout){
protected function setTimeout(int $timeout) : void{
$this->timeout = $timeout;
}
@ -77,7 +81,7 @@ abstract class Test{
return $this->result;
}
public function setResult(int $result){
public function setResult(int $result) : void{
$this->result = $result;
}