package Hexel.things.types;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Set;
import javax.media.opengl.GL2;
import Hexel.Config;
import Hexel.LogData;
import Hexel.PCInput;
import Hexel.Stage;
import Hexel.blocks.types.Block;
import Hexel.blocks.types.BlockDebug;
import Hexel.blocks.types.BlockDirt;
import Hexel.blocks.types.BlockEmpty;
import Hexel.blocks.types.BlockGlass;
import Hexel.blocks.types.BlockLeaf;
import Hexel.blocks.types.BlockSeed;
import Hexel.blocks.types.BlockStone;
import Hexel.blocks.types.BlockWater;
import Hexel.blocks.types.BlockWood;
import Hexel.blocks.types.BlockWoodData;
import Hexel.chunk.Chunk;
import Hexel.math.Vector3d;
import Hexel.math.Vector3i;
import Hexel.rendering.Camera;
import Hexel.rendering.Face;
import Hexel.rendering.HighlightBlockFace;
import Hexel.rendering.Renderable;
import Hexel.things.ThingBridge;
import Hexel.things.blockManipulation.AddBlock;
import Hexel.things.blockManipulation.BlockAction;
import Hexel.things.blockManipulation.BlockManipulator;
import Hexel.things.blockManipulation.RemoveBlock;
import Hexel.util.Util;
public class Player extends Thing implements Movable, Cuboid, Volumetric, Camera,
BlockManipulator, Renderable, InventoryOwner, Controllable {
/**
*
*/
private static final long serialVersionUID = -8059459245330406151L;
public double x;
public double y;
public double z;
public final double xlen = .25;
public final double ylen = .25;
public final double zlen = 1.3;
private double side_dx = 0;
private double side_dy = 0;
private double forward_dx = 0;
private double forward_dy = 0;
public double dz = 0;
private final double headFractionXlen = .5;
private final double headFractionYlen = .5;
private final double headFractionZlen = .75;
public double headXRot = 0;
public double headZRot = 0;
public double health = 1;
public double hunger = 1;
private Hashtable<Thing, Long> lastAttack = new Hashtable<Thing, Long>();
public void step(){
}
@Override
public void updatePlayerControls(Config config, PCInput input) {
if (this.isDead()){
this.setSidewaysSpeed(0);
this.setForwardSpeed(0);
return;
}
while (!input.keysTapped.isEmpty()) {
int keyTapped = input.keysTapped.poll();
if (config.controls.get("gotoDebugBlock").contains(keyTapped)) {
this.blockToPlace = BlockDebug.class;
} else if (config.controls.get("gotoStoneBlock").contains(keyTapped)) {
this.blockToPlace = BlockStone.class;
} else if (config.controls.get("gotoWaterBlock").contains(keyTapped)) {
this.blockToPlace = BlockWater.class;
} else if (config.controls.get("gotoWoodBlock").contains(keyTapped)) {
this.blockToPlace = BlockWood.class;
} else if (config.controls.get("gotoLeafBlock").contains(keyTapped)) {
this.blockToPlace = BlockLeaf.class;
} else if (config.controls.get("gotoGlassBlock").contains(keyTapped)) {
this.blockToPlace = BlockGlass.class;
} else if (config.controls.get("gotoDirtBlock").contains(keyTapped)) {
this.blockToPlace = BlockDirt.class;
} else if (config.controls.get("createBlock").contains(keyTapped)) {
this.createBlock = true;
}
}
double speed = 4;
if (Util.interects(input.keysPressed, config.controls.get("sprint"))) {
speed *= 4.5;
}
if (Util.interects(input.keysPressed, config.controls.get("forward"))) {
this.setForwardSpeed(1 * speed);
} else if (Util.interects(input.keysPressed, config.controls.get("backward"))) {
this.setForwardSpeed(-1 * speed);
} else {
this.setForwardSpeed(0);
}
if (Util.interects(input.keysPressed, config.controls.get("left"))) {
this.setSidewaysSpeed(-1 * speed);
} else if (Util.interects(input.keysPressed, config.controls.get("right"))) {
this.setSidewaysSpeed(1 * speed);
} else {
this.setSidewaysSpeed(0);
}
this.deleteBlock = Util.interects(input.keysPressed, config.controls.get("removeBlock"));
while (!input.mouseClicks.isEmpty()) {
int mouseClick = input.mouseClicks.poll();
if (mouseClick == MouseEvent.BUTTON3){
this.createBlock = true;
}
}
if (input.mouseButtonsPressed.contains(MouseEvent.BUTTON1)){
this.deleteBlock = true;
}
if (Util.interects(input.keysPressed, config.controls.get("jump"))) {
this.jump(4);
}
double dx = input.getDX() / 5.0;
double dy = input.getDY() / 5.0;
this.lookVertical(dy);
this.lookHorizontal(dx);
}
public boolean isDead(){
return this.health <= 0 || this.hunger <= 0;
}
@Override
public double getCameraX() {
return this.x + this.xlen * this.headFractionXlen;
}
@Override
public double getCameraY() {
return this.y + this.ylen * this.headFractionYlen;
}
@Override
public double getCameraZ() {
return this.z + this.zlen * this.headFractionZlen;
}
@Override
public double getCameraXRot() {
return this.headXRot + 90;
}
@Override
public double getCameraYRot() {
return 0;
}
@Override
public double getCameraZRot() {
return this.headZRot;
}
@Override
public double getX() {
return this.x;
}
@Override
public double getY() {
return this.y;
}
@Override
public double getZ() {
return this.z;
}
@Override
public void getXYZ(Vector3d v) {
v.x = x;
v.y = y;
v.z = z;
}
@Override
public double getWidth() {
return this.xlen;
}
@Override
public double getHeight() {
return this.ylen;
}
@Override
public double getDepth() {
return this.zlen;
}
private Inventory inventory = new Inventory();
public Player(double x, double y, double z, double xRot, double zRot,
ThingBridge thingBridge) {
this.x = x;
this.y = y;
this.z = z;
this.headXRot = xRot;
this.headZRot = zRot;
this.thingBridge = thingBridge;
}
@Override
public Vector3d getReqMoveVector(double fps) {
Vector3d v = new Vector3d();
double dragZ = 1;
double dragXY = 1;
if (this.thingBridge.inWater(this)) {
dragZ = .5;
dragXY = .75;
}
v.x = dragXY * (this.side_dx + this.forward_dx) / fps;
v.y = dragXY * (this.side_dy + this.forward_dy) / fps;
v.z = dragZ * this.dz / fps;
return v;
}
@Override
public void applyMoveVector(Vector3d v) {
this.x += v.x;
this.y += v.y;
this.z += v.z;
LogData.set("playerX", this.x);
LogData.set("playerY", this.y);
LogData.set("playerZ", this.z);
}
public void lookVertical(double dx) {
this.headXRot += dx;
if (this.headXRot < -90)
this.headXRot = -90;
if (this.headXRot > 90)
this.headXRot = 90;
}
public void lookHorizontal(double dx) {
this.headZRot += dx;
}
public void setForwardSpeed(double speed) {
this.side_dx = speed * Math.cos(Math.toRadians(90 + this.headZRot));
this.side_dy = speed * Math.sin(Math.toRadians(90 + this.headZRot));
}
public void setSidewaysSpeed(double speed) {
this.forward_dx = speed * Math.cos(Math.toRadians(this.headZRot));
this.forward_dy = speed * Math.sin(Math.toRadians(this.headZRot));
}
public void jump(double mag) {
if (this.thingBridge.onGround(this) || this.thingBridge.inWater(this))
this.dz = mag;
}
@Override
public void accelerate(double fps, double dx, double dy, double dz) {
this.dz += dz / fps;
if (this.thingBridge.inWater(this) && Math.abs(this.dz) > 5)
this.dz = Math.signum(this.dz) * 5;
}
@Override
public void stopX() {
}
@Override
public void stopY() {
}
@Override
public void stopZ() {
this.dz = 0;
}
@Override
public void addBlock(Block b) {
this.inventory.addBlock(b);
}
@Override
public void rmBlock(Block b) {
this.inventory.useBlock(b.getClass());
}
public Vector3d getDirectionLooking() {
double x = Math.cos(Math.toRadians(90 + this.headZRot))
* Math.cos(Math.toRadians(this.headXRot));
double y = Math.sin(Math.toRadians(90 + this.headZRot))
* Math.cos(Math.toRadians(this.headXRot));
double z = Math.sin(Math.toRadians(this.headXRot));
return new Vector3d(x, y, z);
}
public boolean isUnderwater() {
return this.thingBridge.isUnderwater(getCameraX(),
getCameraY(), getCameraZ());
}
@Override
public void render(GL2 gl) {
Vector3d dir = getDirectionLooking();
dir.times(10);
Vector3i closestBlock = this.thingBridge
.getClosestNonEmptyBlockOnVector(
new Vector3d(getCameraX(), getCameraY(), getCameraZ()), dir);
Vector3i closestEmptyBlock = this.thingBridge
.getClosestEmptyBlockOnVector(new Vector3d(getCameraX(),
getCameraY(), getCameraZ()), dir);
if (closestBlock != null) {
Face f = HighlightBlockFace.getBetweenFace(closestBlock,
closestEmptyBlock);
HighlightBlockFace.highlight(gl, closestBlock, f);
}
}
public boolean createBlock = false;
public boolean deleteBlock = false;
public boolean lastDeleteBlock = true;
public Class blockToPlace = null;
public Block getBlockToPlace() {
if (this.blockToPlace == BlockDebug.class){
return BlockDebug.Make(BlockDebug.MAX_HEALTH);
}
else if (this.blockToPlace == BlockDirt.class){
return BlockDirt.Make(BlockDirt.MAX_HEALTH, false);
}
else if (this.blockToPlace == BlockGlass.class){
return BlockGlass.Make(0, BlockGlass.MAX_HEALTH);
}
else if (this.blockToPlace == BlockLeaf.class){
return BlockLeaf.Make(0, BlockLeaf.MAX_HEALTH);
}
else if (this.blockToPlace == BlockSeed.class){
return BlockSeed.Make(5, BlockSeed.MAX_HEALTH);
}
else if (this.blockToPlace == BlockStone.class){
return BlockStone.Make(BlockStone.MAX_HEALTH);
}
else if (this.blockToPlace == BlockWater.class){
return BlockWater.Make(0, 0, 8);
}
else if (this.blockToPlace == BlockWood.class){
return BlockWood.Make(BlockWoodData.deadBlockWoodData);
}
else {
try {
throw new Exception("can't create block, unknown block type");
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
return null;
}
}
public int getBlockAvailability(Class c) {
return this.inventory.numBlock(c);
}
@Override
public BlockAction getBlockAction() {
Vector3d dir = getDirectionLooking();
dir.times(10);
if (this.createBlock) {
lastDeleteBlock = this.deleteBlock;
this.createBlock = false;
if (!this.inventory.hasBlock(this.blockToPlace))
return null;
Vector3i closestBlock = this.thingBridge
.getClosestEmptyBlockOnVector(
new Vector3d(getCameraX(), getCameraY(),
getCameraZ()), dir);
if (closestBlock != null) {
AddBlock ab = new AddBlock();
ab.x = closestBlock.x;
ab.y = closestBlock.y;
ab.z = closestBlock.z;
ab.block = getBlockToPlace();
return ab;
} else {
return null;
}
} else if (this.deleteBlock) {
boolean justClickedDelete = this.deleteBlock != lastDeleteBlock;
lastDeleteBlock = this.deleteBlock;
this.deleteBlock = false;
ArrayList<Vector3i> blocksAttacking = this.thingBridge.getNonEmptyBlocksOnVector(
new Vector3d(getCameraX(), getCameraY(), getCameraZ()), dir);
Set<Thing> things = this.thingBridge.getIntersectingThings(blocksAttacking);
things.remove(this);
if (things.size() > 0){
if (justClickedDelete){
for (Thing thing : things){
if (thing instanceof Zombie){
Long lastAttackTime = lastAttack.get(thing);
lastAttack.put(thing, System.currentTimeMillis());
Zombie zombie = (Zombie)thing;
if (lastAttackTime == null || System.currentTimeMillis() - lastAttackTime > 100){
zombie.health -= .25;
zombie.hurt = 10;
break;
}
}
else if (thing instanceof Deer){
Long lastAttackTime = lastAttack.get(thing);
lastAttack.put(thing, System.currentTimeMillis());
Deer deer = (Deer)thing;
if (lastAttackTime == null || System.currentTimeMillis() - lastAttackTime > 100){
deer.health -= .25;
deer.lastHurt = deer.step;
if (deer.health <= 0)
this.hunger = 1;
break;
}
}
}
}
}
else {
Vector3i closestBlock = blocksAttacking.get(blocksAttacking.size()-1);
Vector3i tmp3i = new Vector3i();
Block b = thingBridge.engine.chunks.getBlock(closestBlock.x, closestBlock.y, closestBlock.z, tmp3i, (Chunk)null);
if (!(b instanceof BlockEmpty || b instanceof BlockWater)){
if (closestBlock != null) {
RemoveBlock ab = new RemoveBlock();
ab.x = closestBlock.x;
ab.y = closestBlock.y;
ab.z = closestBlock.z;
return ab;
}
}
}
return null;
} else {
lastDeleteBlock = this.deleteBlock;
return null;
}
}
private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException {
x = (Double) in.readObject();
y = (Double) in.readObject();
z = (Double) in.readObject();
side_dx = (Double) in.readObject();
side_dy = (Double) in.readObject();
forward_dx = (Double) in.readObject();
forward_dy = (Double) in.readObject();
dz = (Double) in.readObject();
headXRot = (Double) in.readObject();
headZRot = (Double) in.readObject();
health = (Double) in.readObject();
createBlock = (Boolean) in.readObject();
deleteBlock = (Boolean) in.readObject();
blockToPlace = (Class) in.readObject();
inventory = (Inventory) in.readObject();
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.writeObject(x);
out.writeObject(y);
out.writeObject(z);
out.writeObject(side_dx);
out.writeObject(side_dy);
out.writeObject(forward_dx);
out.writeObject(forward_dy);
out.writeObject(dz);
out.writeObject(headXRot);
out.writeObject(headZRot);
out.writeObject(health);
out.writeObject(createBlock);
out.writeObject(deleteBlock);
out.writeObject(blockToPlace);
out.writeObject(inventory);
// out.defaultWriteObject();
}
}