diff --git a/src/pmf/PMFLevel.php b/src/pmf/PMFLevel.php index 4f685176a..17a3e233d 100644 --- a/src/pmf/PMFLevel.php +++ b/src/pmf/PMFLevel.php @@ -144,9 +144,7 @@ class PMFLevel extends PMF{ for($index = 0; $index < 256; ++$index){ $X = $index & 0x0F; $Z = $index >> 4; - - $this->chunks[$index] = false; - $this->chunkChange[$index] = false; + $bitflags = Utils::readShort($this->read(2)); $oldPath = dirname($this->file)."/chunks/".$Z.".".$X.".pmc"; $chunkOld = gzopen($oldPath, "rb"); @@ -186,15 +184,36 @@ class PMFLevel extends PMF{ if(!file_exists(dirname($path))){ @mkdir(dirname($path), 0755); } - ++$this->isGenerating; $this->initCleanChunk($X, $Z); - $ret = $this->level->generateChunk($X, $Z); - $ret = $ret and $this->level->populateChunk($X, $Z); + $ret = $this->level->generateChunk($X, $Z); $this->saveChunk($X, $Z); - --$this->isGenerating; + $this->populateChunk($X - 1, $Z); + $this->populateChunk($X + 1, $Z); + $this->populateChunk($X, $Z - 1); + $this->populateChunk($X, $Z + 1); + $this->populateChunk($X + 1, $Z + 1); + $this->populateChunk($X + 1, $Z - 1); + $this->populateChunk($X - 1, $Z - 1); + $this->populateChunk($X - 1, $Z + 1); return $ret; } + public function populateChunk($X, $Z){ + if($this->isGenerating === 0 and + !$this->isPopulated($X, $Z) and + $this->isGenerated($X - 1, $Z) and + $this->isGenerated($X, $Z - 1) and + $this->isGenerated($X + 1, $Z) and + $this->isGenerated($X, $Z + 1) and + $this->isGenerated($X + 1, $Z + 1) and + $this->isGenerated($X - 1, $Z - 1) and + $this->isGenerated($X + 1, $Z - 1) and + $this->isGenerated($X - 1, $Z + 1)){ + $this->level->populateChunk($X, $Z); + $this->saveChunk($X, $Z); + } + } + public function loadChunk($X, $Z){ $X = (int) $X; $Z = (int) $Z; @@ -206,16 +225,13 @@ class PMFLevel extends PMF{ if(!file_exists($path)){ if($this->isGenerating > 0){ $this->level->generateChunk($X, $Z); - $this->saveChunk($X, $Z); }elseif($this->generateChunk($X, $Z) === false){ return false; } } if($this->isGenerating === 0 and !$this->isPopulated($X, $Z)){ - ++$this->isGenerating; - $this->level->populateChunk($X, $Z); - --$this->isGenerating; + $this->populateChunk($X, $Z); } $chunk = @gzopen($path, "rb"); @@ -262,15 +278,15 @@ class PMFLevel extends PMF{ public function isChunkLoaded($X, $Z){ $index = self::getIndex($X, $Z); - if(!isset($this->chunks[$index]) or $this->chunks[$index] === false){ + if(!isset($this->chunks[$index])){ return false; } return true; } - protected function isMiniChunkEmpty($X, $Z, $Y){ + public function isMiniChunkEmpty($X, $Z, $Y){ $index = self::getIndex($X, $Z); - if($this->chunks[$index][$Y] !== false){ + if(isset($this->chunks[$index]) and $this->chunks[$index][$Y] !== false){ if(substr_count($this->chunks[$index][$Y], "\x00") < 8192){ return false; } @@ -314,7 +330,17 @@ class PMFLevel extends PMF{ 6 => false, 7 => false, ); - $this->chunkChange[$index] = array(-1 => false); + $this->chunkChange[$index] = array( + -1 => true, + 0 => 8192, + 1 => 8192, + 2 => 8192, + 3 => 8192, + 4 => 8192, + 5 => 8192, + 6 => 8192, + 7 => 8192, + ); $this->chunkInfo[$index] = array( 0 => 0, 1 => 0, @@ -347,7 +373,7 @@ class PMFLevel extends PMF{ $Z = $z >> 4; $Y = $y >> 4; $index = self::getIndex($X, $Z); - if(!isset($this->chunks[$index]) or $this->chunks[$index] === false){ + if(!isset($this->chunks[$index])){ return 0; } $aX = $x - ($X << 4); @@ -366,7 +392,7 @@ class PMFLevel extends PMF{ $Y = $y >> 4; $block &= 0xFF; $index = self::getIndex($X, $Z); - if(!isset($this->chunks[$index]) or $this->chunks[$index] === false){ + if(!isset($this->chunks[$index])){ return false; } $aX = $x - ($X << 4); @@ -390,7 +416,7 @@ class PMFLevel extends PMF{ $Z = $z >> 4; $Y = $y >> 4; $index = self::getIndex($X, $Z); - if(!isset($this->chunks[$index]) or $this->chunks[$index] === false){ + if(!isset($this->chunks[$index])){ return 0; } $aX = $x - ($X << 4); @@ -414,7 +440,7 @@ class PMFLevel extends PMF{ $Y = $y >> 4; $damage &= 0x0F; $index = self::getIndex($X, $Z); - if(!isset($this->chunks[$index]) or $this->chunks[$index] === false){ + if(!isset($this->chunks[$index])){ return false; } $aX = $x - ($X << 4); @@ -449,7 +475,7 @@ class PMFLevel extends PMF{ return array(AIR, 0); } $index = self::getIndex($X, $Z); - if(!isset($this->chunks[$index]) or $this->chunks[$index] === false){ + if(!isset($this->chunks[$index])){ if($this->loadChunk($X, $Z) === false){ return array(AIR, 0); } @@ -479,7 +505,7 @@ class PMFLevel extends PMF{ $block &= 0xFF; $meta &= 0x0F; $index = self::getIndex($X, $Z); - if(!isset($this->chunks[$index]) or $this->chunks[$index] === false){ + if(!isset($this->chunks[$index])){ if($this->loadChunk($X, $Z) === false){ return false; } @@ -552,7 +578,7 @@ class PMFLevel extends PMF{ } $chunk = @gzopen($path, "wb".PMFLevel::DEFLATE_LEVEL); gzwrite($chunk, chr($bitmap)); - gzwrite($chunk, Utils::writeInt($this->chunkInfo[$index][0])); + gzwrite($chunk, Utils::writeInt($this->chunkInfo[$index][1])); for($Y = 0; $Y < 8; ++$Y){ $t = 1 << $Y; if(($bitmap & $t) === $t){ @@ -589,6 +615,10 @@ class PMFLevel extends PMF{ return ($this->chunkInfo[$index][1] & 0b00000000000000000000000000000001) > 0; } + public function isGenerated($X, $Z){ + return file_exists($this->getChunkPath($X, $Z)); + } + public function doSaveRound(){ foreach($this->chunks as $index => $chunk){ self::getXZ($index, $X, $Z); diff --git a/src/world/Level.php b/src/world/Level.php index 05e9ce4c0..d63d2c54e 100644 --- a/src/world/Level.php +++ b/src/world/Level.php @@ -148,11 +148,14 @@ class Level{ } public function generateChunk($X, $Z){ + ++$this->level->isGenerating; $this->generator->generateChunk($X, $Z); + --$this->level->isGenerating; } public function populateChunk($X, $Z){ - $this->generator->populateChunk($X, $Z); + $this->generator->populateChunk($X, $Z); + $this->level->setPopulated($X, $Z); } public function __destruct(){ diff --git a/src/world/generator/NormalGenerator.php b/src/world/generator/NormalGenerator.php index a0cd73e6b..bf24d7649 100644 --- a/src/world/generator/NormalGenerator.php +++ b/src/world/generator/NormalGenerator.php @@ -65,10 +65,16 @@ class NormalGenerator implements LevelGenerator{ new OreType(new GravelBlock(), 10, 16, 0, 128), )); $this->populators[] = $ores; + + $trees = new TreePopulator(); + $trees->setBaseAmount(3); + $trees->setRandomAmount(0); + $this->populators[] = $trees; + $tallGrass = new TallGrassPopulator(); $tallGrass->setBaseAmount(5); - $tallGrass->setRandomAmount(1); - $this->populators[] = $tallGrass; + $tallGrass->setRandomAmount(0); + $this->populators[] = $tallGrass; } public function generateChunk($chunkX, $chunkZ){ @@ -89,11 +95,11 @@ class NormalGenerator implements LevelGenerator{ } } } - + for($chunkY = 0; $chunkY < 8; ++$chunkY){ $chunk = ""; $startY = $chunkY << 4; - $endY = $startY + 16; + $endY = $startY + 16; for($z = 0; $z < 16; ++$z){ for($x = 0; $x < 16; ++$x){ $i = ($z << 4) + $x; @@ -120,7 +126,7 @@ class NormalGenerator implements LevelGenerator{ }elseif($diff === 0){ if($patchesSmall[$i] > 0.3){ $chunk .= "\x0d"; //gravel - }elseif($patches[$i] < -0.45){ + }elseif($patchesSmall[$i] < -0.45){ $chunk .= "\x0c"; //sand }else{ $chunk .= "\x03"; //dirt @@ -148,17 +154,12 @@ class NormalGenerator implements LevelGenerator{ } - public function populateChunk($chunkX, $chunkZ){ + public function populateChunk($chunkX, $chunkZ){ + $this->random->setSeed(0xdeadbeef ^ ($chunkX << 8) ^ $chunkZ ^ $this->level->getSeed()); foreach($this->populators as $populator){ $this->random->setSeed(0xdeadbeef ^ ($chunkX << 8) ^ $chunkZ ^ $this->level->getSeed()); $populator->populate($this->level, $chunkX, $chunkZ, $this->random); } - - $this->level->level->setPopulated($chunkX, $chunkZ); - } - - public function populateLevel(){ - } public function getSpawn(){ diff --git a/src/world/generator/SuperflatGenerator.php b/src/world/generator/SuperflatGenerator.php index 95162d42b..d57874456 100644 --- a/src/world/generator/SuperflatGenerator.php +++ b/src/world/generator/SuperflatGenerator.php @@ -129,12 +129,11 @@ class SuperflatGenerator implements LevelGenerator{ } } - public function populateChunk($chunkX, $chunkZ){ + public function populateChunk($chunkX, $chunkZ){ + $this->random->setSeed(0xdeadbeef ^ ($chunkX << 8) ^ $chunkZ ^ $this->level->getSeed()); foreach($this->populators as $populator){ - $this->random->setSeed(0xdeadbeef ^ ($chunkX << 8) ^ $chunkZ ^ $this->level->getSeed()); $populator->populate($this->level, $chunkX, $chunkZ, $this->random); } - $this->level->level->setPopulated($chunkX, $chunkZ); } public function populateLevel(){ diff --git a/src/world/generator/WorldGenerator.php b/src/world/generator/WorldGenerator.php index d5a6f174a..aac73c0ce 100644 --- a/src/world/generator/WorldGenerator.php +++ b/src/world/generator/WorldGenerator.php @@ -46,25 +46,17 @@ class WorldGenerator{ } public function generate(){ - ++$this->level->level->isGenerating; $this->generator->init($this->level, $this->random); //Generate 4 chunks for spawning players for($Z = 7; $Z <= 8; ++$Z){ for($X = 7; $X <= 8; ++$X){ - $this->generator->generateChunk($X, $Z); - } - } - - for($Z = 7; $Z <= 8; ++$Z){ - for($X = 7; $X <= 8; ++$X){ - $this->generator->populateChunk($X, $Z); + $this->level->level->generateChunk($X, $Z); } } $this->level->setSpawn($this->generator->getSpawn()); $this->level->save(true, true); - --$this->level->level->isGenerating; } public function close(){ diff --git a/src/world/generator/populator/TreePopulator.php b/src/world/generator/populator/TreePopulator.php new file mode 100644 index 000000000..635b813eb --- /dev/null +++ b/src/world/generator/populator/TreePopulator.php @@ -0,0 +1,67 @@ +randomAmount = $amount; + } + + public function setBaseAmount($amount){ + $this->baseAmount = $amount; + } + + public function populate(Level $level, $chunkX, $chunkZ, Random $random){ + $this->level = $level; + $amount = $random->nextRange(0, $this->randomAmount + 1) + $this->baseAmount; + for($i = 0; $i < $amount; ++$i){ + $x = $random->nextRange($chunkX << 4, ($chunkX << 4) + 15); + $z = $random->nextRange($chunkZ << 4, ($chunkZ << 4) + 15); + $y = $this->getHighestWorkableBlock($x, $z); + if($y === -1){ + continue; + } + if($random->nextFloat() > 0.75){ + $meta = 1; + }else{ + $meta = 0; + } + TreeObject::growTree($this->level, new Vector3($x, $y, $z), $random, $meta); + } + } + + private function getHighestWorkableBlock($x, $z){ + for($y = 128; $y > 0; --$y){ + $b = $this->level->getBlockRaw(new Vector3($x, $y, $z)); + if($b->getID() !== DIRT and $b->getID() !== GRASS){ + if(--$y <= 0){ + return -1; + } + }else{ + break; + } + } + return ++$y; + } +} \ No newline at end of file