1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +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)
{
QueryReply pack(asker,selection);
pack.player = player;
boost::unique_lock<boost::mutex> lock(*cl->serv->wmx);
*cl->serv << &pack;
}

View File

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

View File

@ -64,7 +64,7 @@ class CClient : public IGameCallback
{
public:
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<IBattleEventsReceiver*> privilagedBattleEventReceivers; //scripting modules, spectator interfaces
std::map<ui8,CGameInterface *> playerint;

View File

@ -528,7 +528,7 @@ void HeroLevelUp::applyCl( CClient *cl )
CGHeroInstance *h = GS(cl)->getHero(heroid);
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);
}
}

View File

@ -2941,8 +2941,14 @@ void CGCreature::endBattle( BattleResult *result ) const
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
{
// 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--;
TSlot slot = getSlotFor(i->second->type);
@ -3013,7 +3019,7 @@ void CGCreature::setPropertyDer(ui8 what, ui32 val)
case ObjProperty::MONSTER_EXP:
giveStackExp(val);
break;
case 13:
case ObjProperty::MONSTER_RESTORE_TYPE:
restore.basicType = val;
break;
}
@ -3145,7 +3151,7 @@ void CGCreature::fight( const CGHeroInstance *h ) const
//split stacks
int totalCount; //TODO: multiple creature types in a stack?
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());
int stacksCount;

View File

@ -1029,7 +1029,7 @@ namespace ObjProperty
{
//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,
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
@ -1791,11 +1791,12 @@ struct QueryReply : public CPackForServer
QueryReply(){type = 6000;};
QueryReply(ui32 QID, ui32 Answer):qid(QID),answer(Answer){type = 6000;};
ui32 qid, answer; //hero and artifact id
ui8 player;
bool applyGh(CGameHandler *gh);
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
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);
tlog5 << "Message successfully applied (result=" << result << ")!\n";
@ -2911,9 +2922,10 @@ bool CGameHandler::hireHero(const CGObjectInstance *obj, ui8 hid, ui8 player)
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);
states.removeQuery(player, qid);
if(vstd::contains(callbacks,qid))
{
CFunctionList<void(ui32)> callb = callbacks[qid];

View File

@ -197,7 +197,7 @@ public:
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);
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 buildBoat( ui32 objid );
bool setFormation( si32 hid, ui8 formation );

View File

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