mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-12 04:20:17 +00:00
Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
d4851a8f1f | |||
480a513f30 | |||
4fd3bee360 | |||
41fd7545e3 | |||
82dddde159 | |||
bc709efb77 | |||
cd98e6a23e | |||
cb591a98f4 | |||
e9d1af0aee | |||
0f545c410a | |||
1c2ed0836f | |||
6cf30dc813 | |||
f7d9247d39 | |||
3380aa3ac2 | |||
6a9cad8fb7 |
@ -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
26
composer.lock
generated
@ -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"
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)){
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
@ -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{
|
||||
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
@ -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()){
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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{
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)){
|
||||
|
Submodule tests/preprocessor updated: a6ec3e1271...b87380457e
Reference in New Issue
Block a user