Beispiel #1
0
void DayWatcherThread::load_settings()
{
    std::string arena_timeout = worldConfig.period.arenaUpdate;
    arena_period = get_timeout_from_string(arena_timeout.c_str(), WEEKLY);

    QueryResult* result = CharacterDatabase.Query("SELECT setting_value FROM server_settings WHERE setting_id = \'last_arena_update_time\'");
    if (result)
    {
        last_arena_time = result->Fetch()[0].GetUInt32();
        delete result;
    }
    else
    {
        LogNotice("DayWatcherThread : Initializing Arena Updates to zero.");
        last_arena_time = 0;
    }

    std::string daily_timeout = worldConfig.period.dailyUpdate;
    daily_period = get_timeout_from_string(daily_timeout.c_str(), DAILY);

    QueryResult* result2 = CharacterDatabase.Query("SELECT setting_value FROM server_settings WHERE setting_id = \'last_daily_update_time\'");
    if (result2)
    {
        last_daily_time = result2->Fetch()[0].GetUInt32();
        delete result2;
    }
    else
    {
        LogNotice("DayWatcherThread : Initializing Daily Updates to zero.");
        last_daily_time = 0;
    }
}
Beispiel #2
0
void Master::ShutdownLootSystem()
{
    LogNotice("Shutdown : Initiated at %s", Util::GetDateTimeStringFromTimeStamp((uint32)UNIXTIME).c_str());

    if (lootmgr.is_loading)
    {
        LogNotice("Shutdown : Waiting for loot to finish loading...");
        while (lootmgr.is_loading)
            Arcemu::Sleep(100);
    }
}
Beispiel #3
0
void Master::StartRemoteConsole()
{
    LogNotice("RemoteConsole : Starting...");
    if (StartConsoleListener())
    {
#ifdef WIN32
        ThreadPool.ExecuteTask(GetConsoleListener());
#endif
        LogNotice("RemoteConsole : Now open.");
    }
    else
    {
        LogWarning("RemoteConsole : Not enabled or failed listen.");
    }
}
Beispiel #4
0
void ConsoleSocket::getConsoleAuthResult(bool result)
{
    sConsoleAuthMgr.addRequestIdSocket(mRequestId, nullptr);
    mRequestId = 0;

    if (result == false)
    {
        mRemoteConsole->Write("Authentication failed.\r\n\r\n");
        mFailedLoginCount++;
        if (mFailedLoginCount < 3)
        {
            mRemoteConsole->Write("login: "******"User `%s` authenticated.\r\n\r\n", mConsoleAuthName.c_str());
        LogNotice("RemoteConsole : User `%s` authenticated.", mConsoleAuthName.c_str());
        const char* argv[1];
        //handServerleInfoCommand(mRemoteConsole, 1, "");
        mRemoteConsole->Write("Type ? to see commands, quit to end session.\r\n");
        mConsoleSocketState = ConsoleDefines::RemoteConsoleState::UserLoggedIn;
    }
}
Beispiel #5
0
bool Master::LoadWorldConfiguration(char* config_file)
{
    LogNotice("Config : Loading Config Files...");
    if (Config.MainConfig.openAndLoadConfigFile(config_file))
    {
        LogDetail("Config : " CONFDIR "/world.conf loaded");
    }
    else
    {
        LogError("Config : error occurred loading " CONFDIR "/world.conf");
        AscLog.~AscEmuLog();
        return false;
    }

#if !defined(WIN32) && defined(__DEBUG__)
    if (Config.MainConfig.GetIntDefault("LogLevel", "DisableCrashdumpReport", 0) == 0)
    {
        char cmd[1024];
        char banner[1024];
        snprintf(banner, 1024, BANNER, BUILD_TAG, BUILD_REVISION, CONFIG, PLATFORM_TEXT, ARCH);
        snprintf(cmd, 1024, "./crashreport -r %d -d \'%s\'", BUILD_REVISION, banner);
        system(cmd);
    }
    unlink("worldserver.uptime");
#endif
    return true;
}
Beispiel #6
0
void DayWatcherThread::update_daily()
{
    LogNotice("DayWatcherThread : Running Daily Quest Reset...");
    CharacterDatabase.WaitExecute("UPDATE characters SET finisheddailies = ''");
    CharacterDatabase.WaitExecute("UPDATE characters SET rbg_daily = '0'");     // Reset RBG
    objmgr.ResetDailies();
    last_daily_time = UNIXTIME;
    dupe_tm_pointer(localtime(&last_daily_time), &local_last_daily_time);
    m_dirty = true;
}
Beispiel #7
0
void BalanccClient::Connected( int client )
{
  LogNotice( "connected to server" );
  char buf[128];
  snprintf( buf, sizeof( buf ), "host %s %d %f %d\n", hostname, ncpu, loadlimit, slots );
  if( !Send( buf, strlen( buf )))
  {
    LogError( "error sending hostname" );
  }
  SendLoad( );
}
Beispiel #8
0
void ConsoleSocket::closeRemoteConnection()
{
    if (mRequestId != 0)
    {
        sConsoleAuthMgr.addRequestIdSocket(mRequestId, nullptr);
        mRequestId = 0;
    }

    if (mConsoleSocketState == ConsoleDefines::RemoteConsoleState::UserLoggedIn)
    {
        LogNotice("RemoteConsole : User `%s` disconnected.", mConsoleAuthName.c_str());
    }
}
Beispiel #9
0
void WorldPacketLog::initWorldPacketLog(bool enableLog)
{
    isLogEnabled = enableLog;

    if (isLogEnabled)
    {
        LogNotice("WorldPacketLog : Enabling packetlog output to \"world-packet.log\"");
        enablePacketLog();
    }
    else
    {
        disablePacketLog();
    }
}
Beispiel #10
0
// Crash Handler
void OnCrash(bool Terminate)
{
    LogError("Crash Handler : Advanced crash handler initialized.");

    if (!m_crashedMutex.AttemptAcquire())
        TerminateThread(GetCurrentThread(), 0);

    try
    {
        if (World::getSingletonPtr() != 0)
        {
            LogNotice("sql : Waiting for all database queries to finish...");
            WorldDatabase.EndThreads();
            CharacterDatabase.EndThreads();
            LogNotice("sql : All pending database operations cleared.");
            sWorld.saveAllPlayersToDb();
            LogNotice("sql : Data saved.");
        }
    }
    catch (...)
    {
        LogError("sql : Threw an exception while attempting to save all data.");
    }

    LogNotice("Server : Closing.");

    // beep
    //printf("\x7");

    // Terminate Entire Application
    if (Terminate)
    {
        HANDLE pH = OpenProcess(PROCESS_TERMINATE, TRUE, GetCurrentProcessId());
        TerminateProcess(pH, 1);
        CloseHandle(pH);
    }
}
Beispiel #11
0
MapMgr* InstanceMgr::_CreateInstance(Instance* in)
{
    if (m_maps[in->m_mapId] == 0)
        return NULL;

    LogNotice("InstanceMgr : Creating saved instance %u (%s)", in->m_instanceId, m_maps[in->m_mapId]->GetMapName().c_str());
    ARCEMU_ASSERT(in->m_mapMgr == NULL);

    // we don't have to check for world map info here, since the instance wouldn't have been saved if it didn't have any.
    in->m_mapMgr = new MapMgr(m_maps[in->m_mapId], in->m_mapId, in->m_instanceId);
    in->m_mapMgr->pInstance = in;
    in->m_mapMgr->iInstanceMode = in->m_difficulty;
    in->m_mapMgr->InactiveMoveTime = 60 + UNIXTIME;

    ThreadPool.ExecuteTask(in->m_mapMgr);
    return in->m_mapMgr;
}
Beispiel #12
0
bool MySQLDatabase::Initialize(const char* Hostname, unsigned int port, const char* Username, const char* Password, const char* DatabaseName, uint32 ConnectionCount, uint32 /*BufferSize*/)
{
    uint32 i;
    MYSQL* temp = NULL;
    MYSQL* temp2 = NULL;
    MySQLDatabaseConnection** conns;
    my_bool my_true = true;

    mHostname = std::string(Hostname);
    mConnectionCount = ConnectionCount;
    mUsername = std::string(Username);
    mPassword = std::string(Password);
    mDatabaseName = std::string(DatabaseName);

    LogNotice("MySQLDatabase : Connecting to `%s`, database `%s`...", Hostname, DatabaseName);

    conns = new MySQLDatabaseConnection*[ConnectionCount];
    Connections = ((DatabaseConnection**)conns);
    for(i = 0; i < ConnectionCount; ++i)
    {
        temp = mysql_init(NULL);
        if(temp == NULL)
            continue;

        if(mysql_options(temp, MYSQL_SET_CHARSET_NAME, "utf8"))
            LOG_ERROR("Could not set utf8 character set.");

        if(mysql_options(temp, MYSQL_OPT_RECONNECT, &my_true))
            LOG_ERROR("MYSQL_OPT_RECONNECT could not be set, connection drops may occur but will be counteracted.");

        temp2 = mysql_real_connect(temp, Hostname, Username, Password, DatabaseName, port, NULL, 0);
        if(temp2 == NULL)
        {
            LOG_ERROR("Connection failed due to: `%s`", mysql_error(temp));
            mysql_close(temp);
            return false;
        }

        conns[i] = new MySQLDatabaseConnection;
        conns[i]->MySql = temp2;
    }

    Database::_Initialize();
    return true;
}
VidscaleSHMIntf::VidscaleSHMIntf()
{
    m_numOfRabObjs = NUM_RAB_OBJECTS;
    LogNotice("\nmax sessions supported = %u\n",
                m_numOfRabObjs);

    sm_firstTunnelStrideSize   = sizeof(FirstStrideBlock);
    sm_numSecondStride         = NUM_TUN_SECOND_STRIDES ;
    sm_secondStrideSize        = (sizeof(SHM_Hash_Table)*sm_numSecondStride);

    //First stride holds structure that points to Hash Tables(Second Strides)
    sm_firstTunnelStrideOffset = SHM_INFO_SIZE;

    //Hash Tables (Second Strides) points to Hash Objects ()
    sm_secondStrideOffset      = SHM_INFO_SIZE + sizeof(FirstStrideBlock);

    sm_rabObjOffset   = sm_secondStrideOffset + sm_secondStrideSize;
    m_rabObjsSize     = (sizeof(umtsRab)*m_numOfRabObjs);
    LogNotice("size of m_rabObjsSize %u\n", ((m_rabObjsSize/8)/1024));

    //Hash Objects points to Hash Entries (UumtsRab entry here)
    m_hashObjsOffset = sm_rabObjOffset + m_rabObjsSize;
    m_numHashObjs = 2*m_numOfRabObjs; //Single Rab objects can be looked by two keys uplink/downlink 
    m_hashObjsSize = sizeof(SHM_Hash_Entry)*((2*m_numOfRabObjs));
    LogNotice("size of m_hashObjsSize %u\n", ((m_hashObjsSize /8)/1024));



    LogNotice("size of sm_firstTunnelStrideSize %u\n", ((sm_firstTunnelStrideSize /8)/1024));
    LogNotice("size of sm_secondStrideSize %u\n", ((sm_secondStrideSize /8)/1024));

    m_sessionShmSize = SHM_INFO_SIZE +
      sm_firstTunnelStrideSize +
      sm_secondStrideSize +
      m_rabObjsSize +
      m_hashObjsSize;

    LogNotice("size of m_sessionShmSize %u\n", ((m_sessionShmSize /8)/1024));
    pthread_mutexattr_t attributes ;
    pthread_mutexattr_init(&attributes);
    /*
       This type of mutex provides error checking. A thread attempting to relock this mutex without first unlocking it shall return with an error. A thread attempting to unlock a mutex which another thread has locked shall return with an error. A thread attempting to unlock an unlocked mutex shall return with an error. 
     */
    pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_ERRORCHECK);

    if(pthread_mutex_init(&m_shmUpdateLock, &attributes)!= 0)
    {
      perror(__FILE__ "pthread_mutex_init :: shmUpdateLock");
      return;
    }
}
Beispiel #14
0
MapMgr* InstanceMgr::_CreateInstance(uint32 mapid, uint32 instanceid)
{
    MapInfo const* inf = sMySQLStore.GetWorldMapInfo(mapid);

    ARCEMU_ASSERT(inf != nullptr && inf->type == INSTANCE_NULL);
    ARCEMU_ASSERT(mapid < NUM_MAPS && m_maps[mapid] != NULL);

    LogNotice("InstanceMgr : Creating continent %s.", m_maps[mapid]->GetMapName().c_str());

    MapMgr* newMap = new MapMgr(m_maps[mapid], mapid, instanceid);

    ARCEMU_ASSERT(newMap != NULL);

    // Scheduling the new map for running
    ThreadPool.ExecuteTask(newMap);
    m_singleMaps[mapid] = newMap;

    return newMap;
}
Beispiel #15
0
void DatabaseCleaner::Run()
{
    LogNotice("DatabaseCleaner : Cleaning characters...");
    CleanCharacters();
}
Beispiel #16
0
/**
 * @attention this function may rewrite yenmacfg
 */
bool
YenmaContext_buildPolicies(YenmaContext *self, YenmaConfig *yenmacfg)
{
    // Resolver
    DnsResolver_initializer *initializer = DnsResolver_lookupInitializer(yenmacfg->resolver_engine);
    if (NULL == initializer) {
        LogError("failed to load resolver module: resolver=%s",
                 PTROR(yenmacfg->resolver_engine, "any"));
        return false;
    }   // end if
    self->resolver_pool =
        ResolverPool_new(initializer, yenmacfg->resolver_conf, yenmacfg->resolver_pool_size,
                         (int) yenmacfg->resolver_timeout, (int) yenmacfg->resolver_retry_count);
    if (NULL == self->resolver_pool) {
        LogNoResource();
        return false;
    }   // end if

    // DMARC setup
    if (yenmacfg->dmarc_verify) {
        // enable SPF and DKIM
        if (!yenmacfg->spf_verify) {
            yenmacfg->spf_verify = true;
            LogNotice("SPF verification is turned on as a part of DMARC verification");
        }   // end if
        if (!yenmacfg->dkim_verify) {
            yenmacfg->dkim_verify = true;
            LogNotice("DKIM verification is turned on as a part of DMARC verification");
        }   // end if

        // load public suffix list
        if (NULL == yenmacfg->dmarc_public_suffix_list) {
            LogError("Public Suffix List must be specified for DMARC verification");
            return false;
        }   // end if
        if (DSTAT_OK !=
            PublicSuffix_build(yenmacfg->dmarc_public_suffix_list, &self->public_suffix)) {
            LogError("failed to load public suffix list: filename=%s",
                     yenmacfg->dmarc_public_suffix_list);
            return false;
        }   // end if

        // check SMTP reject actions
        self->dmarc_reject_action = YenmaConfig_lookupSmtpRejectActionByKeyword(yenmacfg->dmarc_reject_action);
        if (0 > self->dmarc_reject_action) {
            LogError("invalid SMTP action for DMARC reject: action=%s", yenmacfg->dmarc_reject_action);
            return false;
        } else if (SMFIS_REJECT == self->dmarc_reject_action && (notstartwith(yenmacfg->dmarc_reject_reply_code, '5') || notstartwith(yenmacfg->dmarc_reject_enhanced_status_code, '5'))) {
            LogError("invalid SMTP reply code or enhanced status code  for DMARC reject action: reply_code=%s, ehanced_status_code=%s", NNSTR(yenmacfg->dmarc_reject_reply_code), NNSTR(yenmacfg->dmarc_reject_enhanced_status_code));
            return false;
        } else if (SMFIS_TEMPFAIL == self->dmarc_reject_action && (notstartwith(yenmacfg->dmarc_reject_reply_code, '4') || notstartwith(yenmacfg->dmarc_reject_enhanced_status_code, '4'))) {
            LogError("invalid SMTP reply code or enhanced status code  for DMARC tempfail action: reply_code=%s, ehanced_status_code=%s", NNSTR(yenmacfg->dmarc_reject_reply_code), NNSTR(yenmacfg->dmarc_reject_enhanced_status_code));
            return false;
        }   // end if
    }   // end if

    if (yenmacfg->dkim_adsp_verify && !yenmacfg->dkim_verify) {
        yenmacfg->dkim_verify = true;
        LogNotice("DKIM verification is turned on as a part of DKIM-ADSP verification");
    }   // end if

    // building DkimVerificationPolicy
    if (yenmacfg->dkim_verify) {
        DkimStatus config_stat =
            YenmaConfig_buildDkimVerificationPolicy(yenmacfg, &self->dkim_vpolicy);
        if (DSTAT_OK != config_stat) {
            return false;
        }   // end if
    }   // end if

    // building SpfEvalPolicy for SPF (must be after determining authserv-id)
    if (yenmacfg->spf_verify) {
        self->spfevalpolicy = YenmaConfig_buildSpfEvalPolicy(yenmacfg);
        if (NULL == self->spfevalpolicy) {
            return false;
        }   // end if
    }   // end if

    // building SpfEvalPolicy for SIDF (must be after determining authserv-id)
    if (yenmacfg->sidf_verify) {
        self->sidfevalpolicy = YenmaConfig_buildSidfEvalPolicy(yenmacfg);
        if (NULL == self->sidfevalpolicy) {
            return false;
        }   // end if
    }   // end if

    if (NULL != yenmacfg->service_exclusion_blocks) {
        self->exclusion_block = YenmaConfig_buildExclusionBlock(yenmacfg->service_exclusion_blocks);
        if (NULL == self->exclusion_block) {
            return false;
        }   // end if
    }   // end if

    return true;
}   // end function: YenmaContext_buildPolicies
void VidscaleSHMIntf::Init()
{

    LogNotice("\nInitializing memory\n\n");
    int sharedFd = -1;
    int i;
    int keyIndex;
    int tmpFd;

    //First attempt is to see if a shared memory object already exist
    //If object exist unlink that memory so that it can be freed
    // We should close the shm FD after we are through with it.
    // note that an FD does not need to stay open after mmap().
    for(i = 0; i<MAX_SHM_KEYS; i++)
    {
      tmpFd = shm_open(sharedMemKey[i], O_RDWR, S_IRUSR | S_IWUSR);
      if (tmpFd != -1)
      {
        shm_unlink(sharedMemKey[i]);
        close(tmpFd); // close the FD so that we are not holding the old SHM filesystem space
        LogNotice("\n2:Initializing memory\n\n");
      }

      LogNotice("\n3:Initializing memory\n\n");
      if ((sharedFd = shm_open(sharedMemKey[i], 
                               O_RDWR|O_CREAT, S_IRUSR | S_IWUSR)) == -1)
      {
        LogError("Not able to initialize shared memory \n");
        return;   /*should we exit or fall back to normal way ?*/
      }
      else
      { 
        keyIndex = i;
        LogError("Openeing shared memory key(%s) \n", sharedMemKey[keyIndex]);
      }
      LogNotice("\n4:Initializing memory-- size %u\n\n", ((m_sessionShmSize / 8)/ 1024));
    }
    
    if (ftruncate(sharedFd, m_sessionShmSize) == -1)
    {
      LogError("ftruncate failed \n");
      close(sharedFd); // tidy up
      return;
    }

    if ((m_sharedBase = mmap(NULL, m_sessionShmSize, PROT_WRITE | PROT_READ, 
                             MAP_SHARED|MAP_NORESERVE|MAP_LOCKED|MAP_POPULATE , sharedFd, 0)) == (char *)-1) {
      LogError("unable to map the required shared memory \n");
      close(sharedFd); // tidy up
      return;
    }
    else
    {
      LogNotice("MMAP is successful \n\n");
    }

    close(sharedFd); // no more use for FD, so close it

    memset(m_sharedBase, 0, m_sessionShmSize);

    LogNotice("MEMSET is successful \n\n");

    setSessionShmGlobalKey(sharedMemKey[keyIndex]);

    //Set the version of the shared memory
    ShmInfo shmInfo;
    shmInfo.shmVersion = SHM_VERSION;
    memcpy(m_sharedBase, &shmInfo, sizeof(ShmInfo));

   // divideAndInitSharedMemory();
    return;
}
Beispiel #18
0
bool Master::_CheckDBVersion()
{
    QueryResult* wqr = WorldDatabase.QueryNA("SELECT LastUpdate FROM world_db_version ORDER BY id DESC LIMIT 1;");
    if (wqr == NULL)
    {
        LogError("Database : World database is missing the table `world_db_version` OR the table doesn't contain any rows. Can't validate database version. Exiting.");
        LogError("Database : You may need to update your database");
        return false;
    }

    Field* f = wqr->Fetch();
    const char *WorldDBVersion = f->GetString();

    LogNotice("Database : Last world database update: %s", WorldDBVersion);
    int result = strcmp(WorldDBVersion, REQUIRED_WORLD_DB_VERSION);
    if (result != 0)
    {
        LogError("Database : Last world database update doesn't match the required one which is %s.", REQUIRED_WORLD_DB_VERSION);

        if (result < 0)
        {
            LogError("Database : You need to apply the world update queries that are newer than %s. Exiting.", WorldDBVersion);
            LogError("Database : You can find the world update queries in the sql/world_updates sub-directory of your AscEmu source directory.");
        }
        else
        {
            LogError("Database : Your world database is probably too new for this AscEmu version, you need to update your server. Exiting.");
        }

        delete wqr;
        return false;
    }

    delete wqr;

    QueryResult* cqr = CharacterDatabase.QueryNA("SELECT LastUpdate FROM character_db_version;");
    if (cqr == NULL)
    {
        LogError("Database : Character database is missing the table `character_db_version` OR the table doesn't contain any rows. Can't validate database version. Exiting.");
        LogError("Database : You may need to update your database");
        return false;
    }

    f = cqr->Fetch();
    const char *CharDBVersion = f->GetString();

    LogNotice("Database : Last character database update: %s", CharDBVersion);
    result = strcmp(CharDBVersion, REQUIRED_CHAR_DB_VERSION);
    if (result != 0)
    {
        LogError("Database : Last character database update doesn't match the required one which is %s.", REQUIRED_CHAR_DB_VERSION);
        if (result < 0)
        {
            LogError("Database : You need to apply the character update queries that are newer than %s. Exiting.", CharDBVersion);
            LogError("Database : You can find the character update queries in the sql/character_updates sub-directory of your AscEmu source directory.");
        }
        else
        LogError("Database : Your character database is too new for this AscEmu version, you need to update your server. Exiting.");

        delete cqr;
        return false;
    }

    delete cqr;

    LogDetail("Database : Database successfully validated.");

    return true;
}
Beispiel #19
0
void BalanccClient::Disconnected( int client, bool error )
{
  LogNotice( "connection to server lost" );
}
Beispiel #20
0
void ObjectMgr::LoadTransports()
{
    LogNotice("TransportHandler : Start creating transports...");
    {
        uint32_t createCount = 0;

        for (auto it : sMySQLStore._transportDataStore)
        {
            GameObjectProperties const* gameobject_info = sMySQLStore.getGameObjectProperties(it.first);

            std::set<uint32> mapsUsed;

            Transporter* pTransporter = new Transporter((uint64)HIGHGUID_TYPE_TRANSPORTER << 32 | it.first);

            if (pTransporter->GenerateWaypoints(gameobject_info->mo_transport.taxi_path_id) == false)
            {
                LOG_ERROR("Transport entry: %u, failed to create waypoints", it.first);
                delete pTransporter;
                continue;
            }

            if (pTransporter->Create(it.first, it.second.period) == false)
            {
                delete pTransporter;
                continue;
            }

            pTransporter->AddToWorld();

            m_Transporters.insert(pTransporter);
            AddTransport(pTransporter);

            for (std::set<uint32>::const_iterator i = mapsUsed.begin(); i != mapsUsed.end(); ++i)
            {
                m_TransportersByMap[*i].insert(pTransporter);
            }

            ++createCount;
        }

        LogDetail("Transporter Handler : Created %u transports", createCount);
    }

    LogNotice("TransportHandler : Start populating transports with creatures...");
    {
        for (auto it : sMySQLStore._transportCreaturesStore)
        {
            for (ObjectMgr::TransporterSet::iterator itr = m_Transporters.begin(); itr != m_Transporters.end(); ++itr)
            {
                if ((*itr)->getEntry() == it.second.transportEntry)
                {
                    TransportSpawn spawn{ it.second.guid, it.second.entry, it.second.transportEntry, it.second.transportOffsetX, it.second.transportOffsetY, it.second.transportOffsetZ, it.second.transportOffsetO, it.second.animation };
                    (*itr)->AddCreature(spawn);
                    break;
                }
            }
        }

        for (auto transport : m_Transporters)
        {
            transport->RespawnCreaturePassengers();
        }
    }
}
Beispiel #21
0
void Master::ShutdownThreadPools(bool listnersockcreate)
{
    uint32 loopcounter = 0;
    auto last_time = Util::TimeNow();
    uint32 next_printout = Util::getMSTime(), next_send = Util::getMSTime();

    while (!m_stopEvent && listnersockcreate)
    {
        auto start = Util::TimeNow();
        auto diff = Util::GetTimeDifference(last_time, start);
        if (!((++loopcounter) % 10000))        // 5mins
        {
            ThreadPool.ShowStats();
            ThreadPool.IntegrityCheck();
#if !defined(WIN32) && defined(__DEBUG__)
            FILE* f = fopen("worldserver.uptime", "w");
            if (f)
            {
                fprintf(f, "%u %u %u %u", sWorld.GetUptime(), sWorld.GetSessionCount(), sWorld.getPeakSessionCount(), sWorld.getAcceptedConnections());
                fclose(f);
            }
#endif
        }

        /* since time() is an expensive system call, we only update it once per server loop */
        time_t curTime = time(nullptr);
        if (UNIXTIME != curTime)
        {
            UNIXTIME = time(nullptr);
            g_localTime = *localtime(&curTime);
        }

        sSocketGarbageCollector.Update();

        /* UPDATE */
        last_time = Util::TimeNow();
        auto etime = Util::GetTimeDifference(start, last_time);
        if (m_ShutdownEvent)
        {
            if (Util::getMSTime() >= next_printout)
            {
                if (m_ShutdownTimer > 60000.0f)
                {
                    if (!(static_cast<int>(m_ShutdownTimer) % 60000))
                    LogNotice("Server : Shutdown in %i minutes.", static_cast<int>(m_ShutdownTimer / 60000.0f));
                }
                else
                LogNotice("Server : Shutdown in %i seconds.", static_cast<int>(m_ShutdownTimer / 1000.0f));

                next_printout = Util::getMSTime() + 500;
            }

            if (Util::getMSTime() >= next_send)
            {
                int time = m_ShutdownTimer / 1000;
                if ((time % 30 == 0) || time < 10)
                {
                    // broadcast packet.
                    WorldPacket data(20);
                    data.SetOpcode(SMSG_SERVER_MESSAGE);
                    if (m_restartEvent)
                        data << uint32(SERVER_MSG_RESTART_TIME);
                    else
                        data << uint32(SERVER_MSG_SHUTDOWN_TIME);

                    if (time > 0)
                    {
                        int mins = 0, secs = 0;
                        if (time > 60)
                            mins = time / 60;
                        if (mins)
                            time -= (mins * 60);
                        secs = time;
                        char str[20];
                        snprintf(str, 20, "%02u:%02u", mins, secs);
                        data << str;
                        sWorld.sendGlobalMessage(&data);
                    }
                }
                next_send = Util::getMSTime() + 1000;
            }
            if (diff >= m_ShutdownTimer)
                break;
            else
                m_ShutdownTimer -= static_cast<uint32>(diff);
        }

        if (50 > etime)
        {

            Arcemu::Sleep(static_cast<unsigned long>(50 - etime));

        }
    }
}
Beispiel #22
0
void Master::StartNetworkSubsystem()
{
    LogNotice("Network : Starting subsystem...");
    new SocketMgr;
    new SocketGarbageCollector;
}
Beispiel #23
0
void DayWatcherThread::update_arena()
{
    LogNotice("DayWatcherThread : Running Weekly Arena Point Maintenance...");
    QueryResult* result = CharacterDatabase.Query("SELECT guid, arenaPoints FROM characters");  // this one is a little more intensive
    Player* plr;
    uint32 guid, arenapoints, orig_arenapoints;
    ArenaTeam* team;
    uint32 arenapointsPerTeam[3] = { 0 };
    double X, Y;
    if (result)
    {
        do
        {
            Field* f = result->Fetch();
            guid = f[0].GetUInt32();
            arenapoints = f[1].GetUInt32();
            orig_arenapoints = arenapoints;

            for (uint8 i = 0; i < 3; ++i)
                arenapointsPerTeam[i] = 0;

            // are we in any arena teams?
            for (uint8 i = 0; i < 3; ++i)            // 3 arena team types
            {
                team = objmgr.GetArenaTeamByGuid(guid, i);
                if (team)
                {
                    ArenaTeamMember* member = team->GetMemberByGuid(guid);
                    if (member == NULL || team->m_stat_gamesplayedweek < 10 || ((member->Played_ThisWeek * 100) / team->m_stat_gamesplayedweek < 30))
                        continue;

                    // we're in an arena team of this type!
                    // Source: http://www.wowwiki.com/Arena_point
                    X = (double)team->m_stat_rating;
                    if (X <= 510.0)    // "if X<=510"
                        continue;        // no change
                    else if (X > 510.0 && X <= 1500.0)        // "if 510 < X <= 1500"
                    {
                        Y = (0.22 * X) + 14.0;
                    }
                    else            // "if X > 1500"
                    {
                        // http://eu.wowarmory.com/arena-calculator.xml
                        //              1511.26
                        //   ---------------------------
                        //                   -0.00412*X
                        //    1+1639.28*2.71828

                        double power = ((-0.00412) * X);
                        //if (power < 1.0)
                        //    power = 1.0;

                        double divisor = pow(((double)(2.71828)), power);
                        divisor *= 1639.28;
                        divisor += 1.0;
                        //if (divisor < 1.0)
                        //    divisor = 1.0;

                        Y = 1511.26 / divisor;
                    }

                    // 2v2 teams only earn 70% (Was 60% until 13th March 07) of the arena points, 3v3 teams get 80%, while 5v5 teams get 100% of the arena points.
                    // 2v2 - 76%, 3v3 - 88% as of patch 2.2
                    if (team->m_type == ARENA_TEAM_TYPE_2V2)
                    {
                        Y *= 0.76;
                        Y *= worldConfig.getFloatRate(RATE_ARENAPOINTMULTIPLIER2X);
                    }
                    else if (team->m_type == ARENA_TEAM_TYPE_3V3)
                    {
                        Y *= 0.88;
                        Y *= worldConfig.getFloatRate(RATE_ARENAPOINTMULTIPLIER3X);
                    }
                    else
                    {
                        Y *= worldConfig.getFloatRate(RATE_ARENAPOINTMULTIPLIER5X);
                    }

                    if (Y > 1.0)
                        arenapointsPerTeam[i] += long2int32(double(ceil(Y)));
                }
            }

            arenapointsPerTeam[0] = (uint32)std::max(arenapointsPerTeam[0], arenapointsPerTeam[1]);
            arenapoints += (uint32)std::max(arenapointsPerTeam[0], arenapointsPerTeam[2]);
            if (arenapoints > 5000) arenapoints = 5000;

            if (orig_arenapoints != arenapoints)
            {
                plr = objmgr.GetPlayer(guid);
                if (plr)
                {
                    plr->AddArenaPoints(arenapoints, false);

                    // update visible fields (must be done through an event because of no uint lock
                    sEventMgr.AddEvent(plr, &Player::UpdateArenaPoints, EVENT_PLAYER_UPDATE, 100, 1, 0);

                    sChatHandler.SystemMessage(plr->GetSession(), "Your arena points have been updated! Check your PvP tab!");
                }

                // update in sql
                CharacterDatabase.Execute("UPDATE characters SET arenaPoints = %u WHERE guid = %u", arenapoints, guid);
            }
        }
        while (result->NextRow());
        delete result;
    }

    objmgr.UpdateArenaTeamWeekly();

    last_arena_time = UNIXTIME;
    dupe_tm_pointer(localtime(&last_arena_time), &local_last_arena_time);
    m_dirty = true;
}
Beispiel #24
0
void DatabaseCleaner::CleanCharacters()
{
    std::set<uint32> chr_guids;
    std::set<uint32> chr_guilds;
    std::set<uint32> chr_charters;
    LogNotice("DatabaseCleaner : Loading guids...");

    QueryResult* result = CharacterDatabase.Query("SELECT guid, guildid, charterId FROM characters");
    if (result)
    {
        do
        {
            chr_guids.insert(result->Fetch()[0].GetUInt32());
            if (result->Fetch()[1].GetUInt32() != 0)
                chr_guilds.insert(result->Fetch()[1].GetUInt32());
            if (result->Fetch()[2].GetUInt32() != 0)
                chr_guilds.insert(result->Fetch()[2].GetUInt32());
        }
        while (result->NextRow());
        delete result;
    }
    LogNotice("DatabaseCleaner : Got %u guids.", chr_guids.size());
    LogNotice("DatabaseCleaner : Cleaning playeritems...");

    result = CharacterDatabase.Query("SELECT ownerguid, guid FROM playeritems");
    std::vector<uint64> tokill_items;
    if (result)
    {
        do
        {
            if (result->Fetch()[0].GetUInt32() != 0 && chr_guids.find(result->Fetch()[0].GetUInt32()) == chr_guids.end())
            {
                tokill_items.push_back(result->Fetch()[1].GetUInt64());
            }
        }
        while (result->NextRow());
        delete result;
    }

    for (std::vector<uint64>::iterator itr = tokill_items.begin(); itr != tokill_items.end(); ++itr)
    {
        CharacterDatabase.WaitExecute("DELETE FROM playeritems WHERE guid = " I64FMTD, *itr);
    }

    LogNotice("DatabaseCleaner : Deleted %u item instances.", tokill_items.size());
    LogNotice("DatabaseCleaner : Cleaning questlog...");

    result = CharacterDatabase.Query("SELECT index, player_guid FROM questlog");
    std::vector<uint32> tokill_quests;
    if (result)
    {
        do
        {
            if (chr_guids.find(result->Fetch()[1].GetUInt32()) == chr_guids.end())
                tokill_quests.push_back(result->Fetch()[0].GetUInt32());
        }
        while (result->NextRow());
        delete result;
    }

    for (std::vector<uint32>::iterator itr = tokill_quests.begin(); itr != tokill_quests.end(); ++itr)
        CharacterDatabase.WaitExecute("DELETE FROM questlog WHERE index = %u", *itr);

    LogNotice("DatabaseCleaner : Deleted %u questlog entries.", tokill_quests.size());
    LogNotice("DatabaseCleaner : Cleaning corpses...");

    std::vector<uint32> tokill_corpses;
    result = CharacterDatabase.Query("SELECT * FROM corpses");
    if (result)
    {
        do
        {
            Corpse* pCorpse = new Corpse(0, result->Fetch()[0].GetUInt32());
            pCorpse->LoadValues(result->Fetch()[8].GetString());
            pCorpse->SetLowGUID(0);
            if (pCorpse->GetDisplayId() == 0 || GET_LOWGUID_PART(pCorpse->GetOwner()) == 0 || chr_guids.find(GET_LOWGUID_PART(pCorpse->GetOwner())) == chr_guids.end())
            {
                tokill_corpses.push_back(pCorpse->GetLowGUID());
            }
            delete pCorpse;
        }
        while (result->NextRow());
        delete result;
    }

    for (std::vector<uint32>::iterator itr = tokill_corpses.begin(); itr != tokill_corpses.end(); ++itr)
        CharacterDatabase.WaitExecute("DELETE FROM corpses WHERE guid = %u", *itr);

    LogNotice("DatabaseCleaner : Removed %u corpses.", tokill_corpses.size());
    LogNotice("DatabaseCleaner : Cleaning mailbox...");

    result = CharacterDatabase.Query("SELECT message_id, player_guid FROM mailbox");
    std::vector<uint32> tokill_mail;
    if (result)
    {
        do
        {
            if (chr_guids.find(result->Fetch()[1].GetUInt32()) == chr_guids.end())
                tokill_mail.push_back(result->Fetch()[0].GetUInt32());

        }
        while (result->NextRow());
        delete result;
    }

    for (std::vector<uint32>::iterator itr = tokill_mail.begin(); itr != tokill_mail.end(); ++itr)
        CharacterDatabase.WaitExecute("DELETE FROM mailbox WHERE message_id = %u", *itr);
    LogNotice("DatabaseCleaner : Deleted %u mail messages.", tokill_mail.size());
    LogNotice("DatabaseCleaner : Cleaning guilds table...");

    result = CharacterDatabase.Query("SELECT guildId FROM guilds");
    std::vector<uint32> tokill_guilds;
    if (result)
    {
        do
        {
            if (chr_guilds.find(result->Fetch()[0].GetUInt32()) == chr_guilds.end())
            {
                tokill_guilds.push_back(result->Fetch()[0].GetUInt32());
            }
        }
        while (result->NextRow());
        delete result;
    }

    for (std::vector<uint32>::iterator itr = tokill_guilds.begin(); itr != tokill_guilds.end(); ++itr)
        CharacterDatabase.WaitExecute("DELETE FROM guilds WHERE guildId = %u", *itr);

    LogNotice("DatabaseCleaner : Deleted %u guilds.", tokill_guilds.size());
    LogNotice("DatabaseCleaner : Cleaning guild_ranks table...");

    result = CharacterDatabase.Query("SELECT guildId FROM guild_ranks");
    std::set<uint32> tokill_guildranks;
    if (result)
    {
        do
        {
            if (chr_guilds.find(result->Fetch()[0].GetUInt32()) == chr_guilds.end())
            {
                tokill_guildranks.insert(result->Fetch()[0].GetUInt32());
            }
        }
        while (result->NextRow());
        delete result;
    }
    for (std::set<uint32>::iterator itr = tokill_guildranks.begin(); itr != tokill_guildranks.end(); ++itr)
        CharacterDatabase.WaitExecute("DELETE FROM guild_ranks WHERE guildId = %u", *itr);

    LogNotice("DatabaseCleaner : Deleted %u guild rank rows.", tokill_guildranks.size());
    LogNotice("DatabaseCleaner : Cleaning social table...");

    result = CharacterDatabase.Query("SELECT * FROM social");
    std::vector<std::pair<uint32, uint32> > tokill_social;
    if (result)
    {
        do
        {
            uint32 g1 = result->Fetch()[0].GetUInt32();
            uint32 g2 = result->Fetch()[1].GetUInt32();
            if (chr_guids.find(g1) == chr_guids.end() || chr_guids.find(g2) == chr_guids.end())
            {
                std::pair<uint32, uint32> x;
                x.first = g1;
                x.second = g2;
                tokill_social.push_back(x);
            }
        }
        while (result->NextRow());
        delete result;
    }

    for (std::vector<std::pair<uint32, uint32> >::iterator itr = tokill_social.begin(); itr != tokill_social.end(); ++itr)
    {
        CharacterDatabase.WaitExecute("DELETE FROM social WHERE guid = %u and socialguid = %u", itr->first, itr->second);
    }

    LogNotice("DatabaseCleaner : Deleted %u social entries.", tokill_social.size());
    LogNotice("DatabaseCleaner : Cleaning cooldown tables...");

    std::set<uint32> tokill_cool;
    std::vector<std::pair<uint32, uint32> > tokill_cool2;
    result = CharacterDatabase.Query("SELECT OwnerGuid, CooldownTimeStamp FROM playercooldownitems");
    if (result)
    {
        uint32 t = getMSTime();
        do
        {
            uint32 guid = result->Fetch()[0].GetUInt32();
            uint32 cool = result->Fetch()[1].GetUInt32();
            if (chr_guids.find(guid) == chr_guids.end())
                tokill_cool.insert(guid);
            else if (t >= cool)
                tokill_cool2.push_back(std::make_pair(guid, cool));
        }
        while (result->NextRow());
        delete result;
    }

    for (std::vector<std::pair<uint32, uint32> >::iterator itr = tokill_cool2.begin(); itr != tokill_cool2.end(); ++itr)
        CharacterDatabase.WaitExecute("DELETE FROM playercooldownitems WHERE OwnerGuid = %u AND CooldownTimeStamp = %u", itr->first, itr->second);
    for (std::set<uint32>::iterator itr = tokill_cool.begin(); itr != tokill_cool.end(); ++itr)
        CharacterDatabase.WaitExecute("DELETE FROM playercooldownitems WHERE OwnerGuid = %u", *itr);

    LogNotice("DatabaseCleaner : Deleted %u playercooldownitems.", tokill_cool.size() + tokill_cool2.size());
    tokill_cool.clear();
    tokill_cool2.clear();

    result = CharacterDatabase.Query("SELECT OwnerGuid, TimeStamp FROM playercooldownsecurity");
    if (result)
    {
        uint32 t = getMSTime();
        do
        {
            uint32 guid = result->Fetch()[0].GetUInt32();
            uint32 cool = result->Fetch()[1].GetUInt32();
            if (chr_guids.find(guid) == chr_guids.end())
                tokill_cool.insert(guid);
            else if (t >= cool)
                tokill_cool2.push_back(std::make_pair(guid, cool));
        }
        while (result->NextRow());
        delete result;
    }

    for (std::vector<std::pair<uint32, uint32> >::iterator itr = tokill_cool2.begin(); itr != tokill_cool2.end(); ++itr)
        CharacterDatabase.WaitExecute("DELETE FROM playercooldownsecurity WHERE OwnerGuid = %u AND TimeStamp = %u", itr->first, itr->second);
    for (std::set<uint32>::iterator itr = tokill_cool.begin(); itr != tokill_cool.end(); ++itr)
        CharacterDatabase.WaitExecute("DELETE FROM playercooldownsecurity WHERE OwnerGuid = %u", *itr);

    LogNotice("DatabaseCleaner : Deleted %u playercooldownsecurities.", tokill_cool.size() + tokill_cool2.size());
    LogNotice("DatabaseCleaner : Cleaning tutorials...");
    std::vector<uint32> tokill_tutorials;

    result = CharacterDatabase.Query("SELECT playerId FROM tutorials");
    if (result)
    {
        do
        {
            uint32 pi = result->Fetch()[0].GetUInt32();
            if (chr_guids.find(pi) == chr_guids.end())
                tokill_tutorials.push_back(pi);
        }
        while (result->NextRow());
        delete result;
    }

    for (std::vector<uint32>::iterator itr = tokill_tutorials.begin(); itr != tokill_tutorials.end(); ++itr)
        CharacterDatabase.WaitExecute("DELETE FROM tutorials WHERE playerId = %u", *itr);
    LogNotice("DatabaseCleaner : Deleted %u tutorials.", tokill_tutorials.size());
    LogNotice("DatabaseCleaner : Cleaning playerpets...");
    std::set<uint32> tokill_pet;

    result = CharacterDatabase.Query("SELECT ownerguid, petnumber FROM playerpets");
    if (result)
    {
        do
        {
            if (chr_guids.find(result->Fetch()[0].GetUInt32()) == chr_guids.end())
                tokill_pet.insert(result->Fetch()[0].GetUInt32());
        }
        while (result->NextRow());
        delete result;
    }
    for (std::set<uint32>::iterator itr = tokill_pet.begin(); itr != tokill_pet.end(); ++itr)
        CharacterDatabase.WaitExecute("DELETE FROM playerpets WHERE ownerguid = %u", *itr);
    LogNotice("DatabaseCleaner : Deleted %u pets.", tokill_pet.size());
    LogNotice("DatabaseCleaner : Cleaning playersummonspells...");
    std::set<uint32> tokill_ss;

    result = CharacterDatabase.Query("SELECT ownerguid FROM playersummonspells");
    if (result)
    {
        do
        {
            if (chr_guids.find(result->Fetch()[0].GetUInt32()) == chr_guids.end())
                tokill_ss.insert(result->Fetch()[0].GetUInt32());
        }
        while (result->NextRow());
        delete result;
    }
    for (std::set<uint32>::iterator itr = tokill_ss.begin(); itr != tokill_ss.end(); ++itr)
        CharacterDatabase.WaitExecute("DELETE FROM playersummonspells WHERE ownerguid = %u", *itr);
    LogNotice("DatabaseCleaner : Deleted %u summonspells.", tokill_ss.size());
    LogNotice("DatabaseCleaner : Cleaning playerpetspells...");
    std::set<uint32> tokill_ps;

    result = CharacterDatabase.Query("SELECT ownerguid FROM playerpetspells");
    if (result)
    {
        do
        {
            if (chr_guids.find(result->Fetch()[0].GetUInt32()) == chr_guids.end())
                tokill_ps.insert(result->Fetch()[0].GetUInt32());
        }
        while (result->NextRow());
        delete result;
    }
    for (std::set<uint32>::iterator itr = tokill_ps.begin(); itr != tokill_ps.end(); ++itr)
        CharacterDatabase.WaitExecute("DELETE FROM playerpetspells WHERE ownerguid = %u", *itr);
    LogNotice("DatabaseCleaner : Deleted %u petspells.", tokill_ps.size());
    LogNotice("DatabaseCleaner : Cleaning gm_tickets...");
    std::set<uint32> tokill_gm;

    result = CharacterDatabase.Query("SELECT guid FROM gm_tickets");
    if (result)
    {
        do
        {
            if (chr_guids.find(result->Fetch()[0].GetUInt32()) == chr_guids.end())
                tokill_gm.insert(result->Fetch()[0].GetUInt32());
        }
        while (result->NextRow());
        delete result;
    }
    for (std::set<uint32>::iterator itr = tokill_gm.begin(); itr != tokill_gm.end(); ++itr)
        CharacterDatabase.WaitExecute("DELETE FROM gm_tickets WHERE guid = %u", *itr);
    LogNotice("DatabaseCleaner : Deleted %u gm tickets.", tokill_gm.size());
    LogNotice("DatabaseCleaner : Cleaning charters...");
    std::vector<uint32> tokill_charters;

    result = CharacterDatabase.Query("SELECT * FROM charters");
    if (result)
    {
        do
        {
            if (chr_charters.find(result->Fetch()[0].GetUInt32()) == chr_charters.end() ||
                chr_guids.find(result->Fetch()[1].GetUInt32()) == chr_guids.end())
            {
                tokill_charters.push_back(result->Fetch()[0].GetUInt32());
            }
        }
        while (result->NextRow());
        delete result;
    }

    for (std::vector<uint32>::iterator itr = tokill_charters.begin(); itr != tokill_charters.end(); ++itr)
        CharacterDatabase.WaitExecute("DELETE FROM charters WHERE charterId = %u", *itr);
    LogNotice("DatabaseCleaner : Deleted %u charters.", tokill_charters.size());
    LogNotice("DatabaseCleaner : Cleaning charters...");

    result = CharacterDatabase.Query("SELECT auctionId, owner FROM auctions");
    std::vector<uint32> tokill_auct;
    if (result)
    {
        do
        {
            if (chr_guids.find(result->Fetch()[1].GetUInt32()) == chr_guids.end())
                tokill_auct.push_back(result->Fetch()[0].GetUInt32());

        }
        while (result->NextRow());
        delete result;
    }

    for (std::vector<uint32>::iterator itr = tokill_auct.begin(); itr != tokill_auct.end(); ++itr)
        CharacterDatabase.WaitExecute("DELETE FROM auctions WHERE auctionId = %u", *itr);
    LogNotice("DatabaseCleaner : Deleted %u auctions.", tokill_auct.size());
    LogNotice("DatabaseCleaner : Ending...");
}
Beispiel #25
0
bool Master::Run(int /*argc*/, char** /*argv*/)
{
    char* config_file = (char*)CONFDIR "/world.conf";

    UNIXTIME = time(NULL);
    g_localTime = *localtime(&UNIXTIME);

    AscLog.InitalizeLogFiles("world");

    PrintBanner();

    LogDefault("The key combination <Ctrl-C> will safely shut down the server.");

#ifndef WIN32
    if (geteuid() == 0 || getegid() == 0)
        AscLog.ConsoleLogMajorError("You are running AscEmu as root.", "This is not needed, and may be a possible security risk.", "It is advised to hit CTRL+C now and", "start as a non-privileged user.");
#endif

    InitImplicitTargetFlags();

    ThreadPool.Startup();
    auto startTime = Util::TimeNow();

    new EventMgr;
    new World;

    if (!LoadWorldConfiguration(config_file))
    {
        return false;
    }

    sWorld.loadWorldConfigValues();

    AscLog.SetFileLoggingLevel(worldConfig.log.worldFileLogLevel);
    AscLog.SetDebugFlags(worldConfig.log.worldDebugFlags);

    OpenCheatLogFiles();

    if (!_StartDB())
    {
        Database::CleanupLibs();
        AscLog.~AscEmuLog();
        return false;
    }

    if (!_CheckDBVersion())
    {
        AscLog.~AscEmuLog();
        return false;
    }

    // Initialize Opcode Table
    WorldSession::InitPacketHandlerTable();

    new ScriptMgr;

    if (!sWorld.setInitialWorldSettings())
    {
        LOG_ERROR("SetInitialWorldSettings() failed. Something went wrong? Exiting.");
        AscLog.~AscEmuLog();
        return false;
    }

    sWorld.setWorldStartTime((uint32)UNIXTIME);

    worldRunnable = std::move(std::make_unique<WorldRunnable>());

    _HookSignals();

    ConsoleThread* console = new ConsoleThread();
    ThreadPool.ExecuteTask(console);

    StartNetworkSubsystem();

    sSocketMgr.SpawnWorkerThreads();

    sScriptMgr.LoadScripts();

    if (worldConfig.startup.enableSpellIdDump)
    {
        sScriptMgr.DumpUnimplementedSpells();
    }

    LogDetail("Server : Ready for connections. Startup time: %u ms", Util::GetTimeDifferenceToNow(startTime));

    ThreadPool.ExecuteTask(new GameEventMgr::GameEventMgrThread());

    StartRemoteConsole();

    WritePidFile();

    if (!ChannelMgr::getSingletonPtr())
        new ChannelMgr;

    channelmgr.seperatechannels = worldConfig.server.seperateChatChannels;

    if (!MailSystem::getSingletonPtr())
        new MailSystem;

    uint32_t mailFlags = 0;

    if (worldConfig.mail.isCostsForGmDisabled)
        mailFlags |= MAIL_FLAG_NO_COST_FOR_GM;

    if (worldConfig.mail.isCostsForEveryoneDisabled)
        mailFlags |= MAIL_FLAG_DISABLE_POSTAGE_COSTS;

    if (worldConfig.mail.isDelayItemsDisabled)
        mailFlags |= MAIL_FLAG_DISABLE_HOUR_DELAY_FOR_ITEMS;

    if (worldConfig.mail.isMessageExpiryDisabled)
        mailFlags |= MAIL_FLAG_NO_EXPIRY;

    if (worldConfig.mail.isInterfactionMailEnabled)
        mailFlags |= MAIL_FLAG_CAN_SEND_TO_OPPOSITE_FACTION;

    if (worldConfig.mail.isInterfactionMailForGmEnabled)
        mailFlags |= MAIL_FLAG_CAN_SEND_TO_OPPOSITE_FACTION_GM;

    sMailSystem.config_flags = mailFlags;

    //ThreadPool.Gobble();

    /* Connect to realmlist servers / logon servers */
    new LogonCommHandler();
    sLogonCommHandler.startLogonCommHandler();

    // Create listener
    ListenSocket<WorldSocket> * ls = new ListenSocket<WorldSocket>(worldConfig.listen.listenHost.c_str(), worldConfig.listen.listenPort);
    bool listnersockcreate = ls->IsOpen();
#ifdef WIN32
    if (listnersockcreate)
        ThreadPool.ExecuteTask(ls);
#endif

    ShutdownThreadPools(listnersockcreate);

    _UnhookSignals();

    worldRunnable->threadShutdown();
    worldRunnable = nullptr;

    ThreadPool.ShowStats();
    /* Shut down console system */
    console->stopThread();
    delete console;

    // begin server shutdown

    ShutdownLootSystem();

    // send a query to wake it up if its inactive
    LogNotice("Database : Clearing all pending queries...");

    // kill the database thread first so we don't lose any queries/data
    CharacterDatabase.EndThreads();
    WorldDatabase.EndThreads();

    ls->Close();

    CloseConsoleListener();
    sWorld.saveAllPlayersToDb();

    LogNotice("Network : Shutting down network subsystem.");
#ifdef WIN32
    sSocketMgr.ShutdownThreads();
#endif
    sSocketMgr.CloseAll();

    bServerShutdown = true;
    ThreadPool.Shutdown();

    delete ls;

    sWorld.logoutAllPlayers();

    delete LogonCommHandler::getSingletonPtr();

    LogNotice("AddonMgr : ~AddonMgr()");
#if VERSION_STRING != Cata
    sAddonMgr.SaveToDB();
#endif
    delete AddonMgr::getSingletonPtr();

    LogNotice("AuctionMgr : ~AuctionMgr()");
    delete AuctionMgr::getSingletonPtr();

    LogNotice("LootMgr : ~LootMgr()");
    delete LootMgr::getSingletonPtr();

    LogNotice("MailSystem : ~MailSystem()");
    delete MailSystem::getSingletonPtr();

    LogNotice("World : ~World()");
    delete World::getSingletonPtr();

    sScriptMgr.UnloadScripts();
    delete ScriptMgr::getSingletonPtr();

    LogNotice("ChatHandler : ~ChatHandler()");
    delete ChatHandler::getSingletonPtr();

    LogNotice("EventMgr : ~EventMgr()");
    delete EventMgr::getSingletonPtr();

    LogNotice("Database : Closing Connections...");
    _StopDB();

    LogNotice("Network : Deleting Network Subsystem...");
    delete SocketMgr::getSingletonPtr();
    delete SocketGarbageCollector::getSingletonPtr();

    delete GMCommand_Log;
    delete Anticheat_Log;
    delete Player_Log;

    // remove pid
    if (remove("worldserver.pid") != 0)
    {
        LOG_ERROR("Error deleting file worldserver.pid");
    }
    else
    {
        LOG_DEBUG("File worldserver.pid successfully deleted");
    }

    LogDetail("Shutdown : Shutdown complete.");
    AscLog.~AscEmuLog();

#ifdef WIN32
    WSACleanup();
#endif

    return true;
}