mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-07-01 23:59:53 +00:00
Faster level generator
This commit is contained in:
parent
4ccaccc126
commit
b3c51c6d2e
@ -23,13 +23,9 @@ class Vector2{
|
||||
public $x, $y;
|
||||
|
||||
public function __construct($x = 0, $y = 0){
|
||||
if(($x instanceof Vector2) === true){
|
||||
$this->__construct($x->x, $x->y);
|
||||
}else{
|
||||
$this->x = $x;
|
||||
$this->y = $y;
|
||||
}
|
||||
}
|
||||
|
||||
public function getX(){
|
||||
return $this->x;
|
||||
|
@ -23,14 +23,10 @@ class Vector3{
|
||||
public $x, $y, $z;
|
||||
|
||||
public function __construct($x = 0, $y = 0, $z = 0){
|
||||
if(($x instanceof Vector3) === true){
|
||||
$this->__construct($x->x, $x->y, $x->z);
|
||||
}else{
|
||||
$this->x = $x;
|
||||
$this->y = $y;
|
||||
$this->z = $z;
|
||||
}
|
||||
}
|
||||
|
||||
public function getX(){
|
||||
return $this->x;
|
||||
|
@ -305,6 +305,9 @@ class PMFLevel extends PMF{
|
||||
}
|
||||
|
||||
public function getBlockID($x, $y, $z){
|
||||
if($y > 127 or $y < 0 or $x < 0 or $z < 0 or $x > 255 or $z > 255){
|
||||
return 0;
|
||||
}
|
||||
$X = $x >> 4;
|
||||
$Z = $z >> 4;
|
||||
$Y = $y >> 4;
|
||||
@ -312,11 +315,16 @@ class PMFLevel extends PMF{
|
||||
$aX = $x - ($X << 4);
|
||||
$aZ = $z - ($Z << 4);
|
||||
$aY = $y - ($Y << 4);
|
||||
$b = ord($this->chunks[$index][$Y]{(int) ($aY + ($aX << 5) + ($aZ << 9))});
|
||||
$b = ord($this->chunks[$index]
|
||||
[$Y]
|
||||
{(int) ($aY + ($aX << 5) + ($aZ << 9))});
|
||||
return $b;
|
||||
}
|
||||
|
||||
public function setBlockID($x, $y, $z, $block){
|
||||
if($y > 127 or $y < 0 or $x < 0 or $z < 0 or $x > 255 or $z > 255){
|
||||
return false;
|
||||
}
|
||||
$X = $x >> 4;
|
||||
$Z = $z >> 4;
|
||||
$Y = $y >> 4;
|
||||
|
@ -22,38 +22,54 @@
|
||||
|
||||
//Unsecure, not used for "Real Randomness"
|
||||
class Random{
|
||||
private $random;
|
||||
private $x, $y, $z, $w;
|
||||
public function __construct($seed = false){
|
||||
$this->random = new twister(0);
|
||||
$this->setSeed($seed);
|
||||
}
|
||||
|
||||
public function setSeed($seed = false){
|
||||
$this->random->init_with_integer($seed !== false ? (int) $seed:Utils::readInt(Utils::getRandomBytes(4, false)));
|
||||
$seed = $seed !== false ? Utils::writeInt((int) $seed):Utils::getRandomBytes(4, false);
|
||||
$state = array();
|
||||
for($i = 0; $i < 256; ++$i){
|
||||
$state[] = $i;
|
||||
}
|
||||
for($i = $j = 0; $i < 256; ++$i){
|
||||
$j = ($j + ord($seed{$i & 0x03}) + $state[$i]) & 0xFF;
|
||||
$state[$i] ^= $state[$j];
|
||||
$state[$j] ^= $state[$i];
|
||||
$state[$i] ^= $state[$j];
|
||||
}
|
||||
$this->state = $state;
|
||||
$this->i = $this->j = 0;
|
||||
}
|
||||
|
||||
public function nextInt(){
|
||||
return $this->random->int32();
|
||||
return Utils::readInt($this->nextBytes(4)) & 0x7FFFFFFF;
|
||||
}
|
||||
|
||||
public function nextFloat(){
|
||||
return $this->random->real_closed();
|
||||
return $this->nextInt() / 0x7FFFFFFF;
|
||||
}
|
||||
|
||||
public function nextBytes($byteCount){
|
||||
$bytes = "";
|
||||
for($i = 0; $i < $byteCount; ++$i){
|
||||
$bytes .= chr($this->random->rangeint(0, 0xFF));
|
||||
$this->i = ($this->i + 1) & 0xFF;
|
||||
$this->j = ($this->j + $this->state[$this->i]) & 0xFF;
|
||||
$this->state[$this->i] ^= $this->state[$this->j];
|
||||
$this->state[$this->j] ^= $this->state[$this->i];
|
||||
$this->state[$this->i] ^= $this->state[$this->j];
|
||||
$bytes .= chr($this->state[($this->state[$this->i] + $this->state[$this->j]) & 0xFF]);
|
||||
}
|
||||
return $bytes;
|
||||
}
|
||||
|
||||
public function nextBoolean(){
|
||||
return $this->random->rangeint(0, 1) === 1;
|
||||
return ($this->nextBytes(1) & 0x01) == 0;
|
||||
}
|
||||
|
||||
public function nextRange($start = 0, $end = PHP_INT_MAX){
|
||||
return $this->random->rangeint($start, $end);
|
||||
return $start + ($this->nextInt() % ($end + 1 - $start));
|
||||
}
|
||||
|
||||
}
|
@ -127,7 +127,7 @@ class SuperflatGenerator implements LevelGenerator{
|
||||
|
||||
public function populateChunk($chunkX, $chunkZ){
|
||||
foreach($this->populators as $populator){
|
||||
$this->random->setSeed((int) ($chunkX * 0xdead + $chunkZ * 0xbeef));
|
||||
$this->random->setSeed((int) ($chunkX * 0xdead + $chunkZ * 0xbeef) ^ $this->level->getSeed());
|
||||
$populator->populate($this->level, $chunkX, $chunkZ, $this->random);
|
||||
}
|
||||
}
|
||||
@ -167,17 +167,17 @@ class SuperflatGenerator implements LevelGenerator{
|
||||
$grasscount = intval($this->options["spawn"]["grasscount"]);
|
||||
}
|
||||
for($t = 0; $t < $treecount; ++$t){
|
||||
$centerX = $this->random->nextRange(0, 256);
|
||||
$centerZ = $this->random->nextRange(0, 256);
|
||||
$down = $this->level->getBlock(new Vector3($centerX, $this->floorLevel - 1, $centerZ))->getID();
|
||||
$centerX = $this->random->nextRange(0, 255);
|
||||
$centerZ = $this->random->nextRange(0, 255);
|
||||
$down = $this->level->level->getBlockID($centerX, $this->floorLevel - 1, $centerZ);
|
||||
if($down === DIRT or $down === GRASS or $down === FARMLAND){
|
||||
TreeObject::growTree($this->level, new Vector3($centerX, $this->floorLevel, $centerZ), $this->random, $this->random->nextRange(0,3));
|
||||
}
|
||||
}
|
||||
for($t = 0; $t < $grasscount; ++$t){
|
||||
$centerX = $this->random->nextRange(0, 256);
|
||||
$centerZ = $this->random->nextRange(0, 256);
|
||||
$down = $this->level->getBlock(new Vector3($centerX, $this->floorLevel - 1, $centerZ))->getID();
|
||||
$centerX = $this->random->nextRange(0, 255);
|
||||
$centerZ = $this->random->nextRange(0, 255);
|
||||
$down = $this->level->level->getBlockID($centerX, $this->floorLevel - 1, $centerZ);
|
||||
if($down === GRASS){
|
||||
TallGrassObject::growGrass($this->level, new Vector3($centerX, $this->floorLevel - 1, $centerZ), $this->random, $this->random->nextRange(8, 40));
|
||||
}
|
||||
|
@ -32,13 +32,13 @@ class OreObject{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function canPlaceObject(Level $level, Vector3 $pos){
|
||||
return ($level->getBlock($pos)->getID() !== AIR);
|
||||
public function canPlaceObject(Level $level, $x, $y, $z){
|
||||
return ($level->level->getBlockID($x, $y, $z) != AIR);
|
||||
}
|
||||
|
||||
public function placeObject(Level $level, Vector3 $pos){
|
||||
$clusterSize = (int) $this->type->clusterSize;
|
||||
$angle = $this->random->nextFloat() * pi();
|
||||
$angle = $this->random->nextFloat() * M_PI;
|
||||
$offset = VectorMath::getDirection2D($angle)->multiply($clusterSize)->divide(8);
|
||||
$x1 = $pos->x + 8 + $offset->x;
|
||||
$x2 = $pos->x + 8 - $offset->x;
|
||||
@ -50,7 +50,7 @@ class OreObject{
|
||||
$seedX = $x1 + ($x2 - $x1) * $count / $clusterSize;
|
||||
$seedY = $y1 + ($y2 - $y1) * $count / $clusterSize;
|
||||
$seedZ = $z1 + ($z2 - $z1) * $count / $clusterSize;
|
||||
$size = ((sin($count * (pi() / $clusterSize)) + 1) * $this->random->nextFloat() * $clusterSize / 16 + 1) / 2;
|
||||
$size = ((sin($count * (M_PI / $clusterSize)) + 1) * $this->random->nextFloat() * $clusterSize / 16 + 1) / 2;
|
||||
|
||||
$startX = (int) ($seedX - $size);
|
||||
$startY = (int) ($seedY - $size);
|
||||
@ -67,9 +67,8 @@ class OreObject{
|
||||
if($y > 0 and ($sizeX + $sizeY) < 1){
|
||||
for($z = $startZ; $z <= $endZ; ++$z){
|
||||
$sizeZ = pow(($z + 0.5 - $seedZ) / $size, 2);
|
||||
$v = new Vector3($x, $y, $z);
|
||||
if(($sizeX + $sizeY + $sizeZ) < 1 and $level->getBlock($v)->getID() === STONE){
|
||||
$level->setBlockRaw($v, $this->type->material);
|
||||
if(($sizeX + $sizeY + $sizeZ) < 1 and $level->level->getBlockID($x, $y, $z) === STONE){
|
||||
$level->setBlockRaw(new Vector3($x, $y, $z), $this->type->material);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,23 +23,21 @@
|
||||
class TallGrassObject{
|
||||
public static function growGrass(Level $level, Vector3 $pos, Random $random, $count = 15){
|
||||
$arr = array(
|
||||
array(DANDELION, 0),
|
||||
array(CYAN_FLOWER, 0),
|
||||
array(TALL_GRASS, 1),
|
||||
array(TALL_GRASS, 1),
|
||||
array(TALL_GRASS, 1),
|
||||
array(TALL_GRASS, 1),
|
||||
array(AIR, 0),
|
||||
BlockAPI::get(DANDELION, 0),
|
||||
BlockAPI::get(CYAN_FLOWER, 0),
|
||||
BlockAPI::get(TALL_GRASS, 1),
|
||||
BlockAPI::get(TALL_GRASS, 1),
|
||||
BlockAPI::get(TALL_GRASS, 1),
|
||||
BlockAPI::get(TALL_GRASS, 1)
|
||||
);
|
||||
$radius = ceil(sqrt($count) / 2);
|
||||
$radius = 10;
|
||||
$arrC = count($arr) - 1;
|
||||
for($c = 0; $c < $count; ++$c){
|
||||
$x = $random->nextRange($pos->x - $radius, $pos->x + $radius);
|
||||
$z = $random->nextRange($pos->z - $radius, $pos->z + $radius);
|
||||
$b = $level->getBlock(new Vector3($x, $pos->y + 1, $z));
|
||||
$d = $level->getBlock(new Vector3($x, $pos->y, $z));
|
||||
if($b->getID() === AIR and $d->getID() === GRASS){
|
||||
$t = $arr[$random->nextRange(0, count($arr) - 1)];
|
||||
$level->setBlockRaw($b, BlockAPI::get($t[0], $t[1]));
|
||||
if($level->level->getBlockID($x, $pos->y + 1, $z) === AIR and $level->level->getBlockID($x, $pos->y, $z) === GRASS){
|
||||
$t = $arr[$random->nextRange(0, $arrC)];
|
||||
$level->setBlockRaw(new Vector3($x, $pos->y + 1, $z), $t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,8 +38,7 @@ class PineTreeObject extends TreeObject{
|
||||
}
|
||||
for($xx = -$checkRadius; $xx < ($checkRadius + 1); ++$xx){
|
||||
for($zz = -$checkRadius; $zz < ($checkRadius + 1); ++$zz){
|
||||
$block = $level->getBlock(new Vector3($pos->x + $xx, $pos->y + $yy, $pos->z + $zz));
|
||||
if(!isset($this->overridable[$block->getID()])){
|
||||
if(!isset($this->overridable[$level->level->getBlockID($pos->x + $xx, $pos->y + $yy, $pos->z + $zz)])){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -41,8 +41,7 @@ class SmallTreeObject extends TreeObject{
|
||||
}
|
||||
for($xx = -$radiusToCheck; $xx < ($radiusToCheck + 1); ++$xx){
|
||||
for($zz = -$radiusToCheck; $zz < ($radiusToCheck + 1); ++$zz){
|
||||
$block = $level->getBlock(new Vector3($pos->x + $xx, $pos->y + $yy, $pos->z + $zz));
|
||||
if(!isset($this->overridable[$block->getID()])){
|
||||
if(!isset($this->overridable[$level->level->getBlockID($pos->x + $xx, $pos->y + $yy, $pos->z + $zz)])){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -38,8 +38,7 @@ class SpruceTreeObject extends TreeObject{
|
||||
}
|
||||
for($xx = -$checkRadius; $xx < ($checkRadius + 1); ++$xx){
|
||||
for($zz = -$checkRadius; $zz < ($checkRadius + 1); ++$zz){
|
||||
$block = $level->getBlock(new Vector3($pos->x + $xx, $pos->y + $yy, $pos->z + $zz));
|
||||
if(!isset($this->overridable[$block->getID()])){
|
||||
if(!isset($this->overridable[$level->level->getBlockID($pos->x + $xx, $pos->y + $yy, $pos->z + $zz)])){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -25,13 +25,11 @@ class OrePopulator extends Populator{
|
||||
foreach($this->oreTypes as $type){
|
||||
$ore = new OreObject($random, $type);
|
||||
for($i = 0; $i < $ore->type->clusterCount; ++$i){
|
||||
$v = new Vector3(
|
||||
$random->nextRange($chunkX << 4, ($chunkX << 4) + 16),
|
||||
$random->nextRange($ore->type->minHeight, $ore->type->maxHeight),
|
||||
$random->nextRange($chunkZ << 4, ($chunkZ << 4) + 16)
|
||||
);
|
||||
if($ore->canPlaceObject($level, $v)){
|
||||
$ore->placeObject($level, $v);
|
||||
$x = $random->nextRange($chunkX << 4, ($chunkX << 4) + 16);
|
||||
$y = $random->nextRange($ore->type->minHeight, $ore->type->maxHeight);
|
||||
$z = $random->nextRange($chunkZ << 4, ($chunkZ << 4) + 16);
|
||||
if($ore->canPlaceObject($level, $x, $y, $z)){
|
||||
$ore->placeObject($level, new Vector3($x, $y, $z));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user