package Hexel;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.util.HashSet;
import javax.media.opengl.awt.GLCanvas;
import javax.swing.JFrame;
import Hexel.blocks.BlockSimulator;
import Hexel.blocks.types.BlockDebug;
import Hexel.blocks.types.BlockDirt;
import Hexel.blocks.types.BlockGlass;
import Hexel.blocks.types.BlockLeaf;
import Hexel.blocks.types.BlockStone;
import Hexel.blocks.types.BlockTransparent;
import Hexel.blocks.types.BlockWater;
import Hexel.blocks.types.BlockWood;
import Hexel.chunk.ChunkVisibilityManager;
import Hexel.chunk.Chunks;
import Hexel.generation.terrainGenerator.VariedTerrainMap;
import Hexel.generation.terrainGenerator.typeMaps.DrawTypeMap;
import Hexel.rendering.Camera;
import Hexel.rendering.Renderer;
import Hexel.things.ThingBridge;
import Hexel.things.ThingSimulator;
import Hexel.things.types.Controllable;
import Hexel.things.types.Player;
import Hexel.things.types.Thing;
import Hexel.things.types.ZombieSpawnPlanner;
import Hexel.util.Cleanup;
import Hexel.util.FrameRateTracker;
import Hexel.util.TickHandler;
import Hexel.util.Util;
public class Engine {
public Chunks chunks;
public Renderer renderer;
public Camera camera;
private Stage stage;
private FrameRateTracker fps;
public ThingSimulator thingSimulator;
private BlockSimulator worldSimulator;
public ChunkVisibilityManager chunkVisibilityManager;
private PCInput input;
public ZombieSpawnPlanner zsp;
private Controllable controllable;
private Config config = new Config();
public int time;
public static int day_period = 60*60*10; // sunrise @ 0, sunset @ period/2
// public static int day_shift = (int)(day_period/4 + day_period/4);
public static int day_shift = (int)(day_period/4);
private int day_range = 60*10;
public double getAmbientLight(){
double time = this.time + day_shift;
boolean isNight = time%day_period > day_period/2;
double distToLastChange = time%(day_period/2) - 0;
double distToNextChange = time%(day_period/2) - day_period/2;
double lightLevel = isNight?0:1;
if (distToNextChange > -day_range || distToLastChange < day_range){
boolean useDistToNext = distToNextChange > -day_range;
double dist = useDistToNext?distToNextChange:distToLastChange;
double v = dist/(day_range*2);
v = useDistToNext?-v:v;
lightLevel = (isNight)?.5-v:.5+v;
}
lightLevel = (lightLevel > 1)?1:lightLevel;
lightLevel = (lightLevel < .25)?.25:lightLevel;
return lightLevel;
}
public JFrame getFrame() {
return this.renderer.window.getFrame();
}
public GLCanvas getCanvas() {
return this.renderer.window.getCanvas();
}
public void start(TickHandler handler) {
this.renderer.start(handler);
}
public ThingBridge getThingBridge() {
return this.thingSimulator.getThingBridge();
}
public void processInput(PCInput input){
if (this.stage == Stage.INGAME){
updatePlayerControls(input);
}
else {
this.renderer.sendInputToCurrentOverlay(input);
}
}
public void setControllable(Controllable controllable) {
this.renderer.setControllable(controllable);
this.controllable = controllable;
}
public void setStage(Stage stage) {
this.stage = stage;
this.renderer.setStage(stage);
if (this.input != null){
if (this.stage == Stage.INGAME){
this.input.hideCursor();
}
else {
this.input.showCursor();
}
}
}
public void addThing(Thing thing) {
this.thingSimulator.addThing(thing);
}
public void setInput(PCInput input){
this.input = input;
}
public Engine() {
Cleanup cleanup = new Cleanup();
this.chunks = new Chunks(cleanup, 10 * 10 * 10);
this.thingSimulator = new ThingSimulator(cleanup, this, this.chunks);
this.renderer = new Renderer(this, this.chunks);
this.fps = new FrameRateTracker(5);
this.chunkVisibilityManager = new ChunkVisibilityManager(this, this.chunks, this.renderer);
this.worldSimulator = new BlockSimulator(this, this.chunks, this.chunkVisibilityManager);
this.zsp = new ZombieSpawnPlanner(this);
setStage(Stage.START_MENU);
this.time = 0;
if (this.config.settings.get("save").equals("no")){
Session.save = false;
}
Runtime.getRuntime().addShutdownHook(cleanup);
}
public void quit(){
WindowEvent wev = new WindowEvent(this.renderer.window.frame, WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(wev);
}
public void setCamera(Camera camera) {
this.camera = camera;
this.renderer.setCamera(camera);
}
public void step() {
this.fps.hit();
if (this.stage == Stage.INGAME){
this.chunkVisibilityManager.updateVisibility(this.camera);
if (this.fps.avg() >= 1) {
this.thingSimulator.step(this.fps.avg());
this.worldSimulator.step();
time += 1;
LogData.set("time", time);
}
}
}
public void updatePlayerControls(PCInput input) {
HashSet<Integer> used = new HashSet<Integer>();
for (int keyTapped : input.keysTapped){
if (this.config.controls.get("pause").contains(keyTapped)){
this.setStage(Stage.INGAME_MENU);
used.add(keyTapped);
}
else if (this.config.controls.get("debug").contains(keyTapped)){
this.renderer.overlay.hud.displayDebug = !this.renderer.overlay.hud.displayDebug;
used.add(keyTapped);
}
else if (this.config.controls.get("map").contains(keyTapped)){
if (chunks.chunkGenerator.tm instanceof VariedTerrainMap){
new DrawTypeMap(((VariedTerrainMap)chunks.chunkGenerator.tm).tfmg);
}
used.add(keyTapped);
}
}
input.keysTapped.removeAll(used);
if (this.controllable instanceof Controllable){
this.controllable.updatePlayerControls(config, input);
}
}
}