From 579175b3bc1a68857f9659aa54a78876650a1af2 Mon Sep 17 00:00:00 2001 From: Shoghi Cervantes Date: Mon, 10 Jun 2013 17:11:04 +0200 Subject: [PATCH] Ore Generation --- src/world/generator/LevelGenerator.php | 4 +- src/world/generator/Populator.php | 30 +++++++ src/world/generator/SuperflatGenerator.php | 68 ++++++-------- src/world/generator/TemporalGenerator.php | 4 +- src/world/generator/WorldGenerator.php | 12 ++- src/world/generator/object/OreObject.php | 88 +++++++++++++++++++ src/world/generator/object/OreType.php | 38 ++++++++ src/world/generator/object/PondObject.php | 43 +++++++++ .../generator/object/tree/SmallTreeObject.php | 2 +- .../populator/MineshaftPopulator.php | 41 +++++++++ .../generator/populator/OrePopulator.php | 49 +++++++++++ .../generator/populator/PondPopulator.php | 57 ++++++++++++ 12 files changed, 386 insertions(+), 50 deletions(-) create mode 100644 src/world/generator/Populator.php create mode 100644 src/world/generator/object/OreObject.php create mode 100644 src/world/generator/object/OreType.php create mode 100644 src/world/generator/object/PondObject.php create mode 100644 src/world/generator/populator/MineshaftPopulator.php create mode 100644 src/world/generator/populator/OrePopulator.php create mode 100644 src/world/generator/populator/PondPopulator.php diff --git a/src/world/generator/LevelGenerator.php b/src/world/generator/LevelGenerator.php index 0d71ae886..821d3e83b 100644 --- a/src/world/generator/LevelGenerator.php +++ b/src/world/generator/LevelGenerator.php @@ -30,9 +30,9 @@ interface LevelGenerator{ public function init(Level $level, Random $random); - public function generateChunk($chunkX, $chunkY, $chunkZ); + public function generateChunk($chunkX, $chunkZ); - public function populateChunk($chunkX, $chunkY, $chunkZ); + public function populateChunk($chunkX, $chunkZ); public function populateLevel(); diff --git a/src/world/generator/Populator.php b/src/world/generator/Populator.php new file mode 100644 index 000000000..3aa5bfc0c --- /dev/null +++ b/src/world/generator/Populator.php @@ -0,0 +1,30 @@ +preset = "2;7,59x1,3x3,2;1;spawn(radius=10 block=89),decoration(treecount=80 grasscount=120)"; @@ -40,6 +40,24 @@ class SuperflatGenerator implements LevelGenerator{ }else{ $this->parsePreset($this->preset); } + if(isset($this->options["decoration"])){ + $ores = new OrePopulator(); + $ores->setOreTypes(array( + new OreType(new DirtBlock(), 20, 32, 0, 128), + new OreType(new GravelBlock(), 10, 16, 0, 128), + new OreType(new CoalOreBlock(), 20, 16, 0, 128), + new OreType(New IronOreBlock(), 20, 8, 0, 64), + new OreType(new RedstoneOreBlock(), 8, 7, 0, 16), + new OreType(new LapisOreBlock(), 1, 6, 0, 32), + new OreType(new GoldOreBlock(), 2, 8, 0, 32), + new OreType(new DiamondOreBlock(), 1, 7, 0, 16), + )); + $this->populators[] = $ores; + } + + /*if(isset($this->options["mineshaft"])){ + $this->populators[] = new MineshaftPopulator(isset($this->options["mineshaft"]["chance"]) ? floatval($this->options["mineshaft"]["chance"]) : 0.01); + }*/ } public function parsePreset($preset){ @@ -107,48 +125,16 @@ class SuperflatGenerator implements LevelGenerator{ $this->random = $random; } - public function generateChunk($chunkX, $chunkY, $chunkZ){ - $this->level->setMiniChunk($chunkX, $chunkZ, $chunkY, $this->chunks[$chunkY]); + public function generateChunk($chunkX, $chunkZ){ + for($Y = 0; $Y < 8; ++$Y){ + $this->level->setMiniChunk($chunkX, $chunkZ, $Y, $this->chunks[$Y]); + } } - public function populateChunk($chunkX, $chunkY, $chunkZ){ - $this->random->setSeed((int) ($chunkX * 0xdead + $chunkZ * 0xbeef)); - if(isset($this->options["decoration"])){ - //Ore spawning algorithm - $ores = array( - array(new CoalOreBlock(), 1, 70, 143), - array(new IronOreBlock(), 1, 64, 77), - array(new LapisOreBlock(), 1, 31, 3), - array(new GoldOreBlock(), 1, 32, 8), - array(new DiamondOreBlock(), 1, 14, 3), - array(new RedstoneOreBlock(), 1, 14, 25), - ); - $minX = $chunkX << 4; - $maxX = $minX + 16; - $minZ = $chunkZ << 4; - $maxZ = $minZ + 16; - $y = $chunkY << 4; - - foreach($ores as $data){ - $minY = max($y, $data[1]); - $maxY = min($y + 16, min($this->floorLevel - 1, $data[2])); - if($minY > ($y + 16) or $maxY < $y){ - continue; - } - $nRange = $data[2] - $data[1] + 1; - $factor = ($maxY - $minY + 1) / $nRange; - $count = (int) ($this->random->nextRange($data[3] - 1, $data[3] + 1) * $factor); - for($c = 0; $c < $count; ++$c){ - $block = $this->level->getBlock(new Vector3( - $this->random->nextRange($minX, $maxX), - $this->random->nextRange($minY, $maxY), - $this->random->nextRange($minZ, $maxZ) - )); - if($block->getID() === STONE){ - $this->level->setBlockRaw($block, $data[0]); - } - } - } + public function populateChunk($chunkX, $chunkZ){ + foreach($this->populators as $populator){ + $this->random->setSeed((int) ($chunkX * 0xdead + $chunkZ * 0xbeef)); + $populator->populate($this->level, $chunkX, $chunkZ, $this->random); } } diff --git a/src/world/generator/TemporalGenerator.php b/src/world/generator/TemporalGenerator.php index 6e0e23cb1..97370693c 100644 --- a/src/world/generator/TemporalGenerator.php +++ b/src/world/generator/TemporalGenerator.php @@ -52,11 +52,11 @@ class TemporalGenerator implements LevelGenerator{ $this->level->setSeed(TemporalGenerator::$levels[$this->index][0]); } - public function generateChunk($chunkX, $chunkY, $chunkZ){ + public function generateChunk($chunkX, $chunkZ){ } - public function populateChunk($chunkX, $chunkY, $chunkZ){ + public function populateChunk($chunkX, $chunkZ){ } diff --git a/src/world/generator/WorldGenerator.php b/src/world/generator/WorldGenerator.php index fba94a8bf..dde0b51cd 100644 --- a/src/world/generator/WorldGenerator.php +++ b/src/world/generator/WorldGenerator.php @@ -55,15 +55,19 @@ class WorldGenerator{ $this->generator->init($this->level, $this->random); for($Z = 0; $Z < $this->width; ++$Z){ for($X = 0; $X < $this->width; ++$X){ - for($Y = 0; $Y < $this->height; ++$Y){ - $this->generator->generateChunk($X, $Y, $Z); - $this->generator->populateChunk($X, $Y, $Z); - } + $this->generator->generateChunk($X, $Z); } console("[NOTICE] Generating level ".ceil((($Z + 1)/$this->width) * 100)."%"); } console("[NOTICE] Populating level"); $this->generator->populateLevel(); + for($Z = 0; $Z < $this->width; ++$Z){ + for($X = 0; $X < $this->width; ++$X){ + $this->generator->populateChunk($X, $Z); + } + console("[NOTICE] Populating level ".ceil((($Z + 1)/$this->width) * 100)."%"); + } + $this->level->setSpawn($this->generator->getSpawn()); $this->level->save(true, true); } diff --git a/src/world/generator/object/OreObject.php b/src/world/generator/object/OreObject.php new file mode 100644 index 000000000..ac7b74697 --- /dev/null +++ b/src/world/generator/object/OreObject.php @@ -0,0 +1,88 @@ +type = $type; + $this->random = $random; + } + + public function getType(){ + return $this->type; + } + + public function canPlaceObject(Level $level, Vector3 $pos){ + return ($level->getBlock($pos)->getID() !== AIR); + } + + public function placeObject(Level $level, Vector3 $pos){ + $clusterSize = (int) $this->type->clusterSize; + $angle = $this->random->nextFloat() * pi(); + $offset = VectorMath::getDirection2D($angle)->multiply($clusterSize)->divide(8); + $x1 = $pos->x + 8 + $offset->x; + $x2 = $pos->x + 8 - $offset->x; + $z1 = $pos->z + 8 + $offset->y; + $z2 = $pos->z + 8 - $offset->y; + $y1 = $pos->y + $this->random->nextRange(0, 3) + 2; + $y2 = $pos->y + $this->random->nextRange(0, 3) + 2; + for($count = 0; $count <= $clusterSize; ++$count){ + $seedX = $x1 + ($x2 - $x1) * $count / $clusterSize; + $seedY = $y1 + ($y2 - $y1) * $count / $clusterSize; + $seedZ = $z1 + ($z2 - $z1) * $count / $clusterSize; + $size = ((sin($count * (pi() / $clusterSize)) + 1) * $this->random->nextFloat() * $clusterSize / 16 + 1) / 2; + + $startX = (int) ($seedX - $size); + $startY = (int) ($seedY - $size); + $startZ = (int) ($seedZ - $size); + $endX = (int) ($seedX + $size); + $endY = (int) ($seedY + $size); + $endZ = (int) ($seedZ + $size); + + for($x = $startX; $x <= $endX; ++$x){ + $sizeX = pow(($x + 0.5 - $seedX) / $size, 2); + if($sizeX < 1){ + for($y = $startY; $y <= $endY; ++$y){ + $sizeY = pow(($y + 0.5 - $seedY) / $size, 2); + if($y > 0 and ($sizeX + $sizeY) < 1){ + for($z = $startZ; $z <= $endZ; ++$z){ + $sizeZ = pow(($z + 0.5 - $seedZ) / $size, 2); + $v = new Vector3($x, $y, $z); + if(($sizeX + $sizeY + $sizeZ) < 1 and $level->getBlock($v)->getID() === STONE){ + $level->setBlockRaw($v, $this->type->material); + } + } + } + } + } + } + } + } + +} \ No newline at end of file diff --git a/src/world/generator/object/OreType.php b/src/world/generator/object/OreType.php new file mode 100644 index 000000000..2f4b25e42 --- /dev/null +++ b/src/world/generator/object/OreType.php @@ -0,0 +1,38 @@ +material = $material; + $this->clusterCount = (int) $clusterCount; + $this->clusterSize = (int) $clusterSize; + $this->maxHeight = (int) $maxHeight; + $this->minHeight = (int) $minHeight; + } +} \ No newline at end of file diff --git a/src/world/generator/object/PondObject.php b/src/world/generator/object/PondObject.php new file mode 100644 index 000000000..051db126d --- /dev/null +++ b/src/world/generator/object/PondObject.php @@ -0,0 +1,43 @@ +type = $type; + $this->random = $random; + } + + public function canPlaceObject(Level $level, Vector3 $pos){ + } + + public function placeObject(Level $level, Vector3 $pos){ + } + +} \ No newline at end of file diff --git a/src/world/generator/object/tree/SmallTreeObject.php b/src/world/generator/object/tree/SmallTreeObject.php index e24dc5751..c81f428d8 100644 --- a/src/world/generator/object/tree/SmallTreeObject.php +++ b/src/world/generator/object/tree/SmallTreeObject.php @@ -26,7 +26,7 @@ the Free Software Foundation, either version 3 of the License, or */ /***REM_START***/ -require_once("src/world/generator/object/tree/TreeObject.php"); +require_once("TreeObject.php"); /***REM_END***/ class SmallTreeObject extends TreeObject{ diff --git a/src/world/generator/populator/MineshaftPopulator.php b/src/world/generator/populator/MineshaftPopulator.php new file mode 100644 index 000000000..c9425eac6 --- /dev/null +++ b/src/world/generator/populator/MineshaftPopulator.php @@ -0,0 +1,41 @@ +nextRange(0, MineshaftPopulator::$ODD) === 0){ + //$mineshaft = new Mineshaft($random); + } + } + +} \ No newline at end of file diff --git a/src/world/generator/populator/OrePopulator.php b/src/world/generator/populator/OrePopulator.php new file mode 100644 index 000000000..17fb9e936 --- /dev/null +++ b/src/world/generator/populator/OrePopulator.php @@ -0,0 +1,49 @@ +oreTypes as $type){ + $ore = new OreObject($random, $type); + for($i = 0; $i < $ore->type->clusterCount; ++$i){ + $v = new Vector3( + $random->nextRange($chunkX << 4, ($chunkX << 4) + 16), + $random->nextRange($ore->type->minHeight, $ore->type->maxHeight), + $random->nextRange($chunkZ << 4, ($chunkZ << 4) + 16) + ); + if($ore->canPlaceObject($level, $v)){ + $ore->placeObject($level, $v); + } + } + } + } + + public function setOreTypes(array $types){ + $this->oreTypes = $types; + } +} \ No newline at end of file diff --git a/src/world/generator/populator/PondPopulator.php b/src/world/generator/populator/PondPopulator.php new file mode 100644 index 000000000..9f99bcaee --- /dev/null +++ b/src/world/generator/populator/PondPopulator.php @@ -0,0 +1,57 @@ +nextRange(0, $this->waterOdd) === 0){ + $v = new Vector3( + $random->nextRange($chunkX << 4, ($chunkX << 4) + 16), + $random->nextRange(0, 128), + $random->nextRange($chunkZ << 4, ($chunkZ << 4) + 16), + ); + $pond = new PondObject($random, new WaterBlock()); + if($pond->canPlaceObject($level, $v)){ + $pond->placeObject($level, $v); + } + } + } + + public function setWaterOdd($waterOdd){ + $this->waterOdd = $waterOdd; + } + + public function setLavaOdd($lavaOdd){ + $this->lavaOdd = $lavaOdd; + } + + public function setLavaSurfaceOdd($lavaSurfaceOdd){ + $this->lavaSurfaceOdd = $lavaSurfaceOdd; + } +} \ No newline at end of file