Uploading plugin

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

126
LICENSE Normal file
View File

@ -0,0 +1,126 @@
BoxOfDevs General Software License 1.1.3
=========================================
This license is designed to be used with any software which would like to have no selling for profits, nor any public redistribution without giving the original author credits.
--------------------------------------------------------------------------------------------------------------------------------------
The License: refers to the BoxOfDevs International Software License 1.1.2
The Software: refers to any works licensed under The License.
The Modification: refers to any modified version of The Software.
The Redistribution: refers to any redistributions of The Software/The Modification.
The User: refers to any user of The Software licensed under The License.
The Author: refers to any developer, organisation, legal owner, or creator of The Software that has been licensed under the The License.
--------------------------------------------------------------------------------------------------------------------------------------
Section 1 - Allowances:
1. Both The User & The Author Can:
a. Modify private copies of The Software and use in any way they wish.
b. Change which license The Software/The Modification is licensed under.
2. The User Can:
a. Request new features, support, or more rights from The Author.
b. Redistribute The Software/The Modification, ensuring The User gives all appropriate credit to The Author and alerting The Author to The Redistribution.
3. The Author Can:
a. Change or update The Software in any way they wish, ensuring they follow the other terms of The License.
b. Grant extra rights to The User who has requested them.
c. Reserve the right to request The User to take down their instance of The Software/The Modification/The Redistribution.
Section 2 - Restrictions:
1. Both The User & The Author Cannot:
a. Introduce any malicious code into The Software/The Modification.
b. Sell any part of The Software/The Modification for profit.
2. The User Cannot:
a. Hold The Author responsible for any unknown errors.
b. Claim The Software/The Modification/The Redistribution as entirely The User's product.
c. Use the software without crediting the Author.
3. The Author Cannot:
a. Restrict The User in any way not specified by The License.
b. Distribute any form of The Software without proper documentation.
Term. The term of this License is specified in Section 6(a).
Media and formats; technical modifications allowed. The Author authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Author waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this License, simply making modifications authorized by this Section 2(a)(4) never produces Modification.
Downstream recipients.
Offer from the Author Software. Every recipient of the Software automatically receives an offer from the Author to exercise the Licensed Rights under the terms and conditions of this License.
Additional offer from the Author the Modification. Every recipient of the Modification from You automatically receives an offer from the Author to exercise the Licensed Rights in the Modification under the conditions of the Adapters License You apply.
No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Software if doing so restricts exercise of the Licensed Rights by any recipient of the Software.
No endorsement. Nothing in this License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Software is, connected with, or sponsored, endorsed, or granted official status by, the Author or others designated to receive attribution as provided in Section 3(a)(1)(A)(i).
Other rights.
Moral rights, such as the right of integrity, are not licensed under this License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Author waives and/or agrees not to assert any such rights held by the Author to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise.
Patent and trademark rights are not licensed under this License.
To the extent possible, the Author waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Author expressly reserves any right to collect such royalties.
Section 3 License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the following conditions.
a) Attribution.
If You Share the Software (including in modified form), You must:
retain the following if it is supplied by the Author with the Software:
identification of the creator(s) of the Software and any others designated to receive attribution, in any reasonable manner requested by the Author (including by pseudonym if designated);
a copyright notice;
a notice that refers to this License;
a notice that refers to the disclaimer of warranties;
a URI or hyperlink to the Software to the extent reasonably practicable;
indicate if You modified the Software and retain an indication of any previous modifications; and
indicate the Software is licensed under this License, and include the text of, or the URI or hyperlink to, this License.
You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Software. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information.
If requested by the Author, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable.
b) ShareAlike.
In addition to the conditions in Section 3(a), if You Share the Modification You produce, the following conditions also apply.
The Adapters License You apply must be a BoxOfDevs General License with the same License Elements, this version or later, or a BY-SA Compatible License.
You must include the text of, or the URI or hyperlink to, the Adapter's License You apply. You may satisfy this condition in any reasonable manner based on the medium, means, and context in which You Share the Modification.
You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, Modification that restrict exercise of the rights granted under the Adapter's License You apply.
c) Forever Open Source.
In addition to the conditions in Section 3(a) and Section 3(b), if You Share the Modification You produce, the following conditions also apply.
The Adapted work must have an open source existing repertory, accessible by anyone anytime linked in the Redistribution Description/Documentation.
You may not restrict anyone from accessing the source code, use it, and redistribute it under anything not explicily specified by the License.
d) Free.
In addition to the conditions in Section 3(a), Section 3(b) and Section 3(c), if You Share by any way Modification and/or the Software You produce, the following conditions also apply.
The Work must be redistributed entirely free, under this license.
You may not impose fees to anyone that gets the Modification/The Software.
Section 4 Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Software:
for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database;
if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Modification, including for purposes of Section 3(b); and
You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this License where the Licensed Rights include other Copyright and Similar Rights.
Section 5 Disclaimer of Warranties and Limitation of Liability.
Unless otherwise separately undertaken by the Author, to the extent possible, the Author offers the Software as-is and as-available, and makes no representations or warranties of any kind concerning the Software, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You.
To the extent possible, in no event will the Author be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this License or use of the Software, even if the Author has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You.
The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability.
Section 6 Term and Termination.
This License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this License, then Your rights under this License terminate automatically.
Where Your right to use the Software has terminated under Section 6(a), it reinstates:
automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or
upon express reinstatement by the Author.
For the avoidance of doubt, this Section 6(b) does not affect any right the Author may have to seek remedies for Your violations of this License.
For the avoidance of doubt, the Author may also offer the Software under separate terms or conditions or stop distributing the Software at any time; however, doing so will not terminate this License.
Sections 1, 5, 6, 7, and 8 survive termination of this License.
Section 7 Other Terms and Conditions.
The Author shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed.
Any arrangements, understandings, or agreements regarding the Software not stated herein are separate from and independent of the terms and conditions of this License.
In the event that The License is updated/changed on the official github repository/on the official website, you automatically agree.
The Author is not required to notify The User that The License has been updated/changed.
Section 8 Interpretation.
For the avoidance of doubt, this License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Software that could lawfully be made without permission under this License.
To the extent possible, if any provision of this License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this License without affecting the enforceability of the remaining terms and conditions.
No term or condition of this License will be waived and no failure to comply consented to unless expressly agreed to by the Author.
Nothing in this License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Author or You, including from the legal processes of any jurisdiction or authority.

52
README.md Normal file
View File

@ -0,0 +1,52 @@
<img src="https://raw.githubusercontent.com/Ad5001/BetterGen/master/imgs/banner.png"></img>
<center><h1>PocketMine's Tomorrow's Generator.</h1></center>
Welcome user to the home of a new PocketMine World Generator which features 9 new/modified biomes:
------
# Commun:
### Commun structures to all biomes features:
1. <h3>Mineshafts:</h3>
<img src="https://raw.githubusercontent.com/Ad5001/BetterGen/master/imgs/Mineshaft.jpg" style="width: 500px"></img>
2. <h3>Ravines:</h3>
<img src="https://raw.githubusercontent.com/Ad5001/BetterGen/master/imgs/MesaRavine.jpg" style="width: 500px"></img>
3. <h3>Lakes:</h3>
<img src="https://raw.githubusercontent.com/Ad5001/BetterGen/master/imgs/lake.png" style="width: 500px"></img>
4. <h3>Caves:</h3>
<img src="https://raw.githubusercontent.com/Ad5001/BetterGen/master/imgs/cave.jpg" style="width: 500px"></img>
5. <h3>Floating islands:</h3>
<img src="https://raw.githubusercontent.com/Ad5001/BetterGen/master/imgs/Island.jpg" style="width: 500px"></img>
-----
# [NEW BIOME] Sakura forests:
### This biome features new trees: Sakura Trees, japanese pink and white trees and it's own bush.
<img src="https://raw.githubusercontent.com/Ad5001/BetterGen/master/imgs/sakura.jpg" style="width: 500px"></img>
-----
# [NEW BIOMES] Mesa Mountains & Plains
### These biomes are inspired (but not completly taken) from Minecraft PC.
<img src="https://raw.githubusercontent.com/Ad5001/BetterGen/master/imgs/mesa.png" style="width: 500px"></img>
-----
# Better Desert:
### The desert has been reworked and now includes the Minecraft PC's temples and wells !
### Additionaly, deadbush, sugar cane and cactus are here too !
<img src="https://raw.githubusercontent.com/Ad5001/BetterGen/master/imgs/temple.png" style="width: 500px"></img>
-----
# Better Ice Plains
### Ice plains got redisigned ! There is now snow instead of grass at it's bottom ! On the plus side, Igloos were imported from Minecraft PC !
<img src="https://raw.githubusercontent.com/Ad5001/BetterGen/master/imgs/igloo.jpg" style="width: 500px"></img>
-----
# Oak and Birch Forests:
### These two biomes now are a bit better by the additions of bushes.
<img src="https://raw.githubusercontent.com/Ad5001/BetterGen/master/imgs/bushes.png" style="width: 500px"></img>
All content here is copyrighted (C) Ad5001 2017. Infos about this copyright can be found in the license file.

BIN
imgs/Island.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

BIN
imgs/MesaRavine.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

BIN
imgs/Mineshaft.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

BIN
imgs/banner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
imgs/bushes.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

BIN
imgs/cave.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

BIN
imgs/igloo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

BIN
imgs/lake.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
imgs/mesa.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

BIN
imgs/sakura.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

BIN
imgs/temple.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

17
plugin.yml Normal file
View File

@ -0,0 +1,17 @@
---
# Base generated with ImagicalPlugCreator by Ad5001 (C) 2017 for Ad5001
# link: https://ad5001.eu
name: BetterGen
author: Ad5001
main: Ad5001\BetterGen\Main
version: 1.0
api: [3.0.1, 3.0.0-ALPHA3]
commands:
createworld:
description: Generates a new world.
usage: "/createworld <name> [generator = betternormal] [seed = rand()] [options (json)]"
permission: bettergen.cmd.createworld
permissions:
bettergen.cmd.createworld:
default: op
...

View File

@ -0,0 +1,183 @@
{
"max": 27,
"rail": {
"percentage": 79,
"minCount": 4,
"maxCount": 8,
"minStacks": 3,
"maxStacks": 3,
"id": 66,
"data": 0
},
"torch": {
"percentage": 66,
"minCount": 1,
"maxCount": 16,
"minStacks": 3,
"maxStacks": 3,
"id": 50,
"data": 0
},
"bread": {
"percentage": 45,
"minCount": 1,
"maxCount": 3,
"minStacks": 2,
"maxStacks": 4,
"id": 297,
"data": 0
},
"name tag": {
"percentage": 42,
"minCount": 1,
"maxCount": 1,
"minStacks": 2,
"maxStacks": 4,
"id": 297,
"data": 0
},
"coal": {
"percentage": 32,
"minCount": 3,
"maxCount": 8,
"minStacks": 2,
"maxStacks": 4,
"id": 263,
"data": 0
},
"beethroot seeds": {
"percentage": 32,
"minCount": 2,
"maxCount": 4,
"minStacks": 2,
"maxStacks": 4,
"id": 458,
"data": 0
},
"melon seeds": {
"percentage": 32,
"minCount": 2,
"maxCount": 4,
"minStacks": 2,
"maxStacks": 4,
"id": 362,
"data": 0
},
"pumpkin seeds": {
"percentage": 32,
"minCount": 2,
"maxCount": 4,
"minStacks": 2,
"maxStacks": 4,
"id": 361,
"data": 0
},
"iron ingot": {
"percentage": 32,
"minCount": 1,
"maxCount": 5,
"minStacks": 2,
"maxStacks": 4,
"id": 365,
"data": 0
},
"golden apple": {
"percentage": 28,
"minCount": 1,
"maxCount": 1,
"minStacks": 1,
"maxStacks": 1,
"id": 322,
"data": 0
},
"activator rail": {
"percentage": 27,
"minCount": 1,
"maxCount": 4,
"minStacks": 3,
"maxStacks": 3,
"id": 126,
"data": 0
},
"detector rail": {
"percentage": 27,
"minCount": 1,
"maxCount": 4,
"minStacks": 3,
"maxStacks": 3,
"id": 28,
"data": 0
},
"powered rail": {
"percentage": 27,
"minCount": 1,
"maxCount": 4,
"minStacks": 3,
"maxStacks": 3,
"id": 27,
"data": 0
},
"lapis lazuli": {
"percentage": 17,
"minCount": 4,
"maxCount": 9,
"minStacks": 2,
"maxStacks": 4,
"id": 351,
"data": 4
},
"redstone": {
"percentage": 17,
"minCount": 4,
"maxCount": 9,
"minStacks": 2,
"maxStacks": 4,
"id": 331,
"data": 0
},
"gold ingot": {
"percentage": 17,
"minCount": 1,
"maxCount": 3,
"minStacks": 2,
"maxStacks": 4,
"id": 366,
"data": 0
},
"enchanted book": {
"percentage": 14,
"minCount": 1,
"maxCount": 1,
"minStacks": 1,
"maxStacks": 1,
"id": 403,
"data": 0
},
"diamond": {
"percentage": 11,
"minCount": 1,
"maxCount": 2,
"minStacks": 2,
"maxStacks": 4,
"id": 264,
"data": 0
},
"iron pickaxe": {
"percentage": 7,
"minCount": 1,
"maxCount": 1,
"minStacks": 1,
"maxStacks": 1,
"id": 257,
"data": 0
},
"enchanted golden apple": {
"percentage": 1,
"minCount": 1,
"maxCount": 1,
"minStacks": 1,
"maxStacks": 1,
"id": 466,
"data": 0
}
}

154
resources/loots/temple.json Normal file
View File

@ -0,0 +1,154 @@
{
"max": 27,
"bone": {
"percentage": 71,
"minCount": 4,
"maxCount": 6,
"minStacks": 2,
"maxStacks": 4,
"id": 352,
"data": 0
},
"rotten_flesh": {
"percentage": 71,
"minCount": 3,
"maxCount": 7,
"minStacks": 2,
"maxStacks": 4,
"id": 367,
"data": 0
},
"gunpowder": {
"percentage": 59,
"minCount": 1,
"maxCount": 8,
"minStacks": 4,
"maxStacks": 4,
"id": 289,
"data": 0
},
"sand": {
"percentage": 59,
"minCount": 1,
"maxCount": 8,
"minStacks": 4,
"maxStacks": 4,
"id": 12,
"data": 0
},
"string": {
"percentage": 59,
"minCount": 1,
"maxCount": 8,
"minStacks": 4,
"maxStacks": 4,
"id": 287,
"data": 0
},
"spider_eye": {
"percentage": 29,
"minCount": 1,
"maxCount": 3,
"minStacks": 2,
"maxStacks": 4,
"id": 375,
"data": 0
},
"enchanted_book": {
"percentage": 24,
"minCount": 1,
"maxCount": 1,
"id": 403,
"data": 0
},
"saddle": {
"percentage": 24,
"minCount": 1,
"maxCount": 1,
"minStacks": 2,
"maxStacks": 4,
"id": 329,
"data": 0
},
"golden_apple": {
"percentage": 24,
"minCount": 1,
"maxCount": 1,
"minStacks": 1,
"maxStacks": 1,
"id": 322,
"data": 0
},
"gold_ingot": {
"percentage": 18,
"minCount": 2,
"maxCount": 7,
"minStacks": 2,
"maxStacks": 4,
"id": 266,
"data": 0
},
"iron_ingot": {
"percentage": 18,
"minCount": 1,
"maxCount": 5,
"minStacks": 2,
"maxStacks": 4,
"id": 265,
"data": 0
},
"emerald": {
"percentage": 18,
"minCount": 1,
"maxCount": 3,
"minStacks": 2,
"maxStacks": 4,
"id": 388,
"data": 0
},
"iron_horse_armor": {
"percentage": 18,
"minCount": 1,
"maxCount": 1,
"minStacks": 2,
"maxStacks": 4,
"id": 417,
"data": 0
},
"gold_horse_armor": {
"percentage": 12,
"minCount": 1,
"maxCount": 1,
"minStacks": 2,
"maxStacks": 4,
"id": 418,
"data": 0
},
"diamond": {
"percentage": 6,
"minCount": 1,
"maxCount": 3,
"minStacks": 2,
"maxStacks": 4,
"id": 264,
"data": 0
},
"diamond_horse_armor": {
"percentage": 6,
"minCount": 1,
"maxCount": 1,
"minStacks": 2,
"maxStacks": 4,
"id": 419,
"data": 0
},
"enchanted_golden_apple": {
"percentage": 3,
"minCount": 1,
"maxCount": 1,
"minStacks": 2,
"maxStacks": 4,
"id": 466,
"data": 0
}
}

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
];
}
}