package Hexel.blocks.rules;
import java.util.ArrayList;
import java.util.HashSet;
import Hexel.Engine;
import Hexel.blocks.BlockDelta;
import Hexel.blocks.BlockRule;
import Hexel.blocks.BlockRules;
import Hexel.blocks.BlockSimulator;
import Hexel.blocks.BlockTools;
import Hexel.blocks.FreqBlockRule;
import Hexel.blocks.BlockSimulator.BlockDeltaAdder;
import Hexel.blocks.types.Block;
import Hexel.blocks.types.BlockTransparent;
import Hexel.chunk.Chunk;
import Hexel.chunk.Chunks;
import Hexel.chunk.HighestBlockChunk;
import Hexel.math.HexGeometry;
import Hexel.math.Vector2i;
import Hexel.math.Vector3i;
import Hexel.util.Container;
public class NaturalLightRule implements BlockRule {
private Vector3i tmp3i = new Vector3i();
private Vector3i tmp3i2 = new Vector3i();
private Vector2i tmp2i = new Vector2i();
private static boolean INSTANT = true;
private BlockSimulator.PointInSimRange inSimRange;
public NaturalLightRule(BlockSimulator.PointInSimRange inSimRange){
this.inSimRange = inSimRange;
}
private Container<Chunk> chunk = new Container<Chunk>();
private Container<HighestBlockChunk> highestBlockChunk = new Container<HighestBlockChunk>();
@Override
public int run(int bx, int by, int bz, final boolean fastMode, Block b, Chunk c,
HighestBlockChunk hbc, final Chunks chunks, final int step, final BlockDeltaAdder blockDeltaAdder) {
chunk.contents = c;
highestBlockChunk.contents = hbc;
final Vector3i start = new Vector3i(bx, by, bz);
final int startStepsToSim = chunks.getStepsToSim(bx, by, bz, tmp3i, chunk);
if (blockDeltaAdder.hasBlockDelta(start))
return 1;
// final HashSet<Vector3i> seen = new HashSet<Vector3i>();
BlockTools.pointFloodSearch(start, true, new BlockTools.PointFloodSearchMatcher() {
@Override
public boolean matches(Vector3i p) {
Block b = chunks.getBlock(p.x, p.y, p.z, tmp3i, chunk);
if (!(b instanceof BlockTransparent)){
return false;
}
if (blockDeltaAdder.hasBlockDelta(p)){
return false;
}
if (!inSimRange.pointIsInRange(p)){
return false;
}
BlockTransparent be = (BlockTransparent)b;
int newLightLevel = 0;
int highestBlock = chunks.getHighestBlockAtXY(p.x, p.y, tmp2i, highestBlockChunk);
if (p.z > highestBlock){
newLightLevel = 0;
}
else {
Vector3i[] neighbors = HexGeometry.getAllNeighbors(p.x);
int highestNeighborLightLevel = BlockTransparent.MAX_LIGHT_LEVEL;
for (Vector3i neighbor3 : neighbors) {
tmp3i2.x = p.x+neighbor3.x;
tmp3i2.y = p.y+neighbor3.y;
tmp3i2.z = p.z+neighbor3.z;
Block neighbor = chunks.getBlock(tmp3i2.x, tmp3i2.y, tmp3i2.z, tmp3i, chunk);
if (neighbor instanceof BlockTransparent){
int naturalOcclusion = 1;
if (neighbor3.z == 1)
naturalOcclusion = 0;
BlockTransparent neighborE = (BlockTransparent)neighbor;
highestNeighborLightLevel = Math.min(highestNeighborLightLevel, neighborE.getLightLevel()+naturalOcclusion+neighborE.occlusion);
}
}
newLightLevel = highestNeighborLightLevel;
}
if (newLightLevel != be.naturalLightLevel){
BlockTransparent newBE = BlockTools.updateLightLevel(be, newLightLevel);
blockDeltaAdder.addBlockDelta(BlockDelta.Aquire(p.x, p.y, p.z, newBE, startStepsToSim));
return INSTANT;
}
return false;
}
});
return BlockSimulator.DONT_RUN;
}
}