Java tutorial
/******************************************************************************* * This file is part of TERMINAL RECALL * Copyright (c) 2012-2014 Chuck Ritola. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the COPYING and CREDITS files for more details. * * Contributors: * chuck - initial API and implementation ******************************************************************************/ package org.jtrfp.trcl.flow; import java.awt.Color; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.concurrent.ExecutionException; import javax.swing.DefaultListModel; import javax.swing.JOptionPane; import javax.swing.JTextArea; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; import org.jtrfp.jfdt.UnrecognizedFormatException; import org.jtrfp.jtrfp.FileLoadException; import org.jtrfp.jtrfp.pod.IPodData; import org.jtrfp.jtrfp.pod.PodFile; import org.jtrfp.trcl.Camera; import org.jtrfp.trcl.EarlyLoadingScreen; import org.jtrfp.trcl.GLFont; import org.jtrfp.trcl.beh.SkyCubeCloudModeUpdateBehavior; import org.jtrfp.trcl.core.Renderer; import org.jtrfp.trcl.core.TR; import org.jtrfp.trcl.core.TRConfiguration; import org.jtrfp.trcl.file.VOXFile; import org.jtrfp.trcl.prop.HorizGradientCubeGen; import org.jtrfp.trcl.prop.SkyCubeGen; public class GameShell { private final TR tr; public static final SkyCubeGen DEFAULT_GRADIENT = new HorizGradientCubeGen(Color.darkGray, Color.black); private EarlyLoadingScreen earlyLoadingScreen; private GLFont greenFont; public GameShell(TR tr) { this.tr = tr; tr.addPropertyChangeListener(TR.GAME, new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if (evt.getNewValue() == null) { earlyLoadingScreen.setStatusText("No game loaded."); showGameshellScreen(); } else { hideGameshellScreen(); } } }); }//end constructor(TR) public GameShell startShell() { tr.gatherSysInfo(); registerPODs(); applyGFXState(); initLoadingScreen(); return this; }//end startShell() public void showGameshellScreen() { earlyLoadingScreen.activate(); } public void hideGameshellScreen() { earlyLoadingScreen.deactivate(); } private void initLoadingScreen() { System.out.println("Initializing general resources..."); try { greenFont = new GLFont(tr.getResourceManager().getFont("OCRA.zip", "OCRA.ttf"), tr); earlyLoadingScreen = new EarlyLoadingScreen(tr.getDefaultGrid(), tr, greenFont); earlyLoadingScreen.setStatusText("No game loaded."); earlyLoadingScreen.activate(); } catch (Exception e) { gameFailure(e); } }//end initLoadingScreen() public void applyGFXState() { final Renderer renderer = tr.mainRenderer.get(); final Camera camera = renderer.getCamera(); camera.probeForBehavior(SkyCubeCloudModeUpdateBehavior.class).setEnable(false); renderer.getSkyCube().setSkyCubeGen(DEFAULT_GRADIENT); camera.setHeading(Vector3D.PLUS_I); camera.setTop(Vector3D.PLUS_J); } public GameShell newGame() { GameVersion newGameVersion = determineGameVersion(); tr.config.setGameVersion(newGameVersion != null ? newGameVersion : GameVersion.TV); VOXFile vox; vox = determineVOXFile(); if (vox == null) return this;//Abort final Game game = tr.newGame(vox); try { game.boot(); } catch (Exception e) { gameFailure(e); } return this; }//end newGame() public GameShell startGame() { try { tr.getGame().doGameplay(); } catch (Exception e) { gameFailure(e); } return this; } private void gameFailure(Exception e) { handleLoadFailureException(e); tr.abortCurrentGame(); } private void handleLoadFailureException(Throwable th) { assert th != null; while (th instanceof RuntimeException || th instanceof ExecutionException) if (th.getCause() != null) th = th.getCause(); else break; StringBuilder sb = new StringBuilder(); if (th instanceof FileNotFoundException) { sb.append("Could not load file from any of the registered PODs.\n"); sb.append("Ensure that the necessary PODs are registered in the File->Configure menu.\n"); } else if (th instanceof FileLoadException) { sb.append("File was found but could not be loaded, possibly by parsing/formatting error.\n"); } else if (th instanceof UnrecognizedFormatException) { sb.append( "File was found but could not be loaded to the LVL format being unrecognized. (parse error)\n"); } else if (th instanceof IllegalAccessException) { sb.append("Check disk permissions for registered PODs.\n"); } else if (th instanceof IOException) { sb.append("An undocumented IO failure has occurred..\n"); } if (th != null) throwable2StringBuilder(th, sb); JOptionPane.showMessageDialog(tr.getRootWindow(), new JTextArea(sb.toString()), "File Load Failure", JOptionPane.ERROR_MESSAGE); throw new RuntimeException(th); }//end handleLoadFailureException(...) private void throwable2StringBuilder(Throwable e, StringBuilder sb) { assert e != null; assert sb != null; sb.append(e.getClass().getName() + " " + e.getLocalizedMessage() + "\n"); final StackTraceElement[] stackTraceElements = e.getStackTrace(); for (StackTraceElement ste : stackTraceElements) sb.append("\tat " + ste.getClassName() + "." + ste.getMethodName() + "(" + ste.getFileName() + ":" + ste.getLineNumber() + ")\n"); } private VOXFile determineVOXFile() { String voxName = tr.config.getVoxFile(); if (voxName == null) return autoDetermineVOXFile(); else if (voxName.contentEquals(TRConfiguration.AUTO_DETECT)) return autoDetermineVOXFile(); else if (voxName.contentEquals("Fury3")) return Fury3.getDefaultMission(); else if (voxName.contentEquals("TV")) return TV.getDefaultMission(); else if (voxName.contentEquals("FurySE")) return FZone.getDefaultMission(); else return attemptGetVOX(voxName); }//end determineVOXFile() private GameVersion determineGameVersion() { String voxName = tr.config.getVoxFile(); if (voxName == null) return tr.config.getGameVersion(); else if (voxName.contentEquals(TRConfiguration.AUTO_DETECT)) { return guessGameVersionFromPods(); } else if (voxName.contentEquals("Fury3")) return GameVersion.F3; else if (voxName.contentEquals("TV")) return GameVersion.TV; else if (voxName.contentEquals("FurySE")) return GameVersion.FURYSE; else return tr.config.getGameVersion(); } private GameVersion guessGameVersionFromPods() { boolean f3Hint = false, tvHint = false, furyseHint = false; System.out.println("Auto-determine active... pods:" + tr.getResourceManager().getRegisteredPODs().size()); for (IPodData pod : tr.getResourceManager().getRegisteredPODs()) { final String podComment = pod.getComment(); System.out.println("POD comment=" + podComment); f3Hint |= podComment.toUpperCase().startsWith("FURY3"); tvHint |= podComment.toUpperCase().startsWith("TV"); furyseHint |= podComment.toUpperCase().startsWith("FURYSE"); } //end for(pods) int numValidHints = 0 + (f3Hint ? 1 : 0) + (tvHint ? 1 : 0) + (furyseHint ? 1 : 0); if (numValidHints == 1) { return (f3Hint ? GameVersion.F3 : tvHint ? GameVersion.TV : GameVersion.FURYSE); } //end if(hints==1) return null; } private VOXFile autoDetermineVOXFile() { String voxFileName = null; System.out.println("Auto-determine active... pods:" + tr.getResourceManager().getRegisteredPODs().size()); GameVersion gameVersion = guessGameVersionFromPods(); if (gameVersion != null) { switch (gameVersion) { case TV: voxFileName = "TV"; break; case F3: voxFileName = "Fury3"; break; case FURYSE: voxFileName = "FurySE"; break; }//end switch(...) } // end if(!null) if (voxFileName == null) { JOptionPane.showMessageDialog(tr.getRootWindow(), "Could not auto-detect the default mission.\nEnsure all necessary PODs are registered in the File->Configure window or specify a VOX file if it is a custom game.", "Auto-Detect Failure", JOptionPane.ERROR_MESSAGE); return null; } return attemptGetVOX(voxFileName); }//end autoDetermineVOXFile private VOXFile attemptGetVOX(String voxFileName) { try { final VOXFile result = tr.getResourceManager().getVOXFile(voxFileName); return result; } catch (FileLoadException e) { JOptionPane.showMessageDialog(tr.getRootWindow(), "Failed to parse (understand) VOX file " + voxFileName, "Parsing failure", JOptionPane.ERROR_MESSAGE); } catch (IOException e) { JOptionPane.showMessageDialog(tr.getRootWindow(), "Failed to read VOX file " + voxFileName + " from source.", "Read failure", JOptionPane.ERROR_MESSAGE); } catch (IllegalAccessException e) { JOptionPane.showMessageDialog(tr.getRootWindow(), "Could not access specified vox " + voxFileName, "Permission problem?", JOptionPane.ERROR_MESSAGE); } return null; }//end attemptGetVOX() private void registerPODs() { DefaultListModel<String> podList = tr.config.getPodList(); for (int i = 0; i < podList.size(); i++) { final String podPath = podList.get(i); if (podPath != null) { final File file = new File(podPath); PodFile pod = new PodFile(file); try { tr.getResourceManager().registerPOD(file.getAbsolutePath(), pod); } catch (FileLoadException e) { JOptionPane.showMessageDialog(tr.getRootWindow(), "Failed to parse (understand) POD file " + podPath, "Parsing failure", JOptionPane.ERROR_MESSAGE); } //end catch(...) } //end if(!null) } //end for(pods) }//end registerPODs /** * @return the greenFont */ public GLFont getGreenFont() { return greenFont; } /** * @return the earlyLoadingScreen */ public EarlyLoadingScreen getEarlyLoadingScreen() { return earlyLoadingScreen; } }//end GameShell