Skip to content

Commit

Permalink
Improve: creature actions (#3084)
Browse files Browse the repository at this point in the history
Some creature actions, such as checkCreatureAttack, checkCreatureWalk,
updateCreatureWalk, were processed based on the creature ID, as canary
works with smart pointer, we no longer have problems working with the
object reference, before it used the ID to maintain security, because at
the time of execution, the object could no longer exist.
  • Loading branch information
mehah authored Dec 9, 2024
1 parent a81297a commit dec87cb
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 53 deletions.
50 changes: 41 additions & 9 deletions src/creatures/creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,20 @@ void Creature::onThink(uint32_t interval) {
onThink();
}

void Creature::checkCreatureAttack(bool now) {
if (now) {
if (isAlive()) {
onAttacking(0);
}
return;
}

g_dispatcher().addEvent([self = std::weak_ptr<Creature>(getCreature())] {
if (const auto &creature = self.lock()) {
creature->checkCreatureAttack(true);
} }, "Creature::checkCreatureAttack");
}

void Creature::onAttacking(uint32_t interval) {
const auto &attackedCreature = getAttackedCreature();
if (!attackedCreature) {
Expand All @@ -162,15 +176,19 @@ void Creature::onIdleStatus() {
}

void Creature::onCreatureWalk() {
if (checkingWalkCreature) {
if (checkingWalkCreature || isRemoved() || isDead()) {
return;
}

checkingWalkCreature = true;

metrics::method_latency measure(__METRICS_METHOD_NAME__);

g_dispatcher().addWalkEvent([self = getCreature(), this] {
g_dispatcher().addWalkEvent([self = std::weak_ptr<Creature>(getCreature()), this] {
if (!self.lock()) {
return;
}

checkingWalkCreature = false;
if (isRemoved()) {
return;
Expand Down Expand Up @@ -269,12 +287,16 @@ void Creature::addEventWalk(bool firstStep) {
safeCall([this, ticks]() {
// Take first step right away, but still queue the next
if (ticks == 1) {
g_game().checkCreatureWalk(getID());
onCreatureWalk();
}

eventWalk = g_dispatcher().scheduleEvent(
static_cast<uint32_t>(ticks),
[creatureId = getID()] { g_game().checkCreatureWalk(creatureId); }, "Game::checkCreatureWalk"
static_cast<uint32_t>(ticks), [self = std::weak_ptr<Creature>(getCreature())] {
if (const auto &creature = self.lock()) {
creature->onCreatureWalk();
}
},
"Game::checkCreatureWalk"
);
});
}
Expand Down Expand Up @@ -421,7 +443,7 @@ void Creature::onCreatureMove(const std::shared_ptr<Creature> &creature, const s
if (followCreature && (creature.get() == this || creature == followCreature)) {
if (hasFollowPath) {
isUpdatingPath = true;
g_game().updateCreatureWalk(getID()); // internally uses addEventWalk.
updateCreatureWalk();
}

if (newPos.z != oldPos.z || !canSee(followCreature->getPosition())) {
Expand All @@ -436,7 +458,7 @@ void Creature::onCreatureMove(const std::shared_ptr<Creature> &creature, const s
} else {
if (hasExtraSwing()) {
// our target is moving lets see if we can get in hit
g_dispatcher().addEvent([creatureId = getID()] { g_game().checkCreatureAttack(creatureId); }, "Game::checkCreatureAttack");
checkCreatureAttack();
}

if (newTile->getZoneType() != oldTile->getZoneType()) {
Expand Down Expand Up @@ -701,7 +723,13 @@ void Creature::changeHealth(int32_t healthChange, bool sendHealthChange /* = tru
g_game().addCreatureHealth(static_self_cast<Creature>());
}
if (health <= 0) {
g_dispatcher().addEvent([creatureId = getID()] { g_game().executeDeath(creatureId); }, "Game::executeDeath");
g_dispatcher().addEvent([self = std::weak_ptr<Creature>(getCreature())] {
if (const auto &creature = self.lock()) {
if (!creature->isRemoved()) {
g_game().afterCreatureZoneChange(creature, creature->getZones(), {});
creature->onDeath();
}
} }, "Game::executeDeath");
}
}

Expand Down Expand Up @@ -874,6 +902,10 @@ void Creature::getPathSearchParams(const std::shared_ptr<Creature> &, FindPathPa
}

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

if (!hasAsyncTaskFlag(Pathfinder) && onComplete) {
g_dispatcher().addEvent(std::move(onComplete), "goToFollowCreature_async");
}
Expand Down Expand Up @@ -1781,7 +1813,7 @@ void Creature::sendAsyncTasks() {
setAsyncTaskFlag(AsyncTaskRunning, true);
g_dispatcher().asyncEvent([self = std::weak_ptr<Creature>(getCreature())] {
if (const auto &creature = self.lock()) {
if (!creature->isRemoved()) {
if (!creature->isRemoved() && creature->isAlive()) {
for (const auto &task : creature->asyncTasks) {
task();
}
Expand Down
6 changes: 6 additions & 0 deletions src/creatures/creature.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,9 @@ class Creature : virtual public Thing, public SharedObject {
void addEventWalk(bool firstStep = false);
void stopEventWalk();

void updateCreatureWalk() {
goToFollowCreature_async();
}
void goToFollowCreature_async(std::function<void()> &&onComplete = nullptr);
virtual void goToFollowCreature();

Expand Down Expand Up @@ -482,6 +485,9 @@ class Creature : virtual public Thing, public SharedObject {
void setCreatureLight(LightInfo lightInfo);

virtual void onThink(uint32_t interval);

void checkCreatureAttack(bool now = false);

void onAttacking(uint32_t interval);
virtual void onCreatureWalk();
virtual bool getNextStep(Direction &dir, uint32_t &flags);
Expand Down
2 changes: 1 addition & 1 deletion src/creatures/monsters/monster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -954,7 +954,7 @@ bool Monster::selectTarget(const std::shared_ptr<Creature> &creature) {

if (isHostile() || isSummon()) {
if (setAttackedCreature(creature)) {
g_dispatcher().addEvent([creatureId = getID()] { g_game().checkCreatureAttack(creatureId); }, __FUNCTION__);
checkCreatureAttack();
}
}
return setFollowCreature(creature);
Expand Down
11 changes: 6 additions & 5 deletions src/creatures/players/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3430,9 +3430,10 @@ void Player::doAttacking(uint32_t interval) {
}

const auto &task = createPlayerTask(
std::max<uint32_t>(SCHEDULER_MINTICKS, delay),
[playerId = getID()] { g_game().checkCreatureAttack(playerId); },
__FUNCTION__
std::max<uint32_t>(SCHEDULER_MINTICKS, delay), [self = std::weak_ptr<Creature>(getCreature())] {
if (const auto &creature = self.lock()) {
creature->checkCreatureAttack(true);
} }, __FUNCTION__
);

if (!classicSpeed) {
Expand Down Expand Up @@ -5296,7 +5297,7 @@ bool Player::setAttackedCreature(const std::shared_ptr<Creature> &creature) {
}

if (creature) {
g_dispatcher().addEvent([creatureId = getID()] { g_game().checkCreatureAttack(creatureId); }, __FUNCTION__);
checkCreatureAttack();
}
return true;
}
Expand Down Expand Up @@ -9835,7 +9836,7 @@ void Player::onCreatureMove(const std::shared_ptr<Creature> &creature, const std
const auto &followCreature = getFollowCreature();
if (hasFollowPath && (creature == followCreature || (creature.get() == this && followCreature))) {
isUpdatingPath = false;
g_game().updateCreatureWalk(getID()); // internally uses addEventWalk.
updateCreatureWalk();
}

if (creature != getPlayer()) {
Expand Down
34 changes: 2 additions & 32 deletions src/game/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1255,15 +1255,6 @@ bool Game::removeCreature(const std::shared_ptr<Creature> &creature, bool isLogo
return true;
}

void Game::executeDeath(uint32_t creatureId) {
metrics::method_latency measure(__METRICS_METHOD_NAME__);
std::shared_ptr<Creature> creature = getCreatureByID(creatureId);
if (creature && !creature->isRemoved()) {
afterCreatureZoneChange(creature, creature->getZones(), {});
creature->onDeath();
}
}

void Game::playerTeleport(uint32_t playerId, const Position &newPosition) {
metrics::method_latency measure(__METRICS_METHOD_NAME__);
const auto &player = getPlayerByID(playerId);
Expand Down Expand Up @@ -5912,7 +5903,7 @@ void Game::playerSetAttackedCreature(uint32_t playerId, uint32_t creatureId) {
}

player->setAttackedCreature(attackCreature);
updateCreatureWalk(player->getID()); // internally uses addEventWalk.
player->updateCreatureWalk();
}

void Game::playerFollowCreature(uint32_t playerId, uint32_t creatureId) {
Expand All @@ -5922,7 +5913,7 @@ void Game::playerFollowCreature(uint32_t playerId, uint32_t creatureId) {
}

player->setAttackedCreature(nullptr);
updateCreatureWalk(player->getID()); // internally uses addEventWalk.
player->updateCreatureWalk();
player->setFollowCreature(getCreatureByID(creatureId));
}

Expand Down Expand Up @@ -6433,27 +6424,6 @@ bool Game::internalCreatureSay(const std::shared_ptr<Creature> &creature, SpeakC
return true;
}

void Game::checkCreatureWalk(uint32_t creatureId) {
const auto &creature = getCreatureByID(creatureId);
if (creature && creature->getHealth() > 0) {
creature->onCreatureWalk();
}
}

void Game::updateCreatureWalk(uint32_t creatureId) {
const auto &creature = getCreatureByID(creatureId);
if (creature && creature->getHealth() > 0) {
creature->goToFollowCreature_async();
}
}

void Game::checkCreatureAttack(uint32_t creatureId) {
const auto &creature = getCreatureByID(creatureId);
if (creature && creature->getHealth() > 0) {
creature->onAttacking(0);
}
}

void Game::addCreatureCheck(const std::shared_ptr<Creature> &creature) {
if (creature->isRemoved()) {
return;
Expand Down
4 changes: 0 additions & 4 deletions src/game/game.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,6 @@ class Game {
bool placeCreature(const std::shared_ptr<Creature> &creature, const Position &pos, bool extendedPos = false, bool force = false);

bool removeCreature(const std::shared_ptr<Creature> &creature, bool isLogout = true);
void executeDeath(uint32_t creatureId);

void addCreatureCheck(const std::shared_ptr<Creature> &creature);
static void removeCreatureCheck(const std::shared_ptr<Creature> &creature);
Expand Down Expand Up @@ -437,9 +436,6 @@ class Game {
void setGameState(GameState_t newState);

// Events
void checkCreatureWalk(uint32_t creatureId);
void updateCreatureWalk(uint32_t creatureId);
void checkCreatureAttack(uint32_t creatureId);
void checkCreatures();
void checkLight();

Expand Down
3 changes: 1 addition & 2 deletions src/game/scheduling/task.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,13 @@ class Task {
const static std::unordered_set<std::string_view> tasksContext = {
"Decay::checkDecay",
"Dispatcher::asyncEvent",
"Game::checkCreatureAttack",
"Creature::checkCreatureAttack",
"Game::checkCreatureWalk",
"Game::checkCreatures",
"Game::checkImbuements",
"Game::checkLight",
"Game::createFiendishMonsters",
"Game::createInfluencedMonsters",
"Game::updateCreatureWalk",
"Game::updateForgeableMonsters",
"Game::addCreatureCheck",
"GlobalEvents::think",
Expand Down

0 comments on commit dec87cb

Please sign in to comment.