make chunk storage a map

This commit is contained in:
Sen 2025-05-21 15:31:50 +02:00
parent 5e2b36dc82
commit 2dd83c61dc
9 changed files with 144 additions and 328 deletions

View file

@ -2,6 +2,7 @@ package common.packet;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import common.collect.Lists;
import common.network.IClientPlayer;
@ -21,12 +22,12 @@ public class SPacketChunkData implements Packet<IClientPlayer>
{
}
public SPacketChunkData(Chunk chunkIn, boolean biomes, int segUpdate, int[] extend)
public SPacketChunkData(Chunk chunkIn, boolean biomes, int[] extend)
{
this.chunkX = chunkIn.xPos;
this.chunkZ = chunkIn.zPos;
this.biomes = biomes;
this.extractedData = getExtractedData(chunkIn, biomes, !chunkIn.getWorld().dimension.hasNoLight(), segUpdate, extend);
this.extractedData = getExtractedData(chunkIn, biomes, !chunkIn.getWorld().dimension.hasNoLight(), extend);
}
/**
@ -38,7 +39,6 @@ public class SPacketChunkData implements Packet<IClientPlayer>
this.chunkZ = buf.readInt();
this.biomes = buf.readBoolean();
this.extractedData = new SPacketChunkData.Extracted();
this.extractedData.dataSize = buf.readInt();
this.extractedData.data = buf.readByteArray();
this.extractedData.extend = new int[buf.readVarIntFromBuffer()];
for(int z = 0; z < this.extractedData.extend.length; z++) {
@ -54,7 +54,6 @@ public class SPacketChunkData implements Packet<IClientPlayer>
buf.writeInt(this.chunkX);
buf.writeInt(this.chunkZ);
buf.writeBoolean(this.biomes);
buf.writeInt(this.extractedData.dataSize);
buf.writeByteArray(this.extractedData.data);
buf.writeVarIntToBuffer(this.extractedData.extend.length);
for(int z = 0; z < this.extractedData.extend.length; z++) {
@ -84,55 +83,32 @@ public class SPacketChunkData implements Packet<IClientPlayer>
return i + j + k + l;
}
public static SPacketChunkData.Extracted getExtractedData(Chunk chunk, boolean biomes, boolean overworld, int segUpdate, int[] extend)
public static SPacketChunkData.Extracted getExtractedData(Chunk chunk, boolean biomes, boolean overworld, int[] extend)
{
BlockArray[] aextendedblockstorage = chunk.getStorage();
BlockArray[] down = chunk.getStorageDown();
BlockArray[] up = chunk.getStorageUp();
Set<BlockArray> aextendedblockstorage = chunk.getStorage();
SPacketChunkData.Extracted s21packetchunkdata$extracted = new SPacketChunkData.Extracted();
List<BlockArray> list = Lists.<BlockArray>newArrayList();
for (int i = 0; i < aextendedblockstorage.length; ++i)
{
BlockArray extendedblockstorage = aextendedblockstorage[i];
if (extendedblockstorage != null && (!biomes || !extendedblockstorage.isEmpty()) && (segUpdate & 1 << i) != 0)
{
s21packetchunkdata$extracted.dataSize |= 1 << i;
list.add(extendedblockstorage);
}
}
int epos = list.size();
if(extend == null) {
if(down != null) {
for(BlockArray arr : down) {
if(arr != null && (!biomes || !arr.isEmpty()))
list.add(arr);
}
}
if(up != null) {
for(BlockArray arr : up) {
if(arr != null && (!biomes || !arr.isEmpty()))
list.add(arr);
}
}
for(BlockArray arr : aextendedblockstorage) {
if(arr != null && (!biomes || !arr.isEmpty()))
list.add(arr);
}
}
else {
for(int cy : extend) {
if(cy < 0 || cy >= aextendedblockstorage.length) {
BlockArray arr = chunk.getArray(cy);
if(arr != null && (!biomes || !arr.isEmpty()))
list.add(arr);
}
BlockArray arr = chunk.getArray(cy);
if(arr != null && (!biomes || !arr.isEmpty()))
list.add(arr);
}
}
extend = new int[list.size() - epos];
extend = new int[list.size()];
for(int z = 0; z < extend.length; z++) {
extend[z] = list.get(z + epos).getY() >> 4;
extend[z] = list.get(z).getY() >> 4;
}
s21packetchunkdata$extracted.extend = extend;
s21packetchunkdata$extracted.data = new byte[getSize(Integer.bitCount(s21packetchunkdata$extracted.dataSize) + extend.length, overworld, biomes)];
s21packetchunkdata$extracted.data = new byte[getSize(extend.length, overworld, biomes)];
int j = 0;
for (BlockArray extendedblockstorage1 : list)
@ -182,12 +158,7 @@ public class SPacketChunkData implements Packet<IClientPlayer>
{
return this.chunkZ;
}
public int getExtractedSize()
{
return this.extractedData.dataSize;
}
public int[] getExtractedExtend()
{
return this.extractedData.extend;
@ -201,7 +172,6 @@ public class SPacketChunkData implements Packet<IClientPlayer>
public static class Extracted
{
public byte[] data;
public int dataSize;
public int[] extend;
}
}

View file

@ -30,7 +30,7 @@ public class SPacketMapChunkBulk implements Packet<IClientPlayer>
for (int j = 0; j < i; ++j)
{
Chunk chunk = (Chunk)chunks.get(j);
SPacketChunkData.Extracted s21packetchunkdata$extracted = SPacketChunkData.getExtractedData(chunk, true, this.isOverworld, 0xffffffff, null);
SPacketChunkData.Extracted s21packetchunkdata$extracted = SPacketChunkData.getExtractedData(chunk, true, this.isOverworld, null);
this.xPositions[j] = chunk.xPos;
this.zPositions[j] = chunk.zPos;
this.chunksData[j] = s21packetchunkdata$extracted;
@ -53,12 +53,11 @@ public class SPacketMapChunkBulk implements Packet<IClientPlayer>
this.xPositions[j] = buf.readInt();
this.zPositions[j] = buf.readInt();
this.chunksData[j] = new SPacketChunkData.Extracted();
this.chunksData[j].dataSize = buf.readInt();
this.chunksData[j].extend = new int[buf.readVarIntFromBuffer()];
for(int z = 0; z < this.chunksData[j].extend.length; z++) {
this.chunksData[j].extend[z] = buf.readVarIntFromBuffer();
}
this.chunksData[j].data = new byte[SPacketChunkData.getSize(Integer.bitCount(this.chunksData[j].dataSize) + this.chunksData[j].extend.length, this.isOverworld, true)];
this.chunksData[j].data = new byte[SPacketChunkData.getSize(this.chunksData[j].extend.length, this.isOverworld, true)];
}
for (int k = 0; k < i; ++k)
@ -79,7 +78,6 @@ public class SPacketMapChunkBulk implements Packet<IClientPlayer>
{
buf.writeInt(this.xPositions[i]);
buf.writeInt(this.zPositions[i]);
buf.writeInt(this.chunksData[i].dataSize);
buf.writeVarIntToBuffer(this.chunksData[i].extend.length);
for(int z = 0; z < this.chunksData[i].extend.length; z++) {
buf.writeVarIntToBuffer(this.chunksData[i].extend[z]);
@ -119,12 +117,7 @@ public class SPacketMapChunkBulk implements Packet<IClientPlayer>
{
return this.chunksData[p_149256_1_].data;
}
public int getChunkSize(int p_179754_1_)
{
return this.chunksData[p_179754_1_].dataSize;
}
public int[] getChunkExtend(int index)
{
return this.chunksData[index].extend;

View file

@ -127,4 +127,12 @@ public class BlockArray {
public void setSkylight(NibbleArray data) {
this.skylight = data;
}
public int hashCode() {
return this.yBase >> 4;
}
public boolean equals(Object other) {
return other instanceof BlockArray && ((BlockArray)other).yBase == this.yBase;
}
}

View file

@ -3,6 +3,7 @@ package common.world;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.function.Predicate;
@ -10,6 +11,7 @@ import common.biome.Biome;
import common.block.Block;
import common.block.ITileEntityProvider;
import common.collect.Maps;
import common.collect.Sets;
import common.entity.Entity;
import common.init.BlockRegistry;
import common.init.Blocks;
@ -23,6 +25,7 @@ import common.util.ChunkPos;
import common.util.ClassInheritanceMultiMap;
import common.util.ExtMath;
import common.util.Facing;
import common.util.IntHashMap;
import common.util.NibbleArray;
import common.worldgen.BiomeGenerator;
import common.worldgen.DebugStates;
@ -33,7 +36,8 @@ public class Chunk {
private final World world;
private final State filler;
private final Block fillerBlock;
private final BlockArray[] blocks = new BlockArray[32];
private final IntHashMap<BlockArray> blocks = new IntHashMap();
private final Set<BlockArray> blockList = Sets.newHashSet();
private final byte[] biomes = new byte[256];
private final int[] precHeight = new int[256];
private final boolean[] updateSky = new boolean[256];
@ -55,8 +59,6 @@ public class Chunk {
private int top = Integer.MIN_VALUE;
private long lastSave;
private long inhabited;
private BlockArray[] extendDown;
private BlockArray[] extendUp;
public Chunk(World world, int x, int z) {
this.world = world;
@ -80,37 +82,49 @@ public class Chunk {
State state = BlockRegistry.STATEMAP.getByValue(data[bx << 4 | bz | by << 8]);
if(state != null && state.getBlock().getMaterial() != Material.air) {
int y = by >> 4;
if(this.blocks[y] == null)
this.blocks[y] = new BlockArray(y << 4, sky, null);
this.blocks[y].set(bx, by & 15, bz, state);
BlockArray arr = this.getArray(y);
if(arr == null) {
arr = new BlockArray(y << 4, sky, null);
this.setArray(arr);
}
arr.set(bx, by & 15, bz, state);
}
}
}
}
if(base != null) {
if(this.blocks[0] == null)
this.blocks[0] = new BlockArray(0, sky, null);
BlockArray arr = this.getArray(0);
if(arr == null) {
arr = new BlockArray(0, sky, null);
this.setArray(arr);
}
for(int bx = 0; bx < 16; ++bx) {
for(int bz = 0; bz < 16; ++bz) {
for(int by = 0; by < 5; ++by) {
if(by <= rand.zrange(5))
this.blocks[0].set(bx, by, bz, base);
arr.set(bx, by, bz, base);
}
}
}
}
if(ceil != null) {
int y = (height - 1) >> 4;
if(this.blocks[y] == null)
this.blocks[y] = new BlockArray(y << 4, sky, null);
BlockArray arr = this.getArray(y);
if(arr == null) {
arr = new BlockArray(y << 4, sky, null);
this.setArray(arr);
}
y = (height - 5) >> 4;
if(this.blocks[y] == null)
this.blocks[y] = new BlockArray(y << 4, sky, null);
arr = this.getArray(y);
if(arr == null) {
arr = new BlockArray(y << 4, sky, null);
this.setArray(arr);
}
for(int bx = 0; bx < 16; ++bx) {
for(int bz = 0; bz < 16; ++bz) {
for(int by = height - 1; by >= height - 5; --by) {
if(by >= (height - 1) - rand.zrange(5))
this.blocks[by >> 4].set(bx, by & 15, bz, ceil);
this.getArray(by >> 4).set(bx, by & 15, bz, ceil);
}
}
}
@ -133,47 +147,7 @@ public class Chunk {
public int getHeight(int x, int z) {
return this.height[z << 4 | x];
}
private int findTopSegment() {
if(this.extendUp != null) {
for(int y = this.extendUp.length - 1; y >= 0; --y) {
if(this.extendUp[y] != null)
return this.extendUp[y].getY();
}
}
for(int y = this.blocks.length - 1; y >= 0; --y) {
if(this.blocks[y] != null)
return this.blocks[y].getY();
}
if(this.extendDown != null) {
for(int y = this.extendDown.length - 1; y >= 0; --y) {
if(this.extendDown[y] != null)
return this.extendDown[y].getY();
}
}
return Integer.MIN_VALUE;
}
private int findBottomSegment() {
if(this.extendDown != null) {
for(int y = 0; y < this.extendDown.length; ++y) {
if(this.extendDown[y] != null)
return this.extendDown[y].getY();
}
}
for(int y = 0; y < this.blocks.length; ++y) {
if(this.blocks[y] != null)
return this.blocks[y].getY();
}
if(this.extendUp != null) {
for(int y = 0; y < this.extendUp.length; ++y) {
if(this.extendUp[y] != null)
return this.extendUp[y].getY();
}
}
return Integer.MAX_VALUE;
}
public int getTopSegment() {
return this.top;
}
@ -182,50 +156,28 @@ public class Chunk {
return this.bottom;
}
public BlockArray[] getStorage() {
return this.blocks;
}
public BlockArray[] getStorageDown() {
return this.extendDown;
}
public BlockArray[] getStorageUp() {
return this.extendUp;
public Set<BlockArray> getStorage() {
return this.blockList;
}
public BlockArray getArray(int y) {
return y >= 0 && y < this.blocks.length ? this.blocks[y] : (y < 0 ? (this.extendDown == null || -y > this.extendDown.length ? null : this.extendDown[this.extendDown.length + y]) : (this.extendUp == null || y - this.blocks.length >= this.extendUp.length ? null : this.extendUp[y - this.blocks.length]));
return this.blocks.lookup(y);
}
private void setArray(int y, BlockArray array) {
if(y >= 0 && y < this.blocks.length) {
this.blocks[y] = array;
}
else if(y < 0) {
if(this.extendDown == null) {
this.extendDown = new BlockArray[-y];
}
else if(this.extendDown.length < -y) {
BlockArray[] extendDown = this.extendDown;
this.extendDown = new BlockArray[-y];
System.arraycopy(extendDown, 0, this.extendDown, -y - extendDown.length, extendDown.length);
}
this.extendDown[this.extendDown.length + y] = array;
}
else {
if(this.extendUp == null) {
this.extendUp = new BlockArray[1 + y - this.blocks.length];
}
else if(this.extendUp.length <= y - this.blocks.length) {
BlockArray[] extendUp = this.extendUp;
this.extendUp = new BlockArray[1 + y - this.blocks.length];
System.arraycopy(extendUp, 0, this.extendUp, 0, extendUp.length);
}
this.extendUp[y - this.blocks.length] = array;
}
this.bottom = this.findBottomSegment();
this.top = this.findTopSegment();
private void setArray(BlockArray array) {
int y = array.getY() >> 4;
this.blocks.addKey(y, array);
this.blockList.add(array);
y <<= 4;
this.bottom = y < this.bottom ? y : this.bottom;
this.top = y > this.top ? y : this.top;
}
private void clearArrays() {
this.blocks.clearMap();
this.blockList.clear();
this.bottom = Integer.MAX_VALUE;
this.top = Integer.MIN_VALUE;
}
protected void genHeights() {
@ -475,19 +427,8 @@ public class Chunk {
}
private Block getBlock0(int x, int y, int z) {
if(y >= 0 && y >> 4 < this.blocks.length) {
BlockArray stor = this.blocks[y >> 4];
return stor != null ? stor.getBlock(x, y & 15, z) : Blocks.air;
}
else if(y < 0 && this.extendDown != null && -(y >> 4) <= this.extendDown.length) {
BlockArray stor = this.extendDown[this.extendDown.length + (y >> 4)];
return stor != null ? stor.getBlock(x, y & 15, z) : this.fillerBlock;
}
else if(y >> 4 >= this.blocks.length && this.extendUp != null && (y >> 4) - this.blocks.length < this.extendUp.length) {
BlockArray stor = this.extendUp[(y >> 4) - this.blocks.length];
return stor != null ? stor.getBlock(x, y & 15, z) : Blocks.air;
}
return y < 0 ? this.fillerBlock : Blocks.air;
BlockArray stor = this.getArray(y >> 4);
return stor != null ? stor.getBlock(x, y & 15, z) : (y < 0 ? this.fillerBlock : Blocks.air);
}
public State getState(BlockPos pos) {
@ -496,19 +437,8 @@ public class Chunk {
return state == null ? Blocks.air.getState() : state;
}
if(pos.getY() >= 0 && pos.getY() >> 4 < this.blocks.length) {
BlockArray stor = this.blocks[pos.getY() >> 4];
return stor != null ? stor.get(pos.getX() & 15, pos.getY() & 15, pos.getZ() & 15) : Blocks.air.getState();
}
else if(pos.getY() < 0 && this.extendDown != null && -(pos.getY() >> 4) <= this.extendDown.length) {
BlockArray stor = this.extendDown[this.extendDown.length + (pos.getY() >> 4)];
return stor != null ? stor.get(pos.getX() & 15, pos.getY() & 15, pos.getZ() & 15) : this.filler;
}
else if(pos.getY() >> 4 >= this.blocks.length && this.extendUp != null && (pos.getY() >> 4) - this.blocks.length < this.extendUp.length) {
BlockArray stor = this.extendUp[(pos.getY() >> 4) - this.blocks.length];
return stor != null ? stor.get(pos.getX() & 15, pos.getY() & 15, pos.getZ() & 15) : Blocks.air.getState();
}
return pos.getY() < 0 ? this.filler : Blocks.air.getState();
BlockArray stor = this.getArray(pos.getY() >> 4);
return stor != null ? stor.get(pos.getX() & 15, pos.getY() & 15, pos.getZ() & 15) : (pos.getY() < 0 ? this.filler : Blocks.air.getState());
}
public Block getBlock(BlockPos pos) {
@ -543,7 +473,7 @@ public class Chunk {
}
stor = new BlockArray(y >> 4 << 4, !this.world.dimension.hasNoLight(), y < 0 ? this.filler : null);
this.setArray(y >> 4, stor);
this.setArray(stor);
up = y >= h;
}
@ -632,7 +562,7 @@ public class Chunk {
if(stor == null) {
stor = new BlockArray(y >> 4 << 4, !this.world.dimension.hasNoLight(), y < 0 ? this.filler : null);
this.setArray(y >> 4, stor);
this.setArray(stor);
this.genSkyLight();
}
@ -948,52 +878,24 @@ public class Chunk {
return true;
}
public void setStorage(BlockArray[] arrays, BlockArray[] down, BlockArray[] up) {
if(this.blocks.length != arrays.length) {
Log.JNI.warn("Konnte Sektionen des Chunks nicht setzen, Länge des Arrays ist " + arrays.length + " statt "
+ this.blocks.length);
}
else {
for(int n = 0; n < this.blocks.length; ++n) {
this.blocks[n] = arrays[n];
}
this.extendDown = down;
this.extendUp = up;
this.bottom = this.findBottomSegment();
this.top = this.findTopSegment();
public void setStorage(BlockArray[] data) {
for(BlockArray arr : data) {
this.setArray(arr);
}
}
public void setData(byte[] data, int update, int[] extend, boolean biomes) {
public void setData(byte[] data, int[] extend, boolean biomes) {
int pos = 0;
boolean sky = !this.world.dimension.hasNoLight();
for(int n = 0; n < this.blocks.length; ++n) {
if((update & 1 << n) != 0) {
if(this.blocks[n] == null) {
this.blocks[n] = new BlockArray(n << 4, sky, null);
}
char[] blocks = this.blocks[n].getData();
for(int k = 0; k < blocks.length; ++k) {
blocks[k] = (char)((data[pos + 1] & 255) << 8 | data[pos] & 255);
pos += 2;
}
}
else if(biomes && this.blocks[n] != null) {
this.blocks[n] = null;
}
}
if(biomes) {
this.extendDown = null;
this.extendUp = null;
this.clearArrays();
}
for(int cy : extend) {
BlockArray arr = this.getArray(cy);
if(arr == null) {
arr = new BlockArray(cy << 4, sky, null);
this.setArray(cy, arr);
this.setArray(arr);
}
char[] blocks = arr.getData();
@ -1004,13 +906,6 @@ public class Chunk {
}
}
for(int n = 0; n < this.blocks.length; ++n) {
if((update & 1 << n) != 0 && this.blocks[n] != null) {
NibbleArray light = this.blocks[n].getBlocklight();
System.arraycopy(data, pos, light.getData(), 0, light.getData().length);
pos += light.getData().length;
}
}
for(int cy : extend) {
BlockArray arr = this.getArray(cy);
if(arr != null) {
@ -1021,13 +916,6 @@ public class Chunk {
}
if(sky) {
for(int n = 0; n < this.blocks.length; ++n) {
if((update & 1 << n) != 0 && this.blocks[n] != null) {
NibbleArray slight = this.blocks[n].getSkylight();
System.arraycopy(data, pos, slight.getData(), 0, slight.getData().length);
pos += slight.getData().length;
}
}
for(int cy : extend) {
BlockArray arr = this.getArray(cy);
if(arr != null) {
@ -1040,17 +928,8 @@ public class Chunk {
if(biomes) {
System.arraycopy(data, pos, this.biomes, 0, this.biomes.length);
// int unk = pos + this.biomes.length;
}
this.bottom = this.findBottomSegment();
this.top = this.findTopSegment();
for(int n = 0; n < this.blocks.length; ++n) {
if(this.blocks[n] != null && (update & 1 << n) != 0) {
this.blocks[n].update();
}
}
for(int cy : extend) {
BlockArray arr = this.getArray(cy);
if(arr != null) {