|
Atrinik Server 2.5
|
00001 /************************************************************************ 00002 * Atrinik, a Multiplayer Online Role Playing Game * 00003 * * 00004 * Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team * 00005 * * 00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game) * 00007 * and Crossfire (Multiplayer game for X-windows). * 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 * This program is distributed in the hope that it will be useful, * 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00017 * GNU General Public License for more details. * 00018 * * 00019 * You should have received a copy of the GNU General Public License * 00020 * along with this program; if not, write to the Free Software * 00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 00022 * * 00023 * The author can be reached at admin@atrinik.org * 00024 ************************************************************************/ 00025 00030 #ifdef WIN32 00031 # include <fcntl.h> 00032 #endif 00033 00034 #include <plugin_python.h> 00035 00036 #include <compile.h> 00037 #include <eval.h> 00038 #ifdef STR 00039 /* STR is redefined in node.h. Since this file doesn't use STR, we remove it */ 00040 #undef STR 00041 #endif 00042 #include <node.h> 00043 00045 struct plugin_hooklist *hooks; 00046 00048 PyObject *AtrinikError; 00049 00051 static PythonContext *context_stack; 00053 PythonContext *current_context; 00054 00057 /* @cparser 00058 * @page plugin_python_constants Python constants 00059 * <h2>Python constants</h2> 00060 * List of the Python plugin constants and their meaning. */ 00061 static const Atrinik_Constant constants[] = 00062 { 00063 {"NORTH", NORTH}, 00064 {"NORTHEAST", NORTHEAST}, 00065 {"EAST", EAST}, 00066 {"SOUTHEAST", SOUTHEAST}, 00067 {"SOUTH", SOUTH}, 00068 {"SOUTHWEST", SOUTHWEST}, 00069 {"WEST", WEST}, 00070 {"NORTHWEST", NORTHWEST}, 00071 00072 {"llevSystem", llevSystem}, 00073 {"llevError", llevError}, 00074 {"llevBug", llevBug}, 00075 {"llevInfo", llevInfo}, 00076 {"llevDebug", llevDebug}, 00077 {"llevChat", llevChat}, 00078 00079 {"PLUGIN_EVENT_NORMAL", PLUGIN_EVENT_NORMAL}, 00080 {"PLUGIN_EVENT_GLOBAL", PLUGIN_EVENT_GLOBAL}, 00081 {"PLUGIN_EVENT_MAP", PLUGIN_EVENT_MAP}, 00082 00083 {"EVENT_APPLY", EVENT_APPLY}, 00084 {"EVENT_ATTACK", EVENT_ATTACK}, 00085 {"EVENT_DEATH", EVENT_DEATH}, 00086 {"EVENT_DROP", EVENT_DROP}, 00087 {"EVENT_PICKUP", EVENT_PICKUP}, 00088 {"EVENT_SAY", EVENT_SAY}, 00089 {"EVENT_STOP", EVENT_STOP}, 00090 {"EVENT_TIME", EVENT_TIME}, 00091 {"EVENT_THROW", EVENT_THROW}, 00092 {"EVENT_TRIGGER", EVENT_TRIGGER}, 00093 {"EVENT_CLOSE", EVENT_CLOSE}, 00094 {"EVENT_TIMER", EVENT_TIMER}, 00095 {"EVENT_ASK_SHOW", EVENT_ASK_SHOW}, 00096 00097 {"MEVENT_ENTER", MEVENT_ENTER}, 00098 {"MEVENT_LEAVE", MEVENT_LEAVE}, 00099 {"MEVENT_RESET", MEVENT_RESET}, 00100 {"MEVENT_SPELL_CAST", MEVENT_SPELL_CAST}, 00101 {"MEVENT_SKILL_USED", MEVENT_SKILL_USED}, 00102 {"MEVENT_DROP", MEVENT_DROP}, 00103 {"MEVENT_PICK", MEVENT_PICK}, 00104 {"MEVENT_PUT", MEVENT_PUT}, 00105 {"MEVENT_APPLY", MEVENT_APPLY}, 00106 {"MEVENT_LOGIN", MEVENT_LOGIN}, 00107 {"MEVENT_CMD_DROP", MEVENT_CMD_DROP}, 00108 {"MEVENT_CMD_TAKE", MEVENT_CMD_TAKE}, 00109 {"MEVENT_EXAMINE", MEVENT_EXAMINE}, 00110 00111 {"GEVENT_BORN", GEVENT_BORN}, 00112 {"GEVENT_LOGIN", GEVENT_LOGIN}, 00113 {"GEVENT_LOGOUT", GEVENT_LOGOUT}, 00114 {"GEVENT_PLAYER_DEATH", GEVENT_PLAYER_DEATH}, 00115 {"GEVENT_CACHE_REMOVED", GEVENT_CACHE_REMOVED}, 00116 00117 {"MAP_INFO_NORMAL", MAP_INFO_NORMAL}, 00118 {"MAP_INFO_ALL", MAP_INFO_ALL}, 00119 00120 {"COST_TRUE", COST_TRUE}, 00121 {"COST_BUY", COST_BUY}, 00122 {"COST_SELL", COST_SELL}, 00123 00124 {"APPLY_TOGGLE", 0}, 00125 {"APPLY_ALWAYS", AP_APPLY}, 00126 {"UNAPPLY_ALWAYS", AP_UNAPPLY}, 00127 {"UNAPPLY_NO_MERGE", AP_NO_MERGE}, 00128 {"UNAPPLY_IGNORE_CURSE", AP_IGNORE_CURSE}, 00129 {"APPLY_NO_EVENT", AP_NO_EVENT}, 00130 00131 {"MAXLEVEL", MAXLEVEL}, 00132 00133 {"CAST_NORMAL", CAST_NORMAL}, 00134 {"CAST_WAND", CAST_WAND}, 00135 {"CAST_ROD", CAST_ROD}, 00136 {"CAST_HORN", CAST_HORN}, 00137 {"CAST_SCROLL", CAST_SCROLL}, 00138 {"CAST_POTION", CAST_POTION}, 00139 {"CAST_NPC", CAST_NPC}, 00140 00141 {"IDENTIFY_NORMAL", IDENTIFY_NORMAL}, 00142 {"IDENTIFY_ALL", IDENTIFY_ALL}, 00143 {"IDENTIFY_MARKED", IDENTIFY_MARKED}, 00144 00145 {"CLONE_WITH_INVENTORY", 0}, 00146 {"CLONE_WITHOUT_INVENTORY", 1}, 00147 00148 {"EXP_AGILITY", EXP_AGILITY}, 00149 {"EXP_MENTAL", EXP_MENTAL}, 00150 {"EXP_MAGICAL", EXP_MAGICAL}, 00151 {"EXP_PERSONAL", EXP_PERSONAL}, 00152 {"EXP_PHYSICAL", EXP_PHYSICAL}, 00153 {"EXP_WISDOM", EXP_WISDOM}, 00154 00155 {"NDI_SAY", NDI_SAY}, 00156 {"NDI_SHOUT", NDI_SHOUT}, 00157 {"NDI_TELL", NDI_TELL}, 00158 {"NDI_PLAYER", NDI_PLAYER}, 00159 {"NDI_ANIM", NDI_ANIM}, 00160 {"NDI_EMOTE", NDI_EMOTE}, 00161 {"NDI_ALL", NDI_ALL}, 00162 00163 {"PLAYER_EQUIP_MAIL", PLAYER_EQUIP_MAIL}, 00164 {"PLAYER_EQUIP_GAUNTLET", PLAYER_EQUIP_GAUNTLET}, 00165 {"PLAYER_EQUIP_BRACER", PLAYER_EQUIP_BRACER}, 00166 {"PLAYER_EQUIP_HELM", PLAYER_EQUIP_HELM}, 00167 {"PLAYER_EQUIP_BOOTS", PLAYER_EQUIP_BOOTS}, 00168 {"PLAYER_EQUIP_CLOAK", PLAYER_EQUIP_CLOAK}, 00169 {"PLAYER_EQUIP_GIRDLE", PLAYER_EQUIP_GIRDLE}, 00170 {"PLAYER_EQUIP_SHIELD", PLAYER_EQUIP_SHIELD}, 00171 {"PLAYER_EQUIP_RRING", PLAYER_EQUIP_RRING}, 00172 {"PLAYER_EQUIP_LRING", PLAYER_EQUIP_LRING}, 00173 {"PLAYER_EQUIP_AMULET", PLAYER_EQUIP_AMULET}, 00174 {"PLAYER_EQUIP_WEAPON", PLAYER_EQUIP_WEAPON}, 00175 {"PLAYER_EQUIP_BOW", PLAYER_EQUIP_BOW}, 00176 00177 {"QUEST_TYPE_SPECIAL", QUEST_TYPE_SPECIAL}, 00178 {"QUEST_TYPE_KILL", QUEST_TYPE_KILL}, 00179 {"QUEST_TYPE_KILL_ITEM", QUEST_TYPE_KILL_ITEM}, 00180 {"QUEST_TYPE_MULTI", QUEST_TYPE_MULTI}, 00181 {"QUEST_STATUS_COMPLETED", QUEST_STATUS_COMPLETED}, 00182 00183 {"PARTY_MESSAGE_STATUS", PARTY_MESSAGE_STATUS}, 00184 {"PARTY_MESSAGE_CHAT", PARTY_MESSAGE_CHAT}, 00185 00186 {"ATNR_IMPACT", ATNR_IMPACT}, 00187 {"ATNR_SLASH", ATNR_SLASH}, 00188 {"ATNR_CLEAVE", ATNR_CLEAVE}, 00189 {"ATNR_PIERCE", ATNR_PIERCE}, 00190 {"ATNR_WEAPON_MAGIC", ATNR_WEAPON_MAGIC}, 00191 {"ATNR_FIRE", ATNR_FIRE}, 00192 {"ATNR_COLD", ATNR_COLD}, 00193 {"ATNR_ELECTRICITY", ATNR_ELECTRICITY}, 00194 {"ATNR_POISON", ATNR_POISON}, 00195 {"ATNR_ACID", ATNR_ACID}, 00196 {"ATNR_MAGIC", ATNR_MAGIC}, 00197 {"ATNR_MIND", ATNR_MIND}, 00198 {"ATNR_BLIND", ATNR_BLIND}, 00199 {"ATNR_PARALYZE", ATNR_PARALYZE}, 00200 {"ATNR_FORCE", ATNR_FORCE}, 00201 {"ATNR_GODPOWER", ATNR_GODPOWER}, 00202 {"ATNR_CHAOS", ATNR_CHAOS}, 00203 {"ATNR_DRAIN", ATNR_DRAIN}, 00204 {"ATNR_SLOW", ATNR_SLOW}, 00205 {"ATNR_CONFUSION", ATNR_CONFUSION}, 00206 {"ATNR_INTERNAL", ATNR_INTERNAL}, 00207 {"NROFATTACKS", NROFATTACKS}, 00208 00209 {"TERRAIN_NOTHING", TERRAIN_NOTHING}, 00210 {"TERRAIN_AIRBREATH", TERRAIN_NOTHING}, 00211 {"TERRAIN_WATERWALK", TERRAIN_WATERWALK}, 00212 {"TERRAIN_WATERBREATH", TERRAIN_WATERBREATH}, 00213 {"TERRAIN_FIREWALK", TERRAIN_FIREWALK}, 00214 {"TERRAIN_FIREBREATH", TERRAIN_FIREBREATH}, 00215 {"TERRAIN_CLOUDWALK", TERRAIN_CLOUDWALK}, 00216 {"TERRAIN_ALL", TERRAIN_ALL}, 00217 00218 {"P_BLOCKSVIEW", P_BLOCKSVIEW}, 00219 {"P_NO_MAGIC", P_NO_MAGIC}, 00220 {"P_NO_PASS", P_NO_PASS}, 00221 {"P_IS_PLAYER", P_IS_PLAYER}, 00222 {"P_IS_ALIVE", P_IS_ALIVE}, 00223 {"P_NO_CLERIC", P_NO_CLERIC}, 00224 {"P_PLAYER_ONLY", P_PLAYER_ONLY}, 00225 {"P_DOOR_CLOSED", P_DOOR_CLOSED}, 00226 {"P_CHECK_INV", P_CHECK_INV}, 00227 {"P_NO_PVP", P_NO_PVP}, 00228 {"P_PASS_THRU", P_PASS_THRU}, 00229 {"P_MAGIC_EAR", P_MAGIC_EAR}, 00230 {"P_WALK_ON", P_WALK_ON}, 00231 {"P_WALK_OFF", P_WALK_OFF}, 00232 {"P_FLY_OFF", P_FLY_OFF}, 00233 {"P_FLY_ON", P_FLY_ON}, 00234 {"P_MAGIC_MIRROR", P_MAGIC_MIRROR}, 00235 {"P_OUTDOOR", P_OUTDOOR}, 00236 {"P_OUT_OF_MAP", P_OUT_OF_MAP}, 00237 {"P_FLAGS_ONLY", P_FLAGS_ONLY}, 00238 {"P_FLAGS_UPDATE", P_FLAGS_UPDATE}, 00239 {"P_NEED_UPDATE", P_NEED_UPDATE}, 00240 {"P_NO_ERROR", P_NO_ERROR}, 00241 {"P_NO_TERRAIN", P_NO_TERRAIN}, 00242 00243 {"CMD_SOUND_EFFECT", CMD_SOUND_EFFECT}, 00244 {"CMD_SOUND_BACKGROUND", CMD_SOUND_BACKGROUND}, 00245 {"CMD_SOUND_ABSOLUTE", CMD_SOUND_ABSOLUTE}, 00246 00247 {"BANK_SYNTAX_ERROR", BANK_SYNTAX_ERROR}, 00248 {"BANK_SUCCESS", BANK_SUCCESS}, 00249 00250 {"BANK_WITHDRAW_HIGH", BANK_WITHDRAW_HIGH}, 00251 {"BANK_WITHDRAW_MISSING", BANK_WITHDRAW_MISSING}, 00252 {"BANK_WITHDRAW_OVERWEIGHT", BANK_WITHDRAW_OVERWEIGHT}, 00253 00254 {"BANK_DEPOSIT_COPPER", BANK_DEPOSIT_COPPER}, 00255 {"BANK_DEPOSIT_SILVER", BANK_DEPOSIT_SILVER}, 00256 {"BANK_DEPOSIT_GOLD", BANK_DEPOSIT_GOLD}, 00257 {"BANK_DEPOSIT_MITHRIL", BANK_DEPOSIT_MITHRIL}, 00258 00259 {"AROUND_ALL", AROUND_ALL}, 00260 {"AROUND_WALL", AROUND_WALL}, 00261 {"AROUND_BLOCKSVIEW", AROUND_BLOCKSVIEW}, 00262 {"AROUND_PLAYER_ONLY", AROUND_PLAYER_ONLY}, 00263 00264 {"LAYER_SYS", LAYER_SYS}, 00265 {"LAYER_FLOOR", LAYER_FLOOR}, 00266 {"LAYER_FMASK", LAYER_FMASK}, 00267 {"LAYER_ITEM", LAYER_ITEM}, 00268 {"LAYER_ITEM2", LAYER_ITEM2}, 00269 {"LAYER_WALL", LAYER_WALL}, 00270 {"LAYER_LIVING", LAYER_LIVING}, 00271 {"LAYER_EFFECT", LAYER_EFFECT}, 00272 00273 {"INVENTORY_ONLY", INVENTORY_ONLY}, 00274 {"INVENTORY_CONTAINERS", INVENTORY_CONTAINERS}, 00275 {"INVENTORY_ALL", INVENTORY_ALL}, 00276 00277 {"GT_ENVIRONMENT", GT_ENVIRONMENT}, 00278 {"GT_INVISIBLE", GT_INVISIBLE}, 00279 {"GT_STARTEQUIP", GT_STARTEQUIP}, 00280 {"GT_APPLY", GT_APPLY}, 00281 {"GT_ONLY_GOOD", GT_ONLY_GOOD}, 00282 {"GT_UPDATE_INV", GT_UPDATE_INV}, 00283 {"GT_NO_VALUE", GT_NO_VALUE}, 00284 00285 {"SIZEOFFREE", SIZEOFFREE}, 00286 {"SIZEOFFREE1", SIZEOFFREE1}, 00287 {"SIZEOFFREE2", SIZEOFFREE2}, 00288 00289 {"NROFREALSPELLS", NROFREALSPELLS}, 00290 00291 {NULL, 0} 00292 }; 00293 /* @endcparser */ 00294 00296 /* @cparser 00297 * @page plugin_python_constants_types Python game object type constants 00298 * <h2>Python game object type constants</h2> 00299 * List of the Python plugin game object type constants and their meaning. */ 00300 static const Atrinik_Constant constants_types[] = 00301 { 00302 {"PLAYER", PLAYER}, 00303 {"BULLET", BULLET}, 00304 {"ROD", ROD}, 00305 {"TREASURE", TREASURE}, 00306 {"POTION", POTION}, 00307 {"FOOD", FOOD}, 00308 {"POISON", POISON}, 00309 {"BOOK", BOOK}, 00310 {"CLOCK", CLOCK}, 00311 {"LIGHTNING", LIGHTNING}, 00312 {"ARROW", ARROW}, 00313 {"BOW", BOW}, 00314 {"WEAPON", WEAPON}, 00315 {"ARMOUR", ARMOUR}, 00316 {"PEDESTAL", PEDESTAL}, 00317 {"ALTAR", ALTAR}, 00318 {"CONFUSION", CONFUSION}, 00319 {"DOOR", DOOR}, 00320 {"KEY", KEY}, 00321 {"MAP", MAP}, 00322 {"MMISSILE", MMISSILE}, 00323 {"TIMED_GATE", TIMED_GATE}, 00324 {"TRIGGER", TRIGGER}, 00325 {"MAGIC_EAR", MAGIC_EAR}, 00326 {"TRIGGER_BUTTON", TRIGGER_BUTTON}, 00327 {"TRIGGER_ALTAR", TRIGGER_ALTAR}, 00328 {"TRIGGER_PEDESTAL", TRIGGER_PEDESTAL}, 00329 {"SHIELD", SHIELD}, 00330 {"HELMET", HELMET}, 00331 {"HORN", HORN}, 00332 {"MONEY", MONEY}, 00333 {"CLASS", CLASS}, 00334 {"GRAVESTONE", GRAVESTONE}, 00335 {"AMULET", AMULET}, 00336 {"PLAYERMOVER", PLAYERMOVER}, 00337 {"TELEPORTER", TELEPORTER}, 00338 {"CREATOR", CREATOR}, 00339 {"SKILL", SKILL}, 00340 {"EXPERIENCE", EXPERIENCE}, 00341 {"BOMB", BOMB}, 00342 {"THROWN_OBJ", THROWN_OBJ}, 00343 {"BLINDNESS", BLINDNESS}, 00344 {"GOD", GOD}, 00345 {"DETECTOR", DETECTOR}, 00346 {"SKILL_ITEM", SKILL_ITEM}, 00347 {"DEAD_OBJECT", DEAD_OBJECT}, 00348 {"DRINK", DRINK}, 00349 {"MARKER", MARKER}, 00350 {"HOLY_ALTAR", HOLY_ALTAR}, 00351 {"PEARL", PEARL}, 00352 {"GEM", GEM}, 00353 {"FIREWALL", FIREWALL}, 00354 {"CHECK_INV", CHECK_INV}, 00355 {"MOOD_FLOOR", MOOD_FLOOR}, 00356 {"EXIT", EXIT}, 00357 {"SHOP_FLOOR", SHOP_FLOOR}, 00358 {"SHOP_MAT", SHOP_MAT}, 00359 {"RING", RING}, 00360 {"FLOOR", FLOOR}, 00361 {"FLESH", FLESH}, 00362 {"INORGANIC", INORGANIC}, 00363 {"LIGHT_APPLY", LIGHT_APPLY}, 00364 {"LIGHTER", LIGHTER}, 00365 {"WALL", WALL}, 00366 {"LIGHT_SOURCE", LIGHT_SOURCE}, 00367 {"MISC_OBJECT", MISC_OBJECT}, 00368 {"MONSTER", MONSTER}, 00369 {"SPAWN_POINT", SPAWN_POINT}, 00370 {"LIGHT_REFILL", LIGHT_REFILL}, 00371 {"SPAWN_POINT_MOB", SPAWN_POINT_MOB}, 00372 {"SPAWN_POINT_INFO", SPAWN_POINT_INFO}, 00373 {"SPELLBOOK", SPELLBOOK}, 00374 {"ORGANIC", ORGANIC}, 00375 {"CLOAK", CLOAK}, 00376 {"CONE", CONE}, 00377 {"SPINNER", SPINNER}, 00378 {"GATE", GATE}, 00379 {"BUTTON", BUTTON}, 00380 {"HANDLE", HANDLE}, 00381 {"PIT", PIT}, 00382 {"TRAPDOOR", TRAPDOOR}, 00383 {"WORD_OF_RECALL", WORD_OF_RECALL}, 00384 {"SIGN", SIGN}, 00385 {"BOOTS", BOOTS}, 00386 {"GLOVES", GLOVES}, 00387 {"BASE_INFO", BASE_INFO}, 00388 {"RANDOM_DROP", RANDOM_DROP}, 00389 {"CONVERTER", CONVERTER}, 00390 {"BRACERS", BRACERS}, 00391 {"POISONING", POISONING}, 00392 {"SAVEBED", SAVEBED}, 00393 {"WAND", WAND}, 00394 {"ABILITY", ABILITY}, 00395 {"SCROLL", SCROLL}, 00396 {"DIRECTOR", DIRECTOR}, 00397 {"GIRDLE", GIRDLE}, 00398 {"FORCE", FORCE}, 00399 {"POTION_EFFECT", POTION_EFFECT}, 00400 {"JEWEL", JEWEL}, 00401 {"NUGGET", NUGGET}, 00402 {"EVENT_OBJECT", EVENT_OBJECT}, 00403 {"WAYPOINT_OBJECT", WAYPOINT_OBJECT}, 00404 {"QUEST_CONTAINER", QUEST_CONTAINER}, 00405 {"CLOSE_CON", CLOSE_CON}, 00406 {"CONTAINER", CONTAINER}, 00407 {"ARMOUR_IMPROVER", ARMOUR_IMPROVER}, 00408 {"WEAPON_IMPROVER", WEAPON_IMPROVER}, 00409 {"WEALTH", WEALTH}, 00410 {"SKILLSCROLL", SKILLSCROLL}, 00411 {"DEEP_SWAMP", DEEP_SWAMP}, 00412 {"IDENTIFY_ALTAR", IDENTIFY_ALTAR}, 00413 {"SWARM_SPELL", SWARM_SPELL}, 00414 {"RUNE", RUNE}, 00415 {"POWER_CRYSTAL", POWER_CRYSTAL}, 00416 {"CORPSE", CORPSE}, 00417 {"DISEASE", DISEASE}, 00418 {"SYMPTOM", SYMPTOM}, 00419 {"MAP_EVENT_OBJ", MAP_EVENT_OBJ}, 00420 {"MAP_INFO", MAP_INFO}, 00421 {"COMPASS", COMPASS}, 00422 00423 {NULL, 0} 00424 }; 00425 /* @endcparser */ 00426 00428 /* @cparser 00429 * @page plugin_python_constants_gender Python gender constants 00430 * <h2>Python gender constants</h2> 00431 * List of the Python plugin gender constants and their meaning. */ 00432 static const Atrinik_Constant constants_gender[] = 00433 { 00434 {"NEUTER", GENDER_NEUTER}, 00435 {"MALE", GENDER_MALE}, 00436 {"FEMALE", GENDER_FEMALE}, 00437 {"HERMAPHRODITE", GENDER_HERMAPHRODITE}, 00438 00439 {NULL, 0} 00440 }; 00441 /* @endcparser */ 00442 00445 /* @cparser 00446 * @page plugin_python_constants_colors Python color constants 00447 * <h2>Python color constants</h2> 00448 * List of the Python plugin color constants and their meaning. */ 00449 static const char *const constants_colors[][2] = 00450 { 00451 {"COLOR_WHITE", COLOR_WHITE}, 00452 {"COLOR_ORANGE", COLOR_ORANGE}, 00453 {"COLOR_NAVY", COLOR_NAVY}, 00454 {"COLOR_RED", COLOR_RED}, 00455 {"COLOR_GREEN", COLOR_GREEN}, 00456 {"COLOR_BLUE", COLOR_BLUE}, 00457 {"COLOR_GRAY", COLOR_GRAY}, 00458 {"COLOR_BROWN", COLOR_BROWN}, 00459 {"COLOR_PURPLE", COLOR_PURPLE}, 00460 {"COLOR_PINK", COLOR_PINK}, 00461 {"COLOR_YELLOW", COLOR_YELLOW}, 00462 {"COLOR_DK_NAVY", COLOR_DK_NAVY}, 00463 {"COLOR_DK_GREEN", COLOR_DK_GREEN}, 00464 {"COLOR_DK_ORANGE", COLOR_DK_ORANGE}, 00465 {"COLOR_HGOLD", COLOR_HGOLD}, 00466 {"COLOR_DGOLD", COLOR_DGOLD}, 00467 {NULL, NULL} 00468 }; 00469 /* @endcparser */ 00470 00472 static PythonCmd CustomCommand[NR_CUSTOM_CMD]; 00474 static int NextCustomCommand; 00475 00477 #define PYTHON_CACHE_SIZE 256 00478 00480 typedef struct 00481 { 00483 const char *file; 00484 00486 PyCodeObject *code; 00487 00489 time_t cached_time; 00490 00492 time_t used_time; 00493 } cacheentry; 00494 00496 static cacheentry python_cache[PYTHON_CACHE_SIZE]; 00497 00498 static int cmd_customPython(object *op, char *params); 00499 00502 static void initContextStack() 00503 { 00504 current_context = NULL; 00505 context_stack = NULL; 00506 } 00507 00511 static void pushContext(PythonContext *context) 00512 { 00513 if (current_context == NULL) 00514 { 00515 context_stack = context; 00516 context->down = NULL; 00517 } 00518 else 00519 { 00520 context->down = current_context; 00521 } 00522 00523 current_context = context; 00524 } 00525 00531 static PythonContext *popContext() 00532 { 00533 PythonContext *oldcontext; 00534 00535 if (current_context) 00536 { 00537 oldcontext = current_context; 00538 current_context = current_context->down; 00539 return oldcontext; 00540 } 00541 00542 return NULL; 00543 } 00544 00548 static void freeContext(PythonContext *context) 00549 { 00550 free(context); 00551 } 00552 00562 static PyObject *Atrinik_LoadObject(PyObject *self, PyObject *args) 00563 { 00564 char *dumpob; 00565 00566 (void) self; 00567 00568 if (!PyArg_ParseTuple(args, "s", &dumpob)) 00569 { 00570 return NULL; 00571 } 00572 00573 return wrap_object(hooks->load_object_str(dumpob)); 00574 } 00575 00583 static PyObject *Atrinik_ReadyMap(PyObject *self, PyObject *args) 00584 { 00585 const char *path; 00586 int flags = 0, unique = 0; 00587 00588 (void) self; 00589 00590 if (!PyArg_ParseTuple(args, "s|i", &path, &unique)) 00591 { 00592 return NULL; 00593 } 00594 00595 if (unique) 00596 { 00597 flags |= MAP_PLAYER_UNIQUE; 00598 } 00599 00600 return wrap_map(hooks->ready_map_name(path, flags)); 00601 } 00602 00608 static PyObject *Atrinik_FindPlayer(PyObject *self, PyObject *args) 00609 { 00610 const char *name; 00611 player *pl; 00612 00613 (void) self; 00614 00615 if (!PyArg_ParseTuple(args, "s", &name)) 00616 { 00617 return NULL; 00618 } 00619 00620 pl = hooks->find_player(name); 00621 00622 if (pl) 00623 { 00624 return wrap_object(pl->ob); 00625 } 00626 00627 Py_INCREF(Py_None); 00628 return Py_None; 00629 } 00630 00636 static PyObject *Atrinik_PlayerExists(PyObject *self, PyObject *args) 00637 { 00638 const char *name; 00639 char *cp; 00640 int ret; 00641 00642 (void) self; 00643 00644 if (!PyArg_ParseTuple(args, "s", &name)) 00645 { 00646 return NULL; 00647 } 00648 00649 cp = hooks->strdup_local(name); 00650 hooks->adjust_player_name(cp); 00651 ret = hooks->player_exists(cp); 00652 free(cp); 00653 00654 Py_ReturnBoolean(ret); 00655 } 00656 00662 static PyObject *Atrinik_WhoAmI(PyObject *self, PyObject *args) 00663 { 00664 (void) self; 00665 (void) args; 00666 return wrap_object(current_context->who); 00667 } 00668 00673 static PyObject *Atrinik_WhoIsActivator(PyObject *self, PyObject *args) 00674 { 00675 (void) self; 00676 (void) args; 00677 return wrap_object(current_context->activator); 00678 } 00679 00685 static PyObject *Atrinik_WhoIsOther(PyObject *self, PyObject *args) 00686 { 00687 (void) self; 00688 (void) args; 00689 return wrap_object(current_context->other); 00690 } 00691 00696 static PyObject *Atrinik_WhatIsEvent(PyObject *self, PyObject *args) 00697 { 00698 (void) self; 00699 (void) args; 00700 return wrap_object(current_context->event); 00701 } 00702 00707 static PyObject *Atrinik_GetEventNumber(PyObject *self, PyObject *args) 00708 { 00709 (void) self; 00710 (void) args; 00711 return Py_BuildValue("i", current_context->event->sub_type); 00712 } 00713 00718 static PyObject *Atrinik_WhatIsMessage(PyObject *self, PyObject *args) 00719 { 00720 (void) self; 00721 (void) args; 00722 return Py_BuildValue("s", current_context->text); 00723 } 00724 00729 static PyObject *Atrinik_GetOptions(PyObject *self, PyObject *args) 00730 { 00731 (void) self; 00732 (void) args; 00733 return Py_BuildValue("s", current_context->options); 00734 } 00735 00740 static PyObject *Atrinik_GetReturnValue(PyObject *self, PyObject *args) 00741 { 00742 (void) self; 00743 (void) args; 00744 return Py_BuildValue("i", current_context->returnvalue); 00745 } 00746 00751 static PyObject *Atrinik_SetReturnValue(PyObject *self, PyObject *args) 00752 { 00753 int value; 00754 00755 (void) self; 00756 00757 if (!PyArg_ParseTuple(args, "i", &value)) 00758 { 00759 return NULL; 00760 } 00761 00762 current_context->returnvalue = value; 00763 00764 Py_INCREF(Py_None); 00765 return Py_None; 00766 } 00767 00775 static PyObject *Atrinik_GetEventParameters(PyObject *self, PyObject *args) 00776 { 00777 size_t i; 00778 PyObject *list = PyList_New(0); 00779 00780 (void) self; 00781 (void) args; 00782 00783 for (i = 0; i < sizeof(current_context->parms) / sizeof(current_context->parms[0]); i++) 00784 { 00785 PyList_Append(list, Py_BuildValue("i", current_context->parms[i])); 00786 } 00787 00788 return list; 00789 } 00790 00796 static PyObject *Atrinik_GetSpellNr(PyObject *self, PyObject *args) 00797 { 00798 const char *spell; 00799 00800 (void) self; 00801 00802 if (!PyArg_ParseTuple(args, "s", &spell)) 00803 { 00804 return NULL; 00805 } 00806 00807 return Py_BuildValue("i", hooks->look_up_spell_name(spell)); 00808 } 00809 00823 static PyObject *Atrinik_GetSpell(PyObject *self, PyObject *args) 00824 { 00825 int spell; 00826 PyObject *dict; 00827 00828 (void) self; 00829 00830 if (!PyArg_ParseTuple(args, "i", &spell)) 00831 { 00832 return NULL; 00833 } 00834 00835 if (spell < 0 || spell >= NROFREALSPELLS) 00836 { 00837 PyErr_SetString(PyExc_ValueError, "Invalid ID of a spell."); 00838 return NULL; 00839 } 00840 00841 dict = PyDict_New(); 00842 00843 PyDict_SetItemString(dict, "name", Py_BuildValue("s", hooks->spells[spell].name)); 00844 PyDict_SetItemString(dict, "level", Py_BuildValue("i", hooks->spells[spell].level)); 00845 PyDict_SetItemString(dict, "type", Py_BuildValue("s", hooks->spells[spell].type == SPELL_TYPE_WIZARD ? "wizard" : "priest")); 00846 PyDict_SetItemString(dict, "sp", Py_BuildValue("i", hooks->spells[spell].sp)); 00847 PyDict_SetItemString(dict, "time", Py_BuildValue("i", hooks->spells[spell].time)); 00848 00849 return dict; 00850 } 00851 00857 static PyObject *Atrinik_GetSkillNr(PyObject *self, PyObject *args) 00858 { 00859 const char *skill; 00860 00861 (void) self; 00862 00863 if (!PyArg_ParseTuple(args, "s", &skill)) 00864 { 00865 return NULL; 00866 } 00867 00868 return Py_BuildValue("i", hooks->lookup_skill_by_name(skill)); 00869 } 00870 00879 static PyObject *Atrinik_RegisterCommand(PyObject *self, PyObject *args) 00880 { 00881 const char *name, *path; 00882 double speed; 00883 size_t i; 00884 00885 (void) self; 00886 00887 if (!PyArg_ParseTuple(args, "ssd", &name, &path, &speed)) 00888 { 00889 return NULL; 00890 } 00891 00892 for (i = 0; i < NR_CUSTOM_CMD; i++) 00893 { 00894 if (CustomCommand[i].name) 00895 { 00896 if (!strcmp(CustomCommand[i].name, name)) 00897 { 00898 PyErr_SetString(PyExc_ValueError, "RegisterCommand(): Command is already registered."); 00899 return NULL; 00900 } 00901 } 00902 } 00903 00904 for (i = 0; i < NR_CUSTOM_CMD; i++) 00905 { 00906 if (!CustomCommand[i].name) 00907 { 00908 CustomCommand[i].name = hooks->strdup_local(name); 00909 CustomCommand[i].script = hooks->strdup_local(path); 00910 CustomCommand[i].speed = speed; 00911 break; 00912 } 00913 } 00914 00915 Py_INCREF(Py_None); 00916 return Py_None; 00917 } 00918 00925 static PyObject *Atrinik_CreatePathname(PyObject *self, PyObject *args) 00926 { 00927 const char *path; 00928 00929 (void) self; 00930 00931 if (!PyArg_ParseTuple(args, "s", &path)) 00932 { 00933 return NULL; 00934 } 00935 00936 return Py_BuildValue("s", hooks->create_pathname(path)); 00937 } 00938 00956 static PyObject *Atrinik_GetTime(PyObject *self, PyObject *args) 00957 { 00958 PyObject *dict = PyDict_New(); 00959 timeofday_t tod; 00960 00961 (void) self; 00962 (void) args; 00963 00964 hooks->get_tod(&tod); 00965 00966 PyDict_SetItemString(dict, "year", Py_BuildValue("i", tod.year + 1)); 00967 PyDict_SetItemString(dict, "month", Py_BuildValue("i", tod.month + 1)); 00968 PyDict_SetItemString(dict, "month_name", Py_BuildValue("s", hooks->month_name[tod.month])); 00969 PyDict_SetItemString(dict, "day", Py_BuildValue("i", tod.day + 1)); 00970 PyDict_SetItemString(dict, "hour", Py_BuildValue("i", tod.hour)); 00971 PyDict_SetItemString(dict, "minute", Py_BuildValue("i", tod.minute)); 00972 PyDict_SetItemString(dict, "dayofweek", Py_BuildValue("i", tod.dayofweek + 1)); 00973 PyDict_SetItemString(dict, "dayofweek_name", Py_BuildValue("s", hooks->weekdays[tod.dayofweek])); 00974 PyDict_SetItemString(dict, "season", Py_BuildValue("i", tod.season + 1)); 00975 PyDict_SetItemString(dict, "season_name", Py_BuildValue("s", hooks->season_name[tod.season])); 00976 PyDict_SetItemString(dict, "periodofday", Py_BuildValue("i", tod.periodofday + 1)); 00977 PyDict_SetItemString(dict, "periodofday_name", Py_BuildValue("s", hooks->periodsofday[tod.periodofday])); 00978 00979 return dict; 00980 } 00981 00987 static PyObject *Atrinik_LocateBeacon(PyObject *self, PyObject *args) 00988 { 00989 const char *name; 00990 shstr *beacon_name = NULL; 00991 object *myob; 00992 00993 (void) self; 00994 00995 if (!PyArg_ParseTuple(args, "s", &name)) 00996 { 00997 return NULL; 00998 } 00999 01000 FREE_AND_COPY_HASH(beacon_name, name); 01001 myob = hooks->beacon_locate(beacon_name); 01002 FREE_AND_CLEAR_HASH(beacon_name); 01003 01004 return wrap_object(myob); 01005 } 01006 01012 static PyObject *Atrinik_FindParty(PyObject *self, PyObject *args) 01013 { 01014 const char *name; 01015 01016 (void) self; 01017 01018 if (!PyArg_ParseTuple(args, "s", &name)) 01019 { 01020 return NULL; 01021 } 01022 01023 return wrap_party(hooks->find_party(name)); 01024 } 01025 01031 static PyObject *Atrinik_CleanupChatString(PyObject *self, PyObject *args) 01032 { 01033 const char *text; 01034 char *cp; 01035 PyObject *ret; 01036 01037 (void) self; 01038 01039 if (!PyArg_ParseTuple(args, "s", &text)) 01040 { 01041 return NULL; 01042 } 01043 01044 cp = hooks->strdup_local(text); 01045 ret = Py_BuildValue("s", hooks->cleanup_chat_string(cp)); 01046 free(cp); 01047 01048 return ret; 01049 } 01050 01060 static PyObject *Atrinik_LOG(PyObject *self, PyObject *args) 01061 { 01062 const char *string; 01063 uint8 mode; 01064 01065 (void) self; 01066 01067 if (!PyArg_ParseTuple(args, "Bs", &mode, &string)) 01068 { 01069 return NULL; 01070 } 01071 01072 LOG(mode, string); 01073 01074 Py_INCREF(Py_None); 01075 return Py_None; 01076 } 01077 01083 static PyObject *Atrinik_DestroyTimer(PyObject *self, PyObject *args) 01084 { 01085 int id; 01086 01087 (void) self; 01088 01089 if (!PyArg_ParseTuple(args, "i", &id)) 01090 { 01091 return NULL; 01092 } 01093 01094 Py_ReturnBoolean(hooks->cftimer_destroy(id) == TIMER_ERR_NONE); 01095 } 01096 01113 static PyObject *Atrinik_GetRangeVectorFromMapCoords(PyObject *self, PyObject *args) 01114 { 01115 Atrinik_Map *map, *map2; 01116 int x, y, x2, y2, flags = 0; 01117 rv_vector rv; 01118 PyObject *tuple; 01119 01120 (void) self; 01121 01122 if (!PyArg_ParseTuple(args, "O!iiO!ii|i", &Atrinik_MapType, &map, &x, &y, &Atrinik_MapType, &map2, &x2, &y2, &flags)) 01123 { 01124 return NULL; 01125 } 01126 01127 if (!hooks->get_rangevector_from_mapcoords(map->map, x, y, map2->map, x2, y2, &rv, flags)) 01128 { 01129 Py_INCREF(Py_None); 01130 return Py_None; 01131 } 01132 01133 tuple = PyTuple_New(4); 01134 PyTuple_SET_ITEM(tuple, 0, Py_BuildValue("i", rv.direction)); 01135 PyTuple_SET_ITEM(tuple, 1, Py_BuildValue("i", rv.distance)); 01136 PyTuple_SET_ITEM(tuple, 2, Py_BuildValue("i", rv.distance_x)); 01137 PyTuple_SET_ITEM(tuple, 3, Py_BuildValue("i", rv.distance_y)); 01138 01139 return tuple; 01140 } 01141 01148 static PyObject *Atrinik_CostString(PyObject *self, PyObject *args) 01149 { 01150 sint64 value; 01151 01152 (void) self; 01153 01154 if (!PyArg_ParseTuple(args, "L", &value)) 01155 { 01156 return NULL; 01157 } 01158 01159 return Py_BuildValue("s", hooks->cost_string_from_value(value)); 01160 } 01161 01176 static PyObject *Atrinik_CacheAdd(PyObject *self, PyObject *args) 01177 { 01178 const char *key; 01179 PyObject *what; 01180 int ret; 01181 01182 (void) self; 01183 01184 if (!PyArg_ParseTuple(args, "sO", &key, &what)) 01185 { 01186 return NULL; 01187 } 01188 01189 /* Add it to the cache. */ 01190 ret = hooks->cache_add(key, what, CACHE_FLAG_PYOBJ | CACHE_FLAG_GEVENT); 01191 01192 if (ret) 01193 { 01194 Py_INCREF(what); 01195 } 01196 01197 Py_ReturnBoolean(ret); 01198 } 01199 01208 static PyObject *Atrinik_CacheGet(PyObject *self, PyObject *args) 01209 { 01210 const char *key; 01211 shstr *sh_key; 01212 cache_struct *result; 01213 01214 (void) self; 01215 01216 if (!PyArg_ParseTuple(args, "s", &key)) 01217 { 01218 return NULL; 01219 } 01220 01221 sh_key = hooks->find_string(key); 01222 01223 /* Even if the cache entry was found, pretend it doesn't exist if 01224 * CACHE_FLAG_PYOBJ is not set. */ 01225 if (!sh_key || !(result = hooks->cache_find(sh_key)) || !(result->flags & CACHE_FLAG_PYOBJ)) 01226 { 01227 PyErr_SetString(PyExc_ValueError, "No such cache entry."); 01228 return NULL; 01229 } 01230 else 01231 { 01232 Py_INCREF((PyObject *) result->ptr); 01233 return (PyObject *) result->ptr; 01234 } 01235 } 01236 01246 static PyObject *Atrinik_CacheRemove(PyObject *self, PyObject *args) 01247 { 01248 const char *key; 01249 shstr *sh_key; 01250 01251 (void) self; 01252 01253 if (!PyArg_ParseTuple(args, "s", &key)) 01254 { 01255 return NULL; 01256 } 01257 01258 sh_key = hooks->find_string(key); 01259 01260 if (!sh_key || !hooks->cache_remove(sh_key)) 01261 { 01262 PyErr_SetString(PyExc_ValueError, "No such cache entry."); 01263 return NULL; 01264 } 01265 else 01266 { 01267 Py_INCREF(Py_True); 01268 return Py_True; 01269 } 01270 } 01271 01282 static PyObject *Atrinik_GetFirst(PyObject *self, PyObject *args) 01283 { 01284 const char *what; 01285 01286 (void) self; 01287 01288 if (!PyArg_ParseTuple(args, "s", &what)) 01289 { 01290 return NULL; 01291 } 01292 01293 if (!strcmp(what, "player")) 01294 { 01295 return wrap_player(*hooks->first_player); 01296 } 01297 else if (!strcmp(what, "map")) 01298 { 01299 return wrap_map(*hooks->first_map); 01300 } 01301 else if (!strcmp(what, "archetype")) 01302 { 01303 return wrap_archetype(*hooks->first_archetype); 01304 } 01305 else if (!strcmp(what, "party")) 01306 { 01307 return wrap_party(*hooks->first_party); 01308 } 01309 else if (!strcmp(what, "region")) 01310 { 01311 return wrap_region(*hooks->first_region); 01312 } 01313 01314 PyErr_Format(PyExc_ValueError, "GetFirst(): '%s' is not a valid linked list.", what); 01315 return NULL; 01316 } 01317 01327 static PyObject *Atrinik_CreateMap(PyObject *self, PyObject *args) 01328 { 01329 int width, height; 01330 const char *path; 01331 mapstruct *m; 01332 char buf[HUGE_BUF]; 01333 01334 (void) self; 01335 01336 if (!PyArg_ParseTuple(args, "iis", &width, &height, &path)) 01337 { 01338 return NULL; 01339 } 01340 01341 m = hooks->get_empty_map(width, height); 01342 snprintf(buf, sizeof(buf), "/python-maps/%s", path); 01343 m->path = hooks->add_string(buf); 01344 01345 return wrap_map(m); 01346 } 01347 01356 static PyObject *Atrinik_CreateObject(PyObject *self, PyObject *args) 01357 { 01358 const char *archname; 01359 archetype *at; 01360 01361 (void) self; 01362 01363 if (!PyArg_ParseTuple(args, "s", &archname)) 01364 { 01365 return NULL; 01366 } 01367 01368 at = hooks->find_archetype(archname); 01369 01370 if (!at) 01371 { 01372 PyErr_Format(AtrinikError, "CreateObject(): The archetype '%s' doesn't exist.", archname); 01373 return NULL; 01374 } 01375 01376 return wrap_object(hooks->arch_to_object(at)); 01377 } 01378 01384 static PyMethodDef AtrinikMethods[] = 01385 { 01386 {"LoadObject", Atrinik_LoadObject, METH_VARARGS, 0}, 01387 {"ReadyMap", Atrinik_ReadyMap, METH_VARARGS, 0}, 01388 {"FindPlayer", Atrinik_FindPlayer, METH_VARARGS, 0}, 01389 {"PlayerExists", Atrinik_PlayerExists, METH_VARARGS, 0}, 01390 {"WhoAmI", Atrinik_WhoAmI, METH_NOARGS, 0}, 01391 {"WhoIsActivator", Atrinik_WhoIsActivator, METH_NOARGS, 0}, 01392 {"WhoIsOther", Atrinik_WhoIsOther, METH_NOARGS, 0}, 01393 {"WhatIsEvent", Atrinik_WhatIsEvent, METH_NOARGS, 0}, 01394 {"GetEventNumber", Atrinik_GetEventNumber, METH_NOARGS, 0}, 01395 {"WhatIsMessage", Atrinik_WhatIsMessage, METH_NOARGS, 0}, 01396 {"GetOptions", Atrinik_GetOptions, METH_NOARGS, 0}, 01397 {"GetReturnValue", Atrinik_GetReturnValue, METH_NOARGS, 0}, 01398 {"SetReturnValue", Atrinik_SetReturnValue, METH_VARARGS, 0}, 01399 {"GetEventParameters", Atrinik_GetEventParameters, METH_NOARGS, 0}, 01400 {"GetSpellNr", Atrinik_GetSpellNr, METH_VARARGS, 0}, 01401 {"GetSpell", Atrinik_GetSpell, METH_VARARGS, 0}, 01402 {"GetSkillNr", Atrinik_GetSkillNr, METH_VARARGS, 0}, 01403 {"RegisterCommand", Atrinik_RegisterCommand, METH_VARARGS, 0}, 01404 {"CreatePathname", Atrinik_CreatePathname, METH_VARARGS, 0}, 01405 {"GetTime", Atrinik_GetTime, METH_NOARGS, 0}, 01406 {"LocateBeacon", Atrinik_LocateBeacon, METH_VARARGS, 0}, 01407 {"FindParty", Atrinik_FindParty, METH_VARARGS, 0}, 01408 {"CleanupChatString", Atrinik_CleanupChatString, METH_VARARGS, 0}, 01409 {"LOG", Atrinik_LOG, METH_VARARGS, 0}, 01410 {"DestroyTimer", Atrinik_DestroyTimer, METH_VARARGS, 0}, 01411 {"GetRangeVectorFromMapCoords", Atrinik_GetRangeVectorFromMapCoords, METH_VARARGS, 0}, 01412 {"CostString", Atrinik_CostString, METH_VARARGS, 0}, 01413 {"CacheAdd", Atrinik_CacheAdd, METH_VARARGS, 0}, 01414 {"CacheGet", Atrinik_CacheGet, METH_VARARGS, 0}, 01415 {"CacheRemove", Atrinik_CacheRemove, METH_VARARGS, 0}, 01416 {"GetFirst", Atrinik_GetFirst, METH_VARARGS, 0}, 01417 {"CreateMap", Atrinik_CreateMap, METH_VARARGS, 0}, 01418 {"CreateObject", Atrinik_CreateObject, METH_VARARGS, 0}, 01419 {NULL, NULL, 0, 0} 01420 }; 01421 01425 static void PyErr_LOG() 01426 { 01427 PyObject *globals, *locals, *ret; 01428 PyObject *ptype, *pvalue, *ptraceback; 01429 const char *err_handle = 01430 "from Atrinik import *\n" 01431 "import traceback\n" 01432 "exception = \"\".join(traceback.format_exception(exc_type, exc_value, exc_traceback))\n" 01433 "LOG(llevDebug, exception)\n" 01434 "player = GetFirst(\"player\")\n" 01435 "while player:\n" 01436 " if player.ob.f_wiz or \"resetmap\" in player.cmd_permissions:\n" 01437 " player.ob.Write(exception, COLOR_RED)\n" 01438 " player = player.next\n"; 01439 01440 /* Fetch the exception data. */ 01441 PyErr_Fetch(&ptype, &pvalue, &ptraceback); 01442 PyErr_NormalizeException(&ptype, &pvalue, &ptraceback); 01443 01444 /* Construct globals dictionary. */ 01445 globals = PyDict_New(); 01446 PyDict_SetItemString(globals, "__builtins__", PyEval_GetBuiltins()); 01447 01448 /* Construct locals dictionary, with the exception data. */ 01449 locals = PyDict_New(); 01450 PyDict_SetItemString(locals, "exc_type", ptype); 01451 PyDict_SetItemString(locals, "exc_value", pvalue); 01452 PyDict_SetItemString(locals, "exc_traceback", ptraceback); 01453 01454 /* Run the Python code. */ 01455 ret = PyRun_String(err_handle, Py_file_input, globals, locals); 01456 01457 Py_DECREF(globals); 01458 Py_DECREF(locals); 01459 Py_XDECREF(ret); 01460 } 01461 01465 static PyCodeObject *compilePython(char *filename) 01466 { 01467 shstr *sh_path = NULL; 01468 struct stat stat_buf; 01469 struct _node *n; 01470 int i; 01471 cacheentry *entry_replace = NULL, *run = NULL; 01472 01473 if (stat(filename, &stat_buf)) 01474 { 01475 LOG(llevDebug, "Python: The script file %s can't be stat()ed.\n", filename); 01476 return NULL; 01477 } 01478 01479 FREE_AND_COPY_HASH(sh_path, filename); 01480 01481 /* Search through cache. Three cases: 01482 * 1) script in cache, but older than file -> replace cached 01483 * 2) script in cache and up to date -> use cached 01484 * 3) script not in cache, cache not full -> add to end of cache 01485 * 4) script not in cache, cache full -> replace least recently used */ 01486 for (i = 0; i < PYTHON_CACHE_SIZE; i++) 01487 { 01488 /* Script not in cache, cache not full */ 01489 if (python_cache[i].file == NULL) 01490 { 01491 /* Add to end of cache. */ 01492 entry_replace = &python_cache[i]; 01493 break; 01494 } 01495 else if (python_cache[i].file == sh_path) 01496 { 01497 /* Script in cache */ 01498 if (python_cache[i].code == NULL || (python_cache[i].cached_time < stat_buf.st_mtime)) 01499 { 01500 /* Cache older than file, replace cached. */ 01501 entry_replace = &python_cache[i]; 01502 } 01503 else 01504 { 01505 /* cache up-to-date, use cached*/ 01506 entry_replace = NULL; 01507 run = &python_cache[i]; 01508 } 01509 01510 break; 01511 } 01512 else if (entry_replace == NULL || python_cache[i].used_time < entry_replace->used_time) 01513 { 01514 /* If we haven't found it yet, set replace to the oldest cache */ 01515 entry_replace = &python_cache[i]; 01516 } 01517 } 01518 01519 /* Replace a specific cache index with the file. */ 01520 if (entry_replace) 01521 { 01522 FILE *fp; 01523 01524 fp = fopen(filename, "r"); 01525 01526 if (!fp) 01527 { 01528 LOG(llevDebug, "Python: The script file %s can't be opened.\n", filename); 01529 FREE_AND_CLEAR_HASH(sh_path); 01530 return NULL; 01531 } 01532 01533 Py_XDECREF(entry_replace->code); 01534 entry_replace->code = NULL; 01535 01536 /* Need to replace path string? */ 01537 if (entry_replace->file != sh_path) 01538 { 01539 if (entry_replace->file) 01540 { 01541 FREE_AND_CLEAR_HASH(entry_replace->file); 01542 } 01543 01544 FREE_AND_COPY_HASH(entry_replace->file, sh_path); 01545 } 01546 01547 #ifdef WIN32 01548 { 01549 char buf[HUGE_BUF], *pystr = NULL; 01550 size_t buf_len = 0, pystr_len = 0; 01551 01552 while (fgets(buf, sizeof(buf), fp)) 01553 { 01554 buf_len = strlen(buf); 01555 pystr_len += buf_len; 01556 pystr = realloc(pystr, sizeof(char) * (pystr_len + 1)); 01557 strcpy(pystr + pystr_len - buf_len, buf); 01558 pystr[pystr_len] = '\0'; 01559 } 01560 01561 n = PyParser_SimpleParseString(pystr, Py_file_input); 01562 free(pystr); 01563 } 01564 #else 01565 n = PyParser_SimpleParseFile(fp, filename, Py_file_input); 01566 #endif 01567 01568 if (n) 01569 { 01570 entry_replace->code = PyNode_Compile(n, filename); 01571 PyNode_Free(n); 01572 } 01573 01574 if (PyErr_Occurred()) 01575 { 01576 PyErr_LOG(); 01577 } 01578 else 01579 { 01580 entry_replace->cached_time = stat_buf.st_mtime; 01581 entry_replace->used_time = time(NULL); 01582 } 01583 01584 fclose(fp); 01585 run = entry_replace; 01586 } 01587 01588 FREE_AND_CLEAR_HASH(sh_path); 01589 01590 if (run) 01591 { 01592 return run->code; 01593 } 01594 01595 return NULL; 01596 } 01597 01598 static int do_script(PythonContext *context, const char *filename, object *event) 01599 { 01600 PyCodeObject *pycode; 01601 PyObject *dict, *ret; 01602 char path[HUGE_BUF]; 01603 01604 strncpy(path, hooks->create_pathname(filename), sizeof(path) - 1); 01605 01606 if (event && path[0] != '/') 01607 { 01608 char tmp_path[HUGE_BUF]; 01609 object *outermost = event; 01610 01611 while (outermost && outermost->env) 01612 { 01613 outermost = outermost->env; 01614 } 01615 01616 if (outermost && outermost->map) 01617 { 01618 hooks->normalize_path(outermost->map->path, filename, tmp_path); 01619 strncpy(path, hooks->create_pathname(tmp_path), sizeof(path) - 1); 01620 } 01621 } 01622 01623 pycode = compilePython(path); 01624 01625 if (pycode) 01626 { 01627 #ifndef PRODUCTION_SERVER 01628 PyObject *modules = PyImport_GetModuleDict(), *key, *value; 01629 Py_ssize_t pos = 0; 01630 const char *m_filename; 01631 char m_buf[MAX_BUF]; 01632 01633 /* Create path name to the Python scripts directory. */ 01634 strncpy(m_buf, hooks->create_pathname("/python"), sizeof(m_buf) - 1); 01635 01636 /* Go through the loaded modules. */ 01637 while (PyDict_Next(modules, &pos, &key, &value)) 01638 { 01639 m_filename = PyModule_GetFilename(value); 01640 01641 if (!m_filename) 01642 { 01643 PyErr_Clear(); 01644 continue; 01645 } 01646 01647 /* If this module was loaded from one of our script files, 01648 * reload it. */ 01649 if (!strncmp(m_filename, m_buf, strlen(m_buf))) 01650 { 01651 PyImport_ReloadModule(value); 01652 01653 if (PyErr_Occurred()) 01654 { 01655 PyErr_LOG(); 01656 } 01657 } 01658 } 01659 #endif 01660 01661 pushContext(context); 01662 dict = PyDict_New(); 01663 PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins()); 01664 01665 #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 2 01666 ret = PyEval_EvalCode((PyObject *) pycode, dict, NULL); 01667 #else 01668 ret = PyEval_EvalCode(pycode, dict, NULL); 01669 #endif 01670 01671 if (PyErr_Occurred()) 01672 { 01673 PyErr_LOG(); 01674 } 01675 01676 Py_XDECREF(ret); 01677 Py_DECREF(dict); 01678 01679 return 1; 01680 } 01681 01682 return 0; 01683 } 01684 01689 static int handle_event(va_list args) 01690 { 01691 char *script; 01692 PythonContext *context = malloc(sizeof(PythonContext)); 01693 int rv; 01694 01695 context->activator = va_arg(args, object *); 01696 context->who = va_arg(args, object *); 01697 context->other = va_arg(args, object *); 01698 context->event = va_arg(args, object *); 01699 context->text = va_arg(args, char *); 01700 context->parms[0] = va_arg(args, int); 01701 context->parms[1] = va_arg(args, int); 01702 context->parms[2] = va_arg(args, int); 01703 context->parms[3] = va_arg(args, int); 01704 script = va_arg(args, char *); 01705 context->options = va_arg(args, char *); 01706 context->returnvalue = 0; 01707 01708 LOG(llevDebug, "Python: Start script file >%s<, activator: %s, who: %s, other: %s, text: %s, parms: %d, %d, %d, %d\n", script, STRING_OBJ_NAME(context->activator), STRING_OBJ_NAME(context->who), STRING_OBJ_NAME(context->other), STRING_SAFE(context->text), context->parms[0], context->parms[1], context->parms[2], context->parms[3]); 01709 01710 if (!do_script(context, script, context->who)) 01711 { 01712 freeContext(context); 01713 return 0; 01714 } 01715 01716 context = popContext(); 01717 01718 if (context->parms[3] == SCRIPT_FIX_ALL) 01719 { 01720 if (context->other && IS_LIVE(context->other)) 01721 { 01722 hooks->fix_player(context->other); 01723 } 01724 01725 if (context->who && IS_LIVE(context->who)) 01726 { 01727 hooks->fix_player(context->who); 01728 } 01729 01730 if (context->activator && IS_LIVE(context->activator)) 01731 { 01732 hooks->fix_player(context->activator); 01733 } 01734 } 01735 else if (context->parms[3] == SCRIPT_FIX_ACTIVATOR && IS_LIVE(context->activator)) 01736 { 01737 hooks->fix_player(context->activator); 01738 } 01739 01740 rv = context->returnvalue; 01741 freeContext(context); 01742 LOG(llevDebug, "Python: done (returned: %d).\n", rv); 01743 01744 return rv; 01745 } 01746 01751 static int handle_map_event(va_list args) 01752 { 01753 PythonContext *context = calloc(1, sizeof(PythonContext)); 01754 char *script; 01755 int rv; 01756 01757 context->activator = va_arg(args, object *); 01758 context->event = va_arg(args, object *); 01759 context->other = va_arg(args, object *); 01760 context->who = va_arg(args, object *); 01761 script = va_arg(args, char *); 01762 context->options = va_arg(args, char *); 01763 context->text = va_arg(args, char *); 01764 context->parms[0] = va_arg(args, int); 01765 01766 if (!do_script(context, script, context->who)) 01767 { 01768 freeContext(context); 01769 return 0; 01770 } 01771 01772 context = popContext(); 01773 rv = context->returnvalue; 01774 freeContext(context); 01775 01776 return rv; 01777 } 01778 01784 static int handle_global_event(int event_type, va_list args) 01785 { 01786 PythonContext *context; 01787 01788 switch (event_type) 01789 { 01790 case GEVENT_CACHE_REMOVED: 01791 { 01792 void *ptr = va_arg(args, void *); 01793 uint32 flags = *(uint32 *) va_arg(args, void *); 01794 01795 if (flags & CACHE_FLAG_PYOBJ) 01796 { 01797 PyObject *retval; 01798 01799 /* Attempt to close file/database/etc objects. */ 01800 retval = PyObject_CallMethod((PyObject *) ptr, "close", ""); 01801 01802 /* No close() method, ignore the exception. */ 01803 if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_AttributeError)) 01804 { 01805 PyErr_Clear(); 01806 } 01807 01808 Py_XDECREF(retval); 01809 01810 /* Decrease the reference count. */ 01811 Py_DECREF((PyObject *) ptr); 01812 } 01813 01814 return 0; 01815 } 01816 } 01817 01818 context = malloc(sizeof(PythonContext)); 01819 context->activator = NULL; 01820 context->who = NULL; 01821 context->other = NULL; 01822 context->event = NULL; 01823 context->parms[0] = 0; 01824 context->parms[1] = 0; 01825 context->parms[2] = 0; 01826 context->parms[3] = 0; 01827 context->text = NULL; 01828 context->options = NULL; 01829 context->returnvalue = 0; 01830 01831 switch (event_type) 01832 { 01833 case GEVENT_BORN: 01834 context->activator = (object *) va_arg(args, void *); 01835 break; 01836 01837 case GEVENT_LOGIN: 01838 context->activator = ((player *) va_arg(args, void *))->ob; 01839 context->text = (char *) va_arg(args, void *); 01840 break; 01841 01842 case GEVENT_LOGOUT: 01843 context->activator = ((player *) va_arg(args, void *))->ob; 01844 context->text = (char *) va_arg(args, void *); 01845 break; 01846 01847 case GEVENT_PLAYER_DEATH: 01848 break; 01849 } 01850 01851 if (!do_script(context, "/python/events/python_event.py", NULL)) 01852 { 01853 freeContext(context); 01854 return 0; 01855 } 01856 01857 context = popContext(); 01858 freeContext(context); 01859 01860 return 0; 01861 } 01862 01863 MODULEAPI void *triggerEvent(int *type, ...) 01864 { 01865 va_list args; 01866 int eventcode, event_type; 01867 static int result = 0; 01868 01869 va_start(args, type); 01870 event_type = va_arg(args, int); 01871 eventcode = va_arg(args, int); 01872 01873 LOG(llevDebug, "Python: triggerEvent(): eventcode %d\n", eventcode); 01874 01875 switch (event_type) 01876 { 01877 case PLUGIN_EVENT_NORMAL: 01878 result = handle_event(args); 01879 break; 01880 01881 case PLUGIN_EVENT_MAP: 01882 result = handle_map_event(args); 01883 break; 01884 01885 case PLUGIN_EVENT_GLOBAL: 01886 result = handle_global_event(eventcode, args); 01887 break; 01888 01889 default: 01890 LOG(llevBug, "Python: Requested unknown event type %d.\n", event_type); 01891 break; 01892 } 01893 01894 va_end(args); 01895 return &result; 01896 } 01897 01898 MODULEAPI void *getPluginProperty(int *type, ...) 01899 { 01900 va_list args; 01901 const char *propname; 01902 int i, size; 01903 char *buf; 01904 01905 va_start(args, type); 01906 propname = va_arg(args, const char *); 01907 01908 if (!strcmp(propname, "command?")) 01909 { 01910 const char *cmdname = va_arg(args, const char *); 01911 CommArray_s *rtn_cmd = va_arg(args, CommArray_s *); 01912 01913 va_end(args); 01914 01915 for (i = 0; i < NR_CUSTOM_CMD; i++) 01916 { 01917 if (CustomCommand[i].name != NULL) 01918 { 01919 if (!strcmp(CustomCommand[i].name, cmdname)) 01920 { 01921 rtn_cmd->name = CustomCommand[i].name; 01922 rtn_cmd->time = (float) CustomCommand[i].speed; 01923 rtn_cmd->func = cmd_customPython; 01924 rtn_cmd->flags = 0; 01925 NextCustomCommand = i; 01926 return rtn_cmd; 01927 } 01928 } 01929 } 01930 01931 return NULL; 01932 } 01933 else if (!strcmp(propname, "Identification")) 01934 { 01935 buf = va_arg(args, char *); 01936 size = va_arg(args, int); 01937 va_end(args); 01938 snprintf(buf, size, PLUGIN_NAME); 01939 return NULL; 01940 } 01941 else if (!strcmp(propname, "FullName")) 01942 { 01943 buf = va_arg(args, char *); 01944 size = va_arg(args, int); 01945 va_end(args); 01946 snprintf(buf, size, PLUGIN_VERSION); 01947 return NULL; 01948 } 01949 01950 va_end(args); 01951 return NULL; 01952 } 01953 01959 static int cmd_customPython(object *op, char *params) 01960 { 01961 PythonContext *context = malloc(sizeof(PythonContext)); 01962 int rv; 01963 01964 LOG(llevDebug, "Python: handling command %s using script: %s\n", CustomCommand[NextCustomCommand].name, CustomCommand[NextCustomCommand].script); 01965 01966 context->activator = op; 01967 context->who = op; 01968 context->other = op; 01969 context->event = NULL; 01970 context->parms[0] = 0; 01971 context->parms[1] = 0; 01972 context->parms[2] = 0; 01973 context->parms[3] = 0; 01974 context->text = params; 01975 context->options = NULL; 01976 context->returnvalue = 0; 01977 01978 if (!do_script(context, CustomCommand[NextCustomCommand].script, NULL)) 01979 { 01980 freeContext(context); 01981 return 0; 01982 } 01983 01984 context = popContext(); 01985 rv = context->returnvalue; 01986 freeContext(context); 01987 01988 LOG(llevDebug, "Python: done (returned: %d).\n", rv); 01989 01990 return rv; 01991 } 01992 01993 MODULEAPI void postinitPlugin() 01994 { 01995 char path[HUGE_BUF]; 01996 FILE *fp; 01997 01998 LOG(llevDebug, "Python: Start postinitPlugin.\n"); 01999 hooks->register_global_event(PLUGIN_NAME, GEVENT_CACHE_REMOVED); 02000 initContextStack(); 02001 02002 strncpy(path, hooks->create_pathname("/python/events/python_init.py"), sizeof(path) - 1); 02003 fp = fopen(path, "r"); 02004 02005 if (fp) 02006 { 02007 #ifdef WIN32 02008 char *pystring; 02009 02010 fclose(fp); 02011 02012 pystring = malloc(strlen(path) + 64); 02013 sprintf(pystring, "exec(open('%s').read())", path); 02014 PyRun_SimpleString(pystring); 02015 free(pystring); 02016 #else 02017 PyRun_SimpleFile(fp, path); 02018 fclose(fp); 02019 #endif 02020 } 02021 } 02022 02023 #ifdef IS_PY3K 02024 static PyModuleDef AtrinikModule = 02025 { 02026 PyModuleDef_HEAD_INIT, 02027 "Atrinik", 02028 NULL, 02029 -1, 02030 AtrinikMethods, 02031 NULL, NULL, NULL, NULL 02032 }; 02033 02034 static PyObject *PyInit_Atrinik() 02035 { 02036 PyObject *m = PyModule_Create(&AtrinikModule); 02037 Py_INCREF(m); 02038 return m; 02039 } 02040 #endif 02041 02046 static PyObject *module_create(const char *name) 02047 { 02048 char tmp[MAX_BUF]; 02049 02050 snprintf(tmp, sizeof(tmp), "Atrinik_%s", name); 02051 02052 return PyModule_New(tmp); 02053 } 02054 02061 static void module_add_constants(PyObject *module, const char *name, const Atrinik_Constant *consts) 02062 { 02063 size_t i = 0; 02064 PyObject *module_tmp; 02065 02066 /* Create the new module. */ 02067 module_tmp = module_create(name); 02068 02069 /* Append constants. */ 02070 while (consts[i].name) 02071 { 02072 PyModule_AddIntConstant(module_tmp, consts[i].name, consts[i].value); 02073 i++; 02074 } 02075 02076 /* Add the module. */ 02077 PyDict_SetItemString(PyModule_GetDict(module), name, module_tmp); 02078 } 02079 02087 static void module_add_array(PyObject *module, const char *name, void *array, size_t array_size, field_type type) 02088 { 02089 size_t i; 02090 PyObject *list; 02091 02092 /* Create a new list. */ 02093 list = PyList_New(0); 02094 02095 /* Add entries to the list. */ 02096 for (i = 0; i < array_size; i++) 02097 { 02098 if (type == FIELDTYPE_SINT32) 02099 { 02100 PyList_Append(list, Py_BuildValue("i", ((sint32 *) array)[i])); 02101 } 02102 else if (type == FIELDTYPE_CSTR) 02103 { 02104 PyList_Append(list, Py_BuildValue("s", ((char **) array)[i])); 02105 } 02106 } 02107 02108 /* Add it to the module dictionary. */ 02109 PyDict_SetItemString(PyModule_GetDict(module), name, list); 02110 } 02111 02112 #ifndef WIN32 02113 02118 static PyObject *python_openlogfile(FILE *fp, char *name) 02119 { 02120 #ifdef IS_PY3K 02121 return PyFile_FromFd(fileno(fp), name, "w", 1, NULL, NULL, NULL, 0); 02122 #else 02123 return PyFile_FromFile(fp, name, "w", 0); 02124 #endif 02125 } 02126 #endif 02127 02128 MODULEAPI void initPlugin(struct plugin_hooklist *hooklist) 02129 { 02130 PyObject *m, *d, *module_tmp, *logfile_ptr; 02131 int i; 02132 02133 hooks = hooklist; 02134 02135 LOG(llevDebug, "Python: Atrinik Python Plugin loading...\n"); 02136 02137 #ifdef IS_PY26 02138 Py_Py3kWarningFlag++; 02139 #endif 02140 02141 #ifdef IS_PY3K 02142 PyImport_AppendInittab("Atrinik", &PyInit_Atrinik); 02143 #endif 02144 02145 Py_Initialize(); 02146 02147 LOG(llevDebug, "Python: Start initAtrinik.\n"); 02148 02149 #ifdef IS_PY3K 02150 m = PyImport_ImportModule("Atrinik"); 02151 #else 02152 m = Py_InitModule("Atrinik", AtrinikMethods); 02153 #endif 02154 02155 d = PyModule_GetDict(m); 02156 AtrinikError = PyErr_NewException("Atrinik.error", NULL, NULL); 02157 PyDict_SetItemString(d, "AtrinikError", AtrinikError); 02158 02159 for (i = 0; i < NR_CUSTOM_CMD; i++) 02160 { 02161 CustomCommand[i].name = NULL; 02162 CustomCommand[i].script = NULL; 02163 CustomCommand[i].speed = 0.0; 02164 } 02165 02166 if (!Atrinik_Object_init(m) || !Atrinik_Map_init(m) || !Atrinik_Party_init(m) || !Atrinik_Region_init(m) || !Atrinik_Player_init(m) || !Atrinik_Archetype_init(m) || !Atrinik_AttrList_init(m)) 02167 { 02168 return; 02169 } 02170 02171 #ifndef WIN32 02172 logfile_ptr = python_openlogfile(*hooks->logfile, "<stdout>"); 02173 PySys_SetObject("stdout", logfile_ptr); 02174 PySys_SetObject("__stdout__", logfile_ptr); 02175 logfile_ptr = python_openlogfile(*hooks->logfile, "<stderr>"); 02176 PySys_SetObject("stderr", logfile_ptr); 02177 PySys_SetObject("__stderr__", logfile_ptr); 02178 #endif 02179 02180 module_add_constants(m, "Type", constants_types); 02181 module_add_array(m, "freearr_x", hooks->freearr_x, SIZEOFFREE, FIELDTYPE_SINT32); 02182 module_add_array(m, "freearr_y", hooks->freearr_y, SIZEOFFREE, FIELDTYPE_SINT32); 02183 02184 /* Initialize integer constants */ 02185 for (i = 0; constants[i].name; i++) 02186 { 02187 PyModule_AddIntConstant(m, constants[i].name, constants[i].value); 02188 } 02189 02190 /* Initialize integer constants */ 02191 for (i = 0; constants_colors[i][0]; i++) 02192 { 02193 PyModule_AddStringConstant(m, constants_colors[i][0], constants_colors[i][1]); 02194 } 02195 02196 module_tmp = module_create("Gender"); 02197 module_add_array(module_tmp, "gender_noun", hooks->gender_noun, GENDER_MAX, FIELDTYPE_CSTR); 02198 module_add_array(module_tmp, "gender_subjective", hooks->gender_subjective, GENDER_MAX, FIELDTYPE_CSTR); 02199 module_add_array(module_tmp, "gender_subjective_upper", hooks->gender_subjective_upper, GENDER_MAX, FIELDTYPE_CSTR); 02200 module_add_array(module_tmp, "gender_objective", hooks->gender_objective, GENDER_MAX, FIELDTYPE_CSTR); 02201 module_add_array(module_tmp, "gender_possessive", hooks->gender_possessive, GENDER_MAX, FIELDTYPE_CSTR); 02202 module_add_array(module_tmp, "gender_reflexive", hooks->gender_reflexive, GENDER_MAX, FIELDTYPE_CSTR); 02203 02204 for (i = 0; constants_gender[i].name; i++) 02205 { 02206 PyModule_AddIntConstant(module_tmp, constants_gender[i].name, constants_gender[i].value); 02207 } 02208 02209 PyDict_SetItemString(d, "Gender", module_tmp); 02210 02211 LOG(llevDebug, "Python: [Done]\n"); 02212 } 02213 02214 MODULEAPI void closePlugin() 02215 { 02216 LOG(llevDebug, "Python Plugin closing.\n"); 02217 hooks->cache_remove_by_flags(CACHE_FLAG_GEVENT); 02218 Py_Finalize(); 02219 } 02220 02226 static int set_face_field(void *ptr, long face_id) 02227 { 02228 if (face_id < 0 || face_id >= *hooks->nrofpixmaps) 02229 { 02230 PyErr_Format(PyExc_ValueError, "Illegal value for face field: %ld", face_id); 02231 return -1; 02232 } 02233 02234 *(New_Face **) ptr = &(*hooks->new_faces)[face_id]; 02235 return 0; 02236 } 02237 02243 static int set_animation_field(void *ptr, long anim_id) 02244 { 02245 if (anim_id < 0 || anim_id >= *hooks->num_animations) 02246 { 02247 PyErr_Format(PyExc_ValueError, "Illegal value for animation field: %ld", anim_id); 02248 return -1; 02249 } 02250 02251 *(uint16 *) ptr = (uint16) anim_id; 02252 return 0; 02253 } 02254 02261 int generic_field_setter(fields_struct *field, void *ptr, PyObject *value) 02262 { 02263 void *field_ptr; 02264 02265 if ((field->flags & FIELDFLAG_READONLY)) 02266 { 02267 INTRAISE("Trying to modify readonly field."); 02268 } 02269 02270 field_ptr = (void *) ((char *) ptr + field->offset); 02271 02272 switch (field->type) 02273 { 02274 case FIELDTYPE_SHSTR: 02275 if (value == Py_None) 02276 { 02277 FREE_AND_CLEAR_HASH(*(shstr **) field_ptr); 02278 } 02279 else if (PyString_Check(value)) 02280 { 02281 FREE_AND_CLEAR_HASH(*(shstr **) field_ptr); 02282 FREE_AND_COPY_HASH(*(shstr **) field_ptr, PyString_AsString(value)); 02283 } 02284 else 02285 { 02286 INTRAISE("Illegal value for shared string field."); 02287 } 02288 02289 break; 02290 02291 case FIELDTYPE_CSTR: 02292 if (value == Py_None) 02293 { 02294 FREE_AND_NULL_PTR(*(char **) field_ptr); 02295 } 02296 else if (PyString_Check(value)) 02297 { 02298 if (*(char **) field_ptr) 02299 { 02300 free(*(char **) field_ptr); 02301 } 02302 02303 *(char **) field_ptr = hooks->strdup_local(PyString_AsString(value)); 02304 } 02305 else 02306 { 02307 INTRAISE("Illegal value for C string field."); 02308 } 02309 02310 break; 02311 02312 case FIELDTYPE_CARY: 02313 if (value == Py_None) 02314 { 02315 ((char *) field_ptr)[0] = '\0'; 02316 } 02317 else if (PyString_Check(value)) 02318 { 02319 memcpy((char *) field_ptr, PyString_AsString(value), field->extra_data); 02320 ((char *) field_ptr)[field->extra_data] = '\0'; 02321 } 02322 else 02323 { 02324 INTRAISE("Illegal value for C char array field."); 02325 } 02326 02327 break; 02328 02329 case FIELDTYPE_UINT8: 02330 if (PyInt_Check(value)) 02331 { 02332 long val = PyLong_AsLong(value); 02333 02334 if (val < 0 || (unsigned long) val > UINT8_MAX) 02335 { 02336 PyErr_SetString(PyExc_OverflowError, "Invalid integer value for uint8 field."); 02337 return -1; 02338 } 02339 02340 *(uint8 *) field_ptr = (uint8) val; 02341 } 02342 else 02343 { 02344 INTRAISE("Illegal value for uint8 field."); 02345 } 02346 02347 break; 02348 02349 case FIELDTYPE_SINT8: 02350 if (PyInt_Check(value)) 02351 { 02352 long val = PyLong_AsLong(value); 02353 02354 if (val < SINT8_MIN || val > SINT8_MAX) 02355 { 02356 PyErr_SetString(PyExc_OverflowError, "Invalid integer value for sint8 field."); 02357 return -1; 02358 } 02359 02360 *(sint8 *) field_ptr = (sint8) val; 02361 } 02362 else 02363 { 02364 INTRAISE("Illegal value for sint8 field."); 02365 } 02366 02367 break; 02368 02369 case FIELDTYPE_UINT16: 02370 if (PyInt_Check(value)) 02371 { 02372 long val = PyLong_AsLong(value); 02373 02374 if (val < 0 || (unsigned long) val > UINT16_MAX) 02375 { 02376 PyErr_SetString(PyExc_OverflowError, "Invalid integer value for uint16 field."); 02377 return -1; 02378 } 02379 02380 *(uint16 *) field_ptr = (uint16) val; 02381 } 02382 else 02383 { 02384 INTRAISE("Illegal value for uint16 field."); 02385 } 02386 02387 break; 02388 02389 case FIELDTYPE_SINT16: 02390 if (PyInt_Check(value)) 02391 { 02392 long val = PyLong_AsLong(value); 02393 02394 if (val < SINT16_MIN || val > SINT16_MAX) 02395 { 02396 PyErr_SetString(PyExc_OverflowError, "Invalid integer value for sint16 field."); 02397 return -1; 02398 } 02399 02400 *(sint16 *) field_ptr = (sint16) val; 02401 } 02402 else 02403 { 02404 INTRAISE("Illegal value for sint16 field."); 02405 } 02406 02407 break; 02408 02409 case FIELDTYPE_UINT32: 02410 if (PyInt_Check(value)) 02411 { 02412 long val = PyLong_AsLong(value); 02413 02414 if (val < 0 || (unsigned long) val > UINT32_MAX) 02415 { 02416 PyErr_SetString(PyExc_OverflowError, "Invalid integer value for uint32 field."); 02417 return -1; 02418 } 02419 02420 *(uint32 *) field_ptr = (uint32) val; 02421 } 02422 else 02423 { 02424 INTRAISE("Illegal value for uint32 field."); 02425 } 02426 02427 break; 02428 02429 case FIELDTYPE_SINT32: 02430 if (PyInt_Check(value)) 02431 { 02432 long val = PyLong_AsLong(value); 02433 02434 if (val < SINT32_MIN || val > SINT32_MAX) 02435 { 02436 PyErr_SetString(PyExc_OverflowError, "Invalid integer value for sint32 field."); 02437 return -1; 02438 } 02439 02440 *(sint32 *) field_ptr = (sint32) val; 02441 } 02442 else 02443 { 02444 INTRAISE("Illegal value for sint32 field."); 02445 } 02446 02447 break; 02448 02449 case FIELDTYPE_UINT64: 02450 if (PyInt_Check(value)) 02451 { 02452 unsigned PY_LONG_LONG val = PyLong_AsUnsignedLongLong(value); 02453 02454 if (PyErr_Occurred()) 02455 { 02456 PyErr_SetString(PyExc_OverflowError, "Invalid integer value for uint64 field."); 02457 return -1; 02458 } 02459 02460 *(uint64 *) field_ptr = (uint64) val; 02461 } 02462 else 02463 { 02464 INTRAISE("Illegal value for uint64 field."); 02465 } 02466 02467 break; 02468 02469 case FIELDTYPE_SINT64: 02470 if (PyInt_Check(value)) 02471 { 02472 PY_LONG_LONG val = PyLong_AsLongLong(value); 02473 02474 if (PyErr_Occurred()) 02475 { 02476 PyErr_SetString(PyExc_OverflowError, "Invalid integer value for sint64 field."); 02477 return -1; 02478 } 02479 02480 *(sint64 *) field_ptr = (sint64) val; 02481 } 02482 else 02483 { 02484 INTRAISE("Illegal value for sint64 field."); 02485 } 02486 02487 break; 02488 02489 case FIELDTYPE_FLOAT: 02490 if (PyFloat_Check(value)) 02491 { 02492 *(float *) field_ptr = PyFloat_AsDouble(value) * 1.0; 02493 } 02494 else if (PyInt_Check(value)) 02495 { 02496 *(float *) field_ptr = PyLong_AsLong(value) * 1.0; 02497 } 02498 else 02499 { 02500 INTRAISE("Illegal value for float field."); 02501 } 02502 02503 break; 02504 02505 case FIELDTYPE_OBJECT: 02506 if (value == Py_None) 02507 { 02508 *(object **) field_ptr = NULL; 02509 } 02510 else if (PyObject_TypeCheck(value, &Atrinik_ObjectType)) 02511 { 02512 OBJEXISTCHECK_INT((Atrinik_Object *) value); 02513 *(object **) field_ptr = (object *) ((Atrinik_Object *) value)->obj; 02514 } 02515 else 02516 { 02517 INTRAISE("Illegal value for object field."); 02518 } 02519 02520 break; 02521 02522 case FIELDTYPE_OBJECT2: 02523 INTRAISE("Field type not implemented."); 02524 break; 02525 02526 case FIELDTYPE_MAP: 02527 if (value == Py_None) 02528 { 02529 *(mapstruct **) field_ptr = NULL; 02530 } 02531 else if (PyObject_TypeCheck(value, &Atrinik_MapType)) 02532 { 02533 *(mapstruct **) field_ptr = (mapstruct *) ((Atrinik_Map *) value)->map; 02534 } 02535 else 02536 { 02537 INTRAISE("Illegal value for map field."); 02538 } 02539 02540 break; 02541 02542 case FIELDTYPE_OBJECTREF: 02543 { 02544 void *field_ptr2 = (void *) ((char *) ptr + field->extra_data); 02545 02546 if (value == Py_None) 02547 { 02548 *(object **) field_ptr = NULL; 02549 *(tag_t *) field_ptr2 = 0; 02550 } 02551 else if (PyObject_TypeCheck(value, &Atrinik_ObjectType)) 02552 { 02553 object *tmp; 02554 02555 OBJEXISTCHECK_INT((Atrinik_Object *) value); 02556 02557 tmp = (object *) ((Atrinik_Object *) value)->obj; 02558 *(object **) field_ptr = tmp; 02559 *(tag_t *) field_ptr2 = tmp->count; 02560 } 02561 else 02562 { 02563 INTRAISE("Illegal value for object+reference field."); 02564 } 02565 02566 break; 02567 } 02568 02569 case FIELDTYPE_REGION: 02570 if (value == Py_None) 02571 { 02572 *(region **) field_ptr = NULL; 02573 } 02574 else if (PyObject_TypeCheck(value, &Atrinik_RegionType)) 02575 { 02576 *(region **) field_ptr = (region *) ((Atrinik_Region *) value)->region; 02577 } 02578 else 02579 { 02580 INTRAISE("Illegal value for region field."); 02581 } 02582 02583 break; 02584 02585 case FIELDTYPE_PARTY: 02586 if (value == Py_None) 02587 { 02588 *(party_struct **) field_ptr = NULL; 02589 } 02590 else if (PyObject_TypeCheck(value, &Atrinik_PartyType)) 02591 { 02592 *(party_struct **) field_ptr = (party_struct *) ((Atrinik_Party *) value)->party; 02593 } 02594 else 02595 { 02596 INTRAISE("Illegal value for party field."); 02597 } 02598 02599 break; 02600 02601 case FIELDTYPE_ARCH: 02602 if (value == Py_None) 02603 { 02604 *(archetype **) field_ptr = NULL; 02605 } 02606 else if (PyObject_TypeCheck(value, &Atrinik_ArchetypeType)) 02607 { 02608 *(archetype **) field_ptr = (archetype *) ((Atrinik_Archetype *) value)->at; 02609 } 02610 else 02611 { 02612 INTRAISE("Illegal value for archetype field."); 02613 } 02614 02615 break; 02616 02617 case FIELDTYPE_PLAYER: 02618 if (value == Py_None) 02619 { 02620 *(player **) field_ptr = NULL; 02621 } 02622 else if (PyObject_TypeCheck(value, &Atrinik_PlayerType)) 02623 { 02624 *(player **) field_ptr = (player *) ((Atrinik_Player *) value)->pl; 02625 } 02626 else 02627 { 02628 INTRAISE("Illegal value for player field."); 02629 } 02630 02631 break; 02632 02633 case FIELDTYPE_FACE: 02634 if (PyTuple_Check(value)) 02635 { 02636 if (PyTuple_GET_SIZE(value) != 2) 02637 { 02638 PyErr_Format(PyExc_ValueError, "Tuple for face field must have exactly two values."); 02639 return -1; 02640 } 02641 else if (!PyInt_Check(PyTuple_GET_ITEM(value, 1))) 02642 { 02643 PyErr_SetString(PyExc_ValueError, "Second value of tuple used for face field is not an integer."); 02644 return -1; 02645 } 02646 02647 return set_face_field(field_ptr, PyLong_AsLong(PyTuple_GET_ITEM(value, 1))); 02648 } 02649 else if (PyInt_Check(value)) 02650 { 02651 return set_face_field(field_ptr, PyLong_AsLong(value)); 02652 } 02653 else if (PyString_Check(value)) 02654 { 02655 return set_face_field(field_ptr, hooks->find_face(PyString_AsString(value), 0)); 02656 } 02657 else 02658 { 02659 INTRAISE("Illegal value for face field."); 02660 } 02661 02662 break; 02663 02664 case FIELDTYPE_ANIMATION: 02665 if (PyTuple_Check(value)) 02666 { 02667 if (PyTuple_GET_SIZE(value) != 2) 02668 { 02669 PyErr_Format(PyExc_ValueError, "Tuple for animation field must have exactly two values."); 02670 return -1; 02671 } 02672 else if (!PyInt_Check(PyTuple_GET_ITEM(value, 1))) 02673 { 02674 PyErr_SetString(PyExc_ValueError, "Second value of tuple used for animation field is not an integer."); 02675 return -1; 02676 } 02677 02678 return set_animation_field(field_ptr, PyLong_AsLong(PyTuple_GET_ITEM(value, 1))); 02679 } 02680 else if (PyInt_Check(value)) 02681 { 02682 return set_animation_field(field_ptr, PyLong_AsLong(value)); 02683 } 02684 else if (PyString_Check(value)) 02685 { 02686 return set_animation_field(field_ptr, hooks->find_animation(PyString_AsString(value))); 02687 } 02688 else 02689 { 02690 INTRAISE("Illegal value for animation field."); 02691 } 02692 02693 break; 02694 02695 case FIELDTYPE_BOOLEAN: 02696 if (value == Py_True) 02697 { 02698 *(uint8 *) field_ptr = 1; 02699 } 02700 else if (value == Py_False) 02701 { 02702 *(uint8 *) field_ptr = 0; 02703 } 02704 else 02705 { 02706 INTRAISE("Illegal value for boolean field."); 02707 } 02708 02709 break; 02710 02711 default: 02712 break; 02713 } 02714 02715 return 0; 02716 } 02717 02724 PyObject *generic_field_getter(fields_struct *field, void *ptr) 02725 { 02726 void *field_ptr; 02727 02728 field_ptr = (void *) ((char *) ptr + field->offset); 02729 02730 switch (field->type) 02731 { 02732 case FIELDTYPE_SHSTR: 02733 case FIELDTYPE_CSTR: 02734 { 02735 char *str = *(char **) field_ptr; 02736 return Py_BuildValue("s", str ? str : ""); 02737 } 02738 02739 case FIELDTYPE_CARY: 02740 return Py_BuildValue("s", (char *) field_ptr); 02741 02742 case FIELDTYPE_UINT8: 02743 return Py_BuildValue("B", *(uint8 *) field_ptr); 02744 02745 case FIELDTYPE_SINT8: 02746 return Py_BuildValue("b", *(sint8 *) field_ptr); 02747 02748 case FIELDTYPE_UINT16: 02749 return Py_BuildValue("H", *(uint16 *) field_ptr); 02750 02751 case FIELDTYPE_SINT16: 02752 return Py_BuildValue("h", *(sint16 *) field_ptr); 02753 02754 case FIELDTYPE_UINT32: 02755 return Py_BuildValue("I", *(uint32 *) field_ptr); 02756 02757 case FIELDTYPE_SINT32: 02758 return Py_BuildValue("i", *(sint32 *) field_ptr); 02759 02760 case FIELDTYPE_UINT64: 02761 return Py_BuildValue("K", *(uint64 *) field_ptr); 02762 02763 case FIELDTYPE_SINT64: 02764 return Py_BuildValue("L", *(sint64 *) field_ptr); 02765 02766 case FIELDTYPE_FLOAT: 02767 return Py_BuildValue("f", *(float *) field_ptr); 02768 02769 case FIELDTYPE_MAP: 02770 return wrap_map(*(mapstruct **) field_ptr); 02771 02772 case FIELDTYPE_OBJECT: 02773 return wrap_object(*(object **) field_ptr); 02774 02775 case FIELDTYPE_OBJECT2: 02776 return wrap_object((object *) field_ptr); 02777 02778 case FIELDTYPE_OBJECTREF: 02779 { 02780 object *obj = *(object **) field_ptr; 02781 tag_t tag = *(tag_t *) (void *) ((char *) ptr + field->extra_data); 02782 02783 return wrap_object(OBJECT_VALID(obj, tag) ? obj : NULL); 02784 } 02785 02786 case FIELDTYPE_REGION: 02787 return wrap_region(*(region **) field_ptr); 02788 02789 case FIELDTYPE_PARTY: 02790 return wrap_party(*(party_struct **) field_ptr); 02791 02792 case FIELDTYPE_ARCH: 02793 return wrap_archetype(*(archetype **) field_ptr); 02794 02795 case FIELDTYPE_PLAYER: 02796 return wrap_player(*(player **) field_ptr); 02797 02798 case FIELDTYPE_FACE: 02799 return Py_BuildValue("(sH)", (*(New_Face **) field_ptr)->name, (*(New_Face **) field_ptr)->number); 02800 02801 case FIELDTYPE_ANIMATION: 02802 return Py_BuildValue("(sH)", (&(*hooks->animations)[*(uint16 *) field_ptr])->name, *(uint16 *) field_ptr); 02803 02804 case FIELDTYPE_BOOLEAN: 02805 Py_ReturnBoolean(*(uint8 *) field_ptr); 02806 02807 case FIELDTYPE_LIST: 02808 return wrap_attr_list(ptr, field->offset, field->extra_data); 02809 02810 default: 02811 break; 02812 } 02813 02814 RAISE("Unknown field type."); 02815 } 02816 02822 PyObject *generic_rich_compare(int op, int result) 02823 { 02824 /* Based on how Python 3.0 (GPL compatible) implements it for internal types. */ 02825 switch (op) 02826 { 02827 case Py_EQ: 02828 result = (result == 0); 02829 break; 02830 case Py_NE: 02831 result = (result != 0); 02832 break; 02833 case Py_LE: 02834 result = (result <= 0); 02835 break; 02836 case Py_GE: 02837 result = (result >= 0); 02838 break; 02839 case Py_LT: 02840 result = (result == -1); 02841 break; 02842 case Py_GT: 02843 result = (result == 1); 02844 break; 02845 } 02846 02847 return PyBool_FromLong(result); 02848 } 02849 02856 int python_call_int(PyObject *callable, PyObject *arglist) 02857 { 02858 PyObject *result; 02859 int retval = 0; 02860 02861 /* Call the Python function. */ 02862 result = PyEval_CallObject(callable, arglist); 02863 02864 /* Check the result. */ 02865 if (result && PyInt_Check(result)) 02866 { 02867 retval = PyInt_AsLong(result); 02868 } 02869 02870 Py_XDECREF(result); 02871 Py_DECREF(arglist); 02872 02873 return retval; 02874 }
1.7.4