diff options
author | moller21 <42100910+moller21@users.noreply.github.com> | 2020-07-19 19:08:59 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-19 19:08:59 +0200 |
commit | 8ce4ae8d22f31587c600bf8190cfb88e1a4f2ea2 (patch) | |
tree | 5f5d4fa32fc17e4029a8d31f209a193610c4b232 /src/main/java/gregtech | |
parent | b12ebd30b3d2199dfeca0deeaa36353dcf57e006 (diff) | |
download | GT5-Unofficial-8ce4ae8d22f31587c600bf8190cfb88e1a4f2ea2.tar.gz GT5-Unofficial-8ce4ae8d22f31587c600bf8190cfb88e1a4f2ea2.tar.bz2 GT5-Unofficial-8ce4ae8d22f31587c600bf8190cfb88e1a4f2ea2.zip |
Rework clientside pollution (#302)
* Rework clientside pollution
* Pollution rework
* removed debug
Diffstat (limited to 'src/main/java/gregtech')
8 files changed, 577 insertions, 85 deletions
diff --git a/src/main/java/gregtech/api/net/GT_Packet_Pollution.java b/src/main/java/gregtech/api/net/GT_Packet_Pollution.java index 2c67d74150..7f717c1a47 100644 --- a/src/main/java/gregtech/api/net/GT_Packet_Pollution.java +++ b/src/main/java/gregtech/api/net/GT_Packet_Pollution.java @@ -1,38 +1,47 @@ package gregtech.api.net; import com.google.common.io.ByteArrayDataInput; -import com.google.common.io.ByteArrayDataOutput; -import com.google.common.io.ByteStreams; -import gregtech.common.GT_Pollution; +import gregtech.common.GT_Client; +import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.world.IBlockAccess; +import java.nio.ByteBuffer; + public class GT_Packet_Pollution extends GT_Packet { - private int mPollution; + private ChunkCoordIntPair chunk; + private int pollution; public GT_Packet_Pollution() { super(true); } - public GT_Packet_Pollution(int aPollution) { + public GT_Packet_Pollution(ChunkCoordIntPair chunk, int pollution) { super(false); - mPollution = aPollution; + this.chunk = chunk; + this.pollution = pollution; } @Override public byte[] encode() { - ByteArrayDataOutput tOut = ByteStreams.newDataOutput(4); - tOut.writeInt(mPollution); - return tOut.toByteArray(); + return ByteBuffer + .allocate(12) + .putInt(chunk.chunkXPos) + .putInt(chunk.chunkZPos) + .putInt(pollution) + .array(); } @Override public GT_Packet decode(ByteArrayDataInput aData) { - return new GT_Packet_Pollution(aData.readInt()); + return new GT_Packet_Pollution( + new ChunkCoordIntPair(aData.readInt(), aData.readInt()), + aData.readInt() + ); } @Override public void process(IBlockAccess aWorld) { - GT_Pollution.mPlayerPollution = mPollution; + GT_Client.recieveChunkPollutionPacket(chunk, pollution); } @Override diff --git a/src/main/java/gregtech/common/GT_Client.java b/src/main/java/gregtech/common/GT_Client.java index 51f5e30c28..e528323da4 100644 --- a/src/main/java/gregtech/common/GT_Client.java +++ b/src/main/java/gregtech/common/GT_Client.java @@ -33,6 +33,7 @@ import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.stats.StatFileWriter; import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.world.World; import net.minecraftforge.client.event.DrawBlockHighlightEvent; import net.minecraftforge.oredict.OreDictionary; @@ -56,7 +57,8 @@ public class GT_Client extends GT_Proxy }); } - private final HashSet mCapeList = new HashSet(); + private final HashSet<String> mCapeList = new HashSet<>(); + public final static GT_PollutionRenderer mPollutionRenderer = new GT_PollutionRenderer(); private final GT_CapeRenderer mCapeRenderer; private final List mPosR; private final List mPosG; @@ -247,45 +249,6 @@ public class GT_Client extends GT_Proxy drawGrid(aEvent, false); } - //TODO less bad - //@SubscribeEvent - //public void manipulateDensity(EntityViewRenderEvent.FogDensity event) { - // if(GT_Pollution.mPlayerPollution > (GT_Mod.gregtechproxy.mPollutionSmogLimit)){ - // event.density = (0.15f*(Math.min(GT_Pollution.mPlayerPollution/((float)GT_Mod.gregtechproxy.mPollutionSourRainLimit),1.0f)))+0.1f; - // event.setCanceled(true); - // } - //} - - //@SubscribeEvent - //public void manipulateColor(EntityViewRenderEvent.FogColors event) { - // if(GT_Pollution.mPlayerPollution > GT_Mod.gregtechproxy.mPollutionSmogLimit){ - // event.red = 140f/255f; - // event.green = 80f/255f; - // event.blue = 40f/255f; - // } - //} - - //@SubscribeEvent - //public void manipulateGrassColor(BiomeEvent.GetGrassColor event) { - // if(GT_Pollution.mPlayerPollution > GT_Mod.gregtechproxy.mPollutionSmogLimit){ - // event.newColor = 0xD2691E; - // } - //} - - //@SubscribeEvent - //public void manipulateWaterColor(BiomeEvent.GetWaterColor event) { - // if(GT_Pollution.mPlayerPollution > GT_Mod.gregtechproxy.mPollutionSmogLimit){ - // event.newColor = 0x556B2F; - // } - //} - - //@SubscribeEvent - //public void manipulateFoliageColor(BiomeEvent.GetFoliageColor event) { - // if(GT_Pollution.mPlayerPollution > GT_Mod.gregtechproxy.mPollutionSmogLimit){ - // event.newColor = 0xCD853F; - // } - //} - public boolean isServerSide() { return true; } @@ -329,6 +292,8 @@ public class GT_Client extends GT_Proxy mCapeList.add(tName.toLowerCase()); } (new Thread(this)).start(); + + mPollutionRenderer.preLoad(); } public void onLoad() { @@ -730,4 +695,8 @@ public class GT_Client extends GT_Proxy return 0; } } + + public static void recieveChunkPollutionPacket(ChunkCoordIntPair chunk, int pollution) { + mPollutionRenderer.processPacket(chunk, pollution); + } } diff --git a/src/main/java/gregtech/common/GT_Pollution.java b/src/main/java/gregtech/common/GT_Pollution.java index f25c21f86a..be49e57e4a 100644 --- a/src/main/java/gregtech/common/GT_Pollution.java +++ b/src/main/java/gregtech/common/GT_Pollution.java @@ -1,12 +1,18 @@ package gregtech.common; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.TickEvent; +import cpw.mods.fml.common.network.NetworkRegistry; import gregtech.GT_Mod; +import gregtech.api.enums.GT_Values; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.net.GT_Packet_Pollution; import gregtech.api.util.GT_Utility; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.init.Blocks; import net.minecraft.potion.Potion; import net.minecraft.potion.PotionEffect; @@ -15,6 +21,8 @@ import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.world.ChunkPosition; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.world.ChunkWatchEvent; import java.util.ArrayList; import java.util.HashMap; @@ -64,6 +72,10 @@ public class GT_Pollution { private final World aWorld; public static int mPlayerPollution; + private static int POLLUTIONPACKET_MINVALUE = 1000; + + private static GT_PollutionEventHandler EVENT_HANDLER; + public GT_Pollution(World world){ aWorld=world; chunkData=dimensionWiseChunkData.get(aWorld.provider.dimensionId); @@ -72,6 +84,11 @@ public class GT_Pollution { dimensionWiseChunkData.put(world.provider.dimensionId,chunkData); } dimensionWisePollution.put(aWorld.provider.dimensionId,this); + + if (EVENT_HANDLER == null) { + EVENT_HANDLER = new GT_PollutionEventHandler(); + MinecraftForge.EVENT_BUS.register(EVENT_HANDLER); + } } public static void onWorldTick(TickEvent.WorldTickEvent aEvent){//called from proxy @@ -130,7 +147,9 @@ public class GT_Pollution { AxisAlignedBB chunk = AxisAlignedBB.getBoundingBox(actualPos.chunkXPos << 4, 0, actualPos.chunkZPos << 4, (actualPos.chunkXPos << 4) + 16, 256, (actualPos.chunkZPos << 4) + 16); List<EntityLivingBase> tEntitys = aWorld.getEntitiesWithinAABB(EntityLivingBase.class, chunk); for (EntityLivingBase tEnt : tEntitys) { - if (!GT_Utility.isWearingFullGasHazmat(tEnt)) { + if (tEnt instanceof EntityPlayerMP && ((EntityPlayerMP) tEnt).capabilities.isCreativeMode) + continue; + if (!(GT_Utility.isWearingFullGasHazmat(tEnt))) { switch (XSTR_INSTANCE.nextInt(3)) { default: tEnt.addPotionEffect(new PotionEffect(Potion.digSlowdown.id, Math.min(tPollution / 1000, 1000), tPollution / 400000)); @@ -148,6 +167,8 @@ public class GT_Pollution { //AxisAlignedBB chunk = AxisAlignedBB.getBoundingBox(tPos.chunkPosX*16, 0, tPos.chunkPosZ*16, tPos.chunkPosX*16+16, 256, tPos.chunkPosZ*16+16); //List<EntityLiving> tEntitys = aWorld.getEntitiesWithinAABB(EntityLiving.class, chunk); for (EntityLivingBase tEnt : tEntitys) { + if (tEnt instanceof EntityPlayerMP && ((EntityPlayerMP) tEnt).capabilities.isCreativeMode) + continue; if (!GT_Utility.isWearingFullGasHazmat(tEnt)) { switch (XSTR_INSTANCE.nextInt(4)) { default: @@ -178,15 +199,21 @@ public class GT_Pollution { } //Write new pollution to Hashmap !!! chunkData.get(actualPos)[GTPOLLUTION] = tPollution; + + //Send new value to players nearby + if (tPollution > POLLUTIONPACKET_MINVALUE) { + NetworkRegistry.TargetPoint point = new NetworkRegistry.TargetPoint(aWorld.provider.dimensionId, (actualPos.chunkXPos << 4), 64, (actualPos.chunkZPos << 4), 256); + GT_Values.NW.sendToAllAround(new GT_Packet_Pollution(actualPos, tPollution), point); + } } } - + private static void damageBlock(World world, int x, int y, int z, boolean sourRain){ if (world.isRemote) return; Block tBlock = world.getBlock(x, y, z); int tMeta = world.getBlockMetadata(x, y, z); if (tBlock == Blocks.air || tBlock == Blocks.stone || tBlock == Blocks.sand|| tBlock == Blocks.deadbush)return; - + if (tBlock == Blocks.leaves || tBlock == Blocks.leaves2 || tBlock.getMaterial() == Material.leaves) world.setBlockToAir(x, y, z); if (tBlock == Blocks.reeds) { @@ -199,12 +226,12 @@ public class GT_Pollution { tBlock.dropBlockAsItem(world, x, y, z, tMeta, 0); world.setBlockToAir(x, y, z); } - if (tBlock == Blocks.waterlily || tBlock == Blocks.wheat || tBlock == Blocks.cactus || + if (tBlock == Blocks.waterlily || tBlock == Blocks.wheat || tBlock == Blocks.cactus || tBlock.getMaterial() == Material.cactus || tBlock == Blocks.melon_block || tBlock == Blocks.melon_stem) { tBlock.dropBlockAsItem(world, x, y, z, tMeta, 0); world.setBlockToAir(x, y, z); } - if (tBlock == Blocks.red_flower || tBlock == Blocks.yellow_flower || tBlock == Blocks.carrots || + if (tBlock == Blocks.red_flower || tBlock == Blocks.yellow_flower || tBlock == Blocks.carrots || tBlock == Blocks.potatoes || tBlock == Blocks.pumpkin || tBlock == Blocks.pumpkin_stem) { tBlock.dropBlockAsItem(world, x, y, z, tMeta, 0); world.setBlockToAir(x, y, z); @@ -218,12 +245,12 @@ public class GT_Pollution { if (tBlock == Blocks.mossy_cobblestone) world.setBlock(x, y, z, Blocks.cobblestone); if (tBlock == Blocks.grass || tBlock.getMaterial() == Material.grass ) - world.setBlock(x, y, z, Blocks.dirt); + world.setBlock(x, y, z, Blocks.dirt); if(tBlock == Blocks.farmland || tBlock == Blocks.dirt){ - world.setBlock(x, y, z, Blocks.sand); + world.setBlock(x, y, z, Blocks.sand); } - - if(sourRain && world.isRaining() && (tBlock == Blocks.stone || tBlock == Blocks.gravel || tBlock == Blocks.cobblestone) && + + if(sourRain && world.isRaining() && (tBlock == Blocks.stone || tBlock == Blocks.gravel || tBlock == Blocks.cobblestone) && world.getBlock(x, y+1, z) == Blocks.air && world.canBlockSeeTheSky(x, y, z)){ if(tBlock == Blocks.stone){world.setBlock(x, y, z, Blocks.cobblestone); } else if(tBlock == Blocks.cobblestone){world.setBlock(x, y, z, Blocks.gravel); } @@ -256,19 +283,22 @@ public class GT_Pollution { } public static int getPollution(Chunk ch){ - if(!GT_Mod.gregtechproxy.mPollution)return 0; + if(!GT_Mod.gregtechproxy.mPollution) + return 0; HashMap<ChunkCoordIntPair,int[]> dataMap=dimensionWiseChunkData.get(ch.worldObj.provider.dimensionId); if(dataMap==null || dataMap.get(ch.getChunkCoordIntPair())==null) return 0; return dataMap.get(ch.getChunkCoordIntPair())[GTPOLLUTION]; } - public static int getPollution(ChunkCoordIntPair aCh, int aDim){ - if(!GT_Mod.gregtechproxy.mPollution)return 0; - HashMap<ChunkCoordIntPair,int[]> dataMap=dimensionWiseChunkData.get(aDim); - if(dataMap==null || dataMap.get(aCh)==null) return 0; + public static int getPollution(ChunkCoordIntPair aCh, int aDim) { + if (!GT_Mod.gregtechproxy.mPollution) + return 0; + HashMap<ChunkCoordIntPair, int[]> dataMap = dimensionWiseChunkData.get(aDim); + if (dataMap == null || dataMap.get(aCh) == null) + return 0; return dataMap.get(aCh)[GTPOLLUTION]; } - + //Add compatibility with old code @Deprecated /*Don't use it... too weird way of passing position*/ public static void addPollution(World aWorld, ChunkPosition aPos, int aPollution){ @@ -276,4 +306,15 @@ public class GT_Pollution { //is just bad especially when that is both used to store ChunkPos and BlockPos depending on context addPollution(aWorld.getChunkFromBlockCoords(aPos.chunkPosX,aPos.chunkPosZ),aPollution); } + + public class GT_PollutionEventHandler { + @SubscribeEvent + public void chunkWatch(ChunkWatchEvent.Watch event) { + if (chunkData.containsKey(event.chunk)) { + int pollution = chunkData.get(event.chunk)[GTPOLLUTION]; + if (pollution > POLLUTIONPACKET_MINVALUE) + GT_Values.NW.sendToPlayer(new GT_Packet_Pollution(event.chunk, pollution), event.player); + } + } + } } diff --git a/src/main/java/gregtech/common/GT_Proxy.java b/src/main/java/gregtech/common/GT_Proxy.java index 26b971a093..5b762d6d58 100644 --- a/src/main/java/gregtech/common/GT_Proxy.java +++ b/src/main/java/gregtech/common/GT_Proxy.java @@ -1490,11 +1490,6 @@ public abstract class GT_Proxy implements IGT_Mod, IGuiHandler, IFuelHandler { aEvent.player.addExhaustion(Math.max(1.0F, tCount / 666.6F)); } } - if (aEvent.player.ticksExisted % 10 == 0) { - int tPollution = 0; - tPollution = GT_Pollution.getPollution(new ChunkCoordIntPair(aEvent.player.chunkCoordX,aEvent.player.chunkCoordZ), aEvent.player.dimension); - if(aEvent.player instanceof EntityPlayerMP)GT_Values.NW.sendToPlayer(new GT_Packet_Pollution(tPollution), (EntityPlayerMP) aEvent.player); - } } } diff --git a/src/main/java/gregtech/common/entities/GT_EntityFXPollution.java b/src/main/java/gregtech/common/entities/GT_EntityFXPollution.java new file mode 100644 index 0000000000..2123313190 --- /dev/null +++ b/src/main/java/gregtech/common/entities/GT_EntityFXPollution.java @@ -0,0 +1,65 @@ +package gregtech.common.entities; + +import cofh.lib.util.helpers.MathHelper; +import net.minecraft.client.particle.EntityFX; +import net.minecraft.world.World; + +import java.util.Random; + +public class GT_EntityFXPollution extends EntityFX { + + public GT_EntityFXPollution(World world, double x, double y, double z) { + super(world, x, y, z,0 ,0 ,0); + + this.particleRed = 0.25F; + this.particleGreen = 0.2F; + this.particleBlue = 0.25F; + + this.motionX *= 0.1D; + this.motionY *= -0.1D; + this.motionZ *= 0.1F; + + Random random = world.rand; + this.motionX += random.nextFloat() * -1.9D * random.nextFloat() * 0.1D; + this.motionY += random.nextFloat() * -0.5D * random.nextFloat() * 0.1D * 5.0D; + this.motionZ += random.nextFloat() * -1.9D * random.nextFloat() * 0.1D; + + this.particleTextureIndexX = 0; + this.particleTextureIndexY = 0; + + this.particleMaxAge = (int)((double)20 / ((double)random.nextFloat() * 0.8D + 0.2D)); + + this.particleScale *= 0.75F; + this.noClip = true; + } + + @Override + public void onUpdate() { + this.prevPosX = this.posX; + this.prevPosY = this.posY; + this.prevPosZ = this.posZ; + + if (this.particleAge++ >= this.particleMaxAge) { + this.setDead(); + } else { + this.motionY += -5.0E-4D; + this.moveEntity(this.motionX, this.motionY, this.motionZ); + if (this.posY == this.prevPosY) { + this.motionX *= 1.1D; + this.motionZ *= 1.1D; + } + this.motionX *= 0.96D; + this.motionY *= 0.96D; + this.motionZ *= 0.96D; + if (this.onGround) { + this.motionX *= 0.7D; + this.motionZ *= 0.7D; + } + } + } + + + public float getSize(float tickDelta) { + return this.particleScale * MathHelper.clamp(((float)this.particleAge + tickDelta) / (float)this.particleMaxAge * 32.0F, 0.0F, 1.0F); + } +} diff --git a/src/main/java/gregtech/common/misc/GT_ClientPollutionMap.java b/src/main/java/gregtech/common/misc/GT_ClientPollutionMap.java new file mode 100644 index 0000000000..7ba470e412 --- /dev/null +++ b/src/main/java/gregtech/common/misc/GT_ClientPollutionMap.java @@ -0,0 +1,156 @@ +package gregtech.common.misc; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityClientPlayerMP; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.MathHelper; +import org.lwjgl.opengl.GL11; + +public class GT_ClientPollutionMap { + private static final byte RADIUS = 24; + private static final byte DISTANCE_RELOAD_MAP = 5; //When player moved x chunks, shift the map to new center. + private static final byte SIZE = RADIUS*2+1; //Area to keep stored. + + private int x0, z0; + private int dim; + + private boolean initialized = false; + + private static short[][] chunkMatrix; //short because reasons. + + + public GT_ClientPollutionMap(){ } + + public void reset() { + initialized = false; + } + + private void initialize(int playerChunkX, int playerChunkZ, int dimension) { + initialized = true; + chunkMatrix = new short[SIZE][SIZE]; + x0 = playerChunkX; + z0 = playerChunkZ; + dim = dimension; + } + + public void addChunkPollution(int chunkX, int chunkZ, int pollution) { + EntityClientPlayerMP player = Minecraft.getMinecraft().thePlayer; + if (player == null || player.worldObj == null) + return; + + int playerXChunk = MathHelper.floor_double(player.posX) >> 4; + int playerZChunk = MathHelper.floor_double(player.posZ) >> 4; //posX/Z seems to be always loaded, + + if (!initialized) { + initialize(playerXChunk, playerZChunk, player.dimension); + } + + if (dim != player.dimension) { + initialize(playerXChunk, playerZChunk, player.dimension); + } + + if (Math.abs(x0 - playerXChunk) > DISTANCE_RELOAD_MAP || Math.abs(z0 - playerZChunk) > DISTANCE_RELOAD_MAP) + shiftCenter(playerXChunk, playerZChunk); + + int relX = chunkX - x0 + RADIUS; + if (relX >= SIZE || relX < 0) //out of bounds + return; + int relZ = chunkZ - z0 + RADIUS; + if (relZ >= SIZE || relZ < 0) //out of bounds + return; + + pollution = pollution/225; + if (pollution > Short.MAX_VALUE) //Sanity + chunkMatrix[relX][relZ] = Short.MAX_VALUE; //Max pollution = 7,3mill + else if (pollution < 0) + chunkMatrix[relX][relZ] = 0; + else + chunkMatrix[relX][relZ] = (short) (pollution); + } + + //xy interpolation, between 4 chunks as corners, unknown treated as 0. + public int getPollution(double fx, double fz) { + if (!initialized) + return 0; + int x = MathHelper.floor_double(fx); + int z = MathHelper.floor_double(fz); + int xDiff = ((x-8) >> 4) - x0; + int zDiff = ((z-8) >> 4) - z0; + + if (xDiff < -RADIUS || zDiff < -RADIUS || xDiff >= RADIUS || zDiff >= RADIUS ) + return 0; + + //coordinates in shifted chunk. + x = (x-8) % 16; + z = (z-8) % 16; + if (x < 0) + x = 16+x; + if (z < 0) + z = 16+z; + + int xi = 15 - x; + int zi = 15 - z; + + //read pollution in 4 corner chunks + int offsetX = RADIUS+xDiff; + int offsetZ = RADIUS+zDiff; + + int c00 = chunkMatrix[offsetX][offsetZ]; + int c10 = chunkMatrix[offsetX+1][offsetZ]; + int c01 = chunkMatrix[offsetX][offsetZ+1]; + int c11 = chunkMatrix[offsetX+1][offsetZ+1]; + + //Is divided by 15*15 but is handled when storing chunk data. + return c00*xi*zi + c10*x*zi + c01*xi*z + c11*x*z; + } + + //shift the matrix to fit new center + private void shiftCenter(int chunkX, int chunkZ) { + int xDiff = chunkX - x0; + int zDiff = chunkZ - z0; + boolean[] allEmpty = new boolean[SIZE]; //skip check z row if its empty. + if (xDiff > 0) + for (byte x = 0; x < SIZE; x++) { + int xOff = x + xDiff; + if (xOff < SIZE) { + chunkMatrix[x] = chunkMatrix[xOff].clone(); + } else { + chunkMatrix[x] = new short[SIZE]; + allEmpty[x] = true; + } + } + else if (xDiff < 0) + for (byte x = SIZE-1; x >= 0; x--) { + int xOff = x + xDiff; + if (xOff > 0) { + chunkMatrix[x] = chunkMatrix[xOff].clone(); + } else { + chunkMatrix[x] = new short[SIZE]; + allEmpty[x] = true; + } + } + + if (zDiff > 0) + for (byte x = 0; x < SIZE; x++) { + if (allEmpty[x]) + continue; + for (int z = 0; z < SIZE ; z++) { + int zOff = z + zDiff; + chunkMatrix[x][z] = (zOff < SIZE) ? chunkMatrix[x][zOff] : 0; + } + } + else if (zDiff < 0) + for (byte x = 0; x < SIZE; x++) { + if (allEmpty[x]) + continue; + for (int z = SIZE-1; z >= 0 ; z--) { + int zOff = z+zDiff; + chunkMatrix[x][z] = (zOff > 0) ? chunkMatrix[x][zOff] : 0; + } + } + + x0 = chunkX; + z0 = chunkZ; + } +} diff --git a/src/main/java/gregtech/common/misc/GT_Command.java b/src/main/java/gregtech/common/misc/GT_Command.java index 66ae7058bc..f3272ee341 100644 --- a/src/main/java/gregtech/common/misc/GT_Command.java +++ b/src/main/java/gregtech/common/misc/GT_Command.java @@ -1,11 +1,15 @@ package gregtech.common.misc; +import gregtech.GT_Mod; import gregtech.api.enums.GT_Values; import gregtech.api.objects.GT_ChunkManager; +import gregtech.common.GT_Pollution; import net.minecraft.command.CommandBase; import net.minecraft.command.ICommandSender; import net.minecraft.command.WrongUsageException; import net.minecraft.util.ChatComponentText; +import net.minecraft.util.ChunkCoordinates; + import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; @@ -21,10 +25,10 @@ public final class GT_Command extends CommandBase { @Override public String getCommandUsage(ICommandSender sender) { - return "Usage: gt <subcommand>. Valid subcommands are: toggle, chunks."; + return "Usage: gt <subcommand>. Valid subcommands are: toggle, chunks, pollution."; } private void printHelp(ICommandSender sender) { - sender.addChatMessage(new ChatComponentText("Usage: gt <toggle|chunks>")); + sender.addChatMessage(new ChatComponentText("Usage: gt <toggle|chunks|pollution>")); sender.addChatMessage(new ChatComponentText("\"toggle D1\" - toggles general.Debug (D1)")); sender.addChatMessage(new ChatComponentText("\"toggle D2\" - toggles general.Debug2 (D2)")); sender.addChatMessage(new ChatComponentText("\"toggle debugCleanroom\" - toggles cleanroom debug log")); @@ -38,6 +42,10 @@ public final class GT_Command extends CommandBase { sender.addChatMessage(new ChatComponentText("\"toggle debugStones\" - toggles worldgen stones debug")); sender.addChatMessage(new ChatComponentText("\"toggle debugChunkloaders\" - toggles chunkloaders debug")); sender.addChatMessage(new ChatComponentText("\"chunks\" - print a list of the force loaded chunks")); + sender.addChatMessage(new ChatComponentText( + "\"pollution <amount>\" - adds the <amount> of the pollution to the current chunk, " + + "\n if <amount> isnt specified, will add" + GT_Mod.gregtechproxy.mPollutionSmogLimit + "gibbl." + )); } @Override @@ -45,25 +53,24 @@ public final class GT_Command extends CommandBase { List<String> l = new ArrayList<>(); Stream<String> keywords = Arrays.stream(new String[]{"toggle", "chunks"}); String test = ss.length == 0 ? "" : ss[0].trim(); - if (ss.length == 0 || ss.length == 1 && (test.isEmpty() || keywords.anyMatch(s -> s.startsWith(test)))) { - keywords.forEach(s -> { - if (test.isEmpty() || s.startsWith(test)) - l.add(s); - }); + if (ss.length == 0 || ss.length == 1 && (test.isEmpty() || Stream.of("toggle", "chunks", "pollution").anyMatch(s -> s.startsWith(test)))) { + Stream.of("toggle", "chunks", "pollution") + .filter(s -> test.isEmpty() || s.startsWith(test)) + .forEach(l::add); } else if (test.equals("toggle")) { - String test1 = ss.length == 1 ? "" : ss[1].trim(); - Arrays.stream(new String[]{"D1", "D2", "debugCleanroom", "debugDriller", "debugBlockPump", "debugBlockMiner", "debugWorldGen", "debugEntityCramming", - "debugOrevein", "debugSmallOres", "debugStones", "debugChunkloaders"}).forEach(s -> { - if (test1.isEmpty() || s.startsWith(test1)) - l.add(s); - }); + String test1 = ss[1].trim(); + Stream.of("D1", "D2", "debugCleanroom", "debugDriller", "debugBlockPump", "debugBlockMiner", "debugWorldGen", "debugEntityCramming", + "debugOrevein", "debugSmallOres", "debugStones", "debugChunkloaders") + .filter(s -> test1.isEmpty() || s.startsWith(test1)) + .forEach(l::add); + } return l; } @Override public void processCommand(ICommandSender sender, String[] strings) { - if (strings.length < 1 || (!strings[0].equals("toggle") && !strings[0].equals("chunks"))) { + if (strings.length < 1) { printHelp(sender); return; } @@ -90,6 +97,21 @@ public final class GT_Command extends CommandBase { GT_ChunkManager.printTickets(); sender.addChatMessage(new ChatComponentText("Forced chunks logged to GregTech.log")); break; + case "pollution": { + ChunkCoordinates coordinates = sender.getPlayerCoordinates(); + int amount = (strings.length < 2) ? GT_Mod.gregtechproxy.mPollutionSmogLimit : Integer.parseInt(strings[1]); + GT_Pollution.addPollution(sender + .getEntityWorld() + .getChunkFromBlockCoords( + coordinates.posX, + coordinates.posZ + ), + amount + ); + break; + } + default: + printHelp(sender); } } } diff --git a/src/main/java/gregtech/common/render/GT_PollutionRenderer.java b/src/main/java/gregtech/common/render/GT_PollutionRenderer.java new file mode 100644 index 0000000000..832e93ecf9 --- /dev/null +++ b/src/main/java/gregtech/common/render/GT_PollutionRenderer.java @@ -0,0 +1,235 @@ +package gregtech.common.render; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.eventhandler.EventPriority; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.common.gameevent.TickEvent; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import gregtech.common.misc.GT_ClientPollutionMap; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityClientPlayerMP; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.world.ChunkCoordIntPair; +import net.minecraftforge.client.event.EntityViewRenderEvent; +import net.minecraftforge.event.world.WorldEvent; +import org.lwjgl.opengl.GL11; + +@SideOnly(Side.CLIENT) +public class GT_PollutionRenderer { + private static GT_ClientPollutionMap pollutionMap; + private static int playerPollution = 0; + + private static boolean DEBUG = false; + + // PARTICLES_POLLUTION_START + PARTICLES_POLLUTION_END -> Max Particles + private static final int PARTICLES_MAX_NUM = 100; + private static final int PARTICLES_POLLUTION_START = 400000; + private static final int PARTICLES_POLLUTION_END = 3500000; + + private static final int FOG_START_AT_POLLUTION = 400000; + private static final int FOG_MAX_AT_POLLUTION = 7000000; + //jump from linear to exponential fog. x*FOG_MAX_AT_POLLUTION+FOG_START_AT_POLLUTION + private static final double FOG_START_EXP_RATIO = 0.02D; + + private static final float[] fogColor = {0.3f, 0.25f, 0.1f}; + private static final short[] grassColor = {230, 180, 40}; + private static final short[] leavesColor = {160, 80, 15}; + private static final short[] liquidColor = {160, 200, 10}; + private static final short[] foliageColor = {160, 80, 15}; + + //TODO need to soft update some blocks, grass and leaves does more often than liquid it looks like. + + public GT_PollutionRenderer() { + pollutionMap = new GT_ClientPollutionMap(); + } + + public void preLoad() { + net.minecraftforge.common.MinecraftForge.EVENT_BUS.register(this); + FMLCommonHandler.instance().bus().register(this); + } + + public void processPacket(ChunkCoordIntPair chunk, int pollution) { + pollutionMap.addChunkPollution(chunk.chunkXPos, chunk.chunkZPos, pollution); + } + + @SubscribeEvent(priority = EventPriority.HIGH) + public void enteredWorld(WorldEvent.Load event) { + EntityClientPlayerMP p = Minecraft.getMinecraft().thePlayer; + if (!event.world.isRemote || p == null) + return; + pollutionMap.reset(); + } + + private static int color(int color, int pollution, int low, float high, short[] colors) { + if ( pollution < low) + return color; + + int r = (color >> 16) & 0xFF; + int g = (color >> 8) & 0xFF; + int b = color & 0xFF; + float p = (pollution - low) / high; + if (p > 1) p = 1; + float pi = 1 - p; + + r = ((int) (r * pi + p * colors[0])) & 0xFF; + g = ((int) (g * pi + p * colors[1])) & 0xFF; + b = ((int) (b * pi + p * colors[2])) & 0xFF; + + return (r & 0xFF) << 16 | (g & 0xFF) << 8 | b & 0xFF; + } + + // Methods for hodgepodge to color grass / foliage blocks etc. + public static int colorGrass(int oColor, int x, int z) { + return color(oColor, pollutionMap.getPollution(x, z)/1000, 350, 600, grassColor); + } + public static int colorLeaves(int oColor, int x, int z) { + return color(oColor, pollutionMap.getPollution(x, z)/1000, 300, 500, leavesColor); + } + public static int colorLiquid(int oColor, int x, int z) { + return color(oColor, pollutionMap.getPollution(x, z)/1000, 300, 500, liquidColor); + } + public static int colorFoliage(int oColor, int x, int z) { + return color(oColor, pollutionMap.getPollution(x, z)/1000, 300, 500, foliageColor); + } + + @SubscribeEvent(priority = EventPriority.LOW) + public void manipulateColor(EntityViewRenderEvent.FogColors event) { + if (!DEBUG && Minecraft.getMinecraft().thePlayer.capabilities.isCreativeMode) + return; + + if (event.block.getMaterial() == Material.water || + event.block.getMaterial() == Material.lava) + return; + + float x = fogIntensityLastTick > 1 ? 1F : (float) fogIntensityLastTick; + float xi = 1 - x; + + event.red = xi*event.red + x*fogColor[0]; + event.green = xi*event.green + x*fogColor[1]; + event.blue = xi*event.blue + x*fogColor[2]; + } + + private static final int END_MAX_DISTANCE = 192 - 1; + private static double fogIntensityLastTick = 0; + + @SubscribeEvent(priority = EventPriority.LOWEST) + public void renderGTPollutionFog(EntityViewRenderEvent.RenderFogEvent event) { + if ((!DEBUG && Minecraft.getMinecraft().thePlayer.capabilities.isCreativeMode) || + (fogIntensityLastTick <= 0 && fogIntensityLastTick >= FOG_START_EXP_RATIO)) + return; + + if (event.fogMode == 0) { + double v = 1 - fogIntensityLastTick/FOG_START_EXP_RATIO; + //trying to smooth out jump from linear to exponential + GL11.glFogi(GL11.GL_FOG_MODE, GL11.GL_LINEAR); + GL11.glFogf(GL11.GL_FOG_START, (float) ((END_MAX_DISTANCE-20) * 0.75F * v + 20)); + GL11.glFogf(GL11.GL_FOG_END, (float) (END_MAX_DISTANCE * (0.75F + v * 0.25F))); + } + //else if ( event.fogMode < 0) { } + } + + @SubscribeEvent(priority = EventPriority.LOWEST) + public void renderGTPollutionFog(EntityViewRenderEvent.FogDensity event) { + if (!DEBUG && Minecraft.getMinecraft().thePlayer.capabilities.isCreativeMode) + return; + + if (event.entity.isPotionActive(Potion.blindness) || + (fogIntensityLastTick < FOG_START_EXP_RATIO) || + event.block.getMaterial() == Material.water || + event.block.getMaterial() == Material.lava + ) + return; + + GL11.glFogi(GL11.GL_FOG_MODE, GL11.GL_EXP2); + event.density = (float) Math.pow(fogIntensityLastTick - FOG_START_EXP_RATIO, .75F)/5 + 0.01F; + event.setCanceled(true); + } + + private double lastUpdate = 0; + @SubscribeEvent(priority = EventPriority.HIGHEST) + public void onRenderTick(TickEvent.RenderTickEvent event) { + Minecraft mc = Minecraft.getMinecraft(); + if (mc == null) + return; + EntityClientPlayerMP player = mc.thePlayer; + if (player == null) + return; + + if (event.phase == TickEvent.Phase.START) { + if (event.renderTickTime < lastUpdate) + lastUpdate = lastUpdate - 1; + float step = (float) ((event.renderTickTime - lastUpdate) / 50); + lastUpdate = event.renderTickTime; + + float fogIntensity = (playerPollution-FOG_START_AT_POLLUTION)/ (float) FOG_MAX_AT_POLLUTION; + if (fogIntensity > 1) fogIntensity = 1; + else if (fogIntensity < 0) fogIntensity = 0; + + double e = fogIntensity-fogIntensityLastTick; + if (e != 0) { + if (e > 0.2) e = 0.2D; + else if (e < -0.5) e = - 0.5D; + + if (e > 0.001D || e < -0.001D) + fogIntensityLastTick += step *e; + else + fogIntensityLastTick = fogIntensity; + } + } + else if (DEBUG) { + drawPollution("Intensity: " + (fogIntensityLastTick * 10000), 0); + drawPollution("Pollution: " + pollutionMap.getPollution(Minecraft.getMinecraft().thePlayer.lastTickPosX, Minecraft.getMinecraft().thePlayer.lastTickPosZ), 20); + drawPollution("Density: " + ((float)(Math.pow(fogIntensityLastTick - FOG_START_EXP_RATIO, .75F)/5 + 0.01F)* 10000), 40); + } + } + + // Adding dirt particles in the air + @SubscribeEvent(priority = EventPriority.HIGHEST) + public void onClientTick(TickEvent.ClientTickEvent event) { + Minecraft mc = Minecraft.getMinecraft(); + if (mc == null) + return; + EntityClientPlayerMP player = mc.thePlayer; + if (player == null || (player.capabilities.isCreativeMode && !DEBUG)) + return; + + World w = player.worldObj; + playerPollution = pollutionMap.getPollution(player.lastTickPosX, player.lastTickPosZ); + + float intensity = ((float) playerPollution - PARTICLES_POLLUTION_START) / PARTICLES_POLLUTION_END; + if (intensity < 0) + return; + else if (intensity > 1) + intensity = 1; + else + intensity *= intensity; + + int x = MathHelper.floor_double(player.posX); + int y = MathHelper.floor_double(player.posY); + int z = MathHelper.floor_double(player.posZ); + + int numParticles = Math.round(intensity * PARTICLES_MAX_NUM); + + for (int l = 0; l < numParticles; ++l) { + int i1 = x + w.rand.nextInt(16) - w.rand.nextInt(16); + int j1 = y + w.rand.nextInt(16) - w.rand.nextInt(16); + int k1 = z + w.rand.nextInt(16) - w.rand.nextInt(16); + Block block = w.getBlock(i1, j1, k1); + + if (block.getMaterial() == Material.air) { + EntityFX fx = new GT_EntityFXPollution(w, (float) i1 + w.rand.nextFloat(), (float) j1 + w.rand.nextFloat(), (float) k1 + w.rand.nextFloat()); + mc.effectRenderer.addEffect(fx); + } + } + } + + private void drawPollution(String text, int off){ + GL11.glPushMatrix(); + GL11.glEnable(GL11.GL_BLEND); + OpenGlHelper.glBlendFunc(770, 771, 1, 0); + Minecraft.getMinecraft().fontRenderer.drawStringWithShadow(text, 0, off, 0xFFFFFFFF); + GL11.glDisable(GL11.GL_BLEND); + GL11.glPopMatrix(); + } +} |