浏览代码

Proper initialization of the first turn.

Michał W. Urbańczyk 17 年之前
父节点
当前提交
b3c5f19c0d
共有 8 个文件被更改,包括 125 次插入49 次删除
  1. 27 1
      CGameState.cpp
  2. 2 0
      CGameState.h
  3. 19 5
      client/Client.cpp
  4. 7 2
      lib/Connection.cpp
  5. 7 9
      lib/Connection.h
  6. 22 8
      lib/NetPacks.h
  7. 38 24
      server/CGameHandler.cpp
  8. 3 0
      server/CGameHandler.h

+ 27 - 1
CGameState.cpp

@@ -20,7 +20,8 @@
 #include "CLua.h"
 #include "CCallback.h"
 #include "CLuaHandler.h"
-
+#include "lib/NetPacks.h"
+#include <boost/foreach.hpp>
 
 boost::rand48 ran;
 class CMP_stack
@@ -36,6 +37,30 @@ CStack::CStack(CCreature * C, int A, int O, int I, bool AO)
 	:creature(C),amount(A),owner(O), alive(true), position(-1), ID(I), attackerOwned(AO), firstHPleft(C->hitPoints)
 {
 }
+void CGameState::apply(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(NewTurn::Resources h, n->res) //give resources
+			{
+				for(int i=0;i<RESOURCE_QUANTITY;i++)
+					players[h.player].resources[i] = h.resources[i];
+			}
+			if(n->resetBuilded) //reset amount of structures set in this turn in towns
+				BOOST_FOREACH(CGTownInstance* t, map->towns)
+					t->builded = 0;
+		}
+	}
+}
 int CGameState::pickHero(int owner)
 {
 	int h=-1;
@@ -279,6 +304,7 @@ int CGameState::getDate(int mode) const
 }
 void CGameState::init(StartInfo * si, Mapa * map, int Seed)
 {
+	day = 0;
 	seed = Seed;
 	ran.seed((long)seed);
 	scenarioOps = si;

+ 2 - 0
CGameState.h

@@ -23,6 +23,7 @@ struct StartInfo;
 struct SDL_Surface;
 class CMapHandler;
 class CPathfinder;
+struct IPack;
 
 struct DLL_EXPORT PlayerState
 {
@@ -90,6 +91,7 @@ private:
 	}
 
 	void init(StartInfo * si, Mapa * map, int Seed);
+	void apply(IPack * pack);
 	void randomizeObject(CGObjectInstance *cur);
 	std::pair<int,int> pickObject(CGObjectInstance *obj);
 	int pickHero(int owner);

+ 19 - 5
client/Client.cpp

@@ -8,6 +8,7 @@
 #include "../CCallback.h"
 #include "../CPlayerInterface.h"
 #include "../CConsoleHandler.h"
+#include "../lib/NetPacks.h"
 
 CClient::CClient(void)
 {
@@ -74,11 +75,24 @@ void CClient::process(int what)
 	switch (what)
 	{
 	case 100: //one of our interaces has turn
-		ui8 player;
-		*serv >> player;//who?
-		CGI->playerint[gs->players[player].serial]->yourTurn();
-		*serv << ui16(100); //report that we ended turn
-		break;
+		{
+			ui8 player;
+			*serv >> player;//who?
+			std::cout << "It's turn of "<<(unsigned)player<<" player."<<std::endl;
+			CGI->playerint[gs->players[player].serial]->yourTurn();
+			*serv << ui16(100); //report that we ended turn
+			std::cout << "Player "<<(unsigned)player<<" end his turn."<<std::endl;
+			break;
+		}
+	case 101:
+		{
+			NewTurn n;
+			*serv >> n;
+			std::cout << "New day: "<<(unsigned)n.day<<". Applying changes... ";
+			gs->apply(&n);
+			std::cout << "done!"<<std::endl;
+			break;
+		}
 	default:
 		throw std::exception("Not supported server message!");
 		break;

+ 7 - 2
lib/Connection.cpp

@@ -2,6 +2,7 @@
 #pragma warning(disable:4355)
 #include "Connection.h"
 #include <boost/asio.hpp>
+#include <boost/thread.hpp>
 using namespace boost;
 using namespace boost::asio::ip;
 
@@ -31,6 +32,8 @@ void CConnection::init()
 	(*this) << std::string("Aiya!\n") << name << myEndianess; //identify ourselves
 	(*this) >> pom >> pom >> contactEndianess;
 	out << "Established connection with "<<pom<<std::endl;
+	wmx = new boost::mutex;
+	rmx = new boost::mutex;
 }
 
 CConnection::CConnection(std::string host, std::string port, std::string Name, std::ostream & Out)
@@ -63,14 +66,14 @@ CConnection::CConnection(boost::asio::basic_socket_acceptor<boost::asio::ip::tcp
 }
 int CConnection::write(const void * data, unsigned size)
 {
-	LOG("wysylam dane o rozmiarze " << size << std::endl);
+	LOG("Sending " << size << " byte(s) of data" <<std::endl);
 	int ret;
 	ret = asio::write(*socket,asio::const_buffers_1(asio::const_buffer(data,size)));
 	return ret;
 }
 int CConnection::read(void * data, unsigned size)
 {
-	LOG("odbieram dane o rozmiarze " << size << std::endl);
+	LOG("Receiving " << size << " byte(s) of data" <<std::endl);
 	int ret = asio::read(*socket,asio::mutable_buffers_1(asio::mutable_buffer(data,size)));
 	return ret;
 }
@@ -80,4 +83,6 @@ CConnection::~CConnection(void)
 		socket->close();
 	delete socket;
 	delete io_service;
+	delete wmx;
+	delete rmx;
 }

+ 7 - 9
lib/Connection.h

@@ -60,7 +60,7 @@ struct SerializationLevel
 		//else
 		typename mpl::eval_if<
 			boost::is_array<T>,
-			mpl::int_<Wrong>,
+			mpl::int_<Primitive>,
 		//else
 		typename mpl::eval_if<
 			boost::is_enum<T>,
@@ -91,7 +91,7 @@ public:
 	}
 	
 	template<class T>
-	Serializer & operator&(T & t){
+	COSer & operator&(T & t){
 		return * this->This() << t;
 	}
 };
@@ -112,7 +112,7 @@ public:
 	}
 	
 	template<class T>
-	Serializer & operator&(T & t){
+	CISer & operator&(T & t){
 		return * this->This() >> t;
 	}
 };
@@ -176,7 +176,7 @@ class DLL_EXPORT CConnection
 	std::ostream &out;
 	CConnection(void);
 	void init();
-	boost::mutex *mx;
+	boost::mutex *rmx, *wmx; // read/write mutexes
 public:
 
 	template <typename T>
@@ -234,9 +234,10 @@ public:
 	template <typename T>
 	void saveSerializable(const std::set<T> &data)
 	{
-		boost::uint32_t length = data.size();
+		std::set<T> &d = const_cast<std::set<T> &>(data);
+		boost::uint32_t length = d.size();
 		*this << length;
-		for(std::set<T>::iterator i=data.begin();i!=data.end();i++)
+		for(std::set<T>::iterator i=d.begin();i!=d.end();i++)
 			*this << *i;
 	}
 	template <typename T>
@@ -244,7 +245,6 @@ public:
 	{
 		boost::uint32_t length;
 		*this >> length;
-		data.resize(length);
 		T ins;
 		for(ui32 i=0;i<length;i++)
 		{
@@ -287,8 +287,6 @@ public:
 		typex::invoke(*this, data);
 	}
 
-	//CSender send;
-	//CReceiver rec;
 	boost::asio::basic_stream_socket < boost::asio::ip::tcp , boost::asio::stream_socket_service<boost::asio::ip::tcp>  > * socket;
 	bool logging;
 	bool connected;

+ 22 - 8
lib/NetPacks.h

@@ -1,14 +1,25 @@
 #include "../global.h"
-
-struct NewTurn
+struct IPack
+{
+	virtual ui16 getType()=0;
+};
+template <typename T> struct CPack
+	:public IPack
+{
+	ui16 type; 
+	ui16 getType(){return type;}
+	T* This(){return static_cast<T*>(this);};
+};
+struct NewTurn : public CPack<NewTurn> //101
 {
 	struct Hero
 	{
 		ui32 id, move, mana; //id is a general serial id
 		template <typename Handler> void serialize(Handler &h, const int version)
 		{
-			h -= id -= move -= mana;
+			h & id & move & mana;
 		}
+		bool operator<(const Hero&h)const{return id < h.id;}
 	};
 	struct Resources
 	{
@@ -16,17 +27,20 @@ struct NewTurn
 		si32 resources[RESOURCE_QUANTITY];
 		template <typename Handler> void serialize(Handler &h, const int version)
 		{
-			h -= resources;
+			h & player & resources;
 		}
+		bool operator<(const Resources&h)const{return player < h.player;}
 	};
 
-	std::set<Hero> heroes;
-	std::set<Resources> res;
-
+	std::set<Hero> heroes; //updates movement and mana points
+	std::set<Resources> res;//resource list
+	ui32 day;
+	bool resetBuilded;
 
+	NewTurn(){type = 101;};
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h += heroes += res;
+		h & heroes & res & day & resetBuilded;
 	}
 }; 

+ 38 - 24
server/CGameHandler.cpp

@@ -38,7 +38,11 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
 		}
 	}
 }
-
+template <typename T>void CGameHandler::sendToAllClients(CPack<T> * info)
+{
+	BOOST_FOREACH(CConnection* c, conns)
+		*c << info->getType() << *info->This();
+}
 CGameHandler::CGameHandler(void)
 {
 	gs = NULL;
@@ -76,37 +80,46 @@ int valMovePoints(CGHeroInstance * chi)
 }
 void CGameHandler::newTurn()
 {
-	//std::map<int, PlayerState>::iterator i = gs->players.begin() ;
-	gs->day++;
+	NewTurn n;
+	n.day = gs->day + 1;
+
 	for ( std::map<ui8, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
 	{
-		//handle heroes/////////////////////////////
-		for (unsigned j=0;j<(*i).second.heroes.size();j++)
+		if(i->first>=PLAYER_LIMIT) continue;
+		NewTurn::Resources r;
+		r.player = i->first;
+		for(int j=0;j<RESOURCE_QUANTITY;j++)
+			r.resources[j] = i->second.resources[j];
+		
+		for (unsigned j=0;j<(*i).second.heroes.size();j++) //handle heroes
 		{
-			(*i).second.heroes[j]->movement = valMovePoints((*i).second.heroes[j]);
+			NewTurn::Hero h;
+			h.id = (*i).second.heroes[j]->id;
+			h.move = valMovePoints((*i).second.heroes[j]);
+			h.mana = (*i).second.heroes[j]->mana;
+			n.heroes.insert(h);
 		}
-
-
-		//handle towns/////////////////////////////
-		for(unsigned j=0;j<i->second.towns.size();j++)
+		for(unsigned j=0;j<i->second.towns.size();j++)//handle towns
 		{
 			i->second.towns[j]->builded=0;
-			if(gs->getDate(1)==1) //first day of week
-			{
-				for(int k=0;k<CREATURES_PER_TOWN;k++) //creature growths
-				{
-					if(i->second.towns[j]->creatureDwelling(k))//there is dwelling (k-level)
-						i->second.towns[j]->strInfo.creatures[k]+=i->second.towns[j]->creatureGrowth(k);
-				}
-			}
-			if((gs->day>1) && i->first<PLAYER_LIMIT)
-				i->second.resources[6]+=i->second.towns[j]->dailyIncome();
+			//if(gs->getDate(1)==1) //first day of week
+			//{
+			//	for(int k=0;k<CREATURES_PER_TOWN;k++) //creature growths
+			//	{
+			//		if(i->second.towns[j]->creatureDwelling(k))//there is dwelling (k-level)
+			//			i->second.towns[j]->strInfo.creatures[k]+=i->second.towns[j]->creatureGrowth(k);
+			//	}
+			//}
+			if((gs->day>1) && i->first<PLAYER_LIMIT)//not the first day and town not neutral
+				r.resources[6] += i->second.towns[j]->dailyIncome();
 		}
+		n.res.insert(r);
 	}	
-	for (std::set<CCPPObjectScript *>::iterator i=gs->cppscripts.begin();i!=gs->cppscripts.end();i++)
-	{
-		(*i)->newTurn();
-	}
+	sendToAllClients(&n);
+	//for (std::set<CCPPObjectScript *>::iterator i=gs->cppscripts.begin();i!=gs->cppscripts.end();i++)
+	//{
+	//	(*i)->newTurn();
+	//}
 }
 void CGameHandler::run()
 {	
@@ -136,6 +149,7 @@ void CGameHandler::run()
 	}
 	while (1)
 	{
+		newTurn();
 		for(std::map<ui8,PlayerState>::iterator i = gs->players.begin(); i != gs->players.end(); i++)
 		{
 			if((i->second.towns.size()==0 && i->second.heroes.size()==0)  || i->second.color<0) continue; //players has not towns/castle - loser

+ 3 - 0
server/CGameHandler.h

@@ -5,6 +5,8 @@ class CVCMIServer;
 class CGameState;
 class CConnection;
 struct StartInfo;
+template <typename T> struct CPack;
+
 class CGameHandler
 {
 	CGameState *gs;
@@ -16,6 +18,7 @@ public:
 	~CGameHandler(void);
 	void init(StartInfo *si, int Seed);
 	void handleConnection(std::set<int> players, CConnection &c);
+	template <typename T>void sendToAllClients(CPack<T> * info);
 	void run();
 	void newTurn();