/* ** j###t ########## #### #### ** j###t ########## #### #### ** j###T "###L J###" ** ######P' ########## ######### ** ######k, ########## T######T ** ####~###L #### ** #### q###L ########## .##### ** #### \###L ########## #####" ** ** $Id$ ** ** Class History ** ** Date Name Description ** ---------|------------|----------------------------------------------- ** 19Aug98 subtle start of recorded history ** */ package key; import java.net.Socket; import java.net.InetAddress; import java.io.*; import java.util.Hashtable; /** * all output from the program is classified * into one of the 'types' of data that is * being fed back. This not only allows a * great flexibility in the output method * used on a telnet connection, but it allows * for the easy expansion of connections to * support applet clients or other frontends * that require code support. * * This class supports several 'codes' within the * strings you pass to output to the program. * * <ul> * <li><i>\n</i>: To mean 'start a new line' * </ul> */ public abstract class InteractiveConnection extends AnimatedAtom { private transient Player player; private transient Interactive interacting = null; /** * The constructor must take a socket as its sole * argument * * @param s The socket that the connection is on */ public InteractiveConnection() { setKey( "IC" ); } public void interactWith( Interactive i ) { interacting = i; } public void run() { try { while( interacting != null && isAlive() && isConnected() ) { interacting.run( this ); } } catch( Throwable e ) { if( isConnected() ) { try { send( "Sorry, an error occurred. Closing connection.\n" ); } catch( NetworkException ne ) { } Log.error( e ); } } finally { close(); } } private void readObject( ObjectInputStream ois ) throws IOException { throw new UnexpectedResult( "attempting to de-serialise InteractiveConnection" ); } private void writeObject( ObjectOutputStream ois ) throws IOException { throw new UnexpectedResult( "attempting to serialise InteractiveConnection" ); } public String getName() { if( player != null ) return( super.getName() + " for " + player.getName() ); else return( super.getName() ); } public final void startUnIdling( Player p ) { player = p; p.unIdle(); } void stopBeingTemporary() { // do nothing, we always want to be temporary } public abstract boolean isConnected(); public abstract boolean newbiesAllowed(); public abstract void printStackTrace( Throwable t ); public abstract String getFullSiteName(); public abstract String getSiteName(); public void flush() { } /** * The intention is to provide a method that only calls flush() * on the stream if the socket is waiting for input. */ public void flushIfWaiting() { flush(); } /** * Throw away all incoming input. */ public abstract void discard() throws IOException; public final void stopUnIdling() { player = null; } public Player getPlayer() { return( player ); } /** * Specifies that this ic is in 'verbose' * mode - that is, it will recieve newbie * help instrctions and so on. */ public boolean verbose() { return( true ); } /** * The sub-classes should call this routine everytime * the player puts some input into the program */ protected final void unIdle() { if( player != null ) player.unIdle(); } public synchronized void close() { interactWith( null ); } /** * draw a line across the screen */ public abstract void sendLine(); /** * beeps the terminal, if supported. */ public void beep() { } /** * This function should block until it can * return a complete string of the player's * input. It can then be used in sequential * code without complications with loops. * * @param prompt The prompt that the player sees (eg "-> ") * @return the string that the player entered. This string is not \n terminated */ public abstract String input( String prompt ); /** * This function is very similar to * input(), above, except that it should be * used to *not* echo text as it's entered, * mainly for passwords */ public abstract String hiddenInput( String prompt ); /** * leave some blank space (usually the height of the characters */ public abstract void blankLine(); public abstract void sendSubliminal( String message, int duration, int frequency ); public abstract void sendRaw( String message ); public abstract void send( String message ); public abstract void send( char qualifier, String message ); public abstract void send( Paragraph para ); public abstract void send( Paragraph para, boolean okayToPage ); public final void sendSystem( String message ) { send( message ); } public void blankLines( int c ) { while( c-- > 0 ) blankLine(); } /** * This function is used to output direct, * *successful* feedback of a players command. * It is important that this feedback is normal * and expected by the player, since it generally * won't be hilited in any way. Please try * to restrict this output to a single line. * <p> * this command does start a new line * <p> * Examples: * <p> * You tell name 'hi' <br> * * @param message the text to be displayed */ public void sendFeedback( String message ) { send( message ); } /** * This function is used when the user makes some * sort of error in typing - *not* if a command * can't be executed because of a failure. So, * Command not found would go here, but 'Not enough * privs to nuke snapper' wouldn't. * <p> * this command does start a new line */ public void sendError( String message ) { send( message ); } /** META: remove */ public void sendFailure( String message ) { send( message ); } public void send( Screen s ) { send( s.text ); } /** returns true if we need to output a 'paging' prompt */ public abstract boolean isPaging(); }