Browse Source

[Refactoring] Unified SetResources NetPack API.

AlexVinS 9 years ago
parent
commit
86e33a4c45

+ 2 - 2
AI/VCAI/VCAI.cpp

@@ -502,9 +502,9 @@ void VCAI::requestRealized(PackageApplied *pa)
 	}
 	}
 }
 }
 
 
-void VCAI::receivedResource(int type, int val)
+void VCAI::receivedResource()
 {
 {
-	LOG_TRACE_PARAMS(logAi, "type '%i', val '%i'", type % val);
+	LOG_TRACE(logAi);
 	NET_EVENT_HANDLER;
 	NET_EVENT_HANDLER;
 }
 }
 
 

+ 3 - 3
AI/VCAI/VCAI.h

@@ -228,7 +228,7 @@ public:
 	virtual void advmapSpellCast(const CGHeroInstance * caster, int spellID) override;
 	virtual void advmapSpellCast(const CGHeroInstance * caster, int spellID) override;
 	virtual void showInfoDialog(const std::string &text, const std::vector<Component*> &components, int soundID) override;
 	virtual void showInfoDialog(const std::string &text, const std::vector<Component*> &components, int soundID) override;
 	virtual void requestRealized(PackageApplied *pa) override;
 	virtual void requestRealized(PackageApplied *pa) override;
-	virtual void receivedResource(int type, int val) override;
+	virtual void receivedResource() override;
 	virtual void stacksSwapped(const StackLocation &loc1, const StackLocation &loc2) override;
 	virtual void stacksSwapped(const StackLocation &loc1, const StackLocation &loc2) override;
 	virtual void objectRemoved(const CGObjectInstance *obj) override;
 	virtual void objectRemoved(const CGObjectInstance *obj) override;
 	virtual void showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor) override;
 	virtual void showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor) override;
@@ -239,7 +239,7 @@ public:
 	virtual void buildChanged(const CGTownInstance *town, BuildingID buildingID, int what) override;
 	virtual void buildChanged(const CGTownInstance *town, BuildingID buildingID, int what) override;
 	virtual void heroBonusChanged(const CGHeroInstance *hero, const Bonus &bonus, bool gain) override;
 	virtual void heroBonusChanged(const CGHeroInstance *hero, const Bonus &bonus, bool gain) override;
 	virtual void showMarketWindow(const IMarket *market, const CGHeroInstance *visitor) override;
 	virtual void showMarketWindow(const IMarket *market, const CGHeroInstance *visitor) override;
-	void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions) override;	
+	void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions) override;
 
 
 	virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) override;
 	virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) override;
 	virtual void battleEnd(const BattleResult *br) override;
 	virtual void battleEnd(const BattleResult *br) override;
@@ -315,7 +315,7 @@ public:
 	void requestSent(const CPackForServer *pack, int requestID) override;
 	void requestSent(const CPackForServer *pack, int requestID) override;
 	void answerQuery(QueryID queryID, int selection);
 	void answerQuery(QueryID queryID, int selection);
 	//special function that can be called ONLY from game events handling thread and will send request ASAP
 	//special function that can be called ONLY from game events handling thread and will send request ASAP
-	void requestActionASAP(std::function<void()> whatToDo); 
+	void requestActionASAP(std::function<void()> whatToDo);
 
 
 	template <typename Handler> void registerGoals(Handler &h)
 	template <typename Handler> void registerGoals(Handler &h)
 	{
 	{

+ 2 - 2
client/CPlayerInterface.cpp

@@ -507,11 +507,11 @@ void CPlayerInterface::heroMovePointsChanged(const CGHeroInstance * hero)
 	if (makingTurn && hero->tempOwner == playerID)
 	if (makingTurn && hero->tempOwner == playerID)
 		adventureInt->heroList.update(hero);
 		adventureInt->heroList.update(hero);
 }
 }
-void CPlayerInterface::receivedResource(int type, int val)
+void CPlayerInterface::receivedResource()
 {
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	if (CMarketplaceWindow *mw = dynamic_cast<CMarketplaceWindow *>(GH.topInt()))
 	if (CMarketplaceWindow *mw = dynamic_cast<CMarketplaceWindow *>(GH.topInt()))
-		mw->resourceChanged(type, val);
+		mw->resourceChanged();
 
 
 	GH.totalRedraw();
 	GH.totalRedraw();
 }
 }

+ 1 - 1
client/CPlayerInterface.h

@@ -160,7 +160,7 @@ public:
 	void heroManaPointsChanged(const CGHeroInstance * hero) override;
 	void heroManaPointsChanged(const CGHeroInstance * hero) override;
 	void heroMovePointsChanged(const CGHeroInstance * hero) override;
 	void heroMovePointsChanged(const CGHeroInstance * hero) override;
 	void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town) override;
 	void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town) override;
-	void receivedResource(int type, int val) override;
+	void receivedResource() override;
 	void showInfoDialog(const std::string &text, const std::vector<Component*> &components, int soundID) override;
 	void showInfoDialog(const std::string &text, const std::vector<Component*> &components, int soundID) override;
 	void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level) override;
 	void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level) override;
 	void showShipyardDialog(const IShipyard *obj) override; //obj may be town or shipyard;
 	void showShipyardDialog(const IShipyard *obj) override; //obj may be town or shipyard;

+ 2 - 6
client/NetPacksClient.cpp

@@ -108,12 +108,8 @@
 
 
 void SetResources::applyCl(CClient *cl)
 void SetResources::applyCl(CClient *cl)
 {
 {
-	INTERFACE_CALL_IF_PRESENT(player,receivedResource,-1,-1);
-}
-
-void SetResource::applyCl(CClient *cl)
-{
-	INTERFACE_CALL_IF_PRESENT(player,receivedResource,resid,val);
+	//todo: inform on actual resource set transfered
+	INTERFACE_CALL_IF_PRESENT(player,receivedResource);
 }
 }
 
 
 void SetPrimSkill::applyCl(CClient *cl)
 void SetPrimSkill::applyCl(CClient *cl)

+ 1 - 1
client/windows/CTradeWindow.cpp

@@ -1006,7 +1006,7 @@ Point CMarketplaceWindow::selectionOffset(bool Left) const
 	return Point(0,0);
 	return Point(0,0);
 }
 }
 
 
-void CMarketplaceWindow::resourceChanged(int type, int val)
+void CMarketplaceWindow::resourceChanged()
 {
 {
 	initSubs(true);
 	initSubs(true);
 }
 }

+ 1 - 1
client/windows/CTradeWindow.h

@@ -119,7 +119,7 @@ public:
 
 
 	void garrisonChanged() override; //removes creatures with count 0 from the list (apparently whole stack has been sold)
 	void garrisonChanged() override; //removes creatures with count 0 from the list (apparently whole stack has been sold)
 	void artifactsChanged(bool left) override;
 	void artifactsChanged(bool left) override;
-	void resourceChanged(int type, int val);
+	void resourceChanged();
 
 
 	void getBaseForPositions(EType type, int &dx, int &dy, int &x, int &y, int &h, int &w, bool Right, int &leftToRightOffset) const override;
 	void getBaseForPositions(EType type, int &dx, int &dy, int &x, int &y, int &h, int &w, bool Right, int &leftToRightOffset) const override;
 	void updateTraderText();
 	void updateTraderText();

+ 1 - 0
lib/GameConstants.h

@@ -35,6 +35,7 @@ namespace GameConstants
 
 
 	const int HERO_GOLD_COST = 2500;
 	const int HERO_GOLD_COST = 2500;
 	const int SPELLBOOK_GOLD_COST = 500;
 	const int SPELLBOOK_GOLD_COST = 500;
+	const int SKILL_GOLD_COST = 2000;
 	const int BATTLE_PENALTY_DISTANCE = 10; //if the distance is > than this, then shooting stack has distance penalty
 	const int BATTLE_PENALTY_DISTANCE = 10; //if the distance is > than this, then shooting stack has distance penalty
 	const int ARMY_SIZE = 7;
 	const int ARMY_SIZE = 7;
 	const int SKILL_PER_HERO=8;
 	const int SKILL_PER_HERO=8;

+ 1 - 1
lib/IGameEventsReceiver.h

@@ -104,7 +104,7 @@ public:
 	virtual void heroManaPointsChanged(const CGHeroInstance * hero){} //not called at the beginning of turn and after spell casts
 	virtual void heroManaPointsChanged(const CGHeroInstance * hero){} //not called at the beginning of turn and after spell casts
 	virtual void heroMovePointsChanged(const CGHeroInstance * hero){} //not called at the beginning of turn and after movement
 	virtual void heroMovePointsChanged(const CGHeroInstance * hero){} //not called at the beginning of turn and after movement
 	virtual void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town){};
 	virtual void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town){};
-	virtual void receivedResource(int type, int val){};
+	virtual void receivedResource(){};
 	virtual void showInfoDialog(const std::string &text, const std::vector<Component*> &components, int soundID){};
 	virtual void showInfoDialog(const std::string &text, const std::vector<Component*> &components, int soundID){};
 	virtual void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level){}
 	virtual void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level){}
 	virtual void showShipyardDialog(const IShipyard *obj){} //obj may be town or shipyard; state: 0 - can buid, 1 - lack of resources, 2 - dest tile is blocked, 3 - no water
 	virtual void showShipyardDialog(const IShipyard *obj){} //obj may be town or shipyard; state: 0 - can buid, 1 - lack of resources, 2 - dest tile is blocked, 3 - no water

+ 3 - 20
lib/NetPacks.h

@@ -167,36 +167,19 @@ struct YourTurn : public CPackForClient
 	}
 	}
 };
 };
 
 
-struct SetResource : public CPackForClient
-{
-	SetResource()
-		: resid(Res::GOLD), val(0)
-	{}
-	void applyCl(CClient *cl);
-	DLL_LINKAGE void applyGs(CGameState *gs);
-
-	PlayerColor player;
-	Res::ERes resid;
-	TResourceCap val;
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & player & resid & val;
-	}
-};
-
 struct SetResources : public CPackForClient
 struct SetResources : public CPackForClient
 {
 {
-	SetResources(){};
+	SetResources():abs(true){};
 	void applyCl(CClient *cl);
 	void applyCl(CClient *cl);
 	DLL_LINKAGE void applyGs(CGameState *gs);
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
 
+	bool abs; //false - changes by value; 1 - sets to value
 	PlayerColor player;
 	PlayerColor player;
 	TResources res; //res[resid] => res amount
 	TResources res; //res[resid] => res amount
 
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 	{
-		h & player & res;
+		h & abs & player & res;
 	}
 	}
 };
 };
 
 

+ 9 - 8
lib/NetPacksLib.cpp

@@ -37,17 +37,18 @@ std::ostream & operator<<(std::ostream & out, const CPack * pack)
 	return out << (pack? pack->toString() : "<nullptr>");
 	return out << (pack? pack->toString() : "<nullptr>");
 }
 }
 
 
-DLL_LINKAGE void SetResource::applyGs(CGameState *gs)
-{
-	assert(player < PlayerColor::PLAYER_LIMIT);
-	vstd::amax(val, 0); //new value must be >= 0
-	gs->getPlayer(player)->resources[resid] = val;
-}
-
 DLL_LINKAGE void SetResources::applyGs(CGameState *gs)
 DLL_LINKAGE void SetResources::applyGs(CGameState *gs)
 {
 {
 	assert(player < PlayerColor::PLAYER_LIMIT);
 	assert(player < PlayerColor::PLAYER_LIMIT);
-	gs->getPlayer(player)->resources = res;
+	if(abs)
+		gs->getPlayer(player)->resources = res;
+	else
+		gs->getPlayer(player)->resources += res;
+
+	//just ensure that player resources are not negative
+	//server is responsible to check if player can afford deal
+	//but events on server side are allowed to take more than player have
+	gs->getPlayer(player)->resources.positive();
 }
 }
 
 
 DLL_LINKAGE void SetPrimSkill::applyGs(CGameState *gs)
 DLL_LINKAGE void SetPrimSkill::applyGs(CGameState *gs)

+ 1 - 3
lib/mapObjects/CGPandoraBox.cpp

@@ -253,9 +253,7 @@ void CGPandoraBox::giveContentsAfterExp(const CGHeroInstance *h) const
 		cb->showInfoDialog(&iw);
 		cb->showInfoDialog(&iw);
 	}
 	}
 
 
-	for(int i=0; i<resources.size(); i++)
-		if(resources[i])
-			cb->giveResource(h->getOwner(),static_cast<Res::ERes>(i),resources[i]);
+	cb->giveResources(h->getOwner(), resources);
 
 
 	for(auto & elem : artifacts)
 	for(auto & elem : artifacts)
 		cb->giveHeroNewArtifact(h, VLC->arth->artifacts[elem],ArtifactPosition::FIRST_AVAILABLE);
 		cb->giveHeroNewArtifact(h, VLC->arth->artifacts[elem],ArtifactPosition::FIRST_AVAILABLE);

+ 0 - 1
lib/registerTypes/RegisterTypes.h

@@ -211,7 +211,6 @@ void registerTypesClientPacks1(Serializer &s)
 	s.template registerType<CPackForClient, SystemMessage>();
 	s.template registerType<CPackForClient, SystemMessage>();
 	s.template registerType<CPackForClient, PlayerBlocked>();
 	s.template registerType<CPackForClient, PlayerBlocked>();
 	s.template registerType<CPackForClient, YourTurn>();
 	s.template registerType<CPackForClient, YourTurn>();
-	s.template registerType<CPackForClient, SetResource>();
 	s.template registerType<CPackForClient, SetResources>();
 	s.template registerType<CPackForClient, SetResources>();
 	s.template registerType<CPackForClient, SetPrimSkill>();
 	s.template registerType<CPackForClient, SetPrimSkill>();
 	s.template registerType<CPackForClient, SetSecSkill>();
 	s.template registerType<CPackForClient, SetSecSkill>();

+ 26 - 85
server/CGameHandler.cpp

@@ -2226,17 +2226,18 @@ void CGameHandler::showTeleportDialog(TeleportDialog *iw)
 void CGameHandler::giveResource(PlayerColor player, Res::ERes which, int val) //TODO: cap according to Bersy's suggestion
 void CGameHandler::giveResource(PlayerColor player, Res::ERes which, int val) //TODO: cap according to Bersy's suggestion
 {
 {
 	if (!val) return; //don't waste time on empty call
 	if (!val) return; //don't waste time on empty call
-	SetResource sr;
-	sr.player = player;
-	sr.resid = which;
-	sr.val = getPlayer(player)->resources.at(which) + val;
-	sendAndApply(&sr);
+
+	TResources resources;
+	resources.at(which) = val;
+	giveResources(player, resources);
 }
 }
 
 
 void CGameHandler::giveResources(PlayerColor player, TResources resources)
 void CGameHandler::giveResources(PlayerColor player, TResources resources)
 {
 {
-	for (TResources::nziterator i(resources); i.valid(); i++)
-		giveResource(player, i->resType, i->resVal);
+	SetResources sr;
+	sr.abs = false;
+	sr.player = player;
+	sr.res = resources;
 }
 }
 
 
 void CGameHandler::giveCreatures(const CArmedInstance *obj, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove)
 void CGameHandler::giveCreatures(const CArmedInstance *obj, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove)
@@ -2549,12 +2550,6 @@ void CGameHandler::sendAndApply(CGarrisonOperationPack * info)
 	checkVictoryLossConditionsForAll();
 	checkVictoryLossConditionsForAll();
 }
 }
 
 
-void CGameHandler::sendAndApply(SetResource * info)
-{
-	sendAndApply(static_cast<CPackForClient*>(info));
-	checkVictoryLossConditionsForPlayer(info->player);
-}
-
 void CGameHandler::sendAndApply(SetResources * info)
 void CGameHandler::sendAndApply(SetResources * info)
 {
 {
 	sendAndApply(static_cast<CPackForClient*>(info));
 	sendAndApply(static_cast<CPackForClient*>(info));
@@ -2924,10 +2919,7 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID,
 	//Take cost
 	//Take cost
 	if (!force)
 	if (!force)
 	{
 	{
-		SetResources sr;
-		sr.player = t->tempOwner;
-		sr.res = getPlayer(t->tempOwner)->resources - requestedBuilding->resources;
-		sendAndApply(&sr);
+		giveResources(t->tempOwner, -requestedBuilding->resources);
 	}
 	}
 
 
 	//We know what has been built, appluy changes. Do this as final step to properly update town window
 	//We know what has been built, appluy changes. Do this as final step to properly update town window
@@ -3027,16 +3019,12 @@ bool CGameHandler::recruitCreatures(ObjectInstanceID objid, ObjectInstanceID dst
 	}
 	}
 
 
 	//recruit
 	//recruit
-	SetResources sr;
-	sr.player = dst->tempOwner;
-	sr.res = getPlayer(dst->tempOwner)->resources - (c->cost * cram);
+	giveResources(dst->tempOwner, -(c->cost * cram));
 
 
 	SetAvailableCreatures sac;
 	SetAvailableCreatures sac;
 	sac.tid = objid;
 	sac.tid = objid;
 	sac.creatures = dw->creatures;
 	sac.creatures = dw->creatures;
 	sac.creatures[level].first -= cram;
 	sac.creatures[level].first -= cram;
-
-	sendAndApply(&sr);
 	sendAndApply(&sac);
 	sendAndApply(&sac);
 
 
 	if (warMachine)
 	if (warMachine)
@@ -3094,10 +3082,7 @@ bool CGameHandler::upgradeCreature(ObjectInstanceID objid, SlotID pos, CreatureI
 		COMPLAIN_RET("Cannot upgrade, not enough resources!");
 		COMPLAIN_RET("Cannot upgrade, not enough resources!");
 
 
 	//take resources
 	//take resources
-	SetResources sr;
-	sr.player = player;
-	sr.res = p->resources - totalCost;
-	sendAndApply(&sr);
+	giveResources(player, -totalCost);
 
 
 	//upgrade creature
 	//upgrade creature
 	changeStackType(StackLocation(obj, pos), VLC->creh->creatures.at(upgID));
 	changeStackType(StackLocation(obj, pos), VLC->creh->creatures.at(upgID));
@@ -3351,12 +3336,7 @@ bool CGameHandler::buyArtifact(const IMarket *m, const CGHeroInstance *h, Res::E
 	if (getResource(h->tempOwner, rid) < b1)
 	if (getResource(h->tempOwner, rid) < b1)
 		COMPLAIN_RET("You can't afford to buy this artifact!");
 		COMPLAIN_RET("You can't afford to buy this artifact!");
 
 
-	SetResource sr;
-	sr.player = h->tempOwner;
-	sr.resid = rid;
-	sr.val = getResource(h->tempOwner, rid) - b1;
-	sendAndApply(&sr);
-
+	giveResource(h->tempOwner, rid, -b1);
 
 
 	SetAvailableArtifacts saa;
 	SetAvailableArtifacts saa;
 	if (m->o->ID == Obj::TOWN)
 	if (m->o->ID == Obj::TOWN)
@@ -3433,14 +3413,10 @@ bool CGameHandler::buySecSkill(const IMarket *m, const CGHeroInstance *h, Second
 	if (!vstd::contains(m->availableItemsIds(EMarketMode::RESOURCE_SKILL), skill))
 	if (!vstd::contains(m->availableItemsIds(EMarketMode::RESOURCE_SKILL), skill))
 		COMPLAIN_RET("That skill is unavailable!");
 		COMPLAIN_RET("That skill is unavailable!");
 
 
-	if (getResource(h->tempOwner, Res::GOLD) < 2000)//TODO: remove hardcoded resource\summ?
+	if (getResource(h->tempOwner, Res::GOLD) < GameConstants::SKILL_GOLD_COST)//TODO: remove hardcoded resource\summ?
 		COMPLAIN_RET("You can't afford to buy this skill");
 		COMPLAIN_RET("You can't afford to buy this skill");
 
 
-	SetResource sr;
-	sr.player = h->tempOwner;
-	sr.resid = Res::GOLD;
-	sr.val = getResource(h->tempOwner, Res::GOLD) - 2000;
-	sendAndApply(&sr);
+	giveResource(h->tempOwner, Res::GOLD, -GameConstants::SKILL_GOLD_COST);
 
 
 	changeSecSkill(h, skill, 1, true);
 	changeSecSkill(h, skill, 1, true);
 	return true;
 	return true;
@@ -3448,8 +3424,7 @@ bool CGameHandler::buySecSkill(const IMarket *m, const CGHeroInstance *h, Second
 
 
 bool CGameHandler::tradeResources(const IMarket *market, ui32 val, PlayerColor player, ui32 id1, ui32 id2)
 bool CGameHandler::tradeResources(const IMarket *market, ui32 val, PlayerColor player, ui32 id1, ui32 id2)
 {
 {
-	int r1 = getPlayer(player)->resources.at(id1),
-		r2 = getPlayer(player)->resources.at(id2);
+	TResourceCap r1 = getPlayer(player)->resources.at(id1);
 
 
 	vstd::amin(val, r1); //can't trade more resources than have
 	vstd::amin(val, r1); //can't trade more resources than have
 
 
@@ -3459,19 +3434,11 @@ bool CGameHandler::tradeResources(const IMarket *market, ui32 val, PlayerColor p
 
 
 	if (val%b1) //all offered units of resource should be used, if not -> somewhere in calculations must be an error
 	if (val%b1) //all offered units of resource should be used, if not -> somewhere in calculations must be an error
 	{
 	{
-		//TODO: complain?
-		assert(0);
+		COMPLAIN_RET("Invalid deal, not all offered units of resource were used.");
 	}
 	}
 
 
-	SetResource sr;
-	sr.player = player;
-	sr.resid = static_cast<Res::ERes>(id1);
-	sr.val = r1 - b1 * units;
-	sendAndApply(&sr);
-
-	sr.resid = static_cast<Res::ERes>(id2);
-	sr.val = r2 + b2 * units;
-	sendAndApply(&sr);
+	giveResource(player, static_cast<Res::ERes>(id1), - b1 * units);
+	giveResource(player, static_cast<Res::ERes>(id2), b2 * units);
 
 
 	return true;
 	return true;
 }
 }
@@ -3501,11 +3468,7 @@ bool CGameHandler::sellCreatures(ui32 count, const IMarket *market, const CGHero
 
 
 	changeStackCount(StackLocation(hero, slot), -count);
 	changeStackCount(StackLocation(hero, slot), -count);
 
 
-	SetResource sr;
-	sr.player = hero->tempOwner;
-	sr.resid = resourceID;
-	sr.val = getResource(hero->tempOwner, resourceID) + b2 * units;
-	sendAndApply(&sr);
+	giveResource(hero->tempOwner, resourceID, b2 * units);
 
 
 	return true;
 	return true;
 }
 }
@@ -3546,19 +3509,12 @@ bool CGameHandler::sendResources(ui32 val, PlayerColor player, Res::ERes r1, Pla
 		return false;
 		return false;
 	}
 	}
 
 
-	si32 curRes1 = getPlayer(player)->resources.at(r1),
-		 curRes2 = getPlayer(r2)->resources.at(r1);
-	val = std::min(si32(val),curRes1);
+	TResourceCap curRes1 = getPlayer(player)->resources.at(r1);
 
 
-	SetResource sr;
-	sr.player = player;
-	sr.resid = r1;
-	sr.val = curRes1 - val;
-	sendAndApply(&sr);
+	vstd::amin(val, curRes1);
 
 
-	sr.player = r2;
-	sr.val = curRes2 + val;
-	sendAndApply(&sr);
+	giveResource(player, r1, -val);
+	giveResource(r2, r1, val);
 
 
 	return true;
 	return true;
 }
 }
@@ -3651,11 +3607,7 @@ bool CGameHandler::hireHero(const CGObjectInstance *obj, ui8 hid, PlayerColor pl
 	sah.hid[!hid] = theOtherHero ? theOtherHero->subID : -1;
 	sah.hid[!hid] = theOtherHero ? theOtherHero->subID : -1;
 	sendAndApply(&sah);
 	sendAndApply(&sah);
 
 
-	SetResource sr;
-	sr.player = player;
-	sr.resid = Res::GOLD;
-	sr.val = p->resources.at(Res::GOLD) - GameConstants::HERO_GOLD_COST;
-	sendAndApply(&sr);
+	giveResource(player, Res::GOLD, -GameConstants::HERO_GOLD_COST);
 
 
 	if (t)
 	if (t)
 	{
 	{
@@ -4635,9 +4587,7 @@ void CGameHandler::handleTimeEvents()
 			)
 			)
 			{
 			{
 				//give resources
 				//give resources
-				SetResources sr;
-				sr.player = color;
-				sr.res = pinfo->resources + ev.resources;
+				giveResources(color, ev.resources);
 
 
 				//prepare dialog
 				//prepare dialog
 				InfoWindow iw;
 				InfoWindow iw;
@@ -4650,12 +4600,6 @@ void CGameHandler::handleTimeEvents()
 						iw.components.push_back(Component(Component::RESOURCE,i,ev.resources.at(i),0));
 						iw.components.push_back(Component(Component::RESOURCE,i,ev.resources.at(i),0));
 				}
 				}
 
 
-				if (iw.components.size())
-				{
-					sr.res.amax(0); // If removing too much resources, adjust the amount so the total doesn't become negative.
-					sendAndApply(&sr); //update player resources if changed
-				}
-
 				sendAndApply(&iw); //show dialog
 				sendAndApply(&iw); //show dialog
 			}
 			}
 		} //PLAYERS LOOP
 		} //PLAYERS LOOP
@@ -4916,10 +4860,7 @@ bool CGameHandler::buildBoat(ObjectInstanceID objid)
 	}
 	}
 
 
 	//take boat cost
 	//take boat cost
-	SetResources sr;
-	sr.player = playerID;
-	sr.res = (aviable - boatCost);
-	sendAndApply(&sr);
+	giveResources(playerID, -boatCost);
 
 
 	//create boat
 	//create boat
 	NewObject no;
 	NewObject no;

+ 0 - 2
server/CGameHandler.h

@@ -26,7 +26,6 @@ struct BattleAttack;
 struct BattleStackAttacked;
 struct BattleStackAttacked;
 struct CPack;
 struct CPack;
 struct Query;
 struct Query;
-struct SetResource;
 struct SetResources;
 struct SetResources;
 struct NewStructures;
 struct NewStructures;
 class CGHeroInstance;
 class CGHeroInstance;
@@ -250,7 +249,6 @@ public:
 	void sendAndApply(CPackForClient * info) override;
 	void sendAndApply(CPackForClient * info) override;
 	void applyAndSend(CPackForClient * info);
 	void applyAndSend(CPackForClient * info);
 	void sendAndApply(CGarrisonOperationPack * info);
 	void sendAndApply(CGarrisonOperationPack * info);
-	void sendAndApply(SetResource * info);
 	void sendAndApply(SetResources * info);
 	void sendAndApply(SetResources * info);
 	void sendAndApply(NewStructures * info);
 	void sendAndApply(NewStructures * info);