mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-17 03:08:58 +00:00
Automatic population on side loading
This commit is contained in:
parent
5d7198396d
commit
715e51b7c5
@ -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);
|
||||
|
@ -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(){
|
||||
|
@ -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(){
|
||||
|
@ -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(){
|
||||
|
@ -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(){
|
||||
|
67
src/world/generator/populator/TreePopulator.php
Normal file
67
src/world/generator/populator/TreePopulator.php
Normal 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;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user