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 }
// this should always be called in a new thread void WorldServerLoop(void *tmp) { WorldLoopRunning = true; while(RunLoops) { if (worldserver.Connected()) { if (!(worldserver.ReceiveData() && worldserver.SendPacketQueue())) { worldserver.Disconnect(); } } else if (worldserver.GetState() == WSCS_Ready) { if (worldserver.ReconnectTimer->Check()) { worldserver.Connect(); } } Sleep(1); } WorldLoopRunning = false; }
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; }
void Client::GuildCommand(Seperator* sep) { zgm.LoadGuilds(); Guild_Struct* guilds = zgm.GetGuildList(); if (strcasecmp(sep->arg[1], "help") == 0) { this->GuildPCCommandHelp(); this->GuildGMCommandHelp(); } else if (strcasecmp(sep->arg[1], "status") == 0 || strcasecmp(sep->arg[1], "stat") == 0) { Client* client = 0; if (sep->arg[2][0] != 0) { client = entity_list.GetClientByName(sep->argplus[2]); } else if (target != 0 && target->IsClient()) { client = target->CastToClient(); } if (client == 0) { this->Message(BLACK, "You must target someone or specify a character name"); } else if ((client->Admin() >= 100 && admin < 100) && client->GuildDBID() != guilddbid) // no peeping for GMs, make sure tell message stays the same { this->Message(BLACK, "You must target someone or specify a character name."); } else { if (client->GuildDBID() == 0) { this->Message(BLACK, "%s is not in a guild.", client->GetName()); } else if (guilds[client->GuildEQID()].leader == client->AccountID()) { this->Message(BLACK, "%s is the leader of <%s> rank: %s", client->GetName(), guilds[client->GuildEQID()].name, guilds[client->GuildEQID()].rank[client->GuildRank()].rankname); } else { this->Message(BLACK, "%s is a member of <%s> rank: %s", client->GetName(), guilds[client->GuildEQID()].name, guilds[client->GuildEQID()].rank[client->GuildRank()].rankname); } } } else if (strcasecmp(sep->arg[1], "info") == 0) { if (sep->arg[2][0] == 0 && guilddbid == 0) { if (admin >= 100) { this->Message(BLACK, "Usage: #guildinfo guilddbid"); } else { this->Message(BLACK, "You're not in a guild"); } } else { int32 tmp; if (sep->arg[2][0] == 0) { tmp = Database::Instance()->GetGuildEQID(guilddbid); } else { tmp = Database::Instance()->GetGuildEQID(atoi(sep->arg[2])); } if (tmp < 0 || tmp >= 512) { this->Message(BLACK, "Guild not found."); } else { this->Message(BLACK, "Guild info DB# %i, %s", guilds[tmp].databaseID, guilds[tmp].name); if (this->admin >= 100 || guildeqid == tmp) { if (this->account_id == guilds[tmp].leader || guildrank == 0 || admin >= 100) { char leadername[32]; Database::Instance()->GetAccountName(guilds[tmp].leader, leadername); this->Message(BLACK, "Guild Leader: %s", leadername); } for (int i = 0; i <= GUILD_MAX_RANK; i++) { this->Message(BLACK, "Rank %i: %s", i, guilds[tmp].rank[i].rankname); this->Message(BLACK, " HearGU: %i SpeakGU: %i Invite: %i Remove: %i Promote: %i Demote: %i MOTD: %i War/Peace: %i", guilds[tmp].rank[i].heargu, guilds[tmp].rank[i].speakgu, guilds[tmp].rank[i].invite, guilds[tmp].rank[i].remove, guilds[tmp].rank[i].promote, guilds[tmp].rank[i].demote, guilds[tmp].rank[i].motd, guilds[tmp].rank[i].warpeace); } } } } } else if (strcasecmp(sep->arg[1], "leader") == 0) { if (guilddbid == 0) { this->Message(BLACK, "You arent in a guild!"); } else if (guilds[guildeqid].leader != account_id) { this->Message(BLACK, "You aren't the guild leader."); } else { char* tmptar = 0; if (sep->arg[2][0] != 0) { tmptar = sep->argplus[2]; } else if (tmptar == 0 && target != 0 && target->IsClient()) { tmptar = target->CastToClient()->GetName(); } if (tmptar == 0) { Message(BLACK, "You must target someone or specify a character name."); } else { // Dark-Prince - 10/05/2008 - Code Consolidation //zgm.InviteToGuild( //this->SendGuildInvitePacket(tmptar); } } } else if (strcasecmp(sep->arg[1], "invite") == 0) { int32 GuildDBID = atoi(sep->arg[2]); Client* Invitee = entity_list.GetClientByName(sep->arg[3]); GUILDRANK Rank = (GUILDRANK)atoi(sep->arg[4]); int32 GuidlEQID = Database::Instance()->GetGuildEQID(GuildDBID); zgm.InviteToGuild(GuildDBID, GuidlEQID, this, Invitee, Rank); } else if (strcasecmp(sep->arg[1], "remove") == 0) { Client* Removee = entity_list.GetClientByName(sep->arg[2]); if(Removee != 0) { zgm.RemovePCFromGuild(this, Removee); } } else if (strcasecmp(sep->arg[1], "promote") == 0) { if (guilddbid == 0) { Message(BLACK, "You arent in a guild!"); } else if (!(strlen(sep->arg[2]) == 1 && sep->arg[2][0] >= '0' && sep->arg[2][0] <= '9')) { Message(BLACK, "Usage: #guild promote rank [charname]"); } else if (atoi(sep->arg[2]) < 0 || atoi(sep->arg[2]) > GUILD_MAX_RANK) { Message(BLACK, "Error: invalid rank #."); } else { char* tmptar = 0; if (sep->arg[3][0] != 0) { tmptar = sep->argplus[3]; } else if (tmptar == 0 && target != 0 && target->IsClient()) { tmptar = target->CastToClient()->GetName(); } if (tmptar == 0) { Message(BLACK, "You must target someone or specify a character name."); } else { zgm.SendGuildPromotePacket(tmptar, this->GetName()); } } } else if (strcasecmp(sep->arg[1], "demote") == 0) { if (guilddbid == 0) { Message(BLACK, "You arent in a guild!"); } else if (!(strlen(sep->arg[2]) == 1 && sep->arg[2][0] >= '0' && sep->arg[2][0] <= '9')) { Message(BLACK, "Usage: #guild demote rank [charname]"); } else if (atoi(sep->arg[2]) < 0 || atoi(sep->arg[2]) > GUILD_MAX_RANK) { Message(BLACK, "Error: invalid rank #."); } else { char* tmptar = 0; if (sep->arg[3][0] != 0) { tmptar = sep->argplus[3]; } else if (tmptar == 0 && target != 0 && target->IsClient()) { tmptar = target->CastToClient()->GetName(); } if (tmptar == 0) { Message(BLACK, "You must target someone or specify a character name."); } else { zgm.SendGuildDemotePacket(tmptar); } } } else if (strcasecmp(sep->arg[1], "motd") == 0) { if (guilddbid == 0) { Message(BLACK, "You arent in a guild!"); } else if (!guilds[guildeqid].rank[guildrank].motd) { Message(BLACK, "You dont have permission to change the motd."); } else if (!worldserver.Connected()) { Message(BLACK, "Error: World server dirconnected"); } else { char tmp[255]; if (strcasecmp(sep->argplus[2], "none") == 0) { strcpy(tmp, ""); } else { snprintf(tmp, sizeof(tmp), "%s - %s", this->GetName(), sep->argplus[2]); } if (Database::Instance()->SetGuildMOTD(guilddbid, tmp)) { // Dark-Prince - 10/05/2008 - Code Consolidation /* ServerPacket* pack = new ServerPacket; pack->opcode = ServerOP_RefreshGuild; pack->size = 5; pack->pBuffer = new uchar[pack->size]; memcpy(pack->pBuffer, &guildeqid, 4); worldserver.SendPacket(pack); safe_delete(pack);//delete pack; */ } else { this->Message(BLACK, "Motd update failed."); } } } else if (strcasecmp(sep->arg[1], "edit") == 0) { if (guilddbid == 0) { Message(BLACK, "You arent in a guild!"); } else if (!sep->IsNumber(2)) { Message(BLACK, "Error: invalid rank #."); } else if (atoi(sep->arg[2]) < 0 || atoi(sep->arg[2]) > GUILD_MAX_RANK) { Message(BLACK, "Error: invalid rank #."); } else if (!guildrank == 0) { Message(BLACK, "You must be rank %s to use edit.", guilds[guildeqid].rank[0].rankname); } else if (!worldserver.Connected()) { Message(BLACK, "Error: World server dirconnected"); } else { if (!GuildEditCommand(guilddbid, guildeqid, atoi(sep->arg[2]), sep->arg[3], sep->argplus[4])) { Message(BLACK, " #guild edit rank title newtitle"); Message(BLACK, " #guild edit rank permission 0/1"); } else { zgm.SendGuildRefreshPacket(guildeqid); } } } // Start of GM Guild Commands else if (strcasecmp(sep->arg[1], "gmedit") == 0 && admin >= 100) { if (!sep->IsNumber(2)) { Message(BLACK, "Error: invalid guilddbid."); } else if (!sep->IsNumber(3)) { Message(BLACK, "Error: invalid rank #."); } else if (atoi(sep->arg[3]) < 0 || atoi(sep->arg[3]) > GUILD_MAX_RANK) { Message(BLACK, "Error: invalid rank #."); } else if (!worldserver.Connected()) { Message(BLACK, "Error: World server dirconnected"); } else { int32 eqid = Database::Instance()->GetGuildEQID(atoi(sep->arg[2])); if (eqid == 0xFFFFFFFF) { Message(BLACK, "Error: Guild not found"); } else if (!GuildEditCommand(atoi(sep->arg[2]), eqid, atoi(sep->arg[3]), sep->arg[4], sep->argplus[5])) { Message(BLACK, " #guild gmedit guilddbid rank title newtitle"); Message(BLACK, " #guild gmedit guilddbid rank permission 0/1"); } else { zgm.SendGuildRefreshPacket(eqid); } } } else if (strcasecmp(sep->arg[1], "set") == 0 && admin >= 100) { if (!sep->IsNumber(3)) { Message(BLACK, "Usage: #guild set charname guildgbid (0 = clear guildtag)"); } else { /* -- Work in progress GUILDRANK rank = GuildMember; Client* c = entity_list.GetClientByName(sep->arg[2]); if(c == 0) { Message(BLACK, "Player not found!"); return; } int GuidDBID = atoi(sep->arg[3]); if(sep->IsNumber(4)) { rank = (GUILDRANK)atoi(sep->arg[4]); } zgm.LoadGuilds(); int32 GuidEQID = Database::Instance()->GetGuildEQID(GuidDBID); zgm.InviteToGuild(GuidDBID, GuidEQID, this, c, rank); */ ServerPacket* pack = new ServerPacket(ServerOP_GuildGMSet, sizeof(ServerGuildCommand_Struct)); pack->pBuffer = new uchar[pack->size]; memset(pack->pBuffer, 0, pack->size); ServerGuildCommand_Struct* sgc = (ServerGuildCommand_Struct*) pack->pBuffer; sgc->guilddbid = atoi(sep->arg[3]); sgc->admin = admin; strcpy(sgc->from, name); strcpy(sgc->target, sep->arg[2]); worldserver.SendPacket(pack); safe_delete(pack);//delete pack; } } else if (strcasecmp(sep->arg[1], "setrank") == 0 && admin >= 100) { if (!sep->IsNumber(3)) { Message(BLACK, "Usage: #guild setrank charname rank"); } else if (atoi(sep->arg[3]) < 0 || atoi(sep->arg[3]) > GUILD_MAX_RANK) { Message(BLACK, "Error: invalid rank #."); } else { ServerPacket* pack = new ServerPacket(ServerOP_GuildGMSetRank, sizeof(ServerGuildCommand_Struct)); pack->pBuffer = new uchar[pack->size]; memset(pack->pBuffer, 0, pack->size); ServerGuildCommand_Struct* sgc = (ServerGuildCommand_Struct*) pack->pBuffer; sgc->newrank = (GUILDRANK)atoi(sep->arg[3]); sgc->admin = admin; strcpy(sgc->from, name); strcpy(sgc->target, sep->arg[2]); worldserver.SendPacket(pack); target->CastToClient()->SetGuild(target->CastToClient()->guilddbid, sgc->newrank); safe_delete(pack);//delete pack; } } /* New Guild Creation -> Challenge/Response method */ else if (strcasecmp(sep->arg[1], "dpcreate") == 0 && admin >= 100) { if (sep->arg[3][0] == 0) { Message(BLACK, "Usage: #guild create {guildleader charname or AccountID} guild name"); } else if (!worldserver.Connected()) { Message(BLACK, "Error: World server dirconnected"); } else { zgm.CreateGuildRequest(this, sep->arg[2], sep->argplus[3]); } } /* END New Guild Creation -> Challenge/Response method */ else if (strcasecmp(sep->arg[1], "create") == 0 && admin >= 100) { if (sep->arg[3][0] == 0) { Message(BLACK, "Usage: #guild create {guildleader charname or AccountID} guild name"); } else if (!worldserver.Connected()) { Message(BLACK, "Error: World server dirconnected"); } else { Client* Leader = entity_list.GetClientByName(sep->arg[2]); int32 guilddbid = 0; if(Leader != 0) { zgm.CreateGuild(this, Leader, sep->argplus[3], guilddbid); } } } else if (strcasecmp(sep->arg[1], "delete") == 0 && admin >= 100) { if (!sep->IsNumber(2)) { Message(BLACK, "Usage: #guild delete guildDBID"); } else if (!worldserver.Connected()) { Message(BLACK, "Error: World server dirconnected"); } else { int32 tmpeq = Database::Instance()->GetGuildEQID(atoi(sep->arg[2])); char tmpname[32]; if (tmpeq != 0xFFFFFFFF) { strcpy(tmpname, guilds[tmpeq].name); } if (!Database::Instance()->DeleteGuild(atoi(sep->arg[2]))) { Message(BLACK, "Guild delete failed."); } else { if (tmpeq != 0xFFFFFFFF) { zgm.LoadGuilds(); ServerPacket* pack = new ServerPacket(ServerOP_RefreshGuild, 5); pack->pBuffer = new uchar[pack->size]; memcpy(pack->pBuffer, &tmpeq, 4); pack->pBuffer[4] = 1; worldserver.SendPacket(pack); safe_delete(pack);//delete pack; Message(BLACK, "Guild deleted: DB# %i, EQ# %i: %s", atoi(sep->arg[2]), tmpeq, tmpname); } else { Message(BLACK, "Guild deleted: DB# %i", atoi(sep->arg[2])); } } } } else if (strcasecmp(sep->arg[1], "rename") == 0 && admin >= 100) { if ((!sep->IsNumber(2)) || sep->arg[3][0] == 0) { Message(BLACK, "Usage: #guild rename guildDBID newname"); } else if (!worldserver.Connected()) { Message(BLACK, "Error: World server dirconnected"); } else { int32 tmpeq = Database::Instance()->GetGuildEQID(atoi(sep->arg[2])); char tmpname[32]; if (tmpeq != 0xFFFFFFFF) { strcpy(tmpname, guilds[tmpeq].name); } if (!Database::Instance()->RenameGuild(atoi(sep->arg[2]), sep->argplus[3])) { Message(BLACK, "Guild rename failed."); } else { if (tmpeq != 0xFFFFFFFF) { ServerPacket* pack = new ServerPacket(ServerOP_RefreshGuild, 5); pack->pBuffer = new uchar[pack->size]; memcpy(pack->pBuffer, &tmpeq, 4); pack->pBuffer[4] = 1; worldserver.SendPacket(pack); safe_delete(pack);//delete pack; Message(BLACK, "Guild renamed: DB# %i, EQ# %i, OldName: %s, NewName: %s", atoi(sep->arg[2]), tmpeq, tmpname, sep->argplus[3]); } else { Message(BLACK, "Guild renamed: DB# %i, NewName: %s", atoi(sep->arg[2]), sep->argplus[3]); } } } } else if (strcasecmp(sep->arg[1], "setleader") == 0 && admin >= 100) { if (sep->arg[3][0] == 0 || !sep->IsNumber(2)) { Message(BLACK, "Usage: #guild setleader guilddbid {guildleader charname or AccountID}"); } else if (!worldserver.Connected()) { Message(BLACK, "Error: World server dirconnected"); } else { int32 leader = 0; if (sep->IsNumber(3)) { leader = atoi(sep->arg[3]); } else { leader = Database::Instance()->GetAccountIDByChar(sep->argplus[3]); } int32 tmpdb = Database::Instance()->GetGuildDBIDbyLeader(leader); if (leader == 0) { Message(BLACK, "New leader not found."); } else if (tmpdb != 0) { int32 tmpeq = Database::Instance()->GetGuildEQID(tmpdb); if (tmpeq >= 512) { Message(BLACK, "Error: %s already is the leader of DB# %i.", sep->argplus[3], tmpdb); } else { Message(BLACK, "Error: %s already is the leader of DB# %i <%s>.", sep->argplus[3], tmpdb, guilds[tmpeq].name); } } else { int32 tmpeq = Database::Instance()->GetGuildEQID(atoi(sep->arg[2])); if (tmpeq == 0xFFFFFFFF) { Message(BLACK, "Guild not found."); } else if (!Database::Instance()->SetGuildLeader(atoi(sep->arg[2]), leader)) { Message(BLACK, "Guild leader change failed."); } else { zgm.SendGuildRefreshPacket(tmpeq); Message(BLACK, "Guild leader changed: DB# %s, Leader: %s, Name: <%s>", sep->arg[2], sep->argplus[3], guilds[tmpeq].name); } } } } else if (strcasecmp(sep->arg[1], "list") == 0 && admin >= 100) { int x = 0; Message(BLACK, "Listing guilds on the server:"); char leadername[32]; int magicnumber = 512; zgm.LoadGuilds(); guilds = zgm.GetGuildList(); for (int i = 0; i < magicnumber; i++) { if (guilds[i].databaseID != 0) { leadername[0] = 0; Database::Instance()->GetAccountName(guilds[i].leader, leadername); if (leadername[0] == 0) { Message(BLACK, " DB# %i EQ# %i <%s>", guilds[i].databaseID, i, guilds[i].name); } else { Message(BLACK, " DB# %i EQ# %i <%s> Leader: %s", guilds[i].databaseID, i, guilds[i].name, leadername); } x++; } } Message(BLACK, "%i guilds listed.", x); } else if (strcasecmp(sep->arg[1], "reload") == 0 && admin >= 100) { Message(BLACK, "Reloading Guilds"); int32 eqdbid = atoi(sep->arg[2]); zgm.LoadGuilds(); zgm.SendGuildRefreshPacket(eqdbid); } else { Message(BLACK, "Unknown guild command, try #guild help"); } }
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; }