Ore Generation

This commit is contained in:
Shoghi Cervantes 2013-06-10 17:11:04 +02:00
parent 808f5473d0
commit 579175b3bc
12 changed files with 386 additions and 50 deletions

View File

@ -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();

View File

@ -0,0 +1,30 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
*/
abstract class Populator{
public abstract function populate(Level $level, $chunkX, $chunkZ, Random $random);
}

View File

@ -30,7 +30,7 @@ require_once("LevelGenerator.php");
/***REM_END***/
class SuperflatGenerator implements LevelGenerator{
private $level, $random, $structure, $chunks, $options, $floorLevel;
private $level, $random, $structure, $chunks, $options, $floorLevel, $populators = array();
public function __construct(array $options = array()){
$this->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);
}
}

View File

@ -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){
}

View File

@ -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);
}

View File

@ -0,0 +1,88 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
*/
class OreObject{
private $random;
public $type;
public function __construct(Random $random, OreType $type){
$this->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);
}
}
}
}
}
}
}
}
}

View File

@ -0,0 +1,38 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
*/
class OreType{
public $material, $clusterCount, $clusterSize, $maxHeight, $minHeight;
public function __construct(Block $material, $clusterCount, $clusterSize, $minHeight, $maxHeight){
$this->material = $material;
$this->clusterCount = (int) $clusterCount;
$this->clusterSize = (int) $clusterSize;
$this->maxHeight = (int) $maxHeight;
$this->minHeight = (int) $minHeight;
}
}

View File

@ -0,0 +1,43 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
*/
class PondObject{
private $random;
public $type;
public function __construct(Random $random, Block $type){
$this->type = $type;
$this->random = $random;
}
public function canPlaceObject(Level $level, Vector3 $pos){
}
public function placeObject(Level $level, Vector3 $pos){
}
}

View File

@ -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{

View File

@ -0,0 +1,41 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
*/
class MineshaftPopulator extends Populator{
private static $DISTANCE = 256;
private static $VARIATION = 16;
private static $ODD = 3;
private static $BASE_Y = 35;
private static $RAND_Y = 11;
public function populate(Level $level, $chunkX, $chunkZ, Random $random){
if($random->nextRange(0, MineshaftPopulator::$ODD) === 0){
//$mineshaft = new Mineshaft($random);
}
}
}

View File

@ -0,0 +1,49 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
*/
class OrePopulator extends Populator{
private $oreTypes = array();
public function populate(Level $level, $chunkX, $chunkZ, Random $random){
foreach($this->oreTypes as $type){
$ore = new OreObject($random, $type);
for($i = 0; $i < $ore->type->clusterCount; ++$i){
$v = new Vector3(
$random->nextRange($chunkX << 4, ($chunkX << 4) + 16),
$random->nextRange($ore->type->minHeight, $ore->type->maxHeight),
$random->nextRange($chunkZ << 4, ($chunkZ << 4) + 16)
);
if($ore->canPlaceObject($level, $v)){
$ore->placeObject($level, $v);
}
}
}
}
public function setOreTypes(array $types){
$this->oreTypes = $types;
}
}

View File

@ -0,0 +1,57 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
*/
class PondPopulator extends Populator{
private $waterOdd = 4;
private $lavaOdd = 4;
private $lavaSurfaceOdd = 4;
public function populate(Level $level, $chunkX, $chunkZ, Random $random){
if($random->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;
}
}