diff --git a/CCallback.cpp b/CCallback.cpp index 79d11da67..c88d2b1d4 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -26,7 +26,7 @@ #ifdef max #undef max #endif -extern CSharedCond > mess; +extern CSharedCond > mess; int gcd(int x, int y) { @@ -48,6 +48,12 @@ HeroMoveDetails::HeroMoveDetails(int3 Src, int3 Dst, CGHeroInstance*Ho) { owner = ho->getOwner(); }; + +template bool isType(CPack *pack) +{ + return pack->getType() == N; +} + bool CCallback::moveHero(int ID, CPath * path, int idtype, int pathType) { CGHeroInstance * hero = NULL; @@ -108,9 +114,9 @@ bool CCallback::moveHero(int ID, CPath * path, int idtype, int pathType) *cl->serv << ui16(501) << hero->id << stpos << endpos; {//wait till there is server answer boost::unique_lock lock(*mess.mx); - while(std::find_if(mess.res->begin(),mess.res->end(),IPack::isType<501>) == mess.res->end()) + while(std::find_if(mess.res->begin(),mess.res->end(),&isType<501>) == mess.res->end()) mess.cv->wait(lock); - std::set::iterator itr = std::find_if(mess.res->begin(),mess.res->end(),IPack::isType<501>); + std::set::iterator itr = std::find_if(mess.res->begin(),mess.res->end(),&isType<501>); TryMoveHero tmh = *static_cast(*itr); mess.res->erase(itr); if(!tmh.result) diff --git a/CGameInterface.cpp b/CGameInterface.cpp index 71adbe426..af65766a3 100644 --- a/CGameInterface.cpp +++ b/CGameInterface.cpp @@ -1,34 +1,19 @@ #include "stdafx.h" #include "CGameInterface.h" -#include "CAdvmapInterface.h" -#include "CMessage.h" -#include "mapHandler.h" -#include "SDL_Extensions.h" -#include "SDL_framerate.h" -#include "CCursorHandler.h" -#include "CCallback.h" -#include "SDL_Extensions.h" -#include "hch/CLodHandler.h" -#include "CPathfinder.h" -#include -#include "hch/CHeroHandler.h" -#include "SDL_framerate.h" -#include "AI/EmptyAI/CEmptyAI.h" #ifdef _WIN32 #include //for .dll libs #else #include #endif -using namespace CSDL_Ext; CGlobalAI * CAIHandler::getNewAI(CCallback * cb, std::string dllname) { char temp[50]; dllname = "AI/"+dllname; CGlobalAI * ret=NULL; - CGlobalAI*(*getAI)(); //TODO use me - void(*getName)(char*); //TODO use me + CGlobalAI*(*getAI)(); + void(*getName)(char*); #ifdef _WIN32 HINSTANCE dll = LoadLibraryA(dllname.c_str()); @@ -52,6 +37,3 @@ CGlobalAI * CAIHandler::getNewAI(CCallback * cb, std::string dllname) return ret; } -//CGlobalAI::CGlobalAI() -//{ -//} diff --git a/CGameState.cpp b/CGameState.cpp index 6241d801e..6979f2547 100644 --- a/CGameState.cpp +++ b/CGameState.cpp @@ -491,512 +491,13 @@ CGHeroInstance* CGameState::HeroesPool::pickHeroFor(bool native, int player, con } } -void CGameState::applyNL(IPack * pack) -{ - switch(pack->getType()) - { - case 101://NewTurn - { - NewTurn * n = static_cast(pack); - day = n->day; - BOOST_FOREACH(NewTurn::Hero h, n->heroes) //give mana/movement point - { - static_cast(map->objects[h.id])->movement = h.move; - static_cast(map->objects[h.id])->mana = h.mana; - } - BOOST_FOREACH(SetResources h, n->res) //give resources - applyNL(&h); - BOOST_FOREACH(SetAvailableCreatures h, n->cres) //set available creatures in towns - applyNL(&h); - if(n->resetBuilded) //reset amount of structures set in this turn in towns - BOOST_FOREACH(CGTownInstance* t, map->towns) - t->builded = 0; - BOOST_FOREACH(CGHeroInstance *h, map->heroes) - h->bonuses.remove_if(HeroBonus::OneDay); - if(getDate(1) == 7) //new week - BOOST_FOREACH(CGHeroInstance *h, map->heroes) - h->bonuses.remove_if(HeroBonus::OneWeek); - break; - } - case 102: //set resource amount - { - SetResource *sr = static_cast(pack); - players[sr->player].resources[sr->resid] = sr->val; - break; - } - case 104: - { - SetResources *sr = static_cast(pack); - for(int i=0;ires.size();i++) - players[sr->player].resources[i] = sr->res[i]; - break; - } - case 105: - { - SetPrimSkill *sr = static_cast(pack); - CGHeroInstance *hero = getHero(sr->id); - if(sr->which <4) - { - if(sr->abs) - hero->primSkills[sr->which] = sr->val; - else - hero->primSkills[sr->which] += sr->val; - } - else if(sr->which == 4) //XP - { - if(sr->abs) - hero->exp = sr->val; - else - hero->exp += sr->val; - } - break; - } - case 106: - { - SetSecSkill *sr = static_cast(pack); - CGHeroInstance *hero = getHero(sr->id); - if(hero->getSecSkillLevel(sr->which) == 0) - { - hero->secSkills.push_back(std::pair(sr->which, sr->val)); - } - else - { - for(unsigned i=0;isecSkills.size();i++) - { - if(hero->secSkills[i].first == sr->which) - { - if(sr->abs) - hero->secSkills[i].second = sr->val; - else - hero->secSkills[i].second += sr->val; - } - } - } - break; - } - case 108: - { - HeroVisitCastle *vc = static_cast(pack); - CGHeroInstance *h = getHero(vc->hid); - CGTownInstance *t = getTown(vc->tid); - if(vc->start()) - { - if(vc->garrison()) - { - t->garrisonHero = h; - h->visitedTown = t; - h->inTownGarrison = true; - } - else - { - t->visitingHero = h; - h->visitedTown = t; - h->inTownGarrison = false; - } - } - else - { - if(vc->garrison()) - { - t->garrisonHero = NULL; - h->visitedTown = NULL; - h->inTownGarrison = false; - } - else - { - t->visitingHero = NULL; - h->visitedTown = NULL; - h->inTownGarrison = false; - } - } - break; - } - case 109: - { - ChangeSpells *rh = static_cast(pack); - CGHeroInstance *hero = getHero(rh->hid); - if(rh->learn) - BOOST_FOREACH(ui32 sid, rh->spells) - hero->spells.insert(sid); - else - BOOST_FOREACH(ui32 sid, rh->spells) - hero->spells.erase(sid); - break; - } - case 110: - { - SetMana *rh = static_cast(pack); - CGHeroInstance *hero = getHero(rh->hid); - hero->mana = rh->val; - break; - } - case 111: - { - SetMovePoints *rh = static_cast(pack); - CGHeroInstance *hero = getHero(rh->hid); - hero->movement = rh->val; - break; - } - case 112: - { - FoWChange *rh = static_cast(pack); - BOOST_FOREACH(int3 t, rh->tiles) - players[rh->player].fogOfWarMap[t.x][t.y][t.z] = rh->mode; - break; - } - case 113: - { - SetAvailableHeroes *rh = static_cast(pack); - players[rh->player].availableHeroes.clear(); - - CGHeroInstance *h = (rh->hid1>=0 ? hpool.heroesPool[rh->hid1] : NULL); - players[rh->player].availableHeroes.push_back(h); - if(h && rh->flags & 1) - { - h->army.slots.clear(); - h->army.slots[0] = std::pair(VLC->creh->nameToID[h->type->refTypeStack[0]],1); - } - - h = (rh->hid2>=0 ? hpool.heroesPool[rh->hid2] : NULL); - players[rh->player].availableHeroes.push_back(h); - if(rh->flags & 2) - { - h->army.slots.clear(); - h->army.slots[0] = std::pair(VLC->creh->nameToID[h->type->refTypeStack[0]],1); - } - break; - } - case 115: - { - GiveBonus *rh = static_cast(pack); - CGHeroInstance *h = getHero(rh->hid); - h->bonuses.push_back(rh->bonus); - h->bonuses.back().description = toString(rh->bdescr); - break; - } - case 116: - { - ChangeObjPos *rh = static_cast(pack); - CGObjectInstance *obj = map->objects[rh->objid]; - if(!obj) - { - tlog1 << "Wrong ChangeObjPos: object " << rh->objid << " doesn't exist!\n"; - return; - } - map->removeBlockVisTiles(obj); - obj->pos = rh->nPos; - map->addBlockVisTiles(obj); - break; - } - case 500: - { - RemoveObject *rh = static_cast(pack); - CGObjectInstance *obj = map->objects[rh->id]; - if(obj->ID==HEROI_TYPE) - { - CGHeroInstance *h = static_cast(obj); - std::vector::iterator nitr = std::find(map->heroes.begin(), map->heroes.end(),h); - map->heroes.erase(nitr); - int player = h->tempOwner; - nitr = std::find(players[player].heroes.begin(), players[player].heroes.end(), h); - players[player].heroes.erase(nitr); - if(h->visitedTown) - { - if(h->inTownGarrison) - h->visitedTown->garrisonHero = NULL; - else - h->visitedTown->visitingHero = NULL; - h->visitedTown = NULL; - } - } - map->objects[rh->id] = NULL; - - //unblock tiles - if(obj->defInfo) - { - map->removeBlockVisTiles(obj); - } - - - break; - } - case 501://hero try-move - { - TryMoveHero * n = static_cast(pack); - CGHeroInstance *h = static_cast(map->objects[n->id]); - h->movement = n->movePoints; - if(n->start!=n->end && n->result) - { - map->removeBlockVisTiles(h); - h->pos = n->end; - map->addBlockVisTiles(h); - } - BOOST_FOREACH(int3 t, n->fowRevealed) - players[h->getOwner()].fogOfWarMap[t.x][t.y][t.z] = 1; - break; - } - case 502: - { - SetGarrisons * n = static_cast(pack); - for(std::map::iterator i = n->garrs.begin(); i!=n->garrs.end(); i++) - { - CArmedInstance *ai = static_cast(map->objects[i->first]); - ai->army = i->second; - if(ai->ID==TOWNI_TYPE && (static_cast(ai))->garrisonHero) //if there is a hero in garrison then we must update also his army - const_cast((static_cast(ai))->garrisonHero)->army = i->second; - else if(ai->ID==HEROI_TYPE) - { - CGHeroInstance *h = static_cast(ai); - if(h->visitedTown && h->inTownGarrison) - h->visitedTown->army = i->second; - } - } - break; - } - case 503: - { - //SetStrInfo *ssi = static_cast(pack); - //static_cast(map->objects[ssi->tid])->strInfo.creatures = ssi->cres; - break; - } - case 504: - { - NewStructures *ns = static_cast(pack); - CGTownInstance*t = static_cast(map->objects[ns->tid]); - BOOST_FOREACH(si32 bid,ns->bid) - t->builtBuildings.insert(bid); - t->builded = ns->builded; - break; - } - case 506: - { - SetAvailableCreatures *sac = static_cast(pack); - static_cast(map->objects[sac->tid])->strInfo.creatures = sac->creatures; - break; - } - case 508: - { - SetHeroesInTown *sac = static_cast(pack); - CGTownInstance *t = getTown(sac->tid); - CGHeroInstance *v = getHero(sac->visiting), *g = getHero(sac->garrison); - t->visitingHero = v; - t->garrisonHero = g; - if(v) - { - v->visitedTown = t; - v->inTownGarrison = false; - map->addBlockVisTiles(v); - } - if(g) - { - g->visitedTown = t; - g->inTownGarrison = true; - map->removeBlockVisTiles(g); - } - break; - } - case 509: - { - SetHeroArtifacts *sha = static_cast(pack); - CGHeroInstance *h = getHero(sha->hid); - h->artifacts = sha->artifacts; - h->artifWorn = sha->artifWorn; - break; - } - case 514: - { - SetSelection *ss = static_cast(pack); - players[ss->player].currentSelection = ss->id; - break; - } - case 515: - { - HeroRecruited *sha = static_cast(pack); - CGHeroInstance *h = hpool.heroesPool[sha->hid]; - CGTownInstance *t = getTown(sha->tid); - h->setOwner(sha->player); - h->pos = sha->tile; - h->movement = h->maxMovePoints(true); - - hpool.heroesPool.erase(sha->hid); - if(h->id < 0) - { - h->id = map->objects.size(); - map->objects.push_back(h); - } - else - map->objects[h->id] = h; - - h->initHeroDefInfo(); - map->heroes.push_back(h); - players[h->tempOwner].heroes.push_back(h); - map->addBlockVisTiles(h); - t->visitingHero = h; - h->visitedTown = t; - h->inTownGarrison = false; - break; - } - case 516: - { - GiveHero *sha = static_cast(pack); - CGHeroInstance *h = getHero(sha->id); - map->removeBlockVisTiles(h,true); - h->setOwner(sha->player); - h->movement = h->maxMovePoints(true); - h->initHeroDefInfo(); - map->heroes.push_back(h); - players[h->tempOwner].heroes.push_back(h); - map->addBlockVisTiles(h); - h->inTownGarrison = false; - break; - } - case 1001://set object property - { - SetObjectProperty *p = static_cast(pack); - CGObjectInstance *obj = map->objects[p->id]; - if(!obj) - tlog1 << "Wrong object ID - property cannot be set!\n"; - else - obj->setProperty(p->what,p->val); - break; - } - case 1002: - { - SetHoverName *shn = static_cast(pack); - map->objects[shn->id]->hoverName = toString(shn->name); - break; - } - case 2000: - { - HeroLevelUp * bs = static_cast(pack); - getHero(bs->heroid)->level = bs->level; - break; - } - case 3000: - { - BattleStart * bs = static_cast(pack); - curB = bs->info; - break; - } - case 3001: - { - BattleNextRound *ns = static_cast(pack); - curB->castedSpells[0] = curB->castedSpells[1] = 0; - curB->round = ns->round; - for(int i=0; istacks.size();i++) - { - curB->stacks[i]->state -= DEFENDING; - curB->stacks[i]->state -= WAITING; - curB->stacks[i]->state -= MOVED; - curB->stacks[i]->state -= HAD_MORALE; - curB->stacks[i]->counterAttacks = 1; - } - break; - } - case 3002: - { - BattleSetActiveStack *ns = static_cast(pack); - curB->activeStack = ns->stack; - CStack *st = curB->getStack(ns->stack); - if(vstd::contains(st->state,MOVED)) - st->state.insert(HAD_MORALE); - break; - } - case 3003: - { - BattleResult *br = static_cast(pack); - for(unsigned i=0;istacks.size();i++) - delete curB->stacks[i]; - - //remove any "until next battle" bonuses - CGHeroInstance *h; - h = getHero(curB->hero1); - if(h) - h->bonuses.remove_if(HeroBonus::OneBattle); - h = getHero(curB->hero2); - if(h) - h->bonuses.remove_if(HeroBonus::OneBattle); - - delete curB; - curB = NULL; - break; - } - case 3004: - { - BattleStackMoved *br = static_cast(pack); - curB->getStack(br->stack)->position = br->tile; - break; - } - case 3005: - { - BattleStackAttacked *br = static_cast(pack); - CStack * at = curB->getStack(br->stackAttacked); - at->amount = br->newAmount; - at->firstHPleft = br->newHP; - if(br->killed()) - at->state -= ALIVE; - break; - } - case 3006: - { - BattleAttack *br = static_cast(pack); - CStack *attacker = curB->getStack(br->stackAttacking); - if(br->counter()) - attacker->counterAttacks--; - if(br->shot()) - attacker->shots--; - applyNL(&br->bsa); - break; - } - case 3007: - { - StartAction *br = static_cast(pack); - CStack *st = curB->getStack(br->ba.stackNumber); - switch(br->ba.actionType) - { - case 3: - st->state.insert(DEFENDING); - break; - case 8: - st->state.insert(WAITING); - break; - case 2: case 6: case 7: case 9: case 10: case 11: - st->state.insert(MOVED); - break; - } - break; - } - case 3009: - { - SpellCasted *sc = static_cast(pack); - CGHeroInstance *h = (sc->side) ? getHero(curB->hero2) : getHero(curB->hero1); - if(h) - { - h->mana -= VLC->spellh->spells[sc->id].costs[sc->skill]; - if(h->mana < 0) h->mana = 0; - } - if(sc->side >= 0 && sc->side < 2) - { - curB->castedSpells[sc->side]++; - } - break; - } - case 3010: - { - SetStackEffect *sc = static_cast(pack); - CStack *stack = curB->getStack(sc->stack); - stack->effects.push_back(sc->effect); - break; - } - } -} -void CGameState::apply(IPack * pack) -{ - while(!mx->try_lock()) - boost::this_thread::sleep(boost::posix_time::milliseconds(50)); //give other threads time to finish - applyNL(pack); - mx->unlock(); -} +//void CGameState::apply(CPack * pack) +//{ +// while(!mx->try_lock()) +// boost::this_thread::sleep(boost::posix_time::milliseconds(50)); //give other threads time to finish +// //applyNL(pack); +// mx->unlock(); +//} int CGameState::pickHero(int owner) { int h=-1; diff --git a/CGameState.h b/CGameState.h index 79a6639f3..cc06a2fb2 100644 --- a/CGameState.h +++ b/CGameState.h @@ -33,7 +33,6 @@ struct StartInfo; struct SDL_Surface; class CMapHandler; class CPathfinder; -struct IPack; struct SetObjectProperty; struct MetaString; @@ -198,7 +197,7 @@ struct UpgradeInfo class DLL_EXPORT CGameState { -private: +public: StartInfo* scenarioOps; ui32 seed; ui8 currentPlayer; //ID of player currently having turn @@ -226,9 +225,6 @@ private: void init(StartInfo * si, Mapa * map, int Seed); void loadTownDInfos(); - void applyNL(IPack * pack); - - void apply(IPack * pack); void randomizeObject(CGObjectInstance *cur); std::pair pickObject(CGObjectInstance *obj); int pickHero(int owner); @@ -243,7 +239,7 @@ private: float getMarketEfficiency(int player, int mode=0); std::set tilesToReveal(int3 pos, int radious, int player) const; //if player==-1 => adds all tiles in radious int canBuildStructure(const CGTownInstance *t, int ID);// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements -public: + CGameState(); ~CGameState(); void getNeighbours(int3 tile, std::vector &vec, bool onLand); diff --git a/CMT.cpp b/CMT.cpp index b0ad9c2b7..d9c79127d 100644 --- a/CMT.cpp +++ b/CMT.cpp @@ -47,9 +47,7 @@ #undef main #endif std::string NAME = NAME_VER + std::string(" (client)"); -DLL_EXPORT void initDLL(CLodHandler *b); SDL_Surface * screen, * screen2; -extern SDL_Surface * CSDL_Ext::std32bppSurface; std::queue events; boost::mutex eventsM; TTF_Font * TNRB16, *TNR, *GEOR13, *GEORXX, *GEORM, *GEOR16; diff --git a/client/Client.cpp b/client/Client.cpp index 78b44098d..40ceac3cf 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -25,7 +25,6 @@ #include #include #include -CSharedCond > mess(new std::set); extern std::string NAME; namespace intpr = boost::interprocess; @@ -56,83 +55,8 @@ CClient::~CClient(void) } void CClient::process(int what) { - static BattleAction curbaction; switch (what) { - case 95: //system message - { - std::string m; - *serv >> m; - tlog4 << "System message from server: " << m << std::endl; - break; - } - case 100: //one of our interfaces has turn - { - ui8 player; - *serv >> player;//who? - tlog5 << "It's turn of "<<(unsigned)player<<" player."<currentPlayer = player; - boost::thread(boost::bind(&CGameInterface::yourTurn,playerint[player])); - break; - } - case 101: - { - NewTurn n; - *serv >> n; - tlog5 << "New day: "<<(unsigned)n.day<<". Applying changes... "; - gs->apply(&n); - tlog5 << "done!"<> sr; - tlog5 << "Set amount of "<generaltexth->restypes[sr.resid] - << " of player "<<(unsigned)sr.player <<" to "<apply(&sr); - playerint[sr.player]->receivedResource(sr.resid,sr.val); - break; - } - case 103: //show info dialog - { - InfoWindow iw; - *serv >> iw; - std::vector comps; - for(size_t i=0;ishowInfoDialog(str,comps); - break; - } - case 104: - { - SetResources sr; - *serv >> sr; - tlog5 << "Set amount of resources of player "<<(unsigned)sr.player<apply(&sr); - playerint[sr.player]->receivedResource(-1,-1); - break; - } - case 105: - { - SetPrimSkill sps; - *serv >> sps; - tlog5 << "Changing hero primary skill"<apply(&sps); - playerint[gs->getHero(sps.id)->tempOwner]->heroPrimarySkillChanged(gs->getHero(sps.id),sps.which,sps.val); - break; - } - case 106: - { - SetSecSkill sr; - *serv >> sr; - tlog5 << "Changing hero secondary skill"<apply(&sr); - //TODO? - maybe inform interfaces - break; - } case 107: { ShowInInfobox sii; @@ -143,227 +67,6 @@ void CClient::process(int what) static_cast(playerint[sii.player])->showComp(sc); break; } - case 108: - { - HeroVisitCastle vc; - *serv >> vc; - gs->apply(&vc); - if(vc.start() && !vc.garrison() && vstd::contains(playerint,gs->getHero(vc.hid)->tempOwner)) - { - playerint[gs->getHero(vc.hid)->tempOwner]->heroVisitsTown(gs->getHero(vc.hid),gs->getTown(vc.tid)); - } - break; - } - case 109: - { - ChangeSpells vc; - *serv >> vc; - tlog5 << "Changing spells of hero "<apply(&vc); - break; - } - case 110: - { - SetMana sm; - *serv >> sm; - tlog5 << "Setting mana value of hero "<apply(&sm); - CGHeroInstance *h = gs->getHero(sm.hid); - if(vstd::contains(playerint,h->tempOwner)) - playerint[h->tempOwner]->heroManaPointsChanged(h); - break; - } - case 111: - { - SetMovePoints smp; - *serv >> smp; - tlog5 << "Setting movement points of hero "<apply(&smp); - CGHeroInstance *h = gs->getHero(smp.hid); - if(vstd::contains(playerint,h->tempOwner)) - playerint[h->tempOwner]->heroMovePointsChanged(h); - break; - } - case 112: - { - FoWChange fc; - *serv >> fc; - tlog5 << "Changing FoW of player "<<(int)fc.player<apply(&fc); - if(!vstd::contains(playerint,fc.player)) - break; - if(fc.mode) - playerint[fc.player]->tileRevealed(fc.tiles); - else - playerint[fc.player]->tileHidden(fc.tiles); - break; - } - case 113: - { - SetAvailableHeroes sav; - *serv >> sav; - tlog5 << "Setting available heroes for player "<<(int)sav.player<apply(&sav); - break; - } - case 115: - { - GiveBonus gb; - *serv >> gb; - tlog5 << "Hero receives bonus\n"; - gs->apply(&gb); - CGHeroInstance *h = gs->getHero(gb.hid); - if(vstd::contains(playerint,h->tempOwner)) - playerint[h->tempOwner]->heroBonusChanged(h,h->bonuses.back(),true); - break; - } - case 116: - { - ChangeObjPos sav; - *serv >> sav; - tlog5 << "Changing pos of object "<< sav.objid << std::endl; - CGObjectInstance *obj = gs->map->objects[sav.objid]; - //TODO: redraw if neeeded - if(sav.flags & 1) - CGI->mh->hideObject(obj); - - gs->apply(&sav); - - if(sav.flags & 1) - CGI->mh->printObject(obj); - break; - } - case 500: - { - RemoveObject rh; - *serv >> rh; - CGObjectInstance *obj = gs->map->objects[rh.id]; - CGI->mh->removeObject(obj); - gs->apply(&rh); - if(obj->ID == 34) - { - CGHeroInstance *h = static_cast(obj); - tlog5 << "Removing hero with id = "<<(unsigned)rh.id<tempOwner]->heroKilled(h); - } - break; - } - case 501: //hero movement response - we have to notify interfaces and callback - { - TryMoveHero *th = new TryMoveHero; //will be deleted by callback after processing - *serv >> *th; - tlog5 << "HeroMove: id="<id<<"\tResult: "<<(unsigned)th->result<<"\tPosition "<end<start,th->end,static_cast(gs->map->objects[th->id])); - hmd.style = th->result-1; - hmd.successful = th->result; - if(th->result>1) - CGI->mh->removeObject(hmd.ho); - - gs->apply(th); - - if(th->result>1) - CGI->mh->printObject(hmd.ho); - int player = gs->map->objects[th->id]->getOwner(); - - if(playerint[player]) - { - playerint[player]->tileRevealed(th->fowRevealed); - //std::for_each(th->fowRevealed.begin(),th->fowRevealed.end(),boost::bind(&CGameInterface::tileRevealed,playerint[player],_1)); - } - - //notify interfaces about move - for(std::map::iterator i=playerint.begin();i!=playerint.end();i++) - { - if(i->first >= PLAYER_LIMIT) continue; - if(gs->players[i->first].fogOfWarMap[th->start.x-1][th->start.y][th->start.z] || gs->players[i->first].fogOfWarMap[th->end.x-1][th->end.y][th->end.z]) - { - i->second->heroMoved(hmd); - } - } - - //add info for callback - if(th->result<2) - { - mess.mx->lock(); - mess.res->insert(th); - mess.mx->unlock(); - mess.cv->notify_all(); - } - break; - } - case 502: - { - SetGarrisons sg; - *serv >> sg; - tlog5 << "Setting garrisons." << std::endl; - gs->apply(&sg); - for(std::map::iterator i = sg.garrs.begin(); i!=sg.garrs.end(); i++) - 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; - CGTownInstance *town = static_cast(gs->map->objects[ns.tid]); - tlog5 << "New structure(s) in " << ns.tid <<" " << town->name << " - " << *ns.bid.begin() << std::endl; - gs->apply(&ns); - BOOST_FOREACH(si32 bid, ns.bid) - { - if(bid==13) //for or capitol - { - town->defInfo = gs->capitols[town->subID]; - } - if(bid ==7) - { - town->defInfo = gs->forts[town->subID]; - } - playerint[town->tempOwner]->buildChanged(town,bid,1); - } - break; - } - case 506: - { - SetAvailableCreatures ns; - *serv >> ns; - tlog5 << "Setting available creatures in " << ns.tid << std::endl; - gs->apply(&ns); - CGTownInstance *t = gs->getTown(ns.tid); - if(vstd::contains(playerint,t->tempOwner)) - playerint[t->tempOwner]->availableCreaturesChanged(t); - break; - } - case 508: - { - SetHeroesInTown inTown; - *serv >> inTown; - tlog5 << "Setting heroes in town " << inTown.tid << std::endl; - gs->apply(&inTown); - CGTownInstance *t = gs->getTown(inTown.tid); - if(vstd::contains(playerint,t->tempOwner)) - playerint[t->tempOwner]->heroInGarrisonChange(t); - break; - } - case 509: - { - SetHeroArtifacts sha; - *serv >> sha; - tlog5 << "Setting artifacts of hero " << sha.hid << std::endl; - gs->apply(&sha); - CGHeroInstance *t = gs->getHero(sha.hid); - if(vstd::contains(playerint,t->tempOwner)) - playerint[t->tempOwner]->heroArtifactSetChanged(t); - break; - } case 513: { ui8 color; @@ -372,241 +75,6 @@ void CClient::process(int what) tlog4 << "Player "<<(int)color<<" sends a message: " << message << std::endl; break; } - case 514: - { - SetSelection ss; - *serv >> ss; - tlog5 << "Selection of player " << (int)ss.player << " set to " << ss.id << std::endl; - gs->apply(&ss); - break; - } - case 515: - { - HeroRecruited hr; - *serv >> hr; - tlog5 << "New hero bought\n"; - CGHeroInstance *h = gs->hpool.heroesPool[hr.hid]; - gs->apply(&hr); - CGI->mh->initHeroDef(h); - //CGI->mh->printObject(h); - playerint[h->tempOwner]->heroCreated(h); - playerint[h->tempOwner]->heroInGarrisonChange(gs->getTown(hr.tid)); - break; - } - case 516: - { - GiveHero hr; - *serv >> hr; - tlog5 << "Players receives hero\n"; - CGHeroInstance *h = gs->getHero(hr.id); - CGI->mh->hideObject(h); - gs->apply(&hr); - CGI->mh->initHeroDef(h); - CGI->mh->printObject(h); - playerint[h->tempOwner]->heroCreated(h); - break; - } - case 1001: - { - SetObjectProperty sop; - *serv >> sop; - tlog5 << "Setting " << (unsigned)sop.what << " property of " << sop.id <<" object to "<apply(&sop); - break; - } - case 1002: - { - SetHoverName shn; - *serv >> shn; - tlog5 << "Setting a name of " << shn.id <<" object to "<< toString(shn.name) <apply(&shn); - break; - } - case 2000: - { - HeroLevelUp bs; - *serv >> bs; - tlog5 << "Hero levels up!" <apply(&bs); - CGHeroInstance *h = gs->getHero(bs.heroid); - if(vstd::contains(playerint,h->tempOwner)) - { - boost::function callback = boost::function(boost::bind(&CCallback::selectionMade,LOCPLINT->cb,_1,bs.id)); - playerint[h->tempOwner]->heroGotLevel((const CGHeroInstance *)h,(int)bs.primskill,bs.skills, callback); - } - break; - } - case 2001: - { - SelectionDialog sd; - *serv >> sd; - tlog5 << "Showing selection dialog " < comps; - for(size_t i=0; i < sd.components.size(); ++i) { - comps.push_back(&sd.components[i]); - } - std::string str = toString(sd.text); - playerint[sd.player]->showSelDialog(str,comps,sd.id); - break; - } - case 2002: - { - YesNoDialog ynd; - *serv >> ynd; - tlog5 << "Showing yes/no dialog " < comps; - for(size_t i=0; i < ynd.components.size(); ++i) { - comps.push_back(&ynd.components[i]); - } - std::string str = toString(ynd.text); - playerint[ynd.player]->showYesNoDialog(str,comps,ynd.id); - break; - } - case 3000: - { - BattleStart bs; - *serv >> bs; //uses new to allocate memory for battleInfo - must be deleted when battle is over - tlog5 << "Starting battle!" <apply(&bs); - - if(playerint.find(gs->curB->side1) != playerint.end()) - playerint[gs->curB->side1]->battleStart(&gs->curB->army1, &gs->curB->army2, gs->curB->tile, gs->getHero(gs->curB->hero1), gs->getHero(gs->curB->hero2), 0); - if(playerint.find(gs->curB->side2) != playerint.end()) - playerint[gs->curB->side2]->battleStart(&gs->curB->army1, &gs->curB->army2, gs->curB->tile, gs->getHero(gs->curB->hero1), gs->getHero(gs->curB->hero2), 1); - - break; - } - case 3001: - { - BattleNextRound bnr; - *serv >> bnr; - tlog5 << "Round nr " << bnr.round <apply(&bnr); - - //tell players about next round - if(playerint.find(gs->curB->side1) != playerint.end()) - playerint[gs->curB->side1]->battleNewRound(bnr.round); - if(playerint.find(gs->curB->side2) != playerint.end()) - playerint[gs->curB->side2]->battleNewRound(bnr.round); - break; - } - case 3002: - { - BattleSetActiveStack sas; - *serv >> sas; - tlog5 << "Active stack: " << sas.stack <apply(&sas); - int owner = gs->curB->getStack(sas.stack)->owner; - boost::thread(boost::bind(&CClient::waitForMoveAndSend,this,owner)); - break; - } - case 3003: - { - BattleResult br; - *serv >> br; - tlog5 << "Battle ends. Winner: " << (unsigned)br.winner<< ". Type of end: "<< (unsigned)br.result <curB->side1) != playerint.end()) - playerint[gs->curB->side1]->battleEnd(&br); - if(playerint.find(gs->curB->side2) != playerint.end()) - playerint[gs->curB->side2]->battleEnd(&br); - - gs->apply(&br); - break; - } - case 3004: - { - BattleStackMoved br; - *serv >> br; - tlog5 << "Stack "<curB->side1) != playerint.end()) - playerint[gs->curB->side1]->battleStackMoved(br.stack,br.tile); - if(playerint.find(gs->curB->side2) != playerint.end()) - playerint[gs->curB->side2]->battleStackMoved(br.stack,br.tile); - gs->apply(&br); - break; - } - case 3005: - { - BattleStackAttacked bsa; - *serv >> bsa; - gs->apply(&bsa); - if(playerint.find(gs->curB->side1) != playerint.end()) - playerint[gs->curB->side1]->battleStackAttacked(&bsa); - if(playerint.find(gs->curB->side2) != playerint.end()) - playerint[gs->curB->side2]->battleStackAttacked(&bsa); - break; - } - case 3006: - { - BattleAttack ba; - *serv >> ba; - tlog5 << "Stack: " << ba.stackAttacking << " is attacking stack "<< ba.bsa.stackAttacked <curB->side1) != playerint.end()) - playerint[gs->curB->side1]->battleAttack(&ba); - if(playerint.find(gs->curB->side2) != playerint.end()) - playerint[gs->curB->side2]->battleAttack(&ba); - gs->apply(&ba); - if(playerint.find(gs->curB->side1) != playerint.end()) - playerint[gs->curB->side1]->battleStackAttacked(&ba.bsa); - if(playerint.find(gs->curB->side2) != playerint.end()) - playerint[gs->curB->side2]->battleStackAttacked(&ba.bsa); - break; - } - case 3007: - { - *serv >> curbaction; - tlog5 << "Action started. ID: " << (int)curbaction.actionType << ". Destination: "<< curbaction.destinationTile <curB->side1) != playerint.end()) - playerint[gs->curB->side1]->actionStarted(&curbaction); - if(playerint.find(gs->curB->side2) != playerint.end()) - playerint[gs->curB->side2]->actionStarted(&curbaction); - gs->apply(&StartAction(curbaction)); - break; - } - case 3008: - { - tlog5 << "Action ended!\n"; - if(!gs->curB) - { - tlog2 << "There is no battle state!\n"; - break; - } - if(playerint.find(gs->curB->side1) != playerint.end()) - playerint[gs->curB->side1]->actionFinished(&curbaction); - if(playerint.find(gs->curB->side2) != playerint.end()) - playerint[gs->curB->side2]->actionFinished(&curbaction); - break; - } - case 3009: - { - tlog5 << "Spell casted!\n"; - SpellCasted sc; - *serv >> sc; - gs->apply(&sc); - if(playerint.find(gs->curB->side1) != playerint.end()) - playerint[gs->curB->side1]->battleSpellCasted(&sc); - if(playerint.find(gs->curB->side2) != playerint.end()) - playerint[gs->curB->side2]->battleSpellCasted(&sc); - break; - } - case 3010: - { - tlog5 << "Effect set!\n"; - SetStackEffect sse; - *serv >> sse; - gs->apply(&sse); - SpellCasted sc; - sc.id = sse.effect.id; - sc.side = 3; //doesn't matter - sc.skill = sse.effect.level; - sc.tile = gs->curB->getStack(sse.stack)->position; - if(playerint.find(gs->curB->side1) != playerint.end()) - playerint[gs->curB->side1]->battleSpellCasted(&sc); - if(playerint.find(gs->curB->side2) != playerint.end()) - playerint[gs->curB->side2]->battleSpellCasted(&sc); - break; - } case 9999: break; default: diff --git a/client/Client.h b/client/Client.h index fe810edca..edf632342 100644 --- a/client/Client.h +++ b/client/Client.h @@ -10,6 +10,7 @@ class CGameState; class CGameInterface; class CConnection; class CCallback; +struct BattleAction; struct SharedMem; class CClient; void processCommand(const std::string &message, CClient *&client); @@ -41,13 +42,14 @@ struct CSharedCond class CClient : public IGameCallback { +public: CCallback *cb; std::map playerint; CConnection *serv; SharedMem *shared; + BattleAction *curbaction; void waitForMoveAndSend(int color); -public: CClient(void); CClient(CConnection *con, StartInfo *si); ~CClient(void); diff --git a/client/VCMI_client.vcproj b/client/VCMI_client.vcproj index 46644efc4..c4be0bda1 100644 --- a/client/VCMI_client.vcproj +++ b/client/VCMI_client.vcproj @@ -374,6 +374,10 @@ RelativePath="..\mapHandler.cpp" > + + diff --git a/lib/Connection.cpp b/lib/Connection.cpp index ebad9e591..b0895969f 100644 --- a/lib/Connection.cpp +++ b/lib/Connection.cpp @@ -4,9 +4,12 @@ #include #include #include + using namespace boost; using namespace boost::asio::ip; +CTypeList typeList; + #define LOG(a) \ if(logging)\ out << a @@ -148,6 +151,7 @@ void CConnection::close() CSaveFile::CSaveFile( const std::string &fname ) :sfile(new std::ofstream(fname.c_str(),std::ios::binary)) { + registerTypes(*this); if(!(*sfile)) { tlog1 << "Error: cannot open to write " << fname << std::endl; @@ -169,6 +173,7 @@ int CSaveFile::write( const void * data, unsigned size ) CLoadFile::CLoadFile( const std::string &fname ) :sfile(new std::ifstream(fname.c_str(),std::ios::binary)) { + registerTypes(*this); if(!(*sfile)) { tlog1 << "Error: cannot open to read " << fname << std::endl; @@ -185,4 +190,28 @@ int CLoadFile::read( const void * data, unsigned size ) { sfile->read((char *)data,size); return size; +} + +CTypeList::CTypeList() +{ + +} + +ui16 CTypeList::registerType( const type_info *type ) +{ + std::map::const_iterator i = types.find(type); + if(i != types.end()) + return i->second; + + ui16 id = types.size() + 1; + types[type] = id; + return id; +} + +ui16 CTypeList::getTypeID( const type_info *type ) +{ + if(vstd::contains(types,type)) + return types[type]; + else + return 0; } \ No newline at end of file diff --git a/lib/Connection.h b/lib/Connection.h index 114b403aa..346ea0462 100644 --- a/lib/Connection.h +++ b/lib/Connection.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -20,7 +21,6 @@ #include const ui32 version = 703; class CConnection; - namespace mpl = boost::mpl; namespace boost @@ -53,6 +53,28 @@ enum SerializationLvl Serializable }; + template DLL_EXPORT void registerTypes(Serializer &s); //defined in .cpp and explicitly instantiated for used serializers + +class DLL_EXPORT CTypeList +{ + std::map types; +public: + CTypeList(); + ui16 registerType(const type_info *type); + template ui16 registerType(const T * t) + { + return registerType(&typeid(*t)); + } + + ui16 getTypeID(const type_info *type); + template ui16 getTypeID(const T * t) + { + return getTypeID(&typeid(*t)); + } +}; + +extern DLL_EXPORT CTypeList typeList; + template struct SavePrimitive { @@ -169,11 +191,51 @@ struct SerializationLevel static const int value = SerializationLevel::type::value; }; -template class DLL_EXPORT COSer +class DLL_EXPORT CSerializerBase { public: bool saving; - COSer(){saving=true;}; +}; + +class DLL_EXPORT CSaverBase : public virtual CSerializerBase +{ +}; + +class CBasicPointerSaver +{ +public: + virtual void savePtr(CSaverBase &ar, const void *data) const =0; +}; + +template class CPointerSaver : public CBasicPointerSaver +{ +public: + void savePtr(CSaverBase &ar, const void *data) const + { + Serializer &s = static_cast(ar); + const T *ptr = static_cast(data); + + //T is most derived known type, it's time to call actual serialize + const_cast(*ptr).serialize(s,version); + } +}; + +template class DLL_EXPORT COSer : public CSaverBase +{ +public: + std::map savers; // typeID => CPointerSaver + + COSer() + { + saving=true; + } + + template void registerType(const T * t=NULL) + { + ui16 ID = typeList.registerType(&typeid(T)); + savers[ID] = new CPointerSaver; + } + Serializer * This() { return static_cast(this); @@ -185,7 +247,7 @@ public: this->This()->save(t); return * this->This(); } - + template COSer & operator&(const T & t) { @@ -200,14 +262,28 @@ public: { this->This()->write(&data,sizeof(data)); } + template void savePointer(const T &data) { + //write if pointer is not NULL ui8 hlp = (data!=NULL); *this << hlp; - if(hlp) - *this << *data; + + //if pointer is NULL then we don't need anything more... + if(!hlp) + return; + + //write type identifier + ui16 tid = typeList.getTypeID(data); + *this << tid; + + if(!tid) + *this << *data; //if type is unregistered simply write all data in a standard way + else + savers[tid]->savePtr(*this,data); //call serializer specific for our real type } + template void saveArray(const T &data) { @@ -288,11 +364,52 @@ public: *this << i->first << i->second; } }; -template class DLL_EXPORT CISer + + + +class DLL_EXPORT CLoaderBase : public virtual CSerializerBase +{}; + +class CBasicPointerLoader { public: - bool saving; - CISer(){saving = false;}; + virtual void loadPtr(CLoaderBase &ar, void *data) const =0; //data is pointer to the ACTUAL POINTER +}; + +template class CPointerLoader : public CBasicPointerLoader +{ +public: + void loadPtr(CLoaderBase &ar, void *data) const //data is pointer to the ACTUAL POINTER + { + Serializer &s = static_cast(ar); + T *&ptr = *static_cast(data); + + //create new object under pointer + typedef typename boost::remove_pointer::type npT; + ptr = new npT; + + //T is most derived known type, it's time to call actual serialize + ptr->serialize(s,version); + } +}; + + +template class DLL_EXPORT CISer : public CLoaderBase +{ +public: + std::map loaders; // typeID => CPointerSaver + + CISer() + { + saving = false; + } + + template void registerType(const T * t=NULL) + { + ui16 ID = typeList.registerType(&typeid(T)); + loaders[ID] = new CPointerLoader; + } + Serializer * This() { return static_cast(this); @@ -364,10 +481,20 @@ public: return; } - tlog5<<"Allocating memory for pointer!"<::type npT; - data = new npT; - *this >> *data; + //get type id + ui16 tid; + *this >> tid; + + if(!tid) + { + typedef typename boost::remove_pointer::type npT; + data = new npT; + *this >> *data; + } + else + { + loaders[tid]->loadPtr(*this,&data); + } } template void loadSerializable(std::vector &data) diff --git a/lib/IGameCallback.h b/lib/IGameCallback.h index e8164fc8d..1e4424a9d 100644 --- a/lib/IGameCallback.h +++ b/lib/IGameCallback.h @@ -65,5 +65,7 @@ public: virtual void setManaPoints(int hid, int val)=0; virtual void giveHero(int id, int player)=0; virtual void changeObjPos(int objid, int3 newPos, ui8 flags)=0; + + friend class CPackForClient; }; #endif // __IGAMECALLBACK_H__ \ No newline at end of file diff --git a/lib/NetPacks.h b/lib/NetPacks.h index d23c8dcd3..7acace6b1 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -1,42 +1,38 @@ #ifndef __NETPACKS_H__ #define __NETPACKS_H__ #include "../global.h" +#include "../CGameState.h" #include "BattleAction.h" #include "HeroBonus.h" +#include -struct IPack +class CClient; +class CGameState; + +struct CPack { - virtual ui16 getType()const = 0 ; - //template - //static bool isType(const IPack * ip) - //{ - // return Type == ip->getType(); - //} - template - static bool isType(IPack * ip) - { - return Type == ip->getType(); - } - //template - //static bool isType(const IPack & ip) - //{ - // return Type == ip.getType(); - //} -}; -template struct CPack - :public IPack -{ - ui16 type; + ui16 type; + + CPack(){}; + ~CPack(){}; ui16 getType() const{return type;} - T* This(){return static_cast(this);}; }; -template struct Query - :public CPack + +struct CPackForClient : public CPack +{ + CGameState* GS(CClient *cl); + + //virtual void applyFirstCl(CClient *cl){}; //called before applying to gs + //virtual void applyGs(CGameState *gs){}; + //virtual void applyCl(CClient *cl){}; //called after applying to gs +}; + +struct Query : public CPackForClient { ui32 id; }; -struct MetaString : public CPack //2001 helper for object scrips +struct MetaString : public CPack //2001 helper for object scrips { std::vector strings; std::vector > texts; //pairs; types: 1 - generaltexthandler->all; 2 - objh->xtrainfo; 3 - objh->names; 4 - objh->restypes; 5 - arth->artifacts[id].name; 6 - generaltexth->arraytxt; 7 - creh->creatures[os->subID].namePl; 8 - objh->creGens; 9 - objh->mines[ID].first; 10 - objh->mines[ID].second; 11 - objh->advobtxt @@ -70,20 +66,34 @@ struct MetaString : public CPack //2001 helper for object scrips MetaString(){type = 2001;}; }; -struct SetResources : public CPack //104 +struct SystemMessage : public CPackForClient //95 { - SetResources(){res.resize(RESOURCE_QUANTITY);type = 104;}; - ui8 player; - std::vector res; //res[resid] => res amount + SystemMessage(){type = 95;}; + void applyCl(CClient *cl); + std::string text; template void serialize(Handler &h, const int version) { - h & player & res; } }; -struct SetResource : public CPack //102 + +struct YourTurn : public CPackForClient //100 +{ + YourTurn(){type = 100;}; + void applyCl(CClient *cl); + void applyGs(CGameState *gs); + + ui8 player; + template void serialize(Handler &h, const int version) + { + } +}; + +struct SetResource : public CPackForClient //102 { SetResource(){type = 102;}; + void applyCl(CClient *cl); + void applyGs(CGameState *gs); ui8 player, resid; si32 val; @@ -93,9 +103,27 @@ struct SetResource : public CPack //102 h & player & resid & val; } }; -struct SetPrimSkill : public CPack //105 +struct SetResources : public CPackForClient //104 +{ + SetResources(){res.resize(RESOURCE_QUANTITY);type = 104;}; + void applyCl(CClient *cl); + void applyGs(CGameState *gs); + + ui8 player; + std::vector res; //res[resid] => res amount + + template void serialize(Handler &h, const int version) + { + h & player & res; + } +}; + +struct SetPrimSkill : public CPackForClient //105 { SetPrimSkill(){type = 105;}; + void applyCl(CClient *cl); + void applyGs(CGameState *gs); + ui8 abs; //0 - changes by value; 1 - sets to value si32 id; ui16 which, val; @@ -105,9 +133,12 @@ struct SetPrimSkill : public CPack //105 h & abs & id & which & val; } }; -struct SetSecSkill : public CPack //106 +struct SetSecSkill : public CPackForClient //106 { SetSecSkill(){type = 106;}; + void applyCl(CClient *cl); + void applyGs(CGameState *gs); + ui8 abs; //0 - changes by value; 1 - sets to value si32 id; ui16 which, val; @@ -117,9 +148,12 @@ struct SetSecSkill : public CPack //106 h & abs & id & which & val; } }; -struct HeroVisitCastle : public CPack //108 +struct HeroVisitCastle : public CPackForClient //108 { HeroVisitCastle(){flags=0;type = 108;}; + void applyCl(CClient *cl); + void applyGs(CGameState *gs); + ui8 flags; //1 - start, 2 - garrison ui32 tid, hid; @@ -136,9 +170,12 @@ struct HeroVisitCastle : public CPack //108 h & flags & tid & hid; } }; -struct ChangeSpells : public CPack //109 +struct ChangeSpells : public CPackForClient //109 { ChangeSpells(){type = 109;}; + void applyCl(CClient *cl); + void applyGs(CGameState *gs); + ui8 learn; //1 - gives spell, 0 - takes ui32 hid; std::set spells; @@ -149,9 +186,13 @@ struct ChangeSpells : public CPack //109 } }; -struct SetMana : public CPack //110 +struct SetMana : public CPackForClient //110 { SetMana(){type = 110;}; + void applyCl(CClient *cl); + void applyGs(CGameState *gs); + + ui32 hid, val; template void serialize(Handler &h, const int version) @@ -159,9 +200,12 @@ struct SetMana : public CPack //110 h & val & hid; } }; -struct SetMovePoints : public CPack //111 +struct SetMovePoints : public CPackForClient //111 { SetMovePoints(){type = 111;}; + void applyCl(CClient *cl); + void applyGs(CGameState *gs); + ui32 hid, val; template void serialize(Handler &h, const int version) @@ -169,9 +213,12 @@ struct SetMovePoints : public CPack //111 h & val & hid; } }; -struct FoWChange : public CPack //112 +struct FoWChange : public CPackForClient //112 { FoWChange(){type = 112;}; + void applyCl(CClient *cl); + void applyGs(CGameState *gs); + std::set tiles; ui8 player, mode; //mode==0 - hide, mode==1 - reveal template void serialize(Handler &h, const int version) @@ -180,9 +227,12 @@ struct FoWChange : public CPack //112 } }; -struct SetAvailableHeroes : public CPack //113 +struct SetAvailableHeroes : public CPackForClient //113 { SetAvailableHeroes(){type = 113;flags=0;}; + void applyCl(CClient *cl); + void applyGs(CGameState *gs); + ui8 player; si32 hid1, hid2; ui8 flags; //1 - reset army of hero1; 2 - reset army of hero 2 @@ -192,9 +242,11 @@ struct SetAvailableHeroes : public CPack //113 } }; -struct GiveBonus : public CPack //115 +struct GiveBonus : public CPackForClient //115 { GiveBonus(){type = 115;}; + void applyCl(CClient *cl); + void applyGs(CGameState *gs); ui32 hid; HeroBonus bonus; @@ -206,9 +258,12 @@ struct GiveBonus : public CPack //115 } }; -struct ChangeObjPos : public CPack //116 +struct ChangeObjPos : public CPackForClient //116 { ChangeObjPos(){type = 116;}; + void applyFirstCl(CClient *cl); + void applyCl(CClient *cl); + void applyGs(CGameState *gs); ui32 objid; int3 nPos; @@ -220,10 +275,14 @@ struct ChangeObjPos : public CPack //116 } }; -struct RemoveObject : public CPack //500 +struct RemoveObject : public CPackForClient //500 { RemoveObject(){type = 500;}; RemoveObject(si32 ID){id = ID;type = 500;}; + void applyFirstCl(CClient *cl); + void applyCl(CClient *cl); + void applyGs(CGameState *gs); + si32 id; template void serialize(Handler &h, const int version) @@ -231,9 +290,12 @@ struct RemoveObject : public CPack //500 h & id; } }; -struct TryMoveHero : public CPack //501 +struct TryMoveHero : public CPackForClient //501 { TryMoveHero(){type = 501;}; + void applyFirstCl(CClient *cl); + void applyCl(CClient *cl); + void applyqGs(CGameState *gs); ui32 id, movePoints; ui8 result; //0 - failed; 1- succes -normal move; 2 - teleportation, 3 - instant jump @@ -245,9 +307,12 @@ struct TryMoveHero : public CPack //501 h & id & result & start & end & movePoints & fowRevealed; } }; -struct SetGarrisons : public CPack //502 +struct SetGarrisons : public CPackForClient //502 { SetGarrisons(){type = 502;}; + void applyCl(CClient *cl); + void applyGs(CGameState *gs); + std::map garrs; template void serialize(Handler &h, const int version) @@ -255,9 +320,12 @@ struct SetGarrisons : public CPack //502 h & garrs; } }; -struct NewStructures : public CPack //504 +struct NewStructures : public CPackForClient //504 { NewStructures(){type = 504;}; + void applyCl(CClient *cl); + void applyGs(CGameState *gs); + si32 tid; std::set bid; si16 builded; @@ -267,9 +335,12 @@ struct NewStructures : public CPack //504 h & tid & bid & builded; } }; -struct SetAvailableCreatures : public CPack //506 +struct SetAvailableCreatures : public CPackForClient //506 { SetAvailableCreatures(){type = 506;}; + void applyCl(CClient *cl); + void applyGs(CGameState *gs); + si32 tid; std::map creatures; @@ -278,9 +349,12 @@ struct SetAvailableCreatures : public CPack //506 h & tid & creatures; } }; -struct SetHeroesInTown : public CPack //508 +struct SetHeroesInTown : public CPackForClient //508 { SetHeroesInTown(){type = 508;}; + void applyCl(CClient *cl); + void applyGs(CGameState *gs); + si32 tid, visiting, garrison; //id of town, visiting hero, hero in garrison template void serialize(Handler &h, const int version) @@ -288,9 +362,12 @@ struct SetHeroesInTown : public CPack //508 h & tid & visiting & garrison; } }; -struct SetHeroArtifacts : public CPack //509 +struct SetHeroArtifacts : public CPackForClient //509 { SetHeroArtifacts(){type = 509;}; + void applyCl(CClient *cl); + void applyGs(CGameState *gs); + si32 hid; std::vector artifacts; //hero's artifacts from bag std::map artifWorn; //map; positions: 0 - head; 1 - shoulders; 2 - neck; 3 - right hand; 4 - left hand; 5 - torso; 6 - right ring; 7 - left ring; 8 - feet; 9 - misc1; 10 - misc2; 11 - misc3; 12 - misc4; 13 - mach1; 14 - mach2; 15 - mach3; 16 - mach4; 17 - spellbook; 18 - misc5 @@ -301,9 +378,11 @@ struct SetHeroArtifacts : public CPack //509 } }; -struct SetSelection : public CPack //514 +struct SetSelection : public CPackForClient //514 { SetSelection(){type = 514;}; + void applyGs(CGameState *gs); + ui8 player; ui32 id; @@ -313,9 +392,12 @@ struct SetSelection : public CPack //514 } }; -struct HeroRecruited : public CPack //515 +struct HeroRecruited : public CPackForClient //515 { HeroRecruited(){type = 515;}; + void applyCl(CClient *cl); + void applyGs(CGameState *gs); + si32 hid, tid; //subID of hero int3 tile; ui8 player; @@ -326,9 +408,13 @@ struct HeroRecruited : public CPack //515 } }; -struct GiveHero : public CPack //516 +struct GiveHero : public CPackForClient //516 { GiveHero(){type = 516;}; + void applyFirstCl(CClient *cl); + void applyCl(CClient *cl); + void applyGs(CGameState *gs); + ui32 id; //object id ui8 player; @@ -338,8 +424,10 @@ struct GiveHero : public CPack //516 } }; -struct NewTurn : public CPack //101 +struct NewTurn : public CPackForClient //101 { + void applyGs(CGameState *gs); + struct Hero { ui32 id, move, mana; //id is a general serial id @@ -363,17 +451,8 @@ struct NewTurn : public CPack //101 h & heroes & cres & res & day & resetBuilded; } }; -//struct SetStrInfo : public CPack //503 -//{ -// SetStrInfo(){type = 503;}; -// SetAvailableCreatures sac; -// -// template void serialize(Handler &h, const int version) -// { -// h & sac; -// } -//}; -struct Component : public CPack //2002 helper for object scrips informations + +struct Component : public CPack //2002 helper for object scrips informations { ui16 id, subtype; //ids: 0 - primskill; 1 - secskill; 2 - resource; 3 - creature; 4 - artifact; 5 - experience (sub==0 exp points; sub==1 levels) si32 val; // + give; - take @@ -387,8 +466,10 @@ struct Component : public CPack //2002 helper for object scrips infor Component(ui16 Type, ui16 Subtype, si32 Val, si16 When):id(Type),subtype(Subtype),val(Val),when(When){type = 2002;}; }; -struct InfoWindow : public CPack //103 - displays simple info window +struct InfoWindow : public CPackForClient //103 - displays simple info window { + void applyCl(CClient *cl); + MetaString text; std::vector components; ui8 player; @@ -400,8 +481,10 @@ struct InfoWindow : public CPack //103 - displays simple info windo InfoWindow(){type = 103;}; }; -struct SetObjectProperty : public CPack//1001 +struct SetObjectProperty : public CPackForClient//1001 { + void applyGs(CGameState *gs); + ui32 id; ui8 what; //1 - owner; 2 - blockvis; 3 - first stack count; 4 - visitors; 5 - visited; 6 - ID (if 34 then also def is replaced) ui32 val; @@ -414,8 +497,10 @@ struct SetObjectProperty : public CPack//1001 } }; -struct SetHoverName : public CPack//1002 +struct SetHoverName : public CPackForClient//1002 { + void applyGs(CGameState *gs); + ui32 id; MetaString name; SetHoverName(){type = 1002;}; @@ -426,8 +511,11 @@ struct SetHoverName : public CPack//1002 h & id & name; } }; -struct HeroLevelUp : public Query//2000 +struct HeroLevelUp : public Query//2000 { + void applyCl(CClient *cl); + void applyGs(CGameState *gs); + si32 heroid; ui8 primskill, level; std::vector skills; @@ -440,8 +528,10 @@ struct HeroLevelUp : public Query//2000 } }; -struct SelectionDialog : public Query//2001 +struct SelectionDialog : public Query//2001 { + void applyCl(CClient *cl); + MetaString text; std::vector components; ui8 player; @@ -454,8 +544,10 @@ struct SelectionDialog : public Query//2001 } }; -struct YesNoDialog : public Query//2002 +struct YesNoDialog : public Query//2002 { + void applyCl(CClient *cl); + MetaString text; std::vector components; ui8 player; @@ -469,40 +561,52 @@ struct YesNoDialog : public Query//2002 }; struct BattleInfo; -struct BattleStart : public CPack//3000 +struct BattleStart : public CPackForClient//3000 { + BattleStart(){type = 3000;}; + void applyCl(CClient *cl); + void applyGs(CGameState *gs); + BattleInfo * info; - BattleStart(){type = 3000;}; template void serialize(Handler &h, const int version) { h & info; } }; -struct BattleNextRound : public CPack//3001 -{ +struct BattleNextRound : public CPackForClient//3001 +{ + BattleNextRound(){type = 3001;}; + void applyCl(CClient *cl); + void applyGs(CGameState *gs); + si32 round; - BattleNextRound(){type = 3001;}; - template void serialize(Handler &h, const int version) { h & round; } }; -struct BattleSetActiveStack : public CPack//3002 +struct BattleSetActiveStack : public CPackForClient//3002 { + BattleSetActiveStack(){type = 3002;}; + void applyCl(CClient *cl); + void applyGs(CGameState *gs); + ui32 stack; - BattleSetActiveStack(){type = 3002;}; template void serialize(Handler &h, const int version) { h & stack; } }; -struct BattleResult : public CPack//3003 +struct BattleResult : public CPackForClient//3003 { + BattleResult(){type = 3003;}; + void applyFirstCl(CClient *cl); + void applyqGs(CGameState *gs); + ui8 result; //0 - normal victory; 1 - escape; 2 - surrender ui8 winner; //0 - attacker, 1 - defender, [2 - draw (should be possible?)] std::set > casualties[2]; //first => casualties of attackers - set of pairs crid<>number @@ -511,32 +615,36 @@ struct BattleResult : public CPack//3003 - BattleResult(){type = 3003;}; template void serialize(Handler &h, const int version) { h & result & winner & casualties[0] & casualties[1] & exp & artifacts; } }; -struct BattleStackMoved : public CPack//3004 +struct BattleStackMoved : public CPackForClient//3004 { - ui32 stack, tile; BattleStackMoved(){type = 3004;}; + void applyFirstCl(CClient *cl); + void applyqGs(CGameState *gs); + + ui32 stack, tile; template void serialize(Handler &h, const int version) { h & stack & tile; } }; -struct BattleStackAttacked : public CPack//3005 +struct BattleStackAttacked : public CPackForClient//3005 { + BattleStackAttacked(){flags = 0; type = 3005;}; + void applyCl(CClient *cl); + void applyGs(CGameState *gs); + ui32 stackAttacked; ui32 newAmount, newHP, killedAmount, damageAmount; ui8 flags; //1 - is stack killed; 2 - is there special effect to be shown; 4 - lucky hit ui32 effect; //set only if flag 2 is present - - BattleStackAttacked(){flags = 0; type = 3005;}; bool killed() //if target stack was killed { return flags & 1; @@ -555,15 +663,17 @@ struct BattleStackAttacked : public CPack//3005 } }; -struct BattleAttack : public CPack//3006 +struct BattleAttack : public CPackForClient//3006 { + BattleAttack(){flags = 0; type = 3006;}; + void applyFirstCl(CClient *cl); + void applyGs(CGameState *gs); + void applyCl(CClient *cl); + BattleStackAttacked bsa; ui32 stackAttacking; ui8 flags; - - - BattleAttack(){flags = 0; type = 3006;}; bool shot()//distance attack - decrease number of shots { return flags & 1; @@ -582,42 +692,60 @@ struct BattleAttack : public CPack//3006 } }; -struct StartAction : public CPack//3007 +struct StartAction : public CPackForClient//3007 { - BattleAction ba; StartAction(){type = 3007;}; StartAction(const BattleAction &act){ba = act; type = 3007;}; + void applyFirstCl(CClient *cl); + void applyGs(CGameState *gs); + + BattleAction ba; template void serialize(Handler &h, const int version) { h & ba; } }; -struct SpellCasted : public CPack//3009 +struct EndAction : public CPackForClient//3008 { + EndAction(){type = 3008;}; + void applyCl(CClient *cl); + template void serialize(Handler &h, const int version) + { + } +}; + +struct SpellCasted : public CPackForClient//3009 +{ + SpellCasted(){type = 3009;}; + void applyGs(CGameState *gs); + void applyCl(CClient *cl); + ui8 side; //which hero casted spell: 0 - attacker, 1 - defender ui32 id; ui8 skill; ui16 tile; //destination tile (may not be set in some global/mass spells - SpellCasted(){type = 3009;}; template void serialize(Handler &h, const int version) { h & side & id & skill & tile; } }; -struct SetStackEffect : public CPack //3010 +struct SetStackEffect : public CPackForClient //3010 { + SetStackEffect(){type = 3010;}; + void applyGs(CGameState *gs); + void applyCl(CClient *cl); + ui32 stack; CStack::StackEffect effect; - SetStackEffect(){type = 3010;}; template void serialize(Handler &h, const int version) { h & stack & effect; } }; -struct ShowInInfobox : public CPack //107 +struct ShowInInfobox : public CPackForClient //107 { ShowInInfobox(){type = 107;}; ui8 player; diff --git a/lib/VCMI_lib.vcproj b/lib/VCMI_lib.vcproj index 3c9bde0d9..a3d6397ea 100644 --- a/lib/VCMI_lib.vcproj +++ b/lib/VCMI_lib.vcproj @@ -322,6 +322,10 @@ RelativePath="..\map.cpp" > + + diff --git a/map.h b/map.h index 5cfa34633..e095082ab 100644 --- a/map.h +++ b/map.h @@ -329,10 +329,6 @@ struct DLL_EXPORT Mapa : public CMapHeader TerrainTile &getTile(int3 tile); CGHeroInstance * getHero(int ID, int mode=0); bool isInTheMap(int3 pos); - template void serializeObj(Handler &h, const int version, TObject ** obj) - { - h & *obj; - } template void serialize(Handler &h, const int formatVersion) { h & static_cast(*this); @@ -404,119 +400,9 @@ struct DLL_EXPORT Mapa : public CMapHeader for(int i=0; iID) : hlp); - switch(hlp) - { - #define SERIALIZE(TYPE) ( serializeObj( h,version,(TYPE**) (&obj) ) ) - case 34: case 70: case 62: - SERIALIZE(CGHeroInstance); - break; - case 98: case 77: - SERIALIZE(CGTownInstance); - break; - case 26: //for event objects - SERIALIZE(CGEvent); - break; - case 4: //arena - case 51: //Mercenary Camp - case 23: //Marletto Tower - case 61: // Star Axis - case 32: // Garden of Revelation - case 100: //Learning Stone - case 102: //Tree of Knowledge - SERIALIZE(CGVisitableOPH); - break; - case 55: //mystical garden - case 112://windmill - case 109://water wheel - SERIALIZE(CGVisitableOPW); - break; - case 43: //teleport - case 44: //teleport - case 45: //teleport - case 103://subterranean gate - SERIALIZE(CGTeleport); - break; - case 12: //campfire - case 101: //treasure chest - SERIALIZE(CGPickable); - break; - case 54: //Monster - case 71: case 72: case 73: case 74: case 75: // Random Monster 1 - 4 - case 162: case 163: case 164: - SERIALIZE(CGCreature); - break; - case 59: case 91: //ocean bottle and sign - SERIALIZE(CGSignBottle); - break; - case 83: //seer's hut - SERIALIZE(CGSeerHut); - break; - case 113: //witch hut - SERIALIZE(CGWitchHut); - break; - case 81: //scholar - SERIALIZE(CGScholar); - break; - case 33: case 219: //garrison - SERIALIZE(CGGarrison); - break; - case 5: //artifact - case 65: case 66: case 67: case 68: case 69: //random artifact - case 93: //spell scroll - SERIALIZE(CGArtifact); - break; - case 76: case 79: //random resource; resource - SERIALIZE(CGResource); - break; - case 53: - SERIALIZE(CGMine); - break; - case 88: case 89: case 90: //spell shrine - SERIALIZE(CGShrine); - break; - case 6: - SERIALIZE(CGPandoraBox); - break; - case 217: - case 216: - case 218: - //TODO cregen - SERIALIZE(CGObjectInstance); - break; - case 215: - SERIALIZE(CGQuestGuard); - break; - case 28: //faerie ring - case 14: //Swan pond - case 38: //idol of fortune - case 30: //Fountain of Fortune - case 64: //Rally Flag - case 56: //oasis - case 96: //temple - case 110://Watering Hole - case 31: //Fountain of Youth - SERIALIZE(CGBonusingObject); - break; - case 49: //Magic Well - SERIALIZE(CGMagicWell); - break; - default: - SERIALIZE(CGObjectInstance); - } - -#undef SERIALIZE - //definfo h & (h.saving ? (shlp=obj->defInfo->serial) : shlp); //read / write pos of definfo in defs vector if(!h.saving) diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index bfd4aeaec..5bf757b50 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2327,4 +2327,26 @@ void CGameHandler::changeObjPos( int objid, int3 newPos, ui8 flags ) cop.nPos = newPos; cop.flags = flags; sendAndApply(&cop); +} + +void CGameHandler::applyAndAsk( Query * sel, ui8 player, boost::function &callback ) +{ + gsm.lock(); + sel->id = QID; + callbacks[QID] = callback; + states.addQuery(player,QID); + QID++; + sendAndApply(sel); + gsm.unlock(); +} + +void CGameHandler::ask( Query * sel, ui8 player, const CFunctionList &callback ) +{ + gsm.lock(); + sel->id = QID; + callbacks[QID] = callback; + states.addQuery(player,QID); + sendToAllClients(sel); + QID++; + gsm.unlock(); } \ No newline at end of file diff --git a/server/CGameHandler.h b/server/CGameHandler.h index 36a1e462e..27d68fcea 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -17,8 +17,8 @@ class CScriptCallback; struct BattleResult; struct BattleAttack; struct BattleStackAttacked; -template struct CPack; -template struct Query; +struct CPack; +struct Query; class CGHeroInstance; extern std::map > callbacks; //question id => callback functions - for selection dialogs extern boost::mutex gsm; @@ -116,27 +116,43 @@ public: { h & QID & states; } - template void applyAndAsk(Query * sel, ui8 player, boost::function &callback) - { - gsm.lock(); - sel->id = QID; - callbacks[QID] = callback; - states.addQuery(player,QID); - QID++; - sendAndApply(sel); - gsm.unlock(); - } - template void ask(Query * sel, ui8 player, const CFunctionList &callback) - { - gsm.lock(); - sel->id = QID; - callbacks[QID] = callback; - states.addQuery(player,QID); - sendToAllClients(sel); - QID++; - gsm.unlock(); - } + //template void applyAndAsk(Query * sel, ui8 player, boost::function &callback) + //{ + // gsm.lock(); + // sel->id = QID; + // callbacks[QID] = callback; + // states.addQuery(player,QID); + // QID++; + // sendAndApply(sel); + // gsm.unlock(); + //} + //template void ask(Query * sel, ui8 player, const CFunctionList &callback) + //{ + // gsm.lock(); + // sel->id = QID; + // callbacks[QID] = callback; + // states.addQuery(player,QID); + // sendToAllClients(sel); + // QID++; + // gsm.unlock(); + //} + //template void sendToAllClients(CPack * info) + //{ + // for(std::set::iterator i=conns.begin(); i!=conns.end();i++) + // { + // (*i)->wmx->lock(); + // **i << info->getType() << *info->This(); + // (*i)->wmx->unlock(); + // } + //} + //template void sendAndApply(CPack * info) + //{ + // gs->apply(info); + // sendToAllClients(info); + //} + void applyAndAsk(Query * sel, ui8 player, boost::function &callback); + void ask(Query * sel, ui8 player, const CFunctionList &callback); template void sendDataToClients(const T & data) { for(std::set::iterator i=conns.begin(); i!=conns.end();i++) @@ -146,19 +162,14 @@ public: (*i)->wmx->unlock(); } } - template void sendToAllClients(CPack * info) + void sendToAllClients(CPack * info) { - for(std::set::iterator i=conns.begin(); i!=conns.end();i++) - { - (*i)->wmx->lock(); - **i << info->getType() << *info->This(); - (*i)->wmx->unlock(); - } + } - template void sendAndApply(CPack * info) + void sendAndApply(CPack * info) { - gs->apply(info); - sendToAllClients(info); + //gs->apply(info); + //sendToAllClients(info); } void run(bool resume); void newTurn();