Fix respawn/spawn timers racing ahead under multi-threading
POSIX clock() sums CPU time across every thread in the process, unlike Windows' clock() which tracks wall-clock milliseconds. With several worker threads running, respawn/spawn/AI timers based on clock() raced far ahead of real elapsed time. Switch spawn-timer bookkeeping to time(NULL)/time_t (seconds) throughout the world server, and add a portable clock() shim in sockets.h (backed by CLOCK_MONOTONIC, millisecond resolution) for remaining call sites so CLOCKS_PER_SEC==1000 still holds like it did on Windows. Also: fix MapDelay/VisualDelay/WorldDelay being passed to usleep() (us) without converting from their configured milliseconds; fix the shutdown timer likewise; stop leaking the temporary actor used to run an NPC's AIP script; fix CleanDrops() skipping the element that shifts into position after an erase. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1f626c6b93
commit
725620e23c
8 files changed
+66
-37
No files matched your search
@@ -118,8 +118,8 @@ PVOID MapProcess( PVOID TS )
|
||||
if(nextmon != 0)
|
||||
{
|
||||
//Log(MSG_DEBUG,"Spawning TD mobs");
|
||||
clock_t etime = clock() - map->lastTDSpawnTime;
|
||||
if(etime >= map->TDMobDelay) // check if elapsed time is greater than spawn delay
|
||||
time_t etime = time(NULL) - map->lastTDSpawnTime;
|
||||
if(etime >= (time_t)(map->TDMobDelay/1000)) // check if elapsed time (seconds) is greater than spawn delay (TDMobDelay is in ms)
|
||||
{
|
||||
//spawn the next monster on the list
|
||||
//Log(MSG_DEBUG,"Spawning TD mob of type %i at position %i in the list for map %i",nextmon, map->TDNextSpawn, map->id);
|
||||
@@ -130,7 +130,7 @@ PVOID MapProcess( PVOID TS )
|
||||
map->TDNextSpawn++; //move the pointer
|
||||
//Log(MSG_DEBUG,"moved the pointer");
|
||||
if(map->TDNextSpawn > 100)map->TDNextSpawn = 0;
|
||||
map->lastTDSpawnTime = clock();
|
||||
map->lastTDSpawnTime = time(NULL);
|
||||
}
|
||||
}
|
||||
//TD spawn end
|
||||
@@ -330,8 +330,8 @@ PVOID MapProcess( PVOID TS )
|
||||
//Log(MSG_DEBUG,"NPC %i is registered as in battle",monster->thisnpc->id);
|
||||
monster->DoAttack( );
|
||||
}
|
||||
//map->DeleteMonster(monster);
|
||||
//delete monster;
|
||||
GServer->ClearClientID( monster->clientid ); // temp actor for running the NPC's AIP script; never added to MonsterList
|
||||
delete monster;
|
||||
npc->lastAiUpdate = clock();
|
||||
if(AIP == GServer->Config.AIWatch)
|
||||
Log(MSG_DEBUG,"LastAiUpdate clock reset");
|
||||
@@ -359,7 +359,7 @@ PVOID MapProcess( PVOID TS )
|
||||
#ifdef _WIN32
|
||||
Sleep(GServer->Config.MapDelay);
|
||||
#else
|
||||
usleep(GServer->Config.MapDelay);
|
||||
usleep(GServer->Config.MapDelay * 1000); // MapDelay is in milliseconds; usleep wants microseconds
|
||||
#endif
|
||||
}
|
||||
pthread_exit( NULL );
|
||||
@@ -393,7 +393,7 @@ PVOID VisibilityProcess(PVOID TS)
|
||||
#ifdef _WIN32
|
||||
Sleep(GServer->Config.VisualDelay);
|
||||
#else
|
||||
usleep(GServer->Config.VisualDelay);
|
||||
usleep(GServer->Config.VisualDelay * 1000); // VisualDelay is in milliseconds; usleep wants microseconds
|
||||
#endif
|
||||
}
|
||||
pthread_exit(NULL);
|
||||
@@ -424,7 +424,7 @@ PVOID WorldProcess( PVOID TS )
|
||||
#ifdef _WIN32
|
||||
Sleep(GServer->Config.WorldDelay);
|
||||
#else
|
||||
usleep(GServer->Config.WorldDelay);
|
||||
usleep(GServer->Config.WorldDelay * 1000); // WorldDelay is in milliseconds; usleep wants microseconds
|
||||
#endif
|
||||
}
|
||||
pthread_exit(NULL);
|
||||
@@ -438,7 +438,7 @@ void ShutdownServer(PVOID TS)
|
||||
#ifdef _WIN32
|
||||
Sleep(minutes*60000);
|
||||
#else
|
||||
usleep(minutes*60000);
|
||||
sleep(minutes*60); // minutes*60000 was milliseconds; sleep() wants seconds
|
||||
#endif
|
||||
Log( MSG_INFO, "Saving User Information... " );
|
||||
GServer->DisconnectAll();
|
||||
|
||||
Reference in new issue
Block a user