219 lines
7.7 KiB
Java
219 lines
7.7 KiB
Java
package com.github.halotroop.litecraft;
|
|
|
|
import org.joml.*;
|
|
|
|
import com.github.halotroop.litecraft.save.LitecraftSave;
|
|
import com.github.halotroop.litecraft.screens.*;
|
|
import com.github.halotroop.litecraft.types.block.Blocks;
|
|
import com.github.halotroop.litecraft.types.entity.PlayerEntity;
|
|
import com.github.halotroop.litecraft.util.RelativeDirection;
|
|
import com.github.halotroop.litecraft.world.World;
|
|
import com.github.hydos.ginger.engine.common.Constants;
|
|
import com.github.hydos.ginger.engine.common.api.*;
|
|
import com.github.hydos.ginger.engine.common.api.game.*;
|
|
import com.github.hydos.ginger.engine.common.cameras.*;
|
|
import com.github.hydos.ginger.engine.common.elements.objects.*;
|
|
import com.github.hydos.ginger.engine.common.font.FontType;
|
|
import com.github.hydos.ginger.engine.common.info.RenderAPI;
|
|
import com.github.hydos.ginger.engine.common.io.Window;
|
|
import com.github.hydos.ginger.engine.common.obj.ModelLoader;
|
|
import com.github.hydos.ginger.engine.opengl.api.*;
|
|
import com.github.hydos.ginger.engine.opengl.postprocessing.PostProcessing;
|
|
import com.github.hydos.ginger.engine.opengl.render.MasterRenderer;
|
|
import com.github.hydos.ginger.engine.opengl.render.models.GLTexturedModel;
|
|
import com.github.hydos.ginger.engine.opengl.utils.GLLoader;
|
|
import tk.valoeghese.gateways.client.io.*;
|
|
|
|
public class Litecraft extends Game
|
|
{
|
|
// FIXME: search for ((GingerGL)engine) and properly implement both render APIs when Vulkan is complete.
|
|
|
|
private static Litecraft INSTANCE;
|
|
private World world;
|
|
private LitecraftSave save;
|
|
private GingerEngine engine;
|
|
public int fps, ups, tps;
|
|
public Vector4i dbgStats = new Vector4i();
|
|
private long frameTimer;
|
|
|
|
public Litecraft()
|
|
{
|
|
Litecraft.INSTANCE = this;
|
|
// set constants
|
|
this.setupConstants();
|
|
this.setupGinger(1280, 720, 60);
|
|
Blocks.init(); // make sure blocks are initialised
|
|
this.frameTimer = System.currentTimeMillis();
|
|
setupKeybinds(); // setup keybinds
|
|
// start the game loop
|
|
this.engine.startGameLoop();
|
|
}
|
|
|
|
@Override
|
|
public void exit()
|
|
{
|
|
engine.openScreen(new ExitGameScreen());
|
|
render(); // Render the exit game screen
|
|
if (this.world != null)
|
|
{
|
|
System.out.println("Saving chunks...");
|
|
long time = System.currentTimeMillis();
|
|
this.world.unloadAllChunks();
|
|
this.getSave().saveGlobalData(this.world.getSeed(), ((PlayerEntity) this.player));
|
|
System.out.println("Saved world in " + (System.currentTimeMillis() - time) + " milliseconds");
|
|
}
|
|
engine.cleanup();
|
|
System.exit(0);
|
|
}
|
|
|
|
/**
|
|
* Things that ARE rendering: Anything that results in something being drawn to the frame buffer
|
|
* Things that are NOT rendering: Things that happen to update between frames but do not result in things being drawn to the screen
|
|
*/
|
|
@Override
|
|
public void render()
|
|
{
|
|
fps += 1;
|
|
if (System.currentTimeMillis() > frameTimer + 1000) updateDebugStats();
|
|
// Render shadows
|
|
GingerRegister.getInstance().masterRenderer.renderShadowMap(data.entities, data.lights.get(0));
|
|
// If there's a world, render it!
|
|
if (this.world != null) renderWorld(this);
|
|
// Render any overlays (GUIs, HUDs)
|
|
this.engine.renderOverlays(this);
|
|
// Put what's stored in the inactive framebuffer on the screen
|
|
Window.swapBuffers();
|
|
}
|
|
|
|
// Updates the debug stats once per real-time second, regardless of how many frames have been rendered
|
|
private void updateDebugStats()
|
|
{
|
|
this.dbgStats.set(fps, ups, tps, 0);
|
|
this.fps=0;
|
|
this.ups=0;
|
|
this.tps=0;
|
|
this.frameTimer += 1000;
|
|
}
|
|
|
|
public void renderWorld(Game game)
|
|
{
|
|
GameData data = game.data;
|
|
GingerUtils.preRenderScene(((GingerGL)engine).getRegistry().masterRenderer);
|
|
((GingerGL)engine).contrastFbo.bindFBO();
|
|
((GingerGL)engine).getRegistry().masterRenderer.renderScene(data.entities, data.normalMapEntities, data.lights, data.camera, data.clippingPlane);
|
|
((GingerGL)engine).contrastFbo.unbindFBO();
|
|
PostProcessing.doPostProcessing(((GingerGL)engine).contrastFbo.colorTexture);
|
|
if (data.handleGuis) ((GingerGL)engine).renderOverlays(game);
|
|
}
|
|
|
|
public void update()
|
|
{
|
|
ups += 1;
|
|
}
|
|
|
|
private void setupConstants()
|
|
{
|
|
Constants.movementSpeed = 0.5f; // movement speed
|
|
Constants.turnSpeed = 0.00006f; // turn speed
|
|
Constants.gravity = new Vector3f(0, -0.0000000005f, 0); // compute gravity as a vec3f
|
|
Constants.jumpPower = 0.00005f; // jump power
|
|
}
|
|
|
|
// set up Ginger3D engine stuff
|
|
private void setupGinger(int windowWidth, int windowHeight, float frameCap)
|
|
{
|
|
if (engine == null) // Prevents this from being run more than once on accident.
|
|
{
|
|
Window.create(windowWidth, windowHeight, "Litecraft", frameCap, RenderAPI.OpenGL); // create window
|
|
// set up the gateways keybind key tracking
|
|
KeyCallbackHandler.trackWindow(Window.getWindow());
|
|
MouseCallbackHandler.trackWindow(Window.getWindow());
|
|
// set up ginger utilities
|
|
GingerUtils.init();
|
|
|
|
switch (Window.renderAPI)
|
|
{
|
|
case OpenGL:
|
|
{
|
|
this.engine = new GingerGL();
|
|
//Set the player model
|
|
GLTexturedModel playerModel = ModelLoader.loadGenericCube("block/cubes/stone/brick/stonebrick.png");
|
|
FontType font = new FontType(GLLoader.loadFontAtlas("candara.png"), "candara.fnt");
|
|
this.player = new PlayerEntity(playerModel, new Vector3f(0, 0, -3), 0, 180f, 0, new Vector3f(0.2f, 0.2f, 0.2f));
|
|
this.camera = new FirstPersonCamera(player);
|
|
this.data = new GameData(this.player, this.camera, 20);
|
|
this.data.handleGuis = false;
|
|
((GingerGL)engine).setup(new MasterRenderer(this.camera), INSTANCE);
|
|
((GingerGL)engine).setGlobalFont(font);
|
|
this.data.entities.add(this.player);
|
|
break;
|
|
}
|
|
case Vulkan:
|
|
{
|
|
// TODO: Setup Vulkan
|
|
exit();
|
|
break;
|
|
}
|
|
}
|
|
Light sun = new Light(new Vector3f(0, 105, 0), new Vector3f(0.9765625f, 0.98828125f, 0.05859375f), new Vector3f(0.002f, 0.002f, 0.002f));
|
|
this.data.lights.add(sun);
|
|
}
|
|
}
|
|
|
|
private void setupKeybinds()
|
|
{
|
|
Input.addPressCallback(Keybind.EXIT, this::exit);
|
|
Input.addInitialPressCallback(Keybind.FULLSCREEN, Window::fullscreen);
|
|
Input.addInitialPressCallback(Keybind.WIREFRAME, GingerRegister.getInstance()::toggleWireframe);
|
|
Input.addPressCallback(Keybind.MOVE_FORWARD, () -> ((PlayerEntity) this.player).move(RelativeDirection.FORWARD));
|
|
Input.addPressCallback(Keybind.MOVE_BACKWARD, () -> ((PlayerEntity) this.player).move(RelativeDirection.BACKWARD));
|
|
Input.addPressCallback(Keybind.STRAFE_LEFT, () -> ((PlayerEntity) this.player).move(RelativeDirection.LEFT));
|
|
Input.addPressCallback(Keybind.STRAFE_RIGHT, () -> ((PlayerEntity) this.player).move(RelativeDirection.RIGHT));
|
|
Input.addPressCallback(Keybind.FLY_UP, () -> ((PlayerEntity) this.player).move(RelativeDirection.UP));
|
|
Input.addPressCallback(Keybind.FLY_DOWN, () -> ((PlayerEntity) this.player).move(RelativeDirection.DOWN));
|
|
}
|
|
|
|
/**
|
|
* Things that should be ticked: Entities when deciding an action, in-game timers (such as smelting), the in-game time
|
|
* Things that should not be ticked: Rendering, input, player movement
|
|
*/
|
|
@Override
|
|
public void tick()
|
|
{
|
|
tps += 1;
|
|
// Open the title screen if it's not already open.
|
|
if (GingerRegister.getInstance().currentScreen == null && world == null) ((GingerGL)engine).openScreen(new TitleScreen());
|
|
|
|
if (this.player instanceof PlayerEntity && camera != null)
|
|
{
|
|
Input.invokeAllListeners();
|
|
((PlayerEntity) this.player).updateMovement();
|
|
data.camera.updateMovement();
|
|
}
|
|
}
|
|
|
|
// @formatter=off
|
|
public static Litecraft getInstance()
|
|
{ return INSTANCE; }
|
|
|
|
public Camera getCamera()
|
|
{ return this.camera; }
|
|
|
|
public LitecraftSave getSave()
|
|
{ return save; }
|
|
|
|
public World getWorld()
|
|
{ return this.world; }
|
|
|
|
public void changeWorld(World world)
|
|
{ this.world = world; }
|
|
|
|
public void setSave(LitecraftSave save)
|
|
{ this.save = save; }
|
|
|
|
@Override
|
|
public void renderScene()
|
|
{
|
|
world.render(GingerRegister.getInstance().masterRenderer.blockRenderer);
|
|
}
|
|
} |