Advertisement
PsyOps

BlockOps.Main

Jul 16th, 2017
439
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 15.65 KB | None | 0 0
  1. <?php
  2.     /*
  3.                      _____ _         _   _____        
  4.                     | __  | |___ ___| |_|     |___ ___
  5.                     | __ -| | . |  _| '_|  |  | . |_ -|   BlockOps
  6.                     |_____|_|___|___|_,_|_____|  _|___|   aka: Block Operations
  7.                                               |_|      
  8.         Written by:     PsyOps
  9.         Description:    Copy the current Minecraft PE commands - /setblock /fill /clone
  10.        
  11.         SETBLOCK
  12.         ----------------------------------------------------------------------------------------------------------------------------
  13.         /setblock <position: x y z> <tileName: string> [tileData: int] [oldBlockHandling]
  14.         ----------------------------------------------------------------------------------------------------------------------------
  15.         -- oldBlockHandling ---
  16.         *   destroy – Destroys the original block as if done by The Player, before placing the new block
  17.         *   keep – Only replaces air blocks with the new block
  18.         *   replace – Replaces without regards of old block. No dropping of block or content. This is the default
  19.    
  20.         FILL
  21.         ----------------------------------------------------------------------------------------------------------------------------
  22.         /fill <from: x y z> <to: x y z> <tileName: string> [tileData:int] [oldBlockHandling]
  23.         ----------------------------------------------------------------------------------------------------------------------------
  24.         -- oldBlockHandling ---
  25.         *   destroy – Replace all blocks, drops blocks and contents as if mined with unenchanted diamond pickaxe or shovel.
  26.         *   hollow – Replace only the blocks on the outer edge of the region. Drops all inner blocks as if they were mined, and replaced them with air blocks.
  27.         *   keep – Only replace the air blocks in the fill region with the specified block.
  28.         *   outline – Only replace the outer edge of region with specified block. Leave all inner blocks as they were.
  29.         *   replace – Replace all blocks, with no dropping of current blocks. This is the default.
  30.        
  31.         Clone
  32.         ----------------------------------------------------------------------------------------------------------------------------
  33.         command:  /clone <begin x y z> <end x y z> <destination: x y z> [maskMode] [cloneMode] <tileName: string> [tileData:int]
  34.         ----------------------------------------------------------------------------------------------------------------------------
  35.         -- Legal values for maskMode are:
  36.         *   filtered – Only blocks matching tileName is copied.
  37.         *   masked – Only non-air blocks are copied.
  38.         *   replace – All blocks are copied as-is. This is the default.
  39.  
  40.         -- Legal values for cloneMode are:
  41.         *   force – Force moving of blocks even if regions overlap.
  42.         *   move – Move only non-air blocks, and replace them with air-blocks. If filtering is done, this only applies to the filtered blocks.
  43.         *   normal – Do not force or move blocks from source region. This is the default.
  44.     */
  45. namespace S8Plugin\BlockOps;
  46.  
  47. use pocketmine\command\CommandSender;
  48. use pocketmine\command\Command;
  49. use pocketmine\plugin\PluginBase;
  50. use pocketmine\Server;
  51. use pocketmine\Player;
  52. use pocketmine\block\Block;
  53. use pocketmine\item\Item;
  54. use pocketmine\math\Vector3;
  55.  
  56. use pocketmine\tile\Sign;
  57. use pocketmine\nbt\NBT;
  58. use pocketmine\nbt\tag\StringTag;
  59. use pocketmine\nbt\tag\CompoundTag;
  60. use pocketmine\nbt\tag\ListTag;
  61. use pocketmine\nbt\tag\IntTag;
  62. use pocketmine\tile\Tile;
  63. use pocketmine\tile\Chest;
  64. use pocketmine\level\Position;
  65.  
  66. class Main extends PluginBase {
  67.    
  68.     public function onEnable() {
  69.         $this->saveDefaultConfig();
  70.     }
  71.    
  72.     /*    ___                              _    
  73.          / __|___ _ __  _ __  __ _ _ _  __| |___
  74.         | (__/ _ \ '  \| '  \/ _` | ' \/ _` (_-<
  75.          \___\___/_|_|_|_|_|_\__,_|_||_\__,_/__/  - Commands
  76.     --------------------------------------------------------------------------------------------------------------- */
  77.     // Command handler
  78.     public function onCommand(CommandSender $sender, Command $cmd, $label, array $args) {
  79.         switch($cmd->getName()) {
  80.             case "setblock":
  81.                 $this->doSetblock($sender, $args);
  82.                 break;
  83.             case "fill":
  84.                 $this->doFill($sender, $args);
  85.                 break;
  86.             case "clone":
  87.                 $this->doClone($sender, $args);
  88.                 break;
  89.             case "test":
  90.                 $this->doTest($sender, $args);
  91.                 break;
  92.         }
  93.     }
  94.    
  95.     // I use this for my own testing
  96.     private function doTest(CommandSender $sender, array $args){
  97.         if(!$sender->hasPermission("test")) return;
  98.             /*      Code to test here      */
  99.         $sender->sendMessage("§cTest Fail!");
  100.         //$tile = $sender->getLevel()->getTile(new Vector3($x,$y,$z));
  101.     }
  102.    
  103.     //
  104.     private function doClone(CommandSender $sender, array $args){
  105.         // Check for permission
  106.         if(!$sender->hasPermission("clone")) return;
  107.        
  108.         // Make sure command is formatted right
  109.         if ( $this->areValidCoords( $sender, $args, 9 ) ){
  110.             $this->printRegion($sender, false, $args);
  111.             return;
  112.         }
  113.         $sender->sendMessage("§cUsage: /clone <begin x y z> <end x y z> <destination: x y z> [maskMode] [cloneMode] [tileName]");
  114.     }
  115.     private function doFill(CommandSender $sender, array $args){
  116.         // Check for permission
  117.         if(!$sender->hasPermission("fill")) return;
  118.            
  119.         // Make sure command is formatted right
  120.         if ( $this->areValidCoords( $sender, $args, 6 ) && isset($args[6])){
  121.             $this->printRegion($sender, true, $args);
  122.             return;
  123.         }
  124.         // Code will get here only if command is not formated right
  125.         $sender->sendMessage("§cUsage: /fill <from: x y z> <to: x y z> <tileName: string> [tileData:int] [oldBlockHandling]");
  126.     }
  127.     private function doSetblock(CommandSender $sender, array $args){
  128.         // Check for permission
  129.         if(!$sender->hasPermission("setblock")) return;
  130.  
  131.         // Make sure command is formatted right
  132.         if ( $this->areValidCoords( $sender , $args, 3 ) && isset($args[3]) ) {
  133.  
  134.             $this->printBlock($sender, $args[0], $args[1], $args[2], $args[3], isset($args[4]) ? $args[4] : 0, isset($args[5]) ? $args[5] : 'r');
  135.             return;
  136.         }
  137.         // Code will get here only if command is not formated right
  138.         $sender->sendMessage("§cUsage: /setblock <position: x y z> <tileName: string> [tileData: int] [oldBlockHandling]");
  139.     }
  140.    
  141.     /*   ___     _     _  
  142.         | _ \_ _(_)_ _| |_
  143.         |  _/ '_| | ' \  _|
  144.         |_| |_| |_|_||_\__|  - Print
  145.     --------------------------------------------------------------------------------------------------------------- */
  146.     // Main function to print out more than one block at a time
  147.     private function printRegion(CommandSender $sender, $fill, array $args){
  148.        
  149.         // Clone
  150.         if (!$fill){
  151.             // First Check for clone
  152.             // Safety check to make sure origin and destination dont overlap - cloneMode override here too
  153.             if ($this->regionsCollide($args)){
  154.                 if (!isset($args[10]) || ( $args[10] != "force" && $args[10] != "f" )) {
  155.                     $sender->sendMessage("§cCopy region and Clone region collide. Command ignored.");
  156.                     $sender->sendMessage("§cUsage: /clone <begin x y z> <end x y z> <destination: x y z> [maskMode] [cloneMode] [tileName]");
  157.                     return;
  158.                 }
  159.             }
  160.         }
  161.  
  162.         $specialObjects = [];
  163.        
  164.         // Loop through region
  165.         for ($printZ = $args[2]; $printZ <= $args[5]; $printZ++){
  166.             for ($printY = $args[1]; $printY <= $args[4]; $printY++){
  167.                 for ($printX = $args[0]; $printX <= $args[3]; $printX++){
  168.                    
  169.                     $allow = true;
  170.  
  171.                     // Fill
  172.                     if ( $fill ) {
  173.                         // Set the OldBlockHandle
  174.                         $printOldBlockHandle =  isset($args[8]) ? $args[8] : 'r';
  175.                        
  176.                         // Checking OldBlockHandle :Outline - if it is not part of edge do not print
  177.                         if ( $printOldBlockHandle == "outline" || $printOldBlockHandle == "o" && !$this->isOuterEdge($args,$printX,$printY,$printZ) ) $allow = false;
  178.                         // Checking OldBlockHandle :Hollow - if it is not part of edge send air block
  179.                         elseif ( $printOldBlockHandle == "hollow" || $printOldBlockHandle == "h" && !$this->isOuterEdge($args,$printX,$printY,$printZ) ) $printBlock = 'air';
  180.                         // if part of edge print normal
  181.                         else $printBlock = $args[6];
  182.                        
  183.                         // Update meta
  184.                         $printMeta = isset($args[7]) ? $args[7] : '';
  185.                     }
  186.                     // Clone
  187.                     else {
  188.                         // Set the maskMode to replace if it isnt set - default
  189.                         $printOldBlockHandle =  isset($args[9]) ? $args[9] : 'r';
  190.  
  191.                         // Saving Old block to send it out to new spot
  192.                         $oldBlockobj = $sender->getLevel()->getBlock(new Vector3($printX, $printY, $printZ));
  193.                         $printBlock = $oldBlockobj->getId();
  194.                        
  195.                         // Update meta with old block damage
  196.                         $printMeta = $oldBlockobj->getDamage();
  197.                        
  198.                         /* ------------------------------ Clone Mode ------------------------------ */
  199.                         // Checking cloneMode : Move
  200.                         if (isset($args[10])) {
  201.                             if ( $args[10] == "move" || $args[10] == "m" ){
  202.                                 // is it air block
  203.                                 if ($printBlock != 0 ){
  204.                                     // Delete old block if it isnt air
  205.                                     $this->printBlock($sender, $printX, $printY, $printZ, 0, 0, 'r');
  206.                                 }
  207.                             }
  208.                         }
  209.                         /* ------------------------------ Mask Mode ------------------------------ */
  210.                         // Checking maskMode : Masked
  211.                         if ( $printOldBlockHandle == "masked" || $printOldBlockHandle == "m" ) $allow = $printBlock != 0;
  212.                         // Checking maskMode : Filtered
  213.                         elseif ( $printOldBlockHandle == "filtered" || $printOldBlockHandle == "f" ){
  214.                             // Check to see that tiledata was sent
  215.                             if ( isset($args[11])){
  216.                                
  217.                                 // Grab the block to compare for filter
  218.                                 $filterMeta = isset($args[12]) ? $args[12] : 0;
  219.                                 $filterBlock = is_numeric($args[11]) ? Block::get((int)$args[11], $filterMeta) : Block::get((Item::fromString($args[11])->getBlock())->getId(), $filterMeta) ;
  220.                                 $filterBlockId = $filterBlock->getId();
  221.                                
  222.                                 // Only pass along blocks that match filter
  223.                                 $allow = (int)$printBlock === (int)$filterBlockId;
  224.                             }
  225.                         }
  226.                        
  227.                         // Special block check here - Chests and Signs so far
  228.                         if (($allow) && ($printBlock == 63 || $printBlock == 68 || $printBlock == 54 )){
  229.                             $specialObjects[] = array(
  230.                                 'x'=> $args[6] + ($printX - $args[0]),
  231.                                 'y' => $args[7] + ($printY - $args[1]),
  232.                                 'z' => $args[8] + ($printZ - $args[2]),
  233.                                 'id' => $printBlock,
  234.                                 'meta' => $printBlock,
  235.                                 'obh' => $printOldBlockHandle,
  236.                                 'tile' => $sender->getLevel()->getTile(new Vector3($printX,$printY,$printZ)) );
  237.                             // Don't print tile now- hold it for later
  238.                             $allow = false;
  239.                         }
  240.                     }
  241.                    
  242.                     // print block
  243.                     if ($allow) $this->printBlock($sender, $fill ? $printX : $args[6] + ($printX - $args[0]) , $fill ? $printY : $args[7] + ($printY - $args[1]) ,  $fill ? $printZ : $args[8] + ($printZ - $args[2]) , $printBlock, $printMeta, $printOldBlockHandle);
  244.                 }
  245.             }
  246.         }
  247.         // Print special tiles here - My guess is if the tile is attached to another block , block should be placed first
  248.         if (is_array($specialObjects)){
  249.             foreach($specialObjects as $b) {
  250.                 $sender->getLevel()->setBlock(new Vector3($b['x'], $b['y'], $b['z']), Block::get($b['id']));
  251.                
  252.                 // Signs
  253.                 if ($b['id'] == 63 || $b['id'] == 68 || $b['id'] == 54 ){
  254.                    
  255.                     // Setup nbt tag
  256.                     $nbt = new CompoundTag("", [
  257.                     new ListTag("Items", [] ),
  258.                     new StringTag("id", $b['id'] == 54 ? Tile::CHEST :Tile::SIGN),
  259.                     new IntTag("x", $b['x']),
  260.                     new IntTag("y", $b['y']),
  261.                     new IntTag("z", $b['z']) ]);
  262.                     $nbt->Items->setTagType(NBT::TAG_Compound);
  263.                    
  264.                     // Create tile
  265.                     $tile = Tile::createTile( $b['id'] == 54 ? Tile::CHEST :Tile::SIGN, $sender->getLevel(), $nbt);
  266.                     if (isset($tile)){
  267.                         // Copy over text from old sign
  268.                         if( $b['id'] == 63 || $b['id'] == 68 ){
  269.                             $tile->setText($b['tile']->getText()[0], $b['tile']->getText()[1], $b['tile']->getText()[2], $b['tile']->getText()[3]);
  270.                         }
  271.                         // Put copied items into new chest
  272.                         elseif ( $b['id'] == 54 ){
  273.                             $tile->getInventory()->setContents($b['tile']->getInventory()->getContents());
  274.                         }
  275.                     }
  276.                     else $sender->sendMessage("§cTile not picked up!");             
  277.                 }
  278.             }
  279.         }          
  280.     }
  281.     // Single block print
  282.     private function printBlock(CommandSender $sender, $x, $y, $z, $block, $meta, $oldBlockHandle){
  283.         // set meta
  284.         $meta = isset($meta) ? $meta : 0;
  285.        
  286.         // Set as:  old block = air block - it only gets changed if "Keep" is selected
  287.         // for old block handeling
  288.         $isAir = true;
  289.        
  290.         // How to handle the Old Block being replaced
  291.         if (isset($oldBlockHandle)) {
  292.             if ( $oldBlockHandle == "destroy" || $oldBlockHandle == "d" ){
  293.                 $item = null;
  294.                 $sender->getLevel()->useBreakOn(new Vector3($x, $y, $z), $item, $sender, true);
  295.             }
  296.             elseif ( $oldBlockHandle == "keep" || $oldBlockHandle == "k" ){
  297.                 // Add air block check
  298.                 $isAir = $sender->getLevel()->getBlock(new Vector3($x, $y, $z))->getId() == 0;
  299.             }
  300.          }
  301.        
  302.         if ($isAir){
  303.             // Grab block obj
  304.             $blockobj = is_numeric($block) ? Block::get((int)$block, $meta) : Block::get((Item::fromString($block)->getBlock())->getId(), $meta);
  305.             // send the command
  306.             $sender->getLevel()->setBlock(new Vector3($x, $y, $z), $blockobj, true, true);
  307.         }
  308.     }
  309.    
  310.     /*   __  __ _          ___            
  311.         |  \/  (_)___ __  | __|  _ _ _  __
  312.         | |\/| | (_-</ _| | _| || | ' \/ _|
  313.         |_|  |_|_/__/\__| |_| \_,_|_||_\__|  - Misc Functions
  314.     --------------------------------------------------------------------------------------------------------------- */
  315.     // Function to make sure that our copyto region doesnt overlap on the cloneregion
  316.     private function regionsCollide(array $args){
  317.         // Region to clone: Clone region
  318.         $x = $args[0];      $y = $args[1];      $z = $args[2];
  319.         $x2 = $args[3];     $y2 = $args[4];     $z2 = $args[5];
  320.         // Region to copy to: CopyTo Region
  321.         $newX = $args[6];                   $newY = $args[7];                   $newZ = $args[8];
  322.         $newX2 = $newX + ( $x2 - $x );      $newY2 = $newY + ( $y2 - $y );      $newZ2 = $newZ + ( $z2 - $z );
  323.                
  324.          if (  $newX > $x2 || $newX2 < $x ) {  return false; }    
  325.          else if (  $newY > $y2 || $newY2 < $y ) {  return false; }  
  326.          else if (  $newZ > $z2 || $newZ2 < $z ) {  return false; }  
  327.          
  328.          return true;
  329.     }
  330.     private function isOuterEdge( array $args, $newX, $newY, $newZ ){
  331.         $x = $args[0]; $y = $args[1]; $z = $args[2];
  332.         $x2 = $args[3]; $y2 = $args[4]; $z2 = $args[5];
  333.        
  334.         if ( $newX == $x || $newX == $x2 || $newY == $y || $newY == $y2 || $newZ == $z || $newZ == $z2 ) return true;
  335.         return false;
  336.     }
  337.     // Checking coords and rearranging to find lowest point
  338.     private function areValidCoords( CommandSender $sender, array &$args, $count){
  339.        
  340.         $tempSet = array('');
  341.         $count--;
  342.        
  343.         for ($l = 0; $l <= $count ; $l++){
  344.                 // First check- Make sure it is set
  345.                 if (!isset($args[$l])) return false;
  346.                
  347.                 if (is_numeric($args[$l])){
  348.                     $args[$l] = (int)$args[$l];
  349.                     $tempSet[$l] = $args[$l];
  350.                 }// Handle ~ entries
  351.                 elseif($args[$l] == "~" ){
  352.                     // x coord
  353.                     if ( $l == 0 || $l == 3 || $l == 6 ){
  354.                         $args[$l] = (int)$sender->getX();
  355.                         $tempSet[$l] = $args[$l];
  356.                     }// y coord
  357.                     elseif ( $l == 1 || $l == 4 || $l == 7 ){
  358.                         $args[$l] = (int)$sender->getY();
  359.                         $tempSet[$l] = $args[$l];
  360.                     }// z coord
  361.                     elseif ( $l == 2 || $l == 5 || $l == 8 ){
  362.                         $args[$l] = (int)$sender->getZ();
  363.                         $tempSet[$l] = $args[$l];
  364.                     }
  365.                 }
  366.                 else{
  367.                     return false;
  368.                 }
  369.         }
  370.         if ( $count >= 5 ){
  371.             // Rearrange coords so we start at lower most part of region
  372.             $args[0] = $tempSet[0] < $tempSet[3] ? $tempSet[0] : $tempSet[3] ;
  373.             $args[1] = $tempSet[1] < $tempSet[4] ? $tempSet[1] : $tempSet[4] ;
  374.             $args[2] = $tempSet[2] < $tempSet[5] ? $tempSet[2] : $tempSet[5] ;
  375.             $args[3] = $tempSet[0] < $tempSet[3] ? $tempSet[3] : $tempSet[0] ;
  376.             $args[4] = $tempSet[1] < $tempSet[4] ? $tempSet[4] : $tempSet[1] ;
  377.             $args[5] = $tempSet[2] < $tempSet[5] ? $tempSet[5] : $tempSet[2] ;
  378.         }
  379.         return true;
  380.     }
  381. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement