mirror of
https://github.com/Minestom/Minestom.git
synced 2024-12-29 04:28:21 +01:00
Each chunk section gets its own palette, should decrease memory usage on vanilla-like worlds
This commit is contained in:
parent
e9d7de834f
commit
d3d3cc6553
@ -47,16 +47,10 @@ public class PaletteStorage {
|
|||||||
|
|
||||||
private long[][] sectionBlocks = new long[CHUNK_SECTION_COUNT][0];
|
private long[][] sectionBlocks = new long[CHUNK_SECTION_COUNT][0];
|
||||||
|
|
||||||
// palette index = block id
|
// chunk section - palette index = block id
|
||||||
private Short2ShortLinkedOpenHashMap paletteBlockMap = new Short2ShortLinkedOpenHashMap(CHUNK_SECTION_SIZE);
|
private Short2ShortLinkedOpenHashMap[] paletteBlockMaps = new Short2ShortLinkedOpenHashMap[CHUNK_SECTION_COUNT];
|
||||||
// block id = palette index
|
// chunk section - block id = palette index
|
||||||
private Short2ShortOpenHashMap blockPaletteMap = new Short2ShortOpenHashMap(CHUNK_SECTION_SIZE);
|
private Short2ShortOpenHashMap[] blockPaletteMaps = new Short2ShortOpenHashMap[CHUNK_SECTION_COUNT];
|
||||||
|
|
||||||
{
|
|
||||||
// Default value
|
|
||||||
this.paletteBlockMap.put((short) 0, (short) 0);
|
|
||||||
this.blockPaletteMap.put((short) 0, (short) 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new palette storage.
|
* Creates a new palette storage.
|
||||||
@ -100,10 +94,12 @@ public class PaletteStorage {
|
|||||||
/**
|
/**
|
||||||
* Gets the palette with the index and the block id as the value.
|
* Gets the palette with the index and the block id as the value.
|
||||||
*
|
*
|
||||||
|
* @param section the chunk section to get the palette from
|
||||||
* @return the palette
|
* @return the palette
|
||||||
*/
|
*/
|
||||||
public short[] getPalette() {
|
public short[] getPalette(int section) {
|
||||||
return paletteBlockMap.values().toShortArray();
|
Short2ShortLinkedOpenHashMap paletteBlockMap = paletteBlockMaps[section];
|
||||||
|
return paletteBlockMap != null ? paletteBlockMap.values().toShortArray() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -120,11 +116,8 @@ public class PaletteStorage {
|
|||||||
PaletteStorage paletteStorage = new PaletteStorage(bitsPerEntry, bitsIncrement);
|
PaletteStorage paletteStorage = new PaletteStorage(bitsPerEntry, bitsIncrement);
|
||||||
paletteStorage.sectionBlocks = sectionBlocks.clone();
|
paletteStorage.sectionBlocks = sectionBlocks.clone();
|
||||||
|
|
||||||
paletteStorage.paletteBlockMap.clear();
|
paletteStorage.paletteBlockMaps = paletteBlockMaps.clone();
|
||||||
paletteStorage.blockPaletteMap.clear();
|
paletteStorage.blockPaletteMaps = blockPaletteMaps.clone();
|
||||||
|
|
||||||
paletteStorage.paletteBlockMap.putAll(paletteBlockMap);
|
|
||||||
paletteStorage.blockPaletteMap.putAll(blockPaletteMap);
|
|
||||||
|
|
||||||
return paletteStorage;
|
return paletteStorage;
|
||||||
}
|
}
|
||||||
@ -134,23 +127,36 @@ public class PaletteStorage {
|
|||||||
* <p>
|
* <p>
|
||||||
* Also responsible for resizing the palette when full.
|
* Also responsible for resizing the palette when full.
|
||||||
*
|
*
|
||||||
|
* @param section the chunk section
|
||||||
* @param blockId the block id to convert
|
* @param blockId the block id to convert
|
||||||
* @return the palette index of {@code blockId}
|
* @return the palette index of {@code blockId}
|
||||||
*/
|
*/
|
||||||
private short getPaletteIndex(short blockId) {
|
private short getPaletteIndex(int section, short blockId) {
|
||||||
if (!hasPalette) {
|
if (!hasPalette) {
|
||||||
return blockId;
|
return blockId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Short2ShortOpenHashMap blockPaletteMap = blockPaletteMaps[section];
|
||||||
|
if (blockPaletteMap == null) {
|
||||||
|
blockPaletteMap = createBlockPaletteMap();
|
||||||
|
blockPaletteMaps[section] = blockPaletteMap;
|
||||||
|
}
|
||||||
|
|
||||||
if (!blockPaletteMap.containsKey(blockId)) {
|
if (!blockPaletteMap.containsKey(blockId)) {
|
||||||
|
Short2ShortLinkedOpenHashMap paletteBlockMap = paletteBlockMaps[section];
|
||||||
|
if (paletteBlockMap == null) {
|
||||||
|
paletteBlockMap = createPaletteBlockMap();
|
||||||
|
paletteBlockMaps[section] = paletteBlockMap;
|
||||||
|
}
|
||||||
|
|
||||||
// Resize the palette if full
|
// Resize the palette if full
|
||||||
if (paletteBlockMap.size() >= getMaxPaletteSize()) {
|
if (paletteBlockMap.size() >= getMaxPaletteSize()) {
|
||||||
resize(bitsPerEntry + bitsIncrement);
|
resize(bitsPerEntry + bitsIncrement);
|
||||||
}
|
}
|
||||||
|
|
||||||
final short paletteIndex = (short) (paletteBlockMap.lastShortKey() + 1);
|
final short paletteIndex = (short) (paletteBlockMap.lastShortKey() + 1);
|
||||||
this.paletteBlockMap.put(paletteIndex, blockId);
|
paletteBlockMap.put(paletteIndex, blockId);
|
||||||
this.blockPaletteMap.put(blockId, paletteIndex);
|
blockPaletteMap.put(blockId, paletteIndex);
|
||||||
return paletteIndex;
|
return paletteIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,8 +172,8 @@ public class PaletteStorage {
|
|||||||
*/
|
*/
|
||||||
private synchronized void resize(int newBitsPerEntry) {
|
private synchronized void resize(int newBitsPerEntry) {
|
||||||
PaletteStorage paletteStorageCache = new PaletteStorage(newBitsPerEntry, bitsIncrement);
|
PaletteStorage paletteStorageCache = new PaletteStorage(newBitsPerEntry, bitsIncrement);
|
||||||
paletteStorageCache.paletteBlockMap = paletteBlockMap;
|
paletteStorageCache.paletteBlockMaps = paletteBlockMaps;
|
||||||
paletteStorageCache.blockPaletteMap = blockPaletteMap;
|
paletteStorageCache.blockPaletteMaps = blockPaletteMaps;
|
||||||
|
|
||||||
for (int y = 0; y < Chunk.CHUNK_SIZE_Y; y++) {
|
for (int y = 0; y < Chunk.CHUNK_SIZE_Y; y++) {
|
||||||
for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) {
|
for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) {
|
||||||
@ -207,8 +213,10 @@ public class PaletteStorage {
|
|||||||
x = toChunkCoordinate(x);
|
x = toChunkCoordinate(x);
|
||||||
z = toChunkCoordinate(z);
|
z = toChunkCoordinate(z);
|
||||||
|
|
||||||
|
final int section = ChunkUtils.getSectionAt(y);
|
||||||
|
|
||||||
// Change to palette value
|
// Change to palette value
|
||||||
blockId = paletteStorage.getPaletteIndex(blockId);
|
blockId = paletteStorage.getPaletteIndex(section, blockId);
|
||||||
|
|
||||||
final int sectionIndex = getSectionIndex(x, y % CHUNK_SECTION_SIZE, z);
|
final int sectionIndex = getSectionIndex(x, y % CHUNK_SECTION_SIZE, z);
|
||||||
|
|
||||||
@ -218,8 +226,6 @@ public class PaletteStorage {
|
|||||||
final int index = sectionIndex / valuesPerLong;
|
final int index = sectionIndex / valuesPerLong;
|
||||||
final int bitIndex = (sectionIndex % valuesPerLong) * bitsPerEntry;
|
final int bitIndex = (sectionIndex % valuesPerLong) * bitsPerEntry;
|
||||||
|
|
||||||
final int section = ChunkUtils.getSectionAt(y);
|
|
||||||
|
|
||||||
if (paletteStorage.sectionBlocks[section].length == 0) {
|
if (paletteStorage.sectionBlocks[section].length == 0) {
|
||||||
if (blockId == 0) {
|
if (blockId == 0) {
|
||||||
// Section is empty and method is trying to place an air block, stop unnecessary computation
|
// Section is empty and method is trying to place an air block, stop unnecessary computation
|
||||||
@ -269,10 +275,24 @@ public class PaletteStorage {
|
|||||||
|
|
||||||
// Change to palette value and return
|
// Change to palette value and return
|
||||||
return paletteStorage.hasPalette ?
|
return paletteStorage.hasPalette ?
|
||||||
paletteStorage.paletteBlockMap.get((short) value) :
|
paletteStorage.paletteBlockMaps[section].get((short) value) :
|
||||||
(short) value;
|
(short) value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Short2ShortLinkedOpenHashMap createPaletteBlockMap() {
|
||||||
|
Short2ShortLinkedOpenHashMap map = new Short2ShortLinkedOpenHashMap(CHUNK_SECTION_SIZE);
|
||||||
|
map.put((short) 0, (short) 0);
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Short2ShortOpenHashMap createBlockPaletteMap() {
|
||||||
|
Short2ShortOpenHashMap map = new Short2ShortOpenHashMap(CHUNK_SECTION_SIZE);
|
||||||
|
map.put((short) 0, (short) 0);
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the array length of one section based on the number of values which can be stored in one long.
|
* Gets the array length of one section based on the number of values which can be stored in one long.
|
||||||
*
|
*
|
||||||
|
@ -53,7 +53,7 @@ public class ChunkDataPacket implements ServerPacket {
|
|||||||
final long[] section = paletteStorage.getSectionBlocks()[i];
|
final long[] section = paletteStorage.getSectionBlocks()[i];
|
||||||
if (section.length > 0) { // section contains at least one block
|
if (section.length > 0) { // section contains at least one block
|
||||||
mask |= 1 << i;
|
mask |= 1 << i;
|
||||||
Utils.writeBlocks(blocks, paletteStorage.getPalette(), section, paletteStorage.getBitsPerEntry());
|
Utils.writeBlocks(blocks, paletteStorage.getPalette(i), section, paletteStorage.getBitsPerEntry());
|
||||||
} else {
|
} else {
|
||||||
mask |= 0;
|
mask |= 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user