diff --git a/src/math/Vector2.php b/src/math/Vector2.php index 9a66ff8c1..e5c27f47f 100644 --- a/src/math/Vector2.php +++ b/src/math/Vector2.php @@ -23,12 +23,8 @@ 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; - } + $this->x = $x; + $this->y = $y; } public function getX(){ diff --git a/src/math/Vector3.php b/src/math/Vector3.php index 274ee7311..097424f00 100644 --- a/src/math/Vector3.php +++ b/src/math/Vector3.php @@ -23,13 +23,9 @@ 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; - } + $this->x = $x; + $this->y = $y; + $this->z = $z; } public function getX(){ diff --git a/src/pmf/Level.php b/src/pmf/Level.php index 3cf41471a..1e33232b8 100644 --- a/src/pmf/Level.php +++ b/src/pmf/Level.php @@ -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; diff --git a/src/utils/Random.php b/src/utils/Random.php index 7e2e7ea69..fd0273ecb 100644 --- a/src/utils/Random.php +++ b/src/utils/Random.php @@ -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)); } } \ No newline at end of file diff --git a/src/world/generator/SuperflatGenerator.php b/src/world/generator/SuperflatGenerator.php index 0f3b1ae47..dfd3c4a18 100644 --- a/src/world/generator/SuperflatGenerator.php +++ b/src/world/generator/SuperflatGenerator.php @@ -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)); } diff --git a/src/world/generator/object/OreObject.php b/src/world/generator/object/OreObject.php index 90a2eb9fe..8ad0c64f8 100644 --- a/src/world/generator/object/OreObject.php +++ b/src/world/generator/object/OreObject.php @@ -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); } } } diff --git a/src/world/generator/object/grass/TallGrassObject.php b/src/world/generator/object/grass/TallGrassObject.php index 0ea2bcdcc..62bb04edc 100644 --- a/src/world/generator/object/grass/TallGrassObject.php +++ b/src/world/generator/object/grass/TallGrassObject.php @@ -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); } } } diff --git a/src/world/generator/object/tree/PineTreeObject.php b/src/world/generator/object/tree/PineTreeObject.php index a3e75f960..ed3276aad 100644 --- a/src/world/generator/object/tree/PineTreeObject.php +++ b/src/world/generator/object/tree/PineTreeObject.php @@ -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; } } diff --git a/src/world/generator/object/tree/SmallTreeObject.php b/src/world/generator/object/tree/SmallTreeObject.php index 1fb5eee8d..394887e56 100644 --- a/src/world/generator/object/tree/SmallTreeObject.php +++ b/src/world/generator/object/tree/SmallTreeObject.php @@ -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; } } @@ -53,7 +52,7 @@ class SmallTreeObject extends TreeObject{ public function placeObject(Level $level, Vector3 $pos, Random $random){ // The base dirt block - $dirtpos = new Vector3( $pos->x, $pos->y -1, $pos->z ); + $dirtpos = new Vector3( $pos->x, $pos->y - 1, $pos->z ); $level->setBlockRaw( $dirtpos, new DirtBlock() ); // Adjust the tree trunk's height randomly diff --git a/src/world/generator/object/tree/SpruceTreeObject.php b/src/world/generator/object/tree/SpruceTreeObject.php index 796c0bf73..c027ac644 100644 --- a/src/world/generator/object/tree/SpruceTreeObject.php +++ b/src/world/generator/object/tree/SpruceTreeObject.php @@ -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; } } diff --git a/src/world/generator/populator/OrePopulator.php b/src/world/generator/populator/OrePopulator.php index 5830a051d..390cbcba7 100644 --- a/src/world/generator/populator/OrePopulator.php +++ b/src/world/generator/populator/OrePopulator.php @@ -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)); } } }