Michał W. Urbańczyk 16 years ago
parent
commit
b1c0d10ece
16 changed files with 492 additions and 1326 deletions
  1. 9 3
      CCallback.cpp
  2. 2 20
      CGameInterface.cpp
  3. 7 506
      CGameState.cpp
  4. 2 6
      CGameState.h
  5. 0 2
      CMT.cpp
  6. 0 532
      client/Client.cpp
  7. 3 1
      client/Client.h
  8. 4 0
      client/VCMI_client.vcproj
  9. 29 0
      lib/Connection.cpp
  10. 140 13
      lib/Connection.h
  11. 2 0
      lib/IGameCallback.h
  12. 223 95
      lib/NetPacks.h
  13. 4 0
      lib/VCMI_lib.vcproj
  14. 2 116
      map.h
  15. 22 0
      server/CGameHandler.cpp
  16. 43 32
      server/CGameHandler.h

+ 9 - 3
CCallback.cpp

@@ -26,7 +26,7 @@
 #ifdef max
 #undef max
 #endif
-extern CSharedCond<std::set<IPack*> > mess;
+extern CSharedCond<std::set<CPack*> > mess;
 
 int gcd(int x, int y)
 {
@@ -48,6 +48,12 @@ HeroMoveDetails::HeroMoveDetails(int3 Src, int3 Dst, CGHeroInstance*Ho)
 {
 	owner = ho->getOwner();
 };
+
+template <ui16 N> 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<boost::mutex> 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<IPack*>::iterator itr = std::find_if(mess.res->begin(),mess.res->end(),IPack::isType<501>);
+			std::set<CPack*>::iterator itr = std::find_if(mess.res->begin(),mess.res->end(),&isType<501>);
 			TryMoveHero tmh = *static_cast<TryMoveHero*>(*itr);
 			mess.res->erase(itr);
 			if(!tmh.result)

+ 2 - 20
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 <sstream>
-#include "hch/CHeroHandler.h"
-#include "SDL_framerate.h"
-#include "AI/EmptyAI/CEmptyAI.h"
 
 #ifdef _WIN32
 	#include <windows.h> //for .dll libs
 #else
 	#include <dlfcn.h>
 #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()
-//{
-//}

+ 7 - 506
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<NewTurn*>(pack);
-			day = n->day;
-			BOOST_FOREACH(NewTurn::Hero h, n->heroes) //give mana/movement point
-			{
-				static_cast<CGHeroInstance*>(map->objects[h.id])->movement = h.move;
-				static_cast<CGHeroInstance*>(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<SetResource*>(pack);
-			players[sr->player].resources[sr->resid] = sr->val;
-			break;
-		}
-	case 104:
-		{
-			SetResources *sr = static_cast<SetResources*>(pack);
-			for(int i=0;i<sr->res.size();i++)
-				players[sr->player].resources[i] = sr->res[i];
-			break;
-		}
-	case 105:
-		{
-			SetPrimSkill *sr = static_cast<SetPrimSkill*>(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<SetSecSkill*>(pack);
-			CGHeroInstance *hero = getHero(sr->id);
-			if(hero->getSecSkillLevel(sr->which) == 0)
-			{
-				hero->secSkills.push_back(std::pair<int,int>(sr->which, sr->val));
-			}
-			else
-			{
-				for(unsigned i=0;i<hero->secSkills.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<HeroVisitCastle*>(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<ChangeSpells*>(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<SetMana*>(pack);
-			CGHeroInstance *hero = getHero(rh->hid);
-			hero->mana = rh->val;
-			break;
-		}
-	case 111:
-		{
-			SetMovePoints *rh = static_cast<SetMovePoints*>(pack);
-			CGHeroInstance *hero = getHero(rh->hid);
-			hero->movement = rh->val;
-			break;
-		}
-	case 112:
-		{
-			FoWChange *rh = static_cast<FoWChange*>(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<SetAvailableHeroes*>(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<ui32,si32>(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<ui32,si32>(VLC->creh->nameToID[h->type->refTypeStack[0]],1);
-			}
-			break;
-		}
-	case 115:
-		{
-			GiveBonus *rh = static_cast<GiveBonus*>(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<ChangeObjPos*>(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<RemoveObject*>(pack);
-			CGObjectInstance *obj = map->objects[rh->id];
-			if(obj->ID==HEROI_TYPE)
-			{
-				CGHeroInstance *h = static_cast<CGHeroInstance*>(obj);
-				std::vector<CGHeroInstance*>::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<TryMoveHero*>(pack);
-			CGHeroInstance *h = static_cast<CGHeroInstance*>(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<SetGarrisons*>(pack);
-			for(std::map<ui32,CCreatureSet>::iterator i = n->garrs.begin(); i!=n->garrs.end(); i++)
-			{
-				CArmedInstance *ai = static_cast<CArmedInstance*>(map->objects[i->first]);
-				ai->army = i->second;
-				if(ai->ID==TOWNI_TYPE && (static_cast<CGTownInstance*>(ai))->garrisonHero) //if there is a hero in garrison then we must update also his army
-					const_cast<CGHeroInstance*>((static_cast<CGTownInstance*>(ai))->garrisonHero)->army = i->second;
-				else if(ai->ID==HEROI_TYPE)
-				{
-					CGHeroInstance *h =  static_cast<CGHeroInstance*>(ai);
-					if(h->visitedTown && h->inTownGarrison)
-						h->visitedTown->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 506:
-		{
-			SetAvailableCreatures *sac = static_cast<SetAvailableCreatures*>(pack);
-			static_cast<CGTownInstance*>(map->objects[sac->tid])->strInfo.creatures = sac->creatures;
-			break;
-		}
-	case 508:
-		{
-			SetHeroesInTown *sac = static_cast<SetHeroesInTown*>(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<SetHeroArtifacts*>(pack);
-			CGHeroInstance *h = getHero(sha->hid);
-			h->artifacts = sha->artifacts;
-			h->artifWorn = sha->artifWorn;
-			break;
-		}
-	case 514:
-		{
-			SetSelection *ss = static_cast<SetSelection*>(pack);
-			players[ss->player].currentSelection = ss->id;
-			break;
-		}
-	case 515:
-		{
-			HeroRecruited *sha = static_cast<HeroRecruited*>(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<GiveHero*>(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<SetObjectProperty*>(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<SetHoverName*>(pack);
-			map->objects[shn->id]->hoverName = toString(shn->name);
-			break;
-		}
-	case 2000:
-		{
-			HeroLevelUp * bs = static_cast<HeroLevelUp*>(pack);
-			getHero(bs->heroid)->level = bs->level;
-			break;
-		}
-	case 3000:
-		{
-			BattleStart * bs = static_cast<BattleStart*>(pack);
-			curB = bs->info;
-			break;
-		}
-	case 3001:
-		{
-			BattleNextRound *ns = static_cast<BattleNextRound*>(pack);
-			curB->castedSpells[0] = curB->castedSpells[1] = 0;
-			curB->round = ns->round;
-			for(int i=0; i<curB->stacks.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<BattleSetActiveStack*>(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<BattleResult*>(pack);
-			for(unsigned i=0;i<curB->stacks.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<BattleStackMoved*>(pack);
-			curB->getStack(br->stack)->position = br->tile;
-			break;
-		}
-	case 3005:
-		{
-			BattleStackAttacked *br = static_cast<BattleStackAttacked*>(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<BattleAttack*>(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<StartAction*>(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<SpellCasted*>(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<SetStackEffect*>(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;

+ 2 - 6
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<int,int> pickObject(CGObjectInstance *obj);
 	int pickHero(int owner);
@@ -243,7 +239,7 @@ private:
 	float getMarketEfficiency(int player, int mode=0);
 	std::set<int3> 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<int3> &vec, bool onLand);

+ 0 - 2
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<SDL_Event> events;
 boost::mutex eventsM;
 TTF_Font * TNRB16, *TNR, *GEOR13, *GEORXX, *GEORM, *GEOR16;

+ 0 - 532
client/Client.cpp

@@ -25,7 +25,6 @@
 #include <boost/thread.hpp>
 #include <boost/thread/shared_mutex.hpp>
 #include <sstream>
-CSharedCond<std::set<IPack*> > mess(new std::set<IPack*>);
 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."<<std::endl;
-			gs->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!"<<std::endl;
-			break;
-		}
-	case 102: //set resource amount
-		{
-			SetResource sr;
-			*serv >> sr;
-			tlog5 << "Set amount of "<<CGI->generaltexth->restypes[sr.resid] 
-			  << " of player "<<(unsigned)sr.player <<" to "<<sr.val<<std::endl;
-			gs->apply(&sr);
-			playerint[sr.player]->receivedResource(sr.resid,sr.val);
-			break;
-		}
-	case 103: //show info dialog
-		{
-			InfoWindow iw;
-			*serv >> iw;
-			std::vector<Component*> comps;
-			for(size_t i=0;i<iw.components.size();i++) {
-				comps.push_back(&iw.components[i]);
-                        }
-			std::string str = toString(iw.text);
-			playerint[iw.player]->showInfoDialog(str,comps);
-			break;
-		}
-	case 104:
-		{
-			SetResources sr;
-			*serv >> sr;
-			tlog5 << "Set amount of resources of player "<<(unsigned)sr.player<<std::endl;
-			gs->apply(&sr);
-			playerint[sr.player]->receivedResource(-1,-1);
-			break;
-		}
-	case 105:
-		{
-			SetPrimSkill sps;
-			*serv >> sps;
-			tlog5 << "Changing hero primary skill"<<std::endl;
-			gs->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"<<std::endl;
-			gs->apply(&sr);
-			//TODO? - maybe inform interfaces
-			break;
-		}
 	case 107:
 		{
 			ShowInInfobox sii;
@@ -143,227 +67,6 @@ void CClient::process(int what)
 				static_cast<CPlayerInterface*>(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 "<<vc.hid<<std::endl;
-			gs->apply(&vc);
-			break;
-		}
-	case 110:
-		{
-			SetMana sm;
-			*serv >> sm;
-			tlog5 << "Setting mana value of hero "<<sm.hid<<" to "<<sm.val<<std::endl;
-			gs->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 "<<smp.hid<<" to "<<smp.val<<std::endl;
-			gs->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<<std::endl;
-			gs->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<<std::endl;
-			gs->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<CGHeroInstance*>(obj);
-				tlog5 << "Removing hero with id = "<<(unsigned)rh.id<<std::endl;
-				playerint[h->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="<<th->id<<"\tResult: "<<(unsigned)th->result<<"\tPosition "<<th->end<<std::endl;
-
-			HeroMoveDetails hmd(th->start,th->end,static_cast<CGHeroInstance*>(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<ui8, CGameInterface*>::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<ui32,CCreatureSet>::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<CGTownInstance*>(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 "<<sop.val<<std::endl;
-			gs->apply(&sop);
-			break;
-		}
-	case 1002:
-		{
-			SetHoverName shn;
-			*serv >> shn;
-			tlog5 << "Setting a name of " << shn.id <<" object to "<< toString(shn.name) <<std::endl;
-			gs->apply(&shn);
-			break;
-		}
-	case 2000:
-		{
-			HeroLevelUp  bs;
-			*serv >> bs;
-			tlog5 << "Hero levels up!" <<std::endl;
-			gs->apply(&bs);
-			CGHeroInstance *h = gs->getHero(bs.heroid);
-			if(vstd::contains(playerint,h->tempOwner))
-			{
-				boost::function<void(ui32)> callback = boost::function<void(ui32)>(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 " <<std::endl;
-			std::vector<Component*> 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 " <<std::endl;
-			std::vector<Component*> 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!" <<std::endl;
-			gs->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 <<std::endl;
-			gs->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 <<std::endl;
-			gs->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 <<std::endl;
-
-			if(playerint.find(gs->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 "<<br.stack <<" moves to the tile "<<br.tile<<std::endl;
-			if(playerint.find(gs->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 <<std::endl;
-			if(playerint.find(gs->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 <<std::endl;
-			if(playerint.find(gs->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:

+ 3 - 1
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<ui8,CGameInterface *> playerint;
 	CConnection *serv;
 	SharedMem *shared;
+	BattleAction *curbaction;
 
 	void waitForMoveAndSend(int color);
-public:
 	CClient(void);
 	CClient(CConnection *con, StartInfo *si);
 	~CClient(void);

+ 4 - 0
client/VCMI_client.vcproj

@@ -374,6 +374,10 @@
 				RelativePath="..\mapHandler.cpp"
 				>
 			</File>
+			<File
+				RelativePath=".\NetPacksClient.cpp"
+				>
+			</File>
 			<File
 				RelativePath="..\SDL_Extensions.cpp"
 				>

+ 29 - 0
lib/Connection.cpp

@@ -4,9 +4,12 @@
 #include <boost/asio.hpp>
 #include <boost/thread.hpp>
 #include <fstream>
+
 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 type_info *,ui16>::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;
 }

+ 140 - 13
lib/Connection.h

@@ -5,6 +5,7 @@
 #include <vector>
 #include <set>
 #include <list>
+#include <typeinfo>
 
 #include <boost/type_traits/is_fundamental.hpp>
 #include <boost/type_traits/is_enum.hpp>
@@ -20,7 +21,6 @@
 #include <boost/type_traits/is_array.hpp>
 const ui32 version = 703;
 class CConnection;
-
 namespace mpl = boost::mpl;
 
 namespace boost
@@ -53,6 +53,28 @@ enum SerializationLvl
 	Serializable
 };
 
+ template<typename Serializer> DLL_EXPORT void registerTypes(Serializer &s); //defined in .cpp and explicitly instantiated for used serializers
+
+class DLL_EXPORT CTypeList
+{
+	std::map<const type_info *,ui16> types;
+public:
+	CTypeList();
+	ui16 registerType(const type_info *type);
+	template <typename T> ui16 registerType(const T * t)
+	{
+		return registerType(&typeid(*t));
+	}
+
+	ui16 getTypeID(const type_info *type);
+	template <typename T> ui16 getTypeID(const T * t)
+	{
+		return getTypeID(&typeid(*t));
+	}
+};
+
+extern DLL_EXPORT CTypeList typeList;
+
 template<typename Ser,typename T>
 struct SavePrimitive
 {
@@ -169,11 +191,51 @@ struct SerializationLevel
 	static const int value = SerializationLevel::type::value;
 };
 
-template <typename Serializer> 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 <typename Serializer, typename T> class CPointerSaver : public CBasicPointerSaver
+{
+public:
+	void savePtr(CSaverBase &ar, const void *data) const
+	{
+		Serializer &s = static_cast<Serializer&>(ar);
+		const T *ptr = static_cast<const T*>(data);
+
+		//T is most derived known type, it's time to call actual serialize
+		const_cast<T&>(*ptr).serialize(s,version);
+	}
+};
+
+template <typename Serializer> class DLL_EXPORT COSer : public CSaverBase
+{
+public:
+	std::map<ui16,CBasicPointerSaver*> savers; // typeID => CPointerSaver<serializer,type>
+
+	COSer()
+	{
+		saving=true;
+	}
+
+	template<typename T> void registerType(const T * t=NULL)
+	{
+		ui16 ID = typeList.registerType(&typeid(T));
+		savers[ID] = new CPointerSaver<Serializer,T>;
+	}
+
     Serializer * This()
 	{
 		return static_cast<Serializer*>(this);
@@ -185,7 +247,7 @@ public:
 		this->This()->save(t);
 		return * this->This();
 	}
-	
+
 	template<class T>
 	COSer & operator&(const T & t)
 	{
@@ -200,14 +262,28 @@ public:
 	{
 		this->This()->write(&data,sizeof(data));
 	}
+
 	template <typename T>
 	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 <typename T>
 	void saveArray(const T &data)
 	{
@@ -288,11 +364,52 @@ public:
 			*this << i->first << i->second;
 	}
 };
-template <typename Serializer> class DLL_EXPORT CISer
+
+
+
+class DLL_EXPORT CLoaderBase : public virtual CSerializerBase
+{};
+
+class CBasicPointerLoader
+{
+public:
+	virtual void loadPtr(CLoaderBase &ar, void *data) const =0; //data is pointer to the ACTUAL POINTER
+};
+
+template <typename Serializer, typename T> class CPointerLoader : public CBasicPointerLoader
 {
 public:
-	bool saving;
-	CISer(){saving = false;};
+	void loadPtr(CLoaderBase &ar, void *data) const //data is pointer to the ACTUAL POINTER
+	{
+		Serializer &s = static_cast<Serializer&>(ar);
+		T *&ptr = *static_cast<T**>(data);
+
+		//create new object under pointer
+		typedef typename boost::remove_pointer<T>::type npT;
+		ptr = new npT;
+
+		//T is most derived known type, it's time to call actual serialize
+		ptr->serialize(s,version);
+	}
+};
+
+
+template <typename Serializer> class DLL_EXPORT CISer : public CLoaderBase
+{
+public:
+	std::map<ui16,CBasicPointerLoader*> loaders; // typeID => CPointerSaver<serializer,type>
+
+	CISer()
+	{
+		saving = false;
+	}
+
+	template<typename T> void registerType(const T * t=NULL)
+	{
+		ui16 ID = typeList.registerType(&typeid(T));
+		loaders[ID] = new CPointerLoader<Serializer,T>;
+	}
+
     Serializer * This()
 	{
 		return static_cast<Serializer*>(this);
@@ -364,10 +481,20 @@ public:
 			return;
 		}
 
-		tlog5<<"Allocating memory for pointer!"<<std::endl;
-		typedef typename boost::remove_pointer<T>::type npT;
-		data = new npT;
-		*this >> *data;
+		//get type id
+		ui16 tid;
+		*this >> tid;
+
+		if(!tid)
+		{
+			typedef typename boost::remove_pointer<T>::type npT;
+			data = new npT;
+			*this >> *data;
+		}
+		else
+		{
+			loaders[tid]->loadPtr(*this,&data);
+		}
 	}
 	template <typename T>
 	void loadSerializable(std::vector<T> &data)

+ 2 - 0
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__

+ 223 - 95
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 <set>
 
-struct IPack
+class CClient;
+class CGameState;
+
+struct CPack
 {
-	virtual ui16 getType()const = 0 ;
-	//template<ui16 Type>
-	//static bool isType(const IPack * ip)
-	//{
-	//	return Type == ip->getType();
-	//}
-	template<ui16 Type>
-	static bool isType(IPack * ip)
-	{
-		return Type == ip->getType();
-	}
-	//template<ui16 Type>
-	//static bool isType(const IPack & ip)
-	//{
-	//	return Type == ip.getType();
-	//}
+	ui16 type;
+
+	CPack(){};
+	~CPack(){};
+	ui16 getType() const{return type;}
 };
-template <typename T> struct CPack
-	:public IPack
+
+struct CPackForClient : public CPack
 {
-	ui16 type; 
-	ui16 getType() const{return type;}
-	T* This(){return static_cast<T*>(this);};
+	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
 };
-template <typename T> struct Query
-	:public CPack<T>
+
+struct Query : public CPackForClient
 {
 	ui32 id;
 };
 
-struct MetaString : public CPack<MetaString> //2001 helper for object scrips
+struct MetaString : public CPack //2001 helper for object scrips
 {
 	std::vector<std::string> strings;
 	std::vector<std::pair<ui8,ui32> > texts; //pairs<text handler type, text number>; 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<MetaString> //2001 helper for object scrips
 	MetaString(){type = 2001;};
 }; 
 
-struct SetResources : public CPack<SetResources> //104
+struct SystemMessage : public CPackForClient //95
 {
-	SetResources(){res.resize(RESOURCE_QUANTITY);type = 104;};
-	ui8 player;
-	std::vector<si32> res; //res[resid] => res amount
+	SystemMessage(){type = 95;};
+	void applyCl(CClient *cl);
 
+	std::string text;
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & player & res;
 	}
 };
-struct SetResource : public CPack<SetResource> //102
+
+struct YourTurn : public CPackForClient //100
+{
+	YourTurn(){type = 100;};
+	void applyCl(CClient *cl);
+	void applyGs(CGameState *gs);
+
+	ui8 player;
+	template <typename Handler> 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<SetResource> //102
 		h & player & resid & val;
 	}
 }; 
-struct SetPrimSkill : public CPack<SetPrimSkill> //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<si32> res; //res[resid] => res amount
+
+	template <typename Handler> 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<SetPrimSkill> //105
 		h & abs & id & which & val;
 	}
 }; 
-struct SetSecSkill : public CPack<SetSecSkill> //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<SetSecSkill> //106
 		h & abs & id & which & val;
 	}
 }; 
-struct HeroVisitCastle : public CPack<HeroVisitCastle> //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<HeroVisitCastle> //108
 		h & flags & tid & hid;
 	}
 }; 
-struct ChangeSpells : public CPack<ChangeSpells> //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<ui32> spells;
@@ -149,9 +186,13 @@ struct ChangeSpells : public CPack<ChangeSpells> //109
 	}
 }; 
 
-struct SetMana : public CPack<SetMana> //110
+struct SetMana : public CPackForClient //110
 {
 	SetMana(){type = 110;};
+	void applyCl(CClient *cl);
+	void applyGs(CGameState *gs);
+
+
 	ui32 hid, val;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
@@ -159,9 +200,12 @@ struct SetMana : public CPack<SetMana> //110
 		h & val & hid;
 	}
 }; 
-struct SetMovePoints : public CPack<SetMovePoints> //111
+struct SetMovePoints : public CPackForClient //111
 {
 	SetMovePoints(){type = 111;};
+	void applyCl(CClient *cl);
+	void applyGs(CGameState *gs);
+
 	ui32 hid, val;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
@@ -169,9 +213,12 @@ struct SetMovePoints : public CPack<SetMovePoints> //111
 		h & val & hid;
 	}
 }; 
-struct FoWChange : public CPack<FoWChange> //112
+struct FoWChange : public CPackForClient //112
 {
 	FoWChange(){type = 112;};
+	void applyCl(CClient *cl);
+	void applyGs(CGameState *gs);
+
 	std::set<int3> tiles;
 	ui8 player, mode; //mode==0 - hide, mode==1 - reveal
 	template <typename Handler> void serialize(Handler &h, const int version)
@@ -180,9 +227,12 @@ struct FoWChange : public CPack<FoWChange> //112
 	}
 }; 
 
-struct SetAvailableHeroes : public CPack<SetAvailableHeroes> //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<SetAvailableHeroes> //113
 	}
 };
 
-struct GiveBonus :  public CPack<GiveBonus> //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<GiveBonus> //115
 	}
 };
 
-struct ChangeObjPos : public CPack<ChangeObjPos> //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<ChangeObjPos> //116
 	}
 };
 
-struct RemoveObject : public CPack<RemoveObject> //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 <typename Handler> void serialize(Handler &h, const int version)
@@ -231,9 +290,12 @@ struct RemoveObject : public CPack<RemoveObject> //500
 		h & id;
 	}
 }; 
-struct TryMoveHero : public CPack<TryMoveHero> //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<TryMoveHero> //501
 		h & id & result & start & end & movePoints & fowRevealed;
 	}
 }; 
-struct SetGarrisons : public CPack<SetGarrisons> //502
+struct SetGarrisons : public CPackForClient //502
 {
 	SetGarrisons(){type = 502;};
+	void applyCl(CClient *cl);
+	void applyGs(CGameState *gs);
+
 	std::map<ui32,CCreatureSet> garrs;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
@@ -255,9 +320,12 @@ struct SetGarrisons : public CPack<SetGarrisons> //502
 		h & garrs;
 	}
 }; 
-struct NewStructures : public CPack<NewStructures> //504
+struct NewStructures : public CPackForClient //504
 {
 	NewStructures(){type = 504;};
+	void applyCl(CClient *cl);
+	void applyGs(CGameState *gs);
+
 	si32 tid;
 	std::set<si32> bid;
 	si16 builded; 
@@ -267,9 +335,12 @@ struct NewStructures : public CPack<NewStructures> //504
 		h & tid & bid & builded;
 	}
 }; 
-struct SetAvailableCreatures : public CPack<SetAvailableCreatures> //506
+struct SetAvailableCreatures : public CPackForClient //506
 {
 	SetAvailableCreatures(){type = 506;};
+	void applyCl(CClient *cl);
+	void applyGs(CGameState *gs);
+
 	si32 tid;
 	std::map<si32,ui32> creatures;
 
@@ -278,9 +349,12 @@ struct SetAvailableCreatures : public CPack<SetAvailableCreatures> //506
 		h & tid & creatures;
 	}
 };  
-struct SetHeroesInTown : public CPack<SetHeroesInTown> //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 <typename Handler> void serialize(Handler &h, const int version)
@@ -288,9 +362,12 @@ struct SetHeroesInTown : public CPack<SetHeroesInTown> //508
 		h & tid & visiting & garrison;
 	}
 };  
-struct SetHeroArtifacts : public CPack<SetHeroArtifacts> //509
+struct SetHeroArtifacts : public CPackForClient //509
 {
 	SetHeroArtifacts(){type = 509;};
+	void applyCl(CClient *cl);
+	void applyGs(CGameState *gs);
+
 	si32 hid;
 	std::vector<ui32> artifacts; //hero's artifacts from bag
 	std::map<ui16,ui32> artifWorn; //map<position,artifact_id>; 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<SetHeroArtifacts> //509
 	}
 };  
 
-struct SetSelection : public CPack<SetSelection> //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<SetSelection> //514
 	}
 };  
 
-struct HeroRecruited : public CPack<HeroRecruited> //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<HeroRecruited> //515
 	}
 };  
 
-struct GiveHero : public CPack<GiveHero> //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<GiveHero> //516
 	}
 };  
 
-struct NewTurn : public CPack<NewTurn> //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<NewTurn> //101
 		h & heroes & cres & res & day & resetBuilded;
 	}
 }; 
-//struct SetStrInfo : public CPack<SetStrInfo> //503
-//{
-//	SetStrInfo(){type = 503;};
-//	SetAvailableCreatures sac;
-//
-//	template <typename Handler> void serialize(Handler &h, const int version)
-//	{
-//		h & sac;
-//	}
-//};  
-struct Component : public CPack<Component> //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<Component> //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<InfoWindow> //103  - displays simple info window
+struct InfoWindow : public CPackForClient //103  - displays simple info window
 {
+	void applyCl(CClient *cl);
+
 	MetaString text;
 	std::vector<Component> components;
 	ui8 player;
@@ -400,8 +481,10 @@ struct InfoWindow : public CPack<InfoWindow> //103  - displays simple info windo
 	InfoWindow(){type = 103;};
 };
 
-struct SetObjectProperty : public CPack<SetObjectProperty>//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<SetObjectProperty>//1001
 	}
 };
 
-struct SetHoverName : public CPack<SetHoverName>//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<SetHoverName>//1002
 		h & id & name;
 	}
 };
-struct HeroLevelUp : public Query<HeroLevelUp>//2000
+struct HeroLevelUp : public Query//2000
 {
+	void applyCl(CClient *cl);
+	void applyGs(CGameState *gs);
+
 	si32 heroid;
 	ui8 primskill, level;
 	std::vector<ui16> skills;
@@ -440,8 +528,10 @@ struct HeroLevelUp : public Query<HeroLevelUp>//2000
 	}
 };
 
-struct SelectionDialog : public Query<SelectionDialog>//2001
+struct SelectionDialog : public Query//2001
 {
+	void applyCl(CClient *cl);
+
 	MetaString text;
 	std::vector<Component> components;
 	ui8 player;
@@ -454,8 +544,10 @@ struct SelectionDialog : public Query<SelectionDialog>//2001
 	}
 };
 
-struct YesNoDialog : public Query<YesNoDialog>//2002
+struct YesNoDialog : public Query//2002
 {
+	void applyCl(CClient *cl);
+
 	MetaString text;
 	std::vector<Component> components;
 	ui8 player;
@@ -469,40 +561,52 @@ struct YesNoDialog : public Query<YesNoDialog>//2002
 };
 
 struct BattleInfo;
-struct BattleStart : public CPack<BattleStart>//3000
+struct BattleStart : public CPackForClient//3000
 {
+	BattleStart(){type = 3000;};
+	void applyCl(CClient *cl);
+	void applyGs(CGameState *gs);
+
 	BattleInfo * info;
 
-	BattleStart(){type = 3000;};
 	
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & info;
 	}
 };
-struct BattleNextRound : public CPack<BattleNextRound>//3001
-{
+struct BattleNextRound : public CPackForClient//3001
+{	
+	BattleNextRound(){type = 3001;};
+	void applyCl(CClient *cl);
+	void applyGs(CGameState *gs);
+
 	si32 round;
 
-	BattleNextRound(){type = 3001;};
-	
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & round;
 	}
 };
-struct BattleSetActiveStack : public CPack<BattleSetActiveStack>//3002
+struct BattleSetActiveStack : public CPackForClient//3002
 {
+	BattleSetActiveStack(){type = 3002;};
+	void applyCl(CClient *cl);
+	void applyGs(CGameState *gs);
+
 	ui32 stack;
 
-	BattleSetActiveStack(){type = 3002;};
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & stack;
 	}
 };
-struct BattleResult : public CPack<BattleResult>//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<std::pair<ui32,si32> > casualties[2]; //first => casualties of attackers - set of pairs crid<>number
@@ -511,32 +615,36 @@ struct BattleResult : public CPack<BattleResult>//3003
 
 
 
-	BattleResult(){type = 3003;};
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & result & winner & casualties[0] & casualties[1] & exp & artifacts;
 	}
 };
 
-struct BattleStackMoved : public CPack<BattleStackMoved>//3004
+struct BattleStackMoved : public CPackForClient//3004
 {
-	ui32 stack, tile;
 	BattleStackMoved(){type = 3004;};
+	void applyFirstCl(CClient *cl);
+	void applyqGs(CGameState *gs);
+
+	ui32 stack, tile;
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & stack & tile;
 	}
 };
 
-struct BattleStackAttacked : public CPack<BattleStackAttacked>//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<BattleStackAttacked>//3005
 	}
 };
 
-struct BattleAttack : public CPack<BattleAttack>//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<BattleAttack>//3006
 	}
 };
 
-struct StartAction : public CPack<StartAction>//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 <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & ba;
 	}
 };
 
-struct SpellCasted : public CPack<SpellCasted>//3009
+struct EndAction : public CPackForClient//3008
 {
+	EndAction(){type = 3008;};
+	void applyCl(CClient *cl);
+	template <typename Handler> 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 <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & side & id & skill & tile;
 	}
 };
 
-struct SetStackEffect : public CPack<SetStackEffect> //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 <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & stack & effect;
 	}
 };
 
-struct ShowInInfobox : public CPack<ShowInInfobox> //107
+struct ShowInInfobox : public CPackForClient //107
 {
 	ShowInInfobox(){type = 107;};
 	ui8 player;

+ 4 - 0
lib/VCMI_lib.vcproj

@@ -322,6 +322,10 @@
 				RelativePath="..\map.cpp"
 				>
 			</File>
+			<File
+				RelativePath=".\RegisterTypes.cpp"
+				>
+			</File>
 			<File
 				RelativePath="..\stdafx.cpp"
 				>

+ 2 - 116
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 <typename TObject, typename Handler> void serializeObj(Handler &h, const int version, TObject ** obj)
-	{
-		h & *obj;
-	}
 	template <typename Handler> void serialize(Handler &h, const int formatVersion)
 	{
 		h & static_cast<CMapHeader&>(*this);
@@ -404,119 +400,9 @@ struct DLL_EXPORT Mapa : public CMapHeader
 		for(int i=0; i<objects.size(); i++)
 		{
 			CGObjectInstance *&obj = objects[i];
-			ui8 exists = (obj!=NULL);
-			ui32 hlp;
-			si32 shlp;
-			h & exists;
-			if(!exists)
-			{
-				if(!h.saving)
-					obj = 0;
-				continue;
-			}
-			h & (h.saving ? (hlp=obj->ID) : hlp);
-			switch(hlp)
-			{
-				#define SERIALIZE(TYPE) (   serializeObj<TYPE>( 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
+			h & obj;
 
+			si32 shlp;
 			//definfo
 			h & (h.saving ? (shlp=obj->defInfo->serial) : shlp); //read / write pos of definfo in defs vector
 			if(!h.saving)

+ 22 - 0
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<void(ui32)> &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<void(ui32)> &callback )
+{
+	gsm.lock();
+	sel->id = QID;
+	callbacks[QID] = callback;
+	states.addQuery(player,QID);
+	sendToAllClients(sel);
+	QID++; 
+	gsm.unlock();
 }

+ 43 - 32
server/CGameHandler.h

@@ -17,8 +17,8 @@ class CScriptCallback;
 struct BattleResult;
 struct BattleAttack;
 struct BattleStackAttacked;
-template <typename T> struct CPack;
-template <typename T> struct Query;
+struct CPack;
+struct Query;
 class CGHeroInstance;
 extern std::map<ui32, CFunctionList<void(ui32)> > callbacks; //question id => callback functions - for selection dialogs
 extern boost::mutex gsm;
@@ -116,27 +116,43 @@ public:
 	{
 		h & QID & states;
 	}
-	template <typename T> void applyAndAsk(Query<T> * sel, ui8 player, boost::function<void(ui32)> &callback)
-	{
-		gsm.lock();
-		sel->id = QID;
-		callbacks[QID] = callback;
-		states.addQuery(player,QID);
-		QID++; 
-		sendAndApply(sel);
-		gsm.unlock();
-	}
-	template <typename T> void ask(Query<T> * sel, ui8 player, const CFunctionList<void(ui32)> &callback)
-	{
-		gsm.lock();
-		sel->id = QID;
-		callbacks[QID] = callback;
-		states.addQuery(player,QID);
-		sendToAllClients(sel);
-		QID++; 
-		gsm.unlock();
-	}
+	//template <typename T> void applyAndAsk(Query<T> * sel, ui8 player, boost::function<void(ui32)> &callback)
+	//{
+	//	gsm.lock();
+	//	sel->id = QID;
+	//	callbacks[QID] = callback;
+	//	states.addQuery(player,QID);
+	//	QID++; 
+	//	sendAndApply(sel);
+	//	gsm.unlock();
+	//}
+	//template <typename T> void ask(Query<T> * sel, ui8 player, const CFunctionList<void(ui32)> &callback)
+	//{
+	//	gsm.lock();
+	//	sel->id = QID;
+	//	callbacks[QID] = callback;
+	//	states.addQuery(player,QID);
+	//	sendToAllClients(sel);
+	//	QID++; 
+	//	gsm.unlock();
+	//}
 
+	//template <typename T>void sendToAllClients(CPack<T> * info)
+	//{
+	//	for(std::set<CConnection*>::iterator i=conns.begin(); i!=conns.end();i++)
+	//	{
+	//		(*i)->wmx->lock();
+	//		**i << info->getType() << *info->This();
+	//		(*i)->wmx->unlock();
+	//	}
+	//}
+	//template <typename T>void sendAndApply(CPack<T> * info)
+	//{
+	//	gs->apply(info);
+	//	sendToAllClients(info);
+	//}
+	void applyAndAsk(Query * sel, ui8 player, boost::function<void(ui32)> &callback);
+	void ask(Query * sel, ui8 player, const CFunctionList<void(ui32)> &callback);
 	template <typename T>void sendDataToClients(const T & data)
 	{
 		for(std::set<CConnection*>::iterator i=conns.begin(); i!=conns.end();i++)
@@ -146,19 +162,14 @@ public:
 			(*i)->wmx->unlock();
 		}
 	}
-	template <typename T>void sendToAllClients(CPack<T> * info)
+	void sendToAllClients(CPack * info)
 	{
-		for(std::set<CConnection*>::iterator i=conns.begin(); i!=conns.end();i++)
-		{
-			(*i)->wmx->lock();
-			**i << info->getType() << *info->This();
-			(*i)->wmx->unlock();
-		}
+
 	}
-	template <typename T>void sendAndApply(CPack<T> * info)
+	void sendAndApply(CPack * info)
 	{
-		gs->apply(info);
-		sendToAllClients(info);
+		//gs->apply(info);
+		//sendToAllClients(info);
 	}
 	void run(bool resume);
 	void newTurn();