mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-11 20:10:17 +00:00
Compare commits
88 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 |
@ -42,4 +42,14 @@ Plugin developers should **only** update their required API to this version if y
|
||||
- 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.
|
||||
- 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-zlib": ">=1.2.11",
|
||||
"pocketmine/raklib": "^0.12.5",
|
||||
"pocketmine/spl": "^0.3.0",
|
||||
"pocketmine/spl": "^0.3.5",
|
||||
"pocketmine/binaryutils": "^0.1.9",
|
||||
"pocketmine/nbt": "^0.2.10",
|
||||
"pocketmine/math": "^0.2.0",
|
||||
@ -38,6 +38,7 @@
|
||||
"": ["src"]
|
||||
},
|
||||
"files": [
|
||||
"src/pocketmine/CoreConstants.php",
|
||||
"src/pocketmine/GlobalConstants.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",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "377d9e0ab5f1a9a4ef9b664706d26f5b",
|
||||
"content-hash": "f693f278b3bb9c1d266079fa17644dcb",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/json-comment",
|
||||
@ -276,16 +276,16 @@
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/spl",
|
||||
"version": "0.3.3",
|
||||
"version": "0.3.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/SPL.git",
|
||||
"reference": "94d4df142fe837ba836e9348dd00209e4bdcc307"
|
||||
"reference": "88052c67d3df2cc2dc2d99ebeae3d7ede3fc64ab"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/SPL/zipball/94d4df142fe837ba836e9348dd00209e4bdcc307",
|
||||
"reference": "94d4df142fe837ba836e9348dd00209e4bdcc307",
|
||||
"url": "https://api.github.com/repos/pmmp/SPL/zipball/88052c67d3df2cc2dc2d99ebeae3d7ede3fc64ab",
|
||||
"reference": "88052c67d3df2cc2dc2d99ebeae3d7ede3fc64ab",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
@ -299,10 +299,10 @@
|
||||
],
|
||||
"description": "Standard library files required by PocketMine-MP and related projects",
|
||||
"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"
|
||||
},
|
||||
"time": "2019-10-28T11:41:20+00:00"
|
||||
"time": "2020-01-14T16:23:26+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
|
@ -1,13 +1,13 @@
|
||||
includes:
|
||||
- tests/phpstan/configs/com-dotnet-magic.neon
|
||||
- tests/phpstan/configs/custom-leveldb.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/pthreads-bugs.neon
|
||||
- tests/phpstan/configs/runtime-type-checks.neon
|
||||
|
||||
parameters:
|
||||
level: 5
|
||||
level: 6
|
||||
autoload_files:
|
||||
- tests/phpstan/bootstrap.php
|
||||
- src/pocketmine/PocketMine.php
|
||||
@ -19,6 +19,7 @@ parameters:
|
||||
- pocketmine\IS_DEVELOPMENT_BUILD
|
||||
- pocketmine\DEBUG
|
||||
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:
|
||||
-
|
||||
message: "#^Cannot instantiate interface pocketmine\\\\level\\\\format\\\\io\\\\LevelProvider\\.$#"
|
||||
@ -86,11 +87,6 @@ parameters:
|
||||
count: 1
|
||||
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\\.$#"
|
||||
count: 1
|
||||
@ -108,18 +104,10 @@ parameters:
|
||||
message: "#^Constant pocketmine\\\\GIT_COMMIT not found\\.$#"
|
||||
path: src
|
||||
|
||||
-
|
||||
message: "#^Constant pocketmine\\\\PATH not found\\.$#"
|
||||
path: src
|
||||
|
||||
-
|
||||
message: "#^Constant pocketmine\\\\PLUGIN_PATH not found\\.$#"
|
||||
path: src
|
||||
|
||||
-
|
||||
message: "#^Constant pocketmine\\\\RESOURCE_PATH not found\\.$#"
|
||||
path: src
|
||||
|
||||
-
|
||||
message: "#^Constant pocketmine\\\\START_TIME not found\\.$#"
|
||||
path: src
|
||||
|
@ -25,12 +25,16 @@ namespace pocketmine;
|
||||
|
||||
abstract class Collectable extends \Threaded{
|
||||
|
||||
/** @var bool */
|
||||
private $isGarbage = false;
|
||||
|
||||
public function isGarbage() : bool{
|
||||
return $this->isGarbage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setGarbage(){
|
||||
$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 */
|
||||
private $server;
|
||||
/** @var resource */
|
||||
private $fp;
|
||||
/** @var int */
|
||||
private $time;
|
||||
/** @var mixed[] */
|
||||
private $data = [];
|
||||
/** @var string */
|
||||
private $encodedData = "";
|
||||
@ -134,6 +137,9 @@ class CrashDump{
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getEncodedData(){
|
||||
return $this->encodedData;
|
||||
}
|
||||
@ -142,7 +148,7 @@ class CrashDump{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
private function encodeData(){
|
||||
private function encodeData() : void{
|
||||
$this->addLine();
|
||||
$this->addLine("----------------------REPORT THE DATA BELOW THIS LINE-----------------------");
|
||||
$this->addLine();
|
||||
@ -158,7 +164,7 @@ class CrashDump{
|
||||
$this->addLine("===END CRASH DUMP===");
|
||||
}
|
||||
|
||||
private function pluginsData(){
|
||||
private function pluginsData() : void{
|
||||
if($this->server->getPluginManager() instanceof PluginManager){
|
||||
$this->addLine();
|
||||
$this->addLine("Loaded plugins:");
|
||||
@ -182,7 +188,7 @@ class CrashDump{
|
||||
}
|
||||
}
|
||||
|
||||
private function extraData(){
|
||||
private function extraData() : void{
|
||||
global $argv;
|
||||
|
||||
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;
|
||||
|
||||
if(isset($lastExceptionError)){
|
||||
@ -317,7 +323,7 @@ class CrashDump{
|
||||
return false;
|
||||
}
|
||||
|
||||
private function generalData(){
|
||||
private function generalData() : void{
|
||||
$version = new VersionString(\pocketmine\BASE_VERSION, \pocketmine\IS_DEVELOPMENT_BUILD, \pocketmine\BUILD_NUMBER);
|
||||
$this->data["general"] = [];
|
||||
$this->data["general"]["name"] = $this->server->getName();
|
||||
@ -340,10 +346,20 @@ class CrashDump{
|
||||
$this->addLine("OS : " . PHP_OS . ", " . Utils::getOS());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $line
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addLine($line = ""){
|
||||
fwrite($this->fp, $line . PHP_EOL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add($str){
|
||||
fwrite($this->fp, $str);
|
||||
}
|
||||
|
@ -44,6 +44,8 @@ interface IPlayer extends ServerOperator{
|
||||
|
||||
/**
|
||||
* @param bool $banned
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setBanned(bool $banned);
|
||||
|
||||
@ -54,6 +56,8 @@ interface IPlayer extends ServerOperator{
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setWhitelisted(bool $value);
|
||||
|
||||
|
@ -115,7 +115,7 @@ class MemoryManager{
|
||||
$this->init();
|
||||
}
|
||||
|
||||
private function init(){
|
||||
private function init() : void{
|
||||
$this->memoryLimit = ((int) $this->server->getProperty("memory.main-limit", 0)) * 1024 * 1024;
|
||||
|
||||
$defaultMemory = 1024;
|
||||
@ -201,6 +201,8 @@ class MemoryManager{
|
||||
* @param int $limit
|
||||
* @param bool $global
|
||||
* @param int $triggerCount
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
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",
|
||||
@ -230,6 +232,8 @@ class MemoryManager{
|
||||
|
||||
/**
|
||||
* Called every tick to update the memory manager state.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function check(){
|
||||
Timings::$memoryManagerTimer->startTiming();
|
||||
@ -297,6 +301,8 @@ class MemoryManager{
|
||||
* @param string $outputFolder
|
||||
* @param int $maxNesting
|
||||
* @param int $maxStringSize
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function dumpServerMemory(string $outputFolder, int $maxNesting, int $maxStringSize){
|
||||
$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 \Logger $logger
|
||||
*
|
||||
* @return void
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
public static function dumpMemory($startingObject, string $outputFolder, int $maxNesting, int $maxStringSize, \Logger $logger){
|
||||
@ -472,14 +479,14 @@ class MemoryManager{
|
||||
|
||||
/**
|
||||
* @param mixed $from
|
||||
* @param mixed &$data
|
||||
* @param object[] &$objects
|
||||
* @param int[] &$refCounts
|
||||
* @param mixed $data reference parameter
|
||||
* @param object[] $objects reference parameter
|
||||
* @param int[] $refCounts reference parameter
|
||||
* @param int $recursion
|
||||
* @param int $maxNesting
|
||||
* @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){
|
||||
$data = "(error) NESTING LIMIT REACHED";
|
||||
return;
|
||||
|
@ -57,6 +57,9 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Server
|
||||
*/
|
||||
public function getServer(){
|
||||
return $this->server;
|
||||
}
|
||||
|
@ -282,6 +282,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
/** @var string */
|
||||
protected $xuid = "";
|
||||
|
||||
/** @var int */
|
||||
protected $windowCnt = 2;
|
||||
/** @var int[] */
|
||||
protected $windows = [];
|
||||
@ -475,6 +476,11 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
return $this->playedBefore;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setAllowFlight(bool $value){
|
||||
$this->allowFlight = $value;
|
||||
$this->sendSettings();
|
||||
@ -484,6 +490,11 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
return $this->allowFlight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setFlying(bool $value){
|
||||
if($this->flying !== $value){
|
||||
$this->flying = $value;
|
||||
@ -496,6 +507,11 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
return $this->flying;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setAutoJump(bool $value){
|
||||
$this->autoJump = $value;
|
||||
$this->sendSettings();
|
||||
@ -509,6 +525,11 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
return $this->allowMovementCheats;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setAllowMovementCheats(bool $value = true){
|
||||
$this->allowMovementCheats = $value;
|
||||
}
|
||||
@ -538,6 +559,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
|
||||
/**
|
||||
* @param bool $remove
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setRemoveFormat(bool $remove = true){
|
||||
$this->removeFormat = $remove;
|
||||
@ -565,6 +588,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
|
||||
/**
|
||||
* @param Player $player
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function hidePlayer(Player $player){
|
||||
if($player === $this){
|
||||
@ -576,6 +601,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
|
||||
/**
|
||||
* @param Player $player
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function showPlayer(Player $player){
|
||||
if($player === $this){
|
||||
@ -604,6 +631,11 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
return $this->viewDistance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $distance
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setViewDistance(int $distance){
|
||||
$this->viewDistance = $this->server->getAllowedViewDistance($distance);
|
||||
|
||||
@ -634,6 +666,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setOp(bool $value){
|
||||
if($value === $this->isOp()){
|
||||
@ -685,6 +719,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
|
||||
/**
|
||||
* @param PermissionAttachment $attachment
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removeAttachment(PermissionAttachment $attachment){
|
||||
$this->perm->removeAttachment($attachment);
|
||||
@ -720,6 +756,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
return $this->perm->getEffectivePermissions();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function sendCommandData(){
|
||||
$pk = new AvailableCommandsPacket();
|
||||
foreach($this->server->getCommandMap()->getCommands() as $name => $command){
|
||||
@ -817,6 +856,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setDisplayName(string $name){
|
||||
$this->displayName = $name;
|
||||
@ -902,6 +943,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
* @internal Plugins should not use this method.
|
||||
*
|
||||
* @param int $pingMS
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function updatePing(int $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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUsingItem(bool $value){
|
||||
$this->startAction = $value ? $this->server->getTick() : -1;
|
||||
$this->setGenericFlag(self::DATA_FLAG_ACTION, $value);
|
||||
@ -995,6 +1043,13 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $z
|
||||
* @param Level|null $level
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function unloadChunk(int $x, int $z, Level $level = null){
|
||||
$level = $level ?? $this->level;
|
||||
$index = Level::chunkHash($x, $z);
|
||||
@ -1011,6 +1066,13 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
unset($this->loadQueue[$index]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $z
|
||||
* @param BatchPacket $payload
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sendChunk(int $x, int $z, BatchPacket $payload){
|
||||
if(!$this->isConnected()){
|
||||
return;
|
||||
@ -1033,6 +1095,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function sendNextChunk(){
|
||||
if(!$this->isConnected()){
|
||||
return;
|
||||
@ -1067,6 +1132,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
Timings::$playerChunkSendTimer->stopTiming();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function doFirstSpawn(){
|
||||
if($this->spawned){
|
||||
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){
|
||||
$pk = new RespawnPacket();
|
||||
$pk->position = $pos->add(0, $this->baseOffset, 0);
|
||||
@ -1245,6 +1319,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
* Position object
|
||||
*
|
||||
* @param Vector3|Position $pos
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setSpawn(Vector3 $pos){
|
||||
if(!($pos instanceof Position)){
|
||||
@ -1304,6 +1380,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function stopSleep(){
|
||||
if($this->sleeping instanceof Vector3){
|
||||
$b = $this->level->getBlock($this->sleeping);
|
||||
@ -1367,6 +1446,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
|
||||
/**
|
||||
* @param string $achievementId
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removeAchievement(string $achievementId){
|
||||
if($this->hasAchievement($achievementId)){
|
||||
@ -1455,6 +1536,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
/**
|
||||
* @internal
|
||||
* Sends the player's gamemode to the client.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sendGamemode(){
|
||||
$pk = new SetPlayerGameTypePacket();
|
||||
@ -1464,6 +1547,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
|
||||
/**
|
||||
* Sends all the option flags
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sendSettings(){
|
||||
$pk = new AdventureSettingsPacket();
|
||||
@ -1569,6 +1654,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
return false; //currently has no server-side movement
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function checkNearEntities(){
|
||||
foreach($this->level->getNearbyEntities($this->boundingBox->expandedCopy(1, 0.5, 1), $this) as $entity){
|
||||
$entity->scheduleUpdate();
|
||||
@ -1581,6 +1669,11 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $tickDiff
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function processMovement(int $tickDiff){
|
||||
if(!$this->isAlive() or !$this->spawned or $this->newPosition === null or $this->isSleeping()){
|
||||
return;
|
||||
@ -1723,6 +1816,11 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $sendAll
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sendAttributes(bool $sendAll = false){
|
||||
$entries = $sendAll ? $this->attributeMap->getAll() : $this->attributeMap->needSend();
|
||||
if(count($entries) > 0){
|
||||
@ -1828,6 +1926,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
$this->dataPacket($pk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function checkNetwork(){
|
||||
if(!$this->isOnline()){
|
||||
return;
|
||||
@ -1976,6 +2077,12 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $status
|
||||
* @param bool $immediate
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sendPlayStatus(int $status, bool $immediate = false){
|
||||
$pk = new PlayStatusPacket();
|
||||
$pk->status = $status;
|
||||
@ -2019,6 +2126,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
$this->processLogin();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function processLogin(){
|
||||
foreach($this->server->getLoggedInPlayers() as $p){
|
||||
if($p !== $this and ($p->iusername === $this->iusername or $this->getUniqueId()->equals($p->getUniqueId()))){
|
||||
@ -2135,6 +2245,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function completeLoginSequence(){
|
||||
/** @var float[] $pos */
|
||||
$pos = $this->namedtag->getListTag("Pos")->getAllValues();
|
||||
@ -3155,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.
|
||||
*
|
||||
* @param DataPacket $packet
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handleDataPacket(DataPacket $packet){
|
||||
if($this->sessionAdapter !== null){
|
||||
@ -3312,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 $stay Duration in ticks to stay on screen for
|
||||
* @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){
|
||||
$this->setTitleDuration($fadeIn, $stay, $fadeOut);
|
||||
@ -3325,6 +3442,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
* Sets the subtitle message, without sending a title.
|
||||
*
|
||||
* @param string $subtitle
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addSubTitle(string $subtitle){
|
||||
$this->sendTitleText($subtitle, SetTitlePacket::TYPE_SET_SUBTITLE);
|
||||
@ -3334,6 +3453,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
* Adds small text to the user's screen.
|
||||
*
|
||||
* @param string $message
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addActionBarMessage(string $message){
|
||||
$this->sendTitleText($message, SetTitlePacket::TYPE_SET_ACTIONBAR_MESSAGE);
|
||||
@ -3341,6 +3462,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
|
||||
/**
|
||||
* Removes the title from the client's screen.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removeTitles(){
|
||||
$pk = new SetTitlePacket();
|
||||
@ -3350,6 +3473,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
|
||||
/**
|
||||
* Resets the title duration settings to defaults and removes any existing titles.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function resetTitles(){
|
||||
$pk = new SetTitlePacket();
|
||||
@ -3363,6 +3488,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
* @param int $fadeIn Title fade-in time in ticks.
|
||||
* @param int $stay Title stay time in ticks.
|
||||
* @param int $fadeOut Title fade-out time in ticks.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setTitleDuration(int $fadeIn, int $stay, int $fadeOut){
|
||||
if($fadeIn >= 0 and $stay >= 0 and $fadeOut >= 0){
|
||||
@ -3380,6 +3507,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
*
|
||||
* @param string $title
|
||||
* @param int $type
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function sendTitleText(string $title, int $type){
|
||||
$pk = new SetTitlePacket();
|
||||
@ -3392,6 +3521,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
* Sends a direct chat message to a player
|
||||
*
|
||||
* @param TextContainer|string $message
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sendMessage($message){
|
||||
if($message instanceof TextContainer){
|
||||
@ -3411,6 +3542,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
/**
|
||||
* @param string $message
|
||||
* @param string[] $parameters
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sendTranslation(string $message, array $parameters = []){
|
||||
$pk = new TextPacket();
|
||||
@ -3436,6 +3569,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
*
|
||||
* @param string $message
|
||||
* @param string $subtitle @deprecated
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sendPopup(string $message, string $subtitle = ""){
|
||||
$pk = new TextPacket();
|
||||
@ -3444,6 +3579,11 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
$this->dataPacket($pk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sendTip(string $message){
|
||||
$pk = new TextPacket();
|
||||
$pk->type = TextPacket::TYPE_TIP;
|
||||
@ -3454,6 +3594,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
/**
|
||||
* @param string $sender
|
||||
* @param string $message
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sendWhisper(string $sender, string $message){
|
||||
$pk = new TextPacket();
|
||||
@ -3595,6 +3737,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function __debugInfo(){
|
||||
return [];
|
||||
}
|
||||
@ -3611,6 +3756,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
* Handles player data saving
|
||||
*
|
||||
* @throws \InvalidStateException if the player is closed
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function save(){
|
||||
if($this->closed){
|
||||
@ -3773,6 +3920,15 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
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){
|
||||
$yaw = $yaw ?? $this->yaw;
|
||||
$pitch = $pitch ?? $this->pitch;
|
||||
@ -3824,6 +3980,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function addDefaultWindows(){
|
||||
$this->addWindow($this->getInventory(), ContainerIds::INVENTORY, true);
|
||||
|
||||
@ -3949,6 +4108,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
* @param Inventory $inventory
|
||||
* @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
|
||||
*/
|
||||
public function removeWindow(Inventory $inventory, bool $force = false){
|
||||
@ -3968,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.
|
||||
*
|
||||
* @param bool $removePermanentWindows Whether to remove permanent windows.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removeAllWindows(bool $removePermanentWindows = false){
|
||||
foreach($this->windowIndex as $id => $window){
|
||||
@ -3979,6 +4141,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function sendAllInventories(){
|
||||
foreach($this->windowIndex as $id => $inventory){
|
||||
$inventory->sendContents($this);
|
||||
|
@ -36,6 +36,10 @@ namespace pocketmine {
|
||||
|
||||
const MIN_PHP_VERSION = "7.2.0";
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
* @return void
|
||||
*/
|
||||
function critical_error($message){
|
||||
echo "[ERROR] $message" . PHP_EOL;
|
||||
}
|
||||
@ -117,6 +121,10 @@ namespace pocketmine {
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Logger $logger
|
||||
* @return void
|
||||
*/
|
||||
function emit_performance_warnings(\Logger $logger){
|
||||
if(extension_loaded("xdebug")){
|
||||
$logger->warning("Xdebug extension is enabled. This has a major impact on performance.");
|
||||
@ -132,6 +140,9 @@ namespace pocketmine {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
function set_ini_entries(){
|
||||
ini_set("allow_url_fopen", '1');
|
||||
ini_set("display_errors", '1');
|
||||
@ -140,6 +151,9 @@ namespace pocketmine {
|
||||
ini_set('assert.exception', '1');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
function server(){
|
||||
if(count($messages = check_platform_dependencies()) > 0){
|
||||
echo PHP_EOL;
|
||||
@ -157,17 +171,11 @@ namespace pocketmine {
|
||||
error_reporting(-1);
|
||||
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:"]);
|
||||
if(isset($opts["bootstrap"])){
|
||||
$bootstrap = realpath($opts["bootstrap"]) ?: $opts["bootstrap"];
|
||||
}else{
|
||||
$bootstrap = \pocketmine\PATH . 'vendor/autoload.php';
|
||||
$bootstrap = dirname(__FILE__, 3) . '/vendor/autoload.php';
|
||||
}
|
||||
define('pocketmine\COMPOSER_AUTOLOADER_PATH', $bootstrap);
|
||||
|
||||
@ -198,8 +206,6 @@ namespace pocketmine {
|
||||
|
||||
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"]);
|
||||
|
||||
define('pocketmine\DATA', isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR);
|
||||
|
@ -483,6 +483,8 @@ class Server{
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setAutoSave(bool $value){
|
||||
$this->autoSave = $value;
|
||||
@ -874,6 +876,8 @@ class Server{
|
||||
/**
|
||||
* @param string $name
|
||||
* @param CompoundTag $nbtTag
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function saveOfflinePlayerData(string $name, CompoundTag $nbtTag){
|
||||
$ev = new PlayerDataSaveEvent($nbtTag, $name);
|
||||
@ -1277,6 +1281,8 @@ class Server{
|
||||
/**
|
||||
* @param string $variable
|
||||
* @param string $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setConfigString(string $variable, string $value){
|
||||
$this->properties->set($variable, $value);
|
||||
@ -1300,6 +1306,8 @@ class Server{
|
||||
/**
|
||||
* @param string $variable
|
||||
* @param int $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setConfigInt(string $variable, int $value){
|
||||
$this->properties->set($variable, $value);
|
||||
@ -1336,6 +1344,8 @@ class Server{
|
||||
/**
|
||||
* @param string $variable
|
||||
* @param bool $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setConfigBool(string $variable, bool $value){
|
||||
$this->properties->set($variable, $value ? "1" : "0");
|
||||
@ -1370,6 +1380,8 @@ class Server{
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addOp(string $name){
|
||||
$this->operators->set(strtolower($name), true);
|
||||
@ -1382,6 +1394,8 @@ class Server{
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removeOp(string $name){
|
||||
$this->operators->remove(strtolower($name));
|
||||
@ -1394,6 +1408,8 @@ class Server{
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addWhitelist(string $name){
|
||||
$this->whitelist->set(strtolower($name), true);
|
||||
@ -1402,6 +1418,8 @@ class Server{
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removeWhitelist(string $name){
|
||||
$this->whitelist->remove(strtolower($name));
|
||||
@ -1440,6 +1458,9 @@ class Server{
|
||||
return $this->operators;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function reloadWhitelist(){
|
||||
$this->whitelist->reload();
|
||||
}
|
||||
@ -1476,6 +1497,11 @@ class Server{
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $microseconds
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function microSleep(int $microseconds){
|
||||
Server::$sleeper->synchronized(function(int $ms){
|
||||
Server::$sleeper->wait($ms);
|
||||
@ -1913,6 +1939,8 @@ class Server{
|
||||
*
|
||||
* @param Player[] $players
|
||||
* @param DataPacket $packet
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function broadcastPacket(array $players, DataPacket $packet){
|
||||
$packet->encode();
|
||||
@ -1926,6 +1954,8 @@ class Server{
|
||||
* @param DataPacket[] $packets
|
||||
* @param bool $forceSync
|
||||
* @param bool $immediate
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function batchPackets(array $players, array $packets, bool $forceSync = false, bool $immediate = false){
|
||||
if(count($packets) === 0){
|
||||
@ -1964,6 +1994,8 @@ class Server{
|
||||
* @param BatchPacket $pk
|
||||
* @param Player[] $players
|
||||
* @param bool $immediate
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function broadcastPacketsCallback(BatchPacket $pk, array $players, bool $immediate = false){
|
||||
if(!$pk->isEncoded){
|
||||
@ -1978,6 +2010,8 @@ class Server{
|
||||
|
||||
/**
|
||||
* @param int $type
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function enablePlugins(int $type){
|
||||
foreach($this->pluginManager->getPlugins() as $plugin){
|
||||
@ -1994,11 +2028,16 @@ class Server{
|
||||
|
||||
/**
|
||||
* @param Plugin $plugin
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function enablePlugin(Plugin $plugin){
|
||||
$this->pluginManager->enablePlugin($plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function disablePlugins(){
|
||||
$this->pluginManager->disablePlugins();
|
||||
}
|
||||
@ -2033,6 +2072,9 @@ class Server{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function reload(){
|
||||
$this->logger->info("Saving worlds...");
|
||||
|
||||
@ -2072,11 +2114,16 @@ class Server{
|
||||
|
||||
/**
|
||||
* Shuts the server down correctly
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function shutdown(){
|
||||
$this->isRunning = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function forceShutdown(){
|
||||
if($this->hasStopped){
|
||||
return;
|
||||
@ -2162,7 +2209,7 @@ class Server{
|
||||
/**
|
||||
* Starts the PocketMine-MP server and starts processing ticks and packets
|
||||
*/
|
||||
private function start(){
|
||||
private function start() : void{
|
||||
if($this->getConfigBool("enable-query", true)){
|
||||
$this->queryHandler = new QueryHandler();
|
||||
}
|
||||
@ -2204,6 +2251,11 @@ class Server{
|
||||
$this->forceShutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $signo
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handleSignal($signo){
|
||||
if($signo === SIGTERM or $signo === SIGINT or $signo === SIGHUP){
|
||||
$this->shutdown();
|
||||
@ -2213,6 +2265,8 @@ class Server{
|
||||
/**
|
||||
* @param \Throwable $e
|
||||
* @param array|null $trace
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function exceptionHandler(\Throwable $e, $trace = null){
|
||||
while(@ob_end_flush()){}
|
||||
@ -2331,6 +2385,9 @@ class Server{
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function __debugInfo(){
|
||||
return [];
|
||||
}
|
||||
@ -2339,7 +2396,7 @@ class Server{
|
||||
return $this->tickSleeper;
|
||||
}
|
||||
|
||||
private function tickProcessor(){
|
||||
private function tickProcessor() : void{
|
||||
$this->nextTick = microtime(true);
|
||||
|
||||
while($this->isRunning){
|
||||
@ -2350,6 +2407,11 @@ class Server{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Player $player
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function onPlayerLogin(Player $player){
|
||||
if($this->sendUsageTicker > 0){
|
||||
$this->uniquePlayers[$player->getRawUniqueId()] = $player->getRawUniqueId();
|
||||
@ -2358,27 +2420,49 @@ class Server{
|
||||
$this->loggedInPlayers[$player->getRawUniqueId()] = $player;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Player $player
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function onPlayerLogout(Player $player){
|
||||
unset($this->loggedInPlayers[$player->getRawUniqueId()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Player $player
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addPlayer(Player $player){
|
||||
$this->players[spl_object_hash($player)] = $player;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Player $player
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removePlayer(Player $player){
|
||||
unset($this->players[spl_object_hash($player)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Player $player
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addOnlinePlayer(Player $player){
|
||||
$this->updatePlayerListData($player->getUniqueId(), $player->getId(), $player->getDisplayName(), $player->getSkin(), $player->getXuid());
|
||||
|
||||
$this->playerList[$player->getRawUniqueId()] = $player;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Player $player
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removeOnlinePlayer(Player $player){
|
||||
if(isset($this->playerList[$player->getRawUniqueId()])){
|
||||
unset($this->playerList[$player->getRawUniqueId()]);
|
||||
@ -2394,6 +2478,8 @@ class Server{
|
||||
* @param Skin $skin
|
||||
* @param string $xboxUserId
|
||||
* @param Player[]|null $players
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function updatePlayerListData(UUID $uuid, int $entityId, string $name, Skin $skin, string $xboxUserId = "", array $players = null){
|
||||
$pk = new PlayerListPacket();
|
||||
@ -2407,6 +2493,8 @@ class Server{
|
||||
/**
|
||||
* @param UUID $uuid
|
||||
* @param Player[]|null $players
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removePlayerListData(UUID $uuid, array $players = null){
|
||||
$pk = new PlayerListPacket();
|
||||
@ -2417,6 +2505,8 @@ class Server{
|
||||
|
||||
/**
|
||||
* @param Player $p
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sendFullPlayerListData(Player $p){
|
||||
$pk = new PlayerListPacket();
|
||||
@ -2452,6 +2542,9 @@ class Server{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function doAutoSave(){
|
||||
if($this->getAutoSave()){
|
||||
Timings::$worldSaveTimer->startTiming();
|
||||
@ -2470,6 +2563,11 @@ class Server{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $type
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sendUsage($type = SendUsageTask::TYPE_STATUS){
|
||||
if((bool) $this->getProperty("anonymous-statistics.enabled", true)){
|
||||
$this->asyncPool->submitTask(new SendUsageTask($this, $type, $this->uniquePlayers));
|
||||
@ -2506,7 +2604,7 @@ class Server{
|
||||
return $this->memoryManager;
|
||||
}
|
||||
|
||||
private function titleTick(){
|
||||
private function titleTick() : void{
|
||||
Timings::$titleTickTimer->startTiming();
|
||||
$d = Utils::getRealMemoryUsage();
|
||||
|
||||
@ -2531,6 +2629,8 @@ class Server{
|
||||
* @param int $port
|
||||
* @param string $payload
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* TODO: move this to Network
|
||||
*/
|
||||
public function handlePacket(AdvancedSourceInterface $interface, string $address, int $port, string $payload){
|
||||
|
@ -33,12 +33,21 @@ abstract class Thread extends \Thread{
|
||||
/** @var string|null */
|
||||
protected $composerAutoloaderPath;
|
||||
|
||||
/** @var bool */
|
||||
protected $isKilled = false;
|
||||
|
||||
/**
|
||||
* @return \ClassLoader|null
|
||||
*/
|
||||
public function getClassLoader(){
|
||||
return $this->classLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \ClassLoader|null $loader
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setClassLoader(\ClassLoader $loader = null){
|
||||
$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.
|
||||
* 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).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function registerClassLoader(){
|
||||
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){
|
||||
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.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function quit(){
|
||||
$this->isKilled = true;
|
||||
|
@ -31,6 +31,9 @@ class ThreadManager extends \Volatile{
|
||||
/** @var ThreadManager */
|
||||
private static $instance = null;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public static function init(){
|
||||
self::$instance = new ThreadManager();
|
||||
}
|
||||
@ -44,6 +47,8 @@ class ThreadManager extends \Volatile{
|
||||
|
||||
/**
|
||||
* @param Worker|Thread $thread
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add($thread){
|
||||
if($thread instanceof Thread or $thread instanceof Worker){
|
||||
@ -53,6 +58,8 @@ class ThreadManager extends \Volatile{
|
||||
|
||||
/**
|
||||
* @param Worker|Thread $thread
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function remove($thread){
|
||||
if($thread instanceof Thread or $thread instanceof Worker){
|
||||
|
@ -32,6 +32,6 @@ const _VERSION_INFO_INCLUDED = true;
|
||||
|
||||
|
||||
const NAME = "PocketMine-MP";
|
||||
const BASE_VERSION = "3.11.3";
|
||||
const BASE_VERSION = "3.11.4";
|
||||
const IS_DEVELOPMENT_BUILD = false;
|
||||
const BUILD_NUMBER = 0;
|
||||
|
@ -33,12 +33,21 @@ abstract class Worker extends \Worker{
|
||||
/** @var string|null */
|
||||
protected $composerAutoloaderPath;
|
||||
|
||||
/** @var bool */
|
||||
protected $isKilled = false;
|
||||
|
||||
/**
|
||||
* @return \ClassLoader|null
|
||||
*/
|
||||
public function getClassLoader(){
|
||||
return $this->classLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \ClassLoader|null $loader
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setClassLoader(\ClassLoader $loader = null){
|
||||
$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.
|
||||
* 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).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function registerClassLoader(){
|
||||
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){
|
||||
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.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function quit(){
|
||||
$this->isKilled = true;
|
||||
|
@ -76,6 +76,11 @@ class Bed extends Transparent{
|
||||
return ($this->meta & self::BITFLAG_OCCUPIED) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $occupied
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setOccupied(bool $occupied = true){
|
||||
if($occupied){
|
||||
$this->meta |= self::BITFLAG_OCCUPIED;
|
||||
|
@ -111,6 +111,11 @@ class CobblestoneWall extends Transparent{
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Block $block
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canConnect(Block $block){
|
||||
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;
|
||||
}
|
||||
|
||||
private function getFullDamage(){
|
||||
private function getFullDamage() : int{
|
||||
$damage = $this->getDamage();
|
||||
$isUp = ($damage & 0x08) > 0;
|
||||
|
||||
|
@ -103,6 +103,11 @@ abstract class Fence extends Transparent{
|
||||
return $bbs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Block $block
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canConnect(Block $block){
|
||||
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;
|
||||
|
||||
protected $id = self::LEAVES;
|
||||
/** @var int */
|
||||
protected $woodType = self::WOOD;
|
||||
|
||||
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;
|
||||
if(isset($visited[$index])){
|
||||
return false;
|
||||
|
@ -29,6 +29,7 @@ use pocketmine\item\ItemFactory;
|
||||
class Leaves2 extends Leaves{
|
||||
|
||||
protected $id = self::LEAVES2;
|
||||
/** @var int */
|
||||
protected $woodType = self::WOOD2;
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -38,6 +38,7 @@ use function min;
|
||||
|
||||
abstract class Liquid extends Transparent{
|
||||
|
||||
/** @var int */
|
||||
public $adjacentSources = 0;
|
||||
|
||||
/** @var Vector3|null */
|
||||
@ -90,6 +91,9 @@ abstract class Liquid extends Transparent{
|
||||
|
||||
abstract public function getBucketEmptySound() : int;
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getFluidHeightPercent(){
|
||||
$d = $this->meta;
|
||||
if($d >= 8){
|
||||
@ -430,6 +434,9 @@ abstract class Liquid extends Transparent{
|
||||
return ($decay >= 0 && $blockDecay >= $decay) ? $decay : $blockDecay;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function checkForHarden(){
|
||||
|
||||
}
|
||||
|
@ -74,6 +74,11 @@ class TNT extends Solid{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $fuse
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function ignite(int $fuse = 80){
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
||||
|
||||
|
@ -114,6 +114,8 @@ abstract class Command{
|
||||
|
||||
/**
|
||||
* @param string|null $permission
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPermission(string $permission = null){
|
||||
$this->permission = $permission;
|
||||
@ -259,6 +261,8 @@ abstract class Command{
|
||||
|
||||
/**
|
||||
* @param string[] $aliases
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setAliases(array $aliases){
|
||||
$this->aliases = $aliases;
|
||||
@ -269,6 +273,8 @@ abstract class Command{
|
||||
|
||||
/**
|
||||
* @param string $description
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setDescription(string $description){
|
||||
$this->description = $description;
|
||||
@ -276,6 +282,8 @@ abstract class Command{
|
||||
|
||||
/**
|
||||
* @param string $permissionMessage
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPermissionMessage(string $permissionMessage){
|
||||
$this->permissionMessage = $permissionMessage;
|
||||
@ -283,6 +291,8 @@ abstract class Command{
|
||||
|
||||
/**
|
||||
* @param string $usage
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUsage(string $usage){
|
||||
$this->usageMessage = $usage;
|
||||
@ -292,6 +302,8 @@ abstract class Command{
|
||||
* @param CommandSender $source
|
||||
* @param TextContainer|string $message
|
||||
* @param bool $sendToSource
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function broadcastCommandMessage(CommandSender $source, $message, bool $sendToSource = true){
|
||||
if($message instanceof TextContainer){
|
||||
|
@ -29,6 +29,8 @@ interface CommandMap{
|
||||
/**
|
||||
* @param string $fallbackPrefix
|
||||
* @param Command[] $commands
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function registerAll(string $fallbackPrefix, array $commands);
|
||||
|
||||
|
@ -54,7 +54,9 @@ class CommandReader extends Thread{
|
||||
|
||||
/** @var \Threaded */
|
||||
protected $buffer;
|
||||
/** @var bool */
|
||||
private $shutdown = false;
|
||||
/** @var int */
|
||||
private $type = self::TYPE_STREAM;
|
||||
|
||||
/** @var SleeperNotifier|null */
|
||||
@ -71,6 +73,9 @@ class CommandReader extends Thread{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function shutdown(){
|
||||
$this->shutdown = true;
|
||||
}
|
||||
@ -94,7 +99,7 @@ class CommandReader extends Thread{
|
||||
throw new \ThreadException($message);
|
||||
}
|
||||
|
||||
private function initStdin(){
|
||||
private function initStdin() : void{
|
||||
if(is_resource(self::$stdin)){
|
||||
fclose(self::$stdin);
|
||||
}
|
||||
@ -185,6 +190,9 @@ class CommandReader extends Thread{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function run(){
|
||||
$this->registerClassLoader();
|
||||
|
||||
|
@ -31,6 +31,8 @@ interface CommandSender extends Permissible{
|
||||
|
||||
/**
|
||||
* @param TextContainer|string $message
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param int|null $height
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setScreenLineHeight(int $height = null);
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ use const PHP_INT_MAX;
|
||||
|
||||
class ConsoleCommandSender implements CommandSender{
|
||||
|
||||
/** @var PermissibleBase */
|
||||
private $perm;
|
||||
|
||||
/** @var int|null */
|
||||
@ -104,6 +105,8 @@ class ConsoleCommandSender implements CommandSender{
|
||||
|
||||
/**
|
||||
* @param TextContainer|string $message
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sendMessage($message){
|
||||
if($message instanceof TextContainer){
|
||||
@ -133,6 +136,8 @@ class ConsoleCommandSender implements CommandSender{
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setOp(bool $value){
|
||||
|
||||
|
@ -32,6 +32,7 @@ use function strpos;
|
||||
use function substr;
|
||||
|
||||
class FormattedCommandAlias extends Command{
|
||||
/** @var string[] */
|
||||
private $formatStrings = [];
|
||||
|
||||
/**
|
||||
|
@ -70,6 +70,8 @@ class PluginCommand extends Command implements PluginIdentifiableCommand{
|
||||
|
||||
/**
|
||||
* @param CommandExecutor $executor
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setExecutor(CommandExecutor $executor){
|
||||
$this->executor = $executor;
|
||||
|
@ -41,6 +41,9 @@ class RemoteConsoleCommandSender extends ConsoleCommandSender{
|
||||
$this->messages .= trim($message, "\r\n") . "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getMessage(){
|
||||
return $this->messages;
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ class SimpleCommandMap implements CommandMap{
|
||||
$this->setDefaultCommands();
|
||||
}
|
||||
|
||||
private function setDefaultCommands(){
|
||||
private function setDefaultCommands() : void{
|
||||
$this->registerAll("pocketmine", [
|
||||
new BanCommand("ban"),
|
||||
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.
|
||||
* The referenced parameters will be modified accordingly depending on the resulting matched command.
|
||||
*
|
||||
* @param string &$commandName
|
||||
* @param string[] &$args
|
||||
* @param string $commandName reference parameter
|
||||
* @param string[] $args reference parameter
|
||||
*
|
||||
* @return Command|null
|
||||
*/
|
||||
|
@ -75,7 +75,7 @@ class BanIpCommand extends VanillaCommand{
|
||||
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());
|
||||
|
||||
foreach($sender->getServer()->getOnlinePlayers() as $player){
|
||||
|
@ -84,7 +84,7 @@ class VersionCommand extends VanillaCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
private function describeToSender(Plugin $plugin, CommandSender $sender){
|
||||
private function describeToSender(Plugin $plugin, CommandSender $sender) : void{
|
||||
$desc = $plugin->getDescription();
|
||||
$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 ZOMBIE_SPAWN_REINFORCEMENTS = 15;
|
||||
|
||||
/** @var int */
|
||||
private $id;
|
||||
/** @var float */
|
||||
protected $minValue;
|
||||
/** @var float */
|
||||
protected $maxValue;
|
||||
/** @var float */
|
||||
protected $defaultValue;
|
||||
/** @var float */
|
||||
protected $currentValue;
|
||||
/** @var string */
|
||||
protected $name;
|
||||
/** @var bool */
|
||||
protected $shouldSend;
|
||||
|
||||
/** @var bool */
|
||||
protected $desynchronized = true;
|
||||
|
||||
/** @var Attribute[] */
|
||||
@ -137,6 +145,11 @@ class Attribute{
|
||||
return $this->minValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $minValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setMinValue(float $minValue){
|
||||
if($minValue > ($max = $this->getMaxValue())){
|
||||
throw new \InvalidArgumentException("Minimum $minValue is greater than the maximum $max");
|
||||
@ -153,6 +166,11 @@ class Attribute{
|
||||
return $this->maxValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $maxValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setMaxValue(float $maxValue){
|
||||
if($maxValue < ($min = $this->getMinValue())){
|
||||
throw new \InvalidArgumentException("Maximum $maxValue is less than the minimum $min");
|
||||
@ -169,6 +187,11 @@ class Attribute{
|
||||
return $this->defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $defaultValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setDefaultValue(float $defaultValue){
|
||||
if($defaultValue > $this->getMaxValue() or $defaultValue < $this->getMinValue()){
|
||||
throw new \InvalidArgumentException("Default $defaultValue is outside the range " . $this->getMinValue() . " - " . $this->getMaxValue());
|
||||
|
@ -25,6 +25,9 @@ namespace pocketmine\entity;
|
||||
|
||||
use function array_filter;
|
||||
|
||||
/**
|
||||
* @phpstan-implements \ArrayAccess<int, float>
|
||||
*/
|
||||
class AttributeMap implements \ArrayAccess{
|
||||
/** @var Attribute[] */
|
||||
private $attributes = [];
|
||||
@ -58,6 +61,11 @@ class AttributeMap implements \ArrayAccess{
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $offset
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function offsetExists($offset) : bool{
|
||||
return isset($this->attributes[$offset]);
|
||||
}
|
||||
@ -79,6 +87,9 @@ class AttributeMap implements \ArrayAccess{
|
||||
$this->attributes[$offset]->setValue($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $offset
|
||||
*/
|
||||
public function offsetUnset($offset) : void{
|
||||
throw new \RuntimeException("Could not unset an attribute from an attribute map");
|
||||
}
|
||||
|
@ -32,8 +32,10 @@ use function is_string;
|
||||
|
||||
class DataPropertyManager{
|
||||
|
||||
/** @var mixed[][] */
|
||||
private $properties = [];
|
||||
|
||||
/** @var mixed[][] */
|
||||
private $dirtyProperties = [];
|
||||
|
||||
public function __construct(){
|
||||
|
@ -317,6 +317,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
public const DATA_PLAYER_FLAG_SLEEP = 1;
|
||||
public const DATA_PLAYER_FLAG_DEAD = 2; //TODO: CHECK
|
||||
|
||||
/** @var int */
|
||||
public static $entityCount = 1;
|
||||
/** @var string[] */
|
||||
private static $knownEntities = [];
|
||||
@ -504,6 +505,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
|
||||
/** @var float */
|
||||
private $health = 20.0;
|
||||
/** @var int */
|
||||
private $maxHealth = 20;
|
||||
|
||||
/** @var float */
|
||||
@ -1210,15 +1212,19 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
}
|
||||
|
||||
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;
|
||||
$diffRotation = ($this->yaw - $this->lastYaw) ** 2 + ($this->pitch - $this->lastPitch) ** 2;
|
||||
|
||||
$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->lastY = $this->y;
|
||||
$this->lastZ = $this->z;
|
||||
@ -1229,7 +1235,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
$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->broadcastMotion();
|
||||
@ -2279,6 +2285,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return void
|
||||
* @throws \ErrorException
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
|
@ -26,5 +26,8 @@ namespace pocketmine\entity;
|
||||
|
||||
interface Explosive{
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function explode();
|
||||
}
|
||||
|
@ -81,6 +81,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
||||
|
||||
/** @var UUID */
|
||||
protected $uuid;
|
||||
/** @var string */
|
||||
protected $rawUUID;
|
||||
|
||||
public $width = 0.6;
|
||||
@ -90,10 +91,14 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
||||
/** @var Skin */
|
||||
protected $skin;
|
||||
|
||||
/** @var int */
|
||||
protected $foodTickTimer = 0;
|
||||
|
||||
/** @var int */
|
||||
protected $totalXp = 0;
|
||||
/** @var int */
|
||||
protected $xpSeed;
|
||||
/** @var int */
|
||||
protected $xpCooldown = 0;
|
||||
|
||||
protected $baseOffset = 1.62;
|
||||
|
@ -70,6 +70,7 @@ abstract class Living extends Entity implements Damageable{
|
||||
protected $gravity = 0.08;
|
||||
protected $drag = 0.02;
|
||||
|
||||
/** @var int */
|
||||
protected $attackTime = 0;
|
||||
|
||||
/** @var int */
|
||||
@ -77,6 +78,7 @@ abstract class Living extends Entity implements Damageable{
|
||||
/** @var int */
|
||||
protected $maxDeadTicks = 25;
|
||||
|
||||
/** @var float */
|
||||
protected $jumpVelocity = 0.42;
|
||||
|
||||
/** @var EffectInstance[] */
|
||||
|
@ -42,8 +42,10 @@ class Squid extends WaterAnimal{
|
||||
|
||||
/** @var Vector3|null */
|
||||
public $swimDirection = null;
|
||||
/** @var float */
|
||||
public $swimSpeed = 0.1;
|
||||
|
||||
/** @var int */
|
||||
private $switchDirectionTicker = 0;
|
||||
|
||||
public function initEntity() : void{
|
||||
|
@ -43,6 +43,7 @@ class PrimedTNT extends Entity implements Explosive{
|
||||
protected $gravity = 0.04;
|
||||
protected $drag = 0.02;
|
||||
|
||||
/** @var int */
|
||||
protected $fuse;
|
||||
|
||||
public $canCollide = false;
|
||||
|
@ -35,6 +35,8 @@ interface Cancellable{
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setCancelled(bool $value = true);
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ use pocketmine\entity\Entity;
|
||||
use pocketmine\event\Cancellable;
|
||||
|
||||
class EntityCombustEvent extends EntityEvent implements Cancellable{
|
||||
/** @var int */
|
||||
protected $duration;
|
||||
|
||||
/**
|
||||
|
@ -99,6 +99,8 @@ class PlayerCreationEvent extends Event{
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setBaseClass($class){
|
||||
if(!is_a($class, $this->baseClass, true)){
|
||||
@ -117,6 +119,8 @@ class PlayerCreationEvent extends Event{
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPlayerClass($class){
|
||||
if(!is_a($class, $this->baseClass, true)){
|
||||
|
@ -40,6 +40,7 @@ class PlayerDeathEvent extends EntityDeathEvent{
|
||||
|
||||
/** @var TextContainer|string */
|
||||
private $deathMessage;
|
||||
/** @var bool */
|
||||
private $keepInventory = false;
|
||||
|
||||
/**
|
||||
|
@ -84,6 +84,8 @@ abstract class BaseInventory implements Inventory{
|
||||
* WARNING: If the size is smaller, any items past the new size will be lost.
|
||||
*
|
||||
* @param int $size
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setSize(int $size){
|
||||
$this->slots->setSize($size);
|
||||
|
@ -142,6 +142,9 @@ class DoubleChestInventory extends ChestInventory implements InventoryHolder{
|
||||
return $this->right;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function invalidate(){
|
||||
$this->left = null;
|
||||
$this->right = null;
|
||||
|
@ -53,6 +53,8 @@ class EnderChestInventory extends ChestInventory{
|
||||
* Set the holder's position to that of a tile
|
||||
*
|
||||
* @param EnderChest $enderChest
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setHolderPosition(EnderChest $enderChest){
|
||||
$this->holder->setComponents($enderChest->getFloorX(), $enderChest->getFloorY(), $enderChest->getFloorZ());
|
||||
|
@ -44,6 +44,8 @@ class FurnaceRecipe implements Recipe{
|
||||
|
||||
/**
|
||||
* @param Item $item
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setInput(Item $item){
|
||||
$this->ingredient = clone $item;
|
||||
|
@ -39,6 +39,7 @@ class MultiRecipe{
|
||||
public const TYPE_FIREWORKS = "00000000-0000-0000-0000-000000000002";
|
||||
public const TYPE_MAP_LOCKING_CARTOGRAPHY = "602234E4-CAC1-4353-8BB7-B1EBFF70024B";
|
||||
|
||||
/** @var UUID */
|
||||
private $uuid;
|
||||
|
||||
public function __construct(UUID $uuid){
|
||||
|
@ -97,7 +97,7 @@ class PlayerInventory extends BaseInventory{
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
private function throwIfNotHotbarSlot(int $slot){
|
||||
private function throwIfNotHotbarSlot(int $slot) : void{
|
||||
if(!$this->isHotbarSlot($slot)){
|
||||
throw new \InvalidArgumentException("$slot is not a valid hotbar slot index (expected 0 - " . ($this->getHotbarSize() - 1) . ")");
|
||||
}
|
||||
@ -132,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.
|
||||
* 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
|
||||
*/
|
||||
public function setHeldItemIndex(int $hotbarSlot, bool $send = true){
|
||||
@ -170,6 +171,8 @@ class PlayerInventory extends BaseInventory{
|
||||
* Sends the currently-held item to specified targets.
|
||||
*
|
||||
* @param Player|Player[] $target
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sendHeldItem($target){
|
||||
$item = $this->getItemInHand();
|
||||
@ -201,6 +204,9 @@ class PlayerInventory extends BaseInventory{
|
||||
return 9;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function sendCreativeContents(){
|
||||
//TODO: this mess shouldn't be in here
|
||||
$holder = $this->getHolder();
|
||||
|
@ -53,6 +53,7 @@ use function spl_object_hash;
|
||||
* @see InventoryAction
|
||||
*/
|
||||
class InventoryTransaction{
|
||||
/** @var bool */
|
||||
protected $hasExecuted = false;
|
||||
/** @var Player */
|
||||
protected $source;
|
||||
|
@ -37,6 +37,7 @@ class CreativeInventoryAction extends InventoryAction{
|
||||
*/
|
||||
public const TYPE_CREATE_ITEM = 1;
|
||||
|
||||
/** @var int */
|
||||
protected $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.
|
||||
*
|
||||
* @param Living $consumer
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function onConsume(Living $consumer);
|
||||
}
|
||||
|
@ -42,6 +42,8 @@ abstract class Durable extends Item{
|
||||
* Sets whether the item will take damage when used.
|
||||
*
|
||||
* @param bool $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUnbreakable(bool $value = true){
|
||||
$this->setNamedTagEntry(new ByteTag("Unbreakable", $value ? 1 : 0));
|
||||
|
@ -123,6 +123,9 @@ class Item implements ItemIds, \JsonSerializable{
|
||||
/** @var Item[] */
|
||||
private static $creative = [];
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public static function initCreativeItems(){
|
||||
self::clearCreativeItems();
|
||||
|
||||
@ -140,6 +143,8 @@ class Item implements ItemIds, \JsonSerializable{
|
||||
/**
|
||||
* Removes all previously added items from the creative menu.
|
||||
* Note: Players who are already online when this is called will not see this change.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function clearCreativeItems(){
|
||||
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.
|
||||
*
|
||||
* @param Item $item
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function addCreativeItem(Item $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.
|
||||
*
|
||||
* @param Item $item
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function removeCreativeItem(Item $item){
|
||||
$index = self::getCreativeItemIndex($item);
|
||||
@ -233,7 +242,7 @@ class Item implements ItemIds, \JsonSerializable{
|
||||
*
|
||||
* @param CompoundTag|string|null $tags
|
||||
*
|
||||
* @return Item
|
||||
* @return $this
|
||||
*/
|
||||
public function setCompoundTag($tags) : Item{
|
||||
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
|
||||
*/
|
||||
public function clearCustomBlockData(){
|
||||
$this->removeNamedTagEntry(self::TAG_BLOCK_ENTITY_TAG);
|
||||
return $this;
|
||||
@ -280,7 +292,7 @@ class Item implements ItemIds, \JsonSerializable{
|
||||
/**
|
||||
* @param CompoundTag $compound
|
||||
*
|
||||
* @return Item
|
||||
* @return $this
|
||||
*/
|
||||
public function setCustomBlockData(CompoundTag $compound) : Item{
|
||||
$tags = clone $compound;
|
||||
@ -479,7 +491,7 @@ class Item implements ItemIds, \JsonSerializable{
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return Item
|
||||
* @return $this
|
||||
*/
|
||||
public function setCustomName(string $name) : Item{
|
||||
if($name === ""){
|
||||
@ -499,7 +511,7 @@ class Item implements ItemIds, \JsonSerializable{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Item
|
||||
* @return $this
|
||||
*/
|
||||
public function clearCustomName() : Item{
|
||||
$display = $this->getNamedTagEntry(self::TAG_DISPLAY);
|
||||
@ -531,7 +543,7 @@ class Item implements ItemIds, \JsonSerializable{
|
||||
/**
|
||||
* @param string[] $lines
|
||||
*
|
||||
* @return Item
|
||||
* @return $this
|
||||
*/
|
||||
public function setLore(array $lines) : Item{
|
||||
$display = $this->getNamedTagEntry(self::TAG_DISPLAY);
|
||||
@ -588,7 +600,7 @@ class Item implements ItemIds, \JsonSerializable{
|
||||
*
|
||||
* @param CompoundTag $tag
|
||||
*
|
||||
* @return Item
|
||||
* @return $this
|
||||
*/
|
||||
public function setNamedTag(CompoundTag $tag) : Item{
|
||||
if($tag->getCount() === 0){
|
||||
@ -603,7 +615,7 @@ class Item implements ItemIds, \JsonSerializable{
|
||||
|
||||
/**
|
||||
* Removes the Item's NBT.
|
||||
* @return Item
|
||||
* @return $this
|
||||
*/
|
||||
public function clearNamedTag() : Item{
|
||||
return $this->setCompoundTag("");
|
||||
@ -619,7 +631,7 @@ class Item implements ItemIds, \JsonSerializable{
|
||||
/**
|
||||
* @param int $count
|
||||
*
|
||||
* @return Item
|
||||
* @return $this
|
||||
*/
|
||||
public function setCount(int $count) : Item{
|
||||
$this->count = $count;
|
||||
@ -632,7 +644,7 @@ class Item implements ItemIds, \JsonSerializable{
|
||||
*
|
||||
* @param int $count
|
||||
*
|
||||
* @return Item
|
||||
* @return $this
|
||||
* @throws \InvalidArgumentException if trying to pop more items than are on the stack
|
||||
*/
|
||||
public function pop(int $count = 1) : Item{
|
||||
@ -700,7 +712,7 @@ class Item implements ItemIds, \JsonSerializable{
|
||||
/**
|
||||
* @param int $meta
|
||||
*
|
||||
* @return Item
|
||||
* @return $this
|
||||
*/
|
||||
public function setDamage(int $meta) : Item{
|
||||
$this->meta = $meta !== -1 ? $meta & 0x7FFF : -1;
|
||||
|
@ -46,6 +46,9 @@ class ItemFactory{
|
||||
/** @var \SplFixedArray */
|
||||
private static $list = null;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public static function init(){
|
||||
self::$list = new \SplFixedArray(65536);
|
||||
|
||||
@ -285,6 +288,7 @@ class ItemFactory{
|
||||
* @param Item $item
|
||||
* @param bool $override
|
||||
*
|
||||
* @return void
|
||||
* @throws \RuntimeException if something attempted to override an already-registered item without specifying the
|
||||
* $override parameter.
|
||||
*/
|
||||
|
@ -105,6 +105,12 @@ class BaseLang{
|
||||
return $this->langName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param string[] $d reference parameter
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected static function loadLang(string $path, array &$d){
|
||||
if(file_exists($path)){
|
||||
$d = array_map('\stripcslashes', parse_ini_file($path, false, INI_SCANNER_RAW));
|
||||
@ -132,6 +138,11 @@ class BaseLang{
|
||||
return $baseText;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TextContainer $c
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function translate(TextContainer $c){
|
||||
if($c instanceof TranslationContainer){
|
||||
$baseText = $this->internalGet($c->getText());
|
||||
|
@ -37,6 +37,8 @@ class TextContainer{
|
||||
|
||||
/**
|
||||
* @param string $text
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setText(string $text){
|
||||
$this->text = $text;
|
||||
|
@ -59,6 +59,8 @@ class TranslationContainer extends TextContainer{
|
||||
/**
|
||||
* @param int $i
|
||||
* @param string $str
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setParameter(int $i, string $str){
|
||||
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
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setParameters(array $params){
|
||||
$i = 0;
|
||||
|
@ -78,6 +78,8 @@ interface ChunkLoader{
|
||||
* This method will be called when a Chunk is replaced by a new one
|
||||
*
|
||||
* @param Chunk $chunk
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function onChunkChanged(Chunk $chunk);
|
||||
|
||||
@ -85,6 +87,8 @@ interface ChunkLoader{
|
||||
* This method will be called when a registered chunk is loaded
|
||||
*
|
||||
* @param Chunk $chunk
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function onChunkLoaded(Chunk $chunk);
|
||||
|
||||
@ -93,6 +97,8 @@ interface ChunkLoader{
|
||||
* This method will be called when a registered chunk is unloaded
|
||||
*
|
||||
* @param Chunk $chunk
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function onChunkUnloaded(Chunk $chunk);
|
||||
|
||||
@ -101,6 +107,8 @@ interface ChunkLoader{
|
||||
* Usually it'll be sent with another call to onChunkChanged()
|
||||
*
|
||||
* @param Chunk $chunk
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function onChunkPopulated(Chunk $chunk);
|
||||
|
||||
@ -108,6 +116,8 @@ interface ChunkLoader{
|
||||
* This method will be called when a block changes in a registered chunk
|
||||
*
|
||||
* @param Block|Vector3 $block
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function onBlockChanged(Vector3 $block);
|
||||
|
||||
|
@ -44,6 +44,8 @@ interface ChunkManager{
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param int $id 0-255
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setBlockIdAt(int $x, int $y, int $z, int $id);
|
||||
|
||||
@ -65,6 +67,8 @@ interface ChunkManager{
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param int $data 0-15
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setBlockDataAt(int $x, int $y, int $z, int $data);
|
||||
|
||||
@ -86,6 +90,8 @@ interface ChunkManager{
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param int $level
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setBlockLightAt(int $x, int $y, int $z, int $level);
|
||||
|
||||
@ -107,6 +113,8 @@ interface ChunkManager{
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param int $level
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setBlockSkyLightAt(int $x, int $y, int $z, int $level);
|
||||
|
||||
@ -122,6 +130,8 @@ interface ChunkManager{
|
||||
* @param int $chunkX
|
||||
* @param int $chunkZ
|
||||
* @param Chunk|null $chunk
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setChunk(int $chunkX, int $chunkZ, Chunk $chunk = null);
|
||||
|
||||
|
@ -120,7 +120,9 @@ use const PHP_INT_MIN;
|
||||
|
||||
class Level implements ChunkManager, Metadatable{
|
||||
|
||||
/** @var int */
|
||||
private static $levelIdCounter = 1;
|
||||
/** @var int */
|
||||
private static $chunkLoaderCounter = 1;
|
||||
|
||||
public const Y_MASK = 0xFF;
|
||||
@ -433,6 +435,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
/**
|
||||
* @deprecated does nothing
|
||||
* @param int $tickRate
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function unregisterGenerator(){
|
||||
$pool = $this->server->getAsyncPool();
|
||||
foreach($pool->getRunningWorkers() as $i){
|
||||
@ -476,6 +483,9 @@ class Level implements ChunkManager, Metadatable{
|
||||
return $this->closed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function close(){
|
||||
if($this->closed){
|
||||
throw new \InvalidStateException("Tried to close a world which is already closed");
|
||||
@ -498,6 +508,12 @@ class Level implements ChunkManager, Metadatable{
|
||||
$this->closed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Sound $sound
|
||||
* @param Player[]|null $players
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addSound(Sound $sound, array $players = null){
|
||||
$pk = $sound->encode();
|
||||
if(!is_array($pk)){
|
||||
@ -514,6 +530,12 @@ class Level implements ChunkManager, Metadatable{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Particle $particle
|
||||
* @param Player[]|null $players
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addParticle(Particle $particle, array $players = null){
|
||||
$pk = $particle->encode();
|
||||
if(!is_array($pk)){
|
||||
@ -536,6 +558,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
* @param Vector3|null $pos If null, broadcasts to every player in the Level
|
||||
* @param int $evid
|
||||
* @param int $data
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function broadcastLevelEvent(?Vector3 $pos, int $evid, int $data = 0){
|
||||
$pk = new LevelEventPacket();
|
||||
@ -559,6 +583,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
* @param int $entityTypeId
|
||||
* @param bool $isBabyMob
|
||||
* @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){
|
||||
$pk = new LevelSoundEventPacket();
|
||||
@ -575,6 +601,11 @@ class Level implements ChunkManager, Metadatable{
|
||||
return $this->autoSave;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setAutoSave(bool $value){
|
||||
$this->autoSave = $value;
|
||||
}
|
||||
@ -672,6 +703,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
* @param int $chunkX
|
||||
* @param int $chunkZ
|
||||
* @param DataPacket $packet
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addChunkPacket(int $chunkX, int $chunkZ, DataPacket $packet){
|
||||
if(!isset($this->chunkPackets[$index = Level::chunkHash($chunkX, $chunkZ)])){
|
||||
@ -710,6 +743,14 @@ class Level implements ChunkManager, Metadatable{
|
||||
$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){
|
||||
$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){
|
||||
$chunkHash = Level::chunkHash($chunkX, $chunkZ);
|
||||
$loaderId = $loader->getLoaderId();
|
||||
@ -762,6 +810,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
* @internal
|
||||
*
|
||||
* @param Player ...$targets If empty, will send to all players in the level.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sendTime(Player ...$targets){
|
||||
$pk = new SetTimePacket();
|
||||
@ -775,6 +825,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
*
|
||||
* @param int $currentTick
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function doTick(int $currentTick){
|
||||
if($this->closed){
|
||||
@ -927,6 +978,9 @@ class Level implements ChunkManager, Metadatable{
|
||||
$this->chunkPackets = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function checkSleep(){
|
||||
if(count($this->players) === 0){
|
||||
return;
|
||||
@ -962,6 +1016,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
* @param Vector3[] $blocks
|
||||
* @param int $flags
|
||||
* @param bool $optimizeRebuilds
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sendBlocks(array $target, array $blocks, int $flags = UpdateBlockPacket::FLAG_NONE, bool $optimizeRebuilds = false){
|
||||
$packets = [];
|
||||
@ -1021,6 +1077,11 @@ class Level implements ChunkManager, Metadatable{
|
||||
$this->server->batchPackets($target, $packets, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $force
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clearCache(bool $force = false){
|
||||
if($force){
|
||||
$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){
|
||||
unset($this->chunkCache[Level::chunkHash($chunkX, $chunkZ)]);
|
||||
}
|
||||
@ -1045,15 +1112,25 @@ class Level implements ChunkManager, Metadatable{
|
||||
return $this->randomTickBlocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addRandomTickedBlock(int $id){
|
||||
$this->randomTickBlocks[$id] = BlockFactory::get($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removeRandomTickedBlock(int $id){
|
||||
$this->randomTickBlocks[$id] = null;
|
||||
}
|
||||
|
||||
private function tickChunks(){
|
||||
private function tickChunks() : void{
|
||||
if($this->chunksPerTick <= 0 or count($this->loaders) === 0){
|
||||
$this->chunkTickList = [];
|
||||
return;
|
||||
@ -1161,6 +1238,9 @@ class Level implements ChunkManager, Metadatable{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function saveChunks(){
|
||||
$this->timings->syncChunkSaveTimer->startTiming();
|
||||
try{
|
||||
@ -1181,6 +1261,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
*
|
||||
* @param Vector3 $pos
|
||||
* @param int $delay
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function scheduleDelayedBlockUpdate(Vector3 $pos, int $delay){
|
||||
if(
|
||||
@ -1198,6 +1280,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
* Blocks will be updated with the normal update type.
|
||||
*
|
||||
* @param Vector3 $pos
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function scheduleNeighbourBlockUpdates(Vector3 $pos){
|
||||
$pos = $pos->floor();
|
||||
@ -1489,6 +1573,11 @@ class Level implements ChunkManager, Metadatable{
|
||||
return $block;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Vector3 $pos
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function updateAllLight(Vector3 $pos){
|
||||
$this->updateBlockSkyLight($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){
|
||||
$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){
|
||||
$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.
|
||||
*
|
||||
* @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 bool $createParticles
|
||||
*
|
||||
@ -2240,6 +2343,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param int $id 0-255
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
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 :(
|
||||
@ -2279,6 +2384,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param int $data 0-15
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
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 :(
|
||||
@ -2319,6 +2426,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param int $level 0-15
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
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);
|
||||
@ -2344,6 +2453,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param int $level 0-15
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
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);
|
||||
@ -2373,6 +2484,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
* @param int $x
|
||||
* @param int $z
|
||||
* @param int $biomeId
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setBiomeId(int $x, int $z, int $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 $z
|
||||
* @param int $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setHeightMap(int $x, int $z, int $value){
|
||||
$this->getChunk($x >> 4, $z >> 4, true)->setHeightMap($x & 0x0f, $z & 0x0f, $value);
|
||||
@ -2459,6 +2574,13 @@ class Level implements ChunkManager, Metadatable{
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $z
|
||||
* @param Chunk|null $chunk
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function generateChunkCallback(int $x, int $z, ?Chunk $chunk){
|
||||
Timings::$generationCallbackTimer->startTiming();
|
||||
if(isset($this->chunkPopulationQueue[$index = Level::chunkHash($x, $z)])){
|
||||
@ -2496,6 +2618,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
* @param int $chunkZ
|
||||
* @param Chunk|null $chunk
|
||||
* @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){
|
||||
if($chunk === null){
|
||||
@ -2621,6 +2745,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
* Sets the level spawn location
|
||||
*
|
||||
* @param Vector3 $pos
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setSpawnLocation(Vector3 $pos){
|
||||
$previousSpawn = $this->getSpawnLocation();
|
||||
@ -2628,6 +2754,13 @@ class Level implements ChunkManager, Metadatable{
|
||||
(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){
|
||||
$index = Level::chunkHash($x, $z);
|
||||
if(!isset($this->chunkSendQueue[$index])){
|
||||
@ -2637,7 +2770,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
$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)])){
|
||||
foreach($this->chunkSendQueue[$index] as $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){
|
||||
$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){
|
||||
$this->timings->syncChunkSendTimer->startTiming();
|
||||
|
||||
@ -2705,6 +2845,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
/**
|
||||
* @param Entity $entity
|
||||
*
|
||||
* @return void
|
||||
* @throws LevelException
|
||||
*/
|
||||
public function addEntity(Entity $entity){
|
||||
@ -2726,6 +2867,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
*
|
||||
* @param Entity $entity
|
||||
*
|
||||
* @return void
|
||||
* @throws LevelException
|
||||
*/
|
||||
public function removeEntity(Entity $entity){
|
||||
@ -2745,6 +2887,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
/**
|
||||
* @param Tile $tile
|
||||
*
|
||||
* @return void
|
||||
* @throws LevelException
|
||||
*/
|
||||
public function addTile(Tile $tile){
|
||||
@ -2771,6 +2914,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
/**
|
||||
* @param Tile $tile
|
||||
*
|
||||
* @return void
|
||||
* @throws LevelException
|
||||
*/
|
||||
public function removeTile(Tile $tile){
|
||||
@ -2866,11 +3010,18 @@ class Level implements ChunkManager, Metadatable{
|
||||
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);
|
||||
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){
|
||||
if(($safe and $this->isChunkInUse($x, $z)) or $this->isSpawnChunk($x, $z)){
|
||||
return false;
|
||||
@ -2881,6 +3032,12 @@ class Level implements ChunkManager, Metadatable{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $z
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function cancelUnloadChunkRequest(int $x, int $z){
|
||||
unset($this->unloadQueue[Level::chunkHash($x, $z)]);
|
||||
}
|
||||
@ -3032,6 +3189,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
* Sets the current time on the level
|
||||
*
|
||||
* @param int $time
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setTime(int $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
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function stopTime(){
|
||||
$this->stopTime = true;
|
||||
@ -3048,6 +3209,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
|
||||
/**
|
||||
* Start the time again, if it was stopped
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function startTime(){
|
||||
$this->stopTime = false;
|
||||
@ -3067,6 +3230,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
* Sets the seed for the level
|
||||
*
|
||||
* @param int $seed
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setSeed(int $seed){
|
||||
$this->provider->setSeed($seed);
|
||||
@ -3085,6 +3250,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
|
||||
/**
|
||||
* @param int $difficulty
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setDifficulty(int $difficulty){
|
||||
if($difficulty < 0 or $difficulty > 3){
|
||||
@ -3097,6 +3264,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
|
||||
/**
|
||||
* @param Player ...$targets
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sendDifficulty(Player ...$targets){
|
||||
if(count($targets) === 0){
|
||||
@ -3145,6 +3314,9 @@ class Level implements ChunkManager, Metadatable{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function doChunkGarbageCollection(){
|
||||
$this->timings->doChunkGC->startTiming();
|
||||
|
||||
@ -3163,6 +3335,11 @@ class Level implements ChunkManager, Metadatable{
|
||||
$this->timings->doChunkGC->stopTiming();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $force
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unloadChunks(bool $force = false){
|
||||
if(count($this->unloadQueue) > 0){
|
||||
$maxUnload = 96;
|
||||
|
@ -67,10 +67,16 @@ class Location extends Position{
|
||||
return new Location($this->x, $this->y, $this->z, $this->yaw, $this->pitch, $this->level);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getYaw(){
|
||||
return $this->yaw;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getPitch(){
|
||||
return $this->pitch;
|
||||
}
|
||||
|
@ -43,6 +43,12 @@ class Position extends Vector3{
|
||||
$this->setLevel($level);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Vector3 $pos
|
||||
* @param Level|null $level
|
||||
*
|
||||
* @return Position
|
||||
*/
|
||||
public static function fromObject(Vector3 $pos, Level $level = null){
|
||||
return new Position($pos->x, $pos->y, $pos->z, $level);
|
||||
}
|
||||
|
@ -32,7 +32,9 @@ class SimpleChunkManager implements ChunkManager{
|
||||
/** @var Chunk[] */
|
||||
protected $chunks = [];
|
||||
|
||||
/** @var int */
|
||||
protected $seed;
|
||||
/** @var int */
|
||||
protected $worldHeight;
|
||||
|
||||
/**
|
||||
@ -69,6 +71,8 @@ class SimpleChunkManager implements ChunkManager{
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param int $id 0-255
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setBlockIdAt(int $x, int $y, int $z, int $id){
|
||||
if($chunk = $this->getChunk($x >> 4, $z >> 4)){
|
||||
@ -99,6 +103,8 @@ class SimpleChunkManager implements ChunkManager{
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param int $data 0-15
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setBlockDataAt(int $x, int $y, int $z, int $data){
|
||||
if($chunk = $this->getChunk($x >> 4, $z >> 4)){
|
||||
@ -148,6 +154,8 @@ class SimpleChunkManager implements ChunkManager{
|
||||
* @param int $chunkX
|
||||
* @param int $chunkZ
|
||||
* @param Chunk|null $chunk
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setChunk(int $chunkX, int $chunkZ, Chunk $chunk = null){
|
||||
if($chunk === null){
|
||||
@ -157,6 +165,9 @@ class SimpleChunkManager implements ChunkManager{
|
||||
$this->chunks[Level::chunkHash($chunkX, $chunkZ)] = $chunk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function cleanChunks(){
|
||||
$this->chunks = [];
|
||||
}
|
||||
|
@ -76,11 +76,20 @@ abstract class Biome{
|
||||
/** @var float */
|
||||
protected $temperature = 0.5;
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @param Biome $biome
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function register(int $id, Biome $biome){
|
||||
self::$biomes[$id] = $biome;
|
||||
$biome->setId($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public static function init(){
|
||||
self::$biomes = new \SplFixedArray(self::MAX_BIOMES);
|
||||
|
||||
@ -113,10 +122,18 @@ abstract class Biome{
|
||||
return self::$biomes[$id];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function clearPopulators(){
|
||||
$this->populators = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Populator $populator
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addPopulator(Populator $populator){
|
||||
$this->populators[] = $populator;
|
||||
}
|
||||
@ -126,6 +143,8 @@ abstract class Biome{
|
||||
* @param int $chunkX
|
||||
* @param int $chunkZ
|
||||
* @param Random $random
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function populateChunk(ChunkManager $level, int $chunkX, int $chunkZ, Random $random){
|
||||
foreach($this->populators as $populator){
|
||||
@ -140,6 +159,11 @@ abstract class Biome{
|
||||
return $this->populators;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setId(int $id){
|
||||
if(!$this->registered){
|
||||
$this->registered = true;
|
||||
@ -161,6 +185,12 @@ abstract class Biome{
|
||||
return $this->maxElevation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $min
|
||||
* @param int $max
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setElevation(int $min, int $max){
|
||||
$this->minElevation = $min;
|
||||
$this->maxElevation = $max;
|
||||
@ -175,6 +205,8 @@ abstract class Biome{
|
||||
|
||||
/**
|
||||
* @param Block[] $covers
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setGroundCover(array $covers){
|
||||
$this->groundCover = $covers;
|
||||
|
@ -32,6 +32,7 @@ class ForestBiome extends GrassyBiome{
|
||||
public const TYPE_NORMAL = 0;
|
||||
public const TYPE_BIRCH = 1;
|
||||
|
||||
/** @var int */
|
||||
public $type;
|
||||
|
||||
public function __construct(int $type = self::TYPE_NORMAL){
|
||||
|
@ -153,12 +153,19 @@ class Chunk{
|
||||
return $this->z;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setX(int $x){
|
||||
$this->x = $x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $z
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setZ(int $z){
|
||||
$this->z = $z;
|
||||
@ -225,6 +232,8 @@ class Chunk{
|
||||
* @param int $y
|
||||
* @param int $z 0-15
|
||||
* @param int $id 0-255
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setBlockId(int $x, int $y, int $z, int $id){
|
||||
if($this->getSubChunk($y >> 4, true)->setBlockId($x, $y & 0x0f, $z, $id)){
|
||||
@ -252,6 +261,8 @@ class Chunk{
|
||||
* @param int $y
|
||||
* @param int $z 0-15
|
||||
* @param int $data 0-15
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setBlockData(int $x, int $y, int $z, int $data){
|
||||
if($this->getSubChunk($y >> 4, true)->setBlockData($x, $y & 0x0f, $z, $data)){
|
||||
@ -279,6 +290,8 @@ class Chunk{
|
||||
* @param int $y
|
||||
* @param int $z 0-15
|
||||
* @param int $level 0-15
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setBlockSkyLight(int $x, int $y, int $z, int $level){
|
||||
if($this->getSubChunk($y >> 4, true)->setBlockSkyLight($x, $y & 0x0f, $z, $level)){
|
||||
@ -288,6 +301,8 @@ class Chunk{
|
||||
|
||||
/**
|
||||
* @param int $level
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setAllBlockSkyLight(int $level){
|
||||
$char = chr(($level & 0x0f) | ($level << 4));
|
||||
@ -317,6 +332,8 @@ class Chunk{
|
||||
* @param int $y 0-15
|
||||
* @param int $z 0-15
|
||||
* @param int $level 0-15
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setBlockLight(int $x, int $y, int $z, int $level){
|
||||
if($this->getSubChunk($y >> 4, true)->setBlockLight($x, $y & 0x0f, $z, $level)){
|
||||
@ -326,6 +343,8 @@ class Chunk{
|
||||
|
||||
/**
|
||||
* @param int $level
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setAllBlockLight(int $level){
|
||||
$char = chr(($level & 0x0f) | ($level << 4));
|
||||
@ -381,6 +400,8 @@ class Chunk{
|
||||
* @param int $x 0-15
|
||||
* @param int $z 0-15
|
||||
* @param int $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setHeightMap(int $x, int $z, int $value){
|
||||
$this->heightMap[($z << 4) | $x] = $value;
|
||||
@ -388,6 +409,8 @@ class Chunk{
|
||||
|
||||
/**
|
||||
* Recalculates the heightmap for the whole chunk.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function recalculateHeightMap(){
|
||||
for($z = 0; $z < 16; ++$z){
|
||||
@ -423,6 +446,8 @@ class Chunk{
|
||||
* if the chunk is light-populated after being terrain-populated.
|
||||
*
|
||||
* TODO: fast adjacent light spread
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function populateSkyLight(){
|
||||
$maxY = $this->getMaxY();
|
||||
@ -469,6 +494,8 @@ class Chunk{
|
||||
* @param int $x 0-15
|
||||
* @param int $z 0-15
|
||||
* @param int $biomeId 0-255
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setBiomeId(int $x, int $z, int $biomeId){
|
||||
$this->hasChanged = true;
|
||||
@ -549,6 +576,8 @@ class Chunk{
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setLightPopulated(bool $value = true){
|
||||
$this->lightPopulated = $value;
|
||||
@ -563,6 +592,8 @@ class Chunk{
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPopulated(bool $value = true){
|
||||
$this->terrainPopulated = $value;
|
||||
@ -577,6 +608,8 @@ class Chunk{
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setGenerated(bool $value = true){
|
||||
$this->terrainGenerated = $value;
|
||||
@ -584,6 +617,8 @@ class Chunk{
|
||||
|
||||
/**
|
||||
* @param Entity $entity
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addEntity(Entity $entity){
|
||||
if($entity->isClosed()){
|
||||
@ -597,6 +632,8 @@ class Chunk{
|
||||
|
||||
/**
|
||||
* @param Entity $entity
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removeEntity(Entity $entity){
|
||||
unset($this->entities[$entity->getId()]);
|
||||
@ -607,6 +644,8 @@ class Chunk{
|
||||
|
||||
/**
|
||||
* @param Tile $tile
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addTile(Tile $tile){
|
||||
if($tile->isClosed()){
|
||||
@ -624,6 +663,8 @@ class Chunk{
|
||||
|
||||
/**
|
||||
* @param Tile $tile
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removeTile(Tile $tile){
|
||||
unset($this->tiles[$tile->getId()]);
|
||||
@ -690,6 +731,8 @@ class Chunk{
|
||||
* Deserializes tiles and entities from NBT
|
||||
*
|
||||
* @param Level $level
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function initChunk(Level $level){
|
||||
if(!$this->isInit){
|
||||
@ -766,6 +809,8 @@ class Chunk{
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setChanged(bool $value = true){
|
||||
$this->hasChanged = $value;
|
||||
|
@ -38,25 +38,28 @@ if(!defined(__NAMESPACE__ . '\ZERO_NIBBLE_ARRAY')){
|
||||
}
|
||||
|
||||
class SubChunk implements SubChunkInterface{
|
||||
/** @var string */
|
||||
protected $ids;
|
||||
/** @var string */
|
||||
protected $data;
|
||||
/** @var string */
|
||||
protected $blockLight;
|
||||
/** @var string */
|
||||
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){
|
||||
assert($data === "", "Invalid non-zero length given, expected $length, got " . strlen($data));
|
||||
$target = str_repeat($value, $length);
|
||||
}else{
|
||||
$target = $data;
|
||||
return str_repeat($value, $length);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function __construct(string $ids = "", string $data = "", string $skyLight = "", string $blockLight = ""){
|
||||
self::assignData($this->ids, $ids, 4096);
|
||||
self::assignData($this->data, $data, 2048);
|
||||
self::assignData($this->skyLight, $skyLight, 2048, "\xff");
|
||||
self::assignData($this->blockLight, $blockLight, 2048);
|
||||
$this->ids = self::assignData($ids, 4096);
|
||||
$this->data = self::assignData($data, 2048);
|
||||
$this->skyLight = self::assignData($skyLight, 2048, "\xff");
|
||||
$this->blockLight = self::assignData($blockLight, 2048);
|
||||
$this->collectGarbage();
|
||||
}
|
||||
|
||||
@ -214,6 +217,9 @@ class SubChunk implements SubChunkInterface{
|
||||
return "\x00" . $this->ids . $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function __debugInfo(){
|
||||
return [];
|
||||
}
|
||||
|
@ -185,6 +185,8 @@ interface SubChunkInterface{
|
||||
|
||||
/**
|
||||
* @param string $data
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setBlockSkyLightArray(string $data);
|
||||
|
||||
@ -195,6 +197,8 @@ interface SubChunkInterface{
|
||||
|
||||
/**
|
||||
* @param string $data
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setBlockLightArray(string $data);
|
||||
|
||||
|
@ -150,6 +150,9 @@ abstract class BaseLevelProvider implements LevelProvider{
|
||||
return $this->levelData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function saveLevelData(){
|
||||
$nbt = new BigEndianNBTStream();
|
||||
$buffer = $nbt->writeCompressed(new CompoundTag("", [
|
||||
|
@ -34,12 +34,17 @@ use function strlen;
|
||||
|
||||
class ChunkRequestTask extends AsyncTask{
|
||||
|
||||
/** @var int */
|
||||
protected $levelId;
|
||||
|
||||
/** @var string */
|
||||
protected $chunk;
|
||||
/** @var int */
|
||||
protected $chunkX;
|
||||
/** @var int */
|
||||
protected $chunkZ;
|
||||
|
||||
/** @var int */
|
||||
protected $compressionLevel;
|
||||
|
||||
/** @var int */
|
||||
|
@ -72,6 +72,8 @@ interface LevelProvider{
|
||||
* @param int $seed
|
||||
* @param string $generator
|
||||
* @param array $options
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function generate(string $path, string $name, int $seed, string $generator, array $options = []);
|
||||
|
||||
@ -119,6 +121,8 @@ interface LevelProvider{
|
||||
|
||||
/**
|
||||
* @param int $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setTime(int $value);
|
||||
|
||||
@ -129,6 +133,8 @@ interface LevelProvider{
|
||||
|
||||
/**
|
||||
* @param int $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setSeed(int $value);
|
||||
|
||||
@ -139,6 +145,8 @@ interface LevelProvider{
|
||||
|
||||
/**
|
||||
* @param Vector3 $pos
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setSpawn(Vector3 $pos);
|
||||
|
||||
@ -152,16 +160,22 @@ interface LevelProvider{
|
||||
* Sets the world difficulty.
|
||||
*
|
||||
* @param int $difficulty
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setDifficulty(int $difficulty);
|
||||
|
||||
/**
|
||||
* Performs garbage collection in the level provider, such as cleaning up regions in Region-based worlds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function doGarbageCollection();
|
||||
|
||||
/**
|
||||
* Performs cleanups necessary when the level provider is closed and no longer needed.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function close();
|
||||
|
||||
|
@ -31,6 +31,7 @@ use function strtolower;
|
||||
use function trim;
|
||||
|
||||
abstract class LevelProviderManager{
|
||||
/** @var string[] */
|
||||
protected static $providers = [];
|
||||
|
||||
public static function init() : void{
|
||||
@ -43,6 +44,7 @@ abstract class LevelProviderManager{
|
||||
/**
|
||||
* @param string $class
|
||||
*
|
||||
* @return void
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public static function addProvider(string $class){
|
||||
|
@ -102,7 +102,7 @@ class LevelDB extends BaseLevelProvider{
|
||||
/** @var \LevelDB */
|
||||
protected $db;
|
||||
|
||||
private static function checkForLevelDBExtension(){
|
||||
private static function checkForLevelDBExtension() : void{
|
||||
if(!extension_loaded('leveldb')){
|
||||
throw new LevelException("The leveldb PHP extension is required to use this world format");
|
||||
}
|
||||
@ -126,8 +126,12 @@ class LevelDB extends BaseLevelProvider{
|
||||
}
|
||||
|
||||
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();
|
||||
$levelData = $nbt->read(substr(file_get_contents($this->getPath() . "level.dat"), 8));
|
||||
$levelData = $nbt->read(substr($rawLevelData, 8));
|
||||
if($levelData instanceof CompoundTag){
|
||||
$this->levelData = $levelData;
|
||||
}else{
|
||||
@ -519,7 +523,7 @@ class LevelDB extends BaseLevelProvider{
|
||||
* @param CompoundTag[] $targets
|
||||
* @param string $index
|
||||
*/
|
||||
private function writeTags(array $targets, string $index){
|
||||
private function writeTags(array $targets, string $index) : void{
|
||||
if(count($targets) > 0){
|
||||
$nbt = new LittleEndianNBTStream();
|
||||
$this->db->put($index, $nbt->write($targets));
|
||||
|
@ -331,8 +331,10 @@ class McRegion extends BaseLevelProvider{
|
||||
/**
|
||||
* @param int $chunkX
|
||||
* @param int $chunkZ
|
||||
* @param int &$regionX
|
||||
* @param int &$regionZ
|
||||
* @param int $regionX reference parameter
|
||||
* @param int $regionZ reference parameter
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function getRegionIndex(int $chunkX, int $chunkZ, &$regionX, &$regionZ){
|
||||
$regionX = $chunkX >> 5;
|
||||
@ -364,6 +366,8 @@ class McRegion extends BaseLevelProvider{
|
||||
/**
|
||||
* @param int $regionX
|
||||
* @param int $regionZ
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function loadRegion(int $regionX, int $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
|
||||
|
||||
/** @var int */
|
||||
public static $COMPRESSION_LEVEL = 7;
|
||||
|
||||
/** @var int */
|
||||
@ -86,6 +87,7 @@ class RegionLoader{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
* @throws CorruptedRegionException
|
||||
*/
|
||||
public function open(){
|
||||
@ -187,6 +189,7 @@ class RegionLoader{
|
||||
* @param int $z
|
||||
* @param string $chunkData
|
||||
*
|
||||
* @return void
|
||||
* @throws ChunkException
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
@ -219,6 +222,7 @@ class RegionLoader{
|
||||
* @param int $x
|
||||
* @param int $z
|
||||
*
|
||||
* @return void
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function removeChunk(int $x, int $z){
|
||||
@ -243,8 +247,8 @@ class RegionLoader{
|
||||
|
||||
/**
|
||||
* @param int $offset
|
||||
* @param int &$x
|
||||
* @param int &$z
|
||||
* @param int $x reference parameter
|
||||
* @param int $z reference parameter
|
||||
*/
|
||||
protected static function getChunkCoords(int $offset, ?int &$x, ?int &$z) : void{
|
||||
$x = $offset & 0x1f;
|
||||
@ -255,6 +259,8 @@ class RegionLoader{
|
||||
* Writes the region header and closes the file
|
||||
*
|
||||
* @param bool $writeHeader
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function close(bool $writeHeader = true){
|
||||
if(is_resource($this->filePointer)){
|
||||
@ -267,6 +273,7 @@ class RegionLoader{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
* @throws CorruptedRegionException
|
||||
*/
|
||||
protected function loadLocationTable(){
|
||||
@ -328,7 +335,7 @@ class RegionLoader{
|
||||
}
|
||||
}
|
||||
|
||||
private function writeLocationTable(){
|
||||
private function writeLocationTable() : void{
|
||||
$write = [];
|
||||
|
||||
for($i = 0; $i < 1024; ++$i){
|
||||
@ -341,6 +348,11 @@ class RegionLoader{
|
||||
fwrite($this->filePointer, pack("N*", ...$write), 4096 * 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $index
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function writeLocationIndex($index){
|
||||
fseek($this->filePointer, $index << 2);
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function createBlank(){
|
||||
fseek($this->filePointer, 0);
|
||||
ftruncate($this->filePointer, 8192); // this fills the file with the null byte
|
||||
|
@ -34,10 +34,15 @@ use function unserialize;
|
||||
|
||||
class GeneratorRegisterTask extends AsyncTask{
|
||||
|
||||
/** @var string */
|
||||
public $generatorClass;
|
||||
/** @var string */
|
||||
public $settings;
|
||||
/** @var int */
|
||||
public $seed;
|
||||
/** @var int */
|
||||
public $levelId;
|
||||
/** @var int */
|
||||
public $worldHeight = Level::Y_MAX;
|
||||
|
||||
public function __construct(Level $level, string $generatorClass, array $generatorSettings = []){
|
||||
|
@ -28,6 +28,7 @@ use pocketmine\scheduler\AsyncTask;
|
||||
|
||||
class GeneratorUnregisterTask extends AsyncTask{
|
||||
|
||||
/** @var int */
|
||||
public $levelId;
|
||||
|
||||
public function __construct(Level $level){
|
||||
|
@ -31,18 +31,31 @@ use pocketmine\Server;
|
||||
|
||||
class PopulationTask extends AsyncTask{
|
||||
|
||||
/** @var bool */
|
||||
public $state;
|
||||
/** @var int */
|
||||
public $levelId;
|
||||
/** @var string */
|
||||
public $chunk;
|
||||
|
||||
/** @var string */
|
||||
public $chunk0;
|
||||
/** @var string */
|
||||
public $chunk1;
|
||||
/** @var string */
|
||||
public $chunk2;
|
||||
/** @var string */
|
||||
public $chunk3;
|
||||
|
||||
//center chunk
|
||||
|
||||
/** @var string */
|
||||
public $chunk5;
|
||||
/** @var string */
|
||||
public $chunk6;
|
||||
/** @var string */
|
||||
public $chunk7;
|
||||
/** @var string */
|
||||
public $chunk8;
|
||||
|
||||
public function __construct(Level $level, Chunk $chunk){
|
||||
|
@ -52,6 +52,9 @@ abstract class BiomeSelector{
|
||||
*/
|
||||
abstract protected function lookup(float $temperature, float $rainfall) : int;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function recalculate(){
|
||||
$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){
|
||||
return ($this->temperature->noise2D($x, $z, true) + 1) / 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $x
|
||||
* @param float $z
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getRainfall($x, $z){
|
||||
return ($this->rainfall->noise2D($x, $z, true) + 1) / 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: not sure on types here
|
||||
* @param int|float $x
|
||||
* @param int|float $z
|
||||
* @param int $x
|
||||
* @param int $z
|
||||
*
|
||||
* @return Biome
|
||||
*/
|
||||
|
@ -31,30 +31,77 @@ use function array_fill;
|
||||
use function assert;
|
||||
|
||||
abstract class Noise{
|
||||
/** @var int[] */
|
||||
protected $perm = [];
|
||||
/** @var float */
|
||||
protected $offsetX = 0;
|
||||
/** @var float */
|
||||
protected $offsetY = 0;
|
||||
/** @var float */
|
||||
protected $offsetZ = 0;
|
||||
/** @var int */
|
||||
protected $octaves = 8;
|
||||
/** @var float */
|
||||
protected $persistence;
|
||||
/** @var float */
|
||||
protected $expansion;
|
||||
|
||||
/**
|
||||
* @param float $x
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function floor($x) : int{
|
||||
return $x >= 0 ? (int) $x : (int) ($x - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $x
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function fade($x){
|
||||
return $x * $x * $x * ($x * ($x * 6 - 15) + 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $x
|
||||
* @param float $y
|
||||
* @param float $z
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function lerp($x, $y, $z){
|
||||
return $y + $x * ($z - $y);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $x
|
||||
* @param float $x1
|
||||
* @param float $x2
|
||||
* @param float $q0
|
||||
* @param float $q1
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function linearLerp($x, $x1, $x2, $q0, $q1){
|
||||
return (($x2 - $x) / ($x2 - $x1)) * $q0 + (($x - $x1) / ($x2 - $x1)) * $q1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $x
|
||||
* @param float $y
|
||||
* @param float $q00
|
||||
* @param float $q01
|
||||
* @param float $q10
|
||||
* @param float $q11
|
||||
* @param float $x1
|
||||
* @param float $x2
|
||||
* @param float $y1
|
||||
* @param float $y2
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function bilinearLerp($x, $y, $q00, $q01, $q10, $q11, $x1, $x2, $y1, $y2){
|
||||
$dx1 = (($x2 - $x) / ($x2 - $x1));
|
||||
$dx2 = (($x - $x1) / ($x2 - $x1));
|
||||
@ -66,6 +113,27 @@ abstract class Noise{
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $x
|
||||
* @param float $y
|
||||
* @param float $z
|
||||
* @param float $q000
|
||||
* @param float $q001
|
||||
* @param float $q010
|
||||
* @param float $q011
|
||||
* @param float $q100
|
||||
* @param float $q101
|
||||
* @param float $q110
|
||||
* @param float $q111
|
||||
* @param float $x1
|
||||
* @param float $x2
|
||||
* @param float $y1
|
||||
* @param float $y2
|
||||
* @param float $z1
|
||||
* @param float $z2
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function trilinearLerp($x, $y, $z, $q000, $q001, $q010, $q011, $q100, $q101, $q110, $q111, $x1, $x2, $y1, $y2, $z1, $z2){
|
||||
$dx1 = (($x2 - $x) / ($x2 - $x1));
|
||||
$dx2 = (($x - $x1) / ($x2 - $x1));
|
||||
@ -87,6 +155,14 @@ abstract class Noise{
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $hash
|
||||
* @param float $x
|
||||
* @param float $y
|
||||
* @param float $z
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function grad($hash, $x, $y, $z){
|
||||
$hash &= 15;
|
||||
$u = $hash < 8 ? $x : $y;
|
||||
@ -95,10 +171,30 @@ abstract class Noise{
|
||||
return (($hash & 1) === 0 ? $u : -$u) + (($hash & 2) === 0 ? $v : -$v);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $x
|
||||
* @param float $z
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
abstract public function getNoise2D($x, $z);
|
||||
|
||||
/**
|
||||
* @param float $x
|
||||
* @param float $y
|
||||
* @param float $z
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
abstract public function getNoise3D($x, $y, $z);
|
||||
|
||||
/**
|
||||
* @param float $x
|
||||
* @param float $z
|
||||
* @param bool $normalized
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function noise2D($x, $z, $normalized = false){
|
||||
$result = 0;
|
||||
$amp = 1;
|
||||
@ -122,6 +218,14 @@ abstract class Noise{
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $x
|
||||
* @param float $y
|
||||
* @param float $z
|
||||
* @param bool $normalized
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function noise3D($x, $y, $z, $normalized = false){
|
||||
$result = 0;
|
||||
$amp = 1;
|
||||
@ -297,6 +401,13 @@ abstract class Noise{
|
||||
return $noiseArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $x
|
||||
* @param float $y
|
||||
* @param float $z
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setOffset($x, $y, $z){
|
||||
$this->offsetX = $x;
|
||||
$this->offsetY = $y;
|
||||
|
@ -26,6 +26,7 @@ namespace pocketmine\level\generator\noise;
|
||||
use pocketmine\utils\Random;
|
||||
|
||||
class Perlin extends Noise{
|
||||
/** @var int[][] */
|
||||
public static $grad3 = [
|
||||
[1, 1, 0], [-1, 1, 0], [1, -1, 0], [-1, -1, 0],
|
||||
[1, 0, 1], [-1, 0, 1], [1, 0, -1], [-1, 0, -1],
|
||||
@ -33,6 +34,12 @@ class Perlin extends Noise{
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* @param Random $random
|
||||
* @param int $octaves
|
||||
* @param float $persistence
|
||||
* @param float $expansion
|
||||
*/
|
||||
public function __construct(Random $random, $octaves, $persistence, $expansion = 1){
|
||||
$this->octaves = $octaves;
|
||||
$this->persistence = $persistence;
|
||||
@ -144,6 +151,12 @@ class Perlin extends Noise{
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $x
|
||||
* @param float $y
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getNoise2D($x, $y){
|
||||
return $this->getNoise3D($x, $y, 0);
|
||||
}
|
||||
|
@ -34,18 +34,31 @@ use function sqrt;
|
||||
* http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
|
||||
*/
|
||||
class Simplex extends Perlin{
|
||||
/** @var float */
|
||||
protected static $SQRT_3;
|
||||
/** @var float */
|
||||
protected static $SQRT_5;
|
||||
/** @var float */
|
||||
protected static $F2;
|
||||
/** @var float */
|
||||
protected static $G2;
|
||||
/** @var float */
|
||||
protected static $G22;
|
||||
/** @var float */
|
||||
protected static $F3;
|
||||
/** @var float */
|
||||
protected static $G3;
|
||||
/** @var float */
|
||||
protected static $F4;
|
||||
/** @var float */
|
||||
protected static $G4;
|
||||
/** @var float */
|
||||
protected static $G42;
|
||||
/** @var float */
|
||||
protected static $G43;
|
||||
/** @var float */
|
||||
protected static $G44;
|
||||
/** @var int[][] */
|
||||
protected static $grad4 = [[0, 1, 1, 1], [0, 1, 1, -1], [0, 1, -1, 1], [0, 1, -1, -1],
|
||||
[0, -1, 1, 1], [0, -1, 1, -1], [0, -1, -1, 1], [0, -1, -1, -1],
|
||||
[1, 0, 1, 1], [1, 0, 1, -1], [1, 0, -1, 1], [1, 0, -1, -1],
|
||||
@ -54,6 +67,8 @@ class Simplex extends Perlin{
|
||||
[-1, 1, 0, 1], [-1, 1, 0, -1], [-1, -1, 0, 1], [-1, -1, 0, -1],
|
||||
[1, 1, 1, 0], [1, 1, -1, 0], [1, -1, 1, 0], [1, -1, -1, 0],
|
||||
[-1, 1, 1, 0], [-1, 1, -1, 0], [-1, -1, 1, 0], [-1, -1, -1, 0]];
|
||||
|
||||
/** @var int[][] */
|
||||
protected static $simplex = [
|
||||
[0, 1, 2, 3], [0, 1, 3, 2], [0, 0, 0, 0], [0, 2, 3, 1], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [1, 2, 3, 0],
|
||||
[0, 2, 1, 3], [0, 0, 0, 0], [0, 3, 1, 2], [0, 3, 2, 1], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [1, 3, 2, 0],
|
||||
@ -63,9 +78,17 @@ class Simplex extends Perlin{
|
||||
[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0],
|
||||
[2, 0, 1, 3], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [3, 0, 1, 2], [3, 0, 2, 1], [0, 0, 0, 0], [3, 1, 2, 0],
|
||||
[2, 1, 0, 3], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [3, 1, 0, 2], [0, 0, 0, 0], [3, 2, 0, 1], [3, 2, 1, 0]];
|
||||
|
||||
/** @var float */
|
||||
protected $offsetW;
|
||||
|
||||
|
||||
/**
|
||||
* @param Random $random
|
||||
* @param int $octaves
|
||||
* @param float $persistence
|
||||
* @param float $expansion
|
||||
*/
|
||||
public function __construct(Random $random, $octaves, $persistence, $expansion = 1){
|
||||
parent::__construct($random, $octaves, $persistence, $expansion);
|
||||
$this->offsetW = $random->nextFloat() * 256;
|
||||
@ -83,14 +106,38 @@ class Simplex extends Perlin{
|
||||
self::$G44 = self::$G4 * 4.0 - 1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $g
|
||||
* @param float $x
|
||||
* @param float $y
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
protected static function dot2D($g, $x, $y){
|
||||
return $g[0] * $x + $g[1] * $y;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $g
|
||||
* @param float $x
|
||||
* @param float $y
|
||||
* @param float $z
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
protected static function dot3D($g, $x, $y, $z){
|
||||
return $g[0] * $x + $g[1] * $y + $g[2] * $z;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $g
|
||||
* @param float $x
|
||||
* @param float $y
|
||||
* @param float $z
|
||||
* @param float $w
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
protected static function dot4D($g, $x, $y, $z, $w){
|
||||
return $g[0] * $x + $g[1] * $y + $g[2] * $z + $g[3] * $w;
|
||||
}
|
||||
@ -219,6 +266,12 @@ class Simplex extends Perlin{
|
||||
return 32.0 * $n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $x
|
||||
* @param float $y
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getNoise2D($x, $y){
|
||||
$x += $this->offsetX;
|
||||
$y += $this->offsetY;
|
||||
|
@ -55,7 +55,9 @@ class Normal extends Generator{
|
||||
/** @var BiomeSelector */
|
||||
private $selector;
|
||||
|
||||
/** @var float[][]|null */
|
||||
private static $GAUSSIAN_KERNEL = null;
|
||||
/** @var int */
|
||||
private static $SMOOTH_SIZE = 2;
|
||||
|
||||
/**
|
||||
|
@ -26,60 +26,25 @@ namespace pocketmine\level\generator\object;
|
||||
use pocketmine\level\ChunkManager;
|
||||
use pocketmine\utils\Random;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
class BigTree extends Tree{
|
||||
private $trunkHeightMultiplier = 0.618;
|
||||
private $trunkHeight;
|
||||
private $leafAmount = 1;
|
||||
private $leafDistanceLimit = 5;
|
||||
private $widthScale = 1;
|
||||
private $branchSlope = 0.381;
|
||||
|
||||
private $totalHeight = 6;
|
||||
private $leavesHeight = 3;
|
||||
protected $radiusIncrease = 0;
|
||||
private $addLeavesVines = false;
|
||||
private $addLogVines = false;
|
||||
private $addCocoaPlants = false;
|
||||
|
||||
public function canPlaceObject(ChunkManager $level, int $x, int $y, int $z, Random $random) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ChunkManager $level
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param Random $random
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function placeObject(ChunkManager $level, int $x, int $y, int $z, Random $random){
|
||||
|
||||
/*$this->trunkHeight = (int) ($this->totalHeight * $this->trunkHeightMultiplier);
|
||||
$leaves = $this->getLeafGroupPoints($level, $pos);
|
||||
foreach($leaves as $leafGroup){
|
||||
$groupX = $leafGroup->getBlockX();
|
||||
$groupY = $leafGroup->getBlockY();
|
||||
$groupZ = $leafGroup->getBlockZ();
|
||||
for($yy = $groupY; $yy < $groupY + $this->leafDistanceLimit; ++$yy){
|
||||
$this->generateGroupLayer($level, $groupX, $yy, $groupZ, $this->getLeafGroupLayerSize($yy - $groupY));
|
||||
}
|
||||
}
|
||||
final BlockIterator trunk = new BlockIterator(new Point(w, x, y - 1, z), new Point(w, x, y + trunkHeight, z));
|
||||
while (trunk.hasNext()) {
|
||||
trunk.next().setMaterial(VanillaMaterials.LOG, logMetadata);
|
||||
}
|
||||
generateBranches(w, x, y, z, leaves);
|
||||
|
||||
$level->setBlock($x, $pos->y - 1, $z, 3, 0);
|
||||
$this->totalHeight += $random->nextRange(0, 2);
|
||||
$this->leavesHeight += mt_rand(0, 1);
|
||||
for($yy = ($this->totalHeight - $this->leavesHeight); $yy < ($this->totalHeight + 1); ++$yy){
|
||||
$yRadius = ($yy - $this->totalHeight);
|
||||
$xzRadius = (int) (($this->radiusIncrease + 1) - $yRadius / 2);
|
||||
for($xx = -$xzRadius; $xx < ($xzRadius + 1); ++$xx){
|
||||
for($zz = -$xzRadius; $zz < ($xzRadius + 1); ++$zz){
|
||||
if((abs($xx) != $xzRadius or abs($zz) != $xzRadius) and $yRadius != 0){
|
||||
$level->setBlock($pos->x + $xx, $pos->y + $yy, $pos->z + $zz, 18, $this->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for($yy = 0; $yy < ($this->totalHeight - 1); ++$yy){
|
||||
$level->setBlock($x, $pos->y + $yy, $z, 17, $this->type);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ use pocketmine\utils\Random;
|
||||
|
||||
class BirchTree extends Tree{
|
||||
|
||||
/** @var bool */
|
||||
protected $superBirch = false;
|
||||
|
||||
public function __construct(bool $superBirch = false){
|
||||
@ -39,6 +40,15 @@ class BirchTree extends Tree{
|
||||
$this->superBirch = $superBirch;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ChunkManager $level
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param Random $random
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function placeObject(ChunkManager $level, int $x, int $y, int $z, Random $random){
|
||||
$this->treeHeight = $random->nextBoundedInt(3) + 5;
|
||||
if($this->superBirch){
|
||||
|
@ -36,6 +36,15 @@ class OakTree extends Tree{
|
||||
$this->type = Wood::OAK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ChunkManager $level
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param Random $random
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function placeObject(ChunkManager $level, int $x, int $y, int $z, Random $random){
|
||||
$this->treeHeight = $random->nextBoundedInt(3) + 4;
|
||||
parent::placeObject($level, $x, $y, $z, $random);
|
||||
|
@ -49,6 +49,14 @@ class Ore{
|
||||
return $level->getBlockIdAt($x, $y, $z) === Block::STONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ChunkManager $level
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function placeObject(ChunkManager $level, int $x, int $y, int $z){
|
||||
$clusterSize = $this->type->clusterSize;
|
||||
$angle = $this->random->nextFloat() * M_PI;
|
||||
|
@ -29,7 +29,9 @@ use pocketmine\math\Vector3;
|
||||
use pocketmine\utils\Random;
|
||||
|
||||
class Pond{
|
||||
/** @var Random */
|
||||
private $random;
|
||||
/** @var Block */
|
||||
public $type;
|
||||
|
||||
public function __construct(Random $random, Block $type){
|
||||
@ -41,6 +43,12 @@ class Pond{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ChunkManager $level
|
||||
* @param Vector3 $pos
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function placeObject(ChunkManager $level, Vector3 $pos){
|
||||
|
||||
}
|
||||
|
@ -39,6 +39,15 @@ class SpruceTree extends Tree{
|
||||
$this->treeHeight = 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ChunkManager $level
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param Random $random
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function placeObject(ChunkManager $level, int $x, int $y, int $z, Random $random){
|
||||
$this->treeHeight = $random->nextBoundedInt(4) + 6;
|
||||
|
||||
|
@ -31,6 +31,15 @@ use function count;
|
||||
|
||||
class TallGrass{
|
||||
|
||||
/**
|
||||
* @param ChunkManager $level
|
||||
* @param Vector3 $pos
|
||||
* @param Random $random
|
||||
* @param int $count
|
||||
* @param int $radius
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function growGrass(ChunkManager $level, Vector3 $pos, Random $random, int $count = 15, int $radius = 10){
|
||||
$arr = [
|
||||
[Block::DANDELION, 0],
|
||||
|
@ -31,6 +31,7 @@ use pocketmine\utils\Random;
|
||||
use function abs;
|
||||
|
||||
abstract class Tree{
|
||||
/** @var bool[] */
|
||||
public $overridable = [
|
||||
Block::AIR => true,
|
||||
Block::SAPLING => true,
|
||||
@ -39,11 +40,25 @@ abstract class Tree{
|
||||
Block::LEAVES2 => true
|
||||
];
|
||||
|
||||
/** @var int */
|
||||
public $type = 0;
|
||||
/** @var int */
|
||||
public $trunkBlock = Block::LOG;
|
||||
/** @var int */
|
||||
public $leafBlock = Block::LEAVES;
|
||||
/** @var int */
|
||||
public $treeHeight = 7;
|
||||
|
||||
/**
|
||||
* @param ChunkManager $level
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param Random $random
|
||||
* @param int $type
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function growTree(ChunkManager $level, int $x, int $y, int $z, Random $random, int $type = 0){
|
||||
switch($type){
|
||||
case Sapling::SPRUCE:
|
||||
@ -95,6 +110,15 @@ abstract class Tree{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ChunkManager $level
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param Random $random
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function placeObject(ChunkManager $level, int $x, int $y, int $z, Random $random){
|
||||
|
||||
$this->placeTrunk($level, $x, $y, $z, $random, $this->treeHeight - 1);
|
||||
@ -118,6 +142,16 @@ abstract class Tree{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ChunkManager $level
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param Random $random
|
||||
* @param int $trunkHeight
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function placeTrunk(ChunkManager $level, int $x, int $y, int $z, Random $random, int $trunkHeight){
|
||||
// The base dirt block
|
||||
$level->setBlockIdAt($x, $y - 1, $z, Block::DIRT);
|
||||
|
@ -48,6 +48,8 @@ class Ore extends Populator{
|
||||
|
||||
/**
|
||||
* @param OreType[] $types
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setOreTypes(array $types){
|
||||
$this->oreTypes = $types;
|
||||
|
@ -30,8 +30,11 @@ use pocketmine\math\Vector3;
|
||||
use pocketmine\utils\Random;
|
||||
|
||||
class Pond extends Populator{
|
||||
/** @var int */
|
||||
private $waterOdd = 4;
|
||||
/** @var int */
|
||||
private $lavaOdd = 4;
|
||||
/** @var int */
|
||||
private $lavaSurfaceOdd = 4;
|
||||
|
||||
public function populate(ChunkManager $level, int $chunkX, int $chunkZ, Random $random){
|
||||
@ -46,14 +49,29 @@ class Pond extends Populator{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $waterOdd
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setWaterOdd(int $waterOdd){
|
||||
$this->waterOdd = $waterOdd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $lavaOdd
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setLavaOdd(int $lavaOdd){
|
||||
$this->lavaOdd = $lavaOdd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $lavaSurfaceOdd
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setLavaSurfaceOdd(int $lavaSurfaceOdd){
|
||||
$this->lavaSurfaceOdd = $lavaSurfaceOdd;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user