Skip to content

Commit

Permalink
Implemented Hash Cache for spectators.
Browse files Browse the repository at this point in the history
Co-Authored-By: Sarah Wesker <[email protected]>
  • Loading branch information
Codinablack and MillhioreBT committed Dec 7, 2024
1 parent e7fd326 commit b00e97e
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 21 deletions.
30 changes: 22 additions & 8 deletions src/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -407,9 +407,27 @@ void Map::getSpectators(SpectatorVec& spectators, const Position& centerPos, boo
minRangeY = (minRangeY == 0 ? -maxViewportY : -minRangeY);
maxRangeY = (maxRangeY == 0 ? maxViewportY : maxRangeY);

std::array<int32_t, 4> cache_values{
-maxViewportX , maxViewportX , -maxViewportY , maxViewportY
};
chunkKey.minRangeX = minRangeX;
chunkKey.maxRangeX = maxRangeX;
chunkKey.minRangeY = minRangeY;
chunkKey.maxRangeY = maxRangeY;
chunkKey.x = centerPos.x;
chunkKey.y = centerPos.y;
chunkKey.z = centerPos.z;
chunkKey.multifloor = multifloor;
chunkKey.onlyPlayers = onlyPlayers;

auto it = chunksSpectatorCache.find(chunkKey);
if (it != chunksSpectatorCache.end()) {
if (!spectators.empty()) {
spectators.addSpectators(it->second);
} else {
spectators = it->second;
}
foundCache = true;
} else {
cacheResult = true;
}

if (minRangeX == -maxViewportX && maxRangeX == maxViewportX && minRangeY == -maxViewportY && maxRangeY == maxViewportY && multifloor) {
if (onlyPlayers) {
Expand Down Expand Up @@ -467,11 +485,7 @@ void Map::getSpectators(SpectatorVec& spectators, const Position& centerPos, boo
getSpectatorsInternal(spectators, centerPos, minRangeX, maxRangeX, minRangeY, maxRangeY, minRangeZ, maxRangeZ, onlyPlayers);

if (cacheResult) {
if (onlyPlayers) {
playersSpectatorCache[centerPos] = spectators;
} else {
spectatorCache[centerPos] = spectators;
}
chunksSpectatorCache.emplace(chunkKey, spectators);
}
}
}
Expand Down
45 changes: 44 additions & 1 deletion src/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,45 @@ static constexpr int32_t MAX_NODES = 512;
static constexpr int32_t MAP_NORMALWALKCOST = 10;
static constexpr int32_t MAP_DIAGONALWALKCOST = 25;

struct alignas(16) ChunkKey {
int32_t minRangeX, maxRangeX, minRangeY, maxRangeY;
uint16_t x, y;
uint8_t z;
bool multifloor, onlyPlayers;

bool operator==(const ChunkKey& other) const noexcept {
return std::memcmp(this, &other, sizeof(ChunkKey)) == 0;
}
};
static ChunkKey chunkKey;
struct ChunkKeyHash {
std::size_t operator()(const ChunkKey& key) const noexcept {
std::size_t hash = 0;
hash_combine(hash, key.minRangeX, key.maxRangeX, key.minRangeY, key.maxRangeY,
key.x, key.y, key.z, key.multifloor, key.onlyPlayers);
return hash;
}

private:
template <typename... Args>
static void hash_combine(std::size_t& seed, Args&&... args) {
(hash_combine_impl(seed, std::forward<Args>(args)), ...);
}

template <typename T>
static void hash_combine_impl(std::size_t& seed, const T& v) {
seed ^= std::hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
};

struct ChunkKeyEqual {
bool operator()(const ChunkKey& lhs, const ChunkKey& rhs) const noexcept {
return std::memcmp(&lhs, &rhs, sizeof(ChunkKey)) == 0;
}
};

using ChunkCache = std::unordered_map<ChunkKey, SpectatorVec, ChunkKeyHash, ChunkKeyEqual>;

class AStarNodes
{
public:
Expand Down Expand Up @@ -169,6 +208,10 @@ class Map
* \returns true if the map was loaded successfully
*/
bool loadMap(const std::string& identifier, bool loadHouses);
void clearChunkSpectatorCache() {
playersSpectatorCache.clear();
chunksSpectatorCache.clear();
}

/**
* Save a map.
Expand Down Expand Up @@ -268,7 +311,7 @@ class Map
private:
SpectatorCache spectatorCache;
SpectatorCache playersSpectatorCache;

ChunkCache chunksSpectatorCache;
QTreeNode root;

std::filesystem::path spawnfile;
Expand Down
15 changes: 3 additions & 12 deletions src/tile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -902,10 +902,7 @@ void Tile::addThing(int32_t, Thing* thing)
{
Creature* creature = thing->getCreature();
if (creature) {
g_game.map.clearSpectatorCache();
if (creature->getPlayer()) {
g_game.map.clearPlayersSpectatorCache();
}
g_game.map.clearChunkSpectatorCache();

creature->setParent(this);
CreatureVector* creatures = makeCreatures();
Expand Down Expand Up @@ -1111,10 +1108,7 @@ void Tile::removeThing(Thing* thing, uint32_t count)
if (creatures) {
auto it = std::find(creatures->begin(), creatures->end(), thing);
if (it != creatures->end()) {
g_game.map.clearSpectatorCache();
if (creature->getPlayer()) {
g_game.map.clearPlayersSpectatorCache();
}
g_game.map.clearChunkSpectatorCache();

creatures->erase(it);
}
Expand Down Expand Up @@ -1491,10 +1485,7 @@ void Tile::internalAddThing(uint32_t, Thing* thing)

Creature* creature = thing->getCreature();
if (creature) {
g_game.map.clearSpectatorCache();
if (creature->getPlayer()) {
g_game.map.clearPlayersSpectatorCache();
}
g_game.map.clearChunkSpectatorCache();

CreatureVector* creatures = makeCreatures();
creatures->insert(creatures->begin(), creature);
Expand Down

0 comments on commit b00e97e

Please sign in to comment.