ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/plugins/cfpython/cfpython.c
Revision: 1.1
Committed: Fri Feb 3 07:14:18 2006 UTC (18 years, 5 months ago) by root
Content type: text/plain
Branch: MAIN
Branch point for: UPSTREAM
Log Message:
Initial revision

File Contents

# User Rev Content
1 root 1.1 /*****************************************************************************/
2     /* CFPython - A Python module for Crossfire RPG. */
3     /*****************************************************************************/
4     /* This is the third version of the Crossfire Scripting Engine. */
5     /* The first version used Guile. It was directly integrated in the server */
6     /* code, but since Guile wasn't perceived as an easy-to-learn, easy-to-use */
7     /* language by many, it was dropped in favor of Python. */
8     /* The second version, CFPython 1.0, was included as a plugin and provided */
9     /* just about the same level of functionality the current version has. But */
10     /* it used a rather counter-intuitive, procedural way of presenting things. */
11     /* */
12     /* CFPython 2.0 aims at correcting many of the design flaws crippling the */
13     /* older version. It is also the first plugin to be implemented using the */
14     /* new interface, that doesn't need awkward stuff like the horrible CFParm */
15     /* structure. For the Python writer, things should probably be easier and */
16     /* lead to more readable code: instead of writing "CFPython.getObjectXPos(ob)*/
17     /* he/she now can simply write "ob.X". */
18     /* */
19     /*****************************************************************************/
20     /* Please note that it is still very beta - some of the functions may not */
21     /* work as expected and could even cause the server to crash. */
22     /*****************************************************************************/
23     /* Version history: */
24     /* 0.1 "Ophiuchus" - Initial Alpha release */
25     /* 0.5 "Stalingrad" - Message length overflow corrected. */
26     /* 0.6 "Kharkov" - Message and Write correctly redefined. */
27     /* 0.7 "Koursk" - Setting informations implemented. */
28     /* 1.0a "Petersburg" - Last "old-fashioned" version, never submitted to CVS.*/
29     /* 2.0 "Arkangelsk" - First release of the 2.x series. */
30     /*****************************************************************************/
31     /* Version: 2.0beta8 (also known as "Alexander") */
32     /* Contact: yann.chachkoff@myrealbox.com */
33     /*****************************************************************************/
34     /* That code is placed under the GNU General Public Licence (GPL) */
35     /* (C)2001-2005 by Chachkoff Yann (Feel free to deliver your complaints) */
36     /*****************************************************************************/
37     /* CrossFire, A Multiplayer game for X-windows */
38     /* */
39     /* Copyright (C) 2000 Mark Wedel */
40     /* Copyright (C) 1992 Frank Tore Johansen */
41     /* */
42     /* This program is free software; you can redistribute it and/or modify */
43     /* it under the terms of the GNU General Public License as published by */
44     /* the Free Software Foundation; either version 2 of the License, or */
45     /* (at your option) any later version. */
46     /* */
47     /* This program is distributed in the hope that it will be useful, */
48     /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
49     /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
50     /* GNU General Public License for more details. */
51     /* */
52     /* You should have received a copy of the GNU General Public License */
53     /* along with this program; if not, write to the Free Software */
54     /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
55     /* */
56     /*****************************************************************************/
57    
58     /* First let's include the header file needed */
59    
60     #include <cfpython.h>
61     #include <stdarg.h>
62    
63     #define PYTHON_DEBUG /* give us some general infos out */
64    
65     f_plug_api gethook;
66     f_plug_api registerGlobalEvent;
67     f_plug_api unregisterGlobalEvent;
68     f_plug_api systemDirectory;
69     f_plug_api reCmp;
70    
71     static void set_exception(const char *fmt, ...);
72     static PyObject* createCFObject(PyObject* self, PyObject* args);
73     static PyObject* createCFObjectByName(PyObject* self, PyObject* args);
74     static PyObject* getCFPythonVersion(PyObject* self, PyObject* args);
75     static PyObject* getReturnValue(PyObject* self, PyObject* args);
76     static PyObject* setReturnValue(PyObject* self, PyObject* args);
77     static PyObject* matchString(PyObject* self, PyObject* args);
78     static PyObject* findPlayer(PyObject* self, PyObject* args);
79     static PyObject* readyMap(PyObject* self, PyObject* args);
80     static PyObject* getCostFlagTrue(PyObject* self, PyObject* args);
81     static PyObject* getCostFlagBuy(PyObject* self, PyObject* args);
82     static PyObject* getCostFlagSell(PyObject* self, PyObject* args);
83     static PyObject* getCostFlagNoBargain(PyObject* self, PyObject* args);
84     static PyObject* getCostFlagIdentified(PyObject* self, PyObject* args);
85     static PyObject* getCostFlagNotCursed(PyObject* self, PyObject* args);
86     static PyObject* getDirectionNorthEast(PyObject* self, PyObject* args);
87     static PyObject* getDirectionEast(PyObject* self, PyObject* args);
88     static PyObject* getDirectionSouthEast(PyObject* self, PyObject* args);
89     static PyObject* getDirectionSouth(PyObject* self, PyObject* args);
90     static PyObject* getDirectionSouthWest(PyObject* self, PyObject* args);
91     static PyObject* getDirectionWest(PyObject* self, PyObject* args);
92     static PyObject* getDirectionNorthWest(PyObject* self, PyObject* args);
93     static PyObject* getDirectionNorth(PyObject* self, PyObject* args);
94     static PyObject* getMapDirectory(PyObject* self, PyObject* args);
95     static PyObject* getUniqueDirectory(PyObject* self, PyObject* args);
96     static PyObject* getTempDirectory(PyObject* self, PyObject* args);
97     static PyObject* getConfigDirectory(PyObject* self, PyObject* args);
98     static PyObject* getLocalDirectory(PyObject* self, PyObject* args);
99     static PyObject* getPlayerDirectory(PyObject* self, PyObject* args);
100     static PyObject* getDataDirectory(PyObject* self, PyObject* args);
101     static PyObject* getWhoAmI(PyObject* self, PyObject* args);
102     static PyObject* getWhoIsActivator(PyObject* self, PyObject* args);
103     static PyObject* getWhoIsThird(PyObject* self, PyObject* args);
104     static PyObject* getWhatIsMessage(PyObject* self, PyObject* args);
105     static PyObject* getScriptName(PyObject* self, PyObject* args);
106     static PyObject* getScriptParameters(PyObject* self, PyObject* args);
107     static PyObject* getPrivateDictionary(PyObject* self, PyObject* args);
108     static PyObject* getSharedDictionary(PyObject* self, PyObject* args);
109     static PyObject* getArchetypes(PyObject* self, PyObject* args);
110     static PyObject* getMaps(PyObject* self, PyObject* args);
111     static PyObject* getParties(PyObject* self, PyObject* args);
112     static PyObject* getRegions(PyObject* self, PyObject* args);
113     static PyObject* registerCommand(PyObject* self, PyObject* args);
114     static PyObject* registerGEvent(PyObject* self, PyObject* args);
115     static PyObject* unregisterGEvent(PyObject* self, PyObject* args);
116     static PyObject* CFPythonError;
117    
118     /* Set up an Python exception object. */
119     static void set_exception(const char *fmt, ...)
120     {
121     char buf[1024];
122     va_list arg;
123    
124     va_start(arg, fmt);
125     vsnprintf(buf, sizeof(buf), fmt, arg);
126     va_end(arg);
127    
128     PyErr_SetString(PyExc_ValueError, buf);
129     }
130    
131     static PyMethodDef CFPythonMethods[] = {
132     {"WhoAmI", getWhoAmI, METH_VARARGS},
133     {"WhoIsActivator", getWhoIsActivator, METH_VARARGS},
134     {"WhoIsOther", getWhoIsThird, METH_VARARGS},
135     {"WhatIsMessage", getWhatIsMessage, METH_VARARGS},
136     {"ScriptName", getScriptName, METH_VARARGS},
137     {"ScriptParameters", getScriptParameters, METH_VARARGS},
138     {"MapDirectory", getMapDirectory, METH_VARARGS},
139     {"UniqueDirectory", getUniqueDirectory, METH_VARARGS},
140     {"TempDirectory", getTempDirectory, METH_VARARGS},
141     {"ConfigDirectory", getConfigDirectory, METH_VARARGS},
142     {"LocalDirectory", getLocalDirectory, METH_VARARGS},
143     {"PlayerDirectory", getPlayerDirectory, METH_VARARGS},
144     {"DataDirectory", getDataDirectory, METH_VARARGS},
145     {"DirectionNorth", getDirectionNorth, METH_VARARGS},
146     {"DirectionNorthEast", getDirectionNorthEast, METH_VARARGS},
147     {"DirectionEast", getDirectionEast, METH_VARARGS},
148     {"DirectionSouthEast", getDirectionSouthEast, METH_VARARGS},
149     {"DirectionSouth", getDirectionSouth, METH_VARARGS},
150     {"DirectionSouthWest", getDirectionSouthWest, METH_VARARGS},
151     {"DirectionWest", getDirectionWest, METH_VARARGS},
152     {"DirectionNorthWest", getDirectionNorthWest, METH_VARARGS},
153     {"CostFlagTrue", getCostFlagTrue, METH_VARARGS},
154     {"CostFlagBuy", getCostFlagBuy, METH_VARARGS},
155     {"CostFlagSell", getCostFlagSell, METH_VARARGS},
156     {"CostFlagNoBargain", getCostFlagNoBargain, METH_VARARGS},
157     {"CostFlagIdentified", getCostFlagIdentified, METH_VARARGS},
158     {"CostFlagNotCursed", getCostFlagNotCursed, METH_VARARGS},
159     {"ReadyMap", readyMap, METH_VARARGS},
160     {"FindPlayer", findPlayer, METH_VARARGS},
161     {"MatchString", matchString, METH_VARARGS},
162     {"GetReturnValue", getReturnValue, METH_VARARGS},
163     {"SetReturnValue", setReturnValue, METH_VARARGS},
164     {"PluginVersion", getCFPythonVersion, METH_VARARGS},
165     {"CreateObject", createCFObject, METH_VARARGS},
166     {"CreateObjectByName", createCFObjectByName, METH_VARARGS},
167     {"GetPrivateDictionary", getPrivateDictionary, METH_VARARGS},
168     {"GetSharedDictionary", getSharedDictionary, METH_VARARGS},
169     {"GetArchetypes", getArchetypes, METH_VARARGS},
170     {"GetMaps", getMaps, METH_VARARGS},
171     {"GetParties", getParties, METH_VARARGS},
172     {"GetRegions", getRegions, METH_VARARGS},
173     {"RegisterCommand", registerCommand, METH_VARARGS},
174     {"RegisterGlobalEvent", registerGEvent, METH_VARARGS},
175     {"UnregisterGlobalEvent",unregisterGEvent, METH_VARARGS},
176     {NULL, NULL, 0}
177     };
178    
179     CFPContext* context_stack;
180     CFPContext* current_context;
181     static int current_command = -999;
182     static PyObject* shared_data = NULL;
183     static PyObject* private_data = NULL;
184    
185     static PyObject* registerGEvent(PyObject* self, PyObject* args)
186     {
187     int eventcode;
188     if (!PyArg_ParseTuple(args, "i", &eventcode))
189     return NULL;
190    
191     registerGlobalEvent(NULL, eventcode, PLUGIN_NAME, globalEventListener);
192    
193     Py_INCREF(Py_None);
194     return Py_None;
195     }
196     static PyObject* unregisterGEvent(PyObject* self, PyObject* args)
197     {
198     int eventcode;
199     if (!PyArg_ParseTuple(args, "i", &eventcode))
200     return NULL;
201    
202     unregisterGlobalEvent(NULL, EVENT_TELL, PLUGIN_NAME);
203    
204     Py_INCREF(Py_None);
205     return Py_None;
206     }
207    
208     static PyObject* createCFObject(PyObject* self, PyObject* args)
209     {
210     object* op;
211     op = cf_create_object();
212    
213     if (op == NULL) {
214     Py_INCREF(Py_None);
215     return Py_None;
216     }
217     return Crossfire_Object_wrap(op);
218     }
219     static PyObject* createCFObjectByName(PyObject* self, PyObject* args)
220     {
221     char* obname;
222     object* op;
223    
224     if (!PyArg_ParseTuple(args, "s", &obname))
225     return NULL;
226    
227     op = cf_create_object_by_name(obname);
228    
229     if (op == NULL) {
230     Py_INCREF(Py_None);
231     return Py_None;
232     }
233     return Crossfire_Object_wrap(op);
234     }
235     static PyObject* getCFPythonVersion(PyObject* self, PyObject* args)
236     {
237     int i = 2044;
238     if (!PyArg_ParseTuple(args, "", NULL))
239     return NULL;
240     return Py_BuildValue("i", i);
241     }
242     static PyObject* getReturnValue(PyObject* self, PyObject* args)
243     {
244     if (!PyArg_ParseTuple(args, "", NULL))
245     return NULL;
246     return Py_BuildValue("i", current_context->returnvalue);
247     }
248     static PyObject* setReturnValue(PyObject* self, PyObject* args)
249     {
250     int i;
251     if (!PyArg_ParseTuple(args, "i", &i))
252     return NULL;
253     current_context->returnvalue = i;
254     Py_INCREF(Py_None);
255     return Py_None;
256     }
257     static PyObject* matchString(PyObject* self, PyObject* args)
258     {
259     char *premiere;
260     char *seconde;
261     char *result;
262     int val;
263     if (!PyArg_ParseTuple(args, "ss", &premiere, &seconde))
264     return NULL;
265    
266     result = reCmp( &val, premiere, seconde );
267     if (result != NULL)
268     return Py_BuildValue("i", 1);
269     else
270     return Py_BuildValue("i", 0);
271     }
272     static PyObject* findPlayer(PyObject* self, PyObject* args)
273     {
274     player *foundpl;
275     char* txt;
276    
277     if (!PyArg_ParseTuple(args, "s", &txt))
278     return NULL;
279    
280     foundpl = cf_player_find(txt);
281    
282     if (foundpl != NULL)
283     return Py_BuildValue("O", Crossfire_Object_wrap(foundpl->ob));
284     else {
285     Py_INCREF(Py_None);
286     return Py_None;
287     }
288     }
289     static PyObject* readyMap(PyObject* self, PyObject* args)
290     {
291     char* mapname;
292     mapstruct* map;
293    
294     if (!PyArg_ParseTuple(args, "s", &mapname))
295     return NULL;
296    
297     map = cf_map_get_map(mapname);
298    
299     if (map == NULL) {
300     Py_INCREF(Py_None);
301     return Py_None;
302     }
303     return Crossfire_Map_wrap(map);
304     }
305     static PyObject* getCostFlagTrue(PyObject* self, PyObject* args)
306     {
307     int i = F_TRUE;
308     if (!PyArg_ParseTuple(args, "", NULL))
309     return NULL;
310     return Py_BuildValue("i", i);
311     }
312     static PyObject* getCostFlagBuy(PyObject* self, PyObject* args)
313     {
314     int i = F_BUY;
315     if (!PyArg_ParseTuple(args, "", NULL))
316     return NULL;
317     return Py_BuildValue("i", i);
318     }
319     static PyObject* getCostFlagSell(PyObject* self, PyObject* args)
320     {
321     int i = F_SELL;
322     if (!PyArg_ParseTuple(args, "", NULL))
323     return NULL;
324     return Py_BuildValue("i", i);
325     }
326     static PyObject* getCostFlagNoBargain(PyObject* self, PyObject* args)
327     {
328     int i = F_NO_BARGAIN;
329     if (!PyArg_ParseTuple(args, "", NULL))
330     return NULL;
331     return Py_BuildValue("i", i);
332     }
333     static PyObject* getCostFlagIdentified(PyObject* self, PyObject* args)
334     {
335     int i = F_IDENTIFIED;
336     if (!PyArg_ParseTuple(args, "", NULL))
337     return NULL;
338     return Py_BuildValue("i", i);
339     }
340     static PyObject* getCostFlagNotCursed(PyObject* self, PyObject* args)
341     {
342     int i = F_NOT_CURSED;
343     if (!PyArg_ParseTuple(args, "", NULL))
344     return NULL;
345     return Py_BuildValue("i", i);
346     }
347     static PyObject* getDirectionNorthEast(PyObject* self, PyObject* args)
348     {
349     int i = 2;
350     if (!PyArg_ParseTuple(args, "", NULL))
351     return NULL;
352     return Py_BuildValue("i", i);
353     }
354     static PyObject* getDirectionEast(PyObject* self, PyObject* args)
355     {
356     int i = 3;
357     if (!PyArg_ParseTuple(args, "", NULL))
358     return NULL;
359     return Py_BuildValue("i", i);
360     }
361     static PyObject* getDirectionSouthEast(PyObject* self, PyObject* args)
362     {
363     int i = 4;
364     if (!PyArg_ParseTuple(args, "", NULL))
365     return NULL;
366     return Py_BuildValue("i", i);
367     }
368     static PyObject* getDirectionSouth(PyObject* self, PyObject* args)
369     {
370     int i = 5;
371     if (!PyArg_ParseTuple(args, "", NULL))
372     return NULL;
373     return Py_BuildValue("i", i);
374     }
375     static PyObject* getDirectionSouthWest(PyObject* self, PyObject* args)
376     {
377     int i = 6;
378     if (!PyArg_ParseTuple(args, "", NULL))
379     return NULL;
380     return Py_BuildValue("i", i);
381     }
382     static PyObject* getDirectionWest(PyObject* self, PyObject* args)
383     {
384     int i = 7;
385     if (!PyArg_ParseTuple(args, "", NULL))
386     return NULL;
387     return Py_BuildValue("i", i);
388     }
389     static PyObject* getDirectionNorthWest(PyObject* self, PyObject* args)
390     {
391     int i = 8;
392     if (!PyArg_ParseTuple(args, "", NULL))
393     return NULL;
394     return Py_BuildValue("i", i);
395     }
396     static PyObject* getDirectionNorth(PyObject* self, PyObject* args)
397     {
398     int i = 1;
399     if (!PyArg_ParseTuple(args, "", NULL))
400     return NULL;
401     return Py_BuildValue("i", i);
402     }
403     static PyObject* getMapDirectory(PyObject* self, PyObject* args)
404     {
405     int rv;
406     if (!PyArg_ParseTuple(args, "", NULL))
407     return NULL;
408     return Py_BuildValue("s", systemDirectory(&rv, 0));
409     }
410     static PyObject* getUniqueDirectory(PyObject* self, PyObject* args)
411     {
412     int rv;
413     if (!PyArg_ParseTuple(args, "", NULL))
414     return NULL;
415     return Py_BuildValue("s", systemDirectory(&rv, 1));
416     }
417     static PyObject* getTempDirectory(PyObject* self, PyObject* args)
418     {
419     int rv;
420     if (!PyArg_ParseTuple(args, "", NULL))
421     return NULL;
422     return Py_BuildValue("s", systemDirectory(&rv, 2));
423     }
424     static PyObject* getConfigDirectory(PyObject* self, PyObject* args)
425     {
426     int rv;
427     if (!PyArg_ParseTuple(args, "", NULL))
428     return NULL;
429     return Py_BuildValue("s", systemDirectory(&rv, 3));
430     }
431     static PyObject* getLocalDirectory(PyObject* self, PyObject* args)
432     {
433     int rv;
434     if (!PyArg_ParseTuple(args, "", NULL))
435     return NULL;
436     return Py_BuildValue("s", systemDirectory(&rv, 4));
437     }
438     static PyObject* getPlayerDirectory(PyObject* self, PyObject* args)
439     {
440     int rv;
441     if (!PyArg_ParseTuple(args, "", NULL))
442     return NULL;
443     return Py_BuildValue("s", systemDirectory(&rv, 5));
444     }
445     static PyObject* getDataDirectory(PyObject* self, PyObject* args)
446     {
447     int rv;
448     if (!PyArg_ParseTuple(args, "", NULL))
449     return NULL;
450     return Py_BuildValue("s", systemDirectory(&rv, 6));
451     }
452     static PyObject* getWhoAmI(PyObject* self, PyObject* args)
453     {
454     if (!PyArg_ParseTuple(args, "", NULL))
455     return NULL;
456     if (!current_context->who) {
457     Py_INCREF(Py_None);
458     return Py_None;
459     }
460     Py_INCREF(current_context->who);
461     return current_context->who;
462     }
463     static PyObject* getWhoIsActivator(PyObject* self, PyObject* args)
464     {
465     if (!PyArg_ParseTuple(args, "", NULL))
466     return NULL;
467     if (!current_context->activator) {
468     Py_INCREF(Py_None);
469     return Py_None;
470     }
471     Py_INCREF(current_context->activator);
472     return current_context->activator;
473     }
474     static PyObject* getWhoIsThird(PyObject* self, PyObject* args)
475     {
476     if (!PyArg_ParseTuple(args, "", NULL))
477     return NULL;
478     if (!current_context->third) {
479     Py_INCREF(Py_None);
480     return Py_None;
481     }
482     Py_INCREF(current_context->third);
483     return current_context->third;
484     }
485     static PyObject* getWhatIsMessage(PyObject* self, PyObject* args)
486     {
487     if (!PyArg_ParseTuple(args, "", NULL))
488     return NULL;
489    
490     if (current_context->message == NULL)
491     return Py_BuildValue("");
492     else
493     return Py_BuildValue("s", current_context->message);
494     }
495     static PyObject* getScriptName(PyObject* self, PyObject* args)
496     {
497     if (!PyArg_ParseTuple(args, "", NULL))
498     return NULL;
499     return Py_BuildValue("s", current_context->script);
500     }
501     static PyObject* getScriptParameters(PyObject* self, PyObject* args)
502     {
503     if (!PyArg_ParseTuple(args, "", NULL))
504     return NULL;
505     return Py_BuildValue("s", current_context->options);
506     }
507    
508     static PyObject* getPrivateDictionary(PyObject* self, PyObject* args)
509     {
510     PyObject* data;
511    
512     if (!PyArg_ParseTuple(args, "", NULL))
513     return NULL;
514    
515     data = PyDict_GetItemString(private_data, current_context->script);
516     if (!data) {
517     data = PyDict_New();
518     PyDict_SetItemString(private_data, current_context->script, data);
519     Py_DECREF(data);
520     }
521     Py_INCREF(data);
522     return data;
523     }
524    
525     static PyObject* getSharedDictionary(PyObject* self, PyObject* args)
526     {
527     if (!PyArg_ParseTuple(args, "", NULL))
528     return NULL;
529    
530     Py_INCREF(shared_data);
531     return shared_data;
532     }
533    
534     static PyObject* getArchetypes(PyObject* self, PyObject* args)
535     {
536     PyObject* list;
537     archetype* arch;
538    
539     list = PyList_New(0);
540     arch = cf_archetype_get_first();
541     while (arch) {
542     PyList_Append(list, Crossfire_Archetype_wrap(arch));
543     arch = cf_archetype_get_next(arch);
544     }
545     return list;
546     }
547    
548     static PyObject* getMaps(PyObject* self, PyObject* args)
549     {
550     PyObject* list;
551     mapstruct* map;
552    
553     list = PyList_New(0);
554     map = cf_map_get_first();
555     while (map) {
556     PyList_Append(list, Crossfire_Map_wrap(map));
557     map = cf_map_get_property(map, CFAPI_MAP_PROP_NEXT);
558     }
559     return list;
560     }
561    
562     static PyObject* getParties(PyObject* self, PyObject* args)
563     {
564     PyObject* list;
565     partylist* party;
566    
567     list = PyList_New(0);
568     party = cf_party_get_first();
569     while (party) {
570     PyList_Append(list, Crossfire_Party_wrap(party));
571     party = cf_party_get_next(party);
572     }
573     return list;
574     }
575    
576     static PyObject* getRegions(PyObject* self, PyObject* args)
577     {
578     PyObject *list;
579     region *reg;
580    
581     list = PyList_New(0);
582     reg = cf_region_get_first();
583     while (reg) {
584     PyList_Append(list, Crossfire_Region_wrap(reg));
585     reg = cf_region_get_next(reg);
586     }
587     return list;
588     }
589    
590     static PyObject* registerCommand(PyObject* self, PyObject* args)
591     {
592     char *cmdname;
593     char *scriptname;
594     double cmdspeed;
595     int i;
596    
597     if (!PyArg_ParseTuple(args, "ssd", &cmdname, &scriptname, &cmdspeed))
598     return NULL;
599    
600     if (cmdspeed < 0) {
601     set_exception("speed must not be negative");
602     return NULL;
603     }
604    
605     for (i = 0; i < NR_CUSTOM_CMD; i++) {
606     if (CustomCommand[i].name != NULL) {
607     if (!strcmp(CustomCommand[i].name, cmdname)) {
608     set_exception("command '%s' is already registered", cmdname);
609     return NULL;
610     }
611     }
612     }
613     for (i = 0; i < NR_CUSTOM_CMD; i++) {
614     if (CustomCommand[i].name == NULL) {
615     CustomCommand[i].name = cf_strdup_local(cmdname);
616     CustomCommand[i].script = cf_strdup_local(scriptname);
617     CustomCommand[i].speed = cmdspeed;
618     break;
619     }
620     };
621    
622     Py_INCREF(Py_None);
623     return Py_None;
624     }
625    
626     void initContextStack()
627     {
628     current_context = NULL;
629     context_stack = NULL;
630     }
631    
632     void pushContext(CFPContext* context)
633     {
634     if (current_context == NULL) {
635     context_stack = context;
636     context->down = NULL;
637     } else {
638     context->down = current_context;
639     }
640     current_context = context;
641     }
642    
643     CFPContext* popContext()
644     {
645     CFPContext* oldcontext;
646     if (current_context != NULL) {
647     oldcontext = current_context;
648     current_context = current_context->down;
649     return oldcontext;
650     }
651     else
652     return NULL;
653     }
654    
655     void freeContext(CFPContext* context)
656     {
657     Py_XDECREF(context->who);
658     Py_XDECREF(context->activator);
659     Py_XDECREF(context->third);
660     free(context);
661     }
662    
663     static int do_script(CFPContext* context, int silent)
664     {
665     FILE* scriptfile;
666     PyObject* dict;
667     PyObject* ret;
668     #if 0
669     PyObject* list;
670     int item;
671     #endif
672    
673     scriptfile = fopen(context->script, "r");
674     if (scriptfile == NULL) {
675     if (!silent)
676     printf( "cfpython - The Script file %s can't be opened\n", context->script);
677     return 0;
678     }
679     pushContext(context);
680     dict = PyDict_New();
681     PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins());
682     ret = PyRun_File(scriptfile, context->script, Py_file_input, dict, dict);
683     if (PyErr_Occurred()) {
684     PyErr_Print();
685     }
686     Py_XDECREF(ret);
687     #if 0
688     printf( "cfpython - %d items in heap\n", PyDict_Size(dict));
689     list = PyDict_Values(dict);
690     for (item = PyList_Size(list) - 1; item >= 0; item--) {
691     dict = PyList_GET_ITEM(list, item);
692     ret = PyObject_Str(dict);
693     printf(" ref %s = %d\n", PyString_AsString(ret), dict->ob_refcnt);
694     Py_XDECREF(ret);
695     }
696     Py_DECREF(list);
697     #endif
698     Py_DECREF(dict);
699     fclose(scriptfile);
700     return 1;
701     }
702    
703     CF_PLUGIN int initPlugin(const char* iversion, f_plug_api gethooksptr)
704     {
705     PyObject *m, *d;
706     int i;
707     gethook = gethooksptr;
708     printf("CFPython 2.0a init\n");
709    
710     Py_Initialize();
711     Crossfire_ObjectType.tp_new = PyType_GenericNew;
712     Crossfire_MapType.tp_new = PyType_GenericNew;
713     Crossfire_PlayerType.tp_new = PyType_GenericNew;
714     Crossfire_ArchetypeType.tp_new = PyType_GenericNew;
715     Crossfire_PartyType.tp_new = PyType_GenericNew;
716     Crossfire_RegionType.tp_new = PyType_GenericNew;
717     PyType_Ready(&Crossfire_ObjectType);
718     PyType_Ready(&Crossfire_MapType);
719     PyType_Ready(&Crossfire_PlayerType);
720     PyType_Ready(&Crossfire_ArchetypeType);
721     PyType_Ready(&Crossfire_PartyType);
722     PyType_Ready(&Crossfire_RegionType);
723    
724     m = Py_InitModule("Crossfire", CFPythonMethods);
725     d = PyModule_GetDict(m);
726     Py_INCREF(&Crossfire_ObjectType);
727     Py_INCREF(&Crossfire_MapType);
728     Py_INCREF(&Crossfire_PlayerType);
729     Py_INCREF(&Crossfire_ArchetypeType);
730     Py_INCREF(&Crossfire_PartyType);
731     Py_INCREF(&Crossfire_RegionType);
732    
733     PyModule_AddObject(m, "Object", (PyObject*)&Crossfire_ObjectType);
734     PyModule_AddObject(m, "Map", (PyObject*)&Crossfire_MapType);
735     PyModule_AddObject(m, "Player", (PyObject*)&Crossfire_PlayerType);
736     PyModule_AddObject(m, "Archetype", (PyObject*)&Crossfire_ArchetypeType);
737     PyModule_AddObject(m, "Party", (PyObject*)&Crossfire_PartyType);
738     PyModule_AddObject(m, "Region", (PyObject*)&Crossfire_RegionType);
739    
740     CFPythonError = PyErr_NewException("Crossfire.error", NULL, NULL);
741     PyDict_SetItemString(d, "error", CFPythonError);
742     for (i = 0; i < NR_CUSTOM_CMD; i++) {
743     CustomCommand[i].name = NULL;
744     CustomCommand[i].script = NULL;
745     CustomCommand[i].speed = 0.0;
746     }
747     private_data = PyDict_New();
748     shared_data = PyDict_New();
749     return 0;
750     }
751    
752     CF_PLUGIN void* getPluginProperty(int* type, ...)
753     {
754     va_list args;
755     const char* propname;
756     int i;
757     static CommArray_s rtn_cmd;
758    
759     va_start(args, type);
760     propname = va_arg(args, const char *);
761    
762     if (!strcmp(propname, "command?")) {
763     const char* cmdname;
764     cmdname = va_arg(args, const char *);
765     va_end(args);
766    
767     for (i = 0; i < NR_CUSTOM_CMD; i++) {
768     if (CustomCommand[i].name != NULL) {
769     if (!strcmp(CustomCommand[i].name, cmdname)) {
770     rtn_cmd.name = CustomCommand[i].name;
771     rtn_cmd.time = (float)CustomCommand[i].speed;
772     rtn_cmd.func = runPluginCommand;
773     current_command = i;
774     return &rtn_cmd;
775     }
776     }
777     }
778     return NULL;
779     } else if (!strcmp(propname, "Identification")) {
780     va_end(args);
781     return PLUGIN_NAME;
782     } else if (!strcmp(propname, "FullName")) {
783     va_end(args);
784     return PLUGIN_VERSION;
785     }
786     return NULL;
787     }
788    
789     CF_PLUGIN int runPluginCommand(object* op, char* params)
790     {
791     char buf[1024];
792     CFPContext* context;
793     static int rv = 0;
794    
795     rv = 0;
796    
797     if (current_command < 0) {
798     printf("Illegal call of runPluginCommand, call find_plugin_command first.\n");
799     return 1;
800     }
801     snprintf(buf, sizeof(buf), "%s.py", cf_get_maps_directory(CustomCommand[current_command].script));
802    
803     context = malloc(sizeof(CFPContext));
804     context->message[0] = 0;
805    
806     context->who = Crossfire_Object_wrap(op);
807     context->activator = NULL;
808     context->third = NULL;
809     context->fix = 0;
810     snprintf(context->script, sizeof(context->script), "%s", buf);
811     snprintf(context->options, sizeof(context->options), "%s", params);
812     context->returnvalue = 1; /* Default is "command successful" */
813    
814     current_command = -999;
815    
816     if (!do_script(context, 0)) {
817     freeContext(context);
818     return rv;
819     }
820    
821     context = popContext();
822     rv = context->returnvalue;
823     freeContext(context);
824     /* printf("Execution complete"); */
825     return rv;
826     }
827    
828     CF_PLUGIN int postInitPlugin()
829     {
830     int hooktype = 1;
831     int rtype = 0;
832     FILE* scriptfile;
833    
834     printf("CFPython 2.0a post init\n");
835     registerGlobalEvent = gethook(&rtype, hooktype, "cfapi_system_register_global_event");
836     unregisterGlobalEvent = gethook(&rtype, hooktype, "cfapi_system_unregister_global_event");
837     systemDirectory = gethook(&rtype, hooktype, "cfapi_system_directory");
838     reCmp = gethook(&rtype, hooktype, "cfapi_system_re_cmp");
839     cf_init_plugin( gethook );
840     initContextStack();
841     registerGlobalEvent(NULL, EVENT_BORN, PLUGIN_NAME, globalEventListener);
842     /*registerGlobalEvent(NULL, EVENT_CLOCK, PLUGIN_NAME, globalEventListener);*/
843     /*registerGlobalEvent(NULL, EVENT_CRASH, PLUGIN_NAME, globalEventListener);*/
844     registerGlobalEvent(NULL, EVENT_PLAYER_DEATH, PLUGIN_NAME, globalEventListener);
845     registerGlobalEvent(NULL, EVENT_GKILL, PLUGIN_NAME, globalEventListener);
846     registerGlobalEvent(NULL, EVENT_LOGIN, PLUGIN_NAME, globalEventListener);
847     registerGlobalEvent(NULL, EVENT_LOGOUT, PLUGIN_NAME, globalEventListener);
848     registerGlobalEvent(NULL, EVENT_MAPENTER, PLUGIN_NAME, globalEventListener);
849     registerGlobalEvent(NULL, EVENT_MAPLEAVE, PLUGIN_NAME, globalEventListener);
850     registerGlobalEvent(NULL, EVENT_MAPRESET, PLUGIN_NAME, globalEventListener);
851     registerGlobalEvent(NULL, EVENT_REMOVE, PLUGIN_NAME, globalEventListener);
852     registerGlobalEvent(NULL, EVENT_SHOUT, PLUGIN_NAME, globalEventListener);
853     registerGlobalEvent(NULL, EVENT_TELL, PLUGIN_NAME, globalEventListener);
854     registerGlobalEvent(NULL, EVENT_MUZZLE, PLUGIN_NAME, globalEventListener);
855     registerGlobalEvent(NULL, EVENT_KICK, PLUGIN_NAME, globalEventListener);
856    
857     scriptfile = fopen(cf_get_maps_directory("python/events/python_init.py"), "r");
858     if (scriptfile != NULL) {
859     PyRun_SimpleFile(scriptfile, cf_get_maps_directory("python/events/python_init.py"));
860     fclose(scriptfile);
861     }
862    
863     return 0;
864     }
865    
866     CF_PLUGIN void* globalEventListener(int* type, ...)
867     {
868     va_list args;
869     static int rv = 0;
870     CFPContext* context;
871     Crossfire_Player* cfpl;
872     Crossfire_Object* cfob;
873     char* buf;
874     player* pl;
875     object* op;
876     context = malloc(sizeof(CFPContext));
877    
878     rv = 0;
879    
880     va_start(args, type);
881     context->event_code = va_arg(args, int);
882    
883     context->message[0] = 0;
884    
885     context->who = NULL;
886     context->activator = NULL;
887     context->third = NULL;
888     rv = context->returnvalue = 0;
889     snprintf(context->script, sizeof(context->script), "%s", cf_get_maps_directory("python/events/python_event.py"));
890     strcpy(context->options, "");
891     switch(context->event_code) {
892     case EVENT_CRASH:
893     printf( "Unimplemented for now\n");
894     break;
895     case EVENT_BORN:
896     op = va_arg(args, object*);
897     context->activator = Crossfire_Object_wrap(op);
898     snprintf(context->options, sizeof(context->options), "born");
899     cfob = (Crossfire_Object*)context->activator;
900     break;
901     case EVENT_PLAYER_DEATH:
902     op = va_arg(args, object*);
903     context->who = Crossfire_Object_wrap(op);
904     snprintf(context->options, sizeof(context->options), "death");
905     cfob = (Crossfire_Object*)context->who;
906     break;
907     case EVENT_GKILL:
908     op = va_arg(args, object*);
909     context->who = Crossfire_Object_wrap(op);
910     context->activator = Crossfire_Object_wrap(op);
911     snprintf(context->options, sizeof(context->options), "gkill");
912     cfob = (Crossfire_Object*)context->who;
913     break;
914     case EVENT_LOGIN:
915     pl = va_arg(args, player*);
916     context->activator = Crossfire_Object_wrap(pl->ob);
917     buf = va_arg(args, char*);
918     if (buf != NULL)
919     snprintf(context->message, sizeof(context->message), "%s", buf);
920     snprintf(context->options, sizeof(context->options), "login");
921     cfpl = (Crossfire_Player*)context->activator;
922     break;
923     case EVENT_LOGOUT:
924     pl = va_arg(args, player*);
925     context->activator = Crossfire_Object_wrap(pl->ob);
926     buf = va_arg(args, char*);
927     if (buf != NULL)
928     snprintf(context->message, sizeof(context->message), "%s", buf);
929     snprintf(context->options, sizeof(context->options), "logout");
930     cfpl = (Crossfire_Player*)context->activator;
931     break;
932     case EVENT_REMOVE:
933     op = va_arg(args, object*);
934     context->activator = Crossfire_Object_wrap(op);
935     snprintf(context->options, sizeof(context->options), "remove");
936     cfob = (Crossfire_Object*)context->activator;
937     break;
938     case EVENT_SHOUT:
939     op = va_arg(args, object*);
940     context->activator = Crossfire_Object_wrap(op);
941     buf = va_arg(args, char*);
942     if (buf != NULL)
943     snprintf(context->message, sizeof(context->message), "%s", buf);
944     snprintf(context->options, sizeof(context->options), "shout");
945     cfob = (Crossfire_Object*)context->activator;
946     break;
947     case EVENT_MUZZLE:
948     op = va_arg(args, object*);
949     context->activator = Crossfire_Object_wrap(op);
950     buf = va_arg(args, char*);
951     if (buf != NULL)
952     snprintf(context->message, sizeof(context->message), "%s", buf);
953     snprintf(context->options, sizeof(context->options), "muzzle");
954     cfob = (Crossfire_Object*)context->activator;
955     break;
956     case EVENT_KICK:
957     op = va_arg(args, object*);
958     context->activator = Crossfire_Object_wrap(op);
959     buf = va_arg(args, char*);
960     if (buf != NULL)
961     snprintf(context->message, sizeof(context->message), "%s", buf);
962     snprintf(context->options, sizeof(context->options), "kick");
963     cfob = (Crossfire_Object*)context->activator;
964     break;
965     case EVENT_MAPENTER:
966     op = va_arg(args, object*);
967     context->activator = Crossfire_Object_wrap(op);
968     snprintf(context->options, sizeof(context->options), "mapenter");
969     cfob = (Crossfire_Object*)context->activator;
970     break;
971     case EVENT_MAPLEAVE:
972     op = va_arg(args, object*);
973     context->activator = Crossfire_Object_wrap(op);
974     snprintf(context->options, sizeof(context->options), "mapleave");
975     cfob = (Crossfire_Object*)context->activator;
976     break;
977     case EVENT_CLOCK:
978     snprintf(context->options, sizeof(context->options), "clock");
979     break;
980     case EVENT_MAPRESET:
981     buf = va_arg(args, char*);
982     if (buf != NULL)
983     snprintf(context->message, sizeof(context->message), "%s", buf);
984     snprintf(context->options, sizeof(context->options), "mapreset");
985     break;
986     case EVENT_TELL:
987     snprintf(context->options, sizeof(context->options), "tell");
988     break;
989     }
990     va_end(args);
991     context->returnvalue = 0;
992    
993     if (!do_script(context, 1)) {
994     freeContext(context);
995     return &rv;
996     }
997    
998     context = popContext();
999     rv = context->returnvalue;
1000     freeContext(context);
1001    
1002     return &rv;
1003     }
1004    
1005     CF_PLUGIN void* eventListener(int* type, ...)
1006     {
1007     static int rv = 0;
1008     va_list args;
1009     char* buf;
1010     CFPContext* context;
1011    
1012     rv = 0;
1013    
1014     context = malloc(sizeof(CFPContext));
1015    
1016     context->message[0] = 0;
1017    
1018     va_start(args, type);
1019    
1020     context->who = Crossfire_Object_wrap(va_arg(args, object*));
1021     context->event_code = va_arg(args, int);
1022     context->activator = Crossfire_Object_wrap(va_arg(args, object*));
1023     context->third = Crossfire_Object_wrap(va_arg(args, object*));
1024     buf = va_arg(args, char*);
1025     if (buf != NULL)
1026     snprintf(context->message, sizeof(context->message), "%s", buf);
1027     context->fix = va_arg(args, int);
1028     snprintf(context->script, sizeof(context->script), "%s", cf_get_maps_directory(va_arg(args, char*)));
1029     snprintf(context->options, sizeof(context->options), "%s", va_arg(args, char*));
1030     context->returnvalue = 0;
1031    
1032     va_end(args);
1033    
1034     if (!do_script(context, 0)) {
1035     freeContext(context);
1036     return &rv;
1037     }
1038    
1039     context = popContext();
1040     rv = context->returnvalue;
1041     freeContext(context);
1042     return &rv;
1043     }
1044    
1045     CF_PLUGIN int closePlugin()
1046     {
1047     printf("CFPython 2.0a closing\n");
1048     Py_Finalize();
1049     return 0;
1050     }