KDEGames

kgameio.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 "kgameio.h"
10 
11 // own
12 #include "kgame.h"
13 #include "kplayer.h"
14 #include "kgamemessage.h"
15 #include "kmessageio.h"
16 // Qt
17 #include <QWidget>
18 #include <QBuffer>
19 #include <QTimer>
20 #include <QGraphicsScene>
21 #include <QMouseEvent>
22 #include <QKeyEvent>
23 #include <QEvent>
24 // Std
25 #include <cstdlib>
26 
27 class KGameIOPrivate
28 {
29 public:
30  KGameIOPrivate()
31  : mPlayer(nullptr)
32  {
33  }
34 
35  KPlayer *mPlayer;
36 };
37 
38 
39 // ----------------------- Generic IO -------------------------
41  : KGameIO(*new KGameIOPrivate)
42 {
43 }
44 
46  : KGameIO(*new KGameIOPrivate, player)
47 {
48 }
49 
50 KGameIO::KGameIO(KGameIOPrivate &dd, KPlayer *player)
51  : d(&dd)
52 {
53  qCDebug(GAMES_PRIVATE_KGAME) << ": this=" << this << ", sizeof(this)" << sizeof(KGameIO);
54  if (player)
55  {
56  player->addGameIO(this);
57  }
58 }
59 
60 KGameIO::~KGameIO()
61 {
62  qCDebug(GAMES_PRIVATE_KGAME) << ": this=" << this;
63  // unregister ourselves
64  if (player())
65  {
66  player()->removeGameIO(this, false);
67  }
68 }
69 
71 {
72  return d->mPlayer;
73 }
74 
76 {
77  d->mPlayer = p;
78 }
79 
81 {
82  setPlayer(p);
83 }
84 
85 void KGameIO::notifyTurn(bool b)
86 {
87  if (!player())
88  {
89  qCWarning(GAMES_PRIVATE_KGAME) << ": player() is NULL";
90  return;
91  }
92  bool sendit=false;
93  QByteArray buffer;
94  QDataStream stream(&buffer, QIODevice::WriteOnly);
95  Q_EMIT signalPrepareTurn(stream, b, this, &sendit);
96  if (sendit)
97  {
98  QDataStream ostream(buffer);
99  quint32 sender = player()->id(); // force correct sender
100  qCDebug(GAMES_PRIVATE_KGAME) << "Prepare turn sendInput";
101  sendInput(ostream, true, sender);
102  }
103 }
104 
106 {
107  if (!player())
108  {
109  return nullptr;
110  }
111  return player()->game();
112 }
113 
114 bool KGameIO::sendInput(QDataStream& s, bool transmit, quint32 sender)
115 {
116  if (!player())
117  {
118  return false;
119  }
120  return player()->forwardInput(s, transmit, sender);
121 }
122 
124 {
125  qCDebug(GAMES_PRIVATE_KGAME) << "------------------- KGAMEINPUT --------------------";
126  qCDebug(GAMES_PRIVATE_KGAME) << "this: " << this;
127  qCDebug(GAMES_PRIVATE_KGAME) << "rtti : " << rtti();
128  qCDebug(GAMES_PRIVATE_KGAME) << "Player: " << player();
129  qCDebug(GAMES_PRIVATE_KGAME) << "---------------------------------------------------";
130 }
131 
132 // ----------------------- Key IO ---------------------------
133 class KGameKeyIOPrivate : public KGameIOPrivate
134 {
135 };
136 
138  : KGameIO(*new KGameKeyIOPrivate)
139 {
140  if (parent)
141  {
142  qCDebug(GAMES_PRIVATE_KGAME) << "Key Event filter installed";
143  parent->installEventFilter(this);
144  }
145 }
146 
147 KGameKeyIO::~KGameKeyIO()
148 {
149  if (parent())
150  {
151  parent()->removeEventFilter(this);
152  }
153 }
154 
155 int KGameKeyIO::rtti() const { return KeyIO; }
156 
158 {
159  if (!player())
160  {
161  return false;
162  }
163 
164  // key press/release
165  if ( e->type() == QEvent::KeyPress ||
166  e->type() == QEvent::KeyRelease )
167  {
168  QKeyEvent *k = (QKeyEvent*)e;
169  // qCDebug(GAMES_PRIVATE_KGAME) << "KGameKeyIO" << this << "key press/release" << k->key();
170  QByteArray buffer;
171  QDataStream stream(&buffer,QIODevice::WriteOnly);
172  bool eatevent=false;
173  Q_EMIT signalKeyEvent(this,stream,k,&eatevent);
174  QDataStream msg(buffer);
175 
176  if (eatevent && sendInput(msg))
177  {
178  return eatevent;
179  }
180  return false; // do not eat otherwise
181  }
182  return QObject::eventFilter( o, e ); // standard event processing
183 }
184 
185 
186 // ----------------------- Mouse IO ---------------------------
187 class KGameMouseIOPrivate : public KGameIOPrivate
188 {
189 };
190 
192  : KGameIO(*new KGameMouseIOPrivate)
193 {
194  if (parent)
195  {
196  qCDebug(GAMES_PRIVATE_KGAME) << "Mouse Event filter installed tracking=" << trackmouse;
197  parent->installEventFilter(this);
198  parent->setMouseTracking(trackmouse);
199  }
200 }
201 
202 KGameMouseIO::KGameMouseIO(QGraphicsScene *parent,bool /*trackmouse*/)
203  : KGameIO(*new KGameMouseIOPrivate)
204 {
205  if (parent)
206  {
207  //qCDebug(GAMES_PRIVATE_KGAME) << "Mouse Event filter installed tracking=" << trackmouse;
208  parent->installEventFilter(this);
209 // parent->setMouseTracking(trackmouse);
210  }
211 }
212 
213 KGameMouseIO::~KGameMouseIO()
214 {
215  if (parent())
216  {
217  parent()->removeEventFilter(this);
218  }
219 }
220 
222 {
223  return MouseIO;
224 }
225 
227 {
228  if (parent())
229  {
230  ((QWidget*)parent())->setMouseTracking(b);
231  }
232 }
233 
235 {
236  if (!player())
237  {
238  return false;
239  }
240  //qCDebug(GAMES_PRIVATE_KGAME) << "KGameMouseIO" << this << QLatin1String( " " ) << e->type();
241 
242  // mouse action
243  if ( e->type() == QEvent::MouseButtonPress ||
246  e->type() == QEvent::Wheel ||
247  e->type() == QEvent::MouseMove ||
253  )
254  {
255  QMouseEvent *k = (QMouseEvent*)e;
256  // qCDebug(GAMES_PRIVATE_KGAME) << "KGameMouseIO" << this;
257  QByteArray buffer;
258  QDataStream stream(&buffer,QIODevice::WriteOnly);
259  bool eatevent=false;
260  Q_EMIT signalMouseEvent(this,stream,k,&eatevent);
261 // qCDebug(GAMES_PRIVATE_KGAME) << "################# eatevent=" << eatevent;
262  QDataStream msg(buffer);
263  if (eatevent && sendInput(msg))
264  {
265  return eatevent;
266  }
267  return false; // do not eat otherwise
268  }
269  return QObject::eventFilter( o, e ); // standard event processing
270 }
271 
272 
273 // ----------------------- KGameProcesPrivate ---------------------------
274 class KGameProcessIOPrivate : public KGameIOPrivate
275 {
276 public:
277  KGameProcessIOPrivate()
278  {
279  //mMessageServer = 0;
280  //mMessageClient = 0;
281  mProcessIO=nullptr;
282  }
283  //KMessageServer *mMessageServer;
284  //KMessageClient *mMessageClient;
285  KMessageProcess *mProcessIO;
286 };
287 
288 // ----------------------- Process IO ---------------------------
290  : KGameIO(*new KGameProcessIOPrivate)
291 {
292  Q_D(KGameProcessIO);
293 
294  qCDebug(GAMES_PRIVATE_KGAME) << ": this=" << this << ", sizeof(this)=" << sizeof(KGameProcessIO);
295 
296  //qCDebug(GAMES_PRIVATE_KGAME) << "================= KMEssageServer ====================";
297  //d->mMessageServer=new KMessageServer(0,this);
298  //qCDebug(GAMES_PRIVATE_KGAME) << "================= KMEssageClient ====================";
299  //d->mMessageClient=new KMessageClient(this);
300  qCDebug(GAMES_PRIVATE_KGAME) << "================= KMEssageProcessIO ====================";
301  d->mProcessIO=new KMessageProcess(this,name);
302  qCDebug(GAMES_PRIVATE_KGAME) << "================= KMEssage Add client ====================";
303  //d->mMessageServer->addClient(d->mProcessIO);
304  //qCDebug(GAMES_PRIVATE_KGAME) << "================= KMEssage SetSErver ====================";
305  //d->mMessageClient->setServer(d->mMessageServer);
306  qCDebug(GAMES_PRIVATE_KGAME) << "================= KMEssage: Connect ====================";
307  //connect(d->mMessageClient, SIGNAL(broadcastReceived(QByteArray,quint32)),
308  // this, SLOT(clientMessage(QByteArray,quint32)));
309  //connect(d->mMessageClient, SIGNAL(forwardReceived(QByteArray,quint32,QValueList<quint32>)),
310  // this, SLOT(clientMessage(QByteArray,quint32,QValueList<quint32>)));
311  connect(d->mProcessIO, &KMessageProcess::received, this, &KGameProcessIO::receivedMessage);
312  // Relay signal
313  connect(d->mProcessIO, &KMessageProcess::signalReceivedStderr, this, &KGameProcessIO::signalReceivedStderr);
314  //qCDebug(GAMES_PRIVATE_KGAME) << "Our client is id="<<d->mMessageClient->id();
315 }
316 
318 {
319  Q_D(KGameProcessIO);
320 
321  qCDebug(GAMES_PRIVATE_KGAME) << ": this=" << this;
322  qCDebug(GAMES_PRIVATE_KGAME) << "player="<<player();
323  if (player())
324  {
325  player()->removeGameIO(this,false);
326  }
327  if (d->mProcessIO)
328  {
329  delete d->mProcessIO;
330  d->mProcessIO=nullptr;
331  }
332 }
333 
335 {
336  return ProcessIO;
337 }
338 
340 {
341  KGameIO::initIO(p);
342  // Send 'hello' to process
343  QByteArray buffer;
344  QDataStream stream(&buffer, QIODevice::WriteOnly);
345 
346  bool sendit=true;
347  if (p)
348  {
349  qint16 id = p->userId();
350  stream << id;
351  Q_EMIT signalIOAdded(this,stream,p,&sendit);
352  if (sendit )
353  {
354  quint32 sender = p->id();
355  qCDebug(GAMES_PRIVATE_KGAME) << "Sending IOAdded to process player !!!!!!!!!!!!!! ";
356  sendSystemMessage(stream, KGameMessage::IdIOAdded, 0, sender);
357  }
358  }
359 }
360 
362 {
363  if (!player())
364  {
365  qCWarning(GAMES_PRIVATE_KGAME) << ": player() is NULL";
366  return;
367  }
368  bool sendit=true;
369  QByteArray buffer;
370  QDataStream stream(&buffer,QIODevice::WriteOnly);
371  stream << (qint8)b;
372  Q_EMIT signalPrepareTurn(stream,b,this,&sendit);
373  if (sendit)
374  {
375  quint32 sender=player()->id();
376  qCDebug(GAMES_PRIVATE_KGAME) << "Sending Turn to process player !!!!!!!!!!!!!! ";
377  sendSystemMessage(stream, KGameMessage::IdTurn, 0, sender);
378  }
379 }
380 
381 void KGameProcessIO::sendSystemMessage(QDataStream &stream,int msgid, quint32 receiver, quint32 sender)
382 {
383  sendAllMessages(stream, msgid, receiver, sender, false);
384 }
385 
386 void KGameProcessIO::sendMessage(QDataStream &stream,int msgid, quint32 receiver, quint32 sender)
387 {
388  sendAllMessages(stream, msgid, receiver, sender, true);
389 }
390 
391 void KGameProcessIO::sendAllMessages(QDataStream &stream,int msgid, quint32 receiver, quint32 sender, bool usermsg)
392 {
393  Q_D(KGameProcessIO);
394 
395  qCDebug(GAMES_PRIVATE_KGAME) << "==============> KGameProcessIO::sendMessage (usermsg="<<usermsg<<")";
396  // if (!player()) return ;
397  //if (!player()->isActive()) return ;
398 
399  if (usermsg)
400  {
401  msgid+=KGameMessage::IdUser;
402  }
403 
404  qCDebug(GAMES_PRIVATE_KGAME) << "=============* ProcessIO (" << msgid << "," << receiver << "," << sender << ") ===========";
405 
406  QByteArray buffer;
407  QDataStream ostream(&buffer,QIODevice::WriteOnly);
408  QBuffer *device=(QBuffer *)stream.device();
409  QByteArray data=device->buffer();;
410 
411  KGameMessage::createHeader(ostream,sender,receiver,msgid);
412  // ostream.writeRawBytes(data.data()+device->at(),data.size()-device->at());
413  ostream.writeRawData(data.data(),data.size());
414  qCDebug(GAMES_PRIVATE_KGAME) << " Adding user data from pos="<< device->pos() <<" amount=" << data.size() << "byte";
415  //if (d->mMessageClient) d->mMessageClient->sendBroadcast(buffer);
416  if (d->mProcessIO)
417  {
418  d->mProcessIO->send(buffer);
419  }
420 }
421 
422 //void KGameProcessIO::clientMessage(const QByteArray& receiveBuffer, quint32 clientID, const QValueList <quint32> &recv)
423 void KGameProcessIO::receivedMessage(const QByteArray& receiveBuffer)
424 {
425  QDataStream stream(receiveBuffer);
426  int msgid;
427  quint32 sender;
428  quint32 receiver;
429  KGameMessage::extractHeader(stream,sender,receiver,msgid);
430 
431  qCDebug(GAMES_PRIVATE_KGAME) << "************* Got process message sender =" << sender
432  << "receiver=" << receiver << " msgid=" << msgid;
433 
434 
435  // Cut out the header part...to not confuse network code
436  QBuffer *buf=(QBuffer *)stream.device();
437  QByteArray newbuffer;
438  newbuffer = QByteArray::fromRawData(buf->buffer().data()+buf->pos(),buf->size()-buf->pos());
439  QDataStream ostream(newbuffer);
440  qCDebug(GAMES_PRIVATE_KGAME) << "Newbuffer size=" << newbuffer.size();
441 
442 // This is a dummy message which allows us the process to talk with its owner
443  if (msgid==KGameMessage::IdProcessQuery)
444  {
445  Q_EMIT signalProcessQuery(ostream,this);
446  }
447  else if (player())
448  {
449  sender = player()->id(); // force correct sender
450  if (msgid==KGameMessage::IdPlayerInput)
451  {
452  sendInput(ostream,true,sender);
453  }
454  else
455  {
456  player()->forwardMessage(ostream,msgid,receiver,sender);
457  }
458  }
459  else
460  {
461  qCDebug(GAMES_PRIVATE_KGAME) << ": Got message from process but no player defined!";
462  }
463  newbuffer.clear();
464 }
465 
466 
467 // ----------------------- Computer IO --------------------------
468 class KGameComputerIOPrivate : public KGameIOPrivate
469 {
470 //TODO: maybe these should be KGameProperties!!
471 public:
472  KGameComputerIOPrivate()
473  {
474  mAdvanceCounter = 0;
475  mReactionPeriod = 0;
476 
477  mPauseCounter = 0;
478 
479  mAdvanceTimer = nullptr;
480  }
481  int mAdvanceCounter;
482  int mReactionPeriod;
483 
484  int mPauseCounter;
485 
486  QTimer* mAdvanceTimer;
487 };
488 
490  : KGameIO(*new KGameComputerIOPrivate)
491 {
492 }
493 
495  : KGameIO(*new KGameComputerIOPrivate, p)
496 {
497 }
498 
499 KGameComputerIO::~KGameComputerIO()
500 {
501  Q_D(KGameComputerIO);
502 
503  if (d->mAdvanceTimer)
504  {
505  delete d->mAdvanceTimer;
506  }
507 }
508 
510 {
511  return ComputerIO;
512 }
513 
515 {
516  Q_D(KGameComputerIO);
517 
518  d->mReactionPeriod = calls;
519 }
520 
521 int KGameComputerIO::reactionPeriod() const
522 {
523  Q_D(const KGameComputerIO);
524 
525  return d->mReactionPeriod;
526 }
527 
529 {
530  Q_D(KGameComputerIO);
531 
532  stopAdvancePeriod();
533  d->mAdvanceTimer = new QTimer(this);
534  connect(d->mAdvanceTimer, &QTimer::timeout, this, &KGameComputerIO::advance);
535  d->mAdvanceTimer->start(ms);
536 }
537 
538 void KGameComputerIO::stopAdvancePeriod()
539 {
540  Q_D(KGameComputerIO);
541 
542  if (d->mAdvanceTimer)
543  {
544  d->mAdvanceTimer->stop();
545  delete d->mAdvanceTimer;
546  }
547 }
548 
549 void KGameComputerIO::pause(int calls)
550 {
551  Q_D(KGameComputerIO);
552 
553  d->mPauseCounter = calls;
554 }
555 
557 {
558  pause(0);
559 }
560 
562 {
563  Q_D(KGameComputerIO);
564 
565  if (d->mPauseCounter > 0)
566  {
567  d->mPauseCounter--;
568  return;
569  }
570  else if (d->mPauseCounter < 0)
571  {
572  return;
573  }
574  d->mAdvanceCounter++;
575  if (d->mAdvanceCounter >= d->mReactionPeriod)
576  {
577  d->mAdvanceCounter = 0;
578  reaction();
579  }
580 }
581 
583 {
585 }
586 
587 
void signalKeyEvent(KGameIO *io, QDataStream &stream, QKeyEvent *m, bool *eatevent)
Signal handler for keyboard events.
void signalProcessQuery(QDataStream &stream, KGameProcessIO *me)
A computer query message is received.
QEvent::Type type() const const
quint32 id() const
Returns the id of the player.
Definition: kplayer.cpp:235
void clear()
virtual qint64 size() const const override
KGame * game() const
Equivalent to player()->game()
Definition: kgameio.cpp:105
virtual void notifyTurn(bool b)
Notifies the IO device that the player&#39;s setTurn had been called Called by KPlayer.
Definition: kgameio.cpp:85
QObject * sender() const const
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
int rtti() const override
The identification of the IO.
Definition: kgameio.cpp:334
QByteArray fromRawData(const char *data, int size)
void sendSystemMessage(QDataStream &stream, int msgid, quint32 receiver, quint32 sender)
Send a system message to the process.
Definition: kgameio.cpp:381
The KGameProcessIO class.
Definition: kgameio.h:360
QByteArray & buffer()
void setAdvancePeriod(int ms)
Start a QTimer which calls advance every ms milli seconds.
Definition: kgameio.cpp:528
void sendMessage(QDataStream &stream, int msgid, quint32 receiver, quint32 sender)
Send a message to the process.
Definition: kgameio.cpp:386
bool eventFilter(QObject *o, QEvent *e) override
Internal event filter.
Definition: kgameio.cpp:234
KGameMouseIO(QWidget *parent, bool trackmouse=false)
Creates a mouse IO device.
Definition: kgameio.cpp:191
~KGameProcessIO() override
Deletes the process input devices.
Definition: kgameio.cpp:317
void setPlayer(KPlayer *p)
Sets the player to which this IO belongs to.
Definition: kgameio.cpp:75
void timeout()
bool removeGameIO(KGameIO *input=nullptr, bool deleteit=true)
remove (and delete) a game IO device
Definition: kplayer.cpp:271
bool eventFilter(QObject *o, QEvent *e) override
Internal method to process the events.
Definition: kgameio.cpp:157
void signalReaction()
This signal is emitted when your computer player is meant to do something, or better is meant to be a...
void initIO(KPlayer *p) override
Init this device by setting the player and e.g.
Definition: kgameio.cpp:339
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 installEventFilter(QObject *filterObj)
bool addGameIO(KGameIO *input)
Adds an IO device for the player.
Definition: kplayer.cpp:259
int rtti() const override
Run time identification.
Definition: kgameio.cpp:509
virtual bool eventFilter(QObject *watched, QEvent *event)
virtual void initIO(KPlayer *p)
Init this device by setting the player and e.g.
Definition: kgameio.cpp:80
virtual qint64 pos() const const override
Base class for a game player.
Definition: kplayer.h:60
KGameProcessIO(const QString &name)
Creates a computer player via a separate process.
Definition: kgameio.cpp:289
void setMouseTracking(bool b)
Manually activate or deactivate mouse tracking.
Definition: kgameio.cpp:226
void signalReceivedStderr(const QString &msg)
Text is received by the process on STDERR.
int rtti() const override
The identification of the IO.
Definition: kgameio.cpp:221
int rtti() const override
The identification of the IO.
Definition: kgameio.cpp:155
KGameIO()
Constructs a KGameIO object.
Definition: kgameio.cpp:40
The main KDE game object.
Definition: kgame.h:57
void signalPrepareTurn(QDataStream &stream, bool turn, KGameIO *io, bool *send)
Signal generated when KPlayer::myTurn changes.
virtual void advance()
Works kind of similar to QCanvas::advance.
Definition: kgameio.cpp:561
KGameIO variant for real-time games.
Definition: kgameio.h:524
void signalIOAdded(KGameIO *game, QDataStream &stream, KPlayer *p, bool *send)
Signal generated when the computer player is added.
bool sendInput(QDataStream &stream, bool transmit=true, quint32 sender=0)
Send an input message using KPlayer::forwardInput.
Definition: kgameio.cpp:114
int writeRawData(const char *s, int len)
void notifyTurn(bool turn) override
Notifies the IO device that the player&#39;s setTurn had been called Called by KPlayer.
Definition: kgameio.cpp:361
void pause(int calls=-1)
Ignore calls number of advance calls.
Definition: kgameio.cpp:549
void setMouseTracking(bool enable)
char * data()
virtual bool forwardInput(QDataStream &msg, bool transmit=true, quint32 sender=0)
Forwards input to the game object..internal use only.
Definition: kplayer.cpp:182
virtual int rtti() const =0
Run time identification.
Base class for IO devices for games.
Definition: kgameio.h:56
QIODevice * device() const const
void signalMouseEvent(KGameIO *io, QDataStream &stream, QMouseEvent *m, bool *eatevent)
Signal handler for mouse events.
void sendAllMessages(QDataStream &stream, int msgid, quint32 receiver, quint32 sender, bool usermsg)
Internal combined function for all message handling.
Definition: kgameio.cpp:391
KPlayer * player() const
This function returns the player who owns this IO.
Definition: kgameio.cpp:70
virtual void reaction()
Default implementation simply emits signalReaction.
Definition: kgameio.cpp:582
void unpause()
Equivalent to pause(0).
Definition: kgameio.cpp:556
void receivedMessage(const QByteArray &receiveBuffer)
Internal message handler to receive data from the process.
Definition: kgameio.cpp:423
int size() const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
KGameComputerIO()
Creates a LOCAL computer player.
Definition: kgameio.cpp:489
void setReactionPeriod(int advanceCalls)
The number of advance calls until the player (or rather: the IO) does something (default: 1)...
Definition: kgameio.cpp:514
KGameKeyIO(QWidget *parent)
Create a keyboard input devices.
Definition: kgameio.cpp:137
void removeEventFilter(QObject *obj)
Q_EMITQ_EMIT
void Debug()
Gives debug output of the game status.
Definition: kgameio.cpp:123
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Dec 7 2021 22:34:14 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.