GenisysPro  for Minecraft PE/Windows 10 v1.1.x
Feature-rich server software for Minecraft PE and Windows 10 Edition
Level Class Reference

Public Member Functions

 setBlockTempData (Vector3 $pos, $data=null)
 
 getBlockTempData (Vector3 $pos)
 
 setDimension (int $dimension)
 
 getDimension ()
 
 getWeather ()
 
 getTickRate ()
 
 getTickRateTime ()
 
 setTickRate (int $tickRate)
 
 initLevel ()
 
 getWaterHeight ()
 
 registerGenerator ()
 
 unregisterGenerator ()
 
 getBlockMetadata ()
 
 getServer ()
 
 getProvider ()
 
 getId ()
 
 isClosed ()
 
 close ()
 
 addSound (Sound $sound, array $players=null)
 
 addParticle (Particle $particle, array $players=null)
 
 broadcastLevelEvent (Vector3 $pos, int $evid, int $data=0)
 
 broadcastLevelSoundEvent (Vector3 $pos, int $soundId, int $pitch=1, int $extraData=-1)
 
 getAutoSave ()
 
 setAutoSave (bool $value)
 
 unload (bool $force=false)
 
 getChunkPlayers (int $chunkX, int $chunkZ)
 
 getChunkLoaders (int $chunkX, int $chunkZ)
 
 addChunkPacket (int $chunkX, int $chunkZ, DataPacket $packet)
 
 registerChunkLoader (ChunkLoader $loader, int $chunkX, int $chunkZ, bool $autoLoad=true)
 
 unregisterChunkLoader (ChunkLoader $loader, int $chunkX, int $chunkZ)
 
 checkTime ()
 
 sendTime ()
 
 doTick (int $currentTick)
 
 checkSleep ()
 
 sendBlockExtraData (int $x, int $y, int $z, int $id, int $data, array $targets=null)
 
 sendBlocks (array $target, array $blocks, $flags=UpdateBlockPacket::FLAG_NONE, bool $optimizeRebuilds=false)
 
 clearCache (bool $full=false)
 
 clearChunkCache (int $chunkX, int $chunkZ)
 
 __debugInfo ()
 
 save (bool $force=false)
 
 saveChunks ()
 
 updateAround (Vector3 $pos)
 
 scheduleUpdate (Vector3 $pos, int $delay)
 
 getCollisionBlocks (AxisAlignedBB $bb, bool $targetFirst=false)
 
 isFullBlock (Vector3 $pos)
 
 getCollisionCubes (Entity $entity, AxisAlignedBB $bb, bool $entities=true)
 
 getFullLight (Vector3 $pos)
 
 getFullBlock (int $x, int $y, int $z)
 
 getBlock (Vector3 $pos, $cached=true)
 
 updateAllLight (Vector3 $pos)
 
 updateBlockSkyLight (int $x, int $y, int $z)
 
 getHighestAdjacentBlockLight (int $x, int $y, int $z)
 
 updateBlockLight (int $x, int $y, int $z)
 
 setBlock (Vector3 $pos, Block $block, bool $direct=false, bool $update=true)
 
 dropItem (Vector3 $source, Item $item, Vector3 $motion=null, int $delay=10)
 
 useBreakOn (Vector3 $vector, Item &$item=null, Player $player=null, bool $createParticles=false)
 
 useItemOn (Vector3 $vector, Item &$item, int $face, float $fx=0.0, float $fy=0.0, float $fz=0.0, Player $player=null)
 
 getEntity (int $entityId)
 
 getEntities ()
 
 getCollidingEntities (AxisAlignedBB $bb, Entity $entity=null)
 
 getNearbyEntities (AxisAlignedBB $bb, Entity $entity=null)
 
 getNearbyExperienceOrb (AxisAlignedBB $bb)
 
 getTiles ()
 
 getTileById (int $tileId)
 
 getPlayers ()
 
 getLoaders ()
 
 getTile (Vector3 $pos)
 
 getChunkEntities ($X, $Z)
 
 getChunkTiles ($X, $Z)
 
 getBlockIdAt (int $x, int $y, int $z)
 
 setBlockIdAt (int $x, int $y, int $z, int $id)
 
 getBlockExtraDataAt (int $x, int $y, int $z)
 
 setBlockExtraDataAt (int $x, int $y, int $z, int $id, int $data)
 
 getBlockDataAt (int $x, int $y, int $z)
 
 setBlockDataAt (int $x, int $y, int $z, int $data)
 
 getBlockSkyLightAt (int $x, int $y, int $z)
 
 setBlockSkyLightAt (int $x, int $y, int $z, int $level)
 
 getBlockLightAt (int $x, int $y, int $z)
 
 setBlockLightAt (int $x, int $y, int $z, int $level)
 
 getBiomeId (int $x, int $z)
 
 getHeightMap (int $x, int $z)
 
 setBiomeId (int $x, int $z, int $biomeId)
 
 setHeightMap (int $x, int $z, int $value)
 
 getChunks ()
 
 getChunk (int $x, int $z, bool $create=false)
 
 getAdjacentChunks (int $x, int $z)
 
 generateChunkCallback (int $x, int $z, Chunk $chunk)
 
 setChunk (int $chunkX, int $chunkZ, Chunk $chunk=null, bool $unload=true)
 
 sendLighting (int $x, int $y, int $z, Player $p)
 
 spawnLightning (Vector3 $pos)
 
 spawnXPOrb (Vector3 $pos, int $exp=1)
 
 getHighestBlockAt (int $x, int $z)
 
 canBlockSeeSky (Vector3 $pos)
 
 isChunkLoaded (int $x, int $z)
 
 isChunkGenerated (int $x, int $z)
 
 isChunkPopulated (int $x, int $z)
 
 getSpawnLocation ()
 
 setSpawnLocation (Vector3 $pos)
 
 requestChunk (int $x, int $z, Player $player)
 
 removeEntity (Entity $entity)
 
 addEntity (Entity $entity)
 
 addTile (Tile $tile)
 
 removeTile (Tile $tile)
 
 isChunkInUse (int $x, int $z)
 
 loadChunk (int $x, int $z, bool $generate=true)
 
 unloadChunkRequest (int $x, int $z, bool $safe=true)
 
 cancelUnloadChunkRequest (int $x, int $z)
 
 unloadChunk (int $x, int $z, bool $safe=true, bool $trySave=true)
 
 isSpawnChunk (int $X, int $Z)
 
 getSafeSpawn ($spawn=null)
 
 getTime ()
 
 getName ()
 
 getFolderName ()
 
 setTime (int $time)
 
 stopTime ()
 
 startTime ()
 
 getSeed ()
 
 setSeed (int $seed)
 
 populateChunk (int $x, int $z, bool $force=false)
 
 generateChunk (int $x, int $z, bool $force=false)
 
 regenerateChunk (int $x, int $z)
 
 doChunkGarbageCollection ()
 
 unloadChunks (bool $force=false)
 
 setMetadata ($metadataKey, MetadataValue $metadataValue)
 
 getMetadata ($metadataKey)
 
 hasMetadata ($metadataKey)
 
 removeMetadata ($metadataKey, Plugin $plugin)
 
 addEntityMotion (int $chunkX, int $chunkZ, int $entityId, float $x, float $y, float $z)
 
 addEntityMovement (int $chunkX, int $chunkZ, int $entityId, float $x, float $y, float $z, float $yaw, float $pitch, $headYaw=null)
 
- Public Member Functions inherited from ChunkManager
 getChunk (int $chunkX, int $chunkZ)
 
 setChunk (int $chunkX, int $chunkZ, Chunk $chunk=null)
 

Static Public Member Functions

static chunkHash (int $x, int $z)
 
static blockHash (int $x, int $y, int $z)
 
static getBlockXYZ ($hash, &$x, &$y, &$z)
 
static getXZ ($hash, &$x, &$z)
 
static generateChunkLoaderId (ChunkLoader $loader)
 
static getChunkCacheFromData ($chunkX, $chunkZ, $payload)
 

Data Fields

const Y_MASK = 0xFF
 
const Y_MAX = 0x100
 
const BLOCK_UPDATE_NORMAL = 1
 
const BLOCK_UPDATE_RANDOM = 2
 
const BLOCK_UPDATE_SCHEDULED = 3
 
const BLOCK_UPDATE_WEAK = 4
 
const BLOCK_UPDATE_TOUCH = 5
 
const TIME_DAY = 0
 
const TIME_SUNSET = 12000
 
const TIME_NIGHT = 14000
 
const TIME_SUNRISE = 23000
 
const TIME_FULL = 24000
 
const DIMENSION_NORMAL = 0
 
const DIMENSION_NETHER = 1
 
const DIMENSION_END = 2
 
 $updateEntities = []
 
 $updateTiles = []
 
 $stopTime
 
 $sleepTicks = 0
 
 $timings
 
 $tickRateTime = 0
 
 $tickRateCounter = 0
 

Static Public Attributes

static $COMPRESSION_LEVEL = 8
 

Member Function Documentation

◆ __debugInfo()

__debugInfo ( )
1075  : array {
1076  return [];
1077  }

◆ addChunkPacket()

addChunkPacket ( int  $chunkX,
int  $chunkZ,
DataPacket  $packet 
)
676  {
677  if (!isset($this->chunkPackets[$index = Level::chunkHash($chunkX, $chunkZ)])) {
678  $this->chunkPackets[$index] = [$packet];
679  } else {
680  $this->chunkPackets[$index][] = $packet;
681  }
682  }

◆ addEntity()

addEntity ( Entity  $entity)
Parameters
Entity$entity
Exceptions
LevelException
2666  {
2667  if ($entity->getLevel() !== $this) {
2668  throw new LevelException("Invalid Entity level");
2669  }
2670  if ($entity instanceof Player) {
2671  $this->players[$entity->getId()] = $entity;
2672  }
2673  $this->entities[$entity->getId()] = $entity;
2674  }

◆ addEntityMotion()

addEntityMotion ( int  $chunkX,
int  $chunkZ,
int  $entityId,
float  $x,
float  $y,
float  $z 
)
3132  {
3133  if (!isset($this->motionToSend[$index = Level::chunkHash($chunkX, $chunkZ)])) {
3134  $this->motionToSend[$index] = [];
3135  }
3136  $this->motionToSend[$index][$entityId] = [$entityId, $x, $y, $z];
3137  }

◆ addEntityMovement()

addEntityMovement ( int  $chunkX,
int  $chunkZ,
int  $entityId,
float  $x,
float  $y,
float  $z,
float  $yaw,
float  $pitch,
  $headYaw = null 
)
3139  {
3140  if (!isset($this->moveToSend[$index = Level::chunkHash($chunkX, $chunkZ)])) {
3141  $this->moveToSend[$index] = [];
3142  }
3143  $this->moveToSend[$index][$entityId] = [$entityId, $x, $y, $z, $yaw, $headYaw === null ? $yaw : $headYaw, $pitch];
3144  }

◆ addParticle()

addParticle ( Particle  $particle,
array  $players = null 
)
557  {
558  $pk = $particle->encode();
559 
560  if ($players === null) {
561  if ($pk !== null) {
562  if (!is_array($pk)) {
563  $this->addChunkPacket($particle->x >> 4, $particle->z >> 4, $pk);
564  } else {
565  foreach ($pk as $e) {
566  $this->addChunkPacket($particle->x >> 4, $particle->z >> 4, $e);
567  }
568  }
569  }
570  } else {
571  if ($pk !== null) {
572  if (!is_array($pk)) {
573  $this->server->broadcastPacket($players, $pk);
574  } else {
575  $this->server->batchPackets($players, $pk, false);
576  }
577  }
578  }
579  }

◆ addSound()

addSound ( Sound  $sound,
array  $players = null 
)
533  {
534  $pk = $sound->encode();
535 
536  if ($players === null) {
537  if ($pk !== null) {
538  if (!is_array($pk)) {
539  $this->addChunkPacket($sound->x >> 4, $sound->z >> 4, $pk);
540  } else {
541  foreach ($pk as $e) {
542  $this->addChunkPacket($sound->x >> 4, $sound->z >> 4, $e);
543  }
544  }
545  }
546  } else {
547  if ($pk !== null) {
548  if (!is_array($pk)) {
549  $this->server->broadcastPacket($players, $pk);
550  } else {
551  $this->server->batchPackets($players, $pk, false);
552  }
553  }
554  }
555  }

◆ addTile()

addTile ( Tile  $tile)
Parameters
Tile$tile
Exceptions
LevelException
2681  {
2682  if ($tile->getLevel() !== $this) {
2683  throw new LevelException("Invalid Tile level");
2684  }
2685  $this->tiles[$tile->getId()] = $tile;
2686  $this->clearChunkCache($tile->getX() >> 4, $tile->getZ() >> 4);
2687  }

◆ blockHash()

static blockHash ( int  $x,
int  $y,
int  $z 
)
static
327  {
328  return PHP_INT_SIZE === 8 ? (($x & 0xFFFFFFF) << 36) | (($y & Level::Y_MASK) << 28) | ($z & 0xFFFFFFF) : $x . ":" . $y . ":" . $z;
329  }

◆ broadcastLevelEvent()

broadcastLevelEvent ( Vector3  $pos,
int  $evid,
int  $data = 0 
)
581  {
582  $pk = new LevelEventPacket();
583  $pk->evid = $evid;
584  $pk->data = $data;
585  list($pk->x, $pk->y, $pk->z) = [$pos->x, $pos->y, $pos->z];
586  $this->addChunkPacket($pos->x >> 4, $pos->z >> 4, $pk);
587  }

◆ broadcastLevelSoundEvent()

broadcastLevelSoundEvent ( Vector3  $pos,
int  $soundId,
int  $pitch = 1,
int  $extraData = -1 
)
589  {
590  $pk = new LevelSoundEventPacket();
591  $pk->sound = $soundId;
592  $pk->pitch = $pitch;
593  $pk->extraData = $extraData;
594  list($pk->x, $pk->y, $pk->z) = [$pos->x, $pos->y, $pos->z];
595  $this->addChunkPacket($pos->x >> 4, $pos->z >> 4, $pk);
596  }

◆ canBlockSeeSky()

canBlockSeeSky ( Vector3  $pos)
2507  : bool {
2508  return $this->getHighestBlockAt($pos->getFloorX(), $pos->getFloorZ()) < $pos->getY();
2509  }

◆ cancelUnloadChunkRequest()

cancelUnloadChunkRequest ( int  $x,
int  $z 
)
2775  {
2776  unset($this->unloadQueue[Level::chunkHash($x, $z)]);
2777  }

◆ checkSleep()

checkSleep ( )
884  {
885  if (count($this->players) === 0) {
886  return;
887  }
888 
889  $resetTime = true;
890  foreach ($this->getPlayers() as $p) {
891  if (!$p->isSleeping()) {
892  $resetTime = false;
893  break;
894  }
895  }
896 
897  if ($resetTime) {
898  $time = $this->getTime() % Level::TIME_FULL;
899 
900  if ($time >= Level::TIME_NIGHT and $time < Level::TIME_SUNRISE) {
901  $this->setTime($this->getTime() + Level::TIME_FULL - $time);
902 
903  foreach ($this->getPlayers() as $p) {
904  $p->stopSleep();
905  }
906  }
907  }
908  }

◆ checkTime()

checkTime ( )

WARNING: Do not use this, it's only for internal use. Changes to this function won't be recorded on the version.

734  {
735  if ($this->stopTime == true) {
736  return;
737  } else {
738  $this->time += 1;
739  }
740  }

◆ chunkHash()

static chunkHash ( int  $x,
int  $z 
)
static

Returns the chunk unique hash/key

Parameters
int$x
int$z
Returns
string
323  {
324  return PHP_INT_SIZE === 8 ? (($x & 0xFFFFFFFF) << 32) | ($z & 0xFFFFFFFF) : $x . ":" . $z;
325  }

◆ clearCache()

clearCache ( bool  $full = false)
982  {
983  if ($full) {
984  $this->chunkCache = [];
985  $this->blockCache = [];
986  } else {
987  if (count($this->chunkCache) > 768) {
988  $this->chunkCache = [];
989  }
990 
991  if (count($this->blockCache) > 2048) {
992  $this->blockCache = [];
993  }
994 
995  }
996 
997  }

◆ clearChunkCache()

clearChunkCache ( int  $chunkX,
int  $chunkZ 
)
999  {
1000  unset($this->chunkCache[Level::chunkHash($chunkX, $chunkZ)]);
1001  }

◆ close()

close ( )
511  {
512  assert(!$this->closed, "Tried to close a level which is already closed");
513 
514  if ($this->getAutoSave()) {
515  $this->save();
516  }
517 
518  foreach ($this->chunks as $chunk) {
519  $this->unloadChunk($chunk->getX(), $chunk->getZ(), false);
520  }
521 
522  $this->unregisterGenerator();
523 
524  $this->provider->close();
525  $this->provider = null;
526  $this->blockMetadata = null;
527  $this->blockCache = [];
528  $this->temporalPosition = null;
529 
530  $this->closed = true;
531  }

◆ doChunkGarbageCollection()

doChunkGarbageCollection ( )
3045  {
3046  $this->timings->doChunkGC->startTiming();
3047 
3048  $X = null;
3049  $Z = null;
3050 
3051  foreach ($this->chunks as $index => $chunk) {
3052  if (!isset($this->unloadQueue[$index])) {
3053  Level::getXZ($index, $X, $Z);
3054  if (!$this->isSpawnChunk($X, $Z)) {
3055  $this->unloadChunkRequest($X, $Z, true);
3056  }
3057  }
3058  }
3059 
3060  foreach ($this->provider->getLoadedChunks() as $chunk) {
3061  if (!isset($this->chunks[Level::chunkHash($chunk->getX(), $chunk->getZ())])) {
3062  $this->provider->unloadChunk($chunk->getX(), $chunk->getZ(), false);
3063  }
3064  }
3065 
3066  $this->provider->doGarbageCollection();
3067 
3068  $this->timings->doChunkGC->stopTiming();
3069  }

◆ doTick()

doTick ( int  $currentTick)

WARNING: Do not use this, it's only for internal use. Changes to this function won't be recorded on the version.

Parameters
int$currentTick
760  {
761 
762  $this->timings->doTick->startTiming();
763 
764  $this->checkTime();
765 
766  if (++$this->sendTimeTicker === 280) {
767  $this->sendTime();
768  $this->sendTimeTicker = 0;
769  }
770 
771  $this->weather->calcWeather($currentTick);
772 
773  $this->unloadChunks();
774 
775  //Do block updates
776  $this->timings->doTickPending->startTiming();
777  if ($this->updateQueue->count() > 0 and $this->updateQueue->current()["priority"] <= $currentTick) {
778  $block = $this->getBlock($this->updateQueue->extract()["data"]);
779  unset($this->updateQueueIndex[Level::blockHash($block->x, $block->y, $block->z)]);
780  $block->onUpdate(self::BLOCK_UPDATE_SCHEDULED);
781  }
782  $this->timings->doTickPending->stopTiming();
783 
784  $this->timings->entityTick->startTiming();
785  //Update entities that need update
786  Timings::$tickEntityTimer->startTiming();
787  foreach ($this->updateEntities as $id => $entity) {
788  if ($entity->closed or !$entity->onUpdate($currentTick)) {
789  unset($this->updateEntities[$id]);
790  }
791  }
792  Timings::$tickEntityTimer->stopTiming();
793  $this->timings->entityTick->stopTiming();
794 
795  $this->timings->tileEntityTick->startTiming();
796  Timings::$tickTileEntityTimer->startTiming();
797  //Update tiles that need update
798  if (count($this->updateTiles) > 0) {
799  foreach ($this->updateTiles as $id => $tile) {
800  if ($tile->onUpdate() !== true) {
801  unset($this->updateTiles[$id]);
802  }
803  }
804  }
805  Timings::$tickTileEntityTimer->stopTiming();
806  $this->timings->tileEntityTick->stopTiming();
807 
808  $this->timings->doTickTiles->startTiming();
809  if (($currentTick % 2) === 0) $this->tickChunks();
810  $this->timings->doTickTiles->stopTiming();
811 
812  if (count($this->changedBlocks) > 0) {
813  if (count($this->players) > 0) {
814  foreach ($this->changedBlocks as $index => $blocks) {
815  unset($this->chunkCache[$index]);
816  Level::getXZ($index, $chunkX, $chunkZ);
817  if (count($blocks) > 512) {
818  $chunk = $this->getChunk($chunkX, $chunkZ);
819  foreach ($this->getChunkPlayers($chunkX, $chunkZ) as $p) {
820  $p->onChunkChanged($chunk);
821  }
822  } else {
823  $this->sendBlocks($this->getChunkPlayers($chunkX, $chunkZ), $blocks, UpdateBlockPacket::FLAG_ALL);
824  }
825  }
826  } else {
827  $this->chunkCache = [];
828  }
829 
830  $this->changedBlocks = [];
831 
832  }
833 
834  $this->processChunkRequest();
835 
836  if ($this->sleepTicks > 0 and --$this->sleepTicks <= 0) {
837  $this->checkSleep();
838  }
839 
840  foreach ($this->moveToSend as $index => $entry) {
841  Level::getXZ($index, $chunkX, $chunkZ);
842  foreach ($entry as $e) {
843  $pk = new MoveEntityPacket();
844  $pk->eid = $e[0];
845  $pk->x = $e[1];
846  $pk->y = $e[2];
847  $pk->z = $e[3];
848  $pk->yaw = $e[4];
849  $pk->headYaw = $e[5];
850  $pk->pitch = $e[6];
851  $this->addChunkPacket($chunkX, $chunkZ, $pk);
852  }
853  }
854  $this->moveToSend = [];
855 
856  foreach ($this->motionToSend as $index => $entry) {
857  Level::getXZ($index, $chunkX, $chunkZ);
858  foreach ($entry as $entity) {
859  $pk = new SetEntityMotionPacket();
860  $pk->eid = $entity[0];
861  $pk->motionX = $entity[1];
862  $pk->motionY = $entity[2];
863  $pk->motionZ = $entity[3];
864  $this->addChunkPacket($chunkX, $chunkZ, $pk);
865  }
866  }
867  $this->motionToSend = [];
868 
869  foreach ($this->chunkPackets as $index => $entries) {
870  Level::getXZ($index, $chunkX, $chunkZ);
871  $chunkPlayers = $this->getChunkPlayers($chunkX, $chunkZ);
872  if (count($chunkPlayers) > 0) {
873  foreach ($entries as $pk) {
874  $this->server->broadcastPacket($chunkPlayers, $pk);
875  }
876  }
877  }
878 
879  $this->chunkPackets = [];
880 
881  $this->timings->doTick->stopTiming();
882  }

◆ dropItem()

dropItem ( Vector3  $source,
Item  $item,
Vector3  $motion = null,
int  $delay = 10 
)
Parameters
Vector3$source
Item$item
Vector3$motion
int$delay
Returns
null|Entity|DroppedItem|
1561  {
1562  $motion = $motion === null ? new Vector3(lcg_value() * 0.2 - 0.1, 0.2, lcg_value() * 0.2 - 0.1) : $motion;
1563 
1564  if ($item->getId() > 0 and $item->getCount() > 0) {
1565  $itemEntity = Entity::createEntity("Item", $this, new CompoundTag("", [
1566  "Pos" => new ListTag("Pos", [
1567  new DoubleTag("", $source->getX()),
1568  new DoubleTag("", $source->getY()),
1569  new DoubleTag("", $source->getZ())
1570  ]),
1571 
1572  "Motion" => new ListTag("Motion", [
1573  new DoubleTag("", $motion->x),
1574  new DoubleTag("", $motion->y),
1575  new DoubleTag("", $motion->z)
1576  ]),
1577  "Rotation" => new ListTag("Rotation", [
1578  new FloatTag("", lcg_value() * 360),
1579  new FloatTag("", 0)
1580  ]),
1581  "Health" => new ShortTag("Health", 5),
1582  "Item" => $item->nbtSerialize(-1, "Item"),
1583  "PickupDelay" => new ShortTag("PickupDelay", $delay)
1584  ]));
1585 
1586  $itemEntity->spawnToAll();
1587 
1588  return $itemEntity;
1589  }
1590 
1591  return null;
1592  }

◆ generateChunk()

generateChunk ( int  $x,
int  $z,
bool  $force = false 
)
3022  {
3023  if (count($this->chunkGenerationQueue) >= $this->chunkGenerationQueueSize and !$force) {
3024  return;
3025  }
3026 
3027  if (!isset($this->chunkGenerationQueue[$index = Level::chunkHash($x, $z)])) {
3028  Timings::$generationTimer->startTiming();
3029  $this->chunkGenerationQueue[$index] = true;
3030  $task = new GenerationTask($this, $this->getChunk($x, $z, true));
3031  $this->server->getScheduler()->scheduleAsyncTask($task);
3032  Timings::$generationTimer->stopTiming();
3033  }
3034  }

◆ generateChunkCallback()

generateChunkCallback ( int  $x,
int  $z,
Chunk  $chunk 
)
2333  {
2334  Timings::$generationCallbackTimer->startTiming();
2335  if (isset($this->chunkPopulationQueue[$index = Level::chunkHash($x, $z)])) {
2336  $oldChunk = $this->getChunk($x, $z, false);
2337  for ($xx = -1; $xx <= 1; ++$xx) {
2338  for ($zz = -1; $zz <= 1; ++$zz) {
2339  unset($this->chunkPopulationLock[Level::chunkHash($x + $xx, $z + $zz)]);
2340  }
2341  }
2342  unset($this->chunkPopulationQueue[$index]);
2343  $this->setChunk($x, $z, $chunk, false);
2344  $chunk = $this->getChunk($x, $z, false);
2345  if ($chunk !== null and ($oldChunk === null or $oldChunk->isPopulated() === false) and $chunk->isPopulated()) {
2346  $this->server->getPluginManager()->callEvent(new ChunkPopulateEvent($this, $chunk));
2347 
2348  foreach ($this->getChunkLoaders($x, $z) as $loader) {
2349  $loader->onChunkPopulated($chunk);
2350  }
2351  }
2352  } elseif (isset($this->chunkGenerationQueue[$index]) or isset($this->chunkPopulationLock[$index])) {
2353  unset($this->chunkGenerationQueue[$index]);
2354  unset($this->chunkPopulationLock[$index]);
2355  $this->setChunk($x, $z, $chunk, false);
2356  } else {
2357  $this->setChunk($x, $z, $chunk, false);
2358  }
2359  Timings::$generationCallbackTimer->stopTiming();
2360  }

◆ generateChunkLoaderId()

static generateChunkLoaderId ( ChunkLoader  $loader)
static
355  : int {
356  if ($loader->getLoaderId() === 0 or $loader->getLoaderId() === null or $loader->getLoaderId() === null) {
357  return self::$chunkLoaderCounter++;
358  } else {
359  throw new \InvalidStateException("ChunkLoader has a loader id already assigned: " . $loader->getLoaderId());
360  }
361  }

◆ getAdjacentChunks()

getAdjacentChunks ( int  $x,
int  $z 
)

Returns the chunks adjacent to the specified chunk.

Parameters
int$x
int$z
Returns
Chunk[]
2319  : array {
2320  $result = [];
2321  for ($xx = 0; $xx <= 2; ++$xx) {
2322  for ($zz = 0; $zz <= 2; ++$zz) {
2323  $i = $zz * 3 + $xx;
2324  if ($i === 4) {
2325  continue; //center chunk
2326  }
2327  $result[$i] = $this->getChunk($x + $xx - 1, $z + $zz - 1, false);
2328  }
2329  }
2330  return $result;
2331  }

◆ getAutoSave()

getAutoSave ( )
Returns
bool
601  : bool {
602  return $this->autoSave;
603  }

◆ getBiomeId()

getBiomeId ( int  $x,
int  $z 
)
Parameters
int$x
int$z
Returns
int
2253  : int {
2254  return $this->getChunk($x >> 4, $z >> 4, true)->getBiomeId($x & 0x0f, $z & 0x0f);
2255  }

◆ getBlock()

getBlock ( Vector3  $pos,
  $cached = true 
)

Gets the Block object on the Vector3 location

Parameters
Vector3$pos
boolean$cached
Returns
Block
1363  : Block {
1364  $pos = $pos->floor();
1365  $index = Level::blockHash($pos->x, $pos->y, $pos->z);
1366  if ($cached and isset($this->blockCache[$index])) {
1367  return $this->blockCache[$index];
1368  } elseif ($pos->y >= 0 and $pos->y < $this->provider->getWorldHeight() and isset($this->chunks[$chunkIndex = Level::chunkHash($pos->x >> 4, $pos->z >> 4)])) {
1369  $fullState = $this->chunks[$chunkIndex]->getFullBlock($pos->x & 0x0f, $pos->y & Level::Y_MASK, $pos->z & 0x0f);
1370  } else {
1371  $fullState = 0;
1372  }
1373 
1374  $block = clone $this->blockStates[$fullState & 0xfff];
1375 
1376  $block->x = $pos->x;
1377  $block->y = $pos->y;
1378  $block->z = $pos->z;
1379  $block->level = $this;
1380 
1381  return $this->blockCache[$index] = $block;
1382  }

◆ getBlockDataAt()

getBlockDataAt ( int  $x,
int  $y,
int  $z 
)

Gets the raw block metadata

Parameters
int$x
int$y
int$z
Returns
int 0-15

Implements ChunkManager.

2172  : int {
2173  return $this->getChunk($x >> 4, $z >> 4, true)->getBlockData($x & 0x0f, $y & Level::Y_MASK, $z & 0x0f);
2174  }

◆ getBlockExtraDataAt()

getBlockExtraDataAt ( int  $x,
int  $y,
int  $z 
)

Gets the raw block extra data

Parameters
int$x
int$y
int$z
Returns
int 16-bit
2144  : int {
2145  return $this->getChunk($x >> 4, $z >> 4, true)->getBlockExtraData($x & 0x0f, $y & Level::Y_MASK, $z & 0x0f);
2146  }

◆ getBlockIdAt()

getBlockIdAt ( int  $x,
int  $y,
int  $z 
)

Gets the raw block id.

Parameters
int$x
int$y
int$z
Returns
int 0-255

Implements ChunkManager.

2110  : int {
2111  return $this->getChunk($x >> 4, $z >> 4, true)->getBlockId($x & 0x0f, $y & Level::Y_MASK, $z & 0x0f);
2112  }

◆ getBlockLightAt()

getBlockLightAt ( int  $x,
int  $y,
int  $z 
)

Gets the raw block light level

Parameters
int$x
int$y
int$z
Returns
int 0-15

Implements ChunkManager.

2231  : int {
2232  return $this->getChunk($x >> 4, $z >> 4, true)->getBlockLight($x & 0x0f, $y & Level::Y_MASK, $z & 0x0f);
2233  }

◆ getBlockMetadata()

getBlockMetadata ( )
Returns
BlockMetadataStore
480  : BlockMetadataStore {
481  return $this->blockMetadata;
482  }

◆ getBlockSkyLightAt()

getBlockSkyLightAt ( int  $x,
int  $y,
int  $z 
)

Gets the raw block skylight level

Parameters
int$x
int$y
int$z
Returns
int 0-15
2206  : int {
2207  return $this->getChunk($x >> 4, $z >> 4, true)->getBlockSkyLight($x & 0x0f, $y & Level::Y_MASK, $z & 0x0f);
2208  }

◆ getBlockTempData()

getBlockTempData ( Vector3  $pos)

This method is internal use only. Do not use this in plugins

Parameters
Vector3$pos
Returns
int
308  {
309  if (isset($this->blockTempData[self::blockHash($pos->x, $pos->y, $pos->z)])) {
310  return $this->blockTempData[self::blockHash($pos->x, $pos->y, $pos->z)];
311  }
312  return 0;
313  }

◆ getBlockXYZ()

static getBlockXYZ (   $hash,
$x,
$y,
$z 
)
static
331  {
332  if (PHP_INT_SIZE === 8) {
333  $x = $hash >> 36;
334  $y = ($hash >> 28) & Level::Y_MASK; //it's always positive
335  $z = ($hash & 0xFFFFFFF) << 36 >> 36;
336  } else {
337  $hash = explode(":", $hash);
338  $x = (int)$hash[0];
339  $y = (int)$hash[1];
340  $z = (int)$hash[2];
341  }
342  }

◆ getChunk()

getChunk ( int  $x,
int  $z,
bool  $create = false 
)

Gets the Chunk object

Parameters
int$x
int$z
bool$createWhether to generate the chunk if it does not exist
Returns
Chunk
2301  {
2302  if (isset($this->chunks[$index = Level::chunkHash($x, $z)])) {
2303  return $this->chunks[$index];
2304  } elseif ($this->loadChunk($x, $z, $create)) {
2305  return $this->chunks[$index];
2306  }
2307 
2308  return null;
2309  }

◆ getChunkCacheFromData()

static getChunkCacheFromData (   $chunkX,
  $chunkZ,
  $payload 
)
static
Parameters
int$chunkX
int$chunkZ
string$payload
Returns
DataPacket
3102  {
3103  $pk = new FullChunkDataPacket();
3104  $pk->chunkX = $chunkX;
3105  $pk->chunkZ = $chunkZ;
3106  $pk->data = $payload;
3107  $pk->encode();
3108 
3109  $batch = new BatchPacket();
3110  $batch->payload = zlib_encode(Binary::writeUnsignedVarInt(strlen($pk->getBuffer())) . $pk->getBuffer(), ZLIB_ENCODING_DEFLATE, Server::getInstance()->networkCompressionLevel);
3111  $batch->encode();
3112  $batch->isEncoded = true;
3113  return $batch;
3114  }

◆ getChunkEntities()

getChunkEntities (   $X,
  $Z 
)

Returns a list of the entities on a given chunk

Parameters
int$X
int$Z
Returns
Entity[]
2085  : array {
2086  return ($chunk = $this->getChunk($X, $Z)) !== null ? $chunk->getEntities() : [];
2087  }

◆ getChunkLoaders()

getChunkLoaders ( int  $chunkX,
int  $chunkZ 
)

Gets the chunk loaders being used in a specific chunk

Parameters
int$chunkX
int$chunkZ
Returns
ChunkLoader[]
672  : array {
673  return isset($this->chunkLoaders[$index = Level::chunkHash($chunkX, $chunkZ)]) ? $this->chunkLoaders[$index] : [];
674  }

◆ getChunkPlayers()

getChunkPlayers ( int  $chunkX,
int  $chunkZ 
)

Gets the players being used in a specific chunk

Parameters
int$chunkX
int$chunkZ
Returns
Player[]
660  : array {
661  return isset($this->playerLoaders[$index = Level::chunkHash($chunkX, $chunkZ)]) ? $this->playerLoaders[$index] : [];
662  }

◆ getChunks()

getChunks ( )
Returns
Chunk[]
2288  : array {
2289  return $this->chunks;
2290  }

◆ getChunkTiles()

getChunkTiles (   $X,
  $Z 
)

Gives a list of the Tile entities on a given chunk

Parameters
int$X
int$Z
Returns
Tile[]
2097  : array {
2098  return ($chunk = $this->getChunk($X, $Z)) !== null ? $chunk->getTiles() : [];
2099  }

◆ getCollidingEntities()

getCollidingEntities ( AxisAlignedBB  $bb,
Entity  $entity = null 
)

Returns the entities colliding the current one inside the AxisAlignedBB

Parameters
AxisAlignedBB$bb
Entity$entity
Returns
Entity[]
1950  : array {
1951  $nearby = [];
1952 
1953  if ($entity === null or $entity->canCollide) {
1954  $minX = Math::floorFloat(($bb->minX - 2) / 16);
1955  $maxX = Math::ceilFloat(($bb->maxX + 2) / 16);
1956  $minZ = Math::floorFloat(($bb->minZ - 2) / 16);
1957  $maxZ = Math::ceilFloat(($bb->maxZ + 2) / 16);
1958 
1959  for ($x = $minX; $x <= $maxX; ++$x) {
1960  for ($z = $minZ; $z <= $maxZ; ++$z) {
1961  foreach ($this->getChunkEntities($x, $z) as $ent) {
1962  if ($ent instanceof Player and $ent->isSpectator()) {
1963  continue;
1964  }
1965  if ($entity == null) {
1966  if ($ent->boundingBox->intersectsWith($bb)) {
1967  $nearby[] = $ent;
1968  }
1969  } elseif ($entity instanceof Entity and $ent !== $entity and $entity->canCollideWith($ent)) {
1970  if ($ent->boundingBox->intersectsWith($bb)) {
1971  $nearby[] = $ent;
1972  }
1973  }
1974  }
1975  }
1976  }
1977  }
1978 
1979  return $nearby;
1980  }

◆ getCollisionBlocks()

getCollisionBlocks ( AxisAlignedBB  $bb,
bool  $targetFirst = false 
)
Parameters
AxisAlignedBB$bb
bool$targetFirst
Returns
Block[]
1165  : array {
1166  $minX = Math::floorFloat($bb->minX);
1167  $minY = Math::floorFloat($bb->minY);
1168  $minZ = Math::floorFloat($bb->minZ);
1169  $maxX = Math::ceilFloat($bb->maxX);
1170  $maxY = Math::ceilFloat($bb->maxY);
1171  $maxZ = Math::ceilFloat($bb->maxZ);
1172 
1173  $collides = [];
1174 
1175  if ($targetFirst) {
1176  for ($z = $minZ; $z <= $maxZ; ++$z) {
1177  for ($x = $minX; $x <= $maxX; ++$x) {
1178  for ($y = $minY; $y <= $maxY; ++$y) {
1179  $block = $this->getBlock($this->temporalVector->setComponents($x, $y, $z));
1180  if ($block->getId() !== 0 and $block->collidesWithBB($bb)) {
1181  return [$block];
1182  }
1183  }
1184  }
1185  }
1186  } else {
1187  for ($z = $minZ; $z <= $maxZ; ++$z) {
1188  for ($x = $minX; $x <= $maxX; ++$x) {
1189  for ($y = $minY; $y <= $maxY; ++$y) {
1190  $block = $this->getBlock($this->temporalVector->setComponents($x, $y, $z));
1191  if ($block->getId() !== 0 and $block->collidesWithBB($bb)) {
1192  $collides[] = $block;
1193  }
1194  }
1195  }
1196  }
1197  }
1198 
1199 
1200  return $collides;
1201  }

◆ getCollisionCubes()

getCollisionCubes ( Entity  $entity,
AxisAlignedBB  $bb,
bool  $entities = true 
)
Parameters
Entity$entity
AxisAlignedBB$bb
boolean$entities
Returns
AxisAlignedBB[]
1228  : array {
1229  $minX = Math::floorFloat($bb->minX);
1230  $minY = Math::floorFloat($bb->minY);
1231  $minZ = Math::floorFloat($bb->minZ);
1232  $maxX = Math::ceilFloat($bb->maxX);
1233  $maxY = Math::ceilFloat($bb->maxY);
1234  $maxZ = Math::ceilFloat($bb->maxZ);
1235 
1236  $collides = [];
1237 
1238  for ($z = $minZ; $z <= $maxZ; ++$z) {
1239  for ($x = $minX; $x <= $maxX; ++$x) {
1240  for ($y = $minY; $y <= $maxY; ++$y) {
1241  $block = $this->getBlock($this->temporalVector->setComponents($x, $y, $z));
1242  if (!$block->canPassThrough() and $block->collidesWithBB($bb)) {
1243  $collides[] = $block->getBoundingBox();
1244  }
1245  }
1246  }
1247  }
1248 
1249  if ($entities) {
1250  foreach ($this->getCollidingEntities($bb->grow(0.25, 0.25, 0.25), $entity) as $ent) {
1251  $collides[] = clone $ent->boundingBox;
1252  }
1253  }
1254 
1255  return $collides;
1256  }

◆ getDimension()

getDimension ( )
425  : int {
426  return $this->dimension;
427  }

◆ getEntities()

getEntities ( )

Gets the list of all the entities in this level

Returns
Entity[]
1938  : array {
1939  return $this->entities;
1940  }

◆ getEntity()

getEntity ( int  $entityId)
Parameters
int$entityId
Returns
Entity
1929  {
1930  return isset($this->entities[$entityId]) ? $this->entities[$entityId] : null;
1931  }

◆ getFolderName()

getFolderName ( )

Returns the Level folder name

Returns
string
2936  : string {
2937  return $this->folderName;
2938  }

◆ getFullBlock()

getFullBlock ( int  $x,
int  $y,
int  $z 
)
Parameters
$x
$y
$z
Returns
int bitmap, (id << 4) | data
1351  : int {
1352  return $this->getChunk($x >> 4, $z >> 4, false)->getFullBlock($x & 0x0f, $y, $z & 0x0f);
1353  }

◆ getFullLight()

getFullLight ( Vector3  $pos)
1330  : int {
1331  $chunk = $this->getChunk($pos->x >> 4, $pos->z >> 4, false);
1332  $level = 0;
1333  if ($chunk !== null) {
1334  $level = $chunk->getBlockSkyLight($pos->x & 0x0f, $pos->y, $pos->z & 0x0f);
1335  //TODO: decrease light level by time of day
1336  if ($level < 15) {
1337  $level = $chunk->getBlockSkyLight($pos->x & 0x0f, $pos->y, $pos->z & 0x0f);
1338  }
1339  }
1340 
1341  return $level;
1342  }

◆ getHeightMap()

getHeightMap ( int  $x,
int  $z 
)
Parameters
int$x
int$z
Returns
int
2263  : int {
2264  return $this->getChunk($x >> 4, $z >> 4, true)->getHeightMap($x & 0x0f, $z & 0x0f);
2265  }

◆ getHighestAdjacentBlockLight()

getHighestAdjacentBlockLight ( int  $x,
int  $y,
int  $z 
)
1418  : int {
1419  return max([
1420  $this->getBlockLightAt($x + 1, $y, $z),
1421  $this->getBlockLightAt($x - 1, $y, $z),
1422  $this->getBlockLightAt($x, $y + 1, $z),
1423  $this->getBlockLightAt($x, $y - 1, $z),
1424  $this->getBlockLightAt($x, $y, $z + 1),
1425  $this->getBlockLightAt($x, $y, $z - 1)
1426  ]);
1427  }

◆ getHighestBlockAt()

getHighestBlockAt ( int  $x,
int  $z 
)

Gets the highest block Y value at a specific $x and $z

Parameters
int$x
int$z
Returns
int 0-255
2503  : int {
2504  return $this->getChunk($x >> 4, $z >> 4, true)->getHighestBlockAt($x & 0x0f, $z & 0x0f);
2505  }

◆ getId()

getId ( )
final

Returns the unique level identifier

Returns
int
503  : int {
504  return $this->levelId;
505  }

◆ getLoaders()

getLoaders ( )
Returns
ChunkLoader[]
2056  : array {
2057  return $this->loaders;
2058  }

◆ getMetadata()

getMetadata (   $metadataKey)

Returns a list of previously set metadata values from the implementing object's metadata store.

Parameters
string$metadataKey
Returns
MetadataValue[]

Implements Metadatable.

3120  {
3121  return $this->server->getLevelMetadata()->getMetadata($this, $metadataKey);
3122  }

◆ getName()

getName ( )

Returns the Level name

Returns
string
2922  : string {
2923  if ($this->provider !== null and $this->provider->getName() !== null) {
2924  return $this->provider->getName();
2925  } else {
2926  return $this->getFolderName();
2927  }
2928 
2929  }

◆ getNearbyEntities()

getNearbyEntities ( AxisAlignedBB  $bb,
Entity  $entity = null 
)

Returns the entities near the current one inside the AxisAlignedBB

Parameters
AxisAlignedBB$bb
Entity$entity
Returns
Entity[]
1990  : array {
1991  $nearby = [];
1992 
1993  $minX = Math::floorFloat(($bb->minX - 2) / 16);
1994  $maxX = Math::ceilFloat(($bb->maxX + 2) / 16);
1995  $minZ = Math::floorFloat(($bb->minZ - 2) / 16);
1996  $maxZ = Math::ceilFloat(($bb->maxZ + 2) / 16);
1997 
1998  for ($x = $minX; $x <= $maxX; ++$x) {
1999  for ($z = $minZ; $z <= $maxZ; ++$z) {
2000  foreach ($this->getChunkEntities($x, $z) as $ent) {
2001  if ($ent instanceof Player and $ent->isSpectator()) {
2002  continue;
2003  }
2004  if ($ent !== $entity and $ent->boundingBox->intersectsWith($bb)) {
2005  $nearby[] = $ent;
2006  }
2007  }
2008  }
2009  }
2010 
2011  return $nearby;
2012  }

◆ getNearbyExperienceOrb()

getNearbyExperienceOrb ( AxisAlignedBB  $bb)
2014  : array {
2015  $nearby = [];
2016 
2017  foreach ($this->getNearbyEntities($bb) as $entity) {
2018  if ($entity instanceof XPOrb) {
2019  $nearby[] = $entity;
2020  }
2021  }
2022 
2023  return $nearby;
2024  }

◆ getPlayers()

getPlayers ( )

Returns a list of the players in this level

Returns
Player[]
2049  : array {
2050  return $this->players;
2051  }

◆ getProvider()

getProvider ( )
final
Returns
LevelProvider
494  {
495  return $this->provider;
496  }

◆ getSafeSpawn()

getSafeSpawn (   $spawn = null)
Parameters
Vector3$spawndefault null
Returns
bool|Position
2859  {
2860  if (!($spawn instanceof Vector3) or $spawn->y < 1) {
2861  $spawn = $this->getSpawnLocation();
2862  }
2863  if ($spawn instanceof Vector3) {
2864  $max = $this->provider->getWorldHeight();
2865  $v = $spawn->floor();
2866  $chunk = $this->getChunk($v->x >> 4, $v->z >> 4, false);
2867  $x = $v->x & 0x0f;
2868  $z = $v->z & 0x0f;
2869  if ($chunk !== null) {
2870  $y = (int)min($max - 2, $v->y);
2871  $wasAir = ($chunk->getBlockId($x, $y - 1, $z) === 0);
2872  for (; $y > 0; --$y) {
2873  $b = $chunk->getFullBlock($x, $y, $z);
2874  $block = Block::get($b >> 4, $b & 0x0f);
2875  if ($this->isFullBlock($block)) {
2876  if ($wasAir) {
2877  $y++;
2878  break;
2879  }
2880  } else {
2881  $wasAir = true;
2882  }
2883  }
2884 
2885  for (; $y >= 0 and $y < $max; ++$y) {
2886  $b = $chunk->getFullBlock($x, $y + 1, $z);
2887  $block = Block::get($b >> 4, $b & 0x0f);
2888  if (!$this->isFullBlock($block)) {
2889  $b = $chunk->getFullBlock($x, $y, $z);
2890  $block = Block::get($b >> 4, $b & 0x0f);
2891  if (!$this->isFullBlock($block)) {
2892  return new Position($spawn->x, $y === (int)$spawn->y ? $spawn->y : $y, $spawn->z, $this);
2893  }
2894  } else {
2895  ++$y;
2896  }
2897  }
2898 
2899  $v->y = $y;
2900  }
2901 
2902  return new Position($spawn->x, $v->y, $spawn->z, $this);
2903  }
2904 
2905  return false;
2906  }

◆ getSeed()

getSeed ( )

Gets the level seed

Returns
int|string

Implements ChunkManager.

2971  {
2972  return $this->provider->getSeed();
2973  }

◆ getServer()

getServer ( )
Returns
Server
487  : Server {
488  return $this->server;
489  }

◆ getSpawnLocation()

getSpawnLocation ( )

Returns a Position pointing to the spawn

Returns
Position
2548  : Position {
2549  return Position::fromObject($this->provider->getSpawn(), $this);
2550  }

◆ getTickRate()

getTickRate ( )
436  : int {
437  return $this->tickRate;
438  }

◆ getTickRateTime()

getTickRateTime ( )
440  {
441  return $this->tickRateTime;
442  }

◆ getTile()

getTile ( Vector3  $pos)

Returns the Tile in a position, or null if not found

Parameters
Vector3$pos
Returns
Tile
2067  {
2068  $chunk = $this->getChunk($pos->x >> 4, $pos->z >> 4, false);
2069 
2070  if ($chunk !== null) {
2071  return $chunk->getTile($pos->x & 0x0f, $pos->y & Level::Y_MASK, $pos->z & 0x0f);
2072  }
2073 
2074  return null;
2075  }

◆ getTileById()

getTileById ( int  $tileId)
Parameters
$tileId
Returns
Tile
2040  {
2041  return isset($this->tiles[$tileId]) ? $this->tiles[$tileId] : null;
2042  }

◆ getTiles()

getTiles ( )

Returns a list of the Tile entities in this level

Returns
Tile[]
2031  : array {
2032  return $this->tiles;
2033  }

◆ getTime()

getTime ( )

Gets the current time

Returns
int
2913  : int {
2914  return $this->time;
2915  }

◆ getWaterHeight()

getWaterHeight ( )
456  : int {
457  if ($this->generatorInstance instanceof Generator) {
458  return $this->generatorInstance->getWaterHeight();
459  }
460  return 0;
461  }

◆ getWeather()

getWeather ( )
Returns
Weather
432  {
433  return $this->weather;
434  }

◆ getXZ()

static getXZ (   $hash,
$x,
$z 
)
static
344  {
345  if (PHP_INT_SIZE === 8) {
346  $x = $hash >> 32;
347  $z = ($hash & 0xFFFFFFFF) << 32 >> 32;
348  } else {
349  $hash = explode(":", $hash);
350  $x = (int)$hash[0];
351  $z = (int)$hash[1];
352  }
353  }

◆ hasMetadata()

hasMetadata (   $metadataKey)

Tests to see whether the implementing object contains the given metadata value in its metadata store.

Parameters
string$metadataKey
Returns
bool

Implements Metadatable.

3124  {
3125  return $this->server->getLevelMetadata()->hasMetadata($this, $metadataKey);
3126  }

◆ initLevel()

initLevel ( )
448  {
449  $generator = $this->generator;
450  $this->generatorInstance = new $generator($this->provider->getGeneratorOptions());
451  $this->generatorInstance->init($this, new Random($this->getSeed()));
452 
453  $this->registerGenerator();
454  }

◆ isChunkGenerated()

isChunkGenerated ( int  $x,
int  $z 
)
Parameters
int$x
int$z
Returns
bool
2527  : bool {
2528  $chunk = $this->getChunk($x, $z);
2529  return $chunk !== null ? $chunk->isGenerated() : false;
2530  }

◆ isChunkInUse()

isChunkInUse ( int  $x,
int  $z 
)
Parameters
int$x
int$z
Returns
bool
2710  : bool {
2711  return isset($this->chunkLoaders[$index = Level::chunkHash($x, $z)]) and count($this->chunkLoaders[$index]) > 0;
2712  }

◆ isChunkLoaded()

isChunkLoaded ( int  $x,
int  $z 
)
Parameters
int$x
int$z
Returns
bool
2517  : bool {
2518  return isset($this->chunks[Level::chunkHash($x, $z)]) or $this->provider->isChunkLoaded($x, $z);
2519  }

◆ isChunkPopulated()

isChunkPopulated ( int  $x,
int  $z 
)
Parameters
int$x
int$z
Returns
bool
2538  : bool {
2539  $chunk = $this->getChunk($x, $z);
2540  return $chunk !== null ? $chunk->isPopulated() : false;
2541  }

◆ isClosed()

isClosed ( )
507  : bool {
508  return $this->closed;
509  }

◆ isFullBlock()

isFullBlock ( Vector3  $pos)
Parameters
Vector3$pos
Returns
bool
1208  : bool {
1209  if ($pos instanceof Block) {
1210  if ($pos->isSolid()) {
1211  return true;
1212  }
1213  $bb = $pos->getBoundingBox();
1214  } else {
1215  $bb = $this->getBlock($pos)->getBoundingBox();
1216  }
1217 
1218  return $bb !== null and $bb->getAverageEdgeLength() >= 1;
1219  }

◆ isSpawnChunk()

isSpawnChunk ( int  $X,
int  $Z 
)

Returns true if the spawn is part of the spawn

Parameters
int$X
int$Z
Returns
bool
2847  : bool {
2848  $spawnX = $this->provider->getSpawn()->getX() >> 4;
2849  $spawnZ = $this->provider->getSpawn()->getZ() >> 4;
2850 
2851  return abs($X - $spawnX) <= 1 and abs($Z - $spawnZ) <= 1;
2852  }

◆ loadChunk()

loadChunk ( int  $x,
int  $z,
bool  $generate = true 
)
Parameters
int$x
int$z
bool$generate
Returns
bool
2721  : bool {
2722  if (isset($this->chunks[$index = Level::chunkHash($x, $z)])) {
2723  return true;
2724  }
2725 
2726  $this->timings->syncChunkLoadTimer->startTiming();
2727 
2728  $this->cancelUnloadChunkRequest($x, $z);
2729 
2730  $chunk = $this->provider->getChunk($x, $z, $generate);
2731  if ($chunk === null) {
2732  if ($generate) {
2733  throw new \InvalidStateException("Could not create new Chunk");
2734  }
2735  return false;
2736  }
2737 
2738  $this->chunks[$index] = $chunk;
2739  $chunk->initChunk($this);
2740 
2741  $this->server->getPluginManager()->callEvent(new ChunkLoadEvent($this, $chunk, !$chunk->isGenerated()));
2742 
2743  if (!$chunk->isLightPopulated() and $chunk->isPopulated() and $this->getServer()->getProperty("chunk-ticking.light-updates", false)) {
2744  $this->getServer()->getScheduler()->scheduleAsyncTask(new LightPopulationTask($this, $chunk));
2745  }
2746 
2747  if ($this->isChunkInUse($x, $z)) {
2748  foreach ($this->getChunkLoaders($x, $z) as $loader) {
2749  $loader->onChunkLoaded($chunk);
2750  }
2751  } else {
2752  $this->unloadChunkRequest($x, $z);
2753  }
2754 
2755  $this->timings->syncChunkLoadTimer->stopTiming();
2756 
2757  return true;
2758  }

◆ populateChunk()

populateChunk ( int  $x,
int  $z,
bool  $force = false 
)
2984  : bool {
2985  if (isset($this->chunkPopulationQueue[$index = Level::chunkHash($x, $z)]) or (count($this->chunkPopulationQueue) >= $this->chunkPopulationQueueSize and !$force)) {
2986  return false;
2987  }
2988 
2989  $chunk = $this->getChunk($x, $z, true);
2990  if (!$chunk->isPopulated()) {
2991  Timings::$populationTimer->startTiming();
2992  $populate = true;
2993  for ($xx = -1; $xx <= 1; ++$xx) {
2994  for ($zz = -1; $zz <= 1; ++$zz) {
2995  if (isset($this->chunkPopulationLock[Level::chunkHash($x + $xx, $z + $zz)])) {
2996  $populate = false;
2997  break;
2998  }
2999  }
3000  }
3001 
3002  if ($populate) {
3003  if (!isset($this->chunkPopulationQueue[$index])) {
3004  $this->chunkPopulationQueue[$index] = true;
3005  for ($xx = -1; $xx <= 1; ++$xx) {
3006  for ($zz = -1; $zz <= 1; ++$zz) {
3007  $this->chunkPopulationLock[Level::chunkHash($x + $xx, $z + $zz)] = true;
3008  }
3009  }
3010  $task = new PopulationTask($this, $chunk);
3011  $this->server->getScheduler()->scheduleAsyncTask($task);
3012  }
3013  }
3014 
3015  Timings::$populationTimer->stopTiming();
3016  return false;
3017  }
3018 
3019  return true;
3020  }

◆ regenerateChunk()

regenerateChunk ( int  $x,
int  $z 
)
3036  {
3037  $this->unloadChunk($x, $z, false);
3038 
3039  $this->cancelUnloadChunkRequest($x, $z);
3040 
3041  $this->generateChunk($x, $z);
3042  //TODO: generate & refresh chunk from the generator object
3043  }

◆ registerChunkLoader()

registerChunkLoader ( ChunkLoader  $loader,
int  $chunkX,
int  $chunkZ,
bool  $autoLoad = true 
)
684  {
685  $hash = $loader->getLoaderId();
686 
687  if (!isset($this->chunkLoaders[$index = Level::chunkHash($chunkX, $chunkZ)])) {
688  $this->chunkLoaders[$index] = [];
689  $this->playerLoaders[$index] = [];
690  } elseif (isset($this->chunkLoaders[$index][$hash])) {
691  return;
692  }
693 
694  $this->chunkLoaders[$index][$hash] = $loader;
695  if ($loader instanceof Player) {
696  $this->playerLoaders[$index][$hash] = $loader;
697  }
698 
699  if (!isset($this->loaders[$hash])) {
700  $this->loaderCounter[$hash] = 1;
701  $this->loaders[$hash] = $loader;
702  } else {
703  ++$this->loaderCounter[$hash];
704  }
705 
706  $this->cancelUnloadChunkRequest($chunkX, $chunkZ);
707 
708  if ($autoLoad) {
709  $this->loadChunk($chunkX, $chunkZ);
710  }
711  }

◆ registerGenerator()

registerGenerator ( )
463  {
464  $size = $this->server->getScheduler()->getAsyncTaskPoolSize();
465  for ($i = 0; $i < $size; ++$i) {
466  $this->server->getScheduler()->scheduleAsyncTaskToWorker(new GeneratorRegisterTask($this, $this->generatorInstance), $i);
467  }
468  }

◆ removeEntity()

removeEntity ( Entity  $entity)

Removes the entity from the level index

Parameters
Entity$entity
Exceptions
LevelException
2645  {
2646  if ($entity->getLevel() !== $this) {
2647  throw new LevelException("Invalid Entity level");
2648  }
2649 
2650  if ($entity instanceof Player) {
2651  unset($this->players[$entity->getId()]);
2652  $this->checkSleep();
2653  } else {
2654  $entity->close();
2655  }
2656 
2657  unset($this->entities[$entity->getId()]);
2658  unset($this->updateEntities[$entity->getId()]);
2659  }

◆ removeMetadata()

removeMetadata (   $metadataKey,
Plugin  $owningPlugin 
)

Removes the given metadata value from the implementing object's metadata store.

Parameters
string$metadataKey
Plugin$owningPlugin
Returns
void

Implements Metadatable.

3128  {
3129  $this->server->getLevelMetadata()->removeMetadata($this, $metadataKey, $plugin);
3130  }

◆ removeTile()

removeTile ( Tile  $tile)
Parameters
Tile$tile
Exceptions
LevelException
2694  {
2695  if ($tile->getLevel() !== $this) {
2696  throw new LevelException("Invalid Tile level");
2697  }
2698 
2699  unset($this->tiles[$tile->getId()]);
2700  unset($this->updateTiles[$tile->getId()]);
2701  $this->clearChunkCache($tile->getX() >> 4, $tile->getZ() >> 4);
2702  }

◆ requestChunk()

requestChunk ( int  $x,
int  $z,
Player  $player 
)
2563  {
2564  $index = Level::chunkHash($x, $z);
2565  if (!isset($this->chunkSendQueue[$index])) {
2566  $this->chunkSendQueue[$index] = [];
2567  }
2568 
2569  $this->chunkSendQueue[$index][$player->getLoaderId()] = $player;
2570  }

◆ save()

save ( bool  $force = false)
Parameters
bool$force
Returns
bool
1084  : bool {
1085 
1086  if (!$this->getAutoSave() and !$force) {
1087  return false;
1088  }
1089 
1090  $this->server->getPluginManager()->callEvent(new LevelSaveEvent($this));
1091 
1092  $this->provider->setTime((int)$this->time);
1093  $this->saveChunks();
1094  if ($this->provider instanceof BaseLevelProvider) {
1095  $this->provider->saveLevelData();
1096  }
1097 
1098  return true;
1099  }

◆ saveChunks()

saveChunks ( )
1101  {
1102  foreach ($this->chunks as $chunk) {
1103  if ($chunk->hasChanged() and $chunk->isGenerated()) {
1104  $this->provider->setChunk($chunk->getX(), $chunk->getZ(), $chunk);
1105  $this->provider->saveChunk($chunk->getX(), $chunk->getZ());
1106  $chunk->setChanged(false);
1107  }
1108  }
1109  }

◆ scheduleUpdate()

scheduleUpdate ( Vector3  $pos,
int  $delay 
)
Parameters
Vector3$pos
int$delay
1151  {
1152  if (isset($this->updateQueueIndex[$index = Level::blockHash($pos->x, $pos->y, $pos->z)]) and $this->updateQueueIndex[$index] <= $delay) {
1153  return;
1154  }
1155  $this->updateQueueIndex[$index] = $delay;
1156  $this->updateQueue->insert(new Vector3((int)$pos->x, (int)$pos->y, (int)$pos->z), (int)$delay + $this->server->getTick());
1157  }

◆ sendBlockExtraData()

sendBlockExtraData ( int  $x,
int  $y,
int  $z,
int  $id,
int  $data,
array  $targets = null 
)
910  {
911  $pk = new LevelEventPacket;
913  $pk->x = $x + 0.5;
914  $pk->y = $y + 0.5;
915  $pk->z = $z + 0.5;
916  $pk->data = ($data << 8) | $id;
917 
918  $this->server->broadcastPacket($targets === null ? $this->getChunkPlayers($x >> 4, $z >> 4) : $targets, $pk);
919  }

◆ sendBlocks()

sendBlocks ( array  $target,
array  $blocks,
  $flags = UpdateBlockPacket::FLAG_NONE,
bool  $optimizeRebuilds = false 
)
Parameters
Player[]$target
Block[]$blocks
int$flags
bool$optimizeRebuilds
927  {
928  if ($optimizeRebuilds) {
929  $chunks = [];
930  foreach ($blocks as $b) {
931  if ($b === null) {
932  continue;
933  }
934 
935  $pk = new UpdateBlockPacket();
936  $first = false;
937  if (!isset($chunks[$index = Level::chunkHash($b->x >> 4, $b->z >> 4)])) {
938  $chunks[$index] = true;
939  $first = true;
940  }
941 
942  $pk->x = $b->x;
943  $pk->z = $b->z;
944  $pk->y = $b->y;
945 
946  if ($b instanceof Block) {
947  $pk->blockId = $b->getId();
948  $pk->blockData = $b->getDamage();
949  } else {
950  $fullBlock = $this->getFullBlock($b->x, $b->y, $b->z);
951  $pk->blockId = $fullBlock >> 4;
952  $pk->blockData = $fullBlock & 0xf;
953  }
954  $pk->flags = $first ? $flags : UpdateBlockPacket::FLAG_NONE;
955  $this->server->broadcastPacket($target, $pk);
956  }
957  } else {
958  foreach ($blocks as $b) {
959  if ($b === null) {
960  continue;
961  }
962  $pk = new UpdateBlockPacket();
963 
964  $pk->x = $b->x;
965  $pk->z = $b->z;
966  $pk->y = $b->y;
967 
968  if ($b instanceof Block) {
969  $pk->blockId = $b->getId();
970  $pk->blockData = $b->getDamage();
971  } else {
972  $fullBlock = $this->getFullBlock($b->x, $b->y, $b->z);
973  $pk->blockId = $fullBlock >> 4;
974  $pk->blockData = $fullBlock & 0xf;
975  }
976  $pk->flags = $flags;
977  $this->server->broadcastPacket($target, $pk);
978  }
979  }
980  }

◆ sendLighting()

sendLighting ( int  $x,
int  $y,
int  $z,
Player  $p 
)

Directly send a lightning to a player

Deprecated:
Parameters
int$x
int$y
int$z
Player$p
2419  {
2420  $pk = new AddEntityPacket();
2421  $pk->type = Lightning::NETWORK_ID;
2422  $pk->eid = mt_rand(10000000, 100000000);
2423  $pk->x = $x;
2424  $pk->y = $y;
2425  $pk->z = $z;
2426  $pk->metadata = array(3, 3, 3, 3);
2427  $p->dataPacket($pk);
2428  }

◆ sendTime()

sendTime ( )

WARNING: Do not use this, it's only for internal use. Changes to this function won't be recorded on the version.

746  {
747  $pk = new SetTimePacket();
748  $pk->time = (int)$this->time;
749  $pk->started = $this->stopTime == false;
750 
751  $this->server->broadcastPacket($this->players, $pk);
752  }

◆ setAutoSave()

setAutoSave ( bool  $value)
Parameters
bool$value
608  {
609  $this->autoSave = $value;
610  }

◆ setBiomeId()

setBiomeId ( int  $x,
int  $z,
int  $biomeId 
)
Parameters
int$x
int$z
int$biomeId
2272  {
2273  $this->getChunk($x >> 4, $z >> 4, true)->setBiomeId($x & 0x0f, $z & 0x0f, $biomeId);
2274  }

◆ setBlock()

setBlock ( Vector3  $pos,
Block  $block,
bool  $direct = false,
bool  $update = true 
)

Sets on Vector3 the data from a Block object, does block updates and puts the changes to the send queue.

If $direct is true, it'll send changes directly to players. if false, it'll be queued and the best way to send queued changes will be done in the next tick. This way big changes can be sent on a single chunk update packet instead of thousands of packets.

If $update is true, it'll get the neighbour blocks (6 sides) and update them. If you are doing big changes, you might want to set this to false, then update manually.

Parameters
Vector3$pos
Block$block
bool$direct
1497  : bool {
1498  $pos = $pos->floor();
1499  if ($pos->y < 0 or $pos->y >= $this->provider->getWorldHeight()) {
1500  return false;
1501  }
1502 
1503  $this->timings->setBlock->startTiming();
1504  if ($this->getChunk($pos->x >> 4, $pos->z >> 4, true)->setBlock($pos->x & 0x0f, $pos->y & Level::Y_MASK, $pos->z & 0x0f, $block->getId(), $block->getDamage())) {
1505  if (!($pos instanceof Position)) {
1506  $pos = $this->temporalPosition->setComponents($pos->x, $pos->y, $pos->z);
1507  }
1508 
1509  $block->position($pos);
1510  unset($this->blockCache[Level::blockHash($pos->x, $pos->y, $pos->z)]);
1511 
1512  $index = Level::chunkHash($pos->x >> 4, $pos->z >> 4);
1513 
1514  if ($direct === true) {
1515  $this->sendBlocks($this->getChunkPlayers($pos->x >> 4, $pos->z >> 4), [$block], UpdateBlockPacket::FLAG_ALL_PRIORITY);
1516  unset($this->chunkCache[$index]);
1517  } else {
1518  if (!isset($this->changedBlocks[$index])) {
1519  $this->changedBlocks[$index] = [];
1520  }
1521 
1522  $this->changedBlocks[$index][Level::blockHash($block->x, $block->y, $block->z)] = clone $block;
1523  }
1524 
1525  foreach ($this->getChunkLoaders($pos->x >> 4, $pos->z >> 4) as $loader) {
1526  $loader->onBlockChanged($block);
1527  }
1528 
1529  if ($update === true) {
1530  $this->updateAllLight($block);
1531 
1532  $this->server->getPluginManager()->callEvent($ev = new BlockUpdateEvent($block));
1533  if (!$ev->isCancelled()) {
1534  foreach ($this->getNearbyEntities(new AxisAlignedBB($block->x - 1, $block->y - 1, $block->z - 1, $block->x + 1, $block->y + 1, $block->z + 1)) as $entity) {
1535  $entity->scheduleUpdate();
1536  }
1537  $ev->getBlock()->onUpdate(self::BLOCK_UPDATE_NORMAL);
1538  }
1539 
1540  $this->updateAround($pos);
1541  }
1542 
1543  $this->timings->setBlock->stopTiming();
1544 
1545  return true;
1546  }
1547 
1548  $this->timings->setBlock->stopTiming();
1549 
1550  return false;
1551  }

◆ setBlockDataAt()

setBlockDataAt ( int  $x,
int  $y,
int  $z,
int  $data 
)

Sets the raw block metadata.

Parameters
int$x
int$y
int$z
int$data0-15

Implements ChunkManager.

2184  {
2185  unset($this->blockCache[Level::blockHash($x, $y, $z)]);
2186  $this->getChunk($x >> 4, $z >> 4, true)->setBlockData($x & 0x0f, $y & Level::Y_MASK, $z & 0x0f, $data & 0x0f);
2187 
2188  if (!isset($this->changedBlocks[$index = Level::chunkHash($x >> 4, $z >> 4)])) {
2189  $this->changedBlocks[$index] = [];
2190  }
2191  $this->changedBlocks[$index][Level::blockHash($x, $y, $z)] = $v = new Vector3($x, $y, $z);
2192  foreach ($this->getChunkLoaders($x >> 4, $z >> 4) as $loader) {
2193  $loader->onBlockChanged($v);
2194  }
2195  }

◆ setBlockExtraDataAt()

setBlockExtraDataAt ( int  $x,
int  $y,
int  $z,
int  $id,
int  $data 
)

Sets the raw block metadata.

Parameters
int$x
int$y
int$z
int$id
int$data
2157  {
2158  $this->getChunk($x >> 4, $z >> 4, true)->setBlockExtraData($x & 0x0f, $y & Level::Y_MASK, $z & 0x0f, ($data << 8) | $id);
2159 
2160  $this->sendBlockExtraData($x, $y, $z, $id, $data);
2161  }

◆ setBlockIdAt()

setBlockIdAt ( int  $x,
int  $y,
int  $z,
int  $id 
)

Sets the raw block id.

Parameters
int$x
int$y
int$z
int$id0-255

Implements ChunkManager.

2122  {
2123  unset($this->blockCache[Level::blockHash($x, $y, $z)]);
2124  $this->getChunk($x >> 4, $z >> 4, true)->setBlockId($x & 0x0f, $y & Level::Y_MASK, $z & 0x0f, $id & 0xff);
2125 
2126  if (!isset($this->changedBlocks[$index = Level::chunkHash($x >> 4, $z >> 4)])) {
2127  $this->changedBlocks[$index] = [];
2128  }
2129  $this->changedBlocks[$index][Level::blockHash($x, $y, $z)] = $v = new Vector3($x, $y, $z);
2130  foreach ($this->getChunkLoaders($x >> 4, $z >> 4) as $loader) {
2131  $loader->onBlockChanged($v);
2132  }
2133  }

◆ setBlockLightAt()

setBlockLightAt ( int  $x,
int  $y,
int  $z,
int  $level 
)

Sets the raw block light level.

Parameters
int$x
int$y
int$z
int$level0-15

Implements ChunkManager.

2243  {
2244  $this->getChunk($x >> 4, $z >> 4, true)->setBlockLight($x & 0x0f, $y & Level::Y_MASK, $z & 0x0f, $level & 0x0f);
2245  }

◆ setBlockSkyLightAt()

setBlockSkyLightAt ( int  $x,
int  $y,
int  $z,
int  $level 
)

Sets the raw block skylight level.

Parameters
int$x
int$y
int$z
int$level0-15
2218  {
2219  $this->getChunk($x >> 4, $z >> 4, true)->setBlockSkyLight($x & 0x0f, $y & Level::Y_MASK, $z & 0x0f, $level & 0x0f);
2220  }

◆ setBlockTempData()

setBlockTempData ( Vector3  $pos,
  $data = null 
)

This method is internal use only. Do not use this in plugins

Parameters
Vector3$pos
$data
294  {
295  if ($data == null and isset($this->blockTempData[self::blockHash($pos->x, $pos->y, $pos->z)])) {
296  unset($this->blockTempData[self::blockHash($pos->x, $pos->y, $pos->z)]);
297  } else {
298  $this->blockTempData[self::blockHash($pos->x, $pos->y, $pos->z)] = $data;
299  }
300  }

◆ setChunk()

setChunk ( int  $chunkX,
int  $chunkZ,
Chunk  $chunk = null,
bool  $unload = true 
)
Parameters
int$chunkX
int$chunkZ
Chunk$chunk
bool$unload
2368  {
2369  if ($chunk === null) {
2370  return;
2371  }
2372  $index = Level::chunkHash($chunkX, $chunkZ);
2373  $oldChunk = $this->getChunk($chunkX, $chunkZ, false);
2374  if ($unload and $oldChunk !== null) {
2375  $this->unloadChunk($chunkX, $chunkZ, false, false);
2376 
2377  $this->provider->setChunk($chunkX, $chunkZ, $chunk);
2378  $this->chunks[$index] = $chunk;
2379  } else {
2380  $oldEntities = $oldChunk !== null ? $oldChunk->getEntities() : [];
2381  $oldTiles = $oldChunk !== null ? $oldChunk->getTiles() : [];
2382 
2383  $this->provider->setChunk($chunkX, $chunkZ, $chunk);
2384  $this->chunks[$index] = $chunk;
2385 
2386  foreach ($oldEntities as $entity) {
2387  $chunk->addEntity($entity);
2388  $entity->chunk = $chunk;
2389  }
2390 
2391  foreach ($oldTiles as $tile) {
2392  $chunk->addTile($tile);
2393  $tile->chunk = $chunk;
2394  }
2395  }
2396 
2397  unset($this->chunkCache[$index]);
2398  $chunk->setChanged();
2399 
2400  if (!$this->isChunkInUse($chunkX, $chunkZ)) {
2401  $this->unloadChunkRequest($chunkX, $chunkZ);
2402  } else {
2403  foreach ($this->getChunkLoaders($chunkX, $chunkZ) as $loader) {
2404  $loader->onChunkChanged($chunk);
2405  }
2406  }
2407  }

◆ setDimension()

setDimension ( int  $dimension)
421  {
422  $this->dimension = $dimension;
423  }

◆ setHeightMap()

setHeightMap ( int  $x,
int  $z,
int  $value 
)
Parameters
int$x
int$z
int$value
2281  {
2282  $this->getChunk($x >> 4, $z >> 4, true)->setHeightMap($x & 0x0f, $z & 0x0f, $value);
2283  }

◆ setMetadata()

setMetadata (   $metadataKey,
MetadataValue  $newMetadataValue 
)

Sets a metadata value in the implementing object's metadata store.

Parameters
string$metadataKey
MetadataValue$newMetadataValue
Returns
void

Implements Metadatable.

3116  {
3117  $this->server->getLevelMetadata()->setMetadata($this, $metadataKey, $metadataValue);
3118  }

◆ setSeed()

setSeed ( int  $seed)

Sets the seed for the level

Parameters
int$seed
2980  {
2981  $this->provider->setSeed($seed);
2982  }

◆ setSpawnLocation()

setSpawnLocation ( Vector3  $pos)

Sets the level spawn location

Parameters
Vector3$pos
2557  {
2558  $previousSpawn = $this->getSpawnLocation();
2559  $this->provider->setSpawn($pos);
2560  $this->server->getPluginManager()->callEvent(new SpawnChangeEvent($this, $previousSpawn));
2561  }

◆ setTickRate()

setTickRate ( int  $tickRate)
444  {
445  $this->tickRate = $tickRate;
446  }

◆ setTime()

setTime ( int  $time)

Sets the current time on the level

Parameters
int$time
2945  {
2946  $this->time = $time;
2947  $this->sendTime();
2948  }

◆ spawnLightning()

spawnLightning ( Vector3  $pos)

Add a lightning

Parameters
Vector3$pos
Returns
Lightning
2436  : Lightning {
2437  $nbt = new CompoundTag("", [
2438  "Pos" => new ListTag("Pos", [
2439  new DoubleTag("", $pos->getX()),
2440  new DoubleTag("", $pos->getY()),
2441  new DoubleTag("", $pos->getZ())
2442  ]),
2443  "Motion" => new ListTag("Motion", [
2444  new DoubleTag("", 0),
2445  new DoubleTag("", 0),
2446  new DoubleTag("", 0)
2447  ]),
2448  "Rotation" => new ListTag("Rotation", [
2449  new FloatTag("", 0),
2450  new FloatTag("", 0)
2451  ]),
2452  ]);
2453 
2454  $lightning = new Lightning($this, $nbt);
2455  $lightning->spawnToAll();
2456 
2457  return $lightning;
2458  }

◆ spawnXPOrb()

spawnXPOrb ( Vector3  $pos,
int  $exp = 1 
)

Add an experience orb

Parameters
Vector3$pos
int$exp
Returns
bool|XPOrb
2467  {
2468  if ($exp > 0) {
2469  $nbt = new CompoundTag("", [
2470  "Pos" => new ListTag("Pos", [
2471  new DoubleTag("", $pos->getX()),
2472  new DoubleTag("", $pos->getY() + 0.5),
2473  new DoubleTag("", $pos->getZ())
2474  ]),
2475  "Motion" => new ListTag("Motion", [
2476  new DoubleTag("", 0),
2477  new DoubleTag("", 0),
2478  new DoubleTag("", 0)
2479  ]),
2480  "Rotation" => new ListTag("Rotation", [
2481  new FloatTag("", 0),
2482  new FloatTag("", 0)
2483  ]),
2484  "Experience" => new LongTag("Experience", $exp),
2485  ]);
2486 
2487  $expOrb = new XPOrb($this, $nbt);
2488  $expOrb->spawnToAll();
2489 
2490  return $expOrb;
2491  }
2492  return false;
2493  }

◆ startTime()

startTime ( )

Start the time again, if it was stopped

2961  {
2962  $this->stopTime = false;
2963  $this->sendTime();
2964  }

◆ stopTime()

stopTime ( )

Stops the time for the level, will not save the lock state to disk

2953  {
2954  $this->stopTime = true;
2955  $this->sendTime();
2956  }

◆ unload()

unload ( bool  $force = false)

Unloads the current level from memory safely

Parameters
bool$forcedefault false, force unload of default level
Returns
bool
619  : bool {
620 
621  $ev = new LevelUnloadEvent($this);
622 
623  if ($this === $this->server->getDefaultLevel() and $force !== true) {
624  $ev->setCancelled(true);
625  }
626 
627  $this->server->getPluginManager()->callEvent($ev);
628 
629  if (!$force and $ev->isCancelled()) {
630  return false;
631  }
632 
633  $this->server->getLogger()->info($this->server->getLanguage()->translateString("pocketmine.level.unloading", [$this->getName()]));
634  $defaultLevel = $this->server->getDefaultLevel();
635  foreach ($this->getPlayers() as $player) {
636  if ($this === $defaultLevel or $defaultLevel === null) {
637  $player->close($player->getLeaveMessage(), "Forced default level unload");
638  } elseif ($defaultLevel instanceof Level) {
639  $player->teleport($this->server->getDefaultLevel()->getSafeSpawn());
640  }
641  }
642 
643  if ($this === $defaultLevel) {
644  $this->server->setDefaultLevel(null);
645  }
646 
647  $this->close();
648 
649  return true;
650  }

◆ unloadChunk()

unloadChunk ( int  $x,
int  $z,
bool  $safe = true,
bool  $trySave = true 
)
2779  : bool {
2780  if (($safe === true and $this->isChunkInUse($x, $z))) {
2781  return false;
2782  }
2783 
2784  if (!$this->isChunkLoaded($x, $z)) {
2785  return true;
2786  }
2787 
2788  $this->timings->doChunkUnload->startTiming();
2789 
2790  $index = Level::chunkHash($x, $z);
2791 
2792  $chunk = $this->chunks[$index] ?? null;;
2793 
2794  if ($chunk !== null) {
2795  $this->server->getPluginManager()->callEvent($ev = new ChunkUnloadEvent($this, $chunk));
2796  if ($ev->isCancelled()) {
2797  $this->timings->doChunkUnload->stopTiming();
2798  return false;
2799  }
2800  }
2801 
2802  try {
2803  if ($chunk !== null) {
2804  if ($trySave and $this->getAutoSave() and $chunk->isGenerated()) {
2805  $entities = 0;
2806  foreach ($chunk->getEntities() as $e) {
2807  if ($e instanceof Player) {
2808  continue;
2809  }
2810  ++$entities;
2811  }
2812 
2813  if ($chunk->hasChanged() or count($chunk->getTiles()) > 0 or $entities > 0) {
2814  $this->provider->setChunk($x, $z, $chunk);
2815  $this->provider->saveChunk($x, $z);
2816  }
2817  }
2818 
2819  foreach ($this->getChunkLoaders($x, $z) as $loader) {
2820  $loader->onChunkUnloaded($chunk);
2821  }
2822  }
2823  $this->provider->unloadChunk($x, $z, $safe);
2824  } catch (\Throwable $e) {
2825  $logger = $this->server->getLogger();
2826  $logger->error($this->server->getLanguage()->translateString("pocketmine.level.chunkUnloadError", [$e->getMessage()]));
2827  $logger->logException($e);
2828  }
2829 
2830  unset($this->chunks[$index]);
2831  unset($this->chunkTickList[$index]);
2832  unset($this->chunkCache[$index]);
2833 
2834  $this->timings->doChunkUnload->stopTiming();
2835 
2836  return true;
2837  }

◆ unloadChunkRequest()

unloadChunkRequest ( int  $x,
int  $z,
bool  $safe = true 
)
2765  : bool {
2766  if (($safe === true and $this->isChunkInUse($x, $z)) or $this->isSpawnChunk($x, $z)) {
2767  return false;
2768  }
2769 
2770  $this->queueUnloadChunk($x, $z);
2771 
2772  return true;
2773  }

◆ unloadChunks()

unloadChunks ( bool  $force = false)
3071  {
3072  if (!is_null($this->unloadQueue) && count($this->unloadQueue) > 0) {
3073  $maxUnload = 96;
3074  $now = microtime(true);
3075  foreach ($this->unloadQueue as $index => $time) {
3076  Level::getXZ($index, $X, $Z);
3077 
3078  if (!$force) {
3079  if ($maxUnload <= 0) {
3080  break;
3081  } elseif ($time > ($now - 30)) {
3082  continue;
3083  }
3084  }
3085 
3086  //If the chunk can't be unloaded, it stays on the queue
3087  if ($this->unloadChunk($X, $Z, true)) {
3088  unset($this->unloadQueue[$index]);
3089  --$maxUnload;
3090  }
3091  }
3092  }
3093  }

◆ unregisterChunkLoader()

unregisterChunkLoader ( ChunkLoader  $loader,
int  $chunkX,
int  $chunkZ 
)
713  {
714  if (isset($this->chunkLoaders[$index = Level::chunkHash($chunkX, $chunkZ)][$hash = $loader->getLoaderId()])) {
715  unset($this->chunkLoaders[$index][$hash]);
716  unset($this->playerLoaders[$index][$hash]);
717  if (count($this->chunkLoaders[$index]) === 0) {
718  unset($this->chunkLoaders[$index]);
719  unset($this->playerLoaders[$index]);
720  $this->unloadChunkRequest($chunkX, $chunkZ, true);
721  }
722 
723  if (--$this->loaderCounter[$hash] === 0) {
724  unset($this->loaderCounter[$hash]);
725  unset($this->loaders[$hash]);
726  }
727  }
728  }

◆ unregisterGenerator()

unregisterGenerator ( )
470  {
471  $size = $this->server->getScheduler()->getAsyncTaskPoolSize();
472  for ($i = 0; $i < $size; ++$i) {
473  $this->server->getScheduler()->scheduleAsyncTaskToWorker(new GeneratorUnregisterTask($this), $i);
474  }
475  }

◆ updateAllLight()

updateAllLight ( Vector3  $pos)
1384  {
1385  $this->updateBlockSkyLight($pos->x, $pos->y, $pos->z);
1386  $this->updateBlockLight($pos->x, $pos->y, $pos->z);
1387  }

◆ updateAround()

updateAround ( Vector3  $pos)
Parameters
Vector3$pos
1114  {
1115  $pos = $pos->floor();
1116  $this->server->getPluginManager()->callEvent($ev = new BlockUpdateEvent($this->getBlock($this->temporalVector->setComponents($pos->x, $pos->y - 1, $pos->z))));
1117  if (!$ev->isCancelled()) {
1118  $ev->getBlock()->onUpdate(self::BLOCK_UPDATE_NORMAL);
1119  }
1120 
1121  $this->server->getPluginManager()->callEvent($ev = new BlockUpdateEvent($this->getBlock($this->temporalVector->setComponents($pos->x, $pos->y + 1, $pos->z))));
1122  if (!$ev->isCancelled()) {
1123  $ev->getBlock()->onUpdate(self::BLOCK_UPDATE_NORMAL);
1124  }
1125 
1126  $this->server->getPluginManager()->callEvent($ev = new BlockUpdateEvent($this->getBlock($this->temporalVector->setComponents($pos->x - 1, $pos->y, $pos->z))));
1127  if (!$ev->isCancelled()) {
1128  $ev->getBlock()->onUpdate(self::BLOCK_UPDATE_NORMAL);
1129  }
1130 
1131  $this->server->getPluginManager()->callEvent($ev = new BlockUpdateEvent($this->getBlock($this->temporalVector->setComponents($pos->x + 1, $pos->y, $pos->z))));
1132  if (!$ev->isCancelled()) {
1133  $ev->getBlock()->onUpdate(self::BLOCK_UPDATE_NORMAL);
1134  }
1135 
1136  $this->server->getPluginManager()->callEvent($ev = new BlockUpdateEvent($this->getBlock($this->temporalVector->setComponents($pos->x, $pos->y, $pos->z - 1))));
1137  if (!$ev->isCancelled()) {
1138  $ev->getBlock()->onUpdate(self::BLOCK_UPDATE_NORMAL);
1139  }
1140 
1141  $this->server->getPluginManager()->callEvent($ev = new BlockUpdateEvent($this->getBlock($this->temporalVector->setComponents($pos->x, $pos->y, $pos->z + 1))));
1142  if (!$ev->isCancelled()) {
1143  $ev->getBlock()->onUpdate(self::BLOCK_UPDATE_NORMAL);
1144  }
1145  }

◆ updateBlockLight()

updateBlockLight ( int  $x,
int  $y,
int  $z 
)

Updates the light around the block

Parameters
$x
$y
$z

Implements ChunkManager.

1430  {
1431  $this->timings->doBlockLightUpdates->startTiming();
1432  $id = $this->getBlockIdAt($x, $y, $z);
1433  $newLevel = max(Block::$light[$id], $this->getHighestAdjacentBlockLight($x, $y, $z) - Block::$lightFilter[$id]);
1434  $update = new BlockLightUpdate($this);
1435  $update->setAndUpdateLight($x, $y, $z, $newLevel);
1436  $update->execute();
1437  $this->timings->doBlockLightUpdates->stopTiming();
1438  }

◆ updateBlockSkyLight()

updateBlockSkyLight ( int  $x,
int  $y,
int  $z 
)
1389  {
1390  $this->timings->doBlockSkyLightUpdates->startTiming();
1391  $oldHeightMap = $this->getHeightMap($x, $z);
1392  $sourceId = $this->getBlockIdAt($x, $y, $z);
1393  $yPlusOne = $y + 1;
1394  if ($yPlusOne === $oldHeightMap) { //Block changed directly beneath the heightmap. Check if a block was removed or changed to a different light-filter.
1395  $newHeightMap = $this->getChunk($x >> 4, $z >> 4)->recalculateHeightMapColumn($x & 0x0f, $z & 0x0f);
1396  } elseif ($yPlusOne > $oldHeightMap) { //Block **placed** above the heightmap.
1397  $this->setHeightMap($x, $z, $yPlusOne);
1398  $newHeightMap = $yPlusOne;
1399  } else { //block changed below heightmap
1400  $newHeightMap = $oldHeightMap;
1401  }
1402  $update = new SkyLightUpdate($this);
1403  if ($newHeightMap > $oldHeightMap) { //Heightmap increase, block placed, remove sky light
1404  for ($i = $y; $i >= $oldHeightMap; --$i) {
1405  $update->setAndUpdateLight($x, $i, $z, 0); //Remove all light beneath, adjacent recalculation will handle the rest.
1406  }
1407  } elseif ($newHeightMap < $oldHeightMap) { //Heightmap decrease, block changed or removed, add sky light
1408  for ($i = $y; $i >= $newHeightMap; --$i) {
1409  $update->setAndUpdateLight($x, $i, $z, 15);
1410  }
1411  } else { //No heightmap change, block changed "underground"
1412  $update->setAndUpdateLight($x, $y, $z, max(0, $this->getHighestAdjacentBlockLight($x, $y, $z) - Block::$lightFilter[$sourceId]));
1413  }
1414  $update->execute();
1415  $this->timings->doBlockSkyLightUpdates->stopTiming();
1416  }

◆ useBreakOn()

useBreakOn ( Vector3  $vector,
Item $item = null,
Player  $player = null,
bool  $createParticles = false 
)

Tries to break a block using a item, including Player time checks if available It'll try to lower the durability if Item is a tool, and set it to Air if broken.

Parameters
Vector3$vector
Item&$item(if null, can break anything)
Player$player
bool$createParticles
Returns
bool
1605  : bool {
1606  $target = $this->getBlock($vector);
1607 
1608  if ($item === null) {
1609  $item = Item::get(Item::AIR, 0, 0);
1610  }
1611 
1612  if ($player !== null) {
1613  $ev = new BlockBreakEvent($player, $target, $item, ($player->isCreative() or $player->allowInstaBreak()));
1614 
1615  if ($player->isAdventure() or $player->isSpectator() or ($player->isSurvival() and $item instanceof Item and !$target->isBreakable($item))) {
1616  $ev->setCancelled();
1617  } elseif (!$player->isOp() and ($distance = $this->server->getSpawnRadius()) > -1) {
1618  $t = new Vector2($target->x, $target->z);
1619  $s = new Vector2($this->getSpawnLocation()->x, $this->getSpawnLocation()->z);
1620  if (count($this->server->getOps()->getAll()) > 0 and $t->distance($s) <= $distance) { //set it to cancelled so plugins can bypass this
1621  $ev->setCancelled();
1622  }
1623  }
1624  $this->server->getPluginManager()->callEvent($ev);
1625  if ($ev->isCancelled()) {
1626  return false;
1627  }
1628 
1629  $breakTime = ceil($target->getBreakTime($item) * 20);
1630 
1631  if ($player->isCreative() and $breakTime > 3) {
1632  $breakTime = 3;
1633  }
1634 
1635  if ($player->hasEffect(Effect::SWIFTNESS)) {
1636  $breakTime *= 1 - (0.2 * ($player->getEffect(Effect::SWIFTNESS)->getAmplifier() + 1));
1637  }
1638 
1639  if ($player->hasEffect(Effect::MINING_FATIGUE)) {
1640  $breakTime *= 1 + (0.3 * ($player->getEffect(Effect::MINING_FATIGUE)->getAmplifier() + 1));
1641  }
1642 
1643  $breakTime -= 1; //1 tick compensation
1644 
1645  if (!$ev->getInstaBreak() and ((ceil($player->lastBreak * 20)) + $breakTime) > ceil(microtime(true) * 20)) {
1646  return false;
1647  }
1648 
1649  $player->lastBreak = PHP_INT_MAX;
1650 
1651  $drops = $ev->getDrops();
1652 
1653  if ($player->isSurvival() and $this->getServer()->expEnabled) {
1654  $exp = 0;
1655  if ($item->getEnchantmentLevel(Enchantment::TYPE_MINING_SILK_TOUCH) === 0) {
1656  switch ($target->getId()) {
1657  case Block::COAL_ORE:
1658  $exp = mt_rand(0, 2);
1659  break;
1660  case Block::DIAMOND_ORE:
1661  case Block::EMERALD_ORE:
1662  $exp = mt_rand(3, 7);
1663  break;
1665  case Block::LAPIS_ORE:
1666  $exp = mt_rand(2, 5);
1667  break;
1668  case Block::REDSTONE_ORE:
1670  $exp = mt_rand(1, 5);
1671  break;
1672  }
1673  }
1674  switch ($target->getId()) {
1676  $exp = mt_rand(15, 43);
1677  break;
1678  }
1679  if ($exp > 0) {
1680  $this->spawnXPOrb($vector->add(0, 1, 0), $exp);
1681  }
1682  }
1683 
1684  } elseif ($item !== null and !$target->isBreakable($item)) {
1685  return false;
1686  } else {
1687  $drops = $target->getDrops($item); //Fixes tile entities being deleted before getting drops
1688  foreach ($drops as $k => $i) {
1689  if ((isset ($i[0])) && (isset ($i[1])) && (isset ($i[2]))) $drops[$k] = Item::get($i[0], $i[1], $i[2]);
1690  }
1691  }
1692 
1693  $above = $this->getBlock(new Vector3($target->x, $target->y + 1, $target->z));
1694  if ($above !== null) {
1695  if ($above->getId() === Item::FIRE) {
1696  $this->setBlock($above, new Air(), true);
1697  }
1698  }
1699 
1700  $tag = $item->getNamedTagEntry("CanDestroy");
1701  if ($tag instanceof ListTag) {
1702  $canBreak = false;
1703  foreach ($tag as $v) {
1704  if ($v instanceof StringTag) {
1705  $entry = Item::fromString($v->getValue());
1706  if ($entry->getId() > 0 and $entry->getBlock() !== null and $entry->getBlock()->getId() === $target->getId()) {
1707  $canBreak = true;
1708  break;
1709  }
1710  }
1711  }
1712 
1713  if (!$canBreak) {
1714  return false;
1715  }
1716  }
1717 
1718  if ($createParticles) {
1719  $this->addParticle(new DestroyBlockParticle($target, $target));
1720  }
1721 
1722  $target->onBreak($item);
1723 
1724  $tile = $this->getTile($target);
1725  if ($tile !== null) {
1726  if ($tile instanceof InventoryHolder) {
1727  if ($tile instanceof Chest) {
1728  $tile->unpair();
1729  }
1730 
1731  foreach ($tile->getInventory()->getContents() as $chestItem) {
1732  $this->dropItem($target, $chestItem);
1733  }
1734  }
1735 
1736  $tile->close();
1737  }
1738 
1739  if ($item !== null) {
1740  $item->useOn($target);
1741  if ($item->isTool() and $item->getDamage() >= $item->getMaxDurability()) {
1742  $item = Item::get(Item::AIR, 0, 0);
1743  }
1744  }
1745 
1746  if ($player === null or $player->isSurvival()) {
1747  foreach ($drops as $drop) {
1748  if ($drop->getCount() > 0) {
1749  $this->dropItem($vector->add(0.5, 0.5, 0.5), $drop);
1750  }
1751  }
1752  }
1753 
1754  return true;
1755  }

◆ useItemOn()

useItemOn ( Vector3  $vector,
Item $item,
int  $face,
float  $fx = 0.0,
float  $fy = 0.0,
float  $fz = 0.0,
Player  $player = null 
)

Uses a item on a position and face, placing it or activating the block

Parameters
Vector3$vector
Item$item
int$face
float$fxdefault 0.0
float$fydefault 0.0
float$fzdefault 0.0
Player$playerdefault null
Returns
bool
1770  : bool {
1771  $target = $this->getBlock($vector);
1772  $block = $target->getSide($face);
1773 
1774  if ($block->y >= $this->provider->getWorldHeight() or $block->y < 0) {
1775  //TODO: build height limit messages for custom world heights and mcregion cap
1776  return false;
1777  }
1778 
1779  if ($target->getId() === Item::AIR) {
1780  return false;
1781  }
1782 
1783  if ($player !== null) {
1784  $ev = new PlayerInteractEvent($player, $item, $target, $face, $target->getId() === 0 ? PlayerInteractEvent::RIGHT_CLICK_AIR : PlayerInteractEvent::RIGHT_CLICK_BLOCK);
1785  if (!$player->isOp() and ($distance = $this->server->getSpawnRadius()) > -1) {
1786  $t = new Vector2($target->x, $target->z);
1787  $s = new Vector2($this->getSpawnLocation()->x, $this->getSpawnLocation()->z);
1788  if (count($this->server->getOps()->getAll()) > 0 and $t->distance($s) <= $distance) { //set it to cancelled so plugins can bypass this
1789  $ev->setCancelled();
1790  }
1791  }
1792  if ($player->isSpectator()) {
1793  $ev->setCancelled();
1794  }
1795  $this->server->getPluginManager()->callEvent($ev);
1796  if (!$ev->isCancelled()) {
1797  $target->onUpdate(self::BLOCK_UPDATE_TOUCH);
1798  if (!$player->isSneaking()) {
1799  if ($target->canBeActivated() === true and $target->onActivate($item, $player) === true) {
1800  if ($item->getCount() <= 0) {
1801  $item = Item::get(Item::AIR, 0, 0);
1802  } elseif ($item->isTool() and $item->getDamage() >= $item->getMaxDurability()) {
1803  $item = Item::get(Item::AIR, 0, 0);
1804  }
1805  return true;
1806  }
1807  if ($item->canBeActivated() and $item->onActivate($this, $player, $block, $target, $face, $fx, $fy, $fz)) {
1808  if ($item->getCount() <= 0) {
1809  $item = Item::get(Item::AIR, 0, 0);
1810  return true;
1811  } elseif ($item->isTool() and $item->getDamage() >= $item->getMaxDurability()) {
1812  $item = Item::get(Item::AIR, 0, 0);
1813  return true;
1814  }
1815  }
1816  }
1817  /*if(!$player->isSneaking() and $target->canBeActivated() === true and $target->onActivate($item, $player) === true){
1818  return true;
1819  }
1820 
1821  if(!$player->isSneaking() and $item->canBeActivated() and $item->onActivate($this, $player, $block, $target, $face, $fx, $fy, $fz)){
1822  if($item->getCount() <= 0){
1823  $item = Item::get(Item::AIR, 0, 0);
1824 
1825  return true;
1826  }
1827  }*/
1828  } else {
1829  return false;
1830  }
1831  } elseif ($target->canBeActivated() === true and $target->onActivate($item, $player) === true) {
1832  return true;
1833  }
1834 
1835  if ($item->canBePlaced()) {
1836  $hand = $item->getBlock();
1837  $hand->position($block);
1838  } else {
1839  return false;
1840  }
1841 
1842  if (!($block->canBeReplaced() === true or ($hand->getId() === Item::SLAB and $block->getId() === Item::SLAB))) {
1843  return false;
1844  }
1845 
1846  if ($target->canBeReplaced() === true) {
1847  $block = $target;
1848  $hand->position($block);
1849  //$face = -1;
1850  }
1851 
1852  if ($hand->isSolid() === true and $hand->getBoundingBox() !== null) {
1853  $entities = $this->getCollidingEntities($hand->getBoundingBox());
1854  $realCount = 0;
1855  foreach ($entities as $e) {
1856  if ($e instanceof Arrow or $e instanceof DroppedItem or ($e instanceof Player and $e->isSpectator())) {
1857  continue;
1858  }
1859  ++$realCount;
1860  }
1861 
1862  if ($player !== null) {
1863  if (($diff = $player->getNextPosition()->subtract($player->getPosition())) and $diff->lengthSquared() > 0.00001) {
1864  $bb = $player->getBoundingBox()->getOffsetBoundingBox($diff->x, $diff->y, $diff->z);
1865  if ($hand->getBoundingBox()->intersectsWith($bb)) {
1866  ++$realCount;
1867  }
1868  }
1869  }
1870 
1871  if ($realCount > 0) {
1872  return false; //Entity in block
1873  }
1874  }
1875 
1876  $tag = $item->getNamedTagEntry("CanPlaceOn");
1877  if ($tag instanceof ListTag) {
1878  $canPlace = false;
1879  foreach ($tag as $v) {
1880  if ($v instanceof StringTag) {
1881  $entry = Item::fromString($v->getValue());
1882  if ($entry->getId() > 0 and $entry->getBlock() !== null and $entry->getBlock()->getId() === $target->getId()) {
1883  $canPlace = true;
1884  break;
1885  }
1886  }
1887  }
1888 
1889  if (!$canPlace) {
1890  return false;
1891  }
1892  }
1893 
1894 
1895  if ($player !== null) {
1896  $ev = new BlockPlaceEvent($player, $hand, $block, $target, $item);
1897  if (!$player->isOp() and ($distance = $this->server->getSpawnRadius()) > -1) {
1898  $t = new Vector2($target->x, $target->z);
1899  $s = new Vector2($this->getSpawnLocation()->x, $this->getSpawnLocation()->z);
1900  if (count($this->server->getOps()->getAll()) > 0 and $t->distance($s) <= $distance) { //set it to cancelled so plugins can bypass this
1901  $ev->setCancelled();
1902  }
1903  }
1904  $this->server->getPluginManager()->callEvent($ev);
1905  if ($ev->isCancelled()) {
1906  return false;
1907  }
1908 
1909  $this->addSound(new BlockPlaceSound($hand));
1910  }
1911 
1912  if ($hand->place($item, $block, $target, $face, $fx, $fy, $fz, $player) === false) {
1913  return false;
1914  }
1915  $item->setCount($item->getCount() - 1);
1916 
1917  if ($item->getCount() <= 0) {
1918  $item = Item::get(Item::AIR, 0, 0);
1919  }
1920 
1921  return true;
1922  }

Field Documentation

◆ $COMPRESSION_LEVEL

$COMPRESSION_LEVEL = 8
static

◆ $sleepTicks

$sleepTicks = 0

◆ $stopTime

◆ $tickRateCounter

$tickRateCounter = 0

◆ $tickRateTime

$tickRateTime = 0

◆ $timings

$timings

◆ $updateEntities

$updateEntities = []

◆ $updateTiles

$updateTiles = []

◆ BLOCK_UPDATE_NORMAL

const BLOCK_UPDATE_NORMAL = 1

◆ BLOCK_UPDATE_RANDOM

const BLOCK_UPDATE_RANDOM = 2

◆ BLOCK_UPDATE_SCHEDULED

const BLOCK_UPDATE_SCHEDULED = 3

◆ BLOCK_UPDATE_TOUCH

const BLOCK_UPDATE_TOUCH = 5

◆ BLOCK_UPDATE_WEAK

const BLOCK_UPDATE_WEAK = 4

◆ DIMENSION_END

const DIMENSION_END = 2

◆ DIMENSION_NETHER

const DIMENSION_NETHER = 1

◆ DIMENSION_NORMAL

const DIMENSION_NORMAL = 0

◆ TIME_DAY

const TIME_DAY = 0

◆ TIME_FULL

const TIME_FULL = 24000

◆ TIME_NIGHT

const TIME_NIGHT = 14000

◆ TIME_SUNRISE

const TIME_SUNRISE = 23000

◆ TIME_SUNSET

const TIME_SUNSET = 12000

◆ Y_MASK

const Y_MASK = 0xFF

◆ Y_MAX

const Y_MAX = 0x100

The documentation for this class was generated from the following file: