Skip to content

Commit

Permalink
Improve search cache result
Browse files Browse the repository at this point in the history
  • Loading branch information
ramon-bernardo committed Nov 4, 2024
1 parent eb06511 commit b6c43f8
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 150 deletions.
2 changes: 0 additions & 2 deletions src/creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,6 @@ void Creature::onCreatureAppear(Creature* creature, bool isLogin)
}
}

void Creature::onRemoveCreature(Creature* creature, bool) { onCreatureDisappear(creature, true); }

void Creature::onCreatureDisappear(const Creature* creature, bool isLogout)
{
if (attackedCreature == creature) {
Expand Down
2 changes: 1 addition & 1 deletion src/creature.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ class Creature : virtual public Thing
virtual void onRemoveTileItem(const Tile* tile, const Position& pos, const ItemType& iType, const Item* item) {}

Check failure on line 289 in src/creature.h

View workflow job for this annotation

GitHub Actions / test

unused parameter ‘tile’ [-Werror=unused-parameter]

Check failure on line 289 in src/creature.h

View workflow job for this annotation

GitHub Actions / test

unused parameter ‘pos’ [-Werror=unused-parameter]

virtual void onCreatureAppear(Creature* creature, bool isLogin);
virtual void onRemoveCreature(Creature* creature, bool isLogout);
virtual void onRemoveCreature(Creature* creature, bool isLogout) {}
virtual void onCreatureMove(Creature* creature, const Tile* newTile, const Position& newPos, const Tile* oldTile,
const Position& oldPos, bool teleport);

Expand Down
4 changes: 2 additions & 2 deletions src/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -633,9 +633,9 @@ const Tile* Map::canWalkTo(const Creature& creature, const Position& pos) const
{
if (auto monster = creature.getMonster()) {
auto walk_cache = monster->getWalkCache(pos);
if (walk_cache == 0) {
if (walk_cache == WALKCACHE_NOTFOUND) {
return nullptr;
} else if (walk_cache == 1) {
} else if (walk_cache == WALKCACHE_FOUND) {
return getTile(pos.x, pos.y, pos.z);
}
}
Expand Down
248 changes: 112 additions & 136 deletions src/monster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ void Monster::onCreatureAppear(Creature* creature, bool isLogin)

void Monster::onRemoveCreature(Creature* creature, bool isLogout)
{
Creature::onRemoveCreature(creature, isLogout);
onCreatureDisappear(creature, isLogout);

if (creature != this) {
if (hasLoadedMap()) {
Expand Down Expand Up @@ -214,124 +214,7 @@ void Monster::onCreatureMove(Creature* creature, const Tile* newTile, const Posi
const Position& oldPos, bool teleport)
{
if (hasLoadedMap()) {
// update map cache
if (creature == this) {
if (teleport || oldPos.z != newPos.z) {
updateWalkCache();
} else {
const Position& myPos = getPosition();

if (oldPos.y > newPos.y) { // north
// shift y south
for (int32_t y = walkCacheHeight - 1; --y >= 0;) {
memcpy(walkabilityCache[y + 1], walkabilityCache[y], sizeof(walkabilityCache[y]));
}

// update 0
for (int32_t x = -maxWalkCacheWidth; x <= maxWalkCacheWidth; ++x) {
Tile* cacheTile =
g_game.map.getTile(myPos.getX() + x, myPos.getY() - maxWalkCacheHeight, myPos.z);
updateTileWalkCache(cacheTile, x, -maxWalkCacheHeight);
}
} else if (oldPos.y < newPos.y) { // south
// shift y north
for (int32_t y = 0; y <= walkCacheHeight - 2; ++y) {
memcpy(walkabilityCache[y], walkabilityCache[y + 1], sizeof(walkabilityCache[y]));
}

// update map_walk_height - 1
for (int32_t x = -maxWalkCacheWidth; x <= maxWalkCacheWidth; ++x) {
Tile* cacheTile =
g_game.map.getTile(myPos.getX() + x, myPos.getY() + maxWalkCacheHeight, myPos.z);
updateTileWalkCache(cacheTile, x, maxWalkCacheHeight);
}
}

if (oldPos.x < newPos.x) { // east
// shift y west
int32_t starty = 0;
int32_t endy = walkCacheHeight - 1;
int32_t dy = oldPos.getDistanceY(newPos);

if (dy < 0) {
endy += dy;
} else if (dy > 0) {
starty = dy;
}

for (int32_t y = starty; y <= endy; ++y) {
for (int32_t x = 0; x <= walkCacheWidth - 2; ++x) {
walkabilityCache[y][x] = walkabilityCache[y][x + 1];
}
}

// update map_walk_width - 1
for (int32_t y = -maxWalkCacheHeight; y <= maxWalkCacheHeight; ++y) {
Tile* cacheTile = g_game.map.getTile(myPos.x + maxWalkCacheWidth, myPos.y + y, myPos.z);
updateTileWalkCache(cacheTile, maxWalkCacheWidth, y);
}
} else if (oldPos.x > newPos.x) { // west
// shift y east
int32_t starty = 0;
int32_t endy = walkCacheHeight - 1;
int32_t dy = oldPos.getDistanceY(newPos);

if (dy < 0) {
endy += dy;
} else if (dy > 0) {
starty = dy;
}

for (int32_t y = starty; y <= endy; ++y) {
for (int32_t x = walkCacheWidth - 1; --x >= 0;) {
walkabilityCache[y][x + 1] = walkabilityCache[y][x];
}
}

// update 0
for (int32_t y = -maxWalkCacheHeight; y <= maxWalkCacheHeight; ++y) {
Tile* cacheTile = g_game.map.getTile(myPos.x - maxWalkCacheWidth, myPos.y + y, myPos.z);
updateTileWalkCache(cacheTile, -maxWalkCacheWidth, y);
}
}

updateTileWalkCache(oldTile, oldPos);
}
} else {
const Position& myPos = getPosition();
if (newPos.z == myPos.z) {
updateTileWalkCache(newTile, newPos);
}

if (oldPos.z == myPos.z) {
updateTileWalkCache(oldTile, oldPos);
}
}
}

if (creature == followCreature || (creature == this && followCreature)) {
if (hasFollowPath) {
isUpdatingPath = true;
}

if (newPos.z != oldPos.z || !canSee(followCreature->getPosition())) {
onCreatureDisappear(followCreature, false);
}
}

if (creature == attackedCreature || (creature == this && attackedCreature)) {
if (newPos.z != oldPos.z || !canSee(attackedCreature->getPosition())) {
onCreatureDisappear(attackedCreature, false);
} else {
if (hasExtraSwing()) {
// our target is moving lets see if we can get in hit
g_dispatcher.addTask([id = getID()]() { g_game.checkCreatureAttack(id); });
}

if (newTile->getZone() != oldTile->getZone()) {
onAttackedCreatureChangeZone(attackedCreature->getZone());
}
}
updateMoveWalkCache(creature, newTile, newPos, oldTile, oldPos, teleport);
}

Creature::onCreatureMove(creature, newTile, newPos, oldTile, oldPos, teleport);
Expand Down Expand Up @@ -557,11 +440,11 @@ void Monster::onCreatureFound(Creature* creature, bool pushFront /* = false*/)
void Monster::updateWalkCache()
{
Tile* tile;
const Position& myPos = getPosition();
const auto& myPos = getPosition();
Position pos(0, 0, myPos.z);

for (int32_t y = -maxWalkCacheHeight; y <= maxWalkCacheHeight; ++y) {
for (int32_t x = -maxWalkCacheWidth; x <= maxWalkCacheWidth; ++x) {
for (auto y = -Map::maxViewportY; y <= Map::maxViewportY; ++y) {
for (auto x = -Map::maxViewportX; x <= Map::maxViewportX; ++x) {
pos.x = myPos.getX() + x;
pos.y = myPos.getY() + y;
tile = g_game.map.getTile(pos);
Expand All @@ -572,22 +455,115 @@ void Monster::updateWalkCache()

void Monster::updateTileWalkCache(const Tile* tile, int32_t dx, int32_t dy)
{
if (std::abs(dx) <= maxWalkCacheWidth && std::abs(dy) <= maxWalkCacheHeight) {
walkabilityCache[maxWalkCacheHeight + dy][maxWalkCacheWidth + dx] =
if (std::abs(dx) <= Map::maxViewportX && std::abs(dy) <= Map::maxViewportY) {
walkabilityCache[Map::maxViewportY + dy][Map::maxViewportX + dx] =
tile && tile->queryAdd(0, *this, 1, FLAG_PATHFINDING | FLAG_IGNOREFIELDDAMAGE) == RETURNVALUE_NOERROR;
}
}

void Monster::updateTileWalkCache(const Tile* tile, const Position& pos)
{
const Position& myPos = getPosition();
const auto& myPos = getPosition();
if (pos.z == myPos.z) {
int32_t dx = pos.getOffsetX(myPos);
int32_t dy = pos.getOffsetY(myPos);
updateTileWalkCache(tile, dx, dy);
}
}

void Monster::updateMoveWalkCache(Creature* creature, const Tile* newTile, const Position& newPos, const Tile* oldTile,
const Position& oldPos, bool teleport)
{
if (creature == this) {
if (teleport || oldPos.z != newPos.z) {
updateWalkCache();
} else {
const auto& myPos = getPosition();

if (oldPos.y > newPos.y) { // north
// shift y south
for (auto y = walkCacheHeight - 1; --y >= 0;) {
memcpy(walkabilityCache[y + 1], walkabilityCache[y], sizeof(walkabilityCache[y]));
}

// update 0
for (auto x = -Map::maxViewportX; x <= Map::maxViewportX; ++x) {
auto cacheTile = g_game.map.getTile(myPos.getX() + x, myPos.getY() - Map::maxViewportY, myPos.z);
updateTileWalkCache(cacheTile, x, -Map::maxViewportY);
}
} else if (oldPos.y < newPos.y) { // south
// shift y north
for (auto y = 0; y <= walkCacheHeight - 2; ++y) {
memcpy(walkabilityCache[y], walkabilityCache[y + 1], sizeof(walkabilityCache[y]));
}

// update map_walk_height - 1
for (auto x = -Map::maxViewportX; x <= Map::maxViewportX; ++x) {
auto cacheTile = g_game.map.getTile(myPos.getX() + x, myPos.getY() + Map::maxViewportY, myPos.z);
updateTileWalkCache(cacheTile, x, Map::maxViewportY);
}
}

if (oldPos.x < newPos.x) { // east
// shift y west
auto starty = 0;
auto endy = walkCacheHeight - 1;
auto dy = oldPos.getDistanceY(newPos);

if (dy < 0) {
endy += dy;
} else if (dy > 0) {
starty = dy;
}

for (auto y = starty; y <= endy; ++y) {
for (auto x = 0; x <= walkCacheWidth - 2; ++x) {
walkabilityCache[y][x] = walkabilityCache[y][x + 1];
}
}

// update map_walk_width - 1
for (auto y = -Map::maxViewportY; y <= Map::maxViewportY; ++y) {
auto cacheTile = g_game.map.getTile(myPos.x + Map::maxViewportX, myPos.y + y, myPos.z);
updateTileWalkCache(cacheTile, Map::maxViewportX, y);
}
} else if (oldPos.x > newPos.x) { // west
// shift y east
auto starty = 0;
auto endy = walkCacheHeight - 1;
auto dy = oldPos.getDistanceY(newPos);

if (dy < 0) {
endy += dy;
} else if (dy > 0) {
starty = dy;
}

for (auto y = starty; y <= endy; ++y) {
for (auto x = walkCacheWidth - 1; --x >= 0;) {
walkabilityCache[y][x + 1] = walkabilityCache[y][x];
}
}

// update 0
for (auto y = -Map::maxViewportY; y <= Map::maxViewportY; ++y) {
auto cacheTile = g_game.map.getTile(myPos.x - Map::maxViewportX, myPos.y + y, myPos.z);
updateTileWalkCache(cacheTile, -Map::maxViewportX, y);
}
}

updateTileWalkCache(oldTile, oldPos);
}
} else {
const auto& myPos = getPosition();
if (newPos.z == myPos.z) {
updateTileWalkCache(newTile, newPos);
} else if (oldPos.z == myPos.z) {
updateTileWalkCache(oldTile, oldPos);
}
}
}

void Monster::onAddTileItem(const Tile* tile, const Position& pos)
{
if (hasLoadedMap()) {
Expand Down Expand Up @@ -2027,34 +2003,34 @@ bool Monster::getDistanceStep(const Position& targetPos, Direction& direction, b
return true;
}

int32_t Monster::getWalkCache(const Position& pos) const
WalkCacheResult Monster::getWalkCache(const Position& pos) const
{
if (useWalkCache()) {
const Position& myPos = getPosition();
const auto& myPos = getPosition();
if (myPos.z != pos.z) {
return 0;
return WALKCACHE_NOTFOUND;
} else if (pos == myPos) {
return 1;
return WALKCACHE_FOUND;
}

if (int32_t dx = pos.getOffsetX(myPos); std::abs(dx) <= maxWalkCacheWidth) {
if (int32_t dy = pos.getOffsetY(myPos); std::abs(dy) <= maxWalkCacheHeight) {
if (walkabilityCache[maxWalkCacheHeight + dy][maxWalkCacheWidth + dx]) {
return 1;
if (auto x = pos.getOffsetX(myPos); std::abs(x) <= Map::maxViewportX) {
if (auto y = pos.getOffsetY(myPos); std::abs(y) <= Map::maxViewportY) {
if (walkabilityCache[Map::maxViewportY + y][Map::maxViewportX + x]) {
return WALKCACHE_FOUND;
}
return 0;
return WALKCACHE_NOTFOUND;
}
}
}

return 2;
return WALKCACHE_DISABLED;
}

bool Monster::canWalkTo(Position pos, Direction direction) const
{
pos = getNextPosition(direction, pos);
if (isInSpawnRange(pos)) {
if (getWalkCache(pos) == 0) {
if (getWalkCache(pos) == WALKCACHE_NOTFOUND) {
return false;
}

Expand Down
13 changes: 10 additions & 3 deletions src/monster.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ enum TargetSearchType_t
TARGETSEARCH_NEAREST,
};

enum WalkCacheResult
{
WALKCACHE_DISABLED,
WALKCACHE_NOTFOUND,
WALKCACHE_FOUND,
};

class Monster final : public Creature
{
public:
Expand Down Expand Up @@ -130,7 +137,7 @@ class Monster final : public Creature
bool checkArmor = false, bool field = false, bool ignoreResistances = false) override;

// map cache
int32_t getWalkCache(const Position& pos) const;
WalkCacheResult getWalkCache(const Position& pos) const;

// monster icons
MonsterIconHashMap& getSpecialIcons() { return monsterIcons; }
Expand All @@ -141,8 +148,6 @@ class Monster final : public Creature
private:
static constexpr int32_t walkCacheWidth = Map::maxViewportX * 2 + 1;
static constexpr int32_t walkCacheHeight = Map::maxViewportY * 2 + 1;
static constexpr int32_t maxWalkCacheWidth = (walkCacheWidth - 1) / 2;
static constexpr int32_t maxWalkCacheHeight = (walkCacheHeight - 1) / 2;

CreatureHashSet friendList;
CreatureList targetList;
Expand Down Expand Up @@ -242,6 +247,8 @@ class Monster final : public Creature
void updateWalkCache();
void updateTileWalkCache(const Tile* tile, int32_t dx, int32_t dy);
void updateTileWalkCache(const Tile* tile, const Position& pos);
void updateMoveWalkCache(Creature* creature, const Tile* newTile, const Position& newPos, const Tile* oldTile,
const Position& oldPos, bool teleport);

friend class LuaScriptInterface;
};
Expand Down
2 changes: 1 addition & 1 deletion src/npc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ bool NpcType::loadCallback(NpcScriptInterface* scriptInterface)

void Npc::onRemoveCreature(Creature* creature, bool isLogout)
{
Creature::onRemoveCreature(creature, isLogout);
onCreatureDisappear(creature, isLogout);

if (creature == this) {
closeAllShopWindows();
Expand Down
Loading

0 comments on commit b6c43f8

Please sign in to comment.