mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-15 02:09:42 +00:00
Generator works!
This commit is contained in:
parent
5bfc747622
commit
d5601b0c9f
@ -71,6 +71,7 @@ use pocketmine\inventory\StonecutterShapelessRecipe;
|
|||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\format\FullChunk;
|
use pocketmine\level\format\FullChunk;
|
||||||
use pocketmine\level\format\LevelProvider;
|
use pocketmine\level\format\LevelProvider;
|
||||||
|
use pocketmine\level\generator\biome\Biome;
|
||||||
use pocketmine\level\Level;
|
use pocketmine\level\Level;
|
||||||
use pocketmine\level\Location;
|
use pocketmine\level\Location;
|
||||||
use pocketmine\level\Position;
|
use pocketmine\level\Position;
|
||||||
@ -619,8 +620,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->isChunkPopulated($X, $Z)){
|
if(!$this->level->populateChunk($X, $Z)){
|
||||||
$this->level->generateChunk($X, $Z);
|
|
||||||
if($this->spawned){
|
if($this->spawned){
|
||||||
continue;
|
continue;
|
||||||
}else{
|
}else{
|
||||||
@ -628,6 +628,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
++$count;
|
++$count;
|
||||||
|
|
||||||
unset($this->loadQueue[$index]);
|
unset($this->loadQueue[$index]);
|
||||||
@ -1251,6 +1252,8 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
|||||||
|
|
||||||
$this->entityBaseTick(1);
|
$this->entityBaseTick(1);
|
||||||
|
|
||||||
|
if($currentTick % 80 === 0) $this->sendMessage(TextFormat::ITALIC . TextFormat::GRAY . "Y: ".round($this->y)."; biome: ". Biome::getBiome($this->level->getBiomeId((int) $this->x, (int) $this->z))->getName());
|
||||||
|
|
||||||
if($this->speed and $this->isSurvival()){
|
if($this->speed and $this->isSurvival()){
|
||||||
$speed = sqrt($this->speed->x ** 2 + $this->speed->z ** 2);
|
$speed = sqrt($this->speed->x ** 2 + $this->speed->z ** 2);
|
||||||
if($speed > 0.45){
|
if($speed > 0.45){
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
namespace pocketmine\level;
|
namespace pocketmine\level;
|
||||||
|
|
||||||
|
use pocketmine\level\format\FullChunk;
|
||||||
|
|
||||||
interface ChunkManager{
|
interface ChunkManager{
|
||||||
/**
|
/**
|
||||||
* Gets the raw block id.
|
* Gets the raw block id.
|
||||||
@ -63,4 +65,26 @@ interface ChunkManager{
|
|||||||
* @param int $data 0-15
|
* @param int $data 0-15
|
||||||
*/
|
*/
|
||||||
public function setBlockDataAt($x, $y, $z, $data);
|
public function setBlockDataAt($x, $y, $z, $data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $chunkX
|
||||||
|
* @param int $chunkZ
|
||||||
|
*
|
||||||
|
* @return FullChunk
|
||||||
|
*/
|
||||||
|
public function getChunk($chunkX, $chunkZ);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $chunkX
|
||||||
|
* @param int $chunkZ
|
||||||
|
* @param FullChunk $chunk
|
||||||
|
*/
|
||||||
|
public function setChunk($chunkX, $chunkZ, FullChunk $chunk);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the level seed
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getSeed();
|
||||||
}
|
}
|
@ -93,6 +93,7 @@ use pocketmine\tile\Tile;
|
|||||||
use pocketmine\utils\Cache;
|
use pocketmine\utils\Cache;
|
||||||
use pocketmine\utils\LevelException;
|
use pocketmine\utils\LevelException;
|
||||||
use pocketmine\utils\MainLogger;
|
use pocketmine\utils\MainLogger;
|
||||||
|
use pocketmine\utils\Random;
|
||||||
use pocketmine\utils\ReversePriorityQueue;
|
use pocketmine\utils\ReversePriorityQueue;
|
||||||
use pocketmine\utils\TextFormat;
|
use pocketmine\utils\TextFormat;
|
||||||
use pocketmine\level\particle\Particle;
|
use pocketmine\level\particle\Particle;
|
||||||
@ -191,6 +192,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
protected $chunkTickRadius;
|
protected $chunkTickRadius;
|
||||||
protected $chunkTickList = [];
|
protected $chunkTickList = [];
|
||||||
protected $chunksPerTick;
|
protected $chunksPerTick;
|
||||||
|
protected $chunksPopulatedPerTick;
|
||||||
|
protected $chunksPopulated = 0;
|
||||||
protected $clearChunksOnTick;
|
protected $clearChunksOnTick;
|
||||||
protected $randomTickBlocks = [
|
protected $randomTickBlocks = [
|
||||||
Block::GRASS => Grass::class,
|
Block::GRASS => Grass::class,
|
||||||
@ -219,7 +222,10 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
/** @var LevelTimings */
|
/** @var LevelTimings */
|
||||||
public $timings;
|
public $timings;
|
||||||
|
|
||||||
|
/** @var Generator */
|
||||||
protected $generator;
|
protected $generator;
|
||||||
|
/** @var Generator */
|
||||||
|
protected $generatorInstance;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the chunk unique hash/key
|
* Returns the chunk unique hash/key
|
||||||
@ -298,6 +304,7 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
|
|
||||||
$this->chunkTickRadius = min($this->server->getViewDistance(), max(1, (int) $this->server->getProperty("chunk-ticking.tick-radius", 4)));
|
$this->chunkTickRadius = min($this->server->getViewDistance(), max(1, (int) $this->server->getProperty("chunk-ticking.tick-radius", 4)));
|
||||||
$this->chunksPerTick = (int) $this->server->getProperty("chunk-ticking.per-tick", 260);
|
$this->chunksPerTick = (int) $this->server->getProperty("chunk-ticking.per-tick", 260);
|
||||||
|
$this->chunksPopulatedPerTick = (int) $this->server->getProperty("chunk-generation.populations-per-tick", 1);
|
||||||
$this->chunkTickList = [];
|
$this->chunkTickList = [];
|
||||||
$this->clearChunksOnTick = (bool) $this->server->getProperty("chunk-ticking.clear-tick-list", false);
|
$this->clearChunksOnTick = (bool) $this->server->getProperty("chunk-ticking.clear-tick-list", false);
|
||||||
|
|
||||||
@ -308,6 +315,9 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
|
|
||||||
public function initLevel(){
|
public function initLevel(){
|
||||||
$this->server->getGenerationManager()->openLevel($this, $this->generator, $this->provider->getGeneratorOptions());
|
$this->server->getGenerationManager()->openLevel($this, $this->generator, $this->provider->getGeneratorOptions());
|
||||||
|
$generator = $this->generator;
|
||||||
|
$this->generatorInstance = new $generator($this->provider->getGeneratorOptions());
|
||||||
|
$this->generatorInstance->init($this, new Random($this->getSeed()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -592,6 +602,8 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
|
|
||||||
$this->processChunkRequest();
|
$this->processChunkRequest();
|
||||||
|
|
||||||
|
$this->chunksPopulated = 0;
|
||||||
|
|
||||||
$this->timings->doTick->stopTiming();
|
$this->timings->doTick->stopTiming();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2275,6 +2287,32 @@ class Level implements ChunkManager, Metadatable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function populateChunk($x, $z){
|
||||||
|
if(!$this->isChunkPopulated($x, $z)){
|
||||||
|
$populate = true;
|
||||||
|
for($xx = -1; $xx <= 1; ++$xx){
|
||||||
|
for($zz = -1; $zz <= 1; ++$zz){
|
||||||
|
if(!$this->isChunkGenerated($x + $xx, $z + $zz)){
|
||||||
|
$populate = false;
|
||||||
|
$this->generateChunk($x + $xx, $z + $zz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->chunksPopulated < $this->chunksPopulatedPerTick and $populate){
|
||||||
|
$this->generatorInstance->populateChunk($x, $z);
|
||||||
|
$chunk = $this->getChunk($x, $z);
|
||||||
|
$chunk->setPopulated(true);
|
||||||
|
$this->server->getPluginManager()->callEvent(new ChunkPopulateEvent($chunk));
|
||||||
|
++$this->chunksPopulated;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public function generateChunk($x, $z){
|
public function generateChunk($x, $z){
|
||||||
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] = true;
|
||||||
|
@ -295,13 +295,9 @@ class McRegion extends BaseLevelProvider{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected function loadRegion($x, $z){
|
protected function loadRegion($x, $z){
|
||||||
if(isset($this->regions[$index = Level::chunkHash($x, $z)])){
|
if(!isset($this->regions[$index = Level::chunkHash($x, $z)])){
|
||||||
return true;
|
$this->regions[$index] = new RegionLoader($this, $x, $z);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->regions[$index] = new RegionLoader($this, $x, $z);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function close(){
|
public function close(){
|
||||||
|
@ -30,6 +30,7 @@ use pocketmine\block\IronOre;
|
|||||||
use pocketmine\block\LapisOre;
|
use pocketmine\block\LapisOre;
|
||||||
use pocketmine\block\RedstoneOre;
|
use pocketmine\block\RedstoneOre;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
|
use pocketmine\level\ChunkManager;
|
||||||
use pocketmine\level\format\FullChunk;
|
use pocketmine\level\format\FullChunk;
|
||||||
use pocketmine\level\generator\populator\Ore;
|
use pocketmine\level\generator\populator\Ore;
|
||||||
use pocketmine\level\generator\populator\Populator;
|
use pocketmine\level\generator\populator\Populator;
|
||||||
@ -37,7 +38,7 @@ use pocketmine\math\Vector3;
|
|||||||
use pocketmine\utils\Random;
|
use pocketmine\utils\Random;
|
||||||
|
|
||||||
class Flat extends Generator{
|
class Flat extends Generator{
|
||||||
/** @var GenerationChunkManager */
|
/** @var ChunkManager */
|
||||||
private $level;
|
private $level;
|
||||||
/** @var FullChunk */
|
/** @var FullChunk */
|
||||||
private $chunk;
|
private $chunk;
|
||||||
@ -135,7 +136,7 @@ class Flat extends Generator{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function init(GenerationChunkManager $level, Random $random){
|
public function init(ChunkManager $level, Random $random){
|
||||||
$this->level = $level;
|
$this->level = $level;
|
||||||
$this->random = $random;
|
$this->random = $random;
|
||||||
|
|
||||||
|
@ -42,8 +42,6 @@ class GenerationChunkManager implements ChunkManager{
|
|||||||
|
|
||||||
protected $seed;
|
protected $seed;
|
||||||
|
|
||||||
protected $changes = [];
|
|
||||||
|
|
||||||
public function __construct(GenerationManager $manager, $levelID, $seed, $class, array $options){
|
public function __construct(GenerationManager $manager, $levelID, $seed, $class, array $options){
|
||||||
if(!class_exists($class, true) or !is_subclass_of($class, Generator::class)){
|
if(!class_exists($class, true) or !is_subclass_of($class, Generator::class)){
|
||||||
throw new \InvalidStateException("Class $class does not exists or is not a subclass of Noise");
|
throw new \InvalidStateException("Class $class does not exists or is not a subclass of Noise");
|
||||||
@ -88,33 +86,8 @@ class GenerationChunkManager implements ChunkManager{
|
|||||||
return $chunk;
|
return $chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return FullChunk[]
|
|
||||||
*/
|
|
||||||
public function getChangedChunks(){
|
|
||||||
return $this->changes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function cleanChangedChunks(){
|
|
||||||
$this->changes = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function cleanChangedChunk($index){
|
public function cleanChangedChunk($index){
|
||||||
unset($this->changes[$index]);
|
unset($this->chunks[$index]);
|
||||||
}
|
|
||||||
|
|
||||||
public function doGarbageCollection(){
|
|
||||||
$count = 0;
|
|
||||||
|
|
||||||
foreach($this->chunks as $index => $chunk){
|
|
||||||
if(!isset($this->changes[$index]) or $chunk->isPopulated()){
|
|
||||||
unset($this->chunks[$index]);
|
|
||||||
unset($this->changes[$index]);
|
|
||||||
++$count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generateChunk($chunkX, $chunkZ){
|
public function generateChunk($chunkX, $chunkZ){
|
||||||
@ -163,7 +136,6 @@ class GenerationChunkManager implements ChunkManager{
|
|||||||
try{
|
try{
|
||||||
$chunk = $this->getChunk($chunkX, $chunkZ);
|
$chunk = $this->getChunk($chunkX, $chunkZ);
|
||||||
$chunk->setGenerated(true);
|
$chunk->setGenerated(true);
|
||||||
$this->changes[Level::chunkHash($chunkX, $chunkZ)] = $chunk;
|
|
||||||
}catch(\Exception $e){
|
}catch(\Exception $e){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -172,7 +144,6 @@ class GenerationChunkManager implements ChunkManager{
|
|||||||
try{
|
try{
|
||||||
$chunk = $this->getChunk($chunkX, $chunkZ);
|
$chunk = $this->getChunk($chunkX, $chunkZ);
|
||||||
$chunk->setPopulated(true);
|
$chunk->setPopulated(true);
|
||||||
$this->changes[Level::chunkHash($chunkX, $chunkZ)] = $chunk;
|
|
||||||
}catch(\Exception $e){
|
}catch(\Exception $e){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -191,10 +162,6 @@ class GenerationChunkManager implements ChunkManager{
|
|||||||
*/
|
*/
|
||||||
public function setChunk($chunkX, $chunkZ, FullChunk $chunk){
|
public function setChunk($chunkX, $chunkZ, FullChunk $chunk){
|
||||||
$this->chunks[$index = Level::chunkHash($chunkX, $chunkZ)] = $chunk;
|
$this->chunks[$index = Level::chunkHash($chunkX, $chunkZ)] = $chunk;
|
||||||
$this->changes[$index] = $chunk;
|
|
||||||
if($chunk->isPopulated()){
|
|
||||||
//TODO: Queue to be sent
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,15 +72,10 @@ class GenerationLevelManager extends GenerationManager{
|
|||||||
|
|
||||||
public function generateChunk($levelID, $chunkX, $chunkZ){
|
public function generateChunk($levelID, $chunkX, $chunkZ){
|
||||||
if(isset($this->levels[$levelID])){
|
if(isset($this->levels[$levelID])){
|
||||||
$this->levels[$levelID]->populateChunk($chunkX, $chunkZ); //Request population directly
|
$this->levels[$levelID]->generateChunk($chunkX, $chunkZ); //Request population directly
|
||||||
if(isset($this->levels[$levelID])){
|
if(isset($this->levels[$levelID])){
|
||||||
foreach($this->levels[$levelID]->getChangedChunks() as $index => $chunk){
|
$this->sendChunk($levelID, $this->levels[$levelID]->getChunk($chunkX, $chunkZ));
|
||||||
$this->sendChunk($levelID, $chunk);
|
$this->levels[$levelID]->cleanChangedChunk(Level::chunkHash($chunkX, $chunkZ));
|
||||||
$this->levels[$levelID]->cleanChangedChunk($index);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->levels[$levelID]->doGarbageCollection();
|
|
||||||
$this->levels[$levelID]->cleanChangedChunks();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
namespace pocketmine\level\generator;
|
namespace pocketmine\level\generator;
|
||||||
|
|
||||||
|
use pocketmine\block\Block;
|
||||||
use pocketmine\level\format\FullChunk;
|
use pocketmine\level\format\FullChunk;
|
||||||
use pocketmine\level\generator\biome\Biome;
|
use pocketmine\level\generator\biome\Biome;
|
||||||
use pocketmine\level\Level;
|
use pocketmine\level\Level;
|
||||||
@ -111,6 +112,7 @@ class GenerationManager{
|
|||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
$this->loader = $loader;
|
$this->loader = $loader;
|
||||||
$chunkX = $chunkZ = null;
|
$chunkX = $chunkZ = null;
|
||||||
|
Block::init();
|
||||||
Biome::init();
|
Biome::init();
|
||||||
|
|
||||||
while($this->shutdown !== true){
|
while($this->shutdown !== true){
|
||||||
@ -130,7 +132,7 @@ class GenerationManager{
|
|||||||
$this->readPacket();
|
$this->readPacket();
|
||||||
}
|
}
|
||||||
}catch(\Exception $e){
|
}catch(\Exception $e){
|
||||||
$this->logger->warning("[Noise Thread] Exception: " . $e->getMessage() . " on file \"" . $e->getFile() . "\" line " . $e->getLine());
|
$this->logger->warning("[Generation Thread] Exception: " . $e->getMessage() . " on file \"" . $e->getFile() . "\" line " . $e->getLine());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -143,17 +145,10 @@ class GenerationManager{
|
|||||||
|
|
||||||
protected function generateChunk($levelID, $chunkX, $chunkZ){
|
protected function generateChunk($levelID, $chunkX, $chunkZ){
|
||||||
if(isset($this->levels[$levelID])){
|
if(isset($this->levels[$levelID])){
|
||||||
$this->levels[$levelID]->populateChunk($chunkX, $chunkZ); //Request population directly
|
$this->levels[$levelID]->generateChunk($chunkX, $chunkZ);
|
||||||
if(isset($this->levels[$levelID])){
|
if(isset($this->levels[$levelID])){
|
||||||
foreach($this->levels[$levelID]->getChangedChunks() as $index => $chunk){
|
$this->sendChunk($levelID, $this->levels[$levelID]->getChunk($chunkX, $chunkZ));
|
||||||
if($chunk->isPopulated()){
|
$this->levels[$levelID]->cleanChangedChunk(Level::chunkHash($chunkX, $chunkZ));
|
||||||
$this->sendChunk($levelID, $chunk);
|
|
||||||
$this->levels[$levelID]->cleanChangedChunk($index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->levels[$levelID]->doGarbageCollection();
|
|
||||||
$this->levels[$levelID]->cleanChangedChunks();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
*/
|
*/
|
||||||
namespace pocketmine\level\generator;
|
namespace pocketmine\level\generator;
|
||||||
|
|
||||||
|
use pocketmine\level\ChunkManager;
|
||||||
use pocketmine\level\generator\noise\Noise;
|
use pocketmine\level\generator\noise\Noise;
|
||||||
use pocketmine\level\generator\normal\Normal;
|
use pocketmine\level\generator\normal\Normal;
|
||||||
use pocketmine\utils\Random;
|
use pocketmine\utils\Random;
|
||||||
@ -41,6 +42,11 @@ abstract class Generator{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $name
|
||||||
|
*
|
||||||
|
* @return Generator
|
||||||
|
*/
|
||||||
public static function getGenerator($name){
|
public static function getGenerator($name){
|
||||||
if(isset(Generator::$list[$name = strtolower($name)])){
|
if(isset(Generator::$list[$name = strtolower($name)])){
|
||||||
return Generator::$list[$name];
|
return Generator::$list[$name];
|
||||||
@ -229,7 +235,7 @@ abstract class Generator{
|
|||||||
|
|
||||||
public abstract function __construct(array $settings = []);
|
public abstract function __construct(array $settings = []);
|
||||||
|
|
||||||
public abstract function init(GenerationChunkManager $level, Random $random);
|
public abstract function init(ChunkManager $level, Random $random);
|
||||||
|
|
||||||
public abstract function generateChunk($chunkX, $chunkZ);
|
public abstract function generateChunk($chunkX, $chunkZ);
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
namespace pocketmine\level\generator\biome;
|
namespace pocketmine\level\generator\biome;
|
||||||
|
|
||||||
|
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\BeachBiome;
|
||||||
use pocketmine\level\generator\normal\biome\DesertBiome;
|
use pocketmine\level\generator\normal\biome\DesertBiome;
|
||||||
@ -58,6 +59,11 @@ abstract class Biome{
|
|||||||
/** @var Populator[] */
|
/** @var Populator[] */
|
||||||
private $populators = [];
|
private $populators = [];
|
||||||
|
|
||||||
|
private $minElevation;
|
||||||
|
private $maxElevation;
|
||||||
|
|
||||||
|
private $groundCover = [];
|
||||||
|
|
||||||
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);
|
||||||
@ -116,4 +122,31 @@ abstract class Biome{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public abstract function getName();
|
public abstract function getName();
|
||||||
|
|
||||||
|
public function getMinElevation(){
|
||||||
|
return $this->minElevation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMaxElevation(){
|
||||||
|
return $this->maxElevation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setElevation($min, $max){
|
||||||
|
$this->minElevation = $min;
|
||||||
|
$this->maxElevation = $max;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Block[]
|
||||||
|
*/
|
||||||
|
public function getGroundCover(){
|
||||||
|
return $this->groundCover;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Block[] $covers
|
||||||
|
*/
|
||||||
|
public function setGroundCover(array $covers){
|
||||||
|
$this->groundCover = $covers;
|
||||||
|
}
|
||||||
}
|
}
|
@ -42,7 +42,7 @@ class BiomeSelector{
|
|||||||
public function __construct(Random $random, Biome $fallback){
|
public function __construct(Random $random, Biome $fallback){
|
||||||
$this->fallback = $fallback;
|
$this->fallback = $fallback;
|
||||||
$this->temperature = new Simplex($random, 1, 0.004, 0.5, 2);
|
$this->temperature = new Simplex($random, 1, 0.004, 0.5, 2);
|
||||||
$this->rainfall = new Simplex($random, 1, 0.004, 0.5, 2);
|
$this->rainfall = new Simplex($random, 2, 0.004, 0.5, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addBiome(Biome $biome, $start, $end){
|
public function addBiome(Biome $biome, $start, $end){
|
||||||
@ -58,8 +58,6 @@ class BiomeSelector{
|
|||||||
*/
|
*/
|
||||||
public function pickBiome($x, $z){
|
public function pickBiome($x, $z){
|
||||||
|
|
||||||
return Biome::getBiome(Biome::PLAINS);
|
|
||||||
|
|
||||||
//$temperature = $this->temperature->noise2D($x, $z);
|
//$temperature = $this->temperature->noise2D($x, $z);
|
||||||
$rainfall = $this->rainfall->noise2D($x, $z);
|
$rainfall = $this->rainfall->noise2D($x, $z);
|
||||||
|
|
||||||
@ -70,11 +68,15 @@ class BiomeSelector{
|
|||||||
}elseif($rainfall > 0.6){
|
}elseif($rainfall > 0.6){
|
||||||
return Biome::getBiome(Biome::BEACH);
|
return Biome::getBiome(Biome::BEACH);
|
||||||
}elseif($rainfall > 0.2){
|
}elseif($rainfall > 0.2){
|
||||||
return Biome::getBiome(Biome::PLAINS);
|
|
||||||
}elseif($rainfall > -0.3){
|
|
||||||
return Biome::getBiome(Biome::FOREST);
|
return Biome::getBiome(Biome::FOREST);
|
||||||
}else{
|
}elseif($rainfall > -0.3){
|
||||||
|
return Biome::getBiome(Biome::PLAINS);
|
||||||
|
}elseif($rainfall > -0.6){
|
||||||
return Biome::getBiome(Biome::DESERT);
|
return Biome::getBiome(Biome::DESERT);
|
||||||
|
}elseif($rainfall > -0.7){
|
||||||
|
return Biome::getBiome(Biome::BEACH);
|
||||||
|
}else{
|
||||||
|
return Biome::getBiome(Biome::OCEAN);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -64,9 +64,9 @@ class Perlin extends Noise{
|
|||||||
$y += $this->offsetY;
|
$y += $this->offsetY;
|
||||||
$z += $this->offsetZ;
|
$z += $this->offsetZ;
|
||||||
|
|
||||||
$floorX = (int) floor($x);
|
$floorX = (int) $x;
|
||||||
$floorY = (int) floor($y);
|
$floorY = (int) $y;
|
||||||
$floorZ = (int) floor($z);
|
$floorZ = (int) $z;
|
||||||
|
|
||||||
$X = $floorX & 0xFF;
|
$X = $floorX & 0xFF;
|
||||||
$Y = $floorY & 0xFF;
|
$Y = $floorY & 0xFF;
|
||||||
@ -77,26 +77,70 @@ class Perlin extends Noise{
|
|||||||
$z -= $floorZ;
|
$z -= $floorZ;
|
||||||
|
|
||||||
//Fade curves
|
//Fade curves
|
||||||
$fX = self::fade($x);
|
//$fX = self::fade($x);
|
||||||
$fY = self::fade($y);
|
//$fY = self::fade($y);
|
||||||
$fZ = self::fade($z);
|
//$fZ = self::fade($z);
|
||||||
|
$fX = $x ** 3 * ($x * ($x * 6 - 15) + 10);
|
||||||
|
$fY = $y ** 3 * ($y * ($y * 6 - 15) + 10);
|
||||||
|
$fZ = $z ** 3 * ($z * ($z * 6 - 15) + 10);
|
||||||
|
|
||||||
//Cube corners
|
//Cube corners
|
||||||
$A = $this->perm[$X] + $Y;
|
$A = $this->perm[$X] + $Y;
|
||||||
|
$B = $this->perm[$X + 1] + $Y;
|
||||||
|
|
||||||
$AA = $this->perm[$A] + $Z;
|
$AA = $this->perm[$A] + $Z;
|
||||||
$AB = $this->perm[$A + 1] + $Z;
|
$AB = $this->perm[$A + 1] + $Z;
|
||||||
$B = $this->perm[$X + 1] + $Y;
|
|
||||||
$BA = $this->perm[$B] + $Z;
|
$BA = $this->perm[$B] + $Z;
|
||||||
$BB = $this->perm[$B + 1] + $Z;
|
$BB = $this->perm[$B + 1] + $Z;
|
||||||
|
|
||||||
return self::lerp($fZ, self::lerp($fY, self::lerp($fX, self::grad($this->perm[$AA], $x, $y, $z),
|
$AA1 = self::grad($this->perm[$AA], $x, $y, $z);
|
||||||
self::grad($this->perm[$BA], $x - 1, $y, $z)),
|
$BA1 = self::grad($this->perm[$BA], $x - 1, $y, $z);
|
||||||
self::lerp($fX, self::grad($this->perm[$AB], $x, $y - 1, $z),
|
$AB1 = self::grad($this->perm[$AB], $x, $y - 1, $z);
|
||||||
self::grad($this->perm[$BB], $x - 1, $y - 1, $z))),
|
$BB1 = self::grad($this->perm[$BB], $x - 1, $y - 1, $z);
|
||||||
self::lerp($fY, self::lerp($fX, self::grad($this->perm[$AA + 1], $x, $y, $z - 1),
|
$AA2 = self::grad($this->perm[$AA + 1], $x, $y, $z - 1);
|
||||||
self::grad($this->perm[$BA + 1], $x - 1, $y, $z - 1)),
|
$BA2 = self::grad($this->perm[$BA + 1], $x - 1, $y, $z - 1);
|
||||||
self::lerp($fX, self::grad($this->perm[$AB + 1], $x, $y - 1, $z - 1),
|
$AB2 = self::grad($this->perm[$AB + 1], $x, $y - 1, $z - 1);
|
||||||
self::grad($this->perm[$BB + 1], $x - 1, $y - 1, $z - 1))));
|
$BB2 = self::grad($this->perm[$BB + 1], $x - 1, $y - 1, $z - 1);
|
||||||
|
|
||||||
|
$xLerp11 = $AA1 + $fX * ($BA1 - $AA1);
|
||||||
|
|
||||||
|
$zLerp1 = $xLerp11 + $fY * ($AB1 + $fX * ($BB1 - $AB1) - $xLerp11);
|
||||||
|
|
||||||
|
$xLerp21 = $AA2 + $fX * ($BA2 - $AA2);
|
||||||
|
|
||||||
|
return $zLerp1 + $fZ * ($xLerp21 + $fY * ($AB2 + $fX * ($BB2 - $AB2) - $xLerp21) - $zLerp1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
return self::lerp(
|
||||||
|
$fZ,
|
||||||
|
self::lerp(
|
||||||
|
$fY,
|
||||||
|
self::lerp(
|
||||||
|
$fX,
|
||||||
|
self::grad($this->perm[$AA], $x, $y, $z),
|
||||||
|
self::grad($this->perm[$BA], $x - 1, $y, $z)
|
||||||
|
),
|
||||||
|
self::lerp(
|
||||||
|
$fX,
|
||||||
|
self::grad($this->perm[$AB], $x, $y - 1, $z),
|
||||||
|
self::grad($this->perm[$BB], $x - 1, $y - 1, $z)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
self::lerp(
|
||||||
|
$fY,
|
||||||
|
self::lerp(
|
||||||
|
$fX,
|
||||||
|
self::grad($this->perm[$AA + 1], $x, $y, $z - 1),
|
||||||
|
self::grad($this->perm[$BA + 1], $x - 1, $y, $z - 1)
|
||||||
|
),
|
||||||
|
self::lerp(
|
||||||
|
$fX,
|
||||||
|
self::grad($this->perm[$AB + 1], $x, $y - 1, $z - 1),
|
||||||
|
self::grad($this->perm[$BB + 1], $x - 1, $y - 1, $z - 1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getNoise2D($x, $y){
|
public function getNoise2D($x, $y){
|
||||||
|
@ -99,16 +99,14 @@ class Simplex extends Perlin{
|
|||||||
|
|
||||||
// Skew the input space to determine which simplex cell we're in
|
// Skew the input space to determine which simplex cell we're in
|
||||||
$s = ($x + $y + $z) * self::$F3; // Very nice and simple skew factor for 3D
|
$s = ($x + $y + $z) * self::$F3; // Very nice and simple skew factor for 3D
|
||||||
$i = (int) floor($x + $s);
|
$i = (int) ($x + $s);
|
||||||
$j = (int) floor($y + $s);
|
$j = (int) ($y + $s);
|
||||||
$k = (int) floor($z + $s);
|
$k = (int) ($z + $s);
|
||||||
$t = ($i + $j + $k) * self::$G3;
|
$t = ($i + $j + $k) * self::$G3;
|
||||||
$X0 = $i - $t; // Unskew the cell origin back to (x,y,z) space
|
// Unskew the cell origin back to (x,y,z) space
|
||||||
$Y0 = $j - $t;
|
$x0 = $x - ($i - $t); // The x,y,z distances from the cell origin
|
||||||
$Z0 = $k - $t;
|
$y0 = $y - ($j - $t);
|
||||||
$x0 = $x - $X0; // The x,y,z distances from the cell origin
|
$z0 = $z - ($k - $t);
|
||||||
$y0 = $y - $Y0;
|
|
||||||
$z0 = $z - $Z0;
|
|
||||||
|
|
||||||
// For the 3D case, the simplex shape is a slightly irregular tetrahedron.
|
// For the 3D case, the simplex shape is a slightly irregular tetrahedron.
|
||||||
|
|
||||||
@ -185,47 +183,37 @@ class Simplex extends Perlin{
|
|||||||
$ii = $i & 255;
|
$ii = $i & 255;
|
||||||
$jj = $j & 255;
|
$jj = $j & 255;
|
||||||
$kk = $k & 255;
|
$kk = $k & 255;
|
||||||
$gi0 = $this->perm[$ii + $this->perm[$jj + $this->perm[$kk]]] % 12;
|
|
||||||
$gi1 = $this->perm[$ii + $i1 + $this->perm[$jj + $j1 + $this->perm[$kk + $k1]]] % 12;
|
$n = 0;
|
||||||
$gi2 = $this->perm[$ii + $i2 + $this->perm[$jj + $j2 + $this->perm[$kk + $k2]]] % 12;
|
|
||||||
$gi3 = $this->perm[$ii + 1 + $this->perm[$jj + 1 + $this->perm[$kk + 1]]] % 12;
|
|
||||||
|
|
||||||
// Calculate the contribution from the four corners
|
// Calculate the contribution from the four corners
|
||||||
$t0 = 0.6 - $x0 ** 2 - $y0 ** 2 - $z0 ** 2;
|
$t0 = 0.6 - $x0 ** 2 - $y0 ** 2 - $z0 ** 2;
|
||||||
if($t0 < 0){
|
if($t0 > 0){
|
||||||
$n0 = 0.0;
|
$gi0 = self::$grad3[$this->perm[$ii + $this->perm[$jj + $this->perm[$kk]]] % 12];
|
||||||
}else{
|
$n += $t0 ** 4 * ($gi0[0] * $x0 + $gi0[1] * $y0 + $gi0[2] * $z0);
|
||||||
$t0 **= 2;
|
|
||||||
$n0 = $t0 ** 2 * self::dot3D(self::$grad3[$gi0], $x0, $y0, $z0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$t1 = 0.6 - $x1 ** 2 - $y1 ** 2 - $z1 ** 2;
|
$t1 = 0.6 - $x1 ** 2 - $y1 ** 2 - $z1 ** 2;
|
||||||
if($t1 < 0){
|
if($t1 > 0){
|
||||||
$n1 = 0.0;
|
$gi1 = self::$grad3[$this->perm[$ii + $i1 + $this->perm[$jj + $j1 + $this->perm[$kk + $k1]]] % 12];
|
||||||
}else{
|
$n += $t1 ** 4 * ($gi1[0] * $x1 + $gi1[1] * $y1 + $gi1[2] * $z1);
|
||||||
$t1 **= 2;
|
|
||||||
$n1 = $t1 ** 2 * self::dot3D(self::$grad3[$gi1], $x1, $y1, $z1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$t2 = 0.6 - $x2 ** 2 - $y2 ** 2 - $z2 ** 2;
|
$t2 = 0.6 - $x2 ** 2 - $y2 ** 2 - $z2 ** 2;
|
||||||
if($t2 < 0){
|
if($t2 > 0){
|
||||||
$n2 = 0.0;
|
$gi2 = self::$grad3[$this->perm[$ii + $i2 + $this->perm[$jj + $j2 + $this->perm[$kk + $k2]]] % 12];
|
||||||
}else{
|
$n += $t2 ** 4 * ($gi2[0] * $x2 + $gi2[1] * $y2 + $gi2[2] * $z2);
|
||||||
$t2 **= 2;
|
|
||||||
$n2 = $t2 ** 2 * self::dot3D(self::$grad3[$gi2], $x2, $y2, $z2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$t3 = 0.6 - $x3 ** 2 - $y3 ** 2 - $z3 ** 2;
|
$t3 = 0.6 - $x3 ** 2 - $y3 ** 2 - $z3 ** 2;
|
||||||
if($t3 < 0){
|
if($t3 > 0){
|
||||||
$n3 = 0.0;
|
$gi3 = self::$grad3[$this->perm[$ii + 1 + $this->perm[$jj + 1 + $this->perm[$kk + 1]]] % 12];
|
||||||
}else{
|
$n += $t3 ** 4 * ($gi3[0] * $x3 + $gi3[1] * $y3 + $gi3[2] * $z3);
|
||||||
$t3 **= 2;
|
|
||||||
$n3 = $t3 ** 2 * self::dot3D(self::$grad3[$gi3], $x3, $y3, $z3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add contributions from each corner to get the noise value.
|
// Add contributions from each corner to get the noise value.
|
||||||
// The result is scaled to stay just inside [-1,1]
|
// The result is scaled to stay just inside [-1,1]
|
||||||
return 32.0 * ($n0 + $n1 + $n2 + $n3);
|
return 32.0 * $n;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getNoise2D($x, $y){
|
public function getNoise2D($x, $y){
|
||||||
@ -234,13 +222,12 @@ class Simplex extends Perlin{
|
|||||||
|
|
||||||
// Skew the input space to determine which simplex cell we're in
|
// Skew the input space to determine which simplex cell we're in
|
||||||
$s = ($x + $y) * self::$F2; // Hairy factor for 2D
|
$s = ($x + $y) * self::$F2; // Hairy factor for 2D
|
||||||
$i = (int) floor($x + $s);
|
$i = (int) ($x + $s);
|
||||||
$j = (int) floor($y + $s);
|
$j = (int) ($y + $s);
|
||||||
$t = ($i + $j) * self::$G2;
|
$t = ($i + $j) * self::$G2;
|
||||||
$X0 = $i - $t; // Unskew the cell origin back to (x,y) space
|
// Unskew the cell origin back to (x,y) space
|
||||||
$Y0 = $j - $t;
|
$x0 = $x - ($i - $t); // The x,y distances from the cell origin
|
||||||
$x0 = $x - $X0; // The x,y distances from the cell origin
|
$y0 = $y - ($j - $t);
|
||||||
$y0 = $y - $Y0;
|
|
||||||
|
|
||||||
// For the 2D case, the simplex shape is an equilateral triangle.
|
// For the 2D case, the simplex shape is an equilateral triangle.
|
||||||
|
|
||||||
@ -267,26 +254,26 @@ class Simplex extends Perlin{
|
|||||||
// Work out the hashed gradient indices of the three simplex corners
|
// Work out the hashed gradient indices of the three simplex corners
|
||||||
$ii = $i & 255;
|
$ii = $i & 255;
|
||||||
$jj = $j & 255;
|
$jj = $j & 255;
|
||||||
$gi0 = $this->perm[$ii + $this->perm[$jj]] % 12;
|
|
||||||
$gi1 = $this->perm[$ii + $i1 + $this->perm[$jj + $j1]] % 12;
|
|
||||||
$gi2 = $this->perm[$ii + 1 + $this->perm[$jj + 1]] % 12;
|
|
||||||
|
|
||||||
$n = 0;
|
$n = 0;
|
||||||
|
|
||||||
// Calculate the contribution from the three corners
|
// Calculate the contribution from the three corners
|
||||||
$t = 0.5 - $x0 ** 2 - $y0 ** 2;
|
$t0 = 0.5 - $x0 ** 2 - $y0 ** 2;
|
||||||
if($t > 0){
|
if($t0 > 0){
|
||||||
$n += $t ** 4 * self::dot2D(self::$grad3[$gi0], $x0, $y0); // (x,y) of grad3 used for 2D gradient
|
$gi0 = self::$grad3[$this->perm[$ii + $this->perm[$jj]] % 12];
|
||||||
|
$n += $t0 ** 4 * ($gi0[0] * $x0 + $gi0[1] * $y0); // (x,y) of grad3 used for 2D gradient
|
||||||
}
|
}
|
||||||
|
|
||||||
$t = 0.5 - $x1 ** 2 - $y1 ** 2;
|
$t1 = 0.5 - $x1 ** 2 - $y1 ** 2;
|
||||||
if($t > 0){
|
if($t1 > 0){
|
||||||
$n += $t ** 4 * self::dot2D(self::$grad3[$gi1], $x1, $y1);
|
$gi1 = self::$grad3[$this->perm[$ii + $i1 + $this->perm[$jj + $j1]] % 12];
|
||||||
|
$n += $t1 ** 4 * ($gi1[0] * $x1 + $gi1[1] * $y1);
|
||||||
}
|
}
|
||||||
|
|
||||||
$t = 0.5 - $x2 ** 2 - $y2 ** 2;
|
$t2 = 0.5 - $x2 ** 2 - $y2 ** 2;
|
||||||
if($t > 0){
|
if($t2 > 0){
|
||||||
$n += $t ** 4 * self::dot2D(self::$grad3[$gi2], $x2, $y2);
|
$gi2 = self::$grad3[$this->perm[$ii + 1 + $this->perm[$jj + 1]] % 12];
|
||||||
|
$n += $t2 ** 4 * ($gi2[0] * $x2 + $gi2[1] * $y2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add contributions from each corner to get the noise value.
|
// Add contributions from each corner to get the noise value.
|
||||||
|
@ -30,14 +30,17 @@ use pocketmine\block\Gravel;
|
|||||||
use pocketmine\block\IronOre;
|
use pocketmine\block\IronOre;
|
||||||
use pocketmine\block\LapisOre;
|
use pocketmine\block\LapisOre;
|
||||||
use pocketmine\block\RedstoneOre;
|
use pocketmine\block\RedstoneOre;
|
||||||
|
use pocketmine\level\ChunkManager;
|
||||||
use pocketmine\level\generator\biome\Biome;
|
use pocketmine\level\generator\biome\Biome;
|
||||||
use pocketmine\level\generator\biome\BiomeSelector;
|
use pocketmine\level\generator\biome\BiomeSelector;
|
||||||
use pocketmine\level\generator\GenerationChunkManager;
|
use pocketmine\level\generator\GenerationChunkManager;
|
||||||
|
use pocketmine\level\generator\GenerationManager;
|
||||||
use pocketmine\level\generator\Generator;
|
use pocketmine\level\generator\Generator;
|
||||||
use pocketmine\level\generator\noise\Perlin;
|
use pocketmine\level\generator\noise\Perlin;
|
||||||
use pocketmine\level\generator\noise\Simplex;
|
use pocketmine\level\generator\noise\Simplex;
|
||||||
use pocketmine\level\generator\normal\biome\NormalBiome;
|
use pocketmine\level\generator\normal\biome\NormalBiome;
|
||||||
use pocketmine\level\generator\object\OreType;
|
use pocketmine\level\generator\object\OreType;
|
||||||
|
use pocketmine\level\generator\populator\GroundCover;
|
||||||
use pocketmine\level\generator\populator\Ore;
|
use pocketmine\level\generator\populator\Ore;
|
||||||
use pocketmine\level\generator\populator\Populator;
|
use pocketmine\level\generator\populator\Populator;
|
||||||
use pocketmine\level\generator\populator\TallGrass;
|
use pocketmine\level\generator\populator\TallGrass;
|
||||||
@ -50,12 +53,15 @@ class Normal extends Generator{
|
|||||||
|
|
||||||
/** @var Populator[] */
|
/** @var Populator[] */
|
||||||
private $populators = [];
|
private $populators = [];
|
||||||
/** @var GenerationChunkManager */
|
/** @var ChunkManager */
|
||||||
private $level;
|
private $level;
|
||||||
/** @var Random */
|
/** @var Random */
|
||||||
private $random;
|
private $random;
|
||||||
private $waterHeight = 62;
|
private $waterHeight = 62;
|
||||||
private $bedrockDepth = 5;
|
private $bedrockDepth = 5;
|
||||||
|
|
||||||
|
/** @var Populator[] */
|
||||||
|
private $generationPopulators = [];
|
||||||
/** @var Simplex */
|
/** @var Simplex */
|
||||||
private $noiseBase;
|
private $noiseBase;
|
||||||
|
|
||||||
@ -92,7 +98,7 @@ class Normal extends Generator{
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function init(GenerationChunkManager $level, Random $random){
|
public function init(ChunkManager $level, Random $random){
|
||||||
$this->level = $level;
|
$this->level = $level;
|
||||||
$this->random = $random;
|
$this->random = $random;
|
||||||
$this->random->setSeed($this->level->getSeed());
|
$this->random->setSeed($this->level->getSeed());
|
||||||
@ -100,6 +106,9 @@ class Normal extends Generator{
|
|||||||
$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, Biome::getBiome(Biome::OCEAN));
|
||||||
|
|
||||||
|
$cover = new GroundCover();
|
||||||
|
$this->generationPopulators[] = $cover;
|
||||||
|
|
||||||
|
|
||||||
$ores = new Ore();
|
$ores = new Ore();
|
||||||
$ores->setOreTypes([
|
$ores->setOreTypes([
|
||||||
@ -113,16 +122,6 @@ class Normal extends Generator{
|
|||||||
new OreType(new Gravel(), 10, 16, 0, 128),
|
new OreType(new Gravel(), 10, 16, 0, 128),
|
||||||
]);
|
]);
|
||||||
$this->populators[] = $ores;
|
$this->populators[] = $ores;
|
||||||
|
|
||||||
$trees = new Tree();
|
|
||||||
$trees->setBaseAmount(1);
|
|
||||||
$trees->setRandomAmount(1);
|
|
||||||
$this->populators[] = $trees;
|
|
||||||
|
|
||||||
$tallGrass = new TallGrass();
|
|
||||||
$tallGrass->setBaseAmount(5);
|
|
||||||
$tallGrass->setRandomAmount(0);
|
|
||||||
$this->populators[] = $tallGrass;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generateChunk($chunkX, $chunkZ){
|
public function generateChunk($chunkX, $chunkZ){
|
||||||
@ -132,21 +131,22 @@ class Normal extends Generator{
|
|||||||
|
|
||||||
$chunk = $this->level->getChunk($chunkX, $chunkZ);
|
$chunk = $this->level->getChunk($chunkX, $chunkZ);
|
||||||
|
|
||||||
$biomeCache = [];
|
|
||||||
|
|
||||||
for($x = 0; $x < 16; ++$x){
|
for($x = 0; $x < 16; ++$x){
|
||||||
for($z = 0; $z < 16; ++$z){
|
for($z = 0; $z < 16; ++$z){
|
||||||
$minSum = 0;
|
$minSum = 0;
|
||||||
$maxSum = 0;
|
$maxSum = 0;
|
||||||
$weightSum = 0;
|
$weightSum = 0;
|
||||||
|
|
||||||
|
$biome = $this->selector->pickBiome($chunkX * 16 + $x, $chunkZ * 16 + $z);
|
||||||
|
$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));
|
||||||
|
|
||||||
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(isset($biomeCache[$index = (($chunkX * 16 + $x + $sx * 16) >> 2) . ":" . (($chunkZ * 16 + $z + $sz * 16) >> 2)])){
|
if($sx === 0 and $sz === 0){
|
||||||
$adjacent = $biomeCache[$index];
|
$adjacent = $biome;
|
||||||
}else{
|
}else{
|
||||||
$adjacent = $this->selector->pickBiome($chunkX * 16 + $x + $sx * 16, $chunkZ * 16 + $z + $sz * 16);
|
$adjacent = $this->selector->pickBiome($chunkX * 16 + $x + $sx * 16, $chunkZ * 16 + $z + $sz * 16);
|
||||||
$biomeCache[$index] = $adjacent;
|
|
||||||
}
|
}
|
||||||
/** @var NormalBiome $adjacent */
|
/** @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];
|
||||||
@ -182,14 +182,21 @@ class Normal extends Generator{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach($this->generationPopulators as $populator){
|
||||||
|
$populator->populate($this->level, $chunkX, $chunkZ, $this->random);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function populateChunk($chunkX, $chunkZ){
|
public function populateChunk($chunkX, $chunkZ){
|
||||||
$this->random->setSeed(0xdeadbeef ^ ($chunkX << 8) ^ $chunkZ ^ $this->level->getSeed());
|
$this->random->setSeed(0xdeadbeef ^ ($chunkX << 8) ^ $chunkZ ^ $this->level->getSeed());
|
||||||
foreach($this->populators as $populator){
|
foreach($this->populators as $populator){
|
||||||
$this->random->setSeed(0xdeadbeef ^ ($chunkX << 8) ^ $chunkZ ^ $this->level->getSeed());
|
|
||||||
$populator->populate($this->level, $chunkX, $chunkZ, $this->random);
|
$populator->populate($this->level, $chunkX, $chunkZ, $this->random);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$chunk = $this->level->getChunk($chunkX, $chunkZ);
|
||||||
|
$biome = Biome::getBiome($chunk->getBiomeId(7, 7));
|
||||||
|
$biome->populateChunk($this->level, $chunkX, $chunkZ, $this->random);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSpawn(){
|
public function getSpawn(){
|
||||||
|
@ -21,11 +21,12 @@
|
|||||||
|
|
||||||
namespace pocketmine\level\generator\normal\biome;
|
namespace pocketmine\level\generator\normal\biome;
|
||||||
|
|
||||||
class DesertBiome extends GrassyBiome{
|
use pocketmine\block\Block;
|
||||||
|
|
||||||
|
class DesertBiome extends SandyBiome{
|
||||||
|
|
||||||
public function __construct(){
|
public function __construct(){
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
$this->setElevation(63, 74);
|
$this->setElevation(63, 74);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,29 +25,4 @@ use pocketmine\level\generator\biome\Biome;
|
|||||||
|
|
||||||
abstract class NormalBiome extends Biome{
|
abstract class NormalBiome extends Biome{
|
||||||
|
|
||||||
private $minElevation;
|
|
||||||
private $maxElevation;
|
|
||||||
|
|
||||||
private $groundCover = [];
|
|
||||||
|
|
||||||
public function getMinElevation(){
|
|
||||||
return $this->minElevation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getMaxElevation(){
|
|
||||||
return $this->maxElevation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setElevation($min, $max){
|
|
||||||
$this->minElevation = $min;
|
|
||||||
$this->maxElevation = $max;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getGroundCover(){
|
|
||||||
return $this->groundCover;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setGroundCover(array $covers){
|
|
||||||
$this->groundCover = $covers;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ abstract class SandyBiome extends NormalBiome{
|
|||||||
|
|
||||||
public function __construct(){
|
public function __construct(){
|
||||||
$this->setGroundCover([
|
$this->setGroundCover([
|
||||||
|
Block::get(Block::SAND, 0),
|
||||||
Block::get(Block::SAND, 0),
|
Block::get(Block::SAND, 0),
|
||||||
Block::get(Block::SANDSTONE, 0),
|
Block::get(Block::SANDSTONE, 0),
|
||||||
Block::get(Block::SANDSTONE, 0),
|
Block::get(Block::SANDSTONE, 0),
|
||||||
|
58
src/pocketmine/level/generator/populator/GroundCover.php
Normal file
58
src/pocketmine/level/generator/populator/GroundCover.php
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<?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\populator;
|
||||||
|
|
||||||
|
use pocketmine\block\Block;
|
||||||
|
use pocketmine\level\ChunkManager;
|
||||||
|
use pocketmine\level\generator\biome\Biome;
|
||||||
|
use pocketmine\utils\Random;
|
||||||
|
|
||||||
|
class GroundCover extends Populator{
|
||||||
|
|
||||||
|
public function populate(ChunkManager $level, $chunkX, $chunkZ, Random $random){
|
||||||
|
$chunk = $level->getChunk($chunkX, $chunkZ);
|
||||||
|
for($x = 0; $x < 16; ++$x){
|
||||||
|
for($z = 0; $z < 16; ++$z){
|
||||||
|
$biome = Biome::getBiome($chunk->getBiomeId($x, $z));
|
||||||
|
$cover = $biome->getGroundCover();
|
||||||
|
if(count($cover) > 0){
|
||||||
|
$column = $chunk->getBlockIdColumn($x, $z);
|
||||||
|
for($y = 127; $y > 0; --$y){
|
||||||
|
if($column{$y} !== "\x00" and Block::get(ord($column{$y}))->isSolid()){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$startY = $y;
|
||||||
|
$endY = $startY - count($cover);
|
||||||
|
for($y = $startY; $y > $endY and $y >= 0; --$y){
|
||||||
|
$b = $cover[$startY - $y];
|
||||||
|
if($b->getDamage() === 0){
|
||||||
|
$chunk->setBlockId($x, $y, $z, $b->getId());
|
||||||
|
}else{
|
||||||
|
$chunk->setBlock($x, $y, $z, $b->getId(), $b->getDamage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -55,6 +55,8 @@ chunk-generation:
|
|||||||
use-async: true
|
use-async: true
|
||||||
#Max. amount of chunks to generate per tick, only for use-async: false
|
#Max. amount of chunks to generate per tick, only for use-async: false
|
||||||
per-tick: 1
|
per-tick: 1
|
||||||
|
#Max. amount of chunks to populate per tick
|
||||||
|
populations-per-tick: 1
|
||||||
|
|
||||||
chunk-gc:
|
chunk-gc:
|
||||||
period-in-ticks: 600
|
period-in-ticks: 600
|
||||||
|
Loading…
x
Reference in New Issue
Block a user