summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/admin/ladmin.cpp6
-rw-r--r--src/char/char.cpp14
-rw-r--r--src/login/login.cpp3
-rw-r--r--src/map/chrif.cpp525
-rw-r--r--src/map/intif.cpp511
-rw-r--r--src/map/intif.hpp2
-rw-r--r--src/map/pc.cpp14
-rw-r--r--src/map/pc.hpp4
-rw-r--r--src/net/packets.hpp2
9 files changed, 597 insertions, 484 deletions
diff --git a/src/admin/ladmin.cpp b/src/admin/ladmin.cpp
index 7b702ed..ba55d73 100644
--- a/src/admin/ladmin.cpp
+++ b/src/admin/ladmin.cpp
@@ -2815,6 +2815,12 @@ void parse_fromlogin(Session *s)
}
}
+ if (rv == RecvResult::Error)
+ {
+ s->set_eof();
+ return;
+ }
+
// The following was almost certainly wrong and only worked because
// localhost is a fast enough network to never split byte 1 vs byte 2
diff --git a/src/char/char.cpp b/src/char/char.cpp
index 33ee2b9..7bc17ba 100644
--- a/src/char/char.cpp
+++ b/src/char/char.cpp
@@ -1188,13 +1188,7 @@ int char_delete(CharPair *cp)
static
void parse_tologin(Session *ls)
{
- // only login-server can have an access to here.
- // so, if it isn't the login-server, we disconnect the session (fd != login_fd).
- if (ls != login_session)
- {
- ls->set_eof();
- return;
- }
+ assert (ls == login_session);
char_session_data *sd = static_cast<char_session_data *>(ls->session_data.get());
@@ -1665,6 +1659,8 @@ void parse_tologin(Session *ls)
}
}
}
+ if (rv == RecvResult::Error)
+ ls->set_eof();
}
//--------------------------------
@@ -2281,6 +2277,8 @@ void parse_frommap(Session *ms)
}
}
}
+ if (rv == RecvResult::Error)
+ ms->set_eof();
}
static
@@ -2770,6 +2768,8 @@ void parse_char(Session *s)
return;
}
}
+ if (rv == RecvResult::Error)
+ s->set_eof();
}
static
diff --git a/src/login/login.cpp b/src/login/login.cpp
index 6edaeef..7537927 100644
--- a/src/login/login.cpp
+++ b/src/login/login.cpp
@@ -3245,7 +3245,8 @@ void parse_login(Session *s)
}
}
}
- return;
+ if (rv == RecvResult::Error)
+ s->set_eof();
}
//----------------------------------
diff --git a/src/map/chrif.cpp b/src/map/chrif.cpp
index a6c11b9..2998516 100644
--- a/src/map/chrif.cpp
+++ b/src/map/chrif.cpp
@@ -29,9 +29,11 @@
#include "../io/cxxstdio.hpp"
#include "../net/ip.hpp"
+#include "../net/packets.hpp"
#include "../net/socket.hpp"
#include "../net/timer.hpp"
-#include "../net/vomit.hpp"
+
+#include "../proto2/char-map.hpp"
#include "../mmo/human_time_diff.hpp"
#include "../mmo/mmo.hpp"
@@ -48,14 +50,6 @@
#include "../poison.hpp"
-static
-const int packet_len_table[0x20] =
-{
- 60, 3, 10, 27, 22, -1, 6, -1, // 2af8-2aff
- 6, -1, 18, 7, -1, 49, 44, 0, // 2b00-2b07
- 6, 30, -1, 10, 86, 7, 44, 34, // 2b08-2b0f
- -1, -1, 10, 6, 11, -1, 0, 0, // 2b10-2b17
-};
Session *char_session;
static
@@ -133,13 +127,12 @@ int chrif_save(dumb_ptr<map_session_data> sd)
pc_makesavestatus(sd);
- WFIFOW(char_session, 0) = 0x2b01;
- WFIFOW(char_session, 2) = sizeof(sd->status_key) + sizeof(sd->status) + 12;
- WFIFOL(char_session, 4) = unwrap<BlockId>(sd->bl_id);
- WFIFOL(char_session, 8) = unwrap<CharId>(sd->char_id_);
- WFIFO_STRUCT(char_session, 12, sd->status_key);
- WFIFO_STRUCT(char_session, 12 + sizeof(sd->status_key), sd->status);
- WFIFOSET(char_session, WFIFOW(char_session, 2));
+ Packet_Payload<0x2b01> payload_01;
+ payload_01.account_id = block_to_account(sd->bl_id);
+ payload_01.char_id = sd->char_id_;
+ payload_01.char_key = sd->status_key;
+ payload_01.char_data = sd->status;
+ send_ppacket<0x2b01>(char_session, payload_01);
//For data sync
if (sd->state.storage_open)
@@ -155,13 +148,13 @@ int chrif_save(dumb_ptr<map_session_data> sd)
static
int chrif_connect(Session *s)
{
- WFIFOW(s, 0) = 0x2af8;
- WFIFO_STRING(s, 2, userid, 24);
- WFIFO_STRING(s, 26, passwd, 24);
- WFIFOL(s, 50) = 0;
- WFIFOIP(s, 54) = clif_getip();
- WFIFOW(s, 58) = clif_getport(); // [Valaris] thanks to fov
- WFIFOSET(s, 60);
+ Packet_Fixed<0x2af8> fixed_f8;
+ fixed_f8.account_name = userid;
+ fixed_f8.account_pass = passwd;
+ fixed_f8.unused = 0;
+ fixed_f8.ip = clif_getip();
+ fixed_f8.port = clif_getport();
+ send_fpacket<0x2af8, 60>(s, fixed_f8);
return 0;
}
@@ -173,19 +166,17 @@ int chrif_connect(Session *s)
static
int chrif_sendmap(Session *s)
{
- int i = 0;
-
- WFIFOW(s, 0) = 0x2afa;
+ std::vector<Packet_Repeat<0x2afa>> repeat_fa;
for (auto& pair : maps_db)
{
map_abstract *ma = pair.second.get();
if (!ma->gat)
continue;
- WFIFO_STRING(s, 4 + i * 16, ma->name_, 16);
- i++;
+ Packet_Repeat<0x2afa> info;
+ info.map_name = ma->name_;
+ repeat_fa.push_back(info);
}
- WFIFOW(s, 2) = 4 + i * 16;
- WFIFOSET(s, WFIFOW(s, 2));
+ send_packet_repeatonly<0x2afa, 4, 16>(s, repeat_fa);
return 0;
}
@@ -195,23 +186,21 @@ int chrif_sendmap(Session *s)
*------------------------------------------
*/
static
-int chrif_recvmap(Session *s)
+int chrif_recvmap(Session *, Packet_Head<0x2b04> head, const std::vector<Packet_Repeat<0x2b04>>& repeat)
{
- int i, j;
-
if (chrif_state < 2) // まだ準備中
return -1;
- IP4Address ip = RFIFOIP(s, 4);
- uint16_t port = RFIFOW(s, 8);
- for (i = 10, j = 0; i < RFIFOW(s, 2); i += 16, j++)
+ IP4Address ip = head.ip;
+ uint16_t port = head.port;
+ for (const Packet_Repeat<0x2b04>& i : repeat)
{
- MapName map = RFIFO_STRING<16>(s, i);
+ MapName map = i.map_name;
map_setipport(map, ip, port);
}
if (battle_config.etc_log)
- PRINTF("recv map on %s:%d (%d maps)\n"_fmt,
- ip, port, j);
+ PRINTF("recv map on %s:%d (%zu maps)\n"_fmt,
+ ip, port, repeat.size());
return 0;
}
@@ -239,19 +228,19 @@ int chrif_changemapserver(dumb_ptr<map_session_data> sd,
}
}
- WFIFOW(char_session, 0) = 0x2b05;
- WFIFOL(char_session, 2) = unwrap<BlockId>(sd->bl_id);
- WFIFOL(char_session, 6) = sd->login_id1;
- WFIFOL(char_session, 10) = sd->login_id2;
- WFIFOL(char_session, 14) = unwrap<CharId>(sd->status_key.char_id);
- WFIFO_STRING(char_session, 18, name, 16);
- WFIFOW(char_session, 34) = x;
- WFIFOW(char_session, 36) = y;
- WFIFOIP(char_session, 38) = ip;
- WFIFOL(char_session, 42) = port;
- WFIFOB(char_session, 44) = static_cast<uint8_t>(sd->status.sex);
- WFIFOIP(char_session, 45) = s_ip;
- WFIFOSET(char_session, 49);
+ Packet_Fixed<0x2b05> fixed_05;
+ fixed_05.account_id = block_to_account(sd->bl_id);
+ fixed_05.login_id1 = sd->login_id1;
+ fixed_05.login_id2 = sd->login_id2;
+ fixed_05.char_id = sd->status_key.char_id;
+ fixed_05.map_name = name;
+ fixed_05.x = x;
+ fixed_05.y = y;
+ fixed_05.map_ip = ip;
+ fixed_05.map_port = port;
+ fixed_05.sex = sd->status.sex;
+ fixed_05.client_ip = s_ip;
+ send_fpacket<0x2b05, 49>(char_session, fixed_05);
return 0;
}
@@ -261,26 +250,26 @@ int chrif_changemapserver(dumb_ptr<map_session_data> sd,
*------------------------------------------
*/
static
-int chrif_changemapserverack(Session *s)
+int chrif_changemapserverack(Session *, const Packet_Fixed<0x2b06>& fixed)
{
- dumb_ptr<map_session_data> sd = map_id2sd(account_to_block(wrap<AccountId>(RFIFOL(s, 2))));
+ dumb_ptr<map_session_data> sd = map_id2sd(account_to_block(fixed.account_id));
- if (sd == NULL || sd->status_key.char_id != wrap<CharId>(RFIFOL(s, 14)))
+ if (sd == NULL || sd->status_key.char_id != fixed.char_id)
return -1;
// I am fairly certain that this is not possible
- if (RFIFOL(s, 6) == 1)
+ if (fixed.error == 1)
{
if (battle_config.error_log)
PRINTF("map server change failed.\n"_fmt);
pc_authfail(sd->status_key.account_id);
return 0;
}
- MapName mapname = RFIFO_STRING<16>(s, 18);
- uint16_t x = RFIFOW(s, 34);
- uint16_t y = RFIFOW(s, 36);
- IP4Address ip = RFIFOIP(s, 38);
- uint16_t port = RFIFOW(s, 42);
+ MapName mapname = fixed.map_name;
+ uint16_t x = fixed.x;
+ uint16_t y = fixed.y;
+ IP4Address ip = fixed.map_ip;
+ uint16_t port = fixed.map_port;
clif_changemapserver(sd, mapname, x, y, ip, port);
return 0;
@@ -291,11 +280,11 @@ int chrif_changemapserverack(Session *s)
*------------------------------------------
*/
static
-int chrif_connectack(Session *s)
+int chrif_connectack(Session *s, const Packet_Fixed<0x2af9>& fixed)
{
- if (RFIFOB(s, 2))
+ if (fixed.code)
{
- PRINTF("Connected to char-server failed %d.\n"_fmt, RFIFOB(s, 2));
+ PRINTF("Connected to char-server failed %d.\n"_fmt, fixed.code);
exit(1);
}
PRINTF("Connected to char-server (connection #%d).\n"_fmt, s);
@@ -316,16 +305,16 @@ int chrif_connectack(Session *s)
*------------------------------------------
*/
static
-int chrif_sendmapack(Session *s)
+int chrif_sendmapack(Session *, Packet_Fixed<0x2afb> fixed)
{
- if (RFIFOB(s, 2))
+ if (fixed.unknown) //impossible
{
PRINTF("chrif : send map list to char server failed %d\n"_fmt,
- RFIFOB(s, 2));
+ fixed.unknown);
exit(1);
}
- wisp_server_name = stringish<CharName>(RFIFO_STRING<24>(s, 3));
+ wisp_server_name = fixed.whisper_name;
chrif_state = 2;
@@ -351,13 +340,13 @@ int chrif_authreq(dumb_ptr<map_session_data> sd)
if (dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get())) == sd)
{
assert (s == sd->sess);
- WFIFOW(char_session, 0) = 0x2afc;
- WFIFOL(char_session, 2) = unwrap<BlockId>(sd->bl_id);
- WFIFOL(char_session, 6) = unwrap<CharId>(sd->char_id_);
- WFIFOL(char_session, 10) = sd->login_id1;
- WFIFOL(char_session, 14) = sd->login_id2;
- WFIFOIP(char_session, 18) = s->client_ip;
- WFIFOSET(char_session, 22);
+ Packet_Fixed<0x2afc> fixed_fc;
+ fixed_fc.account_id = block_to_account(sd->bl_id);
+ fixed_fc.char_id = sd->char_id_;
+ fixed_fc.login_id1 = sd->login_id1;
+ fixed_fc.login_id2 = sd->login_id2;
+ fixed_fc.ip = s->client_ip;
+ send_fpacket<0x2afc, 22>(char_session, fixed_fc);
break;
}
}
@@ -390,12 +379,12 @@ int chrif_charselectreq(dumb_ptr<map_session_data> sd)
}
}
- WFIFOW(char_session, 0) = 0x2b02;
- WFIFOL(char_session, 2) = unwrap<BlockId>(sd->bl_id);
- WFIFOL(char_session, 6) = sd->login_id1;
- WFIFOL(char_session, 10) = sd->login_id2;
- WFIFOIP(char_session, 14) = s_ip;
- WFIFOSET(char_session, 18);
+ Packet_Fixed<0x2b02> fixed_02;
+ fixed_02.account_id = block_to_account(sd->bl_id);
+ fixed_02.login_id1 = sd->login_id1;
+ fixed_02.login_id2 = sd->login_id2;
+ fixed_02.ip = s_ip;
+ send_fpacket<0x2b02, 18>(char_session, fixed_02);
return 0;
}
@@ -409,12 +398,9 @@ void chrif_changegm(AccountId id, ZString pass)
if (battle_config.etc_log)
PRINTF("chrif_changegm: account: %d, password: '%s'.\n"_fmt, id, pass);
- size_t len = pass.size() + 1;
- WFIFOW(char_session, 0) = 0x2b0a;
- WFIFOW(char_session, 2) = len + 8;
- WFIFOL(char_session, 4) = unwrap<AccountId>(id);
- WFIFO_STRING(char_session, 8, pass, len);
- WFIFOSET(char_session, len + 8);
+ Packet_Head<0x2b0a> head_0a;
+ head_0a.account_id = id;
+ send_vpacket<0x2b0a, 8, 1>(char_session, head_0a, pass);
}
/*==========================================
@@ -428,11 +414,11 @@ void chrif_changeemail(AccountId id, AccountEmail actual_email,
PRINTF("chrif_changeemail: account: %d, actual_email: '%s', new_email: '%s'.\n"_fmt,
id, actual_email, new_email);
- WFIFOW(char_session, 0) = 0x2b0c;
- WFIFOL(char_session, 2) = unwrap<AccountId>(id);
- WFIFO_STRING(char_session, 6, actual_email, 40);
- WFIFO_STRING(char_session, 46, new_email, 40);
- WFIFOSET(char_session, 86);
+ Packet_Fixed<0x2b0c> fixed_0c;
+ fixed_0c.account_id = id;
+ fixed_0c.old_email = actual_email;
+ fixed_0c.new_email = new_email;
+ send_fpacket<0x2b0c, 86>(char_session, fixed_0c);
}
/*==========================================
@@ -449,14 +435,14 @@ void chrif_changeemail(AccountId id, AccountEmail actual_email,
void chrif_char_ask_name(AccountId id, CharName character_name, short operation_type,
HumanTimeDiff modif)
{
- WFIFOW(char_session, 0) = 0x2b0e;
- WFIFOL(char_session, 2) = unwrap<AccountId>(id); // account_id of who ask (for answer) -1 if nobody
- WFIFO_STRING(char_session, 6, character_name.to__actual(), 24);
- WFIFOW(char_session, 30) = operation_type; // type of operation
+ Packet_Fixed<0x2b0e> fixed_0e;
+ fixed_0e.account_id = id; // who ask, or nobody
+ fixed_0e.char_name = character_name;
+ fixed_0e.operation = operation_type; // type of operation
if (operation_type == 2)
- WFIFO_STRUCT(char_session, 32, modif);
+ fixed_0e.ban_add = modif;
PRINTF("chrif : sended 0x2b0e\n"_fmt);
- WFIFOSET(char_session, 44);
+ send_fpacket<0x2b0e, 44>(char_session, fixed_0e);
}
/*==========================================
@@ -476,24 +462,24 @@ void chrif_char_ask_name(AccountId id, CharName character_name, short operation_
*------------------------------------------
*/
static
-int chrif_char_ask_name_answer(Session *s)
+int chrif_char_ask_name_answer(Session *, const Packet_Fixed<0x2b0f>& fixed)
{
- AccountId acc = wrap<AccountId>(RFIFOL(s, 2)); // account_id of who has asked (-1 if nobody)
- CharName player_name = stringish<CharName>(RFIFO_STRING<24>(s, 6));
+ AccountId acc = fixed.account_id; // who asked, or nobody
+ CharName player_name = fixed.char_name;
dumb_ptr<map_session_data> sd = map_id2sd(account_to_block(acc));
if (acc && sd != NULL)
{
AString output;
- if (RFIFOW(s, 32) == 1) // player not found
+ if (fixed.error == 1) // player not found
output = STRPRINTF("The player '%s' doesn't exist."_fmt,
player_name);
else
{
- switch (RFIFOW(s, 30))
+ switch (fixed.operation)
{
case 1: // block
- switch (RFIFOW(s, 32))
+ switch (fixed.error)
{
case 0: // login-server resquest done
output = STRPRINTF(
@@ -514,7 +500,7 @@ int chrif_char_ask_name_answer(Session *s)
}
break;
case 2: // ban
- switch (RFIFOW(s, 32))
+ switch (fixed.error)
{
case 0: // login-server resquest done
output = STRPRINTF(
@@ -535,7 +521,7 @@ int chrif_char_ask_name_answer(Session *s)
}
break;
case 3: // unblock
- switch (RFIFOW(s, 32))
+ switch (fixed.error)
{
case 0: // login-server resquest done
output = STRPRINTF(
@@ -556,7 +542,7 @@ int chrif_char_ask_name_answer(Session *s)
}
break;
case 4: // unban
- switch (RFIFOW(s, 32))
+ switch (fixed.error)
{
case 0: // login-server resquest done
output = STRPRINTF(
@@ -577,7 +563,7 @@ int chrif_char_ask_name_answer(Session *s)
}
break;
case 5: // changesex
- switch (RFIFOW(s, 32))
+ switch (fixed.error)
{
case 0: // login-server resquest done
output = STRPRINTF(
@@ -613,10 +599,10 @@ int chrif_char_ask_name_answer(Session *s)
*------------------------------------------
*/
static
-void chrif_changedgm(Session *s)
+void chrif_changedgm(Session *, const Packet_Fixed<0x2b0b>& fixed)
{
- AccountId acc = wrap<AccountId>(RFIFOL(s, 2));
- GmLevel level = GmLevel::from(RFIFOL(s, 6));
+ AccountId acc = fixed.account_id;
+ GmLevel level = fixed.gm_level;
dumb_ptr<map_session_data> sd = map_id2sd(account_to_block(acc));
@@ -637,13 +623,13 @@ void chrif_changedgm(Session *s)
*------------------------------------------
*/
static
-void chrif_changedsex(Session *s)
+void chrif_changedsex(Session *, const Packet_Fixed<0x2b0d>& fixed)
{
int i;
dumb_ptr<map_session_data> sd;
- AccountId acc = wrap<AccountId>(RFIFOL(s, 2));
- SEX sex = static_cast<SEX>(RFIFOB(s, 6));
+ AccountId acc = fixed.account_id;
+ SEX sex = fixed.sex;
if (battle_config.etc_log)
PRINTF("chrif_changedsex %d.\n"_fmt, acc);
sd = map_id2sd(account_to_block(acc));
@@ -686,24 +672,24 @@ void chrif_changedsex(Session *s)
*/
int chrif_saveaccountreg2(dumb_ptr<map_session_data> sd)
{
- int p, j;
nullpo_retr(-1, sd);
- p = 8;
- for (j = 0; j < sd->status.account_reg2_num; j++)
+ std::vector<Packet_Repeat<0x2b10>> repeat_10;
+ for (size_t j = 0; j < sd->status.account_reg2_num; j++)
{
struct global_reg *reg = &sd->status.account_reg2[j];
if (reg->str && reg->value != 0)
{
- WFIFO_STRING(char_session, p, reg->str, 32);
- WFIFOL(char_session, p + 32) = reg->value;
- p += 36;
+ Packet_Repeat<0x2b10> info;
+ info.name = reg->str;
+ info.value = reg->value;
+ repeat_10.push_back(info);
}
}
- WFIFOW(char_session, 0) = 0x2b10;
- WFIFOW(char_session, 2) = p;
- WFIFOL(char_session, 4) = unwrap<BlockId>(sd->bl_id);
- WFIFOSET(char_session, p);
+
+ Packet_Head<0x2b10> head_10;
+ head_10.account_id = block_to_account(sd->bl_id);
+ send_vpacket<0x2b10, 8, 36>(char_session, head_10, repeat_10);
return 0;
}
@@ -713,20 +699,19 @@ int chrif_saveaccountreg2(dumb_ptr<map_session_data> sd)
*------------------------------------------
*/
static
-int chrif_accountreg2(Session *s)
+int chrif_accountreg2(Session *, const Packet_Head<0x2b11>& head, const std::vector<Packet_Repeat<0x2b11>>& repeat)
{
- int j, p;
- dumb_ptr<map_session_data> sd = map_id2sd(account_to_block(wrap<AccountId>(RFIFOL(s, 4))));
+ dumb_ptr<map_session_data> sd = map_id2sd(account_to_block(head.account_id));
if (sd == NULL)
return 1;
- for (p = 8, j = 0; p < RFIFOW(s, 2) && j < ACCOUNT_REG2_NUM;
- p += 36, j++)
+ size_t jlim = std::min(ACCOUNT_REG2_NUM, repeat.size());
+ for (size_t j = 0; j < jlim; j++)
{
- sd->status.account_reg2[j].str = stringish<VarName>(RFIFO_STRING<32>(s, p));
- sd->status.account_reg2[j].value = RFIFOL(s, p + 32);
+ sd->status.account_reg2[j].str = repeat[j].name;
+ sd->status.account_reg2[j].value = repeat[j].value;
}
- sd->status.account_reg2_num = j;
+ sd->status.account_reg2_num = jlim;
return 0;
}
@@ -775,9 +760,9 @@ int chrif_send_divorce(CharId char_id)
if (!char_session)
return -1;
- WFIFOW(char_session, 0) = 0x2b16;
- WFIFOL(char_session, 2) = unwrap<CharId>(char_id);
- WFIFOSET(char_session, 6);
+ Packet_Fixed<0x2b16> fixed_16;
+ fixed_16.char_id = char_id;
+ send_fpacket<0x2b16, 6>(char_session, fixed_16);
return 0;
}
@@ -786,11 +771,11 @@ int chrif_send_divorce(CharId char_id)
*------------------------------------------
*/
static
-int chrif_accountdeletion(Session *s)
+int chrif_accountdeletion(Session *, const Packet_Fixed<0x2b13>& fixed)
{
dumb_ptr<map_session_data> sd;
- AccountId acc = wrap<AccountId>(RFIFOL(s, 2));
+ AccountId acc = fixed.account_id;
if (battle_config.etc_log)
PRINTF("chrif_accountdeletion %d.\n"_fmt, acc);
sd = map_id2sd(account_to_block(acc));
@@ -818,11 +803,11 @@ int chrif_accountdeletion(Session *s)
*------------------------------------------
*/
static
-int chrif_accountban(Session *s)
+int chrif_accountban(Session *, const Packet_Fixed<0x2b14>& fixed)
{
dumb_ptr<map_session_data> sd;
- AccountId acc = wrap<AccountId>(RFIFOL(s, 2));
+ AccountId acc = fixed.account_id;
if (battle_config.etc_log)
PRINTF("chrif_accountban %d.\n"_fmt, acc);
sd = map_id2sd(account_to_block(acc));
@@ -831,9 +816,9 @@ int chrif_accountban(Session *s)
if (sd != NULL)
{
sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters
- if (RFIFOB(s, 6) == 0)
+ if (fixed.ban_not_status == 0)
{ // 0: change of statut, 1: ban
- switch (RFIFOL(s, 7))
+ switch (static_cast<time_t>(fixed.status_or_ban_until))
{ // status or final date of a banishment
case 1: // 0 = Unregistered ID
clif_displaymessage(sd->sess,
@@ -881,10 +866,10 @@ int chrif_accountban(Session *s)
break;
}
}
- else if (RFIFOB(s, 6) == 1)
+ else if (fixed.ban_not_status == 1)
{
// 0: change of statut, 1: ban
- const TimeT timestamp = static_cast<time_t>(RFIFOL(s, 7)); // status or final date of a banishment
+ const TimeT timestamp = fixed.status_or_ban_until; // status or final date of a banishment
timestamp_seconds_buffer buffer;
stamp_time(buffer, &timestamp);
AString tmpstr = STRPRINTF("Your account has been banished until %s"_fmt, buffer);
@@ -907,10 +892,10 @@ int chrif_accountban(Session *s)
*------------------------------------------
*/
static
-int chrif_recvgmaccounts(Session *s)
+int chrif_recvgmaccounts(Session *s, const std::vector<Packet_Repeat<0x2b15>>& repeat)
{
PRINTF("From login-server: receiving of %d GM accounts information.\n"_fmt,
- pc_read_gm_account(s));
+ pc_read_gm_account(s, repeat));
return 0;
}
@@ -921,9 +906,8 @@ int chrif_recvgmaccounts(Session *s)
*/
int chrif_reloadGMdb(void)
{
-
- WFIFOW(char_session, 0) = 0x2af7;
- WFIFOSET(char_session, 2);
+ Packet_Fixed<0x2af7> fixed_f7;
+ send_fpacket<0x2af7, 2>(char_session, fixed_f7);
return 0;
}
@@ -1014,10 +998,10 @@ void ladmin_itemfrob_c(dumb_ptr<block_list> bl, ItemNameId source_id, ItemNameId
}
static
-void ladmin_itemfrob(Session *s)
+void ladmin_itemfrob(Session *, const Packet_Fixed<0x2afa>& fixed)
{
- ItemNameId source_id = wrap<ItemNameId>(static_cast<uint16_t>(RFIFOL(s, 2)));
- ItemNameId dest_id = wrap<ItemNameId>(static_cast<uint16_t>(RFIFOL(s, 6)));
+ ItemNameId source_id = fixed.source_item_id;
+ ItemNameId dest_id = fixed.dest_item_id;
dumb_ptr<block_list> bl = map_get_first_session();
// flooritems
@@ -1048,121 +1032,213 @@ void chrif_delete(Session *s)
static
void chrif_parse(Session *s)
{
- int packet_len, cmd;
-
- // only char-server can have an access to here.
- // so, if it isn't the char-server, we disconnect the session (fd != char_fd).
- if (s != char_session)
- {
- s->set_eof();
- return;
- }
+ assert (s == char_session);
- while (RFIFOREST(s) >= 2)
+ RecvResult rv = RecvResult::Complete;
+ uint16_t packet_id;
+ while (rv == RecvResult::Complete && packet_peek_id(s, &packet_id))
{
- cmd = RFIFOW(s, 0);
- if (cmd < 0x2af8
- || cmd >=
- 0x2af8 +
- (sizeof(packet_len_table) / sizeof(packet_len_table[0]))
- || packet_len_table[cmd - 0x2af8] == 0)
- {
-
- int r = intif_parse(s); // intifに渡す
-
- if (r == 1)
- continue; // intifで処理した
- if (r == 2)
- return; // intifで処理したが、データが足りない
-
- s->set_eof();
- return;
- }
- packet_len = packet_len_table[cmd - 0x2af8];
- if (packet_len == -1)
- {
- if (RFIFOREST(s) < 4)
- return;
- packet_len = RFIFOW(s, 2);
- }
- if (RFIFOREST(s) < packet_len)
- return;
-
- switch (cmd)
+ switch (packet_id)
{
case 0x2af9:
- chrif_connectack(s);
+ {
+ Packet_Fixed<0x2af9> fixed;
+ rv = recv_fpacket<0x2af9, 3>(s, fixed);
+ if (rv != RecvResult::Complete)
+ break;
+
+ chrif_connectack(s, fixed);
break;
+ }
case 0x2afa:
- ladmin_itemfrob(s);
+ {
+ Packet_Fixed<0x2afa> fixed;
+ rv = recv_fpacket<0x2afa, 10>(s, fixed);
+ if (rv != RecvResult::Complete)
+ break;
+
+ ladmin_itemfrob(s, fixed);
break;
+ }
case 0x2afb:
- chrif_sendmapack(s);
+ {
+ Packet_Fixed<0x2afb> fixed;
+ rv = recv_fpacket<0x2afb, 27>(s, fixed);
+ if (rv != RecvResult::Complete)
+ break;
+
+ chrif_sendmapack(s, fixed);
break;
+ }
case 0x2afd:
{
- AccountId id = wrap<AccountId>(RFIFOL(s, 4));
- int login_id2 = RFIFOL(s, 8);
- TimeT connect_until_time = static_cast<time_t>(RFIFOL(s, 12));
- short tmw_version = RFIFOW(s, 16);
- CharKey st_key;
- CharData st_data;
- RFIFO_STRUCT(s, 18, st_key);
- RFIFO_STRUCT(s, 18 + sizeof(st_key), st_data);
+ Packet_Payload<0x2afd> payload;
+ rv = recv_ppacket<0x2afd>(s, payload);
+ if (rv != RecvResult::Complete)
+ break;
+
+ AccountId id = payload.account_id;
+ int login_id2 = payload.login_id2;
+ TimeT connect_until_time = payload.connect_until;
+ short tmw_version = payload.packet_tmw_version;
+ CharKey st_key = payload.char_key;
+ CharData st_data = payload.char_data;
pc_authok(id, login_id2,
connect_until_time, tmw_version,
&st_key, &st_data);
- }
break;
+ }
case 0x2afe:
- pc_authfail(wrap<AccountId>(RFIFOL(s, 2)));
+ {
+ Packet_Fixed<0x2afe> fixed;
+ rv = recv_fpacket<0x2afe, 6>(s, fixed);
+ if (rv != RecvResult::Complete)
+ break;
+
+ pc_authfail(fixed.account_id);
break;
+ }
case 0x2b00:
- map_setusers(RFIFOL(s, 2));
+ {
+ Packet_Fixed<0x2b00> fixed;
+ rv = recv_fpacket<0x2b00, 6>(s, fixed);
+ if (rv != RecvResult::Complete)
+ break;
+
+ map_setusers(fixed.users);
break;
+ }
case 0x2b03:
- clif_charselectok(wrap<BlockId>(RFIFOL(s, 2)));
+ {
+ Packet_Fixed<0x2b03> fixed;
+ rv = recv_fpacket<0x2b03, 7>(s, fixed);
+ if (rv != RecvResult::Complete)
+ break;
+
+ clif_charselectok(account_to_block(fixed.account_id));
break;
+ }
case 0x2b04:
- chrif_recvmap(s);
+ {
+ Packet_Head<0x2b04> head;
+ std::vector<Packet_Repeat<0x2b04>> repeat;
+ rv = recv_vpacket<0x2b04, 10, 16>(s, head, repeat);
+ if (rv != RecvResult::Complete)
+ break;
+
+ chrif_recvmap(s, head, repeat);
break;
+ }
case 0x2b06:
- chrif_changemapserverack(s);
+ {
+ Packet_Fixed<0x2b06> fixed;
+ rv = recv_fpacket<0x2b06, 44>(s, fixed);
+ if (rv != RecvResult::Complete)
+ break;
+
+ chrif_changemapserverack(s, fixed);
break;
+ }
case 0x2b0b:
- chrif_changedgm(s);
+ {
+ Packet_Fixed<0x2b0b> fixed;
+ rv = recv_fpacket<0x2b0b, 10>(s, fixed);
+ if (rv != RecvResult::Complete)
+ break;
+
+ chrif_changedgm(s, fixed);
break;
+ }
case 0x2b0d:
- chrif_changedsex(s);
+ {
+ Packet_Fixed<0x2b0d> fixed;
+ rv = recv_fpacket<0x2b0d, 7>(s, fixed);
+ if (rv != RecvResult::Complete)
+ break;
+
+ chrif_changedsex(s, fixed);
break;
+ }
case 0x2b0f:
- chrif_char_ask_name_answer(s);
+ {
+ Packet_Fixed<0x2b0f> fixed;
+ rv = recv_fpacket<0x2b0f, 34>(s, fixed);
+ if (rv != RecvResult::Complete)
+ break;
+
+ chrif_char_ask_name_answer(s, fixed);
break;
+ }
case 0x2b11:
- chrif_accountreg2(s);
+ {
+ Packet_Head<0x2b11> head;
+ std::vector<Packet_Repeat<0x2b11>> repeat;
+ rv = recv_vpacket<0x2b11, 8, 36>(s, head, repeat);
+ if (rv != RecvResult::Complete)
+ break;
+
+ chrif_accountreg2(s, head, repeat);
break;
+ }
case 0x2b12:
- chrif_divorce(wrap<CharId>(RFIFOL(s, 2)), wrap<CharId>(RFIFOL(s, 6)));
+ {
+ Packet_Fixed<0x2b12> fixed;
+ rv = recv_fpacket<0x2b12, 10>(s, fixed);
+ if (rv != RecvResult::Complete)
+ break;
+
+ chrif_divorce(fixed.char_id, fixed.partner_id);
break;
+ }
case 0x2b13:
- chrif_accountdeletion(s);
+ {
+ Packet_Fixed<0x2b13> fixed;
+ rv = recv_fpacket<0x2b13, 6>(s, fixed);
+ if (rv != RecvResult::Complete)
+ break;
+
+ chrif_accountdeletion(s, fixed);
break;
+ }
case 0x2b14:
- chrif_accountban(s);
+ {
+ Packet_Fixed<0x2b14> fixed;
+ rv = recv_fpacket<0x2b14, 11>(s, fixed);
+ if (rv != RecvResult::Complete)
+ break;
+
+ chrif_accountban(s, fixed);
break;
+ }
case 0x2b15:
- chrif_recvgmaccounts(s);
- break;
+ {
+ std::vector<Packet_Repeat<0x2b15>> repeat;
+ rv = recv_packet_repeatonly<0x2b15, 4, 5>(s, repeat);
+ if (rv != RecvResult::Complete)
+ break;
+ chrif_recvgmaccounts(s, repeat);
+ break;
+ }
default:
+ {
+ RecvResult r = intif_parse(s, packet_id);
+
+ if (r == RecvResult::Complete)
+ break;
+ if (r == RecvResult::Incomplete)
+ return;
+
if (battle_config.error_log)
PRINTF("chrif_parse : unknown packet %d %d\n"_fmt, s,
- RFIFOW(s, 0));
+ packet_id);
s->set_eof();
return;
+ }
}
- RFIFOSKIP(s, packet_len);
}
+ if (rv == RecvResult::Error)
+ s->set_eof();
}
/*==========================================
@@ -1178,7 +1254,8 @@ void send_users_tochar(TimerData *, tick_t)
if (!char_session)
return;
- WFIFOW(char_session, 0) = 0x2aff;
+ Packet_Head<0x2aff> head_ff;
+ std::vector<Packet_Repeat<0x2aff>> repeat_ff;
for (io::FD i : iter_fds())
{
Session *s = get_session(i);
@@ -1190,13 +1267,13 @@ void send_users_tochar(TimerData *, tick_t)
|| sd->state.shroud_active
|| bool(sd->status.option & Option::HIDE)) && pc_isGM(sd)))
{
- WFIFOL(char_session, 6 + 4 * users) = unwrap<CharId>(sd->status_key.char_id);
- users++;
+ Packet_Repeat<0x2aff> info;
+ info.char_id = sd->status_key.char_id;
+ repeat_ff.push_back(info);
}
}
- WFIFOW(char_session, 2) = 6 + 4 * users;
- WFIFOW(char_session, 4) = users;
- WFIFOSET(char_session, 6 + 4 * users);
+ head_ff.users = users;
+ send_vpacket<0x2aff, 6, 4>(char_session, head_ff, repeat_ff);
}
/*==========================================
diff --git a/src/map/intif.cpp b/src/map/intif.cpp
index bb4b893..3ca2130 100644
--- a/src/map/intif.cpp
+++ b/src/map/intif.cpp
@@ -29,11 +29,13 @@
#include "../io/cxxstdio.hpp"
+#include "../net/packets.hpp"
#include "../net/socket.hpp"
-#include "../net/vomit.hpp"
#include "../mmo/mmo.hpp"
+#include "../proto2/char-map.hpp"
+
#include "battle.hpp"
#include "chrif.hpp"
#include "clif.hpp"
@@ -44,20 +46,6 @@
#include "../poison.hpp"
-static
-const int packet_len_table[] =
-{
- -1, -1, 27, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- -1, 7, 0, 0, 0, 0, 0, 0, -1, 11, 0, 0, 0, 0, 0, 0,
- 35, -1, 11, 15, 34, 29, 7, -1, 0, 0, 0, 0, 0, 0, 0, 0,
- 10, -1, 15, 0, 79, 19, 7, -1, 0, -1, -1, -1, 14, 67, 186, -1,
- 9, 9, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 11, -1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
//-----------------------------------------------------------------
// inter serverへの送信
@@ -65,11 +53,7 @@ const int packet_len_table[] =
// Message for all GMs on all map servers
void intif_GMmessage(XString mes)
{
- WFIFOW(char_session, 0) = 0x3000;
- size_t len = mes.size() + 1;
- WFIFOW(char_session, 2) = 4 + len;
- WFIFO_STRING(char_session, 4, mes, len);
- WFIFOSET(char_session, WFIFOW(char_session, 2));
+ send_packet_repeatonly<0x3000, 4, 1>(char_session, mes);
}
// The transmission of Wisp/Page to inter-server (player not found on this server)
@@ -77,13 +61,10 @@ void intif_wis_message(dumb_ptr<map_session_data> sd, CharName nick, ZString mes
{
nullpo_retv(sd);
- size_t mes_len = mes.size() + 1;
- WFIFOW(char_session, 0) = 0x3001;
- WFIFOW(char_session, 2) = mes_len + 52;
- WFIFO_STRING(char_session, 4, sd->status_key.name.to__actual(), 24);
- WFIFO_STRING(char_session, 28, nick.to__actual(), 24);
- WFIFO_STRING(char_session, 52, mes, mes_len);
- WFIFOSET(char_session, WFIFOW(char_session, 2));
+ Packet_Head<0x3001> head_01;
+ head_01.from_char_name = sd->status_key.name;
+ head_01.to_char_name = nick;
+ send_vpacket<0x3001, 52, 1>(char_session, head_01, mes);
if (battle_config.etc_log)
PRINTF("intif_wis_message from %s to %s)\n"_fmt,
@@ -92,12 +73,12 @@ void intif_wis_message(dumb_ptr<map_session_data> sd, CharName nick, ZString mes
// The reply of Wisp/page
static
-void intif_wis_replay(int id, int flag)
+void intif_wis_replay(CharId id, int flag)
{
- WFIFOW(char_session, 0) = 0x3002;
- WFIFOL(char_session, 2) = id;
- WFIFOB(char_session, 6) = flag; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
- WFIFOSET(char_session, 7);
+ Packet_Fixed<0x3002> fixed_02;
+ fixed_02.char_id = id;
+ fixed_02.flag = flag; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
+ send_fpacket<0x3002, 7>(char_session, fixed_02);
if (battle_config.etc_log)
PRINTF("intif_wis_replay: id: %d, flag:%d\n"_fmt, id, flag);
@@ -106,13 +87,10 @@ void intif_wis_replay(int id, int flag)
// The transmission of GM only Wisp/Page from server to inter-server
void intif_wis_message_to_gm(CharName Wisp_name, GmLevel min_gm_level, ZString mes)
{
- size_t mes_len = mes.size() + 1;
- WFIFOW(char_session, 0) = 0x3003;
- WFIFOW(char_session, 2) = mes_len + 30;
- WFIFO_STRING(char_session, 4, Wisp_name.to__actual(), 24);
- WFIFOW(char_session, 28) = static_cast<uint16_t>(min_gm_level.get_all_bits());
- WFIFO_STRING(char_session, 30, mes, mes_len);
- WFIFOSET(char_session, WFIFOW(char_session, 2));
+ Packet_Head<0x3003> head_03;
+ head_03.char_name = Wisp_name;
+ head_03.min_gm_level = min_gm_level;
+ send_vpacket<0x3003, 30, 1>(char_session, head_03, mes);
if (battle_config.etc_log)
PRINTF("intif_wis_message_to_gm: from: '%s', min level: %d, message: '%s'.\n"_fmt,
@@ -122,20 +100,18 @@ void intif_wis_message_to_gm(CharName Wisp_name, GmLevel min_gm_level, ZString m
// アカウント変数送信
void intif_saveaccountreg(dumb_ptr<map_session_data> sd)
{
- int j, p;
-
nullpo_retv(sd);
assert (sd->status.account_reg_num < ACCOUNT_REG_NUM);
- WFIFOW(char_session, 0) = 0x3004;
- WFIFOL(char_session, 4) = unwrap<BlockId>(sd->bl_id);
- for (j = 0, p = 8; j < sd->status.account_reg_num; j++, p += 36)
+ Packet_Head<0x3004> head_04;
+ head_04.account_id = block_to_account(sd->bl_id);
+ std::vector<Packet_Repeat<0x3004>> repeat_04(sd->status.account_reg_num);
+ for (size_t j = 0; j < sd->status.account_reg_num; j++)
{
- WFIFO_STRING(char_session, p, sd->status.account_reg[j].str, 32);
- WFIFOL(char_session, p + 32) = sd->status.account_reg[j].value;
+ repeat_04[j].name = sd->status.account_reg[j].str;
+ repeat_04[j].value = sd->status.account_reg[j].value;
}
- WFIFOW(char_session, 2) = p;
- WFIFOSET(char_session, p);
+ send_vpacket<0x3004, 8, 36>(char_session, head_04, repeat_04);
}
// アカウント変数要求
@@ -143,28 +119,27 @@ void intif_request_accountreg(dumb_ptr<map_session_data> sd)
{
nullpo_retv(sd);
- WFIFOW(char_session, 0) = 0x3005;
- WFIFOL(char_session, 2) = unwrap<BlockId>(sd->bl_id);
- WFIFOSET(char_session, 6);
+ Packet_Fixed<0x3005> fixed_05;
+ fixed_05.account_id = block_to_account(sd->bl_id);
+ send_fpacket<0x3005, 6>(char_session, fixed_05);
}
// 倉庫データ要求
void intif_request_storage(AccountId account_id)
{
- WFIFOW(char_session, 0) = 0x3010;
- WFIFOL(char_session, 2) = unwrap<AccountId>(account_id);
- WFIFOSET(char_session, 6);
+ Packet_Fixed<0x3010> fixed_10;
+ fixed_10.account_id = account_id;
+ send_fpacket<0x3010, 6>(char_session, fixed_10);
}
// 倉庫データ送信
void intif_send_storage(Storage *stor)
{
nullpo_retv(stor);
- WFIFOW(char_session, 0) = 0x3011;
- WFIFOW(char_session, 2) = sizeof(Storage) + 8;
- WFIFOL(char_session, 4) = unwrap<AccountId>(stor->account_id);
- WFIFO_STRUCT(char_session, 8, *stor);
- WFIFOSET(char_session, WFIFOW(char_session, 2));
+ Packet_Payload<0x3011> payload_11;
+ payload_11.account_id = stor->account_id;
+ payload_11.storage = *stor;
+ send_ppacket<0x3011>(char_session, payload_11);
}
// パーティ作成要求
@@ -172,21 +147,21 @@ void intif_create_party(dumb_ptr<map_session_data> sd, PartyName name)
{
nullpo_retv(sd);
- WFIFOW(char_session, 0) = 0x3020;
- WFIFOL(char_session, 2) = unwrap<AccountId>(sd->status_key.account_id);
- WFIFO_STRING(char_session, 6, name, 24);
- WFIFO_STRING(char_session, 30, sd->status_key.name.to__actual(), 24);
- WFIFO_STRING(char_session, 54, sd->bl_m->name_, 16);
- WFIFOW(char_session, 70) = sd->status.base_level;
- WFIFOSET(char_session, 72);
+ Packet_Fixed<0x3020> fixed_20;
+ fixed_20.account_id = sd->status_key.account_id;
+ fixed_20.party_name = name;
+ fixed_20.char_name = sd->status_key.name;
+ fixed_20.map_name = sd->bl_m->name_;
+ fixed_20.level = sd->status.base_level;
+ send_fpacket<0x3020, 72>(char_session, fixed_20);
}
// パーティ情報要求
void intif_request_partyinfo(PartyId party_id)
{
- WFIFOW(char_session, 0) = 0x3021;
- WFIFOL(char_session, 2) = unwrap<PartyId>(party_id);
- WFIFOSET(char_session, 6);
+ Packet_Fixed<0x3021> fixed_21;
+ fixed_21.party_id = party_id;
+ send_fpacket<0x3021, 6>(char_session, fixed_21);
}
// パーティ追加要求
@@ -196,34 +171,34 @@ void intif_party_addmember(PartyId party_id, AccountId account_id)
sd = map_id2sd(account_to_block(account_id));
if (sd != NULL)
{
- WFIFOW(char_session, 0) = 0x3022;
- WFIFOL(char_session, 2) = unwrap<PartyId>(party_id);
- WFIFOL(char_session, 6) = unwrap<AccountId>(account_id);
- WFIFO_STRING(char_session, 10, sd->status_key.name.to__actual(), 24);
- WFIFO_STRING(char_session, 34, sd->bl_m->name_, 16);
- WFIFOW(char_session, 50) = sd->status.base_level;
- WFIFOSET(char_session, 52);
+ Packet_Fixed<0x3022> fixed_22;
+ fixed_22.party_id = party_id;
+ fixed_22.account_id = account_id;
+ fixed_22.char_name = sd->status_key.name;
+ fixed_22.map_name = sd->bl_m->name_;
+ fixed_22.level = sd->status.base_level;
+ send_fpacket<0x3022, 52>(char_session, fixed_22);
}
}
// パーティ設定変更
void intif_party_changeoption(PartyId party_id, AccountId account_id, int exp, int item)
{
- WFIFOW(char_session, 0) = 0x3023;
- WFIFOL(char_session, 2) = unwrap<PartyId>(party_id);
- WFIFOL(char_session, 6) = unwrap<AccountId>(account_id);
- WFIFOW(char_session, 10) = exp;
- WFIFOW(char_session, 12) = item;
- WFIFOSET(char_session, 14);
+ Packet_Fixed<0x3023> fixed_23;
+ fixed_23.party_id = party_id;
+ fixed_23.account_id = account_id;
+ fixed_23.exp = exp;
+ fixed_23.item = item;
+ send_fpacket<0x3023, 14>(char_session, fixed_23);
}
// パーティ脱退要求
void intif_party_leave(PartyId party_id, AccountId account_id)
{
- WFIFOW(char_session, 0) = 0x3024;
- WFIFOL(char_session, 2) = unwrap<PartyId>(party_id);
- WFIFOL(char_session, 6) = unwrap<AccountId>(account_id);
- WFIFOSET(char_session, 10);
+ Packet_Fixed<0x3024> fixed_24;
+ fixed_24.party_id = party_id;
+ fixed_24.account_id = account_id;
+ send_fpacket<0x3024, 10>(char_session, fixed_24);
}
// パーティ移動要求
@@ -231,36 +206,33 @@ void intif_party_changemap(dumb_ptr<map_session_data> sd, int online)
{
if (sd != NULL)
{
- WFIFOW(char_session, 0) = 0x3025;
- WFIFOL(char_session, 2) = unwrap<PartyId>(sd->status.party_id);
- WFIFOL(char_session, 6) = unwrap<AccountId>(sd->status_key.account_id);
- WFIFO_STRING(char_session, 10, sd->bl_m->name_, 16);
- WFIFOB(char_session, 26) = online;
- WFIFOW(char_session, 27) = sd->status.base_level;
- WFIFOSET(char_session, 29);
+ Packet_Fixed<0x3025> fixed_25;
+ fixed_25.party_id = sd->status.party_id;
+ fixed_25.account_id = sd->status_key.account_id;
+ fixed_25.map_name = sd->bl_m->name_;
+ fixed_25.online = online;
+ fixed_25.level = sd->status.base_level;
+ send_fpacket<0x3025, 29>(char_session, fixed_25);
}
}
// パーティ会話送信
void intif_party_message(PartyId party_id, AccountId account_id, XString mes)
{
- size_t len = mes.size() + 1;
- WFIFOW(char_session, 0) = 0x3027;
- WFIFOW(char_session, 2) = len + 12;
- WFIFOL(char_session, 4) = unwrap<PartyId>(party_id);
- WFIFOL(char_session, 8) = unwrap<AccountId>(account_id);
- WFIFO_STRING(char_session, 12, mes, len);
- WFIFOSET(char_session, len + 12);
+ Packet_Head<0x3027> head_27;
+ head_27.party_id = party_id;
+ head_27.account_id = account_id;
+ send_vpacket<0x3027, 12, 1>(char_session, head_27, mes);
}
// パーティ競合チェック要求
void intif_party_checkconflict(PartyId party_id, AccountId account_id, CharName nick)
{
- WFIFOW(char_session, 0) = 0x3028;
- WFIFOL(char_session, 2) = unwrap<PartyId>(party_id);
- WFIFOL(char_session, 6) = unwrap<AccountId>(account_id);
- WFIFO_STRING(char_session, 10, nick.to__actual(), 24);
- WFIFOSET(char_session, 34);
+ Packet_Fixed<0x3028> fixed_28;
+ fixed_28.party_id = party_id;
+ fixed_28.account_id = account_id;
+ fixed_28.char_name = nick;
+ send_fpacket<0x3028, 34>(char_session, fixed_28);
}
//-----------------------------------------------------------------
@@ -268,21 +240,18 @@ void intif_party_checkconflict(PartyId party_id, AccountId account_id, CharName
// Wisp/Page reception
static
-int intif_parse_WisMessage(Session *s)
+int intif_parse_WisMessage(Session *, const Packet_Head<0x3801>& head, AString& buf)
{
// rewritten by [Yor]
dumb_ptr<map_session_data> sd;
- CharName from = stringish<CharName>(RFIFO_STRING<24>(s, 8));
- CharName to = stringish<CharName>(RFIFO_STRING<24>(s, 32));
-
- size_t len = RFIFOW(s, 2) - 56;
- AString buf = RFIFO_STRING(s, 56, len);
+ CharName from = head.src_char_name;
+ CharName to = head.dst_char_name;
if (battle_config.etc_log)
{
PRINTF("intif_parse_wismessage: id: %d, from: %s, to: %s\n"_fmt,
- RFIFOL(s, 4),
+ head.whisper_id,
from,
to);
}
@@ -294,23 +263,23 @@ int intif_parse_WisMessage(Session *s)
// if source player not found in ignore list
{
clif_wis_message(sd->sess, from, buf);
- intif_wis_replay(RFIFOL(s, 4), 0); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
+ intif_wis_replay(head.whisper_id, 0); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
}
}
}
else
- intif_wis_replay(RFIFOL(s, 4), 1); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
+ intif_wis_replay(head.whisper_id, 1); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
return 0;
}
// Wisp/page transmission result reception
static
-int intif_parse_WisEnd(Session *s)
+int intif_parse_WisEnd(Session *, const Packet_Fixed<0x3802>& fixed)
{
dumb_ptr<map_session_data> sd;
- CharName name = stringish<CharName>(RFIFO_STRING<24>(s, 2));
- uint8_t flag = RFIFOB(s, 26);
+ CharName name = fixed.sender_char_name;
+ uint8_t flag = fixed.flag;
if (battle_config.etc_log)
// flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
PRINTF("intif_parse_wisend: player: %s, flag: %d\n"_fmt,
@@ -324,17 +293,11 @@ int intif_parse_WisEnd(Session *s)
// Received wisp message from map-server via char-server for ALL gm
static
-void mapif_parse_WisToGM(Session *s)
+void mapif_parse_WisToGM(Session *, const Packet_Head<0x3803>& head, AString& message)
{
// 0x3003/0x3803 <packet_len>.w <wispname>.24B <min_gm_level>.w <message>.?B
- if (RFIFOW(s, 2) - 30 <= 0)
- return;
-
- int len = RFIFOW(s, 2) - 30;
-
- GmLevel min_gm_level = GmLevel::from(static_cast<uint32_t>(RFIFOW(s, 28)));
- CharName Wisp_name = stringish<CharName>(RFIFO_STRING<24>(s, 4));
- AString message = RFIFO_STRING(s, 30, len);
+ GmLevel min_gm_level = head.min_gm_level;
+ CharName Wisp_name = head.char_name;
// information is sended to all online GM
for (io::FD i : iter_fds())
{
@@ -352,39 +315,39 @@ void mapif_parse_WisToGM(Session *s)
// アカウント変数通知
static
-int intif_parse_AccountReg(Session *s)
+int intif_parse_AccountReg(Session *, const Packet_Head<0x3804>& head, const std::vector<Packet_Repeat<0x3804>>& repeat)
{
- int j, p;
- dumb_ptr<map_session_data> sd = map_id2sd(account_to_block(wrap<AccountId>(RFIFOL(s, 4))));
+ dumb_ptr<map_session_data> sd = map_id2sd(account_to_block(head.account_id));
if (sd == NULL)
return 1;
- for (p = 8, j = 0; p < RFIFOW(s, 2) && j < ACCOUNT_REG_NUM;
- p += 36, j++)
+
+ size_t jlim = std::min(ACCOUNT_REG_NUM, repeat.size());
+ for (size_t j = 0; j < jlim; j++)
{
- sd->status.account_reg[j].str = stringish<VarName>(RFIFO_STRING<32>(s, p));
- sd->status.account_reg[j].value = RFIFOL(s, p + 32);
+ sd->status.account_reg[j].str = repeat[j].name;
+ sd->status.account_reg[j].value = repeat[j].value;
}
- sd->status.account_reg_num = j;
+ sd->status.account_reg_num = jlim;
return 0;
}
// 倉庫データ受信
static
-int intif_parse_LoadStorage(Session *s)
+int intif_parse_LoadStorage(Session *, const Packet_Payload<0x3810>& payload)
{
Storage *stor;
dumb_ptr<map_session_data> sd;
- sd = map_id2sd(account_to_block(wrap<AccountId>(RFIFOL(s, 4))));
+ sd = map_id2sd(account_to_block(payload.account_id));
if (sd == NULL)
{
if (battle_config.error_log)
PRINTF("intif_parse_LoadStorage: user not found %d\n"_fmt,
- RFIFOL(s, 4));
+ payload.account_id);
return 1;
}
- stor = account2storage(wrap<AccountId>(RFIFOL(s, 4)));
+ stor = account2storage(payload.account_id);
if (stor->storage_status == 1)
{ // Already open.. lets ignore this update
if (battle_config.error_log)
@@ -400,16 +363,9 @@ int intif_parse_LoadStorage(Session *s)
return 1;
}
- if (RFIFOW(s, 2) - 8 != sizeof(Storage))
- {
- if (battle_config.error_log)
- PRINTF("intif_parse_LoadStorage: data size error %d %zu\n"_fmt,
- RFIFOW(s, 2) - 8, sizeof(Storage));
- return 1;
- }
if (battle_config.save_log)
- PRINTF("intif_openstorage: %d\n"_fmt, RFIFOL(s, 4));
- RFIFO_STRUCT(s, 8, *stor);
+ PRINTF("intif_openstorage: %d\n"_fmt, payload.account_id);
+ *stor = payload.storage;
stor->dirty = 0;
stor->storage_status = 1;
sd->state.storage_open = 1;
@@ -422,50 +378,41 @@ int intif_parse_LoadStorage(Session *s)
// 倉庫データ送信成功
static
-void intif_parse_SaveStorage(Session *s)
+void intif_parse_SaveStorage(Session *, const Packet_Fixed<0x3811>& fixed)
{
if (battle_config.save_log)
- PRINTF("intif_savestorage: done %d %d\n"_fmt, RFIFOL(s, 2),
- RFIFOB(s, 6));
- storage_storage_saved(wrap<AccountId>(RFIFOL(s, 2)));
+ PRINTF("intif_savestorage: done %d %d\n"_fmt, fixed.account_id,
+ fixed.unknown);
+ storage_storage_saved(fixed.account_id);
}
// パーティ作成可否
static
-void intif_parse_PartyCreated(Session *s)
+void intif_parse_PartyCreated(Session *, const Packet_Fixed<0x3820>& fixed)
{
if (battle_config.etc_log)
PRINTF("intif: party created\n"_fmt);
- AccountId account_id = wrap<AccountId>(RFIFOL(s, 2));
- int fail = RFIFOB(s, 6);
- PartyId party_id = wrap<PartyId>(RFIFOL(s, 7));
- PartyName name = stringish<PartyName>(RFIFO_STRING<24>(s, 11));
+ AccountId account_id = fixed.account_id;
+ int fail = fixed.error;
+ PartyId party_id = fixed.party_id;
+ PartyName name = fixed.party_name;
party_created(account_id, fail, party_id, name);
}
// パーティ情報
static
-void intif_parse_PartyInfo(Session *s)
+void intif_parse_PartyInfo(Session *, const Packet_Head<0x3821>& head, bool has_opt, const Packet_Option<0x3821>& option)
{
- if (RFIFOW(s, 2) == 8)
+ if (!has_opt)
{
if (battle_config.error_log)
- PRINTF("intif: party noinfo %d\n"_fmt, RFIFOL(s, 4));
- party_recv_noinfo(wrap<PartyId>(RFIFOL(s, 4)));
+ PRINTF("intif: party noinfo %d\n"_fmt, head.party_id);
+ party_recv_noinfo(head.party_id);
return;
}
- if (RFIFOW(s, 2) != sizeof(PartyMost) + 8)
- {
- if (battle_config.error_log)
- PRINTF("intif: party info : data size error %d %d %zu\n"_fmt,
- RFIFOL(s, 4), RFIFOW(s, 2),
- sizeof(PartyMost) + 8);
- }
- PartyId pi;
- PartyMost pm;
- RFIFO_STRUCT(s, 4, pi);
- RFIFO_STRUCT(s, 8, pm);
+ PartyId pi = head.party_id;
+ PartyMost pm = option.party_most;
PartyPair pp;
pp.party_id = pi;
pp.party_most = &pm;
@@ -474,29 +421,29 @@ void intif_parse_PartyInfo(Session *s)
// パーティ追加通知
static
-void intif_parse_PartyMemberAdded(Session *s)
+void intif_parse_PartyMemberAdded(Session *, const Packet_Fixed<0x3822>& fixed)
{
if (battle_config.etc_log)
- PRINTF("intif: party member added %d %d %d\n"_fmt, RFIFOL(s, 2),
- RFIFOL(s, 6), RFIFOB(s, 10));
- party_member_added(wrap<PartyId>(RFIFOL(s, 2)), wrap<AccountId>(RFIFOL(s, 6)), RFIFOB(s, 10));
+ PRINTF("intif: party member added %d %d %d\n"_fmt, fixed.party_id,
+ fixed.account_id, fixed.flag);
+ party_member_added(fixed.party_id, fixed.account_id, fixed.flag);
}
// パーティ設定変更通知
static
-void intif_parse_PartyOptionChanged(Session *s)
+void intif_parse_PartyOptionChanged(Session *, const Packet_Fixed<0x3823>& fixed)
{
- party_optionchanged(wrap<PartyId>(RFIFOL(s, 2)), wrap<AccountId>(RFIFOL(s, 6)), RFIFOW(s, 10),
- RFIFOW(s, 12), RFIFOB(s, 14));
+ party_optionchanged(fixed.party_id, fixed.account_id, fixed.exp,
+ fixed.item, fixed.flag);
}
// パーティ脱退通知
static
-void intif_parse_PartyMemberLeaved(Session *s)
+void intif_parse_PartyMemberLeaved(Session *, const Packet_Fixed<0x3824>& fixed)
{
- PartyId party_id = wrap<PartyId>(RFIFOL(s, 2));
- AccountId account_id = wrap<AccountId>(RFIFOL(s, 6));
- CharName name = stringish<CharName>(RFIFO_STRING<24>(s, 10));
+ PartyId party_id = fixed.party_id;
+ AccountId account_id = fixed.account_id;
+ CharName name = fixed.char_name;
if (battle_config.etc_log)
PRINTF("intif: party member leaved %d %d %s\n"_fmt,
party_id, account_id, name);
@@ -505,118 +452,198 @@ void intif_parse_PartyMemberLeaved(Session *s)
// パーティ解散通知
static
-void intif_parse_PartyBroken(Session *s)
+void intif_parse_PartyBroken(Session *, const Packet_Fixed<0x3826>& fixed)
{
- party_broken(wrap<PartyId>(RFIFOL(s, 2)));
+ party_broken(fixed.party_id);
}
// パーティ移動通知
static
-void intif_parse_PartyMove(Session *s)
+void intif_parse_PartyMove(Session *, const Packet_Fixed<0x3825>& fixed)
{
- PartyId party_id = wrap<PartyId>(RFIFOL(s, 2));
- AccountId account_id = wrap<AccountId>(RFIFOL(s, 6));
- MapName map = stringish<MapName>(RFIFO_STRING<16>(s, 10));
- uint8_t online = RFIFOB(s, 26);
- uint16_t lv = RFIFOW(s, 27);
+ PartyId party_id = fixed.party_id;
+ AccountId account_id = fixed.account_id;
+ MapName map = fixed.map_name;
+ uint8_t online = fixed.online;
+ uint16_t lv = fixed.level;
party_recv_movemap(party_id, account_id, map, online, lv);
}
// パーティメッセージ
static
-void intif_parse_PartyMessage(Session *s)
+void intif_parse_PartyMessage(Session *, const Packet_Head<0x3827>& head, AString& buf)
{
- size_t len = RFIFOW(s, 2) - 12;
- AString buf = RFIFO_STRING(s, 12, len);
- party_recv_message(wrap<PartyId>(RFIFOL(s, 4)), wrap<AccountId>(RFIFOL(s, 8)), buf);
+ party_recv_message(head.party_id, head.account_id, buf);
}
//-----------------------------------------------------------------
// inter serverからの通信
// エラーがあれば0(false)を返すこと
// パケットが処理できれば1,パケット長が足りなければ2を返すこと
-int intif_parse(Session *s)
+RecvResult intif_parse(Session *s, uint16_t packet_id)
{
- int packet_len;
- int cmd = RFIFOW(s, 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(s) < 4)
- return 2;
- packet_len = RFIFOW(s, 2);
- }
- if (RFIFOREST(s) < packet_len)
- {
- return 2;
- }
- // 処理分岐
- switch (cmd)
+ RecvResult rv;
+
+ switch (packet_id)
{
case 0x3800:
{
- AString mes = RFIFO_STRING(s, 4, packet_len - 4);
+ AString mes;
+ rv = recv_packet_repeatonly<0x3800, 4, 1>(s, mes);
+ if (rv != RecvResult::Complete)
+ return rv;
+
clif_GMmessage(NULL, mes, 0);
- }
break;
+ }
case 0x3801:
- intif_parse_WisMessage(s);
+ {
+ Packet_Head<0x3801> head;
+ AString repeat;
+ rv = recv_vpacket<0x3801, 56, 1>(s, head, repeat);
+ if (rv != RecvResult::Complete)
+ return rv;
+
+ intif_parse_WisMessage(s, head, repeat);
break;
+ }
case 0x3802:
- intif_parse_WisEnd(s);
+ {
+ Packet_Fixed<0x3802> fixed;
+ rv = recv_fpacket<0x3802, 27>(s, fixed);
+ if (rv != RecvResult::Complete)
+ return rv;
+
+ intif_parse_WisEnd(s, fixed);
break;
+ }
case 0x3803:
- mapif_parse_WisToGM(s);
+ {
+ Packet_Head<0x3803> head;
+ AString repeat;
+ rv = recv_vpacket<0x3803, 30, 1>(s, head, repeat);
+ if (rv != RecvResult::Complete)
+ return rv;
+
+ mapif_parse_WisToGM(s, head, repeat);
break;
+ }
case 0x3804:
- intif_parse_AccountReg(s);
+ {
+ Packet_Head<0x3804> head;
+ std::vector<Packet_Repeat<0x3804>> repeat;
+ rv = recv_vpacket<0x3804, 8, 36>(s, head, repeat);
+ if (rv != RecvResult::Complete)
+ return rv;
+
+ intif_parse_AccountReg(s, head, repeat);
break;
+ }
case 0x3810:
- intif_parse_LoadStorage(s);
+ {
+ Packet_Payload<0x3810> payload;
+ rv = recv_ppacket<0x3810>(s, payload);
+ if (rv != RecvResult::Complete)
+ return rv;
+
+ intif_parse_LoadStorage(s, payload);
break;
+ }
case 0x3811:
- intif_parse_SaveStorage(s);
+ {
+ Packet_Fixed<0x3811> fixed;
+ rv = recv_fpacket<0x3811, 7>(s, fixed);
+ if (rv != RecvResult::Complete)
+ return rv;
+
+ intif_parse_SaveStorage(s, fixed);
break;
+ }
case 0x3820:
- intif_parse_PartyCreated(s);
+ {
+ Packet_Fixed<0x3820> fixed;
+ rv = recv_fpacket<0x3820, 35>(s, fixed);
+ if (rv != RecvResult::Complete)
+ return rv;
+
+ intif_parse_PartyCreated(s, fixed);
break;
+ }
case 0x3821:
- intif_parse_PartyInfo(s);
+ {
+ Packet_Head<0x3821> head;
+ bool has_opt;
+ Packet_Option<0x3821> option;
+ rv = recv_opacket<0x3821, 8, sizeof(NetPacket_Option<0x3821>)>(s, head, &has_opt, option);
+ if (rv != RecvResult::Complete)
+ return rv;
+
+ intif_parse_PartyInfo(s, head, has_opt, option);
break;
+ }
case 0x3822:
- intif_parse_PartyMemberAdded(s);
+ {
+ Packet_Fixed<0x3822> fixed;
+ rv = recv_fpacket<0x3822, 11>(s, fixed);
+ if (rv != RecvResult::Complete)
+ return rv;
+
+ intif_parse_PartyMemberAdded(s, fixed);
break;
+ }
case 0x3823:
- intif_parse_PartyOptionChanged(s);
+ {
+ Packet_Fixed<0x3823> fixed;
+ rv = recv_fpacket<0x3823, 15>(s, fixed);
+ if (rv != RecvResult::Complete)
+ return rv;
+
+ intif_parse_PartyOptionChanged(s, fixed);
break;
+ }
case 0x3824:
- intif_parse_PartyMemberLeaved(s);
+ {
+ Packet_Fixed<0x3824> fixed;
+ rv = recv_fpacket<0x3824, 34>(s, fixed);
+ if (rv != RecvResult::Complete)
+ return rv;
+
+ intif_parse_PartyMemberLeaved(s, fixed);
break;
+ }
case 0x3825:
- intif_parse_PartyMove(s);
+ {
+ Packet_Fixed<0x3825> fixed;
+ rv = recv_fpacket<0x3825, 29>(s, fixed);
+ if (rv != RecvResult::Complete)
+ return rv;
+
+ intif_parse_PartyMove(s, fixed);
break;
+ }
case 0x3826:
- intif_parse_PartyBroken(s);
+ {
+ Packet_Fixed<0x3826> fixed;
+ rv = recv_fpacket<0x3826, 7>(s, fixed);
+ if (rv != RecvResult::Complete)
+ return rv;
+
+ intif_parse_PartyBroken(s, fixed);
break;
+ }
case 0x3827:
- intif_parse_PartyMessage(s);
+ {
+ Packet_Head<0x3827> head;
+ AString repeat;
+ rv = recv_vpacket<0x3827, 12, 1>(s, head, repeat);
+ if (rv != RecvResult::Complete)
+ return rv;
+
+ intif_parse_PartyMessage(s, head, repeat);
break;
+ }
default:
- if (battle_config.error_log)
- PRINTF("intif_parse : unknown packet %d %x\n"_fmt, s,
- RFIFOW(s, 0));
- return 0;
+ return RecvResult::Error;
}
- // パケット読み飛ばし
- RFIFOSKIP(s, packet_len);
- return 1;
+ return rv;
}
diff --git a/src/map/intif.hpp b/src/map/intif.hpp
index 2e3d3fe..44bd8eb 100644
--- a/src/map/intif.hpp
+++ b/src/map/intif.hpp
@@ -31,7 +31,7 @@
# include "../mmo/fwd.hpp"
-int intif_parse(Session *);
+RecvResult intif_parse(Session *, uint16_t packet_id);
void intif_GMmessage(XString mes);
diff --git a/src/map/pc.cpp b/src/map/pc.cpp
index 33cb57f..e3a672e 100644
--- a/src/map/pc.cpp
+++ b/src/map/pc.cpp
@@ -40,10 +40,11 @@
#include "../io/read.hpp"
#include "../net/timer.hpp"
-#include "../net/vomit.hpp"
#include "../mmo/utils.hpp"
+#include "../proto2/char-map.hpp"
+
#include "atcommand.hpp"
#include "battle.hpp"
#include "chrif.hpp"
@@ -2852,7 +2853,7 @@ int pc_attack(dumb_ptr<map_session_data> sd, BlockId target_id, int type)
if (bl->bl_type == BL::NPC)
{ // monster npcs [Valaris]
- npc_click(sd, wrap<BlockId>(RFIFOL(sd->sess, 2)));
+ npc_click(sd, target_id);
return 0;
}
@@ -5176,15 +5177,14 @@ void pc_autosave(TimerData *, tick_t)
).detach();
}
-int pc_read_gm_account(Session *s)
+int pc_read_gm_account(Session *, const std::vector<Packet_Repeat<0x2b15>>& repeat)
{
gm_accountm.clear();
- // (RFIFOW(fd, 2) - 4) / 5
- for (int i = 4; i < RFIFOW(s, 2); i += 5)
+ for (const auto& i : repeat)
{
- AccountId account_id = wrap<AccountId>(RFIFOL(s, i));
- GmLevel level = GmLevel::from(static_cast<uint32_t>(RFIFOB(s, i + 4)));
+ AccountId account_id = i.account_id;
+ GmLevel level = i.gm_level;
gm_accountm[account_id] = level;
}
return gm_accountm.size();
diff --git a/src/map/pc.hpp b/src/map/pc.hpp
index 10c11cf..53e5c1d 100644
--- a/src/map/pc.hpp
+++ b/src/map/pc.hpp
@@ -31,6 +31,8 @@
# include "../mmo/utils.hpp"
+# include "../proto2/fwd.hpp"
+
# include "clif.t.hpp"
# include "map.hpp"
@@ -172,7 +174,7 @@ void pc_set_gm_level(AccountId account_id, GmLevel level);
void pc_setstand(dumb_ptr<map_session_data> sd);
void pc_cleanup(dumb_ptr<map_session_data> sd); // [Fate] Clean up after a logged-out PC
-int pc_read_gm_account(Session *);
+int pc_read_gm_account(Session *, const std::vector<Packet_Repeat<0x2b15>>&);
int pc_setinvincibletimer(dumb_ptr<map_session_data> sd, interval_t);
int pc_delinvincibletimer(dumb_ptr<map_session_data> sd);
int pc_logout(dumb_ptr<map_session_data> sd); // [fate] Player logs out
diff --git a/src/net/packets.hpp b/src/net/packets.hpp
index 54167e8..4bb412f 100644
--- a/src/net/packets.hpp
+++ b/src/net/packets.hpp
@@ -188,7 +188,7 @@ RecvResult net_recv_opacket(Session *s, NetPacket_Head<id>& head, bool *has_opt,
if (nat.magic_packet_length < sizeof(NetPacket_Head<id>))
return RecvResult::Error;
size_t bytes_repeat = nat.magic_packet_length - sizeof(NetPacket_Head<id>);
- if (bytes_repeat % sizeof(NetPacket_Repeat<id>))
+ if (bytes_repeat % sizeof(NetPacket_Option<id>))
return RecvResult::Error;
size_t has_opt_pls = bytes_repeat / sizeof(NetPacket_Option<id>);
if (has_opt_pls > 1)