// fudged together by Zrutu,
// based hugely on the /net/obj/dict.c object
#include <network.h>
inherit CLIENT;
#define DEBUG !
#include <dict.h>
mapping _connections = ([ ]);
mapping _dictServers = ([ ]);
/** @ignore yes */
void callback(string address, string resolved, int key){
class server_details dictServer;
dictServer = new(class server_details, address:address, resolved:resolved,
key:key);
#ifdef DEBUG
event( users(), "inform","Resolved and adding "+address+" to DICT_H:"+
dictServer->resolved+"",
"debug");
#endif
_dictServers[address] = dictServer;
}
/** @ignore yes */
void create() {
client::create();
SetSocketType(STREAM);
foreach(string str in DICT_SERVERS){
resolve(str,"callback");
}
} /* create() */
void close_socket( int fd, object who ) {
if ( _connections[ who ] ) {
eventWrite(fd, "QUIT\r\n" );
eventAbortCallback( fd );
eventSocketClose( fd );
map_delete( _connections, who );
}
} /* close_socket() */
void open_socket() {
class server_details dServer;
class connection_data dict;
int new_fd;
if ( _connections[ this_player() ] ) {
tell_object(TP,"You already have a session open, to protect system "
"resources you are limited to one session at a time.\n");
return ;
}
// Clean up _dictServers
foreach(string str in keys(_dictServers)){
if (!_dictServers[str]->resolved)
map_delete(_dictServers,str);
}
if(!sizeof(_dictServers)){
#ifdef DEBUG
event( users(), "inform","No .DICT servers have been resolved, please "
"verify dict.h.",
"debug");
#endif
tell_object(TP,"There has been an error with determining a dictionary server "
"this command is currently offline please contact a creator.\n");
return;
}
dServer = _dictServers[keys(_dictServers)[0]];
new_fd = eventCreateSocket(dServer->resolved, 2628);
if (new_fd < 0) {
#ifdef DEBUG
event( users(), "inform","Error connecting to "+
dServer->address+"("+dServer->resolved+").",
"debug");
#endif
map_delete(_dictServers,dServer->address);
tell_object(TP,"There has been an error connecting to the "
"dictionary server, please try again later.\n");
return ;
}
dict = new(class connection_data, fd : new_fd, owner : this_player(),
status : WAITING_FOR_CONNECT, count : -1, definitions : ({ }) );
_connections[ this_player() ] = dict;
_connections[this_player() ]->host_name = dServer->address;
#ifdef DEBUG
event( users(), "inform","Connection to "+
dServer->address+"("+dServer->resolved+") successful! WooHOO!",
"debug");
#endif
call_out( "close_socket", 120, new_fd, this_player() );
return ;
} /* open_socket() */
int do_define(mixed *args) {
class connection_data dict;
if ( !( dict = _connections[ this_player() ] ) ) {
#ifdef DEBUG
event( users(), "inform","ERROR! open a connection before you try and "
"communicate!",
"debug");
#endif
return 0;
}
dict->current_word = args[0];
if (sizeof(args) > 1)
dict->search_mode = SEARCH_MODE_ALL;
else
dict->search_mode = DEFAULT_SEARCH_MODE;
dict->status = SENDING_DEFINE;
dict->action = DEFINE;
eventWrite(dict->fd, sprintf("DEFINE %s %s\r\n", dict->search_mode,
dict->current_word));
#ifdef DEBUG
event( users(), "inform","Searching for "+dict->current_word+" on "+
dict-> host_name,"debug");
#endif
tell_object(TP,"Searching Dictionary... (please be patient)\n");
return 1;
} /* do_define() */
int do_spell(mixed *args) {
class connection_data dict;
if ( !( dict = _connections[ this_player() ] ) ) {
#ifdef DEBUG
event( users(), "inform","ERROR! open a connection before you try and "
"communicate!",
"debug");
#endif
return 0;
}
dict->current_word = args[0];
if(sizeof(args) > 1)
dict->search_mode = SEARCH_MODE_ALL;
else
dict->search_mode = DEFAULT_SEARCH_MODE;
dict->status = SENDING_MATCH;
dict->action = MATCH;
eventWrite(dict->fd, sprintf("MATCH %s . %s\r\n", dict->search_mode,
dict->current_word));
#ifdef DEBUG
event( users(), "inform","Searching SPELLING on "+dict->current_word+" on "+
dict-> host_name,"debug");
#endif
tell_object(TP,"Searching Dictionary... (please be patient)\n");
return 1;
}
void eventRead(int fd, string message) {
class connection_data dict;
mapping destination;
object who;
string *bits, *lines, line, word, extra, dictionary_name, text;
mixed *bing;
int i;
#ifdef DEBUG
event( users(), "inform","Receiving Message: "+message+" on fd"+
fd,"debug");
#endif
/* Check to see if the message is valid. */
if ( !stringp( message ) )
return;
/* Find the user for this connection */
destination = filter( _connections, (: $(fd) == $2->fd :) );
if ( !sizeof( destination ) )
return;
who = keys( destination )[ 0 ];
dict = destination[ who ];
lines = explode( message, "\r\n" );
foreach ( line in lines ) {
if ( !sizeof( line ) )
line = "\n";
if ( line == "." ) {
dict->definitions += ({ dict->working });
dict->count = -1;
continue;
}
bits = explode( line, " " );
if ( !sizeof( bits ) )
continue;
switch ( bits[ 0 ] ) {
case "150":
dict->count++;
dict->working = ({ });
dict->status = RECEIVING;
word = 0;
extra = 0;
dictionary_name = 0;
break;
case "151":
if ( dict->status == RECEIVING &&
( sscanf( line, "151 \"%s\" %s \"%s\"", word, extra,
dictionary_name ) == 3 ) )
dict->working += ({ ({ word, dictionary_name, "" }) });
else
tell_creator( DEBUGGER, "Invalid 151 error code, %s, %s, %s.\n",
word, extra, dictionary_name );
break;
case "152":
dict->count++;
dict->working = ({ });
dict->status = RECEIVING;
word = 0;
extra = 0;
dictionary_name = 0;
break;
case "220":
dict->status = READY;
dict->capabilities = explode( bits[ <2 ][1..<2], "." );
break;
case "250":
text = "";
switch(dict->action) {
case DEFINE:
for ( i = 0; i < sizeof( dict->definitions ); i++ ) {
foreach( bing in dict->definitions[ i ] ) {
bing[ 2 ] = replace( bing[ 2 ],
({ " ", " ", "\t", " " }) );
text += who->fix_string( bing[ 2 ],
who->query_cols() - 5, 0 );
}
text += "\n";
}
tell_object( who, sprintf( "$P$Definition of %s$P$\n"
"%s\n", dict->current_word, text ) );
break;
case MATCH:
text = "";
for(i=0; i<sizeof(dict->definitions); i++) {
foreach(line in dict->definitions[i]) {
if(sscanf(line, "%s \"%s\"", extra, word) == 2)
text += word + "\n";
}
}
tell_object(who, sprintf("$P$Spellings for %s$P$"
"\n%-#*s", dict->current_word,
who->query_cols(), text) + "\n");
}
dict->definitions = ({ });
return;
break;
case "530":
tell_object( who, sprintf( "The dictionary reports: %s\n"
"Please contact a creator.\n", line ) );
close_socket( fd, who );
return;
break;
case "552":
tell_object( who, "No definitions for " +
dict->current_word + ".\n" );
return;
break;
default:
if ( dict->status == RECEIVING ) {
switch(dict->action) {
case DEFINE:
dict->working[<1][<1] += line;
break;
case MATCH:
dict->working += ({ line });
}
} else
break;
}
}
#ifdef DEBUG
event( users(), "inform","Read Code ("+bits[ 0 ]+")","debug");
#endif
call_out( "close_socket", 1, fd, this_player() );
} /* eventRead() */
void dest_me() {
class connection_data dict;
object ob;
foreach ( ob, dict in _connections ) {
close_socket( dict->fd, ob );
}
client::dest_me();
} /* dest_me() */
mapping query_connections(){
return _connections;
}
mapping query_dictservers(){
return _dictServers;
}
class connection_data query_connection_data(object player){
if(!mappingp(_connections))
return 0;
if(!_connections[player])
return 0;
return _connections[player];
}