|
|
|
/*
|
|
|
|
This file is part of the TDE games library
|
|
|
|
Copyright (C) 2001 Andreas Beckermann (b_mann@gmx.de)
|
|
|
|
Copyright (C) 2001 Martin Heni (martin@heni-online.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 "kgamepropertyhandler.h"
|
|
|
|
#include "kgameproperty.h"
|
|
|
|
#include "kgamemessage.h"
|
|
|
|
|
|
|
|
#include <tqmap.h>
|
|
|
|
#include <tqptrqueue.h>
|
|
|
|
|
|
|
|
#include <tdelocale.h>
|
|
|
|
#include <typeinfo>
|
|
|
|
|
|
|
|
#define KPLAYERHANDLER_LOAD_COOKIE 6239
|
|
|
|
|
|
|
|
//---------------------- KGamePropertyHandler -----------------------------------
|
|
|
|
class KGamePropertyHandlerPrivate
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
KGamePropertyHandlerPrivate()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
TQMap<int, TQString> mNameMap;
|
|
|
|
TQIntDict<KGamePropertyBase> mIdDict;
|
|
|
|
int mUniqueId;
|
|
|
|
int mId;
|
|
|
|
KGamePropertyBase::PropertyPolicy mDefaultPolicy;
|
|
|
|
bool mDefaultUserspace;
|
|
|
|
int mIndirectEmit;
|
|
|
|
TQPtrQueue<KGamePropertyBase> mSignalQueue;
|
|
|
|
};
|
|
|
|
|
|
|
|
KGamePropertyHandler::KGamePropertyHandler(int id, const TQObject* receiver, const char * sendf, const char *emitf, TQObject* parent) : TQObject(parent)
|
|
|
|
{
|
|
|
|
init();
|
|
|
|
registerHandler(id,receiver,sendf,emitf);
|
|
|
|
}
|
|
|
|
|
|
|
|
KGamePropertyHandler::KGamePropertyHandler(TQObject* parent) : TQObject(parent)
|
|
|
|
{
|
|
|
|
init();
|
|
|
|
}
|
|
|
|
|
|
|
|
KGamePropertyHandler::~KGamePropertyHandler()
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KGamePropertyHandler::init()
|
|
|
|
{
|
|
|
|
kdDebug(11001) << k_funcinfo << ": this=" << this << endl;
|
|
|
|
d = new KGamePropertyHandlerPrivate; // for future use - is BC important to us?
|
|
|
|
d->mId = 0;
|
|
|
|
d->mUniqueId=KGamePropertyBase::IdAutomatic;
|
|
|
|
d->mDefaultPolicy=KGamePropertyBase::PolicyLocal;
|
|
|
|
d->mDefaultUserspace=true;
|
|
|
|
d->mIndirectEmit=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int KGamePropertyHandler::id() const
|
|
|
|
{
|
|
|
|
return d->mId;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KGamePropertyHandler::setId(int id)
|
|
|
|
{
|
|
|
|
d->mId = id;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KGamePropertyHandler::registerHandler(int id,const TQObject * receiver, const char * sendf, const char *emitf)
|
|
|
|
{
|
|
|
|
setId(id);
|
|
|
|
if (receiver && sendf) {
|
|
|
|
kdDebug(11001) << "Connecting TQT_SLOT " << sendf << endl;
|
|
|
|
connect(this, TQT_SIGNAL(signalSendMessage(int, TQDataStream &, bool*)), receiver, sendf);
|
|
|
|
}
|
|
|
|
if (receiver && emitf) {
|
|
|
|
kdDebug(11001) << "Connecting TQT_SLOT " << emitf << endl;
|
|
|
|
connect(this, TQT_SIGNAL(signalPropertyChanged(KGamePropertyBase *)), receiver, emitf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KGamePropertyHandler::processMessage(TQDataStream &stream, int id, bool isSender)
|
|
|
|
{
|
|
|
|
// kdDebug(11001) << k_funcinfo << ": id=" << id << " mId=" << d->mId << endl;
|
|
|
|
if (id != d->mId) {
|
|
|
|
return false; // Is the message meant for us?
|
|
|
|
}
|
|
|
|
KGamePropertyBase* p;
|
|
|
|
int propertyId;
|
|
|
|
KGameMessage::extractPropertyHeader(stream, propertyId);
|
|
|
|
// kdDebug(11001) << k_funcinfo << ": Got property " << propertyId << endl;
|
|
|
|
if (propertyId==KGamePropertyBase::IdCommand) {
|
|
|
|
int cmd;
|
|
|
|
KGameMessage::extractPropertyCommand(stream, propertyId, cmd);
|
|
|
|
//kdDebug(11001) << k_funcinfo << ": Got COMMAND for id= "<<propertyId <<endl;
|
|
|
|
p = d->mIdDict.find(propertyId);
|
|
|
|
if (p) {
|
|
|
|
if (!isSender || p->policy()==KGamePropertyBase::PolicyClean) {
|
|
|
|
p->command(stream, cmd, isSender);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
kdError(11001) << k_funcinfo << ": (cmd): property " << propertyId << " not found" << endl;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
p = d->mIdDict.find(propertyId);
|
|
|
|
if (p) {
|
|
|
|
//kdDebug(11001) << k_funcinfo << ": Loading " << propertyId << endl;
|
|
|
|
if (!isSender || p->policy()==KGamePropertyBase::PolicyClean) {
|
|
|
|
p->load(stream);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
kdError(11001) << k_funcinfo << ": property " << propertyId << " not found" << endl;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KGamePropertyHandler::removeProperty(KGamePropertyBase* data)
|
|
|
|
{
|
|
|
|
if (!data) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
d->mNameMap.erase(data->id());
|
|
|
|
return d->mIdDict.remove(data->id());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KGamePropertyHandler::addProperty(KGamePropertyBase* data, TQString name)
|
|
|
|
{
|
|
|
|
//kdDebug(11001) << k_funcinfo << ": " << data->id() << endl;
|
|
|
|
if (d->mIdDict.find(data->id())) {
|
|
|
|
// this id already exists
|
|
|
|
kdError(11001) << " -> cannot add property " << data->id() << endl;
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
d->mIdDict.insert(data->id(), data);
|
|
|
|
// if here is a check for "is_debug" or so we can add the strings only in debug mode
|
|
|
|
// and save memory!!
|
|
|
|
if (!name.isNull()) {
|
|
|
|
d->mNameMap[data->id()] = name;
|
|
|
|
//kdDebug(11001) << k_funcinfo << ": nid="<< (data->id()) << " inserted in Map name=" << d->mNameMap[data->id()] <<endl;
|
|
|
|
//kdDebug(11001) << "Typeid=" << typeid(data).name() << endl;
|
|
|
|
//kdDebug(11001) << "Typeid call=" << data->typeinfo()->name() << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString KGamePropertyHandler::propertyName(int id) const
|
|
|
|
{
|
|
|
|
TQString s;
|
|
|
|
if (d->mIdDict.find(id)) {
|
|
|
|
if (d->mNameMap.contains(id)) {
|
|
|
|
s = i18n("%1 (%2)").arg(d->mNameMap[id]).arg(id);
|
|
|
|
} else {
|
|
|
|
s = i18n("Unnamed - ID: %1").arg(id);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Should _never_ happen
|
|
|
|
s = i18n("%1 unregistered").arg(id);
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KGamePropertyHandler::load(TQDataStream &stream)
|
|
|
|
{
|
|
|
|
// Prevent direct emmiting until all is loaded
|
|
|
|
lockDirectEmit();
|
|
|
|
uint count,i;
|
|
|
|
stream >> count;
|
|
|
|
kdDebug(11001) << k_funcinfo << ": " << count << " KGameProperty objects " << endl;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
processMessage(stream, id(),false);
|
|
|
|
}
|
|
|
|
TQ_INT16 cookie;
|
|
|
|
stream >> cookie;
|
|
|
|
if (cookie == KPLAYERHANDLER_LOAD_COOKIE) {
|
|
|
|
kdDebug(11001) << " KGamePropertyHandler loaded propertly"<<endl;
|
|
|
|
} else {
|
|
|
|
kdError(11001) << "KGamePropertyHandler loading error. probably format error"<<endl;
|
|
|
|
}
|
|
|
|
// Allow direct emmiting (if no other lock still holds)
|
|
|
|
unlockDirectEmit();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KGamePropertyHandler::save(TQDataStream &stream)
|
|
|
|
{
|
|
|
|
kdDebug(11001) << k_funcinfo << ": " << d->mIdDict.count() << " KGameProperty objects " << endl;
|
|
|
|
stream << (uint)d->mIdDict.count();
|
|
|
|
TQIntDictIterator<KGamePropertyBase> it(d->mIdDict);
|
|
|
|
while (it.current()) {
|
|
|
|
KGamePropertyBase *base=it.current();
|
|
|
|
if (base) {
|
|
|
|
KGameMessage::createPropertyHeader(stream, base->id());
|
|
|
|
base->save(stream);
|
|
|
|
}
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
stream << (TQ_INT16)KPLAYERHANDLER_LOAD_COOKIE;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
KGamePropertyBase::PropertyPolicy KGamePropertyHandler::policy()
|
|
|
|
{
|
|
|
|
// kdDebug(11001) << k_funcinfo << ": " << d->mDefaultPolicy << endl;
|
|
|
|
return d->mDefaultPolicy;
|
|
|
|
}
|
|
|
|
void KGamePropertyHandler::setPolicy(KGamePropertyBase::PropertyPolicy p,bool userspace)
|
|
|
|
{
|
|
|
|
// kdDebug(11001) << k_funcinfo << ": " << p << endl;
|
|
|
|
d->mDefaultPolicy=p;
|
|
|
|
d->mDefaultUserspace=userspace;
|
|
|
|
TQIntDictIterator<KGamePropertyBase> it(d->mIdDict);
|
|
|
|
while (it.current()) {
|
|
|
|
if (!userspace || it.current()->id()>=KGamePropertyBase::IdUser) {
|
|
|
|
it.current()->setPolicy((KGamePropertyBase::PropertyPolicy)p);
|
|
|
|
}
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KGamePropertyHandler::unlockProperties()
|
|
|
|
{
|
|
|
|
TQIntDictIterator<KGamePropertyBase> it(d->mIdDict);
|
|
|
|
while (it.current()) {
|
|
|
|
it.current()->unlock();
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KGamePropertyHandler::lockProperties()
|
|
|
|
{
|
|
|
|
TQIntDictIterator<KGamePropertyBase> it(d->mIdDict);
|
|
|
|
while (it.current()) {
|
|
|
|
it.current()->lock();
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int KGamePropertyHandler::uniquePropertyId()
|
|
|
|
{
|
|
|
|
return d->mUniqueId++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KGamePropertyHandler::flush()
|
|
|
|
{
|
|
|
|
TQIntDictIterator<KGamePropertyBase> it(d->mIdDict);
|
|
|
|
while (it.current()) {
|
|
|
|
if (it.current()->isDirty()) {
|
|
|
|
it.current()->sendProperty();
|
|
|
|
}
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fire all property signal changed which are collected in
|
|
|
|
* the queque
|
|
|
|
**/
|
|
|
|
void KGamePropertyHandler::lockDirectEmit()
|
|
|
|
{
|
|
|
|
d->mIndirectEmit++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KGamePropertyHandler::unlockDirectEmit()
|
|
|
|
{
|
|
|
|
// If the flag is <=0 we emit the queued signals
|
|
|
|
d->mIndirectEmit--;
|
|
|
|
if (d->mIndirectEmit<=0)
|
|
|
|
{
|
|
|
|
KGamePropertyBase *prop;
|
|
|
|
while((prop=d->mSignalQueue.dequeue()) != 0)
|
|
|
|
{
|
|
|
|
// kdDebug(11001) << "emmiting signal for " << prop->id() << endl;
|
|
|
|
emit signalPropertyChanged(prop);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KGamePropertyHandler::emitSignal(KGamePropertyBase *prop)
|
|
|
|
{
|
|
|
|
// If the indirect flag is set (load and network transmit)
|
|
|
|
// we cannot emit the signals directly as it can happend that
|
|
|
|
// a sigal causes an access to a property which is e.g. not
|
|
|
|
// yet loaded or received
|
|
|
|
|
|
|
|
if (d->mIndirectEmit>0)
|
|
|
|
{
|
|
|
|
// Queque the signal
|
|
|
|
d->mSignalQueue.enqueue(prop);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// directly emit
|
|
|
|
emit signalPropertyChanged(prop);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KGamePropertyHandler::sendProperty(TQDataStream &s)
|
|
|
|
{
|
|
|
|
bool sent = false;
|
|
|
|
emit signalSendMessage(id(), s, &sent);
|
|
|
|
return sent;
|
|
|
|
}
|
|
|
|
|
|
|
|
KGamePropertyBase *KGamePropertyHandler::find(int id)
|
|
|
|
{
|
|
|
|
return d->mIdDict.find(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KGamePropertyHandler::clear()
|
|
|
|
{
|
|
|
|
kdDebug(11001) << k_funcinfo << id() << endl;
|
|
|
|
TQIntDictIterator<KGamePropertyBase> it(d->mIdDict);
|
|
|
|
while (it.toFirst()) {
|
|
|
|
KGamePropertyBase* p = it.toFirst();
|
|
|
|
p->unregisterData();
|
|
|
|
if (d->mIdDict.find(p->id())) {
|
|
|
|
// shouldn't happen - but if mOwner in KGamePropertyBase is NULL
|
|
|
|
// this might be possible
|
|
|
|
removeProperty(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQIntDict<KGamePropertyBase>& KGamePropertyHandler::dict() const
|
|
|
|
{
|
|
|
|
return d->mIdDict;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString KGamePropertyHandler::propertyValue(KGamePropertyBase* prop)
|
|
|
|
{
|
|
|
|
if (!prop) {
|
|
|
|
return i18n("NULL pointer");
|
|
|
|
}
|
|
|
|
|
|
|
|
int id = prop->id();
|
|
|
|
TQString name = propertyName(id);
|
|
|
|
TQString value;
|
|
|
|
|
|
|
|
const type_info* t = prop->typeinfo();
|
|
|
|
if (*t == typeid(int)) {
|
|
|
|
value = TQString::number(((KGamePropertyInt*)prop)->value());
|
|
|
|
} else if (*t == typeid(unsigned int)) {
|
|
|
|
value = TQString::number(((KGamePropertyUInt *)prop)->value());
|
|
|
|
} else if (*t == typeid(long int)) {
|
|
|
|
value = TQString::number(((KGameProperty<long int> *)prop)->value());
|
|
|
|
} else if (*t == typeid(unsigned long int)) {
|
|
|
|
value = TQString::number(((KGameProperty<unsigned long int> *)prop)->value());
|
|
|
|
} else if (*t == typeid(TQString)) {
|
|
|
|
value = ((KGamePropertyTQString*)prop)->value();
|
|
|
|
} else if (*t == typeid(TQ_INT8)) {
|
|
|
|
value = ((KGamePropertyBool*)prop)->value() ? i18n("True") : i18n("False");
|
|
|
|
} else {
|
|
|
|
emit signalRequestValue(prop, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (value.isNull()) {
|
|
|
|
value = i18n("Unknown");
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KGamePropertyHandler::Debug()
|
|
|
|
{
|
|
|
|
kdDebug(11001) << "-----------------------------------------------------------" << endl;
|
|
|
|
kdDebug(11001) << "KGamePropertyHandler:: Debug this=" << this << endl;
|
|
|
|
|
|
|
|
kdDebug(11001) << " Registered properties: (Policy,Lock,Emit,Optimized, Dirty)" << endl;
|
|
|
|
TQIntDictIterator<KGamePropertyBase> it(d->mIdDict);
|
|
|
|
while (it.current()) {
|
|
|
|
KGamePropertyBase *p=it.current();
|
|
|
|
kdDebug(11001) << " "<< p->id() << ": p=" << p->policy()
|
|
|
|
<< " l="<<p->isLocked()
|
|
|
|
<< " e="<<p->isEmittingSignal()
|
|
|
|
<< " o=" << p->isOptimized()
|
|
|
|
<< " d="<<p->isDirty()
|
|
|
|
<< endl;
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
kdDebug(11001) << "-----------------------------------------------------------" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "kgamepropertyhandler.moc"
|