* quick-fix for static initialisation problem in ImageReaders

* fix error in two part NetworkMessageCommandList receive
This commit is contained in:
James McCulloch 2010-03-24 13:39:08 +00:00
parent e91c15b9e2
commit dfc32cdba2
5 changed files with 476 additions and 26 deletions

View File

@ -25,6 +25,8 @@
#include "leak_dumper.h"
#include "network_interface.h"
#include "ImageReaders.h"
using namespace std;
using namespace Shared::Platform;
using namespace Shared::Util;
@ -258,7 +260,7 @@ void MainWindow::eventClose(){
// =====================================================
int glestMain(int argc, char** argv){
Shared::Graphics::ImageRegisterer::registerImageReaders();
SystemFlags::enableNetworkDebugInfo = true;
SystemFlags::enableDebugText = true;

View File

@ -35,6 +35,36 @@ namespace Glest{ namespace Game{
// class NetworkMessage
// =====================================================
bool NetworkMessage::peek(Socket* socket, void* data, int dataSize)
{
int ipeekdatalen = socket->getDataToRead();
if(ipeekdatalen >= dataSize)
{
if(socket->peek(data, dataSize)!=dataSize)
{
if(socket != NULL && socket->getSocketId() > 0)
{
throw runtime_error("Error peeking NetworkMessage");
}
else
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] socket has been disconnected\n",__FILE__,__FUNCTION__);
}
}
else
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] dataSize = %d\n",__FILE__,__FUNCTION__,dataSize);
}
return true;
}
else
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] socket->getDataToRead() returned %d\n",__FILE__,__FUNCTION__,ipeekdatalen);
}
return false;
}
bool NetworkMessage::receive(Socket* socket, void* data, int dataSize)
{
int ipeekdatalen = socket->getDataToRead();
@ -204,40 +234,38 @@ bool NetworkMessageCommandList::addCommand(const NetworkCommand* networkCommand)
}
bool NetworkMessageCommandList::receive(Socket* socket){
//return NetworkMessage::receive(socket, &data, sizeof(data));
// read type, commandCount & frame num first.
if (!NetworkMessage::receive(socket, &data, networkPacketMsgTypeSize)) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s %d] NetworkMessage::receive failed!\n",__FILE__,__FUNCTION__,__LINE__);
// _peek_ type, commandCount & frame num first.
if (!NetworkMessage::peek(socket, &data, commandListHeaderSize)) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s %d] NetworkMessage::peek failed!\n",__FILE__,__FUNCTION__,__LINE__);
return false;
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s %d] messageType = %d, frameCount = %d, data.commandCount = %d\n",
__FILE__,__FUNCTION__,__LINE__,data.messageType,data.frameCount,data.commandCount);
// read data.commandCount commands.
if (data.commandCount) {
bool result = NetworkMessage::receive(socket, &data.commands, sizeof(NetworkCommand) * data.commandCount);
if(SystemFlags::enableNetworkDebugInfo) {
for(int idx = 0 ; idx < data.commandCount; ++idx) {
const NetworkCommand &cmd = data.commands[idx];
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s %d] index = %d, networkCommandType = %d, unitId = %d, commandTypeId = %d, positionX = %d, positionY = %d, unitTypeId = %d, targetId = %d\n",
__FILE__,__FUNCTION__,__LINE__,idx, cmd.getNetworkCommandType(),cmd.getUnitId(), cmd.getCommandTypeId(),
cmd.getPosition().x,cmd.getPosition().y, cmd.getUnitTypeId(), cmd.getTargetId());
}
}
return result;
// read header + data.commandCount commands.
int totalMsgSize = commandListHeaderSize + sizeof(NetworkCommand) * data.commandCount;
if (socket->getDataToRead() < totalMsgSize) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s %d] Insufficient data to read entire command list [need %d bytes, only %d available].\n",
__FILE__,__FUNCTION__,__LINE__, totalMsgSize, socket->getDataToRead());
return false;
}
return true;
bool result = NetworkMessage::receive(socket, &data, totalMsgSize);
if(SystemFlags::enableNetworkDebugInfo) {
for(int idx = 0 ; idx < data.commandCount; ++idx) {
const NetworkCommand &cmd = data.commands[idx];
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s %d] index = %d, networkCommandType = %d, unitId = %d, commandTypeId = %d, positionX = %d, positionY = %d, unitTypeId = %d, targetId = %d\n",
__FILE__,__FUNCTION__,__LINE__,idx, cmd.getNetworkCommandType(),cmd.getUnitId(), cmd.getCommandTypeId(),
cmd.getPosition().x,cmd.getPosition().y, cmd.getUnitTypeId(), cmd.getTargetId());
}
}
return result;
}
void NetworkMessageCommandList::send(Socket* socket) const{
assert(data.messageType==nmtCommandList);
//NetworkMessage::send(socket, &data, sizeof(data));
NetworkMessage::send(socket, &data, networkPacketMsgTypeSize + sizeof(NetworkCommand) * data.commandCount);
NetworkMessage::send(socket, &data, commandListHeaderSize + sizeof(NetworkCommand) * data.commandCount);
if(SystemFlags::enableNetworkDebugInfo) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s %d] messageType = %d, frameCount = %d, data.commandCount = %d\n",

View File

@ -0,0 +1,419 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Martiño Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#ifndef _GLEST_GAME_NETWORKMESSAGE_H_
#define _GLEST_GAME_NETWORKMESSAGE_H_
#include "socket.h"
#include "game_constants.h"
#include "network_types.h"
using Shared::Platform::Socket;
using Shared::Platform::int8;
using Shared::Platform::int16;
namespace Glest{ namespace Game{
class GameSettings;
enum NetworkMessageType{
nmtInvalid,
nmtIntro,
nmtPing,
nmtReady,
nmtLaunch,
nmtCommandList,
nmtText,
nmtQuit,
nmtSynchNetworkGameData,
nmtSynchNetworkGameDataStatus,
nmtSynchNetworkGameDataFileCRCCheck,
nmtSynchNetworkGameDataFileGet,
nmtCount
};
const int32 commandListHeaderSize = 6;
// =====================================================
// class NetworkMessage
// =====================================================
class NetworkMessage{
public:
virtual ~NetworkMessage(){}
virtual bool receive(Socket* socket)= 0;
virtual void send(Socket* socket) const = 0;
protected:
bool peek(Socket* socket, void* data, int dataSize);
bool receive(Socket* socket, void* data, int dataSize);
void send(Socket* socket, const void* data, int dataSize) const;
};
// =====================================================
// class NetworkMessageIntro
//
// Message sent from the server to the client
// when the client connects and vice versa
// =====================================================
class NetworkMessageIntro: public NetworkMessage{
private:
static const int maxVersionStringSize= 64;
static const int maxNameSize= 16;
private:
struct Data{
int8 messageType;
NetworkString<maxVersionStringSize> versionString;
NetworkString<maxNameSize> name;
int16 playerIndex;
};
private:
Data data;
public:
NetworkMessageIntro();
NetworkMessageIntro(const string &versionString, const string &name, int playerIndex);
string getVersionString() const {return data.versionString.getString();}
string getName() const {return data.name.getString();}
int getPlayerIndex() const {return data.playerIndex;}
virtual bool receive(Socket* socket);
virtual void send(Socket* socket) const;
};
// =====================================================
// class NetworkMessageReady
//
// Message sent at the beggining of the game
// =====================================================
class NetworkMessageReady: public NetworkMessage{
private:
struct Data{
int8 messageType;
int32 checksum;
};
private:
Data data;
public:
NetworkMessageReady();
NetworkMessageReady(int32 checksum);
int32 getChecksum() const {return data.checksum;}
virtual bool receive(Socket* socket);
virtual void send(Socket* socket) const;
};
// =====================================================
// class NetworkMessageLaunch
//
// Message sent from the server to the client
// to launch the game
// =====================================================
class NetworkMessageLaunch: public NetworkMessage{
private:
static const int maxStringSize= 256;
private:
struct Data{
int8 messageType;
NetworkString<maxStringSize> description;
NetworkString<maxStringSize> map;
NetworkString<maxStringSize> tileset;
NetworkString<maxStringSize> tech;
NetworkString<maxStringSize> factionTypeNames[GameConstants::maxPlayers]; //faction names
int8 factionControls[GameConstants::maxPlayers];
int8 thisFactionIndex;
int8 factionCount;
int8 teams[GameConstants::maxPlayers];
int8 startLocationIndex[GameConstants::maxPlayers];
int8 defaultResources;
int8 defaultUnits;
int8 defaultVictoryConditions;
};
private:
Data data;
public:
NetworkMessageLaunch();
NetworkMessageLaunch(const GameSettings *gameSettings);
void buildGameSettings(GameSettings *gameSettings) const;
virtual bool receive(Socket* socket);
virtual void send(Socket* socket) const;
};
// =====================================================
// class CommandList
//
// Message to order a commands to several units
// =====================================================
#pragma pack(push, 1)
class NetworkMessageCommandList: public NetworkMessage{
private:
static const int maxCommandCount= 16*4;
private:
struct Data{
int8 messageType;
int8 commandCount;
int32 frameCount;
NetworkCommand commands[maxCommandCount];
};
private:
Data data;
public:
NetworkMessageCommandList(int32 frameCount= -1);
bool addCommand(const NetworkCommand* networkCommand);
void clear() {data.commandCount= 0;}
int getCommandCount() const {return data.commandCount;}
int getFrameCount() const {return data.frameCount;}
const NetworkCommand* getCommand(int i) const {return &data.commands[i];}
virtual bool receive(Socket* socket);
virtual void send(Socket* socket) const;
};
#pragma pack(pop)
// =====================================================
// class NetworkMessageText
//
// Chat text message
// =====================================================
class NetworkMessageText: public NetworkMessage{
private:
static const int maxStringSize= 64;
private:
struct Data{
int8 messageType;
NetworkString<maxStringSize> text;
NetworkString<maxStringSize> sender;
int8 teamIndex;
};
private:
Data data;
public:
NetworkMessageText(){}
NetworkMessageText(const string &text, const string &sender, int teamIndex);
string getText() const {return data.text.getString();}
string getSender() const {return data.sender.getString();}
int getTeamIndex() const {return data.teamIndex;}
virtual bool receive(Socket* socket);
virtual void send(Socket* socket) const;
};
// =====================================================
// class NetworkMessageQuit
//
// Message sent at the beggining of the game
// =====================================================
class NetworkMessageQuit: public NetworkMessage{
private:
struct Data{
int8 messageType;
};
private:
Data data;
public:
NetworkMessageQuit();
virtual bool receive(Socket* socket);
virtual void send(Socket* socket) const;
};
// =====================================================
// class NetworkMessageSynchNetworkGameData
//
// Message sent at the beggining of a network game
// =====================================================
class NetworkMessageSynchNetworkGameData: public NetworkMessage{
private:
static const int maxStringSize= 256;
private:
struct Data{
int8 messageType;
NetworkString<maxStringSize> map;
NetworkString<maxStringSize> tileset;
NetworkString<maxStringSize> tech;
int32 mapCRC;
int32 tilesetCRC;
int32 techCRC;
int8 hasFogOfWar;
};
private:
Data data;
public:
NetworkMessageSynchNetworkGameData() {};
NetworkMessageSynchNetworkGameData(const GameSettings *gameSettings);
virtual bool receive(Socket* socket);
virtual void send(Socket* socket) const;
string getMap() const {return data.map.getString();}
string getTileset() const {return data.tileset.getString();}
string getTech() const {return data.tech.getString();}
int32 getMapCRC() const {return data.mapCRC;}
int32 getTilesetCRC() const {return data.tilesetCRC;}
int32 getTechCRC() const {return data.techCRC;}
int8 getFogOfWar() const { return data.hasFogOfWar; }
};
// =====================================================
// class NetworkMessageSynchNetworkGameDataStatus
//
// Message sent at the beggining of a network game
// =====================================================
class NetworkMessageSynchNetworkGameDataStatus: public NetworkMessage{
private:
static const int maxStringSize= 256;
private:
struct Data{
int8 messageType;
int32 mapCRC;
int32 tilesetCRC;
int32 techCRC;
int8 hasFogOfWar;
};
private:
Data data;
public:
NetworkMessageSynchNetworkGameDataStatus() {};
NetworkMessageSynchNetworkGameDataStatus(int32 mapCRC, int32 tilesetCRC, int32 techCRC, int8 hasFogOfWar);
virtual bool receive(Socket* socket);
virtual void send(Socket* socket) const;
int32 getMapCRC() const {return data.mapCRC;}
int32 getTilesetCRC() const {return data.tilesetCRC;}
int32 getTechCRC() const {return data.techCRC;}
int8 getFogOfWar() const { return data.hasFogOfWar; }
};
// =====================================================
// class NetworkMessageSynchNetworkGameDataFileCRCCheck
//
// Message sent at the beggining of a network game
// =====================================================
class NetworkMessageSynchNetworkGameDataFileCRCCheck: public NetworkMessage{
private:
static const int maxStringSize= 256;
private:
struct Data{
int8 messageType;
int32 totalFileCount;
int32 fileIndex;
int32 fileCRC;
NetworkString<maxStringSize> fileName;
};
private:
Data data;
public:
NetworkMessageSynchNetworkGameDataFileCRCCheck() {};
NetworkMessageSynchNetworkGameDataFileCRCCheck(int32 totalFileCount, int32 fileIndex, int32 fileCRC, const string fileName);
virtual bool receive(Socket* socket);
virtual void send(Socket* socket) const;
int32 getTotalFileCount() const {return data.totalFileCount;}
int32 getFileIndex() const {return data.fileIndex;}
int32 getFileCRC() const {return data.fileCRC;}
string getFileName() const {return data.fileName.getString();}
};
// =====================================================
// class NetworkMessageSynchNetworkGameDataFileGet
//
// Message sent at the beggining of a network game
// =====================================================
class NetworkMessageSynchNetworkGameDataFileGet: public NetworkMessage{
private:
static const int maxStringSize= 256;
private:
struct Data{
int8 messageType;
NetworkString<maxStringSize> fileName;
};
private:
Data data;
public:
NetworkMessageSynchNetworkGameDataFileGet() {};
NetworkMessageSynchNetworkGameDataFileGet(const string fileName);
virtual bool receive(Socket* socket);
virtual void send(Socket* socket) const;
string getFileName() const {return data.fileName.getString();}
};
}}//end namespace
#endif

View File

@ -265,7 +265,7 @@ T* FileReader<T>::read(const string& filepath, T* object) const {
if (!file.is_open()) { //An error occured; TODO: Which one - throw an exception, print error message?
throw runtime_error("Could not open file " + filepath);
}
read(file,filepath,object);
return read(file,filepath,object);
}

View File

@ -31,7 +31,8 @@ namespace ImageRegisterer {
bool registerImageReaders();
//Since you can't call void methods here, I have used a method doing nothing except initializing the image Readers
static bool readersRegistered = registerImageReaders(); //should always return true, this should guarantee that the readers are registered <--> ImageReaders is included anywhere
// this static initialisation relies on other static initialisations. == bad! [was quick-fixed, registerImageReaders() is called from main()]
// static bool readersRegistered = registerImageReaders(); //should always return true, this should guarantee that the readers are registered <--> ImageReaders is included anywhere
}
}} //end namespace