mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
* counterattacks
* spells learning * no tooltips for objects under FoW * working resource silo * new system for simple unit abilities/states * neutral monster army disappears when defeated * synchronization between client and server processes * fixed battle ending
This commit is contained in:
parent
3b16d67b2e
commit
e71b40ccc5
@ -320,13 +320,13 @@ void CBattleInterface::show(SDL_Surface * to)
|
||||
//double loop because dead stacks should be printed first
|
||||
for(std::map<int, CStack>::iterator j=stacks.begin(); j!=stacks.end(); ++j)
|
||||
{
|
||||
if(j->second.alive)
|
||||
if(j->second.alive())
|
||||
stackAliveByHex[j->second.position].push_back(j->second.ID);
|
||||
}
|
||||
std::vector<int> stackDeadByHex[187];
|
||||
for(std::map<int, CStack>::iterator j=stacks.begin(); j!=stacks.end(); ++j)
|
||||
{
|
||||
if(!j->second.alive)
|
||||
if(!j->second.alive())
|
||||
stackDeadByHex[j->second.position].push_back(j->second.ID);
|
||||
}
|
||||
|
||||
@ -336,7 +336,7 @@ void CBattleInterface::show(SDL_Surface * to)
|
||||
{
|
||||
for(int v=0; v<stackDeadByHex[b].size(); ++v)
|
||||
{
|
||||
creAnims[stackDeadByHex[b][v]]->nextFrame(to, creAnims[stackDeadByHex[b][v]]->pos.x, creAnims[stackDeadByHex[b][v]]->pos.y, creDir[stackDeadByHex[b][v]], (animCount%4==0 || creAnims[stackDeadByHex[b][v]]->getType()!=2) && stacks[stackDeadByHex[b][v]].alive, stackDeadByHex[b][v]==activeStack); //increment always when moving, never if stack died
|
||||
creAnims[stackDeadByHex[b][v]]->nextFrame(to, creAnims[stackDeadByHex[b][v]]->pos.x, creAnims[stackDeadByHex[b][v]]->pos.y, creDir[stackDeadByHex[b][v]], (animCount%4==0 || creAnims[stackDeadByHex[b][v]]->getType()!=2) && stacks[stackDeadByHex[b][v]].alive(), stackDeadByHex[b][v]==activeStack); //increment always when moving, never if stack died
|
||||
//printing amount
|
||||
if(stacks[stackDeadByHex[b][v]].amount > 0) //don't print if stack is not alive
|
||||
{
|
||||
@ -353,7 +353,7 @@ void CBattleInterface::show(SDL_Surface * to)
|
||||
{
|
||||
for(int v=0; v<stackAliveByHex[b].size(); ++v)
|
||||
{
|
||||
creAnims[stackAliveByHex[b][v]]->nextFrame(to, creAnims[stackAliveByHex[b][v]]->pos.x, creAnims[stackAliveByHex[b][v]]->pos.y, creDir[stackAliveByHex[b][v]], (animCount%4==0) && stacks[stackAliveByHex[b][v]].alive, stackAliveByHex[b][v]==activeStack); //increment always when moving, never if stack died
|
||||
creAnims[stackAliveByHex[b][v]]->nextFrame(to, creAnims[stackAliveByHex[b][v]]->pos.x, creAnims[stackAliveByHex[b][v]]->pos.y, creDir[stackAliveByHex[b][v]], (animCount%4==0) && stacks[stackAliveByHex[b][v]].alive(), stackAliveByHex[b][v]==activeStack); //increment always when moving, never if stack died
|
||||
//printing amount
|
||||
if(stacks[stackAliveByHex[b][v]].amount > 0) //don't print if stack is not alive
|
||||
{
|
||||
@ -847,7 +847,7 @@ void CBattleInterface::hexLclicked(int whichOne)
|
||||
return; //we are not permit to do anything
|
||||
|
||||
CStack* dest = LOCPLINT->cb->battleGetStackByPos(whichOne); //creature at destination tile; -1 if there is no one
|
||||
if(!dest || !dest->alive) //no creature at that tile
|
||||
if(!dest || !dest->alive()) //no creature at that tile
|
||||
{
|
||||
if(std::find(shadedHexes.begin(),shadedHexes.end(),whichOne)!=shadedHexes.end())// and it's in our range
|
||||
giveCommand(2,whichOne,activeStack);
|
||||
@ -1321,7 +1321,7 @@ void CBattleHex::mouseMoved(SDL_MouseMotionEvent &sEvent)
|
||||
{
|
||||
if(myInterface->console->alterTxt.size() == 0 && LOCPLINT->cb->battleGetStack(myNumber) != -1 &&
|
||||
LOCPLINT->cb->battleGetStackByPos(myNumber)->owner != LOCPLINT->playerID &&
|
||||
LOCPLINT->cb->battleGetStackByPos(myNumber)->alive)
|
||||
LOCPLINT->cb->battleGetStackByPos(myNumber)->alive())
|
||||
{
|
||||
char tabh[160];
|
||||
CStack attackedStack = *LOCPLINT->cb->battleGetStackByPos(myNumber);
|
||||
@ -1352,7 +1352,7 @@ void CBattleHex::clickRight(boost::logic::tribool down)
|
||||
if(hovered && strictHovered && stID!=-1)
|
||||
{
|
||||
CStack myst = *LOCPLINT->cb->battleGetStackByID(stID); //stack info
|
||||
if(!myst.alive) return;
|
||||
if(!myst.alive()) return;
|
||||
StackState *pom = NULL;
|
||||
if(down)
|
||||
{
|
||||
|
@ -234,6 +234,8 @@ std::vector < std::string > CCallback::getObjDescriptions(int3 pos)
|
||||
{
|
||||
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
|
||||
std::vector<std::string> ret;
|
||||
if(!isVisible(pos,player))
|
||||
return ret;
|
||||
BOOST_FOREACH(const CGObjectInstance * obj, gs->map->terrain[pos.x][pos.y][pos.z].blockingObjects)
|
||||
ret.push_back(obj->hoverName);
|
||||
return ret;
|
||||
@ -521,7 +523,7 @@ bool CCallback::battleCanShoot(int ID, int dest) //TODO: finish
|
||||
if(battleGetStackByID(ID)->creature->isShooting()
|
||||
&& battleGetStack(dest) != -1
|
||||
&& battleGetStackByPos(dest)->owner != battleGetStackByID(ID)->owner
|
||||
&& battleGetStackByPos(dest)->alive)
|
||||
&& battleGetStackByPos(dest)->alive())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -522,6 +522,11 @@ void CCastleInterface::buildingClicked(int building)
|
||||
cmw->activate();
|
||||
break;
|
||||
}
|
||||
case 15:
|
||||
{
|
||||
LOCPLINT->showInfoDialog(CGI->buildh->buildings[town->subID][15]->description,std::vector<SComponent*>());
|
||||
break;
|
||||
}
|
||||
case 16:
|
||||
{
|
||||
const CGHeroInstance *hero = town->visitingHero;
|
||||
@ -1432,8 +1437,7 @@ CMageGuildScreen::CMageGuildScreen(CCastleInterface * owner)
|
||||
blitAt(view,332,76,bg);
|
||||
for(int i=0; i<owner->town->town->mageLevel; i++)
|
||||
{
|
||||
int sp = 5 - i; //how many spells are available at this level
|
||||
if(owner->town->subID==2 && vstd::contains(owner->town->builtBuildings,22)) sp++; //magic library in tower
|
||||
int sp = owner->town->spellsAtLevel(i+1,false);
|
||||
for(int j=0; j<sp; j++)
|
||||
{
|
||||
if(i < owner->town->mageGuildLevel())
|
||||
|
@ -28,7 +28,6 @@ public:
|
||||
void clickRight (tribool down);
|
||||
void mouseMoved (SDL_MouseMotionEvent & sEvent);
|
||||
};
|
||||
|
||||
class CHeroGSlot : public ClickableL, public ClickableR, public Hoverable
|
||||
{
|
||||
public:
|
||||
|
@ -112,7 +112,7 @@ CStack * BattleInfo::getStackT(int tileID)
|
||||
|| (stacks[g]->creature->isDoubleWide() && stacks[g]->attackerOwned && stacks[g]->position-1 == tileID)
|
||||
|| (stacks[g]->creature->isDoubleWide() && !stacks[g]->attackerOwned && stacks[g]->position+1 == tileID))
|
||||
{
|
||||
if(stacks[g]->alive)
|
||||
if(stacks[g]->alive())
|
||||
{
|
||||
return stacks[g];
|
||||
}
|
||||
@ -125,7 +125,7 @@ void BattleInfo::getAccessibilityMap(bool *accessibility, int stackToOmmit)
|
||||
memset(accessibility,1,187); //initialize array with trues
|
||||
for(int g=0; g<stacks.size(); ++g)
|
||||
{
|
||||
if(!stacks[g]->alive || stacks[g]->ID==stackToOmmit) //we don't want to lock position of this stack
|
||||
if(!stacks[g]->alive() || stacks[g]->ID==stackToOmmit) //we don't want to lock position of this stack
|
||||
continue;
|
||||
|
||||
accessibility[stacks[g]->position] = false;
|
||||
@ -254,8 +254,9 @@ std::vector<int> BattleInfo::getPath(int start, int dest, bool*accessibility)
|
||||
}
|
||||
|
||||
CStack::CStack(CCreature * C, int A, int O, int I, bool AO, int S)
|
||||
:creature(C),amount(A), baseAmount(A), owner(O), alive(true), position(-1), ID(I), attackerOwned(AO), firstHPleft(C->hitPoints), slot(S)
|
||||
:creature(C),amount(A), baseAmount(A), owner(O), position(-1), ID(I), attackerOwned(AO), firstHPleft(C->hitPoints), slot(S), counterAttacks(0)
|
||||
{
|
||||
state.insert(ALIVE);
|
||||
}
|
||||
void CGameState::applyNL(IPack * pack)
|
||||
{
|
||||
@ -372,6 +373,18 @@ void CGameState::applyNL(IPack * pack)
|
||||
}
|
||||
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 500:
|
||||
{
|
||||
RemoveObject *rh = static_cast<RemoveObject*>(pack);
|
||||
@ -519,6 +532,8 @@ void CGameState::applyNL(IPack * pack)
|
||||
{
|
||||
BattleNextRound *ns = static_cast<BattleNextRound*>(pack);
|
||||
curB->round = ns->round;
|
||||
for(int i=0; i<curB->stacks.size();i++)
|
||||
curB->stacks[i]->counterAttacks = 0;
|
||||
break;
|
||||
}
|
||||
case 3002:
|
||||
@ -551,12 +566,15 @@ void CGameState::applyNL(IPack * pack)
|
||||
CStack * at = curB->getStack(br->stackAttacked);
|
||||
at->amount = br->newAmount;
|
||||
at->firstHPleft = br->newHP;
|
||||
at->alive = !br->killed();
|
||||
if(br->killed())
|
||||
at->state -= ALIVE;
|
||||
break;
|
||||
}
|
||||
case 3006:
|
||||
{
|
||||
BattleAttack *br = static_cast<BattleAttack*>(pack);
|
||||
if(br->counter())
|
||||
curB->getStack(br->stackAttacking)->counterAttacks++;
|
||||
applyNL(&br->bsa);
|
||||
break;
|
||||
}
|
||||
@ -1325,7 +1343,7 @@ void BattleInfo::calculateCasualties( std::set<std::pair<ui32,si32> > *casualtie
|
||||
{
|
||||
for(int i=0; i<stacks.size();i++)//setting casualties
|
||||
{
|
||||
if(!stacks[i]->alive)
|
||||
if(!stacks[i]->alive())
|
||||
{
|
||||
casualties[!stacks[i]->attackerOwned].insert(std::pair<ui32,si32>(stacks[i]->creature->idNumber,stacks[i]->baseAmount));
|
||||
}
|
||||
@ -1334,24 +1352,4 @@ void BattleInfo::calculateCasualties( std::set<std::pair<ui32,si32> > *casualtie
|
||||
casualties[!stacks[i]->attackerOwned].insert(std::pair<ui32,si32>(stacks[i]->creature->idNumber,stacks[i]->baseAmount - stacks[i]->amount));
|
||||
}
|
||||
}
|
||||
//if(br->killedAmount>0)
|
||||
//{
|
||||
// bool found = false;
|
||||
// for(std::set<std::pair<ui32,si32> >::iterator it = curB->cas[1 - at->attackerOwned].begin(); it!=curB->cas[1 - at->attackerOwned].end(); ++it)
|
||||
// {
|
||||
// if(it->first == at->creature->idNumber)
|
||||
// {
|
||||
// found = true;
|
||||
// std::pair<ui32,si32> mod = *it;
|
||||
// mod.second += br->killedAmount;
|
||||
|
||||
// curB->cas[1 - at->attackerOwned].insert(it, mod);
|
||||
// curB->cas[1 - at->attackerOwned].erase(it);
|
||||
// }
|
||||
// }
|
||||
// if(!found)
|
||||
// {
|
||||
// curB->cas[1 - at->attackerOwned].insert(std::make_pair(at->creature->idNumber, br->killedAmount));
|
||||
// }
|
||||
//}
|
||||
}
|
18
CGameState.h
18
CGameState.h
@ -78,19 +78,22 @@ struct DLL_EXPORT BattleInfo
|
||||
};
|
||||
|
||||
class DLL_EXPORT CStack
|
||||
{
|
||||
{
|
||||
public:
|
||||
ui32 ID; //unique ID of stack
|
||||
CCreature * creature;
|
||||
ui32 amount, baseAmount;
|
||||
ui32 firstHPleft; //HP of first creature in stack
|
||||
ui8 owner, slot; //owner - player colour (255 for neutrals), slot - position in garrison (255 for neutrals/called creatures)
|
||||
ui8 owner, slot; //owner - player colour (255 for neutrals), slot - position in garrison (may be 255 for neutrals/called creatures)
|
||||
ui8 attackerOwned; //if true, this stack is owned by attakcer (this one from left hand side of battle)
|
||||
ui16 position; //position on battlefield
|
||||
ui8 alive; //true if it is alive
|
||||
ui8 counterAttacks; //how many counter attacks has this stack perfomed in current round
|
||||
|
||||
std::set<EAbilities> abilities;
|
||||
std::set<ECombatInfo> state;
|
||||
|
||||
CStack(CCreature * C, int A, int O, int I, bool AO, int S);
|
||||
CStack() : creature(NULL),amount(-1),owner(255), alive(true), position(-1), ID(-1), attackerOwned(true), firstHPleft(-1), slot(255), baseAmount(-1){};
|
||||
CStack() : creature(NULL),amount(-1),owner(255), position(-1), ID(-1), attackerOwned(true), firstHPleft(-1), slot(255), baseAmount(-1), counterAttacks(0){};
|
||||
|
||||
template <typename Handler> void save(Handler &h, const int version)
|
||||
{
|
||||
@ -101,15 +104,20 @@ public:
|
||||
ui32 id;
|
||||
h & id;
|
||||
creature = &VLC->creh->creatures[id];
|
||||
abilities = creature->abilities;
|
||||
}
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & ID & amount & baseAmount & firstHPleft & owner & attackerOwned & position & alive;
|
||||
h & ID & amount & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacks;
|
||||
if(h.saving)
|
||||
save(h,version);
|
||||
else
|
||||
load(h,version);
|
||||
}
|
||||
bool alive()
|
||||
{
|
||||
return vstd::contains(state,ALIVE);
|
||||
}
|
||||
};
|
||||
|
||||
struct UpgradeInfo
|
||||
|
18
CLua.cpp
18
CLua.cpp
@ -720,7 +720,7 @@ std::vector<int> CPickable::yourObjects() //returns IDs of objects which are han
|
||||
|
||||
void CTownScript::onHeroVisit(int objid, int heroID)
|
||||
{
|
||||
|
||||
DEFOS;
|
||||
if(cb->getOwner(objid)!=cb->getOwner(heroID))
|
||||
{
|
||||
return;
|
||||
@ -774,7 +774,8 @@ void CHeroScript::onHeroVisit(int objid, int heroID)
|
||||
&vis->army,
|
||||
my->pos,
|
||||
my,
|
||||
vis);
|
||||
vis,
|
||||
0);
|
||||
}
|
||||
}
|
||||
std::vector<int> CHeroScript::yourObjects() //returns IDs of objects which are handled by script
|
||||
@ -834,7 +835,7 @@ void CMonsterS::onHeroVisit(int objid, int heroID)
|
||||
CCreatureSet set;
|
||||
//TODO: zrobic secik w sposob wyrafinowany
|
||||
set.slots[0] = std::pair<ui32,si32>(os->subID,amounts[objid]);
|
||||
cb->startBattle(heroID,set,os->pos);
|
||||
cb->startBattle(heroID,set,os->pos,boost::bind(&CMonsterS::endBattleWith,this,os,_1));
|
||||
}
|
||||
std::vector<int> CMonsterS::yourObjects() //returns IDs of objects which are handled by script
|
||||
{
|
||||
@ -843,6 +844,17 @@ std::vector<int> CMonsterS::yourObjects() //returns IDs of objects which are han
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CMonsterS::endBattleWith(const CGObjectInstance *monster, BattleResult *result )
|
||||
{
|
||||
if(result->winner==0)
|
||||
{
|
||||
cb->removeObject(monster->id);
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO: remove casualties
|
||||
}
|
||||
}
|
||||
|
||||
void CCreatureGen::newObject(int objid)
|
||||
{
|
||||
|
2
CLua.h
2
CLua.h
@ -25,6 +25,7 @@ class CSelectableComponent;
|
||||
class CGameState;
|
||||
struct Mapa;
|
||||
struct lua_State;
|
||||
struct BattleResult;
|
||||
enum ESLan{UNDEF=-1,CPP,ERM,LUA};
|
||||
class CObjectScript
|
||||
{
|
||||
@ -175,6 +176,7 @@ public:
|
||||
void newObject(int objid);
|
||||
void onHeroVisit(int objid, int heroID);
|
||||
std::vector<int> yourObjects(); //returns IDs of objects which are handled by script
|
||||
void endBattleWith(const CGObjectInstance *monster, BattleResult *result);
|
||||
};
|
||||
|
||||
class CCreatureGen : public CCPPObjectScript
|
||||
|
30
CMT.cpp
30
CMT.cpp
@ -6,6 +6,8 @@
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <cmath>
|
||||
#include <boost/interprocess/mapped_region.hpp>
|
||||
#include <boost/interprocess/shared_memory_object.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include "SDL_ttf.h"
|
||||
#include "SDL_mixer.h"
|
||||
@ -37,6 +39,7 @@
|
||||
#include "client/Graphics.h"
|
||||
#include "client/Client.h"
|
||||
#include "lib/Connection.h"
|
||||
#include "lib/Interprocess.h"
|
||||
#include "lib/VCMI_Lib.h"
|
||||
std::string NAME = NAME_VER + std::string(" (client)");
|
||||
DLL_EXPORT void initDLL(CLodHandler *b);
|
||||
@ -45,6 +48,7 @@ extern SDL_Surface * CSDL_Ext::std32bppSurface;
|
||||
std::queue<SDL_Event> events;
|
||||
boost::mutex eventsM;
|
||||
TTF_Font * TNRB16, *TNR, *GEOR13, *GEORXX, *GEORM, *GEOR16;
|
||||
namespace intpr = boost::interprocess;
|
||||
#ifndef __GNUC__
|
||||
int _tmain(int argc, _TCHAR* argv[])
|
||||
#else
|
||||
@ -149,16 +153,23 @@ int main(int argc, char** argv)
|
||||
THC std::cout<<"Initialization CPreGame (together): "<<tmh.getDif()<<std::endl;
|
||||
THC std::cout<<"Initialization of VCMI (togeter): "<<total.getDif()<<std::endl;
|
||||
cpg->mush = mush;
|
||||
|
||||
StartInfo *options = new StartInfo(cpg->runLoop());
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
tmh.getDif();
|
||||
////////////////////////SERVER STARTING/////////////////////////////////////////////////
|
||||
char portc[10]; SDL_itoa(port,portc,10);
|
||||
intpr::shared_memory_object smo(intpr::open_or_create,"vcmi_memory",intpr::read_write);
|
||||
smo.truncate(sizeof(ServerReady));
|
||||
intpr::mapped_region mr(smo,intpr::read_write);
|
||||
ServerReady *sr = new(mr.get_address())ServerReady();
|
||||
std::string comm = std::string(SERVER_NAME) + " " + portc + " > server_log.txt";
|
||||
boost::thread servthr(boost::bind(system,comm.c_str())); //runs server executable;
|
||||
//TODO: will it work on non-windows platforms?
|
||||
boost::thread servthr(boost::bind(system,comm.c_str())); //runs server executable; //TODO: will it work on non-windows platforms?
|
||||
THC std::cout<<"Preparing shared memory and starting server: "<<tmh.getDif()<<std::endl;
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
THC tmh.getDif();pomtime.getDif();//reset timers
|
||||
cgi->pathf = new CPathfinder();
|
||||
THC std::cout<<"\tPathfinder: "<<pomtime.getDif()<<std::endl;
|
||||
if(argc>1)
|
||||
if(argc>2)
|
||||
{
|
||||
std::cout << "Special mode without support for console!" << std::endl;
|
||||
}
|
||||
@ -171,6 +182,17 @@ int main(int argc, char** argv)
|
||||
std::ofstream lll("client_log.txt");
|
||||
|
||||
CConnection *c=NULL;
|
||||
//wait until server is ready
|
||||
std::cout<<"Waiting for server... " << std::flush;
|
||||
{
|
||||
intpr::scoped_lock<intpr::interprocess_mutex> slock(sr->mutex);
|
||||
while(!sr->ready)
|
||||
{
|
||||
sr->cond.wait(slock);
|
||||
}
|
||||
}
|
||||
intpr::shared_memory_object::remove("vcmi_memory");
|
||||
std::cout << tmh.getDif()<<std::endl;
|
||||
while(!c)
|
||||
{
|
||||
try
|
||||
|
@ -1,11 +1,11 @@
|
||||
#include "CSpellWindow.h"
|
||||
#include "client/Graphics.h"
|
||||
#include "hch/CDefHandler.h"
|
||||
#include "hch/CObjectHandler.h"
|
||||
#include "hch/CPreGameTextHandler.h"
|
||||
#include "CAdvmapInterface.h"
|
||||
#include "CGameInfo.h"
|
||||
#include "SDL_Extensions.h"
|
||||
#include "Graphics.h"
|
||||
#include "../hch/CDefHandler.h"
|
||||
#include "../hch/CObjectHandler.h"
|
||||
#include "../hch/CPreGameTextHandler.h"
|
||||
#include "../CAdvmapInterface.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../SDL_Extensions.h"
|
||||
#include <boost/bind.hpp>
|
||||
#include <sstream>
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "global.h"
|
||||
#include "CPlayerInterface.h"
|
||||
#include "../global.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
|
||||
struct SDL_Surface;
|
||||
class CDefHandler;
|
||||
|
@ -255,6 +255,14 @@ void CClient::process(int what)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 109:
|
||||
{
|
||||
ChangeSpells vc;
|
||||
*serv >> vc;
|
||||
std::cout << "Changing spells of hero "<<vc.hid<<std::endl;
|
||||
gs->apply(&vc);
|
||||
break;
|
||||
}
|
||||
case 500:
|
||||
{
|
||||
RemoveObject rh;
|
||||
|
@ -365,6 +365,10 @@
|
||||
RelativePath="..\hch\CSndHandler.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CSpellWindow.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\CThreadHelper.cpp"
|
||||
>
|
||||
@ -511,6 +515,10 @@
|
||||
RelativePath="..\hch\CSndHandler.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CSpellWindow.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\CThreadHelper.h"
|
||||
>
|
||||
|
10
global.h
10
global.h
@ -40,6 +40,12 @@ enum ElossCon {lossCastle, lossHero, timeExpires, lossStandard=255};
|
||||
enum EHeroClasses {HERO_KNIGHT, HERO_CLERIC, HERO_RANGER, HERO_DRUID, HERO_ALCHEMIST, HERO_WIZARD,
|
||||
HERO_DEMONIAC, HERO_HERETIC, HERO_DEATHKNIGHT, HERO_NECROMANCER, HERO_WARLOCK, HERO_OVERLORD,
|
||||
HERO_BARBARIAN, HERO_BATTLEMAGE, HERO_BEASTMASTER, HERO_WITCH, HERO_PLANESWALKER, HERO_ELEMENTALIST};
|
||||
enum EAbilities {DOUBLE_WIDE, FLYING, SHOOTER, TWO_HEX_ATTACK, SIEGE_ABILITY, SIEGE_WEAPON,
|
||||
KING1, KING2, KING3, MIND_IMMUNITY, NO_OBSTACLE_PENALTY, NO_CLOSE_COMBAT_PENALTY,
|
||||
JOUSTING, FIRE_IMMUNITY, TWICE_ATTACK, NO_ENEMY_RETALIATION, NO_MORAL_PENALTY,
|
||||
UNDEAD, MULTI_HEAD_ATTACK, EXTENDED_RADIOUS_SHOOTER, GHOST, RAISES_MORALE,
|
||||
LOWERS_MORALE, DRAGON, STRIKE_AND_RETURN, FEARLESS, REBIRTH}; //some flags are used only for battles
|
||||
enum ECombatInfo{ALIVE = REBIRTH+1, SUMMONED, CLONED, HAD_MORALE, WAITING, MOVED, DEFENDING};
|
||||
class CGameInfo;
|
||||
extern CGameInfo* CGI;
|
||||
|
||||
@ -111,8 +117,8 @@ namespace vstd
|
||||
{
|
||||
return std::find(c.begin(),c.end(),i) != c.end();
|
||||
}
|
||||
template <typename V, typename Item>
|
||||
bool contains(const std::map<Item,V> & c, const Item &i)
|
||||
template <typename V, typename Item, typename Item2>
|
||||
bool contains(const std::map<Item,V> & c, const Item2 &i)
|
||||
{
|
||||
return c.find(i)!=c.end();
|
||||
}
|
||||
|
@ -40,16 +40,16 @@ int CCreature::getQuantityID(int quantity)
|
||||
|
||||
bool CCreature::isDoubleWide()
|
||||
{
|
||||
return boost::algorithm::find_first(abilityRefs, "DOUBLE_WIDE");
|
||||
return vstd::contains(abilities,DOUBLE_WIDE);
|
||||
}
|
||||
|
||||
bool CCreature::isFlying()
|
||||
{
|
||||
return boost::algorithm::find_first(abilityRefs, "FLYING_ARMY");
|
||||
return vstd::contains(abilities,FLYING);
|
||||
}
|
||||
bool CCreature::isShooting()
|
||||
{
|
||||
return boost::algorithm::find_first(abilityRefs, "SHOOTING_ARMY");
|
||||
return vstd::contains(abilities,SHOOTER);
|
||||
}
|
||||
si32 CCreature::maxAmount(const std::vector<si32> &res) const //how many creatures can be bought
|
||||
{
|
||||
@ -306,6 +306,12 @@ void CCreatureHandler::loadCreatures()
|
||||
}
|
||||
ncre.abilityRefs = buf.substr(befi, i-befi);
|
||||
i+=2;
|
||||
if(boost::algorithm::find_first(ncre.abilityRefs, "DOUBLE_WIDE"))
|
||||
ncre.abilities.insert(DOUBLE_WIDE);
|
||||
if(boost::algorithm::find_first(ncre.abilityRefs, "FLYING_ARMY"))
|
||||
ncre.abilities.insert(FLYING);
|
||||
if(boost::algorithm::find_first(ncre.abilityRefs, "SHOOTING_ARMY"))
|
||||
ncre.abilities.insert(SHOOTER);
|
||||
if(ncre.nameSing!=std::string("") && ncre.namePl!=std::string(""))
|
||||
{
|
||||
ncre.idNumber = creatures.size();
|
||||
@ -443,8 +449,10 @@ void CCreatureHandler::loadCreatures()
|
||||
}
|
||||
inp2.close();
|
||||
|
||||
creatures[122].abilityRefs += "DOUBLE_WIDE"; //water elemental should be treated as double-wide
|
||||
creatures[123].abilityRefs += "DOUBLE_WIDE"; //ice elemental should be treated as double-wide
|
||||
|
||||
|
||||
creatures[122].abilities.insert(DOUBLE_WIDE);//water elemental should be treated as double-wide
|
||||
creatures[123].abilities.insert(DOUBLE_WIDE);//ice elemental should be treated as double-wide
|
||||
}
|
||||
|
||||
void CCreatureHandler::loadAnimationInfo()
|
||||
|
@ -22,6 +22,7 @@ public:
|
||||
std::string abilityRefs; //references to abilities, in textformat
|
||||
std::string animDefName;
|
||||
ui32 idNumber;
|
||||
std::set<EAbilities> abilities;
|
||||
int faction; //-1 = neutral
|
||||
|
||||
///animation info
|
||||
|
@ -412,6 +412,16 @@ CGHeroInstance::~CGHeroInstance()
|
||||
|
||||
CGTownInstance::~CGTownInstance()
|
||||
{}
|
||||
|
||||
int CGTownInstance::spellsAtLevel(int level, bool checkGuild) const
|
||||
{
|
||||
if(checkGuild && mageGuildLevel() < level)
|
||||
return 0;
|
||||
int ret = 6 - level; //how many spells are available at this level
|
||||
if(subID == 2 && vstd::contains(builtBuildings,22)) //magic library in Tower
|
||||
ret++;
|
||||
return ret;
|
||||
}
|
||||
CGObjectInstance::CGObjectInstance(const CGObjectInstance & right)
|
||||
{
|
||||
pos = right.pos;
|
||||
|
@ -168,6 +168,7 @@ public:
|
||||
bool hasFort() const;
|
||||
bool hasCapitol() const;
|
||||
int dailyIncome() const;
|
||||
int spellsAtLevel(int level, bool checkGuild) const; //levels are counted from 1 (1 - 5)
|
||||
|
||||
CGTownInstance();
|
||||
virtual ~CGTownInstance();
|
||||
|
22
lib/Interprocess.h
Normal file
22
lib/Interprocess.h
Normal file
@ -0,0 +1,22 @@
|
||||
#include <boost/interprocess/sync/interprocess_mutex.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_condition.hpp>
|
||||
|
||||
struct ServerReady
|
||||
{
|
||||
bool ready;
|
||||
boost::interprocess::interprocess_mutex mutex;
|
||||
boost::interprocess::interprocess_condition cond;
|
||||
|
||||
ServerReady()
|
||||
{
|
||||
ready = false;
|
||||
}
|
||||
|
||||
void setToTrueAndNotify()
|
||||
{
|
||||
mutex.lock();
|
||||
ready = true;
|
||||
mutex.unlock();
|
||||
cond.notify_all();
|
||||
}
|
||||
};
|
@ -96,6 +96,18 @@ struct HeroVisitCastle : public CPack<HeroVisitCastle> //108
|
||||
h & flags & tid & hid;
|
||||
}
|
||||
};
|
||||
struct ChangeSpells : public CPack<ChangeSpells> //109
|
||||
{
|
||||
ChangeSpells(){type = 109;};
|
||||
ui8 learn; //1 - gives spell, 0 - takes
|
||||
ui32 hid;
|
||||
std::set<ui32> spells;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & learn & hid & spells;
|
||||
}
|
||||
};
|
||||
struct RemoveObject : public CPack<RemoveObject> //500
|
||||
{
|
||||
RemoveObject(){type = 500;};
|
||||
@ -442,6 +454,10 @@ struct BattleAttack : public CPack<BattleAttack>//3006
|
||||
{
|
||||
return flags & 1;
|
||||
}
|
||||
bool counter()//is it counterattack?
|
||||
{
|
||||
return flags & 2;
|
||||
}
|
||||
bool killed() //if target stack was killed
|
||||
{
|
||||
return bsa.killed();
|
||||
|
@ -372,6 +372,10 @@
|
||||
RelativePath="..\hch\CTownHandler.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Interprocess.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\map.h"
|
||||
>
|
||||
|
@ -240,11 +240,12 @@ void CGameHandler::changePrimSkill(int ID, int which, int val, bool abs)
|
||||
}
|
||||
}
|
||||
|
||||
void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2)
|
||||
void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb)
|
||||
{
|
||||
BattleInfo *curB = new BattleInfo;
|
||||
setupBattle(curB, tile, army1, army2, hero1, hero2); //battle start
|
||||
setupBattle(curB, tile, army1, army2, hero1, hero2); //initializes stacks, places creatures on battlefield, blocks and informs player interfaces
|
||||
NEW_ROUND;
|
||||
//TODO: pre-tactic stuff, call scripts etc.
|
||||
|
||||
|
||||
//tactic round
|
||||
@ -267,15 +268,15 @@ void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile
|
||||
//stack loop
|
||||
for(unsigned i=0;i<stacks.size() && !battleResult.get();i++)
|
||||
{
|
||||
if(!stacks[i]->alive) continue;//indicates imposiibility of making action for this dead unit
|
||||
if(!stacks[i]->alive()) continue;//indicates imposiibility of making action for this dead unit
|
||||
BattleSetActiveStack sas;
|
||||
sas.stack = stacks[i]->ID;
|
||||
sendAndApply(&sas);
|
||||
boost::unique_lock<boost::mutex> lock(battleMadeAction.mx);
|
||||
while(!battleMadeAction.data)
|
||||
while(!battleMadeAction.data && !battleResult.get()) //active stack hasn't made its action and battle is still going
|
||||
battleMadeAction.cond.wait(lock);
|
||||
battleMadeAction.data = false;
|
||||
checkForBattleEnd(stacks);
|
||||
checkForBattleEnd(stacks); //check if this action ended the battle
|
||||
}
|
||||
}
|
||||
|
||||
@ -287,6 +288,8 @@ void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile
|
||||
|
||||
//end battle, remove all info, free memory
|
||||
sendAndApply(battleResult.data);
|
||||
if(cb)
|
||||
cb(battleResult.data);
|
||||
delete battleResult.data;
|
||||
//for(int i=0;i<stacks.size();i++)
|
||||
// delete stacks[i];
|
||||
@ -565,6 +568,14 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
|
||||
sr.res[i]-=b->resources[i];
|
||||
sendAndApply(&sr);
|
||||
|
||||
if(bid<5) //it's mage guild
|
||||
{
|
||||
if(t->visitingHero)
|
||||
giveSpells(t,t->visitingHero);
|
||||
if(t->garrisonHero)
|
||||
giveSpells(t,t->garrisonHero);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 506: //recruit creature
|
||||
@ -770,7 +781,7 @@ upgend:
|
||||
c >> hid >> aid;
|
||||
CGHeroInstance *hero = gs->getHero(hid);
|
||||
CGTownInstance *town = hero->visitedTown;
|
||||
if(aid==0)
|
||||
if(aid==0) //spellbok
|
||||
{
|
||||
if(!vstd::contains(town->builtBuildings,si32(0)))
|
||||
break;
|
||||
@ -786,6 +797,8 @@ upgend:
|
||||
sha.artifWorn = hero->artifWorn;
|
||||
sha.artifWorn[17] = 0;
|
||||
sendAndApply(&sha);
|
||||
|
||||
giveSpells(town,hero);
|
||||
}
|
||||
else if(aid < 7 && aid > 3) //war machine
|
||||
{
|
||||
@ -883,6 +896,14 @@ upgend:
|
||||
BattleAttack bat;
|
||||
prepareAttack(bat,curStack,stackAtEnd);
|
||||
sendAndApply(&bat);
|
||||
//counterattack
|
||||
if(!vstd::contains(curStack->abilities,NO_ENEMY_RETALIATION)
|
||||
&& !stackAtEnd->counterAttacks ) //TODO: support for multiple retaliatons per turn
|
||||
{
|
||||
prepareAttack(bat,stackAtEnd,curStack);
|
||||
bat.flags |= 2;
|
||||
sendAndApply(&bat);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 7: //shoot
|
||||
@ -942,7 +963,7 @@ void CGameHandler::moveStack(int stack, int dest)
|
||||
else
|
||||
gs->curB->getAccessibilityMap(accessibility,curStack->ID);
|
||||
|
||||
if((stackAtEnd && stackAtEnd!=curStack && stackAtEnd->alive) || !accessibility[dest])
|
||||
if((stackAtEnd && stackAtEnd!=curStack && stackAtEnd->alive()) || !accessibility[dest])
|
||||
return;
|
||||
|
||||
//if(dists[dest] > curStack->creature->speed && !(stackAtEnd && dists[dest] == curStack->creature->speed+1)) //we can attack a stack if we can go to adjacent hex
|
||||
@ -1050,6 +1071,18 @@ void CGameHandler::newTurn()
|
||||
}
|
||||
for(std::vector<CGTownInstance *>::iterator j=i->second.towns.begin();j!=i->second.towns.end();j++)//handle towns
|
||||
{
|
||||
if(vstd::contains((**j).builtBuildings,15)) //there is resource silo
|
||||
{
|
||||
if((**j).town->primaryRes == 127) //we'll give wood and ore
|
||||
{
|
||||
r.res[0] += 1;
|
||||
r.res[2] += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
r.res[(**j).town->primaryRes] += 1;
|
||||
}
|
||||
}
|
||||
if(gs->getDate(1)==7) //first day of week
|
||||
{
|
||||
SetAvailableCreatures sac;
|
||||
@ -1318,17 +1351,36 @@ void CGameHandler::checkForBattleEnd( std::vector<CStack*> &stacks )
|
||||
hasStack[0] = hasStack[1] = false;
|
||||
for(int b = 0; b<stacks.size(); ++b)
|
||||
{
|
||||
if(stacks[b]->alive)
|
||||
if(stacks[b]->alive())
|
||||
{
|
||||
hasStack[1-stacks[b]->attackerOwned] = true;
|
||||
}
|
||||
}
|
||||
if(!hasStack[0] || !hasStack[1]) //somebody has won
|
||||
{
|
||||
BattleResult *br = new BattleResult;
|
||||
BattleResult *br = new BattleResult; //will be deleted at the end of startBattle(...)
|
||||
br->result = 0;
|
||||
br->winner = hasStack[1]; //fleeing side loses
|
||||
gs->curB->calculateCasualties(br->casualties);
|
||||
battleResult.set(br);
|
||||
}
|
||||
}
|
||||
|
||||
void CGameHandler::giveSpells( const CGTownInstance *t, const CGHeroInstance *h )
|
||||
{
|
||||
if(!vstd::contains(h->artifWorn,17))
|
||||
return; //hero hasn't spellbok
|
||||
ChangeSpells cs;
|
||||
cs.hid = h->id;
|
||||
cs.learn = true;
|
||||
for(int i=0; i<std::min(t->mageGuildLevel(),h->getSecSkillLevel(7)+4);i++)
|
||||
{
|
||||
for(int j=0; j<t->spellsAtLevel(i+1,true); j++)
|
||||
{
|
||||
if(!vstd::contains(h->spells,t->spells[i][j]))
|
||||
cs.spells.insert(t->spells[i][j]);
|
||||
}
|
||||
}
|
||||
if(cs.spells.size())
|
||||
sendAndApply(&cs);
|
||||
}
|
@ -11,6 +11,7 @@ class CGameState;
|
||||
struct StartInfo;
|
||||
class CCPPObjectScript;
|
||||
class CScriptCallback;
|
||||
struct BattleResult;
|
||||
template <typename T> struct CPack;
|
||||
template <typename T> struct Query;
|
||||
class CGHeroInstance;
|
||||
@ -52,8 +53,9 @@ class CGameHandler
|
||||
void handleCPPObjS(std::map<int,CCPPObjectScript*> * mapa, CCPPObjectScript * script);
|
||||
void changePrimSkill(int ID, int which, int val, bool abs=false);
|
||||
void changeSecSkill(int ID, ui16 which, int val, bool abs=false);
|
||||
void giveSpells(const CGTownInstance *t, const CGHeroInstance *h);
|
||||
void moveStack(int stack, int dest);
|
||||
void startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2); //use hero=NULL for no hero
|
||||
void startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb); //use hero=NULL for no hero
|
||||
|
||||
void checkForBattleEnd( std::vector<CStack*> &stacks );
|
||||
void setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army1, CCreatureSet &army2, CGHeroInstance * hero1, CGHeroInstance * hero2 );
|
||||
|
@ -117,6 +117,7 @@ void CScriptCallback::heroVisitCastle(int obj, int heroID)
|
||||
vc.tid = obj;
|
||||
vc.flags |= 1;
|
||||
gh->sendAndApply(&vc);
|
||||
gh->giveSpells(getTown(obj),getHero(heroID));
|
||||
}
|
||||
|
||||
void CScriptCallback::stopHeroVisitCastle(int obj, int heroID)
|
||||
@ -144,16 +145,25 @@ void CScriptCallback::giveHeroArtifact(int artid, int hid, int position) //pos==
|
||||
gh->sendAndApply(&sha);
|
||||
}
|
||||
|
||||
void CScriptCallback::startBattle(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2) //use hero=NULL for no hero
|
||||
void CScriptCallback::startBattle(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb) //use hero=NULL for no hero
|
||||
{
|
||||
boost::thread(boost::bind(&CGameHandler::startBattle,gh,*(CCreatureSet *)army1,*(CCreatureSet *)army2,tile,(CGHeroInstance *)hero1,(CGHeroInstance *)hero2));
|
||||
boost::thread(boost::bind(&CGameHandler::startBattle,gh,*(CCreatureSet *)army1,*(CCreatureSet *)army2,tile,(CGHeroInstance *)hero1,(CGHeroInstance *)hero2,cb));
|
||||
}
|
||||
void CScriptCallback::startBattle(int heroID, CCreatureSet army, int3 tile) //for hero<=>neutral army
|
||||
void CScriptCallback::startBattle(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb) //for hero<=>neutral army
|
||||
{
|
||||
CGHeroInstance* h = const_cast<CGHeroInstance*>(getHero(heroID));
|
||||
startBattle(&h->army,&army,tile,h,NULL);
|
||||
startBattle(&h->army,&army,tile,h,NULL,cb);
|
||||
//gh->gs->battle(&h->army,army,tile,h,NULL);
|
||||
}
|
||||
|
||||
void CScriptCallback::changeSpells( int hid, bool give, const std::set<ui32> &spells )
|
||||
{
|
||||
ChangeSpells cs;
|
||||
cs.hid = hid;
|
||||
cs.spells = spells;
|
||||
cs.learn = give;
|
||||
gh->sendAndApply(&cs);
|
||||
}
|
||||
void CLuaCallback::registerFuncs(lua_State * L)
|
||||
{
|
||||
// lua_newtable(L);
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "../global.h"
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include "../client/FunctionList.h"
|
||||
class CVCMIServer;
|
||||
class CGameHandler;
|
||||
@ -19,6 +20,7 @@ struct InfoWindow;
|
||||
struct ShowInInfobox;
|
||||
struct SelectionDialog;
|
||||
struct YesNoDialog;
|
||||
struct BattleResult;
|
||||
class CScriptCallback
|
||||
{
|
||||
CScriptCallback(void);
|
||||
@ -37,6 +39,7 @@ public:
|
||||
const CGTownInstance* getTown(int objid);
|
||||
|
||||
//do sth
|
||||
void changeSpells(int hid, bool give, const std::set<ui32> &spells);
|
||||
void removeObject(int objid);
|
||||
void setBlockVis(int objid, bool bv);
|
||||
void setOwner(int objid, ui8 owner);
|
||||
@ -50,8 +53,8 @@ public:
|
||||
void heroVisitCastle(int obj, int heroID);
|
||||
void stopHeroVisitCastle(int obj, int heroID);
|
||||
void giveHeroArtifact(int artid, int hid, int position); //pos==-1 - first free slot in backpack
|
||||
void startBattle(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2); //use hero=NULL for no hero
|
||||
void startBattle(int heroID, CCreatureSet army, int3 tile); //for hero<=>neutral army
|
||||
void startBattle(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb); //use hero=NULL for no hero
|
||||
void startBattle(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb); //for hero<=>neutral army
|
||||
|
||||
//friends
|
||||
friend class CGameHandler;
|
||||
|
@ -9,21 +9,28 @@
|
||||
#endif
|
||||
#include "CVCMIServer.h"
|
||||
#include <boost/crc.hpp>
|
||||
#include <boost/serialization/split_member.hpp>
|
||||
#include <boost/interprocess/mapped_region.hpp>
|
||||
#include <boost/interprocess/shared_memory_object.hpp>
|
||||
#include "../StartInfo.h"
|
||||
#include "../map.h"
|
||||
#include "../hch/CLodHandler.h"
|
||||
#include "../lib/Interprocess.h"
|
||||
#include "../lib/VCMI_Lib.h"
|
||||
#include "CGameHandler.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;
|
||||
namespace intpr = boost::interprocess;
|
||||
|
||||
bool end2 = false;
|
||||
int port = 3030;
|
||||
|
||||
void vaccept(tcp::acceptor *ac, tcp::socket *s, boost::system::error_code *error)
|
||||
{
|
||||
ac->accept(*s,*error);
|
||||
}
|
||||
|
||||
CVCMIServer::CVCMIServer()
|
||||
: io(new io_service()), acceptor(new tcp::acceptor(*io, tcp::endpoint(tcp::v4(), port)))
|
||||
{
|
||||
@ -90,10 +97,29 @@ void CVCMIServer::newGame(CConnection *c)
|
||||
}
|
||||
void CVCMIServer::start()
|
||||
{
|
||||
ServerReady *sr = NULL;
|
||||
intpr::mapped_region *mr;
|
||||
try
|
||||
{
|
||||
intpr::shared_memory_object smo(intpr::open_only,"vcmi_memory",intpr::read_write);
|
||||
mr = new intpr::mapped_region(smo,intpr::read_write);
|
||||
sr = (ServerReady*)mr->get_address();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
intpr::shared_memory_object smo(intpr::create_only,"vcmi_memory",intpr::read_write);
|
||||
smo.truncate(sizeof(ServerReady));
|
||||
mr = new intpr::mapped_region(smo,intpr::read_write);
|
||||
sr = new(mr->get_address())ServerReady();
|
||||
}
|
||||
|
||||
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);
|
||||
boost::thread acc(boost::bind(vaccept,acceptor,s,&error));
|
||||
sr->setToTrueAndNotify();
|
||||
delete mr;
|
||||
acc.join();
|
||||
if (error)
|
||||
{
|
||||
std::cout<<"Got connection but there is an error " << std::endl << error;
|
||||
@ -147,7 +173,9 @@ int main(int argc, char** argv)
|
||||
io_service io_service;
|
||||
CVCMIServer server;
|
||||
while(!end2)
|
||||
{
|
||||
server.start();
|
||||
}
|
||||
io_service.run();
|
||||
} HANDLE_EXCEPTION
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user