1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Support for saving/loading in player interfaces, including VCAI.

Minor changes.
This commit is contained in:
Michał W. Urbańczyk 2013-05-09 11:09:23 +00:00
parent 5de00c752c
commit 5c2473d436
17 changed files with 227 additions and 144 deletions

View File

@ -89,12 +89,12 @@ void CBattleAI::init( CBattleCallback * CB )
CB->unlockGsWhenWaiting = false; CB->unlockGsWhenWaiting = false;
} }
void CBattleAI::actionFinished( const BattleAction *action ) void CBattleAI::actionFinished(const BattleAction &action)
{ {
print("actionFinished called"); print("actionFinished called");
} }
void CBattleAI::actionStarted( const BattleAction *action ) void CBattleAI::actionStarted(const BattleAction &action)
{ {
print("actionStarted called"); print("actionStarted called");
} }

View File

@ -18,8 +18,8 @@ public:
~CBattleAI(void); ~CBattleAI(void);
void init(CBattleCallback * CB) OVERRIDE; void init(CBattleCallback * CB) OVERRIDE;
void actionFinished(const BattleAction *action) OVERRIDE;//occurs AFTER every action taken by any stack or by the hero void actionFinished(const BattleAction &action) OVERRIDE;//occurs AFTER every action taken by any stack or by the hero
void actionStarted(const BattleAction *action) OVERRIDE;//occurs BEFORE every action taken by any stack or by the hero void actionStarted(const BattleAction &action) OVERRIDE;//occurs BEFORE every action taken by any stack or by the hero
BattleAction activeStack(const CStack * stack) OVERRIDE; //called when it's turn of that stack BattleAction activeStack(const CStack * stack) OVERRIDE; //called when it's turn of that stack
void battleAttack(const BattleAttack *ba) OVERRIDE; //called when stack is performing attack void battleAttack(const BattleAttack *ba) OVERRIDE; //called when stack is performing attack

View File

@ -25,12 +25,12 @@ void CStupidAI::init( CBattleCallback * CB )
cbc = cb = CB; cbc = cb = CB;
} }
void CStupidAI::actionFinished( const BattleAction *action ) void CStupidAI::actionFinished(const BattleAction &action)
{ {
print("actionFinished called"); print("actionFinished called");
} }
void CStupidAI::actionStarted( const BattleAction *action ) void CStupidAI::actionStarted(const BattleAction &action)
{ {
print("actionStarted called"); print("actionStarted called");
} }
@ -312,3 +312,15 @@ BattleAction CStupidAI::goTowards(const CStack * stack, BattleHex destination)
} }
} }
void CStupidAI::saveGame(COSer<CSaveFile> &h, const int version)
{
//TODO to be implemented with saving/loading during the battles
assert(0);
}
void CStupidAI::loadGame(CISer<CLoadFile> &h, const int version)
{
//TODO to be implemented with saving/loading during the battles
assert(0);
}

View File

@ -13,8 +13,8 @@ public:
~CStupidAI(void); ~CStupidAI(void);
void init(CBattleCallback * CB) OVERRIDE; void init(CBattleCallback * CB) OVERRIDE;
void actionFinished(const BattleAction *action) OVERRIDE;//occurs AFTER every action taken by any stack or by the hero void actionFinished(const BattleAction &action) OVERRIDE;//occurs AFTER every action taken by any stack or by the hero
void actionStarted(const BattleAction *action) OVERRIDE;//occurs BEFORE every action taken by any stack or by the hero void actionStarted(const BattleAction &action) OVERRIDE;//occurs BEFORE every action taken by any stack or by the hero
BattleAction activeStack(const CStack * stack) OVERRIDE; //called when it's turn of that stack BattleAction activeStack(const CStack * stack) OVERRIDE; //called when it's turn of that stack
void battleAttack(const BattleAttack *ba) OVERRIDE; //called when stack is performing attack void battleAttack(const BattleAttack *ba) OVERRIDE; //called when stack is performing attack
@ -35,5 +35,9 @@ public:
void battleStacksRemoved(const BattleStacksRemoved & bsr) OVERRIDE; //called when certain stack is completely removed from battlefield void battleStacksRemoved(const BattleStacksRemoved & bsr) OVERRIDE; //called when certain stack is completely removed from battlefield
BattleAction goTowards(const CStack * stack, BattleHex hex ); BattleAction goTowards(const CStack * stack, BattleHex hex );
virtual void saveGame(COSer<CSaveFile> &h, const int version) OVERRIDE;
virtual void loadGame(CISer<CLoadFile> &h, const int version) OVERRIDE;
}; };

View File

@ -573,7 +573,6 @@ void VCAI::heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visi
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
if (start) if (start)
{ {
visitedObject = const_cast<CGObjectInstance *>(visitedObj); // remember the object and wait for return
markObjectVisited (visitedObj); markObjectVisited (visitedObj);
erase_if_present(reservedObjs, visitedObj); //unreserve objects erase_if_present(reservedObjs, visitedObj); //unreserve objects
erase_if_present(reservedHeroesMap[visitor], visitedObj); erase_if_present(reservedHeroesMap[visitor], visitedObj);
@ -677,6 +676,10 @@ void VCAI::objectRemoved(const CGObjectInstance *obj)
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
erase_if_present(visitableObjs, obj); erase_if_present(visitableObjs, obj);
erase_if_present(alreadyVisited, obj);
erase_if_present(reservedObjs, obj);
BOOST_FOREACH(auto &p, reservedHeroesMap) BOOST_FOREACH(auto &p, reservedHeroesMap)
erase_if_present(p.second, obj); erase_if_present(p.second, obj);
@ -837,7 +840,7 @@ void VCAI::yourTurn()
LOG_TRACE(logAi); LOG_TRACE(logAi);
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
status.startedTurn(); status.startedTurn();
makingTurn = new boost::thread(&VCAI::makeTurn, this); makingTurn = make_unique<boost::thread>(&VCAI::makeTurn, this);
} }
void VCAI::heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, int queryID) void VCAI::heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, int queryID)
@ -894,16 +897,20 @@ void VCAI::showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *do
}); });
} }
void VCAI::serialize(COSer<CSaveFile> &h, const int version) void VCAI::saveGame(COSer<CSaveFile> &h, const int version)
{ {
LOG_TRACE_PARAMS(logAi, "version '%i'", version); LOG_TRACE_PARAMS(logAi, "version '%i'", version);
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
CAdventureAI::saveGame(h, version);
serializeInternal(h, version);
} }
void VCAI::serialize(CISer<CLoadFile> &h, const int version) void VCAI::loadGame(CISer<CLoadFile> &h, const int version)
{ {
LOG_TRACE_PARAMS(logAi, "version '%i'", version); LOG_TRACE_PARAMS(logAi, "version '%i'", version);
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
CAdventureAI::loadGame(h, version);
serializeInternal(h, version);
} }
void makePossibleUpgrades(const CArmedInstance *obj) void makePossibleUpgrades(const CArmedInstance *obj)
@ -982,7 +989,7 @@ void VCAI::makeTurn()
cb->recalculatePaths(); cb->recalculatePaths();
makeTurnInternal(); makeTurnInternal();
vstd::clear_pointer(makingTurn); makingTurn.reset();
return; return;
} }
@ -1067,6 +1074,7 @@ bool VCAI::goVisitObj(const CGObjectInstance * obj, HeroPtr h)
void VCAI::performObjectInteraction(const CGObjectInstance * obj, HeroPtr h) void VCAI::performObjectInteraction(const CGObjectInstance * obj, HeroPtr h)
{ {
LOG_TRACE_PARAMS(logAi, "Hero %s and object %s at %s", h->name % obj->getHoverText() % obj->pos);
switch (obj->ID) switch (obj->ID)
{ {
case Obj::CREATURE_GENERATOR1: case Obj::CREATURE_GENERATOR1:
@ -1692,7 +1700,6 @@ bool VCAI::isAccessibleForHero(const int3 & pos, HeroPtr h, bool includeAllies /
bool VCAI::moveHeroToTile(int3 dst, HeroPtr h) bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
{ {
logAi->debugStream() << boost::format("Moving hero %s to tile %s") % h->name % dst; logAi->debugStream() << boost::format("Moving hero %s to tile %s") % h->name % dst;
visitedObject = NULL;
int3 startHpos = h->visitablePos(); int3 startHpos = h->visitablePos();
bool ret = false; bool ret = false;
if(startHpos == dst) if(startHpos == dst)
@ -1750,7 +1757,7 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
} }
ret = !i; ret = !i;
} }
if (visitedObject) //we step into something interesting if (auto visitedObject = frontOrNull(cb->getVisitableObjs(h->visitablePos()))) //we stand on something interesting
{ {
performObjectInteraction (visitedObject, h); performObjectInteraction (visitedObject, h);
//BNLOG("Hero %s moved from %s to %s at %s", h->name % startHpos % visitedObject->hoverName % h->visitablePos()); //BNLOG("Hero %s moved from %s to %s at %s", h->name % startHpos % visitedObject->hoverName % h->visitablePos());

View File

@ -2,6 +2,7 @@
#include "../../lib/AI_Base.h" #include "../../lib/AI_Base.h"
#include "../../CCallback.h" #include "../../CCallback.h"
#include "../../lib/CDefObjInfoHandler.h"
#include "../../lib/CObjectHandler.h" #include "../../lib/CObjectHandler.h"
#include "../../lib/CThreadHelper.h" #include "../../lib/CThreadHelper.h"
@ -50,6 +51,12 @@ public:
const CGHeroInstance *get(bool doWeExpectNull = false) const; const CGHeroInstance *get(bool doWeExpectNull = false) const;
bool validAndSet() const; bool validAndSet() const;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & this->h & hid & name;
}
}; };
enum BattleState enum BattleState
@ -85,6 +92,12 @@ public:
bool haveTurn(); bool haveTurn();
void attemptedAnsweringQuery(int queryID, int answerRequestID); void attemptedAnsweringQuery(int queryID, int answerRequestID);
void receivedAnswerConfirmation(int answerRequestID, int result); void receivedAnswerConfirmation(int answerRequestID, int result);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & battle & remainingQueries & requestToQueryID & havingTurn;
}
}; };
enum EGoals enum EGoals
@ -168,6 +181,13 @@ struct CGoal
} }
return false; return false;
} }
template <typename Handler> void serialize(Handler &h, const int version)
{
h & goalType & isElementar & isAbstract & priority;
h & value & resID & objid & aid & tile & hero & town & bid;
}
}; };
enum {NOT_VISIBLE = 0, NOT_CHECKED = 1, NOT_AVAILABLE}; enum {NOT_VISIBLE = 0, NOT_CHECKED = 1, NOT_AVAILABLE};
@ -228,6 +248,12 @@ struct ObjectIdRef
ObjectIdRef(const CGObjectInstance *obj); ObjectIdRef(const CGObjectInstance *obj);
bool operator<(const ObjectIdRef &rhs) const; bool operator<(const ObjectIdRef &rhs) const;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & id;
}
}; };
class ObjsVector : public std::vector<ObjectIdRef> class ObjsVector : public std::vector<ObjectIdRef>
@ -266,13 +292,12 @@ public:
std::string battlename; std::string battlename;
CCallback *myCb; CCallback *myCb;
unique_ptr<boost::thread> makingTurn;
VCAI(void); VCAI(void);
~VCAI(void); ~VCAI(void);
CGObjectInstance * visitedObject; //remember currently visted object
boost::thread *makingTurn;
void tryRealize(CGoal g); void tryRealize(CGoal g);
int3 explorationBestNeighbour(int3 hpos, int radius, HeroPtr h); int3 explorationBestNeighbour(int3 hpos, int radius, HeroPtr h);
@ -288,8 +313,8 @@ public:
virtual void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, int queryID) OVERRIDE; //TODO virtual void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, int queryID) OVERRIDE; //TODO
virtual void showBlockingDialog(const std::string &text, const std::vector<Component> &components, ui32 askID, const int soundID, bool selection, bool cancel) OVERRIDE; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID. virtual void showBlockingDialog(const std::string &text, const std::vector<Component> &components, ui32 askID, const int soundID, bool selection, bool cancel) OVERRIDE; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.
virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, int queryID) OVERRIDE; //all stacks operations between these objects become allowed, interface has to call onEnd when done virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, int queryID) OVERRIDE; //all stacks operations between these objects become allowed, interface has to call onEnd when done
virtual void serialize(COSer<CSaveFile> &h, const int version) OVERRIDE; //saving virtual void saveGame(COSer<CSaveFile> &h, const int version) OVERRIDE; //saving
virtual void serialize(CISer<CLoadFile> &h, const int version) OVERRIDE; //loading virtual void loadGame(CISer<CLoadFile> &h, const int version) OVERRIDE; //loading
virtual void finish() OVERRIDE; virtual void finish() OVERRIDE;
virtual void availableCreaturesChanged(const CGDwelling *town) OVERRIDE; virtual void availableCreaturesChanged(const CGDwelling *town) OVERRIDE;
@ -403,6 +428,17 @@ public:
void answerQuery(int queryID, int selection); void answerQuery(int queryID, int selection);
//special function that can be called ONLY from game events handling thread and will send request ASAP //special function that can be called ONLY from game events handling thread and will send request ASAP
void requestActionASAP(boost::function<void()> whatToDo); void requestActionASAP(boost::function<void()> whatToDo);
template <typename Handler> void serializeInternal(Handler &h, const int version)
{
h & knownSubterraneanGates & townVisitsThisWeek & lockedHeroes & reservedHeroesMap;
h & visitableObjs & alreadyVisited & reservedObjs;
h & saving & status & battlename;
//myCB is restored after load by init call
}
}; };
class cannotFulfillGoalException : public std::exception class cannotFulfillGoalException : public std::exception

View File

@ -50,7 +50,6 @@ extern CClientState * CCS;
/// for allowing different functions for accessing game informations /// for allowing different functions for accessing game informations
class CGameInfo class CGameInfo
{ {
ConstTransitivePtr<CGameState> state; //don't touch it in client's code
public: public:
ConstTransitivePtr<CModHandler> modh; //public? ConstTransitivePtr<CModHandler> modh; //public?
ConstTransitivePtr<CArtHandler> arth; ConstTransitivePtr<CArtHandler> arth;

View File

@ -1,5 +1,5 @@
#include "StdInc.h" #include "StdInc.h"
#include "../lib/CDefObjInfoHandler.h"
#include "CAdvmapInterface.h" #include "CAdvmapInterface.h"
#include "battle/CBattleInterface.h" #include "battle/CBattleInterface.h"
#include "battle/CBattleInterfaceClasses.h" #include "battle/CBattleInterfaceClasses.h"
@ -731,7 +731,7 @@ void CPlayerInterface::battleNewRound(int round) //called at the beginning of ea
battleInt->newRound(round); battleInt->newRound(round);
} }
void CPlayerInterface::actionStarted(const BattleAction* action) void CPlayerInterface::actionStarted(const BattleAction &action)
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
if(LOCPLINT != this) if(LOCPLINT != this)
@ -739,11 +739,11 @@ void CPlayerInterface::actionStarted(const BattleAction* action)
return; return;
} }
curAction = new BattleAction(*action); curAction = new BattleAction(action);
battleInt->startAction(action); battleInt->startAction(curAction);
} }
void CPlayerInterface::actionFinished(const BattleAction* action) void CPlayerInterface::actionFinished(const BattleAction &action)
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
if(LOCPLINT != this) if(LOCPLINT != this)
@ -751,9 +751,9 @@ void CPlayerInterface::actionFinished(const BattleAction* action)
return; return;
} }
battleInt->endAction(curAction);
delete curAction; delete curAction;
curAction = NULL; curAction = NULL;
battleInt->endAction(action);
} }
BattleAction CPlayerInterface::activeStack(const CStack * stack) //called when it's turn of that stack BattleAction CPlayerInterface::activeStack(const CStack * stack) //called when it's turn of that stack
@ -1160,55 +1160,44 @@ void CPlayerInterface::heroBonusChanged( const CGHeroInstance *hero, const Bonus
template <typename Handler> void CPlayerInterface::serializeTempl( Handler &h, const int version ) template <typename Handler> void CPlayerInterface::serializeTempl( Handler &h, const int version )
{ {
h & playerID;
h & spellbookSettings;
//sleeping heroes h & observerInDuelMode;
ui8 sleepingSize = 0; //fix for uninitialized warning
if (h.saving) h & wanderingHeroes & towns & sleepingHeroes;
sleepingSize = sleepingHeroes.size();
h & sleepingSize; std::map<const CGHeroInstance *, int3> pathsMap; //hero -> dest
for (int i = 0; i < sleepingSize; i++) if(h.saving)
{ {
ObjectInstanceID hid; BOOST_FOREACH(auto &p, paths)
if (h.saving) pathsMap[p.first] = p.second.endPos();
hid = sleepingHeroes[i]->id; h & pathsMap;
h & hid;
if (!h.saving)
{
const CGHeroInstance *hero = cb->getHero(hid);
sleepingHeroes += hero;
}
} }
//hero list order
ui8 heroListSize = 0; //fix for uninitialized warning
if (h.saving)
heroListSize = wanderingHeroes.size();
else else
wanderingHeroes.clear();
h & heroListSize;
for (int i = 0; i < heroListSize; i++)
{ {
ObjectInstanceID hid; h & pathsMap;
if (h.saving)
hid = wanderingHeroes[i]->id; CPathsInfo pathsInfo(cb->getMapSize());
h & hid; BOOST_FOREACH(auto &p, pathsMap)
if (!h.saving)
{ {
const CGHeroInstance *hero = cb->getHero(hid); cb->calculatePaths(p.first, pathsInfo);
wanderingHeroes += hero; CGPath path;
pathsInfo.getPath(p.second, path);
paths[p.first] = path;
logGlobal->traceStream() << boost::format("Restored path for hero %s leading to %s with %d nodes")
% p.first->nodeName() % p.second % path.nodes.size();
} }
} }
h & spellbookSettings;
} }
void CPlayerInterface::serialize( COSer<CSaveFile> &h, const int version ) void CPlayerInterface::saveGame( COSer<CSaveFile> &h, const int version )
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
serializeTempl(h,version); serializeTempl(h,version);
} }
void CPlayerInterface::serialize( CISer<CLoadFile> &h, const int version ) void CPlayerInterface::loadGame( CISer<CLoadFile> &h, const int version )
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
serializeTempl(h,version); serializeTempl(h,version);

View File

@ -182,12 +182,12 @@ public:
void gameOver(PlayerColor player, bool victory) OVERRIDE; void gameOver(PlayerColor player, bool victory) OVERRIDE;
void playerStartsTurn(PlayerColor player) OVERRIDE; //called before yourTurn on active itnerface void playerStartsTurn(PlayerColor player) OVERRIDE; //called before yourTurn on active itnerface
void showComp(const Component &comp, std::string message) OVERRIDE; //display component in the advmapint infobox void showComp(const Component &comp, std::string message) OVERRIDE; //display component in the advmapint infobox
void serialize(COSer<CSaveFile> &h, const int version) OVERRIDE; //saving void saveGame(COSer<CSaveFile> &h, const int version) OVERRIDE; //saving
void serialize(CISer<CLoadFile> &h, const int version) OVERRIDE; //loading void loadGame(CISer<CLoadFile> &h, const int version) OVERRIDE; //loading
//for battles //for battles
void actionFinished(const BattleAction* action) OVERRIDE;//occurs AFTER action taken by active stack or by the hero void actionFinished(const BattleAction& action) OVERRIDE;//occurs AFTER action taken by active stack or by the hero
void actionStarted(const BattleAction* action) OVERRIDE;//occurs BEFORE action taken by active stack or by the hero void actionStarted(const BattleAction& action) OVERRIDE;//occurs BEFORE action taken by active stack or by the hero
BattleAction activeStack(const CStack * stack) OVERRIDE; //called when it's turn of that stack BattleAction activeStack(const CStack * stack) OVERRIDE; //called when it's turn of that stack
void battleAttack(const BattleAttack *ba) OVERRIDE; //stack performs attack void battleAttack(const BattleAttack *ba) OVERRIDE; //stack performs attack
void battleEnd(const BattleResult *br) OVERRIDE; //end of battle void battleEnd(const BattleResult *br) OVERRIDE; //end of battle

View File

@ -78,20 +78,20 @@ public:
} }
}; };
static CApplier<CBaseForCLApply> *applier = NULL; static CApplier<CBaseForCLApply> *applier = nullptr;
void CClient::init() void CClient::init()
{ {
hotSeat = false; hotSeat = false;
connectionHandler = NULL; connectionHandler = nullptr;
pathInfo = NULL; pathInfo = nullptr;
applier = new CApplier<CBaseForCLApply>; applier = new CApplier<CBaseForCLApply>;
registerTypes2(*applier); registerTypes2(*applier);
IObjectInterface::cb = this; IObjectInterface::cb = this;
serv = NULL; serv = nullptr;
gs = NULL; gs = nullptr;
cb = NULL; cb = nullptr;
erm = NULL; erm = nullptr;
terminate = false; terminate = false;
} }
@ -108,7 +108,6 @@ CClient::CClient(CConnection *con, StartInfo *si)
CClient::~CClient(void) CClient::~CClient(void)
{ {
delete pathInfo;
delete applier; delete applier;
} }
@ -202,11 +201,9 @@ void CClient::endGame( bool closeConnection /*= true*/ )
GH.statusbar = NULL; GH.statusbar = NULL;
logNetwork->infoStream() << "Removed GUI."; logNetwork->infoStream() << "Removed GUI.";
vstd::clear_pointer(const_cast<CGameInfo*>(CGI)->mh);
vstd::clear_pointer(gs);
delete CGI->mh;
const_cast<CGameInfo*>(CGI)->mh = NULL;
const_cast<CGameInfo*>(CGI)->state.dellNull();
logNetwork->infoStream() << "Deleted mapHandler and gameState."; logNetwork->infoStream() << "Deleted mapHandler and gameState.";
LOCPLINT = NULL; LOCPLINT = NULL;
} }
@ -242,10 +239,9 @@ void CClient::loadGame( const std::string & fname )
loader = checkingLoader.decay(); loader = checkingLoader.decay();
} }
logNetwork->infoStream() << "Loaded common part of save " << tmh.getDiff(); logNetwork->infoStream() << "Loaded common part of save " << tmh.getDiff();
const_cast<CGameInfo*>(CGI)->state = gs;
const_cast<CGameInfo*>(CGI)->mh = new CMapHandler(); const_cast<CGameInfo*>(CGI)->mh = new CMapHandler();
const_cast<CGameInfo*>(CGI)->mh->map = gs->map; const_cast<CGameInfo*>(CGI)->mh->map = gs->map;
pathInfo = new CPathsInfo(int3(gs->map->width, gs->map->height, gs->map->twoLevel ? 2 : 1)); pathInfo = make_unique<CPathsInfo>(getMapSize());
CGI->mh->init(); CGI->mh->init();
logNetwork->infoStream() <<"Initing maphandler: "<<tmh.getDiff(); logNetwork->infoStream() <<"Initing maphandler: "<<tmh.getDiff();
@ -295,12 +291,12 @@ void CClient::newGame( CConnection *con, StartInfo *si )
networkMode = (con->connectionID == 1) ? HOST : GUEST; networkMode = (con->connectionID == 1) ? HOST : GUEST;
} }
CStopWatch tmh; CConnection &c = *serv;
const_cast<CGameInfo*>(CGI)->state = new CGameState();
logNetwork->infoStream() <<"\tGamestate: "<<tmh.getDiff();
CConnection &c(*serv);
//////////////////////////////////////////////////// ////////////////////////////////////////////////////
logNetwork->infoStream() <<"\tWill send info to server...";
CStopWatch tmh;
if(networkMode == SINGLE) if(networkMode == SINGLE)
{ {
ui8 pom8; ui8 pom8;
@ -319,7 +315,9 @@ void CClient::newGame( CConnection *con, StartInfo *si )
c.disableSmartPointerSerialization(); c.disableSmartPointerSerialization();
// Initialize game state // Initialize game state
gs = const_cast<CGameInfo*>(CGI)->state; gs = new CGameState();
logNetwork->infoStream() <<"\tCreating gamestate: "<<tmh.getDiff();
gs->scenarioOps = si; gs->scenarioOps = si;
gs->init(si); gs->init(si);
logNetwork->infoStream() <<"Initializing GameState (together): "<<tmh.getDiff(); logNetwork->infoStream() <<"Initializing GameState (together): "<<tmh.getDiff();
@ -347,7 +345,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
CGI->mh->map = gs->map; CGI->mh->map = gs->map;
logNetwork->infoStream() <<"Creating mapHandler: "<<tmh.getDiff(); logNetwork->infoStream() <<"Creating mapHandler: "<<tmh.getDiff();
CGI->mh->init(); CGI->mh->init();
pathInfo = new CPathsInfo(int3(gs->map->width, gs->map->height, gs->map->twoLevel ? 2 : 1)); pathInfo = make_unique<CPathsInfo>(getMapSize());
logNetwork->infoStream() <<"Initializing mapHandler (together): "<<tmh.getDiff(); logNetwork->infoStream() <<"Initializing mapHandler (together): "<<tmh.getDiff();
} }
@ -416,7 +414,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
loadNeutralBattleAI(); loadNeutralBattleAI();
} }
serv->addStdVecItems(const_cast<CGameInfo*>(CGI)->state); serv->addStdVecItems(gs);
hotSeat = (humanPlayers > 1); hotSeat = (humanPlayers > 1);
// std::vector<FileInfo> scriptModules; // std::vector<FileInfo> scriptModules;
@ -445,8 +443,11 @@ void CClient::serialize( Handler &h, const int version )
for(auto i = playerint.begin(); i != playerint.end(); i++) for(auto i = playerint.begin(); i != playerint.end(); i++)
{ {
h & i->first & i->second->dllName; LOG_TRACE_PARAMS(logGlobal, "Saving player %s interface", i->first);
i->second->serialize(h,version); assert(i->first == i->second->playerID);
h & i->first & i->second->dllName & i->second->human;
i->second->saveGame(dynamic_cast<COSer<CSaveFile>&>(h), version);
//evil cast that i still like better than sfinae-magic. If I had a "static if"...
} }
} }
else else
@ -457,11 +458,13 @@ void CClient::serialize( Handler &h, const int version )
for(int i=0; i < players; i++) for(int i=0; i < players; i++)
{ {
std::string dllname; std::string dllname;
PlayerColor pid = PlayerColor(0); //fix for uninitialized warning PlayerColor pid;
h & pid & dllname; bool isHuman = false;
h & pid & dllname & isHuman;
LOG_TRACE_PARAMS(logGlobal, "Loading player %s interface", pid);
CGameInterface *nInt = NULL; CGameInterface *nInt = nullptr;
if(dllname.length()) if(dllname.length())
{ {
if(pid == PlayerColor::NEUTRAL) if(pid == PlayerColor::NEUTRAL)
@ -474,15 +477,25 @@ void CClient::serialize( Handler &h, const int version )
continue; continue;
} }
else else
{
assert(!isHuman);
nInt = CDynLibHandler::getNewAI(dllname); nInt = CDynLibHandler::getNewAI(dllname);
}
} }
else else
{
assert(isHuman);
nInt = new CPlayerInterface(pid); nInt = new CPlayerInterface(pid);
}
nInt->dllName = dllname;
nInt->human = isHuman;
nInt->playerID = pid;
battleCallbacks[pid] = callbacks[pid] = make_shared<CCallback>(gs,pid,this); battleCallbacks[pid] = callbacks[pid] = make_shared<CCallback>(gs,pid,this);
battleints[pid] = playerint[pid] = nInt; battleints[pid] = playerint[pid] = nInt;
nInt->init(callbacks[pid].get()); nInt->init(callbacks[pid].get());
nInt->serialize(h, version); nInt->loadGame(dynamic_cast<CISer<CLoadFile>&>(h), version); //another evil cast, check above
} }
if(!vstd::contains(battleints, PlayerColor::NEUTRAL)) if(!vstd::contains(battleints, PlayerColor::NEUTRAL))

View File

@ -121,18 +121,16 @@ public:
std::map<PlayerColor,CBattleGameInterface *> battleints; std::map<PlayerColor,CBattleGameInterface *> battleints;
bool hotSeat; bool hotSeat;
CConnection *serv; CConnection *serv;
BattleAction *curbaction;
CPathsInfo *pathInfo; boost::optional<BattleAction> curbaction;
unique_ptr<CPathsInfo> pathInfo;
boost::mutex pathMx; //protects the variable above boost::mutex pathMx; //protects the variable above
CScriptingModule *erm; CScriptingModule *erm;
ThreadSafeVector<int> waitingRequest; ThreadSafeVector<int> waitingRequest;
std::queue<CPack *> packs;
boost::mutex packsM;
void waitForMoveAndSend(PlayerColor color); void waitForMoveAndSend(PlayerColor color);
//void sendRequest(const CPackForServer *request, bool waitForRealization); //void sendRequest(const CPackForServer *request, bool waitForRealization);
CClient(void); CClient(void);

View File

@ -671,8 +671,8 @@ void BattleAttack::applyCl( CClient *cl )
void StartAction::applyFirstCl( CClient *cl ) void StartAction::applyFirstCl( CClient *cl )
{ {
cl->curbaction = new BattleAction(ba); cl->curbaction = ba;
BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(actionStarted, &ba); BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(actionStarted, ba);
} }
void BattleSpellCast::applyCl( CClient *cl ) void BattleSpellCast::applyCl( CClient *cl )
@ -744,10 +744,8 @@ CGameState* CPackForClient::GS( CClient *cl )
void EndAction::applyCl( CClient *cl ) void EndAction::applyCl( CClient *cl )
{ {
BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(actionFinished, cl->curbaction); BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(actionFinished, *cl->curbaction);
cl->curbaction.reset();
delete cl->curbaction;
cl->curbaction = NULL;
} }
void PackageApplied::applyCl( CClient *cl ) void PackageApplied::applyCl( CClient *cl )
@ -793,24 +791,6 @@ void SaveGame::applyCl(CClient *cl)
{ {
logNetwork->errorStream() << "Failed to save game:" << e.what(); logNetwork->errorStream() << "Failed to save game:" << e.what();
} }
// try
// {
// auto clientPart = CResourceHandler::get()->getResourceName(ResourceID(info.getStem(), EResType::CLIENT_SAVEGAME));
// auto libPart = CResourceHandler::get()->getResourceName(ResourceID(info.getStem(), EResType::LIB_SAVEGAME));
// CLoadIntegrityValidator checker(clientPart, libPart);
//
// CMapHeader mh;
// StartInfo *si;
// LibClasses *lib;
// CGameState *game;
//
// checker.checkMagicBytes(SAVEGAME_MAGIC);
// checker >> mh >> si >> lib >> game;
// }
// catch(...)
// {
// }
} }
void PlayerMessage::applyCl(CClient *cl) void PlayerMessage::applyCl(CClient *cl)

View File

@ -10,6 +10,7 @@
#else #else
#include <dlfcn.h> #include <dlfcn.h>
#endif #endif
#include "Connection.h"
/* /*
* CGameInterface.cpp, part of VCMI engine * CGameInterface.cpp, part of VCMI engine
@ -133,7 +134,7 @@ void CAdventureAI::battleStacksAttacked(const std::vector<BattleStackAttacked> &
battleAI->battleStacksAttacked(bsa); battleAI->battleStacksAttacked(bsa);
} }
void CAdventureAI::actionStarted(const BattleAction *action) void CAdventureAI::actionStarted(const BattleAction &action)
{ {
battleAI->actionStarted(action); battleAI->actionStarted(action);
} }
@ -143,7 +144,7 @@ void CAdventureAI::battleNewRoundFirst(int round)
battleAI->battleNewRoundFirst(round); battleAI->battleNewRoundFirst(round);
} }
void CAdventureAI::actionFinished(const BattleAction *action) void CAdventureAI::actionFinished(const BattleAction &action)
{ {
battleAI->actionFinished(action); battleAI->actionFinished(action);
} }
@ -203,3 +204,41 @@ void CAdventureAI::yourTacticPhase(int distance)
{ {
battleAI->yourTacticPhase(distance); battleAI->yourTacticPhase(distance);
} }
void CAdventureAI::saveGame(COSer<CSaveFile> &h, const int version) /*saving */
{
LOG_TRACE_PARAMS(logAi, "version '%i'", version);
CGlobalAI::saveGame(h, version);
bool hasBattleAI = battleAI;
h << hasBattleAI;
if(hasBattleAI)
{
h << std::string(battleAI->dllName);
battleAI->saveGame(h, version);
}
}
void CAdventureAI::loadGame(CISer<CLoadFile> &h, const int version) /*loading */
{
LOG_TRACE_PARAMS(logAi, "version '%i'", version);
CGlobalAI::loadGame(h, version);
bool hasBattleAI = false;
h >> hasBattleAI;
if(hasBattleAI)
{
std::string dllName;
h >> dllName;
battleAI = CDynLibHandler::getNewBattleAI(dllName);
assert(cbc); //it should have been set by the one who new'ed us
battleAI->init(cbc);
//battleAI->loadGame(h, version);
}
}
void CBattleGameInterface::saveGame(COSer<CSaveFile> &h, const int version)
{
}
void CBattleGameInterface::loadGame(CISer<CLoadFile> &h, const int version)
{
}

View File

@ -53,7 +53,7 @@ template <typename Serializer> class COSer;
struct ArtifactLocation; struct ArtifactLocation;
class CScriptingModule; class CScriptingModule;
class CBattleGameInterface : public IBattleEventsReceiver class DLL_LINKAGE CBattleGameInterface : public IBattleEventsReceiver
{ {
public: public:
bool human; bool human;
@ -66,6 +66,10 @@ public:
//battle call-ins //battle call-ins
virtual BattleAction activeStack(const CStack * stack)=0; //called when it's turn of that stack virtual BattleAction activeStack(const CStack * stack)=0; //called when it's turn of that stack
virtual void yourTacticPhase(int distance){}; //called when interface has opportunity to use Tactics skill -> use cb->battleMakeTacticAction from this function virtual void yourTacticPhase(int distance){}; //called when interface has opportunity to use Tactics skill -> use cb->battleMakeTacticAction from this function
virtual void saveGame(COSer<CSaveFile> &h, const int version);
virtual void loadGame(CISer<CLoadFile> &h, const int version);
}; };
/// Central class for managing human player / AI interface logic /// Central class for managing human player / AI interface logic
@ -86,8 +90,6 @@ public:
// all stacks operations between these objects become allowed, interface has to call onEnd when done // all stacks operations between these objects become allowed, interface has to call onEnd when done
virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, int queryID) = 0; virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, int queryID) = 0;
virtual void serialize(COSer<CSaveFile> &h, const int version){}; //saving
virtual void serialize(CISer<CLoadFile> &h, const int version){}; //loading
virtual void finish(){}; //if for some reason we want to end virtual void finish(){}; //if for some reason we want to end
}; };
@ -124,9 +126,9 @@ public:
virtual void battleCatapultAttacked(const CatapultAttack & ca); virtual void battleCatapultAttacked(const CatapultAttack & ca);
virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side); virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side);
virtual void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa); virtual void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa);
virtual void actionStarted(const BattleAction *action); virtual void actionStarted(const BattleAction &action);
virtual void battleNewRoundFirst(int round); virtual void battleNewRoundFirst(int round);
virtual void actionFinished(const BattleAction *action); virtual void actionFinished(const BattleAction &action);
virtual void battleStacksEffectsSet(const SetStackEffect & sse); virtual void battleStacksEffectsSet(const SetStackEffect & sse);
//virtual void battleTriggerEffect(const BattleTriggerEffect & bte); //virtual void battleTriggerEffect(const BattleTriggerEffect & bte);
virtual void battleStacksRemoved(const BattleStacksRemoved & bsr); virtual void battleStacksRemoved(const BattleStacksRemoved & bsr);
@ -137,4 +139,7 @@ public:
virtual void battleSpellCast(const BattleSpellCast *sc); virtual void battleSpellCast(const BattleSpellCast *sc);
virtual void battleEnd(const BattleResult *br); virtual void battleEnd(const BattleResult *br);
virtual void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, bool tentHeal, si32 lifeDrainFrom); virtual void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, bool tentHeal, si32 lifeDrainFrom);
virtual void saveGame(COSer<CSaveFile> &h, const int version); //saving
virtual void loadGame(CISer<CLoadFile> &h, const int version); //loading
}; };

View File

@ -511,6 +511,7 @@ int CLoadIntegrityValidator::read( const void * data, unsigned size )
unique_ptr<CLoadFile> CLoadIntegrityValidator::decay() unique_ptr<CLoadFile> CLoadIntegrityValidator::decay()
{ {
primaryFile->loadedPointers = this->loadedPointers;
return std::move(primaryFile); return std::move(primaryFile);
} }

View File

@ -1160,19 +1160,19 @@ public:
data = boost::optional<T>(); data = boost::optional<T>();
} }
} }
void loadSerializable(CStackInstance *&s) // void loadSerializable(CStackInstance *&s)
{ // {
if(sendStackInstanceByIds) // if(sendStackInstanceByIds)
{ // {
CArmedInstance *armed; // CArmedInstance *armed;
SlotID slot; // SlotID slot;
*this >> armed >> slot; // *this >> armed >> slot;
assert(armed->hasStackAtSlot(slot)); // assert(armed->hasStackAtSlot(slot));
s = armed->stacks[slot]; // s = armed->stacks[slot];
} // }
else // else
loadSerializableBySerializeCall(s); // loadSerializableBySerializeCall(s);
} // }
template <typename E> template <typename E>
void loadEnum(E &data) void loadEnum(E &data)

View File

@ -49,8 +49,8 @@ struct CPackForServer;
class DLL_LINKAGE IBattleEventsReceiver class DLL_LINKAGE IBattleEventsReceiver
{ {
public: public:
virtual void actionFinished(const BattleAction *action){};//occurs AFTER every action taken by any stack or by the hero virtual void actionFinished(const BattleAction &action){};//occurs AFTER every action taken by any stack or by the hero
virtual void actionStarted(const BattleAction *action){};//occurs BEFORE every action taken by any stack or by the hero virtual void actionStarted(const BattleAction &action){};//occurs BEFORE every action taken by any stack or by the hero
virtual void battleAttack(const BattleAttack *ba){}; //called when stack is performing attack virtual void battleAttack(const BattleAttack *ba){}; //called when stack is performing attack
virtual void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa){}; //called when stack receives damage (after battleAttack()) virtual void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa){}; //called when stack receives damage (after battleAttack())
virtual void battleEnd(const BattleResult *br){}; virtual void battleEnd(const BattleResult *br){};