SHOW:
|
|
- or go back to the newest paste.
| 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 | } |