diff --git a/src/pmf/Level.php b/src/pmf/PMFLevel.php
similarity index 68%
rename from src/pmf/Level.php
rename to src/pmf/PMFLevel.php
index e4c8824fd..657019b09 100644
--- a/src/pmf/Level.php
+++ b/src/pmf/PMFLevel.php
@@ -19,16 +19,17 @@
*
*/
-define("PMF_CURRENT_LEVEL_VERSION", 0x00);
-
class PMFLevel extends PMF{
- private $levelData = array();
- private $locationTable = array();
+ const VERSION = 0x01;
+ const DEFLATE_LEVEL = 9;
+
+ public $level;
+ public $levelData = array();
public $isLoaded = true;
- private $log = 4;
- private $payloadOffset = 0;
private $chunks = array();
private $chunkChange = array();
+ private $chunkInfo = array();
+ public $isGenerating = false;
public function getData($index){
if(!isset($this->levelData[$index])){
@@ -46,8 +47,8 @@ class PMFLevel extends PMF{
}
public function close(){
- $chunks = null;
- unset($chunks, $chunkChange, $locationTable);
+ $this->chunks = null;
+ unset($this->chunks, $this->chunkChange, $this->chunkInfo, $this->level);
parent::close();
}
@@ -57,7 +58,6 @@ class PMFLevel extends PMF{
$this->levelData = $blank;
$this->createBlank();
$this->isLoaded = true;
- $this->log = (int) ((string) log($this->levelData["width"], 2));
}else{
if($this->load($file) !== false){
$this->parseInfo();
@@ -65,7 +65,6 @@ class PMFLevel extends PMF{
$this->isLoaded = false;
}else{
$this->isLoaded = true;
- $this->log = (int) ((string) log($this->levelData["width"], 2));
}
}else{
$this->isLoaded = false;
@@ -73,8 +72,8 @@ class PMFLevel extends PMF{
}
}
- public function saveData($locationTable = true){
- $this->levelData["version"] = PMF_CURRENT_LEVEL_VERSION;
+ public function saveData(){
+ $this->levelData["version"] = PMFLevel::VERSION;
@ftruncate($this->fp, 5);
$this->seek(5);
$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["spawnY"]));
$this->write(Utils::writeFloat($this->levelData["spawnZ"]));
- $this->write(chr($this->levelData["width"]));
$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->payloadOffset = ftell($this->fp);
-
- if($locationTable !== false){
- $this->writeLocationTable();
- }
}
private function createBlank(){
$this->saveData(false);
- $this->locationTable = array();
- $cnt = pow($this->levelData["width"], 2);
@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")){
$entities = new Config(dirname($this->file)."/entities.yml", CONFIG_YAML);
$entities->save();
@@ -127,7 +110,7 @@ class PMFLevel extends PMF{
}
$this->seek(5);
$this->levelData["version"] = ord($this->read(1));
- if($this->levelData["version"] > PMF_CURRENT_LEVEL_VERSION){
+ if($this->levelData["version"] > PMFLevel::VERSION){
return 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["spawnY"] = 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));
- if(($this->levelData["width"] !== 16 and $this->levelData["width"] !== 32) or $this->levelData["height"] !== 8){
+ if($this->levelData["height"] !== 8){
return false;
}
- $lastseek = ftell($this->fp);
- if(($len = $this->read(2)) === false or ($this->levelData["extra"] = @gzinflate($this->read(Utils::readShort($len, false)))) === false){ //Corruption protection
- 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);
+ if($this->levelData["version"] === 0){
+ $this->read(1);
}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){
- $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);
+ private function upgrade_From0_To1(){
for($index = 0; $index < $cnt; ++$index){
$this->chunks[$index] = false;
$this->chunkChange[$index] = false;
- $this->locationTable[$index] = array(
+ $locationTable[$index] = array(
0 => Utils::readShort($this->read(2)), //16 bit flags
);
}
- return true;
}
- private function writeLocationTable(){
- $cnt = pow($this->levelData["width"], 2);
- @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 getIndex($X, $Z){
+ return ($Z << 16) + $X;
+ }
+
+ public static function getXZ($index, &$X = null, &$Z = null){
+ $Z = $index >> 16;
+ $X = $index & 0xFFFF;
+ return array($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){
$X = (int) $X;
$Z = (int) $Z;
- $index = $this->getIndex($X, $Z);
+ $index = self::getIndex($X, $Z);
if($this->isChunkLoaded($X, $Z)){
return true;
- }elseif(!isset($this->locationTable[$index])){
+ }
+ $path = $this->getChunkPath($X, $Z);
+ if(!file_exists($path) and $this->generateChunk($X, $Z) === false){
return false;
}
- $info = $this->locationTable[$index];
- $this->seek($info[0]);
-
- $chunk = @gzopen($this->getChunkPath($X, $Z), "rb");
+ $chunk = @gzopen($path, "rb");
if($chunk === false){
return false;
}
+ $this->chunkInfo[$index] = array(
+ 0 => ord(gzread($chunk, 1)),
+ );
$this->chunks[$index] = array();
$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;
- if(($info[0] & $t) === $t){
+ if(($this->chunkInfo[$index][0] & $t) === $t){
// 4096 + 2048 + 2048, Block Data, Meta, Light
if(strlen($this->chunks[$index][$Y] = gzread($chunk, 8192)) < 8192){
console("[NOTICE] Empty corrupt chunk detected [$X,$Z,:$Y], recovering contents");
@@ -241,15 +215,16 @@ class PMFLevel extends PMF{
}elseif($save !== false){
$this->saveChunk($X, $Z);
}
- $index = $this->getIndex($X, $Z);
+ $index = self::getIndex($X, $Z);
$this->chunks[$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;
}
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){
return false;
}
@@ -257,7 +232,7 @@ class PMFLevel extends PMF{
}
protected function isMiniChunkEmpty($X, $Z, $Y){
- $index = $this->getIndex($X, $Z);
+ $index = self::getIndex($X, $Z);
if($this->chunks[$index][$Y] !== false){
if(substr_count($this->chunks[$index][$Y], "\x00") < 8192){
return false;
@@ -270,11 +245,11 @@ class PMFLevel extends PMF{
if($this->isChunkLoaded($X, $Z) === false){
return false;
}
- $index = $this->getIndex($X, $Z);
+ $index = self::getIndex($X, $Z);
$this->chunks[$index][$Y] = str_repeat("\x00", 8192);
$this->chunkChange[$index][-1] = true;
$this->chunkChange[$index][$Y] = 8192;
- $this->locationTable[$index][0] |= 1 << $Y;
+ $this->chunkInfo[$index][0] |= 1 << $Y;
return true;
}
@@ -282,36 +257,61 @@ class PMFLevel extends PMF{
if($this->loadChunk($X, $Z) === false){
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){
return str_repeat("\x00", 8192);
}
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){
- if($this->isChunkLoaded($X, $Z) === false){
+ if($this->isGenerating === true){
+ $this->initCleanChunk($X, $Z);
+ }elseif($this->isChunkLoaded($X, $Z) === false){
$this->loadChunk($X, $Z);
}
if(strlen($data) !== 8192){
return false;
}
- $index = $this->getIndex($X, $Z);
+ $index = self::getIndex($X, $Z);
$this->chunks[$index][$Y] = (string) $data;
$this->chunkChange[$index][-1] = true;
$this->chunkChange[$index][$Y] = 8192;
- $this->locationTable[$index][0] |= 1 << $Y;
+ $this->chunkInfo[$index][0] |= 1 << $Y;
return true;
}
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;
}
$X = $x >> 4;
$Z = $z >> 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);
$aZ = $z - ($Z << 4);
$aY = $y - ($Y << 4);
@@ -320,17 +320,17 @@ class PMFLevel extends PMF{
}
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;
}
$X = $x >> 4;
$Z = $z >> 4;
$Y = $y >> 4;
$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;
}
- $index = $this->getIndex($X, $Z);
$aX = $x - ($X << 4);
$aZ = $z - ($Z << 4);
$aY = $y - ($Y << 4);
@@ -345,13 +345,16 @@ class PMFLevel extends PMF{
}
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;
}
$X = $x >> 4;
$Z = $z >> 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);
$aZ = $z - ($Z << 4);
$aY = $y - ($Y << 4);
@@ -365,17 +368,17 @@ class PMFLevel extends PMF{
}
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;
}
$X = $x >> 4;
$Z = $z >> 4;
$Y = $y >> 4;
$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;
}
- $index = $this->getIndex($X, $Z);
$aX = $x - ($X << 4);
$aZ = $z - ($Z << 4);
$aY = $y - ($Y << 4);
@@ -404,10 +407,10 @@ class PMFLevel extends PMF{
$X = $x >> 4;
$Z = $z >> 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);
}
- $index = $this->getIndex($X, $Z);
+ $index = self::getIndex($X, $Z);
if(!isset($this->chunks[$index]) or $this->chunks[$index] === false){
if($this->loadChunk($X, $Z) === false){
return array(AIR, 0);
@@ -429,15 +432,15 @@ class PMFLevel extends PMF{
}
public function setBlock($x, $y, $z, $block, $meta = 0){
+ if($y > 127 or $y < 0){
+ return false;
+ }
$X = $x >> 4;
$Z = $z >> 4;
$Y = $y >> 4;
$block &= 0xFF;
$meta &= 0x0F;
- if($X >= 32 or $Z >= 32 or $Y >= $this->levelData["height"] or $y < 0){
- return false;
- }
- $index = $this->getIndex($X, $Z);
+ $index = self::getIndex($X, $Z);
if(!isset($this->chunks[$index]) or $this->chunks[$index] === false){
if($this->loadChunk($X, $Z) === false){
return false;
@@ -486,35 +489,46 @@ class PMFLevel extends PMF{
public function saveChunk($X, $Z){
$X = (int) $X;
$Z = (int) $Z;
- if(!$this->isChunkLoaded($X, $Z)){
+ if($this->isGenerating === true){
+ $this->initCleanChunk($X, $Z);
+ }elseif(!$this->isChunkLoaded($X, $Z)){
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
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;
- 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))){
- gzwrite($chunk, $this->chunks[$index][$Y]);
$bitmap |= 1 << $Y;
}else{
$this->chunks[$index][$Y] = false;
}
$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->locationTable[$index][0] = $bitmap;
- $this->seek($this->payloadOffset + ($index << 1));
- $this->write(Utils::writeShort($this->locationTable[$index][0]));
+ $this->chunkInfo[$index][0] = $bitmap;
return true;
}
public function doSaveRound(){
foreach($this->chunks as $index => $chunk){
- $this->getXZ($index, $X, $Z);
+ self::getXZ($index, $X, $Z);
$this->saveChunk($X, $Z);
}
}
diff --git a/src/pmf/Plugin.php b/src/pmf/PMFPlugin.php
similarity index 100%
rename from src/pmf/Plugin.php
rename to src/pmf/PMFPlugin.php
diff --git a/src/world/Level.php b/src/world/Level.php
index 84ff983be..05414e943 100644
--- a/src/world/Level.php
+++ b/src/world/Level.php
@@ -21,11 +21,12 @@
class 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){
$this->server = ServerAPI::request();
$this->level = $level;
+ $level->level = $this;
$this->level->level = $this;
$this->entities = $entities;
$this->tiles = $tiles;
@@ -40,6 +41,17 @@ class Level{
$this->usedChunks = array();
$this->changedBlocks = 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(){
@@ -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(){
if(isset($this->level)){
$this->save(false, false);
diff --git a/src/world/generator/LevelGenerator.php b/src/world/generator/LevelGenerator.php
index 5da986456..939d356f3 100644
--- a/src/world/generator/LevelGenerator.php
+++ b/src/world/generator/LevelGenerator.php
@@ -20,7 +20,8 @@
*/
interface LevelGenerator{
- public function __construct(array $options = array());
+
+ public function __construct(array $settings = array());
public function init(Level $level, Random $random);
@@ -28,7 +29,9 @@ interface LevelGenerator{
public function populateChunk($chunkX, $chunkZ);
- public function populateLevel();
+ public function getSettings();
+
+ //public function populateLevel();
public function getSpawn();
}
\ No newline at end of file
diff --git a/src/world/generator/NormalGenerator.php b/src/world/generator/NormalGenerator.php
index ac6c3aa18..462154051 100644
--- a/src/world/generator/NormalGenerator.php
+++ b/src/world/generator/NormalGenerator.php
@@ -28,8 +28,9 @@ class NormalGenerator implements LevelGenerator{
private $populators = array();
private $level;
private $random;
- private $worldHeight = 64;
- private $waterHeight = 60;
+ private $worldHeight = 65;
+ private $waterHeight = 62;
+ private $noiseGenBase;
private $noiseGen1;
private $noiseGen2;
private $noiseGen3;
@@ -41,13 +42,17 @@ class NormalGenerator implements LevelGenerator{
}
+ public function getSettings(){
+ return array();
+ }
+
public function init(Level $level, Random $random){
$this->level = $level;
$this->random = $random;
$this->random->setSeed($this->level->getSeed());
- $this->noiseGen1 = new NoiseGeneratorPerlin($this->random, 4);
- $this->noiseGen2 = new NoiseGeneratorPerlin($this->random, 4);
- $this->noiseGen3 = new NoiseGeneratorPerlin($this->random, 4);
+ $this->noiseGenBase = new NoiseGeneratorSimplex($this->random, 4);
+ $this->noiseGen1 = new NoiseGeneratorSimplex($this->random, 8);
+ //$this->noiseGen2 = new NoiseGeneratorSimplex($this->random, 8);
$ores = new OrePopulator();
$ores->setOreTypes(array(
@@ -66,17 +71,18 @@ class NormalGenerator implements LevelGenerator{
public function generateChunk($chunkX, $chunkZ){
$this->random->setSeed(0xdeadbeef ^ ($chunkX << 8) ^ $chunkZ ^ $this->level->getSeed());
- $baseHeight = $this->worldHeight;// + * 35;
for($chunkY = 0; $chunkY < 8; ++$chunkY){
$chunk = "";
$startY = $chunkY << 4;
$endY = $startY + 16;
for($z = 0; $z < 16; ++$z){
for($x = 0; $x < 16; ++$x){
- $noise1 = $this->noiseGen1->noise2D($x + ($chunkX << 4), $z + ($chunkZ << 4), 0.6, 32, true) * 2;
- $noise2 = $this->noiseGen2->noise2D($x + ($chunkX << 4), $z + ($chunkZ << 4), 0.35, 64, true) * 15;
- $noise3 = $this->noiseGen3->noise2D($x + ($chunkX << 4), $z + ($chunkZ << 4), 0.1, 64, true) * 45;
- $height = (int) ($baseHeight + $noise1 + $noise2);
+ $noiseBase = $this->noiseGenBase->noise2D($x + ($chunkX << 4), $z + ($chunkZ << 4), 1/5, 16, true);
+ $noise1 = $this->noiseGen1->noise2D($x + ($chunkX << 4), $z + ($chunkZ << 4), 0.7, 25, true);
+ //$noise2 = $this->noiseGen2->noise2D($x + ($chunkX << 4), $z + ($chunkZ << 4), 0.8, 1);
+ //$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){
$diff = $height - $y;
if($y <= 4 and ($y === 0 or $this->random->nextFloat() < 0.75)){
@@ -86,13 +92,13 @@ class NormalGenerator implements LevelGenerator{
}elseif($diff > 0){
$chunk .= "\x03"; //dirt
}elseif($y <= $this->waterHeight){
- if($diff === 0){
+ if($y === $this->waterHeight and $diff === 0){
$chunk .= "\x0c"; //sand
}else{
$chunk .= "\x09"; //still_water
}
}elseif($diff === 0){
- $chunk .= "\x02"; //grass
+ $chunk .= $noise1 > 0 ? "\x02":"\x01"; //grass
}else{
$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){
foreach($this->populators as $populator){
$this->random->setSeed(0xdeadbeef ^ ($chunkX << 8) ^ $chunkZ ^ $this->level->getSeed());
diff --git a/src/world/generator/SuperflatGenerator.php b/src/world/generator/SuperflatGenerator.php
index 731c304df..2ac111337 100644
--- a/src/world/generator/SuperflatGenerator.php
+++ b/src/world/generator/SuperflatGenerator.php
@@ -26,6 +26,10 @@ require_once("LevelGenerator.php");
class SuperflatGenerator implements LevelGenerator{
private $level, $random, $structure, $chunks, $options, $floorLevel, $populators = array();
+ public function getSettings(){
+ return $this->options;
+ }
+
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->options = $options;
diff --git a/src/world/generator/TemporalGenerator.php b/src/world/generator/TemporalGenerator.php
deleted file mode 100644
index d03fde3db..000000000
--- a/src/world/generator/TemporalGenerator.php
+++ /dev/null
@@ -1,95 +0,0 @@
-level = $level;
- $this->random = $random;
- $this->index = mt_rand(0, count(TemporalGenerator::$levels) - 1);
- $this->world = new PocketChunkParser();
- $this->world->loadRaw(gzinflate(gzinflate(base64_decode(TemporalGenerator::$levels[$this->index][4]))), "");
- $this->world->loadMap();
- $this->level->setSeed(TemporalGenerator::$levels[$this->index][0]);
- }
-
- public function generateChunk($chunkX, $chunkZ){
-
- }
-
- public function populateChunk($chunkX, $chunkZ){
-
- }
-
- public function populateLevel(){
- for($Z = 0; $Z < 16; ++$Z){
- for($X = 0; $X < 16; ++$X){
- $chunk = array(
- 0 => "",
- 1 => "",
- 2 => "",
- 3 => "",
- 4 => "",
- 5 => "",
- 6 => "",
- 7 => ""
- );
- for($z = 0; $z < 16; ++$z){
- for($x = 0; $x < 16; ++$x){
- $block = $this->world->getChunkColumn($X, $Z, $x, $z, 0);
- $meta = $this->world->getChunkColumn($X, $Z, $x, $z, 1);
- for($Y = 0; $Y < 8; ++$Y){
- $chunk[$Y] .= substr($block, $Y << 4, 16);
- $chunk[$Y] .= substr($meta, $Y << 3, 8);
- $chunk[$Y] .= "\x00\x00\x00\x00\x00\x00\x00\x00";
- }
- }
- }
- foreach($chunk as $Y => $data){
- $this->level->setMiniChunk($X, $Z, $Y, $data);
- }
- }
- console("[NOTICE] Importing level ".ceil(($Z + 1)/0.16)."%");
- }
- $this->level->save(true, true);
- $this->world->map = null;
- $this->world = null;
- }
-
- public function getSpawn(){
- return new Vector3(TemporalGenerator::$levels[$this->index][1], TemporalGenerator::$levels[$this->index][2], TemporalGenerator::$levels[$this->index][3]);
- }
-}
\ No newline at end of file
diff --git a/src/world/generator/WorldGenerator.php b/src/world/generator/WorldGenerator.php
index 4b79bf8fb..cfca09041 100644
--- a/src/world/generator/WorldGenerator.php
+++ b/src/world/generator/WorldGenerator.php
@@ -21,10 +21,9 @@
class WorldGenerator{
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->random = new Random($this->seed);
- $this->width = (int) $width;
$this->height = (int) $height;
$this->path = DATA_PATH."worlds/".$name."/";
$this->generator = $generator;
@@ -35,9 +34,10 @@ class WorldGenerator{
"spawnX" => 128,
"spawnY" => 128,
"spawnZ" => 128,
- "extra" => "",
- "width" => $this->width,
- "height" => $this->height
+ "height" => $this->height,
+ "generator" => get_class($this->generator),
+ "generatorSettings" => $this->generator->getSettings(),
+ "extra" => ""
));
$entities = new Config($this->path."entities.yml", CONFIG_YAML);
$tiles = new Config($this->path."tiles.yml", CONFIG_YAML);
@@ -45,25 +45,33 @@ class WorldGenerator{
$this->level = new Level($level, $entities, $tiles, $blockUpdates, $name);
}
- public function generate(){
+ public function generate(){
+ $this->level->level->isGenerating = true;
$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);
}
- console("[NOTICE] Generating level ".ceil((($Z + 1)/$this->width) * 100)."%");
+ console("[NOTICE] Generating level".str_repeat(".", $i));
+ ++$i;
}
- console("[NOTICE] Populating level");
- $this->generator->populateLevel();
- for($Z = 0; $Z < $this->width; ++$Z){
- for($X = 0; $X < $this->width; ++$X){
+ //console("[NOTICE] Populating level");
+ //$this->generator->populateLevel();
+
+ $i = 0;
+ for($Z = 6; $Z <= 10; ++$Z){
+ for($X = 6; $X <= 10; ++$X){
$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->save(true, true);
+ $this->level->level->isGenerating = false;
}
public function close(){
diff --git a/src/world/generator/noise/NoiseGeneratorPerlin.php b/src/world/generator/noise/NoiseGeneratorPerlin.php
index 83341c094..8fcf6a34c 100644
--- a/src/world/generator/noise/NoiseGeneratorPerlin.php
+++ b/src/world/generator/noise/NoiseGeneratorPerlin.php
@@ -96,7 +96,7 @@ class NoiseGeneratorPerlin extends NoiseGenerator{
self::grad($this->perm[$BB + 1], $x - 1, $y - 1, $z - 1))));
}
- public function getNoise2D($x, $z){
- return $this->getNoise3D($x, 0, $z);
+ public function getNoise2D($x, $y){
+ return $this->getNoise3D($x, $y, 0);
}
}
\ No newline at end of file
diff --git a/src/world/generator/noise/NoiseGeneratorSimplex.php b/src/world/generator/noise/NoiseGeneratorSimplex.php
new file mode 100644
index 000000000..f01f108b4
--- /dev/null
+++ b/src/world/generator/noise/NoiseGeneratorSimplex.php
@@ -0,0 +1,437 @@
+
+ * This is a modified version of the freely published version in the paper by
+ * Stefan Gustavson at
+ *
+ * http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
+ */
+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{ // x0perm[$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= 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);
+ }*/
+}
\ No newline at end of file