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

@ -756,7 +756,7 @@ public class ClientPlayer extends NetHandler implements IClientPlayer
if (packetIn.hasBiomes()) if (packetIn.hasBiomes())
{ {
if (packetIn.getExtractedSize() == 0) if (packetIn.getExtractedExtend().length == 0)
{ {
this.clientWorldController.doPreChunk(packetIn.getChunkX(), packetIn.getChunkZ(), false); this.clientWorldController.doPreChunk(packetIn.getChunkX(), packetIn.getChunkZ(), false);
return; return;
@ -767,7 +767,7 @@ public class ClientPlayer extends NetHandler implements IClientPlayer
// this.clientWorldController.invalidateBlockReceiveRegion(packetIn.getChunkX() << 4, 0, packetIn.getChunkZ() << 4, (packetIn.getChunkX() << 4) + 15, 512, (packetIn.getChunkZ() << 4) + 15); // this.clientWorldController.invalidateBlockReceiveRegion(packetIn.getChunkX() << 4, 0, packetIn.getChunkZ() << 4, (packetIn.getChunkX() << 4) + 15, 512, (packetIn.getChunkZ() << 4) + 15);
Chunk chunk = this.clientWorldController.getChunk(packetIn.getChunkX(), packetIn.getChunkZ()); Chunk chunk = this.clientWorldController.getChunk(packetIn.getChunkX(), packetIn.getChunkZ());
chunk.setData(packetIn.getExtractedDataBytes(), packetIn.getExtractedSize(), packetIn.getExtractedExtend(), packetIn.hasBiomes()); chunk.setData(packetIn.getExtractedDataBytes(), packetIn.getExtractedExtend(), packetIn.hasBiomes());
this.clientWorldController.markBlockRangeForRenderUpdate(packetIn.getChunkX() << 4, -World.MAX_SIZE_Y, packetIn.getChunkZ() << 4, (packetIn.getChunkX() << 4) + 15, World.MAX_SIZE_Y, (packetIn.getChunkZ() << 4) + 15); this.clientWorldController.markBlockRangeForRenderUpdate(packetIn.getChunkX() << 4, -World.MAX_SIZE_Y, packetIn.getChunkZ() << 4, (packetIn.getChunkX() << 4) + 15, World.MAX_SIZE_Y, (packetIn.getChunkZ() << 4) + 15);
if (!packetIn.hasBiomes() || this.clientWorldController.dimension.hasNoLight()) // TODO: check if (!packetIn.hasBiomes() || this.clientWorldController.dimension.hasNoLight()) // TODO: check
@ -1413,7 +1413,7 @@ public class ClientPlayer extends NetHandler implements IClientPlayer
this.clientWorldController.doPreChunk(j, k, true); this.clientWorldController.doPreChunk(j, k, true);
// this.clientWorldController.invalidateBlockReceiveRegion(j << 4, 0, k << 4, (j << 4) + 15, 512, (k << 4) + 15); // this.clientWorldController.invalidateBlockReceiveRegion(j << 4, 0, k << 4, (j << 4) + 15, 512, (k << 4) + 15);
Chunk chunk = this.clientWorldController.getChunk(j, k); Chunk chunk = this.clientWorldController.getChunk(j, k);
chunk.setData(packetIn.getChunkBytes(i), packetIn.getChunkSize(i), packetIn.getChunkExtend(i), true); chunk.setData(packetIn.getChunkBytes(i), packetIn.getChunkExtend(i), true);
this.clientWorldController.markBlockRangeForRenderUpdate(j << 4, -World.MAX_SIZE_Y, k << 4, (j << 4) + 15, World.MAX_SIZE_Y, (k << 4) + 15); this.clientWorldController.markBlockRangeForRenderUpdate(j << 4, -World.MAX_SIZE_Y, k << 4, (j << 4) + 15, World.MAX_SIZE_Y, (k << 4) + 15);
if (this.clientWorldController.dimension.hasNoLight()) // TODO: check if (this.clientWorldController.dimension.hasNoLight()) // TODO: check

View file

@ -105,7 +105,7 @@ public class EmptyChunk extends Chunk {
return true; return true;
} }
public void setData(byte[] data, int update, int[] extend, boolean biomes) { public void setData(byte[] data, int[] extend, boolean biomes) {
} }
public Biome getBiome(BlockPos pos, BiomeGenerator gen) { public Biome getBiome(BlockPos pos, BiomeGenerator gen) {

View file

@ -2,6 +2,7 @@ package common.packet;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Set;
import common.collect.Lists; import common.collect.Lists;
import common.network.IClientPlayer; 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.chunkX = chunkIn.xPos;
this.chunkZ = chunkIn.zPos; this.chunkZ = chunkIn.zPos;
this.biomes = biomes; 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.chunkZ = buf.readInt();
this.biomes = buf.readBoolean(); this.biomes = buf.readBoolean();
this.extractedData = new SPacketChunkData.Extracted(); this.extractedData = new SPacketChunkData.Extracted();
this.extractedData.dataSize = buf.readInt();
this.extractedData.data = buf.readByteArray(); this.extractedData.data = buf.readByteArray();
this.extractedData.extend = new int[buf.readVarIntFromBuffer()]; this.extractedData.extend = new int[buf.readVarIntFromBuffer()];
for(int z = 0; z < this.extractedData.extend.length; z++) { 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.chunkX);
buf.writeInt(this.chunkZ); buf.writeInt(this.chunkZ);
buf.writeBoolean(this.biomes); buf.writeBoolean(this.biomes);
buf.writeInt(this.extractedData.dataSize);
buf.writeByteArray(this.extractedData.data); buf.writeByteArray(this.extractedData.data);
buf.writeVarIntToBuffer(this.extractedData.extend.length); buf.writeVarIntToBuffer(this.extractedData.extend.length);
for(int z = 0; z < this.extractedData.extend.length; z++) { 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; 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(); Set<BlockArray> aextendedblockstorage = chunk.getStorage();
BlockArray[] down = chunk.getStorageDown();
BlockArray[] up = chunk.getStorageUp();
SPacketChunkData.Extracted s21packetchunkdata$extracted = new SPacketChunkData.Extracted(); SPacketChunkData.Extracted s21packetchunkdata$extracted = new SPacketChunkData.Extracted();
List<BlockArray> list = Lists.<BlockArray>newArrayList(); 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(extend == null) {
if(down != null) { for(BlockArray arr : aextendedblockstorage) {
for(BlockArray arr : down) {
if(arr != null && (!biomes || !arr.isEmpty())) if(arr != null && (!biomes || !arr.isEmpty()))
list.add(arr); list.add(arr);
} }
} }
if(up != null) {
for(BlockArray arr : up) {
if(arr != null && (!biomes || !arr.isEmpty()))
list.add(arr);
}
}
}
else { else {
for(int cy : extend) { for(int cy : extend) {
if(cy < 0 || cy >= aextendedblockstorage.length) {
BlockArray arr = chunk.getArray(cy); BlockArray arr = chunk.getArray(cy);
if(arr != null && (!biomes || !arr.isEmpty())) if(arr != null && (!biomes || !arr.isEmpty()))
list.add(arr); list.add(arr);
} }
} }
} extend = new int[list.size()];
extend = new int[list.size() - epos];
for(int z = 0; z < extend.length; z++) { 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.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; int j = 0;
for (BlockArray extendedblockstorage1 : list) for (BlockArray extendedblockstorage1 : list)
@ -183,11 +159,6 @@ public class SPacketChunkData implements Packet<IClientPlayer>
return this.chunkZ; return this.chunkZ;
} }
public int getExtractedSize()
{
return this.extractedData.dataSize;
}
public int[] getExtractedExtend() public int[] getExtractedExtend()
{ {
return this.extractedData.extend; return this.extractedData.extend;
@ -201,7 +172,6 @@ public class SPacketChunkData implements Packet<IClientPlayer>
public static class Extracted public static class Extracted
{ {
public byte[] data; public byte[] data;
public int dataSize;
public int[] extend; public int[] extend;
} }
} }

View file

@ -30,7 +30,7 @@ public class SPacketMapChunkBulk implements Packet<IClientPlayer>
for (int j = 0; j < i; ++j) for (int j = 0; j < i; ++j)
{ {
Chunk chunk = (Chunk)chunks.get(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.xPositions[j] = chunk.xPos;
this.zPositions[j] = chunk.zPos; this.zPositions[j] = chunk.zPos;
this.chunksData[j] = s21packetchunkdata$extracted; this.chunksData[j] = s21packetchunkdata$extracted;
@ -53,12 +53,11 @@ public class SPacketMapChunkBulk implements Packet<IClientPlayer>
this.xPositions[j] = buf.readInt(); this.xPositions[j] = buf.readInt();
this.zPositions[j] = buf.readInt(); this.zPositions[j] = buf.readInt();
this.chunksData[j] = new SPacketChunkData.Extracted(); this.chunksData[j] = new SPacketChunkData.Extracted();
this.chunksData[j].dataSize = buf.readInt();
this.chunksData[j].extend = new int[buf.readVarIntFromBuffer()]; this.chunksData[j].extend = new int[buf.readVarIntFromBuffer()];
for(int z = 0; z < this.chunksData[j].extend.length; z++) { for(int z = 0; z < this.chunksData[j].extend.length; z++) {
this.chunksData[j].extend[z] = buf.readVarIntFromBuffer(); 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) 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.xPositions[i]);
buf.writeInt(this.zPositions[i]); buf.writeInt(this.zPositions[i]);
buf.writeInt(this.chunksData[i].dataSize);
buf.writeVarIntToBuffer(this.chunksData[i].extend.length); buf.writeVarIntToBuffer(this.chunksData[i].extend.length);
for(int z = 0; z < this.chunksData[i].extend.length; z++) { for(int z = 0; z < this.chunksData[i].extend.length; z++) {
buf.writeVarIntToBuffer(this.chunksData[i].extend[z]); buf.writeVarIntToBuffer(this.chunksData[i].extend[z]);
@ -120,11 +118,6 @@ public class SPacketMapChunkBulk implements Packet<IClientPlayer>
return this.chunksData[p_149256_1_].data; 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) public int[] getChunkExtend(int index)
{ {
return this.chunksData[index].extend; return this.chunksData[index].extend;

View file

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

View file

@ -985,7 +985,7 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
{ {
if (list.size() == 1) if (list.size() == 1)
{ {
this.sendPacket(new SPacketChunkData((Chunk)list.get(0), true, 0xffffffff, null)); this.sendPacket(new SPacketChunkData((Chunk)list.get(0), true, null));
} }
else else
{ {

View file

@ -14,6 +14,7 @@ import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.zip.DeflaterOutputStream; import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterInputStream; import java.util.zip.InflaterInputStream;
@ -375,18 +376,7 @@ public class Region {
chunk.setLightPopulated(tag.getBoolean("LightPopulated")); chunk.setLightPopulated(tag.getBoolean("LightPopulated"));
chunk.setInhabited(tag.getLong("InhabitedTime")); chunk.setInhabited(tag.getLong("InhabitedTime"));
NBTTagList sects = tag.getTagList("Sections", 10); NBTTagList sects = tag.getTagList("Sections", 10);
int stor = 32; BlockArray[] sections = new BlockArray[sects.tagCount()];
int min = 0;
int max = stor - 1;
for(int n = 0; n < sects.tagCount(); ++n) {
NBTTagCompound sect = sects.getCompoundTagAt(n);
int y = sect.getInteger("Y");
min = y < min ? y : min;
max = y > max ? y : max;
}
BlockArray[] sections = new BlockArray[stor];
BlockArray[] down = min < 0 ? new BlockArray[-min] : null;
BlockArray[] up = max >= stor ? new BlockArray[1 + max - stor] : null;
boolean light = !world.dimension.hasNoLight(); boolean light = !world.dimension.hasNoLight();
for(int n = 0; n < sects.tagCount(); ++n) { for(int n = 0; n < sects.tagCount(); ++n) {
@ -414,15 +404,10 @@ public class Region {
} }
storage.update(); storage.update();
if(y >= 0 && y < stor) sections[n] = storage;
sections[y] = storage;
else if(y < 0)
down[down.length + y] = storage;
else
up[y - stor] = storage;
} }
chunk.setStorage(sections, down, up); chunk.setStorage(sections);
if(tag.hasKey("Biomes", 7)) { if(tag.hasKey("Biomes", 7)) {
chunk.setBiomes(tag.getByteArray("Biomes")); chunk.setBiomes(tag.getByteArray("Biomes"));
@ -509,16 +494,11 @@ public class Region {
tag.setBoolean("TerrainPopulated", chunk.isTerrainPopulated()); tag.setBoolean("TerrainPopulated", chunk.isTerrainPopulated());
tag.setBoolean("LightPopulated", chunk.isLightPopulated()); tag.setBoolean("LightPopulated", chunk.isLightPopulated());
tag.setLong("InhabitedTime", chunk.getInhabited()); tag.setLong("InhabitedTime", chunk.getInhabited());
BlockArray[] sections = chunk.getStorage(); Set<BlockArray> sections = chunk.getStorage();
BlockArray[] down = chunk.getStorageDown();
BlockArray[] up = chunk.getStorageUp();
NBTTagList sects = new NBTTagList(); NBTTagList sects = new NBTTagList();
boolean light = !world.dimension.hasNoLight(); boolean light = !world.dimension.hasNoLight();
for(BlockArray[] sec : new BlockArray[][] {sections, down, up}) { for(BlockArray storage : sections) {
if(sec == null)
continue;
for(BlockArray storage : sec) {
if(storage != null) { if(storage != null) {
NBTTagCompound sect = new NBTTagCompound(); NBTTagCompound sect = new NBTTagCompound();
sect.setInteger("Y", storage.getY() >> 4); sect.setInteger("Y", storage.getY() >> 4);
@ -563,7 +543,6 @@ public class Region {
sects.appendTag(sect); sects.appendTag(sect);
} }
} }
}
tag.setTag("Sections", sects); tag.setTag("Sections", sects);
tag.setByteArray("Biomes", chunk.getBiomes()); tag.setByteArray("Biomes", chunk.getBiomes());

View file

@ -146,6 +146,7 @@ public final class WorldServer extends AWorldServer {
private final IntHashMap<EntityTrackerEntry> trackMap = new IntHashMap(); private final IntHashMap<EntityTrackerEntry> trackMap = new IntHashMap();
private final Map<String, WorldSavedData> dataMap = Maps.<String, WorldSavedData>newHashMap(); private final Map<String, WorldSavedData> dataMap = Maps.<String, WorldSavedData>newHashMap();
private final List<WorldSavedData> dataList = Lists.<WorldSavedData>newArrayList(); private final List<WorldSavedData> dataList = Lists.<WorldSavedData>newArrayList();
private final List<BlockArray> toTick = Lists.newArrayList();
private final Biome[] biomes = new Biome[256]; private final Biome[] biomes = new Biome[256];
private MapGenCaves caveGen; private MapGenCaves caveGen;
@ -712,7 +713,8 @@ public final class WorldServer extends AWorldServer {
l2 = Config.randomTick; l2 = Config.randomTick;
if(l2 > 0) { if(l2 > 0) {
for(BlockArray extendedblockstorage : chunk.getStorage()) { this.toTick.addAll(chunk.getStorage());
for(BlockArray extendedblockstorage : this.toTick) {
if(extendedblockstorage != null && extendedblockstorage.isTicked()) { if(extendedblockstorage != null && extendedblockstorage.isTicked()) {
for(int j1 = 0; j1 < l2; ++j1) { for(int j1 = 0; j1 < l2; ++j1) {
this.updateLCG = this.updateLCG * 3 + 1013904223; this.updateLCG = this.updateLCG * 3 + 1013904223;
@ -732,6 +734,7 @@ public final class WorldServer extends AWorldServer {
} }
} }
} }
this.toTick.clear();
} }
// this.profiler.end(); // this.profiler.end();
@ -2808,7 +2811,6 @@ public final class WorldServer extends AWorldServer {
private final ChunkPos position; private final ChunkPos position;
private int updates; private int updates;
private int sections;
private long prevTime; private long prevTime;
private boolean biomes; private boolean biomes;
@ -2837,7 +2839,7 @@ public final class WorldServer extends AWorldServer {
Chunk chunk = WorldServer.this.getChunk(this.position.x, this.position.z); Chunk chunk = WorldServer.this.getChunk(this.position.x, this.position.z);
if(chunk.isPopulated()) { if(chunk.isPopulated()) {
player.connection.sendPacket(new SPacketChunkData(chunk, true, 0, new int[0])); player.connection.sendPacket(new SPacketChunkData(chunk, true, new int[0]));
} }
this.watching.remove(player); this.watching.remove(player);
@ -2866,7 +2868,6 @@ public final class WorldServer extends AWorldServer {
if(this.updates == 0) if(this.updates == 0)
WorldServer.this.toUpdate.add(this); WorldServer.this.toUpdate.add(this);
this.updates = 64; this.updates = 64;
this.sections = 0xffffffff;
this.biomes = true; this.biomes = true;
} }
@ -2880,9 +2881,6 @@ public final class WorldServer extends AWorldServer {
WorldServer.this.toUpdate.add(this); WorldServer.this.toUpdate.add(this);
} }
if(y >= 0 && y >> 4 < 32)
this.sections |= 1 << (y >> 4);
else
this.extend.add(y >> 4); this.extend.add(y >> 4);
if(this.updates < 64) { if(this.updates < 64) {
@ -2933,7 +2931,7 @@ public final class WorldServer extends AWorldServer {
} }
} }
this.sendToAllPlayersWatchingChunk(new SPacketChunkData(WorldServer.this.getChunk(this.position.x, this.position.z), this.sendToAllPlayersWatchingChunk(new SPacketChunkData(WorldServer.this.getChunk(this.position.x, this.position.z),
this.biomes, this.sections, extend)); this.biomes, extend));
if(this.biomes) { if(this.biomes) {
List<TileEntity> list = WorldServer.this.getTileEntitiesIn(x, Integer.MIN_VALUE, z, x + 16, Integer.MAX_VALUE, z + 16); List<TileEntity> list = WorldServer.this.getTileEntitiesIn(x, Integer.MIN_VALUE, z, x + 16, Integer.MAX_VALUE, z + 16);
@ -2943,16 +2941,6 @@ public final class WorldServer extends AWorldServer {
} }
} }
else { else {
for(int cy = 0; cy < 32; ++cy) {
if((this.sections & 1 << cy) != 0) {
int y = cy << 4;
List<TileEntity> list = WorldServer.this.getTileEntitiesIn(x, y, z, x + 16, y + 16, z + 16);
for(int n = 0; n < list.size(); ++n) {
this.sendTileToAllPlayersWatchingChunk(list.get(n));
}
}
}
for(Integer cy : this.extend) { for(Integer cy : this.extend) {
int y = cy << 4; int y = cy << 4;
List<TileEntity> list = WorldServer.this.getTileEntitiesIn(x, y, z, x + 16, y + 16, z + 16); List<TileEntity> list = WorldServer.this.getTileEntitiesIn(x, y, z, x + 16, y + 16, z + 16);
@ -2980,7 +2968,6 @@ public final class WorldServer extends AWorldServer {
} }
this.updates = 0; this.updates = 0;
this.sections = 0;
this.extend.clear(); this.extend.clear();
this.biomes = false; this.biomes = false;
} }