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

Refactor quadtree: Extracted into tfs::map::quadtree namespace with code improvements and tests #4798

Open
wants to merge 48 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
0065b9e
Rework quadtree
ramon-bernardo Oct 5, 2024
35e0ee0
Use stl array
ramon-bernardo Oct 5, 2024
eee435c
Use inline instead static constexpr
ramon-bernardo Oct 5, 2024
e9d4f5f
Use int32_t instead of fast int32_t and auto when possible; move east…
ramon-bernardo Oct 5, 2024
30976c9
Remove remove erase check and fix comparison qt::find param
ramon-bernardo Oct 5, 2024
b7c3159
Fix use map quadtree
ramon-bernardo Oct 5, 2024
081114f
Rename namespace tfs::quadtree
ramon-bernardo Oct 5, 2024
18e1ea4
Add wildtree doc and some fix in namespace
ramon-bernardo Oct 5, 2024
cc7d235
Add quadtree doc
ramon-bernardo Oct 5, 2024
fe6172e
Simplify namespace doc
ramon-bernardo Oct 5, 2024
50b41c9
Add quadtree doc
ramon-bernardo Oct 5, 2024
d7cf93e
Rename push method, some doc fix
ramon-bernardo Oct 5, 2024
05f887e
Fix quadtree
ramon-bernardo Oct 5, 2024
e8c8d4d
Fix quadtree
ramon-bernardo Oct 6, 2024
ade4eb8
Remove unused z position
ramon-bernardo Oct 6, 2024
10594d5
Impl destructors
ramon-bernardo Oct 6, 2024
657d756
Impl destructors
ramon-bernardo Oct 6, 2024
26420d3
Use generator isntead comparasion
ramon-bernardo Oct 6, 2024
6c301d9
Remove const
ramon-bernardo Oct 6, 2024
33f3b2a
Fix nullptr check
ramon-bernardo Oct 6, 2024
9ad4755
Fix the creation of quadtree leaf nodes
ramon-bernardo Oct 6, 2024
fce5839
Add quadtree test
ramon-bernardo Oct 6, 2024
ab8a668
Fix quadtree function
ramon-bernardo Oct 6, 2024
94f660a
Fix quadtree
ramon-bernardo Oct 6, 2024
8877e35
Add tfs::generator
ramon-bernardo Oct 6, 2024
1ef0a43
Bump cmake C++23
ramon-bernardo Oct 6, 2024
d083eac
Add tfs::generator
ramon-bernardo Oct 6, 2024
01ed2d8
Add tfs::generator
ramon-bernardo Oct 6, 2024
9ff7d47
Add tfs::generator
ramon-bernardo Oct 6, 2024
33f00bd
Test bump gh os
ramon-bernardo Oct 6, 2024
20b994b
Revert "Test bump gh os"
ramon-bernardo Oct 6, 2024
bc23c52
Force use experimental generator
ramon-bernardo Oct 25, 2024
98daa5e
Use SpectatorVec instead generators
ramon-bernardo Oct 26, 2024
8272891
Use explicit const.
ramon-bernardo Oct 26, 2024
1061f10
Fix tests
ramon-bernardo Oct 26, 2024
228911c
Fix tests
ramon-bernardo Oct 26, 2024
010fa48
Fix tests
ramon-bernardo Oct 26, 2024
819c7b6
Fix tests
ramon-bernardo Oct 26, 2024
13caf97
Add new tests
ramon-bernardo Oct 26, 2024
63cd064
Fix tests
ramon-bernardo Oct 26, 2024
1ca68f5
Fix tests
ramon-bernardo Oct 26, 2024
d8d7df7
Fix tests
ramon-bernardo Oct 26, 2024
14c00d3
Create leaf node if not exists
ramon-bernardo Oct 26, 2024
fd9e407
Add method to reset quadtree and fix tests
ramon-bernardo Oct 26, 2024
938396a
Add method to reset quadtree ad remove precompiled header
ramon-bernardo Oct 26, 2024
9c920bf
Add method to reset quadtree
ramon-bernardo Oct 26, 2024
c3a5e0d
Remove quadtree test
ramon-bernardo Oct 26, 2024
9d8fedd
Merge branch 'master' into quadtree-rework-and-tests
ramon-bernardo Nov 17, 2024
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
Prev Previous commit
Next Next commit
Fix quadtree
  • Loading branch information
ramon-bernardo committed Oct 6, 2024
commit e8c8d4ddd8716c4c80f05ac255b6ba6fe0674699
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 @@

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 @@
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 @@
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 @@

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 Expand Up @@ -119,7 +114,7 @@
}
}

void tfs::map::quadtree::move_creature(uint16_t old_x, uint16_t old_y, uint8_t old_z, uint16_t x, uint16_t y, uint8_t z,

Check failure on line 117 in src/quadtree.cpp

View workflow job for this annotation

GitHub Actions / test

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

Check failure on line 117 in src/quadtree.cpp

View workflow job for this annotation

GitHub Actions / test

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

Check failure on line 117 in src/quadtree.cpp

View workflow job for this annotation

GitHub Actions / macos-Debug-luajit=on

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

Check failure on line 117 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 117 in src/quadtree.cpp

View workflow job for this annotation

GitHub Actions / macos-Debug-luajit=off

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

Check failure on line 117 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 117 in src/quadtree.cpp

View workflow job for this annotation

GitHub Actions / macos-Release-luajit=on

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

Check failure on line 117 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 117 in src/quadtree.cpp

View workflow job for this annotation

GitHub Actions / macos-Release-luajit=off

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

Check failure on line 117 in src/quadtree.cpp

View workflow job for this annotation

GitHub Actions / macos-Release-luajit=off

unused parameter 'z' [-Werror,-Wunused-parameter]
Creature* creature)
{
if (auto old_leaf = find_leaf_in_root(old_x, old_y); auto leaf = find_leaf_in_root(x, y)) {
Fixed Show fixed Hide fixed
Expand All @@ -130,14 +125,14 @@
}
}

void tfs::map::quadtree::push_creature(uint16_t x, uint16_t y, uint8_t z, Creature* creature)

Check failure on line 128 in src/quadtree.cpp

View workflow job for this annotation

GitHub Actions / test

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

Check failure on line 128 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 128 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 128 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 128 in src/quadtree.cpp

View workflow job for this annotation

GitHub Actions / macos-Release-luajit=off

unused parameter 'z' [-Werror,-Wunused-parameter]
{
if (auto leaf = find_leaf_in_root(x, y)) {
leaf->push_creature(creature);
}
}

void tfs::map::quadtree::remove_creature(uint16_t x, uint16_t y, uint8_t z, Creature* creature)

Check failure on line 135 in src/quadtree.cpp

View workflow job for this annotation

GitHub Actions / test

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

Check failure on line 135 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 135 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 135 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 135 in src/quadtree.cpp

View workflow job for this annotation

GitHub Actions / macos-Release-luajit=off

unused parameter 'z' [-Werror,-Wunused-parameter]
{
if (auto leaf = find_leaf_in_root(x, y)) {
leaf->remove_creature(creature);
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
Loading