*Problemă/Întrebare:Problema PIN System Owsap
Tipologie server:Clean
*Resursă folosită:sursa/owsap-pin-code-system-t101087.html
*ServerFiles utilizat:Mega release
*Syserr:Nimic
Poză:
*Detalii suplimentare: Cand fac un caracter nou ma pune sa setez un pin, dupa ce incerc sa ma loghez cu acelasi PIN pe care l-am setat la creare, imi apare timerul cu mesajul "Wrong PIN" si ma da la login iar pin-ul nu se "stocheaza" in tabelul player in coloana PIN
Problema pin system
Totalitatea subiectelor care nu respectă regulamentul impus in sectiunea "Probleme şi Întrebări" vor fi stocate aici.
- btn v1
- Nivel 1

- Mesaje: 76
- Membru din: 05 Oct 2021, 17:36
- Aprecieri: 249
- Mulţumiri: 132
- Discord: Copiază ID
- Hamish
- Nivel 1

- Hamish
- Nivel 1

Poti arunca te rog o privire, am incercat sa compar si din serverfiles-ul lui owsap
ClientManagerLogin.cpp
ClientManagerPlayer.cpp
ClientManagerLogin.cpp
#include "stdafx.h"
#include "../../common/CommonDefines.h"
#include "ClientManager.h"
#include "Main.h"
#include "Config.h"
#include "QID.h"
#include "Cache.h"
extern std::string g_stLocale;
extern bool CreatePlayerTableFromRes(MYSQL_RES * res, TPlayerTable * pkTab);
extern int g_test_server;
extern int g_log;
bool CClientManager::InsertLogonAccount(const char * c_pszLogin, DWORD dwHandle, const char * c_pszIP)
{
char szLogin[LOGIN_MAX_LEN + 1];
trim_and_lower(c_pszLogin, szLogin, sizeof(szLogin));
itertype(m_map_kLogonAccount) it = m_map_kLogonAccount.find(szLogin);
if (m_map_kLogonAccount.end() != it)
return false;
CLoginData * pkLD = GetLoginDataByLogin(c_pszLogin);
if (!pkLD)
return false;
pkLD->SetConnectedPeerHandle(dwHandle);
pkLD->SetIP(c_pszIP);
m_map_kLogonAccount.insert(TLogonAccountMap::value_type(szLogin, pkLD));
return true;
}
bool CClientManager::DeleteLogonAccount(const char * c_pszLogin, DWORD dwHandle)
{
char szLogin[LOGIN_MAX_LEN + 1];
trim_and_lower(c_pszLogin, szLogin, sizeof(szLogin));
itertype(m_map_kLogonAccount) it = m_map_kLogonAccount.find(szLogin);
if (it == m_map_kLogonAccount.end())
return false;
CLoginData * pkLD = it->second;
if (pkLD->GetConnectedPeerHandle() != dwHandle)
{
sys_err("%s tried to logout in other peer handle %lu, current handle %lu", szLogin, dwHandle, pkLD->GetConnectedPeerHandle());
return false;
}
if (pkLD->IsPlay())
{
pkLD->SetPlay(false);
}
if (pkLD->IsDeleted())
{
delete pkLD;
}
m_map_kLogonAccount.erase(it);
return true;
}
bool CClientManager::FindLogonAccount(const char * c_pszLogin)
{
char szLogin[LOGIN_MAX_LEN + 1];
trim_and_lower(c_pszLogin, szLogin, sizeof(szLogin));
if (m_map_kLogonAccount.end() == m_map_kLogonAccount.find(szLogin))
return false;
return true;
}
void CClientManager::QUERY_LOGIN_BY_KEY(CPeer * pkPeer, DWORD dwHandle, TPacketGDLoginByKey * p)
{
#ifdef ENABLE_LIMIT_TIME
static int s_updateCount = 0;
static int s_curTime = time(0);
if (s_updateCount > 100)
{
s_curTime = time(0);
s_updateCount = 0;
}
++s_updateCount;
if (s_curTime >= GLOBAL_LIMIT_TIME)
{
sys_err("Server life time expired.");
exit(0);
return;
}
#endif
CLoginData * pkLoginData = GetLoginData(p->dwLoginKey);
char szLogin[LOGIN_MAX_LEN + 1];
trim_and_lower(p->szLogin, szLogin, sizeof(szLogin));
if (!pkLoginData)
{
sys_log(0, "LOGIN_BY_KEY key not exist %s %lu", szLogin, p->dwLoginKey);
pkPeer->EncodeReturn(HEADER_DG_LOGIN_NOT_EXIST, dwHandle);
return;
}
TAccountTable & r = pkLoginData->GetAccountRef();
if (FindLogonAccount(r.login))
{
sys_log(0, "LOGIN_BY_KEY already login %s %lu", r.login, p->dwLoginKey);
TPacketDGLoginAlready ptog;
strlcpy(ptog.szLogin, szLogin, sizeof(ptog.szLogin));
pkPeer->EncodeHeader(HEADER_DG_LOGIN_ALREADY, dwHandle, sizeof(TPacketDGLoginAlready));
pkPeer->Encode(&ptog, sizeof(TPacketDGLoginAlready));
return;
}
if (strcasecmp(r.login, szLogin))
{
sys_log(0, "LOGIN_BY_KEY login differ %s %lu input %s", r.login, p->dwLoginKey, szLogin);
pkPeer->EncodeReturn(HEADER_DG_LOGIN_NOT_EXIST, dwHandle);
return;
}
if (memcmp(pkLoginData->GetClientKey(), p->adwClientKey, sizeof(DWORD) * 4))
{
const DWORD * pdwClientKey = pkLoginData->GetClientKey();
sys_log(0, "LOGIN_BY_KEY client key differ %s %lu %lu %lu %lu, %lu %lu %lu %lu",
r.login,
p->adwClientKey[0], p->adwClientKey[1], p->adwClientKey[2], p->adwClientKey[3],
pdwClientKey[0], pdwClientKey[1], pdwClientKey[2], pdwClientKey[3]);
pkPeer->EncodeReturn(HEADER_DG_LOGIN_NOT_EXIST, dwHandle);
return;
}
TAccountTable * pkTab = new TAccountTable;
memset(pkTab, 0, sizeof(TAccountTable));
pkTab->id = r.id;
trim_and_lower(r.login, pkTab->login, sizeof(pkTab->login));
strlcpy(pkTab->passwd, r.passwd, sizeof(pkTab->passwd));
strlcpy(pkTab->social_id, r.social_id, sizeof(pkTab->social_id));
strlcpy(pkTab->status, "OK", sizeof(pkTab->status));
ClientHandleInfo * info = new ClientHandleInfo(dwHandle);
info->pAccountTable = pkTab;
strlcpy(info->ip, p->szIP, sizeof(info->ip));
sys_log(0, "LOGIN_BY_KEY success %s %lu %s", r.login, p->dwLoginKey, info->ip);
char szQuery[QUERY_MAX_LEN];
#ifdef ENABLE_PLAYER_PER_ACCOUNT5
snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, pid5, empire FROM player_index%s WHERE id=%u", GetTablePostfix(), r.id);
#else
snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, empire FROM player_index%s WHERE id=%u", GetTablePostfix(), r.id);
#endif
CDBManager::instance().ReturnQuery(szQuery, QID_LOGIN_BY_KEY, pkPeer->GetHandle(), info);
}
void CClientManager::RESULT_LOGIN_BY_KEY(CPeer * peer, SQLMsg * msg)
{
CQueryInfo * qi = (CQueryInfo *) msg->pvUserData;
ClientHandleInfo * info = (ClientHandleInfo *) qi->pvData;
if (msg->uiSQLErrno != 0)
{
peer->EncodeReturn(HEADER_DG_LOGIN_NOT_EXIST, info->dwHandle);
delete info;
return;
}
char szQuery[QUERY_MAX_LEN];
if (msg->Get()->uiNumRows == 0)
{
DWORD account_id = info->pAccountTable->id;
char szQuery[QUERY_MAX_LEN];
#ifdef ENABLE_PLAYER_PER_ACCOUNT5
snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, pid5, empire FROM player_index%s WHERE id=%u", GetTablePostfix(), account_id);
#else
snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, empire FROM player_index%s WHERE id=%u", GetTablePostfix(), account_id);
#endif
std::unique_ptr<SQLMsg> pMsg(CDBManager::instance().DirectQuery(szQuery, SQL_PLAYER));
sys_log(0, "RESULT_LOGIN_BY_KEY FAIL player_index's NULL : ID:%d", account_id);
if (pMsg->Get()->uiNumRows == 0)
{
sys_log(0, "RESULT_LOGIN_BY_KEY FAIL player_index's NULL : ID:%d", account_id);
// PLAYER_INDEX_CREATE_BUG_FIX
//snprintf(szQuery, sizeof(szQuery), "INSERT IGNORE INTO player_index%s (id) VALUES(%lu)", GetTablePostfix(), info->pAccountTable->id);
snprintf(szQuery, sizeof(szQuery), "INSERT INTO player_index%s (id) VALUES(%u)", GetTablePostfix(), info->pAccountTable->id);
CDBManager::instance().ReturnQuery(szQuery, QID_PLAYER_INDEX_CREATE, peer->GetHandle(), info);
// END_PLAYER_INDEX_CREATE_BUF_FIX
}
return;
}
MYSQL_ROW row = mysql_fetch_row(msg->Get()->pSQLResult);
int col = 0;
for (; col < PLAYER_PER_ACCOUNT; ++col)
str_to_number(info->pAccountTable->players[col].dwID, row[col]);
str_to_number(info->pAccountTable->bEmpire, row[col++]);
info->account_index = 1;
snprintf(szQuery, sizeof(szQuery),
"SELECT id, name, job, level, playtime, st, ht, dx, iq, part_main, part_hair, part_sash, "
"x, y, skill_group, change_name, "
#if defined(__PLAYER_PIN_SYSTEM__)
"pin, "
#endif
"UNIX_TIMESTAMP(last_play) FROM player%s WHERE account_id = %u",
GetTablePostfix(), info->pAccountTable->id);
CDBManager::instance().ReturnQuery(szQuery, QID_LOGIN, peer->GetHandle(), info);
}
// PLAYER_INDEX_CREATE_BUG_FIX
void CClientManager::RESULT_PLAYER_INDEX_CREATE(CPeer * pkPeer, SQLMsg * msg)
{
CQueryInfo * qi = (CQueryInfo *) msg->pvUserData;
ClientHandleInfo * info = (ClientHandleInfo *) qi->pvData;
char szQuery[QUERY_MAX_LEN];
#ifdef ENABLE_PLAYER_PER_ACCOUNT5
snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, pid5, empire FROM player_index%s WHERE id=%u", GetTablePostfix(),
info->pAccountTable->id);
#else
snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, empire FROM player_index%s WHERE id=%u", GetTablePostfix(),
info->pAccountTable->id);
#endif
CDBManager::instance().ReturnQuery(szQuery, QID_LOGIN_BY_KEY, pkPeer->GetHandle(), info);
}
// END_PLAYER_INDEX_CREATE_BUG_FIX
TAccountTable * CreateAccountTableFromRes(MYSQL_RES * res)
{
char input_pwd[PASSWD_MAX_LEN + 1];
MYSQL_ROW row = NULL;
DWORD col;
row = mysql_fetch_row(res);
col = 0;
TAccountTable * pkTab = new TAccountTable;
memset(pkTab, 0, sizeof(TAccountTable));
// ù¹øÂ° Ä÷³ °Í¸¸ Âü°í ÇÑ´Ù (JOIN QUERY¸¦ À§ÇÑ °Í ÀÓ)
strlcpy(input_pwd, row[col++], sizeof(input_pwd));
str_to_number(pkTab->id, row[col++]);
strlcpy(pkTab->login, row[col++], sizeof(pkTab->login));
strlcpy(pkTab->passwd, row[col++], sizeof(pkTab->passwd));
strlcpy(pkTab->social_id, row[col++], sizeof(pkTab->social_id));
str_to_number(pkTab->bEmpire, row[col++]);
for (int j = 0; j < PLAYER_PER_ACCOUNT; ++j)
str_to_number(pkTab->players[j].dwID, row[col++]);
strlcpy(pkTab->status, row[col++], sizeof(pkTab->status));
if (strcmp(pkTab->passwd, input_pwd))
{
delete pkTab;
return NULL;
}
return pkTab;
}
void CreateAccountPlayerDataFromRes(MYSQL_RES * pRes, TAccountTable * pkTab)
{
if (!pRes)
return;
for (DWORD i = 0; i < mysql_num_rows(pRes); ++i)
{
MYSQL_ROW row = mysql_fetch_row(pRes);
int col = 0;
DWORD player_id = 0;
!row[col++] ? 0 : str_to_number(player_id, row[col - 1]);
if (!player_id)
continue;
int j;
for (j = 0; j < PLAYER_PER_ACCOUNT; ++j)
{
if (pkTab->players[j].dwID == player_id)
{
CPlayerTableCache * pc = CClientManager::instance().GetPlayerCache(player_id);
TPlayerTable * pt = pc ? pc->Get(false) : NULL;
if (pt)
{
strlcpy(pkTab->players[j].szName, pt->name, sizeof(pkTab->players[j].szName));
pkTab->players[j].byJob = pt->job;
pkTab->players[j].byLevel = pt->level;
pkTab->players[j].dwPlayMinutes = pt->playtime;
pkTab->players[j].byST = pt->st;
pkTab->players[j].byHT = pt->ht;
pkTab->players[j].byDX = pt->dx;
pkTab->players[j].byIQ = pt->iq;
pkTab->players[j].wMainPart = pt->parts[PART_MAIN];
pkTab->players[j].wHairPart = pt->parts[PART_HAIR];
#ifdef __SASH_SYSTEM__
pkTab->players[j].wSashPart = pt->parts[PART_SASH];
#endif
pkTab->players[j].x = pt->x;
pkTab->players[j].y = pt->y;
pkTab->players[j].skill_group = pt->skill_group;
pkTab->players[j].bChangeName = 0;
#if defined(__PLAYER_PIN_SYSTEM__)
strlcpy(pkTab->players[j].szPinCode, pt->pin, sizeof(pkTab->players[j].szPinCode));
#endif
}
else
{
if (!row[col++])
*pkTab->players[j].szName = '\0';
else
strlcpy(pkTab->players[j].szName, row[col - 1], sizeof(pkTab->players[j].szName));
pkTab->players[j].byJob = 0;
pkTab->players[j].byLevel = 0;
pkTab->players[j].dwPlayMinutes = 0;
pkTab->players[j].byST = 0;
pkTab->players[j].byHT = 0;
pkTab->players[j].byDX = 0;
pkTab->players[j].byIQ = 0;
pkTab->players[j].wMainPart = 0;
pkTab->players[j].wHairPart = 0;
#ifdef __SASH_SYSTEM__
pkTab->players[j].wSashPart = 0;
#endif
pkTab->players[j].x = 0;
pkTab->players[j].y = 0;
pkTab->players[j].skill_group = 0;
pkTab->players[j].bChangeName = 0;
str_to_number(pkTab->players[j].byJob, row[col++]);
str_to_number(pkTab->players[j].byLevel, row[col++]);
str_to_number(pkTab->players[j].dwPlayMinutes, row[col++]);
str_to_number(pkTab->players[j].byST, row[col++]);
str_to_number(pkTab->players[j].byHT, row[col++]);
str_to_number(pkTab->players[j].byDX, row[col++]);
str_to_number(pkTab->players[j].byIQ, row[col++]);
str_to_number(pkTab->players[j].wMainPart, row[col++]);
str_to_number(pkTab->players[j].wHairPart, row[col++]);
#ifdef __SASH_SYSTEM__
str_to_number(pkTab->players[j].wSashPart, row[col++]);
#endif
str_to_number(pkTab->players[j].x, row[col++]);
str_to_number(pkTab->players[j].y, row[col++]);
str_to_number(pkTab->players[j].skill_group, row[col++]);
str_to_number(pkTab->players[j].bChangeName, row[col++]);
#if defined(__PLAYER_PIN_SYSTEM__)
if (!row[col++])
*pkTab->players[j].szPinCode = '\0';
else
strlcpy(pkTab->players[j].szPinCode, row[col - 1], sizeof(pkTab->players[j].szPinCode));
#endif
}
sys_log(0, "%s %lu %lu hair %u",
pkTab->players[j].szName, pkTab->players[j].x, pkTab->players[j].y, pkTab->players[j].wHairPart);
break;
}
}
/*
if (j == PLAYER_PER_ACCOUNT)
sys_err("cannot find player_id on this account (login: %s id %lu account %lu %lu %lu)",
pkTab->login, player_id,
pkTab->players[0].dwID,
pkTab->players[1].dwID,
pkTab->players[2].dwID);
*/
}
}
void CClientManager::RESULT_LOGIN(CPeer * peer, SQLMsg * msg)
{
CQueryInfo * qi = (CQueryInfo *) msg->pvUserData;
ClientHandleInfo * info = (ClientHandleInfo *) qi->pvData;
if (info->account_index == 0)
{
// °èÁ¤ÀÌ ¾ø³×?
if (msg->Get()->uiNumRows == 0)
{
sys_log(0, "RESULT_LOGIN: no account");
peer->EncodeHeader(HEADER_DG_LOGIN_NOT_EXIST, info->dwHandle, 0);
delete info;
return;
}
info->pAccountTable = CreateAccountTableFromRes(msg->Get()->pSQLResult);
if (!info->pAccountTable)
{
sys_log(0, "RESULT_LOGIN: no account : WRONG_PASSWD");
peer->EncodeReturn(HEADER_DG_LOGIN_WRONG_PASSWD, info->dwHandle);
delete info;
}
else
{
++info->account_index;
char queryStr[512];
snprintf(queryStr, sizeof(queryStr),
"SELECT id, name, job, level, playtime, st, ht, dx, iq, part_main, part_hair, part_sash, "
"x, y, skill_group, change_name, "
#if defined(__PLAYER_PIN_SYSTEM__)
"pin, "
#endif
"UNIX_TIMESTAMP(last_play) FROM player%s WHERE account_id = %u",
GetTablePostfix(), info->pAccountTable->id);
CDBManager::instance().ReturnQuery(queryStr, QID_LOGIN, peer->GetHandle(), info);
}
return;
}
else
{
if (!info->pAccountTable) // ÀÌ·²¸®´Â ¾ø°ÚÁö¸¸;;
{
peer->EncodeReturn(HEADER_DG_LOGIN_WRONG_PASSWD, info->dwHandle);
delete info;
return;
}
// ´Ù¸¥ ÄÁ³Ø¼ÇÀÌ ÀÌ¹Ì ·Î±×ÀÎ ÇØ¹ö·È´Ù¸é.. ÀÌ¹Ì Á¢¼ÓÇß´Ù°í º¸³»¾ß ÇÑ´Ù.
if (!InsertLogonAccount(info->pAccountTable->login, peer->GetHandle(), info->ip))
{
sys_log(0, "RESULT_LOGIN: already logon %s", info->pAccountTable->login);
TPacketDGLoginAlready p;
strlcpy(p.szLogin, info->pAccountTable->login, sizeof(p.szLogin));
peer->EncodeHeader(HEADER_DG_LOGIN_ALREADY, info->dwHandle, sizeof(TPacketDGLoginAlready));
peer->Encode(&p, sizeof(p));
}
else
{
sys_log(0, "RESULT_LOGIN: login success %s rows: %lu", info->pAccountTable->login, msg->Get()->uiNumRows);
if (msg->Get()->uiNumRows > 0)
CreateAccountPlayerDataFromRes(msg->Get()->pSQLResult, info->pAccountTable);
//PREVENT_COPY_ITEM
CLoginData * p = GetLoginDataByLogin(info->pAccountTable->login);
memcpy(&p->GetAccountRef(), info->pAccountTable, sizeof(TAccountTable));
//END_PREVENT_COPY_ITEM
peer->EncodeHeader(HEADER_DG_LOGIN_SUCCESS, info->dwHandle, sizeof(TAccountTable));
peer->Encode(info->pAccountTable, sizeof(TAccountTable));
}
delete info->pAccountTable;
info->pAccountTable = NULL;
delete info;
}
}
void CClientManager::QUERY_LOGOUT(CPeer * peer, DWORD dwHandle,const char * data)
{
TLogoutPacket* packet = (TLogoutPacket*)data;
if (!*packet->login)
return;
CLoginData * pLoginData = GetLoginDataByLogin(packet->login);
if (pLoginData == NULL)
return;
int pid[PLAYER_PER_ACCOUNT];
for (int n = 0; n < PLAYER_PER_ACCOUNT; ++n)
{
if (pLoginData->GetAccountRef().players[n].dwID == 0)
{
if (g_test_server)
sys_log(0, "LOGOUT %s %d", packet->login, pLoginData->GetAccountRef().players[n].dwID);
continue;
}
pid[n] = pLoginData->GetAccountRef().players[n].dwID;
if (g_log)
sys_log(0, "LOGOUT InsertLogoutPlayer %s %d", packet->login, pid[n]);
InsertLogoutPlayer(pid[n]);
}
if (DeleteLogonAccount(packet->login, peer->GetHandle()))
{
if (g_log)
sys_log(0, "LOGOUT %s ", packet->login);
}
}
void CClientManager::QUERY_CHANGE_NAME(CPeer * peer, DWORD dwHandle, TPacketGDChangeName * p)
{
char queryStr[QUERY_MAX_LEN];
if (g_stLocale == "sjis")
snprintf(queryStr, sizeof(queryStr),
"SELECT COUNT(*) as count FROM player%s WHERE name='%s' collate sjis_japanese_ci AND id <> %u",
GetTablePostfix(), p->name, p->pid);
else
snprintf(queryStr, sizeof(queryStr),
"SELECT COUNT(*) as count FROM player%s WHERE name='%s' AND id <> %u", GetTablePostfix(), p->name, p->pid);
std::unique_ptr<SQLMsg> pMsg(CDBManager::instance().DirectQuery(queryStr, SQL_PLAYER));
if (pMsg->Get()->uiNumRows)
{
if (!pMsg->Get()->pSQLResult)
{
peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0);
return;
}
MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);
if (*row[0] != '0')
{
peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_ALREADY, dwHandle, 0);
return;
}
}
else
{
peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0);
return;
}
snprintf(queryStr, sizeof(queryStr),
"UPDATE player%s SET name='%s',change_name=0 WHERE id=%u", GetTablePostfix(), p->name, p->pid);
std::unique_ptr<SQLMsg> pMsg0(CDBManager::instance().DirectQuery(queryStr, SQL_PLAYER));
TPacketDGChangeName pdg;
peer->EncodeHeader(HEADER_DG_CHANGE_NAME, dwHandle, sizeof(TPacketDGChangeName));
pdg.pid = p->pid;
strlcpy(pdg.name, p->name, sizeof(pdg.name));
peer->Encode(&pdg, sizeof(TPacketDGChangeName));
}
#include "stdafx.h"
#include "ClientManager.h"
#include "Main.h"
#include "QID.h"
#include "ItemAwardManager.h"
#include "HB.h"
#include "Cache.h"
#define __TITLE_SYSTEM__
#define ENABLE_SPECIAL_STORAGE
extern bool g_bHotBackup;
extern std::string g_stLocale;
extern int g_test_server;
extern int g_log;
//
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!!!!!!!!!! IMPORTANT !!!!!!!!!!!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
// Check all SELECT syntax on item table before change this function!!!
//
bool CreateItemTableFromRes(MYSQL_RES * res, std::vector<TPlayerItem> * pVec, DWORD dwPID)
{
if (!res)
{
pVec->clear();
return true;
}
int rows;
if ((rows = mysql_num_rows(res)) <= 0) // µ¥ÀÌÅÍ ¾øÀ½
{
pVec->clear();
return true;
}
pVec->resize(rows);
for (int i = 0; i < rows; ++i)
{
MYSQL_ROW row = mysql_fetch_row(res);
TPlayerItem & item = pVec->at(i);
int -cenzurat- = 0;
// Check all SELECT syntax on item table before change this function!!!
// Check all SELECT syntax on item table before change this function!!!
// Check all SELECT syntax on item table before change this function!!!
str_to_number(item.id, row[-cenzurat-++]);
str_to_number(item.window, row[-cenzurat-++]);
str_to_number(item.pos, row[-cenzurat-++]);
str_to_number(item.count, row[-cenzurat-++]);
str_to_number(item.vnum, row[-cenzurat-++]);
#ifdef __CHANGELOOK_SYSTEM__
str_to_number(item.transmutation, row[-cenzurat-++]);
#endif
str_to_number(item.alSockets[0], row[-cenzurat-++]);
str_to_number(item.alSockets[1], row[-cenzurat-++]);
str_to_number(item.alSockets[2], row[-cenzurat-++]);
for (int j = 0; j < ITEM_ATTRIBUTE_MAX_NUM; j++)
{
str_to_number(item.aAttr[j].bType, row[-cenzurat-++]);
str_to_number(item.aAttr[j].sValue, row[-cenzurat-++]);
}
item.owner = dwPID;
}
return true;
}
size_t CreatePlayerSaveQuery(char * pszQuery, size_t querySize, TPlayerTable * pkTab)
{
size_t queryLen;
queryLen = snprintf(pszQuery, querySize,
"UPDATE player%s SET "
"job = %d, "
"voice = %d, "
"dir = %d, "
"x = %d, "
"y = %d, "
"z = %d, "
"map_index = %d, "
"exit_x = %ld, "
"exit_y = %ld, "
"exit_map_index = %ld, "
"hp = %d, "
"mp = %d, "
"stamina = %d, "
"random_hp = %d, "
"random_sp = %d, "
"playtime = %d, "
"level = %d, "
"level_step = %d, "
"st = %d, "
"ht = %d, "
"dx = %d, "
"iq = %d, "
"gold = %lld, "
#ifdef ENABLE_GEM_SYSTEM
"gem = %d, "
#endif
"exp = %u, "
"stat_point = %d, "
"skill_point = %d, "
"sub_skill_point = %d, "
"stat_reset_count = %d, "
"ip = '%s', "
"part_main = %d, "
"part_hair = %d, "
#ifdef __SASH_SYSTEM__
"part_sash = %d, "
#endif
"last_play = NOW(), "
"skill_group = %d, "
"alignment = %ld, "
"horse_level = %d, "
"horse_riding = %d, "
"horse_hp = %d, "
"horse_hp_droptime = %u, "
"horse_stamina = %d, "
"horse_skill_point = %d, "
#ifdef ENABLE_FISH_EVENT
"fish_use_count = %d, "
#endif
#ifdef ENABLE_GEM_SYSTEM
"gem_next_refresh = FROM_UNIXTIME(%d), "
#endif
#ifdef __TITLE_SYSTEM__
"t_choosed = %d, "
"t_available = '%s', "
#endif
,
GetTablePostfix(),
pkTab->job,
pkTab->voice,
pkTab->dir,
pkTab->x,
pkTab->y,
pkTab->z,
pkTab->lMapIndex,
pkTab->lExitX,
pkTab->lExitY,
pkTab->lExitMapIndex,
pkTab->hp,
pkTab->sp,
pkTab->stamina,
pkTab->sRandomHP,
pkTab->sRandomSP,
pkTab->playtime,
pkTab->level,
pkTab->level_step,
pkTab->st,
pkTab->ht,
pkTab->dx,
pkTab->iq,
pkTab->gold,
#ifdef ENABLE_GEM_SYSTEM
pkTab->gem,
#endif
pkTab->exp,
pkTab->stat_point,
pkTab->skill_point,
pkTab->sub_skill_point,
pkTab->stat_reset_count,
pkTab->ip,
pkTab->parts[PART_MAIN],
pkTab->parts[PART_HAIR],
#ifdef __SASH_SYSTEM__
pkTab->parts[PART_SASH],
#endif
pkTab->skill_group,
pkTab->lAlignment,
pkTab->horse.bLevel,
pkTab->horse.bRiding,
pkTab->horse.sHealth,
pkTab->horse.dwHorseHealthDropTime,
pkTab->horse.sStamina,
pkTab->horse_skill_point,
#ifdef ENABLE_FISH_EVENT
pkTab->fishEventUseCount
#endif
#ifdef ENABLE_GEM_SYSTEM
,pkTab->gem_next_refresh
#endif
#ifdef __TITLE_SYSTEM__
,pkTab->iTChoosed
,pkTab->cTAvailable
#endif
);
// Binary ·Î ¹Ù²Ù±â À§ÇÑ Àӽà °ø°£
static char text[8192 + 1];
CDBManager::instance().EscapeString(text, pkTab->skills, sizeof(pkTab->skills));
queryLen += snprintf(pszQuery + queryLen, querySize - queryLen, "skill_level = '%s', ", text);
CDBManager::instance().EscapeString(text, pkTab->quickslot, sizeof(pkTab->quickslot));
queryLen += snprintf(pszQuery + queryLen, querySize - queryLen, "quickslot = '%s', ", text);
CDBManager::instance().EscapeString(text, pkTab->gemItems, sizeof(pkTab->gemItems));
queryLen += snprintf(pszQuery + queryLen, querySize - queryLen, "gem_items = '%s', ", text);
CDBManager::instance().EscapeString(text, pkTab->fishSlots, sizeof(pkTab->fishSlots));
queryLen += snprintf(pszQuery + queryLen, querySize - queryLen, "fish_slots = '%s' ", text);
queryLen += snprintf(pszQuery + queryLen, querySize - queryLen, " WHERE id=%d", pkTab->id);
return queryLen;
}
CPlayerTableCache * CClientManager::GetPlayerCache(DWORD id)
{
TPlayerTableCacheMap::iterator it = m_map_playerCache.find(id);
if (it == m_map_playerCache.end())
return NULL;
TPlayerTable* pTable = it->second->Get(false);
pTable->logoff_interval = GetCurrentTime() - it->second->GetLastUpdateTime();
return it->second;
}
void CClientManager::PutPlayerCache(TPlayerTable * pNew)
{
CPlayerTableCache * c;
c = GetPlayerCache(pNew->id);
if (!c)
{
c = new CPlayerTableCache;
m_map_playerCache.insert(TPlayerTableCacheMap::value_type(pNew->id, c));
}
if (g_bHotBackup)
PlayerHB::instance().Put(pNew->id);
c->Put(pNew);
}
/*
* PLAYER LOAD
*/
void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoadPacket * packet)
{
CPlayerTableCache * c;
TPlayerTable * pTab;
//
// ÇÑ °èÁ¤¿¡ ¼ÓÇÑ ¸ðµç ij¸¯Å͵é ij½¬Ã³¸®
//
CLoginData * pLoginData = GetLoginDataByAID(packet->account_id);
if (pLoginData)
{
for (int n = 0; n < PLAYER_PER_ACCOUNT; ++n)
if (pLoginData->GetAccountRef().players[n].dwID != 0)
DeleteLogoutPlayer(pLoginData->GetAccountRef().players[n].dwID);
}
//----------------------------------------------------------------
// 1. À¯ÀúÁ¤º¸°¡ DBCache ¿¡ Á¸Àç : DBCache¿¡¼
// 2. À¯ÀúÁ¤º¸°¡ DBCache ¿¡ ¾øÀ½ : DB¿¡¼
// ---------------------------------------------------------------
//----------------------------------
// 1. À¯ÀúÁ¤º¸°¡ DBCache ¿¡ Á¸Àç : DBCache¿¡¼
//----------------------------------
if ((c = GetPlayerCache(packet->player_id)))
{
CLoginData * pkLD = GetLoginDataByAID(packet->account_id);
if (!pkLD || pkLD->IsPlay())
{
sys_log(0, "PLAYER_LOAD_ERROR: LoginData %p IsPlay %d", pkLD, pkLD ? pkLD->IsPlay() : 0);
peer->EncodeHeader(HEADER_DG_PLAYER_LOAD_FAILED, dwHandle, 0);
return;
}
pTab = c->Get();
pkLD->SetPlay(true);
thecore_memcpy(pTab->aiPremiumTimes, pkLD->GetPremiumPtr(), sizeof(pTab->aiPremiumTimes));
peer->EncodeHeader(HEADER_DG_PLAYER_LOAD_SUCCESS, dwHandle, sizeof(TPlayerTable));
peer->Encode(pTab, sizeof(TPlayerTable));
if (packet->player_id != pkLD->GetLastPlayerID())
{
TPacketNeedLoginLogInfo logInfo;
logInfo.dwPlayerID = packet->player_id;
pkLD->SetLastPlayerID( packet->player_id );
peer->EncodeHeader( HEADER_DG_NEED_LOGIN_LOG, dwHandle, sizeof(TPacketNeedLoginLogInfo) );
peer->Encode( &logInfo, sizeof(TPacketNeedLoginLogInfo) );
}
char szQuery[1024] = { 0, };
TItemCacheSet * pSet = GetItemCacheSet(pTab->id);
sys_log(0, "[PLAYER_LOAD] ID %s pid %d gold %lld ", pTab->name, pTab->id, pTab->gold);
//--------------------------------------------
// ¾ÆÀÌÅÛ & AFFECT & QUEST ·Îµù :
//--------------------------------------------
// 1) ¾ÆÀÌÅÛÀÌ DBCache ¿¡ Á¸Àç : DBCache ¿¡¼ °¡Á®¿È
// 2) ¾ÆÀÌÅÛÀÌ DBCache ¿¡ ¾øÀ½ : DB ¿¡¼ °¡Á®¿È
/////////////////////////////////////////////
// 1) ¾ÆÀÌÅÛÀÌ DBCache ¿¡ Á¸Àç : DBCache ¿¡¼ °¡Á®¿È
/////////////////////////////////////////////
if (pSet)
{
static std::vector<TPlayerItem> s_items;
s_items.resize(pSet->size());
DWORD dwCount = 0;
TItemCacheSet::iterator it = pSet->begin();
while (it != pSet->end())
{
CItemCache * c = *it++;
TPlayerItem * p = c->Get();
if (p->vnum) // vnumÀÌ ¾øÀ¸¸é »èÁ¦µÈ ¾ÆÀÌÅÛÀÌ´Ù.
thecore_memcpy(&s_items[dwCount++], p, sizeof(TPlayerItem));
}
if (g_test_server)
sys_log(0, "ITEM_CACHE: HIT! %s count: %u", pTab->name, dwCount);
peer->EncodeHeader(HEADER_DG_ITEM_LOAD, dwHandle, sizeof(DWORD) + sizeof(TPlayerItem) * dwCount);
peer->EncodeDWORD(dwCount);
if (dwCount)
peer->Encode(&s_items[0], sizeof(TPlayerItem) * dwCount);
// Quest
snprintf(szQuery, sizeof(szQuery),
"SELECT dwPID,szName,szState,lValue FROM quest%s WHERE dwPID=%d AND lValue<>0",
GetTablePostfix(), pTab->id);
CDBManager::instance().ReturnQuery(szQuery, QID_QUEST, peer->GetHandle(), new ClientHandleInfo(dwHandle,0,packet->account_id));
// Affect
snprintf(szQuery, sizeof(szQuery),
"SELECT dwPID,bType,bApplyOn,lApplyValue,dwFlag,lDuration,lSPCost FROM affect%s WHERE dwPID=%d",
GetTablePostfix(), pTab->id);
// @fixme402 ClientHandleInfo+pTab->id
CDBManager::instance().ReturnQuery(szQuery, QID_AFFECT, peer->GetHandle(), new ClientHandleInfo(dwHandle, pTab->id));
}
/////////////////////////////////////////////
// 2) ¾ÆÀÌÅÛÀÌ DBCache ¿¡ ¾øÀ½ : DB ¿¡¼ °¡Á®¿È
/////////////////////////////////////////////
else
{
snprintf(szQuery, sizeof(szQuery),
"SELECT id,window+0,pos,count,vnum,transmutation,socket0,socket1,socket2,attrtype0,attrvalue0,attrtype1,attrvalue1,attrtype2,attrvalue2,attrtype3,attrvalue3,attrtype4,attrvalue4,attrtype5,attrvalue5,attrtype6,attrvalue6 "
"FROM item%s WHERE owner_id=%d AND (window in ('INVENTORY','EQUIPMENT','DRAGON_SOUL_INVENTORY','UPGRADE_INVENTORY','BOOK_INVENTORY','STONE_INVENTORY','CHEST_INVENTORY','ATTR_INVENTORY','BELT_INVENTORY','SWITCHBOT'))",
GetTablePostfix(), pTab->id);
CDBManager::instance().ReturnQuery(szQuery,
QID_ITEM,
peer->GetHandle(),
new ClientHandleInfo(dwHandle, pTab->id));
snprintf(szQuery, sizeof(szQuery),
"SELECT dwPID, szName, szState, lValue FROM quest%s WHERE dwPID=%d",
GetTablePostfix(), pTab->id);
CDBManager::instance().ReturnQuery(szQuery,
QID_QUEST,
peer->GetHandle(),
new ClientHandleInfo(dwHandle, pTab->id));
snprintf(szQuery, sizeof(szQuery),
"SELECT dwPID, bType, bApplyOn, lApplyValue, dwFlag, lDuration, lSPCost FROM affect%s WHERE dwPID=%d",
GetTablePostfix(), pTab->id);
CDBManager::instance().ReturnQuery(szQuery,
QID_AFFECT,
peer->GetHandle(),
new ClientHandleInfo(dwHandle, pTab->id));
}
//ljw
//return;
}
//----------------------------------
// 2. À¯ÀúÁ¤º¸°¡ DBCache ¿¡ ¾øÀ½ : DB¿¡¼
//----------------------------------
else
{
sys_log(0, "[PLAYER_LOAD] Load from PlayerDB pid[%d]", packet->player_id);
char queryStr[QUERY_MAX_LEN];
//--------------------------------------------------------------
// ij¸¯ÅÍ Á¤º¸ ¾ò¾î¿À±â : ¹«Á¶°Ç DB¿¡¼
//--------------------------------------------------------------
snprintf(queryStr, sizeof(queryStr),
"SELECT "
"id,name,job,voice,dir,x,y,z,map_index,exit_x,exit_y,exit_map_index,hp,mp,stamina,random_hp,random_sp,playtime,"
"gold,"
#ifdef ENABLE_GEM_SYSTEM
"gem,"
#endif
"level,level_step,st,ht,dx,iq,exp,"
"stat_point,skill_point,sub_skill_point,stat_reset_count,part_base,part_hair,part_sash,"
"skill_level,quickslot,skill_group,alignment,horse_level,horse_riding,horse_hp,horse_hp_droptime,horse_stamina,"
"UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(last_play),horse_skill_point"
#ifdef ENABLE_FISH_EVENT
",fish_use_count, fish_slots "
#endif
#ifdef ENABLE_GEM_SYSTEM
",UNIX_TIMESTAMP(gem_next_refresh),gem_items "
#endif
#ifdef __TITLE_SYSTEM__
"t_choosed, "
"t_available "
#endif
" FROM player%s WHERE id=%d",
GetTablePostfix(), packet->player_id);
ClientHandleInfo * pkInfo = new ClientHandleInfo(dwHandle, packet->player_id);
pkInfo->account_id = packet->account_id;
CDBManager::instance().ReturnQuery(queryStr, QID_PLAYER, peer->GetHandle(), pkInfo);
//--------------------------------------------------------------
// ¾ÆÀÌÅÛ °¡Á®¿À±â
//--------------------------------------------------------------
snprintf(queryStr, sizeof(queryStr),
"SELECT id,window+0,pos,count,vnum,transmutation,socket0,socket1,socket2,attrtype0,attrvalue0,attrtype1,attrvalue1,attrtype2,attrvalue2,attrtype3,attrvalue3,attrtype4,attrvalue4,attrtype5,attrvalue5,attrtype6,attrvalue6 "
"FROM item%s WHERE owner_id=%d AND (window in ('INVENTORY','EQUIPMENT','DRAGON_SOUL_INVENTORY','UPGRADE_INVENTORY','BOOK_INVENTORY','STONE_INVENTORY','CHEST_INVENTORY','ATTR_INVENTORY','BELT_INVENTORY','SWITCHBOT'))",
GetTablePostfix(), packet->player_id);
CDBManager::instance().ReturnQuery(queryStr, QID_ITEM, peer->GetHandle(), new ClientHandleInfo(dwHandle, packet->player_id));
//--------------------------------------------------------------
// QUEST °¡Á®¿À±â
//--------------------------------------------------------------
snprintf(queryStr, sizeof(queryStr),
"SELECT dwPID,szName,szState,lValue FROM quest%s WHERE dwPID=%d",
GetTablePostfix(), packet->player_id);
CDBManager::instance().ReturnQuery(queryStr, QID_QUEST, peer->GetHandle(), new ClientHandleInfo(dwHandle, packet->player_id,packet->account_id));
//µ¶ÀÏ ¼±¹° ±â´É¿¡¼ item_awardÅ×ÀÌºí¿¡¼ login Á¤º¸¸¦ ¾ò±âÀ§ÇØ account idµµ ³Ñ°ÜÁØ´Ù
//--------------------------------------------------------------
// AFFECT °¡Á®¿À±â
//--------------------------------------------------------------
snprintf(queryStr, sizeof(queryStr),
"SELECT dwPID,bType,bApplyOn,lApplyValue,dwFlag,lDuration,lSPCost FROM affect%s WHERE dwPID=%d",
GetTablePostfix(), packet->player_id);
CDBManager::instance().ReturnQuery(queryStr, QID_AFFECT, peer->GetHandle(), new ClientHandleInfo(dwHandle, packet->player_id));
}
}
void CClientManager::ItemAward(CPeer * peer,char* login)
{
char login_t[LOGIN_MAX_LEN + 1] = "";
strlcpy(login_t,login,LOGIN_MAX_LEN + 1);
std::set<TItemAward *> * pSet = ItemAwardManager::instance().GetByLogin(login_t);
if(pSet == NULL)
return;
__typeof(pSet->begin()) it = pSet->begin(); //taken_timeÀÌ NULLÀΰ͵é Àоî¿È
while(it != pSet->end() )
{
TItemAward * pItemAward = *(it++);
char* whyStr = pItemAward->szWhy; //why ÄÝ·ë Àбâ
char cmdStr[100] = ""; //whyÄÝ·ë¿¡¼ ÀÐÀº °ªÀ» Àӽà ¹®ÀÚ¿¿¡ º¹»çÇØµÒ
strcpy(cmdStr,whyStr); //¸í·É¾î ¾ò´Â °úÁ¤¿¡¼ ÅäÅ«¾²¸é ¿øº»µµ ÅäÅ«È µÇ±â ¶§¹®
char command[20] = "";
// @fixme203 directly GetCommand instead of strcpy
GetCommand(cmdStr, command); // command ¾ò±â
if( !(strcmp(command,"GIFT") )) // command °¡ GIFTÀ̸é
{
TPacketItemAwardInfromer giftData;
strcpy(giftData.login, pItemAward->szLogin); //·Î±×ÀÎ ¾ÆÀ̵𠺹»ç
strcpy(giftData.command, command); //¸í·É¾î º¹»ç
giftData.vnum = pItemAward->dwVnum; //¾ÆÀÌÅÛ vnumµµ º¹»ç
ForwardPacket(HEADER_DG_ITEMAWARD_INFORMER,&giftData,sizeof(TPacketItemAwardInfromer));
}
}
}
char* CClientManager::GetCommand(char* str, char* command) // @fixme203
{
char* tok;
if( str[0] == '[' )
{
tok = strtok(str,"]");
strcat(command,&tok[1]);
}
return command;
}
bool CreatePlayerTableFromRes(MYSQL_RES * res, TPlayerTable * pkTab)
{
if (mysql_num_rows(res) == 0) // µ¥ÀÌÅÍ ¾øÀ½
return false;
memset(pkTab, 0, sizeof(TPlayerTable));
MYSQL_ROW row = mysql_fetch_row(res);
int col = 0;
// "id,name,job,voice,dir,x,y,z,map_index,exit_x,exit_y,exit_map_index,hp,mp,stamina,random_hp,random_sp,playtime,"
// "gold,level,level_step,st,ht,dx,iq,exp,"
// "stat_point,skill_point,sub_skill_point,stat_reset_count,part_base,part_hair,"
// "skill_level,quickslot,skill_group,alignment,mobile,horse_level,horse_riding,horse_hp,horse_stamina FROM player%s WHERE id=%d",
str_to_number(pkTab->id, row[col++]);
strlcpy(pkTab->name, row[col++], sizeof(pkTab->name));
str_to_number(pkTab->job, row[col++]);
str_to_number(pkTab->voice, row[col++]);
str_to_number(pkTab->dir, row[col++]);
str_to_number(pkTab->x, row[col++]);
str_to_number(pkTab->y, row[col++]);
str_to_number(pkTab->z, row[col++]);
str_to_number(pkTab->lMapIndex, row[col++]);
str_to_number(pkTab->lExitX, row[col++]);
str_to_number(pkTab->lExitY, row[col++]);
str_to_number(pkTab->lExitMapIndex, row[col++]);
str_to_number(pkTab->hp, row[col++]);
str_to_number(pkTab->sp, row[col++]);
str_to_number(pkTab->stamina, row[col++]);
str_to_number(pkTab->sRandomHP, row[col++]);
str_to_number(pkTab->sRandomSP, row[col++]);
str_to_number(pkTab->playtime, row[col++]);
str_to_number(pkTab->gold, row[col++]);
#ifdef ENABLE_GEM_SYSTEM
str_to_number(pkTab->gem, row[col++]);
#endif
str_to_number(pkTab->level, row[col++]);
str_to_number(pkTab->level_step, row[col++]);
str_to_number(pkTab->st, row[col++]);
str_to_number(pkTab->ht, row[col++]);
str_to_number(pkTab->dx, row[col++]);
str_to_number(pkTab->iq, row[col++]);
str_to_number(pkTab->exp, row[col++]);
str_to_number(pkTab->stat_point, row[col++]);
str_to_number(pkTab->skill_point, row[col++]);
str_to_number(pkTab->sub_skill_point, row[col++]);
str_to_number(pkTab->stat_reset_count, row[col++]);
str_to_number(pkTab->part_base, row[col++]);
str_to_number(pkTab->parts[PART_HAIR], row[col++]);
#ifdef __SASH_SYSTEM__
str_to_number(pkTab->parts[PART_SASH], row[col++]);
#endif
if (row[col])
thecore_memcpy(pkTab->skills, row[col], sizeof(pkTab->skills));
else
memset(&pkTab->skills, 0, sizeof(pkTab->skills));
col++;
if (row[col])
thecore_memcpy(pkTab->quickslot, row[col], sizeof(pkTab->quickslot));
else
memset(pkTab->quickslot, 0, sizeof(pkTab->quickslot));
col++;
str_to_number(pkTab->skill_group, row[col++]);
str_to_number(pkTab->lAlignment, row[col++]);
str_to_number(pkTab->horse.bLevel, row[col++]);
str_to_number(pkTab->horse.bRiding, row[col++]);
str_to_number(pkTab->horse.sHealth, row[col++]);
str_to_number(pkTab->horse.dwHorseHealthDropTime, row[col++]);
str_to_number(pkTab->horse.sStamina, row[col++]);
str_to_number(pkTab->logoff_interval, row[col++]);
str_to_number(pkTab->horse_skill_point, row[col++]);
#ifdef ENABLE_FISH_EVENT
str_to_number(pkTab->fishEventUseCount, row[col++]);
if (row[col])
thecore_memcpy(pkTab->fishSlots, row[col], sizeof(pkTab->fishSlots));
else
memset(pkTab->fishSlots, 0, sizeof(pkTab->fishSlots));
col++;
#endif
#ifdef ENABLE_GEM_SYSTEM
str_to_number(pkTab->gem_next_refresh, row[col++]);
if (row[col])
thecore_memcpy(pkTab->gemItems, row[col], sizeof(pkTab->gemItems));
else
memset(pkTab->gemItems, 0, sizeof(pkTab->gemItems));
col++;
#endif
#ifdef __TITLE_SYSTEM__
str_to_number(pkTab->iTChoosed, row[col++]);
if (row[col])
strlcpy(pkTab->cTAvailable, row[col], sizeof(pkTab->cTAvailable));
#endif
// reset sub_skill_point
{
pkTab->skills[123].bLevel = 0; // SKILL_CREATE
if (pkTab->level > 9)
{
int max_point = pkTab->level - 9;
int skill_point =
MIN(20, pkTab->skills[121].bLevel) + // SKILL_LEADERSHIP Åë¼Ö·Â
MIN(20, pkTab->skills[124].bLevel) + // SKILL_MINING 䱤
MIN(10, pkTab->skills[131].bLevel) + // SKILL_HORSE_SUMMON ¸»¼Òȯ
MIN(20, pkTab->skills[141].bLevel) + // SKILL_ADD_HP HPº¸°
MIN(20, pkTab->skills[142].bLevel); // SKILL_RESIST_PENETRATE °üÅëÀúÇ×
pkTab->sub_skill_point = max_point - skill_point;
}
else
pkTab->sub_skill_point = 0;
}
return true;
}
void CClientManager::RESULT_COMPOSITE_PLAYER(CPeer * peer, SQLMsg * pMsg, DWORD dwQID)
{
CQueryInfo * qi = (CQueryInfo *) pMsg->pvUserData;
std::unique_ptr<ClientHandleInfo> info((ClientHandleInfo *) qi->pvData);
MYSQL_RES * pSQLResult = pMsg->Get()->pSQLResult;
if (!pSQLResult)
{
sys_err("null MYSQL_RES QID %u", dwQID);
return;
}
switch (dwQID)
{
case QID_PLAYER:
sys_log(0, "QID_PLAYER %u %u", info->dwHandle, info->player_id);
RESULT_PLAYER_LOAD(peer, pSQLResult, info.get());
break;
case QID_ITEM:
sys_log(0, "QID_ITEM %u", info->dwHandle);
RESULT_ITEM_LOAD(peer, pSQLResult, info->dwHandle, info->player_id);
break;
case QID_QUEST:
{
sys_log(0, "QID_QUEST %u", info->dwHandle);
RESULT_QUEST_LOAD(peer, pSQLResult, info->dwHandle, info->player_id);
//aid¾ò±â
ClientHandleInfo* temp1 = info.get();
if (temp1 == NULL)
break;
CLoginData* pLoginData1 = GetLoginDataByAID(temp1->account_id); //
//µ¶ÀÏ ¼±¹° ±â´É
if( pLoginData1->GetAccountRef().login == NULL)
break;
if( pLoginData1 == NULL )
break;
sys_log(0,"info of pLoginData1 before call ItemAwardfunction %d",pLoginData1);
ItemAward(peer,pLoginData1->GetAccountRef().login);
}
break;
case QID_AFFECT:
sys_log(0, "QID_AFFECT %u", info->dwHandle);
// @fixme402 RESULT_AFFECT_LOAD+info->player_id
RESULT_AFFECT_LOAD(peer, pSQLResult, info->dwHandle, info->player_id);
break;
}
}
void CClientManager::RESULT_PLAYER_LOAD(CPeer * peer, MYSQL_RES * pRes, ClientHandleInfo * pkInfo)
{
TPlayerTable tab;
if (!CreatePlayerTableFromRes(pRes, &tab))
{
peer->EncodeHeader(HEADER_DG_PLAYER_LOAD_FAILED, pkInfo->dwHandle, 0);
return;
}
CLoginData * pkLD = GetLoginDataByAID(pkInfo->account_id);
if (!pkLD || pkLD->IsPlay())
{
sys_log(0, "PLAYER_LOAD_ERROR: LoginData %p IsPlay %d", pkLD, pkLD ? pkLD->IsPlay() : 0);
peer->EncodeHeader(HEADER_DG_PLAYER_LOAD_FAILED, pkInfo->dwHandle, 0);
return;
}
pkLD->SetPlay(true);
thecore_memcpy(tab.aiPremiumTimes, pkLD->GetPremiumPtr(), sizeof(tab.aiPremiumTimes));
peer->EncodeHeader(HEADER_DG_PLAYER_LOAD_SUCCESS, pkInfo->dwHandle, sizeof(TPlayerTable));
peer->Encode(&tab, sizeof(TPlayerTable));
if (tab.id != pkLD->GetLastPlayerID())
{
TPacketNeedLoginLogInfo logInfo;
logInfo.dwPlayerID = tab.id;
pkLD->SetLastPlayerID( tab.id );
peer->EncodeHeader( HEADER_DG_NEED_LOGIN_LOG, pkInfo->dwHandle, sizeof(TPacketNeedLoginLogInfo) );
peer->Encode( &logInfo, sizeof(TPacketNeedLoginLogInfo) );
}
}
void CClientManager::RESULT_ITEM_LOAD(CPeer * peer, MYSQL_RES * pRes, DWORD dwHandle, DWORD dwPID)
{
static std::vector<TPlayerItem> s_items;
//DB¿¡¼ ¾ÆÀÌÅÛ Á¤º¸¸¦ Àоî¿Â´Ù.
CreateItemTableFromRes(pRes, &s_items, dwPID);
DWORD dwCount = s_items.size();
peer->EncodeHeader(HEADER_DG_ITEM_LOAD, dwHandle, sizeof(DWORD) + sizeof(TPlayerItem) * dwCount);
peer->EncodeDWORD(dwCount);
//CacheSetÀ» ¸¸µç´Ù
CreateItemCacheSet(dwPID);
// ITEM_LOAD_LOG_ATTACH_PID
sys_log(0, "ITEM_LOAD: count %u pid %u", dwCount, dwPID);
// END_OF_ITEM_LOAD_LOG_ATTACH_PID
if (dwCount)
{
peer->Encode(&s_items[0], sizeof(TPlayerItem) * dwCount);
for (DWORD i = 0; i < dwCount; ++i)
PutItemCache(&s_items, true); // ·ÎµåÇÑ °ÍÀº µû·Î ÀúÀåÇÒ ÇÊ¿ä ¾øÀ¸¹Ç·Î, ÀÎÀÚ bSkipQuery¿¡ true¸¦ ³Ö´Â´Ù.
}
}
// @fixme402 (RESULT_AFFECT_LOAD +dwRealPID)
void CClientManager::RESULT_AFFECT_LOAD(CPeer * peer, MYSQL_RES * pRes, DWORD dwHandle, DWORD dwRealPID)
{
int iNumRows;
if ((iNumRows = mysql_num_rows(pRes)) == 0) // µ¥ÀÌÅÍ ¾øÀ½
{
// @fixme402 begin
static DWORD dwPID;
static DWORD dwCount = 0; //1;
static TPacketAffectElement paeTable = {0};
dwPID = dwRealPID;
sys_log(0, "AFFECT_LOAD: count %u PID %u RealPID %u", dwCount, dwPID, dwRealPID);
peer->EncodeHeader(HEADER_DG_AFFECT_LOAD, dwHandle, sizeof(DWORD) + sizeof(DWORD) + sizeof(TPacketAffectElement) * dwCount);
peer->Encode(&dwPID, sizeof(DWORD));
peer->Encode(&dwCount, sizeof(DWORD));
peer->Encode(&paeTable, sizeof(TPacketAffectElement) * dwCount);
// @fixme402 end
return;
}
static std::vector<TPacketAffectElement> s_elements;
s_elements.resize(iNumRows);
DWORD dwPID = 0;
MYSQL_ROW row;
for (int i = 0; i < iNumRows; ++i)
{
TPacketAffectElement & r = s_elements;
row = mysql_fetch_row(pRes);
if (dwPID == 0)
str_to_number(dwPID, row[0]);
str_to_number(r.dwType, row[1]);
str_to_number(r.bApplyOn, row[2]);
str_to_number(r.lApplyValue, row[3]);
str_to_number(r.dwFlag, row[4]);
str_to_number(r.lDuration, row[5]);
str_to_number(r.lSPCost, row[6]);
}
sys_log(0, "AFFECT_LOAD: count %d PID %u", s_elements.size(), dwPID);
DWORD dwCount = s_elements.size();
peer->EncodeHeader(HEADER_DG_AFFECT_LOAD, dwHandle, sizeof(DWORD) + sizeof(DWORD) + sizeof(TPacketAffectElement) * dwCount);
peer->Encode(&dwPID, sizeof(DWORD));
peer->Encode(&dwCount, sizeof(DWORD));
peer->Encode(&s_elements[0], sizeof(TPacketAffectElement) * dwCount);
}
void CClientManager::RESULT_QUEST_LOAD(CPeer * peer, MYSQL_RES * pRes, DWORD dwHandle, DWORD pid)
{
int iNumRows;
if ((iNumRows = mysql_num_rows(pRes)) == 0)
{
DWORD dwCount = 0;
peer->EncodeHeader(HEADER_DG_QUEST_LOAD, dwHandle, sizeof(DWORD));
peer->Encode(&dwCount, sizeof(DWORD));
return;
}
static std::vector<TQuestTable> s_table;
s_table.resize(iNumRows);
MYSQL_ROW row;
for (int i = 0; i < iNumRows; ++i)
{
TQuestTable & r = s_table;
row = mysql_fetch_row(pRes);
str_to_number(r.dwPID, row[0]);
strlcpy(r.szName, row[1], sizeof(r.szName));
strlcpy(r.szState, row[2], sizeof(r.szState));
str_to_number(r.lValue, row[3]);
}
sys_log(0, "QUEST_LOAD: count %d PID %u", s_table.size(), s_table[0].dwPID);
DWORD dwCount = s_table.size();
peer->EncodeHeader(HEADER_DG_QUEST_LOAD, dwHandle, sizeof(DWORD) + sizeof(TQuestTable) * dwCount);
peer->Encode(&dwCount, sizeof(DWORD));
peer->Encode(&s_table[0], sizeof(TQuestTable) * dwCount);
}
/*
* PLAYER SAVE
*/
void CClientManager::QUERY_PLAYER_SAVE(CPeer * peer, DWORD dwHandle, TPlayerTable * pkTab)
{
if (g_test_server)
sys_log(0, "PLAYER_SAVE: %s", pkTab->name);
PutPlayerCache(pkTab);
}
typedef std::map<DWORD, time_t> time_by_id_map_t;
static time_by_id_map_t s_createTimeByAccountID;
/*
* PLAYER CREATE
*/
void CClientManager::__QUERY_PLAYER_CREATE(CPeer *peer, DWORD dwHandle, TPlayerCreatePacket* packet)
{
char queryStr[QUERY_MAX_LEN];
int queryLen;
int player_id;
// ÇÑ °èÁ¤¿¡ XÃÊ ³»·Î ij¸¯ÅÍ »ý¼ºÀ» ÇÒ ¼ö ¾ø´Ù.
time_by_id_map_t::iterator it = s_createTimeByAccountID.find(packet->account_id);
if (it != s_createTimeByAccountID.end())
{
time_t curtime = time(0);
if (curtime - it->second < 30)
{
peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0);
return;
}
}
queryLen = snprintf(queryStr, sizeof(queryStr),
"SELECT pid%u FROM player_index%s WHERE id=%d", packet->account_index + 1, GetTablePostfix(), packet->account_id);
std::unique_ptr<SQLMsg> pMsg0(CDBManager::instance().DirectQuery(queryStr));
if (pMsg0->Get()->uiNumRows != 0)
{
if (!pMsg0->Get()->pSQLResult)
{
peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0);
return;
}
MYSQL_ROW row = mysql_fetch_row(pMsg0->Get()->pSQLResult);
DWORD dwPID = 0; str_to_number(dwPID, row[0]);
if (row[0] && dwPID > 0)
{
peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_ALREADY, dwHandle, 0);
sys_log(0, "ALREADY EXIST AccountChrIdx %d ID %d", packet->account_index, dwPID);
return;
}
}
else
{
peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0);
return;
}
if (g_stLocale == "sjis")
snprintf(queryStr, sizeof(queryStr),
"SELECT COUNT(*) as count FROM player%s WHERE name='%s' collate sjis_japanese_ci",
GetTablePostfix(), packet->player_table.name);
else
snprintf(queryStr, sizeof(queryStr),
"SELECT COUNT(*) as count FROM player%s WHERE name='%s'", GetTablePostfix(), packet->player_table.name);
std::unique_ptr<SQLMsg> pMsg1(CDBManager::instance().DirectQuery(queryStr));
if (pMsg1->Get()->uiNumRows)
{
if (!pMsg1->Get()->pSQLResult)
{
peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0);
return;
}
MYSQL_ROW row = mysql_fetch_row(pMsg1->Get()->pSQLResult);
if (*row[0] != '0')
{
sys_log(0, "ALREADY EXIST name %s, row[0] %s query %s", packet->player_table.name, row[0], queryStr);
peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_ALREADY, dwHandle, 0);
return;
}
}
else
{
peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0);
return;
}
queryLen = snprintf(queryStr, sizeof(queryStr),
"INSERT INTO player%s "
"(id, account_id, name, level, st, ht, dx, iq, "
"job, voice, dir, x, y, z, "
"hp, mp, random_hp, random_sp, stat_point, stamina, part_base, "
"part_main, part_hair, part_sash, gold, "
#ifdef ENABLE_GEM_SYSTEM
"gem, "
#endif
"playtime, skill_level, "
#ifdef ENABLE_FISH_EVENT
"fish_slots, "
#endif
#ifdef ENABLE_GEM_SYSTEM
"gem_items, "
#endif
#if defined(__PLAYER_PIN_SYSTEM__)
"pin, "
#endif
"quickslot) "
"VALUES(0, %u, '%s', %d, %d, %d, %d, %d, " // id, account_id, name, level, st, ht, dx, iq,
"%d, %d, %d, %d, %d, %d, " // job, voice, dir, x, y, z,
"%d, %d, %d, %d, %d, %d, %d, " // hp, mp, random_hp, random_sp, stat_point, stamina, part_base,
"0, 0, 0, %lld, " // part_main, part_hair, part_sash, gold,
#ifdef ENABLE_GEM_SYSTEM
"%d, "
#endif
#if defined(__PLAYER_PIN_SYSTEM__)
"'%s', "
#endif
"0, ", // playtime
GetTablePostfix(),
packet->account_id
, packet->player_table.name
, packet->player_table.level
, packet->player_table.st
, packet->player_table.ht
, packet->player_table.dx
, packet->player_table.iq
, packet->player_table.job
, packet->player_table.voice
, packet->player_table.dir
, packet->player_table.x
, packet->player_table.y
, packet->player_table.z
, packet->player_table.hp
, packet->player_table.sp
, packet->player_table.sRandomHP
, packet->player_table.sRandomSP
, packet->player_table.stat_point
, packet->player_table.stamina
, packet->player_table.part_base
, packet->player_table.part_base
, packet->player_table.gold
#ifdef ENABLE_GEM_SYSTEM
,packet->player_table.gem
#endif
#if defined(__PLAYER_PIN_SYSTEM__)
, packet->player_table.pin
#endif
);
sys_log(0, "PlayerCreate accountid %d name %s level %d gold %lld, st %d ht %d job %d",
packet->account_id,
packet->player_table.name,
packet->player_table.level,
packet->player_table.gold,
packet->player_table.st,
packet->player_table.ht,
packet->player_table.job);
static char text[4096 + 1];
CDBManager::instance().EscapeString(text, packet->player_table.skills, sizeof(packet->player_table.skills));
queryLen += snprintf(queryStr + queryLen, sizeof(queryStr) - queryLen, "'%s', ", text);
if (g_test_server)
sys_log(0, "Create_Player queryLen[%d] TEXT[%s]", queryLen, text);
#ifdef ENABLE_GEM_SYSTEM
CDBManager::instance().EscapeString(text, packet->player_table.quickslot, sizeof(packet->player_table.quickslot));
queryLen += snprintf(queryStr + queryLen, sizeof(queryStr) - queryLen, "'%s', ", text);
CDBManager::instance().EscapeString(text, packet->player_table.fishSlots, sizeof(packet->player_table.fishSlots));
queryLen += snprintf(queryStr + queryLen, sizeof(queryStr) - queryLen, "'%s', ", text);
CDBManager::instance().EscapeString(text, packet->player_table.gemItems, sizeof(packet->player_table.gemItems));
queryLen += snprintf(queryStr + queryLen, sizeof(queryStr) - queryLen, "'%s')", text);
#else
CDBManager::instance().EscapeString(text, packet->player_table.quickslot, sizeof(packet->player_table.quickslot));
queryLen += snprintf(queryStr + queryLen, sizeof(queryStr) - queryLen, "'%s')", text);
#endif
std::unique_ptr<SQLMsg> pMsg2(CDBManager::instance().DirectQuery(queryStr));
if (g_test_server)
sys_log(0, "Create_Player queryLen[%d] TEXT[%s]", queryLen, text);
if (pMsg2->Get()->uiAffectedRows <= 0)
{
peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_ALREADY, dwHandle, 0);
sys_log(0, "ALREADY EXIST3 query: %s AffectedRows %lu", queryStr, pMsg2->Get()->uiAffectedRows);
return;
}
player_id = pMsg2->Get()->uiInsertID;
snprintf(queryStr, sizeof(queryStr), "UPDATE player_index%s SET pid%d=%d WHERE id=%d",
GetTablePostfix(), packet->account_index + 1, player_id, packet->account_id);
std::unique_ptr<SQLMsg> pMsg3(CDBManager::instance().DirectQuery(queryStr));
if (pMsg3->Get()->uiAffectedRows <= 0)
{
sys_err("QUERY_ERROR: %s", queryStr);
snprintf(queryStr, sizeof(queryStr), "DELETE FROM player%s WHERE id=%d", GetTablePostfix(), player_id);
CDBManager::instance().DirectQuery(queryStr);
peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0);
return;
}
TPacketDGCreateSuccess pack;
memset(&pack, 0, sizeof(pack));
pack.bAccountCharacterIndex = packet->account_index;
pack.player.dwID = player_id;
strlcpy(pack.player.szName, packet->player_table.name, sizeof(pack.player.szName));
pack.player.byJob = packet->player_table.job;
pack.player.byLevel = 1;
pack.player.dwPlayMinutes = 0;
pack.player.byST = packet->player_table.st;
pack.player.byHT = packet->player_table.ht;
pack.player.byDX = packet->player_table.dx;
pack.player.byIQ = packet->player_table.iq;
pack.player.wMainPart = packet->player_table.part_base;
pack.player.x = packet->player_table.x;
pack.player.y = packet->player_table.y;
#if defined(__PLAYER_PIN_SYSTEM__)
strlcpy(pack.player.szPinCode, packet->player_table.pin, sizeof(pack.player.szPinCode));
#endif
peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_SUCCESS, dwHandle, sizeof(TPacketDGCreateSuccess));
peer->Encode(&pack, sizeof(TPacketDGCreateSuccess));
sys_log(0, "7 name %s job %d", pack.player.szName, pack.player.byJob);
s_createTimeByAccountID[packet->account_id] = time(0);
}
/*
* PLAYER DELETE
*/
void CClientManager::__QUERY_PLAYER_DELETE(CPeer* peer, DWORD dwHandle, TPlayerDeletePacket* packet)
{
if (!packet->login[0] || !packet->player_id || packet->account_index >= PLAYER_PER_ACCOUNT)
return;
CLoginData * ld = GetLoginDataByLogin(packet->login);
if (!ld)
{
peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, dwHandle, 1);
peer->EncodeBYTE(packet->account_index);
return;
}
TAccountTable & r = ld->GetAccountRef();
// block for japan
if (g_stLocale != "sjis")
{
if (!IsChinaEventServer())
{
if (strlen(r.social_id) < 7 || strncmp(packet->private_code, r.social_id + strlen(r.social_id) - 7, 7))
{
sys_log(0, "PLAYER_DELETE FAILED len(%d)", strlen(r.social_id));
peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, dwHandle, 1);
peer->EncodeBYTE(packet->account_index);
return;
}
CPlayerTableCache * pkPlayerCache = GetPlayerCache(packet->player_id);
if (pkPlayerCache)
{
TPlayerTable * pTab = pkPlayerCache->Get();
if (pTab->level >= m_iPlayerDeleteLevelLimit)
{
sys_log(0, "PLAYER_DELETE FAILED LEVEL %u >= DELETE LIMIT %d", pTab->level, m_iPlayerDeleteLevelLimit);
peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, dwHandle, 1);
peer->EncodeBYTE(packet->account_index);
return;
}
if (pTab->level < m_iPlayerDeleteLevelLimitLower)
{
sys_log(0, "PLAYER_DELETE FAILED LEVEL %u < DELETE LIMIT %d", pTab->level, m_iPlayerDeleteLevelLimitLower);
peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, dwHandle, 1);
peer->EncodeBYTE(packet->account_index);
return;
}
}
}
}
char szQuery[128];
snprintf(szQuery, sizeof(szQuery), "SELECT p.id, p.level, p.name FROM player_index%s AS i, player%s AS p WHERE pid%u=%u AND pid%u=p.id",
GetTablePostfix(), GetTablePostfix(), packet->account_index + 1, packet->player_id, packet->account_index + 1);
ClientHandleInfo * pi = new ClientHandleInfo(dwHandle, packet->player_id);
pi->account_index = packet->account_index;
sys_log(0, "PLAYER_DELETE TRY: %s %d pid%d", packet->login, packet->player_id, packet->account_index + 1);
CDBManager::instance().ReturnQuery(szQuery, QID_PLAYER_DELETE, peer->GetHandle(), pi);
}
//
// @version 05/06/10 Bang2ni - Ç÷¹ÀÌ¾î »èÁ¦½Ã °¡°ÝÁ¤º¸ ¸®½ºÆ® »èÁ¦ Ãß°¡.
//
void CClientManager::__RESULT_PLAYER_DELETE(CPeer *peer, SQLMsg* msg)
{
CQueryInfo * qi = (CQueryInfo *) msg->pvUserData;
ClientHandleInfo * pi = (ClientHandleInfo *) qi->pvData;
if (msg->Get() && msg->Get()->uiNumRows)
{
MYSQL_ROW row = mysql_fetch_row(msg->Get()->pSQLResult);
DWORD dwPID = 0;
str_to_number(dwPID, row[0]);
int deletedLevelLimit = 0;
str_to_number(deletedLevelLimit, row[1]);
char szName[64];
strlcpy(szName, row[2], sizeof(szName));
if (deletedLevelLimit >= m_iPlayerDeleteLevelLimit && !IsChinaEventServer())
{
sys_log(0, "PLAYER_DELETE FAILED LEVEL %u >= DELETE LIMIT %d", deletedLevelLimit, m_iPlayerDeleteLevelLimit);
peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, pi->dwHandle, 1);
peer->EncodeBYTE(pi->account_index);
return;
}
if (deletedLevelLimit < m_iPlayerDeleteLevelLimitLower)
{
sys_log(0, "PLAYER_DELETE FAILED LEVEL %u < DELETE LIMIT %d", deletedLevelLimit, m_iPlayerDeleteLevelLimitLower);
peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, pi->dwHandle, 1);
peer->EncodeBYTE(pi->account_index);
return;
}
char queryStr[QUERY_MAX_LEN];
snprintf(queryStr, sizeof(queryStr), "INSERT INTO player_deleted%s SELECT * FROM player%s WHERE id=%d",
GetTablePostfix(), GetTablePostfix(), pi->player_id);
std::unique_ptr<SQLMsg> pIns(CDBManager::instance().DirectQuery(queryStr));
if (pIns->Get()->uiAffectedRows == 0 || pIns->Get()->uiAffectedRows == (uint32_t)-1)
{
sys_log(0, "PLAYER_DELETE FAILED %u CANNOT INSERT TO player_deleted%s", dwPID, GetTablePostfix());
peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, pi->dwHandle, 1);
peer->EncodeBYTE(pi->account_index);
return;
}
// »èÁ¦ ¼º°ø
sys_log(0, "PLAYER_DELETE SUCCESS %u", dwPID);
char account_index_string[16];
snprintf(account_index_string, sizeof(account_index_string), "player_id%d", m_iPlayerIDStart + pi->account_index);
// Ç÷¹À̾î Å×À̺íÀ» ij½¬¿¡¼ »èÁ¦ÇÑ´Ù.
CPlayerTableCache * pkPlayerCache = GetPlayerCache(pi->player_id);
if (pkPlayerCache)
{
m_map_playerCache.erase(pi->player_id);
delete pkPlayerCache;
}
// ¾ÆÀÌÅÛµéÀ» ij½¬¿¡¼ »èÁ¦ÇÑ´Ù.
TItemCacheSet * pSet = GetItemCacheSet(pi->player_id);
if (pSet)
{
TItemCacheSet::iterator it = pSet->begin();
while (it != pSet->end())
{
CItemCache * pkItemCache = *it++;
DeleteItemCache(pkItemCache->Get()->id);
}
pSet->clear();
delete pSet;
m_map_pkItemCacheSetPtr.erase(pi->player_id);
}
snprintf(queryStr, sizeof(queryStr), "UPDATE player_index%s SET pid%u=0 WHERE pid%u=%d",
GetTablePostfix(),
pi->account_index + 1,
pi->account_index + 1,
pi->player_id);
std::unique_ptr<SQLMsg> pMsg(CDBManager::instance().DirectQuery(queryStr));
if (pMsg->Get()->uiAffectedRows == 0 || pMsg->Get()->uiAffectedRows == (uint32_t)-1)
{
sys_log(0, "PLAYER_DELETE FAIL WHEN UPDATE account table");
peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, pi->dwHandle, 1);
peer->EncodeBYTE(pi->account_index);
return;
}
snprintf(queryStr, sizeof(queryStr), "DELETE FROM player%s WHERE id=%d", GetTablePostfix(), pi->player_id);
delete CDBManager::instance().DirectQuery(queryStr);
#ifdef ENABLE_SWITCHBOT
snprintf(queryStr, sizeof(queryStr), "DELETE FROM item%s WHERE owner_id=%d AND (window < %d or window = %d or window = %d)", GetTablePostfix(), pi->player_id, SAFEBOX, DRAGON_SOUL_INVENTORY, UPGRADE_INVENTORY, BOOK_INVENTORY, STONE_INVENTORY, CHEST_INVENTORY, ATTR_INVENTORY, SWITCHBOT);
#else
snprintf(queryStr, sizeof(queryStr), "DELETE FROM item%s WHERE owner_id=%d AND (window < %d or window = %d)", GetTablePostfix(), pi->player_id,, SAFEBOX, DRAGON_SOUL_INVENTORY, UPGRADE_INVENTORY, BOOK_INVENTORY, STONE_INVENTORY, CHEST_INVENTORY, ATTR_INVENTORY,);
#endif
delete CDBManager::instance().DirectQuery(queryStr);
snprintf(queryStr, sizeof(queryStr), "DELETE FROM quest%s WHERE dwPID=%d", GetTablePostfix(), pi->player_id);
CDBManager::instance().AsyncQuery(queryStr);
snprintf(queryStr, sizeof(queryStr), "DELETE FROM affect%s WHERE dwPID=%d", GetTablePostfix(), pi->player_id);
CDBManager::instance().AsyncQuery(queryStr);
snprintf(queryStr, sizeof(queryStr), "DELETE FROM guild_member%s WHERE pid=%d", GetTablePostfix(), pi->player_id);
CDBManager::instance().AsyncQuery(queryStr);
// MYSHOP_PRICE_LIST
snprintf(queryStr, sizeof(queryStr), "DELETE FROM myshop_pricelist%s WHERE owner_id=%d", GetTablePostfix(), pi->player_id);
CDBManager::instance().AsyncQuery(queryStr);
// END_OF_MYSHOP_PRICE_LIST
snprintf(queryStr, sizeof(queryStr), "DELETE FROM messenger_list%s WHERE account='%s' OR companion='%s'", GetTablePostfix(), szName, szName);
CDBManager::instance().AsyncQuery(queryStr);
peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_SUCCESS, pi->dwHandle, 1);
peer->EncodeBYTE(pi->account_index);
}
else
{
// »èÁ¦ ½ÇÆÐ
sys_log(0, "PLAYER_DELETE FAIL NO ROW");
peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, pi->dwHandle, 1);
peer->EncodeBYTE(pi->account_index);
}
}
void CClientManager::QUERY_ADD_AFFECT(CPeer * peer, TPacketGDAddAffect * p)
{
char queryStr[QUERY_MAX_LEN];
/*
snprintf(queryStr, sizeof(queryStr),
"INSERT INTO affect%s (dwPID, bType, bApplyOn, lApplyValue, dwFlag, lDuration, lSPCost) "
"VALUES(%u, %u, %u, %d, %u, %d, %d) "
"ON DUPLICATE KEY UPDATE lApplyValue=%d, dwFlag=%u, lDuration=%d, lSPCost=%d",
GetTablePostfix(),
p->dwPID,
p->elem.dwType,
p->elem.bApplyOn,
p->elem.lApplyValue,
p->elem.dwFlag,
p->elem.lDuration,
p->elem.lSPCost,
p->elem.lApplyValue,
p->elem.dwFlag,
p->elem.lDuration,
p->elem.lSPCost);
*/
snprintf(queryStr, sizeof(queryStr),
"REPLACE INTO affect%s (dwPID, bType, bApplyOn, lApplyValue, dwFlag, lDuration, lSPCost) "
"VALUES(%u, %u, %u, %ld, %u, %ld, %ld)",
GetTablePostfix(),
p->dwPID,
p->elem.dwType,
p->elem.bApplyOn,
p->elem.lApplyValue,
p->elem.dwFlag,
p->elem.lDuration,
p->elem.lSPCost);
CDBManager::instance().AsyncQuery(queryStr);
}
void CClientManager::QUERY_REMOVE_AFFECT(CPeer * peer, TPacketGDRemoveAffect * p)
{
char queryStr[QUERY_MAX_LEN];
snprintf(queryStr, sizeof(queryStr),
"DELETE FROM affect%s WHERE dwPID=%u AND bType=%u AND bApplyOn=%u",
GetTablePostfix(), p->dwPID, p->dwType, p->bApplyOn);
CDBManager::instance().AsyncQuery(queryStr);
}
void CClientManager::QUERY_HIGHSCORE_REGISTER(CPeer* peer, TPacketGDHighscore * data)
{
char szQuery[128];
snprintf(szQuery, sizeof(szQuery), "SELECT value FROM highscore%s WHERE board='%s' AND pid = %u", GetTablePostfix(), data->szBoard, data->dwPID);
sys_log(0, "HEADER_GD_HIGHSCORE_REGISTER: PID %u", data->dwPID);
ClientHandleInfo * pi = new ClientHandleInfo(0);
strlcpy(pi->login, data->szBoard, sizeof(pi->login));
pi->account_id = (DWORD)data->lValue;
pi->player_id = data->dwPID;
pi->account_index = (data->cDir > 0);
CDBManager::instance().ReturnQuery(szQuery, QID_HIGHSCORE_REGISTER, peer->GetHandle(), pi);
}
void CClientManager::RESULT_HIGHSCORE_REGISTER(CPeer * pkPeer, SQLMsg * msg)
{
CQueryInfo * qi = (CQueryInfo *) msg->pvUserData;
ClientHandleInfo * pi = (ClientHandleInfo *) qi->pvData;
//DWORD dwHandle = pi->dwHandle;
char szBoard[21];
strlcpy(szBoard, pi->login, sizeof(szBoard));
int value = (int)pi->account_id;
SQLResult * res = msg->Get();
if (res->uiNumRows == 0)
{
// »õ·Î¿î ÇÏÀ̽ºÄھ »ðÀÔ
char buf[256];
snprintf(buf, sizeof(buf), "INSERT INTO highscore%s VALUES('%s', %u, %d)", GetTablePostfix(), szBoard, pi->player_id, value);
CDBManager::instance().AsyncQuery(buf);
}
else
{
if (!res->pSQLResult)
{
delete pi;
return;
}
MYSQL_ROW row = mysql_fetch_row(res->pSQLResult);
if (row && row[0])
{
int current_value = 0; str_to_number(current_value, row[0]);
if (((pi->account_index)&&(current_value >= value)) || ((!pi->account_index)&&(current_value <= value)))
{
value = current_value;
}
else
{
char buf[256];
snprintf(buf, sizeof(buf), "REPLACE INTO highscore%s VALUES('%s', %u, %d)", GetTablePostfix(), szBoard, pi->player_id, value);
CDBManager::instance().AsyncQuery(buf);
}
}
else
{
char buf[256];
snprintf(buf, sizeof(buf), "INSERT INTO highscore%s VALUES('%s', %u, %d)", GetTablePostfix(), szBoard, pi->player_id, value);
CDBManager::instance().AsyncQuery(buf);
}
}
// TODO: À̰÷¿¡¼ ÇÏÀ̽ºÄھ ¾÷µ¥ÀÌÆ® µÇ¾ú´ÂÁö üũÇÏ¿© °øÁö¸¦ »Ñ·Á¾ßÇÑ´Ù.
delete pi;
}
void CClientManager::InsertLogoutPlayer(DWORD pid)
{
TLogoutPlayerMap::iterator it = m_map_logout.find(pid);
// Á¸ÀçÇÏÁö ¾ÊÀ»°æ¿ì Ãß°¡
if (it != m_map_logout.end())
{
// Á¸ÀçÇÒ°æ¿ì ½Ã°£¸¸ °»½Å
if (g_log)
sys_log(0, "LOGOUT: Update player time pid(%d)", pid);
it->second->time = time(0);
return;
}
TLogoutPlayer * pLogout = new TLogoutPlayer;
pLogout->pid = pid;
pLogout->time = time(0);
m_map_logout.insert(std::make_pair(pid, pLogout));
if (g_log)
sys_log(0, "LOGOUT: Insert player pid(%d)", pid);
}
void CClientManager::DeleteLogoutPlayer(DWORD pid)
{
TLogoutPlayerMap::iterator it = m_map_logout.find(pid);
if (it != m_map_logout.end())
{
delete it->second;
m_map_logout.erase(it);
}
}
extern int g_iLogoutSeconds;
void CClientManager::UpdateLogoutPlayer()
{
time_t now = time(0);
TLogoutPlayerMap::iterator it = m_map_logout.begin();
while (it != m_map_logout.end())
{
TLogoutPlayer* pLogout = it->second;
if (now - g_iLogoutSeconds > pLogout->time)
{
FlushItemCacheSet(pLogout->pid);
FlushPlayerCacheSet(pLogout->pid);
delete pLogout;
m_map_logout.erase(it++);
}
else
++it;
}
}
void CClientManager::FlushPlayerCacheSet(DWORD pid)
{
TPlayerTableCacheMap::iterator it = m_map_playerCache.find(pid);
if (it != m_map_playerCache.end())
{
CPlayerTableCache * c = it->second;
m_map_playerCache.erase(it);
c->Flush();
delete c;
}
}
- iMerv3
- Nivel 1

- Mesaje: 86
- Membru din: 20 Mai 2020, 23:25
- Aprecieri: 85
- Mulţumiri: 159
- Discord: Copiază ID
- Contact:
Să începem de la:
1) Tu pentru câmpul asta:
Trimiți valoare int (totodată nu au nici o legatură):
2) Tu pentru câmpul asta:
queryLen = snprintf(queryStr, sizeof(queryStr),
"INSERT INTO player%s "
"(id, account_id, name, level, st, ht, dx, iq, "
"job, voice, dir, x, y, z, "
"hp, mp, random_hp, random_sp, stat_point, stamina, part_base, "
"part_main, part_hair, part_sash, gold, "
#ifdef ENABLE_GEM_SYSTEM
"gem, "
#endif
"playtime, skill_level, "
#ifdef ENABLE_FISH_EVENT
"fish_slots, "
#endif
#ifdef ENABLE_GEM_SYSTEM
"gem_items, "
#endif
#if defined(__PLAYER_PIN_SYSTEM__)
"pin, "
#endif
"quickslot) "
"VALUES(0, %u, '%s', %d, %d, %d, %d, %d, " // id, account_id, name, level, st, ht, dx, iq,
"%d, %d, %d, %d, %d, %d, " // job, voice, dir, x, y, z,
"%d, %d, %d, %d, %d, %d, %d, " // hp, mp, random_hp, random_sp, stat_point, stamina, part_base,
"0, 0, 0, %lld, " // part_main, part_hair, part_sash, gold,
#ifdef ENABLE_GEM_SYSTEM
"%d, "
#endif
#if defined(__PLAYER_PIN_SYSTEM__)
"'%s', "
#endif
"0, ", // playtime
GetTablePostfix(),
packet->account_id
, packet->player_table.name
, packet->player_table.level
, packet->player_table.st
, packet->player_table.ht
, packet->player_table.dx
, packet->player_table.iq
, packet->player_table.job
, packet->player_table.voice
, packet->player_table.dir
, packet->player_table.x
, packet->player_table.y
, packet->player_table.z
, packet->player_table.hp
, packet->player_table.sp
, packet->player_table.sRandomHP
, packet->player_table.sRandomSP
, packet->player_table.stat_point
, packet->player_table.stamina
, packet->player_table.part_base
, packet->player_table.part_base
, packet->player_table.gold
#ifdef ENABLE_GEM_SYSTEM
,packet->player_table.gem
#endif
#if defined(__PLAYER_PIN_SYSTEM__)
, packet->player_table.pin
#endif
);
"INSERT INTO player%s "
"(id, account_id, name, level, st, ht, dx, iq, "
"job, voice, dir, x, y, z, "
"hp, mp, random_hp, random_sp, stat_point, stamina, part_base, "
"part_main, part_hair, part_sash, gold, "
#ifdef ENABLE_GEM_SYSTEM
"gem, "
#endif
"playtime, skill_level, "
#ifdef ENABLE_FISH_EVENT
"fish_slots, "
#endif
#ifdef ENABLE_GEM_SYSTEM
"gem_items, "
#endif
#if defined(__PLAYER_PIN_SYSTEM__)
"pin, "
#endif
"quickslot) "
"VALUES(0, %u, '%s', %d, %d, %d, %d, %d, " // id, account_id, name, level, st, ht, dx, iq,
"%d, %d, %d, %d, %d, %d, " // job, voice, dir, x, y, z,
"%d, %d, %d, %d, %d, %d, %d, " // hp, mp, random_hp, random_sp, stat_point, stamina, part_base,
"0, 0, 0, %lld, " // part_main, part_hair, part_sash, gold,
#ifdef ENABLE_GEM_SYSTEM
"%d, "
#endif
#if defined(__PLAYER_PIN_SYSTEM__)
"'%s', "
#endif
"0, ", // playtime
GetTablePostfix(),
packet->account_id
, packet->player_table.name
, packet->player_table.level
, packet->player_table.st
, packet->player_table.ht
, packet->player_table.dx
, packet->player_table.iq
, packet->player_table.job
, packet->player_table.voice
, packet->player_table.dir
, packet->player_table.x
, packet->player_table.y
, packet->player_table.z
, packet->player_table.hp
, packet->player_table.sp
, packet->player_table.sRandomHP
, packet->player_table.sRandomSP
, packet->player_table.stat_point
, packet->player_table.stamina
, packet->player_table.part_base
, packet->player_table.part_base
, packet->player_table.gold
#ifdef ENABLE_GEM_SYSTEM
,packet->player_table.gem
#endif
#if defined(__PLAYER_PIN_SYSTEM__)
, packet->player_table.pin
#endif
);
1) Tu pentru câmpul asta:
#ifdef ENABLE_FISH_EVENT
"fish_slots, "
#endif
"fish_slots, "
#endif
#ifdef ENABLE_GEM_SYSTEM
,packet->player_table.gem
#endif
,packet->player_table.gem
#endif
2) Tu pentru câmpul asta:
#ifdef ENABLE_GEM_SYSTEM
"gem_items, "
#endif
Trimiți valoare str (totodată nu au nici o legatură):
Sper că m-am făcut înțeles, nu dai destule argumente la query și ar trebuii deja să ai un warning la compilare. Iar unele le dai în ordinea greșită
.
"gem_items, "
#endif
Trimiți valoare str (totodată nu au nici o legatură):
#if defined(__PLAYER_PIN_SYSTEM__)
"'%s', "
#endif
"'%s', "
#endif
- Hamish
- Nivel 1

iMerv3iMerv3 scrie: ↑09 Dec 2021, 19:11 Să începem de la:queryLen = snprintf(queryStr, sizeof(queryStr),
"INSERT INTO player%s "
"(id, account_id, name, level, st, ht, dx, iq, "
"job, voice, dir, x, y, z, "
"hp, mp, random_hp, random_sp, stat_point, stamina, part_base, "
"part_main, part_hair, part_sash, gold, "
#ifdef ENABLE_GEM_SYSTEM
"gem, "
#endif
"playtime, skill_level, "
#ifdef ENABLE_FISH_EVENT
"fish_slots, "
#endif
#ifdef ENABLE_GEM_SYSTEM
"gem_items, "
#endif
#if defined(__PLAYER_PIN_SYSTEM__)
"pin, "
#endif
"quickslot) "
"VALUES(0, %u, '%s', %d, %d, %d, %d, %d, " // id, account_id, name, level, st, ht, dx, iq,
"%d, %d, %d, %d, %d, %d, " // job, voice, dir, x, y, z,
"%d, %d, %d, %d, %d, %d, %d, " // hp, mp, random_hp, random_sp, stat_point, stamina, part_base,
"0, 0, 0, %lld, " // part_main, part_hair, part_sash, gold,
#ifdef ENABLE_GEM_SYSTEM
"%d, "
#endif
#if defined(__PLAYER_PIN_SYSTEM__)
"'%s', "
#endif
"0, ", // playtime
GetTablePostfix(),
packet->account_id
, packet->player_table.name
, packet->player_table.level
, packet->player_table.st
, packet->player_table.ht
, packet->player_table.dx
, packet->player_table.iq
, packet->player_table.job
, packet->player_table.voice
, packet->player_table.dir
, packet->player_table.x
, packet->player_table.y
, packet->player_table.z
, packet->player_table.hp
, packet->player_table.sp
, packet->player_table.sRandomHP
, packet->player_table.sRandomSP
, packet->player_table.stat_point
, packet->player_table.stamina
, packet->player_table.part_base
, packet->player_table.part_base
, packet->player_table.gold
#ifdef ENABLE_GEM_SYSTEM
,packet->player_table.gem
#endif
#if defined(__PLAYER_PIN_SYSTEM__)
, packet->player_table.pin
#endif
);
1) Tu pentru câmpul asta:Trimiți valoare int (totodată nu au nici o legatură):#ifdef ENABLE_FISH_EVENT
"fish_slots, "
#endif#ifdef ENABLE_GEM_SYSTEM
,packet->player_table.gem
#endif
2) Tu pentru câmpul asta:#ifdef ENABLE_GEM_SYSTEM
"gem_items, "
#endif
Trimiți valoare str (totodată nu au nici o legatură):Sper că m-am făcut înțeles, nu dai destule argumente la query și ar trebuii deja să ai un warning la compilare. Iar unele le dai în ordinea greșită#if defined(__PLAYER_PIN_SYSTEM__)
"'%s', "
#endif.
queryLen = snprintf(queryStr, sizeof(queryStr), "INSERT INTO player%s " "(id, account_id, name, level, st, ht, dx, iq, " "job, voice, dir, x, y, z, " "hp, mp, random_hp, random_sp, stat_point, stamina, part_base, " "part_main, part_hair, part_sash, gold, " #ifdef ENABLE_GEM_SYSTEM "gem, " #endif #if defined(__PLAYER_PIN_SYSTEM__) "pin, " #endif "playtime, skill_level, " #ifdef ENABLE_FISH_EVENT "fish_slots, " #endif #ifdef ENABLE_GEM_SYSTEM "gem_items, " #endif "quickslot) " "VALUES(0, %u, '%s', %d, %d, %d, %d, %d, " // id, account_id, name, level, st, ht, dx, iq, "%d, %d, %d, %d, %d, %d, " // job, voice, dir, x, y, z, "%d, %d, %d, %d, %d, %d, %d, " // hp, mp, random_hp, random_sp, stat_point, stamina, part_base, "0, 0, 0, %lld, " // part_main, part_hair, part_sash, gold, #ifdef ENABLE_GEM_SYSTEM "%d, " #endif #if defined(__PLAYER_PIN_SYSTEM__) "'%s', " #endif "0, ", // playtime GetTablePostfix(), packet->account_id, packet->player_table.name, packet->player_table.level, packet->player_table.st, packet->player_table.ht, packet->player_table.dx, packet->player_table.iq, packet->player_table.job, packet->player_table.voice, packet->player_table.dir, packet->player_table.x, packet->player_table.y, packet->player_table.z, packet->player_table.hp, packet->player_table.sp, packet->player_table.sRandomHP, packet->player_table.sRandomSP, packet->player_table.stat_point, packet->player_table.stamina, packet->player_table.part_base, packet->player_table.part_base, packet->player_table.gold #ifdef ENABLE_GEM_SYSTEM ,packet->player_table.gem #endif #if defined(__PLAYER_PIN_SYSTEM__) , packet->player_table.pin #endif );Am modificat in felul urmator dar tot nu imi dau seama unde gresesc...
In tabel tot nu se salveaza si imi afisaza "(null)"
- iMerv3
- Nivel 1

- Mesaje: 86
- Membru din: 20 Mai 2020, 23:25
- Aprecieri: 85
- Mulţumiri: 159
- Discord: Copiază ID
- Contact:
[PVM EASY]BrilliantsMt2 | new evo | system language | system pet | system costumes ! [OFFICIAL]
Răspunsuri
21 Vizualizări
3802
21 Vizualizări
3802
[PVM EASY]BrilliantsMt2 | new evo | system language | system pet | system costumes ! [OFFICIAL]
Răspunsuri
1 Vizualizări
324
1 Vizualizări
324
Înapoi la “Arhivă Probleme şi Întrebări”
Mergi la
- Comunitate
- ↳ Forumul Just4Metin
- ↳ Începători
- ↳ Prezentare membri
- ↳ Noutăţi
- ↳ Echipă
- ↳ Cunoaşte echipa
- ↳ Arhivă
- ↳ Anunţuri Oficiale
- ↳ Concursuri și Tombole
- Resurse şi informaţii servere metin2
- ↳ Ghiduri şi Tutoriale
- ↳ Ghiduri Joc
- ↳ Arhivă
- ↳ Resurse Metin2
- ↳ Serverfiles
- ↳ Serverfiles Clean
- ↳ Client-uri
- ↳ Interfete client
- ↳ Surse
- ↳ Harți
- ↳ Autopatcher
- ↳ Aplicații utile
- ↳ Altele
- ↳ Arhivă
- ↳ Dezvoltare server
- ↳ Quest-uri
- ↳ FreeBSD
- ↳ Securitate și protecție hackuri
- ↳ Arhivă
- ↳ Modele 3D
- ↳ Costume
- ↳ Arme
- ↳ Armuri
- ↳ Mobi
- ↳ Npc-uri
- ↳ Pet-uri
- ↳ Mounturi
- ↳ Eșarfe
- ↳ Frizuri
- ↳ Obiecte
- ↳ Efecte
- ↳ Pietre Metin
- ↳ Animații GR2
- ↳ Altele
- ↳ Pachet resurse
- ↳ Arhivă
- ↳ Web Scripting
- ↳ Homepage-uri Premium
- ↳ Homepage-uri Gratuite
- ↳ Tutoriale scripting
- ↳ Întrebări şi probleme
- ↳ Arhivă
- ↳ Probleme Rezolvate
- ↳ Index/Intro Page
- ↳ Arhivă
- Metin2
- ↳ Servere Certificate
- ↳ Obține Certificat
- ↳ Arhivă
- ↳ Servere Private
- ↳ Arhivă
- ↳ Servere Private - aflate în faza de proiect
- ↳ Videoclipuri Metin2
- ↳ Arhivă
- Zona ajutor
- ↳ Probleme şi Întrebări
- ↳ Arhivă Probleme şi Întrebări
- ↳ Probleme rezolvate
- ↳ Cereri
- ↳ Arhivă
- ↳ Cereri Rezolvate
- Mica publicitate
- ↳ Anunturi diverse
- ↳ Arhivă
- ↳ Intermediari
- ↳ Servicii si vanzari Metin2
- ↳ Servicii
- ↳ Serverfile si surse
- ↳ Sisteme si coduri
- ↳ Web Scripting si Design
- ↳ 3d Models
- ↳ Arhiva
- ↳ Firme de Hosting
- ↳ Reclamații
- ↳ Contestatii sau rezolvari reclamatii si conturi blocate
- Diverse
- ↳ Discuţii diverse
- ↳ Arhivă
- ↳ Zile de naștere
- ↳ Hobby-uri
- ↳ Seriale
- ↳ Filme
- ↳ Sport
- ↳ Foto/video
- ↳ Calatorii
- ↳ Alte hobby-uri
- ↳ Jocuri
- ↳ Jocuri PC
- ↳ League of Legends
- ↳ World of Warcraft
- ↳ Grand Theft Auto
- ↳ DayZ
- ↳ Minecraft
- ↳ Counter-Strike
- ↳ Alte jocuri
- ↳ Jocuri Console
- ↳ Software
- ↳ Distracţie/Divertisment
- ↳ Filmuleţe amuzante
- ↳ Muzică
- ↳ Bancuri
- ↳ Spam
- ↳ Arhivă
- ↳ Grafică
- ↳ Arhivă
- ↳ Cereri
- ↳ Subiecte vechi
- ↳ Cereri avatare
- ↳ Cereri semnături
- ↳ Portofolii
- ↳ Bătălii
- ↳ Bătălii Finalizate
- ↳ Tutoriale
- ↳ Resurse
- ↳ Cadouri
- Topicuri şi mesaje şterse
- ↳ Arhivă
- ↳ Imagini şi videoclipuri
- ↳ Discuţii generale
- ↳ Bug-uri (Erori)
- ↳ Reclamaţii
- ↳ Reclamaţii jucători
- ↳ Reclamaţii echipă
- ↳ Deblocare cont
- ↳ Punct de negoţ
- ↳ Vânzări
- ↳ Cumpărări
- ↳ Idei şi sugestii
- ↳ Cerere Moderator
- ↳ Arhivă
- ↳ Metin2 - Site-ul serverului.
- ↳ Punct de negoţ
- ↳ Vânzări
- ↳ Cumpărări
- ↳ Probleme şi întrebări
- ↳ Idei şi sugestii
- ↳ Metin2 - Loc Liber
- ↳ Anunţuri şi Noutăţi
- ↳ Loc Liber- Facebook
- ↳ Reclamaţii
- ↳ Reclamaţii jucători
- ↳ Reclamaţii echipă
- ↳ Bug-uri (Erori)
- ↳ Prezentări
- ↳ Prezentare breaslă
- ↳ Imagini şi videoclipuri
- ↳ Contestaţii
- ↳ Discuţii generale
- ↳ Arhivă
- ↳ Cerere Moderator
- Clubul Just4Metin
- ↳ Clubul Just4Metin - Alătură-te nouă
-
- Informaţie
-
Cine este conectat
Utilizatori ce ce navighează pe acest forum: Niciun utilizator înregistrat și 78 vizitatori
de