Çözüldü Sistem Ekleme input_main.cpp

Bu konu çözüme ulaştırılmıştır. Çözüm için konuya yazılan tüm yorumları okumayı unutmayın. Eğer konudaki yorumlar sorununuzu çözmediyse yeni bir konu açabilirsiniz.
Durum
İçerik kilitlendiği için mesaj gönderimine kapatıldı.

suleyman06

Bla bla
MT Üye
Mesaj
309
Çözümler
7
Beğeni
93
Puan
724
Ticaret Puanı
0
arkadaşlar bunu eklicem fakat 2 tane var aynısından hangisine eklemeliyim.

C++:
//1. Search:
        case SHOP_SUBHEADER_CG_SELL2:
            {
                ...
            }
//1. Replace with:
#ifdef UK_ENABLE_SPECIAL_STORAGE
        case SHOP_SUBHEADER_CG_SELL2:
            {
                if (uiBytes < sizeof(BYTE) + sizeof(BYTE) + sizeof(BYTE))
                    return -1;

                const BYTE wPos = *reinterpret_cast<const BYTE*>(c_pData);
                const BYTE bCount = *(c_pData + sizeof(BYTE));
                const BYTE bType = *(c_pData + sizeof(BYTE) + sizeof(BYTE));

                sys_log(0, "INPUT: %s SHOP: SELL2", ch->GetName());

                CShopManager::instance().Sell(ch, wPos, bCount, bType);
                return sizeof(BYTE) + sizeof(BYTE) + sizeof(BYTE);
            }
#else
        case SHOP_SUBHEADER_CG_SELL2:
            {
                if (uiBytes < sizeof(BYTE) + sizeof(BYTE))
                    return -1;

                BYTE pos = *(c_pData++);
                BYTE count = *(c_pData);

                sys_log(0, "INPUT: %s SHOP: SELL2", ch->GetName());
                CShopManager::instance().Sell(ch, pos, count);
                return sizeof(BYTE) + sizeof(BYTE);
            }
#endif

Benim Dosyam:

C++:
#include "constants.h"
#include "config.h"
#include "utils.h"
#include "desc_client.h"
#include "desc_manager.h"
#include "buffer_manager.h"
#include "packet.h"
#include "protocol.h"
#include "char.h"
#include "char_manager.h"
#include "item.h"
#include "item_manager.h"
#include "cmd.h"
#include "shop.h"
#include "shop_manager.h"
#include "safebox.h"
#include "regen.h"
#include "battle.h"
#include "exchange.h"
#include "questmanager.h"
#include "profiler.h"
#include "messenger_manager.h"
#include "party.h"
#include "p2p.h"
#include "affect.h"
#include "guild.h"
#include "guild_manager.h"
#include "log.h"
#include "banword.h"
#include "empire_text_convert.h"
#include "unique_item.h"
#include "building.h"
#include "locale_service.h"
#include "gm.h"
#include "spam.h"
#include "ani.h"
#include "motion.h"
#include "OXEvent.h"
#include "locale_service.h"
#include "HackShield.h"
#include "XTrapManager.h"
#include "DragonSoul.h"

extern void SendShout(const char * szText, BYTE bEmpire);
extern int g_nPortalLimitTime;

static int __deposit_limit()
{
    return (1000*10000); // 1천만
}

void SendBlockChatInfo(LPCHARACTER ch, int sec)
{
    if (sec <= 0)
    {
        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("채팅 금지 상태입니다."));
        return;
    }

    long hour = sec / 3600;
    sec -= hour * 3600;

    long min = (sec / 60);
    sec -= min * 60;

    char buf[128+1];

    if (hour > 0 && min > 0)
        snprintf(buf, sizeof(buf), LC_TEXT("%d 시간 %d 분 %d 초 동안 채팅금지 상태입니다"), hour, min, sec);
    else if (hour > 0 && min == 0)
        snprintf(buf, sizeof(buf), LC_TEXT("%d 시간 %d 초 동안 채팅금지 상태입니다"), hour, sec);
    else if (hour == 0 && min > 0)
        snprintf(buf, sizeof(buf), LC_TEXT("%d 분 %d 초 동안 채팅금지 상태입니다"), min, sec);
    else
        snprintf(buf, sizeof(buf), LC_TEXT("%d 초 동안 채팅금지 상태입니다"), sec);

    ch->ChatPacket(CHAT_TYPE_INFO, buf);
}

EVENTINFO(spam_event_info)
{
    char host[MAX_HOST_LENGTH+1];

    spam_event_info()
    {
        ::memset( host, 0, MAX_HOST_LENGTH+1 );
    }
};

typedef boost::unordered_map<std::string, std::pair<unsigned int, LPEVENT> > spam_score_of_ip_t;
spam_score_of_ip_t spam_score_of_ip;

EVENTFUNC(block_chat_by_ip_event)
{
    spam_event_info* info = dynamic_cast<spam_event_info*>( event->info );

    if ( info == NULL )
    {
        sys_err( "block_chat_by_ip_event> <Factor> Null pointer" );
        return 0;
    }

    const char * host = info->host;

    spam_score_of_ip_t::iterator it = spam_score_of_ip.find(host);

    if (it != spam_score_of_ip.end())
    {
        it->second.first = 0;
        it->second.second = NULL;
    }

    return 0;
}

bool SpamBlockCheck(LPCHARACTER ch, const char* const buf, const size_t buflen)
{
    extern int g_iSpamBlockMaxLevel;

    if (ch->GetLevel() < g_iSpamBlockMaxLevel)
    {
        spam_score_of_ip_t::iterator it = spam_score_of_ip.find(ch->GetDesc()->GetHostName());

        if (it == spam_score_of_ip.end())
        {
            spam_score_of_ip.insert(std::make_pair(ch->GetDesc()->GetHostName(), std::make_pair(0, (LPEVENT) NULL)));
            it = spam_score_of_ip.find(ch->GetDesc()->GetHostName());
        }

        if (it->second.second)
        {
            SendBlockChatInfo(ch, event_time(it->second.second) / passes_per_sec);
            return true;
        }

        unsigned int score;
        const char * word = SpamManager::instance().GetSpamScore(buf, buflen, score);

        it->second.first += score;

        if (word)
            sys_log(0, "SPAM_SCORE: %s text: %s score: %u total: %u word: %s", ch->GetName(), buf, score, it->second.first, word);

        extern unsigned int g_uiSpamBlockScore;
        extern unsigned int g_uiSpamBlockDuration;

        if (it->second.first >= g_uiSpamBlockScore)
        {
            spam_event_info* info = AllocEventInfo<spam_event_info>();
            strlcpy(info->host, ch->GetDesc()->GetHostName(), sizeof(info->host));

            it->second.second = event_create(block_chat_by_ip_event, info, PASSES_PER_SEC(g_uiSpamBlockDuration));
            sys_log(0, "SPAM_IP: %s for %u seconds", info->host, g_uiSpamBlockDuration);

            LogManager::instance().CharLog(ch, 0, "SPAM", word);

            SendBlockChatInfo(ch, event_time(it->second.second) / passes_per_sec);

            return true;
        }
    }

    return false;
}

enum
{
    TEXT_TAG_PLAIN,
    TEXT_TAG_TAG, // ||
    TEXT_TAG_COLOR, // |cffffffff
    TEXT_TAG_HYPERLINK_START, // |H
    TEXT_TAG_HYPERLINK_END, // |h ex) |Hitem:1234:1:1:1|h
    TEXT_TAG_RESTORE_COLOR,
};

int GetTextTag(const char * src, int maxLen, int & tagLen, std::string & extraInfo)
{
    tagLen = 1;

    if (maxLen < 2 || *src != '|')
        return TEXT_TAG_PLAIN;

    const char * cur = ++src;

    if (*cur == '|') // ||는 |로 표시한다.
    {
        tagLen = 2;
        return TEXT_TAG_TAG;
    }
    else if (*cur == 'c') // color |cffffffffblahblah|r
    {
        tagLen = 2;
        return TEXT_TAG_COLOR;
    }
    else if (*cur == 'H') // hyperlink |Hitem:10000:0:0:0:0|h[이름]|h
    {
        tagLen = 2;
        return TEXT_TAG_HYPERLINK_START;
    }
    else if (*cur == 'h') // end of hyperlink
    {
        tagLen = 2;
        return TEXT_TAG_HYPERLINK_END;
    }

    return TEXT_TAG_PLAIN;
}

void GetTextTagInfo(const char * src, int src_len, int & hyperlinks, bool & colored)
{
    colored = false;
    hyperlinks = 0;

    int len;
    std::string extraInfo;

    for (int i = 0; i < src_len;)
    {
        int tag = GetTextTag(&src[i], src_len - i, len, extraInfo);

        if (tag == TEXT_TAG_HYPERLINK_START)
            ++hyperlinks;

        if (tag == TEXT_TAG_COLOR)
            colored = true;

        i += len;
    }
}

int ProcessTextTag(LPCHARACTER ch, const char * c_pszText, size_t len)
{
    return 0; // Disable Glass
    //2012.05.17 김용욱
    //0 : 정상적으로 사용
    //1 : 금강경 부족
    //2 : 금강경이 있으나, 개인상점에서 사용중
    //3 : 교환중
    //4 : 에러
    int hyperlinks;
    bool colored;
  
    GetTextTagInfo(c_pszText, len, hyperlinks, colored);

    if (colored == true && hyperlinks == 0)
        return 4;

    if (ch->GetExchange())
    {
        if (hyperlinks == 0)
            return 0;
        else
            return 3;
    }

    int nPrismCount = ch->CountSpecifyItem(ITEM_PRISM);

    if (nPrismCount < hyperlinks)
        return 0;


    if (!ch->GetMyShop())
    {
        ch->RemoveSpecifyItem(ITEM_PRISM, hyperlinks);
        return 0;
    } else
    {
        int sellingNumber = ch->GetMyShop()->GetNumberByVnum(ITEM_PRISM);
        if(nPrismCount - sellingNumber < hyperlinks)
        {
            return 2;
        } else
        {
            ch->RemoveSpecifyItem(ITEM_PRISM, hyperlinks);
            return 0;
        }
    }
  
    return 4;
}

int CInputMain::Whisper(LPCHARACTER ch, const char * data, size_t uiBytes)
{
    const TPacketCGWhisper* pinfo = reinterpret_cast<const TPacketCGWhisper*>(data);

    if (uiBytes < pinfo->wSize)
        return -1;

    int iExtraLen = pinfo->wSize - sizeof(TPacketCGWhisper);

    if (iExtraLen < 0)
    {
        sys_err("invalid packet length (len %d size %u buffer %u)", iExtraLen, pinfo->wSize, uiBytes);
        ch->GetDesc()->SetPhase(PHASE_CLOSE);
        return -1;
    }

    if (ch->FindAffect(AFFECT_BLOCK_CHAT))
    {
        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("채팅 금지 상태입니다."));
        return (iExtraLen);
    }

    LPCHARACTER pkChr = CHARACTER_MANAGER::instance().FindPC(pinfo->szNameTo);

    if (pkChr == ch)
        return (iExtraLen);

    LPDESC pkDesc = NULL;

    BYTE bOpponentEmpire = 0;

    if (test_server)
    {
        if (!pkChr)
            sys_log(0, "Whisper to %s(%s) from %s", "Null", pinfo->szNameTo, ch->GetName());
        else
            sys_log(0, "Whisper to %s(%s) from %s", pkChr->GetName(), pinfo->szNameTo, ch->GetName());
    }
      
    if (ch->IsBlockMode(BLOCK_WHISPER))
    {
        if (ch->GetDesc())
        {
            TPacketGCWhisper pack;
            pack.bHeader = HEADER_GC_WHISPER;
            pack.bType = WHISPER_TYPE_SENDER_BLOCKED;
            pack.wSize = sizeof(TPacketGCWhisper);
            strlcpy(pack.szNameFrom, pinfo->szNameTo, sizeof(pack.szNameFrom));
            ch->GetDesc()->Packet(&pack, sizeof(pack));
        }
        return iExtraLen;
    }

    if (!pkChr)
    {
        CCI * pkCCI = P2P_MANAGER::instance().Find(pinfo->szNameTo);

        if (pkCCI)
        {
            pkDesc = pkCCI->pkDesc;
            pkDesc->SetRelay(pinfo->szNameTo);
            bOpponentEmpire = pkCCI->bEmpire;

            if (test_server)
                sys_log(0, "Whisper to %s from %s (Channel %d Mapindex %d)", "Null", ch->GetName(), pkCCI->bChannel, pkCCI->lMapIndex);
        }
    }
    else
    {
        pkDesc = pkChr->GetDesc();
        bOpponentEmpire = pkChr->GetEmpire();
    }

    if (!pkDesc)
    {
        if (ch->GetDesc())
        {
            TPacketGCWhisper pack;

            pack.bHeader = HEADER_GC_WHISPER;
            pack.bType = WHISPER_TYPE_NOT_EXIST;
            pack.wSize = sizeof(TPacketGCWhisper);
            strlcpy(pack.szNameFrom, pinfo->szNameTo, sizeof(pack.szNameFrom));
            ch->GetDesc()->Packet(&pack, sizeof(TPacketGCWhisper));
            sys_log(0, "WHISPER: no player");
        }
    }
    else
    {
        if (ch->IsBlockMode(BLOCK_WHISPER))
        {
            if (ch->GetDesc())
            {
                TPacketGCWhisper pack;
                pack.bHeader = HEADER_GC_WHISPER;
                pack.bType = WHISPER_TYPE_SENDER_BLOCKED;
                pack.wSize = sizeof(TPacketGCWhisper);
                strlcpy(pack.szNameFrom, pinfo->szNameTo, sizeof(pack.szNameFrom));
                ch->GetDesc()->Packet(&pack, sizeof(pack));
            }
        }
        else if (pkChr && pkChr->IsBlockMode(BLOCK_WHISPER))
        {
            if (ch->GetDesc())
            {
                TPacketGCWhisper pack;
                pack.bHeader = HEADER_GC_WHISPER;
                pack.bType = WHISPER_TYPE_TARGET_BLOCKED;
                pack.wSize = sizeof(TPacketGCWhisper);
                strlcpy(pack.szNameFrom, pinfo->szNameTo, sizeof(pack.szNameFrom));
                ch->GetDesc()->Packet(&pack, sizeof(pack));
            }
        }
        else
        {
            BYTE bType = WHISPER_TYPE_NORMAL;

            char buf[CHAT_MAX_LEN + 1];
            strlcpy(buf, data + sizeof(TPacketCGWhisper), MIN(iExtraLen + 1, sizeof(buf)));
            const size_t buflen = strlen(buf);

            if (true == SpamBlockCheck(ch, buf, buflen))
            {
                if (!pkChr)
                {
                    CCI * pkCCI = P2P_MANAGER::instance().Find(pinfo->szNameTo);

                    if (pkCCI)
                    {
                        pkDesc->SetRelay("");
                    }
                }
                return iExtraLen;
            }

            if (LC_IsCanada() == false)
            {
                CBanwordManager::instance().ConvertString(buf, buflen);
            }

            if (g_bEmpireWhisper)
                if (!ch->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE))
                    if (!(pkChr && pkChr->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE)))
                        if (bOpponentEmpire != ch->GetEmpire() && ch->GetEmpire() && bOpponentEmpire // 서로 제국이 다르면서
                                && ch->GetGMLevel() == GM_PLAYER && gm_get_level(pinfo->szNameTo) == GM_PLAYER) // 둘다 일반 플레이어이면
                            // 이름 밖에 모르니 gm_get_level 함수를 사용
                        {
                            if (!pkChr)
                            {
                                // 다른 서버에 있으니 제국 표시만 한다. bType의 상위 4비트를 Empire번호로 사용한다.
                                bType = ch->GetEmpire() << 4;
                            }
                            else
                            {
                                ConvertEmpireText(ch->GetEmpire(), buf, buflen, 10 + 2 * pkChr->GetSkillPower(SKILL_LANGUAGE1 + ch->GetEmpire() - 1)/*변환확률*/);
                            }
                        }

            int processReturn = ProcessTextTag(ch, buf, buflen);
            if (0!=processReturn)
            {
                if (ch->GetDesc())
                {
                    TItemTable * pTable = ITEM_MANAGER::instance().GetTable(ITEM_PRISM);

                    if (pTable)
                    {
                        char buf[128];
                        int len;
                        if (3==processReturn) //교환중
                            len = snprintf(buf, sizeof(buf), LC_TEXT("다른 거래중(창고,교환,상점)에는 개인상점을 사용할 수 없습니다."), pTable->szLocaleName);
                        else
                            len = snprintf(buf, sizeof(buf), LC_TEXT("%s이 필요합니다."), pTable->szLocaleName);
                      

                        if (len < 0 || len >= (int) sizeof(buf))
                            len = sizeof(buf) - 1;

                        ++len;  // \0 문자 포함

                        TPacketGCWhisper pack;

                        pack.bHeader = HEADER_GC_WHISPER;
                        pack.bType = WHISPER_TYPE_ERROR;
                        pack.wSize = sizeof(TPacketGCWhisper) + len;
                        strlcpy(pack.szNameFrom, pinfo->szNameTo, sizeof(pack.szNameFrom));

                        ch->GetDesc()->BufferedPacket(&pack, sizeof(pack));
                        ch->GetDesc()->Packet(buf, len);

                        sys_log(0, "WHISPER: not enough %s: char: %s", pTable->szLocaleName, ch->GetName());
                    }
                }

                // 릴래이 상태일 수 있으므로 릴래이를 풀어준다.
                pkDesc->SetRelay("");
                return (iExtraLen);
            }

            if (ch->IsGM())
                bType = (bType & 0xF0) | WHISPER_TYPE_GM;

            if (buflen > 0)
            {
                TPacketGCWhisper pack;

                pack.bHeader = HEADER_GC_WHISPER;
                pack.wSize = sizeof(TPacketGCWhisper) + buflen;
                pack.bType = bType;
                strlcpy(pack.szNameFrom, ch->GetName(), sizeof(pack.szNameFrom));

                // desc->BufferedPacket을 하지 않고 버퍼에 써야하는 이유는
                // P2P relay되어 패킷이 캡슐화 될 수 있기 때문이다.
                TEMP_BUFFER tmpbuf;

                tmpbuf.write(&pack, sizeof(pack));
                tmpbuf.write(buf, buflen);

                pkDesc->Packet(tmpbuf.read_peek(), tmpbuf.size());

                if (LC_IsEurope() != true)
                {
                    sys_log(0, "WHISPER: %s -> %s : %s", ch->GetName(), pinfo->szNameTo, buf);
                }
            }
        }
    }
    if(pkDesc)
        pkDesc->SetRelay("");

    return (iExtraLen);
}

struct RawPacketToCharacterFunc
{
    const void * m_buf;
    int    m_buf_len;

    RawPacketToCharacterFunc(const void * buf, int buf_len) : m_buf(buf), m_buf_len(buf_len)
    {
    }

    void operator () (LPCHARACTER c)
    {
        if (!c->GetDesc())
            return;

        c->GetDesc()->Packet(m_buf, m_buf_len);
    }
};

struct FEmpireChatPacket
{
    packet_chat& p;
    const char* orig_msg;
    int orig_len;
    char converted_msg[CHAT_MAX_LEN+1];

    BYTE bEmpire;
    int iMapIndex;
    int namelen;

    FEmpireChatPacket(packet_chat& p, const char* chat_msg, int len, BYTE bEmpire, int iMapIndex, int iNameLen)
        : p(p), orig_msg(chat_msg), orig_len(len), bEmpire(bEmpire), iMapIndex(iMapIndex), namelen(iNameLen)
    {
        memset( converted_msg, 0, sizeof(converted_msg) );
    }

    void operator () (LPDESC d)
    {
        if (!d->GetCharacter())
            return;

        if (d->GetCharacter()->GetMapIndex() != iMapIndex)
            return;

        d->BufferedPacket(&p, sizeof(packet_chat));

        if (d->GetEmpire() == bEmpire ||
            bEmpire == 0 ||
            d->GetCharacter()->GetGMLevel() > GM_PLAYER ||
            d->GetCharacter()->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE))
        {
            d->Packet(orig_msg, orig_len);
        }
        else
        {
            // 사람마다 스킬레벨이 다르니 매번 해야합니다
            size_t len = strlcpy(converted_msg, orig_msg, sizeof(converted_msg));

            if (len >= sizeof(converted_msg))
                len = sizeof(converted_msg) - 1;

            ConvertEmpireText(bEmpire, converted_msg + namelen, len - namelen, 10 + 2 * d->GetCharacter()->GetSkillPower(SKILL_LANGUAGE1 + bEmpire - 1));
            d->Packet(converted_msg, orig_len);
        }
    }
};

struct FYmirChatPacket
{
    packet_chat& packet;
    const char* m_szChat;
    size_t m_lenChat;
    const char* m_szName;
  
    int m_iMapIndex;
    BYTE m_bEmpire;
    bool m_ring;

    char m_orig_msg[CHAT_MAX_LEN+1];
    int m_len_orig_msg;
    char m_conv_msg[CHAT_MAX_LEN+1];
    int m_len_conv_msg;

    FYmirChatPacket(packet_chat& p, const char* chat, size_t len_chat, const char* name, size_t len_name, int iMapIndex, BYTE empire, bool ring)
        : packet(p),
        m_szChat(chat), m_lenChat(len_chat),
        m_szName(name),
        m_iMapIndex(iMapIndex), m_bEmpire(empire),
        m_ring(ring)
    {
        m_len_orig_msg = snprintf(m_orig_msg, sizeof(m_orig_msg), "%s : %s", m_szName, m_szChat) + 1; // 널 문자 포함

        if (m_len_orig_msg < 0 || m_len_orig_msg >= (int) sizeof(m_orig_msg))
            m_len_orig_msg = sizeof(m_orig_msg) - 1;

        m_len_conv_msg = snprintf(m_conv_msg, sizeof(m_conv_msg), "??? : %s", m_szChat) + 1; // 널 문자 미포함

        if (m_len_conv_msg < 0 || m_len_conv_msg >= (int) sizeof(m_conv_msg))
            m_len_conv_msg = sizeof(m_conv_msg) - 1;

        ConvertEmpireText(m_bEmpire, m_conv_msg + 6, m_len_conv_msg - 6, 10); // 6은 "??? : "의 길이
    }

    void operator() (LPDESC d)
    {
        if (!d->GetCharacter())
            return;

        if (d->GetCharacter()->GetMapIndex() != m_iMapIndex)
            return;

        if (m_ring ||
            d->GetEmpire() == m_bEmpire ||
            d->GetCharacter()->GetGMLevel() > GM_PLAYER ||
            d->GetCharacter()->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE))
        {
            packet.size = m_len_orig_msg + sizeof(TPacketGCChat);

            d->BufferedPacket(&packet, sizeof(packet_chat));
            d->Packet(m_orig_msg, m_len_orig_msg);
        }
        else
        {
            packet.size = m_len_conv_msg + sizeof(TPacketGCChat);

            d->BufferedPacket(&packet, sizeof(packet_chat));
            d->Packet(m_conv_msg, m_len_conv_msg);
        }
    }
};

int CInputMain::Chat(LPCHARACTER ch, const char * data, size_t uiBytes)
{
    const TPacketCGChat* pinfo = reinterpret_cast<const TPacketCGChat*>(data);

    if (uiBytes < pinfo->size)
        return -1;

    const int iExtraLen = pinfo->size - sizeof(TPacketCGChat);

    if (iExtraLen < 0)
    {
        sys_err("invalid packet length (len %d size %u buffer %u)", iExtraLen, pinfo->size, uiBytes);
        ch->GetDesc()->SetPhase(PHASE_CLOSE);
        return -1;
    }

    char buf[CHAT_MAX_LEN - (CHARACTER_NAME_MAX_LEN + 3) + 1];
    strlcpy(buf, data + sizeof(TPacketCGChat), MIN(iExtraLen + 1, sizeof(buf)));
    const size_t buflen = strlen(buf);

    if (buflen > 1 && *buf == '/')
    {
        interpret_command(ch, buf + 1, buflen - 1);
        return iExtraLen;
    }

    if (ch->IncreaseChatCounter() >= 10)
    {
        if (ch->GetChatCounter() == 10)
        {
            sys_log(0, "CHAT_HACK: %s", ch->GetName());
            ch->GetDesc()->DelayedDisconnect(5);
        }

        return iExtraLen;
    }

    // 채팅 금지 Affect 처리
    const CAffect* pAffect = ch->FindAffect(AFFECT_BLOCK_CHAT);

    if (pAffect != NULL)
    {
        SendBlockChatInfo(ch, pAffect->lDuration);
        return iExtraLen;
    }

    if (true == SpamBlockCheck(ch, buf, buflen))
    {
        return iExtraLen;
    }

    char chatbuf[CHAT_MAX_LEN + 1];
    int len = snprintf(chatbuf, sizeof(chatbuf), "%s : %s", ch->GetName(), buf);

    if (CHAT_TYPE_SHOUT == pinfo->type)
    {
        LogManager::instance().ShoutLog(g_bChannel, ch->GetEmpire(), chatbuf);
    }

    if (LC_IsCanada() == false)
    {
        CBanwordManager::instance().ConvertString(buf, buflen);
    }

    if (len < 0 || len >= (int) sizeof(chatbuf))
        len = sizeof(chatbuf) - 1;

    int processReturn = ProcessTextTag(ch, chatbuf, len);
    if (0!=processReturn)
    {
        const TItemTable* pTable = ITEM_MANAGER::instance().GetTable(ITEM_PRISM);

        if (NULL != pTable)
        {
            if (3==processReturn) //교환중
                ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("다른 거래중(창고,교환,상점)에는 개인상점을 사용할 수 없습니다."), pTable->szLocaleName);
            else
                ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s이 필요합니다."), pTable->szLocaleName);
                      
        }

        return iExtraLen;
    }

    if (pinfo->type == CHAT_TYPE_SHOUT)
    {
        const int SHOUT_LIMIT_LEVEL = g_iUseLocale ? 15 : 3;

        if (ch->GetLevel() < SHOUT_LIMIT_LEVEL)
        {
            ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("외치기는 레벨 %d 이상만 사용 가능 합니다."), SHOUT_LIMIT_LEVEL);
            return (iExtraLen);
        }

        if (thecore_heart->pulse - (int) ch->GetLastShoutPulse() < passes_per_sec * 15)
            return (iExtraLen);

        ch->SetLastShoutPulse(thecore_heart->pulse);

        TPacketGGShout p;

        p.bHeader = HEADER_GG_SHOUT;
        p.bEmpire = ch->GetEmpire();
        strlcpy(p.szText, chatbuf, sizeof(p.szText));

        P2P_MANAGER::instance().Send(&p, sizeof(TPacketGGShout));

        SendShout(chatbuf, ch->GetEmpire());

        return (iExtraLen);
    }

    TPacketGCChat pack_chat;

    pack_chat.header = HEADER_GC_CHAT;
    pack_chat.size = sizeof(TPacketGCChat) + len;
    pack_chat.type = pinfo->type;
    pack_chat.id = ch->GetVID();

    switch (pinfo->type)
    {
        case CHAT_TYPE_TALKING:
            {
                const DESC_MANAGER::DESC_SET & c_ref_set = DESC_MANAGER::instance().GetClientSet();

                if (false)
                {
                    std::for_each(c_ref_set.begin(), c_ref_set.end(),
                            FYmirChatPacket(pack_chat,
                                buf,
                                strlen(buf),
                                ch->GetName(),
                                strlen(ch->GetName()),
                                ch->GetMapIndex(),
                                ch->GetEmpire(),
                                ch->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE)));
                }
                else
                {
                    std::for_each(c_ref_set.begin(), c_ref_set.end(),
                            FEmpireChatPacket(pack_chat,
                                chatbuf,
                                len,
                                (ch->GetGMLevel() > GM_PLAYER ||
                                 ch->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE)) ? 0 : ch->GetEmpire(),
                                ch->GetMapIndex(), strlen(ch->GetName())));
                }
            }
            break;

        case CHAT_TYPE_PARTY:
            {
                if (!ch->GetParty())
                    ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("파티 중이 아닙니다."));
                else
                {
                    TEMP_BUFFER tbuf;
                  
                    tbuf.write(&pack_chat, sizeof(pack_chat));
                    tbuf.write(chatbuf, len);

                    RawPacketToCharacterFunc f(tbuf.read_peek(), tbuf.size());
                    ch->GetParty()->ForEachOnlineMember(f);
                }
            }
            break;

        case CHAT_TYPE_GUILD:
            {
                if (!ch->GetGuild())
                    ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("길드에 가입하지 않았습니다."));
                else
                    ch->GetGuild()->Chat(chatbuf);
            }
            break;

        default:
            sys_err("Unknown chat type %d", pinfo->type);
            break;
    }

    return (iExtraLen);
}

void CInputMain::ItemUse(LPCHARACTER ch, const char * data)
{
    ch->UseItem(((struct command_item_use *) data)->Cell);
}

void CInputMain::ItemToItem(LPCHARACTER ch, const char * pcData)
{
    TPacketCGItemUseToItem * p = (TPacketCGItemUseToItem *) pcData;
    if (ch)
        ch->UseItem(p->Cell, p->TargetCell);
}

void CInputMain::ItemDrop(LPCHARACTER ch, const char * data)
{
    struct command_item_drop * pinfo = (struct command_item_drop *) data;

    //MONARCH_LIMIT
    //if (ch->IsMonarch())  
    //    return;
    //END_MONARCH_LIMIT
    if (!ch)
        return;

    // 엘크가 0보다 크면 엘크를 버리는 것 이다.
    if (pinfo->gold > 0)
        ch->DropGold(pinfo->gold);
    else
        ch->DropItem(pinfo->Cell);
}

void CInputMain::ItemDrop2(LPCHARACTER ch, const char * data)
{
    //MONARCH_LIMIT
    //if (ch->IsMonarch())  
    //    return;
    //END_MONARCH_LIMIT

    TPacketCGItemDrop2 * pinfo = (TPacketCGItemDrop2 *) data;

    // 엘크가 0보다 크면 엘크를 버리는 것 이다.
  
    if (!ch)
        return;
    if (pinfo->gold > 0)
        ch->DropGold(pinfo->gold);
    else
        ch->DropItem(pinfo->Cell, pinfo->count);
}

void CInputMain::ItemMove(LPCHARACTER ch, const char * data)
{
    struct command_item_move * pinfo = (struct command_item_move *) data;

    if (ch)
        ch->MoveItem(pinfo->Cell, pinfo->CellTo, pinfo->count);
}

void CInputMain::ItemPickup(LPCHARACTER ch, const char * data)
{
    struct command_item_pickup * pinfo = (struct command_item_pickup*) data;
    if (ch)
        ch->PickupItem(pinfo->vid);
}

void CInputMain::QuickslotAdd(LPCHARACTER ch, const char * data)
{
    struct command_quickslot_add * pinfo = (struct command_quickslot_add *) data;
    if(pinfo->slot.type == QUICKSLOT_TYPE_ITEM)
    {
        LPITEM item = NULL;
        TItemPos srcCell(INVENTORY, pinfo->slot.pos);
        if (!(item = ch->GetItem(srcCell)))
            return;
        if (item->GetType() != ITEM_USE && item->GetType() != ITEM_QUEST)
            return;
    }

    ch->SetQuickslot(pinfo->pos, pinfo->slot);
}

void CInputMain::QuickslotDelete(LPCHARACTER ch, const char * data)
{
    struct command_quickslot_del * pinfo = (struct command_quickslot_del *) data;
    ch->DelQuickslot(pinfo->pos);
}

void CInputMain::QuickslotSwap(LPCHARACTER ch, const char * data)
{
    struct command_quickslot_swap * pinfo = (struct command_quickslot_swap *) data;
    ch->SwapQuickslot(pinfo->pos, pinfo->change_pos);
}

int CInputMain::Messenger(LPCHARACTER ch, const char* c_pData, size_t uiBytes)
{
    TPacketCGMessenger* p = (TPacketCGMessenger*) c_pData;
  
    if (uiBytes < sizeof(TPacketCGMessenger))
        return -1;

    c_pData += sizeof(TPacketCGMessenger);
    uiBytes -= sizeof(TPacketCGMessenger);

    switch (p->subheader)
    {
        case MESSENGER_SUBHEADER_CG_ADD_BY_VID:
            {
                if (uiBytes < sizeof(TPacketCGMessengerAddByVID))
                    return -1;

                TPacketCGMessengerAddByVID * p2 = (TPacketCGMessengerAddByVID *) c_pData;
                LPCHARACTER ch_companion = CHARACTER_MANAGER::instance().Find(p2->vid);

                if (!ch_companion)
                    return sizeof(TPacketCGMessengerAddByVID);

                if (ch->IsObserverMode())
                    return sizeof(TPacketCGMessengerAddByVID);

                if (ch_companion->IsBlockMode(BLOCK_MESSENGER_INVITE))
                {
                    ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상대방이 메신져 추가 거부 상태입니다."));
                    return sizeof(TPacketCGMessengerAddByVID);
                }

                LPDESC d = ch_companion->GetDesc();

                if (!d)
                    return sizeof(TPacketCGMessengerAddByVID);

                if (ch->GetGMLevel() == GM_PLAYER && ch_companion->GetGMLevel() != GM_PLAYER)
                {
                    ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<메신져> 운영자는 메신져에 추가할 수 없습니다."));
                    return sizeof(TPacketCGMessengerAddByVID);
                }

                if (ch->GetDesc() == d) // 자신은 추가할 수 없다.
                    return sizeof(TPacketCGMessengerAddByVID);

                MessengerManager::instance().RequestToAdd(ch, ch_companion);
                //MessengerManager::instance().AddToList(ch->GetName(), ch_companion->GetName());
            }
            return sizeof(TPacketCGMessengerAddByVID);

        case MESSENGER_SUBHEADER_CG_ADD_BY_NAME:
            {
                if (uiBytes < CHARACTER_NAME_MAX_LEN)
                    return -1;

                char name[CHARACTER_NAME_MAX_LEN + 1];
                strlcpy(name, c_pData, sizeof(name));

                if (ch->GetGMLevel() == GM_PLAYER && gm_get_level(name) != GM_PLAYER)
                {
                    ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<메신져> 운영자는 메신져에 추가할 수 없습니다."));
                    return CHARACTER_NAME_MAX_LEN;
                }

                LPCHARACTER tch = CHARACTER_MANAGER::instance().FindPC(name);

                if (!tch)
                    ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s 님은 접속되 있지 않습니다."), name);
                else
                {
                    if (tch == ch) // 자신은 추가할 수 없다.
                        return CHARACTER_NAME_MAX_LEN;

                    if (tch->IsBlockMode(BLOCK_MESSENGER_INVITE) == true)
                    {
                        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상대방이 메신져 추가 거부 상태입니다."));
                    }
                    else
                    {
                        // 메신저가 캐릭터단위가 되면서 변경
                        MessengerManager::instance().RequestToAdd(ch, tch);
                        //MessengerManager::instance().AddToList(ch->GetName(), tch->GetName());
                    }
                }
            }
            return CHARACTER_NAME_MAX_LEN;

        case MESSENGER_SUBHEADER_CG_REMOVE:
            {
                if (uiBytes < CHARACTER_NAME_MAX_LEN)
                    return -1;

                char char_name[CHARACTER_NAME_MAX_LEN + 1];
                strlcpy(char_name, c_pData, sizeof(char_name));
                MessengerManager::instance().RemoveFromList(ch->GetName(), char_name);
                MessengerManager::instance().RemoveFromList(char_name, ch->GetName());//friend removed from companion too.
            }
            return CHARACTER_NAME_MAX_LEN;

        default:
            sys_err("CInputMain::Messenger : Unknown subheader %d : %s", p->subheader, ch->GetName());
            break;
    }

    return 0;
}

int CInputMain::Shop(LPCHARACTER ch, const char * data, size_t uiBytes)
{
    TPacketCGShop * p = (TPacketCGShop *) data;

    if (uiBytes < sizeof(TPacketCGShop))
        return -1;

    if (test_server)
        sys_log(0, "CInputMain::Shop() ==> SubHeader %d", p->subheader);

    const char * c_pData = data + sizeof(TPacketCGShop);
    uiBytes -= sizeof(TPacketCGShop);

    switch (p->subheader)
    {
        case SHOP_SUBHEADER_CG_END:
            sys_log(1, "INPUT: %s SHOP: END", ch->GetName());
            CShopManager::instance().StopShopping(ch);
            return 0;

        case SHOP_SUBHEADER_CG_BUY:
            {
                if (uiBytes < sizeof(BYTE) + sizeof(BYTE))
                    return -1;

                BYTE bPos = *(c_pData + 1);
                sys_log(1, "INPUT: %s SHOP: BUY %d", ch->GetName(), bPos);
                CShopManager::instance().Buy(ch, bPos);
                return (sizeof(BYTE) + sizeof(BYTE));
            }

        case SHOP_SUBHEADER_CG_SELL:
            {
                if (uiBytes < sizeof(BYTE))
                    return -1;

                BYTE pos = *c_pData;

                sys_log(0, "INPUT: %s SHOP: SELL", ch->GetName());
                CShopManager::instance().Sell(ch, pos);
                return sizeof(BYTE);
            }

#ifdef UK_ENABLE_SPECIAL_STORAGE
        case SHOP_SUBHEADER_CG_SELL2:
            {
                if (uiBytes < sizeof(BYTE) + sizeof(BYTE) + sizeof(BYTE))
                    return -1;

                const BYTE wPos = *reinterpret_cast<const BYTE*>(c_pData);
                const BYTE bCount = *(c_pData + sizeof(BYTE));
                const BYTE bType = *(c_pData + sizeof(BYTE) + sizeof(BYTE));

                sys_log(0, "INPUT: %s SHOP: SELL2", ch->GetName());

                CShopManager::instance().Sell(ch, wPos, bCount, bType);
                return sizeof(BYTE) + sizeof(BYTE) + sizeof(BYTE);
            }
#else
        case SHOP_SUBHEADER_CG_SELL2:
            {
                if (uiBytes < sizeof(BYTE) + sizeof(BYTE))
                    return -1;

                BYTE pos = *(c_pData++);
                BYTE count = *(c_pData);

                sys_log(0, "INPUT: %s SHOP: SELL2", ch->GetName());
                CShopManager::instance().Sell(ch, pos, count);
                return sizeof(BYTE) + sizeof(BYTE);
            }
#endif

        default:
            sys_err("CInputMain::Shop : Unknown subheader %d : %s", p->subheader, ch->GetName());
            break;
    }

    return 0;
}

void CInputMain::OnClick(LPCHARACTER ch, const char * data)
{
    struct command_on_click *    pinfo = (struct command_on_click *) data;
    LPCHARACTER            victim;

    if ((victim = CHARACTER_MANAGER::instance().Find(pinfo->vid)))
        victim->OnClick(ch);
    else if (test_server)
    {
        sys_err("CInputMain::OnClick %s.Click.NOT_EXIST_VID[%d]", ch->GetName(), pinfo->vid);
    }
}

void CInputMain::Exchange(LPCHARACTER ch, const char * data)
{
    struct command_exchange * pinfo = (struct command_exchange *) data;
    LPCHARACTER    to_ch = NULL;

    if (!ch->CanHandleItem())
        return;

    int iPulse = thecore_pulse();
  
    if ((to_ch = CHARACTER_MANAGER::instance().Find(pinfo->arg1)))
    {
        if (iPulse - to_ch->GetSafeboxLoadTime() < PASSES_PER_SEC(g_nPortalLimitTime))
        {
            to_ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("거래 후 %d초 이내에 창고를 열수 없습니다."), g_nPortalLimitTime);
            return;
        }

        if( true == to_ch->IsDead() )
        {
            return;
        }
    }

    sys_log(0, "CInputMain()::Exchange()  SubHeader %d ", pinfo->sub_header);

    if (iPulse - ch->GetSafeboxLoadTime() < PASSES_PER_SEC(g_nPortalLimitTime))
    {
        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("거래 후 %d초 이내에 창고를 열수 없습니다."), g_nPortalLimitTime);
        return;
    }


    switch (pinfo->sub_header)
    {
        case EXCHANGE_SUBHEADER_CG_START:    // arg1 == vid of target character
            if (!ch->GetExchange())
            {
                if ((to_ch = CHARACTER_MANAGER::instance().Find(pinfo->arg1)))
                {
                    //MONARCH_LIMIT
                    /*
                    if (to_ch->IsMonarch() || ch->IsMonarch())
                    {
                        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("군주와는 거래를 할수가 없습니다"), g_nPortalLimitTime);
                        return;
                    }
                    //END_MONARCH_LIMIT
                    */
                    if (iPulse - ch->GetSafeboxLoadTime() < PASSES_PER_SEC(g_nPortalLimitTime))
                    {
                        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("창고를 연후 %d초 이내에는 거래를 할수 없습니다."), g_nPortalLimitTime);

                        if (test_server)
                            ch->ChatPacket(CHAT_TYPE_INFO, "[TestOnly][Safebox]Pulse %d LoadTime %d PASS %d", iPulse, ch->GetSafeboxLoadTime(), PASSES_PER_SEC(g_nPortalLimitTime));
                        return;
                    }

                    if (iPulse - to_ch->GetSafeboxLoadTime() < PASSES_PER_SEC(g_nPortalLimitTime))
                    {
                        to_ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("창고를 연후 %d초 이내에는 거래를 할수 없습니다."), g_nPortalLimitTime);


                        if (test_server)
                            to_ch->ChatPacket(CHAT_TYPE_INFO, "[TestOnly][Safebox]Pulse %d LoadTime %d PASS %d", iPulse, to_ch->GetSafeboxLoadTime(), PASSES_PER_SEC(g_nPortalLimitTime));
                        return;
                    }

                    if (ch->GetGold() >= GOLD_MAX)
                    {  
                        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("액수가 20억 냥을 초과하여 거래를 할수가 없습니다.."));

                        sys_err("[OVERFLOG_GOLD] START (%u) id %u name %s ", ch->GetGold(), ch->GetPlayerID(), ch->GetName());
                        return;
                    }

                    if (to_ch->IsPC())
                    {
                        if (quest::CQuestManager::instance().GiveItemToPC(ch->GetPlayerID(), to_ch))
                        {
                            sys_log(0, "Exchange canceled by quest %s %s", ch->GetName(), to_ch->GetName());
                            return;
                        }
                    }


                    if (ch->GetMyShop() || ch->IsOpenSafebox() || ch->GetShopOwner() || ch->IsCubeOpen())
                    {
                        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("다른 거래중일경우 개인상점을 열수가 없습니다."));
                        return;
                    }

                    ch->ExchangeStart(to_ch);
                }
            }
            break;
 
Çözüm
Buyrun. :)
C++:
#include "constants.h"
#include "config.h"
#include "utils.h"
#include "desc_client.h"
#include "desc_manager.h"
#include "buffer_manager.h"
#include "packet.h"
#include "protocol.h"
#include "char.h"
#include "char_manager.h"
#include "item.h"
#include "item_manager.h"
#include "cmd.h"
#include "shop.h"
#include "shop_manager.h"
#include "safebox.h"
#include "regen.h"
#include "battle.h"
#include "exchange.h"
#include "questmanager.h"
#include "profiler.h"
#include "messenger_manager.h"
#include "party.h"
#include "p2p.h"
#include "affect.h"
#include "guild.h"
#include "guild_manager.h"
#include "log.h"
#include "banword.h"
#include "empire_text_convert.h"
#include "unique_item.h"
#include "building.h"
#include...
Buyrun. :)
C++:
#include "constants.h"
#include "config.h"
#include "utils.h"
#include "desc_client.h"
#include "desc_manager.h"
#include "buffer_manager.h"
#include "packet.h"
#include "protocol.h"
#include "char.h"
#include "char_manager.h"
#include "item.h"
#include "item_manager.h"
#include "cmd.h"
#include "shop.h"
#include "shop_manager.h"
#include "safebox.h"
#include "regen.h"
#include "battle.h"
#include "exchange.h"
#include "questmanager.h"
#include "profiler.h"
#include "messenger_manager.h"
#include "party.h"
#include "p2p.h"
#include "affect.h"
#include "guild.h"
#include "guild_manager.h"
#include "log.h"
#include "banword.h"
#include "empire_text_convert.h"
#include "unique_item.h"
#include "building.h"
#include "locale_service.h"
#include "gm.h"
#include "spam.h"
#include "ani.h"
#include "motion.h"
#include "OXEvent.h"
#include "locale_service.h"
#include "HackShield.h"
#include "XTrapManager.h"
#include "DragonSoul.h"
extern void SendShout(const char * szText, BYTE bEmpire);
extern int g_nPortalLimitTime;
static int __deposit_limit()
{
    return (1000*10000); // 1??
}
void SendBlockChatInfo(LPCHARACTER ch, int sec)
{
    if (sec <= 0)
    {
        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("?? ?? ?????."));
        return;
    }
    long hour = sec / 3600;
    sec -= hour * 3600;
    long min = (sec / 60);
    sec -= min * 60;
    char buf[128+1];
    if (hour > 0 && min > 0)
        snprintf(buf, sizeof(buf), LC_TEXT("%d ?? %d ? %d ? ?? ???? ?????"), hour, min, sec);
    else if (hour > 0 && min == 0)
        snprintf(buf, sizeof(buf), LC_TEXT("%d ?? %d ? ?? ???? ?????"), hour, sec);
    else if (hour == 0 && min > 0)
        snprintf(buf, sizeof(buf), LC_TEXT("%d ? %d ? ?? ???? ?????"), min, sec);
    else
        snprintf(buf, sizeof(buf), LC_TEXT("%d ? ?? ???? ?????"), sec);
    ch->ChatPacket(CHAT_TYPE_INFO, buf);
}
EVENTINFO(spam_event_info)
{
    char host[MAX_HOST_LENGTH+1];
    spam_event_info()
    {
        ::memset( host, 0, MAX_HOST_LENGTH+1 );
    }
};
typedef boost::unordered_map<std::string, std::pair<unsigned int, LPEVENT> > spam_score_of_ip_t;
spam_score_of_ip_t spam_score_of_ip;
EVENTFUNC(block_chat_by_ip_event)
{
    spam_event_info* info = dynamic_cast<spam_event_info*>( event->info );
    if ( info == NULL )
    {
        sys_err( "block_chat_by_ip_event> <Factor> Null pointer" );
        return 0;
    }
    const char * host = info->host;
    spam_score_of_ip_t::iterator it = spam_score_of_ip.find(host);
    if (it != spam_score_of_ip.end())
    {
        it->second.first = 0;
        it->second.second = NULL;
    }
    return 0;
}
bool SpamBlockCheck(LPCHARACTER ch, const char* const buf, const size_t buflen)
{
    extern int g_iSpamBlockMaxLevel;
    if (ch->GetLevel() < g_iSpamBlockMaxLevel)
    {
        spam_score_of_ip_t::iterator it = spam_score_of_ip.find(ch->GetDesc()->GetHostName());
        if (it == spam_score_of_ip.end())
        {
            spam_score_of_ip.insert(std::make_pair(ch->GetDesc()->GetHostName(), std::make_pair(0, (LPEVENT) NULL)));
            it = spam_score_of_ip.find(ch->GetDesc()->GetHostName());
        }
        if (it->second.second)
        {
            SendBlockChatInfo(ch, event_time(it->second.second) / passes_per_sec);
            return true;
        }
        unsigned int score;
        const char * word = SpamManager::instance().GetSpamScore(buf, buflen, score);
        it->second.first += score;
        if (word)
            sys_log(0, "SPAM_SCORE: %s text: %s score: %u total: %u word: %s", ch->GetName(), buf, score, it->second.first, word);
        extern unsigned int g_uiSpamBlockScore;
        extern unsigned int g_uiSpamBlockDuration;
        if (it->second.first >= g_uiSpamBlockScore)
        {
            spam_event_info* info = AllocEventInfo<spam_event_info>();
            strlcpy(info->host, ch->GetDesc()->GetHostName(), sizeof(info->host));
            it->second.second = event_create(block_chat_by_ip_event, info, PASSES_PER_SEC(g_uiSpamBlockDuration));
            sys_log(0, "SPAM_IP: %s for %u seconds", info->host, g_uiSpamBlockDuration);
            LogManager::instance().CharLog(ch, 0, "SPAM", word);
            SendBlockChatInfo(ch, event_time(it->second.second) / passes_per_sec);
            return true;
        }
    }
    return false;
}
enum
{
    TEXT_TAG_PLAIN,
    TEXT_TAG_TAG, // ||
    TEXT_TAG_COLOR, // |cffffffff
    TEXT_TAG_HYPERLINK_START, // |H
    TEXT_TAG_HYPERLINK_END, // |h ex) |Hitem:1234:1:1:1|h
    TEXT_TAG_RESTORE_COLOR,
};
int GetTextTag(const char * src, int maxLen, int & tagLen, std::string & extraInfo)
{
    tagLen = 1;
    if (maxLen < 2 || *src != '|')
        return TEXT_TAG_PLAIN;
    const char * cur = ++src;
    if (*cur == '|') // ||? |? ????.
    {
        tagLen = 2;
        return TEXT_TAG_TAG;
    }
    else if (*cur == 'c') // color |cffffffffblahblah|r
    {
        tagLen = 2;
        return TEXT_TAG_COLOR;
    }
    else if (*cur == 'H') // hyperlink |Hitem:10000:0:0:0:0|h[??]|h
    {
        tagLen = 2;
        return TEXT_TAG_HYPERLINK_START;
    }
    else if (*cur == 'h') // end of hyperlink
    {
        tagLen = 2;
        return TEXT_TAG_HYPERLINK_END;
    }
    return TEXT_TAG_PLAIN;
}
void GetTextTagInfo(const char * src, int src_len, int & hyperlinks, bool & colored)
{
    colored = false;
    hyperlinks = 0;
    int len;
    std::string extraInfo;
    for (int i = 0; i < src_len;)
    {
        int tag = GetTextTag(&src[i], src_len - i, len, extraInfo);
        if (tag == TEXT_TAG_HYPERLINK_START)
            ++hyperlinks;
        if (tag == TEXT_TAG_COLOR)
            colored = true;
        i += len;
    }
}
int ProcessTextTag(LPCHARACTER ch, const char * c_pszText, size_t len)
{
    return 0; // Disable Glass
    //2012.05.17 ???
    //0 : ????? ??
    //1 : ??? ??
    //2 : ???? ???, ?????? ???
    //3 : ???
    //4 : ??
    int hyperlinks;
    bool colored;
 
    GetTextTagInfo(c_pszText, len, hyperlinks, colored);
    if (colored == true && hyperlinks == 0)
        return 4;
    if (ch->GetExchange())
    {
        if (hyperlinks == 0)
            return 0;
        else
            return 3;
    }
    int nPrismCount = ch->CountSpecifyItem(ITEM_PRISM);
    if (nPrismCount < hyperlinks)
        return 0;
    if (!ch->GetMyShop())
    {
        ch->RemoveSpecifyItem(ITEM_PRISM, hyperlinks);
        return 0;
    } else
    {
        int sellingNumber = ch->GetMyShop()->GetNumberByVnum(ITEM_PRISM);
        if(nPrismCount - sellingNumber < hyperlinks)
        {
            return 2;
        } else
        {
            ch->RemoveSpecifyItem(ITEM_PRISM, hyperlinks);
            return 0;
        }
    }
 
    return 4;
}
int CInputMain::Whisper(LPCHARACTER ch, const char * data, size_t uiBytes)
{
    const TPacketCGWhisper* pinfo = reinterpret_cast<const TPacketCGWhisper*>(data);
    if (uiBytes < pinfo->wSize)
        return -1;
    int iExtraLen = pinfo->wSize - sizeof(TPacketCGWhisper);
    if (iExtraLen < 0)
    {
        sys_err("invalid packet length (len %d size %u buffer %u)", iExtraLen, pinfo->wSize, uiBytes);
        ch->GetDesc()->SetPhase(PHASE_CLOSE);
        return -1;
    }
    if (ch->FindAffect(AFFECT_BLOCK_CHAT))
    {
        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("?? ?? ?????."));
        return (iExtraLen);
    }
    LPCHARACTER pkChr = CHARACTER_MANAGER::instance().FindPC(pinfo->szNameTo);
    if (pkChr == ch)
        return (iExtraLen);
    LPDESC pkDesc = NULL;
    BYTE bOpponentEmpire = 0;
    if (test_server)
    {
        if (!pkChr)
            sys_log(0, "Whisper to %s(%s) from %s", "Null", pinfo->szNameTo, ch->GetName());
        else
            sys_log(0, "Whisper to %s(%s) from %s", pkChr->GetName(), pinfo->szNameTo, ch->GetName());
    }
     
    if (ch->IsBlockMode(BLOCK_WHISPER))
    {
        if (ch->GetDesc())
        {
            TPacketGCWhisper pack;
            pack.bHeader = HEADER_GC_WHISPER;
            pack.bType = WHISPER_TYPE_SENDER_BLOCKED;
            pack.wSize = sizeof(TPacketGCWhisper);
            strlcpy(pack.szNameFrom, pinfo->szNameTo, sizeof(pack.szNameFrom));
            ch->GetDesc()->Packet(&pack, sizeof(pack));
        }
        return iExtraLen;
    }
    if (!pkChr)
    {
        CCI * pkCCI = P2P_MANAGER::instance().Find(pinfo->szNameTo);
        if (pkCCI)
        {
            pkDesc = pkCCI->pkDesc;
            pkDesc->SetRelay(pinfo->szNameTo);
            bOpponentEmpire = pkCCI->bEmpire;
            if (test_server)
                sys_log(0, "Whisper to %s from %s (Channel %d Mapindex %d)", "Null", ch->GetName(), pkCCI->bChannel, pkCCI->lMapIndex);
        }
    }
    else
    {
        pkDesc = pkChr->GetDesc();
        bOpponentEmpire = pkChr->GetEmpire();
    }
    if (!pkDesc)
    {
        if (ch->GetDesc())
        {
            TPacketGCWhisper pack;
            pack.bHeader = HEADER_GC_WHISPER;
            pack.bType = WHISPER_TYPE_NOT_EXIST;
            pack.wSize = sizeof(TPacketGCWhisper);
            strlcpy(pack.szNameFrom, pinfo->szNameTo, sizeof(pack.szNameFrom));
            ch->GetDesc()->Packet(&pack, sizeof(TPacketGCWhisper));
            sys_log(0, "WHISPER: no player");
        }
    }
    else
    {
        if (ch->IsBlockMode(BLOCK_WHISPER))
        {
            if (ch->GetDesc())
            {
                TPacketGCWhisper pack;
                pack.bHeader = HEADER_GC_WHISPER;
                pack.bType = WHISPER_TYPE_SENDER_BLOCKED;
                pack.wSize = sizeof(TPacketGCWhisper);
                strlcpy(pack.szNameFrom, pinfo->szNameTo, sizeof(pack.szNameFrom));
                ch->GetDesc()->Packet(&pack, sizeof(pack));
            }
        }
        else if (pkChr && pkChr->IsBlockMode(BLOCK_WHISPER))
        {
            if (ch->GetDesc())
            {
                TPacketGCWhisper pack;
                pack.bHeader = HEADER_GC_WHISPER;
                pack.bType = WHISPER_TYPE_TARGET_BLOCKED;
                pack.wSize = sizeof(TPacketGCWhisper);
                strlcpy(pack.szNameFrom, pinfo->szNameTo, sizeof(pack.szNameFrom));
                ch->GetDesc()->Packet(&pack, sizeof(pack));
            }
        }
        else
        {
            BYTE bType = WHISPER_TYPE_NORMAL;
            char buf[CHAT_MAX_LEN + 1];
            strlcpy(buf, data + sizeof(TPacketCGWhisper), MIN(iExtraLen + 1, sizeof(buf)));
            const size_t buflen = strlen(buf);
            if (true == SpamBlockCheck(ch, buf, buflen))
            {
                if (!pkChr)
                {
                    CCI * pkCCI = P2P_MANAGER::instance().Find(pinfo->szNameTo);
                    if (pkCCI)
                    {
                        pkDesc->SetRelay("");
                    }
                }
                return iExtraLen;
            }
            if (LC_IsCanada() == false)
            {
                CBanwordManager::instance().ConvertString(buf, buflen);
            }
            if (g_bEmpireWhisper)
                if (!ch->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE))
                    if (!(pkChr && pkChr->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE)))
                        if (bOpponentEmpire != ch->GetEmpire() && ch->GetEmpire() && bOpponentEmpire // ?? ??? ????
                                && ch->GetGMLevel() == GM_PLAYER && gm_get_level(pinfo->szNameTo) == GM_PLAYER) // ?? ?? ??????
                            // ?? ?? ??? gm_get_level ??? ??
                        {
                            if (!pkChr)
                            {
                                // ?? ??? ??? ?? ??? ??. bType? ?? 4??? Empire??? ????.
                                bType = ch->GetEmpire() << 4;
                            }
                            else
                            {
                                ConvertEmpireText(ch->GetEmpire(), buf, buflen, 10 + 2 * pkChr->GetSkillPower(SKILL_LANGUAGE1 + ch->GetEmpire() - 1)/*????*/);
                            }
                        }
            int processReturn = ProcessTextTag(ch, buf, buflen);
            if (0!=processReturn)
            {
                if (ch->GetDesc())
                {
                    TItemTable * pTable = ITEM_MANAGER::instance().GetTable(ITEM_PRISM);
                    if (pTable)
                    {
                        char buf[128];
                        int len;
                        if (3==processReturn) //???
                            len = snprintf(buf, sizeof(buf), LC_TEXT("?? ???(??,??,??)?? ????? ??? ? ????."), pTable->szLocaleName);
                        else
                            len = snprintf(buf, sizeof(buf), LC_TEXT("%s? ?????."), pTable->szLocaleName);
                     
                        if (len < 0 || len >= (int) sizeof(buf))
                            len = sizeof(buf) - 1;
                        ++len;  // \0 ?? ??
                        TPacketGCWhisper pack;
                        pack.bHeader = HEADER_GC_WHISPER;
                        pack.bType = WHISPER_TYPE_ERROR;
                        pack.wSize = sizeof(TPacketGCWhisper) + len;
                        strlcpy(pack.szNameFrom, pinfo->szNameTo, sizeof(pack.szNameFrom));
                        ch->GetDesc()->BufferedPacket(&pack, sizeof(pack));
                        ch->GetDesc()->Packet(buf, len);
                        sys_log(0, "WHISPER: not enough %s: char: %s", pTable->szLocaleName, ch->GetName());
                    }
                }
                // ??? ??? ? ???? ???? ????.
                pkDesc->SetRelay("");
                return (iExtraLen);
            }
            if (ch->IsGM())
                bType = (bType & 0xF0) | WHISPER_TYPE_GM;
            if (buflen > 0)
            {
                TPacketGCWhisper pack;
                pack.bHeader = HEADER_GC_WHISPER;
                pack.wSize = sizeof(TPacketGCWhisper) + buflen;
                pack.bType = bType;
                strlcpy(pack.szNameFrom, ch->GetName(), sizeof(pack.szNameFrom));
                // desc->BufferedPacket? ?? ?? ??? ???? ???
                // P2P relay?? ??? ??? ? ? ?? ????.
                TEMP_BUFFER tmpbuf;
                tmpbuf.write(&pack, sizeof(pack));
                tmpbuf.write(buf, buflen);
                pkDesc->Packet(tmpbuf.read_peek(), tmpbuf.size());
                if (LC_IsEurope() != true)
                {
                    sys_log(0, "WHISPER: %s -> %s : %s", ch->GetName(), pinfo->szNameTo, buf);
                }
            }
        }
    }
    if(pkDesc)
        pkDesc->SetRelay("");
    return (iExtraLen);
}
struct RawPacketToCharacterFunc
{
    const void * m_buf;
    int    m_buf_len;
    RawPacketToCharacterFunc(const void * buf, int buf_len) : m_buf(buf), m_buf_len(buf_len)
    {
    }
    void operator () (LPCHARACTER c)
    {
        if (!c->GetDesc())
            return;
        c->GetDesc()->Packet(m_buf, m_buf_len);
    }
};
struct FEmpireChatPacket
{
    packet_chat& p;
    const char* orig_msg;
    int orig_len;
    char converted_msg[CHAT_MAX_LEN+1];
    BYTE bEmpire;
    int iMapIndex;
    int namelen;
    FEmpireChatPacket(packet_chat& p, const char* chat_msg, int len, BYTE bEmpire, int iMapIndex, int iNameLen)
        : p(p), orig_msg(chat_msg), orig_len(len), bEmpire(bEmpire), iMapIndex(iMapIndex), namelen(iNameLen)
    {
        memset( converted_msg, 0, sizeof(converted_msg) );
    }
    void operator () (LPDESC d)
    {
        if (!d->GetCharacter())
            return;
        if (d->GetCharacter()->GetMapIndex() != iMapIndex)
            return;
        d->BufferedPacket(&p, sizeof(packet_chat));
        if (d->GetEmpire() == bEmpire ||
            bEmpire == 0 ||
            d->GetCharacter()->GetGMLevel() > GM_PLAYER ||
            d->GetCharacter()->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE))
        {
            d->Packet(orig_msg, orig_len);
        }
        else
        {
            // ???? ????? ??? ?? ?????
            size_t len = strlcpy(converted_msg, orig_msg, sizeof(converted_msg));
            if (len >= sizeof(converted_msg))
                len = sizeof(converted_msg) - 1;
            ConvertEmpireText(bEmpire, converted_msg + namelen, len - namelen, 10 + 2 * d->GetCharacter()->GetSkillPower(SKILL_LANGUAGE1 + bEmpire - 1));
            d->Packet(converted_msg, orig_len);
        }
    }
};
struct FYmirChatPacket
{
    packet_chat& packet;
    const char* m_szChat;
    size_t m_lenChat;
    const char* m_szName;
 
    int m_iMapIndex;
    BYTE m_bEmpire;
    bool m_ring;
    char m_orig_msg[CHAT_MAX_LEN+1];
    int m_len_orig_msg;
    char m_conv_msg[CHAT_MAX_LEN+1];
    int m_len_conv_msg;
    FYmirChatPacket(packet_chat& p, const char* chat, size_t len_chat, const char* name, size_t len_name, int iMapIndex, BYTE empire, bool ring)
        : packet(p),
        m_szChat(chat), m_lenChat(len_chat),
        m_szName(name),
        m_iMapIndex(iMapIndex), m_bEmpire(empire),
        m_ring(ring)
    {
        m_len_orig_msg = snprintf(m_orig_msg, sizeof(m_orig_msg), "%s : %s", m_szName, m_szChat) + 1; // ? ?? ??
        if (m_len_orig_msg < 0 || m_len_orig_msg >= (int) sizeof(m_orig_msg))
            m_len_orig_msg = sizeof(m_orig_msg) - 1;
        m_len_conv_msg = snprintf(m_conv_msg, sizeof(m_conv_msg), "??? : %s", m_szChat) + 1; // ? ?? ???
        if (m_len_conv_msg < 0 || m_len_conv_msg >= (int) sizeof(m_conv_msg))
            m_len_conv_msg = sizeof(m_conv_msg) - 1;
        ConvertEmpireText(m_bEmpire, m_conv_msg + 6, m_len_conv_msg - 6, 10); // 6? "??? : "? ??
    }
    void operator() (LPDESC d)
    {
        if (!d->GetCharacter())
            return;
        if (d->GetCharacter()->GetMapIndex() != m_iMapIndex)
            return;
        if (m_ring ||
            d->GetEmpire() == m_bEmpire ||
            d->GetCharacter()->GetGMLevel() > GM_PLAYER ||
            d->GetCharacter()->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE))
        {
            packet.size = m_len_orig_msg + sizeof(TPacketGCChat);
            d->BufferedPacket(&packet, sizeof(packet_chat));
            d->Packet(m_orig_msg, m_len_orig_msg);
        }
        else
        {
            packet.size = m_len_conv_msg + sizeof(TPacketGCChat);
            d->BufferedPacket(&packet, sizeof(packet_chat));
            d->Packet(m_conv_msg, m_len_conv_msg);
        }
    }
};
int CInputMain::Chat(LPCHARACTER ch, const char * data, size_t uiBytes)
{
    const TPacketCGChat* pinfo = reinterpret_cast<const TPacketCGChat*>(data);
    if (uiBytes < pinfo->size)
        return -1;
    const int iExtraLen = pinfo->size - sizeof(TPacketCGChat);
    if (iExtraLen < 0)
    {
        sys_err("invalid packet length (len %d size %u buffer %u)", iExtraLen, pinfo->size, uiBytes);
        ch->GetDesc()->SetPhase(PHASE_CLOSE);
        return -1;
    }
    char buf[CHAT_MAX_LEN - (CHARACTER_NAME_MAX_LEN + 3) + 1];
    strlcpy(buf, data + sizeof(TPacketCGChat), MIN(iExtraLen + 1, sizeof(buf)));
    const size_t buflen = strlen(buf);
    if (buflen > 1 && *buf == '/')
    {
        interpret_command(ch, buf + 1, buflen - 1);
        return iExtraLen;
    }
    if (ch->IncreaseChatCounter() >= 10)
    {
        if (ch->GetChatCounter() == 10)
        {
            sys_log(0, "CHAT_HACK: %s", ch->GetName());
            ch->GetDesc()->DelayedDisconnect(5);
        }
        return iExtraLen;
    }
    // ?? ?? Affect ??
    const CAffect* pAffect = ch->FindAffect(AFFECT_BLOCK_CHAT);
    if (pAffect != NULL)
    {
        SendBlockChatInfo(ch, pAffect->lDuration);
        return iExtraLen;
    }
    if (true == SpamBlockCheck(ch, buf, buflen))
    {
        return iExtraLen;
    }
    char chatbuf[CHAT_MAX_LEN + 1];
    int len = snprintf(chatbuf, sizeof(chatbuf), "%s : %s", ch->GetName(), buf);
    if (CHAT_TYPE_SHOUT == pinfo->type)
    {
        LogManager::instance().ShoutLog(g_bChannel, ch->GetEmpire(), chatbuf);
    }
    if (LC_IsCanada() == false)
    {
        CBanwordManager::instance().ConvertString(buf, buflen);
    }
    if (len < 0 || len >= (int) sizeof(chatbuf))
        len = sizeof(chatbuf) - 1;
    int processReturn = ProcessTextTag(ch, chatbuf, len);
    if (0!=processReturn)
    {
        const TItemTable* pTable = ITEM_MANAGER::instance().GetTable(ITEM_PRISM);
        if (NULL != pTable)
        {
            if (3==processReturn) //???
                ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("?? ???(??,??,??)?? ????? ??? ? ????."), pTable->szLocaleName);
            else
                ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s? ?????."), pTable->szLocaleName);
                     
        }
        return iExtraLen;
    }
    if (pinfo->type == CHAT_TYPE_SHOUT)
    {
        const int SHOUT_LIMIT_LEVEL = g_iUseLocale ? 15 : 3;
        if (ch->GetLevel() < SHOUT_LIMIT_LEVEL)
        {
            ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("???? ?? %d ??? ?? ?? ???."), SHOUT_LIMIT_LEVEL);
            return (iExtraLen);
        }
        if (thecore_heart->pulse - (int) ch->GetLastShoutPulse() < passes_per_sec * 15)
            return (iExtraLen);
        ch->SetLastShoutPulse(thecore_heart->pulse);
        TPacketGGShout p;
        p.bHeader = HEADER_GG_SHOUT;
        p.bEmpire = ch->GetEmpire();
        strlcpy(p.szText, chatbuf, sizeof(p.szText));
        P2P_MANAGER::instance().Send(&p, sizeof(TPacketGGShout));
        SendShout(chatbuf, ch->GetEmpire());
        return (iExtraLen);
    }
    TPacketGCChat pack_chat;
    pack_chat.header = HEADER_GC_CHAT;
    pack_chat.size = sizeof(TPacketGCChat) + len;
    pack_chat.type = pinfo->type;
    pack_chat.id = ch->GetVID();
    switch (pinfo->type)
    {
        case CHAT_TYPE_TALKING:
            {
                const DESC_MANAGER::DESC_SET & c_ref_set = DESC_MANAGER::instance().GetClientSet();
                if (false)
                {
                    std::for_each(c_ref_set.begin(), c_ref_set.end(),
                            FYmirChatPacket(pack_chat,
                                buf,
                                strlen(buf),
                                ch->GetName(),
                                strlen(ch->GetName()),
                                ch->GetMapIndex(),
                                ch->GetEmpire(),
                                ch->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE)));
                }
                else
                {
                    std::for_each(c_ref_set.begin(), c_ref_set.end(),
                            FEmpireChatPacket(pack_chat,
                                chatbuf,
                                len,
                                (ch->GetGMLevel() > GM_PLAYER ||
                                 ch->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE)) ? 0 : ch->GetEmpire(),
                                ch->GetMapIndex(), strlen(ch->GetName())));
                }
            }
            break;
        case CHAT_TYPE_PARTY:
            {
                if (!ch->GetParty())
                    ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("?? ?? ????."));
                else
                {
                    TEMP_BUFFER tbuf;
                 
                    tbuf.write(&pack_chat, sizeof(pack_chat));
                    tbuf.write(chatbuf, len);
                    RawPacketToCharacterFunc f(tbuf.read_peek(), tbuf.size());
                    ch->GetParty()->ForEachOnlineMember(f);
                }
            }
            break;
        case CHAT_TYPE_GUILD:
            {
                if (!ch->GetGuild())
                    ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("??? ???? ?????."));
                else
                    ch->GetGuild()->Chat(chatbuf);
            }
            break;
        default:
            sys_err("Unknown chat type %d", pinfo->type);
            break;
    }
    return (iExtraLen);
}
void CInputMain::ItemUse(LPCHARACTER ch, const char * data)
{
    ch->UseItem(((struct command_item_use *) data)->Cell);
}
void CInputMain::ItemToItem(LPCHARACTER ch, const char * pcData)
{
    TPacketCGItemUseToItem * p = (TPacketCGItemUseToItem *) pcData;
    if (ch)
        ch->UseItem(p->Cell, p->TargetCell);
}
void CInputMain::ItemDrop(LPCHARACTER ch, const char * data)
{
    struct command_item_drop * pinfo = (struct command_item_drop *) data;
    //MONARCH_LIMIT
    //if (ch->IsMonarch())
    //    return;
    //END_MONARCH_LIMIT
    if (!ch)
        return;
    // ??? 0?? ?? ??? ??? ? ??.
    if (pinfo->gold > 0)
        ch->DropGold(pinfo->gold);
    else
        ch->DropItem(pinfo->Cell);
}
void CInputMain::ItemDrop2(LPCHARACTER ch, const char * data)
{
    //MONARCH_LIMIT
    //if (ch->IsMonarch())
    //    return;
    //END_MONARCH_LIMIT
    TPacketCGItemDrop2 * pinfo = (TPacketCGItemDrop2 *) data;
    // ??? 0?? ?? ??? ??? ? ??.
 
    if (!ch)
        return;
    if (pinfo->gold > 0)
        ch->DropGold(pinfo->gold);
    else
        ch->DropItem(pinfo->Cell, pinfo->count);
}
void CInputMain::ItemMove(LPCHARACTER ch, const char * data)
{
    struct command_item_move * pinfo = (struct command_item_move *) data;
    if (ch)
        ch->MoveItem(pinfo->Cell, pinfo->CellTo, pinfo->count);
}
void CInputMain::ItemPickup(LPCHARACTER ch, const char * data)
{
    struct command_item_pickup * pinfo = (struct command_item_pickup*) data;
    if (ch)
        ch->PickupItem(pinfo->vid);
}
void CInputMain::QuickslotAdd(LPCHARACTER ch, const char * data)
{
    struct command_quickslot_add * pinfo = (struct command_quickslot_add *) data;
    if(pinfo->slot.type == QUICKSLOT_TYPE_ITEM)
    {
        LPITEM item = NULL;
        TItemPos srcCell(INVENTORY, pinfo->slot.pos);
        if (!(item = ch->GetItem(srcCell)))
            return;
        if (item->GetType() != ITEM_USE && item->GetType() != ITEM_QUEST)
            return;
    }
    ch->SetQuickslot(pinfo->pos, pinfo->slot);
}
void CInputMain::QuickslotDelete(LPCHARACTER ch, const char * data)
{
    struct command_quickslot_del * pinfo = (struct command_quickslot_del *) data;
    ch->DelQuickslot(pinfo->pos);
}
void CInputMain::QuickslotSwap(LPCHARACTER ch, const char * data)
{
    struct command_quickslot_swap * pinfo = (struct command_quickslot_swap *) data;
    ch->SwapQuickslot(pinfo->pos, pinfo->change_pos);
}
int CInputMain::Messenger(LPCHARACTER ch, const char* c_pData, size_t uiBytes)
{
    TPacketCGMessenger* p = (TPacketCGMessenger*) c_pData;
 
    if (uiBytes < sizeof(TPacketCGMessenger))
        return -1;
    c_pData += sizeof(TPacketCGMessenger);
    uiBytes -= sizeof(TPacketCGMessenger);
    switch (p->subheader)
    {
        case MESSENGER_SUBHEADER_CG_ADD_BY_VID:
            {
                if (uiBytes < sizeof(TPacketCGMessengerAddByVID))
                    return -1;
                TPacketCGMessengerAddByVID * p2 = (TPacketCGMessengerAddByVID *) c_pData;
                LPCHARACTER ch_companion = CHARACTER_MANAGER::instance().Find(p2->vid);
                if (!ch_companion)
                    return sizeof(TPacketCGMessengerAddByVID);
                if (ch->IsObserverMode())
                    return sizeof(TPacketCGMessengerAddByVID);
                if (ch_companion->IsBlockMode(BLOCK_MESSENGER_INVITE))
                {
                    ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("???? ??? ?? ?? ?????."));
                    return sizeof(TPacketCGMessengerAddByVID);
                }
                LPDESC d = ch_companion->GetDesc();
                if (!d)
                    return sizeof(TPacketCGMessengerAddByVID);
                if (ch->GetGMLevel() == GM_PLAYER && ch_companion->GetGMLevel() != GM_PLAYER)
                {
                    ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<???> ???? ???? ??? ? ????."));
                    return sizeof(TPacketCGMessengerAddByVID);
                }
                if (ch->GetDesc() == d) // ??? ??? ? ??.
                    return sizeof(TPacketCGMessengerAddByVID);
                MessengerManager::instance().RequestToAdd(ch, ch_companion);
                //MessengerManager::instance().AddToList(ch->GetName(), ch_companion->GetName());
            }
            return sizeof(TPacketCGMessengerAddByVID);
        case MESSENGER_SUBHEADER_CG_ADD_BY_NAME:
            {
                if (uiBytes < CHARACTER_NAME_MAX_LEN)
                    return -1;
                char name[CHARACTER_NAME_MAX_LEN + 1];
                strlcpy(name, c_pData, sizeof(name));
                if (ch->GetGMLevel() == GM_PLAYER && gm_get_level(name) != GM_PLAYER)
                {
                    ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<???> ???? ???? ??? ? ????."));
                    return CHARACTER_NAME_MAX_LEN;
                }
                LPCHARACTER tch = CHARACTER_MANAGER::instance().FindPC(name);
                if (!tch)
                    ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s ?? ??? ?? ????."), name);
                else
                {
                    if (tch == ch) // ??? ??? ? ??.
                        return CHARACTER_NAME_MAX_LEN;
                    if (tch->IsBlockMode(BLOCK_MESSENGER_INVITE) == true)
                    {
                        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("???? ??? ?? ?? ?????."));
                    }
                    else
                    {
                        // ???? ?????? ??? ??
                        MessengerManager::instance().RequestToAdd(ch, tch);
                        //MessengerManager::instance().AddToList(ch->GetName(), tch->GetName());
                    }
                }
            }
            return CHARACTER_NAME_MAX_LEN;
        case MESSENGER_SUBHEADER_CG_REMOVE:
            {
                if (uiBytes < CHARACTER_NAME_MAX_LEN)
                    return -1;
                char char_name[CHARACTER_NAME_MAX_LEN + 1];
                strlcpy(char_name, c_pData, sizeof(char_name));
                MessengerManager::instance().RemoveFromList(ch->GetName(), char_name);
                MessengerManager::instance().RemoveFromList(char_name, ch->GetName());//friend removed from companion too.
            }
            return CHARACTER_NAME_MAX_LEN;
        default:
            sys_err("CInputMain::Messenger : Unknown subheader %d : %s", p->subheader, ch->GetName());
            break;
    }
    return 0;
}
int CInputMain::Shop(LPCHARACTER ch, const char * data, size_t uiBytes)
{
    TPacketCGShop * p = (TPacketCGShop *) data;
    if (uiBytes < sizeof(TPacketCGShop))
        return -1;
    if (test_server)
        sys_log(0, "CInputMain::Shop() ==> SubHeader %d", p->subheader);
    const char * c_pData = data + sizeof(TPacketCGShop);
    uiBytes -= sizeof(TPacketCGShop);
    switch (p->subheader)
    {
        case SHOP_SUBHEADER_CG_END:
            sys_log(1, "INPUT: %s SHOP: END", ch->GetName());
            CShopManager::instance().StopShopping(ch);
            return 0;
        case SHOP_SUBHEADER_CG_BUY:
            {
                if (uiBytes < sizeof(BYTE) + sizeof(BYTE))
                    return -1;
                BYTE bPos = *(c_pData + 1);
                sys_log(1, "INPUT: %s SHOP: BUY %d", ch->GetName(), bPos);
                CShopManager::instance().Buy(ch, bPos);
                return (sizeof(BYTE) + sizeof(BYTE));
            }
        case SHOP_SUBHEADER_CG_SELL:
            {
                if (uiBytes < sizeof(BYTE))
                    return -1;
                BYTE pos = *c_pData;
                sys_log(0, "INPUT: %s SHOP: SELL", ch->GetName());
                CShopManager::instance().Sell(ch, pos);
                return sizeof(BYTE);
            }
#ifdef UK_ENABLE_SPECIAL_STORAGE
        case SHOP_SUBHEADER_CG_SELL2:
            {
                if (uiBytes < sizeof(BYTE) + sizeof(BYTE) + sizeof(BYTE))
                    return -1;
                const BYTE wPos = *reinterpret_cast<const BYTE*>(c_pData);
                const BYTE bCount = *(c_pData + sizeof(BYTE));
                const BYTE bType = *(c_pData + sizeof(BYTE) + sizeof(BYTE));
                sys_log(0, "INPUT: %s SHOP: SELL2", ch->GetName());
                CShopManager::instance().Sell(ch, wPos, bCount, bType);
                return sizeof(BYTE) + sizeof(BYTE) + sizeof(BYTE);
            }
#else
        case SHOP_SUBHEADER_CG_SELL2:
            {
                if (uiBytes < sizeof(BYTE) + sizeof(BYTE))
                    return -1;
                BYTE pos = *(c_pData++);
                BYTE count = *(c_pData);
                sys_log(0, "INPUT: %s SHOP: SELL2", ch->GetName());
                CShopManager::instance().Sell(ch, pos, count);
                return sizeof(BYTE) + sizeof(BYTE);
            }
#endif
        default:
            sys_err("CInputMain::Shop : Unknown subheader %d : %s", p->subheader, ch->GetName());
            break;
    }
    return 0;
}
void CInputMain::OnClick(LPCHARACTER ch, const char * data)
{
    struct command_on_click *    pinfo = (struct command_on_click *) data;
    LPCHARACTER            victim;
    if ((victim = CHARACTER_MANAGER::instance().Find(pinfo->vid)))
        victim->OnClick(ch);
    else if (test_server)
    {
        sys_err("CInputMain::OnClick %s.Click.NOT_EXIST_VID[%d]", ch->GetName(), pinfo->vid);
    }
}
void CInputMain::Exchange(LPCHARACTER ch, const char * data)
{
    struct command_exchange * pinfo = (struct command_exchange *) data;
    LPCHARACTER    to_ch = NULL;
    if (!ch->CanHandleItem())
        return;
    int iPulse = thecore_pulse();
 
    if ((to_ch = CHARACTER_MANAGER::instance().Find(pinfo->arg1)))
    {
        if (iPulse - to_ch->GetSafeboxLoadTime() < PASSES_PER_SEC(g_nPortalLimitTime))
        {
            to_ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("?? ? %d? ??? ??? ?? ????."), g_nPortalLimitTime);
            return;
        }
        if( true == to_ch->IsDead() )
        {
            return;
        }
    }
    sys_log(0, "CInputMain()::Exchange()  SubHeader %d ", pinfo->sub_header);
    if (iPulse - ch->GetSafeboxLoadTime() < PASSES_PER_SEC(g_nPortalLimitTime))
    {
        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("?? ? %d? ??? ??? ?? ????."), g_nPortalLimitTime);
        return;
    }
    switch (pinfo->sub_header)
    {
        case EXCHANGE_SUBHEADER_CG_START:    // arg1 == vid of target character
            if (!ch->GetExchange())
            {
                if ((to_ch = CHARACTER_MANAGER::instance().Find(pinfo->arg1)))
                {
                    //MONARCH_LIMIT
                    /*
                    if (to_ch->IsMonarch() || ch->IsMonarch())
                    {
                        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("???? ??? ??? ????"), g_nPortalLimitTime);
                        return;
                    }
                    //END_MONARCH_LIMIT
                    */
                    if (iPulse - ch->GetSafeboxLoadTime() < PASSES_PER_SEC(g_nPortalLimitTime))
                    {
                        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("??? ?? %d? ???? ??? ?? ????."), g_nPortalLimitTime);
                        if (test_server)
                            ch->ChatPacket(CHAT_TYPE_INFO, "[TestOnly][Safebox]Pulse %d LoadTime %d PASS %d", iPulse, ch->GetSafeboxLoadTime(), PASSES_PER_SEC(g_nPortalLimitTime));
                        return;
                    }
                    if (iPulse - to_ch->GetSafeboxLoadTime() < PASSES_PER_SEC(g_nPortalLimitTime))
                    {
                        to_ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("??? ?? %d? ???? ??? ?? ????."), g_nPortalLimitTime);
                        if (test_server)
                            to_ch->ChatPacket(CHAT_TYPE_INFO, "[TestOnly][Safebox]Pulse %d LoadTime %d PASS %d", iPulse, to_ch->GetSafeboxLoadTime(), PASSES_PER_SEC(g_nPortalLimitTime));
                        return;
                    }
                    if (ch->GetGold() >= GOLD_MAX)
                    {
                        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("??? 20? ?? ???? ??? ??? ????.."));
                        sys_err("[OVERFLOG_GOLD] START (%u) id %u name %s ", ch->GetGold(), ch->GetPlayerID(), ch->GetName());
                        return;
                    }
                    if (to_ch->IsPC())
                    {
                        if (quest::CQuestManager::instance().GiveItemToPC(ch->GetPlayerID(), to_ch))
                        {
                            sys_log(0, "Exchange canceled by quest %s %s", ch->GetName(), to_ch->GetName());
                            return;
                        }
                    }
                    if (ch->GetMyShop() || ch->IsOpenSafebox() || ch->GetShopOwner() || ch->IsCubeOpen())
                    {
                        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("?? ?????? ????? ??? ????."));
                        return;
                    }
                    ch->ExchangeStart(to_ch);
                }
            }
            break;
 
Çözüm
Durum
İçerik kilitlendiği için mesaj gönderimine kapatıldı.
Geri
Üst