Only in MOO-1.8.0r5: .cvsignore Only in MOO-1.8.0r5: .indent.pro Only in MOO-1.8.0r5: AddingNewMOOTypes.txt diff -U 2 -b -P -x config.h -x y.tab.c -x y.tab.h MOO-1.8.0r5/ChangeLog.ehMOO.txt ehMOO.0.93.r5.codeonly/ChangeLog.ehMOO.txt --- MOO-1.8.0r5/ChangeLog.ehMOO.txt Wed Dec 31 18:00:00 1969 +++ ehMOO.0.93.r5.codeonly/ChangeLog.ehMOO.txt Thu Feb 15 03:05:22 2001 @@ -0,0 +1,189 @@ +Version ehMOO-0.95, 02/15/01 +-- Version number synced with distribution, no other changes +-- For reference, ehMOO makes changes to the following LambdaMOO files: + + Makefile.in + functions.c + server.c + server.h + tasks.c + tasks.h + list.h + +-- For reference, ehMOO adds following files: + + fntab.c + fntab.h + gprot.c + gprot.h + gprot_lambda.c + gprot_lambda.h + hash.c + hash.h + ll.c + ll.h + objtab.c + objtab.h + oc_data.c + oc_data.h + oreg.c + oreg.h + ChangeLog.ehMOO.txt + +Version ehMOO-0.93, 11/05/98 +-- Changed strdups to str_dups for strings used in var packs in gprot_lambda.c + +Version ehMOO-0.92, 09/02/98 +-- Added room delete moocode for ehed - no changes to server source + +Version ehMOO-0.91, 08/01/98 +-- Added changes needed for ehed, including moocode + +Version ehMOO-0.90, 05/17/98 +-- Added protocol negotiation +-- $gprot_login:do_login_command doesn't do graphics_client_connected + any more - it's now deferred until protocol negotiation completes +-- Gprot opcodes changed from numeric to symbolic + +Version ehMOO-0.04.1, 10/04/96 +-- fixed non-wiz perm problems: + gprot_verbs.eh + $gprot_login:graphics_client_connected - moved set_task_perms() + after user.last_connect_time = time() + + setup.eh + added #6.intro and @chmod #6.intro + fixes #11:greetvis() problem + NOTE: need to change all non-wiz player.intro perms for previously- + created characters to rwc +-- changed #11.greetings to eh greetings +-- made command @make-graphics-player + make_gplayer.eh +-- Made callable function create_robot for gprot + make_gplayer.eh + put on object #0, not builder + Example gprot string: 5 0 0 0 1 name password +-- Added player_creation_enabled to $gprot_login that uses + graphics_connection_name (called from create_robot). Thus, + create_robot will fail if not called from gprot. Also, added + propery $gprot_login.create_enabled. Need to have this follow + $login.create_enabled to allow/disallow creation from either. +-- changed #4:_recycle to completely bypass the possibility of using + $recycler. Need to fix this if we decide to reuse object #s. + 4__recycle.eh +-- Made callable function #4(generic builder):create_object which + takes the same parameters as the moo command @create (#4:@create) + minus the 'named' or 'called' preposition. Allows aliases. + Names with spaces must be in quotes. Example gprot strings: + + 5 0 0 0 4 $thing "new thing" + 5 0 0 0 4 "generic raygun" phaser + 5 0 0 0 4 #5 cat,kitty,kittycat + + The same rules that apply to @create apply to create_object e.g. + the player must be in the same room as the superclass object for + the name form e.g. "generic raygun" to be used. + obj_create.eh +-- Made callable function #4:create_room which takes the same parameters + as the first form of @dig. i.e. @dig . The + @dig forms are not allowed, as only one object number + can be returned. Could have used a list, but decided against it + for simplicity's sake. Names with spaces must be in quotes. + Aliases NOT allowed. Note that it uses $room by default, but will + look at player:build_option("dig_room") for a different $room + subclass. + + Example gprot strings: + + 5 0 0 0 2 "my new room" + 5 0 0 0 2 mynewroom + room_create.eh +-- Made callable function #4:create_exit of the form + create_exit(, source, dest) where exit spec is the + same as the first form in @dig. i.e. only the exit from source + to dest is created and given the direction names specified in the + comma-separated list. The exit from dest to source created by @dig + if two lists separated by | is not created by create_exit. + The source and dest must be object ids. If the player doesn't own either + source or dest, it will fail. Example gprot strings: + + 5 0 0 0 3 north 11 165 + creates an exit from 11 to 165 + 5 0 0 0 3 south,s 165 11 + creates an exit back. south or s can be used to exit back. + exit_create.eh +-- made player class $robot_class which is the superclass for all + bots. Some gprot functions, such as recycle, will check to + make sure the base class is $robot_class. +-- made callable function recycle_object for gprot on #4. + It calls #4:_recycle which calls builtin recycle(), which + calls recycle() on the object being recycled. + obj_recycle.eh +-- recycle()is redefined for $robot_class. + robot_class_recycle.eh +-- fixed problem where graphics-only players were moved to $limbo + because enterfunc on room #11 calls $limbo:acceptable, which checks + if player in connected_players. If not, moved to $limbo. Since + graphics-only players were not in connected_players, they got + moved to $limbo. + + Fixed a lot of problems in this area. Basically scoured + server.c for any gprot issues. Fixes: + + The problem with $limbo above was that h->connection_time for + graphics connections was still 0, thus incurring un-logged-in + connection testing. connection_time for graphics connections + is now set in set_conn_type. connected_players() now handles + graphics connections as well as text. i.e. @who now shows both, + though not which types of connection(s). Note that this fix also + eliminates the unlogged-in player disconnect problem with + graphics connections. These are now treated the same as logged + in connections. Other related fixes: + + bf_connected_seconds and bf_idle_seconds now take into account + graphics connections. +-- Added the following server builtins: + graphics_connection_name + + boot_text_player + added fix to #6:@quit to call boot_text_player (gprotfix.eh) + boot_graphics_player + boot_player now closes both connections + + set_graphics_connection_option + graphics_connection_option + graphics_connection_options + will be needed for setting "binary" on graphics connections + NOTE: the options will be good only for the current graphics + connection session. No transfer to real player + + Added code in main loop to have the other connection reflect the + earliest connection time of either on disconnect of other. + connections never get here if connection is terminated by display + server, as ehwt does now. Need to implement tme to take care of + this. +-- Needed to fix recycle code in main_loop because graphics connections + will return valid(player) False +-- Had to remove code at top of main() to process connections still in + effect when shutdown occurs because it couldn't handle graphics + connections. Need to fix this. +-- Added ocme handling. +-- Added st (t - session terminate). t is called st in code to avoid + clashes with commonly used variable t. +-- Added new files oc_data.c and oc_data.h to handle oc server-specific + data. See notes there for more info. +-- Fixed major memory leak caused by not freeing strings created by + make_xxx_string calls. + +Version ehMOO-0.05, 12/02/96 + +-- Added new built-ins: + get_next_dih() - get the next available drawing information handle + increment_next_dih() - increment the di counter for next time + +-- Added two new moo functions in enter.eh and setup.eh: + #1:solicit_server_state + #6:solicit_server_state + These obviate the need for #6:tell_state, which must be removed +-- Two new moo files, oc.eh and oc_setup.eh contain the support + for sending oc events Only in MOO-1.8.0r5: ChangeLog.txt Only in MOO-1.8.0r5: MOOCodeSequences.txt diff -U 2 -b -P -x config.h -x y.tab.c -x y.tab.h MOO-1.8.0r5/Makefile.in ehMOO.0.93.r5.codeonly/Makefile.in --- MOO-1.8.0r5/Makefile.in Mon Mar 3 00:36:23 1997 +++ ehMOO.0.93.r5.codeonly/Makefile.in Sat Feb 3 01:02:19 2001 @@ -14,4 +14,10 @@ # Pavel@Xerox.Com +# eh Change History +# +# Revision 0.04 1996/03/31 11:13:38 trz +# Added support for eh Graphics Protocol. + + CC = @CC@ LIBRARIES = @LIBS@ @@ -31,5 +37,6 @@ net_proto.c numbers.c objects.c parse_cmd.c pattern.c program.c \ property.c quota.c ref_count.c regexpr.c server.c storage.c streams.c \ - sym_table.c tasks.c timers.c unparse.c utils.c verbs.c version.c + sym_table.c tasks.c timers.c unparse.c utils.c verbs.c version.c\ + gprot.c gprot_lambda.c oc_data.c hash.c ll.c objtab.c oreg.c fntab.c OPT_NET_SRCS = net_single.c net_multi.c \ @@ -50,5 +57,5 @@ ref_count.h regexpr.h server.h storage.h streams.h structures.h \ sym_table.h tasks.h timers.h tokens.h unparse.h utils.h verbs.h \ - version.h + version.h gprot.h gprot_lambda.h SYSHDRS = my-ctype.h my-fcntl.h my-in.h my-inet.h my-ioctl.h my-math.h \ @@ -146,4 +153,10 @@ cp Makefile.in Makefile.in.bak ed - Makefile.in < eddep +# Revision 1.4 1996/03/31 11:07:52 trz +# Added support for eh Graphics Protocol. +# +# Revision 1.1 1996/03/12 07:43:37 root +# Initial revision +# rm -f eddep makedep Only in MOO-1.8.0r5: Minimal.db Only in MOO-1.8.0r5: README Only in MOO-1.8.0r5: README.Minimal Only in MOO-1.8.0r5: README.r5 Only in MOO-1.8.0r5: aclocal.m4 Only in MOO-1.8.0r5: config.h.in Only in MOO-1.8.0r5: configure Only in MOO-1.8.0r5: configure.in diff -U 2 -b -P -x config.h -x y.tab.c -x y.tab.h MOO-1.8.0r5/fntab.c ehMOO.0.93.r5.codeonly/fntab.c --- MOO-1.8.0r5/fntab.c Wed Dec 31 18:00:00 1969 +++ ehMOO.0.93.r5.codeonly/fntab.c Sat Feb 3 00:52:22 2001 @@ -0,0 +1,112 @@ +/********************************************************************** + ** eh protocol dispatch function table + ** Copyright (c) 1996 by Tom Zanussi and Steve Albrecht +**********************************************************************/ + +#include +#include +#include +#include +#ifndef WIN32 +#include +#include +#endif +#include "ll.h" +#include "hash.h" +#include "fntab.h" + +/********************************************************************** + ** This module contains the eh code for mapping gprot messages and + ** events to handler functions +**********************************************************************/ + +#define DEFAULT_HLIST_SIZE 103 + +int fnTable_removeFunction(fnTable * fntab, const char * fn_name) +{ + return HashTable_removeItem(fntab->table, fn_name); +} + +void * fnTable_findFunction(fnTable * fntab, const char * fn_name) +{ + return HashTable_findItem(fntab->table, fn_name); +} + +void fnTable_delete(fnTable * fntab) +{ + if(!fntab) + return; + + if(fntab->table) + HashTable_delete(fntab->table); + free(fntab); +} + +int fnTable_addFunction(fnTable * fntab, const char * fn_name, void * fn) +{ + return HashTable_addItem(fntab->table, fn_name, fn); +} + +/* if filename NULL, or filename not found, empty table returned */ +fnTable * fnTable_new() +{ + fnTable * fntab = (fnTable *)malloc(sizeof(fnTable)); + if(!fntab) + return NULL; + + fntab->table = HashTable_new(DEFAULT_HLIST_SIZE, + createFunction_fn, + deleteFunction_fn, + duplicateFunction_fn, + compareFunction_fn); + + if(!fntab->table) { + free(fntab); + return NULL; + } + + return fntab; +} + + +/* In this case, we don't want to allocate memory, the object has + * been cast to void * + */ +void * createFunction_fn( void * data ) +{ + return data; +} + +/* nothing to delete */ +int deleteFunction_fn( void * data ) +{ + return (1); +} + +/*--------------------------------------------------------------- + * This function determines what to do when inserting a node + * into a list if an existing node with the same data is found + * in the list. In this case, since we are counting words, if a + * duplicate word is found, we simply increment the counter. + * + * Note this function should return one of the following values: + * 0 an error occurred + * 1 delete the duplicate node + * 2 insert the duplicate node + * Any other processing on the duplicate should be done in this + * function. + *-------------------------------------------------------------*/ + +int duplicateFunction_fn(Link new_node, Link list_node) +{ /* don't want duplicates, return 1 to delete new_node */ + return (1); +} + +int compareFunction_fn(void *first, void *second) +{ + HashData * f1 = (HashData *)first; + HashData * f2 = (HashData *)second; + + return (strcmp(f1->key, f2->key)); +} + diff -U 2 -b -P -x config.h -x y.tab.c -x y.tab.h MOO-1.8.0r5/fntab.h ehMOO.0.93.r5.codeonly/fntab.h --- MOO-1.8.0r5/fntab.h Wed Dec 31 18:00:00 1969 +++ ehMOO.0.93.r5.codeonly/fntab.h Sat Feb 3 00:52:29 2001 @@ -0,0 +1,15 @@ +typedef struct fnTable +{ + HashTable * table; +} fnTable; + +void * fnTable_findFunction(fnTable * fntab, const char * fn_name); +int fnTable_removeFunction(fnTable * fntab, const char * fn_name); +void fnTable_delete(fnTable * fntab); +int fnTable_addFunction(fnTable * fntab, const char * fn_name, void * fn); +fnTable * fnTable_new(); + +void * createFunction_fn( void * data ); +int deleteFunction_fn( void * data ); +int duplicateFunction_fn(Link new_node, Link list_node); +int compareFunction_fn(void *first, void *second); diff -U 2 -b -P -x config.h -x y.tab.c -x y.tab.h MOO-1.8.0r5/functions.c ehMOO.0.93.r5.codeonly/functions.c --- MOO-1.8.0r5/functions.c Sun Jul 6 22:24:54 1997 +++ ehMOO.0.93.r5.codeonly/functions.c Sat Feb 3 00:52:22 2001 @@ -16,4 +16,12 @@ *****************************************************************************/ +/* + * eh Change History + * + * Revision 0.04 1996/03/31 11:13:38 trz + * Added support for eh Graphics Protocol. + * + */ + #include "my-stdarg.h" @@ -31,4 +39,6 @@ #include "utils.h" +#include "gprot_lambda.h" + /***************************************************************************** * This is the table of procedures that register MOO built-in functions. To @@ -55,5 +65,6 @@ register_server, register_tasks, - register_verbs + register_verbs, + register_gprot }; diff -U 2 -b -P -x config.h -x y.tab.c -x y.tab.h MOO-1.8.0r5/gprot.c ehMOO.0.93.r5.codeonly/gprot.c --- MOO-1.8.0r5/gprot.c Wed Dec 31 18:00:00 1969 +++ ehMOO.0.93.r5.codeonly/gprot.c Sat Feb 3 00:52:22 2001 @@ -0,0 +1,1158 @@ +/********************************************************************** + ** eh Graphics Protocol implementation common code + ** Copyright (c) 1995 by Tom Zanussi and Steve Albrecht +**********************************************************************/ + +/********************************************************************** + * + * Version History + * + * original - trz + * + * {1} Mar 23, '97 - swa: added oku duration field + * +**********************************************************************/ + +#include +#include +#include +#include "ll.h" +#include "hash.h" +#include "fntab.h" +#include "gprot.h" +#include "oc_data.h" + +/********************************************************************** + ** This module contains the eh Graphics Protocol code common to both + ** client and server implementations. +**********************************************************************/ + +/********************************************************************** + ** Protocol handling functions + ** + ** These functions operate on an instance of GraphicsProtocol, which + ** encapsulates the eh Graphics Protocol. An instance of + ** GraphicsProtocol should be allocated and initialized for each end + ** of a player session. Initialization consists of calling + ** ProtocolInit() for the allocated GraphicsProtocol instance. This + ** sets up the protocol to handle Version 1 events and messages, + ** which all clients and servers must support. Protocol negotiation + ** may result in the GraphicsProtocol instance being modified to + ** handle higher versions through ProtocolAppend(). +**********************************************************************/ + +/* + ** ProtocolAppend() + ** + ** Append a set of protocol handling functions to the current set + ** contained in the passed GraphicsProtocol instance. Used to + ** extend the set of msg/events handled by the GraphicsProtocol. + ** + ** GraphicsProtocol contains a table of function pointers indexed on + ** msg/event id. Control is dispatched to the handler appropriate to + ** the msg/event. + */ +GPROT_ERR ProtocolAppend(GraphicsProtocol * gprot, + gprot_dispatch_entry handlers[], int nHandlers) +{ + int i; + + for(i=0;ihandlers, handlers[i].fn_name, + handlers[i].fn); + } + + gprot->nHandlers += nHandlers; + + return GE_NONE; +} + +/* + ** ProtocolSetup_V1() + ** + ** Append the set of handlers required to handle the base protocol. + ** All implementations must handle V1 functionality. +*/ + +GPROT_ERR ProtocolSetup_V1(GraphicsProtocol * gprot) +{ + gprot_dispatch_entry handlers[] = + { + { PN_MSGID, handle_pn }, + { OS_MSGID, handle_osm }, + { OKU_MSGID, handle_oku }, + { OI_MSGID, handle_oi}, + { OT_MSGID, handle_ot}, + { OD_MSGID, handle_od}, + { OC_MSGID, handle_oc}, + { ST_MSGID, handle_st}, + { OR_MSGID, handle_or}, + { OU_MSGID, handle_ou} + }; + + return ProtocolAppend(gprot, handlers, + sizeof(handlers)/sizeof(gprot_dispatch_entry)); +} + +/* + ** ProtocolInit() + ** + ** Initialize the graphics protocol. At mimimum, V1 handlers must + ** be supported. +*/ + +GPROT_ERR ProtocolInit(GraphicsProtocol * gprot) +{ + gprot->version = current_gprot_version; + gprot->nHandlers = 0; + gprot->handlers = fnTable_new(); + + return ProtocolSetup_V1(gprot); +} + +/* + ** ProtocolCleanup() + ** + ** Clean up graphics protocol related stuff. + ** +*/ + +void ProtocolCleanup(GraphicsProtocol * gprot) +{ + fnTable_delete(gprot->handlers); +} + +static GPROT_ERR parse_graphics_input(char *input, int *argc, char *argv[], + char * msgid); + +/* + ** + ** handle_graphics_input() + ** + ** Parse and dispatch the msg/event to the proper handler. +*/ + +GPROT_ERR handle_graphics_input(ObjectID player, gprot_role role, + void * context, GraphicsProtocol * gprot, + const char * input) +{ + int argc; + GPROT_ERR err; + char msgid[MAX_GPROT_MSGIDLEN]; + char * argv[MAXFIELDS]; + char * s = strdup(input); + + err = parse_graphics_input(s, &argc, argv, msgid); + + if(!err) { + err = dispatch_message(player, role, context, gprot, msgid, + argc, argv); + } + + free(s); + return err; +} + +/* + ** dispatch_message() + ** + ** Make the actual handler function call. +*/ + +GPROT_ERR dispatch_message(ObjectID player, gprot_role role, void * context, + GraphicsProtocol * gprot, char * msgid, + int argc, char ** argv) +{ + GPROT_ERR (*found_fn)() = fnTable_findFunction(gprot->handlers, msgid); + if(found_fn) + return (*found_fn)(player, role, context, argc, argv); + else + return GE_BADMSG; +} + +/********************************************************************** + ** Message/Event handlers + ** + ** Handlers for specific msgs/events. + ** + ** All have the same argument signature: + ** + ** ObjectID player - player on whose behalf the message is sent. Only + ** meaninful to clients. + ** gprot_role role - GPROT_SERVER or GPROT_CLIENT. Indicates whether + ** we are handling a message or an event. Clients + ** and servers call functions defined in a separate + ** module specific to their role to access the + ** appropriate client/server behavior. + ** argc, argv - #args, arglist of field following the msg/event id +**********************************************************************/ + +/* + ** handle_pn() + ** + ** handler for pn (protocol negotiation) +*/ +GPROT_ERR handle_pn(ObjectID player, gprot_role role, void * context, + int argc, char ** argv) +{ + char * p; + int n=0; + pn pn; + + if(argc < 2) + return GE_BADMSG; + + pn.protocol_version = strtoul(argv[n++], &p, 10); + if(*p != '\0') return GE_BADMSG; + + pn.server_type = strtoul(argv[n++], &p, 10); + if(*p != '\0') return GE_BADMSG; + pn.argc = 2; + + if(role == GPROT_SERVER) + return ServerPN(&pn, context); + else + return ClientPN(player, &pn, context); +} + +/* + ** handle_osm() + ** + ** handler for osm (object subscription message) +*/ +GPROT_ERR handle_osm(ObjectID player, gprot_role role, void * context, + int argc, char ** argv) +{ + char * p; + int n=0; + osm osm; + + if(argc < 1) + return GE_BADMSG; + + osm.objectID = strtoul(argv[n++], &p, 10); + if(*p != '\0') return GE_BADMSG; + + osm.argc = 1; + + if(argc > 1) { + osm.event_mask = strtoul(argv[n++], &p, 10); + if(*p != '\0') return GE_BADMSG; + osm.argc = 2; + } + + if(role == GPROT_SERVER) + return ServerOSM(&osm, context); + else + return ClientOSM(player, &osm, context); +} + +/* + ** handle_oku[m/e]() + ** + ** handler for ot (object kinematic update message/event) +*/ + +GPROT_ERR handle_oku(ObjectID player, gprot_role role, void * context, + int argc, char ** argv) +{ + char * p; + int i, n=0; + oku oku; + + if(argc < 2) + return GE_BADMSG; + + oku.objectID = strtoul(argv[n++], &p, 10); + if(*p != '\0') return GE_BADMSG; + + oku.timestamp = strtol(argv[n++], &p, 10); + if(*p != '\0') return GE_BADMSG; + + oku.argc = 2; /* solicitation oku */ + + if(argc >= 5) { + for(i=0;i<3;i++) { + oku.position[i] = strtol(argv[n++], &p, 10); + if(*p != '\0') return GE_BADMSG; + } + oku.argc = 5; + } + + if(argc >= 8) { + for(i=0;i<3;i++) { + oku.facing[i] = strtol(argv[n++], &p, 10); + if(*p != '\0') return GE_BADMSG; + } + oku.argc = 8; + } + + if(argc >= 11) { + for(i=0;i<3;i++) { + oku.velocity[i] = strtol(argv[n++], &p, 10); + if(*p != '\0') return GE_BADMSG; + } + oku.argc = 11; + } + + /* {1} optional duration field */ + if(argc >= 12) { + oku.duration = strtol(argv[n++], &p, 10); + if(*p != '\0') return GE_BADMSG; + oku.argc = 12; + } + + if(argc >= 15) { + for(i=0;i<3;i++) { + oku.angular_velocity[i] = strtol(argv[n++], &p, 10); + if(*p != '\0') return GE_BADMSG; + } + oku.argc = 15; + } + + /* {1} optional duration field */ + if(argc >= 16) { + oku.angular_duration = strtol(argv[n++], &p, 10); + if(*p != '\0') return GE_BADMSG; + oku.argc = 16; + } + + if(role == GPROT_SERVER) + return ServerOKU(&oku, context); + else + return ClientOKU(player, &oku, context); +} + +/* + ** handle_oi[m/e]() + ** + ** handler for oi (object interaction message/event) +*/ +GPROT_ERR handle_oi(ObjectID player, gprot_role role, void * context, + int argc, char ** argv) +{ + char * p; + int i, n=0; + oi oi; + + if(argc < 5) + return GE_BADMSG; + + oi.objectID = strtoul(argv[n++], &p, 10); + if(*p != '\0') return GE_BADMSG; + + oi.timestamp = strtol(argv[n++], &p, 10); + if(*p != '\0') return GE_BADMSG; + + for(i=0;i<3;i++) { + oi.force[i] = strtol(argv[n++], &p, 10); + if(*p != '\0') return GE_BADMSG; + } + oi.argc = 5; + + if(argc >= 6) { + oi.duration = strtoul(argv[n++], &p, 10); + if(*p != '\0') return GE_BADMSG; + oi.argc = 6; + } + + if(role == GPROT_SERVER) + return ServerOI(&oi, context); + else + return ClientOI(player, &oi, context); +} + +/* + ** handle_ot[m/e]() + ** + ** handler for ot (object torque message/event) +*/ +GPROT_ERR handle_ot(ObjectID player, gprot_role role, void * context, + int argc, char ** argv) +{ + char * p; + int i, n=0; + ot ot; + + if(argc < 5) + return GE_BADMSG; + + ot.objectID = strtoul(argv[n++], &p, 10); + if(*p != '\0') return GE_BADMSG; + + ot.timestamp = strtol(argv[n++], &p, 10); + if(*p != '\0') return GE_BADMSG; + + for(i=0;i<3;i++) { + ot.torque[i] = strtol(argv[n++], &p, 10); + if(*p != '\0') return GE_BADMSG; + } + ot.argc = 5; + + if(argc >= 6) { + ot.duration = strtoul(argv[n++], &p, 10); + if(*p != '\0') return GE_BADMSG; + ot.argc = 6; + } + + if(role == GPROT_SERVER) + return ServerOT(&ot, context); + else + return ClientOT(player, &ot, context); +} + +/* + ** handle_od[m/e]() + ** + ** handler for od (object delete message/event) +*/ +GPROT_ERR handle_od(ObjectID player, gprot_role role, void * context, + int argc, char ** argv) +{ + char * p; + int n=0; + od od; + + if(argc < 1) + return GE_BADMSG; + + od.objectID = strtoul(argv[n++], &p, 10); + if(*p != '\0') return GE_BADMSG; + + od.argc = 1; + + if(role == GPROT_SERVER) + return ServerOD(&od, context); + else + return ClientOD(player, &od, context); +} + +/* + ** handle_oc[m/e]() + ** + ** handler for oc (object change message/event) +*/ +GPROT_ERR handle_oc(ObjectID player, gprot_role role, void * context, + int argc, char ** argv) +{ + char * p; + int n=0; + GPROT_ERR rc; + oc * oc = new_oc(OCDT_NONE); + + if(argc < 4) { + delete_oc(oc); + return GE_BADMSG; + } + + oc->objectID = strtoul(argv[n++], &p, 10); + if(*p != '\0') { + delete_oc(oc); + return GE_BADMSG; + } + + oc->handle = strtoul(argv[n++], &p, 10); + if(*p != '\0') { + delete_oc(oc); + return GE_BADMSG; + } + + oc->duration = strtoul(argv[n++], &p, 10); + if(*p != '\0') { + delete_oc(oc); + return GE_BADMSG; + } + + oc->data->datatype = strtoul(argv[n++], &p, 10); + if(*p != '\0') { + delete_oc(oc); + return GE_BADMSG; + } + + if(argc >= 4) /* if not, no associated data */ + oc->data->raw_data = strdup(argv[n++]); + + if(role == GPROT_SERVER) + rc = ServerOC(oc, context); + else + rc = ClientOC(player, oc, context); + + delete_oc(oc); + + return rc; +} + +/* + ** handle_st[m/e]() + ** + ** handler for st (session_terminate message/event) +*/ +GPROT_ERR handle_st(ObjectID player, gprot_role role, void * context, + int argc, char ** argv) +{ + if(role == GPROT_SERVER) + return ServerST(context); + else + return ClientST(player, context); +} + +/* + ** handle_or[m]() + ** + ** handler for or (object registration message) +*/ +GPROT_ERR handle_or(ObjectID player, gprot_role role, void * context, + int argc, char ** argv) +{ + char * p; + int n; + or or; + + if(argc < 1 || argc > MAXFIELDS) + return GE_BADMSG; + + for(n=0 ; n MAXFIELDS) + return GE_BADMSG; + + for(n=0 ; nprotocol_version); + + if(pn->argc >= 1) { + sprintf(buf, " %lu", pn->server_type); + strcat(string, buf); + } + + return string; +} + +/* + ** make_osm_string() + ** + ** Given an osm struct, create an osm string to send to client. + ** Caller owns allocated string memory. +*/ +char * make_osm_string(osm * osm) +{ + char buf[256]; + + char * string = (char *)malloc(256); + sprintf(string, "%s %lu", OS_MSGID, osm->objectID); + + if(osm->argc >= 1) { + sprintf(buf, " %lu", osm->event_mask); + strcat(string, buf); + } + + return string; +} + +/* + ** make_oku_string() + ** + ** Given an oku struct, create an oku string to send to client/server. + ** Caller owns allocated string memory. +*/ +char * make_oku_string(oku * oku) +{ + char buf[256]; + + char * string = (char *)malloc(256); + + sprintf(string, "%s %lu %ld", OKU_MSGID, oku->objectID, oku->timestamp); + + if(oku->argc >= 5) { + sprintf(buf, " %ld %ld %ld", oku->position[0], oku->position[1], + oku->position[2]); + strcat(string, buf); + } + + if(oku->argc >= 8) { + sprintf(buf, " %ld %ld %ld", oku->facing[0], oku->facing[1], + oku->facing[2]); + strcat(string, buf); + } + + if(oku->argc >=11) { + sprintf(buf, " %ld %ld %ld", oku->velocity[0], oku->velocity[1], + oku->velocity[2]); + strcat(string, buf); + } + + /* optional duration field */ /* {1} */ + if(oku->argc >=12) { + sprintf(buf, " %lu", oku->duration); + strcat(string, buf); + } + + if(oku->argc >=15) { + sprintf(buf, " %ld %ld %ld", oku->angular_velocity[0], oku->angular_velocity[1], + oku->angular_velocity[2]); + strcat(string, buf); + } + + /* optional duration field */ /* {1} */ + if(oku->argc >=16) { + sprintf(buf, " %lu", oku->angular_duration); + strcat(string, buf); + } + + return string; +} + +/* + ** make_oi_string() + ** + ** Given an oi struct, create an oi string to send to client/server. + ** Caller owns allocated string memory. +*/ +char * make_oi_string(oi * oi) +{ + char buf[256]; + + char * string = (char *)malloc(256); + sprintf(string, "%s %lu %ld %ld %ld %ld", OI_MSGID, oi->objectID, + oi->timestamp, oi->force[0], oi->force[1], + oi->force[2]); + + if(oi->argc >= 6) { + sprintf(buf, " %lu", oi->duration); + strcat(string, buf); + } + + return string; +} + +/* + ** make_ot_string() + ** + ** Given an ot struct, create an ot string to send to client/server. + ** Caller owns allocated string memory. +*/ +char * make_ot_string(ot * ot) +{ + char buf[256]; + + char * string = (char *)malloc(256); + sprintf(string, "%s %lu %ld %ld %ld %ld", OT_MSGID, ot->objectID, + ot->timestamp, ot->torque[0], ot->torque[1], + ot->torque[2]); + + if(ot->argc >= 6) { + sprintf(buf, " %lu", ot->duration); + strcat(string, buf); + } + + return string; +} + +/* + ** make_od_string() + ** + ** Given an od struct, create an od string to send to client. + ** Caller owns allocated string memory. +*/ +char * make_od_string(od * od) +{ + char * string = (char *)malloc(256); + sprintf(string, "%s %lu", OD_MSGID, od->objectID); + + return string; +} + +/* + ** make_oc_string() + ** + ** Given an oc struct, create an oc string to send to client/server. + ** If the oc contains parsed_data (filled in by caller), concatenate + ** the fields into raw_data to send via gprot. + ** Caller owns allocated string memory. +*/ +char * make_oc_string(oc * oc) +{ + char * string = (char *)malloc(MAX_GPROT_MSGLEN); + + if(!oc->data->raw_data && oc->data->parsed_data) + unparse_oc_data(oc); + + if(oc->data->raw_data) { + sprintf(string, "%s %lu %lu %lu %u %s", OC_MSGID, oc->objectID, + oc->handle, oc->duration, oc->data->datatype, + oc->data->raw_data); + } else { /* no associated data */ + sprintf(string, "%s %lu %lu %lu %u", OC_MSGID, oc->objectID, + oc->handle, oc->duration, oc->data->datatype); + } + + return string; +} + +/* + ** make_st_string() + ** + ** Given a st struct, create a st string to send to client. + ** Caller owns allocated string memory. +*/ +char * make_st_string() +{ + char * string = (char *)malloc(256); + sprintf(string, "%s", ST_MSGID); + + return string; +} + +/* + ** make_or_string() + ** + ** Given an or struct, create an or string to send to client. + ** Caller owns allocated string memory. +*/ +char * make_or_string(or * or) +{ + int i; + char buf[256]; + char * string = (char *)malloc(1024); + + sprintf(string, "%s", OR_MSGID); + + for(i=0 ; iargc ; i++) { + sprintf(buf, " %lu", or->ObjectID[i]); + strcat(string, buf); + } + + return string; +} + +/* + ** make_ou_string() + ** + ** Given an ou struct, create an ou string to send to client. + ** Caller owns allocated string memory. +*/ +char * make_ou_string(ou * ou) +{ + int i; + char buf[256]; + char * string = (char *)malloc(1024); + + sprintf(string, "%s", OU_MSGID); + + for(i=0 ; iargc ; i++) { + sprintf(buf, " %lu", ou->ObjectID[i]); + strcat(string, buf); + } + + return string; +} + +/* + ** parse_oc_input() + ** + ** parse a string into array of tokens. + ** stolen from Lamdba. +*/ +#define MAX_OC_FIELDS 5 +static GPROT_ERR parse_oc_input(char *input, int *argc, char *argv[]) +{ + char *ptr = input; + int fieldcnt = 0; + int lastfield = 0; + + while (*input == ' ') + input++; + + /* parse until server-specific data reached */ + for (*argc = 0; *argc < MAXFIELDS && *input != '\0'; (*argc)++) { + argv[*argc] = ptr; + while (*input != '\0' && (lastfield || *input != ' ')) { + char c = *(input++); + + if (c == '\\') { + if (*input != '\0') + *(ptr++) = *(input++); + } else + *(ptr++) = c; + } + while (*input == ' ') + input++; + *(ptr++) = '\0'; + if(++fieldcnt >= MAX_OC_FIELDS-1) + lastfield = 1; + } + + return GE_NONE; +} + + +/* + ** parse_graphics_input() + ** + ** parse a string into array of tokens. + ** stolen from Lamdba. +*/ +static GPROT_ERR parse_graphics_input(char *input, int *argc, char *argv[], + char * msgid) +{ + char *ptr = input; + char *msgid_ptr = ptr; + + while (*input == ' ') + input++; + + /* parse message id */ + while (*input != '\0' && *input != ' ') { + char c = *(input++); + + if (c == '\\') { + if (*input != '\0') + *(ptr++) = *(input++); + } else + *(ptr++) = c; + } + while (*input == ' ') + input++; + *(ptr++) = '\0'; + + if(strlen(msgid_ptr) > MAX_GPROT_MSGIDLEN) + return GE_SERVER_ERR; + + strcpy(msgid, msgid_ptr); + + if(!strcmp(msgid, OC_MSGID)) + return parse_oc_input(input, argc, argv); + else + return parse_into_fields(input, argc, argv, MAXFIELDS); +} + +/* + ** parse_into_fields() + ** + ** parse a non-oc string into array of tokens. oc strings are + ** parsed by parse_oc_input(). + ** +*/ +GPROT_ERR parse_into_fields(char *input, int *argc, char *argv[], int nfields) +{ + int in_quotes = 0; + char *ptr = input; + int maxfields = nfields < MAXFIELDS ? nfields : MAXFIELDS; + + while (*input == ' ') + input++; + + for (*argc = 0; *argc < maxfields && *input != '\0'; (*argc)++) { + argv[*argc] = ptr; + if(*argc == (maxfields-1)) { + (*argc)++; + break; + } + + while (*input != '\0' && (in_quotes || *input != ' ')) { + char c = *(input++); + + if (c == '"') + in_quotes = !in_quotes; + else if (c == '\\') { + if (*input != '\0') + *(ptr++) = *(input++); + } else + *(ptr++) = c; + } + while (*input == ' ') + input++; + *(ptr++) = '\0'; + } + + return GE_NONE; +} + +#ifdef GPROT_DEBUG +/* + ** make_pn_debug_string() + ** + ** Given a pn struct, create a pn debug string to print. + ** Caller owns allocated string memory. +*/ +char * make_pn_debug_string(pn * pn) +{ + char buf[512]; + + char * string = (char *)malloc(512); + sprintf(string, " version %lu", pn->protocol_version); + + if(pn->argc >= 1) { + sprintf(buf, " ,server_type: %lu", pn->server_type); + strcat(string, buf); + } + + return string; +} + +/* + ** make_osm_debug_string() + ** + ** Given an osm struct, create an osm debug string to print. + ** Caller owns allocated string memory. +*/ +char * make_osm_debug_string(osm * osm) +{ + char buf[512]; + + char * string = (char *)malloc(512); + sprintf(string, " id %lu", osm->objectID); + + if(osm->argc >= 1) { + sprintf(buf, " ,event_mask: %lu", osm->event_mask); + strcat(string, buf); + } + + return string; +} + +/* + ** make_oku_debug_string() + ** + ** Given an oku struct, create an oku debug string to print. + ** Caller owns allocated string memory. +*/ +char * make_oku_debug_string(oku * oku) +{ + char buf[512]; + + char * string = (char *)malloc(512); + + sprintf(string, " id %lu, ts %ld", oku->objectID, oku->timestamp); + + if(oku->argc >= 5) { + sprintf(buf, ", pos [%ld,%ld,%ld]", oku->position[0], oku->position[1], + oku->position[2]); + strcat(string, buf); + } + + if(oku->argc >= 8) { + sprintf(buf, ", fac [%ld,%ld,%ld]", oku->facing[0], oku->facing[1], + oku->facing[2]); + strcat(string, buf); + } + + if(oku->argc >=11) { + sprintf(buf, ", vel [%ld,%ld,%ld]", oku->velocity[0], oku->velocity[1], + oku->velocity[2]); + strcat(string, buf); + } + + if(oku->argc >=12) { /* {1} */ + sprintf(buf, ", dur %lu", oku->duration); + strcat(string, buf); + } + + if(oku->argc >=15) { + sprintf(buf, ", angvel [%ld,%ld,%ld]", oku->angular_velocity[0], oku->angular_velocity[1], + oku->angular_velocity[2]); + strcat(string, buf); + } + + if(oku->argc >=16) { /* {1} */ + sprintf(buf, ", angdur %lu", oku->angular_duration); + strcat(string, buf); + } + + return string; +} + +/* + ** make_oi_debug_string() + ** + ** Given an oi struct, create an oi string to print. + ** Caller owns allocated string memory. +*/ +char * make_oi_debug_string(oi * oi) +{ + char buf[512]; + + char * string = (char *)malloc(512); + sprintf(string, " id %lu, ts %ld, force [%ld,%ld,%ld]", oi->objectID, + oi->timestamp, oi->force[0], oi->force[1], + oi->force[2]); + + if(oi->argc >= 6) { + sprintf(buf, ", dur %lu", oi->duration); + strcat(string, buf); + } + + return string; +} + +/* + ** make_ot_debug_string() + ** + ** Given an ot struct, create an ot string to print. + ** Caller owns allocated string memory. +*/ +char * make_ot_debug_string(ot * ot) +{ + char buf[512]; + + char * string = (char *)malloc(512); + sprintf(string, " id %lu, ts %ld, torque [%ld,%ld,%ld]", ot->objectID, + ot->timestamp, ot->torque[0], ot->torque[1], + ot->torque[2]); + + if(ot->argc >= 6) { + sprintf(buf, ", dur %lu", ot->duration); + strcat(string, buf); + } + + return string; +} + +/* + ** make_od_debug_string() + ** + ** Given an od struct, create an od string to print. + ** Caller owns allocated string memory. +*/ +char * make_od_debug_string(od * od) +{ + char * string = (char *)malloc(512); + sprintf(string, " id %lu", od->objectID); + + return string; +} + +/* + ** make_oc_debug_string() + ** + ** Given an oc struct, create an oc string to print. + ** Caller owns allocated string memory. +*/ +char * make_oc_debug_string(oc * oc) +{ + char * string = (char *)malloc(MAX_GPROT_MSGLEN); + + if(!oc->data->raw_data && oc->data->parsed_data) + unparse_oc_data(oc); + + if(oc->data->raw_data) { + sprintf(string, " id %lu, handle %lu, dur %lu, datatype %u, data %s", oc->objectID, + oc->handle, oc->duration, oc->data->datatype, + oc->data->raw_data); + } else { /* no associated data */ + sprintf(string, " id %s, handle %lu, dur %lu, datatype %u", oc->objectID,"%d %lu %lu %lu %u", OC_MSGID, oc->objectID, + oc->handle, oc->duration, oc->data->datatype); + } + + return string; +} + +/* + ** make_st_debug_string() + ** + ** Given a st struct, create a st string to print. + ** Caller owns allocated string memory. +*/ +char * make_st_debug_string() +{ + char * string = (char *)malloc(256); + sprintf(string, ""); + + return string; +} + +/* + ** make_or_debug_string() + ** + ** Given an or struct, create an or string to send to client. + ** Caller owns allocated string memory. +*/ +char * make_or_debug_string(or * or) +{ + int i; + char buf[256]; + char * string = (char *)malloc(1024); + + sprintf(string, " objectIDs:"); + + for(i=0 ; iargc ; i++) { + sprintf(buf, " %lu", or->ObjectID[i]); + strcat(string, buf); + } + + return string; +} + +/* + ** make_ou_debug_string() + ** + ** Given an ou struct, create an ou string to send to client. + ** Caller owns allocated string memory. +*/ +char * make_ou_debug_string(ou * ou) +{ + int i; + char buf[256]; + char * string = (char *)malloc(1024); + + sprintf(string, " objectIDs:"); + + for(i=0 ; iargc ; i++) { + sprintf(buf, " %lu", ou->ObjectID[i]); + strcat(string, buf); + } + + return string; +} + +#endif diff -U 2 -b -P -x config.h -x y.tab.c -x y.tab.h MOO-1.8.0r5/gprot.h ehMOO.0.93.r5.codeonly/gprot.h --- MOO-1.8.0r5/gprot.h Wed Dec 31 18:00:00 1969 +++ ehMOO.0.93.r5.codeonly/gprot.h Sat Feb 3 00:52:29 2001 @@ -0,0 +1,284 @@ +/* gprot.h + * + * Version History + * + * original - trz + * + * {1} Mar 23, '97 - swa: added duration field to oku for rectilinear motion + * +*/ + +#include + +#define MAXFIELDS 20 +#define MAX_GPROT_MSGLEN 65536 +#define MAX_GPROT_MSGIDLEN 16 + +#define PN_MSGID "pn" +#define OS_MSGID "os" +#define OC_MSGID "oc" +#define OKU_MSGID "oku" +#define OI_MSGID "oi" +#define OT_MSGID "ot" +#define OD_MSGID "od" +#define ST_MSGID "st" +#define OR_MSGID "or" +#define OU_MSGID "ou" + +#define STRTOUL(val, p) strtoul(val, p, 10); if(*p != '\0') return GE_BADMSG +#define STRTOL(val, p) strtol(val, p, 10); if(*p != '\0') return GE_BADMSG + +#define ALL_OBJECTS 0 +#define SELF_OBJECT 1 +#define NO_OBJECT 2 + +#define FIRST_OBJECT 101 + +#define AVATAR_TYPESTR "avatar" +#define OBJECT_TYPESTR "object" +#define ROOM_TYPESTR "room" +#define EXIT_TYPESTR "exit" + +/** + ** eh Graphics Protocal Version info + **/ + +/* The following list must never be reordered, only appended to. There is one + * element per version of the graphics protocol. The integer value of each + * element is used in protocol negotiation. Versioning scheme borrowed from + * LambdaMOO. + */ +typedef enum { + GPROTV_Prehistory, /* Before gprot versions */ + GPROTV_Minimal, /* pn, osm, oku, oi, ot, od, oc, st, dir, diu, + * or, ou + */ + Num_GPROT_Versions /* Special: the current version is this - 1. */ +} GPROT_Version; + +#define current_gprot_version ((GPROT_Version) (Num_GPROT_Versions - 1)) + +extern int check_gprot_version(GPROT_Version); + +/* display server types */ +#define SERVER_DEFAULT 0x00000000 +#define SERVER_VRML_1 0x00000001 +#define SERVER_VRML_2 0x00000002 +#define SERVER_EHWT 0x00000004 + +/** + ** end eh Graphics Protocal Version info + **/ + +typedef enum gprot_role +{ + GPROT_CLIENT, + GPROT_SERVER +} gprot_role; + +typedef unsigned long ObjectID; + +typedef enum gprot_err +{ + GE_NONE, + GE_CLIENT_ERR, + GE_SERVER_ERR, + GE_ALLOC_ERR, + GE_BADMSG +} GPROT_ERR; + +typedef struct gprot_dispatch_entry +{ + const char * fn_name; + GPROT_ERR (*fn)(); +} gprot_dispatch_entry; + +typedef struct gprot_dispatch_table +{ + GPROT_Version version; + int nHandlers; + fnTable * handlers; + +} GraphicsProtocol; + +typedef struct pn +{ + int argc; + unsigned long protocol_version; + unsigned long server_type; +} pn; + +typedef struct osm +{ + int argc; + ObjectID objectID; + unsigned long event_mask; /* optional: all */ + /* 1=oku, 2=oi, 4=oc, 3=oku+oi, etc... */ +} osm; + +typedef struct oku +{ + int argc; + ObjectID objectID; + time_t timestamp; /* time_t type is TBD */ + signed long position[3]; /* units are TBD or may be client-specific */ + signed long facing[3]; /* optional: (0,0,0); units are TBD " */ + signed long velocity[3]; /* optional: (0,0,0); units are TBD " */ + unsigned long duration; /* optional: units are TBD */ /* {1} */ + signed long angular_velocity[3]; /* optional: (0,0,0); units are TBD " */ + unsigned long angular_duration; /* optional: units are TBD */ /* {1} */ +} oku; + +typedef struct oi +{ + int argc; + ObjectID objectID; + time_t timestamp; /* time_t type is TBD */ + signed long force[3]; /* units are TDB */ + unsigned long duration; /* optional: impulse; units are TDB */ +} oi; + +typedef struct ot +{ + int argc; + ObjectID objectID; + time_t timestamp; /* time_t type is TBD */ + signed long torque[3]; /* units are TDB */ + unsigned long duration; /* optional: impulse; units are TDB */ +} ot; + +typedef struct od +{ + int argc; + ObjectID objectID; +} od; + +typedef struct or +{ + int argc; + unsigned long ObjectID[MAXFIELDS]; +} or; + +typedef struct ou +{ + int argc; + unsigned long ObjectID[MAXFIELDS]; +} ou; + + +/** + ** oc definitions + **/ +typedef enum { + OCDT_NONE, + OCDT_OBJECT_CREATE, + OCDT_OBJECT_FACING, + OCDT_EDIT_BOT_CREATE, + OCDT_EDIT_ROOM_CREATE, + OCDT_EDIT_EXIT_CREATE, + OCDT_EDIT_OBJECT_CREATE, + OCDT_EDIT_OBJECT_FACING, + OCDT_EDIT_PORTAL_CREATE, + OCDT_EDIT_ROOM_DRAWING_INFO, + OCDT_EDIT_ROOM_PERSISTENT_SUBSCRIBER_LIST, + OCDT_EDIT_ROOM_DESCRIPTION, + OCDT_EDIT_ROOM_NAME + +} oc_datatype; + +/* first field of server-specific data is always datatype */ +typedef struct oc_data +{ + oc_datatype datatype; + char * raw_data; + void * parsed_data; +} oc_data; + +/* if objectID == 0, a new object is being created and server_data + * should be of type oc_datatype_object_create */ +typedef struct oc +{ + ObjectID objectID; + unsigned long handle; + unsigned long duration; + oc_data * data; /* server-specific data. See oc_data.h */ +} oc; +/** + ** end oc definitions + **/ + +GPROT_ERR ProtocolInit(GraphicsProtocol * gprot); +void ProtocolCleanup(GraphicsProtocol * gprot); +GPROT_ERR dispatch_message(ObjectID player, gprot_role role, void * context, + GraphicsProtocol * gprot, char * msgid, int argc, char ** argv); +GPROT_ERR handle_graphics_input(ObjectID player, gprot_role role, void * context, + GraphicsProtocol * gprot, const char * input); + +GPROT_ERR parse_into_fields(char *input, int *argc, char *argv[], int nfields); + +GPROT_ERR handle_pn(ObjectID player, gprot_role role, void * context, + int argc, char ** argv); +GPROT_ERR handle_osm(ObjectID player, gprot_role role, void * context, + int argc, char ** argv); +GPROT_ERR handle_oku(ObjectID player, gprot_role role, void * context, + int argc, char ** argv); +GPROT_ERR handle_oi(ObjectID player, gprot_role role, void * context, + int argc, char ** argv); +GPROT_ERR handle_ot(ObjectID player, gprot_role role, void * context, + int argc, char ** argv); +GPROT_ERR handle_od(ObjectID player, gprot_role role, void * context, + int argc, char ** argv); +GPROT_ERR handle_oc(ObjectID player, gprot_role role, void * context, + int argc, char ** argv); +GPROT_ERR handle_st(ObjectID player, gprot_role role, void * context, + int argc, char ** argv); +GPROT_ERR handle_or(ObjectID player, gprot_role role, void * context, + int argc, char ** argv); +GPROT_ERR handle_ou(ObjectID player, gprot_role role, void * context, + int argc, char ** argv); + +char * make_pn_string(pn * pn); +char * make_osm_string(osm * osm); +char * make_oku_string(oku * oku); +char * make_oi_string(oi * oi); +char * make_ot_string(ot * ot); +char * make_od_string(od * od); +char * make_oc_string(oc * oc); +char * make_st_string(); +char * make_or_string(or * or); +char * make_ou_string(ou * ou); + +#ifdef GPROT_DEBUG +char * make_pn_debug_string(pn * pn); +char * make_osm_debug_string(osm * osm); +char * make_oku_debug_string(oku * oku); +char * make_oi_debug_string(oi * oi); +char * make_ot_debug_string(ot * ot); +char * make_od_debug_string(od * od); +char * make_oc_debug_string(oc * oc); +char * make_st_debug_string(); +char * make_or_debug_string(or * or); +char * make_ou_debug_string(ou * ou); +#endif + +GPROT_ERR ClientPN(ObjectID player, struct pn * pn, void * context); +GPROT_ERR ClientOSM(ObjectID player, struct osm * osm, void * context); +GPROT_ERR ClientOKU(ObjectID player, struct oku * oku, void * context); +GPROT_ERR ClientOI(ObjectID player, struct oi * oi, void * context); +GPROT_ERR ClientOT(ObjectID player, struct ot * ot, void * context); +GPROT_ERR ClientOD(ObjectID player, struct od * od, void * context); +GPROT_ERR ClientOC(ObjectID player, struct oc * oc, void * context); +GPROT_ERR ClientST(ObjectID player, void * context); +GPROT_ERR ClientOR(ObjectID player, struct or * or, void * context); +GPROT_ERR ClientOU(ObjectID player, struct ou * ou, void * context); + +GPROT_ERR ServerPN(struct pn * pn, void * context); +GPROT_ERR ServerOSM(struct osm * osm, void * context); +GPROT_ERR ServerOKU(struct oku * oku, void * context); +GPROT_ERR ServerOI(struct oi * oi, void * context); +GPROT_ERR ServerOT(struct ot * ot, void * context); +GPROT_ERR ServerOD(struct od * od, void * context); +GPROT_ERR ServerOC(struct oc * oc, void * context); +GPROT_ERR ServerST(void * context); +GPROT_ERR ServerOR(struct or * or, void * context); +GPROT_ERR ServerOU(struct ou * ou, void * context); diff -U 2 -b -P -x config.h -x y.tab.c -x y.tab.h MOO-1.8.0r5/gprot_lambda.c ehMOO.0.93.r5.codeonly/gprot_lambda.c --- MOO-1.8.0r5/gprot_lambda.c Wed Dec 31 18:00:00 1969 +++ ehMOO.0.93.r5.codeonly/gprot_lambda.c Sat Feb 3 00:52:22 2001 @@ -0,0 +1,1292 @@ +/********************************************************************** + ** eh Graphics Protocol implementation for ehMOO + ** Copyright (c) 1995 by Tom Zanussi and Steve Albrecht +**********************************************************************/ + +/* + * eh Change History + * + * Revision 0.04 1996/03/31 11:13:38 trz + * Changed to work with 1.8.0 Lambda. + * + * Revision 0.05.1 {1} 1997/03/28 SWA + * add okum duration field + * + */ + +#include +#include +#include "structures.h" +#include "list.h" +#include "execute.h" +#include "utils.h" +#include "storage.h" +#include "parse_cmd.h" +#include "tasks.h" +#include "functions.h" +#include "server.h" +#include "gprot_lambda.h" +#include "oc_data.h" + +/* + This variable defines the display servers this moo supports. + It should probably be a property on SYSTEM_OBJECT since the drawing + info in the core is really what defines which server types are + supported, but until we support more server types, we'll just do + it here. +*/ +unsigned long supported_gprot_servers = SERVER_DEFAULT | SERVER_EHWT; + +/********************************************************************** + ** This module contains the eh Graphics Protocol code specific to the + ** ehMOO client. +**********************************************************************/ + +/********************************************************************** + ** Message handling functions +**********************************************************************/ + +/* + ** ClientPN() + ** + ** ehMOO handler for pn messages. +*/ + +GPROT_ERR ClientPN(ObjectID player, struct pn * pn, void * context) +{ + Objid graphics_player = (Objid)context; + + if(pn->argc < 2) + return GE_SERVER_ERR; + + return handle_negotiation(graphics_player, + pn->protocol_version, pn->server_type); + +} + +/* + ** ClientOSM() + ** + ** ehMOO handler for osm messages. Called from handle_osm() + ** Calls in-db verb add_subscriber(). +*/ + +GPROT_ERR ClientOSM(ObjectID player, struct osm * osm, void * context) +{ + int n=1; + enum outcome e; + Var args, result; + Objid object; + Objid graphics_player = (Objid)context; + + if((!negotiation_complete(graphics_player)) || + (negotiated_version(graphics_player) < (unsigned long)GPROTV_Minimal)) { + /* we haven't finished protocol negotiation, or version too low */ + return GE_NONE; + } + + if(osm->objectID == 1) + return GE_SERVER_ERR; /* can't subscribe to self */ + else + object = osm->objectID; + + if(osm->argc <= 1) + return GE_SERVER_ERR; + + args = new_list(osm->argc); /* not argc-1, need to add 1 for graphics_player */ + + args.v.list[n].type = TYPE_OBJ; + args.v.list[n++].v.obj = graphics_player; + + if(osm->argc > 1) { + args.v.list[n].type = TYPE_INT; + args.v.list[n++].v.num = osm->event_mask; + } + + if(got_initial_subscription(graphics_player)) { + e = run_server_task(player, object, "handle_osm", args, "", &result); + } else { + e = run_server_task(player, object, "initial_subscription", args, "", &result); + initial_subscription_gotten(graphics_player); + } + + if(e != OUTCOME_DONE) { + return GE_CLIENT_ERR; + } + + return GE_NONE; +} + +/* + ** ClientOKU() + ** + ** ehMOO handler for oku messages. Called from handle_okum() + ** Calls in-db verb gmove(). +*/ +GPROT_ERR ClientOKU(ObjectID player, struct oku * oku, void * context) +{ + int i, n=1; + enum outcome e; + Var args, result; + Objid object; + Objid graphics_player = (Objid)context; + + if((!negotiation_complete(graphics_player)) || + (negotiated_version(graphics_player) < (unsigned long)GPROTV_Minimal)) { + /* we haven't finished protocol negotiation, or version too low */ + return GE_NONE; + } + + if(oku->objectID == 1) + object = player; /* avatar movement */ + else + object = oku->objectID; + + if(oku->argc <= 1) + return GE_SERVER_ERR; + + args = new_list(oku->argc-1); + + args.v.list[n].type = TYPE_INT; + args.v.list[n++].v.num = oku->timestamp; + + if(oku->argc > 2) { /* else solicitation */ + for(i=0;i<3;i++) { + args.v.list[n].type = TYPE_INT; + args.v.list[n++].v.num = oku->position[i]; + } + } else { /* solicitation */ + e = run_server_task(player, object, "send_current_state", + args, "", &result); + return GE_NONE; + } + + if(oku->argc > 5) { + for(i=0;i<3;i++) { + args.v.list[n].type = TYPE_INT; + args.v.list[n++].v.num = oku->facing[i]; + } + } + + if (oku->argc > 8) { + for(i=0;i<3;i++) { + args.v.list[n].type = TYPE_INT; + args.v.list[n++].v.num = oku->velocity[i]; + } + } + + if (oku->argc > 11) { /* {1} */ + args.v.list[n].type = TYPE_INT; + args.v.list[n++].v.num = oku->duration; + } + + if (oku->argc > 12) { + for(i=0;i<3;i++) { + args.v.list[n].type = TYPE_INT; + args.v.list[n++].v.num = oku->angular_velocity[i]; + } + } + + if (oku->argc > 15) { /* {1} */ + args.v.list[n].type = TYPE_INT; + args.v.list[n++].v.num = oku->angular_duration; + } + + /* if this is not the first graphical connection, we don't want to send initial position */ + /* also, text players now have graphics positions, so we need to yank the graphical connection there */ + if((get_gconn_count(player) > 1) || text_player_connected(player)) { /* more than one graphical connection? */ + if(!got_initial_oku(graphics_player)) { /* is this the first oku for this gplayer? */ + initial_oku_gotten(graphics_player); /* only ignore the first one */ + e = OUTCOME_DONE; /* set so we don't trigger an error */ + } else { + e = run_server_task(player, object, "gmove", args, "", &result); + } + } else { /* we're currently the only graphics connection */ + e = run_server_task(player, object, "gmove", args, "", &result); + initial_oku_gotten(graphics_player); + } + + if(e != OUTCOME_DONE) { + return GE_CLIENT_ERR; + } + + return GE_NONE; +} + +/* + ** ClientOI() + ** + ** ehMOO handler for oi messages. Called from handle_oi() + ** Calls in-db verb gforce(). +*/ +GPROT_ERR ClientOI(ObjectID player, struct oi * oi, void * context) +{ + int i, n=1; + enum outcome e; + Var args, result; + Objid object; + Objid graphics_player = (Objid)context; + + if((!negotiation_complete(graphics_player)) || + (negotiated_version(graphics_player) < (unsigned long)GPROTV_Minimal)) { + /* we haven't finished protocol negotiation, or version too low */ + return GE_NONE; + } + + if(oi->objectID == 1) + object = player; /* avatar movement */ + else + object = oi->objectID; + + if(oi->argc <= 1) + return GE_SERVER_ERR; + + args = new_list(oi->argc); /* not argc-1, need to add 1 for graphics_player */ + + args.v.list[n].type = TYPE_INT; + args.v.list[n++].v.num = oi->timestamp; + + args.v.list[n].type = TYPE_OBJ; + args.v.list[n++].v.obj = graphics_player; + + for(i=0;i<3;i++) { + args.v.list[n].type = TYPE_INT; + args.v.list[n++].v.num = oi->force[i]; + } + + if(oi->argc > 5) { + args.v.list[n].type = TYPE_INT; + args.v.list[n++].v.num = oi->duration; + } + + e = run_server_task(player, object, "gforce", args, "", &result); + + if(e != OUTCOME_DONE) { + return GE_CLIENT_ERR; + } + + return GE_NONE; +} + +/* + ** ClientOT() + ** + ** ehMOO handler for ot messages. Called from handle_ot() + ** Calls in-db verb gtorque(). +*/ +GPROT_ERR ClientOT(ObjectID player, struct ot * ot, void * context) +{ + int i, n=1; + enum outcome e; + Var args, result; + Objid object; + Objid graphics_player = (Objid)context; + + if((!negotiation_complete(graphics_player)) || + (negotiated_version(graphics_player) < (unsigned long)GPROTV_Minimal)) { + /* we haven't finished protocol negotiation, or version too low */ + return GE_NONE; + } + + if(ot->objectID == 1) + object = player; /* avatar movement */ + else + object = ot->objectID; + + if(ot->argc <= 1) + return GE_SERVER_ERR; + + args = new_list(ot->argc); /* not argc-1, need to add 1 for graphics_player */ + + args.v.list[n].type = TYPE_INT; + args.v.list[n++].v.num = ot->timestamp; + + args.v.list[n].type = TYPE_OBJ; + args.v.list[n++].v.obj = graphics_player; + + for(i=0;i<3;i++) { + args.v.list[n].type = TYPE_INT; + args.v.list[n++].v.num = ot->torque[i]; + } + + if(ot->argc > 5) { + args.v.list[n].type = TYPE_INT; + args.v.list[n++].v.num = ot->duration; + } + + e = run_server_task(player, object, "gtorque", args, "", &result); + + if(e != OUTCOME_DONE) { + return GE_CLIENT_ERR; + } + + return GE_NONE; +} + +/* + ** ClientOD() + ** + ** ehMOO handler for od messages. Called from handle_od() + ** Implement for editor. +*/ +GPROT_ERR ClientOD(ObjectID player, struct od * od, void * context) +{ + int n=1; + enum outcome e; + Var args, result; + Objid graphics_player = (Objid)context; + + if((!negotiation_complete(graphics_player)) || + (negotiated_version(graphics_player) < (unsigned long)GPROTV_Minimal)) { + /* we haven't finished protocol negotiation, or version too low */ + return GE_NONE; + } + + if(od->objectID < 100) { + char buf[512]; + sprintf(buf, "You tried to recycle object %lu. Use text mode to recycle objects less than %d.", + od->objectID, MIN_GPROT_RECYCLE_ID); + notify(player, buf); + return GE_SERVER_ERR; + } + + args = new_list(1); + + args.v.list[n].type = TYPE_OBJ; + args.v.list[n++].v.obj = od->objectID; + + e = run_server_task(player, player, "recycle_object", args, "", &result); + + if(e != OUTCOME_DONE) { + return GE_CLIENT_ERR; + } + + return GE_NONE; +} + +/* + * ClientOC() support functions + */ + +static Objid oc_create_robot(Objid player, Objid graphics_player, oc_bot_create_params * create_params) +{ + int n=1; + enum outcome e; + Var args, result; + Objid robot_id = NOTHING; + + args = new_list(3); + + args.v.list[n].type = TYPE_STR; + args.v.list[n++].v.str = str_dup(create_params->object_name); + args.v.list[n].type = TYPE_STR; + args.v.list[n++].v.str = str_dup(create_params->object_password); + args.v.list[n].type = TYPE_OBJ; + args.v.list[n++].v.obj = graphics_player; + + e = run_server_task(player, SYSTEM_OBJECT, "create_robot", args, "", &result); + + if(e != OUTCOME_DONE) { + return NOTHING; + } + + if(result.type == TYPE_OBJ && is_user(result.v.obj)) { + robot_id = result.v.obj; + } + + return robot_id; +} + + +static Objid oc_create_object(Objid player, oc_obj_create_params * create_params) +{ + int n=1; + enum outcome e; + Var args, result; + Objid new_object_id = NOTHING; + + args = new_list(3); + + args.v.list[n].type = TYPE_STR; + args.v.list[n++].v.str = str_dup(create_params->superclass); + + args.v.list[n].type = TYPE_STR; + args.v.list[n++].v.str = str_dup("called"); + + args.v.list[n].type = TYPE_STR; + args.v.list[n++].v.str = str_dup(create_params->object_name); + + e = run_server_task(player, player, "create_object", args, "", &result); + + if(e != OUTCOME_DONE) { + return NOTHING; + } + + if(result.type == TYPE_OBJ) { + new_object_id = result.v.obj; + } + + return new_object_id; +} + +static Objid oc_create_room(Objid player, oc_room_create_params * create_params) +{ + int n=1; + enum outcome e; + Var args, result; + Objid new_object_id = NOTHING; + + args = new_list(1); + + args.v.list[n].type = TYPE_STR; + args.v.list[n++].v.str = str_dup(create_params->object_name); + + e = run_server_task(player, player, "create_room", args, "", &result); + + if(e != OUTCOME_DONE) { + return NOTHING; + } + + if(result.type == TYPE_OBJ) { + new_object_id = result.v.obj; + } + + return new_object_id; +} + +static Objid oc_create_exit(Objid player, oc_exit_create_params * create_params) +{ + int n=1; + enum outcome e; + Var args, result; + Objid new_object_id = NOTHING; + + args = new_list(3); + + args.v.list[n].type = TYPE_STR; + args.v.list[n++].v.str = str_dup(create_params->object_name); + args.v.list[n].type = TYPE_OBJ; + args.v.list[n++].v.obj = create_params->source_room; + args.v.list[n].type = TYPE_OBJ; + args.v.list[n++].v.obj = create_params->dest_room; + + e = run_server_task(player, player, "create_exit", args, "", &result); + + if(e != OUTCOME_DONE) { + return NOTHING; + } + + if(result.type == TYPE_OBJ) { + new_object_id = result.v.obj; + } + + return new_object_id; +} + +static Objid oc_create_portal(Objid player, oc_portal_create_params * create_params) +{ + int n=1; + enum outcome e; + Var args, result; + Objid new_object_id = NOTHING; + + args = new_list(4); + + args.v.list[n].type = TYPE_STR; + args.v.list[n++].v.str = str_dup(create_params->to_dest_spec); + args.v.list[n].type = TYPE_STR; + args.v.list[n++].v.str = str_dup(create_params->from_dest_spec); + args.v.list[n].type = TYPE_OBJ; + args.v.list[n++].v.obj = create_params->source_room; + args.v.list[n].type = TYPE_OBJ; + args.v.list[n++].v.obj = create_params->dest_room; + + e = run_server_task(player, player, "create_ehportal", args, "", &result); + + if(e != OUTCOME_DONE) { + return NOTHING; + } + + if(result.type == TYPE_OBJ) { + new_object_id = result.v.obj; + } + + return new_object_id; +} + +/** + ** called from ClientOC. raw_data exists and must be parsed for + ** handling functions first by parse_oc_data + **/ +static Objid oc_create(Objid player, Objid graphics_player, oc * oc) +{ + GPROT_ERR err; + Objid new_object = NOTHING; + + err = parse_oc_data(oc); /* parse raw data into create struct */ + if(err != GE_NONE) { + return NOTHING; + } + + switch(oc->data->datatype) { + + case OCDT_EDIT_BOT_CREATE: + new_object = oc_create_robot(player, graphics_player, + (oc_bot_create_params *)oc->data->parsed_data); + break; + + case OCDT_EDIT_ROOM_CREATE: + new_object = oc_create_room(player, + (oc_room_create_params *)oc->data->parsed_data); + break; + + case OCDT_EDIT_EXIT_CREATE: + new_object = oc_create_exit(player, + (oc_exit_create_params *)oc->data->parsed_data); + break; + + case OCDT_EDIT_OBJECT_CREATE: + new_object = oc_create_object(player, + (oc_obj_create_params *)oc->data->parsed_data); + break; + + case OCDT_EDIT_PORTAL_CREATE: + new_object = oc_create_portal(player, + (oc_portal_create_params *)oc->data->parsed_data); + break; + + default: + new_object = NOTHING; + break; + } + + return new_object; +} + +/* take the url from the edit_facing msg, copy it to web archive, + * add the new name/angle pair to the object, or replace it if that + * angle already exists. Also update last modified time for object + */ +static GPROT_ERR oc_edit_facing(Objid player, oc * oc) +{ + oc_facing_edit_params * facing_params; + char dih_str[1024]; + char hack_string[1024]; + int n=1; + enum outcome e; + Var args, result; + Objid object; + + facing_params = (oc_facing_edit_params *)oc->data->parsed_data; + if(!facing_params->url) + return GE_SERVER_ERR; + + sprintf(dih_str, "%s", facing_params->url); + + if(oc->objectID == 1) + object = player; /* avatar */ + else + object = oc->objectID; + + args = new_list(2); + + args.v.list[n].type = TYPE_INT; + args.v.list[n++].v.num = facing_params->angle; + + args.v.list[n].type = TYPE_STR; + args.v.list[n++].v.str = str_dup(dih_str); + + e = run_server_task(player, object, "edit_facing", args, "", &result); + + if(e != OUTCOME_DONE) { + return GE_CLIENT_ERR; + } + + /* change url for confirm */ + /* need to make the return string different to signify confirm, + * but nothing is changed in the struct, so prepend some text */ + sprintf(hack_string, "added facing: %s", dih_str); + free(facing_params->url); + facing_params->url = strdup(hack_string); + + return GE_NONE; +} + +static GPROT_ERR oc_edit_persistent_subscribers(Objid player, oc * oc) +{ + oc_room_edit_persistent_subscriber_params * subscriber_params; + char subscriber_list_str[1024]; + char hack_string[1024]; + int n=1; + enum outcome e; + Var args, result; + + subscriber_params = (oc_room_edit_persistent_subscriber_params *)oc->data->parsed_data; + if(!subscriber_params->persistent_subscriber_list) + return GE_SERVER_ERR; + + sprintf(subscriber_list_str, "%s", subscriber_params->persistent_subscriber_list); + + args = new_list(2); + + args.v.list[n].type = TYPE_OBJ; + args.v.list[n++].v.obj = oc->objectID; + args.v.list[n].type = TYPE_STR; + args.v.list[n++].v.str = str_dup(subscriber_list_str); + + e = run_server_task(player, player, "set_persistent_subscribers", args, "", &result); + + if(e != OUTCOME_DONE) { + return GE_CLIENT_ERR; + } + + /* change for confirm */ + /* need to make the return string different to signify confirm, + * but nothing is changed in the struct, so prepend some text */ + sprintf(hack_string, "set persistent subscribers: %s", subscriber_list_str); + free(subscriber_params->persistent_subscriber_list); + subscriber_params->persistent_subscriber_list = strdup(hack_string); + + return GE_NONE; +} + +static GPROT_ERR oc_edit_room_drawing_info(Objid player, oc * oc) +{ + oc_room_edit_drawing_info_params * di_params; + char di_str[MAX_GPROT_MSGLEN]; + char hack_string[MAX_GPROT_MSGLEN]; + int n=1; + enum outcome e; + Var args, result; + + di_params = (oc_room_edit_drawing_info_params *)oc->data->parsed_data; + if(!di_params->drawing_info) + return GE_SERVER_ERR; + + sprintf(di_str, "%s", di_params->drawing_info); + + args = new_list(2); + + args.v.list[n].type = TYPE_OBJ; + args.v.list[n++].v.obj = oc->objectID; + args.v.list[n].type = TYPE_STR; + args.v.list[n++].v.str = str_dup(di_str); + + e = run_server_task(player, player, "set_worldlines", args, "", &result); + + if(e != OUTCOME_DONE) { + return GE_CLIENT_ERR; + } + + /* change for confirm */ + /* need to make the return string different to signify confirm, + * but nothing is changed in the struct, so prepend some text */ + sprintf(hack_string, "set drawing info: %s", di_str); + free(di_params->drawing_info); + di_params->drawing_info = strdup(hack_string); + + return GE_NONE; +} + +static GPROT_ERR oc_edit_room_description(Objid player, oc * oc) +{ + oc_room_edit_description_params * desc_params; + char desc_str[MAX_GPROT_MSGLEN]; + char hack_string[MAX_GPROT_MSGLEN]; + int n=1; + enum outcome e; + Var args, result; + + desc_params = (oc_room_edit_description_params *)oc->data->parsed_data; + if(!desc_params->description) + return GE_SERVER_ERR; + + sprintf(desc_str, "%s", desc_params->description); + + args = new_list(2); + + args.v.list[n].type = TYPE_OBJ; + args.v.list[n++].v.obj = oc->objectID; + args.v.list[n].type = TYPE_STR; + args.v.list[n++].v.str = str_dup(desc_str); + + e = run_server_task(player, player, "edit_set_description", args, "", &result); + + if(e != OUTCOME_DONE) { + return GE_CLIENT_ERR; + } + + /* change for confirm */ + /* need to make the return string different to signify confirm, + * but nothing is changed in the struct, so prepend some text */ + sprintf(hack_string, "set description: %s", desc_str); + free(desc_params->description); + desc_params->description = strdup(hack_string); + + return GE_NONE; +} + +static GPROT_ERR oc_edit_room_name(Objid player, oc * oc) +{ + oc_room_edit_name_params * name_params; + char name_str[MAX_GPROT_MSGLEN]; + char hack_string[MAX_GPROT_MSGLEN]; + int n=1; + enum outcome e; + Var args, result; + + name_params = (oc_room_edit_name_params *)oc->data->parsed_data; + if(!name_params->name) + return GE_SERVER_ERR; + + sprintf(name_str, "%s", name_params->name); + + args = new_list(2); + + args.v.list[n].type = TYPE_OBJ; + args.v.list[n++].v.obj = oc->objectID; + args.v.list[n].type = TYPE_STR; + args.v.list[n++].v.str = str_dup(name_str); + + e = run_server_task(player, player, "edit_set_name", args, "", &result); + + if(e != OUTCOME_DONE) { + return GE_CLIENT_ERR; + } + + /* change for confirm */ + /* need to make the return string different to signify confirm, + * but nothing is changed in the struct, so prepend some text */ + sprintf(hack_string, "set name: %s", name_str); + free(name_params->name); + name_params->name = strdup(hack_string); + + return GE_NONE; +} + + +/** + ** called from ClientOC. raw_data exists and must be parsed for + ** handling functions first by parse_oc_data + **/ +static GPROT_ERR oc_edit(Objid player, oc * oc) +{ + GPROT_ERR err; + + err = parse_oc_data(oc); /* parse raw data into create struct */ + if(err != GE_NONE) { + return err; + } + + switch(oc->data->datatype) { + + case OCDT_EDIT_OBJECT_FACING: + err = oc_edit_facing(player, oc); + break; + + case OCDT_EDIT_ROOM_DRAWING_INFO: + err = oc_edit_room_drawing_info(player, oc); + break; + + case OCDT_EDIT_ROOM_PERSISTENT_SUBSCRIBER_LIST: + err = oc_edit_persistent_subscribers(player, oc); + break; + + case OCDT_EDIT_ROOM_DESCRIPTION: + err = oc_edit_room_description(player, oc); + break; + + case OCDT_EDIT_ROOM_NAME: + err = oc_edit_room_name(player, oc); + break; + + default: + err = GE_SERVER_ERR; + break; + } + + return err; +} + + +/* confirm that an object creating oc succeeded */ +static void oc_create_confirm(Objid player, oc * oc, Objid new_object) +{ + char * oc_string; + oc->handle = 0; + oc->objectID = new_object; + + oc_string = make_oc_string(oc); + gnotify(player, oc_string); + free(oc_string); +} + +/* confirm that an object editing oc succeeded */ +/* The relevant fields of the param struct should have been changed + * by the editing function e.g the url field of the facing params + * should reflect the new client assigned url */ +static void oc_edit_confirm(Objid player, oc * oc) +{ + char * oc_string; + + oc_string = make_oc_string(oc); + gnotify(player, oc_string); + free(oc_string); +} + +/* deny an oc request */ +static void oc_deny(Objid player, oc * oc) +{ + char * oc_string = make_oc_string(oc); + gnotify(player, oc_string); + free(oc_string); +} + + + /* + ** ClientOC() + ** + ** ehMOO handler for oc messages. Called from handle_oc() + ** Implement for editor. +*/ + +GPROT_ERR ClientOC(ObjectID player, oc * oc, void * context) +{ + GPROT_ERR rc = GE_NONE; + Objid new_object = NOTHING; + Objid graphics_player = (Objid)context; + + if((!negotiation_complete(graphics_player)) || + (negotiated_version(graphics_player) < (unsigned long)GPROTV_Minimal)) { + /* we haven't finished protocol negotiation, or version too low */ + return GE_NONE; + } + + if(oc->objectID == 0) { + /* new object creation requested */ + new_object = oc_create(player, graphics_player, oc); + if(new_object == NOTHING) { + rc = GE_SERVER_ERR; + notify(player, "Badly formed creation request."); + } + else + oc_create_confirm(player, oc, new_object); + } + else { + /* editing an already existing object */ + rc = oc_edit(player, oc); + if(rc != GE_NONE) { + notify(player, "Badly formed edit request."); + } + else { + oc_edit_confirm(player, oc); + } + } + + if(rc != GE_NONE) + oc_deny(player, oc); + + return rc; +} + + /* + ** ClientST() + ** + ** ehMOO handler for st messages. Called from handle_st() +*/ + +GPROT_ERR ClientST(ObjectID player, void * context) +{ + Objid graphics_player = (Objid)context; + + if((!negotiation_complete(graphics_player)) || + (negotiated_version(graphics_player) < (unsigned long)GPROTV_Minimal)) { + /* we haven't finished protocol negotiation, or version too low */ + return GE_NONE; + } + + boot_graphics_player(graphics_player); + + return GE_NONE; +} + +/* + ** ClientOR() + ** + ** ehMOO handler for or messages. +*/ + +GPROT_ERR ClientOR(ObjectID player, or * or, void * context) +{ + Objid graphics_player = (Objid)context; + + if((!negotiation_complete(graphics_player)) || + (negotiated_version(graphics_player) < (unsigned long)GPROTV_Minimal)) { + /* we haven't finished protocol negotiation, or version too low */ + return GE_NONE; + } + + return register_gprot_objects(player, or); +} + +/* + ** ClientOU() + ** + ** ehMOO handler for ou messages. +*/ + +GPROT_ERR ClientOU(ObjectID player, ou * ou, void * context) +{ + Objid graphics_player = (Objid)context; + + if((!negotiation_complete(graphics_player)) || + (negotiated_version(graphics_player) < (unsigned long)GPROTV_Minimal)) { + /* we haven't finished protocol negotiation, or version too low */ + return GE_NONE; + } + + return unregister_gprot_objects(player, ou); +} + +/* Server stubs */ + +/* + ** ServerPN() + ** + ** stub function. Should never be called. +*/ +GPROT_ERR ServerPN(struct pn * pn, void * context) +{ + return GE_CLIENT_ERR; +} + +/* + ** ServerOSM() + ** + ** stub function. Should never be called. +*/ +GPROT_ERR ServerOSM(struct osm * osm, void * context) +{ + return GE_CLIENT_ERR; +} + +/* + ** ServerOKU() + ** + ** stub function. Should never be called. +*/ +GPROT_ERR ServerOKU(struct oku * oku, void * context) +{ + return GE_CLIENT_ERR; +} + +/* + ** ServerOI() + ** + ** stub function. Should never be called. +*/ +GPROT_ERR ServerOI(struct oi * oi, void * context) +{ + return GE_CLIENT_ERR; +} + +/* + ** ServerOT() + ** + ** stub function. Should never be called. +*/ +GPROT_ERR ServerOT(struct ot * ot, void * context) +{ + return GE_CLIENT_ERR; +} + +/* + ** ServerOD() + ** + ** stub function. Should never be called. +*/ +GPROT_ERR ServerOD(struct od * od, void * context) +{ + return GE_CLIENT_ERR; +} + +/* + ** ServerOC() + ** + ** stub function. Should never be called. +*/ +GPROT_ERR ServerOC(struct oc * oc, void * context) +{ + return GE_CLIENT_ERR; +} + +/* + ** ServerST() + ** + ** stub function. Should never be called. +*/ +GPROT_ERR ServerST(void * context) +{ + return GE_CLIENT_ERR; +} + +/* + ** ServerOR() + ** + ** stub function. Should never be called. +*/ +GPROT_ERR ServerOR(struct or * or, void * context) +{ + return GE_CLIENT_ERR; +} + +/* + ** ServerOU() + ** + ** stub function. Should never be called. +*/ +GPROT_ERR ServerOU(struct ou * ou, void * context) +{ + return GE_CLIENT_ERR; +} + +/********************************************************************** + ** Initialization and utility functions +**********************************************************************/ + +/* + ** bf_make_oku_string() + ** + ** Function to be registered as a builtin. Takes a MOO arglist and + ** formats it into MOO string variable via gprot's make_oku_string(). + ** For making and sending eh Graphics Protocol events in-db. +*/ +static package +bf_make_oku_string(Var arglist, Byte next, void *vdata, Objid progr) +{ + int i, n=1; + oku oku; + Var r; + char * oku_string; + + oku.argc = arglist.v.list[2].v.list[0].v.num + 1; + + oku.objectID = arglist.v.list[1].v.obj; + oku.timestamp = arglist.v.list[2].v.list[n++].v.num; + + if(oku.argc >= 5) { + for(i=0;i<3;i++) { + oku.position[i] = arglist.v.list[2].v.list[n++].v.num; + } + } + + if(oku.argc >= 8) { + for(i=0;i<3;i++) { + oku.facing[i] = arglist.v.list[2].v.list[n++].v.num; + } + } + + if(oku.argc >= 11) { + for(i=0;i<3;i++) { + oku.velocity[i] = arglist.v.list[2].v.list[n++].v.num; + } + } + + if(oku.argc >= 12) { /* {1} */ + oku.duration = arglist.v.list[2].v.list[n++].v.num; + } + + if(oku.argc >= 15) { + for(i=0;i<3;i++) { + oku.angular_velocity[i] = arglist.v.list[2].v.list[n++].v.num; + } + } + + if(oku.argc >= 16) { /* {1} */ + oku.angular_duration = arglist.v.list[2].v.list[n++].v.num; + } + + oku_string = make_oku_string(&oku); + r.type = TYPE_STR; + r.v.str = str_dup(oku_string); + free(oku_string); + + free_var(arglist); + return make_var_pack(r); +} + +/* + ** bf_make_oi_string() + ** + ** Function to be registered as a builtin. Takes a MOO arglist and + ** formats it into MOO string variable via gprot's make_oi_string(). + ** For making and sending eh Graphics Protocol events in-db. +*/ +static package +bf_make_oi_string(Var arglist, Byte next, void *vdata, Objid progr) +{ + int i, n=1; + oi oi; + Var r; + char * oi_string; + +/* oi.argc = arglist.v.list[2].v.list[0].v.num + 1; */ + oi.argc = arglist.v.list[2].v.list[0].v.num; /* don't add 1, need to ignore graphics_player */ + + oi.objectID = arglist.v.list[1].v.obj; + oi.timestamp = arglist.v.list[2].v.list[n++].v.num; + + n++; /* skip graphics_player */ + + for(i=0;i<3;i++) { + oi.force[i] = arglist.v.list[2].v.list[n++].v.num; + } + + if(oi.argc >= 6) { + oi.duration = arglist.v.list[2].v.list[n++].v.num; + } + + oi_string = make_oi_string(&oi); + r.type = TYPE_STR; + r.v.str = str_dup(oi_string); + free(oi_string); + + free_var(arglist); + return make_var_pack(r); +} + +/* + ** bf_make_ot_string() + ** + ** Function to be registered as a builtin. Takes a MOO arglist and + ** formats it into MOO string variable via gprot's make_ot_string(). + ** For making and sending eh Graphics Protocol events in-db. +*/ +static package +bf_make_ot_string(Var arglist, Byte next, void *vdata, Objid progr) +{ + int i, n=1; + ot ot; + Var r; + char * ot_string; + + ot.argc = arglist.v.list[2].v.list[0].v.num; /* don't add 1, need to ignore graphics_player */ + + ot.objectID = arglist.v.list[1].v.obj; + ot.timestamp = arglist.v.list[2].v.list[n++].v.num; + + n++; /* skip graphics_player */ + + for(i=0;i<3;i++) { + ot.torque[i] = arglist.v.list[2].v.list[n++].v.num; + } + + if(ot.argc >= 6) { + ot.duration = arglist.v.list[2].v.list[n++].v.num; + } + + ot_string = make_ot_string(&ot); + r.type = TYPE_STR; + r.v.str = str_dup(ot_string); + free(ot_string); + + free_var(arglist); + return make_var_pack(r); +} + +/* + ** bf_make_od_string() + ** + ** Function to be registered as a builtin. Takes a MOO arglist and + ** formats it into MOO string variable via gprot's make_od_string(). + ** For making and sending eh Graphics Protocol events in-db. +*/ +static package +bf_make_od_string(Var arglist, Byte next, void *vdata, Objid progr) +{ + od od; + Var r; + char * od_string; + + od.argc = arglist.v.list[2].v.list[0].v.num + 1; + + od.objectID = arglist.v.list[1].v.obj; + + od_string = make_od_string(&od); + r.type = TYPE_STR; + r.v.str = str_dup(od_string); + free(od_string); + + free_var(arglist); + return make_var_pack(r); +} + +/* + ** bf_make_object_create_string() + ** + ** Function to be registered as a builtin. + ** Creates an oc object create event from obj, string to send to client via + ** gprot's make_oc_string(). + ** For making and sending eh Graphics Protocol events in-db. +*/ +static package +bf_make_object_create_string(Var arglist, Byte next, void *vdata, Objid progr) +{ + oc * oc; + Var r; + char * oc_string; + oc_objfile_params * params; + + oc = new_oc(OCDT_OBJECT_CREATE); + + oc->objectID = arglist.v.list[1].v.obj; + oc->handle = 0; + oc->duration = 0; + params = (oc_objfile_params *)oc->data->parsed_data; + params->objtype = strdup(arglist.v.list[2].v.str); + params->objfile = strdup(arglist.v.list[3].v.str); + + oc_string = make_oc_string(oc); + delete_oc(oc); + + r.type = TYPE_STR; + r.v.str = str_dup(oc_string); + free(oc_string); + + free_var(arglist); + return make_var_pack(r); +} + +/* + ** eh Graphics Protocol initialization. Called from main(). +*/ + +GraphicsProtocol gprot; + +GPROT_ERR init_eh_graphics_protocol() +{ + return ProtocolInit(&gprot); +} + +/* + ** register_gprot() + ** + ** Register the builtin Graphics Protocol string handling functions. +*/ +void register_gprot(void) +{ + (void) register_function("make_oku_string", 2, 2, bf_make_oku_string, + TYPE_OBJ, TYPE_LIST); + (void) register_function("make_oi_string", 2, 2, bf_make_oi_string, + TYPE_OBJ, TYPE_LIST); + (void) register_function("make_ot_string", 2, 2, bf_make_ot_string, + TYPE_OBJ, TYPE_LIST); + (void) register_function("make_od_string", 2, 2, bf_make_od_string, + TYPE_OBJ, TYPE_LIST); + (void) register_function("make_obj_create_string", 3, 3, bf_make_object_create_string, + TYPE_OBJ, TYPE_STR, TYPE_STR); +} + + + + diff -U 2 -b -P -x config.h -x y.tab.c -x y.tab.h MOO-1.8.0r5/gprot_lambda.h ehMOO.0.93.r5.codeonly/gprot_lambda.h --- MOO-1.8.0r5/gprot_lambda.h Wed Dec 31 18:00:00 1969 +++ ehMOO.0.93.r5.codeonly/gprot_lambda.h Sat Feb 3 00:52:29 2001 @@ -0,0 +1,22 @@ +/********************************************************************** + ** eh Graphics Protocol implementation for ehMOO + ** Copyright (c) 1995 by Tom Zanussi and Steve Albrecht +**********************************************************************/ + +/* + * eh Change History + * + * Revision 0.04 1996/03/31 11:13:38 trz + * Changed to work with 1.8.0 Lambda. + * + */ + +#define MAX_CREATE_STRING 1024 +#define MIN_GPROT_RECYCLE_ID 100 + +/********************************************************************** + ** function prototypes +**********************************************************************/ +GPROT_ERR init_eh_graphics_protocol(); +void register_gprot(void); + diff -U 2 -b -P -x config.h -x y.tab.c -x y.tab.h MOO-1.8.0r5/hash.c ehMOO.0.93.r5.codeonly/hash.c --- MOO-1.8.0r5/hash.c Wed Dec 31 18:00:00 1969 +++ ehMOO.0.93.r5.codeonly/hash.c Sat Feb 3 00:52:22 2001 @@ -0,0 +1,282 @@ +#include +#include +#include +#include +#include +#include + +#include "ll.h" /* Header for generic linked lists */ +#include "hash.h" + + +/*-------------------------------------------------------------- + * We use calloc() to allocate the table. However, on some + * compilers the bit pattern used by calloc() for initialization + * is not the same as NULL (which is what we want). So we check + * for this condition and, if it occurs, intialize the table by + * hand to NULLs. If size is 0, use default table size. + *-------------------------------------------------------------*/ +HashTable * HashTable_new (size_t size, + void * ( * createData_fn ) ( void * ), + int ( * deleteData_fn ) ( void * ), + int ( * duplicateNode_fn ) ( Link, Link ), + int ( * compareData_fn ) ( void *, void * )) +{ + int i; + + HashTable * ht = (HashTable *)malloc(sizeof(HashTable)); + if(!ht) + return NULL; + + ht->size = size ? size : DEFAULT_TABLE_SIZE; + + ht->listops = CreateLList ( createData_fn, + deleteData_fn, + duplicateNode_fn, + compareData_fn); + if(!ht->listops) { + free(ht); + return (NULL); + } + + ht->table = (Link *) calloc ( ht->size, sizeof ( Link )); + if ( ht->table == NULL ) { + free(ht->listops); + free(ht); + return (NULL); + } + + if ( *ht->table != NULL ) { /* is the calloc'd memory == NULL? */ + Link * t = ht->table; + for ( i = 0; i < ht->size; i++, t++ ) + *t = NULL; + } + + return (ht); +} + +void HashTable_delete(HashTable * ht) +{ + /* go through entire table and delete items */ + HashTable_clear(ht); + free(ht->listops); + free(ht); +} + +int HashTable_addItem(HashTable * ht, const char * key, void * item) +{ + int add_status; /* return value from table add*/ + unsigned hash_key; + HashData * hashdata; + + /*--- get the hash value ---*/ + + hash_key = (unsigned int)HashPJW(key); + hash_key %= ht->size; + + /*--- insert into table ---*/ + + ht->listops->LHead = ht->table[hash_key]; + + hashdata = (HashData *)malloc(sizeof(HashData)); + if(!hashdata) { + return 0; + } + + hashdata->key = strdup(key); + hashdata->item = item; + + add_status = AddNodeAscend(ht->listops, (void *)hashdata); + if(add_status != 0) + ht->table[hash_key] = ht->listops->LHead; + + return add_status; +} + +void * HashTable_findItem(HashTable * ht, const char * key) +{ + Link foundLink; + void * foundItem=NULL; + unsigned hash_key; + HashData * hashdata; + HashData * founddata; + + /*--- get the hash value ---*/ + + hash_key = (unsigned int)HashPJW(key); + hash_key %= ht->size; + + /*--- insert into table ---*/ + + ht->listops->LHead = ht->table[hash_key]; + + /* temporary searchkey */ + hashdata = (HashData *)malloc(sizeof(HashData)); + if(!hashdata) { + return NULL; + } + + hashdata->key = strdup(key); + hashdata->item = NULL; + + foundLink = FindNodeAscend(ht->listops, (void *)hashdata); + if(foundLink) { + founddata = (HashData *)foundLink->pdata; + foundItem = founddata->item; + } + + free(hashdata->key); + free(hashdata); + + return foundItem; +} + +static Link HashTable_findLink(HashTable * ht, const char * key) +{ + Link foundLink; + unsigned hash_key; + HashData * hashdata; + + /*--- get the hash value ---*/ + + hash_key = (unsigned int)HashPJW(key); + hash_key %= ht->size; + + /*--- insert into table ---*/ + + ht->listops->LHead = ht->table[hash_key]; + + /* temporary searchkey */ + hashdata = (HashData *)malloc(sizeof(HashData)); + if(!hashdata) { + return NULL; + } + + hashdata->key = strdup(key); + hashdata->item = NULL; + + foundLink = FindNodeAscend(ht->listops, (void *)hashdata); + + free(hashdata->key); + free(hashdata); + + return foundLink; +} + +/* this function will delete the associated data or not, depending + * on what deleteData_fn does. returns 1 if object deleted, 0 if not. + */ +int HashTable_removeItem(HashTable * ht, const char * key) +{ + int delete_status; /* return value from table delete */ + unsigned hash_key; + HashData * d=NULL; + Link foundLink = HashTable_findLink(ht, key); + + if(foundLink) { + /* free hashdata holder */ + d = (HashData *)foundLink->pdata; + /* this frees the link and the object*/ + /*--- get the hash value ---*/ + hash_key = (unsigned int)HashPJW(key); + hash_key %= ht->size; + /*--- make sure LHead points to the list ---*/ + ht->listops->LHead = ht->table[hash_key]; + + delete_status = DeleteNode(ht->listops, foundLink); + if(delete_status != 0) + ht->table[hash_key] = ht->listops->LHead; + + /* frees the key */ + free(d->key); + /* free the pdata e.g. Hash holder */ + free(d); + } + + return foundLink ? 1 : 0; +} + +void HashTable_clear(HashTable * ht) +{ + int i; + + for(i = 0;i < ht->size;i++ ) + { + if (ht->table[i] == NULL ) /* skip empty slots */ + continue; + else + { + ht->listops->LHead = ht->table[i]; + while(ht->listops->LHead) + DeleteNode(ht->listops, ht->listops->LHead); + } + } +} + + +/*-------------------------------------------------------------- + * Function to convert a string to upper case. Exists in most + * PC C libraries but missing from many UNIX C libraries. + *-------------------------------------------------------------*/ +char *strupr ( char *str ) +{ + char *s = str; + + while ( *s ) + { + *s = toupper ( *s ); + s += 1; + } + + return ( str ); +} + + +/*--- elfhash.c ------------------------------------------------ + * The published hash algorithm used in the UNIX ELF format + * for object files. + * + * Accepts a pointer to a string to be hashed and returns an + * unsigned long. Algorithm is similar to that implemented + * in HashPJW. + *-------------------------------------------------------------*/ + +unsigned long ElfHash ( const unsigned char *name ) +{ + unsigned long h = 0, g; + + while ( *name ) + { + h = ( h << 4 ) + *name++; + if ( (g = h & 0xF0000000)) + h ^= g >> 24; + + h &= ~g; + } + return ( h ); +} + +/*--- hashpjw.c ------------------------------------------------- + * An adaptation of Peter Weinberger's (PJW) generic hashing + * algorithm based on Allen Holub's version. + * + * Accepts a pointer to a datum to be hashed and returns an + * unsigned integer. + *-------------------------------------------------------------*/ + +unsigned int HashPJW ( const char * datum ) +{ + unsigned int hash_value, i; + + for ( hash_value = 0; *datum; ++datum ) + { + hash_value = ( hash_value << ONE_EIGHTH ) + *datum; + if (( i = hash_value & HIGH_BITS ) != 0 ) + hash_value = + ( hash_value ^ ( i >> THREE_QUARTERS )) & + ~HIGH_BITS; + } + + return ( hash_value ); +} + diff -U 2 -b -P -x config.h -x y.tab.c -x y.tab.h MOO-1.8.0r5/hash.h ehMOO.0.93.r5.codeonly/hash.h --- MOO-1.8.0r5/hash.h Wed Dec 31 18:00:00 1969 +++ ehMOO.0.93.r5.codeonly/hash.h Sat Feb 3 00:52:29 2001 @@ -0,0 +1,39 @@ +unsigned long ElfHash ( const unsigned char *name ); + +/* HashPJW defines */ +#define BITS_IN_int ( sizeof(int) * CHAR_BIT ) +#define THREE_QUARTERS ((int) ((BITS_IN_int * 3) / 4)) +#define ONE_EIGHTH ((int) (BITS_IN_int / 8)) +#define HIGH_BITS ( ~((unsigned int)(~0) >> ONE_EIGHTH )) + +unsigned int HashPJW ( const char * datum ); + +#define DEFAULT_TABLE_SIZE 7561 /* Number of slots; a prime number */ + +typedef struct HashTable +{ + size_t size; + Link * table; /* Our table is an array of Links */ + struct List * listops; /* list for hash table operations*/ +} HashTable; + +typedef struct HashData +{ + char * key; + void * item; +} HashData; + +HashTable * HashTable_new (size_t size, + void * ( * createData_fn ) ( void * ), + int ( * deleteData_fn ) ( void * ), + int ( * duplicateNode_fn ) ( Link, Link ), + int ( * compareData_fn ) ( void *, void * )); + +void HashTable_delete(HashTable * ht); +int HashTable_addItem(HashTable * ht, const char * key, void * item); +int HashTable_removeItem(HashTable * ht, const char * key); +void * HashTable_findItem(HashTable * ht, const char * key); +void HashTable_clear(HashTable * ht); +char *strupr ( char *str ); + + Only in MOO-1.8.0r5: keywords.gperf diff -U 2 -b -P -x config.h -x y.tab.c -x y.tab.h MOO-1.8.0r5/list.h ehMOO.0.93.r5.codeonly/list.h --- MOO-1.8.0r5/list.h Sun Mar 2 22:18:47 1997 +++ ehMOO.0.93.r5.codeonly/list.h Sat Feb 3 00:52:29 2001 @@ -36,4 +36,7 @@ /* $Log: list.h,v $ + * Revision 1.1 1996/04/01 01:26:22 root + * Initial revision + * * Revision 1.2 1997/03/03 04:18:47 nop * GNU Indent normalization diff -U 2 -b -P -x config.h -x y.tab.c -x y.tab.h MOO-1.8.0r5/ll.c ehMOO.0.93.r5.codeonly/ll.c --- MOO-1.8.0r5/ll.c Wed Dec 31 18:00:00 1969 +++ ehMOO.0.93.r5.codeonly/ll.c Sat Feb 3 00:52:22 2001 @@ -0,0 +1,283 @@ +/*--- ll.c ------------------------------ Listing 2-3 -------- + * Generic primitive functions for doubly linked lists. + * Contains no application-specific functions. + * Functions are in alphabetical order. + *------------------------------------------------------------*/ + +#include +#include + +#include "ll.h" + +/*--- Aliases to make the code more readable ---*/ + +#define LLHead (L->LHead) /* The head of the current list */ +#define LLTail (L->LTail) /* The tail of the current list */ +#define NodeCount (L->LCount) /* Nodes in the current list */ + +#define CreateData (*(L->LCreateData)) +#define DeleteData (*(L->LDeleteData)) +#define DuplicatedNode (*(L->LDuplicatedNode)) +#define NodeDataCmp (*(L->LNodeDataCmp)) + +/*---------------------------------------------------- + * Add a node at head: first allocate the space for + * the data, then allocate a node with a pointer to + * the data, then add the node to the list. + *--------------------------------------------------*/ +int AddNodeAtHead ( struct List *L, void *nd ) +{ + Link pn; + + pn = CreateNode ( L, nd ); + if ( pn == NULL ) + return ( 0 ); + + /*--- Add the node ---*/ + if ( LLHead == NULL ) /* is it the first node? */ + { + LLHead = LLTail = pn; /*--- yes ---*/ + } + else /*--- no ---*/ + { + LLHead->prev = pn; /* first goes node before Head */ + pn->next = LLHead; /* put Head next */ + LLHead = pn; /* then point Head to us */ + } + + NodeCount += 1; + return ( 1 ); +} + +/*---------------------------------------------------- + * Add ascending. Adds a node to an ordered list. + *--------------------------------------------------*/ +int AddNodeAscend ( struct List *L, void *nd ) +{ + Link pn; /* to node we're creating */ + Link prev, curr; /* our current search */ + struct Node dummy; /* a dummy node */ + int compare; + + pn = CreateNode ( L, nd ); + if ( pn == NULL ) + return ( 0 ); + + /* attach dummy node to head of list */ + dummy.next = LLHead; + dummy.prev = NULL; + if ( dummy.next != NULL ) + dummy.next->prev = &dummy; + + prev = &dummy; + curr = dummy.next; + for ( ; curr != NULL; prev = curr, curr = curr->next ) + { + compare = NodeDataCmp ( pn->pdata, curr->pdata ); + if ( compare <= 0 ) + break; /* new node equals or precedes curr */ + } + + if ( curr != NULL && compare == 0 ) + { + compare = DuplicatedNode ( pn, curr ); + if ( compare == 2 ) + /* do nothing -- will get inserted */; + else + { + /* first, repair the linked list */ + LLHead = dummy.next; + LLHead->prev = NULL; + + /* delete the duplicated node, if appropriate */ + if ( compare == 1 ) + { + DeleteData( pn->pdata ); + free ( pn ); + } + return ( 1 ); + } + } + + prev->next = pn; + pn->prev = prev; + pn->next = curr; + if ( curr != NULL ) + curr->prev = pn; + else + LLTail = pn; /* this node is the new tail */ + + NodeCount += 1; + + /* now, unhook the dummy head node */ + LLHead = dummy.next; + LLHead->prev = NULL; + return ( 1 ); +} + +/*--------------------------------------------------------------- + * Creates a linked-list structure and returns a pointer to it. + * On error, returns NULL. This functions accepts pointers + * to the four list-specific functions and initializes the + * linked-list structure with them. + *-------------------------------------------------------------*/ +struct List * CreateLList ( + void * ( * fCreateData ) ( void * ), + int ( * fDeleteData ) ( void * ), + int ( * fDuplicatedNode ) ( Link, Link ), + int ( * fNodeDataCmp ) ( void *, void * )) +{ + struct List * pL; + + pL = (struct List *) malloc ( sizeof ( struct List )); + if ( pL == NULL ) + return NULL; + + pL->LHead = NULL; + pL->LTail = NULL; + pL->LCount = 0; + + pL->LCreateData = fCreateData; + pL->LDeleteData = fDeleteData; + pL->LDuplicatedNode = fDuplicatedNode; + pL->LNodeDataCmp = fNodeDataCmp; + + return ( pL ); +} + +/*--------------------------------------------------------------- + * Creates a node and then calls the application-specific + * function CreateData() to create the node's data structure. + * Returns NULL on error. + *-------------------------------------------------------------*/ +Link CreateNode ( struct List *L, void *data ) +{ + Link new_node; + + new_node = (Link) malloc ( sizeof ( struct Node )); + if ( new_node == NULL ) + return ( NULL ); + + new_node->prev = NULL; + new_node->next = NULL; + + /*--- now call the application-specific data allocation ---*/ + new_node->pdata = CreateData( data ); + if ( new_node->pdata == NULL ) + { + free ( new_node ); + return ( NULL ); + } + else + return ( new_node ); +} + +/*--------------------------------------------------------------- + * Deletes the node pointed to by to_delete. + * Function calls list-specific function to delete data. + *-------------------------------------------------------------*/ +int DeleteNode ( struct List *L, Link to_delete ) +{ + Link pn; + + if ( to_delete == NULL ) /* Double check before */ + return ( 0 ); /* deleting anything. */ + + if ( to_delete->prev == NULL ) /* we're at the head */ + { + L->LHead = to_delete->next; /* update head */ + if(L->LHead) /* trz what if there is no next? */ + L->LHead->prev = NULL; /* update next node */ + } + + else if ( to_delete->next == NULL ) + { /* we're at the tail */ + pn = to_delete->prev; /* get the previous node */ + if(pn) /* what if there is no prev? */ + pn->next = NULL; + L->LTail = pn; /* update tail */ + } + + else /* we're in the list */ + { + pn = to_delete->prev; /* get the previous node */ + pn->next = to_delete->next; /* update previous node to */ + /* point to the next one. */ + pn = to_delete->next; /* get the next node */ + pn->prev = to_delete->prev; /* update it to point to */ + /* the previous one. */ + } + + DeleteData ( to_delete->pdata ); /* delete the data */ + free ( to_delete ); /* free the node */ + + NodeCount -= 1; + + return ( 1 ); +} + +/*--------------------------------------------------------------- + * Finds node by starting at the head of the list, stepping + * through each node, and comparing data items with the search + * key. The Ascend version checks that the data in the node + * being examined is not larger than the search key. If it is, + * we know the key is not in the list. Returns pointer to node + * on success or NULL on failure. + *-------------------------------------------------------------*/ +Link FindNode ( struct List *L, void *nd ) +{ + Link pcurr; /* the node we're examining */ + + if ( LLHead == NULL ) /* empty list */ + return ( NULL ); + + for ( pcurr = LLHead; pcurr != NULL; pcurr = pcurr->next) + { + if ( NodeDataCmp ( nd, pcurr->pdata ) == 0 ) + return ( pcurr ); + } + return ( NULL ); /* could not find node */ +} + +Link FindNodeAscend ( struct List *L, void *nd ) +{ + Link pcurr; /* the node we're examining */ + int cmp_result; + + if ( LLHead == NULL ) /* empty list */ + return ( NULL ); + + for ( pcurr = LLHead; pcurr != NULL; pcurr = pcurr->next) + { + cmp_result = NodeDataCmp ( nd, pcurr->pdata ); + + if ( cmp_result < 0 ) + return ( NULL ); /* too far */ + + if ( cmp_result == 0 ) /* just right */ + return ( pcurr ); + } + + return ( NULL ); /* could not find node */ +} + +/*--------------------------------------------------------------- + * The Goto functions return the pointer to the requested node + * or NULL on error. + *-------------------------------------------------------------*/ + +Link GotoNext ( struct List *L, Link pcurr ) +{ + if ( pcurr->next == NULL || pcurr == LLTail ) + return ( NULL ); + else + return ( pcurr->next ); +} + +Link GotoPrev ( struct List *L, Link pcurr ) +{ + if ( pcurr->prev == NULL || pcurr == LLHead ) + return ( NULL ); + else + return ( pcurr->prev ); +} diff -U 2 -b -P -x config.h -x y.tab.c -x y.tab.h MOO-1.8.0r5/ll.h ehMOO.0.93.r5.codeonly/ll.h --- MOO-1.8.0r5/ll.h Wed Dec 31 18:00:00 1969 +++ ehMOO.0.93.r5.codeonly/ll.h Sat Feb 3 00:52:29 2001 @@ -0,0 +1,69 @@ +/*--- ll.h ----------------------------- Listing 2-2 --------- + * Declarations for generic doubly linked lists. + * Used in conjunction with llgen.c (Listing 2-3). + *-------------------------------------------------------------*/ +#ifndef LL_H /* make sure it's included only once */ +#define LL_H 1 + + +struct Node { + struct Node *prev; /* link to previous node */ + struct Node *next; /* link to next node */ + void *pdata; /* generic pointer to data */ +}; + +typedef struct Node *Link; + +/* a linked list data structure */ +struct List { + Link LHead; + Link LTail; + unsigned int LCount; + void * ( * LCreateData ) ( void * ); + int ( * LDeleteData ) ( void * ); + int ( * LDuplicatedNode ) ( Link, Link ); + int ( * LNodeDataCmp ) ( void *, void * ); +}; + +/* The four functions specific to an individual linked list are: + + LCreateData: is passed a pointer to an application-defined + object and is expected to return a pointer to + whatever is to be stored in the linked list. + + LDeleteData: is passed a pointer to the object an application + has stored in a linked list. LDeleteData must + destroy the object. + + LDuplicatedNode: is passed two pointers. The first pointer is + to a node that you would like to add to a + linked list and the second is to a node that + is already in the list but is a duplicate of + the first pointer. + LDuplicatedNode returns: + 0 -> do nothing to list + 1 -> destroy duplicate + 2 -> add duplicate to list + + LNodeDataCmp: is passed pointers to two application data + objects and must compare them, returning a + number that is < 0, zero, or > 0, depending on + the relationship between the first and second + objects. +*/ + +/*--- generic linked-list primitives ---*/ +int AddNodeAscend ( struct List *, void * ); +int AddNodeAtHead ( struct List *, void * ); +struct List * CreateLList ( + void * ( * ) ( void * ), /* create data */ + int ( * ) ( void * ), /* delete data */ + int ( * ) ( Link, Link ), /* duplicate */ + int ( * ) ( void *, void * )); /* compare */ +Link CreateNode ( struct List * , void * ); +int DeleteNode ( struct List *, Link ); +Link FindNode ( struct List *, void * ); +Link FindNodeAscend ( struct List *, void * ); +Link GotoNext ( struct List *, Link ); +Link GotoPrev ( struct List *, Link ); +#endif diff -U 2 -b -P -x config.h -x y.tab.c -x y.tab.h MOO-1.8.0r5/objtab.c ehMOO.0.93.r5.codeonly/objtab.c --- MOO-1.8.0r5/objtab.c Wed Dec 31 18:00:00 1969 +++ ehMOO.0.93.r5.codeonly/objtab.c Sat Feb 3 00:52:22 2001 @@ -0,0 +1,192 @@ +/********************************************************************** + ** eh object registration table + ** Copyright (c) 1996 by Tom Zanussi and Steve Albrecht +**********************************************************************/ + +#include +#include +#include +#include +#ifndef WIN32 +#include +#include +#endif +#include "ll.h" +#include "hash.h" +#include "objtab.h" + +/********************************************************************** + ** This module contains the eh code handling object registration + ** for both client and server +**********************************************************************/ + +static int objTable_removeObjectS(objTable * otab, const char * str_object); +static void * objTable_findObjectS(objTable * otab, const char * str_object); +static int objTable_addObjectS(objTable * otab, const char * obj_handle, + OBJ_HANDLE handle); + + +static int objTable_removeObjectS(objTable * otab, const char * str_object) +{ + return HashTable_removeItem(otab->table, str_object); +} + +/* remove an object given the string representation */ +int objTable_removeObjectStr(objTable * otab, const char * object_str) +{ + char * p; + OBJ_HANDLE objid; + + objid = strtoul(object_str, &p, 10); + if(*p != '\0') return 0; /* non-object file for sure */ + + return objTable_removeObjectNum(otab, objid); +} + +/* remove an object given the numeric representation */ +int objTable_removeObjectNum(objTable * otab, OBJ_HANDLE objid) +{ + char str_object[256]; + + sprintf(str_object, "%lu", objid); + + return objTable_removeObjectS(otab, str_object); +} + +static void * objTable_findObjectS(objTable * otab, const char * str_object) +{ + return (void *)HashTable_findItem(otab->table, str_object); +} + +/* find a handle given the string representation */ +void * objTable_findObjectStr(objTable * otab, const char * object_str) +{ + char * p; + OBJ_HANDLE objid; + + objid = strtoul(object_str, &p, 10); + if(*p != '\0') return 0; /* non-object file for sure */ + + return objTable_findObjectNum(otab, objid); +} + +/* find a handle given the numeric representation */ +void * objTable_findObjectNum(objTable * otab, OBJ_HANDLE objid) +{ + char obj_str[256]; + + sprintf(obj_str, "%lu", objid); + + return objTable_findObjectS(otab, obj_str); +} + +void objTable_delete(objTable * otab) +{ + if(!otab) + return; + + if(otab->filename) + free(otab->filename); + if(otab->table) + HashTable_delete(otab->table); + free(otab); +} + +/* object cache functions */ + +static int objTable_addObjectS(objTable * otab, const char * obj_handle, + OBJ_HANDLE handle) +{ + return HashTable_addItem(otab->table, obj_handle, (void *)handle); +} + +/* add an object given the string representation */ +int objTable_addObjectStr(objTable * otab, const char * handle_str) +{ + char * p; + OBJ_HANDLE handle; + + handle = strtoul(handle_str, &p, 10); + if(*p != '\0') return 0; /* non-object file for sure */ + + return objTable_addObjectNum(otab, handle); +} + +/* add an object given the numeric representation */ +int objTable_addObjectNum(objTable * otab, OBJ_HANDLE handle) +{ + char str_handle[256]; + + sprintf(str_handle, "%lu", handle); + + return objTable_addObjectS(otab, str_handle, handle); +} + +/* if filename NULL, or filename not found, empty table returned */ +objTable * objTable_new(const char * filename) +{ + objTable * otab = (objTable *)malloc(sizeof(objTable)); + if(!otab) + return NULL; + + if(filename) + otab->filename = strdup(filename); + else + otab->filename = NULL; + + otab->table = HashTable_new(DEFAULT_HLIST_SIZE, + createObject_fn, + deleteObject_fn, + duplicateObject_fn, + compareObject_fn); + + if(!otab->table) { + free(otab); + return NULL; + } + + return otab; +} + + +/* In this case, we don't want to allocate memory, the object has + * been cast to void * + */ +void * createObject_fn( void * data ) +{ + return data; +} + +/* nothing to delete */ +int deleteObject_fn( void * data ) +{ + return (1); +} + +/*--------------------------------------------------------------- + * This function determines what to do when inserting a node + * into a list if an existing node with the same data is found + * in the list. In this case, since we are counting words, if a + * duplicate word is found, we simply increment the counter. + * + * Note this function should return one of the following values: + * 0 an error occurred + * 1 delete the duplicate node + * 2 insert the duplicate node + * Any other processing on the duplicate should be done in this + * function. + *-------------------------------------------------------------*/ + +int duplicateObject_fn(Link new_node, Link list_node) +{ /* don't want duplicates, return 1 to delete new_node */ + return (1); +} + +int compareObject_fn(void *first, void *second) +{ + HashData * o1 = (HashData *)first; + HashData * o2 = (HashData *)second; + + return (strcmp(o1->key, o2->key)); +} + diff -U 2 -b -P -x config.h -x y.tab.c -x y.tab.h MOO-1.8.0r5/objtab.h ehMOO.0.93.r5.codeonly/objtab.h --- MOO-1.8.0r5/objtab.h Wed Dec 31 18:00:00 1969 +++ ehMOO.0.93.r5.codeonly/objtab.h Sat Feb 3 00:52:30 2001 @@ -0,0 +1,24 @@ +#define DEFAULT_HLIST_SIZE 503 + +typedef unsigned long OBJ_HANDLE; + +typedef struct objTable +{ + char * filename; /* where to save/retrieve table */ + HashTable * table; +} objTable; + +int objTable_removeObjectStr(objTable * otab, const char * object_str); +int objTable_removeObjectNum(objTable * otab, OBJ_HANDLE objid); +void * objTable_findObjectStr(objTable * otab, const char * object_str); +void * objTable_findObjectNum(objTable * otab, OBJ_HANDLE objid); +objTable * objTable_new(const char * filename); +void objTable_delete(objTable * otab); +int objTable_addObjectStr(objTable * otab, const char * handle_str); +int objTable_addObjectNum(objTable * otab, OBJ_HANDLE handle); + +void * createObject_fn( void * data ); +int deleteObject_fn( void * data ); +int duplicateObject_fn(Link new_node, Link list_node); +int compareObject_fn(void *first, void *second); + diff -U 2 -b -P -x config.h -x y.tab.c -x y.tab.h MOO-1.8.0r5/oc_data.c ehMOO.0.93.r5.codeonly/oc_data.c --- MOO-1.8.0r5/oc_data.c Wed Dec 31 18:00:00 1969 +++ ehMOO.0.93.r5.codeonly/oc_data.c Sat Feb 3 00:52:22 2001 @@ -0,0 +1,1105 @@ +/********************************************************************** + ** eh Graphics Protocol oc data handling functions + ** Copyright (c) 1996 by Tom Zanussi and Steve Albrecht +**********************************************************************/ + +/* + * eh Change History + * + * Revision 0.01 1996/10/02 11:13:38 trz + * Initial Revision + * + */ + +#include +#include +#include +#include "ll.h" +#include "hash.h" +#include "fntab.h" +#include "gprot.h" +#include "oc_data.h" + +/********************************************************************** + ** This module contains the eh Graphics Protocol code common to both + ** client and server implementations of ocm/e server-specific data + ** handling. +**********************************************************************/ + +/********************************************************************** + ** ocm/e server-specific data functions and utilities. + ** + ** The functions and data structures in this module define the + ** structure and operations currently implemented with respect + ** to the 'server-specific data' glob referred to in the eh + ** graphics protocol document. This module represents only + ** one of the possible schemes available for structuring + ** data. New server-specific data globs can take any form + ** convenient to the implementation. The scheme outlined + ** below happens to be the one currently implemented. + ** + ** NOTE: + ** The following high-level utility functions are provided to + ** allow you to ignore the following explanation: + ** + ** char * make_robot_request_string(char * name, char * password); + ** char * make_room_request_string(char * name); + ** char * make_exit_request_string(char * name, ObjectID source_roomid, + ** ObjectID dest_roomid); + ** char * make_object_request_string(char * superclass, char * name); + ** + ** These functions return a string which can be sent directly via the + ** gprot. + ** END NOTE + ** + ** The {server-specific data} glob referred to in the graphics + ** protocol document is in this scheme structured as follows: + ** + ** {datatype data}; + ** + ** The first field of the data glob specifies a data/operation type. + ** The currently available types are: + ** + ** OCDT_EDIT_BOT_CREATE + ** OCDT_EDIT_ROOM_CREATE + ** OCDT_EDIT_EXIT_CREATE + ** OCDT_EDIT_OBJECT_CREATE + ** OCDT_EDIT_OBJECT_FACING + ** OCDT_OBJECT_CREATE + ** OCDT_AVATAR_CREATE + ** OCDT_OBJECT_FACING + ** OCDT_EDIT_PORTAL_CREATE + ** OCDT_EDIT_ROOM_DRAWING_INFO + ** OCDT_EDIT_ROOM_PERSISTENT_SUBSCRIBER_LIST + ** OCDT_EDIT_ROOM_DESCRIPTION + ** OCDT_EDIT_ROOM_NAME + ** + ** Everthing following the datatype is assumed to be part of the + ** parseable data for that datatype. + ** + ** An oc struct should never be created directly. Instead, the + ** function new_oc() should be called to create one. One of the + ** above datatypes can be specified, or the value OCDT_NONE, which + ** is the equivalent of a void * for oc datatypes, and is normally + ** used internally only. new_oc will create an oc containing a + ** pointer to an allocated data structure of the correct type, + ** which can be accessed via the oc->data->parsed_data member of + ** the oc object. The fields of the corresponding struct can then + ** be filled in (strings should be strdup'ed) with the appropriate + ** values and passed to gprot user functions taking an oc struct + ** as a parameter (make_oc_string). An oc originating from the + ** gprot (msg/event) will have the oc->data->raw_data field filled + ** in. To access the data via the parsed_data field, oc_parse_data() + ** must first be called. + ** + ** An allocated oc should never be free'ed directly. Instead, the + ** function delete_oc() should be called to properly free all + ** contained data. + ** +**********************************************************************/ + +/* create a new oc. If datatype == OCDT_NONE, leave raw_data + * and parsed_data empty. raw_data will be filled in by gprot + * handler when a msg/event is received, or by stringing together + * parsed_data fields filled by requesting code. parsed_data + * will be filled in from raw_data by calling parse_oc_data when + * needed, or be filled in by requesting code. If datatype != + * OCDT_NONE, the appropriate parsed_data struct will be created + * for use by requesting code. + */ +oc * new_oc(oc_datatype datatype) +{ + oc * newoc = (oc *)malloc(sizeof(oc)); + + newoc->objectID = 0; + newoc->handle = 0; + newoc->duration = 0; + + newoc->data = (oc_data *)malloc(sizeof(oc_data)); + newoc->data->datatype = datatype; + newoc->data->raw_data = NULL; + + switch(datatype) { + + case OCDT_EDIT_BOT_CREATE: + newoc->data->parsed_data = + (void *)malloc(sizeof(oc_bot_create_params)); + break; + + case OCDT_EDIT_ROOM_CREATE: + newoc->data->parsed_data = + (void *)malloc(sizeof(oc_room_create_params)); + break; + + case OCDT_EDIT_ROOM_DRAWING_INFO: + newoc->data->parsed_data = + (void *)malloc(sizeof(oc_room_edit_drawing_info_params)); + break; + + case OCDT_EDIT_ROOM_PERSISTENT_SUBSCRIBER_LIST: + newoc->data->parsed_data = + (void *)malloc(sizeof(oc_room_edit_persistent_subscriber_params)); + break; + + case OCDT_EDIT_ROOM_DESCRIPTION: + newoc->data->parsed_data = + (void *)malloc(sizeof(oc_room_edit_description_params)); + break; + + case OCDT_EDIT_ROOM_NAME: + newoc->data->parsed_data = + (void *)malloc(sizeof(oc_room_edit_name_params)); + break; + + case OCDT_EDIT_EXIT_CREATE: + newoc->data->parsed_data = + (void *)malloc(sizeof(oc_exit_create_params)); + break; + + case OCDT_EDIT_PORTAL_CREATE: + newoc->data->parsed_data = + (void *)malloc(sizeof(oc_portal_create_params)); + break; + + case OCDT_EDIT_OBJECT_CREATE: + newoc->data->parsed_data = + (void *)malloc(sizeof(oc_obj_create_params)); + break; + + case OCDT_EDIT_OBJECT_FACING: + newoc->data->parsed_data = + (void *)malloc(sizeof(oc_facing_edit_params)); + break; + + case OCDT_OBJECT_FACING: + newoc->data->parsed_data = + (void *)malloc(sizeof(oc_facing_params)); + break; + + case OCDT_OBJECT_CREATE: + newoc->data->parsed_data = + (void *)malloc(sizeof(oc_objfile_params)); + break; + + default: + newoc->data->parsed_data = NULL; + break; + } + + return newoc; +} + +/* destroy a previously created oc */ +void delete_oc(oc * oc) +{ + if(!oc) + return; + + if(oc->data->parsed_data) { + switch(oc->data->datatype) { + + case OCDT_EDIT_BOT_CREATE: + { + oc_bot_create_params * create_params = + (oc_bot_create_params *)oc->data->parsed_data; + if(create_params->object_name) + free(create_params->object_name); + if(create_params->object_password) + free(create_params->object_password); + } + break; + + case OCDT_EDIT_ROOM_CREATE: + { + oc_room_create_params * create_params = + (oc_room_create_params *)oc->data->parsed_data; + if(create_params->object_name) + free(create_params->object_name); + } + break; + + case OCDT_EDIT_ROOM_DRAWING_INFO: + { + oc_room_edit_drawing_info_params * di_params = + (oc_room_edit_drawing_info_params *)oc->data->parsed_data; + if(di_params->drawing_info) + free(di_params->drawing_info); + } + break; + + case OCDT_EDIT_ROOM_PERSISTENT_SUBSCRIBER_LIST: + { + oc_room_edit_persistent_subscriber_params * list_params = + (oc_room_edit_persistent_subscriber_params *)oc->data->parsed_data; + if(list_params->persistent_subscriber_list) + free(list_params->persistent_subscriber_list); + } + break; + + case OCDT_EDIT_ROOM_DESCRIPTION: + { + oc_room_edit_description_params * desc_params = + (oc_room_edit_description_params *)oc->data->parsed_data; + if(desc_params->description) + free(desc_params->description); + } + break; + + case OCDT_EDIT_ROOM_NAME: + { + oc_room_edit_name_params * name_params = + (oc_room_edit_name_params *)oc->data->parsed_data; + if(name_params->name) + free(name_params->name); + } + break; + + case OCDT_EDIT_EXIT_CREATE: + { + oc_exit_create_params * create_params = + (oc_exit_create_params *)oc->data->parsed_data; + if(create_params->object_name) + free(create_params->object_name); + } + break; + + case OCDT_EDIT_PORTAL_CREATE: + { + oc_portal_create_params * create_params = + (oc_portal_create_params *)oc->data->parsed_data; + if(create_params->to_dest_spec) + free(create_params->to_dest_spec); + if(create_params->from_dest_spec) + free(create_params->from_dest_spec); + } + break; + + case OCDT_EDIT_OBJECT_CREATE: + { + oc_obj_create_params * create_params = + (oc_obj_create_params *)oc->data->parsed_data; + if(create_params->superclass) + free(create_params->superclass); + if(create_params->object_name) + free(create_params->object_name); + } + break; + + case OCDT_EDIT_OBJECT_FACING: + { + oc_facing_edit_params * facing_params = + (oc_facing_edit_params *)oc->data->parsed_data; + if(facing_params->url) + free(facing_params->url); + } + break; + + case OCDT_OBJECT_CREATE: + { + oc_objfile_params * objfile_params = + (oc_objfile_params *)oc->data->parsed_data; + if(objfile_params->objtype) + free(objfile_params->objtype); + if(objfile_params->objfile) + free(objfile_params->objfile); + } + break; + + /* no data to free */ + case OCDT_OBJECT_FACING: + default: + break; + } + + if(oc->data->parsed_data) + free(oc->data->parsed_data); + } + + if(oc->data->raw_data) + free(oc->data->raw_data); + if(oc->data) + free(oc->data); + free(oc); +} + +/* + * given an oc with parsed_data fields filled, fill raw_data with + * concatenated string to send via gprot. + */ +GPROT_ERR unparse_oc_data(oc * oc) +{ + char * string = NULL; + + if(oc->data->raw_data) /* already unparsed */ + return GE_NONE; + + string = (char *)malloc(MAX_GPROT_MSGLEN); + + switch(oc->data->datatype) { + case OCDT_EDIT_BOT_CREATE: + { + oc_bot_create_params * create_params = + (oc_bot_create_params *)oc->data->parsed_data; + sprintf(string, "%s %s", create_params->object_name, + create_params->object_password); + oc->data->raw_data = string; + } + break; + + case OCDT_EDIT_ROOM_CREATE: + { + oc_room_create_params * create_params = + (oc_room_create_params *)oc->data->parsed_data; + sprintf(string, "%s", create_params->object_name); + oc->data->raw_data = string; + } + break; + + case OCDT_EDIT_ROOM_DRAWING_INFO: + { + oc_room_edit_drawing_info_params * di_params = + (oc_room_edit_drawing_info_params *)oc->data->parsed_data; + sprintf(string, "%s", di_params->drawing_info); + oc->data->raw_data = string; + } + break; + + case OCDT_EDIT_ROOM_PERSISTENT_SUBSCRIBER_LIST: + { + oc_room_edit_persistent_subscriber_params * list_params = + (oc_room_edit_persistent_subscriber_params *)oc->data->parsed_data; + sprintf(string, "%s", list_params->persistent_subscriber_list); + oc->data->raw_data = string; + } + break; + + case OCDT_EDIT_ROOM_DESCRIPTION: + { + oc_room_edit_description_params * desc_params = + (oc_room_edit_description_params *)oc->data->parsed_data; + sprintf(string, "%s", desc_params->description); + oc->data->raw_data = string; + } + break; + + case OCDT_EDIT_ROOM_NAME: + { + oc_room_edit_name_params * name_params = + (oc_room_edit_name_params *)oc->data->parsed_data; + sprintf(string, "%s", name_params->name); + oc->data->raw_data = string; + } + break; + + case OCDT_EDIT_EXIT_CREATE: + { + oc_exit_create_params * create_params = + (oc_exit_create_params *)oc->data->parsed_data; + sprintf(string, "%s %lu %lu", create_params->object_name, + create_params->source_room, create_params->dest_room); + oc->data->raw_data = string; + } + break; + + case OCDT_EDIT_PORTAL_CREATE: + { + oc_portal_create_params * create_params = + (oc_portal_create_params *)oc->data->parsed_data; + sprintf(string, "%s %s %lu %lu", create_params->to_dest_spec, + create_params->from_dest_spec, + create_params->source_room, create_params->dest_room); + oc->data->raw_data = string; + } + break; + + case OCDT_EDIT_OBJECT_CREATE: + { + oc_obj_create_params * create_params = + (oc_obj_create_params *)oc->data->parsed_data; + sprintf(string, "%s %s", create_params->superclass, + create_params->object_name); + oc->data->raw_data = string; + } + break; + + case OCDT_EDIT_OBJECT_FACING: + { + oc_facing_edit_params * facing_params = + (oc_facing_edit_params *)oc->data->parsed_data; + sprintf(string, "%d %s", facing_params->angle, + facing_params->url); + oc->data->raw_data = string; + } + break; + + case OCDT_OBJECT_FACING: + { + oc_facing_params * facing_params = + (oc_facing_params *)oc->data->parsed_data; + sprintf(string, "%d", facing_params->angle); + oc->data->raw_data = string; + } + break; + + case OCDT_OBJECT_CREATE: + { + oc_objfile_params * objfile_params = + (oc_objfile_params *)oc->data->parsed_data; + sprintf(string, "%s %s", objfile_params->objtype, + objfile_params->objfile); + + oc->data->raw_data = string; + } + break; + + /* no data to unparse */ + default: + free(string); + string = NULL; + return GE_BADMSG; + break; + } + + return GE_NONE; +} + +/* since clients such as moo transmit only printable characters + * we need to replace the agreed-upon client newline char to newline +*/ +void replace_newlines(char * client_file) +{ + while(*client_file++ != '\0') { + if(*client_file == client_newline) { + *client_file = server_newline; + } + } +} + + +/* + * Given an oc containing raw data (from newly arrived msg or event), + * parse it into usable fields and save as oc->data->parsed_data. + */ +GPROT_ERR parse_oc_data(oc * oc) +{ + int argc; + GPROT_ERR err; + char * argv[MAXFIELDS]; + char * s; + + if(oc->data->parsed_data) /* Already parsed */ + return GE_NONE; + + if(!oc->data->raw_data) /* no associated data */ + return GE_NONE; + + s = strdup(oc->data->raw_data); + + if(oc->data->datatype == OCDT_OBJECT_CREATE) { + err = parse_into_fields(s, &argc, argv, 2); + } else if(oc->data->datatype == OCDT_EDIT_ROOM_DRAWING_INFO) { + err = parse_into_fields(s, &argc, argv, 1); + } else if(oc->data->datatype == OCDT_EDIT_ROOM_PERSISTENT_SUBSCRIBER_LIST) { + err = parse_into_fields(s, &argc, argv, 1); + } else if(oc->data->datatype == OCDT_EDIT_ROOM_DESCRIPTION) { + err = parse_into_fields(s, &argc, argv, 1); + } else if(oc->data->datatype == OCDT_EDIT_ROOM_NAME) { + err = parse_into_fields(s, &argc, argv, 1); + } else { + err = parse_into_fields(s, &argc, argv, MAXFIELDS); + } + + if(err != GE_NONE) { + free(s); + return err; + } + if(argc < 1) { + free(s); + return GE_BADMSG; + } + + switch(oc->data->datatype) { + + case OCDT_EDIT_BOT_CREATE: + if(argc < 2) { + err = GE_BADMSG; + } + else { + oc_bot_create_params * create_params = (oc_bot_create_params *) + malloc(sizeof(oc_bot_create_params)); + + create_params->object_name = strdup(argv[0]); + create_params->object_password = strdup(argv[1]); + oc->data->parsed_data = (void *)create_params; + } + break; + + case OCDT_EDIT_ROOM_CREATE: + { + oc_room_create_params * create_params = (oc_room_create_params *) + malloc(sizeof(oc_room_create_params)); + + create_params->object_name = strdup(argv[0]); + oc->data->parsed_data = (void *)create_params; + } + break; + + case OCDT_EDIT_ROOM_DRAWING_INFO: + if(argc < 1) { + err = GE_BADMSG; + } + else { + oc_room_edit_drawing_info_params * di_params = (oc_room_edit_drawing_info_params *) + malloc(sizeof(oc_room_edit_drawing_info_params)); + + di_params->drawing_info = strdup(argv[0]); + oc->data->parsed_data = (void *)di_params; + } + break; + + case OCDT_EDIT_ROOM_PERSISTENT_SUBSCRIBER_LIST: + if(argc < 1) { + err = GE_BADMSG; + } + else { + oc_room_edit_persistent_subscriber_params * list_params = (oc_room_edit_persistent_subscriber_params *) + malloc(sizeof(oc_room_edit_persistent_subscriber_params)); + + list_params->persistent_subscriber_list = strdup(argv[0]); + oc->data->parsed_data = (void *)list_params; + } + break; + + case OCDT_EDIT_ROOM_DESCRIPTION: + if(argc < 1) { + err = GE_BADMSG; + } + else { + oc_room_edit_description_params * desc_params = (oc_room_edit_description_params *) + malloc(sizeof(oc_room_edit_description_params)); + + desc_params->description = strdup(argv[0]); + oc->data->parsed_data = (void *)desc_params; + } + break; + + case OCDT_EDIT_ROOM_NAME: + if(argc < 1) { + err = GE_BADMSG; + } + else { + oc_room_edit_name_params * name_params = (oc_room_edit_name_params *) + malloc(sizeof(oc_room_edit_name_params)); + + name_params->name = strdup(argv[0]); + oc->data->parsed_data = (void *)name_params; + } + break; + + case OCDT_EDIT_EXIT_CREATE: + if(argc < 3) { + err = GE_BADMSG; + } + else { + char * p; + + oc_exit_create_params * create_params = (oc_exit_create_params *) + malloc(sizeof(oc_exit_create_params)); + + create_params->source_room = strtoul(argv[1], &p, 10); + if(*p != '\0') { + free(create_params); + err = GE_BADMSG; + } + else { + create_params->dest_room = strtoul(argv[2], &p, 10); + if(*p != '\0') { + free(create_params); + err = GE_BADMSG; + } + else { + create_params->object_name = strdup(argv[0]); + oc->data->parsed_data = (void *)create_params; + } + } + } + break; + + case OCDT_EDIT_PORTAL_CREATE: + if(argc < 4) { + err = GE_BADMSG; + } + else { + char * p; + + oc_portal_create_params * create_params = (oc_portal_create_params *) + malloc(sizeof(oc_portal_create_params)); + + create_params->source_room = strtoul(argv[2], &p, 10); + if(*p != '\0') { + free(create_params); + err = GE_BADMSG; + } + else { + create_params->dest_room = strtoul(argv[3], &p, 10); + if(*p != '\0') { + free(create_params); + err = GE_BADMSG; + } + else { + create_params->to_dest_spec = strdup(argv[0]); + create_params->from_dest_spec = strdup(argv[1]); + oc->data->parsed_data = (void *)create_params; + } + } + } + break; + + case OCDT_EDIT_OBJECT_CREATE: + if(argc < 2) { + err = GE_BADMSG; + } + else { + oc_obj_create_params * create_params = (oc_obj_create_params *) + malloc(sizeof(oc_obj_create_params)); + + create_params->superclass = strdup(argv[0]); + create_params->object_name = strdup(argv[1]); + oc->data->parsed_data = (void *)create_params; + } + break; + + case OCDT_EDIT_OBJECT_FACING: + if(argc < 2) { + err = GE_BADMSG; + } + else { + oc_facing_edit_params * facing_params = (oc_facing_edit_params *) + malloc(sizeof(oc_facing_edit_params)); + + facing_params->angle = atoi(argv[0]); + facing_params->url = strdup(argv[1]); + oc->data->parsed_data = (void *)facing_params; + } + break; + + case OCDT_OBJECT_FACING: + { + oc_facing_params * facing_params = (oc_facing_params *) + malloc(sizeof(oc_facing_params)); + + facing_params->angle = atoi(argv[0]); + oc->data->parsed_data = (void *)facing_params; + } + break; + + case OCDT_OBJECT_CREATE: + if(argc < 1) { + err = GE_BADMSG; + } + else { + oc_objfile_params * objfile_params = (oc_objfile_params *) + malloc(sizeof(oc_objfile_params)); + + objfile_params->objtype = strdup(argv[0]); + if(argc < 2) { /* we already have an objfile, none in event */ + objfile_params->objfile = NULL; + } + else { /* the rest of the event is the objfile */ + objfile_params->objfile = strdup(argv[1]); + /* translate client's printable ascii newline into \n */ + replace_newlines(objfile_params->objfile); + } + + oc->data->parsed_data = (void *)objfile_params; + } + break; + + /* should never get here */ + default: + break; + } + + free(s); + return err; +} + +/* + ** make_robot_request_string(name, password) + ** + ** Make a string to send to client requesting creation of a new robot. + ** Must also supply a password for the bot. + ** + ** Caller owns allocated string memory. +*/ +char * make_robot_request_string(char * name, char * password) +{ + char * request_string = NULL; + oc * object_oc = new_oc(OCDT_EDIT_BOT_CREATE); + + if(object_oc) { + oc_bot_create_params * create_params = + (oc_bot_create_params *)object_oc->data->parsed_data; + create_params->object_name = strdup(name); + create_params->object_password = strdup(password); + object_oc->objectID = 0; /* request creation*/ + request_string = make_oc_string(object_oc); + delete_oc(object_oc); + } + return request_string; +} + +/* + ** make_room_request_string(name) + ** + ** Make a string to send to client requesting creation of a new room. + ** + ** Caller owns allocated string memory. +*/ +char * make_room_request_string(char * name) +{ + char * request_string = NULL; + oc * object_oc = new_oc(OCDT_EDIT_ROOM_CREATE); + + if(object_oc) { + oc_room_create_params * create_params = + (oc_room_create_params *)object_oc->data->parsed_data; + create_params->object_name = strdup(name); + object_oc->objectID = 0; /* request creation*/ + request_string = make_oc_string(object_oc); + delete_oc(object_oc); + } + return request_string; +} + +/* + ** make_exit_request_string(name, source_roomid, dest_roomid) + ** + ** Make a string to send to client requesting creation of a new exit. + ** source_roomid is the room the exit originates from, dest_roomid + ** is the room the exit leads to. + ** + ** Caller owns allocated string memory. +*/ +char * make_exit_request_string(char * name, ObjectID source_roomid, + ObjectID dest_roomid) +{ + char * request_string = NULL; + oc * object_oc = new_oc(OCDT_EDIT_EXIT_CREATE); + + if(object_oc) { + oc_exit_create_params * create_params = + (oc_exit_create_params *)object_oc->data->parsed_data; + create_params->object_name = strdup(name); + create_params->source_room = source_roomid; + create_params->dest_room = dest_roomid; + object_oc->objectID = 0; /* request creation*/ + request_string = make_oc_string(object_oc); + delete_oc(object_oc); + } + return request_string; +} + +/* + ** make_object_request_string(superclass, name) + ** + ** Make a string to send to client requesting creation of a new object. + ** Not to be used to make bots, rooms, or exits. The superclass is + ** the client-side class name the object isA type of. + ** + ** Caller owns allocated string memory. +*/ +char * make_object_request_string(char * superclass, char * name) +{ + char * request_string = NULL; + oc * object_oc = new_oc(OCDT_EDIT_OBJECT_CREATE); + + if(object_oc) { + oc_obj_create_params * create_params = + (oc_obj_create_params *)object_oc->data->parsed_data; + create_params->superclass = strdup(superclass); + create_params->object_name = strdup(name); + object_oc->objectID = 0; /* request creation*/ + request_string = make_oc_string(object_oc); + delete_oc(object_oc); + } + return request_string; +} + +/* + ** make_facing_edit_string(angle, url) + ** + ** Make a string specifying a facing angle along with associated + ** url. + ** + ** Caller owns allocated string memory. +*/ +char * make_facing_edit_string(ObjectID objid, unsigned long handle, + unsigned long duration, int angle, char * url) +{ + char * facing_string = NULL; + oc * object_oc = new_oc(OCDT_EDIT_OBJECT_FACING); + + if(object_oc) { + oc_facing_edit_params * facing_params = + (oc_facing_edit_params *)object_oc->data->parsed_data; + + object_oc->objectID = objid; + object_oc->handle = handle; + object_oc->duration = duration; + facing_params->angle = angle; + facing_params->url = strdup(url); + + facing_string = make_oc_string(object_oc); + delete_oc(object_oc); + } + return facing_string; +} + +/* + ** make_facing_string(angle) + ** + ** Make a string specifying a facing angle. The handle will be + ** interpreted as a url. + ** + ** Caller owns allocated string memory. +*/ +char * make_facing_string(ObjectID objid, unsigned long handle, + unsigned long duration, int angle) +{ + char * facing_string = NULL; + oc * object_oc = new_oc(OCDT_OBJECT_FACING); + + if(object_oc) { + oc_facing_params * facing_params = + (oc_facing_params *)object_oc->data->parsed_data; + + object_oc->objectID = objid; + object_oc->handle = handle; + object_oc->duration = duration; + facing_params->angle = angle; + + facing_string = make_oc_string(object_oc); + delete_oc(object_oc); + } + return facing_string; +} + +/* + ** make_object_create_string(objid, objtype, objfile) + ** + ** Make a string to send to server to creation of a new object. + ** Used by client to tell server to create a new object, possibly + ** containing the drawing info file stored on the object. + ** obtype is a string naming the object type, which the server will + ** use to determine default drawing info if none found. objfile is + ** the file describing the object that the server will cache and use + ** to construct the object. + ** + ** Caller owns allocated string memory. +*/ + +char * make_object_create_string(ObjectID objid, char * objtype, char * objfile) +{ + char * create_string = NULL; + oc * object_create_oc = new_oc(OCDT_OBJECT_CREATE); + + if(object_create_oc) { + oc_objfile_params * create_params = + (oc_objfile_params *)object_create_oc->data->parsed_data; + create_params->objtype = strdup(objtype); + create_params->objfile = strdup(objfile); + object_create_oc->objectID = objid; + create_string = make_oc_string(object_create_oc); + delete_oc(object_create_oc); + } + return create_string; +} + +#ifdef GPROT_DEBUG +/* + ** make_robot_request_debug_string(name, password) + ** + ** Make a string to print debug info. + ** + ** Caller owns allocated string memory. +*/ +char * make_robot_request_debug_string(char * name, char * password) +{ + char * request_string = NULL; + oc * object_oc = new_oc(OCDT_EDIT_BOT_CREATE); + + if(object_oc) { + oc_bot_create_params * create_params = + (oc_bot_create_params *)object_oc->data->parsed_data; + create_params->object_name = strdup(name); + create_params->object_password = strdup(password); + object_oc->objectID = 0; /* request creation*/ + request_string = make_oc_debug_string(object_oc); + delete_oc(object_oc); + } + return request_string; +} + +/* + ** make_room_request_debug_string(name) + ** + ** Make a string to print debug info. + ** + ** Caller owns allocated string memory. +*/ +char * make_room_request_debug_string(char * name) +{ + char * request_string = NULL; + oc * object_oc = new_oc(OCDT_EDIT_ROOM_CREATE); + + if(object_oc) { + oc_room_create_params * create_params = + (oc_room_create_params *)object_oc->data->parsed_data; + create_params->object_name = strdup(name); + object_oc->objectID = 0; /* request creation*/ + request_string = make_oc_debug_string(object_oc); + delete_oc(object_oc); + } + return request_string; +} + +/* + ** make_exit_request_debug_string(name, source_roomid, dest_roomid) + ** + ** Make a string to print debug info. + ** + ** Caller owns allocated string memory. +*/ +char * make_exit_request_debug_string(char * name, ObjectID source_roomid, + ObjectID dest_roomid) +{ + char * request_string = NULL; + oc * object_oc = new_oc(OCDT_EDIT_EXIT_CREATE); + + if(object_oc) { + oc_exit_create_params * create_params = + (oc_exit_create_params *)object_oc->data->parsed_data; + create_params->object_name = strdup(name); + create_params->source_room = source_roomid; + create_params->dest_room = dest_roomid; + object_oc->objectID = 0; /* request creation*/ + request_string = make_oc_debug_string(object_oc); + delete_oc(object_oc); + } + return request_string; +} +/* + ** make_object_request_string(superclass, name) + ** + ** Make a string to print debug info. + ** + ** Caller owns allocated string memory. +*/ +char * make_object_request_debug_string(char * superclass, char * name) +{ + char * request_string = NULL; + oc * object_oc = new_oc(OCDT_EDIT_OBJECT_CREATE); + + if(object_oc) { + oc_obj_create_params * create_params = + (oc_obj_create_params *)object_oc->data->parsed_data; + create_params->superclass = strdup(superclass); + create_params->object_name = strdup(name); + object_oc->objectID = 0; /* request creation*/ + request_string = make_oc_debug_string(object_oc); + delete_oc(object_oc); + } + return request_string; +} + +/* + ** make_facing_edit_debug_string(angle, url) + ** + ** Make a string to print debug info. + ** + ** Caller owns allocated string memory. +*/ +char * make_facing_edit_debug_string(ObjectID objid, unsigned long handle, + unsigned long duration, int angle, char * url) +{ + char * facing_string = NULL; + oc * object_oc = new_oc(OCDT_EDIT_OBJECT_FACING); + + if(object_oc) { + oc_facing_edit_params * facing_params = + (oc_facing_edit_params *)object_oc->data->parsed_data; + + object_oc->objectID = objid; + object_oc->handle = handle; + object_oc->duration = duration; + facing_params->angle = angle; + facing_params->url = strdup(url); + + facing_string = make_oc_debug_string(object_oc); + delete_oc(object_oc); + } + return facing_string; +} + +/* + ** make_facing_debug_string(angle) + ** + ** Make a string to print debug info. + ** + ** Caller owns allocated string memory. +*/ +char * make_facing_debug_string(ObjectID objid, unsigned long handle, + unsigned long duration, int angle) +{ + char * facing_string = NULL; + oc * object_oc = new_oc(OCDT_OBJECT_FACING); + + if(object_oc) { + oc_facing_params * facing_params = + (oc_facing_params *)object_oc->data->parsed_data; + + object_oc->objectID = objid; + object_oc->handle = handle; + object_oc->duration = duration; + facing_params->angle = angle; + + facing_string = make_oc_debug_string(object_oc); + delete_oc(object_oc); + } + return facing_string; +} + +/* + ** make_object_create_debug_string(objid, objtype, objfile) + ** + ** Make a string to send to server to creation of a new object. + ** Used by client to tell server to create a new object, possibly + ** containing the drawing info file stored on the object. + ** obtype is a string naming the object type, which the server will + ** use to determine default drawing info if none found. objfile is + ** the file describing the object that the server will cache and use + ** to construct the object. + ** + ** Caller owns allocated string memory. +*/ + +char * make_object_create_debug_string(ObjectID objid, char * objtype, char * objfile) +{ + char * create_string = NULL; + oc * object_create_oc = new_oc(OCDT_OBJECT_CREATE); + + if(object_create_oc) { + oc_objfile_params * create_params = + (oc_objfile_params *)object_create_oc->data->parsed_data; + create_params->objtype = strdup(objtype); + create_params->objfile = strdup(objfile); + object_create_oc->objectID = objid; + create_string = make_oc_debug_string(object_create_oc); + delete_oc(object_create_oc); + } + return create_string; +} + + +#endif diff -U 2 -b -P -x config.h -x y.tab.c -x y.tab.h MOO-1.8.0r5/oc_data.h ehMOO.0.93.r5.codeonly/oc_data.h --- MOO-1.8.0r5/oc_data.h Wed Dec 31 18:00:00 1969 +++ ehMOO.0.93.r5.codeonly/oc_data.h Sat Feb 3 00:52:30 2001 @@ -0,0 +1,107 @@ +typedef struct oc_bot_create_params +{ + char * object_name; + char * object_password; +} oc_bot_create_params; + +typedef struct oc_room_create_params +{ + char * object_name; +} oc_room_create_params; + +typedef struct oc_room_edit_drawing_info_params +{ + char * drawing_info; +} oc_room_edit_drawing_info_params; + +typedef struct oc_room_edit_persistent_subscriber_params +{ + char * persistent_subscriber_list; +} oc_room_edit_persistent_subscriber_params; + +typedef struct oc_room_edit_description_params +{ + char * description; +} oc_room_edit_description_params; + +typedef struct oc_room_edit_name_params +{ + char * name; +} oc_room_edit_name_params; + +typedef struct oc_exit_create_params +{ + char * object_name; + ObjectID source_room; + ObjectID dest_room; +} oc_exit_create_params; + +typedef struct oc_portal_create_params +{ + char * to_dest_spec; + char * from_dest_spec; + ObjectID source_room; + ObjectID dest_room; +} oc_portal_create_params; + +typedef struct oc_obj_create_params +{ + char * superclass; + char * object_name; +} oc_obj_create_params; + +typedef struct oc_facing_edit_params +{ + int angle; + char * url; +} oc_facing_edit_params; + +/* used in oc having data type OCDT_CREATE_OBJECT to send complete */ +/* description of object in file form */ +/* type specifies the type of object to create in the display server */ +typedef struct oc_objfile_params +{ + char * objtype; + char * objfile; +} oc_objfile_params; + +/* used for finer granularity than obj_file, e.g. gestures */ +/* handle serves as the facing filename */ +typedef struct oc_facing_params +{ + int angle; +} oc_facing_params; + +#define server_newline '\n' +#define client_newline '|' + +oc * new_oc(oc_datatype datatype); +void delete_oc(oc * oc); +char * make_robot_request_string(char * name, char * password); +char * make_room_request_string(char * name); +char * make_exit_request_string(char * name, ObjectID source_roomid, + ObjectID dest_roomid); +char * make_object_request_string(char * superclass, char * name); +char * make_facing_edit_string(ObjectID objid, unsigned long handle, + unsigned long duration, int angle, char * url); +char * make_facing_string(ObjectID objid, unsigned long handle, + unsigned long duration, int angle); +char * make_object_create_string(ObjectID objid, char * objtype, + char * objfile); +#ifdef GPROT_DEBUG +char * make_robot_request_debug_string(char * name, char * password); +char * make_room_request_debug_string(char * name); +char * make_exit_request_debug_string(char * name, ObjectID source_roomid, + ObjectID dest_roomid); +char * make_object_request_debug_string(char * superclass, char * name); +char * make_facing_edit_debug_string(ObjectID objid, unsigned long handle, + unsigned long duration, int angle, char * url); +char * make_facing_debug_string(ObjectID objid, unsigned long handle, + unsigned long duration, int angle); +char * make_object_create_debug_string(ObjectID objid, char * objtype, + char * objfile); +#endif + +GPROT_ERR unparse_oc_data(oc * oc); +GPROT_ERR parse_oc_data(oc * oc); + diff -U 2 -b -P -x config.h -x y.tab.c -x y.tab.h MOO-1.8.0r5/oreg.c ehMOO.0.93.r5.codeonly/oreg.c --- MOO-1.8.0r5/oreg.c Wed Dec 31 18:00:00 1969 +++ ehMOO.0.93.r5.codeonly/oreg.c Sat Feb 3 00:52:22 2001 @@ -0,0 +1,56 @@ +/********************************************************************** + ** ehMOO object registration table + ** Copyright (c) 1996 by Tom Zanussi and Steve Albrecht +**********************************************************************/ + +#include +#include +#include +#include +#include + +#include "ll.h" +#include "hash.h" +#include "objtab.h" +#include "oreg.h" + +/********************************************************************** + ** This module contains the ehMOO code handling object registration +**********************************************************************/ + +/* + ** add_registered_object() + ** + ** Add a registered object to the table. +*/ +void add_registered_object(objTable * otab, OBJ_HANDLE h) +{ + objTable_addObjectNum(otab, h); +} + +/* + ** find_registered_object() + ** + ** Find a registered object id. If found return true, else false. +*/ +int find_registered_object(objTable * otab, OBJ_HANDLE h) +{ + void * foundItem = objTable_findObjectNum(otab, h); + if(foundItem) + return 1; + else + return 0; +} + +/* + ** delete_registered_object() + ** + ** Remove a registered object from the table. +*/ +void delete_registered_object(objTable * otab, OBJ_HANDLE h) +{ + if(find_registered_object(otab, h)) { + objTable_removeObjectNum(otab, h); + } +} + diff -U 2 -b -P -x config.h -x y.tab.c -x y.tab.h MOO-1.8.0r5/oreg.h ehMOO.0.93.r5.codeonly/oreg.h --- MOO-1.8.0r5/oreg.h Wed Dec 31 18:00:00 1969 +++ ehMOO.0.93.r5.codeonly/oreg.h Sat Feb 3 00:52:30 2001 @@ -0,0 +1,3 @@ +void add_registered_object(objTable * otab, OBJ_HANDLE h); +int find_registered_object(objTable * otab, OBJ_HANDLE h); +void delete_registered_object(objTable * otab, OBJ_HANDLE h); Only in MOO-1.8.0r5: parser.y Only in MOO-1.8.0r5: pgperf Only in MOO-1.8.0r5: restart Only in MOO-1.8.0r5: restart.sh diff -U 2 -b -P -x config.h -x y.tab.c -x y.tab.h MOO-1.8.0r5/server.c ehMOO.0.93.r5.codeonly/server.c --- MOO-1.8.0r5/server.c Sun Mar 2 23:03:52 1997 +++ ehMOO.0.93.r5.codeonly/server.c Sat Feb 3 00:52:22 2001 @@ -16,4 +16,12 @@ *****************************************************************************/ +/* + * eh Change History + * + * Revision 0.04 1996/03/31 11:13:38 trz + * Added support for eh Graphics Protocol. + * + */ + #include "my-types.h" /* must be first on some systems */ #include "my-signal.h" @@ -49,4 +57,11 @@ #include "execute.h" +#include "execute.h" + +#include "gprot_lambda.h" + +#include "objtab.h" +#include "oreg.h" + static pid_t parent_pid; int in_child = 0; @@ -69,4 +84,5 @@ time_t last_activity_time; Objid player; + Objid real_player; /* for graphics connections (-), associated player */ Objid listener; task_queue tasks; @@ -74,7 +90,25 @@ int outbound, binary; int print_messages; + objTable * registered_objects; + int negotiation_complete; + unsigned long negotiated_gprot_version; + unsigned long negotiated_gprot_display_type; + unsigned long last_version_proposed; + unsigned long last_display_type_proposed; + int got_initial_subscription; + int got_initial_oku; } shandle; static shandle *all_shandles = 0; +#define MAX_GRAPHICS_SESSIONS 256 +shandle * player_shandles[MAX_GRAPHICS_SESSIONS]; + +static shandle * find_shandle(Objid player); +static shandle * find_graphics_shandle_for_player(Objid player); +static shandle ** find_graphics_shandles_for_player(Objid player, + int *n_handles); +static void pn_propose(Objid graphics_player, + unsigned long version, unsigned long type); +extern unsigned long supported_gprot_servers; typedef struct slistener { @@ -92,4 +126,62 @@ {0}; +GPROT_ERR register_gprot_objects(Objid player, or * or) +{ + int i,n_handles; + shandle * h; + + shandle ** handles = find_graphics_shandles_for_player(player, &n_handles); + if(n_handles < 1) + return GE_SERVER_ERR; + + /* all graphics sessions should have the same set of objects registered */ + for(i=0;iargc ; i++) { + if(!objTable_findObjectNum(h->registered_objects, or->ObjectID[i])) { + objTable_addObjectNum(h->registered_objects, or->ObjectID[i]); + } + } + } + return GE_NONE; +} + +GPROT_ERR unregister_gprot_objects(Objid player, ou * ou) +{ + int i,n_handles; + shandle * h; + + shandle ** handles = find_graphics_shandles_for_player(player, &n_handles); + if(n_handles < 1) + return GE_SERVER_ERR; + + /* all graphics sessions should have the same set of objects registered */ + for(i=0;iargc ; i++) { + objTable_removeObjectNum(h->registered_objects, ou->ObjectID[i]); + } + } + return GE_NONE; +} + +int find_registered_gprot_object(Objid player, Objid object) +{ + shandle * h; + + /* All graphics sessions have the same set of objects registered. + Using any one of them here will do the job. */ + h = find_graphics_shandle_for_player(player); + if(!h) + return 0; + + if(objTable_findObjectNum(h->registered_objects, object)) + return 1; + else + return 0; +} + static void free_shandle(shandle * h) @@ -101,4 +193,6 @@ free_task_queue(h->tasks); + objTable_delete(h->registered_objects); + myfree(h, M_NETWORK); } @@ -379,4 +473,81 @@ } +int negotiation_complete(Objid graphics_player) +{ + shandle * h; + + h = find_shandle(graphics_player); + if(!h) + return 0; + + return h->negotiation_complete; +} + +int negotiated_version(Objid graphics_player) +{ + shandle * h; + + h = find_shandle(graphics_player); + if(!h) + return 0; + + return h->negotiated_gprot_version; +} + +GPROT_ERR handle_negotiation(Objid graphics_player, + unsigned long version, unsigned long type) +{ + shandle * h; + unsigned long max_version = (unsigned long)current_gprot_version; + unsigned long propose_version; + unsigned long propose_type; + + h = find_shandle(graphics_player); + if(!h) + return GE_SERVER_ERR; + if((version == h->last_version_proposed) && + (type == h->last_display_type_proposed)) { + /* we got a confirmation */ + h->negotiation_complete = 1; + h->negotiated_gprot_version = version; + h->negotiated_gprot_display_type = type; + /* finish the login and open the floodgates */ + call_notifier(h->real_player, + h->listener, "graphics_client_connected"); + return GE_NONE; /* we're done */ + } + + if((version <= max_version) && + (((type | supported_gprot_servers) == supported_gprot_servers))) { + /* we do support the version and type, resend as confirmation */ + h->negotiation_complete = 1; + h->negotiated_gprot_version = version; + h->negotiated_gprot_display_type = type; + /* finish the login and open the floodgates */ + call_notifier(h->real_player, + h->listener, "graphics_client_connected"); + return GE_NONE; /* we're done */ + } + + if(version <= max_version) { + /* we do support the proposed version, resend as confirmation */ + propose_version = version; + } + else if(version > max_version) { + /* the best we can do is max_version */ + propose_version = max_version; + } + + /* propose only the types requested that are the types we support */ + propose_type = type & supported_gprot_servers; + + h->last_version_proposed = propose_version; + h->last_display_type_proposed = propose_type; + + pn_propose(graphics_player, propose_version, propose_type); + + return GE_NONE; +} + int get_server_option(Objid oid, const char *name, Var * r) @@ -501,7 +672,10 @@ network_close(h->nhandle); free_shandle(h); - } else if (h->connection_time != 0 && !valid(h->player)) { + } else if (h->connection_time != 0 && + ((h->real_player && !valid(h->real_player)) || + (!h->real_player && !valid(h->player)))) { + /* graphics connections will fail valid() call */ oklog("RECYCLED: #%d on %s\n", - h->player, + h->real_player ? h->real_player : h->player, network_connection_name(h->nhandle)); if (h->print_messages) @@ -511,8 +685,33 @@ free_shandle(h); } else if (h->disconnect_me) { + if(h->real_player) { /* fix connect time */ + shandle * rh = find_shandle(h->real_player); + if(rh && (rh->connection_time > h->connection_time)) { + rh->connection_time = h->connection_time; + } + if(rh && (rh->last_activity_time > h->last_activity_time)) { + rh->last_activity_time = h->last_activity_time; + } + } else { + int i,n_handles; + shandle * gh; + shandle ** handles = find_graphics_shandles_for_player(h->player, &n_handles); + + for(i=0;iconnection_time > h->connection_time)) { + gh->connection_time = h->connection_time; + } + if(gh && (gh->last_activity_time > h->last_activity_time)) { + gh->last_activity_time = h->last_activity_time; + } + } + } + call_notifier(h->player, h->listener, "user_disconnected"); oklog("DISCONNECTED: %s on %s\n", - object_name(h->player), + object_name(h->real_player ? h->real_player : h->player), network_connection_name(h->nhandle)); if (h->print_messages) @@ -530,4 +729,41 @@ } +/* + * Graphics connections are handled by unlogged-in player connections + * attached to real player objects. Given a player Objid, return the + * unlogged-in player Objid. + */ +static shandle * +find_graphics_shandle_for_player(Objid player) +{ + shandle *h; + + for (h = all_shandles; h; h = h->next) + if (h->real_player == player) + return h; + + return 0; +} + +/* + * Graphics connections are handled by unlogged-in player connections + * attached to real player objects. Given a player Objid, return the + * unlogged-in player Objid. + */ +static shandle ** +find_graphics_shandles_for_player(Objid player, int *n_handles) +{ + shandle *h; + int i=0; + + for (h = all_shandles; h; h = h->next) + if (h->real_player == player) + player_shandles[i++] = h; + + *n_handles = i; + + return player_shandles; +} + static shandle * find_shandle(Objid player) @@ -958,4 +1194,5 @@ h->last_activity_time = time(0); h->player = next_unconnected_player--; + h->real_player = 0; h->listener = outbound ? SYSTEM_OBJECT : l->oid; h->tasks = new_task_queue(h->player, h->listener); @@ -964,4 +1201,12 @@ h->binary = 0; h->print_messages = (!outbound && l->print_messages); + h->registered_objects = objTable_new(NULL); + h->negotiation_complete = 0; + h->negotiated_gprot_version = 0; + h->negotiated_gprot_display_type = 0; + h->last_version_proposed = 0; + h->last_display_type_proposed = 0; + h->got_initial_subscription = 0; + h->got_initial_oku = 0; if (!outbound) @@ -1004,7 +1249,8 @@ { shandle *h = (shandle *) sh.ptr; + Objid player = h->real_player ? h->real_player : h->player; oklog("CLIENT DISCONNECTED: %s on %s\n", - object_name(h->player), + object_name(player), network_connection_name(h->nhandle)); h->disconnect_me = 1; @@ -1097,7 +1343,95 @@ } +/* Send text to player's graphics port */ +void +gnotify(Objid player, const char *message) +{ + int i,n_handles; + shandle * h; + shandle ** handles = find_graphics_shandles_for_player(player, &n_handles); + + for(i=0;inegotiated_gprot_version) + network_send_line(h->nhandle, message, 1); + } +} + +/* get current number of graphics connections */ +int +get_gconn_count(Objid player) +{ + int n_handles = 0; + find_graphics_shandles_for_player(player, &n_handles); + + return n_handles; +} + +/* Send text only to graphics player given */ +void +gnotify_only(Objid player, Objid only, const char *message) +{ + int i,n_handles; + shandle * h; + shandle ** handles = find_graphics_shandles_for_player(player, &n_handles); + + for(i=0;inegotiated_gprot_version && (h->player == only)) { + network_send_line(h->nhandle, message, 1); + return; + } + } +} + +/* Send text to player's graphics port, excluding graphics player given */ +void +gnotify_exclude(Objid player, Objid exclude, const char *message) +{ + int i,n_handles; + shandle * h; + shandle ** handles = find_graphics_shandles_for_player(player, &n_handles); + + for(i=0;inegotiated_gprot_version && (h->player != exclude)) + network_send_line(h->nhandle, message, 1); + } +} + +/* Send text to player's graphics port, version for protocol negotiation */ +static void +pn_gnotify(Objid graphics_player, const char *message) +{ + shandle *h = find_shandle(graphics_player); + + if (h) + network_send_line(h->nhandle, message, 1); +} + void boot_player(Objid player) { + int i,n_handles; + shandle *gh; + shandle *h = find_shandle(player); + shandle ** handles = find_graphics_shandles_for_player(player, &n_handles); + + if (h) + h->disconnect_me = 1; + + for(i=0;idisconnect_me = 1; + } +} + +void +boot_text_player(Objid player) +{ shandle *h = find_shandle(player); @@ -1107,4 +1441,13 @@ void +boot_graphics_player(Objid graphics_player) +{ + shandle *gh = find_shandle(graphics_player); + + if (gh) + gh->disconnect_me = 1; +} + +void write_active_connections(void) { @@ -1118,5 +1461,5 @@ for (h = all_shandles; h; h = h->next) - dbio_printf("%d %d\n", h->player, h->listener); + dbio_printf("%d %d %d\n", h->player, h->listener, h->real_player); } @@ -1146,10 +1489,13 @@ checkpointed_connections = new_list(count); for (i = 1; i <= count; i++) { - Objid who, listener; + Objid who, listener, real_who; Var v; - + /* is this ever FALSE? */ if (have_listeners) { - if (dbio_scanf("%d %d\n", &who, &listener) != 2) { - errlog("READ_ACTIVE_CONNECTIONS: Bad conn/listener pair.\n"); + int n_read = dbio_scanf("%d %d %d\n", &who, &listener, &real_who); + if (n_read == 2) { + real_who = 0; /* old format */ + } else if (!(n_read == 3)) { + errlog("READ_ACTIVE_CONNECTIONS: Bad conn/listener/gconn set.\n"); return 0; } @@ -1157,9 +1503,11 @@ who = dbio_read_num(); listener = SYSTEM_OBJECT; + real_who = 0; } - checkpointed_connections.v.list[i] = v = new_list(2); + checkpointed_connections.v.list[i] = v = new_list(3); v.v.list[1].type = v.v.list[2].type = TYPE_OBJ; v.v.list[1].v.obj = who; v.v.list[2].v.obj = listener; + v.v.list[3].v.obj = real_who; } @@ -1244,4 +1592,7 @@ reset_command_history(); + if(init_eh_graphics_protocol() != GE_NONE) + errlog("Couldn't init eh graphics protocol\n"); + if (!emergency || emergency_mode()) { if (!start_listener(l)) @@ -1257,4 +1608,279 @@ } +/* + * Associate an unlogged-in graphics connection with a real player + * object. + */ +static int +assoc_gplayer_with_real_player(Objid gplayer, Objid real_player) +{ + shandle *gplayer_h = find_shandle(gplayer); + shandle *real_player_h = find_shandle(real_player); + + if(real_player_h) /* player text-connected */ + network_send_line(real_player_h->nhandle, + "Graphics client connected", 1); + + if(!gplayer_h) + return 0; + + gplayer_h->real_player = real_player; + + return 1; +} + +/* + * Transfer a connection to another object. + */ +static +int transfer_connection_to_object(Objid player, Objid object) +{ + shandle *h = find_shandle(player); + + if(!h) + return 0; + + h->listener = object; + set_new_task_queue_handler(h->tasks,object); + + return 1; +} + +static +void pn_propose(Objid graphics_player, unsigned long version, unsigned long type) +{ + char * pn_string; + pn pn; + shandle *h = find_shandle(graphics_player); + + pn.protocol_version = version; + pn.server_type = type; + pn.argc = 2; + + pn_string = make_pn_string(&pn); + pn_gnotify(graphics_player, pn_string); + free(pn_string); + h->last_version_proposed = version; + h->last_display_type_proposed = type; +} + +/* + * Set the type of a connection e.g. TQ_GRAPHICS + * Called by $gprot_login:do_login_command + */ +static +int set_conn_type(Objid player, tq_type type) +{ + shandle *h = find_shandle(player); + + if(!h) + return 0; + + /* If this is a graphics connection, set connection_time + * to now. Text connections get set in player_connected */ + if(type == TQ_GRAPHICS) { + /* after protocol negotiation, graphics_client_connected */ + /* first proposal, try highest version we know of */ + /* client only sends version in first proposal */ + h->connection_time = time(0); + /* propose the highest version and all supported servers */ + pn_propose(h->player, (unsigned long)current_gprot_version, + supported_gprot_servers); + } + + set_task_queue_type(h->tasks, type); + + return 1; +} + +/* + * determine whether initial oku gotten + */ +int got_initial_oku(Objid graphics_player) +{ + shandle * sh = find_shandle(graphics_player); + if(sh) + return sh->got_initial_oku; + + return 0; +} + +/* + * determine whether initial oku gotten + */ +void initial_oku_gotten(Objid graphics_player) +{ + shandle * sh = find_shandle(graphics_player); + if(sh) + sh->got_initial_oku = 1; +} + +/* + * determine whether the given player is actually connected + */ +int text_player_connected(Objid player) +{ + shandle * sh = find_shandle(player); + + if(sh) + return 1; + else + return 0; +} + +/* + * determine whether initial subcsc + */ +int got_initial_subscription(Objid graphics_player) +{ + shandle * sh = find_shandle(graphics_player); + if(sh) + return sh->got_initial_subscription; + + return 0; +} + +/* + * determine whether initial subcsc + */ +void initial_subscription_gotten(Objid graphics_player) +{ + shandle * sh = find_shandle(graphics_player); + if(sh) + sh->got_initial_subscription = 1; +} + +/* + * Find the real player associated with a graphics connection + */ +static +Objid find_real_player(Objid graphics_player) +{ + shandle * sh = find_shandle(graphics_player); + if(sh) + return sh->real_player; + + return 0; +} + +/* + * Find a graphics connection associated with a real player. This + * should be used to get an _unspecified_ graphics player, to for + * instance determine if there are any graphics connections. + */ +static +Objid find_graphics_player(Objid real_player) +{ + shandle * sh = find_graphics_shandle_for_player(real_player); + if(sh) + return sh->player; + + return 0; +} + + +/* + * Pass graphics input to gprot handlers + */ + +extern GraphicsProtocol gprot; + +GPROT_ERR lambda_handle_graphics_input(Objid player, const char * input) +{ + GPROT_ERR err = GE_NONE; + shandle * sh = find_shandle(player); + if(sh) { + err = handle_graphics_input((ObjectID)sh->real_player, + GPROT_CLIENT, (void *)player, &gprot, input); + } + + return err; +} + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +/* find latest activity time for player of text and graphics */ +static time_t get_last_activity_time(Objid player) +{ + int i,n_handles; + shandle * gh; + + time_t last_activity_time=0; + shandle ** handles = find_graphics_shandles_for_player(player, &n_handles); + shandle *h = find_shandle(player); + + if(h) + last_activity_time = MAX(last_activity_time, h->last_activity_time); + + for(i=0;ilast_activity_time); + } + + return last_activity_time; +} + +/* find latest activity time for player of text and graphics */ +static time_t get_earliest_connection_time(Objid player) +{ + int i,n_handles; + shandle * gh; + + time_t connection_time=0; + shandle ** handles = find_graphics_shandles_for_player(player, &n_handles); + shandle *h = find_shandle(player); + + if(h) + connection_time = h->connection_time; + + for(i=0;iconnection_time) : gh->connection_time; + } + + return connection_time; +} + +/* get disconnect_me based on both text and graphics connections */ +static int get_disconnect_me(Objid player) +{ + int i,n_handles,graphics_disconnects=0 ; + shandle * gh; + + int disconnect_me=0; + shandle ** handles = find_graphics_shandles_for_player(player, &n_handles); + shandle *h = find_shandle(player); + + for(i=0;idisconnect_me) + graphics_disconnects++; + } + } + + if(h && (n_handles > 0)) { + if(h->disconnect_me && (graphics_disconnects == n_handles)) + disconnect_me = 1; + } + else if(h) { + disconnect_me = h->disconnect_me; + } + else if(graphics_disconnects == n_handles) { + disconnect_me = 1; + } + else + disconnect_me = 1; + + return disconnect_me; +} /**** built in functions ****/ @@ -1419,4 +2045,8 @@ count++; result.v.list[count].type = TYPE_OBJ; + /* need to use real_player for graphics connections */ + if(h->real_player) + result.v.list[count].v.obj = h->real_player; + else result.v.list[count].v.obj = h->player; } @@ -1430,9 +2060,14 @@ { /* (player) */ Var r; - shandle *h = find_shandle(arglist.v.list[1].v.obj); + time_t connection_time; + int disconnect_me; + Objid player = arglist.v.list[1].v.obj; + + connection_time = get_earliest_connection_time(player); + disconnect_me = get_disconnect_me(player); r.type = TYPE_INT; - if (h && h->connection_time != 0 && !h->disconnect_me) - r.v.num = time(0) - h->connection_time; + if (connection_time && !disconnect_me) + r.v.num = time(0) - connection_time; else r.v.num = -1; @@ -1448,9 +2083,14 @@ { /* (player) */ Var r; - shandle *h = find_shandle(arglist.v.list[1].v.obj); + time_t last_activity_time; + int disconnect_me; + Objid player = arglist.v.list[1].v.obj; + + last_activity_time = get_last_activity_time(player); + disconnect_me = get_disconnect_me(player); r.type = TYPE_INT; - if (h && !h->disconnect_me) - r.v.num = time(0) - h->last_activity_time; + if (!disconnect_me) + r.v.num = time(0) - last_activity_time; else r.v.num = -1; @@ -1487,4 +2127,31 @@ } +/* get the graphics connection name given a player # */ +static package +bf_graphics_connection_name(Var arglist, Byte next, void *vdata, Objid progr) +{ /* (player) */ + Objid who = arglist.v.list[1].v.obj; + Objid graphics_player = arglist.v.list[2].v.obj; + shandle *h = find_shandle(graphics_player); + const char *conn_name; + Var r; + + if (h && !h->disconnect_me) + conn_name = network_connection_name(h->nhandle); + else + conn_name = 0; + + free_var(arglist); + if (!is_wizard(progr) && progr != who) + return make_error_pack(E_PERM); + else if (!conn_name) + return make_error_pack(E_INVARG); + else { + r.type = TYPE_STR; + r.v.str = str_dup(conn_name); + return make_var_pack(r); + } +} + static package bf_notify(Var arglist, Byte next, void *vdata, Objid progr) @@ -1539,4 +2206,32 @@ static package +bf_boot_graphics_player(Var arglist, Byte next, void *vdata, Objid progr) +{ /* (object) */ + Objid oid = arglist.v.list[1].v.obj; + + free_var(arglist); + + if (oid != progr && !is_wizard(progr)) + return make_error_pack(E_PERM); + + boot_graphics_player(oid); + return no_var_pack(); +} + +static package +bf_boot_text_player(Var arglist, Byte next, void *vdata, Objid progr) +{ /* (object) */ + Objid oid = arglist.v.list[1].v.obj; + + free_var(arglist); + + if (oid != progr && !is_wizard(progr)) + return make_error_pack(E_PERM); + + boot_text_player(oid); + return no_var_pack(); +} + +static package bf_set_connection_option(Var arglist, Byte next, void *vdata, Objid progr) { /* (conn, option, value) */ @@ -1562,4 +2257,36 @@ } +/* Only good for this graphics session. Not saved */ +static package +bf_set_graphics_connection_option(Var arglist, Byte next, void *vdata, Objid progr) +{ /* (conn, option, value) */ + Objid oid = arglist.v.list[1].v.obj; + Objid graphics_player = arglist.v.list[2].v.obj; + const char *option = arglist.v.list[3].v.str; + Var value = arglist.v.list[4]; + shandle *h = find_shandle(graphics_player); + enum error e = E_NONE; + + if(!h) + { + free_var(arglist); + return make_error_pack(E_INVARG); + } + + if (oid != progr && !is_wizard(progr)) + e = E_PERM; + else if (!h || h->disconnect_me + || (!server_set_connection_option(h, option, value) + && !tasks_set_connection_option(h->tasks, option, value) + && !network_set_connection_option(h->nhandle, option, value))) + e = E_INVARG; + + free_var(arglist); + if (e == E_NONE) + return no_var_pack(); + else + return make_error_pack(e); +} + static package bf_connection_options(Var arglist, Byte next, void *vdata, Objid progr) @@ -1596,4 +2323,41 @@ } +/* Only good for this graphics session. Not saved */ +static package +bf_graphics_connection_options(Var arglist, Byte next, void *vdata, Objid progr) +{ /* (conn [, opt-name]) */ + Objid oid = arglist.v.list[1].v.obj; + Objid graphics_player = arglist.v.list[2].v.obj; + int nargs = arglist.v.list[0].v.num; + const char *oname = (nargs >= 3 ? arglist.v.list[3].v.str : 0); + shandle *h = find_shandle(graphics_player); + Var ans; + + if (!h || h->disconnect_me) { + free_var(arglist); + return make_error_pack(E_INVARG); + } else if (oid != progr && !is_wizard(progr)) { + free_var(arglist); + return make_error_pack(E_PERM); + } + + if (oname) { + if (!server_connection_option(h, oname, &ans) + && !tasks_connection_option(h->tasks, oname, &ans) + && !network_connection_option(h->nhandle, oname, &ans)) { + free_var(arglist); + return make_error_pack(E_INVARG); + } + } else { + ans = new_list(0); + ans = server_connection_options(h, ans); + ans = tasks_connection_options(h->tasks, ans); + ans = network_connection_options(h->nhandle, ans); + } + + free_var(arglist); + return make_var_pack(ans); +} + static slistener * find_slistener(Var desc) @@ -1701,4 +2465,187 @@ } +/* Send text over graphics connection */ +static package +bf_gnotify(Var arglist, Byte next, void *vdata, Objid progr) +{ /* (player, string) */ + + if (!is_wizard(progr) && progr != arglist.v.list[1].v.obj) { + free_var(arglist); + return make_error_pack(E_PERM); + } + + gnotify(arglist.v.list[1].v.obj, arglist.v.list[2].v.str); + free_var(arglist); + return no_var_pack(); +} + +/* Send text over graphics connection given in second */ +static package +bf_gnotify_only(Var arglist, Byte next, void *vdata, Objid progr) +{ /* (player, string) */ + + if (!is_wizard(progr) && progr != arglist.v.list[1].v.obj) { + free_var(arglist); + return make_error_pack(E_PERM); + } + + gnotify_only(arglist.v.list[1].v.obj, + arglist.v.list[2].v.obj, arglist.v.list[3].v.str); + free_var(arglist); + return no_var_pack(); +} + +/* Send text over graphics connection, excluding second */ +static package +bf_gnotify_exclude(Var arglist, Byte next, void *vdata, Objid progr) +{ /* (player, string) */ + + if (!is_wizard(progr) && progr != arglist.v.list[1].v.obj) { + free_var(arglist); + return make_error_pack(E_PERM); + } + + gnotify_exclude(arglist.v.list[1].v.obj, + arglist.v.list[2].v.obj, arglist.v.list[3].v.str); + free_var(arglist); + return no_var_pack(); +} + +/* associate (negative) gplayer with a real player Objid */ +static package +bf_new_gplayer(Var arglist, Byte next, void *vdata, Objid progr) +{ /* (player, string) */ + + if (!is_wizard(progr) && progr != arglist.v.list[1].v.obj) { + free_var(arglist); + return make_error_pack(E_PERM); + } + + if(!assoc_gplayer_with_real_player(arglist.v.list[1].v.obj, + arglist.v.list[2].v.obj)) { + return make_error_pack(E_INVARG); + } + + free_var(arglist); + return no_var_pack(); +} + +/* Transfer a connection from listening object to another.*/ +static package +bf_tx_conn_to_obj(Var arglist, Byte next, void *vdata, Objid progr) +{ /* (player, string) */ + + if (!is_wizard(progr) && progr != arglist.v.list[1].v.obj) { + free_var(arglist); + return make_error_pack(E_PERM); + } + + if(!transfer_connection_to_object(arglist.v.list[1].v.obj, + arglist.v.list[2].v.obj)) { + return make_error_pack(E_INVARG); + } + free_var(arglist); + return no_var_pack(); +} + +/* Set a connection type (COMMAND or GRAPHICS) */ +static package +bf_set_conn_type(Var arglist, Byte next, void *vdata, Objid progr) +{ /* (player, string) */ + + if (!is_wizard(progr) && progr != arglist.v.list[1].v.obj) { + free_var(arglist); + return make_error_pack(E_PERM); + } + + if(!set_conn_type(arglist.v.list[1].v.obj, + arglist.v.list[2].v.num)) { + return make_error_pack(E_INVARG); + } + free_var(arglist); + return no_var_pack(); +} + +/* Find the real player objid associated with graphical connection */ +static package +bf_find_real_player(Var arglist, Byte next, void *vdata, Objid progr) +{ /* (player, string) */ + Var r; + + if (!is_wizard(progr) && progr != arglist.v.list[1].v.obj) { + free_var(arglist); + return make_error_pack(E_PERM); + } + + r.type = TYPE_OBJ; + r.v.obj = find_real_player(arglist.v.list[1].v.obj); + + free_var(arglist); + return make_var_pack(r); +} + +/* Find the graphics player objid associated with real player connection */ +static package +bf_find_graphics_player(Var arglist, Byte next, void *vdata, Objid progr) +{ /* (player, string) */ + Var r; + + if (!is_wizard(progr) && progr != arglist.v.list[1].v.obj) { + free_var(arglist); + return make_error_pack(E_PERM); + } + + r.type = TYPE_OBJ; + r.v.obj = find_graphics_player(arglist.v.list[1].v.obj); + + free_var(arglist); + return make_var_pack(r); +} + +/* find out if the player has registered this object */ +static package +bf_find_registered_gprot_obj(Var arglist, Byte next, void *vdata, Objid progr) +{ /* (player, object) */ + Var v; + Objid player = arglist.v.list[1].v.obj; + Objid oid = arglist.v.list[2].v.obj; + + free_var(arglist); + + v.type = TYPE_INT; + v.v.num = find_registered_gprot_object(player, oid); + + return make_var_pack(v); +} + +static package +bf_get_gconn_count(Var arglist, Byte next, void *vdata, Objid progr) +{ /* (player) */ + Var r; + int gconn_count; + Objid player = arglist.v.list[1].v.obj; + + gconn_count = get_gconn_count(player); + + r.type = TYPE_INT; + r.v.num = gconn_count; + free_var(arglist); + + return make_var_pack(r); +} + +static package +bf_text_player_connected(Var arglist, Byte next, void *vdata, Objid progr) +{ /* (player) */ + Var r; + Objid player = arglist.v.list[1].v.obj; + + r.type = TYPE_INT; + r.v.num = text_player_connected(player); + free_var(arglist); + + return make_var_pack(r); +} + void register_server(void) @@ -1719,6 +2666,9 @@ register_function("idle_seconds", 1, 1, bf_idle_seconds, TYPE_OBJ); register_function("connection_name", 1, 1, bf_connection_name, TYPE_OBJ); + register_function("graphics_connection_name", 1, 1, bf_graphics_connection_name, TYPE_OBJ); register_function("notify", 2, 3, bf_notify, TYPE_OBJ, TYPE_STR, TYPE_ANY); register_function("boot_player", 1, 1, bf_boot_player, TYPE_OBJ); + register_function("boot_text_player", 1, 1, bf_boot_text_player, TYPE_OBJ); + register_function("boot_graphics_player", 1, 1, bf_boot_graphics_player, TYPE_OBJ); register_function("set_connection_option", 3, 3, bf_set_connection_option, TYPE_OBJ, TYPE_STR, TYPE_ANY); @@ -1727,4 +2677,10 @@ register_function("connection_options", 1, 1, bf_connection_options, TYPE_OBJ); + register_function("set_graphics_connection_option", 3, 3, bf_set_graphics_connection_option, + TYPE_OBJ, TYPE_STR, TYPE_ANY); + register_function("graphics_connection_option", 2, 2, bf_graphics_connection_options, + TYPE_OBJ, TYPE_STR); + register_function("graphics_connection_options", 1, 1, bf_graphics_connection_options, + TYPE_OBJ); register_function("listen", 2, 3, bf_listen, TYPE_OBJ, TYPE_ANY, TYPE_ANY); register_function("unlisten", 1, 1, bf_unlisten, TYPE_ANY); @@ -1732,4 +2688,25 @@ register_function("buffered_output_length", 0, 1, bf_buffered_output_length, TYPE_OBJ); + (void) register_function("gnotify", 2, 2, bf_gnotify, + TYPE_OBJ, TYPE_STR); + (void) register_function("gnotify_only", 3, 3, bf_gnotify_only, + TYPE_OBJ, TYPE_OBJ, TYPE_STR); + (void) register_function("gnotify_exclude", 3, 3, bf_gnotify_exclude, + TYPE_OBJ, TYPE_OBJ, TYPE_STR); + (void) register_function("new_gplayer", 2, 2, bf_new_gplayer, + TYPE_OBJ, TYPE_OBJ); + (void) register_function("tx_conn_to_obj", 2, 2, bf_tx_conn_to_obj, + TYPE_OBJ, TYPE_OBJ); + (void) register_function("set_conn_type", 2, 2, bf_set_conn_type, + TYPE_OBJ, TYPE_INT); + (void) register_function("find_real_player", 1, 1, bf_find_real_player, + TYPE_OBJ); + (void) register_function("find_graphics_player", 1, 1, bf_find_graphics_player, + TYPE_OBJ); + register_function("find_registered_gprot_obj", 2, 2, + bf_find_registered_gprot_obj, TYPE_OBJ, TYPE_OBJ); + register_function("get_gconn_count", 1, 1, bf_get_gconn_count, + TYPE_OBJ); + register_function("text_player_connected", 1, 1, bf_text_player_connected, TYPE_OBJ); } diff -U 2 -b -P -x config.h -x y.tab.c -x y.tab.h MOO-1.8.0r5/server.h ehMOO.0.93.r5.codeonly/server.h --- MOO-1.8.0r5/server.h Sun Mar 2 22:19:26 1997 +++ ehMOO.0.93.r5.codeonly/server.h Sat Feb 3 00:52:30 2001 @@ -16,4 +16,12 @@ *****************************************************************************/ +/* + * eh Change History + * + * Revision 0.04 1996/03/31 11:13:38 trz + * Added support for eh Graphics Protocol. + * + */ + /* server.h */ @@ -151,4 +159,21 @@ extern enum Fork_Result fork_server(const char *subtask_name); +#include "ll.h" +#include "hash.h" +#include "fntab.h" +#include "gprot.h" + +GPROT_ERR lambda_handle_graphics_input(Objid player, const char * input); +extern GPROT_ERR register_gprot_objects(Objid player, or * or); +extern GPROT_ERR unregister_gprot_objects(Objid player, ou * ou); +extern int find_registered_gprot_object(Objid player, Objid object); +extern GPROT_ERR handle_negotiation(Objid graphics_player, + unsigned long version, unsigned long type); +extern int negotiation_complete(Objid graphics_player); +extern int negotiated_version(Objid graphics_player); +extern void gnotify(Objid player, const char *message); +extern void boot_graphics_player(Objid graphics_player); +extern void pn_propose_version(Objid graphics_player, unsigned long version); + extern void player_connected(Objid old_id, Objid new_id, int is_newly_created); @@ -158,4 +183,11 @@ extern void write_active_connections(void); extern int read_active_connections(void); + +extern int got_initial_subscription(Objid graphics_player); +extern void initial_subscription_gotten(Objid graphics_player); +extern int got_initial_oku(Objid graphics_player); +extern void initial_oku_gotten(Objid graphics_player); +extern int get_gconn_count(Objid player); +extern int text_player_connected(Objid player); #endif /* Server_H */ diff -U 2 -b -P -x config.h -x y.tab.c -x y.tab.h MOO-1.8.0r5/tasks.c ehMOO.0.93.r5.codeonly/tasks.c --- MOO-1.8.0r5/tasks.c Sun Jul 6 22:24:55 1997 +++ ehMOO.0.93.r5.codeonly/tasks.c Sat Feb 3 00:52:22 2001 @@ -16,4 +16,12 @@ *****************************************************************************/ +/* + * eh Change History + * + * Revision 0.04 1996/03/31 11:13:38 trz + * Added support for eh Graphics Protocol. + * + */ + #include "my-string.h" #include "my-time.h" @@ -115,5 +123,5 @@ Objid program_object; const char *program_verb; - + tq_type type; char reading; /* boolean */ vm reading_vm; @@ -228,4 +236,6 @@ tq->last_input_task_id = 0; + tq->type = TQ_COMMAND; /* Always start out as command queue */ + return tq; } @@ -543,4 +553,9 @@ Objid old_max_object = db_last_used_objid(); + if(tq->type == TQ_GRAPHICS) { + lambda_handle_graphics_input(tq->player, command); + return 1; + } + result.type = TYPE_INT; /* In case #0:do_login_command does not exist * or does not immediately return. @@ -613,4 +628,28 @@ return result; +} + +/* + * Set a new handler for a task queue. For transferring connections + * from one object to another. + */ +void +set_new_task_queue_handler(task_queue q, Objid handler) +{ + tqueue *tq = (tqueue *) q.ptr; + + tq->handler = handler; +} + +/* + * Set the task queue type. For setting the type of a connection. + * e.g. from TQ_COMMAND to TQ_GRAPHICS. + */ +void +set_task_queue_type(task_queue q, tq_type type) +{ + tqueue *tq = (tqueue *)q.ptr; + + tq->type = type; } diff -U 2 -b -P -x config.h -x y.tab.c -x y.tab.h MOO-1.8.0r5/tasks.h ehMOO.0.93.r5.codeonly/tasks.h --- MOO-1.8.0r5/tasks.h Sun Mar 2 22:19:32 1997 +++ ehMOO.0.93.r5.codeonly/tasks.h Sat Feb 3 00:52:30 2001 @@ -16,4 +16,12 @@ *****************************************************************************/ +/* + * eh Change History + * + * Revision 0.04 1996/03/31 11:13:38 trz + * Added support for eh Graphics Protocol. + * + */ + #ifndef Tasks_H #define Tasks_H 1 @@ -27,4 +35,9 @@ } task_queue; +typedef enum { + TQ_COMMAND, /* Normal command queue */ + TQ_GRAPHICS /* Graphics command queue */ +} tq_type; + extern task_queue new_task_queue(Objid player, Objid handler); extern void free_task_queue(task_queue q); @@ -107,4 +120,8 @@ const char **message, const char **vname); +extern void set_new_task_queue_handler(task_queue q, + Objid handler); +extern void set_task_queue_type(task_queue q, + tq_type type); #endif /* !Tasks_H */