Skip to content

Commit

Permalink
Fix quadField bug
Browse files Browse the repository at this point in the history
multiple tempQuads vectors were needed in the same time but only one existed.
To prevent similar occurence in the future a mechanism of ExclusiveVectors and QuadFieldQuery was added.
This makes sure every vector is exclusive to the query as long as it is alive.
  • Loading branch information
ashdnazg committed Sep 13, 2017
1 parent b35cace commit 13517d8
Show file tree
Hide file tree
Showing 21 changed files with 348 additions and 238 deletions.
23 changes: 12 additions & 11 deletions rts/ExternalAI/AICallback.cpp
Expand Up @@ -897,9 +897,10 @@ int CAICallback::GetEnemyUnits(int* unitIds, const float3& pos, float radius,
int unitIds_max)
{
verify();
const std::vector<CUnit*>& units = quadField->GetUnitsExact(pos, radius);
QuadFieldQuery qfQuery;
quadField->GetUnitsExact(qfQuery, pos, radius);
myAllyTeamId = teamHandler->AllyTeam(team);
return FilterUnitsVector(units, unitIds, unitIds_max, &unit_IsEnemyAndInLos);
return FilterUnitsVector(*qfQuery.units, unitIds, unitIds_max, &unit_IsEnemyAndInLos);
}


Expand All @@ -914,9 +915,10 @@ int CAICallback::GetFriendlyUnits(int* unitIds, const float3& pos, float radius,
int unitIds_max)
{
verify();
const std::vector<CUnit*>& units = quadField->GetUnitsExact(pos, radius);
QuadFieldQuery qfQuery;
quadField->GetUnitsExact(qfQuery, pos, radius);
myAllyTeamId = teamHandler->AllyTeam(team);
return FilterUnitsVector(units, unitIds, unitIds_max, &unit_IsFriendly);
return FilterUnitsVector(*qfQuery.units, unitIds, unitIds_max, &unit_IsFriendly);
}


Expand All @@ -930,9 +932,10 @@ int CAICallback::GetNeutralUnits(int* unitIds, int unitIds_max)
int CAICallback::GetNeutralUnits(int* unitIds, const float3& pos, float radius, int unitIds_max)
{
verify();
const std::vector<CUnit*>& units = quadField->GetUnitsExact(pos, radius);
QuadFieldQuery qfQuery;
quadField->GetUnitsExact(qfQuery, pos, radius);
myAllyTeamId = teamHandler->AllyTeam(team);
return FilterUnitsVector(units, unitIds, unitIds_max, &unit_IsNeutralAndInLosOrRadar);
return FilterUnitsVector(*qfQuery.units, unitIds, unitIds_max, &unit_IsNeutralAndInLosOrRadar);
}


Expand Down Expand Up @@ -1252,14 +1255,12 @@ int CAICallback::GetFeatures(int* featureIds, int featureIds_sizeMax, const floa
int featureIds_size = 0;

verify();
const std::vector<CFeature*>& ft = quadField->GetFeaturesExact(pos, radius);
QuadFieldQuery qfQuery;
quadField->GetFeaturesExact(qfQuery, pos, radius);
const int allyteam = teamHandler->AllyTeam(team);

std::vector<CFeature*>::const_iterator it;
for (it = ft.begin(); (it != ft.end()) && (featureIds_size < featureIds_sizeMax); ++it) {
const CFeature* f = *it;
assert(f);

for (const CFeature* f: *qfQuery.features) {
if (f->IsInLosForAllyTeam(allyteam)) {
// if it is NULL, the caller only wants to know
// the number of features
Expand Down
10 changes: 6 additions & 4 deletions rts/ExternalAI/AICheats.cpp
Expand Up @@ -179,9 +179,10 @@ int CAICheats::GetEnemyUnits(int* unitIds, int unitIds_max)

int CAICheats::GetEnemyUnits(int* unitIds, const float3& pos, float radius, int unitIds_max)
{
const std::vector<CUnit*>& units = quadField->GetUnitsExact(pos, radius);
QuadFieldQuery qfQuery;
quadField->GetUnitsExact(qfQuery, pos, radius);
myAllyTeamId = teamHandler->AllyTeam(ai->GetTeamId());
return FilterUnitsVector(units, unitIds, unitIds_max, &unit_IsEnemy);
return FilterUnitsVector(*qfQuery.units, unitIds, unitIds_max, &unit_IsEnemy);
}

int CAICheats::GetNeutralUnits(int* unitIds, int unitIds_max)
Expand All @@ -191,8 +192,9 @@ int CAICheats::GetNeutralUnits(int* unitIds, int unitIds_max)

int CAICheats::GetNeutralUnits(int* unitIds, const float3& pos, float radius, int unitIds_max)
{
const std::vector<CUnit*>& units = quadField->GetUnitsExact(pos, radius);
return FilterUnitsVector(units, unitIds, unitIds_max, &unit_IsNeutral);
QuadFieldQuery qfQuery;
quadField->GetUnitsExact(qfQuery, pos, radius);
return FilterUnitsVector(*qfQuery.units, unitIds, unitIds_max, &unit_IsNeutral);
}

int CAICheats::GetFeatures(int* features, int max) const {
Expand Down
8 changes: 4 additions & 4 deletions rts/ExternalAI/SSkirmishAICallbackImpl.cpp
Expand Up @@ -4363,8 +4363,9 @@ EXPORT(int) skirmishAiCallback_getFeatures(int skirmishAIId, int* featureIds, in
EXPORT(int) skirmishAiCallback_getFeaturesIn(int skirmishAIId, float* pos_posF3, float radius, int* featureIds, int featureIdsMaxSize) {
if (skirmishAiCallback_Cheats_isEnabled(skirmishAIId)) {
// cheating
const std::vector<CFeature*>& fset = quadField->GetFeaturesExact(pos_posF3, radius);
const int featureIdsRealSize = fset.size();
QuadFieldQuery qfQuery;
quadField->GetFeaturesExact(qfQuery, pos_posF3, radius);
const int featureIdsRealSize = qfQuery.features->size();

int featureIdsSize = featureIdsRealSize;

Expand All @@ -4373,8 +4374,7 @@ EXPORT(int) skirmishAiCallback_getFeaturesIn(int skirmishAIId, float* pos_posF3,

size_t f = 0;

for (auto it = fset.cbegin(); it != fset.cend() && f < featureIdsSize; ++it) {
const CFeature* feature = *it;
for (const CFeature* feature: *qfQuery.features) {

assert(feature != nullptr);
featureIds[f++] = feature->id;
Expand Down
26 changes: 15 additions & 11 deletions rts/Game/GameHelper.cpp
Expand Up @@ -351,14 +351,15 @@ void CGameHelper::Explosion(const CExplosionParams& params) {
template<typename TFilter, typename TQuery>
static inline void QueryUnits(TFilter filter, TQuery& query)
{
const auto& quads = quadField->GetQuads(query.pos, query.radius);
QuadFieldQuery qfQuery;
quadField->GetQuads(qfQuery, query.pos, query.radius);
const int tempNum = gs->GetTempNum();

for (int t = 0; t < teamHandler->ActiveAllyTeams(); ++t) { //FIXME
if (!filter.Team(t))
continue;

for (const int qi: quads) {
for (const int qi: *qfQuery.quads) {
const auto& allyTeamUnits = quadField->GetQuad(qi).teamUnits[t];

for (CUnit* u: allyTeamUnits) {
Expand Down Expand Up @@ -645,14 +646,15 @@ void CGameHelper::GenerateWeaponTargets(const CWeapon* weapon, const CUnit* avoi
const bool paralyzer = (weapon->damages->paralyzeDamageTime != 0);

// copy on purpose since the below calls lua
const std::vector<int> quads = quadField->GetQuads(pos, radius + (aHeight - std::max(0.0f, readMap->GetInitMinHeight())) * heightMod);
QuadFieldQuery qfQuery;
quadField->GetQuads(qfQuery, pos, radius + (aHeight - std::max(0.0f, readMap->GetInitMinHeight())) * heightMod);
const int tempNum = gs->GetTempNum();

for (int t = 0; t < teamHandler->ActiveAllyTeams(); ++t) {
if (teamHandler->Ally(owner->allyteam, t))
continue;

for (const int qi: quads) {
for (const int qi: *qfQuery.quads) {
const std::vector<CUnit*>& allyTeamUnits = quadField->GetQuad(qi).teamUnits[t];

for (CUnit* targetUnit: allyTeamUnits) {
Expand Down Expand Up @@ -820,10 +822,11 @@ void CGameHelper::GetEnemyUnitsNoLosTest(const float3& pos, float searchRadius,
void CGameHelper::BuggerOff(float3 pos, float radius, bool spherical, bool forced, int teamId, CUnit* excludeUnit)
{
// copy on purpose since BuggerOff can call risky stuff
const std::vector<CUnit*> units = quadField->GetUnitsExact(pos, radius + SQUARE_SIZE, spherical);
QuadFieldQuery qfQuery;
quadField->GetUnitsExact(qfQuery, pos, radius + SQUARE_SIZE, spherical);
const int allyTeamId = teamHandler->AllyTeam(teamId);

for (CUnit* u: units) {
for (CUnit* u: *qfQuery.units) {
if (u == excludeUnit)
continue;
// don't send BuggerOff commands to enemy units
Expand Down Expand Up @@ -1074,18 +1077,19 @@ CGameHelper::BuildSquareStatus CGameHelper::TestUnitBuildSquare(
if (buildInfo.def->needGeo) {
canBuild = BUILDSQUARE_BLOCKED;

const std::vector<CFeature*>& features = quadField->GetFeaturesExact(pos, std::max(xsize, zsize) * 6);
QuadFieldQuery qfQuery;
quadField->GetFeaturesExact(qfQuery, pos, std::max(xsize, zsize) * 6);

const int mindx = xsize * (SQUARE_SIZE >> 1) - (SQUARE_SIZE >> 1);
const int mindz = zsize * (SQUARE_SIZE >> 1) - (SQUARE_SIZE >> 1);

// look for a nearby geothermal feature if we need one
for (std::vector<CFeature*>::const_iterator fi = features.begin(); fi != features.end(); ++fi) {
if (!(*fi)->def->geoThermal)
for (const CFeature* f: *qfQuery.features) {
if (!f->def->geoThermal)
continue;

const float dx = math::fabs((*fi)->pos.x - pos.x);
const float dz = math::fabs((*fi)->pos.z - pos.z);
const float dx = math::fabs(f->pos.x - pos.x);
const float dz = math::fabs(f->pos.z - pos.z);

if (dx < mindx && dz < mindz) {
canBuild = BUILDSQUARE_OPEN;
Expand Down
14 changes: 8 additions & 6 deletions rts/Game/SelectedUnitsAI.cpp
Expand Up @@ -602,16 +602,17 @@ void CSelectedUnitsHandlerAI::SelectCircleUnits(
if (p == NULL)
return;

const std::vector<CUnit*>& tmpUnits = quadField->GetUnitsExact(pos, radius, false);
QuadFieldQuery qfQuery;
quadField->GetUnitsExact(qfQuery, pos, radius, false);

const float radiusSqr = radius * radius;
const unsigned int count = tmpUnits.size();
const unsigned int count = qfQuery.units->size();
const int allyTeam = teamHandler->AllyTeam(p->team);

units.reserve(count);

for (unsigned int i = 0; i < count; i++) {
CUnit* unit = tmpUnits[i];
CUnit* unit = (*qfQuery.units)[i];

if (unit == NULL)
continue;
Expand Down Expand Up @@ -650,15 +651,16 @@ void CSelectedUnitsHandlerAI::SelectRectangleUnits(
const float3 mins(std::min(pos0.x, pos1.x), 0.0f, std::min(pos0.z, pos1.z));
const float3 maxs(std::max(pos0.x, pos1.x), 0.0f, std::max(pos0.z, pos1.z));

const std::vector<CUnit*>& tmpUnits = quadField->GetUnitsExact(mins, maxs);
QuadFieldQuery qfQuery;
quadField->GetUnitsExact(qfQuery, mins, maxs);

const unsigned int count = tmpUnits.size();
const unsigned int count = qfQuery.units->size();
const int allyTeam = teamHandler->AllyTeam(p->team);

units.reserve(count);

for (unsigned int i = 0; i < count; i++) {
const CUnit* unit = tmpUnits[i];
const CUnit* unit = (*qfQuery.units)[i];

if (unit == NULL)
continue;
Expand Down
31 changes: 18 additions & 13 deletions rts/Game/TraceRay.cpp
Expand Up @@ -202,7 +202,8 @@ float TraceRay(
if (scanForFeatures || scanForAnyUnits) {
CollisionQuery cq;

const auto& quads = quadField->GetQuadsOnRay(pos, dir, traceLength);
QuadFieldQuery qfQuery;
quadField->GetQuadsOnRay(qfQuery, pos, dir, traceLength);

// locally point somewhere non-NULL; we cannot pass hitColQuery
// to DetectHit directly because each call resets it internally
Expand All @@ -211,7 +212,7 @@ float TraceRay(

// feature intersection
if (scanForFeatures) {
for (const int quadIdx: quads) {
for (const int quadIdx: *qfQuery.quads) {
const CQuadField::Quad& quad = quadField->GetQuad(quadIdx);

for (CFeature* f: quad.features) {
Expand Down Expand Up @@ -239,7 +240,7 @@ float TraceRay(

// unit intersection
if (scanForAnyUnits) {
for (const int quadIdx: quads) {
for (const int quadIdx: *qfQuery.quads) {
const CQuadField::Quad& quad = quadField->GetQuad(quadIdx);

for (CUnit* u: quad.units) {
Expand Down Expand Up @@ -307,9 +308,10 @@ void TraceRayShields(
) {
CollisionQuery cq;

const auto& quads = quadField->GetQuadsOnRay(start, dir, length);
QuadFieldQuery qfQuery;
quadField->GetQuadsOnRay(qfQuery, start, dir, length);

for (const int quadIdx: quads) {
for (const int quadIdx: *qfQuery.quads) {
const CQuadField::Quad& quad = quadField->GetQuad(quadIdx);

for (CPlasmaRepulser* r: quad.repulsers) {
Expand Down Expand Up @@ -372,9 +374,10 @@ float GuiTraceRay(

CollisionQuery cq;

const auto& quads = quadField->GetQuadsOnRay(start, dir, length);
QuadFieldQuery qfQuery;
quadField->GetQuadsOnRay(qfQuery, start, dir, length);

for (const int quadIdx: quads) {
for (const int quadIdx: *qfQuery.quads) {
const CQuadField::Quad& quad = quadField->GetQuad(quadIdx);

// Unit Intersection
Expand Down Expand Up @@ -475,16 +478,17 @@ bool TestCone(
int traceFlags,
CUnit* owner
) {
const auto& quads = quadField->GetQuadsOnRay(from, dir, length);
QuadFieldQuery qfQuery;
quadField->GetQuadsOnRay(qfQuery, from, dir, length);

if (quads.empty())
if (qfQuery.quads->empty())
return true;

const bool scanForAllies = ((traceFlags & Collision::NOFRIENDLIES) == 0);
const bool scanForNeutrals = ((traceFlags & Collision::NONEUTRALS ) == 0);
const bool scanForFeatures = ((traceFlags & Collision::NOFEATURES ) == 0);

for (const int quadIdx: quads) {
for (const int quadIdx: *qfQuery.quads) {
const CQuadField::Quad& quad = quadField->GetQuad(quadIdx);

if (scanForAllies) {
Expand Down Expand Up @@ -540,16 +544,17 @@ bool TestTrajectoryCone(
int traceFlags,
CUnit* owner
) {
const auto& quads = quadField->GetQuadsOnRay(from, dir, length);
QuadFieldQuery qfQuery;
quadField->GetQuadsOnRay(qfQuery, from, dir, length);

if (quads.empty())
if (qfQuery.quads->empty())
return true;

const bool scanForAllies = ((traceFlags & Collision::NOFRIENDLIES) == 0);
const bool scanForNeutrals = ((traceFlags & Collision::NONEUTRALS ) == 0);
const bool scanForFeatures = ((traceFlags & Collision::NOFEATURES ) == 0);

for (const int quadIdx: quads) {
for (const int quadIdx: *qfQuery.quads) {
const CQuadField::Quad& quad = quadField->GetQuad(quadIdx);

// friendly units in this quad
Expand Down
7 changes: 3 additions & 4 deletions rts/Game/WaitCommandsAI.cpp
Expand Up @@ -828,11 +828,10 @@ void CWaitCommandsAI::DeathWait::SelectAreaUnits(
const float3 mins(std::min(pos0.x, pos1.x), 0.0f, std::min(pos0.z, pos1.z));
const float3 maxs(std::max(pos0.x, pos1.x), 0.0f, std::max(pos0.z, pos1.z));

const std::vector<CUnit*>& tmpUnits = quadField->GetUnitsExact(mins, maxs);

for (unsigned int i = 0; i < tmpUnits.size(); i++) {
const CUnit* unit = tmpUnits[i];
QuadFieldQuery qfQuery;
quadField->GetUnitsExact(qfQuery, mins, maxs);

for (const CUnit* unit: *qfQuery.units) {
if (enemies && teamHandler->Ally(unit->allyteam, gu->myAllyTeam))
continue;

Expand Down

0 comments on commit 13517d8

Please sign in to comment.