Skip to content

Commit

Permalink
Fix quadtree
Browse files Browse the repository at this point in the history
  • Loading branch information
ramon-bernardo committed Oct 6, 2024
1 parent 05f887e commit e8c8d4d
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 41 deletions.
30 changes: 17 additions & 13 deletions src/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "iomap.h"
#include "iomapserialize.h"
#include "monster.h"
#include "quadtree.h"
#include "spectators.h"

extern Game g_game;
Expand Down Expand Up @@ -364,22 +365,25 @@ void Map::getSpectators(SpectatorVec& spectators, const Position& centerPos, boo
uint16_t x2 = std::min<uint32_t>(0xFFFF, std::max<int32_t>(0, (max_x + maxoffset)));
uint16_t y2 = std::min<uint32_t>(0xFFFF, std::max<int32_t>(0, (max_y + maxoffset)));

tfs::map::quadtree::find(x1, y1, x2, y2, spectators, [=](Creature* creature) -> bool {
if (onlyPlayers && !creature->getPlayer()) {
return false;
}
tfs::map::quadtree::find(x1, y1, x2, y2, [&](std::set<Creature*>& creatures) {
for (auto creature : creatures) {
if (onlyPlayers && !creature->getPlayer()) {
continue;
}

const auto& position = creature->getPosition();
if (minRangeZ > position.z || maxRangeZ < position.z) {
return false;
}
const auto& position = creature->getPosition();
if (minRangeZ > position.z || maxRangeZ < position.z) {
continue;
}

auto offsetZ = centerPos.getOffsetZ(position);
if ((min_y + offsetZ) > position.y || (max_y + offsetZ) < position.y || (min_x + offsetZ) > position.x ||
(max_x + offsetZ) < position.x) {
return false;
auto offsetZ = centerPos.getOffsetZ(position);
if ((min_y + offsetZ) > position.y || (max_y + offsetZ) < position.y ||
(min_x + offsetZ) > position.x || (max_x + offsetZ) < position.x) {
continue;
}

spectators.emplace_back(creature);
}
return true;
});

if (cacheResult) {
Expand Down
3 changes: 1 addition & 2 deletions src/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@

#include "house.h"
#include "position.h"
#include "quadtree.h"
#include "spawn.h"
#include "spectators.h"
#include "town.h"

class Creature;

inline constexpr int32_t MAP_MAX_LAYERS = 16;
inline constexpr int32_t const MAP_MAX_LAYERS = 16;

struct FindPathParams;
struct AStarNode
Expand Down
37 changes: 16 additions & 21 deletions src/quadtree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,6 @@ std::array<QuadTree*, 4> nodes = {};

uint8_t create_index(uint16_t x, uint16_t y) { return ((x & 0x8000) >> 15) | ((y & 0x8000) >> 14); }

Leaf* find_leaf_in_root(uint16_t x, uint16_t y)
{
auto index = create_index(x, y);
if (auto node = nodes[index]; auto leaf = find_leaf(x, y, node)) {
return static_cast<Leaf*>(leaf);
}
return nullptr;
}

QuadTree* find_leaf(uint16_t x, uint16_t y, QuadTree* node)
{
if (node->is_leaf()) {
Expand All @@ -27,14 +18,13 @@ QuadTree* find_leaf(uint16_t x, uint16_t y, QuadTree* node)
return nullptr;
}

void create_leaf_in_root(uint16_t x, uint16_t y, uint8_t z)
Leaf* find_leaf_in_root(uint16_t x, uint16_t y)
{
auto index = create_index(x, y);
if (!nodes[index]) {
nodes[index] = new Node();
if (auto node = nodes[index]; auto leaf = find_leaf(x, y, node)) {
return static_cast<Leaf*>(leaf);
}

create_leaf(x, y, (MAP_MAX_LAYERS - 1), nodes[index]);
return nullptr;
}

void create_leaf(uint16_t x, uint16_t y, uint8_t z, QuadTree* node)
Expand All @@ -58,10 +48,20 @@ void create_leaf(uint16_t x, uint16_t y, uint8_t z, QuadTree* node)
create_leaf(x * 2, y * 2, z - 1, node_child);
}

void create_leaf_in_root(uint16_t x, uint16_t y, uint8_t z)

Check failure on line 51 in src/quadtree.cpp

View workflow job for this annotation

GitHub Actions / test

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

Check failure on line 51 in src/quadtree.cpp

View workflow job for this annotation

GitHub Actions / macos-Debug-luajit=on

unused parameter 'z' [-Werror,-Wunused-parameter]

Check failure on line 51 in src/quadtree.cpp

View workflow job for this annotation

GitHub Actions / macos-Debug-luajit=off

unused parameter 'z' [-Werror,-Wunused-parameter]

Check failure on line 51 in src/quadtree.cpp

View workflow job for this annotation

GitHub Actions / macos-Release-luajit=on

unused parameter 'z' [-Werror,-Wunused-parameter]

Check failure on line 51 in src/quadtree.cpp

View workflow job for this annotation

GitHub Actions / macos-Release-luajit=off

unused parameter 'z' [-Werror,-Wunused-parameter]
{
auto index = create_index(x, y);
if (!nodes[index]) {
nodes[index] = new Node();
}

create_leaf(x, y, (MAP_MAX_LAYERS - 1), nodes[index]);
}

} // namespace

void tfs::map::quadtree::find(uint16_t start_x, uint16_t start_y, uint16_t end_x, uint16_t end_y,
SpectatorVec& spectators, std::function<bool(Creature*)> comparison)
std::function<void(std::set<Creature*>&)> comparison)
{
int32_t start_x_aligned = start_x - (start_x % TILE_GRID_SIZE);
int32_t start_y_aligned = start_y - (start_y % TILE_GRID_SIZE);
Expand All @@ -76,12 +76,7 @@ void tfs::map::quadtree::find(uint16_t start_x, uint16_t start_y, uint16_t end_x

for (int32_t nx = start_x_aligned; nx <= end_x_aligned; nx += TILE_GRID_SIZE) {
if (east_leaf) {
for (auto creature : east_leaf->creatures) {
if (comparison(creature)) {
spectators.emplace_back(creature);
}
}

comparison(east_leaf->creatures);
east_leaf = east_leaf->east_leaf;
} else {
east_leaf = find_leaf_in_root(nx + TILE_GRID_SIZE, ny);
Expand Down
21 changes: 16 additions & 5 deletions src/quadtree.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
// Copyright 2023 The Forgotten Server Authors. All rights reserved.
// Use of this source code is governed by the GPL-2.0 License that can be found in the LICENSE file.

#ifndef FS_QUADTREE_H
#define FS_QUADTREE_H

#include "otpch.h"

#include "creature.h"
#include "map.h"

class Creature;
class Tile;

namespace tfs::map::quadtree {

void find(uint16_t start_x, uint16_t start_y, uint16_t end_x, uint16_t end_y, SpectatorVec& spectators,
std::function<bool(Creature*)> comparasion);
void find(uint16_t start_x, uint16_t start_y, uint16_t end_x, uint16_t end_y,
std::function<void(std::set<Creature*>&)> comparasion);

/// @brief Finds the tile at the specified coordinates and layer.
Tile* find_tile(uint16_t x, uint16_t y, uint8_t z);
Expand Down Expand Up @@ -35,7 +44,7 @@ class QuadTree
{
public:
/// @brief Default constructor for QuadTree.
explicit QuadTree() = default;
constexpr QuadTree() = default;

/**
* @brief Virtual destructor for QuadTree.
Expand Down Expand Up @@ -98,7 +107,7 @@ class Node final : public QuadTree
{
public:
/// @brief Default constructor for QuadTree.
explicit Node() = default;
constexpr Node() = default;

/// Deleted copy constructor to ensure Node is non-copyable.
Node(const Node&) = delete;
Expand Down Expand Up @@ -230,3 +239,5 @@ class Leaf final : public QuadTree
Leaf* south_leaf = nullptr;
Leaf* east_leaf = nullptr;
};

#endif // FS_QUADTREE_H

0 comments on commit e8c8d4d

Please sign in to comment.