Fork of Poseidon providing Bukkit #1060 to older Beta versions (b1.0-b1.7.3)
1package net.minecraft.server;
2
3import com.legacyminecraft.poseidon.PoseidonConfig;
4
5import java.util.*;
6
7public class Chunk {
8
9 public static boolean a;
10 public byte[] b;
11 public boolean c;
12 public World world;
13 public NibbleArray e;
14 public NibbleArray f;
15 public NibbleArray g;
16 public byte[] heightMap;
17 public int i;
18 public int x; // UBERBUKKIT non-final
19 public int z; // UBERBUKKIT non-final
20 public Map tileEntities;
21 public List[] entitySlices;
22 public boolean done;
23 public boolean o;
24 public boolean p;
25 public boolean q;
26 public long r;
27
28 public Chunk(World world, int i, int j) {
29 this.tileEntities = new HashMap();
30 this.entitySlices = new List[8];
31 this.done = false;
32 this.o = false;
33 this.q = false;
34 this.r = 0L;
35 this.world = world;
36 this.x = i;
37 this.z = j;
38 this.heightMap = new byte[256];
39
40 for (int k = 0; k < this.entitySlices.length; ++k) {
41 this.entitySlices[k] = new ArrayList();
42 }
43
44 // CraftBukkit start
45 org.bukkit.craftbukkit.CraftWorld cworld = this.world.getWorld();
46 this.bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this);
47 }
48
49 public org.bukkit.Chunk bukkitChunk;
50 // CraftBukkit end
51
52 public Chunk(World world, byte[] abyte, int i, int j) {
53 this(world, i, j);
54 this.b = abyte;
55 this.e = new NibbleArray(abyte.length);
56 this.f = new NibbleArray(abyte.length);
57 this.g = new NibbleArray(abyte.length);
58 }
59
60 public boolean a(int i, int j) {
61 return i == this.x && j == this.z;
62 }
63
64 public int b(int i, int j) {
65 return this.heightMap[j << 4 | i] & 255;
66 }
67
68 public void a() {
69 }
70
71 public void initLighting() {
72 int i = 127;
73
74 int j;
75 int k;
76
77 for (j = 0; j < 16; ++j) {
78 for (k = 0; k < 16; ++k) {
79 int l = 127;
80
81 int i1;
82
83 for (i1 = j << 11 | k << 7; l > 0 && Block.q[this.b[i1 + l - 1] & 255] == 0; --l) {
84 ;
85 }
86
87 this.heightMap[k << 4 | j] = (byte) l;
88 if (l < i) {
89 i = l;
90 }
91
92 if (!this.world.worldProvider.e) {
93 int j1 = 15;
94 int k1 = 127;
95
96 do {
97 j1 -= Block.q[this.b[i1 + k1] & 255];
98 if (j1 > 0) {
99 this.f.a(j, k1, k, j1);
100 }
101
102 --k1;
103 } while (k1 > 0 && j1 > 0);
104 }
105 }
106 }
107
108 this.i = i;
109
110 for (j = 0; j < 16; ++j) {
111 for (k = 0; k < 16; ++k) {
112 this.c(j, k);
113 }
114 }
115
116 this.o = true;
117 }
118
119 public void loadNOP() {
120 }
121
122 private void c(int i, int j) {
123 int k = this.b(i, j);
124 int l = this.x * 16 + i;
125 int i1 = this.z * 16 + j;
126
127 this.f(l - 1, i1, k);
128 this.f(l + 1, i1, k);
129 this.f(l, i1 - 1, k);
130 this.f(l, i1 + 1, k);
131 }
132
133 private void f(int i, int j, int k) {
134 int l = this.world.getHighestBlockYAt(i, j);
135
136 if (l > k) {
137 this.world.a(EnumSkyBlock.SKY, i, k, j, i, l, j);
138 this.o = true;
139 } else if (l < k) {
140 this.world.a(EnumSkyBlock.SKY, i, l, j, i, k, j);
141 this.o = true;
142 }
143 }
144
145 private void g(int i, int j, int k) {
146 int l = this.heightMap[k << 4 | i] & 255;
147 int i1 = l;
148
149 if (j > l) {
150 i1 = j;
151 }
152
153 for (int j1 = i << 11 | k << 7; i1 > 0 && Block.q[this.b[j1 + i1 - 1] & 255] == 0; --i1) {
154 ;
155 }
156
157 if (i1 != l) {
158 this.world.g(i, k, i1, l);
159 this.heightMap[k << 4 | i] = (byte) i1;
160 int k1;
161 int l1;
162 int i2;
163
164 if (i1 < this.i) {
165 this.i = i1;
166 } else {
167 k1 = 127;
168
169 for (l1 = 0; l1 < 16; ++l1) {
170 for (i2 = 0; i2 < 16; ++i2) {
171 if ((this.heightMap[i2 << 4 | l1] & 255) < k1) {
172 k1 = this.heightMap[i2 << 4 | l1] & 255;
173 }
174 }
175 }
176
177 this.i = k1;
178 }
179
180 k1 = this.x * 16 + i;
181 l1 = this.z * 16 + k;
182 if (i1 < l) {
183 for (i2 = i1; i2 < l; ++i2) {
184 this.f.a(i, i2, k, 15);
185 }
186 } else {
187 this.world.a(EnumSkyBlock.SKY, k1, l, l1, k1, i1, l1);
188
189 for (i2 = l; i2 < i1; ++i2) {
190 this.f.a(i, i2, k, 0);
191 }
192 }
193
194 i2 = 15;
195
196 int j2;
197
198 for (j2 = i1; i1 > 0 && i2 > 0; this.f.a(i, i1, k, i2)) {
199 --i1;
200 int k2 = Block.q[this.getTypeId(i, i1, k)];
201
202 if (k2 == 0) {
203 k2 = 1;
204 }
205
206 i2 -= k2;
207 if (i2 < 0) {
208 i2 = 0;
209 }
210 }
211
212 while (i1 > 0 && Block.q[this.getTypeId(i, i1 - 1, k)] == 0) {
213 --i1;
214 }
215
216 if (i1 != j2) {
217 this.world.a(EnumSkyBlock.SKY, k1 - 1, i1, l1 - 1, k1 + 1, j2, l1 + 1);
218 }
219
220 this.o = true;
221 }
222 }
223
224 public int getTypeId(int i, int j, int k) {
225 return this.b[i << 11 | k << 7 | j] & 255;
226 }
227
228 public boolean a(int i, int j, int k, int l, int i1) {
229 byte b0 = (byte) l;
230 int j1 = this.heightMap[k << 4 | i] & 255;
231 int k1 = this.b[i << 11 | k << 7 | j] & 255;
232
233 if (k1 == l && this.e.a(i, j, k) == i1) {
234 return false;
235 } else {
236 int l1 = this.x * 16 + i;
237 int i2 = this.z * 16 + k;
238
239 this.b[i << 11 | k << 7 | j] = (byte) (b0 & 255);
240 if (PoseidonConfig.getInstance().getConfigBoolean("world.settings.pistons.transmutation-fix.enabled", true)) {
241 this.e.a(i, j, k, i1);
242 if (k1 != 0 && !this.world.isStatic) {
243 Block.byId[k1].remove(this.world, l1, j, i2);
244 }
245 } else {
246 if (k1 != 0 && !this.world.isStatic) {
247 Block.byId[k1].remove(this.world, l1, j, i2);
248 }
249 this.e.a(i, j, k, i1);
250 }
251
252 if (!this.world.worldProvider.e) {
253 if (Block.q[b0 & 255] != 0) {
254 if (j >= j1) {
255 this.g(i, j + 1, k);
256 }
257 } else if (j == j1 - 1) {
258 this.g(i, j, k);
259 }
260
261 this.world.a(EnumSkyBlock.SKY, l1, j, i2, l1, j, i2);
262 }
263
264 this.world.a(EnumSkyBlock.BLOCK, l1, j, i2, l1, j, i2);
265 this.c(i, k);
266 if (l != 0) {
267 Block.byId[l].c(this.world, l1, j, i2);
268 }
269
270 this.o = true;
271 return true;
272 }
273 }
274
275 public boolean a(int i, int j, int k, int l) {
276 byte b0 = (byte) l;
277 int i1 = this.heightMap[k << 4 | i] & 255;
278 int j1 = this.b[i << 11 | k << 7 | j] & 255;
279
280 if (j1 == l) {
281 return false;
282 } else {
283 int k1 = this.x * 16 + i;
284 int l1 = this.z * 16 + k;
285
286 this.b[i << 11 | k << 7 | j] = (byte) (b0 & 255);
287 if (j1 != 0) {
288 Block.byId[j1].remove(this.world, k1, j, l1);
289 }
290
291 this.e.a(i, j, k, 0);
292 if (Block.q[b0 & 255] != 0) {
293 if (j >= i1) {
294 this.g(i, j + 1, k);
295 }
296 } else if (j == i1 - 1) {
297 this.g(i, j, k);
298 }
299
300 this.world.a(EnumSkyBlock.SKY, k1, j, l1, k1, j, l1);
301 this.world.a(EnumSkyBlock.BLOCK, k1, j, l1, k1, j, l1);
302 this.c(i, k);
303 if (l != 0 && !this.world.isStatic) {
304 Block.byId[l].c(this.world, k1, j, l1);
305 }
306
307 this.o = true;
308 return true;
309 }
310 }
311
312 public int getData(int i, int j, int k) {
313 return this.e.a(i, j, k);
314 }
315
316 public void b(int i, int j, int k, int l) {
317 this.o = true;
318 this.e.a(i, j, k, l);
319 }
320
321 public int a(EnumSkyBlock enumskyblock, int i, int j, int k) {
322 return enumskyblock == EnumSkyBlock.SKY ? this.f.a(i, j, k) : (enumskyblock == EnumSkyBlock.BLOCK ? this.g.a(i, j, k) : 0);
323 }
324
325 public void a(EnumSkyBlock enumskyblock, int i, int j, int k, int l) {
326 this.o = true;
327 if (enumskyblock == EnumSkyBlock.SKY) {
328 this.f.a(i, j, k, l);
329 } else {
330 if (enumskyblock != EnumSkyBlock.BLOCK) {
331 return;
332 }
333
334 this.g.a(i, j, k, l);
335 }
336 }
337
338 public int c(int i, int j, int k, int l) {
339 int i1 = this.f.a(i, j, k);
340
341 if (i1 > 0) {
342 a = true;
343 }
344
345 i1 -= l;
346 int j1 = this.g.a(i, j, k);
347
348 if (j1 > i1) {
349 i1 = j1;
350 }
351
352 return i1;
353 }
354
355 public void a(Entity entity) {
356 this.q = true;
357 int i = MathHelper.floor(entity.locX / 16.0D);
358 int j = MathHelper.floor(entity.locZ / 16.0D);
359
360 if (i != this.x || j != this.z) {
361 System.out.println("Wrong location! " + entity);
362 // Thread.dumpStack(); // CraftBukkit
363 // CraftBukkit
364 System.out.println("" + entity.locX + "," + entity.locZ + "(" + i + "," + j + ") vs " + this.x + "," + this.z);
365 }
366
367 int k = MathHelper.floor(entity.locY / 16.0D);
368
369 if (k < 0) {
370 k = 0;
371 }
372
373 if (k >= this.entitySlices.length) {
374 k = this.entitySlices.length - 1;
375 }
376
377 entity.bG = true;
378 entity.bH = this.x;
379 entity.bI = k;
380 entity.bJ = this.z;
381 this.entitySlices[k].add(entity);
382 }
383
384 public void b(Entity entity) {
385 this.a(entity, entity.bI);
386 }
387
388 public void a(Entity entity, int i) {
389 if (i < 0) {
390 i = 0;
391 }
392
393 if (i >= this.entitySlices.length) {
394 i = this.entitySlices.length - 1;
395 }
396
397 this.entitySlices[i].remove(entity);
398 }
399
400 public boolean c(int i, int j, int k) {
401 return j >= (this.heightMap[k << 4 | i] & 255);
402 }
403
404 public TileEntity d(int i, int j, int k) {
405 ChunkPosition chunkposition = new ChunkPosition(i, j, k);
406 TileEntity tileentity = (TileEntity) this.tileEntities.get(chunkposition);
407
408 if (tileentity == null) {
409 int l = this.getTypeId(i, j, k);
410
411 if (!Block.isTileEntity[l]) {
412 return null;
413 }
414
415 BlockContainer blockcontainer = (BlockContainer) Block.byId[l];
416
417 blockcontainer.c(this.world, this.x * 16 + i, j, this.z * 16 + k);
418 tileentity = (TileEntity) this.tileEntities.get(chunkposition);
419 }
420
421 if (tileentity != null && tileentity.g()) {
422 this.tileEntities.remove(chunkposition);
423 return null;
424 } else {
425 return tileentity;
426 }
427 }
428
429 public void a(TileEntity tileentity) {
430 int i = tileentity.x - this.x * 16;
431 int j = tileentity.y;
432 int k = tileentity.z - this.z * 16;
433
434 this.placeTileEntity(i, j, k, tileentity);
435 if (this.c) {
436 this.world.c.add(tileentity);
437 }
438 }
439
440 public void placeTileEntity(int i, int j, int k, TileEntity tileentity) {
441 ChunkPosition chunkposition = new ChunkPosition(i, j, k);
442
443 tileentity.world = this.world;
444 tileentity.x = this.x * 16 + i;
445 tileentity.y = j;
446 tileentity.z = this.z * 16 + k;
447 if (this.getTypeId(i, j, k) != 0 && Block.byId[this.getTypeId(i, j, k)] instanceof BlockContainer) {
448 tileentity.j();
449 this.tileEntities.put(chunkposition, tileentity);
450 // Poseidon start - Backport of 0021-Remove-invalid-mob-spawner-tile-entities.patch from PaperSpigot
451 } else if (tileentity instanceof TileEntityMobSpawner && !(Block.byId[this.getTypeId(i, j, k)] instanceof BlockMobSpawner)) {
452 this.tileEntities.remove(chunkposition);
453 // Poseidon end
454 } else {
455 System.out.println("Attempted to place a tile entity where there was no entity tile!");
456 }
457 }
458
459 public void e(int i, int j, int k) {
460 ChunkPosition chunkposition = new ChunkPosition(i, j, k);
461
462 if (this.c) {
463 TileEntity tileentity = (TileEntity) this.tileEntities.remove(chunkposition);
464
465 if (tileentity != null) {
466 tileentity.h();
467 }
468 }
469 }
470
471 public void addEntities() {
472 this.c = true;
473 this.world.a(this.tileEntities.values());
474
475 for (int i = 0; i < this.entitySlices.length; ++i) {
476 this.world.a(this.entitySlices[i]);
477 }
478 }
479
480 public void removeEntities() {
481 this.c = false;
482 Iterator iterator = this.tileEntities.values().iterator();
483
484 while (iterator.hasNext()) {
485 TileEntity tileentity = (TileEntity) iterator.next();
486
487 world.markForRemoval(tileentity); // Craftbukkit
488 }
489
490 for (int i = 0; i < this.entitySlices.length; ++i) {
491 // CraftBukkit start
492 java.util.Iterator<Object> iter = this.entitySlices[i].iterator();
493 while (iter.hasNext()) {
494 Entity entity = (Entity) iter.next();
495 int cx = org.bukkit.Location.locToBlock(entity.locX) >> 4;
496 int cz = org.bukkit.Location.locToBlock(entity.locZ) >> 4;
497
498 // Do not pass along players, as doing so can get them stuck outside of time.
499 // (which for example disables inventory icon updates and prevents block breaking)
500 if (entity instanceof EntityPlayer && (cx != this.x || cz != this.z)) {
501 iter.remove();
502 }
503 }
504 // CraftBukkit end
505
506 this.world.b(this.entitySlices[i]);
507 }
508 }
509
510 public void f() {
511 this.o = true;
512 }
513
514 public void a(Entity entity, AxisAlignedBB axisalignedbb, List list) {
515 int i = MathHelper.floor((axisalignedbb.b - 2.0D) / 16.0D);
516 int j = MathHelper.floor((axisalignedbb.e + 2.0D) / 16.0D);
517
518 if (i < 0) {
519 i = 0;
520 }
521
522 if (j >= this.entitySlices.length) {
523 j = this.entitySlices.length - 1;
524 }
525
526 for (int k = i; k <= j; ++k) {
527 List list1 = this.entitySlices[k];
528
529 for (int l = 0; l < list1.size(); ++l) {
530 Entity entity1 = (Entity) list1.get(l);
531
532 if (entity1 != entity && entity1.boundingBox.a(axisalignedbb)) {
533 list.add(entity1);
534 }
535 }
536 }
537 }
538
539 public void a(Class oclass, AxisAlignedBB axisalignedbb, List list) {
540 int i = MathHelper.floor((axisalignedbb.b - 2.0D) / 16.0D);
541 int j = MathHelper.floor((axisalignedbb.e + 2.0D) / 16.0D);
542
543 if (i < 0) {
544 i = 0;
545 }
546
547 if (j >= this.entitySlices.length) {
548 j = this.entitySlices.length - 1;
549 }
550
551 for (int k = i; k <= j; ++k) {
552 List list1 = this.entitySlices[k];
553
554 for (int l = 0; l < list1.size(); ++l) {
555 Entity entity = (Entity) list1.get(l);
556
557 if (oclass.isAssignableFrom(entity.getClass()) && entity.boundingBox.a(axisalignedbb)) {
558 list.add(entity);
559 }
560 }
561 }
562 }
563
564 public boolean a(boolean flag) {
565 if (this.p) {
566 return false;
567 } else {
568 if (flag) {
569 if (this.q && this.world.getTime() != this.r) {
570 return true;
571 }
572 } else if (this.q && this.world.getTime() >= this.r + 600L) {
573 return true;
574 }
575
576 return this.o;
577 }
578 }
579
580 public int getData(byte[] abyte, int i, int j, int k, int l, int i1, int j1, int k1) {
581 int l1 = l - i;
582 int i2 = i1 - j;
583 int j2 = j1 - k;
584
585 if (l1 * i2 * j2 == this.b.length) {
586 System.arraycopy(this.b, 0, abyte, k1, this.b.length);
587 k1 += this.b.length;
588 System.arraycopy(this.e.a, 0, abyte, k1, this.e.a.length);
589 k1 += this.e.a.length;
590 System.arraycopy(this.g.a, 0, abyte, k1, this.g.a.length);
591 k1 += this.g.a.length;
592 System.arraycopy(this.f.a, 0, abyte, k1, this.f.a.length);
593 k1 += this.f.a.length;
594 return k1;
595 } else {
596 int k2;
597 int l2;
598 int i3;
599 int j3;
600
601 for (k2 = i; k2 < l; ++k2) {
602 for (l2 = k; l2 < j1; ++l2) {
603 i3 = k2 << 11 | l2 << 7 | j;
604 j3 = i1 - j;
605 System.arraycopy(this.b, i3, abyte, k1, j3);
606 k1 += j3;
607 }
608 }
609
610 for (k2 = i; k2 < l; ++k2) {
611 for (l2 = k; l2 < j1; ++l2) {
612 i3 = (k2 << 11 | l2 << 7 | j) >> 1;
613 j3 = (i1 - j) / 2;
614 System.arraycopy(this.e.a, i3, abyte, k1, j3);
615 k1 += j3;
616 }
617 }
618
619 for (k2 = i; k2 < l; ++k2) {
620 for (l2 = k; l2 < j1; ++l2) {
621 i3 = (k2 << 11 | l2 << 7 | j) >> 1;
622 j3 = (i1 - j) / 2;
623 System.arraycopy(this.g.a, i3, abyte, k1, j3);
624 k1 += j3;
625 }
626 }
627
628 for (k2 = i; k2 < l; ++k2) {
629 for (l2 = k; l2 < j1; ++l2) {
630 i3 = (k2 << 11 | l2 << 7 | j) >> 1;
631 j3 = (i1 - j) / 2;
632 System.arraycopy(this.f.a, i3, abyte, k1, j3);
633 k1 += j3;
634 }
635 }
636
637 return k1;
638 }
639 }
640
641 public Random a(long i) {
642 return new Random(this.world.getSeed() + (long) (this.x * this.x * 4987142) + (long) (this.x * 5947611) + (long) (this.z * this.z) * 4392871L + (long) (this.z * 389711) ^ i);
643 }
644
645 public boolean isEmpty() {
646 return false;
647 }
648
649 public void h() {
650 BlockRegister.a(this.b);
651 }
652}