예제 #1
0
BOOL KLogClient::DoPingSignal()
{
    BOOL				bResult			= false;
    BOOL				bRetCode		= false;
    DWORD               dwNowTime       = 0;
    IKG_Buffer*         piSendBuffer    = NULL;
    G2L_PING_SIGNAL*    pPingSingal		= NULL;

    dwNowTime = KG_GetTickCount();

    KG_PROCESS_ERROR(dwNowTime >= m_dwNextPingTime);

    m_dwNextPingTime = dwNowTime + 1000 * m_nPingCycle;

    piSendBuffer = KG_MemoryCreateBuffer(sizeof(G2L_PING_SIGNAL));
    KGLOG_PROCESS_ERROR(piSendBuffer);

    pPingSingal = (G2L_PING_SIGNAL*)piSendBuffer->GetData();
    KGLOG_PROCESS_ERROR(pPingSingal);

    pPingSingal->wProtocolID = g2l_ping_signal;

    bRetCode = Send(piSendBuffer);
    KGLOG_PROCESS_ERROR(bRetCode);   

    bResult = true;
Exit0:
    KG_COM_RELEASE(piSendBuffer);
    return bResult;
}
예제 #2
0
void KPlayerServer::Activate()
{
    assert(g_pSO3World);

    m_dwTimeNow = KG_GetTickCount();

    if (g_pSO3World->m_nGameLoop % GAME_FPS == 0)
    {
        m_fS2CTraffic = m_fS2CTraffic * 0.9f + (float)m_nS2CTraffic * 0.1f;
        m_fC2STraffic = m_fC2STraffic * 0.9f + (float)m_nC2STraffic * 0.1f;

        m_nS2CTraffic = 0;
        m_nC2STraffic = 0;
    }

    for (int i = 0; i < 8; i++)
    {
        int              nConnIndex  = m_nNextCheckConnection;
        KConnectionData* pConnection = m_ConnectionDataList + nConnIndex;

        m_nNextCheckConnection = (m_nNextCheckConnection + 1) % m_nMaxConnection;

        if (pConnection->piSocketStream == NULL)
            continue;

        if (m_dwTimeNow > pConnection->dwLastPingTime + m_nPingCycle * 1000)
        {
            KGLogPrintf(KGLOG_ERR, "Connection timeout: %d\n", nConnIndex);

            Detach(nConnIndex);
            Shutdown(nConnIndex);

            continue;
        }

        if (g_pSO3World->m_nGameLoop >= pConnection->nStatLastUpdateFrame + GAME_FPS)
        {
            int nDeltaFrame = g_pSO3World->m_nGameLoop - pConnection->nStatLastUpdateFrame;

            pConnection->fStatSendSpeed = pConnection->fStatSendSpeed * 0.8f + pConnection->uStatSendByteCount * 0.2f * GAME_FPS / nDeltaFrame;
            pConnection->uStatSendByteCount = 0;
            pConnection->nStatLastUpdateFrame = g_pSO3World->m_nGameLoop;
        }

        if (pConnection->bSendError)
        {
            Detach(nConnIndex);
            Shutdown(nConnIndex);
            pConnection->bSendError = false;
        }
    }
}
예제 #3
0
BOOL KAwardMgr::Award(KPlayer* pPlayer, KAWARD_CARD_TYPE eType, DWORD dwAwardID, unsigned uChooseIndex, BOOL bEndChoose)
{
    BOOL            bResult         = false;
    BOOL            bRetCode        = false;
    IItem*          pItem           = NULL;
    KAwardTable*    pAwardTable     = NULL;
    KAWARD_ITEM*    pAwardItem      = NULL;
    KS2C_Award_Item arrAwardList[cdVipCardCount] = {0};
    IItem*          pLookItem = NULL;
    KSystemMailTxt* pSysMailTxt = NULL;
    KAWARD_ITEM*    pTempItem = NULL;
    KS2C_Award_Item* pAwardItemInfo = NULL;
    KS2C_Award_Item AwardItem;
    DWORD           dwRandSeed = 0;
    int nValuePoint = 0;

    assert(pPlayer);

    KGLOG_PROCESS_ERROR(uChooseIndex < countof(arrAwardList));

    pAwardTable = GetAwardTable(dwAwardID);
    KGLOG_PROCESS_ERROR(pAwardTable);

    pAwardItem = pAwardTable->GetRandomAward();
    if (pAwardItem)
    {
        if (pAwardItem->dwTabType == ittOther || pAwardItem->dwTabType == ittEquip)
        { 
            pSysMailTxt = g_pSO3World->m_Settings.m_SystemMailMgr.GetSystemMailTxt(KMAIL_CHOOSE);
            KGLOG_PROCESS_ERROR(pSysMailTxt);

            bRetCode = GetAwardItemValuePoint(pAwardItem, nValuePoint);
            KGLOG_PROCESS_ERROR(bRetCode);
            
            dwRandSeed = KG_GetTickCount();

            bRetCode = pPlayer->SafeAddItem(pAwardItem->dwTabType, pAwardItem->dwIndex, pAwardItem->nStackNum, nValuePoint, 
                pSysMailTxt->m_szMailTitl, pSysMailTxt->m_szSendName, pSysMailTxt->m_szMailTxt, dwRandSeed
            );

            pItem = g_pSO3World->m_ItemHouse.CreateItem(pAwardItem->dwTabType, pAwardItem->dwIndex, 0, dwRandSeed, nValuePoint);

            if (bRetCode)
            {
                BroadCastAwardItem(pPlayer, pAwardItem);
 
                if (eType == KAWARD_CARD_TYPE_NORMAL)
                {
                    PLAYER_LOG(
                        pPlayer, "item,additem,%u-%u,%d,%d,%s,%d",
                        pAwardItem->dwTabType, pAwardItem->dwIndex, pAwardItem->nStackNum, nValuePoint, 
                        "missionaward", pPlayer->m_dwMapID
                        );
                }
                else if (eType == KAWARD_CARD_TYPE_GOLD)
                {
                    PLAYER_LOG(
                        pPlayer, "item,additem,%u-%u,%d,%d,%s,%d",
                        pAwardItem->dwTabType, pAwardItem->dwIndex, pAwardItem->nStackNum, nValuePoint,
                        "goldaward", pPlayer->m_dwMapID
                        );
                }
                else if (eType == KAWARD_CARD_TYPE_VIP)
                {
                    PLAYER_LOG(
                        pPlayer, "item,additem,%u-%u,%d,%d,%s,%d",
                        pAwardItem->dwTabType, pAwardItem->dwIndex, pAwardItem->nStackNum, nValuePoint,
                        "vipaward", pPlayer->m_dwMapID
                    );
                }
            }
        }
        else if (pAwardItem->dwTabType == ittFashion)
        {
            bRetCode = pPlayer->m_Wardrobe.AddFashion(pAwardItem->dwIndex);
            KGLOG_CHECK_ERROR(bRetCode);
        }
        else if (pAwardItem->dwTabType == ittCheerleading)
        {
            KGCheerleadingInfo* pCheerleadingInfo = g_pSO3World->m_ItemHouse.GetCheerleadingInfo(pAwardItem->dwIndex);
            KGLOG_PROCESS_ERROR(pCheerleadingInfo);

            bRetCode = pPlayer->m_CheerleadingMgr.AddCheerleading(pCheerleadingInfo->dwID);
            KGLOG_PROCESS_ERROR(bRetCode);
        }
        else if (pAwardItem->dwTabType == ittTeamLogo)
        {
            KTEAM_LOGO_INFO*    pTeamLogoInfo = NULL;

            pTeamLogoInfo = g_pSO3World->m_ItemHouse.GetTeamLogoInfo(pAwardItem->dwIndex);
            KGLOG_PROCESS_ERROR(pTeamLogoInfo);

            bRetCode = pPlayer->AddTeamLogo((WORD)pTeamLogoInfo->nID);
            KGLOG_PROCESS_ERROR(bRetCode);
        }
        else if (pAwardItem->nMoney > 0)
        {
            bRetCode = pPlayer->m_MoneyMgr.AddMoney(pAwardItem->eMoneyType, pAwardItem->nMoney);
            KGLOG_PROCESS_ERROR(bRetCode);
            PLAYER_LOG(pPlayer, "money,addmoney,%d,%s,%d-%d,%d,%d", pAwardItem->eMoneyType, "awardtable", 0, 0, 0, pAwardItem->nMoney);


            BroadCastAwardMoney(pPlayer, pAwardItem);
        }

        memset(&AwardItem, 0, sizeof(AwardItem));

        pAwardItemInfo = &AwardItem;

        memset(pAwardItemInfo->RandomAttr, 0, sizeof(pAwardItemInfo->RandomAttr));

        bRetCode = GetAwardItemValuePoint(pAwardItem, nValuePoint);
        KGLOG_PROCESS_ERROR(bRetCode);

        pAwardItemInfo->itemType    = (unsigned char)pAwardItem->dwTabType;
        pAwardItemInfo->itemIndex   = pAwardItem->dwIndex;
        pAwardItemInfo->nCount      = (short)pAwardItem->nStackNum;
        pAwardItemInfo->byMoneyType = (BYTE)pAwardItem->eMoneyType;
        pAwardItemInfo->nMoney      = (short)pAwardItem->nMoney;
        pAwardItemInfo->nValuePoint = nValuePoint;

        if (pItem)
        {
            const KItemProperty*    pProperty   = pItem->GetProperty();
            KAttribute*			    pExtAttr    = pProperty->pExtAttr;  

            for (int j = 0; j < countof(pAwardItemInfo->RandomAttr); ++j)
            {
                if (pExtAttr == NULL)
                    break;

                pAwardItemInfo->RandomAttr[j].wKey = (unsigned short)pExtAttr->nKey;
                pAwardItemInfo->RandomAttr[j].wValue = (unsigned short)pExtAttr->nValue1;
                pExtAttr = pExtAttr->pNext;
            }
        }

        g_PlayerServer.DoAwardItemNotify(pPlayer, eType, AwardItem, uChooseIndex);
    }

    KG_PROCESS_SUCCESS(!bEndChoose);

    memset(arrAwardList, 0, sizeof(arrAwardList));
    for (unsigned i = 0; i < countof(arrAwardList); ++i)
    {
        pTempItem = NULL;
        pAwardItemInfo = &arrAwardList[i];

        memset(pAwardItemInfo->RandomAttr, 0, sizeof(pAwardItemInfo->RandomAttr));

        if (i != uChooseIndex)
        {
            const KItemProperty*    pProperty = NULL;
            KAttribute*			    pExtAttr  = NULL;

            pTempItem = pAwardTable->GetOneAwardItemByEqualRate();
            if (pTempItem == NULL)
                continue;

            bRetCode = GetAwardItemValuePoint(pTempItem, nValuePoint);
			KGLOG_PROCESS_ERROR(bRetCode);

            pAwardItemInfo->itemType    = (unsigned char)pTempItem->dwTabType;
            pAwardItemInfo->itemIndex   = pTempItem->dwIndex;
            pAwardItemInfo->nCount      = (short)pTempItem->nStackNum;
            pAwardItemInfo->byMoneyType = (BYTE)pTempItem->eMoneyType;
            pAwardItemInfo->nMoney      = (short)pTempItem->nMoney;
            pAwardItemInfo->nValuePoint = nValuePoint;

            if (pTempItem->dwTabType > 0 && pTempItem->dwIndex > 0)
            {
                pLookItem = g_pSO3World->m_ItemHouse.CreateItem(pTempItem->dwTabType, pTempItem->dwIndex, 0, 0, nValuePoint);
                KGLOG_CHECK_ERROR(pLookItem);
                if (pLookItem)
                {
                    pProperty   = pLookItem->GetProperty();
                    pExtAttr    = pProperty->pExtAttr;  

                    for (int j = 0; j < countof(pAwardItemInfo->RandomAttr); ++j)
                    {
                        if (pExtAttr == NULL)
                            break;

                        pAwardItemInfo->RandomAttr[j].wKey = (unsigned short)pExtAttr->nKey;
                        pAwardItemInfo->RandomAttr[j].wValue = (unsigned short)pExtAttr->nValue1;
                        pExtAttr = pExtAttr->pNext;
                    }

                    g_pSO3World->m_ItemHouse.DestroyItem(pLookItem);
                    pLookItem = NULL;
                }

            }
        }
    }

    g_PlayerServer.DoAwardItemListNotify(pPlayer, eType, arrAwardList, countof(arrAwardList));

Exit1:
    bResult = true;
Exit0:
    if (pLookItem)
    {
        g_pSO3World->m_ItemHouse.DestroyItem(pLookItem);
        pLookItem = NULL;
    }

    if (pItem)
    {
        g_pSO3World->m_ItemHouse.DestroyItem(pItem);
        pItem = NULL;
    }
    return bResult;
}
예제 #4
0
KAIActionHandle KAILogic::CallAction(KHero* pHero, KAIActionHandle ActionKey)
{
    KAIActionHandle Result;
    KAIActionHandle NextAction;
    KAIAction*      pAction     = ActionKey.pAIAction;
    int             nActionKey  = 0;

    if (!pAction)
        pAction = GetAction(ActionKey.nAIActionID);

    if (pAction == NULL)
    {
        KGLogPrintf(KGLOG_ERR, "[AI] Invalid action call(%d) in AI(%d)", ActionKey.nAIActionID, m_nAIType);
        goto Exit0;
    }

    nActionKey = pAction->m_nKey;

    if (nActionKey < KAI_USER_ACTION)
    {
        int             nBranchIndex    = 0;
        unsigned long   ulPrevTickCount = 0;
        unsigned long   ulPostTickCount = 0;
        KAI_ACTION_FUNC PAction         = NULL;

        if (g_pSO3World->m_AIManager.m_bLogAIRuntimeStat)
            ulPrevTickCount = KG_GetTickCount();

        PAction = g_pSO3World->m_AIManager.GetActionFunction(nActionKey);
        KGLOG_PROCESS_ERROR(PAction);

        nBranchIndex = (*PAction)(pHero, pAction);

        if (nBranchIndex > 0 && nBranchIndex <= KAI_ACTION_BRANCH_NUM)
        {
            int         nNextActionID   = pAction->m_nBranch[nBranchIndex - 1];
            KAIAction*  pNextAction     = pAction->m_pBranch[nBranchIndex - 1];

            if (!pNextAction)
            {
                pNextAction = GetAction(nNextActionID);
                pAction->m_pBranch[nBranchIndex - 1] = pNextAction;
            }

            NextAction.nAIActionID  = nNextActionID;
            NextAction.pAIAction    = pNextAction;

            if (pHero->m_AIVM.m_pAIProcessLogFile)
            {
                fprintf(
                    pHero->m_AIVM.m_pAIProcessLogFile, 
                    "CurrentAction : %d, Branch : %d, NextAction : %d.\n", 
                    ActionKey.nAIActionID, 
                    nBranchIndex, 
                    nNextActionID
                );
            }
        }

        if (nBranchIndex == -1)
        {
            NextAction.nAIActionID = KAI_ACTION_ID_NONE;
            NextAction.pAIAction = NULL;
        }

        if (g_pSO3World->m_AIManager.m_bLogAIRuntimeStat)
        {
            ulPostTickCount = KG_GetTickCount();

            g_pSO3World->m_AIManager.m_ActionRunTimeStatisticsArray[nActionKey].ullTime += ulPostTickCount - ulPrevTickCount;
            g_pSO3World->m_AIManager.m_ActionRunTimeStatisticsArray[nActionKey].uCount++;
        }
    }
    else
    {
        int nLuaTopIndex = 0;
        int nBranchIndex = 0;

        KUSER_ACTION_TABLE::iterator it = m_UserActionTable.find(nActionKey);

        KGLOG_PROCESS_ERROR(it != m_UserActionTable.end());

        g_pSO3World->m_ScriptManager.SafeCallBegin(&nLuaTopIndex);
        g_pSO3World->m_ScriptManager.Push(pHero);
        g_pSO3World->m_ScriptManager.Push(pAction);
        g_pSO3World->m_ScriptManager.Call(m_dwScriptID, it->second.c_str(), 1);
        g_pSO3World->m_ScriptManager.GetValuesFromStack("d", &nBranchIndex);
        g_pSO3World->m_ScriptManager.SafeCallEnd(nLuaTopIndex);

        if (nBranchIndex >= 1 && nBranchIndex <= KAI_ACTION_BRANCH_NUM)
        {
            int         nNextActionID   = pAction->m_nBranch[nBranchIndex - 1];
            KAIAction*  pNextAction     = pAction->m_pBranch[nBranchIndex - 1];

            if (!pNextAction)
            {
                pNextAction = GetAction(nNextActionID);
                pAction->m_pBranch[nBranchIndex - 1] = pNextAction;
            }

            NextAction.nAIActionID  = nNextActionID;
            NextAction.pAIAction    = pNextAction;

            if (pHero->m_AIVM.m_pAIProcessLogFile)
            {
                fprintf(
                    pHero->m_AIVM.m_pAIProcessLogFile, 
                    "CurrentAction : %d, Branch : %d, NextAction : %d.\n", 
                    ActionKey.nAIActionID, 
                    nBranchIndex, 
                    nNextActionID
                );
            }
        }
    }

    Result = NextAction;
Exit0:
    return Result;
}
예제 #5
0
파일: KAIVM.cpp 프로젝트: 1suming/pap2
void KAIVM::FireEvent(int nEvent, DWORD dwEventSrc, int nEventParam)
{
    int             nEventBlock     = m_nCurrentEvent;
    //int             nAction         = KAI_ACTION_BRANCH_ERROR;
    int             nCallCount      = 0;
    DWORD           dwScriptID      = ERROR_ID;
    unsigned long   ulPrevTickCount = 0;
    unsigned long   ulPostTickCount = 0;
    KAIActionHandle ActionKey;

    assert(nEvent > 0);

    KG_PROCESS_ERROR(m_pAILogic);

    dwScriptID = m_pAILogic->GetScriptID();

    assert(m_pOwner);
    assert(m_pState);

    if (g_pSO3World->m_AIManager.m_bLogAIRuntimeStat)
        ulPrevTickCount = KG_GetTickCount();

    // 触发的事件预先判断在当前状态是否有托管
    ActionKey = m_pState->GetEventHandler(nEvent);
    KG_PROCESS_SUCCESS(ActionKey.nAIActionID == KAI_ACTION_ID_NONE);

    if (m_nDebugCount > 0)
        KGLogPrintf(KGLOG_DEBUG, "[AI] <%lu> On event: %d, src: %lu, param: %d\n", m_pOwner->m_dwID, nEvent, dwEventSrc, nEventParam);

    if (nEventBlock != aevInvalid)
    {
        // 重复事件替代
        if (m_nPendingEvent == aevInvalid || m_nPendingEvent == nEvent)
        {
            m_nPendingEvent = nEvent;
            m_dwPendingEventSrc = dwEventSrc;
            m_nPendingEventParam = nEventParam;
        }
        else
        {
            KGLogPrintf(
                KGLOG_ERR, "[AI] Event %d blocked by %d, PendingEvent %d, ai type %d, npc name is %s.\n", 
                nEvent, nEventBlock, m_nPendingEvent, m_nAIType, m_pOwner->m_szName
            );
        }
        goto Exit0;
    }

    m_nCurrentEvent = nEvent;

    m_pOwner->m_AIData.dwAIEventSrc         = dwEventSrc;
    m_pOwner->m_AIData.nAIEventParam        = nEventParam;
    m_pOwner->m_AIData.nTargetGroupCount    = 0;
    memset(m_pOwner->m_AIData.TargetGroup, 0, sizeof(m_pOwner->m_AIData.TargetGroup));

    while (ActionKey.nAIActionID != KAI_ACTION_ID_NONE)
    {
        KAIActionHandle NextActionKey;

        if (nCallCount > MAX_ACTION_CALL)
        {
            // 死循环检测
            KGLogPrintf(
                KGLOG_ERR, "[AI] Action call up to limit(%d), ai type = %d, event = %d, action = %d\n", 
                MAX_ACTION_CALL, m_nAIType, nEvent, ActionKey.nAIActionID
            );
            break;
        }

        if (m_nDebugCount > 0)
        {
            if (g_pSO3World->m_ScriptCenter.IsScriptExist(dwScriptID) && g_pSO3World->m_ScriptCenter.IsFuncExist(dwScriptID, "DebugOnCallAction"))
            {
                int nLuaTopIndex = 0;

                g_pSO3World->m_ScriptCenter.SafeCallBegin(&nLuaTopIndex);

                g_pSO3World->m_ScriptCenter.PushValueToStack(ActionKey.nAIActionID);
                g_pSO3World->m_ScriptCenter.CallFunction(dwScriptID, "DebugOnCallAction", 0);

                g_pSO3World->m_ScriptCenter.SafeCallEnd(nLuaTopIndex);
            }
            else
            {
                KGLogPrintf(KGLOG_DEBUG, "[AI] <%lu> Call action %d\n", m_pOwner->m_dwID, ActionKey.nAIActionID);
            }
        }

        NextActionKey = m_pAILogic->CallAction(m_pOwner, ActionKey);
        if (NextActionKey.nAIActionID == KAI_ACTION_ID_ERROR)
        {
            KGLogPrintf(
                KGLOG_ERR, "[AI] Action call return error, AI type = %d, event = %d, action = %d, character id = %u, name:%s, pos(%d, %d, %d)\n", 
                m_nAIType, nEvent, ActionKey.nAIActionID, m_pOwner->m_dwID, m_pOwner->m_szName, m_pOwner->m_nX, m_pOwner->m_nY, m_pOwner->m_nZ
            );

            m_pAILogic = NULL;  // 出错的时候就把AI清掉,防止Log不断刷屏。
            break;
        }

        if (m_nDebugCount > 0)
            m_nDebugCount--;

        ActionKey = NextActionKey;
        m_nActionID = ActionKey.nAIActionID;
        nCallCount++;
    }

    m_pOwner->m_AIData.dwAIEventSrc = ERROR_ID;

Exit1:
Exit0:
    m_nCurrentEvent = nEventBlock;

    if (g_pSO3World->m_AIManager.m_bLogAIRuntimeStat)
    {
        ulPostTickCount = KG_GetTickCount();
        m_ullRunTimeStatistic += (ulPostTickCount - ulPrevTickCount);
    }

    return;
}
예제 #6
0
int KSystemScriptTable::LuaGetTime(Lua_State* L)
{
    Lua_PushNumber(L, KG_GetTickCount());
    return 1;
}
예제 #7
0
// 初始化面向客户端的连接
BOOL KPlayerServer::Init()
{
    BOOL            bResult                 = false;
    int             nRetCode                = false;
    BOOL            bSocketServerInit       = false;
    IIniFile*	    piIniFile               = NULL;
    unsigned long   ulInternalIPAddressMask = 0;
    unsigned long   ulExternalIPAddress     = INADDR_NONE;
    unsigned long   ulInternalIPAddress     = INADDR_NONE;
    //int				nListenPort             = 0;
    int             nNatPort                = 0;
    int 			nMaxConnection          = 0;
    int             nRecvBufferSize         = 0;
    int             nSendBufferSize         = 0;
    int             nClientGM               = 0;
    int             nMaxClientPackPerFrame  = 0;
    char            szNatIP[16];
    char            szInternalIPMask[16];
    unsigned char   byInternalMacAddress[6];
    unsigned char   byExternalMacAddress[6];
    struct          in_addr  InAddr;
    
    assert(g_pSO3World);
    
    piIniFile = g_OpenIniFile(GS_SETTINGS_FILENAME);
	KGLOG_PROCESS_ERROR(piIniFile);

    memset(szNatIP, 0, sizeof(szNatIP));

    piIniFile->GetString("GS-Player", "NatIP", "", szNatIP, sizeof(szNatIP));
    piIniFile->GetInteger("GS-Player", "NatPort", 0, &nNatPort);
    piIniFile->GetString("GS-Player", "InternalIPAddressMask", "192.168.0.0", szInternalIPMask, 16);
	piIniFile->GetInteger("GS-Player", "MaxConnection", 1024, &nMaxConnection);
	piIniFile->GetInteger("GS-Player", "RecvBufferSize", 8000, &nRecvBufferSize);
	piIniFile->GetInteger("GS-Player", "SendBufferSize", 64000, &nSendBufferSize); 
    piIniFile->GetInteger("GS-Player", "PingCycle", 0, &m_nPingCycle);
    piIniFile->GetInteger("GS-Player", "ClientGM", 0, &nClientGM);
    piIniFile->GetInteger("GS-Player", "MaxClientPackPerFrame", 256, &nMaxClientPackPerFrame);

    if (m_szLocalIP[0] != '\0')
    {
         ulExternalIPAddress = (unsigned long)inet_addr(m_szLocalIP);
         if (ulExternalIPAddress == INADDR_NONE)
         {
             KGLogPrintf(KGLOG_ERR, "[KPlayerServerBase] Invalid ip address or format.\n");
             goto Exit0;
         }    
    }
    else
    {
        char* pszInternetAddr = NULL;

        ulInternalIPAddressMask = inet_addr(szInternalIPMask);
        KGLOG_PROCESS_ERROR(ulInternalIPAddressMask != INADDR_NONE);

        nRetCode = gGetMacAndIPAddress(
            byInternalMacAddress, &ulInternalIPAddress, 
            byExternalMacAddress, &ulExternalIPAddress, ulInternalIPAddressMask
        );
        KGLOG_PROCESS_ERROR(nRetCode > 0);

        InAddr.s_addr = ulExternalIPAddress;
        pszInternetAddr = inet_ntoa(InAddr);
        KGLOG_PROCESS_ERROR(pszInternetAddr);

        strcpy(m_szLocalIP, pszInternetAddr);
    }
    
    KGLOG_PROCESS_ERROR(nMaxConnection > 0);
    
    m_dwTimeNow = KG_GetTickCount();
    m_nClientGM = nClientGM;

    ResetPakStat();

	m_nMaxConnection = nMaxConnection;
    m_nMaxClientPackPerFrame = nMaxClientPackPerFrame;

	m_ConnectionDataList = new KConnectionData[nMaxConnection];
	KGLOG_PROCESS_ERROR(m_ConnectionDataList);

    m_ConnectionDataListFreeVector.reserve(nMaxConnection);

    for (int i = 0; i < nMaxConnection; i++)
    {
        m_ConnectionDataListFreeVector.push_back(nMaxConnection - i - 1);
    }

    m_nSocketEventCount = nMaxConnection + KG_MAX_ACCEPT_EACH_WAIT;

    m_pSocketEventArray = new KG_SOCKET_EVENT[m_nSocketEventCount];
    KGLOG_PROCESS_ERROR(m_pSocketEventArray);

    nRetCode = m_SocketServerAcceptor.Init(
        m_szLocalIP, m_nListenPort, KG_MAX_ACCEPT_EACH_WAIT, 
        nRecvBufferSize, nSendBufferSize, KSG_ENCODE_DECODE_NONE, NULL
    );

    KGLogPrintf(
        KGLOG_INFO, "Start service at %s:%d ... ... [%s]",
        m_szLocalIP, m_nListenPort, nRetCode ? "OK" : "Failed"
    );
    
    KGLOG_PROCESS_ERROR(nRetCode);
    bSocketServerInit = true;

	m_dwInternetAddr    = ulExternalIPAddress;
    if (szNatIP[0] != '\0')
    {
        m_nListenPort       = nNatPort;
        m_dwInternetAddr    = (unsigned long)inet_addr(szNatIP);

        KGLogPrintf(KGLOG_INFO, "NAT at %s:%d", szNatIP, nNatPort);
    }

    m_nNextCheckConnection = 0;

    bResult = true;
Exit0:
    if (!bResult)
    {
        if (bSocketServerInit)
        {
            m_SocketServerAcceptor.UnInit(NULL);
            bSocketServerInit = false;
        }
        KG_DELETE_ARRAY(m_pSocketEventArray);
    	KG_DELETE_ARRAY(m_ConnectionDataList);
    }
    KG_COM_RELEASE(piIniFile);
	return bResult;
}