KDEGames

kplayer.cpp
1 /*
2  This file is part of the KDE games library
3  Copyright (C) 2001 Martin Heni (kde at heni-online.de)
4  Copyright (C) 2001 Andreas Beckermann ([email protected])
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Library General Public
8  License version 2 as published by the Free Software Foundation.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Library General Public License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to
17  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19 */
20 
21 #include "kplayer.h"
22 #include "kgame.h"
23 #include "kgameio.h"
24 #include "kgamemessage.h"
25 #include "kgameproperty.h"
26 #include "kgamepropertyhandler.h"
27 
28 #include <KLocalizedString>
29 
30 #include <QBuffer>
31 
32 #include <stdio.h>
33 #include <assert.h>
34 
35 #define KPLAYER_LOAD_COOKIE 7285
36 
37 class KPlayerPrivate
38 {
39 public:
40  KPlayerPrivate()
41  {
42  mNetworkPlayer = nullptr;
43  }
44 
45  KGame *mGame;
46  bool mActive; // active player
47  KPlayer::KGameIOList mInputList;
48 
49  // GameProperty
50  KGamePropertyBool mAsyncInput; // async input allowed
51  KGamePropertyBool mMyTurn; // Is it my turn to play (only useful if not async)?
52  KGamePropertyInt mUserId; // a user defined id
53 
54  quint32 mId;
55  bool mVirtual; // virtual player
56  int mPriority; // tag for replacement
57 
58  KPlayer* mNetworkPlayer; // replacement player
59 
60  KGamePropertyHandler mProperties;
61 
62 // Playerdata
64  KGamePropertyQString mGroup;
65 };
66 
68  : QObject(), d(new KPlayerPrivate)
69 {
70  init();
71 }
72 
73 void KPlayer::init()
74 {
75 // note that NO KGame object exists here! so we cannot use KGameProperty::send!
76  qCDebug(GAMES_PRIVATE_KGAME) << ": this=" << this << ", sizeof(this)="<<sizeof(KPlayer);
77  qCDebug(GAMES_PRIVATE_KGAME) << "sizeof(m_Group)="<<sizeof(d->mGroup);
78 
79  d->mProperties.registerHandler(KGameMessage::IdPlayerProperty,
80  this,SLOT(sendProperty(int,QDataStream&,bool*)),
82  d->mVirtual=false;
83  d->mActive=true;
84  d->mGame=nullptr;
85  d->mId=0; // "0" is always an invalid ID!
86  d->mPriority=0;
87  // I guess we cannot translate the group otherwise no
88  // international connections are possible
89 
90  d->mUserId.registerData(KGamePropertyBase::IdUserId, this, i18n("UserId"));
91  d->mUserId.setLocal(0);
92  d->mGroup.registerData(KGamePropertyBase::IdGroup, this, i18n("Group"));
93  d->mGroup.setLocal(i18n("default"));
94  d->mName.registerData(KGamePropertyBase::IdName, this, i18n("Name"));
95  d->mName.setLocal(i18n("default"));
96 
97  d->mAsyncInput.registerData(KGamePropertyBase::IdAsyncInput, this, i18n("AsyncInput"));
98  d->mAsyncInput.setLocal(false);
99  d->mMyTurn.registerData(KGamePropertyBase::IdTurn, this, i18n("myTurn"));
100  d->mMyTurn.setLocal(false);
101  d->mMyTurn.setEmittingSignal(true);
102  d->mMyTurn.setOptimized(false);
103 }
104 
105 KPlayer::~KPlayer()
106 {
107  qCDebug(GAMES_PRIVATE_KGAME) << ": this=" << this <<", id=" << this->id();
108 
109  // Delete IODevices
110  qDeleteAll(d->mInputList);
111  d->mInputList.clear();
112  if (game())
113  {
114  game()->playerDeleted(this);
115  }
116 
117 // note: mProperties does not use autoDelete or so - user must delete objects
118 // himself
119  d->mProperties.clear();
120  delete d;
121  qCDebug(GAMES_PRIVATE_KGAME) << "done";
122 }
123 
124 int KPlayer::rtti() const
125 {
126  return 0;
127 }
128 
130 {
131  return &d->mInputList;
132 }
133 
135 {
136  d->mGame = game;
137 }
138 
140 {
141  return d->mGame;
142 }
143 
145 {
146  d->mAsyncInput = a;
147 }
148 
150 {
151  return d->mAsyncInput.value();
152 }
153 
154 bool KPlayer::isActive() const
155 {
156  return d->mActive;
157 }
158 
159 void KPlayer::setActive(bool v)
160 {
161  d->mActive = v;
162 }
163 
164 int KPlayer::userId() const
165 {
166  return d->mUserId.value();
167 }
168 
169 void KPlayer::setUserId(int i)
170 {
171  d->mUserId = i;
172 }
173 
174 bool KPlayer::myTurn() const
175 {
176  return d->mMyTurn.value();
177 }
178 
179 bool KPlayer::forwardMessage(QDataStream &msg,int msgid,quint32 receiver,quint32 sender)
180 {
181  if (!isActive())
182  {
183  return false;
184  }
185  if (!game())
186  {
187  return false;
188  }
189  qCDebug(GAMES_PRIVATE_KGAME) << ": to game sender="<<sender<<"" << "recv="<<receiver <<"msgid="<<msgid;
190  return game()->sendSystemMessage(msg,msgid,receiver,sender);
191 }
192 
193 bool KPlayer::forwardInput(QDataStream &msg,bool transmit,quint32 sender)
194 {
195  if (!isActive())
196  {
197  return false;
198  }
199  if (!game())
200  {
201  return false;
202  }
203 
204  qCDebug(GAMES_PRIVATE_KGAME) << ": to game playerInput(sender="<<sender<<")";
205  if (!asyncInput() && !myTurn())
206  {
207  qCDebug(GAMES_PRIVATE_KGAME) << ": rejected cause it is not our turn";
208  return false;
209  }
210 
211  // AB: I hope I remember the usage correctly:
212  // this function is called twice (on sender side) - once with transmit = true
213  // where it sends the input to the comserver and once with transmit = false
214  // where it really looks at the input
215  if (transmit)
216  {
217  qCDebug(GAMES_PRIVATE_KGAME) << "indirect playerInput";
218  return game()->sendPlayerInput(msg,this,sender);
219  }
220  else
221  {
222  qCDebug(GAMES_PRIVATE_KGAME) << "direct playerInput";
223  return game()->systemPlayerInput(msg,this,sender);
224  }
225 }
226 
227 void KPlayer::setId(quint32 newid)
228 {
229  // Needs to be after the sendProcess
230  d->mId=newid;
231 }
232 
233 
235 { d->mGroup = group; }
236 
237 const QString& KPlayer::group() const
238 { return d->mGroup.value(); }
239 
241 { d->mName = name; }
242 
243 const QString& KPlayer::name() const
244 { return d->mName.value(); }
245 
246 quint32 KPlayer::id() const
247 { return d->mId; }
248 
250 { return &d->mProperties; }
251 
253 { d->mVirtual = v; }
254 
255 bool KPlayer::isVirtual() const
256 { return d->mVirtual;}
257 
259 { d->mNetworkPlayer = p; }
260 
262 { return d->mNetworkPlayer; }
263 
265 { return d->mPriority; }
266 
268 { d->mPriority = p; }
269 
271 {
272  if (!input)
273  {
274  return false;
275  }
276  d->mInputList.append(input);
277  input->initIO(this); // set player and init device
278  return true;
279 }
280 
281 // input=0, remove all
282 bool KPlayer::removeGameIO(KGameIO *targetinput,bool deleteit)
283 {
284  qCDebug(GAMES_PRIVATE_KGAME) << ":" << targetinput << "delete=" << deleteit;
285  bool result=true;
286  if (!targetinput) // delete all
287  {
288  KGameIO *input;
289  while(!d->mInputList.isEmpty())
290  {
291  input = d->mInputList.first();
292  if (input) removeGameIO(input,deleteit);
293  }
294  }
295  else
296  {
297 // qCDebug(GAMES_PRIVATE_KGAME) << "remove IO" << targetinput;
298  if (deleteit)
299  {
300  delete targetinput;
301  }
302  else
303  {
304  targetinput->setPlayer(nullptr);
305  result = d->mInputList.removeAll(targetinput);
306  }
307  }
308  return result;
309 }
310 
311 bool KPlayer::hasRtti(int rtti) const
312 {
313  return findRttiIO(rtti) != nullptr;
314 }
315 
317 {
318  QListIterator<KGameIO*> it(d->mInputList);
319  while (it.hasNext())
320  {
321  KGameIO* curGameIO = it.next();
322  if (curGameIO->rtti() == rtti)
323  {
324  return curGameIO;
325  }
326  }
327  return nullptr;
328 }
329 
331 {
332  int value=0;
333  QListIterator<KGameIO*> it(d->mInputList);
334  while (it.hasNext())
335  {
336  value|=it.next()->rtti();
337  }
338  return value;
339 }
340 
341 bool KPlayer::setTurn(bool b, bool exclusive)
342 {
343  qCDebug(GAMES_PRIVATE_KGAME) << ":" << id() << " (" << this << ") to" << b;
344  if (!isActive())
345  {
346  return false;
347  }
348 
349  // if we get to do an exclusive turn all other players are disallowed
350  if (exclusive && b && game())
351  {
352  for ( KGame::KGamePlayerList::iterator it = game()->playerList()->begin();
353  it!=game()->playerList()->end(); ++it)
354  {
355  if ((*it)==this)
356  {
357  continue;
358  }
359  (*it)->setTurn(false,false);
360  }
361  }
362 
363  // Return if nothing changed
364  d->mMyTurn = b;
365 
366  return true;
367 }
368 
370 {
371  qint32 id,priority;
372  stream >> id >> priority;
373  setId(id);
374  setNetworkPriority(priority);
375 
376  // Load Player Data
377  //FIXME: maybe set all properties setEmitSignal(false) before?
378  d->mProperties.load(stream);
379 
380  qint16 cookie;
381  stream >> cookie;
382  if (cookie==KPLAYER_LOAD_COOKIE)
383  {
384  qCDebug(GAMES_PRIVATE_KGAME) << " Player loaded properly";
385  }
386  else
387  {
388  qCCritical(GAMES_PRIVATE_KGAME) << " Player loading error. probably format error";
389  }
390 
391  // Q_EMIT signalLoad(stream);
392  return true;
393 }
394 
396 {
397  stream << (qint32)id() << (qint32)networkPriority();
398 
399  d->mProperties.save(stream);
400 
401  stream << (qint16)KPLAYER_LOAD_COOKIE;
402 
403  //Q_EMIT signalSave(stream);
404  return true;
405 }
406 
407 
408 void KPlayer::networkTransmission(QDataStream &stream,int msgid,quint32 sender)
409 {
410  //qCDebug(GAMES_PRIVATE_KGAME) ": msgid=" << msgid << "sender=" << sender << "we are=" << id();
411  // PlayerProperties processed
412  bool issender;
413  if (game())
414  {
415  issender=sender==game()->gameId();
416  }
417  else
418  {
419  issender=true;
420  }
421  if (d->mProperties.processMessage(stream,msgid,issender))
422  {
423  return ;
424  }
425  switch(msgid)
426  {
427  case KGameMessage::IdPlayerInput:
428  {
429  qCDebug(GAMES_PRIVATE_KGAME) << ": Got player move "
430  << "KPlayer (virtual) forwards it to the game object";
431  forwardInput(stream,false);
432  }
433  break;
434  default:
435  Q_EMIT signalNetworkData(msgid - KGameMessage::IdUser,
436  ((QBuffer*)stream.device())->readAll(),sender,this);
437  qCDebug(GAMES_PRIVATE_KGAME) << ": "
438  << "User data msgid" << msgid;
439  break;
440  }
441 
442 }
443 
445 {
446  return d->mProperties.find(id);
447 }
448 
450 {
451  return d->mProperties.addProperty(data);
452 }
453 
454 void KPlayer::sendProperty(int msgid, QDataStream& stream, bool* sent)
455 {
456  if (game())
457  {
458  bool s = game()->sendPlayerProperty(msgid, stream, id());
459  if (s)
460  {
461  *sent = true;
462  }
463  }
464 }
465 
467 {
468  // Notify KGameIO (Process) for a new turn
469  if (me->id()==KGamePropertyBase::IdTurn)
470  {
471  //qCDebug(GAMES_PRIVATE_KGAME) << ": for KGamePropertyBase::IdTurn";
472  QListIterator<KGameIO*> it(d->mInputList);
473  while (it.hasNext())
474  {
475  it.next()->notifyTurn(d->mMyTurn.value());
476  }
477  }
478  Q_EMIT signalPropertyChanged(me,this);
479 }
480 
481 // --------------------- DEBUG --------------------
483 {
484  qCDebug(GAMES_PRIVATE_KGAME) << "------------------- KPLAYER -----------------------";
485  qCDebug(GAMES_PRIVATE_KGAME) << "this: " << this;
486  qCDebug(GAMES_PRIVATE_KGAME) << "rtti: " << rtti();
487  qCDebug(GAMES_PRIVATE_KGAME) << "id : " << id();
488  qCDebug(GAMES_PRIVATE_KGAME) << "Name : " << name();
489  qCDebug(GAMES_PRIVATE_KGAME) << "Group: " << group();
490  qCDebug(GAMES_PRIVATE_KGAME) << "Async: " << asyncInput();
491  qCDebug(GAMES_PRIVATE_KGAME) << "myTurn: " << myTurn();
492  qCDebug(GAMES_PRIVATE_KGAME) << "Virtual:" << isVirtual();
493  qCDebug(GAMES_PRIVATE_KGAME) << "Active: " << isActive();
494  qCDebug(GAMES_PRIVATE_KGAME) << "Priority:" << networkPriority();
495  qCDebug(GAMES_PRIVATE_KGAME) << "Game :" << game();
496  qCDebug(GAMES_PRIVATE_KGAME) << "#IOs: " << d->mInputList.count();
497  qCDebug(GAMES_PRIVATE_KGAME) << "---------------------------------------------------";
498 }
499 
500 
void setNetworkPriority(int b)
Set whether this player can be replaced by a network player.
Definition: kplayer.cpp:267
KPlayer * networkPlayer() const
Returns the player which got inactivated to allow this player to be set up via network.
Definition: kplayer.cpp:261
void signalNetworkData(int msgid, const QByteArray &buffer, quint32 sender, KPlayer *me)
The player object got a message which was targeted at it but has no default method to process it...
void setVirtual(bool v)
Definition: kplayer.cpp:252
quint32 id() const
Returns the id of the player.
Definition: kplayer.cpp:246
bool addProperty(KGamePropertyBase *data)
Adds a property to a player.
Definition: kplayer.cpp:449
virtual bool systemPlayerInput(QDataStream &msg, KPlayer *player, quint32 sender=0)
Called when a player input arrives from KMessageServer.
Definition: kgame.cpp:735
const T & next()
bool setTurn(bool b, bool exclusive=true)
Sets whether this player is the next to turn.
Definition: kplayer.cpp:341
int calcIOValue()
Calculates a checksum over the IO devices.
Definition: kplayer.cpp:330
A collection class for KGameProperty objects.
QObject * sender() const const
KGameIOList * ioList()
Returns a list of input devices.
Definition: kplayer.cpp:129
KGame * game() const
Query to which game the player belongs to.
Definition: kplayer.cpp:139
virtual bool forwardMessage(QDataStream &msg, int msgid, quint32 receiver=0, quint32 sender=0)
Forwards Message to the game object..internal use only.
Definition: kplayer.cpp:179
void Debug()
Gives debug output of the game status.
Definition: kplayer.cpp:482
void emitSignal(KGamePropertyBase *me)
Called by KGameProperty only! Internal function!
Definition: kplayer.cpp:466
bool myTurn() const
is it my turn to go
Definition: kplayer.cpp:174
bool isVirtual() const
Is this player a virtual player, i.e.
Definition: kplayer.cpp:255
void signalPropertyChanged(KGamePropertyBase *property, KPlayer *me)
This signal is emitted if a player property changes its value and the property is set to notify this ...
void setPlayer(KPlayer *p)
Sets the player to which this IO belongs to.
Definition: kgameio.cpp:84
bool removeGameIO(KGameIO *input=nullptr, bool deleteit=true)
remove (and delete) a game IO device
Definition: kplayer.cpp:282
KGameIO * findRttiIO(int rtti) const
Finds the KGameIO devies with the given rtti code.
Definition: kplayer.cpp:316
virtual const QString & name() const
Definition: kplayer.cpp:243
int userId() const
Returns the user defined id of the player This value can be used arbitrary by you to have some user i...
Definition: kplayer.cpp:164
void setActive(bool v)
Set an player as active (true) or inactive (false)
Definition: kplayer.cpp:159
bool addGameIO(KGameIO *input)
Adds an IO device for the player.
Definition: kplayer.cpp:270
bool sendPlayerProperty(int msgid, QDataStream &s, quint32 playerId)
This is called by KPlayer::sendProperty only! Internal function!
Definition: kgame.cpp:1452
virtual bool load(QDataStream &stream)
Load a saved player, from file OR network.
Definition: kplayer.cpp:369
void setGroup(const QString &group)
A group the player belongs to.
Definition: kplayer.cpp:234
virtual const QString & group() const
Query the group the player belongs to.
Definition: kplayer.cpp:237
bool asyncInput() const
Query whether this player does asynchronous input.
Definition: kplayer.cpp:149
int networkPriority() const
Returns whether this player can be replaced by a network connection player.
Definition: kplayer.cpp:264
bool hasRtti(int rtti) const
Checks whether this player has a IO device of the given rtti type.
Definition: kplayer.cpp:311
virtual bool save(QDataStream &stream)
Save a player to a file OR to network.
Definition: kplayer.cpp:395
virtual void initIO(KPlayer *p)
Init this device by setting the player and e.g.
Definition: kgameio.cpp:89
Base class for a game player.
Definition: kplayer.h:69
QList::iterator end()
Base class of KGameProperty.
Definition: kgameproperty.h:45
QString i18n(const char *text, const TYPE &arg...)
void setNetworkPlayer(KPlayer *p)
Sets this network player replacement.
Definition: kplayer.cpp:258
void setGame(KGame *game)
sets the game the player belongs to.
Definition: kplayer.cpp:134
virtual bool sendPlayerInput(QDataStream &msg, KPlayer *player, quint32 sender=0)
Called by KPlayer to send a player input to the KMessageServer.
Definition: kgame.cpp:717
KGamePropertyBase * findProperty(int id) const
Searches for a property of the player given its id.
Definition: kplayer.cpp:444
The main KDE game object.
Definition: kgame.h:64
KGamePropertyHandler * dataHandler()
Definition: kplayer.cpp:249
KGamePlayerList * playerList()
Returns a list of all active players.
Definition: kgame.cpp:707
void networkTransmission(QDataStream &stream, int msgid, quint32 sender)
Receives a message.
Definition: kplayer.cpp:408
quint32 gameId() const
The unique ID of this game.
KPlayer()
Create a new player object.
Definition: kplayer.cpp:67
virtual bool forwardInput(QDataStream &msg, bool transmit=true, quint32 sender=0)
Forwards input to the game object..internal use only.
Definition: kplayer.cpp:193
void setAsyncInput(bool a)
Set whether this player can make turns/input all the time (true) or only when it is its turn (false) ...
Definition: kplayer.cpp:144
virtual int rtti() const =0
Run time identification.
Base class for IO devices for games.
Definition: kgameio.h:65
bool isActive() const
Is this player an active player.
Definition: kplayer.cpp:154
QIODevice * device() const const
virtual int rtti() const
The identification of the player.
Definition: kplayer.cpp:124
void setName(const QString &name)
Sets the name of the player.
Definition: kplayer.cpp:240
bool sendSystemMessage(const QByteArray &buffer, int msgid, quint32 receiver=0, quint32 sender=0)
Sends a network message msg with a given msg id msgid to all clients.
void playerDeleted(KPlayer *player)
Called by the destructor of KPlayer to remove itself from the game.
Definition: kgame.cpp:496
int id() const
Q_EMITQ_EMIT
void sendProperty(int msgid, QDataStream &stream, bool *sent)
Called by KGameProperty only! Internal function!
Definition: kplayer.cpp:454
bool hasNext() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Thu Nov 26 2020 22:36:18 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.