mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-28 08:48:48 +02:00
Early changes towards MP support.
It's possible to connect several clients (running on localhost) and enter MP pregame. The actual MP game still not playable. (though it can be started)
This commit is contained in:
parent
aa131bbf15
commit
daeb3af67a
20
StartInfo.h
20
StartInfo.h
@ -26,8 +26,9 @@ struct PlayerSettings
|
||||
si8 bonus; //usees enum type Ebonus
|
||||
ui8 color; //from 0 -
|
||||
ui8 handicap;//0-no, 1-mild, 2-severe
|
||||
|
||||
std::string name;
|
||||
ui8 human;
|
||||
ui8 human; //0 - AI, non-0 serves as player id
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & castle;
|
||||
@ -51,15 +52,15 @@ struct PlayerSettings
|
||||
|
||||
struct StartInfo
|
||||
{
|
||||
enum EMode {NEW_GAME, LOAD_GAME, CAMPAIGN};
|
||||
enum EMode {NEW_GAME, LOAD_GAME, CAMPAIGN, INVALID = 255};
|
||||
|
||||
ui8 mode; //0 - new game; 1 - load game; 2 - campaign
|
||||
ui8 mode; //uses EMode enum
|
||||
ui8 difficulty; //0=easy; 4=impossible
|
||||
std::map<int, PlayerSettings> playerInfos; //color indexed
|
||||
ui8 turnTime; //in minutes, 0=unlimited
|
||||
std::string mapname;
|
||||
ui8 whichMapInCampaign; //used only for mode 2
|
||||
ui8 choosenCampaignBonus; //used only for mode 2
|
||||
ui8 whichMapInCampaign; //used only for mode CAMPAIGN
|
||||
ui8 choosenCampaignBonus; //used only for mode CAMPAIGN
|
||||
PlayerSettings & getIthPlayersSettings(int no)
|
||||
{
|
||||
if(playerInfos.find(no) != playerInfos.end())
|
||||
@ -68,10 +69,10 @@ struct StartInfo
|
||||
throw std::string("Cannot find info about player");
|
||||
}
|
||||
|
||||
PlayerSettings *getPlayersSettings(const std::string &name)
|
||||
PlayerSettings *getPlayersSettings(const ui8 nameID)
|
||||
{
|
||||
for(std::map<int, PlayerSettings>::iterator it=playerInfos.begin(); it != playerInfos.end(); ++it)
|
||||
if(it->second.name == name)
|
||||
if(it->second.human == nameID)
|
||||
return &it->second;
|
||||
|
||||
return NULL;
|
||||
@ -87,6 +88,11 @@ struct StartInfo
|
||||
h & whichMapInCampaign;
|
||||
h & choosenCampaignBonus;
|
||||
}
|
||||
|
||||
StartInfo()
|
||||
{
|
||||
mode = INVALID;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -671,3 +671,8 @@ void CSlider::keyPressed(const SDL_KeyboardEvent & key)
|
||||
|
||||
moveTo(moveDest);
|
||||
}
|
||||
|
||||
void CSlider::moveToMax()
|
||||
{
|
||||
moveTo(amount);
|
||||
}
|
@ -148,6 +148,7 @@ public:
|
||||
CSlider(int x, int y, int totalw, boost::function<void(int)> Moved, int Capacity, int Amount,
|
||||
int Value=0, bool Horizontal=true, int style = 0); //style 0 - brown, 1 - blue
|
||||
~CSlider();
|
||||
void moveToMax();
|
||||
};
|
||||
|
||||
#endif // __ADVENTUREMAPBUTTON_H__
|
||||
|
@ -110,7 +110,7 @@ void init()
|
||||
tlog0 << "\tInitializing minors: " << pomtime.getDif() << std::endl;
|
||||
{
|
||||
//read system options
|
||||
CLoadFile settings(GVCMIDirs.UserPath + "/config/sysopts.bin", false);
|
||||
CLoadFile settings(GVCMIDirs.UserPath + "/config/sysopts.bin", 727);
|
||||
if(settings.sfile)
|
||||
{
|
||||
settings >> GDefaultOptions;
|
||||
@ -282,6 +282,17 @@ int main(int argc, char** argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void printInfoAboutIntObject(const CIntObject *obj, int level)
|
||||
{
|
||||
int tabs = level;
|
||||
while(tabs--) tlog4 << '\t';
|
||||
|
||||
tlog4 << typeid(*obj).name() << " *** " << (obj->active ? "" : "not ") << "active\n";
|
||||
|
||||
BOOST_FOREACH(const CIntObject *child, obj->children)
|
||||
printInfoAboutIntObject(child, level+1);
|
||||
}
|
||||
|
||||
void processCommand(const std::string &message)
|
||||
{
|
||||
std::istringstream readed;
|
||||
@ -452,6 +463,16 @@ void processCommand(const std::string &message)
|
||||
{
|
||||
LOCPLINT->showingDialog->setn(false);
|
||||
}
|
||||
else if(cn == "gui")
|
||||
{
|
||||
BOOST_FOREACH(const IShowActivable *child, GH.listInt)
|
||||
{
|
||||
if(const CIntObject *obj = dynamic_cast<const CIntObject *>(child))
|
||||
printInfoAboutIntObject(obj, 0);
|
||||
else
|
||||
tlog4 << typeid(*obj).name() << std::endl;
|
||||
}
|
||||
}
|
||||
else if(client && client->serv && client->serv->connected) //send to server
|
||||
{
|
||||
PlayerMessage pm(LOCPLINT->playerID,message);
|
||||
@ -459,7 +480,6 @@ void processCommand(const std::string &message)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//plays intro, ends when intro is over or button has been pressed (handles events)
|
||||
void playIntro()
|
||||
{
|
||||
@ -623,7 +643,7 @@ static void listenForEvents()
|
||||
}
|
||||
}
|
||||
|
||||
void startGame(StartInfo * options)
|
||||
void startGame(StartInfo * options, CConnection *serv/* = NULL*/)
|
||||
{
|
||||
GH.curInt =NULL;
|
||||
if(gOnlyAI)
|
||||
@ -655,7 +675,7 @@ void startGame(StartInfo * options)
|
||||
{
|
||||
case StartInfo::NEW_GAME:
|
||||
case StartInfo::CAMPAIGN:
|
||||
client->newGame(NULL, options);
|
||||
client->newGame(serv, options);
|
||||
break;
|
||||
case StartInfo::LOAD_GAME:
|
||||
std::string fname = options->mapname;
|
||||
|
@ -1917,6 +1917,14 @@ SystemOptions::SystemOptions()
|
||||
animSpeed = 2;
|
||||
printMouseShadow = true;
|
||||
showQueue = true;
|
||||
|
||||
playerName = "Player";
|
||||
}
|
||||
|
||||
void SystemOptions::setPlayerName(const std::string &newPlayerName)
|
||||
{
|
||||
playerName = newPlayerName;
|
||||
settingsChanged();
|
||||
}
|
||||
|
||||
void CPlayerInterface::eraseCurrentPathOf( const CGHeroInstance * ho, bool checkForExistanceOfPath /*= true */ )
|
||||
|
@ -76,6 +76,7 @@ namespace boost
|
||||
|
||||
struct SystemOptions
|
||||
{
|
||||
std::string playerName;
|
||||
|
||||
ui8 heroMoveSpeed;/*, enemyMoveSpeed*/ //speed of player's hero movement
|
||||
ui8 mapScrollingSpeed; //map scrolling speed
|
||||
@ -94,13 +95,14 @@ struct SystemOptions
|
||||
void setMapScrollingSpeed(int newSpeed); //set the member above
|
||||
void setMusicVolume(int newVolume);
|
||||
void setSoundVolume(int newVolume);
|
||||
void setPlayerName(const std::string &newPlayerName);
|
||||
void settingsChanged(); //updates file with "default" settings for next running of application
|
||||
void apply();
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & playerName;
|
||||
h & heroMoveSpeed & mapScrollingSpeed & musicVolume & soundVolume;
|
||||
|
||||
h & printCellBorders & printStackRange & animSpeed & printMouseShadow & showQueue;
|
||||
}
|
||||
};
|
||||
|
1270
client/CPreGame.cpp
1270
client/CPreGame.cpp
File diff suppressed because it is too large
Load Diff
@ -6,6 +6,7 @@
|
||||
#include "../StartInfo.h"
|
||||
#include "GUIBase.h"
|
||||
#include "FunctionList.h"
|
||||
#include "../lib/CMapInfo.h"
|
||||
|
||||
/*
|
||||
* CPreGame.h, part of VCMI engine
|
||||
@ -26,27 +27,10 @@ class CGStatusBar;
|
||||
class CTextBox;
|
||||
class CCampaignState;
|
||||
class CConnection;
|
||||
class CPackForSelectionScreen;
|
||||
class PlayerInfo;
|
||||
|
||||
class CMapInfo
|
||||
{
|
||||
public:
|
||||
CMapHeader * mapHeader; //may be NULL if campaign
|
||||
CCampaignHeader * campaignHeader; //may be NULL if scenario
|
||||
StartInfo *scenarioOpts; //options with which scenario has been started (used only with saved games)
|
||||
std::string filename;
|
||||
bool lodCmpgn; //tells if this campaign is located in Lod file
|
||||
std::string date;
|
||||
int playerAmnt, //players in map
|
||||
humenPlayers; //players ALLOWED to be controlled by human
|
||||
int actualHumanPlayers; // >1 if multiplayer game
|
||||
CMapInfo(bool map = true);
|
||||
~CMapInfo();
|
||||
//CMapInfo(const std::string &fname, const unsigned char *map);
|
||||
void setHeader(CMapHeader *header);
|
||||
void mapInit(const std::string &fname, const unsigned char *map);
|
||||
void campaignInit();
|
||||
void countPlayers();
|
||||
};
|
||||
namespace boost{ class thread; class recursive_mutex;}
|
||||
|
||||
enum ESortBy{_playerAm, _size, _format, _name, _viccon, _loscon, _numOfMaps}; //_numOfMaps is for campaigns
|
||||
|
||||
@ -66,7 +50,7 @@ public:
|
||||
};
|
||||
|
||||
enum EMultiMode {
|
||||
SINGLE_PLAYER = 0, HOT_SEAT, MULTI_PLAYER
|
||||
SINGLE_PLAYER = 0, MULTI_HOT_SEAT, MULTI_NETWORK_HOST, MULTI_NETWORK_GUEST
|
||||
};
|
||||
|
||||
CPicture *bgAd;
|
||||
@ -94,6 +78,10 @@ public:
|
||||
CTextInput *inputBox;
|
||||
|
||||
CChatBox(const Rect &rect);
|
||||
|
||||
void keyPressed(const SDL_KeyboardEvent & key);
|
||||
|
||||
void addNewMessage(const std::string &text);
|
||||
};
|
||||
|
||||
class InfoCard : public CIntObject
|
||||
@ -102,9 +90,11 @@ class InfoCard : public CIntObject
|
||||
public:
|
||||
CMenuScreen::EState type;
|
||||
|
||||
bool network;
|
||||
bool chatOn; //if chat is shown, then description is hidden
|
||||
CTextBox *mapDescription;
|
||||
CChatBox *chat;
|
||||
CPicture *playerListBg;
|
||||
|
||||
CHighlightableButtonsGroup *difficulty;
|
||||
CDefHandler *sizes, *sFlags;;
|
||||
@ -115,7 +105,7 @@ public:
|
||||
void showTeamsPopup();
|
||||
void toggleChat();
|
||||
void setChat(bool activateChat);
|
||||
InfoCard(CMenuScreen::EState Type, bool network = false);
|
||||
InfoCard(bool Network = false);
|
||||
~InfoCard();
|
||||
};
|
||||
|
||||
@ -159,7 +149,7 @@ public:
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void keyPressed(const SDL_KeyboardEvent & key);
|
||||
void onDoubleClick();
|
||||
SelectionTab(CMenuScreen::EState Type, const boost::function<void(CMapInfo *)> &OnSelect, bool MultiPlayer=false);
|
||||
SelectionTab(CMenuScreen::EState Type, const boost::function<void(CMapInfo *)> &OnSelect, CMenuScreen::EMultiMode MultiPlayer = CMenuScreen::SINGLE_PLAYER);
|
||||
~SelectionTab();
|
||||
};
|
||||
|
||||
@ -183,6 +173,7 @@ public:
|
||||
|
||||
struct PlayerOptionsEntry : public CIntObject
|
||||
{
|
||||
PlayerInfo π
|
||||
PlayerSettings &s;
|
||||
CPicture *bg;
|
||||
AdventureMapButton *btns[6]; //left and right for town, hero, bonus
|
||||
@ -190,18 +181,25 @@ public:
|
||||
SelectedBox *town;
|
||||
SelectedBox *hero;
|
||||
SelectedBox *bonus;
|
||||
bool fixedHero;
|
||||
enum {HUMAN_OR_CPU, HUMAN, CPU} whoCanPlay;
|
||||
|
||||
PlayerOptionsEntry(OptionsTab *owner, PlayerSettings &S);
|
||||
void selectButtons(bool onlyHero = true); //hides unavailable buttons
|
||||
void showAll(SDL_Surface * to);
|
||||
};
|
||||
CMenuScreen::EState type;
|
||||
|
||||
CSlider *turnDuration;
|
||||
|
||||
std::set<int> usedHeroes;
|
||||
|
||||
struct PlayerToRestore
|
||||
{
|
||||
int color, id;
|
||||
void reset() { color = id = -1; }
|
||||
PlayerToRestore(){ reset(); }
|
||||
} playerToRestore;
|
||||
|
||||
|
||||
std::map<int, PlayerOptionsEntry *> entries; //indexed by color
|
||||
|
||||
void nextCastle(int player, int dir); //dir == -1 or +1
|
||||
@ -210,8 +208,8 @@ public:
|
||||
void setTurnLength(int npos);
|
||||
void flagPressed(int player);
|
||||
|
||||
void changeSelection(const CMapHeader *to);
|
||||
OptionsTab(CMenuScreen::EState Type/*, StartInfo &Opts*/);
|
||||
void recreate();
|
||||
OptionsTab();
|
||||
~OptionsTab();
|
||||
void showAll(SDL_Surface * to);
|
||||
|
||||
@ -220,7 +218,32 @@ public:
|
||||
bool canUseThisHero( int ID );
|
||||
};
|
||||
|
||||
class CSelectionScreen : public CIntObject
|
||||
class ISelectionScreenInfo
|
||||
{
|
||||
public:
|
||||
CMenuScreen::EMultiMode multiPlayer;
|
||||
CMenuScreen::EState screenType; //new/save/load#Game
|
||||
const CMapInfo *current;
|
||||
StartInfo sInfo;
|
||||
std::map<ui32, std::string> playerNames; // id of player <-> player name; 0 is reserved as ID of AI "players"
|
||||
|
||||
ISelectionScreenInfo(const std::map<ui32, std::string> *Names = NULL);
|
||||
virtual ~ISelectionScreenInfo();
|
||||
virtual void update(){};
|
||||
virtual void propagateOptions() {};
|
||||
virtual void postRequest(ui8 what, ui8 dir) {};
|
||||
virtual void postChatMessage(const std::string &txt){};
|
||||
|
||||
void setPlayer(PlayerSettings &pset, unsigned player);
|
||||
void updateStartInfo( std::string filename, StartInfo & sInfo, const CMapHeader * mapHeader );
|
||||
|
||||
int getIdOfFirstUnallocatedPlayer(); //returns 0 if none
|
||||
bool isGuest() const;
|
||||
bool isHost() const;
|
||||
|
||||
};
|
||||
|
||||
class CSelectionScreen : public CIntObject, public ISelectionScreenInfo
|
||||
{
|
||||
public:
|
||||
CPicture *bg; //general bg image
|
||||
@ -229,25 +252,33 @@ public:
|
||||
AdventureMapButton *start, *back;
|
||||
|
||||
SelectionTab *sel;
|
||||
CMenuScreen::EState type; //new/save/load#Game
|
||||
const CMapInfo *current;
|
||||
StartInfo sInfo;
|
||||
CIntObject *curTab;
|
||||
CMenuScreen::EMultiMode multiPlayer;
|
||||
|
||||
boost::thread *serverHandlingThread;
|
||||
boost::recursive_mutex *mx;
|
||||
std::list<CPackForSelectionScreen *> upcomingPacks; //protected by mx
|
||||
|
||||
CConnection *serv; //connection to server, used in MP mode
|
||||
bool ongoingClosing;
|
||||
ui8 myNameID; //used when networking - otherwise all player are "mine"
|
||||
|
||||
CSelectionScreen(CMenuScreen::EState Type, CMenuScreen::EMultiMode MultiPlayer = CMenuScreen::SINGLE_PLAYER);
|
||||
CSelectionScreen(CMenuScreen::EState Type, CMenuScreen::EMultiMode MultiPlayer = CMenuScreen::SINGLE_PLAYER, const std::map<ui32, std::string> *Names = NULL);
|
||||
~CSelectionScreen();
|
||||
void toggleTab(CIntObject *tab);
|
||||
void changeSelection(const CMapInfo *to);
|
||||
static void updateStartInfo( const CMapInfo * to, StartInfo & sInfo, const CMapHeader * mapHeader );
|
||||
void startCampaign();
|
||||
void startGame();
|
||||
void difficultyChange(int to);
|
||||
|
||||
void toggleChat();
|
||||
void handleConnection();
|
||||
|
||||
void processPacks();
|
||||
void setSInfo(const StartInfo &si);
|
||||
void update() OVERRIDE;
|
||||
void propagateOptions() OVERRIDE;
|
||||
void postRequest(ui8 what, ui8 dir) OVERRIDE;
|
||||
void postChatMessage(const std::string &txt) OVERRIDE;
|
||||
void propagateNames();
|
||||
};
|
||||
|
||||
class CSavingScreen : public CSelectionScreen
|
||||
@ -260,7 +291,8 @@ public:
|
||||
~CSavingScreen();
|
||||
};
|
||||
|
||||
class CScenarioInfo : public CIntObject
|
||||
//scenario information screen shown during the game (thus not really a "pre-game" but fits here anyway)
|
||||
class CScenarioInfo : public CIntObject, public ISelectionScreenInfo
|
||||
{
|
||||
public:
|
||||
AdventureMapButton *back;
|
||||
@ -386,10 +418,8 @@ public:
|
||||
CGPreGame();
|
||||
~CGPreGame();
|
||||
void update();
|
||||
void run();
|
||||
void openSel(CMenuScreen::EState type, CMenuScreen::EMultiMode multi = CMenuScreen::SINGLE_PLAYER);
|
||||
|
||||
void resetPlayerNames();
|
||||
void loadGraphics();
|
||||
void disposeGraphics();
|
||||
};
|
||||
|
@ -309,37 +309,57 @@ int CClient::getSelectedHero()
|
||||
|
||||
void CClient::newGame( CConnection *con, StartInfo *si )
|
||||
{
|
||||
enum {SINGLE, HOST, GUEST} networkMode = SINGLE;
|
||||
std::set<ui8> myPlayers;
|
||||
|
||||
if (con == NULL)
|
||||
{
|
||||
CServerHandler sh;
|
||||
con = sh.connectToServer();
|
||||
serv = sh.connectToServer();
|
||||
}
|
||||
else
|
||||
{
|
||||
serv = con;
|
||||
networkMode = (con->connectionID == 1) ? HOST : GUEST;
|
||||
}
|
||||
|
||||
for(std::map<int, PlayerSettings>::iterator it =si->playerInfos.begin();
|
||||
it != si->playerInfos.end(); ++it)
|
||||
{
|
||||
if(networkMode == SINGLE //single - one client has all player
|
||||
|| networkMode != SINGLE && serv->connectionID == it->second.human //multi - client has only "its players"
|
||||
|| networkMode == HOST && it->second.human == false) //multi - host has all AI players
|
||||
{
|
||||
myPlayers.insert(ui8(it->first)); //add player
|
||||
}
|
||||
}
|
||||
if(networkMode != GUEST)
|
||||
myPlayers.insert(255); //neutral
|
||||
|
||||
|
||||
|
||||
timeHandler tmh;
|
||||
CGI->state = new CGameState();
|
||||
tlog0 <<"\tGamestate: "<<tmh.getDif()<<std::endl;
|
||||
serv = con;
|
||||
CConnection &c(*con);
|
||||
CConnection &c(*serv);
|
||||
////////////////////////////////////////////////////
|
||||
ui8 pom8;
|
||||
c << ui8(2) << ui8(1); //new game; one client
|
||||
c << *si;
|
||||
c >> pom8;
|
||||
if(pom8)
|
||||
throw "Server cannot open the map!";
|
||||
else
|
||||
tlog0 << "Server opened map properly.\n";
|
||||
c << ui8(si->playerInfos.size()+1); //number of players + neutral
|
||||
for(std::map<int, PlayerSettings>::iterator it =si->playerInfos.begin();
|
||||
it != si->playerInfos.end(); ++it)
|
||||
|
||||
if(networkMode == SINGLE)
|
||||
{
|
||||
c << ui8(it->first); //players
|
||||
ui8 pom8;
|
||||
c << ui8(2) << ui8(1); //new game; one client
|
||||
c << *si;
|
||||
c >> pom8;
|
||||
if(pom8)
|
||||
throw "Server cannot open the map!";
|
||||
else
|
||||
tlog0 << "Server opened map properly.\n";
|
||||
}
|
||||
c << ui8(255); // neutrals
|
||||
|
||||
c << myPlayers;
|
||||
|
||||
|
||||
ui32 seed, sum;
|
||||
delete si;
|
||||
c >> si >> sum >> seed;
|
||||
tlog0 <<"\tSending/Getting info to/from the server: "<<tmh.getDif()<<std::endl;
|
||||
tlog0 << "\tUsing random seed: "<<seed << std::endl;
|
||||
@ -362,6 +382,9 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
||||
it != gs->scenarioOps->playerInfos.end(); ++it)//initializing interfaces for players
|
||||
{
|
||||
ui8 color = it->first;
|
||||
if(!vstd::contains(myPlayers, color))
|
||||
continue;
|
||||
|
||||
CCallback *cb = new CCallback(gs,color,this);
|
||||
if(!it->second.human)
|
||||
{
|
||||
@ -524,27 +547,15 @@ CConnection * CServerHandler::connectToServer()
|
||||
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);
|
||||
}
|
||||
}
|
||||
CConnection *ret = justConnectToServer(conf.cc.server, port);
|
||||
|
||||
if(verbose)
|
||||
tlog0<<"\tConnecting to the server: "<<th.getDif()<<std::endl;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
CServerHandler::CServerHandler()
|
||||
CServerHandler::CServerHandler(bool runServer /*= false*/)
|
||||
{
|
||||
serverThread = NULL;
|
||||
shared = NULL;
|
||||
@ -569,3 +580,24 @@ void CServerHandler::callServer()
|
||||
std::system(comm.c_str());
|
||||
tlog0 << "Server finished\n";
|
||||
}
|
||||
|
||||
CConnection * CServerHandler::justConnectToServer(const std::string &host, const std::string &port)
|
||||
{
|
||||
CConnection *ret = NULL;
|
||||
while(!ret)
|
||||
{
|
||||
try
|
||||
{
|
||||
tlog0 << "Establishing connection...\n";
|
||||
ret = new CConnection( host.size() ? host : conf.cc.server,
|
||||
port.size() ? port : boost::lexical_cast<std::string>(conf.cc.port),
|
||||
NAME);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
tlog1 << "\nCannot establish connection! Retrying within 2 seconds" << std::endl;
|
||||
SDL_Delay(2000);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
@ -43,11 +43,15 @@ public:
|
||||
bool verbose; //whether to print log msgs
|
||||
std::string port; //port number in text form
|
||||
|
||||
//functions setting up local server
|
||||
void startServer(); //creates a thread with callServer
|
||||
void waitForServer(); //waits till server is ready
|
||||
CConnection * connectToServer(); //connects to server
|
||||
|
||||
CServerHandler();
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
static CConnection * justConnectToServer(const std::string &host = "", const std::string &port = ""); //connects to given host without taking any other actions (like setting up server)
|
||||
|
||||
CServerHandler(bool runServer = false);
|
||||
~CServerHandler();
|
||||
};
|
||||
|
||||
|
@ -1669,7 +1669,7 @@ void CRecruitmentWindow::close()
|
||||
}
|
||||
void CRecruitmentWindow::Max()
|
||||
{
|
||||
slider->moveTo(slider->amount);
|
||||
slider->moveToMax();
|
||||
}
|
||||
void CRecruitmentWindow::Buy()
|
||||
{
|
||||
@ -3172,7 +3172,7 @@ CMarketplaceWindow::~CMarketplaceWindow()
|
||||
|
||||
void CMarketplaceWindow::setMax()
|
||||
{
|
||||
slider->moveTo(slider->amount);
|
||||
slider->moveToMax();
|
||||
}
|
||||
|
||||
void CMarketplaceWindow::makeDeal()
|
||||
@ -3461,7 +3461,7 @@ CAltarWindow::CAltarWindow(const IMarket *Market, const CGHeroInstance *Hero /*=
|
||||
|
||||
slider = new CSlider(231,481,137,0,0,0);
|
||||
slider->moved = boost::bind(&CAltarWindow::sliderMoved,this,_1);
|
||||
max = new AdventureMapButton(CGI->generaltexth->zelp[578],boost::bind(&CSlider::moveTo, slider, boost::ref(slider->amount)),147,520,"IRCBTNS.DEF");
|
||||
max = new AdventureMapButton(CGI->generaltexth->zelp[578],boost::bind(&CSlider::moveToMax, slider),147,520,"IRCBTNS.DEF");
|
||||
|
||||
sacrificedUnits.resize(ARMY_SIZE, 0);
|
||||
sacrificeAll = new AdventureMapButton(CGI->generaltexth->zelp[579],boost::bind(&CAltarWindow::SacrificeAll,this),393,520,"ALTARMY.DEF");
|
||||
@ -6629,6 +6629,7 @@ CTextInput::CTextInput( const Rect &Pos, const Point &bgOffset, const std::strin
|
||||
{
|
||||
focus = false;
|
||||
pos += Pos;
|
||||
captureAllKeys = true;
|
||||
OBJ_CONSTRUCTION;
|
||||
bg = new CPicture(bgName, bgOffset.x, bgOffset.y);
|
||||
used = LCLICK | KEYBOARD;
|
||||
@ -6639,10 +6640,14 @@ CTextInput::CTextInput(const Rect &Pos, SDL_Surface *srf)
|
||||
{
|
||||
focus = false;
|
||||
pos += Pos;
|
||||
captureAllKeys = true;
|
||||
OBJ_CONSTRUCTION;
|
||||
bg = new CPicture(Pos, 0, true);
|
||||
Rect hlp = Pos;
|
||||
CSDL_Ext::blitSurface(srf, &hlp, *bg, NULL);
|
||||
if(srf)
|
||||
CSDL_Ext::blitSurface(srf, &hlp, *bg, NULL);
|
||||
else
|
||||
SDL_FillRect(*bg, NULL, 0);
|
||||
pos.w = bg->pos.w;
|
||||
pos.h = bg->pos.h;
|
||||
bg->pos = pos;
|
||||
|
@ -359,7 +359,7 @@ public:
|
||||
void setText(const std::string &nText, bool callCb = false);
|
||||
|
||||
CTextInput(const Rect &Pos, const Point &bgOffset, const std::string &bgName, const CFunctionList<void(const std::string &)> &CB);
|
||||
CTextInput(const Rect &Pos, SDL_Surface *srf);
|
||||
CTextInput(const Rect &Pos, SDL_Surface *srf = NULL);
|
||||
~CTextInput();
|
||||
void showAll(SDL_Surface * to);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
|
@ -41,12 +41,12 @@
|
||||
|
||||
void SetResources::applyCl( CClient *cl )
|
||||
{
|
||||
cl->playerint[player]->receivedResource(-1,-1);
|
||||
INTERFACE_CALL_IF_PRESENT(player,receivedResource,-1,-1);
|
||||
}
|
||||
|
||||
void SetResource::applyCl( CClient *cl )
|
||||
{
|
||||
cl->playerint[player]->receivedResource(resid,val);
|
||||
INTERFACE_CALL_IF_PRESENT(player,receivedResource,resid,val);
|
||||
}
|
||||
|
||||
void SetPrimSkill::applyCl( CClient *cl )
|
||||
@ -698,7 +698,7 @@ void ShowInInfobox::applyCl(CClient *cl)
|
||||
{
|
||||
SComponent sc(c);
|
||||
text.toString(sc.description);
|
||||
if(cl->playerint[player]->human)
|
||||
if(vstd::contains(cl->playerint, player) && cl->playerint[player]->human)
|
||||
{
|
||||
static_cast<CPlayerInterface*>(cl->playerint[player])->showComp(sc);
|
||||
}
|
||||
|
7
global.h
7
global.h
@ -412,4 +412,11 @@ static inline ui32 read_unaligned_u32(const void *p)
|
||||
#define read_unaligned_u32(p) (* reinterpret_cast<const Uint32 *>(p))
|
||||
#endif
|
||||
|
||||
//for explicit overrides
|
||||
#ifdef _MSC_VER
|
||||
#define OVERRIDE override
|
||||
#else
|
||||
#define OVERRIDE //is there any working counterpart?
|
||||
#endif
|
||||
|
||||
#endif // __GLOBAL_H__
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "RegisterTypes.cpp"
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include "CMapInfo.h"
|
||||
|
||||
boost::rand48 ran;
|
||||
class CGObjectInstance;
|
||||
@ -1057,14 +1058,15 @@ CGHeroInstance * CGameState::HeroesPool::pickHeroFor(bool native, int player, co
|
||||
int CGameState::pickHero(int owner)
|
||||
{
|
||||
int h=-1;
|
||||
if(!map->getHero(h = scenarioOps->getIthPlayersSettings(owner).hero,0) && h>=0) //we haven't used selected hero
|
||||
const PlayerSettings &ps = scenarioOps->getIthPlayersSettings(owner);
|
||||
if(!map->getHero(h = ps.hero,0) && h>=0) //we haven't used selected hero
|
||||
return h;
|
||||
int f = scenarioOps->getIthPlayersSettings(owner).castle;
|
||||
int f = ps.castle;
|
||||
int i=0;
|
||||
do //try to find free hero of our faction
|
||||
{
|
||||
i++;
|
||||
h = scenarioOps->getIthPlayersSettings(owner).castle*HEROES_PER_TYPE*2+(ran()%(HEROES_PER_TYPE*2));//->scenarioOps->playerInfos[pru].hero = VLC->
|
||||
h = ps.castle*HEROES_PER_TYPE*2+(ran()%(HEROES_PER_TYPE*2));//->scenarioOps->playerInfos[pru].hero = VLC->
|
||||
} while( map->getHero(h) && i<175);
|
||||
if(i>174) //probably no free heroes - there's no point in further search, we'll take first free
|
||||
{
|
||||
@ -1368,7 +1370,7 @@ CGameState::~CGameState()
|
||||
delete mx;
|
||||
delete map;
|
||||
delete curB;
|
||||
//delete scenarioOps;
|
||||
delete scenarioOps;
|
||||
delete applierGs;
|
||||
delete objCaller;
|
||||
|
||||
@ -1503,7 +1505,7 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
|
||||
day = 0;
|
||||
seed = Seed;
|
||||
ran.seed((boost::int32_t)seed);
|
||||
scenarioOps = si;
|
||||
scenarioOps = new StartInfo(*si);
|
||||
loadTownDInfos();
|
||||
|
||||
//pick grail location
|
||||
@ -1628,9 +1630,9 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
|
||||
map->objects.push_back(nnn);
|
||||
map->addBlockVisTiles(nnn);
|
||||
//give campaign bonus
|
||||
if (si->mode == StartInfo::CAMPAIGN && getPlayer(nnn->tempOwner)->human)
|
||||
if (scenarioOps->mode == StartInfo::CAMPAIGN && getPlayer(nnn->tempOwner)->human)
|
||||
{
|
||||
HLP::giveCampaignBonusToHero(nnn, si, campaign->camp->scenarios[si->whichMapInCampaign].travelOptions);
|
||||
HLP::giveCampaignBonusToHero(nnn, scenarioOps, campaign->camp->scenarios[scenarioOps->whichMapInCampaign].travelOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1641,7 +1643,7 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
|
||||
{
|
||||
|
||||
CScenarioTravel::STravelBonus bonus =
|
||||
campaign->camp->scenarios[si->whichMapInCampaign].travelOptions.bonusesToChoose[si->choosenCampaignBonus];
|
||||
campaign->camp->scenarios[scenarioOps->whichMapInCampaign].travelOptions.bonusesToChoose[scenarioOps->choosenCampaignBonus];
|
||||
|
||||
|
||||
std::vector<CGHeroInstance *> Xheroes;
|
||||
@ -1743,13 +1745,13 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
|
||||
}
|
||||
|
||||
//give start resource bonus in case of campaign
|
||||
if (si->mode == StartInfo::CAMPAIGN)
|
||||
if (scenarioOps->mode == StartInfo::CAMPAIGN)
|
||||
{
|
||||
CScenarioTravel::STravelBonus chosenBonus =
|
||||
campaign->camp->scenarios[si->whichMapInCampaign].travelOptions.bonusesToChoose[si->choosenCampaignBonus];
|
||||
campaign->camp->scenarios[scenarioOps->whichMapInCampaign].travelOptions.bonusesToChoose[scenarioOps->choosenCampaignBonus];
|
||||
if(chosenBonus.type == 7) //resource
|
||||
{
|
||||
std::vector<const PlayerSettings *> people = HLP::getHumanPlayerInfo(si); //players we will give resource bonus
|
||||
std::vector<const PlayerSettings *> people = HLP::getHumanPlayerInfo(scenarioOps); //players we will give resource bonus
|
||||
for (int b=0; b<people.size(); ++b)
|
||||
{
|
||||
std::vector<int> res; //resources we will give
|
||||
@ -1827,11 +1829,11 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
|
||||
hpool.pavailable[map->disposedHeroes[i].ID] = map->disposedHeroes[i].players;
|
||||
}
|
||||
|
||||
if (si->mode == StartInfo::CAMPAIGN) //give campaign bonuses for specific / best hero
|
||||
if (scenarioOps->mode == StartInfo::CAMPAIGN) //give campaign bonuses for specific / best hero
|
||||
{
|
||||
|
||||
CScenarioTravel::STravelBonus chosenBonus =
|
||||
campaign->camp->scenarios[si->whichMapInCampaign].travelOptions.bonusesToChoose[si->choosenCampaignBonus];
|
||||
campaign->camp->scenarios[scenarioOps->whichMapInCampaign].travelOptions.bonusesToChoose[scenarioOps->choosenCampaignBonus];
|
||||
if (chosenBonus.isBonusForHero() && chosenBonus.info1 != 0xFFFE) //exclude generated heroes
|
||||
{
|
||||
//find human player
|
||||
@ -1856,7 +1858,7 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
|
||||
maxB = b;
|
||||
}
|
||||
}
|
||||
HLP::giveCampaignBonusToHero(heroes[maxB], si, campaign->camp->scenarios[si->whichMapInCampaign].travelOptions);
|
||||
HLP::giveCampaignBonusToHero(heroes[maxB], scenarioOps, campaign->camp->scenarios[scenarioOps->whichMapInCampaign].travelOptions);
|
||||
}
|
||||
else //specific hero
|
||||
{
|
||||
@ -1864,7 +1866,7 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
|
||||
{
|
||||
if (heroes[b]->subID == chosenBonus.info1)
|
||||
{
|
||||
HLP::giveCampaignBonusToHero(heroes[b], si, campaign->camp->scenarios[si->whichMapInCampaign].travelOptions);
|
||||
HLP::giveCampaignBonusToHero(heroes[b], scenarioOps, campaign->camp->scenarios[scenarioOps->whichMapInCampaign].travelOptions);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1904,16 +1906,16 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
|
||||
for(std::map<ui8, PlayerState>::iterator k=players.begin(); k!=players.end(); ++k)
|
||||
{
|
||||
//starting bonus
|
||||
if(si->playerInfos[k->first].bonus==PlayerSettings::brandom)
|
||||
si->playerInfos[k->first].bonus = ran()%3;
|
||||
switch(si->playerInfos[k->first].bonus)
|
||||
if(scenarioOps->playerInfos[k->first].bonus==PlayerSettings::brandom)
|
||||
scenarioOps->playerInfos[k->first].bonus = ran()%3;
|
||||
switch(scenarioOps->playerInfos[k->first].bonus)
|
||||
{
|
||||
case PlayerSettings::bgold:
|
||||
k->second.resources[6] += 500 + (ran()%6)*100;
|
||||
break;
|
||||
case PlayerSettings::bresource:
|
||||
{
|
||||
int res = VLC->townh->towns[si->playerInfos[k->first].castle].primaryRes;
|
||||
int res = VLC->townh->towns[scenarioOps->playerInfos[k->first].castle].primaryRes;
|
||||
if(res == 127)
|
||||
{
|
||||
k->second.resources[0] += 5 + ran()%6;
|
||||
@ -2035,10 +2037,10 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
|
||||
}
|
||||
|
||||
//campaign bonuses for towns
|
||||
if (si->mode == StartInfo::CAMPAIGN)
|
||||
if (scenarioOps->mode == StartInfo::CAMPAIGN)
|
||||
{
|
||||
CScenarioTravel::STravelBonus chosenBonus =
|
||||
campaign->camp->scenarios[si->whichMapInCampaign].travelOptions.bonusesToChoose[si->choosenCampaignBonus];
|
||||
campaign->camp->scenarios[scenarioOps->whichMapInCampaign].travelOptions.bonusesToChoose[scenarioOps->choosenCampaignBonus];
|
||||
|
||||
if (chosenBonus.type == 2)
|
||||
{
|
||||
|
@ -71,6 +71,11 @@ void CConnection::init()
|
||||
tlog0 << "Established connection with "<<pom<<std::endl;
|
||||
wmx = new boost::mutex;
|
||||
rmx = new boost::mutex;
|
||||
|
||||
handler = NULL;
|
||||
receivedStop = sendStop = false;
|
||||
static int cid = 1;
|
||||
connectionID = cid++;
|
||||
}
|
||||
|
||||
CConnection::CConnection(std::string host, std::string port, std::string Name)
|
||||
@ -180,6 +185,11 @@ int CConnection::read(void * data, unsigned size)
|
||||
}
|
||||
CConnection::~CConnection(void)
|
||||
{
|
||||
if(handler)
|
||||
handler->join();
|
||||
|
||||
delete handler;
|
||||
|
||||
close();
|
||||
delete io_service;
|
||||
delete wmx;
|
||||
@ -280,11 +290,11 @@ void CSaveFile::reportState(CLogger &out)
|
||||
}
|
||||
}
|
||||
|
||||
CLoadFile::CLoadFile( const std::string &fname, bool requireLatest )
|
||||
CLoadFile::CLoadFile(const std::string &fname, int minimalVersion /*= version*/)
|
||||
:sfile(NULL)
|
||||
{
|
||||
registerTypes(*this);
|
||||
openNextFile(fname, requireLatest);
|
||||
openNextFile(fname, minimalVersion);
|
||||
}
|
||||
|
||||
CLoadFile::~CLoadFile()
|
||||
@ -304,7 +314,7 @@ void CLoadFile::close()
|
||||
sfile = NULL;
|
||||
}
|
||||
|
||||
void CLoadFile::openNextFile(const std::string &fname, bool requireLatest)
|
||||
void CLoadFile::openNextFile(const std::string &fname, int minimalVersion)
|
||||
{
|
||||
fName = fname;
|
||||
sfile = new std::ifstream(fname.c_str(),std::ios::binary);
|
||||
@ -320,16 +330,16 @@ void CLoadFile::openNextFile(const std::string &fname, bool requireLatest)
|
||||
|
||||
if(std::memcmp(buffer,"VCMI",4))
|
||||
{
|
||||
tlog1 << "Error: not a VCMI save! (file " << fname << " )\n";
|
||||
tlog1 << "Error: not a VCMI file! ( " << fname << " )\n";
|
||||
delete sfile;
|
||||
sfile = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
*this >> myVersion;
|
||||
if(myVersion != version && requireLatest)
|
||||
if(myVersion < minimalVersion)
|
||||
{
|
||||
tlog1 << "Error: Not supported save format! (file " << fname << " )\n";
|
||||
tlog1 << "Error: Old file format! (file " << fname << " )\n";
|
||||
delete sfile;
|
||||
sfile = NULL;
|
||||
}
|
||||
@ -371,6 +381,11 @@ ui16 CTypeList::getTypeID( const std::type_info *type )
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream &str, const CConnection &cpc)
|
||||
{
|
||||
return str << "Connection with " << cpc.name << " (ID: " << cpc.connectionID << /*", " << (cpc.host ? "host" : "guest") <<*/ ")";
|
||||
}
|
||||
|
||||
CSerializer::~CSerializer()
|
||||
{
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/any.hpp>
|
||||
|
||||
const ui32 version = 726;
|
||||
const ui32 version = 727;
|
||||
class CConnection;
|
||||
class CGObjectInstance;
|
||||
class CGameState;
|
||||
@ -824,12 +824,12 @@ public:
|
||||
std::string fName;
|
||||
std::ifstream *sfile;
|
||||
|
||||
CLoadFile(const std::string &fname, bool requireLatest = true);
|
||||
CLoadFile(const std::string &fname, int minimalVersion = version);
|
||||
~CLoadFile();
|
||||
int read(const void * data, unsigned size);
|
||||
|
||||
void close();
|
||||
void openNextFile(const std::string &fname, bool requireLatest);
|
||||
void openNextFile(const std::string &fname, int minimalVersion);
|
||||
void reportState(CLogger &out);
|
||||
};
|
||||
|
||||
@ -853,6 +853,12 @@ public:
|
||||
boost::asio::io_service *io_service;
|
||||
std::string name; //who uses this connection
|
||||
|
||||
int connectionID;
|
||||
CConnection *c;
|
||||
boost::thread *handler;
|
||||
|
||||
bool receivedStop, sendStop;
|
||||
|
||||
CConnection(std::string host, std::string port, std::string Name);
|
||||
CConnection(TAcceptor * acceptor, boost::asio::io_service *Io_service, std::string Name);
|
||||
CConnection(TSocket * Socket, std::string Name); //use immediately after accepting connection into socket
|
||||
@ -868,6 +874,8 @@ public:
|
||||
CPack *retreivePack(); //gets from server next pack (allocates it with new)
|
||||
};
|
||||
|
||||
DLL_EXPORT std::ostream &operator<<(std::ostream &str, const CConnection &cpc);
|
||||
|
||||
template<typename T>
|
||||
class CApplier
|
||||
{
|
||||
|
160
lib/NetPacks.h
160
lib/NetPacks.h
@ -24,6 +24,7 @@ class CConnection;
|
||||
class CCampaignState;
|
||||
class CArtifact;
|
||||
class CSelectionScreen;
|
||||
class CMapInfo;
|
||||
|
||||
struct CPack
|
||||
{
|
||||
@ -1626,7 +1627,13 @@ struct CPackForSelectionScreen : public CPack
|
||||
void apply(CSelectionScreen *selScreen){}; //that functions are implemented in CPreGame.cpp
|
||||
};
|
||||
|
||||
struct ChatMessage : public CPackForSelectionScreen
|
||||
class CPregamePackToPropagate : public CPackForSelectionScreen
|
||||
{};
|
||||
|
||||
class CPregamePackToHost : public CPackForSelectionScreen
|
||||
{};
|
||||
|
||||
struct ChatMessage : public CPregamePackToPropagate
|
||||
{
|
||||
std::string playerName, message;
|
||||
|
||||
@ -1637,4 +1644,155 @@ struct ChatMessage : public CPackForSelectionScreen
|
||||
}
|
||||
};
|
||||
|
||||
struct QuitMenuWithoutStarting : public CPregamePackToPropagate
|
||||
{
|
||||
void apply(CSelectionScreen *selScreen); //that functions are implemented in CPreGame.cpp
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{}
|
||||
};
|
||||
|
||||
struct PlayerJoined : public CPregamePackToHost
|
||||
{
|
||||
std::string playerName;
|
||||
ui8 connectionID;
|
||||
|
||||
void apply(CSelectionScreen *selScreen); //that functions are implemented in CPreGame.cpp
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & playerName & connectionID;
|
||||
}
|
||||
};
|
||||
|
||||
struct SelectMap : public CPregamePackToPropagate
|
||||
{
|
||||
const CMapInfo *mapInfo;
|
||||
bool free;
|
||||
|
||||
SelectMap(const CMapInfo &src)
|
||||
{
|
||||
mapInfo = &src;
|
||||
free = false;
|
||||
}
|
||||
SelectMap()
|
||||
{
|
||||
mapInfo = NULL;
|
||||
free = true;
|
||||
}
|
||||
~SelectMap()
|
||||
{
|
||||
if(free)
|
||||
delete mapInfo;
|
||||
}
|
||||
|
||||
void apply(CSelectionScreen *selScreen); //that functions are implemented in CPreGame.cpp
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & mapInfo;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct UpdateStartOptions : public CPregamePackToPropagate
|
||||
{
|
||||
StartInfo *options;
|
||||
bool free;
|
||||
|
||||
void apply(CSelectionScreen *selScreen); //that functions are implemented in CPreGame.cpp
|
||||
|
||||
UpdateStartOptions(StartInfo &src)
|
||||
{
|
||||
options = &src;
|
||||
free = false;
|
||||
}
|
||||
UpdateStartOptions()
|
||||
{
|
||||
options = NULL;
|
||||
free = true;
|
||||
}
|
||||
~UpdateStartOptions()
|
||||
{
|
||||
if(free)
|
||||
delete options;
|
||||
}
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & options;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct PregameGuiAction : public CPregamePackToPropagate
|
||||
{
|
||||
enum {NO_TAB, OPEN_OPTIONS, OPEN_SCENARIO_LIST};
|
||||
|
||||
ui8 action;
|
||||
|
||||
void apply(CSelectionScreen *selScreen); //that functions are implemented in CPreGame.cpp
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & action;
|
||||
}
|
||||
};
|
||||
|
||||
struct RequestOptionsChange : public CPregamePackToHost
|
||||
{
|
||||
enum {TOWN, HERO, BONUS};
|
||||
ui8 what;
|
||||
si8 direction; //-1 or +1
|
||||
ui8 playerID;
|
||||
|
||||
RequestOptionsChange(ui8 What, si8 Dir, ui8 Player)
|
||||
:what(What), direction(Dir), playerID(Player)
|
||||
{}
|
||||
RequestOptionsChange(){}
|
||||
|
||||
void apply(CSelectionScreen *selScreen); //that functions are implemented in CPreGame.cpp
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & what & direction & playerID;
|
||||
}
|
||||
};
|
||||
|
||||
struct PlayerLeft : public CPregamePackToPropagate
|
||||
{
|
||||
ui8 playerID;
|
||||
|
||||
void apply(CSelectionScreen *selScreen); //that functions are implemented in CPreGame.cpp
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & playerID;
|
||||
}
|
||||
};
|
||||
|
||||
struct PlayersNames : public CPregamePackToPropagate
|
||||
{
|
||||
public:
|
||||
std::map<ui32, std::string> playerNames;
|
||||
|
||||
void apply(CSelectionScreen *selScreen); //that functions are implemented in CPreGame.cpp
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & playerNames;
|
||||
}
|
||||
};
|
||||
|
||||
struct StartWithCurrentSettings : public CPregamePackToPropagate
|
||||
{
|
||||
public:
|
||||
void apply(CSelectionScreen *selScreen); //that functions are implemented in CPreGame.cpp
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
//h & playerNames;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //__NETPACKS_H__
|
||||
|
@ -181,6 +181,15 @@ template<typename Serializer> DLL_EXPORT
|
||||
void registerTypes4(Serializer &s)
|
||||
{
|
||||
s.template registerType<ChatMessage>();
|
||||
s.template registerType<QuitMenuWithoutStarting>();
|
||||
s.template registerType<PlayerJoined>();
|
||||
s.template registerType<SelectMap>();
|
||||
s.template registerType<UpdateStartOptions>();
|
||||
s.template registerType<PregameGuiAction>();
|
||||
s.template registerType<RequestOptionsChange>();
|
||||
s.template registerType<PlayerLeft>();
|
||||
s.template registerType<PlayersNames>();
|
||||
s.template registerType<StartWithCurrentSettings>();
|
||||
}
|
||||
|
||||
template<typename Serializer> DLL_EXPORT
|
||||
|
25
lib/map.h
25
lib/map.h
@ -101,6 +101,31 @@ struct DLL_EXPORT PlayerInfo
|
||||
mainHeroPortrait(0), hasMainTown(0), generateHeroAtMainTown(0),
|
||||
team(255), generateHero(0) {};
|
||||
|
||||
si8 defaultCastle() const
|
||||
{
|
||||
si8 ret = -2;
|
||||
for (int j = 0; j < F_NUMBER && ret != -1; j++) //we start with none and find matching faction. if more than one, then set to random
|
||||
{
|
||||
if((1 << j) & allowedFactions)
|
||||
{
|
||||
if (ret >= 0) //we've already assigned a castle and another one is possible -> set random and let player choose
|
||||
ret = -1; //breaks
|
||||
|
||||
if (ret == -2) //first available castle - pick
|
||||
ret = j;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
si8 defaultHero(bool isMapRoE = false) const
|
||||
{
|
||||
if ((generateHeroAtMainTown || isMapRoE) && hasMainTown //we will generate hero in front of main town
|
||||
|| p8) //random hero
|
||||
return -1;
|
||||
else
|
||||
return -2;
|
||||
}
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & p7 & p8 & p9 & canHumanPlay & canComputerPlay & AITactic & allowedFactions & isFactionRandom &
|
||||
|
@ -1321,25 +1321,30 @@ void CGameHandler::newTurn()
|
||||
}
|
||||
}
|
||||
}
|
||||
void CGameHandler::run(bool resume, const StartInfo *si /*= NULL*/)
|
||||
void CGameHandler::run(bool resume)
|
||||
{
|
||||
using namespace boost::posix_time;
|
||||
BOOST_FOREACH(CConnection *cc, conns)
|
||||
{//init conn.
|
||||
ui8 quantity, pom;
|
||||
ui32 quantity;
|
||||
ui8 pom;
|
||||
//ui32 seed;
|
||||
if(!resume)
|
||||
(*cc) << si << gs->map->checksum << gs->seed; // gs->scenarioOps
|
||||
(*cc) << gs->scenarioOps << gs->map->checksum << gs->seed; // gs->scenarioOps
|
||||
|
||||
(*cc) >> quantity; //how many players will be handled at that client
|
||||
|
||||
tlog0 << "Connection " << cc->connectionID << " will handle " << quantity << " player: ";
|
||||
for(int i=0;i<quantity;i++)
|
||||
{
|
||||
(*cc) >> pom; //read player color
|
||||
tlog0 << (int)pom << " ";
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> lock(gsm);
|
||||
connections[pom] = cc;
|
||||
}
|
||||
}
|
||||
tlog0 << std::endl;
|
||||
}
|
||||
|
||||
for(std::set<CConnection*>::iterator i = conns.begin(); i!=conns.end();i++)
|
||||
|
@ -219,7 +219,7 @@ public:
|
||||
void sendAndApply(SetResources * info);
|
||||
void sendAndApply(NewStructures * info);
|
||||
|
||||
void run(bool resume, const StartInfo *si = NULL);
|
||||
void run(bool resume);
|
||||
void newTurn();
|
||||
void handleAfterAttackCasting( const BattleAttack & bat );
|
||||
bool sacrificeArtifact(const IMarket * m, const CGHeroInstance * hero, ui32 artID);
|
||||
|
@ -28,6 +28,10 @@
|
||||
#include "../lib/VCMI_Lib.h"
|
||||
#include "../lib/VCMIDirs.h"
|
||||
#include "CGameHandler.h"
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include "../lib/CMapInfo.h"
|
||||
|
||||
std::string NAME_AFFIX = "server";
|
||||
std::string NAME = NAME_VER + std::string(" (") + NAME_AFFIX + ')'; //application name
|
||||
using namespace boost;
|
||||
@ -53,8 +57,256 @@ static void vaccept(tcp::acceptor *ac, tcp::socket *s, boost::system::error_code
|
||||
ac->accept(*s,*error);
|
||||
}
|
||||
|
||||
|
||||
|
||||
CPregameServer::CPregameServer(CConnection *Host, TAcceptor *Acceptor /*= NULL*/)
|
||||
: host(Host), state(RUNNING), acceptor(Acceptor), upcomingConnection(NULL), curmap(NULL), listeningThreads(0),
|
||||
curStartInfo(NULL)
|
||||
{
|
||||
initConnection(host);
|
||||
}
|
||||
|
||||
void CPregameServer::handleConnection(CConnection *cpc)
|
||||
{
|
||||
try
|
||||
{
|
||||
while(!cpc->receivedStop)
|
||||
{
|
||||
CPackForSelectionScreen *cpfs = NULL;
|
||||
*cpc >> cpfs;
|
||||
|
||||
tlog0 << "Got package to announce " << typeid(*cpfs).name() << " from " << *cpc << std::endl;
|
||||
|
||||
boost::unique_lock<boost::recursive_mutex> queueLock(mx);
|
||||
bool quitting = dynamic_cast<QuitMenuWithoutStarting*>(cpfs),
|
||||
startingGame = dynamic_cast<StartWithCurrentSettings*>(cpfs);
|
||||
if(quitting || startingGame) //host leaves main menu or wants to start game -> we end
|
||||
{
|
||||
cpc->receivedStop = true;
|
||||
if(!cpc->sendStop)
|
||||
sendPack(cpc, *cpfs);
|
||||
|
||||
if(cpc == host)
|
||||
toAnnounce.push_back(cpfs);
|
||||
}
|
||||
else
|
||||
toAnnounce.push_back(cpfs);
|
||||
|
||||
if(startingGame)
|
||||
{
|
||||
//wait for sending thread to announce start
|
||||
mx.unlock();
|
||||
while(state == RUNNING) boost::this_thread::sleep(boost::posix_time::milliseconds(50));
|
||||
mx.lock();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> queueLock(mx);
|
||||
tlog0 << *cpc << " dies... \nWhat happened: " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
boost::unique_lock<boost::recursive_mutex> queueLock(mx);
|
||||
if(state != ENDING_AND_STARTING_GAME)
|
||||
{
|
||||
connections -= cpc;
|
||||
|
||||
//notify other players about leaving
|
||||
PlayerLeft *pl = new PlayerLeft();
|
||||
pl->playerID = cpc->connectionID;
|
||||
announceTxt(cpc->name + " left the game");
|
||||
toAnnounce.push_back(pl);
|
||||
|
||||
if(!connections.size())
|
||||
{
|
||||
tlog0 << "Last connection lost, server will close itself...\n";
|
||||
boost::this_thread::sleep(boost::posix_time::seconds(2)); //we should never be hasty when networking
|
||||
state = ENDING_WITHOUT_START;
|
||||
}
|
||||
}
|
||||
|
||||
tlog0 << "Thread listening for " << *cpc << " ended\n";
|
||||
listeningThreads--;
|
||||
delNull(cpc->handler);
|
||||
}
|
||||
|
||||
void CPregameServer::run()
|
||||
{
|
||||
startListeningThread(host);
|
||||
start_async_accept();
|
||||
|
||||
while(state == RUNNING)
|
||||
{
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> myLock(mx);
|
||||
while(toAnnounce.size())
|
||||
{
|
||||
processPack(toAnnounce.front());
|
||||
toAnnounce.pop_front();
|
||||
}
|
||||
|
||||
// //we end sending thread if we ordered all our connections to stop
|
||||
// ending = true;
|
||||
// BOOST_FOREACH(CPregameConnection *pc, connections)
|
||||
// if(!pc->sendStop)
|
||||
// ending = false;
|
||||
|
||||
if(state != RUNNING)
|
||||
{
|
||||
tlog0 << "Stopping listening for connections...\n";
|
||||
acceptor->close();
|
||||
}
|
||||
|
||||
if(acceptor)
|
||||
{
|
||||
acceptor->io_service().reset();
|
||||
acceptor->io_service().poll();
|
||||
}
|
||||
} //frees lock
|
||||
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(50));
|
||||
}
|
||||
|
||||
tlog0 << "Thread handling connections ended\n";
|
||||
|
||||
if(state == ENDING_AND_STARTING_GAME)
|
||||
{
|
||||
tlog0 << "Waiting for listening thread to finish...\n";
|
||||
while(listeningThreads) boost::this_thread::sleep(boost::posix_time::milliseconds(50));
|
||||
tlog0 << "Preparing new game\n";
|
||||
}
|
||||
}
|
||||
|
||||
CPregameServer::~CPregameServer()
|
||||
{
|
||||
delete acceptor;
|
||||
delete upcomingConnection;
|
||||
|
||||
BOOST_FOREACH(CPackForSelectionScreen *pack, toAnnounce)
|
||||
delete pack;
|
||||
|
||||
toAnnounce.clear();
|
||||
|
||||
//TODO pregameconnections
|
||||
}
|
||||
|
||||
void CPregameServer::connectionAccepted(const boost::system::error_code& ec)
|
||||
{
|
||||
if(ec)
|
||||
{
|
||||
tlog0 << "Something wrong during accepting: " << ec.message() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
tlog0 << "We got a new connection! :)\n";
|
||||
CConnection *pc = new CConnection(upcomingConnection, NAME);
|
||||
initConnection(pc);
|
||||
upcomingConnection = NULL;
|
||||
|
||||
*pc << (ui8)pc->connectionID << curmap;
|
||||
|
||||
startListeningThread(pc);
|
||||
|
||||
announceTxt(pc->name + " joins the game");
|
||||
PlayerJoined *pj = new PlayerJoined();
|
||||
pj->playerName = pc->name;
|
||||
pj->connectionID = pc->connectionID;
|
||||
toAnnounce.push_back(pj);
|
||||
|
||||
start_async_accept();
|
||||
}
|
||||
|
||||
void CPregameServer::start_async_accept()
|
||||
{
|
||||
assert(!upcomingConnection);
|
||||
assert(acceptor);
|
||||
|
||||
upcomingConnection = new TSocket(acceptor->io_service());
|
||||
acceptor->async_accept(*upcomingConnection, boost::bind(&CPregameServer::connectionAccepted, this, boost::asio::placeholders::error));
|
||||
}
|
||||
|
||||
void CPregameServer::announceTxt(const std::string &txt, const std::string &playerName /*= "system"*/)
|
||||
{
|
||||
tlog0 << playerName << " says: " << txt << std::endl;
|
||||
ChatMessage cm;
|
||||
cm.playerName = playerName;
|
||||
cm.message = txt;
|
||||
|
||||
boost::unique_lock<boost::recursive_mutex> queueLock(mx);
|
||||
toAnnounce.push_front(new ChatMessage(cm));
|
||||
}
|
||||
|
||||
void CPregameServer::announcePack(const CPackForSelectionScreen &pack)
|
||||
{
|
||||
BOOST_FOREACH(CConnection *pc, connections)
|
||||
sendPack(pc, pack);
|
||||
}
|
||||
|
||||
void CPregameServer::sendPack(CConnection * pc, const CPackForSelectionScreen & pack)
|
||||
{
|
||||
if(!pc->sendStop)
|
||||
{
|
||||
tlog0 << "\tSending pack of type " << typeid(pack).name() << " to " << *pc << std::endl;
|
||||
*pc << &pack;
|
||||
}
|
||||
|
||||
if(dynamic_cast<const QuitMenuWithoutStarting*>(&pack))
|
||||
{
|
||||
pc->sendStop = true;
|
||||
}
|
||||
else if(dynamic_cast<const StartWithCurrentSettings*>(&pack))
|
||||
{
|
||||
pc->sendStop = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CPregameServer::processPack(CPackForSelectionScreen * pack)
|
||||
{
|
||||
if(dynamic_cast<CPregamePackToHost*>(pack))
|
||||
{
|
||||
sendPack(host, *pack);
|
||||
}
|
||||
else if(SelectMap *sm = dynamic_cast<SelectMap*>(pack))
|
||||
{
|
||||
delNull(curmap);
|
||||
curmap = sm->mapInfo;
|
||||
sm->free = false;
|
||||
announcePack(*pack);
|
||||
}
|
||||
else if(UpdateStartOptions *uso = dynamic_cast<UpdateStartOptions*>(pack))
|
||||
{
|
||||
delNull(curStartInfo);
|
||||
curStartInfo = uso->options;
|
||||
uso->free = false;
|
||||
announcePack(*pack);
|
||||
}
|
||||
else if(dynamic_cast<const StartWithCurrentSettings*>(pack))
|
||||
{
|
||||
state = ENDING_AND_STARTING_GAME;
|
||||
announcePack(*pack);
|
||||
}
|
||||
else
|
||||
announcePack(*pack);
|
||||
|
||||
delete pack;
|
||||
}
|
||||
|
||||
void CPregameServer::initConnection(CConnection *c)
|
||||
{
|
||||
*c >> c->name;
|
||||
connections.insert(c);
|
||||
tlog0 << "Pregame connection with player " << c->name << " established!" << std::endl;
|
||||
}
|
||||
|
||||
void CPregameServer::startListeningThread(CConnection * pc)
|
||||
{
|
||||
listeningThreads++;
|
||||
pc->handler = new boost::thread(&CPregameServer::handleConnection, this, pc);
|
||||
}
|
||||
|
||||
CVCMIServer::CVCMIServer()
|
||||
: io(new io_service()), acceptor(new tcp::acceptor(*io, tcp::endpoint(tcp::v4(), port)))
|
||||
: io(new io_service()), acceptor(new TAcceptor(*io, tcp::endpoint(tcp::v4(), port))), firstConnection(NULL)
|
||||
{
|
||||
tlog4 << "CVCMIServer created!" <<std::endl;
|
||||
}
|
||||
@ -64,64 +316,75 @@ CVCMIServer::~CVCMIServer()
|
||||
//delete acceptor;
|
||||
}
|
||||
|
||||
void CVCMIServer::newGame(CConnection *c)
|
||||
CGameHandler * CVCMIServer::initGhFromHostingConnection(CConnection &c)
|
||||
{
|
||||
CGameHandler gh;
|
||||
boost::system::error_code error;
|
||||
StartInfo *si = new StartInfo;
|
||||
ui8 clients;
|
||||
*c >> clients; //how many clients should be connected - TODO: support more than one
|
||||
*c >> *si; //get start options
|
||||
CGameHandler *gh = new CGameHandler();
|
||||
StartInfo si;
|
||||
c >> si; //get start options
|
||||
int problem;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
FILE *f;
|
||||
problem = fopen_s(&f,si->mapname.c_str(),"r");
|
||||
problem = fopen_s(&f,si.mapname.c_str(),"r");
|
||||
#else
|
||||
FILE * f = fopen(si->mapname.c_str(),"r");
|
||||
FILE * f = fopen(si.mapname.c_str(),"r");
|
||||
problem = !f;
|
||||
#endif
|
||||
if(problem && si->mode == StartInfo::NEW_GAME) //TODO some checking for campaigns
|
||||
|
||||
if(problem && si.mode == StartInfo::NEW_GAME) //TODO some checking for campaigns
|
||||
{
|
||||
*c << ui8(problem); //WRONG!
|
||||
return;
|
||||
c << ui8(problem); //WRONG!
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(f)
|
||||
fclose(f);
|
||||
*c << ui8(0); //OK!
|
||||
c << ui8(0); //OK!
|
||||
}
|
||||
|
||||
StartInfo startInfoCpy = *si;
|
||||
gh.init(si,rand());
|
||||
c->addStdVecItems(gh.gs);
|
||||
gh->init(&si,std::clock());
|
||||
c.addStdVecItems(gh->gs);
|
||||
gh->conns.insert(&c);
|
||||
|
||||
CConnection* cc; //tcp::socket * ss;
|
||||
for(int i=0; i<clients; i++)
|
||||
{
|
||||
if(!i)
|
||||
{
|
||||
cc=c;
|
||||
}
|
||||
else
|
||||
{
|
||||
tcp::socket * s = new tcp::socket(acceptor->io_service());
|
||||
acceptor->accept(*s,error);
|
||||
if(error) //retry
|
||||
{
|
||||
tlog3<<"Cannot establish connection - retrying..." << std::endl;
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
cc = new CConnection(s,NAME);
|
||||
cc->addStdVecItems(gh.gs);
|
||||
}
|
||||
gh.conns.insert(cc);
|
||||
}
|
||||
|
||||
gh.run(false, &startInfoCpy);
|
||||
return gh;
|
||||
}
|
||||
|
||||
void CVCMIServer::newGame()
|
||||
{
|
||||
CConnection &c = *firstConnection;
|
||||
ui8 clients;
|
||||
c >> clients; //how many clients should be connected
|
||||
assert(clients == 1); //multi goes now by newPregame, TODO: custom lobbies
|
||||
|
||||
CGameHandler *gh = initGhFromHostingConnection(c);
|
||||
gh->run(false);
|
||||
delNull(gh);
|
||||
}
|
||||
|
||||
void CVCMIServer::newPregame()
|
||||
{
|
||||
CPregameServer *cps = new CPregameServer(firstConnection, acceptor);
|
||||
cps->run();
|
||||
if(cps->state == CPregameServer::ENDING_WITHOUT_START)
|
||||
{
|
||||
delete cps;
|
||||
return;
|
||||
}
|
||||
|
||||
if(cps->state == CPregameServer::ENDING_AND_STARTING_GAME)
|
||||
{
|
||||
CGameHandler gh;
|
||||
gh.conns = cps->connections;
|
||||
gh.init(cps->curStartInfo,std::clock());
|
||||
|
||||
BOOST_FOREACH(CConnection *c, gh.conns)
|
||||
c->addStdVecItems(gh.gs);
|
||||
|
||||
gh.run(false);
|
||||
}
|
||||
}
|
||||
|
||||
void CVCMIServer::start()
|
||||
{
|
||||
ServerReady *sr = NULL;
|
||||
@ -147,6 +410,7 @@ void CVCMIServer::start()
|
||||
boost::thread acc(boost::bind(vaccept,acceptor,s,&error));
|
||||
sr->setToTrueAndNotify();
|
||||
delete mr;
|
||||
|
||||
acc.join();
|
||||
if (error)
|
||||
{
|
||||
@ -154,39 +418,44 @@ void CVCMIServer::start()
|
||||
return;
|
||||
}
|
||||
tlog0<<"We've accepted someone... " << std::endl;
|
||||
CConnection *connection = new CConnection(s,NAME);
|
||||
firstConnection = new CConnection(s,NAME);
|
||||
tlog0<<"Got connection!" << std::endl;
|
||||
while(!end2)
|
||||
{
|
||||
ui8 mode;
|
||||
*connection >> mode;
|
||||
*firstConnection >> mode;
|
||||
switch (mode)
|
||||
{
|
||||
case 0:
|
||||
connection->socket->close();
|
||||
firstConnection->close();
|
||||
exit(0);
|
||||
break;
|
||||
case 1:
|
||||
connection->socket->close();
|
||||
firstConnection->close();
|
||||
return;
|
||||
break;
|
||||
case 2:
|
||||
newGame(connection);
|
||||
newGame();
|
||||
break;
|
||||
case 3:
|
||||
loadGame(connection);
|
||||
loadGame();
|
||||
break;
|
||||
case 4:
|
||||
newPregame();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CVCMIServer::loadGame( CConnection *c )
|
||||
void CVCMIServer::loadGame()
|
||||
{
|
||||
CConnection &c = *firstConnection;
|
||||
std::string fname;
|
||||
CGameHandler gh;
|
||||
boost::system::error_code error;
|
||||
ui8 clients;
|
||||
*c >> clients >> fname; //how many clients should be connected - TODO: support more than one
|
||||
|
||||
c >> clients >> fname; //how many clients should be connected - TODO: support more than one
|
||||
|
||||
{
|
||||
ui32 ver;
|
||||
@ -202,7 +471,7 @@ void CVCMIServer::loadGame( CConnection *c )
|
||||
tlog0 <<"Reading handlers"<<std::endl;
|
||||
|
||||
lf >> (gh.gs);
|
||||
c->addStdVecItems(gh.gs);
|
||||
c.addStdVecItems(gh.gs);
|
||||
tlog0 <<"Reading gamestate"<<std::endl;
|
||||
}
|
||||
|
||||
@ -211,14 +480,14 @@ void CVCMIServer::loadGame( CConnection *c )
|
||||
lf >> gh;
|
||||
}
|
||||
|
||||
*c << ui8(0);
|
||||
c << ui8(0);
|
||||
|
||||
CConnection* cc; //tcp::socket * ss;
|
||||
for(int i=0; i<clients; i++)
|
||||
{
|
||||
if(!i)
|
||||
{
|
||||
cc=c;
|
||||
cc = &c;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define __CVCMISERVER_H__
|
||||
#include "../global.h"
|
||||
#include <set>
|
||||
#include <boost/thread/recursive_mutex.hpp>
|
||||
|
||||
/*
|
||||
* CVCMIServer.h, part of VCMI engine
|
||||
@ -13,34 +14,90 @@
|
||||
*
|
||||
*/
|
||||
|
||||
class CMapInfo;
|
||||
|
||||
class CConnection;
|
||||
class CPackForSelectionScreen;
|
||||
class CGameHandler;
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace asio
|
||||
{
|
||||
class io_service;
|
||||
namespace ip
|
||||
{
|
||||
class tcp;
|
||||
}
|
||||
class io_service;
|
||||
|
||||
template <typename Protocol> class stream_socket_service;
|
||||
template <typename Protocol,typename StreamSocketService>
|
||||
class basic_stream_socket;
|
||||
|
||||
template <typename Protocol> class socket_acceptor_service;
|
||||
template <typename Protocol,typename SocketAcceptorService>
|
||||
class basic_socket_acceptor;
|
||||
}
|
||||
};
|
||||
|
||||
typedef boost::asio::basic_socket_acceptor<boost::asio::ip::tcp, boost::asio::socket_acceptor_service<boost::asio::ip::tcp> > TAcceptor;
|
||||
typedef boost::asio::basic_stream_socket < boost::asio::ip::tcp , boost::asio::stream_socket_service<boost::asio::ip::tcp> > TSocket;
|
||||
|
||||
class CVCMIServer
|
||||
{
|
||||
boost::asio::io_service *io;
|
||||
boost::asio::basic_socket_acceptor<boost::asio::ip::tcp, boost::asio::socket_acceptor_service<boost::asio::ip::tcp> > * acceptor;
|
||||
std::map<int,CConnection*> connections;
|
||||
std::set<CConnection*> conns;
|
||||
TAcceptor * acceptor;
|
||||
|
||||
CConnection *firstConnection;
|
||||
public:
|
||||
CVCMIServer(); //c-tor
|
||||
~CVCMIServer(); //d-tor
|
||||
void setUpConnection(CConnection *c, std::string mapname, si32 checksum);
|
||||
void newGame(CConnection *c);
|
||||
void loadGame(CConnection *c);
|
||||
|
||||
void start();
|
||||
CGameHandler *initGhFromHostingConnection(CConnection &c);
|
||||
|
||||
void newGame();
|
||||
void loadGame();
|
||||
void newPregame();
|
||||
};
|
||||
|
||||
class CPregameServer
|
||||
{
|
||||
public:
|
||||
CConnection *host;
|
||||
int listeningThreads;
|
||||
std::set<CConnection *> connections;
|
||||
std::list<CPackForSelectionScreen*> toAnnounce;
|
||||
boost::recursive_mutex mx;
|
||||
|
||||
//std::vector<CMapInfo> maps;
|
||||
TAcceptor *acceptor;
|
||||
TSocket *upcomingConnection;
|
||||
|
||||
const CMapInfo *curmap;
|
||||
StartInfo *curStartInfo;
|
||||
|
||||
CPregameServer(CConnection *Host, TAcceptor *Acceptor = NULL);
|
||||
~CPregameServer();
|
||||
|
||||
void run();
|
||||
|
||||
void processPack(CPackForSelectionScreen * pack);
|
||||
void handleConnection(CConnection *cpc);
|
||||
void connectionAccepted(const boost::system::error_code& ec);
|
||||
void initConnection(CConnection *c);
|
||||
|
||||
void start_async_accept();
|
||||
|
||||
enum { INVALID, RUNNING, ENDING_WITHOUT_START, ENDING_AND_STARTING_GAME
|
||||
} state;
|
||||
|
||||
void announceTxt(const std::string &txt, const std::string &playerName = "system");
|
||||
void announcePack(const CPackForSelectionScreen &pack);
|
||||
|
||||
void sendPack(CConnection * pc, const CPackForSelectionScreen & pack);
|
||||
void startListeningThread(CConnection * pc);
|
||||
};
|
||||
|
||||
|
||||
#endif // __CVCMISERVER_H__
|
||||
|
Loading…
Reference in New Issue
Block a user