Updated with initial 3.4.4 codebase includes:

- network fixes for multiplayer defects found
- initial code (disabled currently) for content crc checking and downloading
- code compiles on Win32 using VS2008 express, project files not yet included
This commit is contained in:
Mark Vejvoda 2010-02-03 01:09:50 +00:00
parent 58ea5ec552
commit fb5035c230
47 changed files with 4527 additions and 1329 deletions

View File

@ -1,11 +1,11 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<EFBFBD>o Figueroa
// 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
// 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
// ==============================================================
@ -22,7 +22,7 @@ using namespace Shared::Util;
namespace Glest{ namespace Game{
const string mailString= "contact_game@glest.org";
const string glestVersionString= "v3.2.3";
const string glestVersionString= "v3.2.4-4-beta1";
string getCrashDumpFileName(){
return "glest"+glestVersionString+".dmp";
@ -52,11 +52,11 @@ string getAboutString2(int i){
string getTeammateName(int i){
switch(i){
case 0: return "Marti<EFBFBD>o Figueroa";
case 1: return "Jos<EFBFBD> Luis Gonz<6E>lez";
case 2: return "Tucho Fern<EFBFBD>ndez";
case 3: return "Jos<EFBFBD> Zanni";
case 4: return "F<EFBFBD>lix Men<65>ndez";
case 0: return "Martiño Figueroa";
case 1: return "José Luis González";
case 2: return "Tucho Fernández";
case 3: return "José Zanni";
case 4: return "Félix Menéndez";
case 5: return "Marcos Caruncho";
case 6: return "Matthias Braun";
}

View File

@ -3,9 +3,9 @@
//
// 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
// 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
// ==============================================================
@ -40,7 +40,7 @@ void ChatManager::init(Console* console, int thisTeamIndex){
}
void ChatManager::keyDown(char key){
Lang &lang= Lang::getInstance();
//toggle team mode
@ -86,18 +86,24 @@ void ChatManager::keyPress(char c){
}
}
void ChatManager::updateNetwork(){
void ChatManager::updateNetwork()
{
GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface();
string text;
string sender;
if(!gameNetworkInterface->getChatText().empty()){
if(!gameNetworkInterface->getChatText().empty())
{
int teamIndex= gameNetworkInterface->getChatTeamIndex();
if(Socket::enableDebugText) printf("In [%s::%s] got nmtText [%s] for team = %d\n",__FILE__,__FUNCTION__,gameNetworkInterface->getChatText().c_str(),teamIndex);
if(teamIndex==-1 || teamIndex==thisTeamIndex){
console->addLine(gameNetworkInterface->getChatSender()+": "+gameNetworkInterface->getChatText(), true);
if(Socket::enableDebugText) printf("In [%s::%s] Added text to console\n",__FILE__,__FUNCTION__);
}
}
}
}}//end namespace

View File

@ -3,9 +3,9 @@
//
// 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
// 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
// ==============================================================
@ -64,7 +64,7 @@ Game::~Game(){
logger.setState(Lang::getInstance().get("Deleting"));
logger.add("Game", true);
renderer.endGame();
SoundRenderer::getInstance().stopAllSounds();
@ -75,7 +75,7 @@ Game::~Game(){
}
// ==================== init and load ====================
// ==================== init and load ====================
void Game::load(){
Logger &logger= Logger::getInstance();
@ -83,7 +83,7 @@ void Game::load(){
string tilesetName= gameSettings.getTileset();
string techName= gameSettings.getTech();
string scenarioName= gameSettings.getScenario();
logger.setState(Lang::getInstance().get("Loading"));
if(scenarioName.empty()){
@ -114,7 +114,10 @@ void Game::load(){
}
}
void Game::init(){
void Game::init()
{
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
Lang &lang= Lang::getInstance();
Logger &logger= Logger::getInstance();
CoreData &coreData= CoreData::getInstance();
@ -122,8 +125,9 @@ void Game::init(){
Map *map= world.getMap();
NetworkManager &networkManager= NetworkManager::getInstance();
if(Socket::enableDebugText) printf("In [%s::%s] Initializing\n",__FILE__,__FUNCTION__);
logger.setState(lang.get("Initializing"));
//mesage box
mainMessageBox.init(lang.get("Yes"), lang.get("No"));
mainMessageBox.setEnabled(false);
@ -143,6 +147,8 @@ void Game::init(){
gameCamera.setPos(Vec2f(v.x, v.y));
scriptManager.init(&world, &gameCamera);
if(Socket::enableDebugText) printf("In [%s::%s] creating AI's\n",__FILE__,__FUNCTION__);
//create IAs
aiInterfaces.resize(world.getFactionCount());
for(int i=0; i<world.getFactionCount(); ++i){
@ -174,12 +180,13 @@ void Game::init(){
}
//init renderer state
if(Socket::enableDebugText) printf("In [%s::%s] Initializing renderer\n",__FILE__,__FUNCTION__);
logger.add("Initializing renderer", true);
renderer.initGame(this);
//sounds
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
Tileset *tileset= world.getTileset();
AmbientSounds *ambientSounds= tileset->getAmbientSounds();
@ -188,36 +195,40 @@ void Game::init(){
logger.add("Starting ambient stream", true);
soundRenderer.playAmbient(ambientSounds->getRain());
}
//snow
if(tileset->getWeather()==wSnowy && ambientSounds->isEnabledSnow()){
logger.add("Starting ambient stream", true);
soundRenderer.playAmbient(ambientSounds->getSnow());
}
if(Socket::enableDebugText) printf("In [%s::%s] Waiting for network\n",__FILE__,__FUNCTION__);
logger.add("Waiting for network", true);
networkManager.getGameNetworkInterface()->waitUntilReady(&checksum);
if(Socket::enableDebugText) printf("In [%s::%s] Starting music stream\n",__FILE__,__FUNCTION__);
logger.add("Starting music stream", true);
StrSound *gameMusic= world.getThisFaction()->getType()->getMusic();
soundRenderer.playMusic(gameMusic);
logger.add("Launching game");
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
}
// ==================== update ====================
// ==================== update ====================
//update
void Game::update(){
// a) Updates non dependant on speed
//misc
updateFps++;
mouse2d= (mouse2d+1) % Renderer::maxMouse2dAnim;
//console
//console
console.update();
// b) Updates depandant on speed
@ -231,7 +242,7 @@ void Game::update(){
//AiInterface
for(int i=0; i<world.getFactionCount(); ++i){
if(world.getFaction(i)->getCpuControl() && scriptManager.getPlayerModifiers(i)->getAiEnabled()){
aiInterfaces[i]->update();
aiInterfaces[i]->update();
}
}
@ -243,7 +254,7 @@ void Game::update(){
//Gui
gui.update();
//Particle systems
if(weatherParticleSystem != NULL){
weatherParticleSystem->setPos(gameCamera.getPos());
@ -270,7 +281,7 @@ void Game::updateCamera(){
}
// ==================== render ====================
// ==================== render ====================
//render
void Game::render(){
@ -280,7 +291,7 @@ void Game::render(){
Renderer::getInstance().swapBuffers();
}
// ==================== tick ====================
// ==================== tick ====================
void Game::tick(){
lastUpdateFps= updateFps;
@ -294,7 +305,7 @@ void Game::tick(){
}
// ==================== events ====================
// ==================== events ====================
void Game::mouseDownLeft(int x, int y){
@ -315,12 +326,12 @@ void Game::mouseDownLeft(int x, int y){
//minimap panel
if(!messageBoxClick){
if(metrics.isInMinimap(x, y) && !gui.isSelectingPos()){
int xm= x - metrics.getMinimapX();
int ym= y - metrics.getMinimapY();
int xCell= static_cast<int>(xm * (static_cast<float>(map->getW()) / metrics.getMinimapW()));
int yCell= static_cast<int>(map->getH() - ym * (static_cast<float>(map->getH()) / metrics.getMinimapH()));
if(map->isInside(xCell, yCell)){
if(!gui.isSelectingPos()){
gameCamera.setPos(Vec2f(static_cast<float>(xCell), static_cast<float>(yCell)));
@ -333,13 +344,13 @@ void Game::mouseDownLeft(int x, int y){
int xd= x - metrics.getDisplayX();
int yd= y - metrics.getDisplayY();
if(gui.mouseValid(xd, yd)){
gui.mouseDownLeftDisplay(xd, yd);
gui.mouseDownLeftDisplay(xd, yd);
}
else{
gui.mouseDownLeftGraphics(x, y);
}
}
//graphics panel
else{
gui.mouseDownLeftGraphics(x, y);
@ -349,12 +360,15 @@ void Game::mouseDownLeft(int x, int y){
//exit message box, has to be the last thing to do in this function
if(mainMessageBox.getEnabled()){
int button= 1;
if(mainMessageBox.mouseClick(x, y, button)){
if(button==1){
networkManager.getGameNetworkInterface()->quitGame();
if(mainMessageBox.mouseClick(x, y, button))
{
if(button==1)
{
networkManager.getGameNetworkInterface()->quitGame(true);
quitGame();
}
else{
else
{
//close message box
mainMessageBox.setEnabled(false);
}
@ -372,7 +386,7 @@ void Game::mouseUpLeft(int x, int y){
void Game::mouseDoubleClickLeft(int x, int y){
const Metrics &metrics= Metrics::getInstance();
//display panel
if(metrics.isInDisplay(x, y) && !gui.isSelectingPos()){
int xd= x - metrics.getDisplayX();
@ -389,28 +403,28 @@ void Game::mouseDoubleClickLeft(int x, int y){
void Game::mouseMove(int x, int y, const MouseState *ms){
const Metrics &metrics= Metrics::getInstance();
mouseX= x;
mouseY= y;
//main window
if(y<10){
if(y<10){
gameCamera.setMoveZ(-1);
}
else if(y> metrics.getVirtualH()-10){
else if(y> metrics.getVirtualH()-10){
gameCamera.setMoveZ(1);
}
else{
else{
gameCamera.stopMoveZ();
}
if(x<10){
if(x<10){
gameCamera.setMoveX(-1);
}
else if(x> metrics.getVirtualW()-10){
else if(x> metrics.getVirtualW()-10){
gameCamera.setMoveX(1);
}
else{
else{
gameCamera.stopMoveX();
}
@ -449,7 +463,7 @@ void Game::keyDown(char key){
else if(key=='E'){
for(int i=0; i<100; ++i){
string path= "screens/screen" + intToStr(i) + ".tga";
FILE *f= fopen(path.c_str(), "rb");
if(f==NULL){
Renderer::getInstance().saveScreen(path);
@ -592,9 +606,9 @@ void Game::quitGame(){
program->setState(new BattleEnd(program, world.getStats()));
}
// ==================== PRIVATE ====================
// ==================== PRIVATE ====================
// ==================== render ====================
// ==================== render ====================
void Game::render3d(){
@ -630,7 +644,7 @@ void Game::render3d(){
//particles
renderer.renderParticleManager(rsGame);
//mouse 3d
renderer.renderMouse3d();
}
@ -642,10 +656,10 @@ void Game::render2d(){
//init
renderer.reset2d();
//display
renderer.renderDisplay();
//minimap
if(!config.getBool("PhotoMode")){
renderer.renderMinimap();
@ -687,7 +701,7 @@ void Game::render2d(){
str+= "Triangle count: "+intToStr(renderer.getTriangleCount())+"\n";
str+= "Vertex count: "+intToStr(renderer.getPointCount())+"\n";
str+= "Frame count:"+intToStr(world.getFrameCount())+"\n";
//visible quad
Quad2i visibleQuad= renderer.getVisibleQuad();
@ -716,7 +730,7 @@ void Game::render2d(){
//network status
if(renderNetworkStatus){
renderer.renderText(
NetworkManager::getInstance().getGameNetworkInterface()->getNetworkStatus(),
NetworkManager::getInstance().getGameNetworkInterface()->getNetworkStatus(),
coreData.getMenuFontNormal(),
Vec3f(1.0f), 20, 500, false);
}
@ -726,15 +740,15 @@ void Game::render2d(){
renderer.renderResourceStatus();
renderer.renderConsole(&console);
}
//2d mouse
renderer.renderMouse2d(mouseX, mouseY, mouse2d, gui.isSelectingPos()? 1.f: 0.f);
}
// ==================== misc ====================
// ==================== misc ====================
void Game::checkWinner(){
void Game::checkWinner(){
if(!gameOver){
if(gameSettings.getDefaultVictoryConditions()){
checkWinnerStandard();
@ -753,7 +767,7 @@ void Game::checkWinnerStandard(){
lose= true;
for(int i=0; i<world.getFactionCount(); ++i){
if(!world.getFaction(i)->isAlly(world.getThisFaction())){
world.getStats()->setVictorious(i);
world.getStats()->setVictorious(i);
}
}
gameOver= true;
@ -775,7 +789,7 @@ void Game::checkWinnerStandard(){
if(win){
for(int i=0; i< world.getFactionCount(); ++i){
if(world.getFaction(i)->isAlly(world.getThisFaction())){
world.getStats()->setVictorious(i);
world.getStats()->setVictorious(i);
}
}
gameOver= true;
@ -789,7 +803,7 @@ void Game::checkWinnerScripted(){
gameOver= true;
for(int i= 0; i<world.getFactionCount(); ++i){
if(scriptManager.getPlayerModifiers(i)->getWinner()){
world.getStats()->setVictorious(i);
world.getStats()->setVictorious(i);
}
}
if(scriptManager.getPlayerModifiers(world.getThisFactionIndex())->getWinner()){
@ -869,7 +883,7 @@ void Game::showMessageBox(const string &text, const string &header, bool toggle)
if(!toggle){
mainMessageBox.setEnabled(false);
}
if(!mainMessageBox.getEnabled()){
mainMessageBox.setText(text);
mainMessageBox.setHeader(header);

View File

@ -1,7 +1,7 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<EFBFBD>o Figueroa
// 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

View File

@ -3,9 +3,9 @@
//
// 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
// 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
// ==============================================================
@ -41,7 +41,50 @@ private:
bool defaultResources;
bool defaultVictoryConditions;
public:
void CopyAll(const GameSettings &game)
{
description = game.description;
map = game.map;
tileset = game.tileset;
tech = game.tech;
scenario = game.scenario;
scenarioDir = game.scenarioDir;
thisFactionIndex = game.thisFactionIndex;
factionCount = game.factionCount;
defaultUnits = game.defaultUnits;
defaultResources = game.defaultResources;
defaultVictoryConditions = game.defaultVictoryConditions;
for(int i = 0; i < GameConstants::maxPlayers; i++)
{
factionTypeNames[i] = game.factionTypeNames[i]; //faction names
factionControls[i] = game.factionControls[i];
teams[i] = game.teams[i];
startLocationIndex[i] = game.startLocationIndex[i];
}
//if(Socket::enableDebugText) printf("In [%s::%s] gameSettings->getTileset() = [%s]\n",__FILE__,__FUNCTION__,getTileset().c_str());
//if(Socket::enableDebugText) printf("In [%s::%s] gameSettings->getTech() = [%s]\n",__FILE__,__FUNCTION__,getTech().c_str());
//if(Socket::enableDebugText) printf("In [%s::%s] gameSettings->getMap() = [%s]\n",__FILE__,__FUNCTION__,getMap().c_str());
}
public:
GameSettings() { }
GameSettings(const GameSettings &game)
{
CopyAll(game);
}
GameSettings & operator=(const GameSettings &game)
{
CopyAll(game);
return *this;
}
//get
const string &getDescription() const {return description;}
const string &getMap() const {return map;}
@ -53,7 +96,7 @@ public:
ControlType getFactionControl(int factionIndex) const {return factionControls[factionIndex];}
int getThisFactionIndex() const {return thisFactionIndex;}
int getFactionCount() const {return factionCount;}
int getFactionCount() const {return factionCount;}
int getTeam(int factionIndex) const {return teams[factionIndex];}
int getStartLocationIndex(int factionIndex) const {return startLocationIndex[factionIndex];}
@ -74,7 +117,7 @@ public:
void setFactionControl(int factionIndex, ControlType controller) {this->factionControls[factionIndex]= controller;}
void setThisFactionIndex(int thisFactionIndex) {this->thisFactionIndex= thisFactionIndex;}
void setFactionCount(int factionCount) {this->factionCount= factionCount;}
void setFactionCount(int factionCount) {this->factionCount= factionCount;}
void setTeam(int factionIndex, int team) {this->teams[factionIndex]= team;}
void setStartLocationIndex(int factionIndex, int startLocationIndex) {this->startLocationIndex[factionIndex]= startLocationIndex;}

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<EFBFBD>o Figueroa
// 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

View File

@ -3,9 +3,9 @@
//
// 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
// 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
// ==============================================================
@ -41,7 +41,7 @@ namespace Glest{ namespace Game{
const int Program::maxTimes= 10;
// ===================== PUBLIC ========================
// ===================== PUBLIC ========================
Program::Program(){
programState= NULL;
@ -54,7 +54,7 @@ void Program::initNormal(WindowGl *window){
void Program::initServer(WindowGl *window){
MainMenu* mainMenu= NULL;
init(window);
mainMenu= new MainMenu(this);
setState(mainMenu);
@ -63,7 +63,7 @@ void Program::initServer(WindowGl *window){
void Program::initClient(WindowGl *window, const Ip &serverIp){
MainMenu* mainMenu= NULL;
init(window);
mainMenu= new MainMenu(this);
setState(mainMenu);
@ -72,14 +72,14 @@ void Program::initClient(WindowGl *window, const Ip &serverIp){
Program::~Program(){
delete programState;
Renderer::getInstance().end();
//restore video mode
restoreDisplaySettings();
}
void Program::mouseDownLeft(int x, int y){
void Program::mouseDownLeft(int x, int y){
const Metrics &metrics= Metrics::getInstance();
programState->mouseDownLeft(metrics.toVirtualX(x), metrics.toVirtualY(y));
}
@ -91,12 +91,12 @@ void Program::mouseUpLeft(int x, int y){
void Program::mouseDownRight(int x, int y){
const Metrics &metrics= Metrics::getInstance();
programState->mouseDownRight(metrics.toVirtualX(x), metrics.toVirtualY(y));
programState->mouseDownRight(metrics.toVirtualX(x), metrics.toVirtualY(y));
}
void Program::mouseDoubleClickLeft(int x, int y){
const Metrics &metrics= Metrics::getInstance();
programState->mouseDoubleClickLeft(metrics.toVirtualX(x), metrics.toVirtualY(y));
programState->mouseDoubleClickLeft(metrics.toVirtualX(x), metrics.toVirtualY(y));
}
void Program::mouseMove(int x, int y, const MouseState *ms){
@ -109,7 +109,7 @@ void Program::keyDown(char key){
programState->keyDown(key);
}
void Program::keyUp(char key){
void Program::keyUp(char key){
programState->keyUp(key);
}
@ -134,7 +134,7 @@ void Program::loop(){
SoundRenderer::getInstance().update();
NetworkManager::getInstance().update();
}
//fps timer
while(fpsTimer.isTime()){
programState->tick();
@ -142,7 +142,7 @@ void Program::loop(){
}
void Program::resize(SizeState sizeState){
switch(sizeState){
case ssMinimized:
//restoreVideoMode();
@ -155,32 +155,44 @@ void Program::resize(SizeState sizeState){
}
}
// ==================== misc ====================
// ==================== misc ====================
void Program::setState(ProgramState *programState)
{
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
void Program::setState(ProgramState *programState){
delete this->programState;
if(Socket::enableDebugText) printf("In [%s::%s] A\n",__FILE__,__FUNCTION__);
this->programState= programState;
programState->load();
if(Socket::enableDebugText) printf("In [%s::%s] B\n",__FILE__,__FUNCTION__);
programState->init();
if(Socket::enableDebugText) printf("In [%s::%s] C\n",__FILE__,__FUNCTION__);
updateTimer.reset();
updateCameraTimer.reset();
fpsTimer.reset();
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
}
void Program::exit(){
window->destroy();
}
// ==================== PRIVATE ====================
// ==================== PRIVATE ====================
void Program::init(WindowGl *window){
this->window= window;
Config &config= Config::getInstance();
//set video mode
setDisplaySettings();
@ -190,7 +202,7 @@ void Program::init(WindowGl *window){
window->setPos(0, 0);
window->setSize(config.getInt("ScreenWidth"), config.getInt("ScreenHeight"));
window->create();
//timers
fpsTimer.init(1, maxTimes);
updateTimer.init(GameConstants::updateFps, maxTimes);
@ -204,13 +216,13 @@ void Program::init(WindowGl *window){
//lang
Lang &lang= Lang::getInstance();
lang.loadStrings(config.getString("Lang"));
//render
Renderer &renderer= Renderer::getInstance();
window->initGl(config.getInt("ColorBits"), config.getInt("DepthBits"), config.getInt("StencilBits"));
window->makeCurrentGl();
//coreData, needs renderer, but must load before renderer init
CoreData &coreData= CoreData::getInstance();
coreData.load();
@ -226,29 +238,29 @@ void Program::init(WindowGl *window){
void Program::setDisplaySettings(){
Config &config= Config::getInstance();
if(!config.getBool("Windowed")){
int freq= config.getInt("RefreshFrequency");
int colorBits= config.getInt("ColorBits");
int screenWidth= config.getInt("ScreenWidth");
int screenHeight= config.getInt("ScreenHeight");
if(!(changeVideoMode(screenWidth, screenHeight, colorBits, freq) ||
changeVideoMode(screenWidth, screenHeight, colorBits, 0)))
{
throw runtime_error(
"Error setting video mode: " +
"Error setting video mode: " +
intToStr(screenWidth) + "x" + intToStr(screenHeight) + "x" + intToStr(colorBits));
}
}
}
}
void Program::restoreDisplaySettings(){
Config &config= Config::getInstance();
if(!config.getBool("Windowed")){
restoreVideoMode();
restoreVideoMode();
}
}

View File

@ -1,11 +1,11 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2005 Marti<EFBFBD>o Figueroa
// Copyright (C) 2001-2005 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
// 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
// ==============================================================
@ -25,6 +25,7 @@
#include "game.h"
#include "leak_dumper.h"
#include <time.h>
namespace Glest{ namespace Game{
@ -34,12 +35,15 @@ using namespace Shared::Util;
// class MenuStateCustomGame
// =====================================================
MenuStateCustomGame::MenuStateCustomGame(Program *program, MainMenu *mainMenu, bool openNetworkSlots):
MenuStateCustomGame::MenuStateCustomGame(Program *program, MainMenu *mainMenu, bool openNetworkSlots):
MenuState(program, mainMenu, "new-game")
{
Lang &lang= Lang::getInstance();
NetworkManager &networkManager= NetworkManager::getInstance();
needToSetChangedGameSettings = false;
lastSetChangedGameSettings = time(NULL);;
vector<string> results, teamItems, controlItems;
//create
@ -121,12 +125,12 @@ MenuStateCustomGame::MenuStateCustomGame(Program *program, MainMenu *mainMenu, b
if(results.size()==0){
throw runtime_error("There is no factions for this tech tree");
}
for(int i=0; i<GameConstants::maxPlayers; ++i){
labelPlayers[i].setText(lang.get("Player")+" "+intToStr(i));
listBoxTeams[i].setItems(teamItems);
listBoxTeams[i].setSelectedItemIndex(i);
listBoxControls[i].setItems(controlItems);
listBoxControls[i].setItems(controlItems);
labelNetStatus[i].setText("");
}
@ -138,7 +142,7 @@ MenuStateCustomGame::MenuStateCustomGame(Program *program, MainMenu *mainMenu, b
labelTeam.setText(lang.get("Team"));
loadMapInfo(Map::getMapPath(mapFiles[listBoxMap.getSelectedItemIndex()]), &mapInfo);
labelMapInfo.setText(mapInfo.desc);
//initialize network interface
@ -156,6 +160,9 @@ MenuStateCustomGame::MenuStateCustomGame(Program *program, MainMenu *mainMenu, b
}
updateControlers();
updateNetworkSlots();
//chatManager.init(&console, world.getThisTeamIndex());
chatManager.init(&console, -1);
}
void MenuStateCustomGame::mouseClick(int x, int y, MouseButton mouseButton){
@ -167,31 +174,67 @@ void MenuStateCustomGame::mouseClick(int x, int y, MouseButton mouseButton){
if(buttonReturn.mouseClick(x,y)){
soundRenderer.playFx(coreData.getClickSoundA());
mainMenu->setState(new MenuStateNewGame(program, mainMenu));
}
else if(buttonPlayNow.mouseClick(x,y)){
GameSettings gameSettings;
}
else if(buttonPlayNow.mouseClick(x,y) && buttonPlayNow.getEnabled()) {
closeUnusedSlots();
soundRenderer.playFx(coreData.getClickSoundC());
GameSettings gameSettings;
loadGameSettings(&gameSettings);
serverInterface->launchGame(&gameSettings);
program->setState(new Game(program, &gameSettings));
// Send the game settings to each client if we have at least one networked client
if( hasNetworkGameSettings() == true &&
needToSetChangedGameSettings == true)
{
serverInterface->setGameSettings(&gameSettings,true);
needToSetChangedGameSettings = false;
lastSetChangedGameSettings = time(NULL);
}
bool bOkToStart = serverInterface->launchGame(&gameSettings);
if(bOkToStart == true)
{
program->setState(new Game(program, &gameSettings));
}
}
else if(listBoxMap.mouseClick(x, y)){
loadMapInfo(Map::getMapPath(mapFiles[listBoxMap.getSelectedItemIndex()]), &mapInfo);
labelMapInfo.setText(mapInfo.desc);
updateControlers();
if(hasNetworkGameSettings() == true)
{
needToSetChangedGameSettings = true;
lastSetChangedGameSettings = time(NULL);;
}
}
else if(listBoxTileset.mouseClick(x, y)){
if(hasNetworkGameSettings() == true)
{
needToSetChangedGameSettings = true;
lastSetChangedGameSettings = time(NULL);;
}
}
else if(listBoxTechTree.mouseClick(x, y)){
reloadFactions();
}
else{
for(int i=0; i<mapInfo.players; ++i){
//ensure thet only 1 human player is present
if(listBoxControls[i].mouseClick(x, y)){
if(hasNetworkGameSettings() == true)
{
needToSetChangedGameSettings = true;
lastSetChangedGameSettings = time(NULL);;
}
}
else
{
for(int i=0; i<mapInfo.players; ++i)
{
//ensure thet only 1 human player is present
if(listBoxControls[i].mouseClick(x, y))
{
//look for human players
int humanIndex1= -1;
int humanIndex2= -1;
@ -217,17 +260,35 @@ void MenuStateCustomGame::mouseClick(int x, int y, MouseButton mouseButton){
listBoxControls[humanIndex1==i? humanIndex2: humanIndex1].setSelectedItemIndex(ctClosed);
}
updateNetworkSlots();
if(hasNetworkGameSettings() == true)
{
needToSetChangedGameSettings = true;
lastSetChangedGameSettings = time(NULL);;
}
}
else if(listBoxFactions[i].mouseClick(x, y)){
if(hasNetworkGameSettings() == true)
{
needToSetChangedGameSettings = true;
lastSetChangedGameSettings = time(NULL);;
}
}
else if(listBoxTeams[i].mouseClick(x, y)){
else if(listBoxTeams[i].mouseClick(x, y))
{
if(hasNetworkGameSettings() == true)
{
needToSetChangedGameSettings = true;
lastSetChangedGameSettings = time(NULL);;
}
}
}
}
}
void MenuStateCustomGame::mouseMove(int x, int y, const MouseState *ms){
buttonReturn.mouseMove(x, y);
buttonPlayNow.mouseMove(x, y);
@ -270,33 +331,131 @@ void MenuStateCustomGame::render(){
renderer.renderListBox(&listBoxMap);
renderer.renderListBox(&listBoxTileset);
renderer.renderListBox(&listBoxTechTree);
renderer.renderChatManager(&chatManager);
renderer.renderConsole(&console);
}
void MenuStateCustomGame::update(){
void MenuStateCustomGame::update()
{
ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface();
Lang& lang= Lang::getInstance();
for(int i= 0; i<mapInfo.players; ++i){
if(listBoxControls[i].getSelectedItemIndex()==ctNetwork){
bool haveAtLeastOneNetworkClientConnected = false;
for(int i= 0; i<mapInfo.players; ++i)
{
if(listBoxControls[i].getSelectedItemIndex() == ctNetwork)
{
//if(Socket::enableDebugText) printf("In [%s::%s] START - ctNetwork\n",__FILE__,__FUNCTION__);
ConnectionSlot* connectionSlot= serverInterface->getSlot(i);
assert(connectionSlot!=NULL);
if(connectionSlot->isConnected()){
labelNetStatus[i].setText(connectionSlot->getName());
//if(Socket::enableDebugText) printf("In [%s::%s] A - ctNetwork\n",__FILE__,__FUNCTION__);
if(connectionSlot->isConnected())
{
haveAtLeastOneNetworkClientConnected = true;
//if(Socket::enableDebugText) printf("In [%s::%s] B - ctNetwork\n",__FILE__,__FUNCTION__);
string label = connectionSlot->getName();
if(connectionSlot->getAllowDownloadDataSynch() == true &&
connectionSlot->getAllowGameDataSynchCheck() == true)
{
if(connectionSlot->getNetworkGameDataSynchCheckOk() == false)
{
label = connectionSlot->getName() + " - waiting to synch:";
if(connectionSlot->getNetworkGameDataSynchCheckOkMap() == false)
{
label = label + " map";
}
if(connectionSlot->getNetworkGameDataSynchCheckOkTile() == false)
{
label = label + " tile";
}
if(connectionSlot->getNetworkGameDataSynchCheckOkTech() == false)
{
label = label + " techtree";
}
if(connectionSlot->getNetworkGameDataSynchCheckOkFogOfWar() == false)
{
label = label + " FogOfWar == false";
}
}
else
{
label = connectionSlot->getName() + " - data synch is ok";
}
}
else
{
label = connectionSlot->getName();
if(connectionSlot->getAllowGameDataSynchCheck() == true)
{
label += " - warning synch mismatch for:";
if(connectionSlot->getNetworkGameDataSynchCheckOkMap() == false)
{
label = label + " map";
}
if(connectionSlot->getNetworkGameDataSynchCheckOkTile() == false)
{
label = label + " tile";
}
if(connectionSlot->getNetworkGameDataSynchCheckOkTech() == false)
{
label = label + " techtree";
}
if(connectionSlot->getNetworkGameDataSynchCheckOkFogOfWar() == false)
{
label = label + " FogOfWar == false";
}
}
}
labelNetStatus[i].setText(label);
}
else
{
//if(Socket::enableDebugText) printf("In [%s::%s] C - ctNetwork\n",__FILE__,__FUNCTION__);
labelNetStatus[i].setText(lang.get("NotConnected"));
}
//if(Socket::enableDebugText) printf("In [%s::%s] END - ctNetwork\n",__FILE__,__FUNCTION__);
}
else{
labelNetStatus[i].setText("");
}
}
// Send the game settings to each client if we have at least one networked client
if( serverInterface->getAllowDownloadDataSynch() == true &&
haveAtLeastOneNetworkClientConnected == true &&
needToSetChangedGameSettings == true &&
difftime(time(NULL),lastSetChangedGameSettings) >= 2)
{
GameSettings gameSettings;
loadGameSettings(&gameSettings);
serverInterface->setGameSettings(&gameSettings);
needToSetChangedGameSettings = false;
lastSetChangedGameSettings = time(NULL);
}
//call the chat manager
chatManager.updateNetwork();
//console
console.update();
}
void MenuStateCustomGame::loadGameSettings(GameSettings *gameSettings){
void MenuStateCustomGame::loadGameSettings(GameSettings *gameSettings)
{
//if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
int factionCount= 0;
@ -307,11 +466,14 @@ void MenuStateCustomGame::loadGameSettings(GameSettings *gameSettings){
gameSettings->setDefaultUnits(true);
gameSettings->setDefaultResources(true);
gameSettings->setDefaultVictoryConditions(true);
for(int i=0; i<mapInfo.players; ++i){
for(int i=0; i<mapInfo.players; ++i)
{
ControlType ct= static_cast<ControlType>(listBoxControls[i].getSelectedItemIndex());
if(ct!=ctClosed){
if(ct==ctHuman){
if(ct != ctClosed)
{
if(ct == ctHuman)
{
gameSettings->setThisFactionIndex(factionCount);
}
gameSettings->setFactionControl(factionCount, ct);
@ -322,10 +484,36 @@ void MenuStateCustomGame::loadGameSettings(GameSettings *gameSettings){
}
}
gameSettings->setFactionCount(factionCount);
//if(Socket::enableDebugText) printf("In [%s::%s] gameSettings->getTileset() = [%s]\n",__FILE__,__FUNCTION__,gameSettings->getTileset().c_str());
//if(Socket::enableDebugText) printf("In [%s::%s] gameSettings->getTech() = [%s]\n",__FILE__,__FUNCTION__,gameSettings->getTech().c_str());
//if(Socket::enableDebugText) printf("In [%s::%s] gameSettings->getMap() = [%s]\n",__FILE__,__FUNCTION__,gameSettings->getMap().c_str());
//if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
}
// ============ PRIVATE ===========================
bool MenuStateCustomGame::hasNetworkGameSettings()
{
bool hasNetworkSlot = false;
for(int i=0; i<mapInfo.players; ++i)
{
ControlType ct= static_cast<ControlType>(listBoxControls[i].getSelectedItemIndex());
if(ct != ctClosed)
{
if(ct == ctNetwork)
{
hasNetworkSlot = true;
break;
}
}
}
return hasNetworkSlot;
}
void MenuStateCustomGame::loadMapInfo(string file, MapInfo *mapInfo){
struct MapFileHeader{
@ -364,7 +552,7 @@ void MenuStateCustomGame::loadMapInfo(string file, MapInfo *mapInfo){
}
void MenuStateCustomGame::reloadFactions(){
vector<string> results;
findAll("techs/"+techTreeFiles[listBoxTechTree.getSelectedItemIndex()]+"/factions/*.", results);
@ -383,7 +571,7 @@ void MenuStateCustomGame::reloadFactions(){
void MenuStateCustomGame::updateControlers(){
bool humanPlayer= false;
for(int i= 0; i<mapInfo.players; ++i){
if(listBoxControls[i].getSelectedItemIndex() == ctHuman){
humanPlayer= true;
@ -411,17 +599,33 @@ void MenuStateCustomGame::closeUnusedSlots(){
updateNetworkSlots();
}
void MenuStateCustomGame::updateNetworkSlots(){
void MenuStateCustomGame::updateNetworkSlots()
{
ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface();
for(int i= 0; i<GameConstants::maxPlayers; ++i){
if(serverInterface->getSlot(i)==NULL && listBoxControls[i].getSelectedItemIndex()==ctNetwork){
for(int i= 0; i<GameConstants::maxPlayers; ++i)
{
if(serverInterface->getSlot(i) == NULL && listBoxControls[i].getSelectedItemIndex() == ctNetwork)
{
serverInterface->addSlot(i);
}
if(serverInterface->getSlot(i) != NULL && listBoxControls[i].getSelectedItemIndex()!=ctNetwork){
if(serverInterface->getSlot(i) != NULL && listBoxControls[i].getSelectedItemIndex() != ctNetwork)
{
serverInterface->removeSlot(i);
}
}
}
void MenuStateCustomGame::keyDown(char key)
{
//send key to the chat manager
chatManager.keyDown(key);
}
void MenuStateCustomGame::keyPress(char c)
{
chatManager.keyPress(c);
}
}}//end namespace

View File

@ -3,9 +3,9 @@
//
// Copyright (C) 2001-2005 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
// 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
// ==============================================================
@ -13,11 +13,12 @@
#define _GLEST_GAME_MENUSTATECUSTOMGAME_H_
#include "main_menu.h"
#include "chat_manager.h"
namespace Glest{ namespace Game{
// ===============================
// class MenuStateCustomGame
// class MenuStateCustomGame
// ===============================
class MenuStateCustomGame: public MenuState{
@ -45,6 +46,12 @@ private:
GraphicLabel labelNetStatus[GameConstants::maxPlayers];
MapInfo mapInfo;
bool needToSetChangedGameSettings;
time_t lastSetChangedGameSettings;
Console console;
ChatManager chatManager;
public:
MenuStateCustomGame(Program *program, MainMenu *mainMenu, bool openNetworkSlots= false);
@ -53,7 +60,12 @@ public:
void render();
void update();
virtual void keyDown(char key);
virtual void keyPress(char c);
private:
bool hasNetworkGameSettings();
void loadGameSettings(GameSettings *gameSettings);
void loadMapInfo(string file, MapInfo *mapInfo);
void reloadFactions();

View File

@ -3,9 +3,9 @@
//
// Copyright (C) 2001-2005 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
// 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
// ==============================================================
@ -31,7 +31,7 @@ namespace Glest{ namespace Game{
using namespace Shared::Util;
// ===============================
// class MenuStateJoinGame
// class MenuStateJoinGame
// ===============================
const int MenuStateJoinGame::newServerIndex= 0;
@ -87,7 +87,8 @@ MenuStateJoinGame::MenuStateJoinGame(Program *program, MainMenu *mainMenu, bool
playerIndex= -1;
//server ip
if(connect){
if(connect)
{
labelServerIp.setText(serverIp.getString() + "_");
connectToServer();
}
@ -95,9 +96,13 @@ MenuStateJoinGame::MenuStateJoinGame(Program *program, MainMenu *mainMenu, bool
{
labelServerIp.setText(config.getString("ServerIp") + "_");
}
chatManager.init(&console, -1);
}
void MenuStateJoinGame::mouseClick(int x, int y, MouseButton mouseButton){
void MenuStateJoinGame::mouseClick(int x, int y, MouseButton mouseButton)
{
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
CoreData &coreData= CoreData::getInstance();
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
@ -121,25 +126,42 @@ void MenuStateJoinGame::mouseClick(int x, int y, MouseButton mouseButton){
}
//return
if(buttonReturn.mouseClick(x, y)){
if(buttonReturn.mouseClick(x, y))
{
soundRenderer.playFx(coreData.getClickSoundA());
if(clientInterface->getSocket() != NULL)
{
if(clientInterface->isConnected() == true)
{
string sQuitText = clientInterface->getHostName() + " has chosen to leave the game!";
clientInterface->sendTextMessage(sQuitText,-1);
}
clientInterface->close();
}
mainMenu->setState(new MenuStateRoot(program, mainMenu));
}
}
//connect
else if(buttonConnect.mouseClick(x, y)){
else if(buttonConnect.mouseClick(x, y))
{
ClientInterface* clientInterface= networkManager.getClientInterface();
soundRenderer.playFx(coreData.getClickSoundA());
labelInfo.setText("");
if(clientInterface->isConnected()){
if(clientInterface->isConnected())
{
clientInterface->reset();
}
else{
else
{
connectToServer();
}
}
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
}
void MenuStateJoinGame::mouseMove(int x, int y, const MouseState *ms){
@ -166,7 +188,7 @@ void MenuStateJoinGame::render(){
renderer.renderLabel(&labelInfo);
renderer.renderButton(&buttonConnect);
renderer.renderListBox(&listBoxServerType);
if(listBoxServerType.getSelectedItemIndex()==newServerIndex){
renderer.renderLabel(&labelServerIp);
}
@ -174,52 +196,145 @@ void MenuStateJoinGame::render(){
{
renderer.renderListBox(&listBoxServers);
}
renderer.renderChatManager(&chatManager);
renderer.renderConsole(&console);
}
void MenuStateJoinGame::update(){
void MenuStateJoinGame::update()
{
ClientInterface* clientInterface= NetworkManager::getInstance().getClientInterface();
Lang &lang= Lang::getInstance();
//update status label
if(clientInterface->isConnected()){
if(clientInterface->isConnected())
{
buttonConnect.setText(lang.get("Disconnect"));
if(!clientInterface->getServerName().empty()){
labelStatus.setText(lang.get("ConnectedToServer") + " " + clientInterface->getServerName());
if(clientInterface->getAllowDownloadDataSynch() == false)
{
string label = lang.get("ConnectedToServer");
if(!clientInterface->getServerName().empty())
{
label = label + " " + clientInterface->getServerName();
}
if(clientInterface->getAllowGameDataSynchCheck() == true &&
clientInterface->getNetworkGameDataSynchCheckOk() == false)
{
label = label + " - warning synch mismatch for:";
if(clientInterface->getNetworkGameDataSynchCheckOkMap() == false)
{
label = label + " map";
}
if(clientInterface->getNetworkGameDataSynchCheckOkTile() == false)
{
label = label + " tile";
}
if(clientInterface->getNetworkGameDataSynchCheckOkTech() == false)
{
label = label + " techtree";
}
if(clientInterface->getNetworkGameDataSynchCheckOkFogOfWar() == false)
{
label = label + " FogOfWar == false";
}
}
else if(clientInterface->getAllowGameDataSynchCheck() == true)
{
label += " - data synch is ok";
}
labelStatus.setText(label);
}
else{
labelStatus.setText(lang.get("ConnectedToServer"));
else
{
string label = lang.get("ConnectedToServer");
if(!clientInterface->getServerName().empty())
{
label = label + " " + clientInterface->getServerName();
}
if(clientInterface->getAllowGameDataSynchCheck() == true &&
clientInterface->getNetworkGameDataSynchCheckOk() == false)
{
label = label + " - waiting to synch:";
if(clientInterface->getNetworkGameDataSynchCheckOkMap() == false)
{
label = label + " map";
}
if(clientInterface->getNetworkGameDataSynchCheckOkTile() == false)
{
label = label + " tile";
}
if(clientInterface->getNetworkGameDataSynchCheckOkTech() == false)
{
label = label + " techtree";
}
if(clientInterface->getNetworkGameDataSynchCheckOkFogOfWar() == false)
{
label = label + " FogOfWar == false";
}
}
else if(clientInterface->getAllowGameDataSynchCheck() == true)
{
label += " - data synch is ok";
}
labelStatus.setText(label);
}
}
else{
else
{
buttonConnect.setText(lang.get("Connect"));
labelStatus.setText(lang.get("NotConnected"));
labelInfo.setText("");
}
//process network messages
if(clientInterface->isConnected()){
if(clientInterface->isConnected())
{
//update lobby
clientInterface->updateLobby();
//call the chat manager
chatManager.updateNetwork();
//console
console.update();
//intro
if(clientInterface->getIntroDone()){
labelInfo.setText(lang.get("WaitingHost"));
if(clientInterface->getIntroDone())
{
labelInfo.setText(lang.get("WaitingHost"));
servers.setString(clientInterface->getServerName(), Ip(labelServerIp.getText()).getString());
}
//launch
if(clientInterface->getLaunchGame()){
if(clientInterface->getLaunchGame())
{
if(Socket::enableDebugText) printf("In [%s::%s] clientInterface->getLaunchGame() - A\n",__FILE__,__FUNCTION__);
servers.save(serverFileName);
program->setState(new Game(program, clientInterface->getGameSettings()));
if(Socket::enableDebugText) printf("In [%s::%s] clientInterface->getLaunchGame() - B\n",__FILE__,__FUNCTION__);
program->setState(new Game(program, clientInterface->getGameSettings()));
if(Socket::enableDebugText) printf("In [%s::%s] clientInterface->getLaunchGame() - C\n",__FILE__,__FUNCTION__);
}
}
if(Socket::enableDebugText && clientInterface->getLaunchGame()) printf("In [%s::%s] clientInterface->getLaunchGame() - D\n",__FILE__,__FUNCTION__);
}
void MenuStateJoinGame::keyDown(char key){
ClientInterface* clientInterface= NetworkManager::getInstance().getClientInterface();
if(!clientInterface->isConnected()){
if(!clientInterface->isConnected())
{
if(key==vkBack){
string text= labelServerIp.getText();
@ -230,12 +345,18 @@ void MenuStateJoinGame::keyDown(char key){
labelServerIp.setText(text);
}
}
else
{
//send key to the chat manager
chatManager.keyDown(key);
}
}
void MenuStateJoinGame::keyPress(char c){
ClientInterface* clientInterface= NetworkManager::getInstance().getClientInterface();
if(!clientInterface->isConnected()){
if(!clientInterface->isConnected())
{
int maxTextSize= 16;
if(c>='0' && c<='9'){
@ -258,20 +379,32 @@ void MenuStateJoinGame::keyPress(char c){
}
}
}
else
{
chatManager.keyPress(c);
}
}
void MenuStateJoinGame::connectToServer(){
void MenuStateJoinGame::connectToServer()
{
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
ClientInterface* clientInterface= NetworkManager::getInstance().getClientInterface();
Config& config= Config::getInstance();
Ip serverIp(labelServerIp.getText());
clientInterface->connect(serverIp, GameConstants::serverPort);
if(Socket::enableDebugText) printf("In [%s::%s] server - [%s]\n",__FILE__,__FUNCTION__,serverIp.getString().c_str());
labelServerIp.setText(serverIp.getString()+'_');
labelInfo.setText("");
//save server ip
config.setString("ServerIp", serverIp.getString());
config.save();
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
}
}}//end namespace

View File

@ -3,9 +3,9 @@
//
// Copyright (C) 2001-2005 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
// 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
// ==============================================================
@ -14,6 +14,7 @@
#include "properties.h"
#include "main_menu.h"
#include "chat_manager.h"
using Shared::Util::Properties;
@ -22,7 +23,7 @@ namespace Glest{ namespace Game{
class NetworkMessageIntro;
// ===============================
// class MenuStateJoinGame
// class MenuStateJoinGame
// ===============================
class MenuStateJoinGame: public MenuState{
@ -45,6 +46,9 @@ private:
int playerIndex;
Properties servers;
Console console;
ChatManager chatManager;
public:
MenuStateJoinGame(Program *program, MainMenu *mainMenu, bool connect= false, Ip serverIp= Ip());
@ -52,8 +56,8 @@ public:
void mouseMove(int x, int y, const MouseState *mouseState);
void render();
void update();
void keyDown(char key);
void keyPress(char c);
virtual void keyDown(char key);
virtual void keyPress(char c);
private:
void connectToServer();

View File

@ -1,7 +1,7 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2005 Marti<EFBFBD>o Figueroa
// Copyright (C) 2001-2005 Martiño Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published

View File

@ -1,7 +1,7 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2005 Marti<EFBFBD>o Figueroa
// Copyright (C) 2001-2005 Martiño Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published

View File

@ -3,9 +3,9 @@
//
// 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
// 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
// ==============================================================
@ -21,6 +21,10 @@
#include "lang.h"
#include "leak_dumper.h"
#include "map.h"
#include "config.h"
#include "logger.h"
using namespace std;
using namespace Shared::Platform;
using namespace Shared::Util;
@ -39,25 +43,56 @@ ClientInterface::ClientInterface(){
launchGame= false;
introDone= false;
playerIndex= -1;
networkGameDataSynchCheckOkMap = false;
networkGameDataSynchCheckOkTile = false;
networkGameDataSynchCheckOkTech = false;
}
ClientInterface::~ClientInterface(){
ClientInterface::~ClientInterface()
{
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
if(clientSocket != NULL && clientSocket->isConnected() == true)
{
string sQuitText = getHostName() + " has chosen to leave the game!";
sendTextMessage(sQuitText,-1);
}
delete clientSocket;
clientSocket = NULL;
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
}
void ClientInterface::connect(const Ip &ip, int port){
void ClientInterface::connect(const Ip &ip, int port)
{
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
delete clientSocket;
this->ip = ip;
this->port = port;
clientSocket= new ClientSocket();
clientSocket->setBlock(false);
clientSocket->connect(ip, port);
if(Socket::enableDebugText) printf("In [%s::%s] END - socket = %d\n",__FILE__,__FUNCTION__,clientSocket->getSocketId());
}
void ClientInterface::reset(){
delete clientSocket;
clientSocket= NULL;
void ClientInterface::reset()
{
if(getSocket() != NULL)
{
string sQuitText = getHostName() + " has chosen to leave the game!";
sendTextMessage(sQuitText,-1);
close();
}
}
void ClientInterface::update(){
void ClientInterface::update()
{
NetworkMessageCommandList networkMessageCommandList;
//send as many commands as we can
@ -79,152 +114,363 @@ void ClientInterface::update(){
chatTeamIndex= -1;
}
void ClientInterface::updateLobby(){
NetworkMessageType networkMessageType= getNextMessageType();
switch(networkMessageType){
case nmtInvalid:
break;
void ClientInterface::updateLobby()
{
//clear chat variables
chatText.clear();
chatSender.clear();
chatTeamIndex= -1;
case nmtIntro:{
NetworkMessageIntro networkMessageIntro;
NetworkMessageType networkMessageType = getNextMessageType(true);
if(receiveMessage(&networkMessageIntro)){
//check consistency
if(Config::getInstance().getBool("NetworkConsistencyChecks")){
if(networkMessageIntro.getVersionString()!=getNetworkVersionString()){
throw runtime_error("Server and client versions do not match (" + networkMessageIntro.getVersionString() + "). You have to use the same binaries.");
}
}
switch(networkMessageType)
{
case nmtInvalid:
break;
//send intro message
NetworkMessageIntro sendNetworkMessageIntro(getNetworkVersionString(), getHostName(), -1);
case nmtIntro:
{
NetworkMessageIntro networkMessageIntro;
playerIndex= networkMessageIntro.getPlayerIndex();
serverName= networkMessageIntro.getName();
sendMessage(&sendNetworkMessageIntro);
assert(playerIndex>=0 && playerIndex<GameConstants::maxPlayers);
introDone= true;
}
}
break;
if(receiveMessage(&networkMessageIntro))
{
if(Socket::enableDebugText) printf("In [%s::%s] got NetworkMessageIntro\n",__FILE__,__FUNCTION__);
case nmtLaunch:{
NetworkMessageLaunch networkMessageLaunch;
//check consistency
if(Config::getInstance().getBool("NetworkConsistencyChecks"))
{
if(networkMessageIntro.getVersionString()!=getNetworkVersionString())
{
throw runtime_error("Server and client versions do not match (" + networkMessageIntro.getVersionString() + "). You have to use the same binaries.");
}
}
if(receiveMessage(&networkMessageLaunch)){
networkMessageLaunch.buildGameSettings(&gameSettings);
//send intro message
NetworkMessageIntro sendNetworkMessageIntro(getNetworkVersionString(), getHostName(), -1);
//replace server player by network
for(int i= 0; i<gameSettings.getFactionCount(); ++i){
//replace by network
if(gameSettings.getFactionControl(i)==ctHuman){
gameSettings.setFactionControl(i, ctNetwork);
}
playerIndex= networkMessageIntro.getPlayerIndex();
serverName= networkMessageIntro.getName();
sendMessage(&sendNetworkMessageIntro);
//set the faction index
if(gameSettings.getStartLocationIndex(i)==playerIndex){
gameSettings.setThisFactionIndex(i);
}
}
launchGame= true;
}
}
break;
assert(playerIndex>=0 && playerIndex<GameConstants::maxPlayers);
introDone= true;
}
}
break;
default:
throw runtime_error("Unexpected network message: " + intToStr(networkMessageType));
}
case nmtSynchNetworkGameData:
{
NetworkMessageSynchNetworkGameData networkMessageSynchNetworkGameData;
if(receiveMessage(&networkMessageSynchNetworkGameData))
{
if(Socket::enableDebugText) printf("In [%s::%s] got NetworkMessageSynchNetworkGameData\n",__FILE__,__FUNCTION__);
// check the checksum's
//Checksum checksum;
//tileset
//string file = "tilesets/" + networkMessageSynchNetworkGameData.getTileset() + "/" + networkMessageSynchNetworkGameData.getTileset() + ".xml";
//checksum.addFile(file);
// models
// sounds
// textures
//int32 tilesetCRC = checksum.getSum();
//if(Socket::enableDebugText) printf("In [%s::%s] file = [%s] checksum = %d\n",__FILE__,__FUNCTION__,file.c_str(),tilesetCRC);
//if(tilesetCRC != networkMessageSynchNetworkGameData.getTilesetCRC())
//{
// if(Socket::enableDebugText) printf("In [%s::%s] tilesetCRC mismatch, local = %d, remote = %d\n",
// __FILE__,__FUNCTION__,tilesetCRC,networkMessageSynchNetworkGameData.getTilesetCRC());
//}
int32 tilesetCRC = getFolderTreeContentsCheckSumRecursively("tilesets/" +
networkMessageSynchNetworkGameData.getTileset() + "/*", ".xml", NULL);
this->setNetworkGameDataSynchCheckOkTile((tilesetCRC == networkMessageSynchNetworkGameData.getTilesetCRC()));
if(this->getNetworkGameDataSynchCheckOkTile() == false)
{
if(Socket::enableDebugText) printf("In [%s::%s] tilesetCRC mismatch, local = %d, remote = %d\n",
__FILE__,__FUNCTION__,tilesetCRC,networkMessageSynchNetworkGameData.getTilesetCRC());
}
//tech, load before map because of resources
//checksum = Checksum();
//file = "techs/" + networkMessageSynchNetworkGameData.getTech() + "/" + networkMessageSynchNetworkGameData.getTech() + ".xml";
//checksum.addFile(file);
// factions
// resources
//int32 techCRC = checksum.getSum();
//if(Socket::enableDebugText) printf("In [%s::%s] file = [%s] checksum = %d\n",__FILE__,__FUNCTION__,file.c_str(),techCRC);
//if(techCRC != networkMessageSynchNetworkGameData.getTechCRC())
//{
// if(Socket::enableDebugText) printf("In [%s::%s] techCRC mismatch, local = %d, remote = %d\n",
// __FILE__,__FUNCTION__,techCRC,networkMessageSynchNetworkGameData.getTechCRC());
//}
int32 techCRC = getFolderTreeContentsCheckSumRecursively("techs/" +
networkMessageSynchNetworkGameData.getTech() + "/*", ".xml", NULL);
this->setNetworkGameDataSynchCheckOkTech((techCRC == networkMessageSynchNetworkGameData.getTechCRC()));
if(this->getNetworkGameDataSynchCheckOkTech() == false)
{
if(Socket::enableDebugText) printf("In [%s::%s] techCRC mismatch, local = %d, remote = %d\n",
__FILE__,__FUNCTION__,techCRC,networkMessageSynchNetworkGameData.getTechCRC());
}
//map
Checksum checksum;
string file = Map::getMapPath(networkMessageSynchNetworkGameData.getMap());
checksum.addFile(file);
int32 mapCRC = checksum.getSum();
//if(Socket::enableDebugText) printf("In [%s::%s] file = [%s] checksum = %d\n",__FILE__,__FUNCTION__,file.c_str(),mapCRC);
this->setNetworkGameDataSynchCheckOkMap((mapCRC == networkMessageSynchNetworkGameData.getMapCRC()));
if(this->getNetworkGameDataSynchCheckOkMap() == false)
{
if(Socket::enableDebugText) printf("In [%s::%s] mapCRC mismatch, local = %d, remote = %d\n",
__FILE__,__FUNCTION__,mapCRC,networkMessageSynchNetworkGameData.getMapCRC());
}
this->setNetworkGameDataSynchCheckOkFogOfWar((getFogOfWar() == networkMessageSynchNetworkGameData.getFogOfWar()));
if(this->getNetworkGameDataSynchCheckOkFogOfWar() == false)
{
if(Socket::enableDebugText) printf("In [%s::%s] getFogOfWar mismatch, local = %d, remote = %d\n",
__FILE__,__FUNCTION__,getFogOfWar(),networkMessageSynchNetworkGameData.getFogOfWar());
}
NetworkMessageSynchNetworkGameDataStatus sendNetworkMessageSynchNetworkGameDataStatus(mapCRC,tilesetCRC,techCRC,getFogOfWar());
sendMessage(&sendNetworkMessageSynchNetworkGameDataStatus);
}
}
break;
case nmtSynchNetworkGameDataFileCRCCheck:
{
NetworkMessageSynchNetworkGameDataFileCRCCheck networkMessageSynchNetworkGameDataFileCRCCheck;
if(receiveMessage(&networkMessageSynchNetworkGameDataFileCRCCheck))
{
/*
if(Socket::enableDebugText) printf("In [%s::%s] got nmtSynchNetworkGameDataFileCRCCheck totalfiles = %d, fileindex = %d, crc = %d, file [%s]\n",
__FILE__,__FUNCTION__,networkMessageSynchNetworkGameDataFileCRCCheck.getTotalFileCount(),
networkMessageSynchNetworkGameDataFileCRCCheck.getFileIndex(),
networkMessageSynchNetworkGameDataFileCRCCheck.getFileCRC(),
networkMessageSynchNetworkGameDataFileCRCCheck.getFileName().c_str());
*/
Checksum checksum;
string file = networkMessageSynchNetworkGameDataFileCRCCheck.getFileName();
checksum.addFile(file);
int32 fileCRC = checksum.getSum();
if(fileCRC != networkMessageSynchNetworkGameDataFileCRCCheck.getFileCRC())
{
if(Socket::enableDebugText) printf("In [%s::%s] got nmtSynchNetworkGameDataFileCRCCheck localCRC = %d, remoteCRC = %d, file [%s]\n",
__FILE__,__FUNCTION__,fileCRC,
networkMessageSynchNetworkGameDataFileCRCCheck.getFileCRC(),
networkMessageSynchNetworkGameDataFileCRCCheck.getFileName().c_str());
// Here we initiate a download of missing or mismatched content
NetworkMessageSynchNetworkGameDataFileGet sendNetworkMessageSynchNetworkGameDataFileGet(networkMessageSynchNetworkGameDataFileCRCCheck.getFileName());
sendMessage(&sendNetworkMessageSynchNetworkGameDataFileGet);
FileTransferInfo fileInfo;
fileInfo.hostType = eClient;
fileInfo.serverIP = this->ip.getString();
fileInfo.serverPort = this->port;
fileInfo.fileName = networkMessageSynchNetworkGameDataFileCRCCheck.getFileName();
FileTransferSocketThread *fileXferThread = new FileTransferSocketThread(fileInfo);
fileXferThread->start();
}
if(networkMessageSynchNetworkGameDataFileCRCCheck.getFileIndex() < networkMessageSynchNetworkGameDataFileCRCCheck.getTotalFileCount())
{
NetworkMessageSynchNetworkGameDataFileCRCCheck sendNetworkMessageSynchNetworkGameDataFileCRCCheck(
networkMessageSynchNetworkGameDataFileCRCCheck.getTotalFileCount(),
networkMessageSynchNetworkGameDataFileCRCCheck.getFileIndex() + 1,
0,
"");
sendMessage(&sendNetworkMessageSynchNetworkGameDataFileCRCCheck);
}
}
}
break;
case nmtText:
{
NetworkMessageText networkMessageText;
if(receiveMessage(&networkMessageText))
{
if(Socket::enableDebugText) printf("In [%s::%s] got nmtText\n",__FILE__,__FUNCTION__);
chatText = networkMessageText.getText();
chatSender = networkMessageText.getSender();
chatTeamIndex = networkMessageText.getTeamIndex();
}
}
break;
case nmtLaunch:
{
NetworkMessageLaunch networkMessageLaunch;
if(receiveMessage(&networkMessageLaunch))
{
if(Socket::enableDebugText) printf("In [%s::%s] got NetworkMessageLaunch\n",__FILE__,__FUNCTION__);
networkMessageLaunch.buildGameSettings(&gameSettings);
//replace server player by network
for(int i= 0; i<gameSettings.getFactionCount(); ++i)
{
//replace by network
if(gameSettings.getFactionControl(i)==ctHuman)
{
gameSettings.setFactionControl(i, ctNetwork);
}
//set the faction index
if(gameSettings.getStartLocationIndex(i)==playerIndex)
{
gameSettings.setThisFactionIndex(i);
}
}
launchGame= true;
}
}
break;
default:
throw runtime_error(string(__FILE__) + "::" + string(__FUNCTION__) + " Unexpected network message: " + intToStr(networkMessageType));
}
}
void ClientInterface::updateKeyframe(int frameCount){
void ClientInterface::updateKeyframe(int frameCount)
{
bool done= false;
while(!done){
while(!done)
{
//wait for the next message
waitForMessage();
//check we have an expected message
NetworkMessageType networkMessageType= getNextMessageType();
NetworkMessageType networkMessageType= getNextMessageType(true);
switch(networkMessageType){
case nmtCommandList:{
switch(networkMessageType)
{
case nmtCommandList:
{
//make sure we read the message
NetworkMessageCommandList networkMessageCommandList;
while(!receiveMessage(&networkMessageCommandList)){
while(!receiveMessage(&networkMessageCommandList))
{
sleep(waitSleepTime);
}
//check that we are in the right frame
if(networkMessageCommandList.getFrameCount()!=frameCount){
if(networkMessageCommandList.getFrameCount()!=frameCount)
{
throw runtime_error("Network synchronization error, frame counts do not match");
}
// give all commands
for(int i= 0; i<networkMessageCommandList.getCommandCount(); ++i){
for(int i= 0; i<networkMessageCommandList.getCommandCount(); ++i)
{
pendingCommands.push_back(*networkMessageCommandList.getCommand(i));
}
}
done= true;
}
break;
case nmtQuit:{
case nmtQuit:
{
NetworkMessageQuit networkMessageQuit;
if(receiveMessage(&networkMessageQuit)){
if(receiveMessage(&networkMessageQuit))
{
quit= true;
}
done= true;
}
break;
case nmtText:{
case nmtText:
{
NetworkMessageText networkMessageText;
if(receiveMessage(&networkMessageText)){
chatText= networkMessageText.getText();
chatSender= networkMessageText.getSender();
chatTeamIndex= networkMessageText.getTeamIndex();
if(receiveMessage(&networkMessageText))
{
chatText = networkMessageText.getText();
chatSender = networkMessageText.getSender();
chatTeamIndex = networkMessageText.getTeamIndex();
}
}
break;
case nmtInvalid:
break;
default:
throw runtime_error("Unexpected message in client interface: " + intToStr(networkMessageType));
throw runtime_error(string(__FILE__) + "::" + string(__FUNCTION__) + " Unexpected message in client interface: " + intToStr(networkMessageType));
}
}
}
void ClientInterface::waitUntilReady(Checksum* checksum){
NetworkMessageReady networkMessageReady;
Chrono chrono;
void ClientInterface::waitUntilReady(Checksum* checksum)
{
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
Logger &logger= Logger::getInstance();
Chrono chrono;
chrono.start();
// FOR TESTING ONLY - delay to see the client count up while waiting
//sleep(5000);
//send ready message
NetworkMessageReady networkMessageReady;
sendMessage(&networkMessageReady);
int64 lastMillisCheck = 0;
//wait until we get a ready message from the server
while(true){
NetworkMessageType networkMessageType= getNextMessageType();
while(true)
{
NetworkMessageType networkMessageType = getNextMessageType(true);
if(networkMessageType==nmtReady){
if(receiveMessage(&networkMessageReady)){
if(networkMessageType == nmtReady)
{
if(receiveMessage(&networkMessageReady))
{
break;
}
}
else if(networkMessageType==nmtInvalid){
if(chrono.getMillis()>readyWaitTimeout){
else if(networkMessageType == nmtInvalid)
{
if(chrono.getMillis() > readyWaitTimeout)
{
throw runtime_error("Timeout waiting for server");
}
else
{
if(chrono.getMillis() / 1000 > lastMillisCheck)
{
lastMillisCheck = (chrono.getMillis() / 1000);
char szBuf[1024]="";
sprintf(szBuf,"Waiting for network: %llu seconds elapsed (maximum wait time: %d seconds)",lastMillisCheck,int(readyWaitTimeout / 1000));
logger.add(szBuf, true);
}
}
}
else{
throw runtime_error("Unexpected network message: " + intToStr(networkMessageType) );
else
{
throw runtime_error(string(__FILE__) + "::" + string(__FUNCTION__) + " Unexpected network message: " + intToStr(networkMessageType) );
}
// sleep a bit
@ -232,14 +478,18 @@ void ClientInterface::waitUntilReady(Checksum* checksum){
}
//check checksum
if(Config::getInstance().getBool("NetworkConsistencyChecks")){
if(networkMessageReady.getChecksum()!=checksum->getSum()){
if(Config::getInstance().getBool("NetworkConsistencyChecks"))
{
if(networkMessageReady.getChecksum() != checksum->getSum())
{
throw runtime_error("Checksum error, you don't have the same data as the server");
}
}
//delay the start a bit, so clients have nore room to get messages
sleep(GameConstants::networkExtraLatency);
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
}
void ClientInterface::sendTextMessage(const string &text, int teamIndex){
@ -251,18 +501,20 @@ string ClientInterface::getNetworkStatus() const{
return Lang::getInstance().get("Server") + ": " + serverName;
}
void ClientInterface::waitForMessage(){
void ClientInterface::waitForMessage()
{
Chrono chrono;
chrono.start();
while(getNextMessageType()==nmtInvalid){
if(!isConnected()){
while(getNextMessageType(true) == nmtInvalid)
{
if(!isConnected())
{
throw runtime_error("Disconnected");
}
if(chrono.getMillis()>messageWaitTimeout){
if(chrono.getMillis()>messageWaitTimeout)
{
throw runtime_error("Timeout waiting for message");
}
@ -270,4 +522,31 @@ void ClientInterface::waitForMessage(){
}
}
void ClientInterface::quitGame(bool userManuallyQuit)
{
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
if(clientSocket != NULL && userManuallyQuit == true)
{
string sQuitText = getHostName() + " has chosen to leave the game!";
sendTextMessage(sQuitText,-1);
close();
}
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
}
void ClientInterface::close()
{
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
delete clientSocket;
clientSocket= NULL;
}
bool ClientInterface::getFogOfWar()
{
return Config::getInstance().getBool("FogOfWar");
}
}}//end namespace

View File

@ -3,9 +3,9 @@
//
// 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
// 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
// ==============================================================
@ -15,7 +15,7 @@
#include <vector>
#include "network_interface.h"
#include "game_settings.h"
//#include "game_settings.h"
#include "socket.h"
@ -36,18 +36,22 @@ private:
private:
ClientSocket *clientSocket;
GameSettings gameSettings;
//GameSettings gameSettings;
string serverName;
bool introDone;
bool launchGame;
int playerIndex;
Ip ip;
int port;
public:
ClientInterface();
virtual ~ClientInterface();
virtual Socket* getSocket() {return clientSocket;}
virtual const Socket* getSocket() const {return clientSocket;}
virtual void close();
//message processing
virtual void update();
@ -57,7 +61,7 @@ public:
// message sending
virtual void sendTextMessage(const string &text, int teamIndex);
virtual void quitGame(){}
virtual void quitGame(bool userManuallyQuit);
//misc
virtual string getNetworkStatus() const;
@ -67,10 +71,11 @@ public:
bool getLaunchGame() const {return launchGame;}
bool getIntroDone() const {return introDone;}
int getPlayerIndex() const {return playerIndex;}
const GameSettings *getGameSettings() {return &gameSettings;}
//const GameSettings *getGameSettings() {return &gameSettings;}
void connect(const Ip &ip, int port);
void reset();
virtual bool getFogOfWar();
private:
void waitForMessage();

View File

@ -3,9 +3,9 @@
//
// 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
// 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
// ==============================================================
@ -20,8 +20,12 @@
#include "network_message.h"
#include "leak_dumper.h"
#include "platform_util.h"
#include "map.h"
using namespace std;
using namespace Shared::Util;
//using namespace Shared::Platform;
namespace Glest{ namespace Game{
@ -29,43 +33,108 @@ namespace Glest{ namespace Game{
// class ClientConnection
// =====================================================
ConnectionSlot::ConnectionSlot(ServerInterface* serverInterface, int playerIndex){
ConnectionSlot::ConnectionSlot(ServerInterface* serverInterface, int playerIndex)
{
this->serverInterface= serverInterface;
this->playerIndex= playerIndex;
socket= NULL;
ready= false;
networkGameDataSynchCheckOkMap = false;
networkGameDataSynchCheckOkTile = false;
networkGameDataSynchCheckOkTech = false;
networkGameDataSynchCheckOkFogOfWar = false;
chatText.clear();
chatSender.clear();
chatTeamIndex= -1;
}
ConnectionSlot::~ConnectionSlot(){
ConnectionSlot::~ConnectionSlot()
{
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
close();
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
}
void ConnectionSlot::update(){
if(socket==NULL){
socket= serverInterface->getServerSocket()->accept();
void ConnectionSlot::update()
{
update(true);
}
//send intro message when connected
if(socket!=NULL){
NetworkMessageIntro networkMessageIntro(getNetworkVersionString(), socket->getHostName(), playerIndex);
sendMessage(&networkMessageIntro);
}
void ConnectionSlot::update(bool checkForNewClients)
{
if(socket == NULL)
{
if(networkGameDataSynchCheckOkMap) networkGameDataSynchCheckOkMap = false;
if(networkGameDataSynchCheckOkTile) networkGameDataSynchCheckOkTile = false;
if(networkGameDataSynchCheckOkTech) networkGameDataSynchCheckOkTech = false;
if(networkGameDataSynchCheckOkFogOfWar) networkGameDataSynchCheckOkFogOfWar = false;
// Is the listener socket ready to be read?
//if(serverInterface->getServerSocket()->isReadable() == true)
if(checkForNewClients == true)
{
socket = serverInterface->getServerSocket()->accept();
//send intro message when connected
if(socket != NULL)
{
if(Socket::enableDebugText) printf("In [%s::%s] accepted new client connection\n",__FILE__,__FUNCTION__);
chatText.clear();
chatSender.clear();
chatTeamIndex= -1;
NetworkMessageIntro networkMessageIntro(getNetworkVersionString(), socket->getHostName(), playerIndex);
sendMessage(&networkMessageIntro);
}
}
}
else{
if(socket->isConnected()){
else
{
if(socket->isConnected())
{
chatText.clear();
chatSender.clear();
chatTeamIndex= -1;
NetworkMessageType networkMessageType= getNextMessageType();
//process incoming commands
switch(networkMessageType){
case nmtInvalid:
case nmtText:
break;
case nmtText:
{
if(Socket::enableDebugText) printf("In [%s::%s] got nmtText\n",__FILE__,__FUNCTION__);
NetworkMessageText networkMessageText;
if(receiveMessage(&networkMessageText))
{
chatText = networkMessageText.getText();
chatSender = networkMessageText.getSender();
chatTeamIndex = networkMessageText.getTeamIndex();
if(Socket::enableDebugText) printf("In [%s::%s] chatText [%s] chatSender [%s] chatTeamIndex = %d\n",__FILE__,__FUNCTION__,chatText.c_str(),chatSender.c_str(),chatTeamIndex);
}
}
break;
//command list
case nmtCommandList:{
case nmtCommandList: {
if(Socket::enableDebugText) printf("In [%s::%s] got nmtCommandList\n",__FILE__,__FUNCTION__);
NetworkMessageCommandList networkMessageCommandList;
if(receiveMessage(&networkMessageCommandList)){
for(int i= 0; i<networkMessageCommandList.getCommandCount(); ++i){
if(receiveMessage(&networkMessageCommandList))
{
for(int i= 0; i<networkMessageCommandList.getCommandCount(); ++i)
{
serverInterface->requestCommand(networkMessageCommandList.getCommand(i));
}
}
@ -73,10 +142,143 @@ void ConnectionSlot::update(){
break;
//process intro messages
case nmtIntro:{
case nmtIntro:
{
if(Socket::enableDebugText) printf("In [%s::%s] got nmtIntro\n",__FILE__,__FUNCTION__);
NetworkMessageIntro networkMessageIntro;
if(receiveMessage(&networkMessageIntro)){
if(receiveMessage(&networkMessageIntro))
{
name= networkMessageIntro.getName();
if(Socket::enableDebugText) printf("In [%s::%s] got name [%s]\n",__FILE__,__FUNCTION__,name.c_str());
if(getAllowGameDataSynchCheck() == true && serverInterface->getGameSettings() != NULL)
{
if(Socket::enableDebugText) printf("In [%s::%s] sending NetworkMessageSynchNetworkGameData\n",__FILE__,__FUNCTION__);
NetworkMessageSynchNetworkGameData networkMessageSynchNetworkGameData(serverInterface->getGameSettings());
sendMessage(&networkMessageSynchNetworkGameData);
}
}
}
break;
//process datasynch messages
case nmtSynchNetworkGameDataStatus:
{
if(Socket::enableDebugText) printf("In [%s::%s] got nmtSynchNetworkGameDataStatus\n",__FILE__,__FUNCTION__);
NetworkMessageSynchNetworkGameDataStatus networkMessageSynchNetworkGameDataStatus;
if(receiveMessage(&networkMessageSynchNetworkGameDataStatus))
{
receivedNetworkGameStatus = true;
int32 tilesetCRC = getFolderTreeContentsCheckSumRecursively("tilesets/" + serverInterface->getGameSettings()->getTileset() + "/*", ".xml", NULL);
int32 techCRC = getFolderTreeContentsCheckSumRecursively("techs/" + serverInterface->getGameSettings()->getTech() + "/*", ".xml", NULL);
Checksum checksum;
string file = Map::getMapPath(serverInterface->getGameSettings()->getMap());
checksum.addFile(file);
int32 mapCRC = checksum.getSum();
networkGameDataSynchCheckOkMap = (networkMessageSynchNetworkGameDataStatus.getMapCRC() == mapCRC);
networkGameDataSynchCheckOkTile = (networkMessageSynchNetworkGameDataStatus.getTilesetCRC() == tilesetCRC);
networkGameDataSynchCheckOkTech = (networkMessageSynchNetworkGameDataStatus.getTechCRC() == techCRC);
networkGameDataSynchCheckOkFogOfWar = (networkMessageSynchNetworkGameDataStatus.getFogOfWar() == serverInterface->getFogOfWar() == true);
// For testing
//techCRC++;
if( networkGameDataSynchCheckOkMap == true &&
networkGameDataSynchCheckOkTile == true &&
networkGameDataSynchCheckOkTech == true &&
networkGameDataSynchCheckOkFogOfWar == true)
{
if(Socket::enableDebugText) printf("In [%s::%s] client data synch ok\n",__FILE__,__FUNCTION__);
}
else
{
if(Socket::enableDebugText) printf("In [%s::%s] mapCRC = %d, remote = %d\n",__FILE__,__FUNCTION__,mapCRC,networkMessageSynchNetworkGameDataStatus.getMapCRC());
if(Socket::enableDebugText) printf("In [%s::%s] tilesetCRC = %d, remote = %d\n",__FILE__,__FUNCTION__,tilesetCRC,networkMessageSynchNetworkGameDataStatus.getTilesetCRC());
if(Socket::enableDebugText) printf("In [%s::%s] techCRC = %d, remote = %d\n",__FILE__,__FUNCTION__,techCRC,networkMessageSynchNetworkGameDataStatus.getTechCRC());
if(Socket::enableDebugText) printf("In [%s::%s] serverInterface->getFogOfWar() = %d, remote = %d\n",__FILE__,__FUNCTION__,serverInterface->getFogOfWar(),networkMessageSynchNetworkGameDataStatus.getFogOfWar());
if(allowDownloadDataSynch == true)
{
// Now get all filenames with their CRC values and send to the client
vctFileList.clear();
if(networkGameDataSynchCheckOkTile == false)
{
if(tilesetCRC == 0)
{
vctFileList = getFolderTreeContentsCheckSumListRecursively("tilesets/" + serverInterface->getGameSettings()->getTileset() + "/*", "", &vctFileList);
}
else
{
vctFileList = getFolderTreeContentsCheckSumListRecursively("tilesets/" + serverInterface->getGameSettings()->getTileset() + "/*", ".xml", &vctFileList);
}
}
if(networkGameDataSynchCheckOkTech == false)
{
if(techCRC == 0)
{
vctFileList = getFolderTreeContentsCheckSumListRecursively("techs/" + serverInterface->getGameSettings()->getTech() + "/*", "", &vctFileList);
}
else
{
vctFileList = getFolderTreeContentsCheckSumListRecursively("techs/" + serverInterface->getGameSettings()->getTech() + "/*", ".xml", &vctFileList);
}
}
if(networkGameDataSynchCheckOkMap == false)
{
vctFileList.push_back(std::pair<string,int32>(Map::getMapPath(serverInterface->getGameSettings()->getMap()),mapCRC));
}
//for(int i = 0; i < vctFileList.size(); i++)
//{
NetworkMessageSynchNetworkGameDataFileCRCCheck networkMessageSynchNetworkGameDataFileCRCCheck(vctFileList.size(), 1, vctFileList[0].second, vctFileList[0].first);
sendMessage(&networkMessageSynchNetworkGameDataFileCRCCheck);
//}
}
}
}
}
break;
case nmtSynchNetworkGameDataFileCRCCheck:
{
if(Socket::enableDebugText) printf("In [%s::%s] got nmtSynchNetworkGameDataFileCRCCheck\n",__FILE__,__FUNCTION__);
NetworkMessageSynchNetworkGameDataFileCRCCheck networkMessageSynchNetworkGameDataFileCRCCheck;
if(receiveMessage(&networkMessageSynchNetworkGameDataFileCRCCheck))
{
int fileIndex = networkMessageSynchNetworkGameDataFileCRCCheck.getFileIndex();
NetworkMessageSynchNetworkGameDataFileCRCCheck networkMessageSynchNetworkGameDataFileCRCCheck(vctFileList.size(), fileIndex, vctFileList[fileIndex-1].second, vctFileList[fileIndex-1].first);
sendMessage(&networkMessageSynchNetworkGameDataFileCRCCheck);
}
}
break;
case nmtSynchNetworkGameDataFileGet:
{
if(Socket::enableDebugText) printf("In [%s::%s] got nmtSynchNetworkGameDataFileGet\n",__FILE__,__FUNCTION__);
NetworkMessageSynchNetworkGameDataFileGet networkMessageSynchNetworkGameDataFileGet;
if(receiveMessage(&networkMessageSynchNetworkGameDataFileGet))
{
FileTransferInfo fileInfo;
fileInfo.hostType = eServer;
//fileInfo.serverIP = this->ip.getString();
fileInfo.serverPort = GameConstants::serverPort;
fileInfo.fileName = networkMessageSynchNetworkGameDataFileGet.getFileName();
FileTransferSocketThread *fileXferThread = new FileTransferSocketThread(fileInfo);
fileXferThread->start();
}
}
break;
@ -85,15 +287,38 @@ void ConnectionSlot::update(){
throw runtime_error("Unexpected message in connection slot: " + intToStr(networkMessageType));
}
}
else{
else
{
if(Socket::enableDebugText) printf("In [%s::%s] calling close...\n",__FILE__,__FUNCTION__);
close();
}
}
}
void ConnectionSlot::close(){
void ConnectionSlot::close()
{
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
delete socket;
socket= NULL;
chatText.clear();
chatSender.clear();
chatTeamIndex= -1;
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
}
bool ConnectionSlot::getFogOfWar()
{
return networkGameDataSynchCheckOkFogOfWar;
}
bool ConnectionSlot::hasValidSocketId()
{
bool result = (socket != NULL && socket->getSocketId() > 0);
return result;
}
}}//end namespace

View File

@ -3,9 +3,9 @@
//
// 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
// 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
// ==============================================================
@ -37,23 +37,30 @@ private:
int playerIndex;
string name;
bool ready;
vector<std::pair<string,int32> > vctFileList;
bool receivedNetworkGameStatus;
public:
ConnectionSlot(ServerInterface* serverInterface, int playerIndex);
~ConnectionSlot();
void update(bool checkForNewClients);
virtual void update();
void setReady() {ready= true;}
const string &getName() const {return name;}
bool isReady() const {return ready;}
protected:
virtual Socket* getSocket() {return socket;}
virtual Socket* getSocket() const {return socket;}
private:
void close();
virtual void close();
virtual bool getFogOfWar();
bool getReceivedNetworkGameStatus() { return receivedNetworkGameStatus; }
void setReceivedNetworkGameStatus(bool value) { receivedNetworkGameStatus = value; }
bool hasValidSocketId();
};
}}//end namespace

View File

@ -3,9 +3,9 @@
//
// 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
// 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
// ==============================================================
@ -19,6 +19,7 @@
#include "platform_util.h"
#include "leak_dumper.h"
#include <fstream>
using namespace Shared::Platform;
using namespace Shared::Util;
@ -32,6 +33,9 @@ namespace Glest{ namespace Game{
const int NetworkInterface::readyWaitTimeout= 60000; //1 minute
bool NetworkInterface::allowGameDataSynchCheck = false;
bool NetworkInterface::allowDownloadDataSynch = false;
void NetworkInterface::sendMessage(const NetworkMessage* networkMessage){
Socket* socket= getSocket();
@ -39,31 +43,52 @@ void NetworkInterface::sendMessage(const NetworkMessage* networkMessage){
networkMessage->send(socket);
}
NetworkMessageType NetworkInterface::getNextMessageType(){
NetworkMessageType NetworkInterface::getNextMessageType(bool checkHasDataFirst)
{
Socket* socket= getSocket();
int8 messageType= nmtInvalid;
//peek message type
if(socket->getDataToRead()>=sizeof(messageType)){
socket->peek(&messageType, sizeof(messageType));
}
if(checkHasDataFirst == false ||
(checkHasDataFirst == true &&
socket != NULL &&
socket->hasDataToRead() == true))
{
//peek message type
int dataSize = socket->getDataToRead();
if(dataSize >= sizeof(messageType)){
if(Socket::enableDebugText) printf("In [%s::%s] socket->getDataToRead() dataSize = %d\n",__FILE__,__FUNCTION__,dataSize);
//sanity check new message type
if(messageType<0 || messageType>=nmtCount){
throw runtime_error("Invalid message type: " + intToStr(messageType));
}
int iPeek = socket->peek(&messageType, sizeof(messageType));
if(Socket::enableDebugText) printf("In [%s::%s] socket->getDataToRead() iPeek = %d, messageType = %d\n",__FILE__,__FUNCTION__,iPeek,messageType);
}
//sanity check new message type
if(messageType<0 || messageType>=nmtCount){
throw runtime_error("Invalid message type: " + intToStr(messageType));
}
}
return static_cast<NetworkMessageType>(messageType);
}
bool NetworkInterface::receiveMessage(NetworkMessage* networkMessage){
if(Socket::enableDebugText) printf("In [%s::%s]\n",__FILE__,__FUNCTION__);
Socket* socket= getSocket();
return networkMessage->receive(socket);
}
bool NetworkInterface::isConnected(){
return getSocket()!=NULL && getSocket()->isConnected();
//if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
bool result = (getSocket()!=NULL && getSocket()->isConnected());
//if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
return result;
}
// =====================================================
@ -74,4 +99,181 @@ GameNetworkInterface::GameNetworkInterface(){
quit= false;
}
// =====================================================
// class FileTransferSocketThread
// =====================================================
const int32 SEND_FILE = 0x20;
const int32 ACK = 0x47;
FileTransferSocketThread::FileTransferSocketThread(FileTransferInfo fileInfo)
{
this->info = fileInfo;
this->info.serverPort += 100;
}
void FileTransferSocketThread::execute()
{
if(info.hostType == eServer)
{
ServerSocket serverSocket;
//serverSocket.setBlock(false);
serverSocket.bind(this->info.serverPort);
serverSocket.listen(1);
Socket *clientSocket = serverSocket.accept();
char data[513]="";
memset(data, 0, 256);
clientSocket->receive(data,256);
if(*data == SEND_FILE)
{
FileInfo file;
memcpy(&file, data+1, sizeof(file));
*data=ACK;
clientSocket->send(data,256);
Checksum checksum;
checksum.addFile(file.fileName);
file.filecrc = checksum.getSum();
ifstream infile(file.fileName.c_str(), ios::in | ios::binary | ios::ate);
if(infile.is_open() == true)
{
file.filesize = infile.tellg();
infile.seekg (0, ios::beg);
memset(data, 0, 256);
*data=SEND_FILE;
memcpy(data+1,&file,sizeof(file));
clientSocket->send(data,256);
clientSocket->receive(data,256);
if(*data != ACK)
;//transfer error
int remain=file.filesize % 512 ;
int packs=(file.filesize-remain)/512;
while(packs--)
{
infile.read(data,512);
//if(!ReadFile(file,data,512,&read,NULL))
// ; //read error
//if(written!=pack)
// ; //read error
clientSocket->send(data,512);
clientSocket->receive(data,256);
if(*data!=ACK)
;//transfer error
}
infile.read(data,remain);
//if(!ReadFile(file,data,remain,&read,NULL))
// ; //read error
//if(written!=pack)
// ; //read error
clientSocket->send(data,remain);
clientSocket->receive(data,256);
if(*data!=ACK)
;//transfer error
infile.close();
}
}
delete clientSocket;
}
else
{
Ip ip(this->info.serverIP);
ClientSocket clientSocket;
//clientSocket.setBlock(false);
clientSocket.connect(this->info.serverIP, this->info.serverPort);
if(clientSocket.isConnected() == true)
{
FileInfo file;
file.fileName = this->info.fileName;
//file.filesize =
//file.filecrc = this->info.
string path = extractDirectoryPathFromFile(file.fileName);
createDirectoryPaths(path);
ofstream outFile(file.fileName.c_str(), ios_base::binary | ios_base::out);
if(outFile.is_open() == true)
{
char data[513]="";
memset(data, 0, 256);
*data=SEND_FILE;
memcpy(data+1,&file,sizeof(file));
clientSocket.send(data,256);
clientSocket.receive(data,256);
if(*data!=ACK)
;//transfer error
clientSocket.receive(data,256);
if(*data == SEND_FILE)
{
memcpy(&file, data+1, sizeof(file));
*data=ACK;
clientSocket.send(data,256);
int remain = file.filesize % 512 ;
int packs = (file.filesize-remain) / 512;
while(packs--)
{
clientSocket.receive(data,512);
outFile.write(data, 512);
if(outFile.bad())
{
int ii = 0;
}
//if(!WriteFile(file,data,512,&written,NULL))
// ; //write error
//if(written != pack)
// ; //write error
*data=ACK;
clientSocket.send(data,256);
}
clientSocket.receive(data,remain);
outFile.write(data, remain);
if(outFile.bad())
{
int ii = 0;
}
//if(!WriteFile(file,data,remain,&written,NULL))
// ; //write error
//if(written!=pack)
// ; //write error
*data=ACK;
clientSocket.send(data,256);
Checksum checksum;
checksum.addFile(file.fileName);
int32 crc = checksum.getSum();
if(file.filecrc != crc)
{
int ii = 0;
}
//if(calc_crc(file)!=info.crc)
// ; //transfeer error
}
outFile.close();
}
}
}
}
}}//end namespace

View File

@ -3,9 +3,9 @@
//
// 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
// 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
// ==============================================================
@ -19,40 +19,88 @@
#include "network_message.h"
#include "network_types.h"
#include "game_settings.h"
#include "thread.h"
#include "types.h"
using std::string;
using std::vector;
using Shared::Util::Checksum;
using namespace Shared::Util;
using namespace Shared::Platform;
namespace Glest{ namespace Game{
//class GameSettings;
// =====================================================
// class NetworkInterface
// =====================================================
class NetworkInterface{
class NetworkInterface {
protected:
static bool allowGameDataSynchCheck;
static bool allowDownloadDataSynch;
bool networkGameDataSynchCheckOkMap;
bool networkGameDataSynchCheckOkTile;
bool networkGameDataSynchCheckOkTech;
bool networkGameDataSynchCheckOkFogOfWar;
string chatText;
string chatSender;
int chatTeamIndex;
public:
static const int readyWaitTimeout;
GameSettings gameSettings;
public:
virtual ~NetworkInterface(){}
virtual Socket* getSocket()= 0;
virtual const Socket* getSocket() const= 0;
virtual void close()= 0;
string getIp() const {return getSocket()->getIp();}
string getHostName() const {return getSocket()->getHostName();}
void sendMessage(const NetworkMessage* networkMessage);
NetworkMessageType getNextMessageType();
NetworkMessageType getNextMessageType(bool checkHasDataFirst = false);
bool receiveMessage(NetworkMessage* networkMessage);
bool isConnected();
//virtual void setGameSettings(GameSettings *serverGameSettings) { gameSettings = *serverGameSettings; }
const virtual GameSettings * getGameSettings() { return &gameSettings; }
virtual void setAllowDownloadDataSynch(bool value) { allowDownloadDataSynch = value; }
virtual bool getAllowDownloadDataSynch() { return allowDownloadDataSynch; }
virtual void setAllowGameDataSynchCheck(bool value) { allowGameDataSynchCheck = value; }
virtual bool getAllowGameDataSynchCheck() { return allowGameDataSynchCheck; }
virtual bool getNetworkGameDataSynchCheckOk() { return (networkGameDataSynchCheckOkMap && networkGameDataSynchCheckOkTile && networkGameDataSynchCheckOkTech && networkGameDataSynchCheckOkFogOfWar); }
virtual void setNetworkGameDataSynchCheckOkMap(bool value) { networkGameDataSynchCheckOkMap = value; }
virtual void setNetworkGameDataSynchCheckOkTile(bool value) { networkGameDataSynchCheckOkTile = value; }
virtual void setNetworkGameDataSynchCheckOkTech(bool value) { networkGameDataSynchCheckOkTech = value; }
virtual bool getNetworkGameDataSynchCheckOkMap() { return networkGameDataSynchCheckOkMap; }
virtual bool getNetworkGameDataSynchCheckOkTile() { return networkGameDataSynchCheckOkTile; }
virtual bool getNetworkGameDataSynchCheckOkTech() { return networkGameDataSynchCheckOkTech; }
virtual bool getFogOfWar()=0;
virtual bool getNetworkGameDataSynchCheckOkFogOfWar() { return networkGameDataSynchCheckOkFogOfWar; }
virtual void setNetworkGameDataSynchCheckOkFogOfWar(bool value) { networkGameDataSynchCheckOkFogOfWar = value; }
const string getChatText() const {return chatText;}
const string getChatSender() const {return chatSender;}
int getChatTeamIndex() const {return chatTeamIndex;}
};
// =====================================================
// class GameNetworkInterface
//
// Adds functions common to servers and clients
//
// Adds functions common to servers and clients
// but not connection slots
// =====================================================
@ -64,9 +112,6 @@ protected:
Commands requestedCommands; //commands requested by the user
Commands pendingCommands; //commands ready to be given
bool quit;
string chatText;
string chatSender;
int chatTeamIndex;
public:
GameNetworkInterface();
@ -79,7 +124,7 @@ public:
//message sending
virtual void sendTextMessage(const string &text, int teamIndex)= 0;
virtual void quitGame()=0;
virtual void quitGame(bool userManuallyQuit)=0;
//misc
virtual string getNetworkStatus() const= 0;
@ -90,11 +135,77 @@ public:
const NetworkCommand* getPendingCommand(int i) const {return &pendingCommands[i];}
void clearPendingCommands() {pendingCommands.clear();}
bool getQuit() const {return quit;}
const string getChatText() const {return chatText;}
const string getChatSender() const {return chatSender;}
int getChatTeamIndex() const {return chatTeamIndex;}
};
// =====================================================
// class FileTransferSocketThread
// =====================================================
enum FileTransferHostType
{
eClient,
eServer
};
enum FileTransferOperationType
{
eSend,
eReceive
};
class FileTransferInfo
{
private:
void CopyAll(const FileTransferInfo &obj)
{
hostType = obj.hostType;
serverIP = obj.serverIP;
serverPort = obj.serverPort;
opType = obj.opType;
fileName = obj.fileName;
}
public:
FileTransferInfo()
{
}
FileTransferInfo(const FileTransferInfo &obj)
{
CopyAll(obj);
}
FileTransferInfo &operator=(const FileTransferInfo &obj)
{
CopyAll(obj);
return *this;
}
FileTransferHostType hostType;
string serverIP;
int32 serverPort;
FileTransferOperationType opType;
string fileName;
};
class FileInfo
{
public:
string fileName;
int64 filesize;
int32 filecrc;
};
class FileTransferSocketThread : public Thread
{
private:
FileTransferInfo info;
public:
FileTransferSocketThread(FileTransferInfo fileInfo);
virtual void execute();
};
}}//end namespace
#endif

View File

@ -3,9 +3,9 @@
//
// 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
// 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
// ==============================================================
@ -20,6 +20,11 @@
#include "leak_dumper.h"
#include "checksum.h"
#include "map.h"
#include "platform_util.h"
#include "config.h"
using namespace Shared::Platform;
using namespace Shared::Util;
using namespace std;
@ -30,19 +35,48 @@ namespace Glest{ namespace Game{
// class NetworkMessage
// =====================================================
bool NetworkMessage::receive(Socket* socket, void* data, int dataSize){
if(socket->getDataToRead()>=dataSize){
if(socket->receive(data, dataSize)!=dataSize){
throw runtime_error("Error receiving NetworkMessage");
bool NetworkMessage::receive(Socket* socket, void* data, int dataSize)
{
int ipeekdatalen = socket->getDataToRead();
if(ipeekdatalen >= dataSize)
{
if(socket->receive(data, dataSize)!=dataSize)
{
if(socket != NULL && socket->getSocketId() > 0)
{
throw runtime_error("Error receiving NetworkMessage");
}
else
{
if(Socket::enableDebugText) printf("In [%s::%s] socket has been disconnected\n",__FILE__,__FUNCTION__);
}
}
else
{
if(Socket::enableDebugText) printf("In [%s::%s] dataSize = %d\n",__FILE__,__FUNCTION__,dataSize);
}
return true;
}
else
{
if(Socket::enableDebugText) printf("In [%s::%s] socket->getDataToRead() returned %d\n",__FILE__,__FUNCTION__,ipeekdatalen);
}
return false;
}
void NetworkMessage::send(Socket* socket, const void* data, int dataSize) const{
if(socket->send(data, dataSize)!=dataSize){
throw runtime_error("Error sending NetworkMessage");
void NetworkMessage::send(Socket* socket, const void* data, int dataSize) const
{
if(socket->send(data, dataSize)!=dataSize)
{
if(socket != NULL && socket->getSocketId() > 0)
{
throw runtime_error("Error sending NetworkMessage");
}
else
{
if(Socket::enableDebugText) printf("In [%s::%s] socket has been disconnected\n",__FILE__,__FUNCTION__);
}
}
}
@ -51,12 +85,12 @@ void NetworkMessage::send(Socket* socket, const void* data, int dataSize) const{
// =====================================================
NetworkMessageIntro::NetworkMessageIntro(){
data.messageType= -1;
data.messageType= -1;
data.playerIndex= -1;
}
NetworkMessageIntro::NetworkMessageIntro(const string &versionString, const string &name, int playerIndex){
data.messageType=nmtIntro;
data.messageType=nmtIntro;
data.versionString= versionString;
data.name= name;
data.playerIndex= static_cast<int16>(playerIndex);
@ -76,11 +110,11 @@ void NetworkMessageIntro::send(Socket* socket) const{
// =====================================================
NetworkMessageReady::NetworkMessageReady(){
data.messageType= nmtReady;
data.messageType= nmtReady;
}
NetworkMessageReady::NetworkMessageReady(int32 checksum){
data.messageType= nmtReady;
data.messageType= nmtReady;
data.checksum= checksum;
}
@ -98,7 +132,7 @@ void NetworkMessageReady::send(Socket* socket) const{
// =====================================================
NetworkMessageLaunch::NetworkMessageLaunch(){
data.messageType=-1;
data.messageType=-1;
}
NetworkMessageLaunch::NetworkMessageLaunch(const GameSettings *gameSettings){
@ -170,12 +204,23 @@ bool NetworkMessageCommandList::addCommand(const NetworkCommand* networkCommand)
}
bool NetworkMessageCommandList::receive(Socket* socket){
return NetworkMessage::receive(socket, &data, sizeof(data));
//return NetworkMessage::receive(socket, &data, sizeof(data));
// read type, commandCount & frame num first.
if (!NetworkMessage::receive(socket, &data, networkPacketMsgTypeSize)) {
return false;
}
// read data.commandCount commands.
if (data.commandCount) {
return NetworkMessage::receive(socket, &data.commands, sizeof(NetworkCommand) * data.commandCount);
}
return true;
}
void NetworkMessageCommandList::send(Socket* socket) const{
assert(data.messageType==nmtCommandList);
NetworkMessage::send(socket, &data, sizeof(data));
//NetworkMessage::send(socket, &data, sizeof(data));
NetworkMessage::send(socket, &data, networkPacketMsgTypeSize + sizeof(NetworkCommand) * data.commandCount);
}
// =====================================================
@ -183,7 +228,7 @@ void NetworkMessageCommandList::send(Socket* socket) const{
// =====================================================
NetworkMessageText::NetworkMessageText(const string &text, const string &sender, int teamIndex){
data.messageType= nmtText;
data.messageType= nmtText;
data.text= text;
data.sender= sender;
data.teamIndex= teamIndex;
@ -203,7 +248,7 @@ void NetworkMessageText::send(Socket* socket) const{
// =====================================================
NetworkMessageQuit::NetworkMessageQuit(){
data.messageType= nmtQuit;
data.messageType= nmtQuit;
}
bool NetworkMessageQuit::receive(Socket* socket){
@ -215,4 +260,133 @@ void NetworkMessageQuit::send(Socket* socket) const{
NetworkMessage::send(socket, &data, sizeof(data));
}
// =====================================================
// class NetworkMessageSynchNetworkGameData
// =====================================================
NetworkMessageSynchNetworkGameData::NetworkMessageSynchNetworkGameData(const GameSettings *gameSettings)
{
data.messageType= nmtSynchNetworkGameData;
data.map = gameSettings->getMap();
data.tileset = gameSettings->getTileset();
data.tech = gameSettings->getTech();
//Checksum checksum;
//tileset
//string file = "tilesets/" + gameSettings->getTileset() + "/" + gameSettings->getTileset() + ".xml";
//checksum.addFile(file);
// models
// sounds
// textures
//data.tilesetCRC = checksum.getSum();
//if(Socket::enableDebugText) printf("In [%s::%s] file = [%s] checksum = %d\n",__FILE__,__FUNCTION__,file.c_str(),data.tilesetCRC);
data.tilesetCRC = getFolderTreeContentsCheckSumRecursively("tilesets/" + gameSettings->getTileset() + "/*", "xml", NULL);
//tech, load before map because of resources
//checksum = Checksum();
//file = "techs/" + gameSettings->getTech() + "/" + gameSettings->getTech() + ".xml";
//checksum.addFile(file);
// factions
// resources
//data.techCRC = checksum.getSum();
//if(Socket::enableDebugText) printf("In [%s::%s] file = [%s] checksum = %d\n",__FILE__,__FUNCTION__,file.c_str(),data.techCRC);
data.techCRC = getFolderTreeContentsCheckSumRecursively("techs/" + gameSettings->getTech() + "/*", "xml", NULL);
//map
Checksum checksum;
string file = Map::getMapPath(gameSettings->getMap());
checksum.addFile(file);
data.mapCRC = checksum.getSum();
//if(Socket::enableDebugText) printf("In [%s::%s] file = [%s] checksum = %d\n",__FILE__,__FUNCTION__,file.c_str(),data.mapCRC);
data.hasFogOfWar = Config::getInstance().getBool("FogOfWar");;
}
bool NetworkMessageSynchNetworkGameData::receive(Socket* socket)
{
return NetworkMessage::receive(socket, &data, sizeof(data));
}
void NetworkMessageSynchNetworkGameData::send(Socket* socket) const
{
assert(data.messageType==nmtSynchNetworkGameData);
NetworkMessage::send(socket, &data, sizeof(data));
}
// =====================================================
// class NetworkMessageSynchNetworkGameDataStatus
// =====================================================
NetworkMessageSynchNetworkGameDataStatus::NetworkMessageSynchNetworkGameDataStatus(int32 mapCRC, int32 tilesetCRC, int32 techCRC, int8 hasFogOfWar)
{
data.messageType= nmtSynchNetworkGameDataStatus;
data.tilesetCRC = tilesetCRC;
data.techCRC = techCRC;
data.mapCRC = mapCRC;
data.hasFogOfWar = hasFogOfWar;
}
bool NetworkMessageSynchNetworkGameDataStatus::receive(Socket* socket)
{
return NetworkMessage::receive(socket, &data, sizeof(data));
}
void NetworkMessageSynchNetworkGameDataStatus::send(Socket* socket) const
{
assert(data.messageType==nmtSynchNetworkGameDataStatus);
NetworkMessage::send(socket, &data, sizeof(data));
}
// =====================================================
// class NetworkMessageSynchNetworkGameDataFileCRCCheck
// =====================================================
NetworkMessageSynchNetworkGameDataFileCRCCheck::NetworkMessageSynchNetworkGameDataFileCRCCheck(int32 totalFileCount, int32 fileIndex, int32 fileCRC, const string fileName)
{
data.messageType= nmtSynchNetworkGameDataFileCRCCheck;
data.totalFileCount = totalFileCount;
data.fileIndex = fileIndex;
data.fileCRC = fileCRC;
data.fileName = fileName;
}
bool NetworkMessageSynchNetworkGameDataFileCRCCheck::receive(Socket* socket)
{
return NetworkMessage::receive(socket, &data, sizeof(data));
}
void NetworkMessageSynchNetworkGameDataFileCRCCheck::send(Socket* socket) const
{
assert(data.messageType==nmtSynchNetworkGameDataFileCRCCheck);
NetworkMessage::send(socket, &data, sizeof(data));
}
// =====================================================
// class NetworkMessageSynchNetworkGameDataFileGet
// =====================================================
NetworkMessageSynchNetworkGameDataFileGet::NetworkMessageSynchNetworkGameDataFileGet(const string fileName)
{
data.messageType= nmtSynchNetworkGameDataFileGet;
data.fileName = fileName;
}
bool NetworkMessageSynchNetworkGameDataFileGet::receive(Socket* socket)
{
return NetworkMessage::receive(socket, &data, sizeof(data));
}
void NetworkMessageSynchNetworkGameDataFileGet::send(Socket* socket) const
{
assert(data.messageType==nmtSynchNetworkGameDataFileGet);
NetworkMessage::send(socket, &data, sizeof(data));
}
}}//end namespace

View File

@ -3,9 +3,9 @@
//
// 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
// 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
// ==============================================================
@ -33,10 +33,16 @@ enum NetworkMessageType{
nmtCommandList,
nmtText,
nmtQuit,
nmtSynchNetworkGameData,
nmtSynchNetworkGameDataStatus,
nmtSynchNetworkGameDataFileCRCCheck,
nmtSynchNetworkGameDataFileGet,
nmtCount
};
const int32 networkPacketMsgTypeSize = 6;
// =====================================================
// class NetworkMessage
// =====================================================
@ -163,10 +169,11 @@ public:
// 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;
@ -182,7 +189,7 @@ 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;}
@ -191,6 +198,7 @@ public:
virtual bool receive(Socket* socket);
virtual void send(Socket* socket) const;
};
#pragma pack(pop)
// =====================================================
// class NetworkMessageText
@ -247,6 +255,164 @@ public:
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

@ -3,9 +3,9 @@
//
// 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
// 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
// ==============================================================
@ -50,6 +50,7 @@ enum NetworkCommandType{
nctSetMeetingPoint
};
#pragma pack(push, 2)
class NetworkCommand{
private:
int16 networkCommandType;
@ -71,6 +72,7 @@ public:
int getUnitTypeId() const {return unitTypeId;}
int getTargetId() const {return targetId;}
};
#pragma pack(pop)
}}//end namespace

View File

@ -3,9 +3,9 @@
//
// 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
// 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
// ==============================================================
@ -20,6 +20,8 @@
#include "lang.h"
#include "leak_dumper.h"
#include "logger.h"
#include <time.h>
using namespace std;
using namespace Shared::Platform;
@ -32,6 +34,9 @@ namespace Glest{ namespace Game{
// =====================================================
ServerInterface::ServerInterface(){
gameHasBeenInitiated = false;
gameSettingsUpdateCount = 0;
for(int i= 0; i<GameConstants::maxPlayers; ++i){
slots[i]= NULL;
}
@ -40,23 +45,39 @@ ServerInterface::ServerInterface(){
}
ServerInterface::~ServerInterface(){
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
for(int i= 0; i<GameConstants::maxPlayers; ++i){
delete slots[i];
}
close();
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
}
void ServerInterface::addSlot(int playerIndex){
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
assert(playerIndex>=0 && playerIndex<GameConstants::maxPlayers);
delete slots[playerIndex];
slots[playerIndex]= new ConnectionSlot(this, playerIndex);
updateListen();
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
}
void ServerInterface::removeSlot(int playerIndex){
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
delete slots[playerIndex];
slots[playerIndex]= NULL;
updateListen();
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
}
ConnectionSlot* ServerInterface::getSlot(int playerIndex){
@ -65,7 +86,7 @@ ConnectionSlot* ServerInterface::getSlot(int playerIndex){
int ServerInterface::getConnectedSlotCount(){
int connectedSlotCount= 0;
for(int i= 0; i<GameConstants::maxPlayers; ++i){
if(slots[i]!= NULL){
++connectedSlotCount;
@ -74,44 +95,138 @@ int ServerInterface::getConnectedSlotCount(){
return connectedSlotCount;
}
void ServerInterface::update(){
void ServerInterface::update()
{
std::map<int,bool> socketTriggeredList;
//update all slots
for(int i= 0; i<GameConstants::maxPlayers; ++i){
if(slots[i]!= NULL){
slots[i]->update();
for(int i= 0; i < GameConstants::maxPlayers; ++i)
{
ConnectionSlot* connectionSlot= slots[i];
if(connectionSlot != NULL && connectionSlot->getSocket() != NULL &&
slots[i]->getSocket()->getSocketId() > 0)
{
socketTriggeredList[connectionSlot->getSocket()->getSocketId()] = false;
}
}
//process text messages
chatText.clear();
chatSender.clear();
chatTeamIndex= -1;
chatText.clear();
chatSender.clear();
chatTeamIndex= -1;
for(int i= 0; i<GameConstants::maxPlayers; ++i){
ConnectionSlot* connectionSlot= slots[i];
if(gameHasBeenInitiated == false || socketTriggeredList.size() > 0)
{
if(gameHasBeenInitiated && Socket::enableDebugText) printf("In [%s::%s] socketTriggeredList.size() = %d\n",__FILE__,__FUNCTION__,socketTriggeredList.size());
if(connectionSlot!= NULL){
if(connectionSlot->isConnected()){
if(connectionSlot->getNextMessageType()==nmtText){
NetworkMessageText networkMessageText;
if(connectionSlot->receiveMessage(&networkMessageText)){
broadcastMessage(&networkMessageText, i);
chatText= networkMessageText.getText();
chatSender= networkMessageText.getSender();
chatTeamIndex= networkMessageText.getTeamIndex();
break;
}
}
}
}
}
bool hasData = Socket::hasDataToRead(socketTriggeredList);
if(hasData && Socket::enableDebugText) printf("In [%s::%s] hasData == true\n",__FILE__,__FUNCTION__);
if(gameHasBeenInitiated == false || hasData == true)
{
//if(gameHasBeenInitiated && Socket::enableDebugText) printf("In [%s::%s] hasData == true\n",__FILE__,__FUNCTION__);
//std::vector<TeamMessageData> vctTeamMessages;
//update all slots
bool checkForNewClients = true;
for(int i= 0; i<GameConstants::maxPlayers; ++i)
{
ConnectionSlot* connectionSlot= slots[i];
if(connectionSlot != NULL &&
(gameHasBeenInitiated == false || (connectionSlot->getSocket() != NULL && socketTriggeredList[connectionSlot->getSocket()->getSocketId()] == true)))
{
if(connectionSlot->isConnected() == false ||
(socketTriggeredList[connectionSlot->getSocket()->getSocketId()] == true))
{
if(gameHasBeenInitiated && Socket::enableDebugText) printf("In [%s::%s] socketTriggeredList[i] = %i\n",__FILE__,__FUNCTION__,(socketTriggeredList[connectionSlot->getSocket()->getSocketId()] ? 1 : 0));
if(connectionSlot->isConnected())
{
if(Socket::enableDebugText) printf("In [%s::%s] calling slots[i]->update() for slot = %d socketId = %d\n",
__FILE__,__FUNCTION__,i,connectionSlot->getSocket()->getSocketId());
}
else
{
if(gameHasBeenInitiated && Socket::enableDebugText) printf("In [%s::%s] slot = %d getSocket() == NULL\n",__FILE__,__FUNCTION__,i);
}
connectionSlot->update(checkForNewClients);
// This means no clients are trying to connect at the moment
if(connectionSlot != NULL && connectionSlot->getSocket() == NULL)
{
checkForNewClients = false;
}
if(connectionSlot != NULL &&
//connectionSlot->isConnected() == true &&
connectionSlot->getChatText().empty() == false)
{
chatText = connectionSlot->getChatText();
chatSender = connectionSlot->getChatSender();
chatTeamIndex = connectionSlot->getChatTeamIndex();
//TeamMessageData teamMessageData;
//teamMessageData.chatSender = connectionSlot->getChatSender();
//teamMessageData.chatText = connectionSlot->getChatText();
//teamMessageData.chatTeamIndex = connectionSlot->getChatTeamIndex();
//teamMessageData.sourceTeamIndex = i;
//vctTeamMessages.push_back(teamMessageData);
if(Socket::enableDebugText) printf("In [%s::%s] #1 about to broadcast nmtText chatText [%s] chatSender [%s] chatTeamIndex = %d for SlotIndex# %d\n",__FILE__,__FUNCTION__,chatText.c_str(),chatSender.c_str(),chatTeamIndex,i);
NetworkMessageText networkMessageText(chatText,chatSender,chatTeamIndex);
broadcastMessage(&networkMessageText, i);
break;
}
}
}
}
//process text messages
if(chatText.empty() == true)
{
chatText.clear();
chatSender.clear();
chatTeamIndex= -1;
for(int i= 0; i< GameConstants::maxPlayers; ++i)
{
ConnectionSlot* connectionSlot= slots[i];
if(connectionSlot!= NULL &&
(gameHasBeenInitiated == false || (connectionSlot->getSocket() != NULL && socketTriggeredList[connectionSlot->getSocket()->getSocketId()] == true)))
{
if(connectionSlot->isConnected() && socketTriggeredList[connectionSlot->getSocket()->getSocketId()] == true)
{
if(connectionSlot->getSocket() != NULL && Socket::enableDebugText) printf("In [%s::%s] calling connectionSlot->getNextMessageType() for slots[i]->getSocket()->getSocketId() = %d\n",
__FILE__,__FUNCTION__,connectionSlot->getSocket()->getSocketId());
if(connectionSlot->getNextMessageType() == nmtText)
{
NetworkMessageText networkMessageText;
if(connectionSlot->receiveMessage(&networkMessageText))
{
if(Socket::enableDebugText) printf("In [%s::%s] #2 about to broadcast nmtText msg for SlotIndex# %d\n",__FILE__,__FUNCTION__,i);
broadcastMessage(&networkMessageText, i);
chatText= networkMessageText.getText();
chatSender= networkMessageText.getSender();
chatTeamIndex= networkMessageText.getTeamIndex();
break;
}
}
}
}
}
}
}
}
}
void ServerInterface::updateKeyframe(int frameCount){
NetworkMessageCommandList networkMessageCommandList(frameCount);
//build command list, remove commands from requested and add to pending
while(!requestedCommands.empty()){
if(networkMessageCommandList.addCommand(&requestedCommands.back())){
@ -128,51 +243,100 @@ void ServerInterface::updateKeyframe(int frameCount){
}
void ServerInterface::waitUntilReady(Checksum* checksum){
if(Socket::enableDebugText) printf("In [%s] START\n",__FUNCTION__);
Logger &logger= Logger::getInstance();
gameHasBeenInitiated = true;
Chrono chrono;
bool allReady= false;
chrono.start();
//wait until we get a ready message from all clients
while(!allReady){
while(allReady == false)
{
vector<string> waitingForHosts;
allReady= true;
for(int i= 0; i<GameConstants::maxPlayers; ++i){
for(int i= 0; i<GameConstants::maxPlayers; ++i)
{
ConnectionSlot* connectionSlot= slots[i];
if(connectionSlot!=NULL){
if(!connectionSlot->isReady()){
NetworkMessageType networkMessageType= connectionSlot->getNextMessageType();
if(connectionSlot != NULL && connectionSlot->isConnected() == true)
{
if(connectionSlot->isReady() == false)
{
NetworkMessageType networkMessageType= connectionSlot->getNextMessageType(true);
NetworkMessageReady networkMessageReady;
if(networkMessageType==nmtReady && connectionSlot->receiveMessage(&networkMessageReady)){
if(networkMessageType == nmtReady &&
connectionSlot->receiveMessage(&networkMessageReady))
{
if(Socket::enableDebugText) printf("In [%s] networkMessageType==nmtReady\n",__FUNCTION__);
connectionSlot->setReady();
}
else if(networkMessageType!=nmtInvalid){
else if(networkMessageType != nmtInvalid)
{
throw runtime_error("Unexpected network message: " + intToStr(networkMessageType));
}
waitingForHosts.push_back(connectionSlot->getHostName());
allReady= false;
}
}
}
//check for timeout
if(chrono.getMillis()>readyWaitTimeout){
throw runtime_error("Timeout waiting for clients");
if(allReady == false)
{
if(chrono.getMillis() > readyWaitTimeout)
{
throw runtime_error("Timeout waiting for clients");
}
else
{
if(chrono.getMillis() % 1000 == 0)
{
string waitForHosts = "";
for(int i = 0; i < waitingForHosts.size(); i++)
{
if(waitForHosts != "")
{
waitForHosts += ", ";
}
waitForHosts += waitingForHosts[i];
}
char szBuf[1024]="";
sprintf(szBuf,"Waiting for network: %d of %d max seconds (waiting for: %s)",int(chrono.getMillis() / 1000),int(readyWaitTimeout / 1000),waitForHosts.c_str());
logger.add(szBuf, true);
}
}
}
}
//send ready message after, so clients start delayed
for(int i= 0; i<GameConstants::maxPlayers; ++i){
NetworkMessageReady networkMessageReady(checksum->getSum());
ConnectionSlot* connectionSlot= slots[i];
if(connectionSlot!=NULL){
// FOR TESTING ONLY - delay to see the client count up while waiting
//sleep(5000);
if(Socket::enableDebugText) printf("In [%s] PART B (telling client we are ready!\n",__FUNCTION__);
//send ready message after, so clients start delayed
for(int i= 0; i < GameConstants::maxPlayers; ++i)
{
NetworkMessageReady networkMessageReady(checksum->getSum());
ConnectionSlot* connectionSlot= slots[i];
if(connectionSlot!=NULL)
{
connectionSlot->sendMessage(&networkMessageReady);
}
}
if(Socket::enableDebugText) printf("In [%s] END\n",__FUNCTION__);
}
void ServerInterface::sendTextMessage(const string &text, int teamIndex){
@ -180,7 +344,15 @@ void ServerInterface::sendTextMessage(const string &text, int teamIndex){
broadcastMessage(&networkMessageText);
}
void ServerInterface::quitGame(){
void ServerInterface::quitGame(bool userManuallyQuit)
{
if(userManuallyQuit == true)
{
string sQuitText = getHostName() + " has chosen to leave the game!";
NetworkMessageText networkMessageText(sQuitText,getHostName(),-1);
broadcastMessage(&networkMessageText, -1);
}
NetworkMessageQuit networkMessageQuit;
broadcastMessage(&networkMessageQuit);
}
@ -191,12 +363,13 @@ string ServerInterface::getNetworkStatus() const{
for(int i= 0; i<GameConstants::maxPlayers; ++i){
ConnectionSlot* connectionSlot= slots[i];
str+= intToStr(i)+ ": ";
if(connectionSlot!= NULL){
if(connectionSlot->isConnected()){
str+= connectionSlot->getName();
str+= connectionSlot->getName();
}
}
else
@ -209,31 +382,96 @@ string ServerInterface::getNetworkStatus() const{
return str;
}
void ServerInterface::launchGame(const GameSettings* gameSettings){
NetworkMessageLaunch networkMessageLaunch(gameSettings);
broadcastMessage(&networkMessageLaunch);
bool ServerInterface::launchGame(const GameSettings* gameSettings){
bool bOkToStart = true;
for(int i= 0; i<GameConstants::maxPlayers; ++i)
{
ConnectionSlot *connectionSlot= slots[i];
if(connectionSlot != NULL &&
connectionSlot->getAllowDownloadDataSynch() == true &&
connectionSlot->isConnected())
{
if(connectionSlot->getNetworkGameDataSynchCheckOk() == false)
{
bOkToStart = false;
break;
}
}
}
if(bOkToStart == true)
{
NetworkMessageLaunch networkMessageLaunch(gameSettings);
broadcastMessage(&networkMessageLaunch);
}
return bOkToStart;
}
void ServerInterface::broadcastMessage(const NetworkMessage* networkMessage, int excludeSlot){
//if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
for(int i= 0; i<GameConstants::maxPlayers; ++i)
{
ConnectionSlot* connectionSlot= slots[i];
if(i != excludeSlot && connectionSlot != NULL)
{
if(connectionSlot->isConnected())
{
if(Socket::enableDebugText) printf("In [%s::%s] before sendMessage\n",__FILE__,__FUNCTION__);
connectionSlot->sendMessage(networkMessage);
}
else if(gameHasBeenInitiated == true)
{
if(Socket::enableDebugText) printf("In [%s::%s] #1 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,i);
removeSlot(i);
}
}
else if(i == excludeSlot && gameHasBeenInitiated == true &&
connectionSlot != NULL && connectionSlot->isConnected() == false)
{
if(Socket::enableDebugText) printf("In [%s::%s] #2 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,i);
removeSlot(i);
}
}
//if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
}
void ServerInterface::broadcastMessageToConnectedClients(const NetworkMessage* networkMessage, int excludeSlot){
//if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
for(int i= 0; i<GameConstants::maxPlayers; ++i){
ConnectionSlot* connectionSlot= slots[i];
if(i!= excludeSlot && connectionSlot!= NULL){
if(connectionSlot->isConnected()){
if(Socket::enableDebugText) printf("In [%s::%s] before sendMessage\n",__FILE__,__FUNCTION__);
connectionSlot->sendMessage(networkMessage);
}
else{
removeSlot(i);
}
}
}
//if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
}
void ServerInterface::updateListen(){
void ServerInterface::updateListen()
{
int openSlotCount= 0;
for(int i= 0; i<GameConstants::maxPlayers; ++i){
if(slots[i]!= NULL && !slots[i]->isConnected()){
for(int i= 0; i<GameConstants::maxPlayers; ++i)
{
if(slots[i] != NULL && slots[i]->isConnected() == false)
{
++openSlotCount;
}
}
@ -241,4 +479,92 @@ void ServerInterface::updateListen(){
serverSocket.listen(openSlotCount);
}
void ServerInterface::setGameSettings(GameSettings *serverGameSettings, bool waitForClientAck)
{
if(Socket::enableDebugText) printf("In [%s::%s] START gameSettingsUpdateCount = %d\n",__FILE__,__FUNCTION__,gameSettingsUpdateCount);
if(getAllowGameDataSynchCheck() == true)
{
if(waitForClientAck == true && gameSettingsUpdateCount > 0)
{
if(Socket::enableDebugText) printf("In [%s::%s] Waiting for client acks #1\n",__FILE__,__FUNCTION__);
time_t tStart = time(NULL);
bool gotAckFromAllClients = false;
while(gotAckFromAllClients == false && difftime(time(NULL),tStart) <= 5)
{
gotAckFromAllClients = true;
for(int i= 0; i<GameConstants::maxPlayers; ++i)
{
ConnectionSlot *connectionSlot = slots[i];
if(connectionSlot != NULL && connectionSlot->isConnected())
{
if(connectionSlot->getReceivedNetworkGameStatus() == false)
{
gotAckFromAllClients = false;
}
connectionSlot->update();
}
}
}
}
for(int i= 0; i<GameConstants::maxPlayers; ++i)
{
ConnectionSlot *connectionSlot = slots[i];
if(connectionSlot != NULL && connectionSlot->isConnected())
{
connectionSlot->setReceivedNetworkGameStatus(false);
}
}
gameSettings = *serverGameSettings;
NetworkMessageSynchNetworkGameData networkMessageSynchNetworkGameData(getGameSettings());
broadcastMessageToConnectedClients(&networkMessageSynchNetworkGameData);
if(waitForClientAck == true)
{
if(Socket::enableDebugText) printf("In [%s::%s] Waiting for client acks #2\n",__FILE__,__FUNCTION__);
time_t tStart = time(NULL);
bool gotAckFromAllClients = false;
while(gotAckFromAllClients == false && difftime(time(NULL),tStart) <= 5)
{
gotAckFromAllClients = true;
for(int i= 0; i<GameConstants::maxPlayers; ++i)
{
ConnectionSlot *connectionSlot = slots[i];
if(connectionSlot != NULL && connectionSlot->isConnected())
{
if(connectionSlot->getReceivedNetworkGameStatus() == false)
{
gotAckFromAllClients = false;
}
connectionSlot->update();
}
}
}
}
gameSettingsUpdateCount++;
}
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
}
void ServerInterface::close()
{
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
//serverSocket = ServerSocket();
}
bool ServerInterface::getFogOfWar()
{
return Config::getInstance().getBool("FogOfWar");
}
}}//end namespace

View File

@ -3,9 +3,9 @@
//
// 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
// 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
// ==============================================================
@ -28,10 +28,21 @@ namespace Glest{ namespace Game{
// class ServerInterface
// =====================================================
typedef struct
{
string chatText;
string chatSender;
int chatTeamIndex;
int sourceTeamIndex;
} TeamMessageData;
class ServerInterface: public GameNetworkInterface{
private:
ConnectionSlot* slots[GameConstants::maxPlayers];
ServerSocket serverSocket;
bool gameHasBeenInitiated;
int gameSettingsUpdateCount;
public:
ServerInterface();
@ -39,6 +50,7 @@ public:
virtual Socket* getSocket() {return &serverSocket;}
virtual const Socket* getSocket() const {return &serverSocket;}
virtual void close();
//message processing
virtual void update();
@ -48,7 +60,7 @@ public:
// message sending
virtual void sendTextMessage(const string &text, int teamIndex);
virtual void quitGame();
virtual void quitGame(bool userManuallyQuit);
//misc
virtual string getNetworkStatus() const;
@ -59,11 +71,14 @@ public:
ConnectionSlot* getSlot(int playerIndex);
int getConnectedSlotCount();
void launchGame(const GameSettings* gameSettings);
bool launchGame(const GameSettings* gameSettings);
virtual void setGameSettings(GameSettings *serverGameSettings, bool waitForClientAck = false);
virtual bool getFogOfWar();
private:
void broadcastMessage(const NetworkMessage* networkMessage, int excludeSlot= -1);
void updateListen();
void broadcastMessageToConnectedClients(const NetworkMessage* networkMessage, int excludeSlot = -1);
};
}}//end namespace

View File

@ -1,11 +1,11 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<EFBFBD>o Figueroa
// 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
// 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
// ==============================================================
@ -31,7 +31,7 @@ namespace Glest{ namespace Game{
// =====================================================
void Faction::init(
const FactionType *factionType, ControlType control, TechTree *techTree,
const FactionType *factionType, ControlType control, TechTree *techTree,
int factionIndex, int teamIndex, int startLocationIndex, bool thisFaction, bool giveResources)
{
this->control= control;
@ -83,7 +83,7 @@ int Faction::getStoreAmount(const ResourceType *rt) const{
bool Faction::getCpuControl() const{
return control==ctCpuEasy ||control==ctCpu || control==ctCpuUltra|| control==ctCpuMega;
}
// ==================== upgrade manager ====================
@ -106,9 +106,9 @@ void Faction::finishUpgrade(const UpgradeType *ut){
//checks if all required units and upgrades are present
bool Faction::reqsOk(const RequirableType *rt) const{
//required units
for(int i=0; i<rt->getUnitReqCount(); ++i){
for(int i=0; i<rt->getUnitReqCount(); ++i){
bool found=false;
for(int j=0; j<getUnitCount(); ++j){
Unit *unit= getUnit(j);
@ -125,7 +125,7 @@ bool Faction::reqsOk(const RequirableType *rt) const{
//required upgrades
for(int i=0; i<rt->getUpgradeReqCount(); ++i){
if(!upgradeManager.isUpgraded(rt->getUpgradeReq(i))){
if(!upgradeManager.isUpgraded(rt->getUpgradeReq(i))){
return false;
}
}
@ -134,7 +134,7 @@ bool Faction::reqsOk(const RequirableType *rt) const{
}
bool Faction::reqsOk(const CommandType *ct) const{
if(ct->getProduced()!=NULL && !reqsOk(ct->getProduced())){
return false;
}
@ -145,113 +145,134 @@ bool Faction::reqsOk(const CommandType *ct) const{
return false;
}
}
return reqsOk(static_cast<const RequirableType*>(ct));
return reqsOk(static_cast<const RequirableType*>(ct));
}
// ================== cost application ==================
//apply costs except static production (start building/production)
bool Faction::applyCosts(const ProducibleType *p){
if(!checkCosts(p)){
return false;
}
//for each unit cost spend it
//pass 2, decrease resources, except negative static costs (ie: farms)
for(int i=0; i<p->getCostCount(); ++i){
for(int i=0; i<p->getCostCount(); ++i)
{
const ResourceType *rt= p->getCost(i)->getType();
int cost= p->getCost(i)->getAmount();
if((cost>0 || rt->getClass()!=rcStatic) && rt->getClass()!=rcConsumable){
if((cost > 0 || (rt->getClass() != rcStatic)) && rt->getClass() != rcConsumable)
{
incResourceAmount(rt, -(cost));
}
}
return true;
}
//apply discount (when a morph ends)
void Faction::applyDiscount(const ProducibleType *p, int discount){
void Faction::applyDiscount(const ProducibleType *p, int discount)
{
//increase resources
for(int i=0; i<p->getCostCount(); ++i){
for(int i=0; i<p->getCostCount(); ++i)
{
const ResourceType *rt= p->getCost(i)->getType();
int cost= p->getCost(i)->getAmount();
if((cost>0 || rt->getClass()!=rcStatic) && rt->getClass()!=rcConsumable){
if((cost > 0 || (rt->getClass() != rcStatic)) && rt->getClass() != rcConsumable)
{
incResourceAmount(rt, cost*discount/100);
}
}
}
//apply static production (for starting units)
void Faction::applyStaticCosts(const ProducibleType *p){
void Faction::applyStaticCosts(const ProducibleType *p)
{
//decrease static resources
for(int i=0; i<p->getCostCount(); ++i){
for(int i=0; i<p->getCostCount(); ++i)
{
const ResourceType *rt= p->getCost(i)->getType();
if(rt->getClass()==rcStatic){
if(rt->getClass() == rcStatic)
{
int cost= p->getCost(i)->getAmount();
if(cost>0){
if(cost > 0)
{
incResourceAmount(rt, -cost);
}
}
}
}
}
//apply static production (when a mana source is done)
void Faction::applyStaticProduction(const ProducibleType *p){
void Faction::applyStaticProduction(const ProducibleType *p)
{
//decrease static resources
for(int i=0; i<p->getCostCount(); ++i){
for(int i=0; i<p->getCostCount(); ++i)
{
const ResourceType *rt= p->getCost(i)->getType();
if(rt->getClass()==rcStatic){
if(rt->getClass() == rcStatic)
{
int cost= p->getCost(i)->getAmount();
if(cost<0){
if(cost < 0)
{
incResourceAmount(rt, -cost);
}
}
}
}
}
//deapply all costs except static production (usually when a building is cancelled)
void Faction::deApplyCosts(const ProducibleType *p){
void Faction::deApplyCosts(const ProducibleType *p)
{
//increase resources
for(int i=0; i<p->getCostCount(); ++i){
for(int i=0; i<p->getCostCount(); ++i)
{
const ResourceType *rt= p->getCost(i)->getType();
int cost= p->getCost(i)->getAmount();
if((cost>0 || rt->getClass()!=rcStatic) && rt->getClass()!=rcConsumable){
if((cost > 0 || (rt->getClass() != rcStatic)) && rt->getClass() != rcConsumable)
{
incResourceAmount(rt, cost);
}
}
}
//deapply static costs (usually when a unit dies)
void Faction::deApplyStaticCosts(const ProducibleType *p){
void Faction::deApplyStaticCosts(const ProducibleType *p)
{
//decrease resources
for(int i=0; i<p->getCostCount(); ++i){
for(int i=0; i<p->getCostCount(); ++i)
{
const ResourceType *rt= p->getCost(i)->getType();
if(rt->getClass()==rcStatic){
int cost= p->getCost(i)->getAmount();
incResourceAmount(rt, cost);
}
if(rt->getClass() == rcStatic)
{
if(rt->getRecoup_cost() == true)
{
int cost= p->getCost(i)->getAmount();
incResourceAmount(rt, cost);
}
}
}
}
//deapply static costs, but not negative costs, for when building gets killed
void Faction::deApplyStaticConsumption(const ProducibleType *p){
void Faction::deApplyStaticConsumption(const ProducibleType *p)
{
//decrease resources
for(int i=0; i<p->getCostCount(); ++i){
for(int i=0; i<p->getCostCount(); ++i)
{
const ResourceType *rt= p->getCost(i)->getType();
if(rt->getClass()==rcStatic){
if(rt->getClass() == rcStatic)
{
int cost= p->getCost(i)->getAmount();
if(cost>0){
if(cost>0)
{
incResourceAmount(rt, cost);
}
}
}
}
}
@ -279,7 +300,7 @@ void Faction::applyCostsOnInterval(){
const Resource *resource= unit->getType()->getCost(k);
if(resource->getType()->getClass()==rcConsumable && resource->getAmount()>0){
incResourceAmount(resource->getType(), -resource->getAmount());
//decrease unit hp
if(getResource(resource->getType())->getAmount()<0){
resetResourceAmount(resource->getType());
@ -296,7 +317,7 @@ void Faction::applyCostsOnInterval(){
}
bool Faction::checkCosts(const ProducibleType *pt){
//for each unit cost check if enough resources
for(int i=0; i<pt->getCostCount(); ++i){
const ResourceType *rt= pt->getCost(i)->getType();
@ -304,7 +325,7 @@ bool Faction::checkCosts(const ProducibleType *pt){
if(cost>0){
int available= getResource(rt)->getAmount();
if(cost>available){
return false;
return false;
}
}
}
@ -320,12 +341,16 @@ bool Faction::isAlly(const Faction *faction){
// ================== misc ==================
void Faction::incResourceAmount(const ResourceType *rt, int amount){
for(int i=0; i<resources.size(); ++i){
void Faction::incResourceAmount(const ResourceType *rt, int amount)
{
for(int i=0; i<resources.size(); ++i)
{
Resource *r= &resources[i];
if(r->getType()==rt){
if(r->getType()==rt)
{
r->setAmount(r->getAmount()+amount);
if(r->getType()->getClass()!=rcStatic && r->getAmount()>getStoreAmount(rt)){
if(r->getType()->getClass() != rcStatic && r->getAmount()>getStoreAmount(rt))
{
r->setAmount(getStoreAmount(rt));
}
return;
@ -368,7 +393,7 @@ void Faction::removeUnit(Unit *unit){
return;
}
}
assert(false);
assert(false);
}
void Faction::addStore(const UnitType *unitType){
@ -396,11 +421,14 @@ void Faction::removeStore(const UnitType *unitType){
limitResourcesToStore();
}
void Faction::limitResourcesToStore(){
for(int i=0; i<resources.size(); ++i){
void Faction::limitResourcesToStore()
{
for(int i=0; i<resources.size(); ++i)
{
Resource *r= &resources[i];
Resource *s= &store[i];
if(r->getType()->getClass()!=rcStatic && r->getAmount()>s->getAmount()){
if(r->getType()->getClass() != rcStatic && r->getAmount()>s->getAmount())
{
r->setAmount(s->getAmount());
}
}

View File

@ -1,7 +1,7 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<EFBFBD>o Figueroa
// 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

View File

@ -1,7 +1,7 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<EFBFBD>o Figueroa
// 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

View File

@ -1,7 +1,7 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<EFBFBD>o Figueroa
// 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
@ -254,7 +254,7 @@ public:
//command related
bool anyCommand() const;
Command *getCurrCommand() const;
uint getCommandSize() const;
unsigned int getCommandSize() const;
CommandResult giveCommand(Command *command); //give a command
CommandResult finishCommand(); //command finished
CommandResult cancelCommand(); //cancel canceled

View File

@ -3,15 +3,15 @@
//
// 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
// 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
// ==============================================================
#include "resource_type.h"
#include "util.h"
#include "util.h"
#include "element_type.h"
#include "logger.h"
#include "renderer.h"
@ -33,9 +33,12 @@ void ResourceType::load(const string &dir, Checksum* checksum){
string path, str;
Renderer &renderer= Renderer::getInstance();
try{
try
{
recoup_cost = true;
name= lastDir(dir);
Logger::getInstance().add("Resource type: "+ formatString(name), true);
path= dir+"/"+name+".xml";
@ -55,46 +58,64 @@ void ResourceType::load(const string &dir, Checksum* checksum){
const XmlNode *typeNode= resourceNode->getChild("type");
resourceClass= strToRc(typeNode->getAttribute("value")->getRestrictedValue());
switch(resourceClass){
case rcTech:{
//model
const XmlNode *modelNode= typeNode->getChild("model");
string path=dir+"/" + modelNode->getAttribute("path")->getRestrictedValue();
model= renderer.newModel(rsGame);
model->load(path);
//default resources
const XmlNode *defaultAmountNode= typeNode->getChild("default-amount");
defResPerPatch= defaultAmountNode->getAttribute("value")->getIntValue();
//resource number
const XmlNode *resourceNumberNode= typeNode->getChild("resource-number");
resourceNumber= resourceNumberNode->getAttribute("value")->getIntValue();
}
break;
switch(resourceClass)
{
case rcTech:
{
//model
const XmlNode *modelNode= typeNode->getChild("model");
string path=dir+"/" + modelNode->getAttribute("path")->getRestrictedValue();
case rcTileset:{
//resource number
const XmlNode *defaultAmountNode= typeNode->getChild("default-amount");
defResPerPatch= defaultAmountNode->getAttribute("value")->getIntValue();
model= renderer.newModel(rsGame);
model->load(path);
//resource number
const XmlNode *tilesetObjectNode= typeNode->getChild("tileset-object");
tilesetObject= tilesetObjectNode->getAttribute("value")->getIntValue();
//default resources
const XmlNode *defaultAmountNode= typeNode->getChild("default-amount");
defResPerPatch= defaultAmountNode->getAttribute("value")->getIntValue();
//resource number
const XmlNode *resourceNumberNode= typeNode->getChild("resource-number");
resourceNumber= resourceNumberNode->getAttribute("value")->getIntValue();
}
break;
case rcConsumable:{
//interval
const XmlNode *intervalNode= typeNode->getChild("interval");
interval= intervalNode->getAttribute("value")->getIntValue();
case rcTileset:
{
//resource number
const XmlNode *defaultAmountNode= typeNode->getChild("default-amount");
defResPerPatch= defaultAmountNode->getAttribute("value")->getIntValue();
//resource number
const XmlNode *tilesetObjectNode= typeNode->getChild("tileset-object");
tilesetObject= tilesetObjectNode->getAttribute("value")->getIntValue();
}
break;
case rcConsumable:
{
//interval
const XmlNode *intervalNode= typeNode->getChild("interval");
interval= intervalNode->getAttribute("value")->getIntValue();
}
break;
case rcStatic:
{
//recoup_cost
if(typeNode->hasChild("recoup_cost") == true)
{
const XmlNode *recoup_costNode= typeNode->getChild("recoup_cost");
if(recoup_costNode != NULL)
{
recoup_cost= recoup_costNode->getAttribute("value")->getBoolValue();
}
}
}
break;
default:
break;
break;
}
}
catch(const exception &e){
@ -103,7 +124,7 @@ void ResourceType::load(const string &dir, Checksum* checksum){
}
// ==================== misc ====================
// ==================== misc ====================
ResourceClass ResourceType::strToRc(const string &s){
if(s=="tech"){

View File

@ -3,9 +3,9 @@
//
// 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
// 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
// ==============================================================
@ -22,7 +22,7 @@ using Shared::Graphics::Model;
using Shared::Util::Checksum;
enum ResourceClass{
rcTech,
rcTech,
rcTileset,
rcStatic,
rcConsumable
@ -41,6 +41,8 @@ private:
int resourceNumber; //used only if class==rcTech, resource number in the map
int interval; //used only if class==rcConsumable
int defResPerPatch; //used only if class==rcTileset || class==rcTech
bool recoup_cost;
Model *model;
public:
@ -53,6 +55,7 @@ public:
int getInterval() const {return interval;}
int getDefResPerPatch() const {return defResPerPatch;}
const Model *getModel() const {return model;}
bool getRecoup_cost() const { return recoup_cost;}
static ResourceClass strToRc(const string &s);
};

View File

@ -3,9 +3,9 @@
//
// 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
// 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
// ==============================================================
@ -31,7 +31,7 @@ class FactionType;
// ===============================
// class Level
// class Level
// ===============================
class Level{
@ -47,7 +47,7 @@ public:
};
// ===============================
// class UnitType
// class UnitType
//
/// A unit or building type
// ===============================
@ -89,9 +89,9 @@ private:
bool light;
Vec3f lightColor;
bool multiSelect;
int sight;
int sight;
int size; //size in cells
int height;
int height;
//cellmap
bool *cellMap;
@ -131,10 +131,10 @@ public:
bool getProperty(Property property) const {return properties[property];}
int getArmor() const {return armor;}
const ArmorType *getArmorType() const {return armorType;}
const SkillType *getSkillType(int i) const {return skillTypes[i];}
const SkillType *getSkillType(int i) const {return skillTypes[i];}
const CommandType *getCommandType(int i) const {return commandTypes[i];}
const Level *getLevel(int i) const {return &levels[i];}
int getSkillTypeCount() const {return skillTypes.size();}
int getSkillTypeCount() const {return skillTypes.size();}
int getCommandTypeCount() const {return commandTypes.size();}
int getLevelCount() const {return levels.size();}
bool getLight() const {return light;}
@ -143,7 +143,7 @@ public:
int getSight() const {return sight;}
int getSize() const {return size;}
int getHeight() const {return height;}
int getStoredResourceCount() const {return storedResources.size();}
int getStoredResourceCount() const {return storedResources.size();}
const Resource *getStoredResource(int i) const {return &storedResources[i];}
bool getCellMapCell(int x, int y) const {return cellMap[size*y+x];}
bool getMeetingPoint() const {return meetingPoint;}
@ -166,7 +166,7 @@ public:
int getTotalSight(const TotalUpgrade *totalUpgrade) const;
//has
bool hasCommandType(const CommandType *commandType) const;
bool hasCommandType(const CommandType *commandType) const;
bool hasCommandClass(CommandClass commandClass) const;
bool hasSkillType(const SkillType *skillType) const;
bool hasSkillClass(SkillClass skillClass) const;

View File

@ -1,7 +1,7 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<EFBFBD>o Figueroa
// 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

View File

@ -1,7 +1,7 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<EFBFBD>o Figueroa
// 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

View File

@ -3,9 +3,9 @@
//
// Copyright (C) 2005 Matthias Braun <matze@braunis.de>
//
// 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
// 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
// ==============================================================
@ -22,6 +22,7 @@
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
#include <map>
using std::string;
@ -51,20 +52,30 @@ public:
class Socket {
protected:
int sock;
public:
Socket(int sock);
Socket();
~Socket();
static bool enableDebugText;
// Int lookup is socket fd while bool result is whether or not that socket was signalled for reading
static bool hasDataToRead(std::map<int,bool> &socketTriggeredList);
static bool hasDataToRead(int socket);
bool hasDataToRead();
void disconnectSocket();
int getSocketId() const { return sock; }
int getDataToRead();
int send(const void *data, int dataSize);
int receive(void *data, int dataSize);
int peek(void *data, int dataSize);
void setBlock(bool block);
bool isReadable();
bool isWritable();
bool isWritable(bool waitOnDelayedResponse);
bool isConnected();
string getHostName() const;

View File

@ -3,9 +3,9 @@
//
// Copyright (C) 2005 Matthias Braun <matze@braunis.de>
//
// 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
// 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 _SHARED_PLATFORM_PLATFORMUTIL_H_
@ -18,6 +18,8 @@
#include <SDL.h>
#include "types.h"
#include "checksum.h"
#include <utility>
using std::string;
using std::vector;
@ -25,6 +27,8 @@ using std::exception;
using Shared::Platform::int64;
using Shared::Util::Checksum;
namespace Shared{ namespace Platform{
// =====================================================
@ -41,7 +45,7 @@ private:
public:
void init(float fps, int maxTimes= -1);
bool isTime();
void reset();
};
@ -85,6 +89,10 @@ public:
// =====================================================
void findAll(const string &path, vector<string> &results, bool cutExtension=false);
int32 getFolderTreeContentsCheckSumRecursively(const string &path, const string &filterFileExt, Checksum *recursiveChecksum);
vector<std::pair<string,int32> > getFolderTreeContentsCheckSumListRecursively(const string &path, const string &filterFileExt, vector<std::pair<string,int32> > *recursiveMap);
void createDirectoryPaths(string Path);
string extractDirectoryPathFromFile(string filename);
bool changeVideoMode(int resH, int resW, int colorBits, int refreshFrequency);
void restoreVideoMode();

View File

@ -14,8 +14,8 @@
#include <windows.h>
#include <gl.h>
#include <glu.h>
#include <GL\gl.h>
#include <GL\glu.h>
#include <glprocs.h>
#include <string>

View File

@ -19,12 +19,15 @@
#include <stdexcept>
#include "types.h"
#include "checksum.h"
#include <utility>
using std::string;
using std::vector;
using std::exception;
using Shared::Platform::int64;
using Shared::Util::Checksum;
namespace Shared{ namespace Platform{
@ -96,6 +99,10 @@ public:
// =====================================================
void findAll(const string &path, vector<string> &results, bool cutExtension=false);
int32 getFolderTreeContentsCheckSumRecursively(const string &path, const string &filterFileExt, Checksum *recursiveChecksum);
vector<std::pair<string,int32> > getFolderTreeContentsCheckSumListRecursively(const string &path, const string &filterFileExt, vector<std::pair<string,int32> > *recursiveMap);
void createDirectoryPaths(string Path);
string extractDirectoryPathFromFile(string filename);
bool changeVideoMode(int resH, int resW, int colorBits, int refreshFrequency);
void restoreVideoMode();

View File

@ -3,9 +3,9 @@
//
// 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
// 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
// ==============================================================
@ -14,6 +14,7 @@
#include <string>
#include <winsock.h>
#include <map>
using std::string;
@ -51,20 +52,30 @@ private:
protected:
static SocketManager socketManager;
SOCKET sock;
public:
Socket(SOCKET sock);
Socket();
~Socket();
static bool enableDebugText;
// Int lookup is socket fd while bool result is whether or not that socket was signalled for reading
static bool hasDataToRead(std::map<int,bool> &socketTriggeredList);
static bool hasDataToRead(int socket);
bool hasDataToRead();
void disconnectSocket();
int getSocketId() const { return sock; }
int getDataToRead();
int send(const void *data, int dataSize);
int receive(void *data, int dataSize);
int peek(void *data, int dataSize);
void setBlock(bool block);
bool isReadable();
bool isWritable();
bool isWritable(bool waitOnDelayedResponse);
bool isConnected();
string getHostName() const;

View File

@ -3,9 +3,9 @@
//
// 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
// 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
// ==============================================================
@ -32,7 +32,7 @@ private:
int32 r;
int32 c1;
int32 c2;
public:
Checksum();

View File

@ -3,9 +3,9 @@
//
// 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
// 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
// ==============================================================
@ -35,11 +35,11 @@ class XmlIo;
class XmlTree;
class XmlNode;
class XmlAttribute;
// =====================================================
// class XmlIo
//
/// Wrapper for Xerces C++
// class XmlIo
//
/// Wrapper for Xerces C++
// =====================================================
class XmlIo{
@ -72,11 +72,11 @@ private:
public:
XmlTree();
~XmlTree();
void init(const string &name);
void load(const string &path);
void save(const string &path);
XmlNode *getRootNode() const {return rootNode;}
};
@ -89,7 +89,7 @@ private:
string name;
string text;
vector<XmlNode*> children;
vector<XmlAttribute*> attributes;
vector<XmlAttribute*> attributes;
private:
XmlNode(XmlNode&);
@ -109,6 +109,7 @@ public:
XmlAttribute *getAttribute(const string &name) const;
XmlNode *getChild(int i) const;
XmlNode *getChild(const string &childName, int childIndex=0) const;
bool hasChild(const string &childName) const;
XmlNode *getParent() const;
@ -143,9 +144,9 @@ public:
const string &getValue() const {return value;}
bool getBoolValue() const;
int getIntValue() const;
int getIntValue() const;
int getIntValue(int min, int max) const;
float getFloatValue() const;
float getFloatValue() const;
float getFloatValue(float min, float max) const;
const string &getRestrictedValue() const;
};

View File

@ -1,9 +1,9 @@
//This file is part of Glest Shared Library (www.glest.org)
//Copyright (C) 2005 Matthias Braun <matze@braunis.de>
//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
//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.
#include "socket.h"
@ -28,6 +28,8 @@ using namespace Shared::Util;
namespace Shared{ namespace Platform{
bool Socket::enableDebugText = true;
// =====================================================
// class Ip
// =====================================================
@ -48,7 +50,7 @@ Ip::Ip(unsigned char byte0, unsigned char byte1, unsigned char byte2, unsigned c
Ip::Ip(const string& ipString){
int offset= 0;
int offset= 0;
int byteIndex= 0;
for(byteIndex= 0; byteIndex<4; ++byteIndex){
@ -71,51 +73,307 @@ Socket::Socket(int sock){
this->sock= sock;
}
Socket::Socket(){
Socket::Socket()
{
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sock<0) {
if(sock < 0)
{
throwException("Error creating socket");
}
}
Socket::~Socket() {
::close(sock);
Socket::~Socket()
{
if(Socket::enableDebugText) printf("In [%s::%s] START closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
disconnectSocket();
if(Socket::enableDebugText) printf("In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
}
void Socket::disconnectSocket()
{
if(Socket::enableDebugText) printf("In [%s::%s] START closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
if(sock > 0)
{
if(Socket::enableDebugText) printf("In [%s::%s] calling shutdown and close for socket = %d...\n",__FILE__,__FUNCTION__,sock);
::shutdown(sock,2);
::close(sock);
sock = -1;
}
if(Socket::enableDebugText) printf("In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
}
// Int lookup is socket fd while bool result is whether or not that socket was signalled for reading
bool Socket::hasDataToRead(std::map<int,bool> &socketTriggeredList)
{
bool bResult = false;
if(socketTriggeredList.size() > 0)
{
/* Watch stdin (fd 0) to see when it has input. */
fd_set rfds;
FD_ZERO(&rfds);
int imaxsocket = 0;
for(std::map<int,bool>::iterator itermap = socketTriggeredList.begin();
itermap != socketTriggeredList.end(); itermap++)
{
int socket = itermap->first;
if(socket > 0)
{
FD_SET(socket, &rfds);
imaxsocket = max(socket,imaxsocket);
}
}
if(imaxsocket > 0)
{
/* Wait up to 0 seconds. */
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
int retval = select(imaxsocket + 1, &rfds, NULL, NULL, &tv);
if(retval < 0)
{
char szBuf[1024]="";
sprintf(szBuf,"In [%s::%s] ERROR SELECTING SOCKET DATA retval = %d errno = %d [%s]",__FILE__,__FUNCTION__,retval,errno,strerror(errno));
fprintf(stderr, "%s", szBuf);
}
else if(retval)
{
bResult = true;
if(Socket::enableDebugText) printf("In [%s::%s] select detected data imaxsocket = %d...\n",__FILE__,__FUNCTION__,imaxsocket);
for(std::map<int,bool>::iterator itermap = socketTriggeredList.begin();
itermap != socketTriggeredList.end(); itermap++)
{
int socket = itermap->first;
if (FD_ISSET(socket, &rfds))
{
if(Socket::enableDebugText) printf("In [%s] FD_ISSET true for socket %d...\n",__FUNCTION__,socket);
itermap->second = true;
}
else
{
itermap->second = false;
}
}
if(Socket::enableDebugText) printf("In [%s::%s] socketTriggeredList->size() = %d\n",__FILE__,__FUNCTION__,socketTriggeredList.size());
}
}
}
return bResult;
}
bool Socket::hasDataToRead()
{
return Socket::hasDataToRead(sock) ;
}
bool Socket::hasDataToRead(int socket)
{
bool bResult = false;
if(socket > 0)
{
fd_set rfds;
struct timeval tv;
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(socket, &rfds);
/* Wait up to 0 seconds. */
tv.tv_sec = 0;
tv.tv_usec = 0;
int retval = select(socket + 1, &rfds, NULL, NULL, &tv);
if(retval)
{
if (FD_ISSET(socket, &rfds))
{
bResult = true;
}
}
}
return bResult;
}
int Socket::getDataToRead(){
unsigned long size;
unsigned long size = 0;
/* ioctl isn't posix, but the following seems to work on all modern
* unixes */
int err= ioctl(sock, FIONREAD, &size);
//fd_set rfds;
//struct timeval tv;
//int retval;
if(err < 0 && errno != EAGAIN){
throwException("Can not get data to read");
}
/* Watch stdin (fd 0) to see when it has input. */
//FD_ZERO(&rfds);
//FD_SET(sock, &rfds);
/* Wait up to 0 seconds. */
//tv.tv_sec = 0;
//tv.tv_usec = 0;
//retval = select(sock + 1, &rfds, NULL, NULL, &tv);
//if(retval)
if(sock > 0)
{
/* ioctl isn't posix, but the following seems to work on all modern
* unixes */
int err= ioctl(sock, FIONREAD, &size);
if(err < 0 && errno != EAGAIN)
{
char szBuf[1024]="";
sprintf(szBuf,"In [%s::%s] ERROR PEEKING SOCKET DATA, err = %d errno = %d [%s]",__FILE__,__FUNCTION__,err,errno,strerror(errno));
throwException(szBuf);
}
else if(err == 0)
{
//if(Socket::enableDebugText) printf("In [%s] ioctl returned = %d, size = %ld\n",__FUNCTION__,err,size);
}
}
return static_cast<int>(size);
}
int Socket::send(const void *data, int dataSize) {
ssize_t bytesSent= ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0);
if(bytesSent<0 && errno != EAGAIN) {
throwException("error while receiving socket data");
ssize_t bytesSent= 0;
if(sock > 0)
{
bytesSent = ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0);
}
if(bytesSent < 0 && errno != EAGAIN)
{
char szBuf[1024]="";
sprintf(szBuf,"In [%s::%s] ERROR WRITING SOCKET DATA, err = %d errno = %d [%s]",__FILE__,__FUNCTION__,bytesSent,errno,strerror(errno));
throwException(szBuf);
}
else if(bytesSent < 0 && errno == EAGAIN)
{
printf("In [%s::%s] #1 EAGAIN during send, trying again...\n",__FILE__,__FUNCTION__);
time_t tStartTimer = time(NULL);
while((bytesSent < 0 && errno == EAGAIN) && (difftime(time(NULL),tStartTimer) <= 5))
{
if(Socket::isWritable(true) == true)
{
bytesSent = ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0);
printf("In [%s::%s] #2 EAGAIN during send, trying again returned: %d\n",__FILE__,__FUNCTION__,bytesSent);
}
}
}
if(bytesSent <= 0)
{
int iErr = errno;
disconnectSocket();
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while sending socket data, bytesSent = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,bytesSent,iErr,strerror(iErr));
printf("%s",szBuf);
//throwException(szBuf);
}
if(Socket::enableDebugText) printf("In [%s::%s] sock = %d, bytesSent = %d\n",__FILE__,__FUNCTION__,sock,bytesSent);
return static_cast<int>(bytesSent);
}
int Socket::receive(void *data, int dataSize) {
ssize_t bytesReceived= recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
if(bytesReceived<0 && errno != EAGAIN) {
throwException("error while receiving socket data");
int Socket::receive(void *data, int dataSize)
{
ssize_t bytesReceived = 0;
if(sock > 0)
{
bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
}
if(bytesReceived < 0 && errno != EAGAIN)
{
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] ERROR READING SOCKET DATA error while sending socket data, bytesSent = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,bytesReceived,errno,strerror(errno));
throwException(szBuf);
}
else if(bytesReceived < 0 && errno == EAGAIN)
{
printf("In [%s::%s] #1 EAGAIN during receive, trying again...\n",__FILE__,__FUNCTION__);
time_t tStartTimer = time(NULL);
while((bytesReceived < 0 && errno == EAGAIN) && (difftime(time(NULL),tStartTimer) <= 5))
{
if(Socket::isReadable() == true)
{
bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
printf("In [%s::%s] #2 EAGAIN during receive, trying again returned: %d\n",__FILE__,__FUNCTION__,bytesReceived);
}
}
}
if(bytesReceived <= 0)
{
int iErr = errno;
disconnectSocket();
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while receiving socket data, bytesReceived = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,bytesReceived,iErr,strerror(iErr));
printf("%s",szBuf);
//throwException(szBuf);
}
return static_cast<int>(bytesReceived);
}
int Socket::peek(void *data, int dataSize){
ssize_t err= recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
if(err<0 && errno != EAGAIN){
throwException("Can not receive data");
ssize_t err = 0;
if(sock > 0)
{
err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
}
if(err < 0 && errno != EAGAIN)
{
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] ERROR PEEKING SOCKET DATA error while sending socket data, bytesSent = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,err,errno,strerror(errno));
throwException(szBuf);
}
else if(err < 0 && errno == EAGAIN)
{
printf("In [%s::%s] #1 EAGAIN during peek, trying again...\n",__FILE__,__FUNCTION__);
time_t tStartTimer = time(NULL);
while((err < 0 && errno == EAGAIN) && (difftime(time(NULL),tStartTimer) <= 5))
{
if(Socket::isReadable() == true)
{
err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
printf("In [%s::%s] #2 EAGAIN during peek, trying again returned: %d\n",__FILE__,__FUNCTION__,err);
}
}
}
if(err <= 0)
{
int iErr = errno;
disconnectSocket();
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while peeking socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,err,iErr,strerror(iErr));
printf("%s",szBuf);
//throwException(szBuf);
}
return static_cast<int>(err);
@ -128,49 +386,114 @@ void Socket::setBlock(bool block){
}
}
bool Socket::isReadable(){
bool Socket::isReadable()
{
if(sock <= 0) return false;
struct timeval tv;
tv.tv_sec= 0;
tv.tv_usec= 10;
tv.tv_usec= 1;
fd_set set;
FD_ZERO(&set);
FD_SET(sock, &set);
int i= select(sock+1, &set, NULL, NULL, &tv);
if(i<0){
throwException("Error selecting socket");
if(i < 0)
{
//throwException("Error selecting socket");
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] error while selecting socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,i,errno,strerror(errno));
printf("%s",szBuf);
}
return i==1;
//return (i == 1 && FD_ISSET(sock, &set));
return (i == 1);
}
bool Socket::isWritable(){
bool Socket::isWritable(bool waitOnDelayedResponse)
{
if(sock <= 0) return false;
struct timeval tv;
tv.tv_sec= 0;
tv.tv_usec= 10;
tv.tv_usec= 1;
fd_set set;
FD_ZERO(&set);
FD_SET(sock, &set);
int i= select(sock+1, NULL, &set, NULL, &tv);
if(i<0){
throwException("Error selecting socket");
}
return i==1;
bool result = false;
do
{
int i = select(sock+1, NULL, &set, NULL, &tv);
if(i < 0 )
{
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] error while selecting socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,i,errno,strerror(errno));
printf("%s",szBuf);
waitOnDelayedResponse = false;
//throwException("Error selecting socket");
}
else if(i == 0)
{
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] TIMEOUT while selecting socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,i,errno,strerror(errno));
printf("%s",szBuf);
if(waitOnDelayedResponse == false)
{
result = true;
}
}
else
{
result = true;
}
} while(waitOnDelayedResponse == true && result == false);
//return (i == 1 && FD_ISSET(sock, &set));
return result;
}
bool Socket::isConnected(){
bool Socket::isConnected()
{
//if the socket is not writable then it is not conencted
if(!isWritable()){
if(isWritable(false) == false)
{
return false;
}
//if the socket is readable it is connected if we can read a byte from it
if(isReadable()){
if(isReadable())
{
char tmp;
return recv(sock, &tmp, sizeof(tmp), MSG_PEEK) > 0;
int err = peek(&tmp, sizeof(tmp));
return (err > 0);
/*
int err = recv(sock, &tmp, sizeof(tmp), MSG_PEEK);
if(err <= 0 && errno != EAGAIN)
{
int iErr = errno;
disconnectSocket();
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while peeking isconnected socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,err,iErr,strerror(iErr));
printf("%s",szBuf);
return false;
}
else if(err <= 0)
{
int iErr = errno;
//disconnectSocket();
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] #2 DISCONNECTED SOCKET error while peeking isconnected socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,err,iErr,strerror(iErr));
printf("%s",szBuf);
}
*/
}
//otherwise the socket is connected
@ -198,9 +521,9 @@ string Socket::getIp() const{
throw runtime_error("Error getting host ip");
}
return
intToStr(address[0]) + "." +
intToStr(address[1]) + "." +
return
intToStr(address[0]) + "." +
intToStr(address[1]) + "." +
intToStr(address[2]) + "." +
intToStr(address[3]);
}
@ -215,7 +538,8 @@ void Socket::throwException(const string &str){
// class ClientSocket
// ===============================================
void ClientSocket::connect(const Ip &ip, int port){
void ClientSocket::connect(const Ip &ip, int port)
{
sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
@ -224,20 +548,23 @@ void ClientSocket::connect(const Ip &ip, int port){
addr.sin_port= htons(port);
int err= ::connect(sock, reinterpret_cast<const sockaddr*>(&addr), sizeof(addr));
if(err < 0) {
if(err < 0)
{
char szBuf[1024]="";
sprintf(szBuf,"#2 Error connecting socket for IP: %s for Port: %d err = %d errno = %d [%s]",ip.getString().c_str(),port,err,errno,strerror(errno));
sprintf(szBuf,"In [%s::%s] #2 Error connecting socket for IP: %s for Port: %d err = %d errno = %d [%s]\n",__FILE__,__FUNCTION__,ip.getString().c_str(),port,err,errno,strerror(errno));
fprintf(stderr, "%s", szBuf);
if (errno == EINPROGRESS) {
if (errno == EINPROGRESS)
{
fd_set myset;
struct timeval tv;
int valopt;
socklen_t lon;
fprintf(stderr, "EINPROGRESS in connect() - selecting\n");
do {
fprintf(stderr, "In [%s::%s] EINPROGRESS in connect() - selecting\n",__FILE__,__FUNCTION__);
do
{
tv.tv_sec = 10;
tv.tv_usec = 0;
@ -246,41 +573,57 @@ void ClientSocket::connect(const Ip &ip, int port){
err = select(sock+1, NULL, &myset, NULL, &tv);
if (err < 0 && errno != EINTR) {
sprintf(szBuf, "Error connecting %d - %s\n", errno, strerror(errno));
throwException(szBuf);
if (err < 0 && errno != EINTR)
{
sprintf(szBuf, "In [%s::%s] Error connecting %d - [%s]\n",__FILE__,__FUNCTION__,errno, strerror(errno));
//throwException(szBuf);
fprintf(stderr, "%s", szBuf);
break;
}
else if (err > 0) {
else if (err > 0)
{
// Socket selected for write
lon = sizeof(int);
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0) {
sprintf(szBuf, "Error in getsockopt() %d - %s\n", errno, strerror(errno));
throwException(szBuf);
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0)
{
sprintf(szBuf, "In [%s::%s] Error in getsockopt() %d - [%s]\n",__FILE__,__FUNCTION__,errno, strerror(errno));
//throwException(szBuf);
fprintf(stderr, "%s", szBuf);
break;
}
// Check the value returned...
if (valopt) {
sprintf(szBuf, "Error in delayed connection() %d - %s\n", valopt, strerror(valopt));
throwException(szBuf);
if (valopt)
{
sprintf(szBuf, "In [%s::%s] Error in delayed connection() %d - [%s]\n",__FILE__,__FUNCTION__,valopt, strerror(valopt));
//throwException(szBuf);
fprintf(stderr, "%s", szBuf);
break;
}
errno = 0;
fprintf(stderr, "Apparent recovery for connection sock = %d, err = %d, errno = %d\n",sock,err,errno);
fprintf(stderr, "In [%s::%s] Apparent recovery for connection sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,errno);
break;
}
else {
sprintf(szBuf, "Timeout in select() - Cancelling!\n");
throwException(szBuf);
else
{
sprintf(szBuf, "In [%s::%s] Timeout in select() - Cancelling!\n",__FILE__,__FUNCTION__);
//throwException(szBuf);
fprintf(stderr, "%s", szBuf);
break;
}
} while (1);
}
if(err < 0)
{
throwException(szBuf);
fprintf(stderr, "In [%s::%s] Before END sock = %d, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,sock,err,errno,strerror(errno));
//throwException(szBuf);
}
else
{
fprintf(stderr, "In [%s::%s] Valid recovery for connection sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,errno);
}
fprintf(stderr, "Valid recovery for connection sock = %d, err = %d, errno = %d\n",sock,err,errno);
}
}
@ -288,7 +631,8 @@ void ClientSocket::connect(const Ip &ip, int port){
// class ServerSocket
// ===============================================
void ServerSocket::bind(int port){
void ServerSocket::bind(int port)
{
//sockaddr structure
sockaddr_in addr;
addr.sin_family= AF_INET;
@ -297,30 +641,45 @@ void ServerSocket::bind(int port){
int val = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
int err= ::bind(sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
if(err < 0) {
throwException("Error binding socket");
if(err < 0)
{
char szBuf[1024]="";
sprintf(szBuf, "In [%s::%s] Error binding socket sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,errno);
throwException(szBuf);
}
}
void ServerSocket::listen(int connectionQueueSize){
void ServerSocket::listen(int connectionQueueSize)
{
int err= ::listen(sock, connectionQueueSize);
if(err < 0) {
throwException("Error listening socket");
if(err < 0)
{
char szBuf[1024]="";
sprintf(szBuf, "In [%s::%s] Error listening socket sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,errno);
throwException(szBuf);
}
}
Socket *ServerSocket::accept(){
Socket *ServerSocket::accept()
{
int newSock= ::accept(sock, NULL, NULL);
if(newSock < 0) {
if(errno == EAGAIN)
return NULL;
if(newSock < 0)
{
char szBuf[1024]="";
if(Socket::enableDebugText) printf(szBuf, "In [%s::%s] Error accepting socket connection sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,newSock,errno);
if(errno == EAGAIN)
{
return NULL;
}
throwException(szBuf);
throwException("Error accepting socket connection");
}
return new Socket(newSock);
}
}}//end namespace

View File

@ -1,9 +1,9 @@
//This file is part of Glest Shared Library (www.glest.org)
//Copyright (C) 2005 Matthias Braun <matze@braunis.de>
//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
//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.
#include "platform_util.h"
@ -24,6 +24,10 @@
#include "window.h"
#include "noimpl.h"
#include "checksum.h"
#include "socket.h"
#include <algorithm>
using namespace Shared::Util;
using namespace std;
@ -38,7 +42,7 @@ int ScreenHeight;
}
// =====================================
// PerformanceTimer
// PerformanceTimer
// =====================================
void PerformanceTimer::init(float fps, int maxTimes){
@ -67,7 +71,7 @@ void PerformanceTimer::reset(){
}
// =====================================
// Chrono
// Chrono
// =====================================
Chrono::Chrono() {
@ -111,7 +115,7 @@ int64 Chrono::queryCounter(int multiplier) const {
}
// =====================================
// Misc
// Misc
// =====================================
//finds all filenames like path and stores them in resultys
@ -128,7 +132,7 @@ void findAll(const string &path, vector<string> &results, bool cutExtension) {
}
glob_t globbuf;
int res = glob(mypath.c_str(), 0, 0, &globbuf);
if(res < 0) {
std::stringstream msg;
@ -160,6 +164,217 @@ void findAll(const string &path, vector<string> &results, bool cutExtension) {
}
}
int isdir(const char *path)
{
struct stat stats;
return stat (path, &stats) == 0 && S_ISDIR (stats.st_mode);
}
bool EndsWith(const string &str, const string& key)
{
size_t keylen = key.length();
size_t strlen = str.length();
if(keylen <= strlen)
return string::npos != str.rfind(key.c_str(),strlen - keylen, keylen);
else
return false;
}
//finds all filenames like path and gets their checksum of all files combined
int32 getFolderTreeContentsCheckSumRecursively(const string &path, const string &filterFileExt, Checksum *recursiveChecksum) {
Checksum checksum = (recursiveChecksum == NULL ? Checksum() : *recursiveChecksum);
//if(Socket::enableDebugText) printf("In [%s::%s] scanning [%s]\n",__FILE__,__FUNCTION__,path.c_str());
std::string mypath = path;
/** Stupid win32 is searching for all files without extension when *. is
* specified as wildcard
*/
if(mypath.compare(mypath.size() - 2, 2, "*.") == 0) {
mypath = mypath.substr(0, mypath.size() - 2);
mypath += "*";
}
glob_t globbuf;
int res = glob(mypath.c_str(), 0, 0, &globbuf);
if(res < 0) {
std::stringstream msg;
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
throw runtime_error(msg.str());
}
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
const char* p = globbuf.gl_pathv[i];
/*
const char* begin = p;
for( ; *p != 0; ++p) {
// strip the path component
if(*p == '/')
begin = p+1;
}
*/
if(isdir(p) == 0)
{
bool addFile = true;
if(filterFileExt != "")
{
addFile = EndsWith(p, filterFileExt);
}
if(addFile)
{
//if(Socket::enableDebugText) printf("In [%s::%s] adding file [%s]\n",__FILE__,__FUNCTION__,p);
checksum.addFile(p);
}
}
}
globfree(&globbuf);
// Look recursively for sub-folders
res = glob(mypath.c_str(), GLOB_ONLYDIR, 0, &globbuf);
if(res < 0) {
std::stringstream msg;
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
throw runtime_error(msg.str());
}
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
const char* p = globbuf.gl_pathv[i];
/*
const char* begin = p;
for( ; *p != 0; ++p) {
// strip the path component
if(*p == '/')
begin = p+1;
}
*/
getFolderTreeContentsCheckSumRecursively(string(p) + "/*", filterFileExt, &checksum);
}
globfree(&globbuf);
return checksum.getSum();
}
//finds all filenames like path and gets the checksum of each file
vector<std::pair<string,int32> > getFolderTreeContentsCheckSumListRecursively(const string &path, const string &filterFileExt, vector<std::pair<string,int32> > *recursiveMap) {
vector<std::pair<string,int32> > checksumFiles = (recursiveMap == NULL ? vector<std::pair<string,int32> >() : *recursiveMap);
//if(Socket::enableDebugText) printf("In [%s::%s] scanning [%s]\n",__FILE__,__FUNCTION__,path.c_str());
std::string mypath = path;
/** Stupid win32 is searching for all files without extension when *. is
* specified as wildcard
*/
if(mypath.compare(mypath.size() - 2, 2, "*.") == 0) {
mypath = mypath.substr(0, mypath.size() - 2);
mypath += "*";
}
glob_t globbuf;
int res = glob(mypath.c_str(), 0, 0, &globbuf);
if(res < 0) {
std::stringstream msg;
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
throw runtime_error(msg.str());
}
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
const char* p = globbuf.gl_pathv[i];
/*
const char* begin = p;
for( ; *p != 0; ++p) {
// strip the path component
if(*p == '/')
begin = p+1;
}
*/
if(isdir(p) == 0)
{
bool addFile = true;
if(filterFileExt != "")
{
addFile = EndsWith(p, filterFileExt);
}
if(addFile)
{
//if(Socket::enableDebugText) printf("In [%s::%s] adding file [%s]\n",__FILE__,__FUNCTION__,p);
Checksum checksum;
checksum.addFile(p);
checksumFiles.push_back(std::pair<string,int32>(p,checksum.getSum()));
}
}
}
globfree(&globbuf);
// Look recursively for sub-folders
res = glob(mypath.c_str(), GLOB_ONLYDIR, 0, &globbuf);
if(res < 0) {
std::stringstream msg;
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
throw runtime_error(msg.str());
}
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
const char* p = globbuf.gl_pathv[i];
/*
const char* begin = p;
for( ; *p != 0; ++p) {
// strip the path component
if(*p == '/')
begin = p+1;
}
*/
checksumFiles = getFolderTreeContentsCheckSumListRecursively(string(p) + "/*", filterFileExt, &checksumFiles);
}
globfree(&globbuf);
return checksumFiles;
}
string extractDirectoryPathFromFile(string filename)
{
return filename.substr( 0, filename.rfind("/")+1 );
}
void createDirectoryPaths(string Path)
{
char DirName[256]="";
const char *path = Path.c_str();
char *dirName = DirName;
while(*path)
{
//if (('\\' == *path) || ('/' == *path))
if ('/' == *path)
{
//if (':' != *(path-1))
{
mkdir(DirName, S_IRWXO);
}
}
*dirName++ = *path++;
*dirName = '\0';
}
mkdir(DirName, S_IRWXO);
}
bool changeVideoMode(int resW, int resH, int colorBits, int ) {
Private::shouldBeFullscreen = true;
return true;

View File

@ -1,265 +1,480 @@
// ==============================================================
// This file is part of Glest Shared Library (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
// ==============================================================
#include "platform_util.h"
#include <io.h>
#include <DbgHelp.h>
#include <cassert>
#include "util.h"
#include "conversion.h"
#include "leak_dumper.h"
using namespace Shared::Util;
using namespace std;
namespace Shared{ namespace Platform{
// =====================================================
// class PerformanceTimer
// =====================================================
void PerformanceTimer::init(int fps, int maxTimes){
int64 freq;
if(QueryPerformanceFrequency((LARGE_INTEGER*) &freq)==0){
throw runtime_error("Performance counters not supported");
}
times= 0;
this->maxTimes= maxTimes;
QueryPerformanceCounter((LARGE_INTEGER*) &lastTicks);
updateTicks= freq/fps;
}
bool PerformanceTimer::isTime(){
QueryPerformanceCounter((LARGE_INTEGER*) &thisTicks);
if((thisTicks-lastTicks)>=updateTicks && times<maxTimes){
lastTicks+= updateTicks;
times++;
return true;
}
times= 0;
return false;
}
void PerformanceTimer::reset(){
QueryPerformanceCounter((LARGE_INTEGER*) &thisTicks);
lastTicks= thisTicks;
}
// =====================================================
// class Chrono
// =====================================================
Chrono::Chrono(){
if(!QueryPerformanceFrequency((LARGE_INTEGER*) &freq)){
throw runtime_error("Performance counters not supported");
}
stopped= true;
accumCount= 0;
}
void Chrono::start(){
stopped= false;
QueryPerformanceCounter((LARGE_INTEGER*) &startCount);
}
void Chrono::stop(){
int64 endCount;
QueryPerformanceCounter((LARGE_INTEGER*) &endCount);
accumCount+= endCount-startCount;
stopped= true;
}
int64 Chrono::getMicros() const{
return queryCounter(1000000);
}
int64 Chrono::getMillis() const{
return queryCounter(1000);
}
int64 Chrono::getSeconds() const{
return queryCounter(1);
}
int64 Chrono::queryCounter(int multiplier) const{
if(stopped){
return multiplier*accumCount/freq;
}
else{
int64 endCount;
QueryPerformanceCounter((LARGE_INTEGER*) &endCount);
return multiplier*(accumCount+endCount-startCount)/freq;
}
}
// =====================================================
// class PlatformExceptionHandler
// =====================================================
PlatformExceptionHandler *PlatformExceptionHandler::thisPointer= NULL;
LONG WINAPI PlatformExceptionHandler::handler(LPEXCEPTION_POINTERS pointers){
HANDLE hFile = CreateFile(
thisPointer->dumpFileName.c_str(),
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
0);
MINIDUMP_EXCEPTION_INFORMATION lExceptionInformation;
lExceptionInformation.ThreadId= GetCurrentThreadId();
lExceptionInformation.ExceptionPointers= pointers;
lExceptionInformation.ClientPointers= false;
MiniDumpWriteDump(
GetCurrentProcess(),
GetCurrentProcessId(),
hFile,
MiniDumpNormal,
&lExceptionInformation,
NULL,
NULL );
thisPointer->handle();
return EXCEPTION_EXECUTE_HANDLER;
}
void PlatformExceptionHandler::install(string dumpFileName){
thisPointer= this;
this->dumpFileName= dumpFileName;
SetUnhandledExceptionFilter(handler);
}
// =====================================================
// class Misc
// =====================================================
//finds all filenames like path and stores them in resultys
void findAll(const string &path, vector<string> &results, bool cutExtension){
int i= 0;
struct _finddata_t fi;
intptr_t handle;
char *cstr;
results.clear();
cstr= new char[path.length()+1];
strcpy(cstr, path.c_str());
if((handle=_findfirst(cstr,&fi))!=-1){
do{
if(!(strcmp(".", fi.name)==0 || strcmp("..", fi.name)==0)){
i++;
results.push_back(fi.name);
}
}
while(_findnext(handle, &fi)==0);
}
else{
throw runtime_error("Error opening files: "+ path);
}
if(i==0){
throw runtime_error("No files found: "+ path);
}
if(cutExtension){
for (int i=0; i<results.size(); ++i){
results.at(i)=cutLastExt(results.at(i));
}
}
delete [] cstr;
}
bool changeVideoMode(int resW, int resH, int colorBits, int refreshFrequency){
DEVMODE devMode;
for (int i=0; EnumDisplaySettings(NULL, i, &devMode) ;i++){
if (devMode.dmPelsWidth== resW &&
devMode.dmPelsHeight== resH &&
devMode.dmBitsPerPel== colorBits){
devMode.dmDisplayFrequency=refreshFrequency;
LONG result= ChangeDisplaySettings(&devMode, 0);
if(result == DISP_CHANGE_SUCCESSFUL){
return true;
}
else{
return false;
}
}
}
return false;
}
void restoreVideoMode(){
int dispChangeErr= ChangeDisplaySettings(NULL, 0);
assert(dispChangeErr==DISP_CHANGE_SUCCESSFUL);
}
void message(string message){
MessageBox(NULL, message.c_str(), "Message", MB_OK);
}
bool ask(string message){
return MessageBox(NULL, message.c_str(), "Confirmation", MB_YESNO)==IDYES;
}
void exceptionMessage(const exception &excp){
string message, title;
showCursor(true);
message+= "ERROR(S):\n\n";
message+= excp.what();
title= "Error: Unhandled Exception";
MessageBox(NULL, message.c_str(), title.c_str(), MB_ICONSTOP | MB_OK | MB_TASKMODAL);
}
int getScreenW(){
return GetSystemMetrics(SM_CXSCREEN);
}
int getScreenH(){
return GetSystemMetrics(SM_CYSCREEN);
}
void sleep(int millis){
Sleep(millis);
}
void showCursor(bool b){
ShowCursor(b);
}
bool isKeyDown(int virtualKey){
return (GetKeyState(virtualKey) & 0x8000) != 0;
}
}}//end namespace
// ==============================================================
// This file is part of Glest Shared Library (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
// ==============================================================
#include "platform_util.h"
#include <io.h>
#include <DbgHelp.h>
#include <cassert>
#include "util.h"
#include "conversion.h"
#include "leak_dumper.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <direct.h>
#define S_ISDIR(mode) ((mode) & _S_IFDIR)
using namespace Shared::Util;
using namespace std;
namespace Shared{ namespace Platform{
// =====================================================
// class PerformanceTimer
// =====================================================
void PerformanceTimer::init(int fps, int maxTimes){
int64 freq;
if(QueryPerformanceFrequency((LARGE_INTEGER*) &freq)==0){
throw runtime_error("Performance counters not supported");
}
times= 0;
this->maxTimes= maxTimes;
QueryPerformanceCounter((LARGE_INTEGER*) &lastTicks);
updateTicks= freq/fps;
}
bool PerformanceTimer::isTime(){
QueryPerformanceCounter((LARGE_INTEGER*) &thisTicks);
if((thisTicks-lastTicks)>=updateTicks && times<maxTimes){
lastTicks+= updateTicks;
times++;
return true;
}
times= 0;
return false;
}
void PerformanceTimer::reset(){
QueryPerformanceCounter((LARGE_INTEGER*) &thisTicks);
lastTicks= thisTicks;
}
// =====================================================
// class Chrono
// =====================================================
Chrono::Chrono(){
if(!QueryPerformanceFrequency((LARGE_INTEGER*) &freq)){
throw runtime_error("Performance counters not supported");
}
stopped= true;
accumCount= 0;
}
void Chrono::start(){
stopped= false;
QueryPerformanceCounter((LARGE_INTEGER*) &startCount);
}
void Chrono::stop(){
int64 endCount;
QueryPerformanceCounter((LARGE_INTEGER*) &endCount);
accumCount+= endCount-startCount;
stopped= true;
}
int64 Chrono::getMicros() const{
return queryCounter(1000000);
}
int64 Chrono::getMillis() const{
return queryCounter(1000);
}
int64 Chrono::getSeconds() const{
return queryCounter(1);
}
int64 Chrono::queryCounter(int multiplier) const{
if(stopped){
return multiplier*accumCount/freq;
}
else{
int64 endCount;
QueryPerformanceCounter((LARGE_INTEGER*) &endCount);
return multiplier*(accumCount+endCount-startCount)/freq;
}
}
// =====================================================
// class PlatformExceptionHandler
// =====================================================
PlatformExceptionHandler *PlatformExceptionHandler::thisPointer= NULL;
LONG WINAPI PlatformExceptionHandler::handler(LPEXCEPTION_POINTERS pointers){
HANDLE hFile = CreateFile(
thisPointer->dumpFileName.c_str(),
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
0);
MINIDUMP_EXCEPTION_INFORMATION lExceptionInformation;
lExceptionInformation.ThreadId= GetCurrentThreadId();
lExceptionInformation.ExceptionPointers= pointers;
lExceptionInformation.ClientPointers= false;
MiniDumpWriteDump(
GetCurrentProcess(),
GetCurrentProcessId(),
hFile,
MiniDumpNormal,
&lExceptionInformation,
NULL,
NULL );
thisPointer->handle();
return EXCEPTION_EXECUTE_HANDLER;
}
void PlatformExceptionHandler::install(string dumpFileName){
thisPointer= this;
this->dumpFileName= dumpFileName;
SetUnhandledExceptionFilter(handler);
}
// =====================================================
// class Misc
// =====================================================
//finds all filenames like path and stores them in resultys
void findAll(const string &path, vector<string> &results, bool cutExtension){
int i= 0;
struct _finddata_t fi;
intptr_t handle;
char *cstr;
results.clear();
cstr= new char[path.length()+1];
strcpy(cstr, path.c_str());
if((handle=_findfirst(cstr,&fi))!=-1){
do{
if(!(strcmp(".", fi.name)==0 || strcmp("..", fi.name)==0)){
i++;
results.push_back(fi.name);
}
}
while(_findnext(handle, &fi)==0);
}
else{
throw runtime_error("Error opening files: "+ path);
}
if(i==0){
throw runtime_error("No files found: "+ path);
}
if(cutExtension){
for (int i=0; i<results.size(); ++i){
results.at(i)=cutLastExt(results.at(i));
}
}
delete [] cstr;
}
int isdir(const char *path)
{
struct stat stats;
return stat (path, &stats) == 0 && S_ISDIR (stats.st_mode);
}
bool EndsWith(const string &str, const string& key)
{
size_t keylen = key.length();
size_t strlen = str.length();
if(keylen <= strlen)
return string::npos != str.rfind(key.c_str(),strlen - keylen, keylen);
else
return false;
}
//finds all filenames like path and gets their checksum of all files combined
int32 getFolderTreeContentsCheckSumRecursively(const string &path, const string &filterFileExt, Checksum *recursiveChecksum) {
Checksum checksum = (recursiveChecksum == NULL ? Checksum() : *recursiveChecksum);
/* MV - PORT THIS to win32
//if(Socket::enableDebugText) printf("In [%s::%s] scanning [%s]\n",__FILE__,__FUNCTION__,path.c_str());
std::string mypath = path;
// Stupid win32 is searching for all files without extension when *. is specified as wildcard
if(mypath.compare(mypath.size() - 2, 2, "*.") == 0) {
mypath = mypath.substr(0, mypath.size() - 2);
mypath += "*";
}
glob_t globbuf;
int res = glob(mypath.c_str(), 0, 0, &globbuf);
if(res < 0) {
std::stringstream msg;
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
throw runtime_error(msg.str());
}
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
const char* p = globbuf.gl_pathv[i];
//
//const char* begin = p;
//for( ; *p != 0; ++p) {
// // strip the path component
// if(*p == '/')
// begin = p+1;
//}
if(isdir(p) == 0)
{
bool addFile = true;
if(filterFileExt != "")
{
addFile = EndsWith(p, filterFileExt);
}
if(addFile)
{
//if(Socket::enableDebugText) printf("In [%s::%s] adding file [%s]\n",__FILE__,__FUNCTION__,p);
checksum.addFile(p);
}
}
}
globfree(&globbuf);
// Look recursively for sub-folders
res = glob(mypath.c_str(), GLOB_ONLYDIR, 0, &globbuf);
if(res < 0) {
std::stringstream msg;
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
throw runtime_error(msg.str());
}
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
const char* p = globbuf.gl_pathv[i];
//
//const char* begin = p;
//for( ; *p != 0; ++p) {
// strip the path component
// if(*p == '/')
// begin = p+1;
//}
getFolderTreeContentsCheckSumRecursively(string(p) + "/*", filterFileExt, &checksum);
}
globfree(&globbuf);
*/
return checksum.getSum();
}
//finds all filenames like path and gets the checksum of each file
vector<std::pair<string,int32> > getFolderTreeContentsCheckSumListRecursively(const string &path, const string &filterFileExt, vector<std::pair<string,int32> > *recursiveMap) {
vector<std::pair<string,int32> > checksumFiles = (recursiveMap == NULL ? vector<std::pair<string,int32> >() : *recursiveMap);
/* MV - PORT THIS to win32
//if(Socket::enableDebugText) printf("In [%s::%s] scanning [%s]\n",__FILE__,__FUNCTION__,path.c_str());
std::string mypath = path;
// Stupid win32 is searching for all files without extension when *. is specified as wildcard
if(mypath.compare(mypath.size() - 2, 2, "*.") == 0) {
mypath = mypath.substr(0, mypath.size() - 2);
mypath += "*";
}
glob_t globbuf;
int res = glob(mypath.c_str(), 0, 0, &globbuf);
if(res < 0) {
std::stringstream msg;
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
throw runtime_error(msg.str());
}
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
const char* p = globbuf.gl_pathv[i];
//
//const char* begin = p;
//for( ; *p != 0; ++p) {
// strip the path component
// if(*p == '/')
// begin = p+1;
//}
if(isdir(p) == 0)
{
bool addFile = true;
if(filterFileExt != "")
{
addFile = EndsWith(p, filterFileExt);
}
if(addFile)
{
//if(Socket::enableDebugText) printf("In [%s::%s] adding file [%s]\n",__FILE__,__FUNCTION__,p);
Checksum checksum;
checksum.addFile(p);
checksumFiles.push_back(std::pair<string,int32>(p,checksum.getSum()));
}
}
}
globfree(&globbuf);
// Look recursively for sub-folders
res = glob(mypath.c_str(), GLOB_ONLYDIR, 0, &globbuf);
if(res < 0) {
std::stringstream msg;
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
throw runtime_error(msg.str());
}
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
const char* p = globbuf.gl_pathv[i];
//
//const char* begin = p;
//for( ; *p != 0; ++p) {
// strip the path component
// if(*p == '/')
// begin = p+1;
//}
checksumFiles = getFolderTreeContentsCheckSumListRecursively(string(p) + "/*", filterFileExt, &checksumFiles);
}
globfree(&globbuf);
*/
return checksumFiles;
}
string extractDirectoryPathFromFile(string filename)
{
return filename.substr( 0, filename.rfind("/")+1 );
}
void createDirectoryPaths(string Path)
{
char DirName[256]="";
const char *path = Path.c_str();
char *dirName = DirName;
while(*path)
{
//if (('\\' == *path) || ('/' == *path))
if ('/' == *path)
{
//if (':' != *(path-1))
{
_mkdir(DirName);
}
}
*dirName++ = *path++;
*dirName = '\0';
}
_mkdir(DirName);
}
bool changeVideoMode(int resW, int resH, int colorBits, int refreshFrequency){
DEVMODE devMode;
for (int i=0; EnumDisplaySettings(NULL, i, &devMode) ;i++){
if (devMode.dmPelsWidth== resW &&
devMode.dmPelsHeight== resH &&
devMode.dmBitsPerPel== colorBits){
devMode.dmDisplayFrequency=refreshFrequency;
LONG result= ChangeDisplaySettings(&devMode, 0);
if(result == DISP_CHANGE_SUCCESSFUL){
return true;
}
else{
return false;
}
}
}
return false;
}
void restoreVideoMode(){
int dispChangeErr= ChangeDisplaySettings(NULL, 0);
assert(dispChangeErr==DISP_CHANGE_SUCCESSFUL);
}
void message(string message){
MessageBox(NULL, message.c_str(), "Message", MB_OK);
}
bool ask(string message){
return MessageBox(NULL, message.c_str(), "Confirmation", MB_YESNO)==IDYES;
}
void exceptionMessage(const exception &excp){
string message, title;
showCursor(true);
message+= "ERROR(S):\n\n";
message+= excp.what();
title= "Error: Unhandled Exception";
MessageBox(NULL, message.c_str(), title.c_str(), MB_ICONSTOP | MB_OK | MB_TASKMODAL);
}
int getScreenW(){
return GetSystemMetrics(SM_CXSCREEN);
}
int getScreenH(){
return GetSystemMetrics(SM_CYSCREEN);
}
void sleep(int millis){
Sleep(millis);
}
void showCursor(bool b){
ShowCursor(b);
}
bool isKeyDown(int virtualKey){
return (GetKeyState(virtualKey) & 0x8000) != 0;
}
}}//end namespace

View File

@ -3,9 +3,9 @@
//
// Copyright (C) 2001-2007 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
// 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
// ==============================================================
@ -16,12 +16,17 @@
#include "conversion.h"
#include "leak_dumper.h"
#include <time.h>
#define socklen_t int
using namespace std;
using namespace Shared::Util;
namespace Shared{ namespace Platform{
bool Socket::enableDebugText = false;
// =====================================================
// class Ip
// =====================================================
@ -42,7 +47,7 @@ Ip::Ip(unsigned char byte0, unsigned char byte1, unsigned char byte2, unsigned c
Ip::Ip(const string& ipString){
int offset= 0;
int offset= 0;
int byteIndex= 0;
for(byteIndex= 0; byteIndex<4; ++byteIndex){
@ -64,7 +69,7 @@ string Ip::getString() const{
Socket::SocketManager Socket::socketManager;
Socket::SocketManager::SocketManager(){
WSADATA wsaData;
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2, 0);
WSAStartup(wVersionRequested, &wsaData);
//dont throw exceptions here, this is a static initializacion
@ -85,59 +90,300 @@ Socket::Socket(){
}
}
Socket::~Socket(){
int err= closesocket(sock);
if(err==INVALID_SOCKET){
throwException("Error closing socket");
}
Socket::~Socket()
{
if(Socket::enableDebugText) printf("In [%s::%s] START closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
disconnectSocket();
if(Socket::enableDebugText) printf("In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
}
void Socket::disconnectSocket()
{
if(Socket::enableDebugText) printf("In [%s::%s] START closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
if(sock > 0)
{
::shutdown(sock,2);
::closesocket(sock);
sock = -1;
}
if(Socket::enableDebugText) printf("In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
}
// Int lookup is socket fd while bool result is whether or not that socket was signalled for reading
bool Socket::hasDataToRead(std::map<int,bool> &socketTriggeredList)
{
bool bResult = false;
if(socketTriggeredList.size() > 0)
{
/* Watch stdin (fd 0) to see when it has input. */
fd_set rfds;
FD_ZERO(&rfds);
int imaxsocket = 0;
for(std::map<int,bool>::iterator itermap = socketTriggeredList.begin();
itermap != socketTriggeredList.end(); itermap++)
{
int socket = itermap->first;
if(socket > 0)
{
FD_SET(socket, &rfds);
imaxsocket = max(socket,imaxsocket);
}
}
if(imaxsocket > 0)
{
/* Wait up to 0 seconds. */
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
int retval = select(imaxsocket + 1, &rfds, NULL, NULL, &tv);
if(retval < 0)
{
char szBuf[1024]="";
sprintf(szBuf,"In [%s::%s] ERROR SELECTING SOCKET DATA retval = %d WSAGetLastError() = %d",__FILE__,__FUNCTION__,retval,WSAGetLastError());
fprintf(stderr, "%s", szBuf);
}
else if(retval)
{
bResult = true;
if(Socket::enableDebugText) printf("In [%s::%s] select detected data imaxsocket = %d...\n",__FILE__,__FUNCTION__,imaxsocket);
for(std::map<int,bool>::iterator itermap = socketTriggeredList.begin();
itermap != socketTriggeredList.end(); itermap++)
{
int socket = itermap->first;
if (FD_ISSET(socket, &rfds))
{
if(Socket::enableDebugText) printf("In [%s] FD_ISSET true for socket %d...\n",__FUNCTION__,socket);
itermap->second = true;
}
else
{
itermap->second = false;
}
}
if(Socket::enableDebugText) printf("In [%s::%s] socketTriggeredList->size() = %d\n",__FILE__,__FUNCTION__,socketTriggeredList.size());
}
}
}
return bResult;
}
bool Socket::hasDataToRead()
{
return Socket::hasDataToRead(sock) ;
}
bool Socket::hasDataToRead(int socket)
{
bool bResult = false;
if(socket > 0)
{
fd_set rfds;
struct timeval tv;
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(socket, &rfds);
/* Wait up to 0 seconds. */
tv.tv_sec = 0;
tv.tv_usec = 0;
int retval = select(socket + 1, &rfds, NULL, NULL, &tv);
if(retval)
{
if (FD_ISSET(socket, &rfds))
{
bResult = true;
}
}
}
return bResult;
}
int Socket::getDataToRead(){
u_long size;
int err= ioctlsocket(sock, FIONREAD, &size);
unsigned long size = 0;
if(err==SOCKET_ERROR){
if(WSAGetLastError()!=WSAEWOULDBLOCK){
throwException("Can not get data to read");
}
}
//fd_set rfds;
//struct timeval tv;
//int retval;
/* Watch stdin (fd 0) to see when it has input. */
//FD_ZERO(&rfds);
//FD_SET(sock, &rfds);
/* Wait up to 0 seconds. */
//tv.tv_sec = 0;
//tv.tv_usec = 0;
//retval = select(sock + 1, &rfds, NULL, NULL, &tv);
//if(retval)
if(sock > 0)
{
/* ioctl isn't posix, but the following seems to work on all modern
* unixes */
int err= ioctlsocket(sock, FIONREAD, &size);
if(err < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
{
char szBuf[1024]="";
sprintf(szBuf,"In [%s::%s] ERROR PEEKING SOCKET DATA, err = %d WSAGetLastError() = %d",__FILE__,__FUNCTION__,err,WSAGetLastError());
throwException(szBuf);
}
else if(err == 0)
{
//if(Socket::enableDebugText) printf("In [%s] ioctl returned = %d, size = %ld\n",__FUNCTION__,err,size);
}
}
return static_cast<int>(size);
}
int Socket::send(const void *data, int dataSize){
int err= ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0);
if(err==SOCKET_ERROR){
if(WSAGetLastError()!=WSAEWOULDBLOCK){
throwException("Can not send data");
}
int Socket::send(const void *data, int dataSize) {
int bytesSent= 0;
if(sock > 0)
{
bytesSent = ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0);
}
return err;
if(bytesSent < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
{
char szBuf[1024]="";
sprintf(szBuf,"In [%s::%s] ERROR WRITING SOCKET DATA, err = %d WSAGetLastError() = %d",__FILE__,__FUNCTION__,bytesSent,WSAGetLastError());
throwException(szBuf);
}
else if(bytesSent < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
{
printf("In [%s::%s] #1 WSAEWOULDBLOCK during send, trying again...\n",__FILE__,__FUNCTION__);
time_t tStartTimer = time(NULL);
while((bytesSent < 0 && WSAGetLastError() == WSAEWOULDBLOCK) && (difftime(time(NULL),tStartTimer) <= 5))
{
if(Socket::isWritable(true) == true)
{
bytesSent = ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0);
printf("In [%s::%s] #2 WSAEWOULDBLOCK during send, trying again returned: %d\n",__FILE__,__FUNCTION__,bytesSent);
}
}
}
if(bytesSent <= 0)
{
int iErr = WSAGetLastError();
disconnectSocket();
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while sending socket data, bytesSent = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,bytesSent,iErr);
printf("%s",szBuf);
//throwException(szBuf);
}
if(Socket::enableDebugText) printf("In [%s::%s] sock = %d, bytesSent = %d\n",__FILE__,__FUNCTION__,sock,bytesSent);
return static_cast<int>(bytesSent);
}
int Socket::receive(void *data, int dataSize){
int err= recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
int Socket::receive(void *data, int dataSize)
{
int bytesReceived = 0;
if(err==SOCKET_ERROR){
if(WSAGetLastError()!=WSAEWOULDBLOCK){
throwException("Can not receive data");
}
if(sock > 0)
{
bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
}
if(bytesReceived < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
{
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] ERROR READING SOCKET DATA error while sending socket data, bytesSent = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,bytesReceived,WSAGetLastError());
throwException(szBuf);
}
else if(bytesReceived < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
{
printf("In [%s::%s] #1 WSAEWOULDBLOCK during receive, trying again...\n",__FILE__,__FUNCTION__);
time_t tStartTimer = time(NULL);
while((bytesReceived < 0 && WSAGetLastError() == WSAEWOULDBLOCK) && (difftime(time(NULL),tStartTimer) <= 5))
{
if(Socket::isReadable() == true)
{
bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
printf("In [%s::%s] #2 WSAEWOULDBLOCK during receive, trying again returned: %d\n",__FILE__,__FUNCTION__,bytesReceived);
}
}
}
return err;
if(bytesReceived <= 0)
{
int iErr = WSAGetLastError();
disconnectSocket();
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while receiving socket data, bytesReceived = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,bytesReceived,iErr);
printf("%s",szBuf);
//throwException(szBuf);
}
return static_cast<int>(bytesReceived);
}
int Socket::peek(void *data, int dataSize){
int err= recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
int err = 0;
if(sock > 0)
{
err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
}
if(err < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
{
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] ERROR PEEKING SOCKET DATA error while sending socket data, bytesSent = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,err,WSAGetLastError());
if(err==SOCKET_ERROR){
if(WSAGetLastError()!=WSAEWOULDBLOCK){
throwException("Can not receive data");
}
throwException(szBuf);
}
else if(err < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
{
printf("In [%s::%s] #1 WSAEWOULDBLOCK during peek, trying again...\n",__FILE__,__FUNCTION__);
time_t tStartTimer = time(NULL);
while((err < 0 && WSAGetLastError() == WSAEWOULDBLOCK) && (difftime(time(NULL),tStartTimer) <= 5))
{
if(Socket::isReadable() == true)
{
err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
printf("In [%s::%s] #2 WSAEWOULDBLOCK during peek, trying again returned: %d\n",__FILE__,__FUNCTION__,err);
}
}
}
return err;
if(err <= 0)
{
int iErr = WSAGetLastError();
disconnectSocket();
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while peeking socket data, err = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,err,iErr);
printf("%s",szBuf);
//throwException(szBuf);
}
return static_cast<int>(err);
}
void Socket::setBlock(bool block){
@ -149,49 +395,101 @@ void Socket::setBlock(bool block){
}
}
bool Socket::isReadable(){
bool Socket::isReadable()
{
if(sock <= 0) return false;
TIMEVAL tv;
tv.tv_sec= 0;
tv.tv_usec= 10;
tv.tv_usec= 1;
fd_set set;
FD_ZERO(&set);
FD_SET(sock, &set);
int i= select(0, &set, NULL, NULL, &tv);
if(i==SOCKET_ERROR){
throwException("Error selecting socket");
}
return i==1;
int i= select(sock+1, &set, NULL, NULL, &tv);
if(i==SOCKET_ERROR)
{
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] error while selecting socket data, err = %d, errno = %d\n",__FILE__,__FUNCTION__,i,WSAGetLastError());
printf("%s",szBuf);
}
//return (i == 1 && FD_ISSET(sock, &set));
return (i == 1);
}
bool Socket::isWritable(){
bool Socket::isWritable(bool waitOnDelayedResponse)
{
if(sock <= 0) return false;
TIMEVAL tv;
tv.tv_sec= 0;
tv.tv_usec= 10;
tv.tv_usec= 1;
fd_set set;
FD_ZERO(&set);
FD_SET(sock, &set);
int i= select(0, NULL, &set, NULL, &tv);
if(i==SOCKET_ERROR){
throwException("Error selecting socket");
}
return i==1;
bool result = false;
do
{
int i= select(sock+1, NULL, &set, NULL, &tv);
if(i==SOCKET_ERROR)
{
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] error while selecting socket data, err = %d, errno = %d\n",__FILE__,__FUNCTION__,i,WSAGetLastError());
printf("%s",szBuf);
waitOnDelayedResponse = false;
}
else if(i == 0)
{
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] TIMEOUT while selecting socket data, err = %d, errno = %d\n",__FILE__,__FUNCTION__,i,WSAGetLastError());
printf("%s",szBuf);
if(waitOnDelayedResponse == false)
{
result = true;
}
}
else
{
result = true;
}
} while(waitOnDelayedResponse == true && result == false);
return result;
}
bool Socket::isConnected(){
//if the socket is not writable then it is not conencted
if(!isWritable()){
if(isWritable(false) == false)
{
return false;
}
//if the socket is readable it is connected if we can read a byte from it
if(isReadable()){
char tmp;
return recv(sock, &tmp, sizeof(tmp), MSG_PEEK) > 0;
if(isReadable())
{
char tmp;
int err = peek(&tmp, sizeof(tmp));
return (err > 0);
/*
int err = recv(sock, &tmp, sizeof(tmp), MSG_PEEK);
if(err <= 0 && WSAGetLastError() != WSAEWOULDBLOCK)
{
int iErr = WSAGetLastError();
disconnectSocket();
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while peeking isconnected socket data, err = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,err,iErr);
printf("%s",szBuf);
return false;
}
*/
}
//otherwise the socket is connected
@ -220,9 +518,9 @@ string Socket::getIp() const{
throwException("Error getting host ip");
}
return
intToStr(address[0]) + "." +
intToStr(address[1]) + "." +
return
intToStr(address[0]) + "." +
intToStr(address[1]) + "." +
intToStr(address[2]) + "." +
intToStr(address[3]);
}
@ -235,20 +533,86 @@ void Socket::throwException(const string &str){
// class ClientSocket
// =====================================================
void ClientSocket::connect(const Ip &ip, int port){
void ClientSocket::connect(const Ip &ip, int port)
{
sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family= AF_INET;
addr.sin_addr.s_addr= inet_addr(ip.getString().c_str());
addr.sin_port= htons(port);
int err= ::connect(sock, reinterpret_cast<const sockaddr*>(&addr), sizeof(addr));
if(err==SOCKET_ERROR){
int lastError= WSAGetLastError();
if(err < 0)
{
char szBuf[1024]="";
sprintf(szBuf,"#2 Error connecting socket for IP: %s for Port: %d err = %d WSAGetLastError() = %d",ip.getString().c_str(),port,err,WSAGetLastError());
fprintf(stderr, "%s", szBuf);
if(lastError!=WSAEWOULDBLOCK && lastError!=WSAEALREADY){
throwException("Can not connect");
}
if (WSAGetLastError() == WSAEINPROGRESS) {
fd_set myset;
struct timeval tv;
int valopt;
socklen_t lon;
fprintf(stderr, "EINPROGRESS in connect() - selecting\n");
do {
tv.tv_sec = 10;
tv.tv_usec = 0;
FD_ZERO(&myset);
FD_SET(sock, &myset);
err = select(sock+1, NULL, &myset, NULL, &tv);
if (err < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
{
sprintf(szBuf, "Error connecting %d\n", WSAGetLastError());
//throwException(szBuf);
fprintf(stderr, "%s", szBuf);
break;
}
else if (err > 0) {
// Socket selected for write
lon = sizeof(int);
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)(&valopt), &lon) < 0)
{
sprintf(szBuf, "Error in getsockopt() %d\n", WSAGetLastError());
//throwException(szBuf);
fprintf(stderr, "%s", szBuf);
break;
}
// Check the value returned...
if (valopt)
{
sprintf(szBuf, "Error in delayed connection() %d\n", valopt);
//throwException(szBuf);
fprintf(stderr, "%s", szBuf);
break;
}
fprintf(stderr, "Apparent recovery for connection sock = %d, err = %d, WSAGetLastError() = %d\n",sock,err,WSAGetLastError());
break;
}
else
{
sprintf(szBuf, "Timeout in select() - Cancelling!\n");
//throwException(szBuf);
fprintf(stderr, "%s", szBuf);
break;
}
} while (1);
}
if(err < 0)
{
fprintf(stderr, "In [%s::%s] Before END sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,WSAGetLastError());
//throwException(szBuf);
}
fprintf(stderr, "Valid recovery for connection sock = %d, err = %d, WSAGetLastError() = %d\n",sock,err,WSAGetLastError());
}
}
@ -262,7 +626,7 @@ void ServerSocket::bind(int port){
addr.sin_family= AF_INET;
addr.sin_addr.s_addr= INADDR_ANY;
addr.sin_port= htons(port);
int err= ::bind(sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
if(err==SOCKET_ERROR){
throwException("Error binding socket");

View File

@ -3,9 +3,9 @@
//
// 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
// 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
// ==============================================================
@ -27,14 +27,14 @@ namespace Shared{ namespace Util{
Checksum::Checksum(){
sum= 0;
r= 55665;
c1= 52845;
r= 55665;
c1= 52845;
c2= 22719;
}
void Checksum::addByte(int8 value){
int32 cipher= (value ^ (r >> 8));
r= (cipher + r) * c1 + c2;
sum+= cipher;
}
@ -46,7 +46,7 @@ void Checksum::addString(const string &value){
}
void Checksum::addFile(const string &path){
FILE* file= fopen(path.c_str(), "rb");
if(file!=NULL){

View File

@ -3,9 +3,9 @@
//
// 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
// 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
// ==============================================================
@ -61,7 +61,7 @@ XmlIo::XmlIo(){
}
catch(const XMLException&){
throw runtime_error("Error initializing XML system");
}
}
try{
XMLCh str[strSize];
@ -84,7 +84,7 @@ XmlIo::~XmlIo(){
}
XmlNode *XmlIo::load(const string &path){
try{
ErrorHandler errorHandler;
#if XERCES_VERSION_MAJOR < 3
@ -99,7 +99,7 @@ XmlNode *XmlIo::load(const string &path){
config->setParameter(XMLUni::fgDOMValidate, true);
#endif
DOMDocument *document= parser->parseURI(path.c_str());
if(document==NULL){
throw runtime_error("Can not parse URL: " + path);
}
@ -110,7 +110,7 @@ XmlNode *XmlIo::load(const string &path){
}
catch(const DOMException &e){
throw runtime_error("Exception while loading: " + path + ": " + XMLString::transcode(e.msg));
}
}
}
void XmlIo::save(const string &path, const XmlNode *node){
@ -144,7 +144,7 @@ void XmlIo::save(const string &path, const XmlNode *node){
}
catch(const DOMException &e){
throw runtime_error("Exception while saving: " + path + ": " + XMLString::transcode(e.msg));
}
}
}
// =====================================================
// class XmlTree
@ -188,7 +188,7 @@ XmlNode::XmlNode(DOMNode *node){
//check children
for(int i=0; i<node->getChildNodes()->getLength(); ++i){
DOMNode *currentNode= node->getChildNodes()->item(i);
DOMNode *currentNode= node->getChildNodes()->item(i);
if(currentNode->getNodeType()==DOMNode::ELEMENT_NODE){
XmlNode *xmlNode= new XmlNode(currentNode);
children.push_back(xmlNode);
@ -234,7 +234,7 @@ XmlAttribute *XmlNode::getAttribute(int i) const{
}
return attributes[i];
}
XmlAttribute *XmlNode::getAttribute(const string &name) const{
for(int i=0; i<attributes.size(); ++i){
if(attributes[i]->getName()==name){
@ -269,6 +269,20 @@ XmlNode *XmlNode::getChild(const string &childName, int i) const{
throw runtime_error("Node \""+getName()+"\" doesn't have "+intToStr(i+1)+" children named \""+childName+"\"\n\nTree: "+getTreeString());
}
bool XmlNode::hasChild(const string &childName) const
{
int count= 0;
for(int j = 0; j < children.size(); ++j)
{
if(children[j]->getName()==childName)
{
return true;
}
}
return false;
}
XmlNode *XmlNode::addChild(const string &name){
XmlNode *node= new XmlNode(name);
children.push_back(node);
@ -290,10 +304,10 @@ DOMElement *XmlNode::buildElement(DOMDocument *document) const{
for(int i=0; i<attributes.size(); ++i){
XMLString::transcode(attributes[i]->getName().c_str(), str, strSize-1);
DOMAttr *attr= document->createAttribute(str);
XMLString::transcode(attributes[i]->getValue().c_str(), str, strSize-1);
attr->setValue(str);
node->setAttributeNode(attr);
}
@ -387,7 +401,7 @@ const string &XmlAttribute::getRestrictedValue() const
"\"\nFor portability reasons the only allowed characters in this field are: " + allowedCharacters);
}
}
return value;
}