Crossfire Server, Branch 1.12
R12190
|
00001 /*****************************************************************************/ 00002 /* CFPython - A Python module for Crossfire RPG. */ 00003 /*****************************************************************************/ 00004 /* This is the third version of the Crossfire Scripting Engine. */ 00005 /* The first version used Guile. It was directly integrated in the server */ 00006 /* code, but since Guile wasn't perceived as an easy-to-learn, easy-to-use */ 00007 /* language by many, it was dropped in favor of Python. */ 00008 /* The second version, CFPython 1.0, was included as a plugin and provided */ 00009 /* just about the same level of functionality the current version has. But */ 00010 /* it used a rather counter-intuitive, procedural way of presenting things. */ 00011 /* */ 00012 /* CFPython 2.0 aims at correcting many of the design flaws crippling the */ 00013 /* older version. It is also the first plugin to be implemented using the */ 00014 /* new interface, that doesn't need awkward stuff like the horrible CFParm */ 00015 /* structure. For the Python writer, things should probably be easier and */ 00016 /* lead to more readable code: instead of writing "CFPython.getObjectXPos(ob)*/ 00017 /* he/she now can simply write "ob.X". */ 00018 /* */ 00019 /*****************************************************************************/ 00020 /* Please note that it is still very beta - some of the functions may not */ 00021 /* work as expected and could even cause the server to crash. */ 00022 /*****************************************************************************/ 00023 /* Version history: */ 00024 /* 0.1 "Ophiuchus" - Initial Alpha release */ 00025 /* 0.5 "Stalingrad" - Message length overflow corrected. */ 00026 /* 0.6 "Kharkov" - Message and Write correctly redefined. */ 00027 /* 0.7 "Koursk" - Setting informations implemented. */ 00028 /* 1.0a "Petersburg" - Last "old-fashioned" version, never submitted to CVS.*/ 00029 /* 2.0 "Arkangelsk" - First release of the 2.x series. */ 00030 /*****************************************************************************/ 00031 /* Version: 2.0beta8 (also known as "Alexander") */ 00032 /* Contact: yann.chachkoff@myrealbox.com */ 00033 /*****************************************************************************/ 00034 /* That code is placed under the GNU General Public Licence (GPL) */ 00035 /* (C)2001-2005 by Chachkoff Yann (Feel free to deliver your complaints) */ 00036 /*****************************************************************************/ 00037 /* CrossFire, A Multiplayer game for X-windows */ 00038 /* */ 00039 /* Copyright (C) 2000 Mark Wedel */ 00040 /* Copyright (C) 1992 Frank Tore Johansen */ 00041 /* */ 00042 /* This program is free software; you can redistribute it and/or modify */ 00043 /* it under the terms of the GNU General Public License as published by */ 00044 /* the Free Software Foundation; either version 2 of the License, or */ 00045 /* (at your option) any later version. */ 00046 /* */ 00047 /* This program is distributed in the hope that it will be useful, */ 00048 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ 00049 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ 00050 /* GNU General Public License for more details. */ 00051 /* */ 00052 /* You should have received a copy of the GNU General Public License */ 00053 /* along with this program; if not, write to the Free Software */ 00054 /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 00055 /* */ 00056 /*****************************************************************************/ 00057 00058 /* First let's include the header file needed */ 00059 00060 #include <cfpython.h> 00061 #include <stdarg.h> 00062 #include <node.h> 00063 00064 #define PYTHON_DEBUG /* give us some general infos out */ 00065 #define PYTHON_CACHE_SIZE 16 /* number of python scripts to store the bytecode of at a time */ 00066 00067 typedef struct { 00068 sstring file; 00069 PyCodeObject *code; 00070 time_t cached_time, used_time; 00071 } pycode_cache_entry; 00072 00073 static PythonCmd CustomCommand[NR_CUSTOM_CMD]; 00074 00075 static pycode_cache_entry pycode_cache[PYTHON_CACHE_SIZE]; 00076 00077 static void set_exception(const char *fmt, ...); 00078 static PyObject *createCFObject(PyObject *self, PyObject *args); 00079 static PyObject *createCFObjectByName(PyObject *self, PyObject *args); 00080 static PyObject *getCFPythonVersion(PyObject *self, PyObject *args); 00081 static PyObject *getReturnValue(PyObject *self, PyObject *args); 00082 static PyObject *setReturnValue(PyObject *self, PyObject *args); 00083 static PyObject *matchString(PyObject *self, PyObject *args); 00084 static PyObject *findPlayer(PyObject *self, PyObject *args); 00085 static PyObject *readyMap(PyObject *self, PyObject *args); 00086 static PyObject *createMap(PyObject *self, PyObject *args); 00087 static PyObject *getMapDirectory(PyObject *self, PyObject *args); 00088 static PyObject *getUniqueDirectory(PyObject *self, PyObject *args); 00089 static PyObject *getTempDirectory(PyObject *self, PyObject *args); 00090 static PyObject *getConfigDirectory(PyObject *self, PyObject *args); 00091 static PyObject *getLocalDirectory(PyObject *self, PyObject *args); 00092 static PyObject *getPlayerDirectory(PyObject *self, PyObject *args); 00093 static PyObject *getDataDirectory(PyObject *self, PyObject *args); 00094 static PyObject *getWhoAmI(PyObject *self, PyObject *args); 00095 static PyObject *getWhoIsActivator(PyObject *self, PyObject *args); 00096 static PyObject *getWhoIsThird(PyObject *self, PyObject *args); 00097 static PyObject *getWhatIsMessage(PyObject *self, PyObject *args); 00098 static PyObject *getScriptName(PyObject *self, PyObject *args); 00099 static PyObject *getScriptParameters(PyObject *self, PyObject *args); 00100 static PyObject *getEvent(PyObject *self, PyObject *args); 00101 static PyObject *getPrivateDictionary(PyObject *self, PyObject *args); 00102 static PyObject *getSharedDictionary(PyObject *self, PyObject *args); 00103 static PyObject *getArchetypes(PyObject *self, PyObject *args); 00104 static PyObject *getPlayers(PyObject *self, PyObject *args); 00105 static PyObject *getMaps(PyObject *self, PyObject *args); 00106 static PyObject *getParties(PyObject *self, PyObject *args); 00107 static PyObject *getRegions(PyObject *self, PyObject *args); 00108 static PyObject *getFriendlyList(PyObject *self, PyObject *args); 00109 static PyObject *registerCommand(PyObject *self, PyObject *args); 00110 static PyObject *registerGEvent(PyObject *self, PyObject *args); 00111 static PyObject *unregisterGEvent(PyObject *self, PyObject *args); 00112 static PyObject *CFPythonError; 00113 static PyObject *getTime(PyObject *self, PyObject *args); 00114 static PyObject *destroyTimer(PyObject *self, PyObject *args); 00115 static PyObject *getMapHasBeenLoaded(PyObject *self, PyObject *args); 00116 static PyObject *findAnimation(PyObject *self, PyObject *args); 00117 static PyObject *log_message(PyObject *self, PyObject *args); 00118 static PyObject *findFace(PyObject *self, PyObject *args); 00119 static PyObject *getSeasonName(PyObject *self, PyObject *args); 00120 static PyObject *getMonthName(PyObject *self, PyObject *args); 00121 static PyObject *getWeekdayName(PyObject *self, PyObject *args); 00122 static PyObject *getPeriodofdayName(PyObject *self, PyObject *args); 00123 00125 static void set_exception(const char *fmt, ...) { 00126 char buf[1024]; 00127 va_list arg; 00128 00129 va_start(arg, fmt); 00130 vsnprintf(buf, sizeof(buf), fmt, arg); 00131 va_end(arg); 00132 00133 PyErr_SetString(PyExc_ValueError, buf); 00134 } 00135 00136 static PyMethodDef CFPythonMethods[] = { 00137 { "WhoAmI", getWhoAmI, METH_NOARGS, NULL }, 00138 { "WhoIsActivator", getWhoIsActivator, METH_NOARGS, NULL }, 00139 { "WhoIsOther", getWhoIsThird, METH_NOARGS, NULL }, 00140 { "WhatIsMessage", getWhatIsMessage, METH_NOARGS, NULL }, 00141 { "ScriptName", getScriptName, METH_NOARGS, NULL }, 00142 { "ScriptParameters", getScriptParameters, METH_NOARGS, NULL }, 00143 { "WhatIsEvent", getEvent, METH_NOARGS, NULL }, 00144 { "MapDirectory", getMapDirectory, METH_NOARGS, NULL }, 00145 { "UniqueDirectory", getUniqueDirectory, METH_NOARGS, NULL }, 00146 { "TempDirectory", getTempDirectory, METH_NOARGS, NULL }, 00147 { "ConfigDirectory", getConfigDirectory, METH_NOARGS, NULL }, 00148 { "LocalDirectory", getLocalDirectory, METH_NOARGS, NULL }, 00149 { "PlayerDirectory", getPlayerDirectory, METH_NOARGS, NULL }, 00150 { "DataDirectory", getDataDirectory, METH_NOARGS, NULL }, 00151 { "ReadyMap", readyMap, METH_VARARGS, NULL }, 00152 { "CreateMap", createMap, METH_VARARGS, NULL }, 00153 { "FindPlayer", findPlayer, METH_VARARGS, NULL }, 00154 { "MatchString", matchString, METH_VARARGS, NULL }, 00155 { "GetReturnValue", getReturnValue, METH_NOARGS, NULL }, 00156 { "SetReturnValue", setReturnValue, METH_VARARGS, NULL }, 00157 { "PluginVersion", getCFPythonVersion, METH_NOARGS, NULL }, 00158 { "CreateObject", createCFObject, METH_NOARGS, NULL }, 00159 { "CreateObjectByName", createCFObjectByName, METH_VARARGS, NULL }, 00160 { "GetPrivateDictionary", getPrivateDictionary, METH_NOARGS, NULL }, 00161 { "GetSharedDictionary", getSharedDictionary, METH_NOARGS, NULL }, 00162 { "GetPlayers", getPlayers, METH_NOARGS, NULL }, 00163 { "GetArchetypes", getArchetypes, METH_NOARGS, NULL }, 00164 { "GetMaps", getMaps, METH_NOARGS, NULL }, 00165 { "GetParties", getParties, METH_NOARGS, NULL }, 00166 { "GetRegions", getRegions, METH_NOARGS, NULL }, 00167 { "GetFriendlyList", getFriendlyList, METH_NOARGS, NULL }, 00168 { "RegisterCommand", registerCommand, METH_VARARGS, NULL }, 00169 { "RegisterGlobalEvent", registerGEvent, METH_VARARGS, NULL }, 00170 { "UnregisterGlobalEvent", unregisterGEvent, METH_VARARGS, NULL }, 00171 { "GetTime", getTime, METH_NOARGS, NULL }, 00172 { "DestroyTimer", destroyTimer, METH_VARARGS, NULL }, 00173 { "MapHasBeenLoaded", getMapHasBeenLoaded, METH_VARARGS, NULL }, 00174 { "Log", log_message, METH_VARARGS, NULL }, 00175 { "FindFace", findFace, METH_VARARGS, NULL }, 00176 { "FindAnimation", findAnimation, METH_VARARGS, NULL }, 00177 { "GetSeasonName", getSeasonName, METH_VARARGS, NULL }, 00178 { "GetMonthName", getMonthName, METH_VARARGS, NULL }, 00179 { "GetWeekdayName", getWeekdayName, METH_VARARGS, NULL }, 00180 { "GetPeriodofdayName", getPeriodofdayName, METH_VARARGS, NULL }, 00181 { NULL, NULL, 0, NULL } 00182 }; 00183 00184 CFPContext *context_stack; 00185 00186 CFPContext *current_context; 00187 00188 static int current_command = -999; 00189 00190 static PyObject *shared_data = NULL; 00191 00192 static PyObject *private_data = NULL; 00193 00194 static PyObject *registerGEvent(PyObject *self, PyObject *args) { 00195 int eventcode; 00196 00197 if (!PyArg_ParseTuple(args, "i", &eventcode)) 00198 return NULL; 00199 00200 cf_system_register_global_event(eventcode, PLUGIN_NAME, cfpython_globalEventListener); 00201 00202 Py_INCREF(Py_None); 00203 return Py_None; 00204 } 00205 00206 static PyObject *unregisterGEvent(PyObject *self, PyObject *args) { 00207 int eventcode; 00208 00209 if (!PyArg_ParseTuple(args, "i", &eventcode)) 00210 return NULL; 00211 00212 cf_system_unregister_global_event(EVENT_TELL, PLUGIN_NAME); 00213 00214 Py_INCREF(Py_None); 00215 return Py_None; 00216 } 00217 00218 static PyObject *createCFObject(PyObject *self, PyObject *args) { 00219 object *op; 00220 00221 op = cf_create_object(); 00222 00223 return Crossfire_Object_wrap(op); 00224 } 00225 00226 static PyObject *createCFObjectByName(PyObject *self, PyObject *args) { 00227 char *obname; 00228 object *op; 00229 00230 if (!PyArg_ParseTuple(args, "s", &obname)) 00231 return NULL; 00232 00233 op = cf_create_object_by_name(obname); 00234 00235 return Crossfire_Object_wrap(op); 00236 } 00237 00238 static PyObject *getCFPythonVersion(PyObject *self, PyObject *args) { 00239 int i = 2044; 00240 00241 return Py_BuildValue("i", i); 00242 } 00243 00244 static PyObject *getReturnValue(PyObject *self, PyObject *args) { 00245 return Py_BuildValue("i", current_context->returnvalue); 00246 } 00247 00248 static PyObject *setReturnValue(PyObject *self, PyObject *args) { 00249 int i; 00250 00251 if (!PyArg_ParseTuple(args, "i", &i)) 00252 return NULL; 00253 current_context->returnvalue = i; 00254 Py_INCREF(Py_None); 00255 return Py_None; 00256 } 00257 00258 static PyObject *matchString(PyObject *self, PyObject *args) { 00259 char *premiere; 00260 char *seconde; 00261 const char *result; 00262 00263 if (!PyArg_ParseTuple(args, "ss", &premiere, &seconde)) 00264 return NULL; 00265 00266 result = cf_re_cmp(premiere, seconde); 00267 if (result != NULL) 00268 return Py_BuildValue("i", 1); 00269 else 00270 return Py_BuildValue("i", 0); 00271 } 00272 00273 static PyObject *findPlayer(PyObject *self, PyObject *args) { 00274 player *foundpl; 00275 char *txt; 00276 00277 if (!PyArg_ParseTuple(args, "s", &txt)) 00278 return NULL; 00279 00280 foundpl = cf_player_find(txt); 00281 00282 if (foundpl != NULL) 00283 return Py_BuildValue("O", Crossfire_Object_wrap(foundpl->ob)); 00284 else { 00285 Py_INCREF(Py_None); 00286 return Py_None; 00287 } 00288 } 00289 00290 static PyObject *readyMap(PyObject *self, PyObject *args) { 00291 char *mapname; 00292 mapstruct *map; 00293 int flags = 0; 00294 00295 if (!PyArg_ParseTuple(args, "s|i", &mapname, &flags)) 00296 return NULL; 00297 00298 map = cf_map_get_map(mapname, flags); 00299 00300 return Crossfire_Map_wrap(map); 00301 } 00302 00303 static PyObject *createMap(PyObject *self, PyObject *args) { 00304 int sizex, sizey; 00305 mapstruct *map; 00306 00307 if (!PyArg_ParseTuple(args, "ii", &sizex, &sizey)) 00308 return NULL; 00309 00310 map = cf_get_empty_map(sizex, sizey); 00311 00312 return Crossfire_Map_wrap(map); 00313 } 00314 00315 static PyObject *getMapDirectory(PyObject *self, PyObject *args) { 00316 return Py_BuildValue("s", cf_get_directory(0)); 00317 } 00318 00319 static PyObject *getUniqueDirectory(PyObject *self, PyObject *args) { 00320 return Py_BuildValue("s", cf_get_directory(1)); 00321 } 00322 00323 static PyObject *getTempDirectory(PyObject *self, PyObject *args) { 00324 return Py_BuildValue("s", cf_get_directory(2)); 00325 } 00326 00327 static PyObject *getConfigDirectory(PyObject *self, PyObject *args) { 00328 return Py_BuildValue("s", cf_get_directory(3)); 00329 } 00330 00331 static PyObject *getLocalDirectory(PyObject *self, PyObject *args) { 00332 return Py_BuildValue("s", cf_get_directory(4)); 00333 } 00334 00335 static PyObject *getPlayerDirectory(PyObject *self, PyObject *args) { 00336 return Py_BuildValue("s", cf_get_directory(5)); 00337 } 00338 00339 static PyObject *getDataDirectory(PyObject *self, PyObject *args) { 00340 return Py_BuildValue("s", cf_get_directory(6)); 00341 } 00342 00343 static PyObject *getWhoAmI(PyObject *self, PyObject *args) { 00344 if (!current_context->who) { 00345 Py_INCREF(Py_None); 00346 return Py_None; 00347 } 00348 Py_INCREF(current_context->who); 00349 return current_context->who; 00350 } 00351 00352 static PyObject *getWhoIsActivator(PyObject *self, PyObject *args) { 00353 if (!current_context->activator) { 00354 Py_INCREF(Py_None); 00355 return Py_None; 00356 } 00357 Py_INCREF(current_context->activator); 00358 return current_context->activator; 00359 } 00360 00361 static PyObject *getWhoIsThird(PyObject *self, PyObject *args) { 00362 if (!current_context->third) { 00363 Py_INCREF(Py_None); 00364 return Py_None; 00365 } 00366 Py_INCREF(current_context->third); 00367 return current_context->third; 00368 } 00369 00370 static PyObject *getWhatIsMessage(PyObject *self, PyObject *args) { 00371 if (current_context->message == NULL) 00372 return Py_BuildValue(""); 00373 else 00374 return Py_BuildValue("s", current_context->message); 00375 } 00376 00377 static PyObject *getScriptName(PyObject *self, PyObject *args) { 00378 return Py_BuildValue("s", current_context->script); 00379 } 00380 00381 static PyObject *getScriptParameters(PyObject *self, PyObject *args) { 00382 if (!current_context->options) { 00383 Py_INCREF(Py_None); 00384 return Py_None; 00385 } 00386 return Py_BuildValue("s", current_context->options); 00387 } 00388 00389 static PyObject *getEvent(PyObject *self, PyObject *args) { 00390 if (!current_context->event) { 00391 Py_INCREF(Py_None); 00392 return Py_None; 00393 } 00394 Py_INCREF(current_context->event); 00395 return current_context->event; 00396 } 00397 00398 static PyObject *getPrivateDictionary(PyObject *self, PyObject *args) { 00399 PyObject *data; 00400 00401 data = PyDict_GetItemString(private_data, current_context->script); 00402 if (!data) { 00403 data = PyDict_New(); 00404 PyDict_SetItemString(private_data, current_context->script, data); 00405 Py_DECREF(data); 00406 } 00407 Py_INCREF(data); 00408 return data; 00409 } 00410 00411 static PyObject *getSharedDictionary(PyObject *self, PyObject *args) { 00412 Py_INCREF(shared_data); 00413 return shared_data; 00414 } 00415 00416 static PyObject *getArchetypes(PyObject *self, PyObject *args) { 00417 PyObject *list; 00418 archetype *arch; 00419 00420 list = PyList_New(0); 00421 arch = cf_archetype_get_first(); 00422 while (arch) { 00423 PyList_Append(list, Crossfire_Archetype_wrap(arch)); 00424 arch = cf_archetype_get_next(arch); 00425 } 00426 return list; 00427 } 00428 00429 static PyObject *getPlayers(PyObject *self, PyObject *args) { 00430 PyObject *list; 00431 object *pl; 00432 00433 list = PyList_New(0); 00434 pl = cf_object_get_object_property(NULL, CFAPI_PLAYER_PROP_NEXT); 00435 while (pl) { 00436 PyList_Append(list, Crossfire_Object_wrap(pl)); 00437 pl = cf_object_get_object_property(pl, CFAPI_PLAYER_PROP_NEXT); 00438 } 00439 return list; 00440 } 00441 00442 static PyObject *getMaps(PyObject *self, PyObject *args) { 00443 PyObject *list; 00444 mapstruct *map; 00445 00446 list = PyList_New(0); 00447 map = cf_map_get_first(); 00448 while (map) { 00449 PyList_Append(list, Crossfire_Map_wrap(map)); 00450 map = cf_map_get_map_property(map, CFAPI_MAP_PROP_NEXT); 00451 } 00452 return list; 00453 } 00454 00455 static PyObject *getParties(PyObject *self, PyObject *args) { 00456 PyObject *list; 00457 partylist *party; 00458 00459 list = PyList_New(0); 00460 party = cf_party_get_first(); 00461 while (party) { 00462 PyList_Append(list, Crossfire_Party_wrap(party)); 00463 party = cf_party_get_next(party); 00464 } 00465 return list; 00466 } 00467 00468 static PyObject *getRegions(PyObject *self, PyObject *args) { 00469 PyObject *list; 00470 region *reg; 00471 00472 list = PyList_New(0); 00473 reg = cf_region_get_first(); 00474 while (reg) { 00475 PyList_Append(list, Crossfire_Region_wrap(reg)); 00476 reg = cf_region_get_next(reg); 00477 } 00478 return list; 00479 } 00480 00481 static PyObject *getFriendlyList(PyObject *self, PyObject *args) { 00482 PyObject *list; 00483 object *ob; 00484 00485 list = PyList_New(0); 00486 ob = cf_friendlylist_get_first(); 00487 while (ob) { 00488 PyList_Append(list, Crossfire_Object_wrap(ob)); 00489 ob = cf_friendlylist_get_next(ob); 00490 } 00491 return list; 00492 } 00493 00494 static PyObject *registerCommand(PyObject *self, PyObject *args) { 00495 char *cmdname; 00496 char *scriptname; 00497 double cmdspeed; 00498 int i; 00499 00500 if (!PyArg_ParseTuple(args, "ssd", &cmdname, &scriptname, &cmdspeed)) 00501 return NULL; 00502 00503 if (cmdspeed < 0) { 00504 set_exception("speed must not be negative"); 00505 return NULL; 00506 } 00507 00508 for (i = 0; i < NR_CUSTOM_CMD; i++) { 00509 if (CustomCommand[i].name != NULL) { 00510 if (!strcmp(CustomCommand[i].name, cmdname)) { 00511 set_exception("command '%s' is already registered", cmdname); 00512 return NULL; 00513 } 00514 } 00515 } 00516 for (i = 0; i < NR_CUSTOM_CMD; i++) { 00517 if (CustomCommand[i].name == NULL) { 00518 CustomCommand[i].name = cf_strdup_local(cmdname); 00519 CustomCommand[i].script = cf_strdup_local(scriptname); 00520 CustomCommand[i].speed = cmdspeed; 00521 break; 00522 } 00523 } 00524 00525 Py_INCREF(Py_None); 00526 return Py_None; 00527 } 00528 00529 static PyObject *getTime(PyObject *self, PyObject *args) { 00530 PyObject *list; 00531 timeofday_t tod; 00532 00533 cf_get_time(&tod); 00534 00535 list = PyList_New(0); 00536 PyList_Append(list, Py_BuildValue("i", tod.year)); 00537 PyList_Append(list, Py_BuildValue("i", tod.month)); 00538 PyList_Append(list, Py_BuildValue("i", tod.day)); 00539 PyList_Append(list, Py_BuildValue("i", tod.hour)); 00540 PyList_Append(list, Py_BuildValue("i", tod.minute)); 00541 PyList_Append(list, Py_BuildValue("i", tod.dayofweek)); 00542 PyList_Append(list, Py_BuildValue("i", tod.weekofmonth)); 00543 PyList_Append(list, Py_BuildValue("i", tod.season)); 00544 PyList_Append(list, Py_BuildValue("i", tod.periodofday)); 00545 00546 return list; 00547 } 00548 00549 static PyObject *destroyTimer(PyObject *self, PyObject *args) { 00550 int id; 00551 00552 if (!PyArg_ParseTuple(args, "i", &id)) 00553 return NULL; 00554 return Py_BuildValue("i", cf_timer_destroy(id)); 00555 } 00556 00557 static PyObject *getMapHasBeenLoaded(PyObject *self, PyObject *args) { 00558 char *name; 00559 00560 if (!PyArg_ParseTuple(args, "s", &name)) 00561 return NULL; 00562 return Crossfire_Map_wrap(cf_map_has_been_loaded(name)); 00563 } 00564 00565 static PyObject *findFace(PyObject *self, PyObject *args) { 00566 char *name; 00567 00568 if (!PyArg_ParseTuple(args, "s", &name)) 00569 return NULL; 00570 return Py_BuildValue("i", cf_find_face(name, 0)); 00571 } 00572 00573 static PyObject *log_message(PyObject *self, PyObject *args) { 00574 LogLevel level; 00575 int intLevel; 00576 char *message; 00577 00578 if (!PyArg_ParseTuple(args, "is", &intLevel, &message)) 00579 return NULL; 00580 00581 switch (intLevel) { 00582 case llevError: 00583 level = llevError; 00584 break; 00585 00586 case llevInfo: 00587 level = llevInfo; 00588 break; 00589 00590 case llevDebug: 00591 level = llevDebug; 00592 break; 00593 00594 case llevMonster: 00595 level = llevMonster; 00596 break; 00597 00598 default: 00599 return NULL; 00600 } 00601 if ((message != NULL) && (message[strlen(message)] == '\n')) 00602 cf_log(level, "CFPython: %s", message); 00603 else 00604 cf_log(level, "CFPython: %s\n", message); 00605 Py_INCREF(Py_None); 00606 return Py_None; 00607 } 00608 00609 static PyObject *findAnimation(PyObject *self, PyObject *args) { 00610 char *name; 00611 00612 if (!PyArg_ParseTuple(args, "s", &name)) 00613 return NULL; 00614 return Py_BuildValue("i", cf_find_animation(name)); 00615 } 00616 00617 static PyObject *getSeasonName(PyObject *self, PyObject *args) { 00618 int i; 00619 00620 if (!PyArg_ParseTuple(args, "i", &i)) 00621 return NULL; 00622 return Py_BuildValue("s", cf_get_season_name(i)); 00623 } 00624 00625 static PyObject *getMonthName(PyObject *self, PyObject *args) { 00626 int i; 00627 00628 if (!PyArg_ParseTuple(args, "i", &i)) 00629 return NULL; 00630 return Py_BuildValue("s", cf_get_month_name(i)); 00631 } 00632 00633 static PyObject *getWeekdayName(PyObject *self, PyObject *args) { 00634 int i; 00635 00636 if (!PyArg_ParseTuple(args, "i", &i)) 00637 return NULL; 00638 return Py_BuildValue("s", cf_get_weekday_name(i)); 00639 } 00640 00641 static PyObject *getPeriodofdayName(PyObject *self, PyObject *args) { 00642 int i; 00643 00644 if (!PyArg_ParseTuple(args, "i", &i)) 00645 return NULL; 00646 return Py_BuildValue("s", cf_get_periodofday_name(i)); 00647 } 00648 00649 static void initContextStack(void) { 00650 current_context = NULL; 00651 context_stack = NULL; 00652 } 00653 00654 static void pushContext(CFPContext *context) { 00655 if (current_context == NULL) { 00656 context_stack = context; 00657 context->down = NULL; 00658 } else { 00659 context->down = current_context; 00660 } 00661 current_context = context; 00662 } 00663 00664 static CFPContext *popContext(void) { 00665 CFPContext *oldcontext; 00666 00667 if (current_context != NULL) { 00668 oldcontext = current_context; 00669 current_context = current_context->down; 00670 return oldcontext; 00671 } 00672 else 00673 return NULL; 00674 } 00675 00676 static void freeContext(CFPContext *context) { 00677 Py_XDECREF(context->event); 00678 Py_XDECREF(context->third); 00679 Py_XDECREF(context->who); 00680 Py_XDECREF(context->activator); 00681 free(context); 00682 } 00683 00685 static PyCodeObject *compilePython(char *filename) { 00686 PyObject *scriptfile; 00687 sstring sh_path; 00688 struct stat stat_buf; 00689 struct _node *n; 00690 int i; 00691 pycode_cache_entry *replace = NULL, *run = NULL; 00692 00693 if (!(scriptfile = PyFile_FromString(filename, "r"))) { 00694 cf_log(llevDebug, "cfpython - The Script file %s can't be opened\n", filename); 00695 return NULL; 00696 } 00697 if (stat(filename, &stat_buf)) { 00698 cf_log(llevDebug, "cfpython - The Script file %s can't be stat:ed\n", filename); 00699 if (scriptfile) { 00700 Py_DECREF(scriptfile); 00701 } 00702 return NULL; 00703 } 00704 00705 sh_path = cf_add_string(filename); 00706 00707 /* Search through cache. Three cases: 00708 * 1) script in cache, but older than file -> replace cached 00709 * 2) script in cache and up to date -> use cached 00710 * 3) script not in cache, cache not full -> add to end of cache 00711 * 4) script not in cache, cache full -> replace least recently used 00712 */ 00713 for (i = 0; i < PYTHON_CACHE_SIZE; i++) { 00714 if (pycode_cache[i].file == NULL) { /* script not in cache, cache not full */ 00715 replace = &pycode_cache[i]; /* add to end of cache */ 00716 break; 00717 } else if (pycode_cache[i].file == sh_path) { 00718 /* script in cache */ 00719 if (pycode_cache[i].code == NULL || (pycode_cache[i].cached_time < stat_buf.st_mtime)) { 00720 /* cache older than file, replace cached */ 00721 replace = &pycode_cache[i]; 00722 } else { 00723 /* cache uptodate, use cached*/ 00724 replace = NULL; 00725 run = &pycode_cache[i]; 00726 } 00727 break; 00728 } else if (replace == NULL || pycode_cache[i].used_time < replace->used_time) 00729 /* if we haven't found it yet, set replace to the oldest cache */ 00730 replace = &pycode_cache[i]; 00731 } 00732 00733 /* replace a specific cache index with the file */ 00734 if (replace) { 00735 Py_XDECREF(replace->code); /* safe to call on NULL */ 00736 replace->code = NULL; 00737 00738 /* Need to replace path string? */ 00739 if (replace->file != sh_path) { 00740 if (replace->file) { 00741 cf_free_string(replace->file); 00742 } 00743 replace->file = cf_add_string(sh_path); 00744 } 00745 00746 /* Load, parse and compile */ 00747 if (!scriptfile && !(scriptfile = PyFile_FromString(filename, "r"))) { 00748 cf_log(llevDebug, "cfpython - The Script file %s can't be opened\n", filename); 00749 replace->code = NULL; 00750 return NULL; 00751 } else { 00752 if ((n = PyParser_SimpleParseFile(PyFile_AsFile(scriptfile), filename, Py_file_input))) { 00753 replace->code = PyNode_Compile(n, filename); 00754 PyNode_Free(n); 00755 } 00756 00757 if (PyErr_Occurred()) 00758 PyErr_Print(); 00759 else 00760 replace->cached_time = stat_buf.st_mtime; 00761 run = replace; 00762 } 00763 } 00764 00765 cf_free_string(sh_path); 00766 00767 if (scriptfile) { 00768 Py_DECREF(scriptfile); 00769 } 00770 00771 if (run) 00772 return run->code; 00773 else 00774 return NULL; 00775 } 00776 00777 static int do_script(CFPContext *context, int silent) { 00778 PyCodeObject *pycode; 00779 PyObject *dict; 00780 PyObject *ret; 00781 #if 0 00782 PyObject *list; 00783 int item; 00784 #endif 00785 00786 pycode = compilePython(context->script); 00787 if (pycode) { 00788 pushContext(context); 00789 dict = PyDict_New(); 00790 PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins()); 00791 ret = PyEval_EvalCode(pycode, dict, NULL); 00792 if (PyErr_Occurred()) { 00793 PyErr_Print(); 00794 } 00795 Py_XDECREF(ret); 00796 #if 0 00797 printf("cfpython - %d items in heap\n", PyDict_Size(dict)); 00798 list = PyDict_Values(dict); 00799 for (item = PyList_Size(list)-1; item >= 0; item--) { 00800 dict = PyList_GET_ITEM(list, item); 00801 ret = PyObject_Str(dict); 00802 printf(" ref %s = %d\n", PyString_AsString(ret), dict->ob_refcnt); 00803 Py_XDECREF(ret); 00804 } 00805 Py_DECREF(list); 00806 #endif 00807 Py_DECREF(dict); 00808 return 1; 00809 } else 00810 return 0; 00811 } 00812 00813 typedef struct { 00814 const char *name; 00815 const int value; 00816 } CFConstant; 00817 00818 static void addConstants(PyObject *module, const char *name, const CFConstant *constants) { 00819 int i = 0; 00820 char tmp[1024]; 00821 PyObject *new; 00822 PyObject *dict; 00823 00824 strncpy(tmp, "Crossfire_", sizeof(tmp)); 00825 strncat(tmp, name, sizeof(tmp)-strlen(tmp)); 00826 00827 new = Py_InitModule(tmp, NULL); 00828 dict = PyDict_New(); 00829 00830 while (constants[i].name != NULL) { 00831 PyModule_AddIntConstant(new, (char *)constants[i].name, constants[i].value); 00832 PyDict_SetItem(dict, PyInt_FromLong(constants[i].value), PyString_FromString(constants[i].name)); 00833 i++; 00834 } 00835 PyDict_SetItemString(PyModule_GetDict(module), name, new); 00836 /* This cause assert() in debug builds if enabled. */ 00837 #if 0 00838 Py_DECREF(new); 00839 #endif 00840 00841 strncpy(tmp, name, sizeof(tmp)); 00842 strncat(tmp, "Name", sizeof(tmp)-strlen(tmp)); 00843 PyDict_SetItemString(PyModule_GetDict(module), tmp, dict); 00844 Py_DECREF(dict); 00845 } 00852 static void addSimpleConstants(PyObject *module, const char *name, const CFConstant *constants) { 00853 int i = 0; 00854 char tmp[1024]; 00855 PyObject *new; 00856 00857 strncpy(tmp, "Crossfire_", sizeof(tmp)); 00858 strncat(tmp, name, sizeof(tmp)-strlen(tmp)); 00859 00860 new = Py_InitModule(tmp, NULL); 00861 00862 while (constants[i].name != NULL) { 00863 PyModule_AddIntConstant(new, (char *)constants[i].name, constants[i].value); 00864 i++; 00865 } 00866 PyDict_SetItemString(PyModule_GetDict(module), name, new); 00867 /* This cause assert() in debug builds if enabled. */ 00868 #if 0 00869 Py_DECREF(new); 00870 #endif 00871 } 00872 00873 static void initConstants(PyObject *module) { 00874 static const CFConstant cstDirection[] = { 00875 { "NORTH", 1 }, 00876 { "NORTHEAST", 2 }, 00877 { "EAST", 3 }, 00878 { "SOUTHEAST", 4 }, 00879 { "SOUTH", 5 }, 00880 { "SOUTHWEST", 6 }, 00881 { "WEST", 7 }, 00882 { "NORTHWEST", 8 }, 00883 { NULL, 0 } 00884 }; 00885 00886 static const CFConstant cstType[] = { 00887 { "PLAYER", PLAYER }, 00888 { "TRANSPORT", TRANSPORT }, 00889 { "ROD", ROD }, 00890 { "TREASURE", TREASURE }, 00891 { "POTION", POTION }, 00892 { "FOOD", FOOD }, 00893 { "POISON", POISON }, 00894 { "BOOK", BOOK }, 00895 { "CLOCK", CLOCK }, 00896 { "ARROW", ARROW }, 00897 { "BOW", BOW }, 00898 { "WEAPON", WEAPON }, 00899 { "ARMOUR", ARMOUR }, 00900 { "PEDESTAL", PEDESTAL }, 00901 { "ALTAR", ALTAR }, 00902 { "LOCKED_DOOR", LOCKED_DOOR }, 00903 { "SPECIAL_KEY", SPECIAL_KEY }, 00904 { "MAP", MAP }, 00905 { "DOOR", DOOR }, 00906 { "KEY", KEY }, 00907 { "TIMED_GATE", TIMED_GATE }, 00908 { "TRIGGER", TRIGGER }, 00909 { "GRIMREAPER", GRIMREAPER }, 00910 { "MAGIC_EAR", MAGIC_EAR }, 00911 { "TRIGGER_BUTTON", TRIGGER_BUTTON }, 00912 { "TRIGGER_ALTAR", TRIGGER_ALTAR }, 00913 { "TRIGGER_PEDESTAL", TRIGGER_PEDESTAL }, 00914 { "SHIELD", SHIELD }, 00915 { "HELMET", HELMET }, 00916 { "HORN", HORN }, 00917 { "MONEY", MONEY }, 00918 { "CLASS", CLASS }, 00919 { "AMULET", AMULET }, 00920 { "PLAYERMOVER", PLAYERMOVER }, 00921 { "TELEPORTER", TELEPORTER }, 00922 { "CREATOR", CREATOR }, 00923 { "SKILL", SKILL }, 00924 { "EXPERIENCE", EXPERIENCE }, 00925 { "EARTHWALL", EARTHWALL }, 00926 { "GOLEM", GOLEM }, 00927 { "THROWN_OBJ", THROWN_OBJ }, 00928 { "BLINDNESS", BLINDNESS }, 00929 { "GOD", GOD }, 00930 { "DETECTOR", DETECTOR }, 00931 { "TRIGGER_MARKER", TRIGGER_MARKER }, 00932 { "DEAD_OBJECT", DEAD_OBJECT }, 00933 { "DRINK", DRINK }, 00934 { "MARKER", MARKER }, 00935 { "HOLY_ALTAR", HOLY_ALTAR }, 00936 { "PLAYER_CHANGER", PLAYER_CHANGER }, 00937 { "BATTLEGROUND", BATTLEGROUND }, 00938 { "PEACEMAKER", PEACEMAKER }, 00939 { "GEM", GEM }, 00940 { "FIREWALL", FIREWALL }, 00941 { "CHECK_INV", CHECK_INV }, 00942 { "MOOD_FLOOR", MOOD_FLOOR }, 00943 { "EXIT", EXIT }, 00944 { "ENCOUNTER", ENCOUNTER }, 00945 { "SHOP_FLOOR", SHOP_FLOOR }, 00946 { "SHOP_MAT", SHOP_MAT }, 00947 { "RING", RING }, 00948 { "FLOOR", FLOOR }, 00949 { "FLESH", FLESH }, 00950 { "INORGANIC", INORGANIC }, 00951 { "SKILL_TOOL", SKILL_TOOL }, 00952 { "LIGHTER", LIGHTER }, 00953 { "WALL", WALL }, 00954 { "MISC_OBJECT", MISC_OBJECT }, 00955 { "MONSTER", MONSTER }, 00956 { "LAMP", LAMP }, 00957 { "DUPLICATOR", DUPLICATOR }, 00958 { "SPELLBOOK", SPELLBOOK }, 00959 { "CLOAK", CLOAK }, 00960 { "SPINNER", SPINNER }, 00961 { "GATE", GATE }, 00962 { "BUTTON", BUTTON }, 00963 { "CF_HANDLE", CF_HANDLE }, 00964 { "HOLE", HOLE }, 00965 { "TRAPDOOR", TRAPDOOR }, 00966 { "SIGN", SIGN }, 00967 { "BOOTS", BOOTS }, 00968 { "GLOVES", GLOVES }, 00969 { "SPELL", SPELL }, 00970 { "SPELL_EFFECT", SPELL_EFFECT }, 00971 { "CONVERTER", CONVERTER }, 00972 { "BRACERS", BRACERS }, 00973 { "POISONING", POISONING }, 00974 { "SAVEBED", SAVEBED }, 00975 { "WAND", WAND }, 00976 { "SCROLL", SCROLL }, 00977 { "DIRECTOR", DIRECTOR }, 00978 { "GIRDLE", GIRDLE }, 00979 { "FORCE", FORCE }, 00980 { "POTION_EFFECT", POTION_EFFECT }, 00981 { "EVENT_CONNECTOR", EVENT_CONNECTOR }, 00982 { "CLOSE_CON", CLOSE_CON }, 00983 { "CONTAINER", CONTAINER }, 00984 { "ARMOUR_IMPROVER", ARMOUR_IMPROVER }, 00985 { "WEAPON_IMPROVER", WEAPON_IMPROVER }, 00986 { "SKILLSCROLL", SKILLSCROLL }, 00987 { "DEEP_SWAMP", DEEP_SWAMP }, 00988 { "IDENTIFY_ALTAR", IDENTIFY_ALTAR }, 00989 { "SHOP_INVENTORY", SHOP_INVENTORY }, 00990 { "RUNE", RUNE }, 00991 { "TRAP", TRAP }, 00992 { "POWER_CRYSTAL", POWER_CRYSTAL }, 00993 { "CORPSE", CORPSE }, 00994 { "DISEASE", DISEASE }, 00995 { "SYMPTOM", SYMPTOM }, 00996 { "BUILDER", BUILDER }, 00997 { "MATERIAL", MATERIAL }, 00998 { NULL, 0 } 00999 }; 01000 01001 static const CFConstant cstMove[] = { 01002 { "WALK", MOVE_WALK }, 01003 { "FLY_LOW", MOVE_FLY_LOW }, 01004 { "FLY_HIGH", MOVE_FLY_HIGH }, 01005 { "FLYING", MOVE_FLYING }, 01006 { "SWIM", MOVE_SWIM }, 01007 { "BOAT", MOVE_BOAT }, 01008 { "ALL", MOVE_ALL }, 01009 { NULL, 0 } 01010 }; 01011 01012 static const CFConstant cstMessageFlag[] = { 01013 { "NDI_BLACK", NDI_BLACK }, 01014 { "NDI_WHITE", NDI_WHITE }, 01015 { "NDI_NAVY", NDI_NAVY }, 01016 { "NDI_RED", NDI_RED }, 01017 { "NDI_ORANGE", NDI_ORANGE }, 01018 { "NDI_BLUE", NDI_BLUE }, 01019 { "NDI_DK_ORANGE", NDI_DK_ORANGE }, 01020 { "NDI_GREEN", NDI_GREEN }, 01021 { "NDI_LT_GREEN", NDI_LT_GREEN }, 01022 { "NDI_GREY", NDI_GREY }, 01023 { "NDI_BROWN", NDI_BROWN }, 01024 { "NDI_GOLD", NDI_GOLD }, 01025 { "NDI_TAN", NDI_TAN }, 01026 { "NDI_UNIQUE", NDI_UNIQUE }, 01027 { "NDI_ALL", NDI_ALL }, 01028 { NULL, 0 } 01029 }; 01030 01031 static const CFConstant cstCostFlag[] = { 01032 { "TRUE", F_TRUE }, 01033 { "BUY", F_BUY }, 01034 { "SELL", F_SELL }, 01035 { "NOBARGAIN", F_NO_BARGAIN }, 01036 { "IDENTIFIED", F_IDENTIFIED }, 01037 { "NOTCURSED", F_NOT_CURSED }, 01038 { NULL, 0 } 01039 }; 01040 01041 static const CFConstant cstAttackType[] = { 01042 { "PHYSICAL", AT_PHYSICAL }, 01043 { "MAGIC", AT_MAGIC }, 01044 { "FIRE", AT_FIRE }, 01045 { "ELECTRICITY", AT_ELECTRICITY }, 01046 { "COLD", AT_COLD }, 01047 { "CONFUSION", AT_CONFUSION }, 01048 { "ACID", AT_ACID }, 01049 { "DRAIN", AT_DRAIN }, 01050 { "WEAPONMAGIC", AT_WEAPONMAGIC }, 01051 { "GHOSTHIT", AT_GHOSTHIT }, 01052 { "POISON", AT_POISON }, 01053 { "SLOW", AT_SLOW }, 01054 { "PARALYZE", AT_PARALYZE }, 01055 { "TURN_UNDEAD", AT_TURN_UNDEAD }, 01056 { "FEAR", AT_FEAR }, 01057 { "CANCELLATION", AT_CANCELLATION }, 01058 { "DEPLETE", AT_DEPLETE }, 01059 { "DEATH", AT_DEATH }, 01060 { "CHAOS", AT_CHAOS }, 01061 { "COUNTERSPELL", AT_COUNTERSPELL }, 01062 { "GODPOWER", AT_GODPOWER }, 01063 { "HOLYWORD", AT_HOLYWORD }, 01064 { "BLIND", AT_BLIND }, 01065 { "INTERNAL", AT_INTERNAL }, 01066 { "LIFE_STEALING", AT_LIFE_STEALING }, 01067 { "DISEASE", AT_DISEASE }, 01068 { NULL, 0 } 01069 }; 01070 01071 static const CFConstant cstAttackTypeNumber[] = { 01072 { "PHYSICAL", ATNR_PHYSICAL }, 01073 { "MAGIC", ATNR_MAGIC }, 01074 { "FIRE", ATNR_FIRE }, 01075 { "ELECTRICITY", ATNR_ELECTRICITY }, 01076 { "COLD", ATNR_COLD }, 01077 { "CONFUSION", ATNR_CONFUSION }, 01078 { "ACID", ATNR_ACID }, 01079 { "DRAIN", ATNR_DRAIN }, 01080 { "WEAPONMAGIC", ATNR_WEAPONMAGIC }, 01081 { "GHOSTHIT", ATNR_GHOSTHIT }, 01082 { "POISON", ATNR_POISON }, 01083 { "SLOW", ATNR_SLOW }, 01084 { "PARALYZE", ATNR_PARALYZE }, 01085 { "TURN_UNDEAD", ATNR_TURN_UNDEAD }, 01086 { "FEAR", ATNR_FEAR }, 01087 { "CANCELLATION", ATNR_CANCELLATION }, 01088 { "DEPLETE", ATNR_DEPLETE }, 01089 { "DEATH", ATNR_DEATH }, 01090 { "CHAOS", ATNR_CHAOS }, 01091 { "COUNTERSPELL", ATNR_COUNTERSPELL }, 01092 { "GODPOWER", ATNR_GODPOWER }, 01093 { "HOLYWORD", ATNR_HOLYWORD }, 01094 { "BLIND", ATNR_BLIND }, 01095 { "INTERNAL", ATNR_INTERNAL }, 01096 { "LIFE_STEALING", ATNR_LIFE_STEALING }, 01097 { "DISEASE", ATNR_DISEASE }, 01098 { NULL, 0 } 01099 }; 01100 01101 static const CFConstant cstEventType[] = { 01102 { "APPLY", EVENT_APPLY }, 01103 { "ATTACK", EVENT_ATTACK }, 01104 { "DEATH", EVENT_DEATH }, 01105 { "DROP", EVENT_DROP }, 01106 { "PICKUP", EVENT_PICKUP }, 01107 { "SAY", EVENT_SAY }, 01108 { "STOP", EVENT_STOP }, 01109 { "TIME", EVENT_TIME }, 01110 { "THROW", EVENT_THROW }, 01111 { "TRIGGER", EVENT_TRIGGER }, 01112 { "CLOSE", EVENT_CLOSE }, 01113 { "TIMER", EVENT_TIMER }, 01114 { "DESTROY", EVENT_DESTROY }, 01115 { "BORN", EVENT_BORN }, 01116 { "CLOCK", EVENT_CLOCK }, 01117 { "CRASH", EVENT_CRASH }, 01118 { "PLAYER_DEATH", EVENT_PLAYER_DEATH }, 01119 { "GKILL", EVENT_GKILL }, 01120 { "LOGIN", EVENT_LOGIN }, 01121 { "LOGOUT", EVENT_LOGOUT }, 01122 { "MAPENTER", EVENT_MAPENTER }, 01123 { "MAPLEAVE", EVENT_MAPLEAVE }, 01124 { "MAPRESET", EVENT_MAPRESET }, 01125 { "REMOVE", EVENT_REMOVE }, 01126 { "SHOUT", EVENT_SHOUT }, 01127 { "TELL", EVENT_TELL }, 01128 { "MUZZLE", EVENT_MUZZLE }, 01129 { "KICK", EVENT_KICK }, 01130 { "MAPUNLOAD", EVENT_MAPUNLOAD }, 01131 { "MAPLOAD", EVENT_MAPLOAD }, 01132 { "USER", EVENT_USER }, 01133 { NULL, 0 } 01134 }; 01135 01136 static const CFConstant cstTime[] = { 01137 { "HOURS_PER_DAY", HOURS_PER_DAY }, 01138 { "DAYS_PER_WEEK", DAYS_PER_WEEK }, 01139 { "WEEKS_PER_MONTH", WEEKS_PER_MONTH }, 01140 { "MONTHS_PER_YEAR", MONTHS_PER_YEAR }, 01141 { "SEASONS_PER_YEAR", SEASONS_PER_YEAR }, 01142 { "PERIODS_PER_DAY", PERIODS_PER_DAY }, 01143 { NULL, 0 } 01144 }; 01145 01146 addConstants(module, "Direction", cstDirection); 01147 addConstants(module, "Type", cstType); 01148 addConstants(module, "Move", cstMove); 01149 addConstants(module, "MessageFlag", cstMessageFlag); 01150 addConstants(module, "CostFlag", cstCostFlag); 01151 addConstants(module, "AttackType", cstAttackType); 01152 addConstants(module, "AttackTypeNumber", cstAttackTypeNumber); 01153 addConstants(module, "EventType", cstEventType); 01154 addSimpleConstants(module, "Time", cstTime); 01155 } 01156 01157 extern PyMODINIT_FUNC initcjson(void); 01158 01159 CF_PLUGIN int initPlugin(const char *iversion, f_plug_api gethooksptr) { 01160 PyObject *m, *d; 01161 int i; 01162 01163 cf_init_plugin(gethooksptr); 01164 cf_log(llevDebug, "CFPython 2.0a init\n"); 01165 01166 init_object_assoc_table(); 01167 init_map_assoc_table(); 01168 01169 #ifdef IS_PY26 01170 Py_Py3kWarningFlag++; 01171 #endif 01172 01173 Py_Initialize(); 01174 Crossfire_ObjectType.tp_new = PyType_GenericNew; 01175 Crossfire_MapType.tp_new = PyType_GenericNew; 01176 Crossfire_PlayerType.tp_new = PyType_GenericNew; 01177 Crossfire_ArchetypeType.tp_new = PyType_GenericNew; 01178 Crossfire_PartyType.tp_new = PyType_GenericNew; 01179 Crossfire_RegionType.tp_new = PyType_GenericNew; 01180 PyType_Ready(&Crossfire_ObjectType); 01181 PyType_Ready(&Crossfire_MapType); 01182 PyType_Ready(&Crossfire_PlayerType); 01183 PyType_Ready(&Crossfire_ArchetypeType); 01184 PyType_Ready(&Crossfire_PartyType); 01185 PyType_Ready(&Crossfire_RegionType); 01186 01187 m = Py_InitModule("Crossfire", CFPythonMethods); 01188 d = PyModule_GetDict(m); 01189 Py_INCREF(&Crossfire_ObjectType); 01190 Py_INCREF(&Crossfire_MapType); 01191 Py_INCREF(&Crossfire_PlayerType); 01192 Py_INCREF(&Crossfire_ArchetypeType); 01193 Py_INCREF(&Crossfire_PartyType); 01194 Py_INCREF(&Crossfire_RegionType); 01195 01196 PyModule_AddObject(m, "Object", (PyObject *)&Crossfire_ObjectType); 01197 PyModule_AddObject(m, "Map", (PyObject *)&Crossfire_MapType); 01198 PyModule_AddObject(m, "Player", (PyObject *)&Crossfire_PlayerType); 01199 PyModule_AddObject(m, "Archetype", (PyObject *)&Crossfire_ArchetypeType); 01200 PyModule_AddObject(m, "Party", (PyObject *)&Crossfire_PartyType); 01201 PyModule_AddObject(m, "Region", (PyObject *)&Crossfire_RegionType); 01202 01203 PyModule_AddObject(m, "LogError", Py_BuildValue("i", llevError)); 01204 PyModule_AddObject(m, "LogInfo", Py_BuildValue("i", llevInfo)); 01205 PyModule_AddObject(m, "LogDebug", Py_BuildValue("i", llevDebug)); 01206 PyModule_AddObject(m, "LogMonster", Py_BuildValue("i", llevMonster)); 01207 01208 CFPythonError = PyErr_NewException("Crossfire.error", NULL, NULL); 01209 PyDict_SetItemString(d, "error", CFPythonError); 01210 for (i = 0; i < NR_CUSTOM_CMD; i++) { 01211 CustomCommand[i].name = NULL; 01212 CustomCommand[i].script = NULL; 01213 CustomCommand[i].speed = 0.0; 01214 } 01215 initConstants(m); 01216 private_data = PyDict_New(); 01217 shared_data = PyDict_New(); 01218 01219 /* add cjson module*/ 01220 initcjson(); 01221 return 0; 01222 } 01223 01224 CF_PLUGIN void *getPluginProperty(int *type, ...) { 01225 va_list args; 01226 const char *propname; 01227 int i, size; 01228 command_array_struct *rtn_cmd; 01229 char *buf; 01230 01231 va_start(args, type); 01232 propname = va_arg(args, const char *); 01233 01234 if (!strcmp(propname, "command?")) { 01235 const char *cmdname; 01236 cmdname = va_arg(args, const char *); 01237 rtn_cmd = va_arg(args, command_array_struct *); 01238 va_end(args); 01239 01240 for (i = 0; i < NR_CUSTOM_CMD; i++) { 01241 if (CustomCommand[i].name != NULL) { 01242 if (!strcmp(CustomCommand[i].name, cmdname)) { 01243 rtn_cmd->name = CustomCommand[i].name; 01244 rtn_cmd->time = (float)CustomCommand[i].speed; 01245 rtn_cmd->func = cfpython_runPluginCommand; 01246 current_command = i; 01247 return rtn_cmd; 01248 } 01249 } 01250 } 01251 return NULL; 01252 } else if (!strcmp(propname, "Identification")) { 01253 buf = va_arg(args, char *); 01254 size = va_arg(args, int); 01255 va_end(args); 01256 snprintf(buf, size, PLUGIN_NAME); 01257 return NULL; 01258 } else if (!strcmp(propname, "FullName")) { 01259 buf = va_arg(args, char *); 01260 size = va_arg(args, int); 01261 va_end(args); 01262 snprintf(buf, size, PLUGIN_VERSION); 01263 return NULL; 01264 } 01265 va_end(args); 01266 return NULL; 01267 } 01268 01269 CF_PLUGIN int cfpython_runPluginCommand(object *op, char *params) { 01270 char buf[1024], path[1024]; 01271 CFPContext *context; 01272 static int rv = 0; 01273 01274 rv = 0; 01275 01276 if (current_command < 0) { 01277 cf_log(llevError, "Illegal call of cfpython_runPluginCommand, call find_plugin_command first.\n"); 01278 return 1; 01279 } 01280 snprintf(buf, sizeof(buf), "%s.py", cf_get_maps_directory(CustomCommand[current_command].script, path, sizeof(path))); 01281 01282 context = malloc(sizeof(CFPContext)); 01283 context->message[0] = 0; 01284 01285 context->who = Crossfire_Object_wrap(op); 01286 context->activator = NULL; 01287 context->third = NULL; 01288 context->fix = 0; 01289 snprintf(context->script, sizeof(context->script), "%s", buf); 01290 if (params) 01291 snprintf(context->options, sizeof(context->options), "%s", params); 01292 else 01293 context->options[0] = 0; 01294 context->returnvalue = 1; /* Default is "command successful" */ 01295 01296 current_command = -999; 01297 if (!do_script(context, 0)) { 01298 freeContext(context); 01299 return rv; 01300 } 01301 01302 context = popContext(); 01303 rv = context->returnvalue; 01304 freeContext(context); 01305 /* printf("Execution complete"); */ 01306 return rv; 01307 } 01308 01309 CF_PLUGIN int postInitPlugin(void) { 01310 PyObject *scriptfile; 01311 char path[1024]; 01312 01313 cf_log(llevDebug, "CFPython 2.0a post init\n"); 01314 initContextStack(); 01315 cf_system_register_global_event(EVENT_BORN, PLUGIN_NAME, cfpython_globalEventListener); 01316 cf_system_register_global_event(EVENT_CLOCK, PLUGIN_NAME, cfpython_globalEventListener); 01317 /*registerGlobalEvent(NULL, EVENT_CRASH, PLUGIN_NAME, cfpython_globalEventListener);*/ 01318 cf_system_register_global_event(EVENT_PLAYER_DEATH, PLUGIN_NAME, cfpython_globalEventListener); 01319 cf_system_register_global_event(EVENT_GKILL, PLUGIN_NAME, cfpython_globalEventListener); 01320 cf_system_register_global_event(EVENT_LOGIN, PLUGIN_NAME, cfpython_globalEventListener); 01321 cf_system_register_global_event(EVENT_LOGOUT, PLUGIN_NAME, cfpython_globalEventListener); 01322 cf_system_register_global_event(EVENT_MAPENTER, PLUGIN_NAME, cfpython_globalEventListener); 01323 cf_system_register_global_event(EVENT_MAPLEAVE, PLUGIN_NAME, cfpython_globalEventListener); 01324 cf_system_register_global_event(EVENT_MAPRESET, PLUGIN_NAME, cfpython_globalEventListener); 01325 cf_system_register_global_event(EVENT_REMOVE, PLUGIN_NAME, cfpython_globalEventListener); 01326 cf_system_register_global_event(EVENT_SHOUT, PLUGIN_NAME, cfpython_globalEventListener); 01327 cf_system_register_global_event(EVENT_TELL, PLUGIN_NAME, cfpython_globalEventListener); 01328 cf_system_register_global_event(EVENT_MUZZLE, PLUGIN_NAME, cfpython_globalEventListener); 01329 cf_system_register_global_event(EVENT_KICK, PLUGIN_NAME, cfpython_globalEventListener); 01330 cf_system_register_global_event(EVENT_MAPUNLOAD, PLUGIN_NAME, cfpython_globalEventListener); 01331 cf_system_register_global_event(EVENT_MAPLOAD, PLUGIN_NAME, cfpython_globalEventListener); 01332 01333 scriptfile = PyFile_FromString(cf_get_maps_directory("python/events/python_init.py", path, sizeof(path)), "r"); 01334 if (scriptfile != NULL) { 01335 PyRun_SimpleFile(PyFile_AsFile(scriptfile), cf_get_maps_directory("python/events/python_init.py", path, sizeof(path))); 01336 Py_DECREF(scriptfile); 01337 } 01338 01339 return 0; 01340 } 01341 01342 CF_PLUGIN void *cfpython_globalEventListener(int *type, ...) { 01343 va_list args; 01344 static int rv = 0; 01345 CFPContext *context; 01346 char *buf; 01347 player *pl; 01348 object *op; 01349 context = malloc(sizeof(CFPContext)); 01350 01351 rv = 0; 01352 01353 va_start(args, type); 01354 context->event_code = va_arg(args, int); 01355 01356 context->message[0] = 0; 01357 01358 context->who = NULL; 01359 context->activator = NULL; 01360 context->third = NULL; 01361 context->event = NULL; 01362 rv = context->returnvalue = 0; 01363 cf_get_maps_directory("python/events/python_event.py", context->script, sizeof(context->script)); 01364 strcpy(context->options, ""); 01365 switch (context->event_code) { 01366 case EVENT_CRASH: 01367 cf_log(llevDebug, "Unimplemented for now\n"); 01368 break; 01369 01370 case EVENT_BORN: 01371 op = va_arg(args, object *); 01372 context->activator = Crossfire_Object_wrap(op); 01373 snprintf(context->options, sizeof(context->options), "born"); 01374 break; 01375 01376 case EVENT_PLAYER_DEATH: 01377 op = va_arg(args, object *); 01378 context->who = Crossfire_Object_wrap(op); 01379 snprintf(context->options, sizeof(context->options), "death"); 01380 break; 01381 01382 case EVENT_GKILL: 01383 op = va_arg(args, object *); 01384 context->who = Crossfire_Object_wrap(op); 01385 context->activator = Crossfire_Object_wrap(op); 01386 snprintf(context->options, sizeof(context->options), "gkill"); 01387 break; 01388 01389 case EVENT_LOGIN: 01390 pl = va_arg(args, player *); 01391 context->activator = Crossfire_Object_wrap(pl->ob); 01392 buf = va_arg(args, char *); 01393 if (buf != NULL) 01394 snprintf(context->message, sizeof(context->message), "%s", buf); 01395 snprintf(context->options, sizeof(context->options), "login"); 01396 break; 01397 01398 case EVENT_LOGOUT: 01399 pl = va_arg(args, player *); 01400 context->activator = Crossfire_Object_wrap(pl->ob); 01401 buf = va_arg(args, char *); 01402 if (buf != NULL) 01403 snprintf(context->message, sizeof(context->message), "%s", buf); 01404 snprintf(context->options, sizeof(context->options), "logout"); 01405 break; 01406 01407 case EVENT_REMOVE: 01408 op = va_arg(args, object *); 01409 context->activator = Crossfire_Object_wrap(op); 01410 snprintf(context->options, sizeof(context->options), "remove"); 01411 break; 01412 01413 case EVENT_SHOUT: 01414 op = va_arg(args, object *); 01415 context->activator = Crossfire_Object_wrap(op); 01416 buf = va_arg(args, char *); 01417 if (buf != NULL) 01418 snprintf(context->message, sizeof(context->message), "%s", buf); 01419 snprintf(context->options, sizeof(context->options), "shout"); 01420 break; 01421 01422 case EVENT_MUZZLE: 01423 op = va_arg(args, object *); 01424 context->activator = Crossfire_Object_wrap(op); 01425 buf = va_arg(args, char *); 01426 if (buf != NULL) 01427 snprintf(context->message, sizeof(context->message), "%s", buf); 01428 snprintf(context->options, sizeof(context->options), "muzzle"); 01429 break; 01430 01431 case EVENT_KICK: 01432 op = va_arg(args, object *); 01433 context->activator = Crossfire_Object_wrap(op); 01434 buf = va_arg(args, char *); 01435 if (buf != NULL) 01436 snprintf(context->message, sizeof(context->message), "%s", buf); 01437 snprintf(context->options, sizeof(context->options), "kick"); 01438 break; 01439 01440 case EVENT_MAPENTER: 01441 op = va_arg(args, object *); 01442 context->activator = Crossfire_Object_wrap(op); 01443 context->who = Crossfire_Map_wrap(va_arg(args, mapstruct *)); 01444 snprintf(context->options, sizeof(context->options), "mapenter"); 01445 break; 01446 01447 case EVENT_MAPLEAVE: 01448 op = va_arg(args, object *); 01449 context->activator = Crossfire_Object_wrap(op); 01450 context->who = Crossfire_Map_wrap(va_arg(args, mapstruct *)); 01451 snprintf(context->options, sizeof(context->options), "mapleave"); 01452 break; 01453 01454 case EVENT_CLOCK: 01455 snprintf(context->options, sizeof(context->options), "clock"); 01456 break; 01457 01458 case EVENT_MAPRESET: 01459 context->who = Crossfire_Map_wrap(va_arg(args, mapstruct *)); 01460 snprintf(context->options, sizeof(context->options), "mapreset"); 01461 break; 01462 01463 case EVENT_TELL: 01464 op = va_arg(args, object *); 01465 buf = va_arg(args, char *); 01466 context->activator = Crossfire_Object_wrap(op); 01467 if (buf != NULL) 01468 snprintf(context->message, sizeof(context->message), "%s", buf); 01469 op = va_arg(args, object *); 01470 context->third = Crossfire_Object_wrap(op); 01471 snprintf(context->options, sizeof(context->options), "tell"); 01472 break; 01473 01474 case EVENT_MAPUNLOAD: 01475 context->who = Crossfire_Map_wrap(va_arg(args, mapstruct *)); 01476 snprintf(context->options, sizeof(context->options), "mapunload"); 01477 break; 01478 01479 case EVENT_MAPLOAD: 01480 context->who = Crossfire_Map_wrap(va_arg(args, mapstruct *)); 01481 snprintf(context->options, sizeof(context->options), "mapload"); 01482 break; 01483 } 01484 va_end(args); 01485 context->returnvalue = 0; 01486 01487 if (!do_script(context, 1)) { 01488 freeContext(context); 01489 return &rv; 01490 } 01491 01492 context = popContext(); 01493 rv = context->returnvalue; 01494 01495 /* Invalidate freed map wrapper. */ 01496 if (context->event_code == EVENT_MAPUNLOAD) 01497 Handle_Map_Unload_Hook((Crossfire_Map *)context->who); 01498 01499 freeContext(context); 01500 01501 return &rv; 01502 } 01503 01504 CF_PLUGIN void *eventListener(int *type, ...) { 01505 static int rv = 0; 01506 va_list args; 01507 char *buf; 01508 CFPContext *context; 01509 object *event; 01510 01511 rv = 0; 01512 01513 context = malloc(sizeof(CFPContext)); 01514 01515 context->message[0] = 0; 01516 01517 va_start(args, type); 01518 01519 context->who = Crossfire_Object_wrap(va_arg(args, object *)); 01520 context->activator = Crossfire_Object_wrap(va_arg(args, object *)); 01521 context->third = Crossfire_Object_wrap(va_arg(args, object *)); 01522 buf = va_arg(args, char *); 01523 if (buf != NULL) 01524 snprintf(context->message, sizeof(context->message), "%s", buf); 01525 context->fix = va_arg(args, int); 01526 event = va_arg(args, object *); 01527 context->event_code = event->subtype; 01528 context->event = Crossfire_Object_wrap(event); 01529 cf_get_maps_directory(event->slaying, context->script, sizeof(context->script)); 01530 snprintf(context->options, sizeof(context->options), "%s", event->name); 01531 context->returnvalue = 0; 01532 01533 va_end(args); 01534 01535 if (!do_script(context, 0)) { 01536 freeContext(context); 01537 return &rv; 01538 } 01539 01540 context = popContext(); 01541 rv = context->returnvalue; 01542 freeContext(context); 01543 return &rv; 01544 } 01545 01546 CF_PLUGIN int closePlugin(void) { 01547 cf_log(llevDebug, "CFPython 2.0a closing\n"); 01548 Py_Finalize(); 01549 return 0; 01550 }