package eu.irreality.age.swing.applet; import java.awt.Dimension; import java.awt.Image; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; import java.net.URL; import java.util.Vector; import java.util.zip.DataFormatException; import javax.swing.JApplet; 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.JSeparator; import javax.swing.SwingUtilities; 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.Utility; 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.menu.ServerMenuHandler; import eu.irreality.age.swing.sdi.NewFromFileListener; import eu.irreality.age.swing.sdi.SwingSDIInterface; import eu.irreality.age.util.VersionComparator; import eu.irreality.age.windowing.AGEClientWindow; import eu.irreality.age.windowing.LoaderThread; import eu.irreality.age.windowing.UpdatingRun; public class SwingSDIApplet extends JApplet 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 InputStream logStream; 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 Applet AGE client, v0.1"; } /** * Removes whatever was on the applet and changes it to a new ColoredSwingClient. */ public void initClient() { gameLog = new Vector(); //init game log //setVisible(false); getContentPane().removeAll(); mainPanel = new JPanel(); //panel que contiene al cliente setMainPanel( mainPanel ); io = new ColoredSwingClient(SwingSDIApplet.this,gameLog); //components are added 'ere. //setVisible(true); } public void prepareLog( World theWorld ) throws Exception { logStream.mark(100000); theWorld.prepareLog(logStream); logStream.reset(); theWorld.setRandomNumberSeed( logStream ); } // 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(SwingSDIApplet.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() ) // { // ((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(SwingSDIApplet.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 //different on applet // { // 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(SwingSDIApplet.this); // maquinaEstados.attachObserver(new ServerMenuHandler(SwingSDIApplet.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 // } public void start() { setVisible(true); this.requestFocus(); this.requestFocusInWindow(); this.requestFocus(); if ( io != null && io instanceof ColoredSwingClient ) ((ColoredSwingClient)io).refreshFocus(); } private void stopGameSaveAndUnlink() { if ( maquinaEstados != null ) maquinaEstados.exitNow(); else saveAndFreeResources(); } public void exitNow() { write( UIMessages.getInstance().getMessage("applet.exit") + "\n" ); //stopGameSaveAndUnlink(); //this.destroy(); //if ( !standalone ) // System.exit(0); } public void destroy() { this.exitNow(); } public void saveAndFreeResources ( ) { /* //autosave io.write ("Guardando la partida...\n"); try { CommonClientUtilities.guardarLog ( new File ( "autosave.alf" ) , gameLog ); } catch (Exception exc) { io.write("�No se ha podido guardar la partida!\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 void setTheJMenuBar(JMenuBar jmb) { setJMenuBar(jmb); } public SwingSDIApplet() { this("AGE Applet"); } public SwingSDIApplet(String title) { super(); this.title = 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(); JMenu menuArchivo = getTheJMenuBar().getMenu(0); //JMenuItem itemNuevo = new JMenuItem("Nuevo juego..."); //menuArchivo.add(itemNuevo,0); //itemNuevo.addActionListener(new NewFromFileListener(this)); JMenuItem itemLoadLog = new JMenuItem( UIMessages.getInstance().getMessage("menu.load.log") ); menuArchivo.add(itemLoadLog,1); itemLoadLog.addActionListener(new ActionListener() { public void actionPerformed( ActionEvent evt ) { loadLogFromCookie(); } }); //JMenuItem itemLoadState = new JMenuItem("Cargar estado..."); //menuArchivo.add(itemLoadState,2); //itemLoadState.addActionListener(new LoadFromStateListener(this)); menuArchivo.add(new JSeparator(),3); setSize(500,400); } public void loadLogFromCookie() { //String logAsString = CookieUtils.readCookie(SwingSDIApplet.this,"log"); String logAsString = ""; if ( LocalStorageUtils.isLocalStorageSupported(this) ) { try { logAsString = LocalStorageUtils.loadCompressedData(SwingSDIApplet.this,"log","UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (DataFormatException e) { e.printStackTrace(); } } else //use plain good ol' cookie { try { logAsString = CookieUtils.readCompressedCookie(SwingSDIApplet.this,"log","UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (DataFormatException e) { e.printStackTrace(); } } if ( logAsString == null ) { write(UIMessages.getInstance().getMessage("applet.load.notsaved")+"\n"); return; } try { logStream = new ByteArrayInputStream(logAsString.getBytes("UTF-8")); } catch ( UnsupportedEncodingException uee ) { uee.printStackTrace(); write(uee.toString()); } usarLog = true; reinit(); } public void startGame ( final String moduledir , final boolean usarLog , final InputStream logStream , final String stateFile ) { if ( loaderThread != null ) //a game is started already { stopGameSaveAndUnlink(); } this.moduledir=moduledir; this.usarLog=usarLog; this.logStream=logStream; 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 SwingSDIApplet ( final String moduledir , final boolean usarLog , final InputStream logStream , final String stateFile ) { //Create Window this(moduledir); startGame ( moduledir , usarLog , logStream , 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 //= SwingSDIApplet.this.new LoaderThread( ); = new LoaderThread ( moduledir, usarLog, stateFile, SwingSDIApplet.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() { //write("AVISO: La funcionalidad de guardar partidas es EXPERIMENTAL y es posible que tenga errores. Adem�s, s�lo se puede guardar una partida a la vez, requiere que tu navegador acepte cookies, y el juego salvado no es permanente sino que pod�a borrarse si tu navegador elimina las cookies cada cierto tiempo.\n"); //write("Puedes guardar partidas de forma totalmente fiable (y tener guardadas m�ltiples partidas a la vez) si te descargas el Aetheria Game Engine, que permite jugar a aventuras como �sta con plena funcionalidad. B�jalo en http://code.google.com/p/aetheria/\n"); write(UIMessages.getInstance().getMessage("applet.save.warning")); String logToString = ""; for ( int i = 0 ; i < gameLog.size() ; i++ ) { logToString += gameLog.get(i); //logToString +="\\n"; //con \n no se ejecuta bien el js logToString +="\n"; //lo de arriba pierde el sentido con base64 } //write("Guardando: " + logToString); boolean localStorageSuccess = false; boolean cookieSuccess = false; if ( LocalStorageUtils.isLocalStorageSupported(this)) { LocalStorageUtils.eraseData(this,"log"); try { localStorageSuccess = LocalStorageUtils.saveAndValidateCompressedData(this, "log", logToString, "UTF-8"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } if ( !localStorageSuccess ) { CookieUtils.eraseCookie(this,"log"); try { cookieSuccess = CookieUtils.createAndValidateCompressedCookie(this,"log",logToString,"UTF-8",100); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } if ( localStorageSuccess || cookieSuccess ) write(UIMessages.getInstance().getMessage("applet.save.done") + "\n"); else write(UIMessages.getInstance().getMessage("applet.save.failed") + "\n"); /* File elFichero = null; 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("No se ha podido guardar la partida..."); write(exc.toString()); } } */ } public void guardarEstado() { //write("AVISO: Desde el navegador no se pueden guardar partidas. Pero puedes guardar partidas si te descargas el Aetheria Game Engine, que permite jugar a aventuras como �sta con plena funcionalidad. B�jalo en http://code.google.com/p/aetheria/\n"); write(UIMessages.getInstance().getMessage("applet.state.warning") + "\n"); guardarLog(); /* File elFichero = null; 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("No se ha podido guardar la partida..."); write(exc.toString()); } } */ } public void init() { //System.err.println(this.getClass().getResource("worlds/Vampiro/world.xml")); System.err.println(this.getClass().getResource("libinvoke.bsh")); SwingAetheriaGameLoaderInterface.loadFont(); startGame ( this.getParameter("worldUrl") , usarLog , logStream , stateFile ); } private String title = "AGE Applet"; public String getTitle() { return title; } public boolean isFullScreenMode() { return false; } public void setFullScreenMode(boolean b) { ; //unsupported } public void setTitle(String s) { title = s; } public boolean supportsFullScreen() { return false; } public void repaint() { validate(); super.repaint(100); } /** * Returns screen size based on the values of screenwidth and screenheight parameters if set */ public Dimension getScreenSize() { int width; int height; String sw = this.getParameter("screenwidth"); String sh = this.getParameter("screenheight"); if ( sw == null || sh == null ) return null; try { return new Dimension ( Integer.valueOf(sw).intValue() , Integer.valueOf(sh).intValue() ); } catch ( NumberFormatException nfe ) { return null; } } public void onAttach(GameEngineThread thread) { } public void onDetach(GameEngineThread thread) { unlinkWorld(); saveAndFreeResources(); } public String recoverMissingWorldPath() { return null; } }