thread manager
Some checks reported errors
studiorailgun/Renderer/pipeline/head Something is wrong with the build of this commit

This commit is contained in:
austin 2024-08-22 21:24:44 -04:00
parent d0e5f3b7d2
commit 5563b4366f
18 changed files with 189 additions and 97 deletions

View File

@ -623,6 +623,7 @@ Setup MantisBT
(08/22/2024) (08/22/2024)
Fix rendering testing on jenkins Fix rendering testing on jenkins
Fix entity scene test spinup by preventing networking sockets from closing Fix entity scene test spinup by preventing networking sockets from closing
Thread manager/tracker + properly closing threads on engine close
# TODO # TODO

View File

@ -1,8 +1,6 @@
package electrosphere.engine; package electrosphere.engine;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import org.joml.Matrix4f; import org.joml.Matrix4f;
import org.joml.Vector3f; import org.joml.Vector3f;
@ -32,7 +30,6 @@ import electrosphere.controls.ScrollCallback;
import electrosphere.engine.assetmanager.AssetDataStrings; import electrosphere.engine.assetmanager.AssetDataStrings;
import electrosphere.engine.assetmanager.AssetManager; import electrosphere.engine.assetmanager.AssetManager;
import electrosphere.engine.loadingthreads.InitialAssetLoading; import electrosphere.engine.loadingthreads.InitialAssetLoading;
import electrosphere.engine.loadingthreads.LoadingThread;
import electrosphere.engine.profiler.Profiler; import electrosphere.engine.profiler.Profiler;
import electrosphere.engine.time.Timekeeper; import electrosphere.engine.time.Timekeeper;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
@ -87,6 +84,11 @@ public class Globals {
//Process data //Process data
// //
public static String javaPID; public static String javaPID;
//
//Thread manager
//
public static ThreadManager threadManager = new ThreadManager();
// //
//Top level user settings object //Top level user settings object
@ -148,7 +150,6 @@ public class Globals {
// //
//Server manager thing //Server manager thing
// //
public static Thread serverThread;
public static Server server; public static Server server;
public static ServerSynchronizationManager serverSynchronizationManager = new ServerSynchronizationManager(); public static ServerSynchronizationManager serverSynchronizationManager = new ServerSynchronizationManager();
public static boolean RUN_SERVER = true; public static boolean RUN_SERVER = true;
@ -343,7 +344,6 @@ public class Globals {
public static ArrayList<Vector3f> skyboxColors; public static ArrayList<Vector3f> skyboxColors;
//thread for loading different game states //thread for loading different game states
public static List<LoadingThread> loadingThreadsList = new LinkedList<LoadingThread>();
public static InitialAssetLoading initialAssetLoadingThread = new InitialAssetLoading(); public static InitialAssetLoading initialAssetLoadingThread = new InitialAssetLoading();
//manager for all widgets currently being drawn to screen //manager for all widgets currently being drawn to screen

View File

@ -154,7 +154,7 @@ public class Main {
Globals.controlHandler.hintUpdateControlState(ControlsState.TITLE_MENU); Globals.controlHandler.hintUpdateControlState(ControlsState.TITLE_MENU);
//start initial asset loading //start initial asset loading
new Thread(Globals.initialAssetLoadingThread).start(); Globals.threadManager.start(new Thread(Globals.initialAssetLoadingThread));
} }
//Sets a hook that fires when the engine process stops //Sets a hook that fires when the engine process stops
@ -204,12 +204,10 @@ public class Main {
LoggerInterface.loggerStartup.INFO("Fire off loading thread"); LoggerInterface.loggerStartup.INFO("Fire off loading thread");
if(Globals.RUN_DEMO){ if(Globals.RUN_DEMO){
LoadingThread serverThread = new LoadingThread(LoadingThreadType.DEMO_MENU); LoadingThread serverThread = new LoadingThread(LoadingThreadType.DEMO_MENU);
Globals.loadingThreadsList.add(serverThread); Globals.threadManager.start(serverThread);
serverThread.start();
} else if(Globals.RUN_CLIENT){ } else if(Globals.RUN_CLIENT){
LoadingThread serverThread = new LoadingThread(LoadingThreadType.TITLE_MENU); LoadingThread serverThread = new LoadingThread(LoadingThreadType.TITLE_MENU);
Globals.loadingThreadsList.add(serverThread); Globals.threadManager.start(serverThread);
serverThread.start();
} else { } else {
throw new IllegalStateException("Need to add handling for only running server again"); throw new IllegalStateException("Need to add handling for only running server again");
} }
@ -247,9 +245,10 @@ public class Main {
LoggerInterface.loggerEngine.DEBUG_LOOP("Begin Main Loop Frame"); LoggerInterface.loggerEngine.DEBUG_LOOP("Begin Main Loop Frame");
// //
//Update timekeeper //Update timekeeper and thread manager
// //
Globals.timekeeper.update(); Globals.timekeeper.update();
Globals.threadManager.update();
@ -432,13 +431,7 @@ public class Main {
glfwTerminate(); glfwTerminate();
} }
//used to signal threads to stop //used to signal threads to stop
running = false; Globals.threadManager.close();
if(Globals.server != null){
Globals.server.close();
if(Globals.serverThread != null){
Globals.serverThread.interrupt();
}
}
//shut down audio engine //shut down audio engine
if(!Globals.HEADLESS && Globals.RUN_CLIENT && Globals.RUN_AUDIO && Globals.audioEngine != null && Globals.audioEngine.initialized()){ if(!Globals.HEADLESS && Globals.RUN_CLIENT && Globals.RUN_AUDIO && Globals.audioEngine != null && Globals.audioEngine.initialized()){
Globals.audioEngine.shutdown(); Globals.audioEngine.shutdown();
@ -460,11 +453,6 @@ public class Main {
} }
public static boolean isRunning(){
return running;
}
public static void initControlHandler(){ public static void initControlHandler(){

View File

@ -0,0 +1,110 @@
package electrosphere.engine;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Semaphore;
import electrosphere.engine.loadingthreads.LoadingThread;
/**
* Manages all running threads
*/
public class ThreadManager {
//Threadsafes the manager
Semaphore threadLock = new Semaphore(1);
//All threads that are actively running
private List<Thread> activeThreads = new LinkedList<Thread>();
//All loading threads that are actively running
private List<LoadingThread> loadingThreads = new LinkedList<LoadingThread>();
//Used by main thread to alert other threads whether they should keep running or not
private boolean shouldKeepRunning = true;
/**
* Updates what threads are being tracked
*/
public void update(){
threadLock.acquireUninterruptibly();
//
//remove loading threads
List<Thread> threadsToRemove = new LinkedList<Thread>();
for(LoadingThread thread : loadingThreads){
if(thread.isDone()){
System.out.println("Collect loading thread of type " + thread.getType());
threadsToRemove.add(thread);
}
}
for(Thread thread : threadsToRemove){
while(loadingThreads.contains(thread)){
loadingThreads.remove(thread);
}
}
threadLock.release();
}
/**
* Starts a new thread with tracking
* @param thread The thread to start
*/
public void start(Thread thread){
threadLock.acquireUninterruptibly();
activeThreads.add(thread);
thread.start();
threadLock.release();
}
/**
* Starts a new loading thread with tracking
* @param thread The loading thread to start
*/
public void start(LoadingThread thread){
threadLock.acquireUninterruptibly();
activeThreads.add(thread);
loadingThreads.add(thread);
thread.start();
threadLock.release();
}
/**
* Checks if any loading threads are active
* @return true if there is an active loading thread, false otherwise
*/
public boolean isLoading(){
return loadingThreads.size() > 0;
}
/**
* Tries to close all threads
*/
public void close(){
this.shouldKeepRunning = false;
threadLock.acquireUninterruptibly();
//for some reason, server must be explicitly closed
if(Globals.server != null){
Globals.server.close();
}
//
//interrupt all threads
for(Thread thread : activeThreads){
thread.interrupt();
}
threadLock.release();
}
/**
* Checks if the thread should keep running or not
* @return true if should keep running, false otherwise
*/
public boolean shouldKeepRunning(){
return this.shouldKeepRunning;
}
}

View File

@ -27,11 +27,20 @@ import electrosphere.renderer.ui.elements.Window;
public class ClientLoading { public class ClientLoading {
/**
* Loads the main menu
* @param params Params (this thread type does not accept any)
*/
protected static void loadMainMenu(Object[] params){ protected static void loadMainMenu(Object[] params){
Window loadingWindow = (Window)Globals.elementManager.getWindow(WindowStrings.WINDOW_LOADING); Window loadingWindow = (Window)Globals.elementManager.getWindow(WindowStrings.WINDOW_LOADING);
WindowUtils.recursiveSetVisible(loadingWindow,false); if(loadingWindow != null){
WindowUtils.recursiveSetVisible(loadingWindow,false);
}
WindowUtils.focusWindow(WindowStrings.WINDOW_MENU_MAIN); WindowUtils.focusWindow(WindowStrings.WINDOW_MENU_MAIN);
WindowUtils.recursiveSetVisible(Globals.elementManager.getWindow(WindowStrings.WINDOW_MENU_MAIN), true); Window mainMenuWindow = (Window)Globals.elementManager.getWindow(WindowStrings.WINDOW_MENU_MAIN);
if(mainMenuWindow != null){
WindowUtils.recursiveSetVisible(mainMenuWindow, true);
}
} }
@ -118,11 +127,9 @@ public class ClientLoading {
*/ */
private static void initClientThread(){ private static void initClientThread(){
//start client networking //start client networking
Thread clientThread = null;
if(Globals.RUN_CLIENT){ if(Globals.RUN_CLIENT){
Globals.clientConnection = new ClientNetworking(NetUtils.getAddress(),NetUtils.getPort()); Globals.clientConnection = new ClientNetworking(NetUtils.getAddress(),NetUtils.getPort());
clientThread = new Thread(Globals.clientConnection); Globals.threadManager.start(new Thread(Globals.clientConnection));
clientThread.start();
} }
} }

View File

@ -1,7 +1,5 @@
package electrosphere.engine.loadingthreads; package electrosphere.engine.loadingthreads;
import java.util.concurrent.Semaphore;
/** /**
* Threads for loading engine state * Threads for loading engine state
*/ */
@ -61,9 +59,9 @@ public class LoadingThread extends Thread {
//the params provided to this thread in particular //the params provided to this thread in particular
Object[] params; Object[] params;
//a lock to track when the loading had completed and block until then //tracks whether the thread is done loading or not
Semaphore lock; boolean isDone = false;
/** /**
* Creates the work for a loading thread * Creates the work for a loading thread
@ -73,12 +71,11 @@ public class LoadingThread extends Thread {
public LoadingThread(LoadingThreadType type, Object ... params){ public LoadingThread(LoadingThreadType type, Object ... params){
threadType = type; threadType = type;
this.params = params; this.params = params;
lock = new Semaphore(1);
} }
@Override @Override
public void run(){ public void run(){
lock.acquireUninterruptibly(); System.out.println("Start loading thread of type " + this.threadType);
switch(threadType){ switch(threadType){
case TITLE_MENU: { case TITLE_MENU: {
@ -119,7 +116,7 @@ public class LoadingThread extends Thread {
} break; } break;
} }
lock.release(); isDone = true;
} }
/** /**
@ -127,11 +124,15 @@ public class LoadingThread extends Thread {
* @return true if it has finished, false otherwise * @return true if it has finished, false otherwise
*/ */
public boolean isDone(){ public boolean isDone(){
boolean rVal = lock.tryAcquire(); return isDone;
if(rVal == true){ }
lock.release();
} /**
return rVal; * Gets the type of the loading thread
* @return The type
*/
public LoadingThreadType getType(){
return this.threadType;
} }
} }

View File

@ -63,8 +63,8 @@ public class LoadingUtils {
//start server networking //start server networking
if(Globals.RUN_SERVER){ if(Globals.RUN_SERVER){
Globals.server = new Server(NetUtils.getPort()); Globals.server = new Server(NetUtils.getPort());
Globals.serverThread = new Thread(Globals.server); Thread serverThread = new Thread(Globals.server);
Globals.serverThread.start(); Globals.threadManager.start(serverThread);
} }
} }
@ -78,11 +78,9 @@ public class LoadingUtils {
static void initClientThread(){ static void initClientThread(){
//start client networking //start client networking
Thread clientThread = null;
if(Globals.RUN_CLIENT){ if(Globals.RUN_CLIENT){
Globals.clientConnection = new ClientNetworking(NetUtils.getAddress(),NetUtils.getPort()); Globals.clientConnection = new ClientNetworking(NetUtils.getAddress(),NetUtils.getPort());
clientThread = new Thread(Globals.clientConnection); Globals.threadManager.start(new Thread(Globals.clientConnection));
clientThread.start();
} }
} }
@ -106,9 +104,7 @@ public class LoadingUtils {
rVal = Globals.server.addLocalPlayer(serverInput, serverOutput); rVal = Globals.server.addLocalPlayer(serverInput, serverOutput);
//start client communication thread //start client communication thread
Globals.clientConnection = new ClientNetworking(clientInput,clientOutput); Globals.clientConnection = new ClientNetworking(clientInput,clientOutput);
Thread clientThread = null; Globals.threadManager.start(new Thread(Globals.clientConnection));
clientThread = new Thread(Globals.clientConnection);
clientThread.start();
} catch (IOException e) { } catch (IOException e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();

View File

@ -51,13 +51,11 @@ public class MenuGenerators {
Globals.clientUsername = "username"; Globals.clientUsername = "username";
Globals.clientPassword = AuthenticationManager.getHashedString("password"); Globals.clientPassword = AuthenticationManager.getHashedString("password");
LoadingThread clientThread = new LoadingThread(LoadingThreadType.CHARACTER_SERVER); LoadingThread clientThread = new LoadingThread(LoadingThreadType.CHARACTER_SERVER);
Globals.loadingThreadsList.add(clientThread);
LoadingThread serverThread = new LoadingThread(LoadingThreadType.MAIN_GAME); LoadingThread serverThread = new LoadingThread(LoadingThreadType.MAIN_GAME);
Globals.loadingThreadsList.add(serverThread);
Globals.RUN_CLIENT = true; Globals.RUN_CLIENT = true;
Globals.RUN_SERVER = true; Globals.RUN_SERVER = true;
serverThread.start(); Globals.threadManager.start(serverThread);
clientThread.start(); Globals.threadManager.start(clientThread);
} else { } else {
SaveUtils.loadSave(saveName.toLowerCase(), false); SaveUtils.loadSave(saveName.toLowerCase(), false);
WindowUtils.replaceMainMenuContents(MenuGenerators.createSaveCreationMenu()); WindowUtils.replaceMainMenuContents(MenuGenerators.createSaveCreationMenu());
@ -182,13 +180,11 @@ public class MenuGenerators {
rVal.addChild(hostButton); rVal.addChild(hostButton);
hostButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){ hostButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
LoadingThread clientThread = new LoadingThread(LoadingThreadType.CHARACTER_SERVER); LoadingThread clientThread = new LoadingThread(LoadingThreadType.CHARACTER_SERVER);
Globals.loadingThreadsList.add(clientThread);
LoadingThread serverThread = new LoadingThread(LoadingThreadType.MAIN_GAME); LoadingThread serverThread = new LoadingThread(LoadingThreadType.MAIN_GAME);
Globals.loadingThreadsList.add(serverThread);
Globals.RUN_CLIENT = true; Globals.RUN_CLIENT = true;
Globals.RUN_SERVER = true; Globals.RUN_SERVER = true;
clientThread.start(); Globals.threadManager.start(serverThread);
serverThread.start(); Globals.threadManager.start(clientThread);
return false; return false;
}}); }});
@ -290,10 +286,9 @@ public class MenuGenerators {
Globals.clientUsername = usernameInput.getText(); Globals.clientUsername = usernameInput.getText();
Globals.clientPassword = AuthenticationManager.getHashedString(passwordInput.getText()); Globals.clientPassword = AuthenticationManager.getHashedString(passwordInput.getText());
LoadingThread clientThread = new LoadingThread(LoadingThreadType.CHARACTER_SERVER); LoadingThread clientThread = new LoadingThread(LoadingThreadType.CHARACTER_SERVER);
Globals.loadingThreadsList.add(clientThread);
Globals.RUN_CLIENT = true; Globals.RUN_CLIENT = true;
Globals.RUN_SERVER = false; Globals.RUN_SERVER = false;
clientThread.start(); Globals.threadManager.start(clientThread);
return false; return false;
}}); }});

View File

@ -89,10 +89,9 @@ public class MenuGeneratorsLevelEditor {
Button launchButton = Button.createButton(saveName, () -> { Button launchButton = Button.createButton(saveName, () -> {
//launch level //launch level
LoadingThread loadingThread = new LoadingThread(LoadingThreadType.LEVEL, saveName); LoadingThread loadingThread = new LoadingThread(LoadingThreadType.LEVEL, saveName);
Globals.loadingThreadsList.add(loadingThread);
Globals.RUN_CLIENT = true; Globals.RUN_CLIENT = true;
Globals.RUN_SERVER = true; Globals.RUN_SERVER = true;
loadingThread.start(); Globals.threadManager.start(loadingThread);
}); });
// //
@ -101,8 +100,7 @@ public class MenuGeneratorsLevelEditor {
Button editButton = Button.createButton("Edit", () -> { Button editButton = Button.createButton("Edit", () -> {
//launch level editor //launch level editor
LoadingThread loadingThread = new LoadingThread(LoadingThreadType.LEVEL_EDITOR, saveName); LoadingThread loadingThread = new LoadingThread(LoadingThreadType.LEVEL_EDITOR, saveName);
Globals.loadingThreadsList.add(loadingThread); Globals.threadManager.start(loadingThread);
loadingThread.start();
}); });
//create row //create row
@ -205,8 +203,7 @@ public class MenuGeneratorsLevelEditor {
rVal.addChild(Button.createButton("Create Level", () -> { rVal.addChild(Button.createButton("Create Level", () -> {
//launch level editor //launch level editor
LoadingThread loadingThread = new LoadingThread(LoadingThreadType.LEVEL_EDITOR, inFlightLevel); LoadingThread loadingThread = new LoadingThread(LoadingThreadType.LEVEL_EDITOR, inFlightLevel);
Globals.loadingThreadsList.add(loadingThread); Globals.threadManager.start(loadingThread);
loadingThread.start();
})); }));

View File

@ -89,10 +89,9 @@ public class MenuGeneratorsTitleMenu {
rVal.addChild(uiDebugSPQuickstartButton); rVal.addChild(uiDebugSPQuickstartButton);
uiDebugSPQuickstartButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){ uiDebugSPQuickstartButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
LoadingThread loadingThread = new LoadingThread(LoadingThreadType.DEBUG_RANDOM_SP_WORLD); LoadingThread loadingThread = new LoadingThread(LoadingThreadType.DEBUG_RANDOM_SP_WORLD);
Globals.loadingThreadsList.add(loadingThread);
Globals.RUN_CLIENT = true; Globals.RUN_CLIENT = true;
Globals.RUN_SERVER = true; Globals.RUN_SERVER = true;
loadingThread.start(); Globals.threadManager.start(loadingThread);
return false; return false;
}}); }});

View File

@ -1,14 +1,12 @@
package electrosphere.net.client; package electrosphere.net.client;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.Main;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.NetworkMessage; import electrosphere.net.parser.net.message.NetworkMessage;
import electrosphere.net.parser.net.message.ServerMessage; import electrosphere.net.parser.net.message.ServerMessage;
import electrosphere.net.parser.net.message.NetworkMessage.MessageType; import electrosphere.net.parser.net.message.NetworkMessage.MessageType;
import electrosphere.net.parser.net.message.ServerMessage.ServerMessageType; import electrosphere.net.parser.net.message.ServerMessage.ServerMessageType;
import electrosphere.net.parser.net.raw.NetworkParser; import electrosphere.net.parser.net.raw.NetworkParser;
import electrosphere.net.server.ServerConnectionHandler;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -170,7 +168,7 @@ public class ClientNetworking implements Runnable {
//start parsing messages //start parsing messages
initialized = true; initialized = true;
while((Main.isRunning() || !ServerConnectionHandler.AUTO_CLOSE_THREAD)){ while(Globals.threadManager.shouldKeepRunning()){
//attempt poll incoming messages //attempt poll incoming messages
parser.readMessagesIn(); parser.readMessagesIn();
//outgoing messages //outgoing messages
@ -207,6 +205,8 @@ public class ClientNetworking implements Runnable {
break; break;
} }
} }
LoggerInterface.loggerNetworking.WARNING("Client networking thread ended");
} }

View File

@ -25,8 +25,7 @@ public class CharacterProtocol implements ClientProtocolTemplate<CharacterMessag
Globals.clientConnection.queueOutgoingMessage(CharacterMessage.constructRequestSpawnCharacterMessage()); Globals.clientConnection.queueOutgoingMessage(CharacterMessage.constructRequestSpawnCharacterMessage());
Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestMetadataMessage()); Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestMetadataMessage());
LoadingThread clientThread = new LoadingThread(LoadingThreadType.CLIENT_WORLD); LoadingThread clientThread = new LoadingThread(LoadingThreadType.CLIENT_WORLD);
Globals.loadingThreadsList.add(clientThread); Globals.threadManager.start(clientThread);
clientThread.start();
break; break;
case REQUESTCHARACTERLIST: case REQUESTCHARACTERLIST:
case REQUESTCREATECHARACTER: case REQUESTCREATECHARACTER:

View File

@ -1,7 +1,6 @@
package electrosphere.net.server; package electrosphere.net.server;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.Main;
import electrosphere.entity.ServerEntityUtils; import electrosphere.entity.ServerEntityUtils;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.net.NetUtils; import electrosphere.net.NetUtils;
@ -24,7 +23,7 @@ import java.util.concurrent.Semaphore;
/** /**
* Lowest level networking class for the server * Lowest level networking class for the server
*/ */
public class Server implements Runnable{ public class Server implements Runnable {
//the port the server is running on //the port the server is running on
int port; int port;
@ -75,7 +74,7 @@ public class Server implements Runnable{
} catch (IOException ex) { } catch (IOException ex) {
LoggerInterface.loggerNetworking.ERROR("Failed to start server socket!",ex); LoggerInterface.loggerNetworking.ERROR("Failed to start server socket!",ex);
} }
while(Main.isRunning()){ while(Globals.threadManager.shouldKeepRunning()){
Socket newSocket; Socket newSocket;
try { try {
newSocket = serverSocket.accept(); newSocket = serverSocket.accept();
@ -84,7 +83,7 @@ public class Server implements Runnable{
// clientMap.put(newSocket.getInetAddress().getHostAddress(), newClient); // clientMap.put(newSocket.getInetAddress().getHostAddress(), newClient);
socketConnectionMap.put(newSocket, newClient); socketConnectionMap.put(newSocket, newClient);
activeConnections.add(newClient); activeConnections.add(newClient);
new Thread(newClient).start(); Globals.threadManager.start(new Thread(newClient));
connectListLock.release(); connectListLock.release();
} catch (SocketException ex){ } catch (SocketException ex){
LoggerInterface.loggerNetworking.ERROR("Socket closed!",ex); LoggerInterface.loggerNetworking.ERROR("Socket closed!",ex);
@ -92,6 +91,7 @@ public class Server implements Runnable{
LoggerInterface.loggerNetworking.ERROR("Socket error on client socket!",ex); LoggerInterface.loggerNetworking.ERROR("Socket error on client socket!",ex);
} }
} }
LoggerInterface.loggerNetworking.WARNING("Server socket thread ended");
} }
/** /**
@ -142,7 +142,7 @@ public class Server implements Runnable{
connectListLock.acquireUninterruptibly(); connectListLock.acquireUninterruptibly();
ServerConnectionHandler newClient = new ServerConnectionHandler(serverInputStream,serverOutputStream); ServerConnectionHandler newClient = new ServerConnectionHandler(serverInputStream,serverOutputStream);
activeConnections.add(newClient); activeConnections.add(newClient);
new Thread(newClient).start(); Globals.threadManager.start(new Thread(newClient));
connectListLock.release(); connectListLock.release();
return newClient; return newClient;
} }

View File

@ -2,13 +2,13 @@ package electrosphere.net.server;
import electrosphere.entity.types.creature.CreatureTemplate; import electrosphere.entity.types.creature.CreatureTemplate;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.Main;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.AuthMessage; import electrosphere.net.parser.net.message.AuthMessage;
import electrosphere.net.parser.net.message.NetworkMessage; import electrosphere.net.parser.net.message.NetworkMessage;
import electrosphere.net.parser.net.message.ServerMessage; import electrosphere.net.parser.net.message.ServerMessage;
import electrosphere.net.parser.net.raw.NetworkParser; import electrosphere.net.parser.net.raw.NetworkParser;
import electrosphere.net.server.player.Player; import electrosphere.net.server.player.Player;
import electrosphere.util.CodeUtils;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -25,12 +25,6 @@ import java.util.concurrent.TimeUnit;
* A connection to the server * A connection to the server
*/ */
public class ServerConnectionHandler implements Runnable { public class ServerConnectionHandler implements Runnable {
/**
* Automatically close threads if the main thread ends.
* Used to make sure threads don't close while running test suite.
*/
public static boolean AUTO_CLOSE_THREAD = true;
//the player id associated with this connection //the player id associated with this connection
static int playerIdIncrementer = 0; static int playerIdIncrementer = 0;
@ -199,7 +193,7 @@ public class ServerConnectionHandler implements Runnable {
initialized = true; initialized = true;
while((Main.isRunning() || !ServerConnectionHandler.AUTO_CLOSE_THREAD) && this.isConnected == true){ while(Globals.threadManager.shouldKeepRunning() && this.isConnected == true){
// //
// Main Loop // Main Loop
@ -314,7 +308,7 @@ public class ServerConnectionHandler implements Runnable {
//sleep //sleep
TimeUnit.MILLISECONDS.sleep(1); TimeUnit.MILLISECONDS.sleep(1);
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
ex.printStackTrace(); CodeUtils.todo(ex, "Handle sleep interrupt on server connection");
} }
} }

View File

@ -439,7 +439,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
} }
}); });
groundDataCells.get(getServerDataCellKey(worldPos)).setReady(false); groundDataCells.get(getServerDataCellKey(worldPos)).setReady(false);
thread.start(); Globals.threadManager.start(thread);
} }
/** /**

View File

@ -11,7 +11,6 @@ public class StartupTest {
@IntegrationSetup @IntegrationSetup
public void testStartupHeadless(){ public void testStartupHeadless(){
LoggerInterface.loggerEngine.INFO("[Test] Startup Headless");
Globals.RUN_CLIENT = false; Globals.RUN_CLIENT = false;
Globals.RUN_SERVER = true; Globals.RUN_SERVER = true;
Globals.HEADLESS = true; Globals.HEADLESS = true;
@ -23,7 +22,6 @@ public class StartupTest {
@IntegrationTest @IntegrationTest
public void testEmpty() { public void testEmpty() {
LoggerInterface.loggerEngine.INFO("[Test] Empty test");
} }
} }

View File

@ -3,7 +3,8 @@ package template;
import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Tag;
import annotations.IntegrationSetup; import annotations.IntegrationSetup;
import electrosphere.net.server.ServerConnectionHandler; import annotations.IntegrationTeardown;
import electrosphere.engine.Main;
import testutils.EngineInit; import testutils.EngineInit;
import testutils.TestEngineUtils; import testutils.TestEngineUtils;
@ -13,17 +14,25 @@ import testutils.TestEngineUtils;
*/ */
public abstract class EntityTestTemplate extends RenderingTestTemplate { public abstract class EntityTestTemplate extends RenderingTestTemplate {
/**
* Starts up the entity scene
*/
@IntegrationSetup @IntegrationSetup
@Override @Override
public void initEngine(){ public void initEngine(){
//init engine //init engine
TestEngineUtils.initGraphicalEngine(); TestEngineUtils.initGraphicalEngine();
//make sure the server network threads continue to execute even if the main thread dies
ServerConnectionHandler.AUTO_CLOSE_THREAD = false;
//load scene //load scene
EngineInit.setupConnectedTestScene(); EngineInit.setupConnectedTestScene();
} }
/**
* Shuts down the engine
*/
@IntegrationTeardown
public void closeEngine(){
Main.shutdown();
}
} }

View File

@ -5,8 +5,6 @@ import java.util.concurrent.TimeUnit;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.loadingthreads.LoadingThread; import electrosphere.engine.loadingthreads.LoadingThread;
import electrosphere.engine.loadingthreads.LoadingThread.LoadingThreadType; import electrosphere.engine.loadingthreads.LoadingThread.LoadingThreadType;
import electrosphere.menu.WindowStrings;
import electrosphere.renderer.ui.elements.Window;
public class EngineInit { public class EngineInit {
@ -17,11 +15,11 @@ public class EngineInit {
// //
//load the scene //load the scene
LoadingThread loadingThread = new LoadingThread(LoadingThreadType.LEVEL,"testscene1"); LoadingThread loadingThread = new LoadingThread(LoadingThreadType.LEVEL,"testscene1");
loadingThread.start(); Globals.threadManager.start(loadingThread);
// //
//wait for client to be fully init'd //wait for client to be fully init'd
while(((Window)Globals.elementManager.getWindow(WindowStrings.WINDOW_LOADING)).getVisible() || Globals.playerEntity == null){ while(Globals.threadManager.isLoading()){
TestEngineUtils.simulateFrames(1); TestEngineUtils.simulateFrames(1);
try { try {
TimeUnit.MILLISECONDS.sleep(1); TimeUnit.MILLISECONDS.sleep(1);