factor FloorItem struct into 6x5F format

This commit is contained in:
Martin Michelsen
2023-10-25 15:06:04 -07:00
parent 5d251361b0
commit 5f0a6f3d8e
3 changed files with 41 additions and 33 deletions
+13 -18
View File
@@ -4317,7 +4317,7 @@ struct G_Unknown_6x5C {
struct G_DropStackedItem_DC_6x5D {
G_ClientIDHeader header;
le_uint16_t area;
le_uint16_t unused2;
le_uint16_t unknown_a2; // Corresponds to FloorItem::unknown_a2
le_float x;
le_float z;
ItemData item_data;
@@ -4336,16 +4336,23 @@ struct G_BuyShopItem_6x5E {
// 6x5F: Drop item from box/enemy
struct G_DropItem_DC_6x5F {
G_UnusedHeader header;
struct FloorItem {
uint8_t area;
uint8_t from_enemy;
le_uint16_t request_id; // < 0x0B50 if from_enemy != 0; otherwise < 0x0BA0
le_uint16_t entity_id; // < 0x0B50 if from_enemy != 0; otherwise < 0x0BA0
le_float x;
le_float z;
le_uint16_t unknown_a1;
le_uint16_t unknown_a2;
ItemData item_data;
// The drop number is scoped to the area and increments by 1 each time an
// item is dropped. The last item dropped in each area has drop_number equal
// to total_items_dropped_per_area[area - 1] - 1.
le_uint16_t drop_number;
ItemData item;
} __packed__;
struct G_DropItem_DC_6x5F {
G_UnusedHeader header;
FloorItem item;
} __packed__;
struct G_DropItem_PC_V3_BB_6x5F : G_DropItem_DC_6x5F {
@@ -4492,18 +4499,6 @@ struct G_SyncItemState_6x6D_Decompressed {
// the client fills in all 12 of these with reasonable values.
parray<le_uint32_t, 12> next_item_id_per_player;
parray<le_uint32_t, 15> floor_item_count_per_area;
struct FloorItem {
le_uint16_t area;
le_uint16_t unknown_a1;
le_float x;
le_float z;
le_uint16_t unknown_a2;
// The drop number is scoped to the area and increments by 1 each time an
// item is dropped. The last item dropped in each area has drop_number equal
// to total_items_dropped_per_area[area - 1] - 1.
le_uint16_t drop_number;
ItemData item_data;
} __packed__;
// Variable-length field:
// FloorItem items[sum(floor_item_count_per_area)];
} __packed__;
+26 -13
View File
@@ -210,14 +210,13 @@ static void on_sync_joining_player_item_state(shared_ptr<Client> c, uint8_t comm
num_floor_items += decompressed_cmd->floor_item_count_per_area[z];
}
size_t required_size = sizeof(G_SyncItemState_6x6D_Decompressed) + num_floor_items * sizeof(G_SyncItemState_6x6D_Decompressed::FloorItem);
size_t required_size = sizeof(G_SyncItemState_6x6D_Decompressed) + num_floor_items * sizeof(FloorItem);
if (decompressed.size() < required_size) {
throw runtime_error(string_printf(
"decompressed 6x6D data (0x%zX bytes) is too short for all items (0x%zX bytes)",
decompressed.size(), required_size));
}
auto* floor_items = reinterpret_cast<G_SyncItemState_6x6D_Decompressed::FloorItem*>(
decompressed.data() + sizeof(G_SyncItemState_6x6D_Decompressed));
auto* floor_items = reinterpret_cast<FloorItem*>(decompressed.data() + sizeof(G_SyncItemState_6x6D_Decompressed));
for (size_t z = 0; z < num_floor_items; z++) {
// NOTE: If we use this codepath for non-V3 in the future, we'll need to
@@ -900,6 +899,12 @@ static void on_buy_shop_item(shared_ptr<Client> c, uint8_t command, uint8_t flag
template <typename CmdT>
static void on_box_or_enemy_item_drop_t(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
// I'm lazy and this should never happen for item commands (since all players
// need to stay in sync)
if (command_is_private(command)) {
throw runtime_error("item subcommand sent via private command");
}
const auto& cmd = check_size_t<CmdT>(data, size);
auto l = c->require_lobby();
@@ -911,22 +916,30 @@ static void on_box_or_enemy_item_drop_t(shared_ptr<Client> c, uint8_t command, u
}
if (l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED) {
{
ItemData item = cmd.item_data;
item.decode_if_mag(c->version());
l->add_item(item, cmd.area, cmd.x, cmd.z);
}
ItemData item = cmd.item.item;
item.decode_if_mag(c->version());
l->add_item(item, cmd.item.area, cmd.item.x, cmd.item.z);
auto name = cmd.item_data.name(false);
auto name = item.name(false);
l->log.info("Leader created ground item %08" PRIX32 " (%s) at %hhu:(%g, %g)",
cmd.item_data.id.load(), name.c_str(), cmd.area, cmd.x.load(), cmd.z.load());
item.id.load(), name.c_str(), cmd.item.area, cmd.item.x.load(), cmd.item.z.load());
if (c->options.debug) {
string name = cmd.item_data.name(true);
send_text_message_printf(c, "$C5DROP %08" PRIX32 "\n%s", cmd.item_data.id.load(), name.c_str());
string name = item.name(true);
send_text_message_printf(c, "$C5DROP %08" PRIX32 "\n%s", item.id.load(), name.c_str());
}
}
forward_subcommand_with_mag_transcode_t(c, command, flag, cmd);
for (auto& lc : l->clients) {
if (!lc || lc == c) {
continue;
}
CmdT out_cmd = cmd;
if (c->version() != lc->version()) {
out_cmd.item.item.decode_if_mag(c->version());
out_cmd.item.item.encode_if_mag(lc->version());
}
send_command_t(lc, command, flag, out_cmd);
}
}
static void on_box_or_enemy_item_drop(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
+2 -2
View File
@@ -2009,8 +2009,8 @@ void send_set_player_visibility(shared_ptr<Lobby> l, shared_ptr<Client> c,
void send_drop_item(Channel& ch, const ItemData& item,
bool from_enemy, uint8_t area, float x, float z, uint16_t entity_id) {
G_DropItem_PC_V3_BB_6x5F cmd = {
{{0x5F, 0x0B, 0x0000}, area, from_enemy, entity_id, x, z, 0, 0, item}, 0};
cmd.item_data.encode_if_mag(ch.version);
{{0x5F, 0x0B, 0x0000}, {area, from_enemy, entity_id, x, z, 0, 0, item}}, 0};
cmd.item.item.encode_if_mag(ch.version);
ch.send(0x60, 0x00, &cmd, sizeof(cmd));
}