mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-08 10:53:05 +00:00
Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
0aeac3af7d | |||
9931c1d50a | |||
8079ae341a | |||
ba295dc7dc | |||
c19174a174 | |||
f95142f6b6 | |||
7ace24caab | |||
32f619ac49 |
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -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
|
||||
|
2
.github/workflows/draft-release.yml
vendored
2
.github/workflows/draft-release.yml
vendored
@ -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
|
||||
|
||||
|
Submodule build/php updated: a59722c676...bd329dba08
@ -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
11
changelogs/3.26.md
Normal 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.
|
@ -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
3
composer.lock
generated
@ -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": "*",
|
||||
|
@ -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());
|
||||
|
@ -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.";
|
||||
}
|
||||
|
@ -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";
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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{
|
||||
|
@ -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{
|
||||
|
Submodule src/pocketmine/resources/vanilla updated: f29b7be8fa...482c679aa5
Reference in New Issue
Block a user