Just finished writing a function to append player update blocks to the circular buffer.
If anyone wants to have a quick look over it to make sure I haven’t made any silly mistakes, feel free to: https://github.com/Lothy/Dionysus/blob/master/src/protocols/508.c
In particular, I need clarification that I have a) included all update blocks, b) have them all in the right order (although wrote a quick class as part of Blake’s server and used the comparator to sort a list of all player and npc update block implementations, and then printed them out in order).
Here’s the code if you CBF going to github for some reason :rolleyes:
int append_player_update_blocks(struct player *player,
struct circular_buffer *cbuf)
{
int i;
int hp_ratio;
int app_block_start_index;
unsigned char app_block_size;
struct item *equip_item;
struct item_definition *item_def;
if (player->update_flags & PUFLAG_SECONDARY_HIT_UPDATE_REQUIRED) {
cwrite_byte_S(cbuf, player->secondary_damage.amount);
cwrite_byte_A(cbuf, player->secondary_damage.type);
}
if (player->update_flags & PUFLAG_FACE_MOB_UPDATE_REQUIRED) {
cwrite_short_B(cbuf, player->mob_to_face);
}
if (player->update_flags & PUFLAG_FORCED_CHAT_UPDATE_REQUIRED) {
player->forced_chat[MAX_FORCED_CHAT_LEN - 1] = '\0';
cwrite_string(cbuf, player->forced_chat);
}
if (player->update_flags & PUFLAG_GRAPHICS_UPDATE_REQUIRED) {
cwrite_short_B(cbuf, player->graphic.graphic_id);
cwrite_int_M(cbuf, player->graphic.height);
}
if (player->update_flags & PUFLAG_FACE_POSITION_UPDATE_REQUIRED) {
cwrite_short_L(cbuf, (player->face_position_abs_x * 2) + 1);
cwrite_short_BA(cbuf, (player->face_position_abs_y * 2) + 1);
}
if (player->update_flags & PUFLAG_CHAT_UPDATE_REQUIRED) {
cwrite_short_BA(cbuf, player->chat.effects);
cwrite_byte_C(cbuf, player->rights);
cwrite_byte_C(cbuf, player->chat.message_len);
player->chat.message[MAX_CHAT_LEN - 1] = '\0';
for (i = 0; i < player->chat.message_len; ++i) {
cwrite_byte(cbuf, player->chat.message[i]);
}
}
if (player->update_flags & PUFLAG_ANIM_UPDATE_REQUIRED) {
cwrite_short_B(cbuf, player->animation.anim_id);
cwrite_byte_S(cbuf, player->animation.delay);
}
if (player->update_flags & PUFLAG_APPEARANCE_UPDATE_REQUIRED) {
app_block_start_index = cwrite_byte(cbuf, 0); /* Placeholder */
cwrite_byte(cbuf, player->appearance.gender);
if ((player->appearance.gender & 0x2) == 2) {
cwrite_byte(cbuf, 0);
cwrite_byte(cbuf, 0);
}
cwrite_byte(cbuf, player->appearance.skull_icon);
cwrite_byte(cbuf, player->appearance.head_icon);
if (player->appearance.npc_id == -1) {
for (i = 0; i < 4; ++i) {
equip_item = &player->equipped_items[i];
if (equip_item->item_id != NO_ITEM_EQUIPPED) {
item_def = get_item_definition(equip_item->item_id);
cwrite_short_B(cbuf, 32768 + item_def->equip_id);
}
else {
cwrite_byte(cbuf, 0);
}
}
/* Chest slot */
equip_item = &player->equipped_items[EQUIPMENT_CHEST];
if (equip_item->item_id != NO_ITEM_EQUIPPED) {
item_def = get_item_definition(equip_item->item_id);
cwrite_short_B(cbuf, 32768 + item_def->equip_id);
}
else {
cwrite_short_B(cbuf, 0x100
+ player->appearance.looks[APPEARANCE_CHEST]);
}
/* Shield slot */
equip_item = &player->equipped_items[EQUIPMENT_SHIELD];
if (equip_item->item_id != NO_ITEM_EQUIPPED) {
item_def = get_item_definition(equip_item->item_id);
cwrite_short_B(cbuf, 32768 + item_def->equip_id);
}
else {
cwrite_byte(cbuf, 0);
}
/* Arms slot */
equip_item = &player->equipped_items[EQUIPMENT_CHEST];
if (equip_item->item_id != NO_ITEM_EQUIPPED) {
if (!is_full_body(equip_item->item_id)) {
cwrite_short_B(cbuf, 0x100
+ player->appearance.looks[APPEARANCE_ARMS]);
}
else {
cwrite_byte(cbuf, 0);
}
}
else {
cwrite_short_B(cbuf, 0x100
+ player->appearance.looks[APPEARANCE_ARMS]);
}
/* Legs slot */
equip_item = &player->equipped_items[EQUIPMENT_LEGS];
if (equip_item->item_id != NO_ITEM_EQUIPPED) {
item_def = get_item_definition(equip_item->item_id);
cwrite_short_B(cbuf, 32768 + item_def->equip_id);
}
else {
cwrite_short_B(cbuf, 0x100
+ player->appearance.looks[APPEARANCE_LEGS]);
}
/* Head slot */
equip_item = &player->equipped_items[EQUIPMENT_HAT];
if (equip_item->item_id != NO_ITEM_EQUIPPED) {
if (is_full_helm(equip_item->item_id) || is_full_mask(
equip_item->item_id)) {
cwrite_byte(cbuf, 0);
}
else {
cwrite_short_B(cbuf, 0x100
+ player->appearance.looks[APPEARANCE_HEAD]);
}
}
else {
cwrite_short_B(cbuf, 0x100
+ player->appearance.looks[APPEARANCE_HEAD]);
}
/* Hands slot */
equip_item = &player->equipped_items[EQUIPMENT_HANDS];
if (equip_item->item_id != NO_ITEM_EQUIPPED) {
item_def = get_item_definition(equip_item->item_id);
cwrite_short_B(cbuf, 32768 + item_def->equip_id);
}
else {
cwrite_short_B(cbuf, 0x100
+ player->appearance.looks[APPEARANCE_HANDS]);
}
/* Feet slot */
equip_item = &player->equipped_items[EQUIPMENT_FEET];
if (equip_item->item_id != NO_ITEM_EQUIPPED) {
item_def = get_item_definition(equip_item->item_id);
cwrite_short_B(cbuf, 32768 + item_def->equip_id);
}
else {
cwrite_short_B(cbuf, 0x100
+ player->appearance.looks[APPEARANCE_FEET]);
}
/* Beard slot */
equip_item = &player->equipped_items[EQUIPMENT_HAT];
if (equip_item->item_id != NO_ITEM_EQUIPPED) {
if (is_full_mask(equip_item->item_id)) {
cwrite_byte(cbuf, 0);
}
else {
cwrite_short_B(cbuf, 0x100
+ player->appearance.looks[APPEARANCE_BEARD]);
}
}
else {
cwrite_short_B(cbuf, 0x100
+ player->appearance.looks[APPEARANCE_BEARD]);
}
}
else {
cwrite_short_B(cbuf, -1);
cwrite_short_B(cbuf, player->appearance.npc_id);
}
for (i = 0; i < 7; ++i) {
cwrite_byte(cbuf, player->appearance.colours[i]);
}
/* Animation indices */
cwrite_short_B(cbuf, player->appearance.stand_anim);
cwrite_short_B(cbuf, 0x337);
cwrite_short_B(cbuf, player->appearance.walk_anim);
cwrite_short_B(cbuf, 0x334);
cwrite_short_B(cbuf, 0x335);
cwrite_short_B(cbuf, 0x336);
cwrite_short_B(cbuf, player->appearance.run_anim);
cwrite_long_B(cbuf, player->username_hash);
cwrite_byte(cbuf, player->combat_level);
cwrite_short_B(cbuf, 0);
/*
* We now need to write the size of the appearance
* update block into the placeholder that we
* set aside at the start.
* As we're using a circular buffer, we have to test
* for wraparound and deal with it.
*/
if (cbuf->write_offset > app_block_start_index) { /* No wraparound */
app_block_size = cbuf->write_offset - app_block_start_index;
cbuf->buffer[app_block_start_index] = app_block_size;
}
else { /* Wraparound occurred */
app_block_size = cbuf->write_offset;
app_block_size += sizeof(cbuf->buffer) - app_block_start_index;
cbuf->buffer[app_block_start_index] = app_block_size;
}
}
if (player->update_flags & PUFLAG_PRIMARY_HIT_UPDATE_REQUIRED) {
if (player->cur_skill_levels[SKILL_HITPOINTS] < 0) {
player->cur_skill_levels[SKILL_HITPOINTS] = 0;
}
hp_ratio = (player->cur_skill_levels[SKILL_HITPOINTS] * 255)
/ player->max_skill_levels[SKILL_HITPOINTS];
if (hp_ratio > 255) {
hp_ratio = 255;
}
cwrite_byte_S(cbuf, player->primary_damage.amount);
cwrite_byte_S(cbuf, player->primary_damage.type);
cwrite_byte_S(cbuf, hp_ratio);
}
return 1;
}
int append_npc_update_blocks(struct npc *npc, struct circular_buffer *cbuf)
{
if (npc->update_flags & NUFLAG_FACE_MOB_UPDATE_REQUIRED) {
}
if (npc->update_flags & NUFLAG_NPC_TRANSFORM_UPDATE_REQUIRED) {
}
if (npc->update_flags & NUFLAG_FORCED_CHAT_UPDATE_REQUIRED) {
}
if (npc->update_flags & NUFLAG_ANIM_UPDATE_REQUIRED) {
}
if (npc->update_flags & NUFLAG_GRAPHICS_UPDATE_REQUIRED) {
}
if (npc->update_flags & NUFLAG_SECONDARY_HIT_UPDATE_REQUIRED) {
}
if (npc->update_flags & NUFLAG_FACE_POSITION_UPDATE_REQUIRED) {
}
if (npc->update_flags & NUFLAG_PRIMARY_HIT_UPDATE_REQUIRED) {
}
return 1;
}