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/
//*****************************************************************************
//
// pyauxiliary.c
//
// This is a wrapper around the auxiliary data system so python can make use
// of it. Allows python modules to install new auxiliary data on characters,
// rooms, objects, etc...
//
//*****************************************************************************

#include <Python.h>
#include <structmember.h>

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

#include "pystorage.h"



//*****************************************************************************
// local variables and datastructures
//*****************************************************************************

// the minimum size of our aux table
#define MIN_AUX_TABLE_SIZE       50

// holds a map from auxiliary data names to their prototype
HASHTABLE *aux_table = NULL;



//*****************************************************************************
// the wrapper layer between python and C auxiliary data
//*****************************************************************************
PyObject *newPyAuxiliaryData(const char *keyword) {
  // look up the prototype
  PyObject *proto = hashGet(aux_table, keyword);
  
  // make sure we've got an OK proto
  if(proto == NULL)
    return NULL;
  else {
    // create a new instance of the proto
    PyObject *instance = PyInstance_New(proto, NULL, NULL);
    return instance;
  }
}

void deletePyAuxiliaryData(PyObject *data) {
  Py_DECREF(data);
}

void pyAuxiliaryDataCopyTo(PyObject *from, PyObject *to) {
  PyObject *retval = PyObject_CallMethod(from, "copyTo", "O", to);
  Py_XDECREF(retval);
}

PyObject *pyAuxiliaryDataCopy(PyObject *data) {
  PyObject *retval = PyObject_CallMethod(data, "copy", NULL);
  return retval;
}

STORAGE_SET *pyAuxiliaryDataStore(PyObject *data) {
  PyObject  *pyset = PyObject_CallMethod(data, "store", NULL);
  STORAGE_SET *set = NULL;

  // make sure the set exists
  if(pyset == NULL || pyset == Py_None)
    set = new_storage_set();
  else
    set = PyStorageSet_AsSet(pyset);
  Py_XDECREF(pyset);
  return set;
}

PyObject *pyAuxiliaryDataRead(const char *keyword, STORAGE_SET *set) {
  // look up the prototype
  PyObject *proto = hashGet(aux_table, keyword);
  
  // make sure we've got an OK proto
  if(proto == NULL)
    return NULL;
  else {
    // build our arguments and keywords
    PyObject  *pystore = newPyStorageSet(set);
    PyObject     *args = Py_BuildValue("(O)", newPyStorageSet(set));
    PyObject *instance = PyInstance_New(proto, args, NULL);
    Py_DECREF(args);
    Py_DECREF(pystore);
    return instance;
  }
}



//*****************************************************************************
//  implementation of the pyauxiliary method 
//*****************************************************************************

//
// install new python auxiliary data. Auxiliary data must be a python CLASS
// OBJECT that has 4 functions:
//   __init__   this function initializes the auxiliary data. It takes an
//              optional argument that is a storage set which should be used
//              to initialize the values of the auxiliary data if it is supplied
//   copy       returns a copy of the auxiliary data
//   copyTo     the values of the auxiliary data to another auxiliary data
//              supplied as an argument to the function
//   store      returns a storage set representation of the auxiliary data
PyObject *PyAuxiliary_install(PyObject *self, PyObject *args) {
  PyObject   *proto = NULL; // the class proto
  char        *name = NULL; // the name of the auxiliary data
  char *installs_on = NULL; // a list of datatypes it installs onto
  bitvector_t  type = 0;    // bitvector representation of we we install on

  // try parsing the install
  if(!PyArg_ParseTuple(args, "sOs", &name, &proto, &installs_on)) {
    PyErr_Format(PyExc_TypeError,
		 "Installed auxiliaries require a name, a proto class, and "
		 "a comma-separated list of datatypes to install onto");
    return NULL;
  }

  // parse the data types that this auxiliary data installs to
  if(is_keyword(installs_on, "character", FALSE))
    SET_BIT(type, AUXILIARY_TYPE_CHAR);
  if(is_keyword(installs_on, "room",      FALSE))
    SET_BIT(type, AUXILIARY_TYPE_ROOM);
  if(is_keyword(installs_on, "object",    FALSE))
    SET_BIT(type, AUXILIARY_TYPE_OBJ);
  if(is_keyword(installs_on, "account",   FALSE))
    SET_BIT(type, AUXILIARY_TYPE_ACCOUNT);
  // more types to come soon!!
  //***********
  // FINISH ME
  //***********

  // add proto to our table
  Py_INCREF(proto);
  hashPut(aux_table, name, proto);
  AUXILIARY_FUNCS *funcs = newAuxiliaryFuncs(type, 
	newPyAuxiliaryData, deletePyAuxiliaryData,
	pyAuxiliaryDataCopyTo, pyAuxiliaryDataCopy,
	pyAuxiliaryDataStore, pyAuxiliaryDataRead);
  auxiliaryFuncSetIsPy(funcs, TRUE);
					     
  auxiliariesInstall(name, funcs);
  return Py_BuildValue("i", 1);
}

PyMethodDef pyauxiliary_module_methods[] = {
  { "install", PyAuxiliary_install, METH_VARARGS,
    "installs new python auxiliary data into the mud. Auxiliary Data must "
    "take the form of an uninstanced class that has a ClassXXX(set = None) "
    "init function, a copy() function, a copyTo(to) function, and a store() "
    "function" },
  {NULL, NULL, 0, NULL}  /* Sentinel */
};


//*****************************************************************************
// implementation of pyauxiliary.h
//*****************************************************************************

// initialize python auxiliary data for use
PyMODINIT_FUNC init_PyAuxiliary(void) {
  aux_table = newHashtableSize(MIN_AUX_TABLE_SIZE);
  Py_InitModule3("auxiliary", pyauxiliary_module_methods,
		 "The module for installing auxiliary data");
}

// returns TRUE if auxiliary data of the given name has been installed by python
bool pyAuxiliaryDataExists(const char *name) {
  return hashIn(aux_table, name);
}