mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-23 09:47:38 +00:00
Char block null check (#1030)
**Add a null-check to CharBlocks FULL section layer-retrieval.** - It is possible to trim CharBlocks whilst it is attempting to read data due to the batching of chunks to help reduce memory - This is done when the number of chunks sitting loaded in memory with having been "submitted" to the queue for writing to disk becomes high - Seconday operations such as heightmap processing and lighting will quickly load chunks, meaning many chunks are submitted early - This leads to much higher chances of the chunk being submitted and subsequently trimmed given heightmap and light processing is done layer-by-layer over many chunks, rather than chunk-by-chunk - thus leading to NPEs. - By adding synchronisation to and around only the specific sections when loading/updating, and not blocking the whole chunk, many access can still be thread-safe without causing deadlocks - This allows removal of lots of the needless and very-slowing synchronisation on get**Block** methods **Remove much of the synchronisation from ChunkHolder** - We shouldn't be synchronising with call() and safety should be added elsewhere. (plus it's making edits very very slow when queue target size is hit) - Also remove much of synchronisation because we've added the null-check and section-specific synchronisation to CharBlocks **Some QOL/thread-safe data access changes** - Replaces the Array#clone seen in the get blocks classes with System#arraycopy as deep cloning is not required, and is also slower than arraycopy - Add System#arraycopy when accessing chunk section data via history to ensure it is not altered whilst being written - Renaming EMPTY to empty means it is not implied to be a static variable Fixes https://github.com/IntellectualSites/FastAsyncWorldEdit/issues/1028 Fixes https://github.com/IntellectualSites/FastAsyncWorldEdit/issues/1025 Fixes https://github.com/IntellectualSites/FastAsyncWorldEdit/issues/1089 Fixes https://github.com/IntellectualSites/FastAsyncWorldEdit/issues/1091 Fixes https://github.com/IntellectualSites/FastAsyncWorldEdit/issues/1097
This commit is contained in:
parent
1cd2d8d121
commit
f6af9925e8
@ -349,17 +349,20 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks implements BukkitGetBl
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateGet(BukkitGetBlocks_1_15_2 get, Chunk nmsChunk, ChunkSection[] sections, ChunkSection section, char[] arr, int layer) {
|
private void updateGet(BukkitGetBlocks_1_15_2 get, Chunk nmsChunk, ChunkSection[] chunkSections, ChunkSection section, char[] arr, int layer) {
|
||||||
synchronized (get) {
|
synchronized (get) {
|
||||||
if (this.getChunk() != nmsChunk) {
|
if (this.getChunk() != nmsChunk) {
|
||||||
this.nmsChunk = nmsChunk;
|
this.nmsChunk = nmsChunk;
|
||||||
this.sections = sections.clone();
|
this.sections = new ChunkSection[chunkSections.length];
|
||||||
|
System.arraycopy(chunkSections, 0, this.sections, 0, chunkSections.length);
|
||||||
this.reset();
|
this.reset();
|
||||||
}
|
}
|
||||||
if (this.sections == null) {
|
if (this.sections == null) {
|
||||||
this.sections = sections.clone();
|
this.sections = new ChunkSection[chunkSections.length];
|
||||||
|
System.arraycopy(chunkSections, 0, this.sections, 0, chunkSections.length);
|
||||||
}
|
}
|
||||||
if (this.sections[layer] != section) {
|
if (this.sections[layer] != section) {
|
||||||
|
// Not sure why it's funky, but it's what I did in commit fda7d00747abe97d7891b80ed8bb88d97e1c70d1 and I don't want to touch it >dords
|
||||||
this.sections[layer] = new ChunkSection[]{section}.clone()[0];
|
this.sections[layer] = new ChunkSection[]{section}.clone()[0];
|
||||||
}
|
}
|
||||||
this.blocks[layer] = arr;
|
this.blocks[layer] = arr;
|
||||||
@ -421,9 +424,14 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks implements BukkitGetBl
|
|||||||
|
|
||||||
bitMask |= 1 << layer;
|
bitMask |= 1 << layer;
|
||||||
|
|
||||||
char[] setArr = set.load(layer).clone();
|
char[] tmp = set.load(layer);
|
||||||
|
char[] setArr = new char[4096];
|
||||||
|
System.arraycopy(tmp, 0, setArr, 0, 4096);
|
||||||
if (createCopy) {
|
if (createCopy) {
|
||||||
copy.storeSection(layer, loadPrivately(layer).clone());
|
char[] tmpLoad = loadPrivately(layer);
|
||||||
|
char[] copyArr = new char[4096];
|
||||||
|
System.arraycopy(tmpLoad, 0, copyArr, 0, 4096);
|
||||||
|
copy.storeSection(layer, copyArr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ChunkSection newSection;
|
ChunkSection newSection;
|
||||||
@ -457,7 +465,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks implements BukkitGetBl
|
|||||||
} else if (existingSection != getSections(false)[layer]) {
|
} else if (existingSection != getSections(false)[layer]) {
|
||||||
this.sections[layer] = existingSection;
|
this.sections[layer] = existingSection;
|
||||||
this.reset();
|
this.reset();
|
||||||
} else if (!Arrays.equals(update(layer, new char[4096]), loadPrivately(layer))) {
|
} else if (!Arrays.equals(update(layer, new char[4096], true), loadPrivately(layer))) {
|
||||||
this.reset(layer);
|
this.reset(layer);
|
||||||
} else if (lock.isModified()) {
|
} else if (lock.isModified()) {
|
||||||
this.reset(layer);
|
this.reset(layer);
|
||||||
@ -675,11 +683,13 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks implements BukkitGetBl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private char[] loadPrivately(int layer) {
|
private synchronized char[] loadPrivately(int layer) {
|
||||||
if (super.sections[layer].isFull()) {
|
if (super.blocks[layer] != null) {
|
||||||
return super.blocks[layer];
|
char[] blocks = new char[4096];
|
||||||
|
System.arraycopy(super.blocks[layer], 0, blocks, 0, 4096);
|
||||||
|
return blocks;
|
||||||
} else {
|
} else {
|
||||||
return BukkitGetBlocks_1_15_2.this.update(layer, null);
|
return BukkitGetBlocks_1_15_2.this.update(layer, null, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -689,8 +699,8 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks implements BukkitGetBl
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized char[] update(int layer, char[] data) {
|
public synchronized char[] update(int layer, char[] data, boolean aggressive) {
|
||||||
ChunkSection section = getSections(true)[layer];
|
ChunkSection section = getSections(aggressive)[layer];
|
||||||
// Section is null, return empty array
|
// Section is null, return empty array
|
||||||
if (section == null) {
|
if (section == null) {
|
||||||
data = new char[4096];
|
data = new char[4096];
|
||||||
@ -807,15 +817,20 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks implements BukkitGetBl
|
|||||||
|
|
||||||
public ChunkSection[] getSections(boolean force) {
|
public ChunkSection[] getSections(boolean force) {
|
||||||
if (force && forceLoadSections) {
|
if (force && forceLoadSections) {
|
||||||
return sections = getChunk().getSections().clone();
|
ChunkSection[] sections = getChunk().getSections();
|
||||||
|
ChunkSection[] copy = new ChunkSection[sections.length];
|
||||||
|
System.arraycopy(sections, 0, copy, 0, sections.length);
|
||||||
|
return copy;
|
||||||
}
|
}
|
||||||
ChunkSection[] tmp = sections;
|
ChunkSection[] tmp = sections;
|
||||||
if (tmp == null) {
|
if (tmp == null) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
tmp = sections;
|
tmp = sections;
|
||||||
if (tmp == null) {
|
if (tmp == null) {
|
||||||
Chunk chunk = getChunk();
|
ChunkSection[] chunkSections = getChunk().getSections();
|
||||||
sections = tmp = chunk.getSections().clone();
|
tmp = new ChunkSection[chunkSections.length];
|
||||||
|
System.arraycopy(chunkSections, 0, tmp, 0, chunkSections.length);
|
||||||
|
sections = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -349,17 +349,20 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks implements BukkitGetBl
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateGet(BukkitGetBlocks_1_16_1 get, Chunk nmsChunk, ChunkSection[] sections, ChunkSection section, char[] arr, int layer) {
|
private void updateGet(BukkitGetBlocks_1_16_1 get, Chunk nmsChunk, ChunkSection[] chunkSections, ChunkSection section, char[] arr, int layer) {
|
||||||
synchronized (get) {
|
synchronized (get) {
|
||||||
if (this.getChunk() != nmsChunk) {
|
if (this.getChunk() != nmsChunk) {
|
||||||
this.nmsChunk = nmsChunk;
|
this.nmsChunk = nmsChunk;
|
||||||
this.sections = sections.clone();
|
this.sections = new ChunkSection[chunkSections.length];
|
||||||
|
System.arraycopy(chunkSections, 0, this.sections, 0, chunkSections.length);
|
||||||
this.reset();
|
this.reset();
|
||||||
}
|
}
|
||||||
if (this.sections == null) {
|
if (this.sections == null) {
|
||||||
this.sections = sections.clone();
|
this.sections = new ChunkSection[chunkSections.length];
|
||||||
|
System.arraycopy(chunkSections, 0, this.sections, 0, chunkSections.length);
|
||||||
}
|
}
|
||||||
if (this.sections[layer] != section) {
|
if (this.sections[layer] != section) {
|
||||||
|
// Not sure why it's funky, but it's what I did in commit fda7d00747abe97d7891b80ed8bb88d97e1c70d1 and I don't want to touch it >dords
|
||||||
this.sections[layer] = new ChunkSection[]{section}.clone()[0];
|
this.sections[layer] = new ChunkSection[]{section}.clone()[0];
|
||||||
}
|
}
|
||||||
this.blocks[layer] = arr;
|
this.blocks[layer] = arr;
|
||||||
@ -421,9 +424,14 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks implements BukkitGetBl
|
|||||||
|
|
||||||
bitMask |= 1 << layer;
|
bitMask |= 1 << layer;
|
||||||
|
|
||||||
char[] setArr = set.load(layer).clone();
|
char[] tmp = set.load(layer);
|
||||||
|
char[] setArr = new char[4096];
|
||||||
|
System.arraycopy(tmp, 0, setArr, 0, 4096);
|
||||||
if (createCopy) {
|
if (createCopy) {
|
||||||
copy.storeSection(layer, loadPrivately(layer).clone());
|
char[] tmpLoad = loadPrivately(layer);
|
||||||
|
char[] copyArr = new char[4096];
|
||||||
|
System.arraycopy(tmpLoad, 0, copyArr, 0, 4096);
|
||||||
|
copy.storeSection(layer, copyArr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ChunkSection newSection;
|
ChunkSection newSection;
|
||||||
@ -457,7 +465,7 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks implements BukkitGetBl
|
|||||||
} else if (existingSection != getSections(false)[layer]) {
|
} else if (existingSection != getSections(false)[layer]) {
|
||||||
this.sections[layer] = existingSection;
|
this.sections[layer] = existingSection;
|
||||||
this.reset();
|
this.reset();
|
||||||
} else if (!Arrays.equals(update(layer, new char[4096]), loadPrivately(layer))) {
|
} else if (!Arrays.equals(update(layer, new char[4096], true), loadPrivately(layer))) {
|
||||||
this.reset(layer);
|
this.reset(layer);
|
||||||
} else if (lock.isModified()) {
|
} else if (lock.isModified()) {
|
||||||
this.reset(layer);
|
this.reset(layer);
|
||||||
@ -676,11 +684,13 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks implements BukkitGetBl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private char[] loadPrivately(int layer) {
|
private synchronized char[] loadPrivately(int layer) {
|
||||||
if (super.sections[layer].isFull()) {
|
if (super.blocks[layer] != null) {
|
||||||
return super.blocks[layer];
|
char[] blocks = new char[4096];
|
||||||
|
System.arraycopy(super.blocks[layer], 0, blocks, 0, 4096);
|
||||||
|
return blocks;
|
||||||
} else {
|
} else {
|
||||||
return BukkitGetBlocks_1_16_1.this.update(layer, null);
|
return BukkitGetBlocks_1_16_1.this.update(layer, null, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -690,8 +700,8 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks implements BukkitGetBl
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized char[] update(int layer, char[] data) {
|
public synchronized char[] update(int layer, char[] data, boolean aggressive) {
|
||||||
ChunkSection section = getSections(true)[layer];
|
ChunkSection section = getSections(aggressive)[layer];
|
||||||
// Section is null, return empty array
|
// Section is null, return empty array
|
||||||
if (section == null) {
|
if (section == null) {
|
||||||
data = new char[4096];
|
data = new char[4096];
|
||||||
@ -808,15 +818,20 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks implements BukkitGetBl
|
|||||||
|
|
||||||
public ChunkSection[] getSections(boolean force) {
|
public ChunkSection[] getSections(boolean force) {
|
||||||
if (force && forceLoadSections) {
|
if (force && forceLoadSections) {
|
||||||
return sections = getChunk().getSections().clone();
|
ChunkSection[] sections = getChunk().getSections();
|
||||||
|
ChunkSection[] copy = new ChunkSection[sections.length];
|
||||||
|
System.arraycopy(sections, 0, copy, 0, sections.length);
|
||||||
|
return copy;
|
||||||
}
|
}
|
||||||
ChunkSection[] tmp = sections;
|
ChunkSection[] tmp = sections;
|
||||||
if (tmp == null) {
|
if (tmp == null) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
tmp = sections;
|
tmp = sections;
|
||||||
if (tmp == null) {
|
if (tmp == null) {
|
||||||
Chunk chunk = getChunk();
|
ChunkSection[] chunkSections = getChunk().getSections();
|
||||||
sections = tmp = chunk.getSections().clone();
|
tmp = new ChunkSection[chunkSections.length];
|
||||||
|
System.arraycopy(chunkSections, 0, tmp, 0, chunkSections.length);
|
||||||
|
sections = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -352,17 +352,20 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks implements BukkitGetBl
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateGet(BukkitGetBlocks_1_16_2 get, Chunk nmsChunk, ChunkSection[] sections, ChunkSection section, char[] arr, int layer) {
|
private void updateGet(BukkitGetBlocks_1_16_2 get, Chunk nmsChunk, ChunkSection[] chunkSections, ChunkSection section, char[] arr, int layer) {
|
||||||
synchronized (get) {
|
synchronized (get) {
|
||||||
if (this.getChunk() != nmsChunk) {
|
if (this.getChunk() != nmsChunk) {
|
||||||
this.nmsChunk = nmsChunk;
|
this.nmsChunk = nmsChunk;
|
||||||
this.sections = sections.clone();
|
this.sections = new ChunkSection[chunkSections.length];
|
||||||
|
System.arraycopy(chunkSections, 0, this.sections, 0, chunkSections.length);
|
||||||
this.reset();
|
this.reset();
|
||||||
}
|
}
|
||||||
if (this.sections == null) {
|
if (this.sections == null) {
|
||||||
this.sections = sections.clone();
|
this.sections = new ChunkSection[chunkSections.length];
|
||||||
|
System.arraycopy(chunkSections, 0, this.sections, 0, chunkSections.length);
|
||||||
}
|
}
|
||||||
if (this.sections[layer] != section) {
|
if (this.sections[layer] != section) {
|
||||||
|
// Not sure why it's funky, but it's what I did in commit fda7d00747abe97d7891b80ed8bb88d97e1c70d1 and I don't want to touch it >dords
|
||||||
this.sections[layer] = new ChunkSection[]{section}.clone()[0];
|
this.sections[layer] = new ChunkSection[]{section}.clone()[0];
|
||||||
}
|
}
|
||||||
this.blocks[layer] = arr;
|
this.blocks[layer] = arr;
|
||||||
@ -424,9 +427,14 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks implements BukkitGetBl
|
|||||||
|
|
||||||
bitMask |= 1 << layer;
|
bitMask |= 1 << layer;
|
||||||
|
|
||||||
char[] setArr = set.load(layer).clone();
|
char[] tmp = set.load(layer);
|
||||||
|
char[] setArr = new char[4096];
|
||||||
|
System.arraycopy(tmp, 0, setArr, 0, 4096);
|
||||||
if (createCopy) {
|
if (createCopy) {
|
||||||
copy.storeSection(layer, loadPrivately(layer).clone());
|
char[] tmpLoad = loadPrivately(layer);
|
||||||
|
char[] copyArr = new char[4096];
|
||||||
|
System.arraycopy(tmpLoad, 0, copyArr, 0, 4096);
|
||||||
|
copy.storeSection(layer, copyArr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ChunkSection newSection;
|
ChunkSection newSection;
|
||||||
@ -460,7 +468,7 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks implements BukkitGetBl
|
|||||||
} else if (existingSection != getSections(false)[layer]) {
|
} else if (existingSection != getSections(false)[layer]) {
|
||||||
this.sections[layer] = existingSection;
|
this.sections[layer] = existingSection;
|
||||||
this.reset();
|
this.reset();
|
||||||
} else if (!Arrays.equals(update(layer, new char[4096]), loadPrivately(layer))) {
|
} else if (!Arrays.equals(update(layer, new char[4096], true), loadPrivately(layer))) {
|
||||||
this.reset(layer);
|
this.reset(layer);
|
||||||
} else if (lock.isModified()) {
|
} else if (lock.isModified()) {
|
||||||
this.reset(layer);
|
this.reset(layer);
|
||||||
@ -679,11 +687,13 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks implements BukkitGetBl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private char[] loadPrivately(int layer) {
|
private synchronized char[] loadPrivately(int layer) {
|
||||||
if (super.sections[layer].isFull()) {
|
if (super.blocks[layer] != null) {
|
||||||
return super.blocks[layer];
|
char[] blocks = new char[4096];
|
||||||
|
System.arraycopy(super.blocks[layer], 0, blocks, 0, 4096);
|
||||||
|
return blocks;
|
||||||
} else {
|
} else {
|
||||||
return BukkitGetBlocks_1_16_2.this.update(layer, null);
|
return BukkitGetBlocks_1_16_2.this.update(layer, null, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -693,8 +703,8 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks implements BukkitGetBl
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized char[] update(int layer, char[] data) {
|
public synchronized char[] update(int layer, char[] data, boolean aggressive) {
|
||||||
ChunkSection section = getSections(true)[layer];
|
ChunkSection section = getSections(aggressive)[layer];
|
||||||
// Section is null, return empty array
|
// Section is null, return empty array
|
||||||
if (section == null) {
|
if (section == null) {
|
||||||
data = new char[4096];
|
data = new char[4096];
|
||||||
@ -811,15 +821,20 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks implements BukkitGetBl
|
|||||||
|
|
||||||
public ChunkSection[] getSections(boolean force) {
|
public ChunkSection[] getSections(boolean force) {
|
||||||
if (force && forceLoadSections) {
|
if (force && forceLoadSections) {
|
||||||
return sections = getChunk().getSections().clone();
|
ChunkSection[] sections = getChunk().getSections();
|
||||||
|
ChunkSection[] copy = new ChunkSection[sections.length];
|
||||||
|
System.arraycopy(sections, 0, copy, 0, sections.length);
|
||||||
|
return copy;
|
||||||
}
|
}
|
||||||
ChunkSection[] tmp = sections;
|
ChunkSection[] tmp = sections;
|
||||||
if (tmp == null) {
|
if (tmp == null) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
tmp = sections;
|
tmp = sections;
|
||||||
if (tmp == null) {
|
if (tmp == null) {
|
||||||
Chunk chunk = getChunk();
|
ChunkSection[] chunkSections = getChunk().getSections();
|
||||||
sections = tmp = chunk.getSections().clone();
|
tmp = new ChunkSection[chunkSections.length];
|
||||||
|
System.arraycopy(chunkSections, 0, tmp, 0, chunkSections.length);
|
||||||
|
sections = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -352,17 +352,20 @@ public class BukkitGetBlocks_1_16_5 extends CharGetBlocks implements BukkitGetBl
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateGet(BukkitGetBlocks_1_16_5 get, Chunk nmsChunk, ChunkSection[] sections, ChunkSection section, char[] arr, int layer) {
|
private void updateGet(BukkitGetBlocks_1_16_5 get, Chunk nmsChunk, ChunkSection[] chunkSections, ChunkSection section, char[] arr, int layer) {
|
||||||
synchronized (get) {
|
synchronized (get) {
|
||||||
if (this.getChunk() != nmsChunk) {
|
if (this.getChunk() != nmsChunk) {
|
||||||
this.nmsChunk = nmsChunk;
|
this.nmsChunk = nmsChunk;
|
||||||
this.sections = sections.clone();
|
this.sections = new ChunkSection[chunkSections.length];
|
||||||
|
System.arraycopy(chunkSections, 0, this.sections, 0, chunkSections.length);
|
||||||
this.reset();
|
this.reset();
|
||||||
}
|
}
|
||||||
if (this.sections == null) {
|
if (this.sections == null) {
|
||||||
this.sections = sections.clone();
|
this.sections = new ChunkSection[chunkSections.length];
|
||||||
|
System.arraycopy(chunkSections, 0, this.sections, 0, chunkSections.length);
|
||||||
}
|
}
|
||||||
if (this.sections[layer] != section) {
|
if (this.sections[layer] != section) {
|
||||||
|
// Not sure why it's funky, but it's what I did in commit fda7d00747abe97d7891b80ed8bb88d97e1c70d1 and I don't want to touch it >dords
|
||||||
this.sections[layer] = new ChunkSection[]{section}.clone()[0];
|
this.sections[layer] = new ChunkSection[]{section}.clone()[0];
|
||||||
}
|
}
|
||||||
this.blocks[layer] = arr;
|
this.blocks[layer] = arr;
|
||||||
@ -424,9 +427,14 @@ public class BukkitGetBlocks_1_16_5 extends CharGetBlocks implements BukkitGetBl
|
|||||||
|
|
||||||
bitMask |= 1 << layer;
|
bitMask |= 1 << layer;
|
||||||
|
|
||||||
char[] setArr = set.load(layer).clone();
|
char[] tmp = set.load(layer);
|
||||||
|
char[] setArr = new char[4096];
|
||||||
|
System.arraycopy(tmp, 0, setArr, 0, 4096);
|
||||||
if (createCopy) {
|
if (createCopy) {
|
||||||
copy.storeSection(layer, loadPrivately(layer).clone());
|
char[] tmpLoad = loadPrivately(layer);
|
||||||
|
char[] copyArr = new char[4096];
|
||||||
|
System.arraycopy(tmpLoad, 0, copyArr, 0, 4096);
|
||||||
|
copy.storeSection(layer, copyArr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ChunkSection newSection;
|
ChunkSection newSection;
|
||||||
@ -460,7 +468,7 @@ public class BukkitGetBlocks_1_16_5 extends CharGetBlocks implements BukkitGetBl
|
|||||||
} else if (existingSection != getSections(false)[layer]) {
|
} else if (existingSection != getSections(false)[layer]) {
|
||||||
this.sections[layer] = existingSection;
|
this.sections[layer] = existingSection;
|
||||||
this.reset();
|
this.reset();
|
||||||
} else if (!Arrays.equals(update(layer, new char[4096]), loadPrivately(layer))) {
|
} else if (!Arrays.equals(update(layer, new char[4096], true), loadPrivately(layer))) {
|
||||||
this.reset(layer);
|
this.reset(layer);
|
||||||
} else if (lock.isModified()) {
|
} else if (lock.isModified()) {
|
||||||
this.reset(layer);
|
this.reset(layer);
|
||||||
@ -679,11 +687,13 @@ public class BukkitGetBlocks_1_16_5 extends CharGetBlocks implements BukkitGetBl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private char[] loadPrivately(int layer) {
|
private synchronized char[] loadPrivately(int layer) {
|
||||||
if (super.sections[layer].isFull()) {
|
if (super.blocks[layer] != null) {
|
||||||
return super.blocks[layer];
|
char[] blocks = new char[4096];
|
||||||
|
System.arraycopy(super.blocks[layer], 0, blocks, 0, 4096);
|
||||||
|
return blocks;
|
||||||
} else {
|
} else {
|
||||||
return BukkitGetBlocks_1_16_5.this.update(layer, null);
|
return BukkitGetBlocks_1_16_5.this.update(layer, null, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -693,8 +703,8 @@ public class BukkitGetBlocks_1_16_5 extends CharGetBlocks implements BukkitGetBl
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized char[] update(int layer, char[] data) {
|
public synchronized char[] update(int layer, char[] data, boolean aggressive) {
|
||||||
ChunkSection section = getSections(true)[layer];
|
ChunkSection section = getSections(aggressive)[layer];
|
||||||
// Section is null, return empty array
|
// Section is null, return empty array
|
||||||
if (section == null) {
|
if (section == null) {
|
||||||
data = new char[4096];
|
data = new char[4096];
|
||||||
@ -811,15 +821,20 @@ public class BukkitGetBlocks_1_16_5 extends CharGetBlocks implements BukkitGetBl
|
|||||||
|
|
||||||
public ChunkSection[] getSections(boolean force) {
|
public ChunkSection[] getSections(boolean force) {
|
||||||
if (force && forceLoadSections) {
|
if (force && forceLoadSections) {
|
||||||
return sections = getChunk().getSections().clone();
|
ChunkSection[] sections = getChunk().getSections();
|
||||||
|
ChunkSection[] copy = new ChunkSection[sections.length];
|
||||||
|
System.arraycopy(sections, 0, copy, 0, sections.length);
|
||||||
|
return copy;
|
||||||
}
|
}
|
||||||
ChunkSection[] tmp = sections;
|
ChunkSection[] tmp = sections;
|
||||||
if (tmp == null) {
|
if (tmp == null) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
tmp = sections;
|
tmp = sections;
|
||||||
if (tmp == null) {
|
if (tmp == null) {
|
||||||
Chunk chunk = getChunk();
|
ChunkSection[] chunkSections = getChunk().getSections();
|
||||||
sections = tmp = chunk.getSections().clone();
|
tmp = new ChunkSection[chunkSections.length];
|
||||||
|
System.arraycopy(chunkSections, 0, tmp, 0, chunkSections.length);
|
||||||
|
sections = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,22 +19,34 @@ public abstract class CharBlocks implements IBlocks {
|
|||||||
return blocks.blocks[layer];
|
return blocks.blocks[layer];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ignore aggressive switch here.
|
||||||
|
@Override
|
||||||
|
public char[] get(CharBlocks blocks, @Range(from = 0, to = 15) int layer, boolean aggressive) {
|
||||||
|
return blocks.blocks[layer];
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean isFull() {
|
public final boolean isFull() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
protected final Section EMPTY = new Section() {
|
protected final Section empty = new Section() {
|
||||||
@Override
|
@Override
|
||||||
public final synchronized char[] get(CharBlocks blocks, int layer) {
|
public final synchronized char[] get(CharBlocks blocks, int layer) {
|
||||||
|
// Defaults to aggressive as it should only be avoided where we know we've reset a chunk during an edit
|
||||||
|
return get(blocks, layer, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized char[] get(CharBlocks blocks, @Range(from = 0, to = 15) int layer, boolean aggressive) {
|
||||||
char[] arr = blocks.blocks[layer];
|
char[] arr = blocks.blocks[layer];
|
||||||
if (arr == null) {
|
if (arr == null) {
|
||||||
arr = blocks.blocks[layer] = blocks.update(layer, null);
|
arr = blocks.blocks[layer] = blocks.update(layer, null, aggressive);
|
||||||
if (arr == null) {
|
if (arr == null) {
|
||||||
throw new IllegalStateException("Array cannot be null: " + blocks.getClass());
|
throw new IllegalStateException("Array cannot be null: " + blocks.getClass());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
blocks.blocks[layer] = blocks.update(layer, arr);
|
blocks.blocks[layer] = blocks.update(layer, arr, aggressive);
|
||||||
if (blocks.blocks[layer] == null) {
|
if (blocks.blocks[layer] == null) {
|
||||||
throw new IllegalStateException("Array cannot be null (update): " + blocks.getClass());
|
throw new IllegalStateException("Array cannot be null (update): " + blocks.getClass());
|
||||||
}
|
}
|
||||||
@ -57,7 +69,7 @@ public abstract class CharBlocks implements IBlocks {
|
|||||||
blocks = new char[16][];
|
blocks = new char[16][];
|
||||||
sections = new Section[16];
|
sections = new Section[16];
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
sections[i] = EMPTY;
|
sections[i] = empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,16 +100,16 @@ public abstract class CharBlocks implements IBlocks {
|
|||||||
@Override
|
@Override
|
||||||
public synchronized IChunkSet reset() {
|
public synchronized IChunkSet reset() {
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
sections[i] = EMPTY;
|
sections[i] = empty;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void reset(@Range(from = 0, to = 15) int layer) {
|
public synchronized void reset(@Range(from = 0, to = 15) int layer) {
|
||||||
sections[layer] = EMPTY;
|
sections[layer] = empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized char[] update(int layer, char[] data) {
|
public synchronized char[] update(int layer, char[] data, boolean aggressive) {
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
return new char[4096];
|
return new char[4096];
|
||||||
}
|
}
|
||||||
@ -114,16 +126,18 @@ public abstract class CharBlocks implements IBlocks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized char[] load(@Range(from = 0, to = 15) int layer) {
|
public char[] load(@Range(from = 0, to = 15) int layer) {
|
||||||
|
synchronized (sections[layer]) {
|
||||||
return sections[layer].get(this, layer);
|
return sections[layer].get(this, layer);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized BlockState getBlock(int x, int y, int z) {
|
public BlockState getBlock(int x, int y, int z) {
|
||||||
return BlockTypesCache.states[get(x, y, z)];
|
return BlockTypesCache.states[get(x, y, z)];
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized char get(int x, @Range(from = 0, to = 255) int y, int z) {
|
public char get(int x, @Range(from = 0, to = 255) int y, int z) {
|
||||||
final int layer = y >> 4;
|
final int layer = y >> 4;
|
||||||
final int index = (y & 15) << 8 | z << 4 | x;
|
final int index = (y & 15) << 8 | z << 4 | x;
|
||||||
if (layer >= sections.length || layer < 0) {
|
if (layer >= sections.length || layer < 0) {
|
||||||
@ -149,7 +163,7 @@ public abstract class CharBlocks implements IBlocks {
|
|||||||
Section
|
Section
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public synchronized final char get(@Range(from = 0, to = 15) int layer, int index) {
|
public final char get(@Range(from = 0, to = 15) int layer, int index) {
|
||||||
return sections[layer].get(this, layer, index);
|
return sections[layer].get(this, layer, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,10 +175,17 @@ public abstract class CharBlocks implements IBlocks {
|
|||||||
|
|
||||||
public abstract char[] get(CharBlocks blocks, @Range(from = 0, to = 15) int layer);
|
public abstract char[] get(CharBlocks blocks, @Range(from = 0, to = 15) int layer);
|
||||||
|
|
||||||
|
public abstract char[] get(CharBlocks blocks, @Range(from = 0, to = 15) int layer, boolean aggressive);
|
||||||
|
|
||||||
public abstract boolean isFull();
|
public abstract boolean isFull();
|
||||||
|
|
||||||
public final char get(CharBlocks blocks, @Range(from = 0, to = 15) int layer, int index) {
|
public final char get(CharBlocks blocks, @Range(from = 0, to = 15) int layer, int index) {
|
||||||
return get(blocks, layer)[index];
|
char[] section = get(blocks, layer);
|
||||||
|
if (section == null) {
|
||||||
|
blocks.reset(layer);
|
||||||
|
section = blocks.empty.get(blocks, layer, false);
|
||||||
|
}
|
||||||
|
return section[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void set(CharBlocks blocks, @Range(from = 0, to = 15) int layer, int index, char value) {
|
public final void set(CharBlocks blocks, @Range(from = 0, to = 15) int layer, int index, char value) {
|
||||||
|
@ -19,13 +19,14 @@ public abstract class CharGetBlocks extends CharBlocks implements IChunkGet {
|
|||||||
@Override
|
@Override
|
||||||
public boolean trim(boolean aggressive) {
|
public boolean trim(boolean aggressive) {
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
sections[i] = EMPTY;
|
sections[i] = empty;
|
||||||
blocks[i] = null;
|
blocks[i] = null;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public char[] update(int layer, char[] data) {
|
@Override
|
||||||
|
public char[] update(int layer, char[] data, boolean aggressive) {
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
data = new char[4096];
|
data = new char[4096];
|
||||||
}
|
}
|
||||||
@ -34,8 +35,8 @@ public abstract class CharGetBlocks extends CharBlocks implements IChunkGet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean trim(boolean aggressive, int layer) {
|
public synchronized boolean trim(boolean aggressive, int layer) {
|
||||||
sections[layer] = EMPTY;
|
sections[layer] = empty;
|
||||||
blocks[layer] = null;
|
blocks[layer] = null;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void recycle() {
|
public synchronized void recycle() {
|
||||||
POOL.offer(this);
|
POOL.offer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet {
|
|||||||
@Override
|
@Override
|
||||||
public void setBlocks(int layer, char[] data) {
|
public void setBlocks(int layer, char[] data) {
|
||||||
this.blocks[layer] = data;
|
this.blocks[layer] = data;
|
||||||
this.sections[layer] = data == null ? EMPTY : FULL;
|
this.sections[layer] = data == null ? empty : FULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -141,7 +141,7 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized CompoundTag getEntity(UUID uuid) {
|
public CompoundTag getEntity(UUID uuid) {
|
||||||
return delegate.get(this).getEntity(uuid);
|
return delegate.get(this).getEntity(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,21 +156,21 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void setLightingToGet(char[][] lighting) {
|
public void setLightingToGet(char[][] lighting) {
|
||||||
delegate.setLightingToGet(this, lighting);
|
delegate.setLightingToGet(this, lighting);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void setSkyLightingToGet(char[][] lighting) {
|
public void setSkyLightingToGet(char[][] lighting) {
|
||||||
delegate.setSkyLightingToGet(this, lighting);
|
delegate.setSkyLightingToGet(this, lighting);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void setHeightmapToGet(HeightMapType type, int[] data) {
|
public void setHeightmapToGet(HeightMapType type, int[] data) {
|
||||||
delegate.setHeightmapToGet(this, type, data);
|
delegate.setHeightmapToGet(this, type, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void flushLightToGet(boolean heightmaps) {
|
public void flushLightToGet(boolean heightmaps) {
|
||||||
delegate.flushLightToGet(this, heightmaps);
|
delegate.flushLightToGet(this, heightmaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -800,22 +800,22 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized Map<BlockVector3, CompoundTag> getTiles() {
|
public Map<BlockVector3, CompoundTag> getTiles() {
|
||||||
return delegate.get(this).getTiles();
|
return delegate.get(this).getTiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized Set<CompoundTag> getEntities() {
|
public Set<CompoundTag> getEntities() {
|
||||||
return delegate.get(this).getEntities();
|
return delegate.get(this).getEntities();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean hasSection(int layer) {
|
public boolean hasSection(int layer) {
|
||||||
return chunkExisting != null && chunkExisting.hasSection(layer);
|
return chunkExisting != null && chunkExisting.hasSection(layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void filterBlocks(Filter filter, ChunkFilterBlock block, @Nullable Region region, boolean full) {
|
public void filterBlocks(Filter filter, ChunkFilterBlock block, @Nullable Region region, boolean full) {
|
||||||
final IChunkGet get = getOrCreateGet();
|
final IChunkGet get = getOrCreateGet();
|
||||||
final IChunkSet set = getOrCreateSet();
|
final IChunkSet set = getOrCreateSet();
|
||||||
set.setFastMode(fastmode);
|
set.setFastMode(fastmode);
|
||||||
@ -863,7 +863,7 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
|||||||
/**
|
/**
|
||||||
* Get or create the existing part of this chunk.
|
* Get or create the existing part of this chunk.
|
||||||
*/
|
*/
|
||||||
public synchronized final IChunkGet getOrCreateGet() {
|
public final IChunkGet getOrCreateGet() {
|
||||||
if (chunkExisting == null) {
|
if (chunkExisting == null) {
|
||||||
chunkExisting = newWrappedGet();
|
chunkExisting = newWrappedGet();
|
||||||
}
|
}
|
||||||
@ -873,7 +873,7 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
|||||||
/**
|
/**
|
||||||
* Get or create the settable part of this chunk.
|
* Get or create the settable part of this chunk.
|
||||||
*/
|
*/
|
||||||
public synchronized final IChunkSet getOrCreateSet() {
|
public final IChunkSet getOrCreateSet() {
|
||||||
if (chunkSet == null) {
|
if (chunkSet == null) {
|
||||||
chunkSet = newWrappedSet();
|
chunkSet = newWrappedSet();
|
||||||
}
|
}
|
||||||
@ -885,7 +885,7 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
|||||||
* - The purpose of wrapping is to allow different extents to intercept / alter behavior
|
* - The purpose of wrapping is to allow different extents to intercept / alter behavior
|
||||||
* - e.g., caching, optimizations, filtering
|
* - e.g., caching, optimizations, filtering
|
||||||
*/
|
*/
|
||||||
private synchronized IChunkSet newWrappedSet() {
|
private IChunkSet newWrappedSet() {
|
||||||
return extent.getCachedSet(chunkX, chunkZ);
|
return extent.getCachedSet(chunkX, chunkZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -917,11 +917,7 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
|||||||
public synchronized T call() {
|
public synchronized T call() {
|
||||||
if (chunkSet != null) {
|
if (chunkSet != null) {
|
||||||
chunkSet.setBitMask(bitMask);
|
chunkSet.setBitMask(bitMask);
|
||||||
return this.call(chunkSet, () -> {
|
return this.call(chunkSet, this::recycle);
|
||||||
synchronized (this) {
|
|
||||||
this.recycle();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -963,82 +959,82 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean setBiome(int x, int y, int z, BiomeType biome) {
|
public boolean setBiome(int x, int y, int z, BiomeType biome) {
|
||||||
return delegate.setBiome(this, x, y, z, biome);
|
return delegate.setBiome(this, x, y, z, biome);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized <B extends BlockStateHolder<B>> boolean setBlock(int x, int y, int z, B block) {
|
public <B extends BlockStateHolder<B>> boolean setBlock(int x, int y, int z, B block) {
|
||||||
return delegate.setBlock(this, x, y, z, block);
|
return delegate.setBlock(this, x, y, z, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized BiomeType getBiomeType(int x, int y, int z) {
|
public BiomeType getBiomeType(int x, int y, int z) {
|
||||||
return delegate.getBiome(this, x, y, z);
|
return delegate.getBiome(this, x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized BlockState getBlock(int x, int y, int z) {
|
public BlockState getBlock(int x, int y, int z) {
|
||||||
return delegate.getBlock(this, x, y, z);
|
return delegate.getBlock(this, x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized BaseBlock getFullBlock(int x, int y, int z) {
|
public BaseBlock getFullBlock(int x, int y, int z) {
|
||||||
return delegate.getFullBlock(this, x, y, z);
|
return delegate.getFullBlock(this, x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void setSkyLight(int x, int y, int z, int value) {
|
public void setSkyLight(int x, int y, int z, int value) {
|
||||||
delegate.setSkyLight(this, x, y, z, value);
|
delegate.setSkyLight(this, x, y, z, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void setHeightMap(HeightMapType type, int[] heightMap) {
|
public void setHeightMap(HeightMapType type, int[] heightMap) {
|
||||||
delegate.setHeightMap(this, type, heightMap);
|
delegate.setHeightMap(this, type, heightMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void removeSectionLighting(int layer, boolean sky) {
|
public void removeSectionLighting(int layer, boolean sky) {
|
||||||
delegate.removeSectionLighting(this, layer, sky);
|
delegate.removeSectionLighting(this, layer, sky);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void setFullBright(int layer) {
|
public void setFullBright(int layer) {
|
||||||
delegate.setFullBright(this, layer);
|
delegate.setFullBright(this, layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void setBlockLight(int x, int y, int z, int value) {
|
public void setBlockLight(int x, int y, int z, int value) {
|
||||||
delegate.setBlockLight(this, x, y, z, value);
|
delegate.setBlockLight(this, x, y, z, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void setLightLayer(int layer, char[] toSet) {
|
public void setLightLayer(int layer, char[] toSet) {
|
||||||
delegate.setLightLayer(this, layer, toSet);
|
delegate.setLightLayer(this, layer, toSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void setSkyLightLayer(int layer, char[] toSet) {
|
public void setSkyLightLayer(int layer, char[] toSet) {
|
||||||
delegate.setSkyLightLayer(this, layer, toSet);
|
delegate.setSkyLightLayer(this, layer, toSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized int getSkyLight(int x, int y, int z) {
|
public int getSkyLight(int x, int y, int z) {
|
||||||
return delegate.getSkyLight(this, x, y, z);
|
return delegate.getSkyLight(this, x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized int getEmmittedLight(int x, int y, int z) {
|
public int getEmmittedLight(int x, int y, int z) {
|
||||||
return delegate.getEmmittedLight(this, x, y, z);
|
return delegate.getEmmittedLight(this, x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized int getBrightness(int x, int y, int z) {
|
public int getBrightness(int x, int y, int z) {
|
||||||
return delegate.getBrightness(this, x, y, z);
|
return delegate.getBrightness(this, x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized int getOpacity(int x, int y, int z) {
|
public int getOpacity(int x, int y, int z) {
|
||||||
return delegate.getOpacity(this, x, y, z);
|
return delegate.getOpacity(this, x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,11 +162,15 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// add each block and tile
|
// add each block and tile
|
||||||
char[] blocksGet = get.load(layer);
|
char[] blocksGet;
|
||||||
if (blocksGet == null) {
|
char[] tmp = get.load(layer);
|
||||||
|
if (tmp == null) {
|
||||||
blocksGet = FaweCache.IMP.EMPTY_CHAR_4096;
|
blocksGet = FaweCache.IMP.EMPTY_CHAR_4096;
|
||||||
|
} else {
|
||||||
|
System.arraycopy(tmp, 0, (blocksGet = new char[4096]), 0, 4096);
|
||||||
}
|
}
|
||||||
char[] blocksSet = set.load(layer);
|
char[] blocksSet;
|
||||||
|
System.arraycopy(set.load(layer), 0, (blocksSet = new char[4096]), 0, 4096);
|
||||||
|
|
||||||
int by = layer << 4;
|
int by = layer << 4;
|
||||||
for (int y = 0, index = 0; y < 16; y++) {
|
for (int y = 0, index = 0; y < 16; y++) {
|
||||||
|
Loading…
Reference in New Issue
Block a user