Trow_Games

CuboID

May 1st, 2015
126
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package me.trow.Teste;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.HashMap;
  5. import java.util.Iterator;
  6. import java.util.List;
  7. import java.util.Map;
  8. import org.bukkit.Bukkit;
  9. import org.bukkit.Chunk;
  10. import org.bukkit.Location;
  11. import org.bukkit.World;
  12. import org.bukkit.block.Block;
  13. import org.bukkit.configuration.serialization.ConfigurationSerializable;
  14.  
  15. public class CuboID implements Iterable<Block>, Cloneable, ConfigurationSerializable{
  16.     protected final String worldName;
  17.     protected final int x1;
  18.     protected final int y1;
  19.     protected final int z1;
  20.     protected final int x2;
  21.     protected final int y2;
  22.     protected final int z2;
  23.    
  24.     public CuboID(Location l1, Location l2){
  25.         if (!l1.getWorld().equals(l2.getWorld())) {
  26.             throw new IllegalArgumentException("Locations must be on the same world");
  27.         }
  28.         this.worldName = l1.getWorld().getName();
  29.         this.x1 = Math.min(l1.getBlockX(), l2.getBlockX());
  30.         this.y1 = Math.min(l1.getBlockY(), l2.getBlockY());
  31.         this.z1 = Math.min(l1.getBlockZ(), l2.getBlockZ());
  32.         this.x2 = Math.max(l1.getBlockX(), l2.getBlockX());
  33.         this.y2 = Math.max(l1.getBlockY(), l2.getBlockY());
  34.         this.z2 = Math.max(l1.getBlockZ(), l2.getBlockZ());
  35.     }
  36.  
  37.     public CuboID(Location l1){
  38.         this(l1, l1);
  39.     }
  40.    
  41.     public CuboID(CuboID other){
  42.         this(other.getWorld().getName(), other.x1, other.y1, other.z1, other.x2, other.y2, other.z2);
  43.     }
  44.    
  45.     public CuboID(World world, int x1, int y1, int z1, int x2, int y2, int z2){
  46.         this.worldName = world.getName();
  47.         this.x1 = Math.min(x1, x2);
  48.         this.x2 = Math.max(x1, x2);
  49.         this.y1 = Math.min(y1, y2);
  50.         this.y2 = Math.max(y1, y2);
  51.         this.z1 = Math.min(z1, z2);
  52.         this.z2 = Math.max(z1, z2);
  53.     }  
  54.    
  55.     private CuboID(String worldName, int x1, int y1, int z1, int x2, int y2, int z2){
  56.         this.worldName = worldName;
  57.         this.x1 = Math.min(x1, x2);
  58.         this.x2 = Math.max(x1, x2);
  59.         this.y1 = Math.min(y1, y2);
  60.         this.y2 = Math.max(y1, y2);
  61.         this.z1 = Math.min(z1, z2);
  62.         this.z2 = Math.max(z1, z2);
  63.     }
  64.    
  65.     public CuboID(Map<String, Object> map){
  66.         this.worldName = ((String)map.get("worldName"));
  67.         this.x1 = ((Integer)map.get("x1")).intValue();
  68.         this.x2 = ((Integer)map.get("x2")).intValue();
  69.         this.y1 = ((Integer)map.get("y1")).intValue();
  70.         this.y2 = ((Integer)map.get("y2")).intValue();
  71.         this.z1 = ((Integer)map.get("z1")).intValue();
  72.         this.z2 = ((Integer)map.get("z2")).intValue();
  73.     }
  74.    
  75.     public Map<String, Object> serialize(){
  76.         Map<String, Object> map = new HashMap();
  77.         map.put("worldName", this.worldName);
  78.         map.put("x1", Integer.valueOf(this.x1));
  79.         map.put("y1", Integer.valueOf(this.y1));
  80.         map.put("z1", Integer.valueOf(this.z1));
  81.         map.put("x2", Integer.valueOf(this.x2));
  82.         map.put("y2", Integer.valueOf(this.y2));
  83.         map.put("z2", Integer.valueOf(this.z2));
  84.         return map;
  85.     }
  86.    
  87.     public Location getLowerNE(){
  88.         return new Location(getWorld(), this.x1, this.y1, this.z1);
  89.     }
  90.    
  91.     public Location getUpperSW(){
  92.         return new Location(getWorld(), this.x2, this.y2, this.z2);
  93.     }
  94.  
  95.     public List<Block> getBlocks(){
  96.         Iterator<Block> blockI = iterator();
  97.         List<Block> copy = new ArrayList();
  98.         while (blockI.hasNext()) {
  99.             copy.add((Block)blockI.next());
  100.         }
  101.         return copy;
  102.     }
  103.  
  104.     public Location getCenter(){
  105.         int x1 = getUpperX() + 1;
  106.         int y1 = getUpperY() + 1;
  107.         int z1 = getUpperZ() + 1;
  108.         return new Location(getWorld(), getLowerX() + (x1 - getLowerX()) / 2.0D, getLowerY() + (y1 - getLowerY()) / 2.0D, getLowerZ() + (z1 - getLowerZ()) / 2.0D);
  109.         }
  110.      
  111.         public World getWorld()
  112.         {
  113.         World world = Bukkit.getWorld(this.worldName);
  114.         if (world == null) {
  115.             throw new IllegalStateException("World '" + this.worldName + "' is not loaded");
  116.         }
  117.         return world;
  118.     }
  119.  
  120.     public int getSizeX(){
  121.     return this.x2 - this.x1 + 1;
  122.     }
  123.  
  124.     public int getSizeY(){
  125.     return this.y2 - this.y1 + 1;
  126.     }
  127.  
  128.     public int getSizeZ(){
  129.     return this.z2 - this.z1 + 1;
  130.     }
  131.  
  132.     public int getLowerX(){
  133.     return this.x1;
  134.     }
  135.  
  136.     public int getLowerY(){
  137.     return this.y1;
  138.     }
  139.  
  140.     public int getLowerZ(){
  141.     return this.z1;
  142.     }
  143.  
  144.     public int getUpperX(){
  145.     return this.x2;
  146.     }
  147.  
  148.     public int getUpperY(){
  149.     return this.y2;
  150.     }
  151.  
  152.     public int getUpperZ(){
  153.     return this.z2;
  154.     }
  155.  
  156.     public Block[] corners(){
  157.     Block[] res = new Block[8];
  158.     World w = getWorld();
  159.     res[0] = w.getBlockAt(this.x1, this.y1, this.z1);
  160.     res[1] = w.getBlockAt(this.x1, this.y1, this.z2);
  161.     res[2] = w.getBlockAt(this.x1, this.y2, this.z1);
  162.     res[3] = w.getBlockAt(this.x1, this.y2, this.z2);
  163.     res[4] = w.getBlockAt(this.x2, this.y1, this.z1);
  164.     res[5] = w.getBlockAt(this.x2, this.y1, this.z2);
  165.     res[6] = w.getBlockAt(this.x2, this.y2, this.z1);
  166.     res[7] = w.getBlockAt(this.x2, this.y2, this.z2);
  167.     return res;
  168.     }
  169.  
  170.     public CuboID expand(CuboidDirection dir, int amount){
  171.         switch (dir){
  172.         case Both:
  173.             return new CuboID(this.worldName, this.x1 - amount, this.y1, this.z1, this.x2, this.y2, this.z2);
  174.         case East:
  175.             return new CuboID(this.worldName, this.x1, this.y1, this.z1, this.x2 + amount, this.y2, this.z2);
  176.         case Down:
  177.             return new CuboID(this.worldName, this.x1, this.y1, this.z1 - amount, this.x2, this.y2, this.z2);
  178.         case Horizontal:
  179.             return new CuboID(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y2, this.z2 + amount);
  180.         case South:
  181.             return new CuboID(this.worldName, this.x1, this.y1 - amount, this.z1, this.x2, this.y2, this.z2);
  182.         case North:
  183.             return new CuboID(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y2 + amount, this.z2);
  184.         }
  185.         throw new IllegalArgumentException("Invalid direction " + dir);
  186.     }
  187.  
  188.     public CuboID shift(CuboidDirection dir, int amount){
  189.         return expand(dir, amount).expand(dir.opposite(), -amount);
  190.     }
  191.  
  192.     public CuboID outset(CuboidDirection dir, int amount){
  193.         CuboID c;
  194.         CuboID c1;
  195.         CuboID c2;
  196.         switch (dir){
  197.         case Unknown:
  198.             c = expand(CuboidDirection.North, amount).expand(CuboidDirection.South, amount).expand(CuboidDirection.East, amount).expand(CuboidDirection.West, amount);
  199.             break;
  200.         case Up:
  201.             c = expand(CuboidDirection.Down, amount).expand(CuboidDirection.Up, amount);
  202.             break;
  203.         case Vertical:
  204.             c = outset(CuboidDirection.Horizontal, amount).outset(CuboidDirection.Vertical, amount);
  205.             break;
  206.         default:
  207.             throw new IllegalArgumentException("Invalid direction " + dir);
  208.         }
  209.         CuboID c3;
  210.         return c;
  211.     }
  212.  
  213.     public CuboID inset(CuboidDirection dir, int amount){
  214.         return outset(dir, -amount);
  215.     }
  216.  
  217.     public boolean contains(int x, int y, int z){
  218.         return (x >= this.x1) && (x <= this.x2) && (y >= this.y1) && (y <= this.y2) && (z >= this.z1) && (z <= this.z2);
  219.     }
  220.  
  221.     public boolean contains(Block b){
  222.         return contains(b.getLocation());
  223.     }
  224.  
  225.     public boolean contains(Location l){
  226.         if (!this.worldName.equals(l.getWorld().getName())) {
  227.             return false;
  228.         }
  229.         return contains(l.getBlockX(), l.getBlockY(), l.getBlockZ());
  230.     }
  231.  
  232.     public int getVolume(){
  233.         return getSizeX() * getSizeY() * getSizeZ();
  234.     }
  235.  
  236.     public byte getAverageLightLevel(){
  237.         long total = 0L;
  238.         int n = 0;
  239.         for (Block b : this) {
  240.             if (b.isEmpty()){
  241.             total += b.getLightLevel();
  242.             n++;
  243.             }
  244.         }
  245.         return n > 0 ? (byte)(int)(total / n) : 0;
  246.     }
  247.  
  248.     public CuboID contract(){
  249.         return contract(CuboidDirection.Down).contract(CuboidDirection.South).contract(CuboidDirection.East).contract(CuboidDirection.Up).contract(CuboidDirection.North).contract(CuboidDirection.West);
  250.     }
  251.  
  252.     public CuboID contract(CuboidDirection dir){
  253.         CuboID face = getFace(dir.opposite());
  254.         switch (dir){
  255.             case South:
  256.                 while ((face.containsOnly(0)) && (face.getLowerY() > getLowerY())) {
  257.                 face = face.shift(CuboidDirection.Down, 1);
  258.                 }
  259.                 return new CuboID(this.worldName, this.x1, this.y1, this.z1, this.x2, face.getUpperY(), this.z2);
  260.             case North:
  261.                 while ((face.containsOnly(0)) && (face.getUpperY() < getUpperY())) {
  262.                 face = face.shift(CuboidDirection.Up, 1);
  263.                 }
  264.                 return new CuboID(this.worldName, this.x1, face.getLowerY(), this.z1, this.x2, this.y2, this.z2);
  265.             case Both:
  266.                 while ((face.containsOnly(0)) && (face.getLowerX() > getLowerX())) {
  267.                 face = face.shift(CuboidDirection.North, 1);
  268.                 }
  269.                 return new CuboID(this.worldName, this.x1, this.y1, this.z1, face.getUpperX(), this.y2, this.z2);
  270.             case East:
  271.                 while ((face.containsOnly(0)) && (face.getUpperX() < getUpperX())) {
  272.                 face = face.shift(CuboidDirection.South, 1);
  273.                 }
  274.                 return new CuboID(this.worldName, face.getLowerX(), this.y1, this.z1, this.x2, this.y2, this.z2);
  275.             case Down:
  276.                 while ((face.containsOnly(0)) && (face.getLowerZ() > getLowerZ())) {
  277.                 face = face.shift(CuboidDirection.East, 1);
  278.                 }
  279.                 return new CuboID(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y2, face.getUpperZ());
  280.             case Horizontal:
  281.                 while ((face.containsOnly(0)) && (face.getUpperZ() < getUpperZ())) {
  282.                 face = face.shift(CuboidDirection.West, 1);
  283.                 }
  284.                 return new CuboID(this.worldName, this.x1, this.y1, face.getLowerZ(), this.x2, this.y2, this.z2);
  285.         }
  286.         throw new IllegalArgumentException("Invalid direction " + dir);
  287.     }
  288.  
  289.     public CuboID getFace(CuboidDirection dir){
  290.         switch (dir){
  291.             case South:
  292.                 return new CuboID(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y1, this.z2);
  293.             case North:
  294.                 return new CuboID(this.worldName, this.x1, this.y2, this.z1, this.x2, this.y2, this.z2);
  295.             case Both:
  296.                 return new CuboID(this.worldName, this.x1, this.y1, this.z1, this.x1, this.y2, this.z2);
  297.             case East:
  298.                 return new CuboID(this.worldName, this.x2, this.y1, this.z1, this.x2, this.y2, this.z2);
  299.             case Down:
  300.                 return new CuboID(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y2, this.z1);
  301.             case Horizontal:
  302.                 return new CuboID(this.worldName, this.x1, this.y1, this.z2, this.x2, this.y2, this.z2);
  303.             }
  304.             throw new IllegalArgumentException("Invalid direction " + dir);
  305.     }
  306.  
  307.     public boolean containsOnly(int blockId){
  308.         for (Block b : this) {
  309.             if (b.getTypeId() != blockId) {
  310.             return false;
  311.             }
  312.         }
  313.         return true;
  314.     }
  315.  
  316.     public CuboID getBoundingCuboid(CuboID other){
  317.         if (other == null) {
  318.             return this;
  319.         }
  320.         int xMin = Math.min(getLowerX(), other.getLowerX());
  321.         int yMin = Math.min(getLowerY(), other.getLowerY());
  322.         int zMin = Math.min(getLowerZ(), other.getLowerZ());
  323.         int xMax = Math.max(getUpperX(), other.getUpperX());
  324.         int yMax = Math.max(getUpperY(), other.getUpperY());
  325.         int zMax = Math.max(getUpperZ(), other.getUpperZ());
  326.          
  327.         return new CuboID(this.worldName, xMin, yMin, zMin, xMax, yMax, zMax);
  328.         }
  329.      
  330.         public Block getRelativeBlock(int x, int y, int z){
  331.         return getWorld().getBlockAt(this.x1 + x, this.y1 + y, this.z1 + z);
  332.         }
  333.      
  334.         public Block getRelativeBlock(World w, int x, int y, int z){
  335.         return w.getBlockAt(this.x1 + x, this.y1 + y, this.z1 + z);
  336.     }
  337.  
  338.     public List<Chunk> getChunks(){
  339.         List<Chunk> res = new ArrayList();
  340.          
  341.         World w = getWorld();
  342.         int x1 = getLowerX() & 0xFFFFFFF0;
  343.         int x2 = getUpperX() & 0xFFFFFFF0;
  344.         int z1 = getLowerZ() & 0xFFFFFFF0;
  345.         int z2 = getUpperZ() & 0xFFFFFFF0;
  346.         for (int x = x1; x <= x2; x += 16) {
  347.             for (int z = z1; z <= z2; z += 16) {
  348.                 res.add(w.getChunkAt(x >> 4, z >> 4));
  349.             }
  350.         }
  351.         return res;
  352.     }
  353.  
  354.     public Iterator<Block> iterator(){
  355.         return new CuboidIterator(getWorld(), this.x1, this.y1, this.z1, this.x2, this.y2, this.z2);
  356.     }
  357.  
  358.     public CuboID clone(){
  359.         return new CuboID(this);
  360.     }
  361.  
  362.     public String toString(){
  363.         return new String("Cuboid: " + this.worldName + "," + this.x1 + "," + this.y1 + "," + this.z1 + "=>" + this.x2 + "," + this.y2 + "," + this.z2);
  364.     }
  365.  
  366.     public class CuboidIterator implements Iterator<Block>{
  367.     private World w;
  368.     private int baseX;
  369.     private int baseY;
  370.     private int baseZ;
  371.     private int x;
  372.     private int y;
  373.     private int z;
  374.     private int sizeX;
  375.     private int sizeY;
  376.     private int sizeZ;
  377.      
  378.     public CuboidIterator(World w, int x1, int y1, int z1, int x2, int y2, int z2){
  379.         this.w = w;
  380.         this.baseX = x1;
  381.         this.baseY = y1;
  382.         this.baseZ = z1;
  383.         this.sizeX = (Math.abs(x2 - x1) + 1);
  384.         this.sizeY = (Math.abs(y2 - y1) + 1);
  385.         this.sizeZ = (Math.abs(z2 - z1) + 1);
  386.         this.x = (this.y = this.z = 0);
  387.     }
  388.      
  389.     public boolean hasNext(){
  390.         return (this.x < this.sizeX) && (this.y < this.sizeY) && (this.z < this.sizeZ);
  391.     }
  392.      
  393.     public Block next(){
  394.         Block b = this.w.getBlockAt(this.baseX + this.x, this.baseY + this.y, this.baseZ + this.z);
  395.         if (++this.x >= this.sizeX){
  396.             this.x = 0;
  397.             if (++this.y >= this.sizeY){
  398.                 this.y = 0;
  399.                 this.z += 1;
  400.             }
  401.         }
  402.         return b;
  403.     }
  404.      
  405.     public void remove() {}
  406.     }
  407.  
  408.     public static enum CuboidDirection{
  409.     North,  East,   South,  West,   Up, Down,   Horizontal, Vertical,   Both,   Unknown;
  410.    
  411.         public CuboidDirection opposite(){
  412.             switch (this){
  413.             case Both:
  414.             return South;
  415.             case Down:
  416.             return West;
  417.             case East:
  418.             return North;
  419.             case Horizontal:
  420.             return East;
  421.             case Unknown:
  422.             return Vertical;
  423.             case Up:
  424.             return Horizontal;
  425.             case North:
  426.             return Down;
  427.             case South:
  428.             return Up;
  429.             case Vertical:
  430.             return Both;
  431.             }
  432.             return Unknown;
  433.         }
  434.     }
  435. }
Add Comment
Please, Sign In to add comment