mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-06 09:56:06 +00:00
Merge branch 'stable' into next-minor
This commit is contained in:
@ -42,15 +42,11 @@ interface ChunkLoader{
|
||||
/**
|
||||
* Returns the ChunkLoader id.
|
||||
* Call Level::generateChunkLoaderId($this) to generate and save it
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getLoaderId() : int;
|
||||
|
||||
/**
|
||||
* Returns if the chunk loader is currently active
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isLoaderActive() : bool;
|
||||
|
||||
@ -77,22 +73,21 @@ 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);
|
||||
|
||||
/**
|
||||
* This method will be called when a registered chunk is loaded
|
||||
*
|
||||
* @param Chunk $chunk
|
||||
* @return void
|
||||
*/
|
||||
public function onChunkLoaded(Chunk $chunk);
|
||||
|
||||
|
||||
/**
|
||||
* This method will be called when a registered chunk is unloaded
|
||||
*
|
||||
* @param Chunk $chunk
|
||||
* @return void
|
||||
*/
|
||||
public function onChunkUnloaded(Chunk $chunk);
|
||||
|
||||
@ -100,7 +95,7 @@ interface ChunkLoader{
|
||||
* This method will be called when a registered chunk is populated
|
||||
* Usually it'll be sent with another call to onChunkChanged()
|
||||
*
|
||||
* @param Chunk $chunk
|
||||
* @return void
|
||||
*/
|
||||
public function onChunkPopulated(Chunk $chunk);
|
||||
|
||||
@ -108,6 +103,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);
|
||||
|
||||
|
@ -29,10 +29,6 @@ interface ChunkManager{
|
||||
/**
|
||||
* Gets the raw block id.
|
||||
*
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
*
|
||||
* @return int 0-255
|
||||
*/
|
||||
public function getBlockIdAt(int $x, int $y, int $z) : int;
|
||||
@ -40,20 +36,15 @@ interface ChunkManager{
|
||||
/**
|
||||
* Sets the raw block id.
|
||||
*
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param int $id 0-255
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setBlockIdAt(int $x, int $y, int $z, int $id);
|
||||
|
||||
/**
|
||||
* Gets the raw block metadata
|
||||
*
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
*
|
||||
* @return int 0-15
|
||||
*/
|
||||
public function getBlockDataAt(int $x, int $y, int $z) : int;
|
||||
@ -61,92 +52,59 @@ interface ChunkManager{
|
||||
/**
|
||||
* Sets the raw block metadata.
|
||||
*
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param int $data 0-15
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setBlockDataAt(int $x, int $y, int $z, int $data);
|
||||
|
||||
/**
|
||||
* Returns the raw block light level
|
||||
*
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getBlockLightAt(int $x, int $y, int $z) : int;
|
||||
|
||||
/**
|
||||
* Sets the raw block light level
|
||||
*
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param int $level
|
||||
* @return void
|
||||
*/
|
||||
public function setBlockLightAt(int $x, int $y, int $z, int $level);
|
||||
|
||||
/**
|
||||
* Returns the highest amount of sky light can reach the specified coordinates.
|
||||
*
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getBlockSkyLightAt(int $x, int $y, int $z) : int;
|
||||
|
||||
/**
|
||||
* Sets the raw block sky light level.
|
||||
*
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param int $level
|
||||
* @return void
|
||||
*/
|
||||
public function setBlockSkyLightAt(int $x, int $y, int $z, int $level);
|
||||
|
||||
/**
|
||||
* @param int $chunkX
|
||||
* @param int $chunkZ
|
||||
*
|
||||
* @return Chunk|null
|
||||
*/
|
||||
public function getChunk(int $chunkX, int $chunkZ);
|
||||
|
||||
/**
|
||||
* @param int $chunkX
|
||||
* @param int $chunkZ
|
||||
* @param Chunk|null $chunk
|
||||
* @return void
|
||||
*/
|
||||
public function setChunk(int $chunkX, int $chunkZ, Chunk $chunk = null);
|
||||
|
||||
/**
|
||||
* Gets the level seed
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getSeed() : int;
|
||||
|
||||
/**
|
||||
* Returns the height of the world
|
||||
* @return int
|
||||
*/
|
||||
public function getWorldHeight() : int;
|
||||
|
||||
/**
|
||||
* Returns whether the specified coordinates are within the valid world boundaries, taking world format limitations
|
||||
* into account.
|
||||
*
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isInWorld(int $x, int $y, int $z) : bool;
|
||||
}
|
||||
|
@ -60,16 +60,14 @@ class Explosion{
|
||||
public $affectedBlocks = [];
|
||||
/** @var float */
|
||||
public $stepLen = 0.3;
|
||||
/** @var Entity|Block */
|
||||
/** @var Entity|Block|null */
|
||||
private $what;
|
||||
|
||||
/** @var SubChunkIteratorManager */
|
||||
private $subChunkHandler;
|
||||
|
||||
/**
|
||||
* @param Position $center
|
||||
* @param float $size
|
||||
* @param Entity|Block $what
|
||||
* @param Entity|Block|null $what
|
||||
*/
|
||||
public function __construct(Position $center, float $size, $what = null){
|
||||
if(!$center->isValid()){
|
||||
@ -88,10 +86,8 @@ class Explosion{
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates which blocks will be destroyed by this explosion. If explodeB() is called without calling this, no blocks
|
||||
* Calculates which blocks will be destroyed by this explosion. If explodeB() is called without calling this, no blocks
|
||||
* will be destroyed.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function explodeA() : bool{
|
||||
if($this->size < 0.1){
|
||||
@ -104,7 +100,7 @@ class Explosion{
|
||||
$currentChunk = null;
|
||||
$currentSubChunk = null;
|
||||
|
||||
$mRays = (int) ($this->rays - 1);
|
||||
$mRays = $this->rays - 1;
|
||||
for($i = 0; $i < $this->rays; ++$i){
|
||||
for($j = 0; $j < $this->rays; ++$j){
|
||||
for($k = 0; $k < $this->rays; ++$k){
|
||||
@ -123,6 +119,10 @@ class Explosion{
|
||||
$vBlock->y = $pointerY >= $y ? $y : $y - 1;
|
||||
$vBlock->z = $pointerZ >= $z ? $z : $z - 1;
|
||||
|
||||
$pointerX += $vector->x;
|
||||
$pointerY += $vector->y;
|
||||
$pointerZ += $vector->z;
|
||||
|
||||
if(!$this->subChunkHandler->moveTo($vBlock->x, $vBlock->y, $vBlock->z)){
|
||||
continue;
|
||||
}
|
||||
@ -137,10 +137,6 @@ class Explosion{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$pointerX += $vector->x;
|
||||
$pointerY += $vector->y;
|
||||
$pointerZ += $vector->z;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -153,8 +149,6 @@ class Explosion{
|
||||
/**
|
||||
* Executes the explosion's effects on the world. This includes destroying blocks (if any), harming and knocking back entities,
|
||||
* and creating sounds and particles.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function explodeB() : bool{
|
||||
$send = [];
|
||||
@ -208,7 +202,6 @@ class Explosion{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$air = ItemFactory::get(Item::AIR);
|
||||
|
||||
foreach($this->affectedBlocks as $block){
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -38,7 +38,6 @@ class Location extends Position{
|
||||
* @param float|int $z
|
||||
* @param float $yaw
|
||||
* @param float $pitch
|
||||
* @param Level $level
|
||||
*/
|
||||
public function __construct($x = 0, $y = 0, $z = 0, $yaw = 0.0, $pitch = 0.0, Level $level = null){
|
||||
$this->yaw = $yaw;
|
||||
@ -47,12 +46,8 @@ class Location extends Position{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Vector3 $pos
|
||||
* @param Level|null $level default null
|
||||
* @param float $yaw default 0.0
|
||||
* @param float $pitch default 0.0
|
||||
*
|
||||
* @return Location
|
||||
*/
|
||||
public static function fromObject(Vector3 $pos, Level $level = null, $yaw = 0.0, $pitch = 0.0) : Location{
|
||||
return new Location($pos->x, $pos->y, $pos->z, $yaw, $pitch, $level ?? (($pos instanceof Position) ? $pos->level : null));
|
||||
@ -60,17 +55,21 @@ class Location extends Position{
|
||||
|
||||
/**
|
||||
* Return a Location instance
|
||||
*
|
||||
* @return Location
|
||||
*/
|
||||
public function asLocation() : Location{
|
||||
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;
|
||||
}
|
||||
|
@ -36,21 +36,21 @@ class Position extends Vector3{
|
||||
* @param float|int $x
|
||||
* @param float|int $y
|
||||
* @param float|int $z
|
||||
* @param Level $level
|
||||
*/
|
||||
public function __construct($x = 0, $y = 0, $z = 0, Level $level = null){
|
||||
parent::__construct($x, $y, $z);
|
||||
$this->setLevel($level);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Position
|
||||
*/
|
||||
public static function fromObject(Vector3 $pos, Level $level = null){
|
||||
return new Position($pos->x, $pos->y, $pos->z, $level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Position instance
|
||||
*
|
||||
* @return Position
|
||||
*/
|
||||
public function asPosition() : Position{
|
||||
return new Position($this->x, $this->y, $this->z, $this->level);
|
||||
@ -74,8 +74,6 @@ class Position extends Vector3{
|
||||
/**
|
||||
* Sets the target Level of the position.
|
||||
*
|
||||
* @param Level|null $level
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws \InvalidArgumentException if the specified Level has been closed
|
||||
@ -91,8 +89,6 @@ class Position extends Vector3{
|
||||
|
||||
/**
|
||||
* Checks if this object has a valid reference to a loaded Level
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isValid() : bool{
|
||||
if($this->level !== null and $this->level->isClosed()){
|
||||
@ -107,9 +103,6 @@ class Position extends Vector3{
|
||||
/**
|
||||
* Returns a side Vector
|
||||
*
|
||||
* @param int $side
|
||||
* @param int $step
|
||||
*
|
||||
* @return Position
|
||||
*/
|
||||
public function getSide(int $side, int $step = 1){
|
||||
|
@ -32,14 +32,13 @@ class SimpleChunkManager implements ChunkManager{
|
||||
/** @var Chunk[] */
|
||||
protected $chunks = [];
|
||||
|
||||
/** @var int */
|
||||
protected $seed;
|
||||
/** @var int */
|
||||
protected $worldHeight;
|
||||
|
||||
/**
|
||||
* SimpleChunkManager constructor.
|
||||
*
|
||||
* @param int $seed
|
||||
* @param int $worldHeight
|
||||
*/
|
||||
public function __construct(int $seed, int $worldHeight = Level::Y_MAX){
|
||||
$this->seed = $seed;
|
||||
@ -49,14 +48,10 @@ class SimpleChunkManager implements ChunkManager{
|
||||
/**
|
||||
* Gets the raw block id.
|
||||
*
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
*
|
||||
* @return int 0-255
|
||||
*/
|
||||
public function getBlockIdAt(int $x, int $y, int $z) : int{
|
||||
if($chunk = $this->getChunk($x >> 4, $z >> 4)){
|
||||
if(($chunk = $this->getChunk($x >> 4, $z >> 4)) !== null){
|
||||
return $chunk->getBlockId($x & 0xf, $y, $z & 0xf);
|
||||
}
|
||||
return 0;
|
||||
@ -65,13 +60,12 @@ class SimpleChunkManager implements ChunkManager{
|
||||
/**
|
||||
* Sets the raw block id.
|
||||
*
|
||||
* @param int $x
|
||||
* @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)){
|
||||
if(($chunk = $this->getChunk($x >> 4, $z >> 4)) !== null){
|
||||
$chunk->setBlockId($x & 0xf, $y, $z & 0xf, $id);
|
||||
}
|
||||
}
|
||||
@ -79,14 +73,10 @@ class SimpleChunkManager implements ChunkManager{
|
||||
/**
|
||||
* Gets the raw block metadata
|
||||
*
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
*
|
||||
* @return int 0-15
|
||||
*/
|
||||
public function getBlockDataAt(int $x, int $y, int $z) : int{
|
||||
if($chunk = $this->getChunk($x >> 4, $z >> 4)){
|
||||
if(($chunk = $this->getChunk($x >> 4, $z >> 4)) !== null){
|
||||
return $chunk->getBlockData($x & 0xf, $y, $z & 0xf);
|
||||
}
|
||||
return 0;
|
||||
@ -95,19 +85,18 @@ class SimpleChunkManager implements ChunkManager{
|
||||
/**
|
||||
* Sets the raw block metadata.
|
||||
*
|
||||
* @param int $x
|
||||
* @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)){
|
||||
if(($chunk = $this->getChunk($x >> 4, $z >> 4)) !== null){
|
||||
$chunk->setBlockData($x & 0xf, $y, $z & 0xf, $data);
|
||||
}
|
||||
}
|
||||
|
||||
public function getBlockLightAt(int $x, int $y, int $z) : int{
|
||||
if($chunk = $this->getChunk($x >> 4, $z >> 4)){
|
||||
if(($chunk = $this->getChunk($x >> 4, $z >> 4)) !== null){
|
||||
return $chunk->getBlockLight($x & 0xf, $y, $z & 0xf);
|
||||
}
|
||||
|
||||
@ -115,13 +104,13 @@ class SimpleChunkManager implements ChunkManager{
|
||||
}
|
||||
|
||||
public function setBlockLightAt(int $x, int $y, int $z, int $level){
|
||||
if($chunk = $this->getChunk($x >> 4, $z >> 4)){
|
||||
if(($chunk = $this->getChunk($x >> 4, $z >> 4)) !== null){
|
||||
$chunk->setBlockLight($x & 0xf, $y, $z & 0xf, $level);
|
||||
}
|
||||
}
|
||||
|
||||
public function getBlockSkyLightAt(int $x, int $y, int $z) : int{
|
||||
if($chunk = $this->getChunk($x >> 4, $z >> 4)){
|
||||
if(($chunk = $this->getChunk($x >> 4, $z >> 4)) !== null){
|
||||
return $chunk->getBlockSkyLight($x & 0xf, $y, $z & 0xf);
|
||||
}
|
||||
|
||||
@ -129,15 +118,12 @@ class SimpleChunkManager implements ChunkManager{
|
||||
}
|
||||
|
||||
public function setBlockSkyLightAt(int $x, int $y, int $z, int $level){
|
||||
if($chunk = $this->getChunk($x >> 4, $z >> 4)){
|
||||
if(($chunk = $this->getChunk($x >> 4, $z >> 4)) !== null){
|
||||
$chunk->setBlockSkyLight($x & 0xf, $y, $z & 0xf, $level);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $chunkX
|
||||
* @param int $chunkZ
|
||||
*
|
||||
* @return Chunk|null
|
||||
*/
|
||||
public function getChunk(int $chunkX, int $chunkZ){
|
||||
@ -145,9 +131,7 @@ 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,14 +141,15 @@ class SimpleChunkManager implements ChunkManager{
|
||||
$this->chunks[Level::chunkHash($chunkX, $chunkZ)] = $chunk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function cleanChunks(){
|
||||
$this->chunks = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the level seed
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getSeed() : int{
|
||||
return $this->seed;
|
||||
|
@ -43,16 +43,16 @@ abstract class Biome{
|
||||
|
||||
public const ICE_PLAINS = 12;
|
||||
|
||||
|
||||
public const SMALL_MOUNTAINS = 20;
|
||||
|
||||
|
||||
public const BIRCH_FOREST = 27;
|
||||
|
||||
|
||||
public const MAX_BIOMES = 256;
|
||||
|
||||
/** @var Biome[]|\SplFixedArray */
|
||||
/**
|
||||
* @var Biome[]|\SplFixedArray
|
||||
* @phpstan-var \SplFixedArray<Biome>
|
||||
*/
|
||||
private static $biomes;
|
||||
|
||||
/** @var int */
|
||||
@ -76,11 +76,17 @@ abstract class Biome{
|
||||
/** @var float */
|
||||
protected $temperature = 0.5;
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
@ -95,17 +101,11 @@ abstract class Biome{
|
||||
|
||||
self::register(self::ICE_PLAINS, new IcePlainsBiome());
|
||||
|
||||
|
||||
self::register(self::SMALL_MOUNTAINS, new SmallMountainsBiome());
|
||||
|
||||
self::register(self::BIRCH_FOREST, new ForestBiome(ForestBiome::TYPE_BIRCH));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
*
|
||||
* @return Biome
|
||||
*/
|
||||
public static function getBiome(int $id) : Biome{
|
||||
if(self::$biomes[$id] === null){
|
||||
self::register($id, new UnknownBiome());
|
||||
@ -113,19 +113,22 @@ abstract class Biome{
|
||||
return self::$biomes[$id];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function clearPopulators(){
|
||||
$this->populators = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function addPopulator(Populator $populator){
|
||||
$this->populators[] = $populator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ChunkManager $level
|
||||
* @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 +143,9 @@ abstract class Biome{
|
||||
return $this->populators;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setId(int $id){
|
||||
if(!$this->registered){
|
||||
$this->registered = true;
|
||||
@ -161,6 +167,9 @@ abstract class Biome{
|
||||
return $this->maxElevation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setElevation(int $min, int $max){
|
||||
$this->minElevation = $min;
|
||||
$this->maxElevation = $max;
|
||||
@ -175,6 +184,8 @@ abstract class Biome{
|
||||
|
||||
/**
|
||||
* @param Block[] $covers
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setGroundCover(array $covers){
|
||||
$this->groundCover = $covers;
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\level\biome;
|
||||
|
||||
|
||||
class DesertBiome extends SandyBiome{
|
||||
|
||||
public function __construct(){
|
||||
|
@ -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){
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\level\biome;
|
||||
|
||||
|
||||
class SmallMountainsBiome extends MountainsBiome{
|
||||
|
||||
public function __construct(){
|
||||
|
@ -72,7 +72,10 @@ class Chunk{
|
||||
/** @var int */
|
||||
protected $height = Chunk::MAX_SUBCHUNKS;
|
||||
|
||||
/** @var \SplFixedArray|SubChunkInterface[] */
|
||||
/**
|
||||
* @var \SplFixedArray|SubChunkInterface[]
|
||||
* @phpstan-var \SplFixedArray<SubChunkInterface>
|
||||
*/
|
||||
protected $subChunks;
|
||||
|
||||
/** @var EmptySubChunk */
|
||||
@ -86,7 +89,10 @@ class Chunk{
|
||||
/** @var Entity[] */
|
||||
protected $entities = [];
|
||||
|
||||
/** @var \SplFixedArray|int[] */
|
||||
/**
|
||||
* @var \SplFixedArray|int[]
|
||||
* @phpstan-var \SplFixedArray<int>
|
||||
*/
|
||||
protected $heightMap;
|
||||
|
||||
/** @var string */
|
||||
@ -99,12 +105,9 @@ class Chunk{
|
||||
protected $NBTentities = [];
|
||||
|
||||
/**
|
||||
* @param int $chunkX
|
||||
* @param int $chunkZ
|
||||
* @param SubChunkInterface[] $subChunks
|
||||
* @param CompoundTag[] $entities
|
||||
* @param CompoundTag[] $tiles
|
||||
* @param string $biomeIds
|
||||
* @param int[] $heightMap
|
||||
*/
|
||||
public function __construct(int $chunkX, int $chunkZ, array $subChunks = [], array $entities = [], array $tiles = [], string $biomeIds = "", array $heightMap = []){
|
||||
@ -139,26 +142,23 @@ class Chunk{
|
||||
$this->NBTentities = $entities;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getX() : int{
|
||||
return $this->x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getZ() : int{
|
||||
return $this->z;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setX(int $x){
|
||||
$this->x = $x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $z
|
||||
* @return void
|
||||
*/
|
||||
public function setZ(int $z){
|
||||
$this->z = $z;
|
||||
@ -166,8 +166,6 @@ class Chunk{
|
||||
|
||||
/**
|
||||
* Returns the chunk height in count of subchunks.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHeight() : int{
|
||||
return $this->height;
|
||||
@ -194,8 +192,6 @@ class Chunk{
|
||||
* @param int $z 0-15
|
||||
* @param int|null $blockId 0-255 if null, does not change
|
||||
* @param int|null $meta 0-15 if null, does not change
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setBlock(int $x, int $y, int $z, ?int $blockId = null, ?int $meta = null) : bool{
|
||||
if($this->getSubChunk($y >> 4, true)->setBlock($x, $y & 0x0f, $z, $blockId !== null ? ($blockId & 0xff) : null, $meta !== null ? ($meta & 0x0f) : null)){
|
||||
@ -225,6 +221,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 +250,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 +279,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)){
|
||||
@ -287,7 +289,7 @@ class Chunk{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $level
|
||||
* @return void
|
||||
*/
|
||||
public function setAllBlockSkyLight(int $level){
|
||||
$char = chr(($level & 0x0f) | ($level << 4));
|
||||
@ -317,6 +319,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)){
|
||||
@ -325,7 +329,7 @@ class Chunk{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $level
|
||||
* @return void
|
||||
*/
|
||||
public function setAllBlockLight(int $level){
|
||||
$char = chr(($level & 0x0f) | ($level << 4));
|
||||
@ -368,8 +372,6 @@ class Chunk{
|
||||
*
|
||||
* @param int $x 0-15
|
||||
* @param int $z 0-15
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHeightMap(int $x, int $z) : int{
|
||||
return $this->heightMap[($z << 4) | $x];
|
||||
@ -380,7 +382,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 +391,8 @@ class Chunk{
|
||||
|
||||
/**
|
||||
* Recalculates the heightmap for the whole chunk.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function recalculateHeightMap(){
|
||||
for($z = 0; $z < 16; ++$z){
|
||||
@ -406,8 +411,8 @@ class Chunk{
|
||||
* @return int New calculated heightmap value (0-256 inclusive)
|
||||
*/
|
||||
public function recalculateHeightMapColumn(int $x, int $z) : int{
|
||||
$max = $this->getHighestBlockAt($x, $z);
|
||||
for($y = $max; $y >= 0; --$y){
|
||||
$y = $this->getHighestBlockAt($x, $z);
|
||||
for(; $y >= 0; --$y){
|
||||
if(BlockFactory::$lightFilter[$id = $this->getBlockId($x, $y, $z)] > 1 or BlockFactory::$diffusesSkyLight[$id]){
|
||||
break;
|
||||
}
|
||||
@ -423,6 +428,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();
|
||||
@ -431,19 +438,17 @@ class Chunk{
|
||||
|
||||
for($x = 0; $x < 16; ++$x){
|
||||
for($z = 0; $z < 16; ++$z){
|
||||
$y = $maxY;
|
||||
$heightMap = $this->getHeightMap($x, $z);
|
||||
|
||||
for($y = $maxY; $y >= $heightMap; --$y){
|
||||
for(; $y >= $heightMap; --$y){
|
||||
$this->setBlockSkyLight($x, $y, $z, 15);
|
||||
}
|
||||
|
||||
$light = 15;
|
||||
for(; $y >= 0; --$y){
|
||||
if($light > 0){
|
||||
$light -= BlockFactory::$lightFilter[$this->getBlockId($x, $y, $z)];
|
||||
if($light <= 0){
|
||||
break;
|
||||
}
|
||||
$light -= BlockFactory::$lightFilter[$this->getBlockId($x, $y, $z)];
|
||||
if($light <= 0){
|
||||
break;
|
||||
}
|
||||
$this->setBlockSkyLight($x, $y, $z, $light);
|
||||
}
|
||||
@ -469,6 +474,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;
|
||||
@ -480,8 +487,6 @@ class Chunk{
|
||||
*
|
||||
* @param int $x 0-15
|
||||
* @param int $z 0-15
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBlockIdColumn(int $x, int $z) : string{
|
||||
$result = "";
|
||||
@ -497,8 +502,6 @@ class Chunk{
|
||||
*
|
||||
* @param int $x 0-15
|
||||
* @param int $z 0-15
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBlockDataColumn(int $x, int $z) : string{
|
||||
$result = "";
|
||||
@ -513,8 +516,6 @@ class Chunk{
|
||||
*
|
||||
* @param int $x 0-15
|
||||
* @param int $z 0-15
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBlockSkyLightColumn(int $x, int $z) : string{
|
||||
$result = "";
|
||||
@ -529,8 +530,6 @@ class Chunk{
|
||||
*
|
||||
* @param int $x 0-15
|
||||
* @param int $z 0-15
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBlockLightColumn(int $x, int $z) : string{
|
||||
$result = "";
|
||||
@ -540,50 +539,41 @@ class Chunk{
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isLightPopulated() : bool{
|
||||
return $this->lightPopulated;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
* @return void
|
||||
*/
|
||||
public function setLightPopulated(bool $value = true){
|
||||
$this->lightPopulated = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isPopulated() : bool{
|
||||
return $this->terrainPopulated;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
* @return void
|
||||
*/
|
||||
public function setPopulated(bool $value = true){
|
||||
$this->terrainPopulated = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isGenerated() : bool{
|
||||
return $this->terrainGenerated;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
* @return void
|
||||
*/
|
||||
public function setGenerated(bool $value = true){
|
||||
$this->terrainGenerated = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Entity $entity
|
||||
* @return void
|
||||
*/
|
||||
public function addEntity(Entity $entity){
|
||||
if($entity->isClosed()){
|
||||
@ -596,7 +586,7 @@ class Chunk{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Entity $entity
|
||||
* @return void
|
||||
*/
|
||||
public function removeEntity(Entity $entity){
|
||||
unset($this->entities[$entity->getId()]);
|
||||
@ -606,7 +596,7 @@ class Chunk{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Tile $tile
|
||||
* @return void
|
||||
*/
|
||||
public function addTile(Tile $tile){
|
||||
if($tile->isClosed()){
|
||||
@ -623,7 +613,7 @@ class Chunk{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Tile $tile
|
||||
* @return void
|
||||
*/
|
||||
public function removeTile(Tile $tile){
|
||||
unset($this->tiles[$tile->getId()]);
|
||||
@ -689,7 +679,7 @@ class Chunk{
|
||||
/**
|
||||
* Deserializes tiles and entities from NBT
|
||||
*
|
||||
* @param Level $level
|
||||
* @return void
|
||||
*/
|
||||
public function initChunk(Level $level){
|
||||
if(!$this->isInit){
|
||||
@ -697,23 +687,21 @@ class Chunk{
|
||||
|
||||
$level->timings->syncChunkLoadEntitiesTimer->startTiming();
|
||||
foreach($this->NBTentities as $nbt){
|
||||
if($nbt instanceof CompoundTag){
|
||||
if(!$nbt->hasTag("id")){ //allow mixed types (because of leveldb)
|
||||
$changed = true;
|
||||
continue;
|
||||
}
|
||||
if(!$nbt->hasTag("id")){ //allow mixed types (because of leveldb)
|
||||
$changed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
try{
|
||||
$entity = Entity::createEntity($nbt->getTag("id")->getValue(), $level, $nbt);
|
||||
if(!($entity instanceof Entity)){
|
||||
$changed = true;
|
||||
continue;
|
||||
}
|
||||
}catch(\Throwable $t){
|
||||
$level->getServer()->getLogger()->logException($t);
|
||||
try{
|
||||
$entity = Entity::createEntity($nbt->getTag("id")->getValue(), $level, $nbt);
|
||||
if(!($entity instanceof Entity)){
|
||||
$changed = true;
|
||||
continue;
|
||||
}
|
||||
}catch(\Throwable $t){
|
||||
$level->getServer()->getLogger()->logException($t);
|
||||
$changed = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$this->NBTentities = [];
|
||||
@ -721,16 +709,14 @@ class Chunk{
|
||||
|
||||
$level->timings->syncChunkLoadTileEntitiesTimer->startTiming();
|
||||
foreach($this->NBTtiles as $nbt){
|
||||
if($nbt instanceof CompoundTag){
|
||||
if(!$nbt->hasTag(Tile::TAG_ID, StringTag::class)){
|
||||
$changed = true;
|
||||
continue;
|
||||
}
|
||||
if(!$nbt->hasTag(Tile::TAG_ID, StringTag::class)){
|
||||
$changed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(Tile::createTile($nbt->getString(Tile::TAG_ID), $level, $nbt) === null){
|
||||
$changed = true;
|
||||
continue;
|
||||
}
|
||||
if(Tile::createTile($nbt->getString(Tile::TAG_ID), $level, $nbt) === null){
|
||||
$changed = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@ -743,9 +729,6 @@ class Chunk{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getBiomeIdArray() : string{
|
||||
return $this->biomeIds;
|
||||
}
|
||||
@ -757,15 +740,12 @@ class Chunk{
|
||||
return $this->heightMap->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasChanged() : bool{
|
||||
return $this->hasChanged;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
* @return void
|
||||
*/
|
||||
public function setChanged(bool $value = true){
|
||||
$this->hasChanged = $value;
|
||||
@ -774,10 +754,7 @@ class Chunk{
|
||||
/**
|
||||
* Returns the subchunk at the specified subchunk Y coordinate, or an empty, unmodifiable stub if it does not exist or the coordinate is out of range.
|
||||
*
|
||||
* @param int $y
|
||||
* @param bool $generateNew Whether to create a new, modifiable subchunk if there is not one in place
|
||||
*
|
||||
* @return SubChunkInterface
|
||||
*/
|
||||
public function getSubChunk(int $y, bool $generateNew = false) : SubChunkInterface{
|
||||
if($y < 0 or $y >= $this->height){
|
||||
@ -792,11 +769,7 @@ class Chunk{
|
||||
/**
|
||||
* Sets a subchunk in the chunk index
|
||||
*
|
||||
* @param int $y
|
||||
* @param SubChunkInterface|null $subChunk
|
||||
* @param bool $allowEmpty Whether to check if the chunk is empty, and if so replace it with an empty stub
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setSubChunk(int $y, SubChunkInterface $subChunk = null, bool $allowEmpty = false) : bool{
|
||||
if($y < 0 or $y >= $this->height){
|
||||
@ -813,6 +786,7 @@ class Chunk{
|
||||
|
||||
/**
|
||||
* @return \SplFixedArray|SubChunkInterface[]
|
||||
* @phpstan-return \SplFixedArray<SubChunkInterface>
|
||||
*/
|
||||
public function getSubChunks() : \SplFixedArray{
|
||||
return $this->subChunks;
|
||||
@ -820,8 +794,6 @@ class Chunk{
|
||||
|
||||
/**
|
||||
* Returns the Y coordinate of the highest non-empty subchunk in this chunk.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHighestSubChunkIndex() : int{
|
||||
for($y = $this->subChunks->count() - 1; $y >= 0; --$y){
|
||||
@ -829,16 +801,14 @@ class Chunk{
|
||||
//No need to thoroughly prune empties at runtime, this will just reduce performance.
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
return $y;
|
||||
}
|
||||
|
||||
return $y;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the count of subchunks that need sending to players
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getSubChunkSendCount() : int{
|
||||
return $this->getHighestSubChunkIndex() + 1;
|
||||
@ -861,8 +831,6 @@ class Chunk{
|
||||
|
||||
/**
|
||||
* Serializes the chunk for sending to players
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function networkSerialize() : string{
|
||||
$result = "";
|
||||
@ -885,8 +853,6 @@ class Chunk{
|
||||
/**
|
||||
* Fast-serializes the chunk for passing between threads
|
||||
* TODO: tiles and entities
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function fastSerialize() : string{
|
||||
$stream = new BinaryStream();
|
||||
@ -922,10 +888,6 @@ class Chunk{
|
||||
|
||||
/**
|
||||
* Deserializes a fast-serialized chunk
|
||||
*
|
||||
* @param string $data
|
||||
*
|
||||
* @return Chunk
|
||||
*/
|
||||
public static function fastDeserialize(string $data) : Chunk{
|
||||
$stream = new BinaryStream($data);
|
||||
|
@ -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 [];
|
||||
}
|
||||
|
@ -25,181 +25,55 @@ namespace pocketmine\level\format;
|
||||
|
||||
interface SubChunkInterface{
|
||||
|
||||
/**
|
||||
* @param bool $checkLight
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmpty(bool $checkLight = true) : bool;
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getBlockId(int $x, int $y, int $z) : int;
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param int $id
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setBlockId(int $x, int $y, int $z, int $id) : bool;
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getBlockData(int $x, int $y, int $z) : int;
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param int $data
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setBlockData(int $x, int $y, int $z, int $data) : bool;
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getFullBlock(int $x, int $y, int $z) : int;
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param int|null $id
|
||||
* @param int|null $data
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setBlock(int $x, int $y, int $z, ?int $id = null, ?int $data = null) : bool;
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getBlockLight(int $x, int $y, int $z) : int;
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param int $level
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setBlockLight(int $x, int $y, int $z, int $level) : bool;
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getBlockSkyLight(int $x, int $y, int $z) : int;
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
* @param int $level
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setBlockSkyLight(int $x, int $y, int $z, int $level) : bool;
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $z
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHighestBlockAt(int $x, int $z) : int;
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $z
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBlockIdColumn(int $x, int $z) : string;
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $z
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBlockDataColumn(int $x, int $z) : string;
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $z
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBlockLightColumn(int $x, int $z) : string;
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $z
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBlockSkyLightColumn(int $x, int $z) : string;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getBlockIdArray() : string;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getBlockDataArray() : string;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getBlockSkyLightArray() : string;
|
||||
|
||||
/**
|
||||
* @param string $data
|
||||
* @return void
|
||||
*/
|
||||
public function setBlockSkyLightArray(string $data);
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getBlockLightArray() : string;
|
||||
|
||||
/**
|
||||
* @param string $data
|
||||
* @return void
|
||||
*/
|
||||
public function setBlockLightArray(string $data);
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function networkSerialize() : string;
|
||||
}
|
||||
|
@ -143,13 +143,13 @@ abstract class BaseLevelProvider implements LevelProvider{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CompoundTag
|
||||
*/
|
||||
public function getLevelData() : CompoundTag{
|
||||
return $this->levelData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function saveLevelData(){
|
||||
$nbt = new BigEndianNBTStream();
|
||||
$buffer = $nbt->writeCompressed(new CompoundTag("", [
|
||||
@ -159,10 +159,6 @@ abstract class BaseLevelProvider implements LevelProvider{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $chunkX
|
||||
* @param int $chunkZ
|
||||
*
|
||||
* @return Chunk|null
|
||||
* @throws CorruptedChunkException
|
||||
* @throws UnsupportedChunkFormatException
|
||||
*/
|
||||
@ -178,10 +174,6 @@ abstract class BaseLevelProvider implements LevelProvider{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $chunkX
|
||||
* @param int $chunkZ
|
||||
*
|
||||
* @return Chunk|null
|
||||
* @throws UnsupportedChunkFormatException
|
||||
* @throws CorruptedChunkException
|
||||
*/
|
||||
|
@ -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 */
|
||||
|
@ -98,8 +98,6 @@ if(!extension_loaded('pocketmine_chunkutils')){
|
||||
* Converts pre-MCPE-1.0 biome color array to biome ID array.
|
||||
*
|
||||
* @param int[] $array of biome color values
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function convertBiomeColors(array $array) : string{
|
||||
$result = str_repeat("\x00", 256);
|
||||
|
@ -26,142 +26,112 @@ namespace pocketmine\level\format\io;
|
||||
use pocketmine\level\format\Chunk;
|
||||
use pocketmine\level\format\io\exception\CorruptedChunkException;
|
||||
use pocketmine\level\format\io\exception\UnsupportedChunkFormatException;
|
||||
use pocketmine\level\generator\Generator;
|
||||
use pocketmine\math\Vector3;
|
||||
|
||||
interface LevelProvider{
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*/
|
||||
public function __construct(string $path);
|
||||
|
||||
/**
|
||||
* Returns the full provider name, like "anvil" or "mcregion", will be used to find the correct format.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getProviderName() : string;
|
||||
|
||||
/**
|
||||
* Gets the build height limit of this world
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getWorldHeight() : int;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPath() : string;
|
||||
|
||||
/**
|
||||
* Tells if the path is a valid level.
|
||||
* This must tell if the current format supports opening the files in the directory
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValid(string $path) : bool;
|
||||
|
||||
/**
|
||||
* Generate the needed files in the path given
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $name
|
||||
* @param int $seed
|
||||
* @param string $generator
|
||||
* @param array $options
|
||||
* @param mixed[] $options
|
||||
* @phpstan-param class-string<Generator> $generator
|
||||
* @phpstan-param array<string, mixed> $options
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function generate(string $path, string $name, int $seed, string $generator, array $options = []);
|
||||
|
||||
/**
|
||||
* Returns the generator name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getGenerator() : string;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @return mixed[]
|
||||
* @phpstan-return array<string, mixed>
|
||||
*/
|
||||
public function getGeneratorOptions() : array;
|
||||
|
||||
/**
|
||||
* Saves a chunk (usually to disk).
|
||||
*
|
||||
* @param Chunk $chunk
|
||||
*/
|
||||
public function saveChunk(Chunk $chunk) : void;
|
||||
|
||||
/**
|
||||
* Loads a chunk (usually from disk storage) and returns it. If the chunk does not exist, null is returned.
|
||||
*
|
||||
* @param int $chunkX
|
||||
* @param int $chunkZ
|
||||
*
|
||||
* @return null|Chunk
|
||||
*
|
||||
* @throws CorruptedChunkException
|
||||
* @throws UnsupportedChunkFormatException
|
||||
*/
|
||||
public function loadChunk(int $chunkX, int $chunkZ) : ?Chunk;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName() : string;
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getTime() : int;
|
||||
|
||||
/**
|
||||
* @param int $value
|
||||
* @return void
|
||||
*/
|
||||
public function setTime(int $value);
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getSeed() : int;
|
||||
|
||||
/**
|
||||
* @param int $value
|
||||
* @return void
|
||||
*/
|
||||
public function setSeed(int $value);
|
||||
|
||||
/**
|
||||
* @return Vector3
|
||||
*/
|
||||
public function getSpawn() : Vector3;
|
||||
|
||||
/**
|
||||
* @param Vector3 $pos
|
||||
* @return void
|
||||
*/
|
||||
public function setSpawn(Vector3 $pos);
|
||||
|
||||
/**
|
||||
* Returns the world difficulty. This will be one of the Level constants.
|
||||
* @return int
|
||||
*/
|
||||
public function getDifficulty() : int;
|
||||
|
||||
/**
|
||||
* 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,10 @@ use function strtolower;
|
||||
use function trim;
|
||||
|
||||
abstract class LevelProviderManager{
|
||||
/**
|
||||
* @var string[]
|
||||
* @phpstan-var array<string, class-string<LevelProvider>>
|
||||
*/
|
||||
protected static $providers = [];
|
||||
|
||||
public static function init() : void{
|
||||
@ -41,8 +45,9 @@ abstract class LevelProviderManager{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @phpstan-param class-string<LevelProvider> $class
|
||||
*
|
||||
* @return void
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public static function addProvider(string $class){
|
||||
@ -65,13 +70,12 @@ abstract class LevelProviderManager{
|
||||
/**
|
||||
* Returns a LevelProvider class for this path, or null
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @return string|null
|
||||
* @phpstan-return class-string<LevelProvider>|null
|
||||
*/
|
||||
public static function getProvider(string $path){
|
||||
foreach(self::$providers as $provider){
|
||||
/** @var $provider LevelProvider */
|
||||
/** @phpstan-var class-string<LevelProvider> $provider */
|
||||
if($provider::isValid($path)){
|
||||
return $provider;
|
||||
}
|
||||
@ -83,9 +87,8 @@ abstract class LevelProviderManager{
|
||||
/**
|
||||
* Returns a LevelProvider by name, or null if not found
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return string|null
|
||||
* @phpstan-return class-string<LevelProvider>|null
|
||||
*/
|
||||
public static function getProviderByName(string $name){
|
||||
return self::$providers[trim(strtolower($name))] ?? null;
|
||||
|
@ -45,6 +45,7 @@ use pocketmine\utils\Binary;
|
||||
use pocketmine\utils\BinaryStream;
|
||||
use function array_values;
|
||||
use function chr;
|
||||
use function count;
|
||||
use function defined;
|
||||
use function explode;
|
||||
use function extension_loaded;
|
||||
@ -101,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");
|
||||
}
|
||||
@ -125,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{
|
||||
@ -247,7 +252,6 @@ class LevelDB extends BaseLevelProvider{
|
||||
$buffer = $nbt->write($levelData);
|
||||
file_put_contents($path . "level.dat", Binary::writeLInt(self::CURRENT_STORAGE_VERSION) . Binary::writeLInt(strlen($buffer)) . $buffer);
|
||||
|
||||
|
||||
$db = self::createDB($path);
|
||||
|
||||
if($generatorType === self::GENERATOR_FLAT and isset($options["preset"])){
|
||||
@ -292,10 +296,6 @@ class LevelDB extends BaseLevelProvider{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $chunkX
|
||||
* @param int $chunkZ
|
||||
*
|
||||
* @return Chunk|null
|
||||
* @throws UnsupportedChunkFormatException
|
||||
*/
|
||||
protected function readChunk(int $chunkX, int $chunkZ) : ?Chunk{
|
||||
@ -516,10 +516,9 @@ class LevelDB extends BaseLevelProvider{
|
||||
|
||||
/**
|
||||
* @param CompoundTag[] $targets
|
||||
* @param string $index
|
||||
*/
|
||||
private function writeTags(array $targets, string $index){
|
||||
if(!empty($targets)){
|
||||
private function writeTags(array $targets, string $index) : void{
|
||||
if(count($targets) > 0){
|
||||
$nbt = new LittleEndianNBTStream();
|
||||
$this->db->put($index, $nbt->write($targets));
|
||||
}else{
|
||||
@ -527,9 +526,6 @@ class LevelDB extends BaseLevelProvider{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \LevelDB
|
||||
*/
|
||||
public function getDatabase() : \LevelDB{
|
||||
return $this->db;
|
||||
}
|
||||
|
@ -21,10 +21,8 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace pocketmine\level\format\io\region;
|
||||
|
||||
|
||||
class CorruptedRegionException extends RegionException{
|
||||
|
||||
}
|
||||
|
@ -67,11 +67,6 @@ class McRegion extends BaseLevelProvider{
|
||||
/** @var RegionLoader[] */
|
||||
protected $regions = [];
|
||||
|
||||
/**
|
||||
* @param Chunk $chunk
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function nbtSerialize(Chunk $chunk) : string{
|
||||
$nbt = new CompoundTag("Level", []);
|
||||
$nbt->setInt("xPos", $chunk->getX());
|
||||
@ -127,9 +122,6 @@ class McRegion extends BaseLevelProvider{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $data
|
||||
*
|
||||
* @return Chunk
|
||||
* @throws CorruptedChunkException
|
||||
*/
|
||||
protected function nbtDeserialize(string $data) : Chunk{
|
||||
@ -206,9 +198,6 @@ class McRegion extends BaseLevelProvider{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $context
|
||||
* @param ListTag $list
|
||||
*
|
||||
* @return CompoundTag[]
|
||||
* @throws CorruptedChunkException
|
||||
*/
|
||||
@ -236,7 +225,6 @@ class McRegion extends BaseLevelProvider{
|
||||
|
||||
/**
|
||||
* Returns the storage version as per Minecraft PC world formats.
|
||||
* @return int
|
||||
*/
|
||||
public static function getPcWorldFormatVersion() : int{
|
||||
return 19132; //mcregion
|
||||
@ -251,7 +239,7 @@ class McRegion extends BaseLevelProvider{
|
||||
$isValid = (file_exists($path . "/level.dat") and is_dir($path . "/region/"));
|
||||
|
||||
if($isValid){
|
||||
$files = array_filter(scandir($path . "/region/", SCANDIR_SORT_NONE), function($file){
|
||||
$files = array_filter(scandir($path . "/region/", SCANDIR_SORT_NONE), function(string $file) : bool{
|
||||
return substr($file, strrpos($file, ".") + 1, 2) === "mc"; //region file
|
||||
});
|
||||
|
||||
@ -329,10 +317,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;
|
||||
@ -340,9 +328,6 @@ class McRegion extends BaseLevelProvider{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $regionX
|
||||
* @param int $regionZ
|
||||
*
|
||||
* @return RegionLoader|null
|
||||
*/
|
||||
protected function getRegion(int $regionX, int $regionZ){
|
||||
@ -351,19 +336,13 @@ class McRegion extends BaseLevelProvider{
|
||||
|
||||
/**
|
||||
* Returns the path to a specific region file based on its X/Z coordinates
|
||||
*
|
||||
* @param int $regionX
|
||||
* @param int $regionZ
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function pathToRegion(int $regionX, int $regionZ) : string{
|
||||
return $this->path . "region/r.$regionX.$regionZ." . static::REGION_FILE_EXTENSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $regionX
|
||||
* @param int $regionZ
|
||||
* @return void
|
||||
*/
|
||||
protected function loadRegion(int $regionX, int $regionZ){
|
||||
if(!isset($this->regions[$index = Level::chunkHash($regionX, $regionZ)])){
|
||||
@ -398,11 +377,6 @@ class McRegion extends BaseLevelProvider{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $chunkX
|
||||
* @param int $chunkZ
|
||||
*
|
||||
* @return Chunk|null
|
||||
*
|
||||
* @throws CorruptedChunkException
|
||||
*/
|
||||
protected function readChunk(int $chunkX, int $chunkZ) : ?Chunk{
|
||||
|
@ -21,10 +21,8 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace pocketmine\level\format\io\region;
|
||||
|
||||
|
||||
class RegionException extends \RuntimeException{
|
||||
|
||||
}
|
||||
|
@ -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(){
|
||||
@ -120,10 +122,6 @@ class RegionLoader{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $z
|
||||
*
|
||||
* @return null|string
|
||||
* @throws \InvalidArgumentException if invalid coordinates are given
|
||||
* @throws CorruptedChunkException if chunk corruption is detected
|
||||
*/
|
||||
@ -172,10 +170,6 @@ class RegionLoader{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $z
|
||||
*
|
||||
* @return bool
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function chunkExists(int $x, int $z) : bool{
|
||||
@ -183,10 +177,7 @@ class RegionLoader{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $z
|
||||
* @param string $chunkData
|
||||
*
|
||||
* @return void
|
||||
* @throws ChunkException
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
@ -216,9 +207,7 @@ class RegionLoader{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $z
|
||||
*
|
||||
* @return void
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function removeChunk(int $x, int $z){
|
||||
@ -228,10 +217,6 @@ class RegionLoader{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $z
|
||||
*
|
||||
* @return int
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected static function getChunkOffset(int $x, int $z) : int{
|
||||
@ -242,9 +227,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;
|
||||
@ -254,7 +238,7 @@ 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 +251,7 @@ class RegionLoader{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
* @throws CorruptedRegionException
|
||||
*/
|
||||
protected function loadLocationTable(){
|
||||
@ -328,7 +313,7 @@ class RegionLoader{
|
||||
}
|
||||
}
|
||||
|
||||
private function writeLocationTable(){
|
||||
private function writeLocationTable() : void{
|
||||
$write = [];
|
||||
|
||||
for($i = 0; $i < 1024; ++$i){
|
||||
@ -341,6 +326,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 +338,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
|
||||
|
@ -35,10 +35,6 @@ class RegionLocationTableEntry{
|
||||
private $timestamp;
|
||||
|
||||
/**
|
||||
* @param int $firstSector
|
||||
* @param int $sectorCount
|
||||
* @param int $timestamp
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __construct(int $firstSector, int $sectorCount, int $timestamp){
|
||||
@ -53,16 +49,10 @@ class RegionLocationTableEntry{
|
||||
$this->timestamp = $timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getFirstSector() : int{
|
||||
return $this->firstSector;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getLastSector() : int{
|
||||
return $this->firstSector + $this->sectorCount - 1;
|
||||
}
|
||||
@ -75,23 +65,14 @@ class RegionLocationTableEntry{
|
||||
return range($this->getFirstSector(), $this->getLastSector());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getSectorCount() : int{
|
||||
return $this->sectorCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getTimestamp() : int{
|
||||
return $this->timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isNull() : bool{
|
||||
return $this->firstSector === 0 or $this->sectorCount === 0;
|
||||
}
|
||||
|
@ -44,13 +44,19 @@ class Flat extends Generator{
|
||||
private $chunk;
|
||||
/** @var Populator[] */
|
||||
private $populators = [];
|
||||
/** @var int[][] */
|
||||
/**
|
||||
* @var int[][]
|
||||
* @phpstan-var array<int, array{0: int, 1: int}>
|
||||
*/
|
||||
private $structure;
|
||||
/** @var int */
|
||||
private $floorLevel;
|
||||
/** @var int */
|
||||
private $biome;
|
||||
/** @var mixed[] */
|
||||
/**
|
||||
* @var mixed[]
|
||||
* @phpstan-var array<string, mixed>
|
||||
*/
|
||||
private $options;
|
||||
/** @var string */
|
||||
private $preset;
|
||||
@ -64,7 +70,8 @@ class Flat extends Generator{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $options
|
||||
* @param mixed[] $options
|
||||
* @phpstan-param array<string, mixed> $options
|
||||
*
|
||||
* @throws InvalidGeneratorOptionsException
|
||||
*/
|
||||
@ -96,9 +103,9 @@ class Flat extends Generator{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $layers
|
||||
*
|
||||
* @return int[][]
|
||||
* @phpstan-return array<int, array{0: int, 1: int}>
|
||||
*
|
||||
* @throws InvalidGeneratorOptionsException
|
||||
*/
|
||||
public static function parseLayers(string $layers) : array{
|
||||
@ -127,9 +134,9 @@ class Flat extends Generator{
|
||||
|
||||
protected function parsePreset() : void{
|
||||
$preset = explode(";", $this->preset);
|
||||
$blocks = (string) ($preset[1] ?? "");
|
||||
$blocks = $preset[1] ?? "";
|
||||
$this->biome = (int) ($preset[2] ?? 1);
|
||||
$options = (string) ($preset[3] ?? "");
|
||||
$options = $preset[3] ?? "";
|
||||
$this->structure = self::parseLayers($blocks);
|
||||
|
||||
$this->floorLevel = count($this->structure);
|
||||
|
@ -36,10 +36,6 @@ abstract class Generator{
|
||||
|
||||
/**
|
||||
* Converts a string level seed into an integer for use by the generator.
|
||||
*
|
||||
* @param string $seed
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public static function convertSeed(string $seed) : ?int{
|
||||
if($seed === ""){ //empty seed should cause a random seed to be selected - can't use 0 here because 0 is a valid seed
|
||||
@ -59,13 +55,13 @@ abstract class Generator{
|
||||
protected $random;
|
||||
|
||||
/**
|
||||
* @param array $settings
|
||||
*
|
||||
* @throws InvalidGeneratorOptionsException
|
||||
*
|
||||
* @param mixed[] $settings
|
||||
* @phpstan-param array<string, mixed> $settings
|
||||
*/
|
||||
abstract public function __construct(array $settings = []);
|
||||
|
||||
|
||||
public function init(ChunkManager $level, Random $random) : void{
|
||||
$this->level = $level;
|
||||
$this->random = $random;
|
||||
@ -75,6 +71,10 @@ abstract class Generator{
|
||||
|
||||
abstract public function populateChunk(int $chunkX, int $chunkZ) : void;
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
* @phpstan-return array<string, mixed>
|
||||
*/
|
||||
abstract public function getSettings() : array;
|
||||
|
||||
abstract public function getName() : string;
|
||||
|
@ -30,7 +30,10 @@ use function is_subclass_of;
|
||||
use function strtolower;
|
||||
|
||||
final class GeneratorManager{
|
||||
/** @var string[] name => classname mapping */
|
||||
/**
|
||||
* @var string[] name => classname mapping
|
||||
* @phpstan-var array<string, class-string<Generator>>
|
||||
*/
|
||||
private static $list = [];
|
||||
|
||||
/**
|
||||
@ -48,6 +51,7 @@ final class GeneratorManager{
|
||||
* @param string $class Fully qualified name of class that extends \pocketmine\level\generator\Generator
|
||||
* @param string $name Alias for this generator type that can be written in configs
|
||||
* @param bool $overwrite Whether to force overwriting any existing registered generator with the same name
|
||||
* @phpstan-param class-string<Generator> $class
|
||||
*/
|
||||
public static function addGenerator(string $class, string $name, bool $overwrite = false) : void{
|
||||
if(!is_subclass_of($class, Generator::class)){
|
||||
@ -73,10 +77,11 @@ final class GeneratorManager{
|
||||
/**
|
||||
* Returns a class name of a registered Generator matching the given name.
|
||||
*
|
||||
* @param string $name
|
||||
* @param bool $throwOnMissing @deprecated this is for backwards compatibility only
|
||||
*
|
||||
* @return string|Generator Name of class that extends Generator (not an actual Generator object)
|
||||
* @return string Name of class that extends Generator
|
||||
* @phpstan-return class-string<Generator>
|
||||
*
|
||||
* @throws \InvalidArgumentException if the generator type isn't registered
|
||||
*/
|
||||
public static function getGenerator(string $name, bool $throwOnMissing = false){
|
||||
@ -94,8 +99,7 @@ final class GeneratorManager{
|
||||
* Returns the registered name of the given Generator class.
|
||||
*
|
||||
* @param string $class Fully qualified name of class that extends \pocketmine\level\generator\Generator
|
||||
*
|
||||
* @return string
|
||||
* @phpstan-param class-string<Generator> $class
|
||||
*/
|
||||
public static function getGeneratorName(string $class) : string{
|
||||
foreach(self::$list as $name => $c){
|
||||
|
@ -34,12 +34,21 @@ 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;
|
||||
|
||||
/**
|
||||
* @param mixed[] $generatorSettings
|
||||
* @phpstan-param array<string, mixed> $generatorSettings
|
||||
*/
|
||||
public function __construct(Level $level, string $generatorClass, array $generatorSettings = []){
|
||||
$this->generatorClass = $generatorClass;
|
||||
$this->settings = serialize($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){
|
||||
@ -89,48 +102,26 @@ class PopulationTask extends AsyncTask{
|
||||
}
|
||||
|
||||
foreach($chunks as $c){
|
||||
if($c !== null){
|
||||
$manager->setChunk($c->getX(), $c->getZ(), $c);
|
||||
if(!$c->isGenerated()){
|
||||
$generator->generateChunk($c->getX(), $c->getZ());
|
||||
$c = $manager->getChunk($c->getX(), $c->getZ());
|
||||
$c->setGenerated();
|
||||
}
|
||||
$manager->setChunk($c->getX(), $c->getZ(), $c);
|
||||
if(!$c->isGenerated()){
|
||||
$generator->generateChunk($c->getX(), $c->getZ());
|
||||
$c->setGenerated();
|
||||
}
|
||||
}
|
||||
|
||||
$generator->populateChunk($chunk->getX(), $chunk->getZ());
|
||||
|
||||
$chunk = $manager->getChunk($chunk->getX(), $chunk->getZ());
|
||||
$chunk->recalculateHeightMap();
|
||||
$chunk->populateSkyLight();
|
||||
$chunk->setLightPopulated();
|
||||
$chunk->setPopulated();
|
||||
$this->chunk = $chunk->fastSerialize();
|
||||
|
||||
$manager->setChunk($chunk->getX(), $chunk->getZ(), null);
|
||||
|
||||
foreach($chunks as $i => $c){
|
||||
if($c !== null){
|
||||
$c = $chunks[$i] = $manager->getChunk($c->getX(), $c->getZ());
|
||||
if(!$c->hasChanged()){
|
||||
$chunks[$i] = null;
|
||||
}
|
||||
}else{
|
||||
//This way non-changed chunks are not set
|
||||
$chunks[$i] = null;
|
||||
}
|
||||
$this->{"chunk$i"} = $c->hasChanged() ? $c->fastSerialize() : null;
|
||||
}
|
||||
|
||||
$manager->cleanChunks();
|
||||
|
||||
for($i = 0; $i < 9; ++$i){
|
||||
if($i === 4){
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->{"chunk$i"} = $chunks[$i] !== null ? $chunks[$i]->fastSerialize() : null;
|
||||
}
|
||||
}
|
||||
|
||||
public function onCompletion(Server $server){
|
||||
|
@ -34,7 +34,10 @@ abstract class BiomeSelector{
|
||||
/** @var Simplex */
|
||||
private $rainfall;
|
||||
|
||||
/** @var Biome[]|\SplFixedArray */
|
||||
/**
|
||||
* @var Biome[]|\SplFixedArray
|
||||
* @phpstan-var \SplFixedArray<Biome>
|
||||
*/
|
||||
private $map = null;
|
||||
|
||||
public function __construct(Random $random){
|
||||
@ -45,13 +48,13 @@ abstract class BiomeSelector{
|
||||
/**
|
||||
* Lookup function called by recalculate() to determine the biome to use for this temperature and rainfall.
|
||||
*
|
||||
* @param float $temperature
|
||||
* @param float $rainfall
|
||||
*
|
||||
* @return int biome ID 0-255
|
||||
*/
|
||||
abstract protected function lookup(float $temperature, float $rainfall) : int;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function recalculate(){
|
||||
$this->map = new \SplFixedArray(64 * 64);
|
||||
|
||||
@ -66,20 +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
|
||||
*
|
||||
* @return Biome
|
||||
* @param int $x
|
||||
* @param int $z
|
||||
*/
|
||||
public function pickBiome($x, $z) : Biome{
|
||||
$temperature = (int) ($this->getTemperature($x, $z) * 63);
|
||||
|
@ -53,7 +53,8 @@ class Nether extends Generator{
|
||||
private $noiseBase;
|
||||
|
||||
/**
|
||||
* @param array $options
|
||||
* @param mixed[] $options
|
||||
* @phpstan-param array<string, mixed> $options
|
||||
*
|
||||
* @throws InvalidGeneratorOptionsException
|
||||
*/
|
||||
|
@ -26,35 +26,79 @@ declare(strict_types=1);
|
||||
*/
|
||||
namespace pocketmine\level\generator\noise;
|
||||
|
||||
|
||||
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
|
||||
*/
|
||||
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 +110,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 +152,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 +168,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 +215,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;
|
||||
@ -146,15 +247,9 @@ abstract class Noise{
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $xSize
|
||||
* @param int $samplingRate
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
*
|
||||
* @return \SplFixedArray
|
||||
* @return \SplFixedArray|float[]
|
||||
* @phpstan-return \SplFixedArray<float>
|
||||
*/
|
||||
public function getFastNoise1D(int $xSize, int $samplingRate, int $x, int $y, int $z) : \SplFixedArray{
|
||||
if($samplingRate === 0){
|
||||
@ -181,14 +276,8 @@ abstract class Noise{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $xSize
|
||||
* @param int $zSize
|
||||
* @param int $samplingRate
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
*
|
||||
* @return \SplFixedArray
|
||||
* @return \SplFixedArray|float[][]
|
||||
* @phpstan-return \SplFixedArray<\SplFixedArray<float>>
|
||||
*/
|
||||
public function getFastNoise2D(int $xSize, int $zSize, int $samplingRate, int $x, int $y, int $z) : \SplFixedArray{
|
||||
assert($samplingRate !== 0, new \InvalidArgumentException("samplingRate cannot be 0"));
|
||||
@ -227,17 +316,7 @@ abstract class Noise{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $xSize
|
||||
* @param int $ySize
|
||||
* @param int $zSize
|
||||
* @param int $xSamplingRate
|
||||
* @param int $ySamplingRate
|
||||
* @param int $zSamplingRate
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $z
|
||||
*
|
||||
* @return array
|
||||
* @return float[][][]
|
||||
*/
|
||||
public function getFastNoise3D(int $xSize, int $ySize, int $zSize, int $xSamplingRate, int $ySamplingRate, int $zSamplingRate, int $x, int $y, int $z) : array{
|
||||
|
||||
@ -297,6 +376,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,13 +26,18 @@ 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],
|
||||
[0, 1, 1], [0, -1, 1], [0, 1, -1], [0, -1, -1]
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* @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 +149,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,15 @@ 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 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 +104,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 +264,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,11 +55,14 @@ class Normal extends Generator{
|
||||
/** @var BiomeSelector */
|
||||
private $selector;
|
||||
|
||||
/** @var float[][]|null */
|
||||
private static $GAUSSIAN_KERNEL = null;
|
||||
/** @var int */
|
||||
private static $SMOOTH_SIZE = 2;
|
||||
|
||||
/**
|
||||
* @param array $options
|
||||
* @param mixed[] $options
|
||||
* @phpstan-param array<string, mixed> $options
|
||||
*
|
||||
* @throws InvalidGeneratorOptionsException
|
||||
*/
|
||||
|
@ -26,60 +26,19 @@ 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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,9 @@ class BirchTree extends Tree{
|
||||
$this->superBirch = $superBirch;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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,9 @@ class OakTree extends Tree{
|
||||
$this->type = Wood::OAK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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,9 @@ class Ore{
|
||||
return $level->getBlockIdAt($x, $y, $z) === Block::STONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function placeObject(ChunkManager $level, int $x, int $y, int $z){
|
||||
$clusterSize = $this->type->clusterSize;
|
||||
$angle = $this->random->nextFloat() * M_PI;
|
||||
@ -72,24 +75,24 @@ class Ore{
|
||||
$endY = (int) ($seedY + $size);
|
||||
$endZ = (int) ($seedZ + $size);
|
||||
|
||||
for($x = $startX; $x <= $endX; ++$x){
|
||||
$sizeX = ($x + 0.5 - $seedX) / $size;
|
||||
for($xx = $startX; $xx <= $endX; ++$xx){
|
||||
$sizeX = ($xx + 0.5 - $seedX) / $size;
|
||||
$sizeX *= $sizeX;
|
||||
|
||||
if($sizeX < 1){
|
||||
for($y = $startY; $y <= $endY; ++$y){
|
||||
$sizeY = ($y + 0.5 - $seedY) / $size;
|
||||
for($yy = $startY; $yy <= $endY; ++$yy){
|
||||
$sizeY = ($yy + 0.5 - $seedY) / $size;
|
||||
$sizeY *= $sizeY;
|
||||
|
||||
if($y > 0 and ($sizeX + $sizeY) < 1){
|
||||
for($z = $startZ; $z <= $endZ; ++$z){
|
||||
$sizeZ = ($z + 0.5 - $seedZ) / $size;
|
||||
if($yy > 0 and ($sizeX + $sizeY) < 1){
|
||||
for($zz = $startZ; $zz <= $endZ; ++$zz){
|
||||
$sizeZ = ($zz + 0.5 - $seedZ) / $size;
|
||||
$sizeZ *= $sizeZ;
|
||||
|
||||
if(($sizeX + $sizeY + $sizeZ) < 1 and $level->getBlockIdAt($x, $y, $z) === Block::STONE){
|
||||
$level->setBlockIdAt($x, $y, $z, $this->type->material->getId());
|
||||
if(($sizeX + $sizeY + $sizeZ) < 1 and $level->getBlockIdAt($xx, $yy, $zz) === Block::STONE){
|
||||
$level->setBlockIdAt($xx, $yy, $zz, $this->type->material->getId());
|
||||
if($this->type->material->getDamage() !== 0){
|
||||
$level->setBlockDataAt($x, $y, $z, $this->type->material->getDamage());
|
||||
$level->setBlockDataAt($xx, $yy, $zz, $this->type->material->getDamage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,9 @@ class Pond{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function placeObject(ChunkManager $level, Vector3 $pos){
|
||||
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ declare(strict_types=1);
|
||||
*/
|
||||
namespace pocketmine\level\generator\object;
|
||||
|
||||
|
||||
abstract class PopulatorObject{
|
||||
|
||||
}
|
||||
|
@ -39,6 +39,9 @@ class SpruceTree extends Tree{
|
||||
$this->treeHeight = 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function placeObject(ChunkManager $level, int $x, int $y, int $z, Random $random){
|
||||
$this->treeHeight = $random->nextBoundedInt(4) + 6;
|
||||
|
||||
|
@ -31,6 +31,9 @@ use function count;
|
||||
|
||||
class TallGrass{
|
||||
|
||||
/**
|
||||
* @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,18 @@ 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;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public static function growTree(ChunkManager $level, int $x, int $y, int $z, Random $random, int $type = 0){
|
||||
switch($type){
|
||||
case Sapling::SPRUCE:
|
||||
@ -76,7 +84,6 @@ abstract class Tree{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function canPlaceObject(ChunkManager $level, int $x, int $y, int $z, Random $random) : bool{
|
||||
$radiusToCheck = 0;
|
||||
for($yy = 0; $yy < $this->treeHeight + 3; ++$yy){
|
||||
@ -95,6 +102,9 @@ abstract class Tree{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 +128,9 @@ abstract class Tree{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
@ -47,12 +47,13 @@ class GroundCover extends Populator{
|
||||
}
|
||||
|
||||
$column = $chunk->getBlockIdColumn($x, $z);
|
||||
for($y = 127; $y > 0; --$y){
|
||||
if($column[$y] !== "\x00" and !BlockFactory::get(ord($column[$y]))->isTransparent()){
|
||||
$startY = 127;
|
||||
for(; $startY > 0; --$startY){
|
||||
if($column[$startY] !== "\x00" and !BlockFactory::get(ord($column[$startY]))->isTransparent()){
|
||||
break;
|
||||
}
|
||||
}
|
||||
$startY = min(127, $y + $diffY);
|
||||
$startY = min(127, $startY + $diffY);
|
||||
$endY = $startY - count($cover);
|
||||
for($y = $startY; $y > $endY and $y >= 0; --$y){
|
||||
$b = $cover[$startY - $y];
|
||||
|
@ -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,23 @@ class Pond extends Populator{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setWaterOdd(int $waterOdd){
|
||||
$this->waterOdd = $waterOdd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setLavaOdd(int $lavaOdd){
|
||||
$this->lavaOdd = $lavaOdd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setLavaSurfaceOdd(int $lavaSurfaceOdd){
|
||||
$this->lavaSurfaceOdd = $lavaSurfaceOdd;
|
||||
}
|
||||
|
@ -32,11 +32,6 @@ use pocketmine\utils\Random;
|
||||
abstract class Populator{
|
||||
|
||||
/**
|
||||
* @param ChunkManager $level
|
||||
* @param int $chunkX
|
||||
* @param int $chunkZ
|
||||
* @param Random $random
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function populate(ChunkManager $level, int $chunkX, int $chunkZ, Random $random);
|
||||
|
@ -30,13 +30,25 @@ use pocketmine\utils\Random;
|
||||
class TallGrass extends Populator{
|
||||
/** @var ChunkManager */
|
||||
private $level;
|
||||
/** @var int */
|
||||
private $randomAmount = 1;
|
||||
/** @var int */
|
||||
private $baseAmount = 0;
|
||||
|
||||
/**
|
||||
* @param int $amount
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setRandomAmount($amount){
|
||||
$this->randomAmount = $amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $amount
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setBaseAmount($amount){
|
||||
$this->baseAmount = $amount;
|
||||
}
|
||||
@ -65,10 +77,10 @@ class TallGrass extends Populator{
|
||||
for($y = 127; $y >= 0; --$y){
|
||||
$b = $this->level->getBlockIdAt($x, $y, $z);
|
||||
if($b !== Block::AIR and $b !== Block::LEAVES and $b !== Block::LEAVES2 and $b !== Block::SNOW_LAYER){
|
||||
break;
|
||||
return $y + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return $y === 0 ? -1 : ++$y;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -32,19 +32,35 @@ use pocketmine\utils\Random;
|
||||
class Tree extends Populator{
|
||||
/** @var ChunkManager */
|
||||
private $level;
|
||||
/** @var int */
|
||||
private $randomAmount = 1;
|
||||
/** @var int */
|
||||
private $baseAmount = 0;
|
||||
|
||||
/** @var int */
|
||||
private $type;
|
||||
|
||||
/**
|
||||
* @param int $type
|
||||
*/
|
||||
public function __construct($type = Sapling::OAK){
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $amount
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setRandomAmount($amount){
|
||||
$this->randomAmount = $amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $amount
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setBaseAmount($amount){
|
||||
$this->baseAmount = $amount;
|
||||
}
|
||||
@ -64,15 +80,15 @@ class Tree extends Populator{
|
||||
}
|
||||
|
||||
private function getHighestWorkableBlock(int $x, int $z) : int{
|
||||
for($y = 127; $y > 0; --$y){
|
||||
for($y = 127; $y >= 0; --$y){
|
||||
$b = $this->level->getBlockIdAt($x, $y, $z);
|
||||
if($b === Block::DIRT or $b === Block::GRASS){
|
||||
break;
|
||||
return $y + 1;
|
||||
}elseif($b !== Block::AIR and $b !== Block::SNOW_LAYER){
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return ++$y;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,9 @@ use pocketmine\Server;
|
||||
|
||||
class LightPopulationTask extends AsyncTask{
|
||||
|
||||
/** @var int */
|
||||
public $levelId;
|
||||
/** @var string */
|
||||
public $chunk;
|
||||
|
||||
public function __construct(Level $level, Chunk $chunk){
|
||||
|
@ -59,8 +59,14 @@ abstract class LightUpdate{
|
||||
|
||||
abstract protected function getLight(int $x, int $y, int $z) : int;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
abstract protected function setLight(int $x, int $y, int $z, int $level);
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setAndUpdateLight(int $x, int $y, int $z, int $newLevel){
|
||||
$this->updateNodes[Level::blockHash($x, $y, $z)] = [$x, $y, $z, $newLevel];
|
||||
}
|
||||
@ -84,6 +90,9 @@ abstract class LightUpdate{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function execute(){
|
||||
$this->prepareNodes();
|
||||
|
||||
@ -137,6 +146,9 @@ abstract class LightUpdate{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function computeRemoveLight(int $x, int $y, int $z, int $oldAdjacentLevel){
|
||||
$current = $this->getLight($x, $y, $z);
|
||||
|
||||
@ -157,6 +169,9 @@ abstract class LightUpdate{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function computeSpreadLight(int $x, int $y, int $z, int $newAdjacentLevel){
|
||||
$current = $this->getLight($x, $y, $z);
|
||||
$potentialLight = $newAdjacentLevel - BlockFactory::$lightFilter[$this->subChunkHandler->currentSubChunk->getBlockId($x & 0x0f, $y & 0x0f, $z & 0x0f)];
|
||||
|
@ -39,16 +39,15 @@ use function str_repeat;
|
||||
class FloatingTextParticle extends Particle{
|
||||
//TODO: HACK!
|
||||
|
||||
/** @var string */
|
||||
protected $text;
|
||||
/** @var string */
|
||||
protected $title;
|
||||
protected $entityId;
|
||||
/** @var int|null */
|
||||
protected $entityId = null;
|
||||
/** @var bool */
|
||||
protected $invisible = false;
|
||||
|
||||
/**
|
||||
* @param Vector3 $pos
|
||||
* @param string $text
|
||||
* @param string $title
|
||||
*/
|
||||
public function __construct(Vector3 $pos, string $text, string $title = ""){
|
||||
parent::__construct($pos->x, $pos->y, $pos->z);
|
||||
$this->text = $text;
|
||||
|
@ -29,7 +29,7 @@ use pocketmine\network\mcpe\protocol\DataPacket;
|
||||
abstract class Particle extends Vector3{
|
||||
|
||||
public const TYPE_BUBBLE = 1;
|
||||
//2 same as 1
|
||||
public const TYPE_BUBBLE_MANUAL = 2;
|
||||
public const TYPE_CRITICAL = 3;
|
||||
public const TYPE_BLOCK_FORCE_FIELD = 4;
|
||||
public const TYPE_SMOKE = 5;
|
||||
@ -40,56 +40,61 @@ abstract class Particle extends Vector3{
|
||||
public const TYPE_LARGE_SMOKE = 10;
|
||||
public const TYPE_REDSTONE = 11;
|
||||
public const TYPE_RISING_RED_DUST = 12;
|
||||
//62 same as 12
|
||||
public const TYPE_ITEM_BREAK = 13;
|
||||
public const TYPE_SNOWBALL_POOF = 14;
|
||||
public const TYPE_HUGE_EXPLODE = 15;
|
||||
//60 same as 15
|
||||
public const TYPE_HUGE_EXPLODE_SEED = 16;
|
||||
public const TYPE_MOB_FLAME = 17;
|
||||
public const TYPE_HEART = 18;
|
||||
public const TYPE_TERRAIN = 19;
|
||||
public const TYPE_SUSPENDED_TOWN = 20, TYPE_TOWN_AURA = 20;
|
||||
//61 same as 20
|
||||
public const TYPE_PORTAL = 21;
|
||||
//22 same as 21
|
||||
public const TYPE_SPLASH = 23, TYPE_WATER_SPLASH = 23;
|
||||
//24 same as 23
|
||||
public const TYPE_WATER_SPLASH_MANUAL = 24;
|
||||
public const TYPE_WATER_WAKE = 25;
|
||||
public const TYPE_DRIP_WATER = 26;
|
||||
public const TYPE_DRIP_LAVA = 27;
|
||||
public const TYPE_FALLING_DUST = 28, TYPE_DUST = 28;
|
||||
public const TYPE_MOB_SPELL = 29;
|
||||
public const TYPE_MOB_SPELL_AMBIENT = 30;
|
||||
public const TYPE_MOB_SPELL_INSTANTANEOUS = 31;
|
||||
public const TYPE_INK = 32;
|
||||
public const TYPE_SLIME = 33;
|
||||
public const TYPE_RAIN_SPLASH = 34;
|
||||
public const TYPE_VILLAGER_ANGRY = 35;
|
||||
//59 same as 35
|
||||
public const TYPE_VILLAGER_HAPPY = 36;
|
||||
public const TYPE_ENCHANTMENT_TABLE = 37;
|
||||
public const TYPE_TRACKING_EMITTER = 38;
|
||||
public const TYPE_NOTE = 39;
|
||||
public const TYPE_WITCH_SPELL = 40;
|
||||
public const TYPE_CARROT = 41;
|
||||
//42 unknown
|
||||
public const TYPE_END_ROD = 43;
|
||||
//58 same as 43
|
||||
public const TYPE_DRAGONS_BREATH = 44;
|
||||
public const TYPE_SPIT = 45;
|
||||
public const TYPE_TOTEM = 46;
|
||||
public const TYPE_FOOD = 47;
|
||||
public const TYPE_FIREWORKS_STARTER = 48;
|
||||
public const TYPE_FIREWORKS_SPARK = 49;
|
||||
public const TYPE_FIREWORKS_OVERLAY = 50;
|
||||
public const TYPE_BALLOON_GAS = 51;
|
||||
public const TYPE_COLORED_FLAME = 52;
|
||||
public const TYPE_SPARKLER = 53;
|
||||
public const TYPE_CONDUIT = 54;
|
||||
public const TYPE_BUBBLE_COLUMN_UP = 55;
|
||||
public const TYPE_BUBBLE_COLUMN_DOWN = 56;
|
||||
public const TYPE_SNEEZE = 57;
|
||||
public const TYPE_DRIP_HONEY = 28;
|
||||
public const TYPE_FALLING_DUST = 29, TYPE_DUST = 29;
|
||||
public const TYPE_MOB_SPELL = 30;
|
||||
public const TYPE_MOB_SPELL_AMBIENT = 31;
|
||||
public const TYPE_MOB_SPELL_INSTANTANEOUS = 32;
|
||||
public const TYPE_INK = 33;
|
||||
public const TYPE_SLIME = 34;
|
||||
public const TYPE_RAIN_SPLASH = 35;
|
||||
public const TYPE_VILLAGER_ANGRY = 36;
|
||||
public const TYPE_VILLAGER_HAPPY = 37;
|
||||
public const TYPE_ENCHANTMENT_TABLE = 38;
|
||||
public const TYPE_TRACKING_EMITTER = 39;
|
||||
public const TYPE_NOTE = 40;
|
||||
public const TYPE_WITCH_SPELL = 41;
|
||||
public const TYPE_CARROT = 42;
|
||||
public const TYPE_MOB_APPEARANCE = 43;
|
||||
public const TYPE_END_ROD = 44;
|
||||
public const TYPE_DRAGONS_BREATH = 45;
|
||||
public const TYPE_SPIT = 46;
|
||||
public const TYPE_TOTEM = 47;
|
||||
public const TYPE_FOOD = 48;
|
||||
public const TYPE_FIREWORKS_STARTER = 49;
|
||||
public const TYPE_FIREWORKS_SPARK = 50;
|
||||
public const TYPE_FIREWORKS_OVERLAY = 51;
|
||||
public const TYPE_BALLOON_GAS = 52;
|
||||
public const TYPE_COLORED_FLAME = 53;
|
||||
public const TYPE_SPARKLER = 54;
|
||||
public const TYPE_CONDUIT = 55;
|
||||
public const TYPE_BUBBLE_COLUMN_UP = 56;
|
||||
public const TYPE_BUBBLE_COLUMN_DOWN = 57;
|
||||
public const TYPE_SNEEZE = 58;
|
||||
public const TYPE_SHULKER_BULLET = 59;
|
||||
public const TYPE_BLEACH = 60;
|
||||
public const TYPE_DRAGON_DESTROY_BLOCK = 61;
|
||||
public const TYPE_MYCELIUM_DUST = 62;
|
||||
public const TYPE_FALLING_RED_DUST = 63;
|
||||
public const TYPE_CAMPFIRE_SMOKE = 64;
|
||||
public const TYPE_TALL_CAMPFIRE_SMOKE = 65;
|
||||
public const TYPE_DRAGON_BREATH_FIRE = 66;
|
||||
public const TYPE_DRAGON_BREATH_TRAIL = 67;
|
||||
|
||||
/**
|
||||
* @return DataPacket|DataPacket[]
|
||||
|
Reference in New Issue
Block a user