// パーティメッセージ static void intif_parse_PartyMessage(int fd) { size_t len = RFIFOW(fd, 2) - 12; FString buf = RFIFO_STRING(fd, 12, len); party_recv_message(RFIFOL(fd, 4), RFIFOL(fd, 8), buf); }
// Received wisp message from map-server via char-server for ALL gm static void mapif_parse_WisToGM(int fd) { // 0x3003/0x3803 <packet_len>.w <wispname>.24B <min_gm_level>.w <message>.?B int min_gm_level, len; if (RFIFOW(fd, 2) - 30 <= 0) return; len = RFIFOW(fd, 2) - 30; min_gm_level = RFIFOW(fd, 28); CharName Wisp_name = stringish<CharName>(RFIFO_STRING<24>(fd, 4)); FString message = RFIFO_STRING(fd, 30, len); // information is sended to all online GM for (int i = 0; i < fd_max; i++) { if (!session[i]) continue; dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get())); if (pl_sd && pl_sd->state.auth) if (pc_isGM(pl_sd) >= min_gm_level) clif_wis_message(i, Wisp_name, message); } }
// Wisp/page request to send static void mapif_parse_WisRequest(int fd) { static int wisid = 0; if (RFIFOW(fd, 2) - 52 <= 0) { // normaly, impossible, but who knows... PRINTF("inter: Wis message doesn't exist.\n"); return; } CharName from = stringish<CharName>(RFIFO_STRING<24>(fd, 4)); CharName to = stringish<CharName>(RFIFO_STRING<24>(fd, 28)); // search if character exists before to ask all map-servers const mmo_charstatus *mcs = search_character(to); if (!mcs) { uint8_t buf[27]; WBUFW(buf, 0) = 0x3802; WBUF_STRING(buf, 2, from.to__actual(), 24); WBUFB(buf, 26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target mapif_send(fd, buf, 27); // Character exists. So, ask all map-servers } else { // to be sure of the correct name, rewrite it to = mcs->name; // if source is destination, don't ask other servers. if (from == to) { uint8_t buf[27]; WBUFW(buf, 0) = 0x3802; WBUF_STRING(buf, 2, from.to__actual(), 24); WBUFB(buf, 26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target mapif_send(fd, buf, 27); } else { struct WisData wd {}; // Whether the failure of previous wisp/page transmission (timeout) check_ttl_wisdata(); wd.id = ++wisid; wd.fd = fd; size_t len = RFIFOW(fd, 2) - 52; wd.src = from; wd.dst = to; wd.msg = RFIFO_STRING(fd, 52, len); wd.tick = gettick(); wis_db.insert(wd.id, wd); mapif_wis_message(&wd); } } }
// GMメッセージ送信 static void mapif_parse_GMmessage(int fd) { size_t msg_len = RFIFOW(fd, 2); size_t str_len = msg_len - 4; FString buf = RFIFO_STRING(fd, 4, str_len); mapif_GMmessage(buf); }
// Wisp/Page reception static int intif_parse_WisMessage(int fd) { // rewritten by [Yor] dumb_ptr<map_session_data> sd; CharName from = stringish<CharName>(RFIFO_STRING<24>(fd, 8)); CharName to = stringish<CharName>(RFIFO_STRING<24>(fd, 32)); size_t len = RFIFOW(fd, 2) - 56; FString buf = RFIFO_STRING(fd, 56, len); if (battle_config.etc_log) { PRINTF("intif_parse_wismessage: id: %d, from: %s, to: %s, message: '%s'\n", RFIFOL(fd, 4), from, to, buf); } sd = map_nick2sd(to); // Searching destination player if (sd != NULL && sd->status.name == to) { // exactly same name (inter-server have checked the name before) { // if source player not found in ignore list { clif_wis_message(sd->fd, from, buf); intif_wis_replay(RFIFOL(fd, 4), 0); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target } } } else intif_wis_replay(RFIFOL(fd, 4), 1); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target return 0; }
//----------------------------------------------------------------- // inter serverからの通信 // エラーがあれば0(false)を返すこと // パケットが処理できれば1,パケット長が足りなければ2を返すこと int intif_parse(int fd) { int packet_len; int cmd = RFIFOW(fd, 0); // パケットのID確認 if (cmd < 0x3800 || cmd >= 0x3800 + (sizeof(packet_len_table) / sizeof(packet_len_table[0])) || packet_len_table[cmd - 0x3800] == 0) { return 0; } // パケットの長さ確認 packet_len = packet_len_table[cmd - 0x3800]; if (packet_len == -1) { if (RFIFOREST(fd) < 4) return 2; packet_len = RFIFOW(fd, 2); } // if(battle_config.etc_log) // PRINTF("intif_parse %d %x %d %d\n",fd,cmd,packet_len,RFIFOREST(fd)); if (RFIFOREST(fd) < packet_len) { return 2; } // 処理分岐 switch (cmd) { case 0x3800: { FString mes = RFIFO_STRING(fd, 4, packet_len - 4); clif_GMmessage(NULL, mes, 0); } break; case 0x3801: intif_parse_WisMessage(fd); break; case 0x3802: intif_parse_WisEnd(fd); break; case 0x3803: mapif_parse_WisToGM(fd); break; case 0x3804: intif_parse_AccountReg(fd); break; case 0x3810: intif_parse_LoadStorage(fd); break; case 0x3811: intif_parse_SaveStorage(fd); break; case 0x3820: intif_parse_PartyCreated(fd); break; case 0x3821: intif_parse_PartyInfo(fd); break; case 0x3822: intif_parse_PartyMemberAdded(fd); break; case 0x3823: intif_parse_PartyOptionChanged(fd); break; case 0x3824: intif_parse_PartyMemberLeaved(fd); break; case 0x3825: intif_parse_PartyMove(fd); break; case 0x3826: intif_parse_PartyBroken(fd); break; case 0x3827: intif_parse_PartyMessage(fd); break; default: if (battle_config.error_log) PRINTF("intif_parse : unknown packet %d %x\n", fd, RFIFOW(fd, 0)); return 0; } // パケット読み飛ばし RFIFOSKIP(fd, packet_len); return 1; }
// map server からの通信 // ・1パケットのみ解析すること // ・パケット長データはinter.cにセットしておくこと // ・パケット長チェックや、RFIFOSKIPは呼び出し元で行われるので行ってはならない // ・エラーなら0(false)、そうでないなら1(true)をかえさなければならない int inter_party_parse_frommap(int fd) { switch (RFIFOW(fd, 0)) { case 0x3020: { int account = RFIFOL(fd, 2); PartyName name = stringish<PartyName>(RFIFO_STRING<24>(fd, 6)); CharName nick = stringish<CharName>(RFIFO_STRING<24>(fd, 30)); MapName map = RFIFO_STRING<16>(fd, 54); uint16_t lv = RFIFOW(fd, 70); mapif_parse_CreateParty(fd, account, name, nick, map, lv); } break; case 0x3021: { int party_id = RFIFOL(fd, 2); mapif_parse_PartyInfo(fd, party_id); } break; case 0x3022: { int party_id = RFIFOL(fd, 2); int account_id = RFIFOL(fd, 6); CharName nick = stringish<CharName>(RFIFO_STRING<24>(fd, 10)); MapName map = RFIFO_STRING<16>(fd, 34); uint16_t lv = RFIFOW(fd, 50); mapif_parse_PartyAddMember(fd, party_id, account_id, nick, map, lv); } break; case 0x3023: { int party_id = RFIFOL(fd, 2); int account_id = RFIFOL(fd, 6); uint16_t exp = RFIFOW(fd, 10); uint16_t item = RFIFOW(fd, 12); mapif_parse_PartyChangeOption(fd, party_id, account_id, exp, item); } break; case 0x3024: { int party_id = RFIFOL(fd, 2); int account_id = RFIFOL(fd, 6); mapif_parse_PartyLeave(fd, party_id, account_id); } break; case 0x3025: { int party_id = RFIFOL(fd, 2); int account_id = RFIFOL(fd, 6); MapName map = RFIFO_STRING<16>(fd, 10); uint8_t online = RFIFOB(fd, 26); uint16_t lv = RFIFOW(fd, 27); mapif_parse_PartyChangeMap(fd, party_id, account_id, map, online, lv); } break; case 0x3026: { int party_id = RFIFOL(fd, 2); mapif_parse_BreakParty(fd, party_id); } break; case 0x3027: { size_t len = RFIFOW(fd, 2) - 12; int party_id = RFIFOL(fd, 4); int account_id = RFIFOL(fd, 8); FString mes = RFIFO_STRING(fd, 12, len); mapif_parse_PartyMessage(fd, party_id, account_id, mes); } break; case 0x3028: { int party_id = RFIFOL(fd, 2); int account_id = RFIFOL(fd, 6); CharName nick = stringish<CharName>(RFIFO_STRING<24>(fd, 10)); mapif_parse_PartyCheck(fd, party_id, account_id, nick); } break; default: return 0; } return 1; }