I'm writing a command .deposit $Character $moneyDelta
with this handler to increase the a character's gold when the character is offline.
static bool HandleDepositCommand(ChatHandler *handler, PlayerIdentifier player, uint32 moneyDelta)
{
ObjectGuid::LowType accountId = player.GetGUID().GetCounter();
// Player must not be in-game
if (player.IsConnected()) {
return false;
}
// The player should not log in until this function finishes execution
// TODO SQL query to increase gold
return true;
}
To ensure that the engine's cache doesn't overwrite my SQL write, I imposed a requirement that the player must not be signed in.
Is it possible for the player to connect before HandleDepositCommand()
finishes execution? If I understand correctly then the world process is a single threaded while loop where new actions such as new login get queued after HandleDepositCommand()
.
///- While we have not World::m_stopEvent, update the world
while (!World::IsStopped())
{
++World::m_worldLoopCounter;
realCurrTime = getMSTime();
uint32 diff = getMSTimeDiff(realPrevTime, realCurrTime);
if (diff < minUpdateDiff)
{
uint32 sleepTime = minUpdateDiff - diff;
if (sleepTime >= halfMaxCoreStuckTime)
LOG_ERROR("server.worldserver", "WorldUpdateLoop() waiting for {} ms with MaxCoreStuckTime set to {} ms", sleepTime, maxCoreStuckTime);
// sleep until enough time passes that we can update all timers
std::this_thread::sleep_for(Milliseconds(sleepTime));
continue;
}
sWorld->Update(diff);
realPrevTime = realCurrTime;
If not then this is a race condition that can lead to an exploit. The player logs in before the SQL completes overwrites the DB state.
There shouldn't be any race condition since chat commands and player logging both have "thread-unsafe" type which means they are running in the same thread.