int_party.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958
  1. // Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3. #include "int_party.hpp"
  4. #include <cstdlib>
  5. #include <cstring>
  6. #include <memory>
  7. #include <unordered_map>
  8. #include <common/cbasetypes.hpp>
  9. #include <common/malloc.hpp>
  10. #include <common/mmo.hpp>
  11. #include <common/showmsg.hpp>
  12. #include <common/socket.hpp>
  13. #include <common/sql.hpp>
  14. #include <common/strlib.hpp>
  15. #include <common/utilities.hpp>
  16. #include "char.hpp"
  17. #include "char_mapif.hpp"
  18. #include "inter.hpp"
  19. using namespace rathena;
  20. struct party_data {
  21. struct party party;
  22. unsigned int min_lv, max_lv;
  23. int family; //Is this party a family? if so, this holds the child id.
  24. unsigned char size; //Total size of party.
  25. };
  26. // int party_id -> struct party_data*
  27. static std::unordered_map<int32, std::shared_ptr<struct party_data>> party_db;
  28. int mapif_party_broken(int party_id,int flag);
  29. int party_check_empty( std::shared_ptr<struct party_data> p );
  30. int mapif_parse_PartyLeave(int fd, int party_id, uint32 account_id, uint32 char_id, char *name, enum e_party_member_withdraw type);
  31. int party_check_exp_share( std::shared_ptr<struct party_data> p );
  32. int mapif_party_optionchanged(int fd,struct party *p, uint32 account_id, int flag);
  33. int party_check_family_share( std::shared_ptr<struct party_data> p );
  34. //Updates party's level range and unsets even share if broken.
  35. static int int_party_check_lv( std::shared_ptr<struct party_data> p ){
  36. int i;
  37. unsigned int lv;
  38. p->min_lv = UINT_MAX;
  39. p->max_lv = 0;
  40. for(i=0;i<MAX_PARTY;i++){
  41. /**
  42. * - If not online (doesn't affect exp range)
  43. **/
  44. if (!p->party.member[i].online)
  45. continue;
  46. lv=p->party.member[i].lv;
  47. if (lv < p->min_lv) p->min_lv = lv;
  48. if (lv > p->max_lv) p->max_lv = lv;
  49. }
  50. if (p->party.exp && !party_check_exp_share(p)) {
  51. p->party.exp = 0;
  52. mapif_party_optionchanged(0, &p->party, 0, 0);
  53. return 0;
  54. }
  55. return 1;
  56. }
  57. //Calculates the state of a party.
  58. void int_party_calc_state( std::shared_ptr<struct party_data> p ){
  59. int i;
  60. p->min_lv = UINT_MAX;
  61. p->max_lv = 0;
  62. p->party.count =
  63. p->size =
  64. p->family = 0;
  65. //Check party size
  66. for(i=0;i<MAX_PARTY;i++){
  67. if (!p->party.member[i].lv)
  68. continue;
  69. p->size++;
  70. if(p->party.member[i].online)
  71. p->party.count++;
  72. }
  73. if( p->size == 2 && ( char_child(p->party.member[0].char_id,p->party.member[1].char_id) || char_child(p->party.member[1].char_id,p->party.member[0].char_id) ) ) {
  74. //Child should be able to share with either of their parents [RoM]
  75. if(p->party.member[0].class_&0x2000) //first slot is the child?
  76. p->family = p->party.member[0].char_id;
  77. else
  78. p->family = p->party.member[1].char_id;
  79. } else if( p->size == 3 ) {
  80. //Check Family State.
  81. p->family = char_family(
  82. p->party.member[0].char_id,
  83. p->party.member[1].char_id,
  84. p->party.member[2].char_id
  85. );
  86. }
  87. //max/min levels.
  88. for(i=0;i<MAX_PARTY;i++){
  89. unsigned int lv=p->party.member[i].lv;
  90. if (!lv)
  91. continue;
  92. if (p->party.member[i].online) {
  93. if( lv < p->min_lv ) p->min_lv=lv;
  94. if( p->max_lv < lv ) p->max_lv=lv;
  95. }
  96. }
  97. if (p->party.exp && !party_check_exp_share(p)) {
  98. p->party.exp = 0; //Set off even share.
  99. mapif_party_optionchanged(0, &p->party, 0, 0);
  100. }
  101. return;
  102. }
  103. // Save party to mysql
  104. int inter_party_tosql(struct party *p, int flag, int index)
  105. {
  106. // 'party' ('party_id','name','exp','item','leader_id','leader_char')
  107. char esc_name[NAME_LENGTH*2+1];// escaped party name
  108. int32 party_id;
  109. if( p == NULL || p->party_id == 0 )
  110. return 0;
  111. party_id = p->party_id;
  112. #ifdef NOISY
  113. ShowInfo("Save party request (" CL_BOLD "%d" CL_RESET " - %s).\n", party_id, p->name);
  114. #endif
  115. Sql_EscapeStringLen(sql_handle, esc_name, p->name, strnlen(p->name, NAME_LENGTH));
  116. if( flag & PS_BREAK )
  117. {// Break the party
  118. // we'll skip name-checking and just reset everyone with the same party id [celest]
  119. if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", schema_config.char_db, party_id) )
  120. Sql_ShowDebug(sql_handle);
  121. if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `party_id`='%d'", schema_config.party_db, party_id) )
  122. Sql_ShowDebug(sql_handle);
  123. //Remove from memory
  124. party_db.erase( party_id );
  125. return 1;
  126. }
  127. if( flag & PS_CREATE )
  128. {// Create party
  129. if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` "
  130. "(`name`, `exp`, `item`, `leader_id`, `leader_char`) "
  131. "VALUES ('%s', '%d', '%d', '%d', '%d')",
  132. schema_config.party_db, esc_name, p->exp, p->item, p->member[index].account_id, p->member[index].char_id) )
  133. {
  134. Sql_ShowDebug(sql_handle);
  135. return 0;
  136. }
  137. party_id = p->party_id = (int)Sql_LastInsertId(sql_handle);
  138. }
  139. if( flag & PS_BASIC )
  140. {// Update party info.
  141. if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `name`='%s', `exp`='%d', `item`='%d' WHERE `party_id`='%d'",
  142. schema_config.party_db, esc_name, p->exp, p->item, party_id) )
  143. Sql_ShowDebug(sql_handle);
  144. }
  145. if( flag & PS_LEADER )
  146. {// Update leader
  147. if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `leader_id`='%d', `leader_char`='%d' WHERE `party_id`='%d'",
  148. schema_config.party_db, p->member[index].account_id, p->member[index].char_id, party_id) )
  149. Sql_ShowDebug(sql_handle);
  150. }
  151. if( flag & PS_ADDMEMBER )
  152. {// Add one party member.
  153. if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='%d' WHERE `account_id`='%d' AND `char_id`='%d'",
  154. schema_config.char_db, party_id, p->member[index].account_id, p->member[index].char_id) )
  155. Sql_ShowDebug(sql_handle);
  156. }
  157. if( flag & PS_DELMEMBER )
  158. {// Remove one party member.
  159. if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d' AND `account_id`='%d' AND `char_id`='%d'",
  160. schema_config.char_db, party_id, p->member[index].account_id, p->member[index].char_id) )
  161. Sql_ShowDebug(sql_handle);
  162. }
  163. if( charserv_config.save_log )
  164. ShowInfo("Party Saved (%d - %s)\n", party_id, p->name);
  165. return 1;
  166. }
  167. // Read party from mysql
  168. std::shared_ptr<struct party_data> inter_party_fromsql( int party_id ){
  169. int leader_id = 0;
  170. int leader_char = 0;
  171. struct party_member* m;
  172. char* data;
  173. size_t len;
  174. int i;
  175. #ifdef NOISY
  176. ShowInfo("Load party request (" CL_BOLD "%d" CL_RESET ")\n", party_id);
  177. #endif
  178. if( party_id <= 0 )
  179. return NULL;
  180. //Load from memory
  181. std::shared_ptr<struct party_data> p = util::umap_find( party_db, party_id );
  182. if( p != nullptr ){
  183. return p;
  184. }
  185. if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `party_id`, `name`,`exp`,`item`, `leader_id`, `leader_char` FROM `%s` WHERE `party_id`='%d'", schema_config.party_db, party_id) )
  186. {
  187. Sql_ShowDebug(sql_handle);
  188. return NULL;
  189. }
  190. if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
  191. return NULL;
  192. p = std::make_shared<struct party_data>();
  193. p->party.party_id = party_id;
  194. Sql_GetData(sql_handle, 1, &data, &len); memcpy(p->party.name, data, zmin(len, NAME_LENGTH));
  195. Sql_GetData(sql_handle, 2, &data, NULL); p->party.exp = (atoi(data) ? 1 : 0);
  196. Sql_GetData(sql_handle, 3, &data, NULL); p->party.item = atoi(data);
  197. Sql_GetData(sql_handle, 4, &data, NULL); leader_id = atoi(data);
  198. Sql_GetData(sql_handle, 5, &data, NULL); leader_char = atoi(data);
  199. Sql_FreeResult(sql_handle);
  200. // Load members
  201. if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`char_id`,`name`,`base_level`,`last_map`,`online`,`class` FROM `%s` WHERE `party_id`='%d'", schema_config.char_db, party_id) )
  202. {
  203. Sql_ShowDebug(sql_handle);
  204. return NULL;
  205. }
  206. for( i = 0; i < MAX_PARTY && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i )
  207. {
  208. m = &p->party.member[i];
  209. Sql_GetData(sql_handle, 0, &data, NULL); m->account_id = atoi(data);
  210. Sql_GetData(sql_handle, 1, &data, NULL); m->char_id = atoi(data);
  211. Sql_GetData(sql_handle, 2, &data, &len); memcpy(m->name, data, zmin(len, NAME_LENGTH));
  212. Sql_GetData(sql_handle, 3, &data, NULL); m->lv = atoi(data);
  213. Sql_GetData(sql_handle, 4, &data, &len); memcpy(m->map, data, zmin(len, sizeof(m->map)));
  214. Sql_GetData(sql_handle, 5, &data, NULL); m->online = (atoi(data) ? 1 : 0);
  215. Sql_GetData(sql_handle, 6, &data, NULL); m->class_ = atoi(data);
  216. m->leader = (m->account_id == leader_id && m->char_id == leader_char ? 1 : 0);
  217. }
  218. Sql_FreeResult(sql_handle);
  219. if( charserv_config.save_log )
  220. ShowInfo("Party loaded (%d - %s).\n", party_id, p->party.name);
  221. //init state
  222. int_party_calc_state(p);
  223. party_db[p->party.party_id] = p;
  224. return p;
  225. }
  226. int inter_party_sql_init(void)
  227. {
  228. // Remove parties with no members on startup from party_db. [Skotlex]
  229. if (charserv_config.clear_parties) {
  230. ShowStatus("Cleaning party table...\n");
  231. if (SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` USING `%s` LEFT JOIN `%s` ON `%s`.leader_id =`%s`.account_id AND `%s`.leader_char = `%s`.char_id WHERE `%s`.account_id IS NULL",
  232. schema_config.party_db, schema_config.party_db, schema_config.char_db, schema_config.party_db, schema_config.char_db, schema_config.party_db, schema_config.char_db, schema_config.char_db))
  233. Sql_ShowDebug(sql_handle);
  234. }
  235. return 0;
  236. }
  237. void inter_party_sql_final(void)
  238. {
  239. party_db.clear();
  240. }
  241. // Search for the party according to its name
  242. std::shared_ptr<struct party_data> search_partyname( char* str ){
  243. char esc_name[NAME_LENGTH*2+1];
  244. char* data;
  245. std::shared_ptr<struct party_data> p = nullptr;
  246. Sql_EscapeStringLen(sql_handle, esc_name, str, safestrnlen(str, NAME_LENGTH));
  247. if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `party_id` FROM `%s` WHERE `name`='%s'", schema_config.party_db, esc_name) )
  248. Sql_ShowDebug(sql_handle);
  249. else if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
  250. {
  251. Sql_GetData(sql_handle, 0, &data, NULL);
  252. p = inter_party_fromsql(atoi(data));
  253. }
  254. Sql_FreeResult(sql_handle);
  255. return p;
  256. }
  257. int party_check_family_share( std::shared_ptr<struct party_data> p ){
  258. int i;
  259. const char* map = nullptr;
  260. if (!p->family)
  261. return 0;
  262. for (i = 0; i < MAX_PARTY; i++) {
  263. if (p->party.member[i].char_id == p->family) {
  264. map = p->party.member[i].map;
  265. break;
  266. }
  267. }
  268. if( map == nullptr ){
  269. return 0;
  270. }
  271. for (i = 0; i < MAX_PARTY; i++) {
  272. struct party_member * mem = &(p->party.member[i]);
  273. if (mem->lv == 0)
  274. continue;
  275. if (p->family == mem->char_id) {
  276. continue;
  277. }
  278. if (mem->online == 0) {
  279. //everyone should be online to share
  280. return 0;
  281. }
  282. if( strncmp( mem->map, map, sizeof( mem->map ) ) != 0 ){
  283. //everyone should be on the same map
  284. return 0;
  285. }
  286. if (mem->lv < 70) {
  287. //parents must both be above 70
  288. return 0;
  289. }
  290. }
  291. return 1;
  292. }
  293. // Returns whether this party can keep having exp share or not.
  294. int party_check_exp_share( std::shared_ptr<struct party_data> p ){
  295. return (p->party.count < 2 || p->max_lv - p->min_lv <= party_share_level || party_check_family_share(p));
  296. }
  297. // Is there any member in the party?
  298. int party_check_empty( std::shared_ptr<struct party_data> p ){
  299. int i;
  300. if( p == nullptr || p->party.party_id == 0 ){
  301. return 1;
  302. }
  303. for(i=0;i<MAX_PARTY && !p->party.member[i].account_id;i++);
  304. if (i < MAX_PARTY) return 0;
  305. // If there is no member, then break the party
  306. mapif_party_broken(p->party.party_id,0);
  307. inter_party_tosql(&p->party, PS_BREAK, 0);
  308. return 1;
  309. }
  310. //-------------------------------------------------------------------
  311. // Communication to the map server
  312. // Create a party whether or not
  313. int mapif_party_created(int fd,uint32 account_id,uint32 char_id,struct party *p)
  314. {
  315. WFIFOHEAD(fd, 39);
  316. WFIFOW(fd,0)=0x3820;
  317. WFIFOL(fd,2)=account_id;
  318. WFIFOL(fd,6)=char_id;
  319. if(p!=NULL){
  320. WFIFOB(fd,10)=0;
  321. WFIFOL(fd,11)=p->party_id;
  322. memcpy(WFIFOP(fd,15),p->name,NAME_LENGTH);
  323. ShowInfo("int_party: Party created (%d - %s)\n",p->party_id,p->name);
  324. }else{
  325. WFIFOB(fd,10)=1;
  326. WFIFOL(fd,11)=0;
  327. memset(WFIFOP(fd,15),0,NAME_LENGTH);
  328. }
  329. WFIFOSET(fd,39);
  330. return 0;
  331. }
  332. //Party information not found
  333. void mapif_party_noinfo(int fd, int party_id, uint32 char_id)
  334. {
  335. WFIFOHEAD(fd, 12);
  336. WFIFOW(fd,0) = 0x3821;
  337. WFIFOW(fd,2) = 12;
  338. WFIFOL(fd,4) = char_id;
  339. WFIFOL(fd,8) = party_id;
  340. WFIFOSET(fd,12);
  341. ShowWarning("int_party: info not found (party_id=%d char_id=%d)\n", party_id, char_id);
  342. }
  343. //Digest party information
  344. void mapif_party_info(int fd, struct party* p, uint32 char_id)
  345. {
  346. unsigned char buf[8 + sizeof(struct party)];
  347. WBUFW(buf,0) = 0x3821;
  348. WBUFW(buf,2) = 8 + sizeof(struct party);
  349. WBUFL(buf,4) = char_id;
  350. memcpy(WBUFP(buf,8), p, sizeof(struct party));
  351. if(fd<0)
  352. chmapif_sendall(buf,WBUFW(buf,2));
  353. else
  354. chmapif_send(fd,buf,WBUFW(buf,2));
  355. }
  356. //Whether or not additional party members
  357. int mapif_party_memberadded(int fd, int party_id, uint32 account_id, uint32 char_id, int flag) {
  358. WFIFOHEAD(fd, 15);
  359. WFIFOW(fd,0) = 0x3822;
  360. WFIFOL(fd,2) = party_id;
  361. WFIFOL(fd,6) = account_id;
  362. WFIFOL(fd,10) = char_id;
  363. WFIFOB(fd,14) = flag;
  364. WFIFOSET(fd,15);
  365. return 0;
  366. }
  367. // Party setting change notification
  368. int mapif_party_optionchanged(int fd,struct party *p,uint32 account_id,int flag)
  369. {
  370. unsigned char buf[16];
  371. WBUFW(buf,0)=0x3823;
  372. WBUFL(buf,2)=p->party_id;
  373. WBUFL(buf,6)=account_id;
  374. WBUFW(buf,10)=p->exp;
  375. WBUFW(buf,12)=p->item;
  376. WBUFB(buf,14)=flag;
  377. if(flag==0)
  378. chmapif_sendall(buf,15);
  379. else
  380. chmapif_send(fd,buf,15);
  381. return 0;
  382. }
  383. //Withdrawal notification party
  384. int mapif_party_withdraw(int party_id, uint32 account_id, uint32 char_id, char *name, enum e_party_member_withdraw type) {
  385. unsigned char buf[15+NAME_LENGTH];
  386. WBUFW(buf,0) = 0x3824;
  387. WBUFL(buf,2) = party_id;
  388. WBUFL(buf,6) = account_id;
  389. WBUFL(buf,10) = char_id;
  390. memcpy(WBUFP(buf,14), name, NAME_LENGTH);
  391. WBUFB(buf,14+NAME_LENGTH) = type;
  392. chmapif_sendall(buf,15+NAME_LENGTH);
  393. return 0;
  394. }
  395. //Party map update notification
  396. int mapif_party_membermoved(struct party *p,int idx)
  397. {
  398. unsigned char buf[17+MAP_NAME_LENGTH_EXT];
  399. WBUFW(buf,0) = 0x3825;
  400. WBUFL(buf,2) = p->party_id;
  401. WBUFL(buf,6) = p->member[idx].account_id;
  402. WBUFL(buf,10) = p->member[idx].char_id;
  403. WBUFB(buf,14) = p->member[idx].online;
  404. WBUFW(buf,15) = p->member[idx].lv;
  405. safestrncpy( WBUFCP( buf, 17 ), p->member[idx].map, sizeof( p->member[idx].map ) );
  406. chmapif_sendall( buf, sizeof( buf ) );
  407. return 0;
  408. }
  409. //Dissolution party notification
  410. int mapif_party_broken(int party_id,int flag)
  411. {
  412. unsigned char buf[16];
  413. WBUFW(buf,0)=0x3826;
  414. WBUFL(buf,2)=party_id;
  415. WBUFB(buf,6)=flag;
  416. chmapif_sendall(buf,7);
  417. //printf("int_party: broken %d\n",party_id);
  418. return 0;
  419. }
  420. //Remarks in the party
  421. int mapif_party_message(int party_id,uint32 account_id,char *mes,int len, int sfd)
  422. {
  423. unsigned char buf[512];
  424. WBUFW(buf,0)=0x3827;
  425. WBUFW(buf,2)=len+12;
  426. WBUFL(buf,4)=party_id;
  427. WBUFL(buf,8)=account_id;
  428. memcpy(WBUFP(buf,12),mes,len);
  429. chmapif_sendallwos(sfd, buf,len+12);
  430. return 0;
  431. }
  432. //-------------------------------------------------------------------
  433. // Communication from the map server
  434. // Create Party
  435. int mapif_parse_CreateParty(int fd, char *name, int item, int item2, struct party_member *leader)
  436. {
  437. std::shared_ptr<struct party_data> p = search_partyname( name );
  438. if( p != nullptr ){
  439. mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
  440. return 0;
  441. }
  442. // Check Authorised letters/symbols in the name of the character
  443. if (charserv_config.char_config.char_name_option == 1) { // only letters/symbols in char_name_letters are authorised
  444. for( int i = 0; i < NAME_LENGTH && name[i]; i++ ){
  445. if (strchr(charserv_config.char_config.char_name_letters, name[i]) == NULL) {
  446. if( name[i] == '"' ) { /* client-special-char */
  447. normalize_name(name,"\"");
  448. mapif_parse_CreateParty(fd,name,item,item2,leader);
  449. return 0;
  450. }
  451. mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
  452. return 0;
  453. }
  454. }
  455. } else if (charserv_config.char_config.char_name_option == 2) { // letters/symbols in char_name_letters are forbidden
  456. for( int i = 0; i < NAME_LENGTH && name[i]; i++ ){
  457. if (strchr(charserv_config.char_config.char_name_letters, name[i]) != NULL) {
  458. mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
  459. return 0;
  460. }
  461. }
  462. }
  463. p = std::make_shared<struct party_data>();
  464. safestrncpy(p->party.name,name,NAME_LENGTH);
  465. p->party.exp=0;
  466. p->party.item=(item?1:0)|(item2?2:0);
  467. memcpy(&p->party.member[0], leader, sizeof(struct party_member));
  468. p->party.member[0].leader=1;
  469. p->party.member[0].online=1;
  470. p->party.party_id=-1;//New party.
  471. if (inter_party_tosql(&p->party,PS_CREATE|PS_ADDMEMBER,0)) {
  472. //Add party to db
  473. int_party_calc_state(p);
  474. party_db[p->party.party_id] = p;
  475. mapif_party_info(fd, &p->party, 0);
  476. mapif_party_created(fd,leader->account_id,leader->char_id,&p->party);
  477. }else{
  478. // Failed to create party.
  479. mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
  480. }
  481. return 0;
  482. }
  483. // Party information request
  484. void mapif_parse_PartyInfo(int fd, int party_id, uint32 char_id)
  485. {
  486. std::shared_ptr<struct party_data> p = inter_party_fromsql( party_id );
  487. if( p != nullptr ){
  488. mapif_party_info(fd, &p->party, char_id);
  489. }else{
  490. mapif_party_noinfo(fd, party_id, char_id);
  491. }
  492. }
  493. // Add a player to party request
  494. int mapif_parse_PartyAddMember(int fd, int party_id, struct party_member *member)
  495. {
  496. int i;
  497. std::shared_ptr<struct party_data> p = inter_party_fromsql( party_id );
  498. if( p == nullptr || p->size == MAX_PARTY ){
  499. mapif_party_memberadded(fd, party_id, member->account_id, member->char_id, 1);
  500. return 0;
  501. }
  502. ARR_FIND( 0, MAX_PARTY, i, p->party.member[i].account_id == 0 );
  503. if( i == MAX_PARTY )
  504. {// Party full
  505. mapif_party_memberadded(fd, party_id, member->account_id, member->char_id, 1);
  506. return 0;
  507. }
  508. memcpy(&p->party.member[i], member, sizeof(struct party_member));
  509. p->party.member[i].leader = 0;
  510. if (p->party.member[i].online) p->party.count++;
  511. p->size++;
  512. if (p->size == 2 || p->size == 3) // Check family state. And also accept either of their Parents. [RoM]
  513. int_party_calc_state(p);
  514. else //Check even share range.
  515. if (member->lv < p->min_lv || member->lv > p->max_lv || p->family) {
  516. if (p->family) p->family = 0; //Family state broken.
  517. int_party_check_lv(p);
  518. }
  519. mapif_party_info(-1, &p->party, 0);
  520. mapif_party_memberadded(fd, party_id, member->account_id, member->char_id, 0);
  521. inter_party_tosql(&p->party, PS_ADDMEMBER, i);
  522. return 0;
  523. }
  524. //Party setting change request
  525. int mapif_parse_PartyChangeOption(int fd,int party_id,uint32 account_id,int exp,int item)
  526. {
  527. int flag = 0;
  528. std::shared_ptr<struct party_data> p = inter_party_fromsql( party_id );
  529. if(!p)
  530. return 0;
  531. if (p->size == 2 || p->size == 3) //check family state. Also accept either of their parents.
  532. int_party_calc_state(p);
  533. p->party.exp=exp;
  534. if( exp && !party_check_exp_share(p) ){
  535. flag|=0x01;
  536. p->party.exp=0;
  537. }
  538. p->party.item = item&0x3; //Filter out invalid values.
  539. mapif_party_optionchanged(fd,&p->party,account_id,flag);
  540. inter_party_tosql(&p->party, PS_BASIC, 0);
  541. return 0;
  542. }
  543. //Request leave party
  544. int mapif_parse_PartyLeave(int fd, int party_id, uint32 account_id, uint32 char_id, char *name, enum e_party_member_withdraw type)
  545. {
  546. int i,j=-1;
  547. std::shared_ptr<struct party_data> p = inter_party_fromsql( party_id );
  548. // Party does not exists?
  549. if( p == nullptr ){
  550. if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", schema_config.char_db, party_id) )
  551. Sql_ShowDebug(sql_handle);
  552. return 0;
  553. }
  554. for (i = 0; i < MAX_PARTY; i++) {
  555. if(p->party.member[i].account_id == account_id &&
  556. p->party.member[i].char_id == char_id) {
  557. break;
  558. }
  559. }
  560. if (i >= MAX_PARTY)
  561. return 0; //Member not found?
  562. mapif_party_withdraw(party_id, account_id, char_id, name, type);
  563. if (p->party.member[i].leader){
  564. // TODO: Official allow 'leaderless' party
  565. p->party.member[i].account_id = 0;
  566. for (j = 0; j < MAX_PARTY; j++) {
  567. if (!p->party.member[j].account_id)
  568. continue;
  569. mapif_party_withdraw(party_id, p->party.member[j].account_id, p->party.member[j].char_id, p->party.member[j].name, type);
  570. p->party.member[j].account_id = 0;
  571. }
  572. //Party gets deleted on the check_empty call below.
  573. } else {
  574. inter_party_tosql(&p->party,PS_DELMEMBER,i);
  575. j = p->party.member[i].lv;
  576. if(p->party.member[i].online) p->party.count--;
  577. memset(&p->party.member[i], 0, sizeof(struct party_member));
  578. p->size--;
  579. if (j == p->min_lv || j == p->max_lv || p->family)
  580. {
  581. if(p->family) p->family = 0; //Family state broken.
  582. int_party_check_lv(p);
  583. }
  584. }
  585. if (party_check_empty(p) == 0)
  586. mapif_party_info(-1, &p->party, 0);
  587. return 0;
  588. }
  589. // When member goes to other map or levels up.
  590. int mapif_parse_PartyChangeMap( int fd, int party_id, uint32 account_id, uint32 char_id, int online, unsigned int lv, const char* map ){
  591. int i;
  592. std::shared_ptr<struct party_data> p = inter_party_fromsql( party_id );
  593. if( p == nullptr ){
  594. return 0;
  595. }
  596. for(i = 0; i < MAX_PARTY &&
  597. (p->party.member[i].account_id != account_id ||
  598. p->party.member[i].char_id != char_id); i++);
  599. if (i == MAX_PARTY) return 0;
  600. if (p->party.member[i].online != online)
  601. {
  602. p->party.member[i].online = online;
  603. if (online)
  604. p->party.count++;
  605. else
  606. p->party.count--;
  607. // Even share check situations: Family state (always breaks)
  608. // character logging on/off is max/min level (update level range)
  609. // or character logging on/off has a different level (update level range using new level)
  610. if (p->family ||
  611. (p->party.member[i].lv <= p->min_lv || p->party.member[i].lv >= p->max_lv) ||
  612. (p->party.member[i].lv != lv && (lv <= p->min_lv || lv >= p->max_lv))
  613. )
  614. {
  615. p->party.member[i].lv = lv;
  616. int_party_check_lv(p);
  617. }
  618. //Send online/offline update.
  619. mapif_party_membermoved(&p->party, i);
  620. }
  621. if (p->party.member[i].lv != lv) {
  622. if(p->party.member[i].lv == p->min_lv ||
  623. p->party.member[i].lv == p->max_lv)
  624. {
  625. p->party.member[i].lv = lv;
  626. int_party_check_lv(p);
  627. } else
  628. p->party.member[i].lv = lv;
  629. //There is no need to send level update to map servers
  630. //since they do nothing with it.
  631. }
  632. if( strncmp( p->party.member[i].map, map, sizeof( p->party.member[i].map ) ) != 0 ){
  633. safestrncpy( p->party.member[i].map, map, sizeof( p->party.member[i].map ) );
  634. mapif_party_membermoved(&p->party, i);
  635. int_party_check_lv(p);
  636. }
  637. return 0;
  638. }
  639. //Request party dissolution
  640. int mapif_parse_BreakParty(int fd,int party_id)
  641. {
  642. std::shared_ptr<struct party_data> p = inter_party_fromsql( party_id );
  643. if(!p)
  644. return 0;
  645. inter_party_tosql(&p->party,PS_BREAK,0);
  646. mapif_party_broken(fd,party_id);
  647. return 0;
  648. }
  649. //Party sending the message
  650. int mapif_parse_PartyMessage(int fd,int party_id,uint32 account_id,char *mes,int len)
  651. {
  652. return mapif_party_message(party_id,account_id,mes,len, fd);
  653. }
  654. int mapif_parse_PartyLeaderChange(int fd,int party_id,uint32 account_id,uint32 char_id)
  655. {
  656. std::shared_ptr<struct party_data> p = inter_party_fromsql( party_id );
  657. if(!p)
  658. return 0;
  659. for( int i = 0; i < MAX_PARTY; i++ ){
  660. if(p->party.member[i].leader)
  661. p->party.member[i].leader = 0;
  662. if(p->party.member[i].account_id == account_id &&
  663. p->party.member[i].char_id == char_id)
  664. {
  665. p->party.member[i].leader = 1;
  666. inter_party_tosql(&p->party,PS_LEADER, i);
  667. }
  668. }
  669. return 1;
  670. }
  671. /**
  672. * Used to update party share level range in run time
  673. * @param fd : map-serv link
  674. * @param share_lvl : Max level number of difference to share exp
  675. * @return
  676. */
  677. int mapif_parse_PartyShareLevel(int fd,unsigned int share_lvl)
  678. {
  679. party_share_level = share_lvl;
  680. // Update online parties
  681. for( const auto& pair : party_db ){
  682. std::shared_ptr<struct party_data> p = pair.second;
  683. if( p->party.count > 1 ){
  684. int_party_calc_state( p );
  685. }
  686. }
  687. return 1;
  688. }
  689. // Communication from the map server
  690. //-Analysis that only one packet
  691. // Data packet length is set to inter.cpp that you
  692. // Do NOT go and check the packet length, RFIFOSKIP is done by the caller
  693. // Return :
  694. // 0 : error
  695. // 1 : ok
  696. int inter_party_parse_frommap(int fd)
  697. {
  698. RFIFOHEAD(fd);
  699. switch(RFIFOW(fd,0)) {
  700. case 0x3020: mapif_parse_CreateParty(fd, RFIFOCP(fd,4), RFIFOB(fd,28), RFIFOB(fd,29), (struct party_member*)RFIFOP(fd,30)); break;
  701. case 0x3021: mapif_parse_PartyInfo(fd, RFIFOL(fd,2), RFIFOL(fd,6)); break;
  702. case 0x3022: mapif_parse_PartyAddMember(fd, RFIFOL(fd,4), (struct party_member*)RFIFOP(fd,8)); break;
  703. case 0x3023: mapif_parse_PartyChangeOption(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOW(fd,10), RFIFOW(fd,12)); break;
  704. case 0x3024: mapif_parse_PartyLeave(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOCP(fd,14), (enum e_party_member_withdraw)RFIFOB(fd,14+NAME_LENGTH)); break;
  705. case 0x3025: mapif_parse_PartyChangeMap( fd, RFIFOL( fd, 2 ), RFIFOL( fd, 6 ), RFIFOL( fd, 10 ), RFIFOB( fd, 14 ), RFIFOW( fd, 15 ), RFIFOCP( fd, 17 ) ); break;
  706. case 0x3026: mapif_parse_BreakParty(fd, RFIFOL(fd,2)); break;
  707. case 0x3027: mapif_parse_PartyMessage(fd, RFIFOL(fd,4), RFIFOL(fd,8), RFIFOCP(fd,12), RFIFOW(fd,2)-12); break;
  708. case 0x3029: mapif_parse_PartyLeaderChange(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break;
  709. case 0x302A: mapif_parse_PartyShareLevel(fd, RFIFOL(fd,2)); break;
  710. default:
  711. return 0;
  712. }
  713. return 1;
  714. }
  715. //Leave request from the server (for delete character)
  716. int inter_party_leave(int party_id,uint32 account_id, uint32 char_id, char *name)
  717. {
  718. return mapif_parse_PartyLeave(-1,party_id,account_id, char_id, name, PARTY_MEMBER_WITHDRAW_EXPEL);
  719. }
  720. int inter_party_CharOnline(uint32 char_id, int party_id)
  721. {
  722. int i;
  723. if( party_id == -1 )
  724. {// Get party_id from the database
  725. char* data;
  726. if( SQL_ERROR == Sql_Query(sql_handle, "SELECT party_id FROM `%s` WHERE char_id='%d'", schema_config.char_db, char_id) )
  727. {
  728. Sql_ShowDebug(sql_handle);
  729. return 0;
  730. }
  731. if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
  732. return 0; //Eh? No party?
  733. Sql_GetData(sql_handle, 0, &data, NULL);
  734. party_id = atoi(data);
  735. Sql_FreeResult(sql_handle);
  736. }
  737. if (party_id == 0)
  738. return 0; //No party...
  739. std::shared_ptr<struct party_data> p = inter_party_fromsql( party_id );
  740. if(!p) {
  741. ShowError("Character %d's party %d not found!\n", char_id, party_id);
  742. return 0;
  743. }
  744. //Set member online
  745. for(i=0; i<MAX_PARTY; i++) {
  746. if (p->party.member[i].char_id == char_id) {
  747. if (!p->party.member[i].online) {
  748. p->party.member[i].online = 1;
  749. p->party.count++;
  750. if (p->party.member[i].lv < p->min_lv ||
  751. p->party.member[i].lv > p->max_lv)
  752. int_party_check_lv(p);
  753. }
  754. break;
  755. }
  756. }
  757. return 1;
  758. }
  759. int inter_party_CharOffline(uint32 char_id, int party_id) {
  760. int i;
  761. if( party_id == -1 )
  762. {// Get guild_id from the database
  763. char* data;
  764. if( SQL_ERROR == Sql_Query(sql_handle, "SELECT party_id FROM `%s` WHERE char_id='%d'", schema_config.char_db, char_id) )
  765. {
  766. Sql_ShowDebug(sql_handle);
  767. return 0;
  768. }
  769. if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
  770. return 0; //Eh? No party?
  771. Sql_GetData(sql_handle, 0, &data, NULL);
  772. party_id = atoi(data);
  773. Sql_FreeResult(sql_handle);
  774. }
  775. if (party_id == 0)
  776. return 0; //No party...
  777. //Character has a party, set character offline and check if they were the only member online
  778. std::shared_ptr<struct party_data> p = inter_party_fromsql( party_id );
  779. if( p == nullptr ){
  780. return 0;
  781. }
  782. //Set member offline
  783. for(i=0; i< MAX_PARTY; i++) {
  784. if(p->party.member[i].char_id == char_id)
  785. {
  786. p->party.member[i].online = 0;
  787. p->party.count--;
  788. if(p->party.member[i].lv == p->min_lv ||
  789. p->party.member[i].lv == p->max_lv)
  790. int_party_check_lv(p);
  791. break;
  792. }
  793. }
  794. // Parties don't have any data that needs be saved at this point... so just remove it from memory.
  795. if( p->party.count == 0 ){
  796. party_db.erase( party_id );
  797. }
  798. return 1;
  799. }
  800. int inter_party_charname_changed(int party_id, uint32 char_id, char *name)
  801. {
  802. int i;
  803. std::shared_ptr<struct party_data> p = inter_party_fromsql( party_id );
  804. if( p == nullptr || p->party.party_id == 0 ){
  805. ShowError("inter_party_charname_changed: Can't find party %d.\n", party_id);
  806. return 0;
  807. }
  808. ARR_FIND(0, MAX_PARTY, i, p->party.member[i].char_id == char_id);
  809. if( i == MAX_PARTY )
  810. {
  811. ShowError("inter_party_charname_changed: Can't find character %d in party %d.\n", char_id, party_id);
  812. return 0;
  813. }
  814. safestrncpy(p->party.member[i].name, name, NAME_LENGTH);
  815. mapif_party_info(-1, &p->party, char_id);
  816. return 0;
  817. }