1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-03-29 21:56:54 +02:00

* Server will strictly require answering the queries before taking any actions. Let me know, if this causes any freezes.

* Fixed crash on new week after we lost battle with neutral monster but killed the top stack (merging failed then).
* minor changes
This commit is contained in:
Michał W. Urbańczyk 2011-09-06 06:00:32 +00:00
parent 5fff82a3d2
commit 8b7a2f179c
9 changed files with 37 additions and 18 deletions

View File

@ -58,6 +58,8 @@ bool CCallback::moveHero(const CGHeroInstance *h, int3 dst)
void CCallback::selectionMade(int selection, int asker) void CCallback::selectionMade(int selection, int asker)
{ {
QueryReply pack(asker,selection); QueryReply pack(asker,selection);
pack.player = player;
boost::unique_lock<boost::mutex> lock(*cl->serv->wmx); boost::unique_lock<boost::mutex> lock(*cl->serv->wmx);
*cl->serv << &pack; *cl->serv << &pack;
} }

View File

@ -214,10 +214,7 @@ void CClient::endGame( bool closeConnection /*= true*/ )
delete pint; delete pint;
} }
BOOST_FOREACH(CCallback *cb, callbacks) callbacks.clear();
{
delete cb;
}
tlog0 << "Deleted playerInts." << std::endl; tlog0 << "Deleted playerInts." << std::endl;
tlog0 << "Client stopped." << std::endl; tlog0 << "Client stopped." << std::endl;
@ -379,6 +376,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
battleints[color] = playerint[color]; battleints[color] = playerint[color];
playerint[color]->init(cb); playerint[color]->init(cb);
callbacks[color] = std::auto_ptr<CCallback>(cb);
} }
else else
{ {
@ -465,10 +463,9 @@ void CClient::serialize( Handler &h, const int version )
else else
nInt = new CPlayerInterface(pid); nInt = new CPlayerInterface(pid);
CCallback *callback = new CCallback(gs,pid,this); callbacks[pid] = std::auto_ptr<CCallback>(new CCallback(gs,pid,this));
callbacks.insert(callback);
battleints[pid] = playerint[pid] = nInt; battleints[pid] = playerint[pid] = nInt;
nInt->init(callback); nInt->init(callbacks[pid].get());
nInt->serialize(h, version); nInt->serialize(h, version);
} }

View File

@ -64,7 +64,7 @@ class CClient : public IGameCallback
{ {
public: public:
CCallback *cb; CCallback *cb;
std::set<CCallback*> callbacks; //callbacks given to player interfaces std::map<ui8,std::auto_ptr<CCallback> > callbacks; //callbacks given to player interfaces
std::vector<IGameEventsReceiver*> privilagedGameEventReceivers; //scripting modules, spectator interfaces std::vector<IGameEventsReceiver*> privilagedGameEventReceivers; //scripting modules, spectator interfaces
std::vector<IBattleEventsReceiver*> privilagedBattleEventReceivers; //scripting modules, spectator interfaces std::vector<IBattleEventsReceiver*> privilagedBattleEventReceivers; //scripting modules, spectator interfaces
std::map<ui8,CGameInterface *> playerint; std::map<ui8,CGameInterface *> playerint;

View File

@ -528,7 +528,7 @@ void HeroLevelUp::applyCl( CClient *cl )
CGHeroInstance *h = GS(cl)->getHero(heroid); CGHeroInstance *h = GS(cl)->getHero(heroid);
if(vstd::contains(cl->playerint,h->tempOwner)) if(vstd::contains(cl->playerint,h->tempOwner))
{ {
boost::function<void(ui32)> callback = boost::function<void(ui32)>(boost::bind(&CCallback::selectionMade,LOCPLINT->cb,_1,id)); boost::function<void(ui32)> callback = boost::function<void(ui32)>(boost::bind(&CCallback::selectionMade,cl->callbacks[h->tempOwner].get(),_1,id));
cl->playerint[h->tempOwner]->heroGotLevel(const_cast<const CGHeroInstance*>(h),static_cast<int>(primskill),skills, callback); cl->playerint[h->tempOwner]->heroGotLevel(const_cast<const CGHeroInstance*>(h),static_cast<int>(primskill),skills, callback);
} }
} }

View File

@ -2941,8 +2941,14 @@ void CGCreature::endBattle( BattleResult *result ) const
cb->changeStackType (StackLocation(this, i->first), cre); //un-upgrade creatures cb->changeStackType (StackLocation(this, i->first), cre); //un-upgrade creatures
} }
} }
//first stack has to be at slot 0 -> if original one got killed, move there first remaining stack
if(!hasStackAtSlot(0))
cb->moveStack(StackLocation(this, stacks.begin()->first), StackLocation(this, 0), stacks.begin()->second->count);
while (stacks.size() > 1) //hopefully that's enough while (stacks.size() > 1) //hopefully that's enough
{ {
// TODO it's either overcomplicated (if we assume there'll be only one stack) or buggy (if we allow multiple stacks... but that'll also cause troubles elsewhere)
i = stacks.end(); i = stacks.end();
i--; i--;
TSlot slot = getSlotFor(i->second->type); TSlot slot = getSlotFor(i->second->type);
@ -3013,7 +3019,7 @@ void CGCreature::setPropertyDer(ui8 what, ui32 val)
case ObjProperty::MONSTER_EXP: case ObjProperty::MONSTER_EXP:
giveStackExp(val); giveStackExp(val);
break; break;
case 13: case ObjProperty::MONSTER_RESTORE_TYPE:
restore.basicType = val; restore.basicType = val;
break; break;
} }
@ -3145,7 +3151,7 @@ void CGCreature::fight( const CGHeroInstance *h ) const
//split stacks //split stacks
int totalCount; //TODO: multiple creature types in a stack? int totalCount; //TODO: multiple creature types in a stack?
int basicType = stacks.begin()->second->type->idNumber; int basicType = stacks.begin()->second->type->idNumber;
cb->setObjProperty(id, 13, basicType); //store info about creature stack cb->setObjProperty(id, ObjProperty::MONSTER_RESTORE_TYPE, basicType); //store info about creature stack
float relativePower = ((float)h->getTotalStrength() / getArmyStrength()); float relativePower = ((float)h->getTotalStrength() / getArmyStrength());
int stacksCount; int stacksCount;

View File

@ -1029,7 +1029,7 @@ namespace ObjProperty
{ {
//TODO: move non general properties out to the appropriate objs classes //TODO: move non general properties out to the appropriate objs classes
enum {OWNER = 1, BLOCKVIS = 2, PRIMARY_STACK_COUNT = 3, VISITORS = 4, VISITED = 5, ID = 6, AVAILABLE_CREATURE = 7, SUBID = 8, enum {OWNER = 1, BLOCKVIS = 2, PRIMARY_STACK_COUNT = 3, VISITORS = 4, VISITED = 5, ID = 6, AVAILABLE_CREATURE = 7, SUBID = 8,
MONSTER_COUNT = 10, MONSTER_POWER = 11, MONSTER_EXP = 12}; MONSTER_COUNT = 10, MONSTER_POWER = 11, MONSTER_EXP = 12, MONSTER_RESTORE_TYPE = 13};
} }
struct SetObjectProperty : public CPackForClient//1001 struct SetObjectProperty : public CPackForClient//1001
@ -1791,11 +1791,12 @@ struct QueryReply : public CPackForServer
QueryReply(){type = 6000;}; QueryReply(){type = 6000;};
QueryReply(ui32 QID, ui32 Answer):qid(QID),answer(Answer){type = 6000;}; QueryReply(ui32 QID, ui32 Answer):qid(QID),answer(Answer){type = 6000;};
ui32 qid, answer; //hero and artifact id ui32 qid, answer; //hero and artifact id
ui8 player;
bool applyGh(CGameHandler *gh); bool applyGh(CGameHandler *gh);
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
h & qid & answer; h & qid & answer & player;
} }
}; };

View File

@ -635,7 +635,18 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
int packType = typeList.getTypeID(pack); //get the id of type int packType = typeList.getTypeID(pack); //get the id of type
CBaseForGHApply *apply = applier->apps[packType]; //and appropriae applier object CBaseForGHApply *apply = applier->apps[packType]; //and appropriae applier object
if(apply) if(packType != typeList.getTypeID<QueryReply>() && states[getCurrentPlayer()].queries.size())
{
complain("Answer the query before attempting any further actions!");
PackageApplied applied;
applied.result = false;
applied.packType = packType;
{
boost::unique_lock<boost::mutex> lock(*c.wmx);
c << &applied;
}
}
else if(apply)
{ {
bool result = apply->applyOnGH(this,&c,pack); bool result = apply->applyOnGH(this,&c,pack);
tlog5 << "Message successfully applied (result=" << result << ")!\n"; tlog5 << "Message successfully applied (result=" << result << ")!\n";
@ -2911,9 +2922,10 @@ bool CGameHandler::hireHero(const CGObjectInstance *obj, ui8 hid, ui8 player)
return true; return true;
} }
bool CGameHandler::queryReply( ui32 qid, ui32 answer ) bool CGameHandler::queryReply(ui32 qid, ui32 answer, ui8 player)
{ {
boost::unique_lock<boost::recursive_mutex> lock(gsm); boost::unique_lock<boost::recursive_mutex> lock(gsm);
states.removeQuery(player, qid);
if(vstd::contains(callbacks,qid)) if(vstd::contains(callbacks,qid))
{ {
CFunctionList<void(ui32)> callb = callbacks[qid]; CFunctionList<void(ui32)> callb = callbacks[qid];

View File

@ -197,7 +197,7 @@ public:
bool makeBattleAction(BattleAction &ba); bool makeBattleAction(BattleAction &ba);
void handleSpellCasting(int spellID, int spellLvl, THex destination, ui8 casterSide, ui8 casterColor, const CGHeroInstance * caster, const CGHeroInstance * secHero, int usedSpellPower, SpellCasting::ECastingMode mode, const CStack * stack); void handleSpellCasting(int spellID, int spellLvl, THex destination, ui8 casterSide, ui8 casterColor, const CGHeroInstance * caster, const CGHeroInstance * secHero, int usedSpellPower, SpellCasting::ECastingMode mode, const CStack * stack);
bool makeCustomAction(BattleAction &ba); bool makeCustomAction(BattleAction &ba);
bool queryReply( ui32 qid, ui32 answer ); bool queryReply( ui32 qid, ui32 answer, ui8 player );
bool hireHero( const CGObjectInstance *obj, ui8 hid, ui8 player ); bool hireHero( const CGObjectInstance *obj, ui8 hid, ui8 player );
bool buildBoat( ui32 objid ); bool buildBoat( ui32 objid );
bool setFormation( si32 hid, ui8 formation ); bool setFormation( si32 hid, ui8 formation );

View File

@ -225,8 +225,9 @@ bool BuildBoat::applyGh( CGameHandler *gh )
bool QueryReply::applyGh( CGameHandler *gh ) bool QueryReply::applyGh( CGameHandler *gh )
{ {
//TODO - check if player matches the query ERROR_IF_NOT(player);
return gh->queryReply(qid,answer); assert(vstd::contains(gh->states.players, player));
return gh->queryReply(qid, answer, player);
} }
bool MakeAction::applyGh( CGameHandler *gh ) bool MakeAction::applyGh( CGameHandler *gh )