diff options
author | Ben Longbons <b.r.longbons@gmail.com> | 2014-06-10 15:31:24 -0700 |
---|---|---|
committer | Ben Longbons <b.r.longbons@gmail.com> | 2014-06-23 21:07:14 -0700 |
commit | 1c1752f40aac20bf9a5e56817951a013c2219bed (patch) | |
tree | d4ca348dd88ec08cf4edbdd37b72396b75a914a4 /src/map | |
parent | 8ce2f240dba5bdd0ca47ac25f16f140d8d1744fc (diff) | |
download | tmwa-1c1752f40aac20bf9a5e56817951a013c2219bed.tar.gz tmwa-1c1752f40aac20bf9a5e56817951a013c2219bed.tar.bz2 tmwa-1c1752f40aac20bf9a5e56817951a013c2219bed.tar.xz tmwa-1c1752f40aac20bf9a5e56817951a013c2219bed.zip |
Generate the map server protocol
Sigh, map server will have no smart filters yet
Diffstat (limited to 'src/map')
-rw-r--r-- | src/map/battle.hpp | 2 | ||||
-rw-r--r-- | src/map/battle.t.hpp | 10 | ||||
-rw-r--r-- | src/map/clif.cpp | 3010 | ||||
-rw-r--r-- | src/map/clif.t.hpp | 545 | ||||
-rw-r--r-- | src/map/magic-interpreter.t.hpp | 32 | ||||
-rw-r--r-- | src/map/magic-stmt.cpp | 14 | ||||
-rw-r--r-- | src/map/map.hpp | 9 | ||||
-rw-r--r-- | src/map/map.t.hpp | 396 | ||||
-rw-r--r-- | src/map/npc.cpp | 60 | ||||
-rw-r--r-- | src/map/npc.hpp | 15 | ||||
-rw-r--r-- | src/map/path.cpp | 2 | ||||
-rw-r--r-- | src/map/pc.cpp | 6 | ||||
-rw-r--r-- | src/map/pc.hpp | 2 | ||||
-rw-r--r-- | src/map/pc.t.hpp | 13 | ||||
-rw-r--r-- | src/map/script.cpp | 2 | ||||
-rw-r--r-- | src/map/script.hpp | 3 |
16 files changed, 2208 insertions, 1913 deletions
diff --git a/src/map/battle.hpp b/src/map/battle.hpp index b448073..5bf7dde 100644 --- a/src/map/battle.hpp +++ b/src/map/battle.hpp @@ -31,7 +31,7 @@ # include "../net/timer.t.hpp" -# include "magic-interpreter.t.hpp" +# include "clif.t.hpp" # include "map.t.hpp" # include "skill.t.hpp" diff --git a/src/map/battle.t.hpp b/src/map/battle.t.hpp index d0d3389..09e2512 100644 --- a/src/map/battle.t.hpp +++ b/src/map/battle.t.hpp @@ -240,14 +240,4 @@ earray<Races, Race, Race::COUNT> race_shift //= Races::other, }}; -enum class DamageType : uint8_t -{ - NORMAL = 0x00, - TAKEITEM = 0x01, - RETURNED = 0x04, - DOUBLED = 0x08, - CRITICAL = 0x0a, - FLEE2 = 0x0b, -}; - #endif // TMWA_MAP_BATTLE_T_HPP diff --git a/src/map/clif.cpp b/src/map/clif.cpp index 218c00b..3548324 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -39,9 +39,13 @@ #include "../io/write.hpp" #include "../net/ip.hpp" +#include "../net/packets.hpp" #include "../net/socket.hpp" #include "../net/timer.hpp" -#include "../net/vomit.hpp" + +#include "../proto2/any-user.hpp" +#include "../proto2/char-map.hpp" +#include "../proto2/map-user.hpp" #include "../mmo/md5more.hpp" #include "../mmo/utils.hpp" @@ -65,8 +69,6 @@ #include "../poison.hpp" -#define DUMP_UNKNOWN_PACKET 1 - constexpr int EMOTE_IGNORED = 0x0e; // functions list. Rate is how many milliseconds are required between @@ -74,20 +76,20 @@ constexpr int EMOTE_IGNORED = 0x0e; // map.h must be the same length as this table. rate 0 is default // rate -1 is unlimited -typedef void (*clif_func)(Session *s, dumb_ptr<map_session_data> sd); +typedef RecvResult (*clif_func)(Session *s, dumb_ptr<map_session_data> sd); struct func_table { interval_t rate; - int len; + uint16_t len_unused; clif_func func; // ctor exists because interval_t must be explicit - func_table(int r, int l, clif_func f) - : rate(r), len(l), func(f) + func_table(int r, uint16_t l, clif_func f) + : rate(r), len_unused(l), func(f) {} }; -constexpr int VAR = -1; +constexpr uint16_t VAR = 1; extern // not really - defined below func_table clif_parse_func_table[0x0220]; @@ -110,36 +112,6 @@ enum class SendWho SELF, }; -inline -void WBUFPOS(uint8_t *p, size_t pos, uint16_t x, uint16_t y) -{ - p += pos; - p[0] = x >> 2; - p[1] = (x << 6) | ((y >> 4) & 0x3f); - p[2] = y << 4; -} -inline -void WBUFPOS2(uint8_t *p, size_t pos, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) -{ - p += pos; - p[0] = x0 >> 2; - p[1] = (x0 << 6) | ((y0 >> 4) & 0x3f); - p[2] = (y0 << 4) | ((x1 >> 6) & 0x0f); - p[3] = (x1 << 2) | ((y1 >> 8) & 0x03); - p[4] = y1; -} - -inline -void WFIFOPOS(Session *s, size_t pos, uint16_t x, uint16_t y) -{ - WBUFPOS(static_cast<uint8_t *>(WFIFOP(s, pos)), 0, x, y); -} -inline -void WFIFOPOS2(Session *s, size_t pos, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) -{ - WBUFPOS2(static_cast<uint8_t *>(WFIFOP(s, pos)), 0, x0, y0, x1, y1); -} - static IP4Address map_ip; static @@ -268,14 +240,14 @@ enum class ChatType }; static -AString clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type); +AString clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type, XString buf); /*========================================== * clif_sendでSendWho::AREA*指定時用 *------------------------------------------ */ static -void clif_send_sub(dumb_ptr<block_list> bl, const unsigned char *buf, int len, +void clif_send_sub(dumb_ptr<block_list> bl, const Buffer& buf, dumb_ptr<block_list> src_bl, SendWho type) { nullpo_retv(bl); @@ -305,11 +277,8 @@ void clif_send_sub(dumb_ptr<block_list> bl, const unsigned char *buf, int len, if (sd->sess != NULL) { { - if (clif_parse_func_table[RBUFW(buf, 0)].len) { - // packet must exist - WFIFO_BUF_CLONE(sd->sess, buf, len); - WFIFOSET(sd->sess, len); + send_buffer(sd->sess, buf); } } } @@ -320,7 +289,7 @@ void clif_send_sub(dumb_ptr<block_list> bl, const unsigned char *buf, int len, *------------------------------------------ */ static -int clif_send(const uint8_t *buf, int len, dumb_ptr<block_list> bl, SendWho type) +int clif_send(const Buffer& buf, dumb_ptr<block_list> bl, SendWho type) { PartyPair p; int x0 = 0, x1 = 0, y0 = 0, y1 = 0; @@ -363,11 +332,8 @@ int clif_send(const uint8_t *buf, int len, dumb_ptr<block_list> bl, SendWho type dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get())); if (sd && sd->state.auth) { - if (clif_parse_func_table[RBUFW(buf, 0)].len) { - // packet must exist - WFIFO_BUF_CLONE(s, buf, len); - WFIFOSET(s, len); + send_buffer(s, buf); } } } @@ -381,25 +347,22 @@ int clif_send(const uint8_t *buf, int len, dumb_ptr<block_list> bl, SendWho type dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get())); if (sd && sd->state.auth && sd->bl_m == bl->bl_m) { - if (clif_parse_func_table[RBUFW(buf, 0)].len) { - // packet must exist - WFIFO_BUF_CLONE(s, buf, len); - WFIFOSET(s, len); + send_buffer(s, buf); } } } break; case SendWho::AREA: case SendWho::AREA_WOS: - map_foreachinarea(std::bind(clif_send_sub, ph::_1, buf, len, bl, type), + map_foreachinarea(std::bind(clif_send_sub, ph::_1, buf, bl, type), bl->bl_m, bl->bl_x - AREA_SIZE, bl->bl_y - AREA_SIZE, bl->bl_x + AREA_SIZE, bl->bl_y + AREA_SIZE, BL::PC); break; case SendWho::AREA_CHAT_WOC: - map_foreachinarea(std::bind(clif_send_sub, ph::_1, buf, len, bl, SendWho::AREA_CHAT_WOC), + map_foreachinarea(std::bind(clif_send_sub, ph::_1, buf, bl, SendWho::AREA_CHAT_WOC), bl->bl_m, bl->bl_x - (AREA_SIZE), bl->bl_y - (AREA_SIZE), bl->bl_x + (AREA_SIZE), bl->bl_y + (AREA_SIZE), @@ -447,11 +410,8 @@ int clif_send(const uint8_t *buf, int len, dumb_ptr<block_list> bl, SendWho type (sd->bl_x < x0 || sd->bl_y < y0 || sd->bl_x > x1 || sd->bl_y > y1)) continue; - if (clif_parse_func_table[RBUFW(buf, 0)].len) { - // packet must exist - WFIFO_BUF_CLONE(sd->sess, buf, len); - WFIFOSET(sd->sess, len); + send_buffer(sd->sess, buf); } } } @@ -465,11 +425,8 @@ int clif_send(const uint8_t *buf, int len, dumb_ptr<block_list> bl, SendWho type { if (sd->partyspy == p.party_id) { - if (clif_parse_func_table[RBUFW(buf, 0)].len) { - // packet must exist - WFIFO_BUF_CLONE(sd->sess, buf, len); - WFIFOSET(sd->sess, len); + send_buffer(sd->sess, buf); } } } @@ -479,11 +436,9 @@ int clif_send(const uint8_t *buf, int len, dumb_ptr<block_list> bl, SendWho type case SendWho::SELF: { dumb_ptr<map_session_data> sd = bl->is_player(); - if (clif_parse_func_table[RBUFW(buf, 0)].len) + { - // packet must exist - WFIFO_BUF_CLONE(sd->sess, buf, len); - WFIFOSET(sd->sess, len); + send_buffer(sd->sess, buf); } } break; @@ -516,12 +471,12 @@ int clif_authok(dumb_ptr<map_session_data> sd) Session *s = sd->sess; - WFIFOW(s, 0) = 0x73; - WFIFOL(s, 2) = gettick().time_since_epoch().count(); - WFIFOPOS(s, 6, sd->bl_x, sd->bl_y); - WFIFOB(s, 9) = 5; - WFIFOB(s, 10) = 5; - WFIFOSET(s, clif_parse_func_table[0x73].len); + Packet_Fixed<0x0073> fixed_73; + fixed_73.tick = gettick(); + fixed_73.pos = Position1{static_cast<uint16_t>(sd->bl_x), static_cast<uint16_t>(sd->bl_y), DIR::S}; + fixed_73.five1 = 5; + fixed_73.five2 = 5; + send_fpacket<0x0073, 11>(s, fixed_73); return 0; } @@ -535,9 +490,9 @@ int clif_authfail_fd(Session *s, int type) if (!s) return 0; - WFIFOW(s, 0) = 0x81; - WFIFOL(s, 2) = type; - WFIFOSET(s, clif_parse_func_table[0x81].len); + Packet_Fixed<0x0081> fixed_81; + fixed_81.error_code = type; + send_fpacket<0x0081, 3>(s, fixed_81); clif_setwaitclose(s); @@ -559,9 +514,9 @@ int clif_charselectok(BlockId id) return 1; Session *s = sd->sess; - WFIFOW(s, 0) = 0xb3; - WFIFOB(s, 2) = 1; - WFIFOSET(s, clif_parse_func_table[0xb3].len); + Packet_Fixed<0x00b3> fixed_b3; + fixed_b3.one = 1; + send_fpacket<0x00b3, 3>(s, fixed_b3); return 0; } @@ -571,22 +526,21 @@ int clif_charselectok(BlockId id) *------------------------------------------ */ static -int clif_set009e(dumb_ptr<flooritem_data> fitem, uint8_t *buf) +void clif_set009e(dumb_ptr<flooritem_data> fitem, Buffer& buf) { - nullpo_ret(fitem); + nullpo_retv(fitem); - //009e <ID>.l <name ID>.w <identify flag>.B <X>.w <Y>.w <subX>.B <subY>.B <amount>.w - WBUFW(buf, 0) = 0x9e; - WBUFL(buf, 2) = unwrap<BlockId>(fitem->bl_id); - WBUFW(buf, 6) = unwrap<ItemNameId>(fitem->item_data.nameid); - WBUFB(buf, 8) = 1; //identify; - WBUFW(buf, 9) = fitem->bl_x; - WBUFW(buf, 11) = fitem->bl_y; - WBUFB(buf, 13) = fitem->subx; - WBUFB(buf, 14) = fitem->suby; - WBUFW(buf, 15) = fitem->item_data.amount; + Packet_Fixed<0x009e> fixed_9e; + fixed_9e.block_id = fitem->bl_id; + fixed_9e.name_id = fitem->item_data.nameid; + fixed_9e.identify = 1; + fixed_9e.x = fitem->bl_x; + fixed_9e.y = fitem->bl_y; + fixed_9e.subx = fitem->subx; + fixed_9e.suby = fitem->suby; + fixed_9e.amount = fitem->item_data.amount; - return clif_parse_func_table[0x9e].len; + buf = create_fpacket<0x009e, 17>(fixed_9e); } /*========================================== @@ -595,14 +549,14 @@ int clif_set009e(dumb_ptr<flooritem_data> fitem, uint8_t *buf) */ int clif_dropflooritem(dumb_ptr<flooritem_data> fitem) { - uint8_t buf[64]; - nullpo_ret(fitem); if (!fitem->item_data.nameid) return 0; + + Buffer buf; clif_set009e(fitem, buf); - clif_send(buf, clif_parse_func_table[0x9e].len, fitem, SendWho::AREA); + clif_send(buf, fitem, SendWho::AREA); return 0; } @@ -613,21 +567,19 @@ int clif_dropflooritem(dumb_ptr<flooritem_data> fitem) */ int clif_clearflooritem(dumb_ptr<flooritem_data> fitem, Session *s) { - unsigned char buf[16]; - nullpo_ret(fitem); - WBUFW(buf, 0) = 0xa1; - WBUFL(buf, 2) = unwrap<BlockId>(fitem->bl_id); + Packet_Fixed<0x00a1> fixed_a1; + fixed_a1.block_id = fitem->bl_id; if (!s) { - clif_send(buf, clif_parse_func_table[0xa1].len, fitem, SendWho::AREA); + Buffer buf = create_fpacket<0x00a1, 6>(fixed_a1); + clif_send(buf, fitem, SendWho::AREA); } else { - WFIFO_BUF_CLONE(s, buf, 6); - WFIFOSET(s, clif_parse_func_table[0xa1].len); + send_fpacket<0x00a1, 6>(s, fixed_a1); } return 0; @@ -639,21 +591,21 @@ int clif_clearflooritem(dumb_ptr<flooritem_data> fitem, Session *s) */ int clif_clearchar(dumb_ptr<block_list> bl, BeingRemoveWhy type) { - unsigned char buf[16]; - nullpo_ret(bl); - WBUFW(buf, 0) = 0x80; - WBUFL(buf, 2) = unwrap<BlockId>(bl->bl_id); + Packet_Fixed<0x0080> fixed_80; + fixed_80.block_id = bl->bl_id; + Buffer buf = create_fpacket<0x0080, 7>(fixed_80); + if (type == BeingRemoveWhy::DISGUISE) { - WBUFB(buf, 6) = static_cast<uint8_t>(BeingRemoveWhy::GONE); - clif_send(buf, clif_parse_func_table[0x80].len, bl, SendWho::AREA); + fixed_80.type = BeingRemoveWhy::GONE; + clif_send(buf, bl, SendWho::AREA); } else { - WBUFB(buf, 6) = static_cast<uint8_t>(type); - clif_send(buf, clif_parse_func_table[0x80].len, bl, + fixed_80.type = type; + clif_send(buf, bl, type == BeingRemoveWhy::DEAD ? SendWho::AREA : SendWho::AREA_WOS); } @@ -697,10 +649,10 @@ int clif_clearchar_delay(tick_t tick, */ void clif_clearchar_id(BlockId id, BeingRemoveWhy type, Session *s) { - WFIFOW(s, 0) = 0x80; - WFIFOL(s, 2) = unwrap<BlockId>(id); - WFIFOB(s, 6) = static_cast<uint8_t>(type); - WFIFOSET(s, clif_parse_func_table[0x80].len); + Packet_Fixed<0x0080> fixed_80; + fixed_80.block_id = id; + fixed_80.type = type; + send_fpacket<0x0080, 7>(s, fixed_80); } /*========================================== @@ -708,59 +660,111 @@ void clif_clearchar_id(BlockId id, BeingRemoveWhy type, Session *s) *------------------------------------------ */ static -int clif_set0078(dumb_ptr<map_session_data> sd, unsigned char *buf) +void clif_set0078_main_1d8(dumb_ptr<map_session_data> sd, Buffer& buf) { - nullpo_ret(sd); + nullpo_retv(sd); - WBUFW(buf, 0) = 0x1d8; - WBUFL(buf, 2) = unwrap<BlockId>(sd->bl_id); - WBUFW(buf, 6) = static_cast<uint16_t>(sd->speed.count()); - WBUFW(buf, 8) = static_cast<uint16_t>(sd->opt1); - WBUFW(buf, 10) = static_cast<uint16_t>(sd->opt2); - WBUFW(buf, 12) = static_cast<uint16_t>(sd->status.option); - WBUFW(buf, 14) = unwrap<Species>(sd->status.species); - WBUFW(buf, 16) = sd->status.hair; + Packet_Fixed<0x01d8> fixed_1d8; + fixed_1d8.block_id = sd->bl_id; + fixed_1d8.speed = sd->speed; + fixed_1d8.opt1 = sd->opt1; + fixed_1d8.opt2 = sd->opt2; + fixed_1d8.option = sd->status.option; + fixed_1d8.species = sd->status.species; + fixed_1d8.hair_style = sd->status.hair; int widx = sd->equip_index_maybe[EQUIP::WEAPON]; int sidx = sd->equip_index_maybe[EQUIP::SHIELD]; if (sd->attack_spell_override) - WBUFW(buf, 18) = sd->attack_spell_look_override; + fixed_1d8.weapon = sd->attack_spell_look_override; else { if (widx >= 0 && sd->inventory_data[widx]) { - WBUFW(buf, 18) = unwrap<ItemNameId>(sd->status.inventory[widx].nameid); + fixed_1d8.weapon = sd->status.inventory[widx].nameid; } else - WBUFW(buf, 18) = unwrap<ItemNameId>(ItemNameId()); + fixed_1d8.weapon = ItemNameId(); } if (sidx >= 0 && sidx != widx && sd->inventory_data[sidx]) { - WBUFW(buf, 20) = unwrap<ItemNameId>(sd->status.inventory[sidx].nameid); + fixed_1d8.shield = sd->status.inventory[sidx].nameid; } else - WBUFW(buf, 20) = unwrap<ItemNameId>(ItemNameId()); - WBUFW(buf, 22) = unwrap<ItemNameId>(sd->status.head_bottom); - WBUFW(buf, 24) = unwrap<ItemNameId>(sd->status.head_top); - WBUFW(buf, 26) = unwrap<ItemNameId>(sd->status.head_mid); - WBUFW(buf, 28) = sd->status.hair_color; - WBUFW(buf, 30) = sd->status.clothes_color; - WBUFW(buf, 32) = static_cast<uint8_t>(sd->head_dir); - WBUFL(buf, 34) = 0 /*guild_id*/; - WBUFW(buf, 38) = 0 /*guild_emblem_id*/; - WBUFW(buf, 40) = sd->status.manner; - WBUFW(buf, 42) = static_cast<uint16_t>(sd->opt3); - WBUFB(buf, 44) = sd->status.karma; - WBUFB(buf, 45) = static_cast<uint8_t>(sd->sex); - WBUFPOS(buf, 46, sd->bl_x, sd->bl_y); - // work around ICE in gcc 4.6 - uint8_t dir = static_cast<uint8_t>(sd->dir); - WBUFB(buf, 48) |= dir; - WBUFW(buf, 49) = pc_isGM(sd).get_public_word(); - WBUFB(buf, 51) = sd->state.dead_sit; - WBUFW(buf, 52) = 0; - - return clif_parse_func_table[0x1d8].len; + fixed_1d8.shield = ItemNameId(); + fixed_1d8.head_bottom = sd->status.head_bottom; + fixed_1d8.head_top = sd->status.head_top; + fixed_1d8.head_mid = sd->status.head_mid; + fixed_1d8.hair_color = sd->status.hair_color; + fixed_1d8.clothes_color = sd->status.clothes_color; + fixed_1d8.head_dir = sd->head_dir; + fixed_1d8.guild_id = 0; + fixed_1d8.guild_emblem_id = 0; + fixed_1d8.manner = sd->status.manner; + fixed_1d8.opt3 = sd->opt3; + fixed_1d8.karma = sd->status.karma; + fixed_1d8.sex = sd->sex; + fixed_1d8.pos.x = sd->bl_x; + fixed_1d8.pos.y = sd->bl_y; + fixed_1d8.pos.dir = sd->dir; + fixed_1d8.gm_bits = pc_isGM(sd).get_public_word(); + fixed_1d8.dead_sit = sd->state.dead_sit; + fixed_1d8.unused = 0; + + buf = create_fpacket<0x01d8, 54>(fixed_1d8); +} +static +void clif_set0078_alt_1d9(dumb_ptr<map_session_data> sd, Buffer& buf) +{ + nullpo_retv(sd); + + Packet_Fixed<0x01d9> fixed_1d8; // LIES + fixed_1d8.block_id = sd->bl_id; + fixed_1d8.speed = sd->speed; + fixed_1d8.opt1 = sd->opt1; + fixed_1d8.opt2 = sd->opt2; + fixed_1d8.option = sd->status.option; + fixed_1d8.species = sd->status.species; + fixed_1d8.hair_style = sd->status.hair; + + int widx = sd->equip_index_maybe[EQUIP::WEAPON]; + int sidx = sd->equip_index_maybe[EQUIP::SHIELD]; + if (sd->attack_spell_override) + fixed_1d8.weapon = sd->attack_spell_look_override; + else + { + if (widx >= 0 && sd->inventory_data[widx]) + { + fixed_1d8.weapon = sd->status.inventory[widx].nameid; + } + else + fixed_1d8.weapon = ItemNameId(); + } + if (sidx >= 0 && sidx != widx && sd->inventory_data[sidx]) + { + fixed_1d8.shield = sd->status.inventory[sidx].nameid; + } + else + fixed_1d8.shield = ItemNameId(); + fixed_1d8.head_bottom = sd->status.head_bottom; + fixed_1d8.head_top = sd->status.head_top; + fixed_1d8.head_mid = sd->status.head_mid; + fixed_1d8.hair_color = sd->status.hair_color; + fixed_1d8.clothes_color = sd->status.clothes_color; + fixed_1d8.head_dir = sd->head_dir; + fixed_1d8.guild_id = 0; + fixed_1d8.guild_emblem_id = 0; + fixed_1d8.manner = sd->status.manner; + fixed_1d8.opt3 = sd->opt3; + fixed_1d8.karma = sd->status.karma; + fixed_1d8.sex = sd->sex; + fixed_1d8.pos.x = sd->bl_x; + fixed_1d8.pos.y = sd->bl_y; + fixed_1d8.pos.dir = sd->dir; + fixed_1d8.gm_bits = pc_isGM(sd).get_public_word(); + fixed_1d8.unused = 0; + + buf = create_fpacket<0x01d9, 53>(fixed_1d8); } /*========================================== @@ -768,51 +772,54 @@ int clif_set0078(dumb_ptr<map_session_data> sd, unsigned char *buf) *------------------------------------------ */ static -int clif_set007b(dumb_ptr<map_session_data> sd, unsigned char *buf) +void clif_set007b(dumb_ptr<map_session_data> sd, Buffer& buf) { - nullpo_ret(sd); + nullpo_retv(sd); - WBUFW(buf, 0) = 0x1da; - WBUFL(buf, 2) = unwrap<BlockId>(sd->bl_id); - WBUFW(buf, 6) = static_cast<uint16_t>(sd->speed.count()); - WBUFW(buf, 8) = static_cast<uint16_t>(sd->opt1); - WBUFW(buf, 10) = static_cast<uint16_t>(sd->opt2); - WBUFW(buf, 12) = static_cast<uint16_t>(sd->status.option); - WBUFW(buf, 14) = unwrap<Species>(sd->status.species); - WBUFW(buf, 16) = sd->status.hair; + Packet_Fixed<0x01da> fixed_1da; + fixed_1da.block_id = sd->bl_id; + fixed_1da.speed = sd->speed; + fixed_1da.opt1 = sd->opt1; + fixed_1da.opt2 = sd->opt2; + fixed_1da.option = sd->status.option; + fixed_1da.species = sd->status.species; + fixed_1da.hair_style = sd->status.hair; int widx = sd->equip_index_maybe[EQUIP::WEAPON]; int sidx = sd->equip_index_maybe[EQUIP::SHIELD]; if (widx >= 0 && sd->inventory_data[widx]) { - WBUFW(buf, 18) = unwrap<ItemNameId>(sd->status.inventory[widx].nameid); + fixed_1da.weapon = sd->status.inventory[widx].nameid; } else - WBUFW(buf, 18) = unwrap<ItemNameId>(ItemNameId()); + fixed_1da.weapon = ItemNameId(); if (sidx >= 0 && sidx != widx && sd->inventory_data[sidx]) { - WBUFW(buf, 20) = unwrap<ItemNameId>(sd->status.inventory[sidx].nameid); + fixed_1da.shield = sd->status.inventory[sidx].nameid; } else - WBUFW(buf, 20) = unwrap<ItemNameId>(ItemNameId()); - WBUFW(buf, 22) = unwrap<ItemNameId>(sd->status.head_bottom); - WBUFL(buf, 24) = gettick().time_since_epoch().count(); - WBUFW(buf, 28) = unwrap<ItemNameId>(sd->status.head_top); - WBUFW(buf, 30) = unwrap<ItemNameId>(sd->status.head_mid); - WBUFW(buf, 32) = sd->status.hair_color; - WBUFW(buf, 34) = sd->status.clothes_color; - WBUFW(buf, 36) = static_cast<uint8_t>(sd->head_dir); - WBUFL(buf, 38) = 0/*guild_id*/; - WBUFW(buf, 42) = 0/*guild_emblem_id*/; - WBUFW(buf, 44) = sd->status.manner; - WBUFW(buf, 46) = static_cast<uint16_t>(sd->opt3); - WBUFB(buf, 48) = sd->status.karma; - WBUFB(buf, 49) = static_cast<uint8_t>(sd->sex); - WBUFPOS2(buf, 50, sd->bl_x, sd->bl_y, sd->to_x, sd->to_y); - WBUFW(buf, 55) = pc_isGM(sd).get_public_word(); - WBUFB(buf, 57) = 5; - WBUFW(buf, 58) = 0; - - return clif_parse_func_table[0x1da].len; + fixed_1da.shield = ItemNameId(); + fixed_1da.head_bottom = sd->status.head_bottom; + fixed_1da.tick = gettick(); + fixed_1da.head_top = sd->status.head_top; + fixed_1da.head_mid = sd->status.head_mid; + fixed_1da.hair_color = sd->status.hair_color; + fixed_1da.clothes_color = sd->status.clothes_color; + fixed_1da.head_dir = sd->head_dir; + fixed_1da.guild_id = 0; + fixed_1da.guild_emblem_id = 0; + fixed_1da.manner = sd->status.manner; + fixed_1da.opt3 = sd->opt3; + fixed_1da.karma = sd->status.karma; + fixed_1da.sex = sd->sex; + fixed_1da.pos2.x0 = sd->bl_x; + fixed_1da.pos2.y0 = sd->bl_y; + fixed_1da.pos2.x1 = sd->to_x; + fixed_1da.pos2.y1 = sd->to_y; + fixed_1da.gm_bits = pc_isGM(sd).get_public_word(); + fixed_1da.five = 5; + fixed_1da.unused = 0; + + buf = create_fpacket<0x01da, 60>(fixed_1da); } /*========================================== @@ -820,30 +827,27 @@ int clif_set007b(dumb_ptr<map_session_data> sd, unsigned char *buf) *------------------------------------------ */ static -int clif_mob0078(dumb_ptr<mob_data> md, unsigned char *buf) +void clif_mob0078(dumb_ptr<mob_data> md, Buffer& buf) { - really_memset0(buf, clif_parse_func_table[0x78].len); - - nullpo_ret(md); + nullpo_retv(md); - WBUFW(buf, 0) = 0x78; - WBUFL(buf, 2) = unwrap<BlockId>(md->bl_id); - WBUFW(buf, 6) = static_cast<uint16_t>(battle_get_speed(md).count()); - WBUFW(buf, 8) = static_cast<uint16_t>(md->opt1); - WBUFW(buf, 10) = static_cast<uint16_t>(md->opt2); - WBUFW(buf, 12) = static_cast<uint16_t>(md->option); - WBUFW(buf, 14) = unwrap<Species>(md->mob_class); + Packet_Fixed<0x0078> fixed_78; + fixed_78.block_id = md->bl_id; + fixed_78.speed = battle_get_speed(md); + fixed_78.opt1 = md->opt1; + fixed_78.opt2 = md->opt2; + fixed_78.option = md->option; + fixed_78.species = md->mob_class; // snip: stuff do do with disguise as a PC - WBUFPOS(buf, 46, md->bl_x, md->bl_y); - // work around ICE in gcc 4.6 - uint8_t dir = static_cast<uint8_t>(md->dir); - WBUFB(buf, 48) |= dir; - WBUFB(buf, 49) = 5; - WBUFB(buf, 50) = 5; + fixed_78.pos.x = md->bl_x; + fixed_78.pos.y = md->bl_y; + fixed_78.pos.dir = md->dir; + fixed_78.five1 = 5; + fixed_78.five2 = 5; int level = battle_get_lv(md); - WBUFW(buf, 52) = (level > battle_config.max_lv) ? battle_config.max_lv : level; + fixed_78.level = (level > battle_config.max_lv) ? battle_config.max_lv : level; - return clif_parse_func_table[0x78].len; + buf = create_fpacket<0x0078, 54>(fixed_78); } /*========================================== @@ -851,29 +855,30 @@ int clif_mob0078(dumb_ptr<mob_data> md, unsigned char *buf) *------------------------------------------ */ static -int clif_mob007b(dumb_ptr<mob_data> md, unsigned char *buf) +void clif_mob007b(dumb_ptr<mob_data> md, Buffer& buf) { - really_memset0(buf, clif_parse_func_table[0x7b].len); - - nullpo_ret(md); + nullpo_retv(md); - WBUFW(buf, 0) = 0x7b; - WBUFL(buf, 2) = unwrap<BlockId>(md->bl_id); - WBUFW(buf, 6) = static_cast<uint16_t>(battle_get_speed(md).count()); - WBUFW(buf, 8) = static_cast<uint16_t>(md->opt1); - WBUFW(buf, 10) = static_cast<uint16_t>(md->opt2); - WBUFW(buf, 12) = static_cast<uint16_t>(md->option); - WBUFW(buf, 14) = unwrap<Species>(md->mob_class); + Packet_Fixed<0x007b> fixed_7b; + fixed_7b.block_id = md->bl_id; + fixed_7b.speed = battle_get_speed(md); + fixed_7b.opt1 = md->opt1; + fixed_7b.opt2 = md->opt2; + fixed_7b.option = md->option; + fixed_7b.mob_class = md->mob_class; // snip: stuff for monsters disguised as PCs - WBUFL(buf, 22) = gettick().time_since_epoch().count(); - - WBUFPOS2(buf, 50, md->bl_x, md->bl_y, md->to_x, md->to_y); - WBUFB(buf, 56) = 5; - WBUFB(buf, 57) = 5; + fixed_7b.tick_and_maybe_part_of_guild_emblem = gettick(); + + fixed_7b.pos2.x0 = md->bl_x; + fixed_7b.pos2.y0 = md->bl_y; + fixed_7b.pos2.x1 = md->to_x; + fixed_7b.pos2.y1 = md->to_y; + fixed_7b.five1 = 5; + fixed_7b.five2 = 5; int level = battle_get_lv(md); - WBUFW(buf, 58) = (level > battle_config.max_lv) ? battle_config.max_lv : level; + fixed_7b.level = (level > battle_config.max_lv) ? battle_config.max_lv : level; - return clif_parse_func_table[0x7b].len; + buf = create_fpacket<0x007b, 60>(fixed_7b); } /*========================================== @@ -881,24 +886,23 @@ int clif_mob007b(dumb_ptr<mob_data> md, unsigned char *buf) *------------------------------------------ */ static -int clif_npc0078(dumb_ptr<npc_data> nd, unsigned char *buf) +void clif_npc0078(dumb_ptr<npc_data> nd, Buffer& buf) { - nullpo_ret(nd); - - really_memset0(buf, clif_parse_func_table[0x78].len); + nullpo_retv(nd); - WBUFW(buf, 0) = 0x78; - WBUFL(buf, 2) = unwrap<BlockId>(nd->bl_id); - WBUFW(buf, 6) = static_cast<uint16_t>(nd->speed.count()); - WBUFW(buf, 14) = nd->npc_class; - WBUFPOS(buf, 46, nd->bl_x, nd->bl_y); - // work around ICE in gcc 4.6 - uint8_t dir = static_cast<uint8_t>(nd->dir); - WBUFB(buf, 48) |= dir; - WBUFB(buf, 49) = 5; - WBUFB(buf, 50) = 5; + Packet_Fixed<0x0078> fixed_78; + fixed_78.block_id = nd->bl_id; + fixed_78.speed = nd->speed; + fixed_78.species = nd->npc_class; + fixed_78.pos.x = nd->bl_x; + fixed_78.pos.y = nd->bl_y; + fixed_78.pos.dir = nd->dir; + fixed_78.five1 = 5; + fixed_78.five2 = 5; + fixed_78.zero = 0; + fixed_78.level = 0; - return clif_parse_func_table[0x78].len; + buf = create_fpacket<0x0078, 54>(fixed_78); } /* These indices are derived from equip_pos in pc.c and some guesswork */ @@ -927,15 +931,12 @@ earray<EQUIP, LOOK, LOOK::COUNT> equip_points //= */ int clif_spawnpc(dumb_ptr<map_session_data> sd) { - unsigned char buf[128]; - nullpo_ret(sd); - clif_set0078(sd, buf); + Buffer buf; + clif_set0078_alt_1d9(sd, buf); - WBUFW(buf, 0) = 0x1d9; - WBUFW(buf, 51) = 0; - clif_send(buf, clif_parse_func_table[0x1d9].len, sd, SendWho::AREA_WOS); + clif_send(buf, sd, SendWho::AREA_WOS); if (sd->bl_m->flag.get(MapFlag::SNOW)) clif_specialeffect(sd, 162, 1); @@ -959,26 +960,23 @@ int clif_spawnpc(dumb_ptr<map_session_data> sd) */ int clif_spawnnpc(dumb_ptr<npc_data> nd) { - unsigned char buf[64]; - int len; - nullpo_ret(nd); - if (nd->npc_class < 0 || nd->flag & 1 || nd->npc_class == INVISIBLE_CLASS) + if (nd->npc_class == NEGATIVE_SPECIES || nd->flag & 1 || nd->npc_class == INVISIBLE_CLASS) return 0; - really_memset0(buf, clif_parse_func_table[0x7c].len); - - WBUFW(buf, 0) = 0x7c; - WBUFL(buf, 2) = unwrap<BlockId>(nd->bl_id); - WBUFW(buf, 6) = static_cast<uint16_t>(nd->speed.count()); - WBUFW(buf, 20) = nd->npc_class; - WBUFPOS(buf, 36, nd->bl_x, nd->bl_y); + Packet_Fixed<0x007c> fixed_7c; + fixed_7c.block_id = nd->bl_id; + fixed_7c.speed = nd->speed; + fixed_7c.species = nd->npc_class; + fixed_7c.pos.x = nd->bl_x; + fixed_7c.pos.y = nd->bl_y; - clif_send(buf, clif_parse_func_table[0x7c].len, nd, SendWho::AREA); + Buffer buf = create_fpacket<0x007c, 41>(fixed_7c); + clif_send(buf, nd, SendWho::AREA); - len = clif_npc0078(nd, buf); - clif_send(buf, len, nd, SendWho::AREA); + clif_npc0078(nd, buf); + clif_send(buf, nd, SendWho::AREA); return 0; } @@ -992,29 +990,34 @@ int clif_spawn_fake_npc_for_player(dumb_ptr<map_session_data> sd, BlockId fake_n if (!s) return 0; - WFIFOW(s, 0) = 0x7c; - WFIFOL(s, 2) = unwrap<BlockId>(fake_npc_id); - WFIFOW(s, 6) = 0; - WFIFOW(s, 8) = 0; - WFIFOW(s, 10) = 0; - WFIFOW(s, 12) = 0; - WFIFOW(s, 20) = 127; - WFIFOPOS(s, 36, sd->bl_x, sd->bl_y); - WFIFOSET(s, clif_parse_func_table[0x7c].len); - - WFIFOW(s, 0) = 0x78; - WFIFOL(s, 2) = unwrap<BlockId>(fake_npc_id); - WFIFOW(s, 6) = 0; - WFIFOW(s, 8) = 0; - WFIFOW(s, 10) = 0; - WFIFOW(s, 12) = 0; - WFIFOW(s, 14) = 127; // identifies as NPC - WFIFOW(s, 20) = 127; - WFIFOPOS(s, 46, sd->bl_x, sd->bl_y); - WFIFOPOS(s, 36, sd->bl_x, sd->bl_y); - WFIFOB(s, 49) = 5; - WFIFOB(s, 50) = 5; - WFIFOSET(s, clif_parse_func_table[0x78].len); + Packet_Fixed<0x007c> fixed_7c; + fixed_7c.block_id = fake_npc_id; + fixed_7c.speed = interval_t(); + fixed_7c.opt1 = Opt1::ZERO; + fixed_7c.opt2 = Opt2::ZERO; + fixed_7c.option = Option::ZERO; + fixed_7c.species = FAKE_NPC_CLASS; + fixed_7c.pos.x = sd->bl_x; + fixed_7c.pos.y = sd->bl_y; + send_fpacket<0x007c, 41>(s, fixed_7c); + + Packet_Fixed<0x0078> fixed_78; + fixed_78.block_id = fake_npc_id; + fixed_78.speed = interval_t(); + fixed_78.opt1 = Opt1::ZERO; + fixed_78.opt2 = Opt2::ZERO; + fixed_78.option = Option::ZERO; + fixed_78.species = FAKE_NPC_CLASS; + fixed_78.unused_head_bottom_or_species_again = unwrap<Species>(FAKE_NPC_CLASS); + fixed_78.pos.x = sd->bl_x; + fixed_78.pos.y = sd->bl_y; + fixed_78.unused_pos_again.x = sd->bl_x; + fixed_78.unused_pos_again.y = sd->bl_y; + fixed_78.five1 = 5; + fixed_78.five2 = 5; + fixed_78.zero = 0; + fixed_78.level = 0; + send_fpacket<0x0078, 54>(s, fixed_78); return 0; } @@ -1025,27 +1028,25 @@ int clif_spawn_fake_npc_for_player(dumb_ptr<map_session_data> sd, BlockId fake_n */ int clif_spawnmob(dumb_ptr<mob_data> md) { - unsigned char buf[64]; - int len; - nullpo_ret(md); { - really_memset0(buf, clif_parse_func_table[0x7c].len); - - WBUFW(buf, 0) = 0x7c; - WBUFL(buf, 2) = unwrap<BlockId>(md->bl_id); - WBUFW(buf, 6) = md->stats[mob_stat::SPEED]; - WBUFW(buf, 8) = static_cast<uint16_t>(md->opt1); - WBUFW(buf, 10) = static_cast<uint16_t>(md->opt2); - WBUFW(buf, 12) = static_cast<uint16_t>(md->option); - WBUFW(buf, 20) = unwrap<Species>(md->mob_class); - WBUFPOS(buf, 36, md->bl_x, md->bl_y); - clif_send(buf, clif_parse_func_table[0x7c].len, md, SendWho::AREA); + Packet_Fixed<0x007c> fixed_7c; + fixed_7c.block_id = md->bl_id; + fixed_7c.speed = interval_t(md->stats[mob_stat::SPEED]); + fixed_7c.opt1 = md->opt1; + fixed_7c.opt2 = md->opt2; + fixed_7c.option = md->option; + fixed_7c.species = md->mob_class; + fixed_7c.pos.x = md->bl_x; + fixed_7c.pos.y = md->bl_y; + Buffer buf = create_fpacket<0x007c, 41>(fixed_7c); + clif_send(buf, md, SendWho::AREA); } - len = clif_mob0078(md, buf); - clif_send(buf, len, md, SendWho::AREA); + Buffer buf; + clif_mob0078(md, buf); + clif_send(buf, md, SendWho::AREA); return 0; } @@ -1060,9 +1061,9 @@ int clif_servertick(dumb_ptr<map_session_data> sd) nullpo_ret(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0x7f; - WFIFOL(s, 2) = sd->server_tick.time_since_epoch().count(); - WFIFOSET(s, clif_parse_func_table[0x7f].len); + Packet_Fixed<0x007f> fixed_7f; + fixed_7f.tick = gettick(); + send_fpacket<0x007f, 6>(s, fixed_7f); return 0; } @@ -1076,11 +1077,14 @@ int clif_walkok(dumb_ptr<map_session_data> sd) nullpo_ret(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0x87; - WFIFOL(s, 2) = gettick().time_since_epoch().count(); - WFIFOPOS2(s, 6, sd->bl_x, sd->bl_y, sd->to_x, sd->to_y); - WFIFOB(s, 11) = 0; - WFIFOSET(s, clif_parse_func_table[0x87].len); + Packet_Fixed<0x0087> fixed_87; + fixed_87.tick = gettick(); + fixed_87.pos2.x0 = sd->bl_x; + fixed_87.pos2.y0 = sd->bl_y; + fixed_87.pos2.x1 = sd->to_x; + fixed_87.pos2.y1 = sd->to_y; + fixed_87.zero = 0; + send_fpacket<0x0087, 12>(s, fixed_87); return 0; } @@ -1091,14 +1095,12 @@ int clif_walkok(dumb_ptr<map_session_data> sd) */ int clif_movechar(dumb_ptr<map_session_data> sd) { - int len; - unsigned char buf[256]; - nullpo_ret(sd); - len = clif_set007b(sd, buf); + Buffer buf; + clif_set007b(sd, buf); - clif_send(buf, len, sd, SendWho::AREA_WOS); + clif_send(buf, sd, SendWho::AREA_WOS); if (battle_config.save_clothcolor == 1 && sd->status.clothes_color > 0) clif_changelook(sd, LOOK::CLOTHES_COLOR, @@ -1150,11 +1152,11 @@ void clif_changemap(dumb_ptr<map_session_data> sd, MapName mapname, int x, int y Session *s = sd->sess; - WFIFOW(s, 0) = 0x91; - WFIFO_STRING(s, 2, mapname, 16); - WFIFOW(s, 18) = x; - WFIFOW(s, 20) = y; - WFIFOSET(s, clif_parse_func_table[0x91].len); + Packet_Fixed<0x0091> fixed_91; + fixed_91.map_name = mapname; + fixed_91.x = x; + fixed_91.y = y; + send_fpacket<0x0091, 22>(s, fixed_91); } /*========================================== @@ -1167,13 +1169,13 @@ void clif_changemapserver(dumb_ptr<map_session_data> sd, nullpo_retv(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0x92; - WFIFO_STRING(s, 2, mapname, 16); - WFIFOW(s, 18) = x; - WFIFOW(s, 20) = y; - WFIFOIP(s, 22) = ip; - WFIFOW(s, 26) = port; - WFIFOSET(s, clif_parse_func_table[0x92].len); + Packet_Fixed<0x0092> fixed_92; + fixed_92.map_name = mapname; + fixed_92.x = x; + fixed_92.y = y; + fixed_92.ip = ip; + fixed_92.port = port; + send_fpacket<0x0092, 28>(s, fixed_92); } /*========================================== @@ -1182,16 +1184,15 @@ void clif_changemapserver(dumb_ptr<map_session_data> sd, */ void clif_fixpos(dumb_ptr<block_list> bl) { - uint8_t buf[16]; - nullpo_retv(bl); - WBUFW(buf, 0) = 0x88; - WBUFL(buf, 2) = unwrap<BlockId>(bl->bl_id); - WBUFW(buf, 6) = bl->bl_x; - WBUFW(buf, 8) = bl->bl_y; + Packet_Fixed<0x0088> fixed_88; + fixed_88.block_id = bl->bl_id; + fixed_88.x = bl->bl_x; + fixed_88.y = bl->bl_y; - clif_send(buf, clif_parse_func_table[0x88].len, bl, SendWho::AREA); + Buffer buf = create_fpacket<0x0088, 10>(fixed_88); + clif_send(buf, bl, SendWho::AREA); } /*========================================== @@ -1203,9 +1204,9 @@ int clif_npcbuysell(dumb_ptr<map_session_data> sd, BlockId id) nullpo_ret(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xc4; - WFIFOL(s, 2) = unwrap<BlockId>(id); - WFIFOSET(s, clif_parse_func_table[0xc4].len); + Packet_Fixed<0x00c4> fixed_c4; + fixed_c4.block_id = id; + send_fpacket<0x00c4, 6>(s, fixed_c4); return 0; } @@ -1223,18 +1224,17 @@ int clif_buylist(dumb_ptr<map_session_data> sd, dumb_ptr<npc_data_shop> nd) nullpo_ret(nd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xc6; + std::vector<Packet_Repeat<0x00c6>> repeat_c6(nd->shop_items.size()); for (i = 0; i < nd->shop_items.size(); i++) { id = itemdb_search(nd->shop_items[i].nameid); val = nd->shop_items[i].value; - WFIFOL(s, 4 + i * 11) = val; // base price - WFIFOL(s, 8 + i * 11) = val; // actual price - WFIFOB(s, 12 + i * 11) = static_cast<uint8_t>(id->type); - WFIFOW(s, 13 + i * 11) = unwrap<ItemNameId>(nd->shop_items[i].nameid); + repeat_c6[i].base_price = val; // base price + repeat_c6[i].actual_price = val; // actual price + repeat_c6[i].type = id->type; + repeat_c6[i].name_id = nd->shop_items[i].nameid; } - WFIFOW(s, 2) = i * 11 + 4; - WFIFOSET(s, WFIFOW(s, 2)); + send_packet_repeatonly<0x00c6, 4, 11>(s, repeat_c6); return 0; } @@ -1245,12 +1245,12 @@ int clif_buylist(dumb_ptr<map_session_data> sd, dumb_ptr<npc_data_shop> nd) */ int clif_selllist(dumb_ptr<map_session_data> sd) { - int i, c = 0, val; + int i, val; nullpo_ret(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xc7; + std::vector<Packet_Repeat<0x00c7>> repeat_c7; for (i = 0; i < MAX_INVENTORY; i++) { if (sd->status.inventory[i].nameid && sd->inventory_data[i]) @@ -1258,14 +1258,14 @@ int clif_selllist(dumb_ptr<map_session_data> sd) val = sd->inventory_data[i]->value_sell; if (val < 0) continue; - WFIFOW(s, 4 + c * 10) = i + 2; - WFIFOL(s, 6 + c * 10) = val; // base price - WFIFOL(s, 10 + c * 10) = val; // actual price - c++; + Packet_Repeat<0x00c7> info; + info.ioff2 = i + 2; + info.base_price = val; + info.actual_price = val; + repeat_c7.push_back(info); } } - WFIFOW(s, 2) = c * 10 + 4; - WFIFOSET(s, WFIFOW(s, 2)); + send_packet_repeatonly<0x00c7, 4, 10>(s, repeat_c7); return 0; } @@ -1280,12 +1280,9 @@ void clif_scriptmes(dumb_ptr<map_session_data> sd, BlockId npcid, XString mes) Session *s = sd->sess; - size_t len = mes.size() + 1; - WFIFOW(s, 0) = 0xb4; - WFIFOW(s, 2) = len + 8; - WFIFOL(s, 4) = unwrap<BlockId>(npcid); - WFIFO_STRING(s, 8, mes, len); - WFIFOSET(s, WFIFOW(s, 2)); + Packet_Head<0x00b4> head_b4; + head_b4.block_id = npcid; + send_vpacket<0x00b4, 8, 1>(s, head_b4, mes); } /*========================================== @@ -1297,9 +1294,9 @@ void clif_scriptnext(dumb_ptr<map_session_data> sd, BlockId npcid) nullpo_retv(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xb5; - WFIFOL(s, 2) = unwrap<BlockId>(npcid); - WFIFOSET(s, clif_parse_func_table[0xb5].len); + Packet_Fixed<0x00b5> fixed_b5; + fixed_b5.block_id = npcid; + send_fpacket<0x00b5, 6>(s, fixed_b5); } /*========================================== @@ -1311,9 +1308,9 @@ void clif_scriptclose(dumb_ptr<map_session_data> sd, BlockId npcid) nullpo_retv(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xb6; - WFIFOL(s, 2) = unwrap<BlockId>(npcid); - WFIFOSET(s, clif_parse_func_table[0xb6].len); + Packet_Fixed<0x00b6> fixed_b6; + fixed_b6.block_id = npcid; + send_fpacket<0x00b6, 6>(s, fixed_b6); } /*========================================== @@ -1325,12 +1322,9 @@ void clif_scriptmenu(dumb_ptr<map_session_data> sd, BlockId npcid, XString mes) nullpo_retv(sd); Session *s = sd->sess; - size_t len = mes.size() + 1; - WFIFOW(s, 0) = 0xb7; - WFIFOW(s, 2) = len + 8; - WFIFOL(s, 4) = unwrap<BlockId>(npcid); - WFIFO_STRING(s, 8, mes, len); - WFIFOSET(s, WFIFOW(s, 2)); + Packet_Head<0x00b7> head_b7; + head_b7.block_id = npcid; + send_vpacket<0x00b7, 8, 1>(s, head_b7, mes); } /*========================================== @@ -1342,9 +1336,9 @@ void clif_scriptinput(dumb_ptr<map_session_data> sd, BlockId npcid) nullpo_retv(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0x142; - WFIFOL(s, 2) = unwrap<BlockId>(npcid); - WFIFOSET(s, clif_parse_func_table[0x142].len); + Packet_Fixed<0x0142> fixed_142; + fixed_142.block_id = npcid; + send_fpacket<0x0142, 6>(s, fixed_142); } /*========================================== @@ -1356,9 +1350,9 @@ void clif_scriptinputstr(dumb_ptr<map_session_data> sd, BlockId npcid) nullpo_retv(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0x1d4; - WFIFOL(s, 2) = unwrap<BlockId>(npcid); - WFIFOSET(s, clif_parse_func_table[0x1d4].len); + Packet_Fixed<0x01d4> fixed_1d4; + fixed_1d4.block_id = npcid; + send_fpacket<0x01d4, 6>(s, fixed_1d4); } /*========================================== @@ -1370,22 +1364,13 @@ int clif_additem(dumb_ptr<map_session_data> sd, int n, int amount, PickupFail fa nullpo_ret(sd); Session *s = sd->sess; + Packet_Fixed<0x00a0> fixed_a0; if (fail != PickupFail::OKAY) { - WFIFOW(s, 0) = 0xa0; - WFIFOW(s, 2) = n + 2; - WFIFOW(s, 4) = amount; - WFIFOW(s, 6) = 0; - WFIFOB(s, 8) = 0; - WFIFOB(s, 9) = 0; - WFIFOB(s, 10) = 0; - WFIFOW(s, 11) = 0; - WFIFOW(s, 13) = 0; - WFIFOW(s, 15) = 0; - WFIFOW(s, 17) = 0; - WFIFOW(s, 19) = 0; - WFIFOB(s, 21) = 0; - WFIFOB(s, 22) = static_cast<uint8_t>(fail); + fixed_a0.ioff2 = n + 2; + fixed_a0.amount = amount; + fixed_a0.name_id = ItemNameId(); + fixed_a0.pickup_fail = fail; } else { @@ -1393,27 +1378,26 @@ int clif_additem(dumb_ptr<map_session_data> sd, int n, int amount, PickupFail fa || sd->inventory_data[n] == NULL) return 1; - WFIFOW(s, 0) = 0xa0; - WFIFOW(s, 2) = n + 2; - WFIFOW(s, 4) = amount; - WFIFOW(s, 6) = unwrap<ItemNameId>(sd->status.inventory[n].nameid); - WFIFOB(s, 8) = 1; //identify; - WFIFOB(s, 9) = 0; // broken or attribute; - WFIFOB(s, 10) = 0; //refine; + fixed_a0.ioff2 = n + 2; + fixed_a0.amount = amount; + fixed_a0.name_id = sd->status.inventory[n].nameid; + fixed_a0.identify = 1; + fixed_a0.broken_or_attribute = 0; + fixed_a0.refine = 0; { - WFIFOW(s, 11) = 0; //card[0]; - WFIFOW(s, 13) = 0; //card[1]; - WFIFOW(s, 15) = 0; //card[2]; - WFIFOW(s, 17) = 0; //card[3]; + fixed_a0.card0 = 0; + fixed_a0.card1 = 0; + fixed_a0.card2 = 0; + fixed_a0.card3 = 0; } - WFIFOW(s, 19) = static_cast<uint16_t>(pc_equippoint(sd, n)); - WFIFOB(s, 21) = static_cast<uint8_t>(sd->inventory_data[n]->type == ItemType::_7 + fixed_a0.epos = pc_equippoint(sd, n); + fixed_a0.item_type = (sd->inventory_data[n]->type == ItemType::_7 ? ItemType::WEAPON : sd->inventory_data[n]->type); - WFIFOB(s, 22) = static_cast<uint8_t>(fail); + fixed_a0.pickup_fail = fail; } - WFIFOSET(s, clif_parse_func_table[0xa0].len); + send_fpacket<0x00a0, 23>(s, fixed_a0); return 0; } @@ -1426,11 +1410,11 @@ void clif_delitem(dumb_ptr<map_session_data> sd, int n, int amount) nullpo_retv(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xaf; - WFIFOW(s, 2) = n + 2; - WFIFOW(s, 4) = amount; + Packet_Fixed<0x00af> fixed_af; + fixed_af.ioff2 = n + 2; + fixed_af.amount = amount; - WFIFOSET(s, clif_parse_func_table[0xaf].len); + send_fpacket<0x00af, 6>(s, fixed_af); } /*========================================== @@ -1441,39 +1425,38 @@ void clif_itemlist(dumb_ptr<map_session_data> sd) { nullpo_retv(sd); - int n = 0; int arrow = -1; Session *s = sd->sess; - WFIFOW(s, 0) = 0x1ee; + std::vector<Packet_Repeat<0x01ee>> repeat_1ee; for (int i = 0; i < MAX_INVENTORY; i++) { if (!sd->status.inventory[i].nameid || sd->inventory_data[i] == NULL || itemdb_isequip2(sd->inventory_data[i])) continue; - WFIFOW(s, n * 18 + 4) = i + 2; - WFIFOW(s, n * 18 + 6) = unwrap<ItemNameId>(sd->status.inventory[i].nameid); - WFIFOB(s, n * 18 + 8) = static_cast<uint8_t>(sd->inventory_data[i]->type); - WFIFOB(s, n * 18 + 9) = 1; //identify; - WFIFOW(s, n * 18 + 10) = sd->status.inventory[i].amount; + Packet_Repeat<0x01ee> info; + info.ioff2 = i + 2; + info.name_id = sd->status.inventory[i].nameid; + info.item_type = sd->inventory_data[i]->type; + info.identify = 1; + info.amount = sd->status.inventory[i].amount; if (sd->inventory_data[i]->equip == EPOS::ARROW) { - WFIFOW(s, n * 18 + 12) = static_cast<uint16_t>(EPOS::ARROW); + info.epos = EPOS::ARROW; if (bool(sd->status.inventory[i].equip)) arrow = i; // ついでに矢装備チェック } else - WFIFOW(s, n * 18 + 12) = static_cast<uint16_t>(EPOS::ZERO); - WFIFOW(s, n * 18 + 14) = 0; //card[0]; - WFIFOW(s, n * 18 + 16) = 0; //card[1]; - WFIFOW(s, n * 18 + 18) = 0; //card[2]; - WFIFOW(s, n * 18 + 20) = 0; //card[3]; - n++; + info.epos = EPOS::ZERO; + info.card0 = 0; + info.card1 = 0; + info.card2 = 0; + info.card3 = 0; + repeat_1ee.push_back(info); } - if (n) + if (!repeat_1ee.empty()) { - WFIFOW(s, 2) = 4 + n * 18; - WFIFOSET(s, WFIFOW(s, 2)); + send_packet_repeatonly<0x01ee, 4, 18>(s, repeat_1ee); } if (arrow >= 0) clif_arrowequip(sd, arrow); @@ -1488,37 +1471,36 @@ void clif_equiplist(dumb_ptr<map_session_data> sd) nullpo_retv(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xa4; - int n = 0; + std::vector<Packet_Repeat<0x00a4>> repeat_a4; for (int i = 0; i < MAX_INVENTORY; i++) { if (!sd->status.inventory[i].nameid || sd->inventory_data[i] == NULL || !itemdb_isequip2(sd->inventory_data[i])) continue; - WFIFOW(s, n * 20 + 4) = i + 2; - WFIFOW(s, n * 20 + 6) = unwrap<ItemNameId>(sd->status.inventory[i].nameid); - WFIFOB(s, n * 20 + 8) = static_cast<uint8_t>( + Packet_Repeat<0x00a4> info; + info.ioff2 = i + 2; + info.name_id = sd->status.inventory[i].nameid; + info.item_type = ( sd->inventory_data[i]->type == ItemType::_7 ? ItemType::WEAPON : sd->inventory_data[i]->type); - WFIFOB(s, n * 20 + 9) = 0; //identify; - WFIFOW(s, n * 20 + 10) = static_cast<uint16_t>(pc_equippoint(sd, i)); - WFIFOW(s, n * 20 + 12) = static_cast<uint16_t>(sd->status.inventory[i].equip); - WFIFOB(s, n * 20 + 14) = 0; //broken or attribute; - WFIFOB(s, n * 20 + 15) = 0; //refine; + info.identify = 0; + info.epos_pc = pc_equippoint(sd, i); + info.epos_inv = sd->status.inventory[i].equip; + info.broken_or_attribute = 0; + info.refine = 0; { - WFIFOW(s, n * 20 + 16) = 0; //card[0]; - WFIFOW(s, n * 20 + 18) = 0; //card[1]; - WFIFOW(s, n * 20 + 20) = 0; //card[2]; - WFIFOW(s, n * 20 + 22) = 0; //card[3]; + info.card0 = 0; + info.card1 = 0; + info.card2 = 0; + info.card3 = 0; } - n++; + repeat_a4.push_back(info); } - if (n) + if (!repeat_a4.empty()) { - WFIFOW(s, 2) = 4 + n * 20; - WFIFOSET(s, WFIFOW(s, 2)); + send_packet_repeatonly<0x00a4, 4, 20>(s, repeat_a4); } } @@ -1532,8 +1514,7 @@ int clif_storageitemlist(dumb_ptr<map_session_data> sd, Storage *stor) nullpo_ret(stor); Session *s = sd->sess; - WFIFOW(s, 0) = 0x1f0; - int n = 0; + std::vector<Packet_Repeat<0x01f0>> repeat_1f0; for (int i = 0; i < MAX_STORAGE; i++) { if (!stor->storage_[i].nameid) @@ -1545,22 +1526,22 @@ int clif_storageitemlist(dumb_ptr<map_session_data> sd, Storage *stor) if (itemdb_isequip2(id)) continue; - WFIFOW(s, n * 18 + 4) = i + 1; - WFIFOW(s, n * 18 + 6) = unwrap<ItemNameId>(stor->storage_[i].nameid); - WFIFOB(s, n * 18 + 8) = static_cast<uint8_t>(id->type); - WFIFOB(s, n * 18 + 9) = 0; //identify; - WFIFOW(s, n * 18 + 10) = stor->storage_[i].amount; - WFIFOW(s, n * 18 + 12) = 0; - WFIFOW(s, n * 18 + 14) = 0; //card[0]; - WFIFOW(s, n * 18 + 16) = 0; //card[1]; - WFIFOW(s, n * 18 + 18) = 0; //card[2]; - WFIFOW(s, n * 18 + 20) = 0; //card[3]; - n++; + Packet_Repeat<0x01f0> info; + info.soff1 = i + 1; + info.name_id = stor->storage_[i].nameid; + info.item_type = id->type; + info.identify = 0; + info.amount = stor->storage_[i].amount; + info.epos_zero = EPOS::ZERO; + info.card0 = 0; + info.card1 = 0; + info.card2 = 0; + info.card3 = 0; + repeat_1f0.push_back(info); } - if (n) + if (!repeat_1f0.empty()) { - WFIFOW(s, 2) = 4 + n * 18; - WFIFOSET(s, WFIFOW(s, 2)); + send_packet_repeatonly<0x01f0, 4, 18>(s, repeat_1f0); } return 0; } @@ -1575,8 +1556,7 @@ int clif_storageequiplist(dumb_ptr<map_session_data> sd, Storage *stor) nullpo_ret(stor); Session *s = sd->sess; - WFIFOW(s, 0) = 0xa6; - int n = 0; + std::vector<Packet_Repeat<0x00a6>> repeat_a6; for (int i = 0; i < MAX_STORAGE; i++) { if (!stor->storage_[i].nameid) @@ -1587,26 +1567,26 @@ int clif_storageequiplist(dumb_ptr<map_session_data> sd, Storage *stor) nullpo_ret(id); if (!itemdb_isequip2(id)) continue; - WFIFOW(s, n * 20 + 4) = i + 1; - WFIFOW(s, n * 20 + 6) = unwrap<ItemNameId>(stor->storage_[i].nameid); - WFIFOB(s, n * 20 + 8) = static_cast<uint8_t>(id->type); - WFIFOB(s, n * 20 + 9) = 0; //identify; - WFIFOW(s, n * 20 + 10) = static_cast<uint16_t>(id->equip); - WFIFOW(s, n * 20 + 12) = static_cast<uint16_t>(stor->storage_[i].equip); - WFIFOB(s, n * 20 + 14) = 0; //broken or attribute - WFIFOB(s, n * 20 + 15) = 0; //refine; + Packet_Repeat<0x00a6> info; + info.soff1 = i + 1; + info.name_id = stor->storage_[i].nameid; + info.item_type = id->type; + info.identify = 0; + info.epos_id = id->equip; + info.epos_stor = stor->storage_[i].equip; + info.broken_or_attribute = 0; + info.refine = 0; { - WFIFOW(s, n * 20 + 16) = 0; //card[0]; - WFIFOW(s, n * 20 + 18) = 0; //card[1]; - WFIFOW(s, n * 20 + 20) = 0; //card[2]; - WFIFOW(s, n * 20 + 22) = 0; //card[3]; + info.card0 = 0; + info.card1 = 0; + info.card2 = 0; + info.card3 = 0; } - n++; + repeat_a6.push_back(info); } - if (n) + if (!repeat_a6.empty()) { - WFIFOW(s, 2) = 4 + n * 20; - WFIFOSET(s, WFIFOW(s, 2)); + send_packet_repeatonly<0x00a6, 4, 20>(s, repeat_a6); } return 0; } @@ -1618,140 +1598,183 @@ int clif_storageequiplist(dumb_ptr<map_session_data> sd, Storage *stor) */ int clif_updatestatus(dumb_ptr<map_session_data> sd, SP type) { - int len = 8; - nullpo_ret(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xb0; - WFIFOW(s, 2) = static_cast<uint16_t>(type); - switch (type) { - // 00b0 + Packet_Fixed<0x00b0> fixed_b0; + fixed_b0.sp_type = type; + switch (type) + { case SP::WEIGHT: pc_checkweighticon(sd); - // is this because pc_checkweighticon can send other packets? - WFIFOW(s, 0) = 0xb0; - WFIFOW(s, 2) = static_cast<uint16_t>(type); - WFIFOL(s, 4) = sd->weight; + fixed_b0.value = sd->weight; break; case SP::MAXWEIGHT: - WFIFOL(s, 4) = sd->max_weight; + fixed_b0.value = sd->max_weight; break; case SP::SPEED: - // ... - WFIFOL(s, 4) = static_cast<uint16_t>(sd->speed.count()); + // 'speed' is actually delay, in milliseconds + fixed_b0.value = sd->speed.count(); break; case SP::BASELEVEL: - WFIFOL(s, 4) = sd->status.base_level; + fixed_b0.value = sd->status.base_level; break; case SP::JOBLEVEL: - WFIFOL(s, 4) = 0; + fixed_b0.value = sd->status.job_level; break; case SP::STATUSPOINT: - WFIFOL(s, 4) = sd->status.status_point; + fixed_b0.value = sd->status.status_point; break; case SP::SKILLPOINT: - WFIFOL(s, 4) = sd->status.skill_point; + fixed_b0.value = sd->status.skill_point; break; case SP::HIT: - WFIFOL(s, 4) = sd->hit; + fixed_b0.value = sd->hit; break; case SP::FLEE1: - WFIFOL(s, 4) = sd->flee; + fixed_b0.value = sd->flee; break; case SP::FLEE2: - WFIFOL(s, 4) = sd->flee2 / 10; + fixed_b0.value = sd->flee2 / 10; break; case SP::MAXHP: - WFIFOL(s, 4) = sd->status.max_hp; + fixed_b0.value = sd->status.max_hp; break; case SP::MAXSP: - WFIFOL(s, 4) = sd->status.max_sp; + fixed_b0.value = sd->status.max_sp; break; case SP::HP: - WFIFOL(s, 4) = sd->status.hp; + fixed_b0.value = sd->status.hp; break; case SP::SP: - WFIFOL(s, 4) = sd->status.sp; + fixed_b0.value = sd->status.sp; break; case SP::ASPD: - WFIFOL(s, 4) = static_cast<uint16_t>(sd->aspd.count()); + fixed_b0.value = sd->aspd.count(); break; case SP::ATK1: - WFIFOL(s, 4) = sd->base_atk + sd->watk; + fixed_b0.value = sd->base_atk + sd->watk; break; case SP::DEF1: - WFIFOL(s, 4) = sd->def; + fixed_b0.value = sd->def; break; case SP::MDEF1: - WFIFOL(s, 4) = sd->mdef; + fixed_b0.value = sd->mdef; break; case SP::ATK2: - WFIFOL(s, 4) = sd->watk2; + fixed_b0.value = sd->watk2; break; case SP::DEF2: - WFIFOL(s, 4) = sd->def2; + fixed_b0.value = sd->def2; break; case SP::MDEF2: - WFIFOL(s, 4) = sd->mdef2; + fixed_b0.value = sd->mdef2; break; case SP::CRITICAL: - WFIFOL(s, 4) = sd->critical / 10; + fixed_b0.value = sd->critical / 10; break; case SP::MATK1: - WFIFOL(s, 4) = sd->matk1; + fixed_b0.value = sd->matk1; break; case SP::MATK2: - WFIFOL(s, 4) = sd->matk2; + fixed_b0.value = sd->matk2; + break; + case SP::GM: + fixed_b0.value = pc_isGM(sd).get_all_bits(); break; + default: + goto not_b0; + } + + send_fpacket<0x00b0, 8>(s, fixed_b0); + return 0; + } +not_b0: + + { + Packet_Fixed<0x00b1> fixed_b1; + fixed_b1.sp_type = type; + switch (type) + { case SP::ZENY: trade_verifyzeny(sd); - WFIFOW(s, 0) = 0xb1; if (sd->status.zeny < 0) sd->status.zeny = 0; - WFIFOL(s, 4) = sd->status.zeny; + fixed_b1.value = sd->status.zeny; break; + case SP::BASEEXP: - WFIFOW(s, 0) = 0xb1; - WFIFOL(s, 4) = sd->status.base_exp; + fixed_b1.value = sd->status.base_exp; break; case SP::JOBEXP: - WFIFOW(s, 0) = 0xb1; - WFIFOL(s, 4) = sd->status.job_exp; + fixed_b1.value = sd->status.job_exp; break; case SP::NEXTBASEEXP: - WFIFOW(s, 0) = 0xb1; - WFIFOL(s, 4) = pc_nextbaseexp(sd); + fixed_b1.value = pc_nextbaseexp(sd); break; case SP::NEXTJOBEXP: - WFIFOW(s, 0) = 0xb1; - WFIFOL(s, 4) = pc_nextjobexp(sd); + fixed_b1.value = pc_nextjobexp(sd); break; - // 00be 終了 + default: + goto not_b1; + } + + send_fpacket<0x00b1, 8>(s, fixed_b1); + return 0; + } +not_b1: + + { + Packet_Fixed<0x00be> fixed_be; + fixed_be.sp_type = type; + switch (type) + { case SP::USTR: case SP::UAGI: case SP::UVIT: case SP::UINT: case SP::UDEX: case SP::ULUK: - WFIFOW(s, 0) = 0xbe; - WFIFOB(s, 4) = pc_need_status_point(sd, usp_to_sp(type)); - len = 5; + fixed_be.value = pc_need_status_point(sd, usp_to_sp(type)); break; - // 013a 終了 + default: + goto not_be; + } + + send_fpacket<0x00be, 5>(s, fixed_be); + return 0; + } +not_be: + + { + Packet_Fixed<0x013a> fixed_13a; + switch (type) + { case SP::ATTACKRANGE: - WFIFOW(s, 0) = 0x13a; - WFIFOW(s, 2) = (sd->attack_spell_override) - ? sd->attack_spell_range : sd->attackrange; - len = 4; + fixed_13a.attack_range = (sd->attack_spell_override + ? sd->attack_spell_range + : sd->attackrange); break; - // 0141 終了 + default: + goto not_13a; + } + + send_fpacket<0x013a, 4>(s, fixed_13a); + return 0; + } +not_13a: + + { + Packet_Fixed<0x00141> fixed_141; + fixed_141.sp_type = type; + switch (type) + { case SP::STR: case SP::AGI: case SP::VIT: @@ -1760,27 +1783,28 @@ int clif_updatestatus(dumb_ptr<map_session_data> sd, SP type) case SP::LUK: { ATTR attr = sp_to_attr(type); - WFIFOW(s, 0) = 0x141; - WFIFOL(s, 2) = static_cast<uint16_t>(type); - WFIFOL(s, 6) = sd->status.attrs[attr]; - WFIFOL(s, 10) = sd->paramb[attr] + sd->parame[attr]; - len = 14; + fixed_141.value_status = sd->status.attrs[attr]; + fixed_141.value_b_e = sd->paramb[attr] + sd->parame[attr]; } break; - case SP::GM: - WFIFOL(s, 4) = pc_isGM(sd).get_all_bits(); - break; - default: + goto not_141; + } + + send_fpacket<0x0141, 14>(s, fixed_141); + return 0; + } + +not_141: + { + { if (battle_config.error_log) PRINTF("clif_updatestatus : make %d routine\n"_fmt, type); return 1; + } } - WFIFOSET(s, len); - - return 0; } /*========================================== @@ -1795,7 +1819,6 @@ int clif_changelook(dumb_ptr<block_list> bl, LOOK type, int val) int clif_changelook_towards(dumb_ptr<block_list> bl, LOOK type, int val, dumb_ptr<map_session_data> dstsd) { - unsigned char buf[32]; dumb_ptr<map_session_data> sd = NULL; nullpo_ret(bl); @@ -1809,61 +1832,65 @@ int clif_changelook_towards(dumb_ptr<block_list> bl, LOOK type, int val, if (sd && (type == LOOK::WEAPON || type == LOOK::SHIELD || type >= LOOK::SHOES)) { - WBUFW(buf, 0) = 0x1d7; - WBUFL(buf, 2) = unwrap<BlockId>(bl->bl_id); + Packet_Fixed<0x01d7> fixed_1d7; + fixed_1d7.block_id = bl->bl_id; if (type >= LOOK::SHOES) { EQUIP equip_point = equip_points[type]; - WBUFB(buf, 6) = static_cast<uint16_t>(type); + fixed_1d7.look_type = type; int idx = sd->equip_index_maybe[equip_point]; if (idx >= 0 && sd->inventory_data[idx]) { - WBUFW(buf, 7) = unwrap<ItemNameId>(sd->status.inventory[idx].nameid); + fixed_1d7.weapon_or_name_id_or_value = unwrap<ItemNameId>(sd->status.inventory[idx].nameid); } else - WBUFW(buf, 7) = 0; - WBUFW(buf, 9) = 0; + fixed_1d7.weapon_or_name_id_or_value = unwrap<ItemNameId>(ItemNameId()); + fixed_1d7.shield = ItemNameId(); } else { - WBUFB(buf, 6) = 2; + fixed_1d7.look_type = LOOK::WEAPON; int widx = sd->equip_index_maybe[EQUIP::WEAPON]; int sidx = sd->equip_index_maybe[EQUIP::SHIELD]; if (sd->attack_spell_override) - WBUFW(buf, 7) = sd->attack_spell_look_override; + fixed_1d7.weapon_or_name_id_or_value = unwrap<ItemNameId>(sd->attack_spell_look_override); else { if (widx >= 0 && sd->inventory_data[widx]) { - WBUFW(buf, 7) = unwrap<ItemNameId>(sd->status.inventory[widx].nameid); + fixed_1d7.weapon_or_name_id_or_value = unwrap<ItemNameId>(sd->status.inventory[widx].nameid); } else - WBUFW(buf, 7) = 0; + fixed_1d7.weapon_or_name_id_or_value = unwrap<ItemNameId>(ItemNameId()); } if (sidx >= 0 && sidx != widx && sd->inventory_data[sidx]) { - WBUFW(buf, 9) = unwrap<ItemNameId>(sd->status.inventory[sidx].nameid); + fixed_1d7.shield = sd->status.inventory[sidx].nameid; } else - WBUFW(buf, 9) = 0; + fixed_1d7.shield = ItemNameId(); } + + Buffer buf = create_fpacket<0x01d7, 11>(fixed_1d7); if (dstsd) - clif_send(buf, clif_parse_func_table[0x1d7].len, dstsd, SendWho::SELF); + clif_send(buf, dstsd, SendWho::SELF); else - clif_send(buf, clif_parse_func_table[0x1d7].len, bl, SendWho::AREA); + clif_send(buf, bl, SendWho::AREA); } else { - WBUFW(buf, 0) = 0x1d7; - WBUFL(buf, 2) = unwrap<BlockId>(bl->bl_id); - WBUFB(buf, 6) = static_cast<uint8_t>(type); - WBUFW(buf, 7) = val; - WBUFW(buf, 9) = 0; + Packet_Fixed<0x01d7> fixed_1d7; + fixed_1d7.block_id = bl->bl_id; + fixed_1d7.look_type = type; + fixed_1d7.weapon_or_name_id_or_value = val; + fixed_1d7.shield = ItemNameId(); + + Buffer buf = create_fpacket<0x01d7, 11>(fixed_1d7); if (dstsd) - clif_send(buf, clif_parse_func_table[0x1d7].len, dstsd, SendWho::SELF); + clif_send(buf, dstsd, SendWho::SELF); else - clif_send(buf, clif_parse_func_table[0x1d7].len, bl, SendWho::AREA); + clif_send(buf, bl, SendWho::AREA); } return 0; } @@ -1879,38 +1906,38 @@ int clif_initialstatus(dumb_ptr<map_session_data> sd) Session *s = sd->sess; - WFIFOW(s, 0) = 0xbd; - WFIFOW(s, 2) = sd->status.status_point; - - WFIFOB(s, 4) = saturate<uint8_t>(sd->status.attrs[ATTR::STR]); - WFIFOB(s, 5) = pc_need_status_point(sd, SP::STR); - WFIFOB(s, 6) = saturate<uint8_t>(sd->status.attrs[ATTR::AGI]); - WFIFOB(s, 7) = pc_need_status_point(sd, SP::AGI); - WFIFOB(s, 8) = saturate<uint8_t>(sd->status.attrs[ATTR::VIT]); - WFIFOB(s, 9) = pc_need_status_point(sd, SP::VIT); - WFIFOB(s, 10) = saturate<uint8_t>(sd->status.attrs[ATTR::INT]); - WFIFOB(s, 11) = pc_need_status_point(sd, SP::INT); - WFIFOB(s, 12) = saturate<uint8_t>(sd->status.attrs[ATTR::DEX]); - WFIFOB(s, 13) = pc_need_status_point(sd, SP::DEX); - WFIFOB(s, 14) = saturate<uint8_t>(sd->status.attrs[ATTR::LUK]); - WFIFOB(s, 15) = pc_need_status_point(sd, SP::LUK); - - WFIFOW(s, 16) = sd->base_atk + sd->watk; - WFIFOW(s, 18) = sd->watk2; //atk bonus - WFIFOW(s, 20) = sd->matk1; - WFIFOW(s, 22) = sd->matk2; - WFIFOW(s, 24) = sd->def; // def - WFIFOW(s, 26) = sd->def2; - WFIFOW(s, 28) = sd->mdef; // mdef - WFIFOW(s, 30) = sd->mdef2; - WFIFOW(s, 32) = sd->hit; - WFIFOW(s, 34) = sd->flee; - WFIFOW(s, 36) = sd->flee2 / 10; - WFIFOW(s, 38) = sd->critical / 10; - WFIFOW(s, 40) = sd->status.karma; - WFIFOW(s, 42) = sd->status.manner; - - WFIFOSET(s, clif_parse_func_table[0xbd].len); + Packet_Fixed<0x00bd> fixed_bd; + fixed_bd.status_point = sd->status.status_point; + + fixed_bd.str_attr = saturate<uint8_t>(sd->status.attrs[ATTR::STR]); + fixed_bd.str_upd = pc_need_status_point(sd, SP::STR); + fixed_bd.agi_attr = saturate<uint8_t>(sd->status.attrs[ATTR::AGI]); + fixed_bd.agi_upd = pc_need_status_point(sd, SP::AGI); + fixed_bd.vit_attr = saturate<uint8_t>(sd->status.attrs[ATTR::VIT]); + fixed_bd.vit_upd = pc_need_status_point(sd, SP::VIT); + fixed_bd.int_attr = saturate<uint8_t>(sd->status.attrs[ATTR::INT]); + fixed_bd.int_upd = pc_need_status_point(sd, SP::INT); + fixed_bd.dex_attr = saturate<uint8_t>(sd->status.attrs[ATTR::DEX]); + fixed_bd.dex_upd = pc_need_status_point(sd, SP::DEX); + fixed_bd.luk_attr = saturate<uint8_t>(sd->status.attrs[ATTR::LUK]); + fixed_bd.luk_upd = pc_need_status_point(sd, SP::LUK); + + fixed_bd.atk_sum = sd->base_atk + sd->watk; + fixed_bd.watk2 = sd->watk2; //atk bonus + fixed_bd.matk1 = sd->matk1; + fixed_bd.matk2 = sd->matk2; + fixed_bd.def = sd->def; + fixed_bd.def2 = sd->def2; + fixed_bd.mdef = sd->mdef; + fixed_bd.mdef2 = sd->mdef2; + fixed_bd.hit = sd->hit; + fixed_bd.flee = sd->flee; + fixed_bd.flee2 = sd->flee2 / 10; + fixed_bd.critical = sd->critical / 10; + fixed_bd.karma = sd->status.karma; + fixed_bd.manner = sd->status.manner; + + send_fpacket<0x00bd, 44>(s, fixed_bd); clif_updatestatus(sd, SP::STR); clif_updatestatus(sd, SP::AGI); @@ -1936,10 +1963,9 @@ int clif_arrowequip(dumb_ptr<map_session_data> sd, int val) sd->attacktarget = BlockId(); Session *s = sd->sess; - WFIFOW(s, 0) = 0x013c; - WFIFOW(s, 2) = val + 2; //矢のアイテムID - - WFIFOSET(s, clif_parse_func_table[0x013c].len); + Packet_Fixed<0x013c> fixed_13c; + fixed_13c.ioff2 = val + 2; + send_fpacket<0x013c, 4>(s, fixed_13c); return 0; } @@ -1954,10 +1980,9 @@ int clif_arrow_fail(dumb_ptr<map_session_data> sd, int type) Session *s = sd->sess; - WFIFOW(s, 0) = 0x013b; - WFIFOW(s, 2) = type; - - WFIFOSET(s, clif_parse_func_table[0x013b].len); + Packet_Fixed<0x013b> fixed_13b; + fixed_13b.type = type; + send_fpacket<0x013b, 4>(s, fixed_13b); return 0; } @@ -1971,11 +1996,11 @@ int clif_statusupack(dumb_ptr<map_session_data> sd, SP type, int ok, int val) nullpo_ret(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xbc; - WFIFOW(s, 2) = static_cast<uint16_t>(type); - WFIFOB(s, 4) = ok; - WFIFOB(s, 5) = val; - WFIFOSET(s, clif_parse_func_table[0xbc].len); + Packet_Fixed<0x00bc> fixed_bc; + fixed_bc.sp_type = type; + fixed_bc.ok = ok; + fixed_bc.val = val; + send_fpacket<0x00bc, 6>(s, fixed_bc); return 0; } @@ -1989,11 +2014,11 @@ int clif_equipitemack(dumb_ptr<map_session_data> sd, int n, EPOS pos, int ok) nullpo_ret(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xaa; - WFIFOW(s, 2) = n + 2; - WFIFOW(s, 4) = static_cast<uint16_t>(pos); - WFIFOB(s, 6) = ok; - WFIFOSET(s, clif_parse_func_table[0xaa].len); + Packet_Fixed<0x00aa> fixed_aa; + fixed_aa.ioff2 = n + 2; + fixed_aa.epos = pos; + fixed_aa.ok = ok; + send_fpacket<0x00aa, 7>(s, fixed_aa); return 0; } @@ -2007,11 +2032,11 @@ int clif_unequipitemack(dumb_ptr<map_session_data> sd, int n, EPOS pos, int ok) nullpo_ret(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xac; - WFIFOW(s, 2) = n + 2; - WFIFOW(s, 4) = static_cast<uint16_t>(pos); - WFIFOB(s, 6) = ok; - WFIFOSET(s, clif_parse_func_table[0xac].len); + Packet_Fixed<0x00ac> fixed_ac; + fixed_ac.ioff2 = n + 2; + fixed_ac.epos = pos; + fixed_ac.ok = ok; + send_fpacket<0x00ac, 7>(s, fixed_ac); return 0; } @@ -2022,15 +2047,14 @@ int clif_unequipitemack(dumb_ptr<map_session_data> sd, int n, EPOS pos, int ok) */ int clif_misceffect(dumb_ptr<block_list> bl, int type) { - uint8_t buf[32]; - nullpo_ret(bl); - WBUFW(buf, 0) = 0x19b; - WBUFL(buf, 2) = unwrap<BlockId>(bl->bl_id); - WBUFL(buf, 6) = type; + Packet_Fixed<0x019b> fixed_19b; + fixed_19b.block_id = bl->bl_id; + fixed_19b.type = type; + Buffer buf = create_fpacket<0x019b, 10>(fixed_19b); - clif_send(buf, clif_parse_func_table[0x19b].len, bl, SendWho::AREA); + clif_send(buf, bl, SendWho::AREA); return 0; } @@ -2041,7 +2065,6 @@ int clif_misceffect(dumb_ptr<block_list> bl, int type) */ int clif_changeoption(dumb_ptr<block_list> bl) { - uint8_t buf[32]; eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; nullpo_ret(bl); @@ -2049,14 +2072,15 @@ int clif_changeoption(dumb_ptr<block_list> bl) Option option = *battle_get_option(bl); sc_data = battle_get_sc_data(bl); - WBUFW(buf, 0) = 0x119; - WBUFL(buf, 2) = unwrap<BlockId>(bl->bl_id); - WBUFW(buf, 6) = static_cast<uint16_t>(*battle_get_opt1(bl)); - WBUFW(buf, 8) = static_cast<uint16_t>(*battle_get_opt2(bl)); - WBUFW(buf, 10) = static_cast<uint16_t>(option); - WBUFB(buf, 12) = 0; // ?? + Packet_Fixed<0x0119> fixed_119; + fixed_119.block_id = bl->bl_id; + fixed_119.opt1 = *battle_get_opt1(bl); + fixed_119.opt2 = *battle_get_opt2(bl); + fixed_119.option = option; + fixed_119.zero = 0; + Buffer buf = create_fpacket<0x0119, 13>(fixed_119); - clif_send(buf, clif_parse_func_table[0x119].len, bl, SendWho::AREA); + clif_send(buf, bl, SendWho::AREA); return 0; } @@ -2073,23 +2097,22 @@ int clif_useitemack(dumb_ptr<map_session_data> sd, int index, int amount, if (!ok) { Session *s = sd->sess; - WFIFOW(s, 0) = 0xa8; - WFIFOW(s, 2) = index + 2; - WFIFOW(s, 4) = amount; - WFIFOB(s, 6) = ok; - WFIFOSET(s, clif_parse_func_table[0xa8].len); + Packet_Fixed<0x00a8> fixed_a8; + fixed_a8.ioff2 = index + 2; + fixed_a8.amount = amount; + fixed_a8.ok = ok; + send_fpacket<0x00a8, 7>(s, fixed_a8); } else { - uint8_t buf[32]; - - WBUFW(buf, 0) = 0x1c8; - WBUFW(buf, 2) = index + 2; - WBUFW(buf, 4) = unwrap<ItemNameId>(sd->status.inventory[index].nameid); - WBUFL(buf, 6) = unwrap<BlockId>(sd->bl_id); - WBUFW(buf, 10) = amount; - WBUFB(buf, 12) = ok; - clif_send(buf, clif_parse_func_table[0x1c8].len, sd, SendWho::SELF); + Packet_Fixed<0x01c8> fixed_1c8; + fixed_1c8.ioff2 = index + 2; + fixed_1c8.name_id = sd->status.inventory[index].nameid; + fixed_1c8.block_id = sd->bl_id; + fixed_1c8.amount = amount; + fixed_1c8.ok = ok; + Buffer buf = create_fpacket<0x01c8, 13>(fixed_1c8); + clif_send(buf, sd, SendWho::SELF); } return 0; @@ -2104,9 +2127,9 @@ void clif_traderequest(dumb_ptr<map_session_data> sd, CharName name) nullpo_retv(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xe5; - WFIFO_STRING(s, 2, name.to__actual(), 24); - WFIFOSET(s, clif_parse_func_table[0xe5].len); + Packet_Fixed<0x00e5> fixed_e5; + fixed_e5.char_name = name; + send_fpacket<0x00e5, 26>(s, fixed_e5); } /*========================================== @@ -2118,9 +2141,9 @@ void clif_tradestart(dumb_ptr<map_session_data> sd, int type) nullpo_retv(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xe7; - WFIFOB(s, 2) = type; - WFIFOSET(s, clif_parse_func_table[0xe7].len); + Packet_Fixed<0x00e7> fixed_e7; + fixed_e7.type = type; + send_fpacket<0x00e7, 3>(s, fixed_e7); } /*========================================== @@ -2128,57 +2151,57 @@ void clif_tradestart(dumb_ptr<map_session_data> sd, int type) *------------------------------------------ */ void clif_tradeadditem(dumb_ptr<map_session_data> sd, - dumb_ptr<map_session_data> tsd, int index, int amount) + dumb_ptr<map_session_data> tsd, int index2, int amount) { nullpo_retv(sd); nullpo_retv(tsd); Session *s = tsd->sess; - WFIFOW(s, 0) = 0xe9; - WFIFOL(s, 2) = amount; - if (index == 0) + Packet_Fixed<0x00e9> fixed_e9; + fixed_e9.amount = amount; + if (index2 == 0) { - WFIFOW(s, 6) = 0; // type id - WFIFOB(s, 8) = 0; //identify flag - WFIFOB(s, 9) = 0; // attribute - WFIFOB(s, 10) = 0; //refine - WFIFOW(s, 11) = 0; //card (4w) - WFIFOW(s, 13) = 0; //card (4w) - WFIFOW(s, 15) = 0; //card (4w) - WFIFOW(s, 17) = 0; //card (4w) + fixed_e9.name_id = ItemNameId(); + fixed_e9.identify = 0; + fixed_e9.broken_or_attribute = 0; + fixed_e9.refine = 0; + fixed_e9.card0 = 0; + fixed_e9.card1 = 0; + fixed_e9.card2 = 0; + fixed_e9.card3 = 0; } else { - index -= 2; - WFIFOW(s, 6) = unwrap<ItemNameId>(sd->status.inventory[index].nameid); // type id - WFIFOB(s, 8) = 0; //identify; - WFIFOB(s, 9) = 0; //broken or attribute; - WFIFOB(s, 10) = 0; //refine; + int index0 = index2 - 2; + fixed_e9.name_id = sd->status.inventory[index0].nameid; + fixed_e9.identify = 0; + fixed_e9.broken_or_attribute = 0; + fixed_e9.refine = 0; { - WFIFOW(s, 11) = 0; //card[0]; - WFIFOW(s, 13) = 0; //card[1]; - WFIFOW(s, 15) = 0; //card[2]; - WFIFOW(s, 17) = 0; //card[3]; + fixed_e9.card0 = 0; + fixed_e9.card1 = 0; + fixed_e9.card2 = 0; + fixed_e9.card3 = 0; } } - WFIFOSET(s, clif_parse_func_table[0xe9].len); + send_fpacket<0x00e9, 19>(s, fixed_e9); } /*========================================== * アイテム追加成功/失敗 *------------------------------------------ */ -int clif_tradeitemok(dumb_ptr<map_session_data> sd, int index, int amount, +int clif_tradeitemok(dumb_ptr<map_session_data> sd, int index2, int amount, int fail) { nullpo_ret(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0x1b1; - WFIFOW(s, 2) = index; - WFIFOW(s, 4) = amount; - WFIFOB(s, 6) = fail; - WFIFOSET(s, clif_parse_func_table[0x1b1].len); + Packet_Fixed<0x01b1> fixed_1b1; + fixed_1b1.ioff2 = index2; + fixed_1b1.amount = amount; + fixed_1b1.fail = fail; + send_fpacket<0x01b1, 7>(s, fixed_1b1); return 0; } @@ -2192,9 +2215,9 @@ int clif_tradedeal_lock(dumb_ptr<map_session_data> sd, int fail) nullpo_ret(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xec; - WFIFOB(s, 2) = fail; // 0=you 1=the other person - WFIFOSET(s, clif_parse_func_table[0xec].len); + Packet_Fixed<0x00ec> fixed_ec; + fixed_ec.fail = fail; // 0=you 1=the other person + send_fpacket<0x00ec, 3>(s, fixed_ec); return 0; } @@ -2208,8 +2231,8 @@ int clif_tradecancelled(dumb_ptr<map_session_data> sd) nullpo_ret(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xee; - WFIFOSET(s, clif_parse_func_table[0xee].len); + Packet_Fixed<0x00ee> fixed_ee; + send_fpacket<0x00ee, 2>(s, fixed_ee); return 0; } @@ -2223,9 +2246,9 @@ int clif_tradecompleted(dumb_ptr<map_session_data> sd, int fail) nullpo_ret(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xf0; - WFIFOB(s, 2) = fail; - WFIFOSET(s, clif_parse_func_table[0xf0].len); + Packet_Fixed<0x00f0> fixed_f0; + fixed_f0.fail = fail; + send_fpacket<0x00f0, 3>(s, fixed_f0); return 0; } @@ -2241,10 +2264,10 @@ int clif_updatestorageamount(dumb_ptr<map_session_data> sd, nullpo_ret(stor); Session *s = sd->sess; - WFIFOW(s, 0) = 0xf2; // update storage amount - WFIFOW(s, 2) = stor->storage_amount; //items - WFIFOW(s, 4) = MAX_STORAGE; //items max - WFIFOSET(s, clif_parse_func_table[0xf2].len); + Packet_Fixed<0x00f2> fixed_f2; + fixed_f2.current_slots = stor->storage_amount; //items + fixed_f2.max_slots = MAX_STORAGE; //items max + send_fpacket<0x00f2, 6>(s, fixed_f2); return 0; } @@ -2260,23 +2283,20 @@ int clif_storageitemadded(dumb_ptr<map_session_data> sd, Storage *stor, nullpo_ret(stor); Session *s = sd->sess; - WFIFOW(s, 0) = 0xf4; // Storage item added - WFIFOW(s, 2) = index + 1; // index - WFIFOL(s, 4) = amount; // amount -/* if ((view = itemdb_viewid(stor->storage_[index].nameid)) > 0) - WFIFOW(fd,8) =view; - else*/ - WFIFOW(s, 8) = unwrap<ItemNameId>(stor->storage_[index].nameid); - WFIFOB(s, 10) = 0; //identify; - WFIFOB(s, 11) = 0; //broken or attribute; - WFIFOB(s, 12) = 0; //refine; + Packet_Fixed<0x00f4> fixed_f4; + fixed_f4.soff1 = index + 1; + fixed_f4.amount = amount; + fixed_f4.name_id = stor->storage_[index].nameid; + fixed_f4.identify = 0; + fixed_f4.broken_or_attribute = 0; + fixed_f4.refine = 0; { - WFIFOW(s, 13) = 0; //card[0]; - WFIFOW(s, 15) = 0; //card[1]; - WFIFOW(s, 17) = 0; //card[2]; - WFIFOW(s, 19) = 0; //card[3]; + fixed_f4.card0 = 0; + fixed_f4.card1 = 0; + fixed_f4.card2 = 0; + fixed_f4.card3 = 0; } - WFIFOSET(s, clif_parse_func_table[0xf4].len); + send_fpacket<0x00f4, 21>(s, fixed_f4); return 0; } @@ -2291,10 +2311,10 @@ int clif_storageitemremoved(dumb_ptr<map_session_data> sd, int index, nullpo_ret(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xf6; // Storage item removed - WFIFOW(s, 2) = index + 1; - WFIFOL(s, 4) = amount; - WFIFOSET(s, clif_parse_func_table[0xf6].len); + Packet_Fixed<0x00f6> fixed_f6; + fixed_f6.soff1 = index + 1; + fixed_f6.amount = amount; + send_fpacket<0x00f6, 8>(s, fixed_f6); return 0; } @@ -2308,8 +2328,8 @@ int clif_storageclose(dumb_ptr<map_session_data> sd) nullpo_ret(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xf8; // Storage Closed - WFIFOSET(s, clif_parse_func_table[0xf8].len); + Packet_Fixed<0x00f8> fixed_f8; + send_fpacket<0x00f8, 2>(s, fixed_f8); return 0; } @@ -2332,25 +2352,22 @@ static void clif_getareachar_pc(dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> dstsd) { - int len; - if (bool(dstsd->status.option & Option::INVISIBILITY)) return; nullpo_retv(sd); nullpo_retv(dstsd); - uint8_t buf[256]; + Buffer buf; if (dstsd->walktimer) { - len = clif_set007b(dstsd, buf); + clif_set007b(dstsd, buf); } else { - len = clif_set0078(dstsd, buf); + clif_set0078_main_1d8(dstsd, buf); } - WFIFO_BUF_CLONE(sd->sess, buf, len); - WFIFOSET(sd->sess, len); + send_buffer(sd->sess, buf); if (battle_config.save_clothcolor == 1 && dstsd->status.clothes_color > 0) clif_changelook(dstsd, LOOK::CLOTHES_COLOR, @@ -2367,16 +2384,15 @@ void clif_getareachar_pc(dumb_ptr<map_session_data> sd, static void clif_getareachar_npc(dumb_ptr<map_session_data> sd, dumb_ptr<npc_data> nd) { - int len; - nullpo_retv(sd); nullpo_retv(nd); - if (nd->npc_class < 0 || nd->flag & 1 || nd->npc_class == INVISIBLE_CLASS) + if (nd->npc_class == NEGATIVE_SPECIES || nd->flag & 1 || nd->npc_class == INVISIBLE_CLASS) return; - len = clif_npc0078(nd, static_cast<uint8_t *>(WFIFOP(sd->sess, 0))); - WFIFOSET(sd->sess, len); + Buffer buf; + clif_npc0078(nd, buf); + send_buffer(sd->sess, buf); } /*========================================== @@ -2385,13 +2401,11 @@ void clif_getareachar_npc(dumb_ptr<map_session_data> sd, dumb_ptr<npc_data> nd) */ int clif_movemob(dumb_ptr<mob_data> md) { - unsigned char buf[256]; - int len; - nullpo_ret(md); - len = clif_mob007b(md, buf); - clif_send(buf, len, md, SendWho::AREA); + Buffer buf; + clif_mob007b(md, buf); + clif_send(buf, md, SendWho::AREA); return 0; } @@ -2402,20 +2416,19 @@ int clif_movemob(dumb_ptr<mob_data> md) */ int clif_fixmobpos(dumb_ptr<mob_data> md) { - unsigned char buf[256]; - int len; - nullpo_ret(md); if (md->state.state == MS::WALK) { - len = clif_mob007b(md, buf); - clif_send(buf, len, md, SendWho::AREA); + Buffer buf; + clif_mob007b(md, buf); + clif_send(buf, md, SendWho::AREA); } else { - len = clif_mob0078(md, buf); - clif_send(buf, len, md, SendWho::AREA); + Buffer buf; + clif_mob0078(md, buf); + clif_send(buf, md, SendWho::AREA); } return 0; @@ -2427,20 +2440,19 @@ int clif_fixmobpos(dumb_ptr<mob_data> md) */ int clif_fixpcpos(dumb_ptr<map_session_data> sd) { - unsigned char buf[256]; - int len; - nullpo_ret(sd); if (sd->walktimer) { - len = clif_set007b(sd, buf); - clif_send(buf, len, sd, SendWho::AREA); + Buffer buf; + clif_set007b(sd, buf); + clif_send(buf, sd, SendWho::AREA); } else { - len = clif_set0078(sd, buf); - clif_send(buf, len, sd, SendWho::AREA); + Buffer buf; + clif_set0078_main_1d8(sd, buf); + clif_send(buf, sd, SendWho::AREA); } clif_changelook_accessories(sd, NULL); @@ -2455,7 +2467,6 @@ int clif_damage(dumb_ptr<block_list> src, dumb_ptr<block_list> dst, tick_t tick, interval_t sdelay, interval_t ddelay, int damage, int div, DamageType type, int damage2) { - unsigned char buf[256]; eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; nullpo_ret(src); @@ -2463,17 +2474,18 @@ int clif_damage(dumb_ptr<block_list> src, dumb_ptr<block_list> dst, sc_data = battle_get_sc_data(dst); - WBUFW(buf, 0) = 0x8a; - WBUFL(buf, 2) = unwrap<BlockId>(src->bl_id); - WBUFL(buf, 6) = unwrap<BlockId>(dst->bl_id); - WBUFL(buf, 10) = tick.time_since_epoch().count(); - WBUFL(buf, 14) = sdelay.count(); - WBUFL(buf, 18) = ddelay.count(); - WBUFW(buf, 22) = (damage > 0x7fff) ? 0x7fff : damage; - WBUFW(buf, 24) = div; - WBUFB(buf, 26) = static_cast<uint8_t>(type); - WBUFW(buf, 27) = damage2; - clif_send(buf, clif_parse_func_table[0x8a].len, src, SendWho::AREA); + Packet_Fixed<0x008a> fixed_8a; + fixed_8a.src_id = src->bl_id; + fixed_8a.dst_id = dst->bl_id; + fixed_8a.tick = tick; + fixed_8a.sdelay = sdelay; + fixed_8a.ddelay = ddelay; + fixed_8a.damage = (damage > 0x7fff) ? 0x7fff : damage; + fixed_8a.div = div; + fixed_8a.damage_type = type; + fixed_8a.damage2 = damage2; + Buffer buf = create_fpacket<0x008a, 29>(fixed_8a); + clif_send(buf, src, SendWho::AREA); return 0; } @@ -2485,19 +2497,20 @@ int clif_damage(dumb_ptr<block_list> src, dumb_ptr<block_list> dst, static void clif_getareachar_mob(dumb_ptr<map_session_data> sd, dumb_ptr<mob_data> md) { - int len; nullpo_retv(sd); nullpo_retv(md); if (md->state.state == MS::WALK) { - len = clif_mob007b(md, static_cast<uint8_t *>(WFIFOP(sd->sess, 0))); - WFIFOSET(sd->sess, len); + Buffer buf; + clif_mob007b(md, buf); + send_buffer(sd->sess, buf); } else { - len = clif_mob0078(md, static_cast<uint8_t *>(WFIFOP(sd->sess, 0))); - WFIFOSET(sd->sess, len); + Buffer buf; + clif_mob0078(md, buf); + send_buffer(sd->sess, buf); } } @@ -2513,18 +2526,16 @@ void clif_getareachar_item(dumb_ptr<map_session_data> sd, nullpo_retv(fitem); Session *s = sd->sess; - //009d <ID>.l <item ID>.w <identify flag>.B <X>.w <Y>.w <amount>.w <subX>.B <subY>.B - WFIFOW(s, 0) = 0x9d; - WFIFOL(s, 2) = unwrap<BlockId>(fitem->bl_id); - WFIFOW(s, 6) = unwrap<ItemNameId>(fitem->item_data.nameid); - WFIFOB(s, 8) = 0; //identify; - WFIFOW(s, 9) = fitem->bl_x; - WFIFOW(s, 11) = fitem->bl_y; - WFIFOW(s, 13) = fitem->item_data.amount; - WFIFOB(s, 15) = fitem->subx; - WFIFOB(s, 16) = fitem->suby; - - WFIFOSET(s, clif_parse_func_table[0x9d].len); + Packet_Fixed<0x009d> fixed_9d; + fixed_9d.block_id = fitem->bl_id; + fixed_9d.name_id = fitem->item_data.nameid; + fixed_9d.identify = 0; + fixed_9d.x = fitem->bl_x; + fixed_9d.y = fitem->bl_y; + fixed_9d.amount = fitem->item_data.amount; + fixed_9d.subx = fitem->subx; + fixed_9d.suby = fitem->suby; + send_fpacket<0x009d, 17>(s, fixed_9d); } /*========================================== @@ -2681,27 +2692,27 @@ int clif_skillinfo(dumb_ptr<map_session_data> sd, SkillID skillid, int type, Session *s = sd->sess; if (!sd->status.skill[skillid].lv) return 0; - WFIFOW(s, 0) = 0x147; - WFIFOW(s, 2) = static_cast<uint16_t>(skillid); + Packet_Fixed<0x0147> fixed_147; + fixed_147.info.skill_id = skillid; if (type < 0) - WFIFOW(s, 4) = skill_get_inf(skillid); + fixed_147.info.type_or_inf = skill_get_inf(skillid); else - WFIFOW(s, 4) = type; - WFIFOW(s, 6) = 0; - WFIFOW(s, 8) = sd->status.skill[skillid].lv; - WFIFOW(s, 10) = skill_get_sp(skillid, sd->status.skill[skillid].lv); + fixed_147.info.type_or_inf = type; + fixed_147.info.flags = SkillFlags::ZERO; + fixed_147.info.level = sd->status.skill[skillid].lv; + fixed_147.info.sp = skill_get_sp(skillid, sd->status.skill[skillid].lv); if (range < 0) { range = skill_get_range(skillid, sd->status.skill[skillid].lv); if (range < 0) range = battle_get_range(sd) - (range + 1); - WFIFOW(s, 12) = range; + fixed_147.info.range = range; } else - WFIFOW(s, 12) = range; - WFIFO_ZERO(s, 14, 24); - WFIFOB(s, 38) = sd->status.skill[skillid].lv < skill_get_max_raise(skillid); - WFIFOSET(s, clif_parse_func_table[0x147].len); + fixed_147.info.range = range; + fixed_147.info.unused = ""_s; + fixed_147.info.can_raise = sd->status.skill[skillid].lv < skill_get_max_raise(skillid); + send_fpacket<0x0147, 39>(s, fixed_147); return 0; } @@ -2712,35 +2723,34 @@ int clif_skillinfo(dumb_ptr<map_session_data> sd, SkillID skillid, int type, */ void clif_skillinfoblock(dumb_ptr<map_session_data> sd) { - int len = 4, range; - nullpo_retv(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0x10f; + std::vector<Packet_Repeat<0x010f>> repeat_10f; for (SkillID i : erange(SkillID(), MAX_SKILL)) { if (sd->status.skill[i].lv && sd->tmw_version >= 1) { + Packet_Repeat<0x010f> info; // [Fate] Version 1 and later don't crash because of bad skill IDs anymore - WFIFOW(s, len) = static_cast<uint16_t>(i); - WFIFOW(s, len + 2) = skill_get_inf(i); - WFIFOW(s, len + 4) = static_cast<uint16_t>( + info.info.skill_id = i; + info.info.type_or_inf = skill_get_inf(i); + info.info.flags = ( skill_db[i].poolflags | (sd->status.skill[i].flags & SkillFlags::POOL_ACTIVATED)); - WFIFOW(s, len + 6) = sd->status.skill[i].lv; - WFIFOW(s, len + 8) = skill_get_sp(i, sd->status.skill[i].lv); - range = skill_get_range(i, sd->status.skill[i].lv); + info.info.level = sd->status.skill[i].lv; + info.info.sp = skill_get_sp(i, sd->status.skill[i].lv); + int range = skill_get_range(i, sd->status.skill[i].lv); if (range < 0) range = battle_get_range(sd) - (range + 1); - WFIFOW(s, len + 10) = range; - WFIFO_ZERO(s, len + 12, 24); - WFIFOB(s, len + 36) = sd->status.skill[i].lv < skill_get_max_raise(i); - len += 37; + info.info.range = range; + info.info.unused = ""_s; + info.info.can_raise = sd->status.skill[i].lv < skill_get_max_raise(i); + + repeat_10f.push_back(info); } } - WFIFOW(s, 2) = len; - WFIFOSET(s, len); + send_packet_repeatonly<0x010f, 4, 37>(s, repeat_10f); } /*========================================== @@ -2749,21 +2759,19 @@ void clif_skillinfoblock(dumb_ptr<map_session_data> sd) */ int clif_skillup(dumb_ptr<map_session_data> sd, SkillID skill_num) { - int range; - nullpo_ret(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0x10e; - WFIFOW(s, 2) = static_cast<uint16_t>(skill_num); - WFIFOW(s, 4) = sd->status.skill[skill_num].lv; - WFIFOW(s, 6) = skill_get_sp(skill_num, sd->status.skill[skill_num].lv); - range = skill_get_range(skill_num, sd->status.skill[skill_num].lv); + Packet_Fixed<0x010e> fixed_10e; + fixed_10e.skill_id = skill_num; + fixed_10e.level = sd->status.skill[skill_num].lv; + fixed_10e.sp = skill_get_sp(skill_num, sd->status.skill[skill_num].lv); + int range = skill_get_range(skill_num, sd->status.skill[skill_num].lv); if (range < 0) range = battle_get_range(sd) - (range + 1); - WFIFOW(s, 8) = range; - WFIFOB(s, 10) = sd->status.skill[skill_num].lv < skill_get_max_raise(skill_num); - WFIFOSET(s, clif_parse_func_table[0x10e].len); + fixed_10e.range = range; + fixed_10e.can_raise = sd->status.skill[skill_num].lv < skill_get_max_raise(skill_num); + send_fpacket<0x010e, 11>(s, fixed_10e); return 0; } @@ -2774,14 +2782,11 @@ int clif_skillup(dumb_ptr<map_session_data> sd, SkillID skill_num) */ int clif_skillcastcancel(dumb_ptr<block_list> bl) { - unsigned char buf[16]; - - nullpo_ret(bl); - - WBUFW(buf, 0) = 0x1b9; - WBUFL(buf, 2) = unwrap<BlockId>(bl->bl_id); - clif_send(buf, clif_parse_func_table[0x1b9].len, bl, SendWho::AREA); + // packet 0x01b9 was being sent with length 0, + // even though there were 6 bytes involved + // and the client ignores it anyway + (void)bl; return 0; } @@ -2801,13 +2806,13 @@ int clif_skill_fail(dumb_ptr<map_session_data> sd, SkillID skill_id, int type, return 0; } - WFIFOW(s, 0) = 0x110; - WFIFOW(s, 2) = static_cast<uint16_t>(skill_id); - WFIFOW(s, 4) = btype; - WFIFOW(s, 6) = 0; - WFIFOB(s, 8) = 0; - WFIFOB(s, 9) = type; - WFIFOSET(s, clif_parse_func_table[0x110].len); + Packet_Fixed<0x0110> fixed_110; + fixed_110.skill_id = skill_id; + fixed_110.btype = btype; + fixed_110.zero1 = 0; + fixed_110.zero2 = 0; + fixed_110.type = type; + send_fpacket<0x0110, 10>(s, fixed_110); return 0; } @@ -2820,7 +2825,6 @@ int clif_skill_damage(dumb_ptr<block_list> src, dumb_ptr<block_list> dst, tick_t tick, interval_t sdelay, interval_t ddelay, int damage, int div, SkillID skill_id, int skill_lv, int type) { - unsigned char buf[64]; eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; nullpo_ret(src); @@ -2828,18 +2832,19 @@ int clif_skill_damage(dumb_ptr<block_list> src, dumb_ptr<block_list> dst, sc_data = battle_get_sc_data(dst); - WBUFW(buf, 0) = 0x1de; - WBUFW(buf, 2) = static_cast<uint16_t>(skill_id); - WBUFL(buf, 4) = unwrap<BlockId>(src->bl_id); - WBUFL(buf, 8) = unwrap<BlockId>(dst->bl_id); - WBUFL(buf, 12) = static_cast<uint32_t>(tick.time_since_epoch().count()); - WBUFL(buf, 16) = static_cast<uint32_t>(sdelay.count()); - WBUFL(buf, 20) = static_cast<uint32_t>(ddelay.count()); - WBUFL(buf, 24) = damage; - WBUFW(buf, 28) = skill_lv; - WBUFW(buf, 30) = div; - WBUFB(buf, 32) = (type > 0) ? type : skill_get_hit(skill_id); - clif_send(buf, clif_parse_func_table[0x1de].len, src, SendWho::AREA); + Packet_Fixed<0x01de> fixed_1de; + fixed_1de.skill_id = skill_id; + fixed_1de.src_id = src->bl_id; + fixed_1de.dst_id = dst->bl_id; + fixed_1de.tick = tick; + fixed_1de.sdelay = sdelay; + fixed_1de.ddelay = ddelay; + fixed_1de.damage = damage; + fixed_1de.skill_level = skill_lv; + fixed_1de.div = div; + fixed_1de.type_or_hit = (type > 0) ? type : skill_get_hit(skill_id); + Buffer buf = create_fpacket<0x01de, 33>(fixed_1de); + clif_send(buf, src, SendWho::AREA); return 0; } @@ -2850,15 +2855,14 @@ int clif_skill_damage(dumb_ptr<block_list> src, dumb_ptr<block_list> dst, */ int clif_status_change(dumb_ptr<block_list> bl, StatusChange type, int flag) { - unsigned char buf[16]; - nullpo_ret(bl); - WBUFW(buf, 0) = 0x0196; - WBUFW(buf, 2) = static_cast<uint16_t>(type); - WBUFL(buf, 4) = unwrap<BlockId>(bl->bl_id); - WBUFB(buf, 8) = flag; - clif_send(buf, clif_parse_func_table[0x196].len, bl, SendWho::AREA); + Packet_Fixed<0x0196> fixed_196; + fixed_196.sc_type = type; + fixed_196.block_id = bl->bl_id; + fixed_196.flag = flag; + Buffer buf = create_fpacket<0x0196, 9>(fixed_196); + clif_send(buf, bl, SendWho::AREA); return 0; } @@ -2871,11 +2875,8 @@ void clif_displaymessage(Session *s, XString mes) if (mes) { // don't send a void message (it's not displaying on the client chat). @help can send void line. - WFIFOW(s, 0) = 0x8e; - size_t str_len = mes.size() + 1; // NUL (might not be NUL yet) - WFIFOW(s, 2) = 4 + str_len; - WFIFO_STRING(s, 4, mes, str_len); - WFIFOSET(s, 4 + str_len); + // This is untrue now ^ + send_packet_repeatonly<0x008e, 4, 1>(s, mes); } } @@ -2885,14 +2886,9 @@ void clif_displaymessage(Session *s, XString mes) */ void clif_GMmessage(dumb_ptr<block_list> bl, XString mes, int flag) { - size_t str_len = mes.size() + 1; - unsigned char buf[str_len + 4]; - - WBUFW(buf, 0) = 0x9a; - WBUFW(buf, 2) = str_len + 4; - WBUF_STRING(buf, 4, mes, str_len); + Buffer buf = create_packet_repeatonly<0x009a, 4, 1>(mes); flag &= 0x07; - clif_send(buf, WBUFW(buf, 2), bl, + clif_send(buf, bl, (flag == 1) ? SendWho::ALL_SAMEMAP : (flag == 2) ? SendWho::AREA : (flag == 3) ? SendWho::SELF : @@ -2905,15 +2901,14 @@ void clif_GMmessage(dumb_ptr<block_list> bl, XString mes, int flag) */ void clif_resurrection(dumb_ptr<block_list> bl, int type) { - uint8_t buf[16]; - nullpo_retv(bl); - WBUFW(buf, 0) = 0x148; - WBUFL(buf, 2) = unwrap<BlockId>(bl->bl_id); - WBUFW(buf, 6) = type; + Packet_Fixed<0x0148> fixed_148; + fixed_148.block_id = bl->bl_id; + fixed_148.type = type; + Buffer buf = create_fpacket<0x0148, 8>(fixed_148); - clif_send(buf, clif_parse_func_table[0x148].len, bl, + clif_send(buf, bl, type == 1 ? SendWho::AREA : SendWho::AREA_WOS); } @@ -2923,12 +2918,9 @@ void clif_resurrection(dumb_ptr<block_list> bl, int type) */ void clif_wis_message(Session *s, CharName nick, XString mes) // R 0097 <len>.w <nick>.24B <message>.?B { - size_t mes_len = mes.size() + 1; - WFIFOW(s, 0) = 0x97; - WFIFOW(s, 2) = mes_len + 24 + 4; - WFIFO_STRING(s, 4, nick.to__actual(), 24); - WFIFO_STRING(s, 28, mes, mes_len); - WFIFOSET(s, WFIFOW(s, 2)); + Packet_Head<0x0097> head_97; + head_97.char_name = nick; + send_vpacket<0x0097, 28, 1>(s, head_97, mes); } /*========================================== @@ -2937,9 +2929,9 @@ void clif_wis_message(Session *s, CharName nick, XString mes) // R 0097 <len>. */ void clif_wis_end(Session *s, int flag) // R 0098 <type>.B: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target { - WFIFOW(s, 0) = 0x98; - WFIFOW(s, 2) = flag; - WFIFOSET(s, clif_parse_func_table[0x98].len); + Packet_Fixed<0x0098> fixed_98; + fixed_98.flag = flag; + send_fpacket<0x0098, 3>(s, fixed_98); } /*========================================== @@ -2959,9 +2951,9 @@ int clif_party_created(dumb_ptr<map_session_data> sd, int flag) nullpo_ret(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xfa; - WFIFOB(s, 2) = flag; - WFIFOSET(s, clif_parse_func_table[0xfa].len); + Packet_Fixed<0x00fa> fixed_fa; + fixed_fa.flag = flag; + send_fpacket<0x00fa, 3>(s, fixed_fa); return 0; } @@ -2971,41 +2963,43 @@ int clif_party_created(dumb_ptr<map_session_data> sd, int flag) */ int clif_party_info(PartyPair p, Session *s) { - unsigned char buf[1024]; - int i, c; + int i; dumb_ptr<map_session_data> sd = NULL; nullpo_ret(p); - WBUFW(buf, 0) = 0xfb; - WBUF_STRING(buf, 4, p->name, 24); - for (i = c = 0; i < MAX_PARTY; i++) + Packet_Head<0x00fb> head_fb; + std::vector<Packet_Repeat<0x00fb>> repeat_fb; + head_fb.party_name = p->name; + for (i = 0; i < MAX_PARTY; i++) { struct party_member *m = &p->member[i]; if (m->account_id) { + Packet_Repeat<0x00fb> info; if (sd == NULL) sd = dumb_ptr<map_session_data>(m->sd); - WBUFL(buf, 28 + c * 46) = unwrap<AccountId>(m->account_id); - WBUF_STRING(buf, 28 + c * 46 + 4, m->name.to__actual(), 24); - WBUF_STRING(buf, 28 + c * 46 + 28, m->map, 16); - WBUFB(buf, 28 + c * 46 + 44) = (m->leader) ? 0 : 1; - WBUFB(buf, 28 + c * 46 + 45) = (m->online) ? 0 : 1; - c++; + + info.account_id = m->account_id; + info.char_name = m->name; + info.map_name = m->map; + info.leader = (m->leader) ? 0 : 1; + info.online = (m->online) ? 0 : 1; + repeat_fb.push_back(info); } } - size_t len = 28 + c * 46; - WBUFW(buf, 2) = len; if (s) { // If set, send only to fd. - WFIFO_BUF_CLONE(s, buf, len); - WFIFOSET(s, len); + send_vpacket<0x00fb, 28, 46>(s, head_fb, repeat_fb); return 9; } // else, send it to all the party, if they exist. if (sd != NULL) - clif_send(buf, len, sd, SendWho::PARTY); + { + Buffer buf = create_vpacket<0x00fb, 28, 46>(head_fb, repeat_fb); + clif_send(buf, sd, SendWho::PARTY); + } return 0; } @@ -3029,10 +3023,10 @@ void clif_party_invite(dumb_ptr<map_session_data> sd, if (!(p = party_search(sd->status.party_id))) return; - WFIFOW(s, 0) = 0xfe; - WFIFOL(s, 2) = unwrap<AccountId>(sd->status_key.account_id); - WFIFO_STRING(s, 6, p->name, 24); - WFIFOSET(s, clif_parse_func_table[0xfe].len); + Packet_Fixed<0x00fe> fixed_fe; + fixed_fe.account_id = sd->status_key.account_id; + fixed_fe.party_name = p->name; + send_fpacket<0x00fe, 30>(s, fixed_fe); } /*========================================== @@ -3054,10 +3048,10 @@ void clif_party_inviteack(dumb_ptr<map_session_data> sd, CharName nick, int flag nullpo_retv(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xfd; - WFIFO_STRING(s, 2, nick.to__actual(), 24); - WFIFOB(s, 26) = flag; - WFIFOSET(s, clif_parse_func_table[0xfd].len); + Packet_Fixed<0x00fd> fixed_fd; + fixed_fd.char_name = nick; + fixed_fd.flag = flag; + send_fpacket<0x00fd, 27>(s, fixed_fd); } /*========================================== @@ -3069,8 +3063,6 @@ void clif_party_inviteack(dumb_ptr<map_session_data> sd, CharName nick, int flag */ void clif_party_option(PartyPair p, dumb_ptr<map_session_data> sd, int flag) { - unsigned char buf[16]; - nullpo_retv(p); if (sd == NULL && flag == 0) @@ -3082,15 +3074,17 @@ void clif_party_option(PartyPair p, dumb_ptr<map_session_data> sd, int flag) } if (sd == NULL) return; - WBUFW(buf, 0) = 0x101; - WBUFW(buf, 2) = ((flag & 0x01) ? 2 : p->exp); - WBUFW(buf, 4) = ((flag & 0x10) ? 2 : p->item); + Packet_Fixed<0x0101> fixed_101; + fixed_101.exp = ((flag & 0x01) ? 2 : p->exp); + fixed_101.item = ((flag & 0x10) ? 2 : p->item); if (flag == 0) - clif_send(buf, clif_parse_func_table[0x101].len, sd, SendWho::PARTY); + { + Buffer buf = create_fpacket<0x0101, 6>(fixed_101); + clif_send(buf, sd, SendWho::PARTY); + } else { - WFIFO_BUF_CLONE(sd->sess, buf, clif_parse_func_table[0x101].len); - WFIFOSET(sd->sess, clif_parse_func_table[0x101].len); + send_fpacket<0x0101, 6>(sd->sess, fixed_101); } } @@ -3101,15 +3095,14 @@ void clif_party_option(PartyPair p, dumb_ptr<map_session_data> sd, int flag) void clif_party_leaved(PartyPair p, dumb_ptr<map_session_data> sd, AccountId account_id, CharName name, int flag) { - unsigned char buf[64]; int i; nullpo_retv(p); - WBUFW(buf, 0) = 0x105; - WBUFL(buf, 2) = unwrap<AccountId>(account_id); - WBUF_STRING(buf, 6, name.to__actual(), 24); - WBUFB(buf, 30) = flag & 0x0f; + Packet_Fixed<0x0105> fixed_105; + fixed_105.account_id = account_id; + fixed_105.char_name = name; + fixed_105.flag = flag & 0x0f; if ((flag & 0xf0) == 0) { @@ -3121,12 +3114,14 @@ void clif_party_leaved(PartyPair p, dumb_ptr<map_session_data> sd, break; } if (sd != NULL) - clif_send(buf, clif_parse_func_table[0x105].len, sd, SendWho::PARTY); + { + Buffer buf = create_fpacket<0x0105, 31>(fixed_105); + clif_send(buf, sd, SendWho::PARTY); + } } else if (sd != NULL) { - WFIFO_BUF_CLONE(sd->sess, buf, clif_parse_func_table[0x105].len); - WFIFOSET(sd->sess, clif_parse_func_table[0x105].len); + send_fpacket<0x0105, 31>(sd->sess, fixed_105); } } @@ -3150,13 +3145,10 @@ void clif_party_message(PartyPair p, AccountId account_id, XString mes) } if (sd != NULL) { - size_t len = mes.size() + 1; - unsigned char buf[len + 8]; - WBUFW(buf, 0) = 0x109; - WBUFW(buf, 2) = len + 8; - WBUFL(buf, 4) = unwrap<AccountId>(account_id); - WBUF_STRING(buf, 8, mes, len); - clif_send(buf, len + 8, sd, SendWho::PARTY); + Packet_Head<0x0109> head_109; + head_109.account_id = account_id; + Buffer buf = create_vpacket<0x0109, 8, 1>(head_109, mes); + clif_send(buf, sd, SendWho::PARTY); } } @@ -3166,15 +3158,14 @@ void clif_party_message(PartyPair p, AccountId account_id, XString mes) */ int clif_party_xy(PartyPair , dumb_ptr<map_session_data> sd) { - unsigned char buf[16]; - nullpo_ret(sd); - WBUFW(buf, 0) = 0x107; - WBUFL(buf, 2) = unwrap<AccountId>(sd->status_key.account_id); - WBUFW(buf, 6) = sd->bl_x; - WBUFW(buf, 8) = sd->bl_y; - clif_send(buf, clif_parse_func_table[0x107].len, sd, SendWho::PARTY_SAMEMAP_WOS); + Packet_Fixed<0x0107> fixed_107; + fixed_107.account_id = sd->status_key.account_id; + fixed_107.x = sd->bl_x; + fixed_107.y = sd->bl_y; + Buffer buf = create_fpacket<0x0107, 10>(fixed_107); + clif_send(buf, sd, SendWho::PARTY_SAMEMAP_WOS); return 0; } @@ -3184,16 +3175,15 @@ int clif_party_xy(PartyPair , dumb_ptr<map_session_data> sd) */ int clif_party_hp(PartyPair , dumb_ptr<map_session_data> sd) { - unsigned char buf[16]; - nullpo_ret(sd); - WBUFW(buf, 0) = 0x106; - WBUFL(buf, 2) = unwrap<AccountId>(sd->status_key.account_id); - WBUFW(buf, 6) = (sd->status.hp > 0x7fff) ? 0x7fff : sd->status.hp; - WBUFW(buf, 8) = + Packet_Fixed<0x0106> fixed_106; + fixed_106.account_id = sd->status_key.account_id; + fixed_106.hp = (sd->status.hp > 0x7fff) ? 0x7fff : sd->status.hp; + fixed_106.max_hp = (sd->status.max_hp > 0x7fff) ? 0x7fff : sd->status.max_hp; - clif_send(buf, clif_parse_func_table[0x106].len, sd, SendWho::PARTY_AREA_WOS); + Buffer buf = create_fpacket<0x0106, 10>(fixed_106); + clif_send(buf, sd, SendWho::PARTY_AREA_WOS); return 0; } @@ -3207,14 +3197,14 @@ int clif_movetoattack(dumb_ptr<map_session_data> sd, dumb_ptr<block_list> bl) nullpo_ret(bl); Session *s = sd->sess; - WFIFOW(s, 0) = 0x139; - WFIFOL(s, 2) = unwrap<BlockId>(bl->bl_id); - WFIFOW(s, 6) = bl->bl_x; - WFIFOW(s, 8) = bl->bl_y; - WFIFOW(s, 10) = sd->bl_x; - WFIFOW(s, 12) = sd->bl_y; - WFIFOW(s, 14) = sd->attackrange; - WFIFOSET(s, clif_parse_func_table[0x139].len); + Packet_Fixed<0x0139> fixed_139; + fixed_139.block_id = bl->bl_id; + fixed_139.bl_x = bl->bl_x; + fixed_139.bl_y = bl->bl_y; + fixed_139.sd_x = sd->bl_x; + fixed_139.sd_y = sd->bl_y; + fixed_139.range = sd->attackrange; + send_fpacket<0x0139, 16>(s, fixed_139); return 0; } @@ -3224,13 +3214,12 @@ int clif_movetoattack(dumb_ptr<map_session_data> sd, dumb_ptr<block_list> bl) */ int clif_mvp_effect(dumb_ptr<map_session_data> sd) { - unsigned char buf[16]; - nullpo_ret(sd); - WBUFW(buf, 0) = 0x10c; - WBUFL(buf, 2) = unwrap<BlockId>(sd->bl_id); - clif_send(buf, clif_parse_func_table[0x10c].len, sd, SendWho::AREA); + Packet_Fixed<0x010c> fixed_10c; + fixed_10c.block_id = sd->bl_id; + Buffer buf = create_fpacket<0x010c, 6>(fixed_10c); + clif_send(buf, sd, SendWho::AREA); return 0; } @@ -3240,22 +3229,19 @@ int clif_mvp_effect(dumb_ptr<map_session_data> sd) */ void clif_emotion(dumb_ptr<block_list> bl, int type) { - unsigned char buf[8]; - nullpo_retv(bl); - WBUFW(buf, 0) = 0xc0; - WBUFL(buf, 2) = unwrap<BlockId>(bl->bl_id); - WBUFB(buf, 6) = type; - clif_send(buf, clif_parse_func_table[0xc0].len, bl, SendWho::AREA); + Packet_Fixed<0x00c0> fixed_c0; + fixed_c0.block_id = bl->bl_id; + fixed_c0.type = type; + Buffer buf = create_fpacket<0x00c0, 7>(fixed_c0); + clif_send(buf, bl, SendWho::AREA); } static void clif_emotion_towards(dumb_ptr<block_list> bl, dumb_ptr<block_list> target, int type) { - unsigned char buf[8]; - int len = clif_parse_func_table[0xc0].len; dumb_ptr<map_session_data> sd = target->is_player(); nullpo_retv(bl); @@ -3264,12 +3250,11 @@ void clif_emotion_towards(dumb_ptr<block_list> bl, if (target->bl_type != BL::PC) return; - WBUFW(buf, 0) = 0xc0; - WBUFL(buf, 2) = unwrap<BlockId>(bl->bl_id); - WBUFB(buf, 6) = type; + Packet_Fixed<0x00c0> fixed_c0; + fixed_c0.block_id = bl->bl_id; + fixed_c0.type = type; - WFIFO_BUF_CLONE(sd->sess, buf, len); - WFIFOSET(sd->sess, len); + send_fpacket<0x00c0, 7>(sd->sess, fixed_c0); } /*========================================== @@ -3278,14 +3263,13 @@ void clif_emotion_towards(dumb_ptr<block_list> bl, */ void clif_sitting(Session *, dumb_ptr<map_session_data> sd) { - unsigned char buf[64]; - nullpo_retv(sd); - WBUFW(buf, 0) = 0x8a; - WBUFL(buf, 2) = unwrap<BlockId>(sd->bl_id); - WBUFB(buf, 26) = 2; - clif_send(buf, clif_parse_func_table[0x8a].len, sd, SendWho::AREA); + Packet_Fixed<0x008a> fixed_8a; + fixed_8a.src_id = sd->bl_id; + fixed_8a.damage_type = DamageType::SIT; + Buffer buf = create_fpacket<0x008a, 29>(fixed_8a); + clif_send(buf, sd, SendWho::AREA); } /*========================================== @@ -3298,14 +3282,14 @@ int clif_GM_kickack(dumb_ptr<map_session_data> sd, AccountId id) nullpo_ret(sd); Session *s = sd->sess; - WFIFOW(s, 0) = 0xcd; - WFIFOL(s, 2) = unwrap<AccountId>(id); - WFIFOSET(s, clif_parse_func_table[0xcd].len); + Packet_Fixed<0x00cd> fixed_cd; + fixed_cd.account_id = id; + send_fpacket<0x00cd, 6>(s, fixed_cd); return 0; } static -void clif_parse_QuitGame(Session *s, dumb_ptr<map_session_data> sd); +void clif_do_quit_game(Session *s, dumb_ptr<map_session_data> sd); int clif_GM_kick(dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> tsd, int type) @@ -3316,7 +3300,7 @@ int clif_GM_kick(dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> tsd, clif_GM_kickack(sd, tsd->status_key.account_id); tsd->opt1 = Opt1::ZERO; tsd->opt2 = Opt2::ZERO; - clif_parse_QuitGame(tsd->sess, tsd); + clif_do_quit_game(tsd->sess, tsd); return 0; } @@ -3324,15 +3308,12 @@ int clif_GM_kick(dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> tsd, // displaying special effects (npcs, weather, etc) [Valaris] int clif_specialeffect(dumb_ptr<block_list> bl, int type, int flag) { - unsigned char buf[24]; - nullpo_ret(bl); - WBUF_ZERO(buf, 0, clif_parse_func_table[0x19b].len); - - WBUFW(buf, 0) = 0x19b; - WBUFL(buf, 2) = unwrap<BlockId>(bl->bl_id); - WBUFL(buf, 6) = type; + Packet_Fixed<0x019b> fixed_19b; + fixed_19b.block_id = bl->bl_id; + fixed_19b.type = type; + Buffer buf = create_fpacket<0x019b, 10>(fixed_19b); if (flag == 2) { @@ -3347,9 +3328,9 @@ int clif_specialeffect(dumb_ptr<block_list> bl, int type, int flag) } } else if (flag == 1) - clif_send(buf, clif_parse_func_table[0x19b].len, bl, SendWho::SELF); + clif_send(buf, bl, SendWho::SELF); else if (!flag) - clif_send(buf, clif_parse_func_table[0x19b].len, bl, SendWho::AREA); + clif_send(buf, bl, SendWho::AREA); return 0; @@ -3364,7 +3345,7 @@ int clif_specialeffect(dumb_ptr<block_list> bl, int type, int flag) *------------------------------------------ */ static -void clif_parse_WantToConnection(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_WantToConnection(Session *s, dumb_ptr<map_session_data> sd) { AccountId account_id; // account_id in the packet @@ -3372,18 +3353,22 @@ void clif_parse_WantToConnection(Session *s, dumb_ptr<map_session_data> sd) { if (battle_config.error_log) PRINTF("clif_parse_WantToConnection : invalid request?\n"_fmt); - return; + return RecvResult::Error; } - if (RFIFOW(s, 0) == 0x72) + Packet_Fixed<0x0072> fixed; + RecvResult rv = recv_fpacket<0x0072, 19>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + { - account_id = wrap<AccountId>(RFIFOL(s, 2)); + account_id = fixed.account_id; } - else - return; // Not the auth packet - WFIFOL(s, 0) = unwrap<AccountId>(account_id); - WFIFOSET(s, 4); + // formerly: account id + Packet_Payload<0x8000> special; + special.magic_packet_length = 4; + send_ppacket<0x8000>(s, special); // if same account already connected, we disconnect the 2 sessions dumb_ptr<map_session_data> old_sd = map_id2sd(account_to_block(account_id)); @@ -3400,16 +3385,16 @@ void clif_parse_WantToConnection(Session *s, dumb_ptr<map_session_data> sd) s->session_data.reset(sd.operator->()); sd->sess = s; - pc_setnewpc(sd, account_id, wrap<CharId>(RFIFOL(s, 6)), RFIFOL(s, 10), - tick_t(static_cast<interval_t>(RFIFOL(s, 14))), - static_cast<SEX>(RFIFOB(s, 18))); + pc_setnewpc(sd, account_id, fixed.char_id, fixed.login_id1, + fixed.client_tick, + fixed.sex); map_addiddb(sd); chrif_authreq(sd); } - return; + return RecvResult::Complete; } /*========================================== @@ -3418,12 +3403,15 @@ void clif_parse_WantToConnection(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_LoadEndAck(Session *, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_LoadEndAck(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); - if (sd->bl_prev != NULL) - return; + return RecvResult::Error; + + Packet_Fixed<0x007d> fixed; + RecvResult rv = recv_fpacket<0x007d, 2>(s, fixed); + if (rv != RecvResult::Complete) + return rv; // 接続ok時 //clif_authok(); @@ -3505,6 +3493,8 @@ void clif_parse_LoadEndAck(Session *, dumb_ptr<map_session_data> sd) if (!sd->state.seen_motd) pc_show_motd(sd); + + return rv; } /*========================================== @@ -3512,13 +3502,18 @@ void clif_parse_LoadEndAck(Session *, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_TickSend(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_TickSend(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + Packet_Fixed<0x007e> fixed; + RecvResult rv = recv_fpacket<0x007e, 6>(s, fixed); + if (rv != RecvResult::Complete) + return rv; - sd->client_tick = tick_t(static_cast<interval_t>(RFIFOL(s, 2))); - sd->server_tick = gettick(); + uint32_t client_tick = fixed.client_tick; + (void)client_tick; clif_servertick(sd); + + return rv; } /*========================================== @@ -3526,55 +3521,68 @@ void clif_parse_TickSend(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_WalkToXY(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_WalkToXY(Session *s, dumb_ptr<map_session_data> sd) { - int x, y; - - nullpo_retv(sd); + Packet_Fixed<0x0085> fixed; + RecvResult rv = recv_fpacket<0x0085, 5>(s, fixed); + if (rv != RecvResult::Complete) + return rv; if (pc_isdead(sd)) { clif_clearchar(sd, BeingRemoveWhy::DEAD); - return; + return rv; } if (sd->npc_id || sd->state.storage_open) - return; + return rv; if (sd->canmove_tick > gettick()) - return; + return rv; // ステータス異常やハイディング中(トンネルドライブ無)で動けない if (bool(sd->opt1) && sd->opt1 != (Opt1::_stone6)) - return; + return rv; if (sd->invincible_timer) pc_delinvincibletimer(sd); pc_stopattack(sd); - x = RFIFOB(s, 2) * 4 + (RFIFOB(s, 3) >> 6); - y = ((RFIFOB(s, 3) & 0x3f) << 4) + (RFIFOB(s, 4) >> 4); + int x = fixed.pos.x; + int y = fixed.pos.y; pc_walktoxy(sd, x, y); + return rv; } /*========================================== * *------------------------------------------ */ -void clif_parse_QuitGame(Session *s, dumb_ptr<map_session_data> sd) +static +RecvResult clif_parse_QuitGame(Session *s, dumb_ptr<map_session_data> sd) { - tick_t tick = gettick(); + Packet_Fixed<0x018a> fixed; + RecvResult rv = recv_fpacket<0x018a, 4>(s, fixed); + if (rv != RecvResult::Complete) + return rv; - nullpo_retv(sd); + clif_do_quit_game(s, sd); + return rv; +} + +void clif_do_quit_game(Session *s, dumb_ptr<map_session_data> sd) +{ - WFIFOW(s, 0) = 0x18b; + tick_t tick = gettick(); + + Packet_Fixed<0x018b> fixed_18b; if ((!pc_isdead(sd) && (sd->opt1 != Opt1::ZERO || sd->opt2 != Opt2::ZERO)) || (tick < sd->canact_tick)) { - WFIFOW(s, 2) = 1; - WFIFOSET(s, clif_parse_func_table[0x18b].len); + fixed_18b.okay = 1; + send_fpacket<0x018b, 4>(s, fixed_18b); return; } @@ -3583,14 +3591,13 @@ void clif_parse_QuitGame(Session *s, dumb_ptr<map_session_data> sd) || tick >= sd->canlog_tick + std::chrono::seconds(10)) { clif_setwaitclose(s); - WFIFOW(s, 2) = 0; + fixed_18b.okay = 0; } else { - WFIFOW(s, 2) = 1; + fixed_18b.okay = 1; } - WFIFOSET(s, clif_parse_func_table[0x18b].len); - + send_fpacket<0x018b, 4>(s, fixed_18b); } /*========================================== @@ -3598,18 +3605,23 @@ void clif_parse_QuitGame(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_GetCharNameRequest(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_GetCharNameRequest(Session *s, dumb_ptr<map_session_data> sd) { + Packet_Fixed<0x0094> fixed; + RecvResult rv = recv_fpacket<0x0094, 6>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + dumb_ptr<block_list> bl; BlockId account_id; - account_id = wrap<BlockId>(RFIFOL(s, 2)); + account_id = fixed.block_id; bl = map_id2bl(account_id); if (bl == NULL) - return; + return rv; - WFIFOW(s, 0) = 0x95; - WFIFOL(s, 2) = unwrap<BlockId>(account_id); + Packet_Fixed<0x0095> fixed_95; + fixed_95.block_id = account_id; switch (bl->bl_type) { @@ -3617,13 +3629,13 @@ void clif_parse_GetCharNameRequest(Session *s, dumb_ptr<map_session_data> sd) { dumb_ptr<map_session_data> ssd = bl->is_player(); - nullpo_retv(ssd); + nullpo_retr(rv, ssd); if (ssd->state.shroud_active) - WFIFO_STRING(s, 6, ""_s, 24); + fixed_95.char_name = CharName(); else - WFIFO_STRING(s, 6, ssd->status_key.name.to__actual(), 24); - WFIFOSET(s, clif_parse_func_table[0x95].len); + fixed_95.char_name = ssd->status_key.name; + send_fpacket<0x0095, 30>(s, fixed_95); PartyPair p; @@ -3639,30 +3651,28 @@ void clif_parse_GetCharNameRequest(Session *s, dumb_ptr<map_session_data> sd) if (send) { - WFIFOW(s, 0) = 0x195; - WFIFOL(s, 2) = unwrap<BlockId>(account_id); - WFIFO_STRING(s, 6, party_name, 24); - WFIFO_STRING(s, 30, ""_s, 24); - WFIFO_STRING(s, 54, ""_s, 24); - WFIFO_STRING(s, 78, ""_s, 24); // We send this value twice because the client expects it - WFIFOSET(s, clif_parse_func_table[0x195].len); - + Packet_Fixed<0x0195> fixed_195; + fixed_195.block_id = account_id; + fixed_195.party_name = party_name; + fixed_195.guild_name = ""_s; + fixed_195.guild_pos = ""_s; + fixed_195.guild_pos = ""_s; // We send this value twice because the client expects it + send_fpacket<0x0195, 102>(s, fixed_195); } if (pc_isGM(sd).satisfies(GmLevel::from(static_cast<uint32_t>(battle_config.hack_info_GM_level)))) { IP4Address ip = ssd->get_ip(); - WFIFOW(s, 0) = 0x20C; + Packet_Fixed<0x020c> fixed_20c; // Mask the IP using the char-server password if (battle_config.mask_ip_gms) ip = MD5_ip(ip); - WFIFOL(s, 2) = unwrap<BlockId>(account_id); - WFIFOIP(s, 6) = ip; - WFIFOSET(s, clif_parse_func_table[0x20C].len); + fixed_20c.block_id = account_id; + fixed_20c.ip = ip; + send_fpacket<0x020c, 10>(s, fixed_20c); } - } break; case BL::NPC: @@ -3670,18 +3680,18 @@ void clif_parse_GetCharNameRequest(Session *s, dumb_ptr<map_session_data> sd) NpcName name = bl->is_npc()->name; // [fate] elim hashed out/invisible names for the client auto it = std::find(name.begin(), name.end(), '#'); - WFIFO_STRING(s, 6, name.xislice_h(it), 24); - WFIFOSET(s, clif_parse_func_table[0x95].len); + fixed_95.char_name = stringish<CharName>(name.xislice_h(it)); + send_fpacket<0x0095, 30>(s, fixed_95); } break; case BL::MOB: { dumb_ptr<mob_data> md = bl->is_mob(); - nullpo_retv(md); + nullpo_retr(rv, md); - WFIFO_STRING(s, 6, md->name, 24); - WFIFOSET(s, clif_parse_func_table[0x95].len); + fixed_95.char_name = stringish<CharName>(md->name); + send_fpacket<0x0095, 30>(s, fixed_95); } break; default: @@ -3690,6 +3700,8 @@ void clif_parse_GetCharNameRequest(Session *s, dumb_ptr<map_session_data> sd) bl->bl_type, account_id); break; } + + return rv; } /*========================================== @@ -3700,19 +3712,22 @@ void clif_parse_GetCharNameRequest(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_GlobalMessage(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_GlobalMessage(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + AString repeat; + RecvResult rv = recv_packet_repeatonly<0x008c, 4, 1>(s, repeat); + if (rv != RecvResult::Complete) + return rv; - AString mbuf = clif_validate_chat(sd, ChatType::Global); + AString mbuf = clif_validate_chat(sd, ChatType::Global, repeat); if (!mbuf) { clif_displaymessage(s, "Your message could not be sent."_s); - return; + return rv; } if (is_atcommand(s, sd, mbuf, GmLevel())) - return; + return rv; if (!magic_message(sd, mbuf)) { @@ -3720,43 +3735,37 @@ void clif_parse_GlobalMessage(Session *s, dumb_ptr<map_session_data> sd) if (tmw_CheckChatSpam(sd, mbuf)) { clif_displaymessage(s, "Your message could not be sent."_s); - return; + return rv; } /* It's not a spell/magic message, so send the message to others. */ - size_t mbuf_size = mbuf.size() + 1; - uint8_t sendbuf[mbuf_size + 8]; - WBUFW(sendbuf, 0) = 0x8d; - WBUFW(sendbuf, 2) = mbuf_size + 8; /* Header(2) + length(2) + ID(4). */ - WBUFL(sendbuf, 4) = unwrap<BlockId>(sd->bl_id); - WBUF_STRING(sendbuf, 8, mbuf, mbuf_size); - - clif_send(sendbuf, mbuf_size + 8, sd, SendWho::AREA_CHAT_WOC); + Packet_Head<0x008d> head_8d; + head_8d.block_id = sd->bl_id; + XString repeat_8d = mbuf; + Buffer sendbuf = create_vpacket<0x008d, 8, 1>(head_8d, repeat_8d); + + clif_send(sendbuf, sd, SendWho::AREA_CHAT_WOC); } /* Send the message back to the speaker. */ - size_t len = RFIFOW(s, 2); - RFIFO_WFIFO_CLONE(s, s, len); - WFIFOW(s, 0) = 0x8e; - WFIFOSET(s, len); + send_packet_repeatonly<0x008e, 4, 1>(s, repeat); + + return rv; } void clif_message(dumb_ptr<block_list> bl, XString msg) { size_t msg_len = msg.size() + 1; - uint8_t buf[512]; - if (msg_len + 16 > 512) return; nullpo_retv(bl); - WBUFW(buf, 0) = 0x8d; - WBUFW(buf, 2) = msg_len + 8; - WBUFL(buf, 4) = unwrap<BlockId>(bl->bl_id); - WBUF_STRING(buf, 8, msg, msg_len); + Packet_Head<0x008d> head_8d; + head_8d.block_id = bl->bl_id; + Buffer buf = create_vpacket<0x008d, 8, 1>(head_8d, msg); - clif_send(buf, WBUFW(buf, 2), bl, SendWho::AREA); + clif_send(buf, bl, SendWho::AREA); } /*========================================== @@ -3764,16 +3773,17 @@ void clif_message(dumb_ptr<block_list> bl, XString msg) *------------------------------------------ */ static -void clif_parse_ChangeDir(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_ChangeDir(Session *s, dumb_ptr<map_session_data> sd) { - unsigned char buf[64]; + Packet_Fixed<0x009b> fixed; + RecvResult rv = recv_fpacket<0x009b, 5>(s, fixed); + if (rv != RecvResult::Complete) + return rv; - nullpo_retv(sd); - - // RFIFOW(fd, 2) and WBUFW(buf, 6) are always 0 + // RFIFOW(fd,2) and WBUFW(buf,6) are always 0 // TODO perhaps we could use that to remove this hack? DIR dir; - uint8_t client_dir = RFIFOB(s, 4); + uint8_t client_dir = fixed.client_dir; // the client uses a diffenent direction enum ... ugh switch (client_dir) { @@ -3786,21 +3796,22 @@ void clif_parse_ChangeDir(Session *s, dumb_ptr<map_session_data> sd) case 0 | 8: dir = DIR::E; break; // right case 1 | 8: dir = DIR::SE; break; default: - return; + return rv; } if (dir == sd->dir) - return; + return rv; pc_setdir(sd, dir); - WBUFW(buf, 0) = 0x9c; - WBUFL(buf, 2) = unwrap<BlockId>(sd->bl_id); - WBUFW(buf, 6) = 0; - WBUFB(buf, 8) = client_dir; + Packet_Fixed<0x009c> fixed_9c; + fixed_9c.block_id = sd->bl_id; + fixed_9c.client_dir = client_dir; + Buffer buf = create_fpacket<0x009c, 9>(fixed_9c); - clif_send(buf, clif_parse_func_table[0x9c].len, sd, SendWho::AREA_WOS); + clif_send(buf, sd, SendWho::AREA_WOS); + return rv; } /*========================================== @@ -3808,23 +3819,27 @@ void clif_parse_ChangeDir(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_Emotion(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_Emotion(Session *s, dumb_ptr<map_session_data> sd) { - unsigned char buf[64]; - - nullpo_retv(sd); + Packet_Fixed<0x00bf> fixed; + RecvResult rv = recv_fpacket<0x00bf, 3>(s, fixed); + if (rv != RecvResult::Complete) + return rv; if (battle_config.basic_skill_check == 0 || pc_checkskill(sd, SkillID::NV_EMOTE) >= 1) { - uint8_t emote = RFIFOB(s, 2); - WBUFW(buf, 0) = 0xc0; - WBUFL(buf, 2) = unwrap<BlockId>(sd->bl_id); - WBUFB(buf, 6) = emote; - clif_send(buf, clif_parse_func_table[0xc0].len, sd, SendWho::AREA); + uint8_t emote = fixed.emote; + Packet_Fixed<0x00c0> fixed_c0; + fixed_c0.block_id = sd->bl_id; + fixed_c0.type = emote; + Buffer buf = create_fpacket<0x00c0, 7>(fixed_c0); + clif_send(buf, sd, SendWho::AREA); } else clif_skill_fail(sd, SkillID::ONE, 0, 1); + + return rv; } /*========================================== @@ -3832,11 +3847,18 @@ void clif_parse_Emotion(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_HowManyConnections(Session *s, dumb_ptr<map_session_data>) +RecvResult clif_parse_HowManyConnections(Session *s, dumb_ptr<map_session_data>) { - WFIFOW(s, 0) = 0xc2; - WFIFOL(s, 2) = map_getusers(); - WFIFOSET(s, clif_parse_func_table[0xc2].len); + Packet_Fixed<0x00c1> fixed; + RecvResult rv = recv_fpacket<0x00c1, 2>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + Packet_Fixed<0x00c2> fixed_c2; + fixed_c2.users = map_getusers(); + send_fpacket<0x00c2, 6>(s, fixed_c2); + + return rv; } /*========================================== @@ -3844,64 +3866,69 @@ void clif_parse_HowManyConnections(Session *s, dumb_ptr<map_session_data>) *------------------------------------------ */ static -void clif_parse_ActionRequest(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_ActionRequest(Session *s, dumb_ptr<map_session_data> sd) { - unsigned char buf[64]; - int action_type; - BlockId target_id; + Packet_Fixed<0x0089> fixed; + RecvResult rv = recv_fpacket<0x0089, 7>(s, fixed); + if (rv != RecvResult::Complete) + return rv; - nullpo_retv(sd); + DamageType action_type; + BlockId target_id; if (pc_isdead(sd)) { clif_clearchar(sd, BeingRemoveWhy::DEAD); - return; + return rv; } if (sd->npc_id || bool(sd->opt1) || sd->state.storage_open) - return; + return rv; tick_t tick = gettick(); pc_stop_walking(sd, 0); pc_stopattack(sd); - target_id = wrap<BlockId>(RFIFOL(s, 2)); - action_type = RFIFOB(s, 6); + target_id = fixed.target_id; + action_type = fixed.action; switch (action_type) { - case 0x00: // once attack - case 0x07: // continuous attack + case DamageType::NORMAL: + case DamageType::CONTINUOUS: if (bool(sd->status.option & Option::HIDE)) - return; + return rv; if (!battle_config.skill_delay_attack_enable) { if (tick < sd->canact_tick) { clif_skill_fail(sd, SkillID::ONE, 4, 0); - return; + return rv; } } if (sd->invincible_timer) pc_delinvincibletimer(sd); sd->attacktarget = BlockId(); - pc_attack(sd, target_id, action_type != 0); + pc_attack(sd, target_id, action_type != DamageType::NORMAL); break; - case 0x02: // sitdown + case DamageType::SIT: pc_stop_walking(sd, 1); pc_setsit(sd); clif_sitting(s, sd); break; - case 0x03: // standup + case DamageType::STAND: pc_setstand(sd); - WBUFW(buf, 0) = 0x8a; - WBUFL(buf, 2) = unwrap<BlockId>(sd->bl_id); - WBUFB(buf, 26) = 3; - clif_send(buf, clif_parse_func_table[0x8a].len, sd, SendWho::AREA); + Packet_Fixed<0x008a> fixed_8a; + fixed_8a.src_id = sd->bl_id; + fixed_8a.damage_type = DamageType::STAND; + Buffer buf = create_fpacket<0x008a, 29>(fixed_8a); + clif_send(buf, sd, SendWho::AREA); break; } + + return rv; } /*========================================== @@ -3909,11 +3936,14 @@ void clif_parse_ActionRequest(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_Restart(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_Restart(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + Packet_Fixed<0x00b2> fixed; + RecvResult rv = recv_fpacket<0x00b2, 3>(s, fixed); + if (rv != RecvResult::Complete) + return rv; - switch (RFIFOB(s, 2)) + switch (fixed.flag) { case 0x00: if (pc_isdead(sd)) @@ -3943,13 +3973,15 @@ void clif_parse_Restart(Session *s, dumb_ptr<map_session_data> sd) } else { - WFIFOW(s, 0) = 0x18b; - WFIFOW(s, 2) = 1; + Packet_Fixed<0x018b> fixed_18b; + fixed_18b.okay = 1; - WFIFOSET(s, clif_parse_func_table[0x018b].len); + send_fpacket<0x018b, 4>(s, fixed_18b); } break; } + + return rv; } /*========================================== @@ -3963,29 +3995,33 @@ void clif_parse_Restart(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_Wis(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_Wis(Session *s, dumb_ptr<map_session_data> sd) { - dumb_ptr<map_session_data> dstsd = NULL; + Packet_Head<0x0096> head; + AString repeat; + RecvResult rv = recv_vpacket<0x0096, 28, 1>(s, head, repeat); + if (rv != RecvResult::Complete) + return rv; - nullpo_retv(sd); + dumb_ptr<map_session_data> dstsd = NULL; - AString mbuf = clif_validate_chat(sd, ChatType::Whisper); + AString mbuf = clif_validate_chat(sd, ChatType::Whisper, repeat); if (!mbuf) { clif_displaymessage(s, "Your message could not be sent."_s); - return; + return rv; } if (is_atcommand(s, sd, mbuf, GmLevel())) { - return; + return rv; } /* Don't send chat that results in an automatic ban. */ if (tmw_CheckChatSpam(sd, mbuf)) { clif_displaymessage(s, "Your message could not be sent."_s); - return; + return rv; } /* @@ -3994,7 +4030,7 @@ void clif_parse_Wis(Session *s, dumb_ptr<map_session_data> sd) * conflict (for instance, "Test" versus "test"), the char-server must * settle the discrepancy. */ - CharName tname = stringish<CharName>(RFIFO_STRING<24>(s, 4)); + CharName tname = head.target_name; if (!(dstsd = map_nick2sd(tname)) || dstsd->status_key.name != tname) intif_wis_message(sd, tname, mbuf); @@ -4018,6 +4054,8 @@ void clif_parse_Wis(Session *s, dumb_ptr<map_session_data> sd) } } } + + return rv; } /*========================================== @@ -4025,36 +4063,41 @@ void clif_parse_Wis(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_TakeItem(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_TakeItem(Session *s, dumb_ptr<map_session_data> sd) { - dumb_ptr<flooritem_data> fitem; + Packet_Fixed<0x009f> fixed; + RecvResult rv = recv_fpacket<0x009f, 6>(s, fixed); + if (rv != RecvResult::Complete) + return rv; - nullpo_retv(sd); + dumb_ptr<flooritem_data> fitem; - BlockId map_object_id = wrap<BlockId>(RFIFOL(s, 2)); + BlockId map_object_id = fixed.object_id; fitem = map_id_is_item(map_object_id); if (pc_isdead(sd)) { clif_clearchar(sd, BeingRemoveWhy::DEAD); - return; + return rv; } if (sd->npc_id || sd->opt1 != Opt1::ZERO) //会話禁止 - return; + return rv; if (fitem == NULL || fitem->bl_m != sd->bl_m) - return; + return rv; if (abs(sd->bl_x - fitem->bl_x) >= 2 || abs(sd->bl_y - fitem->bl_y) >= 2) - return; // too far away to pick up + return rv; // too far away to pick up if (sd->state.shroud_active && sd->state.shroud_disappears_on_pickup) magic_unshroud(sd); pc_takeitem(sd, fitem); + + return rv; } /*========================================== @@ -4062,33 +4105,38 @@ void clif_parse_TakeItem(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_DropItem(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_DropItem(Session *s, dumb_ptr<map_session_data> sd) { - int item_index, item_amount; + Packet_Fixed<0x00a2> fixed; + RecvResult rv = recv_fpacket<0x00a2, 6>(s, fixed); + if (rv != RecvResult::Complete) + return rv; - nullpo_retv(sd); + int item_index, item_amount; if (pc_isdead(sd)) { clif_clearchar(sd, BeingRemoveWhy::DEAD); - return; + return rv; } if (sd->bl_m->flag.get(MapFlag::NO_PLAYER_DROPS)) { clif_displaymessage(sd->sess, "Can't drop items here."_s); - return; + return rv; } if (sd->npc_id || sd->opt1 != Opt1::ZERO) { clif_displaymessage(sd->sess, "Can't drop items right now."_s); - return; + return rv; } - item_index = RFIFOW(s, 2) - 2; - item_amount = RFIFOW(s, 4); + item_index = fixed.ioff2 - 2; + item_amount = fixed.amount; pc_dropitem(sd, item_index, item_amount); + + return rv; } /*========================================== @@ -4096,23 +4144,28 @@ void clif_parse_DropItem(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_UseItem(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_UseItem(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + Packet_Fixed<0x00a7> fixed; + RecvResult rv = recv_fpacket<0x00a7, 8>(s, fixed); + if (rv != RecvResult::Complete) + return rv; if (pc_isdead(sd)) { clif_clearchar(sd, BeingRemoveWhy::DEAD); - return; + return rv; } if (sd->npc_id || sd->opt1 != Opt1::ZERO) //会話禁止 - return; + return rv; if (sd->invincible_timer) pc_delinvincibletimer(sd); - pc_useitem(sd, RFIFOW(s, 2) - 2); + pc_useitem(sd, fixed.ioff2 - 2); + + return rv; } /*========================================== @@ -4120,30 +4173,35 @@ void clif_parse_UseItem(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_EquipItem(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_EquipItem(Session *s, dumb_ptr<map_session_data> sd) { - int index; + Packet_Fixed<0x00a9> fixed; + RecvResult rv = recv_fpacket<0x00a9, 6>(s, fixed); + if (rv != RecvResult::Complete) + return rv; - nullpo_retv(sd); + int index; if (pc_isdead(sd)) { clif_clearchar(sd, BeingRemoveWhy::DEAD); - return; + return rv; } - index = RFIFOW(s, 2) - 2; + index = fixed.ioff2 - 2; if (sd->npc_id) - return; + return rv; if (sd->inventory_data[index]) { - EPOS epos = EPOS(RFIFOW(s, 4)); + EPOS epos = fixed.epos_ignored; if (sd->inventory_data[index]->type == ItemType::ARROW) epos = EPOS::ARROW; // Note: the EPOS argument to pc_equipitem is actually ignored pc_equipitem(sd, index, epos); } + + return rv; } /*========================================== @@ -4151,23 +4209,28 @@ void clif_parse_EquipItem(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_UnequipItem(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_UnequipItem(Session *s, dumb_ptr<map_session_data> sd) { - int index; + Packet_Fixed<0x00ab> fixed; + RecvResult rv = recv_fpacket<0x00ab, 4>(s, fixed); + if (rv != RecvResult::Complete) + return rv; - nullpo_retv(sd); + int index; if (pc_isdead(sd)) { clif_clearchar(sd, BeingRemoveWhy::DEAD); - return; + return rv; } - index = RFIFOW(s, 2) - 2; + index = fixed.ioff2 - 2; if (sd->npc_id || sd->opt1 != Opt1::ZERO) - return; + return rv; pc_unequipitem(sd, index, CalcStatus::NOW); + + return rv; } /*========================================== @@ -4175,18 +4238,23 @@ void clif_parse_UnequipItem(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_NpcClicked(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_NpcClicked(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + Packet_Fixed<0x0090> fixed; + RecvResult rv = recv_fpacket<0x0090, 7>(s, fixed); + if (rv != RecvResult::Complete) + return rv; if (pc_isdead(sd)) { clif_clearchar(sd, BeingRemoveWhy::DEAD); - return; + return rv; } if (sd->npc_id) - return; - npc_click(sd, wrap<BlockId>(RFIFOL(s, 2))); + return rv; + npc_click(sd, fixed.block_id); + + return rv; } /*========================================== @@ -4194,9 +4262,16 @@ void clif_parse_NpcClicked(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_NpcBuySellSelected(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_NpcBuySellSelected(Session *s, dumb_ptr<map_session_data> sd) { - npc_buysellsel(sd, wrap<BlockId>(RFIFOL(s, 2)), RFIFOB(s, 6)); + Packet_Fixed<0x00c5> fixed; + RecvResult rv = recv_fpacket<0x00c5, 7>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + npc_buysellsel(sd, fixed.block_id, fixed.type); + + return rv; } /*========================================== @@ -4204,17 +4279,20 @@ void clif_parse_NpcBuySellSelected(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_NpcBuyListSend(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_NpcBuyListSend(Session *s, dumb_ptr<map_session_data> sd) { - int n = (RFIFOW(s, 2) - 4) / 4; - // really an array of pairs of uint16_t - const uint16_t *item_list = static_cast<const uint16_t *>(RFIFOP(s, 4)); + std::vector<Packet_Repeat<0x00c8>> repeat; + RecvResult rv = recv_packet_repeatonly<0x00c8, 4, 4>(s, repeat); + if (rv != RecvResult::Complete) + return rv; + + int fail = npc_buylist(sd, repeat); - int fail = npc_buylist(sd, n, item_list); + Packet_Fixed<0x00ca> fixed_ca; + fixed_ca.fail = fail; + send_fpacket<0x00ca, 3>(s, fixed_ca); - WFIFOW(s, 0) = 0xca; - WFIFOB(s, 2) = fail; - WFIFOSET(s, clif_parse_func_table[0xca].len); + return rv; } /*========================================== @@ -4222,17 +4300,20 @@ void clif_parse_NpcBuyListSend(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_NpcSellListSend(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_NpcSellListSend(Session *s, dumb_ptr<map_session_data> sd) { - int n = (RFIFOW(s, 2) - 4) / 4; - // really an array of pairs of uint16_t - const uint16_t *item_list = static_cast<const uint16_t *>(RFIFOP(s, 4)); + std::vector<Packet_Repeat<0x00c9>> repeat; + RecvResult rv = recv_packet_repeatonly<0x00c9, 4, 4>(s, repeat); + if (rv != RecvResult::Complete) + return rv; + + int fail = npc_selllist(sd, repeat); - int fail = npc_selllist(sd, n, item_list); + Packet_Fixed<0x00cb> fixed_cb; + fixed_cb.fail = fail; + send_fpacket<0x00cb, 3>(s, fixed_cb); - WFIFOW(s, 0) = 0xcb; - WFIFOB(s, 2) = fail; - WFIFOSET(s, clif_parse_func_table[0xcb].len); + return rv; } /*========================================== @@ -4240,17 +4321,22 @@ void clif_parse_NpcSellListSend(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_TradeRequest(Session *, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_TradeRequest(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + Packet_Fixed<0x00e4> fixed; + RecvResult rv = recv_fpacket<0x00e4, 6>(s, fixed); + if (rv != RecvResult::Complete) + return rv; if (battle_config.basic_skill_check == 0 || pc_checkskill(sd, SkillID::NV_TRADE) >= 1) { - trade_traderequest(sd, wrap<BlockId>(RFIFOL(sd->sess, 2))); + trade_traderequest(sd, fixed.block_id); } else clif_skill_fail(sd, SkillID::ONE, 0, 0); + + return rv; } /*========================================== @@ -4258,11 +4344,16 @@ void clif_parse_TradeRequest(Session *, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_TradeAck(Session *, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_TradeAck(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + Packet_Fixed<0x00e6> fixed; + RecvResult rv = recv_fpacket<0x00e6, 3>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + trade_tradeack(sd, fixed.type); - trade_tradeack(sd, RFIFOB(sd->sess, 2)); + return rv; } /*========================================== @@ -4270,11 +4361,16 @@ void clif_parse_TradeAck(Session *, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_TradeAddItem(Session *, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_TradeAddItem(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + Packet_Fixed<0x00e8> fixed; + RecvResult rv = recv_fpacket<0x00e8, 8>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + trade_tradeadditem(sd, fixed.zeny_or_ioff2, fixed.amount); - trade_tradeadditem(sd, RFIFOW(sd->sess, 2), RFIFOL(sd->sess, 4)); + return rv; } /*========================================== @@ -4282,9 +4378,16 @@ void clif_parse_TradeAddItem(Session *, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_TradeOk(Session *, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_TradeOk(Session *s, dumb_ptr<map_session_data> sd) { + Packet_Fixed<0x00eb> fixed; + RecvResult rv = recv_fpacket<0x00eb, 2>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + trade_tradeok(sd); + + return rv; } /*========================================== @@ -4292,9 +4395,16 @@ void clif_parse_TradeOk(Session *, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_TradeCansel(Session *, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_TradeCansel(Session *s, dumb_ptr<map_session_data> sd) { + Packet_Fixed<0x00ed> fixed; + RecvResult rv = recv_fpacket<0x00ed, 2>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + trade_tradecancel(sd); + + return rv; } /*========================================== @@ -4302,9 +4412,16 @@ void clif_parse_TradeCansel(Session *, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_TradeCommit(Session *, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_TradeCommit(Session *s, dumb_ptr<map_session_data> sd) { + Packet_Fixed<0x00ef> fixed; + RecvResult rv = recv_fpacket<0x00ef, 2>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + trade_tradecommit(sd); + + return rv; } /*========================================== @@ -4312,9 +4429,16 @@ void clif_parse_TradeCommit(Session *, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_StopAttack(Session *, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_StopAttack(Session *s, dumb_ptr<map_session_data> sd) { + Packet_Fixed<0x0118> fixed; + RecvResult rv = recv_fpacket<0x0118, 2>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + pc_stopattack(sd); + + return rv; } /*========================================== @@ -4322,9 +4446,16 @@ void clif_parse_StopAttack(Session *, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_StatusUp(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_StatusUp(Session *s, dumb_ptr<map_session_data> sd) { - pc_statusup(sd, static_cast<SP>(RFIFOW(s, 2))); + Packet_Fixed<0x00bb> fixed; + RecvResult rv = recv_fpacket<0x00bb, 5>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + pc_statusup(sd, fixed.asp); + + return rv; } /*========================================== @@ -4332,9 +4463,16 @@ void clif_parse_StatusUp(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_SkillUp(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_SkillUp(Session *s, dumb_ptr<map_session_data> sd) { - pc_skillup(sd, SkillID(RFIFOW(s, 2))); + Packet_Fixed<0x0112> fixed; + RecvResult rv = recv_fpacket<0x0112, 4>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + pc_skillup(sd, fixed.skill_id); + + return rv; } /*========================================== @@ -4342,12 +4480,17 @@ void clif_parse_SkillUp(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_NpcSelectMenu(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_NpcSelectMenu(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + Packet_Fixed<0x00b8> fixed; + RecvResult rv = recv_fpacket<0x00b8, 7>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + sd->npc_menu = fixed.menu_entry; + map_scriptcont(sd, fixed.npc_id); - sd->npc_menu = RFIFOB(s, 6); - map_scriptcont(sd, wrap<BlockId>(RFIFOL(s, 2))); + return rv; } /*========================================== @@ -4355,9 +4498,16 @@ void clif_parse_NpcSelectMenu(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_NpcNextClicked(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_NpcNextClicked(Session *s, dumb_ptr<map_session_data> sd) { - map_scriptcont(sd, wrap<BlockId>(RFIFOL(s, 2))); + Packet_Fixed<0x00b9> fixed; + RecvResult rv = recv_fpacket<0x00b9, 6>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + map_scriptcont(sd, fixed.npc_id); + + return rv; } /*========================================== @@ -4365,12 +4515,17 @@ void clif_parse_NpcNextClicked(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_NpcAmountInput(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_NpcAmountInput(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + Packet_Fixed<0x0143> fixed; + RecvResult rv = recv_fpacket<0x0143, 10>(s, fixed); + if (rv != RecvResult::Complete) + return rv; - sd->npc_amount = RFIFOL(s, 6); - map_scriptcont(sd, wrap<BlockId>(RFIFOL(s, 2))); + sd->npc_amount = fixed.input_int_value; + map_scriptcont(sd, fixed.block_id); + + return rv; } /*========================================== @@ -4380,22 +4535,19 @@ void clif_parse_NpcAmountInput(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_NpcStringInput(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_NpcStringInput(Session *s, dumb_ptr<map_session_data> sd) { - int len; - nullpo_retv(sd); + Packet_Head<0x01d5> head; + AString repeat; + RecvResult rv = recv_vpacket<0x01d5, 8, 1>(s, head, repeat); + if (rv != RecvResult::Complete) + return rv; - len = RFIFOW(s, 2) - 8; + sd->npc_str = repeat; - /* - * If we check for equal to 0, too, we'll freeze clients that send (or - * claim to have sent) an "empty" message. - */ - if (len < 0) - return; - sd->npc_str = RFIFO_STRING(s, 8, len); + map_scriptcont(sd, head.block_id); - map_scriptcont(sd, wrap<BlockId>(RFIFOL(s, 4))); + return rv; } /*========================================== @@ -4403,9 +4555,16 @@ void clif_parse_NpcStringInput(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_NpcCloseClicked(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_NpcCloseClicked(Session *s, dumb_ptr<map_session_data> sd) { - map_scriptcont(sd, wrap<BlockId>(RFIFOL(s, 2))); + Packet_Fixed<0x0146> fixed; + RecvResult rv = recv_fpacket<0x0146, 6>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + map_scriptcont(sd, fixed.block_id); + + return rv; } /*========================================== @@ -4413,21 +4572,26 @@ void clif_parse_NpcCloseClicked(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_MoveToKafra(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_MoveToKafra(Session *s, dumb_ptr<map_session_data> sd) { - int item_index, item_amount; + Packet_Fixed<0x00f3> fixed; + RecvResult rv = recv_fpacket<0x00f3, 8>(s, fixed); + if (rv != RecvResult::Complete) + return rv; - nullpo_retv(sd); + int item_index, item_amount; - item_index = RFIFOW(s, 2) - 2; - item_amount = RFIFOL(s, 4); + item_index = fixed.ioff2 - 2; + item_amount = fixed.amount; if ((sd->npc_id && !sd->npc_flags.storage) || sd->trade_partner || !sd->state.storage_open) - return; + return rv; if (sd->state.storage_open) storage_storageadd(sd, item_index, item_amount); + + return rv; } /*========================================== @@ -4435,21 +4599,26 @@ void clif_parse_MoveToKafra(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_MoveFromKafra(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_MoveFromKafra(Session *s, dumb_ptr<map_session_data> sd) { - int item_index, item_amount; + Packet_Fixed<0x00f5> fixed; + RecvResult rv = recv_fpacket<0x00f5, 8>(s, fixed); + if (rv != RecvResult::Complete) + return rv; - nullpo_retv(sd); + int item_index, item_amount; - item_index = RFIFOW(s, 2) - 1; - item_amount = RFIFOL(s, 4); + item_index = fixed.soff1 - 1; + item_amount = fixed.amount; if ((sd->npc_id && !sd->npc_flags.storage) || sd->trade_partner || !sd->state.storage_open) - return; + return rv; if (sd->state.storage_open) storage_storageget(sd, item_index, item_amount); + + return rv; } /*========================================== @@ -4457,12 +4626,17 @@ void clif_parse_MoveFromKafra(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_CloseKafra(Session *, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_CloseKafra(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + Packet_Fixed<0x00f7> fixed; + RecvResult rv = recv_fpacket<0x00f7, 2>(s, fixed); + if (rv != RecvResult::Complete) + return rv; if (sd->state.storage_open) storage_storageclose(sd); + + return rv; } /*========================================== @@ -4473,16 +4647,23 @@ void clif_parse_CloseKafra(Session *, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_CreateParty(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_CreateParty(Session *s, dumb_ptr<map_session_data> sd) { + Packet_Fixed<0x00f9> fixed; + RecvResult rv = recv_fpacket<0x00f9, 26>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + if (battle_config.basic_skill_check == 0 || pc_checkskill(sd, SkillID::NV_PARTY) >= 2) { - PartyName name = stringish<PartyName>(RFIFO_STRING<24>(s, 2)); + PartyName name = fixed.party_name; party_create(sd, name); } else clif_skill_fail(sd, SkillID::ONE, 0, 4); + + return rv; } /*========================================== @@ -4493,9 +4674,16 @@ void clif_parse_CreateParty(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_PartyInvite(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_PartyInvite(Session *s, dumb_ptr<map_session_data> sd) { - party_invite(sd, wrap<AccountId>(RFIFOL(s, 2))); + Packet_Fixed<0x00fc> fixed; + RecvResult rv = recv_fpacket<0x00fc, 6>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + party_invite(sd, fixed.account_id); + + return rv; } /*========================================== @@ -4506,18 +4694,25 @@ void clif_parse_PartyInvite(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_ReplyPartyInvite(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_ReplyPartyInvite(Session *s, dumb_ptr<map_session_data> sd) { + Packet_Fixed<0x00ff> fixed; + RecvResult rv = recv_fpacket<0x00ff, 10>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + if (battle_config.basic_skill_check == 0 || pc_checkskill(sd, SkillID::NV_PARTY) >= 1) { - party_reply_invite(sd, wrap<AccountId>(RFIFOL(s, 2)), RFIFOL(s, 6)); + party_reply_invite(sd, fixed.account_id, fixed.flag); } else { - party_reply_invite(sd, wrap<AccountId>(RFIFOL(s, 2)), 0); + party_reply_invite(sd, fixed.account_id, 0); clif_skill_fail(sd, SkillID::ONE, 0, 4); } + + return rv; } /*========================================== @@ -4525,9 +4720,16 @@ void clif_parse_ReplyPartyInvite(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_LeaveParty(Session *, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_LeaveParty(Session *s, dumb_ptr<map_session_data> sd) { + Packet_Fixed<0x0100> fixed; + RecvResult rv = recv_fpacket<0x0100, 2>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + party_leave(sd); + + return rv; } /*========================================== @@ -4535,11 +4737,18 @@ void clif_parse_LeaveParty(Session *, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_RemovePartyMember(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_RemovePartyMember(Session *s, dumb_ptr<map_session_data> sd) { - AccountId account_id = wrap<AccountId>(RFIFOL(s, 2)); - // unused RFIFO_STRING<24>(fd, 6); + Packet_Fixed<0x0103> fixed; + RecvResult rv = recv_fpacket<0x0103, 30>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + AccountId account_id = fixed.account_id; + // unused fixed.unusedchar_name; party_removemember(sd, account_id); + + return rv; } /*========================================== @@ -4547,9 +4756,16 @@ void clif_parse_RemovePartyMember(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_PartyChangeOption(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_PartyChangeOption(Session *s, dumb_ptr<map_session_data> sd) { - party_changeoption(sd, RFIFOW(s, 2), RFIFOW(s, 4)); + Packet_Fixed<0x0102> fixed; + RecvResult rv = recv_fpacket<0x0102, 6>(s, fixed); + if (rv != RecvResult::Complete) + return rv; + + party_changeoption(sd, fixed.exp, fixed.item); + + return rv; } /*========================================== @@ -4561,28 +4777,33 @@ void clif_parse_PartyChangeOption(Session *s, dumb_ptr<map_session_data> sd) *------------------------------------------ */ static -void clif_parse_PartyMessage(Session *s, dumb_ptr<map_session_data> sd) +RecvResult clif_parse_PartyMessage(Session *s, dumb_ptr<map_session_data> sd) { - nullpo_retv(sd); + AString repeat; + RecvResult rv = recv_packet_repeatonly<0x0108, 4, 1>(s, repeat); + if (rv != RecvResult::Complete) + return rv; - AString mbuf = clif_validate_chat(sd, ChatType::Party); + AString mbuf = clif_validate_chat(sd, ChatType::Party, repeat); if (!mbuf) { clif_displaymessage(s, "Your message could not be sent."_s); - return; + return rv; } if (is_atcommand(s, sd, mbuf, GmLevel())) - return; + return rv; /* Don't send chat that results in an automatic ban. */ if (tmw_CheckChatSpam(sd, mbuf)) { clif_displaymessage(s, "Your message could not be sent."_s); - return; + return rv; } party_send_message(sd, mbuf); + + return rv; } func_table clif_parse_func_table[0x0220] = @@ -5135,8 +5356,25 @@ func_table clif_parse_func_table[0x0220] = // Checks for packet flooding static -int clif_check_packet_flood(Session *s, int cmd) +uint16_t clif_check_packet_flood(Session *s, int cmd) { + uint16_t len = clif_parse_func_table[cmd].len_unused; + if (len == VAR) + { + Little16 netlen; + if (!packet_fetch(s, 2, reinterpret_cast<Byte *>(&netlen), 2)) + { + return 0; + } + if (!network_to_native(&len, netlen)) + { + s->set_eof(); + return 0; + } + } + if (packet_avail(s) < len) + return 0; + dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get())); tick_t tick = gettick(); @@ -5162,25 +5400,23 @@ int clif_check_packet_flood(Session *s, int cmd) // ActionRequest - attacks are allowed a faster rate than sit/stand if (cmd == 0x89) { - int action_type = RFIFOB(s, 6); - if (action_type == 0x00 || action_type == 0x07) + DamageType damage_type; + Byte action_type; + if (!packet_fetch(s, 6, &action_type, 1)) + return 0; + if (!network_to_native(&damage_type, action_type)) + { + s->set_eof(); + return 0; + } + if (damage_type == DamageType::NORMAL || damage_type == DamageType::CONTINUOUS) rate = std::chrono::milliseconds(20); else rate = std::chrono::seconds(1); } -// Restore this code when mana1.0 is released -#if 0 - // ChangeDir - only apply limit if not walking - if (cmd == 0x9b) - { - // .29 clients spam this packet when walking into a blocked tile - if (RFIFOB(fd, 4) == sd->dir || sd->walktimer != -1) - return 0; - - rate = 500; - } -#endif + // Restore this code when mana1.0 is released + // nope, nuh-uh // They are flooding if (tick < sd->flood_rates[cmd] + rate) @@ -5202,12 +5438,12 @@ int clif_check_packet_flood(Session *s, int cmd) if (battle_config.packet_spam_kick) { s->set_eof(); - return 1; + return len; } sd->packet_flood_in = 0; } - return 1; + return len; } sd->flood_rates[cmd] = tick; @@ -5231,7 +5467,7 @@ void WARN_MALFORMED_MSG(dumb_ptr<map_session_data> sd, ZString msg) * @return a dynamically allocated copy of the message, or empty string upon failure */ static -AString clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type) +AString clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type, XString buf) { nullpo_retr(AString(), sd); /* @@ -5242,54 +5478,8 @@ AString clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type) return AString(); Session *s = sd->sess; - size_t msg_len = RFIFOW(s, 2) - 4; size_t name_len = sd->status_key.name.to__actual().size(); - /* - * At least one character is required in all instances. - * Notes for length checks: - * - * For all types, header (2) + length (2) is considered empty. - * For type 1, the message must be longer than the maximum name length (24) - * to be valid. - * For type 2, the message must be longer than the sender's name length - * plus the length of the separator (" : "). - */ - size_t min_len = - (type == ChatType::Whisper) ? 24 - : (type == ChatType::Global) ? name_len + 3 - : 0; - - /* The player just sent the header (2) and length (2) words. */ - if (!msg_len) - { - WARN_MALFORMED_MSG(sd, "no message sent"_s); - return AString(); - } - - /* The client sent (or claims to have sent) an empty message. */ - if (msg_len == min_len) - { - WARN_MALFORMED_MSG(sd, "empty message"_s); - return AString(); - } - - /* The protocol specifies that the target must be 24 bytes long. */ - if (type == ChatType::Whisper && msg_len < min_len) - { - /* Disallow malformed messages. */ - clif_setwaitclose(s); - WARN_MALFORMED_MSG(sd, "illegal target name"_s); - return AString(); - } - - size_t pstart = 4; - size_t buf_len = msg_len; - if (type == ChatType::Whisper) - { - pstart += 24; - buf_len -= 24; - } - AString pbuf = RFIFO_STRING(s, pstart, buf_len); + XString pbuf = buf; /* * The client attempted to exceed the maximum message length. @@ -5298,7 +5488,8 @@ AString clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type) * is truncated. But the previous behavior was to drop the message, so * we'll do that, too. */ - if (buf_len >= battle_config.chat_maxline) + // TODO this cuts global chat short by (name_length + 3) + if (buf.size() >= battle_config.chat_maxline) { WARN_MALFORMED_MSG(sd, "exceeded maximum message length"_s); return AString(); @@ -5329,19 +5520,39 @@ AString clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type) static void clif_parse(Session *s) { - int packet_len = 0, cmd = 0; + // old code: + // no while loop (can hang if more than one packet) + // handles 0x7530 and 0x7532 specially, also 0x0072 + // checks packet length table + // checks rate limiter + // dispatches to actual function, unchecked + // interstitial code: + // introduces while loop + // checks rate limiter + // dispatches to actual function + // if incomplete, unchecks rate limiter + // if error, close socket + // future code: + // hoists while loop + // treats all packets as variable-length, except a hard-coded list + // reads packet of that length unconditionally into a buffer + // does rate-limit check (hoisted?) + // dispatches to actual function + // if error, close socket + dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get())); if (!sd || (sd && !sd->state.auth)) { - if (RFIFOREST(s) < 2) - { // too small a packet disconnect - s->set_eof(); - } - if (RFIFOW(s, 0) != 0x72 && RFIFOW(s, 0) != 0x7530) + uint16_t packet_id; + if (!packet_peek_id(s, &packet_id)) + return; + + if (packet_id != 0x0072 && packet_id != 0x7530) { // first packet must be auth or finger s->set_eof(); + return; } } @@ -5350,95 +5561,84 @@ void clif_parse(Session *s) s->set_eof(); return; } - - if (RFIFOREST(s) < 2) - return; // Too small (no packet number) - - cmd = RFIFOW(s, 0); - - // 管理用パケット処理 - if (cmd >= 30000) + if (sd && sd->state.auth == 1 && sd->state.waitingdisconnect == 1) { - switch (cmd) - { - case 0x7530: // Athena情報所得 - WFIFOW(s, 0) = 0x7531; - WFIFO_STRUCT(s, 2, CURRENT_MAP_SERVER_VERSION); - WFIFOSET(s, 10); - RFIFOSKIP(s, 2); - break; - case 0x7532: // 接続の切断 - s->set_eof(); - break; - } + packet_discard(s, packet_avail(s)); return; } - else if (cmd >= 0x200) - return; - // パケット長を計算 - packet_len = clif_parse_func_table[cmd].len; - if (packet_len == VAR) + uint16_t packet_id; + RecvResult rv = RecvResult::Complete; + while (rv == RecvResult::Complete && packet_peek_id(s, &packet_id)) { - if (RFIFOREST(s) < 4) + switch (packet_id) { - return; // Runt packet (variable length without a length sent) + case 0x7530: + { + Packet_Fixed<0x7530> fixed; + rv = recv_fpacket<0x7530, 2>(s, fixed); + if (rv != RecvResult::Complete) + break; + + Packet_Fixed<0x7531> fixed_31; + fixed_31.version = CURRENT_MAP_SERVER_VERSION; + send_fpacket<0x7531, 10>(s, fixed_31); + break; + } + case 0x7532: + { + Packet_Fixed<0x7532> fixed; + rv = recv_fpacket<0x7532, 2>(s, fixed); + if (rv != RecvResult::Complete) + break; + + s->set_eof(); + break; + } } - packet_len = RFIFOW(s, 2); - if (packet_len < 4 || packet_len > 32768) + if (packet_id < 0x0220) { - s->set_eof(); - return; // Runt packet (variable out of bounds) + if (uint16_t len = clif_check_packet_flood(s, packet_id)) + { + // Packet flood: skip packet + packet_discard(s, len); + rv = RecvResult::Complete; + } + else + { + clif_func func = clif_parse_func_table[packet_id].func; + if (!func) + goto unknown_packet; + rv = func(s, sd); + } } + else + goto unknown_packet; } - if (RFIFOREST(s) < packet_len) - { - return; // Runt packet (sent legnth is too small) - } - - if (sd && sd->state.auth == 1 && sd->state.waitingdisconnect == 1) - { // 切断待ちの場合パケットを処理しない - - } - else if (clif_parse_func_table[cmd].func) - { - if (clif_check_packet_flood(s, cmd)) - { - // Flood triggered. Skip packet. - RFIFOSKIP(sd->sess, packet_len); - return; - } + if (rv == RecvResult::Error) + s->set_eof(); + return; - clif_parse_func_table[cmd].func(s, sd); - } - else +unknown_packet: { - // 不明なパケット if (battle_config.error_log) { if (s) - PRINTF("\nclif_parse: session #%d, packet 0x%x, lenght %d\n"_fmt, - s, cmd, packet_len); -#ifdef DUMP_UNKNOWN_PACKET + PRINTF("\nclif_parse: session #%d, packet 0x%x, lenght %zu\n"_fmt, + s, packet_id, packet_avail(s)); { - int i; ZString packet_txt = "save/packet.txt"_s; - PRINTF("---- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F"_fmt); - for (i = 0; i < packet_len; i++) - { - if ((i & 15) == 0) - PRINTF("\n%04X "_fmt, i); - PRINTF("%02X "_fmt, RFIFOB(s, i)); - } if (sd && sd->state.auth) { - PRINTF("\nAccount ID %d, character ID %d, player name %s.\n"_fmt, + PRINTF("Unknown packet: Account ID %d, character ID %d, player name %s.\n"_fmt, sd->status_key.account_id, sd->status_key.char_id, sd->status_key.name); } else if (sd) // not authentified! (refused by char-server or disconnect before to be authentified) - PRINTF("\nAccount ID %d.\n"_fmt, sd->bl_id); + PRINTF("Unkonwn packet (unauthenticated): Account ID %d.\n"_fmt, sd->bl_id); + else + PRINTF("Unknown packet (unknown)\n"_fmt); io::AppendFile fp(packet_txt); if (!fp.is_open()) @@ -5461,24 +5661,18 @@ void clif_parse(Session *s) } else if (sd) // not authentified! (refused by char-server or disconnect before to be authentified) FPRINTF(fp, - "%s\nPlayer with account ID %d sent wrong packet:\n"_fmt, + "%s\nUnauthenticated player with account ID %d sent wrong packet:\n"_fmt, now, sd->bl_id); + else + FPRINTF(fp, + "%s\nUnknown connection sent wrong packet:\n"_fmt, + now); - FPRINTF(fp, - "\t---- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F"_fmt); - for (i = 0; i < packet_len; i++) - { - if ((i & 15) == 0) - FPRINTF(fp, "\n\t%04X "_fmt, i); - FPRINTF(fp, "%02X "_fmt, RFIFOB(s, i)); - } - FPRINTF(fp, "\n\n"_fmt); + packet_dump(fp, s); } } -#endif } } - RFIFOSKIP(s, packet_len); } void do_init_clif(void) diff --git a/src/map/clif.t.hpp b/src/map/clif.t.hpp index 2da6cde..5b3d32f 100644 --- a/src/map/clif.t.hpp +++ b/src/map/clif.t.hpp @@ -25,6 +25,91 @@ # include <cstdint> +# include "../ints/little.hpp" + +# include "../generic/enum.hpp" + +# include "../mmo/enums.hpp" + + +namespace e +{ +// [Fate] status.option properties. These are persistent status changes. +// IDs that are not listed are not used in the code (to the best of my knowledge) +enum class Option : uint16_t +{ + ZERO = 0x0000, + + // [Fate] This is the GM `@hide' flag + HIDE = 0x0040, + // [Fate] Complete invisibility to other clients + INVISIBILITY = 0x1000, + + // ? + REAL_ANY_HIDE = HIDE, +}; +enum class Opt1 : uint16_t +{ + ZERO = 0, + _stone1 = 1, + _freeze = 2, + _stan = 3, + _sleep = 4, + _stone6 = 6, +}; +enum class Opt2 : uint16_t +{ + ZERO = 0x0000, + _poison = 0x0001, + _curse = 0x0002, + _silence = 0x0004, + BLIND = 0x0010, + _speedpotion0 = 0x0020, + _signumcrucis = 0x0040, + _atkpot = 0x0080, + _heal = 0x0100, + _slowpoison = 0x0200, +}; +enum class Opt3 : uint16_t +{ + ZERO = 0x0000, + _concentration = 0x0001, + _overthrust = 0x0002, + _energycoat = 0x0004, + _explosionspirits = 0x0008, + _steelbody = 0x0010, + _berserk = 0x0080, + + _marionette = 0x0400, + _assumptio = 0x0800, +}; + +ENUM_BITWISE_OPERATORS(Option) +ENUM_BITWISE_OPERATORS(Opt2) +ENUM_BITWISE_OPERATORS(Opt3) +} +using e::Option; +using e::Opt1; +using e::Opt2; +using e::Opt3; + + +enum class ItemType : uint8_t +{ + USE = 0, // in eA, healing only + _1 = 1, // unused + _2 = 2, // in eA, other usable items + JUNK = 3, // "useless" items (e.g. quests) + WEAPON = 4, // all weapons + ARMOR = 5, // all other equipment + _6 = 6, // in eA, card + _7 = 7, // in eA, pet egg + _8 = 8, // in eA, pet equipment + _9 = 9, // unused + ARROW = 10, // ammo + _11 = 11, // in eA, delayed use (special script) +}; + enum class BeingRemoveWhy : uint8_t { // general disappearance @@ -40,4 +125,464 @@ enum class BeingRemoveWhy : uint8_t NEGATIVE1 = 0xff, }; +enum class PickupFail : uint8_t +{ + OKAY = 0, + BAD_ITEM = 1, + TOO_HEAVY = 2, + TOO_FAR = 3, + INV_FULL = 4, + STACK_FULL = 5, + DROP_STEAL = 6, +}; + +// this is used for both input and output +// different values are valid in 0x0089 vs 0x008a +enum class DamageType : uint8_t +{ + NORMAL = 0x00, + TAKEITEM = 0x01, + SIT = 0x02, + STAND = 0x03, + RETURNED = 0x04, + CONTINUOUS = 0x07, + DOUBLED = 0x08, + CRITICAL = 0x0a, + FLEE2 = 0x0b, +}; + +enum class LOOK : uint8_t +{ + BASE = 0, + HAIR = 1, + WEAPON = 2, + HEAD_BOTTOM = 3, + HEAD_TOP = 4, + HEAD_MID = 5, + HAIR_COLOR = 6, + CLOTHES_COLOR = 7, + SHIELD = 8, + SHOES = 9, + GLOVES = 10, + CAPE = 11, + MISC1 = 12, + MISC2 = 13, + + COUNT, +}; + +// Note: there is also a typedef by this name in <dirent.h> +// but we should be fine since we never include it. +// (in the long term we should still rename this though) +enum class DIR : uint8_t +{ + S = 0, + SW = 1, + W = 2, + NW = 3, + N = 4, + NE = 5, + E = 6, + SE = 7, + + COUNT, +}; + +constexpr +earray<int, DIR, DIR::COUNT> dirx //= +{{ + 0, -1, -1, -1, 0, 1, 1, 1, +}}, diry //= +{{ + 1, 1, 0, -1, -1, -1, 0, 1, +}}; + +constexpr +bool dir_is_diagonal(DIR d) +{ + return static_cast<uint8_t>(d) & 1; +} + + +enum class SP : uint16_t +{ + // sent to client + SPEED = 0, + + // when used as "no stat" + ZERO = 0, + + // sent to client + BASEEXP = 1, + // sent to client + JOBEXP = 2, +# if 0 + KARMA = 3, +# endif + + // sent to client + HP = 5, + // sent to client + MAXHP = 6, + // sent to client + SP = 7, + // sent to client + MAXSP = 8, + // sent to client + STATUSPOINT = 9, + + // sent to client + BASELEVEL = 11, + // sent to client + SKILLPOINT = 12, + // sent to client + STR = 13, + // sent to client + AGI = 14, + // sent to client + VIT = 15, + // sent to client + INT = 16, + // sent to client + DEX = 17, + // sent to client + LUK = 18, + CLASS = 19, + // sent to client + ZENY = 20, + SEX = 21, + // sent to client + NEXTBASEEXP = 22, + // sent to client + NEXTJOBEXP = 23, + // sent to client + WEIGHT = 24, + // sent to client + MAXWEIGHT = 25, + + // sent to client + USTR = 32, + // sent to client + UAGI = 33, + // sent to client + UVIT = 34, + // sent to client + UINT = 35, + // sent to client + UDEX = 36, + // sent to client + ULUK = 37, + + // sent to client + ATK1 = 41, + // sent to client + ATK2 = 42, + // sent to client + MATK1 = 43, + // sent to client + MATK2 = 44, + // sent to client + DEF1 = 45, + // sent to client + DEF2 = 46, + // sent to client + MDEF1 = 47, + // sent to client + MDEF2 = 48, + // sent to client + HIT = 49, + // sent to client + FLEE1 = 50, + // sent to client + FLEE2 = 51, + // sent to client + CRITICAL = 52, + // sent to client + ASPD = 53, + + // sent to client + JOBLEVEL = 55, + +# if 0 + PARTNER = 57, + CART = 58, + FAME = 59, + UNBREAKABLE = 60, +# endif + + DEAF = 70, + + // sent to client + GM = 500, + + // sent to client + ATTACKRANGE = 1000, +# if 0 + ATKELE = 1001, +# endif +# if 0 + DEFELE = 1002, +# endif +# if 0 + CASTRATE = 1003, +# endif + MAXHPRATE = 1004, +# if 0 + MAXSPRATE = 1005, +# endif +# if 0 + SPRATE = 1006, +# endif + +# if 0 + ADDEFF = 1012, +# endif +# if 0 + RESEFF = 1013, +# endif + BASE_ATK = 1014, + ASPD_RATE = 1015, + HP_RECOV_RATE = 1016, +# if 0 + SP_RECOV_RATE = 1017, +# endif +# if 0 + SPEED_RATE = 1018, +# endif + CRITICAL_DEF = 1019, +# if 0 + NEAR_ATK_DEF = 1020, +# endif +# if 0 + LONG_ATK_DEF = 1021, +# endif +# if 0 + DOUBLE_RATE = 1022, +# endif + DOUBLE_ADD_RATE = 1023, +# if 0 + MATK = 1024, +# endif +# if 0 + MATK_RATE = 1025, +# endif +# if 0 + IGNORE_DEF_ELE = 1026, +# endif +# if 0 + IGNORE_DEF_RACE = 1027, +# endif +# if 0 + ATK_RATE = 1028, +# endif + SPEED_ADDRATE = 1029, +# if 0 + ASPD_ADDRATE = 1030, +# endif +# if 0 + MAGIC_ATK_DEF = 1031, +# endif +# if 0 + MISC_ATK_DEF = 1032, +# endif +# if 0 + IGNORE_MDEF_ELE = 1033, +# endif +# if 0 + IGNORE_MDEF_RACE = 1034, +# endif + +# if 0 + PERFECT_HIT_RATE = 1038, +# endif +# if 0 + PERFECT_HIT_ADD_RATE = 1039, +# endif +# if 0 + CRITICAL_RATE = 1040, +# endif +# if 0 + GET_ZENY_NUM = 1041, +# endif +# if 0 + ADD_GET_ZENY_NUM = 1042, +# endif + +# if 0 + ADD_MONSTER_DROP_ITEM = 1047, +# endif +# if 0 + DEF_RATIO_ATK_ELE = 1048, +# endif +# if 0 + DEF_RATIO_ATK_RACE = 1049, +# endif +# if 0 + ADD_SPEED = 1050, +# endif +# if 0 + HIT_RATE = 1051, +# endif +# if 0 + FLEE_RATE = 1052, +# endif +# if 0 + FLEE2_RATE = 1053, +# endif + DEF_RATE = 1054, + DEF2_RATE = 1055, +# if 0 + MDEF_RATE = 1056, +# endif +# if 0 + MDEF2_RATE = 1057, +# endif +# if 0 + SPLASH_RANGE = 1058, +# endif +# if 0 + SPLASH_ADD_RANGE = 1059, +# endif + + HP_DRAIN_RATE = 1061, +# if 0 + SP_DRAIN_RATE = 1062, +# endif +# if 0 + SHORT_WEAPON_DAMAGE_RETURN = 1063, +# endif +# if 0 + LONG_WEAPON_DAMAGE_RETURN = 1064, +# endif + +# if 0 + ADDEFF2 = 1067, +# endif + BREAK_WEAPON_RATE = 1068, + BREAK_ARMOR_RATE = 1069, + ADD_STEAL_RATE = 1070, + MAGIC_DAMAGE_RETURN = 1071, +# if 0 + RANDOM_ATTACK_INCREASE = 1072, +# endif +}; + +constexpr +SP attr_to_sp(ATTR attr) +{ + return static_cast<SP>(static_cast<uint16_t>(attr) + static_cast<uint16_t>(SP::STR)); +} + +constexpr +ATTR sp_to_attr(SP sp) +{ + return static_cast<ATTR>(static_cast<uint16_t>(sp) - static_cast<uint16_t>(SP::STR)); +} + +constexpr +SP attr_to_usp(ATTR attr) +{ + return static_cast<SP>(static_cast<uint16_t>(attr) + static_cast<uint16_t>(SP::USTR)); +} + +constexpr +ATTR usp_to_attr(SP sp) +{ + return static_cast<ATTR>(static_cast<uint16_t>(sp) - static_cast<uint16_t>(SP::USTR)); +} + +constexpr +SP sp_to_usp(SP sp) +{ + return attr_to_usp(sp_to_attr(sp)); +} + +constexpr +SP usp_to_sp(SP sp) +{ + return attr_to_sp(usp_to_attr(sp)); +} + + +// xxxx xxxx xxyy yyyy yyyy dddd +struct NetPosition1 +{ + Byte data[3]; +}; + +struct Position1 +{ + uint16_t x, y; + DIR dir; +}; + +inline +bool native_to_network(NetPosition1 *network, Position1 native) +{ + uint16_t x = native.x; + uint16_t y = native.y; + uint8_t d = static_cast<uint8_t>(native.dir); + + uint8_t *p = reinterpret_cast<uint8_t *>(network); + p[0] = x >> 2; + p[1] = (x << 6) | ((y >> 4) & 0x3f); + p[2] = y << 4 | d; + + return x < 1024 && y < 1024 && d < 16; +} + +inline +bool network_to_native(Position1 *native, NetPosition1 network) +{ + const uint8_t *p = reinterpret_cast<const uint8_t *>(&network); + native->x = (p[0] & (0x3ff >> 2)) << 2 | p[1] >> (8 - 2); + native->y = (p[1] & (0x3ff >> 4)) << 4 | p[2] >> (8 - 4); + uint8_t d = p[2] & 0x0f; + native->dir = static_cast<DIR>(d); + return d < 8; +} + +// x0xx xxxx xxy0 yyyy yyyy x1xx xxxx xxy1 yyyy yyyy +struct NetPosition2 +{ + Byte data[5]; +}; + +struct Position2 +{ + uint16_t x0, y0; + uint16_t x1, y1; +}; + +inline +bool native_to_network(NetPosition2 *network, Position2 native) +{ + uint16_t x0 = native.x0; + uint16_t y0 = native.y0; + uint16_t x1 = native.x1; + uint16_t y1 = native.y1; + + uint8_t *p = reinterpret_cast<uint8_t *>(network); + p[0] = x0 >> 2; + p[1] = (x0 << 6) | ((y0 >> 4) & 0x3f); + p[2] = (y0 << 4) | ((x1 >> 6) & 0x0f); + p[3] = (x1 << 2) | ((y1 >> 8) & 0x03); + p[4] = y1; + + return x0 < 1024 && y0 < 1024 && x1 < 1024 && y1 < 1024; +} + +inline +bool network_to_native(Position2 *native, NetPosition2 network) +{ + const uint8_t *p = reinterpret_cast<const uint8_t *>(&network); + native->x0 = (p[0] & (0x3ff >> 2)) << 2 | p[1] >> (8 - 2); + native->y0 = (p[1] & (0x3ff >> 4)) << 4 | p[2] >> (8 - 4); + native->x1 = (p[2] & (0x3ff >> 6)) << 6 | p[3] >> (8 - 6); + native->y1 = (p[3] & (0x3ff >> 8)) << 8 | p[4] >> (8 - 8); + return true; +} + + + #endif // TMWA_MAP_CLIF_T_HPP diff --git a/src/map/magic-interpreter.t.hpp b/src/map/magic-interpreter.t.hpp index 1fe5fa3..780d011 100644 --- a/src/map/magic-interpreter.t.hpp +++ b/src/map/magic-interpreter.t.hpp @@ -47,38 +47,6 @@ enum class TYPE : uint8_t NEGATIVE_1 = 255, }; -// Note: there is also a typedef by this name in <dirent.h> -// but we should be fine since we never include it. -// (in the long term we should still rename this though) -enum class DIR : uint8_t -{ - S = 0, - SW = 1, - W = 2, - NW = 3, - N = 4, - NE = 5, - E = 6, - SE = 7, - - COUNT, -}; - -constexpr -earray<int, DIR, DIR::COUNT> dirx //= -{{ - 0, -1, -1, -1, 0, 1, 1, 1, -}}, diry //= -{{ - 1, 1, 0, -1, -1, -1, 0, 1, -}}; - -constexpr -bool dir_is_diagonal(DIR d) -{ - return static_cast<uint8_t>(d) & 1; -} - enum class AREA : uint8_t { LOCATION, diff --git a/src/map/magic-stmt.cpp b/src/map/magic-stmt.cpp index ab7f60e..ae59ae7 100644 --- a/src/map/magic-stmt.cpp +++ b/src/map/magic-stmt.cpp @@ -47,7 +47,7 @@ #include "../poison.hpp" /* used for local spell effects */ -constexpr int INVISIBLE_NPC = 127; +constexpr Species INVISIBLE_NPC = wrap<Species>(127); //#define DEBUG @@ -153,7 +153,7 @@ void spell_free_invocation(dumb_ptr<invocation> invocation_) static void char_set_weapon_icon(dumb_ptr<map_session_data> subject, int count, - StatusChange icon, int look) + StatusChange icon, ItemNameId look) { const StatusChange old_icon = subject->attack_spell_icon_override; @@ -166,7 +166,7 @@ void char_set_weapon_icon(dumb_ptr<map_session_data> subject, int count, clif_fixpcpos(subject); if (count) { - clif_changelook(subject, LOOK::WEAPON, look); + clif_changelook(subject, LOOK::WEAPON, unwrap<ItemNameId>(look)); if (icon != StatusChange::ZERO) clif_status_change(subject, icon, 1); } @@ -213,7 +213,7 @@ void magic_stop_completely(dumb_ptr<map_session_data> c) if (attack_spell) spell_free_invocation(attack_spell); c->attack_spell_override = BlockId(); - char_set_weapon_icon(c, 0, StatusChange::ZERO, 0); + char_set_weapon_icon(c, 0, StatusChange::ZERO, ItemNameId()); char_set_attack_info(c, interval_t::zero(), 0); } } @@ -445,7 +445,7 @@ int op_messenger_npc(dumb_ptr<env_t>, Slice<val_t> args) NpcName npcname = stringish<NpcName>(ARGSTR(2)); npc = npc_spawn_text(loc->m, loc->x, loc->y, - ARGINT(1), npcname, ARGSTR(3)); + wrap<Species>(static_cast<uint16_t>(ARGINT(1))), npcname, ARGSTR(3)); Timer(gettick() + static_cast<interval_t>(ARGINT(4)), std::bind(timer_callback_kill_npc, ph::_1, ph::_2, @@ -587,7 +587,7 @@ int op_override_attack(dumb_ptr<env_t> env, Slice<val_t> args) interval_t attack_delay = static_cast<interval_t>(ARGINT(2)); int attack_range = ARGINT(3); StatusChange icon = StatusChange(ARGINT(4)); - int look = ARGINT(5); + ItemNameId look = wrap<ItemNameId>(static_cast<uint16_t>(ARGINT(5))); int stopattack = ARGINT(6); dumb_ptr<map_session_data> subject; @@ -1623,7 +1623,7 @@ int spell_attack(BlockId caster_id, BlockId target_id) else if (!invocation_ || caster->attack_spell_charges <= 0) { caster->attack_spell_override = BlockId(); - char_set_weapon_icon(caster, 0, StatusChange::ZERO, 0); + char_set_weapon_icon(caster, 0, StatusChange::ZERO, ItemNameId()); char_set_attack_info(caster, interval_t::zero(), 0); if (stop_attack) diff --git a/src/map/map.hpp b/src/map/map.hpp index 78d12f8..cbe8b27 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -46,7 +46,7 @@ # include "../mmo/utils.hpp" # include "battle.t.hpp" -# include "magic-interpreter.t.hpp" +# include "clif.t.hpp" # include "mapflag.hpp" # include "mob.t.hpp" # include "script.hpp" // change to script.t.hpp @@ -194,7 +194,6 @@ struct map_session_data : block_list, SessionData Opt2 opt2; Opt3 opt3; DIR dir, head_dir; - tick_t client_tick, server_tick; struct walkpath_data walkpath; Timer walktimer; BlockId npc_id, areanpc_id, npc_shopid; @@ -227,7 +226,7 @@ struct map_session_data : block_list, SessionData // like a weapon. Check pc_attack_timer() for details. // Weapon equipment slot (slot 4) item override StatusChange attack_spell_icon_override; - short attack_spell_look_override; // Weapon `look' (attack animation) override + ItemNameId attack_spell_look_override; // Weapon `look' (attack animation) override short attack_spell_charges; // [Fate] Remaining number of charges for the attack spell interval_t attack_spell_delay; // [Fate] ms delay after spell attack short attack_spell_range; // [Fate] spell range @@ -347,9 +346,7 @@ struct npc_data : block_list { NpcSubtype npc_subtype; short n; - // TODO This *should* be a Species, but the script files give -1 for - // event-only which is not valid unsigned - short npc_class; + Species npc_class; DIR dir; interval_t speed; NpcName name; diff --git a/src/map/map.t.hpp b/src/map/map.t.hpp index e40befa..4eba867 100644 --- a/src/map/map.t.hpp +++ b/src/map/map.t.hpp @@ -32,67 +32,6 @@ # include "../mmo/ids.hpp" # include "../mmo/mmo.hpp" -namespace e -{ -// [Fate] status.option properties. These are persistent status changes. -// IDs that are not listed are not used in the code (to the best of my knowledge) -enum class Option : uint16_t -{ - ZERO = 0x0000, - - // [Fate] This is the GM `@hide' flag - HIDE = 0x0040, - // [Fate] Complete invisibility to other clients - INVISIBILITY = 0x1000, - - // ? - REAL_ANY_HIDE = HIDE, -}; -enum class Opt1 : uint16_t -{ - ZERO = 0, - _stone1 = 1, - _freeze = 2, - _stan = 3, - _sleep = 4, - _stone6 = 6, -}; -enum class Opt2 : uint16_t -{ - ZERO = 0x0000, - _poison = 0x0001, - _curse = 0x0002, - _silence = 0x0004, - BLIND = 0x0010, - _speedpotion0 = 0x0020, - _signumcrucis = 0x0040, - _atkpot = 0x0080, - _heal = 0x0100, - _slowpoison = 0x0200, -}; -enum class Opt3 : uint16_t -{ - ZERO = 0x0000, - _concentration = 0x0001, - _overthrust = 0x0002, - _energycoat = 0x0004, - _explosionspirits = 0x0008, - _steelbody = 0x0010, - _berserk = 0x0080, - - _marionette = 0x0400, - _assumptio = 0x0800, -}; - -ENUM_BITWISE_OPERATORS(Option) -ENUM_BITWISE_OPERATORS(Opt2) -ENUM_BITWISE_OPERATORS(Opt3) -} -using e::Option; -using e::Opt1; -using e::Opt2; -using e::Opt3; - enum class BL : uint8_t { NUL, @@ -153,325 +92,6 @@ enum class ATK DEF, }; -enum class SP : uint16_t -{ - // sent to client - SPEED = 0, - - // when used as "no stat" - ZERO = 0, - - // sent to client - BASEEXP = 1, - // sent to client - JOBEXP = 2, -# if 0 - KARMA = 3, -# endif - - // sent to client - HP = 5, - // sent to client - MAXHP = 6, - // sent to client - SP = 7, - // sent to client - MAXSP = 8, - // sent to client - STATUSPOINT = 9, - - // sent to client - BASELEVEL = 11, - // sent to client - SKILLPOINT = 12, - // sent to client - STR = 13, - // sent to client - AGI = 14, - // sent to client - VIT = 15, - // sent to client - INT = 16, - // sent to client - DEX = 17, - // sent to client - LUK = 18, - CLASS = 19, - // sent to client - ZENY = 20, - SEX = 21, - // sent to client - NEXTBASEEXP = 22, - // sent to client - NEXTJOBEXP = 23, - // sent to client - WEIGHT = 24, - // sent to client - MAXWEIGHT = 25, - - // sent to client - USTR = 32, - // sent to client - UAGI = 33, - // sent to client - UVIT = 34, - // sent to client - UINT = 35, - // sent to client - UDEX = 36, - // sent to client - ULUK = 37, - - // sent to client - ATK1 = 41, - // sent to client - ATK2 = 42, - // sent to client - MATK1 = 43, - // sent to client - MATK2 = 44, - // sent to client - DEF1 = 45, - // sent to client - DEF2 = 46, - // sent to client - MDEF1 = 47, - // sent to client - MDEF2 = 48, - // sent to client - HIT = 49, - // sent to client - FLEE1 = 50, - // sent to client - FLEE2 = 51, - // sent to client - CRITICAL = 52, - // sent to client - ASPD = 53, - - // sent to client - JOBLEVEL = 55, - -# if 0 - PARTNER = 57, - CART = 58, - FAME = 59, - UNBREAKABLE = 60, -# endif - - DEAF = 70, - - // sent to client - GM = 500, - - // sent to client - ATTACKRANGE = 1000, -# if 0 - ATKELE = 1001, -# endif -# if 0 - DEFELE = 1002, -# endif -# if 0 - CASTRATE = 1003, -# endif - MAXHPRATE = 1004, -# if 0 - MAXSPRATE = 1005, -# endif -# if 0 - SPRATE = 1006, -# endif - -# if 0 - ADDEFF = 1012, -# endif -# if 0 - RESEFF = 1013, -# endif - BASE_ATK = 1014, - ASPD_RATE = 1015, - HP_RECOV_RATE = 1016, -# if 0 - SP_RECOV_RATE = 1017, -# endif -# if 0 - SPEED_RATE = 1018, -# endif - CRITICAL_DEF = 1019, -# if 0 - NEAR_ATK_DEF = 1020, -# endif -# if 0 - LONG_ATK_DEF = 1021, -# endif -# if 0 - DOUBLE_RATE = 1022, -# endif - DOUBLE_ADD_RATE = 1023, -# if 0 - MATK = 1024, -# endif -# if 0 - MATK_RATE = 1025, -# endif -# if 0 - IGNORE_DEF_ELE = 1026, -# endif -# if 0 - IGNORE_DEF_RACE = 1027, -# endif -# if 0 - ATK_RATE = 1028, -# endif - SPEED_ADDRATE = 1029, -# if 0 - ASPD_ADDRATE = 1030, -# endif -# if 0 - MAGIC_ATK_DEF = 1031, -# endif -# if 0 - MISC_ATK_DEF = 1032, -# endif -# if 0 - IGNORE_MDEF_ELE = 1033, -# endif -# if 0 - IGNORE_MDEF_RACE = 1034, -# endif - -# if 0 - PERFECT_HIT_RATE = 1038, -# endif -# if 0 - PERFECT_HIT_ADD_RATE = 1039, -# endif -# if 0 - CRITICAL_RATE = 1040, -# endif -# if 0 - GET_ZENY_NUM = 1041, -# endif -# if 0 - ADD_GET_ZENY_NUM = 1042, -# endif - -# if 0 - ADD_MONSTER_DROP_ITEM = 1047, -# endif -# if 0 - DEF_RATIO_ATK_ELE = 1048, -# endif -# if 0 - DEF_RATIO_ATK_RACE = 1049, -# endif -# if 0 - ADD_SPEED = 1050, -# endif -# if 0 - HIT_RATE = 1051, -# endif -# if 0 - FLEE_RATE = 1052, -# endif -# if 0 - FLEE2_RATE = 1053, -# endif - DEF_RATE = 1054, - DEF2_RATE = 1055, -# if 0 - MDEF_RATE = 1056, -# endif -# if 0 - MDEF2_RATE = 1057, -# endif -# if 0 - SPLASH_RANGE = 1058, -# endif -# if 0 - SPLASH_ADD_RANGE = 1059, -# endif - - HP_DRAIN_RATE = 1061, -# if 0 - SP_DRAIN_RATE = 1062, -# endif -# if 0 - SHORT_WEAPON_DAMAGE_RETURN = 1063, -# endif -# if 0 - LONG_WEAPON_DAMAGE_RETURN = 1064, -# endif - -# if 0 - ADDEFF2 = 1067, -# endif - BREAK_WEAPON_RATE = 1068, - BREAK_ARMOR_RATE = 1069, - ADD_STEAL_RATE = 1070, - MAGIC_DAMAGE_RETURN = 1071, -# if 0 - RANDOM_ATTACK_INCREASE = 1072, -# endif -}; - -constexpr -SP attr_to_sp(ATTR attr) -{ - return static_cast<SP>(static_cast<uint16_t>(attr) + static_cast<uint16_t>(SP::STR)); -} - -constexpr -ATTR sp_to_attr(SP sp) -{ - return static_cast<ATTR>(static_cast<uint16_t>(sp) - static_cast<uint16_t>(SP::STR)); -} - -constexpr -SP attr_to_usp(ATTR attr) -{ - return static_cast<SP>(static_cast<uint16_t>(attr) + static_cast<uint16_t>(SP::USTR)); -} - -constexpr -ATTR usp_to_attr(SP sp) -{ - return static_cast<ATTR>(static_cast<uint16_t>(sp) - static_cast<uint16_t>(SP::USTR)); -} - -constexpr -SP sp_to_usp(SP sp) -{ - return attr_to_usp(sp_to_attr(sp)); -} - -constexpr -SP usp_to_sp(SP sp) -{ - return attr_to_sp(usp_to_attr(sp)); -} - - -enum class LOOK : uint8_t -{ - BASE = 0, - HAIR = 1, - WEAPON = 2, - HEAD_BOTTOM = 3, - HEAD_TOP = 4, - HEAD_MID = 5, - HAIR_COLOR = 6, - CLOTHES_COLOR = 7, - SHIELD = 8, - SHOES = 9, - GLOVES = 10, - CAPE = 11, - MISC1 = 12, - MISC2 = 13, - - COUNT, -}; enum class EQUIP { @@ -521,22 +141,6 @@ EQUIP EQUIPs_noarrow[] = EQUIP::WEAPON, }; -enum class ItemType : uint8_t -{ - USE = 0, // in eA, healing only - _1 = 1, // unused - _2 = 2, // in eA, other usable items - JUNK = 3, // "useless" items (e.g. quests) - WEAPON = 4, // all weapons - ARMOR = 5, // all other equipment - _6 = 6, // in eA, card - _7 = 7, // in eA, pet egg - _8 = 8, // in eA, pet equipment - _9 = 9, // unused - ARROW = 10, // ammo - _11 = 11, // in eA, delayed use (special script) -}; - namespace e { enum class MobMode : uint16_t diff --git a/src/map/npc.cpp b/src/map/npc.cpp index aee3d03..ef10d82 100644 --- a/src/map/npc.cpp +++ b/src/map/npc.cpp @@ -46,6 +46,8 @@ #include "../mmo/extract.hpp" #include "../mmo/utils.hpp" +#include "../proto2/map-user.hpp" + #include "battle.hpp" #include "clif.hpp" #include "itemdb.hpp" @@ -642,7 +644,7 @@ int npc_checknear(dumb_ptr<map_session_data> sd, BlockId id) if (nd->bl_type != BL::NPC) return 1; - if (nd->npc_class < 0) // イベント系は常にOK + if (nd->npc_class == NEGATIVE_SPECIES) return 0; // エリア判定 @@ -778,15 +780,14 @@ int npc_buysellsel(dumb_ptr<map_session_data> sd, BlockId id, int type) *------------------------------------------ */ // TODO enumify return type -int npc_buylist(dumb_ptr<map_session_data> sd, int n, - const uint16_t *item_list) +int npc_buylist(dumb_ptr<map_session_data> sd, + const std::vector<Packet_Repeat<0x00c8>>& item_list) { dumb_ptr<npc_data> nd; double z; int i, j, w, itemamount = 0, new_stacks = 0; nullpo_retr(3, sd); - nullpo_retr(3, item_list); if (npc_checknear(sd, sd->npc_shopid)) return 3; @@ -795,11 +796,10 @@ int npc_buylist(dumb_ptr<map_session_data> sd, int n, if (nd->npc_subtype != NpcSubtype::SHOP) return 3; - for (i = 0, w = 0, z = 0; i < n; i++) + for (i = 0, w = 0, z = 0; i < item_list.size(); i++) { - // TODO this *really needs to be made into a struct - const uint16_t& item_l_count = item_list[i * 2]; - const ItemNameId& item_l_id = wrap<ItemNameId>(item_list[i * 2 + 1]); + const uint16_t& item_l_count = item_list[i].count; + const ItemNameId& item_l_id = item_list[i].name_id; for (j = 0; j < nd->is_shop()->shop_items.size(); j++) { @@ -840,10 +840,10 @@ int npc_buylist(dumb_ptr<map_session_data> sd, int n, pc_payzeny(sd, static_cast<int>(z)); - for (i = 0; i < n; i++) + for (i = 0; i < item_list.size(); i++) { - const uint16_t& item_l_count = item_list[i * 2]; - const ItemNameId& item_l_id = wrap<ItemNameId>(item_list[i * 2 + 1]); + const uint16_t& item_l_count = item_list[i].count; + const ItemNameId& item_l_id = item_list[i].name_id; struct item_data *item_data; if ((item_data = itemdb_exists(item_l_id)) != NULL) @@ -878,38 +878,37 @@ int npc_buylist(dumb_ptr<map_session_data> sd, int n, * *------------------------------------------ */ -int npc_selllist(dumb_ptr<map_session_data> sd, int n, - const uint16_t *item_list) +int npc_selllist(dumb_ptr<map_session_data> sd, + const std::vector<Packet_Repeat<0x00c9>>& item_list) { double z; int i, itemamount = 0; nullpo_retr(1, sd); - nullpo_retr(1, item_list); if (npc_checknear(sd, sd->npc_shopid)) return 1; - for (i = 0, z = 0; i < n; i++) + for (i = 0, z = 0; i < item_list.size(); i++) { - if (item_list[i * 2] - 2 < 0 || item_list[i * 2] - 2 >= MAX_INVENTORY) + if (item_list[i].ioff2 - 2 < 0 || item_list[i].ioff2 - 2 >= MAX_INVENTORY) return 1; - ItemNameId nameid = sd->status.inventory[item_list[i * 2] - 2].nameid; + ItemNameId nameid = sd->status.inventory[item_list[i].ioff2 - 2].nameid; if (!nameid || - sd->status.inventory[item_list[i * 2] - 2].amount < item_list[i * 2 + 1]) + sd->status.inventory[item_list[i].ioff2 - 2].amount < item_list[i].count) return 1; if (sd->trade_partner) return 2; // cant sell while trading - z += static_cast<double>(itemdb_value_sell(nameid)) * item_list[i * 2 + 1]; - itemamount += item_list[i * 2 + 1]; + z += static_cast<double>(itemdb_value_sell(nameid)) * item_list[i].count; + itemamount += item_list[i].count; } if (z > MAX_ZENY) z = MAX_ZENY; pc_getzeny(sd, static_cast<int>(z)); - for (i = 0; i < n; i++) + for (i = 0; i < item_list.size(); i++) { - int item_id = item_list[i * 2] - 2; - pc_delitem(sd, item_id, item_list[i * 2 + 1], 0); + int item_id = item_list[i].ioff2 - 2; + pc_delitem(sd, item_id, item_list[i].count, 0); } return 0; @@ -1116,7 +1115,7 @@ int npc_parse_shop(XString w1, XString, NpcName w3, ZString w4a) MapName mapname; dumb_ptr<npc_data_shop> nd; ZString::iterator w4comma; - int npc_class; + Species npc_class; int dir_; // TODO use enum directly in extract if (!extract(w1, record<','>(&mapname, &x, &y, &dir_)) @@ -1198,7 +1197,8 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, int x, y; DIR dir = DIR::S; map_local *m; - int xs = 0, ys = 0, npc_class = 0; // [Valaris] thanks to fov + int xs = 0, ys = 0; // [Valaris] thanks to fov + Species npc_class; MapName mapname; std::unique_ptr<const ScriptBuffer> script = NULL; dumb_ptr<npc_data_script> nd; @@ -1279,7 +1279,7 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, if (ys >= 0) ys = ys * 2 + 1; - if (npc_class >= 0) + if (npc_class != NEGATIVE_SPECIES) { for (int i = 0; i < ys; i++) @@ -1303,12 +1303,13 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, } else { - npc_class = atoi(w4.c_str()); + if (!extract(w4, &npc_class)) + abort(); nd->scr.xs = 0; nd->scr.ys = 0; } - if (npc_class < 0 && m != nullptr) + if (npc_class == NEGATIVE_SPECIES && m != nullptr) { evflag = 1; } @@ -1318,6 +1319,7 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, assert(false && "feature removed"_s); abort(); } + { nd->name = w3; } @@ -1596,7 +1598,7 @@ int npc_parse_mapflag(XString w1, XString, XString w3, ZString w4) } dumb_ptr<npc_data> npc_spawn_text(map_local *m, int x, int y, - int npc_class, NpcName name, AString message) + Species npc_class, NpcName name, AString message) { dumb_ptr<npc_data_message> retval; retval.new_(); diff --git a/src/map/npc.hpp b/src/map/npc.hpp index 011ea50..2c91dbd 100644 --- a/src/map/npc.hpp +++ b/src/map/npc.hpp @@ -31,14 +31,17 @@ # include "../net/timer.t.hpp" +# include "../proto2/fwd.hpp" + # include "map.hpp" constexpr BlockId START_NPC_NUM = wrap<BlockId>(110000000); // TODO make these species, see npc_class in npc_data -constexpr int WARP_CLASS = 45; -constexpr int WARP_DEBUG_CLASS = 722; -constexpr int INVISIBLE_CLASS = 32767; +constexpr Species WARP_CLASS = wrap<Species>(45); +constexpr Species FAKE_NPC_CLASS = wrap<Species>(127); +constexpr Species WARP_DEBUG_CLASS = wrap<Species>(722); +constexpr Species INVISIBLE_CLASS = wrap<Species>(32767); int npc_event_dequeue(dumb_ptr<map_session_data> sd); int npc_event(dumb_ptr<map_session_data> sd, NpcEvent npcname, int); @@ -48,8 +51,8 @@ int npc_touch_areanpc(dumb_ptr<map_session_data>, map_local *, int, int); int npc_click(dumb_ptr<map_session_data>, BlockId); int npc_scriptcont(dumb_ptr<map_session_data>, BlockId); int npc_buysellsel(dumb_ptr<map_session_data>, BlockId, int); -int npc_buylist(dumb_ptr<map_session_data>, int, const uint16_t *); -int npc_selllist(dumb_ptr<map_session_data>, int, const uint16_t *); +int npc_buylist(dumb_ptr<map_session_data>, const std::vector<Packet_Repeat<0x00c8>>&); +int npc_selllist(dumb_ptr<map_session_data>, const std::vector<Packet_Repeat<0x00c9>>&); int npc_parse_warp(XString w1, XString, NpcName w3, XString w4); int npc_enable(NpcName name, bool flag); @@ -63,7 +66,7 @@ BlockId npc_get_new_npc_id(void); * \param message The message to speak. If message is NULL, the NPC will not do anything at all. */ dumb_ptr<npc_data> npc_spawn_text(map_local *m, int x, int y, - int class_, NpcName name, AString message); + Species class_, NpcName name, AString message); /** * Uninstalls and frees an NPC diff --git a/src/map/path.cpp b/src/map/path.cpp index e0e18b6..fb423e7 100644 --- a/src/map/path.cpp +++ b/src/map/path.cpp @@ -31,7 +31,7 @@ #include "../io/cxxstdio.hpp" -#include "magic-interpreter.t.hpp" +#include "clif.t.hpp" #include "map.hpp" #include "../poison.hpp" diff --git a/src/map/pc.cpp b/src/map/pc.cpp index ac8af28..33cb57f 100644 --- a/src/map/pc.cpp +++ b/src/map/pc.cpp @@ -472,7 +472,7 @@ void pc_makesavestatus(dumb_ptr<map_session_data> sd) *------------------------------------------ */ int pc_setnewpc(dumb_ptr<map_session_data> sd, AccountId account_id, CharId char_id, - int login_id1, tick_t client_tick, SEX sex) + int login_id1, uint32_t client_tick, SEX sex) { nullpo_ret(sd); @@ -485,7 +485,7 @@ int pc_setnewpc(dumb_ptr<map_session_data> sd, AccountId account_id, CharId char // Possible fix: char send auth before client is allowed to know my IP? sd->login_id1 = login_id1; sd->login_id2 = 0; // at this point, we can not know the value :( - sd->client_tick = client_tick; + (void)client_tick; sd->sex = sex; sd->state.auth = 0; sd->bl_type = BL::PC; @@ -912,7 +912,7 @@ void pc_set_weapon_look(dumb_ptr<map_session_data> sd) { if (sd->attack_spell_override) clif_changelook(sd, LOOK::WEAPON, - sd->attack_spell_look_override); + unwrap<ItemNameId>(sd->attack_spell_look_override)); else clif_changelook(sd, LOOK::WEAPON, static_cast<uint16_t>(sd->status.weapon)); diff --git a/src/map/pc.hpp b/src/map/pc.hpp index 900ce97..10c11cf 100644 --- a/src/map/pc.hpp +++ b/src/map/pc.hpp @@ -78,7 +78,7 @@ int pc_counttargeted(dumb_ptr<map_session_data> sd, dumb_ptr<block_list> src, ATK target_lv); int pc_setrestartvalue(dumb_ptr<map_session_data> sd, int type); void pc_makesavestatus(dumb_ptr<map_session_data>); -int pc_setnewpc(dumb_ptr<map_session_data>, AccountId, CharId, int, tick_t, SEX); +int pc_setnewpc(dumb_ptr<map_session_data>, AccountId, CharId, int, uint32_t /*tick_t*/, SEX); int pc_authok(AccountId, int, TimeT, short tmw_version, const CharKey *, const CharData *); int pc_authfail(AccountId accid); diff --git a/src/map/pc.t.hpp b/src/map/pc.t.hpp index e022f3b..86817a7 100644 --- a/src/map/pc.t.hpp +++ b/src/map/pc.t.hpp @@ -50,18 +50,7 @@ enum class ADDITEM enum class CalcStatus { NOW, - LATER , -}; - -enum class PickupFail : uint8_t -{ - OKAY = 0, - BAD_ITEM = 1, - TOO_HEAVY = 2, - TOO_FAR = 3, - INV_FULL = 4, - STACK_FULL = 5, - DROP_STEAL = 6, + LATER, }; #endif // TMWA_MAP_PC_T_HPP diff --git a/src/map/script.cpp b/src/map/script.cpp index 6cac082..b1af725 100644 --- a/src/map/script.cpp +++ b/src/map/script.cpp @@ -4038,7 +4038,7 @@ void builtin_fakenpcname(ScriptState *st) { NpcName name = stringish<NpcName>(ZString(conv_str(st, &AARGO2(2)))); NpcName newname = stringish<NpcName>(ZString(conv_str(st, &AARGO2(3)))); - int newsprite = conv_num(st, &AARGO2(4)); + Species newsprite = wrap<Species>(static_cast<uint16_t>(conv_num(st, &AARGO2(4)))); dumb_ptr<npc_data> nd = npc_name2id(name); if (!nd) { diff --git a/src/map/script.hpp b/src/map/script.hpp index d42da2c..6708bbc 100644 --- a/src/map/script.hpp +++ b/src/map/script.hpp @@ -34,6 +34,9 @@ # include "../generic/db.hpp" # include "../generic/dumb_ptr.hpp" +# include "../mmo/ids.hpp" + +# include "clif.t.hpp" # include "map.t.hpp" enum class ByteCode : uint8_t; |