2017-04-23 14:42:51 +00:00
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* BetterNormal from BetterGen
|
|
|
|
|
* Copyright (C) Ad5001 2017
|
|
|
|
|
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
|
|
|
|
|
* @author ad5001
|
|
|
|
|
*/
|
|
|
|
|
namespace Ad5001\BetterGen\generator;
|
|
|
|
|
|
|
|
|
|
use pocketmine\level\ChunkManager;
|
|
|
|
|
use pocketmine\utils\Random;
|
|
|
|
|
use pocketmine\level\generator\biome\Biome;
|
|
|
|
|
use pocketmine\level\generator\Generator;
|
|
|
|
|
use pocketmine\level\generator\noise\Simplex;
|
|
|
|
|
use pocketmine\level\generator\object\OreType;
|
2017-05-01 10:03:56 +00:00
|
|
|
|
use pocketmine\level\generator\normal\object\OreType as OreType2;
|
2017-04-23 14:42:51 +00:00
|
|
|
|
use pocketmine\level\generator\populator\Ore;
|
|
|
|
|
use pocketmine\block\Block;
|
|
|
|
|
use pocketmine\block\CoalOre;
|
|
|
|
|
use pocketmine\block\DiamondOre;
|
|
|
|
|
use pocketmine\block\Dirt;
|
|
|
|
|
use pocketmine\block\GoldOre;
|
|
|
|
|
use pocketmine\block\Gravel;
|
|
|
|
|
use pocketmine\block\IronOre;
|
|
|
|
|
use pocketmine\block\LapisOre;
|
|
|
|
|
use pocketmine\block\RedstoneOre;
|
|
|
|
|
use pocketmine\level\Level;
|
|
|
|
|
use Ad5001\BetterGen\biome\BetterForest;
|
|
|
|
|
use Ad5001\BetterGen\biome\BetterDesert;
|
|
|
|
|
use Ad5001\BetterGen\biome\BetterIcePlains;
|
|
|
|
|
use Ad5001\BetterGen\biome\BetterMesa;
|
|
|
|
|
use Ad5001\BetterGen\biome\BetterMesaPlains;
|
|
|
|
|
use Ad5001\BetterGen\biome\BetterRiver;
|
|
|
|
|
use Ad5001\BetterGen\biome\Mountainable;
|
|
|
|
|
use Ad5001\BetterGen\populator\CavePopulator;
|
|
|
|
|
use Ad5001\BetterGen\populator\RavinePopulator;
|
|
|
|
|
use Ad5001\BetterGen\populator\LakePopulator;
|
|
|
|
|
use Ad5001\BetterGen\populator\MineshaftPopulator;
|
|
|
|
|
use Ad5001\BetterGen\populator\FloatingIslandPopulator;
|
2017-05-01 10:03:56 +00:00
|
|
|
|
use Ad5001\BetterGen\Main;
|
2017-04-23 14:42:51 +00:00
|
|
|
|
|
|
|
|
|
class BetterNormal extends Generator {
|
|
|
|
|
const NOT_OVERWRITABLE = [
|
|
|
|
|
Block::STONE,
|
|
|
|
|
Block::GRAVEL,
|
|
|
|
|
Block::BEDROCK,
|
|
|
|
|
Block::DIAMOND_ORE,
|
|
|
|
|
Block::GOLD_ORE,
|
|
|
|
|
Block::LAPIS_ORE,
|
|
|
|
|
Block::REDSTONE_ORE,
|
|
|
|
|
Block::IRON_ORE,
|
|
|
|
|
Block::COAL_ORE,
|
|
|
|
|
Block::WATER,
|
|
|
|
|
Block::STILL_WATER
|
|
|
|
|
];
|
|
|
|
|
protected $selector;
|
|
|
|
|
protected $level;
|
|
|
|
|
protected $random;
|
|
|
|
|
protected $populators = [ ];
|
|
|
|
|
protected $generationPopulators = [ ];
|
|
|
|
|
public static $biomes = [ ];
|
|
|
|
|
public static $biomeById = [ ];
|
|
|
|
|
public static $levels = [ ];
|
|
|
|
|
protected static $GAUSSIAN_KERNEL = null; // From main class
|
|
|
|
|
protected static $SMOOTH_SIZE = 2;
|
|
|
|
|
protected $waterHeight = 63;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Picks a biome by X and Z
|
|
|
|
|
* @param $x int
|
|
|
|
|
* @param $z int
|
|
|
|
|
* @return Biome
|
|
|
|
|
*/
|
|
|
|
|
public function pickBiome($x, $z) {
|
|
|
|
|
$hash = $x * 2345803 ^ $z * 9236449 ^ $this->level->getSeed ();
|
|
|
|
|
$hash *= $hash + 223;
|
|
|
|
|
$xNoise = $hash >> 20 & 3;
|
|
|
|
|
$zNoise = $hash >> 22 & 3;
|
|
|
|
|
if ($xNoise == 3) {
|
|
|
|
|
$xNoise = 1;
|
|
|
|
|
}
|
|
|
|
|
if ($zNoise == 3) {
|
|
|
|
|
$zNoise = 1;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-29 09:59:44 +00:00
|
|
|
|
$b = $this->selector->pickBiome($x + $xNoise - 1, $z + $zNoise - 1);
|
|
|
|
|
if ($b instanceof Mountainable && $this->random->nextBoundedInt(1000 ) < 3) {
|
2017-04-23 14:42:51 +00:00
|
|
|
|
$b = clone $b;
|
2017-04-29 09:59:44 +00:00
|
|
|
|
$b->setElevation($b->getMinElevation () + (50 * $b->getMinElevation () / 100), $b->getMaxElevation () + (50 * $b->getMinElevation () / 100));
|
2017-04-23 14:42:51 +00:00
|
|
|
|
}
|
|
|
|
|
return $b;
|
|
|
|
|
}
|
|
|
|
|
public function init(ChunkManager $level, Random $random) {
|
|
|
|
|
$this->level = $level;
|
|
|
|
|
$this->random = $random;
|
|
|
|
|
|
|
|
|
|
self::$levels [] = $level;
|
|
|
|
|
|
2017-04-29 09:59:44 +00:00
|
|
|
|
$this->random->setSeed($this->level->getSeed ());
|
|
|
|
|
$this->noiseBase = new Simplex($this->random, 4, 1 / 4, 1 / 32);
|
|
|
|
|
$this->random->setSeed($this->level->getSeed ());
|
2017-04-23 14:42:51 +00:00
|
|
|
|
|
2017-04-29 09:59:44 +00:00
|
|
|
|
$this->registerBiome(Biome::getBiome(Biome::OCEAN ));
|
|
|
|
|
$this->registerBiome(Biome::getBiome(Biome::PLAINS ));
|
|
|
|
|
$this->registerBiome(new BetterDesert ());
|
|
|
|
|
$this->registerBiome(new BetterMesa ());
|
|
|
|
|
$this->registerBiome(new BetterMesaPlains ());
|
|
|
|
|
$this->registerBiome(Biome::getBiome(Biome::TAIGA ));
|
|
|
|
|
$this->registerBiome(Biome::getBiome(Biome::SWAMP ));
|
|
|
|
|
$this->registerBiome(new BetterRiver ());
|
|
|
|
|
$this->registerBiome(new BetterIcePlains ());
|
|
|
|
|
$this->registerBiome(new BetterForest(0, [
|
2017-04-23 14:42:51 +00:00
|
|
|
|
0.6,
|
|
|
|
|
0.5
|
2017-04-29 09:59:44 +00:00
|
|
|
|
] ));
|
|
|
|
|
$this->registerBiome(new BetterForest(1, [
|
2017-04-23 14:42:51 +00:00
|
|
|
|
0.7,
|
|
|
|
|
0.8
|
2017-04-29 09:59:44 +00:00
|
|
|
|
] ));
|
|
|
|
|
$this->registerBiome(new BetterForest(2, [
|
2017-04-23 14:42:51 +00:00
|
|
|
|
0.6,
|
|
|
|
|
0.4
|
2017-04-29 09:59:44 +00:00
|
|
|
|
] ));
|
2017-04-23 14:42:51 +00:00
|
|
|
|
|
2017-04-29 09:59:44 +00:00
|
|
|
|
$this->selector = new BetterBiomeSelector($random, [
|
2017-04-23 14:42:51 +00:00
|
|
|
|
self::class,
|
|
|
|
|
"getBiome"
|
2017-04-29 09:59:44 +00:00
|
|
|
|
], self::getBiome(0, 0 ));
|
2017-04-23 14:42:51 +00:00
|
|
|
|
|
2017-04-29 09:59:44 +00:00
|
|
|
|
foreach(self::$biomes as $rain ) {
|
|
|
|
|
foreach($rain as $biome ) {
|
|
|
|
|
$this->selector->addBiome($biome);
|
2017-04-23 14:42:51 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->selector->recalculate ();
|
|
|
|
|
|
2017-05-01 10:03:56 +00:00
|
|
|
|
$cover = Main::isOtherNS() ? new \pocketmine\level\generator\normal\populator\GroundCover() : new \pocketmine\level\generator\populator\GroundCover();
|
2017-04-23 14:42:51 +00:00
|
|
|
|
$this->generationPopulators [] = $cover;
|
|
|
|
|
|
|
|
|
|
$cave = new CavePopulator ();
|
2017-04-29 09:59:44 +00:00
|
|
|
|
$cave->setBaseAmount(0);
|
|
|
|
|
$cave->setRandomAmount(2);
|
2017-04-23 14:42:51 +00:00
|
|
|
|
$this->populators [] = $cave;
|
|
|
|
|
|
|
|
|
|
$ravine = new RavinePopulator ();
|
2017-04-29 09:59:44 +00:00
|
|
|
|
$ravine->setBaseAmount(0);
|
|
|
|
|
$ravine->setRandomAmount(51);
|
2017-04-23 14:42:51 +00:00
|
|
|
|
$this->populators [] = $ravine;
|
|
|
|
|
|
|
|
|
|
$mineshaft = new MineshaftPopulator ();
|
2017-04-29 09:59:44 +00:00
|
|
|
|
$mineshaft->setBaseAmount(0);
|
|
|
|
|
$mineshaft->setRandomAmount(102);
|
2017-04-23 14:42:51 +00:00
|
|
|
|
$this->populators [] = $mineshaft;
|
|
|
|
|
|
2017-05-02 17:52:53 +00:00
|
|
|
|
// https://twitter.com/Ad5001P4F/status/859430935468670976
|
|
|
|
|
// $lake = new LakePopulator ();
|
|
|
|
|
// $lake->setBaseAmount(0);
|
|
|
|
|
// $lake->setRandomAmount(1);
|
|
|
|
|
// $this->generationPopulators [] = $lake;
|
|
|
|
|
|
2017-04-23 14:42:51 +00:00
|
|
|
|
|
|
|
|
|
$fisl = new FloatingIslandPopulator();
|
2017-04-29 09:59:44 +00:00
|
|
|
|
$fisl->setBaseAmount(0);
|
|
|
|
|
$fisl->setRandomAmount(132);
|
2017-04-23 14:42:51 +00:00
|
|
|
|
$this->populators [] = $fisl;
|
|
|
|
|
|
2017-05-01 10:03:56 +00:00
|
|
|
|
$ores = Main::isOtherNS() ? new \pocketmine\level\generator\normal\populator\Ore() : new \pocketmine\level\generator\populator\Ore();
|
|
|
|
|
if(Main::isOtherNS()) $ores->setOreTypes([
|
|
|
|
|
new OreType2(new CoalOre (), 20, 16, 0, 128 ),
|
|
|
|
|
new OreType2(new IronOre (), 20, 8, 0, 64 ),
|
|
|
|
|
new OreType2(new RedstoneOre (), 8, 7, 0, 16 ),
|
|
|
|
|
new OreType2(new LapisOre (), 1, 6, 0, 32 ),
|
|
|
|
|
new OreType2(new GoldOre (), 2, 8, 0, 32 ),
|
|
|
|
|
new OreType2(new DiamondOre (), 1, 7, 0, 16 ),
|
|
|
|
|
new OreType2(new Dirt (), 20, 32, 0, 128 ),
|
|
|
|
|
new OreType2(new Gravel (), 10, 16, 0, 128 )
|
|
|
|
|
]);
|
|
|
|
|
if(!Main::isOtherNS()) $ores->setOreTypes([
|
2017-04-29 09:59:44 +00:00
|
|
|
|
new OreType(new CoalOre (), 20, 16, 0, 128 ),
|
|
|
|
|
new OreType(new IronOre (), 20, 8, 0, 64 ),
|
|
|
|
|
new OreType(new RedstoneOre (), 8, 7, 0, 16 ),
|
|
|
|
|
new OreType(new LapisOre (), 1, 6, 0, 32 ),
|
|
|
|
|
new OreType(new GoldOre (), 2, 8, 0, 32 ),
|
|
|
|
|
new OreType(new DiamondOre (), 1, 7, 0, 16 ),
|
|
|
|
|
new OreType(new Dirt (), 20, 32, 0, 128 ),
|
|
|
|
|
new OreType(new Gravel (), 10, 16, 0, 128 )
|
|
|
|
|
]);
|
2017-04-23 14:42:51 +00:00
|
|
|
|
$this->populators [] = $ores;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Adds a biome to the selector. Do not use this method directly use Main::registerBiome which registers it properly
|
|
|
|
|
* @param $biome Biome
|
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
public static function registerBiome(Biome $biome): bool {
|
2017-04-29 09:59:44 +00:00
|
|
|
|
foreach(self::$levels as $lvl )
|
|
|
|
|
if (isset($lvl->selector ))
|
|
|
|
|
$lvl->selector->addBiome($biome); // If no selector created, it would cause errors. These will be added when selectoes
|
|
|
|
|
if (! isset(self::$biomes [( string ) $biome->getRainfall ()] ))
|
2017-04-23 14:42:51 +00:00
|
|
|
|
self::$biomes [( string ) $biome->getRainfall ()] = [ ];
|
|
|
|
|
self::$biomes [( string ) $biome->getRainfall ()] [( string ) $biome->getTemperature ()] = $biome;
|
2017-04-29 09:59:44 +00:00
|
|
|
|
ksort(self::$biomes [( string ) $biome->getRainfall ()]);
|
|
|
|
|
ksort(self::$biomes);
|
2017-04-23 14:42:51 +00:00
|
|
|
|
self::$biomeById[$biome->getId()] = $biome;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Returns a biome by temperature
|
|
|
|
|
* @param $temperature float
|
|
|
|
|
* @param $rainfall float
|
|
|
|
|
*/
|
|
|
|
|
public static function getBiome($temperature, $rainfall) {
|
2017-04-29 09:59:44 +00:00
|
|
|
|
if (! isset(self::$biomes [( string ) round($rainfall, 1 )] )) {
|
|
|
|
|
while(! isset(self::$biomes [( string ) round($rainfall, 1 )] ) ) {
|
|
|
|
|
if (abs($rainfall - round($rainfall, 1 ) ) >= 0.05)
|
2017-04-23 14:42:51 +00:00
|
|
|
|
$rainfall += 0.1;
|
2017-04-29 09:59:44 +00:00
|
|
|
|
if (abs($rainfall - round($rainfall, 1 ) ) < 0.05)
|
2017-04-23 14:42:51 +00:00
|
|
|
|
$rainfall -= 0.1;
|
2017-04-29 09:59:44 +00:00
|
|
|
|
if (round($rainfall, 1 ) < 0)
|
2017-04-23 14:42:51 +00:00
|
|
|
|
$rainfall = 0;
|
2017-04-29 09:59:44 +00:00
|
|
|
|
if (round($rainfall, 1 ) >= 0.9)
|
2017-04-23 14:42:51 +00:00
|
|
|
|
$rainfall = 0.9;
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-04-29 09:59:44 +00:00
|
|
|
|
$b = self::$biomes [( string ) round($rainfall, 1 )];
|
|
|
|
|
foreach($b as $t => $biome ) {
|
|
|
|
|
if ($temperature <=(float ) $t) {
|
2017-04-23 14:42:51 +00:00
|
|
|
|
$ret = $biome;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-04-29 09:59:44 +00:00
|
|
|
|
if (is_string($ret )) {
|
2017-04-23 14:42:51 +00:00
|
|
|
|
$ret = new $ret ();
|
|
|
|
|
} else {
|
|
|
|
|
return $ret;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Returns a biome by its id
|
|
|
|
|
* @param $id int
|
|
|
|
|
* @return Biome
|
|
|
|
|
*/
|
|
|
|
|
public function getBiomeById(int $id): Biome {
|
|
|
|
|
return self::$biomeById[$id] ?? self::$biomeById(Biome::OCEAN);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Generates a chunk.
|
|
|
|
|
* Cloning method to make it work with new methods.
|
|
|
|
|
* @param $chunkX int
|
|
|
|
|
* @param $chunkZ int
|
|
|
|
|
*/
|
|
|
|
|
public function generateChunk($chunkX, $chunkZ) {
|
|
|
|
|
$this->reRegisterBiomes ();
|
|
|
|
|
|
2017-04-29 09:59:44 +00:00
|
|
|
|
$this->random->setSeed(0xdeadbeef ^ ($chunkX << 8) ^ $chunkZ ^ $this->level->getSeed ());
|
2017-04-23 14:42:51 +00:00
|
|
|
|
|
2017-04-29 09:59:44 +00:00
|
|
|
|
$noise = Generator::getFastNoise3D($this->noiseBase, 16, 128, 16, 4, 8, 4, $chunkX * 16, 0, $chunkZ * 16);
|
2017-04-23 14:42:51 +00:00
|
|
|
|
|
2017-04-29 09:59:44 +00:00
|
|
|
|
$chunk = $this->level->getChunk($chunkX, $chunkZ);
|
2017-04-23 14:42:51 +00:00
|
|
|
|
|
|
|
|
|
$biomeCache = [ ];
|
|
|
|
|
|
2017-04-29 09:59:44 +00:00
|
|
|
|
for($x = 0; $x < 16; $x++) {
|
|
|
|
|
for($z = 0; $z < 16; $z++) {
|
2017-04-23 14:42:51 +00:00
|
|
|
|
$minSum = 0;
|
|
|
|
|
$maxSum = 0;
|
|
|
|
|
$weightSum = 0;
|
|
|
|
|
|
2017-04-29 09:59:44 +00:00
|
|
|
|
$biome = $this->pickBiome($chunkX * 16 + $x, $chunkZ * 16 + $z);
|
|
|
|
|
$chunk->setBiomeId($x, $z, $biome->getId ());
|
2017-04-23 14:42:51 +00:00
|
|
|
|
|
2017-04-29 09:59:44 +00:00
|
|
|
|
for($sx = - self::$SMOOTH_SIZE; $sx <= self::$SMOOTH_SIZE; $sx++) {
|
|
|
|
|
for($sz = - self::$SMOOTH_SIZE; $sz <= self::$SMOOTH_SIZE; $sz++) {
|
2017-04-23 14:42:51 +00:00
|
|
|
|
|
|
|
|
|
$weight = self::$GAUSSIAN_KERNEL [$sx + self::$SMOOTH_SIZE] [$sz + self::$SMOOTH_SIZE];
|
|
|
|
|
|
|
|
|
|
if ($sx === 0 and $sz === 0) {
|
|
|
|
|
$adjacent = $biome;
|
|
|
|
|
} else {
|
2017-04-29 09:59:44 +00:00
|
|
|
|
$index = Level::chunkHash($chunkX * 16 + $x + $sx, $chunkZ * 16 + $z + $sz);
|
|
|
|
|
if (isset($biomeCache [$index] )) {
|
2017-04-23 14:42:51 +00:00
|
|
|
|
$adjacent = $biomeCache [$index];
|
|
|
|
|
} else {
|
2017-04-29 09:59:44 +00:00
|
|
|
|
$biomeCache [$index] = $adjacent = $this->pickBiome($chunkX * 16 + $x + $sx, $chunkZ * 16 + $z + $sz);
|
2017-04-23 14:42:51 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
$minSum += ($adjacent->getMinElevation () - 1) * $weight;
|
|
|
|
|
$maxSum += $adjacent->getMaxElevation () * $weight;
|
|
|
|
|
|
|
|
|
|
$weightSum += $weight;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$minSum /= $weightSum;
|
|
|
|
|
$maxSum /= $weightSum;
|
|
|
|
|
|
|
|
|
|
$smoothHeight = ($maxSum - $minSum) / 2;
|
|
|
|
|
|
2017-04-29 09:59:44 +00:00
|
|
|
|
for($y = 0; $y < 128; $y++) {
|
2017-04-23 14:42:51 +00:00
|
|
|
|
if ($y < 3 || ($y < 5 && $this->random->nextBoolean ())) {
|
2017-04-29 09:59:44 +00:00
|
|
|
|
$chunk->setBlockId($x, $y, $z, Block::BEDROCK);
|
2017-04-23 14:42:51 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
$noiseValue = $noise [$x] [$z] [$y] - 1 / $smoothHeight * ($y - $smoothHeight - $minSum);
|
|
|
|
|
|
|
|
|
|
if ($noiseValue > 0) {
|
2017-04-29 09:59:44 +00:00
|
|
|
|
$chunk->setBlockId($x, $y, $z, Block::STONE);
|
2017-04-23 14:42:51 +00:00
|
|
|
|
} elseif ($y <= $this->waterHeight) {
|
2017-04-29 09:59:44 +00:00
|
|
|
|
$chunk->setBlockId($x, $y, $z, Block::STILL_WATER);
|
2017-04-23 14:42:51 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-29 09:59:44 +00:00
|
|
|
|
foreach($this->generationPopulators as $populator ) {
|
|
|
|
|
$populator->populate($this->level, $chunkX, $chunkZ, $this->random);
|
2017-04-23 14:42:51 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Populates a chunk.
|
|
|
|
|
* @param $chunkX int
|
|
|
|
|
* @param $chunk2 int
|
|
|
|
|
*/
|
|
|
|
|
public function populateChunk($chunkX, $chunkZ) {
|
2017-04-29 09:59:44 +00:00
|
|
|
|
$this->random->setSeed(0xdeadbeef ^ ($chunkX << 8) ^ $chunkZ ^ $this->level->getSeed ());
|
|
|
|
|
foreach($this->populators as $populator ) {
|
|
|
|
|
$populator->populate($this->level, $chunkX, $chunkZ, $this->random);
|
2017-04-23 14:42:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Filling lava (lakes & rivers underground)...
|
|
|
|
|
for($x = $chunkX; $x < $chunkX + 16; $x ++)
|
|
|
|
|
for($z = $chunkZ; $z < $chunkZ + 16; $z ++)
|
|
|
|
|
for($y = 1; $y < 11; $y ++) {
|
2017-04-29 09:59:44 +00:00
|
|
|
|
if (! in_array($this->level->getBlockIdAt($x, $y, $z ), self::NOT_OVERWRITABLE ))
|
|
|
|
|
$this->level->setBlockIdAt($x, $y, $z, Block::LAVA);
|
2017-04-23 14:42:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-04-29 09:59:44 +00:00
|
|
|
|
$chunk = $this->level->getChunk($chunkX, $chunkZ);
|
|
|
|
|
$biome = Biome::getBiome($chunk->getBiomeId(7, 7 ));
|
|
|
|
|
$biome->populateChunk($this->level, $chunkX, $chunkZ, $this->random);
|
2017-04-23 14:42:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Constructs the class
|
|
|
|
|
* @param $options array
|
|
|
|
|
*/
|
|
|
|
|
public function __construct(array $options = []) {
|
|
|
|
|
if (self::$GAUSSIAN_KERNEL === null) {
|
|
|
|
|
self::generateKernel ();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Generates the genration kernel based on smooth size (here 2)
|
|
|
|
|
*/
|
|
|
|
|
private static function generateKernel() {
|
|
|
|
|
self::$GAUSSIAN_KERNEL = [ ];
|
|
|
|
|
|
|
|
|
|
$bellSize = 1 / self::$SMOOTH_SIZE;
|
|
|
|
|
$bellHeight = 2 * self::$SMOOTH_SIZE;
|
|
|
|
|
|
2017-04-29 09:59:44 +00:00
|
|
|
|
for($sx = - self::$SMOOTH_SIZE; $sx <= self::$SMOOTH_SIZE; $sx++) {
|
2017-04-23 14:42:51 +00:00
|
|
|
|
self::$GAUSSIAN_KERNEL [$sx + self::$SMOOTH_SIZE] = [ ];
|
|
|
|
|
|
2017-04-29 09:59:44 +00:00
|
|
|
|
for($sz = - self::$SMOOTH_SIZE; $sz <= self::$SMOOTH_SIZE; $sz++) {
|
2017-04-23 14:42:51 +00:00
|
|
|
|
$bx = $bellSize * $sx;
|
|
|
|
|
$bz = $bellSize * $sz;
|
2017-04-29 09:59:44 +00:00
|
|
|
|
self::$GAUSSIAN_KERNEL [$sx + self::$SMOOTH_SIZE] [$sz + self::$SMOOTH_SIZE] = $bellHeight * exp(- ($bx * $bx + $bz * $bz) / 2);
|
2017-04-23 14:42:51 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Returns the name of the generator
|
|
|
|
|
public function getName() {
|
|
|
|
|
return "betternormal";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Gives the generators settings.
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
|
|
|
|
public function getSettings(): array {
|
|
|
|
|
return [ ];
|
|
|
|
|
}
|
|
|
|
|
public function getSpawn() {
|
2017-04-29 09:59:44 +00:00
|
|
|
|
return new Vector3(127.5, 128, 127.5);
|
2017-04-23 14:42:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Returns a safe spawn location
|
|
|
|
|
*/
|
|
|
|
|
public function getSafeSpawn() {
|
2017-04-29 09:59:44 +00:00
|
|
|
|
return new Vector3(127.5, $this->getHighestWorkableBlock(127, 127 ), 127.5);
|
2017-04-23 14:42:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Gets the top block (y) on an x and z axes
|
|
|
|
|
* @param $x int
|
|
|
|
|
* @param $z int
|
|
|
|
|
*/
|
|
|
|
|
protected function getHighestWorkableBlock($x, $z) {
|
|
|
|
|
for($y = 127; $y > 0; -- $y) {
|
2017-04-29 09:59:44 +00:00
|
|
|
|
$b = $this->level->getBlockIdAt($x, $y, $z);
|
2017-04-23 14:42:51 +00:00
|
|
|
|
if ($b === Block::DIRT or $b === Block::GRASS or $b === Block::PODZOL) {
|
|
|
|
|
break;
|
|
|
|
|
} elseif ($b !== 0 and $b !== Block::SNOW_LAYER) {
|
|
|
|
|
return - 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-29 09:59:44 +00:00
|
|
|
|
return $y++;
|
2017-04-23 14:42:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Re registers all biomes for async
|
|
|
|
|
*/
|
|
|
|
|
public function reRegisterBiomes() {
|
2017-04-29 09:59:44 +00:00
|
|
|
|
$reflection = new \ReflectionClass('pocketmine\\level\\generator\\biome\\Biome');
|
|
|
|
|
$register = $reflection->getMethod('register');
|
|
|
|
|
$register->setAccessible(true);
|
|
|
|
|
foreach(self::$biomes as $rainfall => $arr ) {
|
|
|
|
|
foreach($arr as $tmp => $biome ) {
|
|
|
|
|
$register->invoke(null, $biome->getId (), $biome);
|
2017-04-23 14:42:51 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|