1. #include "stdafx.h"
  2. #include "constants.h"
  3. #include "../../common/teen_packet.h"
  4. #include "config.h"
  5. #include "utils.h"
  6. #include "input.h"
  7. #include "desc_client.h"
  8. #include "desc_manager.h"
  9. #include "char.h"
  10. #include "char_manager.h"
  11. #include "cmd.h"
  12. #include "buffer_manager.h"
  13. #include "protocol.h"
  14. #include "pvp.h"
  15. #include "New_PetSystem.h"
  16. #include "start_position.h"
  17. #include "messenger_manager.h"
  18. #include "guild_manager.h"
  19. #include "party.h"
  20. #include "dungeon.h"
  21. #include "war_map.h"
  22. #include "questmanager.h"
  23. #include "building.h"
  24. #include "wedding.h"
  25. #include "affect.h"
  26. #include "arena.h"
  27. #include "OXEvent.h"
  28. #include "priv_manager.h"
  29. #include "block_country.h"
  30. #include "dev_log.h"
  31. #include "log.h"
  32. #include "horsename_manager.h"
  33. #include "MarkManager.h"
  34. #include "HackShield.h"
  35. #include "XTrapManager.h"
  36. #include "questlua.h"
  37. #ifdef ENABLE_ATTENDANCE_EVENT
  38. #include "minigame.h"
  39. #endif
  40. #ifdef __MELEY_LAIR_DUNGEON__
  41. #include "MeleyLair.h"
  42. #endif
  43. #include "../../common/CommonDefines.h"
  44. #include "../../common/service.h"
  45. #ifdef ENABLE_DUNGEON_INFORMATION
  46. #include "DungeonInformation.h"
  47. #endif
  48. #ifdef ENABLE_WOLFMAN_CHARACTER
  49. // #define USE_LYCAN_CREATE_POSITION
  50. #ifdef USE_LYCAN_CREATE_POSITION
  51. DWORD g_lycan_create_position[4][2] =
  52. {
  53. { 0, 0 },
  54. { 768000+38300, 896000+35500 },
  55. { 819200+38300, 896000+35500 },
  56. { 870400+38300, 896000+35500 },
  57. };
  58. inline DWORD LYCAN_CREATE_START_X(BYTE e, BYTE job)
  59. {
  60. if (1 <= e && e <= 3)
  61. return (job==JOB_WOLFMAN)?g_lycan_create_position[e][0]:g_create_position[e][0];
  62. return 0;
  63. }
  64. inline DWORD LYCAN_CREATE_START_Y(BYTE e, BYTE job)
  65. {
  66. if (1 <= e && e <= 3)
  67. return (job==JOB_WOLFMAN)?g_lycan_create_position[e][1]:g_create_position[e][1];
  68. return 0;
  69. }
  70. #endif
  71. #endif
  72. static void _send_bonus_info(LPCHARACTER ch)
  73. {
  74. int item_drop_bonus = 0;
  75. int gold_drop_bonus = 0;
  76. int gold10_drop_bonus = 0;
  77. int exp_bonus = 0;
  78. item_drop_bonus = CPrivManager::instance().GetPriv(ch, PRIV_ITEM_DROP);
  79. gold_drop_bonus = CPrivManager::instance().GetPriv(ch, PRIV_GOLD_DROP);
  80. gold10_drop_bonus = CPrivManager::instance().GetPriv(ch, PRIV_GOLD10_DROP);
  81. exp_bonus = CPrivManager::instance().GetPriv(ch, PRIV_EXP_PCT);
  82. if (item_drop_bonus)
  83. {
  84. ch->ChatPacket(CHAT_TYPE_NOTICE,
  85. LC_TEXT("아이템 드롭률 %d%% 추가 이벤트 중입니다."), item_drop_bonus);
  86. }
  87. if (gold_drop_bonus)
  88. {
  89. ch->ChatPacket(CHAT_TYPE_NOTICE,
  90. LC_TEXT("골드 드롭률 %d%% 추가 이벤트 중입니다."), gold_drop_bonus);
  91. }
  92. if (gold10_drop_bonus)
  93. {
  94. ch->ChatPacket(CHAT_TYPE_NOTICE,
  95. LC_TEXT("대박골드 드롭률 %d%% 추가 이벤트 중입니다."), gold10_drop_bonus);
  96. }
  97. if (exp_bonus)
  98. {
  99. ch->ChatPacket(CHAT_TYPE_NOTICE,
  100. LC_TEXT("경험치 %d%% 추가 획득 이벤트 중입니다."), exp_bonus);
  101. }
  102. }
  103. static bool FN_is_battle_zone(LPCHARACTER ch)
  104. {
  105. switch (ch->GetMapIndex())
  106. {
  107. case 1: // 신수 1차 마을
  108. case 2: // 신수 2차 마을
  109. case 21: // 천조 1차 마을
  110. case 23: // 천조 2차 마을
  111. case 41: // 진노 1차 마을
  112. case 43: // 진노 2차 마을
  113. case 113: // OX 맵
  114. return false;
  115. }
  116. return true;
  117. }
  118. void CInputLogin::Login(LPDESC d, const char * data)
  119. {
  120. TPacketCGLogin * pinfo = (TPacketCGLogin *) data;
  121. char login[LOGIN_MAX_LEN + 1];
  122. trim_and_lower(pinfo->login, login, sizeof(login));
  123. sys_log(0, "InputLogin::Login : %s", login);
  124. TPacketGCLoginFailure failurePacket;
  125. if (!test_server)
  126. {
  127. failurePacket.header = HEADER_GC_LOGIN_FAILURE;
  128. strlcpy(failurePacket.szStatus, "VERSION", sizeof(failurePacket.szStatus));
  129. d->Packet(&failurePacket, sizeof(TPacketGCLoginFailure));
  130. return;
  131. }
  132. if (g_bNoMoreClient)
  133. {
  134. failurePacket.header = HEADER_GC_LOGIN_FAILURE;
  135. strlcpy(failurePacket.szStatus, "SHUTDOWN", sizeof(failurePacket.szStatus));
  136. d->Packet(&failurePacket, sizeof(TPacketGCLoginFailure));
  137. return;
  138. }
  139. if (g_iUserLimit > 0)
  140. {
  141. int iTotal;
  142. int * paiEmpireUserCount;
  143. int iLocal;
  144. DESC_MANAGER::instance().GetUserCount(iTotal, &paiEmpireUserCount, iLocal);
  145. if (g_iUserLimit <= iTotal)
  146. {
  147. failurePacket.header = HEADER_GC_LOGIN_FAILURE;
  148. strlcpy(failurePacket.szStatus, "FULL", sizeof(failurePacket.szStatus));
  149. d->Packet(&failurePacket, sizeof(TPacketGCLoginFailure));
  150. return;
  151. }
  152. }
  153. TLoginPacket login_packet;
  154. strlcpy(login_packet.login, login, sizeof(login_packet.login));
  155. strlcpy(login_packet.passwd, pinfo->passwd, sizeof(login_packet.passwd));
  156. db_clientdesc->DBPacket(HEADER_GD_LOGIN, d->GetHandle(), &login_packet, sizeof(TLoginPacket));
  157. }
  158. void CInputLogin::LoginByKey(LPDESC d, const char * data)
  159. {
  160. TPacketCGLogin2 * pinfo = (TPacketCGLogin2 *) data;
  161. char login[LOGIN_MAX_LEN + 1];
  162. trim_and_lower(pinfo->login, login, sizeof(login));
  163. // is blocked ip?
  164. {
  165. dev_log(LOG_DEB0, "check_blocked_country_start");
  166. if (!is_block_exception(login) && is_blocked_country_ip(d->GetHostName()))
  167. {
  168. sys_log(0, "BLOCK_COUNTRY_IP (%s)", d->GetHostName());
  169. d->SetPhase(PHASE_CLOSE);
  170. return;
  171. }
  172. dev_log(LOG_DEB0, "check_blocked_country_end");
  173. }
  174. if (g_bNoMoreClient)
  175. {
  176. TPacketGCLoginFailure failurePacket;
  177. failurePacket.header = HEADER_GC_LOGIN_FAILURE;
  178. strlcpy(failurePacket.szStatus, "SHUTDOWN", sizeof(failurePacket.szStatus));
  179. d->Packet(&failurePacket, sizeof(TPacketGCLoginFailure));
  180. return;
  181. }
  182. if (g_iUserLimit > 0)
  183. {
  184. int iTotal;
  185. int * paiEmpireUserCount;
  186. int iLocal;
  187. DESC_MANAGER::instance().GetUserCount(iTotal, &paiEmpireUserCount, iLocal);
  188. if (g_iUserLimit <= iTotal)
  189. {
  190. TPacketGCLoginFailure failurePacket;
  191. failurePacket.header = HEADER_GC_LOGIN_FAILURE;
  192. strlcpy(failurePacket.szStatus, "FULL", sizeof(failurePacket.szStatus));
  193. d->Packet(&failurePacket, sizeof(TPacketGCLoginFailure));
  194. return;
  195. }
  196. }
  197. sys_log(0, "LOGIN_BY_KEY: %s key %u", login, pinfo->dwLoginKey);
  198. d->SetLoginKey(pinfo->dwLoginKey);
  199. #ifndef _IMPROVED_PACKET_ENCRYPTION_
  200. d->SetSecurityKey(pinfo->adwClientKey);
  201. #endif
  202. TPacketGDLoginByKey ptod;
  203. strlcpy(ptod.szLogin, login, sizeof(ptod.szLogin));
  204. ptod.dwLoginKey = pinfo->dwLoginKey;
  205. thecore_memcpy(ptod.adwClientKey, pinfo->adwClientKey, sizeof(DWORD) * 4);
  206. strlcpy(ptod.szIP, d->GetHostName(), sizeof(ptod.szIP));
  207. db_clientdesc->DBPacket(HEADER_GD_LOGIN_BY_KEY, d->GetHandle(), &ptod, sizeof(TPacketGDLoginByKey));
  208. }
  209. void CInputLogin::ChangeName(LPDESC d, const char * data)
  210. {
  211. TPacketCGChangeName * p = (TPacketCGChangeName *) data;
  212. const TAccountTable & c_r = d->GetAccountTable();
  213. if (!c_r.id)
  214. {
  215. sys_err("no account table");
  216. return;
  217. }
  218. if (!c_r.players[p->index].bChangeName)
  219. return;
  220. if (!check_name(p->name))
  221. {
  222. TPacketGCCreateFailure pack;
  223. pack.header = HEADER_GC_CHARACTER_CREATE_FAILURE;
  224. pack.bType = 0;
  225. d->Packet(&pack, sizeof(pack));
  226. return;
  227. }
  228. TPacketGDChangeName pdb;
  229. pdb.pid = c_r.players[p->index].dwID;
  230. strlcpy(pdb.name, p->name, sizeof(pdb.name));
  231. db_clientdesc->DBPacket(HEADER_GD_CHANGE_NAME, d->GetHandle(), &pdb, sizeof(TPacketGDChangeName));
  232. }
  233. void CInputLogin::CharacterSelect(LPDESC d, const char * data)
  234. {
  235. struct command_player_select * pinfo = (struct command_player_select *) data;
  236. const TAccountTable & c_r = d->GetAccountTable();
  237. sys_log(0, "player_select: login: %s index: %d", c_r.login, pinfo->index);
  238. if (!c_r.id)
  239. {
  240. sys_err("no account table");
  241. return;
  242. }
  243. if (pinfo->index >= PLAYER_PER_ACCOUNT)
  244. {
  245. sys_err("index overflow %d, login: %s", pinfo->index, c_r.login);
  246. return;
  247. }
  248. if (c_r.players[pinfo->index].bChangeName)
  249. {
  250. sys_err("name must be changed idx %d, login %s, name %s",
  251. pinfo->index, c_r.login, c_r.players[pinfo->index].szName);
  252. return;
  253. }
  254. TPlayerLoadPacket player_load_packet;
  255. player_load_packet.account_id = c_r.id;
  256. player_load_packet.player_id = c_r.players[pinfo->index].dwID;
  257. player_load_packet.account_index = pinfo->index;
  258. db_clientdesc->DBPacket(HEADER_GD_PLAYER_LOAD, d->GetHandle(), &player_load_packet, sizeof(TPlayerLoadPacket));
  259. }
  260. bool NewPlayerTable(TPlayerTable * table,
  261. const char * name,
  262. BYTE job,
  263. BYTE shape,
  264. BYTE bEmpire,
  265. BYTE bCon,
  266. BYTE bInt,
  267. BYTE bStr,
  268. BYTE bDex)
  269. {
  270. if (job >= JOB_MAX_NUM)
  271. return false;
  272. memset(table, 0, sizeof(TPlayerTable));
  273. strlcpy(table->name, name, sizeof(table->name));
  274. table->level = 1;
  275. table->job = job;
  276. table->voice = 0;
  277. table->part_base = shape;
  278. table->st = JobInitialPoints[job].st;
  279. table->dx = JobInitialPoints[job].dx;
  280. table->ht = JobInitialPoints[job].ht;
  281. table->iq = JobInitialPoints[job].iq;
  282. table->hp = JobInitialPoints[job].max_hp + table->ht * JobInitialPoints[job].hp_per_ht;
  283. table->sp = JobInitialPoints[job].max_sp + table->iq * JobInitialPoints[job].sp_per_iq;
  284. table->stamina = JobInitialPoints[job].max_stamina;
  285. #if defined(ENABLE_WOLFMAN_CHARACTER) && defined(USE_LYCAN_CREATE_POSITION)
  286. table->x = LYCAN_CREATE_START_X(bEmpire, job) + number(-300, 300);
  287. table->y = LYCAN_CREATE_START_Y(bEmpire, job) + number(-300, 300);
  288. #else
  289. table->x = CREATE_START_X(bEmpire) + number(-300, 300);
  290. table->y = CREATE_START_Y(bEmpire) + number(-300, 300);
  291. #endif
  292. table->z = 0;
  293. table->dir = 0;
  294. table->playtime = 0;
  295. table->gold = 0;
  296. table->skill_group = 0;
  297. if (china_event_server)
  298. {
  299. table->level = 35;
  300. for (int i = 1; i < 35; ++i)
  301. {
  302. int iHP = number(JobInitialPoints[job].hp_per_lv_begin, JobInitialPoints[job].hp_per_lv_end);
  303. int iSP = number(JobInitialPoints[job].sp_per_lv_begin, JobInitialPoints[job].sp_per_lv_end);
  304. table->sRandomHP += iHP;
  305. table->sRandomSP += iSP;
  306. table->stat_point += 3;
  307. }
  308. table->hp += table->sRandomHP;
  309. table->sp += table->sRandomSP;
  310. table->gold = 1000000;
  311. }
  312. return true;
  313. }
  314. bool RaceToJob(unsigned race, unsigned* ret_job)
  315. {
  316. *ret_job = 0;
  317. if (race >= MAIN_RACE_MAX_NUM)
  318. return false;
  319. switch (race)
  320. {
  321. case MAIN_RACE_WARRIOR_M:
  322. *ret_job = JOB_WARRIOR;
  323. break;
  324. case MAIN_RACE_WARRIOR_W:
  325. *ret_job = JOB_WARRIOR;
  326. break;
  327. case MAIN_RACE_ASSASSIN_M:
  328. *ret_job = JOB_ASSASSIN;
  329. break;
  330. case MAIN_RACE_ASSASSIN_W:
  331. *ret_job = JOB_ASSASSIN;
  332. break;
  333. case MAIN_RACE_SURA_M:
  334. *ret_job = JOB_SURA;
  335. break;
  336. case MAIN_RACE_SURA_W:
  337. *ret_job = JOB_SURA;
  338. break;
  339. case MAIN_RACE_SHAMAN_M:
  340. *ret_job = JOB_SHAMAN;
  341. break;
  342. case MAIN_RACE_SHAMAN_W:
  343. *ret_job = JOB_SHAMAN;
  344. break;
  345. #ifdef ENABLE_WOLFMAN_CHARACTER
  346. case MAIN_RACE_WOLFMAN_M:
  347. *ret_job = JOB_WOLFMAN;
  348. break;
  349. #endif
  350. default:
  351. return false;
  352. break;
  353. }
  354. return true;
  355. }
  356. // 신규 캐릭터 지원
  357. bool NewPlayerTable2(TPlayerTable * table, const char * name, BYTE race, BYTE shape, BYTE bEmpire)
  358. {
  359. if (race >= MAIN_RACE_MAX_NUM)
  360. {
  361. sys_err("NewPlayerTable2.OUT_OF_RACE_RANGE(%d >= max(%d))\n", race, MAIN_RACE_MAX_NUM);
  362. return false;
  363. }
  364. unsigned job;
  365. if (!RaceToJob(race, &job))
  366. {
  367. sys_err("NewPlayerTable2.RACE_TO_JOB_ERROR(%d)\n", race);
  368. return false;
  369. }
  370. sys_log(0, "NewPlayerTable2(name=%s, race=%d, job=%d)", name, race, job);
  371. memset(table, 0, sizeof(TPlayerTable));
  372. strlcpy(table->name, name, sizeof(table->name));
  373. table->level = 1;
  374. table->job = race; // 직업대신 종족을 넣는다
  375. table->voice = 0;
  376. table->part_base = shape;
  377. table->st = JobInitialPoints[job].st;
  378. table->dx = JobInitialPoints[job].dx;
  379. table->ht = JobInitialPoints[job].ht;
  380. table->iq = JobInitialPoints[job].iq;
  381. table->hp = JobInitialPoints[job].max_hp + table->ht * JobInitialPoints[job].hp_per_ht;
  382. table->sp = JobInitialPoints[job].max_sp + table->iq * JobInitialPoints[job].sp_per_iq;
  383. table->stamina = JobInitialPoints[job].max_stamina;
  384. #if defined(ENABLE_WOLFMAN_CHARACTER) && defined(USE_LYCAN_CREATE_POSITION)
  385. table->x = LYCAN_CREATE_START_X(bEmpire, job) + number(-300, 300);
  386. table->y = LYCAN_CREATE_START_Y(bEmpire, job) + number(-300, 300);
  387. #else
  388. table->x = CREATE_START_X(bEmpire) + number(-300, 300);
  389. table->y = CREATE_START_Y(bEmpire) + number(-300, 300);
  390. #endif
  391. table->z = 0;
  392. table->dir = 0;
  393. table->playtime = 0;
  394. table->gold = 0;
  395. #ifdef ENABLE_GEM_SYSTEM
  396. table->gem = 0;
  397. #endif
  398. table->skill_group = 0;
  399. return true;
  400. }
  401. void CInputLogin::CharacterCreate(LPDESC d, const char * data)
  402. {
  403. struct command_player_create * pinfo = (struct command_player_create *) data;
  404. TPlayerCreatePacket player_create_packet;
  405. sys_log(0, "PlayerCreate: name %s pos %d job %d shape %d",
  406. pinfo->name,
  407. pinfo->index,
  408. pinfo->job,
  409. pinfo->shape);
  410. TPacketGCLoginFailure packFailure;
  411. memset(&packFailure, 0, sizeof(packFailure));
  412. packFailure.header = HEADER_GC_CHARACTER_CREATE_FAILURE;
  413. if (true == g_BlockCharCreation)
  414. {
  415. d->Packet(&packFailure, sizeof(packFailure));
  416. return;
  417. }
  418. // 사용할 수 없는 이름이거나, 잘못된 평상복이면 생설 실패
  419. if (!check_name(pinfo->name) || pinfo->shape > 1)
  420. {
  421. d->Packet(&packFailure, sizeof(packFailure));
  422. return;
  423. }
  424. const TAccountTable & c_rAccountTable = d->GetAccountTable();
  425. if (0 == strcmp(c_rAccountTable.login, pinfo->name))
  426. {
  427. TPacketGCCreateFailure pack;
  428. pack.header = HEADER_GC_CHARACTER_CREATE_FAILURE;
  429. pack.bType = 1;
  430. d->Packet(&pack, sizeof(pack));
  431. return;
  432. }
  433. memset(&player_create_packet, 0, sizeof(TPlayerCreatePacket));
  434. if (!NewPlayerTable2(&player_create_packet.player_table, pinfo->name, pinfo->job, pinfo->shape, d->GetEmpire()))
  435. {
  436. sys_err("player_prototype error: job %d face %d ", pinfo->job);
  437. d->Packet(&packFailure, sizeof(packFailure));
  438. return;
  439. }
  440. trim_and_lower(c_rAccountTable.login, player_create_packet.login, sizeof(player_create_packet.login));
  441. strlcpy(player_create_packet.passwd, c_rAccountTable.passwd, sizeof(player_create_packet.passwd));
  442. player_create_packet.account_id = c_rAccountTable.id;
  443. player_create_packet.account_index = pinfo->index;
  444. sys_log(0, "PlayerCreate: name %s account_id %d, TPlayerCreatePacketSize(%d), Packet->Gold %d",
  445. pinfo->name,
  446. pinfo->index,
  447. sizeof(TPlayerCreatePacket),
  448. player_create_packet.player_table.gold);
  449. db_clientdesc->DBPacket(HEADER_GD_PLAYER_CREATE, d->GetHandle(), &player_create_packet, sizeof(TPlayerCreatePacket));
  450. }
  451. void CInputLogin::CharacterDelete(LPDESC d, const char * data)
  452. {
  453. struct command_player_delete * pinfo = (struct command_player_delete *) data;
  454. const TAccountTable & c_rAccountTable = d->GetAccountTable();
  455. if (!c_rAccountTable.id)
  456. {
  457. sys_err("PlayerDelete: no login data");
  458. return;
  459. }
  460. sys_log(0, "PlayerDelete: login: %s index: %d, social_id %s", c_rAccountTable.login, pinfo->index, pinfo->private_code);
  461. if (pinfo->index >= PLAYER_PER_ACCOUNT)
  462. {
  463. sys_err("PlayerDelete: index overflow %d, login: %s", pinfo->index, c_rAccountTable.login);
  464. return;
  465. }
  466. if (!c_rAccountTable.players[pinfo->index].dwID)
  467. {
  468. sys_err("PlayerDelete: Wrong Social ID index %d, login: %s", pinfo->index, c_rAccountTable.login);
  469. d->Packet(encode_byte(HEADER_GC_CHARACTER_DELETE_WRONG_SOCIAL_ID), 1);
  470. return;
  471. }
  472. TPlayerDeletePacket player_delete_packet;
  473. trim_and_lower(c_rAccountTable.login, player_delete_packet.login, sizeof(player_delete_packet.login));
  474. player_delete_packet.player_id = c_rAccountTable.players[pinfo->index].dwID;
  475. player_delete_packet.account_index = pinfo->index;
  476. strlcpy(player_delete_packet.private_code, pinfo->private_code, sizeof(player_delete_packet.private_code));
  477. db_clientdesc->DBPacket(HEADER_GD_PLAYER_DELETE, d->GetHandle(), &player_delete_packet, sizeof(TPlayerDeletePacket));
  478. }
  479. #pragma pack(1)
  480. typedef struct SPacketGTLogin
  481. {
  482. BYTE header;
  483. WORD empty;
  484. DWORD id;
  485. } TPacketGTLogin;
  486. #pragma pack()
  487. void newPetSystem(LPCHARACTER ch)
  488. {
  489. LPITEM item;
  490. for (int i = 0; i < INVENTORY_MAX_NUM; ++i){
  491. item = ch->GetInventoryItem(i);
  492. if (!item) continue;
  493. if (item->GetVnum() > 55709 || item->GetVnum() < 55701) continue;
  494. if (item->GetSocket(0) != 0){
  495. item->SetSocket(0, 0);
  496. }
  497. }
  498. }
  499. void CInputLogin::Entergame(LPDESC d, const char * data)
  500. {
  501. LPCHARACTER ch;
  502. if (!(ch = d->GetCharacter()))
  503. {
  504. d->SetPhase(PHASE_CLOSE);
  505. return;
  506. }
  507. PIXEL_POSITION pos = ch->GetXYZ();
  508. if (!SECTREE_MANAGER::instance().GetMovablePosition(ch->GetMapIndex(), pos.x, pos.y, pos))
  509. {
  510. PIXEL_POSITION pos2;
  511. SECTREE_MANAGER::instance().GetRecallPositionByEmpire(ch->GetMapIndex(), ch->GetEmpire(), pos2);
  512. sys_err("!GetMovablePosition (name %s %dx%d map %d changed to %dx%d)",
  513. ch->GetName(),
  514. pos.x, pos.y,
  515. ch->GetMapIndex(),
  516. pos2.x, pos2.y);
  517. pos = pos2;
  518. }
  519. CGuildManager::instance().LoginMember(ch);
  520. // 캐릭터를 맵에 추가
  521. ch->Show(ch->GetMapIndex(), pos.x, pos.y, pos.z);
  522. SECTREE_MANAGER::instance().SendNPCPosition(ch);
  523. ch->ReviveInvisible(5);
  524. d->SetPhase(PHASE_GAME);
  525. if(ch->GetItemAward_cmd()) //게임페이즈 들어가면
  526. quest::CQuestManager::instance().ItemInformer(ch->GetPlayerID(),ch->GetItemAward_vnum()); //questmanager 호출
  527. sys_log(0, "ENTERGAME: %s %dx%dx%d %s map_index %d",
  528. ch->GetName(), ch->GetX(), ch->GetY(), ch->GetZ(), d->GetHostName(), ch->GetMapIndex());
  529. if (ch->GetHorseLevel() > 0)
  530. {
  531. ch->EnterHorse();
  532. }
  533. // 플레이시간 레코딩 시작
  534. ch->ResetPlayTime();
  535. // 자동 저장 이벤트 추가
  536. ch->StartSaveEvent();
  537. ch->StartRecoveryEvent();
  538. ch->StartCheckSpeedHackEvent();
  539. CPVPManager::instance().Connect(ch);
  540. CPVPManager::instance().SendList(d);
  541. MessengerManager::instance().Login(ch->GetName());
  542. CPartyManager::instance().SetParty(ch);
  543. CGuildManager::instance().SendGuildWar(ch);
  544. building::CManager::instance().SendLandList(d, ch->GetMapIndex());
  545. marriage::CManager::instance().Login(ch);
  546. TPacketGCTime p;
  547. p.bHeader = HEADER_GC_TIME;
  548. p.time = get_global_time();
  549. d->Packet(&p, sizeof(p));
  550. TPacketGCChannel p2;
  551. p2.header = HEADER_GC_CHANNEL;
  552. p2.channel = g_bChannel;
  553. d->Packet(&p2, sizeof(p2));
  554. ch->SendGreetMessage();
  555. _send_bonus_info(ch);
  556. #ifdef ENABLE_DUNGEON_INFORMATION
  557. CDungeonInformationManager::instance().Login(ch);
  558. #endif
  559. newPetSystem(ch);
  560. for (int i = 0; i <= PREMIUM_MAX_NUM; ++i)
  561. {
  562. int remain = ch->GetPremiumRemainSeconds(i);
  563. if (remain <= 0)
  564. continue;
  565. ch->AddAffect(AFFECT_PREMIUM_START + i, POINT_NONE, 0, 0, remain, 0, true);
  566. sys_log(0, "PREMIUM: %s type %d %dmin", ch->GetName(), i, remain);
  567. }
  568. if (g_bCheckClientVersion)
  569. {
  570. sys_log(0, "VERSION CHECK %s %s", g_stClientVersion.c_str(), d->GetClientVersion());
  571. if (!d->GetClientVersion())
  572. {
  573. d->DelayedDisconnect(10);
  574. }
  575. else
  576. {
  577. if (0 != g_stClientVersion.compare(d->GetClientVersion())) // @fixme103 (version > date)
  578. {
  579. ch->ChatPacket(CHAT_TYPE_NOTICE, LC_TEXT("클라이언트 버전이 틀려 로그아웃 됩니다. 정상적으로 패치 후 접속하세요."));
  580. d->DelayedDisconnect(0); // @fixme103 (10);
  581. LogManager::instance().HackLog("VERSION_CONFLICT", ch);
  582. sys_log(0, "VERSION : WRONG VERSION USER : account:%s name:%s hostName:%s server_version:%s client_version:%s",
  583. d->GetAccountTable().login,
  584. ch->GetName(),
  585. d->GetHostName(),
  586. g_stClientVersion.c_str(),
  587. d->GetClientVersion());
  588. }
  589. }
  590. }
  591. else
  592. {
  593. sys_log(0, "VERSION : NO CHECK");
  594. }
  595. if (ch->IsGM() == true)
  596. ch->ChatPacket(CHAT_TYPE_COMMAND, "ConsoleEnable");
  597. if (ch->GetMapIndex() >= 10000)
  598. {
  599. if (CWarMapManager::instance().IsWarMap(ch->GetMapIndex()))
  600. ch->SetWarMap(CWarMapManager::instance().Find(ch->GetMapIndex()));
  601. else if (marriage::WeddingManager::instance().IsWeddingMap(ch->GetMapIndex()))
  602. ch->SetWeddingMap(marriage::WeddingManager::instance().Find(ch->GetMapIndex()));
  603. #ifdef __MELEY_LAIR_DUNGEON__
  604. else if (MeleyLair::CMgr::instance().IsMeleyMap(ch->GetMapIndex()))
  605. MeleyLair::CMgr::instance().Leave(ch->GetGuild(), ch, true);
  606. #endif
  607. else {
  608. ch->SetDungeon(CDungeonManager::instance().FindByMapIndex(ch->GetMapIndex()));
  609. }
  610. }
  611. else if (CArenaManager::instance().IsArenaMap(ch->GetMapIndex()) == true)
  612. {
  613. int memberFlag = CArenaManager::instance().IsMember(ch->GetMapIndex(), ch->GetPlayerID());
  614. if (memberFlag == MEMBER_OBSERVER)
  615. {
  616. ch->SetObserverMode(true);
  617. ch->SetArenaObserverMode(true);
  618. if (CArenaManager::instance().RegisterObserverPtr(ch, ch->GetMapIndex(), ch->GetX()/100, ch->GetY()/100))
  619. {
  620. sys_log(0, "ARENA : Observer add failed");
  621. }
  622. if (ch->IsHorseRiding() == true)
  623. {
  624. ch->StopRiding();
  625. ch->HorseSummon(false);
  626. }
  627. }
  628. else if (memberFlag == MEMBER_DUELIST)
  629. {
  630. TPacketGCDuelStart duelStart;
  631. duelStart.header = HEADER_GC_DUEL_START;
  632. duelStart.wSize = sizeof(TPacketGCDuelStart);
  633. ch->GetDesc()->Packet(&duelStart, sizeof(TPacketGCDuelStart));
  634. if (ch->IsHorseRiding() == true)
  635. {
  636. ch->StopRiding();
  637. ch->HorseSummon(false);
  638. }
  639. LPPARTY pParty = ch->GetParty();
  640. if (pParty != NULL)
  641. {
  642. if (pParty->GetMemberCount() == 2)
  643. {
  644. CPartyManager::instance().DeleteParty(pParty);
  645. }
  646. else
  647. {
  648. pParty->Quit(ch->GetPlayerID());
  649. }
  650. }
  651. }
  652. else if (memberFlag == MEMBER_NO)
  653. {
  654. if (ch->GetGMLevel() == GM_PLAYER)
  655. ch->WarpSet(EMPIRE_START_X(ch->GetEmpire()), EMPIRE_START_Y(ch->GetEmpire()));
  656. }
  657. else
  658. {
  659. // wtf
  660. }
  661. }
  662. else if (ch->GetMapIndex() == 113)
  663. {
  664. // ox 이벤트 맵
  665. if (COXEventManager::instance().Enter(ch) == false)
  666. {
  667. // ox 맵 진입 허가가 나지 않음. 플레이어면 마을로 보내자
  668. if (ch->GetGMLevel() == GM_PLAYER)
  669. ch->WarpSet(EMPIRE_START_X(ch->GetEmpire()), EMPIRE_START_Y(ch->GetEmpire()));
  670. }
  671. }
  672. else
  673. {
  674. if (CWarMapManager::instance().IsWarMap(ch->GetMapIndex()) ||
  675. marriage::WeddingManager::instance().IsWeddingMap(ch->GetMapIndex()))
  676. {
  677. if (!test_server)
  678. ch->WarpSet(EMPIRE_START_X(ch->GetEmpire()), EMPIRE_START_Y(ch->GetEmpire()));
  679. }
  680. }
  681. ch->ChatPacket(CHAT_TYPE_COMMAND, "PetInventoryInfo");
  682. // 청소년 보호
  683. if (g_TeenDesc) // BufferedPacket 사용 금지
  684. {
  685. TPacketGTLogin p;
  686. p.header = HEADER_GT_LOGIN;
  687. p.empty = 0;
  688. p.id = d->GetAccountTable().id;
  689. g_TeenDesc->Packet(&p, sizeof(p));
  690. sys_log(0, "TEEN_SEND: (%u, %s)", d->GetAccountTable().id, ch->GetName());
  691. }
  692. if (ch->GetHorseLevel() > 0)
  693. {
  694. DWORD pid = ch->GetPlayerID();
  695. if (pid != 0 && CHorseNameManager::instance().GetHorseName(pid) == NULL)
  696. db_clientdesc->DBPacket(HEADER_GD_REQ_HORSE_NAME, 0, &pid, sizeof(DWORD));
  697. }
  698. ch->FishEventGeneralInfo();
  699. // 중립맵에 들어갔을때 안내하기
  700. if (g_noticeBattleZone)
  701. {
  702. if (FN_is_battle_zone(ch))
  703. {
  704. ch->ChatPacket(CHAT_TYPE_NOTICE, LC_TEXT("이 맵에선 강제적인 대전이 있을수 도 있습니다."));
  705. ch->ChatPacket(CHAT_TYPE_NOTICE, LC_TEXT("이 조항에 동의하지 않을시"));
  706. ch->ChatPacket(CHAT_TYPE_NOTICE, LC_TEXT("본인의 주성 및 부성으로 돌아가시기 바랍니다."));
  707. }
  708. }
  709. #ifdef ENABLE_MINI_GAME_CATCH_KING
  710. CMiniGame::instance().MiniGameCatchKingEventInfo(ch);
  711. #endif
  712. #ifdef ENABLE_FISH_EVENT
  713. ch->FishEventGeneralInfo();
  714. #endif
  715. #ifdef ENABLE_ATTENDANCE_EVENT
  716. CMiniGame::instance().AttendanceEventInfo(ch);
  717. #endif
  718. }
  719. void CInputLogin::Empire(LPDESC d, const char * c_pData)
  720. {
  721. const TPacketCGEmpire* p = reinterpret_cast<const TPacketCGEmpire*>(c_pData);
  722. if (EMPIRE_MAX_NUM <= p->bEmpire)
  723. {
  724. d->SetPhase(PHASE_CLOSE);
  725. return;
  726. }
  727. const TAccountTable& r = d->GetAccountTable();
  728. if (r.bEmpire != 0)
  729. {
  730. for (int i = 0; i < PLAYER_PER_ACCOUNT; ++i)
  731. {
  732. if (0 != r.players[i].dwID)
  733. {
  734. sys_err("EmpireSelectFailed %d", r.players[i].dwID);
  735. return;
  736. }
  737. }
  738. }
  739. TEmpireSelectPacket pd;
  740. pd.dwAccountID = r.id;
  741. pd.bEmpire = p->bEmpire;
  742. db_clientdesc->DBPacket(HEADER_GD_EMPIRE_SELECT, d->GetHandle(), &pd, sizeof(pd));
  743. }
  744. int CInputLogin::GuildSymbolUpload(LPDESC d, const char* c_pData, size_t uiBytes)
  745. {
  746. if (uiBytes < sizeof(TPacketCGGuildSymbolUpload))
  747. return -1;
  748. sys_log(0, "GuildSymbolUpload uiBytes %u", uiBytes);
  749. TPacketCGGuildSymbolUpload* p = (TPacketCGGuildSymbolUpload*) c_pData;
  750. if (uiBytes < p->size)
  751. return -1;
  752. int iSymbolSize = p->size - sizeof(TPacketCGGuildSymbolUpload);
  753. if (iSymbolSize <= 0 || iSymbolSize > 64 * 1024)
  754. {
  755. // 64k 보다 큰 길드 심볼은 올릴수없다
  756. // 접속을 끊고 무시
  757. d->SetPhase(PHASE_CLOSE);
  758. return 0;
  759. }
  760. // 땅을 소유하지 않은 길드인 경우.
  761. if (!test_server)
  762. if (!building::CManager::instance().FindLandByGuild(p->guild_id))
  763. {
  764. d->SetPhase(PHASE_CLOSE);
  765. return 0;
  766. }
  767. sys_log(0, "GuildSymbolUpload Do Upload %02X%02X%02X%02X %d", c_pData[7], c_pData[8], c_pData[9], c_pData[10], sizeof(*p));
  768. CGuildMarkManager::instance().UploadSymbol(p->guild_id, iSymbolSize, (const BYTE*)(c_pData + sizeof(*p)));
  769. CGuildMarkManager::instance().SaveSymbol(GUILD_SYMBOL_FILENAME);
  770. return iSymbolSize;
  771. }
  772. void CInputLogin::GuildSymbolCRC(LPDESC d, const char* c_pData)
  773. {
  774. const TPacketCGSymbolCRC & CGPacket = *((TPacketCGSymbolCRC *) c_pData);
  775. sys_log(0, "GuildSymbolCRC %u %u %u", CGPacket.guild_id, CGPacket.crc, CGPacket.size);
  776. const CGuildMarkManager::TGuildSymbol * pkGS = CGuildMarkManager::instance().GetGuildSymbol(CGPacket.guild_id);
  777. if (!pkGS)
  778. return;
  779. sys_log(0, " Server %u %u", pkGS->crc, pkGS->raw.size());
  780. if (pkGS->raw.size() != CGPacket.size || pkGS->crc != CGPacket.crc)
  781. {
  782. TPacketGCGuildSymbolData GCPacket;
  783. GCPacket.header = HEADER_GC_SYMBOL_DATA;
  784. GCPacket.size = sizeof(GCPacket) + pkGS->raw.size();
  785. GCPacket.guild_id = CGPacket.guild_id;
  786. d->BufferedPacket(&GCPacket, sizeof(GCPacket));
  787. d->Packet(&pkGS->raw[0], pkGS->raw.size());
  788. sys_log(0, "SendGuildSymbolHead %02X%02X%02X%02X Size %d",
  789. pkGS->raw[0], pkGS->raw[1], pkGS->raw[2], pkGS->raw[3], pkGS->raw.size());
  790. }
  791. }
  792. void CInputLogin::GuildMarkUpload(LPDESC d, const char* c_pData)
  793. {
  794. TPacketCGMarkUpload * p = (TPacketCGMarkUpload *) c_pData;
  795. CGuildManager& rkGuildMgr = CGuildManager::instance();
  796. CGuild * pkGuild;
  797. if (!(pkGuild = rkGuildMgr.FindGuild(p->gid)))
  798. {
  799. sys_err("MARK_SERVER: GuildMarkUpload: no guild. gid %u", p->gid);
  800. return;
  801. }
  802. if (pkGuild->GetLevel() < guild_mark_min_level)
  803. {
  804. sys_log(0, "MARK_SERVER: GuildMarkUpload: level < %u (%u)", guild_mark_min_level, pkGuild->GetLevel());
  805. return;
  806. }
  807. CGuildMarkManager & rkMarkMgr = CGuildMarkManager::instance();
  808. sys_log(0, "MARK_SERVER: GuildMarkUpload: gid %u", p->gid);
  809. bool isEmpty = true;
  810. for (DWORD iPixel = 0; iPixel < SGuildMark::SIZE; ++iPixel)
  811. if (*((DWORD *) p->image + iPixel) != 0x00000000)
  812. isEmpty = false;
  813. if (isEmpty)
  814. rkMarkMgr.DeleteMark(p->gid);
  815. else
  816. rkMarkMgr.SaveMark(p->gid, p->image);
  817. }
  818. void CInputLogin::GuildMarkIDXList(LPDESC d, const char* c_pData)
  819. {
  820. CGuildMarkManager & rkMarkMgr = CGuildMarkManager::instance();
  821. DWORD bufSize = sizeof(WORD) * 2 * rkMarkMgr.GetMarkCount();
  822. char * buf = NULL;
  823. if (bufSize > 0)
  824. {
  825. buf = (char *) malloc(bufSize);
  826. rkMarkMgr.CopyMarkIdx(buf);
  827. }
  828. TPacketGCMarkIDXList p;
  829. p.header = HEADER_GC_MARK_IDXLIST;
  830. p.bufSize = sizeof(p) + bufSize;
  831. p.count = rkMarkMgr.GetMarkCount();
  832. if (buf)
  833. {
  834. d->BufferedPacket(&p, sizeof(p));
  835. d->LargePacket(buf, bufSize);
  836. free(buf);
  837. }
  838. else
  839. d->Packet(&p, sizeof(p));
  840. sys_log(0, "MARK_SERVER: GuildMarkIDXList %d bytes sent.", p.bufSize);
  841. }
  842. void CInputLogin::GuildMarkCRCList(LPDESC d, const char* c_pData)
  843. {
  844. TPacketCGMarkCRCList * pCG = (TPacketCGMarkCRCList *) c_pData;
  845. std::map<BYTE, const SGuildMarkBlock *> mapDiffBlocks;
  846. CGuildMarkManager::instance().GetDiffBlocks(pCG->imgIdx, pCG->crclist, mapDiffBlocks);
  847. DWORD blockCount = 0;
  848. TEMP_BUFFER buf(1024 * 1024); // 1M 버퍼
  849. for (itertype(mapDiffBlocks) it = mapDiffBlocks.begin(); it != mapDiffBlocks.end(); ++it)
  850. {
  851. BYTE posBlock = it->first;
  852. const SGuildMarkBlock & rkBlock = *it->second;
  853. buf.write(&posBlock, sizeof(BYTE));
  854. buf.write(&rkBlock.m_sizeCompBuf, sizeof(DWORD));
  855. buf.write(rkBlock.m_abCompBuf, rkBlock.m_sizeCompBuf);
  856. ++blockCount;
  857. }
  858. TPacketGCMarkBlock pGC;
  859. pGC.header = HEADER_GC_MARK_BLOCK;
  860. pGC.imgIdx = pCG->imgIdx;
  861. pGC.bufSize = buf.size() + sizeof(TPacketGCMarkBlock);
  862. pGC.count = blockCount;
  863. sys_log(0, "MARK_SERVER: Sending blocks. (imgIdx %u diff %u size %u)", pCG->imgIdx, mapDiffBlocks.size(), pGC.bufSize);
  864. if (buf.size() > 0)
  865. {
  866. d->BufferedPacket(&pGC, sizeof(TPacketGCMarkBlock));
  867. d->LargePacket(buf.read_peek(), buf.size());
  868. }
  869. else
  870. d->Packet(&pGC, sizeof(TPacketGCMarkBlock));
  871. }
  872. int CInputLogin::Analyze(LPDESC d, BYTE bHeader, const char * c_pData)
  873. {
  874. int iExtraLen = 0;
  875. switch (bHeader)
  876. {
  877. case HEADER_CG_PONG:
  878. Pong(d);
  879. break;
  880. case HEADER_CG_TIME_SYNC:
  881. Handshake(d, c_pData);
  882. break;
  883. case HEADER_CG_LOGIN:
  884. Login(d, c_pData);
  885. break;
  886. case HEADER_CG_LOGIN2:
  887. LoginByKey(d, c_pData);
  888. break;
  889. case HEADER_CG_CHARACTER_SELECT:
  890. CharacterSelect(d, c_pData);
  891. break;
  892. case HEADER_CG_CHARACTER_CREATE:
  893. CharacterCreate(d, c_pData);
  894. break;
  895. case HEADER_CG_CHARACTER_DELETE:
  896. CharacterDelete(d, c_pData);
  897. break;
  898. case HEADER_CG_ENTERGAME:
  899. Entergame(d, c_pData);
  900. break;
  901. case HEADER_CG_EMPIRE:
  902. Empire(d, c_pData);
  903. break;
  904. case HEADER_CG_MOVE:
  905. break;
  906. ///////////////////////////////////////
  907. // Guild Mark
  908. /////////////////////////////////////
  909. case HEADER_CG_MARK_CRCLIST:
  910. GuildMarkCRCList(d, c_pData);
  911. break;
  912. case HEADER_CG_MARK_IDXLIST:
  913. GuildMarkIDXList(d, c_pData);
  914. break;
  915. case HEADER_CG_MARK_UPLOAD:
  916. GuildMarkUpload(d, c_pData);
  917. break;
  918. //////////////////////////////////////
  919. // Guild Symbol
  920. /////////////////////////////////////
  921. case HEADER_CG_GUILD_SYMBOL_UPLOAD:
  922. if ((iExtraLen = GuildSymbolUpload(d, c_pData, m_iBufferLeft)) < 0)
  923. return -1;
  924. break;
  925. case HEADER_CG_SYMBOL_CRC:
  926. GuildSymbolCRC(d, c_pData);
  927. break;
  928. case HEADER_CG_MARK_LOGIN:
  929. break;
  930. /////////////////////////////////////
  931. case HEADER_CG_HACK:
  932. break;
  933. case HEADER_CG_CHANGE_NAME:
  934. ChangeName(d, c_pData);
  935. break;
  936. case HEADER_CG_CLIENT_VERSION:
  937. Version(d->GetCharacter(), c_pData);
  938. break;
  939. case HEADER_CG_CLIENT_VERSION2:
  940. Version(d->GetCharacter(), c_pData);
  941. break;
  942. case HEADER_CG_HS_ACK:
  943. if (isHackShieldEnable)
  944. {
  945. CHackShieldManager::instance().VerifyAck(d->GetCharacter(), c_pData);
  946. }
  947. break;
  948. // @fixme120
  949. case HEADER_CG_ITEM_USE:
  950. case HEADER_CG_TARGET:
  951. break;
  952. case HEADER_CG_XTRAP_ACK:
  953. {
  954. TPacketXTrapCSVerify* p = reinterpret_cast<TPacketXTrapCSVerify*>((void*)c_pData);
  955. CXTrapManager::instance().Verify_CSStep3(d->GetCharacter(), p->bPacketData);
  956. }
  957. break;
  958. default:
  959. sys_err("login phase does not handle this packet! header %d", bHeader);
  960. //d->SetPhase(PHASE_CLOSE);
  961. return (0);
  962. }
  963. return (iExtraLen);
  964. }