Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: optimized moveCreature and spectators #2667

Merged
merged 2 commits into from
Jun 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/creatures/monsters/monster.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,11 @@ class Monster final : public Creature {
void dropLoot(std::shared_ptr<Container> corpse, std::shared_ptr<Creature> lastHitCreature) override;
void getPathSearchParams(const std::shared_ptr<Creature> &creature, FindPathParams &fpp) override;
bool useCacheMap() const override {
return !randomStepping;
// return !randomStepping;
// As the map cache is done synchronously for each movement that a monster makes, it is better to disable it,
// as the pathfinder, which is one of the resources that uses this cache the most,
// is multithreding and thus the processing cost is divided between the threads.
return false;
}

friend class MonsterFunctions;
Expand Down
28 changes: 25 additions & 3 deletions src/map/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,13 +342,35 @@ void Map::moveCreature(const std::shared_ptr<Creature> &creature, const std::sha

bool teleport = forceTeleport || !newTile->getGround() || !Position::areInRange<1, 1, 0>(oldPos, newPos);

auto spectators = Spectators()
.find<Creature>(oldPos, true)
.find<Creature>(newPos, true);
Spectators spectators;
if (!teleport && oldPos.z == newPos.z) {
int32_t minRangeX = MAP_MAX_VIEW_PORT_X;
int32_t maxRangeX = MAP_MAX_VIEW_PORT_X;
int32_t minRangeY = MAP_MAX_VIEW_PORT_Y;
int32_t maxRangeY = MAP_MAX_VIEW_PORT_Y;

if (oldPos.y > newPos.y) {
++minRangeY;
} else if (oldPos.y < newPos.y) {
++maxRangeY;
}

if (oldPos.x < newPos.x) {
++maxRangeX;
} else if (oldPos.x > newPos.x) {
++minRangeX;
}

spectators.find<Creature>(oldPos, true, minRangeX, maxRangeX, minRangeY, maxRangeY);
} else {
spectators.find<Creature>(oldPos, true);
spectators.find<Creature>(newPos, true);
}

auto playersSpectators = spectators.filter<Player>();

std::vector<int32_t> oldStackPosVector;
oldStackPosVector.reserve(playersSpectators.size());
for (const auto &spec : playersSpectators) {
if (spec->canSeeCreature(creature)) {
oldStackPosVector.push_back(oldTile->getClientIndexOfCreature(spec->getPlayer(), creature));
Expand Down
51 changes: 14 additions & 37 deletions src/map/spectators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,50 +18,27 @@ void Spectators::clearCache() {
spectatorsCache.clear();
}

bool Spectators::contains(const std::shared_ptr<Creature> &creature) {
return creatures.contains(creature);
}

bool Spectators::erase(const std::shared_ptr<Creature> &creature) {
return creatures.erase(creature);
}

Spectators Spectators::insert(const std::shared_ptr<Creature> &creature) {
if (creature) {
creatures.emplace(creature);
creatures.emplace_back(creature);
}
return *this;
}

Spectators Spectators::insertAll(const SpectatorList &list) {
Spectators Spectators::insertAll(const CreatureVector &list) {
if (!list.empty()) {
creatures.insertAll(list);
}
return *this;
}
const bool hasValue = !creatures.empty();

Spectators Spectators::join(Spectators &anotherSpectators) {
return insertAll(anotherSpectators.creatures.data());
}

bool Spectators::empty() const noexcept {
return creatures.empty();
}
creatures.insert(creatures.end(), list.begin(), list.end());

size_t Spectators::size() noexcept {
return creatures.size();
}

CreatureVector::iterator Spectators::begin() noexcept {
return creatures.begin();
}

CreatureVector::iterator Spectators::end() noexcept {
return creatures.end();
}

const CreatureVector &Spectators::data() noexcept {
return creatures.data();
// Remove duplicate
if (hasValue) {
std::unordered_set uset(creatures.begin(), creatures.end());
creatures.clear();
creatures.insert(creatures.end(), uset.begin(), uset.end());
}
}
return *this;
}

bool Spectators::checkCache(const SpectatorsCache::FloorData &specData, bool onlyPlayers, const Position &centerPos, bool checkDistance, bool multifloor, int32_t minRangeX, int32_t maxRangeX, int32_t minRangeY, int32_t maxRangeY) {
Expand All @@ -77,7 +54,7 @@ bool Spectators::checkCache(const SpectatorsCache::FloorData &specData, bool onl
}

if (checkDistance) {
SpectatorList spectators;
CreatureVector spectators;
spectators.reserve(creatures.size());
for (const auto &creature : *list) {
const auto &specPos = creature->getPosition();
Expand Down Expand Up @@ -176,7 +153,7 @@ Spectators Spectators::find(const Position &centerPos, bool multifloor, bool onl
const int32_t endx2 = x2 - (x2 & SECTOR_MASK);
const int32_t endy2 = y2 - (y2 & SECTOR_MASK);

SpectatorList spectators;
CreatureVector spectators;
spectators.reserve(std::max<uint8_t>(MAP_MAX_VIEW_PORT_X, MAP_MAX_VIEW_PORT_Y) * 2);

const MapSector* startSector = g_game().map.getMapSector(startx1, starty1);
Expand Down
49 changes: 35 additions & 14 deletions src/map/spectators.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,10 @@ class Monster;
class Npc;
struct Position;

using SpectatorList = std::vector<std::shared_ptr<Creature>>;

struct SpectatorsCache {
struct FloorData {
std::optional<SpectatorList> floor;
std::optional<SpectatorList> multiFloor;
std::optional<CreatureVector> floor;
std::optional<CreatureVector> multiFloor;
};

int32_t minRangeX { 0 };
Expand All @@ -48,24 +46,47 @@ class Spectators {
requires std::is_base_of_v<Creature, T>
Spectators filter();

bool contains(const std::shared_ptr<Creature> &creature);
bool erase(const std::shared_ptr<Creature> &creature);
Spectators insert(const std::shared_ptr<Creature> &creature);
Spectators insertAll(const SpectatorList &list);
Spectators join(Spectators &anotherSpectators);
bool empty() const noexcept;
size_t size() noexcept;
CreatureVector::iterator begin() noexcept;
CreatureVector::iterator end() noexcept;
const CreatureVector &data() noexcept;
Spectators insertAll(const CreatureVector &list);
Spectators join(const Spectators &anotherSpectators) {
return insertAll(anotherSpectators.creatures);
}

bool contains(const std::shared_ptr<Creature> &creature) const {
return std::ranges::find(creatures, creature) != creatures.end();
}

bool erase(const std::shared_ptr<Creature> &creature) {
return std::erase(creatures, creature) > 0;
}

bool empty() const noexcept {
return creatures.empty();
}

size_t size() const noexcept {
return creatures.size();
}

auto begin() const noexcept {
return creatures.begin();
}

auto end() const noexcept {
return creatures.end();
}

const auto &data() const noexcept {
return creatures;
}

private:
static phmap::flat_hash_map<Position, SpectatorsCache> spectatorsCache;

Spectators find(const Position &centerPos, bool multifloor = false, bool onlyPlayers = false, int32_t minRangeX = 0, int32_t maxRangeX = 0, int32_t minRangeY = 0, int32_t maxRangeY = 0);
bool checkCache(const SpectatorsCache::FloorData &specData, bool onlyPlayers, const Position &centerPos, bool checkDistance, bool multifloor, int32_t minRangeX, int32_t maxRangeX, int32_t minRangeY, int32_t maxRangeY);

stdext::vector_set<std::shared_ptr<Creature>> creatures;
CreatureVector creatures;
};

template <typename T>
Expand Down
Loading