mirror of
https://github.com/HbmMods/Hbm-s-Nuclear-Tech-GIT.git
synced 2026-01-25 10:32:49 +00:00
PRISM pt. 2
This commit is contained in:
parent
c645889998
commit
5010f8812b
@ -1,17 +1,22 @@
|
||||
package com.hbm.handler.radiation;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.hbm.lib.Library;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.world.ChunkCoordIntPair;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
import net.minecraftforge.event.world.ChunkDataEvent;
|
||||
import net.minecraftforge.event.world.ChunkEvent;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
|
||||
/**
|
||||
* The PRISM system aims to make a semi-realistic containment system with simplified and variable resistance values.
|
||||
@ -25,6 +30,12 @@ import net.minecraftforge.common.util.ForgeDirection;
|
||||
* The system's name stems from the "gradient"-like handling of the resistance values per axis, multiple color
|
||||
* gradients make a rainbow, and rainbows come from prisms. Just like a prism, sub-chunks too handle the radiation
|
||||
* going through them differently depending on the angle of approach.
|
||||
* ___
|
||||
* /\ \
|
||||
* / \ \
|
||||
* / \ \
|
||||
* / \ \
|
||||
* /________\__\
|
||||
*
|
||||
* @author hbm
|
||||
*
|
||||
@ -34,6 +45,9 @@ public class ChunkRadiationHandlerPRISM extends ChunkRadiationHandler {
|
||||
private HashMap<World, RadPerWorld> perWorld = new HashMap();
|
||||
|
||||
public static final float MAX_RADIATION = 1_000_000;
|
||||
private static final String NBT_KEY_CHUNK_RADIATION = "hfr_prism_radiation_";
|
||||
private static final String NBT_KEY_CHUNK_RESISTANCE = "hfr_prism_resistance_";
|
||||
private static final String NBT_KEY_CHUNK_EXISTS = "hfr_prism_exists_";
|
||||
|
||||
@Override
|
||||
public float getRadiation(World world, int x, int y, int z) {
|
||||
@ -56,12 +70,18 @@ public class ChunkRadiationHandlerPRISM extends ChunkRadiationHandler {
|
||||
@Override
|
||||
public void setRadiation(World world, int x, int y, int z, float rad) {
|
||||
|
||||
if(Float.isNaN(rad)) rad = 0;
|
||||
|
||||
RadPerWorld system = perWorld.get(world);
|
||||
|
||||
if(system != null) {
|
||||
ChunkCoordIntPair coords = new ChunkCoordIntPair(x >> 4, z >> 4);
|
||||
int yReg = MathHelper.clamp_int(y >> 4, 0, 15);
|
||||
SubChunk[] subChunks = system.radiation.get(coords);
|
||||
if(subChunks == null) {
|
||||
subChunks = new SubChunk[16];
|
||||
system.radiation.put(coords, subChunks);
|
||||
}
|
||||
if(subChunks[yReg] == null) subChunks[yReg] = new SubChunk().rebuild(world, x, y, z);
|
||||
subChunks[yReg].radiation = MathHelper.clamp_float(rad, 0, MAX_RADIATION);
|
||||
world.getChunkFromBlockCoords(x, z).isModified = true;
|
||||
@ -78,10 +98,79 @@ public class ChunkRadiationHandlerPRISM extends ChunkRadiationHandler {
|
||||
setRadiation(world, x, y, z, getRadiation(world, x, y, z) - rad);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveWorldLoad(WorldEvent.Load event) {
|
||||
if(!event.world.isRemote) perWorld.put(event.world, new RadPerWorld());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveWorldUnload(WorldEvent.Unload event) {
|
||||
if(!event.world.isRemote) perWorld.remove(event.world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveChunkLoad(ChunkDataEvent.Load event) {
|
||||
|
||||
if(!event.world.isRemote) {
|
||||
RadPerWorld radWorld = perWorld.get(event.world);
|
||||
|
||||
if(radWorld != null) {
|
||||
SubChunk[] chunk = new SubChunk[16];
|
||||
|
||||
for(int i = 0; i < 16; i++) {
|
||||
if(!event.getData().getBoolean(NBT_KEY_CHUNK_EXISTS + i)) {
|
||||
chunk[i] = new SubChunk().rebuild(event.world, event.getChunk().xPosition << 4, i << 4, event.getChunk().zPosition << 4);
|
||||
continue;
|
||||
}
|
||||
SubChunk sub = new SubChunk();
|
||||
chunk[i] = sub;
|
||||
sub.radiation = event.getData().getFloat(NBT_KEY_CHUNK_RADIATION + i);
|
||||
for(int j = 0; j < 16; j++) sub.xResist[j] = event.getData().getFloat(NBT_KEY_CHUNK_RESISTANCE + "x_" + j + "_" + i);
|
||||
for(int j = 0; j < 16; j++) sub.yResist[j] = event.getData().getFloat(NBT_KEY_CHUNK_RESISTANCE + "y_" + j + "_" + i);
|
||||
for(int j = 0; j < 16; j++) sub.zResist[j] = event.getData().getFloat(NBT_KEY_CHUNK_RESISTANCE + "z_" + j + "_" + i);
|
||||
}
|
||||
|
||||
radWorld.radiation.put(event.getChunk().getChunkCoordIntPair(), chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveChunkSave(ChunkDataEvent.Save event) {
|
||||
if(!event.world.isRemote) {
|
||||
RadPerWorld radWorld = perWorld.get(event.world);
|
||||
if(radWorld != null) {
|
||||
SubChunk[] chunk = radWorld.radiation.get(event.getChunk().getChunkCoordIntPair());
|
||||
for(int i = 0; i < 16; i++) {
|
||||
SubChunk sub = chunk[i];
|
||||
if(sub != null) {
|
||||
float rad = sub.radiation;
|
||||
event.getData().setFloat(NBT_KEY_CHUNK_RADIATION + i, rad);
|
||||
for(int j = 0; j < 16; j++) event.getData().setFloat(NBT_KEY_CHUNK_RESISTANCE + "x_" + j + "_" + i, sub.xResist[j]);
|
||||
for(int j = 0; j < 16; j++) event.getData().setFloat(NBT_KEY_CHUNK_RESISTANCE + "y_" + j + "_" + i, sub.yResist[j]);
|
||||
for(int j = 0; j < 16; j++) event.getData().setFloat(NBT_KEY_CHUNK_RESISTANCE + "z_" + j + "_" + i, sub.zResist[j]);
|
||||
event.getData().setBoolean(NBT_KEY_CHUNK_EXISTS + i, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveChunkUnload(ChunkEvent.Unload event) {
|
||||
if(!event.world.isRemote) {
|
||||
RadPerWorld radWorld = perWorld.get(event.world);
|
||||
if(radWorld != null) {
|
||||
radWorld.radiation.remove(event.getChunk());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSystem() {
|
||||
|
||||
for(Entry<World, RadPerWorld> entries : perWorld.entrySet()) {
|
||||
World world = entries.getKey();
|
||||
RadPerWorld system = entries.getValue();
|
||||
|
||||
//it would be way to expensive to replace the sub-chunks entirely like with the old system
|
||||
@ -91,15 +180,20 @@ public class ChunkRadiationHandlerPRISM extends ChunkRadiationHandler {
|
||||
sub.radiation = 0;
|
||||
}
|
||||
|
||||
for(Entry<ChunkCoordIntPair, SubChunk[]> chunk : system.radiation.entrySet()) {
|
||||
//has to support additions while iterating
|
||||
Iterator<Entry<ChunkCoordIntPair, SubChunk[]>> it = system.radiation.entrySet().iterator();
|
||||
while(it.hasNext()) {
|
||||
Entry<ChunkCoordIntPair, SubChunk[]> chunk = it.next();
|
||||
if(this.getPrevChunkRadiation(chunk.getValue()) <= 0) continue;
|
||||
for(int i = 0; i < 16; i++) {
|
||||
|
||||
SubChunk sub = chunk.getValue()[i];
|
||||
|
||||
if(sub != null) {
|
||||
if(sub.prevRadiation <= 0 || Float.isNaN(sub.prevRadiation)) continue;
|
||||
float radSpread = 0;
|
||||
for(ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) radSpread += spreadRadiation(sub, i, chunk.getKey(), system.radiation, dir);
|
||||
sub.radiation += (sub.prevRadiation - radSpread) * 0.9F;
|
||||
for(ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) radSpread += spreadRadiation(world, sub, i, chunk.getKey(), chunk.getValue(), system.radiation, dir);
|
||||
sub.radiation += (sub.prevRadiation - radSpread) * 0.95F;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -111,19 +205,45 @@ public class ChunkRadiationHandlerPRISM extends ChunkRadiationHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private static float spreadRadiation(SubChunk source, int y, ChunkCoordIntPair origin, HashMap<ChunkCoordIntPair, SubChunk[]> map, ForgeDirection dir) {
|
||||
/** Returns the amount of radiation spread */
|
||||
private static float spreadRadiation(World world, SubChunk source, int y, ChunkCoordIntPair origin, SubChunk[] chunk, HashMap<ChunkCoordIntPair, SubChunk[]> map, ForgeDirection dir) {
|
||||
|
||||
//TODO
|
||||
float spread = 0.1F;
|
||||
float amount = source.prevRadiation * spread;
|
||||
|
||||
return 0F;
|
||||
if(amount <= 1F) return 0;
|
||||
|
||||
if(dir.offsetY != 0) {
|
||||
if(dir == Library.POS_Y && y == 15) return amount; // out of world
|
||||
if(dir == Library.NEG_Y && y == 0) return amount; // out of world
|
||||
if(chunk[y + dir.offsetY] == null) chunk[y + dir.offsetY] = new SubChunk().rebuild(world, origin.chunkXPos << 4, (y + dir.offsetY) << 4, origin.chunkZPos << 4);
|
||||
SubChunk to = chunk[y + dir.offsetY];
|
||||
return spreadRadiationTo(source, to, amount, dir);
|
||||
} else {
|
||||
ChunkCoordIntPair newPos = new ChunkCoordIntPair(origin.chunkXPos + dir.offsetX, origin.chunkZPos + dir.offsetZ);
|
||||
if(!world.getChunkProvider().chunkExists(newPos.chunkXPos, newPos.chunkZPos)) return amount;
|
||||
SubChunk[] newChunk = map.get(newPos);
|
||||
if(newChunk == null) {
|
||||
newChunk = new SubChunk[16];
|
||||
map.put(newPos, newChunk);
|
||||
}
|
||||
if(newChunk[y] == null) newChunk[y] = new SubChunk().rebuild(world, newPos.chunkXPos << 4, y << 4, newPos.chunkZPos << 4);
|
||||
SubChunk to = newChunk[y];
|
||||
return spreadRadiationTo(source, to, amount, dir);
|
||||
}
|
||||
}
|
||||
|
||||
public static float getTotalChunkRadiation(SubChunk[] chunk) {
|
||||
float rad = 0;
|
||||
for(SubChunk sub : chunk) if(sub != null) rad += sub.radiation;
|
||||
return rad;
|
||||
private static float spreadRadiationTo(SubChunk from, SubChunk to, float amount, ForgeDirection movement) {
|
||||
float resistance = from.getResistanceValue(movement.getOpposite()) + to.getResistanceValue(movement);
|
||||
resistance /= 1_000F;
|
||||
float toMove = Math.min(amount / Math.max(resistance, 1F), amount);
|
||||
to.radiation += toMove;
|
||||
return toMove;
|
||||
}
|
||||
|
||||
//private static float getTotalChunkRadiation(SubChunk[] chunk) { float rad = 0; for(SubChunk sub : chunk) if(sub != null) rad += sub.radiation; return rad; }
|
||||
private static float getPrevChunkRadiation(SubChunk[] chunk) { float rad = 0; for(SubChunk sub : chunk) if(sub != null) rad += sub.prevRadiation; return rad; }
|
||||
|
||||
@Override
|
||||
public void clearSystem(World world) {
|
||||
RadPerWorld system = perWorld.get(world);
|
||||
@ -171,6 +291,7 @@ public class ChunkRadiationHandlerPRISM extends ChunkRadiationHandler {
|
||||
if(iX == sX || iY == sY || iZ == sZ) { //only redo the three affected slices by this position change
|
||||
|
||||
Block b = subChunk.getBlockByExtId(iX, iY, iZ);
|
||||
if(b.getMaterial() == Material.air) continue;
|
||||
float resistance = b.getExplosionResistance(null, world, tX + iX, tY + iY, tZ + iZ, x, y, z);
|
||||
if(iX == sX) xResist[iX] += resistance;
|
||||
if(iY == sY) yResist[iY] += resistance;
|
||||
@ -204,6 +325,7 @@ public class ChunkRadiationHandlerPRISM extends ChunkRadiationHandler {
|
||||
for(int iZ = 0; iZ < 16; iZ ++) {
|
||||
|
||||
Block b = subChunk.getBlockByExtId(iX, iY, iZ);
|
||||
if(b.getMaterial() == Material.air) continue;
|
||||
float resistance = b.getExplosionResistance(null, world, tX + iX, tY + iY, tZ + iZ, x, y, z);
|
||||
xResist[iX] += resistance;
|
||||
yResist[iY] += resistance;
|
||||
|
||||
@ -12,7 +12,7 @@ import net.minecraftforge.event.world.WorldEvent;
|
||||
|
||||
public class ChunkRadiationManager {
|
||||
|
||||
public static ChunkRadiationHandler proxy = /*new ChunkRadiationHandlerNT();*/ new ChunkRadiationHandlerSimple();
|
||||
public static ChunkRadiationHandler proxy = /*new ChunkRadiationHandlerNT();*/ new ChunkRadiationHandlerSimple(); /*new ChunkRadiationHandlerPRISM();*/
|
||||
|
||||
@SubscribeEvent
|
||||
public void onWorldLoad(WorldEvent.Load event) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user