nakedmudv3.3/
nakedmudv3.3/lib/
nakedmudv3.3/lib/logs/
nakedmudv3.3/lib/misc/
nakedmudv3.3/lib/players/
nakedmudv3.3/lib/txt/
nakedmudv3.3/lib/world/
nakedmudv3.3/lib/world/examples/
nakedmudv3.3/lib/world/examples/mproto/
nakedmudv3.3/lib/world/examples/oproto/
nakedmudv3.3/lib/world/examples/reset/
nakedmudv3.3/lib/world/examples/rproto/
nakedmudv3.3/lib/world/examples/trigger/
nakedmudv3.3/lib/world/limbo/
nakedmudv3.3/lib/world/limbo/room/
nakedmudv3.3/lib/world/limbo/rproto/
nakedmudv3.3/src/alias/
nakedmudv3.3/src/char_vars/
nakedmudv3.3/src/editor/
nakedmudv3.3/src/example_module/
nakedmudv3.3/src/help/
nakedmudv3.3/src/set_val/
nakedmudv3.3/src/socials/
nakedmudv3.3/src/time/
//*****************************************************************************
//
// auxiliary.c
//
// when installing a new module, it is often required that extra data be 
// stored in the basic datastructures (rooms, characters, objects, etc...). 
// However, we want to keep the modules as removed from the core of the MUD
// as possible, and having to put in extra data into the basic datastructures 
// seems like an undesirable thing. Provided below are a set of functions that 
// can be used for "installing" new data into the datastructures without having
// to directly edit the code.
//
//*****************************************************************************

#include "mud.h"
#include "utils.h"
#include "storage.h"
#include "auxiliary.h"


//*****************************************************************************
//
// local variables, datastructures, and functions
//
//*****************************************************************************

//
// the function sets used for loading and saving 
// auxiliary functions on our datatypes
HASHTABLE *auxiliary_manip_funcs = NULL;

struct auxiliary_functions {
  bitvector_t aux_type;
  bool           is_py;
  void          *(* new)(void);
  void        (* delete)(void *data);
  void        (* copyTo)(void *from, void *to);
  void        *(*  copy)(void *data);
  STORAGE_SET *(* store)(void *data);
  void        *(*  read)(STORAGE_SET *set);
};



//*****************************************************************************
//
// implementation of auxiliary.h
// documentation in auxiliary.h
//
//*****************************************************************************

void init_auxiliaries() {
  auxiliary_manip_funcs = newHashtable();
}

AUXILIARY_FUNCS *
newAuxiliaryFuncs(bitvector_t aux_type, void *new, void *delete, 
		  void *copyTo, void *copy, void *store, void *read) {
  AUXILIARY_FUNCS *newfuncs = malloc(sizeof(AUXILIARY_FUNCS));
  newfuncs->is_py    = FALSE;
  newfuncs->aux_type = aux_type;
  newfuncs->new      = new;
  newfuncs->delete   = delete;
  newfuncs->copyTo   = copyTo;
  newfuncs->copy     = copy;
  newfuncs->store    = store;
  newfuncs->read     = read;
  return newfuncs;
}

void
deleteAuxiliaryFuncs(AUXILIARY_FUNCS *funcs) {
  free(funcs);
}

void auxiliaryFuncSetIsPy(AUXILIARY_FUNCS *funcs, bool val) {
  funcs->is_py = val;
}

void
auxiliariesInstall(const char *name, AUXILIARY_FUNCS *funcs) {
  hashPut(auxiliary_manip_funcs, name, funcs);
}


void
auxiliariesUninstall(const char *name) {
  AUXILIARY_FUNCS *funcs = hashRemove(auxiliary_manip_funcs, name);
  if(funcs != NULL)
    deleteAuxiliaryFuncs(funcs);
}


AUXILIARY_FUNCS *
auxiliariesGetFuncs(const char *name) {
  return hashGet(auxiliary_manip_funcs, name);
}


HASHTABLE *
newAuxiliaryData(bitvector_t aux_type) {
  HASHTABLE        *data = newHashtable();
  HASH_ITERATOR  *hash_i = newHashIterator(auxiliary_manip_funcs);
  AUXILIARY_FUNCS *funcs = NULL;
  const char       *name = NULL;

  ITERATE_HASH(name, funcs, hash_i) {
    if(IS_SET(funcs->aux_type, aux_type)) {
      // are we dealing with python data or not?
      if(!funcs->is_py) 
	hashPut(data, name, funcs->new());
      else {
	// recast the new function
	void *(* new)(const char *) = (void *)funcs->new;
	hashPut(data, name, new(name));
      }
    }
  } deleteHashIterator(hash_i);
  return data;
}


void
auxiliaryEnsureDataComplete(HASHTABLE *data, bitvector_t aux_type) {
  HASH_ITERATOR  *hash_i = newHashIterator(auxiliary_manip_funcs);
  AUXILIARY_FUNCS *funcs = NULL;
  const char       *name = NULL;

  ITERATE_HASH(name, funcs, hash_i) {
    if(IS_SET(funcs->aux_type, aux_type) && !hashGet(data, name)) {
      // are we dealing with python data or not?
      if(!funcs->is_py) 
	hashPut(data, name, funcs->new());
      else {
	// recast the new function
	void *(* new)(const char *) = (void *)funcs->new;
	hashPut(data, name, new(name));
      }
    }
  } deleteHashIterator(hash_i);
}


void
deleteAuxiliaryData(HASHTABLE *data) {
  // go across all of the data in the hashtable, and delete it
  AUXILIARY_FUNCS *funcs  = NULL;
  HASH_ITERATOR   *hash_i = newHashIterator(data);
  void            *entry  = NULL;
  const char      *name   = NULL;

  ITERATE_HASH(name, entry, hash_i) {
    funcs = auxiliariesGetFuncs(name);
    funcs->delete(entry);
  } deleteHashIterator(hash_i);
  deleteHashtable(data);
}


STORAGE_SET *
auxiliaryDataStore(HASHTABLE *data) {
  STORAGE_SET *set = new_storage_set();
  AUXILIARY_FUNCS *funcs  = NULL;
  HASH_ITERATOR   *hash_i = newHashIterator(data);
  void            *entry  = NULL;
  const char      *name   = NULL;

  ITERATE_HASH(name, entry, hash_i) {
    funcs = auxiliariesGetFuncs(name);
    if(funcs->store) 
      store_set(set, name, funcs->store(entry));
  } deleteHashIterator(hash_i);
  return set;
}


HASHTABLE *
auxiliaryDataRead(STORAGE_SET *set, bitvector_t aux_type) {
  HASHTABLE        *data = newHashtable();
  HASH_ITERATOR  *hash_i = newHashIterator(auxiliary_manip_funcs);
  AUXILIARY_FUNCS *funcs = NULL;
  const char       *name = NULL;

  ITERATE_HASH(name, funcs, hash_i) {
    if(!IS_SET(funcs->aux_type, aux_type))
      continue;
    // are we dealing with python data or not?
    if(!funcs->is_py && funcs->read)
      hashPut(data, name, funcs->read(read_set(set, name)));
    else if(funcs->read) {
      // recast the read function
      void *(* read)(const char *, STORAGE_SET *) = (void *)funcs->read;
      hashPut(data, name, read(name, read_set(set, name)));
    }
    // are we dealing with python data or not?
    else if(!funcs->is_py) 
      hashPut(data, name, funcs->new());
    else {
      // recast the new function
      void *(* new)(const char *) = (void *)funcs->new;
      hashPut(data, name, new(name));
    }
  } deleteHashIterator(hash_i);
  return data;
}


void
auxiliaryDataCopyTo(HASHTABLE *from, HASHTABLE *to) {
  AUXILIARY_FUNCS *funcs = NULL;
  HASH_ITERATOR  *hash_i = NULL;
  void            *entry = NULL;
  const char       *name = NULL;

  // first, delete all of the old data
  if(hashSize(to) > 0) {
    hash_i = newHashIterator(to);
    ITERATE_HASH(name, entry, hash_i) {
      funcs = auxiliariesGetFuncs(name);
      funcs->delete(entry);
    } deleteHashIterator(hash_i);
  }

  // now, copy in all of the new data
  if(hashSize(from) > 0) {
    hash_i = newHashIterator(from);
    ITERATE_HASH(name, entry, hash_i) {
      funcs = auxiliariesGetFuncs(name);
      hashPut(to, name, funcs->copy(entry));
    } deleteHashIterator(hash_i);
  }
}


HASHTABLE *
auxiliaryDataCopy(HASHTABLE *data) {
  HASHTABLE *newdata = newHashtableSize(hashSize(data));
  auxiliaryDataCopyTo(data, newdata);
  return newdata;
}