/* hello.c - demonstration module */ /* $Id: hello.c,v 1.19 2001/12/13 04:39:28 dpassmor Exp $ */ #include "../../api.h" #define MOD_HELLO_HELLO_INFORMAL 1 #define MOD_HELLO_FOOF_SHOW 1 /* -------------------------------------------------------------------------- * Conf table. */ struct mod_hello_confstorage { int show_name; char *hello_string; int hello_times; } mod_hello_config; CONF mod_hello_conftable[] = { {(char *)"hello_shows_name", cf_bool, CA_GOD, CA_PUBLIC, (int *)&mod_hello_config.show_name, (long)"Greet players by name"}, {(char *)"hello_string", cf_string, CA_GOD, CA_WIZARD, (int *)&mod_hello_config.hello_string, MBUF_SIZE}, {(char *)"hello_times", cf_int, CA_GOD, CA_PUBLIC, (int *)&mod_hello_config.hello_times, 5}, { NULL, NULL, 0, 0, NULL, 0}}; /* -------------------------------------------------------------------------- * Database. */ unsigned int mod_hello_dbtype; typedef struct mod_hello_dbobj MOD_HELLO_OBJ; struct mod_hello_dbobj { int greeted; /* counter for @hello */ int foofed; /* counter for @foof */ }; MOD_HELLO_OBJ *mod_hello_db = NULL; #define OBJ_INIT_MODULE(x) \ mod_hello_db[x].greeted = 0; \ mod_hello_db[x].foofed = 0; void mod_hello_db_grow(newsize, newtop) int newsize, newtop; { DB_GROW_MODULE(mod_hello_db, newsize, newtop, MOD_HELLO_OBJ); } /* -------------------------------------------------------------------------- * API export. */ API_FUNCTION mod_hello_exports[] = { { "print_greeting", NULL }, { NULL, NULL }}; typedef struct greeting_input HI_INPUT; struct greeting_input { dbref player; char *name; }; typedef struct greeting_output HI_OUTPUT; struct greeting_output { int success_code; }; void mod_hello_print_greeting(in_ptr, out_ptr) void *in_ptr, *out_ptr; { dbref target; HI_INPUT *in_p; HI_OUTPUT *out_p; in_p = (HI_INPUT *) in_ptr; out_p = (HI_OUTPUT *) out_ptr; target = lookup_player(in_p->player, in_p->name, 0); if (target == NOTHING) { out_p->success_code = 0; return; } notify(target, "Greetings!"); out_p->success_code = 1; } /* -------------------------------------------------------------------------- * Handlers. */ int mod_hello_process_command(player, cause, interactive, command, args, nargs) dbref player, cause; int interactive; char *command, *args[]; int nargs; { /* Command intercept before normal matching */ if (!strcmp(command, "hiya")) { notify(player, "Got hiya."); return 1; } return 0; } int mod_hello_process_no_match(player, cause, interactive, lc_command, raw_command, args, nargs) dbref player, cause; int interactive; char *lc_command, *raw_command, *args[]; int nargs; { /* Command intercept before 'Huh?' */ if (!strcmp(lc_command, "heythere")) { notify(player, "Got heythere."); return 1; } return 0; } int mod_hello_did_it(player, thing, master, what, def, owhat, odef, awhat, now, args, nargs) dbref player, thing, master; int what, owhat, awhat, now, nargs; const char *def, *odef; char *args[]; { /* Demonstrate the different ways we can intercept did_it() calls. * * We intercept 'look' (by trapping A_DESC), and return a message of * our own, preventing other modules from showing something, and * preventing the normal server defaults from being run. (Return 1.) * * We intercept 'move' (by trapping A_MOVE), and return a message of * our own, but don't prevent other modules from doing something, * or preventing the normal server defaults from being run. (Return 0.) * * We intercept 'use' (by trapping A_USE), and return a message * of our own. We prevent other modules from doing something, but * not the normal server defaults from being run. (Return -1.) * * If we don't get one of these, we just pass. (Return 0.) */ int f, g; switch (what) { case A_DESC: f = mod_hello_db[thing].foofed; g = mod_hello_db[thing].greeted; notify(player, tprintf("%s has been greeted %d %s and foofed %d %s.", Name(thing), g, ((g == 1) ? "time" : "times"), f, ((f == 1) ? "time" : "times"))); return 1; break; /* NOTREACHED */ case A_MOVE: notify(GOD, tprintf("%s(#%d) just moved.", Name(thing), thing)); return 0; break; /* NOTREACHED */ case A_USE: notify(GOD, tprintf("%s(#%d) was used!", Name(thing), thing)); return -1; break; /* NOTREACHED */ default: return 0; } } void mod_hello_create_obj(player, obj) dbref player, obj; { notify(player, tprintf("You created #%d -- hello says so.", obj)); } void mod_hello_destroy_obj(player, obj) dbref player, obj; { notify(GOD, tprintf("Destroyed #%d -- hello says so.", obj)); } void mod_hello_destroy_player(player, victim) dbref player, victim; { notify(player, tprintf("Say goodbye to %s!", Name(victim))); } void mod_hello_announce_connect(player, reason, num) dbref player; const char *reason; int num; { notify(GOD, tprintf("%s(#%d) just connected -- hello says so.", Name(player), player)); } void mod_hello_announce_disconnect(player, reason, num) dbref player; const char *reason; int num; { notify(GOD, tprintf("%s(#%d) just disconnected -- hello says so.", Name(player), player)); } void mod_hello_examine(player, cause, thing, control, key) dbref player, cause, thing; int control, key; { if (control) { notify(player, tprintf("Greeted: %d Foofed: %d", mod_hello_db[thing].greeted, mod_hello_db[thing].foofed)); } } /* -------------------------------------------------------------------------- * Commands. */ DO_CMD_NO_ARG(mod_hello_do_hello) { int i; if (key & MOD_HELLO_HELLO_INFORMAL) { for (i = 0; i < mod_hello_config.hello_times; i++) notify(player, "Hi there!"); } else { if (mod_hello_config.show_name) notify(player, tprintf("Hello, %s!", Name(player))); else notify(player, mod_hello_config.hello_string); } mod_hello_db[player].greeted += 1; notify(player, tprintf("You have been greeted %d times.", mod_hello_db[player].greeted)); } DO_CMD_ONE_ARG(mod_hello_do_foof) { DBData dbkey; DBData data; /* Demonstrate what we can do: * @foof greets you with a generic message. * * @foof <message> greets you with a customized message that is * preserved in the database. * * @foof/show will show you the message you were last 'foofed' with. * This illustrates the use of the database cache. */ /* Set up our DB key. We'll either be getting, adding or deleting an * entry */ dbkey.dptr = &player; dbkey.dsize = sizeof(dbref); if (key & MOD_HELLO_FOOF_SHOW) { data = cache_get(dbkey, mod_hello_dbtype); if (data.dptr) { notify(player, tprintf("You were last foofed with: %s", data.dptr)); } else { notify(player, "You have not been foofed with a message."); } return; } if (arg1 && *arg1) { notify(player, tprintf("Yay: \"%s\"", arg1)); /* Set up data and store it in cache */ data.dptr = XSTRDUP(arg1, "mod_hello_do_foof"); data.dsize = strlen(arg1) + 1; cache_put(dbkey, data, mod_hello_dbtype); } else { notify(player, "Yay."); /* Delete the entry from cache if it exists */ cache_del(dbkey, mod_hello_dbtype); } mod_hello_db[player].foofed += 1; notify(player, tprintf("You have been foofed %d times.", mod_hello_db[player].foofed)); } NAMETAB mod_hello_hello_sw[] = { {(char *)"informal", 1, CA_PUBLIC, MOD_HELLO_HELLO_INFORMAL}, { NULL, 0, 0, 0}}; NAMETAB mod_hello_foof_sw[] = { {(char *)"show", 1, CA_PUBLIC, MOD_HELLO_FOOF_SHOW}, { NULL, 0, 0, 0}}; CMDENT mod_hello_cmdtable[] = { {(char *)"@hello", mod_hello_hello_sw, CA_PUBLIC, 0, CS_NO_ARGS, NULL, NULL, NULL, {mod_hello_do_hello}}, {(char *)"@foof", mod_hello_foof_sw, CA_PUBLIC, 0, CS_ONE_ARG, NULL, NULL, NULL, {mod_hello_do_foof}}, {(char *)NULL, NULL, 0, 0, 0, NULL, NULL, NULL, {NULL}}}; /* -------------------------------------------------------------------------- * Functions. */ FUNCTION(mod_hello_fun_hello) { safe_str("Hello, world!", buff, bufc); } FUNCTION(mod_hello_fun_hi) { /* Normally we would not call our own API, but here's just an * example. */ static void (*handler)(void *, void *) = NULL; HI_INPUT in_info; HI_OUTPUT out_info; if (!handler) handler = request_api_function("hi", "print_greeting"); if (!handler) { safe_str("#-1 API FUNCTION MISSING", buff, bufc); return; } in_info.player = player; in_info.name = fargs[0]; handler(&in_info, &out_info); if (out_info.success_code == 0) safe_str("#-1 NO SUCH PLAYER", buff, bufc); } FUN mod_hello_functable[] = { {"HELLO", mod_hello_fun_hello, 0, 0, CA_PUBLIC, NULL}, {"HI", mod_hello_fun_hi, 1, 0, CA_PUBLIC, NULL}, {NULL, NULL, 0, 0, 0, NULL}}; /* -------------------------------------------------------------------------- * Hash tables. * (We don't use any of this data. It's just here for demo purposes.) */ HASHTAB mod_hello_greetings; HASHTAB mod_hello_farewells; MODHASHES mod_hello_hashtable[] = { { "Hello greetings", &mod_hello_greetings, 5, 8}, { "Hello farewells", &mod_hello_farewells, 15, 32}, { NULL, NULL, 0, 0}}; NHSHTAB mod_hello_numbers; MODNHASHES mod_hello_nhashtable[] = { { "Hello numbers", &mod_hello_numbers, 5, 16}, { NULL, NULL, 0, 0}}; /* -------------------------------------------------------------------------- * Initialization. */ void mod_hello_init() { /* Give our configuration some default values. */ mod_hello_config.show_name = 0; mod_hello_config.hello_string = XSTRDUP("Hello, world!", "mod_hello_init"); mod_hello_config.hello_times = 1; /* Register everything we have to register. */ register_hashtables(mod_hello_hashtable, mod_hello_nhashtable); register_commands(mod_hello_cmdtable); register_functions(mod_hello_functable); register_api("hello", "hi", mod_hello_exports); } void mod_hello_cleanup_startup() { mod_hello_dbtype = register_dbtype("hello"); } /* -------------------------------------------------------------------------- * Database routines: read and write a flatfile at db conversion time. */ void mod_hello_db_write_flatfile(f) FILE *f; { unsigned int dbtype; dbref thing; DBData key; DBData data; /* Find out our dbtype */ mod_hello_dbtype = register_dbtype("hello"); /* Write out our version number */ fprintf(f, "+V1\n"); DO_WHOLE_DB(thing) { key.dptr = &thing; key.dsize = sizeof(dbref); data = cache_get(key, mod_hello_dbtype); if (data.dptr) { fprintf(f, "!%d\n", thing); putstring(f, data.dptr); } } fputs("***END OF DUMP***\n", f); } void mod_hello_db_read_flatfile(f) FILE *f; { unsigned int dbtype, version; char c; dbref thing; DBData key; DBData data; /* Find out our dbtype */ mod_hello_dbtype = register_dbtype("hello"); /* Load entries */ while(1) { switch(c = getc(f)) { case '+': /* Header */ switch(c = getc(f)) { case 'V': /* Version number */ version = getref(f); break; default: (void)getstring_noalloc(f, 1); } break; case '!': /* DBref */ thing = getref(f); /* Grab the string and put it in cache */ data.dptr = XSTRDUP(getstring_noalloc(f, 1), "mod_hello_db_read_flatfile"); data.dsize = strlen(data.dptr) + 1; key.dptr = &thing; key.dsize = sizeof(dbref); cache_put(key, data, mod_hello_dbtype); break; case '*': /* EOF marker */ return; } } }