PageRenderTime 49ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/client/src/python/clientmodule.cpp

https://github.com/Mutilador/Wolfpack
C++ | 190 lines | 134 code | 31 blank | 25 comment | 26 complexity | 6a7809c7a4264b41b610c6fecc9bf32f MD5 | raw file
  1. #include <Python.h>
  2. #include "skills.h"
  3. #include "utilities.h"
  4. #include "scripts.h"
  5. #include "dialogs/login.h"
  6. #include "gui/gui.h"
  7. #include "muls/localization.h"
  8. #include "muls/gumpart.h"
  9. #include "muls/tiledata.h"
  10. #include "python/genericwrapper.h"
  11. #include "python/utilities.h"
  12. #include "python/universalslot.h"
  13. #include "network/uosocket.h"
  14. #include "network/network.h"
  15. #include "game/mobile.h"
  16. #include "game/world.h"
  17. /*
  18. Connect a QObject Signal to a QObject Slot
  19. or
  20. Connect a QObject Signal to a Python Callable
  21. */
  22. static PyObject *connect(PyObject *self, PyObject *args) {
  23. PyObject *sender, *recipient;
  24. PyObject *pySignal, *pySlot = 0;
  25. if (!PyArg_ParseTuple(args, "O!OO|O", &pyWrapperType, &sender, &pySignal, &recipient, &pySlot)) {
  26. return 0;
  27. }
  28. QString signal = fromPythonToString(pySignal);
  29. // If no slot is specified, reciepient has to be a callable
  30. if (!pySlot && !PyCallable_Check(recipient)) {
  31. PyErr_SetString(PyExc_TypeError, "client.connect(sender, signal, recipient): recipient has to be a callable python object.");
  32. return 0;
  33. }
  34. // If the slot is specified, recipient has to be a QObject
  35. if (pySlot && !isGenericWrapper(recipient)) {
  36. PyErr_SetString(PyExc_TypeError, "client.connect(sender, signal, recipient, slot): slot has to be a wrapped QObject.");
  37. return 0;
  38. }
  39. // Connect using the universal connector
  40. if (!pySlot) {
  41. QObject *qSender = getWrappedObject(sender);
  42. if (!qSender) {
  43. PyErr_SetString(PyExc_RuntimeError, "client.connect(sender, signal, recipient): sender has already been freed.");
  44. return 0;
  45. }
  46. cUniversalSlot *slot = new cUniversalSlot(qSender, signal.toLocal8Bit(), recipient);
  47. if (!slot->isValid()) {
  48. delete slot;
  49. PyErr_Format(PyExc_RuntimeError, "client.connect(sender, signal, recipient): Trying to connect to unknown signal: %s.", signal.toLocal8Bit().data());
  50. return 0;
  51. }
  52. }
  53. Py_RETURN_TRUE;
  54. }
  55. /*
  56. Disconnect a QObject Signal from a QObject Slot
  57. or
  58. Disconnect a QObject Signal from a Python Callable
  59. */
  60. static PyObject *disconnect(PyObject *self, PyObject *args) {
  61. PyObject *sender, *recipient;
  62. if (!PyArg_ParseTuple(args, "O!O", &pyWrapperType, &sender, &recipient)) {
  63. return 0;
  64. }
  65. // If no slot is specified, reciepient has to be a callable
  66. if (!PyCallable_Check(recipient)) {
  67. PyErr_SetString(PyExc_TypeError, "client.disconnect(sender, signal, recipient): recipient has to be a callable python object.");
  68. return 0;
  69. }
  70. // Connect using the universal connector
  71. QObject *qSender = getWrappedObject(sender);
  72. if (!qSender) {
  73. PyErr_SetString(PyExc_RuntimeError, "client.disconnect(sender, signal, recipient): sender has already been freed.");
  74. return 0;
  75. }
  76. // Find the slot connected to the given object
  77. QVector<cUniversalSlot*> slotlist = Scripts->getSlotlist();
  78. foreach (cUniversalSlot *slot, slotlist) {
  79. if (slot->recipient() == recipient) {
  80. qSender->disconnect(slot);
  81. delete slot;
  82. }
  83. }
  84. Py_RETURN_TRUE;
  85. }
  86. static PyObject *random(PyObject *self, PyObject *args) {
  87. if (PyTuple_Size(args) == 2) {
  88. int mi, ma;
  89. if (!PyArg_ParseTuple(args, "ii", &mi, &ma)) {
  90. return 0;
  91. }
  92. return PyInt_FromLong(mi + Random->randInt(ma - mi));
  93. }
  94. Py_RETURN_NONE;
  95. }
  96. static PyObject *sender(PyObject *self, PyObject *args) {
  97. return generateWrapper(Scripts->sender());
  98. }
  99. static PyMethodDef clientMethods[] = {
  100. {"connect", connect, METH_VARARGS, 0},
  101. {"disconnect", disconnect, METH_VARARGS, 0},
  102. {"random", random, METH_VARARGS, 0},
  103. {"sender", sender, METH_VARARGS, 0},
  104. {0, 0, 0, 0}
  105. };
  106. /*
  107. This is a specialized version of the Py_InitModule function.
  108. */
  109. void addModuleMethods(PyObject *m) {
  110. PyObject *d = PyModule_GetDict(m);
  111. PyMethodDef *ml;
  112. PyObject *n = PyString_FromString("client");
  113. if (n == NULL)
  114. return;
  115. for (ml = &clientMethods[0]; ml->ml_name != NULL; ml++) {
  116. PyObject *v = PyCFunction_NewEx(ml, 0, n);
  117. if (v == NULL)
  118. return;
  119. if (PyDict_SetItemString(d, ml->ml_name, v) != 0) {
  120. Py_DECREF(v);
  121. return;
  122. }
  123. Py_DECREF(v);
  124. }
  125. }
  126. void initializeClientModule() {
  127. // Look for an "uoclient" module to modify or a new one to create
  128. PyObject *moduleName = PyString_FromString("client");
  129. PyObject *module = PyImport_Import(moduleName);
  130. Py_DECREF(moduleName);
  131. // If no module was found, create an empty one
  132. if (!module) {
  133. if (PyErr_Occurred()) {
  134. PyErr_Clear();
  135. }
  136. module = PyImport_AddModule("client");
  137. Py_INCREF(module);
  138. }
  139. // Add the global toplevel objects
  140. PyObject *obj;
  141. #define ADD_GLOBAL_OBJ(object) obj = generateWrapper(object); \
  142. PyObject_SetAttrString(module, #object, generateWrapper(object)); \
  143. Py_DECREF(obj);
  144. // Add objects to the module
  145. ADD_GLOBAL_OBJ(Gui);
  146. ADD_GLOBAL_OBJ(Skills);
  147. ADD_GLOBAL_OBJ(Localization);
  148. ADD_GLOBAL_OBJ(Tiledata);
  149. ADD_GLOBAL_OBJ(Gumpart);
  150. ADD_GLOBAL_OBJ(LoginDialog);
  151. ADD_GLOBAL_OBJ(UoSocket);
  152. ADD_GLOBAL_OBJ(Network);
  153. ADD_GLOBAL_OBJ(Player);
  154. ADD_GLOBAL_OBJ(World);
  155. // Add Methods to the module
  156. addModuleMethods(module);
  157. // Free our reference to the module
  158. Py_DECREF(module);
  159. }