ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/plugins/cfpython/cfpython.c
Revision: 1.2
Committed: Sun Aug 13 17:16:02 2006 UTC (17 years, 9 months ago) by elmex
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +0 -0 lines
State: FILE REMOVED
Log Message:
Made server compile with C++.
Removed cfanim plugin and crossedit.
C++ here we come.

File Contents

# Content
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 }