1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Breaking things - trying to remove server-side knowledge of selected objects

This commit is contained in:
Ivan Savenko 2014-09-19 00:18:49 +03:00
parent 818a766fd6
commit 78709e223b
20 changed files with 47 additions and 129 deletions

View File

@ -664,8 +664,8 @@ void VCAI::makeTurn()
}
break;
}
if(cb->getSelectedHero())
cb->recalculatePaths();
//FIXME: necessary? How to re-enable?
//cb->recalculatePaths(cb->getSelectedHero());
markHeroAbleToExplore (primaryHero());
@ -793,7 +793,7 @@ void VCAI::performObjectInteraction(const CGObjectInstance * obj, HeroPtr h)
switch (obj->ID)
{
case Obj::CREATURE_GENERATOR1:
recruitCreatures (dynamic_cast<const CGDwelling *>(obj));
recruitCreatures (dynamic_cast<const CGDwelling *>(obj), h.get());
checkHeroArmy (h);
break;
case Obj::TOWN:
@ -926,7 +926,7 @@ void VCAI::pickBestCreatures(const CArmedInstance * army, const CArmedInstance *
}
}
void VCAI::recruitCreatures(const CGDwelling * d)
void VCAI::recruitCreatures(const CGDwelling * d, const CArmedInstance * recruiter)
{
for(int i = 0; i < d->creatures.size(); i++)
{
@ -941,7 +941,7 @@ void VCAI::recruitCreatures(const CGDwelling * d)
amin(count, freeResources() / VLC->creh->creatures[creID]->cost);
if(count > 0)
cb->recruitCreatures(d, creID, count, i);
cb->recruitCreatures(d, recruiter, creID, count, i);
}
}
@ -1653,7 +1653,7 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
if(path.nodes.empty())
{
logAi->errorStream() << "Hero " << h->name << " cannot reach " << dst;
cb->recalculatePaths();
cb->recalculatePaths(h.get());
throw goalFulfilledException (sptr(Goals::VisitTile(dst).sethero(h)));
}
@ -1702,7 +1702,7 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
reserveObject(h, obj);
}
cb->recalculatePaths();
cb->recalculatePaths(h.get());
if (startHpos == h->visitablePos() && !ret) //we didn't move and didn't reach the target
{
erase_if_present (lockedHeroes, h); //hero seemingly is confused
@ -2212,7 +2212,7 @@ void VCAI::buildArmyIn(const CGTownInstance * t)
{
makePossibleUpgrades(t->visitingHero);
makePossibleUpgrades(t);
recruitCreatures(t);
recruitCreatures(t, t);
moveCreaturesToHero(t);
}

View File

@ -263,7 +263,7 @@ public:
std::vector<const CGObjectInstance *> getPossibleDestinations(HeroPtr h);
void buildStructure(const CGTownInstance * t);
//void recruitCreatures(const CGTownInstance * t);
void recruitCreatures(const CGDwelling * d);
void recruitCreatures(const CGDwelling * d, const CArmedInstance * recruiter);
bool canGetArmy (const CGHeroInstance * h, const CGHeroInstance * source); //can we get any better stacks from other hero?
void pickBestCreatures(const CArmedInstance * army, const CArmedInstance * source); //called when we can't find a slot for new stack
void moveCreaturesToHero(const CGTownInstance * t);

View File

@ -69,12 +69,12 @@ int CCallback::selectionMade(int selection, QueryID queryID)
return sendRequest(&pack);
}
void CCallback::recruitCreatures(const CGObjectInstance *obj, CreatureID ID, ui32 amount, si32 level/*=-1*/)
void CCallback::recruitCreatures(const CGDwelling *obj, const CArmedInstance * dst, CreatureID ID, ui32 amount, si32 level/*=-1*/)
{
if(player!=obj->tempOwner && obj->ID != Obj::WAR_MACHINE_FACTORY)
return;
RecruitCreatures pack(obj->id,ID,amount,level);
RecruitCreatures pack(obj->id, dst->id, ID, amount, level);
sendRequest(&pack);
}
@ -236,18 +236,13 @@ void CCallback::setFormation(const CGHeroInstance * hero, bool tight)
}
void CCallback::setSelection(const CArmedInstance * obj)
{
{/*
if(!player || obj->getOwner() != *player)
{
logGlobal->errorStream() << boost::format("Cannot set selection to the object that is not owned. Object owner is %s, callback player %s") % obj->getOwner() % player;
return;
}
SetSelection ss;
ss.player = *player;
ss.id = obj->id;
sendRequest(&(CPackForClient&)ss);
if(obj->getOwner() != *player)
{
// Cf. bug #1679 http://bugs.vcmi.eu/view.php?id=1679
@ -262,7 +257,7 @@ void CCallback::setSelection(const CArmedInstance * obj)
//nasty workaround. TODO: nice workaround
cl->gs->getPlayer(*player)->currentSelection = obj->id;
}
}*/
}
void CCallback::recruitHero(const CGObjectInstance *townOrTavern, const CGHeroInstance *hero)
@ -360,15 +355,13 @@ int3 CCallback::getGuardingCreaturePosition(int3 tile)
if (!gs->map->isInTheMap(tile))
return int3(-1,-1,-1);
validatePaths();
boost::unique_lock<boost::mutex> pathLock(cl->pathMx);
return gs->map->guardingCreaturePositions[tile.x][tile.y][tile.z];
}
void CCallback::recalculatePaths()
void CCallback::recalculatePaths(const CGHeroInstance * hero)
{
cl->calculatePaths(cl->IGameCallback::getSelectedHero(*player));
if (hero)
cl->calculatePaths(hero);
}
void CCallback::calculatePaths( const CGHeroInstance *hero, CPathsInfo &out, int3 src /*= int3(-1,-1,-1)*/, int movement /*= -1*/ )
@ -398,18 +391,6 @@ void CCallback::unregisterAllInterfaces()
cl->battleints.clear();
}
void CCallback::validatePaths()
{
ASSERT_IF_CALLED_WITH_PLAYER
const CGHeroInstance *h = cl->IGameCallback::getSelectedHero(*player);
if(h && ( cl->pathInfo->hero != h //wrong hero
|| cl->pathInfo->hpos != h->getPosition(false) //wrong hero position
|| !cl->pathInfo->isValid)) //paths invalidated by game event
{
recalculatePaths();
}
}
int CCallback::mergeOrSwapStacks(const CArmedInstance *s1, const CArmedInstance *s2, SlotID p1, SlotID p2)
{
if(s1->getCreature(p1) == s2->getCreature(p2))

View File

@ -54,7 +54,7 @@ public:
//town
virtual void recruitHero(const CGObjectInstance *townOrTavern, const CGHeroInstance *hero)=0;
virtual bool buildBuilding(const CGTownInstance *town, BuildingID buildingID)=0;
virtual void recruitCreatures(const CGObjectInstance *obj, CreatureID ID, ui32 amount, si32 level=-1)=0;
virtual void recruitCreatures(const CGDwelling *obj, const CArmedInstance * dst, CreatureID ID, ui32 amount, si32 level=-1)=0;
virtual bool upgradeCreature(const CArmedInstance *obj, SlotID stackPos, CreatureID newID=CreatureID::NONE)=0; //if newID==-1 then best possible upgrade will be made
virtual void swapGarrisonHero(const CGTownInstance *town)=0;
@ -117,7 +117,7 @@ public:
virtual int3 getGuardingCreaturePosition(int3 tile); //uses main, client pathfinder info
virtual void calculatePaths(const CGHeroInstance *hero, CPathsInfo &out, int3 src = int3(-1,-1,-1), int movement = -1);
virtual void recalculatePaths(); //updates main, client pathfinder info (should be called when moving hero is over)
virtual void recalculatePaths(const CGHeroInstance * hero); //updates main, client pathfinder info (should be called when moving hero is over)
//Set of metrhods that allows adding more interfaces for this player that'll receive game event call-ins.
void registerGameInterface(shared_ptr<IGameEventsReceiver> gameEvents);
@ -142,7 +142,7 @@ public:
//bool moveArtifact(const CStackInstance * stack, ui16 src , const CGHeroInstance * hero, ui16 dest); // TODO: unify classes
bool assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo);
bool buildBuilding(const CGTownInstance *town, BuildingID buildingID) override;
void recruitCreatures(const CGObjectInstance *obj, CreatureID ID, ui32 amount, si32 level=-1);
void recruitCreatures(const CGDwelling * obj, const CArmedInstance * dst, CreatureID ID, ui32 amount, si32 level=-1);
bool dismissCreature(const CArmedInstance *obj, SlotID stackPos);
bool upgradeCreature(const CArmedInstance *obj, SlotID stackPos, CreatureID newID=CreatureID::NONE) override;
void endTurn();

View File

@ -1464,7 +1464,7 @@ void CPlayerInterface::showRecruitmentDialog(const CGDwelling *dwelling, const C
{
EVENT_HANDLER_CALLED_BY_CLIENT;
waitWhileDialog();
auto recruitCb = [=](CreatureID id, int count){ LOCPLINT->cb->recruitCreatures(dwelling, id, count, -1); };
auto recruitCb = [=](CreatureID id, int count){ LOCPLINT->cb->recruitCreatures(dwelling, dst, id, count, -1); };
CRecruitmentWindow *cr = new CRecruitmentWindow(dwelling, level, dst, recruitCb);
GH.pushInt(cr);
}
@ -2185,6 +2185,13 @@ void CPlayerInterface::eraseCurrentPathOf( const CGHeroInstance * ho, bool check
adventureInt->updateMoveHero(ho, false);
}
void CPlayerInterface::updateCurrentHeroPath()
{
//TODO? lazy evaluation? paths now can get recalculated multiple times upon various game events
if (currentSelection)//if we have selected hero...
calculatePaths(currentSelection);
}
void CPlayerInterface::removeLastNodeFromPath(const CGHeroInstance *ho)
{
adventureInt->terrain.currentPath->nodes.erase(adventureInt->terrain.currentPath->nodes.end()-1);

View File

@ -86,6 +86,7 @@ enum
/// Central class for managing user interface logic
class CPlayerInterface : public CGameInterface, public ILockedUpdatable
{
const CGObjectInstance * currentSelection;
public:
bool observerInDuelMode;
@ -246,6 +247,8 @@ public:
void movementPxStep( const TryMoveHero &details, int i, const int3 &hp, const CGHeroInstance * ho );//performing step of movement
void finishMovement( const TryMoveHero &details, const int3 &hp, const CGHeroInstance * ho ); //finish movement
void eraseCurrentPathOf( const CGHeroInstance * ho, bool checkForExistanceOfPath = true );
void updateCurrentHeroPath();
void removeLastNodeFromPath(const CGHeroInstance *ho);
CGPath *getAndVerifyPath( const CGHeroInstance * h );
void acceptTurn(); //used during hot seat after your turn message is close

View File

@ -542,14 +542,6 @@ void CClient::handlePack( CPack * pack )
delete pack;
}
void CClient::updatePaths()
{
//TODO? lazy evaluation? paths now can get recalculated multiple times upon various game events
const CGHeroInstance *h = getSelectedHero();
if (h)//if we have selected hero...
calculatePaths(h);
}
void CClient::finishCampaign( shared_ptr<CCampaignState> camp )
{
}

View File

@ -160,7 +160,6 @@ public:
void proposeNextMission(shared_ptr<CCampaignState> camp);
void invalidatePaths(const CGHeroInstance *h = nullptr); //invalidates paths for hero h or for any hero if h is nullptr => they'll got recalculated when the next query comes
void calculatePaths(const CGHeroInstance *h);
void updatePaths(); //calls calculatePaths for same hero for which we previously calculated paths
bool terminate; // tell to terminate
boost::thread *connectionHandler; //thread running run() method

View File

@ -822,15 +822,6 @@ void PlayerMessage::applyCl(CClient *cl)
LOCPLINT->cingconsole->print(str.str());
}
void SetSelection::applyCl(CClient *cl)
{
const CGHeroInstance *h = cl->getHero(id);
if(!h)
return;
//CPackForClient::GS(cl)->calculatePaths(h, *cl->pathInfo);
}
void ShowInInfobox::applyCl(CClient *cl)
{
INTERFACE_CALL_IF_PRESENT(player,showComp, c, text.toString());
@ -914,7 +905,7 @@ void CenterView::applyCl(CClient *cl)
void NewObject::applyCl(CClient *cl)
{
cl->updatePaths();
INTERFACE_CALL_IF_PRESENT(player, updateCurrentHeroPath);
const CGObjectInstance *obj = cl->getObj(id);
CGI->mh->printObject(obj);

View File

@ -777,7 +777,7 @@ void CCastleBuildings::enterCastleGate()
void CCastleBuildings::enterDwelling(int level)
{
assert(level >= 0 && level < town->creatures.size());
auto recruitCb = [=](CreatureID id, int count){ LOCPLINT->cb->recruitCreatures(town, id, count, level); };
auto recruitCb = [=](CreatureID id, int count){ LOCPLINT->cb->recruitCreatures(town, town, id, count, level); };
GH.pushInt(new CRecruitmentWindow(town, level, town, recruitCb, -87));
}
@ -1066,7 +1066,7 @@ void CCreaInfo::clickLeft(tribool down, bool previousState)
if(previousState && (!down))
{
int offset = LOCPLINT->castleInt? (-87) : 0;
auto recruitCb = [=](CreatureID id, int count) { LOCPLINT->cb->recruitCreatures(town, id, count, level); };
auto recruitCb = [=](CreatureID id, int count) { LOCPLINT->cb->recruitCreatures(town, town, id, count, level); };
GH.pushInt(new CRecruitmentWindow(town, level, town, recruitCb, offset));
}
}

View File

@ -38,18 +38,6 @@ int CGameInfoCallback::getResource(PlayerColor Player, Res::ERes which) const
return p->resources[which];
}
const CGHeroInstance* CGameInfoCallback::getSelectedHero( PlayerColor Player ) const
{
const PlayerState *p = getPlayer(Player);
ERROR_RET_VAL_IF(!p, "No player info!", nullptr);
return getHero(p->currentSelection);
}
const CGHeroInstance* CGameInfoCallback::getSelectedHero() const
{
return getSelectedHero(gs->currentPlayer);
}
const PlayerSettings * CGameInfoCallback::getPlayerSettings(PlayerColor color) const
{
return &gs->scenarioOps->getIthPlayersSettings(color);

View File

@ -72,8 +72,6 @@ public:
bool getHeroInfo(const CGObjectInstance *hero, InfoAboutHero &dest) const;
int getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //when called during battle, takes into account creatures' spell cost reduction
int estimateSpellDamage(const CSpell * sp, const CGHeroInstance * hero) const; //estimates damage of given spell; returns 0 if spell causes no dmg
const CGHeroInstance* getSelectedHero(PlayerColor player) const; //nullptr if no hero is selected
const CGHeroInstance* getSelectedHero() const; //of current (active) player
const CArtifactInstance * getArtInstance(ArtifactInstanceID aid) const;
const CGObjectInstance * getObjInstance(ObjectInstanceID oid) const;

View File

@ -2965,7 +2965,7 @@ void CGPath::convert( ui8 mode )
}
PlayerState::PlayerState()
: color(-1), currentSelection(0xffffffff), enteredWinningCheatCode(0),
: color(-1), enteredWinningCheatCode(0),
enteredLosingCheatCode(0), status(EPlayerStatus::INGAME)
{
setNodeType(PLAYER);

View File

@ -164,7 +164,6 @@ struct DLL_LINKAGE PlayerState : public CBonusSystemNode
public:
PlayerColor color;
bool human; //true if human controlled player, false for AI
ObjectInstanceID currentSelection; //id of hero/town, 0xffffffff if none
TeamID team;
TResources resources;
std::set<ObjectInstanceID> visitedObjects; // as a std::set, since most accesses here will be from visited status checks
@ -183,7 +182,7 @@ public:
template <typename Handler> void serialize(Handler &h, const int version)
{
h & color & human & currentSelection & team & resources & status;
h & color & human & team & resources & status;
h & heroes & towns & availableHeroes & dwellings & visitedObjects;
h & getBonusList(); //FIXME FIXME FIXME
h & status & daysWithoutCastle;

View File

@ -1803,15 +1803,17 @@ struct RazeStructure : public BuildStructure
struct RecruitCreatures : public CPackForServer
{
RecruitCreatures(){};
RecruitCreatures(ObjectInstanceID TID, CreatureID CRID, si32 Amount, si32 Level):tid(TID),crid(CRID),amount(Amount),level(Level){};
ObjectInstanceID tid; //town id
RecruitCreatures(ObjectInstanceID TID, ObjectInstanceID DST, CreatureID CRID, si32 Amount, si32 Level):
tid(TID), dst(DST), crid(CRID), amount(Amount), level(Level){};
ObjectInstanceID tid; //dwelling id, or town
ObjectInstanceID dst; //destination ID, e.g. hero
CreatureID crid;
ui32 amount;//creature amount
si32 level;//dwelling level to buy from, -1 if any
bool applyGh(CGameHandler *gh);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & tid & crid & amount & level;
h & tid & dst & crid & amount & level;
}
};
@ -2049,23 +2051,6 @@ struct PlayerMessage : public CPackForClient, public CPackForServer //513
}
};
struct SetSelection : public CPackForClient, public CPackForServer //514
{
SetSelection(){CPackForClient::type = 514;};
DLL_LINKAGE void applyGs(CGameState *gs);
bool applyGh(CGameHandler *gh);
void applyCl(CClient *cl);
PlayerColor player;
ObjectInstanceID id;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & id & player;
}
};
struct CenterView : public CPackForClient//515
{
CenterView(){CPackForClient::type = 515;};

View File

@ -1658,11 +1658,6 @@ DLL_LINKAGE void YourTurn::applyGs( CGameState *gs )
}
}
DLL_LINKAGE void SetSelection::applyGs( CGameState *gs )
{
gs->getPlayer(player)->currentSelection = id;
}
DLL_LINKAGE Component::Component(const CStackBasicDescriptor &stack)
: id(CREATURE), subtype(stack.type->idNumber), val(stack.count), when(0)
{

View File

@ -298,7 +298,6 @@ void registerTypesClientPacks2(Serializer &s)
s.template registerType<CArtifactOperationPack, DisassembledArtifact>();
s.template registerType<CPackForClient, SaveGame>();
s.template registerType<CPackForClient, SetSelection>();
s.template registerType<CPackForClient, PlayerMessage>();
}
@ -332,7 +331,6 @@ void registerTypesServerPacks(Serializer &s)
s.template registerType<CPackForServer, CommitPackage>();
s.template registerType<CPackForServer, SaveGame>();
s.template registerType<CPackForServer, SetSelection>();
s.template registerType<CPackForServer, PlayerMessage>();
}

View File

@ -2562,7 +2562,7 @@ void CGameHandler::sendMessageToAll( const std::string &message )
sendToAllClients(&sm);
}
bool CGameHandler::recruitCreatures( ObjectInstanceID objid, CreatureID crid, ui32 cram, si32 fromLvl )
bool CGameHandler::recruitCreatures(ObjectInstanceID objid, ObjectInstanceID dstid, CreatureID crid, ui32 cram, si32 fromLvl )
{
const CGDwelling *dw = static_cast<const CGDwelling*>(gs->getObj(objid));
const CArmedInstance *dst = nullptr;
@ -2570,14 +2570,8 @@ bool CGameHandler::recruitCreatures( ObjectInstanceID objid, CreatureID crid, ui
bool warMachine = c->hasBonusOfType(Bonus::SIEGE_WEAPON);
//TODO: test for owning
if(dw->ID == Obj::TOWN)
dst = (static_cast<const CGTownInstance *>(dw))->getUpperArmy();
else if(dw->ID == Obj::CREATURE_GENERATOR1 || dw->ID == Obj::CREATURE_GENERATOR4
|| dw->ID == Obj::REFUGEE_CAMP) //advmap dwelling
dst = getHero(gs->getPlayer(dw->tempOwner)->currentSelection); //TODO: check if current hero is really visiting dwelling
else if(dw->ID == Obj::WAR_MACHINE_FACTORY)
dst = dynamic_cast<const CGHeroInstance *>(getTile(dw->visitablePos())->visitableObjects.back());
//TODO: check if dst can recruit objects (e.g. hero is actually visiting object, town and source are same, etc)
dst = dynamic_cast<const CArmedInstance*>(getObj(dstid));
assert(dw && dst);
@ -3785,7 +3779,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
}
void CGameHandler::playerMessage( PlayerColor player, const std::string &message )
{
{/*
bool cheated=true;
PlayerMessage temp_message(player, message);
@ -3934,7 +3928,7 @@ void CGameHandler::playerMessage( PlayerColor player, const std::string &message
SystemMessage temp_message(VLC->generaltexth->allTexts.at(260));
sendAndApply(&temp_message);
checkVictoryLossConditionsForPlayer(player);//Player enter win code or got required art\creature
}
}*/
}
void CGameHandler::handleSpellCasting( SpellID spellID, int spellLvl, BattleHex destination, ui8 casterSide, PlayerColor casterColor, const CGHeroInstance * caster, const CGHeroInstance * secHero,

View File

@ -224,7 +224,7 @@ public:
bool buySecSkill( const IMarket *m, const CGHeroInstance *h, SecondarySkill skill);
bool garrisonSwap(ObjectInstanceID tid);
bool upgradeCreature( ObjectInstanceID objid, SlotID pos, CreatureID upgID );
bool recruitCreatures(ObjectInstanceID objid, CreatureID crid, ui32 cram, si32 level);
bool recruitCreatures(ObjectInstanceID objid, ObjectInstanceID dst, CreatureID crid, ui32 cram, si32 level);
bool buildStructure(ObjectInstanceID tid, BuildingID bid, bool force=false);//force - for events: no cost, no checkings
bool razeStructure(ObjectInstanceID tid, BuildingID bid);
bool disbandCreature( ObjectInstanceID id, SlotID pos );

View File

@ -114,7 +114,7 @@ bool BuildStructure::applyGh( CGameHandler *gh )
bool RecruitCreatures::applyGh( CGameHandler *gh )
{
return gh->recruitCreatures(tid,crid,amount,level);
return gh->recruitCreatures(tid,dst,crid,amount,level);
}
bool UpgradeCreature::applyGh( CGameHandler *gh )
@ -288,15 +288,3 @@ bool PlayerMessage::applyGh( CGameHandler *gh )
gh->playerMessage(player,text);
return true;
}
bool SetSelection::applyGh( CGameHandler *gh )
{
ERROR_IF_NOT(player);
if(!gh->getObj(id))
{
logNetwork->errorStream() << "No such object...";
ERROR_AND_RETURN;
}
gh->sendAndApply(this);
return true;
}