diff --git a/client/src/client/Client.java b/client/src/client/Client.java index 082184b..cfa961b 100755 --- a/client/src/client/Client.java +++ b/client/src/client/Client.java @@ -94,6 +94,7 @@ import client.window.Keysym; import client.window.Wheel; import client.window.Window; import client.window.WindowEvent; +import client.world.ChunkClient; import client.world.WorldClient; import common.biome.Biome; import common.block.Block; @@ -156,7 +157,6 @@ import common.util.HitPosition; import common.util.LazyLoadBase; import common.util.Util; import common.util.HitPosition.ObjectType; -import common.world.Chunk; import common.world.LightType; import common.world.State; import common.world.World; @@ -1735,8 +1735,8 @@ public class Client implements IThreadListener { String bline; String lline; if(this.world.isBlockLoaded(blockpos)) { - Chunk chunk = this.world.getChunk(blockpos); - biome = chunk.getBiome(blockpos, null); + ChunkClient chunk = this.world.getChunk(blockpos); + biome = chunk.getBiome(blockpos); bline = "Biom: " + biome.display + " (" + biome.id + ")" + /* (this.debugHideInfo ? "" : */ (", D: " + TextColor.stripCodes(this.world.dimension.getFormattedName(false)) + " (" + this.world.dimension.getDimensionId() + ")"); diff --git a/client/src/client/network/ClientPlayer.java b/client/src/client/network/ClientPlayer.java index 3a6b688..4a4fdce 100755 --- a/client/src/client/network/ClientPlayer.java +++ b/client/src/client/network/ClientPlayer.java @@ -28,6 +28,7 @@ import client.gui.ingame.GuiSign; import client.gui.ingame.GuiForm; import client.renderer.particle.EntityPickupFX; import client.renderer.texture.EntityTexManager; +import client.world.ChunkClient; import client.world.WorldClient; import common.attributes.Attribute; import common.attributes.AttributeInstance; @@ -137,7 +138,6 @@ import common.tileentity.TileEntityMachine; import common.tileentity.TileEntitySign; import common.util.BlockPos; import common.village.MerchantRecipeList; -import common.world.Chunk; import common.world.Explosion; import common.world.Weather; import common.world.World; @@ -741,9 +741,9 @@ public class ClientPlayer extends NetHandler implements IClientPlayer { NetHandler.checkThread(packetIn, this, this.gameController, this.clientWorldController); - for (SPacketMultiBlockChange.BlockUpdateData s22packetmultiblockchange$blockupdatedata : packetIn.getChangedBlocks()) + for (SPacketMultiBlockChange.BlockUpdateData update : packetIn.getChangedBlocks()) { - this.clientWorldController.invalidateRegionAndSetBlock(s22packetmultiblockchange$blockupdatedata.getPos(), s22packetmultiblockchange$blockupdatedata.getBlockState()); + this.clientWorldController.invalidateRegionAndSetBlock(SPacketMultiBlockChange.getPos(packetIn.getChunkPos(), update.getRawPos()), update.getBlockState()); } } @@ -766,7 +766,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); - Chunk chunk = this.clientWorldController.getChunk(packetIn.getChunkX(), packetIn.getChunkZ()); + ChunkClient chunk = this.clientWorldController.getChunk(packetIn.getChunkX(), packetIn.getChunkZ()); 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); @@ -779,7 +779,7 @@ public class ClientPlayer extends NetHandler implements IClientPlayer public void handleBiomes(SPacketBiomes packetIn) { NetHandler.checkThread(packetIn, this, this.gameController, this.clientWorldController); - Chunk chunk = this.clientWorldController.getChunk(packetIn.getChunkX(), packetIn.getChunkZ()); + ChunkClient chunk = this.clientWorldController.getChunk(packetIn.getChunkX(), packetIn.getChunkZ()); chunk.setBiomes(packetIn.getBiomes()); 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); } @@ -1412,7 +1412,7 @@ public class ClientPlayer extends NetHandler implements IClientPlayer int k = packetIn.getChunkZ(i); this.clientWorldController.doPreChunk(j, k, true); // this.clientWorldController.invalidateBlockReceiveRegion(j << 4, 0, k << 4, (j << 4) + 15, 512, (k << 4) + 15); - Chunk chunk = this.clientWorldController.getChunk(j, k); + ChunkClient chunk = this.clientWorldController.getChunk(j, k); 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); diff --git a/client/src/client/renderer/RegionRenderCache.java b/client/src/client/renderer/RegionRenderCache.java index e0ec2fc..5d90530 100755 --- a/client/src/client/renderer/RegionRenderCache.java +++ b/client/src/client/renderer/RegionRenderCache.java @@ -2,48 +2,62 @@ package client.renderer; import java.util.Arrays; +import client.world.ChunkClient; +import client.world.WorldClient; import common.biome.Biome; import common.init.Blocks; import common.tileentity.TileEntity; import common.util.BlockPos; import common.util.Facing; import common.util.Vec3i; -import common.world.Chunk; -import common.world.ChunkCache; import common.world.IWorldAccess; import common.world.LightType; import common.world.State; import common.world.World; -public class RegionRenderCache extends ChunkCache implements IWorldAccess +public class RegionRenderCache implements IWorldAccess { private static final State DEFAULT_STATE = Blocks.air.getState(); - - private final World worldObj; + + private final int xPos; + private final int zPos; + private final ChunkClient[][] chunks; + private final World world; private final BlockPos position; private final boolean empty; private int[] combinedLights; private State[] blockStates; - public RegionRenderCache(World worldIn, BlockPos posFromIn, BlockPos posToIn, int subIn) + public RegionRenderCache(WorldClient world, BlockPos from, BlockPos to, int sub) { - super(worldIn, posFromIn, posToIn, subIn); - this.worldObj = worldIn; - boolean empty = true; - for (int i1 = posFromIn.getX() >> 4; i1 <= posToIn.getX() >> 4; ++i1) + this.world = world; + this.xPos = from.getX() - sub >> 4; + this.zPos = from.getZ() - sub >> 4; + int x2 = to.getX() + sub >> 4; + int z2 = to.getZ() + sub >> 4; + this.chunks = new ChunkClient[x2 - this.xPos + 1][z2 - this.zPos + 1]; + for (int x = this.xPos; x <= x2; ++x) { - for (int j1 = posFromIn.getZ() >> 4; j1 <= posToIn.getZ() >> 4; ++j1) + for (int z = this.zPos; z <= z2; ++z) { - Chunk chunk = this.chunkArray[i1 - this.chunkX][j1 - this.chunkZ]; + this.chunks[x - this.xPos][z - this.zPos] = world.getChunk(x, z); + } + } + boolean empty = true; + for (int x = from.getX() >> 4; x <= to.getX() >> 4; ++x) + { + for (int z = from.getZ() >> 4; z <= to.getZ() >> 4; ++z) + { + ChunkClient chunk = this.chunks[x - this.xPos][z - this.zPos]; - if (chunk != null && !chunk.isEmpty(posFromIn.getY(), posToIn.getY())) + if (chunk != null && !chunk.isEmpty(from.getY(), to.getY())) { empty = false; } } } this.empty = empty; - this.position = posFromIn.subtract(new Vec3i(subIn, subIn, subIn)); + this.position = from.subtract(new Vec3i(sub, sub, sub)); int i = 16000; this.combinedLights = new int[16000]; Arrays.fill((int[])this.combinedLights, (int) - 1); @@ -52,9 +66,9 @@ public class RegionRenderCache extends ChunkCache implements IWorldAccess public TileEntity getTileEntity(BlockPos pos) { - int i = (pos.getX() >> 4) - this.chunkX; - int j = (pos.getZ() >> 4) - this.chunkZ; - return this.chunkArray[i][j].getTileEntity(pos, TileEntity.EnumCreateEntityType.QUEUED); + int i = (pos.getX() >> 4) - this.xPos; + int j = (pos.getZ() >> 4) - this.zPos; + return this.chunks[i][j].getTileEntity(pos, TileEntity.EnumCreateEntityType.QUEUED); } public int getCombinedLight(BlockPos pos, int lightValue) @@ -89,9 +103,9 @@ public class RegionRenderCache extends ChunkCache implements IWorldAccess { if (pos.getY() >= -World.MAX_SIZE_Y && pos.getY() < World.MAX_SIZE_Y) { - int i = (pos.getX() >> 4) - this.chunkX; - int j = (pos.getZ() >> 4) - this.chunkZ; - return this.chunkArray[i][j].getState(pos); + int i = (pos.getX() >> 4) - this.xPos; + int j = (pos.getZ() >> 4) - this.zPos; + return this.chunks[i][j].getState(pos); } else { @@ -127,12 +141,12 @@ public class RegionRenderCache extends ChunkCache implements IWorldAccess public Biome getBiomeGenForCoords(BlockPos pos) { - return this.worldObj.getBiomeGenForCoords(pos); + return this.world.getBiomeGenForCoords(pos); } private int getLightForExt(LightType p_175629_1_, BlockPos pos) { - if (p_175629_1_ == LightType.SKY && this.worldObj.dimension.hasNoLight()) + if (p_175629_1_ == LightType.SKY && this.world.dimension.hasNoLight()) { return 0; } @@ -161,9 +175,9 @@ public class RegionRenderCache extends ChunkCache implements IWorldAccess } else { - int i = (pos.getX() >> 4) - this.chunkX; - int j = (pos.getZ() >> 4) - this.chunkZ; - return this.chunkArray[i][j].getLight(p_175629_1_, pos); + int i = (pos.getX() >> 4) - this.xPos; + int j = (pos.getZ() >> 4) - this.zPos; + return this.chunks[i][j].getLight(p_175629_1_, pos); } } else @@ -185,9 +199,9 @@ public class RegionRenderCache extends ChunkCache implements IWorldAccess { if (pos.getY() >= -World.MAX_SIZE_Y && pos.getY() < World.MAX_SIZE_Y) { - int i = (pos.getX() >> 4) - this.chunkX; - int j = (pos.getZ() >> 4) - this.chunkZ; - return this.chunkArray[i][j].getLight(p_175628_1_, pos); + int i = (pos.getX() >> 4) - this.xPos; + int j = (pos.getZ() >> 4) - this.zPos; + return this.chunks[i][j].getLight(p_175628_1_, pos); } else { diff --git a/client/src/client/renderer/RenderGlobal.java b/client/src/client/renderer/RenderGlobal.java index 07a6f6a..302609c 100755 --- a/client/src/client/renderer/RenderGlobal.java +++ b/client/src/client/renderer/RenderGlobal.java @@ -25,6 +25,7 @@ import client.renderer.texture.TextureAtlasSprite; import client.renderer.texture.TextureManager; import client.renderer.texture.TextureMap; import client.renderer.tileentity.TileEntityRendererDispatcher; +import client.world.ChunkClient; import client.world.WorldClient; import common.block.Block; import common.block.BlockChest; @@ -51,7 +52,6 @@ import common.util.Facing; import common.util.HitPosition; import common.util.Vec3; import common.util.Vector3f; -import common.world.Chunk; import common.world.State; import common.world.World; @@ -604,7 +604,7 @@ public class RenderGlobal for (RenderGlobal.ContainerLocalRenderInformation renderglobal$containerlocalrenderinformation : this.renderInfos) { - Chunk chunk = this.theWorld.getChunk(renderglobal$containerlocalrenderinformation.renderChunk.getPosition()); + ChunkClient chunk = this.theWorld.getChunk(renderglobal$containerlocalrenderinformation.renderChunk.getPosition()); ClassInheritanceMultiMap classinheritancemultimap = chunk.getEntities()[ExtMath.clampi(renderglobal$containerlocalrenderinformation.renderChunk.getPosition().getY() / 16, 0, 31)]; if (!classinheritancemultimap.isEmpty()) @@ -935,7 +935,7 @@ public class RenderGlobal { VisGraph visgraph = new VisGraph(); BlockPos blockpos = new BlockPos(pos.getX() >> 4 << 4, pos.getY() >> 4 << 4, pos.getZ() >> 4 << 4); - Chunk chunk = this.theWorld.getChunk(blockpos); + ChunkClient chunk = this.theWorld.getChunk(blockpos); for (BlockPos.MutableBlockPos blockpos$mutableblockpos : BlockPos.getAllInBoxMutable(blockpos, blockpos.add(15, 15, 15))) { diff --git a/client/src/client/renderer/ViewFrustum.java b/client/src/client/renderer/ViewFrustum.java index a9a95af..ede3e1c 100755 --- a/client/src/client/renderer/ViewFrustum.java +++ b/client/src/client/renderer/ViewFrustum.java @@ -1,14 +1,14 @@ package client.renderer; import client.renderer.chunk.RenderChunk; +import client.world.WorldClient; import common.util.BlockPos; import common.util.ExtMath; -import common.world.World; public class ViewFrustum { protected final RenderGlobal renderGlobal; - protected final World world; + protected final WorldClient world; protected int countChunksY; protected int countChunksX; protected int countChunksZ; @@ -18,7 +18,7 @@ public class ViewFrustum return i < 0 ? -((-i - 1) / 16) - 1 : i / 16; } - public ViewFrustum(World worldIn, int renderDistanceChunks, RenderGlobal p_i46246_3_) + public ViewFrustum(WorldClient worldIn, int renderDistanceChunks, RenderGlobal p_i46246_3_) { this.renderGlobal = p_i46246_3_; this.world = worldIn; diff --git a/client/src/client/renderer/chunk/RenderChunk.java b/client/src/client/renderer/chunk/RenderChunk.java index 8667584..06de2e2 100755 --- a/client/src/client/renderer/chunk/RenderChunk.java +++ b/client/src/client/renderer/chunk/RenderChunk.java @@ -19,6 +19,7 @@ import client.renderer.RenderGlobal; import client.renderer.VertexBuffer; import client.renderer.tileentity.TileEntityRendererDispatcher; import client.renderer.tileentity.TileEntitySpecialRenderer; +import client.world.WorldClient; import common.block.Block; import common.collect.Maps; import common.collect.Sets; @@ -28,11 +29,10 @@ import common.util.BlockPos; import common.util.BoundingBox; import common.util.Facing; import common.world.State; -import common.world.World; public class RenderChunk { - private World world; + private WorldClient world; private final RenderGlobal renderGlobal; public static int renderChunksUpdated; private BlockPos position; @@ -49,7 +49,7 @@ public class RenderChunk private boolean needsUpdate = true; private EnumMap mapEnumFacing = Maps.newEnumMap(Facing.class); - public RenderChunk(World worldIn, RenderGlobal renderGlobalIn, BlockPos blockPosIn, int indexIn) + public RenderChunk(WorldClient worldIn, RenderGlobal renderGlobalIn, BlockPos blockPosIn, int indexIn) { this.world = worldIn; this.renderGlobal = renderGlobalIn; diff --git a/client/src/client/world/ChunkClient.java b/client/src/client/world/ChunkClient.java new file mode 100644 index 0000000..a016246 --- /dev/null +++ b/client/src/client/world/ChunkClient.java @@ -0,0 +1,140 @@ +package client.world; + +import common.biome.Biome; +import common.block.Block; +import common.init.Blocks; +import common.tileentity.TileEntity; +import common.util.BlockPos; +import common.util.NibbleArray; +import common.world.BlockArray; +import common.world.Chunk; +import common.world.World; + +public class ChunkClient extends Chunk { + public ChunkClient(World world, int x, int z) { + super(world, x, z); + } + + private void clearArrays() { + this.blocks.clearMap(); + this.blockList.clear(); + this.bottom = Integer.MAX_VALUE; + this.top = Integer.MIN_VALUE; + } + + private void genHeights() { + int top = this.top; + int bottom = this.bottom; + this.minHeight = Integer.MAX_VALUE; + + for(int x = 0; x < 16; ++x) { + for(int z = 0; z < 16; ++z) { + this.precHeight[x + (z << 4)] = -99999999; + + for(int y = top + 16; y > bottom; --y) { + Block block = this.getBlock0(x, y - 1, z); + + if(block.getLightOpacity() != 0) { + this.height[z << 4 | x] = y; + + if(y < this.minHeight) { + this.minHeight = y; + } + + break; + } + } + } + } + + this.modified = true; + } + + public boolean isEmpty(int bottom, int top) { + for(int y = bottom; y <= top; y += 16) { + BlockArray stor = this.getArray(y >> 4); + + if(stor != null ? !stor.isEmpty() : (y < 0 && this.fillerBlock != Blocks.air)) { + return false; + } + } + + return true; + } + + public void setData(byte[] data, int[] extend, boolean biomes) { + int pos = 0; + boolean sky = !this.world.dimension.hasNoLight(); + + if(biomes) { + this.clearArrays(); + } + for(int cy : extend) { + BlockArray arr = this.getArray(cy); + if(arr == null) { + arr = new BlockArray(cy << 4, sky, null); + this.setArray(arr); + } + + char[] blocks = arr.getData(); + + for(int k = 0; k < blocks.length; ++k) { + blocks[k] = (char)((data[pos + 1] & 255) << 8 | data[pos] & 255); + pos += 2; + } + } + + for(int cy : extend) { + BlockArray arr = this.getArray(cy); + if(arr != null) { + NibbleArray light = arr.getBlocklight(); + System.arraycopy(data, pos, light.getData(), 0, light.getData().length); + pos += light.getData().length; + } + } + + if(sky) { + for(int cy : extend) { + BlockArray arr = this.getArray(cy); + if(arr != null) { + NibbleArray slight = arr.getSkylight(); + System.arraycopy(data, pos, slight.getData(), 0, slight.getData().length); + pos += slight.getData().length; + } + } + } + + if(biomes) { + System.arraycopy(data, pos, this.biomes, 0, this.biomes.length); + } + + for(int cy : extend) { + BlockArray arr = this.getArray(cy); + if(arr != null) { + arr.update(); + } + } + + this.lightInit = true; + this.populated = true; + this.genHeights(); + + for(TileEntity tile : this.tiles.values()) { + tile.updateContainingBlockInfo(); + } + } + + public void setLoaded() { + this.loaded = true; + } + + public Biome getBiome(BlockPos pos) { + int x = pos.getX() & 15; + int z = pos.getZ() & 15; + return Biome.getBiomeDef(this.biomes[z << 4 | x] & 255); + } + + public boolean isDummy() { + return false; + } +} diff --git a/client/src/client/world/EmptyChunk.java b/client/src/client/world/ChunkEmpty.java similarity index 90% rename from client/src/client/world/EmptyChunk.java rename to client/src/client/world/ChunkEmpty.java index 24ded26..31a78d2 100755 --- a/client/src/client/world/EmptyChunk.java +++ b/client/src/client/world/ChunkEmpty.java @@ -10,17 +10,15 @@ import common.init.Blocks; import common.tileentity.TileEntity; import common.util.BlockPos; import common.util.BoundingBox; -import common.world.Chunk; import common.world.LightType; import common.world.State; -import common.worldgen.BiomeGenerator; -public class EmptyChunk extends Chunk { +public class ChunkEmpty extends ChunkClient { private final int liquidY; private final State liquid; private final Block liquidBlock; - public EmptyChunk(WorldClient world) { + public ChunkEmpty(WorldClient world) { super(world, 0, 0); this.liquidY = world.dimension.getSeaLevel() - 1; this.liquid = world.dimension.getLiquid(); @@ -65,10 +63,7 @@ public class EmptyChunk extends Chunk { public void removeTileEntity(BlockPos pos) { } - - public void setModified() { - } - + public void getEntities(Entity exclude, BoundingBox bb, List list, Predicate pred) { } @@ -108,7 +103,7 @@ public class EmptyChunk extends Chunk { public void setData(byte[] data, int[] extend, boolean biomes) { } - public Biome getBiome(BlockPos pos, BiomeGenerator gen) { + public Biome getBiome(BlockPos pos) { return Biome.DEF_BIOME; } @@ -128,7 +123,7 @@ public class EmptyChunk extends Chunk { return false; } - public void setLoaded(boolean loaded) { + public void setLoaded() { } public int getLowest() { diff --git a/client/src/client/world/WorldClient.java b/client/src/client/world/WorldClient.java index 32fa891..1ef10ff 100755 --- a/client/src/client/world/WorldClient.java +++ b/client/src/client/world/WorldClient.java @@ -33,7 +33,6 @@ import common.util.ExtMath; import common.util.LongHashMap; import common.util.Vec3; import common.util.BlockPos.MutableBlockPos; -import common.world.Chunk; import common.world.AWorldClient; import common.world.State; import common.world.World; @@ -46,11 +45,11 @@ public class WorldClient extends AWorldClient private final Set entityList = Sets.newHashSet(); private final Set spawnQueue = Sets.newHashSet(); private final Set previousActive = Sets.newHashSet(); - private final LongHashMap chunkMapping = new LongHashMap(); - private final List chunkListing = Lists.newArrayList(); + private final LongHashMap chunkMapping = new LongHashMap(); + private final List chunkListing = Lists.newArrayList(); private final Set emptyChunkListing = Sets.newHashSet(); private final Set nextEmptyChunkListing = Sets.newHashSet(); - private final Chunk emptyChunk = new EmptyChunk(this); + private final ChunkClient emptyChunk = new ChunkEmpty(this); // public final Profiler profiler; protected int lastLightning; protected Vec3 lightColor = new Vec3(0xffffff); @@ -120,7 +119,7 @@ public class WorldClient extends AWorldClient } } long time = System.currentTimeMillis(); - for (Chunk chunk : this.chunkListing) + for (ChunkClient chunk : this.chunkListing) { chunk.update(System.currentTimeMillis() - time > 5L); } @@ -149,7 +148,7 @@ public class WorldClient extends AWorldClient { int j = chunkcoordintpair.x * 16; int k = chunkcoordintpair.z * 16; - Chunk chunk = this.getChunk(chunkcoordintpair.x, chunkcoordintpair.z); + ChunkClient chunk = this.getChunk(chunkcoordintpair.x, chunkcoordintpair.z); chunk.enqueueRelight(); this.previousActive.add(chunkcoordintpair); ++i; @@ -169,14 +168,14 @@ public class WorldClient extends AWorldClient { if(this.chunkMapping.getValueByKey(id) != null) this.doPreChunk(x, z, false); - Chunk chunk = new Chunk(this, x, z); + ChunkClient chunk = new ChunkClient(this, x, z); this.chunkMapping.add(id, chunk); this.chunkListing.add(chunk); - chunk.setLoaded(true); + chunk.setLoaded(); } else { - Chunk chunk = this.getChunk(x, z); + ChunkClient chunk = this.getChunk(x, z); chunk.onChunkUnload(); this.chunkMapping.remove(id); this.chunkListing.remove(chunk); @@ -387,11 +386,26 @@ public class WorldClient extends AWorldClient this.gm.effectRenderer.addEffect(new EntityFirework.StarterFX(this.gm.world, x, y, z, motionX, motionY, motionZ, this.gm.effectRenderer, compund)); } - public Chunk getChunk(int x, int z) + public ChunkClient getChunk(int x, int z) { - Chunk chunk = this.chunkMapping.getValueByKey(LongHashMap.packInt(x, z)); + ChunkClient chunk = this.chunkMapping.getValueByKey(LongHashMap.packInt(x, z)); return chunk == null ? this.emptyChunk : chunk; } + + public ChunkClient getChunk(BlockPos pos) { + return this.getChunk(pos.getX() >> 4, pos.getZ() >> 4); + } + + public Biome getBiomeGenForCoords(BlockPos pos) { + if(this.isBlockLoaded(pos)) + return this.getChunk(pos).getBiome(pos); + else + return Biome.DEF_BIOME; + } + + protected boolean isLoaded(int x, int z, boolean allowEmpty) { + return allowEmpty || !this.getChunk(x, z).isDummy(); + } public String getInfo() { diff --git a/common/src/common/block/BlockTorch.java b/common/src/common/block/BlockTorch.java index 3012c52..ca7552b 100755 --- a/common/src/common/block/BlockTorch.java +++ b/common/src/common/block/BlockTorch.java @@ -19,7 +19,6 @@ import common.util.BoundingBox; import common.util.Facing; import common.util.HitPosition; import common.util.Vec3; -import common.world.Chunk; import common.world.AWorldClient; import common.world.State; import common.world.World; @@ -36,20 +35,10 @@ public class BlockTorch extends Block }); private static boolean isBlockNormalCube(World world, BlockPos pos, boolean def) { - if(!World.isValid(pos)) { + if(!World.isValid(pos) || (world.client && !world.isBlockLoaded(pos, false))) return def; - } - else { - Chunk chunk = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4); - - if(chunk.isDummy()) { - return def; - } - else { - Block block = world.getState(pos).getBlock(); - return block.getMaterial().isOpaque() && block.isFullCube(); - } - } + Block block = world.getState(pos).getBlock(); + return block.getMaterial().isOpaque() && block.isFullCube(); } public BlockTorch() diff --git a/common/src/common/dimension/Dimension.java b/common/src/common/dimension/Dimension.java index 5e63fa8..5ed1030 100755 --- a/common/src/common/dimension/Dimension.java +++ b/common/src/common/dimension/Dimension.java @@ -21,9 +21,6 @@ import common.util.ExtMath; import common.util.Vec3; import common.world.State; import common.world.Weather; -import common.worldgen.FeatureLake; -import common.worldgen.FeatureLiquid; -import common.worldgen.FeatureOre; public abstract class Dimension extends Nameable implements Comparable { public class GeneratorSettings { @@ -288,9 +285,9 @@ public abstract class Dimension extends Nameable implements Comparable ores = Lists.newArrayList(); - private final List lakes = Lists.newArrayList(); - private final List liquids = Lists.newArrayList(); + private final List ores = Lists.newArrayList(); + private final List lakes = Lists.newArrayList(); + private final List liquids = Lists.newArrayList(); private long seed = 0L; @@ -584,24 +581,24 @@ public abstract class Dimension extends Nameable implements Comparable getOres() { + public List getOres() { return this.ores; } - public List getLakes() { + public List getLakes() { return this.lakes; } - public List getLiquids() { + public List getLiquids() { return this.liquids; } } diff --git a/common/src/common/worldgen/FeatureLake.java b/common/src/common/dimension/Lake.java similarity index 70% rename from common/src/common/worldgen/FeatureLake.java rename to common/src/common/dimension/Lake.java index b279e52..2b21b58 100644 --- a/common/src/common/worldgen/FeatureLake.java +++ b/common/src/common/dimension/Lake.java @@ -1,8 +1,8 @@ -package common.worldgen; +package common.dimension; import common.world.State; -public class FeatureLake { +public class Lake { public final State state; public final State filler; public final State top; @@ -11,7 +11,7 @@ public class FeatureLake { public final int maxHeight; public final boolean ratiod; - public FeatureLake(State state, State filler, State top, int chance, int minHeight, int maxHeight, boolean ratiod) { + public Lake(State state, State filler, State top, int chance, int minHeight, int maxHeight, boolean ratiod) { this.state = state; this.filler = filler; this.top = top; diff --git a/common/src/common/worldgen/FeatureLiquid.java b/common/src/common/dimension/Liquid.java similarity index 67% rename from common/src/common/worldgen/FeatureLiquid.java rename to common/src/common/dimension/Liquid.java index d2794c0..b1643f3 100644 --- a/common/src/common/worldgen/FeatureLiquid.java +++ b/common/src/common/dimension/Liquid.java @@ -1,15 +1,15 @@ -package common.worldgen; +package common.dimension; import common.world.State; -public class FeatureLiquid { +public class Liquid { public final State state; public final int chance; public final int minHeight; public final int maxHeight; public final boolean lower; - public FeatureLiquid(State state, int chance, int minHeight, int maxHeight, boolean lower) { + public Liquid(State state, int chance, int minHeight, int maxHeight, boolean lower) { this.state = state; this.chance = chance; this.minHeight = minHeight; diff --git a/common/src/common/worldgen/FeatureOre.java b/common/src/common/dimension/Ore.java similarity index 70% rename from common/src/common/worldgen/FeatureOre.java rename to common/src/common/dimension/Ore.java index 38237ff..5171c68 100644 --- a/common/src/common/worldgen/FeatureOre.java +++ b/common/src/common/dimension/Ore.java @@ -1,8 +1,8 @@ -package common.worldgen; +package common.dimension; import common.world.State; -public class FeatureOre { +public class Ore { public final State state; public final int count; public final int more; @@ -11,7 +11,7 @@ public class FeatureOre { public final int max; public final boolean dist; - public FeatureOre(State state, int count, int more, int size, int min, int max, boolean dist) { + public Ore(State state, int count, int more, int size, int min, int max, boolean dist) { this.state = state; this.count = count; this.more = more; diff --git a/common/src/common/entity/npc/EntitySlime.java b/common/src/common/entity/npc/EntitySlime.java index 2fb6b0a..da33477 100755 --- a/common/src/common/entity/npc/EntitySlime.java +++ b/common/src/common/entity/npc/EntitySlime.java @@ -15,7 +15,6 @@ import common.pathfinding.PathNavigateGround; import common.rng.Random; import common.util.BlockPos; import common.util.ExtMath; -import common.world.Chunk; import common.world.World; import common.world.AWorldServer; @@ -386,8 +385,7 @@ public class EntitySlime extends EntityNPC public boolean getCanSpawnHere() { BlockPos blockpos = new BlockPos(ExtMath.floord(this.posX), 0, ExtMath.floord(this.posZ)); - Chunk chunk = this.worldObj.getChunk(blockpos); - + // if (this.worldObj.getWorldInfo().getTerrainType() == WorldType.FLAT && this.rand.nextInt(4) != 1) // { // return false; @@ -403,7 +401,7 @@ public class EntitySlime extends EntityNPC return super.getCanSpawnHere(); } - if (this.rand.zrange(10) == 0 && getRandomWithSeed((AWorldServer)this.worldObj, chunk.xPos, chunk.zPos, 987234911L).zrange(10) == 0 && this.posY < 40.0D) + if (this.rand.zrange(10) == 0 && getRandomWithSeed((AWorldServer)this.worldObj, blockpos.getX() >> 4, blockpos.getZ() >> 4, 987234911L).zrange(10) == 0 && this.posY < 40.0D) { return super.getCanSpawnHere(); } diff --git a/common/src/common/packet/SPacketChunkData.java b/common/src/common/packet/SPacketChunkData.java index ee87912..66438d6 100755 --- a/common/src/common/packet/SPacketChunkData.java +++ b/common/src/common/packet/SPacketChunkData.java @@ -1,15 +1,9 @@ package common.packet; import java.io.IOException; -import java.util.List; -import java.util.Set; - -import common.collect.Lists; import common.network.IClientPlayer; import common.network.Packet; import common.network.PacketBuffer; -import common.world.BlockArray; -import common.world.Chunk; public class SPacketChunkData implements Packet { @@ -22,12 +16,12 @@ public class SPacketChunkData implements Packet { } - public SPacketChunkData(Chunk chunkIn, boolean biomes, int[] extend) + public SPacketChunkData(int x, int z, boolean biomes, SPacketChunkData.Extracted data) { - this.chunkX = chunkIn.xPos; - this.chunkZ = chunkIn.zPos; + this.chunkX = x; + this.chunkZ = z; this.biomes = biomes; - this.extractedData = getExtractedData(chunkIn, biomes, !chunkIn.getWorld().dimension.hasNoLight(), extend); + this.extractedData = data; } /** @@ -74,7 +68,7 @@ public class SPacketChunkData implements Packet return this.extractedData.data; } - protected static int getSize(int segments, boolean overworld, boolean biomes) + public static int getSize(int segments, boolean overworld, boolean biomes) { int i = segments * 2 * 16 * 16 * 16; int j = segments * 16 * 16 * 16 / 2; @@ -83,72 +77,6 @@ public class SPacketChunkData implements Packet return i + j + k + l; } - public static SPacketChunkData.Extracted getExtractedData(Chunk chunk, boolean biomes, boolean overworld, int[] extend) - { - Set aextendedblockstorage = chunk.getStorage(); - SPacketChunkData.Extracted s21packetchunkdata$extracted = new SPacketChunkData.Extracted(); - List list = Lists.newArrayList(); - - if(extend == null) { - for(BlockArray arr : aextendedblockstorage) { - if(arr != null && (!biomes || !arr.isEmpty())) - list.add(arr); - } - } - else { - for(int cy : extend) { - BlockArray arr = chunk.getArray(cy); - if(arr != null && (!biomes || !arr.isEmpty())) - list.add(arr); - } - } - extend = new int[list.size()]; - for(int z = 0; z < extend.length; z++) { - extend[z] = list.get(z).getY() >> 4; - } - - s21packetchunkdata$extracted.extend = extend; - s21packetchunkdata$extracted.data = new byte[getSize(extend.length, overworld, biomes)]; - int j = 0; - - for (BlockArray extendedblockstorage1 : list) - { - char[] achar = extendedblockstorage1.getData(); - - for (char c0 : achar) - { - s21packetchunkdata$extracted.data[j++] = (byte)(c0 & 255); - s21packetchunkdata$extracted.data[j++] = (byte)(c0 >> 8 & 255); - } - } - - for (BlockArray extendedblockstorage2 : list) - { - j = copyTo(extendedblockstorage2.getBlocklight().getData(), s21packetchunkdata$extracted.data, j); - } - - if (overworld) - { - for (BlockArray extendedblockstorage3 : list) - { - j = copyTo(extendedblockstorage3.getSkylight().getData(), s21packetchunkdata$extracted.data, j); - } - } - - if (biomes) - { - copyTo(chunk.getBiomes(), s21packetchunkdata$extracted.data, j); - } - - return s21packetchunkdata$extracted; - } - - private static int copyTo(byte[] src, byte[] dest, int offset) - { - System.arraycopy(src, 0, dest, offset, src.length); - return offset + src.length; - } - public int getChunkX() { return this.chunkX; diff --git a/common/src/common/packet/SPacketMapChunkBulk.java b/common/src/common/packet/SPacketMapChunkBulk.java index 4c7c4bb..4ba19d2 100755 --- a/common/src/common/packet/SPacketMapChunkBulk.java +++ b/common/src/common/packet/SPacketMapChunkBulk.java @@ -1,48 +1,35 @@ package common.packet; import java.io.IOException; -import java.util.List; - import common.network.IClientPlayer; import common.network.Packet; import common.network.PacketBuffer; -import common.world.Chunk; public class SPacketMapChunkBulk implements Packet { private int[] xPositions; private int[] zPositions; private SPacketChunkData.Extracted[] chunksData; - private boolean isOverworld; + private boolean sky; public SPacketMapChunkBulk() { } - public SPacketMapChunkBulk(List chunks) + public SPacketMapChunkBulk(int[] x, int[] z, SPacketChunkData.Extracted[] chunks, boolean sky) { - int i = chunks.size(); - this.xPositions = new int[i]; - this.zPositions = new int[i]; - this.chunksData = new SPacketChunkData.Extracted[i]; - this.isOverworld = !((Chunk)chunks.get(0)).getWorld().dimension.hasNoLight(); - - for (int j = 0; j < i; ++j) - { - Chunk chunk = (Chunk)chunks.get(j); - 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; - } + this.xPositions = x; + this.zPositions = z; + this.chunksData = chunks; + this.sky = sky; } - + /** * Reads the raw packet data from the data stream. */ public void readPacketData(PacketBuffer buf) throws IOException { - this.isOverworld = buf.readBoolean(); + this.sky = buf.readBoolean(); int i = buf.readVarIntFromBuffer(); this.xPositions = new int[i]; this.zPositions = new int[i]; @@ -57,7 +44,7 @@ public class SPacketMapChunkBulk implements Packet 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(this.chunksData[j].extend.length, this.isOverworld, true)]; + this.chunksData[j].data = new byte[SPacketChunkData.getSize(this.chunksData[j].extend.length, this.sky, true)]; } for (int k = 0; k < i; ++k) @@ -71,7 +58,7 @@ public class SPacketMapChunkBulk implements Packet */ public void writePacketData(PacketBuffer buf) throws IOException { - buf.writeBoolean(this.isOverworld); + buf.writeBoolean(this.sky); buf.writeVarIntToBuffer(this.chunksData.length); for (int i = 0; i < this.xPositions.length; ++i) diff --git a/common/src/common/packet/SPacketMultiBlockChange.java b/common/src/common/packet/SPacketMultiBlockChange.java index f6b4a4b..6694b98 100755 --- a/common/src/common/packet/SPacketMultiBlockChange.java +++ b/common/src/common/packet/SPacketMultiBlockChange.java @@ -8,7 +8,6 @@ import common.network.Packet; import common.network.PacketBuffer; import common.util.BlockPos; import common.util.ChunkPos; -import common.world.Chunk; import common.world.State; public class SPacketMultiBlockChange implements Packet @@ -16,19 +15,18 @@ public class SPacketMultiBlockChange implements Packet private ChunkPos chunkPosCoord; private SPacketMultiBlockChange.BlockUpdateData[] changedBlocks; + public static BlockPos getPos(ChunkPos pos, long position) + { + return new BlockPos(new BlockPos((pos.x << 4) + (int)(position >> 36 & 15L), (int)(position & 4294967295L), (pos.z << 4) + (int)(position >> 32 & 15L))); + } + public SPacketMultiBlockChange() { } - - public SPacketMultiBlockChange(int p_i45181_1_, long[] crammedPositionsIn, Chunk chunkIn) - { - this.chunkPosCoord = new ChunkPos(chunkIn.xPos, chunkIn.zPos); - this.changedBlocks = new SPacketMultiBlockChange.BlockUpdateData[p_i45181_1_]; - - for (int i = 0; i < this.changedBlocks.length; ++i) - { - this.changedBlocks[i] = new SPacketMultiBlockChange.BlockUpdateData(crammedPositionsIn[i], chunkIn); - } + + public SPacketMultiBlockChange(ChunkPos pos, SPacketMultiBlockChange.BlockUpdateData[] changes) { + this.chunkPosCoord = pos; + this.changedBlocks = changes; } /** @@ -74,7 +72,12 @@ public class SPacketMultiBlockChange implements Packet return this.changedBlocks; } - public class BlockUpdateData + public ChunkPos getChunkPos() + { + return this.chunkPosCoord; + } + + public static class BlockUpdateData { private final long position; private final State blockState; @@ -84,19 +87,7 @@ public class SPacketMultiBlockChange implements Packet this.position = raw; this.blockState = state; } - - public BlockUpdateData(long raw, Chunk chunkIn) - { - this.position = raw; - this.blockState = chunkIn.getState(this.getPos()); - } - - public BlockPos getPos() - { - ChunkPos pos = SPacketMultiBlockChange.this.chunkPosCoord; - return new BlockPos(new BlockPos((pos.x << 4) + (int)(this.position >> 36 & 15L), (int)(this.position & 4294967295L), (pos.z << 4) + (int)(this.position >> 32 & 15L))); - } - + public long getRawPos() { return this.position; diff --git a/common/src/common/pathfinding/PathCache.java b/common/src/common/pathfinding/PathCache.java index 255b82c..b33d97b 100755 --- a/common/src/common/pathfinding/PathCache.java +++ b/common/src/common/pathfinding/PathCache.java @@ -3,16 +3,30 @@ package common.pathfinding; import common.init.Blocks; import common.util.BlockPos; import common.world.Chunk; -import common.world.ChunkCache; import common.world.IBlockAccess; import common.world.State; import common.world.World; -public class PathCache extends ChunkCache implements IBlockAccess +public class PathCache implements IBlockAccess { - public PathCache(World worldIn, BlockPos posFromIn, BlockPos posToIn) + protected final int chunkX; + protected final int chunkZ; + protected final Chunk[][] data; + + public PathCache(World world, BlockPos pos1, BlockPos pos2) { - super(worldIn, posFromIn, posToIn, 0); + this.chunkX = pos1.getX() >> 4; + this.chunkZ = pos1.getZ() >> 4; + int cx2 = pos2.getX() >> 4; + int cz2 = pos2.getZ() >> 4; + this.data = new Chunk[cx2 - this.chunkX + 1][cz2 - this.chunkZ + 1]; + for (int x = this.chunkX; x <= cx2; ++x) + { + for (int z = this.chunkZ; z <= cz2; ++z) + { + this.data[x - this.chunkX][z - this.chunkZ] = world.getChunk(x, z); + } + } } public State getState(BlockPos pos) @@ -22,9 +36,9 @@ public class PathCache extends ChunkCache implements IBlockAccess int i = (pos.getX() >> 4) - this.chunkX; int j = (pos.getZ() >> 4) - this.chunkZ; - if (i >= 0 && i < this.chunkArray.length && j >= 0 && j < this.chunkArray[i].length) + if (i >= 0 && i < this.data.length && j >= 0 && j < this.data[i].length) { - Chunk chunk = this.chunkArray[i][j]; + Chunk chunk = this.data[i][j]; if (chunk != null) { diff --git a/common/src/common/tileentity/TileEntity.java b/common/src/common/tileentity/TileEntity.java index 31da294..ce17bb0 100755 --- a/common/src/common/tileentity/TileEntity.java +++ b/common/src/common/tileentity/TileEntity.java @@ -7,6 +7,7 @@ import common.log.Log; import common.nbt.NBTTagCompound; import common.network.Packet; import common.util.BlockPos; +import common.world.AWorldServer; import common.world.State; import common.world.World; @@ -128,7 +129,8 @@ public abstract class TileEntity { State iblockstate = this.worldObj.getState(this.pos); this.blockMetadata = iblockstate.getBlock().getMetaFromState(iblockstate); - this.worldObj.markChunkDirty(this.pos, this); + if(!this.worldObj.client) + ((AWorldServer)this.worldObj).markChunkDirty(this.pos); if (this.getBlockType() != Blocks.air) { diff --git a/common/src/common/world/AWorldServer.java b/common/src/common/world/AWorldServer.java index dbbda3f..3ca91f0 100644 --- a/common/src/common/world/AWorldServer.java +++ b/common/src/common/world/AWorldServer.java @@ -46,4 +46,5 @@ public abstract class AWorldServer extends World { public abstract T findNearestEntityWithinAABB(Class entityType, BoundingBox aabb, T closestTo); public abstract long getTime(); public abstract void setBiome(BlockPos pos, Biome biome); + public abstract void markChunkDirty(BlockPos pos); } diff --git a/common/src/common/world/Chunk.java b/common/src/common/world/Chunk.java index 9feacdc..841292b 100755 --- a/common/src/common/world/Chunk.java +++ b/common/src/common/world/Chunk.java @@ -7,58 +7,49 @@ import java.util.Set; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.function.Predicate; -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; import common.log.Log; import common.material.Material; -import common.rng.Random; import common.tileentity.TileEntity; import common.util.BlockPos; import common.util.BoundingBox; -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; -public class Chunk { +public abstract class Chunk { public final int xPos; public final int zPos; - private final World world; - private final State filler; - private final Block fillerBlock; - private final IntHashMap blocks = new IntHashMap(); - private final Set blockList = Sets.newHashSet(); - private final byte[] biomes = new byte[256]; - private final int[] precHeight = new int[256]; - private final boolean[] updateSky = new boolean[256]; - private final int[] height = new int[256]; - private final Map tiles = Maps.newHashMap(); - private final ClassInheritanceMultiMap[] entities = new ClassInheritanceMultiMap[32]; - private final ConcurrentLinkedQueue tileQueue = new ConcurrentLinkedQueue(); + protected final World world; + protected final State filler; + protected final Block fillerBlock; + protected final IntHashMap blocks = new IntHashMap(); + protected final Set blockList = Sets.newHashSet(); + protected final byte[] biomes = new byte[256]; + protected final int[] precHeight = new int[256]; + protected final boolean[] updateSky = new boolean[256]; + protected final int[] height = new int[256]; + protected final Map tiles = Maps.newHashMap(); + protected final ClassInheritanceMultiMap[] entities = new ClassInheritanceMultiMap[32]; + protected final ConcurrentLinkedQueue tileQueue = new ConcurrentLinkedQueue(); - private boolean loaded; - private boolean gapUpdate; - private boolean populated; - private boolean lightInit; - private boolean updated; - private boolean modified; - private boolean hasEntity; - private int minHeight; - private int lightChecks = Integer.MAX_VALUE; - private int bottom = Integer.MAX_VALUE; - private int top = Integer.MIN_VALUE; - private long lastSave; - private long inhabited; + protected boolean loaded; + protected boolean gapUpdate; + protected boolean populated; + protected boolean lightInit; + protected boolean updated; + protected boolean modified; + protected boolean hasEntity; + protected int minHeight; + protected int lightChecks = Integer.MAX_VALUE; + protected int bottom = Integer.MAX_VALUE; + protected int top = Integer.MIN_VALUE; public Chunk(World world, int x, int z) { this.world = world; @@ -72,101 +63,16 @@ public class Chunk { Arrays.fill(this.precHeight, -99999999); Arrays.fill(this.biomes, (byte)-1); } - - public Chunk(World world, short[] data, int height, boolean base, boolean ceil, Random rand, Biome[] biomes, int x, int z) { - this(world, x, z); - boolean sky = !world.dimension.hasNoLight(); - for(int bx = 0; bx < 16; ++bx) { - for(int bz = 0; bz < 16; ++bz) { - for(int by = 0; by < height; ++by) { - State state = BlockRegistry.STATEMAP.getByValue(data[bx << 4 | bz | by << 8]); - if(state != null && state.getBlock().getMaterial() != Material.air) { - int y = by >> 4; - 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) { - Block caves = world.dimension.getCaveFiller().getBlock(); - 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)) { - Block block = arr.get(bx, by, bz).getBlock(); - if(block == Blocks.air || block.getMaterial().isLiquid() || block == caves) - arr.set(bx, by, bz, this.filler); - } - } - } - } - } - if(ceil) { - int y = (height - 1) >> 4; - BlockArray arr = this.getArray(y); - if(arr == null) { - arr = new BlockArray(y << 4, sky, null); - this.setArray(arr); - } - y = (height - 5) >> 4; - 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.getArray(by >> 4).set(bx, by & 15, bz, Blocks.air.getState()); - } - } - } - } - for(int n = 0; n < this.biomes.length; ++n) { - this.biomes[n] = (byte)biomes[n].id; - } - if(ceil) - this.resetRelight(); - else - this.genSkyLight(); - } - - public int getHeight(BlockPos pos) { - return this.getHeight(pos.getX() & 15, pos.getZ() & 15); - } - + public int getHeight(int x, int z) { return this.height[z << 4 | x]; } - public int getTopSegment() { - return this.top; - } - - public int getBottomSegment() { - return this.bottom; - } - - public Set getStorage() { - return this.blockList; - } - public BlockArray getArray(int y) { return this.blocks.lookup(y); } - private void setArray(BlockArray array) { + protected void setArray(BlockArray array) { int y = array.getY() >> 4; this.blocks.addKey(y, array); this.blockList.add(array); @@ -174,42 +80,7 @@ public class Chunk { 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() { - int top = this.top; - int bottom = this.bottom; - this.minHeight = Integer.MAX_VALUE; - - for(int x = 0; x < 16; ++x) { - for(int z = 0; z < 16; ++z) { - this.precHeight[x + (z << 4)] = -99999999; - - for(int y = top + 16; y > bottom; --y) { - Block block = this.getBlock0(x, y - 1, z); - - if(block.getLightOpacity() != 0) { - this.height[z << 4 | x] = y; - - if(y < this.minHeight) { - this.minHeight = y; - } - - break; - } - } - } - } - - this.modified = true; - } - + public void genSkyLight() { int top = this.top; int bottom = this.bottom; @@ -415,7 +286,7 @@ public class Chunk { } } - public int getOpacity(BlockPos pos) { + private int getOpacity(BlockPos pos) { return this.getBlock(pos).getLightOpacity(); } @@ -423,7 +294,7 @@ public class Chunk { return this.getBlock0(x, y, z).getLightOpacity(); } - private Block getBlock0(int x, int y, int z) { + protected Block getBlock0(int x, int y, int z) { BlockArray stor = this.getArray(y >> 4); return stor != null ? stor.getBlock(x, y & 15, z) : (y < 0 ? this.fillerBlock : Blocks.air); } @@ -672,14 +543,6 @@ public class Chunk { return tile; } - public void addTileEntity(TileEntity tile) { - this.addTileEntity(tile.getPos(), tile); - - if(this.loaded) { - this.world.addTileEntity(tile); - } - } - public void addTileEntity(BlockPos pos, TileEntity tile) { tile.setWorldObj(this.world); tile.setPos(pos); @@ -690,7 +553,7 @@ public class Chunk { } if(tile.validate()) { - this.setModified(); + this.modified = true; } this.tiles.put(pos, tile); } @@ -706,19 +569,6 @@ public class Chunk { } } - public void onChunkLoad() { - this.loaded = true; - this.world.addTileEntities(this.tiles.values()); - - for(int n = 0; n < this.entities.length; ++n) { - for(Entity entity : this.entities[n]) { - entity.onChunkLoad(); - } - - this.world.loadEntities(this.entities[n]); - } - } - public void onChunkUnload() { this.loaded = false; @@ -731,10 +581,6 @@ public class Chunk { } } - public void setModified() { - this.modified = true; - } - public void getEntities(Entity exclude, BoundingBox bb, List list, Predicate pred) { int sy = ExtMath.floord((bb.minY - 2.0D) / 16.0D); int ey = ExtMath.floord((bb.maxY + 2.0D) / 16.0D); @@ -782,17 +628,6 @@ public class Chunk { } } - public boolean isDirty(long time) { - if(this.hasEntity && time != this.lastSave || this.modified) { - return true; - } - return this.modified; - } - - public boolean isDummy() { - return false; - } - public BlockPos getPrecipitation(BlockPos pos) { int x = pos.getX() & 15; int z = pos.getZ() & 15; @@ -851,108 +686,6 @@ public class Chunk { return this.updated && this.populated && this.lightInit; } - public ChunkPos getPos() { - return new ChunkPos(this.xPos, this.zPos); - } - - public boolean isEmpty(int bottom, int top) { - for(int y = bottom; y <= top; y += 16) { - BlockArray stor = this.getArray(y >> 4); - - if(stor != null ? !stor.isEmpty() : (y < 0 && this.fillerBlock != Blocks.air)) { - return false; - } - } - - return true; - } - - public void setStorage(BlockArray[] data) { - for(BlockArray arr : data) { - this.setArray(arr); - } - } - - public void setData(byte[] data, int[] extend, boolean biomes) { - int pos = 0; - boolean sky = !this.world.dimension.hasNoLight(); - - if(biomes) { - this.clearArrays(); - } - for(int cy : extend) { - BlockArray arr = this.getArray(cy); - if(arr == null) { - arr = new BlockArray(cy << 4, sky, null); - this.setArray(arr); - } - - char[] blocks = arr.getData(); - - for(int k = 0; k < blocks.length; ++k) { - blocks[k] = (char)((data[pos + 1] & 255) << 8 | data[pos] & 255); - pos += 2; - } - } - - for(int cy : extend) { - BlockArray arr = this.getArray(cy); - if(arr != null) { - NibbleArray light = arr.getBlocklight(); - System.arraycopy(data, pos, light.getData(), 0, light.getData().length); - pos += light.getData().length; - } - } - - if(sky) { - for(int cy : extend) { - BlockArray arr = this.getArray(cy); - if(arr != null) { - NibbleArray slight = arr.getSkylight(); - System.arraycopy(data, pos, slight.getData(), 0, slight.getData().length); - pos += slight.getData().length; - } - } - } - - if(biomes) { - System.arraycopy(data, pos, this.biomes, 0, this.biomes.length); - } - - for(int cy : extend) { - BlockArray arr = this.getArray(cy); - if(arr != null) { - arr.update(); - } - } - - this.lightInit = true; - this.populated = true; - this.genHeights(); - - for(TileEntity tile : this.tiles.values()) { - tile.updateContainingBlockInfo(); - } - } - - public Biome getBiome(BlockPos pos, BiomeGenerator gen) { - int x = pos.getX() & 15; - int z = pos.getZ() & 15; - int o = this.biomes[z << 4 | x] & 255; - - if(o == 255) { - Biome biome = gen == null ? Biome.DEF_BIOME : gen.getBiomeGenerator(pos, Biome.DEF_BIOME); - o = biome.id; - this.biomes[z << 4 | x] = (byte)(o & 255); - } - - return Biome.getBiomeDef(o); - } - - public byte[] getBiomes() { - return this.biomes; - } - public void setBiomes(byte[] biomes) { if(this.biomes.length != biomes.length) { Log.JNI.warn("Konnte Biome des Chunks nicht setzen, Länge des Arrays ist " + biomes.length + " statt " + this.biomes.length); @@ -1114,75 +847,12 @@ public class Chunk { public boolean isLoaded() { return this.loaded; } - - public void setLoaded(boolean loaded) { - this.loaded = loaded; - } - - public World getWorld() { - return this.world; - } - - public int[] getHeights() { - return this.height; - } - - public void setHeights(int[] map) { - if(this.height.length != map.length) { - Log.JNI.warn("Konnte Höhen des Chunks nicht setzen, Länge des Arrays ist " + map.length + " statt " + this.height.length); - } - else { - for(int n = 0; n < this.height.length; ++n) { - this.height[n] = map[n]; - } - } - } - - public Map getTiles() { - return this.tiles; - } - + public ClassInheritanceMultiMap[] getEntities() { return this.entities; } - public boolean isTerrainPopulated() { - return this.populated; - } - - public void setTerrainPopulated(boolean populated) { - this.populated = populated; - } - - public boolean isLightPopulated() { - return this.lightInit; - } - - public void setLightPopulated(boolean populated) { - this.lightInit = populated; - } - - public void setModified(boolean modified) { - this.modified = modified; - } - - public void setHasEntities(boolean entities) { - this.hasEntity = entities; - } - - public void setSaved(long time) { - this.lastSave = time; - } - public int getLowest() { return this.minHeight; } - - public long getInhabited() { - return this.inhabited; - } - - public void setInhabited(long time) { - this.inhabited = time; - } } diff --git a/common/src/common/world/ChunkCache.java b/common/src/common/world/ChunkCache.java deleted file mode 100755 index d495ab1..0000000 --- a/common/src/common/world/ChunkCache.java +++ /dev/null @@ -1,27 +0,0 @@ -package common.world; - -import common.util.BlockPos; - -public class ChunkCache -{ - protected final int chunkX; - protected final int chunkZ; - protected final Chunk[][] chunkArray; - - public ChunkCache(World worldIn, BlockPos posFromIn, BlockPos posToIn, int subIn) - { - this.chunkX = posFromIn.getX() - subIn >> 4; - this.chunkZ = posFromIn.getZ() - subIn >> 4; - int i = posToIn.getX() + subIn >> 4; - int j = posToIn.getZ() + subIn >> 4; - this.chunkArray = new Chunk[i - this.chunkX + 1][j - this.chunkZ + 1]; - - for (int k = this.chunkX; k <= i; ++k) - { - for (int l = this.chunkZ; l <= j; ++l) - { - this.chunkArray[k - this.chunkX][l - this.chunkZ] = worldIn.getChunk(k, l); - } - } - } -} diff --git a/common/src/common/worldgen/DebugStates.java b/common/src/common/world/DebugStates.java similarity index 94% rename from common/src/common/worldgen/DebugStates.java rename to common/src/common/world/DebugStates.java index 7487eb7..a569464 100644 --- a/common/src/common/worldgen/DebugStates.java +++ b/common/src/common/world/DebugStates.java @@ -1,4 +1,4 @@ -package common.worldgen; +package common.world; import java.util.List; @@ -6,7 +6,6 @@ import common.block.Block; import common.collect.Lists; import common.init.BlockRegistry; import common.util.ExtMath; -import common.world.State; public class DebugStates { private static final List STATES = Lists.newArrayList(); diff --git a/common/src/common/world/World.java b/common/src/common/world/World.java index 41c6290..66e66ce 100755 --- a/common/src/common/world/World.java +++ b/common/src/common/world/World.java @@ -133,12 +133,7 @@ public abstract class World implements IWorldAccess { this.gravity = Math.signum(this.gravity) * 0.075; } - public Biome getBiomeGenForCoords(final BlockPos pos) { - if(this.isBlockLoaded(pos)) - return this.getChunk(pos).getBiome(pos, null); - else - return Biome.DEF_BIOME; - } + public abstract Biome getBiomeGenForCoords(BlockPos pos); public boolean isAirBlock(BlockPos pos) { return this.getState(pos).getBlock().getMaterial() == Material.air; @@ -191,9 +186,7 @@ public abstract class World implements IWorldAccess { } } - protected boolean isLoaded(int x, int z, boolean allowEmpty) { - return allowEmpty || !this.getChunk(x, z).isDummy(); - } + protected abstract boolean isLoaded(int x, int z, boolean allowEmpty); public Chunk getChunk(BlockPos pos) { return this.getChunk(pos.getX() >> 4, pos.getZ() >> 4); @@ -1822,12 +1815,6 @@ public abstract class World implements IWorldAccess { return (Entity)this.entityIds.lookup(id); } - public void markChunkDirty(BlockPos pos, TileEntity unusedTileEntity) { - if(this.isBlockLoaded(pos)) { - this.getChunk(pos).setModified(); - } - } - public void loadEntities(Collection entityCollection) { this.entities.addAll(entityCollection); diff --git a/server/src/server/network/Player.java b/server/src/server/network/Player.java index a185bbc..f2a7bfb 100755 --- a/server/src/server/network/Player.java +++ b/server/src/server/network/Player.java @@ -119,7 +119,7 @@ import common.util.Position; import common.util.Vec3i; import common.util.WorldPos; import common.village.MerchantRecipeList; -import common.world.Chunk; +import common.world.BlockArray; import common.world.State; import common.world.World; import io.netty.util.concurrent.Future; @@ -134,6 +134,7 @@ import server.clipboard.RotationValue; import server.clipboard.Vector; import server.command.Executor; import server.util.Form; +import server.world.ChunkServer; import server.world.Region; import server.world.WorldServer; @@ -915,6 +916,97 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer } + + public static SPacketChunkData.Extracted getExtractedData(ChunkServer chunk, boolean biomes, boolean overworld, int[] extend) + { + Set aextendedblockstorage = chunk.getStorage(); + SPacketChunkData.Extracted s21packetchunkdata$extracted = new SPacketChunkData.Extracted(); + List list = Lists.newArrayList(); + + if(extend == null) { + for(BlockArray arr : aextendedblockstorage) { + if(arr != null && (!biomes || !arr.isEmpty())) + list.add(arr); + } + } + else { + for(int cy : extend) { + BlockArray arr = chunk.getArray(cy); + if(arr != null && (!biomes || !arr.isEmpty())) + list.add(arr); + } + } + extend = new int[list.size()]; + for(int z = 0; z < extend.length; z++) { + extend[z] = list.get(z).getY() >> 4; + } + + s21packetchunkdata$extracted.extend = extend; + s21packetchunkdata$extracted.data = new byte[SPacketChunkData.getSize(extend.length, overworld, biomes)]; + int j = 0; + + for (BlockArray extendedblockstorage1 : list) + { + char[] achar = extendedblockstorage1.getData(); + + for (char c0 : achar) + { + s21packetchunkdata$extracted.data[j++] = (byte)(c0 & 255); + s21packetchunkdata$extracted.data[j++] = (byte)(c0 >> 8 & 255); + } + } + + for (BlockArray extendedblockstorage2 : list) + { + j = copyTo(extendedblockstorage2.getBlocklight().getData(), s21packetchunkdata$extracted.data, j); + } + + if (overworld) + { + for (BlockArray extendedblockstorage3 : list) + { + j = copyTo(extendedblockstorage3.getSkylight().getData(), s21packetchunkdata$extracted.data, j); + } + } + + if (biomes) + { + copyTo(chunk.getBiomes(), s21packetchunkdata$extracted.data, j); + } + + return s21packetchunkdata$extracted; + } + + private static int copyTo(byte[] src, byte[] dest, int offset) + { + System.arraycopy(src, 0, dest, offset, src.length); + return offset + src.length; + } + + public static SPacketChunkData getPacket(ChunkServer chunkIn, boolean biomes, int[] extend, boolean sky) + { + return new SPacketChunkData(chunkIn.xPos, chunkIn.zPos, biomes, getExtractedData(chunkIn, biomes, sky, extend)); + } + + private static SPacketMapChunkBulk getPacket(List chunks, boolean sky) + { + int i = chunks.size(); + int[] xPositions = new int[i]; + int[] zPositions = new int[i]; + SPacketChunkData.Extracted[] chunksData = new SPacketChunkData.Extracted[i]; + + for (int j = 0; j < i; ++j) + { + ChunkServer chunk = chunks.get(j); + SPacketChunkData.Extracted s21packetchunkdata$extracted = getExtractedData(chunk, true, sky, null); + xPositions[j] = chunk.xPos; + zPositions[j] = chunk.zPos; + chunksData[j] = s21packetchunkdata$extracted; + } + + return new SPacketMapChunkBulk(xPositions, zPositions, chunksData, sky); + } + public void updateEntity() { @@ -951,7 +1043,7 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer if (!this.loadedChunks.isEmpty()) { - List list = Lists.newArrayList(); + List list = Lists.newArrayList(); Iterator iterator1 = this.loadedChunks.iterator(); List list1 = Lists.newArrayList(); @@ -965,7 +1057,7 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer { if (this.entity.worldObj.isBlockLoaded(new BlockPos(chunkcoordintpair.x << 4, 0, chunkcoordintpair.z << 4))) { - Chunk chunk = this.entity.worldObj.getChunk(chunkcoordintpair.x, chunkcoordintpair.z); + ChunkServer chunk = this.getEntityWorld().getChunk(chunkcoordintpair.x, chunkcoordintpair.z); if (chunk.isPopulated()) { @@ -985,11 +1077,11 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer { if (list.size() == 1) { - this.sendPacket(new SPacketChunkData((Chunk)list.get(0), true, null)); + this.sendPacket(getPacket(list.get(0), true, null, !this.entity.worldObj.dimension.hasNoLight())); } else { - this.sendPacket(new SPacketMapChunkBulk(list)); + this.sendPacket(getPacket(list, !this.entity.worldObj.dimension.hasNoLight())); } for (TileEntity tileentity : list1) @@ -997,7 +1089,7 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer this.sendTileEntityUpdate(tileentity); } - for (Chunk chunk1 : list) + for (ChunkServer chunk1 : list) { this.getEntityWorld().updateChunksForPlayer(this.entity, chunk1); } diff --git a/server/src/server/world/ChunkServer.java b/server/src/server/world/ChunkServer.java new file mode 100644 index 0000000..15ee816 --- /dev/null +++ b/server/src/server/world/ChunkServer.java @@ -0,0 +1,216 @@ +package server.world; + +import java.util.Map; +import java.util.Set; +import common.biome.Biome; +import common.block.Block; +import common.entity.Entity; +import common.init.BlockRegistry; +import common.init.Blocks; +import common.log.Log; +import common.material.Material; +import common.rng.Random; +import common.tileentity.TileEntity; +import common.util.BlockPos; +import common.world.BlockArray; +import common.world.Chunk; +import common.world.State; +import common.world.World; +import server.worldgen.BiomeGenerator; + +public class ChunkServer extends Chunk { + private long lastSave; + private long inhabited; + + public ChunkServer(World world, int x, int z) { + super(world, x, z); + } + + public ChunkServer(World world, short[] data, int height, boolean base, boolean ceil, Random rand, Biome[] biomes, int x, int z) { + this(world, x, z); + boolean sky = !world.dimension.hasNoLight(); + for(int bx = 0; bx < 16; ++bx) { + for(int bz = 0; bz < 16; ++bz) { + for(int by = 0; by < height; ++by) { + State state = BlockRegistry.STATEMAP.getByValue(data[bx << 4 | bz | by << 8]); + if(state != null && state.getBlock().getMaterial() != Material.air) { + int y = by >> 4; + 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) { + Block caves = world.dimension.getCaveFiller().getBlock(); + 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)) { + Block block = arr.get(bx, by, bz).getBlock(); + if(block == Blocks.air || block.getMaterial().isLiquid() || block == caves) + arr.set(bx, by, bz, this.filler); + } + } + } + } + } + if(ceil) { + int y = (height - 1) >> 4; + BlockArray arr = this.getArray(y); + if(arr == null) { + arr = new BlockArray(y << 4, sky, null); + this.setArray(arr); + } + y = (height - 5) >> 4; + 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.getArray(by >> 4).set(bx, by & 15, bz, Blocks.air.getState()); + } + } + } + } + for(int n = 0; n < this.biomes.length; ++n) { + this.biomes[n] = (byte)biomes[n].id; + } + if(ceil) + this.resetRelight(); + else + this.genSkyLight(); + } + + public int getTopSegment() { + return this.top; + } + + public int getBottomSegment() { + return this.bottom; + } + + public Set getStorage() { + return this.blockList; + } + + public void addTileEntity(TileEntity tile) { + this.addTileEntity(tile.getPos(), tile); + + if(this.loaded) { + this.world.addTileEntity(tile); + } + } + + public void onChunkLoad() { + this.loaded = true; + this.world.addTileEntities(this.tiles.values()); + + for(int n = 0; n < this.entities.length; ++n) { + for(Entity entity : this.entities[n]) { + entity.onChunkLoad(); + } + + this.world.loadEntities(this.entities[n]); + } + } + + public boolean isDirty(long time) { + if(this.hasEntity && time != this.lastSave || this.modified) { + return true; + } + return this.modified; + } + + public void setStorage(BlockArray[] data) { + for(BlockArray arr : data) { + this.setArray(arr); + } + } + + public Biome getBiome(BlockPos pos, BiomeGenerator gen) { + int x = pos.getX() & 15; + int z = pos.getZ() & 15; + int o = this.biomes[z << 4 | x] & 255; + + if(o == 255) { + Biome biome = gen == null ? Biome.DEF_BIOME : gen.getBiomeGenerator(pos, Biome.DEF_BIOME); + o = biome.id; + this.biomes[z << 4 | x] = (byte)(o & 255); + } + + return Biome.getBiomeDef(o); + } + + public byte[] getBiomes() { + return this.biomes; + } + + public int[] getHeights() { + return this.height; + } + + public void setHeights(int[] map) { + if(this.height.length != map.length) { + Log.JNI.warn("Konnte Höhen des Chunks nicht setzen, Länge des Arrays ist " + map.length + " statt " + this.height.length); + } + else { + for(int n = 0; n < this.height.length; ++n) { + this.height[n] = map[n]; + } + } + } + + public Map getTiles() { + return this.tiles; + } + + public boolean isTerrainPopulated() { + return this.populated; + } + + public void setTerrainPopulated(boolean populated) { + this.populated = populated; + } + + public boolean isLightPopulated() { + return this.lightInit; + } + + public void setLightPopulated(boolean populated) { + this.lightInit = populated; + } + + public void setModified(boolean modified) { + this.modified = modified; + } + + public void setHasEntities(boolean entities) { + this.hasEntity = entities; + } + + public void setSaved(long time) { + this.lastSave = time; + } + + public long getInhabited() { + return this.inhabited; + } + + public void setInhabited(long time) { + this.inhabited = time; + } +} diff --git a/server/src/server/world/Region.java b/server/src/server/world/Region.java index 0753655..50921d6 100755 --- a/server/src/server/world/Region.java +++ b/server/src/server/world/Region.java @@ -34,7 +34,6 @@ import common.util.NextTickListEntry; import common.util.NibbleArray; import common.util.Util; import common.world.BlockArray; -import common.world.Chunk; public class Region { private static class ChunkBuffer extends ByteArrayOutputStream { @@ -360,7 +359,7 @@ public class Region { // getRegionFile(dir, x >> 3, z >> 3).writeTag(x & 7, z & 7, tag); } - public static Chunk readNbt(WorldServer world, int x, int z, NBTTagCompound tag) { + public static ChunkServer readNbt(WorldServer world, int x, int z, NBTTagCompound tag) { // if(!tag.hasKey("Level", 10)) { // Log.error("Chunk-Datei bei " + x + "," + z + " hat keine Level-Daten, überspringe"); // return null; @@ -370,7 +369,7 @@ public class Region { Log.JNI.warn("Chunk-Datei bei " + x + "," + z + " hat keine Block-Daten, überspringe"); return null; } - Chunk chunk = new Chunk(world, x, z); + ChunkServer chunk = new ChunkServer(world, x, z); chunk.setHeights(tag.getIntArray("HeightMap")); chunk.setTerrainPopulated(tag.getBoolean("TerrainPopulated")); chunk.setLightPopulated(tag.getBoolean("LightPopulated")); @@ -486,7 +485,7 @@ public class Region { return chunk; } - public static NBTTagCompound writeNbt(WorldServer world, Chunk chunk) { + public static NBTTagCompound writeNbt(WorldServer world, ChunkServer chunk) { NBTTagCompound tag = new NBTTagCompound(); // tag.setShort("V", (short)Config.PROTOCOL); tag.setLong("LastUpdate", world.getTime()); diff --git a/server/src/server/world/Spawner.java b/server/src/server/world/Spawner.java index 49a623f..bbaea74 100755 --- a/server/src/server/world/Spawner.java +++ b/server/src/server/world/Spawner.java @@ -14,7 +14,6 @@ import common.rng.WeightedList; import common.util.BlockPos; import common.util.ChunkPos; import common.util.ExtMath; -import common.world.Chunk; import common.world.World; import server.biome.GenBiome; import server.biome.RngSpawn; @@ -87,7 +86,7 @@ public abstract class Spawner { if(cur <= max) { typeLabel: for(ChunkPos coord : CHUNKS) { - Chunk chunk = world.getChunk(coord.x, coord.z); + ChunkServer chunk = world.getChunk(coord.x, coord.z); int x = coord.x * 16 + world.rand.zrange(16); int z = coord.z * 16 + world.rand.zrange(16); int h = chunk.getTopSegment(); diff --git a/server/src/server/world/WorldServer.java b/server/src/server/world/WorldServer.java index f151139..46f8957 100755 --- a/server/src/server/world/WorldServer.java +++ b/server/src/server/world/WorldServer.java @@ -24,6 +24,9 @@ import common.collect.Lists; import common.collect.Maps; import common.collect.Sets; import common.dimension.Dimension; +import common.dimension.Lake; +import common.dimension.Liquid; +import common.dimension.Ore; import common.entity.DamageSource; import common.entity.Entity; import common.entity.EntityTrackerEntry; @@ -55,7 +58,6 @@ import common.packet.SPacketBiomes; import common.packet.SPacketBlockAction; import common.packet.SPacketBlockBreakAnim; import common.packet.SPacketBlockChange; -import common.packet.SPacketChunkData; import common.packet.SPacketMultiBlockChange; import common.rng.Random; import common.rng.WeightedList; @@ -73,17 +75,12 @@ import common.util.Position; import common.util.Vec3; import common.village.Village; import common.world.BlockArray; -import common.world.Chunk; import common.world.Explosion; import common.world.AWorldServer; import common.world.LightType; import common.world.State; import common.world.Weather; import common.world.World; -import common.worldgen.BiomeGenerator; -import common.worldgen.FeatureLake; -import common.worldgen.FeatureLiquid; -import common.worldgen.FeatureOre; import server.Server; import server.biome.GenBiome; import server.biome.RngSpawn; @@ -93,6 +90,7 @@ import server.village.VillageCollection; import server.worldgen.BiomeGenLayered; import server.worldgen.BiomeGenPerlin; import server.worldgen.BiomeGenSingle; +import server.worldgen.BiomeGenerator; import server.worldgen.BlockReplacer; import server.worldgen.ChunkGenerator; import server.worldgen.ChunkPrimer; @@ -132,8 +130,8 @@ public final class WorldServer extends AWorldServer { private final EventList[] queue = new EventList[] {new EventList(), new EventList()}; private final List ticksNow = Lists.newArrayList(); private final Set dropped = Collections.newSetFromMap(new ConcurrentHashMap()); - private final LongHashMap chunks = new LongHashMap(); - private final List loaded = Lists.newArrayList(); + private final LongHashMap chunks = new LongHashMap(); + private final List loaded = Lists.newArrayList(); private final Map toRemove = new ConcurrentHashMap(); private final Set pending = Collections.newSetFromMap(new ConcurrentHashMap()); private final LongHashMap loaders = new LongHashMap(); @@ -263,7 +261,7 @@ public final class WorldServer extends AWorldServer { return null; FeatureOres[] gens = new FeatureOres[this.dimension.getOres().size()]; for(int z = 0; z < gens.length; z++) { - FeatureOre gen = this.dimension.getOres().get(z); + Ore gen = this.dimension.getOres().get(z); gens[z] = new FeatureOres(gen.state, gen.count, gen.more, gen.size, gen.min, gen.max, gen.dist); } return gens; @@ -274,7 +272,7 @@ public final class WorldServer extends AWorldServer { return null; FeatureLakes[] gens = new FeatureLakes[this.dimension.getLakes().size()]; for(int z = 0; z < gens.length; z++) { - FeatureLake gen = this.dimension.getLakes().get(z); + Lake gen = this.dimension.getLakes().get(z); gens[z] = new FeatureLakes(gen.state, gen.filler, gen.top, gen.chance, gen.minHeight, gen.maxHeight, gen.ratiod); } return gens; @@ -285,7 +283,7 @@ public final class WorldServer extends AWorldServer { return null; FeatureLiquids[] gens = new FeatureLiquids[this.dimension.getLiquids().size()]; for(int z = 0; z < gens.length; z++) { - FeatureLiquid gen = this.dimension.getLiquids().get(z); + Liquid gen = this.dimension.getLiquids().get(z); gens[z] = new FeatureLiquids(gen.state, gen.chance, gen.minHeight, gen.maxHeight, gen.lower); } return gens; @@ -515,7 +513,7 @@ public final class WorldServer extends AWorldServer { for(int i = 0; i < 100; ++i) { if(!this.dropped.isEmpty()) { Long v = (Long)this.dropped.iterator().next(); - Chunk chunk = (Chunk)this.chunks.getValueByKey(v.longValue()); + ChunkServer chunk = this.chunks.getValueByKey(v.longValue()); if(chunk != null) { chunk.onChunkUnload(); this.saveChunkData(chunk); @@ -656,7 +654,7 @@ public final class WorldServer extends AWorldServer { int k = chunkcoordintpair.x * 16; int l = chunkcoordintpair.z * 16; // this.profiler.start("getChunk"); - Chunk chunk = this.getChunk(chunkcoordintpair.x, chunkcoordintpair.z); + ChunkServer chunk = this.getChunk(chunkcoordintpair.x, chunkcoordintpair.z); // this.profiler.next("moodSound"); // this.playMoodSound(k, l, chunk); // this.profiler.next("checkLight"); @@ -891,7 +889,7 @@ public final class WorldServer extends AWorldServer { } } - public List getPendingBlockUpdates(Chunk chunk) { + public List getPendingBlockUpdates(ChunkServer chunk) { int x1 = (chunk.xPos << 4) - 2; int x2 = x1 + 16 + 2; int z1 = (chunk.zPos << 4) - 2; @@ -1071,15 +1069,15 @@ public final class WorldServer extends AWorldServer { Log.JNI.error(e, "Konnte Dorfliste nicht speichern"); } } - List list = Lists.newArrayList(this.loaded); + List list = Lists.newArrayList(this.loaded); for(int n = 0; n < list.size(); ++n) { - Chunk chunk = list.get(n); + ChunkServer chunk = list.get(n); if(chunk.isDirty(this.time)) { this.saveChunkData(chunk); chunk.setModified(false); } } - for(Chunk chunk : Lists.newArrayList(this.loaded)) { + for(ChunkServer chunk : Lists.newArrayList(this.loaded)) { if(chunk != null && !this.hasPlayerInstance(chunk.xPos, chunk.zPos)) { this.dropChunk(chunk.xPos, chunk.zPos); } @@ -1325,14 +1323,18 @@ public final class WorldServer extends AWorldServer { } protected boolean isLoaded(int x, int z, boolean allowEmpty) { - return this.chunkExists(x, z) && super.isLoaded(x, z, allowEmpty); + return this.chunkExists(x, z); } - public Chunk getChunk(int x, int z) { - Chunk chunk = this.chunks.getValueByKey(LongHashMap.packInt(x, z)); + public ChunkServer getChunk(int x, int z) { + ChunkServer chunk = this.chunks.getValueByKey(LongHashMap.packInt(x, z)); return chunk == null ? this.loadChunk(x, z) : chunk; } + public ChunkServer getChunk(BlockPos pos) { + return this.getChunk(pos.getX() >> 4, pos.getZ() >> 4); + } + private boolean chunkExists(int x, int z) { return this.chunks.containsItem(LongHashMap.packInt(x, z)); } @@ -1350,15 +1352,15 @@ public final class WorldServer extends AWorldServer { } public void unloadAllChunks() { - for(Chunk chunk : this.loaded) { + for(ChunkServer chunk : this.loaded) { this.dropChunk(chunk.xPos, chunk.zPos); } } - public Chunk loadChunk(int x, int z) { + public ChunkServer loadChunk(int x, int z) { long id = LongHashMap.packInt(x, z); this.dropped.remove(Long.valueOf(id)); - Chunk chunk = (Chunk)this.chunks.getValueByKey(id); + ChunkServer chunk = this.chunks.getValueByKey(id); if(chunk == null) { if(!this.debug) @@ -1377,7 +1379,7 @@ public final class WorldServer extends AWorldServer { return chunk; } - private Chunk loadChunkFromFile(int x, int z) { + private ChunkServer loadChunkFromFile(int x, int z) { try { ChunkPos coord = new ChunkPos(x, z); NBTTagCompound tag = this.toRemove.get(coord); @@ -1389,7 +1391,7 @@ public final class WorldServer extends AWorldServer { } // tag = CompressedStreamTools.read(in); } - Chunk chunk = Region.readNbt(this, x, z, tag); + ChunkServer chunk = Region.readNbt(this, x, z, tag); if(chunk != null) { chunk.setSaved(this.time); if(this.mineshaftGen != null) { @@ -1416,7 +1418,7 @@ public final class WorldServer extends AWorldServer { } } - private void saveChunkData(Chunk chunk) { + private void saveChunkData(ChunkServer chunk) { // try { chunk.setSaved(this.time); // this.lock.check(); @@ -1424,7 +1426,7 @@ public final class WorldServer extends AWorldServer { // NBTTagCompound ltag = new NBTTagCompound(); // tag.setTag("Level", ltag); NBTTagCompound tag = Region.writeNbt(this, chunk); - ChunkPos coord = chunk.getPos(); + ChunkPos coord = new ChunkPos(chunk.xPos, chunk.zPos); if(!this.pending.contains(coord)) { this.toRemove.put(coord, tag); } @@ -1533,7 +1535,7 @@ public final class WorldServer extends AWorldServer { } private void populate(int x, int z) { - Chunk chunk = this.getChunk(x, z); + ChunkServer chunk = this.getChunk(x, z); if(!chunk.isTerrainPopulated()) { chunk.checkLight(); BlockFalling.fallInstantly = true; @@ -1602,11 +1604,11 @@ public final class WorldServer extends AWorldServer { } // } BlockFalling.fallInstantly = false; - chunk.setModified(); + chunk.setModified(true); } } - private Chunk generate(int x, int z) { + private ChunkServer generate(int x, int z) { this.grng.setSeed((long)x * 341873128712L + (long)z * 132897987541L); ChunkPrimer primer = new ChunkPrimer(this.height); this.generator.generateChunk(this, x, z, primer); @@ -1638,7 +1640,7 @@ public final class WorldServer extends AWorldServer { if(this.scatteredGen != null) { this.scatteredGen.generate(this, x, z, primer); } - return new Chunk(this, primer.getData(), primer.height, this.base, this.ceil, this.grng, this.biomes, x, z); + return new ChunkServer(this, primer.getData(), primer.height, this.base, this.ceil, this.grng, this.biomes, x, z); } public boolean isExterminated() { @@ -1673,7 +1675,7 @@ public final class WorldServer extends AWorldServer { this.exterminated = true; // this.dataModified = true; for(Long v : this.dropped) { - Chunk chunk = this.chunks.getValueByKey(v.longValue()); + ChunkServer chunk = this.chunks.getValueByKey(v.longValue()); if(chunk != null) { chunk.onChunkUnload(); this.chunks.remove(v.longValue()); @@ -1681,10 +1683,10 @@ public final class WorldServer extends AWorldServer { } } this.dropped.clear(); - List loaded = Lists.newArrayList(this.loaded); + List loaded = Lists.newArrayList(this.loaded); this.loaded.clear(); this.setExterminatedGen(); - for(Chunk chunk : loaded) { + for(ChunkServer chunk : loaded) { long pos = LongHashMap.packInt(chunk.xPos, chunk.zPos); chunk.onChunkUnload(); this.chunks.remove(pos); @@ -1693,9 +1695,9 @@ public final class WorldServer extends AWorldServer { this.loaded.add(chunk); chunk.onChunkLoad(); chunk.checkLight(); - chunk.setModified(); + chunk.setModified(true); } - for(Chunk chunk : this.loaded) { + for(ChunkServer chunk : this.loaded) { chunk.update(false); } this.entities.removeAll(this.unloaded); @@ -1877,8 +1879,8 @@ public final class WorldServer extends AWorldServer { PlayerInstance ins = this.instances.getValueByKey(v); if(ins == null) return false; - Chunk chunk = this.getChunk(chunkX, chunkZ); - chunk.setModified(); + ChunkServer chunk = this.getChunk(chunkX, chunkZ); + chunk.setModified(true); ins.sendToAllPlayersWatchingChunk(new SPacketBiomes(chunkX, chunkZ, chunk.getBiomes())); return true; } @@ -2176,7 +2178,7 @@ public final class WorldServer extends AWorldServer { } } - public void updateChunksForPlayer(EntityNPC player, Chunk chunk) { + public void updateChunksForPlayer(EntityNPC player, ChunkServer chunk) { for(EntityTrackerEntry entitytrackerentry : this.tracked) { if(entitytrackerentry.trackedEntity != player && entitytrackerentry.trackedEntity.chunkCoordX == chunk.xPos && entitytrackerentry.trackedEntity.chunkCoordZ == chunk.zPos) { @@ -2189,7 +2191,7 @@ public final class WorldServer extends AWorldServer { // int x = position.getBlockX(); // int y = position.getBlockY(); // int z = position.getBlockZ(); - Chunk chunk = this.getChunk(pos.getX() >> 4, pos.getZ() >> 4); + ChunkServer chunk = this.getChunk(pos.getX() >> 4, pos.getZ() >> 4); // BlockPos pos = new BlockPos(x, y, z); State old = chunk.getState(pos); State newState = block.getState(); @@ -2249,7 +2251,7 @@ public final class WorldServer extends AWorldServer { // } private final boolean setChunkBiome(BlockPos position, Biome biome) { - Chunk chunk = this.getChunk(position); + ChunkServer chunk = this.getChunk(position); if((chunk != null) && (chunk.isLoaded())) { chunk.getBiomes()[((position.getZ() & 0xF) << 4 | position.getX() & 0xF)] = (byte)biome.id; return true; @@ -2437,7 +2439,7 @@ public final class WorldServer extends AWorldServer { } public BlockPos getTopSolidOrLiquidBlock(BlockPos pos) { - Chunk chunk = this.getChunk(pos); + ChunkServer chunk = this.getChunk(pos); int h = chunk.getTopSegment(); if(h == Integer.MIN_VALUE) return new BlockPos(pos.getX(), 0, pos.getZ()); @@ -2792,6 +2794,11 @@ public final class WorldServer extends AWorldServer { return this.server.getWorld(dimension); } + public void markChunkDirty(BlockPos pos) { + if(this.isBlockLoaded(pos)) + this.getChunk(pos).setModified(true); + } + private static class EventList extends ArrayList { private EventList() { } @@ -2808,6 +2815,15 @@ public final class WorldServer extends AWorldServer { this.tag = tag; } } + + private static SPacketMultiBlockChange getPacket(int amount, long[] list, ChunkServer chunk) { + ChunkPos pos = new ChunkPos(chunk.xPos, chunk.zPos); + SPacketMultiBlockChange.BlockUpdateData[] changes = new SPacketMultiBlockChange.BlockUpdateData[amount]; + for(int z = 0; z < changes.length; z++) { + changes[z] = new SPacketMultiBlockChange.BlockUpdateData(list[z], chunk.getState(SPacketMultiBlockChange.getPos(pos, list[z]))); + } + return new SPacketMultiBlockChange(pos, changes); + } private class PlayerInstance { private final List watching = Lists.newArrayList(); @@ -2841,10 +2857,10 @@ public final class WorldServer extends AWorldServer { public void removePlayer(EntityNPC player) { if(this.watching.contains(player)) { - Chunk chunk = WorldServer.this.getChunk(this.position.x, this.position.z); + ChunkServer chunk = WorldServer.this.getChunk(this.position.x, this.position.z); if(chunk.isPopulated()) { - player.connection.sendPacket(new SPacketChunkData(chunk, true, new int[0])); + player.connection.sendPacket(Player.getPacket(chunk, true, new int[0], !WorldServer.this.dimension.hasNoLight())); } this.watching.remove(player); @@ -2876,7 +2892,7 @@ public final class WorldServer extends AWorldServer { this.biomes = true; } - private void increaseInhabitedTime(Chunk chunk) { + private void increaseInhabitedTime(ChunkServer chunk) { chunk.setInhabited(chunk.getInhabited() + WorldServer.this.time - this.prevTime); this.prevTime = WorldServer.this.time; } @@ -2935,8 +2951,8 @@ public final class WorldServer extends AWorldServer { extend[n++] = i; } } - this.sendToAllPlayersWatchingChunk(new SPacketChunkData(WorldServer.this.getChunk(this.position.x, this.position.z), - this.biomes, extend)); + this.sendToAllPlayersWatchingChunk(Player.getPacket(WorldServer.this.getChunk(this.position.x, this.position.z), + this.biomes, extend, !WorldServer.this.dimension.hasNoLight())); if(this.biomes) { List list = WorldServer.this.getTileEntitiesIn(x, Integer.MIN_VALUE, z, x + 16, Integer.MAX_VALUE, z + 16); @@ -2957,7 +2973,7 @@ public final class WorldServer extends AWorldServer { } } else { - this.sendToAllPlayersWatchingChunk(new SPacketMultiBlockChange(this.updates, this.changes, + this.sendToAllPlayersWatchingChunk(getPacket(this.updates, this.changes, WorldServer.this.getChunk(this.position.x, this.position.z))); for(int n = 0; n < this.updates; ++n) { diff --git a/server/src/server/worldgen/BiomeGenLayered.java b/server/src/server/worldgen/BiomeGenLayered.java index bdf9230..7c03681 100755 --- a/server/src/server/worldgen/BiomeGenLayered.java +++ b/server/src/server/worldgen/BiomeGenLayered.java @@ -7,7 +7,6 @@ import common.biome.Biome; import common.collect.Lists; import common.util.BlockPos; import common.util.LongHashMap; -import common.worldgen.BiomeGenerator; import server.worldgen.layer.GenLayer; import server.worldgen.layer.GenLayerAddAreas; import server.worldgen.layer.GenLayerAddExtra; diff --git a/server/src/server/worldgen/BiomeGenSingle.java b/server/src/server/worldgen/BiomeGenSingle.java index 586058f..cd5bade 100755 --- a/server/src/server/worldgen/BiomeGenSingle.java +++ b/server/src/server/worldgen/BiomeGenSingle.java @@ -5,7 +5,6 @@ import java.util.Set; import common.biome.Biome; import common.util.BlockPos; -import common.worldgen.BiomeGenerator; public class BiomeGenSingle implements BiomeGenerator { private final Biome biome; diff --git a/common/src/common/worldgen/BiomeGenerator.java b/server/src/server/worldgen/BiomeGenerator.java similarity index 96% rename from common/src/common/worldgen/BiomeGenerator.java rename to server/src/server/worldgen/BiomeGenerator.java index b6ef4e9..6d75568 100755 --- a/common/src/common/worldgen/BiomeGenerator.java +++ b/server/src/server/worldgen/BiomeGenerator.java @@ -1,4 +1,4 @@ -package common.worldgen; +package server.worldgen; import java.util.Set; diff --git a/server/src/server/worldgen/GeneratorDebug.java b/server/src/server/worldgen/GeneratorDebug.java index d1eb549..1158b5c 100755 --- a/server/src/server/worldgen/GeneratorDebug.java +++ b/server/src/server/worldgen/GeneratorDebug.java @@ -1,7 +1,7 @@ package server.worldgen; +import common.world.DebugStates; import common.world.State; -import common.worldgen.DebugStates; import server.world.WorldServer; public class GeneratorDebug implements ChunkGenerator diff --git a/server/src/server/worldgen/structure/StructureVillage.java b/server/src/server/worldgen/structure/StructureVillage.java index 498cec0..0fb61ae 100755 --- a/server/src/server/worldgen/structure/StructureVillage.java +++ b/server/src/server/worldgen/structure/StructureVillage.java @@ -22,8 +22,8 @@ import common.rng.Random; import common.util.BlockPos; import common.util.Facing; import common.world.State; -import common.worldgen.BiomeGenerator; import server.world.WorldServer; +import server.worldgen.BiomeGenerator; import server.worldgen.LootConstants;