mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-07-03 08:39:53 +00:00
Infinite generation, in-place chunk creation working. New PMF Format
This commit is contained in:
parent
8377416f48
commit
f7b8ad0e37
@ -19,16 +19,17 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
define("PMF_CURRENT_LEVEL_VERSION", 0x00);
|
|
||||||
|
|
||||||
class PMFLevel extends PMF{
|
class PMFLevel extends PMF{
|
||||||
private $levelData = array();
|
const VERSION = 0x01;
|
||||||
private $locationTable = array();
|
const DEFLATE_LEVEL = 9;
|
||||||
|
|
||||||
|
public $level;
|
||||||
|
public $levelData = array();
|
||||||
public $isLoaded = true;
|
public $isLoaded = true;
|
||||||
private $log = 4;
|
|
||||||
private $payloadOffset = 0;
|
|
||||||
private $chunks = array();
|
private $chunks = array();
|
||||||
private $chunkChange = array();
|
private $chunkChange = array();
|
||||||
|
private $chunkInfo = array();
|
||||||
|
public $isGenerating = false;
|
||||||
|
|
||||||
public function getData($index){
|
public function getData($index){
|
||||||
if(!isset($this->levelData[$index])){
|
if(!isset($this->levelData[$index])){
|
||||||
@ -46,8 +47,8 @@ class PMFLevel extends PMF{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function close(){
|
public function close(){
|
||||||
$chunks = null;
|
$this->chunks = null;
|
||||||
unset($chunks, $chunkChange, $locationTable);
|
unset($this->chunks, $this->chunkChange, $this->chunkInfo, $this->level);
|
||||||
parent::close();
|
parent::close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,7 +58,6 @@ class PMFLevel extends PMF{
|
|||||||
$this->levelData = $blank;
|
$this->levelData = $blank;
|
||||||
$this->createBlank();
|
$this->createBlank();
|
||||||
$this->isLoaded = true;
|
$this->isLoaded = true;
|
||||||
$this->log = (int) ((string) log($this->levelData["width"], 2));
|
|
||||||
}else{
|
}else{
|
||||||
if($this->load($file) !== false){
|
if($this->load($file) !== false){
|
||||||
$this->parseInfo();
|
$this->parseInfo();
|
||||||
@ -65,7 +65,6 @@ class PMFLevel extends PMF{
|
|||||||
$this->isLoaded = false;
|
$this->isLoaded = false;
|
||||||
}else{
|
}else{
|
||||||
$this->isLoaded = true;
|
$this->isLoaded = true;
|
||||||
$this->log = (int) ((string) log($this->levelData["width"], 2));
|
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
$this->isLoaded = false;
|
$this->isLoaded = false;
|
||||||
@ -73,8 +72,8 @@ class PMFLevel extends PMF{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function saveData($locationTable = true){
|
public function saveData(){
|
||||||
$this->levelData["version"] = PMF_CURRENT_LEVEL_VERSION;
|
$this->levelData["version"] = PMFLevel::VERSION;
|
||||||
@ftruncate($this->fp, 5);
|
@ftruncate($this->fp, 5);
|
||||||
$this->seek(5);
|
$this->seek(5);
|
||||||
$this->write(chr($this->levelData["version"]));
|
$this->write(chr($this->levelData["version"]));
|
||||||
@ -84,33 +83,17 @@ class PMFLevel extends PMF{
|
|||||||
$this->write(Utils::writeFloat($this->levelData["spawnX"]));
|
$this->write(Utils::writeFloat($this->levelData["spawnX"]));
|
||||||
$this->write(Utils::writeFloat($this->levelData["spawnY"]));
|
$this->write(Utils::writeFloat($this->levelData["spawnY"]));
|
||||||
$this->write(Utils::writeFloat($this->levelData["spawnZ"]));
|
$this->write(Utils::writeFloat($this->levelData["spawnZ"]));
|
||||||
$this->write(chr($this->levelData["width"]));
|
|
||||||
$this->write(chr($this->levelData["height"]));
|
$this->write(chr($this->levelData["height"]));
|
||||||
$extra = gzdeflate($this->levelData["extra"], PMF_LEVEL_DEFLATE_LEVEL);
|
$this->write(Utils::writeShort(strlen($this->levelData["generator"])).$this->levelData["generator"]);
|
||||||
|
$settings = serialize($this->levelData["generatorSettings"]);
|
||||||
|
$this->write(Utils::writeShort(strlen($settings)).$settings);
|
||||||
|
$extra = gzdeflate($this->levelData["extra"], PMFLevel::DEFLATE_LEVEL);
|
||||||
$this->write(Utils::writeShort(strlen($extra)).$extra);
|
$this->write(Utils::writeShort(strlen($extra)).$extra);
|
||||||
$this->payloadOffset = ftell($this->fp);
|
|
||||||
|
|
||||||
if($locationTable !== false){
|
|
||||||
$this->writeLocationTable();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createBlank(){
|
private function createBlank(){
|
||||||
$this->saveData(false);
|
$this->saveData(false);
|
||||||
$this->locationTable = array();
|
|
||||||
$cnt = pow($this->levelData["width"], 2);
|
|
||||||
@mkdir(dirname($this->file)."/chunks/", 0755);
|
@mkdir(dirname($this->file)."/chunks/", 0755);
|
||||||
for($index = 0; $index < $cnt; ++$index){
|
|
||||||
$this->chunks[$index] = false;
|
|
||||||
$this->chunkChange[$index] = false;
|
|
||||||
$this->locationTable[$index] = array(
|
|
||||||
0 => 0,
|
|
||||||
);
|
|
||||||
$this->write(Utils::writeShort(0));
|
|
||||||
$X = $Z = null;
|
|
||||||
$this->getXZ($index, $X, $Z);
|
|
||||||
@file_put_contents($this->getChunkPath($X, $Z), gzdeflate("", PMF_LEVEL_DEFLATE_LEVEL));
|
|
||||||
}
|
|
||||||
if(!file_exists(dirname($this->file)."/entities.yml")){
|
if(!file_exists(dirname($this->file)."/entities.yml")){
|
||||||
$entities = new Config(dirname($this->file)."/entities.yml", CONFIG_YAML);
|
$entities = new Config(dirname($this->file)."/entities.yml", CONFIG_YAML);
|
||||||
$entities->save();
|
$entities->save();
|
||||||
@ -127,7 +110,7 @@ class PMFLevel extends PMF{
|
|||||||
}
|
}
|
||||||
$this->seek(5);
|
$this->seek(5);
|
||||||
$this->levelData["version"] = ord($this->read(1));
|
$this->levelData["version"] = ord($this->read(1));
|
||||||
if($this->levelData["version"] > PMF_CURRENT_LEVEL_VERSION){
|
if($this->levelData["version"] > PMFLevel::VERSION){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$this->levelData["name"] = $this->read(Utils::readShort($this->read(2), false));
|
$this->levelData["name"] = $this->read(Utils::readShort($this->read(2), false));
|
||||||
@ -136,90 +119,81 @@ class PMFLevel extends PMF{
|
|||||||
$this->levelData["spawnX"] = Utils::readFloat($this->read(4));
|
$this->levelData["spawnX"] = Utils::readFloat($this->read(4));
|
||||||
$this->levelData["spawnY"] = Utils::readFloat($this->read(4));
|
$this->levelData["spawnY"] = Utils::readFloat($this->read(4));
|
||||||
$this->levelData["spawnZ"] = Utils::readFloat($this->read(4));
|
$this->levelData["spawnZ"] = Utils::readFloat($this->read(4));
|
||||||
$this->levelData["width"] = ord($this->read(1));
|
|
||||||
$this->levelData["height"] = ord($this->read(1));
|
$this->levelData["height"] = ord($this->read(1));
|
||||||
if(($this->levelData["width"] !== 16 and $this->levelData["width"] !== 32) or $this->levelData["height"] !== 8){
|
if($this->levelData["height"] !== 8){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$lastseek = ftell($this->fp);
|
if($this->levelData["version"] === 0){
|
||||||
if(($len = $this->read(2)) === false or ($this->levelData["extra"] = @gzinflate($this->read(Utils::readShort($len, false)))) === false){ //Corruption protection
|
$this->read(1);
|
||||||
console("[NOTICE] Empty/corrupt location table detected, forcing recovery");
|
|
||||||
fseek($this->fp, $lastseek);
|
|
||||||
$c = gzdeflate("");
|
|
||||||
$this->write(Utils::writeShort(strlen($c)).$c);
|
|
||||||
$this->payloadOffset = ftell($this->fp);
|
|
||||||
$this->levelData["extra"] = "";
|
|
||||||
$cnt = pow($this->levelData["width"], 2);
|
|
||||||
for($index = 0; $index < $cnt; ++$index){
|
|
||||||
$this->write("\x00\xFF"); //Force index recreation
|
|
||||||
}
|
|
||||||
fseek($this->fp, $this->payloadOffset);
|
|
||||||
}else{
|
}else{
|
||||||
$this->payloadOffset = ftell($this->fp);
|
$this->levelData["generator"] = $this->read(Utils::readShort($this->read(2), false));
|
||||||
|
$this->levelData["generatorSettings"] = unserialize($this->read(Utils::readShort($this->read(2), false)));
|
||||||
|
}
|
||||||
|
$this->levelData["extra"] = @gzinflate($this->read(Utils::readShort($this->read(2), false)));
|
||||||
|
|
||||||
|
if($this->levelData["version"] === 0){
|
||||||
|
$this->upgrade_From0_To1();
|
||||||
}
|
}
|
||||||
return $this->readLocationTable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getIndex($X, $Z){
|
private function upgrade_From0_To1(){
|
||||||
$X = (int) $X;
|
|
||||||
$Z = (int) $Z;
|
|
||||||
return ($Z << $this->log) + $X;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getXZ($index, &$X = null, &$Z = null){
|
|
||||||
$X = $index >> $this->log;
|
|
||||||
$Z = $index & (pow($this->log, 2) - 1);
|
|
||||||
return array($X, $Z);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function readLocationTable(){
|
|
||||||
$this->locationTable = array();
|
|
||||||
$cnt = pow($this->levelData["width"], 2);
|
|
||||||
$this->seek($this->payloadOffset);
|
|
||||||
for($index = 0; $index < $cnt; ++$index){
|
for($index = 0; $index < $cnt; ++$index){
|
||||||
$this->chunks[$index] = false;
|
$this->chunks[$index] = false;
|
||||||
$this->chunkChange[$index] = false;
|
$this->chunkChange[$index] = false;
|
||||||
$this->locationTable[$index] = array(
|
$locationTable[$index] = array(
|
||||||
0 => Utils::readShort($this->read(2)), //16 bit flags
|
0 => Utils::readShort($this->read(2)), //16 bit flags
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function writeLocationTable(){
|
public static function getIndex($X, $Z){
|
||||||
$cnt = pow($this->levelData["width"], 2);
|
return ($Z << 16) + $X;
|
||||||
@ftruncate($this->fp, $this->payloadOffset);
|
|
||||||
$this->seek($this->payloadOffset);
|
|
||||||
for($index = 0; $index < $cnt; ++$index){
|
|
||||||
$this->write(Utils::writeShort($this->locationTable[$index][0]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getXZ($index, &$X = null, &$Z = null){
|
||||||
|
$Z = $index >> 16;
|
||||||
|
$X = $index & 0xFFFF;
|
||||||
|
return array($X, $Z);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getChunkPath($X, $Z){
|
private function getChunkPath($X, $Z){
|
||||||
return dirname($this->file)."/chunks/".$Z.".".$X.".pmc";
|
return dirname($this->file)."/chunks/".(($X ^ $Z) & 0xff)."/".$Z.".".$X.".pmc";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generateChunk($X, $Z){
|
||||||
|
$path = $this->getChunkPath($X, $Z);
|
||||||
|
if(!file_exists(dirname($path))){
|
||||||
|
@mkdir(dirname($path), 0755);
|
||||||
|
}
|
||||||
|
$this->isGenerating = true;
|
||||||
|
$ret = $this->level->generateChunk($X, $Z);
|
||||||
|
$this->isGenerating = false;
|
||||||
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function loadChunk($X, $Z){
|
public function loadChunk($X, $Z){
|
||||||
$X = (int) $X;
|
$X = (int) $X;
|
||||||
$Z = (int) $Z;
|
$Z = (int) $Z;
|
||||||
$index = $this->getIndex($X, $Z);
|
$index = self::getIndex($X, $Z);
|
||||||
if($this->isChunkLoaded($X, $Z)){
|
if($this->isChunkLoaded($X, $Z)){
|
||||||
return true;
|
return true;
|
||||||
}elseif(!isset($this->locationTable[$index])){
|
}
|
||||||
|
$path = $this->getChunkPath($X, $Z);
|
||||||
|
if(!file_exists($path) and $this->generateChunk($X, $Z) === false){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$info = $this->locationTable[$index];
|
$chunk = @gzopen($path, "rb");
|
||||||
$this->seek($info[0]);
|
|
||||||
|
|
||||||
$chunk = @gzopen($this->getChunkPath($X, $Z), "rb");
|
|
||||||
if($chunk === false){
|
if($chunk === false){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
$this->chunkInfo[$index] = array(
|
||||||
|
0 => ord(gzread($chunk, 1)),
|
||||||
|
);
|
||||||
$this->chunks[$index] = array();
|
$this->chunks[$index] = array();
|
||||||
$this->chunkChange[$index] = array(-1 => false);
|
$this->chunkChange[$index] = array(-1 => false);
|
||||||
for($Y = 0; $Y < $this->levelData["height"]; ++$Y){
|
for($Y = 0; $Y < $this->chunkInfo[$index][0]; ++$Y){
|
||||||
$t = 1 << $Y;
|
$t = 1 << $Y;
|
||||||
if(($info[0] & $t) === $t){
|
if(($this->chunkInfo[$index][0] & $t) === $t){
|
||||||
// 4096 + 2048 + 2048, Block Data, Meta, Light
|
// 4096 + 2048 + 2048, Block Data, Meta, Light
|
||||||
if(strlen($this->chunks[$index][$Y] = gzread($chunk, 8192)) < 8192){
|
if(strlen($this->chunks[$index][$Y] = gzread($chunk, 8192)) < 8192){
|
||||||
console("[NOTICE] Empty corrupt chunk detected [$X,$Z,:$Y], recovering contents");
|
console("[NOTICE] Empty corrupt chunk detected [$X,$Z,:$Y], recovering contents");
|
||||||
@ -241,15 +215,16 @@ class PMFLevel extends PMF{
|
|||||||
}elseif($save !== false){
|
}elseif($save !== false){
|
||||||
$this->saveChunk($X, $Z);
|
$this->saveChunk($X, $Z);
|
||||||
}
|
}
|
||||||
$index = $this->getIndex($X, $Z);
|
$index = self::getIndex($X, $Z);
|
||||||
$this->chunks[$index] = null;
|
$this->chunks[$index] = null;
|
||||||
$this->chunkChange[$index] = null;
|
$this->chunkChange[$index] = null;
|
||||||
unset($this->chunks[$index], $this->chunkChange[$index]);
|
$this->chunkInfo[$index] = null;
|
||||||
|
unset($this->chunks[$index], $this->chunkChange[$index], $this->chunkInfo[$index]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isChunkLoaded($X, $Z){
|
public function isChunkLoaded($X, $Z){
|
||||||
$index = $this->getIndex($X, $Z);
|
$index = self::getIndex($X, $Z);
|
||||||
if(!isset($this->chunks[$index]) or $this->chunks[$index] === false){
|
if(!isset($this->chunks[$index]) or $this->chunks[$index] === false){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -257,7 +232,7 @@ class PMFLevel extends PMF{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected function isMiniChunkEmpty($X, $Z, $Y){
|
protected function isMiniChunkEmpty($X, $Z, $Y){
|
||||||
$index = $this->getIndex($X, $Z);
|
$index = self::getIndex($X, $Z);
|
||||||
if($this->chunks[$index][$Y] !== false){
|
if($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;
|
||||||
@ -270,11 +245,11 @@ class PMFLevel extends PMF{
|
|||||||
if($this->isChunkLoaded($X, $Z) === false){
|
if($this->isChunkLoaded($X, $Z) === false){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$index = $this->getIndex($X, $Z);
|
$index = self::getIndex($X, $Z);
|
||||||
$this->chunks[$index][$Y] = str_repeat("\x00", 8192);
|
$this->chunks[$index][$Y] = str_repeat("\x00", 8192);
|
||||||
$this->chunkChange[$index][-1] = true;
|
$this->chunkChange[$index][-1] = true;
|
||||||
$this->chunkChange[$index][$Y] = 8192;
|
$this->chunkChange[$index][$Y] = 8192;
|
||||||
$this->locationTable[$index][0] |= 1 << $Y;
|
$this->chunkInfo[$index][0] |= 1 << $Y;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,36 +257,61 @@ class PMFLevel extends PMF{
|
|||||||
if($this->loadChunk($X, $Z) === false){
|
if($this->loadChunk($X, $Z) === false){
|
||||||
return str_repeat("\x00", 8192);
|
return str_repeat("\x00", 8192);
|
||||||
}
|
}
|
||||||
$index = $this->getIndex($X, $Z);
|
$index = self::getIndex($X, $Z);
|
||||||
if(!isset($this->chunks[$index][$Y]) or $this->chunks[$index][$Y] === false){
|
if(!isset($this->chunks[$index][$Y]) or $this->chunks[$index][$Y] === false){
|
||||||
return str_repeat("\x00", 8192);
|
return str_repeat("\x00", 8192);
|
||||||
}
|
}
|
||||||
return $this->chunks[$index][$Y];
|
return $this->chunks[$index][$Y];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function initCleanChunk($X, $Z){
|
||||||
|
$index = self::getIndex($X, $Z);
|
||||||
|
if(!isset($this->chunks[$index])){
|
||||||
|
$this->chunks[$index] = array(
|
||||||
|
0 => false,
|
||||||
|
1 => false,
|
||||||
|
2 => false,
|
||||||
|
3 => false,
|
||||||
|
4 => false,
|
||||||
|
5 => false,
|
||||||
|
6 => false,
|
||||||
|
7 => false,
|
||||||
|
);
|
||||||
|
$this->chunkChange[$index] = array(-1 => false);
|
||||||
|
$this->chunkInfo[$index] = array(
|
||||||
|
0 => 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function setMiniChunk($X, $Z, $Y, $data){
|
public function setMiniChunk($X, $Z, $Y, $data){
|
||||||
if($this->isChunkLoaded($X, $Z) === false){
|
if($this->isGenerating === true){
|
||||||
|
$this->initCleanChunk($X, $Z);
|
||||||
|
}elseif($this->isChunkLoaded($X, $Z) === false){
|
||||||
$this->loadChunk($X, $Z);
|
$this->loadChunk($X, $Z);
|
||||||
}
|
}
|
||||||
if(strlen($data) !== 8192){
|
if(strlen($data) !== 8192){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$index = $this->getIndex($X, $Z);
|
$index = self::getIndex($X, $Z);
|
||||||
$this->chunks[$index][$Y] = (string) $data;
|
$this->chunks[$index][$Y] = (string) $data;
|
||||||
$this->chunkChange[$index][-1] = true;
|
$this->chunkChange[$index][-1] = true;
|
||||||
$this->chunkChange[$index][$Y] = 8192;
|
$this->chunkChange[$index][$Y] = 8192;
|
||||||
$this->locationTable[$index][0] |= 1 << $Y;
|
$this->chunkInfo[$index][0] |= 1 << $Y;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getBlockID($x, $y, $z){
|
public function getBlockID($x, $y, $z){
|
||||||
if($y > 127 or $y < 0 or $x < 0 or $z < 0 or $x > 255 or $z > 255){
|
if($y > 127 or $y < 0){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
$X = $x >> 4;
|
$X = $x >> 4;
|
||||||
$Z = $z >> 4;
|
$Z = $z >> 4;
|
||||||
$Y = $y >> 4;
|
$Y = $y >> 4;
|
||||||
$index = $this->getIndex($X, $Z);
|
$index = self::getIndex($X, $Z);
|
||||||
|
if(!isset($this->chunks[$index]) or $this->chunks[$index] === false){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
$aX = $x - ($X << 4);
|
$aX = $x - ($X << 4);
|
||||||
$aZ = $z - ($Z << 4);
|
$aZ = $z - ($Z << 4);
|
||||||
$aY = $y - ($Y << 4);
|
$aY = $y - ($Y << 4);
|
||||||
@ -320,17 +320,17 @@ class PMFLevel extends PMF{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function setBlockID($x, $y, $z, $block){
|
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){
|
if($y > 127 or $y < 0){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$X = $x >> 4;
|
$X = $x >> 4;
|
||||||
$Z = $z >> 4;
|
$Z = $z >> 4;
|
||||||
$Y = $y >> 4;
|
$Y = $y >> 4;
|
||||||
$block &= 0xFF;
|
$block &= 0xFF;
|
||||||
if($X >= 32 or $Z >= 32 or $Y >= $this->levelData["height"] or $y < 0){
|
$index = self::getIndex($X, $Z);
|
||||||
|
if(!isset($this->chunks[$index]) or $this->chunks[$index] === false){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$index = $this->getIndex($X, $Z);
|
|
||||||
$aX = $x - ($X << 4);
|
$aX = $x - ($X << 4);
|
||||||
$aZ = $z - ($Z << 4);
|
$aZ = $z - ($Z << 4);
|
||||||
$aY = $y - ($Y << 4);
|
$aY = $y - ($Y << 4);
|
||||||
@ -345,13 +345,16 @@ class PMFLevel extends PMF{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getBlockDamage($x, $y, $z){
|
public function getBlockDamage($x, $y, $z){
|
||||||
if($y > 127 or $y < 0 or $x < 0 or $z < 0 or $x > 255 or $z > 255){
|
if($y > 127 or $y < 0){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
$X = $x >> 4;
|
$X = $x >> 4;
|
||||||
$Z = $z >> 4;
|
$Z = $z >> 4;
|
||||||
$Y = $y >> 4;
|
$Y = $y >> 4;
|
||||||
$index = $this->getIndex($X, $Z);
|
$index = self::getIndex($X, $Z);
|
||||||
|
if(!isset($this->chunks[$index]) or $this->chunks[$index] === false){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
$aX = $x - ($X << 4);
|
$aX = $x - ($X << 4);
|
||||||
$aZ = $z - ($Z << 4);
|
$aZ = $z - ($Z << 4);
|
||||||
$aY = $y - ($Y << 4);
|
$aY = $y - ($Y << 4);
|
||||||
@ -365,17 +368,17 @@ class PMFLevel extends PMF{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function setBlockDamage($x, $y, $z, $damage){
|
public function setBlockDamage($x, $y, $z, $damage){
|
||||||
if($y > 127 or $y < 0 or $x < 0 or $z < 0 or $x > 255 or $z > 255){
|
if($y > 127 or $y < 0){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$X = $x >> 4;
|
$X = $x >> 4;
|
||||||
$Z = $z >> 4;
|
$Z = $z >> 4;
|
||||||
$Y = $y >> 4;
|
$Y = $y >> 4;
|
||||||
$damage &= 0x0F;
|
$damage &= 0x0F;
|
||||||
if($X >= 32 or $Z >= 32 or $Y >= $this->levelData["height"] or $y < 0){
|
$index = self::getIndex($X, $Z);
|
||||||
|
if(!isset($this->chunks[$index]) or $this->chunks[$index] === false){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$index = $this->getIndex($X, $Z);
|
|
||||||
$aX = $x - ($X << 4);
|
$aX = $x - ($X << 4);
|
||||||
$aZ = $z - ($Z << 4);
|
$aZ = $z - ($Z << 4);
|
||||||
$aY = $y - ($Y << 4);
|
$aY = $y - ($Y << 4);
|
||||||
@ -404,10 +407,10 @@ class PMFLevel extends PMF{
|
|||||||
$X = $x >> 4;
|
$X = $x >> 4;
|
||||||
$Z = $z >> 4;
|
$Z = $z >> 4;
|
||||||
$Y = $y >> 4;
|
$Y = $y >> 4;
|
||||||
if($x < 0 or $z < 0 or $X >= $this->levelData["width"] or $Z >= $this->levelData["width"] or $Y >= $this->levelData["height"] or $y < 0){
|
if($y < 0 or $y > 127){
|
||||||
return array(AIR, 0);
|
return array(AIR, 0);
|
||||||
}
|
}
|
||||||
$index = $this->getIndex($X, $Z);
|
$index = self::getIndex($X, $Z);
|
||||||
if(!isset($this->chunks[$index]) or $this->chunks[$index] === false){
|
if(!isset($this->chunks[$index]) or $this->chunks[$index] === false){
|
||||||
if($this->loadChunk($X, $Z) === false){
|
if($this->loadChunk($X, $Z) === false){
|
||||||
return array(AIR, 0);
|
return array(AIR, 0);
|
||||||
@ -429,15 +432,15 @@ class PMFLevel extends PMF{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function setBlock($x, $y, $z, $block, $meta = 0){
|
public function setBlock($x, $y, $z, $block, $meta = 0){
|
||||||
|
if($y > 127 or $y < 0){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
$X = $x >> 4;
|
$X = $x >> 4;
|
||||||
$Z = $z >> 4;
|
$Z = $z >> 4;
|
||||||
$Y = $y >> 4;
|
$Y = $y >> 4;
|
||||||
$block &= 0xFF;
|
$block &= 0xFF;
|
||||||
$meta &= 0x0F;
|
$meta &= 0x0F;
|
||||||
if($X >= 32 or $Z >= 32 or $Y >= $this->levelData["height"] or $y < 0){
|
$index = self::getIndex($X, $Z);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$index = $this->getIndex($X, $Z);
|
|
||||||
if(!isset($this->chunks[$index]) or $this->chunks[$index] === false){
|
if(!isset($this->chunks[$index]) or $this->chunks[$index] === false){
|
||||||
if($this->loadChunk($X, $Z) === false){
|
if($this->loadChunk($X, $Z) === false){
|
||||||
return false;
|
return false;
|
||||||
@ -486,35 +489,46 @@ class PMFLevel extends PMF{
|
|||||||
public function saveChunk($X, $Z){
|
public function saveChunk($X, $Z){
|
||||||
$X = (int) $X;
|
$X = (int) $X;
|
||||||
$Z = (int) $Z;
|
$Z = (int) $Z;
|
||||||
if(!$this->isChunkLoaded($X, $Z)){
|
if($this->isGenerating === true){
|
||||||
|
$this->initCleanChunk($X, $Z);
|
||||||
|
}elseif(!$this->isChunkLoaded($X, $Z)){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$index = $this->getIndex($X, $Z);
|
$index = self::getIndex($X, $Z);
|
||||||
if(!isset($this->chunkChange[$index]) or $this->chunkChange[$index][-1] === false){//No changes in chunk
|
if(!isset($this->chunkChange[$index]) or $this->chunkChange[$index][-1] === false){//No changes in chunk
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$chunk = @gzopen($this->getChunkPath($X, $Z), "wb".PMF_LEVEL_DEFLATE_LEVEL);
|
$path = $this->getChunkPath($X, $Z);
|
||||||
|
if(!file_exists(dirname($path))){
|
||||||
|
@mkdir(dirname($path), 0755);
|
||||||
|
}
|
||||||
$bitmap = 0;
|
$bitmap = 0;
|
||||||
for($Y = 0; $Y < $this->levelData["height"]; ++$Y){
|
for($Y = 0; $Y < 8; ++$Y){
|
||||||
if($this->chunks[$index][$Y] !== false and ((isset($this->chunkChange[$index][$Y]) and $this->chunkChange[$index][$Y] === 0) or !$this->isMiniChunkEmpty($X, $Z, $Y))){
|
if($this->chunks[$index][$Y] !== false and ((isset($this->chunkChange[$index][$Y]) and $this->chunkChange[$index][$Y] === 0) or !$this->isMiniChunkEmpty($X, $Z, $Y))){
|
||||||
gzwrite($chunk, $this->chunks[$index][$Y]);
|
|
||||||
$bitmap |= 1 << $Y;
|
$bitmap |= 1 << $Y;
|
||||||
}else{
|
}else{
|
||||||
$this->chunks[$index][$Y] = false;
|
$this->chunks[$index][$Y] = false;
|
||||||
}
|
}
|
||||||
$this->chunkChange[$index][$Y] = 0;
|
$this->chunkChange[$index][$Y] = 0;
|
||||||
}
|
}
|
||||||
|
$chunk = @gzopen($path, "wb".PMFLevel::DEFLATE_LEVEL);
|
||||||
|
gzwrite($chunk, chr($bitmap));
|
||||||
|
for($Y = 0; $Y < 8; ++$Y){
|
||||||
|
$t = 1 << $Y;
|
||||||
|
if(($bitmap & $t) === $t){
|
||||||
|
gzwrite($chunk, $this->chunks[$index][$Y]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gzclose($chunk);
|
||||||
$this->chunkChange[$index][-1] = false;
|
$this->chunkChange[$index][-1] = false;
|
||||||
$this->locationTable[$index][0] = $bitmap;
|
$this->chunkInfo[$index][0] = $bitmap;
|
||||||
$this->seek($this->payloadOffset + ($index << 1));
|
|
||||||
$this->write(Utils::writeShort($this->locationTable[$index][0]));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function doSaveRound(){
|
public function doSaveRound(){
|
||||||
foreach($this->chunks as $index => $chunk){
|
foreach($this->chunks as $index => $chunk){
|
||||||
$this->getXZ($index, $X, $Z);
|
self::getXZ($index, $X, $Z);
|
||||||
$this->saveChunk($X, $Z);
|
$this->saveChunk($X, $Z);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -21,11 +21,12 @@
|
|||||||
|
|
||||||
class Level{
|
class Level{
|
||||||
public $entities, $tiles, $blockUpdates, $nextSave, $players = array(), $level;
|
public $entities, $tiles, $blockUpdates, $nextSave, $players = array(), $level;
|
||||||
private $time, $startCheck, $startTime, $server, $name, $usedChunks, $changedBlocks, $changedCount, $stopTime;
|
private $time, $startCheck, $startTime, $server, $name, $usedChunks, $changedBlocks, $changedCount, $stopTime, $generator;
|
||||||
|
|
||||||
public function __construct(PMFLevel $level, Config $entities, Config $tiles, Config $blockUpdates, $name){
|
public function __construct(PMFLevel $level, Config $entities, Config $tiles, Config $blockUpdates, $name){
|
||||||
$this->server = ServerAPI::request();
|
$this->server = ServerAPI::request();
|
||||||
$this->level = $level;
|
$this->level = $level;
|
||||||
|
$level->level = $this;
|
||||||
$this->level->level = $this;
|
$this->level->level = $this;
|
||||||
$this->entities = $entities;
|
$this->entities = $entities;
|
||||||
$this->tiles = $tiles;
|
$this->tiles = $tiles;
|
||||||
@ -40,6 +41,17 @@ class Level{
|
|||||||
$this->usedChunks = array();
|
$this->usedChunks = array();
|
||||||
$this->changedBlocks = array();
|
$this->changedBlocks = array();
|
||||||
$this->changedCount = array();
|
$this->changedCount = array();
|
||||||
|
if(class_exists($this->level->levelData["generator"])){
|
||||||
|
$gen = $this->level->levelData["generator"];
|
||||||
|
$this->generator = new $gen((array) $this->level->levelData["generatorSettings"]);
|
||||||
|
}else{
|
||||||
|
if(strtoupper($this->server->api->getProperty("level-type")) == "FLAT"){
|
||||||
|
$this->generator = new SuperflatGenerator();
|
||||||
|
}else{
|
||||||
|
$this->generator = new NormalGenerator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->generator->init($this, new Random($this->level->levelData["seed"]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function close(){
|
public function close(){
|
||||||
@ -136,6 +148,13 @@ class Level{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function generateChunk($X, $Z){
|
||||||
|
$this->level->initCleanChunk($X, $Z);
|
||||||
|
$this->generator->generateChunk($X, $Z);
|
||||||
|
$this->generator->populateChunk($X, $Z);
|
||||||
|
$this->level->saveChunk($X, $Z);
|
||||||
|
}
|
||||||
|
|
||||||
public function __destruct(){
|
public function __destruct(){
|
||||||
if(isset($this->level)){
|
if(isset($this->level)){
|
||||||
$this->save(false, false);
|
$this->save(false, false);
|
||||||
|
@ -20,7 +20,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
interface LevelGenerator{
|
interface LevelGenerator{
|
||||||
public function __construct(array $options = array());
|
|
||||||
|
public function __construct(array $settings = array());
|
||||||
|
|
||||||
public function init(Level $level, Random $random);
|
public function init(Level $level, Random $random);
|
||||||
|
|
||||||
@ -28,7 +29,9 @@ interface LevelGenerator{
|
|||||||
|
|
||||||
public function populateChunk($chunkX, $chunkZ);
|
public function populateChunk($chunkX, $chunkZ);
|
||||||
|
|
||||||
public function populateLevel();
|
public function getSettings();
|
||||||
|
|
||||||
|
//public function populateLevel();
|
||||||
|
|
||||||
public function getSpawn();
|
public function getSpawn();
|
||||||
}
|
}
|
@ -28,8 +28,9 @@ class NormalGenerator implements LevelGenerator{
|
|||||||
private $populators = array();
|
private $populators = array();
|
||||||
private $level;
|
private $level;
|
||||||
private $random;
|
private $random;
|
||||||
private $worldHeight = 64;
|
private $worldHeight = 65;
|
||||||
private $waterHeight = 60;
|
private $waterHeight = 62;
|
||||||
|
private $noiseGenBase;
|
||||||
private $noiseGen1;
|
private $noiseGen1;
|
||||||
private $noiseGen2;
|
private $noiseGen2;
|
||||||
private $noiseGen3;
|
private $noiseGen3;
|
||||||
@ -41,13 +42,17 @@ class NormalGenerator implements LevelGenerator{
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSettings(){
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
public function init(Level $level, Random $random){
|
public function init(Level $level, Random $random){
|
||||||
$this->level = $level;
|
$this->level = $level;
|
||||||
$this->random = $random;
|
$this->random = $random;
|
||||||
$this->random->setSeed($this->level->getSeed());
|
$this->random->setSeed($this->level->getSeed());
|
||||||
$this->noiseGen1 = new NoiseGeneratorPerlin($this->random, 4);
|
$this->noiseGenBase = new NoiseGeneratorSimplex($this->random, 4);
|
||||||
$this->noiseGen2 = new NoiseGeneratorPerlin($this->random, 4);
|
$this->noiseGen1 = new NoiseGeneratorSimplex($this->random, 8);
|
||||||
$this->noiseGen3 = new NoiseGeneratorPerlin($this->random, 4);
|
//$this->noiseGen2 = new NoiseGeneratorSimplex($this->random, 8);
|
||||||
|
|
||||||
$ores = new OrePopulator();
|
$ores = new OrePopulator();
|
||||||
$ores->setOreTypes(array(
|
$ores->setOreTypes(array(
|
||||||
@ -66,17 +71,18 @@ class NormalGenerator implements LevelGenerator{
|
|||||||
public function generateChunk($chunkX, $chunkZ){
|
public function generateChunk($chunkX, $chunkZ){
|
||||||
$this->random->setSeed(0xdeadbeef ^ ($chunkX << 8) ^ $chunkZ ^ $this->level->getSeed());
|
$this->random->setSeed(0xdeadbeef ^ ($chunkX << 8) ^ $chunkZ ^ $this->level->getSeed());
|
||||||
|
|
||||||
$baseHeight = $this->worldHeight;// + * 35;
|
|
||||||
for($chunkY = 0; $chunkY < 8; ++$chunkY){
|
for($chunkY = 0; $chunkY < 8; ++$chunkY){
|
||||||
$chunk = "";
|
$chunk = "";
|
||||||
$startY = $chunkY << 4;
|
$startY = $chunkY << 4;
|
||||||
$endY = $startY + 16;
|
$endY = $startY + 16;
|
||||||
for($z = 0; $z < 16; ++$z){
|
for($z = 0; $z < 16; ++$z){
|
||||||
for($x = 0; $x < 16; ++$x){
|
for($x = 0; $x < 16; ++$x){
|
||||||
$noise1 = $this->noiseGen1->noise2D($x + ($chunkX << 4), $z + ($chunkZ << 4), 0.6, 32, true) * 2;
|
$noiseBase = $this->noiseGenBase->noise2D($x + ($chunkX << 4), $z + ($chunkZ << 4), 1/5, 16, true);
|
||||||
$noise2 = $this->noiseGen2->noise2D($x + ($chunkX << 4), $z + ($chunkZ << 4), 0.35, 64, true) * 15;
|
$noise1 = $this->noiseGen1->noise2D($x + ($chunkX << 4), $z + ($chunkZ << 4), 0.7, 25, true);
|
||||||
$noise3 = $this->noiseGen3->noise2D($x + ($chunkX << 4), $z + ($chunkZ << 4), 0.1, 64, true) * 45;
|
//$noise2 = $this->noiseGen2->noise2D($x + ($chunkX << 4), $z + ($chunkZ << 4), 0.8, 1);
|
||||||
$height = (int) ($baseHeight + $noise1 + $noise2);
|
//$height = $this->worldHeight + $noiseBase + $noise1 /*+ $noise2*/;
|
||||||
|
$height = $this->worldHeight + $noiseBase;//$height = (int) ($height + ($height * 0.15 * $noiseBase));
|
||||||
|
$height = (int) $height;
|
||||||
for($y = $startY; $y < $endY; ++$y){
|
for($y = $startY; $y < $endY; ++$y){
|
||||||
$diff = $height - $y;
|
$diff = $height - $y;
|
||||||
if($y <= 4 and ($y === 0 or $this->random->nextFloat() < 0.75)){
|
if($y <= 4 and ($y === 0 or $this->random->nextFloat() < 0.75)){
|
||||||
@ -86,13 +92,13 @@ class NormalGenerator implements LevelGenerator{
|
|||||||
}elseif($diff > 0){
|
}elseif($diff > 0){
|
||||||
$chunk .= "\x03"; //dirt
|
$chunk .= "\x03"; //dirt
|
||||||
}elseif($y <= $this->waterHeight){
|
}elseif($y <= $this->waterHeight){
|
||||||
if($diff === 0){
|
if($y === $this->waterHeight and $diff === 0){
|
||||||
$chunk .= "\x0c"; //sand
|
$chunk .= "\x0c"; //sand
|
||||||
}else{
|
}else{
|
||||||
$chunk .= "\x09"; //still_water
|
$chunk .= "\x09"; //still_water
|
||||||
}
|
}
|
||||||
}elseif($diff === 0){
|
}elseif($diff === 0){
|
||||||
$chunk .= "\x02"; //grass
|
$chunk .= $noise1 > 0 ? "\x02":"\x01"; //grass
|
||||||
}else{
|
}else{
|
||||||
$chunk .= "\x00";
|
$chunk .= "\x00";
|
||||||
}
|
}
|
||||||
@ -105,13 +111,6 @@ class NormalGenerator implements LevelGenerator{
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function initializeNoiseArray($x, $y, $z, $sizeX, $sizeY, $sizeZ){
|
|
||||||
$noiseArray = array_fill(0, $sizeX * $sizeY * $sizeZ, 0.0);
|
|
||||||
|
|
||||||
$noise5 = $this->noiseGen5->generateNoiseOctaves($x, $y, $z);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function populateChunk($chunkX, $chunkZ){
|
public function populateChunk($chunkX, $chunkZ){
|
||||||
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());
|
||||||
|
@ -26,6 +26,10 @@ require_once("LevelGenerator.php");
|
|||||||
class SuperflatGenerator implements LevelGenerator{
|
class SuperflatGenerator implements LevelGenerator{
|
||||||
private $level, $random, $structure, $chunks, $options, $floorLevel, $populators = array();
|
private $level, $random, $structure, $chunks, $options, $floorLevel, $populators = array();
|
||||||
|
|
||||||
|
public function getSettings(){
|
||||||
|
return $this->options;
|
||||||
|
}
|
||||||
|
|
||||||
public function __construct(array $options = array()){
|
public function __construct(array $options = array()){
|
||||||
$this->preset = "2;7,59x1,3x3,2;1;spawn(radius=10 block=89),decoration(treecount=80 grasscount=45)";
|
$this->preset = "2;7,59x1,3x3,2;1;spawn(radius=10 block=89),decoration(treecount=80 grasscount=45)";
|
||||||
$this->options = $options;
|
$this->options = $options;
|
||||||
|
File diff suppressed because one or more lines are too long
@ -21,10 +21,9 @@
|
|||||||
|
|
||||||
class WorldGenerator{
|
class WorldGenerator{
|
||||||
private $seed, $level, $path, $random, $generator, $width;
|
private $seed, $level, $path, $random, $generator, $width;
|
||||||
public function __construct(LevelGenerator $generator, $name, $seed = false, $width = 16, $height = 8){
|
public function __construct(LevelGenerator $generator, $name, $seed = false, $height = 8){
|
||||||
$this->seed = $seed !== false ? (int) $seed:Utils::readInt(Utils::getRandomBytes(4, false));
|
$this->seed = $seed !== false ? (int) $seed:Utils::readInt(Utils::getRandomBytes(4, false));
|
||||||
$this->random = new Random($this->seed);
|
$this->random = new Random($this->seed);
|
||||||
$this->width = (int) $width;
|
|
||||||
$this->height = (int) $height;
|
$this->height = (int) $height;
|
||||||
$this->path = DATA_PATH."worlds/".$name."/";
|
$this->path = DATA_PATH."worlds/".$name."/";
|
||||||
$this->generator = $generator;
|
$this->generator = $generator;
|
||||||
@ -35,9 +34,10 @@ class WorldGenerator{
|
|||||||
"spawnX" => 128,
|
"spawnX" => 128,
|
||||||
"spawnY" => 128,
|
"spawnY" => 128,
|
||||||
"spawnZ" => 128,
|
"spawnZ" => 128,
|
||||||
"extra" => "",
|
"height" => $this->height,
|
||||||
"width" => $this->width,
|
"generator" => get_class($this->generator),
|
||||||
"height" => $this->height
|
"generatorSettings" => $this->generator->getSettings(),
|
||||||
|
"extra" => ""
|
||||||
));
|
));
|
||||||
$entities = new Config($this->path."entities.yml", CONFIG_YAML);
|
$entities = new Config($this->path."entities.yml", CONFIG_YAML);
|
||||||
$tiles = new Config($this->path."tiles.yml", CONFIG_YAML);
|
$tiles = new Config($this->path."tiles.yml", CONFIG_YAML);
|
||||||
@ -46,24 +46,32 @@ class WorldGenerator{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function generate(){
|
public function generate(){
|
||||||
|
$this->level->level->isGenerating = true;
|
||||||
$this->generator->init($this->level, $this->random);
|
$this->generator->init($this->level, $this->random);
|
||||||
for($Z = 0; $Z < $this->width; ++$Z){
|
|
||||||
for($X = 0; $X < $this->width; ++$X){
|
$i = 0;
|
||||||
|
for($Z = 6; $Z <= 10; ++$Z){
|
||||||
|
for($X = 6; $X <= 10; ++$X){
|
||||||
$this->generator->generateChunk($X, $Z);
|
$this->generator->generateChunk($X, $Z);
|
||||||
}
|
}
|
||||||
console("[NOTICE] Generating level ".ceil((($Z + 1)/$this->width) * 100)."%");
|
console("[NOTICE] Generating level".str_repeat(".", $i));
|
||||||
|
++$i;
|
||||||
}
|
}
|
||||||
console("[NOTICE] Populating level");
|
//console("[NOTICE] Populating level");
|
||||||
$this->generator->populateLevel();
|
//$this->generator->populateLevel();
|
||||||
for($Z = 0; $Z < $this->width; ++$Z){
|
|
||||||
for($X = 0; $X < $this->width; ++$X){
|
$i = 0;
|
||||||
|
for($Z = 6; $Z <= 10; ++$Z){
|
||||||
|
for($X = 6; $X <= 10; ++$X){
|
||||||
$this->generator->populateChunk($X, $Z);
|
$this->generator->populateChunk($X, $Z);
|
||||||
}
|
}
|
||||||
console("[NOTICE] Populating level ".ceil((($Z + 1)/$this->width) * 100)."%");
|
console("[NOTICE] Populating level".str_repeat(".", $i));
|
||||||
|
++$i;
|
||||||
}
|
}
|
||||||
|
|
||||||
$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 = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function close(){
|
public function close(){
|
||||||
|
@ -96,7 +96,7 @@ class NoiseGeneratorPerlin extends NoiseGenerator{
|
|||||||
self::grad($this->perm[$BB + 1], $x - 1, $y - 1, $z - 1))));
|
self::grad($this->perm[$BB + 1], $x - 1, $y - 1, $z - 1))));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getNoise2D($x, $z){
|
public function getNoise2D($x, $y){
|
||||||
return $this->getNoise3D($x, 0, $z);
|
return $this->getNoise3D($x, $y, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
437
src/world/generator/noise/NoiseGeneratorSimplex.php
Normal file
437
src/world/generator/noise/NoiseGeneratorSimplex.php
Normal file
@ -0,0 +1,437 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/***REM_START***/
|
||||||
|
require_once("NoiseGenerator.php");
|
||||||
|
/***REM_END***/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates simplex-based noise.
|
||||||
|
* <p>
|
||||||
|
* This is a modified version of the freely published version in the paper by
|
||||||
|
* Stefan Gustavson at
|
||||||
|
* <a href="http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf">
|
||||||
|
* http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf</a>
|
||||||
|
*/
|
||||||
|
class NoiseGeneratorSimplex extends NoiseGeneratorPerlin{
|
||||||
|
protected static $SQRT_3;
|
||||||
|
protected static $SQRT_5;
|
||||||
|
protected static $F2;
|
||||||
|
protected static $G2;
|
||||||
|
protected static $G22;
|
||||||
|
protected static $F3;
|
||||||
|
protected static $G3;
|
||||||
|
protected static $F4;
|
||||||
|
protected static $G4;
|
||||||
|
protected static $G42;
|
||||||
|
protected static $G43;
|
||||||
|
protected static $G44;
|
||||||
|
protected static $grad4 = [[0, 1, 1, 1],[0, 1, 1, -1],[0, 1, -1, 1],[0, 1, -1, -1],
|
||||||
|
[0, -1, 1, 1],[0, -1, 1, -1],[0, -1, -1, 1],[0, -1, -1, -1],
|
||||||
|
[1, 0, 1, 1],[1, 0, 1, -1],[1, 0, -1, 1],[1, 0, -1, -1],
|
||||||
|
[-1, 0, 1, 1],[-1, 0, 1, -1],[-1, 0, -1, 1],[-1, 0, -1, -1],
|
||||||
|
[1, 1, 0, 1],[1, 1, 0, -1],[1, -1, 0, 1],[1, -1, 0, -1],
|
||||||
|
[-1, 1, 0, 1],[-1, 1, 0, -1],[-1, -1, 0, 1],[-1, -1, 0, -1],
|
||||||
|
[1, 1, 1, 0],[1, 1, -1, 0],[1, -1, 1, 0],[1, -1, -1, 0],
|
||||||
|
[-1, 1, 1, 0],[-1, 1, -1, 0],[-1, -1, 1, 0],[-1, -1, -1, 0]];
|
||||||
|
protected static $simplex = [
|
||||||
|
[0, 1, 2, 3],[0, 1, 3, 2],[0, 0, 0, 0],[0, 2, 3, 1],[0, 0, 0, 0],[0, 0, 0, 0],[0, 0, 0, 0],[1, 2, 3, 0],
|
||||||
|
[0, 2, 1, 3],[0, 0, 0, 0],[0, 3, 1, 2],[0, 3, 2, 1],[0, 0, 0, 0],[0, 0, 0, 0],[0, 0, 0, 0],[1, 3, 2, 0],
|
||||||
|
[0, 0, 0, 0],[0, 0, 0, 0],[0, 0, 0, 0],[0, 0, 0, 0],[0, 0, 0, 0],[0, 0, 0, 0],[0, 0, 0, 0],[0, 0, 0, 0],
|
||||||
|
[1, 2, 0, 3],[0, 0, 0, 0],[1, 3, 0, 2],[0, 0, 0, 0],[0, 0, 0, 0],[0, 0, 0, 0],[2, 3, 0, 1],[2, 3, 1, 0],
|
||||||
|
[1, 0, 2, 3],[1, 0, 3, 2],[0, 0, 0, 0],[0, 0, 0, 0],[0, 0, 0, 0],[2, 0, 3, 1],[0, 0, 0, 0],[2, 1, 3, 0],
|
||||||
|
[0, 0, 0, 0],[0, 0, 0, 0],[0, 0, 0, 0],[0, 0, 0, 0],[0, 0, 0, 0],[0, 0, 0, 0],[0, 0, 0, 0],[0, 0, 0, 0],
|
||||||
|
[2, 0, 1, 3],[0, 0, 0, 0],[0, 0, 0, 0],[0, 0, 0, 0],[3, 0, 1, 2],[3, 0, 2, 1],[0, 0, 0, 0],[3, 1, 2, 0],
|
||||||
|
[2, 1, 0, 3],[0, 0, 0, 0],[0, 0, 0, 0],[0, 0, 0, 0],[3, 1, 0, 2],[0, 0, 0, 0],[3, 2, 0, 1],[3, 2, 1, 0]];
|
||||||
|
protected $offsetW;
|
||||||
|
|
||||||
|
public function __construct(Random $random, $octaves){
|
||||||
|
parent::__construct($random, $octaves);
|
||||||
|
$this->offsetW = $random->nextFloat() * 256;
|
||||||
|
self::$SQRT_3 = sqrt(3);
|
||||||
|
self::$SQRT_5 = sqrt(5);
|
||||||
|
self::$F2 = 0.5 * (self::$SQRT_3 - 1);
|
||||||
|
self::$G2 = (3 - self::$SQRT_3) / 6;
|
||||||
|
self::$G22 = self::$G2 * 2.0 - 1;
|
||||||
|
self::$F3 = 1.0 / 3.0;
|
||||||
|
self::$G3 = 1.0 / 6.0;
|
||||||
|
self::$F4 = (self::$SQRT_5 - 1.0) / 4.0;
|
||||||
|
self::$G4 = (5.0 - self::$SQRT_5) / 20.0;
|
||||||
|
self::$G42 = self::$G4 * 2.0;
|
||||||
|
self::$G43 = self::$G4 * 3.0;
|
||||||
|
self::$G44 = self::$G4 * 4.0 - 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function dot2D($g, $x, $y){
|
||||||
|
return $g[0] * $x + $g[1] * $y;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function dot3D($g, $x, $y, $z){
|
||||||
|
return $g[0] * $x + $g[1] * $y + $g[2] * $z;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function dot4D($g, $x, $y, $z, $w){
|
||||||
|
return $g[0] * $x + $g[1] * $y + $g[2] * $z + $g[3] * $w;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getNoise3D($x, $y, $z){
|
||||||
|
$x += $this->offsetX;
|
||||||
|
$y += $this->offsetY;
|
||||||
|
$z += $this->offsetZ;
|
||||||
|
|
||||||
|
// Skew the input space to determine which simplex cell we're in
|
||||||
|
$s = ($x + $y + $z) * self::$F3; // Very nice and simple skew factor for 3D
|
||||||
|
$i = self::floor($x + $s);
|
||||||
|
$j = self::floor($y + $s);
|
||||||
|
$k = self::floor($z + $s);
|
||||||
|
$t = ($i + $j + $k) * self::$G3;
|
||||||
|
$X0 = $i - $t; // Unskew the cell origin back to (x,y,z) space
|
||||||
|
$Y0 = $j - $t;
|
||||||
|
$Z0 = $k - $t;
|
||||||
|
$x0 = $x - $X0; // The x,y,z distances from the cell origin
|
||||||
|
$y0 = $y - $Y0;
|
||||||
|
$z0 = $z - $Z0;
|
||||||
|
|
||||||
|
// For the 3D case, the simplex shape is a slightly irregular tetrahedron.
|
||||||
|
|
||||||
|
// Determine which simplex we are in.
|
||||||
|
if($x0 >= $y0){
|
||||||
|
if($y0 >= $z0){
|
||||||
|
$i1 = 1;
|
||||||
|
$j1 = 0;
|
||||||
|
$k1 = 0;
|
||||||
|
$i2 = 1;
|
||||||
|
$j2 = 1;
|
||||||
|
$k2 = 0;
|
||||||
|
}// X Y Z order
|
||||||
|
elseif($x0 >= $z0){
|
||||||
|
$i1 = 1;
|
||||||
|
$j1 = 0;
|
||||||
|
$k1 = 0;
|
||||||
|
$i2 = 1;
|
||||||
|
$j2 = 0;
|
||||||
|
$k2 = 1;
|
||||||
|
}// X Z Y order
|
||||||
|
else{
|
||||||
|
$i1 = 0;
|
||||||
|
$j1 = 0;
|
||||||
|
$k1 = 1;
|
||||||
|
$i2 = 1;
|
||||||
|
$j2 = 0;
|
||||||
|
$k2 = 1;
|
||||||
|
}// Z X Y order
|
||||||
|
}else{ // x0<y0
|
||||||
|
if($y0 < $z0){
|
||||||
|
$i1 = 0;
|
||||||
|
$j1 = 0;
|
||||||
|
$k1 = 1;
|
||||||
|
$i2 = 0;
|
||||||
|
$j2 = 1;
|
||||||
|
$k2 = 1;
|
||||||
|
}// Z Y X order
|
||||||
|
elseif($x0 < $z0){
|
||||||
|
$i1 = 0;
|
||||||
|
$j1 = 1;
|
||||||
|
$k1 = 0;
|
||||||
|
$i2 = 0;
|
||||||
|
$j2 = 1;
|
||||||
|
$k2 = 1;
|
||||||
|
}// Y Z X order
|
||||||
|
else{
|
||||||
|
$i1 = 0;
|
||||||
|
$j1 = 1;
|
||||||
|
$k1 = 0;
|
||||||
|
$i2 = 1;
|
||||||
|
$j2 = 1;
|
||||||
|
$k2 = 0;
|
||||||
|
}// Y X Z order
|
||||||
|
}
|
||||||
|
|
||||||
|
// A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
|
||||||
|
// a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
|
||||||
|
// a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
|
||||||
|
// c = 1/6.
|
||||||
|
$x1 = $x0 - $i1 + self::$G3; // Offsets for second corner in (x,y,z) coords
|
||||||
|
$y1 = $y0 - $j1 + self::$G3;
|
||||||
|
$z1 = $z0 - $k1 + self::$G3;
|
||||||
|
$x2 = $x0 - $i2 + 2.0 * self::$G3; // Offsets for third corner in (x,y,z) coords
|
||||||
|
$y2 = $y0 - $j2 + 2.0 * self::$G3;
|
||||||
|
$z2 = $z0 - $k2 + 2.0 * self::$G3;
|
||||||
|
$x3 = $x0 - 1.0 + 3.0 * self::$G3; // Offsets for last corner in (x,y,z) coords
|
||||||
|
$y3 = $y0 - 1.0 + 3.0 * self::$G3;
|
||||||
|
$z3 = $z0 - 1.0 + 3.0 * self::$G3;
|
||||||
|
|
||||||
|
// Work out the hashed gradient indices of the four simplex corners
|
||||||
|
$ii = $i & 255;
|
||||||
|
$jj = $j & 255;
|
||||||
|
$kk = $k & 255;
|
||||||
|
$gi0 = $this->perm[$ii + $this->perm[$jj + $this->perm[$kk]]] % 12;
|
||||||
|
$gi1 = $this->perm[$ii + $i1 + $this->perm[$jj + $j1 + $this->perm[$kk + $k1]]] % 12;
|
||||||
|
$gi2 = $this->perm[$ii + $i2 + $this->perm[$jj + $j2 + $this->perm[$kk + $k2]]] % 12;
|
||||||
|
$gi3 = $this->perm[$ii + 1 + $this->perm[$jj + 1 + $this->perm[$kk + 1]]] % 12;
|
||||||
|
|
||||||
|
// Calculate the contribution from the four corners
|
||||||
|
$t0 = 0.6 - $x0 * $x0 - $y0 * $y0 - $z0 * $z0;
|
||||||
|
if($t0 < 0){
|
||||||
|
$n0 = 0.0;
|
||||||
|
}else{
|
||||||
|
$t0 *= $t0;
|
||||||
|
$n0 = $t0 * $t0 * self::dot3D(self::$grad3[$gi0], $x0, $y0, $z0);
|
||||||
|
}
|
||||||
|
|
||||||
|
$t1 = 0.6 - $x1 * $x1 - $y1 * $y1 - $z1 * $z1;
|
||||||
|
if($t1 < 0){
|
||||||
|
$n1 = 0.0;
|
||||||
|
}else{
|
||||||
|
$t1 *= $t1;
|
||||||
|
$n1 = $t1 * $t1 * self::dot3D(self::$grad3[$gi1], $x1, $y1, $z1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$t2 = 0.6 - $x2 * $x2 - $y2 * $y2 - $z2 * $z2;
|
||||||
|
if($t2 < 0){
|
||||||
|
$n2 = 0.0;
|
||||||
|
}else{
|
||||||
|
$t2 *= $t2;
|
||||||
|
$n2 = $t2 * $t2 * self::dot3D(self::$grad3[$gi2], $x2, $y2, $z2);
|
||||||
|
}
|
||||||
|
|
||||||
|
$t3 = 0.6 - $x3 * $x3 - $y3 * $y3 - $z3 * $z3;
|
||||||
|
if($t3 < 0){
|
||||||
|
$n3 = 0.0;
|
||||||
|
}else{
|
||||||
|
$t3 *= $t3;
|
||||||
|
$n3 = $t3 * $t3 * self::dot3D(self::$grad3[$gi3], $x3, $y3, $z3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add contributions from each corner to get the noise value.
|
||||||
|
// The result is scaled to stay just inside [-1,1]
|
||||||
|
return 32.0 * ($n0 + $n1 + $n2 + $n3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getNoise2D($x, $y){
|
||||||
|
$x += $this->offsetX;
|
||||||
|
$y += $this->offsetY;
|
||||||
|
|
||||||
|
// Skew the input space to determine which simplex cell we're in
|
||||||
|
$s = ($x + $y) * self::$F2; // Hairy factor for 2D
|
||||||
|
$i = self::floor($x + $s);
|
||||||
|
$j = self::floor($y + $s);
|
||||||
|
$t = ($i + $j) * self::$G2;
|
||||||
|
$X0 = $i - $t; // Unskew the cell origin back to (x,y) space
|
||||||
|
$Y0 = $j - $t;
|
||||||
|
$x0 = $x - $X0; // The x,y distances from the cell origin
|
||||||
|
$y0 = $y - $Y0;
|
||||||
|
|
||||||
|
// For the 2D case, the simplex shape is an equilateral triangle.
|
||||||
|
|
||||||
|
// Determine which simplex we are in.
|
||||||
|
if($x0 > $y0){
|
||||||
|
$i1 = 1;
|
||||||
|
$j1 = 0;
|
||||||
|
}// lower triangle, XY order: (0,0)->(1,0)->(1,1)
|
||||||
|
else{
|
||||||
|
$i1 = 0;
|
||||||
|
$j1 = 1;
|
||||||
|
}// upper triangle, YX order: (0,0)->(0,1)->(1,1)
|
||||||
|
|
||||||
|
// A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
|
||||||
|
// a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
|
||||||
|
// c = (3-sqrt(3))/6
|
||||||
|
|
||||||
|
$x1 = $x0 - $i1 + self::$G2; // Offsets for middle corner in (x,y) unskewed coords
|
||||||
|
$y1 = $y0 - $j1 + self::$G2;
|
||||||
|
$x2 = $x0 + self::$G22; // Offsets for last corner in (x,y) unskewed coords
|
||||||
|
$y2 = $y0 + self::$G22;
|
||||||
|
|
||||||
|
// Work out the hashed gradient indices of the three simplex corners
|
||||||
|
$ii = $i & 255;
|
||||||
|
$jj = $j & 255;
|
||||||
|
$gi0 = $this->perm[$ii + $this->perm[$jj]] % 12;
|
||||||
|
$gi1 = $this->perm[$ii + $i1 + $this->perm[$jj + $j1]] % 12;
|
||||||
|
$gi2 = $this->perm[$ii + 1 + $this->perm[$jj + 1]] % 12;
|
||||||
|
|
||||||
|
// Calculate the contribution from the three corners
|
||||||
|
$t0 = 0.5 - $x0 * $x0 - $y0 * $y0;
|
||||||
|
if($t0 < 0){
|
||||||
|
$n0 = 0.0;
|
||||||
|
}else{
|
||||||
|
$t0 *= $t0;
|
||||||
|
$n0 = $t0 * $t0 * self::dot2D(self::$grad3[$gi0], $x0, $y0); // (x,y) of grad3 used for 2D gradient
|
||||||
|
}
|
||||||
|
|
||||||
|
$t1 = 0.5 - $x1 * $x1 - $y1 * $y1;
|
||||||
|
if($t1 < 0){
|
||||||
|
$n1 = 0.0;
|
||||||
|
}else{
|
||||||
|
$t1 *= $t1;
|
||||||
|
$n1 = $t1 * $t1 * self::dot2D(self::$grad3[$gi1], $x1, $y1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$t2 = 0.5 - $x2 * $x2 - $y2 * $y2;
|
||||||
|
if($t2 < 0){
|
||||||
|
$n2 = 0.0;
|
||||||
|
}else{
|
||||||
|
$t2 *= $t2;
|
||||||
|
$n2 = $t2 * $t2 * self::dot2D(self::$grad3[$gi2], $x2, $y2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add contributions from each corner to get the noise value.
|
||||||
|
// The result is scaled to return values in the interval [-1,1].
|
||||||
|
return 70.0 * ($n0 + $n1 + $n2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes and returns the 4D simplex noise for the given coordinates in
|
||||||
|
* 4D space
|
||||||
|
*
|
||||||
|
* @param x X coordinate
|
||||||
|
* @param y Y coordinate
|
||||||
|
* @param z Z coordinate
|
||||||
|
* @param w W coordinate
|
||||||
|
* @return Noise at given location, from range -1 to 1
|
||||||
|
*/
|
||||||
|
/*public function getNoise4D(x, y, z, w){
|
||||||
|
x += offsetX;
|
||||||
|
y += offsetY;
|
||||||
|
z += offsetZ;
|
||||||
|
w += offsetW;
|
||||||
|
|
||||||
|
n0, n1, n2, n3, n4; // Noise contributions from the five corners
|
||||||
|
|
||||||
|
// Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in
|
||||||
|
s = (x + y + z + w) * self::$F4; // Factor for 4D skewing
|
||||||
|
i = floor(x + s);
|
||||||
|
j = floor(y + s);
|
||||||
|
k = floor(z + s);
|
||||||
|
l = floor(w + s);
|
||||||
|
|
||||||
|
t = (i + j + k + l) * self::$G4; // Factor for 4D unskewing
|
||||||
|
X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space
|
||||||
|
Y0 = j - t;
|
||||||
|
Z0 = k - t;
|
||||||
|
W0 = l - t;
|
||||||
|
x0 = x - X0; // The x,y,z,w distances from the cell origin
|
||||||
|
y0 = y - Y0;
|
||||||
|
z0 = z - Z0;
|
||||||
|
w0 = w - W0;
|
||||||
|
|
||||||
|
// For the 4D case, the simplex is a 4D shape I won't even try to describe.
|
||||||
|
// To find out which of the 24 possible simplices we're in, we need to
|
||||||
|
// determine the magnitude ordering of x0, y0, z0 and w0.
|
||||||
|
// The method below is a good way of finding the ordering of x,y,z,w and
|
||||||
|
// then find the correct traversal order for the simplex we’re in.
|
||||||
|
// First, six pair-wise comparisons are performed between each possible pair
|
||||||
|
// of the four coordinates, and the results are used to add up binary bits
|
||||||
|
// for an integer index.
|
||||||
|
c1 = (x0 > y0) ? 32 : 0;
|
||||||
|
c2 = (x0 > z0) ? 16 : 0;
|
||||||
|
c3 = (y0 > z0) ? 8 : 0;
|
||||||
|
c4 = (x0 > w0) ? 4 : 0;
|
||||||
|
c5 = (y0 > w0) ? 2 : 0;
|
||||||
|
c6 = (z0 > w0) ? 1 : 0;
|
||||||
|
c = c1 + c2 + c3 + c4 + c5 + c6;
|
||||||
|
i1, j1, k1, l1; // The integer offsets for the second simplex corner
|
||||||
|
i2, j2, k2, l2; // The integer offsets for the third simplex corner
|
||||||
|
i3, j3, k3, l3; // The integer offsets for the fourth simplex corner
|
||||||
|
|
||||||
|
// simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order.
|
||||||
|
// Many values of c will never occur, since e.g. x>y>z>w makes x<z, y<w and x<w
|
||||||
|
// impossible. Only the 24 indices which have non-zero entries make any sense.
|
||||||
|
// We use a thresholding to set the coordinates in turn from the largest magnitude.
|
||||||
|
|
||||||
|
// The number 3 in the "simplex" array is at the position of the largest coordinate.
|
||||||
|
i1 = simplex[c][0] >= 3 ? 1 : 0;
|
||||||
|
j1 = simplex[c][1] >= 3 ? 1 : 0;
|
||||||
|
k1 = simplex[c][2] >= 3 ? 1 : 0;
|
||||||
|
l1 = simplex[c][3] >= 3 ? 1 : 0;
|
||||||
|
|
||||||
|
// The number 2 in the "simplex" array is at the second largest coordinate.
|
||||||
|
i2 = simplex[c][0] >= 2 ? 1 : 0;
|
||||||
|
j2 = simplex[c][1] >= 2 ? 1 : 0;
|
||||||
|
k2 = simplex[c][2] >= 2 ? 1 : 0;
|
||||||
|
l2 = simplex[c][3] >= 2 ? 1 : 0;
|
||||||
|
|
||||||
|
// The number 1 in the "simplex" array is at the second smallest coordinate.
|
||||||
|
i3 = simplex[c][0] >= 1 ? 1 : 0;
|
||||||
|
j3 = simplex[c][1] >= 1 ? 1 : 0;
|
||||||
|
k3 = simplex[c][2] >= 1 ? 1 : 0;
|
||||||
|
l3 = simplex[c][3] >= 1 ? 1 : 0;
|
||||||
|
|
||||||
|
// The fifth corner has all coordinate offsets = 1, so no need to look that up.
|
||||||
|
|
||||||
|
x1 = x0 - i1 + self::$G4; // Offsets for second corner in (x,y,z,w) coords
|
||||||
|
y1 = y0 - j1 + self::$G4;
|
||||||
|
z1 = z0 - k1 + self::$G4;
|
||||||
|
w1 = w0 - l1 + self::$G4;
|
||||||
|
|
||||||
|
x2 = x0 - i2 + self::$G42; // Offsets for third corner in (x,y,z,w) coords
|
||||||
|
y2 = y0 - j2 + self::$G42;
|
||||||
|
z2 = z0 - k2 + self::$G42;
|
||||||
|
w2 = w0 - l2 + self::$G42;
|
||||||
|
|
||||||
|
x3 = x0 - i3 + self::$G43; // Offsets for fourth corner in (x,y,z,w) coords
|
||||||
|
y3 = y0 - j3 + self::$G43;
|
||||||
|
z3 = z0 - k3 + self::$G43;
|
||||||
|
w3 = w0 - l3 + self::$G43;
|
||||||
|
|
||||||
|
x4 = x0 + self::$G44; // Offsets for last corner in (x,y,z,w) coords
|
||||||
|
y4 = y0 + self::$G44;
|
||||||
|
z4 = z0 + self::$G44;
|
||||||
|
w4 = w0 + self::$G44;
|
||||||
|
|
||||||
|
// Work out the hashed gradient indices of the five simplex corners
|
||||||
|
ii = i & 255;
|
||||||
|
jj = j & 255;
|
||||||
|
kk = k & 255;
|
||||||
|
ll = l & 255;
|
||||||
|
|
||||||
|
gi0 = $this->perm[ii + $this->perm[jj + $this->perm[kk + $this->perm[ll]]]] % 32;
|
||||||
|
gi1 = $this->perm[ii + i1 + $this->perm[jj + j1 + $this->perm[kk + k1 + $this->perm[ll + l1]]]] % 32;
|
||||||
|
gi2 = $this->perm[ii + i2 + $this->perm[jj + j2 + $this->perm[kk + k2 + $this->perm[ll + l2]]]] % 32;
|
||||||
|
gi3 = $this->perm[ii + i3 + $this->perm[jj + j3 + $this->perm[kk + k3 + $this->perm[ll + l3]]]] % 32;
|
||||||
|
gi4 = $this->perm[ii + 1 + $this->perm[jj + 1 + $this->perm[kk + 1 + $this->perm[ll + 1]]]] % 32;
|
||||||
|
|
||||||
|
// Calculate the contribution from the five corners
|
||||||
|
t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0;
|
||||||
|
if(t0 < 0){
|
||||||
|
n0 = 0.0;
|
||||||
|
}else{
|
||||||
|
t0 *= t0;
|
||||||
|
n0 = t0 * t0 * dot(grad4[gi0], x0, y0, z0, w0);
|
||||||
|
}
|
||||||
|
|
||||||
|
t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1;
|
||||||
|
if(t1 < 0){
|
||||||
|
n1 = 0.0;
|
||||||
|
}else{
|
||||||
|
t1 *= t1;
|
||||||
|
n1 = t1 * t1 * dot(grad4[gi1], x1, y1, z1, w1);
|
||||||
|
}
|
||||||
|
|
||||||
|
t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2;
|
||||||
|
if(t2 < 0){
|
||||||
|
n2 = 0.0;
|
||||||
|
}else{
|
||||||
|
t2 *= t2;
|
||||||
|
n2 = t2 * t2 * dot(grad4[gi2], x2, y2, z2, w2);
|
||||||
|
}
|
||||||
|
|
||||||
|
t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3;
|
||||||
|
if(t3 < 0){
|
||||||
|
n3 = 0.0;
|
||||||
|
}else{
|
||||||
|
t3 *= t3;
|
||||||
|
n3 = t3 * t3 * dot(grad4[gi3], x3, y3, z3, w3);
|
||||||
|
}
|
||||||
|
|
||||||
|
t4 = 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4;
|
||||||
|
if(t4 < 0){
|
||||||
|
n4 = 0.0;
|
||||||
|
}else{
|
||||||
|
t4 *= t4;
|
||||||
|
n4 = t4 * t4 * dot(grad4[gi4], x4, y4, z4, w4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sum up and scale the result to cover the range [-1,1]
|
||||||
|
return 27.0 * (n0 + n1 + n2 + n3 + n4);
|
||||||
|
}*/
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user