1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-07-17 01:32:21 +02:00

Various fixes and refactorings. Restored client project to solution.

This commit is contained in:
Michał W. Urbańczyk
2011-09-29 21:29:54 +00:00
parent 1282ad4573
commit 2b18e0b821
21 changed files with 235 additions and 152 deletions

View File

@ -239,30 +239,30 @@ void CBattleLogic::MakeStatistics(int currentCreatureId)
typedef SCreatureCasualties const std::pair<int, SCreatureCasualties>::* CreaPairPtr; typedef SCreatureCasualties const std::pair<int, SCreatureCasualties>::* CreaPairPtr;
// sort max damage // sort max damage
std::sort(m_statMaxDamage.begin(), m_statMaxDamage.end(), // std::sort(m_statMaxDamage.begin(), m_statMaxDamage.end(),
bind((IntPtr)&creature_stat::value_type::second, _1) > bind((IntPtr)&creature_stat::value_type::second, _2)); // bind((IntPtr)&creature_stat::value_type::second, _1) > bind((IntPtr)&creature_stat::value_type::second, _2));
// sort min damage // // sort min damage
std::sort(m_statMinDamage.begin(), m_statMinDamage.end(), // std::sort(m_statMinDamage.begin(), m_statMinDamage.end(),
bind((IntPtr)&creature_stat::value_type::second, _1) > bind((IntPtr)&creature_stat::value_type::second, _2)); // bind((IntPtr)&creature_stat::value_type::second, _1) > bind((IntPtr)&creature_stat::value_type::second, _2));
// sort max speed // // sort max speed
std::sort(m_statMaxSpeed.begin(), m_statMaxSpeed.end(), // std::sort(m_statMaxSpeed.begin(), m_statMaxSpeed.end(),
bind((IntPtr)&creature_stat::value_type::second, _1) > bind((IntPtr)&creature_stat::value_type::second, _2)); // bind((IntPtr)&creature_stat::value_type::second, _1) > bind((IntPtr)&creature_stat::value_type::second, _2));
// sort distance // // sort distance
std::sort(m_statDistance.begin(), m_statDistance.end(), // std::sort(m_statDistance.begin(), m_statDistance.end(),
bind((IntPtr)&creature_stat::value_type::second, _1) < bind((IntPtr)&creature_stat::value_type::second, _2)); // bind((IntPtr)&creature_stat::value_type::second, _1) < bind((IntPtr)&creature_stat::value_type::second, _2));
// sort distance from shooters // // sort distance from shooters
std::sort(m_statDistanceFromShooters.begin(), m_statDistanceFromShooters.end(), // std::sort(m_statDistanceFromShooters.begin(), m_statDistanceFromShooters.end(),
bind((IntPtr)&creature_stat::value_type::second, _1) < bind((IntPtr)&creature_stat::value_type::second, _2)); // bind((IntPtr)&creature_stat::value_type::second, _1) < bind((IntPtr)&creature_stat::value_type::second, _2));
// sort hit points // // sort hit points
std::sort(m_statHitPoints.begin(), m_statHitPoints.end(), // std::sort(m_statHitPoints.begin(), m_statHitPoints.end(),
bind((IntPtr)&creature_stat::value_type::second, _1) > bind((IntPtr)&creature_stat::value_type::second, _2)); // bind((IntPtr)&creature_stat::value_type::second, _1) > bind((IntPtr)&creature_stat::value_type::second, _2));
// sort casualties // // sort casualties
std::sort(m_statCasualties.begin(), m_statCasualties.end(), // std::sort(m_statCasualties.begin(), m_statCasualties.end(),
bind((CreaPtr)&creature_stat_casualties::value_type::second_type::damage_max, // bind((CreaPtr)&creature_stat_casualties::value_type::second_type::damage_max,
bind((CreaPairPtr)&creature_stat_casualties::value_type::second, _1)) // bind((CreaPairPtr)&creature_stat_casualties::value_type::second, _1))
> // >
bind((CreaPtr)&creature_stat_casualties::value_type::second_type::damage_max, // bind((CreaPtr)&creature_stat_casualties::value_type::second_type::damage_max,
bind((CreaPairPtr)&creature_stat_casualties::value_type::second, _2))); // bind((CreaPairPtr)&creature_stat_casualties::value_type::second, _2)));
} }
BattleAction CBattleLogic::MakeDecision(int stackID) BattleAction CBattleLogic::MakeDecision(int stackID)

View File

@ -272,6 +272,7 @@ void CCallback::buildBoat( const IShipyard *obj )
CCallback::CCallback( CGameState * GS, int Player, CClient *C ) CCallback::CCallback( CGameState * GS, int Player, CClient *C )
:CBattleCallback(GS, Player, C) :CBattleCallback(GS, Player, C)
{ {
cl = C;
waitTillRealize = false; waitTillRealize = false;
} }

View File

@ -11,6 +11,7 @@
#endif #endif
#include "lib/IGameCallback.h" #include "lib/IGameCallback.h"
#include "lib/CBattleCallback.h"
/* /*
* CCallback.h, part of VCMI engine * CCallback.h, part of VCMI engine
@ -37,15 +38,6 @@ struct CGPath;
struct CPathsInfo; struct CPathsInfo;
struct CPack; struct CPack;
class IBattleCallback
{
public:
bool waitTillRealize; //if true, request functions will return after they are realized by server
bool unlockGsWhenWaiting;//if true after sending each request, gs mutex will be unlocked so the changes can be applied; NOTICE caller must have gs mx locked prior to any call to actiob callback!
//battle
virtual int battleMakeAction(BattleAction* action)=0;//for casting spells by hero - DO NOT use it for moving active stack
virtual bool battleMakeTacticAction(BattleAction * action) =0; // performs tactic phase actions
};
class IGameActionCallback class IGameActionCallback
{ {
@ -83,29 +75,12 @@ public:
virtual void buildBoat(const IShipyard *obj) = 0; virtual void buildBoat(const IShipyard *obj) = 0;
}; };
struct CPack;
class CBattleCallback : public IBattleCallback, public CBattleInfoCallback
{
protected:
void sendRequest(const CPack *request);
CClient *cl;
//virtual bool hasAccess(int playerId) const;
public:
CBattleCallback(CGameState *GS, int Player, CClient *C);
int battleMakeAction(BattleAction* action) OVERRIDE;//for casting spells by hero - DO NOT use it for moving active stack
bool battleMakeTacticAction(BattleAction * action) OVERRIDE; // performs tactic phase actions
friend class CCallback;
friend class CClient;
};
class CCallback : public CPlayerSpecificInfoCallback, public IGameActionCallback, public CBattleCallback class CCallback : public CPlayerSpecificInfoCallback, public IGameActionCallback, public CBattleCallback
{ {
private: private:
CCallback(CGameState * GS, int Player, CClient *C); CCallback(CGameState * GS, int Player, CClient *C);
public: public:
CClient *cl;
//client-specific functionalities (pathfinding) //client-specific functionalities (pathfinding)
virtual bool getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath &ret); //DEPRACATED!!! virtual bool getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath &ret); //DEPRACATED!!!
virtual const CGPathNode *getPathInfo(int3 tile); //uses main, client pathfinder info virtual const CGPathNode *getPathInfo(int3 tile); //uses main, client pathfinder info

View File

@ -7,7 +7,7 @@ int main()
boost::thread t(boost::bind(std::system, "VCMI_server.exe b1.json StupidAI StupidAI")); boost::thread t(boost::bind(std::system, "VCMI_server.exe b1.json StupidAI StupidAI"));
boost::thread tt(boost::bind(std::system, "VCMI_BattleAiHost.exe")); boost::thread tt(boost::bind(std::system, "VCMI_BattleAiHost.exe"));
boost::thread ttt(boost::bind(std::system, "VCMI_BattleAiHost.exe")); boost::thread ttt(boost::bind(std::system, "VCMI_BattleAiHost.exe"));
boost::thread tttt(boost::bind(std::system, "VCMI_BattleAiHost.exe")); //boost::thread tttt(boost::bind(std::system, "VCMI_BattleAiHost.exe"));
//boost::this_thread::sleep(boost::posix_time::seconds(5)); //boost::this_thread::sleep(boost::posix_time::seconds(5));
t.join(); t.join();

View File

@ -1,50 +0,0 @@
#include "BattleCallback.h"
#include "Client.h"
#include "../lib/CGameState.h"
#include "../lib/BattleState.h"
#include "../lib/NetPacks.h"
#include "../lib/Connection.h"
CBattleCallback::CBattleCallback(CGameState *GS, int Player, CClient *C )
{
gs = GS;
player = Player;
cl = C;
}
bool CBattleCallback::battleMakeTacticAction( BattleAction * action )
{
assert(cl->gs->curB->tacticDistance);
MakeAction ma;
ma.ba = *action;
sendRequest(&ma);
return true;
}
int CBattleCallback::battleMakeAction(BattleAction* action)
{
assert(action->actionType == BattleAction::HERO_SPELL);
MakeCustomAction mca(*action);
sendRequest(&mca);
return 0;
}
void CBattleCallback::sendRequest(const CPack* request)
{
//TODO should be part of CClient (client owns connection, not CB)
//but it would have to be very tricky cause template/serialization issues
// if(waitTillRealize)
// cl->waitingRequest.set(typeList.getTypeID(request));
cl->serv->sendPack(*request);
// if(waitTillRealize)
// {
// if(unlockGsWhenWaiting)
// getGsMutex().unlock_shared();
// cl->waitingRequest.waitWhileTrue();
// if(unlockGsWhenWaiting)
// getGsMutex().lock_shared();
// }
}

View File

@ -1,23 +0,0 @@
#pragma once
#include "../global.h"
#include "../CCallback.h"
/*class CBattleCallback : public IBattleCallback, public CBattleInfoCallback
{
private:
CBattleCallback(CGameState *GS, int Player, CClient *C);
protected:
void sendRequest(const CPack *request);
CClient *cl;
//virtual bool hasAccess(int playerId) const;
public:
int battleMakeAction(BattleAction* action) OVERRIDE;//for casting spells by hero - DO NOT use it for moving active stack
bool battleMakeTacticAction(BattleAction * action) OVERRIDE; // performs tactic phase actions
friend class CCallback;
friend class CClient;
};*/

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "../global.h" #include "../global.h"
#include "../lib/CBattleCallback.h"
class CGameState; class CGameState;
class CConnection; class CConnection;
struct CPack; struct CPack;
@ -7,13 +8,12 @@ class CBattleGameInterface;
struct BattleAction; struct BattleAction;
class CStack; class CStack;
class CClient/* : public IGameCallback*/ class CClient/* : public IGameCallback*/ : public IConnectionHandler
{ {
public: public:
bool terminate; bool terminate;
BattleAction *curbaction; BattleAction *curbaction;
CGameState *gs; CGameState *gs;
CConnection *serv;
CBattleGameInterface *ai; CBattleGameInterface *ai;
CClient(); CClient();

View File

@ -394,12 +394,12 @@ void EndAction::applyCl( CClient *cl )
void PackageApplied::applyCl( CClient *cl ) void PackageApplied::applyCl( CClient *cl )
{ {
// ui8 player = GS(cl)->currentPlayer; ui8 player = GS(cl)->currentPlayer;
// INTERFACE_CALL_IF_PRESENT(player, requestRealized, this); //INTERFACE_CALL_IF_PRESENT(player, requestRealized, this);
// if(cl->waitingRequest.get() == packType) if(cl->waitingRequest.get() == packType)
// cl->waitingRequest.setn(false); cl->waitingRequest.setn(false);
// else if(cl->waitingRequest.get()) else if(cl->waitingRequest.get())
// tlog3 << "Surprising server message!\n"; tlog3 << "Surprising server message!\n";
} }
void SystemMessage::applyCl( CClient *cl ) void SystemMessage::applyCl( CClient *cl )

View File

@ -132,13 +132,11 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="BattleCallback.cpp" />
<ClCompile Include="Client.cpp" /> <ClCompile Include="Client.cpp" />
<ClCompile Include="main.cpp" /> <ClCompile Include="main.cpp" />
<ClCompile Include="NetPacksRunner.cpp" /> <ClCompile Include="NetPacksRunner.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="BattleCallback.h" />
<ClInclude Include="CheckTime.h" /> <ClInclude Include="CheckTime.h" />
<ClInclude Include="Client.h" /> <ClInclude Include="Client.h" />
</ItemGroup> </ItemGroup>

View File

@ -22,6 +22,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Odpalarka", "Odpalarka\Odpa
{B952FFC5-3039-4DE1-9F08-90ACDA483D8F} = {B952FFC5-3039-4DE1-9F08-90ACDA483D8F} {B952FFC5-3039-4DE1-9F08-90ACDA483D8F} = {B952FFC5-3039-4DE1-9F08-90ACDA483D8F}
EndProjectSection EndProjectSection
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8C710950-7839-490C-8412-C60AC4D5238B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VCMI_client", "client\VCMI_client.vcxproj", "{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32 Debug|Win32 = Debug|Win32
@ -94,6 +98,17 @@ Global
{27B69211-D138-4142-BBC9-40F5DEA39067}.Release|Win32.ActiveCfg = Release|Win32 {27B69211-D138-4142-BBC9-40F5DEA39067}.Release|Win32.ActiveCfg = Release|Win32
{27B69211-D138-4142-BBC9-40F5DEA39067}.Release|Win32.Build.0 = Release|Win32 {27B69211-D138-4142-BBC9-40F5DEA39067}.Release|Win32.Build.0 = Release|Win32
{27B69211-D138-4142-BBC9-40F5DEA39067}.Release|x64.ActiveCfg = Release|Win32 {27B69211-D138-4142-BBC9-40F5DEA39067}.Release|x64.ActiveCfg = Release|Win32
{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.Debug|Win32.ActiveCfg = Debug|Win32
{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.Debug|Win32.Build.0 = Debug|Win32
{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.Debug|x64.ActiveCfg = Debug|x64
{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.Debug|x64.Build.0 = Debug|x64
{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.RD|Win32.ActiveCfg = RD|Win32
{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.RD|Win32.Build.0 = RD|Win32
{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.RD|x64.ActiveCfg = RD|x64
{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.RD|x64.Build.0 = RD|x64
{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.Release|Win32.ActiveCfg = RD|x64
{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.Release|x64.ActiveCfg = RD|x64
{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.Release|x64.Build.0 = RD|x64
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -6,7 +6,9 @@
[ [
{ {
"side" : 0, "side" : 0,
"army" : [[10, 40]] "army" : [[10, 40]],
"heroid" : 0,
"spells" : [1,2,3,4]
} }
{ {
"side" : 1, "side" : 1,

View File

@ -1193,6 +1193,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
ObjectConstruction h__l__p(this); ObjectConstruction h__l__p(this);
if(!curInt) curInt = LOCPLINT; //may happen when we are defending during network MP game if(!curInt) curInt = LOCPLINT; //may happen when we are defending during network MP game
bool duelMode = curInt->cb->getMyColor() < 0;
animsAreDisplayed.setn(false); animsAreDisplayed.setn(false);
pos = myRect; pos = myRect;
@ -1297,8 +1298,8 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
bOptions = new AdventureMapButton (CGI->generaltexth->zelp[381].first, CGI->generaltexth->zelp[381].second, boost::bind(&CBattleInterface::bOptionsf,this), 3 + pos.x, 561 + pos.y, "icm003.def", SDLK_o); bOptions = new AdventureMapButton (CGI->generaltexth->zelp[381].first, CGI->generaltexth->zelp[381].second, boost::bind(&CBattleInterface::bOptionsf,this), 3 + pos.x, 561 + pos.y, "icm003.def", SDLK_o);
bSurrender = new AdventureMapButton (CGI->generaltexth->zelp[379].first, CGI->generaltexth->zelp[379].second, boost::bind(&CBattleInterface::bSurrenderf,this), 54 + pos.x, 561 + pos.y, "icm001.def", SDLK_s); bSurrender = new AdventureMapButton (CGI->generaltexth->zelp[379].first, CGI->generaltexth->zelp[379].second, boost::bind(&CBattleInterface::bSurrenderf,this), 54 + pos.x, 561 + pos.y, "icm001.def", SDLK_s);
bFlee = new AdventureMapButton (CGI->generaltexth->zelp[380].first, CGI->generaltexth->zelp[380].second, boost::bind(&CBattleInterface::bFleef,this), 105 + pos.x, 561 + pos.y, "icm002.def", SDLK_r); bFlee = new AdventureMapButton (CGI->generaltexth->zelp[380].first, CGI->generaltexth->zelp[380].second, boost::bind(&CBattleInterface::bFleef,this), 105 + pos.x, 561 + pos.y, "icm002.def", SDLK_r);
bFlee->block(!curInt->cb->battleCanFlee()); bFlee->block(duelMode || !curInt->cb->battleCanFlee());
bSurrender->block(curInt->cb->battleGetSurrenderCost() < 0); bSurrender->block(duelMode || curInt->cb->battleGetSurrenderCost() < 0);
bAutofight = new AdventureMapButton (CGI->generaltexth->zelp[382].first, CGI->generaltexth->zelp[382].second, boost::bind(&CBattleInterface::bAutofightf,this), 157 + pos.x, 561 + pos.y, "icm004.def", SDLK_a); bAutofight = new AdventureMapButton (CGI->generaltexth->zelp[382].first, CGI->generaltexth->zelp[382].second, boost::bind(&CBattleInterface::bAutofightf,this), 157 + pos.x, 561 + pos.y, "icm004.def", SDLK_a);
bSpell = new AdventureMapButton (CGI->generaltexth->zelp[385].first, CGI->generaltexth->zelp[385].second, boost::bind(&CBattleInterface::bSpellf,this), 645 + pos.x, 561 + pos.y, "icm005.def", SDLK_c); bSpell = new AdventureMapButton (CGI->generaltexth->zelp[385].first, CGI->generaltexth->zelp[385].second, boost::bind(&CBattleInterface::bSpellf,this), 645 + pos.x, 561 + pos.y, "icm005.def", SDLK_c);
bSpell->block(true); bSpell->block(true);
@ -3869,6 +3870,8 @@ void CBattleInterface::endAction(const BattleAction* action)
if(tacticsMode) //we have activated next stack after sending request that has been just realized -> blockmap due to movement has changed if(tacticsMode) //we have activated next stack after sending request that has been just realized -> blockmap due to movement has changed
redrawBackgroundWithHexes(activeStack); redrawBackgroundWithHexes(activeStack);
waitForAnims();
} }
void CBattleInterface::hideQueue() void CBattleInterface::hideQueue()

View File

@ -456,6 +456,9 @@ private:
bool spellDestSelectMode; //if true, player is choosing destination for his spell bool spellDestSelectMode; //if true, player is choosing destination for his spell
SpellSelectionType spellSelMode; SpellSelectionType spellSelMode;
BattleAction * spellToCast; //spell for which player is choosing destination BattleAction * spellToCast; //spell for which player is choosing destination
bool duelMode;
void endCastingSpell(); //ends casting spell (eg. when spell has been cast or canceled) void endCastingSpell(); //ends casting spell (eg. when spell has been cast or canceled)
void showAliveStack(const CStack *stack, SDL_Surface * to); //helper function for function show void showAliveStack(const CStack *stack, SDL_Surface * to); //helper function for function show

View File

@ -285,9 +285,6 @@ int main(int argc, char** argv)
{ {
StartInfo *si = new StartInfo(); StartInfo *si = new StartInfo();
si->mode = StartInfo::DUEL; si->mode = StartInfo::DUEL;
si->mapname = vm["battle"].as<std::string>();
si->playerInfos[0].color = 0;
si->playerInfos[1].color = 1;
startGame(si); startGame(si);
} }
mainGUIThread = new boost::thread(&CGuiHandler::run, boost::ref(GH)); mainGUIThread = new boost::thread(&CGuiHandler::run, boost::ref(GH));
@ -718,9 +715,11 @@ void startGame(StartInfo * options, CConnection *serv/* = NULL*/)
{ {
case StartInfo::NEW_GAME: case StartInfo::NEW_GAME:
case StartInfo::CAMPAIGN: case StartInfo::CAMPAIGN:
case StartInfo::DUEL:
client->newGame(serv, options); client->newGame(serv, options);
break; break;
case StartInfo::DUEL:
client->newDuel(serv, options);
break;
case StartInfo::LOAD_GAME: case StartInfo::LOAD_GAME:
std::string fname = options->mapname; std::string fname = options->mapname;
boost::algorithm::erase_last(fname,".vlgm1"); boost::algorithm::erase_last(fname,".vlgm1");

View File

@ -101,13 +101,11 @@ void CClient::init()
} }
CClient::CClient(void) CClient::CClient(void)
:waitingRequest(0)
{ {
init(); init();
} }
CClient::CClient(CConnection *con, StartInfo *si) CClient::CClient(CConnection *con, StartInfo *si)
:waitingRequest(0)
{ {
init(); init();
newGame(con,si); newGame(con,si);
@ -418,6 +416,56 @@ void CClient::newGame( CConnection *con, StartInfo *si )
// } // }
} }
void CClient::newDuel(CConnection *con, StartInfo *si)
{
serv = con;
if(!serv)
{
std::string host = "127.0.0.1";
std::string port = "3030";
int i = 3;
while(!serv)
{
try
{
tlog0 << "Establishing connection...\n";
serv = new CConnection(host, port, "DLL host");
}
catch(...)
{
tlog1 << "\nCannot establish connection! Retrying within 2 seconds" << std::endl;
boost::this_thread::sleep(boost::posix_time::seconds(2));
if(!--i)
exit(0);
}
}
}
ui8 color;
std::string battleAIName;
*serv >> *si >> battleAIName >> color;
assert(si->mode == StartInfo::DUEL);
assert(color > 1); //we are NOT participants
//tlog0 << format("Server wants us to be %s in battle %s as side %d") % battleAIName % si.mapname % (int)color;
gs = new CGameState();
const_cast<CGameInfo*>(CGI)->state = gs;
//gs->scenarioOps = si;
gs->init(si, 0, 0);
CPlayerInterface *p = new CPlayerInterface(-1);
privilagedBattleEventReceivers.push_back(p);
p->observerInDuelMode = true;
battleints[254] = playerint[254] = p;
GH.curInt = p;
p->init(new CCallback(gs, -1, this));
battleStarted(gs->curB);
serv->addStdVecItems(const_cast<CGameInfo*>(CGI)->state);
}
template <typename Handler> template <typename Handler>
void CClient::serialize( Handler &h, const int version ) void CClient::serialize( Handler &h, const int version )
{ {

View File

@ -3,10 +3,9 @@
#include "../global.h" #include "../global.h"
#include <boost/thread.hpp>
#include "../lib/IGameCallback.h" #include "../lib/IGameCallback.h"
#include "../lib/CondSh.h"
#include <queue> #include <queue>
#include "../lib/CBattleCallback.h"
/* /*
* Client.h, part of VCMI engine * Client.h, part of VCMI engine
@ -60,7 +59,7 @@ public:
}; };
/// Class which handles client - server logic /// Class which handles client - server logic
class CClient : public IGameCallback class CClient : public IGameCallback, public IConnectionHandler
{ {
public: public:
CCallback *cb; CCallback *cb;
@ -70,7 +69,6 @@ public:
std::map<ui8,CGameInterface *> playerint; std::map<ui8,CGameInterface *> playerint;
std::map<ui8,CBattleGameInterface *> battleints; std::map<ui8,CBattleGameInterface *> battleints;
bool hotSeat; bool hotSeat;
CConnection *serv;
BattleAction *curbaction; BattleAction *curbaction;
CPathsInfo *pathInfo; CPathsInfo *pathInfo;
@ -78,7 +76,6 @@ public:
CScriptingModule *erm; CScriptingModule *erm;
CondSh<int> waitingRequest;
std::queue<CPack *> packs; std::queue<CPack *> packs;
boost::mutex packsM; boost::mutex packsM;
@ -91,6 +88,7 @@ public:
void init(); void init();
void newGame(CConnection *con, StartInfo *si); //con - connection to server void newGame(CConnection *con, StartInfo *si); //con - connection to server
void newDuel(CConnection *con, StartInfo *si); //con - connection to server
void loadNeutralBattleAI(); void loadNeutralBattleAI();
void endGame(bool closeConnection = true); void endGame(bool closeConnection = true);

61
lib/CBattleCallback.cpp Normal file
View File

@ -0,0 +1,61 @@
#define VCMI_DLL
#include "CBattleCallback.h"
#include "NetPacks.h"
#include "Connection.h"
#include "CGameState.h"
#include <boost/thread/shared_mutex.hpp>
#include "BattleState.h"
CBattleCallback::CBattleCallback(CGameState *GS, int Player, IConnectionHandler *C )
{
gs = GS;
player = Player;
connHandler = C;
}
bool CBattleCallback::battleMakeTacticAction( BattleAction * action )
{
assert(gs->curB->tacticDistance);
MakeAction ma;
ma.ba = *action;
sendRequest(&ma);
return true;
}
int CBattleCallback::battleMakeAction(BattleAction* action)
{
assert(action->actionType == BattleAction::HERO_SPELL);
MakeCustomAction mca(*action);
sendRequest(&mca);
return 0;
}
void CBattleCallback::sendRequest(const CPack* request)
{
//TODO should be part of CClient (client owns connection, not CB)
//but it would have to be very tricky cause template/serialization issues
if(waitTillRealize)
connHandler->waitingRequest.set(typeList.getTypeID(request));
connHandler->serv->sendPack(*request);
if(waitTillRealize)
{
if(unlockGsWhenWaiting)
gs->mx->unlock_shared();
connHandler->waitingRequest.waitWhileTrue();
if(unlockGsWhenWaiting)
gs->mx->lock_shared();
}
}
IConnectionHandler::IConnectionHandler()
: waitingRequest(0)
{
}
IConnectionHandler::~IConnectionHandler()
{
}

42
lib/CBattleCallback.h Normal file
View File

@ -0,0 +1,42 @@
#pragma once
#include "../global.h"
#include "IGameCallback.h"
#include "CondSh.h"
class CConnection;
class DLL_EXPORT IConnectionHandler
{
public:
IConnectionHandler();
~IConnectionHandler();
CConnection *serv;
CondSh<int> waitingRequest;
};
class DLL_EXPORT IBattleCallback
{
public:
bool waitTillRealize; //if true, request functions will return after they are realized by server
bool unlockGsWhenWaiting;//if true after sending each request, gs mutex will be unlocked so the changes can be applied; NOTICE caller must have gs mx locked prior to any call to actiob callback!
//battle
virtual int battleMakeAction(BattleAction* action)=0;//for casting spells by hero - DO NOT use it for moving active stack
virtual bool battleMakeTacticAction(BattleAction * action) =0; // performs tactic phase actions
};
class DLL_EXPORT CBattleCallback : public IBattleCallback, public CBattleInfoCallback
{
protected:
void sendRequest(const CPack *request);
IConnectionHandler *connHandler;
//virtual bool hasAccess(int playerId) const;
public:
CBattleCallback(CGameState *GS, int Player, IConnectionHandler *C);
int battleMakeAction(BattleAction* action) OVERRIDE;//for casting spells by hero - DO NOT use it for moving active stack
bool battleMakeTacticAction(BattleAction * action) OVERRIDE; // performs tactic phase actions
friend class CCallback;
friend class CClient;
};

View File

@ -2720,6 +2720,12 @@ DuelParameters DuelParameters::fromJSON(const std::string &fname)
ss.stacks[i].count = stackNode.Vector()[1].Float(); ss.stacks[i].count = stackNode.Vector()[1].Float();
i++; i++;
} }
ss.heroId = n["heroid"].Float();
if(ss.heroId != -1)
BOOST_FOREACH(const JsonNode &spell, n["spells"].Vector())
ss.spells.insert(spell.Float());
} }
return ret; return ret;

View File

@ -214,6 +214,7 @@
<ClCompile Include="BattleAction.cpp" /> <ClCompile Include="BattleAction.cpp" />
<ClCompile Include="BattleState.cpp" /> <ClCompile Include="BattleState.cpp" />
<ClCompile Include="CArtHandler.cpp" /> <ClCompile Include="CArtHandler.cpp" />
<ClCompile Include="CBattleCallback.cpp" />
<ClCompile Include="CBuildingHandler.cpp" /> <ClCompile Include="CBuildingHandler.cpp" />
<ClCompile Include="CCampaignHandler.cpp" /> <ClCompile Include="CCampaignHandler.cpp" />
<ClCompile Include="CCreatureHandler.cpp" /> <ClCompile Include="CCreatureHandler.cpp" />
@ -247,6 +248,7 @@
<ClInclude Include="..\CConsoleHandler.h" /> <ClInclude Include="..\CConsoleHandler.h" />
<ClInclude Include="BattleState.h" /> <ClInclude Include="BattleState.h" />
<ClInclude Include="CArtHandler.h" /> <ClInclude Include="CArtHandler.h" />
<ClInclude Include="CBattleCallback.h" />
<ClInclude Include="CBuildingHandler.h" /> <ClInclude Include="CBuildingHandler.h" />
<ClInclude Include="CCampaignHandler.h" /> <ClInclude Include="CCampaignHandler.h" />
<ClInclude Include="CCreatureHandler.h" /> <ClInclude Include="CCreatureHandler.h" />

View File

@ -456,7 +456,6 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
winnerHero->showNecromancyDialog(raisedStack); winnerHero->showNecromancyDialog(raisedStack);
addToSlot(StackLocation(winnerHero, necroSlot), raisedStack.type, raisedStack.count); addToSlot(StackLocation(winnerHero, necroSlot), raisedStack.type, raisedStack.count);
} }
sendAndApply(&resultsApplied);
if(duel) if(duel)
{ {
@ -471,10 +470,14 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
tlog0 << boost::format("\t* %d of %s\n") % i->second % c->namePl; tlog0 << boost::format("\t* %d of %s\n") % i->second % c->namePl;
casualtiesPoints = c->AIValue * i->second; casualtiesPoints = c->AIValue * i->second;
} }
tlog0 << boost::format("Total causalties points: %d\n") % casualtiesPoints; tlog0 << boost::format("Total casualties points: %d\n") % casualtiesPoints;
return;
} }
sendAndApply(&resultsApplied);
if(duel)
return;
if(visitObjectAfterVictory && winnerHero == hero1) if(visitObjectAfterVictory && winnerHero == hero1)
{ {
visitObjectOnTile(*getTile(winnerHero->getPosition()), winnerHero); visitObjectOnTile(*getTile(winnerHero->getPosition()), winnerHero);