View difference between Paste ID: CG9KayLG and QUb6BQAr
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
}