mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-13 17:29:44 +00:00
World generation with biomes!
This commit is contained in:
parent
1666602652
commit
9da26fdb88
@ -616,7 +616,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
|||||||
$Z = null;
|
$Z = null;
|
||||||
Level::getXZ($index, $X, $Z);
|
Level::getXZ($index, $X, $Z);
|
||||||
|
|
||||||
if(!$this->level->populateChunk($X, $Z)){
|
if(!$this->level->populateChunk($X, $Z, !$this->spawned or count($this->usedChunks) < ($this->viewDistance - 24))){
|
||||||
if($this->spawned){
|
if($this->spawned){
|
||||||
continue;
|
continue;
|
||||||
}else{
|
}else{
|
||||||
|
@ -583,15 +583,15 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
$this->timings->doTickTiles->stopTiming();
|
$this->timings->doTickTiles->stopTiming();
|
||||||
|
|
||||||
if(count($this->changedBlocks) > 0){
|
if(count($this->changedBlocks) > 0){
|
||||||
if(count($this->players) > 0){
|
if(count($this->players) > 5){
|
||||||
foreach($this->changedBlocks as $index => $blocks){
|
foreach($this->changedBlocks as $index => $blocks){
|
||||||
|
Level::getXZ($index, $X, $Z);
|
||||||
if(count($blocks) > 512){
|
if(count($blocks) > 512){
|
||||||
Level::getXZ($index, $X, $Z);
|
|
||||||
foreach($this->getUsingChunk($X, $Z) as $p){
|
foreach($this->getUsingChunk($X, $Z) as $p){
|
||||||
$p->unloadChunk($X, $Z);
|
$p->unloadChunk($X, $Z);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
$this->sendBlocks($this->getUsingChunk($pos->x >> 4, $pos->z >> 4), $blocks);
|
$this->sendBlocks($this->getUsingChunk($X, $Z), $blocks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1821,14 +1821,18 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function generateChunkCallback($x, $z, FullChunk $chunk){
|
public function generateChunkCallback($x, $z, FullChunk $chunk){
|
||||||
$oldChunk = $this->getChunk($x, $z, false);
|
Timings::$generationTimer->startTiming();
|
||||||
unset($this->chunkGenerationQueue[Level::chunkHash($x, $z)]);
|
if(isset($this->chunkGenerationQueue[$index = Level::chunkHash($x, $z)])){
|
||||||
$chunk->setProvider($this->provider);
|
$oldChunk = $this->getChunk($x, $z, false);
|
||||||
$this->setChunk($x, $z, $chunk);
|
unset($this->chunkGenerationQueue[$index = Level::chunkHash($x, $z)]);
|
||||||
$chunk = $this->getChunk($x, $z, false);
|
$chunk->setProvider($this->provider);
|
||||||
if($chunk !== null and ($oldChunk === null or $oldChunk->isPopulated() === false) and $chunk->isPopulated()){
|
$this->setChunk($x, $z, $chunk);
|
||||||
$this->server->getPluginManager()->callEvent(new ChunkPopulateEvent($chunk));
|
$chunk = $this->getChunk($x, $z, false);
|
||||||
|
if($chunk !== null and ($oldChunk === null or $oldChunk->isPopulated() === false) and $chunk->isPopulated() and $chunk->getProvider() !== null){
|
||||||
|
$this->server->getPluginManager()->callEvent(new ChunkPopulateEvent($chunk));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Timings::$generationTimer->stopTiming();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setChunk($x, $z, FullChunk $chunk, $unload = true){
|
public function setChunk($x, $z, FullChunk $chunk, $unload = true){
|
||||||
@ -2079,7 +2083,12 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->server->getPluginManager()->callEvent(new ChunkLoadEvent($chunk, !$chunk->isGenerated()));
|
if($chunk->getProvider() !== null){
|
||||||
|
$this->server->getPluginManager()->callEvent(new ChunkLoadEvent($chunk, !$chunk->isGenerated()));
|
||||||
|
}else{
|
||||||
|
$this->unloadChunk($x, $z, false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2114,7 +2123,7 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
|
|
||||||
$chunk = $this->getChunk($x, $z);
|
$chunk = $this->getChunk($x, $z);
|
||||||
|
|
||||||
if($chunk !== null){
|
if($chunk !== null and $chunk->getProvider() !== null){
|
||||||
$this->server->getPluginManager()->callEvent($ev = new ChunkUnloadEvent($chunk));
|
$this->server->getPluginManager()->callEvent($ev = new ChunkUnloadEvent($chunk));
|
||||||
if($ev->isCancelled()){
|
if($ev->isCancelled()){
|
||||||
return false;
|
return false;
|
||||||
@ -2291,24 +2300,30 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function populateChunk($x, $z){
|
public function populateChunk($x, $z, $force = false){
|
||||||
if(!$this->isChunkPopulated($x, $z)){
|
if(!$this->isChunkPopulated($x, $z)){
|
||||||
$populate = true;
|
$populate = true;
|
||||||
for($xx = -1; $xx <= 1; ++$xx){
|
for($xx = -1; $xx <= 1; ++$xx){
|
||||||
for($zz = -1; $zz <= 1; ++$zz){
|
for($zz = -1; $zz <= 1; ++$zz){
|
||||||
if(!$this->isChunkGenerated($x + $xx, $z + $zz)){
|
if(!$this->isChunkGenerated($x + $xx, $z + $zz)){
|
||||||
$populate = false;
|
$populate = false;
|
||||||
$this->generateChunk($x + $xx, $z + $zz);
|
$this->generateChunk($x + $xx, $z + $zz, $force);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->chunksPopulated < $this->chunksPopulatedPerTick and $populate){
|
if($this->chunksPopulated < $this->chunksPopulatedPerTick and $populate){
|
||||||
|
Timings::$generationTimer->startTiming();
|
||||||
$this->generatorInstance->populateChunk($x, $z);
|
$this->generatorInstance->populateChunk($x, $z);
|
||||||
$chunk = $this->getChunk($x, $z);
|
$chunk = $this->getChunk($x, $z);
|
||||||
$chunk->setPopulated(true);
|
$chunk->setPopulated(true);
|
||||||
$this->server->getPluginManager()->callEvent(new ChunkPopulateEvent($chunk));
|
if($chunk->getProvider() !== null){
|
||||||
|
$this->server->getPluginManager()->callEvent(new ChunkPopulateEvent($chunk));
|
||||||
|
}else{
|
||||||
|
$this->unloadChunk($x, $z, false);
|
||||||
|
}
|
||||||
++$this->chunksPopulated;
|
++$this->chunksPopulated;
|
||||||
|
Timings::$generationTimer->stopTiming();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2317,10 +2332,15 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generateChunk($x, $z){
|
public function generateChunk($x, $z, $force = false){
|
||||||
if(!isset($this->chunkGenerationQueue[$index = Level::chunkHash($x, $z)])){
|
if(!isset($this->chunkGenerationQueue[$index = Level::chunkHash($x, $z)])){
|
||||||
$this->chunkGenerationQueue[$index] = true;
|
$this->chunkGenerationQueue[$index] = 0;
|
||||||
$this->server->getGenerationManager()->requestChunk($this, $x, $z);
|
$this->server->getGenerationManager()->requestChunk($this, $x, $z, $this->getChunk($x, $z, true));
|
||||||
|
}elseif($force){
|
||||||
|
$value = ++$this->chunkGenerationQueue[$index];
|
||||||
|
if($value % 40 === 0){
|
||||||
|
$this->server->getGenerationManager()->requestChunk($this, $x, $z);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,8 +177,9 @@ class GenerationManager{
|
|||||||
if($this->needsChunk[$levelID][0] === $chunk->getX() and $this->needsChunk[$levelID][1] === $chunk->getZ()){
|
if($this->needsChunk[$levelID][0] === $chunk->getX() and $this->needsChunk[$levelID][1] === $chunk->getZ()){
|
||||||
$this->needsChunk[$levelID] = $chunk;
|
$this->needsChunk[$levelID] = $chunk;
|
||||||
}
|
}
|
||||||
|
}elseif(isset($this->levels[$levelID])){
|
||||||
|
$this->levels[$levelID]->setChunk($chunk->getX(), $chunk->getZ(), $chunk);
|
||||||
}
|
}
|
||||||
//TODO: set new received chunks
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -74,9 +74,12 @@ class GenerationRequestManager{
|
|||||||
$this->generationThread->pushMainToThreadPacket($buffer);
|
$this->generationThread->pushMainToThreadPacket($buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function requestChunk(Level $level, $chunkX, $chunkZ){
|
public function requestChunk(Level $level, $chunkX, $chunkZ, FullChunk $chunk = null){
|
||||||
$buffer = chr(GenerationManager::PACKET_REQUEST_CHUNK) . Binary::writeInt($level->getId()) . Binary::writeInt($chunkX) . Binary::writeInt($chunkZ);
|
$buffer = chr(GenerationManager::PACKET_REQUEST_CHUNK) . Binary::writeInt($level->getId()) . Binary::writeInt($chunkX) . Binary::writeInt($chunkZ);
|
||||||
$this->generationThread->pushMainToThreadPacket($buffer);
|
$this->generationThread->pushMainToThreadPacket($buffer);
|
||||||
|
if($chunk !== null){
|
||||||
|
$this->sendChunk($level->getId(), $chunk);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function handleRequest($levelID, $chunkX, $chunkZ){
|
protected function handleRequest($levelID, $chunkX, $chunkZ){
|
||||||
|
@ -23,14 +23,16 @@ namespace pocketmine\level\generator\biome;
|
|||||||
|
|
||||||
use pocketmine\block\Block;
|
use pocketmine\block\Block;
|
||||||
use pocketmine\level\ChunkManager;
|
use pocketmine\level\ChunkManager;
|
||||||
use pocketmine\level\generator\normal\biome\BeachBiome;
|
use pocketmine\level\generator\normal\biome\SwampBiome;
|
||||||
use pocketmine\level\generator\normal\biome\DesertBiome;
|
use pocketmine\level\generator\normal\biome\DesertBiome;
|
||||||
use pocketmine\level\generator\normal\biome\ForestBiome;
|
use pocketmine\level\generator\normal\biome\ForestBiome;
|
||||||
|
use pocketmine\level\generator\normal\biome\IcePlainsBiome;
|
||||||
use pocketmine\level\generator\normal\biome\MountainsBiome;
|
use pocketmine\level\generator\normal\biome\MountainsBiome;
|
||||||
use pocketmine\level\generator\normal\biome\OceanBiome;
|
use pocketmine\level\generator\normal\biome\OceanBiome;
|
||||||
use pocketmine\level\generator\normal\biome\PlainBiome;
|
use pocketmine\level\generator\normal\biome\PlainBiome;
|
||||||
use pocketmine\level\generator\normal\biome\RiverBiome;
|
use pocketmine\level\generator\normal\biome\RiverBiome;
|
||||||
use pocketmine\level\generator\normal\biome\SmallMountainsBiome;
|
use pocketmine\level\generator\normal\biome\SmallMountainsBiome;
|
||||||
|
use pocketmine\level\generator\normal\biome\TaigaBiome;
|
||||||
use pocketmine\level\generator\populator\Populator;
|
use pocketmine\level\generator\populator\Populator;
|
||||||
use pocketmine\utils\Random;
|
use pocketmine\utils\Random;
|
||||||
|
|
||||||
@ -41,14 +43,19 @@ abstract class Biome{
|
|||||||
const DESERT = 2;
|
const DESERT = 2;
|
||||||
const MOUNTAINS = 3;
|
const MOUNTAINS = 3;
|
||||||
const FOREST = 4;
|
const FOREST = 4;
|
||||||
|
const TAIGA = 5;
|
||||||
|
const SWAMP = 6;
|
||||||
const RIVER = 7;
|
const RIVER = 7;
|
||||||
|
|
||||||
const BEACH = 16;
|
const ICE_PLAINS = 12;
|
||||||
|
|
||||||
|
|
||||||
const SMALL_MOUNTAINS = 20;
|
const SMALL_MOUNTAINS = 20;
|
||||||
|
|
||||||
|
|
||||||
|
const BIRCH_FOREST = 27;
|
||||||
|
|
||||||
|
|
||||||
const MAX_BIOMES = 256;
|
const MAX_BIOMES = 256;
|
||||||
|
|
||||||
/** @var Biome[] */
|
/** @var Biome[] */
|
||||||
@ -64,6 +71,9 @@ abstract class Biome{
|
|||||||
|
|
||||||
private $groundCover = [];
|
private $groundCover = [];
|
||||||
|
|
||||||
|
protected $rainfall = 0.5;
|
||||||
|
protected $temperature = 0.5;
|
||||||
|
|
||||||
protected static function register($id, Biome $biome){
|
protected static function register($id, Biome $biome){
|
||||||
self::$biomes[(int) $id] = $biome;
|
self::$biomes[(int) $id] = $biome;
|
||||||
$biome->setId((int) $id);
|
$biome->setId((int) $id);
|
||||||
@ -75,12 +85,17 @@ abstract class Biome{
|
|||||||
self::register(self::DESERT, new DesertBiome());
|
self::register(self::DESERT, new DesertBiome());
|
||||||
self::register(self::MOUNTAINS, new MountainsBiome());
|
self::register(self::MOUNTAINS, new MountainsBiome());
|
||||||
self::register(self::FOREST, new ForestBiome());
|
self::register(self::FOREST, new ForestBiome());
|
||||||
|
self::register(self::TAIGA, new TaigaBiome());
|
||||||
|
|
||||||
self::register(self::RIVER, new RiverBiome());
|
self::register(self::RIVER, new RiverBiome());
|
||||||
|
|
||||||
self::register(self::BEACH, new BeachBiome());
|
self::register(self::ICE_PLAINS, new IcePlainsBiome());
|
||||||
|
|
||||||
|
self::register(self::SWAMP, new SwampBiome());
|
||||||
|
|
||||||
self::register(self::SMALL_MOUNTAINS, new SmallMountainsBiome());
|
self::register(self::SMALL_MOUNTAINS, new SmallMountainsBiome());
|
||||||
|
|
||||||
|
self::register(self::BIRCH_FOREST, new ForestBiome(ForestBiome::TYPE_BIRCH));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,7 +104,7 @@ abstract class Biome{
|
|||||||
* @return Biome
|
* @return Biome
|
||||||
*/
|
*/
|
||||||
public static function getBiome($id){
|
public static function getBiome($id){
|
||||||
return isset(self::$biomes[$id]) ? self::$biomes[$id] : null;
|
return isset(self::$biomes[$id]) ? self::$biomes[$id] : self::$biomes[self::OCEAN];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function clearPopulators(){
|
public function clearPopulators(){
|
||||||
@ -149,4 +164,18 @@ abstract class Biome{
|
|||||||
public function setGroundCover(array $covers){
|
public function setGroundCover(array $covers){
|
||||||
$this->groundCover = $covers;
|
$this->groundCover = $covers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getTemperature(){
|
||||||
|
return $this->temperature;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRainfall(){
|
||||||
|
return $this->rainfall;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int (randomness|Red|Green|Blue)
|
||||||
|
*/
|
||||||
|
abstract public function getColor();
|
||||||
}
|
}
|
@ -37,17 +37,37 @@ class BiomeSelector{
|
|||||||
/** @var Biome[] */
|
/** @var Biome[] */
|
||||||
private $biomes = [];
|
private $biomes = [];
|
||||||
|
|
||||||
private $select = [];
|
private $map = [];
|
||||||
|
|
||||||
public function __construct(Random $random, Biome $fallback){
|
private $lookup;
|
||||||
|
|
||||||
|
public function __construct(Random $random, callable $lookup, Biome $fallback){
|
||||||
$this->fallback = $fallback;
|
$this->fallback = $fallback;
|
||||||
$this->temperature = new Simplex($random, 1, 0.004, 0.5, 2);
|
$this->lookup = $lookup;
|
||||||
$this->rainfall = new Simplex($random, 2, 0.004, 0.5, 2);
|
$this->temperature = new Simplex($random, 1, 0.001, 1, 1);
|
||||||
|
$this->rainfall = new Simplex($random, 1, 0.001, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addBiome(Biome $biome, $start, $end){
|
public function recalculate(){
|
||||||
|
$this->map = new \SplFixedArray(64 * 64);
|
||||||
|
|
||||||
|
for($i = 0; $i < 64; ++$i){
|
||||||
|
for($j = 0; $j < 64; ++$j){
|
||||||
|
$this->map[$i + ($j << 6)] = call_user_func($this->lookup, $i / 63, $j / 63);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addBiome(Biome $biome){
|
||||||
$this->biomes[$biome->getId()] = $biome;
|
$this->biomes[$biome->getId()] = $biome;
|
||||||
$this->select[$biome->getId()] = [$biome->getId(), $start, $end];
|
}
|
||||||
|
|
||||||
|
public function getTemperature($x, $z){
|
||||||
|
return ($this->temperature->noise2D($x, $z, true) + 1) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRainfall($x, $z){
|
||||||
|
return ($this->rainfall->noise2D($x, $z, true) + 1) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,27 +77,10 @@ class BiomeSelector{
|
|||||||
* @return Biome
|
* @return Biome
|
||||||
*/
|
*/
|
||||||
public function pickBiome($x, $z){
|
public function pickBiome($x, $z){
|
||||||
|
$temperature = (int) ($this->getTemperature($x, $z) * 63);
|
||||||
|
$rainfall = (int) ($this->getRainfall($x, $z) * 63);
|
||||||
|
|
||||||
//$temperature = $this->temperature->noise2D($x, $z);
|
$biomeId = $this->map[$temperature + ($rainfall << 6)];
|
||||||
$rainfall = $this->rainfall->noise2D($x, $z);
|
return isset($this->biomes[$biomeId]) ? $this->biomes[$biomeId] : $this->fallback;
|
||||||
|
|
||||||
if($rainfall > 0.9){
|
|
||||||
return Biome::getBiome(Biome::OCEAN);
|
|
||||||
}elseif($rainfall > 0.7){
|
|
||||||
return Biome::getBiome(Biome::RIVER);
|
|
||||||
}elseif($rainfall > 0.6){
|
|
||||||
return Biome::getBiome(Biome::BEACH);
|
|
||||||
}elseif($rainfall > 0.2){
|
|
||||||
return Biome::getBiome(Biome::FOREST);
|
|
||||||
}elseif($rainfall > -0.3){
|
|
||||||
return Biome::getBiome(Biome::PLAINS);
|
|
||||||
}elseif($rainfall > -0.6){
|
|
||||||
return Biome::getBiome(Biome::DESERT);
|
|
||||||
}elseif($rainfall > -0.7){
|
|
||||||
return Biome::getBiome(Biome::BEACH);
|
|
||||||
}else{
|
|
||||||
return Biome::getBiome(Biome::OCEAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -83,9 +83,7 @@ class Normal extends Generator{
|
|||||||
$bellHeight = 2 * self::$SMOOTH_SIZE;
|
$bellHeight = 2 * self::$SMOOTH_SIZE;
|
||||||
for($sx = -self::$SMOOTH_SIZE; $sx <= self::$SMOOTH_SIZE; ++$sx){
|
for($sx = -self::$SMOOTH_SIZE; $sx <= self::$SMOOTH_SIZE; ++$sx){
|
||||||
for($sz = -self::$SMOOTH_SIZE; $sz <= self::$SMOOTH_SIZE; ++$sz){
|
for($sz = -self::$SMOOTH_SIZE; $sz <= self::$SMOOTH_SIZE; ++$sz){
|
||||||
$bx = $bellSize * $sx;
|
self::$GAUSSIAN_KERNEL[$sx + self::$SMOOTH_SIZE][$sz + self::$SMOOTH_SIZE] = 10 / sqrt($sx ** 2 + $sz ** 2 + 0.2);
|
||||||
$bz = $bellSize * $sz;
|
|
||||||
self::$GAUSSIAN_KERNEL[$sx + self::$SMOOTH_SIZE][$sz + self::$SMOOTH_SIZE] = $bellHeight * exp(-($bx * $bx + $bz * $bz) / 2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,9 +100,54 @@ class Normal extends Generator{
|
|||||||
$this->level = $level;
|
$this->level = $level;
|
||||||
$this->random = $random;
|
$this->random = $random;
|
||||||
$this->random->setSeed($this->level->getSeed());
|
$this->random->setSeed($this->level->getSeed());
|
||||||
$this->noiseBase = new Simplex($this->random, 16, 0.012, 0.5, 2);
|
$this->noiseBase = new Simplex($this->random, 16, 0.02, 0.5, 2);
|
||||||
$this->random->setSeed($this->level->getSeed());
|
$this->random->setSeed($this->level->getSeed());
|
||||||
$this->selector = new BiomeSelector($this->random, Biome::getBiome(Biome::OCEAN));
|
$this->selector = new BiomeSelector($this->random, function($temperature, $rainfall){
|
||||||
|
$rainfall *= $temperature;
|
||||||
|
if($temperature < 0.10){
|
||||||
|
return Biome::ICE_PLAINS;
|
||||||
|
}elseif($rainfall < 0.20){
|
||||||
|
if($temperature < 0.50){
|
||||||
|
return Biome::ICE_PLAINS;
|
||||||
|
}elseif($temperature < 0.95){
|
||||||
|
return Biome::SMALL_MOUNTAINS;
|
||||||
|
}else{
|
||||||
|
return Biome::DESERT;
|
||||||
|
}
|
||||||
|
}elseif($rainfall > 0.5 and $temperature < 0.7){
|
||||||
|
return Biome::SWAMP;
|
||||||
|
}elseif($temperature < 0.50){
|
||||||
|
return Biome::TAIGA;
|
||||||
|
}elseif($temperature < 0.97){
|
||||||
|
if($rainfall < 0.35){
|
||||||
|
return Biome::MOUNTAINS;
|
||||||
|
}else {
|
||||||
|
return Biome::RIVER;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if($rainfall < 0.45){
|
||||||
|
return Biome::PLAINS;
|
||||||
|
}elseif($rainfall < 0.90){
|
||||||
|
return Biome::FOREST;
|
||||||
|
}else{
|
||||||
|
return Biome::BIRCH_FOREST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, Biome::getBiome(Biome::OCEAN));
|
||||||
|
|
||||||
|
$this->selector->addBiome(Biome::getBiome(Biome::OCEAN));
|
||||||
|
$this->selector->addBiome(Biome::getBiome(Biome::PLAINS));
|
||||||
|
$this->selector->addBiome(Biome::getBiome(Biome::DESERT));
|
||||||
|
$this->selector->addBiome(Biome::getBiome(Biome::MOUNTAINS));
|
||||||
|
$this->selector->addBiome(Biome::getBiome(Biome::FOREST));
|
||||||
|
$this->selector->addBiome(Biome::getBiome(Biome::TAIGA));
|
||||||
|
$this->selector->addBiome(Biome::getBiome(Biome::SWAMP));
|
||||||
|
$this->selector->addBiome(Biome::getBiome(Biome::RIVER));
|
||||||
|
$this->selector->addBiome(Biome::getBiome(Biome::ICE_PLAINS));
|
||||||
|
$this->selector->addBiome(Biome::getBiome(Biome::SMALL_MOUNTAINS));
|
||||||
|
$this->selector->addBiome(Biome::getBiome(Biome::BIRCH_FOREST));
|
||||||
|
|
||||||
|
$this->selector->recalculate();
|
||||||
|
|
||||||
$cover = new GroundCover();
|
$cover = new GroundCover();
|
||||||
$this->generationPopulators[] = $cover;
|
$this->generationPopulators[] = $cover;
|
||||||
@ -127,7 +170,7 @@ class Normal extends Generator{
|
|||||||
public function generateChunk($chunkX, $chunkZ){
|
public function generateChunk($chunkX, $chunkZ){
|
||||||
$this->random->setSeed(0xdeadbeef ^ ($chunkX << 8) ^ $chunkZ ^ $this->level->getSeed());
|
$this->random->setSeed(0xdeadbeef ^ ($chunkX << 8) ^ $chunkZ ^ $this->level->getSeed());
|
||||||
|
|
||||||
$noise = Generator::getFastNoise3D($this->noiseBase, 16, 128, 16, 8, 8, 8, $chunkX * 16, 0, $chunkZ * 16);
|
$noise = Generator::getFastNoise3D($this->noiseBase, 16, 128, 16, 4, 8, 4, $chunkX * 16, 0, $chunkZ * 16);
|
||||||
|
|
||||||
$chunk = $this->level->getChunk($chunkX, $chunkZ);
|
$chunk = $this->level->getChunk($chunkX, $chunkZ);
|
||||||
|
|
||||||
@ -139,16 +182,16 @@ class Normal extends Generator{
|
|||||||
|
|
||||||
$biome = $this->selector->pickBiome($chunkX * 16 + $x, $chunkZ * 16 + $z);
|
$biome = $this->selector->pickBiome($chunkX * 16 + $x, $chunkZ * 16 + $z);
|
||||||
$chunk->setBiomeId($x, $z, $biome->getId());
|
$chunk->setBiomeId($x, $z, $biome->getId());
|
||||||
$chunk->setBiomeColor($x, $z, 255 - (($biome->getId() * 1377) % 255), 255 - (($biome->getId() * 4096) % 255), 255 - (($biome->getId() * 31337) % 255));
|
$color = $biome->getColor();
|
||||||
|
$chunk->setBiomeColor($x, $z, $color >> 16, ($color >> 8) & 0xff, $color & 0xff);
|
||||||
|
|
||||||
for($sx = -self::$SMOOTH_SIZE; $sx <= self::$SMOOTH_SIZE; ++$sx){
|
for($sx = -self::$SMOOTH_SIZE; $sx <= self::$SMOOTH_SIZE; ++$sx){
|
||||||
for($sz = -self::$SMOOTH_SIZE; $sz <= self::$SMOOTH_SIZE; ++$sz){
|
for($sz = -self::$SMOOTH_SIZE; $sz <= self::$SMOOTH_SIZE; ++$sz){
|
||||||
if($sx === 0 and $sz === 0){
|
if($sx === 0 and $sz === 0){
|
||||||
$adjacent = $biome;
|
continue;
|
||||||
}else{
|
}else{
|
||||||
$adjacent = $this->selector->pickBiome($chunkX * 16 + $x + $sx * 16, $chunkZ * 16 + $z + $sz * 16);
|
$adjacent = $this->selector->pickBiome($chunkX * 16 + $x + $sx * 8, $chunkZ * 16 + $z + $sz * 8);
|
||||||
}
|
}
|
||||||
/** @var NormalBiome $adjacent */
|
|
||||||
$weight = self::$GAUSSIAN_KERNEL[$sx + self::$SMOOTH_SIZE][$sz + self::$SMOOTH_SIZE];
|
$weight = self::$GAUSSIAN_KERNEL[$sx + self::$SMOOTH_SIZE][$sz + self::$SMOOTH_SIZE];
|
||||||
$minSum += $adjacent->getMinElevation() * $weight;
|
$minSum += $adjacent->getMinElevation() * $weight;
|
||||||
$maxSum += $adjacent->getMaxElevation() * $weight;
|
$maxSum += $adjacent->getMaxElevation() * $weight;
|
||||||
|
@ -28,6 +28,9 @@ class DesertBiome extends SandyBiome{
|
|||||||
public function __construct(){
|
public function __construct(){
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->setElevation(63, 74);
|
$this->setElevation(63, 74);
|
||||||
|
|
||||||
|
$this->temperature = 2;
|
||||||
|
$this->rainfall = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName(){
|
public function getName(){
|
||||||
|
@ -21,15 +21,23 @@
|
|||||||
|
|
||||||
namespace pocketmine\level\generator\normal\biome;
|
namespace pocketmine\level\generator\normal\biome;
|
||||||
|
|
||||||
|
use pocketmine\block\Sapling;
|
||||||
use pocketmine\level\generator\populator\TallGrass;
|
use pocketmine\level\generator\populator\TallGrass;
|
||||||
use pocketmine\level\generator\populator\Tree;
|
use pocketmine\level\generator\populator\Tree;
|
||||||
|
|
||||||
class ForestBiome extends GrassyBiome{
|
class ForestBiome extends GrassyBiome{
|
||||||
|
|
||||||
public function __construct(){
|
const TYPE_NORMAL = 0;
|
||||||
|
const TYPE_BIRCH = 1;
|
||||||
|
|
||||||
|
public $type;
|
||||||
|
|
||||||
|
public function __construct($type = self::TYPE_NORMAL){
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
$trees = new Tree();
|
$this->type = $type;
|
||||||
|
|
||||||
|
$trees = new Tree($type === self::TYPE_BIRCH ? Sapling::BIRCH : Sapling::OAK);
|
||||||
$trees->setBaseAmount(5);
|
$trees->setBaseAmount(5);
|
||||||
$this->addPopulator($trees);
|
$this->addPopulator($trees);
|
||||||
|
|
||||||
@ -39,9 +47,21 @@ class ForestBiome extends GrassyBiome{
|
|||||||
$this->addPopulator($tallGrass);
|
$this->addPopulator($tallGrass);
|
||||||
|
|
||||||
$this->setElevation(63, 81);
|
$this->setElevation(63, 81);
|
||||||
|
|
||||||
|
if($type === self::TYPE_BIRCH){
|
||||||
|
$this->temperature = 0.5;
|
||||||
|
$this->rainfall = 0.5;
|
||||||
|
}else{
|
||||||
|
$this->temperature = 0.7;
|
||||||
|
$this->temperature = 0.8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName(){
|
public function getName(){
|
||||||
return "Forest";
|
return $this->type === self::TYPE_BIRCH ? "Birch Forest" : "Forest";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getColor(){
|
||||||
|
return 0x056621;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace pocketmine\level\generator\normal\biome;
|
||||||
|
|
||||||
|
use pocketmine\level\generator\populator\TallGrass;
|
||||||
|
|
||||||
|
class IcePlainsBiome extends SnowyBiome{
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
|
$tallGrass = new TallGrass();
|
||||||
|
$tallGrass->setBaseAmount(5);
|
||||||
|
|
||||||
|
$this->addPopulator($tallGrass);
|
||||||
|
|
||||||
|
$this->setElevation(63, 74);
|
||||||
|
|
||||||
|
$this->temperature = 0.05;
|
||||||
|
$this->rainfall = 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName(){
|
||||||
|
return "Ice Plains";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getColor(){
|
||||||
|
return 0x163933;
|
||||||
|
}
|
||||||
|
}
|
@ -41,6 +41,9 @@ class MountainsBiome extends GrassyBiome{
|
|||||||
//TODO: add emerald
|
//TODO: add emerald
|
||||||
|
|
||||||
$this->setElevation(63, 127);
|
$this->setElevation(63, 127);
|
||||||
|
|
||||||
|
$this->temperature = 0.4;
|
||||||
|
$this->rainfall = 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName(){
|
public function getName(){
|
||||||
|
@ -24,5 +24,7 @@ namespace pocketmine\level\generator\normal\biome;
|
|||||||
use pocketmine\level\generator\biome\Biome;
|
use pocketmine\level\generator\biome\Biome;
|
||||||
|
|
||||||
abstract class NormalBiome extends Biome{
|
abstract class NormalBiome extends Biome{
|
||||||
|
public function getColor(){
|
||||||
|
return 0xffb360; //Detect wrong biomes
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,9 +34,16 @@ class OceanBiome extends GrassyBiome{
|
|||||||
$this->addPopulator($tallGrass);
|
$this->addPopulator($tallGrass);
|
||||||
|
|
||||||
$this->setElevation(46, 58);
|
$this->setElevation(46, 58);
|
||||||
|
|
||||||
|
$this->temperature = 0.5;
|
||||||
|
$this->rainfall = 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName(){
|
public function getName(){
|
||||||
return "Ocean";
|
return "Ocean";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getColor(){
|
||||||
|
return 0x8da360;
|
||||||
|
}
|
||||||
}
|
}
|
@ -29,14 +29,21 @@ class PlainBiome extends GrassyBiome{
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
$tallGrass = new TallGrass();
|
$tallGrass = new TallGrass();
|
||||||
$tallGrass->setBaseAmount(5);
|
$tallGrass->setBaseAmount(12);
|
||||||
|
|
||||||
$this->addPopulator($tallGrass);
|
$this->addPopulator($tallGrass);
|
||||||
|
|
||||||
$this->setElevation(63, 74);
|
$this->setElevation(63, 74);
|
||||||
|
|
||||||
|
$this->temperature = 0.8;
|
||||||
|
$this->rainfall = 0.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName(){
|
public function getName(){
|
||||||
return "Plains";
|
return "Plains";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getColor(){
|
||||||
|
return 0x8db360;
|
||||||
|
}
|
||||||
}
|
}
|
@ -34,9 +34,16 @@ class RiverBiome extends GrassyBiome{
|
|||||||
$this->addPopulator($tallGrass);
|
$this->addPopulator($tallGrass);
|
||||||
|
|
||||||
$this->setElevation(58, 62);
|
$this->setElevation(58, 62);
|
||||||
|
|
||||||
|
$this->temperature = 0.5;
|
||||||
|
$this->rainfall = 0.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName(){
|
public function getName(){
|
||||||
return "River";
|
return "River";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getColor(){
|
||||||
|
return 0x8dc360;
|
||||||
|
}
|
||||||
}
|
}
|
37
src/pocketmine/level/generator/normal/biome/SnowyBiome.php
Normal file
37
src/pocketmine/level/generator/normal/biome/SnowyBiome.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace pocketmine\level\generator\normal\biome;
|
||||||
|
|
||||||
|
use pocketmine\block\Block;
|
||||||
|
|
||||||
|
abstract class SnowyBiome extends NormalBiome{
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
$this->setGroundCover([
|
||||||
|
Block::get(Block::SNOW_LAYER, 0),
|
||||||
|
Block::get(Block::GRASS, 0),
|
||||||
|
Block::get(Block::DIRT, 0),
|
||||||
|
Block::get(Block::DIRT, 0),
|
||||||
|
Block::get(Block::DIRT, 0),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@ -21,15 +21,22 @@
|
|||||||
|
|
||||||
namespace pocketmine\level\generator\normal\biome;
|
namespace pocketmine\level\generator\normal\biome;
|
||||||
|
|
||||||
class BeachBiome extends GrassyBiome{
|
class SwampBiome extends GrassyBiome{
|
||||||
|
|
||||||
public function __construct(){
|
public function __construct(){
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
$this->setElevation(62, 65);
|
$this->setElevation(62, 63);
|
||||||
|
|
||||||
|
$this->temperature = 0.8;
|
||||||
|
$this->rainfall = 0.9;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName(){
|
public function getName(){
|
||||||
return "Beach";
|
return "Swamp";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getColor(){
|
||||||
|
return 0x07f9b2;
|
||||||
}
|
}
|
||||||
}
|
}
|
55
src/pocketmine/level/generator/normal/biome/TaigaBiome.php
Normal file
55
src/pocketmine/level/generator/normal/biome/TaigaBiome.php
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace pocketmine\level\generator\normal\biome;
|
||||||
|
|
||||||
|
use pocketmine\block\Sapling;
|
||||||
|
use pocketmine\level\generator\populator\TallGrass;
|
||||||
|
use pocketmine\level\generator\populator\Tree;
|
||||||
|
|
||||||
|
class TaigaBiome extends SnowyBiome{
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
|
$trees = new Tree(Sapling::SPRUCE);
|
||||||
|
$trees->setBaseAmount(10);
|
||||||
|
$this->addPopulator($trees);
|
||||||
|
|
||||||
|
$tallGrass = new TallGrass();
|
||||||
|
$tallGrass->setBaseAmount(1);
|
||||||
|
|
||||||
|
$this->addPopulator($tallGrass);
|
||||||
|
|
||||||
|
$this->setElevation(63, 81);
|
||||||
|
|
||||||
|
$this->temperature = 0.05;
|
||||||
|
$this->rainfall = 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName(){
|
||||||
|
return "Taiga";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getColor(){
|
||||||
|
return 0x0b6659;
|
||||||
|
}
|
||||||
|
}
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
namespace pocketmine\level\generator\object;
|
namespace pocketmine\level\generator\object;
|
||||||
|
|
||||||
|
use pocketmine\block\Block;
|
||||||
use pocketmine\block\Sapling;
|
use pocketmine\block\Sapling;
|
||||||
use pocketmine\level\ChunkManager;
|
use pocketmine\level\ChunkManager;
|
||||||
use pocketmine\utils\Random;
|
use pocketmine\utils\Random;
|
||||||
@ -33,6 +34,9 @@ class Tree{
|
|||||||
6 => true,
|
6 => true,
|
||||||
17 => true,
|
17 => true,
|
||||||
18 => true,
|
18 => true,
|
||||||
|
Block::SNOW_LAYER => true,
|
||||||
|
Block::LOG2 => true,
|
||||||
|
Block::LEAVES2 => true
|
||||||
];
|
];
|
||||||
|
|
||||||
public static function growTree(ChunkManager $level, $x, $y, $z, Random $random, $type = 0){
|
public static function growTree(ChunkManager $level, $x, $y, $z, Random $random, $type = 0){
|
||||||
|
@ -35,16 +35,24 @@ class GroundCover extends Populator{
|
|||||||
$biome = Biome::getBiome($chunk->getBiomeId($x, $z));
|
$biome = Biome::getBiome($chunk->getBiomeId($x, $z));
|
||||||
$cover = $biome->getGroundCover();
|
$cover = $biome->getGroundCover();
|
||||||
if(count($cover) > 0){
|
if(count($cover) > 0){
|
||||||
|
$diffY = 0;
|
||||||
|
if(!$cover[0]->isSolid()){
|
||||||
|
$diffY = 1;
|
||||||
|
}
|
||||||
|
|
||||||
$column = $chunk->getBlockIdColumn($x, $z);
|
$column = $chunk->getBlockIdColumn($x, $z);
|
||||||
for($y = 127; $y > 0; --$y){
|
for($y = 127; $y > 0; --$y){
|
||||||
if($column{$y} !== "\x00" and Block::get(ord($column{$y}))->isSolid()){
|
if($column{$y} !== "\x00" and !Block::get(ord($column{$y}))->isTransparent()){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$startY = $y;
|
$startY = min(127, $y + $diffY);
|
||||||
$endY = $startY - count($cover);
|
$endY = $startY - count($cover);
|
||||||
for($y = $startY; $y > $endY and $y >= 0; --$y){
|
for($y = $startY; $y > $endY and $y >= 0; --$y){
|
||||||
$b = $cover[$startY - $y];
|
$b = $cover[$startY - $y];
|
||||||
|
if($column{$y} === "\x00" and $b->isSolid()){
|
||||||
|
break;
|
||||||
|
}
|
||||||
if($b->getDamage() === 0){
|
if($b->getDamage() === 0){
|
||||||
$chunk->setBlockId($x, $y, $z, $b->getId());
|
$chunk->setBlockId($x, $y, $z, $b->getId());
|
||||||
}else{
|
}else{
|
||||||
|
@ -43,37 +43,30 @@ class TallGrass extends Populator{
|
|||||||
$this->level = $level;
|
$this->level = $level;
|
||||||
$amount = $random->nextRange(0, $this->randomAmount + 1) + $this->baseAmount;
|
$amount = $random->nextRange(0, $this->randomAmount + 1) + $this->baseAmount;
|
||||||
for($i = 0; $i < $amount; ++$i){
|
for($i = 0; $i < $amount; ++$i){
|
||||||
$x = $random->nextRange($chunkX << 4, ($chunkX << 4) + 15);
|
$x = $random->nextRange($chunkX * 16, $chunkX * 16 + 15);
|
||||||
$z = $random->nextRange($chunkZ << 4, ($chunkZ << 4) + 15);
|
$z = $random->nextRange($chunkZ * 16, $chunkZ * 16 + 15);
|
||||||
for($size = 30; $size > 0; --$size){
|
$y = $this->getHighestWorkableBlock($x, $z);
|
||||||
$xx = $x - 7 + $random->nextRange(0, 15);
|
|
||||||
$zz = $z - 7 + $random->nextRange(0, 15);
|
|
||||||
$yy = $this->getHighestWorkableBlock($xx, $zz);
|
|
||||||
|
|
||||||
if($yy !== -1 and $this->canTallGrassStay($xx, $yy, $zz)){
|
if($y !== -1 and $this->canTallGrassStay($x, $y, $z)){
|
||||||
$this->level->setBlockIdAt($xx, $yy, $zz, Block::TALL_GRASS);
|
$this->level->setBlockIdAt($x, $y, $z, Block::TALL_GRASS);
|
||||||
$this->level->setBlockDataAt($xx, $yy, $zz, 1);
|
$this->level->setBlockDataAt($x, $y, $z, 1);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function canTallGrassStay($x, $y, $z){
|
private function canTallGrassStay($x, $y, $z){
|
||||||
return $this->level->getBlockIdAt($x, $y, $z) === Block::AIR and $this->level->getBlockIdAt($x, $y - 1, $z) === Block::GRASS;
|
$b = $this->level->getBlockIdAt($x, $y, $z);
|
||||||
|
return ($b === Block::AIR or $b === Block::SNOW_LAYER) and $this->level->getBlockIdAt($x, $y - 1, $z) === Block::GRASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getHighestWorkableBlock($x, $z){
|
private function getHighestWorkableBlock($x, $z){
|
||||||
for($y = 128; $y > 0; --$y){
|
for($y = 127; $y >= 0; --$y){
|
||||||
$b = $this->level->getBlockIdAt($x, $y, $z);
|
$b = $this->level->getBlockIdAt($x, $y, $z);
|
||||||
if($b === Block::AIR or $b === Block::LEAVES){
|
if($b !== Block::AIR and $b !== Block::LEAVES and $b !== Block::SNOW_LAYER){
|
||||||
if(--$y <= 0){
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ++$y;
|
return $y === 0 ? -1 : ++$y;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -33,6 +33,12 @@ class Tree extends Populator{
|
|||||||
private $randomAmount;
|
private $randomAmount;
|
||||||
private $baseAmount;
|
private $baseAmount;
|
||||||
|
|
||||||
|
private $type;
|
||||||
|
|
||||||
|
public function __construct($type = Sapling::OAK){
|
||||||
|
$this->type = $type;
|
||||||
|
}
|
||||||
|
|
||||||
public function setRandomAmount($amount){
|
public function setRandomAmount($amount){
|
||||||
$this->randomAmount = $amount;
|
$this->randomAmount = $amount;
|
||||||
}
|
}
|
||||||
@ -51,24 +57,17 @@ class Tree extends Populator{
|
|||||||
if($y === -1){
|
if($y === -1){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if($random->nextFloat() > 0.75){
|
ObjectTree::growTree($this->level, $x, $y, $z, $random, $this->type);
|
||||||
$meta = Sapling::BIRCH;
|
|
||||||
}else{
|
|
||||||
$meta = Sapling::OAK;
|
|
||||||
}
|
|
||||||
ObjectTree::growTree($this->level, $x, $y, $z, $random, $meta);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getHighestWorkableBlock($x, $z){
|
private function getHighestWorkableBlock($x, $z){
|
||||||
for($y = 128; $y > 0; --$y){
|
for($y = 127; $y > 0; --$y){
|
||||||
$b = $this->level->getBlockIdAt($x, $y, $z);
|
$b = $this->level->getBlockIdAt($x, $y, $z);
|
||||||
if($b !== Block::DIRT and $b !== Block::GRASS){
|
if($b === Block::DIRT or $b === Block::GRASS){
|
||||||
if(--$y <= 0){
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
break;
|
break;
|
||||||
|
}elseif($b !== 0 and $b !== Block::SNOW_LAYER){
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
src/spl
2
src/spl
@ -1 +1 @@
|
|||||||
Subproject commit 5ad5b3535c9519b2e013a61a2d55fccae014e037
|
Subproject commit 3db41e1266811b20c3f52f749265f6c9d416c1bb
|
Loading…
x
Reference in New Issue
Block a user