|
|
|
#include "mp_interface.h"
|
|
|
|
#include "mp_interface.moc"
|
|
|
|
|
|
|
|
#include <tqpainter.h>
|
|
|
|
#include <tqlayout.h>
|
|
|
|
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kmessagebox.h>
|
|
|
|
#include <kapplication.h>
|
|
|
|
#include <kkeydialog.h>
|
|
|
|
|
|
|
|
#include "defines.h"
|
|
|
|
#include "types.h"
|
|
|
|
#include "meeting.h"
|
|
|
|
#include "internal.h"
|
|
|
|
#include "keys.h"
|
|
|
|
#include "wizard.h"
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* Constructor & Destructor */
|
|
|
|
/*****************************************************************************/
|
|
|
|
MPInterface::MPInterface(const MPGameInfo &_gameInfo,
|
|
|
|
uint nbActions, const ActionData *data,
|
|
|
|
TQWidget *parent, const char *name)
|
|
|
|
: TQWidget(parent, name), internal(0), gameInfo(_gameInfo), nbLocalHumans(0)
|
|
|
|
{
|
|
|
|
Q_ASSERT( gameInfo.maxNbLocalPlayers>=1 );
|
|
|
|
|
|
|
|
hbl = new TQHBoxLayout(this, 0, 5);
|
|
|
|
hbl->setResizeMode( TQLayout::Fixed );
|
|
|
|
|
|
|
|
_keyData = new KeyData(gameInfo.maxNbLocalPlayers, nbActions, data, TQT_TQOBJECT(this));
|
|
|
|
}
|
|
|
|
|
|
|
|
MPInterface::~MPInterface()
|
|
|
|
{
|
|
|
|
delete internal;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* Game creation */
|
|
|
|
/*****************************************************************************/
|
|
|
|
void MPInterface::clear()
|
|
|
|
{
|
|
|
|
if (internal) {
|
|
|
|
stop();
|
|
|
|
delete internal;
|
|
|
|
internal = 0;
|
|
|
|
_keyData->clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MPInterface::dialog()
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
|
|
|
|
// configuration wizard
|
|
|
|
ConnectionData cd;
|
|
|
|
MPWizard wiz(gameInfo, cd, this);
|
|
|
|
if ( wiz.exec()==TQDialog::Rejected ) {
|
|
|
|
singleHuman(); // create a single game
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// net meeting
|
|
|
|
TQPtrList<RemoteHostData> rhd;
|
|
|
|
rhd.setAutoDelete(TRUE);
|
|
|
|
if (cd.network) {
|
|
|
|
cId id(kapp->name(), gameInfo.gameId);
|
|
|
|
MPOptionWidget *ow = newOptionWidget();
|
|
|
|
NetMeeting *nm;
|
|
|
|
if (cd.server) nm = new ServerNetMeeting(id, cd.rhd, ow, rhd, this);
|
|
|
|
else nm = new ClientNetMeeting(id, cd.rhd, ow, this);
|
|
|
|
int res = nm->exec();
|
|
|
|
if (ow) {
|
|
|
|
if (res) ow->saveData();
|
|
|
|
delete ow;
|
|
|
|
}
|
|
|
|
delete nm;
|
|
|
|
if (!res) {
|
|
|
|
singleHuman();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
createLocalGame(cd);
|
|
|
|
if (cd.server) createServerGame(rhd);
|
|
|
|
else createClientGame(cd.rhd);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MPInterface::specialLocalGame(uint nbHumans, uint nbAIs)
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
|
|
|
|
ConnectionData cd;
|
|
|
|
BoardData bd;
|
|
|
|
PlayerComboBox::Type t;
|
|
|
|
KConfigGroupSaver cg(kapp->config(), MP_GROUP);
|
|
|
|
for (uint i=0; i<(nbHumans+nbAIs); i++) {
|
|
|
|
bd.type = (i<nbHumans ? PlayerComboBox::Human : PlayerComboBox::AI);
|
|
|
|
bd.name = TQString();
|
|
|
|
t = (PlayerComboBox::Type)
|
|
|
|
cg.config()->readNumEntry(TQString(MP_PLAYER_TYPE).tqarg(i),
|
|
|
|
PlayerComboBox::None);
|
|
|
|
if ( bd.type==t )
|
|
|
|
bd.name = cg.config()->readEntry(TQString(MP_PLAYER_NAME).tqarg(i),
|
|
|
|
TQString());
|
|
|
|
if ( bd.name.isNull() )
|
|
|
|
bd.name = (i<nbHumans ? i18n("Human %1").tqarg(i+1)
|
|
|
|
: i18n("AI %1").tqarg(i-nbHumans+1));
|
|
|
|
cd.rhd.bds += bd;
|
|
|
|
}
|
|
|
|
cd.server = TRUE;
|
|
|
|
cd.network = FALSE;
|
|
|
|
Q_ASSERT( (nbHumans+nbAIs)<=gameInfo.maxNbLocalPlayers );
|
|
|
|
Q_ASSERT( gameInfo.AIAllowed || nbAIs==0 );
|
|
|
|
|
|
|
|
createLocalGame(cd);
|
|
|
|
TQPtrList<RemoteHostData> rhd;
|
|
|
|
createServerGame(rhd);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MPInterface::createServerGame(const TQPtrList<RemoteHostData> &rhd)
|
|
|
|
{
|
|
|
|
internal = (rhd.count()
|
|
|
|
? (Local *)new NetworkServer(this, boards, rhd, gameInfo.interval)
|
|
|
|
: (Local *)new LocalServer(this, boards, gameInfo.interval));
|
|
|
|
init();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MPInterface::createClientGame(const RemoteHostData &rhd)
|
|
|
|
{
|
|
|
|
TQPtrList<RemoteHostData> r;
|
|
|
|
r.append((RemoteHostData *)&rhd);
|
|
|
|
internal = new Client(this, boards, r);
|
|
|
|
init();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MPInterface::createLocalGame(const ConnectionData &cd)
|
|
|
|
{
|
|
|
|
_server = cd.server;
|
|
|
|
nbLocalHumans = 0;
|
|
|
|
for (uint i=0; i<cd.rhd.bds.count(); i++)
|
|
|
|
if ( cd.rhd.bds[i].type==PlayerComboBox::Human ) nbLocalHumans++;
|
|
|
|
|
|
|
|
// add or remove boards
|
|
|
|
uint old_s = boards.count();
|
|
|
|
uint new_s = cd.rhd.bds.count();
|
|
|
|
for (uint i=new_s; i<old_s; i++) {
|
|
|
|
delete boards[i].ptr;
|
|
|
|
boards.remove(boards.at(i));
|
|
|
|
}
|
|
|
|
Data d;
|
|
|
|
for(uint i=old_s; i<new_s; i++) {
|
|
|
|
d.ptr = newBoard(i);
|
|
|
|
hbl->addWidget(d.ptr);
|
|
|
|
d.ptr->show();
|
|
|
|
connect(d.ptr, TQT_SIGNAL(enableKeys(bool)), TQT_SLOT(enableKeys(bool)));
|
|
|
|
boards += d;
|
|
|
|
}
|
|
|
|
|
|
|
|
// init local boards
|
|
|
|
_keyData->setCurrentNb(nbLocalHumans);
|
|
|
|
int k = 0;
|
|
|
|
for (uint i=0; i<boards.count(); i++) {
|
|
|
|
bool h = ( cd.rhd.bds[i].type==PlayerComboBox::Human );
|
|
|
|
boards[i].humanIndex = (h ? k : -1);
|
|
|
|
if (h) {
|
|
|
|
_keyData->createActionCollection(k, boards[i].ptr);
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
boards[i].name = cd.rhd.bds[i].name;
|
|
|
|
boards[i].ptr->init(!h, cd.network || boards.count()>1, _server, i==0,
|
|
|
|
cd.rhd.bds[i].name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* Key management */
|
|
|
|
/*****************************************************************************/
|
|
|
|
void MPInterface::setDefaultKeycodes(uint nb, uint i, const int *def)
|
|
|
|
{
|
|
|
|
_keyData->setKeycodes(nb, i, def);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MPInterface::addKeys(KKeyDialog &d)
|
|
|
|
{
|
|
|
|
_keyData->addKeys(d);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MPInterface::saveKeys()
|
|
|
|
{
|
|
|
|
_keyData->save();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MPInterface::enableKeys(bool enable)
|
|
|
|
{
|
|
|
|
if ( nbLocalHumans==0 ) return;
|
|
|
|
// find the sending board
|
|
|
|
uint i;
|
|
|
|
for (i=0; i<boards.count(); i++) if ( sender()==boards[i].ptr ) break;
|
|
|
|
int hi = boards[i].humanIndex;
|
|
|
|
if ( hi==-1 ) return; // AI board (no keys)
|
|
|
|
_keyData->setEnabled(hi, enable);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MPInterface::keyPressEvent(TQKeyEvent *e)
|
|
|
|
{
|
|
|
|
_keyData->keyEvent(e, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MPInterface::keyReleaseEvent(TQKeyEvent *e)
|
|
|
|
{
|
|
|
|
_keyData->keyEvent(e, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* Misc. functions */
|
|
|
|
/*****************************************************************************/
|
|
|
|
uint MPInterface::nbPlayers() const
|
|
|
|
{
|
|
|
|
return internal->nbPlayers();
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString MPInterface::playerName(uint i) const
|
|
|
|
{
|
|
|
|
Q_ASSERT(_server);
|
|
|
|
return internal->playerName(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
TQDataStream &MPInterface::readingStream(uint i) const
|
|
|
|
{
|
|
|
|
Q_ASSERT(_server);
|
|
|
|
return internal->ioBuffer(i)->reading;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQDataStream &MPInterface::writingStream(uint i) const
|
|
|
|
{
|
|
|
|
return internal->ioBuffer(i)->writing;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQDataStream &MPInterface::dataToClientsStream() const
|
|
|
|
{
|
|
|
|
Q_ASSERT(_server);
|
|
|
|
return *internal->globalStream();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MPInterface::immediateWrite()
|
|
|
|
{
|
|
|
|
internal->writeData(_server);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MPInterface::hostDisconnected(uint, const TQString &msg)
|
|
|
|
{
|
|
|
|
errorBox(msg, TQString(), this);
|
|
|
|
|
|
|
|
if ( !disconnected ) { // to avoid multiple calls
|
|
|
|
disconnected = TRUE;
|
|
|
|
// the zero timer is used to be outside the "internal" class
|
|
|
|
TQTimer::singleShot(0, this, TQT_SLOT(singleHumanSlot()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MPInterface::singleHumanSlot()
|
|
|
|
{
|
|
|
|
disconnected = FALSE;
|
|
|
|
singleHuman();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MPInterface::paintEvent(TQPaintEvent *e)
|
|
|
|
{
|
|
|
|
TQPainter p(this);
|
|
|
|
p.fillRect(e->rect(), darkGray);
|
|
|
|
}
|