Compare commits

..

15 Commits
3.5.5 ... 3.5.6

Author SHA1 Message Date
d4851a8f1f Release 3.5.6 2019-01-19 17:33:07 +00:00
480a513f30 Sign: fixed asserts on loading NBT, closes #2636 2019-01-19 16:42:22 +00:00
4fd3bee360 Entity: Address fireticks crashdumps
This will now throw an exception at the source instead of crashing when the entity is saved, which should put the blame on the correct plugin responsible for this.
This also includes magic method hacks to preserve backwards compatibility, since the fireTicks field is now protected.
2019-01-19 16:05:10 +00:00
41fd7545e3 RegionLoader: Account for unexpected EOF when reading chunks, closes #2676 2019-01-19 15:49:19 +00:00
82dddde159 Remove dead code in /time command handler 2019-01-19 15:15:04 +00:00
bc709efb77 Prevent stupidity with /enchant 2019-01-19 15:14:51 +00:00
cd98e6a23e Updated PreProcessor submodule 2019-01-19 13:57:17 +00:00
cb591a98f4 NetworkBinaryStream: Skip item NBT which is too large when encoded
Encoded tags larger than 32KB overflow the length field, so we can't send these over network. However, it's unreasonable to randomly throw this burden off onto users by crashing their servers, so the next best solution is to just not send the NBT. This is also not an ideal solution (books and the like with too-large tags won't work on the client side) but it's better than crashing the server or client due to a protocol bug. Mojang have confirmed this will be resolved by a future MCPE release, so we'll just work around this problem until then.
2019-01-16 21:50:43 +00:00
e9d1af0aee Fixed stack trace encoding bug in CrashDump
it was encoding the real (full) trace, instead of emitting the printable version.
2019-01-16 18:56:56 +00:00
0f545c410a Bow: Improve consistency with vanilla (JE at least), closes #2660
This change causes the existing test I did to now report ~55-60 blocks, which is much closer to parity with vanilla.
2019-01-15 14:42:41 +00:00
1c2ed0836f Sync composer dependencies 2019-01-15 10:26:33 +00:00
6cf30dc813 build 7.3 on travis 2019-01-11 23:54:44 +00:00
f7d9247d39 Server: Permit NULL value entries in pocketmine.yml worlds
this permits listing worlds to load as keys without values.
2019-01-10 19:30:37 +00:00
3380aa3ac2 Config: Assert only whitespace precedes .properties key, fixes #commented properties not being skipped 2019-01-07 12:25:05 +00:00
6a9cad8fb7 3.5.6 is next 2019-01-06 20:18:32 +00:00
16 changed files with 129 additions and 54 deletions

View File

@ -2,13 +2,14 @@ language: php
php:
- 7.2
- 7.3
before_script:
# - pecl install channel://pecl.php.net/pthreads-3.1.6
- echo | pecl install channel://pecl.php.net/yaml-2.0.2
- echo | pecl install channel://pecl.php.net/yaml-2.0.4
- git clone https://github.com/pmmp/pthreads.git
- cd pthreads
- git checkout c8cfacda84f21032d6014b53e72bf345ac901dac
- git checkout 6ca019c58b4fa09ee2ff490f2444e34bef0773d0
- phpize
- ./configure
- make

26
composer.lock generated
View File

@ -92,16 +92,16 @@
},
{
"name": "pocketmine/binaryutils",
"version": "0.1.5",
"version": "0.1.7",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BinaryUtils.git",
"reference": "03361b0d78ef2b400a99e96406aa594a5bc1c4ed"
"reference": "3403751da9d39853b43426085cd242173baadd2b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BinaryUtils/zipball/03361b0d78ef2b400a99e96406aa594a5bc1c4ed",
"reference": "03361b0d78ef2b400a99e96406aa594a5bc1c4ed",
"url": "https://api.github.com/repos/pmmp/BinaryUtils/zipball/3403751da9d39853b43426085cd242173baadd2b",
"reference": "3403751da9d39853b43426085cd242173baadd2b",
"shasum": ""
},
"require": {
@ -119,10 +119,10 @@
],
"description": "Classes and methods for conveniently handling binary data",
"support": {
"source": "https://github.com/pmmp/BinaryUtils/tree/0.1.5",
"source": "https://github.com/pmmp/BinaryUtils/tree/0.1.7",
"issues": "https://github.com/pmmp/BinaryUtils/issues"
},
"time": "2019-01-04T13:32:11+00:00"
"time": "2019-01-07T15:59:50+00:00"
},
{
"name": "pocketmine/math",
@ -160,16 +160,16 @@
},
{
"name": "pocketmine/nbt",
"version": "0.2.4",
"version": "0.2.5",
"source": {
"type": "git",
"url": "https://github.com/pmmp/NBT.git",
"reference": "05dddb51830fd8f3b6c93e553abe07643ec96fc5"
"reference": "0b290fa0f5b44835ebeea8146c9ac960cac833f5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/NBT/zipball/05dddb51830fd8f3b6c93e553abe07643ec96fc5",
"reference": "05dddb51830fd8f3b6c93e553abe07643ec96fc5",
"url": "https://api.github.com/repos/pmmp/NBT/zipball/0b290fa0f5b44835ebeea8146c9ac960cac833f5",
"reference": "0b290fa0f5b44835ebeea8146c9ac960cac833f5",
"shasum": ""
},
"require": {
@ -194,10 +194,10 @@
],
"description": "PHP library for working with Named Binary Tags",
"support": {
"source": "https://github.com/pmmp/NBT/tree/0.2.4",
"source": "https://github.com/pmmp/NBT/tree/0.2.5",
"issues": "https://github.com/pmmp/NBT/issues"
},
"time": "2019-01-04T15:28:44+00:00"
"time": "2019-01-07T17:28:16+00:00"
},
{
"name": "pocketmine/raklib",
@ -302,7 +302,7 @@
],
"description": "Standard library files required by PocketMine-MP and related projects",
"support": {
"source": "https://github.com/pmmp/SPL/tree/master"
"source": "https://github.com/pmmp/SPL/tree/0.3.2"
},
"time": "2018-08-12T15:17:39+00:00"
}

View File

@ -44,6 +44,7 @@ use function implode;
use function is_dir;
use function is_resource;
use function json_encode;
use function json_last_error_msg;
use function max;
use function mkdir;
use function ob_end_clean;
@ -146,7 +147,11 @@ class CrashDump{
$this->addLine("----------------------REPORT THE DATA BELOW THIS LINE-----------------------");
$this->addLine();
$this->addLine("===BEGIN CRASH DUMP===");
$this->encodedData = zlib_encode(json_encode($this->data, JSON_UNESCAPED_SLASHES), ZLIB_ENCODING_DEFLATE, 9);
$json = json_encode($this->data, JSON_UNESCAPED_SLASHES);
if($json === false){
throw new \RuntimeException("Failed to encode crashdump JSON: " . json_last_error_msg());
}
$this->encodedData = zlib_encode($json, ZLIB_ENCODING_DEFLATE, 9);
foreach(str_split(base64_encode($this->encodedData), 76) as $line){
$this->addLine($line);
}
@ -238,6 +243,9 @@ class CrashDump{
}
if(isset($lastError)){
if(isset($lastError["trace"])){
$lastError["trace"] = Utils::printableTrace($lastError["trace"]);
}
$this->data["lastError"] = $lastError;
}

View File

@ -37,7 +37,7 @@ namespace pocketmine {
use pocketmine\wizard\SetupWizard;
const NAME = "PocketMine-MP";
const BASE_VERSION = "3.5.5";
const BASE_VERSION = "3.5.6";
const IS_DEVELOPMENT_BUILD = false;
const BUILD_NUMBER = 0;

View File

@ -1731,7 +1731,9 @@ class Server{
GeneratorManager::registerDefaultGenerators();
foreach((array) $this->getProperty("worlds", []) as $name => $options){
if(!is_array($options)){
if($options === null){
$options = [];
}elseif(!is_array($options)){
continue;
}
if(!$this->loadLevel($name)){

View File

@ -67,7 +67,7 @@ class Water extends Liquid{
public function onEntityCollide(Entity $entity) : void{
$entity->resetFallDistance();
if($entity->fireTicks > 0){
if($entity->isOnFire()){
$entity->extinguish();
}

View File

@ -77,7 +77,15 @@ class EnchantCommand extends VanillaCommand{
return true;
}
$item->addEnchantment(new EnchantmentInstance($enchantment, (int) ($args[2] ?? 1)));
$level = 1;
if(isset($args[2])){
$level = $this->getBoundedInt($sender, $args[2], 1, $enchantment->getMaxLevel());
if($level === null){
return false;
}
}
$item->addEnchantment(new EnchantmentInstance($enchantment, $level));
$player->getInventory()->setItemInHand($item);

View File

@ -55,9 +55,7 @@ class TimeCommand extends VanillaCommand{
return true;
}
foreach($sender->getServer()->getLevels() as $level){
$level->checkTime();
$level->startTime();
$level->checkTime();
}
Command::broadcastCommandMessage($sender, "Restarted the time");
return true;
@ -68,9 +66,7 @@ class TimeCommand extends VanillaCommand{
return true;
}
foreach($sender->getServer()->getLevels() as $level){
$level->checkTime();
$level->stopTime();
$level->checkTime();
}
Command::broadcastCommandMessage($sender, "Stopped the time");
return true;
@ -110,9 +106,7 @@ class TimeCommand extends VanillaCommand{
}
foreach($sender->getServer()->getLevels() as $level){
$level->checkTime();
$level->setTime($value);
$level->checkTime();
}
Command::broadcastCommandMessage($sender, new TranslationContainer("commands.time.set", [$value]));
}elseif($args[0] === "add"){
@ -124,9 +118,7 @@ class TimeCommand extends VanillaCommand{
$value = $this->getInteger($sender, $args[1], 0);
foreach($sender->getServer()->getLevels() as $level){
$level->checkTime();
$level->setTime($level->getTime() + $value);
$level->checkTime();
}
Command::broadcastCommandMessage($sender, new TranslationContainer("commands.time.added", [$value]));
}else{

View File

@ -477,7 +477,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/** @var int */
public $lastUpdate;
/** @var int */
public $fireTicks = 0;
protected $fireTicks = 0;
/** @var CompoundTag */
public $namedtag;
/** @var bool */
@ -1093,8 +1093,8 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
public function setOnFire(int $seconds) : void{
$ticks = $seconds * 20;
if($ticks > $this->fireTicks){
$this->fireTicks = $ticks;
if($ticks > $this->getFireTicks()){
$this->setFireTicks($ticks);
}
$this->setGenericFlag(self::DATA_FLAG_ONFIRE, true);
@ -1109,8 +1109,12 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/**
* @param int $fireTicks
* @throws \InvalidArgumentException
*/
public function setFireTicks(int $fireTicks) : void{
if($fireTicks < 0 or $fireTicks > 0x7fff){
throw new \InvalidArgumentException("Fire ticks must be in range 0 ... " . 0x7fff . ", got $fireTicks");
}
$this->fireTicks = $fireTicks;
}
@ -2187,4 +2191,47 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
public function __toString(){
return (new \ReflectionClass($this))->getShortName() . "(" . $this->getId() . ")";
}
/**
* TODO: remove this BC hack in 4.0
*
* @param string $name
*
* @return mixed
* @throws \ErrorException
*/
public function __get($name){
if($name === "fireTicks"){
return $this->fireTicks;
}
throw new \ErrorException("Undefined property: " . get_class($this) . "::\$" . $name);
}
/**
* TODO: remove this BC hack in 4.0
*
* @param string $name
* @param mixed $value
*
* @throws \ErrorException
* @throws \InvalidArgumentException
*/
public function __set($name, $value){
if($name === "fireTicks"){
$this->setFireTicks($value);
}else{
throw new \ErrorException("Undefined property: " . get_class($this) . "::\$" . $name);
}
}
/**
* TODO: remove this BC hack in 4.0
*
* @param string $name
*
* @return bool
*/
public function __isset($name){
return $name === "fireTicks";
}
}

View File

@ -319,7 +319,7 @@ abstract class Projectile extends Entity{
$entityHit->attack($ev);
if($this->fireTicks > 0){
if($this->isOnFire()){
$ev = new EntityCombustByEntityEvent($this, $entityHit, 5);
$ev->call();
if(!$ev->isCancelled()){

View File

@ -63,10 +63,10 @@ class Bow extends Tool{
$diff = $player->getItemUseDuration();
$p = $diff / 20;
$force = min((($p ** 2) + $p * 2) / 3, 1) * 2;
$baseForce = min((($p ** 2) + $p * 2) / 3, 1);
$entity = Entity::createEntity("Arrow", $player->getLevel(), $nbt, $player, $force == 2);
$entity = Entity::createEntity("Arrow", $player->getLevel(), $nbt, $player, $baseForce >= 1);
if($entity instanceof Projectile){
$infinity = $this->hasEnchantment(Enchantment::INFINITY);
if($entity instanceof ArrowEntity){
@ -83,9 +83,9 @@ class Bow extends Tool{
if($this->hasEnchantment(Enchantment::FLAME)){
$entity->setOnFire(intdiv($entity->getFireTicks(), 20) + 100);
}
$ev = new EntityShootBowEvent($player, $this, $entity, $force);
$ev = new EntityShootBowEvent($player, $this, $entity, $baseForce * 3);
if($force < 0.1 or $diff < 5){
if($baseForce < 0.1 or $diff < 5){
$ev->setCancelled();
}

View File

@ -46,6 +46,7 @@ use function str_pad;
use function stream_set_read_buffer;
use function stream_set_write_buffer;
use function strlen;
use function substr;
use function time;
use function touch;
use function unpack;
@ -134,8 +135,11 @@ class RegionLoader{
}
fseek($this->filePointer, $this->locationTable[$index][0] << 12);
$length = Binary::readInt(fread($this->filePointer, 4));
$compression = ord(fgetc($this->filePointer));
$prefix = fread($this->filePointer, 4);
if($prefix === false or strlen($prefix) !== 4){
throw new CorruptedChunkException("Corrupted chunk header detected (unexpected end of file reading length prefix)");
}
$length = Binary::readInt($prefix);
if($length <= 0 or $length > self::MAX_SECTOR_LENGTH){ //Not yet generated / corrupted
if($length >= self::MAX_SECTOR_LENGTH){
@ -150,17 +154,19 @@ class RegionLoader{
MainLogger::getLogger()->error("Corrupted bigger chunk detected (bigger than number of sectors given in header)");
$this->locationTable[$index][1] = $length >> 12;
$this->writeLocationIndex($index);
}elseif($compression !== self::COMPRESSION_ZLIB and $compression !== self::COMPRESSION_GZIP){
}
$chunkData = fread($this->filePointer, $length);
if($chunkData === false or strlen($chunkData) !== $length){
throw new CorruptedChunkException("Corrupted chunk detected (unexpected end of file reading chunk data)");
}
$compression = ord($chunkData[0]);
if($compression !== self::COMPRESSION_ZLIB and $compression !== self::COMPRESSION_GZIP){
throw new CorruptedChunkException("Invalid compression type (got $compression, expected " . self::COMPRESSION_ZLIB . " or " . self::COMPRESSION_GZIP . ")");
}
$chunkData = fread($this->filePointer, $length - 1);
if($chunkData === false){
throw new CorruptedChunkException("Corrupted chunk detected (failed to read chunk data from disk)");
}
return $chunkData;
return substr($chunkData, 1);
}
public function chunkExists(int $x, int $z) : bool{

View File

@ -113,7 +113,17 @@ class NetworkBinaryStream extends BinaryStream{
$nbt = $item->getCompoundTag();
$nbtLen = strlen($nbt);
if($nbtLen > 32767){
throw new \InvalidArgumentException("NBT encoded length must be < 32768, got $nbtLen bytes");
/*
* TODO: Workaround bug in the protocol (overflow)
* Encoded tags larger than 32KB overflow the length field, so we can't send these over network.
* However, it's unreasonable to randomly throw this burden off onto users by crashing their servers, so the
* next best solution is to just not send the NBT. This is also not an ideal solution (books and the like
* with too-large tags won't work on the client side) but it's better than crashing the server or client due
* to a protocol bug. Mojang have confirmed this will be resolved by a future MCPE release, so we'll just
* work around this problem until then.
*/
$nbt = "";
$nbtLen = 0;
}
$this->putLShort($nbtLen);

View File

@ -31,8 +31,6 @@ use pocketmine\utils\TextFormat;
use function array_map;
use function array_pad;
use function array_slice;
use function assert;
use function count;
use function explode;
use function implode;
use function sprintf;
@ -41,13 +39,16 @@ class Sign extends Spawnable{
public const TAG_TEXT_BLOB = "Text";
public const TAG_TEXT_LINE = "Text%d"; //sprintf()able
private static function fixTextBlob(string $blob) : array{
return array_slice(array_pad(explode("\n", $blob), 4, ""), 0, 4);
}
/** @var string[] */
protected $text = ["", "", "", ""];
protected function readSaveData(CompoundTag $nbt) : void{
if($nbt->hasTag(self::TAG_TEXT_BLOB, StringTag::class)){ //MCPE 1.2 save format
$this->text = array_pad(explode("\n", $nbt->getString(self::TAG_TEXT_BLOB)), 4, "");
assert(count($this->text) === 4, "Too many lines!");
$this->text = self::fixTextBlob($nbt->getString(self::TAG_TEXT_BLOB));
}else{
for($i = 1; $i <= 4; ++$i){
$textKey = sprintf(self::TAG_TEXT_LINE, $i);
@ -138,7 +139,7 @@ class Sign extends Spawnable{
}
if($nbt->hasTag(self::TAG_TEXT_BLOB, StringTag::class)){
$lines = array_slice(array_pad(explode("\n", $nbt->getString(self::TAG_TEXT_BLOB)), 4, ""), 0, 4);
$lines = self::fixTextBlob($nbt->getString(self::TAG_TEXT_BLOB));
}else{
return false;
}

View File

@ -564,7 +564,7 @@ class Config{
* @param string $content
*/
private function parseProperties(string $content){
if(preg_match_all('/([a-zA-Z0-9\-_\.]+)[ \t]*=([^\r\n]*)/u', $content, $matches) > 0){ //false or 0 matches
if(preg_match_all('/^\s*([a-zA-Z0-9\-_\.]+)[ \t]*=([^\r\n]*)/um', $content, $matches) > 0){ //false or 0 matches
foreach($matches[1] as $i => $k){
$v = trim($matches[2][$i]);
switch(strtolower($v)){