aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/common/GT_Pollution.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/gregtech/common/GT_Pollution.java')
-rw-r--r--src/main/java/gregtech/common/GT_Pollution.java130
1 files changed, 94 insertions, 36 deletions
diff --git a/src/main/java/gregtech/common/GT_Pollution.java b/src/main/java/gregtech/common/GT_Pollution.java
index 865fa83f7e..afaac41650 100644
--- a/src/main/java/gregtech/common/GT_Pollution.java
+++ b/src/main/java/gregtech/common/GT_Pollution.java
@@ -9,6 +9,7 @@ import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.net.GT_Packet_Pollution;
import gregtech.api.util.GT_ChunkAssociatedData;
import gregtech.api.util.GT_Utility;
+import gregtech.common.render.GT_PollutionRenderer;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.entity.EntityLivingBase;
@@ -27,12 +28,16 @@ import net.minecraftforge.event.world.ChunkDataEvent;
import net.minecraftforge.event.world.ChunkWatchEvent;
import net.minecraftforge.event.world.WorldEvent;
+import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
+import java.util.function.Consumer;
import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
import static gregtech.common.GT_Proxy.dimensionWisePollution;
@@ -73,11 +78,12 @@ public class GT_Pollution {
* Muffler Hatch Pollution reduction: ** inaccurate **
* LV (0%), MV (30%), HV (52%), EV (66%), IV (76%), LuV (84%), ZPM (89%), UV (92%), MAX (95%)
*/
- private List<ChunkCoordIntPair> pollutionList = new ArrayList<>();//chunks left to process
- private final List<ChunkCoordIntPair> chunkData = new ArrayList<>();//link to chunk data that is saved/loaded
+ private List<ChunkCoordIntPair> pollutionList = new ArrayList<>();//chunks left to process in this cycle
+ private final Set<ChunkCoordIntPair> pollutedChunks = new HashSet<>();// a global list of all chunks with positive pollution
private int operationsPerTick = 0;//how much chunks should be processed in each cycle
private static final short cycleLen = 1200;
private final World world;
+ private boolean blank = true;
public static int mPlayerPollution;
private static int POLLUTIONPACKET_MINVALUE = 1000;
@@ -96,6 +102,7 @@ public class GT_Pollution {
public static void onWorldTick(TickEvent.WorldTickEvent aEvent) {//called from proxy
//return if pollution disabled
if (!GT_Mod.gregtechproxy.mPollution) return;
+ if (aEvent.phase == TickEvent.Phase.START) return;
final GT_Pollution pollutionInstance = dimensionWisePollution.get(aEvent.world.provider.dimensionId);
if (pollutionInstance == null) return;
pollutionInstance.tickPollutionInWorld((int) (aEvent.world.getTotalWorldTime() % cycleLen));
@@ -103,16 +110,18 @@ public class GT_Pollution {
private void tickPollutionInWorld(int aTickID) {//called from method above
//gen data set
- if (aTickID == 0) {
+ if (aTickID == 0 || blank) {
// make a snapshot of what to work on
- // counterintuitive as it seems, but this is the fastest way java collections framework offers us.
- pollutionList = new ArrayList<>(chunkData);
+ pollutionList = new ArrayList<>(pollutedChunks);
//set operations per tick
- if (pollutionList.size() > 0) operationsPerTick = (pollutionList.size() / cycleLen);
- else operationsPerTick = 0;//SANity
+ if (pollutionList.size() > 0)
+ operationsPerTick = Math.max(1, pollutionList.size() / cycleLen);
+ else
+ operationsPerTick = 0; //SANity
+ blank = false;
}
- for (int chunksProcessed = 0; chunksProcessed <= operationsPerTick; chunksProcessed++) {
+ 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
//get pollution
@@ -120,10 +129,8 @@ public class GT_Pollution {
int tPollution = currentData.getAmount();
//remove some
tPollution = (int) (0.9945f * tPollution);
- //tPollution -= 2000;//This does not really matter...
- if (tPollution <= 0) tPollution = 0;//SANity check
- else if (tPollution > 400000) {//Spread Pollution
+ if (tPollution > 400000) {//Spread Pollution
ChunkCoordIntPair[] tNeighbors = new ChunkCoordIntPair[4];//array is faster
tNeighbors[0] = (new ChunkCoordIntPair(actualPos.chunkXPos + 1, actualPos.chunkZPos));
@@ -138,7 +145,7 @@ public class GT_Pollution {
tDiff = tDiff / 20;
neighborPollution = GT_Utility.safeInt((long) neighborPollution + tDiff);//tNPol += tDiff;
tPollution -= tDiff;
- neighbor.setAmount(neighborPollution);
+ setChunkPollution(neighborPosition, neighborPollution);
}
}
@@ -200,7 +207,7 @@ public class GT_Pollution {
}
}
//Write new pollution to Hashmap !!!
- currentData.setAmount(tPollution);
+ setChunkPollution(actualPos, tPollution);
//Send new value to players nearby
if (tPollution > POLLUTIONPACKET_MINVALUE) {
@@ -210,6 +217,10 @@ public class GT_Pollution {
}
}
+ private void setChunkPollution(ChunkCoordIntPair coord, int pollution) {
+ mutatePollution(world, coord.chunkXPos, coord.chunkZPos, c -> c.setAmount(pollution), pollutedChunks);
+ }
+
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);
@@ -265,23 +276,81 @@ public class GT_Pollution {
}
}
+ private static GT_Pollution getPollutionManager(World world) {
+ return dimensionWisePollution.computeIfAbsent(world.provider.dimensionId, i -> new GT_Pollution(world));
+ }
+
+ /** @see #addPollution(World, int, int, int) */
public static void addPollution(IGregTechTileEntity te, int aPollution) {
- addPollution(te.getWorld().getChunkFromBlockCoords(te.getXCoord(), te.getZCoord()), aPollution);
+ if (!GT_Mod.gregtechproxy.mPollution || aPollution == 0 || te.isClientSide()) return;
+ mutatePollution(te.getWorld(), te.getXCoord() >> 4, te.getZCoord() >> 4, d -> d.changeAmount(aPollution), null);
}
+ /** @see #addPollution(World, int, int, int) */
public static void addPollution(Chunk ch, int aPollution) {
- if (!GT_Mod.gregtechproxy.mPollution || aPollution == 0) return;
- STORAGE.get(ch).changeAmount(aPollution);
+ if (!GT_Mod.gregtechproxy.mPollution || aPollution == 0 || ch.worldObj.isRemote) return;
+ mutatePollution(ch.worldObj, ch.xPosition, ch.zPosition, d -> d.changeAmount(aPollution), null);
+ }
+
+ /**
+ * Add some pollution to given chunk. Can pass in negative to remove pollution.
+ * Will clamp the final pollution number to 0 if it would be changed into negative.
+ *
+ * @param w world to modify. do nothing if it's a client world
+ * @param chunkX chunk coordinate X, i.e. blockX >> 4
+ * @param chunkZ chunk coordinate Z, i.e. blockZ >> 4
+ * @param aPollution desired delta. Positive means the pollution in chunk would go higher.
+ */
+ public static void addPollution(World w, int chunkX, int chunkZ, int aPollution) {
+ if (!GT_Mod.gregtechproxy.mPollution || aPollution == 0 || w.isRemote) return;
+ mutatePollution(w, chunkX, chunkZ, d -> d.changeAmount(aPollution), null);
+ }
+
+ private static void mutatePollution(World world, int x, int z, Consumer<ChunkData> mutator, @Nullable Set<ChunkCoordIntPair> chunks) {
+ ChunkData data = STORAGE.get(world, x, z);
+ boolean hadPollution = data.getAmount() > 0;
+ mutator.accept(data);
+ boolean hasPollution = data.getAmount() > 0;
+ if (hasPollution != hadPollution) {
+ if (chunks == null)
+ chunks = getPollutionManager(world).pollutedChunks;
+ if (hasPollution)
+ chunks.add(new ChunkCoordIntPair(x, z));
+ else
+ chunks.remove(new ChunkCoordIntPair(x, z));
+ }
}
+ /** @see #getPollution(World, int, int) */
public static int getPollution(IGregTechTileEntity te) {
- return getPollution(te.getWorld().getChunkFromBlockCoords(te.getXCoord(), te.getZCoord()));
+ return getPollution(te.getWorld(), te.getXCoord() >> 4, te.getZCoord() >> 4);
}
+ /** @see #getPollution(World, int, int) */
public static int getPollution(Chunk ch) {
+ return getPollution(ch.worldObj, ch.xPosition, ch.zPosition);
+ }
+
+ /**
+ * Get the pollution in specified chunk
+ * @param w world to look in. can be a client world, but that limits the knowledge to what server side send us
+ * @param chunkX chunk coordinate X, i.e. blockX >> 4
+ * @param chunkZ chunk coordinate Z, i.e. blockZ >> 4
+ * @return pollution amount. may be 0 if pollution is disabled, or if it's a client world and server did not send
+ * us info about this chunk
+ */
+ public static int getPollution(World w, int chunkX, int chunkZ) {
if (!GT_Mod.gregtechproxy.mPollution)
return 0;
- return STORAGE.get(ch).getAmount();
+ if (w.isRemote)
+ // it really should be querying the client side stuff instead
+ return GT_PollutionRenderer.getKnownPollution(chunkX << 4, chunkZ << 4);
+ return STORAGE.get(w, chunkX, chunkZ).getAmount();
+ }
+
+ @Deprecated
+ public static int getPollution(ChunkCoordIntPair aCh, int aDim) {
+ return getPollution(DimensionManager.getWorld(aDim), aCh.chunkXPos, aCh.chunkZPos);
}
public static boolean hasPollution(Chunk ch) {
@@ -290,12 +359,6 @@ public class GT_Pollution {
return STORAGE.isCreated(ch.worldObj, ch.getChunkCoordIntPair()) && STORAGE.get(ch).getAmount() > 0;
}
- public static int getPollution(ChunkCoordIntPair aCh, int aDim) {
- if (!GT_Mod.gregtechproxy.mPollution)
- return 0;
- return STORAGE.get(DimensionManager.getWorld(aDim), aCh.chunkXPos, aCh.chunkZPos).getAmount();
- }
-
//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) {
@@ -323,7 +386,8 @@ public class GT_Pollution {
@SubscribeEvent
public void onWorldLoad(WorldEvent.Load e) {
// super class loads everything lazily. We force it to load them all.
- STORAGE.loadAll(e.world);
+ if (!e.world.isRemote)
+ STORAGE.loadAll(e.world);
}
}
@@ -340,15 +404,14 @@ public class GT_Pollution {
@Override
protected ChunkData readElement(DataInput input, int version, World world, int chunkX, int chunkZ) throws IOException {
+ if (version != 0)
+ throw new IOException("Region file corrupted");
ChunkData data = new ChunkData(input.readInt());
- getChunkData(world).add(new ChunkCoordIntPair(chunkX, chunkZ));
+ if (data.getAmount() > 0)
+ getPollutionManager(world).pollutedChunks.add(new ChunkCoordIntPair(chunkX, chunkZ));
return data;
}
- private List<ChunkCoordIntPair> getChunkData(World world) {
- return dimensionWisePollution.computeIfAbsent(world.provider.dimensionId, i -> new GT_Pollution(world)).chunkData;
- }
-
@Override
protected ChunkData createElement(World world, int chunkX, int chunkZ) {
return new ChunkData();
@@ -359,11 +422,6 @@ public class GT_Pollution {
super.loadAll(w);
}
- public void set(World world, ChunkCoordIntPair coord, ChunkData data) {
- set(world, coord.chunkXPos, coord.chunkZPos, data);
- getChunkData(world).add(coord);
- }
-
public boolean isCreated(World world, ChunkCoordIntPair coord) {
return isCreated(world.provider.dimensionId, coord.chunkXPos, coord.chunkZPos);
}
@@ -377,7 +435,7 @@ public class GT_Pollution {
}
private ChunkData(int amount) {
- this.amount = amount;
+ this.amount = Math.max(0, amount);
}
/**