Some changes on the VisibilityUpdate message system, aimed at correcting recent OOS problems.

I still experience troubles with serialization tests but I played a few
games without OOS. At least these changes will help us to debug more
efficiently the remaining problems.

Fixes initialization of visibility data and update order for LoS-related
systems (territory borders, etc).
Also removes a C-like array and fixes a player ID shifting.

Refs #599

This was SVN commit r15563.
This commit is contained in:
Nicolas Auvray 2014-07-26 16:02:18 +00:00
parent e3888448c4
commit ea708e14bf

View File

@ -135,7 +135,7 @@ static std::map<entity_id_t, EntityParabolicRangeOutline> ParabolicRangesOutline
*/
struct EntityData
{
EntityData() : retainInFog(0), owner(-1), inWorld(0), flags(1) { }
EntityData() : visibilities(0), retainInFog(0), owner(-1), inWorld(0), flags(1) { }
entity_pos_t x, z;
entity_pos_t visionRange;
u32 visibilities; // 2-bit visibility, per player
@ -197,8 +197,8 @@ struct SerializeEntityData
serialize.NumberFixed_Unbounded("x", value.x);
serialize.NumberFixed_Unbounded("z", value.z);
serialize.NumberFixed_Unbounded("vision", value.visionRange);
serialize.NumberU8("retain in fog", value.retainInFog, 0, 1);
serialize.NumberU32_Unbounded("visibilities", value.visibilities);
serialize.NumberU8("retain in fog", value.retainInFog, 0, 1);
serialize.NumberI8_Unbounded("owner", value.owner);
serialize.NumberU8("in world", value.inWorld, 0, 1);
serialize.NumberU8_Unbounded("flags", value.flags);
@ -288,7 +288,7 @@ public:
// Cache for visibility tracking (not serialized)
i32 m_LosTilesPerSide;
bool* m_DirtyVisibility;
std::vector<u8> m_DirtyVisibility;
std::vector<std::set<entity_id_t> > m_LosTiles;
// List of entities that must be updated, regardless of the status of their tile
std::vector<entity_id_t> m_ModifiedEntities;
@ -341,14 +341,11 @@ public:
m_LosCircular = false;
m_TerrainVerticesPerSide = 0;
m_DirtyVisibility = NULL;
m_TerritoriesDirtyID = 0;
}
virtual void Deinit()
{
delete[] m_DirtyVisibility;
}
template<typename S>
@ -567,9 +564,9 @@ public:
case MT_Update:
{
m_DebugOverlayDirty = true;
UpdateVisibilityData();
UpdateTerritoriesLos();
ExecuteActiveQueries();
UpdateVisibilityData();
break;
}
case MT_RenderSubmit:
@ -674,8 +671,8 @@ public:
m_LosStateRevealed.clear();
m_LosStateRevealed.resize(m_TerrainVerticesPerSide*m_TerrainVerticesPerSide);
delete[] m_DirtyVisibility;
m_DirtyVisibility = new bool[m_LosTilesPerSide*m_LosTilesPerSide]();
m_DirtyVisibility.clear();
m_DirtyVisibility.resize(m_LosTilesPerSide*m_LosTilesPerSide, 1);
m_LosTiles.clear();
m_LosTiles.resize(m_LosTilesPerSide*m_LosTilesPerSide);
@ -1379,7 +1376,9 @@ public:
virtual ELosVisibility GetLosVisibility(CEntityHandle ent, player_id_t player, bool forceRetainInFog)
{
// (We can't use m_EntityData since this needs to handle LOCAL entities too)
// This function provides the real visibility of any entity (even local ones) at any time.
// The m_EntityData visibility is updated at most once per turn with this function's return value
// and must not be used for rendering
// Entities not with positions in the world are never visible
if (ent.GetId() == INVALID_ENTITY)
@ -1464,7 +1463,7 @@ public:
for (i32 n = 0; n < m_LosTilesPerSide*m_LosTilesPerSide; ++n)
{
if (m_DirtyVisibility[n])
if (m_DirtyVisibility[n] == 1)
{
for (std::set<entity_id_t>::iterator it = m_LosTiles[n].begin();
it != m_LosTiles[n].end();
@ -1472,7 +1471,7 @@ public:
{
UpdateVisibility(*it);
}
m_DirtyVisibility[n] = false;
m_DirtyVisibility[n] = 0;
}
}
@ -1491,14 +1490,14 @@ public:
for (player_id_t player = 1; player <= MAX_LOS_PLAYER_ID; ++player)
{
u8 oldVis = (itEnts->second.visibilities >> (2*player)) & 0x3;
u8 oldVis = (itEnts->second.visibilities >> (2*(player-1))) & 0x3;
u8 newVis = GetLosVisibility(itEnts->first, player, false);
if (oldVis != newVis)
{
CMessageVisibilityChanged msg(player, ent, oldVis, newVis);
GetSimContext().GetComponentManager().PostMessage(ent, msg);
itEnts->second.visibilities = (itEnts->second.visibilities & ~(0x3 << 2*player)) | (newVis << 2*player);
itEnts->second.visibilities = (itEnts->second.visibilities & ~(0x3 << 2*(player-1))) | (newVis << 2*(player-1));
}
}
}
@ -1650,7 +1649,7 @@ public:
explored += !(m_LosState[idx] & (LOS_EXPLORED << (2*(owner-1))));
m_LosState[idx] |= ((LOS_VISIBLE | LOS_EXPLORED) << (2*(owner-1)));
}
m_DirtyVisibility[(j/LOS_TILES_RATIO)*m_LosTilesPerSide + i/LOS_TILES_RATIO] = true;
m_DirtyVisibility[(j/LOS_TILES_RATIO)*m_LosTilesPerSide + i/LOS_TILES_RATIO] = 1;
}
ASSERT(counts[idx] < 65535);
@ -1680,7 +1679,7 @@ public:
m_LosState[idx] &= ~(LOS_VISIBLE << (2*(owner-1)));
i32 i = i0 + idx - idx0;
m_DirtyVisibility[(j/LOS_TILES_RATIO)*m_LosTilesPerSide + i/LOS_TILES_RATIO] = true;
m_DirtyVisibility[(j/LOS_TILES_RATIO)*m_LosTilesPerSide + i/LOS_TILES_RATIO] = 1;
}
}
}