Fix backing out to main menu
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit

This commit is contained in:
austin 2024-11-20 19:12:18 -05:00
parent fc4f124a25
commit b892bea3d3
19 changed files with 166 additions and 36 deletions

View File

@ -1093,6 +1093,10 @@ Add engine logo to title menu
Use STBttf for font loading/remove dependency on java.awt.fonts Use STBttf for font loading/remove dependency on java.awt.fonts
Fix font height lookups in string carousel, text input, and word Fix font height lookups in string carousel, text input, and word
Fix invalid audio source ID bug Fix invalid audio source ID bug
Up threshold on tests for approximate color matching
Refactor signal service subscription mechanism
Add main thread signal service
Fix backing out to main menu
# TODO # TODO
@ -1119,10 +1123,6 @@ Implement gadgets
- Torch - Torch
- Throwable potions - Throwable potions
Ability to fully reload game engine state without exiting client
- Back out to main menu and load a new level without any values persisting
- Receive a teleport packet from server and flush all game state before requesting state from server again
Bug Fixes Bug Fixes
- Fix hitbox placement does not scale with entity scale on server - Fix hitbox placement does not scale with entity scale on server
- Fix not all grass tiles update when updating a nearby voxel (ie it doesn't go into negative coordinates to scan for foliage updates) - Fix not all grass tiles update when updating a nearby voxel (ie it doesn't go into negative coordinates to scan for foliage updates)

View File

@ -9,6 +9,7 @@ import electrosphere.client.entity.instance.InstanceTemplate;
import electrosphere.client.entity.instance.InstancedEntityUtils; import electrosphere.client.entity.instance.InstancedEntityUtils;
import electrosphere.engine.assetmanager.AssetDataStrings; import electrosphere.engine.assetmanager.AssetDataStrings;
import electrosphere.engine.signal.Signal; import electrosphere.engine.signal.Signal;
import electrosphere.engine.signal.Signal.SignalType;
import electrosphere.engine.signal.SignalServiceImpl; import electrosphere.engine.signal.SignalServiceImpl;
import electrosphere.entity.DrawableUtils; import electrosphere.entity.DrawableUtils;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
@ -73,7 +74,12 @@ public class ParticleService extends SignalServiceImpl {
* Constructor * Constructor
*/ */
public ParticleService() { public ParticleService() {
super("ParticleService"); super(
"ParticleService",
new SignalType[]{
SignalType.RENDERING_ENGINE_READY,
}
);
} }
@Override @Override

View File

@ -7,8 +7,6 @@ import electrosphere.client.ui.menu.WindowUtils;
import electrosphere.controls.ControlHandler.ControlsState; import electrosphere.controls.ControlHandler.ControlsState;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.Main; import electrosphere.engine.Main;
import electrosphere.engine.loadingthreads.LoadingThread;
import electrosphere.engine.loadingthreads.LoadingThread.LoadingThreadType;
import electrosphere.engine.signal.Signal.SignalType; import electrosphere.engine.signal.Signal.SignalType;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityDataStrings;
@ -77,7 +75,7 @@ public class MenuGeneratorsInGame {
//Return to main menu //Return to main menu
div.addChild(Button.createButton("Return To Main Menu", () -> { div.addChild(Button.createButton("Return To Main Menu", () -> {
Globals.threadManager.start(new LoadingThread(LoadingThreadType.RETURN_TITLE_MENU)); Globals.signalSystem.post(SignalType.ENGINE_RETURN_TO_TITLE);
})); }));

View File

@ -39,7 +39,7 @@ import electrosphere.engine.loadingthreads.InitialAssetLoading;
import electrosphere.engine.profiler.Profiler; import electrosphere.engine.profiler.Profiler;
import electrosphere.engine.service.ServiceManager; import electrosphere.engine.service.ServiceManager;
import electrosphere.engine.signal.SignalSystem; import electrosphere.engine.signal.SignalSystem;
import electrosphere.engine.signal.Signal.SignalType; import electrosphere.engine.signal.sync.MainThreadSignalService;
import electrosphere.engine.threads.ThreadManager; import electrosphere.engine.threads.ThreadManager;
import electrosphere.engine.time.Timekeeper; import electrosphere.engine.time.Timekeeper;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
@ -329,6 +329,9 @@ public class Globals {
//script engine //script engine
public static ScriptEngine scriptEngine; public static ScriptEngine scriptEngine;
//services
public static MainThreadSignalService mainThreadSignalService;
//client scene management //client scene management
public static Scene clientScene; public static Scene clientScene;
@ -534,6 +537,7 @@ public class Globals {
Globals.elementService = (ElementService)serviceManager.registerService(new ElementService()); Globals.elementService = (ElementService)serviceManager.registerService(new ElementService());
Globals.particleService = (ParticleService)serviceManager.registerService(new ParticleService()); Globals.particleService = (ParticleService)serviceManager.registerService(new ParticleService());
Globals.scriptEngine = (ScriptEngine)serviceManager.registerService(new ScriptEngine()); Globals.scriptEngine = (ScriptEngine)serviceManager.registerService(new ScriptEngine());
Globals.mainThreadSignalService = (MainThreadSignalService)serviceManager.registerService(new MainThreadSignalService());
serviceManager.instantiate(); serviceManager.instantiate();
// //
//End service manager //End service manager
@ -541,11 +545,10 @@ public class Globals {
// //
//Register all signals //Register all signals
Globals.signalSystem.registerService(SignalType.YOGA_APPLY, Globals.elementService); Globals.signalSystem.registerService(Globals.elementService);
Globals.signalSystem.registerService(SignalType.YOGA_DESTROY, Globals.elementService); Globals.signalSystem.registerService(Globals.particleService);
Globals.signalSystem.registerService(SignalType.UI_MODIFICATION, Globals.elementService); Globals.signalSystem.registerService(Globals.scriptEngine);
Globals.signalSystem.registerService(SignalType.RENDERING_ENGINE_READY, Globals.particleService); Globals.signalSystem.registerService(Globals.mainThreadSignalService);
Globals.signalSystem.registerService(SignalType.SCRIPT_RECOMPILE, Globals.scriptEngine);
} }

View File

@ -15,6 +15,7 @@ import electrosphere.controls.ControlHandler.ControlsState;
import electrosphere.engine.cli.CLIParser; import electrosphere.engine.cli.CLIParser;
import electrosphere.engine.loadingthreads.LoadingThread; import electrosphere.engine.loadingthreads.LoadingThread;
import electrosphere.engine.loadingthreads.LoadingThread.LoadingThreadType; import electrosphere.engine.loadingthreads.LoadingThread.LoadingThreadType;
import electrosphere.engine.signal.SynchronousSignalHandling;
import electrosphere.engine.time.Timekeeper; import electrosphere.engine.time.Timekeeper;
import electrosphere.game.server.world.MacroData; import electrosphere.game.server.world.MacroData;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
@ -298,7 +299,7 @@ public class Main {
/// ///
/// S Y N C H R O N O U S S I G N A L H A N D L I N G /// S Y N C H R O N O U S S I G N A L H A N D L I N G
/// ///
Globals.scriptEngine.handleAllSignals(); SynchronousSignalHandling.runMainThreadSignalHandlers();
/// ///
/// S C R I P T E N G I N E /// S C R I P T E N G I N E

View File

@ -7,7 +7,6 @@ import electrosphere.engine.Globals;
import electrosphere.engine.signal.Signal.SignalType; import electrosphere.engine.signal.Signal.SignalType;
import electrosphere.engine.threads.LabeledThread.ThreadLabel; import electrosphere.engine.threads.LabeledThread.ThreadLabel;
import electrosphere.renderer.ui.elements.Window; import electrosphere.renderer.ui.elements.Window;
import electrosphere.server.datacell.RealmManager;
/** /**
* Loading thread that returns the client to the main menu * Loading thread that returns the client to the main menu
@ -19,7 +18,7 @@ public class MainMenuLoading {
* Resets all state to main menu * Resets all state to main menu
* @param params not necessary * @param params not necessary
*/ */
protected static void returnToMainMenu(Object[] params){ public static void returnToMainMenu(Object[] params){
// //
//stop rendering game //stop rendering game
Globals.RENDER_FLAG_RENDER_SHADOW_MAP = false; Globals.RENDER_FLAG_RENDER_SHADOW_MAP = false;
@ -59,7 +58,8 @@ public class MainMenuLoading {
Globals.server.close(); Globals.server.close();
Globals.server = null; Globals.server = null;
Globals.serverSynchronizationManager = null; Globals.serverSynchronizationManager = null;
Globals.realmManager = new RealmManager(); Globals.realmManager.reset();
Globals.realmManager = null;
Globals.macroSimulation = null; Globals.macroSimulation = null;
} }

View File

@ -16,6 +16,7 @@ public class Signal {
//CORE ENGINE //CORE ENGINE
// //
ENGINE_SHUTDOWN, ENGINE_SHUTDOWN,
ENGINE_RETURN_TO_TITLE,
// //
//RENDERING //RENDERING

View File

@ -1,6 +1,9 @@
package electrosphere.engine.signal; package electrosphere.engine.signal;
import java.util.Collection;
import electrosphere.engine.service.Service; import electrosphere.engine.service.Service;
import electrosphere.engine.signal.Signal.SignalType;
/** /**
* A service that can receive a signal * A service that can receive a signal
@ -13,4 +16,10 @@ public interface SignalService extends Service {
*/ */
public void post(Signal signal); public void post(Signal signal);
/**
* Gets the collection of signal types that this service wants to subscribe to
* @return The collection of signal types
*/
public Collection<SignalType> getSubscriptionTargets();
} }

View File

@ -1,9 +1,12 @@
package electrosphere.engine.signal; package electrosphere.engine.signal;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.concurrent.Semaphore; import java.util.concurrent.Semaphore;
import electrosphere.engine.signal.Signal.SignalType;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
/** /**
@ -26,13 +29,20 @@ public class SignalServiceImpl implements SignalService {
*/ */
String serviceName; String serviceName;
/**
* The list of signal types that this service wants to listen for
*/
List<SignalType> targetTypes;
/** /**
* Constructor, used to require certain fields be provided to this service instance * Constructor, used to require certain fields be provided to this service instance
* @param serviceName The name of the service * @param serviceName The name of the service
* @param types The types of signals this service wants to subscribe to
*/ */
public SignalServiceImpl(String serviceName){ public SignalServiceImpl(String serviceName, SignalType[] types){
this.serviceName = serviceName; this.serviceName = serviceName;
this.targetTypes = Arrays.asList(types);
} }
@Override @Override
@ -108,5 +118,10 @@ public class SignalServiceImpl implements SignalService {
public boolean handle(Signal signal){ public boolean handle(Signal signal){
throw new UnsupportedOperationException("Unimplemented method 'getName'"); throw new UnsupportedOperationException("Unimplemented method 'getName'");
} }
@Override
public Collection<SignalType> getSubscriptionTargets() {
return this.targetTypes;
}
} }

View File

@ -51,7 +51,30 @@ public class SignalSystem implements Service {
* @param signalType The type of signal * @param signalType The type of signal
* @param service The service to associate with that signal type * @param service The service to associate with that signal type
*/ */
public void registerService(SignalType signalType, SignalService service){ public void registerService(SignalService service){
systemLock.acquireUninterruptibly();
LoggerInterface.loggerEngine.DEBUG("[SignalSystem] Register signal service " + service.getName());
for(SignalType signalType : service.getSubscriptionTargets()){
if(typeServiceMap.containsKey(signalType)){
Set<SignalService> services = this.typeServiceMap.get(signalType);
if(!services.contains(service)){
services.add(service);
}
} else {
Set<SignalService> services = new HashSet<SignalService>();
services.add(service);
this.typeServiceMap.put(signalType, services);
}
}
systemLock.release();
}
/**
* Registers a service to a type of signal
* @param signalType The type of signal
* @param service The service to associate with that signal type
*/
public void registerServiceToSignal(SignalType signalType, SignalService service){
systemLock.acquireUninterruptibly(); systemLock.acquireUninterruptibly();
LoggerInterface.loggerEngine.DEBUG("[SignalSystem] Register signal service " + service.getName()); LoggerInterface.loggerEngine.DEBUG("[SignalSystem] Register signal service " + service.getName());
if(typeServiceMap.containsKey(signalType)){ if(typeServiceMap.containsKey(signalType)){
@ -72,7 +95,7 @@ public class SignalSystem implements Service {
* @param signalType The type of signal * @param signalType The type of signal
* @param service The signal service to unassociate from that signal type * @param service The signal service to unassociate from that signal type
*/ */
public void deregisterService(SignalType signalType, SignalService service){ public void deregisterServiceToSignal(SignalType signalType, SignalService service){
systemLock.acquireUninterruptibly(); systemLock.acquireUninterruptibly();
LoggerInterface.loggerEngine.DEBUG("[SignalSystem] Deregister signal service " + service.getName()); LoggerInterface.loggerEngine.DEBUG("[SignalSystem] Deregister signal service " + service.getName());
if(typeServiceMap.containsKey(signalType)){ if(typeServiceMap.containsKey(signalType)){

View File

@ -0,0 +1,18 @@
package electrosphere.engine.signal;
import electrosphere.engine.Globals;
/**
* Synchronously handles signals
*/
public class SynchronousSignalHandling {
/**
* Runs the main thread signal handlers
*/
public static void runMainThreadSignalHandlers(){
Globals.scriptEngine.handleAllSignals();
Globals.mainThreadSignalService.handleAllSignals();
}
}

View File

@ -0,0 +1,38 @@
package electrosphere.engine.signal.sync;
import electrosphere.engine.loadingthreads.MainMenuLoading;
import electrosphere.engine.signal.Signal;
import electrosphere.engine.signal.Signal.SignalType;
import electrosphere.engine.signal.SignalServiceImpl;
import electrosphere.logger.LoggerInterface;
public class MainThreadSignalService extends SignalServiceImpl {
/**
* Constructor
*/
public MainThreadSignalService() {
super(
"MainThreadSignalService",
new SignalType[]{
SignalType.ENGINE_RETURN_TO_TITLE,
}
);
}
@Override
public boolean handle(Signal signal){
boolean rVal = false;
switch(signal.getType()){
case ENGINE_RETURN_TO_TITLE: {
MainMenuLoading.returnToMainMenu(null);
rVal = true;
} break;
default: {
LoggerInterface.loggerEngine.WARNING("MainThreadSignalService received signal that it does not have handling for! " + signal);
} break;
}
return rVal;
}
}

View File

@ -112,7 +112,7 @@ public class ThreadManager {
Globals.server.close(); Globals.server.close();
} }
if(Globals.realmManager.getRealms() != null){ if(Globals.realmManager != null && Globals.realmManager.getRealms() != null){
for(Realm realm : Globals.realmManager.getRealms()){ for(Realm realm : Globals.realmManager.getRealms()){
if(realm.getServerWorldData() != null && realm.getServerWorldData().getServerTerrainManager() != null){ if(realm.getServerWorldData() != null && realm.getServerWorldData().getServerTerrainManager() != null){
realm.getServerWorldData().getServerTerrainManager().closeThreads(); realm.getServerWorldData().getServerTerrainManager().closeThreads();

View File

@ -8,7 +8,6 @@ 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;
@ -321,7 +320,7 @@ public class ServerConnectionHandler implements Runnable {
TimeUnit.MILLISECONDS.sleep(1); TimeUnit.MILLISECONDS.sleep(1);
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
//silently ignore //silently ignore
CodeUtils.todo(ex, "Handle sleep interrupt on server connection"); // CodeUtils.todo(ex, "Handle sleep interrupt on server connection");
} }
return rVal; return rVal;
} }

View File

@ -13,6 +13,7 @@ import org.joml.Vector2i;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.signal.Signal; import electrosphere.engine.signal.Signal;
import electrosphere.engine.signal.Signal.SignalType;
import electrosphere.engine.signal.SignalServiceImpl; import electrosphere.engine.signal.SignalServiceImpl;
import electrosphere.renderer.ui.elements.Window; import electrosphere.renderer.ui.elements.Window;
import electrosphere.renderer.ui.elementtypes.ContainerElement; import electrosphere.renderer.ui.elementtypes.ContainerElement;
@ -39,7 +40,14 @@ public class ElementService extends SignalServiceImpl {
* Constructor * Constructor
*/ */
public ElementService() { public ElementService() {
super("ElementService"); super(
"ElementService",
new SignalType[]{
SignalType.YOGA_APPLY,
SignalType.YOGA_DESTROY,
SignalType.UI_MODIFICATION,
}
);
} }
Map<String,Element> elementMap = new ConcurrentHashMap<String,Element>(); Map<String,Element> elementMap = new ConcurrentHashMap<String,Element>();

View File

@ -28,6 +28,7 @@ import electrosphere.client.ui.menu.tutorial.TutorialMenus;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.engine.Main; import electrosphere.engine.Main;
import electrosphere.engine.signal.Signal; import electrosphere.engine.signal.Signal;
import electrosphere.engine.signal.Signal.SignalType;
import electrosphere.engine.signal.SignalServiceImpl; import electrosphere.engine.signal.SignalServiceImpl;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.script.translation.JSServerUtils; import electrosphere.script.translation.JSServerUtils;
@ -134,7 +135,12 @@ public class ScriptEngine extends SignalServiceImpl {
* Constructor * Constructor
*/ */
public ScriptEngine(){ public ScriptEngine(){
super("ScriptEngine"); super(
"ScriptEngine",
new SignalType[]{
SignalType.SCRIPT_RECOMPILE,
}
);
sourceMap = new HashMap<String,Source>(); sourceMap = new HashMap<String,Source>();
this.fs = FileSystems.getDefault(); this.fs = FileSystems.getDefault();
try { try {

View File

@ -209,6 +209,11 @@ public class RealmManager {
* Resets the realm manager * Resets the realm manager
*/ */
public void reset(){ public void reset(){
for(Realm realm : this.realms){
if(realm.getServerWorldData() != null && realm.getServerWorldData().getServerTerrainManager() != null){
realm.getServerWorldData().getServerTerrainManager().closeThreads();
}
}
this.realms.clear(); this.realms.clear();
this.entityToRealmMap.clear(); this.entityToRealmMap.clear();
this.playerToRealmMap.clear(); this.playerToRealmMap.clear();

View File

@ -36,7 +36,7 @@ public class SignalSystemTests {
SignalService service = Mockito.mock(SignalService.class); SignalService service = Mockito.mock(SignalService.class);
signalSystem.registerService(SignalType.YOGA_APPLY, service); signalSystem.registerServiceToSignal(SignalType.YOGA_APPLY, service);
} }
@ -46,7 +46,7 @@ public class SignalSystemTests {
signalSystem.init(); signalSystem.init();
SignalService service = Mockito.mock(SignalService.class); SignalService service = Mockito.mock(SignalService.class);
signalSystem.registerService(SignalType.YOGA_APPLY, service); signalSystem.registerServiceToSignal(SignalType.YOGA_APPLY, service);
signalSystem.post(SignalType.YOGA_APPLY); signalSystem.post(SignalType.YOGA_APPLY);
@ -60,8 +60,8 @@ public class SignalSystemTests {
SignalService service = Mockito.mock(SignalService.class); SignalService service = Mockito.mock(SignalService.class);
SignalService service2 = Mockito.mock(SignalService.class); SignalService service2 = Mockito.mock(SignalService.class);
signalSystem.registerService(SignalType.YOGA_APPLY, service); signalSystem.registerServiceToSignal(SignalType.YOGA_APPLY, service);
signalSystem.registerService(SignalType.YOGA_APPLY, service2); signalSystem.registerServiceToSignal(SignalType.YOGA_APPLY, service2);
signalSystem.post(SignalType.YOGA_APPLY); signalSystem.post(SignalType.YOGA_APPLY);
@ -77,9 +77,9 @@ public class SignalSystemTests {
SignalService service = Mockito.mock(SignalService.class); SignalService service = Mockito.mock(SignalService.class);
SignalService service2 = Mockito.mock(SignalService.class); SignalService service2 = Mockito.mock(SignalService.class);
SignalService service3 = Mockito.mock(SignalService.class); SignalService service3 = Mockito.mock(SignalService.class);
signalSystem.registerService(SignalType.YOGA_APPLY, service); signalSystem.registerServiceToSignal(SignalType.YOGA_APPLY, service);
signalSystem.registerService(SignalType.YOGA_APPLY, service2); signalSystem.registerServiceToSignal(SignalType.YOGA_APPLY, service2);
signalSystem.registerService(SignalType.ENGINE_SHUTDOWN, service3); signalSystem.registerServiceToSignal(SignalType.ENGINE_SHUTDOWN, service3);
signalSystem.post(SignalType.YOGA_APPLY); signalSystem.post(SignalType.YOGA_APPLY);
@ -95,8 +95,8 @@ public class SignalSystemTests {
signalSystem.init(); signalSystem.init();
SignalService service = Mockito.mock(SignalService.class); SignalService service = Mockito.mock(SignalService.class);
signalSystem.registerService(SignalType.YOGA_APPLY, service); signalSystem.registerServiceToSignal(SignalType.YOGA_APPLY, service);
signalSystem.deregisterService(SignalType.YOGA_APPLY, service); signalSystem.deregisterServiceToSignal(SignalType.YOGA_APPLY, service);
signalSystem.post(SignalType.YOGA_APPLY); signalSystem.post(SignalType.YOGA_APPLY);
Mockito.verify(service, Mockito.never()).post(signalCaptor.capture()); Mockito.verify(service, Mockito.never()).post(signalCaptor.capture());

View File

@ -20,7 +20,7 @@ public class Assertions {
/** /**
* The threshold at which we say the colors are 'close enough' * The threshold at which we say the colors are 'close enough'
*/ */
static final int COLOR_COMPARE_THRESHOLD = 3; static final int COLOR_COMPARE_THRESHOLD = 4;
/** /**
* A very small number for comparisons * A very small number for comparisons