2017-04-23 14:42:51 +00:00
< ? php
2017-05-10 15:03:04 +00:00
/**
2017-05-12 07:01:46 +00:00
* ____ __ __ ____
* / \ _ `\ /\ \__ /\ \__ /\ _` \
* \ \ \L\ \ __ \ \ , _\\ \ , _\ __ _ __ \ \ \L\_\ __ ___
* \ \ _ < ' /' __ `\\ \ \/ \ \ \/ /'__` \ / \ `'__\\ \ \L_L /'__` \ / ' _ ` \
* \ \ \L\ \ / \ __ / \ \ \_ \ \ \_ / \ __ / \ \ \ / \ \ \ / , \ / \ __ / / \ \ / \ \
2017-05-10 15:03:04 +00:00
* \ \____ / \ \____\ \ \__\ \ \__\\ \____\\ \_\ \ \____ / \ \____\\ \_\ \_\
* \ / ___ / \ / ____ / \ / __ / \ / __ / \ / ____ / \ / _ / \ / ___ / \ / ____ / \ / _ / \ / _ /
2017-05-11 11:29:22 +00:00
* Tomorrow ' s pocketmine generator .
2017-05-10 15:03:04 +00:00
* @ author Ad5001
* @ link https :// github . com / Ad5001 / BetterGen
2017-04-23 14:42:51 +00:00
*/
namespace Ad5001\BetterGen ;
use Ad5001\BetterGen\biome\BetterForest ;
2017-05-11 12:07:26 +00:00
use Ad5001\BetterGen\generator\BetterNormal ;
2017-04-23 14:42:51 +00:00
use Ad5001\BetterGen\loot\LootTable ;
2017-05-14 05:58:25 +00:00
use Ad5001\BetterGen\structure\FallenTree ;
use Ad5001\BetterGen\structure\Igloo ;
use Ad5001\BetterGen\structure\SakuraTree ;
2017-05-12 07:01:46 +00:00
use Ad5001\BetterGen\structure\Temple ;
2017-05-14 05:58:25 +00:00
use Ad5001\BetterGen\structure\Well ;
2017-04-23 14:42:51 +00:00
use pocketmine\block\Block ;
2017-05-14 09:32:58 +00:00
use pocketmine\block\Chest ;
2017-05-11 11:29:22 +00:00
use pocketmine\command\Command ;
use pocketmine\command\CommandSender ;
2017-05-11 12:07:26 +00:00
use pocketmine\event\block\BlockBreakEvent ;
2017-05-11 11:29:22 +00:00
use pocketmine\event\Listener ;
2017-05-11 12:07:26 +00:00
use pocketmine\event\player\PlayerInteractEvent ;
2017-05-14 09:32:58 +00:00
use pocketmine\item\Item ;
2017-04-23 14:42:51 +00:00
use pocketmine\level\generator\biome\Biome ;
use pocketmine\level\generator\Generator ;
2017-05-14 05:58:25 +00:00
use pocketmine\level\generator\object\OakTree ;
use pocketmine\level\Position ;
2017-04-23 14:42:51 +00:00
use pocketmine\nbt\tag\CompoundTag ;
2017-05-11 12:07:26 +00:00
use pocketmine\nbt\tag\IntTag ;
2017-04-23 14:42:51 +00:00
use pocketmine\nbt\tag\StringTag ;
2017-05-12 07:01:46 +00:00
use pocketmine\Player ;
2017-05-11 12:07:26 +00:00
use pocketmine\plugin\PluginBase ;
2017-05-14 05:58:25 +00:00
use pocketmine\tile\Chest as TileChest ;
2017-04-23 14:42:51 +00:00
use pocketmine\tile\Tile ;
2017-05-11 12:07:26 +00:00
use pocketmine\utils\Config ;
2017-05-12 07:01:46 +00:00
use pocketmine\utils\Random ;
2017-05-14 05:58:25 +00:00
use pocketmine\utils\TextFormat ;
2017-04-23 14:42:51 +00:00
2017-05-11 11:29:22 +00:00
class Main extends PluginBase implements Listener {
2017-04-23 14:42:51 +00:00
const PREFIX = " §l§o§b[§r§l§2Better§aGen§o§b]§r§f " ;
const SAKURA_FOREST = 100 ; // Letting some place for future biomes.
2017-05-14 09:32:58 +00:00
private static $instance ;
2017-05-12 07:01:46 +00:00
2017-05-14 05:58:25 +00:00
/**
* 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
*/
2017-05-12 07:01:46 +00:00
public static function registerBiome ( int $id , Biome $biome ) {
BetterNormal :: registerBiome ( $biome );
2017-04-23 14:42:51 +00:00
}
2017-05-12 07:01:46 +00:00
2017-05-14 09:32:58 +00:00
/**
* Places a looting chest block and creates the corresponding tile
* @ param Block $block
* @ param $lootfile
*/
static public function placeLootChest ( Block $block , $lootfile ) {
$block -> 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 ();
}
2017-05-14 05:58:25 +00:00
/**
* Called when the plugin enables
2017-04-23 14:42:51 +00:00
*/
2017-05-12 07:01:46 +00:00
public function onEnable () {
2017-05-14 09:32:58 +00:00
self :: $instance = $this ;
2017-05-12 07:01:46 +00:00
$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 ());
2017-05-16 10:02:29 +00:00
@ 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' );
2017-04-23 14:42:51 +00:00
}
2017-05-12 07:01:46 +00:00
2017-05-14 05:58:25 +00:00
/**
* Check if it ' s a Tesseract like namespace
2017-05-14 09:32:58 +00:00
* @ return bool
2017-04-23 14:42:51 +00:00
*/
2017-05-12 07:01:46 +00:00
public static function isOtherNS () {
try {
return @ class_exists ( " pocketmine \\ level \\ generator \\ normal \\ object \\ OakTree " );
} catch ( \Exception $e ) {
return false ;
}
}
2017-05-14 05:58:25 +00:00
/**
* Called when the plugin disables
*/
2017-05-12 07:01:46 +00:00
public function onDisable () {
}
2017-05-14 05:58:25 +00:00
/**
* 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
*/
2017-05-11 11:29:22 +00:00
public function onCommand ( CommandSender $sender , Command $cmd , $label , array $args ) : bool {
2017-05-12 07:01:46 +00:00
switch ( $cmd -> getName ()) {
2017-05-13 15:03:26 +00:00
case " createworld " : // /createworld <name> [generator = betternormal] [seed = rand()] [options(json)]
2017-05-12 07:01:46 +00:00
switch ( count ( $args )) {
2017-04-23 14:42:51 +00:00
case 0 :
return false ;
break ;
case 1 : // /createworld <name>
2017-05-13 21:42:44 +00:00
$name = $args [ 0 ];
2017-04-23 14:42:51 +00:00
$generator = Generator :: getGenerator ( " betternormal " );
$generatorName = " betternormal " ;
$seed = $this -> generateRandomSeed ();
2017-05-12 07:01:46 +00:00
$options = [];
2017-04-23 14:42:51 +00:00
break ;
case 2 : // /createworld <name> [generator = betternormal]
2017-05-13 21:42:44 +00:00
$name = $args [ 0 ];
$generator = Generator :: getGenerator ( $args [ 1 ]);
if ( Generator :: getGeneratorName ( $generator ) !== strtolower ( $args [ 1 ])) {
2017-04-23 14:42:51 +00:00
$sender -> sendMessage ( self :: PREFIX . " §4Could not find generator { $args [ 1 ] } . Are you sure it is registered? " );
return true ;
}
2017-05-13 21:42:44 +00:00
$generatorName = strtolower ( $args [ 1 ]);
2017-04-23 14:42:51 +00:00
$seed = $this -> generateRandomSeed ();
2017-05-12 07:01:46 +00:00
$options = [];
2017-04-23 14:42:51 +00:00
break ;
case 3 : // /createworld <name> [generator = betternormal] [seed = rand()]
2017-05-13 21:42:44 +00:00
$name = $args [ 0 ];
$generator = Generator :: getGenerator ( $args [ 1 ]);
if ( Generator :: getGeneratorName ( $generator ) !== strtolower ( $args [ 1 ])) {
2017-04-23 14:42:51 +00:00
$sender -> sendMessage ( self :: PREFIX . " §4Could not find generator { $args [ 1 ] } . Are you sure it is registered? " );
return true ;
}
2017-05-13 21:42:44 +00:00
$generatorName = strtolower ( $args [ 1 ]);
if ( preg_match ( " [^ \ d] " , $args [ 2 ]) !== false ) {
$parts = str_split ( $args [ 2 ]);
2017-05-12 07:01:46 +00:00
foreach ( $parts as $key => $str ) {
2017-05-13 21:42:44 +00:00
$parts [ $key ] = ord ( $str );
2017-04-23 14:42:51 +00:00
}
$seed = implode ( " " , $parts );
} else {
2017-05-13 21:42:44 +00:00
$seed = $args [ 2 ];
2017-04-23 14:42:51 +00:00
}
2017-05-12 07:01:46 +00:00
$options = [];
2017-04-23 14:42:51 +00:00
break ;
default : // /createworld <name> [generator = betternormal] [seed = rand()] [options(json)]
2017-05-13 21:42:44 +00:00
$name = $args [ 0 ];
$generator = Generator :: getGenerator ( $args [ 1 ]);
if ( Generator :: getGeneratorName ( $generator ) !== strtolower ( $args [ 1 ])) {
2017-04-23 14:42:51 +00:00
$sender -> sendMessage ( self :: PREFIX . " §4Could not find generator { $args [ 1 ] } . Are you sure it is registered? " );
return true ;
}
2017-05-13 21:42:44 +00:00
$generatorName = strtolower ( $args [ 1 ]);
2017-05-12 07:01:46 +00:00
if ( $args [ 2 ] == " rand " ) $args [ 2 ] = $this -> generateRandomSeed ();
2017-05-13 21:42:44 +00:00
if ( preg_match ( " [^ \ d] " , $args [ 2 ]) !== false ) {
$parts = str_split ( $args [ 2 ]);
2017-05-12 07:01:46 +00:00
foreach ( $parts as $key => $str ) {
2017-05-13 21:42:44 +00:00
$parts [ $key ] = ord ( $str );
2017-04-23 14:42:51 +00:00
}
$seed = implode ( " " , $parts );
} else {
2017-05-13 21:42:44 +00:00
$seed = $args [ 2 ];
2017-04-23 14:42:51 +00:00
}
2017-05-13 21:42:44 +00:00
unset ( $args [ 0 ], $args [ 1 ], $args [ 2 ]);
$options = json_decode ( $args [ 3 ], true );
2017-05-12 07:01:46 +00:00
if ( ! is_array ( $options )) {
2017-04-23 14:42:51 +00:00
$sender -> sendMessage ( Main :: PREFIX . " §4Invalid JSON for options. " );
return true ;
}
break ;
}
2017-05-10 15:03:04 +00:00
$options [ " preset " ] = json_encode ( $options );
2017-05-12 07:01:46 +00:00
if (( int ) $seed == 0 /*String*/ ) {
2017-05-10 15:03:04 +00:00
$seed = $this -> generateRandomSeed ();
}
2017-04-23 14:42:51 +00:00
$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 ;
2017-05-13 15:03:26 +00:00
case " worldtp " :
2017-05-14 05:58:25 +00:00
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 ]))) {
2017-05-13 14:43:07 +00:00
$this -> getServer () -> loadLevel ( $args [ 0 ]);
2017-05-14 05:58:25 +00:00
if ( is_null ( $this -> getServer () -> getLevelByName ( $args [ 0 ]))) {
2017-05-13 14:43:07 +00:00
$sender -> sendMessage ( " Could not find level { $args [ 0 ] } . " );
return false ;
}
}
2017-05-14 05:58:25 +00:00
$sender -> teleport ( Position :: fromObject ( $sender , $this -> getServer () -> getLevelByName ( $args [ 0 ])));
2017-05-13 14:43:07 +00:00
$sender -> sendMessage ( " §aTeleporting to { $args [ 0 ] } ... " );
return true ;
} else {
return false ;
}
break ;
2017-05-14 05:58:25 +00:00
case 'structure' : {
if ( ! $sender instanceof Player ) {
$sender -> sendMessage ( TextFormat :: RED . 'You can\'t use this command' );
return true ;
}
2017-05-12 07:01:46 +00:00
/** @var Player $sender */
2017-05-14 05:58:25 +00:00
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' ]));
2017-05-12 07:01:46 +00:00
return true ;
}
2017-04-23 14:42:51 +00:00
}
2017-05-11 11:29:22 +00:00
return false ;
2017-04-23 14:42:51 +00:00
}
2017-05-12 07:01:46 +00:00
2017-05-14 05:58:25 +00:00
/**
2017-04-23 14:42:51 +00:00
* Generates a ( semi ) random seed .
* @ return int
*/
public function generateRandomSeed () : int {
2017-05-12 07:01:46 +00:00
return ( int ) round ( rand ( 0 , round ( time ()) / memory_get_usage ( true )) * ( int ) str_shuffle ( " 127469453645108 " ) / ( int ) str_shuffle ( " 12746945364 " ));
2017-04-23 14:42:51 +00:00
}
2017-05-12 07:01:46 +00:00
2017-05-14 05:58:25 +00:00
/**
* Registers a forest type .
* @ param $name string
* @ param $treeClass string
2017-05-14 09:32:58 +00:00
* @ param array $infos
2017-05-14 05:58:25 +00:00
* @ return bool
2017-05-14 09:32:58 +00:00
* @ params $infos Array ( temperature , rainfall )
2017-04-23 14:42:51 +00:00
*/
2017-05-12 07:01:46 +00:00
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 ;
2017-05-13 21:42:44 +00:00
if ( count ( $infos ) < 2 or ! is_float ( $infos [ 0 ]) or ! is_float ( $infos [ 1 ]))
2017-05-12 07:01:46 +00:00
return false ;
return BetterForest :: registerForest ( $name , $treeClass , $infos );
}
2017-05-14 05:58:25 +00:00
/**
* Checks when a player attempts to open a loot chest which is not created yet
* @ param PlayerInteractEvent $event
2017-05-12 07:01:46 +00:00
*/
2017-05-14 05:58:25 +00:00
public function onInteract ( PlayerInteractEvent $event ) {
2017-05-14 09:32:58 +00:00
if (( $block = $event -> getBlock ()) -> getId () !== Block :: CHEST || $event -> getAction () !== PlayerInteractEvent :: RIGHT_CLICK_BLOCK ) return ;
2017-05-14 05:58:25 +00:00
$this -> generateLootChest ( $block );
2017-04-23 14:42:51 +00:00
}
2017-05-12 07:01:46 +00:00
2017-05-14 09:32:58 +00:00
/**
* 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 ;
2017-05-16 10:02:29 +00:00
$table = new LootTable ( $config = new Config ( self :: getInstance () -> getDataFolder () . 'addon\\' . $tile -> namedtag -> generateLoot . '.json' , Config :: DETECT , []));
2017-05-14 09:32:58 +00:00
$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 ;
}
2017-05-14 05:58:25 +00:00
/**
* Checks when a player breaks a loot chest which is not created yet
* @ param BlockBreakEvent $event
2017-04-23 14:42:51 +00:00
*/
2017-05-14 05:58:25 +00:00
public function onBlockBreak ( BlockBreakEvent $event ) {
if (( $block = $event -> getBlock ()) -> getId () !== Block :: CHEST ) return ;
$this -> generateLootChest ( $block );
2017-04-23 14:42:51 +00:00
}
2017-05-08 13:59:19 +00:00
}