• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • libtdegames
 

libtdegames

  • libtdegames
  • kgame
kgame.cpp
1/*
2 This file is part of the TDE games library
3 Copyright (C) 2001 Martin Heni (martin@heni-online.de)
4 Copyright (C) 2001 Andreas Beckermann (b_mann@gmx.de)
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 $Id$
22*/
23
24#include "kgame.h"
25#include "kgame.moc"
26#include "kgamepropertyhandler.h"
27#include "kgameproperty.h"
28#include "kplayer.h"
29#include "kgameio.h"
30#include "kgameerror.h"
31#include "kgamesequence.h"
32
33#include "kgamemessage.h"
34
35#include <unistd.h>
36#include <stdio.h>
37#include <assert.h>
38
39#include <tqbuffer.h>
40#include <tqtimer.h>
41#include <tqptrqueue.h>
42#include <tqfile.h>
43
44#include <tdelocale.h>
45#include <krandomsequence.h>
46#include <kdebug.h>
47
48#define KGAME_LOAD_COOKIE 4210
49
50// try to place as much as possible here
51// many things are *not* possible here as KGame has to use some inline function
52class KGamePrivate
53{
54public:
55 KGamePrivate()
56 {
57 mUniquePlayerNumber = 0;
58 mPolicy=KGame::PolicyLocal;
59 mGameSequence = 0;
60 }
61
62 int mUniquePlayerNumber;
63 TQPtrQueue<KPlayer> mAddPlayerList;// this is a list of to-be-added players. See addPlayer() docu
64 KRandomSequence* mRandom;
65 KGame::GamePolicy mPolicy;
66 KGameSequence* mGameSequence;
67
68
69 KGamePropertyHandler* mProperties;
70
71 // player lists
72 KGame::KGamePlayerList mPlayerList;
73 KGame::KGamePlayerList mInactivePlayerList;
74
75 //KGamePropertys
76 KGamePropertyInt mMaxPlayer;
77 KGamePropertyUInt mMinPlayer;
78 KGamePropertyInt mGameStatus; // Game running?
79 TQValueList<int> mInactiveIdList;
80
81};
82
83// ------------------- GAME CLASS --------------------------
84KGame::KGame(int cookie,TQObject* parent) : KGameNetwork(cookie,parent)
85{
86 kdDebug(11001) << k_funcinfo << " - " << this << ", sizeof(KGame)=" << sizeof(KGame) << endl;
87 d = new KGamePrivate;
88
89 d->mProperties = new KGamePropertyHandler(this);
90
91 d->mProperties->registerHandler(KGameMessage::IdGameProperty,
92 this,TQ_SLOT(sendProperty(int, TQDataStream&, bool* )),
93 TQ_SLOT(emitSignal(KGamePropertyBase *)));
94 d->mMaxPlayer.registerData(KGamePropertyBase::IdMaxPlayer, this, i18n("MaxPlayers"));
95 d->mMaxPlayer.setLocal(-1); // Infinite
96 d->mMinPlayer.registerData(KGamePropertyBase::IdMinPlayer, this, i18n("MinPlayers"));
97 d->mMinPlayer.setLocal(0); // Always ok
98 d->mGameStatus.registerData(KGamePropertyBase::IdGameStatus, this, i18n("GameStatus"));
99 d->mGameStatus.setLocal(Init);
100 // d->mUniquePlayerNumber = 0;
101 d->mRandom = new KRandomSequence;
102 d->mRandom->setSeed(0);
103
104 connect(this, TQ_SIGNAL(signalClientConnected(TQ_UINT32)),
105 this, TQ_SLOT(slotClientConnected(TQ_UINT32)));
106 connect(this, TQ_SIGNAL(signalClientDisconnected(TQ_UINT32,bool)),
107 this, TQ_SLOT(slotClientDisconnected(TQ_UINT32,bool)));
108 connect(this, TQ_SIGNAL(signalConnectionBroken()),
109 this, TQ_SLOT(slotServerDisconnected()));
110
111 setGameSequence(new KGameSequence());
112
113 // BL: FIXME This signal does no longer exist. When we are merging
114 // MH: super....and how do I find out about the lost conenction now?
115 // KGame and KGameNetwork, this could be improved!
116// connect(this,TQ_SIGNAL(signalConnectionLost(KGameClient *)),
117// this,TQ_SLOT(slotConnectionLost(KGameClient *)));
118}
119
120KGame::~KGame()
121{
122 kdDebug(11001) << k_funcinfo << endl;
123// Debug();
124 reset();
125 delete d->mGameSequence;
126 delete d->mRandom;
127 delete d;
128 kdDebug(11001) << k_funcinfo << " done" << endl;
129}
130
131bool KGame::reset()
132{
133 deletePlayers();
134 deleteInactivePlayers();
135 return true;
136}
137
138void KGame::deletePlayers()
139{
140// kdDebug(11001) << k_funcinfo << endl;
141 KGamePlayerList tmp = d->mPlayerList; // in case of PolicyClean player=d->mPlayerList.first() is infinite
142 KPlayer *player;
143 while((player=tmp.first()))
144 {
145 delete player; // delete and removes the player
146 tmp.removeFirst();
147 }
148// kdDebug(11001) << k_funcinfo << " done" << endl;
149}
150
151void KGame::deleteInactivePlayers()
152{
153 KPlayer *player;
154 while((player=d->mInactivePlayerList.first()))
155 {
156 //player->setGame(0); // prevent call backs
157 d->mInactivePlayerList.remove(player);
158 delete player;
159 }
160}
161
162bool KGame::load(TQString filename,bool reset)
163{
164 if (filename.isNull())
165 {
166 return false;
167 }
168 TQFile f(filename);
169 if (!f.open(IO_ReadOnly))
170 {
171 return false;
172 }
173 TQDataStream s( &f );
174 load(s,reset);
175 f.close();
176 return true;
177}
178
179bool KGame::load(TQDataStream &stream,bool reset)
180{ return loadgame(stream, false,reset); }
181
182bool KGame::loadgame(TQDataStream &stream, bool network,bool resetgame)
183{
184 // Load Game Data
185
186 // internal data
187 TQ_INT32 c;
188 stream >> c; // cookie
189
190 if (c!=cookie())
191 {
192 kdWarning(11001) << "Trying to load different game version we="<<cookie() << " saved=" << c << endl;
193 bool result=false;
194 emit signalLoadError(stream,network,(int)c,result);
195 return result;
196 }
197 if (resetgame) reset();
198
199 uint i;
200 stream >> i;
201// setPolicy((GamePolicy)i);
202
203 stream >> d->mUniquePlayerNumber;
204
205 if (gameSequence())
206 {
207 gameSequence()->setCurrentPlayer(0); // TODO !!!
208 }
209 int newseed;
210 stream >> newseed;
211 d->mRandom->setSeed(newseed);
212
213 // Switch off the direct emitting of signals while
214 // loading properties. This can cause inconsistencies
215 // otherwise if a property emits and this emit accesses
216 // a property not yet loaded
217 // Note we habe to have this external locking to prevent the games unlocking
218 // to access the players
219 dataHandler()->lockDirectEmit();
220 KPlayer *player;
221 for ( player=playerList()->first(); player != 0; player=playerList()->next() )
222 {
223 player->dataHandler()->lockDirectEmit();
224 // kdDebug(11001) << "Player "<<player->id() << " to indirect emit" <<endl;
225 }
226
227 // Properties
228 dataHandler()->load(stream);
229
230 // If there is additional data to be loaded before players are loaded then do
231 // this here.
232 emit signalLoadPrePlayers(stream);
233
234 // Load Playerobjects
235 uint playercount;
236 stream >> playercount;
237 kdDebug(11001) << "Loading KGame " << playercount << " KPlayer objects " << endl;
238 for (i=0;i<playercount;i++)
239 {
240 KPlayer *newplayer=loadPlayer(stream,network);
241 systemAddPlayer(newplayer);
242 }
243
244 TQ_INT16 cookie;
245 stream >> cookie;
246 if (cookie==KGAME_LOAD_COOKIE) {
247 kdDebug(11001) << " Game loaded propertly"<<endl;
248 } else {
249 kdError(11001) << " Game loading error. probably format error"<<endl;
250 }
251
252 // Switch back on the direct emitting of signals and emit the
253 // queued signals.
254 // Note we habe to have this external locking to prevent the games unlocking
255 // to access the players
256 dataHandler()->unlockDirectEmit();
257 for ( player=playerList()->first(); player != 0; player=playerList()->next() )
258 {
259 player->dataHandler()->unlockDirectEmit();
260 // kdDebug(11001) << "Player "<<player->id() << " to direct emit" <<endl;
261 }
262
263 emit signalLoad(stream);
264 return true;
265}
266
267bool KGame::save(TQString filename,bool saveplayers)
268{
269 if (filename.isNull())
270 {
271 return false;
272 }
273 TQFile f(filename);
274 if (!f.open(IO_WriteOnly))
275 {
276 return false;
277 }
278 TQDataStream s( &f );
279 save(s,saveplayers);
280 f.close();
281 return true;
282}
283
284bool KGame::save(TQDataStream &stream,bool saveplayers)
285{ return savegame(stream, false,saveplayers); }
286
287bool KGame::savegame(TQDataStream &stream,bool /*network*/,bool saveplayers)
288{
289 // Save Game Data
290
291 // internal variables
292 TQ_INT32 c=cookie();
293 stream << c;
294
295 uint p=(uint)policy();
296 stream << p;
297 stream << d->mUniquePlayerNumber;
298 int newseed=(int)d->mRandom->getLong(65535);
299 stream << newseed;
300 d->mRandom->setSeed(newseed);
301
302 // Properties
303 dataHandler()->save(stream);
304
305 // Save all data that need to be saved *before* the players are saved
306 emit signalSavePrePlayers(stream);
307
308 if (saveplayers)
309 {
310 savePlayers(stream,playerList());
311 }
312 else
313 {
314 stream << (uint)0; // no players saved
315 }
316
317 stream << (TQ_INT16)KGAME_LOAD_COOKIE;
318
319 emit signalSave(stream);
320 return true;
321}
322
323void KGame::savePlayer(TQDataStream &stream,KPlayer* p)
324{
325// this could be in KGameMessage as well
326 stream << (TQ_INT32)p->rtti();
327 stream << (TQ_INT32)p->id();
328 stream << (TQ_INT32)p->calcIOValue();
329 p->save(stream);
330}
331
332void KGame::savePlayers(TQDataStream &stream, KGamePlayerList *list)
333{
334 if (!list)
335 {
336 list=playerList();
337 }
338
339 TQ_INT32 cnt=list->count();
340 kdDebug(11001) << "Saving KGame " << cnt << " KPlayer objects " << endl;
341 stream << cnt;
342 KPlayer *player;
343 for ( player=list->first(); player != 0; player=list->next() )
344 {
345 savePlayer(stream,player);
346 }
347}
348
349KPlayer *KGame::createPlayer(int /*rtti*/,int /*io*/,bool /*isvirtual*/)
350{
351 kdWarning(11001) << " No user defined player created. Creating default KPlayer. This crashes if you have overwritten KPlayer!!!! " << endl;
352 return new KPlayer;
353}
354KPlayer *KGame::loadPlayer(TQDataStream& stream,bool isvirtual)
355{
356 TQ_INT32 rtti,id,iovalue;
357 stream >> rtti >> id >> iovalue;
358 KPlayer *newplayer=findPlayer(id);
359 if (!newplayer)
360 {
361 kdDebug(11001) << k_funcinfo << "Player "<< id << " not found...asking user to create one " << endl;
362 newplayer=createPlayer(rtti,iovalue,isvirtual);
363 //emit signalCreatePlayer(newplayer,rtti,iovalue,isvirtual,this);
364 }
365 /*
366 if (!newplayer)
367 {
368 kdWarning(11001) << " No user defined player created. Creating default KPlayer. This crashes if you have overwritten KPlayer!!!! " << endl;
369 newplayer=new KPlayer;
370 }
371 else
372 {
373 kdDebug(11001) << " USER Player " << newplayer << " done player->rtti=" << newplayer->rtti() << " rtti=" << rtti << endl;
374 }
375 */
376 newplayer->load(stream);
377 if (isvirtual)
378 {
379 newplayer->setVirtual(true);
380 }
381 return newplayer;
382}
383
384// ----------------- Player handling -----------------------
385
386KPlayer * KGame::findPlayer(TQ_UINT32 id) const
387{
388 for (TQPtrListIterator<KPlayer> it(d->mPlayerList); it.current(); ++it)
389 {
390 if (it.current()->id() == id)
391 {
392 return it.current();
393 }
394 }
395 for (TQPtrListIterator<KPlayer> it(d->mInactivePlayerList); it.current(); ++it)
396 {
397 if (it.current()->id() == id)
398 {
399 return it.current();
400 }
401 }
402 return 0;
403}
404
405// it is necessary that addPlayer and systemAddPlayer are called in the same
406// order. Ie if addPlayer(foo) followed by addPlayer(bar) is called, you must
407// not call systemAddPlayer(bar) followed by systemAddPlayer(foo), as the
408// mAddPlayerList would get confused. Should be no problem as long as comServer
409// and the clients are working correctly.
410// BUT: if addPlayer(foo) does not arrive by any reason while addPlayer(bar)
411// does, we would be in trouble...
412void KGame::addPlayer(KPlayer* newplayer)
413{
414 kdDebug(11001) << k_funcinfo << ": " << "; maxPlayers=" << maxPlayers() << " playerCount=" << playerCount() << endl;
415 if (!newplayer)
416 {
417 kdFatal(11001) << "trying to add NULL player in KGame::addPlayer()" << endl;
418 return ;
419 }
420
421 if (maxPlayers() >= 0 && (int)playerCount() >= maxPlayers())
422 {
423 kdWarning(11001) << "cannot add more than " << maxPlayers() << " players - deleting..." << endl;
424 delete newplayer;
425 return;
426 }
427
428 if (newplayer->id() == 0)
429 {
430 d->mUniquePlayerNumber++;
431 newplayer->setId(KGameMessage::createPlayerId(d->mUniquePlayerNumber, gameId()));
432 kdDebug(11001) << k_funcinfo << "NEW!!! player " << newplayer << " now has id " << newplayer->id() << endl;
433 }
434 else
435 {
436 // this could happen in games which use their own ID management by certain
437 // reasons. that is NOT recommended
438 kdDebug(11001) << k_funcinfo << "player " << newplayer << " already has an id: " << newplayer->id() << endl;
439 }
440
441 TQByteArray buffer;
442 TQDataStream stream(buffer,IO_WriteOnly);
443 // We distinguis here what policy we have
444 if (policy()==PolicyLocal || policy()==PolicyDirty)
445 {
446 systemAddPlayer(newplayer);
447 }
448 if (policy()==PolicyClean || policy()==PolicyDirty)
449 {
450 savePlayer(stream,newplayer);
451 // Store the player for delayed clean adding
452 if (policy()==PolicyClean)
453 {
454 d->mAddPlayerList.enqueue(newplayer);
455 }
456 sendSystemMessage(stream,(int)KGameMessage::IdAddPlayer, 0);
457 }
458}
459
460void KGame::systemAddPlayer(KPlayer* newplayer)
461{
462 if (!newplayer)
463 {
464 kdFatal(11001) << "trying to add NULL player in KGame::systemAddPlayer()" << endl;
465 return ;
466 }
467 if (newplayer->id() == 0)
468 {
469 kdWarning(11001) << k_funcinfo << "player " << newplayer << " has no ID" << endl;
470 }
471
472 if (findPlayer(newplayer->id()))
473 {
474 kdError(11001) << "ERROR: Double adding player !!!!! NOT GOOD !!!!!! " << newplayer->id() << "...I delete it again" << endl;
475 delete newplayer;
476 }
477 else
478 {
479 kdDebug(11001) << "Trying to add player " << newplayer <<" maxPlayers="<<maxPlayers()<<" playerCount="<<playerCount() << endl;
480 // Add the player to the game
481 d->mPlayerList.append(newplayer);
482 newplayer->setGame(this);
483 kdDebug(11001) << "Player: isVirtual=" << newplayer->isVirtual() << endl;
484 kdDebug(11001) << " id=" << newplayer->id() << " #Players="
485 << d->mPlayerList.count() << " added " << newplayer
486 << " (virtual=" << newplayer->isVirtual() << ")" << endl;
487 emit signalPlayerJoinedGame(newplayer);
488 }
489}
490
491// Called by the KPlayer destructor
492void KGame::playerDeleted(KPlayer *player)
493{
494 kdDebug(11001) << k_funcinfo << ": id (" << player->id() << ") to be removed " << player << endl;
495
496 if (policy()==PolicyLocal || policy()==PolicyDirty)
497 {
498 systemRemovePlayer(player,false);
499 }
500 if (policy()==PolicyClean || policy()==PolicyDirty)
501 {
502 if (!player->isVirtual())
503 {
504 kdDebug(11001) << k_funcinfo << ": sending IdRemovePlayer "<<player->id() << endl;
505 sendSystemMessage(player->id(), KGameMessage::IdRemovePlayer, 0);
506 }
507 }
508}
509
510bool KGame::removePlayer(KPlayer * player, TQ_UINT32 receiver)
511{//transmit to all clients, or to receiver only
512 if (!player)
513 {
514 kdFatal(11001) << "trying to remove NULL player in KGame::removePlayer()" << endl;
515 return false;
516 }
517 kdDebug(11001) << k_funcinfo << ": id (" << player->id() << ") to be removed " << player << endl;
518
519 if (policy()==PolicyLocal || policy()==PolicyDirty)
520 {
521 systemRemovePlayer(player,true);
522 }
523 if (policy()==PolicyClean || policy()==PolicyDirty)
524 {
525 kdDebug(11001) << k_funcinfo << ": sending IdRemovePlayer "<<player->id() << endl;
526 sendSystemMessage(player->id(),KGameMessage::IdRemovePlayer, receiver);
527 }
528 return true;
529 // we will receive the message in networkTransmission()
530}
531
532void KGame::systemRemovePlayer(KPlayer* player,bool deleteit)
533{
534 kdDebug(11001) << k_funcinfo << endl;
535 if (!player)
536 {
537 kdWarning(11001) << "cannot remove NULL player" << endl;
538 return;
539 }
540 if (!systemRemove(player,deleteit))
541 {
542 kdWarning(11001) << "player " << player << "(" << player->id() << ") Could not be found!" << endl;
543 }
544
545 if (gameStatus()==(int)Run && playerCount()<minPlayers())
546 {
547 kdWarning(11001) << k_funcinfo ": not enough players, PAUSING game\n" << endl;
548 setGameStatus(Pause);
549 }
550}
551
552bool KGame::systemRemove(KPlayer* p,bool deleteit)
553{
554 if (!p)
555 {
556 kdWarning(11001) << "cannot remove NULL player" << endl;
557 return false;
558 }
559 bool result;
560 kdDebug(11001) << k_funcinfo << ": Player (" << p->id() << ") to be removed " << p << endl;
561
562 if (d->mPlayerList.count() == 0)
563 {
564 result = false;
565 }
566 else
567 {
568 result = d->mPlayerList.remove(p);
569 }
570
571 emit signalPlayerLeftGame(p);
572
573 p->setGame(0);
574 if (deleteit)
575 {
576 delete p;
577 }
578
579 return result;
580}
581
582bool KGame::inactivatePlayer(KPlayer* player)
583{
584 if (!player)
585 {
586 return false;
587 }
588 kdDebug(11001) << "Inactivate player " << player->id() << endl;
589
590 if (policy()==PolicyLocal || policy()==PolicyDirty)
591 {
592 systemInactivatePlayer(player);
593 }
594 if (policy()==PolicyClean || policy()==PolicyDirty)
595 {
596 sendSystemMessage(player->id(), KGameMessage::IdInactivatePlayer);
597 }
598
599 return true;
600}
601
602bool KGame::systemInactivatePlayer(KPlayer* player)
603{
604 if (!player || !player->isActive())
605 {
606 return false;
607 }
608 kdDebug(11001) << " Inactivate player " << player->id() << endl;
609
610 int pid=player->id();
611 // Virtual players cannot be deactivated. They will be removed
612 if (player->isVirtual())
613 {
614 systemRemovePlayer(player,true);
615 }
616 else
617 {
618 d->mPlayerList.remove(player);
619 d->mInactivePlayerList.prepend(player);
620 player->setActive(false);
621 }
622 emit signalPlayerLeftGame(player);
623 if (isAdmin())
624 {
625 d->mInactiveIdList.prepend(pid);
626 }
627 return true;
628}
629
630bool KGame::activatePlayer(KPlayer * player)
631{
632 if (!player)
633 {
634 return false;
635 }
636 kdDebug(11001) << k_funcinfo << ": activate " << player->id() << endl;
637 if (policy()==PolicyLocal || policy()==PolicyDirty)
638 {
639 systemActivatePlayer(player);
640 }
641 if (policy()==PolicyClean || policy()==PolicyDirty)
642 {
643 sendSystemMessage(player->id(), KGameMessage::IdActivatePlayer);
644 }
645 return true;
646}
647
648bool KGame::systemActivatePlayer(KPlayer* player)
649{
650 if (!player || player->isActive())
651 {
652 return false;
653 }
654 kdDebug(11001) << k_funcinfo << ": activate " << player->id() << endl;
655
656 d->mInactivePlayerList.remove(player);
657 player->setActive(true);
658 addPlayer(player);
659 if (isAdmin())
660 {
661 d->mInactiveIdList.remove(player->id());
662 }
663 return true;
664}
665
666// -------------------- Properties ---------------------------
667
668void KGame::setMaxPlayers(uint maxnumber)
669{ if (isAdmin()) { d->mMaxPlayer.changeValue(maxnumber); } }
670
671void KGame::setMinPlayers(uint minnumber)
672{ if (isAdmin()) { d->mMinPlayer.changeValue(minnumber); } }
673
674uint KGame::minPlayers() const
675{ return d->mMinPlayer.value(); }
676
677int KGame::maxPlayers() const
678{ return d->mMaxPlayer.value(); }
679
680uint KGame::playerCount() const
681{ return d->mPlayerList.count(); }
682
683int KGame::gameStatus() const
684{ return d->mGameStatus.value(); }
685
686bool KGame::isRunning() const
687{ return d->mGameStatus.value() == Run; }
688
689KGamePropertyHandler* KGame::dataHandler() const
690{ return d->mProperties; }
691
692
693KGame::KGamePlayerList* KGame::inactivePlayerList()
694{ return &d->mInactivePlayerList; }
695
696const KGame::KGamePlayerList* KGame::inactivePlayerList() const
697{ return &d->mInactivePlayerList; }
698
699KGame::KGamePlayerList* KGame::playerList()
700{ return &d->mPlayerList; }
701
702const KGame::KGamePlayerList* KGame::playerList() const
703{ return &d->mPlayerList; }
704
705KRandomSequence* KGame::random() const
706{ return d->mRandom; }
707
708
709bool KGame::sendPlayerInput(TQDataStream &msg, KPlayer *player, TQ_UINT32 sender)
710{
711 if (!player)
712 {
713 kdError(11001) << k_funcinfo << ": NULL player" << endl;
714 return false;
715 }
716 if (!isRunning())
717 {
718 kdError(11001) << k_funcinfo << ": game not running" << endl;
719 return false;
720 }
721
722 kdDebug(11001) << k_funcinfo << ": transmitting playerInput over network" << endl;
723 sendSystemMessage(msg, (int)KGameMessage::IdPlayerInput, player->id(), sender);
724 return true;
725}
726
727bool KGame::systemPlayerInput(TQDataStream &msg, KPlayer *player, TQ_UINT32 sender)
728{
729 if (!player)
730 {
731 kdError(11001) << k_funcinfo << ": NULL player" << endl;
732 return false;
733 }
734 if (!isRunning())
735 {
736 kdError(11001) << k_funcinfo << ": game not running" << endl;
737 return false;
738 }
739 kdDebug(11001) << "KGame: Got playerInput from messageServer... sender: " << sender << endl;
740 if (playerInput(msg,player))
741 {
742 playerInputFinished(player);
743 }
744 else
745 {
746 kdDebug(11001) << k_funcinfo<<": switching off player input"<<endl;
747 // TODO: (MH 03-2003): We need an return option from playerInput so that
748 // the player's is not automatically disabled here
749 if (!player->asyncInput())
750 {
751 player->setTurn(false); // in turn based games we have to switch off input now
752 }
753 }
754 return true;
755}
756
757
758KPlayer * KGame::playerInputFinished(KPlayer *player)
759{
760 kdDebug(11001) << k_funcinfo<<"player input finished for "<<player->id()<<endl;
761 // Check for game over and if not allow the next player to move
762 int gameOver = 0;
763 if (gameSequence())
764 {
765 gameSequence()->setCurrentPlayer(player);
766 }
767 // do not call gameSequence()->checkGameOver() to keep backward compatibility!
768 gameOver = checkGameOver(player);
769 if (gameOver!=0)
770 {
771 if (player)
772 {
773 player->setTurn(false);
774 }
775 setGameStatus(End);
776 emit signalGameOver(gameOver,player,this);
777 }
778 else if (!player->asyncInput())
779 {
780 player->setTurn(false); // in turn based games we have to switch off input now
781 if (gameSequence())
782 {
783 TQTimer::singleShot(0,this,TQ_SLOT(prepareNext()));
784 }
785 }
786 return player;
787}
788
789// Per default we do not do anything
790int KGame::checkGameOver(KPlayer *player)
791{
792 if (gameSequence())
793 {
794 return gameSequence()->checkGameOver(player);
795 }
796 return 0;
797}
798
799void KGame::setGameSequence(KGameSequence* sequence)
800{
801 delete d->mGameSequence;
802 d->mGameSequence = sequence;
803 if (d->mGameSequence)
804 {
805 d->mGameSequence->setGame(this);
806 }
807}
808
809KGameSequence* KGame::gameSequence() const
810{
811 return d->mGameSequence;
812}
813
814void KGame::prepareNext()
815{
816 if (gameSequence())
817 {
818 // we don't call gameSequence->nextPlayer() to keep old code working
819 nextPlayer(gameSequence()->currentPlayer());
820 }
821}
822
823KPlayer *KGame::nextPlayer(KPlayer *last,bool exclusive)
824{
825 if (gameSequence())
826 {
827 return gameSequence()->nextPlayer(last, exclusive);
828 }
829 return 0;
830}
831
832void KGame::setGameStatus(int status)
833{
834 kdDebug(11001) << k_funcinfo << ": GAMESTATUS CHANGED to" << status << endl;
835 if (status==(int)Run && playerCount()<minPlayers())
836 {
837 kdDebug(11001) << k_funcinfo << ": not enough players, pausing game\n" << endl;
838 status=Pause;
839 }
840 d->mGameStatus = status;
841}
842
843void KGame::networkTransmission(TQDataStream &stream, int msgid, TQ_UINT32 receiver, TQ_UINT32 sender, TQ_UINT32 /*clientID*/)
844{//clientID is unused
845 // message targets a playerobject. If we find it we forward the message to the
846 // player. Otherwise we proceed here and hope the best that the user processes
847 // the message
848
849// kdDebug(11001) << k_funcinfo << ": we="<<(int)gameId()<<" id="<<msgid<<" recv=" << receiver << " sender=" << sender << endl;
850
851
852 // *first* notice the game that something has changed - so no return prevents
853 // this
854 emit signalMessageUpdate(msgid, receiver, sender);
855 if (KGameMessage::isPlayer(receiver))
856 {
857 //kdDebug(11001) << "message id " << msgid << " seems to be for a player ("<<active=p->isActive()<<" recv="<< receiver << endl;
858 KPlayer *p=findPlayer(receiver);
859 if (p && p->isActive())
860 {
861 p->networkTransmission(stream,msgid,sender);
862 return;
863 }
864 if (p)
865 {
866 kdDebug(11001) << "player is here but not active" << endl;
867 }
868 else
869 {
870 kdDebug(11001) << "no player found" << endl;
871 }
872 }
873 // If it is not for a player it is meant for us!!!! Otherwise the
874 // gamenetwork would not have passed the message to us!
875
876 // GameProperties processed
877 if (d->mProperties->processMessage(stream, msgid, sender == gameId()))
878 {
879// kdDebug(11001 ) << "KGame: message taken by property - returning" << endl;
880 return ;
881 }
882
883 switch(msgid)
884 {
885 case KGameMessage::IdSetupGame: // Client: First step in setup game
886 {
887 TQ_INT16 v;
888 TQ_INT32 c;
889 stream >> v >> c;
890 kdDebug(11001) << " ===================> (Client) " << k_funcinfo << ": Got IdSetupGame ================== " << endl;
891 kdDebug(11001) << "our game id is " << gameId() << " Lib version=" << v << " App Cookie=" << c << endl;
892 // Verify identity of the network partners
893 if (c!=cookie())
894 {
895 kdError(11001) << "IdGameSetup: Negotiate Game: cookie mismatch I'am="<<cookie()<<" master="<<c<<endl;
896 sendError(KGameError::Cookie, KGameError::errCookie(cookie(), c));
897 disconnect(); // disconnect from master
898 }
899 else if (v!=KGameMessage::version())
900 {
901 sendError(KGameError::Version, KGameError::errVersion(v));
902 disconnect(); // disconnect from master
903 }
904 else
905 {
906 setupGame(sender);
907 }
908 kdDebug(11001) << "========== (Client) Setup game done\n";
909 }
910 break;
911 case KGameMessage::IdSetupGameContinue: // Master: second step in game setup
912 {
913 kdDebug(11001) << "=====>(Master) " << k_funcinfo << " - IdSetupGameContinue" << endl;
914 setupGameContinue(stream, sender);
915 }
916 break;
917 case KGameMessage::IdActivatePlayer: // Activate Player
918 {
919 int id;
920 stream >> id;
921 kdDebug(11001) << "Got IdActivatePlayer id=" << id << endl;
922 if (sender!=gameId() || policy()!=PolicyDirty)
923 {
924 systemActivatePlayer(findPlayer(id));
925 }
926 }
927 break;
928 case KGameMessage::IdInactivatePlayer: // Inactivate Player
929 {
930 int id;
931 stream >> id;
932 kdDebug(11001) << "Got IdInactivatePlayer id=" << id << endl;
933 if (sender!=gameId() || policy()!=PolicyDirty)
934 {
935 systemInactivatePlayer(findPlayer(id));
936 }
937 }
938 break;
939 case KGameMessage::IdAddPlayer:
940 {
941 kdDebug(11001) << k_funcinfo << ": Got IdAddPlayer" << endl;
942 if (sender!=gameId() || policy()!=PolicyDirty)
943 {
944 KPlayer *newplayer=0;
945 // We sent the message so the player is already available
946 if (sender==gameId())
947 {
948 kdDebug(11001) << "dequeue previously added player" << endl;
949 newplayer = d->mAddPlayerList.dequeue();
950 }
951 else
952 {
953 newplayer=loadPlayer(stream,true);
954 }
955 systemAddPlayer(newplayer);// the final, local, adding
956 //systemAddPlayer(stream);
957 }
958 }
959 break;
960 case KGameMessage::IdRemovePlayer: // Client should delete player id
961 {
962 int id;
963 stream >> id;
964 kdDebug(11001) << k_funcinfo << ": Got IdRemovePlayer " << id << endl;
965 KPlayer *p=findPlayer(id);
966 if (p)
967 {
968 // Otherwise the player is already removed
969 if (sender!=gameId() || policy()!=PolicyDirty)
970 {
971 systemRemovePlayer(p,true);
972 }
973 }
974 else
975 {
976 kdWarning(11001) << k_funcinfo << "Cannot find player " << id << endl;
977 }
978 }
979 break;
980 case KGameMessage::IdGameLoad:
981 {
982 kdDebug(11001) << "====> (Client) " << k_funcinfo << ": Got IdGameLoad" << endl;
983 loadgame(stream,true,false);
984 }
985 break;
986 case KGameMessage::IdGameSetupDone:
987 {
988 int cid;
989 stream >> cid;
990 kdDebug(11001) << "====> (CLIENT) " << k_funcinfo << ": Got IdGameSetupDone for client "
991 << cid << " we are =" << gameId() << endl;
992 sendSystemMessage(gameId(), KGameMessage::IdGameConnected, 0);
993 }
994 break;
995 case KGameMessage::IdGameConnected:
996 {
997 int cid;
998 stream >> cid;
999 kdDebug(11001) << "====> (ALL) " << k_funcinfo << ": Got IdGameConnected for client "<< cid << " we are =" << gameId() << endl;
1000 emit signalClientJoinedGame(cid,this);
1001 }
1002 break;
1003
1004 case KGameMessage::IdSyncRandom: // Master forces a new random seed on us
1005 {
1006 int newseed;
1007 stream >> newseed;
1008 kdDebug(11001) << "CLIENT: setting random seed to " << newseed << endl;
1009 d->mRandom->setSeed(newseed);
1010 }
1011 break;
1012 case KGameMessage::IdDisconnect:
1013 {
1014 // if we disconnect we *always* start a local game.
1015 // this could lead into problems if we just change the message server
1016 if (sender != gameId())
1017 {
1018 kdDebug(11001) << "client " << sender << " leaves game" << endl;
1019 return;
1020 }
1021 kdDebug(11001) << "leaving the game" << endl;
1022 // start a new local game
1023 // no other client is by default connected to this so this call should be
1024 // enough
1025 setMaster();
1026 }
1027 break;
1028 default:
1029 {
1030 if (msgid < KGameMessage::IdUser)
1031 {
1032 kdError(11001) << "incorrect message id " << msgid << " - emit anyway"
1033 << endl;
1034 }
1035 kdDebug(11001) << k_funcinfo << ": User data msgid " << msgid << endl;
1036 emit signalNetworkData(msgid - KGameMessage::IdUser,((TQBuffer*)stream.device())->readAll(),receiver,sender);
1037 }
1038 break;
1039 }
1040
1041}
1042
1043// called by the IdSetupGameContinue Message - MASTER SIDE
1044// Here the master needs to decide which players can take part at the game
1045// and which will be deactivated
1046void KGame::setupGameContinue(TQDataStream& stream, TQ_UINT32 sender)
1047{
1048 KPlayer *player;
1049 TQ_INT32 cnt;
1050 int i;
1051 stream >> cnt;
1052
1053 TQValueList<int> inactivateIds;
1054
1055 KGamePlayerList newPlayerList;
1056 newPlayerList.setAutoDelete(true);
1057 for (i=0;i<cnt;i++)
1058 {
1059 player=loadPlayer(stream,true);
1060 kdDebug(11001) << " Master got player " << player->id() <<" rawgame=" << KGameMessage::rawGameId(player->id()) << " from sender " << sender << endl;
1061 if (KGameMessage::rawGameId(player->id()) != sender)
1062 {
1063 kdError(11001) << "Client tries to add player with wrong game id - cheat possible" << endl;
1064 }
1065 else
1066 {
1067 newPlayerList.append(player);
1068 kdDebug(11001) << " newplayerlist appended " << player->id() << endl;
1069 }
1070 }
1071
1072 newPlayersJoin(playerList(),&newPlayerList,inactivateIds);
1073
1074
1075 kdDebug(11001) << " Master calculates how many players to activate client has cnt=" << cnt << endl;
1076 kdDebug(11001) << " The game has " << playerCount() << " active players" << endl;
1077 kdDebug(11001) << " The user deactivated "<< inactivateIds.count() << " player already " << endl;
1078 kdDebug(11001) << " MaxPlayers for this game is " << maxPlayers() << endl;
1079
1080 // Do we have too many players? (After the programmer disabled some?)
1081 // MH: We cannot use have player here as it CHANGES in the loop
1082 // int havePlayers = cnt+playerCount()-inactivateIds.count();
1083 kdDebug(11001) << " havePlayers " << cnt+playerCount()-inactivateIds.count() << endl;
1084 while (maxPlayers() > 0 && maxPlayers() < (int)(cnt+playerCount() - inactivateIds.count()))
1085 {
1086 kdDebug(11001) << " Still to deacticvate "
1087 << (int)(cnt+playerCount()-inactivateIds.count())-(int)maxPlayers()
1088 << endl;
1089 KPlayer *currentPlayer=0;
1090 int currentPriority=0x7fff; // MAX_UINT (16bit?) to get the maximum of the list
1091 // find lowest network priority which is not yet in the newPlayerList
1092 // do this for the new players
1093 for ( player=newPlayerList.first(); player != 0; player=newPlayerList.next() )
1094 {
1095 // Already in the list
1096 if (inactivateIds.find(player->id())!=inactivateIds.end())
1097 {
1098 continue;
1099 }
1100 if (player->networkPriority()<currentPriority)
1101 {
1102 currentPriority=player->networkPriority();
1103 currentPlayer=player;
1104 }
1105 }
1106
1107 // find lowest network priority which is not yet in the newPlayerList
1108 // Do this for the network players
1109 for ( player=d->mPlayerList.first(); player != 0; player=d->mPlayerList.next() )
1110 {
1111 // Already in the list
1112 if (inactivateIds.find(player->id())!=inactivateIds.end())
1113 {
1114 continue;
1115 }
1116 if (player->networkPriority()<currentPriority)
1117 {
1118 currentPriority=player->networkPriority();
1119 currentPlayer=player;
1120 }
1121 }
1122
1123 // add it to inactivateIds
1124 if (currentPlayer)
1125 {
1126 kdDebug(11001) << "Marking player " << currentPlayer->id() << " for inactivation" << endl;
1127 inactivateIds.append(currentPlayer->id());
1128 }
1129 else
1130 {
1131 kdError(11001) << "Couldn't find a player to dectivate..That is not so good..." << endl;
1132 break;
1133 }
1134 }
1135
1136 kdDebug(11001) << "Alltogether deactivated " << inactivateIds.count() << " players" << endl;
1137
1138 TQValueList<int>::Iterator it;
1139 for ( it = inactivateIds.begin(); it != inactivateIds.end(); ++it )
1140 {
1141 int pid=*it;
1142 kdDebug(11001) << " pid=" << pid << endl;
1143 }
1144
1145 // Now deactivate the network players from the inactivateId list
1146 //TQValueList<int>::Iterator it;
1147 for ( it = inactivateIds.begin(); it != inactivateIds.end(); ++it )
1148 {
1149 int pid=*it;
1150 if (KGameMessage::rawGameId(pid) == sender)
1151 {
1152 continue; // client's player
1153 }
1154 kdDebug(11001) << " -> the network needs to deactivate " << pid <<endl;
1155 player=findPlayer(pid);
1156 if (player)
1157 {
1158 // We have to make REALLY sure that the player is gone. With any policy
1159 systemInactivatePlayer(player);
1160 if (policy()!=PolicyLocal)
1161 {
1162 sendSystemMessage(player->id(), KGameMessage::IdInactivatePlayer);
1163 }
1164 }
1165 else
1166 {
1167 kdError(11001) << " We should deactivate a player, but cannot find it...not good." << endl;
1168 }
1169 }
1170
1171 // Now send out the player list which the client can activate
1172 for ( player=newPlayerList.first(); player != 0; player=newPlayerList.next() )
1173 {
1174 kdDebug(11001) << " newplayerlist contains " << player->id() << endl;
1175 // Only activate what is not in the list
1176 if (inactivateIds.find(player->id())!=inactivateIds.end())
1177 {
1178 continue;
1179 }
1180 kdDebug(11001) << " -> the client can ******** reactivate ******** " << player->id() << endl;
1181 sendSystemMessage(player->id(), KGameMessage::IdActivatePlayer, sender);
1182 }
1183
1184 // Save the game over the network
1185 TQByteArray bufferS;
1186 TQDataStream streamS(bufferS,IO_WriteOnly);
1187 // Save game over netowrk and save players
1188 savegame(streamS,true,true);
1189 sendSystemMessage(streamS,KGameMessage::IdGameLoad,sender);
1190
1191
1192 // Only to the client first , as the client will add players
1193 sendSystemMessage(sender, KGameMessage::IdGameSetupDone, sender);
1194}
1195
1196// called by the IdSetupGame Message - CLIENT SIDE
1197// Client needs to prepare for network transfer
1198void KGame::setupGame(TQ_UINT32 sender)
1199{
1200 TQByteArray bufferS;
1201 TQDataStream streamS(bufferS,IO_WriteOnly);
1202
1203 // Deactivate all players
1204 KGamePlayerList mTmpList(d->mPlayerList); // we need copy otherwise the removal crashes
1205 TQ_INT32 cnt=mTmpList.count();
1206 kdDebug(11001) << "Client: playerlistcount=" << d->mPlayerList.count() << " tmplistcout=" << cnt << endl;
1207
1208 streamS << cnt;
1209
1210 TQPtrListIterator<KPlayer> it(mTmpList);
1211 KPlayer *player;
1212 while (it.current())
1213 {
1214 player=it.current();
1215 systemInactivatePlayer(player);
1216 // Give the new game id to all players (which are inactivated now)
1217 player->setId(KGameMessage::createPlayerId(player->id(),gameId()));
1218
1219 // Save it for the master to decide what to do
1220 savePlayer(streamS,player);
1221
1222 ++it;
1223 --cnt;
1224 }
1225 if (d->mPlayerList.count() > 0 || cnt!=0)
1226 {
1227 kdFatal(11001) << "KGame::setupGame(): Player list is not empty! or cnt!=0=" <<cnt << endl;
1228 }
1229
1230 sendSystemMessage(streamS,KGameMessage::IdSetupGameContinue,sender);
1231}
1232
1233// unused by KGame
1234void KGame::syncRandom()
1235{
1236 int newseed=(int)d->mRandom->getLong(65535);
1237 sendSystemMessage(newseed,KGameMessage::IdSyncRandom); // Broadcast
1238 d->mRandom->setSeed(newseed);
1239}
1240
1241void KGame::Debug()
1242{
1243 KGameNetwork::Debug();
1244 kdDebug(11001) << "------------------- KGAME -------------------------" << endl;
1245 kdDebug(11001) << "this: " << this << endl;
1246 kdDebug(11001) << "uniquePlayer " << d->mUniquePlayerNumber << endl;
1247 kdDebug(11001) << "gameStatus " << gameStatus() << endl;
1248 kdDebug(11001) << "MaxPlayers : " << maxPlayers() << endl;
1249 kdDebug(11001) << "NoOfPlayers : " << playerCount() << endl;
1250 kdDebug(11001) << "NoOfInactive: " << d->mInactivePlayerList.count() << endl;
1251 kdDebug(11001) << "---------------------------------------------------" << endl;
1252}
1253
1254void KGame::slotClientConnected(TQ_UINT32 clientID)
1255{
1256 if (isAdmin())
1257 {
1258 negotiateNetworkGame(clientID);
1259 }
1260}
1261
1262void KGame::slotServerDisconnected() // Client side
1263{
1264 kdDebug(11001) << "======= SERVER DISCONNECT ======="<<endl;
1265 kdDebug(11001) << "+++ (CLIENT)++++++++" << k_funcinfo << ": our GameID="<<gameId() << endl;
1266
1267 int oldgamestatus=gameStatus();
1268
1269 KPlayer *player;
1270 KGamePlayerList removeList;
1271 kdDebug(11001) << "Playerlist of client=" << d->mPlayerList.count() << " count" << endl;
1272 kdDebug(11001) << "Inactive Playerlist of client=" << d->mInactivePlayerList.count() << " count" << endl;
1273 for ( player=d->mPlayerList.first(); player != 0; player=d->mPlayerList.next() )
1274 {
1275 // TODO: CHECK: id=0, could not connect to server in the first place??
1276 if (KGameMessage::rawGameId(player->id()) != gameId() && gameId()!=0)
1277 {
1278 kdDebug(11001) << "Player " << player->id() << " belongs to a removed game" << endl;
1279 removeList.append(player);
1280 }
1281 }
1282
1283 for ( player=removeList.first(); player != 0; player=removeList.next() )
1284 {
1285 bool remove = true;
1286 emit signalReplacePlayerIO(player, &remove);
1287 if (remove)
1288 {
1289 kdDebug(11001) << " ---> Removing player " << player->id() << endl;
1290 systemRemovePlayer(player,true); // no network necessary
1291 }
1292 }
1293
1294 setMaster();
1295 kdDebug(11001) << " our game id is after setMaster " << gameId() << endl;
1296
1297 KGamePlayerList mReList(d->mInactivePlayerList);
1298 for ( player=mReList.first(); player != 0; player=mReList.next() )
1299 {
1300 // TODO ?check for priority? Sequence should be ok
1301 if ((int)playerCount()<maxPlayers() || maxPlayers()<0)
1302 {
1303 systemActivatePlayer(player);
1304 }
1305 }
1306 kdDebug(11001) << " Players activated player-cnt=" << playerCount() << endl;
1307
1308 for ( player=d->mPlayerList.first(); player != 0; player=d->mPlayerList.next() )
1309 {
1310 int oldid=player->id();
1311 d->mUniquePlayerNumber++;
1312 player->setId(KGameMessage::createPlayerId(d->mUniquePlayerNumber,gameId()));
1313 kdDebug(11001) << "Player id " << oldid <<" changed to " << player->id() << " as we are now local" << endl;
1314 }
1315 // TODO clear inactive lists ?
1316 Debug();
1317 for ( player=d->mPlayerList.first(); player != 0; player=d->mPlayerList.next() )
1318 {
1319 player->Debug();
1320 }
1321 kdDebug(11001) << "+++++++++++" << k_funcinfo << " DONE=" << endl;
1322 emit signalClientLeftGame(0,oldgamestatus,this);
1323}
1324
1325void KGame::slotClientDisconnected(TQ_UINT32 clientID,bool /*broken*/) // server side
1326{
1327 kdDebug(11001) << "++++(SERVER)+++++++" << k_funcinfo << " clientId=" << clientID << endl;
1328
1329 int oldgamestatus=gameStatus();
1330
1331 KPlayer *player;
1332 KGamePlayerList removeList;
1333 kdDebug(11001) << "Playerlist of client=" << d->mPlayerList.count() << " count" << endl;
1334 for ( player=d->mPlayerList.first(); player != 0; player=d->mPlayerList.next() )
1335 {
1336 if (KGameMessage::rawGameId(player->id())==clientID)
1337 {
1338 kdDebug(11001) << "Player " << player->id() << " belongs to the removed game" << endl;
1339 removeList.append(player);
1340 }
1341 }
1342
1343 for ( player=removeList.first(); player != 0; player=removeList.next() )
1344 {
1345 // try to replace the KGameIO first
1346 bool remove = true;
1347 emit signalReplacePlayerIO(player, &remove);
1348 if (remove) {
1349 // otherwise (no new KGameIO) remove the player
1350 kdDebug(11001) << " ---> Removing player " << player->id() << endl;
1351 removePlayer(player,0);
1352 }
1353 }
1354
1355 // Now add inactive players - sequence should be ok
1356 // TODO remove players from removed game
1357 for (unsigned int idx=0;idx<d->mInactiveIdList.count();idx++)
1358 {
1359 TQValueList<int>::Iterator it1 = d->mInactiveIdList.at(idx);
1360 player = findPlayer(*it1);
1361 if (((int)playerCount() < maxPlayers() || maxPlayers() < 0) && player && KGameMessage::rawGameId(*it1) != clientID)
1362 {
1363 activatePlayer(player);
1364 }
1365 }
1366 emit signalClientLeftGame(clientID,oldgamestatus,this);
1367}
1368
1369
1370// -------------------- Synchronisation -----------------------
1371
1372// this initializes a newly connected client.
1373// we send the number of players (including type) as well as game status and
1374// properties to the client. After the initialization has been completed both
1375// clients should have the same status (ie players, properties, etc)
1376void KGame::negotiateNetworkGame(TQ_UINT32 clientID)
1377{
1378 kdDebug(11001) << "===========================" << k_funcinfo << ": clientID=" << clientID << " =========================== "<< endl;
1379 if (!isAdmin())
1380 {
1381 kdError(11001) << k_funcinfo << ": Serious WARNING..only gameAdmin should call this" << endl;
1382 return ;
1383 }
1384
1385 TQByteArray buffer;
1386 TQDataStream streamGS(buffer,IO_WriteOnly);
1387
1388 // write Game setup specific data
1389 //streamGS << (TQ_INT32)maxPlayers();
1390 //streamGS << (TQ_INT32)minPlayers();
1391
1392 // send to the newly connected client *only*
1393 TQ_INT16 v=KGameMessage::version();
1394 TQ_INT32 c=cookie();
1395 streamGS << v << c;
1396 sendSystemMessage(streamGS, KGameMessage::IdSetupGame, clientID);
1397}
1398
1399bool KGame::sendGroupMessage(const TQByteArray &msg, int msgid, TQ_UINT32 sender, const TQString& group)
1400{
1401// AB: group must not be i18n'ed!! we should better use an id for group and use
1402// a groupName() for the name // FIXME
1403 KPlayer *player;
1404 for ( player=d->mPlayerList.first(); player != 0; player=d->mPlayerList.next() )
1405 {
1406 if (player && player->group()==group)
1407 {
1408 sendMessage(msg,msgid,player->id(), sender);
1409 }
1410 }
1411 return true;
1412}
1413
1414bool KGame::sendGroupMessage(const TQDataStream &msg, int msgid, TQ_UINT32 sender, const TQString& group)
1415{ return sendGroupMessage(((TQBuffer*)msg.device())->buffer(), msgid, sender, group); }
1416
1417bool KGame::sendGroupMessage(const TQString& msg, int msgid, TQ_UINT32 sender, const TQString& group)
1418{
1419 TQByteArray buffer;
1420 TQDataStream stream(buffer, IO_WriteOnly);
1421 stream << msg;
1422 return sendGroupMessage(stream, msgid, sender, group);
1423}
1424
1425bool KGame::addProperty(KGamePropertyBase* data)
1426{ return dataHandler()->addProperty(data); }
1427
1428bool KGame::sendPlayerProperty(int msgid, TQDataStream& s, TQ_UINT32 playerId)
1429{ return sendSystemMessage(s, msgid, playerId); }
1430
1431void KGame::sendProperty(int msgid, TQDataStream& stream, bool* sent)
1432{
1433 bool s = sendSystemMessage(stream, msgid);
1434 if (s)
1435 {
1436 *sent = true;
1437 }
1438}
1439
1440void KGame::emitSignal(KGamePropertyBase *me)
1441{
1442 emit signalPropertyChanged(me,this);
1443}
1444
1445KGamePropertyBase* KGame::findProperty(int id) const
1446{ return d->mProperties->find(id); }
1447
1448KGame::GamePolicy KGame::policy() const
1449{
1450 return d->mPolicy;
1451}
1452void KGame::setPolicy(GamePolicy p,bool recursive)
1453{
1454 // Set KGame policy
1455 d->mPolicy=p;
1456 if (recursive)
1457 {
1458 // Set all KGame property policy
1459 dataHandler()->setPolicy((KGamePropertyBase::PropertyPolicy)p,false);
1460
1461 // Set all KPLayer (active or inactive) property policy
1462 for (TQPtrListIterator<KPlayer> it(d->mPlayerList); it.current(); ++it)
1463 {
1464 it.current()->dataHandler()->setPolicy((KGamePropertyBase::PropertyPolicy)p,false);
1465 }
1466 for (TQPtrListIterator<KPlayer> it(d->mInactivePlayerList); it.current(); ++it)
1467 {
1468 it.current()->dataHandler()->setPolicy((KGamePropertyBase::PropertyPolicy)p,false);
1469 }
1470 }
1471}
KGameNetwork
The KGameNetwork class is the KGame class with network support.
Definition: kgamenetwork.h:47
KGameNetwork::isAdmin
bool isAdmin() const
The admin of a game is the one who initializes newly connected clients using negotiateNetworkGame and...
Definition: kgamenetwork.cpp:104
KGameNetwork::signalClientDisconnected
void signalClientDisconnected(TQ_UINT32 clientID, bool broken)
This signal is emitted whenever the KMessageServer sends us a message that a connection to a client w...
KGameNetwork::Debug
virtual void Debug()
Gives debug output of the game status.
Definition: kgamenetwork.cpp:505
KGameNetwork::disconnect
void disconnect()
Disconnect the current connection and establish a new local one.
Definition: kgamenetwork.cpp:273
KGameNetwork::signalClientConnected
void signalClientConnected(TQ_UINT32 clientID)
This signal is emitted whenever the KMessageServer sends us a message that a new client connected.
KGameNetwork::gameId
TQ_UINT32 gameId() const
The unique ID of this game.
Definition: kgamenetwork.cpp:86
KGameNetwork::cookie
int cookie() const
Application cookie.
Definition: kgamenetwork.cpp:98
KGameNetwork::sendSystemMessage
bool sendSystemMessage(const TQByteArray &buffer, int msgid, TQ_UINT32 receiver=0, TQ_UINT32 sender=0)
Sends a network message msg with a given msg id msgid to all clients.
Definition: kgamenetwork.cpp:396
KGameNetwork::sendMessage
bool sendMessage(const TQByteArray &buffer, int msgid, TQ_UINT32 receiver=0, TQ_UINT32 sender=0)
Send a network message msg with a given message ID msgid to all clients.
Definition: kgamenetwork.cpp:447
KGameNetwork::signalConnectionBroken
void signalConnectionBroken()
Our connection to the KMessageServer has broken.
KGameNetwork::sendError
void sendError(int error, const TQByteArray &message, TQ_UINT32 receiver=0, TQ_UINT32 sender=0)
Sends a network message.
Definition: kgamenetwork.cpp:450
KGamePropertyBase
Base class of KGameProperty.
Definition: kgameproperty.h:43
KGamePropertyBase::PropertyPolicy
PropertyPolicy
The policy of the property.
Definition: kgameproperty.h:110
KGamePropertyHandler
A collection class for KGameProperty objects.
Definition: kgamepropertyhandler.h:73
KGamePropertyHandler::load
virtual bool load(TQDataStream &stream)
Loads properties from the datastream.
Definition: kgamepropertyhandler.cpp:188
KGamePropertyHandler::setPolicy
void setPolicy(KGamePropertyBase::PropertyPolicy p, bool userspace=true)
Set the policy for all kgame variables which are currently registerd in the KGame proeprty handler.
Definition: kgamepropertyhandler.cpp:232
KGamePropertyHandler::unlockDirectEmit
void unlockDirectEmit()
Removes the lock from the emitting of property signals.
Definition: kgamepropertyhandler.cpp:288
KGamePropertyHandler::lockDirectEmit
void lockDirectEmit()
Called by the KGame or KPlayer object or the handler itself to delay emmiting of signals.
Definition: kgamepropertyhandler.cpp:283
KGamePropertyHandler::save
virtual bool save(TQDataStream &stream)
Saves properties into the datastream.
Definition: kgamepropertyhandler.cpp:210
KGamePropertyHandler::addProperty
bool addProperty(KGamePropertyBase *data, TQString name=0)
Adds a KGameProperty property to the handler.
Definition: kgamepropertyhandler.cpp:151
KGameProperty< int >
KGameSequence
This class takes care of round or move management as well of the gameover condition.
Definition: kgamesequence.h:43
KGameSequence::nextPlayer
virtual KPlayer * nextPlayer(KPlayer *last, bool exclusive=true)
Select the next player in a turn based game.
Definition: kgamesequence.cpp:50
KGameSequence::checkGameOver
virtual int checkGameOver(KPlayer *player)
Check whether the game is over.
Definition: kgamesequence.cpp:119
KGame::createPlayer
virtual KPlayer * createPlayer(int rtti, int io, bool isvirtual)
This virtual function is called if the KGame needs to create a new player.
Definition: kgame.cpp:349
KGame::inactivePlayerList
KGamePlayerList * inactivePlayerList()
Returns a list of all inactive players.
Definition: kgame.cpp:693
KGame::signalSavePrePlayers
void signalSavePrePlayers(TQDataStream &stream)
The game will be saved to the given stream.
KGame::maxPlayers
int maxPlayers() const
What is the maximal number of players?
Definition: kgame.cpp:677
KGame::removePlayer
bool removePlayer(KPlayer *player)
Sends a message over the network, msgid=IdRemovePlayer.
Definition: kgame.h:223
KGame::newPlayersJoin
virtual void newPlayersJoin(KGamePlayerList *oldplayer, KGamePlayerList *newplayer, TQValueList< int > &inactivate)
This virtual function can be overwritten for your own player management.
Definition: kgame.h:754
KGame::sendPlayerProperty
bool sendPlayerProperty(int msgid, TQDataStream &s, TQ_UINT32 playerId)
This is called by KPlayer::sendProperty only! Internal function!
Definition: kgame.cpp:1428
KGame::networkTransmission
virtual void networkTransmission(TQDataStream &stream, int msgid, TQ_UINT32 receiver, TQ_UINT32 sender, TQ_UINT32 clientID)
This will either forward an incoming message to a specified player (see KPlayer::networkTransmission)...
Definition: kgame.cpp:843
KGame::signalPropertyChanged
void signalPropertyChanged(KGamePropertyBase *property, KGame *me)
This signal is emmited if a player property changes its value and the property is set to notify this ...
KGame::save
virtual bool save(TQDataStream &stream, bool saveplayers=true)
Save a game to a file OR to network.
Definition: kgame.cpp:284
KGame::Debug
virtual void Debug()
Gives debug output of the game status.
Definition: kgame.cpp:1241
KGame::signalReplacePlayerIO
void signalReplacePlayerIO(KPlayer *player, bool *remove)
When a client disconnects from the game usually all players from that client are removed.
KGame::checkGameOver
virtual int checkGameOver(KPlayer *player)
Definition: kgame.cpp:790
KGame::setGameSequence
void setGameSequence(KGameSequence *sequence)
Set a new KGameSequence to control player management.
Definition: kgame.cpp:799
KGame::prepareNext
virtual void prepareNext()
Definition: kgame.cpp:814
KGame::sendPlayerInput
virtual bool sendPlayerInput(TQDataStream &msg, KPlayer *player, TQ_UINT32 sender=0)
Called by KPlayer to send a player input to the KMessageServer.
Definition: kgame.cpp:709
KGame::signalLoadError
void signalLoadError(TQDataStream &stream, bool network, int cookie, bool &result)
Is emmited if a game with a different version cookie is loaded.
KGame::slotServerDisconnected
void slotServerDisconnected()
This slot is called whenever the connection to the server is lost (ie the signal KGameNetwork::signal...
Definition: kgame.cpp:1262
KGame::savePlayer
void savePlayer(TQDataStream &stream, KPlayer *player)
Prepare a player for being added.
Definition: kgame.cpp:323
KGame::signalMessageUpdate
void signalMessageUpdate(int msgid, TQ_UINT32 receiver, TQ_UINT32 sender)
We got an network message.
KGame::activatePlayer
bool activatePlayer(KPlayer *player)
sends activate player: internal use only?
Definition: kgame.cpp:630
KGame::syncRandom
void syncRandom()
syncronise the random numbers with all network clients not used by KGame - if it should be kept then ...
Definition: kgame.cpp:1234
KGame::addPlayer
void addPlayer(KPlayer *newplayer)
Note that KPlayer::save must be implemented properly, as well as KPlayer::rtti This will only send a ...
Definition: kgame.cpp:412
KGame::sendProperty
void sendProperty(int msgid, TQDataStream &stream, bool *sent)
Called by KGamePropertyHandler only! Internal function!
Definition: kgame.cpp:1431
KGame::slotClientConnected
void slotClientConnected(TQ_UINT32 clientId)
Calls negotiateNetworkGame() See KGameNetwork::signalClientConnected.
Definition: kgame.cpp:1254
KGame::signalGameOver
void signalGameOver(int status, KPlayer *current, KGame *me)
Is emitted after a call to gameOver() returns a non zero return code.
KGame::signalPlayerJoinedGame
void signalPlayerJoinedGame(KPlayer *player)
a player joined the game
KGame::isRunning
bool isRunning() const
Is the game running.
Definition: kgame.cpp:686
KGame::nextPlayer
virtual KPlayer * nextPlayer(KPlayer *last, bool exclusive=true)
Definition: kgame.cpp:823
KGame::reset
virtual bool reset()
Resets the game, i.e.
Definition: kgame.cpp:131
KGame::signalSave
void signalSave(TQDataStream &stream)
The game will be saved to the given stream.
KGame::systemInactivatePlayer
bool systemInactivatePlayer(KPlayer *player)
inactivates player.
Definition: kgame.cpp:602
KGame::systemActivatePlayer
bool systemActivatePlayer(KPlayer *player)
activates player.
Definition: kgame.cpp:648
KGame::signalLoadPrePlayers
void signalLoadPrePlayers(TQDataStream &stream)
The game will be loaded from the given stream.
KGame::random
KRandomSequence * random() const
Returns a pointer to the game's KRandomSequence.
Definition: kgame.cpp:705
KGame::playerInputFinished
KPlayer * playerInputFinished(KPlayer *player)
Called after the player input is processed by the game.
Definition: kgame.cpp:758
KGame::KGame
KGame(int cookie=42, TQObject *parent=0)
Create a KGame object.
Definition: kgame.cpp:84
KGame::dataHandler
KGamePropertyHandler * dataHandler() const
Returns a pointer to the KGame property handler.
Definition: kgame.cpp:689
KGame::playerList
KGamePlayerList * playerList()
Returns a list of all active players.
Definition: kgame.cpp:699
KGame::systemAddPlayer
void systemAddPlayer(KPlayer *newplayer)
Adds a player to the game.
Definition: kgame.cpp:460
KGame::playerInput
virtual bool playerInput(TQDataStream &msg, KPlayer *player)=0
A player input occurred.
KGame::emitSignal
void emitSignal(KGamePropertyBase *me)
Called by KGamePropertyHandler only! Internal function!
Definition: kgame.cpp:1440
KGame::gameStatus
int gameStatus() const
returns the game status, ie running,pause,ended,...
Definition: kgame.cpp:683
KGame::findPlayer
KPlayer * findPlayer(TQ_UINT32 id) const
Returns the player object for a given player id.
Definition: kgame.cpp:386
KGame::signalNetworkData
void signalNetworkData(int msgid, const TQByteArray &buffer, TQ_UINT32 receiver, TQ_UINT32 sender)
We got an user defined update message.
KGame::gameSequence
KGameSequence * gameSequence() const
Definition: kgame.cpp:809
KGame::setMinPlayers
void setMinPlayers(uint minnumber)
Set the minimal number of players.
Definition: kgame.cpp:671
KGame::addProperty
bool addProperty(KGamePropertyBase *data)
docu: see KPlayer
Definition: kgame.cpp:1425
KGame::setGameStatus
void setGameStatus(int status)
sets the game status
Definition: kgame.cpp:832
KGame::playerCount
uint playerCount() const
Returns how many players are plugged into the game.
Definition: kgame.cpp:680
KGame::GamePolicy
GamePolicy
The policy of the property.
Definition: kgame.h:92
KGame::inactivatePlayer
bool inactivatePlayer(KPlayer *player)
sends inactivate player: internal use only?
Definition: kgame.cpp:582
KGame::playerDeleted
void playerDeleted(KPlayer *player)
Called by the destructor of KPlayer to remove itself from the game.
Definition: kgame.cpp:492
KGame::signalPlayerLeftGame
void signalPlayerLeftGame(KPlayer *player)
a player left the game because of a broken connection or so!
KGame::sendGroupMessage
bool sendGroupMessage(const TQByteArray &msg, int msgid, TQ_UINT32 sender, const TQString &group)
See KGameNetwork::sendMessage.
Definition: kgame.cpp:1399
KGame::loadgame
virtual bool loadgame(TQDataStream &stream, bool network, bool reset)
Load a saved game, from file OR network.
Definition: kgame.cpp:182
KGame::negotiateNetworkGame
virtual void negotiateNetworkGame(TQ_UINT32 clientID)
This member function will transmit e.g.
Definition: kgame.cpp:1376
KGame::setMaxPlayers
void setMaxPlayers(uint maxnumber)
Set the maximal number of players.
Definition: kgame.cpp:668
KGame::signalLoad
void signalLoad(TQDataStream &stream)
The game will be loaded from the given stream.
KGame::slotClientDisconnected
void slotClientDisconnected(TQ_UINT32 clientId, bool broken)
This slot is called whenever the connection to a client is lost (ie the signal KGameNetwork::signalCl...
Definition: kgame.cpp:1325
KGame::signalClientLeftGame
void signalClientLeftGame(int clientID, int oldgamestatus, KGame *me)
This signal is emitted after a network partner left the game (either by a broken connection or volunt...
KGame::loadPlayer
KPlayer * loadPlayer(TQDataStream &stream, bool isvirtual=false)
Load the player list from a stream.
Definition: kgame.cpp:354
KGame::savegame
virtual bool savegame(TQDataStream &stream, bool network, bool saveplayers)
Save a game, to file OR network.
Definition: kgame.cpp:287
KGame::policy
GamePolicy policy() const
Definition: kgame.cpp:1448
KGame::signalClientJoinedGame
void signalClientJoinedGame(TQ_UINT32 clientid, KGame *me)
Is emmited after a client is successfully connected to the game.
KGame::minPlayers
uint minPlayers() const
What is the minimal number of players?
Definition: kgame.cpp:674
KGame::load
virtual bool load(TQDataStream &stream, bool reset=true)
Load a saved game, from file OR network.
Definition: kgame.cpp:179
KGame::~KGame
virtual ~KGame()
Destructs the game.
Definition: kgame.cpp:120
KGame::savePlayers
void savePlayers(TQDataStream &stream, KGamePlayerList *list=0)
Save the player list to a stream.
Definition: kgame.cpp:332
KGame::findProperty
KGamePropertyBase * findProperty(int id) const
This function allows to find the pointer to a player property when you know it's id.
Definition: kgame.cpp:1445
KGame::setPolicy
void setPolicy(GamePolicy p, bool recursive=true)
Changes the consistency policy of a property.
Definition: kgame.cpp:1452
KGame::systemRemovePlayer
void systemRemovePlayer(KPlayer *player, bool deleteit)
Removes a player from the game.
Definition: kgame.cpp:532
KGame::systemPlayerInput
virtual bool systemPlayerInput(TQDataStream &msg, KPlayer *player, TQ_UINT32 sender=0)
Called when a player input arrives from KMessageServer.
Definition: kgame.cpp:727
KPlayer
Base class for a game player.
Definition: kplayer.h:70
KPlayer::setActive
void setActive(bool v)
Set an player as active (true) or inactive (false)
Definition: kplayer.h:181
KPlayer::calcIOValue
int calcIOValue()
Calculates a checksum over the IO devices.
Definition: kplayer.cpp:273
KPlayer::isVirtual
bool isVirtual() const
Is this player a virtual player, ie is it created by mirroring a real player from another network gam...
Definition: kplayer.cpp:204
KPlayer::rtti
virtual int rtti() const
The idendification of the player.
Definition: kplayer.h:99
KPlayer::save
virtual bool save(TQDataStream &stream)
Save a player to a file OR to network.
Definition: kplayer.cpp:340
KPlayer::id
TQ_UINT32 id() const
Returns the id of the player.
Definition: kplayer.cpp:195
KPlayer::asyncInput
bool asyncInput() const
Query whether this player does asynchronous input.
Definition: kplayer.h:145
KPlayer::networkTransmission
void networkTransmission(TQDataStream &stream, int msgid, TQ_UINT32 sender)
Receives a message.
Definition: kplayer.cpp:353
KPlayer::group
virtual const TQString & group() const
Query the group the player belongs to.
Definition: kplayer.cpp:186
KPlayer::setTurn
bool setTurn(bool b, bool exclusive=true)
Sets whether this player is the next to turn.
Definition: kplayer.cpp:285
KPlayer::isActive
bool isActive() const
Is this player an active player.
Definition: kplayer.h:174
KPlayer::setGame
void setGame(KGame *game)
sets the game the player belongs to.
Definition: kplayer.h:121
KPlayer::networkPriority
int networkPriority() const
Returns whether this player can be replaced by a network connection player.
Definition: kplayer.cpp:213
KPlayer::dataHandler
KGamePropertyHandler * dataHandler()
Definition: kplayer.cpp:198
KPlayer::load
virtual bool load(TQDataStream &stream)
Load a saved player, from file OR network.
Definition: kplayer.cpp:314
KPlayer::Debug
void Debug()
Gives debug output of the game status.
Definition: kplayer.cpp:428

libtdegames

Skip menu "libtdegames"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

libtdegames

Skip menu "libtdegames"
  • libtdegames
Generated for libtdegames by doxygen 1.9.4
This website is maintained by Timothy Pearson.