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
|
si8 bonus; //usees enum type Ebonus
|
||||||
ui8 color; //from 0 -
|
ui8 color; //from 0 -
|
||||||
ui8 handicap;//0-no, 1-mild, 2-severe
|
ui8 handicap;//0-no, 1-mild, 2-severe
|
||||||
|
|
||||||
std::string name;
|
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)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & castle;
|
h & castle;
|
||||||
@ -51,15 +52,15 @@ struct PlayerSettings
|
|||||||
|
|
||||||
struct StartInfo
|
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
|
ui8 difficulty; //0=easy; 4=impossible
|
||||||
std::map<int, PlayerSettings> playerInfos; //color indexed
|
std::map<int, PlayerSettings> playerInfos; //color indexed
|
||||||
ui8 turnTime; //in minutes, 0=unlimited
|
ui8 turnTime; //in minutes, 0=unlimited
|
||||||
std::string mapname;
|
std::string mapname;
|
||||||
ui8 whichMapInCampaign; //used only for mode 2
|
ui8 whichMapInCampaign; //used only for mode CAMPAIGN
|
||||||
ui8 choosenCampaignBonus; //used only for mode 2
|
ui8 choosenCampaignBonus; //used only for mode CAMPAIGN
|
||||||
PlayerSettings & getIthPlayersSettings(int no)
|
PlayerSettings & getIthPlayersSettings(int no)
|
||||||
{
|
{
|
||||||
if(playerInfos.find(no) != playerInfos.end())
|
if(playerInfos.find(no) != playerInfos.end())
|
||||||
@ -68,10 +69,10 @@ struct StartInfo
|
|||||||
throw std::string("Cannot find info about player");
|
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)
|
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 &it->second;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -87,6 +88,11 @@ struct StartInfo
|
|||||||
h & whichMapInCampaign;
|
h & whichMapInCampaign;
|
||||||
h & choosenCampaignBonus;
|
h & choosenCampaignBonus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StartInfo()
|
||||||
|
{
|
||||||
|
mode = INVALID;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -670,4 +670,9 @@ void CSlider::keyPressed(const SDL_KeyboardEvent & key)
|
|||||||
}
|
}
|
||||||
|
|
||||||
moveTo(moveDest);
|
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,
|
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
|
int Value=0, bool Horizontal=true, int style = 0); //style 0 - brown, 1 - blue
|
||||||
~CSlider();
|
~CSlider();
|
||||||
|
void moveToMax();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __ADVENTUREMAPBUTTON_H__
|
#endif // __ADVENTUREMAPBUTTON_H__
|
||||||
|
@ -110,7 +110,7 @@ void init()
|
|||||||
tlog0 << "\tInitializing minors: " << pomtime.getDif() << std::endl;
|
tlog0 << "\tInitializing minors: " << pomtime.getDif() << std::endl;
|
||||||
{
|
{
|
||||||
//read system options
|
//read system options
|
||||||
CLoadFile settings(GVCMIDirs.UserPath + "/config/sysopts.bin", false);
|
CLoadFile settings(GVCMIDirs.UserPath + "/config/sysopts.bin", 727);
|
||||||
if(settings.sfile)
|
if(settings.sfile)
|
||||||
{
|
{
|
||||||
settings >> GDefaultOptions;
|
settings >> GDefaultOptions;
|
||||||
@ -282,6 +282,17 @@ int main(int argc, char** argv)
|
|||||||
return 0;
|
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)
|
void processCommand(const std::string &message)
|
||||||
{
|
{
|
||||||
std::istringstream readed;
|
std::istringstream readed;
|
||||||
@ -452,6 +463,16 @@ void processCommand(const std::string &message)
|
|||||||
{
|
{
|
||||||
LOCPLINT->showingDialog->setn(false);
|
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
|
else if(client && client->serv && client->serv->connected) //send to server
|
||||||
{
|
{
|
||||||
PlayerMessage pm(LOCPLINT->playerID,message);
|
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)
|
//plays intro, ends when intro is over or button has been pressed (handles events)
|
||||||
void playIntro()
|
void playIntro()
|
||||||
{
|
{
|
||||||
@ -623,7 +643,7 @@ static void listenForEvents()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void startGame(StartInfo * options)
|
void startGame(StartInfo * options, CConnection *serv/* = NULL*/)
|
||||||
{
|
{
|
||||||
GH.curInt =NULL;
|
GH.curInt =NULL;
|
||||||
if(gOnlyAI)
|
if(gOnlyAI)
|
||||||
@ -655,7 +675,7 @@ void startGame(StartInfo * options)
|
|||||||
{
|
{
|
||||||
case StartInfo::NEW_GAME:
|
case StartInfo::NEW_GAME:
|
||||||
case StartInfo::CAMPAIGN:
|
case StartInfo::CAMPAIGN:
|
||||||
client->newGame(NULL, options);
|
client->newGame(serv, options);
|
||||||
break;
|
break;
|
||||||
case StartInfo::LOAD_GAME:
|
case StartInfo::LOAD_GAME:
|
||||||
std::string fname = options->mapname;
|
std::string fname = options->mapname;
|
||||||
|
@ -1917,6 +1917,14 @@ SystemOptions::SystemOptions()
|
|||||||
animSpeed = 2;
|
animSpeed = 2;
|
||||||
printMouseShadow = true;
|
printMouseShadow = true;
|
||||||
showQueue = true;
|
showQueue = true;
|
||||||
|
|
||||||
|
playerName = "Player";
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemOptions::setPlayerName(const std::string &newPlayerName)
|
||||||
|
{
|
||||||
|
playerName = newPlayerName;
|
||||||
|
settingsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPlayerInterface::eraseCurrentPathOf( const CGHeroInstance * ho, bool checkForExistanceOfPath /*= true */ )
|
void CPlayerInterface::eraseCurrentPathOf( const CGHeroInstance * ho, bool checkForExistanceOfPath /*= true */ )
|
||||||
|
@ -76,6 +76,7 @@ namespace boost
|
|||||||
|
|
||||||
struct SystemOptions
|
struct SystemOptions
|
||||||
{
|
{
|
||||||
|
std::string playerName;
|
||||||
|
|
||||||
ui8 heroMoveSpeed;/*, enemyMoveSpeed*/ //speed of player's hero movement
|
ui8 heroMoveSpeed;/*, enemyMoveSpeed*/ //speed of player's hero movement
|
||||||
ui8 mapScrollingSpeed; //map scrolling speed
|
ui8 mapScrollingSpeed; //map scrolling speed
|
||||||
@ -94,13 +95,14 @@ struct SystemOptions
|
|||||||
void setMapScrollingSpeed(int newSpeed); //set the member above
|
void setMapScrollingSpeed(int newSpeed); //set the member above
|
||||||
void setMusicVolume(int newVolume);
|
void setMusicVolume(int newVolume);
|
||||||
void setSoundVolume(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 settingsChanged(); //updates file with "default" settings for next running of application
|
||||||
void apply();
|
void apply();
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
|
h & playerName;
|
||||||
h & heroMoveSpeed & mapScrollingSpeed & musicVolume & soundVolume;
|
h & heroMoveSpeed & mapScrollingSpeed & musicVolume & soundVolume;
|
||||||
|
|
||||||
h & printCellBorders & printStackRange & animSpeed & printMouseShadow & showQueue;
|
h & printCellBorders & printStackRange & animSpeed & printMouseShadow & showQueue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
1272
client/CPreGame.cpp
1272
client/CPreGame.cpp
File diff suppressed because it is too large
Load Diff
@ -6,6 +6,7 @@
|
|||||||
#include "../StartInfo.h"
|
#include "../StartInfo.h"
|
||||||
#include "GUIBase.h"
|
#include "GUIBase.h"
|
||||||
#include "FunctionList.h"
|
#include "FunctionList.h"
|
||||||
|
#include "../lib/CMapInfo.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CPreGame.h, part of VCMI engine
|
* CPreGame.h, part of VCMI engine
|
||||||
@ -26,27 +27,10 @@ class CGStatusBar;
|
|||||||
class CTextBox;
|
class CTextBox;
|
||||||
class CCampaignState;
|
class CCampaignState;
|
||||||
class CConnection;
|
class CConnection;
|
||||||
|
class CPackForSelectionScreen;
|
||||||
|
class PlayerInfo;
|
||||||
|
|
||||||
class CMapInfo
|
namespace boost{ class thread; class recursive_mutex;}
|
||||||
{
|
|
||||||
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();
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ESortBy{_playerAm, _size, _format, _name, _viccon, _loscon, _numOfMaps}; //_numOfMaps is for campaigns
|
enum ESortBy{_playerAm, _size, _format, _name, _viccon, _loscon, _numOfMaps}; //_numOfMaps is for campaigns
|
||||||
|
|
||||||
@ -66,7 +50,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum EMultiMode {
|
enum EMultiMode {
|
||||||
SINGLE_PLAYER = 0, HOT_SEAT, MULTI_PLAYER
|
SINGLE_PLAYER = 0, MULTI_HOT_SEAT, MULTI_NETWORK_HOST, MULTI_NETWORK_GUEST
|
||||||
};
|
};
|
||||||
|
|
||||||
CPicture *bgAd;
|
CPicture *bgAd;
|
||||||
@ -94,6 +78,10 @@ public:
|
|||||||
CTextInput *inputBox;
|
CTextInput *inputBox;
|
||||||
|
|
||||||
CChatBox(const Rect &rect);
|
CChatBox(const Rect &rect);
|
||||||
|
|
||||||
|
void keyPressed(const SDL_KeyboardEvent & key);
|
||||||
|
|
||||||
|
void addNewMessage(const std::string &text);
|
||||||
};
|
};
|
||||||
|
|
||||||
class InfoCard : public CIntObject
|
class InfoCard : public CIntObject
|
||||||
@ -102,9 +90,11 @@ class InfoCard : public CIntObject
|
|||||||
public:
|
public:
|
||||||
CMenuScreen::EState type;
|
CMenuScreen::EState type;
|
||||||
|
|
||||||
|
bool network;
|
||||||
bool chatOn; //if chat is shown, then description is hidden
|
bool chatOn; //if chat is shown, then description is hidden
|
||||||
CTextBox *mapDescription;
|
CTextBox *mapDescription;
|
||||||
CChatBox *chat;
|
CChatBox *chat;
|
||||||
|
CPicture *playerListBg;
|
||||||
|
|
||||||
CHighlightableButtonsGroup *difficulty;
|
CHighlightableButtonsGroup *difficulty;
|
||||||
CDefHandler *sizes, *sFlags;;
|
CDefHandler *sizes, *sFlags;;
|
||||||
@ -115,7 +105,7 @@ public:
|
|||||||
void showTeamsPopup();
|
void showTeamsPopup();
|
||||||
void toggleChat();
|
void toggleChat();
|
||||||
void setChat(bool activateChat);
|
void setChat(bool activateChat);
|
||||||
InfoCard(CMenuScreen::EState Type, bool network = false);
|
InfoCard(bool Network = false);
|
||||||
~InfoCard();
|
~InfoCard();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -159,7 +149,7 @@ public:
|
|||||||
void clickLeft(tribool down, bool previousState);
|
void clickLeft(tribool down, bool previousState);
|
||||||
void keyPressed(const SDL_KeyboardEvent & key);
|
void keyPressed(const SDL_KeyboardEvent & key);
|
||||||
void onDoubleClick();
|
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();
|
~SelectionTab();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -183,6 +173,7 @@ public:
|
|||||||
|
|
||||||
struct PlayerOptionsEntry : public CIntObject
|
struct PlayerOptionsEntry : public CIntObject
|
||||||
{
|
{
|
||||||
|
PlayerInfo π
|
||||||
PlayerSettings &s;
|
PlayerSettings &s;
|
||||||
CPicture *bg;
|
CPicture *bg;
|
||||||
AdventureMapButton *btns[6]; //left and right for town, hero, bonus
|
AdventureMapButton *btns[6]; //left and right for town, hero, bonus
|
||||||
@ -190,18 +181,25 @@ public:
|
|||||||
SelectedBox *town;
|
SelectedBox *town;
|
||||||
SelectedBox *hero;
|
SelectedBox *hero;
|
||||||
SelectedBox *bonus;
|
SelectedBox *bonus;
|
||||||
bool fixedHero;
|
|
||||||
enum {HUMAN_OR_CPU, HUMAN, CPU} whoCanPlay;
|
enum {HUMAN_OR_CPU, HUMAN, CPU} whoCanPlay;
|
||||||
|
|
||||||
PlayerOptionsEntry(OptionsTab *owner, PlayerSettings &S);
|
PlayerOptionsEntry(OptionsTab *owner, PlayerSettings &S);
|
||||||
void selectButtons(bool onlyHero = true); //hides unavailable buttons
|
void selectButtons(bool onlyHero = true); //hides unavailable buttons
|
||||||
void showAll(SDL_Surface * to);
|
void showAll(SDL_Surface * to);
|
||||||
};
|
};
|
||||||
CMenuScreen::EState type;
|
|
||||||
CSlider *turnDuration;
|
CSlider *turnDuration;
|
||||||
|
|
||||||
std::set<int> usedHeroes;
|
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
|
std::map<int, PlayerOptionsEntry *> entries; //indexed by color
|
||||||
|
|
||||||
void nextCastle(int player, int dir); //dir == -1 or +1
|
void nextCastle(int player, int dir); //dir == -1 or +1
|
||||||
@ -210,8 +208,8 @@ public:
|
|||||||
void setTurnLength(int npos);
|
void setTurnLength(int npos);
|
||||||
void flagPressed(int player);
|
void flagPressed(int player);
|
||||||
|
|
||||||
void changeSelection(const CMapHeader *to);
|
void recreate();
|
||||||
OptionsTab(CMenuScreen::EState Type/*, StartInfo &Opts*/);
|
OptionsTab();
|
||||||
~OptionsTab();
|
~OptionsTab();
|
||||||
void showAll(SDL_Surface * to);
|
void showAll(SDL_Surface * to);
|
||||||
|
|
||||||
@ -220,7 +218,32 @@ public:
|
|||||||
bool canUseThisHero( int ID );
|
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:
|
public:
|
||||||
CPicture *bg; //general bg image
|
CPicture *bg; //general bg image
|
||||||
@ -229,25 +252,33 @@ public:
|
|||||||
AdventureMapButton *start, *back;
|
AdventureMapButton *start, *back;
|
||||||
|
|
||||||
SelectionTab *sel;
|
SelectionTab *sel;
|
||||||
CMenuScreen::EState type; //new/save/load#Game
|
|
||||||
const CMapInfo *current;
|
|
||||||
StartInfo sInfo;
|
|
||||||
CIntObject *curTab;
|
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
|
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();
|
~CSelectionScreen();
|
||||||
void toggleTab(CIntObject *tab);
|
void toggleTab(CIntObject *tab);
|
||||||
void changeSelection(const CMapInfo *to);
|
void changeSelection(const CMapInfo *to);
|
||||||
static void updateStartInfo( const CMapInfo * to, StartInfo & sInfo, const CMapHeader * mapHeader );
|
|
||||||
void startCampaign();
|
void startCampaign();
|
||||||
void startGame();
|
void startGame();
|
||||||
void difficultyChange(int to);
|
void difficultyChange(int to);
|
||||||
|
|
||||||
void toggleChat();
|
|
||||||
void handleConnection();
|
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
|
class CSavingScreen : public CSelectionScreen
|
||||||
@ -260,7 +291,8 @@ public:
|
|||||||
~CSavingScreen();
|
~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:
|
public:
|
||||||
AdventureMapButton *back;
|
AdventureMapButton *back;
|
||||||
@ -386,10 +418,8 @@ public:
|
|||||||
CGPreGame();
|
CGPreGame();
|
||||||
~CGPreGame();
|
~CGPreGame();
|
||||||
void update();
|
void update();
|
||||||
void run();
|
|
||||||
void openSel(CMenuScreen::EState type, CMenuScreen::EMultiMode multi = CMenuScreen::SINGLE_PLAYER);
|
void openSel(CMenuScreen::EState type, CMenuScreen::EMultiMode multi = CMenuScreen::SINGLE_PLAYER);
|
||||||
|
|
||||||
void resetPlayerNames();
|
|
||||||
void loadGraphics();
|
void loadGraphics();
|
||||||
void disposeGraphics();
|
void disposeGraphics();
|
||||||
};
|
};
|
||||||
|
@ -309,37 +309,57 @@ int CClient::getSelectedHero()
|
|||||||
|
|
||||||
void CClient::newGame( CConnection *con, StartInfo *si )
|
void CClient::newGame( CConnection *con, StartInfo *si )
|
||||||
{
|
{
|
||||||
|
enum {SINGLE, HOST, GUEST} networkMode = SINGLE;
|
||||||
|
std::set<ui8> myPlayers;
|
||||||
|
|
||||||
if (con == NULL)
|
if (con == NULL)
|
||||||
{
|
{
|
||||||
CServerHandler sh;
|
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;
|
timeHandler tmh;
|
||||||
CGI->state = new CGameState();
|
CGI->state = new CGameState();
|
||||||
tlog0 <<"\tGamestate: "<<tmh.getDif()<<std::endl;
|
tlog0 <<"\tGamestate: "<<tmh.getDif()<<std::endl;
|
||||||
serv = con;
|
CConnection &c(*serv);
|
||||||
CConnection &c(*con);
|
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
ui8 pom8;
|
|
||||||
c << ui8(2) << ui8(1); //new game; one client
|
if(networkMode == SINGLE)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
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;
|
ui32 seed, sum;
|
||||||
delete si;
|
|
||||||
c >> si >> sum >> seed;
|
c >> si >> sum >> seed;
|
||||||
tlog0 <<"\tSending/Getting info to/from the server: "<<tmh.getDif()<<std::endl;
|
tlog0 <<"\tSending/Getting info to/from the server: "<<tmh.getDif()<<std::endl;
|
||||||
tlog0 << "\tUsing random seed: "<<seed << 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
|
it != gs->scenarioOps->playerInfos.end(); ++it)//initializing interfaces for players
|
||||||
{
|
{
|
||||||
ui8 color = it->first;
|
ui8 color = it->first;
|
||||||
|
if(!vstd::contains(myPlayers, color))
|
||||||
|
continue;
|
||||||
|
|
||||||
CCallback *cb = new CCallback(gs,color,this);
|
CCallback *cb = new CCallback(gs,color,this);
|
||||||
if(!it->second.human)
|
if(!it->second.human)
|
||||||
{
|
{
|
||||||
@ -524,27 +547,15 @@ CConnection * CServerHandler::connectToServer()
|
|||||||
waitForServer();
|
waitForServer();
|
||||||
|
|
||||||
th.update();
|
th.update();
|
||||||
CConnection *ret = NULL;
|
CConnection *ret = justConnectToServer(conf.cc.server, port);
|
||||||
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)
|
if(verbose)
|
||||||
tlog0<<"\tConnecting to the server: "<<th.getDif()<<std::endl;
|
tlog0<<"\tConnecting to the server: "<<th.getDif()<<std::endl;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
CServerHandler::CServerHandler()
|
CServerHandler::CServerHandler(bool runServer /*= false*/)
|
||||||
{
|
{
|
||||||
serverThread = NULL;
|
serverThread = NULL;
|
||||||
shared = NULL;
|
shared = NULL;
|
||||||
@ -569,3 +580,24 @@ void CServerHandler::callServer()
|
|||||||
std::system(comm.c_str());
|
std::system(comm.c_str());
|
||||||
tlog0 << "Server finished\n";
|
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
|
bool verbose; //whether to print log msgs
|
||||||
std::string port; //port number in text form
|
std::string port; //port number in text form
|
||||||
|
|
||||||
|
//functions setting up local server
|
||||||
void startServer(); //creates a thread with callServer
|
void startServer(); //creates a thread with callServer
|
||||||
void waitForServer(); //waits till server is ready
|
void waitForServer(); //waits till server is ready
|
||||||
CConnection * connectToServer(); //connects to server
|
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();
|
~CServerHandler();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1669,7 +1669,7 @@ void CRecruitmentWindow::close()
|
|||||||
}
|
}
|
||||||
void CRecruitmentWindow::Max()
|
void CRecruitmentWindow::Max()
|
||||||
{
|
{
|
||||||
slider->moveTo(slider->amount);
|
slider->moveToMax();
|
||||||
}
|
}
|
||||||
void CRecruitmentWindow::Buy()
|
void CRecruitmentWindow::Buy()
|
||||||
{
|
{
|
||||||
@ -3172,7 +3172,7 @@ CMarketplaceWindow::~CMarketplaceWindow()
|
|||||||
|
|
||||||
void CMarketplaceWindow::setMax()
|
void CMarketplaceWindow::setMax()
|
||||||
{
|
{
|
||||||
slider->moveTo(slider->amount);
|
slider->moveToMax();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMarketplaceWindow::makeDeal()
|
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 = new CSlider(231,481,137,0,0,0);
|
||||||
slider->moved = boost::bind(&CAltarWindow::sliderMoved,this,_1);
|
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);
|
sacrificedUnits.resize(ARMY_SIZE, 0);
|
||||||
sacrificeAll = new AdventureMapButton(CGI->generaltexth->zelp[579],boost::bind(&CAltarWindow::SacrificeAll,this),393,520,"ALTARMY.DEF");
|
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;
|
focus = false;
|
||||||
pos += Pos;
|
pos += Pos;
|
||||||
|
captureAllKeys = true;
|
||||||
OBJ_CONSTRUCTION;
|
OBJ_CONSTRUCTION;
|
||||||
bg = new CPicture(bgName, bgOffset.x, bgOffset.y);
|
bg = new CPicture(bgName, bgOffset.x, bgOffset.y);
|
||||||
used = LCLICK | KEYBOARD;
|
used = LCLICK | KEYBOARD;
|
||||||
@ -6639,10 +6640,14 @@ CTextInput::CTextInput(const Rect &Pos, SDL_Surface *srf)
|
|||||||
{
|
{
|
||||||
focus = false;
|
focus = false;
|
||||||
pos += Pos;
|
pos += Pos;
|
||||||
|
captureAllKeys = true;
|
||||||
OBJ_CONSTRUCTION;
|
OBJ_CONSTRUCTION;
|
||||||
bg = new CPicture(Pos, 0, true);
|
bg = new CPicture(Pos, 0, true);
|
||||||
Rect hlp = Pos;
|
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.w = bg->pos.w;
|
||||||
pos.h = bg->pos.h;
|
pos.h = bg->pos.h;
|
||||||
bg->pos = pos;
|
bg->pos = pos;
|
||||||
|
@ -359,7 +359,7 @@ public:
|
|||||||
void setText(const std::string &nText, bool callCb = false);
|
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, 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();
|
~CTextInput();
|
||||||
void showAll(SDL_Surface * to);
|
void showAll(SDL_Surface * to);
|
||||||
void clickLeft(tribool down, bool previousState);
|
void clickLeft(tribool down, bool previousState);
|
||||||
|
@ -41,12 +41,12 @@
|
|||||||
|
|
||||||
void SetResources::applyCl( CClient *cl )
|
void SetResources::applyCl( CClient *cl )
|
||||||
{
|
{
|
||||||
cl->playerint[player]->receivedResource(-1,-1);
|
INTERFACE_CALL_IF_PRESENT(player,receivedResource,-1,-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetResource::applyCl( CClient *cl )
|
void SetResource::applyCl( CClient *cl )
|
||||||
{
|
{
|
||||||
cl->playerint[player]->receivedResource(resid,val);
|
INTERFACE_CALL_IF_PRESENT(player,receivedResource,resid,val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetPrimSkill::applyCl( CClient *cl )
|
void SetPrimSkill::applyCl( CClient *cl )
|
||||||
@ -698,7 +698,7 @@ void ShowInInfobox::applyCl(CClient *cl)
|
|||||||
{
|
{
|
||||||
SComponent sc(c);
|
SComponent sc(c);
|
||||||
text.toString(sc.description);
|
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);
|
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))
|
#define read_unaligned_u32(p) (* reinterpret_cast<const Uint32 *>(p))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//for explicit overrides
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define OVERRIDE override
|
||||||
|
#else
|
||||||
|
#define OVERRIDE //is there any working counterpart?
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // __GLOBAL_H__
|
#endif // __GLOBAL_H__
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "RegisterTypes.cpp"
|
#include "RegisterTypes.cpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
#include "CMapInfo.h"
|
||||||
|
|
||||||
boost::rand48 ran;
|
boost::rand48 ran;
|
||||||
class CGObjectInstance;
|
class CGObjectInstance;
|
||||||
@ -1057,14 +1058,15 @@ CGHeroInstance * CGameState::HeroesPool::pickHeroFor(bool native, int player, co
|
|||||||
int CGameState::pickHero(int owner)
|
int CGameState::pickHero(int owner)
|
||||||
{
|
{
|
||||||
int h=-1;
|
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;
|
return h;
|
||||||
int f = scenarioOps->getIthPlayersSettings(owner).castle;
|
int f = ps.castle;
|
||||||
int i=0;
|
int i=0;
|
||||||
do //try to find free hero of our faction
|
do //try to find free hero of our faction
|
||||||
{
|
{
|
||||||
i++;
|
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);
|
} 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
|
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 mx;
|
||||||
delete map;
|
delete map;
|
||||||
delete curB;
|
delete curB;
|
||||||
//delete scenarioOps;
|
delete scenarioOps;
|
||||||
delete applierGs;
|
delete applierGs;
|
||||||
delete objCaller;
|
delete objCaller;
|
||||||
|
|
||||||
@ -1503,7 +1505,7 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
|
|||||||
day = 0;
|
day = 0;
|
||||||
seed = Seed;
|
seed = Seed;
|
||||||
ran.seed((boost::int32_t)seed);
|
ran.seed((boost::int32_t)seed);
|
||||||
scenarioOps = si;
|
scenarioOps = new StartInfo(*si);
|
||||||
loadTownDInfos();
|
loadTownDInfos();
|
||||||
|
|
||||||
//pick grail location
|
//pick grail location
|
||||||
@ -1628,9 +1630,9 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
|
|||||||
map->objects.push_back(nnn);
|
map->objects.push_back(nnn);
|
||||||
map->addBlockVisTiles(nnn);
|
map->addBlockVisTiles(nnn);
|
||||||
//give campaign bonus
|
//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 =
|
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;
|
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
|
//give start resource bonus in case of campaign
|
||||||
if (si->mode == StartInfo::CAMPAIGN)
|
if (scenarioOps->mode == StartInfo::CAMPAIGN)
|
||||||
{
|
{
|
||||||
CScenarioTravel::STravelBonus chosenBonus =
|
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
|
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)
|
for (int b=0; b<people.size(); ++b)
|
||||||
{
|
{
|
||||||
std::vector<int> res; //resources we will give
|
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;
|
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 =
|
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
|
if (chosenBonus.isBonusForHero() && chosenBonus.info1 != 0xFFFE) //exclude generated heroes
|
||||||
{
|
{
|
||||||
//find human player
|
//find human player
|
||||||
@ -1856,7 +1858,7 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
|
|||||||
maxB = b;
|
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
|
else //specific hero
|
||||||
{
|
{
|
||||||
@ -1864,7 +1866,7 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
|
|||||||
{
|
{
|
||||||
if (heroes[b]->subID == chosenBonus.info1)
|
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;
|
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)
|
for(std::map<ui8, PlayerState>::iterator k=players.begin(); k!=players.end(); ++k)
|
||||||
{
|
{
|
||||||
//starting bonus
|
//starting bonus
|
||||||
if(si->playerInfos[k->first].bonus==PlayerSettings::brandom)
|
if(scenarioOps->playerInfos[k->first].bonus==PlayerSettings::brandom)
|
||||||
si->playerInfos[k->first].bonus = ran()%3;
|
scenarioOps->playerInfos[k->first].bonus = ran()%3;
|
||||||
switch(si->playerInfos[k->first].bonus)
|
switch(scenarioOps->playerInfos[k->first].bonus)
|
||||||
{
|
{
|
||||||
case PlayerSettings::bgold:
|
case PlayerSettings::bgold:
|
||||||
k->second.resources[6] += 500 + (ran()%6)*100;
|
k->second.resources[6] += 500 + (ran()%6)*100;
|
||||||
break;
|
break;
|
||||||
case PlayerSettings::bresource:
|
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)
|
if(res == 127)
|
||||||
{
|
{
|
||||||
k->second.resources[0] += 5 + ran()%6;
|
k->second.resources[0] += 5 + ran()%6;
|
||||||
@ -2035,10 +2037,10 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
|
|||||||
}
|
}
|
||||||
|
|
||||||
//campaign bonuses for towns
|
//campaign bonuses for towns
|
||||||
if (si->mode == StartInfo::CAMPAIGN)
|
if (scenarioOps->mode == StartInfo::CAMPAIGN)
|
||||||
{
|
{
|
||||||
CScenarioTravel::STravelBonus chosenBonus =
|
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)
|
if (chosenBonus.type == 2)
|
||||||
{
|
{
|
||||||
|
@ -71,6 +71,11 @@ void CConnection::init()
|
|||||||
tlog0 << "Established connection with "<<pom<<std::endl;
|
tlog0 << "Established connection with "<<pom<<std::endl;
|
||||||
wmx = new boost::mutex;
|
wmx = new boost::mutex;
|
||||||
rmx = 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)
|
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)
|
CConnection::~CConnection(void)
|
||||||
{
|
{
|
||||||
|
if(handler)
|
||||||
|
handler->join();
|
||||||
|
|
||||||
|
delete handler;
|
||||||
|
|
||||||
close();
|
close();
|
||||||
delete io_service;
|
delete io_service;
|
||||||
delete wmx;
|
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)
|
:sfile(NULL)
|
||||||
{
|
{
|
||||||
registerTypes(*this);
|
registerTypes(*this);
|
||||||
openNextFile(fname, requireLatest);
|
openNextFile(fname, minimalVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
CLoadFile::~CLoadFile()
|
CLoadFile::~CLoadFile()
|
||||||
@ -304,7 +314,7 @@ void CLoadFile::close()
|
|||||||
sfile = NULL;
|
sfile = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CLoadFile::openNextFile(const std::string &fname, bool requireLatest)
|
void CLoadFile::openNextFile(const std::string &fname, int minimalVersion)
|
||||||
{
|
{
|
||||||
fName = fname;
|
fName = fname;
|
||||||
sfile = new std::ifstream(fname.c_str(),std::ios::binary);
|
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))
|
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;
|
delete sfile;
|
||||||
sfile = NULL;
|
sfile = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
*this >> myVersion;
|
*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;
|
delete sfile;
|
||||||
sfile = NULL;
|
sfile = NULL;
|
||||||
}
|
}
|
||||||
@ -371,6 +381,11 @@ ui16 CTypeList::getTypeID( const std::type_info *type )
|
|||||||
return 0;
|
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()
|
CSerializer::~CSerializer()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
#include <boost/mpl/identity.hpp>
|
#include <boost/mpl/identity.hpp>
|
||||||
#include <boost/any.hpp>
|
#include <boost/any.hpp>
|
||||||
|
|
||||||
const ui32 version = 726;
|
const ui32 version = 727;
|
||||||
class CConnection;
|
class CConnection;
|
||||||
class CGObjectInstance;
|
class CGObjectInstance;
|
||||||
class CGameState;
|
class CGameState;
|
||||||
@ -824,12 +824,12 @@ public:
|
|||||||
std::string fName;
|
std::string fName;
|
||||||
std::ifstream *sfile;
|
std::ifstream *sfile;
|
||||||
|
|
||||||
CLoadFile(const std::string &fname, bool requireLatest = true);
|
CLoadFile(const std::string &fname, int minimalVersion = version);
|
||||||
~CLoadFile();
|
~CLoadFile();
|
||||||
int read(const void * data, unsigned size);
|
int read(const void * data, unsigned size);
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
void openNextFile(const std::string &fname, bool requireLatest);
|
void openNextFile(const std::string &fname, int minimalVersion);
|
||||||
void reportState(CLogger &out);
|
void reportState(CLogger &out);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -853,6 +853,12 @@ public:
|
|||||||
boost::asio::io_service *io_service;
|
boost::asio::io_service *io_service;
|
||||||
std::string name; //who uses this connection
|
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(std::string host, std::string port, std::string Name);
|
||||||
CConnection(TAcceptor * acceptor, boost::asio::io_service *Io_service, 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
|
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)
|
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>
|
template<typename T>
|
||||||
class CApplier
|
class CApplier
|
||||||
{
|
{
|
||||||
|
160
lib/NetPacks.h
160
lib/NetPacks.h
@ -24,6 +24,7 @@ class CConnection;
|
|||||||
class CCampaignState;
|
class CCampaignState;
|
||||||
class CArtifact;
|
class CArtifact;
|
||||||
class CSelectionScreen;
|
class CSelectionScreen;
|
||||||
|
class CMapInfo;
|
||||||
|
|
||||||
struct CPack
|
struct CPack
|
||||||
{
|
{
|
||||||
@ -1626,7 +1627,13 @@ struct CPackForSelectionScreen : public CPack
|
|||||||
void apply(CSelectionScreen *selScreen){}; //that functions are implemented in CPreGame.cpp
|
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;
|
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__
|
#endif //__NETPACKS_H__
|
||||||
|
@ -181,6 +181,15 @@ template<typename Serializer> DLL_EXPORT
|
|||||||
void registerTypes4(Serializer &s)
|
void registerTypes4(Serializer &s)
|
||||||
{
|
{
|
||||||
s.template registerType<ChatMessage>();
|
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
|
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),
|
mainHeroPortrait(0), hasMainTown(0), generateHeroAtMainTown(0),
|
||||||
team(255), generateHero(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)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & p7 & p8 & p9 & canHumanPlay & canComputerPlay & AITactic & allowedFactions & isFactionRandom &
|
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;
|
using namespace boost::posix_time;
|
||||||
BOOST_FOREACH(CConnection *cc, conns)
|
BOOST_FOREACH(CConnection *cc, conns)
|
||||||
{//init conn.
|
{//init conn.
|
||||||
ui8 quantity, pom;
|
ui32 quantity;
|
||||||
|
ui8 pom;
|
||||||
//ui32 seed;
|
//ui32 seed;
|
||||||
if(!resume)
|
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
|
(*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++)
|
for(int i=0;i<quantity;i++)
|
||||||
{
|
{
|
||||||
(*cc) >> pom; //read player color
|
(*cc) >> pom; //read player color
|
||||||
|
tlog0 << (int)pom << " ";
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::recursive_mutex> lock(gsm);
|
boost::unique_lock<boost::recursive_mutex> lock(gsm);
|
||||||
connections[pom] = cc;
|
connections[pom] = cc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
tlog0 << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(std::set<CConnection*>::iterator i = conns.begin(); i!=conns.end();i++)
|
for(std::set<CConnection*>::iterator i = conns.begin(); i!=conns.end();i++)
|
||||||
|
@ -219,7 +219,7 @@ public:
|
|||||||
void sendAndApply(SetResources * info);
|
void sendAndApply(SetResources * info);
|
||||||
void sendAndApply(NewStructures * info);
|
void sendAndApply(NewStructures * info);
|
||||||
|
|
||||||
void run(bool resume, const StartInfo *si = NULL);
|
void run(bool resume);
|
||||||
void newTurn();
|
void newTurn();
|
||||||
void handleAfterAttackCasting( const BattleAttack & bat );
|
void handleAfterAttackCasting( const BattleAttack & bat );
|
||||||
bool sacrificeArtifact(const IMarket * m, const CGHeroInstance * hero, ui32 artID);
|
bool sacrificeArtifact(const IMarket * m, const CGHeroInstance * hero, ui32 artID);
|
||||||
|
@ -28,6 +28,10 @@
|
|||||||
#include "../lib/VCMI_Lib.h"
|
#include "../lib/VCMI_Lib.h"
|
||||||
#include "../lib/VCMIDirs.h"
|
#include "../lib/VCMIDirs.h"
|
||||||
#include "CGameHandler.h"
|
#include "CGameHandler.h"
|
||||||
|
#include <boost/thread.hpp>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include "../lib/CMapInfo.h"
|
||||||
|
|
||||||
std::string NAME_AFFIX = "server";
|
std::string NAME_AFFIX = "server";
|
||||||
std::string NAME = NAME_VER + std::string(" (") + NAME_AFFIX + ')'; //application name
|
std::string NAME = NAME_VER + std::string(" (") + NAME_AFFIX + ')'; //application name
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
@ -53,8 +57,256 @@ static void vaccept(tcp::acceptor *ac, tcp::socket *s, boost::system::error_code
|
|||||||
ac->accept(*s,*error);
|
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()
|
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;
|
tlog4 << "CVCMIServer created!" <<std::endl;
|
||||||
}
|
}
|
||||||
@ -64,64 +316,75 @@ CVCMIServer::~CVCMIServer()
|
|||||||
//delete acceptor;
|
//delete acceptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CVCMIServer::newGame(CConnection *c)
|
CGameHandler * CVCMIServer::initGhFromHostingConnection(CConnection &c)
|
||||||
{
|
{
|
||||||
CGameHandler gh;
|
CGameHandler *gh = new CGameHandler();
|
||||||
boost::system::error_code error;
|
StartInfo si;
|
||||||
StartInfo *si = new StartInfo;
|
c >> si; //get start options
|
||||||
ui8 clients;
|
|
||||||
*c >> clients; //how many clients should be connected - TODO: support more than one
|
|
||||||
*c >> *si; //get start options
|
|
||||||
int problem;
|
int problem;
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
FILE *f;
|
FILE *f;
|
||||||
problem = fopen_s(&f,si->mapname.c_str(),"r");
|
problem = fopen_s(&f,si.mapname.c_str(),"r");
|
||||||
#else
|
#else
|
||||||
FILE * f = fopen(si->mapname.c_str(),"r");
|
FILE * f = fopen(si.mapname.c_str(),"r");
|
||||||
problem = !f;
|
problem = !f;
|
||||||
#endif
|
#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!
|
c << ui8(problem); //WRONG!
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(f)
|
if(f)
|
||||||
fclose(f);
|
fclose(f);
|
||||||
*c << ui8(0); //OK!
|
c << ui8(0); //OK!
|
||||||
}
|
}
|
||||||
|
|
||||||
StartInfo startInfoCpy = *si;
|
gh->init(&si,std::clock());
|
||||||
gh.init(si,rand());
|
c.addStdVecItems(gh->gs);
|
||||||
c->addStdVecItems(gh.gs);
|
gh->conns.insert(&c);
|
||||||
|
|
||||||
CConnection* cc; //tcp::socket * ss;
|
return gh;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()
|
void CVCMIServer::start()
|
||||||
{
|
{
|
||||||
ServerReady *sr = NULL;
|
ServerReady *sr = NULL;
|
||||||
@ -147,6 +410,7 @@ void CVCMIServer::start()
|
|||||||
boost::thread acc(boost::bind(vaccept,acceptor,s,&error));
|
boost::thread acc(boost::bind(vaccept,acceptor,s,&error));
|
||||||
sr->setToTrueAndNotify();
|
sr->setToTrueAndNotify();
|
||||||
delete mr;
|
delete mr;
|
||||||
|
|
||||||
acc.join();
|
acc.join();
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
@ -154,39 +418,44 @@ void CVCMIServer::start()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tlog0<<"We've accepted someone... " << std::endl;
|
tlog0<<"We've accepted someone... " << std::endl;
|
||||||
CConnection *connection = new CConnection(s,NAME);
|
firstConnection = new CConnection(s,NAME);
|
||||||
tlog0<<"Got connection!" << std::endl;
|
tlog0<<"Got connection!" << std::endl;
|
||||||
while(!end2)
|
while(!end2)
|
||||||
{
|
{
|
||||||
ui8 mode;
|
ui8 mode;
|
||||||
*connection >> mode;
|
*firstConnection >> mode;
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
connection->socket->close();
|
firstConnection->close();
|
||||||
exit(0);
|
exit(0);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
connection->socket->close();
|
firstConnection->close();
|
||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
newGame(connection);
|
newGame();
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
loadGame(connection);
|
loadGame();
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
newPregame();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CVCMIServer::loadGame( CConnection *c )
|
void CVCMIServer::loadGame()
|
||||||
{
|
{
|
||||||
|
CConnection &c = *firstConnection;
|
||||||
std::string fname;
|
std::string fname;
|
||||||
CGameHandler gh;
|
CGameHandler gh;
|
||||||
boost::system::error_code error;
|
boost::system::error_code error;
|
||||||
ui8 clients;
|
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;
|
ui32 ver;
|
||||||
@ -202,7 +471,7 @@ void CVCMIServer::loadGame( CConnection *c )
|
|||||||
tlog0 <<"Reading handlers"<<std::endl;
|
tlog0 <<"Reading handlers"<<std::endl;
|
||||||
|
|
||||||
lf >> (gh.gs);
|
lf >> (gh.gs);
|
||||||
c->addStdVecItems(gh.gs);
|
c.addStdVecItems(gh.gs);
|
||||||
tlog0 <<"Reading gamestate"<<std::endl;
|
tlog0 <<"Reading gamestate"<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,14 +480,14 @@ void CVCMIServer::loadGame( CConnection *c )
|
|||||||
lf >> gh;
|
lf >> gh;
|
||||||
}
|
}
|
||||||
|
|
||||||
*c << ui8(0);
|
c << ui8(0);
|
||||||
|
|
||||||
CConnection* cc; //tcp::socket * ss;
|
CConnection* cc; //tcp::socket * ss;
|
||||||
for(int i=0; i<clients; i++)
|
for(int i=0; i<clients; i++)
|
||||||
{
|
{
|
||||||
if(!i)
|
if(!i)
|
||||||
{
|
{
|
||||||
cc=c;
|
cc = &c;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define __CVCMISERVER_H__
|
#define __CVCMISERVER_H__
|
||||||
#include "../global.h"
|
#include "../global.h"
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <boost/thread/recursive_mutex.hpp>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CVCMIServer.h, part of VCMI engine
|
* CVCMIServer.h, part of VCMI engine
|
||||||
@ -13,34 +14,90 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
class CMapInfo;
|
||||||
|
|
||||||
class CConnection;
|
class CConnection;
|
||||||
|
class CPackForSelectionScreen;
|
||||||
|
class CGameHandler;
|
||||||
|
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
namespace asio
|
namespace asio
|
||||||
{
|
{
|
||||||
class io_service;
|
|
||||||
namespace ip
|
namespace ip
|
||||||
{
|
{
|
||||||
class tcp;
|
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> class socket_acceptor_service;
|
||||||
template <typename Protocol,typename SocketAcceptorService>
|
template <typename Protocol,typename SocketAcceptorService>
|
||||||
class basic_socket_acceptor;
|
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
|
class CVCMIServer
|
||||||
{
|
{
|
||||||
boost::asio::io_service *io;
|
boost::asio::io_service *io;
|
||||||
boost::asio::basic_socket_acceptor<boost::asio::ip::tcp, boost::asio::socket_acceptor_service<boost::asio::ip::tcp> > * acceptor;
|
TAcceptor * acceptor;
|
||||||
std::map<int,CConnection*> connections;
|
|
||||||
std::set<CConnection*> conns;
|
CConnection *firstConnection;
|
||||||
public:
|
public:
|
||||||
CVCMIServer(); //c-tor
|
CVCMIServer(); //c-tor
|
||||||
~CVCMIServer(); //d-tor
|
~CVCMIServer(); //d-tor
|
||||||
void setUpConnection(CConnection *c, std::string mapname, si32 checksum);
|
|
||||||
void newGame(CConnection *c);
|
|
||||||
void loadGame(CConnection *c);
|
|
||||||
void start();
|
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__
|
#endif // __CVCMISERVER_H__
|
||||||
|
Loading…
Reference in New Issue
Block a user