diff --git a/engine/src/main/java/org/terasology/engine/core/TerasologyEngine.java b/engine/src/main/java/org/terasology/engine/core/TerasologyEngine.java index fe3292ac3ac..912b3830dc3 100644 --- a/engine/src/main/java/org/terasology/engine/core/TerasologyEngine.java +++ b/engine/src/main/java/org/terasology/engine/core/TerasologyEngine.java @@ -247,7 +247,6 @@ private void verifyInitialisation() { verifyRequiredSystemIsRegistered(Time.class); verifyRequiredSystemIsRegistered(DisplayDevice.class); verifyRequiredSystemIsRegistered(RenderingSubsystemFactory.class); - verifyRequiredSystemIsRegistered(InputSystem.class); } /** @@ -588,7 +587,9 @@ private void switchState(GameState newState) { newState.init(this); stateChangeSubscribers.forEach(StateChangeSubscriber::onStateChange); InputSystem inputSystem = rootContext.get(InputSystem.class); - inputSystem.drainQueues(); + if (inputSystem != null) { + inputSystem.drainQueues(); + } } @Override diff --git a/engine/src/main/java/org/terasology/engine/core/modes/AbstractState.java b/engine/src/main/java/org/terasology/engine/core/modes/AbstractState.java index 11f03d46254..327b884d356 100644 --- a/engine/src/main/java/org/terasology/engine/core/modes/AbstractState.java +++ b/engine/src/main/java/org/terasology/engine/core/modes/AbstractState.java @@ -31,7 +31,7 @@ public abstract class AbstractState implements GameState { protected EventSystem eventSystem; protected ComponentSystemManager componentSystemManager; - protected void initEntityAndComponentManagers() { + protected void initEntityAndComponentManagers(boolean isHeadless) { verifyNotNull(context); CoreRegistry.setContext(context); @@ -41,9 +41,10 @@ protected void initEntityAndComponentManagers() { eventSystem = context.get(EventSystem.class); context.put(Console.class, new ConsoleImpl(context)); - - NUIManager nuiManager = new NUIManagerInternal((TerasologyCanvasRenderer) context.get(CanvasRenderer.class), context); - context.put(NUIManager.class, nuiManager); + if (!isHeadless) { + NUIManager nuiManager = new NUIManagerInternal((TerasologyCanvasRenderer) context.get(CanvasRenderer.class), context); + context.put(NUIManager.class, nuiManager); + } componentSystemManager = new ComponentSystemManager(context); context.put(ComponentSystemManager.class, componentSystemManager); diff --git a/engine/src/main/java/org/terasology/engine/core/modes/StateIngame.java b/engine/src/main/java/org/terasology/engine/core/modes/StateIngame.java index bdc3aa79c5e..2660c3ae33f 100644 --- a/engine/src/main/java/org/terasology/engine/core/modes/StateIngame.java +++ b/engine/src/main/java/org/terasology/engine/core/modes/StateIngame.java @@ -83,24 +83,28 @@ public void init(GameEngine engine) { componentSystemManager = context.get(ComponentSystemManager.class); entityManager = context.get(EngineEntityManager.class); cameraTargetSystem = context.get(CameraTargetSystem.class); - inputSystem = context.get(InputSystem.class); - eventSystem.registerEventHandler(nuiManager); + if (nuiManager != null) { + inputSystem = context.get(InputSystem.class); + eventSystem.registerEventHandler(nuiManager); + } networkSystem = context.get(NetworkSystem.class); storageManager = context.get(StorageManager.class); storageServiceWorker = context.get(StorageServiceWorker.class); console = context.get(Console.class); - // Show or hide the HUD according to the settings - nuiManager.getHUD().bindVisible(new ReadOnlyBinding() { - @Override - public Boolean get() { - return !context.get(Config.class).getRendering().getDebug().isHudHidden(); - } - }); + if (nuiManager != null) { + // Show or hide the HUD according to the settings + nuiManager.getHUD().bindVisible(new ReadOnlyBinding() { + @Override + public Boolean get() { + return !context.get(Config.class).getRendering().getDebug().isHudHidden(); + } + }); + } if (networkSystem.getMode() == NetworkMode.CLIENT) { String motd = networkSystem.getServer().getInfo().getMOTD(); - if (motd != null && motd.length() != 0) { + if (nuiManager != null && motd != null && motd.length() != 0) { nuiManager.pushScreen(MessagePopup.ASSET_URI, MessagePopup.class).setMessage("Server MOTD", motd); } } @@ -133,7 +137,9 @@ public void dispose(boolean shuttingDown) { // TODO: Shutdown background threads eventSystem.process(); GameThread.processWaitingProcesses(); - nuiManager.clear(); + if (nuiManager != null) { + nuiManager.clear(); + } context.get(AudioManager.class).stopAllSounds(); @@ -162,11 +168,13 @@ public void dispose(boolean shuttingDown) { console.dispose(); GameThread.clearWaitingProcesses(); - /* - * Clear the binding as otherwise the complete ingame state would be - * referenced. - */ - nuiManager.getHUD().clearVisibleBinding(); + if (nuiManager != null) { + /* + * Clear the binding as otherwise the complete ingame state would be + * referenced. + */ + nuiManager.getHUD().clearVisibleBinding(); + } } @Override @@ -187,8 +195,9 @@ public void update(float delta) { storageManager.update(); } - - updateUserInterface(delta); + if (nuiManager != null) { + updateUserInterface(delta); + } storageServiceWorker.flushNotificationsToConsole(console); } diff --git a/engine/src/main/java/org/terasology/engine/core/modes/StateLoading.java b/engine/src/main/java/org/terasology/engine/core/modes/StateLoading.java index f303a955e5b..f3051dd1e19 100644 --- a/engine/src/main/java/org/terasology/engine/core/modes/StateLoading.java +++ b/engine/src/main/java/org/terasology/engine/core/modes/StateLoading.java @@ -26,10 +26,10 @@ import org.terasology.engine.core.modes.loadProcesses.InitialisePhysics; import org.terasology.engine.core.modes.loadProcesses.InitialiseRecordAndReplay; import org.terasology.engine.core.modes.loadProcesses.InitialiseRemoteWorld; +import org.terasology.engine.core.modes.loadProcesses.InitialiseRendering; import org.terasology.engine.core.modes.loadProcesses.InitialiseSystems; import org.terasology.engine.core.modes.loadProcesses.InitialiseWorld; import org.terasology.engine.core.modes.loadProcesses.InitialiseWorldGenerator; -import org.terasology.engine.core.modes.loadProcesses.InitialiseRendering; import org.terasology.engine.core.modes.loadProcesses.JoinServer; import org.terasology.engine.core.modes.loadProcesses.LoadEntities; import org.terasology.engine.core.modes.loadProcesses.LoadExtraBlockData; @@ -110,8 +110,10 @@ public void init(GameEngine engine) { systemConfig = context.get(SystemConfig.class); - this.nuiManager = new NUIManagerInternal((TerasologyCanvasRenderer) context.get(CanvasRenderer.class), context); - context.put(NUIManager.class, nuiManager); + if (netMode.hasLocalClient()) { + this.nuiManager = new NUIManagerInternal((TerasologyCanvasRenderer) context.get(CanvasRenderer.class), context); + context.put(NUIManager.class, nuiManager); + } EngineTime time = (EngineTime) context.get(Time.class); time.setPaused(true); @@ -134,9 +136,10 @@ public void init(GameEngine engine) { } popStep(); - loadingScreen = nuiManager.pushScreen("engine:loadingScreen", LoadingScreen.class); - loadingScreen.updateStatus(current.getMessage(), current.getProgress()); - + if (nuiManager != null) { + loadingScreen = nuiManager.pushScreen("engine:loadingScreen", LoadingScreen.class); + loadingScreen.updateStatus(current.getMessage(), current.getProgress()); + } chunkGenerationStarted = false; } @@ -167,16 +170,20 @@ private void initClient() { private void initHost() { loadProcesses.add(new RegisterMods(context, gameManifest)); - if(netMode.hasLocalClient()) { + if (netMode.hasLocalClient()) { loadProcesses.add(new InitialiseRendering(context)); } loadProcesses.add(new InitialiseEntitySystem(context)); loadProcesses.add(new RegisterBlocks(context, gameManifest)); - loadProcesses.add(new InitialiseGraphics(context)); + if (netMode.hasLocalClient()) { + loadProcesses.add(new InitialiseGraphics(context)); + } loadProcesses.add(new LoadPrefabs(context)); loadProcesses.add(new ProcessBlockPrefabs(context)); loadProcesses.add(new InitialiseComponentSystemManager(context)); - loadProcesses.add(new RegisterInputSystem(context)); + if (netMode.hasLocalClient()) { + loadProcesses.add(new RegisterInputSystem(context)); + } loadProcesses.add(new RegisterSystems(context, netMode)); loadProcesses.add(new InitialiseCommandSystem(context)); loadProcesses.add(new LoadExtraBlockData(context)); @@ -252,14 +259,17 @@ public void update(float delta) { } } if (current == null) { - nuiManager.closeScreen(loadingScreen); - nuiManager.setHUDVisible(true); + if (nuiManager != null) { + nuiManager.closeScreen(loadingScreen); + nuiManager.setHUDVisible(true); + } context.get(GameEngine.class).changeState(new StateIngame(gameManifest, context)); } else { float progressValue = (progress + current.getExpectedCost() * current.getProgress()) / maxProgress; - loadingScreen.updateStatus(current.getMessage(), progressValue); - nuiManager.update(delta); - + if (nuiManager != null) { + loadingScreen.updateStatus(current.getMessage(), progressValue); + nuiManager.update(delta); + } // chunk generation begins at the AwaitCharacterSpawn step if (current instanceof AwaitCharacterSpawn && !chunkGenerationStarted) { chunkGenerationStarted = true; @@ -280,7 +290,9 @@ public void update(float delta) { @Override public void render() { - nuiManager.render(); + if (nuiManager != null) { + nuiManager.render(); + } } @Override diff --git a/engine/src/main/java/org/terasology/engine/core/modes/StateMainMenu.java b/engine/src/main/java/org/terasology/engine/core/modes/StateMainMenu.java index 5ea120c2d25..ae37cc064d4 100644 --- a/engine/src/main/java/org/terasology/engine/core/modes/StateMainMenu.java +++ b/engine/src/main/java/org/terasology/engine/core/modes/StateMainMenu.java @@ -44,7 +44,7 @@ public StateMainMenu(String showMessageOnLoad) { @Override public void init(GameEngine gameEngine) { context = gameEngine.createChildContext(); - initEntityAndComponentManagers(); + initEntityAndComponentManagers(false); createLocalPlayer(context); diff --git a/engine/src/main/java/org/terasology/engine/core/subsystem/headless/HeadlessInput.java b/engine/src/main/java/org/terasology/engine/core/subsystem/headless/HeadlessInput.java index 52ec44fd912..9a8dbc59933 100644 --- a/engine/src/main/java/org/terasology/engine/core/subsystem/headless/HeadlessInput.java +++ b/engine/src/main/java/org/terasology/engine/core/subsystem/headless/HeadlessInput.java @@ -4,7 +4,6 @@ import org.terasology.engine.context.Context; import org.terasology.engine.core.subsystem.EngineSubsystem; -import org.terasology.engine.input.InputSystem; public class HeadlessInput implements EngineSubsystem { @@ -19,8 +18,7 @@ public void postInitialise(Context context) { } private void initControls(Context context) { - InputSystem inputSystem = new InputSystem(); - context.put(InputSystem.class, inputSystem); + } } diff --git a/engine/src/main/java/org/terasology/engine/core/subsystem/headless/mode/StateHeadlessSetup.java b/engine/src/main/java/org/terasology/engine/core/subsystem/headless/mode/StateHeadlessSetup.java index c9be58d5226..4eae2b18c95 100644 --- a/engine/src/main/java/org/terasology/engine/core/subsystem/headless/mode/StateHeadlessSetup.java +++ b/engine/src/main/java/org/terasology/engine/core/subsystem/headless/mode/StateHeadlessSetup.java @@ -15,7 +15,6 @@ import org.terasology.engine.core.module.ModuleManager; import org.terasology.engine.core.module.StandardModuleExtension; import org.terasology.engine.game.GameManifest; -import org.terasology.engine.input.InputSystem; import org.terasology.engine.network.NetworkMode; import org.terasology.engine.rendering.nui.layers.mainMenu.savedGames.GameInfo; import org.terasology.engine.rendering.nui.layers.mainMenu.savedGames.GameProvider; @@ -40,12 +39,9 @@ public StateHeadlessSetup() { @Override public void init(GameEngine gameEngine) { context = gameEngine.createChildContext(); - initEntityAndComponentManagers(); + initEntityAndComponentManagers(true); createLocalPlayer(context); - componentSystemManager.register(context.get(InputSystem.class), "engine:InputSystem"); - componentSystemManager.initialise(); - GameManifest gameManifest; List savedGames = GameProvider.getSavedGames(); if (savedGames.size() > 0) { diff --git a/engine/src/main/java/org/terasology/engine/core/subsystem/headless/renderer/HeadlessWorldRenderer.java b/engine/src/main/java/org/terasology/engine/core/subsystem/headless/renderer/HeadlessWorldRenderer.java index 43a97ab95fb..74b903c665b 100644 --- a/engine/src/main/java/org/terasology/engine/core/subsystem/headless/renderer/HeadlessWorldRenderer.java +++ b/engine/src/main/java/org/terasology/engine/core/subsystem/headless/renderer/HeadlessWorldRenderer.java @@ -8,7 +8,6 @@ import org.joml.Vector3ic; import org.terasology.engine.config.Config; import org.terasology.engine.context.Context; -import org.terasology.engine.logic.players.LocalPlayerSystem; import org.terasology.engine.monitoring.PerformanceMonitor; import org.terasology.engine.rendering.assets.material.Material; import org.terasology.engine.rendering.cameras.Camera; @@ -48,8 +47,6 @@ public class HeadlessWorldRenderer implements WorldRenderer { public HeadlessWorldRenderer(Context context) { this.worldProvider = context.get(WorldProvider.class); this.chunkProvider = context.get(ChunkProvider.class); - LocalPlayerSystem localPlayerSystem = context.get(LocalPlayerSystem.class); - localPlayerSystem.setPlayerCamera(noCamera); config = context.get(Config.class); } diff --git a/engine/src/main/java/org/terasology/engine/input/InputSystem.java b/engine/src/main/java/org/terasology/engine/input/InputSystem.java index dafcd44bbe8..e6bde58ffdd 100644 --- a/engine/src/main/java/org/terasology/engine/input/InputSystem.java +++ b/engine/src/main/java/org/terasology/engine/input/InputSystem.java @@ -14,6 +14,7 @@ import org.terasology.engine.core.subsystem.config.BindsManager; import org.terasology.engine.entitySystem.entity.EntityRef; import org.terasology.engine.entitySystem.systems.BaseComponentSystem; +import org.terasology.engine.entitySystem.systems.RegisterMode; import org.terasology.engine.entitySystem.systems.RegisterSystem; import org.terasology.engine.input.cameraTarget.CameraTargetSystem; import org.terasology.engine.input.events.CharEvent; @@ -61,7 +62,7 @@ * In addition to raw keyboard and mouse input, the system handles Bind Buttons and Bind Axis, which can be mapped to * one or more inputs. */ -@RegisterSystem +@RegisterSystem(RegisterMode.CLIENT) public class InputSystem extends BaseComponentSystem { @In diff --git a/engine/src/main/java/org/terasology/engine/logic/chat/ChatSystem.java b/engine/src/main/java/org/terasology/engine/logic/chat/ChatSystem.java index 73d1b4aa5a8..fc0ea85081b 100644 --- a/engine/src/main/java/org/terasology/engine/logic/chat/ChatSystem.java +++ b/engine/src/main/java/org/terasology/engine/logic/chat/ChatSystem.java @@ -50,7 +50,9 @@ public class ChatSystem extends BaseComponentSystem { @Override public void initialise() { - overlay = nuiManager.addOverlay(NotificationOverlay.ASSET_URI, NotificationOverlay.class); + if (nuiManager != null) { + overlay = nuiManager.addOverlay(NotificationOverlay.ASSET_URI, NotificationOverlay.class); + } } @ReceiveEvent(components = ClientComponent.class) diff --git a/engine/src/main/java/org/terasology/engine/logic/console/ConsoleSystem.java b/engine/src/main/java/org/terasology/engine/logic/console/ConsoleSystem.java index a119315353f..99e6f701266 100644 --- a/engine/src/main/java/org/terasology/engine/logic/console/ConsoleSystem.java +++ b/engine/src/main/java/org/terasology/engine/logic/console/ConsoleSystem.java @@ -8,13 +8,13 @@ import org.terasology.engine.entitySystem.systems.BaseComponentSystem; import org.terasology.engine.entitySystem.systems.RegisterMode; import org.terasology.engine.entitySystem.systems.RegisterSystem; +import org.terasology.engine.input.binds.general.ConsoleButton; import org.terasology.engine.logic.console.commandSystem.ConsoleCommand; import org.terasology.engine.logic.console.ui.NotificationOverlay; -import org.terasology.input.ButtonState; -import org.terasology.engine.input.binds.general.ConsoleButton; import org.terasology.engine.network.ClientComponent; import org.terasology.engine.registry.In; import org.terasology.engine.rendering.nui.NUIManager; +import org.terasology.input.ButtonState; @RegisterSystem public class ConsoleSystem extends BaseComponentSystem { @@ -29,16 +29,18 @@ public class ConsoleSystem extends BaseComponentSystem { @Override public void initialise() { - overlay = nuiManager.addOverlay(NotificationOverlay.ASSET_URI, NotificationOverlay.class); - console.subscribe((Message message) -> { - if (!nuiManager.isOpen("engine:console")) { - // make sure the message isn't already shown in the chat overlay - if (message.getType() != CoreMessageType.CHAT && message.getType() != CoreMessageType.NOTIFICATION - || !nuiManager.isOpen("engine:chat")) { - overlay.setVisible(true); + if (nuiManager != null) { + overlay = nuiManager.addOverlay(NotificationOverlay.ASSET_URI, NotificationOverlay.class); + console.subscribe((Message message) -> { + if (!nuiManager.isOpen("engine:console")) { + // make sure the message isn't already shown in the chat overlay + if (message.getType() != CoreMessageType.CHAT && message.getType() != CoreMessageType.NOTIFICATION + || !nuiManager.isOpen("engine:chat")) { + overlay.setVisible(true); + } } - } - }); + }); + } } @ReceiveEvent(components = ClientComponent.class, priority = EventPriority.PRIORITY_CRITICAL) diff --git a/facades/PC/src/main/java/org/terasology/engine/Terasology.java b/facades/PC/src/main/java/org/terasology/engine/Terasology.java index 36a1f764246..321563a43d2 100644 --- a/facades/PC/src/main/java/org/terasology/engine/Terasology.java +++ b/facades/PC/src/main/java/org/terasology/engine/Terasology.java @@ -23,7 +23,6 @@ import org.terasology.engine.core.subsystem.config.BindsSubsystem; import org.terasology.engine.core.subsystem.headless.HeadlessAudio; import org.terasology.engine.core.subsystem.headless.HeadlessGraphics; -import org.terasology.engine.core.subsystem.headless.HeadlessInput; import org.terasology.engine.core.subsystem.headless.HeadlessTimer; import org.terasology.engine.core.subsystem.headless.mode.HeadlessStateChangeListener; import org.terasology.engine.core.subsystem.headless.mode.StateHeadlessSetup; @@ -270,8 +269,7 @@ private void populateSubsystems(TerasologyEngineBuilder builder) { if (isHeadless) { builder.add(new HeadlessGraphics()) .add(new HeadlessTimer()) - .add(new HeadlessAudio()) - .add(new HeadlessInput()); + .add(new HeadlessAudio()); } else { EngineSubsystem audio = soundEnabled ? new LwjglAudio() : new HeadlessAudio(); builder.add(audio)