Atrinik Server  4.0
atrinik_party.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
32 #include <plugin_python.h>
33 #include <player.h>
34 
38 static fields_struct fields[] = {
39  {"name", FIELDTYPE_SHSTR, offsetof(party_struct, name), FIELDFLAG_READONLY,
40  0, "Name of the party.; str (readonly)"},
41  {"leader", FIELDTYPE_SHSTR, offsetof(party_struct, leader), 0, 0,
42  "Name of the party's leader (a player name).; str"},
43  {"password", FIELDTYPE_CARY, offsetof(party_struct, passwd),
44  FIELDFLAG_READONLY, 0, "Password required to join the party.; str"}
45 };
46 
48 static const char doc_Atrinik_Party_AddMember[] =
49 ".. method:: AddMember(player).\n\n"
50 "Add a player to the party.\n\n"
51 ":param player: Player object to add to the party.\n"
52 ":type player: :class:`Atrinik.Object.Object`\n"
53 ":raises ValueError: If *player* is not a player object.\n"
54 ":raises Atrinik.AtrinikError: If the player is already in a party.";
55 
60 static PyObject *Atrinik_Party_AddMember(Atrinik_Party *self, PyObject *args)
61 {
62  Atrinik_Object *ob;
63 
64  if (!PyArg_ParseTuple(args, "O!", &Atrinik_ObjectType, &ob)) {
65  return NULL;
66  }
67 
68  OBJEXISTCHECK(ob);
69 
70  if (ob->obj->type != PLAYER || CONTR(ob->obj) == NULL) {
71  PyErr_SetString(PyExc_ValueError, "'player' must be a player object.");
72  return NULL;
73  } else if (CONTR(ob->obj)->party != NULL) {
74  if (CONTR(ob->obj)->party == self->party) {
75  RAISE("The specified player object is already in the party.");
76  } else {
77  RAISE("The specified player object is already in another party.");
78  }
79  }
80 
81  hooks->add_party_member(self->party, ob->obj);
82 
83  Py_INCREF(Py_None);
84  return Py_None;
85 }
86 
88 static const char doc_Atrinik_Party_RemoveMember[] =
89 ".. method:: RemoveMember(player).\n\n"
90 "Remove a player from the party.\n\n"
91 ":param player: Player object to remove from the party.\n"
92 ":type player: :class:`Atrinik.Object.Object`\n"
93 ":raises ValueError: If *player* is not a player object.\n"
94 ":raises Atrinik.AtrinikError: If the player is not in a party.";
95 
100 static PyObject *Atrinik_Party_RemoveMember(Atrinik_Party *self, PyObject *args)
101 {
102  Atrinik_Object *ob;
103 
104  if (!PyArg_ParseTuple(args, "O!", &Atrinik_ObjectType, &ob)) {
105  return NULL;
106  }
107 
108  OBJEXISTCHECK(ob);
109 
110  if (ob->obj->type != PLAYER || CONTR(ob->obj) == NULL) {
111  PyErr_SetString(PyExc_ValueError, "'player' must be a player object.");
112  return NULL;
113  } else if (CONTR(ob->obj)->party == NULL) {
114  RAISE("The specified player is not in a party.");
115  }
116 
117  hooks->remove_party_member(self->party, ob->obj);
118 
119  Py_INCREF(Py_None);
120  return Py_None;
121 }
122 
124 static const char doc_Atrinik_Party_GetMembers[] =
125 ".. method:: GetMembers().\n\n"
126 "Get members of the party.\n\n"
127 ":returns: List containing the party members as player objects.\n"
128 ":rtype: list of :class:`Atrinik.Object.Object`";
129 
135 {
136  PyObject *list = PyList_New(0);
137  for (objectlink *ol = self->party->members; ol != NULL; ol = ol->next) {
138  PyList_Append(list, wrap_object(ol->objlink.ob));
139  }
140 
141  return list;
142 }
143 
145 static const char doc_Atrinik_Party_SendMessage[] =
146 ".. method:: SendMessage(message, flags, player=None, exclude=None).\n\n"
147 "Send a message to members of the party.\n\n"
148 ":param message: Message to send.\n"
149 ":type message: str\n"
150 ":param flags: One of the PARTY_MESSAGE_xxx constants, eg, :attr:"
151 "`~Atrinik.PARTY_MESSAGE_STATUS`\n"
152 ":type flags: int\n"
153 ":param player: Who is sending the message. Required for :attr:"
154 "`~Atrinik.PARTY_MESSAGE_CHAT`.\n"
155 ":type player: :class:`Atrinik.Object.Object`\n"
156 ":param exclude: Player object to exclude from sending the message to.\n"
157 ":type exclude: :class:`Atrinik.Object.Object`";
158 
163 static PyObject *Atrinik_Party_SendMessage(Atrinik_Party *self, PyObject *args)
164 {
165  Atrinik_Object *ob = NULL, *exclude = NULL;
166  int flags;
167  const char *msg;
168 
169  if (!PyArg_ParseTuple(args, "si|O!O!", &msg, &flags, &Atrinik_ObjectType,
170  &ob, &Atrinik_ObjectType, &exclude)) {
171  return NULL;
172  }
173 
174  if (ob != NULL) {
175  OBJEXISTCHECK(ob);
176  }
177 
178  if (exclude != NULL) {
179  OBJEXISTCHECK(exclude);
180  }
181 
182  if (flags == PARTY_MESSAGE_CHAT && ob == NULL) {
183  RAISE("'player' argument is required.")
184  }
185 
186  hooks->send_party_message(self->party, msg, flags,
187  ob != NULL ? ob->obj : NULL, exclude != NULL ? exclude->obj : NULL);
188 
189  Py_INCREF(Py_None);
190  return Py_None;
191 }
192 
194 static PyMethodDef PartyMethods[] = {
195  {"AddMember", (PyCFunction) Atrinik_Party_AddMember, METH_VARARGS,
197  {"RemoveMember", (PyCFunction) Atrinik_Party_RemoveMember, METH_VARARGS,
199  {"GetMembers", (PyCFunction) Atrinik_Party_GetMembers, METH_NOARGS,
201  {"SendMessage", (PyCFunction) Atrinik_Party_SendMessage, METH_VARARGS,
203  {NULL, NULL, 0, 0}
204 };
205 
215 static PyObject *Party_GetAttribute(Atrinik_Party *party, void *context)
216 {
217  return generic_field_getter(context, party->party);
218 }
219 
231 static int Party_SetAttribute(Atrinik_Party *party, PyObject *value,
232  void *context)
233 {
234  if (generic_field_setter(context, party->party, value) == -1) {
235  return -1;
236  }
237 
238  return 0;
239 }
240 
252 static PyObject *Atrinik_Party_new(PyTypeObject *type, PyObject *args,
253  PyObject *kwds)
254 {
255  Atrinik_Party *self = (Atrinik_Party *) type->tp_alloc(type, 0);
256  if (self != NULL) {
257  self->party = NULL;
258  }
259 
260  return (PyObject *) self;
261 }
262 
269 {
270  self->party = NULL;
271 #ifndef IS_PY_LEGACY
272  Py_TYPE(self)->tp_free((PyObject *) self);
273 #else
274  self->ob_type->tp_free((PyObject *) self);
275 #endif
276 }
277 
285 static PyObject *Atrinik_Party_str(Atrinik_Party *self)
286 {
287  return Py_BuildValue("s", self->party->name);
288 }
289 
290 static int Atrinik_Party_InternalCompare(Atrinik_Party *left,
291  Atrinik_Party *right)
292 {
293  return (left->party < right->party ? -1 :
294  (left->party == right->party ? 0 : 1));
295 }
296 
297 static PyObject *Atrinik_Party_RichCompare(Atrinik_Party *left,
298  Atrinik_Party *right, int op)
299 {
300  if (left == NULL || right == NULL ||
301  !PyObject_TypeCheck((PyObject *) left, &Atrinik_PartyType) ||
302  !PyObject_TypeCheck((PyObject *) right, &Atrinik_PartyType)) {
303  Py_INCREF(Py_NotImplemented);
304  return Py_NotImplemented;
305  }
306 
307  return generic_rich_compare(op, Atrinik_Party_InternalCompare(left, right));
308 }
309 
311 static PyGetSetDef getseters[NUM_FIELDS + 1];
312 
314 PyTypeObject Atrinik_PartyType = {
315 #ifdef IS_PY3K
316  PyVarObject_HEAD_INIT(NULL, 0)
317 #else
318  PyObject_HEAD_INIT(NULL)
319  0,
320 #endif
321  "Atrinik.Party",
322  sizeof(Atrinik_Party),
323  0,
324  (destructor) Atrinik_Party_dealloc,
325  NULL, NULL, NULL,
326 #ifdef IS_PY3K
327  NULL,
328 #else
329  (cmpfunc) Atrinik_Party_InternalCompare,
330 #endif
331  0, 0, 0, 0, 0, 0,
332  (reprfunc) Atrinik_Party_str,
333  0, 0, 0,
334  Py_TPFLAGS_DEFAULT,
335  "Atrinik parties",
336  NULL, NULL,
337  (richcmpfunc) Atrinik_Party_RichCompare,
338  0, 0, 0,
339  PartyMethods,
340  0,
341  getseters,
342  0, 0, 0, 0, 0, 0, 0,
344  0, 0, 0, 0, 0, 0, 0, 0
345 #ifndef IS_PY_LEGACY
346  , 0
347 #endif
348 #ifdef Py_TPFLAGS_HAVE_FINALIZE
349  , NULL
350 #endif
351 };
352 
360 int Atrinik_Party_init(PyObject *module)
361 {
362  size_t i;
363 
364  /* Field getters */
365  for (i = 0; i < NUM_FIELDS; i++) {
366  PyGetSetDef *def = &getseters[i];
367 
368  def->name = fields[i].name;
369  def->get = (getter) Party_GetAttribute;
370  def->set = (setter) Party_SetAttribute;
371  def->doc = fields[i].doc;
372  def->closure = &fields[i];
373  }
374 
375  getseters[i].name = NULL;
376 
377  Atrinik_PartyType.tp_new = PyType_GenericNew;
378 
379  if (PyType_Ready(&Atrinik_PartyType) < 0) {
380  return 0;
381  }
382 
383  Py_INCREF(&Atrinik_PartyType);
384  PyModule_AddObject(module, "Party", (PyObject *) &Atrinik_PartyType);
385 
386  return 1;
387 }
388 
396 PyObject *wrap_party(party_struct *what)
397 {
398  /* Return None if no party was to be wrapped. */
399  if (what == NULL) {
400  Py_INCREF(Py_None);
401  return Py_None;
402  }
403 
404  Atrinik_Party *wrapper = PyObject_NEW(Atrinik_Party, &Atrinik_PartyType);
405  if (wrapper != NULL) {
406  wrapper->party = what;
407  }
408 
409  return (PyObject *) wrapper;
410 }
PyTypeObject Atrinik_ObjectType
static PyObject * Atrinik_Party_AddMember(Atrinik_Party *self, PyObject *args)
Definition: atrinik_party.c:60
Definition: object.h:488
static PyObject * Party_GetAttribute(Atrinik_Party *party, void *context)
struct plugin_hooklist * hooks
Definition: plugin_arena.c:160
uint8_t type
One of operation types.
Definition: sound_ambient.c:45
static PyObject * Atrinik_Party_SendMessage(Atrinik_Party *self, PyObject *args)
static const char doc_Atrinik_Party_SendMessage[]
static PyGetSetDef getseters[NUM_FIELDS+1]
#define RAISE(msg)
int generic_field_setter(fields_struct *field, void *ptr, PyObject *value)
PyObject * generic_rich_compare(int op, int result)
#define PLAYER
Definition: define.h:122
PyObject * wrap_object(object *what)
static const char doc_Atrinik_Party_GetMembers[]
#define IS_PY_LEGACY
Definition: plugin_python.h:55
static fields_struct fields[]
Definition: atrinik_party.c:38
static PyObject * Atrinik_Party_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static PyObject * Atrinik_Party_GetMembers(Atrinik_Party *self)
static int Party_SetAttribute(Atrinik_Party *party, PyObject *value, void *context)
#define FIELDFLAG_READONLY
#define NUM_FIELDS
static const char doc_Atrinik_Party_AddMember[]
Definition: atrinik_party.c:48
static PyObject * Atrinik_Party_RemoveMember(Atrinik_Party *self, PyObject *args)
static void Atrinik_Party_dealloc(Atrinik_Party *self)
static PyMethodDef PartyMethods[]
static const char doc_Atrinik_Party_RemoveMember[]
Definition: atrinik_party.c:88
PyTypeObject Atrinik_PartyType
int Atrinik_Party_init(PyObject *module)
PyObject * generic_field_getter(fields_struct *field, void *ptr)
PyObject_HEAD party_struct * party
struct oblnk * next
Definition: object.h:500
PyObject * wrap_party(party_struct *what)
uint8_t type
Definition: object.h:360
#define PARTY_MESSAGE_CHAT
Definition: party.h:45
static PyObject * Atrinik_Party_str(Atrinik_Party *self)
PyObject_HEAD object * obj