aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/common/render/PollutionRenderer.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/gregtech/common/render/PollutionRenderer.java')
-rw-r--r--src/main/java/gregtech/common/render/PollutionRenderer.java251
1 files changed, 251 insertions, 0 deletions
diff --git a/src/main/java/gregtech/common/render/PollutionRenderer.java b/src/main/java/gregtech/common/render/PollutionRenderer.java
new file mode 100644
index 0000000000..3b97fc820f
--- /dev/null
+++ b/src/main/java/gregtech/common/render/PollutionRenderer.java
@@ -0,0 +1,251 @@
+package gregtech.common.render;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.entity.EntityClientPlayerMP;
+import net.minecraft.client.particle.EntityFX;
+import net.minecraft.client.renderer.OpenGlHelper;
+import net.minecraft.potion.Potion;
+import net.minecraft.util.MathHelper;
+import net.minecraft.world.ChunkCoordIntPair;
+import net.minecraft.world.World;
+import net.minecraftforge.client.event.EntityViewRenderEvent;
+import net.minecraftforge.event.world.WorldEvent;
+
+import org.lwjgl.opengl.GL11;
+
+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.GTMod;
+import gregtech.common.entities.EntityFXPollution;
+import gregtech.common.misc.GTClientPollutionMap;
+
+@SideOnly(Side.CLIENT)
+public class PollutionRenderer {
+
+ private static GTClientPollutionMap pollutionMap;
+ private static int playerPollution = 0;
+
+ private static final 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 PollutionRenderer() {
+ pollutionMap = new GTClientPollutionMap();
+ }
+
+ 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);
+ }
+
+ public static int getKnownPollution(int x, int z) {
+ return pollutionMap.getPollution(x, z);
+ }
+
+ @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 (!GTMod.gregtechproxy.mRenderPollutionFog) return;
+
+ if ((!DEBUG && Minecraft.getMinecraft().thePlayer.capabilities.isCreativeMode)
+ || (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 (!GTMod.gregtechproxy.mRenderPollutionFog) return;
+
+ 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) {
+ if (!GTMod.gregtechproxy.mRenderDirtParticles) return;
+ 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 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();
+ }
+}