• 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
52 class KGamePrivate
53 {
54 public:
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 --------------------------
84 KGame::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 
120 KGame::~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 
131 bool KGame::reset()
132 {
133  deletePlayers();
134  deleteInactivePlayers();
135  return true;
136 }
137 
138 void 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 
151 void 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 
162 bool 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 
179 bool KGame::load(TQDataStream &stream,bool reset)
180 { return loadgame(stream, false,reset); }
181 
182 bool 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 
267 bool 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 
284 bool KGame::save(TQDataStream &stream,bool saveplayers)
285 { return savegame(stream, false,saveplayers); }
286 
287 bool 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 
323 void 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 
332 void 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 
349 KPlayer *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 }
354 KPlayer *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 
386 KPlayer * 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...
412 void 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 
460 void 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
492 void 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 
510 bool 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 
532 void 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 
552 bool 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 
582 bool 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 
602 bool 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 
630 bool 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 
648 bool 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 
668 void KGame::setMaxPlayers(uint maxnumber)
669 { if (isAdmin()) { d->mMaxPlayer.changeValue(maxnumber); } }
670 
671 void KGame::setMinPlayers(uint minnumber)
672 { if (isAdmin()) { d->mMinPlayer.changeValue(minnumber); } }
673 
674 uint KGame::minPlayers() const
675 { return d->mMinPlayer.value(); }
676 
677 int KGame::maxPlayers() const
678 { return d->mMaxPlayer.value(); }
679 
680 uint KGame::playerCount() const
681 { return d->mPlayerList.count(); }
682 
683 int KGame::gameStatus() const
684 { return d->mGameStatus.value(); }
685 
686 bool KGame::isRunning() const
687 { return d->mGameStatus.value() == Run; }
688 
689 KGamePropertyHandler* KGame::dataHandler() const
690 { return d->mProperties; }
691 
692 
693 KGame::KGamePlayerList* KGame::inactivePlayerList()
694 { return &d->mInactivePlayerList; }
695 
696 const KGame::KGamePlayerList* KGame::inactivePlayerList() const
697 { return &d->mInactivePlayerList; }
698 
699 KGame::KGamePlayerList* KGame::playerList()
700 { return &d->mPlayerList; }
701 
702 const KGame::KGamePlayerList* KGame::playerList() const
703 { return &d->mPlayerList; }
704 
705 KRandomSequence* KGame::random() const
706 { return d->mRandom; }
707 
708 
709 bool 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 
727 bool 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 
758 KPlayer * 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
790 int KGame::checkGameOver(KPlayer *player)
791 {
792  if (gameSequence())
793  {
794  return gameSequence()->checkGameOver(player);
795  }
796  return 0;
797 }
798 
799 void 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 
809 KGameSequence* KGame::gameSequence() const
810 {
811  return d->mGameSequence;
812 }
813 
814 void 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 
823 KPlayer *KGame::nextPlayer(KPlayer *last,bool exclusive)
824 {
825  if (gameSequence())
826  {
827  return gameSequence()->nextPlayer(last, exclusive);
828  }
829  return 0;
830 }
831 
832 void 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 
843 void 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
1046 void 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
1198 void 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
1234 void KGame::syncRandom()
1235 {
1236  int newseed=(int)d->mRandom->getLong(65535);
1237  sendSystemMessage(newseed,KGameMessage::IdSyncRandom); // Broadcast
1238  d->mRandom->setSeed(newseed);
1239 }
1240 
1241 void 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 
1254 void KGame::slotClientConnected(TQ_UINT32 clientID)
1255 {
1256  if (isAdmin())
1257  {
1258  negotiateNetworkGame(clientID);
1259  }
1260 }
1261 
1262 void 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 
1325 void 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)
1376 void 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 
1399 bool 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 
1414 bool KGame::sendGroupMessage(const TQDataStream &msg, int msgid, TQ_UINT32 sender, const TQString& group)
1415 { return sendGroupMessage(((TQBuffer*)msg.device())->buffer(), msgid, sender, group); }
1416 
1417 bool 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 
1425 bool KGame::addProperty(KGamePropertyBase* data)
1426 { return dataHandler()->addProperty(data); }
1427 
1428 bool KGame::sendPlayerProperty(int msgid, TQDataStream& s, TQ_UINT32 playerId)
1429 { return sendSystemMessage(s, msgid, playerId); }
1430 
1431 void 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 
1440 void KGame::emitSignal(KGamePropertyBase *me)
1441 {
1442  emit signalPropertyChanged(me,this);
1443 }
1444 
1445 KGamePropertyBase* KGame::findProperty(int id) const
1446 { return d->mProperties->find(id); }
1447 
1448 KGame::GamePolicy KGame::policy() const
1449 {
1450  return d->mPolicy;
1451 }
1452 void 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 }
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
KGameSequence
This class takes care of round or move management as well of the gameover condition.
Definition: kgamesequence.h:42
KGame::reset
virtual bool reset()
Resets the game, i.e.
Definition: kgame.cpp:131
KGame::setMaxPlayers
void setMaxPlayers(uint maxnumber)
Set the maximal number of players.
Definition: kgame.cpp:668
KGame::emitSignal
void emitSignal(KGamePropertyBase *me)
Called by KGamePropertyHandler only! Internal function!
Definition: kgame.cpp:1440
KGame::playerCount
uint playerCount() const
Returns how many players are plugged into the game.
Definition: kgame.cpp:680
KGame::loadPlayer
KPlayer * loadPlayer(TQDataStream &stream, bool isvirtual=false)
Load the player list from a stream.
Definition: kgame.cpp:354
KGame::loadgame
virtual bool loadgame(TQDataStream &stream, bool network, bool reset)
Load a saved game, from file OR network.
Definition: kgame.cpp:182
KPlayer::rtti
virtual int rtti() const
The idendification of the player.
Definition: kplayer.h:99
KGamePropertyHandler::lockDirectEmit
void lockDirectEmit()
Called by the KGame or KPlayer object or the handler itself to delay emmiting of signals.
Definition: kgamepropertyhandler.cpp:283
KGame::minPlayers
uint minPlayers() const
What is the minimal number of players?
Definition: kgame.cpp:674
KGameNetwork::signalConnectionBroken
void signalConnectionBroken()
Our connection to the KMessageServer has broken.
KGame::findPlayer
KPlayer * findPlayer(TQ_UINT32 id) const
Returns the player object for a given player id.
Definition: kgame.cpp:386
KGame::save
virtual bool save(TQDataStream &stream, bool saveplayers=true)
Save a game to a file OR to network.
Definition: kgame.cpp:284
KGame::removePlayer
bool removePlayer(KPlayer *player)
Sends a message over the network, msgid=IdRemovePlayer.
Definition: kgame.h:223
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
KPlayer::setTurn
bool setTurn(bool b, bool exclusive=true)
Sets whether this player is the next to turn.
Definition: kplayer.cpp:285
KPlayer::calcIOValue
int calcIOValue()
Calculates a checksum over the IO devices.
Definition: kplayer.cpp:273
KGamePropertyHandler
A collection class for KGameProperty objects.
Definition: kgamepropertyhandler.h:72
KGameNetwork::gameId
TQ_UINT32 gameId() const
The unique ID of this game.
Definition: kgamenetwork.cpp:86
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::systemInactivatePlayer
bool systemInactivatePlayer(KPlayer *player)
inactivates player.
Definition: kgame.cpp:602
KGamePropertyHandler::load
virtual bool load(TQDataStream &stream)
Loads properties from the datastream.
Definition: kgamepropertyhandler.cpp:188
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
KGame::systemRemovePlayer
void systemRemovePlayer(KPlayer *player, bool deleteit)
Removes a player from the game.
Definition: kgame.cpp:532
KGame::savePlayers
void savePlayers(TQDataStream &stream, KGamePlayerList *list=0)
Save the player list to a stream.
Definition: kgame.cpp:332
KGamePropertyBase::PropertyPolicy
PropertyPolicy
The policy of the property.
Definition: kgameproperty.h:109
KGame::activatePlayer
bool activatePlayer(KPlayer *player)
sends activate player: internal use only?
Definition: kgame.cpp:630
KPlayer::Debug
void Debug()
Gives debug output of the game status.
Definition: kplayer.cpp:428
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::signalLoad
void signalLoad(TQDataStream &stream)
The game will be loaded from the given stream.
KGame::signalMessageUpdate
void signalMessageUpdate(int msgid, TQ_UINT32 receiver, TQ_UINT32 sender)
We got an network message.
KGame::setMinPlayers
void setMinPlayers(uint minnumber)
Set the minimal number of players.
Definition: kgame.cpp:671
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...
KGame::inactivatePlayer
bool inactivatePlayer(KPlayer *player)
sends inactivate player: internal use only?
Definition: kgame.cpp:582
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
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
KGame::slotClientConnected
void slotClientConnected(TQ_UINT32 clientId)
Calls negotiateNetworkGame() See KGameNetwork::signalClientConnected.
Definition: kgame.cpp:1254
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::savePlayer
void savePlayer(TQDataStream &stream, KPlayer *player)
Prepare a player for being added.
Definition: kgame.cpp:323
KGame::GamePolicy
GamePolicy
The policy of the property.
Definition: kgame.h:91
KGame::Debug
virtual void Debug()
Gives debug output of the game status.
Definition: kgame.cpp:1241
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::signalNetworkData
void signalNetworkData(int msgid, const TQByteArray &buffer, TQ_UINT32 receiver, TQ_UINT32 sender)
We got an user defined update message.
KGameSequence::checkGameOver
virtual int checkGameOver(KPlayer *player)
Check whether the game is over.
Definition: kgamesequence.cpp:119
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::checkGameOver
virtual int checkGameOver(KPlayer *player)
Definition: kgame.cpp:790
KGame::systemAddPlayer
void systemAddPlayer(KPlayer *newplayer)
Adds a player to the game.
Definition: kgame.cpp:460
KPlayer::group
virtual const TQString & group() const
Query the group the player belongs to.
Definition: kplayer.cpp:186
KPlayer::setActive
void setActive(bool v)
Set an player as active (true) or inactive (false)
Definition: kplayer.h:181
KGame::playerInputFinished
KPlayer * playerInputFinished(KPlayer *player)
Called after the player input is processed by the game.
Definition: kgame.cpp:758
KGame::sendProperty
void sendProperty(int msgid, TQDataStream &stream, bool *sent)
Called by KGamePropertyHandler only! Internal function!
Definition: kgame.cpp:1431
KGame::gameSequence
KGameSequence * gameSequence() const
Definition: kgame.cpp:809
KGame::inactivePlayerList
KGamePlayerList * inactivePlayerList()
Returns a list of all inactive players.
Definition: kgame.cpp:693
KPlayer::id
TQ_UINT32 id() const
Returns the id of the player.
Definition: kplayer.cpp:195
KGameSequence::nextPlayer
virtual KPlayer * nextPlayer(KPlayer *last, bool exclusive=true)
Select the next player in a turn based game.
Definition: kgamesequence.cpp:50
KGame::signalClientJoinedGame
void signalClientJoinedGame(TQ_UINT32 clientid, KGame *me)
Is emmited after a client is successfully connected to the game.
KGame::negotiateNetworkGame
virtual void negotiateNetworkGame(TQ_UINT32 clientID)
This member function will transmit e.g.
Definition: kgame.cpp:1376
KGame::signalPlayerJoinedGame
void signalPlayerJoinedGame(KPlayer *player)
a player joined the game
KGame::signalLoadError
void signalLoadError(TQDataStream &stream, bool network, int cookie, bool &result)
Is emmited if a game with a different version cookie is loaded.
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
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::cookie
int cookie() const
Application cookie.
Definition: kgamenetwork.cpp:98
KGame::findProperty
KGamePropertyBase * findProperty(int id) const
This function allows to find the pointer to a player property when you know it&#39;s id.
Definition: kgame.cpp:1445
KPlayer::asyncInput
bool asyncInput() const
Query whether this player does asynchronous input.
Definition: kplayer.h:145
KPlayer
Base class for a game player.
Definition: kplayer.h:69
KGame::signalGameOver
void signalGameOver(int status, KPlayer *current, KGame *me)
Is emitted after a call to gameOver() returns a non zero return code.
KGame::playerInput
virtual bool playerInput(TQDataStream &msg, KPlayer *player)=0
A player input occurred.
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
KGame::maxPlayers
int maxPlayers() const
What is the maximal number of players?
Definition: kgame.cpp:677
KGamePropertyBase
Base class of KGameProperty.
Definition: kgameproperty.h:42
KGame::signalReplacePlayerIO
void signalReplacePlayerIO(KPlayer *player, bool *remove)
When a client disconnects from the game usually all players from that client are removed.
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::sendGroupMessage
bool sendGroupMessage(const TQByteArray &msg, int msgid, TQ_UINT32 sender, const TQString &group)
See KGameNetwork::sendMessage.
Definition: kgame.cpp:1399
KGame::signalPlayerLeftGame
void signalPlayerLeftGame(KPlayer *player)
a player left the game because of a broken connection or so!
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
KGame::prepareNext
virtual void prepareNext()
Definition: kgame.cpp:814
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
KPlayer::isActive
bool isActive() const
Is this player an active player.
Definition: kplayer.h:174
KPlayer::load
virtual bool load(TQDataStream &stream)
Load a saved player, from file OR network.
Definition: kplayer.cpp:314
KGame::systemActivatePlayer
bool systemActivatePlayer(KPlayer *player)
activates player.
Definition: kgame.cpp:648
KGame::KGame
KGame(int cookie=42, TQObject *parent=0)
Create a KGame object.
Definition: kgame.cpp:84
KGameNetwork
The KGameNetwork class is the KGame class with network support.
Definition: kgamenetwork.h:46
KGame::signalSave
void signalSave(TQDataStream &stream)
The game will be saved to the given stream.
KGamePropertyHandler::addProperty
bool addProperty(KGamePropertyBase *data, TQString name=0)
Adds a KGameProperty property to the handler.
Definition: kgamepropertyhandler.cpp:151
KGameNetwork::signalClientConnected
void signalClientConnected(TQ_UINT32 clientID)
This signal is emitted whenever the KMessageServer sends us a message that a new client connected...
KPlayer::setGame
void setGame(KGame *game)
sets the game the player belongs to.
Definition: kplayer.h:121
KGame::signalSavePrePlayers
void signalSavePrePlayers(TQDataStream &stream)
The game will be saved to the given stream.
KGame::random
KRandomSequence * random() const
Returns a pointer to the game&#39;s KRandomSequence.
Definition: kgame.cpp:705
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 ...
KPlayer::dataHandler
KGamePropertyHandler * dataHandler()
Definition: kplayer.cpp:198
KGame::setGameStatus
void setGameStatus(int status)
sets the game status
Definition: kgame.cpp:832
KPlayer::networkTransmission
void networkTransmission(TQDataStream &stream, int msgid, TQ_UINT32 sender)
Receives a message.
Definition: kplayer.cpp:353
KGamePropertyHandler::save
virtual bool save(TQDataStream &stream)
Saves properties into the datastream.
Definition: kgamepropertyhandler.cpp:210
KGame::addProperty
bool addProperty(KGamePropertyBase *data)
docu: see KPlayer
Definition: kgame.cpp:1425
KGame::playerList
KGamePlayerList * playerList()
Returns a list of all active players.
Definition: kgame.cpp:699
KGameNetwork::disconnect
void disconnect()
Disconnect the current connection and establish a new local one.
Definition: kgamenetwork.cpp:273
KGame::isRunning
bool isRunning() const
Is the game running.
Definition: kgame.cpp:686
KGame::~KGame
virtual ~KGame()
Destructs the game.
Definition: kgame.cpp:120
KGame::setGameSequence
void setGameSequence(KGameSequence *sequence)
Set a new KGameSequence to control player management.
Definition: kgame.cpp:799
KGameNetwork::Debug
virtual void Debug()
Gives debug output of the game status.
Definition: kgamenetwork.cpp:505
KGame::policy
GamePolicy policy() const
Definition: kgame.cpp:1448
KPlayer::networkPriority
int networkPriority() const
Returns whether this player can be replaced by a network connection player.
Definition: kplayer.cpp:213
KGame::dataHandler
KGamePropertyHandler * dataHandler() const
Returns a pointer to the KGame property handler.
Definition: kgame.cpp:689
KGame::load
virtual bool load(TQDataStream &stream, bool reset=true)
Load a saved game, from file OR network.
Definition: kgame.cpp:179
KGameProperty< int >
KGame::playerDeleted
void playerDeleted(KPlayer *player)
Called by the destructor of KPlayer to remove itself from the game.
Definition: kgame.cpp:492
KGame::signalLoadPrePlayers
void signalLoadPrePlayers(TQDataStream &stream)
The game will be loaded from the given stream.
KGamePropertyHandler::unlockDirectEmit
void unlockDirectEmit()
Removes the lock from the emitting of property signals.
Definition: kgamepropertyhandler.cpp:288
KGame::setPolicy
void setPolicy(GamePolicy p, bool recursive=true)
Changes the consistency policy of a property.
Definition: kgame.cpp:1452
KPlayer::save
virtual bool save(TQDataStream &stream)
Save a player to a file OR to network.
Definition: kplayer.cpp:340
KGame::savegame
virtual bool savegame(TQDataStream &stream, bool network, bool saveplayers)
Save a game, to file OR network.
Definition: kgame.cpp:287
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::nextPlayer
virtual KPlayer * nextPlayer(KPlayer *last, bool exclusive=true)
Definition: kgame.cpp:823
KGame::gameStatus
int gameStatus() const
returns the game status, ie running,pause,ended,...
Definition: kgame.cpp:683

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.8.13
This website is maintained by Timothy Pearson.