diff --git a/client/src/client/Client.java b/client/src/client/Client.java index 3ac6dda..733137d 100755 --- a/client/src/client/Client.java +++ b/client/src/client/Client.java @@ -95,6 +95,7 @@ import client.window.Wheel; import client.window.Window; import client.window.WindowEvent; import client.world.WorldClient; +import common.biome.Biome; import common.block.Block; import common.collect.Lists; import common.collect.Maps; @@ -156,7 +157,9 @@ 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; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelException; @@ -424,9 +427,8 @@ public class Client implements IThreadListener { public int soundBufferSize = 2048; @Variable(name = "snd_frame_size", category = CVarCategory.SOUND, min = 2, max = 8192, display = "PCM-Intervall") public int soundFrameSize = 32; - + private String serverInfo; - private String tickInfo; private int lastTickTime = -1; private AudioInterface audio; private boolean cfgDirty; @@ -1651,11 +1653,10 @@ public class Client implements IThreadListener { this.serverInfo = info; } - public void setLastTick(int time, String info) { + public void setLastTick(int time) { if(this.lastTickTime >= 0) { this.lastTicked = System.currentTimeMillis(); this.lastTickTime = time; - this.tickInfo = info; } } @@ -1729,20 +1730,30 @@ public class Client implements IThreadListener { break; } - String light; + Biome biome = null; + String bline; + String lline; if(this.world.isBlockLoaded(blockpos)) { Chunk chunk = this.world.getChunk(blockpos); - light = "Licht: " + chunk.getLightSub(blockpos, 0) + " (" - + chunk.getLight(blockpos) + " Blöcke, " + String.format( + biome = chunk.getBiome(blockpos, null); + bline = "Biom: " + biome.display + " (" + biome.id + ")" + /* (this.debugHideInfo ? "" : */ (", D: " + + TextColor.stripCodes(this.world.dimension.getFormattedName(false)) + + " (" + this.world.dimension.getDimensionId() + ")"); + lline = "Licht: " + chunk.getLightSub(blockpos, 0) + " (" + chunk.getLight(LightType.SKY, blockpos) + " Himmel, " + + chunk.getLight(LightType.BLOCK, blockpos) + " Blöcke, " + String.format( "%.1f", this.world.getSunBrightness(1.0f) * 15.0f) + " Welt), A: " + String.format("%.3f", this.world.getCelestialAngle(1.0f)); } else { - light = "Licht: " + String.format( + bline = "Biom: , D: " + + TextColor.stripCodes(this.world.dimension.getFormattedName(false)) + + " (" + this.world.dimension.getDimensionId() + ")"; + lline = "Licht: " + String.format( "%.1f", this.world.getSunBrightness(1.0f) * 15.0f) + " Welt, A: " + String.format("%.3f", this.world.getCelestialAngle(1.0f)); } - + + float temp = this.world.getTempOffset() + (biome != null ? biome.getTemperature(blockpos) : 0.0f); long ticked = System.currentTimeMillis() - this.lastTicked; return @@ -1767,10 +1778,8 @@ public class Client implements IThreadListener { String.format(" (Zoom x%.1f)", this.zoomLevel) : "") + "\n" + String.format("Richtung: %s (%.1f / %.1f)", dirStr, ExtMath.wrapf(entity.rotYaw), ExtMath.wrapf(entity.rotPitch)) + "\n" + - "Dimension: " + (this.world.isExterminated() ? "[zerstört] " : "") + - TextColor.stripCodes(this.world.dimension.getFormattedName(false)) + - " (" + this.world.dimension.getDimensionId() + ")" + "\n" + - light + "\n" + + bline + "\n" + + lline + "\n" + String.format("Zeit: %d T, R %d / %d T, U %d / %d T", this.world.getDayTime(), this.world.getDayTime() % this.world.dimension.getRotationalPeriod(), @@ -1778,7 +1787,10 @@ public class Client implements IThreadListener { this.world.getDayTime() % this.world.dimension.getOrbitalPeriod(), this.world.dimension.getOrbitalPeriod() ) + "\n" + - String.format("Wetter: %s (R %.1f, %.1f)", + String.format("Laub: %s%s, T: %.2f K / %.2f °C, %s (R %.1f, %.1f)", + !this.world.dimension.getType().days ? "*" : "", + this.world.getLeavesGen(blockpos).getDisplayName(), + temp, World.ABSOLUTE_ZERO + temp, this.world.getWeather().getDisplay(), this.world.getRainStrength(), this.world.getDarkness() ) + "\n" + @@ -1788,8 +1800,7 @@ public class Client implements IThreadListener { String.format("Letzte Zeitsynch.: + %d.%d s", ticked / 1000L, (ticked / 100L) % 10L ) + - (this.serverInfo != null ? "\n" + this.serverInfo : "") + - (this.tickInfo != null ? "\n" + this.tickInfo : "") + (this.serverInfo != null ? "\n" + this.serverInfo : "") // IWorldServer world = this.server.getWorld(this.theWorld.dimension.getDimensionId()); // if(world != null) // list.add("Seed: " + world.getSeed()); @@ -1856,7 +1867,7 @@ public class Client implements IThreadListener { "Eigens.: " + (entity.dead ? "D" : " ") + (entity.noClip ? "N" : " ") + (entity.onGround ? "G" : " ") + (entity.canBeCollidedWith() ? "C" : " ") + (entity.canBePushed() ? "P" : " ") + (entity.isBurning() ? "B" : " ") // + (entity.isInvisible() ? "I" : " ") // + (entity.isSilent() ? "S" : " ") - + (entity.canAttackWithItem() ? "A" : " ") + + (entity.isWet() ? "W" : " ") + (entity.canAttackWithItem() ? "A" : " ") + (entity.passenger != null ? "H" : " ") + (entity.vehicle != null ? "R" : " ") + (entity instanceof EntityLiving ? ("+" /* + (((EntityLivingBase)entity).isEntityUndead() ? "U" : " ") */ // + (((EntityLivingBase)entity).isChild() ? "C" : " ") + (((EntityLiving)entity).doesEntityNotTriggerPressurePlate() ? "P" : " ")) : "") + "\n" + @@ -2598,7 +2609,6 @@ public class Client implements IThreadListener { if(Client.this.lastTickTime >= 0) { Client.this.performAction(Action.STOP_PROFILING); Client.this.lastTickTime = -1; - Client.this.tickInfo = null; } else { Client.this.performAction(Action.START_PROFILING); diff --git a/client/src/client/network/ClientPlayer.java b/client/src/client/network/ClientPlayer.java index fd0f656..eb3c533 100755 --- a/client/src/client/network/ClientPlayer.java +++ b/client/src/client/network/ClientPlayer.java @@ -94,6 +94,7 @@ import common.packet.S39PacketPlayerAbilities; import common.packet.S3APacketTabComplete; import common.packet.S43PacketUpdateEntityNBT; import common.packet.SPacketAnimation; +import common.packet.SPacketBiomes; import common.packet.SPacketBlockAction; import common.packet.SPacketBlockBreakAnim; import common.packet.SPacketBlockChange; @@ -752,7 +753,7 @@ public class ClientPlayer extends NetHandler implements IClientPlayer { NetHandler.checkThread(packetIn, this, this.gameController, this.clientWorldController); - if (packetIn.isResend()) + if (packetIn.hasBiomes()) { if (packetIn.getExtractedSize() == 0) { @@ -765,15 +766,23 @@ 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()); - chunk.setData(packetIn.getExtractedDataBytes(), packetIn.getExtractedSize(), packetIn.isResend()); + chunk.setData(packetIn.getExtractedDataBytes(), packetIn.getExtractedSize(), packetIn.hasBiomes()); this.clientWorldController.markBlockRangeForRenderUpdate(packetIn.getChunkX() << 4, 0, packetIn.getChunkZ() << 4, (packetIn.getChunkX() << 4) + 15, 512, (packetIn.getChunkZ() << 4) + 15); - if (!packetIn.isResend() || this.clientWorldController.dimension.hasNoLight()) // TODO: check + if (!packetIn.hasBiomes() || this.clientWorldController.dimension.hasNoLight()) // TODO: check { chunk.resetRelight(); } } + public void handleBiomes(SPacketBiomes packetIn) + { + NetHandler.checkThread(packetIn, this, this.gameController, this.clientWorldController); + Chunk chunk = this.clientWorldController.getChunk(packetIn.getChunkX(), packetIn.getChunkZ()); + chunk.setBiomes(packetIn.getBiomes()); + this.clientWorldController.markBlockRangeForRenderUpdate(packetIn.getChunkX() << 4, 0, packetIn.getChunkZ() << 4, (packetIn.getChunkX() << 4) + 15, 512, (packetIn.getChunkZ() << 4) + 15); + } + /** * Updates the block and metadata and generates a blockupdate (and notify the clients) */ @@ -989,7 +998,7 @@ public class ClientPlayer extends NetHandler implements IClientPlayer public void handleServerTick(SPacketServerTick packet) { NetHandler.checkThread(packet, this, this.gameController); - this.gameController.setLastTick(packet.getTime(), packet.getServerinfo()); + this.gameController.setLastTick(packet.getTime()); } // public void handleCompass(SPacketCompass packetIn) @@ -1432,6 +1441,9 @@ public class ClientPlayer extends NetHandler implements IClientPlayer case FOG_STRENGTH: this.clientWorldController.setFogStrength(packetIn.getFloat(true)); break; + case TEMPERATURE: + this.clientWorldController.setTemperature(packetIn.getFloat(false)); + break; } } diff --git a/client/src/client/renderer/EntityRenderer.java b/client/src/client/renderer/EntityRenderer.java index 36a3002..9e5bf48 100755 --- a/client/src/client/renderer/EntityRenderer.java +++ b/client/src/client/renderer/EntityRenderer.java @@ -14,6 +14,7 @@ import client.renderer.particle.EffectRenderer; import client.renderer.texture.DynamicTexture; import client.renderer.texture.TextureMap; import client.world.WorldClient; +import common.biome.Biome; import common.block.Block; import common.entity.Entity; import common.entity.npc.EntityNPC; @@ -1142,10 +1143,11 @@ public class EntityRenderer { for (int l = 0; l < k; ++l) { - BlockPos blockpos1 = world.getPrecipitationHeight(blockpos.add(this.random.zrange(i) - this.random.zrange(i), 0, this.random.zrange(i) - this.random.zrange(i)), blockpos.getY() + 48, 64); + BlockPos blockpos1 = world.getPrecipitationHeight(blockpos.add(this.random.zrange(i) - this.random.zrange(i), 0, this.random.zrange(i) - this.random.zrange(i))); + Biome biomegenbase = world.getBiomeGenForCoords(blockpos1); BlockPos blockpos2 = blockpos1.down(); Block block = world.getState(blockpos2).getBlock(); - float temp = 10.0f; // world.getTemperatureC(blockpos1); TODO: fix particles + float temp = World.ABSOLUTE_ZERO + world.getTempOffset() + biomegenbase.getTemperature(blockpos1); if (blockpos1.getY() <= blockpos.getY() + i && blockpos1.getY() >= blockpos.getY() - i && /* biomegenbase.canRain() && */ temp > 0.0F) { @@ -1187,7 +1189,7 @@ public class EntityRenderer { { this.rainSoundCounter = 0; - if (d1 > (double)(blockpos.getY() + 1) && world.getPrecipitationHeight(blockpos, blockpos.getY() + 46, 48).getY() > ExtMath.floorf((float)blockpos.getY())) + if (d1 > (double)(blockpos.getY() + 1) && world.getPrecipitationHeight(blockpos).getY() > ExtMath.floorf((float)blockpos.getY())) { this.gm.world.playSound(d0, d1, d2, n >= j ? this.pickMoltenSound() : SoundEvent.RAIN, n >= j ? 0.2f : 0.1F); } @@ -1251,10 +1253,11 @@ public class EntityRenderer { double d3 = (double)this.rainXCoords[i2] * 0.5D; double d4 = (double)this.rainYCoords[i2] * 0.5D; blockpos$mutableblockpos.set(l1, 0, k1); + Biome biomegenbase = world.getBiomeGenForCoords(blockpos$mutableblockpos); // if (biomegenbase.canRain() || biomegenbase.isSnowyBiome()) // { - int j2 = world.getPrecipitationHeight(blockpos$mutableblockpos, ExtMath.floord(d1) + 48, 64).getY(); + int j2 = world.getPrecipitationHeight(blockpos$mutableblockpos).getY(); int k2 = j - i1; int l2 = j + i1; @@ -1279,7 +1282,7 @@ public class EntityRenderer { { this.random.setSeed((long)(l1 * l1 * 3121 + l1 * 45238971 ^ k1 * k1 * 418711 + k1 * 13761)); blockpos$mutableblockpos.set(l1, k2, k1); - float f2 = 10.0f; // world.getTemperatureC(blockpos$mutableblockpos); TODO: fix particles + float f2 = World.ABSOLUTE_ZERO + world.getTempOffset() + biomegenbase.getTemperature(blockpos$mutableblockpos); if(f2 >= 194.0f) { diff --git a/client/src/client/renderer/RegionRenderCache.java b/client/src/client/renderer/RegionRenderCache.java index 4ea9417..635a77a 100755 --- a/client/src/client/renderer/RegionRenderCache.java +++ b/client/src/client/renderer/RegionRenderCache.java @@ -2,6 +2,7 @@ package client.renderer; import java.util.Arrays; +import common.biome.Biome; import common.init.Blocks; import common.tileentity.TileEntity; import common.util.BlockPos; @@ -10,6 +11,7 @@ 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; @@ -112,19 +114,29 @@ public class RegionRenderCache extends ChunkCache implements IWorldAccess public int getLight(BlockPos pos, int lightValue) { - int j = this.getLightForExt(pos); + int i = this.getLightForExt(LightType.SKY, pos); + int j = this.getLightForExt(LightType.BLOCK, pos); if (j < lightValue) { j = lightValue; } - return 15 << 20 | j << 4; + return i << 20 | j << 4; } - - private int getLightForExt(BlockPos pos) + + public Biome getBiomeGenForCoords(BlockPos pos) { - if (pos.getY() >= 0 && pos.getY() < 512) + return this.worldObj.getBiomeGenForCoords(pos); + } + + private int getLightForExt(LightType p_175629_1_, BlockPos pos) + { + if (p_175629_1_ == LightType.SKY && this.worldObj.dimension.hasNoLight()) + { + return 0; + } + else if (pos.getY() >= 0 && pos.getY() < 512) { if (this.getState(pos).getBlock().getSumBrightness()) { @@ -132,7 +144,7 @@ public class RegionRenderCache extends ChunkCache implements IWorldAccess for (Facing enumfacing : Facing.values()) { - int k = this.getLightFor(pos.offset(enumfacing)); + int k = this.getLightFor(p_175629_1_, pos.offset(enumfacing)); if (k > l) { @@ -151,12 +163,12 @@ public class RegionRenderCache extends ChunkCache implements IWorldAccess { int i = (pos.getX() >> 4) - this.chunkX; int j = (pos.getZ() >> 4) - this.chunkZ; - return this.chunkArray[i][j].getLight(pos); + return this.chunkArray[i][j].getLight(p_175629_1_, pos); } } else { - return 0; + return p_175629_1_.defValue; } } @@ -169,17 +181,17 @@ public class RegionRenderCache extends ChunkCache implements IWorldAccess // return this.getBlockState(pos).getBlock().getMaterial() == Material.air; // } - public int getLightFor(BlockPos pos) + public int getLightFor(LightType p_175628_1_, BlockPos pos) { if (pos.getY() >= 0 && pos.getY() < 512) { int i = (pos.getX() >> 4) - this.chunkX; int j = (pos.getZ() >> 4) - this.chunkZ; - return this.chunkArray[i][j].getLight(pos); + return this.chunkArray[i][j].getLight(p_175628_1_, pos); } else { - return 0; + return p_175628_1_.defValue; } } diff --git a/client/src/client/renderer/entity/RenderWolf.java b/client/src/client/renderer/entity/RenderWolf.java index 66ae7d7..3fb1bf1 100755 --- a/client/src/client/renderer/entity/RenderWolf.java +++ b/client/src/client/renderer/entity/RenderWolf.java @@ -1,5 +1,6 @@ package client.renderer.entity; +import client.renderer.GlState; import client.renderer.layers.LayerWolfCollar; import client.renderer.model.ModelBase; import common.entity.animal.EntityWolf; @@ -24,7 +25,21 @@ public class RenderWolf extends RenderLiving { return livingBase.getTailRotation(); } - + + /** + * Renders the desired {@code T} type Entity. + */ + public void doRender(EntityWolf entity, double x, double y, double z, float partialTicks) + { + if (entity.isWolfWet()) + { + float f = entity.getBrightness(partialTicks) * entity.getShadingWhileWet(partialTicks); + GlState.color(f, f, f, 1.0F); + } + + super.doRender(entity, x, y, z, partialTicks); + } + /** * Returns the location of an entity's texture. Doesn't seem to be called unless you call Render.bindEntityTexture. */ diff --git a/client/src/client/renderer/model/ModelWolf.java b/client/src/client/renderer/model/ModelWolf.java index acc9ff4..7bb6909 100755 --- a/client/src/client/renderer/model/ModelWolf.java +++ b/client/src/client/renderer/model/ModelWolf.java @@ -157,7 +157,10 @@ public class ModelWolf extends ModelBase this.wolfLeg4.rotateAngleX = ExtMath.cos(p_78086_2_ * 0.6662F) * 1.4F * p_78086_3_; } - this.wolfHeadMain.rotateAngleZ = entitywolf.getInterestedAngle(partialTickTime); + this.wolfHeadMain.rotateAngleZ = entitywolf.getInterestedAngle(partialTickTime) + entitywolf.getShakeAngle(partialTickTime, 0.0F); + this.wolfMane.rotateAngleZ = entitywolf.getShakeAngle(partialTickTime, -0.08F); + this.wolfBody.rotateAngleZ = entitywolf.getShakeAngle(partialTickTime, -0.16F); + this.wolfTail.rotateAngleZ = entitywolf.getShakeAngle(partialTickTime, -0.2F); } /** diff --git a/client/src/client/world/EmptyChunk.java b/client/src/client/world/EmptyChunk.java index 6bec1b5..190c2d7 100755 --- a/client/src/client/world/EmptyChunk.java +++ b/client/src/client/world/EmptyChunk.java @@ -10,12 +10,23 @@ import common.tileentity.TileEntity; import common.util.BlockPos; import common.util.BoundingBox; import common.world.Chunk; +import common.world.LightType; public class EmptyChunk extends Chunk { public EmptyChunk(WorldClient world) { super(world, 0, 0); } + public int getHeight(int x, int z) { + return 0; + } + + public void genHeights() { + } + + public void genSkyLight() { + } + public Block getBlock(BlockPos pos) { return Blocks.air; } @@ -28,11 +39,11 @@ public class EmptyChunk extends Chunk { return 0; } - public int getLight(BlockPos pos) { - return 0; + public int getLight(LightType type, BlockPos pos) { + return type.defValue; } - public void setLight(BlockPos pos, int value) { + public void setLight(LightType type, BlockPos pos, int value) { } public int getLightSub(BlockPos pos, int amount) { @@ -45,6 +56,10 @@ public class EmptyChunk extends Chunk { public void removeEntity(Entity entity) { } + public boolean canSeeSky(BlockPos pos) { + return false; + } + public TileEntity getTileEntity(BlockPos pos, TileEntity.EnumCreateEntityType type) { return null; } diff --git a/client/src/client/world/WorldClient.java b/client/src/client/world/WorldClient.java index 096ad5c..7e8f142 100755 --- a/client/src/client/world/WorldClient.java +++ b/client/src/client/world/WorldClient.java @@ -1,15 +1,14 @@ package client.world; import java.util.List; -import java.util.Map; import java.util.Set; import client.Client; import client.renderer.particle.EntityFX; import client.renderer.particle.EntityFirework; +import common.biome.Biome; import common.block.Block; import common.collect.Lists; -import common.collect.Maps; import common.collect.Sets; import common.dimension.Dimension; import common.entity.Entity; @@ -31,6 +30,7 @@ import common.tileentity.TileEntity; import common.util.BlockPos; import common.util.ChunkPos; import common.util.ExtMath; +import common.util.LongHashMap; import common.util.Vec3; import common.util.BlockPos.MutableBlockPos; import common.world.Chunk; @@ -45,13 +45,12 @@ 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 Map chunkMapping = Maps.newHashMap(); + private final LongHashMap chunkMapping = new LongHashMap(); private final List chunkListing = Lists.newArrayList(); private final Chunk blankChunk = new EmptyChunk(this); // public final Profiler profiler; protected int lastLightning; protected Vec3 lightColor = new Vec3(0xffffff); - protected boolean exterminated; public WorldClient(Client gm, boolean debug, Dimension dim) { @@ -86,7 +85,7 @@ public class WorldClient extends AWorldClient long time = System.currentTimeMillis(); for (Chunk chunk : this.chunkListing) { - chunk.update(); + chunk.update(System.currentTimeMillis() - time > 5L); } if (System.currentTimeMillis() - time > 100L) { @@ -128,13 +127,12 @@ public class WorldClient extends AWorldClient public void doPreChunk(int x, int z, boolean load) { - ChunkPos pos = new ChunkPos(x, z); if (load) { - if(this.chunkMapping.get(pos) != null) + if(this.chunkMapping.getValueByKey(LongHashMap.packInt(x, z)) != null) this.doPreChunk(x, z, false); Chunk chunk = new Chunk(this, x, z); - this.chunkMapping.put(pos, chunk); + this.chunkMapping.add(LongHashMap.packInt(x, z), chunk); this.chunkListing.add(chunk); chunk.setLoaded(true); } @@ -145,7 +143,7 @@ public class WorldClient extends AWorldClient { chunk.onChunkUnload(); } - this.chunkMapping.remove(pos); + this.chunkMapping.remove(LongHashMap.packInt(x, z)); this.chunkListing.remove(chunk); } @@ -355,13 +353,13 @@ public class WorldClient extends AWorldClient public Chunk getChunk(int x, int z) { - Chunk chunk = this.chunkMapping.get(new ChunkPos(x, z)); + Chunk chunk = this.chunkMapping.getValueByKey(LongHashMap.packInt(x, z)); return chunk == null ? this.blankChunk : chunk; } public String getInfo() { - return "Chunk-Cache: M " + this.chunkMapping.size() + ", L " + this.chunkListing.size(); + return "Chunk-Cache: M " + this.chunkMapping.getNumHashElements() + ", L " + this.chunkListing.size(); } public void playSound(SoundEvent sound, double x, double y, double z, float volume) @@ -759,16 +757,19 @@ public class WorldClient extends AWorldClient } public Vec3 getSkyColor(Entity entity, float partial) { + BlockPos pos = new BlockPos(ExtMath.floord(entity.posX), ExtMath.floord(entity.posY), + ExtMath.floord(entity.posZ)); + Biome biome = this.getBiomeGenForCoords(pos); Vec3 vec; - if(this.exterminated) - vec = new Vec3(0x101010); + if(biome.skyColor != 0xffffffff) + vec = new Vec3(biome.skyColor); else vec = new Vec3(this.dimension.getSkyColor()); if(this.dimension.getType().days) { float mult = ExtMath.clampf(ExtMath.cos(this.getCelestialAngle(partial) * (float)Math.PI * 2.0F) * 2.0F + 0.5F, 0.0F, 1.0F); if(this.dimension.getSkyColor() == 0xffffffff) { - float temp = ExtMath.clampf(((0.0f /* temp */ + 14.0f) / 40.0f + 0.15f) / 3.0F, + float temp = ExtMath.clampf(((biome.getTemperature(pos) + 14.0f) / 40.0f + 0.15f) / 3.0F, -1.0F, 1.0F); Vec3 sky = new Vec3(hsvToRGB(0.62222224F - temp * 0.05F, 0.5F + temp * 0.1F, 1.0F)); vec = new Vec3(vec.xCoord * sky.xCoord * mult, vec.yCoord * sky.yCoord * mult, vec.zCoord * sky.zCoord * mult); @@ -814,8 +815,10 @@ public class WorldClient extends AWorldClient public Vec3 getCloudColour(Entity entity, float partialTicks) { Vec3 color = new Vec3(this.dimension.getCloudColor()); - if(this.exterminated) - color = new Vec3(0x000000); + Biome biome = this.getBiomeGenForCoords(new BlockPos(ExtMath.floord(entity.posX), ExtMath.floord(entity.posY), + ExtMath.floord(entity.posZ))); + if(biome.cloudColor != 0xffffffff) + color = new Vec3(biome.cloudColor); float r = (float)color.xCoord; float g = (float)color.yCoord; float b = (float)color.zCoord; @@ -851,8 +854,10 @@ public class WorldClient extends AWorldClient public Vec3 getFogColor(Entity entity, float partialTicks) { Vec3 color = new Vec3(this.dimension.getFogColor()); - if(this.exterminated) - color = new Vec3(0x303030); + Biome biome = this.getBiomeGenForCoords(new BlockPos(ExtMath.floord(entity.posX), ExtMath.floord(entity.posY), + ExtMath.floord(entity.posZ))); + if(biome.fogColor != 0xffffffff) + color = new Vec3(biome.fogColor); if(!this.dimension.getType().days) return color; float sun = ExtMath.clampf(ExtMath.cos(this.getCelestialAngle(partialTicks) * (float)Math.PI * 2.0F) * 2.0F + 0.5F, @@ -925,12 +930,4 @@ public class WorldClient extends AWorldClient public boolean hasNoChunks() { return this.chunkListing.isEmpty(); } - - public void setExterminated(boolean exterminated) { - this.exterminated = exterminated; - } - - public boolean isExterminated() { - return this.exterminated; - } } diff --git a/common/src/common/ai/EntityAIFleeSun.java b/common/src/common/ai/EntityAIFleeSun.java new file mode 100755 index 0000000..85c8c7e --- /dev/null +++ b/common/src/common/ai/EntityAIFleeSun.java @@ -0,0 +1,95 @@ +package common.ai; + +import common.entity.types.EntityLiving; +import common.rng.Random; +import common.util.BlockPos; +import common.util.Vec3; +import common.world.World; +import common.world.AWorldServer; + +public class EntityAIFleeSun extends EntityAIBase +{ + private EntityLiving theCreature; + private double shelterX; + private double shelterY; + private double shelterZ; + private double movementSpeed; + private World theWorld; + + public EntityAIFleeSun(EntityLiving theCreatureIn, double movementSpeedIn) + { + this.theCreature = theCreatureIn; + this.movementSpeed = movementSpeedIn; + this.theWorld = theCreatureIn.worldObj; + this.setMutexBits(1); + } + + /** + * Returns whether the EntityAIBase should begin execution. + */ + public boolean shouldExecute() + { + if (!((AWorldServer)this.theWorld).isDaytime()) + { + return false; + } + else if (!this.theCreature.isBurning()) + { + return false; + } + else if (!this.theWorld.canSeeSky(new BlockPos(this.theCreature.posX, this.theCreature.getEntityBoundingBox().minY, this.theCreature.posZ))) + { + return false; + } + else + { + Vec3 vec3 = this.findPossibleShelter(); + + if (vec3 == null) + { + return false; + } + else + { + this.shelterX = vec3.xCoord; + this.shelterY = vec3.yCoord; + this.shelterZ = vec3.zCoord; + return true; + } + } + } + + /** + * Returns whether an in-progress EntityAIBase should continue executing + */ + public boolean continueExecuting() + { + return !this.theCreature.getNavigator().noPath(); + } + + /** + * Execute a one shot task or start executing a continuous task + */ + public void startExecuting() + { + this.theCreature.getNavigator().tryMoveToXYZ(this.shelterX, this.shelterY, this.shelterZ, this.movementSpeed); + } + + private Vec3 findPossibleShelter() + { + Random random = this.theCreature.getRNG(); + BlockPos blockpos = new BlockPos(this.theCreature.posX, this.theCreature.getEntityBoundingBox().minY, this.theCreature.posZ); + + for (int i = 0; i < 10; ++i) + { + BlockPos blockpos1 = blockpos.add(random.zrange(20) - 10, random.zrange(6) - 3, random.zrange(20) - 10); + + if (!this.theWorld.canSeeSky(blockpos1) && this.theCreature.getBlockPathWeight(blockpos1) < 0.0F) + { + return new Vec3((double)blockpos1.getX(), (double)blockpos1.getY(), (double)blockpos1.getZ()); + } + } + + return null; + } +} diff --git a/common/src/common/ai/EntityAIRestrictSun.java b/common/src/common/ai/EntityAIRestrictSun.java new file mode 100755 index 0000000..50e2901 --- /dev/null +++ b/common/src/common/ai/EntityAIRestrictSun.java @@ -0,0 +1,39 @@ +package common.ai; + +import common.entity.types.EntityLiving; +import common.pathfinding.PathNavigateGround; +import common.world.AWorldServer; + +public class EntityAIRestrictSun extends EntityAIBase +{ + private EntityLiving theEntity; + + public EntityAIRestrictSun(EntityLiving creature) + { + this.theEntity = creature; + } + + /** + * Returns whether the EntityAIBase should begin execution. + */ + public boolean shouldExecute() + { + return ((AWorldServer)this.theEntity.worldObj).isDaytime(); + } + + /** + * Execute a one shot task or start executing a continuous task + */ + public void startExecuting() + { + ((PathNavigateGround)this.theEntity.getNavigator()).setAvoidSun(true); + } + + /** + * Resets the task + */ + public void resetTask() + { + ((PathNavigateGround)this.theEntity.getNavigator()).setAvoidSun(false); + } +} diff --git a/common/src/common/biome/Biome.java b/common/src/common/biome/Biome.java index 935453e..b02260c 100644 --- a/common/src/common/biome/Biome.java +++ b/common/src/common/biome/Biome.java @@ -5,10 +5,12 @@ import java.util.Map; import common.collect.Lists; import common.collect.Maps; +import common.color.Colorizer; import common.log.Log; import common.rng.PerlinGen; import common.rng.Random; import common.util.BlockPos; +import common.util.ExtMath; public enum Biome { NONE(0, "none", "", 0x000000), @@ -17,16 +19,16 @@ public enum Biome { EXTREMEHILLS(3, "extremeHills", "Extremes Bergland", 0x606060, -12.0f, 30.0f), FOREST(4, "forest", "Wald", 0x056621, 8.0f, 80.0f), TAIGA(5, "taiga", "Taiga", 0x0b6659, -10.0f, 80.0f), - SWAMPLAND(6, "swampland", "Sumpf", 0x07f9b2, 12.0f, 90.0f), + SWAMPLAND(6, "swampland", "Sumpf", 0x07f9b2, 12.0f, 90.0f, 0xe0ffae, 0xffffffff, 6975545), RIVER(7, "river", "Fluss", 0x0000ff), - EXTERMINATED(8, "exterminated", "Ausgelöscht", 0x000000, 150.0f, 0.0f), + EXTERMINATED(8, "exterminated", "Ausgelöscht", 0x000000, 150.0f, 0.0f, 0x202020, 0x303030, 0x303030, 0x101010, 0x303030, 0x000000), SPACE(9, "space", "Leere des Weltraums", 0x000000, 0.0f, 0.0f), FROZENSEA(10, "frozenSea", "Vereister See", 0x9090a0, -20.0f), FROZENRIVER(11, "frozenRiver", "Vereister Fluss", 0xa0a0ff, -20.0f), ICEPLAINS(12, "icePlains", "Eisebene", 0xffffff, -20.0f), ICEMOUNTAINS(13, "iceMountains", "Vereistes Bergland", 0xa0a0a0, -20.0f), MUSHROOMPLAINS(14, "mushroomPlains", "Pilzland", 0xff00ff, 16.0f, 100.0f), - BLACKENED(15, "blackened", "Schwarz", 0x000000, 0.0f, 0.0f), + BLACKENED(15, "blackened", "Schwarz", 0x000000, 0.0f, 0.0f, 0x000000, 0x303030, 0x303030), BEACH(16, "beach", "Strand", 0xfade55, 12.0f, 40.0f), DESERTHILLS(17, "desertHills", "Wüsten-Bergland", 0xd25f12, 60.0f, 0.0f), FORESTHILLS(18, "forestHills", "Wald-Bergland", 0x22551c, 8.0f, 80.0f), @@ -48,17 +50,17 @@ public enum Biome { EXTREMEHILLSPLUS(34, "extremeHillsPlus", "Extremes Bergland +", 0x507050, -12.0f, 30.0f), SAVANNA(35, "savanna", "Savanne", 0xbdb25f, 28.0f, 0.0f), SAVANNAPLATEAU(36, "savannaPlateau", "Savannen-Plateau", 0xa79d64, 20.0f, 0.0f), - MESA(37, "mesa", "Mesa", 0xd94515, 0.0f, 0.0f), - MESAPLATEAUF(38, "mesaPlateauF", "Mesa-Waldplateau", 0xb09765, 0.0f, 0.0f), - MESAPLATEAU(39, "mesaPlateau", "Mesa-Plateau", 0xca8c65, 0.0f, 0.0f), + MESA(37, "mesa", "Mesa", 0xd94515, 0.0f, 0.0f, 0xffffff, 9470285, 10387789), + MESAPLATEAUF(38, "mesaPlateauF", "Mesa-Waldplateau", 0xb09765, 0.0f, 0.0f, 0xffffff, 9470285, 10387789), + MESAPLATEAU(39, "mesaPlateau", "Mesa-Plateau", 0xca8c65, 0.0f, 0.0f, 0xffffff, 9470285, 10387789), SNOWLAND(40, "snowLand", "Eisland", 0xffffff, 0.0f, 100.0f), TIAN(41, "tian", "Tian", 0x808080, 0.0f, 80.0f), ELVENFOREST(42, "elvenForest", "Elbenwald", 0x059821, 8.0f, 90.0f), - UPPERHELL(43, "upperHell", "Übergang in die Hölle", 0xff0000, 0.0f, 0.0f), - LOWERHELL(44, "lowerHell", "Abgrund der Hölle", 0xff0000, 0.0f, 0.0f), - HELLHILLS(45, "hellHills", "Bergland der Hölle", 0xff0000, 0.0f, 0.0f), - SOULPLAINS(46, "soulPlains", "Seelenland", 0xff0000, 0.0f, 0.0f), - ASHLAND(47, "ashLand", "Verbrannt", 0xff0000, 0.0f, 0.0f), + UPPERHELL(43, "upperHell", "Übergang in die Hölle", 0xff0000, 0.0f, 0.0f, 0x000000, 0x000000, 0x000000), + LOWERHELL(44, "lowerHell", "Abgrund der Hölle", 0xff0000, 0.0f, 0.0f, 0x000000, 0x000000, 0x000000), + HELLHILLS(45, "hellHills", "Bergland der Hölle", 0xff0000, 0.0f, 0.0f, 0x000000, 0x000000, 0x000000), + SOULPLAINS(46, "soulPlains", "Seelenland", 0xff0000, 0.0f, 0.0f, 0x000000, 0x000000, 0x000000), + ASHLAND(47, "ashLand", "Verbrannt", 0xff0000, 0.0f, 0.0f, 0x000000, 0x000000, 0x000000), MOON(48, "moon", "Mondoberfläche", 0xa0a0a0, 0.0f, 0.0f), CHAOS(49, "chaos", "Chaos", 0xff00ff), @@ -66,7 +68,7 @@ public enum Biome { EXTREMEHILLSM(131, "extremeHillsM", "Extremes Bergland M", 0x606060, -12.0f, 30.0f), FLOWERFOREST(132, "flowerForest", "Blumenwald", 0x6a7425, 8.0f, 80.0f), TAIGAM(133, "taigaM", "Taiga M", 0x0b6659, -10.0f, 80.0f), - SWAMPLANDM(134, "swamplandM", "Sumpf M", 0x07f9b2, 12.0f, 90.0f), + SWAMPLANDM(134, "swamplandM", "Sumpf M", 0x07f9b2, 12.0f, 90.0f, 0xe0ffae, 0xffffffff, 6975545), ICEPLAINSSPIKES(140, "icePlainsSpikes", "Eisebene + Spitzen", 0xd2ffff, -20.0f), JUNGLEM(149, "jungleM", "Urwald M", 0x537b09, 18.0f, 90.0f), JUNGLEEDGEM(151, "jungleEdgeM", "Urwald Gr. M", 0x628b17, 18.0f, 80.0f), @@ -79,20 +81,28 @@ public enum Biome { EXTREMEHILLSPLUSM(162, "extremeHillsPlusM", "Extremes Bergland + M", 0x507050, -12.0f, 30.0f), SAVANNAM(163, "savannaM", "Savanne M", 0xbdb25f, 24.0f, 0.0f), SAVANNAPLATEAUM(164, "savannaPlateauM", "Savannen-Plateau M", 0xa79d64, 20.0f, 0.0f), - MESABRYCE(165, "mesaBryce", "Mesa (Bryce)", 0xd94515, 0.0f, 0.0f), - MESAPLATEAUFM(166, "mesaPlateauFM", "Mesa-Waldplateau M", 0xb09765, 0.0f, 0.0f), - MESAPLATEAUM(167, "mesaPlateauM", "Mesa-Plateau M", 0xca8c65, 0.0f, 0.0f); + MESABRYCE(165, "mesaBryce", "Mesa (Bryce)", 0xd94515, 0.0f, 0.0f, 0xffffff, 9470285, 10387789), + MESAPLATEAUFM(166, "mesaPlateauFM", "Mesa-Waldplateau M", 0xb09765, 0.0f, 0.0f, 0xffffff, 9470285, 10387789), + MESAPLATEAUM(167, "mesaPlateauM", "Mesa-Plateau M", 0xca8c65, 0.0f, 0.0f, 0xffffff, 9470285, 10387789); public static final Biome DEF_BIOME = FOREST; private static final PerlinGen TEMP_NOISE = new PerlinGen(new Random(836430928262265276L), 1); + private static final PerlinGen COLOR_NOISE = new PerlinGen(new Random(6549321755809421L), 1); private static final Biome[] BIOMES = new Biome[256]; private static final Map LOOKUP = Maps.newTreeMap(); public final int id; public final String name; public final String display; + public final int color; public final float temperature; public final float humidity; + public final int waterColor; + public final int grassColor; + public final int foliageColor; + public final int skyColor; + public final int fogColor; + public final int cloudColor; static { for(Biome biome : values()) { @@ -149,20 +159,35 @@ public enum Biome { return biome; } - private Biome(int id, String name, String display, int color, float temperature, float humidity) { + private Biome(int id, String name, String display, int color, float temperature, float humidity, int waterColor, int grassColor, int foliageColor, int skyColor, int fogColor, int cloudColor) { this.id = id; this.name = name; this.display = display; this.temperature = temperature; this.humidity = humidity; + this.color = color; + this.waterColor = waterColor; + this.grassColor = grassColor; + this.foliageColor = foliageColor; + this.skyColor = skyColor; + this.fogColor = fogColor; + this.cloudColor = cloudColor; } - + + private Biome(int id, String name, String display, int color, float temperature, float humidity, int waterColor, int grassColor, int foliageColor) { + this(id, name, display, color, temperature, humidity, waterColor, grassColor, foliageColor, 0xffffffff, 0xffffffff, 0xffffffff); + } + + private Biome(int id, String name, String display, int color, float temperature, float humidity) { + this(id, name, display, color, temperature, humidity, 0xffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff); + } + private Biome(int id, String name, String display, int color, float temperature) { - this(id, name, display, color, temperature, 50.0f); + this(id, name, display, color, temperature, 50.0f, 0xffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff); } private Biome(int id, String name, String display, int color) { - this(id, name, display, color, 0.0f, 50.0f); + this(id, name, display, color, 0.0f, 50.0f, 0xffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff); } public final float getTemperature(BlockPos pos) { @@ -181,4 +206,30 @@ public enum Biome { public boolean isHighHumidity() { return this.humidity > 85.0f; } + + // skycolor = ((temp + 14) / 40 + 0.15) / 3 + + public int getGrassColorAtPos(BlockPos pos) { + if(this.grassColor != 0xffffffff) + return this.grassColor; + if(this == SWAMPLAND || this == SWAMPLANDM) { + double d0 = COLOR_NOISE.generate((double)pos.getX() * 0.0225D, (double)pos.getZ() * 0.0225D); + return d0 < -0.1D ? 5011004 : 6975545; + } + if(this == ELVENFOREST) + return Colorizer.getGrassColor(1.0f, this.humidity * 0.01f); + double d0 = (double)ExtMath.clampf((this.getTemperature(pos) + 14.0f) / 40.0f + 0.15f, 0.0F, 1.0F); + double d1 = (double)ExtMath.clampf(this.humidity * 0.01f, 0.0F, 1.0F); + return this == ROOFEDFOREST || this == ROOFEDFORESTM ? (Colorizer.getGrassColor(d0, d1) & 16711422) + 2634762 >> 1 : Colorizer.getGrassColor(d0, d1); + } + + public int getFoliageColorAtPos(BlockPos pos) { + if(this.foliageColor != 0xffffffff) + return this.foliageColor; + if(this == ELVENFOREST) + return Colorizer.getFoliageColor(1.0f, this.humidity * 0.01f); + double d0 = (double)ExtMath.clampf((this.getTemperature(pos) + 14.0f) / 40.0f + 0.15f, 0.0F, 1.0F); + double d1 = (double)ExtMath.clampf(this.humidity * 0.01f, 0.0F, 1.0F); + return Colorizer.getFoliageColor(d0, d1); + } } diff --git a/common/src/common/block/BlockCrops.java b/common/src/common/block/BlockCrops.java index fbf07d6..fee8af4 100755 --- a/common/src/common/block/BlockCrops.java +++ b/common/src/common/block/BlockCrops.java @@ -129,7 +129,7 @@ public class BlockCrops extends BlockBush implements IGrowable public boolean canBlockStay(World worldIn, BlockPos pos, State state) { - return this.canPlaceBlockOn(worldIn.getState(pos.down()).getBlock()); + return (worldIn.getLight(pos) >= 8 || worldIn.canSeeSky(pos)) && this.canPlaceBlockOn(worldIn.getState(pos.down()).getBlock()); } protected Item getSeed() diff --git a/common/src/common/block/BlockDaylightDetector.java b/common/src/common/block/BlockDaylightDetector.java index 735a4bb..f213c1f 100755 --- a/common/src/common/block/BlockDaylightDetector.java +++ b/common/src/common/block/BlockDaylightDetector.java @@ -21,6 +21,7 @@ import common.util.BlockPos; import common.util.ExtMath; import common.util.Facing; import common.world.IWorldAccess; +import common.world.LightType; import common.world.State; import common.world.World; import common.world.AWorldServer; @@ -57,7 +58,7 @@ public class BlockDaylightDetector extends BlockContainer if (!worldIn.dimension.hasNoLight()) { State iblockstate = worldIn.getState(pos); - int i = 15 - worldIn.getSkylightSubtracted(); + int i = worldIn.getLightFor(LightType.SKY, pos) - worldIn.getSkylightSubtracted(); float f = worldIn.getCelestialAngleRadians(1.0F); float f1 = f < (float)Math.PI ? 0.0F : ((float)Math.PI * 2F); f = f + (f1 - f) * 0.2F; diff --git a/common/src/common/block/BlockFire.java b/common/src/common/block/BlockFire.java index 0af399f..e0bc2f7 100755 --- a/common/src/common/block/BlockFire.java +++ b/common/src/common/block/BlockFire.java @@ -232,7 +232,7 @@ public class BlockFire extends Block } } - protected boolean canDie(AWorldServer worldIn, BlockPos pos) + protected boolean canDie(World worldIn, BlockPos pos) { return worldIn.isRainingAt(pos, true) || worldIn.isRainingAt(pos.west(), true) || worldIn.isRainingAt(pos.east(), true) || worldIn.isRainingAt(pos.north(), true) || worldIn.isRainingAt(pos.south(), true); } @@ -254,7 +254,7 @@ public class BlockFire extends Block return integer == null ? 0 : integer.intValue(); } - private void catchOnFire(AWorldServer worldIn, BlockPos pos, int chance, Random random, int age) + private void catchOnFire(World worldIn, BlockPos pos, int chance, Random random, int age) { int i = this.getFlammability(worldIn.getState(pos).getBlock()); diff --git a/common/src/common/block/BlockIce.java b/common/src/common/block/BlockIce.java index 438dd31..a1e5981 100755 --- a/common/src/common/block/BlockIce.java +++ b/common/src/common/block/BlockIce.java @@ -11,6 +11,7 @@ import common.model.BlockLayer; import common.rng.Random; import common.tileentity.TileEntity; import common.util.BlockPos; +import common.world.LightType; import common.world.State; import common.world.World; import common.world.AWorldServer; @@ -45,7 +46,7 @@ public class BlockIce extends BlockBreakable } else { - if (((AWorldServer)worldIn).doesWaterVaporize(pos)) + if (worldIn.doesWaterVaporize(pos)) { worldIn.setBlockToAir(pos); return; @@ -72,7 +73,7 @@ public class BlockIce extends BlockBreakable public void updateTick(AWorldServer worldIn, BlockPos pos, State state, Random rand) { - if (Config.iceMelt && ((worldIn.getLightFor(pos) > 11 - this.getLightOpacity()) || !worldIn.canFreezeAt(pos))) + if (Config.iceMelt && ((worldIn.getLightFor(LightType.BLOCK, pos) > 11 - this.getLightOpacity()) || !worldIn.canFreezeAt(pos))) { if (worldIn.doesWaterVaporize(pos)) { diff --git a/common/src/common/block/BlockLeaves.java b/common/src/common/block/BlockLeaves.java index 1c9a795..8c2014a 100755 --- a/common/src/common/block/BlockLeaves.java +++ b/common/src/common/block/BlockLeaves.java @@ -16,6 +16,7 @@ import common.item.ItemStack; import common.material.Material; import common.model.Model; import common.model.ModelProvider; +import common.model.ParticleType; import common.properties.IProperty; import common.properties.PropertyBool; import common.properties.PropertyEnum; @@ -214,13 +215,13 @@ public class BlockLeaves extends BlockLeavesBase public void randomDisplayTick(AWorldClient worldIn, BlockPos pos, State state, Random rand) { -// if (worldIn.isRainingAt(pos.up(), true) && !worldIn.isBlockSolid(pos.down()) && rand.chance(15)) // == 1 TODO: fix particles -// { -// double d0 = (double)((float)pos.getX() + rand.floatv()); -// double d1 = (double)pos.getY() - 0.05D; -// double d2 = (double)((float)pos.getZ() + rand.floatv()); -// worldIn.spawnParticle(ParticleType.DRIP_WATER, d0, d1, d2, 0.0D, 0.0D, 0.0D); -// } + if (worldIn.isRainingAt(pos.up(), true) && !worldIn.isBlockSolid(pos.down()) && rand.chance(15)) // == 1 + { + double d0 = (double)((float)pos.getX() + rand.floatv()); + double d1 = (double)pos.getY() - 0.05D; + double d2 = (double)((float)pos.getZ() + rand.floatv()); + worldIn.spawnParticle(ParticleType.DRIP_WATER, d0, d1, d2, 0.0D, 0.0D, 0.0D); + } } private void destroy(World worldIn, BlockPos pos) diff --git a/common/src/common/block/BlockLiquid.java b/common/src/common/block/BlockLiquid.java index 88ad69f..9f036fd 100755 --- a/common/src/common/block/BlockLiquid.java +++ b/common/src/common/block/BlockLiquid.java @@ -215,7 +215,7 @@ public abstract class BlockLiquid extends Block */ public int tickRate(World worldIn, BlockPos pos) { - return this.flowRate >= 0 ? this.flowRate : (!worldIn.client && ((AWorldServer)worldIn).isLavaFaster(pos) ? (-this.flowRate / 3) : (-this.flowRate)); + return this.flowRate >= 0 ? this.flowRate : (worldIn.isLavaFaster(pos) ? (-this.flowRate / 3) : (-this.flowRate)); } public int getMixedBrightnessForBlock(IWorldAccess worldIn, BlockPos pos) diff --git a/common/src/common/block/BlockReed.java b/common/src/common/block/BlockReed.java index 216f4dd..8d7b151 100755 --- a/common/src/common/block/BlockReed.java +++ b/common/src/common/block/BlockReed.java @@ -1,6 +1,5 @@ package common.block; -import common.color.Colorizer; import common.init.Blocks; import common.init.Config; import common.init.Items; @@ -155,7 +154,7 @@ public class BlockReed extends Block public int colorMultiplier(IWorldAccess worldIn, BlockPos pos, int renderPass) { - return Colorizer.getGrassColor(1.0f, 0.9f); + return worldIn.getBiomeGenForCoords(pos).getGrassColorAtPos(pos); } public BlockLayer getBlockLayer() diff --git a/common/src/common/block/BlockSnow.java b/common/src/common/block/BlockSnow.java index 02c193a..3647804 100755 --- a/common/src/common/block/BlockSnow.java +++ b/common/src/common/block/BlockSnow.java @@ -20,6 +20,7 @@ import common.util.BoundingBox; import common.util.Facing; import common.world.IBlockAccess; import common.world.IWorldAccess; +import common.world.LightType; import common.world.State; import common.world.World; import common.world.AWorldServer; @@ -136,7 +137,7 @@ public class BlockSnow extends Block public void updateTick(AWorldServer worldIn, BlockPos pos, State state, Random rand) { - if (Config.snowMelt && ((worldIn.getLightFor(pos) > 11) || !worldIn.canFreezeAt(pos))) + if (Config.snowMelt && ((worldIn.getLightFor(LightType.BLOCK, pos) > 11) || !worldIn.canFreezeAt(pos))) { this.dropBlockAsItem(worldIn, pos, worldIn.getState(pos), 0); worldIn.setBlockToAir(pos); diff --git a/common/src/common/block/BlockSnowBlock.java b/common/src/common/block/BlockSnowBlock.java index da6fd2f..0e4a60e 100755 --- a/common/src/common/block/BlockSnowBlock.java +++ b/common/src/common/block/BlockSnowBlock.java @@ -7,6 +7,7 @@ import common.item.Item; import common.material.Material; import common.rng.Random; import common.util.BlockPos; +import common.world.LightType; import common.world.State; import common.world.AWorldServer; @@ -37,7 +38,7 @@ public class BlockSnowBlock extends Block public void updateTick(AWorldServer worldIn, BlockPos pos, State state, Random rand) { - if (Config.snowFullMelt && worldIn.getLightFor(pos) > 11) + if (Config.snowFullMelt && worldIn.getLightFor(LightType.BLOCK, pos) > 11) { this.dropBlockAsItem(worldIn, pos, worldIn.getState(pos), 0); worldIn.setBlockToAir(pos); diff --git a/common/src/common/block/BlockTallGrass.java b/common/src/common/block/BlockTallGrass.java index 1e169ee..a527f19 100755 --- a/common/src/common/block/BlockTallGrass.java +++ b/common/src/common/block/BlockTallGrass.java @@ -82,7 +82,7 @@ public class BlockTallGrass extends BlockBush implements IGrowable public int colorMultiplier(IWorldAccess worldIn, BlockPos pos, int renderPass) { - return Colorizer.getGrassColor(1.0f, 0.9f); + return worldIn.getBiomeGenForCoords(pos).getGrassColorAtPos(pos); } /** diff --git a/common/src/common/block/BlockVine.java b/common/src/common/block/BlockVine.java index 968a396..ed6f33b 100755 --- a/common/src/common/block/BlockVine.java +++ b/common/src/common/block/BlockVine.java @@ -226,7 +226,7 @@ public class BlockVine extends Block public int colorMultiplier(IWorldAccess worldIn, BlockPos pos, int renderPass) { - return Colorizer.getFoliageColor(1.0f, 0.9f); + return worldIn.getBiomeGenForCoords(pos).getFoliageColorAtPos(pos); } /** diff --git a/common/src/common/color/Colorizer.java b/common/src/common/color/Colorizer.java index 9e58742..dcae2c9 100755 --- a/common/src/common/color/Colorizer.java +++ b/common/src/common/color/Colorizer.java @@ -1,5 +1,6 @@ package common.color; +import common.biome.Biome; import common.util.BlockPos; import common.world.IWorldAccess; @@ -7,22 +8,22 @@ public enum Colorizer { NONE(0xffffff), BASIC(0x37b500), PINE(0x3f993f), BIRCH(0x68a723); private interface ColorResolver { - int getColorAtPos(BlockPos pos); + int getColorAtPos(Biome biome, BlockPos pos); } private static final ColorResolver GRASS_COLOR = new ColorResolver() { - public int getColorAtPos(BlockPos pos) { - return Colorizer.getGrassColor(1.0f, 0.9f); + public int getColorAtPos(Biome biome, BlockPos pos) { + return biome.getGrassColorAtPos(pos); } }; private static final ColorResolver FOLIAGE_COLOR = new ColorResolver() { - public int getColorAtPos(BlockPos pos) { - return Colorizer.getFoliageColor(1.0f, 0.9f); + public int getColorAtPos(Biome biome, BlockPos pos) { + return biome.getFoliageColorAtPos(pos); } }; private static final ColorResolver WATER_COLOR_MULTIPLIER = new ColorResolver() { - public int getColorAtPos(BlockPos pos) { - return 0xffffff; + public int getColorAtPos(Biome biome, BlockPos pos) { + return biome.waterColor; } }; private static final int[] GRASS = new int[65536]; @@ -59,7 +60,7 @@ public enum Colorizer { int b = 0; for(BlockPos.MutableBlockPos loc : BlockPos.getAllInBoxMutable(pos.add(-1, 0, -1), pos.add(1, 0, 1))) { - int c = resolver.getColorAtPos(loc); + int c = resolver.getColorAtPos(access.getBiomeGenForCoords(loc), loc); r += (c & 16711680) >> 16; g += (c & 65280) >> 8; b += c & 255; diff --git a/common/src/common/entity/Entity.java b/common/src/common/entity/Entity.java index 04d12af..59c59a1 100755 --- a/common/src/common/entity/Entity.java +++ b/common/src/common/entity/Entity.java @@ -342,7 +342,7 @@ public abstract class Entity this.setOnFireFromLava(); this.fallDistance *= 0.5F; } - else if(!this.worldObj.client && ((AWorldServer)this.worldObj).canBurnAt(this.getPosition()) && this.isInDownfall()) { + else if(this.worldObj.canBurnAt(this.getPosition()) && this.isInDownfall()) { this.setOnFireFromMolten(); } @@ -773,7 +773,7 @@ public abstract class Entity this.doBlockCollisions(); - boolean flag2 = !this.worldObj.client && this.isWet(); + boolean flag2 = this.isWet(); if (this.worldObj.isFlammableWithin(this.getEntityBoundingBox().contract(0.001D, 0.001D, 0.001D))) { @@ -949,14 +949,17 @@ public abstract class Entity } } + /** + * Checks if this entity is either in water or on an open air block in rain (used in wolves). + */ public boolean isWet() { - return this.inLiquid || ((AWorldServer)this.worldObj).isRainingAt(new BlockPos(this.posX, this.posY, this.posZ), true) || ((AWorldServer)this.worldObj).isRainingAt(new BlockPos(this.posX, this.posY + (double)this.height, this.posZ), true); + return this.inLiquid || this.worldObj.isRainingAt(new BlockPos(this.posX, this.posY, this.posZ), true) || this.worldObj.isRainingAt(new BlockPos(this.posX, this.posY + (double)this.height, this.posZ), true); } public boolean isInDownfall() { - return ((AWorldServer)this.worldObj).isRainingAt(new BlockPos(this.posX, this.posY, this.posZ), false) || ((AWorldServer)this.worldObj).isRainingAt(new BlockPos(this.posX, this.posY + (double)this.height, this.posZ), false); + return this.worldObj.isRainingAt(new BlockPos(this.posX, this.posY, this.posZ), false) || this.worldObj.isRainingAt(new BlockPos(this.posX, this.posY + (double)this.height, this.posZ), false); } /** diff --git a/common/src/common/entity/animal/EntityHorse.java b/common/src/common/entity/animal/EntityHorse.java index b26f87e..7352c24 100755 --- a/common/src/common/entity/animal/EntityHorse.java +++ b/common/src/common/entity/animal/EntityHorse.java @@ -38,7 +38,6 @@ import common.pathfinding.PathNavigateGround; import common.potion.Potion; import common.util.BlockPos; import common.util.ExtMath; -import common.world.AWorldServer; import common.world.World; public class EntityHorse extends EntityAnimal implements IInvBasic @@ -391,7 +390,7 @@ public class EntityHorse extends EntityAnimal implements IInvBasic { int i = ExtMath.floord(this.posX); int j = ExtMath.floord(this.posZ); - ((AWorldServer)this.worldObj).getBiomeGenForCoords(new BlockPos(i, 0, j)); + this.worldObj.getBiomeGenForCoords(new BlockPos(i, 0, j)); return true; } diff --git a/common/src/common/entity/animal/EntitySheep.java b/common/src/common/entity/animal/EntitySheep.java index ab6c7ba..dae424c 100755 --- a/common/src/common/entity/animal/EntitySheep.java +++ b/common/src/common/entity/animal/EntitySheep.java @@ -33,7 +33,6 @@ import common.nbt.NBTTagCompound; import common.pathfinding.PathNavigateGround; import common.rng.Random; import common.util.ExtMath; -import common.world.AWorldServer; import common.world.World; public class EntitySheep extends EntityAnimal @@ -348,7 +347,7 @@ public class EntitySheep extends EntityAnimal public Object onInitialSpawn(Object livingdata) { livingdata = super.onInitialSpawn(livingdata); - this.setFleeceColor(getRandomSheepColor(this.worldObj.rand, ((AWorldServer)this.worldObj).getBiomeGenForCoords(this.getPosition()))); + this.setFleeceColor(getRandomSheepColor(this.worldObj.rand, this.worldObj.getBiomeGenForCoords(this.getPosition()))); return livingdata; } diff --git a/common/src/common/entity/animal/EntityWolf.java b/common/src/common/entity/animal/EntityWolf.java index c10da66..caa4b4a 100755 --- a/common/src/common/entity/animal/EntityWolf.java +++ b/common/src/common/entity/animal/EntityWolf.java @@ -30,15 +30,30 @@ import common.init.SoundEvent; import common.item.Item; import common.item.ItemFood; import common.item.ItemStack; +import common.model.ParticleType; import common.nbt.NBTTagCompound; import common.pathfinding.PathNavigateGround; +import common.util.ExtMath; import common.world.World; public class EntityWolf extends EntityTameable { + /** Float used to smooth the rotation of the wolf head */ private float headRotationCourse; private float headRotationCourseOld; - + + /** true is the wolf is wet else false */ + private boolean isWet; + + /** True if the wolf is shaking else False */ + private boolean isShaking; + + /** + * This time increases while wolf is shaking and emitting water particles. + */ + private float timeWolfIsShaking; + private float prevTimeWolfIsShaking; + public EntityWolf(World worldIn) { super(worldIn); @@ -189,7 +204,15 @@ public class EntityWolf extends EntityTameable public void onLivingUpdate() { super.onLivingUpdate(); - + + if (!this.worldObj.client && this.isWet && !this.isShaking && !this.hasPath() && this.onGround) + { + this.isShaking = true; + this.timeWolfIsShaking = 0.0F; + this.prevTimeWolfIsShaking = 0.0F; + this.worldObj.setEntityState(this, (byte)8); + } + if (!this.worldObj.client && this.getAttackTarget() == null && this.isAngry()) { this.setAngry(false); @@ -212,8 +235,79 @@ public class EntityWolf extends EntityTameable { this.headRotationCourse += (0.0F - this.headRotationCourse) * 0.4F; } + + if (this.isWet()) + { + this.isWet = true; + this.isShaking = false; + this.timeWolfIsShaking = 0.0F; + this.prevTimeWolfIsShaking = 0.0F; + } + else if ((this.isWet || this.isShaking) && this.isShaking) + { + if (this.timeWolfIsShaking == 0.0F) + { + this.playSound(SoundEvent.WOLF_SHAKE, this.getSoundVolume()); + } + + this.prevTimeWolfIsShaking = this.timeWolfIsShaking; + this.timeWolfIsShaking += 0.05F; + + if (this.prevTimeWolfIsShaking >= 2.0F) + { + this.isWet = false; + this.isShaking = false; + this.prevTimeWolfIsShaking = 0.0F; + this.timeWolfIsShaking = 0.0F; + } + + if (this.timeWolfIsShaking > 0.4F) + { + float f = (float)this.getEntityBoundingBox().minY; + int i = (int)(ExtMath.sin((this.timeWolfIsShaking - 0.4F) * (float)Math.PI) * 7.0F); + + for (int j = 0; j < i; ++j) + { + float f1 = (this.rand.floatv() * 2.0F - 1.0F) * this.width * 0.5F; + float f2 = (this.rand.floatv() * 2.0F - 1.0F) * this.width * 0.5F; + this.worldObj.spawnParticle(ParticleType.WATER_SPLASH, this.posX + (double)f1, (double)(f + 0.8F), this.posZ + (double)f2, this.motionX, this.motionY, this.motionZ); + } + } + } } - + + /** + * True if the wolf is wet + */ + public boolean isWolfWet() + { + return this.isWet; + } + + /** + * Used when calculating the amount of shading to apply while the wolf is wet. + */ + public float getShadingWhileWet(float p_70915_1_) + { + return 0.75F + (this.prevTimeWolfIsShaking + (this.timeWolfIsShaking - this.prevTimeWolfIsShaking) * p_70915_1_) / 2.0F * 0.25F; + } + + public float getShakeAngle(float p_70923_1_, float p_70923_2_) + { + float f = (this.prevTimeWolfIsShaking + (this.timeWolfIsShaking - this.prevTimeWolfIsShaking) * p_70923_1_ + p_70923_2_) / 1.8F; + + if (f < 0.0F) + { + f = 0.0F; + } + else if (f > 1.0F) + { + f = 1.0F; + } + + return ExtMath.sin(f * (float)Math.PI) * ExtMath.sin(f * (float)Math.PI * 11.0F) * 0.15F * (float)Math.PI; + } + public float getInterestedAngle(float p_70917_1_) { return (this.headRotationCourseOld + (this.headRotationCourse - this.headRotationCourseOld) * p_70917_1_) * 0.15F * (float)Math.PI; @@ -381,7 +475,21 @@ public class EntityWolf extends EntityTameable return super.interact(player); } - + + public void handleStatusUpdate(byte id) + { + if (id == 8) + { + this.isShaking = true; + this.timeWolfIsShaking = 0.0F; + this.prevTimeWolfIsShaking = 0.0F; + } + else + { + super.handleStatusUpdate(id); + } + } + public float getTailRotation() { return this.isAngry() ? 1.5393804F : (this.isTamed() ? (0.55F - (20.0F - (float)this.dataWatcher.getWatchableObjectInt(18)) * 0.02F) * (float)Math.PI : ((float)Math.PI / 5F)); diff --git a/common/src/common/entity/npc/EntitySlime.java b/common/src/common/entity/npc/EntitySlime.java index 08e36f8..2fb6b0a 100755 --- a/common/src/common/entity/npc/EntitySlime.java +++ b/common/src/common/entity/npc/EntitySlime.java @@ -396,7 +396,7 @@ public class EntitySlime extends EntityNPC // { // if (this.worldObj.getDifficulty() != Difficulty.PEACEFUL) // { - Biome biomegenbase = ((AWorldServer)this.worldObj).getBiomeGenForCoords(blockpos); + Biome biomegenbase = this.worldObj.getBiomeGenForCoords(blockpos); if (biomegenbase == Biome.SWAMPLAND && this.posY > 50.0D && this.posY < 70.0D && this.rand.floatv() < 0.5F && this.rand.floatv() < this.worldObj.getCurrentMoonPhaseFactor() && this.worldObj.getLightFromNeighbors(new BlockPos(this)) <= this.rand.zrange(8)) { diff --git a/common/src/common/entity/projectile/EntityArrow.java b/common/src/common/entity/projectile/EntityArrow.java index 507198b..3174775 100755 --- a/common/src/common/entity/projectile/EntityArrow.java +++ b/common/src/common/entity/projectile/EntityArrow.java @@ -454,7 +454,7 @@ public class EntityArrow extends Entity implements IProjectile, IObjectData f4 = 0.6F; } - if (!this.worldObj.client && this.isWet()) + if (this.isWet()) { this.extinguish(); } diff --git a/common/src/common/entity/projectile/EntityHook.java b/common/src/common/entity/projectile/EntityHook.java index 6f44d35..8e51dd4 100755 --- a/common/src/common/entity/projectile/EntityHook.java +++ b/common/src/common/entity/projectile/EntityHook.java @@ -388,11 +388,16 @@ public class EntityHook extends Entity implements IObjectData int l = 1; BlockPos blockpos = (new BlockPos(this)).up(); - if (this.rand.floatv() < 0.25F && worldserver.isRainingAt(blockpos, true)) + if (this.rand.floatv() < 0.25F && this.worldObj.isRainingAt(blockpos, true)) { l = 2; } + if (this.rand.floatv() < 0.5F && !this.worldObj.canSeeSky(blockpos)) + { + --l; + } + if (this.ticksCatchable > 0) { --this.ticksCatchable; diff --git a/common/src/common/entity/types/EntityLiving.java b/common/src/common/entity/types/EntityLiving.java index abcd0db..117a3fd 100755 --- a/common/src/common/entity/types/EntityLiving.java +++ b/common/src/common/entity/types/EntityLiving.java @@ -314,7 +314,7 @@ public abstract class EntityLiving extends Entity // } // } - if (!this.worldObj.client && this.isEntityAlive() && this.isWet()) + if (this.isEntityAlive() && this.isWet()) { this.extinguish(); } diff --git a/common/src/common/item/ItemBucket.java b/common/src/common/item/ItemBucket.java index 464a389..94cb7c2 100755 --- a/common/src/common/item/ItemBucket.java +++ b/common/src/common/item/ItemBucket.java @@ -249,32 +249,38 @@ public class ItemBucket extends Item { return false; } - else if(!worldIn.client) + else { - if (((AWorldServer)worldIn).doesWaterVaporize(pos) && this.liquid.getMaterial() == Material.water) + if (worldIn.doesWaterVaporize(pos) && this.liquid.getMaterial() == Material.water) { int i = pos.getX(); int j = pos.getY(); int k = pos.getZ(); worldIn.playSound(SoundEvent.FIZZ, (double)((float)i + 0.5F), (double)((float)j + 0.5F), (double)((float)k + 0.5F), 0.5F); - ((AWorldServer)worldIn).spawnParticle(ParticleType.SMOKE_LARGE, (double)i, (double)j, (double)k, 8, 1.0D, 1.0D, 1.0D, 0.0f); + + for (int l = 0; l < 8; ++l) + { + worldIn.spawnParticle(ParticleType.SMOKE_LARGE, (double)i + Math.random(), (double)j + Math.random(), (double)k + Math.random(), 0.0D, 0.0D, 0.0D); + } } else { - if (flag && !material.isLiquid()) + if (!worldIn.client && flag && !material.isLiquid()) { worldIn.destroyBlock(pos, true); } if(this.recursive) { - setRecursive((AWorldServer)worldIn, pos, 4, FluidRegistry.getStaticBlock(this.liquid)); + if(!worldIn.client) + setRecursive((AWorldServer)worldIn, pos, 4, FluidRegistry.getStaticBlock(this.liquid)); } else { worldIn.setState(pos, this.liquid.getState(), 3); } } + + return true; } - return true; } } diff --git a/common/src/common/network/IClientPlayer.java b/common/src/common/network/IClientPlayer.java index a1c0704..b412c36 100644 --- a/common/src/common/network/IClientPlayer.java +++ b/common/src/common/network/IClientPlayer.java @@ -34,6 +34,7 @@ import common.packet.S39PacketPlayerAbilities; import common.packet.S3APacketTabComplete; import common.packet.S43PacketUpdateEntityNBT; import common.packet.SPacketAnimation; +import common.packet.SPacketBiomes; import common.packet.SPacketBlockAction; import common.packet.SPacketBlockBreakAnim; import common.packet.SPacketBlockChange; @@ -99,6 +100,7 @@ public interface IClientPlayer { void handlePlayerPosLook(SPacketPlayerPosLook packetIn); void handleMultiBlockChange(SPacketMultiBlockChange packetIn); void handleChunkData(SPacketChunkData packetIn); + void handleBiomes(SPacketBiomes packetIn); void handleBlockChange(SPacketBlockChange packetIn); void handleDisconnect(SPacketDisconnect packetIn); void handleCollectItem(SPacketCollectItem packetIn); diff --git a/common/src/common/network/PacketBuffer.java b/common/src/common/network/PacketBuffer.java index 390c141..4d0df41 100755 --- a/common/src/common/network/PacketBuffer.java +++ b/common/src/common/network/PacketBuffer.java @@ -58,14 +58,16 @@ public class PacketBuffer public BlockPos readBlockPos() { - return new BlockPos(this.readInt(), this.readInt(), this.readInt()); +// return new BlockPos(this.readInt(), this.readInt(), this.readInt()); + return BlockPos.fromLong(this.readLong()); } public void writeBlockPos(BlockPos pos) { - this.writeInt(pos.getX()); - this.writeInt(pos.getY()); - this.writeInt(pos.getZ()); + this.writeLong(pos.toLong()); +// this.writeInt(pos.getX()); +// this.writeInt(pos.getY()); +// this.writeInt(pos.getZ()); } // public Text readChatComponent() throws IOException diff --git a/common/src/common/network/PacketRegistry.java b/common/src/common/network/PacketRegistry.java index d905ace..fd8e7c0 100755 --- a/common/src/common/network/PacketRegistry.java +++ b/common/src/common/network/PacketRegistry.java @@ -56,6 +56,7 @@ import common.packet.S39PacketPlayerAbilities; import common.packet.S3APacketTabComplete; import common.packet.S43PacketUpdateEntityNBT; import common.packet.SPacketAnimation; +import common.packet.SPacketBiomes; import common.packet.SPacketBlockAction; import common.packet.SPacketBlockBreakAnim; import common.packet.SPacketBlockChange; @@ -176,6 +177,7 @@ public enum PacketRegistry this.server(SPacketWorld.class); // this.server(SPacketCapes.class); this.server(SPacketCamera.class); + this.server(SPacketBiomes.class); // this.server(S42PacketTitle.class); this.server(S43PacketUpdateEntityNBT.class); // this.server(SPacketBook.class); diff --git a/common/src/common/packet/S2BPacketChangeGameState.java b/common/src/common/packet/S2BPacketChangeGameState.java index ba4ca54..488573a 100755 --- a/common/src/common/packet/S2BPacketChangeGameState.java +++ b/common/src/common/packet/S2BPacketChangeGameState.java @@ -65,6 +65,6 @@ public class S2BPacketChangeGameState implements Packet } public static enum Action { - SET_WEATHER, RAIN_STRENGTH, DARKNESS, FOG_STRENGTH; + SET_WEATHER, RAIN_STRENGTH, DARKNESS, FOG_STRENGTH, TEMPERATURE; } } diff --git a/common/src/common/packet/SPacketBiomes.java b/common/src/common/packet/SPacketBiomes.java new file mode 100755 index 0000000..3d83aed --- /dev/null +++ b/common/src/common/packet/SPacketBiomes.java @@ -0,0 +1,50 @@ +package common.packet; + +import java.io.IOException; + +import common.network.IClientPlayer; +import common.network.Packet; +import common.network.PacketBuffer; + +public class SPacketBiomes implements Packet { + private int chunkX; + private int chunkZ; + private byte[] biomes; + + public SPacketBiomes() { + } + + public SPacketBiomes(int chunkX, int chunkZ, byte[] biomes) { + this.chunkX = chunkX; + this.chunkZ = chunkZ; + this.biomes = biomes; + } + + public void readPacketData(PacketBuffer buf) throws IOException { + this.chunkX = buf.readInt(); + this.chunkZ = buf.readInt(); + buf.readBytes(this.biomes = new byte[256]); + } + + public void writePacketData(PacketBuffer buf) throws IOException { + buf.writeInt(this.chunkX); + buf.writeInt(this.chunkZ); + buf.writeBytes(this.biomes); + } + + public void processPacket(IClientPlayer handler) { + handler.handleBiomes(this); + } + + public int getChunkX() { + return this.chunkX; + } + + public int getChunkZ() { + return this.chunkZ; + } + + public byte[] getBiomes() { + return this.biomes; + } +} diff --git a/common/src/common/packet/SPacketChunkData.java b/common/src/common/packet/SPacketChunkData.java index 0878dda..1996522 100755 --- a/common/src/common/packet/SPacketChunkData.java +++ b/common/src/common/packet/SPacketChunkData.java @@ -15,18 +15,18 @@ public class SPacketChunkData implements Packet private int chunkX; private int chunkZ; private SPacketChunkData.Extracted extractedData; - private boolean resend; + private boolean biomes; public SPacketChunkData() { } - public SPacketChunkData(Chunk chunkIn, boolean resend, int segUpdate) + public SPacketChunkData(Chunk chunkIn, boolean biomes, int segUpdate) { this.chunkX = chunkIn.xPos; this.chunkZ = chunkIn.zPos; - this.resend = resend; - this.extractedData = getExtractedData(chunkIn, resend, segUpdate); + this.biomes = biomes; + this.extractedData = getExtractedData(chunkIn, biomes, !chunkIn.getWorld().dimension.hasNoLight(), segUpdate); } /** @@ -36,7 +36,7 @@ public class SPacketChunkData implements Packet { this.chunkX = buf.readInt(); this.chunkZ = buf.readInt(); - this.resend = buf.readBoolean(); + this.biomes = buf.readBoolean(); this.extractedData = new SPacketChunkData.Extracted(); this.extractedData.dataSize = buf.readInt(); this.extractedData.data = buf.readByteArray(); @@ -49,7 +49,7 @@ public class SPacketChunkData implements Packet { buf.writeInt(this.chunkX); buf.writeInt(this.chunkZ); - buf.writeBoolean(this.resend); + buf.writeBoolean(this.biomes); buf.writeInt(this.extractedData.dataSize); buf.writeByteArray(this.extractedData.data); } @@ -67,14 +67,16 @@ public class SPacketChunkData implements Packet return this.extractedData.data; } - protected static int getSize(int segments) + protected static int getSize(int segments, boolean overworld, boolean biomes) { int i = segments * 2 * 16 * 16 * 16; int j = segments * 16 * 16 * 16 / 2; - return i + j; + int k = overworld ? segments * 16 * 16 * 16 / 2 : 0; + int l = biomes ? 256 : 0; + return i + j + k + l; } - public static SPacketChunkData.Extracted getExtractedData(Chunk chunk, boolean biomes, int segUpdate) + public static SPacketChunkData.Extracted getExtractedData(Chunk chunk, boolean biomes, boolean overworld, int segUpdate) { BlockArray[] aextendedblockstorage = chunk.getStorage(); SPacketChunkData.Extracted s21packetchunkdata$extracted = new SPacketChunkData.Extracted(); @@ -91,7 +93,7 @@ public class SPacketChunkData implements Packet } } - s21packetchunkdata$extracted.data = new byte[getSize(Integer.bitCount(s21packetchunkdata$extracted.dataSize))]; + s21packetchunkdata$extracted.data = new byte[getSize(Integer.bitCount(s21packetchunkdata$extracted.dataSize), overworld, biomes)]; int j = 0; for (BlockArray extendedblockstorage1 : list) @@ -110,6 +112,19 @@ public class SPacketChunkData implements Packet 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; } @@ -134,9 +149,9 @@ public class SPacketChunkData implements Packet return this.extractedData.dataSize; } - public boolean isResend() + public boolean hasBiomes() { - return this.resend; + return this.biomes; } public static class Extracted diff --git a/common/src/common/packet/SPacketMapChunkBulk.java b/common/src/common/packet/SPacketMapChunkBulk.java index 653352e..aebfac5 100755 --- a/common/src/common/packet/SPacketMapChunkBulk.java +++ b/common/src/common/packet/SPacketMapChunkBulk.java @@ -13,6 +13,7 @@ public class SPacketMapChunkBulk implements Packet private int[] xPositions; private int[] zPositions; private SPacketChunkData.Extracted[] chunksData; + private boolean isOverworld; public SPacketMapChunkBulk() { @@ -24,11 +25,12 @@ public class SPacketMapChunkBulk implements Packet 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, 0xffffffff); + SPacketChunkData.Extracted s21packetchunkdata$extracted = SPacketChunkData.getExtractedData(chunk, true, this.isOverworld, 0xffffffff); this.xPositions[j] = chunk.xPos; this.zPositions[j] = chunk.zPos; this.chunksData[j] = s21packetchunkdata$extracted; @@ -40,6 +42,7 @@ public class SPacketMapChunkBulk implements Packet */ public void readPacketData(PacketBuffer buf) throws IOException { + this.isOverworld = buf.readBoolean(); int i = buf.readVarIntFromBuffer(); this.xPositions = new int[i]; this.zPositions = new int[i]; @@ -51,7 +54,7 @@ public class SPacketMapChunkBulk implements Packet this.zPositions[j] = buf.readInt(); this.chunksData[j] = new SPacketChunkData.Extracted(); this.chunksData[j].dataSize = buf.readInt(); - this.chunksData[j].data = new byte[SPacketChunkData.getSize(Integer.bitCount(this.chunksData[j].dataSize))]; + this.chunksData[j].data = new byte[SPacketChunkData.getSize(Integer.bitCount(this.chunksData[j].dataSize), this.isOverworld, true)]; } for (int k = 0; k < i; ++k) @@ -65,6 +68,7 @@ public class SPacketMapChunkBulk implements Packet */ public void writePacketData(PacketBuffer buf) throws IOException { + buf.writeBoolean(this.isOverworld); buf.writeVarIntToBuffer(this.chunksData.length); for (int i = 0; i < this.xPositions.length; ++i) diff --git a/common/src/common/packet/SPacketServerTick.java b/common/src/common/packet/SPacketServerTick.java index 4cac35c..0a9eac1 100644 --- a/common/src/common/packet/SPacketServerTick.java +++ b/common/src/common/packet/SPacketServerTick.java @@ -8,24 +8,20 @@ import common.network.PacketBuffer; public class SPacketServerTick implements Packet { private int time; - private String serverInfo; public SPacketServerTick() { } - public SPacketServerTick(int time, String info) { + public SPacketServerTick(int time) { this.time = time; - this.serverInfo = info; } public void readPacketData(PacketBuffer buf) throws IOException { this.time = buf.readInt(); - this.serverInfo = buf.readStringFromBuffer(64); } public void writePacketData(PacketBuffer buf) throws IOException { buf.writeInt(this.time); - buf.writeString(this.serverInfo); } public void processPacket(IClientPlayer handler) { @@ -35,8 +31,4 @@ public class SPacketServerTick implements Packet { public int getTime() { return this.time; } - - public String getServerinfo() { - return this.serverInfo; - } } diff --git a/common/src/common/pathfinding/PathNavigate.java b/common/src/common/pathfinding/PathNavigate.java index 8044438..0d8fb09 100755 --- a/common/src/common/pathfinding/PathNavigate.java +++ b/common/src/common/pathfinding/PathNavigate.java @@ -163,6 +163,8 @@ public abstract class PathNavigate this.currentPath = pathentityIn; } + this.removeSunnyPath(); + if (this.currentPath.getCurrentPathLength() == 0) { return false; @@ -320,6 +322,13 @@ public abstract class PathNavigate return this.theEntity.isInLiquid() || this.theEntity.isInMolten(); } + /** + * Trims path data from the end to the first sun covered block + */ + protected void removeSunnyPath() + { + } + /** * Returns true when an entity of specified size could safely walk in a straight line between the two points. Args: * pos1, pos2, entityXSize, entityYSize, entityZSize diff --git a/common/src/common/pathfinding/PathNavigateGround.java b/common/src/common/pathfinding/PathNavigateGround.java index afef617..f12b1c8 100755 --- a/common/src/common/pathfinding/PathNavigateGround.java +++ b/common/src/common/pathfinding/PathNavigateGround.java @@ -13,6 +13,7 @@ import common.world.World; public class PathNavigateGround extends PathNavigate { protected WalkNodeProcessor nodeProcessor; + private boolean shouldAvoidSun; public PathNavigateGround(EntityLiving entitylivingIn, World worldIn) { @@ -70,6 +71,33 @@ public class PathNavigateGround extends PathNavigate } } + /** + * Trims path data from the end to the first sun covered block + */ + protected void removeSunnyPath() + { + super.removeSunnyPath(); + + if (this.shouldAvoidSun) + { + if (this.worldObj.canSeeSky(new BlockPos(ExtMath.floord(this.theEntity.posX), (int)(this.theEntity.getEntityBoundingBox().minY + 0.5D), ExtMath.floord(this.theEntity.posZ)))) + { + return; + } + + for (int i = 0; i < this.currentPath.getCurrentPathLength(); ++i) + { + PathPoint pathpoint = this.currentPath.getPathPointFromIndex(i); + + if (this.worldObj.canSeeSky(new BlockPos(pathpoint.xCoord, pathpoint.yCoord, pathpoint.zCoord))) + { + this.currentPath.setCurrentPathLength(i - 1); + return; + } + } + } + } + /** * Returns true when an entity of specified size could safely walk in a straight line between the two points. Args: * pos1, pos2, entityXSize, entityYSize, entityZSize @@ -258,4 +286,9 @@ public class PathNavigateGround extends PathNavigate { return this.nodeProcessor.getCanSwim(); } + + public void setAvoidSun(boolean par1) + { + this.shouldAvoidSun = par1; + } } diff --git a/common/src/common/tileentity/TileEntityMachine.java b/common/src/common/tileentity/TileEntityMachine.java index ab5df5e..45d9d6b 100755 --- a/common/src/common/tileentity/TileEntityMachine.java +++ b/common/src/common/tileentity/TileEntityMachine.java @@ -12,7 +12,6 @@ import common.network.Packet; import common.packet.S35PacketUpdateTileEntity; import common.rng.Random; import common.util.ExtMath; -import common.world.AWorldServer; public abstract class TileEntityMachine extends TileEntityLockable implements IHopper, ITickable { public static enum Status { @@ -217,7 +216,7 @@ public abstract class TileEntityMachine extends TileEntityLockable implements IH public void update() { if(this.worldObj != null && !this.worldObj.client && this.status != Status.BROKEN) { - int envTemp = (int)((AWorldServer)this.worldObj).getTemperatureC(this.getPos()); + int envTemp = (int)this.worldObj.getTemperatureC(this.getPos()); if(this.executeFunction()) { this.temperature += this.getTempIncrement(); this.status = this.temperature >= (this.getMaxTemp() * 9) / 10 ? Status.OVERHEAT : Status.RUNNING; diff --git a/common/src/common/util/BlockPos.java b/common/src/common/util/BlockPos.java index 160736e..493452c 100755 --- a/common/src/common/util/BlockPos.java +++ b/common/src/common/util/BlockPos.java @@ -8,6 +8,14 @@ import common.entity.Entity; public class BlockPos extends Vec3i { public static final BlockPos ORIGIN = new BlockPos(0, 0, 0); + private static final int NUM_X_BITS = 1 + 26; // ExtMath.calculateLogBaseTwo(ExtMath.roundUpToPowerOfTwo(World.MAX_SIZE)); + private static final int NUM_Z_BITS = NUM_X_BITS; + private static final int NUM_Y_BITS = 64 - NUM_X_BITS - NUM_Z_BITS; + private static final int Y_SHIFT = 0 + NUM_Z_BITS; + private static final int X_SHIFT = Y_SHIFT + NUM_Y_BITS; + private static final long X_MASK = (1L << NUM_X_BITS) - 1L; + private static final long Y_MASK = (1L << NUM_Y_BITS) - 1L; + private static final long Z_MASK = (1L << NUM_Z_BITS) - 1L; public BlockPos(int x, int y, int z) { @@ -186,6 +194,19 @@ public class BlockPos extends Vec3i return new BlockPos(this.getY() * vec.getZ() - this.getZ() * vec.getY(), this.getZ() * vec.getX() - this.getX() * vec.getZ(), this.getX() * vec.getY() - this.getY() * vec.getX()); } + public long toLong() + { + return ((long)this.getX() & X_MASK) << X_SHIFT | ((long)this.getY() & Y_MASK) << Y_SHIFT | ((long)this.getZ() & Z_MASK) << 0; + } + + public static BlockPos fromLong(long serialized) + { + int i = (int)(serialized << 64 - X_SHIFT - NUM_X_BITS >> 64 - NUM_X_BITS); + int j = (int)(serialized << 64 - Y_SHIFT - NUM_Y_BITS >> 64 - NUM_Y_BITS); + int k = (int)(serialized << 64 - NUM_Z_BITS >> 64 - NUM_Z_BITS); + return new BlockPos(i, j, k); + } + public static Iterable getAllInBox(BlockPos from, BlockPos to) { final BlockPos blockpos = new BlockPos(Math.min(from.getX(), to.getX()), Math.min(from.getY(), to.getY()), Math.min(from.getZ(), to.getZ())); diff --git a/common/src/common/util/LongHashMap.java b/common/src/common/util/LongHashMap.java new file mode 100755 index 0000000..89aba64 --- /dev/null +++ b/common/src/common/util/LongHashMap.java @@ -0,0 +1,285 @@ +package common.util; + +public class LongHashMap +{ + private transient LongHashMap.Entry[] hashArray = new LongHashMap.Entry[4096]; + private transient int numHashElements; + private int mask; + private int capacity = 3072; + private final float percentUseable = 0.75F; + private transient volatile int modCount; + + public static long packInt(int x, int z) { + return (long)x & 4294967295L | ((long)z & 4294967295L) << 32; + } + + public LongHashMap() + { + this.mask = this.hashArray.length - 1; + } + + /** + * returns the hashed key given the original key + */ + private static int getHashedKey(long originalKey) + { + return hash((int)(originalKey ^ originalKey >>> 32)); + } + + /** + * the hash function + */ + private static int hash(int integer) + { + integer = integer ^ integer >>> 20 ^ integer >>> 12; + return integer ^ integer >>> 7 ^ integer >>> 4; + } + + /** + * gets the index in the hash given the array length and the hashed key + */ + private static int getHashIndex(int p_76158_0_, int p_76158_1_) + { + return p_76158_0_ & p_76158_1_; + } + + public int getNumHashElements() + { + return this.numHashElements; + } + + /** + * get the value from the map given the key + */ + public V getValueByKey(long p_76164_1_) + { + int i = getHashedKey(p_76164_1_); + + for (LongHashMap.Entry entry = this.hashArray[getHashIndex(i, this.mask)]; entry != null; entry = entry.nextEntry) + { + if (entry.key == p_76164_1_) + { + return entry.value; + } + } + + return (V)null; + } + + public boolean containsItem(long p_76161_1_) + { + return this.getEntry(p_76161_1_) != null; + } + + final LongHashMap.Entry getEntry(long p_76160_1_) + { + int i = getHashedKey(p_76160_1_); + + for (LongHashMap.Entry entry = this.hashArray[getHashIndex(i, this.mask)]; entry != null; entry = entry.nextEntry) + { + if (entry.key == p_76160_1_) + { + return entry; + } + } + + return null; + } + + /** + * Add a key-value pair. + */ + public void add(long p_76163_1_, V p_76163_3_) + { + int i = getHashedKey(p_76163_1_); + int j = getHashIndex(i, this.mask); + + for (LongHashMap.Entry entry = this.hashArray[j]; entry != null; entry = entry.nextEntry) + { + if (entry.key == p_76163_1_) + { + entry.value = p_76163_3_; + return; + } + } + + ++this.modCount; + this.createKey(i, p_76163_1_, p_76163_3_, j); + } + + /** + * resizes the table + */ + private void resizeTable(int p_76153_1_) + { + LongHashMap.Entry[] entry = this.hashArray; + int i = entry.length; + + if (i == 1073741824) + { + this.capacity = Integer.MAX_VALUE; + } + else + { + LongHashMap.Entry[] entry1 = new LongHashMap.Entry[p_76153_1_]; + this.copyHashTableTo(entry1); + this.hashArray = entry1; + this.mask = this.hashArray.length - 1; + this.capacity = (int)((float)p_76153_1_ * this.percentUseable); + } + } + + /** + * copies the hash table to the specified array + */ + private void copyHashTableTo(LongHashMap.Entry[] p_76154_1_) + { + LongHashMap.Entry[] entry = this.hashArray; + int i = p_76154_1_.length; + + for (int j = 0; j < entry.length; ++j) + { + LongHashMap.Entry entry1 = entry[j]; + + if (entry1 != null) + { + entry[j] = null; + + while (true) + { + LongHashMap.Entry entry2 = entry1.nextEntry; + int k = getHashIndex(entry1.hash, i - 1); + entry1.nextEntry = p_76154_1_[k]; + p_76154_1_[k] = entry1; + entry1 = entry2; + + if (entry2 == null) + { + break; + } + } + } + } + } + + /** + * calls the removeKey method and returns removed object + */ + public V remove(long p_76159_1_) + { + LongHashMap.Entry entry = this.removeKey(p_76159_1_); + return (V)(entry == null ? null : entry.value); + } + + final LongHashMap.Entry removeKey(long p_76152_1_) + { + int i = getHashedKey(p_76152_1_); + int j = getHashIndex(i, this.mask); + LongHashMap.Entry entry = this.hashArray[j]; + LongHashMap.Entry entry1; + LongHashMap.Entry entry2; + + for (entry1 = entry; entry1 != null; entry1 = entry2) + { + entry2 = entry1.nextEntry; + + if (entry1.key == p_76152_1_) + { + ++this.modCount; + --this.numHashElements; + + if (entry == entry1) + { + this.hashArray[j] = entry2; + } + else + { + entry.nextEntry = entry2; + } + + return entry1; + } + + entry = entry1; + } + + return entry1; + } + + /** + * creates the key in the hash table + */ + private void createKey(int p_76156_1_, long p_76156_2_, V p_76156_4_, int p_76156_5_) + { + LongHashMap.Entry entry = this.hashArray[p_76156_5_]; + this.hashArray[p_76156_5_] = new LongHashMap.Entry(p_76156_1_, p_76156_2_, p_76156_4_, entry); + + if (this.numHashElements++ >= this.capacity) + { + this.resizeTable(2 * this.hashArray.length); + } + } + + static class Entry + { + final long key; + V value; + LongHashMap.Entry nextEntry; + final int hash; + + Entry(int p_i1553_1_, long p_i1553_2_, V p_i1553_4_, LongHashMap.Entry p_i1553_5_) + { + this.value = p_i1553_4_; + this.nextEntry = p_i1553_5_; + this.key = p_i1553_2_; + this.hash = p_i1553_1_; + } + + public final long getKey() + { + return this.key; + } + + public final V getValue() + { + return this.value; + } + + public final boolean equals(Object p_equals_1_) + { + if (!(p_equals_1_ instanceof LongHashMap.Entry)) + { + return false; + } + else + { + LongHashMap.Entry entry = (LongHashMap.Entry)p_equals_1_; + Object object = Long.valueOf(this.getKey()); + Object object1 = Long.valueOf(entry.getKey()); + + if (object == object1 || object != null && object.equals(object1)) + { + Object object2 = this.getValue(); + Object object3 = entry.getValue(); + + if (object2 == object3 || object2 != null && object2.equals(object3)) + { + return true; + } + } + + return false; + } + } + + public final int hashCode() + { + return LongHashMap.getHashedKey(this.key); + } + + public final String toString() + { + return this.getKey() + "=" + this.getValue(); + } + } +} diff --git a/common/src/common/world/AWorldServer.java b/common/src/common/world/AWorldServer.java index b1d4457..3ab7b11 100644 --- a/common/src/common/world/AWorldServer.java +++ b/common/src/common/world/AWorldServer.java @@ -2,9 +2,7 @@ package common.world; import java.util.List; -import common.biome.Biome; import common.block.Block; -import common.block.LeavesType; import common.dimension.Dimension; import common.entity.Entity; import common.entity.npc.EntityNPC; @@ -46,12 +44,4 @@ public abstract class AWorldServer extends World { public abstract boolean isBlockinHighHumidity(BlockPos pos); public abstract T findNearestEntityWithinAABB(Class entityType, BoundingBox aabb, T closestTo); public abstract long getTime(); - public abstract Biome getBiomeGenForCoords(BlockPos pos); - public abstract boolean canBurnAt(BlockPos pos); - public abstract boolean canFreezeAt(BlockPos pos); - public abstract boolean doesWaterVaporize(BlockPos pos); - public abstract boolean isLavaFaster(BlockPos pos); - public abstract LeavesType getLeavesGen(BlockPos pos); - public abstract float getTemperatureC(BlockPos pos); - public abstract boolean isRainingAt(BlockPos strikePosition, boolean wet); } diff --git a/common/src/common/world/BlockArray.java b/common/src/common/world/BlockArray.java index 557e89d..44fba70 100755 --- a/common/src/common/world/BlockArray.java +++ b/common/src/common/world/BlockArray.java @@ -11,11 +11,14 @@ public class BlockArray { private int ticked; private char[] data; private NibbleArray blocklight; + private NibbleArray skylight; - public BlockArray(int y) { + public BlockArray(int y, boolean sky) { this.yBase = y; this.data = new char[4096]; this.blocklight = new NibbleArray(); + if(sky) + this.skylight = new NibbleArray(); } public State get(int x, int y, int z) { @@ -61,6 +64,14 @@ public class BlockArray { return this.yBase; } + public void setSky(int x, int y, int z, int value) { + this.skylight.set(x, y, z, value); + } + + public int getSky(int x, int y, int z) { + return this.skylight.get(x, y, z); + } + public void setLight(int x, int y, int z, int value) { this.blocklight.set(x, y, z, value); } @@ -94,6 +105,10 @@ public class BlockArray { return this.blocklight; } + public NibbleArray getSkylight() { + return this.skylight; + } + public void setData(char[] data) { this.data = data; } @@ -101,4 +116,8 @@ public class BlockArray { public void setBlocklight(NibbleArray data) { this.blocklight = data; } + + public void setSkylight(NibbleArray data) { + this.skylight = data; + } } diff --git a/common/src/common/world/Chunk.java b/common/src/common/world/Chunk.java index 5720983..6a5fdf7 100755 --- a/common/src/common/world/Chunk.java +++ b/common/src/common/world/Chunk.java @@ -1,5 +1,6 @@ package common.world; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentLinkedQueue; @@ -23,6 +24,7 @@ import common.util.ClassInheritanceMultiMap; import common.util.ExtMath; import common.util.Facing; import common.util.NibbleArray; +import common.worldgen.BiomeGenerator; import common.worldgen.DebugStates; public class Chunk { @@ -31,15 +33,21 @@ public class Chunk { private final World world; private final BlockArray[] blocks = new BlockArray[32]; 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(); 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 = 8192; private long lastSave; private long inhabited; @@ -51,10 +59,13 @@ public class Chunk { for(int y = 0; y < this.entities.length; ++y) { this.entities[y] = new ClassInheritanceMultiMap(Entity.class); } + Arrays.fill(this.precHeight, -999); + Arrays.fill(this.biomes, (byte)-1); } - public Chunk(World world, short[] data, int height, State base, State ceil, Random rand, int x, int z) { + public Chunk(World world, short[] data, int height, State base, State 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) { @@ -62,7 +73,7 @@ public class Chunk { if(state != null && state.getBlock().getMaterial() != Material.air) { int y = by >> 4; if(this.blocks[y] == null) - this.blocks[y] = new BlockArray(y << 4); + this.blocks[y] = new BlockArray(y << 4, sky); this.blocks[y].set(bx, by & 15, bz, state); } } @@ -70,7 +81,7 @@ public class Chunk { } if(base != null) { if(this.blocks[0] == null) - this.blocks[0] = new BlockArray(0); + this.blocks[0] = new BlockArray(0, sky); for(int bx = 0; bx < 16; ++bx) { for(int bz = 0; bz < 16; ++bz) { for(int by = 0; by < 5; ++by) { @@ -83,10 +94,10 @@ public class Chunk { if(ceil != null) { int y = (height - 1) >> 4; if(this.blocks[y] == null) - this.blocks[y] = new BlockArray(y << 4); + this.blocks[y] = new BlockArray(y << 4, sky); y = (height - 5) >> 4; if(this.blocks[y] == null) - this.blocks[y] = new BlockArray(y << 4); + this.blocks[y] = new BlockArray(y << 4, sky); for(int bx = 0; bx < 16; ++bx) { for(int bz = 0; bz < 16; ++bz) { for(int by = height - 1; by >= height - 5; --by) { @@ -96,14 +107,272 @@ public class Chunk { } } } - if(ceil != null) + for(int n = 0; n < this.biomes.length; ++n) { + this.biomes[n] = (byte)biomes[n].id; + } + if(ceil == null) + this.genSkyLight(); + else this.resetRelight(); } + 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() { + for(int y = this.blocks.length - 1; y >= 0; --y) { + if(this.blocks[y] != null) { + return this.blocks[y].getY(); + } + } + + return 0; + } + public BlockArray[] getStorage() { return this.blocks; } - + + protected void genHeights() { + int h = this.getTopSegment(); + this.minHeight = Integer.MAX_VALUE; + + for(int x = 0; x < 16; ++x) { + for(int z = 0; z < 16; ++z) { + this.precHeight[x + (z << 4)] = -999; + + for(int y = h + 16; y > 0; --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 h = this.getTopSegment(); + this.minHeight = Integer.MAX_VALUE; + + for(int x = 0; x < 16; ++x) { + for(int z = 0; z < 16; ++z) { + this.precHeight[x + (z << 4)] = -999; + + for(int y = h + 16; y > 0; --y) { + if(this.getOpacity(x, y - 1, z) != 0) { + this.height[z << 4 | x] = y; + + if(y < this.minHeight) { + this.minHeight = y; + } + + break; + } + } + + if(!this.world.dimension.hasNoLight()) { + int l = 15; + int y = h + 16 - 1; + + while(true) { + int b = this.getOpacity(x, y, z); + + if(b == 0 && l != 15) { + b = 1; + } + + l -= b; + + if(l > 0) { + BlockArray stor = this.blocks[y >> 4]; + + if(stor != null) { + stor.setSky(x, y & 15, z, l); + this.world.notifyLightSet(new BlockPos((this.xPos << 4) + x, y, (this.zPos << 4) + z)); + } + } + + --y; + + if(y <= 0 || l <= 0) { + break; + } + } + } + } + } + + this.modified = true; + } + + private void propagateOcclusion(int x, int z) { + this.updateSky[x + z * 16] = true; + this.gapUpdate = true; + } + + private void recheckGaps(boolean single) { +// this.world.profiler.start("recheckGaps"); + + if(this.world.isAreaLoaded(new BlockPos(this.xPos * 16 + 8, 0, this.zPos * 16 + 8), 16)) { + for(int x = 0; x < 16; ++x) { + for(int z = 0; z < 16; ++z) { + if(this.updateSky[x + z * 16]) { + this.updateSky[x + z * 16] = false; + int h = this.getHeight(x, z); + int cx = this.xPos * 16 + x; + int cz = this.zPos * 16 + z; + int max = Integer.MAX_VALUE; + + for(Facing face : Facing.Plane.HORIZONTAL) { + max = Math.min(max, this.world.getChunksLowestHorizon(cx + face.getFrontOffsetX(), + cz + face.getFrontOffsetZ())); + } + + this.checkNeighbor(cx, cz, max); + + for(Facing face : Facing.Plane.HORIZONTAL) { + this.checkNeighbor(cx + face.getFrontOffsetX(), cz + face.getFrontOffsetZ(), h); + } + + if(single) { +// this.world.profiler.end(); + return; + } + } + } + } + + this.gapUpdate = false; + } + +// this.world.profiler.end(); + } + + private void checkNeighbor(int x, int z, int max) { + int h = this.world.getHeight(new BlockPos(x, 0, z)).getY(); + + if(h > max) { + this.updateNeighbor(x, z, max, h + 1); + } + else if(h < max) { + this.updateNeighbor(x, z, h, max + 1); + } + } + + private void updateNeighbor(int x, int z, int bottom, int top) { + if(top > bottom && this.world.isAreaLoaded(new BlockPos(x, 0, z), 16)) { + for(int y = bottom; y < top; ++y) { + this.world.checkLightFor(LightType.SKY, new BlockPos(x, y, z)); + } + + this.modified = true; + } + } + + private void relightBlock(int x, int y, int z) { + int h = this.height[z << 4 | x] & 511; + int cy = h; + + if(y > h) { + cy = y; + } + + while(cy > 0 && this.getOpacity(x, cy - 1, z) == 0) { + --cy; + } + + if(cy != h) { + this.world.markBlocksDirtyVertical(x + this.xPos * 16, z + this.zPos * 16, cy, h); + this.height[z << 4 | x] = cy; + int cx = this.xPos * 16 + x; + int cz = this.zPos * 16 + z; + + if(!this.world.dimension.hasNoLight()) { + if(cy < h) { + for(int n = cy; n < h; ++n) { + BlockArray stor = this.blocks[n >> 4]; + + if(stor != null) { + stor.setSky(x, n & 15, z, 15); + this.world.notifyLightSet(new BlockPos((this.xPos << 4) + x, n, (this.zPos << 4) + z)); + } + } + } + else { + for(int n = h; n < cy; ++n) { + BlockArray stor = this.blocks[n >> 4]; + + if(stor != null) { + stor.setSky(x, n & 15, z, 0); + this.world.notifyLightSet(new BlockPos((this.xPos << 4) + x, n, (this.zPos << 4) + z)); + } + } + } + + int l = 15; + + while(cy > 0 && l > 0) { + --cy; + int b = this.getOpacity(x, cy, z); + + if(b == 0) { + b = 1; + } + + l -= b; + + if(l < 0) { + l = 0; + } + + BlockArray stor = this.blocks[cy >> 4]; + + if(stor != null) { + stor.setSky(x, cy & 15, z, l); + } + } + } + + int sh = this.height[z << 4 | x]; + int sy = h; + int ey = sh; + + if(sh < h) { + sy = sh; + ey = h; + } + + if(sh < this.minHeight) { + this.minHeight = sh; + } + + if(!this.world.dimension.hasNoLight()) { + for(Facing face : Facing.Plane.HORIZONTAL) { + this.updateNeighbor(cx + face.getFrontOffsetX(), cz + face.getFrontOffsetZ(), sy, ey); + } + + this.updateNeighbor(cx, cz, sy, ey); + } + + this.modified = true; + } + } + public int getOpacity(BlockPos pos) { return this.getBlock(pos).getLightOpacity(); } @@ -184,6 +453,11 @@ public class Chunk { int z = pos.getZ() & 15; int o = z << 4 | x; + if(y >= this.precHeight[o] - 1) { + this.precHeight[o] = -999; + } + + int h = this.height[o]; State old = this.getState(pos); if(old == state) { @@ -193,13 +467,15 @@ public class Chunk { Block block = state.getBlock(); Block oldb = old.getBlock(); BlockArray stor = this.blocks[y >> 4]; + boolean up = false; if(stor == null) { if(block == Blocks.air) { return null; } - stor = this.blocks[y >> 4] = new BlockArray(y >> 4 << 4); + stor = this.blocks[y >> 4] = new BlockArray(y >> 4 << 4, !this.world.dimension.hasNoLight()); + up = y >= h; } stor.set(x, y & 15, z, state); @@ -217,6 +493,27 @@ public class Chunk { return null; } else { + if(up) { + this.genSkyLight(); + } + else { + int b = block.getLightOpacity(); + int ob = oldb.getLightOpacity(); + + if(b > 0) { + if(y >= h) { + this.relightBlock(x, y + 1, z); + } + } + else if(y == h - 1) { + this.relightBlock(x, y, z); + } + + if(b != ob && (b < ob || this.getLight(LightType.SKY, pos) > 0 || this.getLight(LightType.BLOCK, pos) > 0)) { + this.propagateOcclusion(x, z); + } + } + if(oldb instanceof ITileEntityProvider) { TileEntity tile = this.getTileEntity(pos, TileEntity.EnumCreateEntityType.CHECK); @@ -248,27 +545,37 @@ public class Chunk { } } - public int getLight(BlockPos pos) { + public int getLight(LightType type, BlockPos pos) { int x = pos.getX() & 15; int y = pos.getY(); int z = pos.getZ() & 15; BlockArray stor = this.blocks[y >> 4]; - return stor == null ? 0 : stor.getLight(x, y & 15, z); + return stor == null ? (this.canSeeSky(pos) ? type.defValue : 0) + : (type == LightType.SKY ? (this.world.dimension.hasNoLight() ? 0 : stor.getSky(x, y & 15, z)) + : (type == LightType.BLOCK ? stor.getLight(x, y & 15, z) : type.defValue)); } - public void setLight(BlockPos pos, int value) { + public void setLight(LightType type, BlockPos pos, int value) { int x = pos.getX() & 15; int y = pos.getY(); int z = pos.getZ() & 15; BlockArray stor = this.blocks[y >> 4]; if(stor == null) { - stor = this.blocks[y >> 4] = new BlockArray(y >> 4 << 4); + stor = this.blocks[y >> 4] = new BlockArray(y >> 4 << 4, !this.world.dimension.hasNoLight()); + this.genSkyLight(); } this.modified = true; - stor.setLight(x, y & 15, z, value); + if(type == LightType.SKY) { + if(!this.world.dimension.hasNoLight()) { + stor.setSky(x, y & 15, z, value); + } + } + else if(type == LightType.BLOCK) { + stor.setLight(x, y & 15, z, value); + } } public int getLightSub(BlockPos pos, int amount) { @@ -278,11 +585,11 @@ public class Chunk { BlockArray stor = this.blocks[y >> 4]; if(stor == null) { - return !this.world.dimension.hasNoLight() && amount < 15 - ? 15 - amount : 0; + return !this.world.dimension.hasNoLight() && amount < LightType.SKY.defValue + ? LightType.SKY.defValue - amount : 0; } else { - int l = this.world.dimension.hasNoLight() ? 0 : 15; + int l = this.world.dimension.hasNoLight() ? 0 : stor.getSky(x, y & 15, z); l = l - amount; int b = stor.getLight(x, y & 15, z); @@ -335,6 +642,13 @@ public class Chunk { this.entities[y].remove(entity); } + public boolean canSeeSky(BlockPos pos) { + int x = pos.getX() & 15; + int y = pos.getY(); + int z = pos.getZ() & 15; + return y >= this.height[z << 4 | x]; + } + private TileEntity createNewTileEntity(BlockPos pos) { Block block = this.getBlock(pos); return !block.hasTileEntity() ? null : ((ITileEntityProvider)block).createNewTileEntity(this.world, this.getMeta(pos)); @@ -489,9 +803,48 @@ public class Chunk { return false; } - public void update() { + public BlockPos getPrecipitation(BlockPos pos) { + int x = pos.getX() & 15; + int z = pos.getZ() & 15; + int o = x | z << 4; + BlockPos loc = new BlockPos(pos.getX(), this.precHeight[o], pos.getZ()); + + if(loc.getY() == -999) { + int y = this.getTopSegment() + 15; + loc = new BlockPos(pos.getX(), y, pos.getZ()); + int h = -1; + + while(loc.getY() > 0 && h == -1) { + Block block = this.getBlock(loc); + Material mat = block.getMaterial(); + + if((!mat.blocksMovement() && !mat.isLiquid()) + || (mat == Material.leaves && ((mat = this.getBlock(loc.up()).getMaterial()) == Material.snow) + || mat == Material.leaves)) { + loc = loc.down(); + } + else { + h = loc.getY() + 1; + } + } + + this.precHeight[o] = h; + } + + return new BlockPos(pos.getX(), this.precHeight[o], pos.getZ()); + } + + public void update(boolean noGaps) { + if(this.gapUpdate && !this.world.dimension.hasNoLight() && !noGaps) { + this.recheckGaps(this.world.client); + } + this.updated = true; - + + if(!this.lightInit && this.populated) { + this.checkLight(); + } + while(!this.tileQueue.isEmpty()) { BlockPos pos = (BlockPos)this.tileQueue.poll(); @@ -504,7 +857,7 @@ public class Chunk { } public boolean isPopulated() { - return this.updated && this.populated; + return this.updated && this.populated && this.lightInit; } public ChunkPos getPos() { @@ -543,13 +896,14 @@ public class Chunk { } } - public void setData(byte[] data, int update, boolean resend) { + public void setData(byte[] data, int update, boolean biomes) { int pos = 0; + boolean sky = !this.world.dimension.hasNoLight(); for(int n = 0; n < this.blocks.length; ++n) { if((update & 1 << n) != 0) { if(this.blocks[n] == null) { - this.blocks[n] = new BlockArray(n << 4); + this.blocks[n] = new BlockArray(n << 4, sky); } char[] blocks = this.blocks[n].getData(); @@ -559,7 +913,7 @@ public class Chunk { pos += 2; } } - else if(resend && this.blocks[n] != null) { + else if(biomes && this.blocks[n] != null) { this.blocks[n] = null; } } @@ -572,32 +926,65 @@ public class Chunk { } } + if(sky) { + for(int n = 0; n < this.blocks.length; ++n) { + if((update & 1 << n) != 0 && this.blocks[n] != null) { + NibbleArray slight = this.blocks[n].getSkylight(); + System.arraycopy(data, pos, slight.getData(), 0, slight.getData().length); + pos += slight.getData().length; + } + } + } + + if(biomes) { + System.arraycopy(data, pos, this.biomes, 0, this.biomes.length); +// int unk = pos + this.biomes.length; + } + for(int n = 0; n < this.blocks.length; ++n) { if(this.blocks[n] != null && (update & 1 << n) != 0) { this.blocks[n].update(); } } + this.lightInit = true; this.populated = true; + this.genHeights(); for(TileEntity tile : this.tiles.values()) { tile.updateContainingBlockInfo(); } } - public Biome getBiome(BlockPos pos) { + 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) { - o = Biome.DEF_BIOME.id; + 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); + } + else { + for(int n = 0; n < this.biomes.length; ++n) { + this.biomes[n] = biomes[n]; + } + } + } + public void resetRelight() { this.lightChecks = 0; } @@ -640,7 +1027,106 @@ public class Chunk { } } } - + + public void checkLight() { + this.populated = true; + this.lightInit = true; + BlockPos pos = new BlockPos(this.xPos << 4, 0, this.zPos << 4); + + if(!this.world.dimension.hasNoLight()) { + if(this.world.isAreaLoaded(pos.add(-1, 0, -1), pos.add(16, this.world.getSeaLevel(), 16))) { + label92: + + for(int x = 0; x < 16; ++x) { + for(int z = 0; z < 16; ++z) { + if(!this.updateColumn(x, z)) { + this.lightInit = false; + break label92; + } + } + } + + if(this.lightInit) { + for(Facing face : Facing.Plane.HORIZONTAL) { + int d = face.getAxisDirection() == Facing.AxisDirection.POSITIVE ? 16 : 1; + this.world.getChunk(pos.offset(face, d)).updateColumns(face.getOpposite()); + } + + this.setSkyDirty(); + } + } + else { + this.lightInit = false; + } + } + } + + private void setSkyDirty() { + for(int n = 0; n < this.updateSky.length; ++n) { + this.updateSky[n] = true; + } + + this.recheckGaps(false); + } + + private void updateColumns(Facing facing) { + if(this.populated) { + if(facing == Facing.EAST) { + for(int z = 0; z < 16; ++z) { + this.updateColumn(15, z); + } + } + else if(facing == Facing.WEST) { + for(int z = 0; z < 16; ++z) { + this.updateColumn(0, z); + } + } + else if(facing == Facing.SOUTH) { + for(int x = 0; x < 16; ++x) { + this.updateColumn(x, 15); + } + } + else if(facing == Facing.NORTH) { + for(int x = 0; x < 16; ++x) { + this.updateColumn(x, 0); + } + } + } + } + + private boolean updateColumn(int x, int z) { + int top = this.getTopSegment(); + boolean opaque = false; + boolean below = false; + BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos((this.xPos << 4) + x, 0, (this.zPos << 4) + z); + + for(int y = top + 16 - 1; y > this.world.getSeaLevel() || y > 0 && !below; --y) { + pos.set(pos.getX(), y, pos.getZ()); + int o = this.getOpacity(pos); + + if(o == 255 && pos.getY() < this.world.getSeaLevel()) { + below = true; + } + + if(!opaque && o > 0) { + opaque = true; + } + else if(opaque && o == 0 && !this.world.checkLight(pos)) { + return false; + } + } + + for(int y = pos.getY(); y > 0; --y) { + pos.set(pos.getX(), y, pos.getZ()); + + if(this.getBlock(pos).getLightValue() > 0) { + this.world.checkLight(pos); + } + } + + return true; + } + public boolean isLoaded() { return this.loaded; } @@ -653,6 +1139,21 @@ public class Chunk { 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; } @@ -669,6 +1170,14 @@ public class Chunk { 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; } @@ -681,6 +1190,10 @@ public class Chunk { this.lastSave = time; } + public int getLowest() { + return this.minHeight; + } + public long getInhabited() { return this.inhabited; } diff --git a/common/src/common/world/IWorldAccess.java b/common/src/common/world/IWorldAccess.java index 3986e79..b798152 100755 --- a/common/src/common/world/IWorldAccess.java +++ b/common/src/common/world/IWorldAccess.java @@ -1,5 +1,6 @@ package common.world; +import common.biome.Biome; import common.tileentity.TileEntity; import common.util.BlockPos; @@ -7,4 +8,5 @@ public interface IWorldAccess extends IBlockAccess { TileEntity getTileEntity(BlockPos pos); int getCombinedLight(BlockPos pos, int lightValue); + Biome getBiomeGenForCoords(BlockPos pos); } diff --git a/common/src/common/world/LightType.java b/common/src/common/world/LightType.java new file mode 100755 index 0000000..e1bfdbb --- /dev/null +++ b/common/src/common/world/LightType.java @@ -0,0 +1,11 @@ +package common.world; + +public enum LightType { + SKY(15), BLOCK(0); + + public final int defValue; + + private LightType(int def) { + this.defValue = def; + } +} diff --git a/common/src/common/world/World.java b/common/src/common/world/World.java index 67d0743..519dc36 100755 --- a/common/src/common/world/World.java +++ b/common/src/common/world/World.java @@ -6,12 +6,14 @@ import java.util.List; import java.util.Set; import java.util.function.Predicate; +import common.biome.Biome; import common.block.Block; import common.block.BlockHopper; import common.block.BlockLiquid; import common.block.BlockSlab; import common.block.BlockSnow; import common.block.BlockStairs; +import common.block.LeavesType; import common.collect.Lists; import common.collect.Sets; import common.dimension.Dimension; @@ -78,6 +80,7 @@ public abstract class World implements IWorldAccess { protected float rain; protected float darkness; protected float fog; + protected float temp; protected Weather weather; protected long daytime; @@ -129,7 +132,14 @@ public abstract class World implements IWorldAccess { if(Math.abs(this.gravity) < 0.075) 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 boolean isAirBlock(BlockPos pos) { return this.getState(pos).getBlock().getMaterial() == Material.air; } @@ -272,7 +282,13 @@ public abstract class World implements IWorldAccess { z2 = x2; x2 = i; } - + + if(!this.dimension.hasNoLight()) { + for(int j = x2; j <= z2; ++j) { + this.checkLightFor(LightType.SKY, new BlockPos(x1, j, z1)); + } + } + this.markBlockRangeForRenderUpdate(x1, x2, z1, x1, z2, z1); } @@ -323,6 +339,10 @@ public abstract class World implements IWorldAccess { } } + public boolean canSeeSky(BlockPos pos) { + return this.getChunk(pos).canSeeSky(pos); + } + public int getLight(BlockPos pos) { if(pos.getY() < 0) { return 0; @@ -384,83 +404,122 @@ public abstract class World implements IWorldAccess { } } - public int getLightFromNeighborsFor(BlockPos pos) { + public BlockPos getHeight(BlockPos pos) { + int i; + + if(pos.getX() >= -MAX_SIZE && pos.getZ() >= -MAX_SIZE && pos.getX() < MAX_SIZE && pos.getZ() < MAX_SIZE) { + if(this.isLoaded(pos.getX() >> 4, pos.getZ() >> 4, true)) { + i = this.getChunk(pos.getX() >> 4, pos.getZ() >> 4).getHeight(pos.getX() & 15, pos.getZ() & 15); + } + else { + i = 0; + } + } + else { + i = this.getSeaLevel() + 1; + } + + return new BlockPos(pos.getX(), i, pos.getZ()); + } + + public int getChunksLowestHorizon(int x, int z) { + if(x >= -MAX_SIZE && z >= -MAX_SIZE && x < MAX_SIZE && z < MAX_SIZE) { + if(!this.isLoaded(x >> 4, z >> 4, true)) { + return 0; + } + else { + Chunk chunk = this.getChunk(x >> 4, z >> 4); + return chunk.getLowest(); + } + } + else { + return this.getSeaLevel() + 1; + } + } + + public int getLightFromNeighborsFor(LightType type, BlockPos pos) { + if(this.dimension.hasNoLight() && type == LightType.SKY) { + return 0; + } + else { + if(pos.getY() < 0) { + pos = new BlockPos(pos.getX(), 0, pos.getZ()); + } + + if(!isValid(pos)) { + return type.defValue; + } + else if(!this.isBlockLoaded(pos)) { + return type.defValue; + } + else if(this.getState(pos).getBlock().getSumBrightness()) { + int i1 = this.getLightFor(type, pos.up()); + int i = this.getLightFor(type, pos.east()); + int j = this.getLightFor(type, pos.west()); + int k = this.getLightFor(type, pos.south()); + int l = this.getLightFor(type, pos.north()); + + if(i > i1) { + i1 = i; + } + + if(j > i1) { + i1 = j; + } + + if(k > i1) { + i1 = k; + } + + if(l > i1) { + i1 = l; + } + + return i1; + } + else { + Chunk chunk = this.getChunk(pos); + return chunk.getLight(type, pos); + } + } + } + + public int getLightFor(LightType type, BlockPos pos) { if(pos.getY() < 0) { pos = new BlockPos(pos.getX(), 0, pos.getZ()); } if(!isValid(pos)) { - return 0; + return type.defValue; } else if(!this.isBlockLoaded(pos)) { - return 0; - } - else if(this.getState(pos).getBlock().getSumBrightness()) { - int i1 = this.getLightFor(pos.up()); - int i = this.getLightFor(pos.east()); - int j = this.getLightFor(pos.west()); - int k = this.getLightFor(pos.south()); - int l = this.getLightFor(pos.north()); - - if(i > i1) { - i1 = i; - } - - if(j > i1) { - i1 = j; - } - - if(k > i1) { - i1 = k; - } - - if(l > i1) { - i1 = l; - } - - return i1; + return type.defValue; } else { Chunk chunk = this.getChunk(pos); - return chunk.getLight(pos); + return chunk.getLight(type, pos); } } - public int getLightFor(BlockPos pos) { - if(pos.getY() < 0) { - pos = new BlockPos(pos.getX(), 0, pos.getZ()); - } - - if(!isValid(pos)) { - return 0; - } - else if(!this.isBlockLoaded(pos)) { - return 0; - } - else { - Chunk chunk = this.getChunk(pos); - return chunk.getLight(pos); - } - } - - public void setLightFor(BlockPos pos, int lightValue) { + public void setLightFor(LightType type, BlockPos pos, int lightValue) { if(isValid(pos)) { if(this.isBlockLoaded(pos)) { Chunk chunk = this.getChunk(pos); - chunk.setLight(pos, lightValue); + chunk.setLight(type, pos, lightValue); this.notifyLightSet(pos); } } } public int getCombinedLight(BlockPos pos, int lightValue) { - int j = this.getLightFromNeighborsFor(pos); + int i = this.getLightFromNeighborsFor(LightType.SKY, pos); + int j = this.getLightFromNeighborsFor(LightType.BLOCK, pos); if(j < lightValue) { j = lightValue; } - return 15 << 20 | j << 4; + return i << 20 | j << 4; } public float getLightBrightness(BlockPos pos) { @@ -876,30 +935,8 @@ public abstract class World implements IWorldAccess { return f * (float)Math.PI * 2.0F; } - public BlockPos getPrecipitationHeight(BlockPos pos, int y, int scan) { - scan = y - scan; - BlockPos loc = new BlockPos(pos.getX(), y, pos.getZ()); - y = -1; - - while(loc.getY() > 0 && loc.getY() >= scan && y == -1) { - Block block = this.getState(loc).getBlock(); - Material mat = block.getMaterial(); - - if((!mat.blocksMovement() && !mat.isLiquid()) - || (mat == Material.leaves && ((mat = this.getState(loc.up()).getBlock().getMaterial()) == Material.snow) - || mat == Material.leaves)) { - loc = loc.down(); - } - else { - y = loc.getY() + 1; - } - } - - return new BlockPos(pos.getX(), y, pos.getZ()); - } - public BlockPos getPrecipitationHeight(BlockPos pos) { - return this.getPrecipitationHeight(pos, 256, 256); + return this.getChunk(pos).getPrecipitation(pos); } public void updateEntities() { @@ -1472,6 +1509,7 @@ public abstract class World implements IWorldAccess { this.rain = this.weather.hasDownfall() ? 1.0f : 0.0f; this.darkness = this.weather.isDark() ? 1.0f : 0.0f; this.fog = this.weather.getFogIntensity(); + this.temp = this.getBaseTemperature() + this.weather.getTemperature(); } protected void setActivePlayerChunksAndCheckLight(int l) { @@ -1507,48 +1545,121 @@ public abstract class World implements IWorldAccess { // this.profiler.end(); } - public boolean checkLight(BlockPos pos) { - return this.checkLightFor(pos); + public float getTempOffset() { + return this.temp; + } + + protected float getBaseTemperature() { + return this.dimension.getTemperature() + this.dimension.getOrbitOffset() * + ExtMath.sin((((float)(this.daytime % this.dimension.getOrbitalPeriod()) / (float)this.dimension.getOrbitalPeriod()) + -0.125f) * (float)Math.PI * 2.0f); + } + + public LeavesType getLeavesGen(BlockPos pos) { + return this.canFreezeAt(pos) ? LeavesType.SNOWY : ((!this.dimension.getType().days || this.dimension.getOrbitOffset() == 0.0f) ? + this.dimension.getLeavesType() : LeavesType.values()[(int)((this.daytime % + this.dimension.getOrbitalPeriod()) * (long)LeavesType.values().length / this.dimension.getOrbitalPeriod())]); } - private int getRawLight(BlockPos pos) { - Block block = this.getState(pos).getBlock(); - int i = block.getLightValue(); - int j = block.getLightOpacity(); + public float getTemperatureK(BlockPos pos) { + return this.temp + this.getBiomeGenForCoords(pos).getTemperature(pos); + } - if(j >= 15 && block.getLightValue() > 0) { - j = 1; - } + public float getTemperatureC(BlockPos pos) { + return World.ABSOLUTE_ZERO + this.getTemperatureK(pos); + } - if(j < 1) { - j = 1; - } + public boolean canFreezeAt(BlockPos pos) { + return this.getTemperatureC(pos) <= 0.0F; + } - if(j >= 15) { - return 0; + public boolean canBurnAt(BlockPos pos) { + return this.getTemperatureC(pos) >= 194.0f; + } + + public boolean doesWaterVaporize(BlockPos pos) { + return this.getTemperatureC(pos) >= 100.0f; + } + + public boolean isLavaFaster(BlockPos pos) { + return this.getTemperatureC(pos) >= 314.0f; + } + + public boolean canSnowAt(BlockPos pos, boolean checkLight, boolean allowLayers) { + if(!this.canFreezeAt(pos)) { + return false; } - else if(i >= 14) { - return i; + else if(!checkLight) { + return true; } else { - for(Facing enumfacing : Facing.values()) { - BlockPos blockpos = pos.offset(enumfacing); - int k = this.getLightFor(blockpos) - j; + if(pos.getY() >= 0 && pos.getY() < 512 && this.getLightFor(LightType.BLOCK, pos) < 10) { + Block block = this.getState(pos).getBlock(); - if(k > i) { - i = k; - } - - if(i >= 14) { - return i; + if((block.getMaterial() == Material.air || (allowLayers && block == Blocks.snow_layer)) + && Blocks.snow_layer.canPlaceBlockAt(this, pos)) { + return true; } } - return i; + return false; } } - public boolean checkLightFor(BlockPos pos) { + public boolean checkLight(BlockPos pos) { + boolean flag = false; + + if(!this.dimension.hasNoLight()) { + flag |= this.checkLightFor(LightType.SKY, pos); + } + + flag = flag | this.checkLightFor(LightType.BLOCK, pos); + return flag; + } + + private int getRawLight(BlockPos pos, LightType lightType) { + if(lightType == LightType.SKY && this.canSeeSky(pos)) { + return 15; + } + else { + Block block = this.getState(pos).getBlock(); + int i = lightType == LightType.SKY ? 0 : block.getLightValue(); + int j = block.getLightOpacity(); + + if(j >= 15 && block.getLightValue() > 0) { + j = 1; + } + + if(j < 1) { + j = 1; + } + + if(j >= 15) { + return 0; + } + else if(i >= 14) { + return i; + } + else { + for(Facing enumfacing : Facing.values()) { + BlockPos blockpos = pos.offset(enumfacing); + int k = this.getLightFor(lightType, blockpos) - j; + + if(k > i) { + i = k; + } + + if(i >= 14) { + return i; + } + } + + return i; + } + } + } + + public boolean checkLightFor(LightType lightType, BlockPos pos) { if(!this.isAreaLoaded(pos, 17, false)) { return false; } @@ -1556,8 +1667,8 @@ public abstract class World implements IWorldAccess { int i = 0; int j = 0; // this.profiler.start("getBrightness"); - int k = this.getLightFor(pos); - int l = this.getRawLight(pos); + int k = this.getLightFor(lightType, pos); + int l = this.getRawLight(pos, lightType); int i1 = pos.getX(); int j1 = pos.getY(); int k1 = pos.getZ(); @@ -1575,10 +1686,10 @@ public abstract class World implements IWorldAccess { int k2 = (l1 >> 12 & 63) - 32 + k1; int l2 = l1 >> 18 & 15; BlockPos blockpos = new BlockPos(i2, j2, k2); - int i3 = this.getLightFor(blockpos); + int i3 = this.getLightFor(lightType, blockpos); if(i3 == l2) { - this.setLightFor(blockpos, 0); + this.setLightFor(lightType, blockpos, 0); if(l2 > 0) { int j3 = ExtMath.absi(i2 - i1); @@ -1594,7 +1705,7 @@ public abstract class World implements IWorldAccess { int k4 = k2 + enumfacing.getFrontOffsetZ(); blockpos$mutableblockpos.set(i4, j4, k4); int l4 = Math.max(1, this.getState(blockpos$mutableblockpos).getBlock().getLightOpacity()); - i3 = this.getLightFor(blockpos$mutableblockpos); + i3 = this.getLightFor(lightType, blockpos$mutableblockpos); if(i3 == l2 - l4 && j < this.lightUpdate.length) { this.lightUpdate[j++] = i4 - i1 + 32 | j4 - j1 + 32 << 6 | k4 - k1 + 32 << 12 | l2 - l4 << 18; @@ -1617,11 +1728,11 @@ public abstract class World implements IWorldAccess { int k5 = (i5 >> 6 & 63) - 32 + j1; int l5 = (i5 >> 12 & 63) - 32 + k1; BlockPos blockpos1 = new BlockPos(j5, k5, l5); - int i6 = this.getLightFor(blockpos1); - int j6 = this.getRawLight(blockpos1); + int i6 = this.getLightFor(lightType, blockpos1); + int j6 = this.getRawLight(blockpos1, lightType); if(j6 != i6) { - this.setLightFor(blockpos1, j6); + this.setLightFor(lightType, blockpos1, j6); if(j6 > i6) { int k6 = Math.abs(j5 - i1); @@ -1630,27 +1741,27 @@ public abstract class World implements IWorldAccess { boolean flag = j < this.lightUpdate.length - 6; if(k6 + l6 + i7 < 17 && flag) { - if(this.getLightFor(blockpos1.west()) < j6) { + if(this.getLightFor(lightType, blockpos1.west()) < j6) { this.lightUpdate[j++] = j5 - 1 - i1 + 32 + (k5 - j1 + 32 << 6) + (l5 - k1 + 32 << 12); } - if(this.getLightFor(blockpos1.east()) < j6) { + if(this.getLightFor(lightType, blockpos1.east()) < j6) { this.lightUpdate[j++] = j5 + 1 - i1 + 32 + (k5 - j1 + 32 << 6) + (l5 - k1 + 32 << 12); } - if(this.getLightFor(blockpos1.down()) < j6) { + if(this.getLightFor(lightType, blockpos1.down()) < j6) { this.lightUpdate[j++] = j5 - i1 + 32 + (k5 - 1 - j1 + 32 << 6) + (l5 - k1 + 32 << 12); } - if(this.getLightFor(blockpos1.up()) < j6) { + if(this.getLightFor(lightType, blockpos1.up()) < j6) { this.lightUpdate[j++] = j5 - i1 + 32 + (k5 + 1 - j1 + 32 << 6) + (l5 - k1 + 32 << 12); } - if(this.getLightFor(blockpos1.north()) < j6) { + if(this.getLightFor(lightType, blockpos1.north()) < j6) { this.lightUpdate[j++] = j5 - i1 + 32 + (k5 - j1 + 32 << 6) + (l5 - 1 - k1 + 32 << 12); } - if(this.getLightFor(blockpos1.south()) < j6) { + if(this.getLightFor(lightType, blockpos1.south()) < j6) { this.lightUpdate[j++] = j5 - i1 + 32 + (k5 - j1 + 32 << 6) + (l5 + 1 - k1 + 32 << 12); } } @@ -1928,7 +2039,11 @@ public abstract class World implements IWorldAccess { public void setFogStrength(float strength) { this.fog = strength; } - + + public void setTemperature(float temp) { + this.temp = temp; + } + public boolean isDark() { return this.darkness > 0.9f; } @@ -1945,6 +2060,23 @@ public abstract class World implements IWorldAccess { return this.hasDownfall() && this.weather.canRain(); } + public boolean isRainingAt(BlockPos strikePosition, boolean wet) { + if(wet ? !this.isRaining() : !this.hasDownfall()) { + return false; + } + else if(!this.canSeeSky(strikePosition)) { + return false; + } + else if(this.getPrecipitationHeight(strikePosition).getY() > strikePosition.getY()) { + return false; + } + return !this.canSnowAt(strikePosition, false, false); +// else { +// Biome biomegenbase = this.getBiomeGenForCoords(strikePosition); +// return biomegenbase.isSnowyBiome() ? false : ( ? false : biomegenbase.canRain()); +// } + } + // public void setItemData(String dataID, WorldSavedData worldSavedDataIn) { // } // diff --git a/server/src/server/worldgen/BiomeGenerator.java b/common/src/common/worldgen/BiomeGenerator.java similarity index 96% rename from server/src/server/worldgen/BiomeGenerator.java rename to common/src/common/worldgen/BiomeGenerator.java index 6d75568..b6ef4e9 100755 --- a/server/src/server/worldgen/BiomeGenerator.java +++ b/common/src/common/worldgen/BiomeGenerator.java @@ -1,4 +1,4 @@ -package server.worldgen; +package common.worldgen; import java.util.Set; diff --git a/server/src/server/Server.java b/server/src/server/Server.java index b05cff8..8f54ba4 100755 --- a/server/src/server/Server.java +++ b/server/src/server/Server.java @@ -1174,6 +1174,7 @@ public final class Server implements IThreadListener { conn.sendPacket(new S2BPacketChangeGameState(S2BPacketChangeGameState.Action.RAIN_STRENGTH, world.getRainStrength())); conn.sendPacket(new S2BPacketChangeGameState(S2BPacketChangeGameState.Action.DARKNESS, world.getDarkness())); conn.sendPacket(new S2BPacketChangeGameState(S2BPacketChangeGameState.Action.FOG_STRENGTH, world.getFogStrength())); + conn.sendPacket(new S2BPacketChangeGameState(S2BPacketChangeGameState.Action.TEMPERATURE, world.getTempOffset())); } public void syncPlayerInventory(EntityNPC player) { diff --git a/server/src/server/biome/BiomeChaos.java b/server/src/server/biome/BiomeChaos.java index 07444af..0bd3c45 100755 --- a/server/src/server/biome/BiomeChaos.java +++ b/server/src/server/biome/BiomeChaos.java @@ -38,7 +38,7 @@ public class BiomeChaos extends GenBiome { int i8 = rand.chOffset(); int l11 = rand.chOffset(); - BlockPos blockpos2 = worldIn.getPrecipitationHeight(pos.add(i8, 0, l11)); + BlockPos blockpos2 = worldIn.getHeight(pos.add(i8, 0, l11)); this.mushroomBlueGen.generate(worldIn, rand, blockpos2); } } diff --git a/server/src/server/biome/BiomeDesert.java b/server/src/server/biome/BiomeDesert.java index 079692e..0171ff5 100755 --- a/server/src/server/biome/BiomeDesert.java +++ b/server/src/server/biome/BiomeDesert.java @@ -33,7 +33,7 @@ public class BiomeDesert extends GenBiome { int i = rand.chOffset(); int j = rand.chOffset(); - BlockPos blockpos = worldIn.getPrecipitationHeight(pos.add(i, 0, j)).up(); + BlockPos blockpos = worldIn.getHeight(pos.add(i, 0, j)).up(); (new WorldGenDesertWells()).generate(worldIn, rand, blockpos); } } diff --git a/server/src/server/biome/BiomeForest.java b/server/src/server/biome/BiomeForest.java index f6a5ecc..c0ecc14 100755 --- a/server/src/server/biome/BiomeForest.java +++ b/server/src/server/biome/BiomeForest.java @@ -134,7 +134,7 @@ public class BiomeForest extends GenBiome { int k = i * 4 + rand.range(9, 11); int l = j * 4 + rand.range(9, 11); - BlockPos blockpos = worldIn.getPrecipitationHeight(pos.add(k, 0, l)); + BlockPos blockpos = worldIn.getHeight(pos.add(k, 0, l)); if (rand.chance(20)) { @@ -183,7 +183,7 @@ public class BiomeForest extends GenBiome { int j2 = rand.chOffset(); int k2 = rand.chOffset(); - int i1 = rand.zrange(worldIn.getPrecipitationHeight(pos.add(j2, 0, k2)).getY() + 32); + int i1 = rand.zrange(worldIn.getHeight(pos.add(j2, 0, k2)).getY() + 32); if (DOUBLE_PLANT_GEN.generate(worldIn, rand, new BlockPos(pos.getX() + j2, i1, pos.getZ() + k2))) { diff --git a/server/src/server/biome/BiomeJungle.java b/server/src/server/biome/BiomeJungle.java index 8431daa..e871913 100755 --- a/server/src/server/biome/BiomeJungle.java +++ b/server/src/server/biome/BiomeJungle.java @@ -69,7 +69,7 @@ public class BiomeJungle extends GenBiome super.decorate(worldIn, rand, pos); int i = rand.chOffset(); int j = rand.chOffset(); - int k = rand.zrange(worldIn.getPrecipitationHeight(pos.add(i, 0, j)).getY() * 2); + int k = rand.zrange(worldIn.getHeight(pos.add(i, 0, j)).getY() * 2); (new WorldGenMelon()).generate(worldIn, rand, pos.add(i, k, j)); WorldGenVines worldgenvines = new WorldGenVines(); diff --git a/server/src/server/biome/BiomePlains.java b/server/src/server/biome/BiomePlains.java index 45ce1f0..2732ac8 100755 --- a/server/src/server/biome/BiomePlains.java +++ b/server/src/server/biome/BiomePlains.java @@ -87,7 +87,7 @@ public class BiomePlains extends GenBiome { int j = rand.chOffset(); int k = rand.chOffset(); - int l = rand.zrange(worldIn.getPrecipitationHeight(pos.add(j, 0, k)).getY() + 32); + int l = rand.zrange(worldIn.getHeight(pos.add(j, 0, k)).getY() + 32); DOUBLE_PLANT_GEN.generate(worldIn, rand, pos.add(j, l, k)); } } @@ -101,7 +101,7 @@ public class BiomePlains extends GenBiome // { int j1 = rand.chOffset(); int k1 = rand.chOffset(); - int l1 = rand.zrange(worldIn.getPrecipitationHeight(pos.add(j1, 0, k1)).getY() + 32); + int l1 = rand.zrange(worldIn.getHeight(pos.add(j1, 0, k1)).getY() + 32); DOUBLE_PLANT_GEN.generate(worldIn, rand, pos.add(j1, l1, k1)); // } } diff --git a/server/src/server/biome/BiomeSavanna.java b/server/src/server/biome/BiomeSavanna.java index c8b3776..1063529 100755 --- a/server/src/server/biome/BiomeSavanna.java +++ b/server/src/server/biome/BiomeSavanna.java @@ -46,7 +46,7 @@ public class BiomeSavanna extends GenBiome { int j = rand.chOffset(); int k = rand.chOffset(); - int l = rand.zrange(worldIn.getPrecipitationHeight(pos.add(j, 0, k)).getY() + 32); + int l = rand.zrange(worldIn.getHeight(pos.add(j, 0, k)).getY() + 32); DOUBLE_PLANT_GEN.generate(worldIn, rand, pos.add(j, l, k)); } diff --git a/server/src/server/biome/BiomeSnow.java b/server/src/server/biome/BiomeSnow.java index e3e1d94..ea236f2 100755 --- a/server/src/server/biome/BiomeSnow.java +++ b/server/src/server/biome/BiomeSnow.java @@ -36,14 +36,14 @@ public class BiomeSnow extends GenBiome { int j = rand.chOffset(); int k = rand.chOffset(); - this.spikeGen.generate(worldIn, rand, worldIn.getPrecipitationHeight(pos.add(j, 0, k))); + this.spikeGen.generate(worldIn, rand, worldIn.getHeight(pos.add(j, 0, k))); } for (int l = 0; l < 2; ++l) { int i1 = rand.chOffset(); int j1 = rand.chOffset(); - this.pathGen.generate(worldIn, rand, worldIn.getPrecipitationHeight(pos.add(i1, 0, j1))); + this.pathGen.generate(worldIn, rand, worldIn.getHeight(pos.add(i1, 0, j1))); } } diff --git a/server/src/server/biome/BiomeTaiga.java b/server/src/server/biome/BiomeTaiga.java index 4d9fbc6..d7a9c5f 100755 --- a/server/src/server/biome/BiomeTaiga.java +++ b/server/src/server/biome/BiomeTaiga.java @@ -70,7 +70,7 @@ public class BiomeTaiga extends GenBiome { int k = rand.chOffset(); int l = rand.chOffset(); - BlockPos blockpos = worldIn.getPrecipitationHeight(pos.add(k, 0, l)); + BlockPos blockpos = worldIn.getHeight(pos.add(k, 0, l)); field_150643_aG.generate(worldIn, rand, blockpos); } } @@ -81,7 +81,7 @@ public class BiomeTaiga extends GenBiome { int j1 = rand.chOffset(); int k1 = rand.chOffset(); - int l1 = rand.zrange(worldIn.getPrecipitationHeight(pos.add(j1, 0, k1)).getY() + 32); + int l1 = rand.zrange(worldIn.getHeight(pos.add(j1, 0, k1)).getY() + 32); DOUBLE_PLANT_GEN.generate(worldIn, rand, pos.add(j1, l1, k1)); } diff --git a/server/src/server/biome/BiomeTian.java b/server/src/server/biome/BiomeTian.java index 5f05ad9..58c7d45 100755 --- a/server/src/server/biome/BiomeTian.java +++ b/server/src/server/biome/BiomeTian.java @@ -68,7 +68,7 @@ public class BiomeTian extends GenBiome { int i8 = rand.chOffset(); int l11 = rand.chOffset(); - BlockPos blockpos2 = worldIn.getPrecipitationHeight(pos.add(i8, 0, l11)); + BlockPos blockpos2 = worldIn.getHeight(pos.add(i8, 0, l11)); this.mushroomBlueGen.generate(worldIn, rand, blockpos2); } } diff --git a/server/src/server/biome/GenBiome.java b/server/src/server/biome/GenBiome.java index f87a088..825b630 100755 --- a/server/src/server/biome/GenBiome.java +++ b/server/src/server/biome/GenBiome.java @@ -340,7 +340,7 @@ public abstract class GenBiome implements IBiome { int l = rand.chOffset(); WorldGenTree treeGen = this.genBigTreeChance(rand); treeGen.prepare(); - BlockPos blockpos = world.getPrecipitationHeight(pos.add(k6, 0, l)); + BlockPos blockpos = world.getHeight(pos.add(k6, 0, l)); if (treeGen.generate(world, rand, blockpos)) { @@ -352,14 +352,14 @@ public abstract class GenBiome implements IBiome { { int l6 = rand.chOffset(); int k10 = rand.chOffset(); - this.bigMushroomGen.generate(world, rand, world.getPrecipitationHeight(pos.add(l6, 0, k10))); + this.bigMushroomGen.generate(world, rand, world.getHeight(pos.add(l6, 0, k10))); } for (int l2 = 0; l2 < this.flowersPerChunk; ++l2) { int i7 = rand.chOffset(); int l10 = rand.chOffset(); - int j14 = world.getPrecipitationHeight(pos.add(i7, 0, l10)).getY() + 32; + int j14 = world.getHeight(pos.add(i7, 0, l10)).getY() + 32; if (j14 > 0) { @@ -380,7 +380,7 @@ public abstract class GenBiome implements IBiome { { int j7 = rand.chOffset(); int i11 = rand.chOffset(); - int k14 = world.getPrecipitationHeight(pos.add(j7, 0, i11)).getY() * 2; + int k14 = world.getHeight(pos.add(j7, 0, i11)).getY() * 2; if (k14 > 0) { @@ -393,7 +393,7 @@ public abstract class GenBiome implements IBiome { { int k7 = rand.chOffset(); int j11 = rand.chOffset(); - int l14 = world.getPrecipitationHeight(pos.add(k7, 0, j11)).getY() * 2; + int l14 = world.getHeight(pos.add(k7, 0, j11)).getY() * 2; if (l14 > 0) { @@ -406,7 +406,7 @@ public abstract class GenBiome implements IBiome { { int l7 = rand.chOffset(); int k11 = rand.chOffset(); - int i15 = world.getPrecipitationHeight(pos.add(l7, 0, k11)).getY() * 2; + int i15 = world.getHeight(pos.add(l7, 0, k11)).getY() * 2; if (i15 > 0) { @@ -434,7 +434,7 @@ public abstract class GenBiome implements IBiome { { int i8 = rand.chOffset(); int l11 = rand.chOffset(); - BlockPos blockpos2 = world.getPrecipitationHeight(pos.add(i8, 0, l11)); + BlockPos blockpos2 = world.getHeight(pos.add(i8, 0, l11)); this.mushroomBrownGen.generate(world, rand, blockpos2); } @@ -442,7 +442,7 @@ public abstract class GenBiome implements IBiome { { int j8 = rand.chOffset(); int i12 = rand.chOffset(); - int j15 = world.getPrecipitationHeight(pos.add(j8, 0, i12)).getY() * 2; + int j15 = world.getHeight(pos.add(j8, 0, i12)).getY() * 2; if (j15 > 0) { @@ -457,7 +457,7 @@ public abstract class GenBiome implements IBiome { { int i4 = rand.chOffset(); int k8 = rand.chOffset(); - int j12 = world.getPrecipitationHeight(pos.add(i4, 0, k8)).getY() * 2; + int j12 = world.getHeight(pos.add(i4, 0, k8)).getY() * 2; if (j12 > 0) { @@ -470,7 +470,7 @@ public abstract class GenBiome implements IBiome { { int j4 = rand.chOffset(); int l8 = rand.chOffset(); - int k12 = world.getPrecipitationHeight(pos.add(j4, 0, l8)).getY() * 2; + int k12 = world.getHeight(pos.add(j4, 0, l8)).getY() * 2; if (k12 > 0) { @@ -483,7 +483,7 @@ public abstract class GenBiome implements IBiome { { int i9 = rand.chOffset(); int l12 = rand.chOffset(); - int i16 = world.getPrecipitationHeight(pos.add(i9, 0, l12)).getY() * 2; + int i16 = world.getHeight(pos.add(i9, 0, l12)).getY() * 2; if (i16 > 0) { @@ -496,7 +496,7 @@ public abstract class GenBiome implements IBiome { { int j9 = rand.chOffset(); int i13 = rand.chOffset(); - int j16 = world.getPrecipitationHeight(pos.add(j9, 0, i13)).getY() * 2; + int j16 = world.getHeight(pos.add(j9, 0, i13)).getY() * 2; if (j16 > 0) { @@ -509,7 +509,7 @@ public abstract class GenBiome implements IBiome { { int i5 = rand.chOffset(); int k9 = rand.chOffset(); - int j13 = world.getPrecipitationHeight(pos.add(i5, 0, k9)).getY() * 2; + int j13 = world.getHeight(pos.add(i5, 0, k9)).getY() * 2; if (j13 > 0) { @@ -522,7 +522,7 @@ public abstract class GenBiome implements IBiome { { int l9 = rand.chOffset(); int k13 = rand.chOffset(); - int l16 = world.getPrecipitationHeight(pos.add(l9, 0, k13)).getY() * 2; + int l16 = world.getHeight(pos.add(l9, 0, k13)).getY() * 2; if (l16 > 0) { diff --git a/server/src/server/network/Player.java b/server/src/server/network/Player.java index b5cbd23..f42a452 100755 --- a/server/src/server/network/Player.java +++ b/server/src/server/network/Player.java @@ -254,7 +254,7 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer this.sendPacket(new SPacketKeepAlive(this.pingKey)); } if(this.admin && this.profiling) - this.sendPacket(new SPacketServerTick((int)this.server.getLastTick(), this.getTickInfo())); + this.sendPacket(new SPacketServerTick((int)this.server.getLastTick())); if(this.respawnTimer > 0) { if(--this.respawnTimer == 0) { this.respawnPlayer(); @@ -262,18 +262,6 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer } } - private String getTickInfo() { - if(this.charEditor || this.entity == null) - return ""; - WorldServer world = this.getEntityWorld(); - BlockPos pos = this.entity.getPosition(); - return String.format("Temperatur: %.2f K / %.2f °C, L: %s%s", - world.getTemperatureK(pos), world.getTemperatureC(pos), - !world.dimension.getType().days ? "*" : "", - world.getLeavesGen(pos).getDisplayName() - ); - } - public void displayLoading(String message) { this.sendPacket(new SPacketLoading(message)); } diff --git a/server/src/server/village/VillageCollection.java b/server/src/server/village/VillageCollection.java index 4730732..53ad125 100755 --- a/server/src/server/village/VillageCollection.java +++ b/server/src/server/village/VillageCollection.java @@ -215,16 +215,15 @@ public class VillageCollection for (int j = 1; j <= 5; ++j) { - BlockPos pos = centerPos.offset(direction, j); - for(int z = 0; z < 5; z++) { - if(!world.isAirBlock(pos.up(z))) - break; - if(z == 4) { - ++i; - if(i >= limitation) - return i; + if (world.canSeeSky(centerPos.offset(direction, j))) + { + ++i; + + if (i >= limitation) + { + return i; } - } + } } return i; diff --git a/server/src/server/world/Region.java b/server/src/server/world/Region.java index 573f860..fcf1367 100755 --- a/server/src/server/world/Region.java +++ b/server/src/server/world/Region.java @@ -370,16 +370,19 @@ public class Region { return null; } Chunk chunk = new Chunk(world, x, z); + chunk.setHeights(tag.getIntArray("HeightMap")); chunk.setTerrainPopulated(tag.getBoolean("TerrainPopulated")); + chunk.setLightPopulated(tag.getBoolean("LightPopulated")); chunk.setInhabited(tag.getLong("InhabitedTime")); NBTTagList sects = tag.getTagList("Sections", 10); int stor = 32; BlockArray[] sections = new BlockArray[stor]; - + boolean light = !world.dimension.hasNoLight(); + for(int n = 0; n < sects.tagCount(); ++n) { NBTTagCompound sect = sects.getCompoundTagAt(n); int y = sect.getByte("Y"); - BlockArray storage = new BlockArray(y << 4); + BlockArray storage = new BlockArray(y << 4, light); byte[] blocks = sect.getByteArray("Blocks"); NibbleArray data = new NibbleArray(sect.getByteArray("Data")); NibbleArray adddata = sect.hasKey("Add", 7) ? new NibbleArray(sect.getByteArray("Add")) : null; @@ -395,13 +398,21 @@ public class Region { storage.setData(seg); storage.setBlocklight(new NibbleArray(sect.getByteArray("BlockLight"))); - + + if(light) { + storage.setSkylight(new NibbleArray(sect.getByteArray("SkyLight"))); + } + storage.update(); sections[y] = storage; } chunk.setStorage(sections); + if(tag.hasKey("Biomes", 7)) { + chunk.setBiomes(tag.getByteArray("Biomes")); + } + NBTTagList entities = tag.getTagList("Entities", 10); if(entities != null) { @@ -479,7 +490,9 @@ public class Region { NBTTagCompound tag = new NBTTagCompound(); // tag.setShort("V", (short)Config.PROTOCOL); tag.setLong("LastUpdate", world.getTime()); + tag.setIntArray("HeightMap", chunk.getHeights()); tag.setBoolean("TerrainPopulated", chunk.isTerrainPopulated()); + tag.setBoolean("LightPopulated", chunk.isLightPopulated()); tag.setLong("InhabitedTime", chunk.getInhabited()); BlockArray[] sections = chunk.getStorage(); NBTTagList sects = new NBTTagList(); @@ -519,12 +532,20 @@ public class Region { } sect.setByteArray("BlockLight", storage.getBlocklight().getData()); - + + if(light) { + sect.setByteArray("SkyLight", storage.getSkylight().getData()); + } + else { + sect.setByteArray("SkyLight", new byte[storage.getBlocklight().getData().length]); + } + sects.appendTag(sect); } } tag.setTag("Sections", sects); + tag.setByteArray("Biomes", chunk.getBiomes()); chunk.setHasEntities(false); NBTTagList entities = new NBTTagList(); diff --git a/server/src/server/world/Spawner.java b/server/src/server/world/Spawner.java index 02f27ff..5133cf3 100755 --- a/server/src/server/world/Spawner.java +++ b/server/src/server/world/Spawner.java @@ -14,6 +14,7 @@ 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; @@ -86,14 +87,15 @@ public abstract class Spawner { if(cur <= max) { typeLabel: for(ChunkPos coord : CHUNKS) { + Chunk 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 = world.getPrecipitationHeight(new BlockPos(x, 0, z)).getY() + 1; + int h = chunk.getHeight(new BlockPos(x, 0, z)) + 1; if(h > 0) { int m = h % 16; h = m == 0 ? h : h + 16 - m; } - h = h <= 0 ? 16 : h; + h = h == 0 ? 16 : (h > 0 ? h : chunk.getTopSegment() + 16 - 1); int y = world.rand.excl(h <= 8 ? 0 : 8, h); BlockPos pos = new BlockPos(x, y, z); Block block = world.getState(pos).getBlock(); diff --git a/server/src/server/world/WorldServer.java b/server/src/server/world/WorldServer.java index 53461a0..84c1cf1 100755 --- a/server/src/server/world/WorldServer.java +++ b/server/src/server/world/WorldServer.java @@ -20,7 +20,6 @@ import common.block.BlockEventData; import common.block.BlockFalling; import common.block.BlockLiquid; import common.block.BlockSnow; -import common.block.LeavesType; import common.collect.Lists; import common.collect.Maps; import common.collect.Sets; @@ -52,6 +51,7 @@ import common.packet.S29PacketSoundEffect; import common.packet.S2APacketParticles; import common.packet.S2BPacketChangeGameState; import common.packet.S2CPacketSpawnGlobalEntity; +import common.packet.SPacketBiomes; import common.packet.SPacketBlockAction; import common.packet.SPacketBlockBreakAnim; import common.packet.SPacketBlockChange; @@ -66,6 +66,7 @@ import common.util.ChunkPos; import common.util.ExtMath; import common.util.FileUtils; import common.util.IntHashMap; +import common.util.LongHashMap; import common.util.NextTickListEntry; import common.util.PortalType; import common.util.Position; @@ -75,9 +76,11 @@ 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; @@ -90,7 +93,6 @@ 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; @@ -129,15 +131,15 @@ public final class WorldServer extends AWorldServer { private final TreeSet ticksNext = new TreeSet(); 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 Map chunks = Maps.newHashMap(); + private final Set dropped = Collections.newSetFromMap(new ConcurrentHashMap()); + 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 Map loaders = Maps.newHashMap(); + private final LongHashMap loaders = new LongHashMap(); private final Set loaderList = Sets.newHashSet(); private final List managed = Lists.newArrayList(); - private final Map instances = Maps.newHashMap(); + private final LongHashMap instances = new LongHashMap(); private final List toUpdate = Lists.newArrayList(); private final List instList = Lists.newArrayList(); private final Set tracked = Sets.newHashSet(); @@ -177,7 +179,6 @@ public final class WorldServer extends AWorldServer { private boolean loadersModified; // private boolean warpsModified; private boolean exterminated; - private float temp; private int emptyTicks; private int blockEvtIdx; private int trackDistance; @@ -512,12 +513,12 @@ public final class WorldServer extends AWorldServer { if(!this.debug) { for(int i = 0; i < 100; ++i) { if(!this.dropped.isEmpty()) { - ChunkPos v = this.dropped.iterator().next(); - Chunk chunk = this.chunks.get(v); + Long v = (Long)this.dropped.iterator().next(); + Chunk chunk = (Chunk)this.chunks.getValueByKey(v.longValue()); if(chunk != null) { chunk.onChunkUnload(); this.saveChunkData(chunk); - this.chunks.remove(v); + this.chunks.remove(v.longValue()); this.loaded.remove(chunk); } this.dropped.remove(v); @@ -570,10 +571,10 @@ public final class WorldServer extends AWorldServer { } public boolean addLoader(BlockPos pos) { - ChunkPos chunk = new ChunkPos(pos.getX() / 16, pos.getZ() / 16); - if(this.loaders.containsKey(chunk)) + long chunk = LongHashMap.packInt(pos.getX() / 16, pos.getZ() / 16); + if(this.loaders.containsItem(chunk)) return false; - this.loaders.put(chunk, pos); + this.loaders.add(chunk, pos); this.loaderList.add(pos); this.loadersModified = true; return true; @@ -584,8 +585,8 @@ public final class WorldServer extends AWorldServer { // } public boolean removeLoader(BlockPos pos) { - ChunkPos chunk = new ChunkPos(pos.getX() / 16, pos.getZ() / 16); - BlockPos loader = this.loaders.get(chunk); + long chunk = LongHashMap.packInt(pos.getX() / 16, pos.getZ() / 16); + BlockPos loader = this.loaders.getValueByKey(chunk); if(!pos.equals(loader)) return false; this.loaders.remove(chunk); @@ -622,84 +623,11 @@ public final class WorldServer extends AWorldServer { return this.biomeGen; } - public Biome getBiomeGenForCoords(BlockPos pos) { - return this.biomeGen.getBiomeGenerator(pos, Biome.DEF_BIOME); - } - - protected void calculateInitialWeather() { - super.calculateInitialWeather(); - this.temp = this.getBaseTemperature() + this.weather.getTemperature(); - } - - public float getTempOffset() { - return this.temp; - } - - protected float getBaseTemperature() { - return this.dimension.getTemperature() + this.dimension.getOrbitOffset() * - ExtMath.sin((((float)(this.daytime % this.dimension.getOrbitalPeriod()) / (float)this.dimension.getOrbitalPeriod()) - -0.125f) * (float)Math.PI * 2.0f); - } - - public LeavesType getLeavesGen(BlockPos pos) { - return this.canFreezeAt(pos) ? LeavesType.SNOWY : ((!this.dimension.getType().days || this.dimension.getOrbitOffset() == 0.0f) ? - this.dimension.getLeavesType() : LeavesType.values()[(int)((this.daytime % - this.dimension.getOrbitalPeriod()) * (long)LeavesType.values().length / this.dimension.getOrbitalPeriod())]); - } - - public float getTemperatureK(BlockPos pos) { - return this.temp + this.getBiomeGenForCoords(pos).getTemperature(pos); - } - - public float getTemperatureC(BlockPos pos) { - return World.ABSOLUTE_ZERO + this.getTemperatureK(pos); - } - - public boolean canFreezeAt(BlockPos pos) { - return this.getTemperatureC(pos) <= 0.0F; - } - - public boolean canBurnAt(BlockPos pos) { - return this.getTemperatureC(pos) >= 194.0f; - } - - public boolean doesWaterVaporize(BlockPos pos) { - return this.getTemperatureC(pos) >= 100.0f; - } - - public boolean isLavaFaster(BlockPos pos) { - return this.getTemperatureC(pos) >= 314.0f; - } - - public boolean canSnowAt(BlockPos pos, boolean checkLight, boolean allowLayers) { - if(!this.canFreezeAt(pos)) { - return false; - } - else if(!checkLight) { - return true; - } - else { - if(pos.getY() >= 0 && pos.getY() < 512 && this.getLightFor(pos) < 10) { - Block block = this.getState(pos).getBlock(); - - if((block.getMaterial() == Material.air || (allowLayers && block == Blocks.snow_layer)) - && Blocks.snow_layer.canPlaceBlockAt(this, pos)) { - return true; - } - } - - return false; - } - } - - public boolean isRainingAt(BlockPos strikePosition, boolean wet) { - if(wet ? !this.isRaining() : !this.hasDownfall()) { - return false; - } - else if(this.getPrecipitationHeight(strikePosition, strikePosition.getY() + 46, 48).getY() > strikePosition.getY()) { - return false; - } - return !this.canSnowAt(strikePosition, false, false); + public Biome getBiomeGenForCoords(final BlockPos pos) { + if(this.isBlockLoaded(pos)) + return this.getChunk(pos).getBiome(pos, this.biomeGen); + else + return this.biomeGen.getBiomeGenerator(pos, Biome.DEF_BIOME); } public void setItemData(String dataID, WorldSavedData worldSavedDataIn) { @@ -716,7 +644,7 @@ public final class WorldServer extends AWorldServer { if(this.debug) { for(ChunkPos chunkcoordintpair1 : this.active) { - this.getChunk(chunkcoordintpair1.x, chunkcoordintpair1.z).update(); + this.getChunk(chunkcoordintpair1.x, chunkcoordintpair1.z).update(false); } } else { @@ -733,7 +661,7 @@ public final class WorldServer extends AWorldServer { // this.profiler.next("checkLight"); chunk.enqueueRelight(); // this.profiler.next("tickChunk"); - chunk.update(); + chunk.update(false); // this.profiler.next("thunder"); int l2 = Config.boltChance; @@ -817,7 +745,7 @@ public final class WorldServer extends AWorldServer { 3.0D, 3.0D); List list = this.getEntitiesWithinAABB(EntityLiving.class, axisalignedbb, new Predicate() { public boolean test(EntityLiving p_apply_1_) { - return p_apply_1_ != null && p_apply_1_.isEntityAlive() && p_apply_1_.getPosition().getY() >= blockpos.getY(); + return p_apply_1_ != null && p_apply_1_.isEntityAlive() && WorldServer.this.canSeeSky(p_apply_1_.getPosition()); } }); return !list.isEmpty() ? ((EntityLiving)list.get(this.rand.zrange(list.size()))).getPosition() : blockpos; @@ -1361,6 +1289,10 @@ public final class WorldServer extends AWorldServer { else if(this.temp > temp) { this.temp = Math.max((float)((double)this.temp - 0.01D), temp); } + + if(prevTemp != this.temp || force) { + this.server.sendPacket(new S2BPacketChangeGameState(S2BPacketChangeGameState.Action.TEMPERATURE, this.temp), this.dimension.getDimensionId()); + } } // if(this.resetWeather) @@ -1394,18 +1326,18 @@ public final class WorldServer extends AWorldServer { } public Chunk getChunk(int x, int z) { - Chunk chunk = this.chunks.get(new ChunkPos(x, z)); + Chunk chunk = this.chunks.getValueByKey(LongHashMap.packInt(x, z)); return chunk == null ? this.loadChunk(x, z) : chunk; } private boolean chunkExists(int x, int z) { - return this.chunks.containsKey(new ChunkPos(x, z)); + return this.chunks.containsItem(LongHashMap.packInt(x, z)); } public void dropChunk(int x, int z) { - ChunkPos chunk = new ChunkPos(x, z); - if(!this.loaders.containsKey(chunk)) - this.dropped.add(chunk); + long chunk = LongHashMap.packInt(x, z); + if(!this.loaders.containsItem(chunk)) + this.dropped.add(Long.valueOf(chunk)); } public void loadForcedChunks() { @@ -1421,9 +1353,9 @@ public final class WorldServer extends AWorldServer { } public Chunk loadChunk(int x, int z) { - ChunkPos id = new ChunkPos(x, z); - this.dropped.remove(id); - Chunk chunk = this.chunks.get(id); + long id = LongHashMap.packInt(x, z); + this.dropped.remove(Long.valueOf(id)); + Chunk chunk = (Chunk)this.chunks.getValueByKey(id); if(chunk == null) { if(!this.debug) @@ -1433,7 +1365,7 @@ public final class WorldServer extends AWorldServer { chunk = this.generate(x, z); } - this.chunks.put(id, chunk); + this.chunks.add(id, chunk); this.loaded.add(chunk); chunk.onChunkLoad(); this.popChunk(x, z); @@ -1600,7 +1532,7 @@ public final class WorldServer extends AWorldServer { private void populate(int x, int z) { Chunk chunk = this.getChunk(x, z); if(!chunk.isTerrainPopulated()) { - chunk.setTerrainPopulated(true); + chunk.checkLight(); BlockFalling.fallInstantly = true; int bx = x * 16; int bz = z * 16; @@ -1703,7 +1635,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, x, z); + return new Chunk(this, primer.getData(), primer.height, this.base, this.ceil, this.grng, this.biomes, x, z); } public boolean isExterminated() { @@ -1721,7 +1653,7 @@ public final class WorldServer extends AWorldServer { if(!this.loaderList.isEmpty()) this.loadersModified = true; for(BlockPos pos : this.loaderList) { - this.loaders.remove(new ChunkPos(pos.getX() / 16, pos.getZ() / 16)); + this.loaders.remove(LongHashMap.packInt(pos.getX() / 16, pos.getZ() / 16)); } this.loaderList.clear(); for(Iterator> iter = this.server.getWarps().entrySet().iterator(); iter.hasNext();) { @@ -1737,11 +1669,11 @@ public final class WorldServer extends AWorldServer { })); this.exterminated = true; // this.dataModified = true; - for(ChunkPos v : this.dropped) { - Chunk chunk = this.chunks.get(v); + for(Long v : this.dropped) { + Chunk chunk = this.chunks.getValueByKey(v.longValue()); if(chunk != null) { chunk.onChunkUnload(); - this.chunks.remove(v); + this.chunks.remove(v.longValue()); this.loaded.remove(chunk); } } @@ -1750,18 +1682,18 @@ public final class WorldServer extends AWorldServer { this.loaded.clear(); this.setExterminatedGen(); for(Chunk chunk : loaded) { - ChunkPos pos = new ChunkPos(chunk.xPos, chunk.zPos); + long pos = LongHashMap.packInt(chunk.xPos, chunk.zPos); chunk.onChunkUnload(); this.chunks.remove(pos); chunk = this.generate(chunk.xPos, chunk.zPos); - this.chunks.put(pos, chunk); + this.chunks.add(pos, chunk); this.loaded.add(chunk); chunk.onChunkLoad(); - chunk.setTerrainPopulated(true); + chunk.checkLight(); chunk.setModified(); } for(Chunk chunk : this.loaded) { - chunk.update(); + chunk.update(false); } this.entities.removeAll(this.unloaded); for(int l = 0; l < this.unloaded.size(); ++l) { @@ -1833,7 +1765,7 @@ public final class WorldServer extends AWorldServer { Object[] worlds = server.getWorlds().toArray(); for(Object obj : worlds) { WorldServer world = (WorldServer)obj; - chunks += world.chunks.size(); + chunks += world.chunks.getNumHashElements(); entities += world.entities.size(); tiles += world.tiles.size(); ticked += world.tickable.size(); @@ -1933,17 +1865,28 @@ public final class WorldServer extends AWorldServer { } private boolean hasPlayerInstance(int chunkX, int chunkZ) { - ChunkPos v = new ChunkPos(chunkX, chunkZ); - return this.instances.get(v) != null; + long v = (long)chunkX + 2147483647L | (long)chunkZ + 2147483647L << 32; + return this.instances.getValueByKey(v) != null; + } + + public boolean updateBiomes(int chunkX, int chunkZ) { + long v = (long)chunkX + 2147483647L | (long)chunkZ + 2147483647L << 32; + PlayerInstance ins = this.instances.getValueByKey(v); + if(ins == null) + return false; + Chunk chunk = this.getChunk(chunkX, chunkZ); + chunk.setModified(); + ins.sendToAllPlayersWatchingChunk(new SPacketBiomes(chunkX, chunkZ, chunk.getBiomes())); + return true; } private PlayerInstance getPlayerInstance(int chunkX, int chunkZ, boolean create) { - ChunkPos v = new ChunkPos(chunkX, chunkZ); - PlayerInstance inst = this.instances.get(v); + long v = (long)chunkX + 2147483647L | (long)chunkZ + 2147483647L << 32; + PlayerInstance inst = this.instances.getValueByKey(v); if(inst == null && create) { inst = new PlayerInstance(chunkX, chunkZ); - this.instances.put(v, inst); + this.instances.add(v, inst); this.instList.add(inst); } @@ -2302,6 +2245,29 @@ public final class WorldServer extends AWorldServer { // return new LazyBlock(state, this, position); // } + public final boolean setBiome(BlockPos position, Biome biome) { + Chunk chunk = this.getChunk(position); + if((chunk != null) && (chunk.isLoaded())) { + chunk.getBiomes()[((position.getZ() & 0xF) << 4 | position.getX() & 0xF)] = (byte)biome.id; + return true; + } + return false; + } + + public final void setBiomes(BlockPos start, BlockPos end, Biome biome) { + Set chunks = Sets.newHashSet(); + for(int x = start.getX(); x <= end.getX(); x++) { + for(int z = start.getZ(); z <= end.getZ(); z++) { + if(this.setBiome(new BlockPos(x, 0, z), biome)) + chunks.add(new ChunkPos(x >> 4, z >> 4)); + } + } + for(ChunkPos pos : chunks) { + this.updateBiomes(pos.x, pos.z); + } + chunks.clear(); + } + // public final List getEntities(EditRegion region) { // List entities = Lists.newArrayList(); // for(Entity entity : this.entities) { @@ -2338,7 +2304,10 @@ public final class WorldServer extends AWorldServer { } public boolean canStrikeAt(BlockPos strikePosition) { - if(this.getPrecipitationHeight(strikePosition).getY() > strikePosition.getY()) { + if(!this.canSeeSky(strikePosition)) { + return false; + } + else if(this.getPrecipitationHeight(strikePosition).getY() > strikePosition.getY()) { return false; } return true; @@ -2411,7 +2380,7 @@ public final class WorldServer extends AWorldServer { return false; } else { - if(pos.getY() >= 0 && pos.getY() < 512 && this.getLightFor(pos) < 10) { + if(pos.getY() >= 0 && pos.getY() < 512 && this.getLightFor(LightType.BLOCK, pos) < 10) { State iblockstate = this.getState(pos); Block block = iblockstate.getBlock(); @@ -2459,13 +2428,12 @@ public final class WorldServer extends AWorldServer { return false; } - public BlockPos getTopSolidOrLiquidBlock(BlockPos pos, int y, int scan) { - scan = y - scan; + public BlockPos getTopSolidOrLiquidBlock(BlockPos pos) { Chunk chunk = this.getChunk(pos); BlockPos blockpos; BlockPos blockpos1; - for(blockpos = new BlockPos(pos.getX(), y, pos.getZ()); blockpos.getY() >= 0 && blockpos.getY() >= scan; blockpos = blockpos1) { + for(blockpos = new BlockPos(pos.getX(), chunk.getTopSegment() + 16, pos.getZ()); blockpos.getY() >= 0; blockpos = blockpos1) { blockpos1 = blockpos.down(); Material material = chunk.getBlock(blockpos1).getMaterial(); @@ -2477,10 +2445,6 @@ public final class WorldServer extends AWorldServer { return blockpos; } - public BlockPos getTopSolidOrLiquidBlock(BlockPos pos) { - return this.getTopSolidOrLiquidBlock(pos, 256, 256); - } - public void removePlayerEntityDangerously(Entity entityIn) { entityIn.setDead(); @@ -2838,7 +2802,7 @@ public final class WorldServer extends AWorldServer { private int updates; private int sections; private long prevTime; - private boolean resend; + private boolean biomes; public PlayerInstance(int chunkX, int chunkZ) { this.position = new ChunkPos(chunkX, chunkZ); @@ -2872,8 +2836,9 @@ public final class WorldServer extends AWorldServer { player.connection.getLoadedChunkList().remove(this.position); if(this.watching.isEmpty()) { + long v = (long)this.position.x + 2147483647L | (long)this.position.z + 2147483647L << 32; this.increaseInhabitedTime(chunk); - WorldServer.this.instances.remove(this.position); + WorldServer.this.instances.remove(v); WorldServer.this.instList.remove(this); if(this.updates > 0) { @@ -2894,7 +2859,7 @@ public final class WorldServer extends AWorldServer { WorldServer.this.toUpdate.add(this); this.updates = 64; this.sections = 0xffffffff; - this.resend = true; + this.biomes = true; } private void increaseInhabitedTime(Chunk chunk) { @@ -2949,7 +2914,7 @@ public final class WorldServer extends AWorldServer { int x = this.position.x * 16; int z = this.position.z * 16; this.sendToAllPlayersWatchingChunk(new SPacketChunkData(WorldServer.this.getChunk(this.position.x, this.position.z), - this.resend, this.sections)); + this.biomes, this.sections)); for(int cy = 0; cy < 32; ++cy) { if((this.sections & 1 << cy) != 0) { @@ -2980,7 +2945,7 @@ public final class WorldServer extends AWorldServer { this.updates = 0; this.sections = 0; - this.resend = false; + this.biomes = false; } } diff --git a/server/src/server/worldgen/BiomeGenLayered.java b/server/src/server/worldgen/BiomeGenLayered.java index 0a790ea..bdf9230 100755 --- a/server/src/server/worldgen/BiomeGenLayered.java +++ b/server/src/server/worldgen/BiomeGenLayered.java @@ -1,14 +1,13 @@ package server.worldgen; import java.util.List; -import java.util.Map; import java.util.Set; import common.biome.Biome; import common.collect.Lists; -import common.collect.Maps; import common.util.BlockPos; -import common.util.ChunkPos; +import common.util.LongHashMap; +import common.worldgen.BiomeGenerator; import server.worldgen.layer.GenLayer; import server.worldgen.layer.GenLayerAddAreas; import server.worldgen.layer.GenLayerAddExtra; @@ -55,7 +54,7 @@ public class BiomeGenLayered implements BiomeGenerator { private final GenLayer genBiomes; private final GenLayer biomeIndexLayer; - private final Map cacheMap = Maps.newHashMap(); + private final LongHashMap cacheMap = new LongHashMap(); private final List cache = Lists.newArrayList(); private long lastCleanupTime; @@ -126,13 +125,13 @@ public class BiomeGenLayered implements BiomeGenerator { { x = x >> 4; z = z >> 4; - ChunkPos pos = new ChunkPos(x, z); - CacheBlock blk = this.cacheMap.get(pos); + long i = LongHashMap.packInt(x, z); // (long)x & 4294967295L | ((long)z & 4294967295L) << 32; + CacheBlock blk = this.cacheMap.getValueByKey(i); if (blk == null) { blk = new CacheBlock(x, z); - this.cacheMap.put(pos, blk); + this.cacheMap.add(i, blk); this.cache.add(blk); } @@ -157,7 +156,8 @@ public class BiomeGenLayered implements BiomeGenerator { if (l > 30000L || l < 0L) { this.cache.remove(k--); - this.cacheMap.remove(new ChunkPos(blk.xPosition, blk.zPosition)); + long i1 = LongHashMap.packInt(blk.xPosition, blk.zPosition) ; // (long)biomecache$block.xPosition & 4294967295L | ((long)biomecache$block.zPosition & 4294967295L) << 32; + this.cacheMap.remove(i1); } } } diff --git a/server/src/server/worldgen/BiomeGenSingle.java b/server/src/server/worldgen/BiomeGenSingle.java index cd5bade..586058f 100755 --- a/server/src/server/worldgen/BiomeGenSingle.java +++ b/server/src/server/worldgen/BiomeGenSingle.java @@ -5,6 +5,7 @@ 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/server/src/server/worldgen/FeatureLakes.java b/server/src/server/worldgen/FeatureLakes.java index 1f4e2c1..98fe8bd 100755 --- a/server/src/server/worldgen/FeatureLakes.java +++ b/server/src/server/worldgen/FeatureLakes.java @@ -5,6 +5,7 @@ import common.init.Blocks; import common.material.Material; import common.rng.Random; import common.util.BlockPos; +import common.world.LightType; import common.world.State; import server.biome.GenBiome; import server.world.WorldServer; @@ -160,7 +161,7 @@ public class FeatureLakes { BlockPos blockpos = position.add(i2, j4 - 1, j3); - if (worldIn.getState(blockpos).getBlock() == replace && worldIn.isAirBlock(position.add(i2, j4, j3))) + if (worldIn.getState(blockpos).getBlock() == replace && worldIn.getLightFor(LightType.SKY, position.add(i2, j4, j3)) > 0) { GenBiome biomegenbase = GenBiome.BIOMES[worldIn.getBiomeGenForCoords(blockpos).id]; diff --git a/server/src/server/worldgen/structure/MapGenStructure.java b/server/src/server/worldgen/structure/MapGenStructure.java index ab8c362..dc911fe 100755 --- a/server/src/server/worldgen/structure/MapGenStructure.java +++ b/server/src/server/worldgen/structure/MapGenStructure.java @@ -9,6 +9,7 @@ import common.nbt.NBTTagCompound; import common.rng.Random; import common.util.BlockPos; import common.util.ChunkPos; +import common.util.LongHashMap; import common.world.World; import server.world.WorldServer; import server.world.WorldServer.WorldSavedData; @@ -18,7 +19,7 @@ import server.worldgen.caves.MapGenBase; public abstract class MapGenStructure extends MapGenBase { private WorldSavedData structureData; - protected Map structureMap = Maps.newHashMap(); + protected Map structureMap = Maps.newHashMap(); public abstract String getStructureName(); @@ -33,15 +34,14 @@ public abstract class MapGenStructure extends MapGenBase return; this.initializeStructureData(worldIn); - ChunkPos pos = new ChunkPos(chunkX, chunkZ); - if (!this.structureMap.containsKey(pos)) + if (!this.structureMap.containsKey(Long.valueOf(LongHashMap.packInt(chunkX, chunkZ)))) { this.rand.intv(); if (this.canSpawnStructureAtCoords(chunkX, chunkZ)) { StructureStart structurestart = this.getStructureStart(chunkX, chunkZ); - this.structureMap.put(pos, structurestart); + this.structureMap.put(Long.valueOf(LongHashMap.packInt(chunkX, chunkZ)), structurestart); this.setStructureStart(chunkX, chunkZ, structurestart); } } @@ -221,7 +221,7 @@ public abstract class MapGenStructure extends MapGenBase if (structurestart != null) { - this.structureMap.put(new ChunkPos(i, j), structurestart); + this.structureMap.put(Long.valueOf(LongHashMap.packInt(i, j)), structurestart); } } } diff --git a/server/src/server/worldgen/structure/StructureVillage.java b/server/src/server/worldgen/structure/StructureVillage.java index 0fb61ae..498cec0 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;