Compare commits

...

8 Commits

Author SHA1 Message Date
0aeac3af7d Release 3.26.0 2021-11-30 18:53:36 +00:00
9931c1d50a Protocol changes for 1.18.0 2021-11-30 18:46:29 +00:00
8079ae341a Updated build/php submodule to pmmp/php-build-scripts@bd329dba08 2021-11-30 01:19:14 +00:00
ba295dc7dc Always use LF in .neon files 2021-11-30 01:16:28 +00:00
c19174a174 3.25.7 is next 2021-11-26 23:37:47 +00:00
f95142f6b6 Release 3.25.6 2021-11-26 23:37:46 +00:00
7ace24caab Fixed borked build number
this was a problem before the recent clean-up; the only reason it just decided to show now is because 2000+25 is valid PHP code, so PHP saved our asses.
2021-11-26 23:36:19 +00:00
32f619ac49 3.25.6 is next 2021-11-26 23:20:48 +00:00
16 changed files with 118 additions and 16 deletions

1
.gitattributes vendored
View File

@ -4,6 +4,7 @@
*.sh text eol=lf
*.txt text eol=lf
*.properties text eol=lf
*.neon text eol=lf
*.bat text eol=crlf
*.cmd text eol=crlf
*.ps1 text eol=crlf

View File

@ -38,7 +38,7 @@ jobs:
- name: Calculate build number
id: build-number
run: |
BUILD_NUMBER=2000+$GITHUB_RUN_NUMBER #to stay above jenkins
BUILD_NUMBER=$((2000+$GITHUB_RUN_NUMBER)) #to stay above jenkins
echo "Build number: $BUILD_NUMBER"
echo ::set-output name=BUILD_NUMBER::$BUILD_NUMBER

View File

@ -33,3 +33,6 @@ Plugin developers should **only** update their required API to this version if y
- Protocol: Fixed incorrect encoding in `StructureSettings`
- Fixed reading tags from non-docblock comments in script plugins.
- Build number is now defined in phar metadata instead of being patched into the source code directly.
# 3.25.6
- Fixed borked build number in release build of 3.25.5.

11
changelogs/3.26.md Normal file
View File

@ -0,0 +1,11 @@
**For Minecraft: Bedrock Edition 1.18.0**
### Note about API versions
Plugins which don't touch the protocol and compatible with any previous 3.x.y version will also run on these releases and do not need API bumps.
Plugin developers should **only** update their required API to this version if you need the changes in this build.
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
# 3.26.0
- Added support for Minecraft: Bedrock Edition 1.18.0.
- Removed compatibility with earlier versions.

View File

@ -7,6 +7,7 @@
"require": {
"php": "^8.0",
"php-64bit": "*",
"ext-chunkutils2": "^0.3.1",
"ext-ctype": "*",
"ext-curl": "*",
"ext-date": "*",

3
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": "f13c4ed7311b99ac07dca31d2f77ad1d",
"content-hash": "2d144524b177c9e7f699ba7366c16354",
"packages": [
{
"name": "adhocore/json-comment",
@ -2761,6 +2761,7 @@
"platform": {
"php": "^8.0",
"php-64bit": "*",
"ext-chunkutils2": "^0.3.1",
"ext-ctype": "*",
"ext-curl": "*",
"ext-date": "*",

View File

@ -2279,6 +2279,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$pk->itemTable = ItemTypeDictionary::getInstance()->getEntries();
$pk->playerMovementSettings = new PlayerMovementSettings(PlayerMovementType::LEGACY, 0, false);
$pk->serverSoftwareVersion = sprintf("%s %s", \pocketmine\NAME, \pocketmine\VERSION);
$pk->blockPaletteChecksum = 0; //we don't bother with this (0 skips verification) - the preimage is some dumb stringified NBT, not even actual NBT
$this->dataPacket($pk);
$this->sendDataPacket(new AvailableActorIdentifiersPacket());

View File

@ -74,6 +74,7 @@ namespace pocketmine {
}
$extensions = [
"chunkutils2" => "PocketMine ChunkUtils v2",
"curl" => "cURL",
"ctype" => "ctype",
"date" => "Date",
@ -115,6 +116,16 @@ namespace pocketmine {
}
}
$chunkutils2_version = phpversion("chunkutils2");
$wantedVersionLock = "0.3";
$wantedVersionMin = "$wantedVersionLock.0";
if($chunkutils2_version !== false && (
version_compare($chunkutils2_version, $wantedVersionMin) < 0 ||
preg_match("/^" . preg_quote($wantedVersionLock, "/") . "\.\d+(?:-dev)?$/", $chunkutils2_version) === 0 //lock in at ^0.2, optionally at a patch release
)){
$messages[] = "chunkutils2 ^$wantedVersionMin is required, while you have $chunkutils2_version.";
}
if(extension_loaded("pocketmine")){
$messages[] = "The native PocketMine extension is no longer supported.";
}

View File

@ -33,6 +33,6 @@ if(defined('pocketmine\_VERSION_INFO_INCLUDED')){
const _VERSION_INFO_INCLUDED = true;
const NAME = "PocketMine-MP";
const BASE_VERSION = "3.25.5";
const BASE_VERSION = "3.26.0";
const IS_DEVELOPMENT_BUILD = false;
const BUILD_CHANNEL = "stable";

View File

@ -28,6 +28,7 @@ namespace pocketmine\level\format;
use pocketmine\block\BlockFactory;
use pocketmine\entity\Entity;
use pocketmine\level\biome\Biome;
use pocketmine\level\Level;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag;
@ -35,13 +36,20 @@ use pocketmine\nbt\tag\StringTag;
use pocketmine\Player;
use pocketmine\tile\Spawnable;
use pocketmine\tile\Tile;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\Binary;
use pocketmine\utils\BinaryStream;
use pocketmine\world\format\PalettedBlockArray;
use function array_fill;
use function array_filter;
use function array_flip;
use function array_values;
use function assert;
use function chr;
use function count;
use function file_get_contents;
use function is_array;
use function json_decode;
use function ord;
use function pack;
use function str_repeat;
@ -841,10 +849,21 @@ class Chunk{
public function networkSerialize() : string{
$result = "";
$subChunkCount = $this->getSubChunkSendCount();
//TODO: HACK! fill in fake subchunks to make up for the new negative space client-side
for($y = 0; $y < 4; ++$y){
$result .= chr(8); //subchunk version 8
$result .= chr(0); //0 layers - client will treat this as all-air
}
for($y = 0; $y < $subChunkCount; ++$y){
$result .= $this->subChunks[$y]->networkSerialize();
}
$result .= $this->biomeIds . chr(0); //border block array count
//TODO: right now we don't support 3D natively, so we just 3Dify our 2D biomes so they fill the column
$encodedBiomePalette = $this->networkSerializeBiomesAsPalette();
$result .= str_repeat($encodedBiomePalette, 25);
$result .= chr(0); //border block array count
//Border block entry format: 1 byte (4 bits X, 4 bits Z). These are however useless since they crash the regular client.
foreach($this->tiles as $tile){
@ -856,6 +875,49 @@ class Chunk{
return $result;
}
private function networkSerializeBiomesAsPalette() : string{
/** @var string[]|null $biomeIdMap */
static $biomeIdMap = null;
if($biomeIdMap === null){
$biomeIdMapRaw = file_get_contents(\pocketmine\RESOURCE_PATH . '/vanilla/biome_id_map.json');
if($biomeIdMapRaw === false) throw new AssumptionFailedError();
$biomeIdMapDecoded = json_decode($biomeIdMapRaw, true);
if(!is_array($biomeIdMapDecoded)) throw new AssumptionFailedError();
$biomeIdMap = array_flip($biomeIdMapDecoded);
}
$biomePalette = new PalettedBlockArray($this->getBiomeId(0, 0));
for($x = 0; $x < 16; ++$x){
for($z = 0; $z < 16; ++$z){
$biomeId = $this->getBiomeId($x, $z);
if(!isset($biomeIdMap[$biomeId])){
//make sure we aren't sending bogus biomes - the 1.18.0 client crashes if we do this
$biomeId = Biome::OCEAN;
}
for($y = 0; $y < 16; ++$y){
$biomePalette->set($x, $y, $z, $biomeId);
}
}
}
$biomePaletteBitsPerBlock = $biomePalette->getBitsPerBlock();
$encodedBiomePalette =
chr(($biomePaletteBitsPerBlock << 1) | 1) . //the last bit is non-persistence (like for blocks), though it has no effect on biomes since they always use integer IDs
$biomePalette->getWordArray();
//these LSHIFT by 1 uvarints are optimizations: the client expects zigzag varints here
//but since we know they are always unsigned, we can avoid the extra fcall overhead of
//zigzag and just shift directly.
$biomePaletteArray = $biomePalette->getPalette();
if($biomePaletteBitsPerBlock !== 0){
$encodedBiomePalette .= Binary::writeUnsignedVarInt(count($biomePaletteArray) << 1);
}
foreach($biomePaletteArray as $p){
$encodedBiomePalette .= Binary::writeUnsignedVarInt($p << 1);
}
return $encodedBiomePalette;
}
/**
* Fast-serializes the chunk for passing between threads
* TODO: tiles and entities

View File

@ -47,21 +47,18 @@ class ChunkRequestTask extends AsyncTask{
/** @var int */
protected $compressionLevel;
/** @var int */
private $subChunkCount;
public function __construct(Level $level, int $chunkX, int $chunkZ, Chunk $chunk){
$this->levelId = $level->getId();
$this->compressionLevel = $level->getServer()->networkCompressionLevel;
$this->chunk = $chunk->networkSerialize();
$this->chunk = $chunk->fastSerialize();
$this->chunkX = $chunkX;
$this->chunkZ = $chunkZ;
$this->subChunkCount = $chunk->getSubChunkSendCount();
}
public function onRun(){
$pk = LevelChunkPacket::withoutCache($this->chunkX, $this->chunkZ, $this->subChunkCount, $this->chunk);
$chunk = Chunk::fastDeserialize($this->chunk);
$pk = LevelChunkPacket::withoutCache($this->chunkX, $this->chunkZ, $chunk->getSubChunkSendCount() + 4, $chunk->networkSerialize());
$batch = new BatchPacket();
$batch->addPacket($pk);

View File

@ -37,11 +37,11 @@ interface ProtocolInfo{
*/
/** Actual Minecraft: PE protocol version */
public const CURRENT_PROTOCOL = 471;
public const CURRENT_PROTOCOL = 475;
/** Current Minecraft PE version reported by the server. This is usually the earliest currently supported version. */
public const MINECRAFT_VERSION = 'v1.17.40';
public const MINECRAFT_VERSION = 'v1.18.0';
/** Version number sent to clients in ping responses. */
public const MINECRAFT_VERSION_NETWORK = '1.17.40';
public const MINECRAFT_VERSION_NETWORK = '1.18.0';
public const LOGIN_PACKET = 0x01;
public const PLAY_STATUS_PACKET = 0x02;

View File

@ -182,6 +182,8 @@ class StartGamePacket extends DataPacket{
/** @var string */
public $serverSoftwareVersion;
public int $blockPaletteChecksum;
protected function decodePayload(){
$this->entityUniqueId = $this->getEntityUniqueId();
$this->entityRuntimeId = $this->getEntityRuntimeId();
@ -265,6 +267,7 @@ class StartGamePacket extends DataPacket{
$this->multiplayerCorrelationId = $this->getString();
$this->enableNewInventorySystem = $this->getBool();
$this->serverSoftwareVersion = $this->getString();
$this->blockPaletteChecksum = $this->getLLong();
}
protected function encodePayload(){
@ -346,6 +349,7 @@ class StartGamePacket extends DataPacket{
$this->putString($this->multiplayerCorrelationId);
$this->putBool($this->enableNewInventorySystem);
$this->putString($this->serverSoftwareVersion);
$this->putLLong($this->blockPaletteChecksum);
}
public function handle(NetworkSession $session) : bool{

View File

@ -39,8 +39,9 @@ class SubChunkPacket extends DataPacket{
private string $data;
private int $requestResult;
private ?SubChunkPacketHeightMapInfo $heightMapData = null;
private ?int $usedBlobHash = null;
public static function create(int $dimension, int $subChunkX, int $subChunkY, int $subChunkZ, string $data, int $requestResult, ?SubChunkPacketHeightMapInfo $heightMapData) : self{
public static function create(int $dimension, int $subChunkX, int $subChunkY, int $subChunkZ, string $data, int $requestResult, ?SubChunkPacketHeightMapInfo $heightMapData, ?int $usedBlobHash) : self{
$result = new self;
$result->dimension = $dimension;
$result->subChunkX = $subChunkX;
@ -49,6 +50,7 @@ class SubChunkPacket extends DataPacket{
$result->data = $data;
$result->requestResult = $requestResult;
$result->heightMapData = $heightMapData;
$result->usedBlobHash = $usedBlobHash;
return $result;
}
@ -66,6 +68,8 @@ class SubChunkPacket extends DataPacket{
public function getHeightMapData() : ?SubChunkPacketHeightMapInfo{ return $this->heightMapData; }
public function getUsedBlobHash() : ?int{ return $this->usedBlobHash; }
protected function decodePayload() : void{
$this->dimension = $this->getVarInt();
$this->subChunkX = $this->getVarInt();
@ -81,6 +85,7 @@ class SubChunkPacket extends DataPacket{
SubChunkPacketHeightMapType::ALL_TOO_LOW => SubChunkPacketHeightMapInfo::allTooLow(),
default => throw new \UnexpectedValueException("Unknown heightmap data type $heightMapDataType")
};
$this->usedBlobHash = $this->getBool() ? $this->getLLong() : null;
}
protected function encodePayload() : void{
@ -101,6 +106,11 @@ class SubChunkPacket extends DataPacket{
$this->putByte(SubChunkPacketHeightMapType::DATA);
$heightMapData->write($this);
}
$usedBlobHash = $this->usedBlobHash;
$this->putBool($usedBlobHash !== null);
if($usedBlobHash !== null){
$this->putLLong($usedBlobHash);
}
}
public function handle(NetworkSession $handler) : bool{