package eu.irreality.age.swing.sdi; import java.awt.Color; import java.awt.Dimension; import java.awt.DisplayMode; import java.awt.Frame; import java.awt.Graphics; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.Image; import java.awt.Toolkit; import java.awt.event.FocusListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.Vector; import javax.swing.ImageIcon; import javax.swing.JDesktopPane; import javax.swing.JFileChooser; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JFrame; import javax.swing.JSeparator; import javax.swing.SwingUtilities; import javax.swing.event.InternalFrameAdapter; import javax.swing.event.InternalFrameEvent; import eu.irreality.age.AGESoundClient; import eu.irreality.age.ColoredSwingClient; import eu.irreality.age.CommonClientUtilities; import eu.irreality.age.FiltroFicheroEstado; import eu.irreality.age.FiltroFicheroLog; import eu.irreality.age.FiltroFicheroMundo; import eu.irreality.age.GameEngineThread; import eu.irreality.age.InputOutputClient; import eu.irreality.age.ObjectCode; import eu.irreality.age.SwingAetheriaGameLoader; import eu.irreality.age.SwingAetheriaGameLoaderInterface; import eu.irreality.age.World; import eu.irreality.age.debug.Debug; import eu.irreality.age.filemanagement.Paths; import eu.irreality.age.filemanagement.WorldLoader; import eu.irreality.age.i18n.UIMessages; import eu.irreality.age.observer.GameThreadObserver; import eu.irreality.age.swing.CommonSwingFunctions; import eu.irreality.age.swing.FileSelectorDialogs; import eu.irreality.age.swing.SwingMenuAetheria; import eu.irreality.age.swing.UILanguageSelectionMenu; import eu.irreality.age.swing.applet.SwingSDIApplet; import eu.irreality.age.swing.config.AGEConfiguration; import eu.irreality.age.swing.mdi.SwingAetheriaGUI; import eu.irreality.age.swing.menu.ServerMenuHandler; import eu.irreality.age.util.VersionComparator; import eu.irreality.age.windowing.AGEClientWindow; import eu.irreality.age.windowing.LoaderThread; import eu.irreality.age.windowing.MenuMnemonicOnTheFly; import eu.irreality.age.windowing.UpdatingRun; public class SwingSDIInterface extends JFrame implements AGEClientWindow, GameThreadObserver { private World mundo; private boolean fullScreenMode; private InputOutputClient io; private JPanel mainPanel; private Vector gameLog; private Thread loaderThread = null; private GameEngineThread maquinaEstados; private String moduledir; private boolean usarLog; private String logFile; private String stateFile; private Object mundoSemaphore = new Object(); public void setMainPanel ( JPanel panel ) { if ( mainPanel != null ) getContentPane().remove(mainPanel); mainPanel = panel; getContentPane().add ( panel ); } public void write ( String s ) { io.write(s); } public InputOutputClient getIO() { return io; } public void setIO ( InputOutputClient io ) { this.io = io; } public GameEngineThread getEngineThread ( ) { return maquinaEstados; } public void setEngineThread ( GameEngineThread get ) { maquinaEstados = get; } public Vector getGameLog ( ) { return gameLog; } public String getVersion ( ) { return "Swing-based simplified SDI client, v1.0"; } /** * Removes whatever was on the window and changes it to a new ColoredSwingClient. */ public void initClient() { gameLog = new Vector(); //init game log //setVisible(false); //cover(); getContentPane().removeAll(); mainPanel = new JPanel(); //panel que contiene al cliente setMainPanel( mainPanel ); io = new ColoredSwingClient(SwingSDIInterface.this,gameLog); //components are added 'ere. //setVisible(true); //uncover(); } public void prepareLog ( World theWorld ) throws Exception { theWorld.prepareLog(logFile); theWorld.setRandomNumberSeed( logFile ); } // class LoaderThread extends Thread // { // // public void run () // { // // try // { // SwingUtilities.invokeAndWait // ( // new Runnable() // { // public void run() // { // // initClient(); // // if ( usarLog ) // { // ((ColoredSwingClient)io).hideForLogLoad(); // if ( ((ColoredSwingClient)io).getSoundClient() instanceof AGESoundClient ) // { // AGESoundClient asc = (AGESoundClient) ((ColoredSwingClient)io).getSoundClient(); // asc.deactivate(); //will be activated on log end (player:endOfLog() // } // } // // CommonSwingFunctions.writeIntroductoryInfo(SwingSDIInterface.this); // // } // } // ); // } // catch ( Exception e ) // { // if ( io != null ) ((ColoredSwingClient)io).showAfterLogLoad(); // e.printStackTrace(); // } // // //System.out.println("2"); // // String worldName; // World theWorld = null; // // if ( moduledir == null || moduledir.length() == 0 ) moduledir="aetherworld"; // // // try // { // SwingUtilities.invokeAndWait // ( // new Runnable() // { // public void run() // { // repaint(); // updateNow(); // } // } // ); // } // catch ( Exception e ) // { // ((ColoredSwingClient)io).showAfterLogLoad(); // e.printStackTrace(); // } // // //System.out.println("3"); // // try // { // theWorld = WorldLoader.loadWorld( moduledir , gameLog, io, mundoSemaphore); // } // catch ( Exception e ) // /* // * This shouldn't happen, because unchecked exceptions in world initialization scripts are caught before reaching this level, // * and the loadWorld method doesn't throw its own exceptions (it returns null if the world cannot be loaded). But it's defensive // * programming in case AGE forgets to catch some unchecked exception, which has happened in the past. // */ // { // if ( io != null ) ((ColoredSwingClient)io).showAfterLogLoad(); // if ( io != null ) write ( "Exception on loading world: " + e ); // e.printStackTrace(); // } // if ( theWorld == null || io.isDisconnected() ) //io could be disconnected due to closing the window before assigning player // { // ((ColoredSwingClient)io).showAfterLogLoad(); // return; // } // mundo = theWorld; // // //{theWorld NOT null} // // final World theFinalWorld = theWorld; // // // try // { // SwingUtilities.invokeAndWait // ( // new Runnable() // { // public void run() // { // // updateNow(); // // //atender telnet // //SimpleTelnetClientHandler stch = new SimpleTelnetClientHandler ( theWorld , 6 , (short)8010 ); // //No. Dar medios para meterla en partidas dedicadas en forma de PartidaEnCurso. // // if ( theFinalWorld.getModuleName() != null && theFinalWorld.getModuleName().length() > 0 ) // setTitle(theFinalWorld.getModuleName()); // } // } // ); // // } // catch ( Exception e ) // { // ((ColoredSwingClient)io).showAfterLogLoad(); // e.printStackTrace(); // } // // if ( new VersionComparator().compare(GameEngineThread.getVersionNumber(),theWorld.getRequiredAGEVersion()) < 0 ) // { // String mess = UIMessages.getInstance().getMessage("age.version.warning", // "$curversion",GameEngineThread.getVersionNumber(),"$reqversion",theWorld.getRequiredAGEVersion(), // "$world",theWorld.getModuleName()); // mess = mess + " " + UIMessages.getInstance().getMessage("age.download.url"); // JOptionPane.showMessageDialog(SwingSDIInterface.this, mess, UIMessages.getInstance().getMessage("age.version.warning.title"), JOptionPane.WARNING_MESSAGE); // } // // //usar estado si lo hay // if ( stateFile != null ) // { // try // { // theWorld.loadState ( stateFile ); // } // catch ( Exception exc ) // { // ((ColoredSwingClient)io).showAfterLogLoad(); // write(UIMessages.getInstance().getMessage("swing.cannot.read.state","$file",stateFile)); // write(exc.toString()); // exc.printStackTrace(); // } // } // // // if ( usarLog ) // { // try // { // prepareLog(theWorld); // } // catch ( Exception exc ) // { // ((ColoredSwingClient)io).showAfterLogLoad(); // write(UIMessages.getInstance().getMessage("swing.cannot.read.log","$exc",exc.toString())); // exc.printStackTrace(); // return; // } // } // else // { // theWorld.setRandomNumberSeed(); // } // gameLog.addElement(String.valueOf(theWorld.getRandomNumberSeed())); //segunda l�nea, semilla // // //TODO use invoke method for this to avoid deadlocks: // try // { // SwingUtilities.invokeAndWait( new Runnable() { public void run() { setVisible(true); } } ); // } // catch (InvocationTargetException e1) // { // e1.printStackTrace(); // } // catch (InterruptedException e1) // { // e1.printStackTrace(); // } // // // mundo = theWorld; // synchronized ( mundoSemaphore ) // { // mundoSemaphore.notifyAll(); // } // // maquinaEstados = // new GameEngineThread ( // theWorld, false ); // // maquinaEstados.attachObserver(SwingSDIInterface.this); // maquinaEstados.attachObserver(new ServerMenuHandler(SwingSDIInterface.this)); // // //System.out.println("STARTING ENGINE THREAD"); // // maquinaEstados.start(); // // //System.out.println("ENGINE THREAD STARTED"); // // //Esto enga�a con los estados, lo quitamos. // /* // if (noSerCliente) // write("Este mundo se est� ejecutando en modo Dedicado. Por eso no ves nada aqu�: no eres jugador."); // */ // // try // { // SwingUtilities.invokeAndWait // ( // new Runnable() // { // public void run() // { // repaint(); // updateNow(); // //setVisible(false); // //setVisible(true); // // } // } // ); // } // catch ( Exception e ) // { // e.printStackTrace(); // } // // if ( io instanceof ColoredSwingClient ) // ((ColoredSwingClient)io).refreshFocus(); // // // // } //end run // } private void stopGameSaveAndUnlink() { if ( maquinaEstados != null ) maquinaEstados.exitNow(); else saveAndFreeResources(); } /** * Saves this window's coordinates to the adequate properties file so next time a window from this class * is constructed (i.e. next execution) it will have the same location and size. */ public void saveWindowCoordinates() { try { if ( (this.getExtendedState() & JFrame.MAXIMIZED_BOTH) != JFrame.MAXIMIZED_BOTH ) { AGEConfiguration.getInstance().setProperty("sdiWindowWidth",String.valueOf(this.getWidth())); AGEConfiguration.getInstance().setProperty("sdiWindowHeight",String.valueOf(this.getHeight())); AGEConfiguration.getInstance().setProperty("sdiWindowMaximized","false"); AGEConfiguration.getInstance().setProperty("sdiWindowLocationX",String.valueOf(this.getX())); AGEConfiguration.getInstance().setProperty("sdiWindowLocationY",String.valueOf(this.getY())); } else { AGEConfiguration.getInstance().setProperty("sdiWindowMaximized","true"); }; AGEConfiguration.getInstance().storeProperties(); } catch ( IOException ioe ) { ioe.printStackTrace(); } } public void exitNow() { saveWindowCoordinates(); stopGameSaveAndUnlink(); this.dispose(); //if ( !standalone ) // System.exit(0); } private boolean standalone = false; public void setStandalone ( boolean standalone ) { this.standalone = standalone; } public void saveAndFreeResources ( ) { //autosave io.write ( UIMessages.getInstance().getMessage("swing.saving") + "\n"); try { CommonClientUtilities.guardarLog ( new File ( "autosave.alf" ) , gameLog ); } catch (Exception exc) { io.write( UIMessages.getInstance().getMessage("swing.cannot.save.log") + "\n"); } io.write ( UIMessages.getInstance().getMessage("swing.bye") + "\n"); //wait(2); //System.exit(0); //if ( fullScreenMode ) // setFullScreenMode ( false ); //this.getDesktopPane().remove(this); if ( this.getClient() instanceof ColoredSwingClient ) { ((ColoredSwingClient)this.getClient()).uninitClientMenu(this); ((ColoredSwingClient)this.getClient()).exit(); //this also gets rid of threads waiting in the client } if ( maquinaEstados != null ) maquinaEstados.detachAllObservers(); //maquinaEstados.uninitServerMenu(this); //very important to avoid memory leaks: unreference thread maquinaEstados = null; Runtime.getRuntime().gc(); } public JPanel getMainPanel() { return mainPanel; } public void unlinkWorld ( ) { mundo = null; } public InputOutputClient getClient() { return io; } public World getWorld() { return mundo; } public void setWorld ( World w ) { mundo = w; } public JMenuBar getTheJMenuBar() { return getJMenuBar(); } public boolean isFullScreenMode() { return fullScreenMode; } public void setFullScreenMode(boolean onOrOff) { if ( onOrOff ) //set full-screen ON { System.out.println("Setting full-screen dedicated mode ON"); if ( fullScreenMode ) //ya estaba ON return; fullScreenMode = true; GraphicsEnvironment env = GraphicsEnvironment. getLocalGraphicsEnvironment(); GraphicsDevice[] devices = env.getScreenDevices(); // REMIND : Multi-monitor full-screen mode not yet supported dispose(); //if ( !isDisplayable() ) setUndecorated(true); setResizable(false); devices[0].setFullScreenWindow ( this ); DisplayMode dm = devices[0].getDisplayMode(); setSize(new Dimension(dm.getWidth(), dm.getHeight())); validate(); paintAll(getGraphics()); requestFocus(); Runnable updateCode = new UpdatingRun(this); Thread c = new Thread ( updateCode ); c.setPriority ( Thread.MAX_PRIORITY ); c.start(); setVisible(true); requestFocus(); if ( io instanceof ColoredSwingClient ) ((ColoredSwingClient)io).refreshFocus(); } else //set full screen mode off { System.out.println("Setting full-screen dedicated mode OFF"); if ( !fullScreenMode ) //ya estaba OFF return; fullScreenMode = false; dispose(); setUndecorated(false); setResizable(true); GraphicsEnvironment env = GraphicsEnvironment. getLocalGraphicsEnvironment(); GraphicsDevice[] devices = env.getScreenDevices(); // REMIND : Multi-monitor full-screen mode not yet supported devices[0].setFullScreenWindow ( null ); DisplayMode dm = devices[0].getDisplayMode(); setVisible(true); } } public void setTheJMenuBar(JMenuBar jmb) { setJMenuBar(jmb); } /** * Maximizes this frame if supported by the platform. */ private void maximizeIfPossible() { int state = getExtendedState(); state |= Frame.MAXIMIZED_BOTH; setExtendedState(state); } public SwingSDIInterface(String title) { super(title); setSize(AGEConfiguration.getInstance().getIntegerProperty("sdiWindowWidth"),AGEConfiguration.getInstance().getIntegerProperty("sdiWindowHeight")); setLocation(AGEConfiguration.getInstance().getIntegerProperty("sdiWindowLocationX"),AGEConfiguration.getInstance().getIntegerProperty("sdiWindowLocationY")); //setSize(600,600); if ( AGEConfiguration.getInstance().getBooleanProperty("sdiWindowMaximized") ) maximizeIfPossible(); //setTitle(Messages.getInstance().getMessage("frame.title")); //Image iconito = getToolkit().getImage("images" + File.separatorChar + "intficon.gif"); try { Image iconito = this.getToolkit().getImage(this.getClass().getClassLoader().getResource("images/intficon.gif")); this.setIconImage ( iconito ); } catch ( Exception e ) { e.printStackTrace(); } new SwingMenuAetheria(this).addToWindow(); addWindowListener ( new WindowAdapter() { public void windowClosing ( WindowEvent e ) { System.out.println("Frame closed."); exitNow(); //includes call to this.exitNow(); //kldispose(); } }); JMenu menuArchivo = getTheJMenuBar().getMenu(0); JMenuItem itemNuevo = new JMenuItem( UIMessages.getInstance().getMessage("menu.new.game") ); menuArchivo.add(itemNuevo,0); itemNuevo.addActionListener(new NewFromFileListener(this)); JMenuItem itemLoadLog = new JMenuItem( UIMessages.getInstance().getMessage("menu.load.game") ); menuArchivo.add(itemLoadLog,1); itemLoadLog.addActionListener(new LoadFromLogListener(this)); JMenuItem itemLoadState = new JMenuItem( UIMessages.getInstance().getMessage("menu.load.state") ); menuArchivo.add(itemLoadState,2); itemLoadState.addActionListener(new LoadFromStateListener(this)); menuArchivo.add(new JSeparator(),3); //setSize(600,440); getTheJMenuBar().add( new UILanguageSelectionMenu(this) ); MenuMnemonicOnTheFly.setMnemonics(getTheJMenuBar()); } /** * Start a game on this window. * Uses log if logFile != null. * Uses state if stateFile != null. * @param moduledir * @param logFile * @param stateFile */ public void startGame ( final String moduledir , final String logFile , final String stateFile ) { startGame ( moduledir , logFile!=null , logFile , stateFile ); } public void startGame ( final String moduledir , final boolean usarLog , final String logFile , final String stateFile ) { if ( loaderThread != null ) //a game is started already { stopGameSaveAndUnlink(); } this.moduledir=moduledir; this.usarLog=usarLog; this.logFile=logFile; this.stateFile=stateFile; System.out.println("B"); Thread.currentThread().setPriority(Thread.MAX_PRIORITY); //setSize(500,400); if ( moduledir.equalsIgnoreCase("") ) { setTitle("Aetheria Game Engine. " + UIMessages.getInstance().getMessage("swing.default.title.module") + " (sin nombre)"); } else { setTitle("Aetheria Game Engine. " + UIMessages.getInstance().getMessage("swing.default.title.module") + " " + moduledir); } setVisible(true); loaderThread = //this.new LoaderThread( ); new LoaderThread ( moduledir, usarLog, stateFile, this , mundoSemaphore ); loaderThread.start(); } //local init public SwingSDIInterface ( final String moduledir , final boolean usarLog , final String logFile , final String stateFile ) { //Create Window this(moduledir); startGame ( moduledir , usarLog , logFile , stateFile ); } public void reinit() { if ( loaderThread != null ) { //final boolean fsm = fullScreenMode; //setFullScreenMode(false); //dejemonos de finuras, total, vamos a recargar el mundo. [2011-05-01] /* maquinaEstados.uninitServerMenu(this); maquinaEstados.exitForReinit(); ((ColoredSwingClient)io).uninitClientMenu(this); */ maquinaEstados.exitNow(); Thread thr = new Thread() { public void run() { loaderThread = //SwingSDIInterface.this.new LoaderThread( ); new LoaderThread ( moduledir, usarLog, stateFile, SwingSDIInterface.this , mundoSemaphore ); loaderThread.start(); try { loaderThread.join(); } catch ( InterruptedException ie ) { ie.printStackTrace(); } //setFullScreenMode(fsm); } }; thr.start(); } } protected Runnable updateCode = new UpdatingRun(this); public void updateNow() { Thread c = new Thread ( updateCode ); c.setPriority ( Thread.MAX_PRIORITY ); c.start(); } //funciones de la ventana copypasteadas de SwingAetheriaGameLoader public void guardarLog() { File elFichero = null; File savePath = new File(Paths.SAVE_PATH); if ( !savePath.exists() ) savePath.mkdirs(); JFileChooser selectorFichero = new JFileChooser( Paths.SAVE_PATH ); selectorFichero.setFileSelectionMode(JFileChooser.FILES_ONLY); FiltroFicheroLog filtro = new FiltroFicheroLog(); selectorFichero.setFileFilter(filtro); int returnVal = selectorFichero.showSaveDialog(this); if ( returnVal == JFileChooser.APPROVE_OPTION ) { elFichero = selectorFichero.getSelectedFile(); try { if ( !elFichero.toString().toLowerCase().endsWith(".alf") ) { elFichero = new File ( elFichero.toString() + ".alf" ); } CommonClientUtilities.guardarLog ( elFichero , gameLog ); } catch ( Exception exc ) { write( UIMessages.getInstance().getMessage("swing.cannot.save.log") + "\n" ); write(exc.toString()); } } } public void guardarEstado() { File elFichero = null; File savePath = new File(Paths.SAVE_PATH); if ( !savePath.exists() ) savePath.mkdirs(); JFileChooser selectorFichero = new JFileChooser( Paths.SAVE_PATH ); selectorFichero.setFileSelectionMode(JFileChooser.FILES_ONLY); FiltroFicheroEstado filtro = new FiltroFicheroEstado(); selectorFichero.setFileFilter(filtro); int returnVal = selectorFichero.showSaveDialog(this); if ( returnVal == JFileChooser.APPROVE_OPTION ) { elFichero = selectorFichero.getSelectedFile(); try { if ( !elFichero.toString().toLowerCase().endsWith(".asf") ) { elFichero = new File ( elFichero.toString() + ".asf" ); } CommonClientUtilities.guardarEstado ( elFichero , mundo ); } catch ( Exception exc ) { write( UIMessages.getInstance().getMessage("swing.cannot.save.state") + "\n" ); write(exc.toString()); } } } public static void main ( String[] args ) { SwingAetheriaGameLoaderInterface.loadFont(); JFileChooser selector = new JFileChooser( Paths.WORLD_PATH ); selector.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); selector.setDialogTitle( UIMessages.getInstance().getMessage("dialog.new.title") ); selector.setFileFilter ( new FiltroFicheroMundo() ); int returnVal = selector.showOpenDialog(null); if(returnVal == JFileChooser.APPROVE_OPTION) { //System.out.println("Nombre: " + selector.getSelectedFile().getAbsolutePath() ); //if ( selector.getSelectedFile().isFile() ) //{ //new SwingAetheriaGameLoader( selector.getSelectedFile().getParent() , thePanel , false ,null , null, true ); //} //else //{ //Thread.currentThread().setPriority(Thread.MAX_PRIORITY); new SwingSDIInterface(selector.getSelectedFile().getAbsolutePath(),false,null,null); //} } } public boolean supportsFullScreen() { return true; } public void cover() { JPanel glass = new JPanel(); glass.setBackground(Color.WHITE); glass.setOpaque(true); setGlassPane(glass); glass.setVisible(true); } public void uncover() { JPanel glass = (JPanel) getGlassPane(); glass.setVisible(false); } public Dimension getScreenSize() { return Toolkit.getDefaultToolkit().getScreenSize(); } public void onAttach(GameEngineThread thread) { } public void onDetach(GameEngineThread thread) { unlinkWorld(); saveAndFreeResources(); } public String recoverMissingWorldPath() { return FileSelectorDialogs.showOpenWorldDialog(this); } }