1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-25 22:42:04 +02:00

[Refactoring] Unified SetResources NetPack API.

This commit is contained in:
AlexVinS
2016-11-26 15:14:43 +03:00
parent a497824288
commit 86e33a4c45
15 changed files with 53 additions and 136 deletions

View File

@@ -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;
} }

View File

@@ -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)
{ {

View File

@@ -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();
} }

View File

@@ -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;

View File

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

View File

@@ -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);
} }

View File

@@ -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();

View File

@@ -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;

View File

@@ -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

View File

@@ -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;
} }
}; };

View File

@@ -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)

View File

@@ -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++) cb->giveResources(h->getOwner(), resources);
if(resources[i])
cb->giveResource(h->getOwner(),static_cast<Res::ERes>(i),resources[i]);
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);

View File

@@ -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>();

View File

@@ -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; TResources resources;
sr.resid = which; resources.at(which) = val;
sr.val = getPlayer(player)->resources.at(which) + val; giveResources(player, resources);
sendAndApply(&sr);
} }
void CGameHandler::giveResources(PlayerColor player, TResources resources) void CGameHandler::giveResources(PlayerColor player, TResources resources)
{ {
for (TResources::nziterator i(resources); i.valid(); i++) SetResources sr;
giveResource(player, i->resType, i->resVal); 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; giveResources(t->tempOwner, -requestedBuilding->resources);
sr.player = t->tempOwner;
sr.res = getPlayer(t->tempOwner)->resources - requestedBuilding->resources;
sendAndApply(&sr);
} }
//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; giveResources(dst->tempOwner, -(c->cost * cram));
sr.player = dst->tempOwner;
sr.res = getPlayer(dst->tempOwner)->resources - (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; giveResources(player, -totalCost);
sr.player = player;
sr.res = p->resources - totalCost;
sendAndApply(&sr);
//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; giveResource(h->tempOwner, rid, -b1);
sr.player = h->tempOwner;
sr.resid = rid;
sr.val = getResource(h->tempOwner, rid) - b1;
sendAndApply(&sr);
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; giveResource(h->tempOwner, Res::GOLD, -GameConstants::SKILL_GOLD_COST);
sr.player = h->tempOwner;
sr.resid = Res::GOLD;
sr.val = getResource(h->tempOwner, Res::GOLD) - 2000;
sendAndApply(&sr);
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), TResourceCap r1 = getPlayer(player)->resources.at(id1);
r2 = getPlayer(player)->resources.at(id2);
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? COMPLAIN_RET("Invalid deal, not all offered units of resource were used.");
assert(0);
} }
SetResource sr; giveResource(player, static_cast<Res::ERes>(id1), - b1 * units);
sr.player = player; giveResource(player, static_cast<Res::ERes>(id2), b2 * units);
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);
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; giveResource(hero->tempOwner, resourceID, b2 * units);
sr.player = hero->tempOwner;
sr.resid = resourceID;
sr.val = getResource(hero->tempOwner, resourceID) + b2 * units;
sendAndApply(&sr);
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), TResourceCap curRes1 = getPlayer(player)->resources.at(r1);
curRes2 = getPlayer(r2)->resources.at(r1);
val = std::min(si32(val),curRes1);
SetResource sr; vstd::amin(val, curRes1);
sr.player = player;
sr.resid = r1;
sr.val = curRes1 - val;
sendAndApply(&sr);
sr.player = r2; giveResource(player, r1, -val);
sr.val = curRes2 + val; giveResource(r2, r1, val);
sendAndApply(&sr);
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; giveResource(player, Res::GOLD, -GameConstants::HERO_GOLD_COST);
sr.player = player;
sr.resid = Res::GOLD;
sr.val = p->resources.at(Res::GOLD) - GameConstants::HERO_GOLD_COST;
sendAndApply(&sr);
if (t) if (t)
{ {
@@ -4635,9 +4587,7 @@ void CGameHandler::handleTimeEvents()
) )
{ {
//give resources //give resources
SetResources sr; giveResources(color, ev.resources);
sr.player = color;
sr.res = pinfo->resources + 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; giveResources(playerID, -boatCost);
sr.player = playerID;
sr.res = (aviable - boatCost);
sendAndApply(&sr);
//create boat //create boat
NewObject no; NewObject no;

View File

@@ -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);