You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdegames/libkdegames/kgame/kplayer.cpp

447 lines
11 KiB

/*
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 "kgameio.h"
#include "kplayer.h"
#include "kgamemessage.h"
#include "kgamepropertyhandler.h"
#include <kdebug.h>
#include <klocale.h>
#include <tqbuffer.h>
#include <stdio.h>
#include <assert.h>
#define KPLAYER_LOAD_COOKIE 7285
class KPlayerPrivate
{
public:
KPlayerPrivate()
{
mNetworkPlayer = 0;
}
TQ_UINT32 mId;
bool mVirtual; // virtual player
int mPriority; // tag for replacement
KPlayer* mNetworkPlayer; // replacement player
KGamePropertyHandler mProperties;
// Playerdata
KGamePropertyTQString mName;
KGamePropertyTQString mGroup;
};
KPlayer::KPlayer() : TQObject(0,0)
{
init();
}
KPlayer::KPlayer(KGame* game) : TQObject(0, 0)
{
init();
game->addPlayer(this);
}
void KPlayer::init()
{
// note that NO KGame object exists here! so we cannot use KGameProperty::send!
kdDebug(11001) << k_funcinfo << ": this=" << this << ", sizeof(this)="<<sizeof(KPlayer) << endl;
kdDebug(11001) << "sizeof(m_Group)="<<sizeof(d->mGroup)<<endl;
d = new KPlayerPrivate;
d->mProperties.registerHandler(KGameMessage::IdPlayerProperty,
this,TQT_SLOT(sendProperty(int, TQDataStream&, bool*)),
TQT_SLOT(emitSignal(KGamePropertyBase *)));
d->mVirtual=false;
mActive=true;
mGame=0;
d->mId=0; // "0" is always an invalid ID!
d->mPriority=0;
// I guess we cannot translate the group otherwise no
// international conenctions are possible
mUserId.registerData(KGamePropertyBase::IdUserId, this, i18n("UserId"));
mUserId.setLocal(0);
d->mGroup.registerData(KGamePropertyBase::IdGroup, this, i18n("Group"));
d->mGroup.setLocal(i18n("default"));
d->mName.registerData(KGamePropertyBase::IdName, this, i18n("Name"));
d->mName.setLocal(i18n("default"));
mAsyncInput.registerData(KGamePropertyBase::IdAsyncInput, this, i18n("AsyncInput"));
mAsyncInput.setLocal(false);
mMyTurn.registerData(KGamePropertyBase::IdTurn, this, i18n("myTurn"));
mMyTurn.setLocal(false);
mMyTurn.setEmittingSignal(true);
mMyTurn.setOptimized(false);
}
KPlayer::~KPlayer()
{
kdDebug(11001) << k_funcinfo << ": this=" << this <<", id=" << this->id() << endl;
// Delete IODevices
KGameIO *input;
while((input=mInputList.first()))
{
delete input;
}
if (game())
{
game()->playerDeleted(this);
}
// note: mProperties does not use autoDelete or so - user must delete objects
// himself
d->mProperties.clear();
delete d;
// kdDebug(11001) << k_funcinfo << " done" << endl;
}
bool KPlayer::forwardMessage(TQDataStream &msg,int msgid,TQ_UINT32 receiver,TQ_UINT32 sender)
{
if (!isActive())
{
return false;
}
if (!game())
{
return false;
}
kdDebug(11001) << k_funcinfo << ": to game sender="<<sender<<"" << "recv="<<receiver <<"msgid="<<msgid << endl;
return game()->sendSystemMessage(msg,msgid,receiver,sender);
}
bool KPlayer::forwardInput(TQDataStream &msg,bool transmit,TQ_UINT32 sender)
{
if (!isActive())
{
return false;
}
if (!game())
{
return false;
}
kdDebug(11001) << k_funcinfo << ": to game playerInput(sender="<<sender<<")" << endl;
if (!asyncInput() && !myTurn())
{
kdDebug(11001) << k_funcinfo << ": rejected cause it is not our turn" << endl;
return false;
}
// AB: I hope I remember the usage correctly:
// this function is called twice (on sender side) - once with transmit = true
// where it sends the input to the comserver and once with transmit = false
// where it really looks at the input
if (transmit)
{
kdDebug(11001) << "indirect playerInput" << endl;
return game()->sendPlayerInput(msg,this,sender);
}
else
{
kdDebug(11001) << "direct playerInput" << endl;
return game()->systemPlayerInput(msg,this,sender);
}
}
void KPlayer::setId(TQ_UINT32 newid)
{
// Needs to be after the sendProcess
d->mId=newid;
}
void KPlayer::setGroup(const TQString& group)
{ d->mGroup = group; }
const TQString& KPlayer::group() const
{ return d->mGroup.value(); }
void KPlayer::setName(const TQString& name)
{ d->mName = name; }
const TQString& KPlayer::name() const
{ return d->mName.value(); }
TQ_UINT32 KPlayer::id() const
{ return d->mId; }
KGamePropertyHandler * KPlayer::dataHandler()
{ return &d->mProperties; }
void KPlayer::setVirtual(bool v)
{ d->mVirtual = v; }
bool KPlayer::isVirtual() const
{ return d->mVirtual;}
void KPlayer::setNetworkPlayer(KPlayer* p)
{ d->mNetworkPlayer = p; }
KPlayer* KPlayer::networkPlayer() const
{ return d->mNetworkPlayer; }
int KPlayer::networkPriority() const
{ return d->mPriority; }
void KPlayer::setNetworkPriority(int p)
{ d->mPriority = p; }
bool KPlayer::addGameIO(KGameIO *input)
{
if (!input)
{
return false;
}
mInputList.append(input);
input->initIO(this); // set player and init device
return true;
}
// input=0, remove all
bool KPlayer::removeGameIO(KGameIO *targetinput,bool deleteit)
{
kdDebug(11001) << k_funcinfo << ": " << targetinput << " delete=" << deleteit<< endl;
bool result=true;
if (!targetinput) // delete all
{
KGameIO *input;
while((input=mInputList.first()))
{
if (input) removeGameIO(input,deleteit);
}
}
else
{
// kdDebug(11001) << "remove IO " << targetinput << endl;
if (deleteit)
{
delete targetinput;
}
else
{
targetinput->setPlayer(0);
result=mInputList.remove(targetinput);
}
}
return result;
}
KGameIO * KPlayer::findRttiIO(int rtti) const
{
TQPtrListIterator<KGameIO> it(mInputList);
while (it.current())
{
if (it.current()->rtti() == rtti)
{
return it.current();
}
++it;
}
return 0;
}
int KPlayer::calcIOValue()
{
int value=0;
TQPtrListIterator<KGameIO> it(mInputList);
while (it.current())
{
value|=it.current()->rtti();
++it;
}
return value;
}
bool KPlayer::setTurn(bool b, bool exclusive)
{
kdDebug(11001) << k_funcinfo << ": " << id() << " (" << this << ") to " << b << endl;
if (!isActive())
{
return false;
}
// if we get to do an exclusive turn all other players are disallowed
if (exclusive && b && game())
{
KPlayer *player;
KGame::KGamePlayerList *list=game()->playerList();
for ( player=list->first(); player != 0; player=list->next() )
{
if (player==this)
{
continue;
}
player->setTurn(false,false);
}
}
// Return if nothing changed
mMyTurn = b;
return true;
}
bool KPlayer::load(TQDataStream &stream)
{
TQ_INT32 id,priority;
stream >> id >> priority;
setId(id);
setNetworkPriority(priority);
// Load Player Data
//FIXME: maybe set all properties setEmitSignal(false) before?
d->mProperties.load(stream);
TQ_INT16 cookie;
stream >> cookie;
if (cookie==KPLAYER_LOAD_COOKIE)
{
kdDebug(11001) << " Player loaded propertly"<<endl;
}
else
{
kdError(11001) << " Player loading error. probably format error"<<endl;
}
// emit signalLoad(stream);
return true;
}
bool KPlayer::save(TQDataStream &stream)
{
stream << (TQ_INT32)id() << (TQ_INT32)networkPriority();
d->mProperties.save(stream);
stream << (TQ_INT16)KPLAYER_LOAD_COOKIE;
//emit signalSave(stream);
return true;
}
void KPlayer::networkTransmission(TQDataStream &stream,int msgid,TQ_UINT32 sender)
{
//kdDebug(11001) << k_funcinfo ": msgid=" << msgid << " sender=" << sender << " we are=" << id() << endl;
// PlayerProperties processed
bool issender;
if (game())
{
issender=sender==game()->gameId();
}
else
{
issender=true;
}
if (d->mProperties.processMessage(stream,msgid,issender))
{
return ;
}
switch(msgid)
{
case KGameMessage::IdPlayerInput:
{
kdDebug(11001) << k_funcinfo << ": Got player move "
<< "KPlayer (virtual) forwards it to the game object" << endl;
forwardInput(stream,false);
}
break;
default:
emit signalNetworkData(msgid - KGameMessage::IdUser,
((TQBuffer*)stream.device())->readAll(),sender,this);
kdDebug(11001) << k_funcinfo << ": "
<< "User data msgid " << msgid << endl;
break;
}
}
KGamePropertyBase* KPlayer::findProperty(int id) const
{
return d->mProperties.tqfind(id);
}
bool KPlayer::addProperty(KGamePropertyBase* data)
{
return d->mProperties.addProperty(data);
}
void KPlayer::sendProperty(int msgid, TQDataStream& stream, bool* sent)
{
if (game())
{
bool s = game()->sendPlayerProperty(msgid, stream, id());
if (s)
{
*sent = true;
}
}
}
void KPlayer::emitSignal(KGamePropertyBase *me)
{
// Notify KGameIO (Process) for a new turn
if (me->id()==KGamePropertyBase::IdTurn)
{
//kdDebug(11001) << k_funcinfo << ": for KGamePropertyBase::IdTurn " << endl;
TQPtrListIterator<KGameIO> it(mInputList);
while (it.current())
{
it.current()->notifyTurn(mMyTurn.value());
++it;
}
}
emit signalPropertyChanged(me,this);
}
// --------------------- DEBUG --------------------
void KPlayer::Debug()
{
kdDebug(11001) << "------------------- KPLAYER -----------------------" << endl;
kdDebug(11001) << "this: " << this << endl;
kdDebug(11001) << "rtti: " << rtti() << endl;
kdDebug(11001) << "id : " << id() << endl;
kdDebug(11001) << "Name : " << name() << endl;
kdDebug(11001) << "Group: " << group() << endl;
kdDebug(11001) << "Async: " << asyncInput() << endl;
kdDebug(11001) << "myTurn: " << myTurn() << endl;
kdDebug(11001) << "Virtual: " << isVirtual() << endl;
kdDebug(11001) << "Active: " << isActive() << endl;
kdDebug(11001) << "Priority:" << networkPriority() << endl;
kdDebug(11001) << "Game : " << game() << endl;
kdDebug(11001) << "#IOs: " << mInputList.count() << endl;
kdDebug(11001) << "---------------------------------------------------" << endl;
}
#include "kplayer.moc"