forked from Ad5001/BetterGen
293 lines
11 KiB
PHP
293 lines
11 KiB
PHP
<?php
|
|
/**
|
|
* ____ __ __ ____
|
|
* /\ _`\ /\ \__ /\ \__ /\ _`\
|
|
* \ \ \L\ \ __ \ \ ,_\\ \ ,_\ __ _ __ \ \ \L\_\ __ ___
|
|
* \ \ _ <' /'__`\\ \ \/ \ \ \/ /'__`\/\`'__\\ \ \L_L /'__`\ /' _ `\
|
|
* \ \ \L\ \/\ __/ \ \ \_ \ \ \_ /\ __/\ \ \/ \ \ \/, \/\ __/ /\ \/\ \
|
|
* \ \____/\ \____\ \ \__\ \ \__\\ \____\\ \_\ \ \____/\ \____\\ \_\ \_\
|
|
* \/___/ \/____/ \/__/ \/__/ \/____/ \/_/ \/___/ \/____/ \/_/\/_/
|
|
* Tomorrow's pocketmine generator.
|
|
* @author Ad5001 <mail@ad5001.eu>, XenialDan <https://github.com/thebigsmileXD>
|
|
* @link https://github.com/Ad5001/BetterGen
|
|
* @category World Generator
|
|
* @api 3.0.0
|
|
* @version 1.1
|
|
*/
|
|
|
|
namespace Ad5001\BetterGen;
|
|
|
|
use Ad5001\BetterGen\biome\BetterForest;
|
|
use Ad5001\BetterGen\generator\BetterNormal;
|
|
use Ad5001\BetterGen\loot\LootTable;
|
|
use Ad5001\BetterGen\structure\Temple;
|
|
use pocketmine\block\Block;
|
|
use pocketmine\command\Command;
|
|
use pocketmine\command\CommandSender;
|
|
use pocketmine\command\ConsoleCommandSender;
|
|
use pocketmine\event\block\BlockBreakEvent;
|
|
use pocketmine\event\level\ChunkPopulateEvent;
|
|
use pocketmine\event\Listener;
|
|
use pocketmine\event\player\PlayerInteractEvent;
|
|
use pocketmine\level\generator\biome\Biome;
|
|
use pocketmine\level\generator\Generator;
|
|
use pocketmine\nbt\tag\CompoundTag;
|
|
use pocketmine\nbt\tag\IntTag;
|
|
use pocketmine\nbt\tag\ListTag;
|
|
use pocketmine\nbt\tag\StringTag;
|
|
use pocketmine\Player;
|
|
use pocketmine\plugin\PluginBase;
|
|
use pocketmine\tile\Chest;
|
|
use pocketmine\tile\Tile;
|
|
use pocketmine\utils\Config;
|
|
use pocketmine\utils\Random;
|
|
|
|
class Main extends PluginBase implements Listener {
|
|
const PREFIX = "§l§o§b[§r§l§2Better§aGen§o§b]§r§f ";
|
|
const SAKURA_FOREST = 100; // Letting some place for future biomes.
|
|
|
|
/**
|
|
* Regisetrs a biome to betternormal
|
|
*
|
|
* @param int $id
|
|
* @param Biome $biome
|
|
* @return void
|
|
*/
|
|
public static function registerBiome(int $id, Biome $biome) {
|
|
BetterNormal::registerBiome($biome);
|
|
}
|
|
|
|
/**
|
|
* Called when the plugin enales
|
|
*
|
|
* @return void
|
|
*/
|
|
public function onEnable() {
|
|
$this->getServer()->getPluginManager()->registerEvents($this, $this);
|
|
Generator::addGenerator(BetterNormal::class, "betternormal");
|
|
if ($this->isOtherNS()) $this->getLogger()->warning("Tesseract detected. Note that Tesseract is not up to date with the generation structure and some generation features may be limited or not working");
|
|
@mkdir(LootTable::getPluginFolder());
|
|
@mkdir(LootTable::getPluginFolder() . "loots");
|
|
if (!file_exists(LootTable::getPluginFolder() . "processingLoots.json"))
|
|
file_put_contents(LootTable::getPluginFolder() . "processingLoots.json", "{}");
|
|
}
|
|
|
|
|
|
/**
|
|
* Checks for tesseract like namespaces. Returns true if thats the case
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public static function isOtherNS() {
|
|
try {
|
|
return @class_exists("pocketmine\\level\\generator\\normal\\object\\OakTree");
|
|
} catch (\Exception $e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called when a command executes
|
|
*
|
|
* @param CommandSender $sender
|
|
* @param Command $cmd
|
|
* @param int $label
|
|
* @param array $args
|
|
* @return bool
|
|
*/
|
|
public function onCommand(CommandSender $sender, 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]);
|
|
$parts = str_split($args[2]);
|
|
foreach ($parts as $key=>$str) {
|
|
if(is_numeric($str) == false && $str <> '-'){
|
|
$parts[$key] = ord($str);
|
|
}
|
|
}
|
|
$seed = (int)implode("", $parts);
|
|
$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 ($args[2] == "rand") $args[2] = $this->generateRandomSeed();
|
|
$parts = str_split($args[2]);
|
|
foreach ($parts as $key=>$str) {
|
|
if(is_numeric($str) == false && $str <> '-'){
|
|
$parts[$key] = ord($str);
|
|
}
|
|
}
|
|
$seed = (int)implode("", $parts);
|
|
unset($args[0], $args[1], $args[2]);
|
|
$options = json_decode($args[3], true);
|
|
if (!is_array($options)) {
|
|
$sender->sendMessage(Main::PREFIX . "§4Invalid JSON for options.");
|
|
return true;
|
|
}
|
|
break;
|
|
}
|
|
$options["preset"] = json_encode($options);
|
|
if ((int)$seed == 0/*String*/) {
|
|
$seed = $this->generateRandomSeed();
|
|
}
|
|
$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;
|
|
case "worldtp":
|
|
if(isset($args[0])) {
|
|
if(is_null($this->getServer()->getLevelByName($args[0]))) {
|
|
$this->getServer()->loadLevel($args[0]);
|
|
if(is_null($this->getServer()->getLevelByName($args[0]))) {
|
|
$sender->sendMessage("Could not find level {$args[0]}.");
|
|
return false;
|
|
}
|
|
}
|
|
$sender->teleport(\pocketmine\level\Position::fromObject($sender, $this->getServer()->getLevelByName($args[0])));
|
|
$sender->sendMessage("§aTeleporting to {$args[0]}...");
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
break;
|
|
case 'temple':{
|
|
if($sender instanceof ConsoleCommandSender) return false;
|
|
/** @var Player $sender */
|
|
$temple = new Temple();
|
|
$temple->placeObject($sender->getLevel(), $sender->x, $sender->y, $sender->z, new Random(microtime()));
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Generates a (semi) random seed.
|
|
* @return int
|
|
*/
|
|
public function generateRandomSeed(): int {
|
|
return (int)round(rand(0, round(time()) / memory_get_usage(true)) * (int)str_shuffle("127469453645108") / (int)str_shuffle("12746945364"));
|
|
}
|
|
|
|
/**
|
|
* Registers a forest from a tree class
|
|
*
|
|
* @param string $name
|
|
* @param string $treeClass
|
|
* @param array $infos
|
|
* @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);
|
|
}
|
|
|
|
|
|
/**
|
|
* Checks when a chunk populates to populate chests back
|
|
*
|
|
* @param ChunkPopulateEvent $event
|
|
* @return void
|
|
*/
|
|
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 touches an ungenerated chest to generate it.
|
|
*
|
|
* @param PlayerInteractEvent $event
|
|
* @return void
|
|
*/
|
|
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;
|
|
$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)
|
|
]);
|
|
/** @var Chest $chest */
|
|
$chest = Tile::createTile(Tile::CHEST, $event->getBlock()->getLevel(), $nbt);
|
|
$chest->setName("§k(Fake)§r Minecart chest");
|
|
LootTable::fillChest($chest->getInventory(), $event->getBlock());
|
|
}
|
|
|
|
/**
|
|
* Checks when a players breaks an ungenerated chest to generate it.
|
|
*
|
|
* @param BlockBreakEvent $event
|
|
* @return void
|
|
*/
|
|
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;
|
|
$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)
|
|
]);
|
|
/** @var Chest $chest */
|
|
$chest = Tile::createTile(Tile::CHEST, $event->getBlock()->getLevel(), $nbt);
|
|
$chest->setName("§k(Fake)§r Minecart chest");
|
|
LootTable::fillChest($chest->getInventory(), $event->getBlock());
|
|
}
|
|
}
|