Micro optimize block placement

This commit is contained in:
TheMode 2021-07-19 23:41:28 +02:00
parent 111d5b9b66
commit 14e42f7907

View File

@ -4,14 +4,18 @@ import it.unimi.dsi.fastutil.shorts.Short2ShortLinkedOpenHashMap;
import it.unimi.dsi.fastutil.shorts.Short2ShortOpenHashMap; import it.unimi.dsi.fastutil.shorts.Short2ShortOpenHashMap;
import net.minestom.server.MinecraftServer; import net.minestom.server.MinecraftServer;
import net.minestom.server.instance.Chunk; import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.block.Block;
import net.minestom.server.utils.MathUtils; import net.minestom.server.utils.MathUtils;
import net.minestom.server.utils.clone.PublicCloneable; import net.minestom.server.utils.clone.PublicCloneable;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import static net.minestom.server.instance.Chunk.CHUNK_SECTION_SIZE; import static net.minestom.server.instance.Chunk.CHUNK_SECTION_SIZE;
public class Palette implements PublicCloneable<Palette> { /**
* Represents a palette storing a complete chunk section.
* <p>
* 0 is always interpreted as being air, reason being that the block array will be filled with it during initialization.
*/
public final class Palette implements PublicCloneable<Palette> {
/** /**
* The maximum bits per entry value. * The maximum bits per entry value.
@ -66,19 +70,16 @@ public class Palette implements PublicCloneable<Palette> {
} }
public void setBlockAt(int x, int y, int z, short blockId) { public void setBlockAt(int x, int y, int z, short blockId) {
final boolean placedAir = blockId == 0;
if (blocks.length == 0) { if (blocks.length == 0) {
if (blockId == 0) { if (placedAir) {
// 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
return; return;
} }
// Initialize the section // Initialize the section
blocks = new long[getSize(valuesPerLong)]; blocks = new long[getSize(valuesPerLong)];
} }
// Check if the new block is air, used for counting none air blocks.
final boolean isAir = Block.fromStateId(blockId).isAir();
// Change to palette value // Change to palette value
blockId = getPaletteIndex(blockId); blockId = getPaletteIndex(blockId);
@ -92,20 +93,20 @@ public class Palette implements PublicCloneable<Palette> {
{ {
final long clear = MAGIC_MASKS[bitsPerEntry]; final long clear = MAGIC_MASKS[bitsPerEntry];
final long value = block >> bitIndex & clear; final long oldBlock = block >> bitIndex & clear;
if (oldBlock == blockId)
return; // Trying to place the same block
final boolean currentAir = oldBlock == 0;
final boolean isCurrentAir = Block.fromStateId(fromPalette((short) value)).isAir(); final long indexClear = clear << bitIndex;
block |= indexClear;
block |= clear << bitIndex; block ^= indexClear;
block ^= clear << bitIndex;
block |= (long) blockId << bitIndex; block |= (long) blockId << bitIndex;
if (!isCurrentAir && isAir) { // The old block isn't air & the new block is. if (currentAir != placedAir) {
this.blockCount--; // Block count changed
} else if (isCurrentAir && !isAir) { // The old block is air & the new block isn't. this.blockCount += currentAir ? 1 : -1;
this.blockCount++; }
} // If both block are air or not air then don't change the value.
blocks[index] = block; blocks[index] = block;
} }
} }
@ -115,7 +116,6 @@ public class Palette implements PublicCloneable<Palette> {
// Section is not loaded, can only be air // Section is not loaded, can only be air
return -1; return -1;
} }
final int sectionIdentifier = getSectionIndex(x, y, z); final int sectionIdentifier = getSectionIndex(x, y, z);
final int index = sectionIdentifier / valuesPerLong; final int index = sectionIdentifier / valuesPerLong;
@ -225,20 +225,18 @@ public class Palette implements PublicCloneable<Palette> {
if (!hasPalette) { if (!hasPalette) {
return blockId; return blockId;
} }
final short value = blockPaletteMap.getOrDefault(blockId, (short)-1);
if (!blockPaletteMap.containsKey(blockId)) { if(value == -1){
// 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);
paletteBlockMap.put(paletteIndex, blockId); paletteBlockMap.put(paletteIndex, blockId);
blockPaletteMap.put(blockId, paletteIndex); blockPaletteMap.put(blockId, paletteIndex);
return paletteIndex; return paletteIndex;
} }
return value;
return blockPaletteMap.get(blockId);
} }
/** /**