/*
* Copyright 2013 MovingBlocks
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.terasology.engine.modes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.terasology.audio.AudioManager;
import org.terasology.config.Config;
import org.terasology.context.Context;
import org.terasology.engine.ComponentSystemManager;
import org.terasology.engine.GameEngine;
import org.terasology.engine.GameThread;
import org.terasology.engine.bootstrap.EnvironmentSwitchHandler;
import org.terasology.engine.module.ModuleManager;
import org.terasology.engine.subsystem.DisplayDevice;
import org.terasology.entitySystem.entity.internal.EngineEntityManager;
import org.terasology.entitySystem.event.internal.EventSystem;
import org.terasology.entitySystem.systems.UpdateSubscriberSystem;
import org.terasology.game.GameManifest;
import org.terasology.input.InputSystem;
import org.terasology.input.cameraTarget.CameraTargetSystem;
import org.terasology.logic.console.Console;
import org.terasology.module.Module;
import org.terasology.module.ModuleEnvironment;
import org.terasology.monitoring.PerformanceMonitor;
import org.terasology.network.NetworkMode;
import org.terasology.network.NetworkSystem;
import org.terasology.persistence.StorageManager;
import org.terasology.physics.engine.PhysicsEngine;
import org.terasology.rendering.nui.NUIManager;
import org.terasology.rendering.nui.databinding.ReadOnlyBinding;
import org.terasology.rendering.world.WorldRenderer;
import org.terasology.rendering.world.WorldRenderer.RenderingStage;
import org.terasology.world.chunks.ChunkProvider;
import java.util.Collections;
/**
* Play mode.
*
* @version 0.1
*/
public class StateIngame implements GameState {
private static final Logger logger = LoggerFactory.getLogger(StateIngame.class);
private ComponentSystemManager componentSystemManager;
private EventSystem eventSystem;
private NUIManager nuiManager;
private WorldRenderer worldRenderer;
private EngineEntityManager entityManager;
private CameraTargetSystem cameraTargetSystem;
private InputSystem inputSystem;
private NetworkSystem networkSystem;
private Context context;
/* GAME LOOP */
private boolean pauseGame;
private StorageManager storageManager;
private GameManifest gameManifest;
public StateIngame(GameManifest gameManifest, Context context) {
this.gameManifest = gameManifest;
this.context = context;
}
@Override
public void init(GameEngine engine) {
// context from loading state gets used.
nuiManager = context.get(NUIManager.class);
worldRenderer = context.get(WorldRenderer.class);
eventSystem = context.get(EventSystem.class);
componentSystemManager = context.get(ComponentSystemManager.class);
entityManager = context.get(EngineEntityManager.class);
cameraTargetSystem = context.get(CameraTargetSystem.class);
inputSystem = context.get(InputSystem.class);
eventSystem.registerEventHandler(nuiManager);
networkSystem = context.get(NetworkSystem.class);
storageManager = context.get(StorageManager.class);
// Show or hide the HUD according to the settings
nuiManager.getHUD().bindVisible(new ReadOnlyBinding<Boolean>() {
@Override
public Boolean get() {
return !context.get(Config.class).getRendering().getDebug().isHudHidden();
}
});
}
@Override
public void dispose() {
ChunkProvider chunkProvider = context.get(ChunkProvider.class);
chunkProvider.dispose();
boolean save = networkSystem.getMode().isAuthority();
if (save) {
storageManager.waitForCompletionOfPreviousSaveAndStartSaving();
}
networkSystem.shutdown();
// TODO: Shutdown background threads
eventSystem.process();
GameThread.processWaitingProcesses();
nuiManager.clear();
context.get(AudioManager.class).stopAllSounds();
if (worldRenderer != null) {
worldRenderer.dispose();
worldRenderer = null;
}
componentSystemManager.shutdown();
context.get(PhysicsEngine.class).dispose();
entityManager.clear();
if (storageManager != null) {
storageManager.finishSavingAndShutdown();
}
ModuleEnvironment oldEnvironment = context.get(ModuleManager.class).getEnvironment();
context.get(ModuleManager.class).loadEnvironment(Collections.<Module>emptySet(), true);
context.get(EnvironmentSwitchHandler.class).handleSwitchToEmptyEnivronment(context);
if (oldEnvironment != null) {
oldEnvironment.close();
}
context.get(Console.class).dispose();
GameThread.clearWaitingProcesses();
/*
* Clear the binding as otherwise the complete ingame state would be
* referenced.
*/
nuiManager.getHUD().clearVisibleBinding();
}
@Override
public void update(float delta) {
eventSystem.process();
for (UpdateSubscriberSystem system : componentSystemManager.iterateUpdateSubscribers()) {
PerformanceMonitor.startActivity(system.getClass().getSimpleName());
system.update(delta);
PerformanceMonitor.endActivity();
}
if (worldRenderer != null && shouldUpdateWorld()) {
worldRenderer.update(delta);
}
if (storageManager != null) {
storageManager.update();
}
updateUserInterface(delta);
}
@Override
public void handleInput(float delta) {
cameraTargetSystem.update(delta);
inputSystem.update(delta);
}
private boolean shouldUpdateWorld() {
return !pauseGame;
}
@Override
public void render() {
DisplayDevice display = context.get(DisplayDevice.class);
display.prepareToRender();
if (worldRenderer != null) {
if (!context.get(Config.class).getRendering().isVrSupport()) {
worldRenderer.render(RenderingStage.MONO);
} else {
worldRenderer.render(RenderingStage.LEFT_EYE);
worldRenderer.render(RenderingStage.RIGHT_EYE);
}
}
/* UI */
PerformanceMonitor.startActivity("Render and Update UI");
renderUserInterface();
PerformanceMonitor.endActivity();
}
@Override
public boolean isHibernationAllowed() {
return networkSystem.getMode() == NetworkMode.NONE;
}
@Override
public String getLoggingPhase() {
return gameManifest.getTitle();
}
public void renderUserInterface() {
PerformanceMonitor.startActivity("Rendering NUI");
nuiManager.render();
PerformanceMonitor.endActivity();
}
private void updateUserInterface(float delta) {
nuiManager.update(delta);
}
public void pause() {
pauseGame = true;
}
public void unpause() {
pauseGame = false;
}
public void togglePauseGame() {
if (pauseGame) {
unpause();
} else {
pause();
}
}
public boolean isGamePaused() {
return pauseGame;
}
public Context getContext() {
return context;
}
}