- Mesaj
- 309
- Çözümler
- 7
- Beğeni
- 94
- Puan
- 724
- Ticaret Puanı
- 0
arkadaşlar bunu eklicem fakat 2 tane var aynısından hangisine eklemeliyim.
Benim Dosyam:
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;