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

Improved threa-safety, almost finished building structures in towns.

This commit is contained in:
Michał W. Urbańczyk 2008-08-01 11:21:15 +00:00
parent 5c5c80933b
commit e5a064f36b
20 changed files with 202 additions and 52 deletions

View File

@ -112,7 +112,7 @@ void CCallback::recruitCreatures(const CGObjectInstance *obj, int ID, int amount
//verify
bool found = false;
typedef std::pair<const int,int> Parka;
for(std::map<int,int>::iterator av=t->strInfo.creatures.begin();av!=t->strInfo.creatures.end();av++)
for(std::map<si32,ui32>::iterator av=t->strInfo.creatures.begin();av!=t->strInfo.creatures.end();av++)
{
if( ( found = (ID == t->town->basicCreatures[av->first]) ) //creature is available among basic cretures
|| (found = (ID == t->town->upgradedCreatures[av->first])) )//creature is available among upgraded cretures
@ -172,11 +172,9 @@ void CCallback::recruitCreatures(const CGObjectInstance *obj, int ID, int amount
bool CCallback::dismissCreature(const CArmedInstance *obj, int stackPos)
{
if((player>=0) && obj->tempOwner != player)
if(((player>=0) && obj->tempOwner != player) || obj->army.slots.size()<2)
return false;
CArmedInstance *ob = const_cast<CArmedInstance*>(obj);
ob->army.slots.erase(stackPos);
cl->playerint[player]->garrisonChanged(obj);
*cl->serv << ui16(503) << obj->id << ui8(stackPos);
return true;
}
bool CCallback::upgradeCreature(const CArmedInstance *obj, int stackPos, int newID)
@ -202,7 +200,7 @@ UpgradeInfo CCallback::getUpgradeInfo(const CArmedInstance *obj, int stackPos)
t = static_cast<CGTownInstance *>(const_cast<CArmedInstance *>(obj));
else
t = static_cast<const CGHeroInstance*>(obj)->visitedTown;
for(std::set<int>::iterator i=t->builtBuildings.begin(); i!=t->builtBuildings.end(); i++)
for(std::set<si32>::iterator i=t->builtBuildings.begin(); i!=t->builtBuildings.end(); i++)
{
if( (*i) >= 37 && (*i) < 44 ) //upgraded creature dwelling
{
@ -283,7 +281,7 @@ int CCallback::getResourceAmount(int type)
{
return gs->players[player].resources[type];
}
std::vector<int> CCallback::getResourceAmount()
std::vector<si32> CCallback::getResourceAmount()
{
return gs->players[player].resources;
}
@ -472,31 +470,19 @@ bool CCallback::swapArifacts(const CGHeroInstance * hero1, bool worn1, int pos1,
return true;
}
bool CCallback::buildBuilding(const CGTownInstance *town, int buildingID)
bool CCallback::buildBuilding(const CGTownInstance *town, si32 buildingID)
{
CGTownInstance * t = const_cast<CGTownInstance *>(town);
CBuilding *b = CGI->buildh->buildings[t->subID][buildingID];
if(0/*not allowed*/)//TODO: check if we are allowed to build
if(town->tempOwner!=player)
return false;
if(buildingID>36) //upg dwelling
{
if(t->getHordeLevel(0) == (buildingID-37))
t->builtBuildings.insert(19);
else if(t->getHordeLevel(1) == (buildingID-37))
t->builtBuildings.insert(25);
}
else if(buildingID >= 30) //bas. dwelling
{
t->strInfo.creatures[buildingID-30] = CGI->creh->creatures[t->town->basicCreatures[buildingID-30]].growth;
}
t->builtBuildings.insert(buildingID);
CBuilding *b = CGI->buildh->buildings[t->subID][buildingID];
for(int i=0;i<7;i++)
gs->players[player].resources[i]-=b->resources[i];
t->builded++;
cl->playerint[player]->buildChanged(town,buildingID,1);
if(b->resources[i] > gs->players[player].resources[i])
return false; //lack of resources
*cl->serv << ui16(504) << town->id << buildingID;
//TODO: check if we are allowed to build
return true;
}

View File

@ -107,7 +107,7 @@ public:
int splitStack(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2, int val);
bool dismissHero(const CGHeroInstance * hero);
bool swapArifacts(const CGHeroInstance * hero1, bool worn1, int pos1, const CGHeroInstance * hero2, bool worn2, int pos2);
bool buildBuilding(const CGTownInstance *town, int buildingID);
bool buildBuilding(const CGTownInstance *town, si32 buildingID);
void recruitCreatures(const CGObjectInstance *obj, int ID, int amount);
bool dismissCreature(const CArmedInstance *obj, int stackPos);
bool upgradeCreature(const CArmedInstance *obj, int stackPos, int newID=-1);
@ -119,7 +119,7 @@ public:
std::vector< std::vector< std::vector<unsigned char> > > & getVisibilityMap(); //returns visibility map (TODO: make it const)
const CGHeroInstance * getHeroInfo(int player, int val, bool mode); //mode = 0 -> val = serial; mode = 1 -> val = ID
int getResourceAmount(int type);
std::vector<int> getResourceAmount();
std::vector<si32> getResourceAmount();
int howManyHeroes();
const CGTownInstance * getTownInfo(int val, bool mode); //mode = 0 -> val = serial; mode = 1 -> val = ID
std::vector < const CGTownInstance *> getTownsInfo(bool onlyOur=true);

View File

@ -533,7 +533,7 @@ void CCastleInterface::recreateBuildings()
std::set< std::pair<int,int> > s; //group - id
for (std::set<int>::const_iterator i=town->builtBuildings.begin();i!=town->builtBuildings.end();i++)
for (std::set<si32>::const_iterator i=town->builtBuildings.begin();i!=town->builtBuildings.end();i++)
{
if(CGI->townh->structures.find(town->subID) != CGI->townh->structures.end()) //we have info about structures in this town
{

View File

@ -128,6 +128,13 @@ void CGameState::apply(IPack * pack)
players[sr->player].resources[sr->resid] = sr->val;
break;
}
case 104:
{
SetResources *sr = static_cast<SetResources*>(pack);
for(int i=0;sr->res.size();i++)
players[sr->player].resources[i] = sr->res[i];
break;
}
case 501://hero try-move
{
TryMoveHero * n = static_cast<TryMoveHero*>(pack);
@ -148,6 +155,21 @@ void CGameState::apply(IPack * pack)
static_cast<CArmedInstance*>(map->objects[i->first])->army = i->second;
break;
}
case 503:
{
SetStrInfo *ssi = static_cast<SetStrInfo*>(pack);
static_cast<CGTownInstance*>(map->objects[ssi->tid])->strInfo.creatures = ssi->cres;
break;
}
case 504:
{
NewStructures *ns = static_cast<NewStructures*>(pack);
CGTownInstance*t = static_cast<CGTownInstance*>(map->objects[ns->tid]);
BOOST_FOREACH(si32 bid,ns->bid)
t->builtBuildings.insert(bid);
t->builded = ns->builded;
break;
}
case 1001://set object property
{
SetObjectProperty *p = static_cast<SetObjectProperty*>(pack);

View File

@ -33,9 +33,9 @@ namespace boost
struct DLL_EXPORT PlayerState
{
public:
int color, serial;
std::vector<std::vector<std::vector<unsigned char> > > fogOfWarMap; //true - visible, false - hidden
std::vector<int> resources;
ui8 color, serial;
std::vector<std::vector<std::vector<ui8> > > fogOfWarMap; //true - visible, false - hidden
std::vector<si32> resources;
std::vector<CGHeroInstance *> heroes;
std::vector<CGTownInstance *> towns;
PlayerState():color(-1){};

View File

@ -31,7 +31,6 @@
#include "hch/CHeroHandler.h"
#include "hch/CCreatureHandler.h"
#include "hch/CSpellHandler.h"
#include "hch/CBuildingHandler.h"
#include "hch/CMusicHandler.h"
#include "hch/CLodHandler.h"
#include "hch/CDefHandler.h"
@ -106,6 +105,7 @@ int _tmain(int argc, _TCHAR* argv[])
CGI->heroh = VLC->heroh;
CGI->objh = VLC->objh;
CGI->dobjinfo = VLC->dobjinfo;
CGI->buildh = VLC->buildh;
THC std::cout<<"Initializing VCMI_Lib: "<<tmh.getDif()<<std::endl;
@ -152,12 +152,6 @@ int _tmain(int argc, _TCHAR* argv[])
cgi->spellh = spellh;
THC std::cout<<"\tSpell handler: "<<pomtime.getDif()<<std::endl;
CBuildingHandler * buildh = new CBuildingHandler;
buildh->loadBuildings();
cgi->buildh = buildh;
THC std::cout<<"\tBuilding handler: "<<pomtime.getDif()<<std::endl;
cgi->pathf = new CPathfinder();
THC std::cout<<"\tPathfinder: "<<pomtime.getDif()<<std::endl;

View File

@ -920,6 +920,11 @@ CPlayerInterface::CPlayerInterface(int Player, int serial)
playerID=Player;
serialID=serial;
human=true;
pim = new boost::mutex;
}
CPlayerInterface::~CPlayerInterface()
{
delete pim;
}
void CPlayerInterface::init(ICallback * CB)
{
@ -989,6 +994,9 @@ void CPlayerInterface::yourTurn()
//}
//water tiles updated
CGI->screenh->updateScreen();
pim->lock();
int tv = th.getDif();
for (int i=0;i<timeinterested.size();i++)
{
@ -1065,6 +1073,7 @@ void CPlayerInterface::yourTurn()
}
for(int i=0;i<objsToBlit.size();i++)
objsToBlit[i]->show();
pim->unlock();
//SDL_Flip(screen);
CSDL_Ext::update(screen);
SDL_Delay(5); //give time for other apps
@ -1137,6 +1146,7 @@ void CPlayerInterface::heroMoved(const HeroMoveDetails & details)
//initializing objects and performing first step of move
CGHeroInstance * ho = details.ho; //object representing this hero
int3 hp = details.src;
boost::unique_lock<boost::mutex> un(*pim);
if (!details.successful)
{
ho->moveDir = getDir(details.src,details.dst);
@ -1878,6 +1888,7 @@ void CPlayerInterface::heroVisitsTown(const CGHeroInstance* hero, const CGTownIn
}
void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj)
{
boost::unique_lock<boost::mutex> un(*pim);
if(obj->ID == 34) //hero
{
const CGHeroInstance * hh;
@ -1922,6 +1933,7 @@ void CPlayerInterface::buildChanged(const CGTownInstance *town, int buildingID,
return;
if(castleInt->town!=town)
return;
boost::unique_lock<boost::mutex> un(*pim);
switch(what)
{
case 1:

View File

@ -25,6 +25,11 @@ class CCreatureSet;
class CGObjectInstance;
class CSlider;
namespace boost
{
class mutex;
};
class IShowable
{
public:
@ -292,6 +297,7 @@ class CPlayerInterface : public CGameInterface
{
public:
//minor interfaces
boost::mutex *pim;
bool makingTurn;
SDL_Event * current;
IActivable *curint;
@ -356,6 +362,7 @@ public:
void showInfoDialog(std::string text, std::vector<SComponent*> & components);
CPlayerInterface(int Player, int serial);//c-tor
~CPlayerInterface();//d-tor
};
class CStatusBar
: public CIntObject, public IStatusBar

View File

@ -11,6 +11,7 @@
#include "../lib/NetPacks.h"
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/foreach.hpp>
#include "../hch/CObjectHandler.h"
#include "../hch/CGeneralTextHandler.h"
#include "../hch/CArtHandler.h"
@ -190,6 +191,15 @@ void CClient::process(int what)
playerint[iw.player]->showInfoDialog(toString(iw.text),comps);
break;
}
case 104:
{
SetResources sr;
*serv >> sr;
std::cout << "Set amount of resources of player "<<(unsigned)sr.player<<std::endl;
gs->apply(&sr);
playerint[sr.player]->receivedResource(-1,-1);
break;
}
case 501: //hero movement response - we have to notify interfaces and callback
{
TryMoveHero *th = new TryMoveHero; //will be deleted by callback after processing
@ -235,6 +245,23 @@ void CClient::process(int what)
playerint[gs->map->objects[i->first]->tempOwner]->garrisonChanged(gs->map->objects[i->first]);
break;
}
case 503:
{
SetStrInfo ssi;
*serv >> ssi;
gs->apply(&ssi);
//TODO: notify interfaces
break;
}
case 504:
{
NewStructures ns;
*serv >> ns;
gs->apply(&ns);
BOOST_FOREACH(si32 bid, ns.bid)
playerint[gs->map->objects[ns.tid]->tempOwner]->buildChanged(static_cast<CGTownInstance*>(gs->map->objects[ns.tid]),bid,1);
break;
}
case 1001:
{
SetObjectProperty sop;

View File

@ -28,6 +28,7 @@ unsigned int readNr(std::string &in, unsigned int &it)
CBuilding * readBg(std::string &buf, unsigned int& it)
{
CBuilding * nb = new CBuilding();
nb->resources.resize(RESOURCE_QUANTITY);
for(int res=0;res<7;res++)
nb->resources[res] = readNr(buf,it);
nb->refName = readTo(buf,it,'\n');

View File

@ -2,13 +2,14 @@
#define CBUILDINGHANDLER_H
#include "../global.h"
#include <map>
#include <vector>
//enum EbuildingType {NEUTRAL=-1, CASTLE, RAMPART, TOWER, INFERNO, NECROPOLIS, DUNGEON, STRONGHOLD, FORTRESS, CONFLUX};
class DLL_EXPORT CBuilding //a typical building encountered in every castle ;]
{
public:
std::string name;
std::string refName; //reference name, for identification
int resources[7];
std::vector<int> resources;
std::string description;
//EbuildingType type; //type of building (occures in many castles or is specific for one castle)
//bool isDwelling; //true, if this building is a dwelling

View File

@ -45,13 +45,13 @@ bool CCreature::isFlying()
{
return boost::algorithm::find_first(abilityRefs, "FLYING_ARMY");
}
int CCreature::maxAmount(const std::vector<int> &res) const //how many creatures can be bought
si32 CCreature::maxAmount(const std::vector<si32> &res) const //how many creatures can be bought
{
int ret = 2147483645;
int resAmnt = std::min(res.size(),cost.size());
for(int i=0;i<resAmnt;i++)
if(cost[i])
ret = std::min(ret,res[i]/cost[i]);
ret = std::min(ret,(int)(res[i]/cost[i]));
return ret;
}

View File

@ -40,7 +40,7 @@ public:
bool isDoubleWide(); //returns true if unit is double wide on battlefield
bool isFlying(); //returns true if it is a flying unit
int maxAmount(const std::vector<int> &res) const; //how many creatures can be bought
si32 maxAmount(const std::vector<si32> &res) const; //how many creatures can be bought
static int getQuantityID(int quantity); //0 - a few, 1 - several, 2 - pack, 3 - lots, 4 - horde, 5 - throng, 6 - swarm, 7 - zounds, 8 - legion
};

View File

@ -140,12 +140,17 @@ public:
const CGHeroInstance * garrisonHero, *visitingHero;
int identifier; //special identifier from h3m (only > RoE maps)
int alignment;
std::set<int> forbiddenBuildings, builtBuildings;
std::set<si32> forbiddenBuildings, builtBuildings;
std::vector<int> possibleSpells, obligatorySpells, availableSpells;
struct StrInfo
{
std::map<int,int> creatures; //level - available amount
std::map<si32,ui32> creatures; //level - available amount
template <typename Handler> void serialize(Handler &h, const int version)
{
h & creatures;
}
} strInfo;
std::set<CCastleEvent> events;

View File

@ -71,6 +71,17 @@ struct SetResource : public CPack<SetResource> //102
h & player & resid & val;
}
};
struct SetResources : public CPack<SetResources> //104
{
SetResources(){type = 104;};
ui8 player;
std::vector<si32> res; //res[resid] => res amount
template <typename Handler> void serialize(Handler &h, const int version)
{
h & player & res;
}
};
struct TryMoveHero : public CPack<TryMoveHero> //501
{
TryMoveHero(){type = 501;};
@ -95,6 +106,29 @@ struct SetGarrisons : public CPack<SetGarrisons> //502
h & garrs;
}
};
struct SetStrInfo : public CPack<SetStrInfo> //503
{
SetStrInfo(){type = 503;};
si32 tid;
std::map<si32,ui32> cres;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & tid & cres;
}
};
struct NewStructures : public CPack<NewStructures> //504
{
NewStructures(){type = 504;};
si32 tid;
std::set<si32> bid;
si16 builded;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & tid & bid & builded;
}
};
struct MetaString : public CPack<MetaString> //2001 helper for object scrips
{
std::vector<std::string> strings;

View File

@ -7,6 +7,7 @@
#include "../hch/CHeroHandler.h"
#include "../hch/CObjectHandler.h"
#include "../hch/CTownHandler.h"
#include "../hch/CBuildingHandler.h"
class CLodHandler;
LibClasses * VLC = NULL;
CLodHandler * bitmaph=NULL;
@ -45,6 +46,10 @@ DLL_EXPORT void initDLL(CLodHandler *b)
VLC->dobjinfo = new CDefObjInfoHandler;
VLC->dobjinfo->load();
THC std::cout<<"\tDef information handler: "<<pomtime.getDif()<<std::endl;
VLC->buildh = new CBuildingHandler;
VLC->buildh->loadBuildings();
THC std::cout<<"\tBuilding handler: "<<pomtime.getDif()<<std::endl;
}
DLL_EXPORT void loadToIt(std::string &dest, std::string &src, int &iter, int mode)

View File

@ -9,7 +9,7 @@ class CCreatureHandler;
//class CSpellHandler;
//class CAmbarCendamo;
//class CPreGameTextHandler;
//class CBuildingHandler;
class CBuildingHandler;
class CObjectHandler;
//class CMusicHandler;
//class CSemiLodHandler;
@ -37,7 +37,7 @@ public:
//CSpellHandler * spellh;
//CMapHandler * mh;
//CPreGameTextHandler * preth;
//CBuildingHandler * buildh;
CBuildingHandler * buildh;
CObjectHandler * objh;
//CMusicHandler * mush;
//CSemiLodHandler * sspriteh;

View File

@ -6,10 +6,10 @@
#include "lib/VCMI_Lib.h"
#include <zlib.h>
#include <boost/crc.hpp>
std::set<int> convertBuildings(const std::set<int> h3m, int castleID)
std::set<si32> convertBuildings(const std::set<si32> h3m, int castleID)
{
std::map<int,int> mapa;
std::set<int> ret;
std::set<si32> ret;
std::ifstream b5("config/buildings5.txt");
while(!b5.eof())
{
@ -20,7 +20,7 @@ std::set<int> convertBuildings(const std::set<int> h3m, int castleID)
mapa[a]=b;
}
for(std::set<int>::const_iterator i=h3m.begin();i!=h3m.end();i++)
for(std::set<si32>::const_iterator i=h3m.begin();i!=h3m.end();i++)
{
if(mapa[*i]>=0)
ret.insert(mapa[*i]);

View File

@ -13,6 +13,7 @@
#include "../CLua.h"
#include "../hch/CObjectHandler.h"
#include "../hch/CTownHandler.h"
#include "../hch/CBuildingHandler.h"
#include "../hch/CHeroHandler.h"
#include "boost/date_time/posix_time/posix_time_types.hpp" //no i/o just types
#include "../lib/VCMI_Lib.h"
@ -223,6 +224,61 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
if(s1 != s2)
sg.garrs[id2] = *S2;
sendAndApply(&sg);
break;
}
case 503:
{
si32 id;
ui8 pos;
c >> id >> pos;
CArmedInstance *s1 = static_cast<CArmedInstance*>(gs->map->objects[id]);
s1->army.slots.erase(pos);
SetGarrisons sg;
sg.garrs[id] = s1->army;
sendAndApply(&sg);
break;
}
case 504:
{
si32 tid, bid;
c >> tid >> bid;
CGTownInstance * t = static_cast<CGTownInstance*>(gs->map->objects[tid]);
CBuilding * b = VLC->buildh->buildings[t->subID][bid];
for(int i=0;i<RESOURCE_QUANTITY;i++)
if(b->resources[i] > gs->players[t->tempOwner].resources[i])
break; //no res
//TODO: check requirements
//TODO: check if building isn't forbidden
NewStructures ns;
ns.tid = tid;
if(bid>36) //upg dwelling
{
if(t->getHordeLevel(0) == (bid-37))
ns.bid.insert(19);
else if(t->getHordeLevel(1) == (bid-37))
ns.bid.insert(25);
}
else if(bid >= 30) //bas. dwelling
{
SetStrInfo ssi;
ssi.tid = tid;
ssi.cres = t->strInfo.creatures;
ssi.cres[bid-30] = VLC->creh->creatures[t->town->basicCreatures[bid-30]].growth;
sendAndApply(&ssi);
}
ns.bid.insert(bid);
ns.builded = t->builded + 1;
sendAndApply(&ns);
SetResources sr;
sr.player = t->tempOwner;
sr.res = gs->players[t->tempOwner].resources;
for(int i=0;i<7;i++)
sr.res[i]-=b->resources[i];
sendAndApply(&sr);
break;
}
default:

View File

@ -121,7 +121,7 @@ int CScriptCallback::getSelectedHero()
// ret = ((CGHeroInstance*)(LOCPLINT->adventureInt->selection.selected))->subID;
//else
// ret = -1;;
return ret;
return -1;
}
int CScriptCallback::getDate(int mode)
{