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 kdDebug(11001) <<
" ---> Removing player " << player->
id() << endl;
01286
systemRemovePlayer(player,
true);
01287 }
01288
01289 setMaster();
01290 kdDebug(11001) <<
" our game id is after setMaster " <<
gameId() << endl;
01291
01292
KGamePlayerList mReList(d->mInactivePlayerList);
01293
for ( player=mReList.first(); player != 0; player=mReList.next() )
01294 {
01295
01296
if ((
int)
playerCount()<
maxPlayers() ||
maxPlayers()<0)
01297 {
01298
systemActivatePlayer(player);
01299 }
01300 }
01301 kdDebug(11001) <<
" Players activated player-cnt=" <<
playerCount() << endl;
01302
01303
for ( player=d->mPlayerList.first(); player != 0; player=d->mPlayerList.next() )
01304 {
01305
int oldid=player->
id();
01306 player->
setId(KGameMessage::createPlayerId(player->
id(),
gameId()));
01307 kdDebug(11001) <<
"Player id " << oldid <<
" changed to " << player->
id() <<
" as we are now local" << endl;
01308 }
01309
01310
Debug();
01311
for ( player=d->mPlayerList.first(); player != 0; player=d->mPlayerList.next() )
01312 {
01313 player->
Debug();
01314 }
01315 kdDebug(11001) <<
"+++++++++++" << k_funcinfo <<
" DONE=" << endl;
01316 emit
signalClientLeftGame(0,oldgamestatus,
this);
01317 }
01318
01319 void KGame::slotClientDisconnected(Q_UINT32 clientID,
bool )
01320 {
01321 kdDebug(11001) <<
"++++(SERVER)+++++++" << k_funcinfo <<
" clientId=" << clientID << endl;
01322
01323
int oldgamestatus=
gameStatus();
01324
01325
KPlayer *player;
01326
KGamePlayerList removeList;
01327 kdDebug(11001) <<
"Playerlist of client=" << d->mPlayerList.count() <<
" count" << endl;
01328
for ( player=d->mPlayerList.first(); player != 0; player=d->mPlayerList.next() )
01329 {
01330
if (KGameMessage::rawGameId(player->
id())==clientID)
01331 {
01332 kdDebug(11001) <<
"Player " << player->
id() <<
" belongs to the removed game" << endl;
01333 removeList.append(player);
01334 }
01335 }
01336
01337
for ( player=removeList.first(); player != 0; player=removeList.next() )
01338 {
01339
01340
bool remove =
true;
01341 emit
signalReplacePlayerIO(player, &remove);
01342
if (remove) {
01343
01344 kdDebug(11001) <<
" ---> Removing player " << player->
id() << endl;
01345
removePlayer(player,0);
01346 }
01347 }
01348
01349
01350
01351
for (
unsigned int idx=0;idx<d->mInactiveIdList.count();idx++)
01352 {
01353
QValueList<int>::Iterator it1 = d->mInactiveIdList.at(idx);
01354 player =
findPlayer(*it1);
01355
if (((
int)
playerCount() <
maxPlayers() ||
maxPlayers() < 0) && player && KGameMessage::rawGameId(*it1) != clientID)
01356 {
01357
activatePlayer(player);
01358 }
01359 }
01360 emit
signalClientLeftGame(clientID,oldgamestatus,
this);
01361 }
01362
01363
01364
01365
01366
01367
01368
01369
01370 void KGame::negotiateNetworkGame(Q_UINT32 clientID)
01371 {
01372 kdDebug(11001) <<
"===========================" << k_funcinfo <<
": clientID=" << clientID <<
" =========================== "<< endl;
01373
if (!
isAdmin())
01374 {
01375 kdError(11001) << k_funcinfo <<
": Serious WARNING..only gameAdmin should call this" << endl;
01376
return ;
01377 }
01378
01379
QByteArray buffer;
01380
QDataStream streamGS(buffer,IO_WriteOnly);
01381
01382
01383
01384
01385
01386
01387 Q_INT16 v=KGameMessage::version();
01388 Q_INT32 c=
cookie();
01389 streamGS << v << c;
01390
sendSystemMessage(streamGS, KGameMessage::IdSetupGame, clientID);
01391 }
01392
01393 bool KGame::sendGroupMessage(
const QByteArray &msg,
int msgid, Q_UINT32 sender,
const QString& group)
01394 {
01395
01396
01397
KPlayer *player;
01398
for ( player=d->mPlayerList.first(); player != 0; player=d->mPlayerList.next() )
01399 {
01400
if (player && player->
group()==group)
01401 {
01402
sendMessage(msg,msgid,player->
id(), sender);
01403 }
01404 }
01405
return true;
01406 }
01407
01408
bool KGame::sendGroupMessage(
const QDataStream &msg,
int msgid, Q_UINT32 sender,
const QString& group)
01409 {
return sendGroupMessage(((
QBuffer*)msg.device())->buffer(), msgid, sender, group); }
01410
01411
bool KGame::sendGroupMessage(
const QString& msg,
int msgid, Q_UINT32 sender,
const QString& group)
01412 {
01413
QByteArray buffer;
01414
QDataStream stream(buffer, IO_WriteOnly);
01415 stream << msg;
01416
return sendGroupMessage(stream, msgid, sender, group);
01417 }
01418
01419 bool KGame::addProperty(
KGamePropertyBase* data)
01420 {
return dataHandler()->
addProperty(data); }
01421
01422 bool KGame::sendPlayerProperty(
int msgid,
QDataStream& s, Q_UINT32 playerId)
01423 {
return sendSystemMessage(s, msgid, playerId); }
01424
01425 void KGame::sendProperty(
int msgid,
QDataStream& stream,
bool* sent)
01426 {
01427
bool s =
sendSystemMessage(stream, msgid);
01428
if (s)
01429 {
01430 *sent =
true;
01431 }
01432 }
01433
01434 void KGame::emitSignal(
KGamePropertyBase *me)
01435 {
01436 emit
signalPropertyChanged(me,
this);
01437 }
01438
01439 KGamePropertyBase*
KGame::findProperty(
int id)
const
01440
{
return d->mProperties->find(
id); }
01441
01442 KGame::GamePolicy KGame::policy()
const
01443
{
01444
return d->mPolicy;
01445 }
01446 void KGame::setPolicy(GamePolicy p,
bool recursive)
01447 {
01448
01449 d->mPolicy=p;
01450
if (recursive)
01451 {
01452
01453
dataHandler()->
setPolicy((KGamePropertyBase::PropertyPolicy)p,
false);
01454
01455
01456
for (
QPtrListIterator<KPlayer> it(d->mPlayerList); it.current(); ++it)
01457 {
01458 it.current()->dataHandler()->setPolicy((KGamePropertyBase::PropertyPolicy)p,
false);
01459 }
01460
for (
QPtrListIterator<KPlayer> it(d->mInactivePlayerList); it.current(); ++it)
01461 {
01462 it.current()->dataHandler()->setPolicy((KGamePropertyBase::PropertyPolicy)p,
false);
01463 }
01464 }
01465 }
01466
01467
01468
01469