package Hexel.things;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Set;
import Hexel.Engine;
import Hexel.Resources;
import Hexel.blocks.BlockTools;
import Hexel.blocks.BlockTools.PointFloodSearchMatcher;
import Hexel.blocks.types.Block;
import Hexel.blocks.types.BlockEmpty;
import Hexel.blocks.types.BlockWater;
import Hexel.chunk.Chunk;
import Hexel.chunk.Chunks;
import Hexel.math.HexGeometry;
import Hexel.math.Vector2d;
import Hexel.math.Vector3d;
import Hexel.math.Vector3i;
import Hexel.things.types.Cuboid;
import Hexel.things.types.Player;
import Hexel.things.types.Thing;
import Hexel.things.types.Volumetric;
public class ThingBridge {
private Chunks chunks;
public ThingTools thingTools;
public Player player;
public Engine engine;
public ThingTools.FixOffsetTmps fixOffsetTmps;
public ThingBridge(Engine engine, Chunks chunks) {
this.chunks = chunks;
this.engine = engine;
this.thingTools = new ThingTools(engine, chunks);
this.fixOffsetTmps = this.thingTools.new FixOffsetTmps();
}
private static final Vector3d onGroundOffset = new Vector3d(0, 0, -.1);
private static final Vector3d zeroOffset = new Vector3d(0, 0, 0);
public void getPlayerXYZ(Vector3d v){
v.x = player.x;
v.y = player.y;
v.z = player.z;
}
public void restorePlayerHealth(double h){
player.health = Math.min(1, player.health + h);
}
public void damagePlayerHealth(double h){
player.health = Math.max(0, player.health - h);
}
public boolean onGround(Volumetric v) {
return this.thingTools.collidesSolid(v, onGroundOffset, this.fixOffsetTmps);
}
public boolean inWater(Volumetric v) {
return this.thingTools.collidesWater(v, zeroOffset, this.fixOffsetTmps);
}
public boolean isUnderwater(double x, double y, double z) {
Vector3i tmp3i = new Vector3i();
Vector2d tmp2d = new Vector2d();
return this.thingTools.collidesWater(x, y, z, tmp2d, tmp3i);
}
public ArrayList<Vector3i> getNonEmptyBlocksOnVector(Vector3d offset, Vector3d t){
ArrayList<Vector3i> blocks = new ArrayList<Vector3i>();
double STEP_SIZE = .01;
Vector3d v = new Vector3d();
Vector3d step = Vector3d.Sub(t, v);
step.unit();
step.times(STEP_SIZE);
Vector2d tmp2d = new Vector2d();
Vector3i tmp3i = new Vector3i();
Vector3i blockPos = new Vector3i();
while (v.mag() < t.mag()) {
v.add(step);
HexGeometry.cartesianToBlock(v.x + offset.x, v.y + offset.y, v.z + offset.z, tmp2d, blockPos);
Block b = this.chunks.getBlock(blockPos.x, blockPos.y, blockPos.z, tmp3i, (Chunk)null);
blocks.add(new Vector3i(blockPos));
if (!(b instanceof BlockEmpty || b instanceof BlockWater)) {
break;
}
}
return blocks;
}
public Vector3i getClosestNonEmptyBlockOnVector(Vector3d offset, Vector3d t) {
double STEP_SIZE = .01;
Vector3d v = new Vector3d();
Vector3d step = Vector3d.Sub(t, v);
step.unit();
step.times(STEP_SIZE);
Vector2d tmp2d = new Vector2d();
Vector3i tmp3i = new Vector3i();
Vector3i blockPos = new Vector3i();
while (v.mag() < t.mag()) {
v.add(step);
HexGeometry.cartesianToBlock(v.x + offset.x, v.y + offset.y, v.z
+ offset.z, tmp2d, blockPos);
Block b = this.chunks.getBlock(blockPos.x, blockPos.y, blockPos.z, tmp3i, (Chunk)null);
if (!(b instanceof BlockEmpty || b instanceof BlockWater)) {
return blockPos;
}
}
return null;
}
public Vector3i getClosestEmptyBlockOnVector(Vector3d offset, Vector3d t) {
double STEP_SIZE = .01;
Vector3d v = new Vector3d();
Vector3d step = Vector3d.Sub(t, v);
step.unit();
step.times(STEP_SIZE);
Vector3i farthestEmpty = new Vector3i();
Vector3i blockPos = new Vector3i();
Vector2d tmp2d = new Vector2d();
Vector3i tmp3i = new Vector3i();
while (v.mag() < t.mag()) {
v.add(step);
HexGeometry.cartesianToBlock(v.x + offset.x, v.y + offset.y, v.z
+ offset.z, tmp2d, blockPos);
Block b = this.chunks.getBlock(blockPos.x, blockPos.y, blockPos.z, tmp3i, (Chunk)null);
if (!(b instanceof BlockEmpty || b instanceof BlockWater)) {
return farthestEmpty;
} else {
farthestEmpty.x = blockPos.x;
farthestEmpty.y = blockPos.y;
farthestEmpty.z = blockPos.z;
}
}
return null;
}
public Set<Thing> getIntersectingThings(ArrayList<Vector3i> blocks){
final HashSet<Thing> thingsIntersecting = new HashSet<Thing>();
final HashSet<Vector3i> blocksIntersecting = new HashSet<Vector3i>();
blocksIntersecting.addAll(blocks);
Set<Thing> things = this.engine.thingSimulator.things;
synchronized (things){
for (Thing thing : things){
final Thing thing0 = thing;
if (thing instanceof Cuboid){
final Cuboid c = (Cuboid)thing;
ArrayList<Vector3i> blocksIntersectingThing = thingTools.getBlocksIntersectingThing(c, fixOffsetTmps);
for (Vector3i v : blocksIntersectingThing){
if (blocksIntersecting.contains(v)){
thingsIntersecting.add(thing0);
}
}
}
}
}
return thingsIntersecting;
}
}