diff --git a/src/main/java/com/hbm/handler/radiation/ChunkRadiationHandler3D.java b/src/main/java/com/hbm/handler/radiation/ChunkRadiationHandler3D.java new file mode 100644 index 000000000..5c81a416e --- /dev/null +++ b/src/main/java/com/hbm/handler/radiation/ChunkRadiationHandler3D.java @@ -0,0 +1,178 @@ +package com.hbm.handler.radiation; + +import java.util.HashMap; +import java.util.Map.Entry; + +import net.minecraft.util.MathHelper; +import net.minecraft.world.ChunkCoordIntPair; +import net.minecraft.world.World; +import net.minecraftforge.event.world.ChunkDataEvent; +import net.minecraftforge.event.world.ChunkEvent; +import net.minecraftforge.event.world.WorldEvent; + +/** + * A slightly more sophisticated version of the ChunkRadiationHandlerSimple, each chunk has 16 radiation values depending on height. + * The bottom and topmost values extend up to infinity, preventing people from escaping radiation when leaving the build height. + * @author hbm + */ +public class ChunkRadiationHandler3D extends ChunkRadiationHandler { + + private HashMap perWorld = new HashMap(); + + @Override + public float getRadiation(World world, int x, int y, int z) { + ThreeDimRadiationPerWorld radWorld = perWorld.get(world); + + if(radWorld != null) { + ChunkCoordIntPair coords = new ChunkCoordIntPair(x >> 4, z >> 4); + + int yReg = MathHelper.clamp_int(y >> 4, 0, 15); + + Float rad = radWorld.radiation.get(coords)[yReg]; + return rad == null ? 0F : rad; + } + + return 0; + } + + @Override + public void setRadiation(World world, int x, int y, int z, float rad) { + ThreeDimRadiationPerWorld radWorld = perWorld.get(world); + + if(radWorld != null) { + + if(world.blockExists(x, 0, z)) { + + ChunkCoordIntPair coords = new ChunkCoordIntPair(x >> 4, z >> 4); + + int yReg = MathHelper.clamp_int(y >> 4, 0, 15); + + if(radWorld.radiation.containsKey(coords)) { + radWorld.radiation.get(coords)[yReg] = rad; + } + + world.getChunkFromBlockCoords(x, z).isModified = true; + } + } + } + + @Override + public void incrementRad(World world, int x, int y, int z, float rad) { + setRadiation(world, x, y, z, getRadiation(world, x, y, z) + rad); + } + + @Override + public void decrementRad(World world, int x, int y, int z, float rad) { + setRadiation(world, x, y, z, Math.max(getRadiation(world, x, y, z) - rad, 0)); + } + + @Override + public void updateSystem() { + + for(Entry entry : perWorld.entrySet()) { + + HashMap radiation = entry.getValue().radiation; + HashMap buff = new HashMap(radiation); + radiation.clear(); + + for(Entry chunk : buff.entrySet()) { + + ChunkCoordIntPair coord = chunk.getKey(); + + for(int y = 0; y < 16; y++) { + + for(int i = -1; i <= 1; i++) { + for(int j = -1; j <= 1; j++) { + for(int k = -1; k <= 1; k++) { + + int type = Math.abs(i) + Math.abs(j) + Math.abs(k); + + if(type == 3) + continue; + + float percent = type == 0 ? 0.6F : type == 1 ? 0.075F : 0.025F; + + ChunkCoordIntPair newCoord = new ChunkCoordIntPair(coord.chunkXPos + i, coord.chunkZPos + k); + + if(buff.containsKey(newCoord)) { + int newY = MathHelper.clamp_int(y + j, 0, 15); + Float[] vals = radiation.get(newCoord); + float rad = vals[newY]; + float newRad = vals[newY] + chunk.getValue()[newY] * percent; + vals[newY] = Math.max(0F, newRad * 0.999F - 0.05F); + } + } + } + } + } + } + } + } + + @Override + public void receiveWorldLoad(WorldEvent.Load event) { + if(!event.world.isRemote) + perWorld.put(event.world, new ThreeDimRadiationPerWorld()); + } + + @Override + public void receiveWorldUnload(WorldEvent.Unload event) { + if(!event.world.isRemote) + perWorld.remove(event.world); + } + + private static final String NBT_KEY_CHUNK_RADIATION = "hfr_3d_radiation_"; + + @Override + public void receiveChunkLoad(ChunkDataEvent.Load event) { + + if(!event.world.isRemote) { + ThreeDimRadiationPerWorld radWorld = perWorld.get(event.world); + + if(radWorld != null) { + + Float[] vals = new Float[16]; + + for(int i = 0; i < 16; i++) { + vals[i] = event.getData().getFloat(NBT_KEY_CHUNK_RADIATION + i); + } + + radWorld.radiation.put(event.getChunk().getChunkCoordIntPair(), vals); + } + } + } + + @Override + public void receiveChunkSave(ChunkDataEvent.Save event) { + + if(!event.world.isRemote) { + ThreeDimRadiationPerWorld radWorld = perWorld.get(event.world); + + if(radWorld != null) { + Float[] vals = radWorld.radiation.get(event.getChunk().getChunkCoordIntPair()); + + for(int i = 0; i < 16; i++) { + float rad = vals[i] == null ? 0F : vals[i]; + event.getData().setFloat(NBT_KEY_CHUNK_RADIATION + i, rad); + } + } + } + } + + @Override + public void receiveChunkUnload(ChunkEvent.Unload event) { + + if(!event.world.isRemote) { + ThreeDimRadiationPerWorld radWorld = perWorld.get(event.world); + + if(radWorld != null) { + radWorld.radiation.remove(event.getChunk()); + } + } + } + + public static class ThreeDimRadiationPerWorld { + + public HashMap radiation = new HashMap(); + } +} diff --git a/src/main/java/com/hbm/handler/radiation/ChunkRadiationHandlerSimple.java b/src/main/java/com/hbm/handler/radiation/ChunkRadiationHandlerSimple.java index 35f46becb..bf0023392 100644 --- a/src/main/java/com/hbm/handler/radiation/ChunkRadiationHandlerSimple.java +++ b/src/main/java/com/hbm/handler/radiation/ChunkRadiationHandlerSimple.java @@ -9,6 +9,10 @@ import net.minecraftforge.event.world.ChunkDataEvent; import net.minecraftforge.event.world.ChunkEvent; import net.minecraftforge.event.world.WorldEvent; +/** + * Most basic implementation of a chunk radiation system: Each chunk has a radiation value which spreads out to its neighbors. + * @author hbm + */ public class ChunkRadiationHandlerSimple extends ChunkRadiationHandler { private HashMap perWorld = new HashMap(); @@ -124,9 +128,6 @@ public class ChunkRadiationHandlerSimple extends ChunkRadiationHandler { Float val = radWorld.radiation.get(event.getChunk().getChunkCoordIntPair()); float rad = val == null ? 0F : val; event.getData().setFloat(NBT_KEY_CHUNK_RADIATION, rad); - - if(rad > 0) { - } } } } diff --git a/src/main/java/com/hbm/util/ContaminationUtil.java b/src/main/java/com/hbm/util/ContaminationUtil.java index e50bfae4b..867111691 100644 --- a/src/main/java/com/hbm/util/ContaminationUtil.java +++ b/src/main/java/com/hbm/util/ContaminationUtil.java @@ -1,5 +1,6 @@ package com.hbm.util; +import com.hbm.config.GeneralConfig; import com.hbm.entity.mob.EntityNuclearCreeper; import com.hbm.entity.mob.EntityQuackos; import com.hbm.extprop.HbmLivingProps; @@ -299,7 +300,7 @@ public class ContaminationUtil { return false; } - if(hazard == HazardType.RADIATION && isRadImmune(entity)) + if(hazard == HazardType.RADIATION && (isRadImmune(entity) || !GeneralConfig.enableRads)) return false; switch(hazard) {