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

KDE's Doxygen guidelines are available online.