123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442 |
- //*****************************************************************************
- //
- // zone.c
- //
- // A zone is like a stand-alone module, or encounter, within the game (e.g.
- // a city in the world), and contains all of the NPCs, objects, rooms, scripts,
- // etc... needed for the zone to be complete.
- //
- //*****************************************************************************
- #include <sys/stat.h>
- #include <dirent.h>
- #include "mud.h"
- #include "storage.h"
- #include "utils.h"
- #include "auxiliary.h"
- #include "world.h"
- #include "hooks.h"
- #include "zone.h"
- //*****************************************************************************
- // zone type data
- //*****************************************************************************
- typedef struct {
- /*
- void *(* read_func)(STORAGE_SET *);
- STORAGE_SET *(* store_func)(void *);
- void (* delete_func)(void *);
- void (* key_func)(void *, const char *);
- */
- void *read_func;
- void *store_func;
- void *delete_func;
- void *key_func;
- bool forgetful;
- HASHTABLE *key_map;
- char *type;
- } ZONE_TYPE_DATA;
- ZONE_TYPE_DATA *newZoneType(const char *type, void *reader, void *storer,
- void *deleter, void *keysetter, bool forgetful) {
- ZONE_TYPE_DATA *data = malloc(sizeof(ZONE_TYPE_DATA));
- data->read_func = reader;
- data->store_func = storer;
- data->delete_func = deleter;
- data->key_func = keysetter;
- data->forgetful = forgetful;
- data->key_map = newHashtable();
- data->type = strdupsafe(type);
- return data;
- }
- void *do_zone_read(ZONE_TYPE_DATA *tdata, STORAGE_SET *set) {
- if(tdata->forgetful) {
- void *(* read_func)(const char *, STORAGE_SET *) = tdata->read_func;
- return read_func(tdata->type, set);
- }
- else {
- void *(* read_func)(STORAGE_SET *) = tdata->read_func;
- return read_func(set);
- }
- }
- void do_zone_setkey(ZONE_TYPE_DATA *tdata, void *data, const char *key) {
- if(tdata->forgetful) {
- void (* key_func)(const char *, void *, const char *) = tdata->key_func;
- key_func(tdata->type, data, key);
- }
- else {
- void (* key_func)(void *, const char *) = tdata->key_func;
- key_func(data, key);
- }
- }
- STORAGE_SET *do_zone_store(ZONE_TYPE_DATA *tdata, void *data) {
- if(tdata->forgetful) {
- STORAGE_SET *(* store_func)(const char *, void *) = tdata->store_func;
- return store_func(tdata->type, data);
- }
- else {
- STORAGE_SET *(* store_func)(void *) = tdata->store_func;
- return store_func(data);
- }
- }
- //*****************************************************************************
- // zone data
- //*****************************************************************************
- struct zone_data {
- char *key;
- char *name;
- char *editors;
- BUFFER *desc;
- WORLD_DATA *world;
- LIST *resettable; // a list of rooms that need to be reset on pulse
- HASHTABLE *type_table; // a table of our types and their functions
- int pulse_timer; // the timer duration
- int pulse; // how far down have we gone?
- AUX_TABLE *auxiliary_data; // additional data installed on us
- };
- ZONE_DATA *newZone(const char *key) {
- ZONE_DATA *zone = malloc(sizeof(ZONE_DATA));
- zone->type_table = newHashtable();
- zone->name = strdup("");
- zone->key = strdup(key);
- zone->desc = newBuffer(1);
- zone->editors = strdup("");
- zone->resettable = newList();
- zone->pulse_timer = -1; // never resets
- zone->pulse = -1;
- zone->world = NULL;
- zone->auxiliary_data = newAuxiliaryData(AUXILIARY_TYPE_ZONE);
- return zone;
- }
- ZONE_DATA *zoneCopy(ZONE_DATA *zone) {
- ZONE_DATA *newzone = newZone(zone->key);
- zoneCopyTo(zone, newzone);
- return newzone;
- }
- void zoneCopyTo(ZONE_DATA *from, ZONE_DATA *to) {
- zoneSetName(to, zoneGetName(from));
- zoneSetDesc(to, zoneGetDesc(from));
- zoneSetEditors(to, zoneGetEditors(from));
- zoneSetKey(to, zoneGetKey(from));
- deleteListWith(to->resettable, free);
- to->resettable = listCopyWith(from->resettable, strdup);
- to->pulse_timer = from->pulse_timer;
- to->pulse = from->pulse;
- auxiliaryDataCopyTo(from->auxiliary_data, to->auxiliary_data);
- }
- void deleteZone(ZONE_DATA *zone){
- if(zone->name) free(zone->name);
- if(zone->desc) deleteBuffer(zone->desc);
- if(zone->editors) free(zone->editors);
- if(zone->type_table) deleteHashtable(zone->type_table);
- if(zone->key) free(zone->key);
- if(zone->resettable) deleteListWith(zone->resettable, free);
- deleteAuxiliaryData(zone->auxiliary_data);
- //*******************************************************************
- // The only time we're deleting a zone is when we're editing the copy
- // in OLC. So, We don't want to delete any of the zone's content when
- // we delete it.
- //*******************************************************************
-
- free(zone);
- }
- //
- // Pulse a zone. i.e. decrement it's reset timer. When the timer hits 0,
- // set it back to the max, and reset everything in the zone
- void zonePulse(ZONE_DATA *zone) {
- zone->pulse--;
- if(zone->pulse == 0) {
- zone->pulse = zone->pulse_timer;
- hookRun("reset_zone", hookBuildInfo("str", zoneGetKey(zone)));
- }
- }
- void zoneForceReset(ZONE_DATA *zone) {
- zone->pulse = 1;
- zonePulse(zone);
- }
- //
- // parses out one resettable room from a storage set
- char *read_resettable_room(STORAGE_SET *set) {
- return strdup(read_string(set, "room"));
- }
- ZONE_DATA *zoneLoad(WORLD_DATA *world, const char *key) {
- ZONE_DATA *zone = newZone(key);
- char fname[SMALL_BUFFER];
- zone->world = world;
- // first, load all of the zone data
- sprintf(fname, "%s/zone", worldGetZonePath(world, zone->key));
- STORAGE_SET *set = storage_read(fname);
- zone->pulse_timer = read_int (set, "pulse_timer");
- zoneSetName(zone, read_string(set, "name"));
- zoneSetDesc(zone, read_string(set, "desc"));
- zoneSetEditors(zone,read_string(set, "editors"));
-
- // add in all of our resettable rooms
- deleteList(zone->resettable);
- zone->resettable = gen_read_list(read_list(set, "resettable"),
- read_resettable_room);
- deleteAuxiliaryData(zone->auxiliary_data);
- zone->auxiliary_data = auxiliaryDataRead(read_set(set, "auxiliary"),
- AUXILIARY_TYPE_ZONE);
- storage_close(set);
- return zone;
- }
- //
- // turns an entry for a resettable room into a storage set
- STORAGE_SET *store_resettable_room(char *key) {
- STORAGE_SET *set = new_storage_set();
- store_string(set, "room", key);
- return set;
- }
- //
- // the new zone saving function
- bool zoneSave(ZONE_DATA *zone) {
- char fname[MAX_BUFFER];
-
- // first, for our zone data
- sprintf(fname, "%s/zone", worldGetZonePath(zone->world, zone->key));
- STORAGE_SET *set = new_storage_set();
- store_int (set, "pulse_timer", zone->pulse_timer);
- store_string(set, "name", zone->name);
- store_string(set, "desc", bufferString(zone->desc));
- store_string(set, "editors", zone->editors);
- store_set (set, "auxiliary", auxiliaryDataStore(zone->auxiliary_data));
- store_list (set, "resettable", gen_store_list(zone->resettable,
- store_resettable_room));
- storage_write(set, fname);
- storage_close(set);
- return TRUE;
- }
- //*****************************************************************************
- // get and set functions for zones
- //*****************************************************************************
- void *zoneGetAuxiliaryData(const ZONE_DATA *zone, char *name) {
- return auxiliaryGet(zone->auxiliary_data, name);
- }
- int zoneGetPulseTimer(ZONE_DATA *zone) {
- return zone->pulse_timer;
- }
- int zoneGetPulse(ZONE_DATA *zone) {
- return zone->pulse;
- }
- WORLD_DATA *zoneGetWorld(ZONE_DATA *zone) {
- return zone->world;
- }
- const char *zoneGetName(ZONE_DATA *zone) {
- return zone->name;
- }
- const char *zoneGetDesc(ZONE_DATA *zone) {
- return bufferString(zone->desc);
- }
- const char *zoneGetEditors(ZONE_DATA *zone) {
- return zone->editors;
- }
- BUFFER *zoneGetDescBuffer(ZONE_DATA *zone) {
- return zone->desc;
- }
- LIST *zoneGetResettable(ZONE_DATA *zone) {
- return zone->resettable;
- }
- void zoneSetPulseTimer(ZONE_DATA *zone, int timer) {
- // if we normally do not reset, change that
- if(zone->pulse_timer < 0)
- zone->pulse = timer;
- zone->pulse_timer = timer;
- }
- void zoneSetPulse(ZONE_DATA *zone, int pulse_left) {
- zone->pulse = pulse_left;
- }
- void zoneSetWorld(ZONE_DATA *zone, WORLD_DATA *world) {
- zone->world = world;
- }
- void zoneSetName(ZONE_DATA *zone, const char *name) {
- if(zone->name) free(zone->name);
- zone->name = strdupsafe(name);
- }
- void zoneSetDesc(ZONE_DATA *zone, const char *desc) {
- bufferClear(zone->desc);
- bufferCat(zone->desc, desc);
- }
- void zoneSetEditors(ZONE_DATA *zone, const char *names) {
- if(zone->editors) free(zone->editors);
- zone->editors = strdupsafe(names);
- }
- //*****************************************************************************
- // the new zone type interface
- //*****************************************************************************
- //
- // returns a list of all the keys in the zone for the specified type. Doesn't
- // include the locale in the key. Just the name. List and contents must be
- // deleted after use.
- LIST *zoneGetTypeKeys(ZONE_DATA *zone, const char *type) {
- LIST *key_list = newList();
- char path[MAX_BUFFER];
- sprintf(path, "%s/%s", worldGetZonePath(zone->world, zone->key), type);
- DIR *dir = opendir(path);
- struct dirent *entry = NULL;
- if(dir != NULL) {
- for(entry = readdir(dir); entry; entry = readdir(dir)) {
- if(!startswith(entry->d_name, "."))
- listPut(key_list, strdup(entry->d_name));
- }
- closedir(dir);
- }
- return key_list;
- }
- //
- // loads the item with the specified key into memory and returns it
- void *zoneLoadType(ZONE_DATA *zone, const char *type, const char *key) {
- ZONE_TYPE_DATA *tdata = hashGet(zone->type_table, type);
- if(tdata == NULL)
- return NULL;
- else {
- char buf[MAX_BUFFER];
- void *data = NULL;
- sprintf(buf, "%s/%s/%s", worldGetZonePath(zone->world, zone->key),
- type, key);
- STORAGE_SET *set = storage_read(buf);
- if(set != NULL) {
- data = do_zone_read(tdata, set);
- hashPut(tdata->key_map, key, data);
- do_zone_setkey(tdata, data, get_fullkey(key, zone->key));
- storage_close(set);
- }
- return data;
- }
- }
- void *zoneGetType(ZONE_DATA *zone, const char *type, const char *key) {
- ZONE_TYPE_DATA *tdata = hashGet(zone->type_table, type);
- if(tdata == NULL)
- return NULL;
- else {
- void *data = NULL;
- // if we haven't loaded it into memory yet, do so
- if((data = hashGet(tdata->key_map, key)) == NULL)
- data = zoneLoadType(zone, type, key);
- return data;
- }
- }
- void zoneSaveType(ZONE_DATA *zone, const char *type, const char *key) {
- void *data = zoneGetType(zone, type, key);
- if(data != NULL) {
- ZONE_TYPE_DATA *tdata = hashGet(zone->type_table, type);
- STORAGE_SET *set = do_zone_store(tdata, data);
- if(set != NULL) {
- char buf[MAX_BUFFER];
- sprintf(buf,"%s/%s/%s",worldGetZonePath(zone->world,zone->key),type,key);
- storage_write(set, buf);
- storage_close(set);
- }
- }
- }
- void *zoneRemoveType(ZONE_DATA *zone, const char *type, const char *key) {
- ZONE_TYPE_DATA *tdata = hashGet(zone->type_table, type);
- if(tdata == NULL)
- return NULL;
- else {
- // first, delete the file for it
- char buf[MAX_BUFFER];
- sprintf(buf, "%s/%s/%s",worldGetZonePath(zone->world,zone->key),type,key);
- unlink(buf);
- // then remove it from the key map
- void *data = hashRemove(tdata->key_map, key);
- if(data != NULL)
- do_zone_setkey(tdata, data, "");
- return data;
- }
- }
- void zonePutType(ZONE_DATA *zone, const char *type, const char *key,
- void *data) {
- ZONE_TYPE_DATA *tdata = hashGet(zone->type_table, type);
- if(tdata != NULL) {
- hashPut(tdata->key_map, key, data);
- do_zone_setkey(tdata, data, get_fullkey(key, zone->key));
- }
- }
- void zoneAddType(ZONE_DATA *zone, const char *type, void *reader,
- void *storer, void *deleter, void *typesetter) {
- if(!hashIn(zone->type_table, type)) {
- hashPut(zone->type_table, type, newZoneType(type, reader, storer, deleter,
- typesetter, FALSE));
- char buf[MAX_BUFFER];
- sprintf(buf, "%s/%s", worldGetZonePath(zone->world, zone->key), type);
- mkdir(buf, S_IRWXU | S_IRWXG);
- }
- }
- void zoneAddForgetfulType(ZONE_DATA *zone, const char *type, void *reader,
- void *storer, void *deleter, void *typesetter) {
- if(!hashIn(zone->type_table, type)) {
- hashPut(zone->type_table, type, newZoneType(type, reader, storer, deleter,
- typesetter, TRUE));
- char buf[MAX_BUFFER];
- sprintf(buf, "%s/%s", worldGetZonePath(zone->world, zone->key), type);
- mkdir(buf, S_IRWXU | S_IRWXG);
- }
- }
- void zoneSetKey(ZONE_DATA *zone, const char *key) {
- if(zone->key) free(zone->key);
- zone->key = strdupsafe(key);
- }
- const char *zoneGetKey(ZONE_DATA *zone) {
- return zone->key;
- }
|