/* * (c) 2000-2009 Carlos G�mez Rodr�guez, todos los derechos reservados / all rights reserved. * Licencia en license/bsd.txt / License in license/bsd.txt */ package eu.irreality.age.telnet; import java.util.*; import java.io.*; import java.net.*; import eu.irreality.age.InputOutputClient; import eu.irreality.age.Player; import eu.irreality.age.StringMethods; import eu.irreality.age.World; import eu.irreality.age.XMLtoWorldException; import eu.irreality.age.i18n.UIMessages; public class SimpleTelnetClientProxy implements InputOutputClient , TelnetConstants { private Socket incoming; private int id; private InputStream is; private OutputStream os; private BufferedReader in; private PrintWriter out; private boolean asynchronous; //synchronous or asynchronous mode private LinkedList inputQueue = new LinkedList(); //for asynchronous command queueing private Vector gameLog = new Vector(); private boolean clientHasDisconnected=false; public boolean isDisconnected() { return clientHasDisconnected; } public boolean checkForANSISupport ( ) throws IOException { //the telnet negotiations which check for ANSI support!! boolean terminamos = false; int tries = 10; //ask for terminal-type negotiation os.write ( IAC ); os.write ( DO ); os.write ( TELOPT_TTYPE ); for(;!terminamos;) { System.out.println("Iteration."); int abyte = is.read(); if ( tries == 0 ) terminamos = true; if ( abyte == -1 ) break; if ( abyte == IAC ) { System.out.println("IAC."); int bbyte = is.read(); switch ( bbyte ) { case WILL: System.out.println("WILL."); int cbyte = is.read(); if ( cbyte == TELOPT_TTYPE ) { //aceptan negociar terminal type! //pedimos tipos de terminal... os.write ( IAC ); os.write ( SB ); os.write ( TELOPT_TTYPE ); os.write ( TEL_QUAL_SEND ); os.write ( IAC ); os.write ( SE ); //otra iteraci�n para SB } break; case WONT: System.out.println("WONT."); int cbyte2 = is.read(); if ( cbyte2 == TELOPT_TTYPE ) { System.out.println("TELOPT_TTYPE."); write("Your telnet client refuses negotiating terminal types.\n"); terminamos = true; } break; case SB: //subnegotiation begin System.out.println("SB."); int cbyte3 = is.read(); if ( cbyte3 == TELOPT_TTYPE ) { byte[] buf = new byte[100]; int i = 0; int c; is.skip(1); //IS while ( (c=is.read()) != IAC && i < 99 ) { buf[i] = (byte)c; i++; } buf[i] = '\0'; String termTypeString = new String ( buf ); System.out.println("TERMTYPESTRING:"+termTypeString+"\n"); if ( termTypeString.equalsIgnoreCase("ansi") || termTypeString.equalsIgnoreCase("vt100") || termTypeString.equalsIgnoreCase("xterm") || termTypeString.equalsIgnoreCase("vt320") || termTypeString.equalsIgnoreCase("mushclient") || termTypeString.equalsIgnoreCase("zmud") ) { write("ANSI support detected (" + termTypeString + ")\n"); return true; } else { //pedir otra terminal os.write ( IAC ); os.write ( SB ); os.write ( TELOPT_TTYPE ); os.write ( TEL_QUAL_SEND ); os.write ( IAC ); os.write ( SE ); //otra iteraci�n para SB y procesar subnegotiation tries--; } } default: break; } } } return false; } public SimpleTelnetClientProxy ( java.net.Socket s , int id , World mundo ) { this.incoming = s; this.id = id; try { if (incoming != null) { in = new BufferedReader(new InputStreamReader((is=incoming.getInputStream()))); out = new PrintWriter(new OutputStreamWriter((os=incoming.getOutputStream()))); } } catch (Exception e) { System.out.println("Error: " + e); } try { boolean ANSIsupport = checkForANSISupport(); write("Welcome to " + s.getLocalAddress() + " [port " + s.getLocalPort() + "] running the Aetheria Game Engine.\n"); write("Your client ID is " + id + ".\n"); mundo.addNewPlayerASAP ( this ); } catch ( XMLtoWorldException e ) { System.out.println("Couldn't: XMLtoWorldException " + e ); } catch ( IOException e ) { System.out.println("I/O Exception: " + e); } } public boolean isColorEnabled() { return false; } public boolean isMemoryEnabled() { return false; } public boolean isLoggingEnabled() { return true; } public boolean isTitleEnabled() { return false; } private void setSynchronousMode() { asynchronous = false; } private void setAsynchronousMode() { if ( !asynchronous ) { asynchronous = true; inputQueue = new LinkedList(); Thread t = new Thread ( ) { public void run ( ) { try { for(;;) { String str = in.readLine(); if ( str == null ) { System.out.println("Nullified input.\n"); clientHasDisconnected=true; break; } System.out.println("Adding 2 Que: " + str); inputQueue.addLast(str); } } catch ( IOException ioe ) { clientHasDisconnected=true; System.out.println("IO Exception.\n"); } } }; t.start(); } } //bloqueante. public String getInput ( Player pl ) { setSynchronousMode(); try { write("SynchronousInput> "); String str = in.readLine(); if ( str == null ) { clientHasDisconnected=true; return null; } System.out.println("INPUT GOTTEN: " + str ); return str; } catch ( IOException ioe ) { clientHasDisconnected=true; System.out.println("Oh yeppie, en �i Ou Excepxen.\n"); //maybe set an exception flag and ask world to remove player ASAP. return null; } } //no bloqueante public String getRealTimeInput ( Player pl ) { setAsynchronousMode(); if ( inputQueue.isEmpty() ) return null; String str = (String) inputQueue.removeFirst(); return str; } //bloqueante public void waitKeyPress() { setSynchronousMode(); write("[Pulse ENTER]\n"); try { String str = in.readLine(); System.out.println("INPUT GOTTEN (line)\n"); } catch ( IOException ioe ) { } } /** * @deprecated Use {@link #writeTitle(String)} instead */ public void escribirTitulo(String s) { writeTitle(s); } public void writeTitle(String s) { return; /*disabled*/ } /** * @deprecated Use {@link #writeTitle(String,int)} instead */ public void escribirTitulo(String s , int pos) { writeTitle(s, pos); } public void writeTitle(String s , int pos) { return; /*disabled*/ } //do /** * @deprecated Use {@link #write(String)} instead */ public void escribir ( String s ) { write(s); } //do public void write ( String s ) { if ( out != null ) { System.out.print("Systemoutprinting:"+s); //print with LF -> CRLF substitution! out.print( StringMethods.textualSubstitution ( s , "\n" , "\n\r" ) ); out.flush(); } } public void loguear ( String s ) { gameLog.add ( s ); } /** * @deprecated Use {@link #forceInput(String,boolean)} instead */ public void forzarEntrada ( String s , boolean output_enabled ) { forceInput(s, output_enabled); } public void forceInput ( String s , boolean output_enabled ) { gameLog.addElement(s); write("\n"); write(" > " + s.trim() ); } /** * @deprecated Use {@link #clearScreen()} instead */ public void borrarPantalla ( ) { clearScreen(); } public void clearScreen ( ) { //write(UIMessages.getInstance().getMessage("telnet.clear.placeholder")+"\n"); write("\n\n"); } public String getColorCode ( String colorKey ) { return ""; } }