otland / forgottenserver

A free and open-source MMORPG server emulator written in C++
https://otland.net
GNU General Public License v2.0
1.56k stars 1.04k forks source link

classicAttackSpeed makes server go 100% CPU #4676

Closed gesior closed 2 months ago

gesior commented 2 months ago

Steps to reproduce

  1. Turn on classicAttackSpeed in config.lua
  2. Login 2 players few SQM from each other.
  3. Attack one player using melee weapon.
  4. Watch how number of doAttacking (or checkCreatureAttack) executions per second grows over time (OTS Stats or add 'std::cout' in that function)

You can make it go high faster by running around. Each step of attacked/attacking player adds 1 extra event.

Expected behaviour

Server checks players attacks every getAttackSpeed() - once, not multiple times.

Actual behaviour

Server adds new checkCreatureAttack event to Scheduler every second (onThink) and every player step. Each event is recurring, if target cannot be hit by player. Server generates infinite number of Scheduler events and CPU goes 100% after few minutes/hours.

Environment

Tested on TFS 1.4, but master code looks the same.

Fix

  1. In player.h under:

    uint32_t walkTaskEvent = 0;

    add:

    uint32_t classicAttackEvent = 0;
  2. In player.cpp in function void Player::doAttacking(uint32_t) replace:

    g_scheduler.addEvent(task);

    with:

    g_scheduler.stopEvent(classicAttackEvent);
    classicAttackEvent = g_scheduler.addEvent(task);

It will limit number of checkCreatureAttack events to 1 per player.