Compare commits

..

41 Commits
3.1.2 ... 3.1.4

Author SHA1 Message Date
17f7dc34be Release 3.1.4 2018-08-16 18:26:49 +01:00
a63d66c048 Sync 3.1 and 3.0 branches 2018-08-16 18:26:26 +01:00
95f6995ae0 3.0.12 is next 2018-08-16 18:25:31 +01:00
4a24d7909e Release 3.0.11 2018-08-16 18:14:04 +01:00
4e2387edc1 Merge branch 'release/3.0' into release/3.1 2018-08-16 15:52:12 +01:00
a5e38576ef ItemEntity: fixed using -1 for infinite pickup delay not working
closes #2382 (squash-merge)
2018-08-16 15:52:05 +01:00
381151dedc Merge branch 'release/3.0' into release/3.1 2018-08-15 13:48:36 +01:00
a604e6835e CoalOre: fixed ignoring silk touch for XP drops, closes #2374 2018-08-15 13:48:29 +01:00
142a6d7678 Merge branch 'release/3.0' into release/3.1 2018-08-14 15:03:22 +01:00
b2ca364de0 SplashPotion: Don't apply effects to entities which are not alive
fixes #2372
2018-08-14 15:03:15 +01:00
09ed40a921 Merge branch 'release/3.0' into release/3.1 2018-08-13 13:22:32 +01:00
565373cee6 OfflinePlayer: remove unnecessary getName() usages 2018-08-13 13:22:00 +01:00
c29723e3c4 OfflinePlayer: remove unnecessary strtolower() calls
closes #2371
2018-08-13 13:18:58 +01:00
a8811ab2b3 Fixed 1.5.0 PlayerSkinPacket protocol change that somehow disappeared
I am 100% sure I committed this change, but it isn't in the merge...
2018-08-11 19:59:44 +01:00
974583a853 Merge branch 'release/3.0' into release/3.1 2018-08-11 19:37:10 +01:00
03f8fe62d4 Fixed structure of GuiDataPickItemPacket
this changed in 1.2.0.7 beta and I didn't spot it.
2018-08-11 19:36:53 +01:00
699f35cc05 Merge branch 'release/3.0' into release/3.1 2018-08-07 18:49:06 +01:00
8fa196efc9 FallingBlock: fixed state not being saved 2018-08-07 18:48:52 +01:00
b1ab881b99 Merge branch 'release/3.0' into release/3.1 2018-08-07 14:32:28 +01:00
69c54e789a Clear the title bar when the server shutdown. 2018-08-07 14:31:39 +01:00
e33d1279fa Merge branch 'release/3.0' into release/3.1 2018-08-06 18:45:01 +01:00
9e1fa453ad Level: Fixed leak of global packets when no players are online
If a global packet was broadcasted when no players were online, it would be held in memory indefinitely (until a player joined).
2018-08-06 18:44:53 +01:00
6a05edb4e9 Merge branch 'release/3.0' into release/3.1 2018-08-05 11:33:02 +01:00
70635d0870 DropItemAction: Consider invalid if the target item is null
it's not possible to drop a null item.
2018-08-05 11:32:50 +01:00
46bd096f06 3.1.4 is next 2018-08-04 16:46:51 +01:00
51a8905fb3 Release 3.1.3 2018-08-04 16:41:16 +01:00
f954d7c3dc Bring 3.1 up to speed with 3.0 2018-08-04 16:40:40 +01:00
7ad0aa56b1 3.0.11 is next 2018-08-04 16:39:53 +01:00
1ff6f8846e disable dev flag 2018-08-04 16:30:23 +01:00
e6f53cc56b Merge branch 'release/3.0' into release/3.1 2018-08-03 20:07:46 +01:00
87f458f9bd AsyncPool: remove now-unnecessary isTerminated() call 2018-08-03 20:07:37 +01:00
5a7e575c3a AsyncPool: isCrashed() now returns true when a fatal error occurred
the fix for chunks earlier didn't fix...
2018-08-03 20:06:41 +01:00
20b37d0208 Merge branch 'release/3.0' into release/3.1 2018-08-03 18:50:14 +01:00
d6d98183ea MainLogger: Log messages and exception traces in a synchronized block
this ensures that stack traces are emitted coherently without messages from other threads landing in the middle.
2018-08-03 18:50:06 +01:00
89cf76363f Merge branch 'release/3.0' into release/3.1 2018-08-03 18:24:36 +01:00
9ff5c65fb6 Level: Make async chunk sending aware of faults
Previously any random error could occur during an AsyncTask preparing a chunk, and the Level would never know about it and thus never send the chunk.

I don't know how many invisible-chunk bug cases this fixes, but I expect it's quite a lot.
2018-08-03 18:23:32 +01:00
1532b0ef6d Level: Remove chunks from chunk send queue on unload
When a chunk request task crashes, these can get stuck and never get removed. This allows using /gc to collect the bad chunk in order to fix the bug.
2018-08-03 18:04:56 +01:00
61accee682 Merge branch 'release/3.0' into release/3.1 2018-08-02 14:43:44 +01:00
9ece971a2b Server: remove useless check from exceptionHandler()
this cannot be null... @shoghicp y u litter the code with these useless checks ???
2018-08-02 14:41:28 +01:00
5546c88f88 Server: Fixed parse errors getting reported to CA
this changed to throwing errors as of PHP 7
2018-08-02 14:40:36 +01:00
4c4761d200 back to dev 2018-07-30 15:21:10 +01:00
14 changed files with 86 additions and 63 deletions

View File

@ -44,7 +44,7 @@ class OfflinePlayer implements IPlayer, Metadatable{
public function __construct(Server $server, string $name){
$this->server = $server;
$this->name = $name;
if(file_exists($this->server->getDataPath() . "players/" . strtolower($this->getName()) . ".dat")){
if(file_exists($this->server->getDataPath() . "players/" . strtolower($this->name) . ".dat")){
$this->namedtag = $this->server->getOfflinePlayerData($this->name);
}else{
$this->namedtag = null;
@ -64,7 +64,7 @@ class OfflinePlayer implements IPlayer, Metadatable{
}
public function isOp() : bool{
return $this->server->isOp(strtolower($this->getName()));
return $this->server->isOp($this->name);
}
public function setOp(bool $value){
@ -73,38 +73,38 @@ class OfflinePlayer implements IPlayer, Metadatable{
}
if($value){
$this->server->addOp(strtolower($this->getName()));
$this->server->addOp($this->name);
}else{
$this->server->removeOp(strtolower($this->getName()));
$this->server->removeOp($this->name);
}
}
public function isBanned() : bool{
return $this->server->getNameBans()->isBanned(strtolower($this->getName()));
return $this->server->getNameBans()->isBanned($this->name);
}
public function setBanned(bool $value){
if($value){
$this->server->getNameBans()->addBan($this->getName(), null, null, null);
$this->server->getNameBans()->addBan($this->name, null, null, null);
}else{
$this->server->getNameBans()->remove($this->getName());
$this->server->getNameBans()->remove($this->name);
}
}
public function isWhitelisted() : bool{
return $this->server->isWhitelisted(strtolower($this->getName()));
return $this->server->isWhitelisted($this->name);
}
public function setWhitelisted(bool $value){
if($value){
$this->server->addWhitelist(strtolower($this->getName()));
$this->server->addWhitelist($this->name);
}else{
$this->server->removeWhitelist(strtolower($this->getName()));
$this->server->removeWhitelist($this->name);
}
}
public function getPlayer(){
return $this->server->getPlayerExact($this->getName());
return $this->server->getPlayerExact($this->name);
}
public function getFirstPlayed(){

View File

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

View File

@ -2013,6 +2013,10 @@ class Server{
return;
}
if($this->doTitleTick){
echo "\x1b]0;\x07";
}
try{
if(!$this->isRunning()){
$this->sendUsage(SendUsageTask::TYPE_CLOSE);
@ -2144,10 +2148,6 @@ class Server{
* @param array|null $trace
*/
public function exceptionHandler(\Throwable $e, $trace = null){
if($e === null){
return;
}
global $lastError;
if($trace === null){
@ -2205,7 +2205,7 @@ class Server{
}
}
if($dump->getData()["error"]["type"] === "E_PARSE" or $dump->getData()["error"]["type"] === "E_COMPILE_ERROR"){
if($dump->getData()["error"]["type"] === \ParseError::class){
$report = false;
}

View File

@ -57,7 +57,7 @@ class CoalOre extends Solid{
];
}
public function getXpDropForTool(Item $item) : int{
protected function getXpDropAmount() : int{
return mt_rand(0, 2);
}
}

View File

@ -134,6 +134,7 @@ class FallingBlock extends Entity{
}
public function saveNBT() : void{
parent::saveNBT();
$this->namedtag->setInt("TileID", $this->block->getId(), true);
$this->namedtag->setByte("Data", $this->block->getDamage());
}

View File

@ -197,7 +197,7 @@ class ItemEntity extends Entity{
}
public function onCollideWithPlayer(Player $player) : void{
if($this->getPickupDelay() > 0){
if($this->getPickupDelay() !== 0){
return;
}

View File

@ -82,7 +82,7 @@ class SplashPotion extends Throwable{
if($hasEffects){
if(!$this->willLinger()){
foreach($this->level->getNearbyEntities($this->boundingBox->expandedCopy(4.125, 2.125, 4.125), $this) as $entity){
if($entity instanceof Living){
if($entity instanceof Living and $entity->isAlive()){
$distanceSquared = $entity->distanceSquared($this);
if($distanceSquared > 16){ //4 blocks
continue;

View File

@ -38,7 +38,7 @@ class DropItemAction extends InventoryAction{
}
public function isValid(Player $source) : bool{
return true;
return !$this->targetItem->isNull();
}
public function onPreExecute(Player $source) : bool{

View File

@ -191,7 +191,7 @@ class Level implements ChunkManager, Metadatable{
/** @var Player[][] */
private $chunkSendQueue = [];
/** @var bool[] */
/** @var ChunkRequestTask[] */
private $chunkSendTasks = [];
/** @var bool[] */
@ -797,8 +797,10 @@ class Level implements ChunkManager, Metadatable{
$this->checkSleep();
}
if(!empty($this->players) and !empty($this->globalPackets)){
$this->server->batchPackets($this->players, $this->globalPackets);
if(!empty($this->globalPackets)){
if(!empty($this->players)){
$this->server->batchPackets($this->players, $this->globalPackets);
}
$this->globalPackets = [];
}
@ -2456,7 +2458,7 @@ class Level implements ChunkManager, Metadatable{
}
private function sendChunkFromCache(int $x, int $z){
if(isset($this->chunkSendTasks[$index = Level::chunkHash($x, $z)])){
if(isset($this->chunkSendQueue[$index = Level::chunkHash($x, $z)])){
foreach($this->chunkSendQueue[$index] as $player){
/** @var Player $player */
if($player->isConnected() and isset($player->usedChunks[$index])){
@ -2464,7 +2466,6 @@ class Level implements ChunkManager, Metadatable{
}
}
unset($this->chunkSendQueue[$index]);
unset($this->chunkSendTasks[$index]);
}
}
@ -2473,11 +2474,17 @@ class Level implements ChunkManager, Metadatable{
$this->timings->syncChunkSendTimer->startTiming();
foreach($this->chunkSendQueue as $index => $players){
if(isset($this->chunkSendTasks[$index])){
continue;
}
Level::getXZ($index, $x, $z);
$this->chunkSendTasks[$index] = true;
if(isset($this->chunkSendTasks[$index])){
if($this->chunkSendTasks[$index]->isCrashed()){
unset($this->chunkSendTasks[$index]);
$this->server->getLogger()->error("Failed to prepare chunk $x $z for sending, retrying");
}else{
//Not ready for sending yet
continue;
}
}
if(isset($this->chunkCache[$index])){
$this->sendChunkFromCache($x, $z);
continue;
@ -2490,7 +2497,8 @@ class Level implements ChunkManager, Metadatable{
}
assert($chunk->getX() === $x and $chunk->getZ() === $z, "Chunk coordinate mismatch: expected $x $z, but chunk has coordinates " . $chunk->getX() . " " . $chunk->getZ() . ", did you forget to clone a chunk before setting?");
$this->server->getAsyncPool()->submitTask(new ChunkRequestTask($this, $x, $z, $chunk));
$this->server->getAsyncPool()->submitTask($task = new ChunkRequestTask($this, $x, $z, $chunk));
$this->chunkSendTasks[$index] = $task;
$this->timings->syncChunkSendPrepareTimer->stopTiming();
}
@ -2503,24 +2511,14 @@ class Level implements ChunkManager, Metadatable{
$this->timings->syncChunkSendTimer->startTiming();
$index = Level::chunkHash($x, $z);
unset($this->chunkSendTasks[$index]);
if(!isset($this->chunkCache[$index]) and $this->server->getMemoryManager()->canUseChunkCache()){
$this->chunkCache[$index] = $payload;
$this->sendChunkFromCache($x, $z);
$this->timings->syncChunkSendTimer->stopTiming();
return;
$this->chunkCache[$index] = $payload;
$this->sendChunkFromCache($x, $z);
if(!$this->server->getMemoryManager()->canUseChunkCache()){
unset($this->chunkCache[$index]);
}
if(isset($this->chunkSendTasks[$index])){
foreach($this->chunkSendQueue[$index] as $player){
/** @var Player $player */
if($player->isConnected() and isset($player->usedChunks[$index])){
$player->sendChunk($x, $z, $payload);
}
}
unset($this->chunkSendQueue[$index]);
unset($this->chunkSendTasks[$index]);
}
$this->timings->syncChunkSendTimer->stopTiming();
}
@ -2754,6 +2752,8 @@ class Level implements ChunkManager, Metadatable{
unset($this->chunkCache[$chunkHash]);
unset($this->blockCache[$chunkHash]);
unset($this->changedBlocks[$chunkHash]);
unset($this->chunkSendQueue[$chunkHash]);
unset($this->chunkSendTasks[$chunkHash]);
$this->timings->doChunkUnload->stopTiming();

View File

@ -30,14 +30,22 @@ use pocketmine\network\mcpe\NetworkSession;
class GuiDataPickItemPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::GUI_DATA_PICK_ITEM_PACKET;
/** @var string */
public $itemDescription;
/** @var string */
public $itemEffects;
/** @var int */
public $hotbarSlot;
protected function decodePayload(){
$this->itemDescription = $this->getString();
$this->itemEffects = $this->getString();
$this->hotbarSlot = $this->getLInt();
}
protected function encodePayload(){
$this->putString($this->itemDescription);
$this->putString($this->itemEffects);
$this->putLInt($this->hotbarSlot);
}

View File

@ -40,7 +40,8 @@ class PlayerSkinPacket extends DataPacket{
public $newSkinName = "";
/** @var Skin */
public $skin;
/** @var bool */
public $premiumSkin = false;
protected function decodePayload(){
$this->uuid = $this->getUUID();
@ -54,6 +55,8 @@ class PlayerSkinPacket extends DataPacket{
$geometryData = $this->getString();
$this->skin = new Skin($skinId, $skinData, $capeData, $geometryModel, $geometryData);
$this->premiumSkin = $this->getBool();
}
protected function encodePayload(){
@ -66,6 +69,8 @@ class PlayerSkinPacket extends DataPacket{
$this->putString($this->skin->getCapeData());
$this->putString($this->skin->getGeometryName());
$this->putString($this->skin->getGeometryData());
$this->putBool($this->premiumSkin);
}
public function handle(NetworkSession $session) : bool{

View File

@ -295,7 +295,7 @@ class AsyncPool{
}
$this->removeTask($task);
}elseif($task->isTerminated() or $task->isCrashed()){
}elseif($task->isCrashed()){
$this->logger->critical("Could not execute asynchronous task " . (new \ReflectionClass($task))->getShortName() . ": Task crashed");
$this->removeTask($task, true);
}

View File

@ -80,7 +80,7 @@ abstract class AsyncTask extends Collectable{
}
public function isCrashed() : bool{
return $this->crashed;
return $this->crashed or $this->isTerminated();
}
/**

View File

@ -204,10 +204,16 @@ class MainLogger extends \AttachableThreadedLogger{
$errno = $errorConversion[$errno] ?? $errno;
$errstr = preg_replace('/\s+/', ' ', trim($errstr));
$errfile = Utils::cleanPath($errfile);
$this->log($type, get_class($e) . ": \"$errstr\" ($errno) in \"$errfile\" at line $errline");
foreach(Utils::getTrace(0, $trace) as $i => $line){
$this->debug($line, true);
}
$message = get_class($e) . ": \"$errstr\" ($errno) in \"$errfile\" at line $errline";
$stack = Utils::getTrace(0, $trace);
$this->synchronized(function() use ($type, $message, $stack) : void{
$this->log($type, $message);
foreach($stack as $line){
$this->debug($line, true);
}
});
$this->syncFlushBuffer();
}
@ -259,19 +265,22 @@ class MainLogger extends \AttachableThreadedLogger{
}
$message = sprintf($this->format, date("H:i:s", $now), $color, $threadName, $prefix, $message);
$cleanMessage = TextFormat::clean($message);
if($this->mainThreadHasFormattingCodes and Terminal::hasFormattingCodes()){ //hasFormattingCodes() lazy-inits colour codes because we don't know if they've been registered on this thread
echo Terminal::toANSI($message) . PHP_EOL;
}else{
echo $cleanMessage . PHP_EOL;
}
$this->synchronized(function() use ($message, $level, $now) : void{
$cleanMessage = TextFormat::clean($message);
foreach($this->attachments as $attachment){
$attachment->call($level, $message);
}
if($this->mainThreadHasFormattingCodes and Terminal::hasFormattingCodes()){ //hasFormattingCodes() lazy-inits colour codes because we don't know if they've been registered on this thread
echo Terminal::toANSI($message) . PHP_EOL;
}else{
echo $cleanMessage . PHP_EOL;
}
$this->logStream[] = date("Y-m-d", $now) . " " . $cleanMessage . PHP_EOL;
foreach($this->attachments as $attachment){
$attachment->call($level, $message);
}
$this->logStream[] = date("Y-m-d", $now) . " " . $cleanMessage . PHP_EOL;
});
}
public function syncFlushBuffer(){