fix reloading world repeatedly

This commit is contained in:
austin 2025-05-15 11:28:37 -04:00
parent 7ad7a0c477
commit 2cf14bcdd2
15 changed files with 125 additions and 5 deletions

View File

@ -1797,6 +1797,7 @@ Utilities to free all of a type of resource
Slowdown entity tests to prevent VSCode from exploding when running tests
Fix static state caching between tests in visual shader construction
Safe executor service creation in non final static contexts
Fix reloading client world repeatedly

View File

@ -729,6 +729,7 @@ public class Globals {
Globals.realmManager.reset();
}
Globals.dbController.disconnect();
Globals.serviceManager.unloadScene();
}
/**

View File

@ -35,6 +35,8 @@ public class MainMenuLoading {
Globals.unloadScene();
Globals.threadManager.interruptLabel(ThreadLabel.NETWORKING_CLIENT);
Globals.threadManager.interruptLabel(ThreadLabel.NETWORKING_SERVER);
Globals.threadManager.awaitThreadClose(ThreadLabel.NETWORKING_CLIENT);
Globals.threadManager.awaitThreadClose(ThreadLabel.NETWORKING_SERVER);
//
//reveal in game main menu

View File

@ -15,6 +15,11 @@ public interface Service {
*/
public void destroy();
/**
* Resets the service on closing the client and/or server
*/
public void unloadScene();
/**
* Returns the name of the service
* @return

View File

@ -62,4 +62,13 @@ public class ServiceManager {
this.trackedServices = null;
}
/**
* Fires all functions required to unload a scene.
*/
public void unloadScene(){
for(Service serivce : this.trackedServices){
serivce.unloadScene();
}
}
}

View File

@ -123,5 +123,12 @@ public class SignalServiceImpl implements SignalService {
public Collection<SignalType> getSubscriptionTargets() {
return this.targetTypes;
}
@Override
public void unloadScene(){
this.threadLock.acquireUninterruptibly();
this.signals.clear();
this.threadLock.release();
}
}

View File

@ -142,5 +142,9 @@ public class SignalSystem implements Service {
public void post(SignalType type, Runnable runnable){
this.post(type,(Object)runnable);
}
@Override
public void unloadScene(){
}
}

View File

@ -9,9 +9,21 @@ public class LabeledThread {
* The label associated with the thread
*/
public static enum ThreadLabel {
/**
* The server socket networking thread
*/
NETWORKING_SERVER,
/**
* The client networking thread
*/
NETWORKING_CLIENT,
/**
* The main asset loading thread
*/
ASSET_LOADING,
/**
* The main loading thread
*/
LOADING,
}

View File

@ -83,8 +83,12 @@ public class ThreadManager {
* @param thread The thread to start
*/
public void start(ThreadLabel label, Thread thread){
if(label.toString() == null || label.toString().length() < 1){
throw new Error("Invalid label name! " + label.toString());
}
threadLock.lock();
activeThreads.add(new LabeledThread(label, thread));
thread.setName(label.toString());
thread.start();
threadLock.unlock();
}
@ -117,6 +121,22 @@ public class ThreadManager {
return Collections.unmodifiableList(loadingThreads);
}
/**
* Waits for a named thread to close
* @param label the label of the thread
*/
public void awaitThreadClose(ThreadLabel label){
boolean running = true;
while(running){
try {
TimeUnit.MILLISECONDS.sleep(1);
} catch (InterruptedException e) {
running = false;
}
running = this.isRunning(label);
}
}
/**
* Tries to close all threads
*/
@ -197,6 +217,39 @@ public class ThreadManager {
threadLock.unlock();
}
/**
* Updates the list of active threads
*/
private void updateActiveThreads(){
this.threadLock.lock();
List<LabeledThread> clearQueue = new LinkedList<LabeledThread>();
for(LabeledThread thread : activeThreads){
if(!thread.getThread().isAlive()){
clearQueue.add(thread);
}
}
activeThreads.removeAll(clearQueue);
this.threadLock.unlock();
}
/**
* Checks if a thread label is running
* @param label The label
* @return true if it is actively running, false otherwise
*/
public boolean isRunning(ThreadLabel label){
boolean rVal = false;
threadLock.lock();
this.updateActiveThreads();
for(LabeledThread thread : activeThreads){
if(thread.getLabel() == label){
rVal = true;
}
}
threadLock.unlock();
return rVal;
}
/**
* Requests a fixed-size thread pool
* @param threads The number of threads

View File

@ -241,6 +241,17 @@ public class ClientNetworking implements Runnable {
}
}
if(this.socket != null){
try {
this.socket.close();
} catch (IOException e) {
LoggerInterface.loggerNetworking.ERROR(e);
}
}
//null out global state
Globals.clientConnection = null;
LoggerInterface.loggerNetworking.INFO("Client networking thread ended");
}

View File

@ -117,7 +117,9 @@ public class Server implements Runnable {
LoggerInterface.loggerEngine.DEBUG("Failed to sleep", e);
}
}
this.isOpen = false;
this.close();
//null out global state
Globals.server = null;
LoggerInterface.loggerNetworking.INFO("Server socket thread ended");
}

View File

@ -297,6 +297,14 @@ public class ServerConnectionHandler implements Runnable {
}
}
if(this.socket != null){
try {
this.socket.close();
} catch (IOException e) {
LoggerInterface.loggerNetworking.ERROR(e);
}
}
LoggerInterface.loggerNetworking.INFO("Server connection thread ended");
}

View File

@ -10,7 +10,6 @@ import electrosphere.server.physics.block.diskmap.ServerBlockChunkDiskMap;
import electrosphere.util.annotation.Exclude;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
import org.joml.Vector3i;
@ -46,7 +45,7 @@ public class ServerBlockManager {
* The threadpool for chunk generation
*/
@Exclude
static final ExecutorService chunkExecutorService = Executors.newFixedThreadPool(ThreadCounts.SERVER_BLOCK_GENERATION_THREADS);
ExecutorService chunkExecutorService = Globals.threadManager.requestFixedThreadPool(ThreadCounts.SERVER_BLOCK_GENERATION_THREADS);
/**
* Constructor

View File

@ -20,7 +20,6 @@ import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
import org.joml.Vector3i;
@ -78,7 +77,7 @@ public class ServerTerrainManager {
* The threadpool for chunk generation
*/
@Exclude
static final ExecutorService chunkExecutorService = Executors.newFixedThreadPool(ThreadCounts.SERVER_TERRAIN_GENERATION_THREADS);
ExecutorService chunkExecutorService = Globals.threadManager.requestFixedThreadPool(ThreadCounts.SERVER_TERRAIN_GENERATION_THREADS);
/**
* Constructor

View File

@ -275,4 +275,11 @@ public class CharacterService extends SignalServiceImpl {
lock.unlock();
}
@Override
public void unloadScene(){
super.unloadScene();
this.loadedCharacterMap.clear();
this.characterEntityMap.clear();
}
}