1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

Chenges (networking for PG, minor fixes)

This commit is contained in:
mateuszb 2010-09-03 18:42:54 +00:00
parent dc0cdf68b6
commit 4ba3c68ced
12 changed files with 379 additions and 165 deletions

View File

@ -72,6 +72,7 @@ void CButtonBase::showAll( SDL_Surface * to )
void CButtonBase::addTextOverlay( const std::string Text, EFonts font, SDL_Color color)
{
delete text;
text = new TextOverlay;
text->text = Text;

View File

@ -1824,11 +1824,11 @@ void CPlayerInterface::gameOver(ui8 player, bool victory )
}
else
{
if(!victory) //enemy has lost
if(!victory && cb->getPlayerStatus(playerID) == PlayerState::INGAME) //enemy has lost
{
std::string txt = CGI->generaltexth->allTexts[5]; //%s has been vanquished!
boost::algorithm::replace_first(txt, "%s", CGI->generaltexth->capColors[player]);
//showInfoDialog(txt,std::vector<SComponent*>(1, new SComponent(SComponent::flag, player, 0)));
showInfoDialog(txt,std::vector<SComponent*>(1, new SComponent(SComponent::flag, player, 0)));
}
}
}

View File

@ -39,6 +39,11 @@
#include "../hch/CArtHandler.h" /*for campaign bonuses*/
#include "../hch/CBuildingHandler.h" /*for campaign bonuses*/
#include "CBitmapHandler.h"
#include "Client.h"
#include "../lib/NetPacks.h"
#define NOT_LIB
#include "../lib/RegisterTypes.cpp"
/*
* CPreGame.cpp, part of VCMI engine
@ -97,6 +102,29 @@ static void clearInfo()
playerNames.clear();
}
class CBaseForPGApply
{
public:
virtual void applyOnPG(CSelectionScreen *selScr, void *pack) const =0;
virtual ~CBaseForPGApply(){};
template<typename U> static CBaseForPGApply *getApplier(const U * t=NULL)
{
return new CApplyOnPG<U>;
}
};
template <typename T> class CApplyOnPG : public CBaseForPGApply
{
public:
void applyOnPG(CSelectionScreen *selScr, void *pack) const
{
T *ptr = static_cast<T*>(pack);
ptr->apply(selScr);
}
};
CApplier<CBaseForPGApply> *applier = NULL;
void CMapInfo::countPlayers()
{
actualHumanPlayers = playerAmnt = humenPlayers = 0;
@ -186,7 +214,7 @@ CMenuScreen::CMenuScreen( EState which )
case newGame:
{
bgAd = new CPicture(BitmapHandler::loadBitmap("ZNEWGAM.bmp"), 114, 312, true);
buttons[0] = new AdventureMapButton("", CGI->generaltexth->zelp[10].second, bind(&CGPreGame::openSel, CGP, newGame, false), 545, 4, "ZTSINGL.DEF", SDLK_s);
buttons[0] = new AdventureMapButton("", CGI->generaltexth->zelp[10].second, bind(&CGPreGame::openSel, CGP, newGame, SINGLE_PLAYER), 545, 4, "ZTSINGL.DEF", SDLK_s);
buttons[1] = new AdventureMapButton("", CGI->generaltexth->zelp[11].second, &pushIntT<CMultiMode>, 568, 120, "ZTMULTI.DEF", SDLK_m);
buttons[2] = new AdventureMapButton("", CGI->generaltexth->zelp[12].second, bind(&CMenuScreen::moveTo, this, ref(CGP->scrs[campaignMain])), 541, 233, "ZTCAMPN.DEF", SDLK_c);
buttons[3] = new AdventureMapButton("", CGI->generaltexth->zelp[13].second, 0 /*cb*/, 545, 358, "ZTTUTOR.DEF", SDLK_t);
@ -196,8 +224,8 @@ CMenuScreen::CMenuScreen( EState which )
case loadGame:
{
bgAd = new CPicture(BitmapHandler::loadBitmap("ZLOADGAM.bmp"), 114, 312, true);
buttons[0] = new AdventureMapButton("", CGI->generaltexth->zelp[10].second, bind(&CGPreGame::openSel, CGP, loadGame, false), 545, 4, "ZTSINGL.DEF", SDLK_s);
buttons[1] = new AdventureMapButton("", CGI->generaltexth->zelp[11].second, bind(&CGPreGame::openSel, CGP, loadGame, true), 568, 120, "ZTMULTI.DEF", SDLK_m);
buttons[0] = new AdventureMapButton("", CGI->generaltexth->zelp[10].second, bind(&CGPreGame::openSel, CGP, loadGame, SINGLE_PLAYER), 545, 4, "ZTSINGL.DEF", SDLK_s);
buttons[1] = new AdventureMapButton("", CGI->generaltexth->zelp[11].second, bind(&CGPreGame::openSel, CGP, loadGame, HOT_SEAT), 568, 120, "ZTMULTI.DEF", SDLK_m);
buttons[2] = new AdventureMapButton("", CGI->generaltexth->zelp[12].second, 0 /*cb*/, 541, 233, "ZTCAMPN.DEF", SDLK_c);
buttons[3] = new AdventureMapButton("", CGI->generaltexth->zelp[13].second, 0 /*cb*/, 545, 358, "ZTTUTOR.DEF", SDLK_t);
buttons[4] = new AdventureMapButton("", CGI->generaltexth->zelp[14].second, bind(&CMenuScreen::moveTo, this, CGP->scrs[mainMenu]), 582, 464, "ZTBACK.DEF", SDLK_ESCAPE);
@ -208,7 +236,7 @@ CMenuScreen::CMenuScreen( EState which )
buttons[0] = new AdventureMapButton("", "", 0 /*cb*/, 535, 8, "ZSSSOD.DEF", SDLK_s);
buttons[1] = new AdventureMapButton("", "", 0 /*cb*/, 494, 117, "ZSSROE.DEF", SDLK_m);
buttons[2] = new AdventureMapButton("", "", 0 /*cb*/, 486, 241, "ZSSARM.DEF", SDLK_c);
buttons[3] = new AdventureMapButton("", "", bind(&CGPreGame::openSel, CGP, campaignList, false), 550, 358, "ZSSCUS.DEF", SDLK_t);
buttons[3] = new AdventureMapButton("", "", bind(&CGPreGame::openSel, CGP, campaignList, SINGLE_PLAYER), 550, 358, "ZSSCUS.DEF", SDLK_t);
buttons[4] = new AdventureMapButton("", "", bind(&CMenuScreen::moveTo, this, CGP->scrs[newGame]), 582, 464, "ZSSEXIT.DEF", SDLK_ESCAPE);
}
@ -259,10 +287,9 @@ CGPreGame::~CGPreGame()
delete scrs[i];
}
void CGPreGame::openSel( CMenuScreen::EState type, bool multi )
void CGPreGame::openSel(CMenuScreen::EState type, CMenuScreen::EMultiMode multi /*= CMenuScreen::SINGLE_PLAYER*/)
{
resetPlayerNames();
GH.pushInt(new CSelectionScreen(type, multi));
}
@ -314,10 +341,19 @@ void CGPreGame::resetPlayerNames()
playerNames.push_back(CGI->generaltexth->allTexts[434]); //we have only one player and his name is "Player"
}
CSelectionScreen::CSelectionScreen(CMenuScreen::EState Type, bool MultiPlayer)
:multiPlayer(MultiPlayer)
CSelectionScreen::CSelectionScreen(CMenuScreen::EState Type, CMenuScreen::EMultiMode MultiPlayer /*= CMenuScreen::SINGLE_PLAYER*/)
:multiPlayer(MultiPlayer), serv(NULL)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
applier = new CApplier<CBaseForPGApply>;
CServerHandler *sh = NULL;
if(multiPlayer == CMenuScreen::MULTI_PLAYER)
{
sh = new CServerHandler;
sh->startServer();
}
IShowActivable::type = BLOCK_ADV_HOTKEYS;
pos.w = 762;
pos.h = 584;
@ -349,7 +385,7 @@ CSelectionScreen::CSelectionScreen(CMenuScreen::EState Type, bool MultiPlayer)
sInfo.turnTime = 0;
curTab = NULL;
card = new InfoCard(type); //right info card
card = new InfoCard(type, multiPlayer == CMenuScreen::MULTI_PLAYER); //right info card
if (type == CMenuScreen::campaignList)
{
opt = NULL;
@ -378,6 +414,12 @@ CSelectionScreen::CSelectionScreen(CMenuScreen::EState Type, bool MultiPlayer)
random->addTextOverlay(CGI->generaltexth->allTexts[740], FONT_SMALL);
start = new AdventureMapButton(CGI->generaltexth->zelp[103], bind(&CSelectionScreen::startGame, this), 411, 529, "SCNRBEG.DEF", SDLK_b);
if(multiPlayer == CMenuScreen::MULTI_PLAYER)
{
AdventureMapButton *hideChat = new AdventureMapButton(CGI->generaltexth->zelp[48], 0, 619, 75, "GSPBUT2.DEF", SDLK_h);
hideChat->addTextOverlay(CGI->generaltexth->allTexts[531], FONT_SMALL);
}
}
break;
case CMenuScreen::loadGame:
@ -408,6 +450,13 @@ CSelectionScreen::CSelectionScreen(CMenuScreen::EState Type, bool MultiPlayer)
}
back = new AdventureMapButton("", CGI->generaltexth->zelp[105].second, bind(&CGuiHandler::popIntTotally, &GH, this), 581, 529, backName, SDLK_ESCAPE);
if(multiPlayer == CMenuScreen::MULTI_PLAYER)
{
serv = sh->connectToServer();
}
delete sh;
}
CSelectionScreen::~CSelectionScreen()
@ -416,6 +465,7 @@ CSelectionScreen::~CSelectionScreen()
curOpts = NULL;
playerColor = -1;
playerNames.clear();
delete applier;
}
void CSelectionScreen::toggleTab(CIntObject *tab)
@ -598,6 +648,19 @@ void CSelectionScreen::difficultyChange( int to )
GH.totalRedraw();
}
void CSelectionScreen::handleConnection()
{
while(serv)
{
}
}
void CSelectionScreen::toggleChat()
{
}
// A new size filter (Small, Medium, ...) has been selected. Populate
// selMaps with the relevant data.
void SelectionTab::filter( int size, bool selectFirst )
@ -1167,8 +1230,14 @@ void SelectionTab::selectFName( const std::string &fname )
InfoCard::InfoCard( CMenuScreen::EState Type )
: difficulty(NULL), sizes(NULL), sFlags(NULL), bg(NULL)
CChatBox::CChatBox(const Rect &rect)
{
const int height = 10;
//inputBox = new CTextInput(Rect(rect.x, rect.y + rect.h - height, rect.w, height));
}
InfoCard::InfoCard( CMenuScreen::EState Type, bool network )
: difficulty(NULL), sizes(NULL), sFlags(NULL), bg(NULL), chatOn(false), chat(NULL)
{
OBJ_CONSTRUCTION;
pos.x += 393;
@ -1209,6 +1278,12 @@ InfoCard::InfoCard( CMenuScreen::EState Type )
//description needs bg
moveChild(new CPicture(*bg, descriptionRect), this, mapDescription, true); //move subpicture bg to our description control (by default it's our (Infocard) child)
if(network)
{
new CPicture("CHATPLUG.bmp", 17, 276);
chat = new CChatBox(descriptionRect);
}
}
}
@ -1413,6 +1488,36 @@ void InfoCard::showTeamsPopup()
GH.pushInt(new CInfoPopup(bmp, true));
}
void InfoCard::toggleChat()
{
setChat(!chatOn);
}
void InfoCard::setChat(bool activateChat)
{
if(chatOn == activateChat)
return;
assert(active);
if(activateChat)
{
mapDescription->recActions = 0;
mapDescription->deactivate();
chat->recActions = 255;
chat->activate();
}
else
{
mapDescription->recActions = 255;
mapDescription->activate();
chat->recActions = 0;
chat->deactivate();
}
chatOn = activateChat;
}
OptionsTab::OptionsTab( CMenuScreen::EState Type)
:type(Type)
{
@ -2172,6 +2277,8 @@ CMultiMode::CMultiMode()
txt->setText(CGI->generaltexth->allTexts[434]); //Player
btns[0] = new AdventureMapButton(CGI->generaltexth->zelp[266], bind(&CMultiMode::openHotseat, this), 373, 78, "MUBHOT.DEF");
btns[1] = new AdventureMapButton("Host TCP/IP game", "", bind(&CMultiMode::hostTCP, this), 373, 78 + 57*1, "MUBHOST.DEF");
btns[2] = new AdventureMapButton("Join TCP/IP game", "", bind(&CMultiMode::joinTCP, this), 373, 78 + 57*2, "MUBJOIN.DEF");
btns[6] = new AdventureMapButton(CGI->generaltexth->zelp[288], bind(&CGuiHandler::popIntTotally, ref(GH), this), 373, 424, "MUBCANC.DEF", SDLK_ESCAPE);
}
@ -2180,6 +2287,19 @@ void CMultiMode::openHotseat()
GH.pushInt(new CHotSeatPlayers(txt->text));
}
void CMultiMode::hostTCP()
{
playerNames.clear();
playerNames.push_back(txt->text);
GH.popIntTotally(this);
GH.pushInt(new CSelectionScreen(CMenuScreen::newGame, CMenuScreen::MULTI_PLAYER));
}
void CMultiMode::joinTCP()
{
}
CHotSeatPlayers::CHotSeatPlayers(const std::string &firstPlayer)
{
OBJ_CONSTRUCTION;
@ -2206,7 +2326,7 @@ void CHotSeatPlayers::enterSelectionScreen()
if(txt[i]->text.length())
playerNames.push_back(txt[i]->text);
GH.popInts(2);
GH.popInts(2); //pop MP mode window and this
GH.pushInt(new CSelectionScreen(CMenuScreen::newGame));
}
@ -2779,7 +2899,7 @@ void CBonusSelection::CRegion::show( SDL_Surface * to )
}
CSavingScreen::CSavingScreen(bool hotseat)
: CSelectionScreen(CMenuScreen::saveGame, hotseat)
: CSelectionScreen(CMenuScreen::saveGame, hotseat ? CMenuScreen::HOT_SEAT : CMenuScreen::SINGLE_PLAYER)
{
ourGame = mapInfoFromGame();
sInfo = *LOCPLINT->cb->getStartInfo();
@ -2791,3 +2911,7 @@ CSavingScreen::~CSavingScreen()
}
void ChatMessage::apply(CSelectionScreen *selScreen)
{
}

View File

@ -25,6 +25,7 @@ class CCampaign;
class CGStatusBar;
class CTextBox;
class CCampaignState;
class CConnection;
class CMapInfo
{
@ -64,6 +65,10 @@ public:
mainMenu, newGame, loadGame, campaignMain, saveGame, scenarioInfo, campaignList
};
enum EMultiMode {
SINGLE_PLAYER = 0, HOT_SEAT, MULTI_PLAYER
};
CPicture *bgAd;
AdventureMapButton *buttons[5];
@ -82,13 +87,25 @@ struct FileInfo
bool inLod; //tells if this file is located in Lod
};
class CChatBox : public CIntObject
{
public:
CTextBox *chatHistory;
CTextInput *inputBox;
CChatBox(const Rect &rect);
};
class InfoCard : public CIntObject
{
CPicture *bg;
public:
CMenuScreen::EState type;
bool chatOn; //if chat is shown, then description is hidden
CTextBox *mapDescription;
CChatBox *chat;
CHighlightableButtonsGroup *difficulty;
CDefHandler *sizes, *sFlags;;
@ -96,7 +113,9 @@ public:
void showAll(SDL_Surface * to);
void clickRight(tribool down, bool previousState);
void showTeamsPopup();
InfoCard(CMenuScreen::EState Type);
void toggleChat();
void setChat(bool activateChat);
InfoCard(CMenuScreen::EState Type, bool network = false);
~InfoCard();
};
@ -214,9 +233,11 @@ public:
const CMapInfo *current;
StartInfo sInfo;
CIntObject *curTab;
bool multiPlayer;
CMenuScreen::EMultiMode multiPlayer;
CSelectionScreen(CMenuScreen::EState Type, bool MultiPlayer = false);
CConnection *serv; //connection to server, used in MP mode
CSelectionScreen(CMenuScreen::EState Type, CMenuScreen::EMultiMode MultiPlayer = CMenuScreen::SINGLE_PLAYER);
~CSelectionScreen();
void toggleTab(CIntObject *tab);
void changeSelection(const CMapInfo *to);
@ -224,6 +245,9 @@ public:
void startCampaign();
void startGame();
void difficultyChange(int to);
void toggleChat();
void handleConnection();
};
class CSavingScreen : public CSelectionScreen
@ -257,6 +281,8 @@ public:
CMultiMode();
void openHotseat();
void hostTCP();
void joinTCP();
};
class CHotSeatPlayers : public CIntObject
@ -359,7 +385,7 @@ public:
~CGPreGame();
void update();
void run();
void openSel(CMenuScreen::EState type, bool multi = false);
void openSel(CMenuScreen::EState type, CMenuScreen::EMultiMode multi = CMenuScreen::SINGLE_PLAYER);
void resetPlayerNames();
void loadGraphics();

View File

@ -26,11 +26,11 @@
#include <boost/foreach.hpp>
#include <boost/thread.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/lexical_cast.hpp>
#include <sstream>
#include "CPreGame.h"
#undef DLL_EXPORT
#define DLL_EXPORT
#define NOT_LIB
#include "../lib/RegisterTypes.cpp"
extern std::string NAME;
namespace intpr = boost::interprocess;
@ -45,13 +45,21 @@ namespace intpr = boost::interprocess;
*
*/
template <typename T> class CApplyOnCL;
class CBaseForCLApply
{
public:
virtual void applyOnClAfter(CClient *cl, void *pack) const =0;
virtual void applyOnClBefore(CClient *cl, void *pack) const =0;
virtual ~CBaseForCLApply(){}
template<typename U> static CBaseForCLApply *getApplier(const U * t=NULL)
{
return new CApplyOnCL<U>;
}
};
template <typename T> class CApplyOnCL : public CBaseForCLApply
{
public:
@ -67,46 +75,20 @@ public:
}
};
class CCLApplier
{
public:
std::map<ui16,CBaseForCLApply*> apps;
CCLApplier()
{
registerTypes2(*this);
}
~CCLApplier()
{
std::map<ui16,CBaseForCLApply*>::iterator iter;
for(iter = apps.begin(); iter != apps.end(); iter++)
delete iter->second;
}
template<typename T> void registerType(const T * t=NULL)
{
ui16 ID = typeList.registerType(t);
apps[ID] = new CApplyOnCL<T>;
}
} *applier = NULL;
CApplier<CBaseForCLApply> *applier = NULL;
void CClient::init()
{
hotSeat = false;
connectionHandler = NULL;
pathInfo = NULL;
applier = new CCLApplier;
applier = new CApplier<CBaseForCLApply>;
registerTypes2(*applier);
IObjectInterface::cb = this;
serv = NULL;
gs = NULL;
cb = NULL;
terminate = false;
boost::interprocess::shared_memory_object::remove("vcmi_memory"); //if the application has previously crashed, the memory may not have been removed. to avoid problems - try to destroy it
try
{
shared = new SharedMem();
} HANDLE_EXCEPTIONC(tlog1 << "Cannot open interprocess memory: ";)
}
CClient::CClient(void)
@ -114,18 +96,20 @@ CClient::CClient(void)
{
init();
}
CClient::CClient(CConnection *con, StartInfo *si)
:waitingRequest(false)
{
init();
newGame(con,si);
}
CClient::~CClient(void)
{
delete pathInfo;
delete applier;
delete shared;
}
void CClient::waitForMoveAndSend(int color)
{
try
@ -144,7 +128,7 @@ void CClient::run()
CPack *pack = NULL;
while(!terminate)
{
pack = retreivePack(); //get the package from the server
pack = serv->retreivePack(); //get the package from the server
if (terminate)
{
@ -231,8 +215,9 @@ void CClient::endGame( bool closeConnection /*= true*/ )
LOCPLINT = NULL;
while (!playerint.empty())
{
delete playerint.begin()->second;
CGameInterface *pint = playerint.begin()->second;
playerint.erase(playerint.begin());
delete pint;
}
BOOST_FOREACH(CCallback *cb, callbacks)
@ -251,13 +236,10 @@ void CClient::loadGame( const std::string & fname )
{
tlog0 <<"\n\nLoading procedure started!\n\n";
CServerHandler sh;
sh.startServer();
timeHandler tmh;
char portc[10];
SDL_itoa(conf.cc.port,portc,10);
runServer(portc); //create new server
tlog0 <<"Restarting server: "<<tmh.getDif()<<std::endl;
{
ui32 ver;
char sig[8];
@ -284,14 +266,10 @@ void CClient::loadGame( const std::string & fname )
tlog0 <<"Initing maphandler: "<<tmh.getDif()<<std::endl;
}
waitForServer();
tlog0 <<"Waiting for server: "<<tmh.getDif()<<std::endl;
serv = new CConnection(conf.cc.server,portc,NAME);
serv = sh.connectToServer();
serv->addStdVecItems(gs);
tlog0 <<"Setting up connection: "<<tmh.getDif()<<std::endl;
tmh.update();
ui8 pom8;
*serv << ui8(3) << ui8(1); //load game; one client
*serv << fname;
@ -333,32 +311,8 @@ void CClient::newGame( CConnection *con, StartInfo *si )
{
if (con == NULL)
{
timeHandler pomtime;
char portc[10];
SDL_itoa(conf.cc.port,portc,10);
CClient::runServer(portc);
tlog0<<"Preparing shared memory and starting server: "<<pomtime.getDif()<<std::endl;
pomtime.getDif();//reset timers
//wait until server is ready
tlog0<<"Waiting for server... ";
waitForServer();
tlog0 << pomtime.getDif()<<std::endl;
while(!con)
{
try
{
tlog0 << "Establishing connection...\n";
con = new CConnection(conf.cc.server,portc,NAME);
}
catch(...)
{
tlog1 << "\nCannot establish connection! Retrying within 2 seconds" <<std::endl;
SDL_Delay(2000);
}
}
THC tlog0<<"\tConnecting to the server: "<<pomtime.getDif()<<std::endl;
CServerHandler sh;
con = sh.connectToServer();
}
timeHandler tmh;
@ -429,21 +383,6 @@ void CClient::newGame( CConnection *con, StartInfo *si )
playerint[255]->init(new CCallback(gs,255,this));
}
void CClient::runServer(const char * portc)
{
static std::string comm = std::string(BIN_DIR PATH_SEPARATOR SERVER_NAME " ") + portc + " > server_log.txt"; //needs to be static, if not - will be probably destroyed before new thread reads it
boost::thread servthr(boost::bind(system,comm.c_str())); //runs server executable; //TODO: will it work on non-windows platforms?
}
void CClient::waitForServer()
{
intpr::scoped_lock<intpr::interprocess_mutex> slock(shared->sr->mutex);
while(!shared->sr->ready)
{
shared->sr->cond.wait(slock);
}
}
template <typename Handler>
void CClient::serialize( Handler &h, const int version )
{
@ -487,16 +426,6 @@ void CClient::serialize( Handler &h, const int version )
}
}
CPack * CClient::retreivePack()
{
CPack *ret = NULL;
boost::unique_lock<boost::mutex> lock(*serv->rmx);
tlog5 << "Listening... ";
*serv >> ret;
tlog5 << "\treceived server message of type " << typeid(*ret).name() << std::endl;
return ret;
}
void CClient::handlePack( CPack * pack )
{
CBaseForCLApply *apply = applier->apps[typeList.getTypeID(pack)]; //find the applier
@ -564,3 +493,79 @@ void CClient::stopConnection()
template void CClient::serialize( CISer<CLoadFile> &h, const int version );
template void CClient::serialize( COSer<CSaveFile> &h, const int version );
void CServerHandler::startServer()
{
th.update();
serverThread = new boost::thread(&CServerHandler::callServer, this); //runs server executable; //TODO: will it work on non-windows platforms?
if(verbose)
tlog0 << "Setting up thread calling server: " << th.getDif() << std::endl;
}
void CServerHandler::waitForServer()
{
if(!serverThread)
startServer();
th.update();
intpr::scoped_lock<intpr::interprocess_mutex> slock(shared->sr->mutex);
while(!shared->sr->ready)
{
shared->sr->cond.wait(slock);
}
if(verbose)
tlog0 << "Waiting for server: " << th.getDif() << std::endl;
}
CConnection * CServerHandler::connectToServer()
{
if(!shared->sr->ready)
waitForServer();
th.update();
CConnection *ret = NULL;
while(!ret)
{
try
{
tlog0 << "Establishing connection...\n";
ret = new CConnection(conf.cc.server, port, NAME);
}
catch(...)
{
tlog1 << "\nCannot establish connection! Retrying within 2 seconds" <<std::endl;
SDL_Delay(2000);
}
}
if(verbose)
tlog0<<"\tConnecting to the server: "<<th.getDif()<<std::endl;
return ret;
}
CServerHandler::CServerHandler()
{
serverThread = NULL;
shared = NULL;
port = boost::lexical_cast<std::string>(conf.cc.port);
boost::interprocess::shared_memory_object::remove("vcmi_memory"); //if the application has previously crashed, the memory may not have been removed. to avoid problems - try to destroy it
try
{
shared = new SharedMem();
} HANDLE_EXCEPTIONC(tlog1 << "Cannot open interprocess memory: ";)
}
CServerHandler::~CServerHandler()
{
delete shared;
delete serverThread; //detaches, not kills thread
}
void CServerHandler::callServer()
{
std::string comm = std::string(BIN_DIR PATH_SEPARATOR SERVER_NAME " ") + port + " > server_log.txt";
std::system(comm.c_str());
tlog0 << "Server finished\n";
}

View File

@ -27,9 +27,30 @@ struct BattleAction;
struct SharedMem;
class CClient;
struct CPathsInfo;
namespace boost { class thread; }
void processCommand(const std::string &message, CClient *&client);
//structure to handle running server and connecting to it
class CServerHandler
{
private:
void callServer(); //calls server via system(), should be called as thread
public:
timeHandler th;
boost::thread *serverThread; //thread that called system to run server
SharedMem *shared; //interprocess memory (for waiting for server)
bool verbose; //whether to print log msgs
std::string port; //port number in text form
void startServer(); //creates a thread with callServer
void waitForServer(); //waits till server is ready
CConnection * connectToServer(); //connects to server
CServerHandler();
~CServerHandler();
};
class CClient : public IGameCallback
{
public:
@ -38,7 +59,6 @@ public:
std::map<ui8,CGameInterface *> playerint;
bool hotSeat;
CConnection *serv;
SharedMem *shared;
BattleAction *curbaction;
CPathsInfo *pathInfo;
@ -111,10 +131,6 @@ public:
friend class CCallback; //handling players actions
friend void processCommand(const std::string &message, CClient *&client); //handling console
static void runServer(const char * portc);
void waitForServer();
CPack * retreivePack(); //gets from server next pack (allocates it with new)
void handlePack( CPack * pack ); //applies the given pack and deletes it
void updatePaths();

View File

@ -66,7 +66,12 @@ class CBaseForGSApply
public:
virtual void applyOnGS(CGameState *gs, void *pack) const =0;
virtual ~CBaseForGSApply(){};
template<typename U> static CBaseForGSApply *getApplier(const U * t=NULL)
{
return new CApplyOnGS<U>;
}
};
template <typename T> class CApplyOnGS : public CBaseForGSApply
{
public:
@ -80,29 +85,7 @@ public:
}
};
class CGSApplier
{
public:
std::map<ui16,CBaseForGSApply*> apps;
CGSApplier()
{
registerTypes2(*this);
}
~CGSApplier()
{
std::map<ui16,CBaseForGSApply*>::iterator iter;
for(iter = apps.begin(); iter != apps.end(); iter++)
delete iter->second;
}
template<typename T> void registerType(const T * t=NULL)
{
ui16 ID = typeList.registerType(t);
apps[ID] = new CApplyOnGS<T>;
}
} *applierGs = NULL;
CApplier<CBaseForGSApply> *applierGs = NULL;
class IObjectCaller
{
@ -1373,7 +1356,8 @@ CGameState::CGameState()
map = NULL;
curB = NULL;
scenarioOps = NULL;
applierGs = new CGSApplier;
applierGs = new CApplier<CBaseForGSApply>;
registerTypes2(*applierGs);
objCaller = new CObjectCallersHandler;
campaign = NULL;
}

View File

@ -20,6 +20,7 @@
#include "../hch/CHeroHandler.h"
#include "../hch/CTownHandler.h"
#include "../hch/CCampaignHandler.h"
#include "NetPacks.h"
/*
@ -219,6 +220,16 @@ void CConnection::reportState(CLogger &out)
}
}
CPack * CConnection::retreivePack()
{
CPack *ret = NULL;
boost::unique_lock<boost::mutex> lock(*rmx);
tlog5 << "Listening... ";
*this >> ret;
tlog5 << "\treceived server message of type " << typeid(*ret).name() << std::endl;
return ret;
}
CSaveFile::CSaveFile( const std::string &fname )
:sfile(NULL)
{

View File

@ -30,6 +30,7 @@ class CGameState;
class CCreature;
class LibClasses;
class CHero;
class CPack;
extern DLL_EXPORT LibClasses * VLC;
namespace mpl = boost::mpl;
@ -863,6 +864,29 @@ public:
template<class T>
CConnection &operator&(const T&);
~CConnection(void);
CPack *retreivePack(); //gets from server next pack (allocates it with new)
};
template<typename T>
class CApplier
{
public:
std::map<ui16,T*> apps;
~CApplier()
{
std::map<ui16,T*>::iterator iter;
for(iter = apps.begin(); iter != apps.end(); iter++)
delete iter->second;
}
template<typename U> void registerType(const U * t=NULL)
{
ui16 ID = typeList.registerType(t);
apps[ID] = T::getApplier(t);
}
};
#endif // __CONNECTION_H__

View File

@ -23,6 +23,7 @@ class CGameHandler;
class CConnection;
class CCampaignState;
class CArtifact;
class CSelectionScreen;
struct CPack
{
@ -1618,5 +1619,22 @@ struct CenterView : public CPackForClient//515
}
};
/***********************************************************************************************************/
struct CPackForSelectionScreen : public CPack
{
void apply(CSelectionScreen *selScreen){}; //that functions are implemented in CPreGame.cpp
};
struct ChatMessage : public CPackForSelectionScreen
{
std::string playerName, message;
void apply(CSelectionScreen *selScreen);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & playerName & message;
}
};
#endif //__NETPACKS_H__

View File

@ -1,12 +1,11 @@
#define VCMI_DLL
#include "Connection.h"
#include "NetPacks.h"
#include "VCMI_Lib.h"
#include "../hch/CObjectHandler.h"
#include "../hch/CHeroHandler.h"
#include "../hch/CTownHandler.h"
#include "RegisterTypes.h"
/*
* RegisterTypes.cpp, part of VCMI engine
*
@ -17,6 +16,13 @@
*
*/
#ifndef VCMI_DLL
#undef DLL_EXPORT
#define DLL_EXPORT
#endif
#include "RegisterTypes.h"
template<typename Serializer> DLL_EXPORT
void registerTypes1(Serializer &s)
{
@ -171,10 +177,17 @@ void registerTypes3(Serializer &s)
s.template registerType<PlayerMessage>();
}
template<typename Serializer> DLL_EXPORT
void registerTypes4(Serializer &s)
{
s.template registerType<ChatMessage>();
}
template<typename Serializer> DLL_EXPORT
void registerTypes(Serializer &s)
{
registerTypes1(s);
registerTypes2(s);
registerTypes3(s);
registerTypes4(s);
}

View File

@ -60,10 +60,16 @@ CondSh<BattleResult *> battleResult(NULL);
std::ptrdiff_t randomizer (ptrdiff_t i) {return rand();}
std::ptrdiff_t (*p_myrandom)(std::ptrdiff_t) = randomizer;
class CBaseForGHApply
{
public:
virtual bool applyOnGH(CGameHandler *gh, CConnection *c, void *pack) const =0;
virtual ~CBaseForGHApply(){}
template<typename U> static CBaseForGHApply *getApplier(const U * t=NULL)
{
return new CApplyOnGH<U>;
}
};
template <typename T> class CApplyOnGH : public CBaseForGHApply
{
@ -76,22 +82,7 @@ public:
}
};
class CGHApplier
{
public:
std::map<ui16,CBaseForGHApply*> apps;
CGHApplier()
{
registerTypes3(*this);
}
template<typename T> void registerType(const T * t=NULL)
{
ui16 ID = typeList.registerType(t);
apps[ID] = new CApplyOnGH<T>;
}
} *applier = NULL;
CApplier<CBaseForGHApply> *applier = NULL;
CMP_stack cmpst ;
@ -938,7 +929,8 @@ CGameHandler::CGameHandler(void)
QID = 1;
gs = NULL;
IObjectInterface::cb = this;
applier = new CGHApplier;
applier = new CApplier<CBaseForGHApply>;
registerTypes3(*applier);
visitObjectAfterVictory = false;
}