501 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			501 lines
		
	
	
		
			16 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.controls.ControlHandler.ControlsState;
 | |
| 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.debug.ImGuiWindowMacros;
 | |
| import electrosphere.renderer.RenderingEngine;
 | |
| import electrosphere.server.MainServerFunctions;
 | |
| import electrosphere.server.simulation.MacroSimulation;
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * The main class
 | |
|  */
 | |
| 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 java pid of engine
 | |
|         Globals.javaPID = ManagementFactory.getRuntimeMXBean().getName();
 | |
| 
 | |
|         //load user settings
 | |
|         UserSettings.loadUserSettings();
 | |
|         
 | |
|         //init global variables
 | |
|         Globals.initGlobals();
 | |
| 
 | |
|         //init scripting engine
 | |
|         Globals.scriptEngine.init();
 | |
| 
 | |
|         //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){
 | |
|             //create opengl context
 | |
|             Globals.renderingEngine = new RenderingEngine();
 | |
|             Globals.renderingEngine.createOpenglContext();
 | |
|             Globals.initDefaultGraphicalResources();
 | |
|             ImGuiWindowMacros.initImGuiWindows();
 | |
| 
 | |
|             //inits the controls state of the control handler
 | |
|             Globals.controlHandler.hintUpdateControlState(ControlsState.TITLE_MENU);
 | |
| 
 | |
|             //start initial asset loading
 | |
|             new Thread(Globals.initialAssetLoadingThread).start();
 | |
|         }
 | |
| 
 | |
|         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/baseman9.glb");
 | |
|     //        Globals.assetManager.loadAssetsInQueue();
 | |
|     //        Model model = Globals.assetManager.fetchModel("/Models/baseman9.glb");
 | |
|     //     //    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.describeHighLevel();
 | |
|     //         // model.animations.get(0).fullDescribeAnimation();
 | |
|     //     //    model.describeHighLevel();
 | |
|     //        System.exit(0);
 | |
|     //    }
 | |
|         
 | |
|         //create the audio context
 | |
|         if(Globals.RUN_CLIENT && !Globals.HEADLESS && Globals.RUN_AUDIO){
 | |
|             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_DEMO){
 | |
|             LoadingThread serverThread = new LoadingThread(LoadingThread.LOAD_DEMO_MENU);
 | |
|             Globals.loadingThreadsList.add(serverThread);
 | |
|             serverThread.start();
 | |
|         } else 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){
 | |
| 
 | |
|         //main loop
 | |
|         while (running) {
 | |
| 
 | |
|             try {
 | |
| 
 | |
|             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 A I N     R O U T I N E S
 | |
|                 ///
 | |
|                 Globals.profiler.beginCpuSample("Main Server Functions");
 | |
|                 MainServerFunctions.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();
 | |
| 
 | |
|             } catch (NullPointerException ex){
 | |
|                 LoggerInterface.loggerEngine.ERROR("Main frame uncaught NPE", ex);
 | |
|                 //after a while, jvm will stop reporting stack traces with errors
 | |
|                 //need to explicitly kill the vm if you want to see the stack trace
 | |
|                 if(Globals.ENGINE_DEBUG){
 | |
|                     System.exit(1);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|         }
 | |
| 
 | |
|         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.RUN_AUDIO){
 | |
|             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;
 | |
|     //         }
 | |
|     //     }
 | |
|     // }
 | |
|     
 | |
|     
 | |
|     
 | |
| }
 |