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

feat: pathfinder multithreading #1646

Merged
merged 57 commits into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
219d19e
init
mehah Sep 28, 2023
47ec6b0
improve
mehah Sep 28, 2023
d7f833f
improve
mehah Sep 28, 2023
f79ef3b
Merge branch 'main' into pathfinder-multithread
mehah Sep 28, 2023
db31c6b
improve
mehah Sep 28, 2023
9309300
Merge branch 'main' into pathfinder-multithread
mehah Sep 29, 2023
e233f80
changes
mehah Sep 29, 2023
427bc64
Merge branch 'main' into pathfinder-multithread
mehah Sep 29, 2023
c279611
Merge branch 'main' into pathfinder-multithread
mehah Sep 29, 2023
0b0e9af
silence task
luan Oct 1, 2023
d60d234
use flags instead of checking items vector in hasProperty
mehah Oct 2, 2023
c11bae2
Code format - (Clang-format)
github-actions[bot] Oct 2, 2023
e20c1df
setTileFlags for ground
mehah Oct 2, 2023
e16c533
Merge branch 'pathfinder-multithread' of https://github.com/opentibia…
mehah Oct 2, 2023
543fc25
improve + security
mehah Oct 2, 2023
49403c1
fix warning
mehah Oct 2, 2023
20e23f6
change order
mehah Oct 2, 2023
3bd1400
cleanup
mehah Oct 3, 2023
7049f53
Code format - (Clang-format)
github-actions[bot] Oct 3, 2023
59d1eac
auto to bool
mehah Oct 3, 2023
1d24a22
threadsafe: hasCondition and getTopVisibleCreature
mehah Oct 3, 2023
1c45b40
Merge branch 'main' into pathfinder-multithread
mehah Oct 7, 2023
ca29900
Code format - (Clang-format)
github-actions[bot] Oct 7, 2023
1cf1dc8
Update map.cpp
mehah Oct 7, 2023
9268808
removed position check
mehah Oct 9, 2023
f2f98b0
removed position check
mehah Oct 9, 2023
11d003f
Merge branch 'main' into pathfinder-multithread
mehah Oct 11, 2023
5ca4199
Merge branch 'main' into pathfinder-multithread
mehah Oct 18, 2023
4fb63fe
Merge branch 'main' into pathfinder-multithread
mehah Oct 23, 2023
0342b55
use asyncEvent
mehah Oct 23, 2023
6a62013
Code format - (Clang-format)
github-actions[bot] Oct 23, 2023
54a0979
use deque instead of forward_list, it's faster.
mehah Oct 23, 2023
07e7b43
use arraylist
mehah Oct 23, 2023
f36ceab
walk fix
mehah Oct 23, 2023
3f7c8aa
Code format - (Clang-format)
github-actions[bot] Oct 23, 2023
04e9331
Update creature.cpp
mehah Oct 23, 2023
38da18d
Update arraylist.hpp
mehah Oct 23, 2023
e34999e
Merge branch 'main' into pathfinder-multithread
mehah Oct 25, 2023
81829ec
Lua code format - (Stylua)
github-actions[bot] Oct 25, 2023
0a321f1
condition_variable to atomic_wait
mehah Oct 25, 2023
f28bf23
Merge branch 'main' into pathfinder-multithread
mehah Oct 25, 2023
2980466
fix smell
mehah Oct 25, 2023
f9a1553
Update dispatcher.cpp
mehah Oct 25, 2023
18be95e
improve
mehah Oct 25, 2023
6c47163
rework
mehah Oct 26, 2023
3250d3f
Update creature.cpp
mehah Oct 26, 2023
761cafe
improve
mehah Oct 26, 2023
ba5bf04
fix
mehah Oct 26, 2023
57aa2b0
Update creature.cpp
mehah Oct 26, 2023
570efba
Update dispatcher.cpp
mehah Oct 26, 2023
df869e7
Update dispatcher.cpp
mehah Oct 26, 2023
bd6f54b
improve
mehah Oct 26, 2023
2ecf669
Update dispatcher.cpp
mehah Oct 26, 2023
f12d4a4
checkPendingTasks
mehah Oct 26, 2023
c367db8
Merge branch 'main' into pathfinder-multithread
mehah Oct 29, 2023
4d3261f
Merge branch 'main' into pathfinder-multithread
mehah Oct 30, 2023
ddf85ae
Merge branch 'main' into pathfinder-multithread
dudantas Nov 2, 2023
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
2 changes: 1 addition & 1 deletion src/creatures/combat/combat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -898,7 +898,7 @@ void Combat::addDistanceEffect(std::shared_ptr<Creature> caster, const Position

void Combat::doChainEffect(const Position &origin, const Position &dest, uint8_t effect) {
if (effect > 0) {
std::forward_list<Direction> dirList;
stdext::arraylist<Direction> dirList(128);
FindPathParams fpp;
fpp.minTargetDist = 0;
fpp.maxTargetDist = 1;
Expand Down
6 changes: 3 additions & 3 deletions src/creatures/combat/condition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1929,7 +1929,7 @@ bool ConditionFeared::getFleeDirection(std::shared_ptr<Creature> creature) {
return false;
}

bool ConditionFeared::getFleePath(std::shared_ptr<Creature> creature, const Position &pos, std::forward_list<Direction> &dirList) {
bool ConditionFeared::getFleePath(std::shared_ptr<Creature> creature, const Position &pos, stdext::arraylist<Direction> &dirList) {
const std::vector<uint8_t> walkSize { 15, 9, 3, 1 };
bool found = false;
std::ptrdiff_t found_size = 0;
Expand Down Expand Up @@ -2030,7 +2030,7 @@ bool ConditionFeared::startCondition(std::shared_ptr<Creature> creature) {

bool ConditionFeared::executeCondition(std::shared_ptr<Creature> creature, int32_t interval) {
Position currentPos = creature->getPosition();
std::forward_list<Direction> listDir;
stdext::arraylist<Direction> listDir(128);

g_logger().debug("[ConditionFeared::executeCondition] Executing condition, current position is {}", currentPos.toString());

Expand All @@ -2040,7 +2040,7 @@ bool ConditionFeared::executeCondition(std::shared_ptr<Creature> creature, int32
}

if (getFleePath(creature, currentPos, listDir)) {
g_dispatcher().addEvent(std::bind(&Game::forcePlayerAutoWalk, &g_game(), creature->getID(), listDir), "ConditionFeared::executeCondition");
g_dispatcher().addEvent(std::bind(&Game::forcePlayerAutoWalk, &g_game(), creature->getID(), listDir.data()), "ConditionFeared::executeCondition");
g_logger().debug("[ConditionFeared::executeCondition] Walking Scheduled");
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/creatures/combat/condition.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ class ConditionFeared final : public Condition {
private:
bool canWalkTo(std::shared_ptr<Creature> creature, Position pos, Direction moveDirection) const;
bool getFleeDirection(std::shared_ptr<Creature> creature);
bool getFleePath(std::shared_ptr<Creature> creature, const Position &pos, std::forward_list<Direction> &dirList);
bool getFleePath(std::shared_ptr<Creature> creature, const Position &pos, stdext::arraylist<Direction> &dirList);
bool getRandomDirection(std::shared_ptr<Creature> creature, Position pos);
bool isStuck(std::shared_ptr<Creature> creature, Position pos) const;

Expand Down
173 changes: 94 additions & 79 deletions src/creatures/creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,16 +133,23 @@ void Creature::onThink(uint32_t interval) {
}
}

auto onThink = [self = getCreature(), interval] {
// scripting event - onThink
const auto &thinkEvents = self->getCreatureEvents(CREATURE_EVENT_THINK);
for (const auto creatureEventPtr : thinkEvents) {
creatureEventPtr->executeOnThink(self->static_self_cast<Creature>(), interval);
}
};

if (isUpdatingPath) {
isUpdatingPath = false;
goToFollowCreature();
g_dispatcher().asyncEvent([self = getCreature(), onThink = std::move(onThink)] {
self->isUpdatingPath = false;
self->goToFollowCreature_async(onThink);
});
return;
}

// scripting event - onThink
const CreatureEventList &thinkEvents = getCreatureEvents(CREATURE_EVENT_THINK);
for (const auto creatureEventPtr : thinkEvents) {
creatureEventPtr->executeOnThink(static_self_cast<Creature>(), interval);
}
onThink();
}

void Creature::onAttacking(uint32_t interval) {
Expand Down Expand Up @@ -224,18 +231,20 @@ bool Creature::getNextStep(Direction &dir, uint32_t &) {
return true;
}

void Creature::startAutoWalk(const std::forward_list<Direction> &listDir, bool ignoreConditions /* = false*/) {
void Creature::startAutoWalk(const std::vector<Direction> &listDir, bool ignoreConditions /* = false*/) {
listWalkDir.clear();

if (!ignoreConditions && (hasCondition(CONDITION_ROOTED) || hasCondition(CONDITION_FEARED))) {
return;
}

listWalkDir = listDir;
listWalkDir = { listDir.begin(), listDir.end() };

size_t size = 0;
for (auto it = listDir.begin(); it != listDir.end() && size <= 1; ++it) {
size++;
if (listWalkDir.empty()) {
return;
}
addEventWalk(size == 1);

addEventWalk(listWalkDir.size() == 1);
}

void Creature::addEventWalk(bool firstStep) {
Expand All @@ -249,20 +258,22 @@ void Creature::addEventWalk(bool firstStep) {
return;
}

int64_t ticks = getEventStepTicks(firstStep);
const int64_t ticks = getEventStepTicks(firstStep);
if (ticks <= 0) {
return;
}

// Take first step right away, but still queue the next
if (ticks == 1) {
g_game().checkCreatureWalk(getID());
}
g_dispatcher().context().tryAddEvent([ticks, self = getCreature()]() {
// Take first step right away, but still queue the next
if (ticks == 1) {
g_game().checkCreatureWalk(self->getID());
}

eventWalk = g_dispatcher().scheduleEvent(
static_cast<uint32_t>(ticks), std::bind(&Game::checkCreatureWalk, &g_game(), getID()),
"Creature::checkCreatureWalk"
);
self->eventWalk = g_dispatcher().scheduleEvent(
static_cast<uint32_t>(ticks), std::bind(&Game::checkCreatureWalk, &g_game(), self->getID()),
"Creature::checkCreatureWalk"
);
});
}

void Creature::stopEventWalk() {
Expand Down Expand Up @@ -320,11 +331,7 @@ int32_t Creature::getWalkCache(const Position &pos) {
if (std::abs(dx) <= maxWalkCacheWidth) {
int32_t dy = Position::getOffsetY(pos, myPos);
if (std::abs(dy) <= maxWalkCacheHeight) {
if (localMapCache[maxWalkCacheHeight + dy][maxWalkCacheWidth + dx]) {
return 1;
} else {
return 0;
}
return localMapCache[maxWalkCacheHeight + dy][maxWalkCacheWidth + dx];
}
}

Expand Down Expand Up @@ -464,7 +471,7 @@ void Creature::checkSummonMove(const Position &newPos, bool teleportSummon) {
}
}

void Creature::onCreatureMove(std::shared_ptr<Creature> creature, std::shared_ptr<Tile> newTile, const Position &newPos, std::shared_ptr<Tile> oldTile, const Position &oldPos, bool teleport) {
void Creature::onCreatureMove(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Tile> &newTile, const Position &newPos, const std::shared_ptr<Tile> &oldTile, const Position &oldPos, bool teleport) {
if (creature == getCreature()) {
lastStep = OTSYS_TIME();
lastStepCost = 1;
Expand Down Expand Up @@ -512,7 +519,7 @@ void Creature::onCreatureMove(std::shared_ptr<Creature> creature, std::shared_pt

// update 0
for (int32_t x = -maxWalkCacheWidth; x <= maxWalkCacheWidth; ++x) {
std::shared_ptr<Tile> cacheTile = g_game().map.getTile(static_cast<uint16_t>(myPos.getX() + x), static_cast<uint16_t>(myPos.getY() - maxWalkCacheHeight), myPos.z);
const auto &cacheTile = g_game().map.getTile(static_cast<uint16_t>(myPos.getX() + x), static_cast<uint16_t>(myPos.getY() - maxWalkCacheHeight), myPos.z);
updateTileCache(cacheTile, x, -maxWalkCacheHeight);
}
} else if (oldPos.y < newPos.y) { // south
Expand All @@ -523,7 +530,7 @@ void Creature::onCreatureMove(std::shared_ptr<Creature> creature, std::shared_pt

// update mapWalkHeight - 1
for (int32_t x = -maxWalkCacheWidth; x <= maxWalkCacheWidth; ++x) {
std::shared_ptr<Tile> cacheTile = g_game().map.getTile(static_cast<uint16_t>(myPos.getX() + x), static_cast<uint16_t>(myPos.getY() + maxWalkCacheHeight), myPos.z);
const auto &cacheTile = g_game().map.getTile(static_cast<uint16_t>(myPos.getX() + x), static_cast<uint16_t>(myPos.getY() + maxWalkCacheHeight), myPos.z);
updateTileCache(cacheTile, x, maxWalkCacheHeight);
}
}
Expand All @@ -548,7 +555,7 @@ void Creature::onCreatureMove(std::shared_ptr<Creature> creature, std::shared_pt

// update mapWalkWidth - 1
for (int32_t y = -maxWalkCacheHeight; y <= maxWalkCacheHeight; ++y) {
std::shared_ptr<Tile> cacheTile = g_game().map.getTile(myPos.x + maxWalkCacheWidth, static_cast<uint16_t>(myPos.y + y), myPos.z);
const auto &cacheTile = g_game().map.getTile(myPos.x + maxWalkCacheWidth, static_cast<uint16_t>(myPos.y + y), myPos.z);
updateTileCache(cacheTile, maxWalkCacheWidth, y);
}
} else if (oldPos.x > newPos.x) { // west
Expand Down Expand Up @@ -593,7 +600,7 @@ void Creature::onCreatureMove(std::shared_ptr<Creature> creature, std::shared_pt
}
}

auto followCreature = getFollowCreature();
const auto &followCreature = getFollowCreature();
if (followCreature && (creature == getCreature() || creature == followCreature)) {
if (hasFollowPath) {
isUpdatingPath = true;
Expand All @@ -605,7 +612,7 @@ void Creature::onCreatureMove(std::shared_ptr<Creature> creature, std::shared_pt
}
}

auto attackedCreature = getAttackedCreature();
const auto &attackedCreature = getAttackedCreature();
if (attackedCreature && (creature == attackedCreature || creature == getCreature())) {
if (newPos.z != oldPos.z || !canSee(attackedCreature->getPosition())) {
onCreatureDisappear(attackedCreature, false);
Expand Down Expand Up @@ -948,63 +955,72 @@ bool Creature::setAttackedCreature(std::shared_ptr<Creature> creature) {
return true;
}

void Creature::getPathSearchParams(std::shared_ptr<Creature>, FindPathParams &fpp) {
void Creature::getPathSearchParams(const std::shared_ptr<Creature> &, FindPathParams &fpp) {
fpp.fullPathSearch = !hasFollowPath;
fpp.clearSight = true;
fpp.maxSearchDist = 12;
fpp.minTargetDist = 1;
fpp.maxTargetDist = 1;
}

void Creature::goToFollowCreature_async(std::function<void()> &&onComplete) {
if (pathfinderRunning.load()) {
return;
}

pathfinderRunning.store(true);
g_dispatcher().asyncEvent([self = getCreature()] {
self->goToFollowCreature();
self->pathfinderRunning.store(false);
});

if (onComplete) {
g_dispatcher().context().addEvent(std::move(onComplete));
}
}

void Creature::goToFollowCreature() {
auto followCreature = getFollowCreature();
if (followCreature) {
if (isSummon() && !getMonster()->isFamiliar() && !canFollowMaster()) {
hasFollowPath = false;
return;
}
const auto &followCreature = getFollowCreature();
if (!followCreature) {
return;
}

FindPathParams fpp;
getPathSearchParams(followCreature, fpp);
std::shared_ptr<Monster> monster = getMonster();
if (monster && !monster->getMaster() && (monster->isFleeing() || fpp.maxTargetDist > 1)) {
Direction dir = DIRECTION_NONE;

if (monster->isFleeing()) {
monster->getDistanceStep(followCreature->getPosition(), dir, true);
} else { // maxTargetDist > 1
if (!monster->getDistanceStep(followCreature->getPosition(), dir)) {
// if we can't get anything then let the A* calculate
listWalkDir.clear();
if (getPathTo(followCreature->getPosition(), listWalkDir, fpp)) {
hasFollowPath = true;
startAutoWalk(listWalkDir);
} else {
hasFollowPath = false;
}
return;
}
}
const auto &monster = getMonster();

if (dir != DIRECTION_NONE) {
listWalkDir.clear();
listWalkDir.push_front(dir);
if (isSummon() && !monster->isFamiliar() && !canFollowMaster()) {
listWalkDir.clear();
return;
}

hasFollowPath = true;
startAutoWalk(listWalkDir);
}
} else {
listWalkDir.clear();
if (getPathTo(followCreature->getPosition(), listWalkDir, fpp)) {
hasFollowPath = true;
startAutoWalk(listWalkDir);
} else {
hasFollowPath = false;
}
bool executeOnFollow = true;
stdext::arraylist<Direction> listDir(128);

FindPathParams fpp;
getPathSearchParams(followCreature, fpp);

if (monster && !monster->getMaster() && (monster->isFleeing() || fpp.maxTargetDist > 1)) {
Direction dir = DIRECTION_NONE;

if (monster->isFleeing()) {
monster->getDistanceStep(followCreature->getPosition(), dir, true);
} else if (!monster->getDistanceStep(followCreature->getPosition(), dir)) { // maxTargetDist > 1
// if we can't get anything then let the A* calculate
executeOnFollow = false;
} else if (dir != DIRECTION_NONE) {
listDir.push_back(dir);
hasFollowPath = true;
}
}

onFollowCreatureComplete(followCreature);
if (listDir.empty()) {
hasFollowPath = getPathTo(getFollowCreature()->getPosition(), listDir, fpp);
}

startAutoWalk(listDir.data());

if (executeOnFollow) {
onFollowCreatureComplete(getFollowCreature());
}
}

bool Creature::canFollowMaster() {
Expand Down Expand Up @@ -1248,7 +1264,6 @@ bool Creature::addCondition(std::shared_ptr<Condition> condition) {
std::shared_ptr<Condition> prevCond = getCondition(condition->getType(), condition->getId(), condition->getSubId());
if (prevCond) {
prevCond->addCondition(getCreature(), condition);

return true;
}

Expand Down Expand Up @@ -1638,11 +1653,11 @@ bool Creature::isInvisible() const {
!= conditions.end();
}

bool Creature::getPathTo(const Position &targetPos, std::forward_list<Direction> &dirList, const FindPathParams &fpp) {
bool Creature::getPathTo(const Position &targetPos, stdext::arraylist<Direction> &dirList, const FindPathParams &fpp) {
return g_game().map.getPathMatching(getCreature(), dirList, FrozenPathingConditionCall(targetPos), fpp);
}

bool Creature::getPathTo(const Position &targetPos, std::forward_list<Direction> &dirList, int32_t minTargetDist, int32_t maxTargetDist, bool fullPathSearch /*= true*/, bool clearSight /*= true*/, int32_t maxSearchDist /*= 7*/) {
bool Creature::getPathTo(const Position &targetPos, stdext::arraylist<Direction> &dirList, int32_t minTargetDist, int32_t maxTargetDist, bool fullPathSearch /*= true*/, bool clearSight /*= true*/, int32_t maxSearchDist /*= 7*/) {
FindPathParams fpp;
fpp.fullPathSearch = fullPathSearch;
fpp.maxSearchDist = maxSearchDist;
Expand Down
Loading
Loading