public function __construct(Level $level, FullChunk $chunk) { $this->state = true; $this->levelId = $level->getId(); $this->chunk = $chunk->toFastBinary(); $this->chunkClass = get_class($chunk); }
public function __construct(Level $level, Generator $generator) { $this->generator = get_class($generator); $this->settings = $generator->getSettings(); $this->seed = $level->getSeed(); $this->levelId = $level->getId(); }
public function __construct(Level $level) { $name = $level->getFolderName() . " - "; $this->mobSpawn = new TimingsHandler("** " . $name . "mobSpawn"); $this->doChunkUnload = new TimingsHandler("** " . $name . "doChunkUnload"); $this->doTickPending = new TimingsHandler("** " . $name . "doTickPending"); $this->doTickTiles = new TimingsHandler("** " . $name . "doTickTiles"); $this->doVillages = new TimingsHandler("** " . $name . "doVillages"); $this->doChunkMap = new TimingsHandler("** " . $name . "doChunkMap"); $this->doSounds = new TimingsHandler("** " . $name . "doSounds"); $this->doChunkGC = new TimingsHandler("** " . $name . "doChunkGC"); $this->doPortalForcer = new TimingsHandler("** " . $name . "doPortalForcer"); $this->entityTick = new TimingsHandler("** " . $name . "entityTick"); $this->tileEntityTick = new TimingsHandler("** " . $name . "tileEntityTick"); $this->tileEntityPending = new TimingsHandler("** " . $name . "tileEntityPending"); $this->syncChunkSendTimer = new TimingsHandler("** " . $name . "syncChunkSend"); $this->syncChunkSendPrepareTimer = new TimingsHandler("** " . $name . "syncChunkSendPrepare"); $this->syncChunkLoadTimer = new TimingsHandler("** " . $name . "syncChunkLoad"); $this->syncChunkLoadDataTimer = new TimingsHandler("** " . $name . "syncChunkLoad - Data"); $this->syncChunkLoadStructuresTimer = new TimingsHandler("** " . $name . "syncChunkLoad - Structures"); $this->syncChunkLoadEntitiesTimer = new TimingsHandler("** " . $name . "syncChunkLoad - Entities"); $this->syncChunkLoadTileEntitiesTimer = new TimingsHandler("** " . $name . "syncChunkLoad - TileEntities"); $this->syncChunkLoadTileTicksTimer = new TimingsHandler("** " . $name . "syncChunkLoad - TileTicks"); $this->syncChunkLoadPostTimer = new TimingsHandler("** " . $name . "syncChunkLoad - Post"); $this->tracker = new TimingsHandler($name . "tracker"); $this->doTick = new TimingsHandler($name . "doTick"); $this->tickEntities = new TimingsHandler($name . "tickEntities"); }
public function setMetadata($block, $metadataKey, MetadataValue $newMetadatavalue) { if (!$block instanceof Block) { throw new \InvalidArgumentException("Object must be a Block"); } if ($block->getLevel() === $this->owningLevel) { parent::setMetadata($block, $metadataKey, $newMetadatavalue); } else { throw new \InvalidStateException("Block does not belong to world " . $this->owningLevel->getName()); } }
public function onActivate(Level $level, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz) { if (($player->gamemode & 0x1) === 0 and $this->useOn($block) and $this->getDamage() >= $this->getMaxDurability()) { $player->getInventory()->setItemInHand(new Item(Item::AIR, 0, 0)); } if ($block->getId() === self::AIR and $target instanceof Solid) { $level->setBlock($block, new Fire(), true); return true; } return false; }
public function __construct(Level $level, FullChunk $chunk) { $this->state = true; $this->levelId = $level->getId(); $this->chunk = $chunk->toFastBinary(); $this->chunkClass = get_class($chunk); for ($i = 0; $i < 9; ++$i) { if ($i === 4) { continue; } $xx = -1 + $i % 3; $zz = -1 + (int) ($i / 3); $ck = $level->getChunk($chunk->getX() + $xx, $chunk->getZ() + $zz, false); $this->{"chunk{$i}"} = $ck !== null ? $ck->toFastBinary() : null; } }
public function onActivate(Level $level, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz) { $entity = null; $chunk = $level->getChunk($block->getX() >> 4, $block->getZ() >> 4); if (!$chunk instanceof FullChunk) { return false; } $nbt = new Compound("", ["Pos" => new Enum("Pos", [new Double("", $block->getX() + 0.5), new Double("", $block->getY()), new Double("", $block->getZ() + 0.5)]), "Motion" => new Enum("Motion", [new Double("", 0), new Double("", 0), new Double("", 0)]), "Rotation" => new Enum("Rotation", [new Float("", lcg_value() * 360), new Float("", 0)])]); if ($this->hasCustomName()) { $nbt->CustomName = new String("CustomName", $this->getCustomName()); } $entity = Entity::createEntity($this->meta, $chunk, $nbt); if ($entity instanceof Entity) { $entity->setDataFlag(Entity::DATA_FLAGS, Entity::DATA_NO_AI, true); $entity->getLevel()->getServer()->broadcastPopup(TextFormat::RED . "Mob AI isn't implemented yet!"); if ($player->isSurvival()) { --$this->count; } $entity->spawnToAll(); return true; } return false; }
public function setBlockExtraData($x, $y, $z, $data) { if ($data === 0) { unset($this->extraData[Level::chunkBlockHash($x, $y, $z)]); } else { $this->extraData[Level::chunkBlockHash($x, $y, $z)] = $data; } $this->setChanged(true); }
public function setRedstoneUpdateList($type, $power) { if ($type === Level::REDSTONE_UPDATE_NORMAL) { if ($power > $this->getPower() + 1) { $this_hash = Level::blockHash($this->x, $this->y, $this->z); $this->getLevel()->RedstoneUpdaters[$this_hash] = false; $thispower = $power - 1; $this->getLevel()->RedstoneUpdateList[$this_hash] = ['x' => $this->x, 'y' => $this->y, 'z' => $this->z, 'power' => $thispower]; for ($side = 2; $side <= 5; $side++) { $near = $this->getSide($side); if ($near instanceof RedstoneTransmitter) { $near->setRedstoneUpdateList($type, $thispower); } else { $around_down = $near->getSide(0); $around_up = $near->getSide(1); if ($near->getId() == Block::AIR and $around_down instanceof RedstoneTransmitter) { $around_down->setRedstoneUpdateList($type, $thispower); } elseif (!$near instanceof Transparent and $around_up instanceof RedstoneTransmitter) { $around_up->setRedstoneUpdateList($type, $thispower); } } } $this->getLevel()->RedstoneUpdaters[$this_hash] = true; $this->doRedstoneListUpdate(); } else { return; } } if ($type === Level::REDSTONE_UPDATE_REPOWER) { $type = Level::REDSTONE_UPDATE_NORMAL; $this_hash = Level::blockHash($this->x, $this->y, $this->z); unset($this->getLevel()->RedstoneRepowers[$this_hash]); $thispower = $this->getPower(); $this->getLevel()->RedstoneUpdateList[$this_hash] = ['x' => $this->x, 'y' => $this->y, 'z' => $this->z, 'power' => $thispower]; for ($side = 2; $side <= 5; $side++) { $near = $this->getSide($side); if ($near instanceof RedstoneTransmitter) { $near->setRedstoneUpdateList($type, $thispower); } else { $around_down = $near->getSide(0); $around_up = $near->getSide(1); if ($near->getId() == Block::AIR and $around_down instanceof RedstoneTransmitter) { $around_down->setRedstoneUpdateList($type, $thispower); } elseif (!$near instanceof Transparent and $around_up instanceof RedstoneTransmitter) { $around_up->setRedstoneUpdateList($type, $thispower); } } } $this->doRedstoneListUpdate(); } if ($type === Level::REDSTONE_UPDATE_LOSTPOWER) { if ($this->getPower() !== 0 and $power >= $this->getPower + 1) { $thispower = $this->getPower(); $this_hash = Level::blockHash($this->x, $this->y, $this->z); $this->getLevel()->RedstoneUpdateList[$this_hash] = ['x' => $this->x, 'y' => $this->y, 'z' => $this->z, 'power' => 0]; $FetchedMaxPower = $this->fetchMaxPower(); if ($FetchedMaxPower == Block::REDSTONESOURCEPOWER) { unset($this->getLevel()->RedstoneUpdateList[$this_hash]); $this->getLevel()->RedstoneRepowers[$this_hash] = ['x' => $this->x, 'y' => $this->y, 'z' => $this->z]; return; } $this->getLevel()->RedstoneUpdaters[$this_hash] = false; for ($side = 2; $side <= 5; $side++) { $near = $this->getSide($side); if ($near instanceof RedstoneTransmitter) { $near_hash = Level::blockHash($near->x, $near->y, $near->z); if (isset($this->getLevel()->RedstoneUpdateList[$near_hash])) { continue; } $near->setRedstoneUpdateList($type, $thispower); } else { $around_down = $near->getSide(0); $around_up = $near->getSide(1); if ($near->getId() == Block::AIR and $around_down instanceof RedstoneTransmitter) { $around_down_hash = Level::blockHash($around_down->x, $around_down->y, $around_down->z); if (isset($this->getLevel()->RedstoneUpdateList[$around_down_hash])) { continue; } $around_down->setRedstoneUpdateList($type, $thispower); } elseif (!$near instanceof Transparent and $around_up instanceof RedstoneTransmitter) { $around_up_hash = Level::blockHash($around_up->x, $around_up->y, $around_up->z); if (isset($this->getLevel()->RedstoneUpdateList[$around_up_hash])) { continue; } $around_up->setRedstoneUpdateList($type, $thispower); } } } $this->getLevel()->RedstoneUpdaters[$this_hash] = true; $this->doRedstoneListUpdate(); } } }
protected function loadRegion($x, $z) { if (!isset($this->regions[$index = Level::chunkHash($x, $z)])) { $this->regions[$index] = new RegionLoader($this, $x, $z); } }
public function __construct(Level $level) { $this->levelId = $level->getId(); }
public function onChunkChanged(FullChunk $chunk) { $this->loadQueue[Level::chunkHash($chunk->getX(), $chunk->getZ())] = abs(($this->x >> 4) - $chunk->getX()) + abs(($this->z >> 4) - $chunk->getZ()); }
public function __construct(Level $level, Vector3 $start, Vector3 $direction, $yOffset = 0, $maxDistance = 0) { $this->level = $level; $this->maxDistance = (int) $maxDistance; $this->blockQueue = new \SplFixedArray(3); $startClone = new Vector3($start->x, $start->y, $start->z); $startClone->y += $yOffset; $this->currentDistance = 0; $mainDirection = 0; $secondDirection = 0; $thirdDirection = 0; $mainPosition = 0; $secondPosition = 0; $thirdPosition = 0; $pos = new Vector3($startClone->x, $startClone->y, $startClone->z); $startBlock = $this->level->getBlock(new Vector3(floor($pos->x), floor($pos->y), floor($pos->z))); if ($this->getXLength($direction) > $mainDirection) { $this->mainFace = $this->getXFace($direction); $mainDirection = $this->getXLength($direction); $mainPosition = $this->getXPosition($direction, $startClone, $startBlock); $this->secondFace = $this->getYFace($direction); $secondDirection = $this->getYLength($direction); $secondPosition = $this->getYPosition($direction, $startClone, $startBlock); $this->thirdFace = $this->getZFace($direction); $thirdDirection = $this->getZLength($direction); $thirdPosition = $this->getZPosition($direction, $startClone, $startBlock); } if ($this->getYLength($direction) > $mainDirection) { $this->mainFace = $this->getYFace($direction); $mainDirection = $this->getYLength($direction); $mainPosition = $this->getYPosition($direction, $startClone, $startBlock); $this->secondFace = $this->getZFace($direction); $secondDirection = $this->getZLength($direction); $secondPosition = $this->getZPosition($direction, $startClone, $startBlock); $this->thirdFace = $this->getXFace($direction); $thirdDirection = $this->getXLength($direction); $thirdPosition = $this->getXPosition($direction, $startClone, $startBlock); } if ($this->getZLength($direction) > $mainDirection) { $this->mainFace = $this->getZFace($direction); $mainDirection = $this->getZLength($direction); $mainPosition = $this->getZPosition($direction, $startClone, $startBlock); $this->secondFace = $this->getXFace($direction); $secondDirection = $this->getXLength($direction); $secondPosition = $this->getXPosition($direction, $startClone, $startBlock); $this->thirdFace = $this->getYFace($direction); $thirdDirection = $this->getYLength($direction); $thirdPosition = $this->getYPosition($direction, $startClone, $startBlock); } $d = $mainPosition / $mainDirection; $secondd = $secondPosition - $secondDirection * $d; $thirdd = $thirdPosition - $thirdDirection * $d; $this->secondError = floor($secondd * self::$gridSize); $this->secondStep = round($secondDirection / $mainDirection * self::$gridSize); $this->thirdError = floor($thirdd * self::$gridSize); $this->thirdStep = round($thirdDirection / $mainDirection * self::$gridSize); if ($this->secondError + $this->secondStep <= 0) { $this->secondError = -$this->secondStep + 1; } if ($this->thirdError + $this->thirdStep <= 0) { $this->thirdError = -$this->thirdStep + 1; } $lastBlock = $startBlock->getSide(Vector3::getOppositeSide($this->mainFace)); if ($this->secondError < 0) { $this->secondError += self::$gridSize; $lastBlock = $lastBlock->getSide(Vector3::getOppositeSide($this->secondFace)); } if ($this->thirdError < 0) { $this->thirdError += self::$gridSize; $lastBlock = $lastBlock->getSide(Vector3::getOppositeSide($this->thirdFace)); } $this->secondError -= self::$gridSize; $this->thirdError -= self::$gridSize; $this->blockQueue[0] = $lastBlock; $this->currentBlock = -1; $this->scan(); $startBlockFound = false; for ($cnt = $this->currentBlock; $cnt >= 0; --$cnt) { if ($this->blockEquals($this->blockQueue[$cnt], $startBlock)) { $this->currentBlock = $cnt; $startBlockFound = true; break; } } if (!$startBlockFound) { throw new \InvalidStateException("Start block missed in BlockIterator"); } $this->maxDistanceInt = round($maxDistance / (sqrt($mainDirection ** 2 + $secondDirection ** 2 + $thirdDirection ** 2) / $mainDirection)); }
public function generateChunk($chunkX, $chunkZ) { $this->random->setSeed(0xdeadbeef ^ $chunkX << 8 ^ $chunkZ ^ $this->level->getSeed()); $noise = Generator::getFastNoise3D($this->noiseBase, 16, 128, 16, 4, 8, 4, $chunkX * 16, 0, $chunkZ * 16); $chunk = $this->level->getChunk($chunkX, $chunkZ); $biomeCache = []; for ($x = 0; $x < 16; ++$x) { for ($z = 0; $z < 16; ++$z) { $minSum = 0; $maxSum = 0; $weightSum = 0; $biome = $this->pickBiome($chunkX * 16 + $x, $chunkZ * 16 + $z); $chunk->setBiomeId($x, $z, $biome->getId()); $color = [0, 0, 0]; for ($sx = -self::$SMOOTH_SIZE; $sx <= self::$SMOOTH_SIZE; ++$sx) { for ($sz = -self::$SMOOTH_SIZE; $sz <= self::$SMOOTH_SIZE; ++$sz) { $weight = self::$GAUSSIAN_KERNEL[$sx + self::$SMOOTH_SIZE][$sz + self::$SMOOTH_SIZE]; if ($sx === 0 and $sz === 0) { $adjacent = $biome; } else { $index = Level::chunkHash($chunkX * 16 + $x + $sx, $chunkZ * 16 + $z + $sz); if (isset($biomeCache[$index])) { $adjacent = $biomeCache[$index]; } else { $biomeCache[$index] = $adjacent = $this->pickBiome($chunkX * 16 + $x + $sx, $chunkZ * 16 + $z + $sz); } } $minSum += ($adjacent->getMinElevation() - 1) * $weight; $maxSum += $adjacent->getMaxElevation() * $weight; $bColor = $adjacent->getColor(); $color[0] += ($bColor >> 16) ** 2 * $weight; $color[1] += ($bColor >> 8 & 0xff) ** 2 * $weight; $color[2] += ($bColor & 0xff) ** 2 * $weight; $weightSum += $weight; } } $minSum /= $weightSum; $maxSum /= $weightSum; $chunk->setBiomeColor($x, $z, sqrt($color[0] / $weightSum), sqrt($color[1] / $weightSum), sqrt($color[2] / $weightSum)); $solidLand = false; for ($y = 127; $y >= 0; --$y) { if ($y === 0) { $chunk->setBlockId($x, $y, $z, Block::BEDROCK); continue; } // A noiseAdjustment of 1 will guarantee ground, a noiseAdjustment of -1 will guarantee air. //$effHeight = min($y - $smoothHeight - $minSum, $noiseAdjustment = 2 * (($maxSum - $y) / ($maxSum - $minSum)) - 1; // To generate caves, we bring the noiseAdjustment down away from 1. $caveLevel = $minSum - 10; $distAboveCaveLevel = max(0, $y - $caveLevel); // must be positive $noiseAdjustment = min($noiseAdjustment, 0.4 + $distAboveCaveLevel / 10); $noiseValue = $noise[$x][$z][$y] + $noiseAdjustment; if ($noiseValue > 0) { $chunk->setBlockId($x, $y, $z, Block::STONE); $solidLand = true; } elseif ($y <= $this->waterHeight && $solidLand == false) { $chunk->setBlockId($x, $y, $z, Block::STILL_WATER); } } } } foreach ($this->generationPopulators as $populator) { $populator->populate($this->level, $chunkX, $chunkZ, $this->random); } }
/** * @param int $chunkX * @param int $chunkZ * @param FullChunk $chunk */ public function setChunk($chunkX, $chunkZ, FullChunk $chunk = null) { if ($chunk === null) { unset($this->chunks[Level::chunkHash($chunkX, $chunkZ)]); return; } $this->chunks[Level::chunkHash($chunkX, $chunkZ)] = $chunk; }
public function getHash() { return Level::blockHash($this->x, $this->y, $this->z); }
public function setChunk($chunkX, $chunkZ, FullChunk $chunk) { if (!$chunk instanceof Chunk) { throw new ChunkException("Invalid Chunk class"); } $chunk->setProvider($this); $chunk->setX($chunkX); $chunk->setZ($chunkZ); if (isset($this->chunks[$index = Level::chunkHash($chunkX, $chunkZ)]) and $this->chunks[$index] !== $chunk) { $this->unloadChunk($chunkX, $chunkZ, false); } $this->chunks[$index] = $chunk; }
public function addEntityMovement($chunkX, $chunkZ, $entityId, $x, $y, $z, $yaw, $pitch, $headYaw = null) { if (!isset($this->moveToSend[$index = Level::chunkHash($chunkX, $chunkZ)])) { $this->moveToSend[$index] = []; } $this->moveToSend[$index][$entityId] = [$entityId, $x, $y, $z, $yaw, $headYaw === null ? $yaw : $headYaw, $pitch]; }
public function explodeB() { $send = []; $updateBlocks = []; $source = (new Vector3($this->source->x, $this->source->y, $this->source->z))->floor(); $yield = 1 / $this->size * 100; if ($this->what instanceof Entity) { $this->level->getServer()->getPluginManager()->callEvent($ev = new EntityExplodeEvent($this->what, $this->source, $this->affectedBlocks, $yield)); if ($ev->isCancelled()) { return false; } else { $yield = $ev->getYield(); $this->affectedBlocks = $ev->getBlockList(); } } $explosionSize = $this->size * 2; $minX = Math::floorFloat($this->source->x - $explosionSize - 1); $maxX = Math::ceilFloat($this->source->x + $explosionSize + 1); $minY = Math::floorFloat($this->source->y - $explosionSize - 1); $maxY = Math::ceilFloat($this->source->y + $explosionSize + 1); $minZ = Math::floorFloat($this->source->z - $explosionSize - 1); $maxZ = Math::ceilFloat($this->source->z + $explosionSize + 1); $explosionBB = new AxisAlignedBB($minX, $minY, $minZ, $maxX, $maxY, $maxZ); $list = $this->level->getNearbyEntities($explosionBB, $this->what instanceof Entity ? $this->what : null); foreach ($list as $entity) { $distance = $entity->distance($this->source) / $explosionSize; if ($distance <= 1) { $motion = $entity->subtract($this->source)->normalize(); $impact = (1 - $distance) * ($exposure = 1); $damage = (int) (($impact * $impact + $impact) / 2 * 8 * $explosionSize + 1); if ($this->what instanceof Entity) { $ev = new EntityDamageByEntityEvent($this->what, $entity, EntityDamageEvent::CAUSE_ENTITY_EXPLOSION, $damage); } elseif ($this->what instanceof Block) { $ev = new EntityDamageByBlockEvent($this->what, $entity, EntityDamageEvent::CAUSE_BLOCK_EXPLOSION, $damage); } else { $ev = new EntityDamageEvent($entity, EntityDamageEvent::CAUSE_BLOCK_EXPLOSION, $damage); } $entity->attack($ev->getFinalDamage(), $ev); $entity->setMotion($motion->multiply($impact)); } } $air = Item::get(Item::AIR); foreach ($this->affectedBlocks as $block) { if ($block->getId() === Block::TNT) { $mot = (new Random())->nextSignedFloat() * M_PI * 2; $tnt = Entity::createEntity("PrimedTNT", $this->level->getChunk($block->x >> 4, $block->z >> 4), new Compound("", ["Pos" => new Enum("Pos", [new Double("", $block->x + 0.5), new Double("", $block->y), new Double("", $block->z + 0.5)]), "Motion" => new Enum("Motion", [new Double("", -sin($mot) * 0.02), new Double("", 0.2), new Double("", -cos($mot) * 0.02)]), "Rotation" => new Enum("Rotation", [new Float("", 0), new Float("", 0)]), "Fuse" => new Byte("Fuse", mt_rand(10, 30))])); $tnt->spawnToAll(); } elseif (mt_rand(0, 100) < $yield) { foreach ($block->getDrops($air) as $drop) { $this->level->dropItem($block->add(0.5, 0.5, 0.5), Item::get(...$drop)); } } $this->level->setBlockIdAt($block->x, $block->y, $block->z, 0); $pos = new Vector3($block->x, $block->y, $block->z); for ($side = 0; $side < 5; $side++) { $sideBlock = $pos->getSide($side); if (!isset($this->affectedBlocks[$index = Level::blockHash($sideBlock->x, $sideBlock->y, $sideBlock->z)]) and !isset($updateBlocks[$index])) { $this->level->getServer()->getPluginManager()->callEvent($ev = new BlockUpdateEvent($this->level->getBlock($sideBlock))); if (!$ev->isCancelled()) { $ev->getBlock()->onUpdate(Level::BLOCK_UPDATE_NORMAL); } $updateBlocks[$index] = true; } } $send[] = new Vector3($block->x - $source->x, $block->y - $source->y, $block->z - $source->z); } $pk = new ExplodePacket(); $pk->x = $this->source->x; $pk->y = $this->source->y; $pk->z = $this->source->z; $pk->radius = $this->size; $pk->records = $send; $this->level->addChunkPacket($source->x >> 4, $source->z >> 4, $pk); return true; }
public function getServer() { return $this->level->getServer(); }
/** * @param Player $player */ public function spawnTo(Player $player) { if (!isset($this->hasSpawned[$player->getLoaderId()]) and isset($player->usedChunks[Level::chunkHash($this->chunk->getX(), $this->chunk->getZ())])) { $this->hasSpawned[$player->getLoaderId()] = $player; } }