483 lines
15 KiB
Java
483 lines
15 KiB
Java
package electrosphere.engine;
|
|
|
|
import static org.lwjgl.glfw.GLFW.glfwTerminate;
|
|
import static org.lwjgl.glfw.GLFW.glfwWindowShouldClose;
|
|
|
|
import java.lang.management.ManagementFactory;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
import org.ode4j.ode.OdeHelper;
|
|
|
|
import electrosphere.audio.AudioEngine;
|
|
import electrosphere.audio.VirtualAudioSourceManager;
|
|
import electrosphere.controls.ControlHandler;
|
|
import electrosphere.engine.cli.CLIParser;
|
|
import electrosphere.engine.loadingthreads.LoadingThread;
|
|
import electrosphere.engine.time.Timekeeper;
|
|
import electrosphere.game.config.UserSettings;
|
|
import electrosphere.game.server.world.MacroData;
|
|
import electrosphere.logger.LoggerInterface;
|
|
import electrosphere.menu.ImGuiWindowMacros;
|
|
import electrosphere.renderer.RenderingEngine;
|
|
import electrosphere.server.simulation.MacroSimulation;
|
|
|
|
|
|
|
|
public class Main {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static boolean running = true;
|
|
|
|
//target amount of time per frame
|
|
public static float targetFrameRate = 60.0f;
|
|
static float targetFramePeriod = 1.0f/targetFrameRate;
|
|
|
|
//framestep variable
|
|
static int framestep = 2;
|
|
|
|
public static void main(String args[]){
|
|
|
|
//
|
|
//
|
|
// I N I T I A L I Z A T I O N
|
|
//
|
|
//
|
|
|
|
//parse command line arguments
|
|
CLIParser.parseCLIArgs(args);
|
|
|
|
startUp();
|
|
|
|
mainLoop();
|
|
|
|
}
|
|
|
|
public static void startUp(){
|
|
//initialize logging interfaces
|
|
LoggerInterface.initLoggers();
|
|
|
|
//gets pid of engine
|
|
System.out.println(ManagementFactory.getRuntimeMXBean().getName());
|
|
|
|
//load user settings
|
|
UserSettings.loadUserSettings();
|
|
|
|
//init global variables
|
|
Globals.initGlobals();
|
|
|
|
//controls
|
|
if(Globals.RUN_CLIENT){
|
|
initControlHandler();
|
|
}
|
|
|
|
//init ODE
|
|
OdeHelper.initODE();
|
|
|
|
// if(1==1){
|
|
// SaveUtils.loadSave("arena");
|
|
// Globals.authenticationManager = new AuthenticationManager();
|
|
// String rawPass = "testpassword";
|
|
// String hashedPassword = AuthenticationManager.getHashedString(rawPass);
|
|
// boolean authed = Globals.authenticationManager.authenticate("testuser", hashedPassword);
|
|
// System.out.println("Authenticated: " + authed);
|
|
// System.exit(0);
|
|
// }
|
|
|
|
//world gen testing
|
|
//gen terrain
|
|
if(Globals.RUN_SIMULATION_ONLY){
|
|
//gen world
|
|
Globals.macroData = MacroData.generateWorld(0);
|
|
Globals.macroData.describeWorld();
|
|
boolean run = true;
|
|
Globals.macroSimulation = new MacroSimulation();
|
|
while(run){
|
|
Globals.macroSimulation.simulate();
|
|
try {
|
|
TimeUnit.MILLISECONDS.sleep(1000);
|
|
} catch (InterruptedException ex) {
|
|
ex.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
|
|
// if(1==1){
|
|
// Globals.audioEngine = new AudioEngine();
|
|
// Globals.audioEngine.init();
|
|
// Globals.assetManager.addAudioPathToQueue("/Audio/MenuStartup.ogg");
|
|
// Globals.assetManager.loadAssetsInQueue();
|
|
// Globals.audioEngine.setGain(0.1f);
|
|
// AudioSource startupSound = AudioUtils.playAudioAtLocation("/Audio/MenuStartup.ogg", new Vector3f(3,0,0));
|
|
// if(startupSound != null){
|
|
// while(startupSound.isPlaying()){
|
|
// try {
|
|
// TimeUnit.MILLISECONDS.sleep(10);
|
|
// } catch (InterruptedException ex) {
|
|
// ex.printStackTrace();
|
|
// }
|
|
// }
|
|
// }
|
|
// System.exit(0);
|
|
// }
|
|
|
|
|
|
|
|
//debug: create terrain/world viewer
|
|
// TerrainViewer.runViewer();
|
|
|
|
//create the drawing context
|
|
if(Globals.RUN_CLIENT && !Globals.HEADLESS){
|
|
Globals.renderingEngine = new RenderingEngine();
|
|
Globals.renderingEngine.createOpenglContext();
|
|
Globals.initDefaultGraphicalResources();
|
|
ImGuiWindowMacros.initImGuiWindows();
|
|
}
|
|
|
|
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
|
System.out.println("Shutdown hook!");
|
|
}));
|
|
|
|
//uncomment to test loading a model into engine
|
|
// if(1==1){
|
|
// Globals.assetManager.addModelPathToQueue("/Models/tank1.fbx");
|
|
// Globals.assetManager.loadAssetsInQueue();
|
|
// Model model = Globals.assetManager.fetchModel("/Models/tank1.fbx");
|
|
// // for(electrosphere.renderer.anim.Animation anim : model.animations){
|
|
// // if(anim.name.equals("Armature|Idle1")){
|
|
// // System.out.println(anim.duration);
|
|
// // for(electrosphere.renderer.anim.AnimChannel channel : anim.channels){
|
|
// // if(channel.getNodeID().equals("Torso")){
|
|
// // channel.fullDescribeChannel();
|
|
// // }
|
|
// // // System.out.println("CHannel: " + channel.getNodeID());
|
|
// // }
|
|
// // break;
|
|
// // }
|
|
// // }
|
|
// model.animations.get(0).fullDescribeAnimation();
|
|
// // model.describeHighLevel();
|
|
// System.exit(0);
|
|
// }
|
|
|
|
//create the audio context
|
|
if(Globals.RUN_CLIENT && !Globals.HEADLESS){
|
|
Globals.virtualAudioSourceManager = new VirtualAudioSourceManager();
|
|
Globals.audioEngine = new AudioEngine();
|
|
Globals.audioEngine.init();
|
|
Globals.audioEngine.listAllDevices();
|
|
Globals.initDefaultAudioResources();
|
|
// Globals.audioEngine.setGain(0.1f);
|
|
}
|
|
|
|
//init timekeeper
|
|
Globals.timekeeper.init(targetFramePeriod);
|
|
|
|
//fire off a loading thread for the title menus/screen
|
|
LoggerInterface.loggerStartup.INFO("Fire off loading thread");
|
|
if(Globals.RUN_CLIENT){
|
|
LoadingThread serverThread = new LoadingThread(LoadingThread.LOAD_TITLE_MENU);
|
|
Globals.loadingThreadsList.add(serverThread);
|
|
serverThread.start();
|
|
} else {
|
|
LoadingThread clientThread = new LoadingThread(LoadingThread.LOAD_ARENA);
|
|
Globals.loadingThreadsList.add(clientThread);
|
|
clientThread.start();
|
|
}
|
|
|
|
//recapture the screen for rendering
|
|
if(Globals.RUN_CLIENT && !Globals.HEADLESS){
|
|
LoggerInterface.loggerStartup.INFO("Recapture screen");
|
|
Globals.controlHandler.setRecapture(true);
|
|
}
|
|
// RenderUtils.recaptureScreen();
|
|
}
|
|
|
|
/**
|
|
* Runs the main loop indefinitely. Blocks the thread this is called in.
|
|
*/
|
|
public static void mainLoop(){
|
|
mainLoop(0);
|
|
}
|
|
|
|
/**
|
|
* Runs the main loop for a specified number of frames.
|
|
* @param maxFrames The number of frames to run for. If 0, will run indefinitely.
|
|
*/
|
|
public static void mainLoop(long maxFrames){
|
|
|
|
double functionTrackTimeStart = 0;
|
|
//main loop
|
|
while (running) {
|
|
|
|
Globals.profiler.beginRootCpuSample("frame");
|
|
LoggerInterface.loggerEngine.DEBUG("Begin Main Loop Frame");
|
|
|
|
//
|
|
//Update timekeeper
|
|
//
|
|
Globals.timekeeper.update();
|
|
|
|
|
|
|
|
///
|
|
/// A S S E T M A N A G E R S T U F F
|
|
///
|
|
if(Globals.RUN_CLIENT){
|
|
Globals.profiler.beginCpuSample("Load Assets");
|
|
LoggerInterface.loggerEngine.DEBUG("Begin load assets");
|
|
Globals.assetManager.loadAssetsInQueue();
|
|
Globals.profiler.endCpuSample();
|
|
}
|
|
|
|
|
|
|
|
|
|
///
|
|
/// C L I E N T N E T W O R K I N G S T U F F
|
|
///
|
|
//Why is this its own function? Just to get the networking code out of main()
|
|
if(Globals.clientConnection != null){
|
|
Globals.profiler.beginCpuSample("Client networking");
|
|
LoggerInterface.loggerEngine.DEBUG("Begin parse client messages");
|
|
Globals.clientConnection.parseMessages();
|
|
Globals.profiler.endCpuSample();
|
|
}
|
|
|
|
|
|
|
|
///
|
|
/// I N P U T C O N T R O L S
|
|
///
|
|
//Poll controls
|
|
if(Globals.RUN_CLIENT){
|
|
Globals.profiler.beginCpuSample("Poll Controls");
|
|
LoggerInterface.loggerEngine.DEBUG("Begin recapture screen");
|
|
Globals.controlHandler.pollControls();
|
|
RenderingEngine.recaptureIfNecessary();
|
|
Globals.profiler.endCpuSample();
|
|
}
|
|
|
|
|
|
///
|
|
///
|
|
/// M A I N S I M U L A T I O N I N N E R L O O P
|
|
///
|
|
|
|
int simFrameHardcapCounter = 0;
|
|
while(Globals.timekeeper.pullFromAccumulator() && framestep > 0 && simFrameHardcapCounter < Timekeeper.SIM_FRAME_HARDCAP){
|
|
|
|
//sim frame hard cap counter increment
|
|
simFrameHardcapCounter++;
|
|
//handle framestep
|
|
if(framestep == 1){
|
|
framestep = 0;
|
|
}
|
|
|
|
|
|
|
|
///
|
|
/// C L I E N T S I M U L A T I O N S T U F F
|
|
///
|
|
LoggerInterface.loggerEngine.DEBUG("Begin client simulation");
|
|
if(Globals.clientSimulation != null){
|
|
Globals.profiler.beginCpuSample("Client simulation");
|
|
Globals.clientSimulation.simulate();
|
|
Globals.profiler.endCpuSample();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///
|
|
/// S E R V E R M I C R O S I M U L A T I O N
|
|
///
|
|
Globals.profiler.beginCpuSample("Server simulation");
|
|
LoggerInterface.loggerEngine.DEBUG("Begin server micro simulation");
|
|
if(Globals.realmManager != null){
|
|
Globals.realmManager.simulate();
|
|
}
|
|
|
|
///
|
|
/// M A C R O S I M U L A T I O N S T U F F
|
|
///
|
|
LoggerInterface.loggerEngine.DEBUG("Begin server macro simulation");
|
|
if(Globals.macroSimulation != null && Globals.macroSimulation.isReady()){
|
|
Globals.macroSimulation.simulate();
|
|
}
|
|
Globals.profiler.endCpuSample();
|
|
}
|
|
|
|
|
|
|
|
|
|
///
|
|
/// M A I N R E N D E R F U N C T I O N
|
|
///
|
|
LoggerInterface.loggerEngine.DEBUG("Begin rendering call");
|
|
if(Globals.RUN_CLIENT && !Globals.HEADLESS){
|
|
Globals.profiler.beginCpuSample("render");
|
|
Globals.renderingEngine.drawScreen();
|
|
Globals.profiler.endCpuSample();
|
|
}
|
|
|
|
|
|
|
|
|
|
///
|
|
/// G A R B A G E C H E C K
|
|
///
|
|
Globals.profiler.beginCpuSample("gc");
|
|
if(Globals.EXPLICIT_GC){
|
|
System.gc();
|
|
}
|
|
Globals.profiler.endCpuSample();
|
|
|
|
|
|
|
|
|
|
|
|
///
|
|
/// S H U T D O W N C H E C K
|
|
///
|
|
|
|
if(Globals.HEADLESS){
|
|
if(Globals.ENGINE_SHUTDOWN_FLAG){
|
|
running = false;
|
|
}
|
|
} else {
|
|
if(Globals.ENGINE_SHUTDOWN_FLAG || (Globals.RUN_CLIENT && glfwWindowShouldClose(Globals.window))){
|
|
running = false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// C L E A N U P T I M E V A R I A B L E S
|
|
//
|
|
Globals.profiler.beginCpuSample("sleep");
|
|
if(Globals.timekeeper.getMostRecentRawFrametime() < targetFramePeriod){
|
|
sleep((int)(1000.0 * (targetFramePeriod - Globals.timekeeper.getMostRecentRawFrametime())));
|
|
} else {
|
|
sleep(1);
|
|
}
|
|
Globals.profiler.endCpuSample();
|
|
Globals.timekeeper.numberOfRenderedFrames++;
|
|
if(maxFrames > 0 && Globals.timekeeper.numberOfRenderedFrames > maxFrames){
|
|
running = false;
|
|
}
|
|
|
|
|
|
//
|
|
// End main loop
|
|
//
|
|
LoggerInterface.loggerEngine.DEBUG("End Main Loop Frame");
|
|
Globals.profiler.endCpuSample();
|
|
|
|
}
|
|
|
|
LoggerInterface.loggerEngine.WARNING("ENGINE SHUTDOWN");
|
|
//
|
|
// S H U T D O W N
|
|
//
|
|
//Terminate the program.
|
|
if(!Globals.HEADLESS && Globals.RUN_CLIENT){
|
|
glfwTerminate();
|
|
}
|
|
//used to signal threads to stop
|
|
running = false;
|
|
if(Globals.server != null){
|
|
Globals.server.close();
|
|
if(Globals.serverThread != null){
|
|
Globals.serverThread.interrupt();
|
|
}
|
|
}
|
|
//shut down audio engine
|
|
if(!Globals.HEADLESS && Globals.RUN_CLIENT){
|
|
Globals.audioEngine.shutdown();
|
|
}
|
|
//if netmonitor is running, close
|
|
if(Globals.netMonitor != null){
|
|
Globals.netMonitor.close();
|
|
}
|
|
//shutdown ode
|
|
OdeHelper.closeODE();
|
|
}
|
|
|
|
static void sleep(int i) {
|
|
try {
|
|
TimeUnit.MILLISECONDS.sleep(i);
|
|
} catch (InterruptedException ex) {
|
|
System.out.println("Sleep somehow interrupted?!");
|
|
}
|
|
}
|
|
|
|
|
|
public static boolean isRunning(){
|
|
return running;
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void initControlHandler(){
|
|
LoggerInterface.loggerStartup.INFO("Initialize control handler");
|
|
Globals.controlHandler = ControlHandler.generateExampleControlsMap();
|
|
Globals.controlHandler.setCallbacks();
|
|
// Globals.controlHandler = FileLoadingUtils.loadModelObjectFromBakedJsonFile("/Config/keybinds.json",ControlHandler.class);
|
|
}
|
|
|
|
/**
|
|
* Sets the framestep state (2 to resume automatic, 1 to make single step)
|
|
* @param framestep 2 - automatic framestep, 1 - single step, 0 - no step
|
|
*/
|
|
public static void setFramestep(int framestep){
|
|
Main.framestep = framestep;
|
|
}
|
|
|
|
|
|
|
|
|
|
// public static void updateMouseVariables(){
|
|
// glfwGetCursorPos(Globals.window, mouse_X_Buffer, mouse_Y_Buffer);
|
|
// xpos = mouse_X_Buffer[0];
|
|
// ypos = mouse_Y_Buffer[0];
|
|
// float xoffset = (float) (xpos - mouse_lastX) * mouseSensitivity;
|
|
// float yoffset = (float) (mouse_lastY - ypos) * mouseSensitivity;
|
|
// mouse_lastX = (float) xpos;
|
|
// mouse_lastY = (float) ypos;
|
|
|
|
// if(Globals.controlHandler != null && !Globals.controlHandler.isMouseVisible()){
|
|
// yaw = yaw + xoffset;
|
|
// pitch = pitch - yoffset;
|
|
|
|
// if (pitch > 100.0f) {
|
|
// pitch = 100.0f;
|
|
// }
|
|
// if (pitch < -99.0f) {
|
|
// pitch = -99.0f;
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
|
|
|
|
}
|