mirror of
https://github.com/Minestom/Minestom.git
synced 2024-12-28 12:07:42 +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];
|
||||
|
||||
// palette index = block id
|
||||
private Short2ShortLinkedOpenHashMap paletteBlockMap = new Short2ShortLinkedOpenHashMap(CHUNK_SECTION_SIZE);
|
||||
// block id = palette index
|
||||
private Short2ShortOpenHashMap blockPaletteMap = new Short2ShortOpenHashMap(CHUNK_SECTION_SIZE);
|
||||
|
||||
{
|
||||
// Default value
|
||||
this.paletteBlockMap.put((short) 0, (short) 0);
|
||||
this.blockPaletteMap.put((short) 0, (short) 0);
|
||||
}
|
||||
// chunk section - palette index = block id
|
||||
private Short2ShortLinkedOpenHashMap[] paletteBlockMaps = new Short2ShortLinkedOpenHashMap[CHUNK_SECTION_COUNT];
|
||||
// chunk section - block id = palette index
|
||||
private Short2ShortOpenHashMap[] blockPaletteMaps = new Short2ShortOpenHashMap[CHUNK_SECTION_COUNT];
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param section the chunk section to get the palette from
|
||||
* @return the palette
|
||||
*/
|
||||
public short[] getPalette() {
|
||||
return paletteBlockMap.values().toShortArray();
|
||||
public short[] getPalette(int section) {
|
||||
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.sectionBlocks = sectionBlocks.clone();
|
||||
|
||||
paletteStorage.paletteBlockMap.clear();
|
||||
paletteStorage.blockPaletteMap.clear();
|
||||
|
||||
paletteStorage.paletteBlockMap.putAll(paletteBlockMap);
|
||||
paletteStorage.blockPaletteMap.putAll(blockPaletteMap);
|
||||
paletteStorage.paletteBlockMaps = paletteBlockMaps.clone();
|
||||
paletteStorage.blockPaletteMaps = blockPaletteMaps.clone();
|
||||
|
||||
return paletteStorage;
|
||||
}
|
||||
@ -134,23 +127,36 @@ public class PaletteStorage {
|
||||
* <p>
|
||||
* Also responsible for resizing the palette when full.
|
||||
*
|
||||
* @param section the chunk section
|
||||
* @param blockId the block id to convert
|
||||
* @return the palette index of {@code blockId}
|
||||
*/
|
||||
private short getPaletteIndex(short blockId) {
|
||||
private short getPaletteIndex(int section, short blockId) {
|
||||
if (!hasPalette) {
|
||||
return blockId;
|
||||
}
|
||||
|
||||
Short2ShortOpenHashMap blockPaletteMap = blockPaletteMaps[section];
|
||||
if (blockPaletteMap == null) {
|
||||
blockPaletteMap = createBlockPaletteMap();
|
||||
blockPaletteMaps[section] = blockPaletteMap;
|
||||
}
|
||||
|
||||
if (!blockPaletteMap.containsKey(blockId)) {
|
||||
Short2ShortLinkedOpenHashMap paletteBlockMap = paletteBlockMaps[section];
|
||||
if (paletteBlockMap == null) {
|
||||
paletteBlockMap = createPaletteBlockMap();
|
||||
paletteBlockMaps[section] = paletteBlockMap;
|
||||
}
|
||||
|
||||
// Resize the palette if full
|
||||
if (paletteBlockMap.size() >= getMaxPaletteSize()) {
|
||||
resize(bitsPerEntry + bitsIncrement);
|
||||
}
|
||||
|
||||
final short paletteIndex = (short) (paletteBlockMap.lastShortKey() + 1);
|
||||
this.paletteBlockMap.put(paletteIndex, blockId);
|
||||
this.blockPaletteMap.put(blockId, paletteIndex);
|
||||
paletteBlockMap.put(paletteIndex, blockId);
|
||||
blockPaletteMap.put(blockId, paletteIndex);
|
||||
return paletteIndex;
|
||||
}
|
||||
|
||||
@ -166,8 +172,8 @@ public class PaletteStorage {
|
||||
*/
|
||||
private synchronized void resize(int newBitsPerEntry) {
|
||||
PaletteStorage paletteStorageCache = new PaletteStorage(newBitsPerEntry, bitsIncrement);
|
||||
paletteStorageCache.paletteBlockMap = paletteBlockMap;
|
||||
paletteStorageCache.blockPaletteMap = blockPaletteMap;
|
||||
paletteStorageCache.paletteBlockMaps = paletteBlockMaps;
|
||||
paletteStorageCache.blockPaletteMaps = blockPaletteMaps;
|
||||
|
||||
for (int y = 0; y < Chunk.CHUNK_SIZE_Y; y++) {
|
||||
for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) {
|
||||
@ -207,8 +213,10 @@ public class PaletteStorage {
|
||||
x = toChunkCoordinate(x);
|
||||
z = toChunkCoordinate(z);
|
||||
|
||||
final int section = ChunkUtils.getSectionAt(y);
|
||||
|
||||
// Change to palette value
|
||||
blockId = paletteStorage.getPaletteIndex(blockId);
|
||||
blockId = paletteStorage.getPaletteIndex(section, blockId);
|
||||
|
||||
final int sectionIndex = getSectionIndex(x, y % CHUNK_SECTION_SIZE, z);
|
||||
|
||||
@ -218,8 +226,6 @@ public class PaletteStorage {
|
||||
final int index = sectionIndex / valuesPerLong;
|
||||
final int bitIndex = (sectionIndex % valuesPerLong) * bitsPerEntry;
|
||||
|
||||
final int section = ChunkUtils.getSectionAt(y);
|
||||
|
||||
if (paletteStorage.sectionBlocks[section].length == 0) {
|
||||
if (blockId == 0) {
|
||||
// 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
|
||||
return paletteStorage.hasPalette ?
|
||||
paletteStorage.paletteBlockMap.get((short) value) :
|
||||
paletteStorage.paletteBlockMaps[section].get((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.
|
||||
*
|
||||
|
@ -53,7 +53,7 @@ public class ChunkDataPacket implements ServerPacket {
|
||||
final long[] section = paletteStorage.getSectionBlocks()[i];
|
||||
if (section.length > 0) { // section contains at least one block
|
||||
mask |= 1 << i;
|
||||
Utils.writeBlocks(blocks, paletteStorage.getPalette(), section, paletteStorage.getBitsPerEntry());
|
||||
Utils.writeBlocks(blocks, paletteStorage.getPalette(i), section, paletteStorage.getBitsPerEntry());
|
||||
} else {
|
||||
mask |= 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user