279 lines
12 KiB
Java
279 lines
12 KiB
Java
package gregtech.common;
|
|
|
|
import cpw.mods.fml.common.gameevent.TickEvent;
|
|
import gregtech.GT_Mod;
|
|
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
|
|
import gregtech.api.objects.XSTR;
|
|
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.init.Blocks;
|
|
import net.minecraft.potion.Potion;
|
|
import net.minecraft.potion.PotionEffect;
|
|
import net.minecraft.util.AxisAlignedBB;
|
|
import net.minecraft.world.ChunkCoordIntPair;
|
|
import net.minecraft.world.ChunkPosition;
|
|
import net.minecraft.world.World;
|
|
import net.minecraft.world.chunk.Chunk;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
|
|
import static gregtech.common.GT_Proxy.*;
|
|
|
|
//import net.minecraft.entity.EntityLiving;
|
|
|
|
public class GT_Pollution {
|
|
/**
|
|
* Pollution dispersion until effects start:
|
|
* Calculation: ((Limit * 0.01) + 2000) * (4 <- spreading rate)
|
|
*
|
|
* SMOG(500k) 466.7 pollution/sec
|
|
* Poison(750k) 633,3 pollution/sec
|
|
* Dying Plants(1mio) 800 pollution/sec
|
|
* Sour Rain(1.5mio) 1133.3 pollution/sec
|
|
*
|
|
* Pollution producers (pollution/sec)
|
|
* Bronze Boiler(20)
|
|
* Lava Boiler(20)
|
|
* High Pressure Boiler(20)
|
|
* Bronze Blast Furnace(50)
|
|
* Diesel Generator(40/80/160)
|
|
* Gas Turbine(20/40/80)
|
|
* Charcoal Pile(100)
|
|
*
|
|
* Large Diesel Engine(320)
|
|
* Electric Blast Furnace(100)
|
|
* Implosion Compressor(2000)
|
|
* Large Boiler(240)
|
|
* Large Gas Turbine(160)
|
|
* Multi Smelter(100)
|
|
* Pyrolyse Oven(200)
|
|
*
|
|
* Machine Explosion(100,000)
|
|
*
|
|
* Muffler Hatch Pollution reduction:
|
|
* LV (0%), MV (30%), HV (52%), EV (66%), IV (76%), LuV (84%), ZPM (89%), UV (92%), MAX (95%)
|
|
*/
|
|
private static XSTR tRan = new XSTR();
|
|
private List<ChunkCoordIntPair> pollutionList = new ArrayList<>();//chunks left to process
|
|
private HashMap<ChunkCoordIntPair,int[]> chunkData;//link to chunk data that is saved/loaded
|
|
private int operationsPerTick=0;//how much chunks should be processed in each cycle
|
|
private static final short cycleLen=1200;
|
|
private final World aWorld;
|
|
public static int mPlayerPollution;
|
|
|
|
public GT_Pollution(World world){
|
|
aWorld=world;
|
|
chunkData=dimensionWiseChunkData.get(aWorld.provider.dimensionId);
|
|
if(chunkData==null){
|
|
chunkData=new HashMap<>(1024);
|
|
dimensionWiseChunkData.put(world.provider.dimensionId,chunkData);
|
|
}
|
|
dimensionWisePollution.put(aWorld.provider.dimensionId,this);
|
|
}
|
|
|
|
public static void onWorldTick(TickEvent.WorldTickEvent aEvent){//called from proxy
|
|
//return if pollution disabled
|
|
if(!GT_Mod.gregtechproxy.mPollution) return;
|
|
final GT_Pollution pollutionInstance = dimensionWisePollution.get(aEvent.world.provider.dimensionId);
|
|
if(pollutionInstance==null)return;
|
|
pollutionInstance.tickPollutionInWorld((int)(aEvent.world.getTotalWorldTime()%cycleLen));
|
|
}
|
|
|
|
private void tickPollutionInWorld(int aTickID){//called from method above
|
|
//gen data set
|
|
if(aTickID==0){
|
|
pollutionList = new ArrayList<>(chunkData.keySet());
|
|
//set operations per tick
|
|
if(pollutionList.size()>0) operationsPerTick =(pollutionList.size()/cycleLen);
|
|
else operationsPerTick=0;//SANity
|
|
}
|
|
|
|
for(int chunksProcessed=0;chunksProcessed<=operationsPerTick;chunksProcessed++){
|
|
if(pollutionList.size()==0)break;//no more stuff to do
|
|
ChunkCoordIntPair actualPos=pollutionList.remove(pollutionList.size()-1);//faster
|
|
//add default data if missing
|
|
if(!chunkData.containsKey(actualPos)) chunkData.put(actualPos,getDefaultChunkDataOnCreation());
|
|
//get pollution
|
|
int tPollution = chunkData.get(actualPos)[GTPOLLUTION];
|
|
//remove some
|
|
tPollution = (int)(0.99f*tPollution);
|
|
tPollution -= 2000;
|
|
|
|
if(tPollution<=0) tPollution = 0;//SANity check
|
|
else if(tPollution>50000){//Spread Pollution
|
|
|
|
ChunkCoordIntPair[] tNeighbors = new ChunkCoordIntPair[4];//array is faster
|
|
tNeighbors[0]=(new ChunkCoordIntPair(actualPos.chunkXPos+1,actualPos.chunkZPos));
|
|
tNeighbors[1]=(new ChunkCoordIntPair(actualPos.chunkXPos-1,actualPos.chunkZPos));
|
|
tNeighbors[2]=(new ChunkCoordIntPair(actualPos.chunkXPos,actualPos.chunkZPos+1));
|
|
tNeighbors[3]=(new ChunkCoordIntPair(actualPos.chunkXPos,actualPos.chunkZPos-1));
|
|
for(ChunkCoordIntPair neighborPosition : tNeighbors){
|
|
if(!chunkData.containsKey(neighborPosition)) chunkData.put(neighborPosition,getDefaultChunkDataOnCreation());
|
|
|
|
int neighborPollution = chunkData.get(neighborPosition)[GTPOLLUTION];
|
|
if(neighborPollution*6 < tPollution*5){//METHEMATICS...
|
|
int tDiff = tPollution - neighborPollution;
|
|
tDiff = tDiff/10;
|
|
neighborPollution += tDiff;
|
|
tPollution -= tDiff;
|
|
chunkData.get(neighborPosition)[GTPOLLUTION] = neighborPollution;
|
|
}
|
|
}
|
|
|
|
|
|
//Create Pollution effects
|
|
if(tPollution > GT_Mod.gregtechproxy.mPollutionSmogLimit) {
|
|
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)) {
|
|
switch (tRan.nextInt(3)) {
|
|
default:
|
|
tEnt.addPotionEffect(new PotionEffect(Potion.digSlowdown.id, Math.min(tPollution / 1000, 1000), tPollution / 400000));
|
|
case 1:
|
|
tEnt.addPotionEffect(new PotionEffect(Potion.weakness.id, Math.min(tPollution / 1000, 1000), tPollution / 400000));
|
|
case 2:
|
|
tEnt.addPotionEffect(new PotionEffect(Potion.moveSlowdown.id, Math.min(tPollution / 1000, 1000), tPollution / 400000));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//Poison effects
|
|
if (tPollution > GT_Mod.gregtechproxy.mPollutionPoisonLimit) {
|
|
//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 (!GT_Utility.isWearingFullGasHazmat(tEnt)) {
|
|
switch (tRan.nextInt(4)) {
|
|
default:
|
|
tEnt.addPotionEffect(new PotionEffect(Potion.hunger.id, tPollution / 500000));
|
|
case 1:
|
|
tEnt.addPotionEffect(new PotionEffect(Potion.confusion.id, Math.min(tPollution / 2000, 1000), 1));
|
|
case 2:
|
|
tEnt.addPotionEffect(new PotionEffect(Potion.poison.id, Math.min(tPollution / 4000, 1000), tPollution / 500000));
|
|
case 3:
|
|
tEnt.addPotionEffect(new PotionEffect(Potion.blindness.id, Math.min(tPollution / 2000, 1000), 1));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//killing plants
|
|
if (tPollution > GT_Mod.gregtechproxy.mPollutionVegetationLimit) {
|
|
int f = 20;
|
|
for (; f < (tPollution / 25000); f++) {
|
|
int x = (actualPos.chunkXPos << 4) + tRan.nextInt(16);
|
|
int y = 60 + (-f + tRan.nextInt(f * 2 + 1));
|
|
int z = (actualPos.chunkZPos << 4) + tRan.nextInt(16);
|
|
damageBlock(aWorld, x, y, z, tPollution > GT_Mod.gregtechproxy.mPollutionSourRainLimit);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//Write new pollution to Hashmap !!!
|
|
chunkData.get(actualPos)[GTPOLLUTION] = tPollution;
|
|
}
|
|
}
|
|
|
|
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) {
|
|
tBlock.dropBlockAsItem(world, x, y, z, tMeta, 0);
|
|
world.setBlockToAir(x, y, z);
|
|
}
|
|
if (tBlock == Blocks.tallgrass)
|
|
world.setBlock(x, y, z, Blocks.deadbush);
|
|
if (tBlock == Blocks.vine) {
|
|
tBlock.dropBlockAsItem(world, x, y, z, tMeta, 0);
|
|
world.setBlockToAir(x, y, z);
|
|
}
|
|
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 ||
|
|
tBlock == Blocks.potatoes || tBlock == Blocks.pumpkin || tBlock == Blocks.pumpkin_stem) {
|
|
tBlock.dropBlockAsItem(world, x, y, z, tMeta, 0);
|
|
world.setBlockToAir(x, y, z);
|
|
}
|
|
if (tBlock == Blocks.sapling || tBlock.getMaterial() == Material.plants)
|
|
world.setBlock(x, y, z, Blocks.deadbush);
|
|
if (tBlock == Blocks.cocoa) {
|
|
tBlock.dropBlockAsItem(world, x, y, z, tMeta, 0);
|
|
world.setBlockToAir(x, y, z);
|
|
}
|
|
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);
|
|
if(tBlock == Blocks.farmland || tBlock == Blocks.dirt){
|
|
world.setBlock(x, y, z, Blocks.sand);
|
|
}
|
|
|
|
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); }
|
|
else if(tBlock == Blocks.gravel){world.setBlock(x, y, z, Blocks.sand); }
|
|
}
|
|
}
|
|
|
|
public static void addPollution(IGregTechTileEntity te, int aPollution){
|
|
addPollution(te.getWorld().getChunkFromBlockCoords(te.getXCoord(),te.getZCoord()), aPollution);
|
|
}
|
|
|
|
public static void addPollution(Chunk ch, int aPollution){
|
|
if(!GT_Mod.gregtechproxy.mPollution)return;
|
|
HashMap<ChunkCoordIntPair,int[]> dataMap=dimensionWiseChunkData.get(ch.worldObj.provider.dimensionId);
|
|
if(dataMap==null){
|
|
dataMap=new HashMap<>(1024);
|
|
dimensionWiseChunkData.put(ch.worldObj.provider.dimensionId,dataMap);
|
|
}
|
|
int[] dataArr=dataMap.get(ch.getChunkCoordIntPair());
|
|
if(dataArr==null){
|
|
dataArr=getDefaultChunkDataOnCreation();
|
|
dataMap.put(ch.getChunkCoordIntPair(),dataArr);
|
|
}
|
|
dataArr[GTPOLLUTION]+=aPollution;
|
|
if(dataArr[GTPOLLUTION]<0)dataArr[GTPOLLUTION]=0;
|
|
}
|
|
|
|
public static int getPollution(IGregTechTileEntity te){
|
|
return getPollution(te.getWorld().getChunkFromBlockCoords(te.getXCoord(),te.getZCoord()));
|
|
}
|
|
|
|
public static int getPollution(Chunk ch){
|
|
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;
|
|
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){
|
|
//The abuse of ChunkPosition to store block position and dim...
|
|
//is just bad expacially when that is both used to store ChunkPos and BlockPos depeending on context
|
|
addPollution(aWorld.getChunkFromBlockCoords(aPos.chunkPosX,aPos.chunkPosZ),aPollution);
|
|
}
|
|
}
|