void ProcessLoop(void *tmp) { #else void *ProcessLoop(void *tmp) { #endif srand(time(NULL)); bool worldwasconnected = worldserver.Connected(); ProcessLoopRunning = true; while(RunLoops) { if (worldserver.Connected()) { worldserver.Process(); worldwasconnected = true; } else { if (worldwasconnected && ZoneLoaded) entity_list.ChannelMessageFromWorld(0, 0, 6, 0, 0, "WARNING: World server connection lost"); worldwasconnected = false; } if (ZoneLoaded) { if (numclients > 0) // Don't run entity_list Process() unless there are clients inside. entity_list.Process(); else entity_list.BoatProcessOnly(); // Tazadar : We move boats even if the zone is empty ! if (!zone->Process()) { Zone::Shutdown(); } } Sleep(1); } ProcessLoopRunning = false; #ifndef WIN32 return 0; #endif }
int main(int argc, char** argv) { RegisterExecutablePlatform(ExePlatformZone); Log.LoadLogSettingsDefaults(); set_exception_handler(); QServ = new QueryServ; Log.Out(Logs::General, Logs::Zone_Server, "Loading server configuration.."); if(!ZoneConfig::LoadConfig()) { Log.Out(Logs::General, Logs::Error, "Loading server configuration failed."); return 1; } Config = ZoneConfig::get(); const char *zone_name; uint32 instance_id = 0; std::string z_name; if(argc == 4) { instance_id = atoi(argv[3]); worldserver.SetLauncherName(argv[2]); auto zone_port = SplitString(argv[1], ':'); if(!zone_port.empty()) { z_name = zone_port[0]; } if(zone_port.size() > 1) { std::string p_name = zone_port[1]; Config->SetZonePort(atoi(p_name.c_str())); } worldserver.SetLaunchedName(z_name.c_str()); if(strncmp(z_name.c_str(), "dynamic_", 8) == 0) { zone_name = "."; } else { zone_name = z_name.c_str(); } } else if(argc == 3) { worldserver.SetLauncherName(argv[2]); auto zone_port = SplitString(argv[1], ':'); if(!zone_port.empty()) { z_name = zone_port[0]; } if(zone_port.size() > 1) { std::string p_name = zone_port[1]; Config->SetZonePort(atoi(p_name.c_str())); } worldserver.SetLaunchedName(z_name.c_str()); if(strncmp(z_name.c_str(), "dynamic_", 8) == 0) { zone_name = "."; } else { zone_name = z_name.c_str(); } } else if (argc == 2) { worldserver.SetLauncherName("NONE"); auto zone_port = SplitString(argv[1], ':'); if(!zone_port.empty()) { z_name = zone_port[0]; } if(zone_port.size() > 1) { std::string p_name = zone_port[1]; Config->SetZonePort(atoi(p_name.c_str())); } worldserver.SetLaunchedName(z_name.c_str()); if(strncmp(z_name.c_str(), "dynamic_", 8) == 0) { zone_name = "."; } else { zone_name = z_name.c_str(); } } else { zone_name = "."; worldserver.SetLaunchedName("."); worldserver.SetLauncherName("NONE"); } worldserver.SetPassword(Config->SharedKey.c_str()); Log.Out(Logs::General, Logs::Zone_Server, "Connecting to MySQL..."); if (!database.Connect( Config->DatabaseHost.c_str(), Config->DatabaseUsername.c_str(), Config->DatabasePassword.c_str(), Config->DatabaseDB.c_str(), Config->DatabasePort)) { Log.Out(Logs::General, Logs::Error, "Cannot continue without a database connection."); return 1; } #ifdef BOTS if (!botdb.Connect( Config->DatabaseHost.c_str(), Config->DatabaseUsername.c_str(), Config->DatabasePassword.c_str(), Config->DatabaseDB.c_str(), Config->DatabasePort)) { Log.Out(Logs::General, Logs::Error, "Cannot continue without a bots database connection."); return 1; } #endif /* Register Log System and Settings */ Log.OnLogHookCallBackZone(&Zone::GMSayHookCallBackProcess); database.LoadLogSettings(Log.log_settings); Log.StartFileLogs(); /* Guilds */ guild_mgr.SetDatabase(&database); GuildBanks = nullptr; #ifdef _EQDEBUG _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif Log.Out(Logs::General, Logs::Zone_Server, "CURRENT_VERSION: %s", CURRENT_VERSION); /* * Setup nice signal handlers */ if (signal(SIGINT, CatchSignal) == SIG_ERR) { Log.Out(Logs::General, Logs::Error, "Could not set signal handler"); return 1; } if (signal(SIGTERM, CatchSignal) == SIG_ERR) { Log.Out(Logs::General, Logs::Error, "Could not set signal handler"); return 1; } #ifndef WIN32 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { Log.Out(Logs::General, Logs::Error, "Could not set signal handler"); return 1; } #endif Log.Out(Logs::General, Logs::Zone_Server, "Mapping Incoming Opcodes"); MapOpcodes(); Log.Out(Logs::General, Logs::Zone_Server, "Loading Variables"); database.LoadVariables(); std::string hotfix_name; if(database.GetVariable("hotfix_name", hotfix_name)) { if(!hotfix_name.empty()) { Log.Out(Logs::General, Logs::Zone_Server, "Current hotfix in use: '%s'", hotfix_name.c_str()); } } Log.Out(Logs::General, Logs::Zone_Server, "Loading zone names"); database.LoadZoneNames(); Log.Out(Logs::General, Logs::Zone_Server, "Loading items"); if(!database.LoadItems(hotfix_name)) { Log.Out(Logs::General, Logs::Error, "Loading items FAILED!"); Log.Out(Logs::General, Logs::Error, "Failed. But ignoring error and going on..."); } Log.Out(Logs::General, Logs::Zone_Server, "Loading npc faction lists"); if(!database.LoadNPCFactionLists(hotfix_name)) { Log.Out(Logs::General, Logs::Error, "Loading npcs faction lists FAILED!"); return 1; } Log.Out(Logs::General, Logs::Zone_Server, "Loading loot tables"); if(!database.LoadLoot(hotfix_name)) { Log.Out(Logs::General, Logs::Error, "Loading loot FAILED!"); return 1; } Log.Out(Logs::General, Logs::Zone_Server, "Loading skill caps"); if(!database.LoadSkillCaps(std::string(hotfix_name))) { Log.Out(Logs::General, Logs::Error, "Loading skill caps FAILED!"); return 1; } Log.Out(Logs::General, Logs::Zone_Server, "Loading spells"); if(!database.LoadSpells(hotfix_name, &SPDAT_RECORDS, &spells)) { Log.Out(Logs::General, Logs::Error, "Loading spells FAILED!"); return 1; } Log.Out(Logs::General, Logs::Zone_Server, "Loading base data"); if(!database.LoadBaseData(hotfix_name)) { Log.Out(Logs::General, Logs::Error, "Loading base data FAILED!"); return 1; } Log.Out(Logs::General, Logs::Zone_Server, "Loading guilds"); guild_mgr.LoadGuilds(); Log.Out(Logs::General, Logs::Zone_Server, "Loading factions"); database.LoadFactionData(); Log.Out(Logs::General, Logs::Zone_Server, "Loading titles"); title_manager.LoadTitles(); Log.Out(Logs::General, Logs::Zone_Server, "Loading tributes"); database.LoadTributes(); Log.Out(Logs::General, Logs::Zone_Server, "Loading corpse timers"); database.GetDecayTimes(npcCorpseDecayTimes); Log.Out(Logs::General, Logs::Zone_Server, "Loading commands"); int retval=command_init(); if(retval<0) Log.Out(Logs::General, Logs::Error, "Command loading FAILED"); else Log.Out(Logs::General, Logs::Zone_Server, "%d commands loaded", retval); //rules: { std::string tmp; if (database.GetVariable("RuleSet", tmp)) { Log.Out(Logs::General, Logs::Zone_Server, "Loading rule set '%s'", tmp.c_str()); if(!RuleManager::Instance()->LoadRules(&database, tmp.c_str())) { Log.Out(Logs::General, Logs::Error, "Failed to load ruleset '%s', falling back to defaults.", tmp.c_str()); } } else { if(!RuleManager::Instance()->LoadRules(&database, "default")) { Log.Out(Logs::General, Logs::Zone_Server, "No rule set configured, using default rules"); } else { Log.Out(Logs::General, Logs::Zone_Server, "Loaded default rule set 'default'", tmp.c_str()); } } } #ifdef BOTS Log.Out(Logs::General, Logs::Zone_Server, "Loading bot commands"); int botretval = bot_command_init(); if (botretval<0) Log.Out(Logs::General, Logs::Error, "Bot command loading FAILED"); else Log.Out(Logs::General, Logs::Zone_Server, "%d bot commands loaded", botretval); #endif if(RuleB(TaskSystem, EnableTaskSystem)) { Log.Out(Logs::General, Logs::Tasks, "[INIT] Loading Tasks"); taskmanager = new TaskManager; taskmanager->LoadTasks(); } parse = new QuestParserCollection(); #ifdef LUA_EQEMU auto lua_parser = new LuaParser(); parse->RegisterQuestInterface(lua_parser, "lua"); #endif #ifdef EMBPERL auto perl_parser = new PerlembParser(); parse->RegisterQuestInterface(perl_parser, "pl"); /* Load Perl Event Export Settings */ parse->LoadPerlEventExportSettings(parse->perl_event_export_settings); #endif //now we have our parser, load the quests Log.Out(Logs::General, Logs::Zone_Server, "Loading quests"); parse->ReloadQuests(); if (!worldserver.Connect()) { Log.Out(Logs::General, Logs::Error, "Worldserver Connection Failed :: worldserver.Connect()"); } Timer InterserverTimer(INTERSERVER_TIMER); // does MySQL pings and auto-reconnect #ifdef EQPROFILE #ifdef PROFILE_DUMP_TIME Timer profile_dump_timer(PROFILE_DUMP_TIME*1000); profile_dump_timer.Start(); #endif #endif if (!strlen(zone_name) || !strcmp(zone_name,".")) { Log.Out(Logs::General, Logs::Zone_Server, "Entering sleep mode"); } else if (!Zone::Bootup(database.GetZoneID(zone_name), instance_id, true)) { Log.Out(Logs::General, Logs::Error, "Zone Bootup failed :: Zone::Bootup"); zone = 0; } //register all the patches we have avaliable with the stream identifier. EQStreamIdentifier stream_identifier; RegisterAllPatches(stream_identifier); #ifndef WIN32 Log.Out(Logs::Detail, Logs::None, "Main thread running with thread id %d", pthread_self()); #endif Timer quest_timers(100); UpdateWindowTitle(); bool worldwasconnected = worldserver.Connected(); std::shared_ptr<EQStream> eqss; EQStreamInterface *eqsi; uint8 IDLEZONEUPDATE = 200; uint8 ZONEUPDATE = 10; Timer zoneupdate_timer(ZONEUPDATE); zoneupdate_timer.Start(); while(RunLoops) { { //profiler block to omit the sleep from times //Advance the timer to our current point in time Timer::SetCurrentTime(); worldserver.Process(); if (!eqsf.IsOpen() && Config->ZonePort != 0) { Log.Out(Logs::General, Logs::Zone_Server, "Starting EQ Network server on port %d", Config->ZonePort); if (!eqsf.Open(Config->ZonePort)) { Log.Out(Logs::General, Logs::Error, "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.Out(Logs::Detail, Logs::World_Server, "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.Out(Logs::Detail, Logs::World_Server, "New client from %s:%d", inet_ntoa(in), ntohs(eqsi->GetRemotePort())); auto client = new Client(eqsi); entity_list.AddClient(client); } if ( numclients < 1 && zoneupdate_timer.GetDuration() != IDLEZONEUPDATE ) zoneupdate_timer.SetTimer(IDLEZONEUPDATE); else if ( numclients > 0 && zoneupdate_timer.GetDuration() == IDLEZONEUPDATE ) { zoneupdate_timer.SetTimer(ZONEUPDATE); zoneupdate_timer.Trigger(); } //check for timeouts in other threads timeout_manager.CheckTimeouts(); if (worldserver.Connected()) { worldwasconnected = true; } else { if (worldwasconnected && is_zone_loaded) entity_list.ChannelMessageFromWorld(0, 0, 6, 0, 0, "WARNING: World server connection lost"); worldwasconnected = false; } if (is_zone_loaded && zoneupdate_timer.Check()) { { if(net.group_timer.Enabled() && net.group_timer.Check()) entity_list.GroupProcess(); if(net.door_timer.Enabled() && net.door_timer.Check()) entity_list.DoorProcess(); if(net.object_timer.Enabled() && net.object_timer.Check()) entity_list.ObjectProcess(); 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(); entity_list.Process(); entity_list.MobProcess(); entity_list.BeaconProcess(); entity_list.EncounterProcess(); if (zone) { if(!zone->Process()) { Zone::Shutdown(); } } if(quest_timers.Check()) quest_manager.Process(); } } if (InterserverTimer.Check()) { InterserverTimer.Start(); database.ping(); // AsyncLoadVariables(dbasync, &database); entity_list.UpdateWho(); if (worldserver.TryReconnect() && (!worldserver.Connected())) worldserver.AsyncConnect(); } #ifdef EQPROFILE #ifdef PROFILE_DUMP_TIME if(profile_dump_timer.Check()) { DumpZoneProfile(); } #endif #endif } //end extra profiler block Sleep(ZoneTimerResolution); } entity_list.Clear(); parse->ClearInterfaces(); #ifdef EMBPERL safe_delete(perl_parser); #endif #ifdef LUA_EQEMU safe_delete(lua_parser); #endif safe_delete(Config); if (zone != 0) Zone::Shutdown(true); //Fix for Linux world server problem. eqsf.Close(); worldserver.Disconnect(); safe_delete(taskmanager); command_deinit(); #ifdef BOTS bot_command_deinit(); #endif safe_delete(parse); Log.Out(Logs::General, Logs::Zone_Server, "Proper zone shutdown complete."); Log.CloseFileLogs(); return 0; }
int main(int argc, char** argv) { RegisterExecutablePlatform(ExePlatformZone); set_exception_handler(); const char *zone_name; if(argc == 3) { worldserver.SetLauncherName(argv[2]); worldserver.SetLaunchedName(argv[1]); if(strncmp(argv[1], "dynamic_", 8) == 0) { //dynamic zone with a launcher name correlation zone_name = "."; } else { zone_name = argv[1]; worldserver.SetLaunchedName(zone_name); } } else if (argc == 2) { worldserver.SetLauncherName("NONE"); worldserver.SetLaunchedName(argv[1]); if(strncmp(argv[1], "dynamic_", 8) == 0) { //dynamic zone with a launcher name correlation zone_name = "."; } else { zone_name = argv[1]; worldserver.SetLaunchedName(zone_name); } } else { zone_name = "."; worldserver.SetLaunchedName("."); worldserver.SetLauncherName("NONE"); } _log(ZONE__INIT, "Loading server configuration.."); if (!ZoneConfig::LoadConfig()) { _log(ZONE__INIT_ERR, "Loading server configuration failed."); return(1); } const ZoneConfig *Config=ZoneConfig::get(); if(!load_log_settings(Config->LogSettingsFile.c_str())) _log(ZONE__INIT, "Warning: Unable to read %s", Config->LogSettingsFile.c_str()); else _log(ZONE__INIT, "Log settings loaded from %s", Config->LogSettingsFile.c_str()); worldserver.SetPassword(Config->SharedKey.c_str()); _log(ZONE__INIT, "Connecting to MySQL..."); if (!database.Connect( Config->DatabaseHost.c_str(), Config->DatabaseUsername.c_str(), Config->DatabasePassword.c_str(), Config->DatabaseDB.c_str(), Config->DatabasePort)) { _log(ZONE__INIT_ERR, "Cannot continue without a database connection."); return(1); } dbasync = new DBAsync(&database); dbasync->AddFQ(&MTdbafq); guild_mgr.SetDatabase(&database); GuildBanks = NULL; #ifdef _EQDEBUG _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif _log(ZONE__INIT, "CURRENT_VERSION: %s", CURRENT_VERSION); /* * Setup nice signal handlers */ if (signal(SIGINT, CatchSignal) == SIG_ERR) { _log(ZONE__INIT_ERR, "Could not set signal handler"); return 0; } if (signal(SIGTERM, CatchSignal) == SIG_ERR) { _log(ZONE__INIT_ERR, "Could not set signal handler"); return 0; } #ifndef WIN32 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { _log(ZONE__INIT_ERR, "Could not set signal handler"); return 0; } #endif const char *log_ini_file = "./log.ini"; if(!load_log_settings(log_ini_file)) _log(ZONE__INIT, "Warning: Unable to read %s", log_ini_file); else _log(ZONE__INIT, "Log settings loaded from %s", log_ini_file); _log(ZONE__INIT, "Mapping Incoming Opcodes"); MapOpcodes(); _log(ZONE__INIT, "Loading Variables"); database.LoadVariables(); _log(ZONE__INIT, "Loading zone names"); database.LoadZoneNames(); _log(ZONE__INIT, "Loading items"); if (!database.LoadItems()) { _log(ZONE__INIT_ERR, "Loading items FAILED!"); _log(ZONE__INIT, "Failed. But ignoring error and going on..."); } _log(ZONE__INIT, "Loading npc faction lists"); if (!database.LoadNPCFactionLists()) { _log(ZONE__INIT_ERR, "Loading npcs faction lists FAILED!"); CheckEQEMuErrorAndPause(); return 0; } _log(ZONE__INIT, "Loading loot tables"); if (!database.LoadLoot()) { _log(ZONE__INIT_ERR, "Loading loot FAILED!"); CheckEQEMuErrorAndPause(); return 0; } _log(ZONE__INIT, "Loading skill caps"); if (!database.LoadSkillCaps()) { _log(ZONE__INIT_ERR, "Loading skill caps FAILED!"); CheckEQEMuErrorAndPause(); return 0; } _log(ZONE__INIT, "Loading spells"); EQEmu::MemoryMappedFile *mmf = NULL; LoadSpells(&mmf); _log(ZONE__INIT, "Loading guilds"); guild_mgr.LoadGuilds(); _log(ZONE__INIT, "Loading factions"); database.LoadFactionData(); _log(ZONE__INIT, "Loading titles"); title_manager.LoadTitles(); _log(ZONE__INIT, "Loading AA effects"); database.LoadAAEffects(); _log(ZONE__INIT, "Loading tributes"); database.LoadTributes(); _log(ZONE__INIT, "Loading corpse timers"); database.GetDecayTimes(npcCorpseDecayTimes); _log(ZONE__INIT, "Loading commands"); int retval=command_init(); if(retval<0) _log(ZONE__INIT_ERR, "Command loading FAILED"); else _log(ZONE__INIT, "%d commands loaded", retval); //rules: { char tmp[64]; if (database.GetVariable("RuleSet", tmp, sizeof(tmp)-1)) { _log(ZONE__INIT, "Loading rule set '%s'", tmp); if(!RuleManager::Instance()->LoadRules(&database, tmp)) { _log(ZONE__INIT_ERR, "Failed to load ruleset '%s', falling back to defaults.", tmp); } } else { if(!RuleManager::Instance()->LoadRules(&database, "default")) { _log(ZONE__INIT, "No rule set configured, using default rules"); } else { _log(ZONE__INIT, "Loaded default rule set 'default'", tmp); } } } if(RuleB(TaskSystem, EnableTaskSystem)) { _log(ZONE__INIT, "Loading Tasks"); taskmanager = new TaskManager; taskmanager->LoadTasks(); } parse = new QuestParserCollection(); PerlXSParser *pxs = new PerlXSParser(); Parser *ps = new Parser(); parse->RegisterQuestInterface(pxs, "pl"); //parse->RegisterQuestInterface(ps, "qst"); //now we have our parser, load the quests _log(ZONE__INIT, "Loading quests"); parse->ReloadQuests(); #ifdef CLIENT_LOGS LogFile->SetAllCallbacks(ClientLogs::EQEmuIO_buf); LogFile->SetAllCallbacks(ClientLogs::EQEmuIO_fmt); LogFile->SetAllCallbacks(ClientLogs::EQEmuIO_pva); #endif if (!worldserver.Connect()) { _log(ZONE__INIT_ERR, "worldserver.Connect() FAILED!"); } Timer InterserverTimer(INTERSERVER_TIMER); // does MySQL pings and auto-reconnect #ifdef EQPROFILE #ifdef PROFILE_DUMP_TIME Timer profile_dump_timer(PROFILE_DUMP_TIME*1000); profile_dump_timer.Start(); #endif #endif if (!strlen(zone_name) || !strcmp(zone_name,".")) { _log(ZONE__INIT, "Entering sleep mode"); } else if (!Zone::Bootup(database.GetZoneID(zone_name), 0, true)) { //todo: go above and fix this to allow cmd line instance _log(ZONE__INIT_ERR, "Zone bootup FAILED!"); zone = 0; } //register all the patches we have avaliable with the stream identifier. EQStreamIdentifier stream_identifier; RegisterAllPatches(stream_identifier); #ifndef WIN32 _log(COMMON__THREADS, "Main thread running with thread id %d", pthread_self()); #endif Timer quest_timers(100); UpdateWindowTitle(); bool worldwasconnected = worldserver.Connected(); EQStream* eqss; EQStreamInterface *eqsi; Timer temp_timer(10); temp_timer.Start(); 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 worldserver.Process(); 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()) { { if(net.group_timer.Enabled() && net.group_timer.Check()) entity_list.GroupProcess(); if(net.door_timer.Enabled() && net.door_timer.Check()) entity_list.DoorProcess(); if(net.object_timer.Enabled() && net.object_timer.Check()) entity_list.ObjectProcess(); 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(); entity_list.Process(); entity_list.MobProcess(); entity_list.BeaconProcess(); if (zone) { if(!zone->Process()) { Zone::Shutdown(); } } if(quest_timers.Check()) quest_manager.Process(); } } DBAsyncWork* dbaw = 0; while ((dbaw = MTdbafq.Pop())) { DispatchFinishedDBAsync(dbaw); } if (InterserverTimer.Check()) { InterserverTimer.Start(); database.ping(); AsyncLoadVariables(dbasync, &database); entity_list.UpdateWho(); if (worldserver.TryReconnect() && (!worldserver.Connected())) worldserver.AsyncConnect(); } #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); } safe_delete(parse); safe_delete(pxs); safe_delete(ps); safe_delete(mmf); entity_list.Clear(); if (zone != 0) Zone::Shutdown(true); //Fix for Linux world server problem. eqsf.Close(); worldserver.Disconnect(); dbasync->CommitWrites(); dbasync->StopThread(); safe_delete(taskmanager); command_deinit(); CheckEQEMuErrorAndPause(); _log(ZONE__INIT, "Proper zone shutdown complete."); return 0; }
int main(int argc, char** argv) { RegisterExecutablePlatform(ExePlatformZone); LogSys.LoadLogSettingsDefaults(); set_exception_handler(); #ifdef USE_MAP_MMFS if (argc == 3 && strcasecmp(argv[1], "convert_map") == 0) { if (!ZoneConfig::LoadConfig()) return 1; Config = ZoneConfig::get(); std::string mapfile = argv[2]; std::transform(mapfile.begin(), mapfile.end(), mapfile.begin(), ::tolower); std::string filename = Config->MapDir; filename += mapfile; auto m = new Map(); auto success = m->Load(filename, true); delete m; std::cout << mapfile.c_str() << " conversion " << (success ? "succeeded" : "failed") << std::endl; return 0; } #endif /*USE_MAP_MMFS*/ QServ = new QueryServ; Log(Logs::General, Logs::Zone_Server, "Loading server configuration.."); if (!ZoneConfig::LoadConfig()) { Log(Logs::General, Logs::Error, "Loading server configuration failed."); return 1; } Config = ZoneConfig::get(); const char *zone_name; uint32 instance_id = 0; std::string z_name; if (argc == 4) { instance_id = atoi(argv[3]); worldserver.SetLauncherName(argv[2]); auto zone_port = SplitString(argv[1], ':'); if (!zone_port.empty()) { z_name = zone_port[0]; } if (zone_port.size() > 1) { std::string p_name = zone_port[1]; Config->SetZonePort(atoi(p_name.c_str())); } worldserver.SetLaunchedName(z_name.c_str()); if (strncmp(z_name.c_str(), "dynamic_", 8) == 0) { zone_name = "."; } else { zone_name = z_name.c_str(); } } else if (argc == 3) { worldserver.SetLauncherName(argv[2]); auto zone_port = SplitString(argv[1], ':'); if (!zone_port.empty()) { z_name = zone_port[0]; } if (zone_port.size() > 1) { std::string p_name = zone_port[1]; Config->SetZonePort(atoi(p_name.c_str())); } worldserver.SetLaunchedName(z_name.c_str()); if (strncmp(z_name.c_str(), "dynamic_", 8) == 0) { zone_name = "."; } else { zone_name = z_name.c_str(); } } else if (argc == 2) { worldserver.SetLauncherName("NONE"); auto zone_port = SplitString(argv[1], ':'); if (!zone_port.empty()) { z_name = zone_port[0]; } if (zone_port.size() > 1) { std::string p_name = zone_port[1]; Config->SetZonePort(atoi(p_name.c_str())); } worldserver.SetLaunchedName(z_name.c_str()); if (strncmp(z_name.c_str(), "dynamic_", 8) == 0) { zone_name = "."; } else { zone_name = z_name.c_str(); } } else { zone_name = "."; worldserver.SetLaunchedName("."); worldserver.SetLauncherName("NONE"); } Log(Logs::General, Logs::Zone_Server, "Connecting to MySQL..."); if (!database.Connect( Config->DatabaseHost.c_str(), Config->DatabaseUsername.c_str(), Config->DatabasePassword.c_str(), Config->DatabaseDB.c_str(), Config->DatabasePort)) { Log(Logs::General, Logs::Error, "Cannot continue without a database connection."); return 1; } #ifdef BOTS if (!botdb.Connect( Config->DatabaseHost.c_str(), Config->DatabaseUsername.c_str(), Config->DatabasePassword.c_str(), Config->DatabaseDB.c_str(), Config->DatabasePort)) { Log(Logs::General, Logs::Error, "Cannot continue without a bots database connection."); return 1; } #endif /* Register Log System and Settings */ LogSys.OnLogHookCallBackZone(&Zone::GMSayHookCallBackProcess); database.LoadLogSettings(LogSys.log_settings); LogSys.StartFileLogs(); /* Guilds */ guild_mgr.SetDatabase(&database); GuildBanks = nullptr; /** * NPC Scale Manager */ npc_scale_manager = new NpcScaleManager; npc_scale_manager->LoadScaleData(); #ifdef _EQDEBUG _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif Log(Logs::General, Logs::Zone_Server, "CURRENT_VERSION: %s", CURRENT_VERSION); /* * Setup nice signal handlers */ if (signal(SIGINT, CatchSignal) == SIG_ERR) { Log(Logs::General, Logs::Error, "Could not set signal handler"); return 1; } if (signal(SIGTERM, CatchSignal) == SIG_ERR) { Log(Logs::General, Logs::Error, "Could not set signal handler"); return 1; } #ifndef WIN32 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { Log(Logs::General, Logs::Error, "Could not set signal handler"); return 1; } #endif Log(Logs::General, Logs::Zone_Server, "Mapping Incoming Opcodes"); MapOpcodes(); Log(Logs::General, Logs::Zone_Server, "Loading Variables"); database.LoadVariables(); std::string hotfix_name; if (database.GetVariable("hotfix_name", hotfix_name)) { if (!hotfix_name.empty()) { Log(Logs::General, Logs::Zone_Server, "Current hotfix in use: '%s'", hotfix_name.c_str()); } } Log(Logs::General, Logs::Zone_Server, "Loading zone names"); database.LoadZoneNames(); Log(Logs::General, Logs::Zone_Server, "Loading items"); if (!database.LoadItems(hotfix_name)) { Log(Logs::General, Logs::Error, "Loading items FAILED!"); Log(Logs::General, Logs::Error, "Failed. But ignoring error and going on..."); } Log(Logs::General, Logs::Zone_Server, "Loading npc faction lists"); if (!database.LoadNPCFactionLists(hotfix_name)) { Log(Logs::General, Logs::Error, "Loading npcs faction lists FAILED!"); return 1; } Log(Logs::General, Logs::Zone_Server, "Loading loot tables"); if (!database.LoadLoot(hotfix_name)) { Log(Logs::General, Logs::Error, "Loading loot FAILED!"); return 1; } Log(Logs::General, Logs::Zone_Server, "Loading skill caps"); if (!database.LoadSkillCaps(std::string(hotfix_name))) { Log(Logs::General, Logs::Error, "Loading skill caps FAILED!"); return 1; } Log(Logs::General, Logs::Zone_Server, "Loading spells"); if (!database.LoadSpells(hotfix_name, &SPDAT_RECORDS, &spells)) { Log(Logs::General, Logs::Error, "Loading spells FAILED!"); return 1; } Log(Logs::General, Logs::Zone_Server, "Loading base data"); if (!database.LoadBaseData(hotfix_name)) { Log(Logs::General, Logs::Error, "Loading base data FAILED!"); return 1; } Log(Logs::General, Logs::Zone_Server, "Loading guilds"); guild_mgr.LoadGuilds(); Log(Logs::General, Logs::Zone_Server, "Loading factions"); database.LoadFactionData(); Log(Logs::General, Logs::Zone_Server, "Loading titles"); title_manager.LoadTitles(); Log(Logs::General, Logs::Zone_Server, "Loading tributes"); database.LoadTributes(); Log(Logs::General, Logs::Zone_Server, "Loading corpse timers"); database.GetDecayTimes(npcCorpseDecayTimes); Log(Logs::General, Logs::Zone_Server, "Loading profanity list"); if (!EQEmu::ProfanityManager::LoadProfanityList(&database)) Log(Logs::General, Logs::Error, "Loading profanity list FAILED!"); Log(Logs::General, Logs::Zone_Server, "Loading commands"); int retval = command_init(); if (retval<0) Log(Logs::General, Logs::Error, "Command loading FAILED"); else Log(Logs::General, Logs::Zone_Server, "%d commands loaded", retval); //rules: { std::string tmp; if (database.GetVariable("RuleSet", tmp)) { Log(Logs::General, Logs::Zone_Server, "Loading rule set '%s'", tmp.c_str()); if (!RuleManager::Instance()->LoadRules(&database, tmp.c_str(), false)) { Log(Logs::General, Logs::Error, "Failed to load ruleset '%s', falling back to defaults.", tmp.c_str()); } } else { if (!RuleManager::Instance()->LoadRules(&database, "default", false)) { Log(Logs::General, Logs::Zone_Server, "No rule set configured, using default rules"); } else { Log(Logs::General, Logs::Zone_Server, "Loaded default rule set 'default'", tmp.c_str()); } } EQEmu::InitializeDynamicLookups(); Log(Logs::General, Logs::Zone_Server, "Initialized dynamic dictionary entries"); } #ifdef BOTS Log(Logs::General, Logs::Zone_Server, "Loading bot commands"); int botretval = bot_command_init(); if (botretval<0) Log(Logs::General, Logs::Error, "Bot command loading FAILED"); else Log(Logs::General, Logs::Zone_Server, "%d bot commands loaded", botretval); Log(Logs::General, Logs::Zone_Server, "Loading bot spell casting chances"); if (!botdb.LoadBotSpellCastingChances()) Log(Logs::General, Logs::Error, "Bot spell casting chances loading FAILED"); #endif if (RuleB(TaskSystem, EnableTaskSystem)) { Log(Logs::General, Logs::Tasks, "[INIT] Loading Tasks"); taskmanager = new TaskManager; taskmanager->LoadTasks(); } parse = new QuestParserCollection(); #ifdef LUA_EQEMU parse->RegisterQuestInterface(LuaParser::Instance(), "lua"); #endif #ifdef EMBPERL auto perl_parser = new PerlembParser(); parse->RegisterQuestInterface(perl_parser, "pl"); /* Load Perl Event Export Settings */ parse->LoadPerlEventExportSettings(parse->perl_event_export_settings); #endif //now we have our parser, load the quests Log(Logs::General, Logs::Zone_Server, "Loading quests"); parse->ReloadQuests(); worldserver.Connect(); Timer InterserverTimer(INTERSERVER_TIMER); // does MySQL pings and auto-reconnect #ifdef EQPROFILE #ifdef PROFILE_DUMP_TIME Timer profile_dump_timer(PROFILE_DUMP_TIME * 1000); profile_dump_timer.Start(); #endif #endif if (!strlen(zone_name) || !strcmp(zone_name, ".")) { Log(Logs::General, Logs::Zone_Server, "Entering sleep mode"); } else if (!Zone::Bootup(database.GetZoneID(zone_name), instance_id, true)) { Log(Logs::General, Logs::Error, "Zone Bootup failed :: Zone::Bootup"); zone = 0; } //register all the patches we have avaliable with the stream identifier. EQStreamIdentifier stream_identifier; RegisterAllPatches(stream_identifier); #ifndef WIN32 Log(Logs::Detail, Logs::None, "Main thread running with thread id %d", pthread_self()); #endif Timer quest_timers(100); UpdateWindowTitle(); bool worldwasconnected = worldserver.Connected(); std::shared_ptr<EQStreamInterface> eqss; EQStreamInterface *eqsi; bool eqsf_open = false; std::unique_ptr<EQ::Net::EQStreamManager> eqsm; std::chrono::time_point<std::chrono::system_clock> frame_prev = std::chrono::system_clock::now(); auto loop_fn = [&](EQ::Timer* t) { //Advance the timer to our current point in time Timer::SetCurrentTime(); //Calculate frame time std::chrono::time_point<std::chrono::system_clock> frame_now = std::chrono::system_clock::now(); frame_time = std::chrono::duration_cast<std::chrono::duration<double>>(frame_now - frame_prev).count(); frame_prev = frame_now; if (!eqsf_open && Config->ZonePort != 0) { Log(Logs::General, Logs::Zone_Server, "Starting EQ Network server on port %d", Config->ZonePort); EQ::Net::EQStreamManagerOptions opts(Config->ZonePort, false, true); opts.daybreak_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS); opts.daybreak_options.resend_delay_factor = RuleR(Network, ResendDelayFactor); opts.daybreak_options.resend_delay_min = RuleI(Network, ResendDelayMinMS); opts.daybreak_options.resend_delay_max = RuleI(Network, ResendDelayMaxMS); eqsm.reset(new EQ::Net::EQStreamManager(opts)); eqsf_open = true; eqsm->OnNewConnection([&stream_identifier](std::shared_ptr<EQ::Net::EQStream> stream) { stream_identifier.AddStream(stream); LogF(Logs::Detail, Logs::World_Server, "New connection from IP {0}:{1}", stream->RemoteEndpoint(), ntohs(stream->GetRemotePort())); }); } //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(Logs::Detail, Logs::World_Server, "New client from %s:%d", inet_ntoa(in), ntohs(eqsi->GetRemotePort())); auto client = new Client(eqsi); entity_list.AddClient(client); } if (worldserver.Connected()) { worldwasconnected = true; } else { if (worldwasconnected && is_zone_loaded) { entity_list.ChannelMessageFromWorld(0, 0, 6, 0, 0, "WARNING: World server connection lost"); worldwasconnected = false; } } if (is_zone_loaded) { { if (net.group_timer.Enabled() && net.group_timer.Check()) entity_list.GroupProcess(); if (net.door_timer.Enabled() && net.door_timer.Check()) entity_list.DoorProcess(); if (net.object_timer.Enabled() && net.object_timer.Check()) entity_list.ObjectProcess(); 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(); entity_list.Process(); entity_list.MobProcess(); entity_list.BeaconProcess(); entity_list.EncounterProcess(); if (zone) { if (!zone->Process()) { Zone::Shutdown(); } } if (quest_timers.Check()) quest_manager.Process(); } } if (InterserverTimer.Check()) { InterserverTimer.Start(); database.ping(); entity_list.UpdateWho(); } }; EQ::Timer process_timer(loop_fn); bool is_boat_zone = strstr(zone_name, "erudnext") != NULL || strstr(zone_name, "freporte") != NULL || strstr(zone_name, "qeynos") != NULL || strstr(zone_name, "oot") != NULL || strstr(zone_name, "timorous") != NULL || strstr(zone_name, "erudsxing") != NULL || strstr(zone_name, "firiona") != NULL || strstr(zone_name, "butcher") != NULL || strstr(zone_name, "overthere") != NULL || strstr(zone_name, "oasis") != NULL || strstr(zone_name, "nro") != NULL || strstr(zone_name, "iceclad") != NULL; if (!is_boat_zone) process_timer.Start(1000, true); else process_timer.Start(100, true); while (RunLoops) { if (!is_boat_zone) { bool previous_loaded = is_zone_loaded && numclients > 0; EQ::EventLoop::Get().Process(); bool current_loaded = is_zone_loaded && numclients > 0; if (previous_loaded && !current_loaded) { process_timer.Stop(); process_timer.Start(1000, true); } else if (!previous_loaded && current_loaded) { process_timer.Stop(); process_timer.Start(32, true); } if (current_loaded) { Sleep(1); } else { Sleep(10); } } else { bool previous_loaded = is_zone_loaded; EQ::EventLoop::Get().Process(); bool current_loaded = is_zone_loaded; if (previous_loaded && !current_loaded) { process_timer.Stop(); process_timer.Start(100, true); if (zone && zone->GetZoneID() && zone->GetInstanceVersion()) { uint32 shutdown_timer = database.getZoneShutDownDelay(zone->GetZoneID(), zone->GetInstanceVersion()); zone->StartShutdownTimer(shutdown_timer); } } else if (!previous_loaded && current_loaded) { process_timer.Stop(); process_timer.Start(10, true); } Sleep(1); } } entity_list.Clear(); entity_list.RemoveAllEncounters(); // gotta do it manually or rewrite lots of shit :P parse->ClearInterfaces(); #ifdef EMBPERL safe_delete(perl_parser); #endif safe_delete(Config); if (zone != 0) Zone::Shutdown(true); //Fix for Linux world server problem. safe_delete(taskmanager); command_deinit(); #ifdef BOTS bot_command_deinit(); #endif safe_delete(parse); Log(Logs::General, Logs::Zone_Server, "Proper zone shutdown complete."); LogSys.CloseFileLogs(); return 0; }
int main(int argc, char** argv) { #ifdef _DEBUG _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); // _crtBreakAlloc = 2025; #endif srand(time(NULL)); for (int logs = 0; logs < EQEMuLog::MaxLogID; logs++) { LogFile->write((EQEMuLog::LogIDs)logs, "CURRENT_ZONE_VERSION: %s", CURRENT_ZONE_VERSION); } if (argc != 5) { cerr << "Usage: zone zone_name address port worldaddress" << endl; exit(0); } char* filename = argv[0]; char* zone_name = argv[1]; char* address = argv[2]; int32 port = atoi(argv[3]); char* worldaddress = argv[4]; if (strlen(address) <= 0) { cerr << "Invalid address" << endl; exit(0); } if (port <= 0) { cerr << "Bad port specified" << endl; exit(0); } if (strlen(worldaddress) <= 0) { cerr << "Invalid worldaddress" << endl; exit(0); } if (signal(SIGINT, CatchSignal) == SIG_ERR) { cerr << "Could not set signal handler" << endl; return 0; } #ifndef WIN32 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { cerr << "Could not set signal handler" << endl; return 0; } #endif net.SaveInfo(address, port, worldaddress,filename); LogFile->write(EQEMuLog::Status, "Loading Variables"); database.LoadVariables(); LogFile->write(EQEMuLog::Status, "Loading zone names"); database.LoadZoneNames(); LogFile->write(EQEMuLog::Status, "Loading items"); if (!database.LoadItems()) { LogFile->write(EQEMuLog::Error, "Loading items FAILED!"); cout << "Failed. But ignoring error and going on..." << endl; } LogFile->write(EQEMuLog::Status, "Loading npcs"); if (!database.LoadNPCTypes()) { LogFile->write(EQEMuLog::Error, "Loading npcs FAILED!"); CheckEQEMuErrorAndPause(); return 0; } #ifdef SHAREMEM LogFile->write(EQEMuLog::Status, "Loading npc faction lists"); if (!database.LoadNPCFactionLists()) { LogFile->write(EQEMuLog::Error, "Loading npcs faction lists FAILED!"); CheckEQEMuErrorAndPause(); return 0; } #endif LogFile->write(EQEMuLog::Status, "Loading loot tables"); if (!database.LoadLoot()) { LogFile->write(EQEMuLog::Error, "Loading loot FAILED!"); CheckEQEMuErrorAndPause(); return 0; } #ifdef SHAREMEM LogFile->write(EQEMuLog::Status, "Loading doors"); database.LoadDoors(); #endif LoadSPDat(); #ifdef GUILDWARS LogFile->write(EQEMuLog::Status, "Loading guild alliances"); //database.LoadGuildAlliances(); #endif // New Load function. keeping it commented till I figure out why its not working correctly in linux. Trump. // NewLoadSPDat(); LogFile->write(EQEMuLog::Status, "Loading guilds"); database.LoadGuilds(guilds); LogFile->write(EQEMuLog::Status, "Loading factions"); database.LoadFactionData(); LogFile->write(EQEMuLog::Status, "Loading corpse timers"); database.GetDecayTimes(npcCorpseDecayTimes); LogFile->write(EQEMuLog::Status, "Loading what ever is left"); database.ExtraOptions(); AutoDelete<Parser> ADparse(&parse, new Parser); #ifdef ADDONCMD LogFile->write(EQEMuLog::Status, "Looding addon commands from dll"); if ( !addonCmd.openLib() ) { LogFile->write(EQEMuLog::Error, "Loading addons failed =("); } #endif if (!worldserver.Connect()) { LogFile->write(EQEMuLog::Error, "worldserver.Connect() FAILED!"); } if (strcmp(zone_name, ".") == 0 || strcasecmp(zone_name, "sleep") == 0) { LogFile->write(EQEMuLog::Status, "Entering sleep mode"); } else if (!Zone::Bootup(database.GetZoneID(zone_name), true)) { LogFile->write(EQEMuLog::Error, "Zone bootup FAILED!"); zone = 0; } Timer InterserverTimer(INTERSERVER_TIMER); // does MySQL pings and auto-reconnect UpdateWindowTitle(); bool worldwasconnected = worldserver.Connected(); EQNetworkConnection* eqnc; while(RunLoops) { Timer::SetCurrentTime(); while ((eqnc = eqns.NewQueuePop())) { struct in_addr in; in.s_addr = eqnc->GetrIP(); LogFile->write(EQEMuLog::Status, "%i New client from ip:%s port:%i", Timer::GetCurrentTime(), inet_ntoa(in), ntohs(eqnc->GetrPort())); Client* client = new Client(eqnc); entity_list.AddClient(client); } #ifdef CATCH_CRASH try{ #endif worldserver.Process(); #ifdef CATCH_CRASH } catch(...){ error = 1; adverrornum = worldserver.GetErrorNumber(); worldserver.Disconnect(); worldwasconnected = false; } #endif 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) { { #ifdef CATCH_CRASH try{ #endif entity_list.Process(); #ifdef CATCH_CRASH } catch(...){ error = 4; } try{ #endif zoneprocess= zone->Process(); if (!zoneprocess) { Zone::Shutdown(); } #ifdef CATCH_CRASH } catch(...){ error = 2; } #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(); // 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(_DEBUG) && 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 Sleep(1); } #ifdef CATCH_CRASH if (error) FilePrint("eqemudebug.log",true,true,"Zone %i crashed. Errorcode: %i/%i. Current zone loaded:%s. Current clients:%i. Caused by: %s",net.GetZonePort(), error,adverrornum, zone->GetShortName(), numclients,errorname); try{ entity_list.Message(0, 15, "ZONEWIDE_MESSAGE: This zone caused a fatal error and will shut down now. Your character will be restored to the last saved status. We are sorry for any inconvenience!"); } catch(...){} if (error){ #ifdef WIN32 ExitProcess(error); #else entity_list.Clear(); safe_delete(zone); #endif } #endif entity_list.Clear(); if (zone != 0 #ifdef CATCH_CRASH & !error #endif ) Zone::Shutdown(true); //Fix for Linux world server problem. eqns.Close(); worldserver.Disconnect(); dbasync->CommitWrites(); dbasync->StopThread(); #ifdef NEW_LoadSPDat safe_delete(spells_delete); #endif CheckEQEMuErrorAndPause(); return 0; }
void WorldServer::Process() { if(this == 0) { return; } if(!Connected()) { return; } SOCKADDR_IN to; memset((char *) &to, 0, sizeof(to)); to.sin_family = AF_INET; to.sin_port = port; to.sin_addr.s_addr = ip; /************ Get all packets from packet manager out queue and process them ************/ ServerPacket *pack = 0; while(pack = ServerRecvQueuePop()) { switch(pack->opcode) { case 0: { break; } case ServerOP_KeepAlive: { // ignore this break; } case ServerOP_ChannelMessage: { if (!ZoneLoaded) break; ServerChannelMessage_Struct* scm = (ServerChannelMessage_Struct*) pack->pBuffer; if (scm->deliverto[0] == 0) { entity_list.ChannelMessageFromWorld(scm->from, scm->to, scm->chan_num, scm->guilddbid, scm->language, scm->message); } else { Client* client; client = entity_list.GetClientByName(scm->deliverto); if (client != 0) { if (client->Connected()) { client->ChannelMessageSend(scm->from, scm->to, scm->chan_num, scm->language, scm->message); if (!scm->noreply) { // if it's a tell, echo back so it shows up scm->noreply = true; scm->chan_num = 14; memset(scm->deliverto, 0, sizeof(scm->deliverto)); strcpy(scm->deliverto, scm->from); SendPacket(pack); } } } } break; } case ServerOP_EmoteMessage: { if (!ZoneLoaded) { break; } ServerEmoteMessage_Struct* sem = (ServerEmoteMessage_Struct*) pack->pBuffer; if (sem->to[0] != 0) { if (strcasecmp(sem->to, zone->GetShortName()) == 0) { entity_list.Message(sem->guilddbid, (MessageFormat)sem->type, sem->message); } else { Client* client = entity_list.GetClientByName(sem->to); if (client != 0) { client->Message((MessageFormat)sem->type, sem->message); } } } else { entity_list.Message(sem->guilddbid, (MessageFormat)sem->type, sem->message); } break; } /* case ServerOP_GroupRefresh: //Kibanu - 4/22/2009 { cout << "WorldServer_Process: In Group Refresh" << endl; if (!ZoneLoaded) { break; } ServerGroupRefresh_Struct* gr = (ServerGroupRefresh_Struct*) pack->pBuffer; if (gr->member[0] != 0) { cout << "WorldServer_Process: Refreshing group for " << gr->member << endl; Client* client = entity_list.GetClientByName(gr->member); if (client != 0) { client->RefreshGroup(gr->gid, gr->action); } } break; }*/ case ServerOP_ShutdownAll: { entity_list.Save(); CatchSignal(2); break; } case ServerOP_ZoneShutdown: { // Annouce the change to the world if (!ZoneLoaded) { SetZone(""); } else { worldserver.SendEmoteMessage(0, 0, 15, "Zone shutdown: %s", zone->GetLongName()); ServerZoneStateChange_struct* zst = (ServerZoneStateChange_struct *) pack->pBuffer; cout << "Zone shutdown by " << zst->adminname << endl; Zone::Shutdown(); } break; } case ServerOP_ZoneBootup: { ServerZoneStateChange_struct* zst = (ServerZoneStateChange_struct *) pack->pBuffer; if (ZoneLoaded) { SetZone(zone->GetShortName()); if (strcasecmp(Database::Instance()->GetZoneName(zst->zoneid), zone->GetShortName()) == 0) { // This packet also doubles as "incomming client" notification, lets not shut down before they get here zone->StartShutdownTimer(AUTHENTICATION_TIMEOUT * 1000); } else { worldserver.SendEmoteMessage(zst->adminname, 0, 0, "Zone bootup failed: Already running '%s'", zone->GetShortName()); } break; } if (zst->adminname[0] != 0) { cout << "Zone bootup by " << zst->adminname << endl; } if (!(Zone::Bootup(Database::Instance()->GetZoneName(zst->zoneid)))) { worldserver.SendChannelMessage(0, 0, 10, 0, 0, "%s:%i Zone::Bootup failed: %s", net.GetZoneAddress(), net.GetZonePort(), Database::Instance()->GetZoneName(zst->zoneid)); } break; } case ServerOP_ZonePlayer: { ServerZonePlayer_Struct* szp = (ServerZonePlayer_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(szp->name); if (client != 0) { if (strcasecmp(szp->adminname, szp->name) == 0) { client->Message(BLACK, "Zoning to: %s", szp->zone); } else if (client->GetAnon() == 1 && client->Admin() > szp->adminrank) { break; } else { worldserver.SendEmoteMessage(szp->adminname, 0, 0, "Summoning %s to %s %1.1f, %1.1f, %1.1f", szp->name, szp->zone, szp->x_pos, szp->y_pos, szp->z_pos); } client->SetIsZoning(true); client->SetUsingSoftCodedZoneLine(true); client->SetZoningHeading(client->GetHeading()); client->SetZoningX(szp->x_pos); client->SetZoningY(szp->y_pos); client->SetZoningZ(szp->z_pos); client->ZonePC(szp->zone, szp->x_pos, szp->y_pos, szp->z_pos); } break; } // Cofruben: used to send a packet directly to a client. /* case ServerOP_SendPacket: { ServerSendPacket_Struct* sss = (ServerSendPacket_Struct*)pack->pBuffer; int32 PacketSize = pack->size - sizeof(sss->charname) - sizeof(sss->opcode); Client* PacketTo = entity_list.GetClientByName(sss->charname); if(!PacketTo) { break; } APPLAYER* outapp = new APPLAYER(sss->opcode, PacketSize); memcpy(outapp->pBuffer, sss->packet, PacketSize); PacketTo->QueuePacket(outapp); safe_delete(outapp);//delete outapp; break; }*/ case ServerOP_KickPlayer: { ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(skp->name); if (client != 0) { if (skp->adminrank >= client->Admin()) { client->Kick(); if (ZoneLoaded) { worldserver.SendEmoteMessage(skp->adminname, 0, 0, "Remote Kick: %s booted in zone %s.", skp->name, zone->GetShortName()); } else { worldserver.SendEmoteMessage(skp->adminname, 0, 0, "Remote Kick: %s booted.", skp->name); } } else if (client->GetAnon() != 1) { worldserver.SendEmoteMessage(skp->adminname, 0, 0, "Remote Kick: Your avatar level is not high enough to kick %s", skp->name); } } break; } case ServerOP_KillPlayer: { ServerKillPlayer_Struct* skp = (ServerKillPlayer_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(skp->target); if (client != 0) { if (skp->admin >= client->Admin()) { client->Kill(); if (ZoneLoaded) { worldserver.SendEmoteMessage(skp->gmname, 0, 0, "Remote Kill: %s killed in zone %s.", skp->target, zone->GetShortName()); } else { worldserver.SendEmoteMessage(skp->gmname, 0, 0, "Remote Kill: %s killed.", skp->target); } } else if (client->GetAnon() != 1) { worldserver.SendEmoteMessage(skp->gmname, 0, 0, "Remote Kill: Your avatar level is not high enough to kill %s", skp->target); } } break; } case ServerOP_RefreshGuild: { if (pack->size == 5) { int32 guildeqid = 0; memcpy(&guildeqid, pack->pBuffer, 4); zgm.LoadGuilds(); Guild_Struct* guilds = zgm.GetGuildList(); if (pack->pBuffer[4] == 1) { APPLAYER* outapp = new APPLAYER(OP_GuildUpdate, 64); memset(outapp->pBuffer, 0, outapp->size); GuildUpdate_Struct* gu = (GuildUpdate_Struct*) outapp->pBuffer; gu->guildID = guildeqid; gu->entry.guildID = guildeqid; if (guilds[guildeqid].databaseID == 0) { gu->entry.exists = 0; // = 0x01 if exists, 0x00 on empty } else { strcpy(gu->entry.name, guilds[guildeqid].name); gu->entry.exists = 1; // = 0x01 if exists, 0x00 on empty } gu->entry.unknown1[0] = 0xFF; gu->entry.unknown1[1] = 0xFF; gu->entry.unknown1[2] = 0xFF; gu->entry.unknown1[3] = 0xFF; gu->entry.unknown3[0] = 0xFF; gu->entry.unknown3[1] = 0xFF; gu->entry.unknown3[2] = 0xFF; gu->entry.unknown3[3] = 0xFF; entity_list.QueueClients(0, outapp, false); safe_delete(outapp);//delete outapp; } } else cout << "Wrong size: ServerOP_RefreshGuild. size=" << pack->size << endl; break; } case ServerOP_GuildLeader: { ServerGuildCommand_Struct* sgc = (ServerGuildCommand_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(sgc->target); if (client == 0) { // do nothing } else if (client->GuildDBID() != sgc->guilddbid) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "%s is not in your guild.", client->GetName()); } else if ((client->GuildRank() != 0) || (client->GuildRank() != 1)) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "%s is not rank 0.", client->GetName()); } else { if (Database::Instance()->SetGuildLeader(sgc->guilddbid, client->AccountID())) { worldserver.SendEmoteMessage(0, sgc->guilddbid, MESSAGETYPE_Guild, "%s is now the leader of your guild.", client->GetName()); ServerPacket* pack2 = new ServerPacket(ServerOP_RefreshGuild, 4); pack2->pBuffer = new uchar[pack->size]; memcpy(pack2->pBuffer, &sgc->guildeqid, 4); worldserver.SendPacket(pack2); safe_delete(pack2);//delete pack2; } else { worldserver.SendEmoteMessage(sgc->from, 0, 0, "Guild leadership transfer failed."); } } break; } case ServerOP_GuildInvite: { ServerGuildCommand_Struct* sgc = (ServerGuildCommand_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(sgc->target); zgm.LoadGuilds(); Guild_Struct* guilds = zgm.GetGuildList(); if (client == 0) { // do nothing } else if (!guilds[sgc->guildeqid].rank[sgc->fromrank].invite) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "You dont have permission to invite."); } else if (client->GuildDBID() != 0) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "%s is already in another guild.", client->GetName()); } else if (client->PendingGuildInvite != 0 && !(client->PendingGuildInvite == sgc->guilddbid)) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "%s has another pending guild invite.", client->GetName()); } else { client->PendingGuildInvite = sgc->guilddbid; APPLAYER* outapp = new APPLAYER(OP_GuildInvite, sizeof(GuildCommand_Struct)); memset(outapp->pBuffer, 0, outapp->size); GuildCommand_Struct* gc = (GuildCommand_Struct*) outapp->pBuffer; gc->guildeqid = sgc->guildeqid; strcpy(gc->Inviter, sgc->target); strcpy(gc->Invitee, sgc->from); client->QueuePacket(outapp); /* if (client->SetGuild(sgc->guilddbid, GUILD_MAX_RANK)) worldserver.SendEmoteMessage(0, sgc->guilddbid, MT_Guild, "%s has joined the guild. Rank: %s.", client->GetName(), guilds[sgc->guildeqid].rank[GUILD_MAX_RANK].rankname); else worldserver.SendEmoteMessage(sgc->from, 0, 0, "Guild invite failed."); */ } break; } case ServerOP_GuildRemove: { ServerGuildCommand_Struct* sgc = (ServerGuildCommand_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(sgc->target); zgm.LoadGuilds(); Guild_Struct* guilds = zgm.GetGuildList(); if (client == 0) { // do nothing } else if ((!guilds[sgc->guildeqid].rank[sgc->fromrank].remove) && !(strcasecmp(sgc->from, sgc->target) == 0)) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "You dont have permission to remove."); } else if (client->GuildDBID() != sgc->guilddbid) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "%s is not in your guild.", client->GetName()); } else if (client->GuildRank() <= sgc->fromrank && !(sgc->fromaccountid == guilds[sgc->guildeqid].leader) && !(strcasecmp(sgc->from, sgc->target) == 0)) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "%s's rank is too high for you to remove them.", client->GetName()); } else { if (client->SetGuild(0, GUILD_MAX_RANK)) { if (strcasecmp(sgc->from, sgc->target) == 0) { worldserver.SendEmoteMessage(0, sgc->guilddbid, GUILD, "%s has left the guild.", client->GetName()); } else { worldserver.SendEmoteMessage(0, sgc->guilddbid, GUILD, "%s has been removed from the guild by %s.", client->GetName(), sgc->from); client->Message(GUILD, "You have been removed from the guild by %s.", sgc->from); } } else { worldserver.SendEmoteMessage(sgc->from, 0, 0, "Guild remove failed."); } } break; } case ServerOP_GuildPromote: { ServerGuildCommand_Struct* sgc = (ServerGuildCommand_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(sgc->target); zgm.LoadGuilds(); Guild_Struct* guilds = zgm.GetGuildList(); if (client == 0) { // do nothing } else if (client->GuildDBID() != sgc->guilddbid) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "%s is not in your guild.", client->GetName()); } else if ((!guilds[sgc->guildeqid].rank[sgc->fromrank].promote) && !(strcasecmp(sgc->from, sgc->target) == 0)) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "You dont have permission to promote."); } else if (client->GuildDBID() != sgc->guilddbid) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "%s isnt in your guild.", client->GetName()); } else if (client->GuildRank() <= sgc->newrank) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "%s is already rank %i.", client->GetName(), client->GuildRank()); } else if (sgc->newrank <= sgc->fromrank && sgc->fromaccountid != guilds[sgc->guildeqid].leader) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "You cannot promote people to a greater or equal rank than yourself."); } else { if (client->SetGuild(sgc->guilddbid, sgc->newrank)) { worldserver.SendEmoteMessage(0, sgc->guilddbid, MESSAGETYPE_Guild, "%s has been promoted to %s by %s.", client->GetName(), guilds[sgc->guildeqid].rank[sgc->newrank].rankname, sgc->from); } else { worldserver.SendEmoteMessage(sgc->from, 0, 0, "Guild promote failed"); } } break; } case ServerOP_GuildDemote: { ServerGuildCommand_Struct* sgc = (ServerGuildCommand_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(sgc->target); zgm.LoadGuilds(); Guild_Struct* guilds = zgm.GetGuildList(); if (client == 0) { // do nothing } else if (client->GuildDBID() != sgc->guilddbid) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "%s is not in your guild.", client->GetName()); } else if (!guilds[sgc->guildeqid].rank[sgc->fromrank].demote) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "You dont have permission to demote."); } else if (client->GuildRank() >= sgc->newrank) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "%s is already rank %i.", client->GetName(), client->GuildRank()); } else if (sgc->newrank <= sgc->fromrank && sgc->fromaccountid != guilds[sgc->guildeqid].leader && !(strcasecmp(sgc->from, sgc->target) == 0)) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "You cannot demote people with a greater or equal rank than yourself."); } else { if (client->SetGuild(sgc->guilddbid, sgc->newrank)) { worldserver.SendEmoteMessage(0, sgc->guilddbid, MESSAGETYPE_Guild, "%s has been demoted to %s by %s.", client->GetName(), guilds[sgc->guildeqid].rank[sgc->newrank].rankname, sgc->from); } else { worldserver.SendEmoteMessage(sgc->from, 0, 0, "Guild demote failed"); } } break; } case ServerOP_GuildGMSet: { ServerGuildCommand_Struct* sgc = (ServerGuildCommand_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(sgc->target); if (client != 0) { if (client->GuildDBID() == 0 || sgc->guilddbid == 0) { if (!client->SetGuild(sgc->guilddbid, GUILD_MAX_RANK)) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "Error: Guild #%i not found", sgc->guilddbid); } } else { worldserver.SendEmoteMessage(sgc->from, 0, 0, "Error: %s is already in a guild", sgc->target); } } break; } case ServerOP_GuildGMSetRank: { ServerGuildCommand_Struct* sgc = (ServerGuildCommand_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(sgc->target); if (client != 0) { if (client->GuildDBID() != 0) { if (!client->SetGuild(client->GuildDBID(), sgc->newrank)) { worldserver.SendEmoteMessage(sgc->from, 0, 0, "Error: SetRank failed.", sgc->guilddbid); } } else { worldserver.SendEmoteMessage(sgc->from, 0, 0, "Error: %s is not in a guild", sgc->target); } } break; } /* case ServerOP_GuildCreateResponse: { GuildCreateResponse_Struct* gcrs = (GuildCreateResponse_Struct*) pack->pBuffer; if(gcrs->Created) { cout << "Guild " << gcrs->GuildName << " created." << endl; Client* client = entity_list.GetClientByName(gcrs->LeaderCharName); // invite the client to guild zgm.InviteToGuild(0, gcrs->eqid, client, client, GuildLeader); } break; }*/ case ServerOP_FlagUpdate: { Client* client = entity_list.GetClientByAccID(Database::Instance()->GetAccountIDByName((char*) pack->pBuffer)); if (client != 0) { client->UpdateAdmin(); } break; } case ServerOP_GMGoto: { if (pack->size != sizeof(ServerGMGoto_Struct)) { cout << "Wrong size on ServerOP_GMGoto. Got: " << pack->size << ", Expected: " << sizeof(ServerGMGoto_Struct) << endl; break; } if (!ZoneLoaded) { break; } ServerGMGoto_Struct* gmg = (ServerGMGoto_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(gmg->gotoname); if (client != 0) { worldserver.SendEmoteMessage(gmg->myname, 0, 13, "Summoning you to: %s @ %s, %1.1f, %1.1f, %1.1f", client->GetName(), zone->GetShortName(), client->GetX(), client->GetY(), client->GetZ()); ServerPacket* outpack = new ServerPacket(ServerOP_ZonePlayer, sizeof(ServerZonePlayer_Struct)); outpack->pBuffer = new uchar[outpack->size]; memset(outpack->pBuffer, 0, outpack->size); ServerZonePlayer_Struct* szp = (ServerZonePlayer_Struct*) outpack->pBuffer; strcpy(szp->adminname, gmg->myname); strcpy(szp->name, gmg->myname); strcpy(szp->zone, zone->GetShortName()); szp->x_pos = client->GetX(); szp->y_pos = client->GetY(); szp->z_pos = client->GetZ(); worldserver.SendPacket(outpack); safe_delete(outpack);//delete outpack; } else { worldserver.SendEmoteMessage(gmg->myname, 0, 13, "Error: %s not found", gmg->gotoname); } break; } case ServerOP_MultiLineMsg: { ServerMultiLineMsg_Struct* mlm = (ServerMultiLineMsg_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(mlm->to); if (client) { APPLAYER* outapp = new APPLAYER(OP_MultiLineMsg, strlen(mlm->message)); strcpy((char*) outapp->pBuffer, mlm->message); client->QueuePacket(outapp); safe_delete(outapp);//delete outapp; } break; } case ServerOP_RezzPlayer: { RezzPlayer_Struct* srs = (RezzPlayer_Struct*)pack->pBuffer; //Yeahlight: A resurrection request has been made if(srs->rezzopcode == OP_RezzRequest) { Client* client = entity_list.GetClientByName(srs->owner); //Yeahlight: Owner of the corpse is online if(client) { Spell* spell = spells_handler.GetSpellPtr(srs->rez.spellID); //Yeahlight: Spell passed through the packet is a legit spell if(spell) { //Yeahlight: Record the pending resurrection information client->SetPendingRez(true); client->SetPendingRezExp(srs->exp); client->SetPendingCorpseID(srs->corpseDBID); client->SetPendingRezX(srs->rez.x); client->SetPendingRezY(srs->rez.y); client->SetPendingRezZ(srs->rez.z); client->SetPendingRezZone(srs->rez.zoneName); client->SetPendingSpellID(spell->GetSpellID()); client->StartPendingRezTimer(); if(client->GetDebugMe()) client->Message(YELLOW, "Debug: Forwarding the resurrection request to your client (%s)", srs->rez.targetName); //Yeahlight: Forward the resurrection packet to the corpse's owner APPLAYER* outapp = new APPLAYER(OP_RezzRequest, sizeof(Resurrect_Struct)); Resurrect_Struct* rez = (Resurrect_Struct*)outapp->pBuffer; memset(rez, 0, sizeof(Resurrect_Struct)); memcpy(rez, &srs->rez, sizeof(Resurrect_Struct)); client->QueuePacket(outapp); safe_delete(outapp); } } } //Yeahlight: A resurrection confirmation has been made else if(srs->rezzopcode == OP_RezzAnswer) { Client* client = entity_list.GetClientByName(srs->owner); //Yeahlight: Owner of the corpse is online if(client) { bool fullGMRez = false; //Yeahlight: The corpse owner answers 'yes' to the request if(srs->action == 1) { Database::Instance()->SetCorpseRezzed(client->GetPendingCorpseID()); //Yeahlight: Player casted resurrection if(client->GetPendingSpellID() != 994) { float expRefund = 0.00; //Yeahlight: PC has exp on the corpse if(client->GetPendingRezExp()) { //Yeahlight: Switch based on spell ID switch(client->GetPendingSpellID()) { //Yeahlight: Revive case 391: { expRefund = 0.00; break; } //Yeahlight: Resuscitate case 388: { expRefund = 0.50; break; } //Yeahlight: Resurrection case 392: { expRefund = 0.90; break; } //Yeahlight: Reviviscence case 1524: { expRefund = 0.96; break; } //Yeahlight: Convergence case 1733: { expRefund = 0.93; break; } default: { client->Message(RED, "ERROR: Unknown resurrection spell ID: %i", client->GetPendingSpellID()); expRefund = 0.00; } } if(client->GetDebugMe()) client->Message(LIGHTEN_BLUE, "Debug: Your resurrection return on exp: %1.2f", expRefund); client->AddEXP(client->GetPendingRezExp() * expRefund, true); } } //Yeahlight: GM casted resurrection else { fullGMRez = true; if(client->GetDebugMe()) client->Message(LIGHTEN_BLUE, "Debug: Your resurrection return on exp: 1.00"); client->AddEXP(client->GetPendingRezExp(), true); } //Yeahlight: Client is being resurrected in another zone; prepare them for transit if(strcmp(zone->GetShortName(), srs->rez.zoneName) != 0) { client->SetTempHeading(0); client->SetUsingSoftCodedZoneLine(true); client->SetIsZoning(true); client->SetZoningX(client->GetPendingRezX()); client->SetZoningY(client->GetPendingRezY()); client->SetZoningZ(client->GetPendingRezZ()); } //Yeahlight: Send the packet back to the owner of the corpse APPLAYER* outapp = new APPLAYER(OP_RezzComplete, sizeof(Resurrect_Struct)); memcpy(outapp->pBuffer, &srs->rez, sizeof(Resurrect_Struct)); srs->rez.fullGMRez = fullGMRez; client->QueuePacket(outapp); safe_delete(outapp); } //Yeahlight: The corpse owner answers 'no' to the request else if(srs->action == 0) { client->Message(BLACK, "You decline the request to be resurrected."); client->SetPendingRez(false); client->SetPendingRezExp(0); } } } break; } case ServerOP_Uptime: { if (pack->size != sizeof(ServerUptime_Struct)) { cout << "Wrong size on ServerOP_Uptime. Got: " << pack->size << ", Expected: " << sizeof(ServerUptime_Struct) << endl; break; } ServerUptime_Struct* sus = (ServerUptime_Struct*) pack->pBuffer; int32 ms = Timer::GetCurrentTime(); int32 d = ms / 86400000; ms -= d * 86400000; int32 h = ms / 3600000; ms -= h * 3600000; int32 m = ms / 60000; ms -= m * 60000; int32 s = ms / 1000; if (d) { this->SendEmoteMessage(sus->adminname, 0, 0, "Zone #%i Uptime: %02id %02ih %02im %02is", sus->zoneserverid, d, h, m, s); } else if (h) { this->SendEmoteMessage(sus->adminname, 0, 0, "Zone #%i Uptime: %02ih %02im %02is", sus->zoneserverid, h, m, s); } else { this->SendEmoteMessage(sus->adminname, 0, 0, "Zone #%i Uptime: %02im %02is", sus->zoneserverid, m, s); } break; } case ServerOP_Petition: { cout << "Got Server Requested Petition List Refresh" << endl; ServerPetitionUpdate_Struct* sus = (ServerPetitionUpdate_Struct*) pack->pBuffer; if (sus->status = 0) { petition_list.ReadDatabase(); } else if (sus->status = 1) { petition_list.ReadDatabase(); // Until I fix this to be better.... } break; } case ServerOP_RemoveBoat: // Tazadar (06/12/09) : We remove the boat from the zone { BoatName_Struct* bs = (BoatName_Struct*) pack->pBuffer; cout << "Trying to remove the boat : " << bs->boatname << endl; Mob * tmp = entity_list.GetMob(bs->boatname); if(tmp){ tmp->CastToNPC()->Depop(false); entity_list.RemoveNPC(tmp->CastToNPC()); } break; } case ServerOP_ZoneBoat : // Tazadar (06/16/09) : We teleport player to the other zone ! { cout << "A boat is zoning ! Teleporting clients !" << endl; ZoneBoat_Struct * zb = (ZoneBoat_Struct *) pack->pBuffer; Entity * tmp = 0; Mob * boat = entity_list.GetMob(zb->boatname); float xboat,yboat,zboat,headingboat; if(boat){ xboat = boat->GetX(); yboat = boat->GetY(); zboat = boat->GetZ();; headingboat = boat->GetHeading(); } else{ cerr << "Error in ServerOP_ZoneBoat boat : "<< zb->boatname << " does not exist."<<endl; break; } char * clients = (char *) pack->pBuffer; char zone[16] = ""; strcpy(zone, zb->zonename); char name[30]; float x,y,z,heading; for(int i=0 ; i < zb->numberOfPlayers ; i++){ memcpy(name,clients+sizeof(ZoneBoat_Struct)+30*i,30*sizeof(char)); cout << "Trying to teleport : "<< name << endl; tmp = entity_list.GetClientByName(name); if(tmp != 0 && tmp->IsClient()){ //cout << "ZonePC to " << zone << endl; Client * client = tmp->CastToClient(); heading = client->GetHeading()-headingboat; // Tazadar : Relative heading from the boat z = client->GetZ()-zboat; // Tazadar : Relative z from the boat client->GetRelativeCoordToBoat(client->GetY()-yboat,client->GetX()-xboat,(zb->heading-headingboat)*1.4,y,x); client->SetZoningHeading(zb->heading+heading); client->SetUsingSoftCodedZoneLine(true); client->SetIsZoning(true); client->SetZoningX(zb->x+x); client->SetZoningY(zb->y+y); client->SetZoningZ(zb->z+z); client->ZonePC(zone,0,0,10); } else{ // Tazadar : Player has crashed ? We remove it from boat infos // Tazadar : Make the packet for the World Serv ServerPacket* pack = new ServerPacket(ServerOP_BoatPL, sizeof(ServerBoat_Struct)); ServerBoat_Struct* servBoatInfos = (ServerBoat_Struct*) pack->pBuffer; // Tazadar : Fill the packet memcpy(servBoatInfos->player_name,name,sizeof(servBoatInfos->player_name)); // Tazadar : Send the packet worldserver.SendPacket(pack); } } break; } case ServerOP_SpawnBoat: // Tazadar (06/13/09) : We make the boat spawn before the zone in at the correct location. { SpawnBoat_Struct * bs = (SpawnBoat_Struct *) pack->pBuffer; Mob * tmp = 0; cout << "Spawning the boat :" << bs->boatname << "at loc " << bs->x <<","<< bs->y << "," << bs->z <<" heading " << bs->heading<<endl; //cout << "Loading boat from DB " << endl; string name = bs->boatname; name.resize(name.length()-2); NPCType boat; bool lineroute = false; Database::Instance()->LoadBoatData(name.c_str(),boat,lineroute); NPC* npc = new NPC(&boat, 0, bs->x, bs->y, bs->z, bs->heading); npc->SetLineRoute(lineroute); entity_list.AddNPC(npc); npc->SendPosUpdate(false); break; } case ServerOP_BoatGoTo : // Tazadar (06/14/09) : We make the boat move { BoatGoTo_Struct * gt = (BoatGoTo_Struct *) pack->pBuffer; cout << "World orders " << gt->boatname << " to go to node number " << gt->toNode << endl; Mob * tmp = entity_list.GetMob(gt->boatname); if(tmp && tmp->IsNPC()){ if(tmp->CastToNPC()->IsBoat()){ tmp->CastToNPC()->setBoatDestinationNode(gt->fromNode,gt->toNode); } else{ cerr << "Tried to give an order to the npc "<< gt->boatname <<" which is not a boat " << endl; } } else{ cerr << "Error in ServerOP_BoatGoTo boat " << gt->boatname << " does not exist"<<endl; } break; } case ServerOP_DayTime : // Kibanu - 7/30/2009 : Switch to day time for spawn data { if (ZoneLoaded) zone->SetTimeOfDay(true); break; } case ServerOP_NightTime : // Kibanu - 7/30/2009 : Switch to day time for spawn data { if (ZoneLoaded) zone->SetTimeOfDay(false); break; } case ServerOP_ZoneToZoneRequest: { if(pack->size != sizeof(ZoneToZone_Struct)) break; if (!ZoneLoaded) break; ZoneToZone_Struct* ztz = (ZoneToZone_Struct*) pack->pBuffer; if(ztz->current_zone_id == zone->GetZoneID()) { // it's a response Entity* entity = entity_list.GetClientByName(ztz->name); if(entity == 0) break; APPLAYER *outapp; outapp = new APPLAYER(OP_ZoneChange,sizeof(ZoneChange_Struct)); ZoneChange_Struct* zc2=(ZoneChange_Struct*)outapp->pBuffer; if(ztz->response == 0 || ztz->response == -1) { zc2->success = ZONE_ERROR_NOTREADY; entity->CastToMob()->SetZone(ztz->current_zone_id); } else { strncpy(zc2->char_name,entity->CastToMob()->GetName(),64); zc2->zoneID=ztz->requested_zone_id; zc2->success = 1; } entity->CastToClient()->QueuePacket(outapp); delete outapp; switch(ztz->response) { case -1: { entity->CastToMob()->Message(RED,"The zone is currently full, please try again later."); break; } case 0: { entity->CastToMob()->Message(RED,"All zone servers are taken at this time, please try again later."); break; } } } else { // it's a request if(zone->GetMaxClients() != 0 && numclients >= zone->GetMaxClients()) ztz->response = -1; else { ztz->response = 1; // since they asked about coming, lets assume they are on their way and not shut down. zone->StartShutdownTimer(AUTHENTICATION_TIMEOUT * 1000); } SendPacket(pack); break; } break; } default: { cout << "Unknown ZSopcode:" << (int)pack->opcode; cout << "size:" << pack->size << endl; //DumpPacket(pack->pBuffer, pack->size); break; } } safe_delete(pack);//delete pack; //Yeahlight: Zone freeze debug if(ZONE_FREEZE_DEBUG && rand()%ZONE_FREEZE_DEBUG == 1) EQC_FREEZE_DEBUG(__LINE__, __FILE__); } return; }