/** Gives a chance to subsystems to do something BEFORE managers and Time are initialized. */ private void preInitSubsystems() { changeStatus(TerasologyEngineStatus.PREPARING_SUBSYSTEMS); for (EngineSubsystem subsystem : getSubsystems()) { changeStatus(() -> "Pre-initialising " + subsystem.getName() + " subsystem"); subsystem.preInitialise(rootContext); } }
private void initSubsystems() { changeStatus(TerasologyEngineStatus.INITIALIZING_SUBSYSTEMS); for (EngineSubsystem subsystem : getSubsystems()) { changeStatus(() -> "Initialising " + subsystem.getName() + " subsystem"); subsystem.initialise(this, rootContext); } }
/** * Disposes of the engine by disposing of its subsystems. Originally this method was called * dispose(), but to improve Exception handling in the PC Facade the GameEngine interface * implemented by this class was made to extend AutoCloseable. This in turn requires a close() * method. */ @Override public void close() { /* * The engine is shutdown even when in RUNNING state. This way terasology gets properly disposed also in * case of a crash: The mouse must be made visible again for the crash reporter and the main window needs to * be closed. */ engineState = EngineState.DISPOSED; Iterator<EngineSubsystem> iter = subsystems.descendingIterator(); while (iter.hasNext()) { EngineSubsystem subsystem = iter.next(); try { subsystem.dispose(); } catch (Throwable t) { logger.error("Unable to dispose subsystem {}", subsystem, t); } } }
private void cleanup() { logger.info("Shutting down Terasology..."); try { Iterator<EngineSubsystem> iter = subsystems.descendingIterator(); while (iter.hasNext()) { EngineSubsystem subsystem = iter.next(); subsystem.shutdown(config); } config.save(); if (currentState != null) { currentState.dispose(); currentState = null; } } finally { // Even if a graceful shutdown of the subsystems fails, // the thread pool has to be shut down stopThreads(); } }
private void cleanup() { logger.info("Shutting down Terasology..."); changeStatus(StandardGameStatus.SHUTTING_DOWN); if (currentState != null) { currentState.dispose(); currentState = null; } Iterator<EngineSubsystem> preshutdownIter = allSubsystems.descendingIterator(); while (preshutdownIter.hasNext()) { EngineSubsystem subsystem = preshutdownIter.next(); try { subsystem.preShutdown(); } catch (RuntimeException e) { logger.error("Error preparing to shutdown {} subsystem", subsystem.getName(), e); } } Iterator<EngineSubsystem> shutdownIter = allSubsystems.descendingIterator(); while (shutdownIter.hasNext()) { EngineSubsystem subsystem = shutdownIter.next(); try { subsystem.shutdown(); } catch (RuntimeException e) { logger.error("Error shutting down {} subsystem", subsystem.getName(), e); } } }
private void initAssets() { DefaultBlockFamilyFactoryRegistry familyFactoryRegistry = new DefaultBlockFamilyFactoryRegistry(); rootContext.put(BlockFamilyFactoryRegistry.class, familyFactoryRegistry); // cast lambdas explicitly to avoid inconsistent compiler behavior wrt. type inference assetTypeManager.registerCoreAssetType( Prefab.class, (AssetFactory<Prefab, PrefabData>) PojoPrefab::new, false, "prefabs"); assetTypeManager.registerCoreAssetType( BlockShape.class, (AssetFactory<BlockShape, BlockShapeData>) BlockShapeImpl::new, "shapes"); assetTypeManager.registerCoreAssetType( BlockSounds.class, (AssetFactory<BlockSounds, BlockSoundsData>) BlockSounds::new, "blockSounds"); assetTypeManager.registerCoreAssetType( BlockTile.class, (AssetFactory<BlockTile, TileData>) BlockTile::new, "blockTiles"); assetTypeManager.registerCoreAssetType( BlockFamilyDefinition.class, (AssetFactory<BlockFamilyDefinition, BlockFamilyDefinitionData>) BlockFamilyDefinition::new, "blocks"); assetTypeManager.registerCoreFormat( BlockFamilyDefinition.class, new BlockFamilyDefinitionFormat(assetTypeManager.getAssetManager(), familyFactoryRegistry)); assetTypeManager.registerCoreAssetType( UISkin.class, (AssetFactory<UISkin, UISkinData>) UISkin::new, "skins"); assetTypeManager.registerCoreAssetType( BehaviorTree.class, (AssetFactory<BehaviorTree, BehaviorTreeData>) BehaviorTree::new, false, "behaviors"); assetTypeManager.registerCoreAssetType( UIElement.class, (AssetFactory<UIElement, UIData>) UIElement::new, "ui"); for (EngineSubsystem subsystem : allSubsystems) { subsystem.registerCoreAssetTypes(assetTypeManager); } }
/** * The main loop runs until the EngineState is set back to INITIALIZED by shutdown() or until the * OS requests the application's window to be closed. Engine cleanup and disposal occur * afterwards. */ private void mainLoop() { PerformanceMonitor.startActivity("Other"); // MAIN GAME LOOP while (!shutdownRequested) { assetTypeManager.reloadChangedOnDisk(); processPendingState(); if (currentState == null) { shutdown(); break; } Iterator<Float> updateCycles = timeSubsystem.getEngineTime().tick(); for (EngineSubsystem subsystem : allSubsystems) { try (Activity ignored = PerformanceMonitor.startActivity(subsystem.getName() + " PreUpdate")) { subsystem.preUpdate(currentState, timeSubsystem.getEngineTime().getRealDelta()); } } while (updateCycles.hasNext()) { float updateDelta = updateCycles.next(); // gameTime gets updated here! try (Activity ignored = PerformanceMonitor.startActivity("Main Update")) { currentState.update(updateDelta); } } // Waiting processes are set by modules via GameThread.a/synch() methods. GameThread.processWaitingProcesses(); for (EngineSubsystem subsystem : getSubsystems()) { try (Activity ignored = PerformanceMonitor.startActivity(subsystem.getName() + " Subsystem postUpdate")) { subsystem.postUpdate(currentState, timeSubsystem.getEngineTime().getRealDelta()); } } assetTypeManager.disposedUnusedAssets(); PerformanceMonitor.rollCycle(); PerformanceMonitor.startActivity("Other"); } PerformanceMonitor.endActivity(); }
/** Gives a chance to subsystems to do something AFTER managers and Time are initialized. */ private void postInitSubsystems() { for (EngineSubsystem subsystem : getSubsystems()) { subsystem.postInitialise(rootContext); } }
/** * The main loop runs until the EngineState is set back to INITIALIZED by shutdown() or until the * OS requests the application's window to be closed. Engine cleanup and disposal occur * afterwards. */ private void mainLoop() { NetworkSystem networkSystem = CoreRegistry.get(NetworkSystem.class); DisplayDevice display = CoreRegistry.get(DisplayDevice.class); PerformanceMonitor.startActivity("Other"); // MAIN GAME LOOP while (engineState == EngineState.RUNNING && !display.isCloseRequested()) { long totalDelta; float updateDelta; float subsystemsDelta; // Only process rendering and updating once a second if (!display.isActive() && isHibernationAllowed()) { time.setPaused(true); Iterator<Float> updateCycles = time.tick(); while (updateCycles.hasNext()) { updateCycles.next(); } try { Thread.sleep(100); } catch (InterruptedException e) { logger.warn("Display inactivity sleep interrupted", e); } display.processMessages(); time.setPaused(false); continue; } processPendingState(); if (currentState == null) { shutdown(); break; } Iterator<Float> updateCycles = time.tick(); try (Activity ignored = PerformanceMonitor.startActivity("Network Update")) { networkSystem.update(); } totalDelta = 0; while (updateCycles.hasNext()) { updateDelta = updateCycles.next(); // gameTime gets updated here! totalDelta += time.getDeltaInMs(); try (Activity ignored = PerformanceMonitor.startActivity("Main Update")) { currentState.update(updateDelta); } } subsystemsDelta = totalDelta / 1000f; for (EngineSubsystem subsystem : getSubsystems()) { try (Activity ignored = PerformanceMonitor.startActivity(subsystem.getClass().getSimpleName())) { subsystem.preUpdate(currentState, subsystemsDelta); } } // Waiting processes are set by modules via GameThread.a/synch() methods. GameThread.processWaitingProcesses(); for (EngineSubsystem subsystem : getSubsystems()) { try (Activity ignored = PerformanceMonitor.startActivity(subsystem.getClass().getSimpleName())) { subsystem.postUpdate(currentState, subsystemsDelta); } } PerformanceMonitor.rollCycle(); PerformanceMonitor.startActivity("Other"); } PerformanceMonitor.endActivity(); // This becomes important only if display.isCloseRequested() is true. // In all other circumstances the EngineState is already set to // INITIALIZED by the time the flow gets here. engineState = EngineState.INITIALIZED; }
/** Gives a chance to subsystems to do something AFTER managers and Time are initialized. */ private void postInitSubsystems() { for (EngineSubsystem subsystem : getSubsystems()) { subsystem.postInitialise(config); } }
/** Gives a chance to subsystems to do something BEFORE managers and Time are initialized. */ private void preInitSubsystems() { for (EngineSubsystem subsystem : getSubsystems()) { subsystem.preInitialise(); } }