parent
							
								
									e4e7aa7eb3
								
							
						
					
					
						commit
						e03d547fab
					
				@ -0,0 +1,276 @@ | 
				
			|||||||
 | 
					package mightypork.gamecore.control; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.File; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import javax.swing.JOptionPane; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import mightypork.gamecore.audio.SoundSystem; | 
				
			||||||
 | 
					import mightypork.gamecore.control.bus.EventBus; | 
				
			||||||
 | 
					import mightypork.gamecore.control.bus.events.*; | 
				
			||||||
 | 
					import mightypork.gamecore.control.interf.Destroyable; | 
				
			||||||
 | 
					import mightypork.gamecore.control.interf.NoImpl; | 
				
			||||||
 | 
					import mightypork.gamecore.control.interf.Updateable; | 
				
			||||||
 | 
					import mightypork.gamecore.gui.screens.ScreenRegistry; | 
				
			||||||
 | 
					import mightypork.gamecore.input.InputSystem; | 
				
			||||||
 | 
					import mightypork.gamecore.loading.AsyncResourceLoader; | 
				
			||||||
 | 
					import mightypork.gamecore.render.DisplaySystem; | 
				
			||||||
 | 
					import mightypork.rogue.util.SlickLogRedirector; | 
				
			||||||
 | 
					import mightypork.utils.files.InstanceLock; | 
				
			||||||
 | 
					import mightypork.utils.logging.Log; | 
				
			||||||
 | 
					import mightypork.utils.logging.LogInstance; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * Basic screen-based game with subsystems.<br> | 
				
			||||||
 | 
					 * This class takes care of the initialization sequence. | 
				
			||||||
 | 
					 *  | 
				
			||||||
 | 
					 * @author MightyPork | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					public abstract class BaseApp implements AppAccess { | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						// modules
 | 
				
			||||||
 | 
						private InputSystem inputSystem; | 
				
			||||||
 | 
						private DisplaySystem displaySystem; | 
				
			||||||
 | 
						private SoundSystem soundSystem; | 
				
			||||||
 | 
						private EventBus eventBus; | 
				
			||||||
 | 
						private GameLoop gameLoop; | 
				
			||||||
 | 
						private ScreenRegistry screenRegistry; | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						/** | 
				
			||||||
 | 
						 * Start the application | 
				
			||||||
 | 
						 */ | 
				
			||||||
 | 
						public void start() | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							Log.i("Commencing initialization sequence..."); | 
				
			||||||
 | 
							 | 
				
			||||||
 | 
							initialize(); | 
				
			||||||
 | 
							 | 
				
			||||||
 | 
							Log.i("Starting main loop..."); | 
				
			||||||
 | 
							 | 
				
			||||||
 | 
							// open first screen		
 | 
				
			||||||
 | 
							gameLoop.start(); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						protected void initialize() | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							preInit(); | 
				
			||||||
 | 
							 | 
				
			||||||
 | 
							/* | 
				
			||||||
 | 
							 *  Lock working directory | 
				
			||||||
 | 
							 */ | 
				
			||||||
 | 
							initLock(); | 
				
			||||||
 | 
							 | 
				
			||||||
 | 
							/* | 
				
			||||||
 | 
							 * Setup logging | 
				
			||||||
 | 
							 */ | 
				
			||||||
 | 
							final LogInstance log = createLog(); | 
				
			||||||
 | 
							org.newdawn.slick.util.Log.setLogSystem(new SlickLogRedirector(log)); | 
				
			||||||
 | 
							 | 
				
			||||||
 | 
							// only here it makes sense to log.
 | 
				
			||||||
 | 
							Log.f1("Initializing subsystems..."); | 
				
			||||||
 | 
							 | 
				
			||||||
 | 
							/* | 
				
			||||||
 | 
							 * Event bus | 
				
			||||||
 | 
							 */ | 
				
			||||||
 | 
							Log.f2("Starting Event Bus..."); | 
				
			||||||
 | 
							eventBus = new EventBus(); | 
				
			||||||
 | 
							 | 
				
			||||||
 | 
							Log.f3("Registering channels..."); | 
				
			||||||
 | 
							initChannels(eventBus); | 
				
			||||||
 | 
							 | 
				
			||||||
 | 
							/* | 
				
			||||||
 | 
							 * Display | 
				
			||||||
 | 
							 */ | 
				
			||||||
 | 
							Log.f2("Initializing Display System..."); | 
				
			||||||
 | 
							displaySystem = new DisplaySystem(this); | 
				
			||||||
 | 
							initDisplay(displaySystem); | 
				
			||||||
 | 
							 | 
				
			||||||
 | 
							/* | 
				
			||||||
 | 
							 * Audio | 
				
			||||||
 | 
							 */ | 
				
			||||||
 | 
							Log.f2("Initializing Sound System..."); | 
				
			||||||
 | 
							soundSystem = new SoundSystem(this); | 
				
			||||||
 | 
							initSoundSystem(soundSystem); | 
				
			||||||
 | 
							 | 
				
			||||||
 | 
							/* | 
				
			||||||
 | 
							 * Input | 
				
			||||||
 | 
							 */ | 
				
			||||||
 | 
							Log.f2("Initializing Input System..."); | 
				
			||||||
 | 
							inputSystem = new InputSystem(this); | 
				
			||||||
 | 
							initKeystrokes(inputSystem); | 
				
			||||||
 | 
							 | 
				
			||||||
 | 
							/* | 
				
			||||||
 | 
							 * Prepare main loop | 
				
			||||||
 | 
							 */ | 
				
			||||||
 | 
							Log.f1("Creating Screen Registry and Game Loop..."); | 
				
			||||||
 | 
							screenRegistry = new ScreenRegistry(this); | 
				
			||||||
 | 
							gameLoop = createLoop(); | 
				
			||||||
 | 
							gameLoop.setRootRenderable(screenRegistry); | 
				
			||||||
 | 
							 | 
				
			||||||
 | 
							/* | 
				
			||||||
 | 
							 * Load resources | 
				
			||||||
 | 
							 *  | 
				
			||||||
 | 
							 * Resources should be registered to banks, and AsyncResourceLoader will load them. | 
				
			||||||
 | 
							 */ | 
				
			||||||
 | 
							Log.f1("Loading resources..."); | 
				
			||||||
 | 
							AsyncResourceLoader.launch(this); | 
				
			||||||
 | 
							initResources(); | 
				
			||||||
 | 
							 | 
				
			||||||
 | 
							/* | 
				
			||||||
 | 
							 * Screen registry | 
				
			||||||
 | 
							 *  | 
				
			||||||
 | 
							 * Must be after resources, because screens can request them during instantiation. | 
				
			||||||
 | 
							 */ | 
				
			||||||
 | 
							Log.f2("Registering screens..."); | 
				
			||||||
 | 
							initScreens(screenRegistry); | 
				
			||||||
 | 
							 | 
				
			||||||
 | 
							postInit(); | 
				
			||||||
 | 
							Log.i("Initialized sequence completed."); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						@NoImpl | 
				
			||||||
 | 
						protected void preInit() | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						@NoImpl | 
				
			||||||
 | 
						protected void postInit() | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						protected abstract LogInstance createLog(); | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						protected abstract void initDisplay(DisplaySystem display); | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						protected abstract void initSoundSystem(SoundSystem audio); | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						protected abstract void initKeystrokes(InputSystem input); | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						protected abstract void initResources(); | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						protected abstract void initScreens(ScreenRegistry screens); | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						protected abstract GameLoop createLoop(); | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						protected void initChannels(EventBus bus) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							// framework events
 | 
				
			||||||
 | 
							bus.addChannel(DestroyEvent.class, Destroyable.class); | 
				
			||||||
 | 
							bus.addChannel(UpdateEvent.class, Updateable.class); | 
				
			||||||
 | 
							 | 
				
			||||||
 | 
							// input events
 | 
				
			||||||
 | 
							bus.addChannel(ScreenChangeEvent.class, ScreenChangeEvent.Listener.class); | 
				
			||||||
 | 
							bus.addChannel(KeyEvent.class, KeyEvent.Listener.class); | 
				
			||||||
 | 
							bus.addChannel(MouseMotionEvent.class, MouseMotionEvent.Listener.class); | 
				
			||||||
 | 
							bus.addChannel(MouseButtonEvent.class, MouseButtonEvent.Listener.class); | 
				
			||||||
 | 
							 | 
				
			||||||
 | 
							// control events
 | 
				
			||||||
 | 
							bus.addChannel(ScreenRequestEvent.class, ScreenRequestEvent.Listener.class); | 
				
			||||||
 | 
							bus.addChannel(ResourceLoadRequest.class, ResourceLoadRequest.Listener.class); | 
				
			||||||
 | 
							bus.addChannel(MainLoopTaskRequest.class, MainLoopTaskRequest.Listener.class); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						/** | 
				
			||||||
 | 
						 * Try to obtain lock. | 
				
			||||||
 | 
						 */ | 
				
			||||||
 | 
						private void initLock() | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							final File lockFile = getLockFile(); | 
				
			||||||
 | 
							 | 
				
			||||||
 | 
							if (lockFile == null) { | 
				
			||||||
 | 
								// lock off
 | 
				
			||||||
 | 
								return; | 
				
			||||||
 | 
							} | 
				
			||||||
 | 
							 | 
				
			||||||
 | 
							if (!InstanceLock.onFile(lockFile)) { | 
				
			||||||
 | 
								onLockError(); | 
				
			||||||
 | 
								return; | 
				
			||||||
 | 
							} | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						/** | 
				
			||||||
 | 
						 * Triggered when lock cannot be obtained.<br> | 
				
			||||||
 | 
						 * App should terminate gracefully. | 
				
			||||||
 | 
						 */ | 
				
			||||||
 | 
						protected void onLockError() | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							System.err.println("Could not obtain lock file.\nOnly one instance can run at a time."); | 
				
			||||||
 | 
							 | 
				
			||||||
 | 
							//@formatter:off
 | 
				
			||||||
 | 
							JOptionPane.showMessageDialog( | 
				
			||||||
 | 
									null, | 
				
			||||||
 | 
									"Another instance is already running.", | 
				
			||||||
 | 
									"Lock Error", | 
				
			||||||
 | 
									JOptionPane.ERROR_MESSAGE | 
				
			||||||
 | 
							); | 
				
			||||||
 | 
							//@formatter:on
 | 
				
			||||||
 | 
							 | 
				
			||||||
 | 
							shutdown(); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						/** | 
				
			||||||
 | 
						 * Get lock file path; Used to enforce single-instance policy. | 
				
			||||||
 | 
						 *  | 
				
			||||||
 | 
						 * @return lock file, or null to disable lock. | 
				
			||||||
 | 
						 */ | 
				
			||||||
 | 
						protected abstract File getLockFile(); | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						@Override | 
				
			||||||
 | 
						public final SoundSystem getSoundSystem() | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							return soundSystem; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						@Override | 
				
			||||||
 | 
						public final InputSystem getInput() | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							return inputSystem; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						@Override | 
				
			||||||
 | 
						public final DisplaySystem getDisplay() | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							return displaySystem; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						@Override | 
				
			||||||
 | 
						public final EventBus getEventBus() | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							return eventBus; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						 | 
				
			||||||
 | 
						@Override | 
				
			||||||
 | 
						public void shutdown() | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							Log.i("Shutting down subsystems..."); | 
				
			||||||
 | 
							 | 
				
			||||||
 | 
							if (getEventBus() != null) { | 
				
			||||||
 | 
								getEventBus().send(new DestroyEvent()); | 
				
			||||||
 | 
								getEventBus().destroy(); | 
				
			||||||
 | 
							} | 
				
			||||||
 | 
							 | 
				
			||||||
 | 
							Log.i("Terminating..."); | 
				
			||||||
 | 
							System.exit(0); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					} | 
				
			||||||
@ -1,4 +1,4 @@ | 
				
			|||||||
package mightypork.gamecore; | 
					package mightypork.rogue.util; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import mightypork.utils.logging.LogInstance; | 
					import mightypork.utils.logging.LogInstance; | 
				
			||||||
					Loading…
					
					
				
		Reference in new issue