/*****************************************************************************/ /* CFPython - A Python module for Crossfire RPG. */ /*****************************************************************************/ /* This is the third version of the Crossfire Scripting Engine. */ /* The first version used Guile. It was directly integrated in the server */ /* code, but since Guile wasn't perceived as an easy-to-learn, easy-to-use */ /* language by many, it was dropped in favor of Python. */ /* The second version, CFPython 1.0, was included as a plugin and provided */ /* just about the same level of functionality the current version has. But */ /* it used a rather counter-intuitive, procedural way of presenting things. */ /* */ /* CFPython 2.0 aims at correcting many of the design flaws crippling the */ /* older version. It is also the first plugin to be implemented using the */ /* new interface, that doesn't need awkward stuff like the horrible CFParm */ /* structure. For the Python writer, things should probably be easier and */ /* lead to more readable code: instead of writing "CFPython.getObjectXPos(ob)*/ /* he/she now can simply write "ob.X". */ /* */ /*****************************************************************************/ /* Please note that it is still very beta - some of the functions may not */ /* work as expected and could even cause the server to crash. */ /*****************************************************************************/ /* Version history: */ /* 0.1 "Ophiuchus" - Initial Alpha release */ /* 0.5 "Stalingrad" - Message length overflow corrected. */ /* 0.6 "Kharkov" - Message and Write correctly redefined. */ /* 0.7 "Koursk" - Setting informations implemented. */ /* 1.0a "Petersburg" - Last "old-fashioned" version, never submitted to CVS.*/ /* 2.0 "Arkangelsk" - First release of the 2.x series. */ /*****************************************************************************/ /* Version: 2.0beta8 (also known as "Alexander") */ /* Contact: yann.chachkoff@myrealbox.com */ /*****************************************************************************/ /* That code is placed under the GNU General Public Licence (GPL) */ /* (C)2001-2005 by Chachkoff Yann (Feel free to deliver your complaints) */ /*****************************************************************************/ /* CrossFire, A Multiplayer game for X-windows */ /* */ /* Copyright (C) 2000 Mark Wedel */ /* Copyright (C) 1992 Frank Tore Johansen */ /* */ /* This program is free software; you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* */ /*****************************************************************************/ /* First let's include the header file needed */ #include #include #define PYTHON_DEBUG /* give us some general infos out */ f_plug_api gethook; f_plug_api registerGlobalEvent; f_plug_api unregisterGlobalEvent; f_plug_api systemDirectory; f_plug_api reCmp; static void set_exception(const char *fmt, ...); static PyObject* createCFObject(PyObject* self, PyObject* args); static PyObject* createCFObjectByName(PyObject* self, PyObject* args); static PyObject* getCFPythonVersion(PyObject* self, PyObject* args); static PyObject* getReturnValue(PyObject* self, PyObject* args); static PyObject* setReturnValue(PyObject* self, PyObject* args); static PyObject* matchString(PyObject* self, PyObject* args); static PyObject* findPlayer(PyObject* self, PyObject* args); static PyObject* readyMap(PyObject* self, PyObject* args); static PyObject* getCostFlagTrue(PyObject* self, PyObject* args); static PyObject* getCostFlagBuy(PyObject* self, PyObject* args); static PyObject* getCostFlagSell(PyObject* self, PyObject* args); static PyObject* getCostFlagNoBargain(PyObject* self, PyObject* args); static PyObject* getCostFlagIdentified(PyObject* self, PyObject* args); static PyObject* getCostFlagNotCursed(PyObject* self, PyObject* args); static PyObject* getDirectionNorthEast(PyObject* self, PyObject* args); static PyObject* getDirectionEast(PyObject* self, PyObject* args); static PyObject* getDirectionSouthEast(PyObject* self, PyObject* args); static PyObject* getDirectionSouth(PyObject* self, PyObject* args); static PyObject* getDirectionSouthWest(PyObject* self, PyObject* args); static PyObject* getDirectionWest(PyObject* self, PyObject* args); static PyObject* getDirectionNorthWest(PyObject* self, PyObject* args); static PyObject* getDirectionNorth(PyObject* self, PyObject* args); static PyObject* getMapDirectory(PyObject* self, PyObject* args); static PyObject* getUniqueDirectory(PyObject* self, PyObject* args); static PyObject* getTempDirectory(PyObject* self, PyObject* args); static PyObject* getConfigDirectory(PyObject* self, PyObject* args); static PyObject* getLocalDirectory(PyObject* self, PyObject* args); static PyObject* getPlayerDirectory(PyObject* self, PyObject* args); static PyObject* getDataDirectory(PyObject* self, PyObject* args); static PyObject* getWhoAmI(PyObject* self, PyObject* args); static PyObject* getWhoIsActivator(PyObject* self, PyObject* args); static PyObject* getWhoIsThird(PyObject* self, PyObject* args); static PyObject* getWhatIsMessage(PyObject* self, PyObject* args); static PyObject* getScriptName(PyObject* self, PyObject* args); static PyObject* getScriptParameters(PyObject* self, PyObject* args); static PyObject* getPrivateDictionary(PyObject* self, PyObject* args); static PyObject* getSharedDictionary(PyObject* self, PyObject* args); static PyObject* getArchetypes(PyObject* self, PyObject* args); static PyObject* getMaps(PyObject* self, PyObject* args); static PyObject* getParties(PyObject* self, PyObject* args); static PyObject* getRegions(PyObject* self, PyObject* args); static PyObject* registerCommand(PyObject* self, PyObject* args); static PyObject* registerGEvent(PyObject* self, PyObject* args); static PyObject* unregisterGEvent(PyObject* self, PyObject* args); static PyObject* CFPythonError; PythonCmd CustomCommand[NR_CUSTOM_CMD]; /* Set up an Python exception object. */ static void set_exception(const char *fmt, ...) { char buf[1024]; va_list arg; va_start(arg, fmt); vsnprintf(buf, sizeof(buf), fmt, arg); va_end(arg); PyErr_SetString(PyExc_ValueError, buf); } static PyMethodDef CFPythonMethods[] = { {"WhoAmI", getWhoAmI, METH_VARARGS}, {"WhoIsActivator", getWhoIsActivator, METH_VARARGS}, {"WhoIsOther", getWhoIsThird, METH_VARARGS}, {"WhatIsMessage", getWhatIsMessage, METH_VARARGS}, {"ScriptName", getScriptName, METH_VARARGS}, {"ScriptParameters", getScriptParameters, METH_VARARGS}, {"MapDirectory", getMapDirectory, METH_VARARGS}, {"UniqueDirectory", getUniqueDirectory, METH_VARARGS}, {"TempDirectory", getTempDirectory, METH_VARARGS}, {"ConfigDirectory", getConfigDirectory, METH_VARARGS}, {"LocalDirectory", getLocalDirectory, METH_VARARGS}, {"PlayerDirectory", getPlayerDirectory, METH_VARARGS}, {"DataDirectory", getDataDirectory, METH_VARARGS}, {"DirectionNorth", getDirectionNorth, METH_VARARGS}, {"DirectionNorthEast", getDirectionNorthEast, METH_VARARGS}, {"DirectionEast", getDirectionEast, METH_VARARGS}, {"DirectionSouthEast", getDirectionSouthEast, METH_VARARGS}, {"DirectionSouth", getDirectionSouth, METH_VARARGS}, {"DirectionSouthWest", getDirectionSouthWest, METH_VARARGS}, {"DirectionWest", getDirectionWest, METH_VARARGS}, {"DirectionNorthWest", getDirectionNorthWest, METH_VARARGS}, {"CostFlagTrue", getCostFlagTrue, METH_VARARGS}, {"CostFlagBuy", getCostFlagBuy, METH_VARARGS}, {"CostFlagSell", getCostFlagSell, METH_VARARGS}, {"CostFlagNoBargain", getCostFlagNoBargain, METH_VARARGS}, {"CostFlagIdentified", getCostFlagIdentified, METH_VARARGS}, {"CostFlagNotCursed", getCostFlagNotCursed, METH_VARARGS}, {"ReadyMap", readyMap, METH_VARARGS}, {"FindPlayer", findPlayer, METH_VARARGS}, {"MatchString", matchString, METH_VARARGS}, {"GetReturnValue", getReturnValue, METH_VARARGS}, {"SetReturnValue", setReturnValue, METH_VARARGS}, {"PluginVersion", getCFPythonVersion, METH_VARARGS}, {"CreateObject", createCFObject, METH_VARARGS}, {"CreateObjectByName", createCFObjectByName, METH_VARARGS}, {"GetPrivateDictionary", getPrivateDictionary, METH_VARARGS}, {"GetSharedDictionary", getSharedDictionary, METH_VARARGS}, {"GetArchetypes", getArchetypes, METH_VARARGS}, {"GetMaps", getMaps, METH_VARARGS}, {"GetParties", getParties, METH_VARARGS}, {"GetRegions", getRegions, METH_VARARGS}, {"RegisterCommand", registerCommand, METH_VARARGS}, {"RegisterGlobalEvent", registerGEvent, METH_VARARGS}, {"UnregisterGlobalEvent",unregisterGEvent, METH_VARARGS}, {NULL, NULL, 0} }; CFPContext* context_stack; CFPContext* current_context; static int current_command = -999; static PyObject* shared_data = NULL; static PyObject* private_data = NULL; static PyObject* registerGEvent(PyObject* self, PyObject* args) { int eventcode; if (!PyArg_ParseTuple(args, "i", &eventcode)) return NULL; registerGlobalEvent(NULL, eventcode, PLUGIN_NAME, globalEventListener); Py_INCREF(Py_None); return Py_None; } static PyObject* unregisterGEvent(PyObject* self, PyObject* args) { int eventcode; if (!PyArg_ParseTuple(args, "i", &eventcode)) return NULL; unregisterGlobalEvent(NULL, EVENT_TELL, PLUGIN_NAME); Py_INCREF(Py_None); return Py_None; } static PyObject* createCFObject(PyObject* self, PyObject* args) { object* op; op = cf_create_object(); if (op == NULL) { Py_INCREF(Py_None); return Py_None; } return Crossfire_Object_wrap(op); } static PyObject* createCFObjectByName(PyObject* self, PyObject* args) { char* obname; object* op; if (!PyArg_ParseTuple(args, "s", &obname)) return NULL; op = cf_create_object_by_name(obname); if (op == NULL) { Py_INCREF(Py_None); return Py_None; } return Crossfire_Object_wrap(op); } static PyObject* getCFPythonVersion(PyObject* self, PyObject* args) { int i = 2044; if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("i", i); } static PyObject* getReturnValue(PyObject* self, PyObject* args) { if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("i", current_context->returnvalue); } static PyObject* setReturnValue(PyObject* self, PyObject* args) { int i; if (!PyArg_ParseTuple(args, "i", &i)) return NULL; current_context->returnvalue = i; Py_INCREF(Py_None); return Py_None; } static PyObject* matchString(PyObject* self, PyObject* args) { char *premiere; char *seconde; char *result; int val; if (!PyArg_ParseTuple(args, "ss", &premiere, &seconde)) return NULL; result = (char*) reCmp( &val, premiere, seconde ); if (result != NULL) return Py_BuildValue("i", 1); else return Py_BuildValue("i", 0); } static PyObject* findPlayer(PyObject* self, PyObject* args) { player *foundpl; char* txt; if (!PyArg_ParseTuple(args, "s", &txt)) return NULL; foundpl = cf_player_find(txt); if (foundpl != NULL) return Py_BuildValue("O", Crossfire_Object_wrap(foundpl->ob)); else { Py_INCREF(Py_None); return Py_None; } } static PyObject* readyMap(PyObject* self, PyObject* args) { char* mapname; mapstruct* map; if (!PyArg_ParseTuple(args, "s", &mapname)) return NULL; map = cf_map_get_map(mapname); if (map == NULL) { Py_INCREF(Py_None); return Py_None; } return Crossfire_Map_wrap(map); } static PyObject* getCostFlagTrue(PyObject* self, PyObject* args) { int i = F_TRUE; if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("i", i); } static PyObject* getCostFlagBuy(PyObject* self, PyObject* args) { int i = F_BUY; if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("i", i); } static PyObject* getCostFlagSell(PyObject* self, PyObject* args) { int i = F_SELL; if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("i", i); } static PyObject* getCostFlagNoBargain(PyObject* self, PyObject* args) { int i = F_NO_BARGAIN; if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("i", i); } static PyObject* getCostFlagIdentified(PyObject* self, PyObject* args) { int i = F_IDENTIFIED; if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("i", i); } static PyObject* getCostFlagNotCursed(PyObject* self, PyObject* args) { int i = F_NOT_CURSED; if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("i", i); } static PyObject* getDirectionNorthEast(PyObject* self, PyObject* args) { int i = 2; if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("i", i); } static PyObject* getDirectionEast(PyObject* self, PyObject* args) { int i = 3; if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("i", i); } static PyObject* getDirectionSouthEast(PyObject* self, PyObject* args) { int i = 4; if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("i", i); } static PyObject* getDirectionSouth(PyObject* self, PyObject* args) { int i = 5; if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("i", i); } static PyObject* getDirectionSouthWest(PyObject* self, PyObject* args) { int i = 6; if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("i", i); } static PyObject* getDirectionWest(PyObject* self, PyObject* args) { int i = 7; if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("i", i); } static PyObject* getDirectionNorthWest(PyObject* self, PyObject* args) { int i = 8; if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("i", i); } static PyObject* getDirectionNorth(PyObject* self, PyObject* args) { int i = 1; if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("i", i); } static PyObject* getMapDirectory(PyObject* self, PyObject* args) { int rv; if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("s", systemDirectory(&rv, 0)); } static PyObject* getUniqueDirectory(PyObject* self, PyObject* args) { int rv; if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("s", systemDirectory(&rv, 1)); } static PyObject* getTempDirectory(PyObject* self, PyObject* args) { int rv; if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("s", systemDirectory(&rv, 2)); } static PyObject* getConfigDirectory(PyObject* self, PyObject* args) { int rv; if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("s", systemDirectory(&rv, 3)); } static PyObject* getLocalDirectory(PyObject* self, PyObject* args) { int rv; if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("s", systemDirectory(&rv, 4)); } static PyObject* getPlayerDirectory(PyObject* self, PyObject* args) { int rv; if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("s", systemDirectory(&rv, 5)); } static PyObject* getDataDirectory(PyObject* self, PyObject* args) { int rv; if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("s", systemDirectory(&rv, 6)); } static PyObject* getWhoAmI(PyObject* self, PyObject* args) { if (!PyArg_ParseTuple(args, "", NULL)) return NULL; if (!current_context->who) { Py_INCREF(Py_None); return Py_None; } Py_INCREF(current_context->who); return current_context->who; } static PyObject* getWhoIsActivator(PyObject* self, PyObject* args) { if (!PyArg_ParseTuple(args, "", NULL)) return NULL; if (!current_context->activator) { Py_INCREF(Py_None); return Py_None; } Py_INCREF(current_context->activator); return current_context->activator; } static PyObject* getWhoIsThird(PyObject* self, PyObject* args) { if (!PyArg_ParseTuple(args, "", NULL)) return NULL; if (!current_context->third) { Py_INCREF(Py_None); return Py_None; } Py_INCREF(current_context->third); return current_context->third; } static PyObject* getWhatIsMessage(PyObject* self, PyObject* args) { if (!PyArg_ParseTuple(args, "", NULL)) return NULL; if (current_context->message == NULL) return Py_BuildValue(""); else return Py_BuildValue("s", current_context->message); } static PyObject* getScriptName(PyObject* self, PyObject* args) { if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("s", current_context->script); } static PyObject* getScriptParameters(PyObject* self, PyObject* args) { if (!PyArg_ParseTuple(args, "", NULL)) return NULL; return Py_BuildValue("s", current_context->options); } static PyObject* getPrivateDictionary(PyObject* self, PyObject* args) { PyObject* data; if (!PyArg_ParseTuple(args, "", NULL)) return NULL; data = PyDict_GetItemString(private_data, current_context->script); if (!data) { data = PyDict_New(); PyDict_SetItemString(private_data, current_context->script, data); Py_DECREF(data); } Py_INCREF(data); return data; } static PyObject* getSharedDictionary(PyObject* self, PyObject* args) { if (!PyArg_ParseTuple(args, "", NULL)) return NULL; Py_INCREF(shared_data); return shared_data; } static PyObject* getArchetypes(PyObject* self, PyObject* args) { PyObject* list; archetype* arch; list = PyList_New(0); arch = cf_archetype_get_first(); while (arch) { PyList_Append(list, Crossfire_Archetype_wrap(arch)); arch = cf_archetype_get_next(arch); } return list; } static PyObject* getMaps(PyObject* self, PyObject* args) { PyObject* list; mapstruct* map; list = PyList_New(0); map = cf_map_get_first(); while (map) { PyList_Append(list, Crossfire_Map_wrap(map)); map = (mapstruct*) cf_map_get_property(map, CFAPI_MAP_PROP_NEXT); } return list; } static PyObject* getParties(PyObject* self, PyObject* args) { PyObject* list; partylist* party; list = PyList_New(0); party = cf_party_get_first(); while (party) { PyList_Append(list, Crossfire_Party_wrap(party)); party = cf_party_get_next(party); } return list; } static PyObject* getRegions(PyObject* self, PyObject* args) { PyObject *list; region *reg; list = PyList_New(0); reg = cf_region_get_first(); while (reg) { PyList_Append(list, Crossfire_Region_wrap(reg)); reg = cf_region_get_next(reg); } return list; } static PyObject* registerCommand(PyObject* self, PyObject* args) { char *cmdname; char *scriptname; double cmdspeed; int i; if (!PyArg_ParseTuple(args, "ssd", &cmdname, &scriptname, &cmdspeed)) return NULL; if (cmdspeed < 0) { set_exception("speed must not be negative"); return NULL; } for (i = 0; i < NR_CUSTOM_CMD; i++) { if (CustomCommand[i].name != NULL) { if (!strcmp(CustomCommand[i].name, cmdname)) { set_exception("command '%s' is already registered", cmdname); return NULL; } } } for (i = 0; i < NR_CUSTOM_CMD; i++) { if (CustomCommand[i].name == NULL) { CustomCommand[i].name = cf_strdup_local(cmdname); CustomCommand[i].script = cf_strdup_local(scriptname); CustomCommand[i].speed = cmdspeed; break; } }; Py_INCREF(Py_None); return Py_None; } void initContextStack() { current_context = NULL; context_stack = NULL; } void pushContext(CFPContext* context) { if (current_context == NULL) { context_stack = context; context->down = NULL; } else { context->down = current_context; } current_context = context; } CFPContext* popContext() { CFPContext* oldcontext; if (current_context != NULL) { oldcontext = current_context; current_context = current_context->down; return oldcontext; } else return NULL; } void freeContext(CFPContext* context) { Py_XDECREF(context->who); Py_XDECREF(context->activator); Py_XDECREF(context->third); free(context); } static int do_script(CFPContext* context, int silent) { FILE* scriptfile; PyObject* dict; PyObject* ret; #if 0 PyObject* list; int item; #endif scriptfile = fopen(context->script, "r"); if (scriptfile == NULL) { if (!silent) printf( "cfpython - The Script file %s can't be opened\n", context->script); return 0; } pushContext(context); dict = PyDict_New(); PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins()); ret = PyRun_File(scriptfile, context->script, Py_file_input, dict, dict); if (PyErr_Occurred()) { PyErr_Print(); } Py_XDECREF(ret); #if 0 printf( "cfpython - %d items in heap\n", PyDict_Size(dict)); list = PyDict_Values(dict); for (item = PyList_Size(list) - 1; item >= 0; item--) { dict = PyList_GET_ITEM(list, item); ret = PyObject_Str(dict); printf(" ref %s = %d\n", PyString_AsString(ret), dict->ob_refcnt); Py_XDECREF(ret); } Py_DECREF(list); #endif Py_DECREF(dict); fclose(scriptfile); return 1; } extern "C" CF_PLUGIN int initPlugin(const char* iversion, f_plug_api gethooksptr) { PyObject *m, *d; int i; gethook = gethooksptr; printf("CFPython 2.0a init\n"); Py_Initialize(); Crossfire_ObjectType.tp_new = PyType_GenericNew; Crossfire_MapType.tp_new = PyType_GenericNew; Crossfire_PlayerType.tp_new = PyType_GenericNew; Crossfire_ArchetypeType.tp_new = PyType_GenericNew; Crossfire_PartyType.tp_new = PyType_GenericNew; Crossfire_RegionType.tp_new = PyType_GenericNew; PyType_Ready(&Crossfire_ObjectType); PyType_Ready(&Crossfire_MapType); PyType_Ready(&Crossfire_PlayerType); PyType_Ready(&Crossfire_ArchetypeType); PyType_Ready(&Crossfire_PartyType); PyType_Ready(&Crossfire_RegionType); m = Py_InitModule("Crossfire", CFPythonMethods); d = PyModule_GetDict(m); Py_INCREF(&Crossfire_ObjectType); Py_INCREF(&Crossfire_MapType); Py_INCREF(&Crossfire_PlayerType); Py_INCREF(&Crossfire_ArchetypeType); Py_INCREF(&Crossfire_PartyType); Py_INCREF(&Crossfire_RegionType); PyModule_AddObject(m, "Object", (PyObject*)&Crossfire_ObjectType); PyModule_AddObject(m, "Map", (PyObject*)&Crossfire_MapType); PyModule_AddObject(m, "Player", (PyObject*)&Crossfire_PlayerType); PyModule_AddObject(m, "Archetype", (PyObject*)&Crossfire_ArchetypeType); PyModule_AddObject(m, "Party", (PyObject*)&Crossfire_PartyType); PyModule_AddObject(m, "Region", (PyObject*)&Crossfire_RegionType); CFPythonError = PyErr_NewException("Crossfire.error", NULL, NULL); PyDict_SetItemString(d, "error", CFPythonError); for (i = 0; i < NR_CUSTOM_CMD; i++) { CustomCommand[i].name = NULL; CustomCommand[i].script = NULL; CustomCommand[i].speed = 0.0; } private_data = PyDict_New(); shared_data = PyDict_New(); return 0; } extern "C" CF_PLUGIN void* getPluginProperty(int* type, ...) { va_list args; const char* propname; int i; static CommArray_s rtn_cmd; va_start(args, type); propname = va_arg(args, const char *); if (!strcmp(propname, "command?")) { const char* cmdname; cmdname = va_arg(args, const char *); va_end(args); for (i = 0; i < NR_CUSTOM_CMD; i++) { if (CustomCommand[i].name != NULL) { if (!strcmp(CustomCommand[i].name, cmdname)) { rtn_cmd.name = CustomCommand[i].name; rtn_cmd.time = (float)CustomCommand[i].speed; rtn_cmd.func = runPluginCommand; current_command = i; return &rtn_cmd; } } } return NULL; } else if (!strcmp(propname, "Identification")) { va_end(args); return (void*) PLUGIN_NAME; } else if (!strcmp(propname, "FullName")) { va_end(args); return (void*) PLUGIN_VERSION; } return NULL; } extern "C" CF_PLUGIN int runPluginCommand(object* op, char* params) { char buf[1024]; CFPContext* context; static int rv = 0; rv = 0; if (current_command < 0) { printf("Illegal call of runPluginCommand, call find_plugin_command first.\n"); return 1; } snprintf(buf, sizeof(buf), "%s.py", cf_get_maps_directory(CustomCommand[current_command].script)); context = (CFPContext*) malloc(sizeof(CFPContext)); context->message[0] = 0; context->who = Crossfire_Object_wrap(op); context->activator = NULL; context->third = NULL; context->fix = 0; snprintf(context->script, sizeof(context->script), "%s", buf); snprintf(context->options, sizeof(context->options), "%s", params); context->returnvalue = 1; /* Default is "command successful" */ current_command = -999; if (!do_script(context, 0)) { freeContext(context); return rv; } context = popContext(); rv = context->returnvalue; freeContext(context); /* printf("Execution complete"); */ return rv; } extern "C" CF_PLUGIN int postInitPlugin() { int hooktype = 1; int rtype = 0; FILE* scriptfile; printf("CFPython 2.0a post init\n"); registerGlobalEvent = (void* (*)(int*, ...)) gethook(&rtype, hooktype, "cfapi_system_register_global_event"); unregisterGlobalEvent = (void* (*)(int*, ...))gethook(&rtype, hooktype, "cfapi_system_unregister_global_event"); systemDirectory = (void* (*)(int*, ...))gethook(&rtype, hooktype, "cfapi_system_directory"); reCmp = (void* (*)(int*, ...))gethook(&rtype, hooktype, "cfapi_system_re_cmp"); cf_init_plugin( gethook ); initContextStack(); registerGlobalEvent(NULL, EVENT_BORN, PLUGIN_NAME, globalEventListener); /*registerGlobalEvent(NULL, EVENT_CLOCK, PLUGIN_NAME, globalEventListener);*/ /*registerGlobalEvent(NULL, EVENT_CRASH, PLUGIN_NAME, globalEventListener);*/ registerGlobalEvent(NULL, EVENT_PLAYER_DEATH, PLUGIN_NAME, globalEventListener); registerGlobalEvent(NULL, EVENT_GKILL, PLUGIN_NAME, globalEventListener); registerGlobalEvent(NULL, EVENT_LOGIN, PLUGIN_NAME, globalEventListener); registerGlobalEvent(NULL, EVENT_LOGOUT, PLUGIN_NAME, globalEventListener); registerGlobalEvent(NULL, EVENT_MAPENTER, PLUGIN_NAME, globalEventListener); registerGlobalEvent(NULL, EVENT_MAPLEAVE, PLUGIN_NAME, globalEventListener); registerGlobalEvent(NULL, EVENT_MAPRESET, PLUGIN_NAME, globalEventListener); registerGlobalEvent(NULL, EVENT_REMOVE, PLUGIN_NAME, globalEventListener); registerGlobalEvent(NULL, EVENT_SHOUT, PLUGIN_NAME, globalEventListener); registerGlobalEvent(NULL, EVENT_TELL, PLUGIN_NAME, globalEventListener); registerGlobalEvent(NULL, EVENT_MUZZLE, PLUGIN_NAME, globalEventListener); registerGlobalEvent(NULL, EVENT_KICK, PLUGIN_NAME, globalEventListener); scriptfile = fopen(cf_get_maps_directory("python/events/python_init.py"), "r"); if (scriptfile != NULL) { PyRun_SimpleFile(scriptfile, cf_get_maps_directory("python/events/python_init.py")); fclose(scriptfile); } return 0; } extern "C" CF_PLUGIN void* globalEventListener(int* type, ...) { va_list args; static int rv = 0; CFPContext* context; Crossfire_Player* cfpl; Crossfire_Object* cfob; char* buf; player* pl; object* op; context = (CFPContext*) malloc(sizeof(CFPContext)); rv = 0; va_start(args, type); context->event_code = va_arg(args, int); context->message[0] = 0; context->who = NULL; context->activator = NULL; context->third = NULL; rv = context->returnvalue = 0; snprintf(context->script, sizeof(context->script), "%s", cf_get_maps_directory("python/events/python_event.py")); strcpy(context->options, ""); switch(context->event_code) { case EVENT_CRASH: printf( "Unimplemented for now\n"); break; case EVENT_BORN: op = va_arg(args, object*); context->activator = Crossfire_Object_wrap(op); snprintf(context->options, sizeof(context->options), "born"); cfob = (Crossfire_Object*)context->activator; break; case EVENT_PLAYER_DEATH: op = va_arg(args, object*); context->who = Crossfire_Object_wrap(op); snprintf(context->options, sizeof(context->options), "death"); cfob = (Crossfire_Object*)context->who; break; case EVENT_GKILL: op = va_arg(args, object*); context->who = Crossfire_Object_wrap(op); context->activator = Crossfire_Object_wrap(op); snprintf(context->options, sizeof(context->options), "gkill"); cfob = (Crossfire_Object*)context->who; break; case EVENT_LOGIN: pl = va_arg(args, player*); context->activator = Crossfire_Object_wrap(pl->ob); buf = va_arg(args, char*); if (buf != NULL) snprintf(context->message, sizeof(context->message), "%s", buf); snprintf(context->options, sizeof(context->options), "login"); cfpl = (Crossfire_Player*)context->activator; break; case EVENT_LOGOUT: pl = va_arg(args, player*); context->activator = Crossfire_Object_wrap(pl->ob); buf = va_arg(args, char*); if (buf != NULL) snprintf(context->message, sizeof(context->message), "%s", buf); snprintf(context->options, sizeof(context->options), "logout"); cfpl = (Crossfire_Player*)context->activator; break; case EVENT_REMOVE: op = va_arg(args, object*); context->activator = Crossfire_Object_wrap(op); snprintf(context->options, sizeof(context->options), "remove"); cfob = (Crossfire_Object*)context->activator; break; case EVENT_SHOUT: op = va_arg(args, object*); context->activator = Crossfire_Object_wrap(op); buf = va_arg(args, char*); if (buf != NULL) snprintf(context->message, sizeof(context->message), "%s", buf); snprintf(context->options, sizeof(context->options), "shout"); cfob = (Crossfire_Object*)context->activator; break; case EVENT_MUZZLE: op = va_arg(args, object*); context->activator = Crossfire_Object_wrap(op); buf = va_arg(args, char*); if (buf != NULL) snprintf(context->message, sizeof(context->message), "%s", buf); snprintf(context->options, sizeof(context->options), "muzzle"); cfob = (Crossfire_Object*)context->activator; break; case EVENT_KICK: op = va_arg(args, object*); context->activator = Crossfire_Object_wrap(op); buf = va_arg(args, char*); if (buf != NULL) snprintf(context->message, sizeof(context->message), "%s", buf); snprintf(context->options, sizeof(context->options), "kick"); cfob = (Crossfire_Object*)context->activator; break; case EVENT_MAPENTER: op = va_arg(args, object*); context->activator = Crossfire_Object_wrap(op); snprintf(context->options, sizeof(context->options), "mapenter"); cfob = (Crossfire_Object*)context->activator; break; case EVENT_MAPLEAVE: op = va_arg(args, object*); context->activator = Crossfire_Object_wrap(op); snprintf(context->options, sizeof(context->options), "mapleave"); cfob = (Crossfire_Object*)context->activator; break; case EVENT_CLOCK: snprintf(context->options, sizeof(context->options), "clock"); break; case EVENT_MAPRESET: buf = va_arg(args, char*); if (buf != NULL) snprintf(context->message, sizeof(context->message), "%s", buf); snprintf(context->options, sizeof(context->options), "mapreset"); break; case EVENT_TELL: snprintf(context->options, sizeof(context->options), "tell"); break; } va_end(args); context->returnvalue = 0; if (!do_script(context, 1)) { freeContext(context); return &rv; } context = popContext(); rv = context->returnvalue; freeContext(context); return &rv; } extern "C" CF_PLUGIN void* eventListener(int* type, ...) { static int rv = 0; va_list args; char* buf; CFPContext* context; rv = 0; context = (CFPContext*) malloc(sizeof(CFPContext)); context->message[0] = 0; va_start(args, type); context->who = Crossfire_Object_wrap(va_arg(args, object*)); context->event_code = va_arg(args, int); context->activator = Crossfire_Object_wrap(va_arg(args, object*)); context->third = Crossfire_Object_wrap(va_arg(args, object*)); buf = va_arg(args, char*); if (buf != NULL) snprintf(context->message, sizeof(context->message), "%s", buf); context->fix = va_arg(args, int); snprintf(context->script, sizeof(context->script), "%s", cf_get_maps_directory(va_arg(args, char*))); snprintf(context->options, sizeof(context->options), "%s", va_arg(args, char*)); context->returnvalue = 0; va_end(args); if (!do_script(context, 0)) { freeContext(context); return &rv; } context = popContext(); rv = context->returnvalue; freeContext(context); return &rv; } extern "C" CF_PLUGIN int closePlugin() { printf("CFPython 2.0a closing\n"); Py_Finalize(); return 0; }