Automatic population on side loading

This commit is contained in:
Shoghi Cervantes 2014-02-14 00:19:26 +01:00
parent 5d7198396d
commit 715e51b7c5
6 changed files with 139 additions and 47 deletions

View File

@ -145,8 +145,6 @@ class PMFLevel extends PMF{
$X = $index & 0x0F; $X = $index & 0x0F;
$Z = $index >> 4; $Z = $index >> 4;
$this->chunks[$index] = false;
$this->chunkChange[$index] = false;
$bitflags = Utils::readShort($this->read(2)); $bitflags = Utils::readShort($this->read(2));
$oldPath = dirname($this->file)."/chunks/".$Z.".".$X.".pmc"; $oldPath = dirname($this->file)."/chunks/".$Z.".".$X.".pmc";
$chunkOld = gzopen($oldPath, "rb"); $chunkOld = gzopen($oldPath, "rb");
@ -186,15 +184,36 @@ class PMFLevel extends PMF{
if(!file_exists(dirname($path))){ if(!file_exists(dirname($path))){
@mkdir(dirname($path), 0755); @mkdir(dirname($path), 0755);
} }
++$this->isGenerating;
$this->initCleanChunk($X, $Z); $this->initCleanChunk($X, $Z);
$ret = $this->level->generateChunk($X, $Z); $ret = $this->level->generateChunk($X, $Z);
$ret = $ret and $this->level->populateChunk($X, $Z);
$this->saveChunk($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; 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){ public function loadChunk($X, $Z){
$X = (int) $X; $X = (int) $X;
$Z = (int) $Z; $Z = (int) $Z;
@ -206,16 +225,13 @@ class PMFLevel extends PMF{
if(!file_exists($path)){ if(!file_exists($path)){
if($this->isGenerating > 0){ if($this->isGenerating > 0){
$this->level->generateChunk($X, $Z); $this->level->generateChunk($X, $Z);
$this->saveChunk($X, $Z);
}elseif($this->generateChunk($X, $Z) === false){ }elseif($this->generateChunk($X, $Z) === false){
return false; return false;
} }
} }
if($this->isGenerating === 0 and !$this->isPopulated($X, $Z)){ if($this->isGenerating === 0 and !$this->isPopulated($X, $Z)){
++$this->isGenerating; $this->populateChunk($X, $Z);
$this->level->populateChunk($X, $Z);
--$this->isGenerating;
} }
$chunk = @gzopen($path, "rb"); $chunk = @gzopen($path, "rb");
@ -262,15 +278,15 @@ class PMFLevel extends PMF{
public function isChunkLoaded($X, $Z){ public function isChunkLoaded($X, $Z){
$index = self::getIndex($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 false;
} }
return true; return true;
} }
protected function isMiniChunkEmpty($X, $Z, $Y){ public function isMiniChunkEmpty($X, $Z, $Y){
$index = self::getIndex($X, $Z); $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){ if(substr_count($this->chunks[$index][$Y], "\x00") < 8192){
return false; return false;
} }
@ -314,7 +330,17 @@ class PMFLevel extends PMF{
6 => false, 6 => false,
7 => 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( $this->chunkInfo[$index] = array(
0 => 0, 0 => 0,
1 => 0, 1 => 0,
@ -347,7 +373,7 @@ class PMFLevel extends PMF{
$Z = $z >> 4; $Z = $z >> 4;
$Y = $y >> 4; $Y = $y >> 4;
$index = self::getIndex($X, $Z); $index = self::getIndex($X, $Z);
if(!isset($this->chunks[$index]) or $this->chunks[$index] === false){ if(!isset($this->chunks[$index])){
return 0; return 0;
} }
$aX = $x - ($X << 4); $aX = $x - ($X << 4);
@ -366,7 +392,7 @@ class PMFLevel extends PMF{
$Y = $y >> 4; $Y = $y >> 4;
$block &= 0xFF; $block &= 0xFF;
$index = self::getIndex($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 false;
} }
$aX = $x - ($X << 4); $aX = $x - ($X << 4);
@ -390,7 +416,7 @@ class PMFLevel extends PMF{
$Z = $z >> 4; $Z = $z >> 4;
$Y = $y >> 4; $Y = $y >> 4;
$index = self::getIndex($X, $Z); $index = self::getIndex($X, $Z);
if(!isset($this->chunks[$index]) or $this->chunks[$index] === false){ if(!isset($this->chunks[$index])){
return 0; return 0;
} }
$aX = $x - ($X << 4); $aX = $x - ($X << 4);
@ -414,7 +440,7 @@ class PMFLevel extends PMF{
$Y = $y >> 4; $Y = $y >> 4;
$damage &= 0x0F; $damage &= 0x0F;
$index = self::getIndex($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 false;
} }
$aX = $x - ($X << 4); $aX = $x - ($X << 4);
@ -449,7 +475,7 @@ class PMFLevel extends PMF{
return array(AIR, 0); return array(AIR, 0);
} }
$index = self::getIndex($X, $Z); $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){ if($this->loadChunk($X, $Z) === false){
return array(AIR, 0); return array(AIR, 0);
} }
@ -479,7 +505,7 @@ class PMFLevel extends PMF{
$block &= 0xFF; $block &= 0xFF;
$meta &= 0x0F; $meta &= 0x0F;
$index = self::getIndex($X, $Z); $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){ if($this->loadChunk($X, $Z) === false){
return false; return false;
} }
@ -552,7 +578,7 @@ class PMFLevel extends PMF{
} }
$chunk = @gzopen($path, "wb".PMFLevel::DEFLATE_LEVEL); $chunk = @gzopen($path, "wb".PMFLevel::DEFLATE_LEVEL);
gzwrite($chunk, chr($bitmap)); 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){ for($Y = 0; $Y < 8; ++$Y){
$t = 1 << $Y; $t = 1 << $Y;
if(($bitmap & $t) === $t){ if(($bitmap & $t) === $t){
@ -589,6 +615,10 @@ class PMFLevel extends PMF{
return ($this->chunkInfo[$index][1] & 0b00000000000000000000000000000001) > 0; return ($this->chunkInfo[$index][1] & 0b00000000000000000000000000000001) > 0;
} }
public function isGenerated($X, $Z){
return file_exists($this->getChunkPath($X, $Z));
}
public function doSaveRound(){ public function doSaveRound(){
foreach($this->chunks as $index => $chunk){ foreach($this->chunks as $index => $chunk){
self::getXZ($index, $X, $Z); self::getXZ($index, $X, $Z);

View File

@ -148,11 +148,14 @@ class Level{
} }
public function generateChunk($X, $Z){ public function generateChunk($X, $Z){
++$this->level->isGenerating;
$this->generator->generateChunk($X, $Z); $this->generator->generateChunk($X, $Z);
--$this->level->isGenerating;
} }
public function populateChunk($X, $Z){ public function populateChunk($X, $Z){
$this->generator->populateChunk($X, $Z); $this->generator->populateChunk($X, $Z);
$this->level->setPopulated($X, $Z);
} }
public function __destruct(){ public function __destruct(){

View File

@ -65,9 +65,15 @@ class NormalGenerator implements LevelGenerator{
new OreType(new GravelBlock(), 10, 16, 0, 128), new OreType(new GravelBlock(), 10, 16, 0, 128),
)); ));
$this->populators[] = $ores; $this->populators[] = $ores;
$trees = new TreePopulator();
$trees->setBaseAmount(3);
$trees->setRandomAmount(0);
$this->populators[] = $trees;
$tallGrass = new TallGrassPopulator(); $tallGrass = new TallGrassPopulator();
$tallGrass->setBaseAmount(5); $tallGrass->setBaseAmount(5);
$tallGrass->setRandomAmount(1); $tallGrass->setRandomAmount(0);
$this->populators[] = $tallGrass; $this->populators[] = $tallGrass;
} }
@ -120,7 +126,7 @@ class NormalGenerator implements LevelGenerator{
}elseif($diff === 0){ }elseif($diff === 0){
if($patchesSmall[$i] > 0.3){ if($patchesSmall[$i] > 0.3){
$chunk .= "\x0d"; //gravel $chunk .= "\x0d"; //gravel
}elseif($patches[$i] < -0.45){ }elseif($patchesSmall[$i] < -0.45){
$chunk .= "\x0c"; //sand $chunk .= "\x0c"; //sand
}else{ }else{
$chunk .= "\x03"; //dirt $chunk .= "\x03"; //dirt
@ -149,16 +155,11 @@ 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){ foreach($this->populators as $populator){
$this->random->setSeed(0xdeadbeef ^ ($chunkX << 8) ^ $chunkZ ^ $this->level->getSeed()); $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);
} }
$this->level->level->setPopulated($chunkX, $chunkZ);
}
public function populateLevel(){
} }
public function getSpawn(){ public function getSpawn(){

View File

@ -130,11 +130,10 @@ class SuperflatGenerator implements LevelGenerator{
} }
public function populateChunk($chunkX, $chunkZ){ public function populateChunk($chunkX, $chunkZ){
foreach($this->populators as $populator){
$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){
$populator->populate($this->level, $chunkX, $chunkZ, $this->random); $populator->populate($this->level, $chunkX, $chunkZ, $this->random);
} }
$this->level->level->setPopulated($chunkX, $chunkZ);
} }
public function populateLevel(){ public function populateLevel(){

View File

@ -46,25 +46,17 @@ class WorldGenerator{
} }
public function generate(){ public function generate(){
++$this->level->level->isGenerating;
$this->generator->init($this->level, $this->random); $this->generator->init($this->level, $this->random);
//Generate 4 chunks for spawning players //Generate 4 chunks for spawning players
for($Z = 7; $Z <= 8; ++$Z){ for($Z = 7; $Z <= 8; ++$Z){
for($X = 7; $X <= 8; ++$X){ for($X = 7; $X <= 8; ++$X){
$this->generator->generateChunk($X, $Z); $this->level->level->generateChunk($X, $Z);
}
}
for($Z = 7; $Z <= 8; ++$Z){
for($X = 7; $X <= 8; ++$X){
$this->generator->populateChunk($X, $Z);
} }
} }
$this->level->setSpawn($this->generator->getSpawn()); $this->level->setSpawn($this->generator->getSpawn());
$this->level->save(true, true); $this->level->save(true, true);
--$this->level->level->isGenerating;
} }
public function close(){ public function close(){

View File

@ -0,0 +1,67 @@
<?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/
*
*
*/
class TreePopulator extends Populator{
private $level;
private $randomAmount;
private $baseAmount;
public function setRandomAmount($amount){
$this->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;
}
}