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:
parent
5fff82a3d2
commit
8b7a2f179c
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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 );
|
||||
|
@ -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 )
|
||||
|
Loading…
Reference in New Issue
Block a user