Răsfoiți Sursa

* a bit better stack reversing
* FoWChange uses unordered_set instead of set

mateuszb 14 ani în urmă
părinte
comite
2451c0dea6

+ 2 - 2
CGameInterface.h

@@ -128,8 +128,8 @@ public:
 	virtual void showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor){};
 	virtual void showTavernWindow(const CGObjectInstance *townOrTavern){};
 	virtual void advmapSpellCast(const CGHeroInstance * caster, int spellID){}; //called when a hero casts a spell
-	virtual void tileHidden(const std::set<int3> &pos){};
-	virtual void tileRevealed(const std::set<int3> &pos){};
+	virtual void tileHidden(const boost::unordered_set<int3, ShashInt3> &pos){};
+	virtual void tileRevealed(const boost::unordered_set<int3, ShashInt3> &pos){};
 	virtual void newObject(const CGObjectInstance * obj){}; //eg. ship built in shipyard
 	virtual void availableArtifactsChanged(const CGBlackMarket *bm = NULL){}; //bm may be NULL, then artifacts are changed in the global pool (used by merchants in towns)
 	virtual void yourTurn(){};

+ 3 - 3
client/CBattleInterface.cpp

@@ -3245,9 +3245,9 @@ void CBattleInterface::endAction(const BattleAction* action)
 	}
 
 	//check if we should reverse stacks
-	std::vector<const CStack *> stacks;
-	stacks.push_back(LOCPLINT->cb->battleGetStackByID(action->stackNumber));
-	stacks.push_back(LOCPLINT->cb->battleGetStackByPos(action->destinationTile));
+	std::set<const CStack *> stacks;
+	stacks.insert(LOCPLINT->cb->battleGetStackByID(action->stackNumber));
+	stacks.insert(LOCPLINT->cb->battleGetStackByPos(action->destinationTile));
 
 	BOOST_FOREACH(const CStack *s, stacks)
 	{

+ 4 - 4
client/CPlayerInterface.cpp

@@ -933,19 +933,19 @@ void CPlayerInterface::showBlockingDialog( const std::string &text, const std::v
 
 }
 
-void CPlayerInterface::tileRevealed(const std::set<int3> &pos)
+void CPlayerInterface::tileRevealed(const boost::unordered_set<int3, ShashInt3> &pos)
 {
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
-	for(std::set<int3>::const_iterator i=pos.begin(); i!=pos.end();i++)
+	for(boost::unordered_set<int3, ShashInt3>::const_iterator i=pos.begin(); i!=pos.end();i++)
 		adventureInt->minimap.showTile(*i);
 	if(pos.size())
 		GH.totalRedraw();
 }
 
-void CPlayerInterface::tileHidden(const std::set<int3> &pos)
+void CPlayerInterface::tileHidden(const boost::unordered_set<int3, ShashInt3> &pos)
 {
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
-	for(std::set<int3>::const_iterator i=pos.begin(); i!=pos.end();i++)
+	for(boost::unordered_set<int3, ShashInt3>::const_iterator i=pos.begin(); i!=pos.end();i++)
 		adventureInt->minimap.hideTile(*i);
 	if(pos.size())
 		GH.totalRedraw();

+ 2 - 2
client/CPlayerInterface.h

@@ -192,8 +192,8 @@ public:
 	void showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor) OVERRIDE;
 	void showTavernWindow(const CGObjectInstance *townOrTavern) OVERRIDE;
 	void advmapSpellCast(const CGHeroInstance * caster, int spellID) OVERRIDE; //called when a hero casts a spell
-	void tileHidden(const std::set<int3> &pos) OVERRIDE; //called when given tiles become hidden under fog of war
-	void tileRevealed(const std::set<int3> &pos) OVERRIDE; //called when fog of war disappears from given tiles
+	void tileHidden(const boost::unordered_set<int3, ShashInt3> &pos) OVERRIDE; //called when given tiles become hidden under fog of war
+	void tileRevealed(const boost::unordered_set<int3, ShashInt3> &pos) OVERRIDE; //called when fog of war disappears from given tiles
 	void newObject(const CGObjectInstance * obj) OVERRIDE;
 	void availableArtifactsChanged(const CGBlackMarket *bm = NULL) OVERRIDE; //bm may be NULL, then artifacts are changed in the global pool (used by merchants in towns)
 	void yourTurn() OVERRIDE;

+ 39 - 41
client/Client.h

@@ -98,32 +98,31 @@ public:
 	int getSelectedHero();
 
 	//not working yet, will be implement somewhen later with support for local-sim-based gameplay
-	void changeSpells(int hid, bool give, const std::set<ui32> &spells){};
-	bool removeObject(int objid){return false;};
-	void setBlockVis(int objid, bool bv){};
-	void setOwner(int objid, ui8 owner){};
-	void setHoverName(int objid, MetaString * name){};
-	void setObjProperty(int objid, int prop, si64 val){};
-	void changePrimSkill(int ID, int which, si64 val, bool abs=false){};
-	void changeSecSkill(int ID, int which, int val, bool abs=false){}; 
-	void showInfoDialog(InfoWindow *iw){};
-	void showBlockingDialog(BlockingDialog *iw, const CFunctionList<void(ui32)> &callback){};
-	ui32 showBlockingDialog(BlockingDialog *iw){return 0;}; //synchronous version of above
-	void showGarrisonDialog(int upobj, int hid, bool removableUnits, const boost::function<void()> &cb){};
-	void showThievesGuildWindow(int requestingObjId){};
-	void giveResource(int player, int which, int val){};
-
-	void giveCreatures (const CArmedInstance * objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) {};
-	void takeCreatures (int objid, TSlots creatures){};
-	void takeCreatures (int objid, std::vector<CStackBasicDescriptor> creatures){};
-	bool changeStackType(const StackLocation &sl, CCreature *c){return false;};
-	bool changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false){return false;};
-	bool insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count){return false;};
+	void changeSpells(int hid, bool give, const std::set<ui32> &spells) OVERRIDE {};
+	bool removeObject(int objid) OVERRIDE {return false;};
+	void setBlockVis(int objid, bool bv) OVERRIDE {};
+	void setOwner(int objid, ui8 owner) OVERRIDE {};
+	void setHoverName(int objid, MetaString * name) OVERRIDE {};
+	void setObjProperty(int objid, int prop, si64 val) OVERRIDE {};
+	void changePrimSkill(int ID, int which, si64 val, bool abs=false) OVERRIDE {};
+	void changeSecSkill(int ID, int which, int val, bool abs=false) OVERRIDE {}; 
+	void showInfoDialog(InfoWindow *iw) OVERRIDE {};
+	void showBlockingDialog(BlockingDialog *iw, const CFunctionList<void(ui32)> &callback) OVERRIDE {};
+	ui32 showBlockingDialog(BlockingDialog *iw) OVERRIDE {return 0;}; //synchronous version of above
+	void showGarrisonDialog(int upobj, int hid, bool removableUnits, const boost::function<void()> &cb) OVERRIDE {};
+	void showThievesGuildWindow(int requestingObjId) OVERRIDE {};
+	void giveResource(int player, int which, int val) OVERRIDE {};
+
+	void giveCreatures (const CArmedInstance * objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) OVERRIDE {};
+	void takeCreatures (int objid, std::vector<CStackBasicDescriptor> creatures) OVERRIDE {};
+	bool changeStackType(const StackLocation &sl, CCreature *c) OVERRIDE {return false;};
+	bool changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false) OVERRIDE {return false;};
+	bool insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count) OVERRIDE {return false;};
 	bool eraseStack(const StackLocation &sl, bool forceRemoval = false){return false;};
-	bool swapStacks(const StackLocation &sl1, const StackLocation &sl2){return false;}
-	bool addToSlot(const StackLocation &sl, const CCreature *c, TQuantity count){return false;}
-	void tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished, bool allowMerging){}
-	bool moveStack(const StackLocation &src, const StackLocation &dst, TQuantity count = -1){return false;}
+	bool swapStacks(const StackLocation &sl1, const StackLocation &sl2) OVERRIDE {return false;}
+	bool addToSlot(const StackLocation &sl, const CCreature *c, TQuantity count) OVERRIDE {return false;}
+	void tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished, bool allowMerging) OVERRIDE {}
+	bool moveStack(const StackLocation &src, const StackLocation &dst, TQuantity count = -1) OVERRIDE {return false;}
 
 	void giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact *artType, int pos) OVERRIDE {};
 	void giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, int pos) OVERRIDE {};
@@ -131,24 +130,23 @@ public:
 	void removeArtifact(const ArtifactLocation &al) OVERRIDE {};
 	void moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) OVERRIDE {};
 
-	void showCompInfo(ShowInInfobox * comp){};
-	void heroVisitCastle(int obj, int heroID){};
-	void stopHeroVisitCastle(int obj, int heroID){};
+	void showCompInfo(ShowInInfobox * comp) OVERRIDE {};
+	void heroVisitCastle(int obj, int heroID) OVERRIDE {};
+	void stopHeroVisitCastle(int obj, int heroID) OVERRIDE {};
 	//void giveHeroArtifact(int artid, int hid, int position){}; 
 	//void giveNewArtifact(int hid, int position){};
-	bool removeArtifact(const CArtifact* art, int hid){return false;};
-	void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, boost::function<void(BattleResult*)> cb = 0, const CGTownInstance *town = NULL){}; //use hero=NULL for no hero
-	void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false){}; //if any of armies is hero, hero will be used
-	void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false){}; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
-	void setAmount(int objid, ui32 val){};
-	bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255){return false;};
-	void giveHeroBonus(GiveBonus * bonus){};
-	void setMovePoints(SetMovePoints * smp){};
-	void setManaPoints(int hid, int val){};
-	void giveHero(int id, int player){};
-	void changeObjPos(int objid, int3 newPos, ui8 flags){};
-	void sendAndApply(CPackForClient * info){};
-	void heroExchange(si32 hero1, si32 hero2){};
+	void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, boost::function<void(BattleResult*)> cb = 0, const CGTownInstance *town = NULL) OVERRIDE {}; //use hero=NULL for no hero
+	void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false) OVERRIDE {}; //if any of armies is hero, hero will be used
+	void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false) OVERRIDE {}; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
+	void setAmount(int objid, ui32 val) OVERRIDE {};
+	bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255) OVERRIDE {return false;};
+	void giveHeroBonus(GiveBonus * bonus) OVERRIDE {};
+	void setMovePoints(SetMovePoints * smp) OVERRIDE {};
+	void setManaPoints(int hid, int val) OVERRIDE {};
+	void giveHero(int id, int player) OVERRIDE {};
+	void changeObjPos(int objid, int3 newPos, ui8 flags) OVERRIDE {};
+	void sendAndApply(CPackForClient * info) OVERRIDE {};
+	void heroExchange(si32 hero1, si32 hero2) OVERRIDE {};
 
 	//////////////////////////////////////////////////////////////////////////
 	friend class CCallback; //handling players actions

+ 1 - 0
global.h

@@ -363,6 +363,7 @@ enum EAlignment
 	#define DLL_EXPORT DLL_F_IMPORT
 #endif
 
+
 template<typename T, size_t N> char (&_ArrayCountObj(const T (&)[N]))[N];  
 #define ARRAY_COUNT(arr)    (sizeof(_ArrayCountObj(arr)))
 

+ 12 - 0
int3.h

@@ -82,6 +82,7 @@ public:
 	{
 		h & x & y & z;
 	}
+	
 };
 inline std::istream & operator>>(std::istream & str, int3 & dest)
 {
@@ -93,4 +94,15 @@ inline std::ostream & operator<<(std::ostream & str, const int3 & sth)
 	return str<<sth.x<<' '<<sth.y<<' '<<sth.z;
 }
 
+struct ShashInt3
+{
+	size_t operator()(int3 const& pos) const
+	{
+		size_t ret = ::boost::hash<int>()(pos.x);
+		boost::hash_combine(ret, pos.y);
+		boost::hash_combine(ret, pos.z);
+		return ret;
+	}
+};
+
 #endif // __INT3_H__

+ 1 - 1
lib/CGameState.cpp

@@ -1335,7 +1335,7 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
 		{
 			if( !vstd::contains(k->second.players, obj->tempOwner)) continue; //not a flagged object
 
-			std::set<int3> tiles;
+			boost::unordered_set<int3, ShashInt3> tiles;
 			obj->getSightTiles(tiles);
 			BOOST_FOREACH(int3 tile, tiles)
 			{

+ 1 - 1
lib/CObjectHandler.cpp

@@ -435,7 +435,7 @@ int CGObjectInstance::getSightRadious() const
 {
 	return 3;
 }
-void CGObjectInstance::getSightTiles(std::set<int3> &tiles) const //returns reference to the set
+void CGObjectInstance::getSightTiles(boost::unordered_set<int3, ShashInt3> &tiles) const //returns reference to the set
 {
 	cb->getTilesInRange(tiles, getSightCenter(), getSightRadious(), tempOwner, 1);
 }

+ 2 - 1
lib/CObjectHandler.h

@@ -13,6 +13,7 @@
 #endif
 #include "../lib/CCreatureSet.h"
 #include "../lib/ConstTransitivePtr.h"
+#include <boost/unordered_set.hpp>
 
 /*
  * CObjectHandler.h, part of VCMI engine
@@ -157,7 +158,7 @@ public:
 	virtual ui8 getPassableness() const; //bitmap - if the bit is set the corresponding player can pass through the visitable tiles of object, even if it's blockvis; if not set - default properties from definfo are used
 	virtual int3 getSightCenter() const; //"center" tile from which the sight distance is calculated
 	virtual int getSightRadious() const; //sight distance (should be used if player-owned structure)
-	void getSightTiles(std::set<int3> &tiles) const; //returns reference to the set
+	void getSightTiles(boost::unordered_set<int3, ShashInt3> &tiles) const; //returns reference to the set
 	int getOwner() const;
 	void setOwner(int ow);
 	int getWidth() const; //returns width of object graphic in tiles

+ 21 - 0
lib/Connection.h

@@ -16,6 +16,7 @@
 #include <boost/type_traits/is_array.hpp>
 #include <boost/type_traits/remove_pointer.hpp>
 #include <boost/type_traits/remove_const.hpp>
+#include <boost/unordered_set.hpp>
 
 #include <boost/mpl/eval_if.hpp>
 #include <boost/mpl/equal_to.hpp>
@@ -520,6 +521,15 @@ public:
 		for(typename std::set<T>::iterator i=d.begin();i!=d.end();i++)
 			*this << *i;
 	}
+	template <typename T, typename U>
+	void saveSerializable(const boost::unordered_set<T, U> &data)
+	{
+		boost::unordered_set<T, U> &d = const_cast<boost::unordered_set<T, U> &>(data);
+		boost::uint32_t length = d.size();
+		*this << length;
+		for(typename boost::unordered_set<T, U>::iterator i=d.begin();i!=d.end();i++)
+			*this << *i;
+	}
 	template <typename T>
 	void saveSerializable(const std::list<T> &data)
 	{
@@ -780,6 +790,17 @@ public:
 			data.insert(ins);
 		}
 	}
+	template <typename T, typename U>
+	void loadSerializable(boost::unordered_set<T, U> &data)
+	{
+		READ_CHECK_U32(length);
+		T ins;
+		for(ui32 i=0;i<length;i++)
+		{
+			*this >> ins;
+			data.insert(ins);
+		}
+	}
 	template <typename T>
 	void loadSerializable(std::list<T> &data)
 	{

+ 2 - 2
lib/IGameCallback.cpp

@@ -96,7 +96,7 @@ int IGameCallback::getHeroCount( int player, bool includeGarrisoned )
 	return ret;
 }
 
-void IGameCallback::getTilesInRange( std::set<int3> &tiles, int3 pos, int radious, int player/*=-1*/, int mode/*=0*/ )
+void IGameCallback::getTilesInRange( boost::unordered_set<int3, ShashInt3> &tiles, int3 pos, int radious, int player/*=-1*/, int mode/*=0*/ )
 {
 	if(player >= PLAYER_LIMIT)
 	{
@@ -126,7 +126,7 @@ void IGameCallback::getTilesInRange( std::set<int3> &tiles, int3 pos, int radiou
 	}
 }
 
-void IGameCallback::getAllTiles (std::set<int3> &tiles, int player/*=-1*/, int level, int surface )
+void IGameCallback::getAllTiles (boost::unordered_set<int3, ShashInt3> &tiles, int player/*=-1*/, int level, int surface )
 {
 	if(player >= PLAYER_LIMIT)
 	{

+ 2 - 2
lib/IGameCallback.h

@@ -60,8 +60,8 @@ public:
 	virtual int getSelectedHero()=0;
 	virtual const PlayerSettings * getPlayerSettings(int color);
 	virtual int getHeroCount(int player, bool includeGarrisoned);
-	virtual void getTilesInRange(std::set<int3> &tiles, int3 pos, int radious, int player=-1, int mode=0);  //mode 1 - only unrevealed tiles; mode 0 - all, mode -1 -  only unrevealed
-	virtual void getAllTiles (std::set<int3> &tiles, int player=-1, int level=-1, int surface=0); //returns all tiles on given level (-1 - both levels, otherwise number of level); surface: 0 - land and water, 1 - only land, 2 - only water
+	virtual void getTilesInRange(boost::unordered_set<int3, ShashInt3> &tiles, int3 pos, int radious, int player=-1, int mode=0);  //mode 1 - only unrevealed tiles; mode 0 - all, mode -1 -  only unrevealed
+	virtual void getAllTiles (boost::unordered_set<int3, ShashInt3> &tiles, int player=-1, int level=-1, int surface=0); //returns all tiles on given level (-1 - both levels, otherwise number of level); surface: 0 - land and water, 1 - only land, 2 - only water
 	virtual void getFreeTiles (std::vector<int3> &tiles); //used for random spawns
 	virtual bool isAllowed(int type, int id); //type: 0 - spell; 1- artifact; 2 - secondary skill
 	virtual ui16 getRandomArt (int flags);

+ 8 - 4
lib/NetPacks.h

@@ -1,5 +1,6 @@
 #ifndef __NETPACKS_H__
 #define __NETPACKS_H__
+#include <boost/unordered_set.hpp>
 #include "../global.h"
 #include "BattleAction.h"
 #include "HeroBonus.h"
@@ -8,6 +9,7 @@
 #include "CMapInfo.h"
 #include "../StartInfo.h"
 #include "ConstTransitivePtr.h"
+#include "../int3.h"
 
 /*
  * NetPacks.h, part of VCMI engine
@@ -330,7 +332,8 @@ struct SetMana : public CPackForClient //110
 	{
 		h & val & hid;
 	}
-}; 
+};
+
 struct SetMovePoints : public CPackForClient //111
 {
 	SetMovePoints(){type = 111;};
@@ -343,14 +346,15 @@ struct SetMovePoints : public CPackForClient //111
 	{
 		h & val & hid;
 	}
-}; 
+};
+
 struct FoWChange : public CPackForClient //112
 {
 	FoWChange(){type = 112;};
 	void applyCl(CClient *cl);
 	DLL_EXPORT void applyGs(CGameState *gs);
 
-	std::set<int3> tiles;
+	boost::unordered_set<int3, struct ShashInt3 > tiles;
 	ui8 player, mode; //mode==0 - hide, mode==1 - reveal
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
@@ -521,7 +525,7 @@ struct TryMoveHero : public CPackForClient //501
 	ui32 id, movePoints;
 	ui8 result; //uses EResult
 	int3 start, end; //h3m format
-	std::set<int3> fowRevealed; //revealed tiles
+	boost::unordered_set<int3, ShashInt3> fowRevealed; //revealed tiles
 	int3 attackedFrom; // Set when stepping into endangered tile.
 
 	bool humanKnows; //used locally during applying to client

+ 1 - 1
lib/NetPacksLib.cpp

@@ -150,7 +150,7 @@ DLL_EXPORT void FoWChange::applyGs( CGameState *gs )
 		team->fogOfWarMap[t.x][t.y][t.z] = mode;
 	if (mode == 0) //do not hide too much
 	{
-		std::set<int3> tilesRevealed;
+		boost::unordered_set<int3, ShashInt3> tilesRevealed;
 		for (size_t i = 0; i < gs->map->objects.size(); i++)
 		{
 			if (gs->map->objects[i])

+ 6 - 1
server/CGameHandler.cpp

@@ -1,4 +1,5 @@
 #include "stdafx.h"
+#include "../int3.h"
 #include "../lib/CCampaignHandler.h"
 #include "../StartInfo.h"
 #include "../lib/CArtHandler.h"
@@ -3405,11 +3406,15 @@ void CGameHandler::playerMessage( ui8 player, const std::string &message )
 		FoWChange fc;
 		fc.mode = 1;
 		fc.player = player;
+		int3 * hlp_tab = new int3[gs->map->width * gs->map->height * (gs->map->twoLevel + 1)];
+		int lastUnc = 0;
 		for(int i=0;i<gs->map->width;i++)
 			for(int j=0;j<gs->map->height;j++)
 				for(int k=0;k<gs->map->twoLevel+1;k++)
 					if(!gs->getPlayerTeam(fc.player)->fogOfWarMap[i][j][k])
-						fc.tiles.insert(int3(i,j,k));
+						hlp_tab[lastUnc++] = int3(i,j,k);
+		fc.tiles.insert(hlp_tab, hlp_tab + lastUnc);
+		delete [] hlp_tab;
 		sendAndApply(&fc);
 	}
 	else if(message == "vcmiglorfindel") //selected hero gains a new level