Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1154,6 +1154,13 @@ public boolean hasSection(int layer) {
return getSections(false)[layer] != null;
}

@Override
public boolean hasNonEmptySection(int layer) {
layer -= getMinSectionPosition();
LevelChunkSection section = getSections(false)[layer];
return section != null && !section.hasOnlyAir();
}

@Override
@SuppressWarnings("unchecked")
public synchronized boolean trim(boolean aggressive) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1152,6 +1152,13 @@ public boolean hasSection(int layer) {
return getSections(false)[layer] != null;
}

@Override
public boolean hasNonEmptySection(int layer) {
layer -= getMinSectionPosition();
LevelChunkSection section = getSections(false)[layer];
return section != null && !section.hasOnlyAir();
}

@Override
@SuppressWarnings("unchecked")
public synchronized boolean trim(boolean aggressive) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1155,6 +1155,13 @@ public boolean hasSection(int layer) {
return getSections(false)[layer] != null;
}

@Override
public boolean hasNonEmptySection(int layer) {
layer -= getMinSectionPosition();
LevelChunkSection section = getSections(false)[layer];
return section != null && !section.hasOnlyAir();
}

@Override
@SuppressWarnings("unchecked")
public synchronized boolean trim(boolean aggressive) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1150,6 +1150,13 @@ public boolean hasSection(int layer) {
return getSections(false)[layer] != null;
}

@Override
public boolean hasNonEmptySection(int layer) {
layer -= getMinSectionPosition();
LevelChunkSection section = getSections(false)[layer];
return section != null && !section.hasOnlyAir();
}

@Override
@SuppressWarnings("unchecked")
public synchronized boolean trim(boolean aggressive) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1151,6 +1151,13 @@ public boolean hasSection(int layer) {
return getSections(false)[layer] != null;
}

@Override
public boolean hasNonEmptySection(int layer) {
layer -= getMinSectionPosition();
LevelChunkSection section = getSections(false)[layer];
return section != null && !section.hasOnlyAir();
}

@Override
@SuppressWarnings("unchecked")
public synchronized boolean trim(boolean aggressive) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1149,6 +1149,13 @@ public boolean hasSection(int layer) {
return getSections(false)[layer] != null;
}

@Override
public boolean hasNonEmptySection(int layer) {
layer -= getMinSectionPosition();
LevelChunkSection section = getSections(false)[layer];
return section != null && !section.hasOnlyAir();
}

@Override
@SuppressWarnings("unchecked")
public synchronized boolean trim(boolean aggressive) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ public class HeightmapProcessor implements IBatchProcessor {
private static final HeightMapType[] TYPES = HeightMapType.values();
private static final int BLOCKS_PER_Y_SHIFT = 8; // log2(256)
private static final int BLOCKS_PER_Y = 256; // 16 x 16
private static final boolean[] COMPLETE = new boolean[BLOCKS_PER_Y];
private static final char[] AIR_LAYER = new char[4096];
private static final int NEEDED_UPDATES = TYPES.length * BLOCKS_PER_Y;

static {
Arrays.fill(COMPLETE, true);
Arrays.fill(AIR_LAYER, (char) BlockTypesCache.ReservedIDs.AIR);
}

Expand All @@ -49,13 +48,12 @@ private static int index(int y, int offset) {
public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) {
// each heightmap gets one 16*16 array
int[][] heightmaps = new int[TYPES.length][BLOCKS_PER_Y];
boolean[][] updated = new boolean[TYPES.length][BLOCKS_PER_Y];
int skip = 0;
int allSkipped = (1 << TYPES.length) - 1; // lowest types.length bits are set
layer:
byte[] updated = new byte[BLOCKS_PER_Y];
int updateCount = 0; // count updates, this way we know when we're finished
layerIter:
for (int layer = maxY >> 4; layer >= minY >> 4; layer--) {
boolean hasSectionSet = set.hasSection(layer);
boolean hasSectionGet = get.hasSection(layer);
boolean hasSectionSet = set.hasNonEmptySection(layer);
boolean hasSectionGet = get.hasNonEmptySection(layer);
if (!(hasSectionSet || hasSectionGet)) {
continue;
}
Expand All @@ -78,7 +76,7 @@ public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) {
if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) {
if (!hasSectionGet) {
if (!hasSectionSet) {
continue layer;
continue layerIter;
}
continue;
} else if (getSection == null) {
Expand All @@ -88,7 +86,7 @@ public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) {
|| Arrays.equals(getSection, AIR_LAYER)) {
hasSectionGet = false;
if (!hasSectionSet) {
continue layer;
continue layerIter;
}
continue;
}
Expand All @@ -103,30 +101,26 @@ public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) {
if (block == null) {
continue;
}
byte updateStateAtJ = updated[j];
for (int i = 0; i < TYPES.length; i++) {
if ((skip & (1 << i)) != 0) {
continue; // skip finished height map
int bitFlag = 1 << i;
if ((updateStateAtJ & bitFlag) != 0) {
continue; // skip finished height map at this column
}
HeightMapType type = TYPES[i];
// ignore if that position was already set
if (!updated[i][j] && type.includes(block)) {
if (type.includes(block)) {
// mc requires + 1, heightmaps are normalized internally, thus we need to "zero" them.
heightmaps[i][j] = ((layer - get.getMinSectionPosition()) << 4) + y + 1;
updated[i][j] = true; // mark as updated
updated[j] |= (byte) bitFlag; // mark as updated
if (++updateCount == NEEDED_UPDATES) {
break layerIter; // all heightmaps in all columns updated
}

}
}
}
}
for (int i = 0; i < updated.length; i++) {
if ((skip & (1 << i)) == 0 // if already true, skip array equality check
&& Arrays.equals(updated[i], COMPLETE)) {
skip |= 1 << i;
}
}
if (skip != allSkipped) {
continue;
}
break; // all maps are processed
}
for (int i = 0; i < TYPES.length; i++) {
set.setHeightMap(TYPES[i], heightmaps[i]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ public interface IBlocks extends Trimable {
*/
boolean hasSection(int layer);

/**
* {@return whether the chunk has a section that has any non-air/reserved blocks}
* This method might be conservative and return {@code true} even if the section is empty.
*
* @param layer the section's layer
* @since TODO
*/
default boolean hasNonEmptySection(int layer) {
return hasSection(layer);
}

/**
* Obtain the specified chunk section stored as an array of ordinals. Uses normal minecraft chunk-section position indices
* (length 4096). Operations synchronises on the section and will load the section into memory if not present. For chunk
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -882,6 +882,11 @@ public boolean hasSection(int layer) {
return chunkExisting != null && chunkExisting.hasSection(layer);
}

@Override
public boolean hasNonEmptySection(final int layer) {
return chunkExisting != null && chunkExisting.hasNonEmptySection(layer);
}

@Override
public synchronized void filterBlocks(Filter filter, ChunkFilterBlock block, @Nullable Region region, boolean full) {
final IChunkGet get = getOrCreateGet();
Expand Down
Loading