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

KDE's Doxygen guidelines are available online.