1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

Base for netcode

This commit is contained in:
Michał W. Urbańczyk 2008-07-09 17:22:28 +00:00
parent 9422b0d9ca
commit 358ab062eb
10 changed files with 345 additions and 95 deletions

View File

@ -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,

View File

@ -106,6 +106,7 @@ public:
friend CScriptCallback;
friend void handleCPPObjS(std::map<int,CCPPObjectScript*> * mapa, CCPPObjectScript * script);
friend class CMapHandler;
friend class CVCMIServer;
};
#endif //CGAMESTATE_H

79
CMT.cpp
View File

@ -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 <boost/thread.hpp>
#include "lib/Connection.h"
#include <boost/crc.hpp>
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): "<<total.getDif()<<std::endl;
cpg->mush = mush;
StartInfo *options = new StartInfo(cpg->runLoop());
///////////////////////////////////////////////////////////////////////////////////////
cgi->dobjinfo = new CDefObjInfoHandler;
cgi->dobjinfo->load();
THC std::cout<<"\tDef information handler: "<<pomtime.getDif()<<std::endl;
@ -192,7 +189,9 @@ int _tmain(int argc, _TCHAR* argv[])
cgi->consoleh->runConsole();
THC std::cout<<"\tCallback and console: "<<pomtime.getDif()<<std::endl;
THC std::cout<<"Handlers initialization (together): "<<tmh.getDif()<<std::endl;
//////////////////////////////////loading map and connecting
CConnection c("localhost","3030",NAME,std::cout);
THC std::cout<<"\tConnecting to the server: "<<tmh.getDif()<<std::endl;
std::string mapname = cpg->ourScenSel->mapsel.ourMaps[cpg->ourScenSel->mapsel.selected].filename;
std::cout<<"Opening map file: "<<mapname<<"\t\t"<<std::flush;
gzFile map = gzopen(mapname.c_str(),"rb");
@ -208,9 +207,25 @@ int _tmain(int argc, _TCHAR* argv[])
initTable[ss] = mapstr[ss];
}
std::cout<<"done."<<std::endl;
////////////////////////////////////////////////////
ui8 pom8;
c << uint8_t(2) << uint8_t(1) << mapname;
c >> pom8;
if(pom8) throw "Server cannot open the map!";
c < *options;
c << ui8(options->playerInfos.size());
for(int i=0;i<options->playerInfos.size();i++)
c << ui8(options->playerInfos[i].color);
boost::crc_32_type result;
result.process_bytes(initTable,mapstr.size());
std::cout << "\tMap checksum: "<<result.checksum();
std::cout << "\t" << sizeof(result.checksum());
THC std::cout<<"\tSending info to the server: "<<tmh.getDif()<<std::endl;
Mapa * mapa = new Mapa(initTable);
THC std::cout<<"Reading and detecting map file (together): "<<tmh.getDif()<<std::endl;
THC std::cout<<"Reading and detecting map file (together): "<<tmh.getDif()<<std::endl;
cgi->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; g<cgi->playerint.size(); ++g)
{
if(!cgi->playerint[g]->human)
continue;
CMinimap & mm = ((CPlayerInterface*)cgi->playerint[g])->adventureInt->minimap;
//for(int g=0; g<cgi->playerint.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; d<cgi->mh->map->twoLevel+1; ++d)
{
SDL_Surface * pt = CSDL_Ext::newSurface(mm.pos.w, mm.pos.h, CSDL_Ext::std32bppSurface);
// for(int d=0; d<cgi->mh->map->twoLevel+1; ++d)
// {
// SDL_Surface * pt = CSDL_Ext::newSurface(mm.pos.w, mm.pos.h, CSDL_Ext::std32bppSurface);
for (int i=0; i<mw; i++)
{
for (int j=0; j<mh; j++)
{
int3 pp( ((i*CGI->mh->sizes.x)/mw), ((j*CGI->mh->sizes.y)/mh), d );
// for (int i=0; i<mw; i++)
// {
// for (int j=0; j<mh; j++)
// {
// int3 pp( ((i*CGI->mh->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
{

Binary file not shown.

View File

@ -10,26 +10,47 @@ struct StartInfo
{
struct PlayerSettings
{
int castle, hero, //ID, if -1 then random, if -2 then none
si32 castle, hero, //ID, if -1 then random, if -2 then none
heroPortrait; //-1 if default, else ID
std::string heroName;
Ebonus bonus;
Ecolor color; //from 0 -
int serial;
int handicap;//0-no, 1-mild, 2-severe
si8 bonus; //usees enum type Ebonus
ui8 color; //from 0 -
ui8 serial;
ui8 handicap;//0-no, 1-mild, 2-severe
std::string name;
bool human;
template <typename Handler> 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<PlayerSettings> 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<playerInfos.size(); ++i)
for(unsigned int i=0; i<playerInfos.size(); ++i)
if(playerInfos[i].color == no)
return playerInfos[i];
throw new std::exception("Cannot find info about player");
}
template <typename Handler> void serialize(Handler &h, const int version)
{
h && difficulty;
h & playerInfos;
h && turnTime;
h && mapname;
}
};
#endif

View File

@ -1,11 +1,18 @@
#ifndef GLOBAL_H
#define GLOBAL_H
#include <iostream>
#include <boost/logic/tribool.hpp>
#include <boost/cstdint.hpp>
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 <boost/logic/tribool.hpp>
#include <iostream>
#include "int3.h"
#define THC
#endif

View File

@ -1,4 +1,5 @@
#define VCMI_DLL
#pragma warning(disable:4355)
#include "Connection.h"
#include <boost/asio.hpp>
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 "<<pom<<std::endl;
}
CConnection::CConnection(std::string host, std::string port, std::string Name, std::ostream & Out)
:io_service(new asio::io_service), name(Name), out(Out), send(this), rec(this)
{
system::error_code error = asio::error::host_not_found;
socket = new tcp::socket(*io_service);
tcp::resolver resolver(*io_service);
tcp::resolver::iterator endpoint_iterator = resolver.resolve(tcp::resolver::query(host,port));
socket->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<boost::asio::ip::tcp , boost::asio::stream_socket_service<boost::asio::ip::tcp> > * 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<boost::asio::ip::tcp, boost::asio::socket_acceptor_service<boost::asio::ip::tcp> > * 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;
}

View File

@ -1,7 +1,11 @@
#pragma once
#include "../global.h"
#include <boost/cstdint.hpp>
#include <string>
#include <vector>
#include <set>
const int version = 63;
class CConnection;
namespace boost
{
namespace asio
@ -13,17 +17,55 @@ namespace boost
class io_service;
template <typename Protocol> class stream_socket_service;
template <typename Protocol,
typename StreamSocketService>
template <typename Protocol,typename StreamSocketService>
class basic_stream_socket;
template <typename Protocol> class socket_acceptor_service;
template <typename Protocol,typename SocketAcceptorService>
class basic_socket_acceptor;
}
};
class CSender
{
public:
CConnection* c;
CSender(CConnection* C):c(C){};
template <typename T> CSender & operator&&(T &data) //send built-in type
{
*c << data;
return *this;
}
template <typename T> CSender & operator&(T &data) //send serializable type
{
*c < data;
return *this;
}
};
class CReceiver
{
public:
CConnection *c;
CReceiver(CConnection* C):c(C){};
template <typename T> CReceiver & operator&&(T &data) //get built-in type
{
*c >> data;
return *this;
}
template <typename T> 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<boost::asio::ip::tcp> > * 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<boost::asio::ip::tcp> > * 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<boost::asio::ip::tcp, boost::asio::socket_acceptor_service<boost::asio::ip::tcp> > * 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<boost::asio::ip::tcp> > * 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 " <<length << " bajtow."<<std::endl;
data = new char[length];
c.read(data,length);
return c;
}
template <typename T> CConnection & operator<<(CConnection &c, std::vector<T> &data)
{
boost::uint32_t length = data.size();
c << length;
for(ui32 i=0;i<length;i++)
c << data[i];
return c;
}
template <typename T> CConnection & operator>>(CConnection &c, std::vector<T> &data)
{
boost::uint32_t length;
c >> length;
data.resize(length);
for(ui32 i=0;i<length;i++)
c >> data[i];
return c;
}
//template <typename T> CConnection & operator<<(CConnection &c, std::set<T> &data)
//{
// boost::uint32_t length = data.size();
// c << length;
// for(std::set<T>::iterator i=data.begin();i!=data.end();i++)
// c << *i;
// return c;
//}
//template <typename T> CConnection & operator>>(CConnection &c, std::set<T> &data)
//{
// boost::uint32_t length;
// c >> length;
// data.resize(length);
// T pom;
// for(int i=0;i<length;i++)
// {
// c >> pom;
// data.insert(pom);
// }
// return c;
//}
template <typename T> CConnection & operator<<(CConnection &c, const T &data)
{
c.write(&data,sizeof(data));
@ -81,4 +168,31 @@ template <typename T> CConnection & operator>>(CConnection &c, T &data)
{
c.read(&data,sizeof(data));
return c;
}
template <typename T> CConnection & operator<(CConnection &c, std::vector<T> &data)
{
boost::uint32_t length = data.size();
c << length;
for(ui32 i=0;i<length;i++)
data[i].serialize(c.send,version);
return c;
}
template <typename T> CConnection & operator>(CConnection &c, std::vector<T> &data)
{
boost::uint32_t length;
c >> length;
data.resize(length);
for(ui32 i=0;i<length;i++)
data[i].serialize(c.rec,version);
return c;
}
template <typename T> CConnection & operator<(CConnection &c, T &data)
{
data.serialize(c.send,version);
return c;
}
template <typename T> CConnection & operator>(CConnection &c, T &data)
{
data.serialize(c.rec,version);
return c;
}

View File

@ -20,7 +20,7 @@
OutputDirectory="$(SolutionDir)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
@ -45,6 +45,7 @@
RuntimeLibrary="3"
WarningLevel="3"
DebugInformationFormat="4"
DisableSpecificWarnings="4251"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@ -57,7 +58,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="VCMI_lib.lib"
AdditionalDependencies="VCMI_lib.lib zdll.lib"
AdditionalLibraryDirectories="G:\vcmt\repa\libs"
GenerateDebugInformation="true"
TargetMachine="1"
@ -127,7 +128,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="VCMI_lib.lib"
AdditionalDependencies="VCMI_lib.lib zdll.lib"
AdditionalLibraryDirectories="G:\vcmt\repa\libs"
GenerateDebugInformation="true"
OptimizeReferences="2"

View File

@ -4,58 +4,139 @@
#include <boost/asio.hpp>
#include "../global.h"
#include "../lib/Connection.h"
#include "../CGameState.h"
#include "zlib.h"
#include <boost/thread.hpp>
#include <boost/crc.hpp>
#include <boost/serialization/split_member.hpp>
#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<CConnection*> connections;
std::map<int,CConnection*> connections;
std::set<CConnection*> 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<quantity;i++)
{
(*c) >> 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<unsigned char> 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<clients; i++)
{
if(!i)
{
cc=&c;
}
else
{
tcp::socket * s = new tcp::socket(acceptor.io_service());
acceptor.accept(*s,error);
if(error) //retry
{
std::cout<<"Cannot establish connection - retrying..." << std::endl;
i--;
continue;
}
cc = new CConnection(s,NAME,std::cout);
}
setUpConnection(cc,mapname,checksum);
}
//TODO: wait for other connections
}
void start()
{
srand ( time(NULL) );
seed = rand();
boost::system::error_code error;
std::cout<<"Listening for connections at port " << acceptor.local_endpoint().port() << std::endl;
tcp::socket * s = new tcp::socket(acceptor.io_service());
acceptor.accept(*s,error);
if (error)
{
std::cout<<"Got connection but there is an error " << std::endl;
return;
}
CConnection connection(s,NAME,std::cout);
std::cout<<"Got connection!" << std::endl;
while(1)
{
uint8_t mode;
connection >> 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)