Compare commits

...

25 Commits
3.4.0 ... 3.4.3

Author SHA1 Message Date
9b078854c4 Release 3.4.3 2018-12-22 17:17:24 +00:00
1455c38dbe Utils: fixed crash in getCoreCount(), closes #2600
this should just default to 2 instead of shitting its pants.
2018-12-22 13:27:11 +00:00
75df6973df LevelDB: Account for 2D maps tag being missing
I don't know why this would be missing, but in some cases it is, as seen in the crash archive. Whatever the case, we shouldn't be shitting the bed because of this.
2018-12-22 13:13:14 +00:00
4763360e9e Update BinaryUtils dependency 2018-12-22 13:07:45 +00:00
0299191e64 Attribute: fit value when resetting to default, closes #2599 2018-12-22 11:44:36 +00:00
4249c00c3e Level: Fixed generation/send race condition causing blocks to be missing on the client
this FINALLY fixes the remaining occurrences of half-trees.
2018-12-21 18:39:33 +00:00
69c343bb9b Level: fix setChunk() deleting tiles when replacing a chunk with the same chunk
this can be desirable to trigger events related to chunks changing, such as chunk sending.
2018-12-21 17:24:08 +00:00
34a899e28b Clean up Utils error handling functions (internal) 2018-12-16 17:50:00 +00:00
b80868040e Utils: fixed getTrace() including itself in trace when no alt trace is given
it always seemed a little strange that crashdump trace would pop 4 frames when only 3 are written in the comment...
2018-12-16 17:15:16 +00:00
bf8a8b386e Allow ~relative coordinates to work in /particle 2018-12-16 14:12:46 +00:00
60b1f0a6e9 Fixed burning TNT setting affected mobs on fire when exploding, closes #2561 2018-12-14 17:32:11 +00:00
d4fe1b8ece 3.4.3 is next 2018-12-14 09:30:44 +00:00
9b2653fb6f Release 3.4.2 2018-12-14 09:30:14 +00:00
ed88684e71 Fixed invisible FloatingTextParticle crashing the server, closes #2560 2018-12-14 09:30:14 +00:00
cbb9c4f298 Entity: require scale > 0 in setScale(), fixes #2563 2018-12-14 09:30:14 +00:00
660d42e8d1 Backport usage of SetLocalPlayerAsInitializedPacket to 3.4 (#2558)
This fixes various problems, such as forms not working on PlayerJoinEvent.
2018-12-13 20:07:17 +00:00
1d71f5edb3 DataPacket: more detail in error messages for undefined fields 2018-12-13 09:55:50 +00:00
4975da2aae NetworkInventoryAction: additional validity checks 2018-12-12 10:11:44 +00:00
f704061618 Tree: fixed being able to overwrite other trees
this was observable by planting a sapling underneath an existing tree and punching it with bone meal.

This change will also prevent trees generating too close together.
2018-12-09 19:26:48 +00:00
23dc6e09d8 Sync DevTools submodule 2018-12-09 15:34:06 +00:00
15b7fc978e 3.4.2 is next 2018-12-08 17:00:36 +00:00
bb396174ba Release 3.4.1 2018-12-08 17:00:07 +00:00
dcef3cba21 CrashDump: cleanup some version related stuff
this should have been done a long time ago, but we didn't want to cause compatibility problems with CA. Now it enforces version checks, this isn't a problem anymore.
2018-12-08 16:58:06 +00:00
5f8a9f8747 Add a new format_version field to crashdumps
this will be used in the future to allow CA to decide how to decode crashdumps and/or refuse crashdumps from incompatible versions.
2018-12-08 16:57:57 +00:00
84e41e6967 3.4.1 is next 2018-12-06 21:01:57 +00:00
19 changed files with 122 additions and 65 deletions

12
composer.lock generated
View File

@ -48,16 +48,16 @@
},
{
"name": "pocketmine/binaryutils",
"version": "0.1.1",
"version": "0.1.2",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BinaryUtils.git",
"reference": "54efeb978be0ff9335022729fe63c1e2077bf1be"
"reference": "2c1628f08a9cdeca4d3c682e13f24420944ca845"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BinaryUtils/zipball/54efeb978be0ff9335022729fe63c1e2077bf1be",
"reference": "54efeb978be0ff9335022729fe63c1e2077bf1be",
"url": "https://api.github.com/repos/pmmp/BinaryUtils/zipball/2c1628f08a9cdeca4d3c682e13f24420944ca845",
"reference": "2c1628f08a9cdeca4d3c682e13f24420944ca845",
"shasum": ""
},
"require": {
@ -75,10 +75,10 @@
],
"description": "Classes and methods for conveniently handling binary data",
"support": {
"source": "https://github.com/pmmp/BinaryUtils/tree/master",
"source": "https://github.com/pmmp/BinaryUtils/tree/0.1.2",
"issues": "https://github.com/pmmp/BinaryUtils/issues"
},
"time": "2018-08-26T18:11:05+00:00"
"time": "2018-12-22T12:29:30+00:00"
},
{
"name": "pocketmine/math",

View File

@ -33,6 +33,14 @@ use raklib\RakLib;
class CrashDump{
/**
* Crashdump data format version, used by the crash archive to decide how to decode the crashdump
* This should be incremented when backwards incompatible changes are introduced, such as fields being removed or
* having their content changed, version format changing, etc.
* It is not necessary to increase this when adding new fields.
*/
private const FORMAT_VERSION = 1;
/** @var Server */
private $server;
private $fp;
@ -54,6 +62,7 @@ class CrashDump{
if(!is_resource($this->fp)){
throw new \RuntimeException("Could not create Crash Dump");
}
$this->data["format_version"] = self::FORMAT_VERSION;
$this->data["time"] = $this->time;
$this->addLine($this->server->getName() . " Crash Dump " . date("D M j H:i:s T Y", $this->time));
$this->addLine();
@ -150,7 +159,7 @@ class CrashDump{
$error = $lastExceptionError;
}else{
$error = (array) error_get_last();
$error["trace"] = Utils::getTrace(4); //Skipping CrashDump->baseCrash, CrashDump->construct, Server->crashDump
$error["trace"] = Utils::printableCurrentTrace(3); //Skipping CrashDump->baseCrash, CrashDump->construct, Server->crashDump
$errorConversion = [
E_ERROR => "E_ERROR",
E_WARNING => "E_WARNING",
@ -232,10 +241,10 @@ class CrashDump{
$version = new VersionString(\pocketmine\BASE_VERSION, \pocketmine\IS_DEVELOPMENT_BUILD, \pocketmine\BUILD_NUMBER);
$this->data["general"] = [];
$this->data["general"]["name"] = $this->server->getName();
$this->data["general"]["version"] = $version->getFullVersion(false);
$this->data["general"]["build"] = $version->getBuild();
$this->data["general"]["base_version"] = \pocketmine\BASE_VERSION;
$this->data["general"]["build"] = \pocketmine\BUILD_NUMBER;
$this->data["general"]["is_dev"] = \pocketmine\IS_DEVELOPMENT_BUILD;
$this->data["general"]["protocol"] = ProtocolInfo::CURRENT_PROTOCOL;
$this->data["general"]["api"] = \pocketmine\BASE_VERSION;
$this->data["general"]["git"] = \pocketmine\GIT_COMMIT;
$this->data["general"]["raklib"] = RakLib::VERSION;
$this->data["general"]["uname"] = php_uname("a");

View File

@ -276,7 +276,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
/** @var int */
protected $spawnThreshold;
/** @var int */
protected $chunkLoadCount = 0;
protected $spawnChunkLoadCount = 0;
/** @var int */
protected $chunksPerTick;
@ -962,8 +962,6 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
}
$this->usedChunks[Level::chunkHash($x, $z)] = true;
$this->chunkLoadCount++;
$this->dataPacket($payload);
if($this->spawned){
@ -974,8 +972,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
}
}
if($this->chunkLoadCount >= $this->spawnThreshold and !$this->spawned){
$this->doFirstSpawn();
if($this->spawnChunkLoadCount !== -1 and ++$this->spawnChunkLoadCount >= $this->spawnThreshold){
$this->sendPlayStatus(PlayStatusPacket::PLAYER_SPAWN);
$this->spawnChunkLoadCount = -1;
}
}
@ -1013,11 +1012,12 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
Timings::$playerChunkSendTimer->stopTiming();
}
protected function doFirstSpawn(){
public function doFirstSpawn(){
if($this->spawned){
return; //avoid player spawning twice (this can only happen on 3.x with a custom malicious client)
}
$this->spawned = true;
$this->sendPlayStatus(PlayStatusPacket::PLAYER_SPAWN);
if($this->hasPermission(Server::BROADCAST_CHANNEL_USERS)){
PermissionManager::getInstance()->subscribeToPermission(Server::BROADCAST_CHANNEL_USERS, $this);
}

View File

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

View File

@ -2173,7 +2173,7 @@ class Server{
"fullFile" => $e->getFile(),
"file" => $errfile,
"line" => $errline,
"trace" => Utils::getTrace(0, $trace)
"trace" => Utils::printableTrace($trace)
];
global $lastExceptionError, $lastError;

View File

@ -29,6 +29,7 @@ use pocketmine\command\utils\InvalidCommandSyntaxException;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\lang\TranslationContainer;
use pocketmine\level\Level;
use pocketmine\level\particle\AngryVillagerParticle;
use pocketmine\level\particle\BlockForceFieldParticle;
use pocketmine\level\particle\BubbleParticle;
@ -84,14 +85,18 @@ class ParticleCommand extends VanillaCommand{
if($sender instanceof Player){
$level = $sender->getLevel();
$pos = new Vector3(
$this->getRelativeDouble($sender->getX(), $sender, $args[1]),
$this->getRelativeDouble($sender->getY(), $sender, $args[2], 0, Level::Y_MAX),
$this->getRelativeDouble($sender->getZ(), $sender, $args[3])
);
}else{
$level = $sender->getServer()->getDefaultLevel();
$pos = new Vector3((float) $args[1], (float) $args[2], (float) $args[3]);
}
$name = strtolower($args[0]);
$pos = new Vector3((float) $args[1], (float) $args[2], (float) $args[3]);
$xd = (float) $args[4];
$yd = (float) $args[5];
$zd = (float) $args[6];

View File

@ -171,7 +171,7 @@ class Attribute{
}
public function resetToDefault() : void{
$this->setValue($this->getDefaultValue());
$this->setValue($this->getDefaultValue(), true);
}
public function getValue() : float{

View File

@ -637,6 +637,9 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
* @param float $value
*/
public function setScale(float $value) : void{
if($value <= 0){
throw new \InvalidArgumentException("Scale must be greater than 0");
}
$multiplier = $value / $this->getScale();
$this->width *= $multiplier;

View File

@ -571,7 +571,10 @@ abstract class Living extends Entity implements Damageable{
}
if($e !== null){
if($e->isOnFire()){
if((
$source->getCause() === EntityDamageEvent::CAUSE_PROJECTILE or
$source->getCause() === EntityDamageEvent::CAUSE_ENTITY_ATTACK
) and $e->isOnFire()){
$this->setOnFire(2 * $this->level->getDifficulty());
}

View File

@ -450,13 +450,14 @@ class Level implements ChunkManager, Metadatable{
if(!is_array($pk)){
$pk = [$pk];
}
if($players === null){
foreach($pk as $e){
$this->broadcastPacketToViewers($sound, $e);
if(!empty($pk)){
if($players === null){
foreach($pk as $e){
$this->broadcastPacketToViewers($sound, $e);
}
}else{
$this->server->batchPackets($players, $pk, false);
}
}else{
$this->server->batchPackets($players, $pk, false);
}
}
@ -465,13 +466,14 @@ class Level implements ChunkManager, Metadatable{
if(!is_array($pk)){
$pk = [$pk];
}
if($players === null){
foreach($pk as $e){
$this->broadcastPacketToViewers($particle, $e);
if(!empty($pk)){
if($players === null){
foreach($pk as $e){
$this->broadcastPacketToViewers($particle, $e);
}
}else{
$this->server->batchPackets($players, $pk, false);
}
}else{
$this->server->batchPackets($players, $pk, false);
}
}
@ -2438,7 +2440,7 @@ class Level implements ChunkManager, Metadatable{
$chunkHash = Level::chunkHash($chunkX, $chunkZ);
$oldChunk = $this->getChunk($chunkX, $chunkZ, false);
if($oldChunk !== null){
if($oldChunk !== null and $oldChunk !== $chunk){
if($unload){
$this->unloadChunk($chunkX, $chunkZ, false, false);
}else{
@ -2460,6 +2462,10 @@ class Level implements ChunkManager, Metadatable{
unset($this->blockCache[$chunkHash]);
unset($this->chunkCache[$chunkHash]);
unset($this->changedBlocks[$chunkHash]);
if(isset($this->chunkSendTasks[$chunkHash])){ //invalidate pending caches
$this->chunkSendTasks[$chunkHash]->cancelRun();
unset($this->chunkSendTasks[$chunkHash]);
}
$chunk->setChanged();
if(!$this->isChunkInUse($chunkX, $chunkZ)){

View File

@ -283,6 +283,11 @@ class LevelDB extends BaseLevelProvider{
/** @var SubChunk[] $subChunks */
$subChunks = [];
/** @var int[] $heightMap */
$heightMap = [];
/** @var string $biomeIds */
$biomeIds = "";
/** @var bool $lightPopulated */
$lightPopulated = true;
@ -325,10 +330,12 @@ class LevelDB extends BaseLevelProvider{
}
}
$binaryStream->setBuffer($this->db->get($index . self::TAG_DATA_2D), 0);
if(($maps2d = $this->db->get($index . self::TAG_DATA_2D)) !== false){
$binaryStream->setBuffer($maps2d, 0);
$heightMap = array_values(unpack("v*", $binaryStream->get(512)));
$biomeIds = $binaryStream->get(256);
$heightMap = array_values(unpack("v*", $binaryStream->get(512)));
$biomeIds = $binaryStream->get(256);
}
break;
case 2: // < MCPE 1.0
$binaryStream->setBuffer($this->db->get($index . self::TAG_LEGACY_TERRAIN));

View File

@ -33,10 +33,8 @@ abstract class Tree{
public $overridable = [
Block::AIR => true,
Block::SAPLING => true,
Block::LOG => true,
Block::LEAVES => true,
Block::SNOW_LAYER => true,
Block::LOG2 => true,
Block::LEAVES2 => true
];

View File

@ -58,6 +58,7 @@ use pocketmine\network\mcpe\protocol\RequestChunkRadiusPacket;
use pocketmine\network\mcpe\protocol\ResourcePackChunkRequestPacket;
use pocketmine\network\mcpe\protocol\ResourcePackClientResponsePacket;
use pocketmine\network\mcpe\protocol\ServerSettingsRequestPacket;
use pocketmine\network\mcpe\protocol\SetLocalPlayerAsInitializedPacket;
use pocketmine\network\mcpe\protocol\SetPlayerGameTypePacket;
use pocketmine\network\mcpe\protocol\ShowCreditsPacket;
use pocketmine\network\mcpe\protocol\SpawnExperienceOrbPacket;
@ -280,4 +281,9 @@ class PlayerNetworkSessionAdapter extends NetworkSession{
public function handleServerSettingsRequest(ServerSettingsRequestPacket $packet) : bool{
return false; //TODO: GUI stuff
}
public function handleSetLocalPlayerAsInitialized(SetLocalPlayerAsInitializedPacket $packet) : bool{
$this->player->doFirstSpawn();
return true;
}
}

View File

@ -139,10 +139,10 @@ abstract class DataPacket extends NetworkBinaryStream{
}
public function __get($name){
throw new \Error("Cannot read non-existing field \"$name\"");
throw new \Error("Undefined property: " . get_class($this) . "::\$" . $name);
}
public function __set($name, $value){
throw new \Error("Cannot write non-existing field \"$name\"");
throw new \Error("Undefined property: " . get_class($this) . "::\$" . $name);
}
}

View File

@ -88,7 +88,7 @@ class LoginPacket extends DataPacket{
$logger = MainLogger::getLogger();
$logger->debug(get_class($e) . " was thrown while decoding connection request in login (protocol version " . ($this->protocol ?? "unknown") . "): " . $e->getMessage());
foreach(Utils::getTrace(0, $e->getTrace()) as $line){
foreach(Utils::printableTrace($e->getTrace()) as $line){
$logger->debug($line);
}
}

View File

@ -118,6 +118,8 @@ class NetworkInventoryAction{
break;
}
break;
default:
throw new \UnexpectedValueException("Unknown inventory action source type $this->sourceType");
}
$this->inventorySlot = $packet->getUnsignedVarInt();
@ -145,6 +147,8 @@ class NetworkInventoryAction{
case self::SOURCE_TODO:
$packet->putVarInt($this->windowId);
break;
default:
throw new \UnexpectedValueException("Unknown inventory action source type $this->sourceType");
}
$packet->putUnsignedVarInt($this->inventorySlot);

View File

@ -210,7 +210,7 @@ class MainLogger extends \AttachableThreadedLogger{
$errfile = Utils::cleanPath($errfile);
$message = get_class($e) . ": \"$errstr\" ($errno) in \"$errfile\" at line $errline";
$stack = Utils::getTrace(0, $trace);
$stack = Utils::printableTrace($trace);
$this->synchronized(function() use ($type, $message, $stack) : void{
$this->log($type, $message);

View File

@ -313,8 +313,8 @@ class Utils{
++$processors;
}
}
}else{
if(preg_match("/^([0-9]+)\\-([0-9]+)$/", trim(@file_get_contents("/sys/devices/system/cpu/present")), $matches) > 0){
}elseif(is_readable("/sys/devices/system/cpu/present")){
if(preg_match("/^([0-9]+)\\-([0-9]+)$/", trim(file_get_contents("/sys/devices/system/cpu/present")), $matches) > 0){
$processors = (int) ($matches[2] - $matches[1]);
}
}
@ -525,24 +525,13 @@ class Utils{
}
/**
* @param int $start
* @param array|null $trace
* @param array $trace
*
* @return array
*/
public static function getTrace($start = 0, $trace = null){
if($trace === null){
if(function_exists("xdebug_get_function_stack")){
$trace = array_reverse(xdebug_get_function_stack());
}else{
$e = new \Exception();
$trace = $e->getTrace();
}
}
public static function printableTrace(array $trace) : array{
$messages = [];
$j = 0;
for($i = (int) $start; isset($trace[$i]); ++$i, ++$j){
for($i = 0; isset($trace[$i]); ++$i){
$params = "";
if(isset($trace[$i]["args"]) or isset($trace[$i]["params"])){
if(isset($trace[$i]["args"])){
@ -555,12 +544,39 @@ class Utils{
return (is_object($value) ? get_class($value) . " object" : gettype($value) . " " . (is_array($value) ? "Array()" : Utils::printable(@strval($value))));
}, $args));
}
$messages[] = "#$j " . (isset($trace[$i]["file"]) ? self::cleanPath($trace[$i]["file"]) : "") . "(" . (isset($trace[$i]["line"]) ? $trace[$i]["line"] : "") . "): " . (isset($trace[$i]["class"]) ? $trace[$i]["class"] . (($trace[$i]["type"] === "dynamic" or $trace[$i]["type"] === "->") ? "->" : "::") : "") . $trace[$i]["function"] . "(" . Utils::printable($params) . ")";
$messages[] = "#$i " . (isset($trace[$i]["file"]) ? self::cleanPath($trace[$i]["file"]) : "") . "(" . (isset($trace[$i]["line"]) ? $trace[$i]["line"] : "") . "): " . (isset($trace[$i]["class"]) ? $trace[$i]["class"] . (($trace[$i]["type"] === "dynamic" or $trace[$i]["type"] === "->") ? "->" : "::") : "") . $trace[$i]["function"] . "(" . Utils::printable($params) . ")";
}
return $messages;
}
/**
* @param int $skipFrames
*
* @return array
*/
public static function currentTrace(int $skipFrames = 0) : array{
++$skipFrames; //omit this frame from trace, in addition to other skipped frames
if(function_exists("xdebug_get_function_stack")){
$trace = array_reverse(xdebug_get_function_stack());
}else{
$e = new \Exception();
$trace = $e->getTrace();
}
for($i = 0; $i < $skipFrames; ++$i){
unset($trace[$i]);
}
return array_values($trace);
}
/**
* @param int $skipFrames
*
* @return array
*/
public static function printableCurrentTrace(int $skipFrames = 0) : array{
return self::printableTrace(self::currentTrace(++$skipFrames));
}
public static function cleanPath($path){
return str_replace(["\\", ".php", "phar://", str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PATH), str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PLUGIN_PATH)], ["/", "", "", "", ""], $path);
}