KingMort
11-28-2008, 10:18 AM
OK well maybe some servers have not experienced this, and maybe this has already been posted hopefully not anyway..
Rampage AA you can actually crash zones using it.. If you want to block a certain guild it comes in handy you simply pull the entire zone and use it and blam crashage of the zoneage...
The same also applies for Wizard AOE nukes when killing too many mobs at once...
King
AndMetal
11-29-2008, 05:51 AM
OK well maybe some servers have not experienced this, and maybe this has already been posted hopefully not anyway..
Rampage AA you can actually crash zones using it.. If you want to block a certain guild it comes in handy you simply pull the entire zone and use it and blam crashage of the zoneage...
The same also applies for Wizard AOE nukes when killing too many mobs at once...
King
http://www.eqemulator.net/forums/showthread.php?t=26592
I was actually just thinking about this over the past few days, and trying to figure out if there are any opportunities.
I think one big question I have is, are we doing any actual multi-threading in the zone process? As far as I can tell, it doesn't look like it. It basically looks like we're just going down the list of everything that needs to be done throughout the main while loop:
while(RunLoops) {
{ //profiler block to omit the sleep from times
_ZP(net_main);
//Advance the timer to our current point in time
Timer::SetCurrentTime();
//process stuff from world
#ifdef CATCH_CRASH
try{
#endif
worldserver.Process();
#ifdef CATCH_CRASH
}
catch(...){
error = 1;
worldserver.Disconnect();
worldwasconnected = false;
}
#endif
if (!eqsf.IsOpen() && Config->ZonePort!=0) {
_log(ZONE__INIT, "Starting EQ Network server on port %d",Config->ZonePort);
if (!eqsf.Open(Config->ZonePort)) {
_log(ZONE__INIT_ERR, "Failed to open port %d",Config->ZonePort);
ZoneConfig::SetZonePort(0);
worldserver.Disconnect();
worldwasconnected = false;
}
}
//check the factory for any new incoming streams.
while ((eqss = eqsf.Pop())) {
//pull the stream out of the factory and give it to the stream identifier
//which will figure out what patch they are running, and set up the dynamic
//structures and opcodes for that patch.
struct in_addr in;
in.s_addr = eqss->GetRemoteIP();
_log(WORLD__CLIENT, "New connection from %s:%d", inet_ntoa(in),ntohs(eqss->GetRemotePort()));
stream_identifier.AddStream(eqss); //takes the stream
}
//give the stream identifier a chance to do its work....
stream_identifier.Process();
//check the stream identifier for any now-identified streams
while((eqsi = stream_identifier.PopIdentified())) {
//now that we know what patch they are running, start up their client object
struct in_addr in;
in.s_addr = eqsi->GetRemoteIP();
_log(WORLD__CLIENT, "New client from %s:%d", inet_ntoa(in), ntohs(eqsi->GetRemotePort()));
Client* client = new Client(eqsi);
entity_list.AddClient(client);
}
//check for timeouts in other threads
timeout_manager.CheckTimeouts();
if (worldserver.Connected()) {
worldwasconnected = true;
}
else {
if (worldwasconnected && ZoneLoaded)
entity_list.ChannelMessageFromWorld(0, 0, 6, 0, 0, "WARNING: World server connection lost");
worldwasconnected = false;
}
if (ZoneLoaded && temp_timer.Check()) {
{
int8 error2 = 4;
#ifdef CATCH_CRASH
try{
#endif
if(net.group_timer.Enabled() && net.group_timer.Check())
entity_list.GroupProcess();
error2 = 99;
if(net.door_timer.Enabled() && net.door_timer.Check())
entity_list.DoorProcess();
error2 = 98;
if(net.object_timer.Enabled() && net.object_timer.Check())
entity_list.ObjectProcess();
error2 = 97;
if(net.corpse_timer.Enabled() && net.corpse_timer.Check())
entity_list.CorpseProcess();
if(net.trap_timer.Enabled() && net.trap_timer.Check())
entity_list.TrapProcess();
if(net.raid_timer.Enabled() && net.raid_timer.Check())
entity_list.RaidProcess();
error2 = 98;
error2 = 96;
entity_list.Process();
error2 = 95;
#ifdef CATCH_CRASH
try{
entity_list.MobProcess();
}
catch(...){
printf("Catching Mob Crash...\n");
}
#else
entity_list.MobProcess();
#endif
error2 = 94;
entity_list.BeaconProcess();
#ifdef CATCH_CRASH
}
catch(...){
error=error2;
}
try{
#endif
if (zone) {
zoneprocess= zone->Process();
if (!zoneprocess) {
Zone::Shutdown();
}
}
#ifdef CATCH_CRASH
}
catch(...){
error = 2;
}
try{
#endif
if(quest_timers.Check())
quest_manager.Process();
#ifdef CATCH_CRASH
}
catch(...){
error = 77777;
}
#endif
}
}
DBAsyncWork* dbaw = 0;
while ((dbaw = MTdbafq.Pop())) {
DispatchFinishedDBAsync(dbaw);
}
if (InterserverTimer.Check()
#ifdef CATCH_CRASH
&& !error
#endif
) {
#ifdef CATCH_CRASH
try{
#endif
InterserverTimer.Start();
database.ping();
AsyncLoadVariables(dbasync, &database);
// NPC::GetAILevel(true);
entity_list.UpdateWho();
if (worldserver.TryReconnect() && (!worldserver.Connected()))
worldserver.AsyncConnect();
#ifdef CATCH_CRASH
}
catch(...)
{
error = 16;
RunLoops = false;
}
#endif
}
#ifdef CATCH_CRASH
if (error){
RunLoops = false;
}
#endif
#if defined(_EQDEBUG) && defined(DEBUG_PC)
QueryPerformanceCounter(&tmp3);
mainloop_time += tmp3.QuadPart - tmp2.QuadPart;
if (!--tmp0) {
tmp0 = 200;
printf("Elapsed Tics : %9.0f (%1.4f sec)\n", (double)mainloop_time, ((double)mainloop_time/tmp.QuadPart));
printf("NPCAI Tics : %9.0f (%1.2f%%)\n", (double)npcai_time, ((double)npcai_time/mainloop_time)*100);
printf("FindSpell Tics: %9.0f (%1.2f%%)\n", (double)findspell_time, ((double)findspell_time/mainloop_time)*100);
printf("AtkAllowd Tics: %9.0f (%1.2f%%)\n", (double)IsAttackAllowed_time, ((double)IsAttackAllowed_time/mainloop_time)*100);
printf("ClientPro Tics: %9.0f (%1.2f%%)\n", (double)clientprocess_time, ((double)clientprocess_time/mainloop_time)*100);
printf("ClientAtk Tics: %9.0f (%1.2f%%)\n", (double)clientattack_time, ((double)clientattack_time/mainloop_time)*100);
mainloop_time = 0;
npcai_time = 0;
findspell_time = 0;
IsAttackAllowed_time = 0;
clientprocess_time = 0;
clientattack_time = 0;
}
#endif
#ifdef EQPROFILE
#ifdef PROFILE_DUMP_TIME
if(profile_dump_timer.Check()) {
DumpZoneProfile();
}
#endif
#endif
} //end extra profiler block
Sleep(ZoneTimerResolution);
}
If we threaded different parts of the zone code, including combat & spells, I think we could get to a point where we could keep communication going with the clients, since other communications would process at the same time as the threads for combat, and the clients wouldn't timeout. Not only that, but it would take out a lot of the cause & effect feel of the Emu experience that you don't get on Live (especially with skills, timers, etc).
Anyone have any thoughts or insight, especially if there is some threading in the zone process that I'm not seeing?
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.