00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "kgame.h"
00025 #include "kgame.moc"
00026 #include "kgamepropertyhandler.h"
00027 #include "kgameproperty.h"
00028 #include "kplayer.h"
00029 #include "kgameio.h"
00030 #include "kgameerror.h"
00031 #include "kgamesequence.h"
00032
00033 #include "kgamemessage.h"
00034
00035 #include <unistd.h>
00036 #include <stdio.h>
00037 #include <assert.h>
00038
00039 #include <qbuffer.h>
00040 #include <qtimer.h>
00041 #include <qptrqueue.h>
00042 #include <qfile.h>
00043
00044 #include <klocale.h>
00045 #include <krandomsequence.h>
00046 #include <kdebug.h>
00047
00048 #define KGAME_LOAD_COOKIE 4210
00049
00050
00051
00052 class KGamePrivate
00053 {
00054 public:
00055 KGamePrivate()
00056 {
00057 mUniquePlayerNumber = 0;
00058 mPolicy=KGame::PolicyLocal;
00059 mGameSequence = 0;
00060 }
00061
00062 int mUniquePlayerNumber;
00063 QPtrQueue<KPlayer> mAddPlayerList;
00064 KRandomSequence* mRandom;
00065 KGame::GamePolicy mPolicy;
00066 KGameSequence* mGameSequence;
00067
00068
00069 KGamePropertyHandler* mProperties;
00070
00071
00072 KGame::KGamePlayerList mPlayerList;
00073 KGame::KGamePlayerList mInactivePlayerList;
00074
00075
00076 KGamePropertyInt mMaxPlayer;
00077 KGamePropertyUInt mMinPlayer;
00078 KGamePropertyInt mGameStatus;
00079 QValueList<int> mInactiveIdList;
00080
00081 };
00082
00083
00084 KGame::KGame(int cookie,QObject* parent) : KGameNetwork(cookie,parent)
00085 {
00086 kdDebug(11001) << k_funcinfo << " - " << this << ", sizeof(KGame)=" << sizeof(KGame) << endl;
00087 d = new KGamePrivate;
00088
00089 d->mProperties = new KGamePropertyHandler(this);
00090
00091 d->mProperties->registerHandler(KGameMessage::IdGameProperty,
00092 this,SLOT(sendProperty(int, QDataStream&, bool* )),
00093 SLOT(emitSignal(KGamePropertyBase *)));
00094 d->mMaxPlayer.registerData(KGamePropertyBase::IdMaxPlayer, this, i18n("MaxPlayers"));
00095 d->mMaxPlayer.setLocal(-1);
00096 d->mMinPlayer.registerData(KGamePropertyBase::IdMinPlayer, this, i18n("MinPlayers"));
00097 d->mMinPlayer.setLocal(0);
00098 d->mGameStatus.registerData(KGamePropertyBase::IdGameStatus, this, i18n("GameStatus"));
00099 d->mGameStatus.setLocal(Init);
00100
00101 d->mRandom = new KRandomSequence;
00102 d->mRandom->setSeed(0);
00103
00104 connect(this, SIGNAL(signalClientConnected(Q_UINT32)),
00105 this, SLOT(slotClientConnected(Q_UINT32)));
00106 connect(this, SIGNAL(signalClientDisconnected(Q_UINT32,bool)),
00107 this, SLOT(slotClientDisconnected(Q_UINT32,bool)));
00108 connect(this, SIGNAL(signalConnectionBroken()),
00109 this, SLOT(slotServerDisconnected()));
00110
00111 setGameSequence(new KGameSequence());
00112
00113
00114
00115
00116
00117
00118 }
00119
00120 KGame::~KGame()
00121 {
00122 kdDebug(11001) << k_funcinfo << endl;
00123
00124 reset();
00125 delete d->mGameSequence;
00126 delete d->mRandom;
00127 delete d;
00128 kdDebug(11001) << k_funcinfo << " done" << endl;
00129 }
00130
00131 bool KGame::reset()
00132 {
00133 deletePlayers();
00134 deleteInactivePlayers();
00135 return true;
00136 }
00137
00138 void KGame::deletePlayers()
00139 {
00140
00141 KGamePlayerList tmp = d->mPlayerList;
00142 KPlayer *player;
00143 while((player=tmp.first()))
00144 {
00145 delete player;
00146 tmp.removeFirst();
00147 }
00148
00149 }
00150
00151 void KGame::deleteInactivePlayers()
00152 {
00153 KPlayer *player;
00154 while((player=d->mInactivePlayerList.first()))
00155 {
00156
00157 d->mInactivePlayerList.remove(player);
00158 delete player;
00159 }
00160 }
00161
00162 bool KGame::load(QString filename,bool reset)
00163 {
00164 if (filename.isNull())
00165 {
00166 return false;
00167 }
00168 QFile f(filename);
00169 if (!f.open(IO_ReadOnly))
00170 {
00171 return false;
00172 }
00173 QDataStream s( &f );
00174 load(s,reset);
00175 f.close();
00176 return true;
00177 }
00178
00179 bool KGame::load(QDataStream &stream,bool reset)
00180 { return loadgame(stream, false,reset); }
00181
00182 bool KGame::loadgame(QDataStream &stream, bool network,bool resetgame)
00183 {
00184
00185
00186
00187 Q_INT32 c;
00188 stream >> c;
00189
00190 if (c!=cookie())
00191 {
00192 kdWarning(11001) << "Trying to load different game version we="<<cookie() << " saved=" << c << endl;
00193 bool result=false;
00194 emit signalLoadError(stream,network,(int)c,result);
00195 return result;
00196 }
00197 if (resetgame) reset();
00198
00199 uint i;
00200 stream >> i;
00201
00202
00203 stream >> d->mUniquePlayerNumber;
00204
00205 if (gameSequence())
00206 {
00207 gameSequence()->setCurrentPlayer(0);
00208 }
00209 int newseed;
00210 stream >> newseed;
00211 d->mRandom->setSeed(newseed);
00212
00213
00214
00215
00216
00217
00218
00219 dataHandler()->lockDirectEmit();
00220 KPlayer *player;
00221 for ( player=playerList()->first(); player != 0; player=playerList()->next() )
00222 {
00223 player->dataHandler()->lockDirectEmit();
00224
00225 }
00226
00227
00228 dataHandler()->load(stream);
00229
00230
00231
00232 emit signalLoadPrePlayers(stream);
00233
00234
00235 uint playercount;
00236 stream >> playercount;
00237 kdDebug(11001) << "Loading KGame " << playercount << " KPlayer objects " << endl;
00238 for (i=0;i<playercount;i++)
00239 {
00240 KPlayer *newplayer=loadPlayer(stream,network);
00241 systemAddPlayer(newplayer);
00242 }
00243
00244 Q_INT16 cookie;
00245 stream >> cookie;
00246 if (cookie==KGAME_LOAD_COOKIE) {
00247 kdDebug(11001) << " Game loaded propertly"<<endl;
00248 } else {
00249 kdError(11001) << " Game loading error. probably format error"<<endl;
00250 }
00251
00252
00253
00254
00255
00256 dataHandler()->unlockDirectEmit();
00257 for ( player=playerList()->first(); player != 0; player=playerList()->next() )
00258 {
00259 player->dataHandler()->unlockDirectEmit();
00260
00261 }
00262
00263 emit signalLoad(stream);
00264 return true;
00265 }
00266
00267 bool KGame::save(QString filename,bool saveplayers)
00268 {
00269 if (filename.isNull())
00270 {
00271 return false;
00272 }
00273 QFile f(filename);
00274 if (!f.open(IO_WriteOnly))
00275 {
00276 return false;
00277 }
00278 QDataStream s( &f );
00279 save(s,saveplayers);
00280 f.close();
00281 return true;
00282 }
00283
00284 bool KGame::save(QDataStream &stream,bool saveplayers)
00285 { return savegame(stream, false,saveplayers); }
00286
00287 bool KGame::savegame(QDataStream &stream,bool ,bool saveplayers)
00288 {
00289
00290
00291
00292 Q_INT32 c=cookie();
00293 stream << c;
00294
00295 uint p=(uint)policy();
00296 stream << p;
00297 stream << d->mUniquePlayerNumber;
00298 int newseed=(int)d->mRandom->getLong(65535);
00299 stream << newseed;
00300 d->mRandom->setSeed(newseed);
00301
00302
00303 dataHandler()->save(stream);
00304
00305
00306 emit signalSavePrePlayers(stream);
00307
00308 if (saveplayers)
00309 {
00310 savePlayers(stream,playerList());
00311 }
00312 else
00313 {
00314 stream << (uint)0;
00315 }
00316
00317 stream << (Q_INT16)KGAME_LOAD_COOKIE;
00318
00319 emit signalSave(stream);
00320 return true;
00321 }
00322
00323 void KGame::savePlayer(QDataStream &stream,KPlayer* p)
00324 {
00325
00326 stream << (Q_INT32)p->rtti();
00327 stream << (Q_INT32)p->id();
00328 stream << (Q_INT32)p->calcIOValue();
00329 p->save(stream);
00330 }
00331
00332 void KGame::savePlayers(QDataStream &stream, KGamePlayerList *list)
00333 {
00334 if (!list)
00335 {
00336 list=playerList();
00337 }
00338
00339 Q_INT32 cnt=list->count();
00340 kdDebug(11001) << "Saving KGame " << cnt << " KPlayer objects " << endl;
00341 stream << cnt;
00342 KPlayer *player;
00343 for ( player=list->first(); player != 0; player=list->next() )
00344 {
00345 savePlayer(stream,player);
00346 }
00347 }
00348
00349 KPlayer *KGame::createPlayer(int ,int ,bool )
00350 {
00351 kdWarning(11001) << " No user defined player created. Creating default KPlayer. This crashes if you have overwritten KPlayer!!!! " << endl;
00352 return new KPlayer;
00353 }
00354 KPlayer *KGame::loadPlayer(QDataStream& stream,bool isvirtual)
00355 {
00356 Q_INT32 rtti,id,iovalue;
00357 stream >> rtti >> id >> iovalue;
00358 KPlayer *newplayer=findPlayer(id);
00359 if (!newplayer)
00360 {
00361 kdDebug(11001) << k_funcinfo << "Player "<< id << " not found...asking user to create one " << endl;
00362 newplayer=createPlayer(rtti,iovalue,isvirtual);
00363
00364 }
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 newplayer->load(stream);
00377 if (isvirtual)
00378 {
00379 newplayer->setVirtual(true);
00380 }
00381 return newplayer;
00382 }
00383
00384
00385
00386 KPlayer * KGame::findPlayer(Q_UINT32 id) const
00387 {
00388 for (QPtrListIterator<KPlayer> it(d->mPlayerList); it.current(); ++it)
00389 {
00390 if (it.current()->id() == id)
00391 {
00392 return it.current();
00393 }
00394 }
00395 for (QPtrListIterator<KPlayer> it(d->mInactivePlayerList); it.current(); ++it)
00396 {
00397 if (it.current()->id() == id)
00398 {
00399 return it.current();
00400 }
00401 }
00402 return 0;
00403 }
00404
00405
00406
00407
00408
00409
00410
00411
00412 void KGame::addPlayer(KPlayer* newplayer)
00413 {
00414 kdDebug(11001) << k_funcinfo << ": " << "; maxPlayers=" << maxPlayers() << " playerCount=" << playerCount() << endl;
00415 if (!newplayer)
00416 {
00417 kdFatal(11001) << "trying to add NULL player in KGame::addPlayer()" << endl;
00418 return ;
00419 }
00420
00421 if (maxPlayers() >= 0 && (int)playerCount() >= maxPlayers())
00422 {
00423 kdWarning(11001) << "cannot add more than " << maxPlayers() << " players - deleting..." << endl;
00424 delete newplayer;
00425 return;
00426 }
00427
00428 if (newplayer->id() == 0)
00429 {
00430 d->mUniquePlayerNumber++;
00431 newplayer->setId(KGameMessage::createPlayerId(d->mUniquePlayerNumber, gameId()));
00432 kdDebug(11001) << k_funcinfo << "NEW!!! player " << newplayer << " now has id " << newplayer->id() << endl;
00433 }
00434 else
00435 {
00436
00437
00438 kdDebug(11001) << k_funcinfo << "player " << newplayer << " already has an id: " << newplayer->id() << endl;
00439 }
00440
00441 QByteArray buffer;
00442 QDataStream stream(buffer,IO_WriteOnly);
00443
00444 if (policy()==PolicyLocal || policy()==PolicyDirty)
00445 {
00446 systemAddPlayer(newplayer);
00447 }
00448 if (policy()==PolicyClean || policy()==PolicyDirty)
00449 {
00450 savePlayer(stream,newplayer);
00451
00452 if (policy()==PolicyClean)
00453 {
00454 d->mAddPlayerList.enqueue(newplayer);
00455 }
00456 sendSystemMessage(stream,(int)KGameMessage::IdAddPlayer, 0);
00457 }
00458 }
00459
00460 void KGame::systemAddPlayer(KPlayer* newplayer)
00461 {
00462 if (!newplayer)
00463 {
00464 kdFatal(11001) << "trying to add NULL player in KGame::systemAddPlayer()" << endl;
00465 return ;
00466 }
00467 if (newplayer->id() == 0)
00468 {
00469 kdWarning(11001) << k_funcinfo << "player " << newplayer << " has no ID" << endl;
00470 }
00471
00472 if (findPlayer(newplayer->id()))
00473 {
00474 kdError(11001) << "ERROR: Double adding player !!!!! NOT GOOD !!!!!! " << newplayer->id() << "...I delete it again" << endl;
00475 delete newplayer;
00476 }
00477 else
00478 {
00479 kdDebug(11001) << "Trying to add player " << newplayer <<" maxPlayers="<<maxPlayers()<<" playerCount="<<playerCount() << endl;
00480
00481 d->mPlayerList.append(newplayer);
00482 newplayer->setGame(this);
00483 kdDebug(11001) << "Player: isVirtual=" << newplayer->isVirtual() << endl;
00484 kdDebug(11001) << " id=" << newplayer->id() << " #Players="
00485 << d->mPlayerList.count() << " added " << newplayer
00486 << " (virtual=" << newplayer->isVirtual() << ")" << endl;
00487 emit signalPlayerJoinedGame(newplayer);
00488 }
00489 }
00490
00491
00492 void KGame::playerDeleted(KPlayer *player)
00493 {
00494 kdDebug(11001) << k_funcinfo << ": id (" << player->id() << ") to be removed " << player << endl;
00495
00496 if (policy()==PolicyLocal || policy()==PolicyDirty)
00497 {
00498 systemRemovePlayer(player,false);
00499 }
00500 if (policy()==PolicyClean || policy()==PolicyDirty)
00501 {
00502 if (!player->isVirtual())
00503 {
00504 kdDebug(11001) << k_funcinfo << ": sending IdRemovePlayer "<<player->id() << endl;
00505 sendSystemMessage(player->id(), KGameMessage::IdRemovePlayer, 0);
00506 }
00507 }
00508 }
00509
00510 bool KGame::removePlayer(KPlayer * player, Q_UINT32 receiver)
00511 {
00512 if (!player)
00513 {
00514 kdFatal(11001) << "trying to remove NULL player in KGame::removePlayer()" << endl;
00515 return false;
00516 }
00517 kdDebug(11001) << k_funcinfo << ": id (" << player->id() << ") to be removed " << player << endl;
00518
00519 if (policy()==PolicyLocal || policy()==PolicyDirty)
00520 {
00521 systemRemovePlayer(player,true);
00522 }
00523 if (policy()==PolicyClean || policy()==PolicyDirty)
00524 {
00525 kdDebug(11001) << k_funcinfo << ": sending IdRemovePlayer "<<player->id() << endl;
00526 sendSystemMessage(player->id(),KGameMessage::IdRemovePlayer, receiver);
00527 }
00528 return true;
00529
00530 }
00531
00532 void KGame::systemRemovePlayer(KPlayer* player,bool deleteit)
00533 {
00534 kdDebug(11001) << k_funcinfo << endl;
00535 if (!player)
00536 {
00537 kdWarning(11001) << "cannot remove NULL player" << endl;
00538 return;
00539 }
00540 if (!systemRemove(player,deleteit))
00541 {
00542 kdWarning(11001) << "player " << player << "(" << player->id() << ") Could not be found!" << endl;
00543 }
00544
00545 if (gameStatus()==(int)Run && playerCount()<minPlayers())
00546 {
00547 kdWarning(11001) << k_funcinfo ": not enough players, PAUSING game\n" << endl;
00548 setGameStatus(Pause);
00549 }
00550 }
00551
00552 bool KGame::systemRemove(KPlayer* p,bool deleteit)
00553 {
00554 if (!p)
00555 {
00556 kdWarning(11001) << "cannot remove NULL player" << endl;
00557 return false;
00558 }
00559 bool result;
00560 kdDebug(11001) << k_funcinfo << ": Player (" << p->id() << ") to be removed " << p << endl;
00561
00562 if (d->mPlayerList.count() == 0)
00563 {
00564 result = false;
00565 }
00566 else
00567 {
00568 result = d->mPlayerList.remove(p);
00569 }
00570
00571 emit signalPlayerLeftGame(p);
00572
00573 p->setGame(0);
00574 if (deleteit)
00575 {
00576 delete p;
00577 }
00578
00579 return result;
00580 }
00581
00582 bool KGame::inactivatePlayer(KPlayer* player)
00583 {
00584 if (!player)
00585 {
00586 return false;
00587 }
00588 kdDebug(11001) << "Inactivate player " << player->id() << endl;
00589
00590 if (policy()==PolicyLocal || policy()==PolicyDirty)
00591 {
00592 systemInactivatePlayer(player);
00593 }
00594 if (policy()==PolicyClean || policy()==PolicyDirty)
00595 {
00596 sendSystemMessage(player->id(), KGameMessage::IdInactivatePlayer);
00597 }
00598
00599 return true;
00600 }
00601
00602 bool KGame::systemInactivatePlayer(KPlayer* player)
00603 {
00604 if (!player || !player->isActive())
00605 {
00606 return false;
00607 }
00608 kdDebug(11001) << " Inactivate player " << player->id() << endl;
00609
00610 int pid=player->id();
00611
00612 if (player->isVirtual())
00613 {
00614 systemRemovePlayer(player,true);
00615 }
00616 else
00617 {
00618 d->mPlayerList.remove(player);
00619 d->mInactivePlayerList.prepend(player);
00620 player->setActive(false);
00621 }
00622 emit signalPlayerLeftGame(player);
00623 if (isAdmin())
00624 {
00625 d->mInactiveIdList.prepend(pid);
00626 }
00627 return true;
00628 }
00629
00630 bool KGame::activatePlayer(KPlayer * player)
00631 {
00632 if (!player)
00633 {
00634 return false;
00635 }
00636 kdDebug(11001) << k_funcinfo << ": activate " << player->id() << endl;
00637 if (policy()==PolicyLocal || policy()==PolicyDirty)
00638 {
00639 systemActivatePlayer(player);
00640 }
00641 if (policy()==PolicyClean || policy()==PolicyDirty)
00642 {
00643 sendSystemMessage(player->id(), KGameMessage::IdActivatePlayer);
00644 }
00645 return true;
00646 }
00647
00648 bool KGame::systemActivatePlayer(KPlayer* player)
00649 {
00650 if (!player || player->isActive())
00651 {
00652 return false;
00653 }
00654 kdDebug(11001) << k_funcinfo << ": activate " << player->id() << endl;
00655
00656 d->mInactivePlayerList.remove(player);
00657 player->setActive(true);
00658 addPlayer(player);
00659 if (isAdmin())
00660 {
00661 d->mInactiveIdList.remove(player->id());
00662 }
00663 return true;
00664 }
00665
00666
00667
00668 void KGame::setMaxPlayers(uint maxnumber)
00669 { if (isAdmin()) { d->mMaxPlayer.changeValue(maxnumber); } }
00670
00671 void KGame::setMinPlayers(uint minnumber)
00672 { if (isAdmin()) { d->mMinPlayer.changeValue(minnumber); } }
00673
00674 uint KGame::minPlayers() const
00675 { return d->mMinPlayer.value(); }
00676
00677 int KGame::maxPlayers() const
00678 { return d->mMaxPlayer.value(); }
00679
00680 uint KGame::playerCount() const
00681 { return d->mPlayerList.count(); }
00682
00683 int KGame::gameStatus() const
00684 { return d->mGameStatus.value(); }
00685
00686 bool KGame::isRunning() const
00687 { return d->mGameStatus.value() == Run; }
00688
00689 KGamePropertyHandler* KGame::dataHandler() const
00690 { return d->mProperties; }
00691
00692
00693 KGame::KGamePlayerList* KGame::inactivePlayerList()
00694 { return &d->mInactivePlayerList; }
00695
00696 const KGame::KGamePlayerList* KGame::inactivePlayerList() const
00697 { return &d->mInactivePlayerList; }
00698
00699 KGame::KGamePlayerList* KGame::playerList()
00700 { return &d->mPlayerList; }
00701
00702 const KGame::KGamePlayerList* KGame::playerList() const
00703 { return &d->mPlayerList; }
00704
00705 KRandomSequence* KGame::random() const
00706 { return d->mRandom; }
00707
00708
00709 bool KGame::sendPlayerInput(QDataStream &msg, KPlayer *player, Q_UINT32 sender)
00710 {
00711 if (!player)
00712 {
00713 kdError(11001) << k_funcinfo << ": NULL player" << endl;
00714 return false;
00715 }
00716 if (!isRunning())
00717 {
00718 kdError(11001) << k_funcinfo << ": game not running" << endl;
00719 return false;
00720 }
00721
00722 kdDebug(11001) << k_funcinfo << ": transmitting playerInput over network" << endl;
00723 sendSystemMessage(msg, (int)KGameMessage::IdPlayerInput, player->id(), sender);
00724 return true;
00725 }
00726
00727 bool KGame::systemPlayerInput(QDataStream &msg, KPlayer *player, Q_UINT32 sender)
00728 {
00729 if (!player)
00730 {
00731 kdError(11001) << k_funcinfo << ": NULL player" << endl;
00732 return false;
00733 }
00734 if (!isRunning())
00735 {
00736 kdError(11001) << k_funcinfo << ": game not running" << endl;
00737 return false;
00738 }
00739 kdDebug(11001) << "KGame: Got playerInput from messageServer... sender: " << sender << endl;
00740 if (playerInput(msg,player))
00741 {
00742 playerInputFinished(player);
00743 }
00744 else
00745 {
00746 kdDebug(11001) << k_funcinfo<<": switching off player input"<<endl;
00747
00748
00749 if (!player->asyncInput())
00750 {
00751 player->setTurn(false);
00752 }
00753 }
00754 return true;
00755 }
00756
00757
00758 KPlayer * KGame::playerInputFinished(KPlayer *player)
00759 {
00760 kdDebug(11001) << k_funcinfo<<"player input finished for "<<player->id()<<endl;
00761
00762 int gameOver = 0;
00763 if (gameSequence())
00764 {
00765 gameSequence()->setCurrentPlayer(player);
00766 }
00767
00768 gameOver = checkGameOver(player);
00769 if (gameOver!=0)
00770 {
00771 if (player)
00772 {
00773 player->setTurn(false);
00774 }
00775 setGameStatus(End);
00776 emit signalGameOver(gameOver,player,this);
00777 }
00778 else if (!player->asyncInput())
00779 {
00780 player->setTurn(false);
00781 if (gameSequence())
00782 {
00783 QTimer::singleShot(0,this,SLOT(prepareNext()));
00784 }
00785 }
00786 return player;
00787 }
00788
00789
00790 int KGame::checkGameOver(KPlayer *player)
00791 {
00792 if (gameSequence())
00793 {
00794 return gameSequence()->checkGameOver(player);
00795 }
00796 return 0;
00797 }
00798
00799 void KGame::setGameSequence(KGameSequence* sequence)
00800 {
00801 delete d->mGameSequence;
00802 d->mGameSequence = sequence;
00803 if (d->mGameSequence)
00804 {
00805 d->mGameSequence->setGame(this);
00806 }
00807 }
00808
00809 KGameSequence* KGame::gameSequence() const
00810 {
00811 return d->mGameSequence;
00812 }
00813
00814 void KGame::prepareNext()
00815 {
00816 if (gameSequence())
00817 {
00818
00819 nextPlayer(gameSequence()->currentPlayer());
00820 }
00821 }
00822
00823 KPlayer *KGame::nextPlayer(KPlayer *last,bool exclusive)
00824 {
00825 if (gameSequence())
00826 {
00827 return gameSequence()->nextPlayer(last, exclusive);
00828 }
00829 return 0;
00830 }
00831
00832 void KGame::setGameStatus(int status)
00833 {
00834 kdDebug(11001) << k_funcinfo << ": GAMESTATUS CHANGED to" << status << endl;
00835 if (status==(int)Run && playerCount()<minPlayers())
00836 {
00837 kdDebug(11001) << k_funcinfo << ": not enough players, pausing game\n" << endl;
00838 status=Pause;
00839 }
00840 d->mGameStatus = status;
00841 }
00842
00843 void KGame::networkTransmission(QDataStream &stream, int msgid, Q_UINT32 receiver, Q_UINT32 sender, Q_UINT32 )
00844 {
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854 emit signalMessageUpdate(msgid, receiver, sender);
00855 if (KGameMessage::isPlayer(receiver))
00856 {
00857
00858 KPlayer *p=findPlayer(receiver);
00859 if (p && p->isActive())
00860 {
00861 p->networkTransmission(stream,msgid,sender);
00862 return;
00863 }
00864 if (p)
00865 {
00866 kdDebug(11001) << "player is here but not active" << endl;
00867 }
00868 else
00869 {
00870 kdDebug(11001) << "no player found" << endl;
00871 }
00872 }
00873
00874
00875
00876
00877 if (d->mProperties->processMessage(stream, msgid, sender == gameId()))
00878 {
00879
00880 return ;
00881 }
00882
00883 switch(msgid)
00884 {
00885 case KGameMessage::IdSetupGame:
00886 {
00887 Q_INT16 v;
00888 Q_INT32 c;
00889 stream >> v >> c;
00890 kdDebug(11001) << " ===================> (Client) " << k_funcinfo << ": Got IdSetupGame ================== " << endl;
00891 kdDebug(11001) << "our game id is " << gameId() << " Lib version=" << v << " App Cookie=" << c << endl;
00892
00893 if (c!=cookie())
00894 {
00895 kdError(11001) << "IdGameSetup: Negotiate Game: cookie mismatch I'am="<<cookie()<<" master="<<c<<endl;
00896 sendError(KGameError::Cookie, KGameError::errCookie(cookie(), c));
00897 disconnect();
00898 }
00899 else if (v!=KGameMessage::version())
00900 {
00901 sendError(KGameError::Version, KGameError::errVersion(v));
00902 disconnect();
00903 }
00904 else
00905 {
00906 setupGame(sender);
00907 }
00908 kdDebug(11001) << "========== (Client) Setup game done\n";
00909 }
00910 break;
00911 case KGameMessage::IdSetupGameContinue:
00912 {
00913 kdDebug(11001) << "=====>(Master) " << k_funcinfo << " - IdSetupGameContinue" << endl;
00914 setupGameContinue(stream, sender);
00915 }
00916 break;
00917 case KGameMessage::IdActivatePlayer:
00918 {
00919 int id;
00920 stream >> id;
00921 kdDebug(11001) << "Got IdActivatePlayer id=" << id << endl;
00922 if (sender!=gameId() || policy()!=PolicyDirty)
00923 {
00924 systemActivatePlayer(findPlayer(id));
00925 }
00926 }
00927 break;
00928 case KGameMessage::IdInactivatePlayer:
00929 {
00930 int id;
00931 stream >> id;
00932 kdDebug(11001) << "Got IdInactivatePlayer id=" << id << endl;
00933 if (sender!=gameId() || policy()!=PolicyDirty)
00934 {
00935 systemInactivatePlayer(findPlayer(id));
00936 }
00937 }
00938 break;
00939 case KGameMessage::IdAddPlayer:
00940 {
00941 kdDebug(11001) << k_funcinfo << ": Got IdAddPlayer" << endl;
00942 if (sender!=gameId() || policy()!=PolicyDirty)
00943 {
00944 KPlayer *newplayer=0;
00945
00946 if (sender==gameId())
00947 {
00948 kdDebug(11001) << "dequeue previously added player" << endl;
00949 newplayer = d->mAddPlayerList.dequeue();
00950 }
00951 else
00952 {
00953 newplayer=loadPlayer(stream,true);
00954 }
00955 systemAddPlayer(newplayer);
00956
00957 }
00958 }
00959 break;
00960 case KGameMessage::IdRemovePlayer:
00961 {
00962 int id;
00963 stream >> id;
00964 kdDebug(11001) << k_funcinfo << ": Got IdRemovePlayer " << id << endl;
00965 KPlayer *p=findPlayer(id);
00966 if (p)
00967 {
00968
00969 if (sender!=gameId() || policy()!=PolicyDirty)
00970 {
00971 systemRemovePlayer(p,true);
00972 }
00973 }
00974 else
00975 {
00976 kdWarning(11001) << k_funcinfo << "Cannot find player " << id << endl;
00977 }
00978 }
00979 break;
00980 case KGameMessage::IdGameLoad:
00981 {
00982 kdDebug(11001) << "====> (Client) " << k_funcinfo << ": Got IdGameLoad" << endl;
00983 loadgame(stream,true,false);
00984 }
00985 break;
00986 case KGameMessage::IdGameSetupDone:
00987 {
00988 int cid;
00989 stream >> cid;
00990 kdDebug(11001) << "====> (CLIENT) " << k_funcinfo << ": Got IdGameSetupDone for client "
00991 << cid << " we are =" << gameId() << endl;
00992 sendSystemMessage(gameId(), KGameMessage::IdGameConnected, 0);
00993 }
00994 break;
00995 case KGameMessage::IdGameConnected:
00996 {
00997 int cid;
00998 stream >> cid;
00999 kdDebug(11001) << "====> (ALL) " << k_funcinfo << ": Got IdGameConnected for client "<< cid << " we are =" << gameId() << endl;
01000 emit signalClientJoinedGame(cid,this);
01001 }
01002 break;
01003
01004 case KGameMessage::IdSyncRandom:
01005 {
01006 int newseed;
01007 stream >> newseed;
01008 kdDebug(11001) << "CLIENT: setting random seed to " << newseed << endl;
01009 d->mRandom->setSeed(newseed);
01010 }
01011 break;
01012 case KGameMessage::IdDisconnect:
01013 {
01014
01015
01016 if (sender != gameId())
01017 {
01018 kdDebug(11001) << "client " << sender << " leaves game" << endl;
01019 return;
01020 }
01021 kdDebug(11001) << "leaving the game" << endl;
01022
01023
01024
01025 setMaster();
01026 }
01027 break;
01028 default:
01029 {
01030 if (msgid < KGameMessage::IdUser)
01031 {
01032 kdError(11001) << "incorrect message id " << msgid << " - emit anyway"
01033 << endl;
01034 }
01035 kdDebug(11001) << k_funcinfo << ": User data msgid " << msgid << endl;
01036 emit signalNetworkData(msgid - KGameMessage::IdUser,((QBuffer*)stream.device())->readAll(),receiver,sender);
01037 }
01038 break;
01039 }
01040
01041 }
01042
01043
01044
01045
01046 void KGame::setupGameContinue(QDataStream& stream, Q_UINT32 sender)
01047 {
01048 KPlayer *player;
01049 Q_INT32 cnt;
01050 int i;
01051 stream >> cnt;
01052
01053 QValueList<int> inactivateIds;
01054
01055 KGamePlayerList newPlayerList;
01056 newPlayerList.setAutoDelete(true);
01057 for (i=0;i<cnt;i++)
01058 {
01059 player=loadPlayer(stream,true);
01060 kdDebug(11001) << " Master got player " << player->id() <<" rawgame=" << KGameMessage::rawGameId(player->id()) << " from sender " << sender << endl;
01061 if (KGameMessage::rawGameId(player->id()) != sender)
01062 {
01063 kdError(11001) << "Client tries to add player with wrong game id - cheat possible" << endl;
01064 }
01065 else
01066 {
01067 newPlayerList.append(player);
01068 kdDebug(11001) << " newplayerlist appended " << player->id() << endl;
01069 }
01070 }
01071
01072 newPlayersJoin(playerList(),&newPlayerList,inactivateIds);
01073
01074
01075 kdDebug(11001) << " Master calculates how many players to activate client has cnt=" << cnt << endl;
01076 kdDebug(11001) << " The game has " << playerCount() << " active players" << endl;
01077 kdDebug(11001) << " The user deactivated "<< inactivateIds.count() << " player already " << endl;
01078 kdDebug(11001) << " MaxPlayers for this game is " << maxPlayers() << endl;
01079
01080
01081
01082
01083 kdDebug(11001) << " havePlayers " << cnt+playerCount()-inactivateIds.count() << endl;
01084 while (maxPlayers() > 0 && maxPlayers() < (int)(cnt+playerCount() - inactivateIds.count()))
01085 {
01086 kdDebug(11001) << " Still to deacticvate "
01087 << (int)(cnt+playerCount()-inactivateIds.count())-(int)maxPlayers()
01088 << endl;
01089 KPlayer *currentPlayer=0;
01090 int currentPriority=0x7fff;
01091
01092
01093 for ( player=newPlayerList.first(); player != 0; player=newPlayerList.next() )
01094 {
01095
01096 if (inactivateIds.find(player->id())!=inactivateIds.end())
01097 {
01098 continue;
01099 }
01100 if (player->networkPriority()<currentPriority)
01101 {
01102 currentPriority=player->networkPriority();
01103 currentPlayer=player;
01104 }
01105 }
01106
01107
01108
01109 for ( player=d->mPlayerList.first(); player != 0; player=d->mPlayerList.next() )
01110 {
01111
01112 if (inactivateIds.find(player->id())!=inactivateIds.end())
01113 {
01114 continue;
01115 }
01116 if (player->networkPriority()<currentPriority)
01117 {
01118 currentPriority=player->networkPriority();
01119 currentPlayer=player;
01120 }
01121 }
01122
01123
01124 if (currentPlayer)
01125 {
01126 kdDebug(11001) << "Marking player " << currentPlayer->id() << " for inactivation" << endl;
01127 inactivateIds.append(currentPlayer->id());
01128 }
01129 else
01130 {
01131 kdError(11001) << "Couldn't find a player to dectivate..That is not so good..." << endl;
01132 break;
01133 }
01134 }
01135
01136 kdDebug(11001) << "Alltogether deactivated " << inactivateIds.count() << " players" << endl;
01137
01138 QValueList<int>::Iterator it;
01139 for ( it = inactivateIds.begin(); it != inactivateIds.end(); ++it )
01140 {
01141 int pid=*it;
01142 kdDebug(11001) << " pid=" << pid << endl;
01143 }
01144
01145
01146
01147 for ( it = inactivateIds.begin(); it != inactivateIds.end(); ++it )
01148 {
01149 int pid=*it;
01150 if (KGameMessage::rawGameId(pid) == sender)
01151 {
01152 continue;
01153 }
01154 kdDebug(11001) << " -> the network needs to deactivate " << pid <<endl;
01155 player=findPlayer(pid);
01156 if (player)
01157 {
01158
01159 systemInactivatePlayer(player);
01160 if (policy()!=PolicyLocal)
01161 {
01162 sendSystemMessage(player->id(), KGameMessage::IdInactivatePlayer);
01163 }
01164 }
01165 else
01166 {
01167 kdError(11001) << " We should deactivate a player, but cannot find it...not good." << endl;
01168 }
01169 }
01170
01171
01172 for ( player=newPlayerList.first(); player != 0; player=newPlayerList.next() )
01173 {
01174 kdDebug(11001) << " newplayerlist contains " << player->id() << endl;
01175
01176 if (inactivateIds.find(player->id())!=inactivateIds.end())
01177 {
01178 continue;
01179 }
01180 kdDebug(11001) << " -> the client can ******** reactivate ******** " << player->id() << endl;
01181 sendSystemMessage(player->id(), KGameMessage::IdActivatePlayer, sender);
01182 }
01183
01184
01185 QByteArray bufferS;
01186 QDataStream streamS(bufferS,IO_WriteOnly);
01187
01188 savegame(streamS,true,true);
01189 sendSystemMessage(streamS,KGameMessage::IdGameLoad,sender);
01190
01191
01192
01193 sendSystemMessage(sender, KGameMessage::IdGameSetupDone, sender);
01194 }
01195
01196
01197
01198 void KGame::setupGame(Q_UINT32 sender)
01199 {
01200 QByteArray bufferS;
01201 QDataStream streamS(bufferS,IO_WriteOnly);
01202
01203
01204 KGamePlayerList mTmpList(d->mPlayerList);
01205 Q_INT32 cnt=mTmpList.count();
01206 kdDebug(11001) << "Client: playerlistcount=" << d->mPlayerList.count() << " tmplistcout=" << cnt << endl;
01207
01208 streamS << cnt;
01209
01210 QPtrListIterator<KPlayer> it(mTmpList);
01211 KPlayer *player;
01212 while (it.current())
01213 {
01214 player=it.current();
01215 systemInactivatePlayer(player);
01216
01217 player->setId(KGameMessage::createPlayerId(player->id(),gameId()));
01218
01219
01220 savePlayer(streamS,player);
01221
01222 ++it;
01223 --cnt;
01224 }
01225 if (d->mPlayerList.count() > 0 || cnt!=0)
01226 {
01227 kdFatal(11001) << "KGame::setupGame(): Player list is not empty! or cnt!=0=" <<cnt << endl;
01228 }
01229
01230 sendSystemMessage(streamS,KGameMessage::IdSetupGameContinue,sender);
01231 }
01232
01233
01234 void KGame::syncRandom()
01235 {
01236 int newseed=(int)d->mRandom->getLong(65535);
01237 sendSystemMessage(newseed,KGameMessage::IdSyncRandom);
01238 d->mRandom->setSeed(newseed);
01239 }
01240
01241 void KGame::Debug()
01242 {
01243 KGameNetwork::Debug();
01244 kdDebug(11001) << "------------------- KGAME -------------------------" << endl;
01245 kdDebug(11001) << "this: " << this << endl;
01246 kdDebug(11001) << "uniquePlayer " << d->mUniquePlayerNumber << endl;
01247 kdDebug(11001) << "gameStatus " << gameStatus() << endl;
01248 kdDebug(11001) << "MaxPlayers : " << maxPlayers() << endl;
01249 kdDebug(11001) << "NoOfPlayers : " << playerCount() << endl;
01250 kdDebug(11001) << "NoOfInactive: " << d->mInactivePlayerList.count() << endl;
01251 kdDebug(11001) << "---------------------------------------------------" << endl;
01252 }
01253
01254 void KGame::slotClientConnected(Q_UINT32 clientID)
01255 {
01256 if (isAdmin())
01257 {
01258 negotiateNetworkGame(clientID);
01259 }
01260 }
01261
01262 void KGame::slotServerDisconnected()
01263 {
01264 kdDebug(11001) << "======= SERVER DISCONNECT ======="<<endl;
01265 kdDebug(11001) << "+++ (CLIENT)++++++++" << k_funcinfo << ": our GameID="<<gameId() << endl;
01266
01267 int oldgamestatus=gameStatus();
01268
01269 KPlayer *player;
01270 KGamePlayerList removeList;
01271 kdDebug(11001) << "Playerlist of client=" << d->mPlayerList.count() << " count" << endl;
01272 kdDebug(11001) << "Inactive Playerlist of client=" << d->mInactivePlayerList.count() << " count" << endl;
01273 for ( player=d->mPlayerList.first(); player != 0; player=d->mPlayerList.next() )
01274 {
01275
01276 if (KGameMessage::rawGameId(player->id()) != gameId() && gameId()!=0)
01277 {
01278 kdDebug(11001) << "Player " << player->id() << " belongs to a removed game" << endl;
01279 removeList.append(player);
01280 }
01281 }
01282
01283 for ( player=removeList.first(); player != 0; player=removeList.next() )
01284 {
01285 bool remove = true;
01286 emit signalReplacePlayerIO(player, &remove);
01287 if (remove)
01288 {
01289 kdDebug(11001) << " ---> Removing player " << player->id() << endl;
01290 systemRemovePlayer(player,true);
01291 }
01292 }
01293
01294 setMaster();
01295 kdDebug(11001) << " our game id is after setMaster " << gameId() << endl;
01296
01297 KGamePlayerList mReList(d->mInactivePlayerList);
01298 for ( player=mReList.first(); player != 0; player=mReList.next() )
01299 {
01300
01301 if ((int)playerCount()<maxPlayers() || maxPlayers()<0)
01302 {
01303 systemActivatePlayer(player);
01304 }
01305 }
01306 kdDebug(11001) << " Players activated player-cnt=" << playerCount() << endl;
01307
01308 for ( player=d->mPlayerList.first(); player != 0; player=d->mPlayerList.next() )
01309 {
01310 int oldid=player->id();
01311 d->mUniquePlayerNumber++;
01312 player->setId(KGameMessage::createPlayerId(d->mUniquePlayerNumber,gameId()));
01313 kdDebug(11001) << "Player id " << oldid <<" changed to " << player->id() << " as we are now local" << endl;
01314 }
01315
01316 Debug();
01317 for ( player=d->mPlayerList.first(); player != 0; player=d->mPlayerList.next() )
01318 {
01319 player->Debug();
01320 }
01321 kdDebug(11001) << "+++++++++++" << k_funcinfo << " DONE=" << endl;
01322 emit signalClientLeftGame(0,oldgamestatus,this);
01323 }
01324
01325 void KGame::slotClientDisconnected(Q_UINT32 clientID,bool )
01326 {
01327 kdDebug(11001) << "++++(SERVER)+++++++" << k_funcinfo << " clientId=" << clientID << endl;
01328
01329 int oldgamestatus=gameStatus();
01330
01331 KPlayer *player;
01332 KGamePlayerList removeList;
01333 kdDebug(11001) << "Playerlist of client=" << d->mPlayerList.count() << " count" << endl;
01334 for ( player=d->mPlayerList.first(); player != 0; player=d->mPlayerList.next() )
01335 {
01336 if (KGameMessage::rawGameId(player->id())==clientID)
01337 {
01338 kdDebug(11001) << "Player " << player->id() << " belongs to the removed game" << endl;
01339 removeList.append(player);
01340 }
01341 }
01342
01343 for ( player=removeList.first(); player != 0; player=removeList.next() )
01344 {
01345
01346 bool remove = true;
01347 emit signalReplacePlayerIO(player, &remove);
01348 if (remove) {
01349
01350 kdDebug(11001) << " ---> Removing player " << player->id() << endl;
01351 removePlayer(player,0);
01352 }
01353 }
01354
01355
01356
01357 for (unsigned int idx=0;idx<d->mInactiveIdList.count();idx++)
01358 {
01359 QValueList<int>::Iterator it1 = d->mInactiveIdList.at(idx);
01360 player = findPlayer(*it1);
01361 if (((int)playerCount() < maxPlayers() || maxPlayers() < 0) && player && KGameMessage::rawGameId(*it1) != clientID)
01362 {
01363 activatePlayer(player);
01364 }
01365 }
01366 emit signalClientLeftGame(clientID,oldgamestatus,this);
01367 }
01368
01369
01370
01371
01372
01373
01374
01375
01376 void KGame::negotiateNetworkGame(Q_UINT32 clientID)
01377 {
01378 kdDebug(11001) << "===========================" << k_funcinfo << ": clientID=" << clientID << " =========================== "<< endl;
01379 if (!isAdmin())
01380 {
01381 kdError(11001) << k_funcinfo << ": Serious WARNING..only gameAdmin should call this" << endl;
01382 return ;
01383 }
01384
01385 QByteArray buffer;
01386 QDataStream streamGS(buffer,IO_WriteOnly);
01387
01388
01389
01390
01391
01392
01393 Q_INT16 v=KGameMessage::version();
01394 Q_INT32 c=cookie();
01395 streamGS << v << c;
01396 sendSystemMessage(streamGS, KGameMessage::IdSetupGame, clientID);
01397 }
01398
01399 bool KGame::sendGroupMessage(const QByteArray &msg, int msgid, Q_UINT32 sender, const QString& group)
01400 {
01401
01402
01403 KPlayer *player;
01404 for ( player=d->mPlayerList.first(); player != 0; player=d->mPlayerList.next() )
01405 {
01406 if (player && player->group()==group)
01407 {
01408 sendMessage(msg,msgid,player->id(), sender);
01409 }
01410 }
01411 return true;
01412 }
01413
01414 bool KGame::sendGroupMessage(const QDataStream &msg, int msgid, Q_UINT32 sender, const QString& group)
01415 { return sendGroupMessage(((QBuffer*)msg.device())->buffer(), msgid, sender, group); }
01416
01417 bool KGame::sendGroupMessage(const QString& msg, int msgid, Q_UINT32 sender, const QString& group)
01418 {
01419 QByteArray buffer;
01420 QDataStream stream(buffer, IO_WriteOnly);
01421 stream << msg;
01422 return sendGroupMessage(stream, msgid, sender, group);
01423 }
01424
01425 bool KGame::addProperty(KGamePropertyBase* data)
01426 { return dataHandler()->addProperty(data); }
01427
01428 bool KGame::sendPlayerProperty(int msgid, QDataStream& s, Q_UINT32 playerId)
01429 { return sendSystemMessage(s, msgid, playerId); }
01430
01431 void KGame::sendProperty(int msgid, QDataStream& stream, bool* sent)
01432 {
01433 bool s = sendSystemMessage(stream, msgid);
01434 if (s)
01435 {
01436 *sent = true;
01437 }
01438 }
01439
01440 void KGame::emitSignal(KGamePropertyBase *me)
01441 {
01442 emit signalPropertyChanged(me,this);
01443 }
01444
01445 KGamePropertyBase* KGame::findProperty(int id) const
01446 { return d->mProperties->find(id); }
01447
01448 KGame::GamePolicy KGame::policy() const
01449 {
01450 return d->mPolicy;
01451 }
01452 void KGame::setPolicy(GamePolicy p,bool recursive)
01453 {
01454
01455 d->mPolicy=p;
01456 if (recursive)
01457 {
01458
01459 dataHandler()->setPolicy((KGamePropertyBase::PropertyPolicy)p,false);
01460
01461
01462 for (QPtrListIterator<KPlayer> it(d->mPlayerList); it.current(); ++it)
01463 {
01464 it.current()->dataHandler()->setPolicy((KGamePropertyBase::PropertyPolicy)p,false);
01465 }
01466 for (QPtrListIterator<KPlayer> it(d->mInactivePlayerList); it.current(); ++it)
01467 {
01468 it.current()->dataHandler()->setPolicy((KGamePropertyBase::PropertyPolicy)p,false);
01469 }
01470 }
01471 }
01472
01473
01474
01475