1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-04-13 11:40:38 +02:00

- linux fix for BuildingHandler

- #584 should be fixed

- first part of ally support:
-- shared FoW
-- function Callback::getPlayerRelations for team checking
This commit is contained in:
Ivan Savenko 2010-08-03 12:34:06 +00:00
parent 54496ddee1
commit 3c868146a6
11 changed files with 112 additions and 41 deletions

View File

@ -315,7 +315,7 @@ bool CCallback::verifyPath(CPath * path, bool blockSea) const
std::vector< std::vector< std::vector<unsigned char> > > & CCallback::getVisibilityMap() const std::vector< std::vector< std::vector<unsigned char> > > & CCallback::getVisibilityMap() const
{ {
boost::shared_lock<boost::shared_mutex> lock(*gs->mx); boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
return gs->players[player].fogOfWarMap; return gs->getPlayerTeam(player)->fogOfWarMap;
} }

View File

@ -157,13 +157,13 @@ std::vector<std::string> CMessage::breakText( std::string text, size_t maxLineSi
else else
{ {
/* TODO: boost should have a nice method to do that. */ /* TODO: boost should have a nice method to do that. */
while(pos > 0 && while(pos > 0 && text[pos]>' ')
text[pos] != ' ' && /* text[pos] != ' ' &&
text[pos] != ',' && text[pos] != ',' &&
text[pos] != '.' && text[pos] != '.' &&
text[pos] != ';' && text[pos] != ';' &&
text[pos] != '!' && text[pos] != '!' &&
text[pos] != '?') text[pos] != '?')*/
pos --; pos --;
} }
if (pos > 0) if (pos > 0)

View File

@ -194,7 +194,7 @@ void RemoveObject::applyFirstCl( CClient *cl )
for(std::map<ui8, CGameInterface*>::iterator i=cl->playerint.begin();i!=cl->playerint.end();i++) for(std::map<ui8, CGameInterface*>::iterator i=cl->playerint.begin();i!=cl->playerint.end();i++)
{ {
if(i->first >= PLAYER_LIMIT) continue; if(i->first >= PLAYER_LIMIT) continue;
if(GS(cl)->players[i->first].fogOfWarMap[pos.x][pos.y][pos.z]) if(GS(cl)->getPlayerTeam(i->first)->fogOfWarMap[pos.x][pos.y][pos.z])
{ {
i->second->objectRemoved(o); i->second->objectRemoved(o);
} }
@ -216,8 +216,9 @@ void TryMoveHero::applyFirstCl( CClient *cl )
{ {
if(i->first >= PLAYER_LIMIT) if(i->first >= PLAYER_LIMIT)
continue; continue;
PlayerState &p = GS(cl)->players[i->first]; TeamState *t = GS(cl)->getPlayerTeam(i->first);
if((p.fogOfWarMap[start.x-1][start.y][start.z] || p.fogOfWarMap[end.x-1][end.y][end.z]) && p.human) if((t->fogOfWarMap[start.x-1][start.y][start.z] || t->fogOfWarMap[end.x-1][end.y][end.z])
&& GS(cl)->getPlayer(i->first)->human)
humanKnows = true; humanKnows = true;
} }
@ -250,8 +251,8 @@ void TryMoveHero::applyCl( CClient *cl )
for(std::map<ui8, CGameInterface*>::iterator i=cl->playerint.begin();i!=cl->playerint.end();i++) for(std::map<ui8, CGameInterface*>::iterator i=cl->playerint.begin();i!=cl->playerint.end();i++)
{ {
if(i->first >= PLAYER_LIMIT) continue; if(i->first >= PLAYER_LIMIT) continue;
PlayerState &p = GS(cl)->players[i->first]; TeamState *t = GS(cl)->getPlayerTeam(i->first);
if(p.fogOfWarMap[start.x-1][start.y][start.z] || p.fogOfWarMap[end.x-1][end.y][end.z]) if(t->fogOfWarMap[start.x-1][start.y][start.z] || t->fogOfWarMap[end.x-1][end.y][end.z])
{ {
i->second->heroMoved(*this); i->second->heroMoved(*this);
} }
@ -786,7 +787,7 @@ void NewObject::applyCl(CClient *cl)
{ {
//TODO: check if any covered tile is visible //TODO: check if any covered tile is visible
if(i->first >= PLAYER_LIMIT) continue; if(i->first >= PLAYER_LIMIT) continue;
if(GS(cl)->players[i->first].fogOfWarMap[obj->pos.x][obj->pos.y][obj->pos.z]) if(GS(cl)->getPlayerTeam(i->first)->fogOfWarMap[obj->pos.x][obj->pos.y][obj->pos.z])
{ {
i->second->newObject(obj); i->second->newObject(obj);
} }

View File

@ -145,7 +145,7 @@ void CBuildingHandler::loadBuildings()
} }
//loading ERMU to picture //loading ERMU to picture
std::ifstream etp("config/ERMU_to_picture.txt"); std::ifstream etp(DATA_DIR "/config/ERMU_to_picture.txt");
assert(etp.is_open()); assert(etp.is_open());

View File

@ -435,9 +435,9 @@ void CGObjectInstance::getSightTiles(std::set<int3> &tiles) const //returns refe
} }
void CGObjectInstance::hideTiles(int ourplayer, int radius) const void CGObjectInstance::hideTiles(int ourplayer, int radius) const
{ {
for (std::map<ui8, PlayerState>::iterator i = cb->gameState()->players.begin(); i != cb->gameState()->players.end(); i++) for (std::map<ui8, TeamState>::iterator i = cb->gameState()->teams.begin(); i != cb->gameState()->teams.end(); i++)
{ {
if (ourplayer != i->first && i->second.status == PlayerState::INGAME) //TODO: team support if ( !vstd::contains(i->second.players, ourplayer )/* && i->second.status == PlayerState::INGAME*/)
{ {
FoWChange fw; FoWChange fw;
fw.mode = 0; fw.mode = 0;
@ -923,8 +923,7 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
if (ID == HEROI_TYPE) //hero if (ID == HEROI_TYPE) //hero
{ {
//TODO: check for allies if( cb->getPlayerRelations(tempOwner, h->tempOwner)) //our or ally hero
if(tempOwner == h->tempOwner) //our hero
{ {
//exchange //exchange
cb->heroExchange(id, h->id); cb->heroExchange(id, h->id);

View File

@ -1394,6 +1394,8 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
std::pair<int,PlayerState> ins(it->first,PlayerState()); std::pair<int,PlayerState> ins(it->first,PlayerState());
ins.second.color=ins.first; ins.second.color=ins.first;
ins.second.human = it->second.human; ins.second.human = it->second.human;
ins.second.team = map->players[ins.first].team;
teams[ins.second.team].players.insert(ins.first);
players.insert(ins); players.insert(ins);
} }
@ -1608,8 +1610,8 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
} }
} }
/*************************FOG**OF**WAR******************************************/ /*************************FOG**OF**WAR******************************************/
for(std::map<ui8, PlayerState>::iterator k=players.begin(); k!=players.end(); ++k) for(std::map<ui8, TeamState>::iterator k=teams.begin(); k!=teams.end(); ++k)
{ {
k->second.fogOfWarMap.resize(map->width); k->second.fogOfWarMap.resize(map->width);
for(int g=0; g<map->width; ++g) for(int g=0; g<map->width; ++g)
@ -1626,7 +1628,7 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
BOOST_FOREACH(CGObjectInstance *obj, map->objects) BOOST_FOREACH(CGObjectInstance *obj, map->objects)
{ {
if(obj->tempOwner != k->first) continue; //not a flagged object if( !vstd::contains(k->second.players, obj->tempOwner)) continue; //not a flagged object
std::set<int3> tiles; std::set<int3> tiles;
obj->getSightTiles(tiles); obj->getSightTiles(tiles);
@ -1635,7 +1637,10 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
k->second.fogOfWarMap[tile.x][tile.y][tile.z] = 1; k->second.fogOfWarMap[tile.x][tile.y][tile.z] = 1;
} }
} }
}
for(std::map<ui8, PlayerState>::iterator k=players.begin(); k!=players.end(); ++k)
{
//starting bonus //starting bonus
if(si->playerInfos[k->first].bonus==PlayerSettings::brandom) if(si->playerInfos[k->first].bonus==PlayerSettings::brandom)
si->playerInfos[k->first].bonus = ran()%3; si->playerInfos[k->first].bonus = ran()%3;
@ -2225,6 +2230,28 @@ void CGameState::apply(CPack *pack)
applierGs->apps[typ]->applyOnGS(this,pack); applierGs->apps[typ]->applyOnGS(this,pack);
} }
TeamState *CGameState::getTeam(ui8 teamID)
{
if(vstd::contains(teams,teamID))
{
return &teams[teamID];
}
else
{
tlog2 << "Warning: Cannot find info for team " << int(teamID) << std::endl;
return NULL;
}
}
TeamState *CGameState::getPlayerTeam(ui8 color)
{
PlayerState * ps = getPlayer(color);
if (ps)
return getTeam(ps->team);
return NULL;
}
PlayerState * CGameState::getPlayer( ui8 color, bool verbose ) PlayerState * CGameState::getPlayer( ui8 color, bool verbose )
{ {
if(vstd::contains(players,color)) if(vstd::contains(players,color))
@ -2244,6 +2271,17 @@ const PlayerState * CGameState::getPlayer( ui8 color, bool verbose ) const
return (const_cast<CGameState *>(this))->getPlayer(color, verbose); return (const_cast<CGameState *>(this))->getPlayer(color, verbose);
} }
const TeamState * CGameState::getTeam( ui8 teamID ) const
{
return (const_cast<CGameState *>(this))->getTeam(teamID);
}
const TeamState * CGameState::getPlayerTeam( ui8 teamID ) const
{
return (const_cast<CGameState *>(this))->getPlayerTeam(teamID);
}
bool CGameState::getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath &ret) bool CGameState::getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath &ret)
{ {
if(!map->isInTheMap(src) || !map->isInTheMap(dest)) //check input if(!map->isInTheMap(src) || !map->isInTheMap(dest)) //check input
@ -2261,7 +2299,7 @@ bool CGameState::getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath
// else // else
// blockLandSea = boost::logic::indeterminate; // blockLandSea = boost::logic::indeterminate;
const std::vector<std::vector<std::vector<ui8> > > &FoW = getPlayer(hero->tempOwner)->fogOfWarMap; const std::vector<std::vector<std::vector<ui8> > > &FoW = getPlayerTeam(hero->tempOwner)->fogOfWarMap;
//graph initialization //graph initialization
std::vector< std::vector<CPathNode> > graph; std::vector< std::vector<CPathNode> > graph;
@ -2407,7 +2445,7 @@ void CGameState::calculatePaths(const CGHeroInstance *hero, CPathsInfo &out, int
else else
onLand = boost::logic::indeterminate; onLand = boost::logic::indeterminate;
const std::vector<std::vector<std::vector<ui8> > > &FoW = getPlayer(hero->tempOwner)->fogOfWarMap; const std::vector<std::vector<std::vector<ui8> > > &FoW = getPlayerTeam(hero->tempOwner)->fogOfWarMap;
bool flying = hero->hasBonusOfType(Bonus::FLYING_MOVEMENT); bool flying = hero->hasBonusOfType(Bonus::FLYING_MOVEMENT);
bool waterWalk = hero->hasBonusOfType(Bonus::WATER_WALKING); bool waterWalk = hero->hasBonusOfType(Bonus::WATER_WALKING);
@ -2654,7 +2692,7 @@ bool CGameState::isVisible(int3 pos, int player)
{ {
if(player == 255) //neutral player if(player == 255) //neutral player
return false; return false;
return players[player].fogOfWarMap[pos.x][pos.y][pos.z]; return getPlayerTeam(player)->fogOfWarMap[pos.x][pos.y][pos.z];
} }
bool CGameState::isVisible( const CGObjectInstance *obj, int player ) bool CGameState::isVisible( const CGObjectInstance *obj, int player )
@ -3434,9 +3472,9 @@ ui8 CGameState::checkForStandardWin() const
{ {
//first player remaining ingame - candidate for victory //first player remaining ingame - candidate for victory
supposedWinner = i->second.color; supposedWinner = i->second.color;
winnerTeam = map->players[supposedWinner].team; winnerTeam = i->second.team;
} }
else if(winnerTeam != map->players[i->second.color].team) else if(winnerTeam != i->second.team)
{ {
//current candidate has enemy remaining in game -> no vicotry //current candidate has enemy remaining in game -> no vicotry
return 255; return 255;

View File

@ -120,7 +120,8 @@ public:
ui8 color; ui8 color;
ui8 human; //true if human controlled player, false for AI ui8 human; //true if human controlled player, false for AI
ui32 currentSelection; //id of hero/town, 0xffffffff if none ui32 currentSelection; //id of hero/town, 0xffffffff if none
std::vector<std::vector<std::vector<ui8> > > fogOfWarMap; //true - visible, false - hidden ui8 team;
//std::vector<std::vector<std::vector<ui8> > > * fogOfWarMap; //pointer to team's fog of war
std::vector<si32> resources; std::vector<si32> resources;
std::vector<CGHeroInstance *> heroes; std::vector<CGHeroInstance *> heroes;
std::vector<CGTownInstance *> towns; std::vector<CGTownInstance *> towns;
@ -139,13 +140,29 @@ public:
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
h & color & human & currentSelection & fogOfWarMap & resources & status; h & color & human & currentSelection & team & resources & status;
h & heroes & towns & availableHeroes & dwellings & bonuses & status & daysWithoutCastle; h & heroes & towns & availableHeroes & dwellings & bonuses & status & daysWithoutCastle;
h & enteredLosingCheatCode & enteredWinningCheatCode; h & enteredLosingCheatCode & enteredWinningCheatCode;
h & static_cast<CBonusSystemNode&>(*this); h & static_cast<CBonusSystemNode&>(*this);
} }
}; };
struct DLL_EXPORT TeamState : public CBonusSystemNode
{
public:
std::set<ui8> players; // members of this team
std::vector<std::vector<std::vector<ui8> > > fogOfWarMap; //true - visible, false - hidden
//TeamState();
template <typename Handler> void serialize(Handler &h, const int version)
{
h & players & fogOfWarMap;
h & static_cast<CBonusSystemNode&>(*this);
}
};
struct DLL_EXPORT CObstacleInstance struct DLL_EXPORT CObstacleInstance
{ {
int uniqueID; int uniqueID;
@ -384,6 +401,7 @@ public:
ui32 day; //total number of days in game ui32 day; //total number of days in game
Mapa * map; Mapa * map;
std::map<ui8, PlayerState> players; //ID <-> player state std::map<ui8, PlayerState> players; //ID <-> player state
std::map<ui8, TeamState> teams; //ID <-> team state
std::map<int, CGDefInfo*> villages, forts, capitols; //def-info for town graphics std::map<int, CGDefInfo*> villages, forts, capitols; //def-info for town graphics
CBonusSystemNode globalEffects; CBonusSystemNode globalEffects;
@ -402,7 +420,11 @@ public:
boost::shared_mutex *mx; boost::shared_mutex *mx;
PlayerState *getPlayer(ui8 color, bool verbose = true); PlayerState *getPlayer(ui8 color, bool verbose = true);
TeamState *getTeam(ui8 teamID);//get team by team ID
TeamState *getPlayerTeam(ui8 color);// get team by player color
const PlayerState *getPlayer(ui8 color, bool verbose = true) const; const PlayerState *getPlayer(ui8 color, bool verbose = true) const;
const TeamState *getTeam(ui8 teamID) const;
const TeamState *getPlayerTeam(ui8 color) const;
void init(StartInfo * si, ui32 checksum, int Seed); void init(StartInfo * si, ui32 checksum, int Seed);
void loadTownDInfos(); void loadTownDInfos();
void randomizeObject(CGObjectInstance *cur); void randomizeObject(CGObjectInstance *cur);

View File

@ -107,7 +107,7 @@ void IGameCallback::getTilesInRange( std::set<int3> &tiles, int3 pos, int radiou
getAllTiles (tiles, player, -1, 0); getAllTiles (tiles, player, -1, 0);
else else
{ {
PlayerState * plr = &gs->players.find(player)->second; const TeamState * team = gs->getPlayerTeam(player);
for (int xd = std::max<int>(pos.x - radious , 0); xd <= std::min<int>(pos.x + radious, gs->map->width - 1); xd++) for (int xd = std::max<int>(pos.x - radious , 0); xd <= std::min<int>(pos.x + radious, gs->map->width - 1); xd++)
{ {
for (int yd = std::max<int>(pos.y - radious, 0); yd <= std::min<int>(pos.y + radious, gs->map->height - 1); yd++) for (int yd = std::max<int>(pos.y - radious, 0); yd <= std::min<int>(pos.y + radious, gs->map->height - 1); yd++)
@ -116,8 +116,8 @@ void IGameCallback::getTilesInRange( std::set<int3> &tiles, int3 pos, int radiou
if(distance <= radious) if(distance <= radious)
{ {
if(player < 0 if(player < 0
|| (mode == 1 && plr->fogOfWarMap[xd][yd][pos.z]==0) || (mode == 1 && team->fogOfWarMap[xd][yd][pos.z]==0)
|| (mode == -1 && plr->fogOfWarMap[xd][yd][pos.z]==1) || (mode == -1 && team->fogOfWarMap[xd][yd][pos.z]==1)
) )
tiles.insert(int3(xd,yd,pos.z)); tiles.insert(int3(xd,yd,pos.z));
} }
@ -239,6 +239,18 @@ const PlayerState * IGameCallback::getPlayerState( int color )
return gs->getPlayer(color, false); return gs->getPlayer(color, false);
} }
int IGameCallback::getPlayerRelations( ui8 color1, ui8 color2 )
{
if ( color1 == color2 )
return 2;
if ( color1 == 255 || color2 == 255)
return 0;
const TeamState * ts = gs->getPlayerTeam(color1);
if (ts && vstd::contains(ts->players, color2))
return 1;
return 0;
}
const CTown * IGameCallback::getNativeTown(int color) const CTown * IGameCallback::getNativeTown(int color)
{ {
return &VLC->townh->towns[gs->scenarioOps->getIthPlayersSettings(color).castle]; return &VLC->townh->towns[gs->scenarioOps->getIthPlayersSettings(color).castle];

View File

@ -68,6 +68,7 @@ public:
virtual int3 getMapSize(); //returns size of the map virtual int3 getMapSize(); //returns size of the map
virtual TerrainTile * getTile(int3 pos); virtual TerrainTile * getTile(int3 pos);
virtual const PlayerState * getPlayerState(int color); virtual const PlayerState * getPlayerState(int color);
virtual int getPlayerRelations(ui8 color1, ui8 color2);// -1 = enemy, 0 = neutral, 1 = ally, 2 = same player
virtual const CTown *getNativeTown(int color); virtual const CTown *getNativeTown(int color);
//do sth //do sth

View File

@ -143,14 +143,15 @@ DLL_EXPORT void SetMovePoints::applyGs( CGameState *gs )
DLL_EXPORT void FoWChange::applyGs( CGameState *gs ) DLL_EXPORT void FoWChange::applyGs( CGameState *gs )
{ {
BOOST_FOREACH(int3 t, tiles) TeamState * team = gs->getPlayerTeam(player);
gs->getPlayer(player)->fogOfWarMap[t.x][t.y][t.z] = mode; BOOST_FOREACH(int3 t, tiles)
team->fogOfWarMap[t.x][t.y][t.z] = mode;
if (mode == 0) //do not hide too much if (mode == 0) //do not hide too much
{ {
std::set<int3> tilesRevealed; std::set<int3> tilesRevealed;
for (size_t i = 0; i < gs->map->objects.size(); i++) for (size_t i = 0; i < gs->map->objects.size(); i++)
{ {
if(gs->map->objects[i] && gs->map->objects[i]->tempOwner == player) //check owned observators if (gs->map->objects[i])
{ {
switch(gs->map->objects[i]->ID) switch(gs->map->objects[i]->ID)
{ {
@ -158,13 +159,14 @@ DLL_EXPORT void FoWChange::applyGs( CGameState *gs )
case 53://mine case 53://mine
case 98://town case 98://town
case 220: case 220:
gs->map->objects[i]->getSightTiles(tilesRevealed); if(vstd::contains(team->players, player)) //check owned observators
gs->map->objects[i]->getSightTiles(tilesRevealed);
break; break;
} }
} }
} }
BOOST_FOREACH(int3 t, tilesRevealed) //probably not the most optimal solution ever BOOST_FOREACH(int3 t, tilesRevealed) //probably not the most optimal solution ever
gs->getPlayer(player)->fogOfWarMap[t.x][t.y][t.z] = 1; team->fogOfWarMap[t.x][t.y][t.z] = 1;
} }
} }
DLL_EXPORT void SetAvailableHeroes::applyGs( CGameState *gs ) DLL_EXPORT void SetAvailableHeroes::applyGs( CGameState *gs )
@ -377,7 +379,7 @@ void TryMoveHero::applyGs( CGameState *gs )
} }
BOOST_FOREACH(int3 t, fowRevealed) BOOST_FOREACH(int3 t, fowRevealed)
gs->getPlayer(h->getOwner())->fogOfWarMap[t.x][t.y][t.z] = 1; gs->getPlayerTeam(h->getOwner())->fogOfWarMap[t.x][t.y][t.z] = 1;
} }
DLL_EXPORT void SetGarrisons::applyGs( CGameState *gs ) DLL_EXPORT void SetGarrisons::applyGs( CGameState *gs )

View File

@ -1888,12 +1888,11 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
{ {
CGHeroInstance *dh = static_cast<CGHeroInstance *>(obj); CGHeroInstance *dh = static_cast<CGHeroInstance *>(obj);
if(obj->tempOwner==h->tempOwner) if( getPlayerRelations(dh->tempOwner, h->tempOwner))
{ {
heroExchange(dh->id, h->id); heroExchange(dh->id, h->id);
return true; return true;
} }
//TODO: check for ally
startBattleI(h, dh); startBattleI(h, dh);
return true; return true;
} }
@ -3357,10 +3356,8 @@ bool CGameHandler::transformInUndead(const IMarket *market, const CGHeroInstance
} }
if (!army) if (!army)
COMPLAIN_RET("Incorrect call to transform in undead!"); COMPLAIN_RET("Incorrect call to transform in undead!");
tlog1<<"test2\n";
if(!vstd::contains(army->Slots(), slot)) if(!vstd::contains(army->Slots(), slot))
COMPLAIN_RET("Army doesn't have any creature in that slot!"); COMPLAIN_RET("Army doesn't have any creature in that slot!");
tlog1<<"test3\n";
const CStackInstance &s = army->getStack(slot); const CStackInstance &s = army->getStack(slot);
int resCreature;//resulting creature - bone dragons or skeletons int resCreature;//resulting creature - bone dragons or skeletons
@ -3368,7 +3365,6 @@ bool CGameHandler::transformInUndead(const IMarket *market, const CGHeroInstance
resCreature = 68; resCreature = 68;
else else
resCreature = 56; resCreature = 56;
tlog1<<"test4\n";
SetGarrisons sg; SetGarrisons sg;
sg.garrs[army->id] = army->getArmy(); sg.garrs[army->id] = army->getArmy();
sg.garrs[army->id].setCreature(slot, resCreature, s.count); sg.garrs[army->id].setCreature(slot, resCreature, s.count);
@ -3913,7 +3909,7 @@ void CGameHandler::playerMessage( ui8 player, const std::string &message )
for(int i=0;i<gs->map->width;i++) for(int i=0;i<gs->map->width;i++)
for(int j=0;j<gs->map->height;j++) for(int j=0;j<gs->map->height;j++)
for(int k=0;k<gs->map->twoLevel+1;k++) for(int k=0;k<gs->map->twoLevel+1;k++)
if(!gs->getPlayer(fc.player)->fogOfWarMap[i][j][k]) if(!gs->getPlayerTeam(fc.player)->fogOfWarMap[i][j][k])
fc.tiles.insert(int3(i,j,k)); fc.tiles.insert(int3(i,j,k));
sendAndApply(&fc); sendAndApply(&fc);
} }