getLevel()->setBlock($block, $block, true); $nbt = new CompoundTag("", [ new StringTag("id", Tile::CHEST), new IntTag("x", (int)$block->x), new IntTag("y", (int)$block->y), new IntTag("z", (int)$block->z), new StringTag("generateLoot", $lootfile) ]); $tile = new TileChest($block->getLevel(), $nbt); $tile->spawnToAll(); } /** * Called when the plugin enables */ public function onEnable() { self::$instance = $this; $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($this->getDataFolder()); @mkdir($this->getDataFolder() . 'addon'); if ((($files = @scandir($this->getDataFolder() . 'addon')) && count($files) <= 2)) $this->getLogger()->alert('The loot files are missing, this means no loot will generate! You can get them here: https://aka.ms/behaviorpacktemplate or here https://github.com/dktapps/mcpe-default-addon for an optimised version'); } /** * Check if it's a Tesseract like namespace * @return bool */ public static function isOtherNS() { try { return @class_exists("pocketmine\\level\\generator\\normal\\object\\OakTree"); } catch (\Exception $e) { return false; } } /** * 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(CommandSender $sender, Command $cmd, $label, array $args): bool { switch ($cmd->getName()) { case "createworld": // /createworld [generator = betternormal] [seed = rand()] [options(json)] switch (count($args)) { case 0 : return false; break; case 1 : // /createworld $name = $args[0]; $generator = Generator::getGenerator("betternormal"); $generatorName = "betternormal"; $seed = $this->generateRandomSeed(); $options = []; break; case 2 : // /createworld [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 [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 [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(); 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($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 (!$sender instanceof Player) { $sender->sendMessage(TextFormat::RED . 'You can\'t use this command'); return true; } /** @var Player $sender */ 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(Position::fromObject($sender, $this->getServer()->getLevelByName($args[0]))); $sender->sendMessage("§aTeleporting to {$args[0]}..."); return true; } else { return false; } break; case 'structure': { if (!$sender instanceof Player) { $sender->sendMessage(TextFormat::RED . 'You can\'t use this command'); return true; } /** @var Player $sender */ if (isset($args[0])) { switch ($args[0]) { case 'temple': { $temple = new Temple(); $temple->placeObject($sender->getLevel(), $sender->x, $sender->y, $sender->z, new Random(microtime())); return true; } break; case 'fallen': { $temple = new FallenTree(new OakTree()); $temple->placeObject($sender->getLevel(), $sender->x, $sender->y, $sender->z); return true; } break; case 'igloo': { $temple = new Igloo(); $temple->placeObject($sender->getLevel(), $sender->x, $sender->y, $sender->z, new Random(microtime())); return true; } break; case 'well': { $temple = new Well(); $temple->placeObject($sender->getLevel(), $sender->x, $sender->y, $sender->z, new Random(microtime())); return true; } break; case 'sakura': { $temple = new SakuraTree(); $temple->placeObject($sender->getLevel(), $sender->x, $sender->y, $sender->z, new Random(microtime())); return true; } break; default: { } } } $sender->sendMessage(implode(', ', ['temple', 'fallen', 'igloo', 'well', 'sakura'])); 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 type. * @param $name string * @param $treeClass string * @param array $infos * @return bool * @params $infos Array(temperature, rainfall) */ 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 player attempts to open a loot chest which is not created yet * @param PlayerInteractEvent $event */ public function onInteract(PlayerInteractEvent $event) { if (($block = $event->getBlock())->getId() !== Block::CHEST || $event->getAction() !== PlayerInteractEvent::RIGHT_CLICK_BLOCK) return; $this->generateLootChest($block); } /** * Fills a chest with loot * @param Block $block * @param Random|null $random */ static public function generateLootChest(Block $block, Random $random = null) { if (!$block instanceof Chest) return; $tile = $block->getLevel()->getTile($block); if (is_null($tile)) { //TODO new tile, but no loot, because we don't know which type of loot chest this is $nbt = new CompoundTag("", [ new StringTag("id", Tile::CHEST), new IntTag("x", (int)$block->x), new IntTag("y", (int)$block->y), new IntTag("z", (int)$block->z) ]); $tile = new TileChest($block->getLevel(), $nbt); $tile->spawnToAll(); return; } if (!$tile instanceof TileChest) return; //Check if lootchest (or already generated loot) if (!isset($tile->namedtag->generateLoot)) return; $table = new LootTable($config = new Config(self::getInstance()->getDataFolder() . 'addon\\' . $tile->namedtag->generateLoot . '.json', Config::DETECT, [])); $size = $tile->getInventory()->getSize(); $loot = $table->getRandomLoot($random); $items = array_pad($loot, $size, Item::get(0)); shuffle($items); $tile->getInventory()->setContents($items); unset($tile->namedtag->generateLoot); } /** * @return Main */ static public function getInstance() { return self::$instance; } /** * Checks when a player breaks a loot chest which is not created yet * @param BlockBreakEvent $event */ public function onBlockBreak(BlockBreakEvent $event) { if (($block = $event->getBlock())->getId() !== Block::CHEST) return; $this->generateLootChest($block); } }