Uploading plugin

This commit is contained in:
Adsooi 2017-04-23 16:42:51 +02:00
commit f170caebf7
50 changed files with 5849 additions and 0 deletions

View file

@ -0,0 +1,248 @@
<?php
/*
* Main from BetterGen
* Copyright(C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen;
use pocketmine\plugin\PluginBase;
use pocketmine\level\generator\biome\Biome;
use pocketmine\level\generator\Generator;
use pocketmine\level\generator\normal\Normal;
use pocketmine\event\level\ChunkPopulateEvent;
use Ad5001\BetterGen\generator\BetterNormal;
use Ad5001\BetterGen\biome\BetterForest;
use Ad5001\BetterGen\loot\LootTable;
use pocketmine\utils\Config;
use pocketmine\block\Block;
use pocketmine\tile\Chest;
use pocketmine\nbt\NBT;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\tile\Tile;
use pocketmine\item\Item;
use pocketmine\event\player\PlayerInteractEvent;
use pocketmine\event\block\BlockBreakEvent;
class Main extends PluginBase implements \pocketmine\event\Listener {
const PREFIX = "§l§o§b[§r§l§2Better§aGen§o§b]§r§f ";
const SAKURA_FOREST = 100; // Letting some place for future biomes.
/*
* Called when the plugin enables
*/
public function onEnable() {
$this->getServer()->getPluginManager()->registerEvents($this, $this);
Generator::addGenerator(BetterNormal::class, "betternormal");
@mkdir($this->getDataFolder());
if(! file_exists(LootTable::getPluginFolder(). "processingLoots.json"))
file_put_contents(LootTable::getPluginFolder(). "processingLoots.json", "{}");
}
/*
* Called when the plugin disables
*/
public function onDisable() {
}
/*
* Called when one of the defined commands of the plugin has been called
* @param $sender \pocketmine\command\CommandSender
* @param $cmd \pocketmine\command\Command
* @param $label mixed
* @param $args array
* return bool
*/
public function onCommand(\pocketmine\command\CommandSender $sender, \pocketmine\command\Command $cmd, $label, array $args): bool {
switch($cmd->getName()) {
case "createworld" : // /createworld <name> [generator = betternormal] [seed = rand()] [options(json)]
switch(count($args)) {
case 0 :
return false;
break;
case 1 : // /createworld <name>
$name = $args [0];
$generator = Generator::getGenerator("betternormal");
$generatorName = "betternormal";
$seed = $this->generateRandomSeed();
$options = [ ];
break;
case 2 : // /createworld <name> [generator = betternormal]
$name = $args [0];
$generator = Generator::getGenerator($args [1]);
if(Generator::getGeneratorName($generator) !== strtolower($args [1])) {
$sender->sendMessage(self::PREFIX . "§4Could not find generator {$args[1]}. Are you sure it is registered?");
return true;
}
$generatorName = strtolower($args [1]);
$seed = $this->generateRandomSeed();
$options = [ ];
break;
case 3 : // /createworld <name> [generator = betternormal] [seed = rand()]
$name = $args [0];
$generator = Generator::getGenerator($args [1]);
if(Generator::getGeneratorName($generator) !== strtolower($args [1])) {
$sender->sendMessage(self::PREFIX . "§4Could not find generator {$args[1]}. Are you sure it is registered?");
return true;
}
$generatorName = strtolower($args [1]);
if(preg_match("[^\d]", $args [2]) !== false) {
$parts = str_split($args [2]);
foreach($parts as $key => $str) {
$parts [$key] = ord($str);
}
$seed = implode("", $parts);
} else {
$seed = $args [2];
}
$options = [ ];
break;
default : // /createworld <name> [generator = betternormal] [seed = rand()] [options(json)]
$name = $args [0];
$generator = Generator::getGenerator($args [1]);
if(Generator::getGeneratorName($generator) !== strtolower($args [1])) {
$sender->sendMessage(self::PREFIX . "§4Could not find generator {$args[1]}. Are you sure it is registered?");
return true;
}
$generatorName = strtolower($args [1]);
if(preg_match("[^\d]", $args [2]) !== false) {
$parts = str_split($args [2]);
foreach($parts as $key => $str) {
$parts [$key] = ord($str);
}
$seed = implode("", $parts);
} else {
$seed = $args [2];
}
unset($args [0], $args [1], $args [2]);
$options = json_decode($args [3], true);
if(! is_array($json)) {
$sender->sendMessage(Main::PREFIX . "§4Invalid JSON for options.");
return true;
}
break;
}
$this->getServer()->broadcastMessage(Main::PREFIX . "§aGenerating level $name with generator $generatorName and seed $seed..");
$this->getServer()->generateLevel($name, $seed, $generator, $options);
$this->getServer()->loadLevel($name);
return true;
break;
}
}
/*
* Registers a forest type.
* @param $name string
* @param $treeClass string
* @params $infos Array(temperature, rainfall)
* @return bool
*/
public function registerForest(string $name, string $treeClass, array $infos): bool {
if(! @class_exists($treeClass))
return false;
if(! @is_subclass_of($treeClass, "pocketmine\\level\\generator\\normal\\object\\Tree"))
return false;
if(count($infos) < 2 or ! is_float($infos [0]) or ! is_float($infos [1]))
return false;
return BetterForest::registerForest($name, $treeClass, $infos);
}
/*
* Registers a biome for the normal generator. Normal means(Biome::register) doesn't allow biome to be generated
* @param $id int
* @param $biome Biome
* @return void
*/
public static function registerBiome(int $id, Biome $biome) {
$reflection = new \ReflectionClass('pocketmine\\level\\generator\\biome\\Biome');
$register = $reflection->getMethod('register');
$register->setAccessible(true);
$register->invoke(null, $id, $biome);
BetterNormal::registerBiome($biome);
}
/*
* Generates a(semi) random seed.
* @return int
*/
public function generateRandomSeed(): int {
return(int) round(time() * rand(0, time()) / memory_get_usage());
}
// Listener
/*
* Checks after a chunk populates so we an add tiles and loot tables
* @param $event pocketmine\event\level\ChunkPopulateEvent
* @return int
*/
public function onChunkPopulate(ChunkPopulateEvent $event) {
$cfg = new Config(LootTable::getPluginFolder() . "processingLoots.json", Config::JSON);
foreach($cfg->getAll() as $key => $value) {
list($x, $y, $z) = explode(";", $key);
if($value["saveAs"] == "chest" && $event->getLevel()->getBlockIdAt($x, $y, $z) == Block::AIR ){
$event->getLevel()->setBlockIdAt($x, $y, $z, Block::CHEST);
} else {
$cfg->remove($key);
$cfg->save();
}
}
}
/*
* Checks when a player interacts with a loot chest to create it.
*/
public function onInteract(PlayerInteractEvent $event) {
$cfg = new Config(LootTable::getPluginFolder() . "processingLoots.json", Config::JSON);
if($event->getBlock()->getId() !== Block::CHEST) return;
if(!$cfg->exists($event->getBlock()->getX() . ";" . $event->getBlock()->getY() . ";" . $event->getBlock()->getZ())) return;
echo "Doing {$event->getBlock()}";
$chest = new \pocketmine\block\Chest(0);
$nbt = new CompoundTag("", [
new ListTag("Items", []),
new StringTag("id", Tile::CHEST),
new IntTag("x", $event->getBlock()->x),
new IntTag("y", $event->getBlock()->y),
new IntTag("z", $event->getBlock()->z)
]);
$chest->setLevel($event->getBlock()->getLevel());
$cItem = Item::get(Item::CHEST, 0);
$cItem->setCustomName("§k(Fake)§r Minecart chest");
$chest->place($cItem, $event->getBlock()->getLevel()->getBlock($event->getBlock()), $chest, 0, 0, 0, 0);
$inv = $event->getBlock()->getLevel()->getTile($event->getBlock());
LootTable::fillChest($inv->getInventory(), $event->getBlock());
}
/*
* Checks when a player breaks a loot chest which is not created to create it
*/
public function onBlockBreak(BlockBreakEvent $event) {
$cfg = new Config(LootTable::getPluginFolder() . "processingLoots.json", Config::JSON);
if($event->getBlock()->getId() !== Block::CHEST) return;
if(!$cfg->exists($event->getBlock()->getX() . ";" . $event->getBlock()->getY() . ";" . $event->getBlock()->getZ())) return;
echo "Doing {$event->getBlock()}";
$chest = new \pocketmine\block\Chest(0);
$nbt = new CompoundTag("", [
new ListTag("Items", []),
new StringTag("id", Tile::CHEST),
new IntTag("x", $event->getBlock()->x),
new IntTag("y", $event->getBlock()->y),
new IntTag("z", $event->getBlock()->z)
]);
$chest->setLevel($event->getBlock()->getLevel());
$cItem = Item::get(Item::CHEST, 0);
$cItem->setCustomName("§k(Fake)§r Minecart chest");
$chest->place($cItem, $event->getBlock()->getLevel()->getBlock($event->getBlock()), $chest, 0, 0, 0, 0);
$inv = $event->getBlock()->getLevel()->getTile($event->getBlock());
LootTable::fillChest($inv->getInventory(), $event->getBlock());
$event->setCancelled();
}
}

View file

@ -0,0 +1,79 @@
<?php
/*
* BetterDesert from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\biome;
use pocketmine\level\generator\normal\biome\SandyBiome;
use pocketmine\level\generator\biome\Biome;
use pocketmine\block\Block;
use Ad5001\BetterGen\populator\TemplePopulator;
use Ad5001\BetterGen\populator\WellPopulator;
use Ad5001\BetterGen\populator\CactusPopulator;
use Ad5001\BetterGen\populator\DeadbushPopulator;
use Ad5001\BetterGen\populator\SugarCanePopulator;
class BetterDesert extends SandyBiome implements Mountainable {
public function __construct() {
$deadBush = new DeadbushPopulator ();
$deadBush->setBaseAmount ( 1 );
$deadBush->setRandomAmount ( 2 );
$cactus = new CactusPopulator ();
$cactus->setBaseAmount ( 1 );
$cactus->setRandomAmount ( 2 );
$sugarCane = new SugarCanePopulator ();
$sugarCane->setRandomAmount ( 20 );
$sugarCane->setBaseAmount ( 3 );
$temple = new TemplePopulator ();
$well = new WellPopulator ();
$this->addPopulator ( $cactus );
$this->addPopulator ( $deadBush );
$this->addPopulator ( $sugarCane );
$this->addPopulator ( $temple );
$this->addPopulator ( $well );
$this->setElevation ( 63, 70 );
// $this->setElevation(66, 70);
$this->temperature = 0.5;
$this->rainfall = 0;
$this->setGroundCover ( [
Block::get ( Block::SAND, 0 ),
Block::get ( Block::SAND, 0 ),
Block::get ( Block::SAND, 0 ),
Block::get ( Block::SAND, 0 ),
Block::get ( Block::SANDSTONE, 0 ),
Block::get ( Block::SANDSTONE, 0 ),
Block::get ( Block::SANDSTONE, 0 ),
Block::get ( Block::SANDSTONE, 0 ),
Block::get ( Block::SANDSTONE, 0 ),
Block::get ( Block::SANDSTONE, 0 ),
Block::get ( Block::SANDSTONE, 0 ),
Block::get ( Block::SANDSTONE, 0 ),
Block::get ( Block::SANDSTONE, 0 ),
Block::get ( Block::SANDSTONE, 0 ),
Block::get ( Block::SANDSTONE, 0 ),
Block::get ( Block::SANDSTONE, 0 ),
Block::get ( Block::SANDSTONE, 0 )
] );
}
public function getName(): string {
return "Better Desert";
}
/*
* Returns biome id
*/
public function getId() {
return Biome::DESERT;
}
}

View file

@ -0,0 +1,76 @@
<?php
/*
* BetterForest from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\biome;
use pocketmine\level\generator\normal\biome\ForestBiome;
use pocketmine\level\generator\biome\Biome;
use pocketmine\level\generator\populator\TallGrass;
use Ad5001\BetterGen\Main;
use Ad5001\BetterGen\populator\TreePopulator;
use Ad5001\BetterGen\populator\BushPopulator;
class BetterForest extends ForestBiome implements Mountainable {
static $types = [
"Oak Forest",
"Birch Forest",
"Sakura Forest"
];
static $ids = [
Biome::FOREST,
Biome::BIRCH_FOREST,
Main::SAKURA_FOREST
];
public function __construct($type = 0, array $infos = [0.6, 0.5]) {
parent::__construct ( $type );
$this->clearPopulators ();
$this->type = $type;
$bush = new BushPopulator ( $type );
$bush->setBaseAmount ( 10 );
$this->addPopulator ( $bush );
$trees = new TreePopulator ( $type );
$trees->setBaseAmount ( (null !== @constant ( TreePopulator::$types [$type] . "::maxPerChunk" )) ? constant ( TreePopulator::$types [$type] . "::maxPerChunk" ) : 5 );
$this->addPopulator ( $trees );
$tallGrass = new TallGrass ();
$tallGrass->setBaseAmount ( 3 );
$this->addPopulator ( $tallGrass );
$this->setElevation ( 63, 81 );
$this->temperature = $infos [0];
$this->rainfall = $infos [1];
}
public function getName() {
return self::$types [$this->type];
}
/*
* Returns the ID relativly.
*/
public function getId() {
return self::$ids [$this->type];
}
/*
* Registers a forest type. Don't use this method directly use the one from the main class.
* @param $name string
* @param $treeClass string
* @param
* @return bool
*/
public static function registerForest(string $name, string $treeClass, array $infos): bool {
self::$types [] = str_ireplace ( "tree", "", explode ( "\\", $treeClass ) [count ( explode ( "\\", $treeClass ) )] ) . " Forest";
TreePopulator::$types [] = $treeClass;
self::$ids [] = Main::SAKURA_FOREST + (count ( self::$types ) - 2);
Main::register ( Main::SAKURA_FOREST + (count ( self::$types ) - 2), new BetterForest ( count ( self::$types ) - 1, $infos ) );
}
}

View file

@ -0,0 +1,50 @@
<?php
/*
* BetterIcePlains from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\biome;
use pocketmine\level\generator\normal\biome\SnowyBiome;
use pocketmine\level\generator\biome\Biome;
use pocketmine\block\Block;
use pocketmine\level\generator\populator\TallGrass;
use Ad5001\BetterGen\populator\IglooPopulator;
class BetterIcePlains extends SnowyBiome implements Mountainable {
public function __construct() {
parent::__construct ();
$this->setGroundCover ( [
Block::get ( Block::SNOW, 0 ),
Block::get ( Block::GRASS, 0 ),
Block::get ( Block::DIRT, 0 ),
Block::get ( Block::DIRT, 0 ),
Block::get ( Block::DIRT, 0 )
] );
$this->addPopulator ( new IglooPopulator () );
$tallGrass = new TallGrass ();
$tallGrass->setBaseAmount ( 3 );
$this->addPopulator ( $tallGrass );
$this->setElevation ( 63, 74 );
$this->temperature = 0.05;
$this->rainfall = 0.8;
}
public function getName() {
return "Better Ice Plains";
}
/*
* Returns biome's id.
*/
public function getId() {
return Biome::ICE_PLAINS;
}
}

View file

@ -0,0 +1,113 @@
<?php
/*
* BetterMesa from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\biome;
use pocketmine\level\generator\normal\biome\SandyBiome;
use pocketmine\level\generator\populator\Ore;
use pocketmine\level\generator\object\OreType;
use pocketmine\level\generator\biome\Biome;
use pocketmine\block\Block;
use pocketmine\block\GoldOre;
use Ad5001\BetterGen\populator\TreePopulator;
use Ad5001\BetterGen\populator\CactusPopulator;
use Ad5001\BetterGen\populator\DeadbushPopulator;
use Ad5001\BetterGen\populator\SugarCanePopulator;
class BetterMesa extends SandyBiome {
public function __construct() {
$deadBush = new DeadbushPopulator ();
$deadBush->setBaseAmount ( 1 );
$deadBush->setRandomAmount ( 2 );
$cactus = new CactusPopulator ();
$cactus->setBaseAmount ( 1 );
$cactus->setRandomAmount ( 2 );
$sugarCane = new SugarCanePopulator ();
$sugarCane->setRandomAmount ( 20 );
$sugarCane->setBaseAmount ( 3 );
$sugarCane = new TreePopulator ();
$sugarCane->setRandomAmount ( 2 );
$sugarCane->setBaseAmount ( 0 );
$ores = new Ore ();
$ores->setOreTypes ( [
new OreType ( new GoldOre (), 2, 8, 0, 32 )
] );
$this->addPopulator ( $cactus );
$this->addPopulator ( $deadBush );
$this->addPopulator ( $sugarCane );
$this->addPopulator ( $ores );
$this->setElevation ( 80, 83 );
// $this->setElevation(66, 70);
$this->temperature = 0.8;
$this->rainfall = 0;
$this->setGroundCover ( [
Block::get ( Block::DIRT, 0 ),
Block::get ( Block::HARDENED_CLAY, 0 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::HARDENED_CLAY, 0 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 7 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::HARDENED_CLAY, 0 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 12 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 12 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 12 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 14 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 14 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 14 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 4 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 7 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 0 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 7 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::HARDENED_CLAY, 0 ),
Block::get ( Block::HARDENED_CLAY, 0 ),
Block::get ( Block::HARDENED_CLAY, 0 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::RED_SANDSTONE, 0 ),
Block::get ( Block::RED_SANDSTONE, 0 ),
Block::get ( Block::RED_SANDSTONE, 0 ),
Block::get ( Block::RED_SANDSTONE, 0 ),
Block::get ( Block::RED_SANDSTONE, 0 ),
Block::get ( Block::RED_SANDSTONE, 0 ),
Block::get ( Block::RED_SANDSTONE, 0 ),
Block::get ( Block::RED_SANDSTONE, 0 )
] );
}
public function getName(): string {
return "Better Mesa";
}
/*
* Returns biome id
*/
public function getId() {
return 39;
}
}

View file

@ -0,0 +1,108 @@
<?php
/*
* BetterMesaPlains from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\biome;
use pocketmine\level\generator\normal\biome\SandyBiome;
use pocketmine\level\generator\populator\Ore;
use pocketmine\level\generator\object\OreType;
use pocketmine\level\generator\biome\Biome;
use pocketmine\block\Block;
use pocketmine\block\GoldOre;
use Ad5001\BetterGen\populator\CactusPopulator;
use Ad5001\BetterGen\populator\DeadbushPopulator;
use Ad5001\BetterGen\populator\SugarCanePopulator;
class BetterMesaPlains extends SandyBiome {
public function __construct() {
$deadBush = new DeadbushPopulator ();
$deadBush->setBaseAmount ( 1 );
$deadBush->setRandomAmount ( 2 );
$cactus = new CactusPopulator ();
$cactus->setBaseAmount ( 1 );
$cactus->setRandomAmount ( 2 );
$sugarCane = new SugarCanePopulator ();
$sugarCane->setRandomAmount ( 20 );
$sugarCane->setBaseAmount ( 3 );
$ores = new Ore ();
$ores->setOreTypes ( [
new OreType ( new GoldOre (), 20, 8, 0, 32 )
] );
$this->addPopulator ( $cactus );
$this->addPopulator ( $deadBush );
$this->addPopulator ( $sugarCane );
$this->addPopulator ( $ores );
$this->setElevation ( 62, 67 );
// $this->setElevation(66, 70);
$this->temperature = 0.6;
$this->rainfall = 0;
$this->setGroundCover ( [
Block::get ( Block::SAND, 1 ),
Block::get ( Block::SAND, 1 ),
Block::get ( Block::HARDENED_CLAY, 0 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::HARDENED_CLAY, 0 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 7 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::HARDENED_CLAY, 0 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 12 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 12 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 12 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 14 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 14 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 14 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 4 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 7 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 0 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 7 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::HARDENED_CLAY, 0 ),
Block::get ( Block::HARDENED_CLAY, 0 ),
Block::get ( Block::HARDENED_CLAY, 0 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::STAINED_HARDENED_CLAY, 1 ),
Block::get ( Block::RED_SANDSTONE, 0 ),
Block::get ( Block::RED_SANDSTONE, 0 ),
Block::get ( Block::RED_SANDSTONE, 0 ),
Block::get ( Block::RED_SANDSTONE, 0 ),
Block::get ( Block::RED_SANDSTONE, 0 ),
Block::get ( Block::RED_SANDSTONE, 0 ),
Block::get ( Block::RED_SANDSTONE, 0 ),
Block::get ( Block::RED_SANDSTONE, 0 )
] );
}
public function getName(): string {
return "Better Mesa Plains";
}
/*
* Returns biome id
*/
public function getId() {
return 40;
}
}

View file

@ -0,0 +1,48 @@
<?php
/*
* BetterRiver from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\biome;
use pocketmine\level\generator\biome\Biome;
use pocketmine\block\Block;
class BetterRiver extends Biome {
public function __construct() {
$this->clearPopulators ();
$this->setGroundCover ( [
Block::get ( Block::SAND, 0 ),
Block::get ( Block::SAND, 0 ),
Block::get ( Block::SAND, 0 ),
Block::get ( Block::SANDSTONE, 0 ),
Block::get ( Block::SANDSTONE, 0 ),
Block::get ( Block::SANDSTONE, 0 ),
Block::get ( Block::SANDSTONE, 0 ),
Block::get ( Block::SANDSTONE, 0 ),
Block::get ( Block::SANDSTONE, 0 ),
Block::get ( Block::SANDSTONE, 0 ),
Block::get ( Block::SANDSTONE, 0 )
] );
$this->setElevation ( 60, 60 );
$this->temperature = 0.5;
$this->rainfall = 0.7;
}
public function getName() {
return "Better River";
}
/*
* Returns the ID relativly.
*/
public function getId() {
return Biome::RIVER;
}
}

View file

@ -0,0 +1,14 @@
<?php
/*
* Mountainable from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\biome;
// Class to iplement when the biome can be set as a mountain
interface Mountainable {
}

View file

@ -0,0 +1,66 @@
<?php
/*
* BetterBiomeSelector from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\generator;
use pocketmine\level\generator\biome\BiomeSelector;
use pocketmine\level\generator\biome\Biome;
use pocketmine\utils\Random;
use pocketmine\level\generator\noise\Simplex;
class BetterBiomeSelector extends BiomeSelector {
/** @var Biome */
private $fallback;
/** @var Simplex */
private $temperature;
/** @var Simplex */
private $rainfall;
/** @var Biome[] */
private $biomes = [ ];
private $map = [ ];
private $lookup;
public function __construct(Random $random, callable $lookup, Biome $fallback) {
$this->fallback = $fallback;
$this->lookup = $lookup;
$this->temperature = new Simplex ( $random, 2, 1 / 16, 1 / 512 );
$this->rainfall = new Simplex ( $random, 2, 1 / 16, 1 / 512 );
}
public function recalculate() {
} // Using our own system, No need for that
public function addBiome(Biome $biome) {
$this->biomes [$biome->getId ()] = $biome;
}
public function getTemperature($x, $z) {
return ($this->temperature->noise2D ( $x, $z, true ) + 1) / 2;
}
public function getRainfall($x, $z) {
return ($this->rainfall->noise2D ( $x, $z, true ) + 1) / 2;
}
/**
*
* @param
* $x
* @param
* $z
*
* @return Biome
*/
public function pickBiome($x, $z) {
$temperature = ($this->getTemperature ( $x, $z ));
$rainfall = ($this->getRainfall ( $x, $z ));
$biomeId = BetterNormal::getBiome ( $temperature, $rainfall );
// $biomeId = new \Ad5001\BetterGen\biome\BetterDesert();
$b = (($biomeId instanceof Biome) ? $biomeId : ($this->biomes [$biomeId] ?? $this->fallback));
return $b;
}
}

View file

@ -0,0 +1,421 @@
<?php
/*
* BetterNormal from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\generator;
use pocketmine\level\ChunkManager;
use pocketmine\utils\Random;
use pocketmine\level\generator\biome\Biome;
use pocketmine\level\generator\Generator;
use pocketmine\level\generator\noise\Simplex;
use pocketmine\level\generator\object\OreType;
use pocketmine\level\generator\populator\GroundCover;
use pocketmine\level\generator\populator\Ore;
use pocketmine\block\Block;
use pocketmine\block\CoalOre;
use pocketmine\block\DiamondOre;
use pocketmine\block\Dirt;
use pocketmine\block\GoldOre;
use pocketmine\block\Gravel;
use pocketmine\block\IronOre;
use pocketmine\block\LapisOre;
use pocketmine\block\RedstoneOre;
use pocketmine\level\Level;
use Ad5001\BetterGen\biome\BetterForest;
use Ad5001\BetterGen\biome\BetterDesert;
use Ad5001\BetterGen\biome\BetterIcePlains;
use Ad5001\BetterGen\biome\BetterMesa;
use Ad5001\BetterGen\biome\BetterMesaPlains;
use Ad5001\BetterGen\biome\BetterRiver;
use Ad5001\BetterGen\biome\Mountainable;
use Ad5001\BetterGen\populator\CavePopulator;
use Ad5001\BetterGen\populator\RavinePopulator;
use Ad5001\BetterGen\populator\LakePopulator;
use Ad5001\BetterGen\populator\MineshaftPopulator;
use Ad5001\BetterGen\populator\FloatingIslandPopulator;
class BetterNormal extends Generator {
const NOT_OVERWRITABLE = [
Block::STONE,
Block::GRAVEL,
Block::BEDROCK,
Block::DIAMOND_ORE,
Block::GOLD_ORE,
Block::LAPIS_ORE,
Block::REDSTONE_ORE,
Block::IRON_ORE,
Block::COAL_ORE,
Block::WATER,
Block::STILL_WATER
];
protected $selector;
protected $level;
protected $random;
protected $populators = [ ];
protected $generationPopulators = [ ];
public static $biomes = [ ];
public static $biomeById = [ ];
public static $levels = [ ];
protected static $GAUSSIAN_KERNEL = null; // From main class
protected static $SMOOTH_SIZE = 2;
protected $waterHeight = 63;
/*
* Picks a biome by X and Z
* @param $x int
* @param $z int
* @return Biome
*/
public function pickBiome($x, $z) {
$hash = $x * 2345803 ^ $z * 9236449 ^ $this->level->getSeed ();
$hash *= $hash + 223;
$xNoise = $hash >> 20 & 3;
$zNoise = $hash >> 22 & 3;
if ($xNoise == 3) {
$xNoise = 1;
}
if ($zNoise == 3) {
$zNoise = 1;
}
$b = $this->selector->pickBiome ( $x + $xNoise - 1, $z + $zNoise - 1 );
if ($b instanceof Mountainable && $this->random->nextBoundedInt ( 1000 ) < 3) {
$b = clone $b;
$b->setElevation ( $b->getMinElevation () + (50 * $b->getMinElevation () / 100), $b->getMaxElevation () + (50 * $b->getMinElevation () / 100) );
}
return $b;
}
public function init(ChunkManager $level, Random $random) {
$this->level = $level;
$this->random = $random;
self::$levels [] = $level;
$this->random->setSeed ( $this->level->getSeed () );
$this->noiseBase = new Simplex ( $this->random, 4, 1 / 4, 1 / 32 );
$this->random->setSeed ( $this->level->getSeed () );
$this->registerBiome ( Biome::getBiome ( Biome::OCEAN ) );
$this->registerBiome ( Biome::getBiome ( Biome::PLAINS ) );
$this->registerBiome ( new BetterDesert () );
$this->registerBiome ( new BetterMesa () );
$this->registerBiome ( new BetterMesaPlains () );
$this->registerBiome ( Biome::getBiome ( Biome::TAIGA ) );
$this->registerBiome ( Biome::getBiome ( Biome::SWAMP ) );
$this->registerBiome ( new BetterRiver () );
$this->registerBiome ( new BetterIcePlains () );
$this->registerBiome ( new BetterForest ( 0, [
0.6,
0.5
] ) );
$this->registerBiome ( new BetterForest ( 1, [
0.7,
0.8
] ) );
$this->registerBiome ( new BetterForest ( 2, [
0.6,
0.4
] ) );
$this->selector = new BetterBiomeSelector ( $random, [
self::class,
"getBiome"
], self::getBiome ( 0, 0 ) );
foreach ( self::$biomes as $rain ) {
foreach ( $rain as $biome ) {
$this->selector->addBiome ( $biome );
}
}
$this->selector->recalculate ();
$cover = new GroundCover ();
$this->generationPopulators [] = $cover;
$cave = new CavePopulator ();
$cave->setBaseAmount ( 0 );
$cave->setRandomAmount ( 2 );
$this->populators [] = $cave;
$ravine = new RavinePopulator ();
$ravine->setBaseAmount ( 0 );
$ravine->setRandomAmount ( 51 );
$this->populators [] = $ravine;
$mineshaft = new MineshaftPopulator ();
$mineshaft->setBaseAmount ( 0 );
$mineshaft->setRandomAmount ( 102 );
$this->populators [] = $mineshaft;
$lake = new LakePopulator ();
$lake->setBaseAmount ( 0 );
$lake->setRandomAmount ( 1 );
$this->generationPopulators [] = $lake;
$fisl = new FloatingIslandPopulator();
$fisl->setBaseAmount ( 0 );
$fisl->setRandomAmount ( 132 );
$this->populators [] = $fisl;
$ores = new Ore ();
$ores->setOreTypes ( [
new OreType ( new CoalOre (), 20, 16, 0, 128 ),
new OreType ( new IronOre (), 20, 8, 0, 64 ),
new OreType ( new RedstoneOre (), 8, 7, 0, 16 ),
new OreType ( new LapisOre (), 1, 6, 0, 32 ),
new OreType ( new GoldOre (), 2, 8, 0, 32 ),
new OreType ( new DiamondOre (), 1, 7, 0, 16 ),
new OreType ( new Dirt (), 20, 32, 0, 128 ),
new OreType ( new Gravel (), 10, 16, 0, 128 )
] );
$this->populators [] = $ores;
}
/*
* Adds a biome to the selector. Do not use this method directly use Main::registerBiome which registers it properly
* @param $biome Biome
* @return bool
*/
public static function registerBiome(Biome $biome): bool {
foreach ( self::$levels as $lvl )
if (isset ( $lvl->selector ))
$lvl->selector->addBiome ( $biome ); // If no selector created, it would cause errors. These will be added when selectoes
if (! isset ( self::$biomes [( string ) $biome->getRainfall ()] ))
self::$biomes [( string ) $biome->getRainfall ()] = [ ];
self::$biomes [( string ) $biome->getRainfall ()] [( string ) $biome->getTemperature ()] = $biome;
ksort ( self::$biomes [( string ) $biome->getRainfall ()] );
ksort ( self::$biomes );
self::$biomeById[$biome->getId()] = $biome;
return true;
}
/*
* Returns a biome by temperature
* @param $temperature float
* @param $rainfall float
*/
public static function getBiome($temperature, $rainfall) {
if (! isset ( self::$biomes [( string ) round ( $rainfall, 1 )] )) {
while ( ! isset ( self::$biomes [( string ) round ( $rainfall, 1 )] ) ) {
if (abs ( $rainfall - round ( $rainfall, 1 ) ) >= 0.05)
$rainfall += 0.1;
if (abs ( $rainfall - round ( $rainfall, 1 ) ) < 0.05)
$rainfall -= 0.1;
if (round ( $rainfall, 1 ) < 0)
$rainfall = 0;
if (round ( $rainfall, 1 ) >= 0.9)
$rainfall = 0.9;
}
}
$b = self::$biomes [( string ) round ( $rainfall, 1 )];
foreach ( $b as $t => $biome ) {
if ($temperature <= ( float ) $t) {
$ret = $biome;
break;
}
}
if (is_string ( $ret )) {
$ret = new $ret ();
} else {
return $ret;
}
}
/*
* Returns a biome by its id
* @param $id int
* @return Biome
*/
public function getBiomeById(int $id): Biome {
return self::$biomeById[$id] ?? self::$biomeById(Biome::OCEAN);
}
/*
* Generates a chunk.
* Cloning method to make it work with new methods.
* @param $chunkX int
* @param $chunkZ int
*/
public function generateChunk($chunkX, $chunkZ) {
$this->reRegisterBiomes ();
$this->random->setSeed ( 0xdeadbeef ^ ($chunkX << 8) ^ $chunkZ ^ $this->level->getSeed () );
$noise = Generator::getFastNoise3D ( $this->noiseBase, 16, 128, 16, 4, 8, 4, $chunkX * 16, 0, $chunkZ * 16 );
$chunk = $this->level->getChunk ( $chunkX, $chunkZ );
$biomeCache = [ ];
for($x = 0; $x < 16; ++ $x) {
for($z = 0; $z < 16; ++ $z) {
$minSum = 0;
$maxSum = 0;
$weightSum = 0;
$biome = $this->pickBiome ( $chunkX * 16 + $x, $chunkZ * 16 + $z );
$chunk->setBiomeId ( $x, $z, $biome->getId () );
for($sx = - self::$SMOOTH_SIZE; $sx <= self::$SMOOTH_SIZE; ++ $sx) {
for($sz = - self::$SMOOTH_SIZE; $sz <= self::$SMOOTH_SIZE; ++ $sz) {
$weight = self::$GAUSSIAN_KERNEL [$sx + self::$SMOOTH_SIZE] [$sz + self::$SMOOTH_SIZE];
if ($sx === 0 and $sz === 0) {
$adjacent = $biome;
} else {
$index = Level::chunkHash ( $chunkX * 16 + $x + $sx, $chunkZ * 16 + $z + $sz );
if (isset ( $biomeCache [$index] )) {
$adjacent = $biomeCache [$index];
} else {
$biomeCache [$index] = $adjacent = $this->pickBiome ( $chunkX * 16 + $x + $sx, $chunkZ * 16 + $z + $sz );
}
}
$minSum += ($adjacent->getMinElevation () - 1) * $weight;
$maxSum += $adjacent->getMaxElevation () * $weight;
$weightSum += $weight;
}
}
$minSum /= $weightSum;
$maxSum /= $weightSum;
$smoothHeight = ($maxSum - $minSum) / 2;
for($y = 0; $y < 128; ++ $y) {
if ($y < 3 || ($y < 5 && $this->random->nextBoolean ())) {
$chunk->setBlockId ( $x, $y, $z, Block::BEDROCK );
continue;
}
$noiseValue = $noise [$x] [$z] [$y] - 1 / $smoothHeight * ($y - $smoothHeight - $minSum);
if ($noiseValue > 0) {
$chunk->setBlockId ( $x, $y, $z, Block::STONE );
} elseif ($y <= $this->waterHeight) {
$chunk->setBlockId ( $x, $y, $z, Block::STILL_WATER );
}
}
}
}
foreach ( $this->generationPopulators as $populator ) {
$populator->populate ( $this->level, $chunkX, $chunkZ, $this->random );
}
}
/*
* Populates a chunk.
* @param $chunkX int
* @param $chunk2 int
*/
public function populateChunk($chunkX, $chunkZ) {
$this->random->setSeed ( 0xdeadbeef ^ ($chunkX << 8) ^ $chunkZ ^ $this->level->getSeed () );
foreach ( $this->populators as $populator ) {
$populator->populate ( $this->level, $chunkX, $chunkZ, $this->random );
}
// Filling lava (lakes & rivers underground)...
for($x = $chunkX; $x < $chunkX + 16; $x ++)
for($z = $chunkZ; $z < $chunkZ + 16; $z ++)
for($y = 1; $y < 11; $y ++) {
if (! in_array ( $this->level->getBlockIdAt ( $x, $y, $z ), self::NOT_OVERWRITABLE ))
$this->level->setBlockIdAt ( $x, $y, $z, Block::LAVA );
}
$chunk = $this->level->getChunk ( $chunkX, $chunkZ );
$biome = Biome::getBiome ( $chunk->getBiomeId ( 7, 7 ) );
$biome->populateChunk ( $this->level, $chunkX, $chunkZ, $this->random );
}
/*
* Constructs the class
* @param $options array
*/
public function __construct(array $options = []) {
if (self::$GAUSSIAN_KERNEL === null) {
self::generateKernel ();
}
}
/*
* Generates the genration kernel based on smooth size (here 2)
*/
private static function generateKernel() {
self::$GAUSSIAN_KERNEL = [ ];
$bellSize = 1 / self::$SMOOTH_SIZE;
$bellHeight = 2 * self::$SMOOTH_SIZE;
for($sx = - self::$SMOOTH_SIZE; $sx <= self::$SMOOTH_SIZE; ++ $sx) {
self::$GAUSSIAN_KERNEL [$sx + self::$SMOOTH_SIZE] = [ ];
for($sz = - self::$SMOOTH_SIZE; $sz <= self::$SMOOTH_SIZE; ++ $sz) {
$bx = $bellSize * $sx;
$bz = $bellSize * $sz;
self::$GAUSSIAN_KERNEL [$sx + self::$SMOOTH_SIZE] [$sz + self::$SMOOTH_SIZE] = $bellHeight * exp ( - ($bx * $bx + $bz * $bz) / 2 );
}
}
}
//  Returns the name of the generator
public function getName() {
return "betternormal";
}
/*
* Gives the generators settings.
* @return array
*/
public function getSettings(): array {
return [ ];
}
public function getSpawn() {
return new Vector3 ( 127.5, 128, 127.5 );
}
/*
* Returns a safe spawn location
*/
public function getSafeSpawn() {
return new Vector3 ( 127.5, $this->getHighestWorkableBlock ( 127, 127 ), 127.5 );
}
/*
* Gets the top block (y) on an x and z axes
* @param $x int
* @param $z int
*/
protected function getHighestWorkableBlock($x, $z) {
for($y = 127; $y > 0; -- $y) {
$b = $this->level->getBlockIdAt ( $x, $y, $z );
if ($b === Block::DIRT or $b === Block::GRASS or $b === Block::PODZOL) {
break;
} elseif ($b !== 0 and $b !== Block::SNOW_LAYER) {
return - 1;
}
}
return ++ $y;
}
/*
* Re registers all biomes for async
*/
public function reRegisterBiomes() {
$reflection = new \ReflectionClass ( 'pocketmine\\level\\generator\\biome\\Biome' );
$register = $reflection->getMethod ( 'register' );
$register->setAccessible ( true );
foreach ( self::$biomes as $rainfall => $arr ) {
foreach ( $arr as $tmp => $biome ) {
$register->invoke ( null, $biome->getId (), $biome );
}
}
}
}

View file

@ -0,0 +1,124 @@
<?php
/*
* LootTable from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\loot;
use pocketmine\utils\Config;
use pocketmine\utils\Random;
use pocketmine\math\Vector3;
use pocketmine\item\Item;
use pocketmine\inventory\BaseInventory;
use pocketmine\nbt\NBT;
/*
* This class is used for loot setting.
* Please note that they AREN'T as powerfull as PC ones due to some implementations limitations.
* Loot table format:
* {
* "max": Max number of loots (storable amount)
* "example": {
* "percentage": Chance of appearing(in percent)
* "minCount": Minimal count
* "maxCount": Maximal count
* "id": Id of the item
* "data": Item damage
* "tags": {"display": {"Name": "Example NBT data"}}. This parameter is optionnal
* "minStacks": If choosen, the minimum amount of stacks that can be found
* "maxStacks": If choosen the maximum number of stacks that can be choosen
* }
* }
*/
class LootTable {
const LOOT_NAMES = [
"temple",
"igloo",
"mineshaft"
];
const LOOT_SAVE = [
"chest",
"chest",
"chest"
];
const LOOT_DESERT_TEMPLE = 0;
const LOOT_IGLOO = 1;
const LOOT_MINESHAFT = 2;
/*
* Asyncronous loot table choosing
* @param $place pocketmine\math\Vector3
* @param $type int
* @param $random pocketmine\utils\Random
* @return void
*/
public static function buildLootTable(Vector3 $place, int $type, Random $random) {
if($place->y < 1) return; // Making sure sometimes that it doesn't write for nothing
$cfg = new Config(self::getPluginFolder() . "processingLoots.json", Config::JSON);
$lootsFromJson = json_decode(file_get_contents(self::getResourcesFolder() . "loots/" . self::LOOT_NAMES[$type] . ".json"), true);
$loots =[];
foreach($lootsFromJson as $loot) {
if(is_array($loot) && $random->nextBoundedInt(101) < $loot["percentage"])
$loots[] = $loot;
}
if($lootsFromJson["max"] < count($loots)) {
while($lootsFromJson["max"] < count($loots))
unset($loots[array_rand($loots)]);
}
$loots["saveAs"] = self::LOOT_SAVE[$type];
$cfg->set($place->x . ";" . $place->y . ";" . $place->z, $loots);
$cfg->save();
}
/*
* Syncronous inventory filling with loot table.
* @param $inv pocketmine\inventory\BaseInventory
* @param $pos pocketmine\math\Vector3
* @return void
*/
public static function fillChest(BaseInventory $inv, Vector3 $pos) {
$cfg = new Config(self::getPluginFolder() . "processingLoots.json", Config::JSON);
if($cfg->exists($pos->x . ";" . $pos->y . ";" . $pos->z)) {
$loots = $cfg->get($pos->x . ";" . $pos->y . ";" . $pos->z);
$items = [];
foreach($loots as $loot) {
if(!is_array($loot)) continue;
$randCount = rand($loot["minStacks"], $loot["maxStacks"]);
for($i = 0; $i <= $randCount; $i++) {
$rand = rand(0, count($loots));
$items[$rand] = Item::get($loot["id"], $loot["data"], rand($loot["minCount"], $loot["maxCount"]));
if(isset($loot["tags"])) $items[$rand]->setCompoundTag(NBT::fromJSON($loot["tags"]));
}
}
$inv->setContents($items);
$cfg->remove($pos->x . ";" . $pos->y . ";" . $pos->z);
$cfg->save();
}
}
/*
* Returns the plugins folder.
* @return string
*/
public static function getPluginFolder(): string {
$dir = explode(DIRECTORY_SEPARATOR, __DIR__);
$c = count($dir);
unset($dir[$c - 1], $dir[$c - 2], $dir[$c - 3], $dir[$c - 4], $dir[$c - 5]);
return str_ireplace("phar://", "", implode(DIRECTORY_SEPARATOR, $dir)) . DIRECTORY_SEPARATOR . "BetterGen" . DIRECTORY_SEPARATOR;
}
/*
* Returns the resources folder.
* @return string
*/
public static function getResourcesFolder(): string {
$dir = explode(DIRECTORY_SEPARATOR, __DIR__);
$c = count($dir);
unset($dir[$c - 1], $dir[$c - 2], $dir[$c - 3], $dir[$c - 4]);
return str_ireplace("phar://", "", implode(DIRECTORY_SEPARATOR, $dir)) . DIRECTORY_SEPARATOR . "resources" . DIRECTORY_SEPARATOR;
}
}

View file

@ -0,0 +1,62 @@
<?php
/*
* AmountPopulator from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\populator;
use pocketmine\utils\Random;
use pocketmine\level\generator\populator\Populator;
abstract class AmountPopulator extends Populator {
protected $baseAmount = 0;
protected $randomAmount = 0;
/*
* Crosssoftware class for random amount
*/
/*
* Sets the random addition amount
* @param $amount int
*/
public function setRandomAmount(int $amount) {
$this->randomAmount = $amount;
}
/*
* Sets the base addition amount
* @param $amount int
*/
public function setBaseAmount(int $amount) {
$this->baseAmount = $amount;
}
/*
* Returns the amount based on random
* @param $random Random
*/
public function getAmount(Random $random) {
return $this->baseAmount + $random->nextRange ( 0, $this->randomAmount + 1 );
}
/*
* Returns the base amount
* @return int
*/
public function getBaseAmount(): int {
return $this->baseAmount;
}
/*
* Returns the random additional amount
* @return int
*/
public function getRandomAmount(): int {
return $this->randomAmount;
}
}

View file

@ -0,0 +1,70 @@
<?php
/*
* BushPopulator from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\populator;
use pocketmine\utils\Random;
use pocketmine\block\Block;
use pocketmine\level\ChunkManager;
use Ad5001\BetterGen\populator\TreePopulator;
use Ad5001\BetterGen\populator\AmountPopulator;
use Ad5001\BetterGen\structure\Bush;
class BushPopulator extends AmountPopulator {
protected $level;
protected $type;
/*
* Constructs the class
* @param $type int
*/
public function __construct($type = 0) {
$this->type = $type;
}
/*
* Populate the chunk
* @param $level pocketmine\level\ChunkManager
* @param $chunkX int
* @param $chunkZ int
* @param $random pocketmine\utils\Random
*/
public function populate(ChunkManager $level, $chunkX, $chunkZ, Random $random) {
$this->level = $level;
$amount = $this->getAmount ( $random );
for($i = 0; $i < $amount; ++ $i) {
$x = $random->nextRange ( $chunkX << 4, ($chunkX << 4) + 15 );
$z = $random->nextRange ( $chunkZ << 4, ($chunkZ << 4) + 15 );
$y = $this->getHighestWorkableBlock ( $x, $z );
if ($y === - 1) {
continue;
}
$tree = new TreePopulator::$types [$this->type] ();
$bush = new Bush ( $tree->leafBlock, $tree->leafType ?? $tree->type);
$bush->placeObject ( $level, $x, $y, $z, $random );
}
}
/*
* Gets the top block (y) on an x and z axes
* @param $x int
* @param $z int
*/
protected function getHighestWorkableBlock($x, $z) {
for($y = 127; $y > 0; -- $y) {
$b = $this->level->getBlockIdAt ( $x, $y, $z );
if ($b === Block::DIRT or $b === Block::GRASS or $b === Block::PODZOL) {
break;
} elseif ($b !== 0 and $b !== Block::SNOW_LAYER) {
return - 1;
}
}
return ++ $y;
}
}

View file

@ -0,0 +1,63 @@
<?php
/*
* CactusPopulator from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\populator;
use pocketmine\block\Block;
use pocketmine\level\ChunkManager;
use pocketmine\utils\Random;
use Ad5001\BetterGen\structure\Cactus;
use Ad5001\BetterGen\populator\AmountPopulator;
class CactusPopulator extends AmountPopulator {
protected $level;
/*
* Constructs the class
*/
public function __construct() {
$this->setBaseAmount ( 1 );
$this->setRandomAmount ( 2 );
}
/*
* Populate the chunk
* @param $level pocketmine\level\ChunkManager
* @param $chunkX int
* @param $chunkZ int
* @param $random pocketmine\utils\Random
*/
public function populate(ChunkManager $level, $chunkX, $chunkZ, Random $random) {
$this->level = $level;
$amount = $this->getAmount ( $random );
$cactus = new Cactus ();
for($i = 0; $i < $amount; ++ $i) {
$x = $random->nextRange ( $chunkX * 16, $chunkX * 16 + 15 );
$z = $random->nextRange ( $chunkZ * 16, $chunkZ * 16 + 15 );
$y = $this->getHighestWorkableBlock ( $x, $z );
if ($y !== - 1 and $cactus->canPlaceObject ( $level, $x, $y, $z, $random )) {
$cactus->placeObject ( $level, $x, $y, $z );
}
}
}
/*
* Gets the top block (y) on an x and z axes
* @param $x int
* @param $z int
*/
protected function getHighestWorkableBlock($x, $z) {
for($y = 127; $y >= 0; -- $y) {
$b = $this->level->getBlockIdAt ( $x, $y, $z );
if ($b !== Block::AIR and $b !== Block::LEAVES and $b !== Block::LEAVES2) {
break;
}
}
return $y === 0 ? - 1 : ++ $y;
}
}

View file

@ -0,0 +1,158 @@
<?php
/*
* CavePopulator from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\populator;
use pocketmine\utils\Random;
use pocketmine\block\Block;
use pocketmine\level\ChunkManager;
use pocketmine\math\Vector3;
use Ad5001\BetterGen\utils\BuildingUtils;
use Ad5001\BetterGen\populator\AmountPopulator;
class CavePopulator extends AmountPopulator {
protected $level;
const STOP = false;
const CONTINUE = true;
/*
* Populate the chunk
* @param $level pocketmine\level\ChunkManager
* @param $chunkX int
* @param $chunkZ int
* @param $random pocketmine\utils\Random
*/
public function populate(ChunkManager $level, $chunkX, $chunkZ, Random $random) {
$this->level = $level;
$amount = $this->getAmount ( $random );
for($i = 0; $i < $amount; ++ $i) {
$x = $random->nextRange ( $chunkX << 4, ($chunkX << 4) + 15 );
$z = $random->nextRange ( $chunkZ << 4, ($chunkZ << 4) + 15 );
$y = $random->nextRange ( 10, $this->getHighestWorkableBlock ( $x, $z ) );
// echo "Generating cave at $x, $y, $z." . PHP_EOL;
$this->generateCave ( $x, $y, $z, $random );
}
// echo "Finished Populating chunk $chunkX, $chunkZ !" . PHP_EOL;
// Filling water & lava sources randomly
for($i = 0; $i < $random->nextBoundedInt ( 10 ) + 15; $i ++) {
$x = $random->nextRange ( $chunkX << 4, ($chunkX << 4) + 15 );
$z = $random->nextRange ( $chunkZ << 4, ($chunkZ << 4) + 15 );
$y = $random->nextRange ( 10, $this->getHighestWorkableBlock ( $x, $z ) );
if ($level->getBlockIdAt ( $x, $y, $z ) == Block::STONE && ($level->getBlockIdAt ( $x + 1, $y, $z ) == Block::AIR || $level->getBlockIdAt ( $x - 1, $y, $z ) == Block::AIR || $level->getBlockIdAt ( $x, $y, $z + 1 ) == Block::AIR || $level->getBlockIdAt ( $x, $y, $z - 1 ) == Block::AIR) && $level->getBlockIdAt ( $x, $y - 1, $z ) !== Block::AIR && $level->getBlockIdAt ( $x, $y + 1, $z ) !== Block::AIR) {
if ($y < 40 && $random->nextBoolean ()) {
$level->setBlockIdAt ( $x, $y, $z, Block::LAVA );
} else {
$level->setBlockIdAt ( $x, $y, $z, Block::WATER );
}
}
}
}
/*
* Gets the top block (y) on an x and z axes
* @param $x int
* @param $z int
*/
protected function getHighestWorkableBlock($x, $z) {
for($y = 127; $y > 0; -- $y) {
$b = $this->level->getBlockIdAt ( $x, $y, $z );
if ($b === Block::DIRT or $b === Block::GRASS or $b === Block::PODZOL or $b === Block::SAND or $b === Block::SNOW_BLOCK or $b === Block::SANDSTONE) {
break;
} elseif ($b !== 0 and $b !== Block::SNOW_LAYER and $b !== Block::WATER) {
return - 1;
}
}
return ++ $y;
}
/*
* Generates a cave
* @param $x int
* @param $y int
* @param $z int
* @param $random pocketmine\utils\Random
* @return void
*/
public function generateCave($x, $y, $z, Random $random) {
$generatedBranches = $random->nextBoundedInt ( 10 ) + 1;
// echo "Num of branch left => " . $generatedBranches . PHP_EOL;
foreach ( $gen = $this->generateBranch ( $x, $y, $z, 5, 3, 5, $random ) as $v3 ) {
$generatedBranches --;
if ($generatedBranches <= 0) {
$gen->send ( self::STOP );
} else {
$gen->send ( self::CONTINUE );
}
}
}
/*
* Generates a cave branch.
* @param $x int
* @param $y int
* @param $z int
* @param $length int
* @param $height int
* @param $depth int
* @param $random pocketmine\utils\Random
* @yield int
* @return void
*/
public function generateBranch($x, $y, $z, $length, $height, $depth, Random $random) {
if (! (yield new Vector3 ( $x, $y, $z ))) {
for($i = 0; $i <= 4; $i ++) {
BuildingUtils::buildRandom ( $this->level, new Vector3 ( $x, $y, $z ), new Vector3 ( $length - $i, $height - $i, $depth - $i ), $random, Block::get ( Block::AIR ) );
$x += round ( ($random->nextBoundedInt ( round ( 30 * ($length / 10) ) + 1 ) / 10 - 2) );
$yP = $random->nextRange ( - 14, 14 );
if ($yP > 12) {
$y ++;
} elseif ($yP < - 12) {
$y --;
}
$z += round ( ($random->nextBoundedInt ( round ( 30 * ($depth / 10) ) + 1 ) / 10 - 1) );
return [ ];
}
}
$repeat = $random->nextBoundedInt ( 25 ) + 15;
while ( $repeat -- > 0 ) {
// echo "Y => $y; H => $height; L => $length; D => $depth; R => $repeat" . PHP_EOL;
BuildingUtils::buildRandom ( $this->level, new Vector3 ( $x, $y, $z ), new Vector3 ( $length, $height, $depth ), $random, Block::get ( Block::AIR ) );
$x += round ( ($random->nextBoundedInt ( round ( 30 * ($length / 10) ) + 1 ) / 10 - 2) );
$yP = $random->nextRange ( - 14, 14 );
if ($yP > 12) {
$y ++;
} elseif ($yP < - 12) {
$y --;
}
$z += round ( ($random->nextBoundedInt ( round ( 30 * ($depth / 10) ) + 1 ) / 10 - 1) );
$height += $random->nextBoundedInt ( 3 ) - 1;
$length += $random->nextBoundedInt ( 3 ) - 1;
$depth += $random->nextBoundedInt ( 3 ) - 1;
if ($height < 3)
$height = 3;
if ($length < 3)
$length = 3;
if ($height < 3)
$height = 3;
if ($height < 7)
$height = 7;
if ($length < 7)
$length = 7;
if ($height < 7)
$height = 7;
if ($random->nextBoundedInt ( 10 ) == 0) {
foreach ( $generator = $this->generateBranch ( $x, $y, $z, $length, $height, $depth, $random ) as $gen ) {
if (! (yield $gen))
$generator->send ( self::STOP );
}
}
}
return;
}
}

View file

@ -0,0 +1,55 @@
<?php
/*
* DeadbushPopulator from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\populator;
use pocketmine\block\Block;
use pocketmine\level\ChunkManager;
use pocketmine\utils\Random;
use Ad5001\BetterGen\populator\AmountPopulator;
class DeadbushPopulator extends AmountPopulator {
protected $level;
/*
* Populate the chunk
* @param $level pocketmine\level\ChunkManager
* @param $chunkX int
* @param $chunkZ int
* @param $random pocketmine\utils\Random
*/
public function populate(ChunkManager $level, $chunkX, $chunkZ, Random $random) {
$this->level = $level;
$amount = $this->getAmount ( $random );
for($i = 0; $i < $amount; ++ $i) {
$x = $random->nextRange ( $chunkX * 16, $chunkX * 16 + 15 );
$z = $random->nextRange ( $chunkZ * 16, $chunkZ * 16 + 15 );
$y = $this->getHighestWorkableBlock ( $x, $z );
if ($y !== - 1 && $level->getBlockIdAt ( $x, $y - 1, $z ) == Block::SAND) {
$level->setBlockIdAt ( $x, $y, $z, Block::DEAD_BUSH );
$level->setBlockDataAt ( $x, $y, $z, 1 );
}
}
}
/*
* Gets the top block (y) on an x and z axes
* @param $x int
* @param $z int
*/
protected function getHighestWorkableBlock($x, $z) {
for($y = 127; $y >= 0; -- $y) {
$b = $this->level->getBlockIdAt ( $x, $y, $z );
if ($b !== Block::AIR and $b !== Block::LEAVES and $b !== Block::LEAVES2) {
break;
}
}
return $y === 0 ? - 1 : ++ $y;
}
}

View file

@ -0,0 +1,151 @@
<?php
namespace Ad5001\BetterGen\populator;
use pocketmine\level\ChunkManager;
use pocketmine\utils\Random;
use Ad5001\BetterGen\generator\BetterNormal;
use pocketmine\block\Block;
use pocketmine\level\generator\populator\Ore;
use pocketmine\level\generator\object\OreType;
use pocketmine\math\Vector3;
use pocketmine\block\CoalOre;
use pocketmine\block\IronOre;
use pocketmine\block\RedstoneOre;
use pocketmine\block\LapisOre;
use pocketmine\block\GoldOre;
use pocketmine\block\DiamondOre;
/*
* FloatingIslandPopulator from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
class FloatingIslandPopulator extends AmountPopulator {
/*
* Populate the chunk
* @param $level pocketmine\level\ChunkManager
* @param $chunkX int
* @param $chunkZ int
* @param $random pocketmine\utils\Random
*/
public function populate(ChunkManager $level, $chunkX, $chunkZ, Random $random) {
$this->level = $level;
if($this->getAmount($random) > 130) {
$x = $random->nextRange(($chunkX << 4), ($chunkX << 4) + 15);
$z = $random->nextRange(($chunkX << 4), ($chunkX << 4) + 15);
$y = $random->nextRange($this->getHighestWorkableBlock($x, $z) < 96 ? $this->getHighestWorkableBlock($x, $z) + 20 : $this->getHighestWorkableBlock($x, $z), 126);
$radius = $random->nextRange(5, 8);
$height = $this->buildIslandBottomShape($level, new Vector3($x, $y, $z), $radius, $random);
$this->populateOres($level, new Vector3($x, $y - 1, $z), $radius * 2, $height, $random);
$chunk = $level->getChunk($chunkX, $chunkZ);
$biome = BetterNormal::getBiomeById($chunk->getBiomeId($x % 16, $z % 16));
$populators = $biome->getPopulators();
foreach($populators as $populator) {
$populator->populate($level, $chunkX, $chunkZ, $random);
}
}
}
/*
* Gets the top block (y) on an x and z axes
* @param $x int
* @param $z int
*/
protected function getHighestWorkableBlock($x, $z) {
for($y = 127; $y > 0; -- $y) {
$b = $this->level->getBlockIdAt ( $x, $y, $z );
if ($b === Block::DIRT or $b === Block::GRASS or $b === Block::PODZOL or $b === Block::SAND) {
break;
} elseif ($b !== 0 and $b !== Block::SNOW_LAYER) {
return 90;
}
}
return ++ $y;
}
/*
* Builds a an island shape
* @param $level pocketmine\level\ChunkManager
* @param $pos pocketmine\math\Vector3
* @param $radius int
* @param $random pocketmine\utils\Random
* @return void
*/
public function buildIslandBottomShape(ChunkManager $level, Vector3 $pos, int $radius, Random $random) {
$pos = $pos->round();
$xx = $pos->x;
$zz = $z;
$currentLen = 1;
$isEdge = false;
$hBound = 0;
$current = 0;
for($y = $pos->y - 1; $radius > 0; $y--) {
for($x = $pos->x - $radius; $x <= $pos->x + $radius; $x++) {
for($z = $pos->z - $radius; $z <= $pos->z + $radius; $z ++) {
if(abs(abs($x - $pos->x) ** 2) + abs(abs($z - $pos->z) ** 2) == ($radius ** 2) * 0.67) {
$isEdge = true;
} else {
$isEdge = false;
}
if(abs(abs($x - $pos->x) ** 2) + abs(abs($z - $pos->z) ** 2) <= ($radius ** 2) * 0.67 && $y < 128) {
if($chunk = $level->getChunk($x >> 4, $z >> 4)) {
$biome = BetterNormal::getBiomeById($chunk->getBiomeId($x % 16, $z % 16));
$block = $biome->getGroundCover()[$pos->y - $y - 1] ?? Block::get(Block::STONE);
$block = $block->getId();
} elseif($random->nextBoundedInt(5) == 0 && $isEdge) {
$block = Block::AIR;
} else {
$block = Block::STONE;
}
$level->setBlockIdAt($x, $y, $z, $block ?? Block::STONE);
}
}
}
$current++;
$oldHB = $hBound;
$hBound = $random->nextFloat();
if($current >= $currentLen + $hBound) {
if($radius == 0) return;
$current = 0;
$currentLen += 0.3 * ($random->nextFloat() + 0.5);
$radius--;
}
}
return $pos->y - 1 - $y;
}
/*
* BPopulate the island with ores
* @param $level pocketmine\level\ChunkManager
* @param $pos pocketmine\math\Vector3
* @param $width int
* @param $height int
* @param $random pocketmine\utils\Random
* @return void
*/
public function populateOres(ChunkManager $level, Vector3 $pos, int $width, int $height, Random $random) {
$ores = new Ore ();
$ores->setOreTypes ( [
new OreType ( new CoalOre (), 20, 16, $pos->y - $height, $pos->y ),
new OreType ( new IronOre (), 20, 8, $pos->y - $height, $pos->y - round($height * 0.75)),
new OreType ( new RedstoneOre (), 8, 7, $pos->y - $height, $pos->y - round($height / 2)),
new OreType ( new LapisOre (), 1, 6, $pos->y - $height, $pos->y - round($height / 2)),
new OreType ( new GoldOre (), 2, 8, $pos->y - $height, $pos->y - round($height / 2)),
new OreType ( new DiamondOre (), 1, 7, $pos->y - $height, $pos->y - round($height / 4))
] );
$ores->populate($level, $x >> 4, $z >> 4, $random);
}
}

View file

@ -0,0 +1,56 @@
<?php
/*
* IglooPopulator from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\populator;
use pocketmine\utils\Random;
use pocketmine\block\Block;
use pocketmine\level\ChunkManager;
use Ad5001\BetterGen\populator\AmountPopulator;
use Ad5001\BetterGen\structure\Igloo;
class IglooPopulator extends AmountPopulator {
protected $level;
/*
* Populate the chunk
* @param $level pocketmine\level\ChunkManager
* @param $chunkX int
* @param $chunkZ int
* @param $random pocketmine\utils\Random
*/
public function populate(ChunkManager $level, $chunkX, $chunkZ, Random $random) {
$this->level = $level;
if ($random->nextBoundedInt ( 100 ) > 30)
return;
$igloo = new Igloo ();
$x = $random->nextRange ( $chunkX << 4, ($chunkX << 4) + 15 );
$z = $random->nextRange ( $chunkZ << 4, ($chunkZ << 4) + 15 );
$y = $this->getHighestWorkableBlock ( $x, $z ) - 1;
if ($igloo->canPlaceObject ( $level, $x, $y, $z, $random ))
$igloo->placeObject ( $level, $x, $y, $z, $random );
}
/*
* Gets the top block (y) on an x and z axes
* @param $x int
* @param $z int
*/
protected function getHighestWorkableBlock($x, $z) {
for($y = 127; $y > 0; -- $y) {
$b = $this->level->getBlockIdAt ( $x, $y, $z );
if ($b === Block::DIRT or $b === Block::GRASS or $b === Block::PODZOL) {
break;
} elseif ($b !== 0 and $b !== Block::SNOW_LAYER) {
return - 1;
}
}
return ++ $y;
}
}

View file

@ -0,0 +1,65 @@
<?php
/*
* LakePopulator from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\populator;
use pocketmine\utils\Random;
use pocketmine\block\Block;
use pocketmine\level\ChunkManager;
use pocketmine\math\Vector3;
use Ad5001\BetterGen\utils\BuildingUtils;
use Ad5001\BetterGen\populator\AmountPopulator;
class LakePopulator extends AmountPopulator {
protected $level;
/*
* Populate the chunk
* @param $level pocketmine\level\ChunkManager
* @param $chunkX int
* @param $chunkZ int
* @param $random pocketmine\utils\Random
*/
public function populate(ChunkManager $level, $chunkX, $chunkZ, Random $random) {
$this->level = $level;
$x = $random->nextRange ( $chunkX << 4, ($chunkX << 4) + 15 );
$z = $random->nextRange ( $chunkZ << 4, ($chunkZ << 4) + 15 );
$ory = $random->nextRange ( 20, 63 ); // Water level
$y = $ory;
for($i = 0; $i < 4; $i ++) {
$x += $random->nextRange ( - 1, 1 );
$y += $random->nextRange ( - 1, 1 );
$z += $random->nextRange ( - 1, 1 );
if ($level->getBlockIdAt ( $x, $y, $z ) !== Block::AIR)
BuildingUtils::buildRandom ( $this->level, new Vector3 ( $x, $y, $z ), new Vector3 ( 5, 5, 5 ), $random, Block::get ( Block::WATER ) );
}
for($xx = $x - 8; $xx <= $x + 8; $xx ++)
for($zz = $z - 8; $zz <= $z + 8; $zz ++)
for($yy = $ory + 1; $yy <= $y + 3; $yy ++)
if ($level->getBlockIdAt ( $xx, $yy, $zz ) == Block::WATER)
$level->setBlockIdAt ( $xx, $yy, $zz, Block::AIR );
}
/*
* Gets the top block (y) on an x and z axes
* @param $x int
* @param $z int
*/
protected function getHighestWorkableBlock($x, $z) {
for($y = 127; $y > 0; -- $y) {
$b = $this->level->getBlockIdAt ( $x, $y, $z );
if ($b === Block::DIRT or $b === Block::GRASS or $b === Block::PODZOL) {
break;
} elseif ($b !== 0 and $b !== Block::SNOW_LAYER) {
return - 1;
}
}
return ++ $y;
}
}

View file

@ -0,0 +1,427 @@
<?php
/*
* MineshaftPopulator from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\populator;
use pocketmine\level\ChunkManager;
use pocketmine\utils\Random;
use Ad5001\BetterGen\utils\BuildingUtils;
use pocketmine\math\Vector3;
use pocketmine\block\Block;
use Ad5001\BetterGen\loot\LootTable;
class MineshaftPopulator extends AmountPopulator {
protected $maxPath;
protected $level;
const DIR_XPLUS = 0;
const DIR_XMIN = 1;
const DIR_ZPLUS = 2;
const DIR_ZMIN = 3;
const TYPE_FORWARD = 0;
const TYPE_CROSSPATH = 1;
const TYPE_STAIRS = 2;
/*
* Populate the chunk
* @param $level pocketmine\level\ChunkManager
* @param $chunkX int
* @param $chunkZ int
* @param $random pocketmine\utils\Random
*/
public function populate(ChunkManager $level, $chunkX, $chunkZ, Random $random) {
if ($this->getAmount ( $random ) < 100)
return;
$this->level = $level;
$x = $random->nextRange ( $chunkX << 4, ($chunkX << 4) + 15 );
$z = $random->nextRange ( $chunkZ << 4, ($chunkZ << 4) + 15 );
$y = $random->nextRange ( 5, 50 );
// First filling the large dirt place (center of the mineshaft)
BuildingUtils::fill ( $level, new Vector3 ( $x - 6, $y, $x - 6 ), new Vector3 ( $x + 6, $y + 8, $z + 6 ), Block::get ( Block::AIR ) );
BuildingUtils::fill ( $level, new Vector3 ( $x - 6, $y, $x - 6 ), new Vector3 ( $x + 6, $y, $z + 6 ), Block::get ( Block::DIRT ) );
$startingPath = $random->nextBoundedInt ( 4 );
$this->maxPath = $random->nextBoundedInt ( 100 ) + 50;
foreach ( array_fill ( 0, $startingPath, 1 ) as $hey ) {
$dir = $random->nextBoundedInt ( 4 );
switch ($dir) {
case self::DIR_XPLUS :
$this->generateMineshaftPart ( $x + 6, $y + $random->nextBoundedInt ( 5 ), $z + $random->nextBoundedInt ( 12 ) - 6, $dir, $random );
break;
case self::DIR_XMIN :
$this->generateMineshaftPart ( $x - 6, $y + $random->nextBoundedInt ( 5 ), $z + $random->nextBoundedInt ( 12 ) - 6, $dir, $random );
break;
case self::DIR_ZPLUS :
$this->generateMineshaftPart ( $x + $random->nextBoundedInt ( 12 ) - 6, $y + $random->nextBoundedInt ( 8 ), $z + 6, $dir, $random );
break;
case self::DIR_ZMIN :
$this->generateMineshaftPart ( $x + $random->nextBoundedInt ( 12 ) - 6, $y + $random->nextBoundedInt ( 8 ), $z - 6, $dir, $random );
break;
}
}
}
/*
* Builds a mineshaft part and return applicable directions
* @param $x int
* @param $y int
* @param $z int
* @param $dir int
* @param $random pocketmine\utils\Random
* @param $deepneth int
*/
public function generateMineshaftPart(int $x, int $y, int $z, int $dir, Random $random) {
if ($this->maxPath -- < 1)
return;
$type = $random->nextBoundedInt ( 3 );
$level = $this->level;
switch ($type) {
case self::TYPE_FORWARD :
switch ($dir) {
case self::DIR_XPLUS :
// First, filling everything blank.
BuildingUtils::fill ( $this->level, new Vector3 ( $x, $y, $z - 1 ), new Vector3 ( $x + 4, $y + 2, $z + 1 ), Block::get ( Block::AIR ) );
// Then, making sure the floor is solid.
BuildingUtils::fillCallback ( new Vector3 ( $x, $y - 1, $z - 1 ), new Vector3 ( $x + 4, $y - 1, $z + 1 ), function ($v3, $params) {
$level = $params [0];
if ($level->getBlockIdAt ( $v3->x, $v3->y, $v3->z ) == Block::AIR)
$level->setBlockIdAt ( $v3->x, $v3->y, $v3->z, Block::PLANK );
}, $this->level );
// Putting rails
BuildingUtils::fillCallback ( new Vector3 ( $x, $y, $z ), new Vector3 ( $x + 4, $y, $z ), function ($v3, $params) {
$level = $params [0];
$random = $params [1];
if ($random->nextBoundedInt ( 3 ) !== 0) {
$level->setBlockIdAt ( $v3->x, $v3->y, $v3->z, Block::RAIL );
$level->setBlockDataAt ( $v3->x, $v3->y, $v3->z, 1 );
}
}, $this->level, $random );
// After this, building the floor maintener (the wood structure)
$level->setBlockIdAt ( $x, $y, $z - 1, Block::FENCE );
$level->setBlockIdAt ( $x, $y, $z + 1, Block::FENCE );
$level->setBlockIdAt ( $x, $y + 1, $z - 1, Block::FENCE );
$level->setBlockIdAt ( $x, $y + 1, $z + 1, Block::FENCE );
$level->setBlockIdAt ( $x, $y + 2, $z - 1, Block::PLANK );
$level->setBlockIdAt ( $x, $y + 2, $z, Block::PLANK );
$level->setBlockIdAt ( $x, $y + 2, $z + 1, Block::PLANK );
$level->setBlockIdAt ( $x + 1, $y + 2, $z, Block::TORCH );
$level->setBlockDataAt ( $x + 1, $y + 2, $z, 2 );
// Generating chest
if ($random->nextBoundedInt ( 30 ) == 0) {
$direction = ( int ) $random->nextBoolean ();
if ($direction == 0)
$direction = - 1; // Choosing the part of the rail.
$direction2 = ( int ) $random->nextBoolean ();
if ($direction2 == 0)
$direction2 = 2;
if ($direction2 == 1)
$direction2 = 4;
LootTable::buildLootTable ( new Vector3 ( $x + $direction2, $y, $z + $direction ), LootTable::LOOT_MINESHAFT, $random );
}
if ($random->nextBoundedInt ( 30 ) !== 0)
$this->generateMineshaftPart ( $x + 5, $y, $z, $dir, $random );
break;
case self::DIR_XMIN :
// First, filling everything blank.
BuildingUtils::fill ( $this->level, new Vector3 ( $x, $y, $z - 1 ), new Vector3 ( $x - 4, $y + 2, $z + 1 ) );
// Then, making sure the floor is solid.
BuildingUtils::fillCallback ( new Vector3 ( $x, $y - 1, $z - 1 ), new Vector3 ( $x - 4, $y - 1, $z + 1 ), function ($v3, $params) {
$level = $params [0];
if ($level->getBlockIdAt ( $v3->x, $v3->y, $v3->z ) == Block::AIR)
$level->setBlockIdAt ( $v3->x, $v3->y, $v3->z, Block::PLANK );
}, $this->level );
// Putting rails
BuildingUtils::fillCallback ( new Vector3 ( $x, $y, $z ), new Vector3 ( $x - 4, $y, $z ), function ($v3, $params) {
$level = $params [0];
$random = $params [1];
if ($random->nextBoundedInt ( 3 ) !== 0) {
$level->setBlockIdAt ( $v3->x, $v3->y, $v3->z, Block::RAIL );
$level->setBlockDataAt ( $v3->x, $v3->y, $v3->z, 1 );
}
}, $this->level, $random );
// After this, building the floor maintener (the wood structure)
$level->setBlockIdAt ( $x, $y, $z - 1, Block::FENCE );
$level->setBlockIdAt ( $x, $y, $z + 1, Block::FENCE );
$level->setBlockIdAt ( $x, $y + 1, $z - 1, Block::FENCE );
$level->setBlockIdAt ( $x, $y + 1, $z + 1, Block::FENCE );
$level->setBlockIdAt ( $x, $y + 2, $z - 1, Block::PLANK );
$level->setBlockIdAt ( $x, $y + 2, $z, Block::PLANK );
$level->setBlockIdAt ( $x, $y + 2, $z + 1, Block::PLANK );
$level->setBlockIdAt ( $x - 1, $y + 2, $z, Block::TORCH );
$level->setBlockDataAt ( $x - 1, $y + 2, $z, 1 );
// Generating chest
if ($random->nextBoundedInt ( 30 ) == 0) {
$direction = ( int ) $random->nextBoolean ();
if ($direction == 0)
$direction = - 1; // Choosing the part of the rail.
$direction2 = ( int ) $random->nextBoolean ();
if ($direction2 == 0)
$direction2 = 2;
if ($direction2 == 1)
$direction2 =
LootTable::buildLootTable ( new Vector3 ( $x - $direction2, $y, $z + $direction ), LootTable::LOOT_MINESHAFT, $random );
}
if ($random->nextBoundedInt ( 30 ) !== 0)
$this->generateMineshaftPart ( $x - 5, $y, $z, $dir, $random );
break;
case self::DIR_ZPLUS :
// First, filling everything blank.
BuildingUtils::fill ( $this->level, new Vector3 ( $x - 1, $y, $z ), new Vector3 ( $x + 1, $y + 2, $z + 4 ) );
// Then, making sure the floor is solid.
BuildingUtils::fillCallback ( new Vector3 ( $x - 1, $y - 1, $z ), new Vector3 ( $x + 1, $y - 1, $z + 4 ), function ($v3, $params) {
$level = $params [0];
if ($level->getBlockIdAt ( $v3->x, $v3->y, $v3->z ) == Block::AIR)
$level->setBlockIdAt ( $v3->x, $v3->y, $v3->z, Block::PLANK );
}, $this->level );
// Putting rails
BuildingUtils::fillCallback ( new Vector3 ( $x, $y, $z ), new Vector3 ( $x, $y, $z + 4 ), function ($v3, $params) {
$level = $params [0];
$random = $params [1];
if ($random->nextBoundedInt ( 3 ) !== 0) {
$level->setBlockIdAt ( $v3->x, $v3->y, $v3->z, Block::RAIL );
$level->setBlockDataAt ( $v3->x, $v3->y, $v3->z, 0 );
}
}, $this->level, $random );
// After this, building the floor maintener (the wood structure)
$level->setBlockIdAt ( $x - 1, $y, $z, Block::FENCE );
$level->setBlockIdAt ( $x + 1, $y, $z, Block::FENCE );
$level->setBlockIdAt ( $x - 1, $y + 1, $z, Block::FENCE );
$level->setBlockIdAt ( $x + 1, $y + 1, $z, Block::FENCE );
$level->setBlockIdAt ( $x - 1, $y + 2, $z, Block::PLANK );
$level->setBlockIdAt ( $x, $y + 2, $z, Block::PLANK );
$level->setBlockIdAt ( $x + 1, $y + 2, $z, Block::PLANK );
$level->setBlockIdAt ( $x, $y + 2, $z - 1, Block::TORCH );
$level->setBlockDataAt ( $x, $y + 2, $z - 1, 4 );
// Generating chest
if ($random->nextBoundedInt ( 30 ) == 0) {
$direction = ( int ) $random->nextBoolean ();
if ($direction == 0)
$direction = - 1; // Choosing the part of the rail.
$direction2 = ( int ) $random->nextBoolean ();
if ($direction2 == 0)
$direction2 = 2;
if ($direction2 == 1)
$direction2 = 4;
LootTable::buildLootTable ( new Vector3 ( $x + $direction, $y, $z + $direction2 ), LootTable::LOOT_MINESHAFT, $random );
}
if ($random->nextBoundedInt ( 30 ) !== 0)
$this->generateMineshaftPart ( $x, $y, $z + 5, $dir, $random );
break;
case self::DIR_ZMIN :
// First, filling everything blank.
BuildingUtils::fill ( $this->level, new Vector3 ( $x - 1, $y, $z ), new Vector3 ( $x + 1, $y + 2, $z - 4 ) );
// Then, making sure the floor is solid.
BuildingUtils::fillCallback ( new Vector3 ( $x - 1, $y - 1, $z ), new Vector3 ( $x + 1, $y - 1, $z - 4 ), function ($v3, $params) {
$level = $params [0];
if ($level->getBlockIdAt ( $v3->x, $v3->y, $v3->z ) == Block::AIR)
$level->setBlockIdAt ( $v3->x, $v3->y, $v3->z, Block::PLANK );
}, $this->level );
// Putting rails
BuildingUtils::fillCallback ( new Vector3 ( $x, $y, $z ), new Vector3 ( $x, $y, $z - 4 ), function ($v3, $params) {
$level = $params [0];
$random = $params [1];
if ($random->nextBoundedInt ( 3 ) !== 0) {
$level->setBlockIdAt ( $v3->x, $v3->y, $v3->z, Block::RAIL );
$level->setBlockDataAt ( $v3->x, $v3->y, $v3->z, 0 );
}
}, $this->level, $random );
// After this, building the floor maintener (the wood structure)
$level->setBlockIdAt ( $x - 1, $y, $z, Block::FENCE );
$level->setBlockIdAt ( $x + 1, $y, $z, Block::FENCE );
$level->setBlockIdAt ( $x - 1, $y + 1, $z, Block::FENCE );
$level->setBlockIdAt ( $x + 1, $y + 1, $z, Block::FENCE );
$level->setBlockIdAt ( $x - 1, $y + 2, $z, Block::PLANK );
$level->setBlockIdAt ( $x, $y + 2, $z, Block::PLANK );
$level->setBlockIdAt ( $x + 1, $y + 2, $z, Block::PLANK );
$level->setBlockIdAt ( $x, $y + 2, $z - 1, Block::TORCH );
$level->setBlockDataAt ( $x, $y + 2, $z - 1, 3 );
// Generating chest
if ($random->nextBoundedInt ( 30 ) == 0) {
$direction = ( int ) $random->nextBoolean ();
if ($direction == 0)
$direction = - 1; // Choosing the part of the rail.
$direction2 = ( int ) $random->nextBoolean ();
if ($direction2 == 0)
$direction2 = 2;
if ($direction2 == 1)
$direction2 = 4;
LootTable::buildLootTable ( new Vector3 ( $x + $direction, $y, $z - $direction2 ), LootTable::LOOT_MINESHAFT, $random );
}
if ($random->nextBoundedInt ( 30 ) !== 0)
$this->generateMineshaftPart ( $x, $y, $z - 5, $dir, $random );
break;
}
// Doing cobwebs
$webNum = $random->nextBoundedInt ( 5 ) + 2;
for($i = 0; $i < $webNum; $i ++) {
$xx = $x + $random->nextBoundedInt ( 5 ) - 2;
$yy = $y + $random->nextBoundedInt ( 3 );
$zz = $z + $random->nextBoundedInt ( 5 ) - 2;
if ($level->getBlockIdAt ( $xx, $yy, $zz ) == Block::AIR)
$level->setBlockIdAt ( $xx, $yy, $zz, Block::COBWEB );
}
break;
case self::TYPE_CROSSPATH :
$possiblePathes = [
self::DIR_XPLUS,
self::DIR_XMIN,
self::DIR_ZPLUS,
self::DIR_ZMIN
];
switch ($dir) {
case self::DIR_XPLUS :
$x ++;
unset ( $possiblePathes [0] );
break;
case self::DIR_XMIN :
$x --;
unset ( $possiblePathes [1] );
break;
case self::DIR_ZPLUS :
$z ++;
unset ( $possiblePathes [2] );
break;
case self::DIR_ZMIN :
$z --;
unset ( $possiblePathes [3] );
break;
}
// Then, making sure the floor is solid.
BuildingUtils::fillCallback ( new Vector3 ( $x + 1, $y - 1, $z - 1 ), new Vector3 ( $x - 1, $y - 1, $z + 1 ), function ($v3, $params) {
$level = $params [0];
if ($level->getBlockIdAt ( $v3->x, $v3->y, $v3->z ) == Block::AIR)
$level->setBlockIdAt ( $v3->x, $v3->y, $v3->z, Block::PLANK );
}, $this->level );
// Putting rails
BuildingUtils::fill ( $this->level, new Vector3 ( $x - 1, $y, $z - 1 ), new Vector3 ( $x + 1, $y + 6, $z + 1 ), Block::get ( Block::AIR ) );
BuildingUtils::corners ( $this->level, new Vector3 ( $x - 1, $y, $z - 1 ), new Vector3 ( $x + 1, $y + 6, $z + 1 ), Block::get ( Block::PLANK ) );
$newFloor = $random->nextBoolean ();
$numberFloor = $random->nextBoundedInt ( 4 + ($newFloor ? 5 : 0) );
$possiblePathes = [
$possiblePathes,
($newFloor ? [
self::DIR_XPLUS,
self::DIR_XMIN,
self::DIR_ZPLUS,
self::DIR_ZMIN
] : [ ])
];
for($i = 7; $i > $newfloor; $i --) {
$chooseNew = ( int ) $newFloor && $random->nextBoolean ();
$choose = $random->nextBoundedInt ( 4 );
unset ( $possiblePathes [$chooseNew] [$choose] );
}
// Buidling pathes
foreach ( $possiblePathes [0] as $path ) {
switch ($path) {
case self::DIR_XPLUS :
$this->generateMineshaftPart ( $x + 2, $y, $z, self::DIR_XPLUS, $random );
break;
case self::DIR_XMIN :
$this->generateMineshaftPart ( $x - 2, $y, $z, self::DIR_XMIN, $random );
break;
case self::DIR_ZPLUS :
$this->generateMineshaftPart ( $x, $y, $z + 2, self::DIR_ZPLUS, $random );
break;
case self::DIR_ZMIN :
$this->generateMineshaftPart ( $x, $y, $z - 2, self::DIR_ZMIN, $random );
break;
}
}
foreach ( $possiblePathes [1] as $path ) {
switch ($path) {
case self::DIR_XPLUS :
$this->generateMineshaftPart ( $x + 2, $y + 4, $z, self::DIR_XPLUS, $random );
break;
case self::DIR_XMIN :
$this->generateMineshaftPart ( $x - 2, $y + 4, $z, self::DIR_XMIN, $random );
break;
case self::DIR_ZPLUS :
$this->generateMineshaftPart ( $x, $y + 4, $z + 2, self::DIR_ZPLUS, $random );
break;
case self::DIR_ZMIN :
$this->generateMineshaftPart ( $x, $y + 4, $z - 2, self::DIR_ZMIN, $random );
break;
}
}
// Doing cobwebs
$webNum = $random->nextBoundedInt ( 5 ) + 2;
for($i = 0; $i < $webNum; $i ++) {
$xx = $x + $random->nextBoundedInt ( 3 ) - 1;
$yy = $y + $random->nextBoundedInt ( 6 );
$zz = $z + $random->nextBoundedInt ( 3 ) - 1;
if ($level->getBlockIdAt ( $xx, $yy, $zz ) == Block::AIR)
$level->setBlockIdAt ( $xx, $yy, $zz, Block::COBWEB );
}
break;
case self::TYPE_STAIRS :
if($y <= 5) {
$this->generateMineshaftPart ( $x, $y, $z, $dir, $random );
return;
}
// Building stairs
for($i = 0; $i < 4; $i ++) {
switch ($path) {
case self::DIR_XPLUS :
BuildingUtils::fill ( $this->level, new Vector3 ( $x + $i, $y - $i - 1, $z - 2 ), new Vector3 ( $x + $i, $y - $i + 3, $z + 2 ), Block::get ( Block::AIR ) );
BuildingUtils::fillCallback ( new Vector3 ( $x + $i, $y - $i - 2, $z - 2 ), new Vector3 ( $x + $i, $y - $i - 2, $z + 2 ), function ($v3, $params) {
$level = $params [0];
if ($level->getBlockIdAt ( $v3->x, $v3->y, $v3->z ) == Block::AIR)
$level->setBlockIdAt ( $v3->x, $v3->y, $v3->z, Block::PLANK );
}, $this->level );
break;
case self::DIR_XMIN :
BuildingUtils::fill ( $this->level, new Vector3 ( $x - $i, $y - $i - 1, $z - 2 ), new Vector3 ( $x - $i, $y - $i + 3, $z + 2 ), Block::get ( Block::AIR ) );
BuildingUtils::fillCallback ( new Vector3 ( $x - $i, $y - $i - 2, $z - 2 ), new Vector3 ( $x - $i, $y - $i - 2, $z + 2 ), function ($v3, $params) {
$level = $params [0];
if ($level->getBlockIdAt ( $v3->x, $v3->y, $v3->z ) == Block::AIR)
$level->setBlockIdAt ( $v3->x, $v3->y, $v3->z, Block::PLANK );
}, $this->level );
break;
case self::DIR_ZPLUS :
BuildingUtils::fill ( $this->level, new Vector3 ( $x - 2, $y - $i - 1, $z + $i ), new Vector3 ( $x + 2, $y - $i + 3, $z + $i ), Block::get ( Block::AIR ) );
BuildingUtils::fillCallback ( new Vector3 ( $x - 2, $y - $i - 2, $z + $i ), new Vector3 ( $x + 2, $y - $i - 2, $z + $i ), function ($v3, $params) {
$level = $params [0];
if ($level->getBlockIdAt ( $v3->x, $v3->y, $v3->z ) == Block::AIR)
$level->setBlockIdAt ( $v3->x, $v3->y, $v3->z, Block::PLANK );
}, $this->level );
break;
case self::DIR_ZMIN :
BuildingUtils::fill ( $this->level, new Vector3 ( $x - 2, $y - $i - 1, $z - $i ), new Vector3 ( $x + 2, $y - $i + 3, $z - $i ), Block::get ( Block::AIR ) );
BuildingUtils::fillCallback ( new Vector3 ( $x - 2, $y - $i - 2, $z - $i ), new Vector3 ( $x + 2, $y - $i - 2, $z - $i ), function ($v3, $params) {
$level = $params [0];
if ($level->getBlockIdAt ( $v3->x, $v3->y, $v3->z ) == Block::AIR)
$level->setBlockIdAt ( $v3->x, $v3->y, $v3->z, Block::PLANK );
}, $this->level );
break;
}
}
// Next one
switch ($path) {
case self::DIR_XPLUS :
$this->generateMineshaftPart ( $x + 4, $y - 4, $z, self::DIR_XPLUS, $random );
break;
case self::DIR_XMIN :
$this->generateMineshaftPart ( $x - 4, $y - 4, $z, self::DIR_XMIN, $random );
break;
case self::DIR_ZPLUS :
$this->generateMineshaftPart ( $x, $y - 4, $z + 4, self::DIR_ZPLUS, $random );
break;
case self::DIR_ZMIN :
$this->generateMineshaftPart ( $x, $y - 4, $z - 4, self::DIR_ZMIN, $random );
break;
}
break;
}
}
}
?>

View file

@ -0,0 +1,121 @@
<?php
/*
* RavinePopulator from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\populator;
use pocketmine\utils\Random;
use pocketmine\block\Block;
use pocketmine\level\ChunkManager;
use Ad5001\BetterGen\populator\AmountPopulator;
use Ad5001\BetterGen\utils\BuildingUtils;
class RavinePopulator extends AmountPopulator {
protected $level;
const NOISE = 250;
/*
* Populate the chunk
* @param $level pocketmine\level\ChunkManager
* @param $chunkX int
* @param $chunkZ int
* @param $random pocketmine\utils\Random
*/
public function populate(ChunkManager $level, $chunkX, $chunkZ, Random $random) {
$this->level = $level;
$amount = $this->getAmount ( $random );
if ($amount > 50) { // Only build one per chunk
$depth = $random->nextBoundedInt ( 60 ) + 30; // 2Much4U?
$x = $random->nextRange ( $chunkX << 4, ($chunkX << 4) + 15 );
$z = $random->nextRange ( $chunkZ << 4, ($chunkZ << 4) + 15 );
$y = $random->nextRange ( 5, $this->getHighestWorkableBlock ( $x, $z ) );
$deffX = $x;
$deffZ = $z;
$height = $random->nextRange ( 15, 30 );
$length = $random->nextRange ( 5, 12 );
for($i = 0; $i < $depth; $i ++) {
$this->buildRavinePart ( $x, $y, $z, $height, $length, $random );
$diffX = $x - $deffX;
$diffZ = $z - $deffZ;
if ($diffX > $length / 2)
$diffX = $length / 2;
if ($diffX < - $length / 2)
$diffX = - $length / 2;
if ($diffZ > $length / 2)
$diffZ = $length / 2;
if ($diffZ < - $length / 2)
$diffZ = - $length / 2;
if ($length > 10)
$length = 10;
if ($length < 5)
$length = 5;
$x += $random->nextRange ( 0 + $diffX, 2 + $diffX ) - 1;
$y += $random->nextRange ( 0, 2 ) - 1;
$z += $random->nextRange ( 0 + $diffZ, 2 + $diffZ ) - 1;
$heigth += $random->nextRange ( 0, 2 ) - 1;
$length += $random->nextRange ( 0, 2 ) - 1;
}
}
}
/*
* Gets the top block (y) on an x and z axes
* @param $x int
* @param $z int
*/
protected function getHighestWorkableBlock($x, $z) {
for($y = 127; $y > 0; -- $y) {
$b = $this->level->getBlockIdAt ( $x, $y, $z );
if ($b === Block::DIRT or $b === Block::GRASS or $b === Block::PODZOL or $b === Block::SAND or $b === Block::SNOW_BLOCK or $b === Block::SANDSTONE) {
break;
} elseif ($b !== 0 and $b !== Block::SNOW_LAYER and $b !== Block::WATER) {
return - 1;
}
}
return ++ $y;
}
/*
* Builds a ravine part
* @param $x int
* @param $y int
* @param $z int
* @param $height int
* @param $length int
* @param $random pocketmine\utils\Random
*/
protected function buildRavinePart($x, $y, $z, $height, $length, Random $random) {
for($xx = $x - $length; $xx <= $x + $length; $xx ++) {
for($yy = $y; $yy <= $y + $height; $yy ++) {
for($zz = $z - $length; $zz <= $z + $length; $zz ++) {
$oldXB = $xBounded;
$xBounded = $random->nextBoundedInt ( self::NOISE * 2 ) - self::NOISE;
$oldZB = $zBounded;
$zBounded = $random->nextBoundedInt ( self::NOISE * 2 ) - self::NOISE;
if ($xBounded > self::NOISE - 2) {
$xBounded = 1;
} elseif ($xBounded < - self::NOISE + 2) {
$xBounded = - 1;
} else {
$xBounded = $oldXB;
}
if ($zBounded > self::NOISE - 2) {
$zBounded = 1;
} elseif ($zBounded < - self::NOISE + 2) {
$zBounded = - 1;
} else {
$zBounded = $oldZB;
}
if (abs ( (abs ( $xx ) - abs ( $x )) ** 2 + (abs ( $zz ) - abs ( $z )) ** 2 ) < ((($length / 2 - $xBounded) + ($length / 2 - $zBounded)) / 2) ** 2 && $y > 0 && ! in_array ( $this->level->getBlockIdAt ( ( int ) round ( $xx ), ( int ) round ( $yy ), ( int ) round ( $zz ) ), BuildingUtils::TO_NOT_OVERWRITE ) && ! in_array ( $this->level->getBlockIdAt ( ( int ) round ( $xx ), ( int ) round ( $yy + 1 ), ( int ) round ( $zz ) ), BuildingUtils::TO_NOT_OVERWRITE )) {
$this->level->setBlockIdAt ( ( int ) round ( $xx ), ( int ) round ( $yy ), ( int ) round ( $zz ), Block::AIR );
}
}
}
}
}
}

View file

@ -0,0 +1,63 @@
<?php
/*
* SugarCanePopulator from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\populator;
use pocketmine\block\Block;
use pocketmine\level\ChunkManager;
use pocketmine\utils\Random;
use Ad5001\BetterGen\structure\SugarCane;
use Ad5001\BetterGen\populator\AmountPopulator;
class SugarCanePopulator extends AmountPopulator {
protected $level;
/*
* Constructs the class
*/
public function __construct() {
$this->setBaseAmount ( 1 );
$this->setRandomAmount ( 2 );
}
/*
* Populate the chunk
* @param $level pocketmine\level\ChunkManager
* @param $chunkX int
* @param $chunkZ int
* @param $random pocketmine\utils\Random
*/
public function populate(ChunkManager $level, $chunkX, $chunkZ, Random $random) {
$this->level = $level;
$amount = $this->getAmount ( $random );
$sugarcane = new SugarCane ();
for($i = 0; $i < $amount; ++ $i) {
$x = $random->nextRange ( $chunkX * 16, $chunkX * 16 + 15 );
$z = $random->nextRange ( $chunkZ * 16, $chunkZ * 16 + 15 );
$y = $this->getHighestWorkableBlock ( $x, $z );
if ($y !== - 1 and $sugarcane->canPlaceObject ( $level, $x, $y, $z, $random )) {
$sugarcane->placeObject ( $level, $x, $y, $z );
}
}
}
/*
* Gets the top block (y) on an x and z axes
* @param $x int
* @param $z int
*/
protected function getHighestWorkableBlock($x, $z) {
for($y = 127; $y >= 0; -- $y) {
$b = $this->level->getBlockIdAt ( $x, $y, $z );
if ($b !== Block::AIR and $b !== Block::LEAVES and $b !== Block::LEAVES2) {
break;
}
}
return $y === 0 ? - 1 : ++ $y;
}
}

View file

@ -0,0 +1,54 @@
<?php
/*
* TemplePopulator from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\populator;
use pocketmine\utils\Random;
use pocketmine\block\Block;
use pocketmine\level\ChunkManager;
use Ad5001\BetterGen\structure\Temple;
use Ad5001\BetterGen\populator\AmountPopulator;
class TemplePopulator extends AmountPopulator {
protected $level;
/*
* Populate the chunk
* @param $level pocketmine\level\ChunkManager
* @param $chunkX int
* @param $chunkZ int
* @param $random pocketmine\utils\Random
*/
public function populate(ChunkManager $level, $chunkX, $chunkZ, Random $random) {
$this->level = $level;
if ($random->nextBoundedInt ( 1000 ) > 70)
return;
$temple = new Temple ();
$x = $random->nextRange ( $chunkX << 4, ($chunkX << 4) + 15 );
$z = $random->nextRange ( $chunkZ << 4, ($chunkZ << 4) + 15 );
$y = $this->getHighestWorkableBlock ( $x, $z );
if ($temple->canPlaceObject ( $level, $x, $y, $z, $random ))
$temple->placeObject ( $level, $x, $y - 1, $z, $random );
}
/*
* Gets the top block (y) on an x and z axes
* @param $x int
* @param $z int
*/
protected function getHighestWorkableBlock($x, $z) {
for($y = 127; $y > 0; -- $y) {
$b = $this->level->getBlockIdAt ( $x, $y, $z );
if ($b === Block::SAND) {
break;
}
}
return ++ $y;
}
}

View file

@ -0,0 +1,75 @@
<?php
/*
* TreePopulator from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\populator;
use pocketmine\utils\Random;
use pocketmine\block\Block;
use pocketmine\level\ChunkManager;
use Ad5001\BetterGen\structure\SakuraTree;
use Ad5001\BetterGen\populator\AmountPopulator;
class TreePopulator extends AmountPopulator {
static $types = [
"pocketmine\\level\\generator\\object\\OakTree",
"pocketmine\\level\\generator\\object\\BirchTree",
"Ad5001\\BetterGen\\structure\\SakuraTree"
];
protected $level;
protected $type;
/*
* Constructs the class
*/
public function __construct($type = 0) {
$this->type = $type;
}
/*
* Populate the chunk
* @param $level pocketmine\level\ChunkManager
* @param $chunkX int
* @param $chunkZ int
* @param $random pocketmine\utils\Random
*/
public function populate(ChunkManager $level, $chunkX, $chunkZ, Random $random) {
$this->level = $level;
$amount = $this->getAmount ( $random );
for($i = 0; $i < $amount; ++ $i) {
$x = $random->nextRange ( $chunkX << 4, ($chunkX << 4) + 15 );
$z = $random->nextRange ( $chunkZ << 4, ($chunkZ << 4) + 15 );
$y = $this->getHighestWorkableBlock ( $x, $z );
if ($y === - 1) {
continue;
}
$tree = new self::$types [$this->type] ();
if ($tree->canPlaceObject ( $level, $x, $y, $z, $random )) {
$tree->placeObject ( $level, $x, $y, $z, $random );
}
}
}
/*
* Gets the top block (y) on an x and z axes
* @param $x int
* @param $z int
*/
protected function getHighestWorkableBlock($x, $z) {
for($y = 127; $y > 0; -- $y) {
$b = $this->level->getBlockIdAt ( $x, $y, $z );
if ($b === Block::DIRT or $b === Block::GRASS or $b === Block::PODZOL) {
break;
} elseif ($b !== 0 and $b !== Block::SNOW_LAYER) {
return - 1;
}
}
return ++ $y;
}
}

View file

@ -0,0 +1,54 @@
<?php
/*
* WellPopulator from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\populator;
use pocketmine\utils\Random;
use pocketmine\block\Block;
use pocketmine\level\ChunkManager;
use Ad5001\BetterGen\structure\Well;
use Ad5001\BetterGen\populator\AmountPopulator;
class WellPopulator extends AmountPopulator {
protected $level;
/*
* Populate the chunk
* @param $level pocketmine\level\ChunkManager
* @param $chunkX int
* @param $chunkZ int
* @param $random pocketmine\utils\Random
*/
public function populate(ChunkManager $level, $chunkX, $chunkZ, Random $random) {
$this->level = $level;
if ($random->nextBoundedInt ( 1000 ) > 25)
return; // ~1 chance / 1000 due to building limitations.
$well = new Well ();
$x = $random->nextRange ( $chunkX << 4, ($chunkX << 4) + 15 );
$z = $random->nextRange ( $chunkZ << 4, ($chunkZ << 4) + 15 );
$y = $this->getHighestWorkableBlock ( $x, $z ) - 1;
if ($well->canPlaceObject ( $level, $x, $y, $z, $random ))
$well->placeObject ( $level, $x, $y, $z, $random );
}
/*
* Gets the top block (y) on an x and z axes
* @param $x int
* @param $z int
*/
protected function getHighestWorkableBlock($x, $z) {
for($y = 127; $y > 0; -- $y) {
$b = $this->level->getBlockIdAt ( $x, $y, $z );
if ($b === Block::SAND) {
break;
}
}
return ++ $y;
}
}

View file

@ -0,0 +1,76 @@
<?php
/*
* Bush from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\structure;
use pocketmine\block\Leaves;
use pocketmine\block\Block;
use pocketmine\level\ChunkManager;
use pocketmine\utils\Random;
use pocketmine\math\Vector3;
use pocketmine\level\generator\object\Object;
class Bush extends Object {
public $overridable = [
Block::AIR => true,
17 => true,
Block::SNOW_LAYER => true,
Block::LOG2 => true
];
protected $leaf;
protected $height;
/*
* Constructs the class
* @param $leafId int
* @param $leafData int
*/
public function __construct($leafId = Block::LEAVES, $leafData = 0) {
$this->leaf = [
$leafId,
$leafData
];
}
/*
* Places a bush
* @param $level pocketmine\level\ChunkManager
* @param $x int
* @param $y int
* @param $z int
* @param $random pocketmine\utils\Random
*/
public function placeObject(ChunkManager $level, $x, $y, $z, Random $random) {
$number = $random->nextBoundedInt ( 6 );
$pos = new Vector3 ( $x, $y, $z );
$this->placeLeaf ( $pos->x, $pos->y, $pos->z, $level );
for($i = 0; $i < $number; $i ++) {
$transfer = $random->nextBoolean ();
$direction = $random->nextBoundedInt ( 6 );
$newPos = $pos->getSide ( $direction );
if ($transfer)
$pos = $newPos;
$this->placeLeaf ( $newPos->x, $newPos->y, $newPos->z, $level );
}
}
/*
* Places a leaf
* @param $x int
* @param $y int
* @param $z int
* @param $level pocketmine\level\ChunkManager
*/
public function placeLeaf($x, $y, $z, ChunkManager $level) {
if (isset ( $this->overridable [$level->getBlockIdAt ( $x, $y, $z )] ) && ! isset ( $this->overridable [$level->getBlockIdAt ( $x, $y - 1, $z )] )) {
$level->setBlockIdAt ( $x, $y, $z, $this->leaf [0] );
$level->setBlockDataAt ( $x, $y, $z, $this->leaf [1] );
}
}
}

View file

@ -0,0 +1,54 @@
<?php
/*
* Cactus from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\structure;
use pocketmine\block\Block;
use pocketmine\utils\Random;
use pocketmine\level\ChunkManager;
use pocketmine\level\generator\object\Object;
class Cactus extends Object {
/*
* Checks if a cactus is placeable
* @param $level pocketmine\level\ChunkManager
* @param $x int
* @param $y int
* @param $z int
* @param $random pocketmine\utils\Random
*/
public function canPlaceObject(ChunkManager $level, int $x, int $y, int $z, Random $random): bool {
$this->totalHeight = 1 + $random->nextBoundedInt ( 3 );
$below = $level->getBlockIdAt ( $x, $y - 1, $z );
for($yy = $y; $yy <= $y + $totalHeight; $yy ++) {
if ($level->getBlockIdAt ( $x, $yy, $z ) !== Block::AIR || ($below !== Block::SAND && $below !== Block::CACTUS) || ($level->getBlockIdAt ( $x - 1, $yy, $z ) !== Block::AIR || $level->getBlockIdAt ( $x + 1, $yy, $z ) !== Block::AIR || $level->getBlockIdAt ( $x, $yy, $z - 1 ) !== Block::AIR || $level->getBlockIdAt ( $x, $yy, $z + 1 ) !== Block::AIR)) {
return false;
}
}
return true;
}
/*
* Places a cactus
* @param $level pocketmine\level\ChunkManager
* @param $x int
* @param $y int
* @param $z int
*/
public function placeObject(ChunkManager $level, int $x, int $y, int $z) {
for($yy = 0; $yy < $this->totalHeight; $yy ++) {
if ($level->getBlockIdAt ( $x, $y + $yy, $z ) != Block::AIR) {
return;
}
$level->setBlockIdAt ( $x, $y + $yy, $z, Block::CACTUS );
}
}
}

View file

@ -0,0 +1,384 @@
<?php
/*
* Cactus from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\structure;
use pocketmine\block\Block;
use pocketmine\level\ChunkManager;
use pocketmine\utils\Random;
use pocketmine\level\generator\object\Object;
class Igloo extends Object {
public $overridable = [
Block::AIR => true,
6 => true,
17 => true,
18 => true,
Block::DANDELION => true,
Block::POPPY => true,
Block::SNOW_LAYER => true,
Block::LOG2 => true,
Block::LEAVES2 => true
];
protected $direction;
/*
* Checks if an igloo is placeable
* @param $level pocketmine\level\ChunkManager
* @param $x int
* @param $y int
* @param $z int
* @param $random pocketmine\utils\Random
* @return bool
*/
public function canPlaceObject(ChunkManager $level, $x, $y, $z, Random $random) {
$this->direction = $random->nextBoundedInt ( 4 );
switch ($this->direction) {
case 0 : // Entrance is x+
for($xx = $x - 3; $xx <= $x + 4; $xx ++)
for($yy = $y + 1; $yy <= $y + 4; $yy ++)
for($zz = $z - 3; $zz <= $z + 3; $zz ++)
if (! isset ( $this->overridable [$level->getBlockIdAt ( $xx, $yy, $zz )] ))
return false;
break;
case 1 : // Entrance is x-
for($xx = $x - 4; $xx <= $x + 3; $xx ++)
for($yy = $y + 1; $yy <= $y + 4; $yy ++)
for($zz = $z - 3; $zz <= $z + 3; $zz ++)
if (! isset ( $this->overridable [$level->getBlockIdAt ( $xx, $yy, $zz )] ))
return false;
break;
case 2 : // Entrence is z+
for($xx = $x - 3; $xx <= $x + 3; $xx ++)
for($yy = $y + 1; $yy <= $y + 4; $yy ++)
for($zz = $z - 3; $zz <= $z + 4; $zz ++)
if (! isset ( $this->overridable [$level->getBlockIdAt ( $xx, $yy, $zz )] ))
return false;
break;
case 3 : // Entrance is z-
for($xx = $x - 3; $xx <= $x + 3; $xx ++)
for($yy = $y + 1; $yy <= $y + 4; $yy ++)
for($zz = $z - 4; $zz <= $z + 3; $zz ++)
if (! isset ( $this->overridable [$level->getBlockIdAt ( $xx, $yy, $zz )] ))
return false;
break;
}
return true;
}
/*
* Places an igloo
* @param $level pocketmine\level\ChunkManager
* @param $x int
* @param $y int
* @param $z int
* @param $random pocketmine\utils\Random
*/
public function placeObject(ChunkManager $level, $x, $y, $z, Random $random) {
if (! isset ( $this->direction ) && ! $this->canPlaceObject ( $level, $x, $y, $z, $random ))
return false;
switch ($this->direction) {
case 0 : // Entrance is x+
// Ground
for($xx = $x - 3; $xx <= $x + 4; $xx ++)
for($zz = $z - 3; $zz <= $z + 3; $zz ++)
if (! isset ( $this->overridable [$level->getBlockIdAt ( $xx, $y, $zz )] ))
$level->setBlockIdAt ( $xx, $y, $zz, Block::SNOW_BLOCK );
// Entrance
for($i = 0; $i < 2; $i ++) {
$level->setBlockIdAt ( $x + 3 + $i, $y, $z, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x + 3 + $i, $y + 3, $z, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x + 3 + $i, $y + 1, $z + 1, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x + 3 + $i, $y + 1, $z - 1, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x + 3 + $i, $y + 2, $z + 1, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x + 3 + $i, $y + 2, $z - 1, Block::SNOW_BLOCK );
}
// Back
for($zz = $z - 1; $zz <= $z + 1; $zz ++) {
$level->setBlockIdAt ( $x - 3, $y + 1, $zz, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 3, $y + 2, $zz, Block::SNOW_BLOCK );
}
// Sides
for($xx = $x - 1; $xx <= $x + 1; $xx ++) {
$level->setBlockIdAt ( $xx, $y + 1, $z - 3, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $xx, $y + 2, $z - 3, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $xx, $y + 1, $z + 3, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $xx, $y + 2, $z + 3, Block::SNOW_BLOCK );
}
$level->setBlockIdAt ( $x, $y + 1, $z + 3, Block::ICE );
$level->setBlockIdAt ( $x, $y + 1, $z - 3, Block::ICE );
// Diags
for($i = 1; $i <= 2; $i ++) {
$level->setBlockIdAt ( $x + 2, $y + $i, $z + 2, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 2, $y + $i, $z + 2, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 2, $y + $i, $z - 2, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x + 2, $y + $i, $z - 2, Block::SNOW_BLOCK );
}
// 2nd layer
for($i = 0; $i < 3; $i ++) {
$level->setBlockIdAt ( $x - 1 + $i, $y + 3, $z + 2, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 1 + $i, $y + 3, $z - 2, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x + 2, $y + 3, $z - 1 + $i, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 2, $y + 3, $z - 1 + $i, Block::SNOW_BLOCK );
}
// Top
for($xx = $x - 1; $xx <= $x + 1; $xx ++)
for($zz = $z - 1; $zz <= $z + 1; $zz ++) {
$level->setBlockIdAt ( $xx, $y + 4, $zz, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $xx, $y, $zz, Block::SNOW_BLOCK );
}
// Carpets
for($xx = $x - 2; $xx <= $x + 1; $xx ++)
for($zz = $z - 1; $zz <= $z + 1; $zz ++) {
$level->setBlockIdAt ( $xx, $y + 1, $zz, Block::CARPET );
}
// Other furnitures
// Bed
$level->setBlockIdAt ( $x - 1, $y + 1, $z + 2, Block::BED_BLOCK );
$level->setBlockIdAt ( $x, $y + 1, $z + 2, Block::BED_BLOCK );
$level->setBlockDataAt ( $x - 1, $y + 1, $z + 2, 9 );
$level->setBlockDataAt ( $x, $y + 1, $z + 2, 1 );
// Other
$level->setBlockIdAt ( $x - 1, $y + 1, $z - 2, Block::CRAFTING_TABLE );
$level->setBlockIdAt ( $x, $y + 1, $z - 2, Block::REDSTONE_TORCH );
$level->setBlockIdAt ( $x + 1, $y + 1, $z - 2, Block::FURNACE );
break;
// Second direction
case 1 : // Entrance is x-
// Ground
for($xx = $x - 4; $xx <= $x + 3; $xx ++)
for($zz = $z - 3; $zz <= $z + 3; $zz ++)
if (! isset ( $this->overridable [$level->getBlockIdAt ( $xx, $y, $zz )] ))
$level->setBlockIdAt ( $xx, $y, $zz, Block::SNOW_BLOCK );
// Entrance
for($i = 0; $i < 2; $i ++) {
$level->setBlockIdAt ( $x - 3 - $i, $y, $z, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 3 - $i, $y + 3, $z, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 3 - $i, $y + 1, $z + 1, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 3 - $i, $y + 1, $z - 1, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 3 - $i, $y + 2, $z + 1, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 3 - $i, $y + 2, $z - 1, Block::SNOW_BLOCK );
}
// Back
for($zz = $z - 1; $zz <= $z + 1; $zz ++) {
$level->setBlockIdAt ( $x + 3, $y + 1, $zz, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x + 3, $y + 2, $zz, Block::SNOW_BLOCK );
}
// Sides
for($xx = $x - 1; $xx <= $x + 1; $xx ++) {
$level->setBlockIdAt ( $xx, $y + 1, $z - 3, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $xx, $y + 2, $z - 3, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $xx, $y + 1, $z + 3, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $xx, $y + 2, $z + 3, Block::SNOW_BLOCK );
}
$level->setBlockIdAt ( $x, $y + 1, $z + 3, Block::ICE );
$level->setBlockIdAt ( $x, $y + 1, $z - 3, Block::ICE );
// Diags
for($i = 1; $i <= 2; $i ++) {
$level->setBlockIdAt ( $x + 2, $y + $i, $z + 2, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 2, $y + $i, $z + 2, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 2, $y + $i, $z - 2, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x + 2, $y + $i, $z - 2, Block::SNOW_BLOCK );
}
// 2nd layer
for($i = 0; $i < 3; $i ++) {
$level->setBlockIdAt ( $x - 1 + $i, $y + 3, $z + 2, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 1 + $i, $y + 3, $z - 2, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x + 2, $y + 3, $z - 1 + $i, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 2, $y + 3, $z - 1 + $i, Block::SNOW_BLOCK );
}
// Top
for($xx = $x - 1; $xx <= $x + 1; $xx ++)
for($zz = $z - 1; $zz <= $z + 1; $zz ++) {
$level->setBlockIdAt ( $xx, $y + 4, $zz, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $xx, $y, $zz, Block::SNOW_BLOCK );
}
// Carpets
for($xx = $x - 1; $xx <= $x + 2; $xx ++)
for($zz = $z - 1; $zz <= $z + 1; $zz ++) {
$level->setBlockIdAt ( $xx, $y + 1, $zz, Block::CARPET );
}
// Other furnitures
// Bed
$level->setBlockIdAt ( $x + 1, $y + 1, $z + 2, Block::BED_BLOCK );
$level->setBlockIdAt ( $x, $y + 1, $z + 2, Block::BED_BLOCK );
$level->setBlockDataAt ( $x + 1, $y + 1, $z + 2, 11 );
$level->setBlockDataAt ( $x, $y + 1, $z + 2, 3 );
// Other
$level->setBlockIdAt ( $x + 1, $y + 1, $z - 2, Block::CRAFTING_TABLE );
$level->setBlockIdAt ( $x, $y + 1, $z - 2, Block::REDSTONE_TORCH );
$level->setBlockIdAt ( $x - 1, $y + 1, $z - 2, Block::FURNACE );
break;
// Third direction
case 2 : // Entrence is z+
// Ground
for($xx = $x - 3; $xx <= $x + 3; $xx ++)
for($zz = $z - 3; $zz <= $z + 4; $zz ++)
if (! isset ( $this->overridable [$level->getBlockIdAt ( $xx, $y, $zz )] ))
$level->setBlockIdAt ( $xx, $y, $zz, Block::SNOW_BLOCK );
// Entrance
for($i = 0; $i < 2; $i ++) {
$level->setBlockIdAt ( $x, $y, $z + 3 + $i, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x, $y + 3, $z + 3 + $i, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x + 1, $y + 1, $z + 3 + $i, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 1, $y + 1, $z + 3 + $i, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x + 1, $y + 2, $z + 3 + $i, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 1, $y + 2, $z + 3 + $i, Block::SNOW_BLOCK );
}
// Back
for($xx = $x - 1; $xx <= $x + 1; $xx ++) {
$level->setBlockIdAt ( $xx, $y + 1, $z - 3, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $xx, $y + 2, $z - 3, Block::SNOW_BLOCK );
}
// Sides
for($zz = $z - 1; $zz <= $z + 1; $zz ++) {
$level->setBlockIdAt ( $x - 3, $y + 1, $zz, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 3, $y + 2, $zz, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x + 3, $y + 1, $zz, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x + 3, $y + 2, $zz, Block::SNOW_BLOCK );
}
$level->setBlockIdAt ( $x + 3, $y + 1, $z, Block::ICE );
$level->setBlockIdAt ( $x - 3, $y + 1, $z, Block::ICE );
// Diags
for($i = 1; $i <= 2; $i ++) {
$level->setBlockIdAt ( $x + 2, $y + $i, $z + 2, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 2, $y + $i, $z + 2, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 2, $y + $i, $z - 2, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x + 2, $y + $i, $z - 2, Block::SNOW_BLOCK );
}
// 2nd layer
for($i = 0; $i < 3; $i ++) {
$level->setBlockIdAt ( $x - 1 + $i, $y + 3, $z + 2, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 1 + $i, $y + 3, $z - 2, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x + 2, $y + 3, $z - 1 + $i, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 2, $y + 3, $z - 1 + $i, Block::SNOW_BLOCK );
}
// Top
for($xx = $x - 1; $xx <= $x + 1; $xx ++)
for($zz = $z - 1; $zz <= $z + 1; $zz ++) {
$level->setBlockIdAt ( $xx, $y + 4, $zz, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $xx, $y, $zz, Block::SNOW_BLOCK );
}
// Carpets
for($xx = $x - 1; $xx <= $x + 1; $xx ++)
for($zz = $z - 2; $zz <= $z + 1; $zz ++) {
$level->setBlockIdAt ( $xx, $y + 1, $zz, Block::CARPET );
}
// Other furnitures
// Bed
$level->setBlockIdAt ( $x + 2, $y + 1, $z - 1, Block::BED_BLOCK );
$level->setBlockIdAt ( $x + 2, $y + 1, $z, Block::BED_BLOCK );
$level->setBlockDataAt ( $x + 2, $y + 1, $z - 1, 10 );
$level->setBlockDataAt ( $x + 2, $y + 1, $z, 2 );
// Other
$level->setBlockIdAt ( $x - 2, $y + 1, $z + 1, Block::CRAFTING_TABLE );
$level->setBlockIdAt ( $x - 2, $y + 1, $z, Block::REDSTONE_TORCH );
$level->setBlockIdAt ( $x - 2, $y + 1, $z - 1, Block::FURNACE );
break;
// Fourth direction
case 3 : // Entrance is z-
// Ground
for($xx = $x - 3; $xx <= $x + 3; $xx ++)
for($zz = $z - 4; $zz <= $z + 3; $zz ++)
if (! isset ( $this->overridable [$level->getBlockIdAt ( $xx, $y, $zz )] ))
$level->setBlockIdAt ( $xx, $y, $zz, Block::SNOW_BLOCK );
// Entrance
for($i = 0; $i < 2; $i ++) {
$level->setBlockIdAt ( $x, $y, $z - 3 - $i, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x, $y + 3, $z - 3 - $i, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x + 1, $y + 1, $z - 3 - $i, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 1, $y + 1, $z - 3 - $i, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x + 1, $y + 2, $z - 3 - $i, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 1, $y + 2, $z - 3 - $i, Block::SNOW_BLOCK );
}
// Back
for($xx = $x - 1; $xx <= $x + 1; $xx ++) {
$level->setBlockIdAt ( $xx, $y + 1, $z + 3, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $xx, $y + 2, $z + 3, Block::SNOW_BLOCK );
}
// Sides
for($zz = $z - 1; $zz <= $z + 1; $zz ++) {
$level->setBlockIdAt ( $x - 3, $y + 1, $zz, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 3, $y + 2, $zz, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x + 3, $y + 1, $zz, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x + 3, $y + 2, $zz, Block::SNOW_BLOCK );
}
$level->setBlockIdAt ( $x + 3, $y + 1, $z, Block::ICE );
$level->setBlockIdAt ( $x - 3, $y + 1, $z, Block::ICE );
// Diags
for($i = 1; $i <= 2; $i ++) {
$level->setBlockIdAt ( $x + 2, $y + $i, $z + 2, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 2, $y + $i, $z + 2, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 2, $y + $i, $z - 2, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x + 2, $y + $i, $z - 2, Block::SNOW_BLOCK );
}
// 2nd layer
for($i = 0; $i < 3; $i ++) {
$level->setBlockIdAt ( $x - 1 + $i, $y + 3, $z + 2, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 1 + $i, $y + 3, $z - 2, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x + 2, $y + 3, $z - 1 + $i, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $x - 2, $y + 3, $z - 1 + $i, Block::SNOW_BLOCK );
}
// Top
for($xx = $x - 1; $xx <= $x + 1; $xx ++)
for($zz = $z - 1; $zz <= $z + 1; $zz ++) {
$level->setBlockIdAt ( $xx, $y + 4, $zz, Block::SNOW_BLOCK );
$level->setBlockIdAt ( $xx, $y, $zz, Block::SNOW_BLOCK );
}
// Carpets
for($xx = $x - 1; $xx <= $x + 1; $xx ++)
for($zz = $z - 1; $zz <= $z + 2; $zz ++) {
$level->setBlockIdAt ( $xx, $y + 1, $zz, Block::CARPET );
}
// Other furnitures
// Bed
$level->setBlockIdAt ( $x + 2, $y + 1, $z + 1, Block::BED_BLOCK );
$level->setBlockIdAt ( $x + 2, $y + 1, $z, Block::BED_BLOCK );
$level->setBlockDataAt ( $x + 2, $y + 1, $z + 1, 8 );
$level->setBlockDataAt ( $x + 2, $y + 1, $z, 0 );
// Other
$level->setBlockIdAt ( $x - 2, $y + 1, $z - 1, Block::CRAFTING_TABLE );
$level->setBlockIdAt ( $x - 2, $y + 1, $z, Block::REDSTONE_TORCH );
$level->setBlockIdAt ( $x - 2, $y + 1, $z + 1, Block::FURNACE );
break;
}
}
}

View file

@ -0,0 +1,661 @@
<?php
/*
* SakuraTree from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\structure;
use pocketmine\block\Block;
use pocketmine\block\Wood;
use pocketmine\level\ChunkManager;
use pocketmine\utils\Random;
use pocketmine\level\generator\object\Tree;
class SakuraTree extends Tree {
const TRUNK_POS = [ // Checks for trees trunks. Not automaticly generated but there is no point of making more or less
7 => [
0,
1
], // 0 vertical, 1 horizontal and same goes for others...
8 => [
1,
0
],
9 => [
1,
1
],
10 => [
2,
0
],
11 => [
2,
1
],
12 => [
2,
2
],
13 => [
3,
1
]
];
const DIAG_LEAVES = [ // Diag poses of the leaves based on the height of the tree.X relative to $lastX and Z from $lastZ
7 => [
[
4,
4
],
[
- 4,
4
],
[
4,
- 4
],
[
- 4,
- 4
]
],
8 => [
[
6,
6
],
[
- 6,
6
],
[
6,
- 6
],
[
- 6,
- 6
]
],
9 => [
[
6,
6
],
[
- 6,
6
],
[
6,
- 6
],
[
- 6,
- 6
]
],
10 => [
[
6,
6
],
[
- 6,
6
],
[
6,
- 6
],
[
- 6,
- 6
]
],
11 => [
[
7,
7
],
[
6,
8
],
[
8,
6
],
[
- 7,
7
],
[
- 6,
8
],
[
- 8,
6
],
[
7,
- 7
],
[
6,
- 8
],
[
8,
- 6
],
[
- 7,
- 7
],
[
- 6,
- 8
],
[
- 8,
- 6
]
],
12 => [
[
7,
7
],
[
6,
8
],
[
8,
6
],
[
- 7,
7
],
[
- 6,
8
],
[
- 8,
6
],
[
7,
- 7
],
[
6,
- 8
],
[
8,
- 6
],
[
- 7,
- 7
],
[
- 6,
- 8
],
[
- 8,
- 6
]
],
13 => [
[
7,
7
],
[
6,
8
],
[
8,
6
],
[
- 7,
7
],
[
- 6,
8
],
[
- 8,
6
],
[
7,
- 7
],
[
6,
- 8
],
[
8,
- 6
],
[
- 7,
- 7
],
[
- 6,
- 8
],
[
- 8,
- 6
]
]
];
const ADDITIONAL_BLOCKS = [ // Blocks who aren't set to fully fill the tree. X relative to $lastX and Z from $lastZ
7 => [ ],
8 => [ ],
9 => [ ],
10 => [ ],
11 => [
[
6,
6
],
[
7,
6
],
[
6,
7
],
[
- 6,
6
],
[
- 7,
6
],
[
- 6,
7
],
[
6,
- 6
],
[
7,
- 6
],
[
6,
- 7
],
[
- 6,
- 6
],
[
- 7,
- 6
],
[
- 6,
- 7
]
],
12 => [
[
6,
6
],
[
7,
6
],
[
6,
7
],
[
- 6,
6
],
[
- 7,
6
],
[
- 6,
7
],
[
6,
- 6
],
[
7,
- 6
],
[
6,
- 7
],
[
- 6,
- 6
],
[
- 7,
- 6
],
[
- 6,
- 7
]
],
13 => [
[
6,
6
],
[
7,
6
],
[
6,
7
],
[
- 6,
6
],
[
- 7,
6
],
[
- 6,
7
],
[
6,
- 6
],
[
7,
- 6
],
[
6,
- 7
],
[
- 6,
- 6
],
[
- 7,
- 6
],
[
- 6,
- 7
]
]
];
const maxPerChunk = 2;
/*
* Constructs the class
*/
public function __construct() {
$this->trunkBlock = Block::LOG;
$this->leafBlock = Block::WOOL;
$this->leafType = 6;
$this->leaf2Type = 0;
$this->type = Wood::OAK;
}
/*
* Builds the tree.
* @param $level \pocketmine\level\ChunkManager
* @param $x int
* @param $y int
* @param $z int
* @param $random $random
*/
public function placeObject(ChunkManager $level, $x, $y, $z, Random $random) {
$percentage = $random->nextBoundedInt ( 100 );
if ($percentage > 10) {
return;
}
$trunkHeight = 7 + $random->nextBoundedInt ( 7 );
$direction = $random->nextBoundedInt ( 3 ); // Choosing building north east west south
switch ($direction) {
case 0 :
$xDiff = 0;
$zDiff = - 1;
break;
case 1 :
$xDiff = 0;
$zDiff = 1;
break;
case 2 :
$xDiff = - 1;
$zDiff = 0;
break;
case 3 :
$xDiff = 1;
$zDiff = 0;
break;
}
list ( $vParts, $hParts ) = self::TRUNK_POS [$trunkHeight];
$this->setLog ( $level, $x, $y, $z );
list ( $lastX, $lastY, $lastZ ) = [
$x,
$y,
$z
];
// Filling horisontally
if ($hParts > 0) {
for($i = 0; $i < $hParts; $i ++) {
$lastX += $xDiff * 2;
$lastY ++;
$lastZ += $zDiff * 2;
$this->setLog ( $level, $lastX - $xDiff, $lastY, $lastZ - $zDiff );
$this->setLog ( $level, $lastX, $lastY, $lastZ );
}
}
// The middle block
$lastX += $xDiff;
$lastY ++;
$lastZ += $zDiff;
$this->setLog ( $level, $lastX, $lastY, $lastZ );
// Filling verticaly
if ($vParts > 0) {
for($i = 0; $i < $vParts; $i ++) {
$lastX += $xDiff;
$lastY += 2;
$lastZ += $zDiff;
$this->setLog ( $level, $lastX, $lastY - 1, $lastZ );
$this->setLog ( $level, $lastX, $lastY, $lastZ );
}
}
// Filling the top trunk.
$lastX += $xDiff;
$lastY ++;
$lastZ += $zDiff;
for($i = 0; $i < 4; $i ++) {
$this->setLog ( $level, $lastX, $lastY + $i, $lastZ );
}
$lastY ++;
// FIlling the branches.
$branchLen2 = function ($base) {
return ceil ( $base / 2 );
};
for($dir = 0; $dir < 4; $dir ++) {
switch ($dir) {
case 0 :
$xd = 0;
$zd = - 1;
break;
case 1 :
$xd = 0;
$zd = 1;
break;
case 2 :
$xd = - 1;
$zd = 0;
break;
case 3 :
$xd = 1;
$zd = 0;
break;
}
$stickLen = round ( $trunkHeight / 3 );
$stickLen2 = call_user_func ( $branchLen2, $stickLen );
$totalLength = $stickLen + $stickLen2; // Length of the stick
$sideLen = $totalLength ** 2; // Side length
// First branch part + first leave part
for($i = 1; $i < $stickLen + 1; $i ++) {
$lX1 = $lastX + ($xd * $i);
$lZ1 = $lastZ + ($zd * $i);
if ($zd !== 0)
for($x = $lX1 - $numForward; $x !== $lX1 + $numForward + 1; $x ++) {
$this->setLeave ( $level, $x, $lastY + 3, $lZ1, $random );
}
if ($xd !== 0)
for($z = $lZ1 - $numForward; $z !== $lZ1 + $numForward + 1; $z ++) {
$this->setLeave ( $level, $lX1, $lastY + 3, $z, $random );
}
$this->setLog ( $level, $lX1, $lastY, $lZ1 );
}
// Second branch part. + second leave part
$numForward = ($totalLength % 2 == 0) ? $totalLength - 1 : $totalLength;
for($i = 1; $i < $stickLen + 1; $i ++) {
$lX = $lX1 + ($xd * $i);
$lZ = $lZ1 + ($zd * $i);
if ($zd !== 0)
for($x = $lX - $numForward; $x !== $lX + $numForward + 1; $x ++) {
$this->setLeave ( $level, $x, $lastY + 2, $lZ, $random );
}
if ($xd !== 0)
for($z = $lZ - $numForward; $z !== $lZ + $numForward + 1; $z ++) {
$this->setLeave ( $level, $lX, $lastY + 2, $z, $random );
}
$this->setLog ( $level, $lX, $lastY + 1, $lZ );
}
$lX += $xd;
$lZ += $zd;
// Leaves falling from the tree forward
if ($lastZ !== $lZ) { // Z has changed, using X for setting
for($x = $lX - $numForward; $x <= $lX + $numForward; $x ++) {
$numDown = $random->nextBoundedInt ( 3 ) + 1;
for($y = $lastY + 1; $y > $lastY - $numDown; $y --)
$this->setLeave ( $level, $x, $y, $lZ, $random );
}
} else { // Z have stayed, X has changed
for($z = $lZ - $numForward; $z <= $lZ + $numForward; $z ++) {
$numDown = $random->nextBoundedInt ( 3 ) + 1;
for($y = $lastY + 1; $y > $lastY + 1 - $numDown; $y --)
$this->setLeave ( $level, $lX, $y, $z, $random );
}
}
// continue;
switch ($dir + 1) {
case 4 :
$xd2 = 0;
$zd2 = - 1;
break;
case 1 :
$xd2 = 0;
$zd2 = 1;
break;
case 2 :
$xd2 = - 1;
$zd2 = 0;
break;
case 3 :
$xd2 = 1;
$zd2 = 0;
break;
}
// Leaves falling from the tree diagonaly
foreach ( self::DIAG_LEAVES [$trunkHeight] as $pos ) {
$numDown = $random->nextBoundedInt ( 3 ) + 1;
for($y = $lastY + 1; $y > $lastY - $numDown; $y --)
$this->setLeave ( $level, $lastX + $pos [0], $y, $lastZ + $pos [1], $random );
}
// Additional leaves
foreach ( self::ADDITIONAL_BLOCKS [$trunkHeight] as $pos ) {
$this->setLeave ( $level, $lastX + $pos [0], $lastY + 2, $lastZ + $pos [1], $random );
}
}
}
/*
* Fills a log at.
* @param $level pocketmine\level\ChunkManager
* @param $x int
* @param $y int
* @param $z int
*/
public function setLog(ChunkManager $level, $x, $y, $z) {
$level->setBlockIdAt ( $x, $y, $z, $this->trunkBlock );
$level->setBlockDataAt ( $x, $y, $z, $this->type );
}
/*
* Fills a leave at.
* @param $level pocketmine\level\ChunkManager
* @param $x int
* @param $y int
* @param $z int
* @param $random pocketmine\utils\Random
*/
public function setLeave(ChunkManager $level, $x, $y, $z, Random $random) {
$data = [
$this->leafType,
$this->leaf2Type
] [( int ) $random->nextBoolean ()];
$level->setBlockIdAt ( $x, $y, $z, $this->leafBlock );
$level->setBlockDataAt ( $x, $y, $z, $data );
}
}

View file

@ -0,0 +1,52 @@
<?php
/*
* SugarCane from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\structure;
use pocketmine\block\Block;
use pocketmine\utils\Random;
use pocketmine\level\ChunkManager;
use pocketmine\level\generator\object\Object;
class SugarCane extends Object {
/*
* Checks if a cactus is placeable
* @param $level pocketmine\level\ChunkManager
* @param $x int
* @param $y int
* @param $z int
* @param $random pocketmine\utils\Random
*/
public function canPlaceObject(ChunkManager $level, int $x, int $y, int $z, Random $random): bool {
$this->totalHeight = 1 + $random->nextBoundedInt ( 3 );
$below = $level->getBlockIdAt ( $x, $y - 1, $z );
if (($below == Block::SAND || $below == Block::GRASS) && ($level->getBlockIdAt ( $x + 1, $y - 1, $z ) == Block::WATER || $level->getBlockIdAt ( $x - 1, $y - 1, $z ) == Block::WATER || $level->getBlockIdAt ( $x, $y - 1, $z + 1 ) == Block::WATER || $level->getBlockIdAt ( $x, $y - 1, $z - 1 ) == Block::WATER)) {
return true;
}
return false;
}
/*
* Places a cactus
* @param $level pocketmine\level\ChunkManager
* @param $x int
* @param $y int
* @param $z int
*/
public function placeObject(ChunkManager $level, int $x, int $y, int $z) {
for($yy = 0; $yy < $this->totalHeight; $yy ++) {
if ($level->getBlockIdAt ( $x, $y + $yy, $z ) != Block::AIR) {
return;
}
$level->setBlockIdAt ( $x, $y + $yy, $z, Block::SUGARCANE_BLOCK );
}
}
}

View file

@ -0,0 +1,907 @@
<?php
/*
* Temple from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\structure;
use pocketmine\block\Block;
use pocketmine\level\ChunkManager;
use pocketmine\utils\Random;
use pocketmine\math\Vector3;
use pocketmine\level\generator\object\Object;
use Ad5001\BetterGen\loot\LootTable;
use Ad5001\BetterGen\utils\BuildingUtils;
class Temple extends Object {
const DIRECTION_PLUSX = 0;
const DIRECTION_MINX = 1;
const DIRECTION_PLUSZ = 2;
const DIRECTION_MINZ = 3;
const THREE_DIAGS = [
[
3,
0
],
[
0,
3
],
[
2,
1
],
[
1,
2
],
[
- 3,
0
],
[
- 2,
1
],
[
- 1,
2
],
[
0,
- 3
],
[
2,
- 1
],
[
1,
- 2
],
[
- 2,
- 1
],
[
- 1,
- 2
]
];
public $overridable = [
Block::AIR => true,
6 => true,
17 => true,
18 => true,
Block::DANDELION => true,
Block::POPPY => true,
Block::SNOW_LAYER => true,
Block::LOG2 => true,
Block::LEAVES2 => true,
Block::CACTUS => true
];
protected $directions = [
[
1,
1
],
[
1,
- 1
],
[
- 1,
- 1
],
[
- 1,
1
]
];
/*
* Checks if a temple is placeable
* @param $level pocketmine\level\ChunkManager
* @param $x int
* @param $y int
* @param $z int
* @param $random pocketmine\utils\Random
* @return bool
*/
public function canPlaceObject(ChunkManager $level, $x, $y, $z, Random $random) {
$this->direction = $random->nextBoundedInt ( 4 );
for($xx = $x - 10; $xx <= $x + 10; $xx ++)
for($yy = $y + 1; $yy <= $y + 11; $yy ++)
for($zz = $z - 10; $zz <= $z + 10; $zz ++)
if (! isset ( $this->overridable [$level->getBlockIdAt ( $xx, $yy, $zz )] ))
return false;
return true;
}
/*
* Places a temple
* @param $level pocketmine\level\ChunkManager
* @param $x int
* @param $y int
* @param $z int
* @param $random pocketmine\utils\Random
*/
public function placeObject(ChunkManager $level, $x, $y, $z, Random $random) {
// Clearing space...
BuildingUtils::fill ( $level, new Vector3 ( $x + 10, $y + 1, $z + 10 ), new Vector3 ( $x - 10, $y + 2, $z - 10 ), Block::get ( Block::AIR ) );
// First, build a pyramid.
$this->level = $level;
$firstPos = new Vector3 ( $x + 10, $y, $z + 10 );
$sndPos = new Vector3 ( $x - 10, $y, $z - 10 );
for($i = 0; $i <= 9; $i ++) {
// Building sides
BuildingUtils::walls ( $level, $firstPos, $sndPos, Block::get ( Block::SANDSTONE ) );
// Next floor
$firstPos->x --;
$firstPos->z --;
$firstPos->y = $y + $i;
$sndPos->x ++;
$sndPos->z ++;
$sndPos->y = $y + $i;
}
// Floors
for($xx = $x + 9; $xx >= $x - 9; $xx --)
for($zz = $z + 9; $zz >= $z - 9; $zz --)
$this->placeBlock ( $xx, $y, $zz );
for($xx = $x + 5; $xx >= $x - 5; $xx --)
for($zz = $z + 5; $zz >= $z - 5; $zz --)
$this->placeBlock ( $xx, $y + 4, $zz );
// Creating hole
for($xx = $x - 1; $xx <= $x + 1; $xx ++)
for($yy = $y - 11; $yy <= $y + 4; $yy ++)
for($zz = $z - 1; $zz <= $z + 1; $zz ++)
$this->placeBlock ( $xx, $yy, $zz, 0 );
// Floor patern
foreach ( $this->directions as $dir ) {
// Building pillar
for($yy = $y + 1; $yy <= $y + 3; $yy ++)
$this->placeBlock ( $x + ($dir [0] * 2), $yy, $z + ($dir [1] * 2), Block::SANDSTONE, 2 );
// Orange hardened clay
$this->placeBlock ( $x + $dir [0], $y, $z + $dir [1], Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + ($dir [0] * 2), $y, $z, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + ($dir [0] * 3), $y, $z, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x, $y, $z + ($dir [1] * 2), Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x, $y, $z + ($dir [1] * 3), Block::STAINED_HARDENED_CLAY, 1 );
// Sandstone
$this->placeBlock ( $x + $dir [0], $y, $z );
$this->placeBlock ( $x, $y, $z + $dir [1] );
}
// Blue hardened clay (center)
$this->placeBlock ( $x, $y, $z, Block::STAINED_HARDENED_CLAY, 11 );
// Hole walls
BuildingUtils::walls ( $level, new Vector3 ( $x - 2, $y, $z - 2 ), new Vector3 ( $x + 2, $y - 8, $z + 2 ), Block::get ( Block::SANDSTONE ) );
// Last step like this
for($xx = $x - 2; $xx <= $x + 2; $xx ++) {
$this->placeBlock ( $xx, $y - 9, $z - 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $xx, $y - 9, $z + 2, Block::SANDSTONE, 2 );
}
for($zz = $z - 2; $zz <= $z + 2; $zz ++) {
$this->placeBlock ( $x - 2, $y - 9, $zz, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 2, $y - 9, $zz, Block::SANDSTONE, 2 );
}
foreach ( self::THREE_DIAGS as $diagPos ) {
$this->placeBlock ( $x + $diagPos [0], $y - 10, $z + $diagPos [1], Block::SANDSTONE, 1 );
$this->placeBlock ( $x + $diagPos [0], $y - 11, $z + $diagPos [1], Block::SANDSTONE, 2 );
}
// Floor + TNT
for($xx = $x - 2; $xx <= $x + 2; $xx ++)
for($zz = $z - 2; $zz <= $z + 2; $zz ++)
$this->placeBlock ( $xx, $y - 12, $zz, Block::SANDSTONE, 2 );
for($xx = $x - 1; $xx <= $x + 1; $xx ++)
for($zz = $z - 1; $zz <= $z + 1; $zz ++)
$this->placeBlock ( $xx, $y - 13, $zz, Block::TNT );
$this->placeBlock ( $x, $y - 11, $z, Block::STONE_PRESSURE_PLATE );
// Chests
LootTable::buildLootTable ( new Vector3 ( $x, $y - 11, $z + 2 ), LootTable::LOOT_DESERT_TEMPLE, $random );
LootTable::buildLootTable ( new Vector3 ( $x, $y - 11, $z - 2 ), LootTable::LOOT_DESERT_TEMPLE, $random );
LootTable::buildLootTable ( new Vector3 ( $x + 2, $y - 11, $z ), LootTable::LOOT_DESERT_TEMPLE, $random );
LootTable::buildLootTable ( new Vector3 ( $x - 2, $y - 11, $z ), LootTable::LOOT_DESERT_TEMPLE, $random );
// Entrance is a rectangular parallelepiped
switch ($this->direction) {
case self::DIRECTION_PLUSX : // x+ (0)
// Building towers.
$this->placeTower ( $x + 8, $y, $z + 8, self::DIRECTION_PLUSX, self::DIRECTION_PLUSZ );
$this->placeTower ( $x + 8, $y, $z - 8, self::DIRECTION_PLUSX, self::DIRECTION_MINZ );
// Creating rectangular parallelepiped of sandstone.
BuildingUtils::fill ( $level, new Vector3 ( $x + 6, $y + 1, $z - 6 ), new Vector3 ( $x + 9, $y + 4, $z + 6 ), Block::get ( Block::SANDSTONE ) );
// Creating a path to the entrance
BuildingUtils::fill ( $level, new Vector3 ( $x + 6, $y + 1, $z - 1 ), new Vector3 ( $x + 9, $y + 4, $z + 1 ), Block::get ( Block::AIR ) );
// Creating path to towers.
for($yy = $y + 1; $yy <= $y + 2; $yy ++)
for($zz = $z - 6; $zz <= $z + 6; $zz ++)
$this->placeBlock ( $x + 8, $yy, $zz, 0 );
// Door additional blocks
for($yy = $y + 1; $yy <= $y + 4; $yy ++) {
$this->placeBlock ( $x + 6, $yy, $z - 2 );
$this->placeBlock ( $x + 6, $yy, $z + 2 );
// Polished entrance
$this->placeBlock ( $x + 9, $yy, $z + 1, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 9, $yy, $z - 1, Block::SANDSTONE, 2 );
// Starting entrance structure
$this->placeBlock ( $x + 10, $yy, $z - 2 );
$this->placeBlock ( $x + 10, $yy, $z + 2 );
}
// Finishing entrance structure
$this->placeBlock ( $x + 9, $y + 3, $z, Block::SANDSTONE, 2 );
for($zz = $z - 2; $zz <= $z + 2; $zz ++)
$this->placeBlock ( $x + 10, $y + 4, $zz, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 10, $y + 5, $z, Block::SANDSTONE, 1 );
$this->placeBlock ( $x + 10, $y + 5, $z - 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 10, $y + 5, $z + 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 10, $y + 5, $z - 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 10, $y + 5, $z + 2, Block::SANDSTONE, 2 );
for($zz = $z - 1; $zz <= $z + 1; $zz ++)
$this->placeBlock ( $x + 10, $y + 6, $zz, Block::SANDSTONE, 2 );
for($xx = $x + 6; $xx <= $x + 9; $xx ++)
for($zz = $z - 2; $zz <= $z + 2; $zz ++)
$this->placeBlock ( $xx, $y + 4, $zz );
break;
case self::DIRECTION_MINX : // x- (1)
// Building towers.
$this->placeTower ( $x - 8, $y, $z + 8, self::DIRECTION_MINX, self::DIRECTION_PLUSZ );
$this->placeTower ( $x - 8, $y, $z - 8, self::DIRECTION_MINX, self::DIRECTION_MINZ );
// Creating rectangular parallelepiped of sandstone.
for($xx = $x - 6; $xx >= $x - 9; $xx --)
for($yy = $y + 1; $yy <= $y + 4; $yy ++)
for($zz = $z - 6; $zz <= $z + 6; $zz ++)
$this->placeBlock ( $xx, $yy, $zz );
// Creating a path to the entrance
for($xx = $x - 6; $xx >= $x - 9; $xx --)
for($yy = $y + 1; $yy <= $y + 4; $yy ++)
for($zz = $z - 1; $zz <= $z + 1; $zz ++)
$this->placeBlock ( $xx, $yy, $zz, 0 );
// Creating path to towers.
for($yy = $y + 1; $yy <= $y + 2; $yy ++)
for($zz = $z - 6; $zz <= $z + 6; $zz ++)
$this->placeBlock ( $x - 8, $yy, $zz, 0 );
// Door additional blocks
for($yy = $y + 1; $yy <= $y + 4; $yy ++) {
$this->placeBlock ( $x - 6, $yy, $z - 2 );
$this->placeBlock ( $x - 6, $yy, $z + 2 );
// Polished entrance
$this->placeBlock ( $x - 9, $yy, $z + 1, Block::SANDSTONE, 2 );
$this->placeBlock ( $x - 9, $yy, $z - 1, Block::SANDSTONE, 2 );
// Starting entrance structure
$this->placeBlock ( $x - 10, $yy, $z - 2 );
$this->placeBlock ( $x - 10, $yy, $z + 2 );
}
// Finishing entrance structure
$this->placeBlock ( $x - 9, $y + 3, $z, Block::SANDSTONE, 2 );
for($zz = $z - 2; $zz <= $z + 2; $zz ++)
$this->placeBlock ( $x - 10, $y + 4, $zz, Block::SANDSTONE, 2 );
$this->placeBlock ( $x - 10, $y + 5, $z, Block::SANDSTONE, 1 );
$this->placeBlock ( $x - 10, $y + 5, $z - 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 10, $y + 5, $z + 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 10, $y + 5, $z - 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x - 10, $y + 5, $z + 2, Block::SANDSTONE, 2 );
for($zz = $z - 1; $zz <= $z + 1; $zz ++)
$this->placeBlock ( $x - 10, $y + 6, $zz, Block::SANDSTONE, 2 );
for($xx = $x - 6; $xx >= $x - 9; $xx --)
for($zz = $z - 2; $zz <= $z + 2; $zz ++)
$this->placeBlock ( $xx, $y + 4, $zz );
break;
case self::DIRECTION_PLUSZ : // z+ (2)
// Building towers.
$this->placeTower ( $x + 8, $y, $z + 8, self::DIRECTION_PLUSZ, self::DIRECTION_PLUSX );
$this->placeTower ( $x - 8, $y, $z + 8, self::DIRECTION_PLUSZ, self::DIRECTION_MINX );
// Creating rectangular parallelepiped of sandstone.
BuildingUtils::fill ( $level, new Vector3 ( $x - 6, $y + 1, $z + 6 ), new Vector3 ( $x + 6, $y + 4, $z + 9 ), Block::get ( Block::SANDSTONE ) );
// Creating a path to the entrance
for($xx = $x - 1; $xx <= $x + 1; $xx ++)
for($yy = $y + 1; $yy <= $y + 4; $yy ++)
for($zz = $z + 6; $zz <= $z + 9; $zz ++)
$this->placeBlock ( $xx, $yy, $zz, 0 );
// Creating path to towers.
BuildingUtils::fill ( $level, new Vector3 ( $x - 1, $y + 1, $z + 6 ), new Vector3 ( $x + 1, $y + 4, $z + 9 ), Block::get ( Block::AIR ) );
// Door additional blocks
for($yy = $y + 1; $yy <= $y + 4; $yy ++) {
$this->placeBlock ( $x - 2, $yy, $z + 6 );
$this->placeBlock ( $x + 2, $yy, $z + 6 );
// Polished entrance
$this->placeBlock ( $x + 1, $yy, $z + 9, Block::SANDSTONE, 2 );
$this->placeBlock ( $x - 1, $yy, $z + 9, Block::SANDSTONE, 2 );
// Starting entrance structure
$this->placeBlock ( $x + 2, $yy, $z + 10 );
$this->placeBlock ( $x - 2, $yy, $z + 10 );
}
// Finishing entrance structure
$this->placeBlock ( $x, $y + 3, $z + 9, Block::SANDSTONE, 2 );
for($xx = $x - 2; $xx <= $x + 2; $xx ++)
$this->placeBlock ( $xx, $y + 4, $z + 10, Block::SANDSTONE, 2 );
$this->placeBlock ( $x, $y + 5, $z + 10, Block::SANDSTONE, 1 );
$this->placeBlock ( $x - 1, $y + 5, $z + 10, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 1, $y + 5, $z + 10, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 2, $y + 5, $z + 10, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 2, $y + 5, $z + 10, Block::SANDSTONE, 2 );
for($xx = $x - 1; $xx <= $x + 1; $xx ++)
$this->placeBlock ( $xx, $y + 6, $z + 10, Block::SANDSTONE, 2 );
for($zz = $z + 6; $zz <= $z + 9; $zz ++)
for($xx = $x - 2; $xx <= $x + 2; $xx ++)
$this->placeBlock ( $xx, $y + 4, $zz );
break;
case self::DIRECTION_MINZ : // z- (3)
// Building towers.
$this->placeTower ( $x + 8, $y, $z - 8, self::DIRECTION_MINZ, self::DIRECTION_PLUSX );
$this->placeTower ( $x - 8, $y, $z - 8, self::DIRECTION_MINZ, self::DIRECTION_MINX );
// Creating rectangular parallelepiped of sandstone.
BuildingUtils::fill ( $level, new Vector3 ( $x - 6, $y + 1, $z - 6 ), new Vector3 ( $x + 6, $y + 4, $z - 9 ), Block::get ( Block::SANDSTONE ) );
// Creating a path to the entrance
BuildingUtils::fill ( $level, new Vector3 ( $x - 1, $y + 1, $z - 6 ), new Vector3 ( $x + 1, $y + 4, $z - 9 ), Block::get ( Block::AIR ) );
// Creating path to towers.
for($yy = $y + 1; $yy <= $y + 2; $yy ++)
for($xx = $x - 6; $xx <= $x + 6; $xx ++)
$this->placeBlock ( $xx, $yy, $z - 8, 0 );
// Door additional blocks
for($yy = $y + 1; $yy <= $y + 4; $yy ++) {
$this->placeBlock ( $x - 2, $yy, $z - 6 );
$this->placeBlock ( $x + 2, $yy, $z - 6 );
// Polished entrance
$this->placeBlock ( $x + 1, $yy, $z - 9, Block::SANDSTONE, 2 );
$this->placeBlock ( $x - 1, $yy, $z - 9, Block::SANDSTONE, 2 );
// Starting entrance structure
$this->placeBlock ( $x + 2, $yy, $z - 10 );
$this->placeBlock ( $x - 2, $yy, $z - 10 );
}
// Finishing entrance structure
$this->placeBlock ( $x, $y + 3, $z - 9, Block::SANDSTONE, 2 );
for($xx = $x - 2; $xx <= $x + 2; $xx ++)
$this->placeBlock ( $xx, $y + 4, $z - 10, Block::SANDSTONE, 2 );
$this->placeBlock ( $x, $y + 5, $z - 10, Block::SANDSTONE, 1 );
$this->placeBlock ( $x - 1, $y + 5, $z - 10, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 1, $y + 5, $z - 10, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 2, $y + 5, $z - 10, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 2, $y + 5, $z - 10, Block::SANDSTONE, 2 );
for($xx = $x - 1; $xx <= $x + 1; $xx ++)
$this->placeBlock ( $xx, $y + 6, $z - 10, Block::SANDSTONE, 2 );
for($zz = $z - 6; $zz >= $z - 9; $zz --)
for($xx = $x - 2; $xx <= $x + 2; $xx ++)
$this->placeBlock ( $xx, $y + 4, $zz );
break;
}
}
/*
* Places a slab
* @param $x int
* @param $y int
* @param $z int
* @return void
*/
protected function placeSlab($x, $y, $z) {
$this->level->setBlockIdAt ( $x, $y, $z, 44 );
$this->level->setBlockDataAt ( $x, $y, $z, 1 );
}
/*
* Places a slab
* @param $x int
* @param $y int
* @param $z int
* @param $id int
* @param $meta int
* @return void
*/
protected function placeBlock($x, $y, $z, $id = Block::SANDSTONE, $meta = 0) {
$this->level->setBlockIdAt ( $x, $y, $z, $id );
$this->level->setBlockDataAt ( $x, $y, $z, $meta );
}
/*
* Places one of the towers. Out is inversed $direction1, stairs come from inversed $direction2 to $direction2, patterns are on $direction1 and $direction2
* @param $x int
* @param $y int
* @param $z int
* @param $direction1 int
* @param $direction2 int
* @return void
*/
public function placeTower($x, $y, $z, $direction1 = self::DIRECTION_PLUSX, $direction2 = self::DIRECTION_PLUSZ) {
BuildingUtils::walls ( $this->level, new Vector3 ( $x + 2, $y, $z + 2 ), new Vector3 ( $x - 2, $y + 8, $z - 2 ), Block::get ( Block::SANDSTONE ) );
switch ($direction1) {
case self::DIRECTION_PLUSX : // x+ (0)
// Stairs
switch ($direction2) {
case self::DIRECTION_PLUSZ :
for($zz = $z + 1; $zz >= $z; $zz --) {
$this->placeBlock ( $x - 1, $y + 1, $zz );
$this->placeBlock ( $x - 1, $y + 2, $zz );
}
$this->placeBlock ( $x, $y + 1, $z, Block::SANDSTONE_STAIRS, 2 );
$this->placeBlock ( $x, $y + 1, $z + 1 );
$this->placeSlab ( $x, $y + 2, $z + 1 );
// Pattern
foreach ( [
1,
2,
4
] as $h ) {
$this->placeBlock ( $x - 1, $y + $h, $z + 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 1, $y + $h, $z + 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x, $y + $h, $z + 2, Block::STAINED_HARDENED_CLAY, 1 );
}
foreach ( [
3,
5
] as $h ) {
$this->placeBlock ( $x - 1, $y + $h, $z + 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 1, $y + $h, $z + 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x, $y + $h, $z + 2, Block::SANDSTONE, 1 );
}
$this->placeBlock ( $x - 1, $y + 6, $z + 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x, $y + 6, $z + 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 1, $y + 6, $z + 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 1, $y + 7, $z + 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x, $y + 7, $z + 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 1, $y + 7, $z + 2, Block::SANDSTONE, 2 );
// Building entrance to second floor.
BuildingUtils::fill ( $this->level, new Vector3 ( $x - 9, $y + 5, $z - 4 ), new Vector3 ( $x - 7, $y + 7, $z - 5 ), Block::get ( Block::SANDSTONE, 2 ) );
BuildingUtils::fill ( $this->level, new Vector3 ( $x - 8, $y + 5, $z - 4 ), new Vector3 ( $x - 8, $y + 6, $z - 5 ), Block::get ( Block::AIR ) );
break;
case self::DIRECTION_MINZ :
for($zz = $z - 1; $zz <= $z; $zz ++) {
$this->placeBlock ( $x - 1, $y + 1, $zz );
$this->placeBlock ( $x - 1, $y + 2, $zz );
}
$this->placeBlock ( $x, $y + 1, $z, Block::SANDSTONE_STAIRS, 3 );
$this->placeBlock ( $x, $y + 1, $z - 1 );
$this->placeSlab ( $x, $y + 2, $z - 1 );
// Pattern
foreach ( [
1,
2,
4
] as $h ) {
$this->placeBlock ( $x - 1, $y + $h, $z - 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 1, $y + $h, $z - 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x, $y + $h, $z - 2, Block::STAINED_HARDENED_CLAY, 1 );
}
foreach ( [
3,
5
] as $h ) {
$this->placeBlock ( $x - 1, $y + $h, $z - 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 1, $y + $h, $z - 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x, $y + $h, $z - 2, Block::SANDSTONE, 1 );
}
$this->placeBlock ( $x - 1, $y + 6, $z - 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x, $y + 6, $z - 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 1, $y + 6, $z - 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 1, $y + 7, $z - 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x, $y + 7, $z - 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 1, $y + 7, $z - 2, Block::SANDSTONE, 2 );
break;
// Building entrance to second floor.
BuildingUtils::fill ( $this->level, new Vector3 ( $x - 9, $y + 5, $z + 4 ), new Vector3 ( $x - 7, $y + 7, $z + 5 ), Block::get ( Block::SANDSTONE, 2 ) );
BuildingUtils::fill ( $this->level, new Vector3 ( $x - 8, $y + 5, $z + 4 ), new Vector3 ( $x - 8, $y + 6, $z + 5 ), Block::get ( Block::AIR ) );
}
// Finishing stairs system
$this->placeBlock ( $x - 2, $y + 3, $z, Block::SANDSTONE_STAIRS, 1 );
$this->placeBlock ( $x - 3, $y + 4, $z, Block::SANDSTONE_STAIRS, 1 );
$this->placeBlock ( $x - 2, $y + 4, $z, Block::AIR );
$this->placeBlock ( $x - 2, $y + 5, $z, Block::AIR );
$this->placeBlock ( $x - 2, $y + 6, $z, Block::AIR );
// Making path from stairs to first floor.
BuildingUtils::fill ( $this->level, new Vector3 ( $x - 4, $y, $z + 2 ), new Vector3 ( $x - 9, $y + 4, $z - 2 ), Block::get ( Block::SANDSTONE ) );
// Other side pattern
foreach ( [
1,
2,
4
] as $h ) {
$this->placeBlock ( $x + 2, $y + $h, $z + 1, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 2, $y + $h, $z - 1, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 2, $y + $h, $z, Block::STAINED_HARDENED_CLAY, 1 );
}
foreach ( [
3,
5
] as $h ) {
$this->placeBlock ( $x + 2, $y + $h, $z - 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 2, $y + $h, $z + 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 2, $y + $h, $z, Block::SANDSTONE, 1 );
}
$this->placeBlock ( $x + 2, $y + 6, $z - 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 2, $y + 6, $z, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 2, $y + 6, $z + 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 2, $y + 7, $z - 1, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 2, $y + 7, $z, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 2, $y + 7, $z + 1, Block::SANDSTONE, 2 );
break;
case self::DIRECTION_MINX : // x- (1)
// Stairs
switch ($direction2) {
case self::DIRECTION_PLUSZ :
for($zz = $z + 1; $zz >= $z; $zz --) {
$this->placeBlock ( $x + 1, $y + 1, $zz );
$this->placeBlock ( $x + 1, $y + 2, $zz );
}
$this->placeBlock ( $x, $y + 1, $z, Block::SANDSTONE_STAIRS, 2 );
$this->placeBlock ( $x, $y + 1, $z + 1 );
$this->placeSlab ( $x, $y + 2, $z + 1 );
// Pattern
foreach ( [
1,
2,
4
] as $h ) {
$this->placeBlock ( $x + 1, $y + $h, $z + 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x - 1, $y + $h, $z + 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x, $y + $h, $z + 2, Block::STAINED_HARDENED_CLAY, 1 );
}
foreach ( [
3,
5
] as $h ) {
$this->placeBlock ( $x + 1, $y + $h, $z + 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 1, $y + $h, $z + 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x, $y + $h, $z + 2, Block::SANDSTONE, 1 );
}
$this->placeBlock ( $x - 1, $y + 6, $z + 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x, $y + 6, $z + 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 1, $y + 6, $z + 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 1, $y + 7, $z + 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x, $y + 7, $z + 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 1, $y + 7, $z + 2, Block::SANDSTONE, 2 );
// Building entrance to second floor.
BuildingUtils::fill ( $this->level, new Vector3 ( $x + 9, $y + 5, $z - 4 ), new Vector3 ( $x + 7, $y + 7, $z - 5 ), Block::get ( Block::SANDSTONE, 2 ) );
BuildingUtils::fill ( $this->level, new Vector3 ( $x + 8, $y + 5, $z - 4 ), new Vector3 ( $x + 8, $y + 6, $z - 5 ), Block::get ( Block::AIR ) );
break;
case self::DIRECTION_MINZ :
for($zz = $z - 1; $zz <= $z; $zz ++) {
$this->placeBlock ( $x + 1, $y + 1, $zz );
$this->placeBlock ( $x + 1, $y + 2, $zz );
}
$this->placeBlock ( $x, $y + 1, $z, Block::SANDSTONE_STAIRS, 3 );
$this->placeBlock ( $x, $y + 1, $z - 1 );
$this->placeSlab ( $x, $y + 2, $z - 1 );
// Pattern
foreach ( [
1,
2,
4
] as $h ) {
$this->placeBlock ( $x + 1, $y + $h, $z - 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x - 1, $y + $h, $z - 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x, $y + $h, $z - 2, Block::STAINED_HARDENED_CLAY, 1 );
}
foreach ( [
3,
5
] as $h ) {
$this->placeBlock ( $x + 1, $y + $h, $z - 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 1, $y + $h, $z - 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x, $y + $h, $z - 2, Block::SANDSTONE, 1 );
}
$this->placeBlock ( $x - 1, $y + 6, $z - 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x, $y + 6, $z - 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 1, $y + 6, $z - 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 1, $y + 6, $z - 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x, $y + 6, $z - 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 1, $y + 6, $z - 2, Block::SANDSTONE, 2 );
// Building entrance to second floor.
BuildingUtils::fill ( $this->level, new Vector3 ( $x + 9, $y + 5, $z + 4 ), new Vector3 ( $x + 7, $y + 7, $z + 5 ), Block::get ( Block::SANDSTONE, 2 ) );
BuildingUtils::fill ( $this->level, new Vector3 ( $x + 8, $y + 5, $z + 4 ), new Vector3 ( $x + 8, $y + 6, $z + 5 ), Block::get ( Block::AIR ) );
break;
}
// Finishing stairs system
$this->placeBlock ( $x + 2, $y + 3, $z, Block::SANDSTONE_STAIRS, 0 );
$this->placeBlock ( $x + 3, $y + 4, $z, Block::SANDSTONE_STAIRS, 0 );
$this->placeBlock ( $x + 2, $y + 4, $z, Block::AIR );
$this->placeBlock ( $x + 2, $y + 5, $z, Block::AIR );
$this->placeBlock ( $x + 2, $y + 6, $z, Block::AIR );
// Making path from stairs to first floor.
BuildingUtils::fill ( $this->level, new Vector3 ( $x + 4, $y, $z + 2 ), new Vector3 ( $x + 9, $y + 4, $z - 2 ), Block::get ( Block::SANDSTONE ) );
// Other side pattern
foreach ( [
1,
2,
4
] as $h ) {
$this->placeBlock ( $x - 2, $y + $h, $z + 1, Block::SANDSTONE, 2 );
$this->placeBlock ( $x - 2, $y + $h, $z - 1, Block::SANDSTONE, 2 );
$this->placeBlock ( $x - 2, $y + $h, $z, Block::STAINED_HARDENED_CLAY, 1 );
}
foreach ( [
3,
5
] as $h ) {
$this->placeBlock ( $x - 2, $y + $h, $z - 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 2, $y + $h, $z + 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 2, $y + $h, $z, Block::SANDSTONE, 1 );
}
$this->placeBlock ( $x - 2, $y + 6, $z - 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 2, $y + 6, $z, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 2, $y + 6, $z + 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 2, $y + 7, $z - 1, Block::SANDSTONE, 2 );
$this->placeBlock ( $x - 2, $y + 7, $z, Block::SANDSTONE, 2 );
$this->placeBlock ( $x - 2, $y + 7, $z + 1, Block::SANDSTONE, 2 );
break;
case self::DIRECTION_PLUSZ : // z+ (2)
// Stairs
switch ($direction2) {
case self::DIRECTION_PLUSX :
for($xx = $x + 1; $xx >= $x; $xx --) {
$this->placeBlock ( $xx, $y + 1, $z - 1 );
$this->placeBlock ( $xx, $y + 2, $z - 1 );
}
$this->placeBlock ( $x, $y + 1, $z, Block::SANDSTONE_STAIRS, 0 );
$this->placeBlock ( $x + 1, $y + 1, $z );
$this->placeSlab ( $x + 1, $y + 2, $z );
// Pattern
foreach ( [
1,
2,
4
] as $h ) {
$this->placeBlock ( $x + 2, $y + $h, $z + 1, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 2, $y + $h, $z - 1, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 2, $y + $h, $z, Block::STAINED_HARDENED_CLAY, 1 );
}
foreach ( [
3,
5
] as $h ) {
$this->placeBlock ( $x + 2, $y + $h, $z + 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 2, $y + $h, $z - 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 2, $y + $h, $z, Block::SANDSTONE, 1 );
}
$this->placeBlock ( $x + 2, $y + 6, $z - 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 2, $y + 6, $z, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 2, $y + 6, $z + 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 2, $y + 7, $z - 1, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 2, $y + 7, $z, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 2, $y + 7, $z + 1, Block::SANDSTONE, 2 );
// Building entrance to second floor.
BuildingUtils::fill ( $this->level, new Vector3 ( $x - 4, $y + 5, $z - 9 ), new Vector3 ( $x - 5, $y + 7, $z - 7 ), Block::get ( Block::SANDSTONE, 2 ) );
BuildingUtils::fill ( $this->level, new Vector3 ( $x - 4, $y + 5, $z - 8 ), new Vector3 ( $x - 5, $y + 6, $z - 8 ), Block::get ( Block::AIR ) );
break;
case self::DIRECTION_MINX :
for($xx = $x - 1; $xx <= $x; $xx ++) {
$this->placeBlock ( $xx, $y + 1, $z - 1 );
$this->placeBlock ( $xx, $y + 2, $z - 1 );
}
$this->placeBlock ( $x, $y + 1, $z, Block::SANDSTONE_STAIRS, 1 );
$this->placeBlock ( $x - 1, $y + 1, $z );
$this->placeSlab ( $x - 1, $y + 2, $z );
// Pattern
foreach ( [
1,
2,
4
] as $h ) {
$this->placeBlock ( $x - 2, $y + $h, $z - 1, Block::SANDSTONE, 2 );
$this->placeBlock ( $x - 2, $y + $h, $z + 1, Block::SANDSTONE, 2 );
$this->placeBlock ( $x - 2, $y + $h, $z, Block::STAINED_HARDENED_CLAY, 1 );
}
foreach ( [
3,
5
] as $h ) {
$this->placeBlock ( $x - 2, $y + $h, $z - 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 2, $y + $h, $z + 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 2, $y + $h, $z, Block::SANDSTONE, 1 );
}
$this->placeBlock ( $x - 2, $y + 6, $z - 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 2, $y + 6, $z, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 2, $y + 6, $z + 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 2, $y + 7, $z - 1, Block::SANDSTONE, 2 );
$this->placeBlock ( $x - 2, $y + 7, $z, Block::SANDSTONE, 2 );
$this->placeBlock ( $x - 2, $y + 7, $z + 1, Block::SANDSTONE, 2 );
// Building entrance to second floor.
BuildingUtils::fill ( $this->level, new Vector3 ( $x + 4, $y + 5, $z - 9 ), new Vector3 ( $x + 5, $y + 7, $z - 7 ), Block::get ( Block::SANDSTONE, 2 ) );
BuildingUtils::fill ( $this->level, new Vector3 ( $x + 4, $y + 5, $z - 8 ), new Vector3 ( $x + 5, $y + 6, $z - 8 ), Block::get ( Block::AIR ) );
break;
}
// Finishing stairs system
$this->placeBlock ( $x, $y + 3, $z - 2, Block::SANDSTONE_STAIRS, 3 );
$this->placeBlock ( $x, $y + 4, $z - 3, Block::SANDSTONE_STAIRS, 3 );
$this->placeBlock ( $x, $y + 4, $z - 2, Block::AIR );
$this->placeBlock ( $x, $y + 5, $z - 2, Block::AIR );
$this->placeBlock ( $x, $y + 6, $z - 2, Block::AIR );
// Making path from stairs to first floor.
BuildingUtils::fill ( $this->level, new Vector3 ( $x + 2, $y, $z - 4 ), new Vector3 ( $x - 2, $y + 4, $z - 9 ), Block::get ( Block::SANDSTONE ) );
// Other side pattern
foreach ( [
1,
2,
4
] as $h ) {
$this->placeBlock ( $x + 1, $y + $h, $z + 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x - 1, $y + $h, $z + 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x, $y + $h, $z + 2, Block::STAINED_HARDENED_CLAY, 1 );
}
foreach ( [
3,
5
] as $h ) {
$this->placeBlock ( $x + 1, $y + $h, $z + 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 1, $y + $h, $z + 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x, $y + $h, $z + 2, Block::SANDSTONE, 1 );
}
$this->placeBlock ( $x - 1, $y + 6, $z + 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x, $y + 6, $z + 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 1, $y + 6, $z + 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 1, $y + 7, $z + 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x, $y + 7, $z + 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 1, $y + 7, $z + 2, Block::SANDSTONE, 2 );
break;
case self::DIRECTION_MINZ : // z- (3)
// Stairs
switch ($direction2) {
case self::DIRECTION_PLUSX :
for($xx = $x + 1; $xx >= $x; $xx --) {
$this->placeBlock ( $xx, $y + 1, $z + 1 );
$this->placeBlock ( $xx, $y + 2, $z + 1 );
}
$this->placeBlock ( $x, $y + 1, $z, Block::SANDSTONE_STAIRS, 0 );
$this->placeBlock ( $x + 1, $y + 1, $z );
$this->placeSlab ( $x + 1, $y + 2, $z );
// Pattern
foreach ( [
1,
2,
4
] as $h ) {
$this->placeBlock ( $x + 2, $y + $h, $z + 1, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 2, $y + $h, $z - 1, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 2, $y + $h, $z, Block::STAINED_HARDENED_CLAY, 1 );
}
foreach ( [
3,
5
] as $h ) {
$this->placeBlock ( $x + 2, $y + $h, $z + 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 2, $y + $h, $z - 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 2, $y + $h, $z, Block::SANDSTONE, 1 );
}
$this->placeBlock ( $x + 2, $y + 6, $z - 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 2, $y + 6, $z, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 2, $y + 6, $z + 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 2, $y + 7, $z - 1, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 2, $y + 7, $z, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 2, $y + 7, $z + 1, Block::SANDSTONE, 2 );
// Building entrance to second floor.
BuildingUtils::fill ( $this->level, new Vector3 ( $x - 4, $y + 5, $z + 9 ), new Vector3 ( $x - 5, $y + 7, $z + 7 ), Block::get ( Block::SANDSTONE, 2 ) );
BuildingUtils::fill ( $this->level, new Vector3 ( $x - 4, $y + 5, $z + 8 ), new Vector3 ( $x - 5, $y + 6, $z + 8 ), Block::get ( Block::AIR ) );
break;
case self::DIRECTION_MINX :
for($xx = $x - 1; $xx <= $x; $xx ++) {
$this->placeBlock ( $xx, $y + 1, $z + 1 );
$this->placeBlock ( $xx, $y + 2, $z + 1 );
}
$this->placeBlock ( $x, $y + 1, $z, Block::SANDSTONE_STAIRS, 1 );
$this->placeBlock ( $x - 1, $y + 1, $z );
$this->placeSlab ( $x - 1, $y + 2, $z );
// Pattern
foreach ( [
1,
2,
4
] as $h ) {
$this->placeBlock ( $x - 2, $y + $h, $z - 1, Block::SANDSTONE, 2 );
$this->placeBlock ( $x - 2, $y + $h, $z + 1, Block::SANDSTONE, 2 );
$this->placeBlock ( $x - 2, $y + $h, $z, Block::STAINED_HARDENED_CLAY, 1 );
}
foreach ( [
3,
5
] as $h ) {
$this->placeBlock ( $x - 2, $y + $h, $z - 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 2, $y + $h, $z + 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 2, $y + $h, $z, Block::SANDSTONE, 1 );
}
$this->placeBlock ( $x - 2, $y + 6, $z - 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 2, $y + 6, $z, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 2, $y + 6, $z + 1, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 2, $y + 7, $z - 1, Block::SANDSTONE, 2 );
$this->placeBlock ( $x - 2, $y + 7, $z, Block::SANDSTONE, 2 );
$this->placeBlock ( $x - 2, $y + 7, $z + 1, Block::SANDSTONE, 2 );
// Building entrance to second floor.
BuildingUtils::fill ( $this->level, new Vector3 ( $x + 4, $y + 5, $z + 9 ), new Vector3 ( $x + 5, $y + 7, $z + 7 ), Block::get ( Block::SANDSTONE, 2 ) );
BuildingUtils::fill ( $this->level, new Vector3 ( $x + 4, $y + 5, $z + 8 ), new Vector3 ( $x + 5, $y + 6, $z + 8 ), Block::get ( Block::AIR ) );
break;
}
// Finishing stairs system
$this->placeBlock ( $x, $y + 3, $z + 2, Block::SANDSTONE_STAIRS, 2 );
$this->placeBlock ( $x, $y + 4, $z + 3, Block::SANDSTONE_STAIRS, 2 );
$this->placeBlock ( $x, $y + 4, $z + 2, Block::AIR );
$this->placeBlock ( $x, $y + 5, $z + 2, Block::AIR );
$this->placeBlock ( $x, $y + 6, $z + 2, Block::AIR );
// Making path from stairs to first floor.
BuildingUtils::fill ( $this->level, new Vector3 ( $x + 2, $y, $z + 4 ), new Vector3 ( $x - 2, $y + 4, $z + 9 ), Block::get ( Block::SANDSTONE ) );
// Other side pattern
foreach ( [
1,
2,
4
] as $h ) {
$this->placeBlock ( $x + 1, $y + $h, $z - 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x - 1, $y + $h, $z - 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x, $y + $h, $z - 2, Block::STAINED_HARDENED_CLAY, 1 );
}
foreach ( [
3,
5
] as $h ) {
$this->placeBlock ( $x + 1, $y + $h, $z - 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 1, $y + $h, $z - 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x, $y + $h, $z - 2, Block::SANDSTONE, 1 );
}
$this->placeBlock ( $x - 1, $y + 6, $z - 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x, $y + 6, $z - 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x + 1, $y + 6, $z - 2, Block::STAINED_HARDENED_CLAY, 1 );
$this->placeBlock ( $x - 1, $y + 7, $z - 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x, $y + 7, $z - 2, Block::SANDSTONE, 2 );
$this->placeBlock ( $x + 1, $y + 7, $z - 2, Block::SANDSTONE, 2 );
break;
}
// Making top
BuildingUtils::top ( $this->level, new Vector3 ( $x - 1, $y + 9, $z - 1 ), new Vector3 ( $x + 1, $y, $z + 1 ), Block::get ( Block::SANDSTONE ) );
$this->placeBlock ( $x - 2, $y + 9, $z, Block::SANDSTONE_STAIRS, 0 );
$this->placeBlock ( $x + 2, $y + 9, $z, Block::SANDSTONE_STAIRS, 1 );
$this->placeBlock ( $x, $y + 9, $z - 2, Block::SANDSTONE_STAIRS, 2 );
$this->placeBlock ( $x, $y + 9, $z + 2, Block::SANDSTONE_STAIRS, 3 );
}
/*
* Inverses a direction
* @param $direction int
* @return int
*/
protected function getInversedDirection(int $direction): int {
switch ($direction) {
case self::DIRECTION_PLUSX : // x+ (0)
return self::DIRECTION_MINX;
break;
case self::DIRECTION_MINX : // x- (1)
return self::DIRECTION_PLUSX;
break;
case self::DIRECTION_PLUSZ : // z+ (2)
return self::DIRECTION_MINZ;
break;
case self::DIRECTION_MINZ : // z- (3)
return self::DIRECTION_PLUSZ;
break;
default :
return - 1;
break;
}
}
}

View file

@ -0,0 +1,130 @@
<?php
/*
* Well from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\structure;
use pocketmine\block\Block;
use pocketmine\level\ChunkManager;
use pocketmine\utils\Random;
use pocketmine\level\generator\object\Object;
class Well extends Object {
public $overridable = [
Block::AIR => true,
6 => true,
17 => true,
18 => true,
Block::DANDELION => true,
Block::POPPY => true,
Block::SNOW_LAYER => true,
Block::LOG2 => true,
Block::LEAVES2 => true,
Block::CACTUS => true
];
protected $directions = [
[
1,
1
],
[
1,
- 1
],
[
- 1,
- 1
],
[
- 1,
1
]
];
/*
* Checks if a well is placeable
* @param $level pocketmine\level\ChunkManager
* @param $x int
* @param $y int
* @param $z int
* @param $random pocketmine\utils\Random
* @return bool
*/
public function canPlaceObject(ChunkManager $level, $x, $y, $z, Random $random) {
for($xx = $x - 2; $xx <= $x + 2; $xx ++)
for($yy = $y; $yy <= $y + 3; $yy ++)
for($zz = $z - 2; $zz <= $z + 2; $zz ++)
if (! isset ( $this->overridable [$level->getBlockIdAt ( $xx, $yy, $zz )] ))
return false;
return true;
}
/*
* Places a well
* @param $level pocketmine\level\ChunkManager
* @param $x int
* @param $y int
* @param $z int
* @param $random pocketmine\utils\Random
*/
public function placeObject(ChunkManager $level, $x, $y, $z, Random $random) {
$this->level = $level;
foreach ( $this->directions as $direction ) {
// Building pillard
for($yy = $y; $yy < $y + 3; $yy ++)
$this->placeBlock ( $x + $direction [0], $yy, $z + $direction [1], Block::SANDSTONE );
// Building corners
$this->placeBlock ( $x + ($direction [0] * 2), $y, $z + $direction [1], Block::SANDSTONE );
$this->placeBlock ( $x + $direction [0], $y, $z + ($direction [1] * 2), Block::SANDSTONE );
$this->placeBlock ( $x + ($direction [0] * 2), $y, $z + ($direction [1] * 2), Block::SANDSTONE );
// Building slabs on the sides. Places two times due to all directions.
$this->placeSlab ( $x + ($direction [0] * 2), $y, $z );
$this->placeSlab ( $x, $y, $z + ($direction [1] * 2) );
// Placing water.Places two times due to all directions.
$this->placeBlock ( $x + $direction [0], $y, $z, Block::WATER );
$this->placeBlock ( $x, $y, $z + $direction [1], Block::WATER );
}
// Finitions
for($xx = $x - 1; $xx <= $x + 1; $xx ++)
for($zz = $z - 1; $zz <= $z + 1; $zz ++)
$this->placeSlab ( $xx, $y + 3, $zz );
$this->placeSlab ( $x, $y + 3, $z, Block::SANDSTONE );
$this->placeSlab ( $x, $y, $z, Block::WATER );
}
/*
* Places a slab
* @param $x int
* @param $y int
* @param $z int
* @return void
*/
public function placeSlab($x, $y, $z) {
$this->level->setBlockIdAt ( $x, $y, $z, 44 );
$this->level->setBlockDataAt ( $x, $y, $z, 1 );
}
/*
* Places a slab
* @param $x int
* @param $y int
* @param $z int
* @param $id int
* @return void
*/
public function placeBlock($x, $y, $z, $id) {
$this->level->setBlockIdAt ( $x, $y, $z, $id );
}
}

View file

@ -0,0 +1,44 @@
<?php
namespace Ad5001\BetterGen\tasks;
use Ad5001\BetterGen\Main;
use Ad5001\BetterGen\loot\LootTable;
use pocketmine\block\Block;
use pocketmine\scheduler\PluginTask;
use pocketmine\level\Position;
use pocketmine\item\Item;
/*
* ChestGenerateTask from BetterGen
* Copyright (C) Ad5001 2017
*
* @author Ad5001
* @link https://en.ad5001.eu
*/
class ChestGenerateTask extends PluginTask {
protected $block;
protected $pos;
protected $item;
/*
* Constructs the class
*/
public function __construct(Main $main, Block $block, Position $pos, Item $item) {
parent::__construct($main);
$this->block = $block;
$this->pos = $pos;
$this->item = $item;
}
/*
* Runs when the delay comes
*/
public function onRun($currentTick) {
$this->block->place($this->item, $this->pos->getLevel()->getBlock($this->pos), $this->block, 0, 0, 0, 0);
$inv = $this->pos->getLevel()->getTile($this->pos);
LootTable::fillChest($inv->getInventory(), $this->pos);
}
}

View file

@ -0,0 +1,188 @@
<?php
/*
* BuildingUtils from BetterGen
* Copyright (C) Ad5001 2017
* Licensed under the BoxOfDevs Public General LICENSE which can be found in the file LICENSE in the root directory
* @author ad5001
*/
namespace Ad5001\BetterGen\utils;
use pocketmine\math\Vector3;
use pocketmine\block\Block;
use pocketmine\level\ChunkManager;
use pocketmine\utils\Random;
class BuildingUtils {
const TO_NOT_OVERWRITE = [
Block::WATER,
Block::STILL_WATER,
Block::STILL_LAVA,
Block::LAVA,
Block::BEDROCK,
Block::CACTUS,
Block::PLANK
];
/*
* Fills an area
* @param $level pocketmine\level\ChunkManager
* @param $pos1 pocketmine\math\Vector3
* @param $pos2 pocketmine\math\Vector3
* @param $block pocketmine\block\Block
* @return void
*/
public static function fill(ChunkManager $level, Vector3 $pos1, Vector3 $pos2, Block $block = null) {
if ($block == null)
$block = Block::get ( Block::AIR );
list ( $pos1, $pos2 ) = self::minmax ( $pos1, $pos2 );
for($x = $pos1->x; $x >= $pos2->x; $x --)
for($y = $pos1->y; $y >= $pos2->y; $y --)
for($z = $pos1->z; $z >= $pos2->z; $z --) {
$level->setBlockIdAt ( $x, $y, $z, $block->getId () );
$level->setBlockDataAt ( $x, $y, $z, $block->getDamage () );
}
}
/*
* Fills an area by custom filling
* @param $pos1 pocketmine\math\Vector3
* @param $pos2 pocketmine\math\Vector3
* @param $call callback
* @param $params array
* @return void
*/
public static function fillCallback(Vector3 $pos1, Vector3 $pos2, callable $call, ...$params) {
list ( $pos1, $pos2 ) = self::minmax ( $pos1, $pos2 );
for($x = $pos1->x; $x >= $pos2->x; $x --)
for($y = $pos1->y; $y >= $pos2->y; $y --)
for($z = $pos1->z; $z >= $pos2->z; $z --) {
call_user_func ( $call, new Vector3 ( $x, $y, $z ), $params );
}
}
/*
* Creates walls
* @param $level pocketmine\level\ChunkManager
* @param $pos1 pocketmine\math\Vector3
* @param $pos2 pocketmine\math\Vector3
* @param $block pocketmine\block\Block
* @return void
*/
public static function walls(ChunkManager $level, Vector3 $pos1, Vector3 $pos2, Block $block) {
list ( $pos1, $pos2 ) = self::minmax ( $pos1, $pos2 );
for($y = $pos1->y; $y >= $pos2->y; $y --) {
for($x = $pos1->x; $x >= $pos2->x; $x --) {
$level->setBlockIdAt ( $x, $y, $pos1->z, $block->getId () );
$level->setBlockDataAt ( $x, $y, $pos1->z, $block->getDamage () );
$level->setBlockIdAt ( $x, $y, $pos2->z, $block->getId () );
$level->setBlockDataAt ( $x, $y, $pos2->z, $block->getDamage () );
}
for($z = $pos1->z; $z >= $pos2->z; $z --) {
$level->setBlockIdAt ( $pos1->x, $y, $z, $block->getId () );
$level->setBlockDataAt ( $pos1->x, $y, $z, $block->getDamage () );
$level->setBlockIdAt ( $pos2->x, $y, $z, $block->getId () );
$level->setBlockDataAt ( $pos2->x, $y, $z, $block->getDamage () );
}
}
}
/*
* Creates the top of a structure
* @param $level pocketmine\level\ChunkManager
* @param $pos1 pocketmine\math\Vector3
* @param $pos2 pocketmine\math\Vector3
* @param $block pocketmine\block\Block
* @return void
*/
public static function top(ChunkManager $level, Vector3 $pos1, Vector3 $pos2, Block $block) {
list ( $pos1, $pos2 ) = self::minmax ( $pos1, $pos2 );
for($x = $pos1->x; $x >= $pos2->x; $x --)
for($z = $pos1->z; $z >= $pos2->z; $z --) {
$level->setBlockIdAt ( $x, $pos1->y, $z, $block->getId () );
$level->setBlockDataAt ( $x, $pos1->y, $z, $block->getDamage () );
}
}
/*
* Creates all corners from positions. Used for Mineshaft.
* @param $level pocketmine\level\ChunkManager
* @param $pos1 pocketmine\math\Vector3
* @param $pos2 pocketmine\math\Vector3
* @param $block pocketmine\block\Block
* @return void
*/
public static function corners(ChunkManager $level, Vector3 $pos1, Vector3 $pos2, Block $block) {
list ( $pos1, $pos2 ) = self::minmax ( $pos1, $pos2 );
for($y = $pos1->y; $y >= $pos2->y; $y --) {
$level->setBlockIdAt ( $pos1->x, $y, $pos1->z, $block->getId () );
$level->setBlockDataAt ( $pos1->x, $y, $pos1->z, $block->getDamage () );
$level->setBlockIdAt ( $pos2->x, $y, $pos1->z, $block->getId () );
$level->setBlockDataAt ( $pos2->x, $y, $pos1->z, $block->getDamage () );
$level->setBlockIdAt ( $pos1->x, $y, $pos2->z, $block->getId () );
$level->setBlockDataAt ( $pos1->x, $y, $pos2->z, $block->getDamage () );
$level->setBlockIdAt ( $pos2->x, $y, $pos2->z, $block->getId () );
$level->setBlockDataAt ( $pos2->x, $y, $pos2->z, $block->getDamage () );
}
}
/*
* Creates the bottom of a structure
* @param $level pocketmine\level\ChunkManager
* @param $pos1 pocketmine\math\Vector3
* @param $pos2 pocketmine\math\Vector3
* @param $block pocketmine\block\Block
* @return void
*/
public static function bottom(ChunkManager $level, Vector3 $pos1, Vector3 $pos2, Block $block) {
list ( $pos1, $pos2 ) = self::minmax ( $pos1, $pos2 );
for($x = $pos1->x; $x >= $pos2->x; $x --)
for($z = $pos1->z; $z >= $pos2->z; $z --) {
$level->setBlockIdAt ( $x, $pos2->y, $z, $block->getId () );
$level->setBlockDataAt ( $x, $pos2->y, $z, $block->getDamage () );
}
}
/*
* Builds a random structure depending of length, height, depth and random
* @param $level pocketmine\level\ChunkManager
* @param $pos pocketmine\math\Vector3
* @param $infos pocketmine\math\Vector3
* @param $random pocketmine\utils\Random
* @param $block pocketmine\block\Block
* @return void
*/
public function buildRandom(ChunkManager $level, Vector3 $pos, Vector3 $infos, Random $random, Block $block) {
$xBounded = $random->nextBoundedInt ( 3 ) - 1;
$yBounded = $random->nextBoundedInt ( 3 ) - 1;
$zBounded = $random->nextBoundedInt ( 3 ) - 1;
$pos = $pos->round ();
for($x = $pos->x - ($infos->x / 2); $x <= $pos->x + ($infos->x / 2); $x ++) {
for($y = $pos->y - ($infos->y / 2); $y <= $pos->y + ($infos->y / 2); $y ++) {
for($z = $pos->z - ($infos->z / 2); $z <= $pos->z + ($infos->z / 2); $z ++) {
// if(abs((abs($x) - abs($pos->x)) ** 2 + ($y - $pos->y) ** 2 + (abs($z) - abs($pos->z)) ** 2) < (abs($infos->x / 2 + $xBounded) + abs($infos->y / 2 + $yBounded) + abs($infos->z / 2 + $zBounded)) ** 2
if (abs ( (abs ( $x ) - abs ( $pos->x )) ** 2 + ($y - $pos->y) ** 2 + (abs ( $z ) - abs ( $pos->z )) ** 2 ) < ((($infos->x / 2 - $xBounded) + ($infos->y / 2 - $yBounded) + ($infos->z / 2 - $zBounded)) / 3) ** 2 && $y > 0 && ! in_array ( $level->getBlockIdAt ( $x, $y, $z ), self::TO_NOT_OVERWRITE ) && ! in_array ( $level->getBlockIdAt ( $x, $y + 1, $z ), self::TO_NOT_OVERWRITE )) {
$level->setBlockIdAt ( $x, $y, $z, $block->getId () );
$level->setBlockDataAt ( $x, $y, $z, $block->getDamage () );
}
}
}
}
}
/*
* Returns 2 vector3, one with minimal values, one with max values of the provided ones.
* @param $pos1 pocketmine\math\Vector3
* @param $pos2 pocketmine\math\Vector3
* @return array
*/
protected static function minmax(Vector3 $pos1, Vector3 $pos2): array {
$v1 = new Vector3 ( max ( $pos1->x, $pos2->x ), max ( $pos1->y, $pos2->y ), max ( $pos1->z, $pos2->z ) );
$v2 = new Vector3 ( min ( $pos1->x, $pos2->x ), min ( $pos1->y, $pos2->y ), min ( $pos1->z, $pos2->z ) );
return [
$v1,
$v2
];
}
}