//***************************************************************************** // // pymudsys.c // // A set of system level commands and variables that may be needed by python, // but which are not neccessarily needed by scripts. // //***************************************************************************** #include <Python.h> #include <structmember.h> #include "../mud.h" #include "../utils.h" #include "../character.h" #include "../socket.h" #include "../save.h" #include "../handler.h" #include "../account.h" #include "pymudsys.h" #include "scripts.h" #include "pyplugs.h" #include "pychar.h" #include "pyaccount.h" #include "pysocket.h" //***************************************************************************** // local variables and functions //***************************************************************************** // a list of methods to add to the mudsys module LIST *pymudsys_methods = NULL; //***************************************************************************** // mudsys methods //***************************************************************************** PyObject *mudsys_set_sys_val(PyObject *self, PyObject *args) { char *key, *val; if(!PyArg_ParseTuple(args, "ss", &key, &val)) { PyErr_Format(PyExc_TypeError, "Provide a string key and value"); return NULL; } mudsettingSetString(key, val); return Py_BuildValue("i", 1); } PyObject *mudsys_get_sys_val(PyObject *self, PyObject *args) { char *key; if(!PyArg_ParseTuple(args, "s", &key)) { PyErr_Format(PyExc_TypeError, "Provide a string key"); return NULL; } return Py_BuildValue("s", mudsettingGetString(key)); } PyObject *mudsys_shutdown(PyObject *self, PyObject *args) { shut_down = TRUE; return Py_BuildValue("i", 1); } PyObject *mudsys_copyover(PyObject *self, PyObject *args) { do_copyover(); return Py_BuildValue("i", 1); } PyObject *mudsys_create_account(PyObject *self, PyObject *args) { char *name = NULL; if(!PyArg_ParseTuple(args, "s", &name)) { PyErr_Format(PyExc_TypeError, "A string name must be supplied."); return NULL; } if(account_exists(name)) return Py_BuildValue("O", Py_None); if(account_creating(name)) return Py_BuildValue("O", Py_None); ACCOUNT_DATA *acct = newAccount(); accountSetName(acct, name); return Py_BuildValue("O", accountGetPyFormBorrowed(acct)); } PyObject *mudsys_create_player(PyObject *Self, PyObject *args) { char *name = NULL; if(!PyArg_ParseTuple(args, "s", &name)) { PyErr_Format(PyExc_TypeError, "A string name must be supplied."); return NULL; } if(player_exists(name)) return Py_BuildValue("O", Py_None); if(player_creating(name)) return Py_BuildValue("O", Py_None); CHAR_DATA *ch = newChar(); charSetName(ch, name); // give the character a unique id int next_char_uid = mudsettingGetInt("puid") + 1; mudsettingSetInt("puid", next_char_uid); charSetUID(ch, next_char_uid); // if it's the first player, give him all priviledges if(charGetUID(ch) == 1) bitSet(charGetUserGroups(ch), "admin, builder, scripter, player, playtester"); char_exist(ch); return Py_BuildValue("O", charGetPyFormBorrowed(ch)); } PyObject *mudsys_player_exists(PyObject *self, PyObject *args) { char *name = NULL; if(!PyArg_ParseTuple(args, "s", &name)) { PyErr_Format(PyExc_TypeError, "A string name must be supplied."); return NULL; } return Py_BuildValue("i", player_exists(name)); } PyObject *mudsys_account_exists(PyObject *self, PyObject *args) { char *name = NULL; if(!PyArg_ParseTuple(args, "s", &name)) { PyErr_Format(PyExc_TypeError, "A string name must be supplied."); return NULL; } return Py_BuildValue("i", account_exists(name)); } PyObject *mudsys_player_creating(PyObject *self, PyObject *args) { char *name = NULL; if(!PyArg_ParseTuple(args, "s", &name)) { PyErr_Format(PyExc_TypeError, "A string name must be supplied."); return NULL; } return Py_BuildValue("i", player_creating(name)); } PyObject *mudsys_account_creating(PyObject *self, PyObject *args) { char *name = NULL; if(!PyArg_ParseTuple(args, "s", &name)) { PyErr_Format(PyExc_TypeError, "A string name must be supplied."); return NULL; } return Py_BuildValue("i", account_creating(name)); } // // registers a player into the system PyObject *mudsys_do_register(PyObject *Self, PyObject *args) { PyObject *val = NULL; CHAR_DATA *ch = NULL; ACCOUNT_DATA *acct = NULL; if(!PyArg_ParseTuple(args, "O", &val)) { PyErr_Format(PyExc_TypeError, "A char or account to be registered must be supplied."); return NULL; } if(PyChar_Check(val)) { if((ch = PyChar_AsChar(val)) == NULL) { PyErr_Format(PyExc_StandardError, "Tried to register nonexistant player, %d.", PyChar_AsUid(val)); return NULL; } if(!charIsNPC(ch)) register_player(ch); } else if(PyAccount_Check(val)) { if((acct = PyAccount_AsAccount(val)) == NULL) { PyErr_Format(PyExc_StandardError, "Tried to register nonexistant account."); return NULL; } register_account(acct); } else { PyErr_Format(PyExc_TypeError, "Only players and accounts may be registered."); return NULL; } return Py_BuildValue("i", 1); } // // saves a player to disk PyObject *mudsys_do_save(PyObject *self, PyObject *args) { PyObject *val = NULL; CHAR_DATA *ch = NULL; ACCOUNT_DATA *acct = NULL; if(!PyArg_ParseTuple(args, "O", &val)) { PyErr_Format(PyExc_TypeError, "A character or account must be supplied."); return NULL; } if(PyChar_Check(val)) { if( (ch = PyChar_AsChar(val)) == NULL) { PyErr_Format(PyExc_StandardError, "Tried to save nonexistant character, %d.", PyChar_AsUid(val)); return NULL; } // only save registered characters if(!player_exists(charGetName(ch))) return Py_BuildValue("i", 0); if(!charIsNPC(ch)) save_player(ch); } else if(PyAccount_Check(val)) { if( (acct = PyAccount_AsAccount(val)) == NULL) { PyErr_Format(PyExc_StandardError, "Tried to save nonexistant account."); return NULL; } // only save registered players if(!account_exists(accountGetName(acct))) return Py_BuildValue("i", 0); save_account(acct); } else { PyErr_Format(PyExc_TypeError, "Only characters and accounts may be saved."); return NULL; } return Py_BuildValue("i", 1); } // // attaches an account to a socket PyObject *mudsys_attach_account_socket(PyObject *self, PyObject *args) { PyObject *pyacct = NULL; PyObject *pysock = NULL; ACCOUNT_DATA *acct = NULL; SOCKET_DATA *sock = NULL; if(!PyArg_ParseTuple(args, "OO", &pyacct, &pysock)) { PyErr_Format(PyExc_TypeError,"An account and socket to be attached must be supplied."); return NULL; } if(!PyAccount_Check(pyacct)) { PyErr_Format(PyExc_TypeError, "First argument must be an account."); return NULL; } if(!PySocket_Check(pysock)) { PyErr_Format(PyExc_TypeError, "Second argument must be a socket."); return NULL; } if( (acct = PyAccount_AsAccount(pyacct)) == NULL) { PyErr_Format(PyExc_StandardError, "Tried to attach nonexistant account."); return NULL; } if( (sock = PySocket_AsSocket(pysock)) == NULL) { PyErr_Format(PyExc_StandardError, "Tried to attach nonexistant socket, %d.",PySocket_AsUid(pysock)); return NULL; } // first, do any nessessary detaching for our old character and old socket if(socketGetAccount(sock) != NULL && account_exists(accountGetName(socketGetAccount(sock)))) unreference_account(socketGetAccount(sock)); socketSetAccount(sock, acct); if(account_exists(accountGetName(acct))) reference_account(acct); return Py_BuildValue("i", 1); } // // attaches a character to a socket PyObject *mudsys_attach_char_socket(PyObject *self, PyObject *args) { PyObject *pych = NULL; PyObject *pysock = NULL; CHAR_DATA *ch = NULL; SOCKET_DATA *sock = NULL; if(!PyArg_ParseTuple(args, "OO", &pych, &pysock)) { PyErr_Format(PyExc_TypeError,"A character and socket to be attached must be supplied."); return NULL; } if(!PyChar_Check(pych)) { PyErr_Format(PyExc_TypeError, "First argument must be a character."); return NULL; } if(!PySocket_Check(pysock)) { PyErr_Format(PyExc_TypeError, "Second argument must be a socket."); return NULL; } if( (ch = PyChar_AsChar(pych)) == NULL) { PyErr_Format(PyExc_StandardError, "Tried to attach nonexistant character, %d.",PyChar_AsUid(pych)); return NULL; } if( (sock = PySocket_AsSocket(pysock)) == NULL) { PyErr_Format(PyExc_StandardError, "Tried to attach nonexistant socket, %d.",PySocket_AsUid(pysock)); return NULL; } // first, do any nessessary detaching for our old character and old socket if(socketGetChar(sock) != NULL) charSetSocket(socketGetChar(sock), NULL); if(charGetSocket(ch) != NULL) socketSetChar(charGetSocket(ch), NULL); charSetSocket(ch, sock); socketSetChar(sock, ch); return Py_BuildValue("i", 1); } // // detaches a character from its socket PyObject *mudsys_detach_char_socket(PyObject *self, PyObject *args) { PyObject *pych = NULL; CHAR_DATA *ch = NULL; SOCKET_DATA *sock = NULL; if(!PyArg_ParseTuple(args, "O", &pych)) { PyErr_Format(PyExc_TypeError,"A character to be detached must be supplied."); return NULL; } if(!PyChar_Check(pych)) { PyErr_Format(PyExc_TypeError, "Only characters may be detached."); return NULL; } if( (ch = PyChar_AsChar(pych)) == NULL) { PyErr_Format(PyExc_StandardError, "Tried to detach nonexistant character, %d.",PyChar_AsUid(pych)); return NULL; } sock = charGetSocket(ch); if(sock != NULL) socketSetChar(sock, NULL); charSetSocket(ch, NULL); return Py_BuildValue("i", 1); } // // quits a character from the game PyObject *mudsys_do_quit(PyObject *self, PyObject *args) { PyObject *pych = NULL; CHAR_DATA *ch = NULL; if(!PyArg_ParseTuple(args, "O", &pych)) { PyErr_Format(PyExc_TypeError,"A character to be quitted must be supplied."); return NULL; } if(!PyChar_Check(pych)) { PyErr_Format(PyExc_TypeError, "Only characters may be quitted."); return NULL; } if( (ch = PyChar_AsChar(pych)) == NULL) { PyErr_Format(PyExc_StandardError, "Tried to quit nonexistant character, %d.",PyChar_AsUid(pych)); return NULL; } if(!charIsNPC(ch) && charGetSocket(ch)) { SOCKET_DATA *sock = charGetSocket(ch); charSetSocket(ch, NULL); socketSetChar(sock, NULL); socketPopInputHandler(sock); extract_mobile(ch); } return Py_BuildValue("i", 1); } // // loads an account from disk PyObject *mudsys_load_account(PyObject *self, PyObject *args) { char *name = NULL; if(!PyArg_ParseTuple(args, "s", &name)) { PyErr_Format(PyExc_TypeError, "An account name must be supplied."); return NULL; } // newPyAccount increases the reference count on the account. We can // unreference it after we've created the Python wrapper for it ACCOUNT_DATA *acct = get_account(name); if(acct == NULL) return Py_BuildValue("O", Py_None); PyObject *retval = Py_BuildValue("O", accountGetPyFormBorrowed(acct)); unreference_account(acct); return retval; } // // loads a character from disk PyObject *mudsys_load_char(PyObject *self, PyObject *args) { char *name = NULL; if(!PyArg_ParseTuple(args, "s", &name)) { PyErr_Format(PyExc_TypeError, "A character name must be supplied."); return NULL; } CHAR_DATA *ch = get_player(name); if(ch == NULL) return Py_BuildValue("O", Py_None); char_exist(ch); return Py_BuildValue("O", charGetPyFormBorrowed(ch)); } // // tries to put the player into the game PyObject *mudsys_try_enter_game(PyObject *self, PyObject *args) { PyObject *pych = NULL; CHAR_DATA *ch = NULL; if(!PyArg_ParseTuple(args, "O", &pych)) { PyErr_Format(PyExc_TypeError,"A character to enter game must be supplied."); return NULL; } if(!PyChar_Check(pych)) { PyErr_Format(PyExc_TypeError, "Only characters may enter game."); return NULL; } if((ch = PyChar_AsChar(pych)) == NULL) { PyErr_Format(PyExc_StandardError, "Tried enter game with nonexistant character, %d.", PyChar_AsUid(pych)); return NULL; } // only enter game if we're not already in the game if(listIn(mobile_list, ch)) return Py_BuildValue("i", 0); else return Py_BuildValue("i", try_enter_game(ch)); } // // disconnects a character from its socket PyObject *mudsys_do_disconnect(PyObject *self, PyObject *args) { PyObject *pych = NULL; CHAR_DATA *ch = NULL; if(!PyArg_ParseTuple(args, "O", &pych)) { PyErr_Format(PyExc_TypeError,"A character to be dc'd must be supplied."); return NULL; } if(!PyChar_Check(pych)) { PyErr_Format(PyExc_TypeError, "Only characters may be dc'd."); return NULL; } if( (ch = PyChar_AsChar(pych)) == NULL) { PyErr_Format(PyExc_StandardError, "Tried to dc nonexistant character, %d.",PyChar_AsUid(pych)); return NULL; } if(charGetSocket(ch)) { SOCKET_DATA *sock = charGetSocket(ch); charSetSocket(ch, NULL); socketSetChar(sock, NULL); close_socket(sock, FALSE); } return Py_BuildValue("i", 1); } PyObject *mudsys_password_matches(PyObject *self, PyObject *args) { PyObject *pyacct = NULL; char *pwd = NULL; ACCOUNT_DATA *acct = NULL; if(!PyArg_ParseTuple(args, "Os", &pyacct, &pwd)) { PyErr_Format(PyExc_TypeError, "an account and password must be supplied."); return NULL; } if(!PyAccount_Check(pyacct)) { PyErr_Format(PyExc_TypeError, "only accounts may have passwords checked."); return NULL; } if( (acct = PyAccount_AsAccount(pyacct)) == NULL) { PyErr_Format(PyExc_StandardError, "Tried to check password for nonexistant account."); return NULL; } return Py_BuildValue("i", compares(crypt(pwd, accountGetName(acct)), accountGetPassword(acct))); } PyObject *mudsys_set_password(PyObject *self, PyObject *args) { PyObject *pyacct = NULL; char *pwd = NULL; ACCOUNT_DATA *acct = NULL; if(!PyArg_ParseTuple(args, "Os", &pyacct, &pwd)) { PyErr_Format(PyExc_TypeError, "an account and password must be supplied."); return NULL; } if(!PyAccount_Check(pyacct)) { PyErr_Format(PyExc_TypeError, "only accounts may have passwords set."); return NULL; } if( (acct = PyAccount_AsAccount(pyacct)) == NULL) { PyErr_Format(PyExc_StandardError, "Tried to set password for nonexistant account."); return NULL; } accountSetPassword(acct, crypt(pwd, accountGetName(acct))); return Py_BuildValue("i", 1); } // // add a new command to the mud, via a python script or module. Takes in a // command name, a sort_by command, the function, a minimum and maximum // position in the form of strings, a level, and boolean values for whether the // command can be performed by mobiles, and whether it interrupts actions. PyObject *mudsys_add_cmd(PyObject *self, PyObject *args) { PyObject *func = NULL; char *name = NULL, *sort_by = NULL, *min_pos = NULL, *max_pos = NULL, *group = NULL; bool mob_ok = FALSE, interrupts = FALSE; int min_pos_num, max_pos_num; // parse all of the values if (!PyArg_ParseTuple(args, "szOsssbb", &name, &sort_by, &func, &min_pos, &max_pos, &group, &mob_ok, &interrupts)) { PyErr_Format(PyExc_TypeError, "Could not add new command. Improper arguments supplied"); return NULL; } // get our positions min_pos_num = posGetNum(min_pos); max_pos_num = posGetNum(max_pos); if(min_pos_num == POS_NONE || max_pos_num == POS_NONE) { PyErr_Format(PyExc_TypeError, "Could not add new command. Invalid position names."); return NULL; } // add the command to the game add_py_cmd(name, sort_by, func, min_pos_num, max_pos_num, group, mob_ok, interrupts); return Py_BuildValue("O", Py_None); } // // removes a command from the game PyObject *mudsys_remove_cmd(PyObject *self, PyObject *args) { char *name = NULL; // parse all of the values if (!PyArg_ParseTuple(args, "s", &name)) { PyErr_Format(PyExc_TypeError, "function requires string argument."); return NULL; } remove_cmd(name); return Py_BuildValue("O", Py_None); } PyObject *mudsys_handle_cmd_input(PyObject *self, PyObject *args) { PyObject *pysock = NULL; SOCKET_DATA *sock = NULL; char *cmd = NULL; if(!PyArg_ParseTuple(args, "Os", &pysock, &cmd)) { PyErr_Format(PyExc_TypeError, "A socket and command must be supplied."); return NULL; } if(!PySocket_Check(pysock)) { PyErr_Format(PyExc_TypeError, "A socket must be supplied."); return NULL; } if( (sock = PySocket_AsSocket(pysock)) == NULL) { PyErr_Format(PyExc_StandardError, "Tried to run command for nonexistent socket."); return NULL; } handle_cmd_input(sock, cmd); return Py_BuildValue("i", 1); } PyObject *mudsys_show_prompt(PyObject *self, PyObject *args) { PyObject *pysock = NULL; SOCKET_DATA *sock = NULL; if(!PyArg_ParseTuple(args, "O", &pysock)) { PyErr_Format(PyExc_TypeError, "A socket must be supplied."); return NULL; } if(!PySocket_Check(pysock)) { PyErr_Format(PyExc_TypeError, "A socket must be supplied."); return NULL; } if( (sock = PySocket_AsSocket(pysock)) == NULL) { PyErr_Format(PyExc_StandardError, "Tried to show prompt to nonexistent socket."); return NULL; } show_prompt(sock); return Py_BuildValue("i", 1); } //***************************************************************************** // MudSys module //***************************************************************************** void PyMudSys_addMethod(const char *name, void *f, int flags, const char *doc) { // make sure our list of methods is created if(pymudsys_methods == NULL) pymudsys_methods = newList(); // make the Method def PyMethodDef *def = calloc(1, sizeof(PyMethodDef)); def->ml_name = strdup(name); def->ml_meth = (PyCFunction)f; def->ml_flags = flags; def->ml_doc = (doc ? strdup(doc) : NULL); listPut(pymudsys_methods, def); } PyMODINIT_FUNC init_PyMudSys(void) { // add all of our methods PyMudSys_addMethod("do_shutdown", mudsys_shutdown, METH_VARARGS, "shuts the mud down."); PyMudSys_addMethod("do_copyover", mudsys_copyover, METH_VARARGS, "performs a copyover on the mud."); PyMudSys_addMethod("sys_setval", mudsys_set_sys_val, METH_VARARGS, "sets a system value on the mud."); PyMudSys_addMethod("sys_getval", mudsys_get_sys_val, METH_VARARGS, "returns a system value on the mud."); PyMudSys_addMethod("player_exists", mudsys_player_exists, METH_VARARGS, "returns whether a player with the name exists."); PyMudSys_addMethod("account_exists", mudsys_account_exists, METH_VARARGS, "returns whether an account with the name exists."); PyMudSys_addMethod("player_creating", mudsys_player_creating, METH_VARARGS, "returns whether a player with the name is creating."); PyMudSys_addMethod("account_creating", mudsys_account_creating, METH_VARARGS, "returns whether an account with the name is creating."); PyMudSys_addMethod("do_register", mudsys_do_register, METH_VARARGS, "register a player to disk, and with an account."); PyMudSys_addMethod("load_char", mudsys_load_char, METH_VARARGS, "load a characer from disk"); PyMudSys_addMethod("load_account", mudsys_load_account, METH_VARARGS, "load an account from disk"); PyMudSys_addMethod("try_enter_game", mudsys_try_enter_game, METH_VARARGS, "Tries to put the character into the game world"); PyMudSys_addMethod("do_save", mudsys_do_save, METH_VARARGS, "save a character to disk"); PyMudSys_addMethod("do_quit", mudsys_do_quit, METH_VARARGS, "quit a character from game"); PyMudSys_addMethod("attach_account_socket",mudsys_attach_account_socket, METH_VARARGS, "attaches an account and socket."); PyMudSys_addMethod("attach_char_socket", mudsys_attach_char_socket, METH_VARARGS, "attaches a char and socket."); PyMudSys_addMethod("detach_char_socket", mudsys_detach_char_socket, METH_VARARGS, "detachs a char from a socket."); PyMudSys_addMethod("do_disconnect", mudsys_do_disconnect, METH_VARARGS, "disconnects a character from its socket"); PyMudSys_addMethod("password_matches", mudsys_password_matches, METH_VARARGS, "returns whether or not the password matches the account's" " password."); PyMudSys_addMethod("set_password", mudsys_set_password, METH_VARARGS, "sets an account's password."); PyMudSys_addMethod("add_cmd", mudsys_add_cmd, METH_VARARGS, "Add a new command to the game."); PyMudSys_addMethod("remove_cmd", mudsys_remove_cmd, METH_VARARGS, "Removes a command from the game."); PyMudSys_addMethod("handle_cmd_input", mudsys_handle_cmd_input, METH_VARARGS, "the default input handler for character commands."); PyMudSys_addMethod("show_prompt", mudsys_show_prompt, METH_VARARGS, "the default character prompt. Can be replaced in Python " "by assigning a new prompt to the same named variable."); PyMudSys_addMethod("create_account", mudsys_create_account, METH_VARARGS, "creates a new account by name. Must be registered " "after fully created."); PyMudSys_addMethod("create_player", mudsys_create_player, METH_VARARGS, "creates a new player by name. Must be registered " "after fully created."); Py_InitModule3("mudsys", makePyMethods(pymudsys_methods), "The mudsys module, for all MUD system utils."); }