KDEGames

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

KDE's Doxygen guidelines are available online.