mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-11 03:58:06 +00:00
Compare commits
39 Commits
4.0.0-BETA
...
4.0.0-BETA
Author | SHA1 | Date | |
---|---|---|---|
d560cf17fc | |||
3f6efd0018 | |||
aea124af74 | |||
8620e67d88 | |||
d5f81fe261 | |||
0aeac3af7d | |||
9931c1d50a | |||
d21a3d8750 | |||
6d62b06ce6 | |||
8be92d16fe | |||
8079ae341a | |||
ba295dc7dc | |||
38325c8573 | |||
f239b077b9 | |||
6f8f460a6c | |||
882df94bcb | |||
4a8ca603a1 | |||
52f0c4f3ed | |||
e2815eed60 | |||
932a88764c | |||
9540193766 | |||
cc23e0b7a1 | |||
1f9400f901 | |||
e5149756a8 | |||
bc18969a09 | |||
c19174a174 | |||
f95142f6b6 | |||
7ace24caab | |||
32f619ac49 | |||
1bb6ac4fb6 | |||
533d3aae8b | |||
52a891ba73 | |||
71b813d4f9 | |||
f2540a72ad | |||
03f13495b7 | |||
7e0f6c02a1 | |||
1bc7869f6e | |||
5556861000 | |||
7dd5d0b593 |
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
|
||||
|
11
.github/workflows/draft-release.yml
vendored
11
.github/workflows/draft-release.yml
vendored
@ -35,17 +35,18 @@ jobs:
|
||||
- name: Install Composer dependencies
|
||||
run: composer install --no-dev --prefer-dist --no-interaction --ignore-platform-reqs
|
||||
|
||||
- name: Patch VersionInfo
|
||||
- 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"
|
||||
sed -i "s/const BUILD_NUMBER = 0/const BUILD_NUMBER = ${BUILD_NUMBER}/" src/VersionInfo.php
|
||||
echo ::set-output name=BUILD_NUMBER::$BUILD_NUMBER
|
||||
|
||||
- name: Minify BedrockData JSON files
|
||||
run: php vendor/pocketmine/bedrock-data/.minify_json.php
|
||||
|
||||
- name: Build PocketMine-MP.phar
|
||||
run: php -dphar.readonly=0 build/server-phar.php --git ${{ github.sha }}
|
||||
run: php -dphar.readonly=0 build/server-phar.php --git ${{ github.sha }} --build ${{ steps.build-number.outputs.BUILD_NUMBER }}
|
||||
|
||||
- name: Get PocketMine-MP release version
|
||||
id: get-pm-version
|
||||
@ -56,7 +57,7 @@ jobs:
|
||||
echo ::set-output name=PM_VERSION_MD::$(php -r 'require "vendor/autoload.php"; echo str_replace(".", "", \pocketmine\VersionInfo::BASE_VERSION);')
|
||||
|
||||
- name: Generate build info
|
||||
run: php build/generate-build-info-json.php ${{ github.sha }} ${{ steps.get-pm-version.outputs.PM_VERSION }} ${{ github.repository }} > build_info.json
|
||||
run: php build/generate-build-info-json.php ${{ github.sha }} ${{ steps.get-pm-version.outputs.PM_VERSION }} ${{ github.repository }} ${{ steps.build-number.outputs.BUILD_NUMBER }} > build_info.json
|
||||
|
||||
- name: Upload release artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
|
@ -23,15 +23,15 @@ declare(strict_types=1);
|
||||
|
||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
if(count($argv) !== 4){
|
||||
fwrite(STDERR, "required args: <git hash> <tag name> <github repo (owner/name)>");
|
||||
if(count($argv) !== 5){
|
||||
fwrite(STDERR, "required args: <git hash> <tag name> <github repo (owner/name)> <build number>");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
"php_version" => sprintf("%d.%d", PHP_MAJOR_VERSION, PHP_MINOR_VERSION),
|
||||
"base_version" => \pocketmine\VersionInfo::BASE_VERSION,
|
||||
"build" => \pocketmine\VersionInfo::BUILD_NUMBER,
|
||||
"build" => (int) $argv[4],
|
||||
"is_dev" => \pocketmine\VersionInfo::IS_DEVELOPMENT_BUILD,
|
||||
"channel" => \pocketmine\VersionInfo::BUILD_CHANNEL,
|
||||
"git_commit" => $argv[1],
|
||||
|
Submodule build/php updated: 7a2ab5b922...bd329dba08
@ -134,13 +134,18 @@ function main() : void{
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$opts = getopt("", ["out:", "git:"]);
|
||||
$opts = getopt("", ["out:", "git:", "build:"]);
|
||||
if(isset($opts["git"])){
|
||||
$gitHash = $opts["git"];
|
||||
}else{
|
||||
$gitHash = Git::getRepositoryStatePretty(dirname(__DIR__));
|
||||
echo "Git hash detected as $gitHash" . PHP_EOL;
|
||||
}
|
||||
if(isset($opts["build"])){
|
||||
$build = (int) $opts["build"];
|
||||
}else{
|
||||
$build = 0;
|
||||
}
|
||||
foreach(buildPhar(
|
||||
$opts["out"] ?? getcwd() . DIRECTORY_SEPARATOR . "PocketMine-MP.phar",
|
||||
dirname(__DIR__) . DIRECTORY_SEPARATOR,
|
||||
@ -150,7 +155,8 @@ function main() : void{
|
||||
'vendor'
|
||||
],
|
||||
[
|
||||
'git' => $gitHash
|
||||
'git' => $gitHash,
|
||||
'build' => $build
|
||||
],
|
||||
<<<'STUB'
|
||||
<?php
|
||||
|
@ -28,3 +28,11 @@ Plugin developers should **only** update their required API to this version if y
|
||||
|
||||
# 3.25.4
|
||||
- Fixed a long-standing issue with `Player->removeWindow()` breaking inventory UIs on the client.
|
||||
|
||||
# 3.25.5
|
||||
- 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.
|
@ -1748,3 +1748,20 @@ Released 25th November 2021.
|
||||
|
||||
### Utils
|
||||
- `Utils::parseDocComment()` now allows `-` in tag names.
|
||||
|
||||
# 4.0.0-BETA14
|
||||
Released 30th November 2021.
|
||||
|
||||
## General
|
||||
- The server will now log an EMERGENCY-level message when `forceShutdown()` is used for any other reason than a graceful shutdown.
|
||||
- The server will now attempt to translate invalid blocks to valid equivalents when loading chunks. This fixes many issues with `update!` blocks appearing in worlds, particularly ghost structures (these would appear when world editors previously erased some blocks by setting their IDs but not metadata).
|
||||
|
||||
## Fixes
|
||||
- Fixed `ConsoleReaderThread` spawning many zombie processes when running a server inside a Docker container.
|
||||
|
||||
# 4.0.0-BETA15
|
||||
Released 30th November 2021.
|
||||
|
||||
## General
|
||||
- Added support for Minecraft: Bedrock 1.18.0
|
||||
- Removed support for earlier versions.
|
||||
|
@ -7,7 +7,7 @@
|
||||
"require": {
|
||||
"php": "^8.0",
|
||||
"php-64bit": "*",
|
||||
"ext-chunkutils2": "^0.3.0",
|
||||
"ext-chunkutils2": "^0.3.1",
|
||||
"ext-crypto": "^0.3.1",
|
||||
"ext-ctype": "*",
|
||||
"ext-curl": "*",
|
||||
@ -34,8 +34,8 @@
|
||||
"adhocore/json-comment": "^1.1",
|
||||
"fgrosse/phpasn1": "^2.3",
|
||||
"netresearch/jsonmapper": "^4.0",
|
||||
"pocketmine/bedrock-data": "^1.4.0+bedrock-1.17.40",
|
||||
"pocketmine/bedrock-protocol": "^6.0.0+bedrock-1.17.40",
|
||||
"pocketmine/bedrock-data": "^1.5.0+bedrock-1.18.0",
|
||||
"pocketmine/bedrock-protocol": "^7.0.0+bedrock-1.18.0",
|
||||
"pocketmine/binaryutils": "^0.2.1",
|
||||
"pocketmine/callback-validator": "^1.0.2",
|
||||
"pocketmine/classloader": "^0.2.0",
|
||||
@ -79,7 +79,7 @@
|
||||
"sort-packages": true
|
||||
},
|
||||
"scripts": {
|
||||
"make-devtools": "@php -dphar.readonly=0 tests/plugins/DevTools/src/DevTools/ConsoleScript.php --make tests/plugins/DevTools --out plugins/DevTools.phar",
|
||||
"make-devtools": "@php -dphar.readonly=0 tests/plugins/DevTools/src/ConsoleScript.php --make tests/plugins/DevTools --out plugins/DevTools.phar",
|
||||
"make-server": [
|
||||
"@composer install --no-dev --classmap-authoritative --ignore-platform-reqs",
|
||||
"@php -dphar.readonly=0 build/server-phar.php"
|
||||
|
40
composer.lock
generated
40
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": "fb545e4c8e17b0b07e8e20986b64e5a6",
|
||||
"content-hash": "b515e7eebbf12a6251d2df817ce56dbc",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/json-comment",
|
||||
@ -249,16 +249,16 @@
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-data",
|
||||
"version": "1.4.0+bedrock-1.17.40",
|
||||
"version": "1.5.0+bedrock-1.18.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BedrockData.git",
|
||||
"reference": "f29b7be8fa3046d2ee4c6421485b97b3f5b07774"
|
||||
"reference": "482c679aa5ed0b81c088c2b1ff0b8110a94c8a6c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/f29b7be8fa3046d2ee4c6421485b97b3f5b07774",
|
||||
"reference": "f29b7be8fa3046d2ee4c6421485b97b3f5b07774",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/482c679aa5ed0b81c088c2b1ff0b8110a94c8a6c",
|
||||
"reference": "482c679aa5ed0b81c088c2b1ff0b8110a94c8a6c",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
@ -269,22 +269,22 @@
|
||||
"description": "Blobs of data generated from Minecraft: Bedrock Edition, used by PocketMine-MP",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/BedrockData/issues",
|
||||
"source": "https://github.com/pmmp/BedrockData/tree/bedrock-1.17.40"
|
||||
"source": "https://github.com/pmmp/BedrockData/tree/bedrock-1.18.0"
|
||||
},
|
||||
"time": "2021-10-19T16:55:41+00:00"
|
||||
"time": "2021-11-30T18:30:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-protocol",
|
||||
"version": "6.0.0+bedrock-1.17.40",
|
||||
"version": "7.0.0+bedrock-1.18.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BedrockProtocol.git",
|
||||
"reference": "906bafec4fc41f548749ce01d120902b25c1bbfe"
|
||||
"reference": "040a883a4abb8c9b93114d5278cb5fecc635da82"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/906bafec4fc41f548749ce01d120902b25c1bbfe",
|
||||
"reference": "906bafec4fc41f548749ce01d120902b25c1bbfe",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/040a883a4abb8c9b93114d5278cb5fecc635da82",
|
||||
"reference": "040a883a4abb8c9b93114d5278cb5fecc635da82",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -316,9 +316,9 @@
|
||||
"description": "An implementation of the Minecraft: Bedrock Edition protocol in PHP",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/BedrockProtocol/issues",
|
||||
"source": "https://github.com/pmmp/BedrockProtocol/tree/6.0.0+bedrock-1.17.40"
|
||||
"source": "https://github.com/pmmp/BedrockProtocol/tree/7.0.0+bedrock-1.18.0"
|
||||
},
|
||||
"time": "2021-11-21T20:56:18+00:00"
|
||||
"time": "2021-11-30T19:02:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/binaryutils",
|
||||
@ -533,16 +533,16 @@
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/locale-data",
|
||||
"version": "2.0.17",
|
||||
"version": "2.0.20",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/Language.git",
|
||||
"reference": "30e4a64d5674bac556c4e2b9842b19a981471ac4"
|
||||
"reference": "a6e4eb22587e0014f6d658732cf633262723f8d3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/Language/zipball/30e4a64d5674bac556c4e2b9842b19a981471ac4",
|
||||
"reference": "30e4a64d5674bac556c4e2b9842b19a981471ac4",
|
||||
"url": "https://api.github.com/repos/pmmp/Language/zipball/a6e4eb22587e0014f6d658732cf633262723f8d3",
|
||||
"reference": "a6e4eb22587e0014f6d658732cf633262723f8d3",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
@ -550,9 +550,9 @@
|
||||
"description": "Language resources used by PocketMine-MP",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/Language/issues",
|
||||
"source": "https://github.com/pmmp/Language/tree/2.0.17"
|
||||
"source": "https://github.com/pmmp/Language/tree/2.0.20"
|
||||
},
|
||||
"time": "2021-11-12T00:59:39+00:00"
|
||||
"time": "2021-11-25T20:56:12+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/log",
|
||||
@ -3510,7 +3510,7 @@
|
||||
"platform": {
|
||||
"php": "^8.0",
|
||||
"php-64bit": "*",
|
||||
"ext-chunkutils2": "^0.3.0",
|
||||
"ext-chunkutils2": "^0.3.1",
|
||||
"ext-crypto": "^0.3.1",
|
||||
"ext-ctype": "*",
|
||||
"ext-curl": "*",
|
||||
|
@ -1413,6 +1413,9 @@ class Server{
|
||||
echo "\x1b]0;\x07";
|
||||
}
|
||||
|
||||
if($this->isRunning){
|
||||
$this->logger->emergency("Forcing server shutdown");
|
||||
}
|
||||
try{
|
||||
if(!$this->isRunning()){
|
||||
$this->sendUsage(SendUsageTask::TYPE_CLOSE);
|
||||
|
@ -25,13 +25,14 @@ namespace pocketmine;
|
||||
|
||||
use pocketmine\utils\Git;
|
||||
use pocketmine\utils\VersionString;
|
||||
use function is_array;
|
||||
use function is_int;
|
||||
use function str_repeat;
|
||||
|
||||
final class VersionInfo{
|
||||
public const NAME = "PocketMine-MP";
|
||||
public const BASE_VERSION = "4.0.0-BETA13";
|
||||
public const BASE_VERSION = "4.0.0-BETA15";
|
||||
public const IS_DEVELOPMENT_BUILD = false;
|
||||
public const BUILD_NUMBER = 0;
|
||||
public const BUILD_CHANNEL = "beta";
|
||||
|
||||
private function __construct(){
|
||||
@ -61,12 +62,29 @@ final class VersionInfo{
|
||||
return self::$gitHash;
|
||||
}
|
||||
|
||||
private static ?int $buildNumber = null;
|
||||
|
||||
public static function BUILD_NUMBER() : int{
|
||||
if(self::$buildNumber === null){
|
||||
self::$buildNumber = 0;
|
||||
if(\Phar::running(true) !== ""){
|
||||
$phar = new \Phar(\Phar::running(false));
|
||||
$meta = $phar->getMetadata();
|
||||
if(is_array($meta) && isset($meta["build"]) && is_int($meta["build"])){
|
||||
self::$buildNumber = $meta["build"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return self::$buildNumber;
|
||||
}
|
||||
|
||||
/** @var VersionString|null */
|
||||
private static $fullVersion = null;
|
||||
|
||||
public static function VERSION() : VersionString{
|
||||
if(self::$fullVersion === null){
|
||||
self::$fullVersion = new VersionString(self::BASE_VERSION, self::IS_DEVELOPMENT_BUILD, self::BUILD_NUMBER);
|
||||
self::$fullVersion = new VersionString(self::BASE_VERSION, self::IS_DEVELOPMENT_BUILD, self::BUILD_NUMBER());
|
||||
}
|
||||
return self::$fullVersion;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -27,14 +27,24 @@ use pocketmine\utils\AssumptionFailedError;
|
||||
use function fclose;
|
||||
use function fgets;
|
||||
use function fopen;
|
||||
use function is_resource;
|
||||
use function stream_select;
|
||||
use function trim;
|
||||
use function usleep;
|
||||
|
||||
final class ConsoleReader{
|
||||
/** @var resource */
|
||||
private $stdin;
|
||||
|
||||
public function __construct(){
|
||||
$this->initStdin();
|
||||
}
|
||||
|
||||
private function initStdin() : void{
|
||||
if(is_resource($this->stdin)){
|
||||
fclose($this->stdin);
|
||||
}
|
||||
|
||||
$stdin = fopen("php://stdin", "r");
|
||||
if($stdin === false) throw new AssumptionFailedError("Opening stdin should never fail");
|
||||
$this->stdin = $stdin;
|
||||
@ -42,19 +52,23 @@ final class ConsoleReader{
|
||||
|
||||
/**
|
||||
* Reads a line from the console and adds it to the buffer. This method may block the thread.
|
||||
* @throws ConsoleReaderException
|
||||
*/
|
||||
public function readLine() : ?string{
|
||||
if(!is_resource($this->stdin)){
|
||||
$this->initStdin();
|
||||
}
|
||||
|
||||
$r = [$this->stdin];
|
||||
$w = $e = null;
|
||||
if(($count = stream_select($r, $w, $e, 0, 200000)) === 0){ //nothing changed in 200000 microseconds
|
||||
return null;
|
||||
}elseif($count === false){ //stream error
|
||||
throw new ConsoleReaderException("Unexpected EOF on select()");
|
||||
return null;
|
||||
}
|
||||
|
||||
if(($raw = fgets($this->stdin)) === false){ //broken pipe or EOF
|
||||
throw new ConsoleReaderException("Unexpected EOF on fgets()");
|
||||
usleep(200000); //prevent CPU waste if it's end of pipe
|
||||
return null; //loop back round
|
||||
}
|
||||
|
||||
$line = trim($raw);
|
||||
|
@ -45,14 +45,7 @@ if($socket === false){
|
||||
}
|
||||
$consoleReader = new ConsoleReader();
|
||||
while(!feof($socket)){
|
||||
try{
|
||||
$line = $consoleReader->readLine();
|
||||
}catch(ConsoleReaderException $e){
|
||||
//Encountered unexpected EOF. This might be because the user did something stupid, or because the parent process
|
||||
//has died. In either case, commit suicide. If the parent process is still alive, it will start a new console
|
||||
//reader.
|
||||
break;
|
||||
}
|
||||
$line = $consoleReader->readLine();
|
||||
if(@fwrite($socket, ($line ?? "") . "\n") === false){
|
||||
//Always send even if there's no line, to check if the parent is alive
|
||||
//If the parent process was terminated forcibly, it won't close the connection properly, so feof() will return
|
||||
|
@ -31,6 +31,7 @@ use function base64_encode;
|
||||
use function fgets;
|
||||
use function fopen;
|
||||
use function preg_replace;
|
||||
use function proc_close;
|
||||
use function proc_open;
|
||||
use function proc_terminate;
|
||||
use function sprintf;
|
||||
@ -130,6 +131,7 @@ final class ConsoleReaderThread extends Thread{
|
||||
//gets stuck in a blocking fgets() read because stream_select() is a hunk of junk (hence the separate process in
|
||||
//the first place).
|
||||
proc_terminate($sub);
|
||||
proc_close($sub);
|
||||
stream_socket_shutdown($client, STREAM_SHUT_RDWR);
|
||||
}
|
||||
|
||||
|
@ -279,7 +279,7 @@ class CrashDump{
|
||||
$this->data->general = new CrashDumpDataGeneral(
|
||||
name: $this->server->getName(),
|
||||
base_version: VersionInfo::BASE_VERSION,
|
||||
build: VersionInfo::BUILD_NUMBER,
|
||||
build: VersionInfo::BUILD_NUMBER(),
|
||||
is_dev: VersionInfo::IS_DEVELOPMENT_BUILD,
|
||||
protocol: ProtocolInfo::CURRENT_PROTOCOL,
|
||||
git: VersionInfo::GIT_HASH(),
|
||||
|
@ -21,8 +21,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\console;
|
||||
namespace pocketmine\data\bedrock;
|
||||
|
||||
final class ConsoleReaderException extends \RuntimeException{
|
||||
use pocketmine\utils\SingletonTrait;
|
||||
use Webmozart\PathUtil\Path;
|
||||
|
||||
final class LegacyBiomeIdToStringIdMap extends LegacyToStringBidirectionalIdMap{
|
||||
use SingletonTrait;
|
||||
|
||||
public function __construct(){
|
||||
parent::__construct(Path::join(\pocketmine\BEDROCK_DATA_PATH, 'biome_id_map.json'));
|
||||
}
|
||||
}
|
@ -252,6 +252,7 @@ class ItemFactory{
|
||||
$this->register(new Steak(new ItemIdentifier(ItemIds::STEAK, 0), "Steak"));
|
||||
$this->register(new Stick(new ItemIdentifier(ItemIds::STICK, 0), "Stick"));
|
||||
$this->register(new StringItem(new ItemIdentifier(ItemIds::STRING, 0), "String"));
|
||||
$this->register(new SweetBerries(new ItemIdentifier(ItemIds::SWEET_BERRIES, 0), "Sweet Berries"));
|
||||
$this->register(new Totem(new ItemIdentifier(ItemIds::TOTEM, 0), "Totem of Undying"));
|
||||
$this->register(new WheatSeeds(new ItemIdentifier(ItemIds::WHEAT_SEEDS, 0), "Wheat Seeds"));
|
||||
$this->register(new WritableBook(new ItemIdentifier(ItemIds::WRITABLE_BOOK, 0), "Book & Quill"));
|
||||
@ -327,7 +328,6 @@ class ItemFactory{
|
||||
//TODO: minecraft:shield
|
||||
//TODO: minecraft:sparkler
|
||||
//TODO: minecraft:spawn_egg
|
||||
$this->register(new SweetBerries(new ItemIdentifier(ItemIds::SWEET_BERRIES, 0), "Sweet Berries"));
|
||||
//TODO: minecraft:tnt_minecart
|
||||
//TODO: minecraft:trident
|
||||
//TODO: minecraft:turtle_helmet
|
||||
|
@ -69,7 +69,7 @@ class ChunkRequestTask extends AsyncTask{
|
||||
|
||||
public function onRun() : void{
|
||||
$chunk = FastChunkSerializer::deserializeTerrain($this->chunk);
|
||||
$subCount = ChunkSerializer::getSubChunkCount($chunk);
|
||||
$subCount = ChunkSerializer::getSubChunkCount($chunk) + ChunkSerializer::LOWER_PADDING_SIZE;
|
||||
$encoderContext = new PacketSerializerContext(GlobalItemTypeDictionary::getInstance()->getDictionary());
|
||||
$payload = ChunkSerializer::serializeFullChunk($chunk, RuntimeBlockMapping::getInstance(), $encoderContext, $this->tiles);
|
||||
$this->setResult($this->compressor->compress(PacketBatch::fromPackets($encoderContext, LevelChunkPacket::create($this->chunkX, $this->chunkZ, $subCount, null, $payload))->getBuffer()));
|
||||
|
@ -104,6 +104,7 @@ class PreSpawnPacketHandler extends PacketHandler{
|
||||
false,
|
||||
sprintf("%s %s", VersionInfo::NAME, VersionInfo::VERSION()->getFullVersion(true)),
|
||||
[],
|
||||
0,
|
||||
GlobalItemTypeDictionary::getInstance()->getDictionary()->getEntries()
|
||||
));
|
||||
|
||||
|
@ -24,6 +24,8 @@ declare(strict_types=1);
|
||||
namespace pocketmine\network\mcpe\serializer;
|
||||
|
||||
use pocketmine\block\tile\Spawnable;
|
||||
use pocketmine\data\bedrock\BiomeIds;
|
||||
use pocketmine\data\bedrock\LegacyBiomeIdToStringIdMap;
|
||||
use pocketmine\nbt\TreeRoot;
|
||||
use pocketmine\network\mcpe\convert\RuntimeBlockMapping;
|
||||
use pocketmine\network\mcpe\protocol\serializer\NetworkNbtSerializer;
|
||||
@ -32,10 +34,14 @@ use pocketmine\network\mcpe\protocol\serializer\PacketSerializerContext;
|
||||
use pocketmine\utils\Binary;
|
||||
use pocketmine\utils\BinaryStream;
|
||||
use pocketmine\world\format\Chunk;
|
||||
use pocketmine\world\format\PalettedBlockArray;
|
||||
use pocketmine\world\format\SubChunk;
|
||||
use function chr;
|
||||
use function count;
|
||||
use function str_repeat;
|
||||
|
||||
final class ChunkSerializer{
|
||||
public const LOWER_PADDING_SIZE = 4;
|
||||
|
||||
private function __construct(){
|
||||
//NOOP
|
||||
@ -58,11 +64,22 @@ final class ChunkSerializer{
|
||||
|
||||
public static function serializeFullChunk(Chunk $chunk, RuntimeBlockMapping $blockMapper, PacketSerializerContext $encoderContext, ?string $tiles = null) : string{
|
||||
$stream = PacketSerializer::encoder($encoderContext);
|
||||
|
||||
//TODO: HACK! fill in fake subchunks to make up for the new negative space client-side
|
||||
for($y = 0; $y < self::LOWER_PADDING_SIZE; $y++){
|
||||
$stream->putByte(8); //subchunk version 8
|
||||
$stream->putByte(0); //0 layers - client will treat this as all-air
|
||||
}
|
||||
|
||||
$subChunkCount = self::getSubChunkCount($chunk);
|
||||
for($y = Chunk::MIN_SUBCHUNK_INDEX, $writtenCount = 0; $writtenCount < $subChunkCount; ++$y, ++$writtenCount){
|
||||
self::serializeSubChunk($chunk->getSubChunk($y), $blockMapper, $stream, false);
|
||||
}
|
||||
$stream->put($chunk->getBiomeIdArray());
|
||||
|
||||
//TODO: right now we don't support 3D natively, so we just 3Dify our 2D biomes so they fill the column
|
||||
$encodedBiomePalette = self::serializeBiomesAsPalette($chunk);
|
||||
$stream->put(str_repeat($encodedBiomePalette, 25));
|
||||
|
||||
$stream->putByte(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.
|
||||
|
||||
@ -116,4 +133,39 @@ final class ChunkSerializer{
|
||||
|
||||
return $stream->getBuffer();
|
||||
}
|
||||
|
||||
private static function serializeBiomesAsPalette(Chunk $chunk) : string{
|
||||
$biomeIdMap = LegacyBiomeIdToStringIdMap::getInstance();
|
||||
$biomePalette = new PalettedBlockArray($chunk->getBiomeId(0, 0));
|
||||
for($x = 0; $x < 16; ++$x){
|
||||
for($z = 0; $z < 16; ++$z){
|
||||
$biomeId = $chunk->getBiomeId($x, $z);
|
||||
if($biomeIdMap->legacyToString($biomeId) === null){
|
||||
//make sure we aren't sending bogus biomes - the 1.18.0 client crashes if we do this
|
||||
$biomeId = BiomeIds::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;
|
||||
}
|
||||
}
|
||||
|
@ -2466,6 +2466,27 @@ class World implements ChunkManager{
|
||||
|
||||
private function initChunk(int $chunkX, int $chunkZ, ChunkData $chunkData) : void{
|
||||
$logger = new \PrefixedLogger($this->logger, "Loading chunk $chunkX $chunkZ");
|
||||
|
||||
$this->timings->syncChunkLoadFixInvalidBlocks->startTiming();
|
||||
$blockFactory = BlockFactory::getInstance();
|
||||
$invalidBlocks = 0;
|
||||
foreach($chunkData->getChunk()->getSubChunks() as $subChunk){
|
||||
foreach($subChunk->getBlockLayers() as $blockLayer){
|
||||
foreach($blockLayer->getPalette() as $blockStateId){
|
||||
$mappedStateId = $blockFactory->getMappedStateId($blockStateId);
|
||||
if($mappedStateId !== $blockStateId){
|
||||
$blockLayer->replaceAll($blockStateId, $mappedStateId);
|
||||
$invalidBlocks++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if($invalidBlocks > 0){
|
||||
$logger->debug("Fixed $invalidBlocks invalid blockstates");
|
||||
$chunkData->getChunk()->setTerrainDirtyFlag(Chunk::DIRTY_FLAG_BLOCKS, true);
|
||||
}
|
||||
$this->timings->syncChunkLoadFixInvalidBlocks->stopTiming();
|
||||
|
||||
if(count($chunkData->getEntityNBT()) !== 0){
|
||||
$this->timings->syncChunkLoadEntities->startTiming();
|
||||
$entityFactory = EntityFactory::getInstance();
|
||||
|
@ -45,6 +45,7 @@ class WorldTimings{
|
||||
|
||||
public TimingsHandler $syncChunkLoad;
|
||||
public TimingsHandler $syncChunkLoadData;
|
||||
public TimingsHandler $syncChunkLoadFixInvalidBlocks;
|
||||
public TimingsHandler $syncChunkLoadEntities;
|
||||
public TimingsHandler $syncChunkLoadTileEntities;
|
||||
public TimingsHandler $syncChunkSave;
|
||||
@ -64,14 +65,15 @@ class WorldTimings{
|
||||
$this->entityTick = new TimingsHandler(Timings::INCLUDED_BY_OTHER_TIMINGS_PREFIX . $name . "Tick Entities");
|
||||
|
||||
Timings::init(); //make sure the timers we want are available
|
||||
$this->syncChunkSend = new TimingsHandler("** " . $name . "Player Send Chunks", Timings::$playerChunkSend);
|
||||
$this->syncChunkSendPrepare = new TimingsHandler("** " . $name . "Player Send Chunk Prepare", Timings::$playerChunkSend);
|
||||
$this->syncChunkSend = new TimingsHandler(Timings::INCLUDED_BY_OTHER_TIMINGS_PREFIX . $name . "Player Send Chunks", Timings::$playerChunkSend);
|
||||
$this->syncChunkSendPrepare = new TimingsHandler(Timings::INCLUDED_BY_OTHER_TIMINGS_PREFIX . $name . "Player Send Chunk Prepare", Timings::$playerChunkSend);
|
||||
|
||||
$this->syncChunkLoad = new TimingsHandler("** " . $name . "Chunk Load", Timings::$worldLoad);
|
||||
$this->syncChunkLoadData = new TimingsHandler("** " . $name . "Chunk Load - Data");
|
||||
$this->syncChunkLoadEntities = new TimingsHandler("** " . $name . "Chunk Load - Entities");
|
||||
$this->syncChunkLoadTileEntities = new TimingsHandler("** " . $name . "Chunk Load - TileEntities");
|
||||
$this->syncChunkSave = new TimingsHandler("** " . $name . "Chunk Save", Timings::$worldSave);
|
||||
$this->syncChunkLoad = new TimingsHandler(Timings::INCLUDED_BY_OTHER_TIMINGS_PREFIX . $name . "Chunk Load", Timings::$worldLoad);
|
||||
$this->syncChunkLoadData = new TimingsHandler(Timings::INCLUDED_BY_OTHER_TIMINGS_PREFIX . $name . "Chunk Load - Data");
|
||||
$this->syncChunkLoadFixInvalidBlocks = new TimingsHandler(Timings::INCLUDED_BY_OTHER_TIMINGS_PREFIX . $name . "Chunk Load - Fix Invalid Blocks");
|
||||
$this->syncChunkLoadEntities = new TimingsHandler(Timings::INCLUDED_BY_OTHER_TIMINGS_PREFIX . $name . "Chunk Load - Entities");
|
||||
$this->syncChunkLoadTileEntities = new TimingsHandler(Timings::INCLUDED_BY_OTHER_TIMINGS_PREFIX . $name . "Chunk Load - TileEntities");
|
||||
$this->syncChunkSave = new TimingsHandler(Timings::INCLUDED_BY_OTHER_TIMINGS_PREFIX . $name . "Chunk Save", Timings::$worldSave);
|
||||
|
||||
$this->doTick = new TimingsHandler($name . "World Tick");
|
||||
}
|
||||
|
@ -505,6 +505,11 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/command/defaults/TimingsCommand.php
|
||||
|
||||
-
|
||||
message: "#^Call to function is_resource\\(\\) with resource will always evaluate to true\\.$#"
|
||||
count: 2
|
||||
path: ../../../src/console/ConsoleReader.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$json of function json_decode expects string, string\\|false given\\.$#"
|
||||
count: 1
|
||||
|
@ -107,7 +107,6 @@ class BlockTest extends TestCase{
|
||||
public function blockGetProvider() : array{
|
||||
return [
|
||||
[BlockLegacyIds::STONE, 5],
|
||||
[BlockLegacyIds::STONE, 15],
|
||||
[BlockLegacyIds::GOLD_BLOCK, 0],
|
||||
[BlockLegacyIds::WOODEN_PLANKS, 5],
|
||||
[BlockLegacyIds::SAND, 0],
|
||||
|
File diff suppressed because one or more lines are too long
Submodule tests/plugins/DevTools updated: db184c2563...6af57741e6
@ -20,7 +20,7 @@ mkdir "$DATA_DIR"
|
||||
mkdir "$PLUGINS_DIR"
|
||||
|
||||
cd tests/plugins/DevTools
|
||||
php -dphar.readonly=0 ./src/DevTools/ConsoleScript.php --make ./ --relative ./ --out "$PLUGINS_DIR/DevTools.phar"
|
||||
php -dphar.readonly=0 ./src/ConsoleScript.php --make ./ --relative ./ --out "$PLUGINS_DIR/DevTools.phar"
|
||||
cd ../../..
|
||||
composer make-server
|
||||
|
||||
|
Reference in New Issue
Block a user