From 358ab062ebbbbf8abe71af885c80a5b21f618302 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20W=2E=20Urba=C5=84czyk?= Date: Wed, 9 Jul 2008 17:22:28 +0000 Subject: [PATCH] Base for netcode --- CAdvmapInterface.cpp | 2 +- CGameState.h | 1 + CMT.cpp | 79 +++++++++++++---------- CPreGame.cpp | Bin 129722 -> 129816 bytes StartInfo.h | 37 ++++++++--- global.h | 13 +++- lib/Connection.cpp | 46 ++++++++------ lib/Connection.h | 126 +++++++++++++++++++++++++++++++++++-- server/VCMI_server.vcproj | 7 ++- server/server_main.cpp | 129 +++++++++++++++++++++++++++++++------- 10 files changed, 345 insertions(+), 95 deletions(-) diff --git a/CAdvmapInterface.cpp b/CAdvmapInterface.cpp index 4e708bd3b..9486af337 100644 --- a/CAdvmapInterface.cpp +++ b/CAdvmapInterface.cpp @@ -119,7 +119,7 @@ void CMinimap::draw() } } } - blitAt(FoW[LOCPLINT->adventureInt->position.z],0,0,temps); + //blitAt(FoW[LOCPLINT->adventureInt->position.z],0,0,temps); //draw radar int bx = (((float)LOCPLINT->adventureInt->position.x)/(((float)CGI->mh->sizes.x)))*pos.w, diff --git a/CGameState.h b/CGameState.h index 14f5dd982..c62181219 100644 --- a/CGameState.h +++ b/CGameState.h @@ -106,6 +106,7 @@ public: friend CScriptCallback; friend void handleCPPObjS(std::map * mapa, CCPPObjectScript * script); friend class CMapHandler; + friend class CVCMIServer; }; #endif //CGAMESTATE_H diff --git a/CMT.cpp b/CMT.cpp index db4b48dd8..7cfefd511 100644 --- a/CMT.cpp +++ b/CMT.cpp @@ -1,7 +1,6 @@ // CMT.cpp : Defines the entry point for the console application. // #include "stdafx.h" -#include "SDL.h" #include "SDL_TTF.h" #include "hch/CVideoHandler.h" #include "SDL_mixer.h" @@ -44,6 +43,7 @@ #include "client/Graphics.h" #include #include "lib/Connection.h" +#include std::string NAME = NAME_VER + std::string(" (client)"); DLL_EXPORT void initDLL(CLodHandler *b); SDL_Surface * screen, * screen2; @@ -62,9 +62,6 @@ int _tmain(int argc, _TCHAR* argv[]) { //boost::thread servthr(boost::bind(system,"VCMI_server.exe")); //runs server executable; //TODO: add versions for other platforms - CConnection c("localhost","3030",NAME,std::cout); - int r; - c >> r; std::cout << NAME << std::endl; srand ( time(NULL) ); @@ -150,7 +147,7 @@ int _tmain(int argc, _TCHAR* argv[]) THC std::cout<<"Initialization of VCMI (togeter): "<mush = mush; StartInfo *options = new StartInfo(cpg->runLoop()); - +/////////////////////////////////////////////////////////////////////////////////////// cgi->dobjinfo = new CDefObjInfoHandler; cgi->dobjinfo->load(); THC std::cout<<"\tDef information handler: "<consoleh->runConsole(); THC std::cout<<"\tCallback and console: "<ourScenSel->mapsel.ourMaps[cpg->ourScenSel->mapsel.selected].filename; std::cout<<"Opening map file: "<> pom8; + if(pom8) throw "Server cannot open the map!"; + c < *options; + c << ui8(options->playerInfos.size()); + for(int i=0;iplayerInfos.size();i++) + c << ui8(options->playerInfos[i].color); + boost::crc_32_type result; + result.process_bytes(initTable,mapstr.size()); + std::cout << "\tMap checksum: "<state->init(options,mapa,8); CMapHandler * mh = cgi->mh = new CMapHandler(); @@ -236,36 +251,36 @@ int _tmain(int argc, _TCHAR* argv[]) } ///claculating FoWs for minimap /****************************Minimaps' FoW******************************************/ - for(int g=0; gplayerint.size(); ++g) - { - if(!cgi->playerint[g]->human) - continue; - CMinimap & mm = ((CPlayerInterface*)cgi->playerint[g])->adventureInt->minimap; + //for(int g=0; gplayerint.size(); ++g) + //{ + // if(!cgi->playerint[g]->human) + // continue; + // CMinimap & mm = ((CPlayerInterface*)cgi->playerint[g])->adventureInt->minimap; - int mw = mm.map[0]->w, mh = mm.map[0]->h, - wo = mw/CGI->mh->sizes.x, ho = mh/CGI->mh->sizes.y; + // int mw = mm.map[0]->w, mh = mm.map[0]->h, + // wo = mw/CGI->mh->sizes.x, ho = mh/CGI->mh->sizes.y; - for(int d=0; dmh->map->twoLevel+1; ++d) - { - SDL_Surface * pt = CSDL_Ext::newSurface(mm.pos.w, mm.pos.h, CSDL_Ext::std32bppSurface); + // for(int d=0; dmh->map->twoLevel+1; ++d) + // { + // SDL_Surface * pt = CSDL_Ext::newSurface(mm.pos.w, mm.pos.h, CSDL_Ext::std32bppSurface); - for (int i=0; imh->sizes.x)/mw), ((j*CGI->mh->sizes.y)/mh), d ); + // for (int i=0; imh->sizes.x)/mw), ((j*CGI->mh->sizes.y)/mh), d ); - if ( !((CPlayerInterface*)cgi->playerint[g])->cb->isVisible(pp) ) - { - CSDL_Ext::SDL_PutPixelWithoutRefresh(pt,i,j,0,0,0); - } - } - } - CSDL_Ext::update(pt); - mm.FoW.push_back(pt); - } + // if ( !((CPlayerInterface*)cgi->playerint[g])->cb->isVisible(pp) ) + // { + // CSDL_Ext::SDL_PutPixelWithoutRefresh(pt,i,j,0,0,0); + // } + // } + // } + // CSDL_Ext::update(pt); + // mm.FoW.push_back(pt); + // } - } + //} while(1) //main game loop, one execution per turn { diff --git a/CPreGame.cpp b/CPreGame.cpp index afad3fd17ee050570477b834108e49712dc97fa0..a3c904c31753eca114269c40320eaeeadf2dd70f 100644 GIT binary patch delta 62 zcmdn>m3_uH_6!0Tp8a delta 27 jcmbR7jeXZw_6 void serialize(Handler &h, const int version) + { + h && castle; + h && hero; + h && heroPortrait; + h && heroName; + h && bonus; + h && color; + h && serial; + h && handicap; + h && name; + h && human; + } }; - int difficulty; //0=easy; 4=impossible + si32 difficulty; //0=easy; 4=impossible std::vector playerInfos; - int turnTime; //in minutes, 0=unlimited + ui8 turnTime; //in minutes, 0=unlimited + std::string mapname; PlayerSettings & getIthPlayersSettings(int no) { - for(int i=0; i void serialize(Handler &h, const int version) + { + h && difficulty; + h & playerInfos; + h && turnTime; + h && mapname; + } }; #endif \ No newline at end of file diff --git a/global.h b/global.h index 8fa7d111a..0634bbd50 100644 --- a/global.h +++ b/global.h @@ -1,11 +1,18 @@ #ifndef GLOBAL_H #define GLOBAL_H +#include +#include +#include +typedef boost::uint32_t ui32; //unsigned int 32 bits (4 bytes) +typedef boost::uint16_t ui16; //unsigned int 16 bits (2 bytes) +typedef boost::uint8_t ui8; //unsigned int 8 bits (1 byte) +typedef boost::int32_t si32; //signed int 32 bits (4 bytes) +typedef boost::int16_t si16; //signed int 16 bits (2 bytes) +typedef boost::int8_t si8; //signed int 8 bits (1 byte) +#include "int3.h" #define CHECKTIME 1 #if CHECKTIME #include "timeHandler.h" -#include -#include -#include "int3.h" #define THC #endif diff --git a/lib/Connection.cpp b/lib/Connection.cpp index b79557d11..6ae1d2c52 100644 --- a/lib/Connection.cpp +++ b/lib/Connection.cpp @@ -1,4 +1,5 @@ #define VCMI_DLL +#pragma warning(disable:4355) #include "Connection.h" #include using namespace boost; @@ -17,41 +18,48 @@ using namespace boost::asio::ip; #define LIL_ENDIAN #endif - -CConnection::CConnection(std::string host, std::string port, std::string Name, std::ostream & Out) -:io_service(new asio::io_service), name(Name), out(Out) +void CConnection::init() { #ifdef LIL_ENDIAN myEndianess = true; #else myEndianess = false; #endif + connected = true; + std::string pom; + //we got connection + (*this) << std::string("Aiya!\n") << name << myEndianess; //identify ourselves + (*this) >> pom >> pom >> contactEndianess; + out << "Established connection with "<connect(*endpoint_iterator, error); - if(error) - { - connected = false; - return; - } - std::string pom; - //we got connection - (*this) << std::string("Aiya!\n") << name << myEndianess; //identify ourselves - (*this) >> pom >> pom >> contactEndianess; + if (error){ delete socket; throw "Can't establish connection :("; } + init(); } CConnection::CConnection( boost::asio::basic_stream_socket > * Socket, - boost::asio::io_service *Io_service, std::string Name, std::ostream & Out ) -:socket(Socket),io_service(Io_service), out(Out), name(Name) + :socket(Socket),io_service(Socket->io_service()), out(Out), name(Name), send(this), rec(this) { - std::string pom; - //we start with just connected socket - (*this) << std::string("Aiya!\n") << name << myEndianess; //identify ourselves - (*this) >> pom >> pom >> contactEndianess; + init(); +} +CConnection::CConnection(boost::asio::basic_socket_acceptor > * acceptor, boost::asio::io_service *Io_service, std::string Name, std::ostream & Out) +: out(Out), name(Name), send(this), rec(this) +{ + system::error_code error = asio::error::host_not_found; + socket = new tcp::socket(*io_service); + acceptor->accept(*socket,error); + if (error){ delete socket; throw "Can't establish connection :("; } + init(); } int CConnection::write(const void * data, unsigned size) { @@ -68,5 +76,7 @@ int CConnection::read(void * data, unsigned size) CConnection::~CConnection(void) { delete io_service; + if(socket) + socket->close(); delete socket; } diff --git a/lib/Connection.h b/lib/Connection.h index 9e262ca6a..0a1a4f68b 100644 --- a/lib/Connection.h +++ b/lib/Connection.h @@ -1,7 +1,11 @@ #pragma once #include "../global.h" -#include #include +#include +#include +const int version = 63; +class CConnection; + namespace boost { namespace asio @@ -13,17 +17,55 @@ namespace boost class io_service; template class stream_socket_service; - template + template class basic_stream_socket; + + template class socket_acceptor_service; + template + class basic_socket_acceptor; } }; +class CSender +{ +public: + CConnection* c; + CSender(CConnection* C):c(C){}; + template CSender & operator&&(T &data) //send built-in type + { + *c << data; + return *this; + } + template CSender & operator&(T &data) //send serializable type + { + *c < data; + return *this; + } +}; +class CReceiver +{ +public: + CConnection *c; + CReceiver(CConnection* C):c(C){}; + template CReceiver & operator&&(T &data) //get built-in type + { + *c >> data; + return *this; + } + template CReceiver & operator&(T &data) //get serializable type + { + *c > data; + return *this; + } +}; class DLL_EXPORT CConnection { std::ostream &out; CConnection(void); + void init(); public: + CSender send; + CReceiver rec; boost::asio::basic_stream_socket < boost::asio::ip::tcp , boost::asio::stream_socket_service > * socket; bool logging; bool connected; @@ -31,8 +73,14 @@ public: boost::asio::io_service *io_service; std::string name; //who uses this connection - CConnection(std::string host, std::string port, std::string Name, std::ostream & Out); - CConnection(boost::asio::basic_stream_socket < boost::asio::ip::tcp , boost::asio::stream_socket_service > * Socket, boost::asio::io_service *Io_service, std::string Name, std::ostream & Out); //use immediately after accepting connection into socket + CConnection + (std::string host, std::string port, std::string Name, std::ostream & Out); + CConnection + (boost::asio::basic_socket_acceptor > * acceptor, + boost::asio::io_service *Io_service, std::string Name, std::ostream & Out); + CConnection + (boost::asio::basic_stream_socket < boost::asio::ip::tcp , boost::asio::stream_socket_service > * Socket, + std::string Name, std::ostream & Out); //use immediately after accepting connection into socket int write(const void * data, unsigned size); int read(void * data, unsigned size); int readLine(void * data, unsigned maxSize); @@ -53,7 +101,7 @@ CConnection & operator>>(CConnection &c, std::string &data) { boost::uint32_t length; c >> length; - data.reserve(length); + data.resize(length); c.read((void*)data.c_str(),length); return c; } @@ -68,10 +116,49 @@ CConnection & operator>>(CConnection &c, char * &data) { boost::uint32_t length; c >> length; + std::cout <<"Alokujemy " < CConnection & operator<<(CConnection &c, std::vector &data) +{ + boost::uint32_t length = data.size(); + c << length; + for(ui32 i=0;i CConnection & operator>>(CConnection &c, std::vector &data) +{ + boost::uint32_t length; + c >> length; + data.resize(length); + for(ui32 i=0;i> data[i]; + return c; +} +//template CConnection & operator<<(CConnection &c, std::set &data) +//{ +// boost::uint32_t length = data.size(); +// c << length; +// for(std::set::iterator i=data.begin();i!=data.end();i++) +// c << *i; +// return c; +//} +//template CConnection & operator>>(CConnection &c, std::set &data) +//{ +// boost::uint32_t length; +// c >> length; +// data.resize(length); +// T pom; +// for(int i=0;i> pom; +// data.insert(pom); +// } +// return c; +//} template CConnection & operator<<(CConnection &c, const T &data) { c.write(&data,sizeof(data)); @@ -81,4 +168,31 @@ template CConnection & operator>>(CConnection &c, T &data) { c.read(&data,sizeof(data)); return c; +} +template CConnection & operator<(CConnection &c, std::vector &data) +{ + boost::uint32_t length = data.size(); + c << length; + for(ui32 i=0;i CConnection & operator>(CConnection &c, std::vector &data) +{ + boost::uint32_t length; + c >> length; + data.resize(length); + for(ui32 i=0;i CConnection & operator<(CConnection &c, T &data) +{ + data.serialize(c.send,version); + return c; +} +template CConnection & operator>(CConnection &c, T &data) +{ + data.serialize(c.rec,version); + return c; } \ No newline at end of file diff --git a/server/VCMI_server.vcproj b/server/VCMI_server.vcproj index f05aa6e97..616074d21 100644 --- a/server/VCMI_server.vcproj +++ b/server/VCMI_server.vcproj @@ -20,7 +20,7 @@ OutputDirectory="$(SolutionDir)" IntermediateDirectory="$(ConfigurationName)" ConfigurationType="1" - CharacterSet="2" + CharacterSet="1" > #include "../global.h" #include "../lib/Connection.h" +#include "../CGameState.h" +#include "zlib.h" +#include +#include +#include +#include "../StartInfo.h" std::string NAME = NAME_VER + std::string(" (server)"); using boost::asio::ip::tcp; using namespace boost; using namespace boost::asio; using namespace boost::asio::ip; - +mutex smx1; class CVCMIServer { + CGameState *gs; tcp::acceptor acceptor; - std::vector connections; + std::map connections; + std::set conns; + ui32 seed; public: CVCMIServer(io_service& io_service) : acceptor(io_service, tcp::endpoint(tcp::v4(), 3030)) { - start_accept(); + start(); } -private: - void start_accept() + void setUpConnection(CConnection *c, std::string mapname, si32 checksum) + { + ui8 quantity, pom; + (*c) << mapname << checksum << seed; + (*c) >> quantity; + for(int i=0;i> pom; + smx1.lock(); + connections[pom] = c; + conns.insert(c); + smx1.unlock(); + } + } + void newGame(CConnection &c) { boost::system::error_code error; - std::cout<<"Listening for connections at port " << acceptor.local_endpoint().port() << std::endl; - tcp::socket s(acceptor.io_service()); - acceptor.accept(s,error); - if (!error) + StartInfo *si = new StartInfo; + ui8 clients; + std::string mapname; + c >> clients; + c >> mapname; + //getting map + gzFile map = gzopen(mapname.c_str(),"rb"); + if(!map){ c << int8_t(1); return; } + std::vector mapstr; int pom; + while((pom=gzgetc(map))>=0) { - CConnection *connection = new CConnection(&s,&s.io_service(),NAME,std::cout); - std::cout<<"Got connection!" << std::endl; + mapstr.push_back(pom); } - else + gzclose(map); + //map is decompressed + c << int8_t(0); //OK! + gs = new CGameState(); + gs->scenarioOps = si; + c > *si; //get start options + boost::crc_32_type result; + result.process_bytes(&(*mapstr.begin()),mapstr.size()); + int checksum = result.checksum(); + std::cout << "Checksum:" << checksum << std::endl; + CConnection* cc; tcp::socket * ss; + for(int i=0; i> mode; + switch (mode) + { + case 0: + connection.socket->close(); + exit(0); + break; + case 1: + connection.socket->close(); + return; + break; + case 2: + newGame(connection); + break; + } } - - //asio::write(s,asio::buffer("570")); - //new_connection->witaj(); - //acceptor.async_accept(s, - // boost::bind(&CVCMIServer::gotConnection, this, &s, - // placeholders::error)); } - - void gotConnection(tcp::socket *s,const boost::system::error_code& error) - { - } - }; -int main() +int _tmain(int argc, _TCHAR* argv[]) { try { io_service io_service; CVCMIServer server(io_service); + while(1) + server.start(); io_service.run(); } catch (std::exception& e)