mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-13 12:55:06 +00:00
Compare commits
146 Commits
Author | SHA1 | Date | |
---|---|---|---|
13f28d8454 | |||
5a97c378fc | |||
e5d62ec901 | |||
cfd975009e | |||
73257ffde7 | |||
8252bea699 | |||
ea935a1af5 | |||
e8a5fa8a37 | |||
db734675d8 | |||
6ede56015d | |||
5334099fbf | |||
82e9072223 | |||
2c11742f9e | |||
bd4a63b668 | |||
cd36af46bf | |||
aa7d55e21d | |||
31e8efa6d1 | |||
facca13139 | |||
fffeeddca6 | |||
e6ba3ce8a6 | |||
11cae2f0c0 | |||
f5a18df835 | |||
1cc7027f92 | |||
8776b71d63 | |||
0b9d0f3cdc | |||
e419d76367 | |||
36cde9f352 | |||
05c602a044 | |||
0db7e57a15 | |||
205e47c0c4 | |||
e328d00cca | |||
ccbcc14600 | |||
e544bc0d4b | |||
fd27227cc7 | |||
b42966f61b | |||
ca86ec2ec2 | |||
97b6183404 | |||
0587d03c03 | |||
c7f1b605f2 | |||
f069df65a8 | |||
1e624e7bb9 | |||
f16a530849 | |||
7137b8a8a4 | |||
ab57914322 | |||
260869c0d5 | |||
9135877da1 | |||
07cb603231 | |||
f59094e6d6 | |||
d8acae5495 | |||
239fe909be | |||
c22576a266 | |||
bac788fd00 | |||
f6d96c5827 | |||
b1458db47b | |||
2d2c9379cd | |||
3400771770 | |||
e12ecaf629 | |||
1303cbfe02 | |||
ad4a211cba | |||
d1e56c4611 | |||
d9bbab54f4 | |||
07cf4eb7a9 | |||
50a7663369 | |||
651ef500a3 | |||
30f2e75278 | |||
2cfc25b4f8 | |||
5bded9cff8 | |||
5816ff85ba | |||
8f7d8347ee | |||
3614d9a78d | |||
818d0e19ab | |||
17720041a3 | |||
c329ff7d4f | |||
8794292788 | |||
0a39e580e9 | |||
c4580dd56d | |||
fab81d28bc | |||
039478223e | |||
64b5db4bf2 | |||
c85f4256c7 | |||
1192b8bdf1 | |||
6dcd2a4ece | |||
3fff0a0656 | |||
e1e1bfa5e3 | |||
1eedac87b2 | |||
cda3e6f4dc | |||
e6a58e2690 | |||
27350c4673 | |||
0d5704b156 | |||
f355044626 | |||
4794ba236a | |||
6490a49c70 | |||
5cd7e11b29 | |||
08e3b8ffdc | |||
9232f4509c | |||
cef77907c6 | |||
06ec8b8397 | |||
ee08286eca | |||
a83211f96a | |||
0b3c4ee496 | |||
54de518634 | |||
a908197907 | |||
3e23a568ca | |||
dadc5c1b87 | |||
a37d740111 | |||
2de0ec02ba | |||
d83820477f | |||
8726604899 | |||
9cbe378e8c | |||
494660102e | |||
216138a37e | |||
b08c38f8f9 | |||
911b6feaf9 | |||
2cb6990698 | |||
f7d66613df | |||
95c32d26df | |||
9e1f6a2486 | |||
76994f15ac | |||
cf73d74bd0 | |||
37a8d95464 | |||
9a4b72add5 | |||
919534d978 | |||
cb598155a4 | |||
00888fdc55 | |||
77795ae3bc | |||
f39fc7e525 | |||
77f7595e0e | |||
e8d3a25028 | |||
1370930ea9 | |||
70c3008b7b | |||
46930b98b7 | |||
92be8c8ec0 | |||
62069bc7af | |||
26230c1f9b | |||
a9fafbc5eb | |||
b8778cb791 | |||
73c5fe5cf9 | |||
b3cfa5a3a0 | |||
6127a02a8b | |||
dbca36e5e2 | |||
1171bae691 | |||
494f8e8251 | |||
3c9af56e06 | |||
40a2211a5a | |||
0196aa21d7 | |||
833f3e574b |
@ -36,7 +36,6 @@ use function system;
|
|||||||
use const pocketmine\BASE_VERSION;
|
use const pocketmine\BASE_VERSION;
|
||||||
use const STDIN;
|
use const STDIN;
|
||||||
|
|
||||||
require_once dirname(__DIR__) . '/src/pocketmine/VersionInfo.php';
|
|
||||||
require_once dirname(__DIR__) . '/vendor/autoload.php';
|
require_once dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
|
||||||
if(isset($argv[1])){
|
if(isset($argv[1])){
|
||||||
|
147
build/server-phar.php
Normal file
147
build/server-phar.php
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\build\server_phar;
|
||||||
|
|
||||||
|
use pocketmine\utils\Git;
|
||||||
|
|
||||||
|
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string[] $strings
|
||||||
|
* @param string|null $delim
|
||||||
|
*
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
function preg_quote_array(array $strings, string $delim = null) : array{
|
||||||
|
return array_map(function(string $str) use ($delim) : string{ return preg_quote($str, $delim); }, $strings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $pharPath
|
||||||
|
* @param string $basePath
|
||||||
|
* @param string[] $includedPaths
|
||||||
|
* @param array $metadata
|
||||||
|
* @param string $stub
|
||||||
|
* @param int $signatureAlgo
|
||||||
|
* @param int|null $compression
|
||||||
|
*
|
||||||
|
* @return \Generator|string[]
|
||||||
|
*/
|
||||||
|
function buildPhar(string $pharPath, string $basePath, array $includedPaths, array $metadata, string $stub, int $signatureAlgo = \Phar::SHA1, ?int $compression = null){
|
||||||
|
$basePath = rtrim(str_replace("/", DIRECTORY_SEPARATOR, $basePath), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
||||||
|
$includedPaths = array_map(function($path){
|
||||||
|
return rtrim(str_replace("/", DIRECTORY_SEPARATOR, $path), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
||||||
|
}, $includedPaths);
|
||||||
|
yield "Creating output file $pharPath";
|
||||||
|
if(file_exists($pharPath)){
|
||||||
|
yield "Phar file already exists, overwriting...";
|
||||||
|
try{
|
||||||
|
\Phar::unlinkArchive($pharPath);
|
||||||
|
}catch(\PharException $e){
|
||||||
|
//unlinkArchive() doesn't like dodgy phars
|
||||||
|
unlink($pharPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
yield "Adding files...";
|
||||||
|
|
||||||
|
$start = microtime(true);
|
||||||
|
$phar = new \Phar($pharPath);
|
||||||
|
$phar->setMetadata($metadata);
|
||||||
|
$phar->setStub($stub);
|
||||||
|
$phar->setSignatureAlgorithm($signatureAlgo);
|
||||||
|
$phar->startBuffering();
|
||||||
|
|
||||||
|
//If paths contain any of these, they will be excluded
|
||||||
|
$excludedSubstrings = preg_quote_array([
|
||||||
|
realpath($pharPath), //don't add the phar to itself
|
||||||
|
], '/');
|
||||||
|
|
||||||
|
$folderPatterns = preg_quote_array([
|
||||||
|
DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR,
|
||||||
|
DIRECTORY_SEPARATOR . '.' //"Hidden" files, git dirs etc
|
||||||
|
], '/');
|
||||||
|
|
||||||
|
//Only exclude these within the basedir, otherwise the project won't get built if it itself is in a directory that matches these patterns
|
||||||
|
$basePattern = preg_quote(rtrim($basePath, DIRECTORY_SEPARATOR), '/');
|
||||||
|
foreach($folderPatterns as $p){
|
||||||
|
$excludedSubstrings[] = $basePattern . '.*' . $p;
|
||||||
|
}
|
||||||
|
|
||||||
|
$regex = sprintf('/^(?!.*(%s))^%s(%s).*/i',
|
||||||
|
implode('|', $excludedSubstrings), //String may not contain any of these substrings
|
||||||
|
preg_quote($basePath, '/'), //String must start with this path...
|
||||||
|
implode('|', preg_quote_array($includedPaths, '/')) //... and must be followed by one of these relative paths, if any were specified. If none, this will produce a null capturing group which will allow anything.
|
||||||
|
);
|
||||||
|
|
||||||
|
$directory = new \RecursiveDirectoryIterator($basePath, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS | \FilesystemIterator::CURRENT_AS_PATHNAME); //can't use fileinfo because of symlinks
|
||||||
|
$iterator = new \RecursiveIteratorIterator($directory);
|
||||||
|
$regexIterator = new \RegexIterator($iterator, $regex);
|
||||||
|
|
||||||
|
$count = count($phar->buildFromIterator($regexIterator, $basePath));
|
||||||
|
yield "Added $count files";
|
||||||
|
|
||||||
|
if($compression !== null){
|
||||||
|
yield "Checking for compressible files...";
|
||||||
|
foreach($phar as $file => $finfo){
|
||||||
|
/** @var \PharFileInfo $finfo */
|
||||||
|
if($finfo->getSize() > (1024 * 512)){
|
||||||
|
yield "Compressing " . $finfo->getFilename();
|
||||||
|
$finfo->compress($compression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$phar->stopBuffering();
|
||||||
|
|
||||||
|
yield "Done in " . round(microtime(true) - $start, 3) . "s";
|
||||||
|
}
|
||||||
|
|
||||||
|
function main() : void{
|
||||||
|
if(ini_get("phar.readonly") == 1){
|
||||||
|
echo "Set phar.readonly to 0 with -dphar.readonly=0" . PHP_EOL;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$opts = getopt("", ["out:"]);
|
||||||
|
$gitHash = Git::getRepositoryStatePretty(dirname(__DIR__));
|
||||||
|
echo "Git hash detected as $gitHash" . PHP_EOL;
|
||||||
|
foreach(buildPhar(
|
||||||
|
$opts["out"] ?? getcwd() . DIRECTORY_SEPARATOR . "PocketMine-MP.phar",
|
||||||
|
dirname(__DIR__) . DIRECTORY_SEPARATOR,
|
||||||
|
[
|
||||||
|
'src',
|
||||||
|
'vendor'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'git' => $gitHash
|
||||||
|
],
|
||||||
|
'<?php require("phar://" . __FILE__ . "/src/pocketmine/PocketMine.php"); __HALT_COMPILER();'
|
||||||
|
) as $line){
|
||||||
|
echo $line . PHP_EOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!defined('pocketmine\_PHPSTAN_ANALYSIS')){
|
||||||
|
main();
|
||||||
|
}
|
@ -9,3 +9,47 @@ Plugin developers should **only** update their required API to this version if y
|
|||||||
# 3.11.0
|
# 3.11.0
|
||||||
- Added support for Minecraft: Bedrock Edition 1.14.0
|
- Added support for Minecraft: Bedrock Edition 1.14.0
|
||||||
- Removed compatibility with 1.13.0
|
- Removed compatibility with 1.13.0
|
||||||
|
|
||||||
|
# 3.11.1
|
||||||
|
- Fixed blocks with incorrect properties when placed or interacted with.
|
||||||
|
|
||||||
|
# 3.11.2
|
||||||
|
## Core
|
||||||
|
- PHPStan 0.12.3 with level 5 is now used for automated static analysis.
|
||||||
|
- Fixed a possible crash when plugins override the `EnderChest` tile class with something incompatible.
|
||||||
|
- Fixed disconnected players being considered as never played.
|
||||||
|
- Fixed enchantments with IDs outside the range 0-255 in item NBT crashing the server.
|
||||||
|
- Fixed particles rendering incorrectly.
|
||||||
|
- Timings handlers are no longer able to underflow; they now throw exceptions when attempting to be stopped more times than they were started.
|
||||||
|
- Fixed explosion rays getting stuck in empty subchunks (possible incorrect behaviour in large caves).
|
||||||
|
- Fixed bad tile/entity NBT data being propagated from world providers in some cases.
|
||||||
|
- Fixed a possible crash when detecting timezone on CentOS.
|
||||||
|
- Fixed many cases of incorrectly documented types in the API found by PHPStan.
|
||||||
|
- Generation tasks no longer assume that generator instances stored in TLS are always valid, fixing a possible crash.
|
||||||
|
|
||||||
|
## Protocol
|
||||||
|
- Fixed skin animation image corruption in LoginPacket handling caused by incorrect data handling.
|
||||||
|
- Fixed skin animation extra data not being decoded from LoginPacket.
|
||||||
|
- `SkinImage` now throws `InvalidArgumentException` if it receives an unexpected amount of bytes for the given image heigh/width.
|
||||||
|
- Fixed broken code in `PlayerAuthInputPacket::create()`.
|
||||||
|
- Removed some dead constants from `NetworkInventoryAction`.
|
||||||
|
|
||||||
|
# 3.11.3
|
||||||
|
- Fixed some PHPStan false-positives in release builds.
|
||||||
|
- Git hash is now correctly detected for source builds when the working directory is not the repository root.
|
||||||
|
- Added a specialized build script `build/server-phar.php` for creating server phars.
|
||||||
|
- Fixed timings crashing the server.
|
||||||
|
- Timings chains now work correctly.
|
||||||
|
- Fixed some minor timing errors in chained timings.
|
||||||
|
- Forcing resource packs no longer causes removal of client-sided resource packs. If this behaviour is desired, use a vanilla resource pack at the bottom of your resource stack (as was necessary for non-forced packs).
|
||||||
|
- Added documentation to the API to clarify that effect durations are in ticks.
|
||||||
|
|
||||||
|
# 3.11.4
|
||||||
|
- Fixed performance issue in leaf decay.
|
||||||
|
- Fixed entity position desync when entities stop moving, but still have velocity on the client.
|
||||||
|
- Fixed a crash when encountering truncated `level.dat` files in LevelDB worlds.
|
||||||
|
- Core code is now analyzed using PHPStan level 6.
|
||||||
|
- The core constants `pocketmine\PATH` and `pocketmine\RESOURCE_PATH` are now unconditionally available when including the Composer autoloader.
|
||||||
|
- Populate type information in lots of places where it was previously missing; this will improve the quality of static analysis for plugins.
|
||||||
|
- `MainLogger::logException()` now logs previous exceptions recursively.
|
||||||
|
- `MainLogger::logException()` now always logs exceptions as `critical`.
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
"ext-zip": "*",
|
"ext-zip": "*",
|
||||||
"ext-zlib": ">=1.2.11",
|
"ext-zlib": ">=1.2.11",
|
||||||
"pocketmine/raklib": "^0.12.5",
|
"pocketmine/raklib": "^0.12.5",
|
||||||
"pocketmine/spl": "^0.3.0",
|
"pocketmine/spl": "^0.3.5",
|
||||||
"pocketmine/binaryutils": "^0.1.9",
|
"pocketmine/binaryutils": "^0.1.9",
|
||||||
"pocketmine/nbt": "^0.2.10",
|
"pocketmine/nbt": "^0.2.10",
|
||||||
"pocketmine/math": "^0.2.0",
|
"pocketmine/math": "^0.2.0",
|
||||||
@ -38,6 +38,7 @@
|
|||||||
"": ["src"]
|
"": ["src"]
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
|
"src/pocketmine/CoreConstants.php",
|
||||||
"src/pocketmine/GlobalConstants.php",
|
"src/pocketmine/GlobalConstants.php",
|
||||||
"src/pocketmine/VersionInfo.php"
|
"src/pocketmine/VersionInfo.php"
|
||||||
]
|
]
|
||||||
|
14
composer.lock
generated
14
composer.lock
generated
@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "377d9e0ab5f1a9a4ef9b664706d26f5b",
|
"content-hash": "f693f278b3bb9c1d266079fa17644dcb",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "adhocore/json-comment",
|
"name": "adhocore/json-comment",
|
||||||
@ -276,16 +276,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "pocketmine/spl",
|
"name": "pocketmine/spl",
|
||||||
"version": "0.3.3",
|
"version": "0.3.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/pmmp/SPL.git",
|
"url": "https://github.com/pmmp/SPL.git",
|
||||||
"reference": "94d4df142fe837ba836e9348dd00209e4bdcc307"
|
"reference": "88052c67d3df2cc2dc2d99ebeae3d7ede3fc64ab"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/pmmp/SPL/zipball/94d4df142fe837ba836e9348dd00209e4bdcc307",
|
"url": "https://api.github.com/repos/pmmp/SPL/zipball/88052c67d3df2cc2dc2d99ebeae3d7ede3fc64ab",
|
||||||
"reference": "94d4df142fe837ba836e9348dd00209e4bdcc307",
|
"reference": "88052c67d3df2cc2dc2d99ebeae3d7ede3fc64ab",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
@ -299,10 +299,10 @@
|
|||||||
],
|
],
|
||||||
"description": "Standard library files required by PocketMine-MP and related projects",
|
"description": "Standard library files required by PocketMine-MP and related projects",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/pmmp/SPL/tree/0.3.3",
|
"source": "https://github.com/pmmp/SPL/tree/0.3",
|
||||||
"issues": "https://github.com/pmmp/SPL/issues"
|
"issues": "https://github.com/pmmp/SPL/issues"
|
||||||
},
|
},
|
||||||
"time": "2019-10-28T11:41:20+00:00"
|
"time": "2020-01-14T16:23:26+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [],
|
"packages-dev": [],
|
||||||
|
@ -1,18 +1,25 @@
|
|||||||
includes:
|
includes:
|
||||||
|
- tests/phpstan/configs/com-dotnet-magic.neon
|
||||||
|
- tests/phpstan/configs/custom-leveldb.neon
|
||||||
- tests/phpstan/configs/gc-hacks.neon
|
- tests/phpstan/configs/gc-hacks.neon
|
||||||
- tests/phpstan/configs/optional-com-dotnet.neon
|
|
||||||
- tests/phpstan/configs/optional-leveldb.neon
|
|
||||||
- tests/phpstan/configs/phpstan-bugs.neon
|
- tests/phpstan/configs/phpstan-bugs.neon
|
||||||
- tests/phpstan/configs/pthreads-bugs.neon
|
- tests/phpstan/configs/pthreads-bugs.neon
|
||||||
|
- tests/phpstan/configs/runtime-type-checks.neon
|
||||||
|
|
||||||
parameters:
|
parameters:
|
||||||
level: 3
|
level: 6
|
||||||
autoload_files:
|
autoload_files:
|
||||||
- tests/phpstan/bootstrap.php
|
- tests/phpstan/bootstrap.php
|
||||||
- src/pocketmine/PocketMine.php
|
- src/pocketmine/PocketMine.php
|
||||||
|
- build/server-phar.php
|
||||||
paths:
|
paths:
|
||||||
- src
|
- src
|
||||||
|
- build/server-phar.php
|
||||||
|
dynamicConstantNames:
|
||||||
|
- pocketmine\IS_DEVELOPMENT_BUILD
|
||||||
|
- pocketmine\DEBUG
|
||||||
reportUnmatchedIgnoredErrors: false #no other way to silence platform-specific non-warnings
|
reportUnmatchedIgnoredErrors: false #no other way to silence platform-specific non-warnings
|
||||||
|
checkMissingIterableValueType: false #TODO: pthreads Threaded base for too many things, fix this later
|
||||||
ignoreErrors:
|
ignoreErrors:
|
||||||
-
|
-
|
||||||
message: "#^Cannot instantiate interface pocketmine\\\\level\\\\format\\\\io\\\\LevelProvider\\.$#"
|
message: "#^Cannot instantiate interface pocketmine\\\\level\\\\format\\\\io\\\\LevelProvider\\.$#"
|
||||||
@ -80,11 +87,6 @@ parameters:
|
|||||||
count: 1
|
count: 1
|
||||||
path: src/pocketmine/level/generator/normal/Normal.php
|
path: src/pocketmine/level/generator/normal/Normal.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Used constant pocketmine\\\\RESOURCE_PATH not found\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/pocketmine/network/mcpe/protocol/StartGamePacket.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Constructor of class pocketmine\\\\scheduler\\\\TaskScheduler has an unused parameter \\$logger\\.$#"
|
message: "#^Constructor of class pocketmine\\\\scheduler\\\\TaskScheduler has an unused parameter \\$logger\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
@ -102,18 +104,10 @@ parameters:
|
|||||||
message: "#^Constant pocketmine\\\\GIT_COMMIT not found\\.$#"
|
message: "#^Constant pocketmine\\\\GIT_COMMIT not found\\.$#"
|
||||||
path: src
|
path: src
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Constant pocketmine\\\\PATH not found\\.$#"
|
|
||||||
path: src
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Constant pocketmine\\\\PLUGIN_PATH not found\\.$#"
|
message: "#^Constant pocketmine\\\\PLUGIN_PATH not found\\.$#"
|
||||||
path: src
|
path: src
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Constant pocketmine\\\\RESOURCE_PATH not found\\.$#"
|
|
||||||
path: src
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Constant pocketmine\\\\START_TIME not found\\.$#"
|
message: "#^Constant pocketmine\\\\START_TIME not found\\.$#"
|
||||||
path: src
|
path: src
|
||||||
|
@ -25,12 +25,16 @@ namespace pocketmine;
|
|||||||
|
|
||||||
abstract class Collectable extends \Threaded{
|
abstract class Collectable extends \Threaded{
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
private $isGarbage = false;
|
private $isGarbage = false;
|
||||||
|
|
||||||
public function isGarbage() : bool{
|
public function isGarbage() : bool{
|
||||||
return $this->isGarbage;
|
return $this->isGarbage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function setGarbage(){
|
public function setGarbage(){
|
||||||
$this->isGarbage = true;
|
$this->isGarbage = true;
|
||||||
}
|
}
|
||||||
|
33
src/pocketmine/CoreConstants.php
Normal file
33
src/pocketmine/CoreConstants.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine;
|
||||||
|
|
||||||
|
// composer autoload doesn't use require_once and also pthreads can inherit things
|
||||||
|
if(defined('pocketmine\_CORE_CONSTANTS_INCLUDED')){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
define('pocketmine\_CORE_CONSTANTS_INCLUDED', true);
|
||||||
|
|
||||||
|
define('pocketmine\PATH', dirname(__DIR__, 2) . '/');
|
||||||
|
define('pocketmine\RESOURCE_PATH', __DIR__ . '/resources/');
|
@ -96,8 +96,11 @@ class CrashDump{
|
|||||||
|
|
||||||
/** @var Server */
|
/** @var Server */
|
||||||
private $server;
|
private $server;
|
||||||
|
/** @var resource */
|
||||||
private $fp;
|
private $fp;
|
||||||
|
/** @var int */
|
||||||
private $time;
|
private $time;
|
||||||
|
/** @var mixed[] */
|
||||||
private $data = [];
|
private $data = [];
|
||||||
/** @var string */
|
/** @var string */
|
||||||
private $encodedData = "";
|
private $encodedData = "";
|
||||||
@ -134,6 +137,9 @@ class CrashDump{
|
|||||||
return $this->path;
|
return $this->path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function getEncodedData(){
|
public function getEncodedData(){
|
||||||
return $this->encodedData;
|
return $this->encodedData;
|
||||||
}
|
}
|
||||||
@ -142,7 +148,7 @@ class CrashDump{
|
|||||||
return $this->data;
|
return $this->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function encodeData(){
|
private function encodeData() : void{
|
||||||
$this->addLine();
|
$this->addLine();
|
||||||
$this->addLine("----------------------REPORT THE DATA BELOW THIS LINE-----------------------");
|
$this->addLine("----------------------REPORT THE DATA BELOW THIS LINE-----------------------");
|
||||||
$this->addLine();
|
$this->addLine();
|
||||||
@ -158,7 +164,7 @@ class CrashDump{
|
|||||||
$this->addLine("===END CRASH DUMP===");
|
$this->addLine("===END CRASH DUMP===");
|
||||||
}
|
}
|
||||||
|
|
||||||
private function pluginsData(){
|
private function pluginsData() : void{
|
||||||
if($this->server->getPluginManager() instanceof PluginManager){
|
if($this->server->getPluginManager() instanceof PluginManager){
|
||||||
$this->addLine();
|
$this->addLine();
|
||||||
$this->addLine("Loaded plugins:");
|
$this->addLine("Loaded plugins:");
|
||||||
@ -182,7 +188,7 @@ class CrashDump{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function extraData(){
|
private function extraData() : void{
|
||||||
global $argv;
|
global $argv;
|
||||||
|
|
||||||
if($this->server->getProperty("auto-report.send-settings", true) !== false){
|
if($this->server->getProperty("auto-report.send-settings", true) !== false){
|
||||||
@ -209,7 +215,7 @@ class CrashDump{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function baseCrash(){
|
private function baseCrash() : void{
|
||||||
global $lastExceptionError, $lastError;
|
global $lastExceptionError, $lastError;
|
||||||
|
|
||||||
if(isset($lastExceptionError)){
|
if(isset($lastExceptionError)){
|
||||||
@ -317,7 +323,7 @@ class CrashDump{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function generalData(){
|
private function generalData() : void{
|
||||||
$version = new VersionString(\pocketmine\BASE_VERSION, \pocketmine\IS_DEVELOPMENT_BUILD, \pocketmine\BUILD_NUMBER);
|
$version = new VersionString(\pocketmine\BASE_VERSION, \pocketmine\IS_DEVELOPMENT_BUILD, \pocketmine\BUILD_NUMBER);
|
||||||
$this->data["general"] = [];
|
$this->data["general"] = [];
|
||||||
$this->data["general"]["name"] = $this->server->getName();
|
$this->data["general"]["name"] = $this->server->getName();
|
||||||
@ -340,10 +346,20 @@ class CrashDump{
|
|||||||
$this->addLine("OS : " . PHP_OS . ", " . Utils::getOS());
|
$this->addLine("OS : " . PHP_OS . ", " . Utils::getOS());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $line
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function addLine($line = ""){
|
public function addLine($line = ""){
|
||||||
fwrite($this->fp, $line . PHP_EOL);
|
fwrite($this->fp, $line . PHP_EOL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $str
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function add($str){
|
public function add($str){
|
||||||
fwrite($this->fp, $str);
|
fwrite($this->fp, $str);
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,8 @@ interface IPlayer extends ServerOperator{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bool $banned
|
* @param bool $banned
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setBanned(bool $banned);
|
public function setBanned(bool $banned);
|
||||||
|
|
||||||
@ -54,6 +56,8 @@ interface IPlayer extends ServerOperator{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bool $value
|
* @param bool $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setWhitelisted(bool $value);
|
public function setWhitelisted(bool $value);
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ class MemoryManager{
|
|||||||
$this->init();
|
$this->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function init(){
|
private function init() : void{
|
||||||
$this->memoryLimit = ((int) $this->server->getProperty("memory.main-limit", 0)) * 1024 * 1024;
|
$this->memoryLimit = ((int) $this->server->getProperty("memory.main-limit", 0)) * 1024 * 1024;
|
||||||
|
|
||||||
$defaultMemory = 1024;
|
$defaultMemory = 1024;
|
||||||
@ -201,6 +201,8 @@ class MemoryManager{
|
|||||||
* @param int $limit
|
* @param int $limit
|
||||||
* @param bool $global
|
* @param bool $global
|
||||||
* @param int $triggerCount
|
* @param int $triggerCount
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function trigger(int $memory, int $limit, bool $global = false, int $triggerCount = 0){
|
public function trigger(int $memory, int $limit, bool $global = false, int $triggerCount = 0){
|
||||||
$this->server->getLogger()->debug(sprintf("[Memory Manager] %sLow memory triggered, limit %gMB, using %gMB",
|
$this->server->getLogger()->debug(sprintf("[Memory Manager] %sLow memory triggered, limit %gMB, using %gMB",
|
||||||
@ -230,6 +232,8 @@ class MemoryManager{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Called every tick to update the memory manager state.
|
* Called every tick to update the memory manager state.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function check(){
|
public function check(){
|
||||||
Timings::$memoryManagerTimer->startTiming();
|
Timings::$memoryManagerTimer->startTiming();
|
||||||
@ -297,6 +301,8 @@ class MemoryManager{
|
|||||||
* @param string $outputFolder
|
* @param string $outputFolder
|
||||||
* @param int $maxNesting
|
* @param int $maxNesting
|
||||||
* @param int $maxStringSize
|
* @param int $maxStringSize
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function dumpServerMemory(string $outputFolder, int $maxNesting, int $maxStringSize){
|
public function dumpServerMemory(string $outputFolder, int $maxNesting, int $maxStringSize){
|
||||||
$this->server->getLogger()->notice("[Dump] After the memory dump is done, the server might crash");
|
$this->server->getLogger()->notice("[Dump] After the memory dump is done, the server might crash");
|
||||||
@ -319,6 +325,7 @@ class MemoryManager{
|
|||||||
* @param int $maxStringSize
|
* @param int $maxStringSize
|
||||||
* @param \Logger $logger
|
* @param \Logger $logger
|
||||||
*
|
*
|
||||||
|
* @return void
|
||||||
* @throws \ReflectionException
|
* @throws \ReflectionException
|
||||||
*/
|
*/
|
||||||
public static function dumpMemory($startingObject, string $outputFolder, int $maxNesting, int $maxStringSize, \Logger $logger){
|
public static function dumpMemory($startingObject, string $outputFolder, int $maxNesting, int $maxStringSize, \Logger $logger){
|
||||||
@ -472,14 +479,14 @@ class MemoryManager{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mixed $from
|
* @param mixed $from
|
||||||
* @param mixed &$data
|
* @param mixed $data reference parameter
|
||||||
* @param object[] &$objects
|
* @param object[] $objects reference parameter
|
||||||
* @param int[] &$refCounts
|
* @param int[] $refCounts reference parameter
|
||||||
* @param int $recursion
|
* @param int $recursion
|
||||||
* @param int $maxNesting
|
* @param int $maxNesting
|
||||||
* @param int $maxStringSize
|
* @param int $maxStringSize
|
||||||
*/
|
*/
|
||||||
private static function continueDump($from, &$data, array &$objects, array &$refCounts, int $recursion, int $maxNesting, int $maxStringSize){
|
private static function continueDump($from, &$data, array &$objects, array &$refCounts, int $recursion, int $maxNesting, int $maxStringSize) : void{
|
||||||
if($maxNesting <= 0){
|
if($maxNesting <= 0){
|
||||||
$data = "(error) NESTING LIMIT REACHED";
|
$data = "(error) NESTING LIMIT REACHED";
|
||||||
return;
|
return;
|
||||||
|
@ -57,6 +57,9 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
|||||||
return $this->name;
|
return $this->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Server
|
||||||
|
*/
|
||||||
public function getServer(){
|
public function getServer(){
|
||||||
return $this->server;
|
return $this->server;
|
||||||
}
|
}
|
||||||
|
@ -282,6 +282,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
/** @var string */
|
/** @var string */
|
||||||
protected $xuid = "";
|
protected $xuid = "";
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
protected $windowCnt = 2;
|
protected $windowCnt = 2;
|
||||||
/** @var int[] */
|
/** @var int[] */
|
||||||
protected $windows = [];
|
protected $windows = [];
|
||||||
@ -464,17 +465,22 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getFirstPlayed(){
|
public function getFirstPlayed(){
|
||||||
return $this->namedtag instanceof CompoundTag ? $this->namedtag->getLong("firstPlayed", 0, true) : null;
|
return $this->namedtag->getLong("firstPlayed", 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLastPlayed(){
|
public function getLastPlayed(){
|
||||||
return $this->namedtag instanceof CompoundTag ? $this->namedtag->getLong("lastPlayed", 0, true) : null;
|
return $this->namedtag->getLong("lastPlayed", 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hasPlayedBefore() : bool{
|
public function hasPlayedBefore() : bool{
|
||||||
return $this->playedBefore;
|
return $this->playedBefore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function setAllowFlight(bool $value){
|
public function setAllowFlight(bool $value){
|
||||||
$this->allowFlight = $value;
|
$this->allowFlight = $value;
|
||||||
$this->sendSettings();
|
$this->sendSettings();
|
||||||
@ -484,6 +490,11 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
return $this->allowFlight;
|
return $this->allowFlight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function setFlying(bool $value){
|
public function setFlying(bool $value){
|
||||||
if($this->flying !== $value){
|
if($this->flying !== $value){
|
||||||
$this->flying = $value;
|
$this->flying = $value;
|
||||||
@ -496,6 +507,11 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
return $this->flying;
|
return $this->flying;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function setAutoJump(bool $value){
|
public function setAutoJump(bool $value){
|
||||||
$this->autoJump = $value;
|
$this->autoJump = $value;
|
||||||
$this->sendSettings();
|
$this->sendSettings();
|
||||||
@ -509,6 +525,11 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
return $this->allowMovementCheats;
|
return $this->allowMovementCheats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function setAllowMovementCheats(bool $value = true){
|
public function setAllowMovementCheats(bool $value = true){
|
||||||
$this->allowMovementCheats = $value;
|
$this->allowMovementCheats = $value;
|
||||||
}
|
}
|
||||||
@ -538,6 +559,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bool $remove
|
* @param bool $remove
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setRemoveFormat(bool $remove = true){
|
public function setRemoveFormat(bool $remove = true){
|
||||||
$this->removeFormat = $remove;
|
$this->removeFormat = $remove;
|
||||||
@ -565,6 +588,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Player $player
|
* @param Player $player
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function hidePlayer(Player $player){
|
public function hidePlayer(Player $player){
|
||||||
if($player === $this){
|
if($player === $this){
|
||||||
@ -576,6 +601,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Player $player
|
* @param Player $player
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function showPlayer(Player $player){
|
public function showPlayer(Player $player){
|
||||||
if($player === $this){
|
if($player === $this){
|
||||||
@ -604,6 +631,11 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
return $this->viewDistance;
|
return $this->viewDistance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $distance
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function setViewDistance(int $distance){
|
public function setViewDistance(int $distance){
|
||||||
$this->viewDistance = $this->server->getAllowedViewDistance($distance);
|
$this->viewDistance = $this->server->getAllowedViewDistance($distance);
|
||||||
|
|
||||||
@ -634,6 +666,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bool $value
|
* @param bool $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setOp(bool $value){
|
public function setOp(bool $value){
|
||||||
if($value === $this->isOp()){
|
if($value === $this->isOp()){
|
||||||
@ -685,6 +719,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param PermissionAttachment $attachment
|
* @param PermissionAttachment $attachment
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function removeAttachment(PermissionAttachment $attachment){
|
public function removeAttachment(PermissionAttachment $attachment){
|
||||||
$this->perm->removeAttachment($attachment);
|
$this->perm->removeAttachment($attachment);
|
||||||
@ -720,6 +756,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
return $this->perm->getEffectivePermissions();
|
return $this->perm->getEffectivePermissions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function sendCommandData(){
|
public function sendCommandData(){
|
||||||
$pk = new AvailableCommandsPacket();
|
$pk = new AvailableCommandsPacket();
|
||||||
foreach($this->server->getCommandMap()->getCommands() as $name => $command){
|
foreach($this->server->getCommandMap()->getCommands() as $name => $command){
|
||||||
@ -741,7 +780,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
$data->overloads[0][0] = $parameter;
|
$data->overloads[0][0] = $parameter;
|
||||||
|
|
||||||
$aliases = $command->getAliases();
|
$aliases = $command->getAliases();
|
||||||
if(!empty($aliases)){
|
if(count($aliases) > 0){
|
||||||
if(!in_array($data->commandName, $aliases, true)){
|
if(!in_array($data->commandName, $aliases, true)){
|
||||||
//work around a client bug which makes the original name not show when aliases are used
|
//work around a client bug which makes the original name not show when aliases are used
|
||||||
$aliases[] = $data->commandName;
|
$aliases[] = $data->commandName;
|
||||||
@ -817,6 +856,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $name
|
* @param string $name
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setDisplayName(string $name){
|
public function setDisplayName(string $name){
|
||||||
$this->displayName = $name;
|
$this->displayName = $name;
|
||||||
@ -902,6 +943,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
* @internal Plugins should not use this method.
|
* @internal Plugins should not use this method.
|
||||||
*
|
*
|
||||||
* @param int $pingMS
|
* @param int $pingMS
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function updatePing(int $pingMS){
|
public function updatePing(int $pingMS){
|
||||||
$this->lastPingMeasure = $pingMS;
|
$this->lastPingMeasure = $pingMS;
|
||||||
@ -926,6 +969,11 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
return $this->getGenericFlag(self::DATA_FLAG_ACTION) and $this->startAction > -1;
|
return $this->getGenericFlag(self::DATA_FLAG_ACTION) and $this->startAction > -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function setUsingItem(bool $value){
|
public function setUsingItem(bool $value){
|
||||||
$this->startAction = $value ? $this->server->getTick() : -1;
|
$this->startAction = $value ? $this->server->getTick() : -1;
|
||||||
$this->setGenericFlag(self::DATA_FLAG_ACTION, $value);
|
$this->setGenericFlag(self::DATA_FLAG_ACTION, $value);
|
||||||
@ -995,6 +1043,13 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $x
|
||||||
|
* @param int $z
|
||||||
|
* @param Level|null $level
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
protected function unloadChunk(int $x, int $z, Level $level = null){
|
protected function unloadChunk(int $x, int $z, Level $level = null){
|
||||||
$level = $level ?? $this->level;
|
$level = $level ?? $this->level;
|
||||||
$index = Level::chunkHash($x, $z);
|
$index = Level::chunkHash($x, $z);
|
||||||
@ -1011,6 +1066,13 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
unset($this->loadQueue[$index]);
|
unset($this->loadQueue[$index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $x
|
||||||
|
* @param int $z
|
||||||
|
* @param BatchPacket $payload
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function sendChunk(int $x, int $z, BatchPacket $payload){
|
public function sendChunk(int $x, int $z, BatchPacket $payload){
|
||||||
if(!$this->isConnected()){
|
if(!$this->isConnected()){
|
||||||
return;
|
return;
|
||||||
@ -1033,6 +1095,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
protected function sendNextChunk(){
|
protected function sendNextChunk(){
|
||||||
if(!$this->isConnected()){
|
if(!$this->isConnected()){
|
||||||
return;
|
return;
|
||||||
@ -1067,6 +1132,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
Timings::$playerChunkSendTimer->stopTiming();
|
Timings::$playerChunkSendTimer->stopTiming();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function doFirstSpawn(){
|
public function doFirstSpawn(){
|
||||||
if($this->spawned){
|
if($this->spawned){
|
||||||
return; //avoid player spawning twice (this can only happen on 3.x with a custom malicious client)
|
return; //avoid player spawning twice (this can only happen on 3.x with a custom malicious client)
|
||||||
@ -1116,6 +1184,12 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Vector3 $pos
|
||||||
|
* @param int $respawnState
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
protected function sendRespawnPacket(Vector3 $pos, int $respawnState = RespawnPacket::SEARCHING_FOR_SPAWN){
|
protected function sendRespawnPacket(Vector3 $pos, int $respawnState = RespawnPacket::SEARCHING_FOR_SPAWN){
|
||||||
$pk = new RespawnPacket();
|
$pk = new RespawnPacket();
|
||||||
$pk->position = $pos->add(0, $this->baseOffset, 0);
|
$pk->position = $pos->add(0, $this->baseOffset, 0);
|
||||||
@ -1208,7 +1282,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->loadQueue = $newOrder;
|
$this->loadQueue = $newOrder;
|
||||||
if(!empty($this->loadQueue) or !empty($unloadChunks)){
|
if(count($this->loadQueue) > 0 or count($unloadChunks) > 0){
|
||||||
$pk = new NetworkChunkPublisherUpdatePacket();
|
$pk = new NetworkChunkPublisherUpdatePacket();
|
||||||
$pk->x = $this->getFloorX();
|
$pk->x = $this->getFloorX();
|
||||||
$pk->y = $this->getFloorY();
|
$pk->y = $this->getFloorY();
|
||||||
@ -1245,6 +1319,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
* Position object
|
* Position object
|
||||||
*
|
*
|
||||||
* @param Vector3|Position $pos
|
* @param Vector3|Position $pos
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setSpawn(Vector3 $pos){
|
public function setSpawn(Vector3 $pos){
|
||||||
if(!($pos instanceof Position)){
|
if(!($pos instanceof Position)){
|
||||||
@ -1304,6 +1380,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function stopSleep(){
|
public function stopSleep(){
|
||||||
if($this->sleeping instanceof Vector3){
|
if($this->sleeping instanceof Vector3){
|
||||||
$b = $this->level->getBlock($this->sleeping);
|
$b = $this->level->getBlock($this->sleeping);
|
||||||
@ -1367,6 +1446,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $achievementId
|
* @param string $achievementId
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function removeAchievement(string $achievementId){
|
public function removeAchievement(string $achievementId){
|
||||||
if($this->hasAchievement($achievementId)){
|
if($this->hasAchievement($achievementId)){
|
||||||
@ -1455,6 +1536,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
* Sends the player's gamemode to the client.
|
* Sends the player's gamemode to the client.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function sendGamemode(){
|
public function sendGamemode(){
|
||||||
$pk = new SetPlayerGameTypePacket();
|
$pk = new SetPlayerGameTypePacket();
|
||||||
@ -1464,6 +1547,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends all the option flags
|
* Sends all the option flags
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function sendSettings(){
|
public function sendSettings(){
|
||||||
$pk = new AdventureSettingsPacket();
|
$pk = new AdventureSettingsPacket();
|
||||||
@ -1569,6 +1654,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
return false; //currently has no server-side movement
|
return false; //currently has no server-side movement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
protected function checkNearEntities(){
|
protected function checkNearEntities(){
|
||||||
foreach($this->level->getNearbyEntities($this->boundingBox->expandedCopy(1, 0.5, 1), $this) as $entity){
|
foreach($this->level->getNearbyEntities($this->boundingBox->expandedCopy(1, 0.5, 1), $this) as $entity){
|
||||||
$entity->scheduleUpdate();
|
$entity->scheduleUpdate();
|
||||||
@ -1581,6 +1669,11 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $tickDiff
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
protected function processMovement(int $tickDiff){
|
protected function processMovement(int $tickDiff){
|
||||||
if(!$this->isAlive() or !$this->spawned or $this->newPosition === null or $this->isSleeping()){
|
if(!$this->isAlive() or !$this->spawned or $this->newPosition === null or $this->isSleeping()){
|
||||||
return;
|
return;
|
||||||
@ -1723,6 +1816,11 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $sendAll
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function sendAttributes(bool $sendAll = false){
|
public function sendAttributes(bool $sendAll = false){
|
||||||
$entries = $sendAll ? $this->attributeMap->getAll() : $this->attributeMap->needSend();
|
$entries = $sendAll ? $this->attributeMap->getAll() : $this->attributeMap->needSend();
|
||||||
if(count($entries) > 0){
|
if(count($entries) > 0){
|
||||||
@ -1828,6 +1926,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
$this->dataPacket($pk);
|
$this->dataPacket($pk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function checkNetwork(){
|
public function checkNetwork(){
|
||||||
if(!$this->isOnline()){
|
if(!$this->isOnline()){
|
||||||
return;
|
return;
|
||||||
@ -1921,7 +2022,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
|
|
||||||
$animations = [];
|
$animations = [];
|
||||||
foreach($packet->clientData["AnimatedImageData"] as $animation){
|
foreach($packet->clientData["AnimatedImageData"] as $animation){
|
||||||
$animations[] = new SkinAnimation(new SkinImage($animation["ImageHeight"], $animation["ImageWidth"], $animation["Image"]), $animation["Type"], $animation["Frames"]);
|
$animations[] = new SkinAnimation(new SkinImage($animation["ImageHeight"], $animation["ImageWidth"], base64_decode($animation["Image"], true)), $animation["Type"], $animation["Frames"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$skinData = new SkinData(
|
$skinData = new SkinData(
|
||||||
@ -1931,7 +2032,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
$animations,
|
$animations,
|
||||||
new SkinImage($packet->clientData["CapeImageHeight"], $packet->clientData["CapeImageWidth"], base64_decode($packet->clientData["CapeData"] ?? "")),
|
new SkinImage($packet->clientData["CapeImageHeight"], $packet->clientData["CapeImageWidth"], base64_decode($packet->clientData["CapeData"] ?? "")),
|
||||||
base64_decode($packet->clientData["SkinGeometryData"] ?? ""),
|
base64_decode($packet->clientData["SkinGeometryData"] ?? ""),
|
||||||
base64_decode($packet->clientData["AnimationData"] ?? ""),
|
base64_decode($packet->clientData["SkinAnimationData"] ?? ""),
|
||||||
$packet->clientData["PremiumSkin"] ?? false,
|
$packet->clientData["PremiumSkin"] ?? false,
|
||||||
$packet->clientData["PersonaSkin"] ?? false,
|
$packet->clientData["PersonaSkin"] ?? false,
|
||||||
$packet->clientData["CapeOnClassicSkin"] ?? false,
|
$packet->clientData["CapeOnClassicSkin"] ?? false,
|
||||||
@ -1976,6 +2077,12 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $status
|
||||||
|
* @param bool $immediate
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function sendPlayStatus(int $status, bool $immediate = false){
|
public function sendPlayStatus(int $status, bool $immediate = false){
|
||||||
$pk = new PlayStatusPacket();
|
$pk = new PlayStatusPacket();
|
||||||
$pk->status = $status;
|
$pk->status = $status;
|
||||||
@ -2019,6 +2126,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
$this->processLogin();
|
$this->processLogin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
protected function processLogin(){
|
protected function processLogin(){
|
||||||
foreach($this->server->getLoggedInPlayers() as $p){
|
foreach($this->server->getLoggedInPlayers() as $p){
|
||||||
if($p !== $this and ($p->iusername === $this->iusername or $this->getUniqueId()->equals($p->getUniqueId()))){
|
if($p !== $this and ($p->iusername === $this->iusername or $this->getUniqueId()->equals($p->getUniqueId()))){
|
||||||
@ -2118,7 +2228,10 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
$pk = new ResourcePackStackPacket();
|
$pk = new ResourcePackStackPacket();
|
||||||
$manager = $this->server->getResourcePackManager();
|
$manager = $this->server->getResourcePackManager();
|
||||||
$pk->resourcePackStack = $manager->getResourceStack();
|
$pk->resourcePackStack = $manager->getResourceStack();
|
||||||
$pk->mustAccept = $manager->resourcePacksRequired();
|
//we don't force here, because it doesn't have user-facing effects
|
||||||
|
//but it does have an annoying side-effect when true: it makes
|
||||||
|
//the client remove its own non-server-supplied resource packs.
|
||||||
|
$pk->mustAccept = false;
|
||||||
$this->dataPacket($pk);
|
$this->dataPacket($pk);
|
||||||
break;
|
break;
|
||||||
case ResourcePackClientResponsePacket::STATUS_COMPLETED:
|
case ResourcePackClientResponsePacket::STATUS_COMPLETED:
|
||||||
@ -2132,6 +2245,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
protected function completeLoginSequence(){
|
protected function completeLoginSequence(){
|
||||||
/** @var float[] $pos */
|
/** @var float[] $pos */
|
||||||
$pos = $this->namedtag->getListTag("Pos")->getAllValues();
|
$pos = $this->namedtag->getListTag("Pos")->getAllValues();
|
||||||
@ -3152,6 +3268,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
* Called when a packet is received from the client. This method will call DataPacketReceiveEvent.
|
* Called when a packet is received from the client. This method will call DataPacketReceiveEvent.
|
||||||
*
|
*
|
||||||
* @param DataPacket $packet
|
* @param DataPacket $packet
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function handleDataPacket(DataPacket $packet){
|
public function handleDataPacket(DataPacket $packet){
|
||||||
if($this->sessionAdapter !== null){
|
if($this->sessionAdapter !== null){
|
||||||
@ -3309,6 +3427,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
* @param int $fadeIn Duration in ticks for fade-in. If -1 is given, client-sided defaults will be used.
|
* @param int $fadeIn Duration in ticks for fade-in. If -1 is given, client-sided defaults will be used.
|
||||||
* @param int $stay Duration in ticks to stay on screen for
|
* @param int $stay Duration in ticks to stay on screen for
|
||||||
* @param int $fadeOut Duration in ticks for fade-out.
|
* @param int $fadeOut Duration in ticks for fade-out.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function addTitle(string $title, string $subtitle = "", int $fadeIn = -1, int $stay = -1, int $fadeOut = -1){
|
public function addTitle(string $title, string $subtitle = "", int $fadeIn = -1, int $stay = -1, int $fadeOut = -1){
|
||||||
$this->setTitleDuration($fadeIn, $stay, $fadeOut);
|
$this->setTitleDuration($fadeIn, $stay, $fadeOut);
|
||||||
@ -3322,6 +3442,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
* Sets the subtitle message, without sending a title.
|
* Sets the subtitle message, without sending a title.
|
||||||
*
|
*
|
||||||
* @param string $subtitle
|
* @param string $subtitle
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function addSubTitle(string $subtitle){
|
public function addSubTitle(string $subtitle){
|
||||||
$this->sendTitleText($subtitle, SetTitlePacket::TYPE_SET_SUBTITLE);
|
$this->sendTitleText($subtitle, SetTitlePacket::TYPE_SET_SUBTITLE);
|
||||||
@ -3331,6 +3453,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
* Adds small text to the user's screen.
|
* Adds small text to the user's screen.
|
||||||
*
|
*
|
||||||
* @param string $message
|
* @param string $message
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function addActionBarMessage(string $message){
|
public function addActionBarMessage(string $message){
|
||||||
$this->sendTitleText($message, SetTitlePacket::TYPE_SET_ACTIONBAR_MESSAGE);
|
$this->sendTitleText($message, SetTitlePacket::TYPE_SET_ACTIONBAR_MESSAGE);
|
||||||
@ -3338,6 +3462,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the title from the client's screen.
|
* Removes the title from the client's screen.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function removeTitles(){
|
public function removeTitles(){
|
||||||
$pk = new SetTitlePacket();
|
$pk = new SetTitlePacket();
|
||||||
@ -3347,6 +3473,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the title duration settings to defaults and removes any existing titles.
|
* Resets the title duration settings to defaults and removes any existing titles.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function resetTitles(){
|
public function resetTitles(){
|
||||||
$pk = new SetTitlePacket();
|
$pk = new SetTitlePacket();
|
||||||
@ -3360,6 +3488,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
* @param int $fadeIn Title fade-in time in ticks.
|
* @param int $fadeIn Title fade-in time in ticks.
|
||||||
* @param int $stay Title stay time in ticks.
|
* @param int $stay Title stay time in ticks.
|
||||||
* @param int $fadeOut Title fade-out time in ticks.
|
* @param int $fadeOut Title fade-out time in ticks.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setTitleDuration(int $fadeIn, int $stay, int $fadeOut){
|
public function setTitleDuration(int $fadeIn, int $stay, int $fadeOut){
|
||||||
if($fadeIn >= 0 and $stay >= 0 and $fadeOut >= 0){
|
if($fadeIn >= 0 and $stay >= 0 and $fadeOut >= 0){
|
||||||
@ -3377,6 +3507,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
*
|
*
|
||||||
* @param string $title
|
* @param string $title
|
||||||
* @param int $type
|
* @param int $type
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function sendTitleText(string $title, int $type){
|
protected function sendTitleText(string $title, int $type){
|
||||||
$pk = new SetTitlePacket();
|
$pk = new SetTitlePacket();
|
||||||
@ -3389,6 +3521,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
* Sends a direct chat message to a player
|
* Sends a direct chat message to a player
|
||||||
*
|
*
|
||||||
* @param TextContainer|string $message
|
* @param TextContainer|string $message
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function sendMessage($message){
|
public function sendMessage($message){
|
||||||
if($message instanceof TextContainer){
|
if($message instanceof TextContainer){
|
||||||
@ -3408,6 +3542,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
/**
|
/**
|
||||||
* @param string $message
|
* @param string $message
|
||||||
* @param string[] $parameters
|
* @param string[] $parameters
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function sendTranslation(string $message, array $parameters = []){
|
public function sendTranslation(string $message, array $parameters = []){
|
||||||
$pk = new TextPacket();
|
$pk = new TextPacket();
|
||||||
@ -3433,6 +3569,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
*
|
*
|
||||||
* @param string $message
|
* @param string $message
|
||||||
* @param string $subtitle @deprecated
|
* @param string $subtitle @deprecated
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function sendPopup(string $message, string $subtitle = ""){
|
public function sendPopup(string $message, string $subtitle = ""){
|
||||||
$pk = new TextPacket();
|
$pk = new TextPacket();
|
||||||
@ -3441,6 +3579,11 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
$this->dataPacket($pk);
|
$this->dataPacket($pk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $message
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function sendTip(string $message){
|
public function sendTip(string $message){
|
||||||
$pk = new TextPacket();
|
$pk = new TextPacket();
|
||||||
$pk->type = TextPacket::TYPE_TIP;
|
$pk->type = TextPacket::TYPE_TIP;
|
||||||
@ -3451,6 +3594,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
/**
|
/**
|
||||||
* @param string $sender
|
* @param string $sender
|
||||||
* @param string $message
|
* @param string $message
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function sendWhisper(string $sender, string $message){
|
public function sendWhisper(string $sender, string $message){
|
||||||
$pk = new TextPacket();
|
$pk = new TextPacket();
|
||||||
@ -3592,6 +3737,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed[]
|
||||||
|
*/
|
||||||
public function __debugInfo(){
|
public function __debugInfo(){
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@ -3608,6 +3756,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
* Handles player data saving
|
* Handles player data saving
|
||||||
*
|
*
|
||||||
* @throws \InvalidStateException if the player is closed
|
* @throws \InvalidStateException if the player is closed
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function save(){
|
public function save(){
|
||||||
if($this->closed){
|
if($this->closed){
|
||||||
@ -3770,6 +3920,15 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Vector3 $pos
|
||||||
|
* @param float|null $yaw
|
||||||
|
* @param float|null $pitch
|
||||||
|
* @param int $mode
|
||||||
|
* @param Player[]|null $targets
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function sendPosition(Vector3 $pos, float $yaw = null, float $pitch = null, int $mode = MovePlayerPacket::MODE_NORMAL, array $targets = null){
|
public function sendPosition(Vector3 $pos, float $yaw = null, float $pitch = null, int $mode = MovePlayerPacket::MODE_NORMAL, array $targets = null){
|
||||||
$yaw = $yaw ?? $this->yaw;
|
$yaw = $yaw ?? $this->yaw;
|
||||||
$pitch = $pitch ?? $this->pitch;
|
$pitch = $pitch ?? $this->pitch;
|
||||||
@ -3821,6 +3980,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
protected function addDefaultWindows(){
|
protected function addDefaultWindows(){
|
||||||
$this->addWindow($this->getInventory(), ContainerIds::INVENTORY, true);
|
$this->addWindow($this->getInventory(), ContainerIds::INVENTORY, true);
|
||||||
|
|
||||||
@ -3946,6 +4108,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
* @param Inventory $inventory
|
* @param Inventory $inventory
|
||||||
* @param bool $force Forces removal of permanent windows such as normal inventory, cursor
|
* @param bool $force Forces removal of permanent windows such as normal inventory, cursor
|
||||||
*
|
*
|
||||||
|
* @return void
|
||||||
* @throws \InvalidArgumentException if trying to remove a fixed inventory window without the `force` parameter as true
|
* @throws \InvalidArgumentException if trying to remove a fixed inventory window without the `force` parameter as true
|
||||||
*/
|
*/
|
||||||
public function removeWindow(Inventory $inventory, bool $force = false){
|
public function removeWindow(Inventory $inventory, bool $force = false){
|
||||||
@ -3965,6 +4128,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
* Removes all inventory windows from the player. By default this WILL NOT remove permanent windows.
|
* Removes all inventory windows from the player. By default this WILL NOT remove permanent windows.
|
||||||
*
|
*
|
||||||
* @param bool $removePermanentWindows Whether to remove permanent windows.
|
* @param bool $removePermanentWindows Whether to remove permanent windows.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function removeAllWindows(bool $removePermanentWindows = false){
|
public function removeAllWindows(bool $removePermanentWindows = false){
|
||||||
foreach($this->windowIndex as $id => $window){
|
foreach($this->windowIndex as $id => $window){
|
||||||
@ -3976,6 +4141,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
protected function sendAllInventories(){
|
protected function sendAllInventories(){
|
||||||
foreach($this->windowIndex as $id => $inventory){
|
foreach($this->windowIndex as $id => $inventory){
|
||||||
$inventory->sendContents($this);
|
$inventory->sendContents($this);
|
||||||
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine {
|
namespace pocketmine {
|
||||||
|
|
||||||
|
use pocketmine\utils\Git;
|
||||||
use pocketmine\utils\MainLogger;
|
use pocketmine\utils\MainLogger;
|
||||||
use pocketmine\utils\ServerKiller;
|
use pocketmine\utils\ServerKiller;
|
||||||
use pocketmine\utils\Terminal;
|
use pocketmine\utils\Terminal;
|
||||||
@ -35,6 +36,10 @@ namespace pocketmine {
|
|||||||
|
|
||||||
const MIN_PHP_VERSION = "7.2.0";
|
const MIN_PHP_VERSION = "7.2.0";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $message
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
function critical_error($message){
|
function critical_error($message){
|
||||||
echo "[ERROR] $message" . PHP_EOL;
|
echo "[ERROR] $message" . PHP_EOL;
|
||||||
}
|
}
|
||||||
@ -116,6 +121,10 @@ namespace pocketmine {
|
|||||||
return $messages;
|
return $messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \Logger $logger
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
function emit_performance_warnings(\Logger $logger){
|
function emit_performance_warnings(\Logger $logger){
|
||||||
if(extension_loaded("xdebug")){
|
if(extension_loaded("xdebug")){
|
||||||
$logger->warning("Xdebug extension is enabled. This has a major impact on performance.");
|
$logger->warning("Xdebug extension is enabled. This has a major impact on performance.");
|
||||||
@ -131,6 +140,9 @@ namespace pocketmine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
function set_ini_entries(){
|
function set_ini_entries(){
|
||||||
ini_set("allow_url_fopen", '1');
|
ini_set("allow_url_fopen", '1');
|
||||||
ini_set("display_errors", '1');
|
ini_set("display_errors", '1');
|
||||||
@ -139,8 +151,11 @@ namespace pocketmine {
|
|||||||
ini_set('assert.exception', '1');
|
ini_set('assert.exception', '1');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
function server(){
|
function server(){
|
||||||
if(!empty($messages = check_platform_dependencies())){
|
if(count($messages = check_platform_dependencies()) > 0){
|
||||||
echo PHP_EOL;
|
echo PHP_EOL;
|
||||||
$binary = version_compare(PHP_VERSION, "5.4") >= 0 ? PHP_BINARY : "unknown";
|
$binary = version_compare(PHP_VERSION, "5.4") >= 0 ? PHP_BINARY : "unknown";
|
||||||
critical_error("Selected PHP binary ($binary) does not satisfy some requirements.");
|
critical_error("Selected PHP binary ($binary) does not satisfy some requirements.");
|
||||||
@ -156,17 +171,11 @@ namespace pocketmine {
|
|||||||
error_reporting(-1);
|
error_reporting(-1);
|
||||||
set_ini_entries();
|
set_ini_entries();
|
||||||
|
|
||||||
if(\Phar::running(true) !== ""){
|
|
||||||
define('pocketmine\PATH', \Phar::running(true) . "/");
|
|
||||||
}else{
|
|
||||||
define('pocketmine\PATH', dirname(__FILE__, 3) . DIRECTORY_SEPARATOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
$opts = getopt("", ["bootstrap:"]);
|
$opts = getopt("", ["bootstrap:"]);
|
||||||
if(isset($opts["bootstrap"])){
|
if(isset($opts["bootstrap"])){
|
||||||
$bootstrap = realpath($opts["bootstrap"]) ?: $opts["bootstrap"];
|
$bootstrap = realpath($opts["bootstrap"]) ?: $opts["bootstrap"];
|
||||||
}else{
|
}else{
|
||||||
$bootstrap = \pocketmine\PATH . 'vendor/autoload.php';
|
$bootstrap = dirname(__FILE__, 3) . '/vendor/autoload.php';
|
||||||
}
|
}
|
||||||
define('pocketmine\COMPOSER_AUTOLOADER_PATH', $bootstrap);
|
define('pocketmine\COMPOSER_AUTOLOADER_PATH', $bootstrap);
|
||||||
|
|
||||||
@ -186,12 +195,7 @@ namespace pocketmine {
|
|||||||
$gitHash = str_repeat("00", 20);
|
$gitHash = str_repeat("00", 20);
|
||||||
|
|
||||||
if(\Phar::running(true) === ""){
|
if(\Phar::running(true) === ""){
|
||||||
if(Utils::execute("git rev-parse HEAD", $out) === 0 and $out !== false and strlen($out = trim($out)) === 40){
|
$gitHash = Git::getRepositoryStatePretty(\pocketmine\PATH);
|
||||||
$gitHash = trim($out);
|
|
||||||
if(Utils::execute("git diff --quiet") === 1 or Utils::execute("git diff --cached --quiet") === 1){ //Locally-modified
|
|
||||||
$gitHash .= "-dirty";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}else{
|
}else{
|
||||||
$phar = new \Phar(\Phar::running(false));
|
$phar = new \Phar(\Phar::running(false));
|
||||||
$meta = $phar->getMetadata();
|
$meta = $phar->getMetadata();
|
||||||
@ -202,8 +206,6 @@ namespace pocketmine {
|
|||||||
|
|
||||||
define('pocketmine\GIT_COMMIT', $gitHash);
|
define('pocketmine\GIT_COMMIT', $gitHash);
|
||||||
|
|
||||||
define('pocketmine\RESOURCE_PATH', \pocketmine\PATH . 'src' . DIRECTORY_SEPARATOR . 'pocketmine' . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR);
|
|
||||||
|
|
||||||
$opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-ansi", "disable-ansi"]);
|
$opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-ansi", "disable-ansi"]);
|
||||||
|
|
||||||
define('pocketmine\DATA', isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR);
|
define('pocketmine\DATA', isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR);
|
||||||
|
@ -483,6 +483,8 @@ class Server{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bool $value
|
* @param bool $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setAutoSave(bool $value){
|
public function setAutoSave(bool $value){
|
||||||
$this->autoSave = $value;
|
$this->autoSave = $value;
|
||||||
@ -874,6 +876,8 @@ class Server{
|
|||||||
/**
|
/**
|
||||||
* @param string $name
|
* @param string $name
|
||||||
* @param CompoundTag $nbtTag
|
* @param CompoundTag $nbtTag
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function saveOfflinePlayerData(string $name, CompoundTag $nbtTag){
|
public function saveOfflinePlayerData(string $name, CompoundTag $nbtTag){
|
||||||
$ev = new PlayerDataSaveEvent($nbtTag, $name);
|
$ev = new PlayerDataSaveEvent($nbtTag, $name);
|
||||||
@ -1212,9 +1216,9 @@ class Server{
|
|||||||
}
|
}
|
||||||
$path = $this->getDataPath() . "worlds/" . $name . "/";
|
$path = $this->getDataPath() . "worlds/" . $name . "/";
|
||||||
if(!($this->getLevelByName($name) instanceof Level)){
|
if(!($this->getLevelByName($name) instanceof Level)){
|
||||||
return is_dir($path) and !empty(array_filter(scandir($path, SCANDIR_SORT_NONE), function($v){
|
return is_dir($path) and count(array_filter(scandir($path, SCANDIR_SORT_NONE), function($v){
|
||||||
return $v !== ".." and $v !== ".";
|
return $v !== ".." and $v !== ".";
|
||||||
}));
|
})) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -1277,6 +1281,8 @@ class Server{
|
|||||||
/**
|
/**
|
||||||
* @param string $variable
|
* @param string $variable
|
||||||
* @param string $value
|
* @param string $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setConfigString(string $variable, string $value){
|
public function setConfigString(string $variable, string $value){
|
||||||
$this->properties->set($variable, $value);
|
$this->properties->set($variable, $value);
|
||||||
@ -1300,6 +1306,8 @@ class Server{
|
|||||||
/**
|
/**
|
||||||
* @param string $variable
|
* @param string $variable
|
||||||
* @param int $value
|
* @param int $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setConfigInt(string $variable, int $value){
|
public function setConfigInt(string $variable, int $value){
|
||||||
$this->properties->set($variable, $value);
|
$this->properties->set($variable, $value);
|
||||||
@ -1336,6 +1344,8 @@ class Server{
|
|||||||
/**
|
/**
|
||||||
* @param string $variable
|
* @param string $variable
|
||||||
* @param bool $value
|
* @param bool $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setConfigBool(string $variable, bool $value){
|
public function setConfigBool(string $variable, bool $value){
|
||||||
$this->properties->set($variable, $value ? "1" : "0");
|
$this->properties->set($variable, $value ? "1" : "0");
|
||||||
@ -1370,6 +1380,8 @@ class Server{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $name
|
* @param string $name
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function addOp(string $name){
|
public function addOp(string $name){
|
||||||
$this->operators->set(strtolower($name), true);
|
$this->operators->set(strtolower($name), true);
|
||||||
@ -1382,6 +1394,8 @@ class Server{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $name
|
* @param string $name
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function removeOp(string $name){
|
public function removeOp(string $name){
|
||||||
$this->operators->remove(strtolower($name));
|
$this->operators->remove(strtolower($name));
|
||||||
@ -1394,6 +1408,8 @@ class Server{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $name
|
* @param string $name
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function addWhitelist(string $name){
|
public function addWhitelist(string $name){
|
||||||
$this->whitelist->set(strtolower($name), true);
|
$this->whitelist->set(strtolower($name), true);
|
||||||
@ -1402,6 +1418,8 @@ class Server{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $name
|
* @param string $name
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function removeWhitelist(string $name){
|
public function removeWhitelist(string $name){
|
||||||
$this->whitelist->remove(strtolower($name));
|
$this->whitelist->remove(strtolower($name));
|
||||||
@ -1440,6 +1458,9 @@ class Server{
|
|||||||
return $this->operators;
|
return $this->operators;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function reloadWhitelist(){
|
public function reloadWhitelist(){
|
||||||
$this->whitelist->reload();
|
$this->whitelist->reload();
|
||||||
}
|
}
|
||||||
@ -1476,6 +1497,11 @@ class Server{
|
|||||||
return self::$instance;
|
return self::$instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $microseconds
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public static function microSleep(int $microseconds){
|
public static function microSleep(int $microseconds){
|
||||||
Server::$sleeper->synchronized(function(int $ms){
|
Server::$sleeper->synchronized(function(int $ms){
|
||||||
Server::$sleeper->wait($ms);
|
Server::$sleeper->wait($ms);
|
||||||
@ -1913,6 +1939,8 @@ class Server{
|
|||||||
*
|
*
|
||||||
* @param Player[] $players
|
* @param Player[] $players
|
||||||
* @param DataPacket $packet
|
* @param DataPacket $packet
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function broadcastPacket(array $players, DataPacket $packet){
|
public function broadcastPacket(array $players, DataPacket $packet){
|
||||||
$packet->encode();
|
$packet->encode();
|
||||||
@ -1926,16 +1954,18 @@ class Server{
|
|||||||
* @param DataPacket[] $packets
|
* @param DataPacket[] $packets
|
||||||
* @param bool $forceSync
|
* @param bool $forceSync
|
||||||
* @param bool $immediate
|
* @param bool $immediate
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function batchPackets(array $players, array $packets, bool $forceSync = false, bool $immediate = false){
|
public function batchPackets(array $players, array $packets, bool $forceSync = false, bool $immediate = false){
|
||||||
if(empty($packets)){
|
if(count($packets) === 0){
|
||||||
throw new \InvalidArgumentException("Cannot send empty batch");
|
throw new \InvalidArgumentException("Cannot send empty batch");
|
||||||
}
|
}
|
||||||
Timings::$playerNetworkTimer->startTiming();
|
Timings::$playerNetworkTimer->startTiming();
|
||||||
|
|
||||||
$targets = array_filter($players, function(Player $player) : bool{ return $player->isConnected(); });
|
$targets = array_filter($players, function(Player $player) : bool{ return $player->isConnected(); });
|
||||||
|
|
||||||
if(!empty($targets)){
|
if(count($targets) > 0){
|
||||||
$pk = new BatchPacket();
|
$pk = new BatchPacket();
|
||||||
|
|
||||||
foreach($packets as $p){
|
foreach($packets as $p){
|
||||||
@ -1964,6 +1994,8 @@ class Server{
|
|||||||
* @param BatchPacket $pk
|
* @param BatchPacket $pk
|
||||||
* @param Player[] $players
|
* @param Player[] $players
|
||||||
* @param bool $immediate
|
* @param bool $immediate
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function broadcastPacketsCallback(BatchPacket $pk, array $players, bool $immediate = false){
|
public function broadcastPacketsCallback(BatchPacket $pk, array $players, bool $immediate = false){
|
||||||
if(!$pk->isEncoded){
|
if(!$pk->isEncoded){
|
||||||
@ -1978,6 +2010,8 @@ class Server{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $type
|
* @param int $type
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function enablePlugins(int $type){
|
public function enablePlugins(int $type){
|
||||||
foreach($this->pluginManager->getPlugins() as $plugin){
|
foreach($this->pluginManager->getPlugins() as $plugin){
|
||||||
@ -1994,11 +2028,16 @@ class Server{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Plugin $plugin
|
* @param Plugin $plugin
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function enablePlugin(Plugin $plugin){
|
public function enablePlugin(Plugin $plugin){
|
||||||
$this->pluginManager->enablePlugin($plugin);
|
$this->pluginManager->enablePlugin($plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function disablePlugins(){
|
public function disablePlugins(){
|
||||||
$this->pluginManager->disablePlugins();
|
$this->pluginManager->disablePlugins();
|
||||||
}
|
}
|
||||||
@ -2033,6 +2072,9 @@ class Server{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function reload(){
|
public function reload(){
|
||||||
$this->logger->info("Saving worlds...");
|
$this->logger->info("Saving worlds...");
|
||||||
|
|
||||||
@ -2072,11 +2114,16 @@ class Server{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Shuts the server down correctly
|
* Shuts the server down correctly
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function shutdown(){
|
public function shutdown(){
|
||||||
$this->isRunning = false;
|
$this->isRunning = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function forceShutdown(){
|
public function forceShutdown(){
|
||||||
if($this->hasStopped){
|
if($this->hasStopped){
|
||||||
return;
|
return;
|
||||||
@ -2162,7 +2209,7 @@ class Server{
|
|||||||
/**
|
/**
|
||||||
* Starts the PocketMine-MP server and starts processing ticks and packets
|
* Starts the PocketMine-MP server and starts processing ticks and packets
|
||||||
*/
|
*/
|
||||||
private function start(){
|
private function start() : void{
|
||||||
if($this->getConfigBool("enable-query", true)){
|
if($this->getConfigBool("enable-query", true)){
|
||||||
$this->queryHandler = new QueryHandler();
|
$this->queryHandler = new QueryHandler();
|
||||||
}
|
}
|
||||||
@ -2204,6 +2251,11 @@ class Server{
|
|||||||
$this->forceShutdown();
|
$this->forceShutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $signo
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function handleSignal($signo){
|
public function handleSignal($signo){
|
||||||
if($signo === SIGTERM or $signo === SIGINT or $signo === SIGHUP){
|
if($signo === SIGTERM or $signo === SIGINT or $signo === SIGHUP){
|
||||||
$this->shutdown();
|
$this->shutdown();
|
||||||
@ -2213,6 +2265,8 @@ class Server{
|
|||||||
/**
|
/**
|
||||||
* @param \Throwable $e
|
* @param \Throwable $e
|
||||||
* @param array|null $trace
|
* @param array|null $trace
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function exceptionHandler(\Throwable $e, $trace = null){
|
public function exceptionHandler(\Throwable $e, $trace = null){
|
||||||
while(@ob_end_flush()){}
|
while(@ob_end_flush()){}
|
||||||
@ -2246,6 +2300,9 @@ class Server{
|
|||||||
$this->crashDump();
|
$this->crashDump();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function crashDump(){
|
public function crashDump(){
|
||||||
while(@ob_end_flush()){}
|
while(@ob_end_flush()){}
|
||||||
if(!$this->isRunning){
|
if(!$this->isRunning){
|
||||||
@ -2328,6 +2385,9 @@ class Server{
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed[]
|
||||||
|
*/
|
||||||
public function __debugInfo(){
|
public function __debugInfo(){
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@ -2336,7 +2396,7 @@ class Server{
|
|||||||
return $this->tickSleeper;
|
return $this->tickSleeper;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function tickProcessor(){
|
private function tickProcessor() : void{
|
||||||
$this->nextTick = microtime(true);
|
$this->nextTick = microtime(true);
|
||||||
|
|
||||||
while($this->isRunning){
|
while($this->isRunning){
|
||||||
@ -2347,6 +2407,11 @@ class Server{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Player $player
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function onPlayerLogin(Player $player){
|
public function onPlayerLogin(Player $player){
|
||||||
if($this->sendUsageTicker > 0){
|
if($this->sendUsageTicker > 0){
|
||||||
$this->uniquePlayers[$player->getRawUniqueId()] = $player->getRawUniqueId();
|
$this->uniquePlayers[$player->getRawUniqueId()] = $player->getRawUniqueId();
|
||||||
@ -2355,27 +2420,49 @@ class Server{
|
|||||||
$this->loggedInPlayers[$player->getRawUniqueId()] = $player;
|
$this->loggedInPlayers[$player->getRawUniqueId()] = $player;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Player $player
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function onPlayerLogout(Player $player){
|
public function onPlayerLogout(Player $player){
|
||||||
unset($this->loggedInPlayers[$player->getRawUniqueId()]);
|
unset($this->loggedInPlayers[$player->getRawUniqueId()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Player $player
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function addPlayer(Player $player){
|
public function addPlayer(Player $player){
|
||||||
$this->players[spl_object_hash($player)] = $player;
|
$this->players[spl_object_hash($player)] = $player;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Player $player
|
* @param Player $player
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function removePlayer(Player $player){
|
public function removePlayer(Player $player){
|
||||||
unset($this->players[spl_object_hash($player)]);
|
unset($this->players[spl_object_hash($player)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Player $player
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function addOnlinePlayer(Player $player){
|
public function addOnlinePlayer(Player $player){
|
||||||
$this->updatePlayerListData($player->getUniqueId(), $player->getId(), $player->getDisplayName(), $player->getSkin(), $player->getXuid());
|
$this->updatePlayerListData($player->getUniqueId(), $player->getId(), $player->getDisplayName(), $player->getSkin(), $player->getXuid());
|
||||||
|
|
||||||
$this->playerList[$player->getRawUniqueId()] = $player;
|
$this->playerList[$player->getRawUniqueId()] = $player;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Player $player
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function removeOnlinePlayer(Player $player){
|
public function removeOnlinePlayer(Player $player){
|
||||||
if(isset($this->playerList[$player->getRawUniqueId()])){
|
if(isset($this->playerList[$player->getRawUniqueId()])){
|
||||||
unset($this->playerList[$player->getRawUniqueId()]);
|
unset($this->playerList[$player->getRawUniqueId()]);
|
||||||
@ -2391,6 +2478,8 @@ class Server{
|
|||||||
* @param Skin $skin
|
* @param Skin $skin
|
||||||
* @param string $xboxUserId
|
* @param string $xboxUserId
|
||||||
* @param Player[]|null $players
|
* @param Player[]|null $players
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function updatePlayerListData(UUID $uuid, int $entityId, string $name, Skin $skin, string $xboxUserId = "", array $players = null){
|
public function updatePlayerListData(UUID $uuid, int $entityId, string $name, Skin $skin, string $xboxUserId = "", array $players = null){
|
||||||
$pk = new PlayerListPacket();
|
$pk = new PlayerListPacket();
|
||||||
@ -2404,6 +2493,8 @@ class Server{
|
|||||||
/**
|
/**
|
||||||
* @param UUID $uuid
|
* @param UUID $uuid
|
||||||
* @param Player[]|null $players
|
* @param Player[]|null $players
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function removePlayerListData(UUID $uuid, array $players = null){
|
public function removePlayerListData(UUID $uuid, array $players = null){
|
||||||
$pk = new PlayerListPacket();
|
$pk = new PlayerListPacket();
|
||||||
@ -2414,6 +2505,8 @@ class Server{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Player $p
|
* @param Player $p
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function sendFullPlayerListData(Player $p){
|
public function sendFullPlayerListData(Player $p){
|
||||||
$pk = new PlayerListPacket();
|
$pk = new PlayerListPacket();
|
||||||
@ -2449,6 +2542,9 @@ class Server{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function doAutoSave(){
|
public function doAutoSave(){
|
||||||
if($this->getAutoSave()){
|
if($this->getAutoSave()){
|
||||||
Timings::$worldSaveTimer->startTiming();
|
Timings::$worldSaveTimer->startTiming();
|
||||||
@ -2467,6 +2563,11 @@ class Server{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $type
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function sendUsage($type = SendUsageTask::TYPE_STATUS){
|
public function sendUsage($type = SendUsageTask::TYPE_STATUS){
|
||||||
if((bool) $this->getProperty("anonymous-statistics.enabled", true)){
|
if((bool) $this->getProperty("anonymous-statistics.enabled", true)){
|
||||||
$this->asyncPool->submitTask(new SendUsageTask($this, $type, $this->uniquePlayers));
|
$this->asyncPool->submitTask(new SendUsageTask($this, $type, $this->uniquePlayers));
|
||||||
@ -2503,7 +2604,7 @@ class Server{
|
|||||||
return $this->memoryManager;
|
return $this->memoryManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function titleTick(){
|
private function titleTick() : void{
|
||||||
Timings::$titleTickTimer->startTiming();
|
Timings::$titleTickTimer->startTiming();
|
||||||
$d = Utils::getRealMemoryUsage();
|
$d = Utils::getRealMemoryUsage();
|
||||||
|
|
||||||
@ -2528,6 +2629,8 @@ class Server{
|
|||||||
* @param int $port
|
* @param int $port
|
||||||
* @param string $payload
|
* @param string $payload
|
||||||
*
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
* TODO: move this to Network
|
* TODO: move this to Network
|
||||||
*/
|
*/
|
||||||
public function handlePacket(AdvancedSourceInterface $interface, string $address, int $port, string $payload){
|
public function handlePacket(AdvancedSourceInterface $interface, string $address, int $port, string $payload){
|
||||||
|
@ -33,12 +33,21 @@ abstract class Thread extends \Thread{
|
|||||||
/** @var string|null */
|
/** @var string|null */
|
||||||
protected $composerAutoloaderPath;
|
protected $composerAutoloaderPath;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
protected $isKilled = false;
|
protected $isKilled = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \ClassLoader|null
|
||||||
|
*/
|
||||||
public function getClassLoader(){
|
public function getClassLoader(){
|
||||||
return $this->classLoader;
|
return $this->classLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \ClassLoader|null $loader
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function setClassLoader(\ClassLoader $loader = null){
|
public function setClassLoader(\ClassLoader $loader = null){
|
||||||
$this->composerAutoloaderPath = \pocketmine\COMPOSER_AUTOLOADER_PATH;
|
$this->composerAutoloaderPath = \pocketmine\COMPOSER_AUTOLOADER_PATH;
|
||||||
|
|
||||||
@ -54,6 +63,8 @@ abstract class Thread extends \Thread{
|
|||||||
* WARNING: This method MUST be called from any descendent threads' run() method to make autoloading usable.
|
* WARNING: This method MUST be called from any descendent threads' run() method to make autoloading usable.
|
||||||
* If you do not do this, you will not be able to use new classes that were not loaded when the thread was started
|
* If you do not do this, you will not be able to use new classes that were not loaded when the thread was started
|
||||||
* (unless you are using a custom autoloader).
|
* (unless you are using a custom autoloader).
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function registerClassLoader(){
|
public function registerClassLoader(){
|
||||||
if($this->composerAutoloaderPath !== null){
|
if($this->composerAutoloaderPath !== null){
|
||||||
@ -64,6 +75,11 @@ abstract class Thread extends \Thread{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int|null $options TODO: pthreads bug
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function start(?int $options = \PTHREADS_INHERIT_ALL){
|
public function start(?int $options = \PTHREADS_INHERIT_ALL){
|
||||||
ThreadManager::getInstance()->add($this);
|
ThreadManager::getInstance()->add($this);
|
||||||
|
|
||||||
@ -75,6 +91,8 @@ abstract class Thread extends \Thread{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops the thread using the best way possible. Try to stop it yourself before calling this.
|
* Stops the thread using the best way possible. Try to stop it yourself before calling this.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function quit(){
|
public function quit(){
|
||||||
$this->isKilled = true;
|
$this->isKilled = true;
|
||||||
|
@ -31,6 +31,9 @@ class ThreadManager extends \Volatile{
|
|||||||
/** @var ThreadManager */
|
/** @var ThreadManager */
|
||||||
private static $instance = null;
|
private static $instance = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public static function init(){
|
public static function init(){
|
||||||
self::$instance = new ThreadManager();
|
self::$instance = new ThreadManager();
|
||||||
}
|
}
|
||||||
@ -44,6 +47,8 @@ class ThreadManager extends \Volatile{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Worker|Thread $thread
|
* @param Worker|Thread $thread
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function add($thread){
|
public function add($thread){
|
||||||
if($thread instanceof Thread or $thread instanceof Worker){
|
if($thread instanceof Thread or $thread instanceof Worker){
|
||||||
@ -53,6 +58,8 @@ class ThreadManager extends \Volatile{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Worker|Thread $thread
|
* @param Worker|Thread $thread
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function remove($thread){
|
public function remove($thread){
|
||||||
if($thread instanceof Thread or $thread instanceof Worker){
|
if($thread instanceof Thread or $thread instanceof Worker){
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine;
|
namespace pocketmine;
|
||||||
|
|
||||||
// composer autoload doesn't use require_once and also pthreads can inherit things
|
// composer autoload doesn't use require_once and also pthreads can inherit things
|
||||||
@ -30,6 +32,6 @@ const _VERSION_INFO_INCLUDED = true;
|
|||||||
|
|
||||||
|
|
||||||
const NAME = "PocketMine-MP";
|
const NAME = "PocketMine-MP";
|
||||||
const BASE_VERSION = "3.11.0";
|
const BASE_VERSION = "3.11.4";
|
||||||
const IS_DEVELOPMENT_BUILD = false;
|
const IS_DEVELOPMENT_BUILD = false;
|
||||||
const BUILD_NUMBER = 0;
|
const BUILD_NUMBER = 0;
|
||||||
|
@ -33,12 +33,21 @@ abstract class Worker extends \Worker{
|
|||||||
/** @var string|null */
|
/** @var string|null */
|
||||||
protected $composerAutoloaderPath;
|
protected $composerAutoloaderPath;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
protected $isKilled = false;
|
protected $isKilled = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \ClassLoader|null
|
||||||
|
*/
|
||||||
public function getClassLoader(){
|
public function getClassLoader(){
|
||||||
return $this->classLoader;
|
return $this->classLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \ClassLoader|null $loader
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function setClassLoader(\ClassLoader $loader = null){
|
public function setClassLoader(\ClassLoader $loader = null){
|
||||||
$this->composerAutoloaderPath = \pocketmine\COMPOSER_AUTOLOADER_PATH;
|
$this->composerAutoloaderPath = \pocketmine\COMPOSER_AUTOLOADER_PATH;
|
||||||
|
|
||||||
@ -54,6 +63,8 @@ abstract class Worker extends \Worker{
|
|||||||
* WARNING: This method MUST be called from any descendent threads' run() method to make autoloading usable.
|
* WARNING: This method MUST be called from any descendent threads' run() method to make autoloading usable.
|
||||||
* If you do not do this, you will not be able to use new classes that were not loaded when the thread was started
|
* If you do not do this, you will not be able to use new classes that were not loaded when the thread was started
|
||||||
* (unless you are using a custom autoloader).
|
* (unless you are using a custom autoloader).
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function registerClassLoader(){
|
public function registerClassLoader(){
|
||||||
if($this->composerAutoloaderPath !== null){
|
if($this->composerAutoloaderPath !== null){
|
||||||
@ -64,6 +75,11 @@ abstract class Worker extends \Worker{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int|null $options TODO: pthreads bug
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function start(?int $options = \PTHREADS_INHERIT_ALL){
|
public function start(?int $options = \PTHREADS_INHERIT_ALL){
|
||||||
ThreadManager::getInstance()->add($this);
|
ThreadManager::getInstance()->add($this);
|
||||||
|
|
||||||
@ -75,6 +91,8 @@ abstract class Worker extends \Worker{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops the thread using the best way possible. Try to stop it yourself before calling this.
|
* Stops the thread using the best way possible. Try to stop it yourself before calling this.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function quit(){
|
public function quit(){
|
||||||
$this->isKilled = true;
|
$this->isKilled = true;
|
||||||
|
@ -76,6 +76,11 @@ class Bed extends Transparent{
|
|||||||
return ($this->meta & self::BITFLAG_OCCUPIED) !== 0;
|
return ($this->meta & self::BITFLAG_OCCUPIED) !== 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $occupied
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function setOccupied(bool $occupied = true){
|
public function setOccupied(bool $occupied = true){
|
||||||
if($occupied){
|
if($occupied){
|
||||||
$this->meta |= self::BITFLAG_OCCUPIED;
|
$this->meta |= self::BITFLAG_OCCUPIED;
|
||||||
|
@ -40,6 +40,7 @@ use pocketmine\network\mcpe\protocol\types\RuntimeBlockMapping;
|
|||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
use pocketmine\plugin\Plugin;
|
use pocketmine\plugin\Plugin;
|
||||||
use function array_merge;
|
use function array_merge;
|
||||||
|
use function count;
|
||||||
use function get_class;
|
use function get_class;
|
||||||
use const PHP_INT_MAX;
|
use const PHP_INT_MAX;
|
||||||
|
|
||||||
@ -727,7 +728,7 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
*/
|
*/
|
||||||
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) : ?RayTraceResult{
|
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) : ?RayTraceResult{
|
||||||
$bbs = $this->getCollisionBoxes();
|
$bbs = $this->getCollisionBoxes();
|
||||||
if(empty($bbs)){
|
if(count($bbs) === 0){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +111,11 @@ class CobblestoneWall extends Transparent{
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Block $block
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function canConnect(Block $block){
|
public function canConnect(Block $block){
|
||||||
return $block instanceof static or $block instanceof FenceGate or ($block->isSolid() and !$block->isTransparent());
|
return $block instanceof static or $block instanceof FenceGate or ($block->isSolid() and !$block->isTransparent());
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ abstract class Door extends Transparent{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getFullDamage(){
|
private function getFullDamage() : int{
|
||||||
$damage = $this->getDamage();
|
$damage = $this->getDamage();
|
||||||
$isUp = ($damage & 0x08) > 0;
|
$isUp = ($damage & 0x08) > 0;
|
||||||
|
|
||||||
|
@ -84,6 +84,9 @@ class EnderChest extends Chest{
|
|||||||
$enderChest = $t;
|
$enderChest = $t;
|
||||||
}else{
|
}else{
|
||||||
$enderChest = Tile::createTile(Tile::ENDER_CHEST, $this->getLevel(), TileEnderChest::createNBT($this));
|
$enderChest = Tile::createTile(Tile::ENDER_CHEST, $this->getLevel(), TileEnderChest::createNBT($this));
|
||||||
|
if(!($enderChest instanceof TileEnderChest)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!$this->getSide(Vector3::SIDE_UP)->isTransparent()){
|
if(!$this->getSide(Vector3::SIDE_UP)->isTransparent()){
|
||||||
|
@ -25,6 +25,7 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
|
use function count;
|
||||||
|
|
||||||
abstract class Fence extends Transparent{
|
abstract class Fence extends Transparent{
|
||||||
|
|
||||||
@ -85,7 +86,7 @@ abstract class Fence extends Transparent{
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(empty($bbs)){
|
if(count($bbs) === 0){
|
||||||
//centre post AABB (only needed if not connected on any axis - other BBs overlapping will do this if any connections are made)
|
//centre post AABB (only needed if not connected on any axis - other BBs overlapping will do this if any connections are made)
|
||||||
return [
|
return [
|
||||||
new AxisAlignedBB(
|
new AxisAlignedBB(
|
||||||
@ -102,6 +103,11 @@ abstract class Fence extends Transparent{
|
|||||||
return $bbs;
|
return $bbs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Block $block
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function canConnect(Block $block){
|
public function canConnect(Block $block){
|
||||||
return $block instanceof static or $block instanceof FenceGate or ($block->isSolid() and !$block->isTransparent());
|
return $block instanceof static or $block instanceof FenceGate or ($block->isSolid() and !$block->isTransparent());
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ class Leaves extends Transparent{
|
|||||||
public const DARK_OAK = 1;
|
public const DARK_OAK = 1;
|
||||||
|
|
||||||
protected $id = self::LEAVES;
|
protected $id = self::LEAVES;
|
||||||
|
/** @var int */
|
||||||
protected $woodType = self::WOOD;
|
protected $woodType = self::WOOD;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(int $meta = 0){
|
||||||
@ -68,7 +69,7 @@ class Leaves extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected function findLog(Block $pos, array $visited, int $distance, ?int $fromSide = null) : bool{
|
protected function findLog(Block $pos, array &$visited, int $distance, ?int $fromSide = null) : bool{
|
||||||
$index = $pos->x . "." . $pos->y . "." . $pos->z;
|
$index = $pos->x . "." . $pos->y . "." . $pos->z;
|
||||||
if(isset($visited[$index])){
|
if(isset($visited[$index])){
|
||||||
return false;
|
return false;
|
||||||
|
@ -29,6 +29,7 @@ use pocketmine\item\ItemFactory;
|
|||||||
class Leaves2 extends Leaves{
|
class Leaves2 extends Leaves{
|
||||||
|
|
||||||
protected $id = self::LEAVES2;
|
protected $id = self::LEAVES2;
|
||||||
|
/** @var int */
|
||||||
protected $woodType = self::WOOD2;
|
protected $woodType = self::WOOD2;
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -38,6 +38,7 @@ use function min;
|
|||||||
|
|
||||||
abstract class Liquid extends Transparent{
|
abstract class Liquid extends Transparent{
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
public $adjacentSources = 0;
|
public $adjacentSources = 0;
|
||||||
|
|
||||||
/** @var Vector3|null */
|
/** @var Vector3|null */
|
||||||
@ -90,6 +91,9 @@ abstract class Liquid extends Transparent{
|
|||||||
|
|
||||||
abstract public function getBucketEmptySound() : int;
|
abstract public function getBucketEmptySound() : int;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
public function getFluidHeightPercent(){
|
public function getFluidHeightPercent(){
|
||||||
$d = $this->meta;
|
$d = $this->meta;
|
||||||
if($d >= 8){
|
if($d >= 8){
|
||||||
@ -430,6 +434,9 @@ abstract class Liquid extends Transparent{
|
|||||||
return ($decay >= 0 && $blockDecay >= $decay) ? $decay : $blockDecay;
|
return ($decay >= 0 && $blockDecay >= $decay) ? $decay : $blockDecay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
protected function checkForHarden(){
|
protected function checkForHarden(){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -74,6 +74,11 @@ class TNT extends Solid{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $fuse
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function ignite(int $fuse = 80){
|
public function ignite(int $fuse = 80){
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
|
use function count;
|
||||||
|
|
||||||
abstract class Thin extends Transparent{
|
abstract class Thin extends Transparent{
|
||||||
|
|
||||||
@ -77,7 +78,7 @@ abstract class Thin extends Transparent{
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(empty($bbs)){
|
if(count($bbs) === 0){
|
||||||
//centre post AABB (only needed if not connected on any axis - other BBs overlapping will do this if any connections are made)
|
//centre post AABB (only needed if not connected on any axis - other BBs overlapping will do this if any connections are made)
|
||||||
return [
|
return [
|
||||||
new AxisAlignedBB(
|
new AxisAlignedBB(
|
||||||
|
@ -114,6 +114,8 @@ abstract class Command{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string|null $permission
|
* @param string|null $permission
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setPermission(string $permission = null){
|
public function setPermission(string $permission = null){
|
||||||
$this->permission = $permission;
|
$this->permission = $permission;
|
||||||
@ -259,6 +261,8 @@ abstract class Command{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string[] $aliases
|
* @param string[] $aliases
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setAliases(array $aliases){
|
public function setAliases(array $aliases){
|
||||||
$this->aliases = $aliases;
|
$this->aliases = $aliases;
|
||||||
@ -269,6 +273,8 @@ abstract class Command{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $description
|
* @param string $description
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setDescription(string $description){
|
public function setDescription(string $description){
|
||||||
$this->description = $description;
|
$this->description = $description;
|
||||||
@ -276,6 +282,8 @@ abstract class Command{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $permissionMessage
|
* @param string $permissionMessage
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setPermissionMessage(string $permissionMessage){
|
public function setPermissionMessage(string $permissionMessage){
|
||||||
$this->permissionMessage = $permissionMessage;
|
$this->permissionMessage = $permissionMessage;
|
||||||
@ -283,6 +291,8 @@ abstract class Command{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $usage
|
* @param string $usage
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setUsage(string $usage){
|
public function setUsage(string $usage){
|
||||||
$this->usageMessage = $usage;
|
$this->usageMessage = $usage;
|
||||||
@ -292,6 +302,8 @@ abstract class Command{
|
|||||||
* @param CommandSender $source
|
* @param CommandSender $source
|
||||||
* @param TextContainer|string $message
|
* @param TextContainer|string $message
|
||||||
* @param bool $sendToSource
|
* @param bool $sendToSource
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function broadcastCommandMessage(CommandSender $source, $message, bool $sendToSource = true){
|
public static function broadcastCommandMessage(CommandSender $source, $message, bool $sendToSource = true){
|
||||||
if($message instanceof TextContainer){
|
if($message instanceof TextContainer){
|
||||||
|
@ -29,6 +29,8 @@ interface CommandMap{
|
|||||||
/**
|
/**
|
||||||
* @param string $fallbackPrefix
|
* @param string $fallbackPrefix
|
||||||
* @param Command[] $commands
|
* @param Command[] $commands
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function registerAll(string $fallbackPrefix, array $commands);
|
public function registerAll(string $fallbackPrefix, array $commands);
|
||||||
|
|
||||||
|
@ -54,7 +54,9 @@ class CommandReader extends Thread{
|
|||||||
|
|
||||||
/** @var \Threaded */
|
/** @var \Threaded */
|
||||||
protected $buffer;
|
protected $buffer;
|
||||||
|
/** @var bool */
|
||||||
private $shutdown = false;
|
private $shutdown = false;
|
||||||
|
/** @var int */
|
||||||
private $type = self::TYPE_STREAM;
|
private $type = self::TYPE_STREAM;
|
||||||
|
|
||||||
/** @var SleeperNotifier|null */
|
/** @var SleeperNotifier|null */
|
||||||
@ -71,6 +73,9 @@ class CommandReader extends Thread{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function shutdown(){
|
public function shutdown(){
|
||||||
$this->shutdown = true;
|
$this->shutdown = true;
|
||||||
}
|
}
|
||||||
@ -94,7 +99,7 @@ class CommandReader extends Thread{
|
|||||||
throw new \ThreadException($message);
|
throw new \ThreadException($message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function initStdin(){
|
private function initStdin() : void{
|
||||||
if(is_resource(self::$stdin)){
|
if(is_resource(self::$stdin)){
|
||||||
fclose(self::$stdin);
|
fclose(self::$stdin);
|
||||||
}
|
}
|
||||||
@ -185,6 +190,9 @@ class CommandReader extends Thread{
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function run(){
|
public function run(){
|
||||||
$this->registerClassLoader();
|
$this->registerClassLoader();
|
||||||
|
|
||||||
|
@ -31,6 +31,8 @@ interface CommandSender extends Permissible{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param TextContainer|string $message
|
* @param TextContainer|string $message
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function sendMessage($message);
|
public function sendMessage($message);
|
||||||
|
|
||||||
@ -56,6 +58,8 @@ interface CommandSender extends Permissible{
|
|||||||
* Sets the line height used for command output pagination for this command sender. `null` will reset it to default.
|
* Sets the line height used for command output pagination for this command sender. `null` will reset it to default.
|
||||||
*
|
*
|
||||||
* @param int|null $height
|
* @param int|null $height
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setScreenLineHeight(int $height = null);
|
public function setScreenLineHeight(int $height = null);
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@ use const PHP_INT_MAX;
|
|||||||
|
|
||||||
class ConsoleCommandSender implements CommandSender{
|
class ConsoleCommandSender implements CommandSender{
|
||||||
|
|
||||||
|
/** @var PermissibleBase */
|
||||||
private $perm;
|
private $perm;
|
||||||
|
|
||||||
/** @var int|null */
|
/** @var int|null */
|
||||||
@ -104,6 +105,8 @@ class ConsoleCommandSender implements CommandSender{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param TextContainer|string $message
|
* @param TextContainer|string $message
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function sendMessage($message){
|
public function sendMessage($message){
|
||||||
if($message instanceof TextContainer){
|
if($message instanceof TextContainer){
|
||||||
@ -133,6 +136,8 @@ class ConsoleCommandSender implements CommandSender{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bool $value
|
* @param bool $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setOp(bool $value){
|
public function setOp(bool $value){
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ use function strpos;
|
|||||||
use function substr;
|
use function substr;
|
||||||
|
|
||||||
class FormattedCommandAlias extends Command{
|
class FormattedCommandAlias extends Command{
|
||||||
|
/** @var string[] */
|
||||||
private $formatStrings = [];
|
private $formatStrings = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,6 +70,8 @@ class PluginCommand extends Command implements PluginIdentifiableCommand{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param CommandExecutor $executor
|
* @param CommandExecutor $executor
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setExecutor(CommandExecutor $executor){
|
public function setExecutor(CommandExecutor $executor){
|
||||||
$this->executor = $executor;
|
$this->executor = $executor;
|
||||||
|
@ -41,6 +41,9 @@ class RemoteConsoleCommandSender extends ConsoleCommandSender{
|
|||||||
$this->messages .= trim($message, "\r\n") . "\n";
|
$this->messages .= trim($message, "\r\n") . "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function getMessage(){
|
public function getMessage(){
|
||||||
return $this->messages;
|
return $this->messages;
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ class SimpleCommandMap implements CommandMap{
|
|||||||
$this->setDefaultCommands();
|
$this->setDefaultCommands();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function setDefaultCommands(){
|
private function setDefaultCommands() : void{
|
||||||
$this->registerAll("pocketmine", [
|
$this->registerAll("pocketmine", [
|
||||||
new BanCommand("ban"),
|
new BanCommand("ban"),
|
||||||
new BanIpCommand("ban-ip"),
|
new BanIpCommand("ban-ip"),
|
||||||
@ -226,8 +226,8 @@ class SimpleCommandMap implements CommandMap{
|
|||||||
* This method is intended to provide capability for handling commands with spaces in their name.
|
* This method is intended to provide capability for handling commands with spaces in their name.
|
||||||
* The referenced parameters will be modified accordingly depending on the resulting matched command.
|
* The referenced parameters will be modified accordingly depending on the resulting matched command.
|
||||||
*
|
*
|
||||||
* @param string &$commandName
|
* @param string $commandName reference parameter
|
||||||
* @param string[] &$args
|
* @param string[] $args reference parameter
|
||||||
*
|
*
|
||||||
* @return Command|null
|
* @return Command|null
|
||||||
*/
|
*/
|
||||||
@ -328,12 +328,12 @@ class SimpleCommandMap implements CommandMap{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!empty($recursive)){
|
if(count($recursive) > 0){
|
||||||
$this->server->getLogger()->warning($this->server->getLanguage()->translateString("pocketmine.command.alias.recursive", [$alias, implode(", ", $recursive)]));
|
$this->server->getLogger()->warning($this->server->getLanguage()->translateString("pocketmine.command.alias.recursive", [$alias, implode(", ", $recursive)]));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!empty($bad)){
|
if(count($bad) > 0){
|
||||||
$this->server->getLogger()->warning($this->server->getLanguage()->translateString("pocketmine.command.alias.notFound", [$alias, implode(", ", $bad)]));
|
$this->server->getLogger()->warning($this->server->getLanguage()->translateString("pocketmine.command.alias.notFound", [$alias, implode(", ", $bad)]));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ class BanIpCommand extends VanillaCommand{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function processIPBan(string $ip, CommandSender $sender, string $reason){
|
private function processIPBan(string $ip, CommandSender $sender, string $reason) : void{
|
||||||
$sender->getServer()->getIPBans()->addBan($ip, $reason, null, $sender->getName());
|
$sender->getServer()->getIPBans()->addBan($ip, $reason, null, $sender->getName());
|
||||||
|
|
||||||
foreach($sender->getServer()->getOnlinePlayers() as $player){
|
foreach($sender->getServer()->getOnlinePlayers() as $player){
|
||||||
|
@ -84,7 +84,7 @@ class VersionCommand extends VanillaCommand{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function describeToSender(Plugin $plugin, CommandSender $sender){
|
private function describeToSender(Plugin $plugin, CommandSender $sender) : void{
|
||||||
$desc = $plugin->getDescription();
|
$desc = $plugin->getDescription();
|
||||||
$sender->sendMessage(TextFormat::DARK_GREEN . $desc->getName() . TextFormat::WHITE . " version " . TextFormat::DARK_GREEN . $desc->getVersion());
|
$sender->sendMessage(TextFormat::DARK_GREEN . $desc->getName() . TextFormat::WHITE . " version " . TextFormat::DARK_GREEN . $desc->getVersion());
|
||||||
|
|
||||||
|
@ -46,14 +46,22 @@ class Attribute{
|
|||||||
public const HORSE_JUMP_STRENGTH = 14;
|
public const HORSE_JUMP_STRENGTH = 14;
|
||||||
public const ZOMBIE_SPAWN_REINFORCEMENTS = 15;
|
public const ZOMBIE_SPAWN_REINFORCEMENTS = 15;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
private $id;
|
private $id;
|
||||||
|
/** @var float */
|
||||||
protected $minValue;
|
protected $minValue;
|
||||||
|
/** @var float */
|
||||||
protected $maxValue;
|
protected $maxValue;
|
||||||
|
/** @var float */
|
||||||
protected $defaultValue;
|
protected $defaultValue;
|
||||||
|
/** @var float */
|
||||||
protected $currentValue;
|
protected $currentValue;
|
||||||
|
/** @var string */
|
||||||
protected $name;
|
protected $name;
|
||||||
|
/** @var bool */
|
||||||
protected $shouldSend;
|
protected $shouldSend;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
protected $desynchronized = true;
|
protected $desynchronized = true;
|
||||||
|
|
||||||
/** @var Attribute[] */
|
/** @var Attribute[] */
|
||||||
@ -137,6 +145,11 @@ class Attribute{
|
|||||||
return $this->minValue;
|
return $this->minValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param float $minValue
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
public function setMinValue(float $minValue){
|
public function setMinValue(float $minValue){
|
||||||
if($minValue > ($max = $this->getMaxValue())){
|
if($minValue > ($max = $this->getMaxValue())){
|
||||||
throw new \InvalidArgumentException("Minimum $minValue is greater than the maximum $max");
|
throw new \InvalidArgumentException("Minimum $minValue is greater than the maximum $max");
|
||||||
@ -153,6 +166,11 @@ class Attribute{
|
|||||||
return $this->maxValue;
|
return $this->maxValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param float $maxValue
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
public function setMaxValue(float $maxValue){
|
public function setMaxValue(float $maxValue){
|
||||||
if($maxValue < ($min = $this->getMinValue())){
|
if($maxValue < ($min = $this->getMinValue())){
|
||||||
throw new \InvalidArgumentException("Maximum $maxValue is less than the minimum $min");
|
throw new \InvalidArgumentException("Maximum $maxValue is less than the minimum $min");
|
||||||
@ -169,6 +187,11 @@ class Attribute{
|
|||||||
return $this->defaultValue;
|
return $this->defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param float $defaultValue
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
public function setDefaultValue(float $defaultValue){
|
public function setDefaultValue(float $defaultValue){
|
||||||
if($defaultValue > $this->getMaxValue() or $defaultValue < $this->getMinValue()){
|
if($defaultValue > $this->getMaxValue() or $defaultValue < $this->getMinValue()){
|
||||||
throw new \InvalidArgumentException("Default $defaultValue is outside the range " . $this->getMinValue() . " - " . $this->getMaxValue());
|
throw new \InvalidArgumentException("Default $defaultValue is outside the range " . $this->getMinValue() . " - " . $this->getMaxValue());
|
||||||
|
@ -25,6 +25,9 @@ namespace pocketmine\entity;
|
|||||||
|
|
||||||
use function array_filter;
|
use function array_filter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @phpstan-implements \ArrayAccess<int, float>
|
||||||
|
*/
|
||||||
class AttributeMap implements \ArrayAccess{
|
class AttributeMap implements \ArrayAccess{
|
||||||
/** @var Attribute[] */
|
/** @var Attribute[] */
|
||||||
private $attributes = [];
|
private $attributes = [];
|
||||||
@ -58,6 +61,11 @@ class AttributeMap implements \ArrayAccess{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $offset
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function offsetExists($offset) : bool{
|
public function offsetExists($offset) : bool{
|
||||||
return isset($this->attributes[$offset]);
|
return isset($this->attributes[$offset]);
|
||||||
}
|
}
|
||||||
@ -79,6 +87,9 @@ class AttributeMap implements \ArrayAccess{
|
|||||||
$this->attributes[$offset]->setValue($value);
|
$this->attributes[$offset]->setValue($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $offset
|
||||||
|
*/
|
||||||
public function offsetUnset($offset) : void{
|
public function offsetUnset($offset) : void{
|
||||||
throw new \RuntimeException("Could not unset an attribute from an attribute map");
|
throw new \RuntimeException("Could not unset an attribute from an attribute map");
|
||||||
}
|
}
|
||||||
|
@ -32,8 +32,10 @@ use function is_string;
|
|||||||
|
|
||||||
class DataPropertyManager{
|
class DataPropertyManager{
|
||||||
|
|
||||||
|
/** @var mixed[][] */
|
||||||
private $properties = [];
|
private $properties = [];
|
||||||
|
|
||||||
|
/** @var mixed[][] */
|
||||||
private $dirtyProperties = [];
|
private $dirtyProperties = [];
|
||||||
|
|
||||||
public function __construct(){
|
public function __construct(){
|
||||||
|
@ -195,7 +195,8 @@ class Effect{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the default duration this effect will apply for if a duration is not specified.
|
* Returns the default duration (in ticks) this effect will apply for if a duration is not specified.
|
||||||
|
*
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getDefaultDuration() : int{
|
public function getDefaultDuration() : int{
|
||||||
|
@ -75,6 +75,8 @@ class EffectInstance{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Returns the number of ticks remaining until the effect expires.
|
||||||
|
*
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getDuration() : int{
|
public function getDuration() : int{
|
||||||
@ -82,6 +84,8 @@ class EffectInstance{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Sets the number of ticks remaining until the effect expires.
|
||||||
|
*
|
||||||
* @param int $duration
|
* @param int $duration
|
||||||
*
|
*
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
|
@ -317,6 +317,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
|||||||
public const DATA_PLAYER_FLAG_SLEEP = 1;
|
public const DATA_PLAYER_FLAG_SLEEP = 1;
|
||||||
public const DATA_PLAYER_FLAG_DEAD = 2; //TODO: CHECK
|
public const DATA_PLAYER_FLAG_DEAD = 2; //TODO: CHECK
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
public static $entityCount = 1;
|
public static $entityCount = 1;
|
||||||
/** @var string[] */
|
/** @var string[] */
|
||||||
private static $knownEntities = [];
|
private static $knownEntities = [];
|
||||||
@ -463,12 +464,12 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
|||||||
/** @var Block[]|null */
|
/** @var Block[]|null */
|
||||||
protected $blocksAround = null;
|
protected $blocksAround = null;
|
||||||
|
|
||||||
/** @var float|null */
|
/** @var float */
|
||||||
public $lastX = null;
|
public $lastX;
|
||||||
/** @var float|null */
|
/** @var float */
|
||||||
public $lastY = null;
|
public $lastY;
|
||||||
/** @var float|null */
|
/** @var float */
|
||||||
public $lastZ = null;
|
public $lastZ;
|
||||||
|
|
||||||
/** @var Vector3 */
|
/** @var Vector3 */
|
||||||
protected $motion;
|
protected $motion;
|
||||||
@ -504,6 +505,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
|||||||
|
|
||||||
/** @var float */
|
/** @var float */
|
||||||
private $health = 20.0;
|
private $health = 20.0;
|
||||||
|
/** @var int */
|
||||||
private $maxHealth = 20;
|
private $maxHealth = 20;
|
||||||
|
|
||||||
/** @var float */
|
/** @var float */
|
||||||
@ -1102,7 +1104,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
|||||||
$this->justCreated = false;
|
$this->justCreated = false;
|
||||||
|
|
||||||
$changedProperties = $this->propertyManager->getDirty();
|
$changedProperties = $this->propertyManager->getDirty();
|
||||||
if(!empty($changedProperties)){
|
if(count($changedProperties) > 0){
|
||||||
$this->sendData($this->hasSpawned, $changedProperties);
|
$this->sendData($this->hasSpawned, $changedProperties);
|
||||||
$this->propertyManager->clearDirtyProperties();
|
$this->propertyManager->clearDirtyProperties();
|
||||||
}
|
}
|
||||||
@ -1210,15 +1212,19 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected function updateMovement(bool $teleport = false) : void{
|
protected function updateMovement(bool $teleport = false) : void{
|
||||||
//TODO: hack for client-side AI interference: prevent client sided movement when motion is 0
|
|
||||||
$this->setImmobile($this->motion->x == 0 and $this->motion->y == 0 and $this->motion->z == 0);
|
|
||||||
|
|
||||||
$diffPosition = ($this->x - $this->lastX) ** 2 + ($this->y - $this->lastY) ** 2 + ($this->z - $this->lastZ) ** 2;
|
$diffPosition = ($this->x - $this->lastX) ** 2 + ($this->y - $this->lastY) ** 2 + ($this->z - $this->lastZ) ** 2;
|
||||||
$diffRotation = ($this->yaw - $this->lastYaw) ** 2 + ($this->pitch - $this->lastPitch) ** 2;
|
$diffRotation = ($this->yaw - $this->lastYaw) ** 2 + ($this->pitch - $this->lastPitch) ** 2;
|
||||||
|
|
||||||
$diffMotion = $this->motion->subtract($this->lastMotion)->lengthSquared();
|
$diffMotion = $this->motion->subtract($this->lastMotion)->lengthSquared();
|
||||||
|
|
||||||
if($teleport or $diffPosition > 0.0001 or $diffRotation > 1.0){
|
$still = $this->motion->lengthSquared() == 0.0;
|
||||||
|
$wasStill = $this->lastMotion->lengthSquared() == 0.0;
|
||||||
|
if($wasStill !== $still){
|
||||||
|
//TODO: hack for client-side AI interference: prevent client sided movement when motion is 0
|
||||||
|
$this->setImmobile($still);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($teleport or $diffPosition > 0.0001 or $diffRotation > 1.0 or (!$wasStill and $still)){
|
||||||
$this->lastX = $this->x;
|
$this->lastX = $this->x;
|
||||||
$this->lastY = $this->y;
|
$this->lastY = $this->y;
|
||||||
$this->lastZ = $this->z;
|
$this->lastZ = $this->z;
|
||||||
@ -1229,7 +1235,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
|||||||
$this->broadcastMovement($teleport);
|
$this->broadcastMovement($teleport);
|
||||||
}
|
}
|
||||||
|
|
||||||
if($diffMotion > 0.0025 or ($diffMotion > 0.0001 and $this->motion->lengthSquared() <= 0.0001)){ //0.05 ** 2
|
if($diffMotion > 0.0025 or $wasStill !== $still){ //0.05 ** 2
|
||||||
$this->lastMotion = clone $this->motion;
|
$this->lastMotion = clone $this->motion;
|
||||||
|
|
||||||
$this->broadcastMotion();
|
$this->broadcastMotion();
|
||||||
@ -2279,6 +2285,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
|||||||
* @param string $name
|
* @param string $name
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
*
|
*
|
||||||
|
* @return void
|
||||||
* @throws \ErrorException
|
* @throws \ErrorException
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
|
@ -26,5 +26,8 @@ namespace pocketmine\entity;
|
|||||||
|
|
||||||
interface Explosive{
|
interface Explosive{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function explode();
|
public function explode();
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,7 @@ use function array_merge;
|
|||||||
use function array_rand;
|
use function array_rand;
|
||||||
use function array_values;
|
use function array_values;
|
||||||
use function ceil;
|
use function ceil;
|
||||||
|
use function count;
|
||||||
use function in_array;
|
use function in_array;
|
||||||
use function max;
|
use function max;
|
||||||
use function min;
|
use function min;
|
||||||
@ -80,6 +81,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
|||||||
|
|
||||||
/** @var UUID */
|
/** @var UUID */
|
||||||
protected $uuid;
|
protected $uuid;
|
||||||
|
/** @var string */
|
||||||
protected $rawUUID;
|
protected $rawUUID;
|
||||||
|
|
||||||
public $width = 0.6;
|
public $width = 0.6;
|
||||||
@ -89,10 +91,14 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
|||||||
/** @var Skin */
|
/** @var Skin */
|
||||||
protected $skin;
|
protected $skin;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
protected $foodTickTimer = 0;
|
protected $foodTickTimer = 0;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
protected $totalXp = 0;
|
protected $totalXp = 0;
|
||||||
|
/** @var int */
|
||||||
protected $xpSeed;
|
protected $xpSeed;
|
||||||
|
/** @var int */
|
||||||
protected $xpCooldown = 0;
|
protected $xpCooldown = 0;
|
||||||
|
|
||||||
protected $baseOffset = 1.62;
|
protected $baseOffset = 1.62;
|
||||||
@ -554,7 +560,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!empty($equipment)){
|
if(count($equipment) > 0){
|
||||||
$repairItem = $equipment[$k = array_rand($equipment)];
|
$repairItem = $equipment[$k = array_rand($equipment)];
|
||||||
if($repairItem->getDamage() > 0){
|
if($repairItem->getDamage() > 0){
|
||||||
$repairAmount = min($repairItem->getDamage(), $xpValue * 2);
|
$repairAmount = min($repairItem->getDamage(), $xpValue * 2);
|
||||||
|
@ -70,6 +70,7 @@ abstract class Living extends Entity implements Damageable{
|
|||||||
protected $gravity = 0.08;
|
protected $gravity = 0.08;
|
||||||
protected $drag = 0.02;
|
protected $drag = 0.02;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
protected $attackTime = 0;
|
protected $attackTime = 0;
|
||||||
|
|
||||||
/** @var int */
|
/** @var int */
|
||||||
@ -77,6 +78,7 @@ abstract class Living extends Entity implements Damageable{
|
|||||||
/** @var int */
|
/** @var int */
|
||||||
protected $maxDeadTicks = 25;
|
protected $maxDeadTicks = 25;
|
||||||
|
|
||||||
|
/** @var float */
|
||||||
protected $jumpVelocity = 0.42;
|
protected $jumpVelocity = 0.42;
|
||||||
|
|
||||||
/** @var EffectInstance[] */
|
/** @var EffectInstance[] */
|
||||||
@ -263,7 +265,7 @@ abstract class Living extends Entity implements Damageable{
|
|||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function hasEffects() : bool{
|
public function hasEffects() : bool{
|
||||||
return !empty($this->effects);
|
return count($this->effects) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -332,7 +334,7 @@ abstract class Living extends Entity implements Damageable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!empty($colors)){
|
if(count($colors) > 0){
|
||||||
$this->propertyManager->setInt(Entity::DATA_POTION_COLOR, Color::mix(...$colors)->toARGB());
|
$this->propertyManager->setInt(Entity::DATA_POTION_COLOR, Color::mix(...$colors)->toARGB());
|
||||||
$this->propertyManager->setByte(Entity::DATA_POTION_AMBIENT, $ambient ? 1 : 0);
|
$this->propertyManager->setByte(Entity::DATA_POTION_AMBIENT, $ambient ? 1 : 0);
|
||||||
}else{
|
}else{
|
||||||
@ -713,7 +715,7 @@ abstract class Living extends Entity implements Damageable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return !empty($this->effects);
|
return count($this->effects) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -893,7 +895,7 @@ abstract class Living extends Entity implements Damageable{
|
|||||||
*/
|
*/
|
||||||
public function getTargetBlock(int $maxDistance, array $transparent = []) : ?Block{
|
public function getTargetBlock(int $maxDistance, array $transparent = []) : ?Block{
|
||||||
$line = $this->getLineOfSight($maxDistance, 1, $transparent);
|
$line = $this->getLineOfSight($maxDistance, 1, $transparent);
|
||||||
if(!empty($line)){
|
if(count($line) > 0){
|
||||||
return array_shift($line);
|
return array_shift($line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,8 +42,10 @@ class Squid extends WaterAnimal{
|
|||||||
|
|
||||||
/** @var Vector3|null */
|
/** @var Vector3|null */
|
||||||
public $swimDirection = null;
|
public $swimDirection = null;
|
||||||
|
/** @var float */
|
||||||
public $swimSpeed = 0.1;
|
public $swimSpeed = 0.1;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
private $switchDirectionTicker = 0;
|
private $switchDirectionTicker = 0;
|
||||||
|
|
||||||
public function initEntity() : void{
|
public function initEntity() : void{
|
||||||
|
@ -43,6 +43,7 @@ class PrimedTNT extends Entity implements Explosive{
|
|||||||
protected $gravity = 0.04;
|
protected $gravity = 0.04;
|
||||||
protected $drag = 0.02;
|
protected $drag = 0.02;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
protected $fuse;
|
protected $fuse;
|
||||||
|
|
||||||
public $canCollide = false;
|
public $canCollide = false;
|
||||||
|
@ -34,6 +34,7 @@ use pocketmine\item\Potion;
|
|||||||
use pocketmine\network\mcpe\protocol\LevelEventPacket;
|
use pocketmine\network\mcpe\protocol\LevelEventPacket;
|
||||||
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
|
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
|
||||||
use pocketmine\utils\Color;
|
use pocketmine\utils\Color;
|
||||||
|
use function count;
|
||||||
use function round;
|
use function round;
|
||||||
use function sqrt;
|
use function sqrt;
|
||||||
|
|
||||||
@ -63,7 +64,7 @@ class SplashPotion extends Throwable{
|
|||||||
$effects = $this->getPotionEffects();
|
$effects = $this->getPotionEffects();
|
||||||
$hasEffects = true;
|
$hasEffects = true;
|
||||||
|
|
||||||
if(empty($effects)){
|
if(count($effects) === 0){
|
||||||
$colors = [
|
$colors = [
|
||||||
new Color(0x38, 0x5d, 0xc6) //Default colour for splash water bottle and similar with no effects.
|
new Color(0x38, 0x5d, 0xc6) //Default colour for splash water bottle and similar with no effects.
|
||||||
];
|
];
|
||||||
|
@ -35,6 +35,8 @@ interface Cancellable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bool $value
|
* @param bool $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setCancelled(bool $value = true);
|
public function setCancelled(bool $value = true);
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ use pocketmine\entity\Entity;
|
|||||||
use pocketmine\event\Cancellable;
|
use pocketmine\event\Cancellable;
|
||||||
|
|
||||||
class EntityCombustEvent extends EntityEvent implements Cancellable{
|
class EntityCombustEvent extends EntityEvent implements Cancellable{
|
||||||
|
/** @var int */
|
||||||
protected $duration;
|
protected $duration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -99,6 +99,8 @@ class PlayerCreationEvent extends Event{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $class
|
* @param string $class
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setBaseClass($class){
|
public function setBaseClass($class){
|
||||||
if(!is_a($class, $this->baseClass, true)){
|
if(!is_a($class, $this->baseClass, true)){
|
||||||
@ -117,6 +119,8 @@ class PlayerCreationEvent extends Event{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $class
|
* @param string $class
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setPlayerClass($class){
|
public function setPlayerClass($class){
|
||||||
if(!is_a($class, $this->baseClass, true)){
|
if(!is_a($class, $this->baseClass, true)){
|
||||||
|
@ -40,6 +40,7 @@ class PlayerDeathEvent extends EntityDeathEvent{
|
|||||||
|
|
||||||
/** @var TextContainer|string */
|
/** @var TextContainer|string */
|
||||||
private $deathMessage;
|
private $deathMessage;
|
||||||
|
/** @var bool */
|
||||||
private $keepInventory = false;
|
private $keepInventory = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,7 +46,7 @@ abstract class BaseInventory implements Inventory{
|
|||||||
protected $name;
|
protected $name;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
protected $title;
|
protected $title;
|
||||||
/** @var \SplFixedArray|Item[] */
|
/** @var \SplFixedArray|(Item|null)[] */
|
||||||
protected $slots;
|
protected $slots;
|
||||||
/** @var Player[] */
|
/** @var Player[] */
|
||||||
protected $viewers = [];
|
protected $viewers = [];
|
||||||
@ -84,6 +84,8 @@ abstract class BaseInventory implements Inventory{
|
|||||||
* WARNING: If the size is smaller, any items past the new size will be lost.
|
* WARNING: If the size is smaller, any items past the new size will be lost.
|
||||||
*
|
*
|
||||||
* @param int $size
|
* @param int $size
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setSize(int $size){
|
public function setSize(int $size){
|
||||||
$this->slots->setSize($size);
|
$this->slots->setSize($size);
|
||||||
|
@ -142,6 +142,9 @@ class DoubleChestInventory extends ChestInventory implements InventoryHolder{
|
|||||||
return $this->right;
|
return $this->right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function invalidate(){
|
public function invalidate(){
|
||||||
$this->left = null;
|
$this->left = null;
|
||||||
$this->right = null;
|
$this->right = null;
|
||||||
|
@ -53,6 +53,8 @@ class EnderChestInventory extends ChestInventory{
|
|||||||
* Set the holder's position to that of a tile
|
* Set the holder's position to that of a tile
|
||||||
*
|
*
|
||||||
* @param EnderChest $enderChest
|
* @param EnderChest $enderChest
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setHolderPosition(EnderChest $enderChest){
|
public function setHolderPosition(EnderChest $enderChest){
|
||||||
$this->holder->setComponents($enderChest->getFloorX(), $enderChest->getFloorY(), $enderChest->getFloorZ());
|
$this->holder->setComponents($enderChest->getFloorX(), $enderChest->getFloorY(), $enderChest->getFloorZ());
|
||||||
|
@ -44,6 +44,8 @@ class FurnaceRecipe implements Recipe{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Item $item
|
* @param Item $item
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setInput(Item $item){
|
public function setInput(Item $item){
|
||||||
$this->ingredient = clone $item;
|
$this->ingredient = clone $item;
|
||||||
|
@ -39,6 +39,7 @@ class MultiRecipe{
|
|||||||
public const TYPE_FIREWORKS = "00000000-0000-0000-0000-000000000002";
|
public const TYPE_FIREWORKS = "00000000-0000-0000-0000-000000000002";
|
||||||
public const TYPE_MAP_LOCKING_CARTOGRAPHY = "602234E4-CAC1-4353-8BB7-B1EBFF70024B";
|
public const TYPE_MAP_LOCKING_CARTOGRAPHY = "602234E4-CAC1-4353-8BB7-B1EBFF70024B";
|
||||||
|
|
||||||
|
/** @var UUID */
|
||||||
private $uuid;
|
private $uuid;
|
||||||
|
|
||||||
public function __construct(UUID $uuid){
|
public function __construct(UUID $uuid){
|
||||||
|
@ -66,19 +66,23 @@ class PlayerInventory extends BaseInventory{
|
|||||||
* @return bool if the equipment change was successful, false if not.
|
* @return bool if the equipment change was successful, false if not.
|
||||||
*/
|
*/
|
||||||
public function equipItem(int $hotbarSlot) : bool{
|
public function equipItem(int $hotbarSlot) : bool{
|
||||||
|
$holder = $this->getHolder();
|
||||||
if(!$this->isHotbarSlot($hotbarSlot)){
|
if(!$this->isHotbarSlot($hotbarSlot)){
|
||||||
$this->sendContents($this->getHolder());
|
if($holder instanceof Player){
|
||||||
|
$this->sendContents($holder);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$ev = new PlayerItemHeldEvent($this->getHolder(), $this->getItem($hotbarSlot), $hotbarSlot);
|
if($holder instanceof Player){
|
||||||
$ev->call();
|
$ev = new PlayerItemHeldEvent($holder, $this->getItem($hotbarSlot), $hotbarSlot);
|
||||||
|
$ev->call();
|
||||||
|
|
||||||
if($ev->isCancelled()){
|
if($ev->isCancelled()){
|
||||||
$this->sendHeldItem($this->getHolder());
|
$this->sendHeldItem($holder);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->setHeldItemIndex($hotbarSlot, false);
|
$this->setHeldItemIndex($hotbarSlot, false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -93,7 +97,7 @@ class PlayerInventory extends BaseInventory{
|
|||||||
*
|
*
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
private function throwIfNotHotbarSlot(int $slot){
|
private function throwIfNotHotbarSlot(int $slot) : void{
|
||||||
if(!$this->isHotbarSlot($slot)){
|
if(!$this->isHotbarSlot($slot)){
|
||||||
throw new \InvalidArgumentException("$slot is not a valid hotbar slot index (expected 0 - " . ($this->getHotbarSize() - 1) . ")");
|
throw new \InvalidArgumentException("$slot is not a valid hotbar slot index (expected 0 - " . ($this->getHotbarSize() - 1) . ")");
|
||||||
}
|
}
|
||||||
@ -128,6 +132,7 @@ class PlayerInventory extends BaseInventory{
|
|||||||
* @param bool $send Whether to send updates back to the inventory holder. This should usually be true for plugin calls.
|
* @param bool $send Whether to send updates back to the inventory holder. This should usually be true for plugin calls.
|
||||||
* It should only be false to prevent feedback loops of equipment packets between client and server.
|
* It should only be false to prevent feedback loops of equipment packets between client and server.
|
||||||
*
|
*
|
||||||
|
* @return void
|
||||||
* @throws \InvalidArgumentException if the hotbar slot is out of range
|
* @throws \InvalidArgumentException if the hotbar slot is out of range
|
||||||
*/
|
*/
|
||||||
public function setHeldItemIndex(int $hotbarSlot, bool $send = true){
|
public function setHeldItemIndex(int $hotbarSlot, bool $send = true){
|
||||||
@ -166,6 +171,8 @@ class PlayerInventory extends BaseInventory{
|
|||||||
* Sends the currently-held item to specified targets.
|
* Sends the currently-held item to specified targets.
|
||||||
*
|
*
|
||||||
* @param Player|Player[] $target
|
* @param Player|Player[] $target
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function sendHeldItem($target){
|
public function sendHeldItem($target){
|
||||||
$item = $this->getItemInHand();
|
$item = $this->getItemInHand();
|
||||||
@ -197,6 +204,9 @@ class PlayerInventory extends BaseInventory{
|
|||||||
return 9;
|
return 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function sendCreativeContents(){
|
public function sendCreativeContents(){
|
||||||
//TODO: this mess shouldn't be in here
|
//TODO: this mess shouldn't be in here
|
||||||
$holder = $this->getHolder();
|
$holder = $this->getHolder();
|
||||||
|
@ -135,6 +135,6 @@ class ShapelessRecipe implements CraftingRecipe{
|
|||||||
return false; //failed to match the needed item to a given item
|
return false; //failed to match the needed item to a given item
|
||||||
}
|
}
|
||||||
|
|
||||||
return empty($input); //crafting grid should be empty apart from the given ingredient stacks
|
return count($input) === 0; //crafting grid should be empty apart from the given ingredient stacks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,14 +68,14 @@ class CraftingTransaction extends InventoryTransaction{
|
|||||||
* @throws TransactionValidationException
|
* @throws TransactionValidationException
|
||||||
*/
|
*/
|
||||||
protected function matchRecipeItems(array $txItems, array $recipeItems, bool $wildcards, int $iterations = 0) : int{
|
protected function matchRecipeItems(array $txItems, array $recipeItems, bool $wildcards, int $iterations = 0) : int{
|
||||||
if(empty($recipeItems)){
|
if(count($recipeItems) === 0){
|
||||||
throw new TransactionValidationException("No recipe items given");
|
throw new TransactionValidationException("No recipe items given");
|
||||||
}
|
}
|
||||||
if(empty($txItems)){
|
if(count($txItems) === 0){
|
||||||
throw new TransactionValidationException("No transaction items given");
|
throw new TransactionValidationException("No transaction items given");
|
||||||
}
|
}
|
||||||
|
|
||||||
while(!empty($recipeItems)){
|
while(count($recipeItems) > 0){
|
||||||
/** @var Item $recipeItem */
|
/** @var Item $recipeItem */
|
||||||
$recipeItem = array_pop($recipeItems);
|
$recipeItem = array_pop($recipeItems);
|
||||||
$needCount = $recipeItem->getCount();
|
$needCount = $recipeItem->getCount();
|
||||||
@ -114,7 +114,7 @@ class CraftingTransaction extends InventoryTransaction{
|
|||||||
if($iterations < 1){
|
if($iterations < 1){
|
||||||
throw new TransactionValidationException("Tried to craft zero times");
|
throw new TransactionValidationException("Tried to craft zero times");
|
||||||
}
|
}
|
||||||
if(!empty($txItems)){
|
if(count($txItems) > 0){
|
||||||
//all items should be destroyed in this process
|
//all items should be destroyed in this process
|
||||||
throw new TransactionValidationException("Expected 0 ingredients left over, have " . count($txItems));
|
throw new TransactionValidationException("Expected 0 ingredients left over, have " . count($txItems));
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,7 @@ use function spl_object_hash;
|
|||||||
* @see InventoryAction
|
* @see InventoryAction
|
||||||
*/
|
*/
|
||||||
class InventoryTransaction{
|
class InventoryTransaction{
|
||||||
|
/** @var bool */
|
||||||
protected $hasExecuted = false;
|
protected $hasExecuted = false;
|
||||||
/** @var Player */
|
/** @var Player */
|
||||||
protected $source;
|
protected $source;
|
||||||
@ -237,13 +238,13 @@ class InventoryTransaction{
|
|||||||
* @return null|Item
|
* @return null|Item
|
||||||
*/
|
*/
|
||||||
protected function findResultItem(Item $needOrigin, array $possibleActions) : ?Item{
|
protected function findResultItem(Item $needOrigin, array $possibleActions) : ?Item{
|
||||||
assert(!empty($possibleActions));
|
assert(count($possibleActions) > 0);
|
||||||
|
|
||||||
foreach($possibleActions as $i => $action){
|
foreach($possibleActions as $i => $action){
|
||||||
if($action->getSourceItem()->equalsExact($needOrigin)){
|
if($action->getSourceItem()->equalsExact($needOrigin)){
|
||||||
$newList = $possibleActions;
|
$newList = $possibleActions;
|
||||||
unset($newList[$i]);
|
unset($newList[$i]);
|
||||||
if(empty($newList)){
|
if(count($newList) === 0){
|
||||||
return $action->getTargetItem();
|
return $action->getTargetItem();
|
||||||
}
|
}
|
||||||
$result = $this->findResultItem($action->getTargetItem(), $newList);
|
$result = $this->findResultItem($action->getTargetItem(), $newList);
|
||||||
|
@ -37,6 +37,7 @@ class CreativeInventoryAction extends InventoryAction{
|
|||||||
*/
|
*/
|
||||||
public const TYPE_CREATE_ITEM = 1;
|
public const TYPE_CREATE_ITEM = 1;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
protected $actionType;
|
protected $actionType;
|
||||||
|
|
||||||
public function __construct(Item $sourceItem, Item $targetItem, int $actionType){
|
public function __construct(Item $sourceItem, Item $targetItem, int $actionType){
|
||||||
|
@ -49,6 +49,8 @@ interface Consumable{
|
|||||||
* Called when this Consumable is consumed by mob, after standard resulting effects have been applied.
|
* Called when this Consumable is consumed by mob, after standard resulting effects have been applied.
|
||||||
*
|
*
|
||||||
* @param Living $consumer
|
* @param Living $consumer
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function onConsume(Living $consumer);
|
public function onConsume(Living $consumer);
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,8 @@ abstract class Durable extends Item{
|
|||||||
* Sets whether the item will take damage when used.
|
* Sets whether the item will take damage when used.
|
||||||
*
|
*
|
||||||
* @param bool $value
|
* @param bool $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setUnbreakable(bool $value = true){
|
public function setUnbreakable(bool $value = true){
|
||||||
$this->setNamedTagEntry(new ByteTag("Unbreakable", $value ? 1 : 0));
|
$this->setNamedTagEntry(new ByteTag("Unbreakable", $value ? 1 : 0));
|
||||||
|
@ -123,6 +123,9 @@ class Item implements ItemIds, \JsonSerializable{
|
|||||||
/** @var Item[] */
|
/** @var Item[] */
|
||||||
private static $creative = [];
|
private static $creative = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public static function initCreativeItems(){
|
public static function initCreativeItems(){
|
||||||
self::clearCreativeItems();
|
self::clearCreativeItems();
|
||||||
|
|
||||||
@ -140,6 +143,8 @@ class Item implements ItemIds, \JsonSerializable{
|
|||||||
/**
|
/**
|
||||||
* Removes all previously added items from the creative menu.
|
* Removes all previously added items from the creative menu.
|
||||||
* Note: Players who are already online when this is called will not see this change.
|
* Note: Players who are already online when this is called will not see this change.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function clearCreativeItems(){
|
public static function clearCreativeItems(){
|
||||||
Item::$creative = [];
|
Item::$creative = [];
|
||||||
@ -154,6 +159,8 @@ class Item implements ItemIds, \JsonSerializable{
|
|||||||
* Note: Players who are already online when this is called will not see this change.
|
* Note: Players who are already online when this is called will not see this change.
|
||||||
*
|
*
|
||||||
* @param Item $item
|
* @param Item $item
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function addCreativeItem(Item $item){
|
public static function addCreativeItem(Item $item){
|
||||||
Item::$creative[] = clone $item;
|
Item::$creative[] = clone $item;
|
||||||
@ -164,6 +171,8 @@ class Item implements ItemIds, \JsonSerializable{
|
|||||||
* Note: Players who are already online when this is called will not see this change.
|
* Note: Players who are already online when this is called will not see this change.
|
||||||
*
|
*
|
||||||
* @param Item $item
|
* @param Item $item
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function removeCreativeItem(Item $item){
|
public static function removeCreativeItem(Item $item){
|
||||||
$index = self::getCreativeItemIndex($item);
|
$index = self::getCreativeItemIndex($item);
|
||||||
@ -233,7 +242,7 @@ class Item implements ItemIds, \JsonSerializable{
|
|||||||
*
|
*
|
||||||
* @param CompoundTag|string|null $tags
|
* @param CompoundTag|string|null $tags
|
||||||
*
|
*
|
||||||
* @return Item
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setCompoundTag($tags) : Item{
|
public function setCompoundTag($tags) : Item{
|
||||||
if($tags instanceof CompoundTag){
|
if($tags instanceof CompoundTag){
|
||||||
@ -272,6 +281,9 @@ class Item implements ItemIds, \JsonSerializable{
|
|||||||
return $this->getNamedTagEntry(self::TAG_BLOCK_ENTITY_TAG) instanceof CompoundTag;
|
return $this->getNamedTagEntry(self::TAG_BLOCK_ENTITY_TAG) instanceof CompoundTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
public function clearCustomBlockData(){
|
public function clearCustomBlockData(){
|
||||||
$this->removeNamedTagEntry(self::TAG_BLOCK_ENTITY_TAG);
|
$this->removeNamedTagEntry(self::TAG_BLOCK_ENTITY_TAG);
|
||||||
return $this;
|
return $this;
|
||||||
@ -280,7 +292,7 @@ class Item implements ItemIds, \JsonSerializable{
|
|||||||
/**
|
/**
|
||||||
* @param CompoundTag $compound
|
* @param CompoundTag $compound
|
||||||
*
|
*
|
||||||
* @return Item
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setCustomBlockData(CompoundTag $compound) : Item{
|
public function setCustomBlockData(CompoundTag $compound) : Item{
|
||||||
$tags = clone $compound;
|
$tags = clone $compound;
|
||||||
@ -479,7 +491,7 @@ class Item implements ItemIds, \JsonSerializable{
|
|||||||
/**
|
/**
|
||||||
* @param string $name
|
* @param string $name
|
||||||
*
|
*
|
||||||
* @return Item
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setCustomName(string $name) : Item{
|
public function setCustomName(string $name) : Item{
|
||||||
if($name === ""){
|
if($name === ""){
|
||||||
@ -499,7 +511,7 @@ class Item implements ItemIds, \JsonSerializable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Item
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function clearCustomName() : Item{
|
public function clearCustomName() : Item{
|
||||||
$display = $this->getNamedTagEntry(self::TAG_DISPLAY);
|
$display = $this->getNamedTagEntry(self::TAG_DISPLAY);
|
||||||
@ -531,7 +543,7 @@ class Item implements ItemIds, \JsonSerializable{
|
|||||||
/**
|
/**
|
||||||
* @param string[] $lines
|
* @param string[] $lines
|
||||||
*
|
*
|
||||||
* @return Item
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setLore(array $lines) : Item{
|
public function setLore(array $lines) : Item{
|
||||||
$display = $this->getNamedTagEntry(self::TAG_DISPLAY);
|
$display = $this->getNamedTagEntry(self::TAG_DISPLAY);
|
||||||
@ -588,7 +600,7 @@ class Item implements ItemIds, \JsonSerializable{
|
|||||||
*
|
*
|
||||||
* @param CompoundTag $tag
|
* @param CompoundTag $tag
|
||||||
*
|
*
|
||||||
* @return Item
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setNamedTag(CompoundTag $tag) : Item{
|
public function setNamedTag(CompoundTag $tag) : Item{
|
||||||
if($tag->getCount() === 0){
|
if($tag->getCount() === 0){
|
||||||
@ -603,7 +615,7 @@ class Item implements ItemIds, \JsonSerializable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the Item's NBT.
|
* Removes the Item's NBT.
|
||||||
* @return Item
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function clearNamedTag() : Item{
|
public function clearNamedTag() : Item{
|
||||||
return $this->setCompoundTag("");
|
return $this->setCompoundTag("");
|
||||||
@ -619,7 +631,7 @@ class Item implements ItemIds, \JsonSerializable{
|
|||||||
/**
|
/**
|
||||||
* @param int $count
|
* @param int $count
|
||||||
*
|
*
|
||||||
* @return Item
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setCount(int $count) : Item{
|
public function setCount(int $count) : Item{
|
||||||
$this->count = $count;
|
$this->count = $count;
|
||||||
@ -632,7 +644,7 @@ class Item implements ItemIds, \JsonSerializable{
|
|||||||
*
|
*
|
||||||
* @param int $count
|
* @param int $count
|
||||||
*
|
*
|
||||||
* @return Item
|
* @return $this
|
||||||
* @throws \InvalidArgumentException if trying to pop more items than are on the stack
|
* @throws \InvalidArgumentException if trying to pop more items than are on the stack
|
||||||
*/
|
*/
|
||||||
public function pop(int $count = 1) : Item{
|
public function pop(int $count = 1) : Item{
|
||||||
@ -700,7 +712,7 @@ class Item implements ItemIds, \JsonSerializable{
|
|||||||
/**
|
/**
|
||||||
* @param int $meta
|
* @param int $meta
|
||||||
*
|
*
|
||||||
* @return Item
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setDamage(int $meta) : Item{
|
public function setDamage(int $meta) : Item{
|
||||||
$this->meta = $meta !== -1 ? $meta & 0x7FFF : -1;
|
$this->meta = $meta !== -1 ? $meta & 0x7FFF : -1;
|
||||||
|
@ -46,6 +46,9 @@ class ItemFactory{
|
|||||||
/** @var \SplFixedArray */
|
/** @var \SplFixedArray */
|
||||||
private static $list = null;
|
private static $list = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public static function init(){
|
public static function init(){
|
||||||
self::$list = new \SplFixedArray(65536);
|
self::$list = new \SplFixedArray(65536);
|
||||||
|
|
||||||
@ -285,6 +288,7 @@ class ItemFactory{
|
|||||||
* @param Item $item
|
* @param Item $item
|
||||||
* @param bool $override
|
* @param bool $override
|
||||||
*
|
*
|
||||||
|
* @return void
|
||||||
* @throws \RuntimeException if something attempted to override an already-registered item without specifying the
|
* @throws \RuntimeException if something attempted to override an already-registered item without specifying the
|
||||||
* $override parameter.
|
* $override parameter.
|
||||||
*/
|
*/
|
||||||
|
@ -31,6 +31,7 @@ use pocketmine\math\Vector3;
|
|||||||
use pocketmine\network\mcpe\protocol\LevelEventPacket;
|
use pocketmine\network\mcpe\protocol\LevelEventPacket;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
use function array_rand;
|
use function array_rand;
|
||||||
|
use function count;
|
||||||
|
|
||||||
class PaintingItem extends Item{
|
class PaintingItem extends Item{
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(int $meta = 0){
|
||||||
@ -66,7 +67,7 @@ class PaintingItem extends Item{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(empty($motives)){ //No space available
|
if(count($motives) === 0){ //No space available
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,6 +155,9 @@ class Enchantment{
|
|||||||
* @return Enchantment|null
|
* @return Enchantment|null
|
||||||
*/
|
*/
|
||||||
public static function getEnchantment(int $id) : ?Enchantment{
|
public static function getEnchantment(int $id) : ?Enchantment{
|
||||||
|
if($id < 0 or $id >= self::$enchantments->getSize()){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return self::$enchantments[$id] ?? null;
|
return self::$enchantments[$id] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,6 +105,12 @@ class BaseLang{
|
|||||||
return $this->langName;
|
return $this->langName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $path
|
||||||
|
* @param string[] $d reference parameter
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
protected static function loadLang(string $path, array &$d){
|
protected static function loadLang(string $path, array &$d){
|
||||||
if(file_exists($path)){
|
if(file_exists($path)){
|
||||||
$d = array_map('\stripcslashes', parse_ini_file($path, false, INI_SCANNER_RAW));
|
$d = array_map('\stripcslashes', parse_ini_file($path, false, INI_SCANNER_RAW));
|
||||||
@ -115,9 +121,9 @@ class BaseLang{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $str
|
* @param string $str
|
||||||
* @param string[] $params
|
* @param (float|int|string)[] $params
|
||||||
* @param string|null $onlyPrefix
|
* @param string|null $onlyPrefix
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
@ -132,6 +138,11 @@ class BaseLang{
|
|||||||
return $baseText;
|
return $baseText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param TextContainer $c
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function translate(TextContainer $c){
|
public function translate(TextContainer $c){
|
||||||
if($c instanceof TranslationContainer){
|
if($c instanceof TranslationContainer){
|
||||||
$baseText = $this->internalGet($c->getText());
|
$baseText = $this->internalGet($c->getText());
|
||||||
|
@ -37,6 +37,8 @@ class TextContainer{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $text
|
* @param string $text
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setText(string $text){
|
public function setText(string $text){
|
||||||
$this->text = $text;
|
$this->text = $text;
|
||||||
|
@ -31,8 +31,8 @@ class TranslationContainer extends TextContainer{
|
|||||||
protected $params = [];
|
protected $params = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $text
|
* @param string $text
|
||||||
* @param string[] $params
|
* @param (float|int|string)[] $params
|
||||||
*/
|
*/
|
||||||
public function __construct(string $text, array $params = []){
|
public function __construct(string $text, array $params = []){
|
||||||
parent::__construct($text);
|
parent::__construct($text);
|
||||||
@ -59,6 +59,8 @@ class TranslationContainer extends TextContainer{
|
|||||||
/**
|
/**
|
||||||
* @param int $i
|
* @param int $i
|
||||||
* @param string $str
|
* @param string $str
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setParameter(int $i, string $str){
|
public function setParameter(int $i, string $str){
|
||||||
if($i < 0 or $i > count($this->params)){ //Intended, allow to set the last
|
if($i < 0 or $i > count($this->params)){ //Intended, allow to set the last
|
||||||
@ -70,6 +72,8 @@ class TranslationContainer extends TextContainer{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string[] $params
|
* @param string[] $params
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setParameters(array $params){
|
public function setParameters(array $params){
|
||||||
$i = 0;
|
$i = 0;
|
||||||
|
@ -78,6 +78,8 @@ interface ChunkLoader{
|
|||||||
* This method will be called when a Chunk is replaced by a new one
|
* This method will be called when a Chunk is replaced by a new one
|
||||||
*
|
*
|
||||||
* @param Chunk $chunk
|
* @param Chunk $chunk
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function onChunkChanged(Chunk $chunk);
|
public function onChunkChanged(Chunk $chunk);
|
||||||
|
|
||||||
@ -85,6 +87,8 @@ interface ChunkLoader{
|
|||||||
* This method will be called when a registered chunk is loaded
|
* This method will be called when a registered chunk is loaded
|
||||||
*
|
*
|
||||||
* @param Chunk $chunk
|
* @param Chunk $chunk
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function onChunkLoaded(Chunk $chunk);
|
public function onChunkLoaded(Chunk $chunk);
|
||||||
|
|
||||||
@ -93,6 +97,8 @@ interface ChunkLoader{
|
|||||||
* This method will be called when a registered chunk is unloaded
|
* This method will be called when a registered chunk is unloaded
|
||||||
*
|
*
|
||||||
* @param Chunk $chunk
|
* @param Chunk $chunk
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function onChunkUnloaded(Chunk $chunk);
|
public function onChunkUnloaded(Chunk $chunk);
|
||||||
|
|
||||||
@ -101,6 +107,8 @@ interface ChunkLoader{
|
|||||||
* Usually it'll be sent with another call to onChunkChanged()
|
* Usually it'll be sent with another call to onChunkChanged()
|
||||||
*
|
*
|
||||||
* @param Chunk $chunk
|
* @param Chunk $chunk
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function onChunkPopulated(Chunk $chunk);
|
public function onChunkPopulated(Chunk $chunk);
|
||||||
|
|
||||||
@ -108,6 +116,8 @@ interface ChunkLoader{
|
|||||||
* This method will be called when a block changes in a registered chunk
|
* This method will be called when a block changes in a registered chunk
|
||||||
*
|
*
|
||||||
* @param Block|Vector3 $block
|
* @param Block|Vector3 $block
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function onBlockChanged(Vector3 $block);
|
public function onBlockChanged(Vector3 $block);
|
||||||
|
|
||||||
|
@ -44,6 +44,8 @@ interface ChunkManager{
|
|||||||
* @param int $y
|
* @param int $y
|
||||||
* @param int $z
|
* @param int $z
|
||||||
* @param int $id 0-255
|
* @param int $id 0-255
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setBlockIdAt(int $x, int $y, int $z, int $id);
|
public function setBlockIdAt(int $x, int $y, int $z, int $id);
|
||||||
|
|
||||||
@ -65,6 +67,8 @@ interface ChunkManager{
|
|||||||
* @param int $y
|
* @param int $y
|
||||||
* @param int $z
|
* @param int $z
|
||||||
* @param int $data 0-15
|
* @param int $data 0-15
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setBlockDataAt(int $x, int $y, int $z, int $data);
|
public function setBlockDataAt(int $x, int $y, int $z, int $data);
|
||||||
|
|
||||||
@ -86,6 +90,8 @@ interface ChunkManager{
|
|||||||
* @param int $y
|
* @param int $y
|
||||||
* @param int $z
|
* @param int $z
|
||||||
* @param int $level
|
* @param int $level
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setBlockLightAt(int $x, int $y, int $z, int $level);
|
public function setBlockLightAt(int $x, int $y, int $z, int $level);
|
||||||
|
|
||||||
@ -107,6 +113,8 @@ interface ChunkManager{
|
|||||||
* @param int $y
|
* @param int $y
|
||||||
* @param int $z
|
* @param int $z
|
||||||
* @param int $level
|
* @param int $level
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setBlockSkyLightAt(int $x, int $y, int $z, int $level);
|
public function setBlockSkyLightAt(int $x, int $y, int $z, int $level);
|
||||||
|
|
||||||
@ -122,6 +130,8 @@ interface ChunkManager{
|
|||||||
* @param int $chunkX
|
* @param int $chunkX
|
||||||
* @param int $chunkZ
|
* @param int $chunkZ
|
||||||
* @param Chunk|null $chunk
|
* @param Chunk|null $chunk
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setChunk(int $chunkX, int $chunkZ, Chunk $chunk = null);
|
public function setChunk(int $chunkX, int $chunkZ, Chunk $chunk = null);
|
||||||
|
|
||||||
|
@ -123,6 +123,10 @@ class Explosion{
|
|||||||
$vBlock->y = $pointerY >= $y ? $y : $y - 1;
|
$vBlock->y = $pointerY >= $y ? $y : $y - 1;
|
||||||
$vBlock->z = $pointerZ >= $z ? $z : $z - 1;
|
$vBlock->z = $pointerZ >= $z ? $z : $z - 1;
|
||||||
|
|
||||||
|
$pointerX += $vector->x;
|
||||||
|
$pointerY += $vector->y;
|
||||||
|
$pointerZ += $vector->z;
|
||||||
|
|
||||||
if(!$this->subChunkHandler->moveTo($vBlock->x, $vBlock->y, $vBlock->z)){
|
if(!$this->subChunkHandler->moveTo($vBlock->x, $vBlock->y, $vBlock->z)){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -137,10 +141,6 @@ class Explosion{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$pointerX += $vector->x;
|
|
||||||
$pointerY += $vector->y;
|
|
||||||
$pointerZ += $vector->z;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,9 @@ use const PHP_INT_MIN;
|
|||||||
|
|
||||||
class Level implements ChunkManager, Metadatable{
|
class Level implements ChunkManager, Metadatable{
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
private static $levelIdCounter = 1;
|
private static $levelIdCounter = 1;
|
||||||
|
/** @var int */
|
||||||
private static $chunkLoaderCounter = 1;
|
private static $chunkLoaderCounter = 1;
|
||||||
|
|
||||||
public const Y_MASK = 0xFF;
|
public const Y_MASK = 0xFF;
|
||||||
@ -433,6 +435,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
/**
|
/**
|
||||||
* @deprecated does nothing
|
* @deprecated does nothing
|
||||||
* @param int $tickRate
|
* @param int $tickRate
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setTickRate(int $tickRate){
|
public function setTickRate(int $tickRate){
|
||||||
|
|
||||||
@ -443,6 +447,9 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
$this->server->getAsyncPool()->submitTaskToWorker(new GeneratorRegisterTask($this, $this->generator, $this->provider->getGeneratorOptions()), $worker);
|
$this->server->getAsyncPool()->submitTaskToWorker(new GeneratorRegisterTask($this, $this->generator, $this->provider->getGeneratorOptions()), $worker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function unregisterGenerator(){
|
public function unregisterGenerator(){
|
||||||
$pool = $this->server->getAsyncPool();
|
$pool = $this->server->getAsyncPool();
|
||||||
foreach($pool->getRunningWorkers() as $i){
|
foreach($pool->getRunningWorkers() as $i){
|
||||||
@ -476,6 +483,9 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
return $this->closed;
|
return $this->closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function close(){
|
public function close(){
|
||||||
if($this->closed){
|
if($this->closed){
|
||||||
throw new \InvalidStateException("Tried to close a world which is already closed");
|
throw new \InvalidStateException("Tried to close a world which is already closed");
|
||||||
@ -498,12 +508,18 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
$this->closed = true;
|
$this->closed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Sound $sound
|
||||||
|
* @param Player[]|null $players
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function addSound(Sound $sound, array $players = null){
|
public function addSound(Sound $sound, array $players = null){
|
||||||
$pk = $sound->encode();
|
$pk = $sound->encode();
|
||||||
if(!is_array($pk)){
|
if(!is_array($pk)){
|
||||||
$pk = [$pk];
|
$pk = [$pk];
|
||||||
}
|
}
|
||||||
if(!empty($pk)){
|
if(count($pk) > 0){
|
||||||
if($players === null){
|
if($players === null){
|
||||||
foreach($pk as $e){
|
foreach($pk as $e){
|
||||||
$this->broadcastPacketToViewers($sound, $e);
|
$this->broadcastPacketToViewers($sound, $e);
|
||||||
@ -514,12 +530,18 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Particle $particle
|
||||||
|
* @param Player[]|null $players
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function addParticle(Particle $particle, array $players = null){
|
public function addParticle(Particle $particle, array $players = null){
|
||||||
$pk = $particle->encode();
|
$pk = $particle->encode();
|
||||||
if(!is_array($pk)){
|
if(!is_array($pk)){
|
||||||
$pk = [$pk];
|
$pk = [$pk];
|
||||||
}
|
}
|
||||||
if(!empty($pk)){
|
if(count($pk) > 0){
|
||||||
if($players === null){
|
if($players === null){
|
||||||
foreach($pk as $e){
|
foreach($pk as $e){
|
||||||
$this->broadcastPacketToViewers($particle, $e);
|
$this->broadcastPacketToViewers($particle, $e);
|
||||||
@ -536,6 +558,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
* @param Vector3|null $pos If null, broadcasts to every player in the Level
|
* @param Vector3|null $pos If null, broadcasts to every player in the Level
|
||||||
* @param int $evid
|
* @param int $evid
|
||||||
* @param int $data
|
* @param int $data
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function broadcastLevelEvent(?Vector3 $pos, int $evid, int $data = 0){
|
public function broadcastLevelEvent(?Vector3 $pos, int $evid, int $data = 0){
|
||||||
$pk = new LevelEventPacket();
|
$pk = new LevelEventPacket();
|
||||||
@ -559,6 +583,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
* @param int $entityTypeId
|
* @param int $entityTypeId
|
||||||
* @param bool $isBabyMob
|
* @param bool $isBabyMob
|
||||||
* @param bool $disableRelativeVolume If true, all players receiving this sound-event will hear the sound at full volume regardless of distance
|
* @param bool $disableRelativeVolume If true, all players receiving this sound-event will hear the sound at full volume regardless of distance
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function broadcastLevelSoundEvent(Vector3 $pos, int $soundId, int $extraData = -1, int $entityTypeId = -1, bool $isBabyMob = false, bool $disableRelativeVolume = false){
|
public function broadcastLevelSoundEvent(Vector3 $pos, int $soundId, int $extraData = -1, int $entityTypeId = -1, bool $isBabyMob = false, bool $disableRelativeVolume = false){
|
||||||
$pk = new LevelSoundEventPacket();
|
$pk = new LevelSoundEventPacket();
|
||||||
@ -575,6 +601,11 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
return $this->autoSave;
|
return $this->autoSave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function setAutoSave(bool $value){
|
public function setAutoSave(bool $value){
|
||||||
$this->autoSave = $value;
|
$this->autoSave = $value;
|
||||||
}
|
}
|
||||||
@ -672,6 +703,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
* @param int $chunkX
|
* @param int $chunkX
|
||||||
* @param int $chunkZ
|
* @param int $chunkZ
|
||||||
* @param DataPacket $packet
|
* @param DataPacket $packet
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function addChunkPacket(int $chunkX, int $chunkZ, DataPacket $packet){
|
public function addChunkPacket(int $chunkX, int $chunkZ, DataPacket $packet){
|
||||||
if(!isset($this->chunkPackets[$index = Level::chunkHash($chunkX, $chunkZ)])){
|
if(!isset($this->chunkPackets[$index = Level::chunkHash($chunkX, $chunkZ)])){
|
||||||
@ -710,6 +743,14 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
$this->globalPackets[] = $packet;
|
$this->globalPackets[] = $packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ChunkLoader $loader
|
||||||
|
* @param int $chunkX
|
||||||
|
* @param int $chunkZ
|
||||||
|
* @param bool $autoLoad
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function registerChunkLoader(ChunkLoader $loader, int $chunkX, int $chunkZ, bool $autoLoad = true){
|
public function registerChunkLoader(ChunkLoader $loader, int $chunkX, int $chunkZ, bool $autoLoad = true){
|
||||||
$loaderId = $loader->getLoaderId();
|
$loaderId = $loader->getLoaderId();
|
||||||
|
|
||||||
@ -739,6 +780,13 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ChunkLoader $loader
|
||||||
|
* @param int $chunkX
|
||||||
|
* @param int $chunkZ
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function unregisterChunkLoader(ChunkLoader $loader, int $chunkX, int $chunkZ){
|
public function unregisterChunkLoader(ChunkLoader $loader, int $chunkX, int $chunkZ){
|
||||||
$chunkHash = Level::chunkHash($chunkX, $chunkZ);
|
$chunkHash = Level::chunkHash($chunkX, $chunkZ);
|
||||||
$loaderId = $loader->getLoaderId();
|
$loaderId = $loader->getLoaderId();
|
||||||
@ -762,6 +810,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
* @internal
|
* @internal
|
||||||
*
|
*
|
||||||
* @param Player ...$targets If empty, will send to all players in the level.
|
* @param Player ...$targets If empty, will send to all players in the level.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function sendTime(Player ...$targets){
|
public function sendTime(Player ...$targets){
|
||||||
$pk = new SetTimePacket();
|
$pk = new SetTimePacket();
|
||||||
@ -775,6 +825,7 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
*
|
*
|
||||||
* @param int $currentTick
|
* @param int $currentTick
|
||||||
*
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function doTick(int $currentTick){
|
public function doTick(int $currentTick){
|
||||||
if($this->closed){
|
if($this->closed){
|
||||||
@ -881,7 +932,7 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
if(count($this->changedBlocks) > 0){
|
if(count($this->changedBlocks) > 0){
|
||||||
if(count($this->players) > 0){
|
if(count($this->players) > 0){
|
||||||
foreach($this->changedBlocks as $index => $blocks){
|
foreach($this->changedBlocks as $index => $blocks){
|
||||||
if(empty($blocks)){ //blocks can be set normally and then later re-set with direct send
|
if(count($blocks) === 0){ //blocks can be set normally and then later re-set with direct send
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
unset($this->chunkCache[$index]);
|
unset($this->chunkCache[$index]);
|
||||||
@ -909,8 +960,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
$this->checkSleep();
|
$this->checkSleep();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!empty($this->globalPackets)){
|
if(count($this->globalPackets) > 0){
|
||||||
if(!empty($this->players)){
|
if(count($this->players) > 0){
|
||||||
$this->server->batchPackets($this->players, $this->globalPackets);
|
$this->server->batchPackets($this->players, $this->globalPackets);
|
||||||
}
|
}
|
||||||
$this->globalPackets = [];
|
$this->globalPackets = [];
|
||||||
@ -927,6 +978,9 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
$this->chunkPackets = [];
|
$this->chunkPackets = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function checkSleep(){
|
public function checkSleep(){
|
||||||
if(count($this->players) === 0){
|
if(count($this->players) === 0){
|
||||||
return;
|
return;
|
||||||
@ -962,6 +1016,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
* @param Vector3[] $blocks
|
* @param Vector3[] $blocks
|
||||||
* @param int $flags
|
* @param int $flags
|
||||||
* @param bool $optimizeRebuilds
|
* @param bool $optimizeRebuilds
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function sendBlocks(array $target, array $blocks, int $flags = UpdateBlockPacket::FLAG_NONE, bool $optimizeRebuilds = false){
|
public function sendBlocks(array $target, array $blocks, int $flags = UpdateBlockPacket::FLAG_NONE, bool $optimizeRebuilds = false){
|
||||||
$packets = [];
|
$packets = [];
|
||||||
@ -1021,6 +1077,11 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
$this->server->batchPackets($target, $packets, false, false);
|
$this->server->batchPackets($target, $packets, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $force
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function clearCache(bool $force = false){
|
public function clearCache(bool $force = false){
|
||||||
if($force){
|
if($force){
|
||||||
$this->chunkCache = [];
|
$this->chunkCache = [];
|
||||||
@ -1037,6 +1098,12 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $chunkX
|
||||||
|
* @param int $chunkZ
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function clearChunkCache(int $chunkX, int $chunkZ){
|
public function clearChunkCache(int $chunkX, int $chunkZ){
|
||||||
unset($this->chunkCache[Level::chunkHash($chunkX, $chunkZ)]);
|
unset($this->chunkCache[Level::chunkHash($chunkX, $chunkZ)]);
|
||||||
}
|
}
|
||||||
@ -1045,15 +1112,25 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
return $this->randomTickBlocks;
|
return $this->randomTickBlocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $id
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function addRandomTickedBlock(int $id){
|
public function addRandomTickedBlock(int $id){
|
||||||
$this->randomTickBlocks[$id] = BlockFactory::get($id);
|
$this->randomTickBlocks[$id] = BlockFactory::get($id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $id
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function removeRandomTickedBlock(int $id){
|
public function removeRandomTickedBlock(int $id){
|
||||||
$this->randomTickBlocks[$id] = null;
|
$this->randomTickBlocks[$id] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function tickChunks(){
|
private function tickChunks() : void{
|
||||||
if($this->chunksPerTick <= 0 or count($this->loaders) === 0){
|
if($this->chunksPerTick <= 0 or count($this->loaders) === 0){
|
||||||
$this->chunkTickList = [];
|
$this->chunkTickList = [];
|
||||||
return;
|
return;
|
||||||
@ -1161,6 +1238,9 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function saveChunks(){
|
public function saveChunks(){
|
||||||
$this->timings->syncChunkSaveTimer->startTiming();
|
$this->timings->syncChunkSaveTimer->startTiming();
|
||||||
try{
|
try{
|
||||||
@ -1181,6 +1261,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
*
|
*
|
||||||
* @param Vector3 $pos
|
* @param Vector3 $pos
|
||||||
* @param int $delay
|
* @param int $delay
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function scheduleDelayedBlockUpdate(Vector3 $pos, int $delay){
|
public function scheduleDelayedBlockUpdate(Vector3 $pos, int $delay){
|
||||||
if(
|
if(
|
||||||
@ -1198,6 +1280,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
* Blocks will be updated with the normal update type.
|
* Blocks will be updated with the normal update type.
|
||||||
*
|
*
|
||||||
* @param Vector3 $pos
|
* @param Vector3 $pos
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function scheduleNeighbourBlockUpdates(Vector3 $pos){
|
public function scheduleNeighbourBlockUpdates(Vector3 $pos){
|
||||||
$pos = $pos->floor();
|
$pos = $pos->floor();
|
||||||
@ -1489,6 +1573,11 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
return $block;
|
return $block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Vector3 $pos
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function updateAllLight(Vector3 $pos){
|
public function updateAllLight(Vector3 $pos){
|
||||||
$this->updateBlockSkyLight($pos->x, $pos->y, $pos->z);
|
$this->updateBlockSkyLight($pos->x, $pos->y, $pos->z);
|
||||||
$this->updateBlockLight($pos->x, $pos->y, $pos->z);
|
$this->updateBlockLight($pos->x, $pos->y, $pos->z);
|
||||||
@ -1514,6 +1603,13 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $x
|
||||||
|
* @param int $y
|
||||||
|
* @param int $z
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function updateBlockSkyLight(int $x, int $y, int $z){
|
public function updateBlockSkyLight(int $x, int $y, int $z){
|
||||||
$this->timings->doBlockSkyLightUpdates->startTiming();
|
$this->timings->doBlockSkyLightUpdates->startTiming();
|
||||||
|
|
||||||
@ -1574,6 +1670,13 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $x
|
||||||
|
* @param int $y
|
||||||
|
* @param int $z
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function updateBlockLight(int $x, int $y, int $z){
|
public function updateBlockLight(int $x, int $y, int $z){
|
||||||
$this->timings->doBlockLightUpdates->startTiming();
|
$this->timings->doBlockLightUpdates->startTiming();
|
||||||
|
|
||||||
@ -1776,7 +1879,7 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
* It'll try to lower the durability if Item is a tool, and set it to Air if broken.
|
* It'll try to lower the durability if Item is a tool, and set it to Air if broken.
|
||||||
*
|
*
|
||||||
* @param Vector3 $vector
|
* @param Vector3 $vector
|
||||||
* @param Item &$item (if null, can break anything)
|
* @param Item $item reference parameter (if null, can break anything)
|
||||||
* @param Player $player
|
* @param Player $player
|
||||||
* @param bool $createParticles
|
* @param bool $createParticles
|
||||||
*
|
*
|
||||||
@ -1845,7 +1948,7 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
|
|
||||||
$item->onDestroyBlock($target);
|
$item->onDestroyBlock($target);
|
||||||
|
|
||||||
if(!empty($drops)){
|
if(count($drops) > 0){
|
||||||
$dropPos = $target->add(0.5, 0.5, 0.5);
|
$dropPos = $target->add(0.5, 0.5, 0.5);
|
||||||
foreach($drops as $drop){
|
foreach($drops as $drop){
|
||||||
if(!$drop->isNull()){
|
if(!$drop->isNull()){
|
||||||
@ -1949,7 +2052,7 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
|
|
||||||
if($hand->isSolid()){
|
if($hand->isSolid()){
|
||||||
foreach($hand->getCollisionBoxes() as $collisionBox){
|
foreach($hand->getCollisionBoxes() as $collisionBox){
|
||||||
if(!empty($this->getCollidingEntities($collisionBox))){
|
if(count($this->getCollidingEntities($collisionBox)) > 0){
|
||||||
return false; //Entity in block
|
return false; //Entity in block
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2240,6 +2343,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
* @param int $y
|
* @param int $y
|
||||||
* @param int $z
|
* @param int $z
|
||||||
* @param int $id 0-255
|
* @param int $id 0-255
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setBlockIdAt(int $x, int $y, int $z, int $id){
|
public function setBlockIdAt(int $x, int $y, int $z, int $id){
|
||||||
if(!$this->isInWorld($x, $y, $z)){ //TODO: bad hack but fixing this requires BC breaks to do properly :(
|
if(!$this->isInWorld($x, $y, $z)){ //TODO: bad hack but fixing this requires BC breaks to do properly :(
|
||||||
@ -2279,6 +2384,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
* @param int $y
|
* @param int $y
|
||||||
* @param int $z
|
* @param int $z
|
||||||
* @param int $data 0-15
|
* @param int $data 0-15
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setBlockDataAt(int $x, int $y, int $z, int $data){
|
public function setBlockDataAt(int $x, int $y, int $z, int $data){
|
||||||
if(!$this->isInWorld($x, $y, $z)){ //TODO: bad hack but fixing this requires BC breaks to do properly :(
|
if(!$this->isInWorld($x, $y, $z)){ //TODO: bad hack but fixing this requires BC breaks to do properly :(
|
||||||
@ -2319,6 +2426,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
* @param int $y
|
* @param int $y
|
||||||
* @param int $z
|
* @param int $z
|
||||||
* @param int $level 0-15
|
* @param int $level 0-15
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setBlockSkyLightAt(int $x, int $y, int $z, int $level){
|
public function setBlockSkyLightAt(int $x, int $y, int $z, int $level){
|
||||||
$this->getChunk($x >> 4, $z >> 4, true)->setBlockSkyLight($x & 0x0f, $y, $z & 0x0f, $level & 0x0f);
|
$this->getChunk($x >> 4, $z >> 4, true)->setBlockSkyLight($x & 0x0f, $y, $z & 0x0f, $level & 0x0f);
|
||||||
@ -2344,6 +2453,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
* @param int $y
|
* @param int $y
|
||||||
* @param int $z
|
* @param int $z
|
||||||
* @param int $level 0-15
|
* @param int $level 0-15
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setBlockLightAt(int $x, int $y, int $z, int $level){
|
public function setBlockLightAt(int $x, int $y, int $z, int $level){
|
||||||
$this->getChunk($x >> 4, $z >> 4, true)->setBlockLight($x & 0x0f, $y, $z & 0x0f, $level & 0x0f);
|
$this->getChunk($x >> 4, $z >> 4, true)->setBlockLight($x & 0x0f, $y, $z & 0x0f, $level & 0x0f);
|
||||||
@ -2373,6 +2484,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
* @param int $x
|
* @param int $x
|
||||||
* @param int $z
|
* @param int $z
|
||||||
* @param int $biomeId
|
* @param int $biomeId
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setBiomeId(int $x, int $z, int $biomeId){
|
public function setBiomeId(int $x, int $z, int $biomeId){
|
||||||
$this->getChunk($x >> 4, $z >> 4, true)->setBiomeId($x & 0x0f, $z & 0x0f, $biomeId);
|
$this->getChunk($x >> 4, $z >> 4, true)->setBiomeId($x & 0x0f, $z & 0x0f, $biomeId);
|
||||||
@ -2392,6 +2505,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
* @param int $x
|
* @param int $x
|
||||||
* @param int $z
|
* @param int $z
|
||||||
* @param int $value
|
* @param int $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setHeightMap(int $x, int $z, int $value){
|
public function setHeightMap(int $x, int $z, int $value){
|
||||||
$this->getChunk($x >> 4, $z >> 4, true)->setHeightMap($x & 0x0f, $z & 0x0f, $value);
|
$this->getChunk($x >> 4, $z >> 4, true)->setHeightMap($x & 0x0f, $z & 0x0f, $value);
|
||||||
@ -2442,7 +2557,7 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
* @param int $x
|
* @param int $x
|
||||||
* @param int $z
|
* @param int $z
|
||||||
*
|
*
|
||||||
* @return Chunk[]
|
* @return (Chunk|null)[]
|
||||||
*/
|
*/
|
||||||
public function getAdjacentChunks(int $x, int $z) : array{
|
public function getAdjacentChunks(int $x, int $z) : array{
|
||||||
$result = [];
|
$result = [];
|
||||||
@ -2459,6 +2574,13 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $x
|
||||||
|
* @param int $z
|
||||||
|
* @param Chunk|null $chunk
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function generateChunkCallback(int $x, int $z, ?Chunk $chunk){
|
public function generateChunkCallback(int $x, int $z, ?Chunk $chunk){
|
||||||
Timings::$generationCallbackTimer->startTiming();
|
Timings::$generationCallbackTimer->startTiming();
|
||||||
if(isset($this->chunkPopulationQueue[$index = Level::chunkHash($x, $z)])){
|
if(isset($this->chunkPopulationQueue[$index = Level::chunkHash($x, $z)])){
|
||||||
@ -2496,6 +2618,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
* @param int $chunkZ
|
* @param int $chunkZ
|
||||||
* @param Chunk|null $chunk
|
* @param Chunk|null $chunk
|
||||||
* @param bool $deleteEntitiesAndTiles Whether to delete entities and tiles on the old chunk, or transfer them to the new one
|
* @param bool $deleteEntitiesAndTiles Whether to delete entities and tiles on the old chunk, or transfer them to the new one
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setChunk(int $chunkX, int $chunkZ, Chunk $chunk = null, bool $deleteEntitiesAndTiles = true){
|
public function setChunk(int $chunkX, int $chunkZ, Chunk $chunk = null, bool $deleteEntitiesAndTiles = true){
|
||||||
if($chunk === null){
|
if($chunk === null){
|
||||||
@ -2621,6 +2745,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
* Sets the level spawn location
|
* Sets the level spawn location
|
||||||
*
|
*
|
||||||
* @param Vector3 $pos
|
* @param Vector3 $pos
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setSpawnLocation(Vector3 $pos){
|
public function setSpawnLocation(Vector3 $pos){
|
||||||
$previousSpawn = $this->getSpawnLocation();
|
$previousSpawn = $this->getSpawnLocation();
|
||||||
@ -2628,6 +2754,13 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
(new SpawnChangeEvent($this, $previousSpawn))->call();
|
(new SpawnChangeEvent($this, $previousSpawn))->call();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $x
|
||||||
|
* @param int $z
|
||||||
|
* @param Player $player
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function requestChunk(int $x, int $z, Player $player){
|
public function requestChunk(int $x, int $z, Player $player){
|
||||||
$index = Level::chunkHash($x, $z);
|
$index = Level::chunkHash($x, $z);
|
||||||
if(!isset($this->chunkSendQueue[$index])){
|
if(!isset($this->chunkSendQueue[$index])){
|
||||||
@ -2637,7 +2770,7 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
$this->chunkSendQueue[$index][$player->getLoaderId()] = $player;
|
$this->chunkSendQueue[$index][$player->getLoaderId()] = $player;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function sendChunkFromCache(int $x, int $z){
|
private function sendChunkFromCache(int $x, int $z) : void{
|
||||||
if(isset($this->chunkSendQueue[$index = Level::chunkHash($x, $z)])){
|
if(isset($this->chunkSendQueue[$index = Level::chunkHash($x, $z)])){
|
||||||
foreach($this->chunkSendQueue[$index] as $player){
|
foreach($this->chunkSendQueue[$index] as $player){
|
||||||
/** @var Player $player */
|
/** @var Player $player */
|
||||||
@ -2649,7 +2782,7 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function processChunkRequest(){
|
private function processChunkRequest() : void{
|
||||||
if(count($this->chunkSendQueue) > 0){
|
if(count($this->chunkSendQueue) > 0){
|
||||||
$this->timings->syncChunkSendTimer->startTiming();
|
$this->timings->syncChunkSendTimer->startTiming();
|
||||||
|
|
||||||
@ -2687,6 +2820,13 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $x
|
||||||
|
* @param int $z
|
||||||
|
* @param BatchPacket $payload
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function chunkRequestCallback(int $x, int $z, BatchPacket $payload){
|
public function chunkRequestCallback(int $x, int $z, BatchPacket $payload){
|
||||||
$this->timings->syncChunkSendTimer->startTiming();
|
$this->timings->syncChunkSendTimer->startTiming();
|
||||||
|
|
||||||
@ -2705,6 +2845,7 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
/**
|
/**
|
||||||
* @param Entity $entity
|
* @param Entity $entity
|
||||||
*
|
*
|
||||||
|
* @return void
|
||||||
* @throws LevelException
|
* @throws LevelException
|
||||||
*/
|
*/
|
||||||
public function addEntity(Entity $entity){
|
public function addEntity(Entity $entity){
|
||||||
@ -2726,6 +2867,7 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
*
|
*
|
||||||
* @param Entity $entity
|
* @param Entity $entity
|
||||||
*
|
*
|
||||||
|
* @return void
|
||||||
* @throws LevelException
|
* @throws LevelException
|
||||||
*/
|
*/
|
||||||
public function removeEntity(Entity $entity){
|
public function removeEntity(Entity $entity){
|
||||||
@ -2745,6 +2887,7 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
/**
|
/**
|
||||||
* @param Tile $tile
|
* @param Tile $tile
|
||||||
*
|
*
|
||||||
|
* @return void
|
||||||
* @throws LevelException
|
* @throws LevelException
|
||||||
*/
|
*/
|
||||||
public function addTile(Tile $tile){
|
public function addTile(Tile $tile){
|
||||||
@ -2771,6 +2914,7 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
/**
|
/**
|
||||||
* @param Tile $tile
|
* @param Tile $tile
|
||||||
*
|
*
|
||||||
|
* @return void
|
||||||
* @throws LevelException
|
* @throws LevelException
|
||||||
*/
|
*/
|
||||||
public function removeTile(Tile $tile){
|
public function removeTile(Tile $tile){
|
||||||
@ -2866,11 +3010,18 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function queueUnloadChunk(int $x, int $z){
|
private function queueUnloadChunk(int $x, int $z) : void{
|
||||||
$this->unloadQueue[$index = Level::chunkHash($x, $z)] = microtime(true);
|
$this->unloadQueue[$index = Level::chunkHash($x, $z)] = microtime(true);
|
||||||
unset($this->chunkTickList[$index]);
|
unset($this->chunkTickList[$index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $x
|
||||||
|
* @param int $z
|
||||||
|
* @param bool $safe
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function unloadChunkRequest(int $x, int $z, bool $safe = true){
|
public function unloadChunkRequest(int $x, int $z, bool $safe = true){
|
||||||
if(($safe and $this->isChunkInUse($x, $z)) or $this->isSpawnChunk($x, $z)){
|
if(($safe and $this->isChunkInUse($x, $z)) or $this->isSpawnChunk($x, $z)){
|
||||||
return false;
|
return false;
|
||||||
@ -2881,6 +3032,12 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $x
|
||||||
|
* @param int $z
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function cancelUnloadChunkRequest(int $x, int $z){
|
public function cancelUnloadChunkRequest(int $x, int $z){
|
||||||
unset($this->unloadQueue[Level::chunkHash($x, $z)]);
|
unset($this->unloadQueue[Level::chunkHash($x, $z)]);
|
||||||
}
|
}
|
||||||
@ -3032,6 +3189,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
* Sets the current time on the level
|
* Sets the current time on the level
|
||||||
*
|
*
|
||||||
* @param int $time
|
* @param int $time
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setTime(int $time){
|
public function setTime(int $time){
|
||||||
$this->time = $time;
|
$this->time = $time;
|
||||||
@ -3040,6 +3199,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops the time for the level, will not save the lock state to disk
|
* Stops the time for the level, will not save the lock state to disk
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function stopTime(){
|
public function stopTime(){
|
||||||
$this->stopTime = true;
|
$this->stopTime = true;
|
||||||
@ -3048,6 +3209,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Start the time again, if it was stopped
|
* Start the time again, if it was stopped
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function startTime(){
|
public function startTime(){
|
||||||
$this->stopTime = false;
|
$this->stopTime = false;
|
||||||
@ -3067,6 +3230,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
* Sets the seed for the level
|
* Sets the seed for the level
|
||||||
*
|
*
|
||||||
* @param int $seed
|
* @param int $seed
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setSeed(int $seed){
|
public function setSeed(int $seed){
|
||||||
$this->provider->setSeed($seed);
|
$this->provider->setSeed($seed);
|
||||||
@ -3085,6 +3250,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $difficulty
|
* @param int $difficulty
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setDifficulty(int $difficulty){
|
public function setDifficulty(int $difficulty){
|
||||||
if($difficulty < 0 or $difficulty > 3){
|
if($difficulty < 0 or $difficulty > 3){
|
||||||
@ -3097,6 +3264,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Player ...$targets
|
* @param Player ...$targets
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function sendDifficulty(Player ...$targets){
|
public function sendDifficulty(Player ...$targets){
|
||||||
if(count($targets) === 0){
|
if(count($targets) === 0){
|
||||||
@ -3145,6 +3314,9 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function doChunkGarbageCollection(){
|
public function doChunkGarbageCollection(){
|
||||||
$this->timings->doChunkGC->startTiming();
|
$this->timings->doChunkGC->startTiming();
|
||||||
|
|
||||||
@ -3163,6 +3335,11 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
$this->timings->doChunkGC->stopTiming();
|
$this->timings->doChunkGC->stopTiming();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $force
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function unloadChunks(bool $force = false){
|
public function unloadChunks(bool $force = false){
|
||||||
if(count($this->unloadQueue) > 0){
|
if(count($this->unloadQueue) > 0){
|
||||||
$maxUnload = 96;
|
$maxUnload = 96;
|
||||||
|
@ -33,12 +33,12 @@ class Location extends Position{
|
|||||||
public $pitch;
|
public $pitch;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $x
|
* @param float|int $x
|
||||||
* @param int $y
|
* @param float|int $y
|
||||||
* @param int $z
|
* @param float|int $z
|
||||||
* @param float $yaw
|
* @param float $yaw
|
||||||
* @param float $pitch
|
* @param float $pitch
|
||||||
* @param Level $level
|
* @param Level $level
|
||||||
*/
|
*/
|
||||||
public function __construct($x = 0, $y = 0, $z = 0, $yaw = 0.0, $pitch = 0.0, Level $level = null){
|
public function __construct($x = 0, $y = 0, $z = 0, $yaw = 0.0, $pitch = 0.0, Level $level = null){
|
||||||
$this->yaw = $yaw;
|
$this->yaw = $yaw;
|
||||||
@ -67,10 +67,16 @@ class Location extends Position{
|
|||||||
return new Location($this->x, $this->y, $this->z, $this->yaw, $this->pitch, $this->level);
|
return new Location($this->x, $this->y, $this->z, $this->yaw, $this->pitch, $this->level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
public function getYaw(){
|
public function getYaw(){
|
||||||
return $this->yaw;
|
return $this->yaw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
public function getPitch(){
|
public function getPitch(){
|
||||||
return $this->pitch;
|
return $this->pitch;
|
||||||
}
|
}
|
||||||
|
@ -33,16 +33,22 @@ class Position extends Vector3{
|
|||||||
public $level = null;
|
public $level = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $x
|
* @param float|int $x
|
||||||
* @param int $y
|
* @param float|int $y
|
||||||
* @param int $z
|
* @param float|int $z
|
||||||
* @param Level $level
|
* @param Level $level
|
||||||
*/
|
*/
|
||||||
public function __construct($x = 0, $y = 0, $z = 0, Level $level = null){
|
public function __construct($x = 0, $y = 0, $z = 0, Level $level = null){
|
||||||
parent::__construct($x, $y, $z);
|
parent::__construct($x, $y, $z);
|
||||||
$this->setLevel($level);
|
$this->setLevel($level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Vector3 $pos
|
||||||
|
* @param Level|null $level
|
||||||
|
*
|
||||||
|
* @return Position
|
||||||
|
*/
|
||||||
public static function fromObject(Vector3 $pos, Level $level = null){
|
public static function fromObject(Vector3 $pos, Level $level = null){
|
||||||
return new Position($pos->x, $pos->y, $pos->z, $level);
|
return new Position($pos->x, $pos->y, $pos->z, $level);
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,9 @@ class SimpleChunkManager implements ChunkManager{
|
|||||||
/** @var Chunk[] */
|
/** @var Chunk[] */
|
||||||
protected $chunks = [];
|
protected $chunks = [];
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
protected $seed;
|
protected $seed;
|
||||||
|
/** @var int */
|
||||||
protected $worldHeight;
|
protected $worldHeight;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -69,6 +71,8 @@ class SimpleChunkManager implements ChunkManager{
|
|||||||
* @param int $y
|
* @param int $y
|
||||||
* @param int $z
|
* @param int $z
|
||||||
* @param int $id 0-255
|
* @param int $id 0-255
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setBlockIdAt(int $x, int $y, int $z, int $id){
|
public function setBlockIdAt(int $x, int $y, int $z, int $id){
|
||||||
if($chunk = $this->getChunk($x >> 4, $z >> 4)){
|
if($chunk = $this->getChunk($x >> 4, $z >> 4)){
|
||||||
@ -99,6 +103,8 @@ class SimpleChunkManager implements ChunkManager{
|
|||||||
* @param int $y
|
* @param int $y
|
||||||
* @param int $z
|
* @param int $z
|
||||||
* @param int $data 0-15
|
* @param int $data 0-15
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setBlockDataAt(int $x, int $y, int $z, int $data){
|
public function setBlockDataAt(int $x, int $y, int $z, int $data){
|
||||||
if($chunk = $this->getChunk($x >> 4, $z >> 4)){
|
if($chunk = $this->getChunk($x >> 4, $z >> 4)){
|
||||||
@ -148,6 +154,8 @@ class SimpleChunkManager implements ChunkManager{
|
|||||||
* @param int $chunkX
|
* @param int $chunkX
|
||||||
* @param int $chunkZ
|
* @param int $chunkZ
|
||||||
* @param Chunk|null $chunk
|
* @param Chunk|null $chunk
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setChunk(int $chunkX, int $chunkZ, Chunk $chunk = null){
|
public function setChunk(int $chunkX, int $chunkZ, Chunk $chunk = null){
|
||||||
if($chunk === null){
|
if($chunk === null){
|
||||||
@ -157,6 +165,9 @@ class SimpleChunkManager implements ChunkManager{
|
|||||||
$this->chunks[Level::chunkHash($chunkX, $chunkZ)] = $chunk;
|
$this->chunks[Level::chunkHash($chunkX, $chunkZ)] = $chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function cleanChunks(){
|
public function cleanChunks(){
|
||||||
$this->chunks = [];
|
$this->chunks = [];
|
||||||
}
|
}
|
||||||
|
@ -76,11 +76,20 @@ abstract class Biome{
|
|||||||
/** @var float */
|
/** @var float */
|
||||||
protected $temperature = 0.5;
|
protected $temperature = 0.5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $id
|
||||||
|
* @param Biome $biome
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
protected static function register(int $id, Biome $biome){
|
protected static function register(int $id, Biome $biome){
|
||||||
self::$biomes[$id] = $biome;
|
self::$biomes[$id] = $biome;
|
||||||
$biome->setId($id);
|
$biome->setId($id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public static function init(){
|
public static function init(){
|
||||||
self::$biomes = new \SplFixedArray(self::MAX_BIOMES);
|
self::$biomes = new \SplFixedArray(self::MAX_BIOMES);
|
||||||
|
|
||||||
@ -113,10 +122,18 @@ abstract class Biome{
|
|||||||
return self::$biomes[$id];
|
return self::$biomes[$id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function clearPopulators(){
|
public function clearPopulators(){
|
||||||
$this->populators = [];
|
$this->populators = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Populator $populator
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function addPopulator(Populator $populator){
|
public function addPopulator(Populator $populator){
|
||||||
$this->populators[] = $populator;
|
$this->populators[] = $populator;
|
||||||
}
|
}
|
||||||
@ -126,6 +143,8 @@ abstract class Biome{
|
|||||||
* @param int $chunkX
|
* @param int $chunkX
|
||||||
* @param int $chunkZ
|
* @param int $chunkZ
|
||||||
* @param Random $random
|
* @param Random $random
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function populateChunk(ChunkManager $level, int $chunkX, int $chunkZ, Random $random){
|
public function populateChunk(ChunkManager $level, int $chunkX, int $chunkZ, Random $random){
|
||||||
foreach($this->populators as $populator){
|
foreach($this->populators as $populator){
|
||||||
@ -140,6 +159,11 @@ abstract class Biome{
|
|||||||
return $this->populators;
|
return $this->populators;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $id
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function setId(int $id){
|
public function setId(int $id){
|
||||||
if(!$this->registered){
|
if(!$this->registered){
|
||||||
$this->registered = true;
|
$this->registered = true;
|
||||||
@ -161,6 +185,12 @@ abstract class Biome{
|
|||||||
return $this->maxElevation;
|
return $this->maxElevation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $min
|
||||||
|
* @param int $max
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function setElevation(int $min, int $max){
|
public function setElevation(int $min, int $max){
|
||||||
$this->minElevation = $min;
|
$this->minElevation = $min;
|
||||||
$this->maxElevation = $max;
|
$this->maxElevation = $max;
|
||||||
@ -175,6 +205,8 @@ abstract class Biome{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Block[] $covers
|
* @param Block[] $covers
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setGroundCover(array $covers){
|
public function setGroundCover(array $covers){
|
||||||
$this->groundCover = $covers;
|
$this->groundCover = $covers;
|
||||||
|
@ -32,6 +32,7 @@ class ForestBiome extends GrassyBiome{
|
|||||||
public const TYPE_NORMAL = 0;
|
public const TYPE_NORMAL = 0;
|
||||||
public const TYPE_BIRCH = 1;
|
public const TYPE_BIRCH = 1;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
public $type;
|
public $type;
|
||||||
|
|
||||||
public function __construct(int $type = self::TYPE_NORMAL){
|
public function __construct(int $type = self::TYPE_NORMAL){
|
||||||
|
@ -153,12 +153,19 @@ class Chunk{
|
|||||||
return $this->z;
|
return $this->z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $x
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function setX(int $x){
|
public function setX(int $x){
|
||||||
$this->x = $x;
|
$this->x = $x;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $z
|
* @param int $z
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setZ(int $z){
|
public function setZ(int $z){
|
||||||
$this->z = $z;
|
$this->z = $z;
|
||||||
@ -225,6 +232,8 @@ class Chunk{
|
|||||||
* @param int $y
|
* @param int $y
|
||||||
* @param int $z 0-15
|
* @param int $z 0-15
|
||||||
* @param int $id 0-255
|
* @param int $id 0-255
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setBlockId(int $x, int $y, int $z, int $id){
|
public function setBlockId(int $x, int $y, int $z, int $id){
|
||||||
if($this->getSubChunk($y >> 4, true)->setBlockId($x, $y & 0x0f, $z, $id)){
|
if($this->getSubChunk($y >> 4, true)->setBlockId($x, $y & 0x0f, $z, $id)){
|
||||||
@ -252,6 +261,8 @@ class Chunk{
|
|||||||
* @param int $y
|
* @param int $y
|
||||||
* @param int $z 0-15
|
* @param int $z 0-15
|
||||||
* @param int $data 0-15
|
* @param int $data 0-15
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setBlockData(int $x, int $y, int $z, int $data){
|
public function setBlockData(int $x, int $y, int $z, int $data){
|
||||||
if($this->getSubChunk($y >> 4, true)->setBlockData($x, $y & 0x0f, $z, $data)){
|
if($this->getSubChunk($y >> 4, true)->setBlockData($x, $y & 0x0f, $z, $data)){
|
||||||
@ -279,6 +290,8 @@ class Chunk{
|
|||||||
* @param int $y
|
* @param int $y
|
||||||
* @param int $z 0-15
|
* @param int $z 0-15
|
||||||
* @param int $level 0-15
|
* @param int $level 0-15
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setBlockSkyLight(int $x, int $y, int $z, int $level){
|
public function setBlockSkyLight(int $x, int $y, int $z, int $level){
|
||||||
if($this->getSubChunk($y >> 4, true)->setBlockSkyLight($x, $y & 0x0f, $z, $level)){
|
if($this->getSubChunk($y >> 4, true)->setBlockSkyLight($x, $y & 0x0f, $z, $level)){
|
||||||
@ -288,6 +301,8 @@ class Chunk{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $level
|
* @param int $level
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setAllBlockSkyLight(int $level){
|
public function setAllBlockSkyLight(int $level){
|
||||||
$char = chr(($level & 0x0f) | ($level << 4));
|
$char = chr(($level & 0x0f) | ($level << 4));
|
||||||
@ -317,6 +332,8 @@ class Chunk{
|
|||||||
* @param int $y 0-15
|
* @param int $y 0-15
|
||||||
* @param int $z 0-15
|
* @param int $z 0-15
|
||||||
* @param int $level 0-15
|
* @param int $level 0-15
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setBlockLight(int $x, int $y, int $z, int $level){
|
public function setBlockLight(int $x, int $y, int $z, int $level){
|
||||||
if($this->getSubChunk($y >> 4, true)->setBlockLight($x, $y & 0x0f, $z, $level)){
|
if($this->getSubChunk($y >> 4, true)->setBlockLight($x, $y & 0x0f, $z, $level)){
|
||||||
@ -326,6 +343,8 @@ class Chunk{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $level
|
* @param int $level
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setAllBlockLight(int $level){
|
public function setAllBlockLight(int $level){
|
||||||
$char = chr(($level & 0x0f) | ($level << 4));
|
$char = chr(($level & 0x0f) | ($level << 4));
|
||||||
@ -381,6 +400,8 @@ class Chunk{
|
|||||||
* @param int $x 0-15
|
* @param int $x 0-15
|
||||||
* @param int $z 0-15
|
* @param int $z 0-15
|
||||||
* @param int $value
|
* @param int $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setHeightMap(int $x, int $z, int $value){
|
public function setHeightMap(int $x, int $z, int $value){
|
||||||
$this->heightMap[($z << 4) | $x] = $value;
|
$this->heightMap[($z << 4) | $x] = $value;
|
||||||
@ -388,6 +409,8 @@ class Chunk{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Recalculates the heightmap for the whole chunk.
|
* Recalculates the heightmap for the whole chunk.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function recalculateHeightMap(){
|
public function recalculateHeightMap(){
|
||||||
for($z = 0; $z < 16; ++$z){
|
for($z = 0; $z < 16; ++$z){
|
||||||
@ -423,6 +446,8 @@ class Chunk{
|
|||||||
* if the chunk is light-populated after being terrain-populated.
|
* if the chunk is light-populated after being terrain-populated.
|
||||||
*
|
*
|
||||||
* TODO: fast adjacent light spread
|
* TODO: fast adjacent light spread
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function populateSkyLight(){
|
public function populateSkyLight(){
|
||||||
$maxY = $this->getMaxY();
|
$maxY = $this->getMaxY();
|
||||||
@ -469,6 +494,8 @@ class Chunk{
|
|||||||
* @param int $x 0-15
|
* @param int $x 0-15
|
||||||
* @param int $z 0-15
|
* @param int $z 0-15
|
||||||
* @param int $biomeId 0-255
|
* @param int $biomeId 0-255
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setBiomeId(int $x, int $z, int $biomeId){
|
public function setBiomeId(int $x, int $z, int $biomeId){
|
||||||
$this->hasChanged = true;
|
$this->hasChanged = true;
|
||||||
@ -549,6 +576,8 @@ class Chunk{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bool $value
|
* @param bool $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setLightPopulated(bool $value = true){
|
public function setLightPopulated(bool $value = true){
|
||||||
$this->lightPopulated = $value;
|
$this->lightPopulated = $value;
|
||||||
@ -563,6 +592,8 @@ class Chunk{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bool $value
|
* @param bool $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setPopulated(bool $value = true){
|
public function setPopulated(bool $value = true){
|
||||||
$this->terrainPopulated = $value;
|
$this->terrainPopulated = $value;
|
||||||
@ -577,6 +608,8 @@ class Chunk{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bool $value
|
* @param bool $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setGenerated(bool $value = true){
|
public function setGenerated(bool $value = true){
|
||||||
$this->terrainGenerated = $value;
|
$this->terrainGenerated = $value;
|
||||||
@ -584,6 +617,8 @@ class Chunk{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Entity $entity
|
* @param Entity $entity
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function addEntity(Entity $entity){
|
public function addEntity(Entity $entity){
|
||||||
if($entity->isClosed()){
|
if($entity->isClosed()){
|
||||||
@ -597,6 +632,8 @@ class Chunk{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Entity $entity
|
* @param Entity $entity
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function removeEntity(Entity $entity){
|
public function removeEntity(Entity $entity){
|
||||||
unset($this->entities[$entity->getId()]);
|
unset($this->entities[$entity->getId()]);
|
||||||
@ -607,6 +644,8 @@ class Chunk{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Tile $tile
|
* @param Tile $tile
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function addTile(Tile $tile){
|
public function addTile(Tile $tile){
|
||||||
if($tile->isClosed()){
|
if($tile->isClosed()){
|
||||||
@ -624,6 +663,8 @@ class Chunk{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Tile $tile
|
* @param Tile $tile
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function removeTile(Tile $tile){
|
public function removeTile(Tile $tile){
|
||||||
unset($this->tiles[$tile->getId()]);
|
unset($this->tiles[$tile->getId()]);
|
||||||
@ -690,6 +731,8 @@ class Chunk{
|
|||||||
* Deserializes tiles and entities from NBT
|
* Deserializes tiles and entities from NBT
|
||||||
*
|
*
|
||||||
* @param Level $level
|
* @param Level $level
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function initChunk(Level $level){
|
public function initChunk(Level $level){
|
||||||
if(!$this->isInit){
|
if(!$this->isInit){
|
||||||
@ -766,6 +809,8 @@ class Chunk{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bool $value
|
* @param bool $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setChanged(bool $value = true){
|
public function setChanged(bool $value = true){
|
||||||
$this->hasChanged = $value;
|
$this->hasChanged = $value;
|
||||||
|
@ -38,25 +38,28 @@ if(!defined(__NAMESPACE__ . '\ZERO_NIBBLE_ARRAY')){
|
|||||||
}
|
}
|
||||||
|
|
||||||
class SubChunk implements SubChunkInterface{
|
class SubChunk implements SubChunkInterface{
|
||||||
|
/** @var string */
|
||||||
protected $ids;
|
protected $ids;
|
||||||
|
/** @var string */
|
||||||
protected $data;
|
protected $data;
|
||||||
|
/** @var string */
|
||||||
protected $blockLight;
|
protected $blockLight;
|
||||||
|
/** @var string */
|
||||||
protected $skyLight;
|
protected $skyLight;
|
||||||
|
|
||||||
private static function assignData(&$target, string $data, int $length, string $value = "\x00"){
|
private static function assignData(string $data, int $length, string $value = "\x00") : string{
|
||||||
if(strlen($data) !== $length){
|
if(strlen($data) !== $length){
|
||||||
assert($data === "", "Invalid non-zero length given, expected $length, got " . strlen($data));
|
assert($data === "", "Invalid non-zero length given, expected $length, got " . strlen($data));
|
||||||
$target = str_repeat($value, $length);
|
return str_repeat($value, $length);
|
||||||
}else{
|
|
||||||
$target = $data;
|
|
||||||
}
|
}
|
||||||
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __construct(string $ids = "", string $data = "", string $skyLight = "", string $blockLight = ""){
|
public function __construct(string $ids = "", string $data = "", string $skyLight = "", string $blockLight = ""){
|
||||||
self::assignData($this->ids, $ids, 4096);
|
$this->ids = self::assignData($ids, 4096);
|
||||||
self::assignData($this->data, $data, 2048);
|
$this->data = self::assignData($data, 2048);
|
||||||
self::assignData($this->skyLight, $skyLight, 2048, "\xff");
|
$this->skyLight = self::assignData($skyLight, 2048, "\xff");
|
||||||
self::assignData($this->blockLight, $blockLight, 2048);
|
$this->blockLight = self::assignData($blockLight, 2048);
|
||||||
$this->collectGarbage();
|
$this->collectGarbage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,6 +217,9 @@ class SubChunk implements SubChunkInterface{
|
|||||||
return "\x00" . $this->ids . $this->data;
|
return "\x00" . $this->ids . $this->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed[]
|
||||||
|
*/
|
||||||
public function __debugInfo(){
|
public function __debugInfo(){
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
@ -185,6 +185,8 @@ interface SubChunkInterface{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $data
|
* @param string $data
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setBlockSkyLightArray(string $data);
|
public function setBlockSkyLightArray(string $data);
|
||||||
|
|
||||||
@ -195,6 +197,8 @@ interface SubChunkInterface{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $data
|
* @param string $data
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setBlockLightArray(string $data);
|
public function setBlockLightArray(string $data);
|
||||||
|
|
||||||
|
@ -150,6 +150,9 @@ abstract class BaseLevelProvider implements LevelProvider{
|
|||||||
return $this->levelData;
|
return $this->levelData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function saveLevelData(){
|
public function saveLevelData(){
|
||||||
$nbt = new BigEndianNBTStream();
|
$nbt = new BigEndianNBTStream();
|
||||||
$buffer = $nbt->writeCompressed(new CompoundTag("", [
|
$buffer = $nbt->writeCompressed(new CompoundTag("", [
|
||||||
|
@ -34,12 +34,17 @@ use function strlen;
|
|||||||
|
|
||||||
class ChunkRequestTask extends AsyncTask{
|
class ChunkRequestTask extends AsyncTask{
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
protected $levelId;
|
protected $levelId;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
protected $chunk;
|
protected $chunk;
|
||||||
|
/** @var int */
|
||||||
protected $chunkX;
|
protected $chunkX;
|
||||||
|
/** @var int */
|
||||||
protected $chunkZ;
|
protected $chunkZ;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
protected $compressionLevel;
|
protected $compressionLevel;
|
||||||
|
|
||||||
/** @var int */
|
/** @var int */
|
||||||
|
@ -71,7 +71,9 @@ interface LevelProvider{
|
|||||||
* @param string $name
|
* @param string $name
|
||||||
* @param int $seed
|
* @param int $seed
|
||||||
* @param string $generator
|
* @param string $generator
|
||||||
* @param array[] $options
|
* @param array $options
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function generate(string $path, string $name, int $seed, string $generator, array $options = []);
|
public static function generate(string $path, string $name, int $seed, string $generator, array $options = []);
|
||||||
|
|
||||||
@ -119,6 +121,8 @@ interface LevelProvider{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $value
|
* @param int $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setTime(int $value);
|
public function setTime(int $value);
|
||||||
|
|
||||||
@ -129,6 +133,8 @@ interface LevelProvider{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $value
|
* @param int $value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setSeed(int $value);
|
public function setSeed(int $value);
|
||||||
|
|
||||||
@ -139,6 +145,8 @@ interface LevelProvider{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Vector3 $pos
|
* @param Vector3 $pos
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setSpawn(Vector3 $pos);
|
public function setSpawn(Vector3 $pos);
|
||||||
|
|
||||||
@ -152,16 +160,22 @@ interface LevelProvider{
|
|||||||
* Sets the world difficulty.
|
* Sets the world difficulty.
|
||||||
*
|
*
|
||||||
* @param int $difficulty
|
* @param int $difficulty
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function setDifficulty(int $difficulty);
|
public function setDifficulty(int $difficulty);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs garbage collection in the level provider, such as cleaning up regions in Region-based worlds.
|
* Performs garbage collection in the level provider, such as cleaning up regions in Region-based worlds.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function doGarbageCollection();
|
public function doGarbageCollection();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs cleanups necessary when the level provider is closed and no longer needed.
|
* Performs cleanups necessary when the level provider is closed and no longer needed.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function close();
|
public function close();
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ use function strtolower;
|
|||||||
use function trim;
|
use function trim;
|
||||||
|
|
||||||
abstract class LevelProviderManager{
|
abstract class LevelProviderManager{
|
||||||
|
/** @var string[] */
|
||||||
protected static $providers = [];
|
protected static $providers = [];
|
||||||
|
|
||||||
public static function init() : void{
|
public static function init() : void{
|
||||||
@ -43,6 +44,7 @@ abstract class LevelProviderManager{
|
|||||||
/**
|
/**
|
||||||
* @param string $class
|
* @param string $class
|
||||||
*
|
*
|
||||||
|
* @return void
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public static function addProvider(string $class){
|
public static function addProvider(string $class){
|
||||||
|
@ -26,6 +26,7 @@ namespace pocketmine\level\format\io\leveldb;
|
|||||||
use pocketmine\level\format\Chunk;
|
use pocketmine\level\format\Chunk;
|
||||||
use pocketmine\level\format\io\BaseLevelProvider;
|
use pocketmine\level\format\io\BaseLevelProvider;
|
||||||
use pocketmine\level\format\io\ChunkUtils;
|
use pocketmine\level\format\io\ChunkUtils;
|
||||||
|
use pocketmine\level\format\io\exception\CorruptedChunkException;
|
||||||
use pocketmine\level\format\io\exception\UnsupportedChunkFormatException;
|
use pocketmine\level\format\io\exception\UnsupportedChunkFormatException;
|
||||||
use pocketmine\level\format\SubChunk;
|
use pocketmine\level\format\SubChunk;
|
||||||
use pocketmine\level\generator\Flat;
|
use pocketmine\level\generator\Flat;
|
||||||
@ -44,6 +45,7 @@ use pocketmine\utils\Binary;
|
|||||||
use pocketmine\utils\BinaryStream;
|
use pocketmine\utils\BinaryStream;
|
||||||
use function array_values;
|
use function array_values;
|
||||||
use function chr;
|
use function chr;
|
||||||
|
use function count;
|
||||||
use function defined;
|
use function defined;
|
||||||
use function explode;
|
use function explode;
|
||||||
use function extension_loaded;
|
use function extension_loaded;
|
||||||
@ -100,7 +102,7 @@ class LevelDB extends BaseLevelProvider{
|
|||||||
/** @var \LevelDB */
|
/** @var \LevelDB */
|
||||||
protected $db;
|
protected $db;
|
||||||
|
|
||||||
private static function checkForLevelDBExtension(){
|
private static function checkForLevelDBExtension() : void{
|
||||||
if(!extension_loaded('leveldb')){
|
if(!extension_loaded('leveldb')){
|
||||||
throw new LevelException("The leveldb PHP extension is required to use this world format");
|
throw new LevelException("The leveldb PHP extension is required to use this world format");
|
||||||
}
|
}
|
||||||
@ -124,8 +126,12 @@ class LevelDB extends BaseLevelProvider{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected function loadLevelData() : void{
|
protected function loadLevelData() : void{
|
||||||
|
$rawLevelData = file_get_contents($this->getPath() . "level.dat");
|
||||||
|
if($rawLevelData === false or strlen($rawLevelData) <= 8){
|
||||||
|
throw new LevelException("Truncated level.dat");
|
||||||
|
}
|
||||||
$nbt = new LittleEndianNBTStream();
|
$nbt = new LittleEndianNBTStream();
|
||||||
$levelData = $nbt->read(substr(file_get_contents($this->getPath() . "level.dat"), 8));
|
$levelData = $nbt->read(substr($rawLevelData, 8));
|
||||||
if($levelData instanceof CompoundTag){
|
if($levelData instanceof CompoundTag){
|
||||||
$this->levelData = $levelData;
|
$this->levelData = $levelData;
|
||||||
}else{
|
}else{
|
||||||
@ -414,24 +420,27 @@ class LevelDB extends BaseLevelProvider{
|
|||||||
/** @var CompoundTag[] $entities */
|
/** @var CompoundTag[] $entities */
|
||||||
$entities = [];
|
$entities = [];
|
||||||
if(($entityData = $this->db->get($index . self::TAG_ENTITY)) !== false and $entityData !== ""){
|
if(($entityData = $this->db->get($index . self::TAG_ENTITY)) !== false and $entityData !== ""){
|
||||||
$entities = $nbt->read($entityData, true);
|
$entityTags = $nbt->read($entityData, true);
|
||||||
if(!is_array($entities)){
|
foreach((is_array($entityTags) ? $entityTags : [$entityTags]) as $entityTag){
|
||||||
$entities = [$entities];
|
if(!($entityTag instanceof CompoundTag)){
|
||||||
}
|
throw new CorruptedChunkException("Entity root tag should be TAG_Compound");
|
||||||
}
|
}
|
||||||
|
if($entityTag->hasTag("id", IntTag::class)){
|
||||||
/** @var CompoundTag $entityNBT */
|
$entityTag->setInt("id", $entityTag->getInt("id") & 0xff); //remove type flags - TODO: use these instead of removing them)
|
||||||
foreach($entities as $entityNBT){
|
}
|
||||||
if($entityNBT->hasTag("id", IntTag::class)){
|
$entities[] = $entityTag;
|
||||||
$entityNBT->setInt("id", $entityNBT->getInt("id") & 0xff); //remove type flags - TODO: use these instead of removing them)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @var CompoundTag[] $tiles */
|
||||||
$tiles = [];
|
$tiles = [];
|
||||||
if(($tileData = $this->db->get($index . self::TAG_BLOCK_ENTITY)) !== false and $tileData !== ""){
|
if(($tileData = $this->db->get($index . self::TAG_BLOCK_ENTITY)) !== false and $tileData !== ""){
|
||||||
$tiles = $nbt->read($tileData, true);
|
$tileTags = $nbt->read($tileData, true);
|
||||||
if(!is_array($tiles)){
|
foreach((is_array($tileTags) ? $tileTags : [$tileTags]) as $tileTag){
|
||||||
$tiles = [$tiles];
|
if(!($tileTag instanceof CompoundTag)){
|
||||||
|
throw new CorruptedChunkException("Tile root tag should be TAG_Compound");
|
||||||
|
}
|
||||||
|
$tiles[] = $tileTag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -514,8 +523,8 @@ class LevelDB extends BaseLevelProvider{
|
|||||||
* @param CompoundTag[] $targets
|
* @param CompoundTag[] $targets
|
||||||
* @param string $index
|
* @param string $index
|
||||||
*/
|
*/
|
||||||
private function writeTags(array $targets, string $index){
|
private function writeTags(array $targets, string $index) : void{
|
||||||
if(!empty($targets)){
|
if(count($targets) > 0){
|
||||||
$nbt = new LittleEndianNBTStream();
|
$nbt = new LittleEndianNBTStream();
|
||||||
$this->db->put($index, $nbt->write($targets));
|
$this->db->put($index, $nbt->write($targets));
|
||||||
}else{
|
}else{
|
||||||
|
@ -51,7 +51,7 @@ class Anvil extends McRegion{
|
|||||||
|
|
||||||
$subChunks = [];
|
$subChunks = [];
|
||||||
foreach($chunk->getSubChunks() as $y => $subChunk){
|
foreach($chunk->getSubChunks() as $y => $subChunk){
|
||||||
if($subChunk->isEmpty()){
|
if(!($subChunk instanceof SubChunk) or $subChunk->isEmpty()){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,8 +122,8 @@ class Anvil extends McRegion{
|
|||||||
$chunk->getInt("xPos"),
|
$chunk->getInt("xPos"),
|
||||||
$chunk->getInt("zPos"),
|
$chunk->getInt("zPos"),
|
||||||
$subChunks,
|
$subChunks,
|
||||||
$chunk->hasTag("Entities", ListTag::class) ? $chunk->getListTag("Entities")->getValue() : [],
|
$chunk->hasTag("Entities", ListTag::class) ? self::getCompoundList("Entities", $chunk->getListTag("Entities")) : [],
|
||||||
$chunk->hasTag("TileEntities", ListTag::class) ? $chunk->getListTag("TileEntities")->getValue() : [],
|
$chunk->hasTag("TileEntities", ListTag::class) ? self::getCompoundList("TileEntities", $chunk->getListTag("TileEntities")) : [],
|
||||||
$biomeIds,
|
$biomeIds,
|
||||||
$chunk->getIntArray("HeightMap", [])
|
$chunk->getIntArray("HeightMap", [])
|
||||||
);
|
);
|
||||||
|
@ -194,8 +194,8 @@ class McRegion extends BaseLevelProvider{
|
|||||||
$chunk->getInt("xPos"),
|
$chunk->getInt("xPos"),
|
||||||
$chunk->getInt("zPos"),
|
$chunk->getInt("zPos"),
|
||||||
$subChunks,
|
$subChunks,
|
||||||
$chunk->hasTag("Entities", ListTag::class) ? $chunk->getListTag("Entities")->getValue() : [],
|
$chunk->hasTag("Entities", ListTag::class) ? self::getCompoundList("Entities", $chunk->getListTag("Entities")) : [],
|
||||||
$chunk->hasTag("TileEntities", ListTag::class) ? $chunk->getListTag("TileEntities")->getValue() : [],
|
$chunk->hasTag("TileEntities", ListTag::class) ? self::getCompoundList("TileEntities", $chunk->getListTag("TileEntities")) : [],
|
||||||
$biomeIds,
|
$biomeIds,
|
||||||
$heightMap
|
$heightMap
|
||||||
);
|
);
|
||||||
@ -205,6 +205,31 @@ class McRegion extends BaseLevelProvider{
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $context
|
||||||
|
* @param ListTag $list
|
||||||
|
*
|
||||||
|
* @return CompoundTag[]
|
||||||
|
* @throws CorruptedChunkException
|
||||||
|
*/
|
||||||
|
protected static function getCompoundList(string $context, ListTag $list) : array{
|
||||||
|
if($list->count() === 0){ //empty lists might have wrong types, we don't care
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
if($list->getTagType() !== NBT::TAG_Compound){
|
||||||
|
throw new CorruptedChunkException("Expected TAG_List<TAG_Compound> for '$context'");
|
||||||
|
}
|
||||||
|
$result = [];
|
||||||
|
foreach($list as $tag){
|
||||||
|
if(!($tag instanceof CompoundTag)){
|
||||||
|
//this should never happen, but it's still possible due to lack of native type safety
|
||||||
|
throw new CorruptedChunkException("Expected TAG_List<TAG_Compound> for '$context'");
|
||||||
|
}
|
||||||
|
$result[] = $tag;
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
public static function getProviderName() : string{
|
public static function getProviderName() : string{
|
||||||
return "mcregion";
|
return "mcregion";
|
||||||
}
|
}
|
||||||
@ -306,8 +331,10 @@ class McRegion extends BaseLevelProvider{
|
|||||||
/**
|
/**
|
||||||
* @param int $chunkX
|
* @param int $chunkX
|
||||||
* @param int $chunkZ
|
* @param int $chunkZ
|
||||||
* @param int &$regionX
|
* @param int $regionX reference parameter
|
||||||
* @param int &$regionZ
|
* @param int $regionZ reference parameter
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function getRegionIndex(int $chunkX, int $chunkZ, &$regionX, &$regionZ){
|
public static function getRegionIndex(int $chunkX, int $chunkZ, &$regionX, &$regionZ){
|
||||||
$regionX = $chunkX >> 5;
|
$regionX = $chunkX >> 5;
|
||||||
@ -339,6 +366,8 @@ class McRegion extends BaseLevelProvider{
|
|||||||
/**
|
/**
|
||||||
* @param int $regionX
|
* @param int $regionX
|
||||||
* @param int $regionZ
|
* @param int $regionZ
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function loadRegion(int $regionX, int $regionZ){
|
protected function loadRegion(int $regionX, int $regionZ){
|
||||||
if(!isset($this->regions[$index = Level::chunkHash($regionX, $regionZ)])){
|
if(!isset($this->regions[$index = Level::chunkHash($regionX, $regionZ)])){
|
||||||
|
@ -62,6 +62,7 @@ class RegionLoader{
|
|||||||
|
|
||||||
private const FIRST_SECTOR = 2; //location table occupies 0 and 1
|
private const FIRST_SECTOR = 2; //location table occupies 0 and 1
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
public static $COMPRESSION_LEVEL = 7;
|
public static $COMPRESSION_LEVEL = 7;
|
||||||
|
|
||||||
/** @var int */
|
/** @var int */
|
||||||
@ -86,6 +87,7 @@ class RegionLoader{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @return void
|
||||||
* @throws CorruptedRegionException
|
* @throws CorruptedRegionException
|
||||||
*/
|
*/
|
||||||
public function open(){
|
public function open(){
|
||||||
@ -187,6 +189,7 @@ class RegionLoader{
|
|||||||
* @param int $z
|
* @param int $z
|
||||||
* @param string $chunkData
|
* @param string $chunkData
|
||||||
*
|
*
|
||||||
|
* @return void
|
||||||
* @throws ChunkException
|
* @throws ChunkException
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
@ -219,6 +222,7 @@ class RegionLoader{
|
|||||||
* @param int $x
|
* @param int $x
|
||||||
* @param int $z
|
* @param int $z
|
||||||
*
|
*
|
||||||
|
* @return void
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function removeChunk(int $x, int $z){
|
public function removeChunk(int $x, int $z){
|
||||||
@ -243,8 +247,8 @@ class RegionLoader{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $offset
|
* @param int $offset
|
||||||
* @param int &$x
|
* @param int $x reference parameter
|
||||||
* @param int &$z
|
* @param int $z reference parameter
|
||||||
*/
|
*/
|
||||||
protected static function getChunkCoords(int $offset, ?int &$x, ?int &$z) : void{
|
protected static function getChunkCoords(int $offset, ?int &$x, ?int &$z) : void{
|
||||||
$x = $offset & 0x1f;
|
$x = $offset & 0x1f;
|
||||||
@ -255,6 +259,8 @@ class RegionLoader{
|
|||||||
* Writes the region header and closes the file
|
* Writes the region header and closes the file
|
||||||
*
|
*
|
||||||
* @param bool $writeHeader
|
* @param bool $writeHeader
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function close(bool $writeHeader = true){
|
public function close(bool $writeHeader = true){
|
||||||
if(is_resource($this->filePointer)){
|
if(is_resource($this->filePointer)){
|
||||||
@ -267,6 +273,7 @@ class RegionLoader{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @return void
|
||||||
* @throws CorruptedRegionException
|
* @throws CorruptedRegionException
|
||||||
*/
|
*/
|
||||||
protected function loadLocationTable(){
|
protected function loadLocationTable(){
|
||||||
@ -328,7 +335,7 @@ class RegionLoader{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function writeLocationTable(){
|
private function writeLocationTable() : void{
|
||||||
$write = [];
|
$write = [];
|
||||||
|
|
||||||
for($i = 0; $i < 1024; ++$i){
|
for($i = 0; $i < 1024; ++$i){
|
||||||
@ -341,6 +348,11 @@ class RegionLoader{
|
|||||||
fwrite($this->filePointer, pack("N*", ...$write), 4096 * 2);
|
fwrite($this->filePointer, pack("N*", ...$write), 4096 * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $index
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
protected function writeLocationIndex($index){
|
protected function writeLocationIndex($index){
|
||||||
fseek($this->filePointer, $index << 2);
|
fseek($this->filePointer, $index << 2);
|
||||||
fwrite($this->filePointer, Binary::writeInt(($this->locationTable[$index]->getFirstSector() << 8) | $this->locationTable[$index]->getSectorCount()), 4);
|
fwrite($this->filePointer, Binary::writeInt(($this->locationTable[$index]->getFirstSector() << 8) | $this->locationTable[$index]->getSectorCount()), 4);
|
||||||
@ -348,6 +360,9 @@ class RegionLoader{
|
|||||||
fwrite($this->filePointer, Binary::writeInt($this->locationTable[$index]->getTimestamp()), 4);
|
fwrite($this->filePointer, Binary::writeInt($this->locationTable[$index]->getTimestamp()), 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
protected function createBlank(){
|
protected function createBlank(){
|
||||||
fseek($this->filePointer, 0);
|
fseek($this->filePointer, 0);
|
||||||
ftruncate($this->filePointer, 8192); // this fills the file with the null byte
|
ftruncate($this->filePointer, 8192); // this fills the file with the null byte
|
||||||
|
@ -34,10 +34,15 @@ use function unserialize;
|
|||||||
|
|
||||||
class GeneratorRegisterTask extends AsyncTask{
|
class GeneratorRegisterTask extends AsyncTask{
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
public $generatorClass;
|
public $generatorClass;
|
||||||
|
/** @var string */
|
||||||
public $settings;
|
public $settings;
|
||||||
|
/** @var int */
|
||||||
public $seed;
|
public $seed;
|
||||||
|
/** @var int */
|
||||||
public $levelId;
|
public $levelId;
|
||||||
|
/** @var int */
|
||||||
public $worldHeight = Level::Y_MAX;
|
public $worldHeight = Level::Y_MAX;
|
||||||
|
|
||||||
public function __construct(Level $level, string $generatorClass, array $generatorSettings = []){
|
public function __construct(Level $level, string $generatorClass, array $generatorSettings = []){
|
||||||
|
@ -28,6 +28,7 @@ use pocketmine\scheduler\AsyncTask;
|
|||||||
|
|
||||||
class GeneratorUnregisterTask extends AsyncTask{
|
class GeneratorUnregisterTask extends AsyncTask{
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
public $levelId;
|
public $levelId;
|
||||||
|
|
||||||
public function __construct(Level $level){
|
public function __construct(Level $level){
|
||||||
|
@ -31,18 +31,31 @@ use pocketmine\Server;
|
|||||||
|
|
||||||
class PopulationTask extends AsyncTask{
|
class PopulationTask extends AsyncTask{
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
public $state;
|
public $state;
|
||||||
|
/** @var int */
|
||||||
public $levelId;
|
public $levelId;
|
||||||
|
/** @var string */
|
||||||
public $chunk;
|
public $chunk;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
public $chunk0;
|
public $chunk0;
|
||||||
|
/** @var string */
|
||||||
public $chunk1;
|
public $chunk1;
|
||||||
|
/** @var string */
|
||||||
public $chunk2;
|
public $chunk2;
|
||||||
|
/** @var string */
|
||||||
public $chunk3;
|
public $chunk3;
|
||||||
|
|
||||||
//center chunk
|
//center chunk
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
public $chunk5;
|
public $chunk5;
|
||||||
|
/** @var string */
|
||||||
public $chunk6;
|
public $chunk6;
|
||||||
|
/** @var string */
|
||||||
public $chunk7;
|
public $chunk7;
|
||||||
|
/** @var string */
|
||||||
public $chunk8;
|
public $chunk8;
|
||||||
|
|
||||||
public function __construct(Level $level, Chunk $chunk){
|
public function __construct(Level $level, Chunk $chunk){
|
||||||
@ -56,11 +69,9 @@ class PopulationTask extends AsyncTask{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onRun(){
|
public function onRun(){
|
||||||
/** @var SimpleChunkManager $manager */
|
|
||||||
$manager = $this->getFromThreadStore("generation.level{$this->levelId}.manager");
|
$manager = $this->getFromThreadStore("generation.level{$this->levelId}.manager");
|
||||||
/** @var Generator $generator */
|
|
||||||
$generator = $this->getFromThreadStore("generation.level{$this->levelId}.generator");
|
$generator = $this->getFromThreadStore("generation.level{$this->levelId}.generator");
|
||||||
if($manager === null or $generator === null){
|
if(!($manager instanceof SimpleChunkManager) or !($generator instanceof Generator)){
|
||||||
$this->state = false;
|
$this->state = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,9 @@ abstract class BiomeSelector{
|
|||||||
*/
|
*/
|
||||||
abstract protected function lookup(float $temperature, float $rainfall) : int;
|
abstract protected function lookup(float $temperature, float $rainfall) : int;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function recalculate(){
|
public function recalculate(){
|
||||||
$this->map = new \SplFixedArray(64 * 64);
|
$this->map = new \SplFixedArray(64 * 64);
|
||||||
|
|
||||||
@ -66,18 +69,29 @@ abstract class BiomeSelector{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param float $x
|
||||||
|
* @param float $z
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
public function getTemperature($x, $z){
|
public function getTemperature($x, $z){
|
||||||
return ($this->temperature->noise2D($x, $z, true) + 1) / 2;
|
return ($this->temperature->noise2D($x, $z, true) + 1) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param float $x
|
||||||
|
* @param float $z
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
public function getRainfall($x, $z){
|
public function getRainfall($x, $z){
|
||||||
return ($this->rainfall->noise2D($x, $z, true) + 1) / 2;
|
return ($this->rainfall->noise2D($x, $z, true) + 1) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: not sure on types here
|
* @param int $x
|
||||||
* @param int|float $x
|
* @param int $z
|
||||||
* @param int|float $z
|
|
||||||
*
|
*
|
||||||
* @return Biome
|
* @return Biome
|
||||||
*/
|
*/
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user