KDEGames

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

KDE's Doxygen guidelines are available online.