summaryrefslogtreecommitdiffstats
path: root/libkdegames/kgame/kgame.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libkdegames/kgame/kgame.cpp')
-rw-r--r--libkdegames/kgame/kgame.cpp1475
1 files changed, 0 insertions, 1475 deletions
diff --git a/libkdegames/kgame/kgame.cpp b/libkdegames/kgame/kgame.cpp
deleted file mode 100644
index 2eebac64..00000000
--- a/libkdegames/kgame/kgame.cpp
+++ /dev/null
@@ -1,1475 +0,0 @@
-/*
- This file is part of the KDE games library
- Copyright (C) 2001 Martin Heni (martin@heni-online.de)
- Copyright (C) 2001 Andreas Beckermann (b_mann@gmx.de)
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License version 2 as published by the Free Software Foundation.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public License
- along with this library; see the file COPYING.LIB. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-/*
- $Id$
-*/
-
-#include "kgame.h"
-#include "kgame.moc"
-#include "kgamepropertyhandler.h"
-#include "kgameproperty.h"
-#include "kplayer.h"
-#include "kgameio.h"
-#include "kgameerror.h"
-#include "kgamesequence.h"
-
-#include "kgamemessage.h"
-
-#include <unistd.h>
-#include <stdio.h>
-#include <assert.h>
-
-#include <tqbuffer.h>
-#include <tqtimer.h>
-#include <tqptrqueue.h>
-#include <tqfile.h>
-
-#include <klocale.h>
-#include <krandomsequence.h>
-#include <kdebug.h>
-
-#define KGAME_LOAD_COOKIE 4210
-
-// try to place as much as possible here
-// many things are *not* possible here as KGame has to use some inline function
-class KGamePrivate
-{
-public:
- KGamePrivate()
- {
- mUniquePlayerNumber = 0;
- mPolicy=KGame::PolicyLocal;
- mGameSequence = 0;
- }
-
- int mUniquePlayerNumber;
- TQPtrQueue<KPlayer> mAddPlayerList;// this is a list of to-be-added players. See addPlayer() docu
- KRandomSequence* mRandom;
- KGame::GamePolicy mPolicy;
- KGameSequence* mGameSequence;
-
-
- KGamePropertyHandler* mProperties;
-
- // player lists
- KGame::KGamePlayerList mPlayerList;
- KGame::KGamePlayerList mInactivePlayerList;
-
- //KGamePropertys
- KGamePropertyInt mMaxPlayer;
- KGamePropertyUInt mMinPlayer;
- KGamePropertyInt mGametqStatus; // Game running?
- TQValueList<int> mInactiveIdList;
-
-};
-
-// ------------------- GAME CLASS --------------------------
-KGame::KGame(int cookie,TQObject* parent) : KGameNetwork(cookie,parent)
-{
- kdDebug(11001) << k_funcinfo << " - " << this << ", sizeof(KGame)=" << sizeof(KGame) << endl;
- d = new KGamePrivate;
-
- d->mProperties = new KGamePropertyHandler(this);
-
- d->mProperties->registerHandler(KGameMessage::IdGameProperty,
- this,TQT_SLOT(sendProperty(int, TQDataStream&, bool* )),
- TQT_SLOT(emitSignal(KGamePropertyBase *)));
- d->mMaxPlayer.registerData(KGamePropertyBase::IdMaxPlayer, this, i18n("MaxPlayers"));
- d->mMaxPlayer.setLocal(-1); // Infinite
- d->mMinPlayer.registerData(KGamePropertyBase::IdMinPlayer, this, i18n("MinPlayers"));
- d->mMinPlayer.setLocal(0); // Always ok
- d->mGametqStatus.registerData(KGamePropertyBase::IdGametqStatus, this, i18n("GameStatus"));
- d->mGametqStatus.setLocal(Init);
- // d->mUniquePlayerNumber = 0;
- d->mRandom = new KRandomSequence;
- d->mRandom->setSeed(0);
-
- connect(this, TQT_SIGNAL(signalClientConnected(TQ_UINT32)),
- this, TQT_SLOT(slotClientConnected(TQ_UINT32)));
- connect(this, TQT_SIGNAL(signalClientDisconnected(TQ_UINT32,bool)),
- this, TQT_SLOT(slotClientDisconnected(TQ_UINT32,bool)));
- connect(this, TQT_SIGNAL(signalConnectionBroken()),
- this, TQT_SLOT(slotServerDisconnected()));
-
- setGameSequence(new KGameSequence());
-
- // BL: FIXME This signal does no longer exist. When we are merging
- // MH: super....and how do I find out about the lost conenction now?
- // KGame and KGameNetwork, this could be improved!
-// connect(this,TQT_SIGNAL(signalConnectionLost(KGameClient *)),
-// this,TQT_SLOT(slotConnectionLost(KGameClient *)));
-}
-
-KGame::~KGame()
-{
- kdDebug(11001) << k_funcinfo << endl;
-// Debug();
- reset();
- delete d->mGameSequence;
- delete d->mRandom;
- delete d;
- kdDebug(11001) << k_funcinfo << " done" << endl;
-}
-
-bool KGame::reset()
-{
- deletePlayers();
- deleteInactivePlayers();
- return true;
-}
-
-void KGame::deletePlayers()
-{
-// kdDebug(11001) << k_funcinfo << endl;
- KGamePlayerList tmp = d->mPlayerList; // in case of PolicyClean player=d->mPlayerList.first() is infinite
- KPlayer *player;
- while((player=tmp.first()))
- {
- delete player; // delete and removes the player
- tmp.removeFirst();
- }
-// kdDebug(11001) << k_funcinfo << " done" << endl;
-}
-
-void KGame::deleteInactivePlayers()
-{
- KPlayer *player;
- while((player=d->mInactivePlayerList.first()))
- {
- //player->setGame(0); // prevent call backs
- d->mInactivePlayerList.remove(player);
- delete player;
- }
-}
-
-bool KGame::load(TQString filename,bool reset)
-{
- if (filename.isNull())
- {
- return false;
- }
- TQFile f(filename);
- if (!f.open(IO_ReadOnly))
- {
- return false;
- }
- TQDataStream s( &f );
- load(s,reset);
- f.close();
- return true;
-}
-
-bool KGame::load(TQDataStream &stream,bool reset)
-{ return loadgame(stream, false,reset); }
-
-bool KGame::loadgame(TQDataStream &stream, bool network,bool resetgame)
-{
- // Load Game Data
-
- // internal data
- TQ_INT32 c;
- stream >> c; // cookie
-
- if (c!=cookie())
- {
- kdWarning(11001) << "Trying to load different game version we="<<cookie() << " saved=" << c << endl;
- bool result=false;
- emit signalLoadError(stream,network,(int)c,result);
- return result;
- }
- if (resetgame) reset();
-
- uint i;
- stream >> i;
-// setPolicy((GamePolicy)i);
-
- stream >> d->mUniquePlayerNumber;
-
- if (gameSequence())
- {
- gameSequence()->setCurrentPlayer(0); // TODO !!!
- }
- int newseed;
- stream >> newseed;
- d->mRandom->setSeed(newseed);
-
- // Switch off the direct emitting of signals while
- // loading properties. This can cause inconsistencies
- // otherwise if a property emits and this emit accesses
- // a property not yet loaded
- // Note we habe to have this external locking to prevent the games unlocking
- // to access the players
- dataHandler()->lockDirectEmit();
- KPlayer *player;
- for ( player=playerList()->first(); player != 0; player=playerList()->next() )
- {
- player->dataHandler()->lockDirectEmit();
- // kdDebug(11001) << "Player "<<player->id() << " to indirect emit" <<endl;
- }
-
- // Properties
- dataHandler()->load(stream);
-
- // If there is additional data to be loaded before players are loaded then do
- // this here.
- emit signalLoadPrePlayers(stream);
-
- // Load Playerobjects
- uint playercount;
- stream >> playercount;
- kdDebug(11001) << "Loading KGame " << playercount << " KPlayer objects " << endl;
- for (i=0;i<playercount;i++)
- {
- KPlayer *newplayer=loadPlayer(stream,network);
- systemAddPlayer(newplayer);
- }
-
- TQ_INT16 cookie;
- stream >> cookie;
- if (cookie==KGAME_LOAD_COOKIE) {
- kdDebug(11001) << " Game loaded propertly"<<endl;
- } else {
- kdError(11001) << " Game loading error. probably format error"<<endl;
- }
-
- // Switch back on the direct emitting of signals and emit the
- // queued signals.
- // Note we habe to have this external locking to prevent the games unlocking
- // to access the players
- dataHandler()->unlockDirectEmit();
- for ( player=playerList()->first(); player != 0; player=playerList()->next() )
- {
- player->dataHandler()->unlockDirectEmit();
- // kdDebug(11001) << "Player "<<player->id() << " to direct emit" <<endl;
- }
-
- emit signalLoad(stream);
- return true;
-}
-
-bool KGame::save(TQString filename,bool saveplayers)
-{
- if (filename.isNull())
- {
- return false;
- }
- TQFile f(filename);
- if (!f.open(IO_WriteOnly))
- {
- return false;
- }
- TQDataStream s( &f );
- save(s,saveplayers);
- f.close();
- return true;
-}
-
-bool KGame::save(TQDataStream &stream,bool saveplayers)
-{ return savegame(stream, false,saveplayers); }
-
-bool KGame::savegame(TQDataStream &stream,bool /*network*/,bool saveplayers)
-{
- // Save Game Data
-
- // internal variables
- TQ_INT32 c=cookie();
- stream << c;
-
- uint p=(uint)policy();
- stream << p;
- stream << d->mUniquePlayerNumber;
- int newseed=(int)d->mRandom->getLong(65535);
- stream << newseed;
- d->mRandom->setSeed(newseed);
-
- // Properties
- dataHandler()->save(stream);
-
- // Save all data that need to be saved *before* the players are saved
- emit signalSavePrePlayers(stream);
-
- if (saveplayers)
- {
- savePlayers(stream,playerList());
- }
- else
- {
- stream << (uint)0; // no players saved
- }
-
- stream << (TQ_INT16)KGAME_LOAD_COOKIE;
-
- emit signalSave(stream);
- return true;
-}
-
-void KGame::savePlayer(TQDataStream &stream,KPlayer* p)
-{
-// this could be in KGameMessage as well
- stream << (TQ_INT32)p->rtti();
- stream << (TQ_INT32)p->id();
- stream << (TQ_INT32)p->calcIOValue();
- p->save(stream);
-}
-
-void KGame::savePlayers(TQDataStream &stream, KGamePlayerList *list)
-{
- if (!list)
- {
- list=playerList();
- }
-
- TQ_INT32 cnt=list->count();
- kdDebug(11001) << "Saving KGame " << cnt << " KPlayer objects " << endl;
- stream << cnt;
- KPlayer *player;
- for ( player=list->first(); player != 0; player=list->next() )
- {
- savePlayer(stream,player);
- }
-}
-
-KPlayer *KGame::createPlayer(int /*rtti*/,int /*io*/,bool /*isvirtual*/)
-{
- kdWarning(11001) << " No user defined player created. Creating default KPlayer. This crashes if you have overwritten KPlayer!!!! " << endl;
- return new KPlayer;
-}
-KPlayer *KGame::loadPlayer(TQDataStream& stream,bool isvirtual)
-{
- TQ_INT32 rtti,id,iovalue;
- stream >> rtti >> id >> iovalue;
- KPlayer *newplayer=findPlayer(id);
- if (!newplayer)
- {
- kdDebug(11001) << k_funcinfo << "Player "<< id << " not found...asking user to create one " << endl;
- newplayer=createPlayer(rtti,iovalue,isvirtual);
- //emit signalCreatePlayer(newplayer,rtti,iovalue,isvirtual,this);
- }
- /*
- if (!newplayer)
- {
- kdWarning(11001) << " No user defined player created. Creating default KPlayer. This crashes if you have overwritten KPlayer!!!! " << endl;
- newplayer=new KPlayer;
- }
- else
- {
- kdDebug(11001) << " USER Player " << newplayer << " done player->rtti=" << newplayer->rtti() << " rtti=" << rtti << endl;
- }
- */
- newplayer->load(stream);
- if (isvirtual)
- {
- newplayer->setVirtual(true);
- }
- return newplayer;
-}
-
-// ----------------- Player handling -----------------------
-
-KPlayer * KGame::findPlayer(TQ_UINT32 id) const
-{
- for (TQPtrListIterator<KPlayer> it(d->mPlayerList); it.current(); ++it)
- {
- if (it.current()->id() == id)
- {
- return it.current();
- }
- }
- for (TQPtrListIterator<KPlayer> it(d->mInactivePlayerList); it.current(); ++it)
- {
- if (it.current()->id() == id)
- {
- return it.current();
- }
- }
- return 0;
-}
-
-// it is necessary that addPlayer and systemAddPlayer are called in the same
-// order. Ie if addPlayer(foo) followed by addPlayer(bar) is called, you must
-// not call systemAddPlayer(bar) followed by systemAddPlayer(foo), as the
-// mAddPlayerList would get confused. Should be no problem as long as comServer
-// and the clients are working correctly.
-// BUT: if addPlayer(foo) does not arrive by any reason while addPlayer(bar)
-// does, we would be in trouble...
-void KGame::addPlayer(KPlayer* newplayer)
-{
- kdDebug(11001) << k_funcinfo << ": " << "; maxPlayers=" << maxPlayers() << " playerCount=" << playerCount() << endl;
- if (!newplayer)
- {
- kdFatal(11001) << "trying to add NULL player in KGame::addPlayer()" << endl;
- return ;
- }
-
- if (maxPlayers() >= 0 && (int)playerCount() >= maxPlayers())
- {
- kdWarning(11001) << "cannot add more than " << maxPlayers() << " players - deleting..." << endl;
- delete newplayer;
- return;
- }
-
- if (newplayer->id() == 0)
- {
- d->mUniquePlayerNumber++;
- newplayer->setId(KGameMessage::createPlayerId(d->mUniquePlayerNumber, gameId()));
- kdDebug(11001) << k_funcinfo << "NEW!!! player " << newplayer << " now has id " << newplayer->id() << endl;
- }
- else
- {
- // this could happen in games which use their own ID management by certain
- // reasons. that is NOT recommended
- kdDebug(11001) << k_funcinfo << "player " << newplayer << " already has an id: " << newplayer->id() << endl;
- }
-
- TQByteArray buffer;
- TQDataStream stream(buffer,IO_WriteOnly);
- // We distinguis here what policy we have
- if (policy()==PolicyLocal || policy()==PolicyDirty)
- {
- systemAddPlayer(newplayer);
- }
- if (policy()==PolicyClean || policy()==PolicyDirty)
- {
- savePlayer(stream,newplayer);
- // Store the player for delayed clean adding
- if (policy()==PolicyClean)
- {
- d->mAddPlayerList.enqueue(newplayer);
- }
- sendSystemMessage(stream,(int)KGameMessage::IdAddPlayer, 0);
- }
-}
-
-void KGame::systemAddPlayer(KPlayer* newplayer)
-{
- if (!newplayer)
- {
- kdFatal(11001) << "trying to add NULL player in KGame::systemAddPlayer()" << endl;
- return ;
- }
- if (newplayer->id() == 0)
- {
- kdWarning(11001) << k_funcinfo << "player " << newplayer << " has no ID" << endl;
- }
-
- if (findPlayer(newplayer->id()))
- {
- kdError(11001) << "ERROR: Double adding player !!!!! NOT GOOD !!!!!! " << newplayer->id() << "...I delete it again" << endl;
- delete newplayer;
- }
- else
- {
- kdDebug(11001) << "Trying to add player " << newplayer <<" maxPlayers="<<maxPlayers()<<" playerCount="<<playerCount() << endl;
- // Add the player to the game
- d->mPlayerList.append(newplayer);
- newplayer->setGame(this);
- kdDebug(11001) << "Player: isVirtual=" << newplayer->isVirtual() << endl;
- kdDebug(11001) << " id=" << newplayer->id() << " #Players="
- << d->mPlayerList.count() << " added " << newplayer
- << " (virtual=" << newplayer->isVirtual() << ")" << endl;
- emit signalPlayerJoinedGame(newplayer);
- }
-}
-
-// Called by the KPlayer destructor
-void KGame::playerDeleted(KPlayer *player)
-{
- kdDebug(11001) << k_funcinfo << ": id (" << player->id() << ") to be removed " << player << endl;
-
- if (policy()==PolicyLocal || policy()==PolicyDirty)
- {
- systemRemovePlayer(player,false);
- }
- if (policy()==PolicyClean || policy()==PolicyDirty)
- {
- if (!player->isVirtual())
- {
- kdDebug(11001) << k_funcinfo << ": sending IdRemovePlayer "<<player->id() << endl;
- sendSystemMessage(player->id(), KGameMessage::IdRemovePlayer, 0);
- }
- }
-}
-
-bool KGame::removePlayer(KPlayer * player, TQ_UINT32 receiver)
-{//transmit to all clients, or to receiver only
- if (!player)
- {
- kdFatal(11001) << "trying to remove NULL player in KGame::removePlayer()" << endl;
- return false;
- }
- kdDebug(11001) << k_funcinfo << ": id (" << player->id() << ") to be removed " << player << endl;
-
- if (policy()==PolicyLocal || policy()==PolicyDirty)
- {
- systemRemovePlayer(player,true);
- }
- if (policy()==PolicyClean || policy()==PolicyDirty)
- {
- kdDebug(11001) << k_funcinfo << ": sending IdRemovePlayer "<<player->id() << endl;
- sendSystemMessage(player->id(),KGameMessage::IdRemovePlayer, receiver);
- }
- return true;
- // we will receive the message in networkTransmission()
-}
-
-void KGame::systemRemovePlayer(KPlayer* player,bool deleteit)
-{
- kdDebug(11001) << k_funcinfo << endl;
- if (!player)
- {
- kdWarning(11001) << "cannot remove NULL player" << endl;
- return;
- }
- if (!systemRemove(player,deleteit))
- {
- kdWarning(11001) << "player " << player << "(" << player->id() << ") Could not be found!" << endl;
- }
-
- if (gametqStatus()==(int)Run && playerCount()<minPlayers())
- {
- kdWarning(11001) << k_funcinfo ": not enough players, PAUSING game\n" << endl;
- setGametqStatus(Pause);
- }
-}
-
-bool KGame::systemRemove(KPlayer* p,bool deleteit)
-{
- if (!p)
- {
- kdWarning(11001) << "cannot remove NULL player" << endl;
- return false;
- }
- bool result;
- kdDebug(11001) << k_funcinfo << ": Player (" << p->id() << ") to be removed " << p << endl;
-
- if (d->mPlayerList.count() == 0)
- {
- result = false;
- }
- else
- {
- result = d->mPlayerList.remove(p);
- }
-
- emit signalPlayerLeftGame(p);
-
- p->setGame(0);
- if (deleteit)
- {
- delete p;
- }
-
- return result;
-}
-
-bool KGame::inactivatePlayer(KPlayer* player)
-{
- if (!player)
- {
- return false;
- }
- kdDebug(11001) << "Inactivate player " << player->id() << endl;
-
- if (policy()==PolicyLocal || policy()==PolicyDirty)
- {
- systemInactivatePlayer(player);
- }
- if (policy()==PolicyClean || policy()==PolicyDirty)
- {
- sendSystemMessage(player->id(), KGameMessage::IdInactivatePlayer);
- }
-
- return true;
-}
-
-bool KGame::systemInactivatePlayer(KPlayer* player)
-{
- if (!player || !player->isActive())
- {
- return false;
- }
- kdDebug(11001) << " Inactivate player " << player->id() << endl;
-
- int pid=player->id();
- // Virtual players cannot be deactivated. They will be removed
- if (player->isVirtual())
- {
- systemRemovePlayer(player,true);
- }
- else
- {
- d->mPlayerList.remove(player);
- d->mInactivePlayerList.prepend(player);
- player->setActive(false);
- }
- emit signalPlayerLeftGame(player);
- if (isAdmin())
- {
- d->mInactiveIdList.prepend(pid);
- }
- return true;
-}
-
-bool KGame::activatePlayer(KPlayer * player)
-{
- if (!player)
- {
- return false;
- }
- kdDebug(11001) << k_funcinfo << ": activate " << player->id() << endl;
- if (policy()==PolicyLocal || policy()==PolicyDirty)
- {
- systemActivatePlayer(player);
- }
- if (policy()==PolicyClean || policy()==PolicyDirty)
- {
- sendSystemMessage(player->id(), KGameMessage::IdActivatePlayer);
- }
- return true;
-}
-
-bool KGame::systemActivatePlayer(KPlayer* player)
-{
- if (!player || player->isActive())
- {
- return false;
- }
- kdDebug(11001) << k_funcinfo << ": activate " << player->id() << endl;
-
- d->mInactivePlayerList.remove(player);
- player->setActive(true);
- addPlayer(player);
- if (isAdmin())
- {
- d->mInactiveIdList.remove(player->id());
- }
- return true;
-}
-
-// -------------------- Properties ---------------------------
-
-void KGame::setMaxPlayers(uint maxnumber)
-{ if (isAdmin()) { d->mMaxPlayer.changeValue(maxnumber); } }
-
-void KGame::setMinPlayers(uint minnumber)
-{ if (isAdmin()) { d->mMinPlayer.changeValue(minnumber); } }
-
-uint KGame::minPlayers() const
-{ return d->mMinPlayer.value(); }
-
-int KGame::maxPlayers() const
-{ return d->mMaxPlayer.value(); }
-
-uint KGame::playerCount() const
-{ return d->mPlayerList.count(); }
-
-int KGame::gametqStatus() const
-{ return d->mGametqStatus.value(); }
-
-bool KGame::isRunning() const
-{ return d->mGametqStatus.value() == Run; }
-
-KGamePropertyHandler* KGame::dataHandler() const
-{ return d->mProperties; }
-
-
-KGame::KGamePlayerList* KGame::inactivePlayerList()
-{ return &d->mInactivePlayerList; }
-
-const KGame::KGamePlayerList* KGame::inactivePlayerList() const
-{ return &d->mInactivePlayerList; }
-
-KGame::KGamePlayerList* KGame::playerList()
-{ return &d->mPlayerList; }
-
-const KGame::KGamePlayerList* KGame::playerList() const
-{ return &d->mPlayerList; }
-
-KRandomSequence* KGame::random() const
-{ return d->mRandom; }
-
-
-bool KGame::sendPlayerInput(TQDataStream &msg, KPlayer *player, TQ_UINT32 sender)
-{
- if (!player)
- {
- kdError(11001) << k_funcinfo << ": NULL player" << endl;
- return false;
- }
- if (!isRunning())
- {
- kdError(11001) << k_funcinfo << ": game not running" << endl;
- return false;
- }
-
- kdDebug(11001) << k_funcinfo << ": transmitting playerInput over network" << endl;
- sendSystemMessage(msg, (int)KGameMessage::IdPlayerInput, player->id(), sender);
- return true;
-}
-
-bool KGame::systemPlayerInput(TQDataStream &msg, KPlayer *player, TQ_UINT32 sender)
-{
- if (!player)
- {
- kdError(11001) << k_funcinfo << ": NULL player" << endl;
- return false;
- }
- if (!isRunning())
- {
- kdError(11001) << k_funcinfo << ": game not running" << endl;
- return false;
- }
- kdDebug(11001) << "KGame: Got playerInput from messageServer... sender: " << sender << endl;
- if (playerInput(msg,player))
- {
- playerInputFinished(player);
- }
- else
- {
- kdDebug(11001) << k_funcinfo<<": switching off player input"<<endl;
- // TODO: (MH 03-2003): We need an return option from playerInput so that
- // the player's is not automatically disabled here
- if (!player->asyncInput())
- {
- player->setTurn(false); // in turn based games we have to switch off input now
- }
- }
- return true;
-}
-
-
-KPlayer * KGame::playerInputFinished(KPlayer *player)
-{
- kdDebug(11001) << k_funcinfo<<"player input finished for "<<player->id()<<endl;
- // Check for game over and if not allow the next player to move
- int gameOver = 0;
- if (gameSequence())
- {
- gameSequence()->setCurrentPlayer(player);
- }
- // do not call gameSequence()->checkGameOver() to keep backward compatibility!
- gameOver = checkGameOver(player);
- if (gameOver!=0)
- {
- if (player)
- {
- player->setTurn(false);
- }
- setGametqStatus(End);
- emit signalGameOver(gameOver,player,this);
- }
- else if (!player->asyncInput())
- {
- player->setTurn(false); // in turn based games we have to switch off input now
- if (gameSequence())
- {
- TQTimer::singleShot(0,this,TQT_SLOT(prepareNext()));
- }
- }
- return player;
-}
-
-// Per default we do not do anything
-int KGame::checkGameOver(KPlayer *player)
-{
- if (gameSequence())
- {
- return gameSequence()->checkGameOver(player);
- }
- return 0;
-}
-
-void KGame::setGameSequence(KGameSequence* sequence)
-{
- delete d->mGameSequence;
- d->mGameSequence = sequence;
- if (d->mGameSequence)
- {
- d->mGameSequence->setGame(this);
- }
-}
-
-KGameSequence* KGame::gameSequence() const
-{
- return d->mGameSequence;
-}
-
-void KGame::prepareNext()
-{
- if (gameSequence())
- {
- // we don't call gameSequence->nextPlayer() to keep old code working
- nextPlayer(gameSequence()->currentPlayer());
- }
-}
-
-KPlayer *KGame::nextPlayer(KPlayer *last,bool exclusive)
-{
- if (gameSequence())
- {
- return gameSequence()->nextPlayer(last, exclusive);
- }
- return 0;
-}
-
-void KGame::setGametqStatus(int status)
-{
- kdDebug(11001) << k_funcinfo << ": GAMESTATUS CHANGED to" << status << endl;
- if (status==(int)Run && playerCount()<minPlayers())
- {
- kdDebug(11001) << k_funcinfo << ": not enough players, pausing game\n" << endl;
- status=Pause;
- }
- d->mGametqStatus = status;
-}
-
-void KGame::networkTransmission(TQDataStream &stream, int msgid, TQ_UINT32 receiver, TQ_UINT32 sender, TQ_UINT32 /*clientID*/)
-{//clientID is unused
- // message targets a playerobject. If we find it we forward the message to the
- // player. Otherwise we proceed here and hope the best that the user processes
- // the message
-
-// kdDebug(11001) << k_funcinfo << ": we="<<(int)gameId()<<" id="<<msgid<<" recv=" << receiver << " sender=" << sender << endl;
-
-
- // *first* notice the game that something has changed - so no return prevents
- // this
- emit signalMessageUpdate(msgid, receiver, sender);
- if (KGameMessage::isPlayer(receiver))
- {
- //kdDebug(11001) << "message id " << msgid << " seems to be for a player ("<<active=p->isActive()<<" recv="<< receiver << endl;
- KPlayer *p=findPlayer(receiver);
- if (p && p->isActive())
- {
- p->networkTransmission(stream,msgid,sender);
- return;
- }
- if (p)
- {
- kdDebug(11001) << "player is here but not active" << endl;
- }
- else
- {
- kdDebug(11001) << "no player found" << endl;
- }
- }
- // If it is not for a player it is meant for us!!!! Otherwise the
- // gamenetwork would not have passed the message to us!
-
- // GameProperties processed
- if (d->mProperties->processMessage(stream, msgid, sender == gameId()))
- {
-// kdDebug(11001 ) << "KGame: message taken by property - returning" << endl;
- return ;
- }
-
- switch(msgid)
- {
- case KGameMessage::IdSetupGame: // Client: First step in setup game
- {
- TQ_INT16 v;
- TQ_INT32 c;
- stream >> v >> c;
- kdDebug(11001) << " ===================> (Client) " << k_funcinfo << ": Got IdSetupGame ================== " << endl;
- kdDebug(11001) << "our game id is " << gameId() << " Lib version=" << v << " App Cookie=" << c << endl;
- // Verify identity of the network partners
- if (c!=cookie())
- {
- kdError(11001) << "IdGameSetup: Negotiate Game: cookie mismatch I'am="<<cookie()<<" master="<<c<<endl;
- sendError(KGameError::Cookie, KGameError::errCookie(cookie(), c));
- disconnect(); // disconnect from master
- }
- else if (v!=KGameMessage::version())
- {
- sendError(KGameError::Version, KGameError::errVersion(v));
- disconnect(); // disconnect from master
- }
- else
- {
- setupGame(sender);
- }
- kdDebug(11001) << "========== (Client) Setup game done\n";
- }
- break;
- case KGameMessage::IdSetupGameContinue: // Master: second step in game setup
- {
- kdDebug(11001) << "=====>(Master) " << k_funcinfo << " - IdSetupGameContinue" << endl;
- setupGameContinue(stream, sender);
- }
- break;
- case KGameMessage::IdActivatePlayer: // Activate Player
- {
- int id;
- stream >> id;
- kdDebug(11001) << "Got IdActivatePlayer id=" << id << endl;
- if (sender!=gameId() || policy()!=PolicyDirty)
- {
- systemActivatePlayer(findPlayer(id));
- }
- }
- break;
- case KGameMessage::IdInactivatePlayer: // Inactivate Player
- {
- int id;
- stream >> id;
- kdDebug(11001) << "Got IdInactivatePlayer id=" << id << endl;
- if (sender!=gameId() || policy()!=PolicyDirty)
- {
- systemInactivatePlayer(findPlayer(id));
- }
- }
- break;
- case KGameMessage::IdAddPlayer:
- {
- kdDebug(11001) << k_funcinfo << ": Got IdAddPlayer" << endl;
- if (sender!=gameId() || policy()!=PolicyDirty)
- {
- KPlayer *newplayer=0;
- // We sent the message so the player is already available
- if (sender==gameId())
- {
- kdDebug(11001) << "dequeue previously added player" << endl;
- newplayer = d->mAddPlayerList.dequeue();
- }
- else
- {
- newplayer=loadPlayer(stream,true);
- }
- systemAddPlayer(newplayer);// the final, local, adding
- //systemAddPlayer(stream);
- }
- }
- break;
- case KGameMessage::IdRemovePlayer: // Client should delete player id
- {
- int id;
- stream >> id;
- kdDebug(11001) << k_funcinfo << ": Got IdRemovePlayer " << id << endl;
- KPlayer *p=findPlayer(id);
- if (p)
- {
- // Otherwise the player is already removed
- if (sender!=gameId() || policy()!=PolicyDirty)
- {
- systemRemovePlayer(p,true);
- }
- }
- else
- {
- kdWarning(11001) << k_funcinfo << "Cannot find player " << id << endl;
- }
- }
- break;
- case KGameMessage::IdGameLoad:
- {
- kdDebug(11001) << "====> (Client) " << k_funcinfo << ": Got IdGameLoad" << endl;
- loadgame(stream,true,false);
- }
- break;
- case KGameMessage::IdGameSetupDone:
- {
- int cid;
- stream >> cid;
- kdDebug(11001) << "====> (CLIENT) " << k_funcinfo << ": Got IdGameSetupDone for client "
- << cid << " we are =" << gameId() << endl;
- sendSystemMessage(gameId(), KGameMessage::IdGameConnected, 0);
- }
- break;
- case KGameMessage::IdGameConnected:
- {
- int cid;
- stream >> cid;
- kdDebug(11001) << "====> (ALL) " << k_funcinfo << ": Got IdGameConnected for client "<< cid << " we are =" << gameId() << endl;
- emit signalClientJoinedGame(cid,this);
- }
- break;
-
- case KGameMessage::IdSyncRandom: // Master forces a new random seed on us
- {
- int newseed;
- stream >> newseed;
- kdDebug(11001) << "CLIENT: setting random seed to " << newseed << endl;
- d->mRandom->setSeed(newseed);
- }
- break;
- case KGameMessage::IdDisconnect:
- {
- // if we disconnect we *always* start a local game.
- // this could lead into problems if we just change the message server
- if (sender != gameId())
- {
- kdDebug(11001) << "client " << sender << " leaves game" << endl;
- return;
- }
- kdDebug(11001) << "leaving the game" << endl;
- // start a new local game
- // no other client is by default connected to this so this call should be
- // enough
- setMaster();
- }
- break;
- default:
- {
- if (msgid < KGameMessage::IdUser)
- {
- kdError(11001) << "incorrect message id " << msgid << " - emit anyway"
- << endl;
- }
- kdDebug(11001) << k_funcinfo << ": User data msgid " << msgid << endl;
- emit signalNetworkData(msgid - KGameMessage::IdUser,((TQBuffer*)stream.device())->readAll(),receiver,sender);
- }
- break;
- }
-
-}
-
-// called by the IdSetupGameContinue Message - MASTER SIDE
-// Here the master needs to decide which players can take part at the game
-// and which will be deactivated
-void KGame::setupGameContinue(TQDataStream& stream, TQ_UINT32 sender)
-{
- KPlayer *player;
- TQ_INT32 cnt;
- int i;
- stream >> cnt;
-
- TQValueList<int> inactivateIds;
-
- KGamePlayerList newPlayerList;
- newPlayerList.setAutoDelete(true);
- for (i=0;i<cnt;i++)
- {
- player=loadPlayer(stream,true);
- kdDebug(11001) << " Master got player " << player->id() <<" rawgame=" << KGameMessage::rawGameId(player->id()) << " from sender " << sender << endl;
- if (KGameMessage::rawGameId(player->id()) != sender)
- {
- kdError(11001) << "Client tries to add player with wrong game id - cheat possible" << endl;
- }
- else
- {
- newPlayerList.append(player);
- kdDebug(11001) << " newplayerlist appended " << player->id() << endl;
- }
- }
-
- newPlayersJoin(playerList(),&newPlayerList,inactivateIds);
-
-
- kdDebug(11001) << " Master calculates how many players to activate client has cnt=" << cnt << endl;
- kdDebug(11001) << " The game has " << playerCount() << " active players" << endl;
- kdDebug(11001) << " The user deactivated "<< inactivateIds.count() << " player already " << endl;
- kdDebug(11001) << " MaxPlayers for this game is " << maxPlayers() << endl;
-
- // Do we have too many players? (After the programmer disabled some?)
- // MH: We cannot use have player here as it CHANGES in the loop
- // int havePlayers = cnt+playerCount()-inactivateIds.count();
- kdDebug(11001) << " havePlayers " << cnt+playerCount()-inactivateIds.count() << endl;
- while (maxPlayers() > 0 && maxPlayers() < (int)(cnt+playerCount() - inactivateIds.count()))
- {
- kdDebug(11001) << " Still to deacticvate "
- << (int)(cnt+playerCount()-inactivateIds.count())-(int)maxPlayers()
- << endl;
- KPlayer *currentPlayer=0;
- int currentPriority=0x7fff; // MAX_UINT (16bit?) to get the maximum of the list
- // find lowest network priority which is not yet in the newPlayerList
- // do this for the new players
- for ( player=newPlayerList.first(); player != 0; player=newPlayerList.next() )
- {
- // Already in the list
- if (inactivateIds.find(player->id())!=inactivateIds.end())
- {
- continue;
- }
- if (player->networkPriority()<currentPriority)
- {
- currentPriority=player->networkPriority();
- currentPlayer=player;
- }
- }
-
- // find lowest network priority which is not yet in the newPlayerList
- // Do this for the network players
- for ( player=d->mPlayerList.first(); player != 0; player=d->mPlayerList.next() )
- {
- // Already in the list
- if (inactivateIds.find(player->id())!=inactivateIds.end())
- {
- continue;
- }
- if (player->networkPriority()<currentPriority)
- {
- currentPriority=player->networkPriority();
- currentPlayer=player;
- }
- }
-
- // add it to inactivateIds
- if (currentPlayer)
- {
- kdDebug(11001) << "Marking player " << currentPlayer->id() << " for inactivation" << endl;
- inactivateIds.append(currentPlayer->id());
- }
- else
- {
- kdError(11001) << "Couldn't find a player to dectivate..That is not so good..." << endl;
- break;
- }
- }
-
- kdDebug(11001) << "Alltogether deactivated " << inactivateIds.count() << " players" << endl;
-
- TQValueList<int>::Iterator it;
- for ( it = inactivateIds.begin(); it != inactivateIds.end(); ++it )
- {
- int pid=*it;
- kdDebug(11001) << " pid=" << pid << endl;
- }
-
- // Now deactivate the network players from the inactivateId list
- //TQValueList<int>::Iterator it;
- for ( it = inactivateIds.begin(); it != inactivateIds.end(); ++it )
- {
- int pid=*it;
- if (KGameMessage::rawGameId(pid) == sender)
- {
- continue; // client's player
- }
- kdDebug(11001) << " -> the network needs to deactivate " << pid <<endl;
- player=findPlayer(pid);
- if (player)
- {
- // We have to make REALLY sure that the player is gone. With any policy
- systemInactivatePlayer(player);
- if (policy()!=PolicyLocal)
- {
- sendSystemMessage(player->id(), KGameMessage::IdInactivatePlayer);
- }
- }
- else
- {
- kdError(11001) << " We should deactivate a player, but cannot find it...not good." << endl;
- }
- }
-
- // Now send out the player list which the client can activate
- for ( player=newPlayerList.first(); player != 0; player=newPlayerList.next() )
- {
- kdDebug(11001) << " newplayerlist contains " << player->id() << endl;
- // Only activate what is not in the list
- if (inactivateIds.find(player->id())!=inactivateIds.end())
- {
- continue;
- }
- kdDebug(11001) << " -> the client can ******** reactivate ******** " << player->id() << endl;
- sendSystemMessage(player->id(), KGameMessage::IdActivatePlayer, sender);
- }
-
- // Save the game over the network
- TQByteArray bufferS;
- TQDataStream streamS(bufferS,IO_WriteOnly);
- // Save game over netowrk and save players
- savegame(streamS,true,true);
- sendSystemMessage(streamS,KGameMessage::IdGameLoad,sender);
-
-
- // Only to the client first , as the client will add players
- sendSystemMessage(sender, KGameMessage::IdGameSetupDone, sender);
-}
-
-// called by the IdSetupGame Message - CLIENT SIDE
-// Client needs to prepare for network transfer
-void KGame::setupGame(TQ_UINT32 sender)
-{
- TQByteArray bufferS;
- TQDataStream streamS(bufferS,IO_WriteOnly);
-
- // Deactivate all players
- KGamePlayerList mTmpList(d->mPlayerList); // we need copy otherwise the removal crashes
- TQ_INT32 cnt=mTmpList.count();
- kdDebug(11001) << "Client: playerlistcount=" << d->mPlayerList.count() << " tmplistcout=" << cnt << endl;
-
- streamS << cnt;
-
- TQPtrListIterator<KPlayer> it(mTmpList);
- KPlayer *player;
- while (it.current())
- {
- player=it.current();
- systemInactivatePlayer(player);
- // Give the new game id to all players (which are inactivated now)
- player->setId(KGameMessage::createPlayerId(player->id(),gameId()));
-
- // Save it for the master to decide what to do
- savePlayer(streamS,player);
-
- ++it;
- --cnt;
- }
- if (d->mPlayerList.count() > 0 || cnt!=0)
- {
- kdFatal(11001) << "KGame::setupGame(): Player list is not empty! or cnt!=0=" <<cnt << endl;
- }
-
- sendSystemMessage(streamS,KGameMessage::IdSetupGameContinue,sender);
-}
-
-// unused by KGame
-void KGame::syncRandom()
-{
- int newseed=(int)d->mRandom->getLong(65535);
- sendSystemMessage(newseed,KGameMessage::IdSyncRandom); // Broadcast
- d->mRandom->setSeed(newseed);
-}
-
-void KGame::Debug()
-{
- KGameNetwork::Debug();
- kdDebug(11001) << "------------------- KGAME -------------------------" << endl;
- kdDebug(11001) << "this: " << this << endl;
- kdDebug(11001) << "uniquePlayer " << d->mUniquePlayerNumber << endl;
- kdDebug(11001) << "gameStatus " << gametqStatus() << endl;
- kdDebug(11001) << "MaxPlayers : " << maxPlayers() << endl;
- kdDebug(11001) << "NoOfPlayers : " << playerCount() << endl;
- kdDebug(11001) << "NoOfInactive: " << d->mInactivePlayerList.count() << endl;
- kdDebug(11001) << "---------------------------------------------------" << endl;
-}
-
-void KGame::slotClientConnected(TQ_UINT32 clientID)
-{
- if (isAdmin())
- {
- negotiateNetworkGame(clientID);
- }
-}
-
-void KGame::slotServerDisconnected() // Client side
-{
- kdDebug(11001) << "======= SERVER DISCONNECT ======="<<endl;
- kdDebug(11001) << "+++ (CLIENT)++++++++" << k_funcinfo << ": our GameID="<<gameId() << endl;
-
- int oldgamestatus=gametqStatus();
-
- KPlayer *player;
- KGamePlayerList removeList;
- kdDebug(11001) << "Playerlist of client=" << d->mPlayerList.count() << " count" << endl;
- kdDebug(11001) << "Inactive Playerlist of client=" << d->mInactivePlayerList.count() << " count" << endl;
- for ( player=d->mPlayerList.first(); player != 0; player=d->mPlayerList.next() )
- {
- // TODO: CHECK: id=0, could not connect to server in the first place??
- if (KGameMessage::rawGameId(player->id()) != gameId() && gameId()!=0)
- {
- kdDebug(11001) << "Player " << player->id() << " belongs to a removed game" << endl;
- removeList.append(player);
- }
- }
-
- for ( player=removeList.first(); player != 0; player=removeList.next() )
- {
- bool remove = true;
- emit signalReplacePlayerIO(player, &remove);
- if (remove)
- {
- kdDebug(11001) << " ---> Removing player " << player->id() << endl;
- systemRemovePlayer(player,true); // no network necessary
- }
- }
-
- setMaster();
- kdDebug(11001) << " our game id is after setMaster " << gameId() << endl;
-
- KGamePlayerList mReList(d->mInactivePlayerList);
- for ( player=mReList.first(); player != 0; player=mReList.next() )
- {
- // TODO ?check for priority? Sequence should be ok
- if ((int)playerCount()<maxPlayers() || maxPlayers()<0)
- {
- systemActivatePlayer(player);
- }
- }
- kdDebug(11001) << " Players activated player-cnt=" << playerCount() << endl;
-
- for ( player=d->mPlayerList.first(); player != 0; player=d->mPlayerList.next() )
- {
- int oldid=player->id();
- d->mUniquePlayerNumber++;
- player->setId(KGameMessage::createPlayerId(d->mUniquePlayerNumber,gameId()));
- kdDebug(11001) << "Player id " << oldid <<" changed to " << player->id() << " as we are now local" << endl;
- }
- // TODO clear inactive lists ?
- Debug();
- for ( player=d->mPlayerList.first(); player != 0; player=d->mPlayerList.next() )
- {
- player->Debug();
- }
- kdDebug(11001) << "+++++++++++" << k_funcinfo << " DONE=" << endl;
- emit signalClientLeftGame(0,oldgamestatus,this);
-}
-
-void KGame::slotClientDisconnected(TQ_UINT32 clientID,bool /*broken*/) // server side
-{
- kdDebug(11001) << "++++(SERVER)+++++++" << k_funcinfo << " clientId=" << clientID << endl;
-
- int oldgamestatus=gametqStatus();
-
- KPlayer *player;
- KGamePlayerList removeList;
- kdDebug(11001) << "Playerlist of client=" << d->mPlayerList.count() << " count" << endl;
- for ( player=d->mPlayerList.first(); player != 0; player=d->mPlayerList.next() )
- {
- if (KGameMessage::rawGameId(player->id())==clientID)
- {
- kdDebug(11001) << "Player " << player->id() << " belongs to the removed game" << endl;
- removeList.append(player);
- }
- }
-
- for ( player=removeList.first(); player != 0; player=removeList.next() )
- {
- // try to replace the KGameIO first
- bool remove = true;
- emit signalReplacePlayerIO(player, &remove);
- if (remove) {
- // otherwise (no new KGameIO) remove the player
- kdDebug(11001) << " ---> Removing player " << player->id() << endl;
- removePlayer(player,0);
- }
- }
-
- // Now add inactive players - sequence should be ok
- // TODO remove players from removed game
- for (unsigned int idx=0;idx<d->mInactiveIdList.count();idx++)
- {
- TQValueList<int>::Iterator it1 = d->mInactiveIdList.at(idx);
- player = findPlayer(*it1);
- if (((int)playerCount() < maxPlayers() || maxPlayers() < 0) && player && KGameMessage::rawGameId(*it1) != clientID)
- {
- activatePlayer(player);
- }
- }
- emit signalClientLeftGame(clientID,oldgamestatus,this);
-}
-
-
-// -------------------- Synchronisation -----------------------
-
-// this initializes a newly connected client.
-// we send the number of players (including type) as well as game status and
-// properties to the client. After the initialization has been completed both
-// clients should have the same status (ie players, properties, etc)
-void KGame::negotiateNetworkGame(TQ_UINT32 clientID)
-{
- kdDebug(11001) << "===========================" << k_funcinfo << ": clientID=" << clientID << " =========================== "<< endl;
- if (!isAdmin())
- {
- kdError(11001) << k_funcinfo << ": Serious WARNING..only gameAdmin should call this" << endl;
- return ;
- }
-
- TQByteArray buffer;
- TQDataStream streamGS(buffer,IO_WriteOnly);
-
- // write Game setup specific data
- //streamGS << (TQ_INT32)maxPlayers();
- //streamGS << (TQ_INT32)minPlayers();
-
- // send to the newly connected client *only*
- TQ_INT16 v=KGameMessage::version();
- TQ_INT32 c=cookie();
- streamGS << v << c;
- sendSystemMessage(streamGS, KGameMessage::IdSetupGame, clientID);
-}
-
-bool KGame::sendGroupMessage(const TQByteArray &msg, int msgid, TQ_UINT32 sender, const TQString& group)
-{
-// AB: group must not be i18n'ed!! we should better use an id for group and use
-// a groupName() for the name // FIXME
- KPlayer *player;
- for ( player=d->mPlayerList.first(); player != 0; player=d->mPlayerList.next() )
- {
- if (player && player->group()==group)
- {
- sendMessage(msg,msgid,player->id(), sender);
- }
- }
- return true;
-}
-
-bool KGame::sendGroupMessage(const TQDataStream &msg, int msgid, TQ_UINT32 sender, const TQString& group)
-{ return sendGroupMessage(((TQBuffer*)msg.device())->buffer(), msgid, sender, group); }
-
-bool KGame::sendGroupMessage(const TQString& msg, int msgid, TQ_UINT32 sender, const TQString& group)
-{
- TQByteArray buffer;
- TQDataStream stream(buffer, IO_WriteOnly);
- stream << msg;
- return sendGroupMessage(stream, msgid, sender, group);
-}
-
-bool KGame::addProperty(KGamePropertyBase* data)
-{ return dataHandler()->addProperty(data); }
-
-bool KGame::sendPlayerProperty(int msgid, TQDataStream& s, TQ_UINT32 playerId)
-{ return sendSystemMessage(s, msgid, playerId); }
-
-void KGame::sendProperty(int msgid, TQDataStream& stream, bool* sent)
-{
- bool s = sendSystemMessage(stream, msgid);
- if (s)
- {
- *sent = true;
- }
-}
-
-void KGame::emitSignal(KGamePropertyBase *me)
-{
- emit signalPropertyChanged(me,this);
-}
-
-KGamePropertyBase* KGame::findProperty(int id) const
-{ return d->mProperties->find(id); }
-
-KGame::GamePolicy KGame::policy() const
-{
- return d->mPolicy;
-}
-void KGame::setPolicy(GamePolicy p,bool recursive)
-{
- // Set KGame policy
- d->mPolicy=p;
- if (recursive)
- {
- // Set all KGame property policy
- dataHandler()->setPolicy((KGamePropertyBase::PropertyPolicy)p,false);
-
- // Set all KPLayer (active or inactive) property policy
- for (TQPtrListIterator<KPlayer> it(d->mPlayerList); it.current(); ++it)
- {
- it.current()->dataHandler()->setPolicy((KGamePropertyBase::PropertyPolicy)p,false);
- }
- for (TQPtrListIterator<KPlayer> it(d->mInactivePlayerList); it.current(); ++it)
- {
- it.current()->dataHandler()->setPolicy((KGamePropertyBase::PropertyPolicy)p,false);
- }
- }
-}
-
-/*
- * vim: et sw=2
- */