~stilbruch/cobble

52bfdaf725522c981413b75116a578d51c697c4e — stilbruch 2 years ago 3d0d0c9
HUGE commit! Added a new packet generation script, and implemented all
functions required for the code that is generated to compile.
32 files changed, 4095 insertions(+), 151 deletions(-)

M .gitignore
M Makefile
M README
M include/cobble/cobble.h
M include/cobble/error.h
A include/cobble/nbt.h
M include/cobble/protocol/decode.h
M include/cobble/protocol/encode.h
M include/cobble/protocol/packet.h
M include/cobble/protocol/types.h
M include/cobble/server.h
A include/cobble/versioned/736/decode_packet.h
A include/cobble/versioned/736/encode_packet.h
A include/cobble/versioned/736/includes.h
A include/cobble/versioned/736/packets.h
R cobble.cfg => resources/cobble.cfg
A scripts/gen_packets.py
M src/client.c
M src/data/queue.c
M src/protocol/decode.c
M src/protocol/encode.c
M src/server.c
A src/versioned/736/decode_packet.c
A src/versioned/736/encode_packet.c
A test/Makefile
R test/{data/buffer.c => src/data/buffer.c}
R test/{data/queue.c => src/data/queue.c}
R test/{data/vector.c => src/data/vector.c}
R test/{main.c => src/main.c}
R test/{protocol/decode.c => src/protocol/decode.c}
R test/{protocol/encode.c => src/protocol/encode.c}
R test/{test.h => src/test.h}
M .gitignore => .gitignore +3 -1
@@ 1,3 1,5 @@
.vscode/

./cobble
\ No newline at end of file
obj/
bin/
test/cobble_tests
\ No newline at end of file

M Makefile => Makefile +70 -27
@@ 1,38 1,81 @@
EXE = cobble 
TEST_EXE = cobble_tests
#Compiler and Linker
CC          := gcc

CC = gcc
CFLAGS := -Iinclude/ -flto -std=gnu99
DEBUG_CFLAGS := -DDEBUG -g3 -gdwarf-2 -Wall -Wextra -Wshadow -Wdouble-promotion -fno-common
LIBS += -lpthread -luev -linih
#The Target Binary Program
TARGET      := cobble
TEST_TARGET	:= cobble_tests

SRC := $(shell find src/ -name "*.c")
TEST_SRC := $(shell find src/ ! -name "main.c" -name "*.c")
TEST_SRC += test/main.c
#The Directories, Source, Includes, Objects, Binary and Resources
SRCDIR		:= src
INCDIR		:= include
TESTDIR		:= test
BUILDDIR	:= obj
TARGETDIR	:= bin
RESDIR		:= resources
SRCEXT		:= c
DEPEXT		:= d
OBJEXT		:= o

.PHONY: build check clean debug run test
#Flags, Libraries and Includes
CFLAGS		:= -flto -std=c99
R_CFLAGS	:= -O3 -s
DBG_FLAGS	:= -DDEBUG -O0 -g -g3 -gdwarf-2 -Wall -Wextra -Wshadow -Wdouble-promotion -fno-common
LD_FLAGS	:= 
LIB			:= -lpthread -luev -linih
INC			:= -I$(INCDIR) -I/usr/local/include
INCDEP		:= -I$(INCDIR)

build: CFLAGS += -O3
build: $(EXE)
SOURCES     := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
OBJECTS     := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.$(OBJEXT)))

clean:
	$(RM) $(EXE)
	$(RM) $(TEST_EXE)
#Defauilt Make
all: resources $(TARGET)

#Remake
remake: cleaner all

# build release
release: CFLAGS += $(R_CFLAGS)
release: all

# build debug
debug: CFLAGS += $(DBG_FLAGS)
debug: LD_FLAGS += -g3 -gdwarf-2
debug: all

check: clean test
	./cobble_tests
#Copy Resources from Resources Directory to Target Directory
resources: directories
	@cp $(RESDIR)/* $(TARGETDIR)/

#Make the Directories
directories:
	@mkdir -p $(TARGETDIR)
	@mkdir -p $(BUILDDIR)

#Clean only Objects
clean:
	@$(RM) -rf $(BUILDDIR)

debug: CFLAGS += $(DEBUG_CFLAGS)
debug: $(EXE)
#Full Clean, Objects and Binaries
cleaner: clean
	@$(RM) -rf $(TARGETDIR)

run:
	./$(EXE)
#Pull in dependency info for *existing* .o files
-include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT))

test: CFLAGS += $(DEBUG_CFLAGS)
test: $(TEST_EXE)
#Link
$(TARGET): $(OBJECTS)
	$(CC) $(LD_FLAGS) -o $(TARGETDIR)/$(TARGET) $^ $(LIB)

$(EXE):
	$(CC) $(SRC) $(LDFLAGS) $(CFLAGS) $(LIBS) -o $(EXE)
#Compile
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT)
	@mkdir -p $(dir $@)
	$(CC) $(CFLAGS) $(INC) -c -o $@ $<
	@$(CC) $(CFLAGS) $(INCDEP) -MM $(SRCDIR)/$*.$(SRCEXT) > $(BUILDDIR)/$*.$(DEPEXT)
	@cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp
	@sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT)
	@sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT)
	@rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp

$(TEST_EXE):
	$(CC) $(TEST_SRC) $(LDFLAGS) $(CFLAGS) $(LIBS) -o $(TEST_EXE)
\ No newline at end of file
#Non-File Targets
.PHONY: all remake clean cleaner resources release debug
\ No newline at end of file

M README => README +2 -2
@@ 7,7 7,7 @@
                                             \\:  .  /
             cobble                           ||:   |
                                              ||:.  |
     a minecraft server in c                  ||:  .|
     a minecraft server in c99                ||:  .|
                                              ||:   |       \,/
                                              ||: , |            /`\
                                              ||:   |


@@ 17,7 17,7 @@
 -~--~                   ~---__ ,--~'                  ~~----_____-~'   `~--

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 
LAST UPDATED: 2020-11-07 ~ stilbruch
LAST UPDATED: 2020-11-22 ~ stilbruch
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 
[Table of Contents]:
...0: What is this?

M include/cobble/cobble.h => include/cobble/cobble.h +6 -0
@@ 3,6 3,12 @@
#define _COBBLE_COBBLE_H_

#define COBBLE_VERSION "0.0.1"
#define MC_VERSION 736

/* versioned info */
#if MC_VERSION == 736
    #include <cobble/versioned/736/includes.h>
#endif

#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))


M include/cobble/error.h => include/cobble/error.h +4 -3
@@ 9,6 9,10 @@
    ENTRY(E_SUCCESS, "Success")\
    ENTRY(E_FAILED, "Failed")\
    ENTRY(E_INVALID_PARAM, "Invalid parameter")\
    ENTRY(E_NOT_IMPLEMENTED, "Not implemented")\
    ENTRY(E_OOB, "Out of bounds")\
    ENTRY(E_OVERFLOW, "Overflow")\
    ENTRY(E_UNDERFLOW, "Underflow")\
    ENTRY(E_ASSERT, "Assert failed")\
    ENTRY(E_CALLOC, "Calloc failed")\
    ENTRY(E_MALLOC, "Malloc failed")\


@@ 20,9 24,6 @@
    ENTRY(E_DECODE_INVALID, "Invalid input to decoder")\
    ENTRY(E_ENCODE_INVALID, "Invalid input to encoder")\
    ENTRY(E_PKT_DATA_INVALID, "Invalid packet data")\
    ENTRY(E_VECTOR_OOB, "Vector access out of bounds")\
    ENTRY(E_VECTOR_UNDERFLOW, "Vector underflow")\
    ENTRY(E_QUEUE_UNDERFLOW, "Queue underflow")

enum cbl_error {
    #define ENTRY(e, d) e,

A include/cobble/nbt.h => include/cobble/nbt.h +7 -0
@@ 0,0 1,7 @@
/* see LICENSE for copyright and license details */
#ifndef _COBBLE_NBT_H_
#define _COBBLE_NBT_H_

struct nbt {};

#endif

M include/cobble/protocol/decode.h => include/cobble/protocol/decode.h +12 -0
@@ 2,6 2,7 @@
#ifndef _COBBLE_PROTO_DECODE_H_
#define _COBBLE_PROTO_DECODE_H_

#include <stdbool.h>
#include <stdint.h>

#include <cobble/client.h>


@@ 11,9 12,20 @@

CBL_ERROR cbl_decode_i8(struct queue*, int8_t*);
CBL_ERROR cbl_decode_i16(struct queue*, int16_t*);
CBL_ERROR cbl_decode_i32(struct queue*, int32_t*);
CBL_ERROR cbl_decode_i64(struct queue*, int64_t*);
CBL_ERROR cbl_decode_u8(struct queue*, uint8_t*);
CBL_ERROR cbl_decode_u16(struct queue*, uint16_t*);
CBL_ERROR cbl_decode_u32(struct queue*, uint32_t*);
CBL_ERROR cbl_decode_u64(struct queue*, uint64_t*);
CBL_ERROR cbl_decode_f32(struct queue*, float*);
CBL_ERROR cbl_decode_f64(struct queue*, double*);
CBL_ERROR cbl_decode_bool(struct queue*, bool*);
CBL_ERROR cbl_decode_varint(struct queue*, mc_varint*);
CBL_ERROR cbl_decode_string(struct queue*, mc_string*);
CBL_ERROR cbl_decode_slot(struct queue*, struct slot*);
CBL_ERROR cbl_decode_position(struct queue*, struct position*);
CBL_ERROR cbl_decode_uuid(struct queue*, struct uuid*);
CBL_ERROR cbl_decode_packet(struct queue*, struct cbl_client*, struct packet*);

#endif
\ No newline at end of file

M include/cobble/protocol/encode.h => include/cobble/protocol/encode.h +11 -0
@@ 3,14 3,25 @@
#define _COBBLE_PROTO_ENCODE_H_

#include <cobble/data/vector.h>
#include <cobble/nbt.h>
#include <cobble/protocol/packet.h>
#include <cobble/protocol/types.h>

CBL_ERROR cbl_encode_i8(struct vector*, int8_t);
CBL_ERROR cbl_encode_i16(struct vector*, int16_t);
CBL_ERROR cbl_encode_i32(struct vector*, int32_t);
CBL_ERROR cbl_encode_i64(struct vector*, int64_t);
CBL_ERROR cbl_encode_u8(struct vector*, uint8_t);
CBL_ERROR cbl_encode_f32(struct vector*, float);
CBL_ERROR cbl_encode_f64(struct vector*, double);
CBL_ERROR cbl_encode_bool(struct vector*, bool);
CBL_ERROR cbl_encode_varint(struct vector*, mc_varint);
CBL_ERROR cbl_encode_varint_before(struct vector*, mc_varint);
CBL_ERROR cbl_encode_string(struct vector*, mc_string);
CBL_ERROR cbl_encode_slot(struct vector*, struct slot*);
CBL_ERROR cbl_encode_position(struct vector*, struct position*);
CBL_ERROR cbl_encode_uuid(struct vector*, struct uuid*);
CBL_ERROR cbl_encode_nbt(struct vector*, struct nbt*);
CBL_ERROR cbl_encode_packet(struct vector *, struct packet*);

#endif
\ No newline at end of file

M include/cobble/protocol/packet.h => include/cobble/protocol/packet.h +7 -34
@@ 5,9 5,12 @@
#include <stdbool.h>
#include <stdint.h>

#include <cobble/cobble.h>
#include <cobble/error.h>
#include <cobble/protocol/types.h>

#include COBBLE_VERSIONED_PACKETS_H

enum protocol_state {
    PROTO_HANDSHAKE,
    PROTO_STATUS,


@@ 15,43 18,13 @@ enum protocol_state {
    PROTO_PLAY
};

/* name, id, clientbound, state, struct, */
#define PACKET_TABLE\
    ENTRY(HANDSHAKE,    0x00, false,    HANDSHAKE,    pkt_handshake)\
    ENTRY(REQUEST,      0x00, false,    STATUS,       pkt_status_request)\
    ENTRY(PING,         0x01, false,    STATUS,       pkt_ping)\
    ENTRY(RESPONSE,     0x00, true,     STATUS,       pkt_status_response)\
    ENTRY(PONG,         0x01, true,     STATUS,       pkt_pong)\

enum packet_type {
    PKT_INVALID = -1,
    #define ENTRY(n, i, c, s, t) PKT_##s##_##n,
    PACKET_TABLE
    #define ENTRY(i,c,s,n,t) n,
    PACKET_INFO_TABLE
    #undef ENTRY
};

struct pkt_handshake {
    mc_varint protocol_version;
    mc_string server_address;
    uint16_t server_port;
    mc_varint next_state;
};

struct pkt_status_request {
};

struct pkt_ping {
    int64_t payload;
};

struct pkt_status_response {
    mc_string json_response;
};

struct pkt_pong {
    int64_t payload;
};

struct packet {
    void *data;
    enum packet_type type;


@@ 66,8 39,8 @@ struct packet_info {
};

static const struct packet_info PACKET_INFO[] = {
    #define ENTRY(n, i, c, s, t) [PKT_##s##_##n] = {.id = i, .state = PROTO_##s, .clientbound = c, .struct_size = sizeof(struct t), .name = #n},
    PACKET_TABLE
    #define ENTRY(i,c,s,n,t) [n] = {.id = i, .state = PROTO_##s, .clientbound = c, .struct_size = sizeof(struct t), .name = #n},
    PACKET_INFO_TABLE
    #undef ENTRY
};


M include/cobble/protocol/types.h => include/cobble/protocol/types.h +17 -1
@@ 5,8 5,24 @@
#include <stddef.h>
#include <stdint.h>

/* typedefs */
typedef int32_t mc_varint;
typedef char* mc_string;

struct __attribute__((packed)) position {
    int32_t x :26;
    int16_t y :12;
    int32_t z :26;
};

struct __attribute__((packed)) uuid {
    uint64_t uuid1;
    uint64_t uuid2;
};

struct slot {
    /* is there an item in this slot */
    bool present;
};


#endif
\ No newline at end of file

M include/cobble/server.h => include/cobble/server.h +1 -1
@@ 2,10 2,10 @@
#ifndef _COBBLE_SERVER_H_
#define _COBBLE_SERVER_H_

#include <netinet/in.h>
#include <pthread.h>
#include <stdint.h>
#include <stdbool.h>
#include <uv.h>
#include <uev/uev.h>

#include <cobble/config.h>

A include/cobble/versioned/736/decode_packet.h => include/cobble/versioned/736/decode_packet.h +164 -0
@@ 0,0 1,164 @@
/* see LICENSE file for copyright and license details. */
#ifndef _COBBLE_VERSIONED_736_DECODE_PACKET_H_
#define _COBBLE_VERSIONED_736_DECODE_PACKET_H_

#include <cobble/data/queue.h>
#include <cobble/error.h>
#include <cobble/protocol/packet.h>

CBL_ERROR pkt_set_protocol_decode(struct queue*, struct packet*);
CBL_ERROR pkt_legacy_server_list_ping_decode(struct queue*, struct packet*);
CBL_ERROR pkt_server_info_decode(struct queue*, struct packet*);
CBL_ERROR pkt_pong_decode(struct queue*, struct packet*);
CBL_ERROR pkt_ping_start_decode(struct queue*, struct packet*);
CBL_ERROR pkt_ping_decode(struct queue*, struct packet*);
CBL_ERROR pkt_disconnect_decode(struct queue*, struct packet*);
CBL_ERROR pkt_encryption_request_decode(struct queue*, struct packet*);
CBL_ERROR pkt_success_decode(struct queue*, struct packet*);
CBL_ERROR pkt_compress_decode(struct queue*, struct packet*);
CBL_ERROR pkt_login_plugin_request_decode(struct queue*, struct packet*);
CBL_ERROR pkt_login_start_decode(struct queue*, struct packet*);
CBL_ERROR pkt_encryption_response_decode(struct queue*, struct packet*);
CBL_ERROR pkt_login_plugin_response_decode(struct queue*, struct packet*);
CBL_ERROR pkt_spawn_entity_decode(struct queue*, struct packet*);
CBL_ERROR pkt_spawn_entity_experience_orb_decode(struct queue*, struct packet*);
CBL_ERROR pkt_spawn_entity_living_decode(struct queue*, struct packet*);
CBL_ERROR pkt_spawn_entity_painting_decode(struct queue*, struct packet*);
CBL_ERROR pkt_named_entity_spawn_decode(struct queue*, struct packet*);
CBL_ERROR pkt_animation_decode(struct queue*, struct packet*);
CBL_ERROR pkt_statistics_decode(struct queue*, struct packet*);
CBL_ERROR pkt_advancements_decode(struct queue*, struct packet*);
CBL_ERROR pkt_block_break_animation_decode(struct queue*, struct packet*);
CBL_ERROR pkt_tile_entity_data_decode(struct queue*, struct packet*);
CBL_ERROR pkt_block_action_decode(struct queue*, struct packet*);
CBL_ERROR pkt_block_change_decode(struct queue*, struct packet*);
CBL_ERROR pkt_boss_bar_decode(struct queue*, struct packet*);
CBL_ERROR pkt_difficulty_decode(struct queue*, struct packet*);
CBL_ERROR pkt_tab_complete_clientbound_decode(struct queue*, struct packet*);
CBL_ERROR pkt_declare_commands_decode(struct queue*, struct packet*);
CBL_ERROR pkt_face_player_decode(struct queue*, struct packet*);
CBL_ERROR pkt_nbt_query_response_decode(struct queue*, struct packet*);
CBL_ERROR pkt_chat_clientbound_decode(struct queue*, struct packet*);
CBL_ERROR pkt_multi_block_change_decode(struct queue*, struct packet*);
CBL_ERROR pkt_transaction_clientbound_decode(struct queue*, struct packet*);
CBL_ERROR pkt_close_window_clientbound_decode(struct queue*, struct packet*);
CBL_ERROR pkt_open_window_decode(struct queue*, struct packet*);
CBL_ERROR pkt_window_items_decode(struct queue*, struct packet*);
CBL_ERROR pkt_craft_progress_bar_decode(struct queue*, struct packet*);
CBL_ERROR pkt_set_slot_decode(struct queue*, struct packet*);
CBL_ERROR pkt_set_cooldown_decode(struct queue*, struct packet*);
CBL_ERROR pkt_plugin_message_clientbound_decode(struct queue*, struct packet*);
CBL_ERROR pkt_named_sound_effect_decode(struct queue*, struct packet*);
CBL_ERROR pkt_kick_disconnect_decode(struct queue*, struct packet*);
CBL_ERROR pkt_entity_status_decode(struct queue*, struct packet*);
CBL_ERROR pkt_explosion_decode(struct queue*, struct packet*);
CBL_ERROR pkt_unload_chunk_decode(struct queue*, struct packet*);
CBL_ERROR pkt_game_state_change_decode(struct queue*, struct packet*);
CBL_ERROR pkt_open_horse_window_decode(struct queue*, struct packet*);
CBL_ERROR pkt_keep_alive_clientbound_decode(struct queue*, struct packet*);
CBL_ERROR pkt_map_chunk_decode(struct queue*, struct packet*);
CBL_ERROR pkt_world_event_decode(struct queue*, struct packet*);
CBL_ERROR pkt_world_particles_decode(struct queue*, struct packet*);
CBL_ERROR pkt_update_light_decode(struct queue*, struct packet*);
CBL_ERROR pkt_login_decode(struct queue*, struct packet*);
CBL_ERROR pkt_map_decode(struct queue*, struct packet*);
CBL_ERROR pkt_trade_list_decode(struct queue*, struct packet*);
CBL_ERROR pkt_rel_entity_move_decode(struct queue*, struct packet*);
CBL_ERROR pkt_entity_move_look_decode(struct queue*, struct packet*);
CBL_ERROR pkt_entity_look_decode(struct queue*, struct packet*);
CBL_ERROR pkt_entity_decode(struct queue*, struct packet*);
CBL_ERROR pkt_vehicle_move_clientbound_decode(struct queue*, struct packet*);
CBL_ERROR pkt_open_book_decode(struct queue*, struct packet*);
CBL_ERROR pkt_open_sign_entity_decode(struct queue*, struct packet*);
CBL_ERROR pkt_craft_recipe_response_decode(struct queue*, struct packet*);
CBL_ERROR pkt_abilities_clientbound_decode(struct queue*, struct packet*);
CBL_ERROR pkt_combat_event_decode(struct queue*, struct packet*);
CBL_ERROR pkt_player_info_decode(struct queue*, struct packet*);
CBL_ERROR pkt_position_look_clientbound_decode(struct queue*, struct packet*);
CBL_ERROR pkt_unlock_recipes_decode(struct queue*, struct packet*);
CBL_ERROR pkt_entity_destroy_decode(struct queue*, struct packet*);
CBL_ERROR pkt_remove_entity_effect_decode(struct queue*, struct packet*);
CBL_ERROR pkt_resource_pack_send_decode(struct queue*, struct packet*);
CBL_ERROR pkt_respawn_decode(struct queue*, struct packet*);
CBL_ERROR pkt_entity_head_rotation_decode(struct queue*, struct packet*);
CBL_ERROR pkt_world_border_decode(struct queue*, struct packet*);
CBL_ERROR pkt_camera_decode(struct queue*, struct packet*);
CBL_ERROR pkt_held_item_change_clientbound_decode(struct queue*, struct packet*);
CBL_ERROR pkt_update_view_position_decode(struct queue*, struct packet*);
CBL_ERROR pkt_update_view_distance_decode(struct queue*, struct packet*);
CBL_ERROR pkt_scoreboard_display_objective_decode(struct queue*, struct packet*);
CBL_ERROR pkt_entity_metadata_decode(struct queue*, struct packet*);
CBL_ERROR pkt_attach_entity_decode(struct queue*, struct packet*);
CBL_ERROR pkt_entity_velocity_decode(struct queue*, struct packet*);
CBL_ERROR pkt_entity_equipment_decode(struct queue*, struct packet*);
CBL_ERROR pkt_experience_decode(struct queue*, struct packet*);
CBL_ERROR pkt_update_health_decode(struct queue*, struct packet*);
CBL_ERROR pkt_scoreboard_objective_decode(struct queue*, struct packet*);
CBL_ERROR pkt_set_passengers_decode(struct queue*, struct packet*);
CBL_ERROR pkt_teams_decode(struct queue*, struct packet*);
CBL_ERROR pkt_scoreboard_score_decode(struct queue*, struct packet*);
CBL_ERROR pkt_spawn_position_decode(struct queue*, struct packet*);
CBL_ERROR pkt_update_time_decode(struct queue*, struct packet*);
CBL_ERROR pkt_title_decode(struct queue*, struct packet*);
CBL_ERROR pkt_entity_sound_effect_decode(struct queue*, struct packet*);
CBL_ERROR pkt_stop_sound_decode(struct queue*, struct packet*);
CBL_ERROR pkt_sound_effect_decode(struct queue*, struct packet*);
CBL_ERROR pkt_playerlist_header_decode(struct queue*, struct packet*);
CBL_ERROR pkt_collect_decode(struct queue*, struct packet*);
CBL_ERROR pkt_entity_teleport_decode(struct queue*, struct packet*);
CBL_ERROR pkt_entity_update_attributes_decode(struct queue*, struct packet*);
CBL_ERROR pkt_entity_effect_decode(struct queue*, struct packet*);
CBL_ERROR pkt_select_advancement_tab_decode(struct queue*, struct packet*);
CBL_ERROR pkt_declare_recipes_decode(struct queue*, struct packet*);
CBL_ERROR pkt_tags_decode(struct queue*, struct packet*);
CBL_ERROR pkt_acknowledge_player_digging_decode(struct queue*, struct packet*);
CBL_ERROR pkt_teleport_confirm_decode(struct queue*, struct packet*);
CBL_ERROR pkt_query_block_nbt_decode(struct queue*, struct packet*);
CBL_ERROR pkt_set_difficulty_decode(struct queue*, struct packet*);
CBL_ERROR pkt_edit_book_decode(struct queue*, struct packet*);
CBL_ERROR pkt_query_entity_nbt_decode(struct queue*, struct packet*);
CBL_ERROR pkt_pick_item_decode(struct queue*, struct packet*);
CBL_ERROR pkt_name_item_decode(struct queue*, struct packet*);
CBL_ERROR pkt_select_trade_decode(struct queue*, struct packet*);
CBL_ERROR pkt_set_beacon_effect_decode(struct queue*, struct packet*);
CBL_ERROR pkt_update_command_block_decode(struct queue*, struct packet*);
CBL_ERROR pkt_update_command_block_minecart_decode(struct queue*, struct packet*);
CBL_ERROR pkt_update_structure_block_decode(struct queue*, struct packet*);
CBL_ERROR pkt_tab_complete_serverbound_decode(struct queue*, struct packet*);
CBL_ERROR pkt_chat_serverbound_decode(struct queue*, struct packet*);
CBL_ERROR pkt_client_command_decode(struct queue*, struct packet*);
CBL_ERROR pkt_settings_decode(struct queue*, struct packet*);
CBL_ERROR pkt_transaction_serverbound_decode(struct queue*, struct packet*);
CBL_ERROR pkt_enchant_item_decode(struct queue*, struct packet*);
CBL_ERROR pkt_window_click_decode(struct queue*, struct packet*);
CBL_ERROR pkt_close_window_serverbound_decode(struct queue*, struct packet*);
CBL_ERROR pkt_plugin_message_serverbound_decode(struct queue*, struct packet*);
CBL_ERROR pkt_use_entity_decode(struct queue*, struct packet*);
CBL_ERROR pkt_generate_structure_decode(struct queue*, struct packet*);
CBL_ERROR pkt_keep_alive_serverbound_decode(struct queue*, struct packet*);
CBL_ERROR pkt_lock_difficulty_decode(struct queue*, struct packet*);
CBL_ERROR pkt_position_decode(struct queue*, struct packet*);
CBL_ERROR pkt_position_look_serverbound_decode(struct queue*, struct packet*);
CBL_ERROR pkt_look_decode(struct queue*, struct packet*);
CBL_ERROR pkt_flying_decode(struct queue*, struct packet*);
CBL_ERROR pkt_vehicle_move_serverbound_decode(struct queue*, struct packet*);
CBL_ERROR pkt_steer_boat_decode(struct queue*, struct packet*);
CBL_ERROR pkt_craft_recipe_request_decode(struct queue*, struct packet*);
CBL_ERROR pkt_abilities_serverbound_decode(struct queue*, struct packet*);
CBL_ERROR pkt_block_dig_decode(struct queue*, struct packet*);
CBL_ERROR pkt_entity_action_decode(struct queue*, struct packet*);
CBL_ERROR pkt_steer_vehicle_decode(struct queue*, struct packet*);
CBL_ERROR pkt_crafting_book_data_decode(struct queue*, struct packet*);
CBL_ERROR pkt_resource_pack_receive_decode(struct queue*, struct packet*);
CBL_ERROR pkt_held_item_change_serverbound_decode(struct queue*, struct packet*);
CBL_ERROR pkt_set_creative_slot_decode(struct queue*, struct packet*);
CBL_ERROR pkt_update_jigsaw_block_decode(struct queue*, struct packet*);
CBL_ERROR pkt_update_sign_decode(struct queue*, struct packet*);
CBL_ERROR pkt_arm_animation_decode(struct queue*, struct packet*);
CBL_ERROR pkt_spectate_decode(struct queue*, struct packet*);
CBL_ERROR pkt_block_place_decode(struct queue*, struct packet*);
CBL_ERROR pkt_use_item_decode(struct queue*, struct packet*);
CBL_ERROR pkt_advancement_tab_decode(struct queue*, struct packet*);


#endif
\ No newline at end of file

A include/cobble/versioned/736/encode_packet.h => include/cobble/versioned/736/encode_packet.h +164 -0
@@ 0,0 1,164 @@
/* see LICENSE file for copyright and license details. */
#ifndef _COBBLE_VERSIONED_736_ENCODE_PACKET_H_
#define _COBBLE_VERSIONED_736_ENCODE_PACKET_H_

#include <cobble/data/vector.h>
#include <cobble/error.h>
#include <cobble/protocol/packet.h>

CBL_ERROR pkt_set_protocol_encode(struct vector*, struct packet*);
CBL_ERROR pkt_legacy_server_list_ping_encode(struct vector*, struct packet*);
CBL_ERROR pkt_server_info_encode(struct vector*, struct packet*);
CBL_ERROR pkt_pong_encode(struct vector*, struct packet*);
CBL_ERROR pkt_ping_start_encode(struct vector*, struct packet*);
CBL_ERROR pkt_ping_encode(struct vector*, struct packet*);
CBL_ERROR pkt_disconnect_encode(struct vector*, struct packet*);
CBL_ERROR pkt_encryption_request_encode(struct vector*, struct packet*);
CBL_ERROR pkt_success_encode(struct vector*, struct packet*);
CBL_ERROR pkt_compress_encode(struct vector*, struct packet*);
CBL_ERROR pkt_login_plugin_request_encode(struct vector*, struct packet*);
CBL_ERROR pkt_login_start_encode(struct vector*, struct packet*);
CBL_ERROR pkt_encryption_response_encode(struct vector*, struct packet*);
CBL_ERROR pkt_login_plugin_response_encode(struct vector*, struct packet*);
CBL_ERROR pkt_spawn_entity_encode(struct vector*, struct packet*);
CBL_ERROR pkt_spawn_entity_experience_orb_encode(struct vector*, struct packet*);
CBL_ERROR pkt_spawn_entity_living_encode(struct vector*, struct packet*);
CBL_ERROR pkt_spawn_entity_painting_encode(struct vector*, struct packet*);
CBL_ERROR pkt_named_entity_spawn_encode(struct vector*, struct packet*);
CBL_ERROR pkt_animation_encode(struct vector*, struct packet*);
CBL_ERROR pkt_statistics_encode(struct vector*, struct packet*);
CBL_ERROR pkt_advancements_encode(struct vector*, struct packet*);
CBL_ERROR pkt_block_break_animation_encode(struct vector*, struct packet*);
CBL_ERROR pkt_tile_entity_data_encode(struct vector*, struct packet*);
CBL_ERROR pkt_block_action_encode(struct vector*, struct packet*);
CBL_ERROR pkt_block_change_encode(struct vector*, struct packet*);
CBL_ERROR pkt_boss_bar_encode(struct vector*, struct packet*);
CBL_ERROR pkt_difficulty_encode(struct vector*, struct packet*);
CBL_ERROR pkt_tab_complete_clientbound_encode(struct vector*, struct packet*);
CBL_ERROR pkt_declare_commands_encode(struct vector*, struct packet*);
CBL_ERROR pkt_face_player_encode(struct vector*, struct packet*);
CBL_ERROR pkt_nbt_query_response_encode(struct vector*, struct packet*);
CBL_ERROR pkt_chat_clientbound_encode(struct vector*, struct packet*);
CBL_ERROR pkt_multi_block_change_encode(struct vector*, struct packet*);
CBL_ERROR pkt_transaction_clientbound_encode(struct vector*, struct packet*);
CBL_ERROR pkt_close_window_clientbound_encode(struct vector*, struct packet*);
CBL_ERROR pkt_open_window_encode(struct vector*, struct packet*);
CBL_ERROR pkt_window_items_encode(struct vector*, struct packet*);
CBL_ERROR pkt_craft_progress_bar_encode(struct vector*, struct packet*);
CBL_ERROR pkt_set_slot_encode(struct vector*, struct packet*);
CBL_ERROR pkt_set_cooldown_encode(struct vector*, struct packet*);
CBL_ERROR pkt_plugin_message_clientbound_encode(struct vector*, struct packet*);
CBL_ERROR pkt_named_sound_effect_encode(struct vector*, struct packet*);
CBL_ERROR pkt_kick_disconnect_encode(struct vector*, struct packet*);
CBL_ERROR pkt_entity_status_encode(struct vector*, struct packet*);
CBL_ERROR pkt_explosion_encode(struct vector*, struct packet*);
CBL_ERROR pkt_unload_chunk_encode(struct vector*, struct packet*);
CBL_ERROR pkt_game_state_change_encode(struct vector*, struct packet*);
CBL_ERROR pkt_open_horse_window_encode(struct vector*, struct packet*);
CBL_ERROR pkt_keep_alive_clientbound_encode(struct vector*, struct packet*);
CBL_ERROR pkt_map_chunk_encode(struct vector*, struct packet*);
CBL_ERROR pkt_world_event_encode(struct vector*, struct packet*);
CBL_ERROR pkt_world_particles_encode(struct vector*, struct packet*);
CBL_ERROR pkt_update_light_encode(struct vector*, struct packet*);
CBL_ERROR pkt_login_encode(struct vector*, struct packet*);
CBL_ERROR pkt_map_encode(struct vector*, struct packet*);
CBL_ERROR pkt_trade_list_encode(struct vector*, struct packet*);
CBL_ERROR pkt_rel_entity_move_encode(struct vector*, struct packet*);
CBL_ERROR pkt_entity_move_look_encode(struct vector*, struct packet*);
CBL_ERROR pkt_entity_look_encode(struct vector*, struct packet*);
CBL_ERROR pkt_entity_encode(struct vector*, struct packet*);
CBL_ERROR pkt_vehicle_move_clientbound_encode(struct vector*, struct packet*);
CBL_ERROR pkt_open_book_encode(struct vector*, struct packet*);
CBL_ERROR pkt_open_sign_entity_encode(struct vector*, struct packet*);
CBL_ERROR pkt_craft_recipe_response_encode(struct vector*, struct packet*);
CBL_ERROR pkt_abilities_clientbound_encode(struct vector*, struct packet*);
CBL_ERROR pkt_combat_event_encode(struct vector*, struct packet*);
CBL_ERROR pkt_player_info_encode(struct vector*, struct packet*);
CBL_ERROR pkt_position_look_clientbound_encode(struct vector*, struct packet*);
CBL_ERROR pkt_unlock_recipes_encode(struct vector*, struct packet*);
CBL_ERROR pkt_entity_destroy_encode(struct vector*, struct packet*);
CBL_ERROR pkt_remove_entity_effect_encode(struct vector*, struct packet*);
CBL_ERROR pkt_resource_pack_send_encode(struct vector*, struct packet*);
CBL_ERROR pkt_respawn_encode(struct vector*, struct packet*);
CBL_ERROR pkt_entity_head_rotation_encode(struct vector*, struct packet*);
CBL_ERROR pkt_world_border_encode(struct vector*, struct packet*);
CBL_ERROR pkt_camera_encode(struct vector*, struct packet*);
CBL_ERROR pkt_held_item_change_clientbound_encode(struct vector*, struct packet*);
CBL_ERROR pkt_update_view_position_encode(struct vector*, struct packet*);
CBL_ERROR pkt_update_view_distance_encode(struct vector*, struct packet*);
CBL_ERROR pkt_scoreboard_display_objective_encode(struct vector*, struct packet*);
CBL_ERROR pkt_entity_metadata_encode(struct vector*, struct packet*);
CBL_ERROR pkt_attach_entity_encode(struct vector*, struct packet*);
CBL_ERROR pkt_entity_velocity_encode(struct vector*, struct packet*);
CBL_ERROR pkt_entity_equipment_encode(struct vector*, struct packet*);
CBL_ERROR pkt_experience_encode(struct vector*, struct packet*);
CBL_ERROR pkt_update_health_encode(struct vector*, struct packet*);
CBL_ERROR pkt_scoreboard_objective_encode(struct vector*, struct packet*);
CBL_ERROR pkt_set_passengers_encode(struct vector*, struct packet*);
CBL_ERROR pkt_teams_encode(struct vector*, struct packet*);
CBL_ERROR pkt_scoreboard_score_encode(struct vector*, struct packet*);
CBL_ERROR pkt_spawn_position_encode(struct vector*, struct packet*);
CBL_ERROR pkt_update_time_encode(struct vector*, struct packet*);
CBL_ERROR pkt_title_encode(struct vector*, struct packet*);
CBL_ERROR pkt_entity_sound_effect_encode(struct vector*, struct packet*);
CBL_ERROR pkt_stop_sound_encode(struct vector*, struct packet*);
CBL_ERROR pkt_sound_effect_encode(struct vector*, struct packet*);
CBL_ERROR pkt_playerlist_header_encode(struct vector*, struct packet*);
CBL_ERROR pkt_collect_encode(struct vector*, struct packet*);
CBL_ERROR pkt_entity_teleport_encode(struct vector*, struct packet*);
CBL_ERROR pkt_entity_update_attributes_encode(struct vector*, struct packet*);
CBL_ERROR pkt_entity_effect_encode(struct vector*, struct packet*);
CBL_ERROR pkt_select_advancement_tab_encode(struct vector*, struct packet*);
CBL_ERROR pkt_declare_recipes_encode(struct vector*, struct packet*);
CBL_ERROR pkt_tags_encode(struct vector*, struct packet*);
CBL_ERROR pkt_acknowledge_player_digging_encode(struct vector*, struct packet*);
CBL_ERROR pkt_teleport_confirm_encode(struct vector*, struct packet*);
CBL_ERROR pkt_query_block_nbt_encode(struct vector*, struct packet*);
CBL_ERROR pkt_set_difficulty_encode(struct vector*, struct packet*);
CBL_ERROR pkt_edit_book_encode(struct vector*, struct packet*);
CBL_ERROR pkt_query_entity_nbt_encode(struct vector*, struct packet*);
CBL_ERROR pkt_pick_item_encode(struct vector*, struct packet*);
CBL_ERROR pkt_name_item_encode(struct vector*, struct packet*);
CBL_ERROR pkt_select_trade_encode(struct vector*, struct packet*);
CBL_ERROR pkt_set_beacon_effect_encode(struct vector*, struct packet*);
CBL_ERROR pkt_update_command_block_encode(struct vector*, struct packet*);
CBL_ERROR pkt_update_command_block_minecart_encode(struct vector*, struct packet*);
CBL_ERROR pkt_update_structure_block_encode(struct vector*, struct packet*);
CBL_ERROR pkt_tab_complete_serverbound_encode(struct vector*, struct packet*);
CBL_ERROR pkt_chat_serverbound_encode(struct vector*, struct packet*);
CBL_ERROR pkt_client_command_encode(struct vector*, struct packet*);
CBL_ERROR pkt_settings_encode(struct vector*, struct packet*);
CBL_ERROR pkt_transaction_serverbound_encode(struct vector*, struct packet*);
CBL_ERROR pkt_enchant_item_encode(struct vector*, struct packet*);
CBL_ERROR pkt_window_click_encode(struct vector*, struct packet*);
CBL_ERROR pkt_close_window_serverbound_encode(struct vector*, struct packet*);
CBL_ERROR pkt_plugin_message_serverbound_encode(struct vector*, struct packet*);
CBL_ERROR pkt_use_entity_encode(struct vector*, struct packet*);
CBL_ERROR pkt_generate_structure_encode(struct vector*, struct packet*);
CBL_ERROR pkt_keep_alive_serverbound_encode(struct vector*, struct packet*);
CBL_ERROR pkt_lock_difficulty_encode(struct vector*, struct packet*);
CBL_ERROR pkt_position_encode(struct vector*, struct packet*);
CBL_ERROR pkt_position_look_serverbound_encode(struct vector*, struct packet*);
CBL_ERROR pkt_look_encode(struct vector*, struct packet*);
CBL_ERROR pkt_flying_encode(struct vector*, struct packet*);
CBL_ERROR pkt_vehicle_move_serverbound_encode(struct vector*, struct packet*);
CBL_ERROR pkt_steer_boat_encode(struct vector*, struct packet*);
CBL_ERROR pkt_craft_recipe_request_encode(struct vector*, struct packet*);
CBL_ERROR pkt_abilities_serverbound_encode(struct vector*, struct packet*);
CBL_ERROR pkt_block_dig_encode(struct vector*, struct packet*);
CBL_ERROR pkt_entity_action_encode(struct vector*, struct packet*);
CBL_ERROR pkt_steer_vehicle_encode(struct vector*, struct packet*);
CBL_ERROR pkt_crafting_book_data_encode(struct vector*, struct packet*);
CBL_ERROR pkt_resource_pack_receive_encode(struct vector*, struct packet*);
CBL_ERROR pkt_held_item_change_serverbound_encode(struct vector*, struct packet*);
CBL_ERROR pkt_set_creative_slot_encode(struct vector*, struct packet*);
CBL_ERROR pkt_update_jigsaw_block_encode(struct vector*, struct packet*);
CBL_ERROR pkt_update_sign_encode(struct vector*, struct packet*);
CBL_ERROR pkt_arm_animation_encode(struct vector*, struct packet*);
CBL_ERROR pkt_spectate_encode(struct vector*, struct packet*);
CBL_ERROR pkt_block_place_encode(struct vector*, struct packet*);
CBL_ERROR pkt_use_item_encode(struct vector*, struct packet*);
CBL_ERROR pkt_advancement_tab_encode(struct vector*, struct packet*);


#endif
\ No newline at end of file

A include/cobble/versioned/736/includes.h => include/cobble/versioned/736/includes.h +9 -0
@@ 0,0 1,9 @@
/* see LICENSE file for copyright and license details. */
#ifndef _COBBLE_VERSIONED_736_INCLUDES_H_
#define _COBBLE_VERSIONED_736_INCLUDES_H_

#define COBBLE_VERSIONED_PACKETS_H <cobble/versioned/736/packets.h>
#define COBBLE_VERSIONED_DECODE_PACKET_H <cobble/versioned/736/decode_packet.h>
#define COBBLE_VERSIONED_ENCODE_PACKET_H <cobble/versioned/736/encode_packet.h>

#endif
\ No newline at end of file

A include/cobble/versioned/736/packets.h => include/cobble/versioned/736/packets.h +1179 -0
@@ 0,0 1,1179 @@
/* see LICENSE file for copyright and license details. */
#ifndef _COBBLE_VERSIONED_736_PACKETS_H_
#define _COBBLE_VERSIONED_736_PACKETS_H_

#include <stdbool.h>
#include <cobble/nbt.h>
#include <cobble/protocol/types.h>

struct pkt_set_protocol {
	mc_varint protocol_version;
	mc_string server_host;
	uint16_t server_port;
	mc_varint next_state;
};

struct pkt_legacy_server_list_ping {
	uint8_t payload;
};

struct pkt_server_info {
	mc_string response;
};

struct pkt_pong {
	int64_t time;
};

struct pkt_ping_start {
};

struct pkt_ping {
	int64_t time;
};

struct pkt_disconnect {
	mc_string reason;
};

struct pkt_encryption_request {
	mc_string server_id;
	mc_varint public_key_len;
	uint8_t *public_key;
	mc_varint verify_token_len;
	uint8_t *verify_token;
};

struct pkt_success {
	struct uuid uuid;
	mc_string username;
};

struct pkt_compress {
	mc_varint threshold;
};

struct pkt_login_plugin_request {
	mc_varint message_id;
	mc_string channel;
	/* data: restBuffer */
};

struct pkt_login_start {
	mc_string username;
};

struct pkt_encryption_response {
	mc_varint shared_secret_len;
	uint8_t *shared_secret;
	mc_varint verify_token_len;
	uint8_t *verify_token;
};

struct pkt_login_plugin_response {
	mc_varint message_id;
	bool has_data;
	/* data: restBuffer */;
};

struct pkt_spawn_entity {
	mc_varint entity_id;
	struct uuid object_u_u_i_d;
	mc_varint type;
	double x;
	double y;
	double z;
	int8_t pitch;
	int8_t yaw;
	int32_t object_data;
	int16_t velocity_x;
	int16_t velocity_y;
	int16_t velocity_z;
};

struct pkt_spawn_entity_experience_orb {
	mc_varint entity_id;
	double x;
	double y;
	double z;
	int16_t count;
};

struct pkt_spawn_entity_living {
	mc_varint entity_id;
	struct uuid entity_u_u_i_d;
	mc_varint type;
	double x;
	double y;
	double z;
	int8_t yaw;
	int8_t pitch;
	int8_t head_pitch;
	int16_t velocity_x;
	int16_t velocity_y;
	int16_t velocity_z;
};

struct pkt_spawn_entity_painting {
	mc_varint entity_id;
	struct uuid entity_u_u_i_d;
	mc_varint title;
	struct position location;
	uint8_t direction;
};

struct pkt_named_entity_spawn {
	mc_varint entity_id;
	struct uuid player_u_u_i_d;
	double x;
	double y;
	double z;
	int8_t yaw;
	int8_t pitch;
};

struct pkt_animation {
	mc_varint entity_id;
	uint8_t animation;
};

struct pkt_statistics {
	mc_varint entries_len;
	struct {} entries;
};

struct pkt_advancements {
	bool reset;
	mc_varint advancement_mapping_len;
	struct {} advancement_mapping;
	mc_varint identifiers_len;
	mc_string identifiers;
	mc_varint progress_mapping_len;
	struct {} progress_mapping;
};

struct pkt_block_break_animation {
	mc_varint entity_id;
	struct position location;
	int8_t destroy_stage;
};

struct pkt_tile_entity_data {
	struct position location;
	uint8_t action;
	struct nbt nbt_data;
};

struct pkt_block_action {
	struct position location;
	uint8_t byte1;
	uint8_t byte2;
	mc_varint block_id;
};

struct pkt_block_change {
	struct position location;
	mc_varint type;
};

struct pkt_boss_bar {
	struct uuid entity_u_u_i_d;
	mc_varint action;
	/* title: 0 */
	/* health: 0 */
	/* color: 0 */
	/* dividers: 0 */
	/* flags: 0 */
};

struct pkt_difficulty {
	uint8_t difficulty;
	bool difficulty_locked;
};

struct pkt_tab_complete_clientbound {
	mc_varint transaction_id;
	mc_varint start;
	mc_varint length;
	mc_varint matches_len;
	struct {} matches;
};

struct pkt_declare_commands {
	mc_varint nodes_len;
	struct {} nodes;
	mc_varint root_index;
};

struct pkt_face_player {
	mc_varint feet_eyes;
	double x;
	double y;
	double z;
	bool is_entity;
	/* entity_id: true */
	/* entity_feet_eyes: true */
};

struct pkt_nbt_query_response {
	mc_varint transaction_id;
	struct nbt nbt;
};

struct pkt_chat_clientbound {
	mc_string message;
	int8_t position;
	struct uuid sender;
};

struct pkt_multi_block_change {
	int32_t chunk_x;
	int32_t chunk_z;
	mc_varint records_len;
	struct {} records;
};

struct pkt_transaction_clientbound {
	int8_t window_id;
	int16_t action;
	bool accepted;
};

struct pkt_close_window_clientbound {
	uint8_t window_id;
};

struct pkt_open_window {
	mc_varint window_id;
	mc_varint inventory_type;
	mc_string window_title;
};

struct pkt_window_items {
	uint8_t window_id;
	int16_t items_len;
	struct slot items;
};

struct pkt_craft_progress_bar {
	uint8_t window_id;
	int16_t property;
	int16_t value;
};

struct pkt_set_slot {
	int8_t window_id;
	int16_t slot;
	struct slot item;
};

struct pkt_set_cooldown {
	mc_varint item_i_d;
	mc_varint cooldown_ticks;
};

struct pkt_plugin_message_clientbound {
	mc_string channel;
	/* data: restBuffer */
};

struct pkt_named_sound_effect {
	mc_string sound_name;
	mc_varint sound_category;
	int32_t x;
	int32_t y;
	int32_t z;
	float volume;
	float pitch;
};

struct pkt_kick_disconnect {
	mc_string reason;
};

struct pkt_entity_status {
	int32_t entity_id;
	int8_t entity_status;
};

struct pkt_explosion {
	float x;
	float y;
	float z;
	float radius;
	int32_t affected_block_offsets_len;
	struct {} affected_block_offsets;
	float player_motion_x;
	float player_motion_y;
	float player_motion_z;
};

struct pkt_unload_chunk {
	int32_t chunk_x;
	int32_t chunk_z;
};

struct pkt_game_state_change {
	uint8_t reason;
	float game_mode;
};

struct pkt_open_horse_window {
	uint8_t window_id;
	mc_varint nb_slots;
	int32_t entity_id;
};

struct pkt_keep_alive_clientbound {
	int64_t keep_alive_id;
};

struct pkt_map_chunk {
	int32_t x;
	int32_t z;
	bool ground_up;
	bool ignore_old_data;
	mc_varint bit_map;
	struct nbt heightmaps;
	/* biomes: false */
	mc_varint chunk_data_len;
	uint8_t *chunk_data;
	mc_varint block_entities_len;
	struct nbt block_entities;
};

struct pkt_world_event {
	int32_t effect_id;
	struct position location;
	int32_t data;
	bool global;
};

struct pkt_world_particles {
	int32_t particle_id;
	bool long_distance;
	double x;
	double y;
	double z;
	float offset_x;
	float offset_y;
	float offset_z;
	float particle_data;
	int32_t particles;
	/* data: ['particleData', {'compareTo': 'particleId'}] */
};

struct pkt_update_light {
	mc_varint chunk_x;
	mc_varint chunk_z;
	bool trust_edges;
	mc_varint sky_light_mask;
	mc_varint block_light_mask;
	mc_varint empty_sky_light_mask;
	mc_varint empty_block_light_mask;
	/* data: restBuffer */
};

struct pkt_login {
	int32_t entity_id;
	uint8_t game_mode;
	uint8_t previous_game_mode;
	mc_varint world_names_len;
	mc_string world_names;
	struct nbt dimension_codec;
	mc_string dimension;
	mc_string world_name;
	int64_t hashed_seed;
	uint8_t max_players;
	mc_varint view_distance;
	bool reduced_debug_info;
	bool enable_respawn_screen;
	bool is_debug;
	bool is_flat;
};

struct pkt_map {
	mc_varint item_damage;
	int8_t scale;
	bool tracking_position;
	bool locked;
	mc_varint icons_len;
	struct {} icons;
	int8_t columns;
	/* rows: 0 */
	/* x: 0 */
	/* y: 0 */
	/* data: 0 */
};

struct pkt_trade_list {
	mc_varint window_id;
	uint8_t trades_len;
	struct {} trades;
	mc_varint villager_level;
	mc_varint experience;
	bool is_regular_villager;
	bool can_restock;
};

struct pkt_rel_entity_move {
	mc_varint entity_id;
	int16_t d_x;
	int16_t d_y;
	int16_t d_z;
	bool on_ground;
};

struct pkt_entity_move_look {
	mc_varint entity_id;
	int16_t d_x;
	int16_t d_y;
	int16_t d_z;
	int8_t yaw;
	int8_t pitch;
	bool on_ground;
};

struct pkt_entity_look {
	mc_varint entity_id;
	int8_t yaw;
	int8_t pitch;
	bool on_ground;
};

struct pkt_entity {
	mc_varint entity_id;
};

struct pkt_vehicle_move_clientbound {
	double x;
	double y;
	double z;
	float yaw;
	float pitch;
};

struct pkt_open_book {
	mc_varint hand;
};

struct pkt_open_sign_entity {
	struct position location;
};

struct pkt_craft_recipe_response {
	int8_t window_id;
	mc_string recipe;
};

struct pkt_abilities_clientbound {
	int8_t flags;
	float flying_speed;
	float walking_speed;
};

struct pkt_combat_event {
	mc_varint event;
	/* duration: 1 */
	/* player_id: 2 */
	/* entity_id: 1 */
	/* message: 2 */
};

struct pkt_player_info {
	mc_varint action;
	mc_varint data_len;
	struct {} data;
};

struct pkt_position_look_clientbound {
	double x;
	double y;
	double z;
	float yaw;
	float pitch;
	int8_t flags;
	mc_varint teleport_id;
};

struct pkt_unlock_recipes {
	mc_varint action;
	bool crafting_book_open;
	bool filtering_craftable;
	bool smelting_book_open;
	bool filtering_smeltable;
	mc_varint recipes1_len;
	mc_string recipes1;
	/* recipes2: 0 */
};

struct pkt_entity_destroy {
	mc_varint entity_ids_len;
	mc_varint entity_ids;
};

struct pkt_remove_entity_effect {
	mc_varint entity_id;
	int8_t effect_id;
};

struct pkt_resource_pack_send {
	mc_string url;
	mc_string hash;
};

struct pkt_respawn {
	mc_string dimension;
	mc_string world_name;
	int64_t hashed_seed;
	uint8_t gamemode;
	uint8_t previous_gamemode;
	bool is_debug;
	bool is_flat;
	bool copy_metadata;
};

struct pkt_entity_head_rotation {
	mc_varint entity_id;
	int8_t head_yaw;
};

struct pkt_world_border {
	mc_varint action;
	/* radius: 0 */
	/* x: 2 */
	/* z: 2 */
	/* old_radius: 1 */
	/* new_radius: 1 */
	/* speed: 1 */
	/* portal_boundary: 3 */
	/* warning_time: 3 */
	/* warning_blocks: 3 */
};

struct pkt_camera {
	mc_varint camera_id;
};

struct pkt_held_item_change_clientbound {
	int8_t slot;
};

struct pkt_update_view_position {
	mc_varint chunk_x;
	mc_varint chunk_z;
};

struct pkt_update_view_distance {
	mc_varint view_distance;
};

struct pkt_scoreboard_display_objective {
	int8_t position;
	mc_string name;
};

struct pkt_entity_metadata {
	mc_varint entity_id;
	/* metadata: entityMetadata */
};

struct pkt_attach_entity {
	int32_t entity_id;
	int32_t vehicle_id;
};

struct pkt_entity_velocity {
	mc_varint entity_id;
	int16_t velocity_x;
	int16_t velocity_y;
	int16_t velocity_z;
};

struct pkt_entity_equipment {
	mc_varint entity_id;
	/* equipments: ['topBitSetTerminatedArray', {'type': ['container', [{'name': 'slot', 'type': 'i8'}, {'name': 'item', 'type': 'slot'}]]}] */
};

struct pkt_experience {
	float experience_bar;
	mc_varint level;
	mc_varint total_experience;
};

struct pkt_update_health {
	float health;
	mc_varint food;
	float food_saturation;
};

struct pkt_scoreboard_objective {
	mc_string name;
	int8_t action;
	/* display_text: 0 */
	/* type: 0 */
};

struct pkt_set_passengers {
	mc_varint entity_id;
	mc_varint passengers_len;
	mc_varint passengers;
};

struct pkt_teams {
	mc_string team;
	int8_t mode;
	/* name: 0 */
	/* friendly_fire: 0 */
	/* name_tag_visibility: 0 */
	/* collision_rule: 0 */
	/* formatting: 0 */
	/* prefix: 0 */
	/* suffix: 0 */
	/* players: 0 */
};

struct pkt_scoreboard_score {
	mc_string item_name;
	int8_t action;
	mc_string score_name;
	/* value: 1 */
};

struct pkt_spawn_position {
	struct position location;
};

struct pkt_update_time {
	int64_t age;
	int64_t time;
};

struct pkt_title {
	mc_varint action;
	/* text: 0 */
	/* fade_in: 3 */
	/* stay: 3 */
	/* fade_out: 3 */
};

struct pkt_entity_sound_effect {
	mc_varint sound_id;
	mc_varint sound_category;
	mc_varint entity_id;
	float volume;
	float pitch;
};

struct pkt_stop_sound {
	int8_t flags;
	/* source: 3 */
	/* sound: 3 */
};

struct pkt_sound_effect {
	mc_varint sound_id;
	mc_varint sound_category;
	int32_t x;
	int32_t y;
	int32_t z;
	float volume;
	float pitch;
};

struct pkt_playerlist_header {
	mc_string header;
	mc_string footer;
};

struct pkt_collect {
	mc_varint collected_entity_id;
	mc_varint collector_entity_id;
	mc_varint pickup_item_count;
};

struct pkt_entity_teleport {
	mc_varint entity_id;
	double x;
	double y;
	double z;
	int8_t yaw;
	int8_t pitch;
	bool on_ground;
};

struct pkt_entity_update_attributes {
	mc_varint entity_id;
	int32_t properties_len;
	struct {} properties;
};

struct pkt_entity_effect {
	mc_varint entity_id;
	int8_t effect_id;
	int8_t amplifier;
	mc_varint duration;
	int8_t hide_particles;
};

struct pkt_select_advancement_tab {
	bool has_id;
	mc_string id;;
};

struct pkt_declare_recipes {
	mc_varint recipes_len;
	struct {} recipes;
};

struct pkt_tags {
	/* blockTags: tags */
	/* itemTags: tags */
	/* fluidTags: tags */
	/* entityTags: tags */
};

struct pkt_acknowledge_player_digging {
	struct position location;
	mc_varint block;
	mc_varint status;
	bool successful;
};

struct pkt_teleport_confirm {
	mc_varint teleport_id;
};

struct pkt_query_block_nbt {
	mc_varint transaction_id;
	struct position location;
};

struct pkt_set_difficulty {
	uint8_t new_difficulty;
};

struct pkt_edit_book {
	struct slot new_book;
	bool signing;
	mc_varint hand;
};

struct pkt_query_entity_nbt {
	mc_varint transaction_id;
	mc_varint entity_id;
};

struct pkt_pick_item {
	mc_varint slot;
};

struct pkt_name_item {
	mc_string name;
};

struct pkt_select_trade {
	mc_varint slot;
};

struct pkt_set_beacon_effect {
	mc_varint primary_effect;
	mc_varint secondary_effect;
};

struct pkt_update_command_block {
	struct position location;
	mc_string command;
	mc_varint mode;
	uint8_t flags;
};

struct pkt_update_command_block_minecart {
	mc_varint entity_id;
	mc_string command;
	bool track_output;
};

struct pkt_update_structure_block {
	struct position location;
	mc_varint action;
	mc_varint mode;
	mc_string name;
	uint8_t offset_x;
	uint8_t offset_y;
	uint8_t offset_z;
	uint8_t size_x;
	uint8_t size_y;
	uint8_t size_z;
	mc_varint mirror;
	mc_varint rotation;
	mc_string metadata;
	float integrity;
	mc_varint seed;
	uint8_t flags;
};

struct pkt_tab_complete_serverbound {
	mc_varint transaction_id;
	mc_string text;
};

struct pkt_chat_serverbound {
	mc_string message;
};

struct pkt_client_command {
	mc_varint action_id;
};

struct pkt_settings {
	mc_string locale;
	int8_t view_distance;
	mc_varint chat_flags;
	bool chat_colors;
	uint8_t skin_parts;
	mc_varint main_hand;
};

struct pkt_transaction_serverbound {
	int8_t window_id;
	int16_t action;
	bool accepted;
};

struct pkt_enchant_item {
	int8_t window_id;
	int8_t enchantment;
};

struct pkt_window_click {
	uint8_t window_id;
	int16_t slot;
	int8_t mouse_button;
	int16_t action;
	int8_t mode;
	struct slot item;
};

struct pkt_close_window_serverbound {
	uint8_t window_id;
};

struct pkt_plugin_message_serverbound {
	mc_string channel;
	/* data: restBuffer */
};

struct pkt_use_entity {
	mc_varint target;
	mc_varint mouse;
	/* x: 2 */
	/* y: 2 */
	/* z: 2 */
	/* hand: 0 */
	bool sneaking;
};

struct pkt_generate_structure {
	struct position location;
	mc_varint levels;
	bool keep_jigsaws;
};

struct pkt_keep_alive_serverbound {
	int64_t keep_alive_id;
};

struct pkt_lock_difficulty {
	bool locked;
};

struct pkt_position {
	double x;
	double y;
	double z;
	bool on_ground;
};

struct pkt_position_look_serverbound {
	double x;
	double y;
	double z;
	float yaw;
	float pitch;
	bool on_ground;
};

struct pkt_look {
	float yaw;
	float pitch;
	bool on_ground;
};

struct pkt_flying {
	bool on_ground;
};

struct pkt_vehicle_move_serverbound {
	double x;
	double y;
	double z;
	float yaw;
	float pitch;
};

struct pkt_steer_boat {
	bool left_paddle;
	bool right_paddle;
};

struct pkt_craft_recipe_request {
	int8_t window_id;
	mc_string recipe;
	bool make_all;
};

struct pkt_abilities_serverbound {
	int8_t flags;
};

struct pkt_block_dig {
	int8_t status;
	struct position location;
	int8_t face;
};

struct pkt_entity_action {
	mc_varint entity_id;
	mc_varint action_id;
	mc_varint jump_boost;
};

struct pkt_steer_vehicle {
	float sideways;
	float forward;
	uint8_t jump;
};

struct pkt_crafting_book_data {
	mc_varint type;
	/* {'anon': True, 'type': ['switch', {'compareTo': 'type', 'fields': {'0': ['container', [{'name': 'displayedRecipe', 'type': 'string'}]], '1': ['container', [{'name': 'craftingBookOpen', 'type': 'bool'}, {'name': 'craftingFilter', 'type': 'bool'}, {'name': 'smeltingBookOpen', 'type': 'bool'}, {'name': 'smeltingFilter', 'type': 'bool'}, {'name': 'blastingBookOpen', 'type': 'bool'}, {'name': 'blastingFilter', 'type': 'bool'}, {'name': 'smokingBookOpen', 'type': 'bool'}, {'name': 'smokingFilter', 'type': 'bool'}]]}}]} */
};

struct pkt_resource_pack_receive {
	mc_varint result;
};

struct pkt_held_item_change_serverbound {
	int16_t slot_id;
};

struct pkt_set_creative_slot {
	int16_t slot;
	struct slot item;
};

struct pkt_update_jigsaw_block {
	struct position location;
	mc_string name;
	mc_string target;
	mc_string pool;
	mc_string final_state;
	mc_string joint_type;
};

struct pkt_update_sign {
	struct position location;
	mc_string text1;
	mc_string text2;
	mc_string text3;
	mc_string text4;
};

struct pkt_arm_animation {
	mc_varint hand;
};

struct pkt_spectate {
	struct uuid target;
};

struct pkt_block_place {
	mc_varint hand;
	struct position location;
	mc_varint direction;
	float cursor_x;
	float cursor_y;
	float cursor_z;
	bool inside_block;
};

struct pkt_use_item {
	mc_varint hand;
};

struct pkt_advancement_tab {
	mc_varint action;
	/* tab_id: 0 */
};

#define PACKET_INFO_TABLE_CB\
	ENTRY(0x00,	true,	STATUS, PKT_SERVER_INFO, pkt_server_info)\
	ENTRY(0x01,	true,	STATUS, PKT_PONG, pkt_pong)\
	ENTRY(0x00,	true,	LOGIN, PKT_DISCONNECT, pkt_disconnect)\
	ENTRY(0x01,	true,	LOGIN, PKT_ENCRYPTION_REQUEST, pkt_encryption_request)\
	ENTRY(0x02,	true,	LOGIN, PKT_SUCCESS, pkt_success)\
	ENTRY(0x03,	true,	LOGIN, PKT_COMPRESS, pkt_compress)\
	ENTRY(0x04,	true,	LOGIN, PKT_LOGIN_PLUGIN_REQUEST, pkt_login_plugin_request)\
	ENTRY(0x00,	true,	PLAY, PKT_SPAWN_ENTITY, pkt_spawn_entity)\
	ENTRY(0x01,	true,	PLAY, PKT_SPAWN_ENTITY_EXPERIENCE_ORB, pkt_spawn_entity_experience_orb)\
	ENTRY(0x02,	true,	PLAY, PKT_SPAWN_ENTITY_LIVING, pkt_spawn_entity_living)\
	ENTRY(0x03,	true,	PLAY, PKT_SPAWN_ENTITY_PAINTING, pkt_spawn_entity_painting)\
	ENTRY(0x04,	true,	PLAY, PKT_NAMED_ENTITY_SPAWN, pkt_named_entity_spawn)\
	ENTRY(0x05,	true,	PLAY, PKT_ANIMATION, pkt_animation)\
	ENTRY(0x06,	true,	PLAY, PKT_STATISTICS, pkt_statistics)\
	ENTRY(0x57,	true,	PLAY, PKT_ADVANCEMENTS, pkt_advancements)\
	ENTRY(0x08,	true,	PLAY, PKT_BLOCK_BREAK_ANIMATION, pkt_block_break_animation)\
	ENTRY(0x09,	true,	PLAY, PKT_TILE_ENTITY_DATA, pkt_tile_entity_data)\
	ENTRY(0x0a,	true,	PLAY, PKT_BLOCK_ACTION, pkt_block_action)\
	ENTRY(0x0b,	true,	PLAY, PKT_BLOCK_CHANGE, pkt_block_change)\
	ENTRY(0x0c,	true,	PLAY, PKT_BOSS_BAR, pkt_boss_bar)\
	ENTRY(0x0d,	true,	PLAY, PKT_DIFFICULTY, pkt_difficulty)\
	ENTRY(0x06,	true,	PLAY, PKT_TAB_COMPLETE_CLIENTBOUND, pkt_tab_complete_clientbound)\
	ENTRY(0x11,	true,	PLAY, PKT_DECLARE_COMMANDS, pkt_declare_commands)\
	ENTRY(0x34,	true,	PLAY, PKT_FACE_PLAYER, pkt_face_player)\
	ENTRY(0x54,	true,	PLAY, PKT_NBT_QUERY_RESPONSE, pkt_nbt_query_response)\
	ENTRY(0x03,	true,	PLAY, PKT_CHAT_CLIENTBOUND, pkt_chat_clientbound)\
	ENTRY(0x0f,	true,	PLAY, PKT_MULTI_BLOCK_CHANGE, pkt_multi_block_change)\
	ENTRY(0x07,	true,	PLAY, PKT_TRANSACTION_CLIENTBOUND, pkt_transaction_clientbound)\
	ENTRY(0x0a,	true,	PLAY, PKT_CLOSE_WINDOW_CLIENTBOUND, pkt_close_window_clientbound)\
	ENTRY(0x2e,	true,	PLAY, PKT_OPEN_WINDOW, pkt_open_window)\
	ENTRY(0x14,	true,	PLAY, PKT_WINDOW_ITEMS, pkt_window_items)\
	ENTRY(0x15,	true,	PLAY, PKT_CRAFT_PROGRESS_BAR, pkt_craft_progress_bar)\
	ENTRY(0x16,	true,	PLAY, PKT_SET_SLOT, pkt_set_slot)\
	ENTRY(0x17,	true,	PLAY, PKT_SET_COOLDOWN, pkt_set_cooldown)\
	ENTRY(0x0b,	true,	PLAY, PKT_PLUGIN_MESSAGE_CLIENTBOUND, pkt_plugin_message_clientbound)\
	ENTRY(0x19,	true,	PLAY, PKT_NAMED_SOUND_EFFECT, pkt_named_sound_effect)\
	ENTRY(0x1a,	true,	PLAY, PKT_KICK_DISCONNECT, pkt_kick_disconnect)\
	ENTRY(0x1b,	true,	PLAY, PKT_ENTITY_STATUS, pkt_entity_status)\
	ENTRY(0x1c,	true,	PLAY, PKT_EXPLOSION, pkt_explosion)\
	ENTRY(0x1d,	true,	PLAY, PKT_UNLOAD_CHUNK, pkt_unload_chunk)\
	ENTRY(0x1e,	true,	PLAY, PKT_GAME_STATE_CHANGE, pkt_game_state_change)\
	ENTRY(0x1f,	true,	PLAY, PKT_OPEN_HORSE_WINDOW, pkt_open_horse_window)\
	ENTRY(0x10,	true,	PLAY, PKT_KEEP_ALIVE_CLIENTBOUND, pkt_keep_alive_clientbound)\
	ENTRY(0x21,	true,	PLAY, PKT_MAP_CHUNK, pkt_map_chunk)\
	ENTRY(0x22,	true,	PLAY, PKT_WORLD_EVENT, pkt_world_event)\
	ENTRY(0x23,	true,	PLAY, PKT_WORLD_PARTICLES, pkt_world_particles)\
	ENTRY(0x24,	true,	PLAY, PKT_UPDATE_LIGHT, pkt_update_light)\
	ENTRY(0x25,	true,	PLAY, PKT_LOGIN, pkt_login)\
	ENTRY(0x26,	true,	PLAY, PKT_MAP, pkt_map)\
	ENTRY(0x27,	true,	PLAY, PKT_TRADE_LIST, pkt_trade_list)\
	ENTRY(0x28,	true,	PLAY, PKT_REL_ENTITY_MOVE, pkt_rel_entity_move)\
	ENTRY(0x29,	true,	PLAY, PKT_ENTITY_MOVE_LOOK, pkt_entity_move_look)\
	ENTRY(0x2a,	true,	PLAY, PKT_ENTITY_LOOK, pkt_entity_look)\
	ENTRY(0x2b,	true,	PLAY, PKT_ENTITY, pkt_entity)\
	ENTRY(0x16,	true,	PLAY, PKT_VEHICLE_MOVE_CLIENTBOUND, pkt_vehicle_move_clientbound)\
	ENTRY(0x2d,	true,	PLAY, PKT_OPEN_BOOK, pkt_open_book)\
	ENTRY(0x2f,	true,	PLAY, PKT_OPEN_SIGN_ENTITY, pkt_open_sign_entity)\
	ENTRY(0x30,	true,	PLAY, PKT_CRAFT_RECIPE_RESPONSE, pkt_craft_recipe_response)\
	ENTRY(0x1a,	true,	PLAY, PKT_ABILITIES_CLIENTBOUND, pkt_abilities_clientbound)\
	ENTRY(0x32,	true,	PLAY, PKT_COMBAT_EVENT, pkt_combat_event)\
	ENTRY(0x33,	true,	PLAY, PKT_PLAYER_INFO, pkt_player_info)\
	ENTRY(0x12,	true,	PLAY, PKT_POSITION_LOOK_CLIENTBOUND, pkt_position_look_clientbound)\
	ENTRY(0x36,	true,	PLAY, PKT_UNLOCK_RECIPES, pkt_unlock_recipes)\
	ENTRY(0x37,	true,	PLAY, PKT_ENTITY_DESTROY, pkt_entity_destroy)\
	ENTRY(0x38,	true,	PLAY, PKT_REMOVE_ENTITY_EFFECT, pkt_remove_entity_effect)\
	ENTRY(0x39,	true,	PLAY, PKT_RESOURCE_PACK_SEND, pkt_resource_pack_send)\
	ENTRY(0x3a,	true,	PLAY, PKT_RESPAWN, pkt_respawn)\
	ENTRY(0x3b,	true,	PLAY, PKT_ENTITY_HEAD_ROTATION, pkt_entity_head_rotation)\
	ENTRY(0x3d,	true,	PLAY, PKT_WORLD_BORDER, pkt_world_border)\
	ENTRY(0x3e,	true,	PLAY, PKT_CAMERA, pkt_camera)\
	ENTRY(0x24,	true,	PLAY, PKT_HELD_ITEM_CHANGE_CLIENTBOUND, pkt_held_item_change_clientbound)\
	ENTRY(0x40,	true,	PLAY, PKT_UPDATE_VIEW_POSITION, pkt_update_view_position)\
	ENTRY(0x41,	true,	PLAY, PKT_UPDATE_VIEW_DISTANCE, pkt_update_view_distance)\
	ENTRY(0x43,	true,	PLAY, PKT_SCOREBOARD_DISPLAY_OBJECTIVE, pkt_scoreboard_display_objective)\
	ENTRY(0x44,	true,	PLAY, PKT_ENTITY_METADATA, pkt_entity_metadata)\
	ENTRY(0x45,	true,	PLAY, PKT_ATTACH_ENTITY, pkt_attach_entity)\
	ENTRY(0x46,	true,	PLAY, PKT_ENTITY_VELOCITY, pkt_entity_velocity)\
	ENTRY(0x47,	true,	PLAY, PKT_ENTITY_EQUIPMENT, pkt_entity_equipment)\
	ENTRY(0x48,	true,	PLAY, PKT_EXPERIENCE, pkt_experience)\
	ENTRY(0x49,	true,	PLAY, PKT_UPDATE_HEALTH, pkt_update_health)\
	ENTRY(0x4a,	true,	PLAY, PKT_SCOREBOARD_OBJECTIVE, pkt_scoreboard_objective)\
	ENTRY(0x4b,	true,	PLAY, PKT_SET_PASSENGERS, pkt_set_passengers)\
	ENTRY(0x4c,	true,	PLAY, PKT_TEAMS, pkt_teams)\
	ENTRY(0x4d,	true,	PLAY, PKT_SCOREBOARD_SCORE, pkt_scoreboard_score)\
	ENTRY(0x42,	true,	PLAY, PKT_SPAWN_POSITION, pkt_spawn_position)\
	ENTRY(0x4e,	true,	PLAY, PKT_UPDATE_TIME, pkt_update_time)\
	ENTRY(0x4f,	true,	PLAY, PKT_TITLE, pkt_title)\
	ENTRY(0x50,	true,	PLAY, PKT_ENTITY_SOUND_EFFECT, pkt_entity_sound_effect)\
	ENTRY(0x52,	true,	PLAY, PKT_STOP_SOUND, pkt_stop_sound)\
	ENTRY(0x51,	true,	PLAY, PKT_SOUND_EFFECT, pkt_sound_effect)\
	ENTRY(0x53,	true,	PLAY, PKT_PLAYERLIST_HEADER, pkt_playerlist_header)\
	ENTRY(0x55,	true,	PLAY, PKT_COLLECT, pkt_collect)\
	ENTRY(0x56,	true,	PLAY, PKT_ENTITY_TELEPORT, pkt_entity_teleport)\
	ENTRY(0x58,	true,	PLAY, PKT_ENTITY_UPDATE_ATTRIBUTES, pkt_entity_update_attributes)\
	ENTRY(0x59,	true,	PLAY, PKT_ENTITY_EFFECT, pkt_entity_effect)\
	ENTRY(0x3c,	true,	PLAY, PKT_SELECT_ADVANCEMENT_TAB, pkt_select_advancement_tab)\
	ENTRY(0x5a,	true,	PLAY, PKT_DECLARE_RECIPES, pkt_declare_recipes)\
	ENTRY(0x5b,	true,	PLAY, PKT_TAGS, pkt_tags)\
	ENTRY(0x07,	true,	PLAY, PKT_ACKNOWLEDGE_PLAYER_DIGGING, pkt_acknowledge_player_digging)

#define PACKET_INFO_TABLE_SB\
	ENTRY(0x00,	false,	HANDSHAKE, PKT_SET_PROTOCOL, pkt_set_protocol)\
	ENTRY(0xfe,	false,	HANDSHAKE, PKT_LEGACY_SERVER_LIST_PING, pkt_legacy_server_list_ping)\
	ENTRY(0x00,	false,	STATUS, PKT_PING_START, pkt_ping_start)\
	ENTRY(0x01,	false,	STATUS, PKT_PING, pkt_ping)\
	ENTRY(0x00,	false,	LOGIN, PKT_LOGIN_START, pkt_login_start)\
	ENTRY(0x01,	false,	LOGIN, PKT_ENCRYPTION_RESPONSE, pkt_encryption_response)\
	ENTRY(0x02,	false,	LOGIN, PKT_LOGIN_PLUGIN_RESPONSE, pkt_login_plugin_response)\
	ENTRY(0x00,	false,	PLAY, PKT_TELEPORT_CONFIRM, pkt_teleport_confirm)\
	ENTRY(0x01,	false,	PLAY, PKT_QUERY_BLOCK_NBT, pkt_query_block_nbt)\
	ENTRY(0x02,	false,	PLAY, PKT_SET_DIFFICULTY, pkt_set_difficulty)\
	ENTRY(0x0c,	false,	PLAY, PKT_EDIT_BOOK, pkt_edit_book)\
	ENTRY(0x0d,	false,	PLAY, PKT_QUERY_ENTITY_NBT, pkt_query_entity_nbt)\
	ENTRY(0x18,	false,	PLAY, PKT_PICK_ITEM, pkt_pick_item)\
	ENTRY(0x1f,	false,	PLAY, PKT_NAME_ITEM, pkt_name_item)\
	ENTRY(0x22,	false,	PLAY, PKT_SELECT_TRADE, pkt_select_trade)\
	ENTRY(0x23,	false,	PLAY, PKT_SET_BEACON_EFFECT, pkt_set_beacon_effect)\
	ENTRY(0x25,	false,	PLAY, PKT_UPDATE_COMMAND_BLOCK, pkt_update_command_block)\
	ENTRY(0x26,	false,	PLAY, PKT_UPDATE_COMMAND_BLOCK_MINECART, pkt_update_command_block_minecart)\
	ENTRY(0x29,	false,	PLAY, PKT_UPDATE_STRUCTURE_BLOCK, pkt_update_structure_block)\
	ENTRY(0x06,	false,	PLAY, PKT_TAB_COMPLETE_SERVERBOUND, pkt_tab_complete_serverbound)\
	ENTRY(0x03,	false,	PLAY, PKT_CHAT_SERVERBOUND, pkt_chat_serverbound)\
	ENTRY(0x04,	false,	PLAY, PKT_CLIENT_COMMAND, pkt_client_command)\
	ENTRY(0x05,	false,	PLAY, PKT_SETTINGS, pkt_settings)\
	ENTRY(0x07,	false,	PLAY, PKT_TRANSACTION_SERVERBOUND, pkt_transaction_serverbound)\
	ENTRY(0x08,	false,	PLAY, PKT_ENCHANT_ITEM, pkt_enchant_item)\
	ENTRY(0x09,	false,	PLAY, PKT_WINDOW_CLICK, pkt_window_click)\
	ENTRY(0x0a,	false,	PLAY, PKT_CLOSE_WINDOW_SERVERBOUND, pkt_close_window_serverbound)\
	ENTRY(0x0b,	false,	PLAY, PKT_PLUGIN_MESSAGE_SERVERBOUND, pkt_plugin_message_serverbound)\
	ENTRY(0x0e,	false,	PLAY, PKT_USE_ENTITY, pkt_use_entity)\
	ENTRY(0x0f,	false,	PLAY, PKT_GENERATE_STRUCTURE, pkt_generate_structure)\
	ENTRY(0x10,	false,	PLAY, PKT_KEEP_ALIVE_SERVERBOUND, pkt_keep_alive_serverbound)\
	ENTRY(0x11,	false,	PLAY, PKT_LOCK_DIFFICULTY, pkt_lock_difficulty)\
	ENTRY(0x12,	false,	PLAY, PKT_POSITION, pkt_position)\
	ENTRY(0x13,	false,	PLAY, PKT_POSITION_LOOK_SERVERBOUND, pkt_position_look_serverbound)\
	ENTRY(0x14,	false,	PLAY, PKT_LOOK, pkt_look)\
	ENTRY(0x15,	false,	PLAY, PKT_FLYING, pkt_flying)\
	ENTRY(0x16,	false,	PLAY, PKT_VEHICLE_MOVE_SERVERBOUND, pkt_vehicle_move_serverbound)\
	ENTRY(0x17,	false,	PLAY, PKT_STEER_BOAT, pkt_steer_boat)\
	ENTRY(0x19,	false,	PLAY, PKT_CRAFT_RECIPE_REQUEST, pkt_craft_recipe_request)\
	ENTRY(0x1a,	false,	PLAY, PKT_ABILITIES_SERVERBOUND, pkt_abilities_serverbound)\
	ENTRY(0x1b,	false,	PLAY, PKT_BLOCK_DIG, pkt_block_dig)\
	ENTRY(0x1c,	false,	PLAY, PKT_ENTITY_ACTION, pkt_entity_action)\
	ENTRY(0x1d,	false,	PLAY, PKT_STEER_VEHICLE, pkt_steer_vehicle)\
	ENTRY(0x1e,	false,	PLAY, PKT_CRAFTING_BOOK_DATA, pkt_crafting_book_data)\
	ENTRY(0x20,	false,	PLAY, PKT_RESOURCE_PACK_RECEIVE, pkt_resource_pack_receive)\
	ENTRY(0x24,	false,	PLAY, PKT_HELD_ITEM_CHANGE_SERVERBOUND, pkt_held_item_change_serverbound)\
	ENTRY(0x27,	false,	PLAY, PKT_SET_CREATIVE_SLOT, pkt_set_creative_slot)\
	ENTRY(0x28,	false,	PLAY, PKT_UPDATE_JIGSAW_BLOCK, pkt_update_jigsaw_block)\
	ENTRY(0x2a,	false,	PLAY, PKT_UPDATE_SIGN, pkt_update_sign)\
	ENTRY(0x2b,	false,	PLAY, PKT_ARM_ANIMATION, pkt_arm_animation)\
	ENTRY(0x2c,	false,	PLAY, PKT_SPECTATE, pkt_spectate)\
	ENTRY(0x2d,	false,	PLAY, PKT_BLOCK_PLACE, pkt_block_place)\
	ENTRY(0x2e,	false,	PLAY, PKT_USE_ITEM, pkt_use_item)\
	ENTRY(0x21,	false,	PLAY, PKT_ADVANCEMENT_TAB, pkt_advancement_tab)

#define PACKET_INFO_TABLE PACKET_INFO_TABLE_CB PACKET_INFO_TABLE_SB

#endif
\ No newline at end of file

R cobble.cfg => resources/cobble.cfg +0 -0
A scripts/gen_packets.py => scripts/gen_packets.py +326 -0
@@ 0,0 1,326 @@
#!/bin/python3

import json
import sys
from pprint import pprint
from functools import reduce

PACKET_NAME_MAP = {
    "STATUS": {
        # clientbound
        "true": {
            "pkt_ping": "pkt_pong"
        }
    },
    "LOGIN": {
        # clientbound
        "true": {
            "pkt_encryption_begin": "pkt_encryption_request"
        },
        "false": {
            "pkt_encryption_begin": "pkt_encryption_response"
        }
    },
    "PLAY": {
        # clientbound
        "true": {
            "pkt_abilities": "pkt_abilities_clientbound",
            "pkt_chat": "pkt_chat_clientbound",
            "pkt_close_window": "pkt_close_window_clientbound",
            "pkt_custom_payload": "pkt_plugin_message_clientbound",
            "pkt_held_item_slot": "pkt_held_item_change_clientbound",
            "pkt_keep_alive": "pkt_keep_alive_clientbound",
            "pkt_position": "pkt_position_look_clientbound",
            "pkt_tab_complete": "pkt_tab_complete_clientbound",
            "pkt_transaction": "pkt_transaction_clientbound",
            "pkt_vehicle_move": "pkt_vehicle_move_clientbound",
        },
        "false": {
            "pkt_abilities": "pkt_abilities_serverbound",
            "pkt_chat": "pkt_chat_serverbound",
            "pkt_close_window": "pkt_close_window_serverbound",
            "pkt_custom_payload": "pkt_plugin_message_serverbound",
            "pkt_held_item_slot": "pkt_held_item_change_serverbound",
            "pkt_keep_alive": "pkt_keep_alive_serverbound",
            "pkt_position_look": "pkt_position_look_serverbound",
            "pkt_tab_complete": "pkt_tab_complete_serverbound",
            "pkt_transaction": "pkt_transaction_serverbound",
            "pkt_vehicle_move": "pkt_vehicle_move_serverbound",
        }
    }
}

TYPE_MAP = {
    "u8": "uint8_t",
    "u16": "uint16_t",
    "u32": "uint32_t",
    "u64": "uint64_t",
    "i8": "int8_t",
    "i16": "int16_t",
    "i32": "int32_t",
    "i64": "int64_t",
    "f32": "float",
    "f64": "double",
    "varint": "mc_varint",
    "varlong": "mc_varlong",
    "bool": "bool",
    "string": "mc_string",
    "position": "struct position",
    "UUID": "struct uuid",
    "uuid": "struct uuid",
    "nbt": "struct nbt",
    "optionalNbt": "struct nbt",
    "slot": "struct slot"
}

STATE_MAP = {
    "handshaking": "HANDSHAKE",
    "status": "STATUS",
    "login": "LOGIN",
    "play": "PLAY"
}

def gen_definition(name, t):
    i = gen_identifier(name)

    if type(t) is str:
        if t in TYPE_MAP:
            return f"{TYPE_MAP[t]} {i};"
    if type(t) is dict:
        return f"/* {name}: {t} */"
    if type(t) is list:
        if t[0] == "option":
            return f"bool has_{i};\n\t{gen_definition(i, t[1])};"
        if t[0] == "switch":
            tt = next(iter(t[1]["fields"]))
            return gen_definition(i, tt)
        if t[0] == "array":
            count_type = t[1]["countType"]
            return f'{gen_definition(f"{i}_len", count_type)}\n\t{gen_definition(i, t[1]["type"])}'
        if t[0] == "buffer":
            count_type = t[1]["countType"]
            return f'{gen_definition(f"{i}_len", count_type)}\n\tuint8_t *{i};'
        if t[0] == "container":
            output = "struct {"
            output += f"}} {i};"
            return output

    return f"/* {name}: {t} */"

def gen_identifier(id):
    if type(id) is str:
        return ''.join(['_'+i.lower() if i.isupper()  else i for i in id]).lstrip('_')  
    else:
        return id

def gen_struct(name, d):
    output = f"struct {name} {{\n"
    for field in d[1]:
        if ("name" in field and "type" in field):
            name = field["name"]
            output += f'\t{gen_definition(name, field["type"])}\n'
        else:
            output += f"\t{field}\n"
    output += "};"

    return output

def gen_decode_field(field):
    if "name" in field and "type" in field:
        i = gen_identifier(field["name"])
        t = field["type"]

        if type(t) is list:
            if t[0] == "switch":
                return f'/* {field} */'
        if type(t) is str:
            if t == "UUID": t = "uuid"

            if not t in ["restBuffer"]:
                return f'TRY_E(cbl_decode_{t}(q, &p->{i}));'

    return f'/* {field} */'


def gen_encode_field(field):
    if "name" in field and "type" in field:
        i = gen_identifier(field["name"])
        t = field["type"]

        if type(t) is list:
            if t[0] == "switch":
                return f'/* {field} */'
        if type(t) is str:
            if t == "UUID": t = "uuid"

            if not t in ["restBuffer", "tags", "entityMetadata", "optionalNbt"]:
                if t in TYPE_MAP and "struct" in TYPE_MAP[t]:
                    return f'TRY_E(cbl_encode_{t}(v, &p->{i}));'
                else:
                    return f'TRY_E(cbl_encode_{t}(v, p->{i}));'

    return f'/* {field} */'


def gen_decode_func(packet):
    output = f'inline CBL_ERROR\n{packet["name"]}_decode(struct queue *q, struct packet *packet)\n{{\n'
    output += f'\tstruct {packet["name"]} *p = packet->data;\n\n'

    for field in packet["type_data"][1]:
        output += f"\t{gen_decode_field(field)}\n"

    output += "\n\treturn E_SUCCESS;\n"
    output += '}'
    return output

def gen_encode_func(packet):
    output = f'inline CBL_ERROR\n{packet["name"]}_encode(struct vector *v, struct packet *packet)\n{{\n'
    output += f'\tstruct {packet["name"]} *p = packet->data;\n\n'

    for field in packet["type_data"][1]:
        output += f"\t{gen_encode_field(field)}\n"
        pass

    output += "\n\treturn E_SUCCESS;\n"
    output += '}'
    return output

ver = sys.argv[1]
df = f"scripts/data/{ver}/protocol.json"
with open(df) as f:
    data = json.load(f)

packets = []

for state in ["handshaking", "status", "login", "play"]:
    for direction in ["toClient", "toServer"]:
        for t in data[state][direction]["types"]:
            if not t.startswith("packet_"): continue

            packet = {
                "name": t,
                "state": STATE_MAP[state],
                "clientbound": "true" if direction == "toClient" else "false",
                "data": data[state][direction],
                "type_data": data[state][direction]["types"][t]
            }

            packets.append(packet)
        # apply mappings
        mappings = data[state][direction]["types"]["packet"][1][0]["type"][1]["mappings"]
        for key in mappings:
            for packet in packets:
                if packet["name"] == f'packet_{mappings[key]}':
                    packet["id"] = key

# sort packets
sorted(packets, key=lambda p: p["id"])

# rename all "packet" to pkt
for packet in packets:
    packet["name"] = packet["name"].replace("packet_", "pkt_")

# apply renames
for packet in packets:
    if packet["state"] in PACKET_NAME_MAP:
        n = PACKET_NAME_MAP[packet["state"]]
        if packet["clientbound"] in n:
            n = n[packet["clientbound"]]
            if packet["name"] in n:
                packet["name"] = n[packet["name"]]

# generate packets.h
with open(f"include/cobble/versioned/{ver}/packets.h", "w") as f:
    # header guards
    f.write("/* see LICENSE file for copyright and license details. */\n")
    f.write(f"#ifndef _COBBLE_VERSIONED_{ver}_PACKETS_H_\n")
    f.write(f"#define _COBBLE_VERSIONED_{ver}_PACKETS_H_\n\n")

    # includes
    for i in ["stdbool.h", "cobble/nbt.h", "cobble/protocol/types.h"]:
        f.write(f"#include <{i}>\n")
    f.write("\n")

    # packet structs
    for packet in packets:
        name = packet["name"]
        f.write(f'{gen_struct(name, packet["type_data"])}\n\n')

    # packet info table
    f.write("#define PACKET_INFO_TABLE_CB")
    for packet in packets:
        if packet["clientbound"] == "false": continue
        f.write(f'\\\n\tENTRY({packet["id"]},\t{packet["clientbound"]},\t{packet["state"]}, {packet["name"].upper()}, {packet["name"]})')

    f.write("\n\n#define PACKET_INFO_TABLE_SB")
    for packet in packets:
        if packet["clientbound"] == "true": continue
        f.write(f'\\\n\tENTRY({packet["id"]},\t{packet["clientbound"]},\t{packet["state"]}, {packet["name"].upper()}, {packet["name"]})')
        
    f.write("\n\n#define PACKET_INFO_TABLE PACKET_INFO_TABLE_CB PACKET_INFO_TABLE_SB")

    # close out header guards
    f.write("\n\n#endif")

# generate decode_packet.h
with open(f"include/cobble/versioned/{ver}/decode_packet.h", "w") as f:
    # header guards
    f.write("/* see LICENSE file for copyright and license details. */\n")
    f.write(f"#ifndef _COBBLE_VERSIONED_{ver}_DECODE_PACKET_H_\n")
    f.write(f"#define _COBBLE_VERSIONED_{ver}_DECODE_PACKET_H_\n\n")

    # includes
    for i in ["cobble/data/queue.h", "cobble/error.h", "cobble/protocol/packet.h"]:
        f.write(f"#include <{i}>\n")
    f.write("\n")

    for packet in packets:
        f.write(f'CBL_ERROR {packet["name"]}_decode(struct queue*, struct packet*);\n')

    # close out header guards
    f.write("\n\n#endif")

# generate encode_packet.h
with open(f"include/cobble/versioned/{ver}/encode_packet.h", "w") as f:
    # header guards
    f.write("/* see LICENSE file for copyright and license details. */\n")
    f.write(f"#ifndef _COBBLE_VERSIONED_{ver}_ENCODE_PACKET_H_\n")
    f.write(f"#define _COBBLE_VERSIONED_{ver}_ENCODE_PACKET_H_\n\n")

    # includes
    for i in ["cobble/data/vector.h", "cobble/error.h", "cobble/protocol/packet.h"]:
        f.write(f"#include <{i}>\n")
    f.write("\n")

    for packet in packets:
        f.write(f'CBL_ERROR {packet["name"]}_encode(struct vector*, struct packet*);\n')

    # close out header guards
    f.write("\n\n#endif")


# generate decode_packet.c
with open(f"src/versioned/{ver}/decode_packet.c", "w") as f:
    f.write("/* see LICENSE file for copyright and license details. */\n\n")

    for i in ["cobble/cobble.h", "cobble/data/queue.h",
                "cobble/error.h", "cobble/protocol/decode.h", "cobble/protocol/packet.h"]:
        f.write(f"#include <{i}>\n")
    f.write("\n#include COBBLE_VERSIONED_DECODE_PACKET_H")

    for packet in packets:
        if packet["clientbound"] == "true": continue
        f.write(f'\n\n{gen_decode_func(packet)}')

# generate encode_packet.c
with open(f"src/versioned/{ver}/encode_packet.c", "w") as f:
    f.write("/* see LICENSE file for copyright and license details. */\n\n")

    for i in ["cobble/cobble.h", "cobble/data/vector.h",
                "cobble/error.h", "cobble/protocol/encode.h", "cobble/protocol/packet.h"]:
        f.write(f"#include <{i}>\n")
    f.write("\n#include COBBLE_VERSIONED_ENCODE_PACKET_H")

    for packet in packets:
        if packet["clientbound"] == "false": continue
        f.write(f'\n\n{gen_encode_func(packet)}')
\ No newline at end of file

M src/client.c => src/client.c +1 -0
@@ 1,6 1,7 @@
/* see LICENSE file for copyright and license details. */

#include <assert.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>


M src/data/queue.c => src/data/queue.c +1 -1
@@ 137,7 137,7 @@ queue_dequeue(struct queue *q, void *output)
CBL_ERROR
queue_dequeue_range(struct queue *q, void *output, size_t n)
{
    if (queue_size(q) + n > q->vec.len) return E_UNDERFLOW;
    if (queue_size(q) < n) return E_UNDERFLOW;

    for (size_t i = 0;i < n;i++) {
        TRY_E(queue_dequeue(q, output + (i * q->vec.e_size)));

M src/protocol/decode.c => src/protocol/decode.c +85 -58
@@ 4,6 4,15 @@
#include <cobble/protocol/packet.h>
#include <cobble/protocol/decode.h>

#include COBBLE_VERSIONED_DECODE_PACKET_H

typedef CBL_ERROR (*pkt_func)(struct queue*, struct packet*);

static const pkt_func PACKET_DECODE_JT[] = {
    #define ENTRY(i,c,s,n,t) [n] = t##_decode,
    PACKET_INFO_TABLE_SB
};

CBL_ERROR
cbl_decode_i8(struct queue *q, int8_t *output)
{


@@ 27,6 36,20 @@ cbl_decode_i16(struct queue *q, int16_t *output)
}

CBL_ERROR
cbl_decode_i32(struct queue *q, int32_t *output)
{
    *output = 0;

    uint8_t read;
    for (int i = 3;i >= 0;i--) {
        TRY_E(queue_dequeue(q, &read));
        *output |= (uint64_t) read << (i * 8);
    }

    return E_SUCCESS;
}

CBL_ERROR
cbl_decode_i64(struct queue *q, int64_t *output)
{
    *output = 0;


@@ 40,6 63,48 @@ cbl_decode_i64(struct queue *q, int64_t *output)
    return E_SUCCESS;
}

inline CBL_ERROR
cbl_decode_u8(struct queue *q, uint8_t *output)
{
    return cbl_decode_i8(q, (int8_t*) output);
}

inline CBL_ERROR
cbl_decode_u16(struct queue *q, uint16_t *output)
{
    return cbl_decode_i16(q, (int16_t*) output);
}

inline CBL_ERROR
cbl_decode_u32(struct queue *q, uint32_t *output)
{
    return cbl_decode_i32(q, (int32_t*) output);
}

inline CBL_ERROR
cbl_decode_u64(struct queue *q, uint64_t *output)
{
    return cbl_decode_i64(q, (int64_t*) output);
}

CBL_ERROR
cbl_decode_f32(struct queue *q, float *output)
{
    return E_NOT_IMPLEMENTED;
}

CBL_ERROR
cbl_decode_f64(struct queue *q, double *output)
{
    return E_NOT_IMPLEMENTED;
}

inline CBL_ERROR
cbl_decode_bool(struct queue *q, bool *output)
{
    return cbl_decode_i8(q, (int8_t*) output);
}

CBL_ERROR
cbl_decode_varint(struct queue *q, mc_varint *output)
{


@@ 74,6 139,24 @@ cbl_decode_string(struct queue *q, mc_string *string)
    return E_SUCCESS;
}

CBL_ERROR
cbl_decode_slot(struct queue *q, struct slot *slot)
{
    return E_NOT_IMPLEMENTED;
}

CBL_ERROR
cbl_decode_position(struct queue *q, struct position *pos)
{
    return E_NOT_IMPLEMENTED;
}

CBL_ERROR
cbl_decode_uuid(struct queue *q, struct uuid *uuid)
{
    return E_NOT_IMPLEMENTED;
}

/* the most important function in cobble */
CBL_ERROR
cbl_decode_packet(struct queue *q, struct cbl_client *client, struct packet *packet)


@@ 85,7 168,7 @@ cbl_decode_packet(struct queue *q, struct cbl_client *client, struct packet *pac
    if (packet_type == PKT_INVALID) {
        log_warn("Unsupported packet { state: %d, id: %d }", client->protocol_state, packet_id);
        return E_DECODE_INVALID;
    }
    } 

    /* init the new packet */
    TRY_E(packet_init(packet, packet_type));


@@ 95,61 178,5 @@ cbl_decode_packet(struct queue *q, struct cbl_client *client, struct packet *pac
    /* allocate space for the packet data */
    packet->data = malloc(info.struct_size);

    if (packet->type == PKT_HANDSHAKE_HANDSHAKE) {
        struct pkt_handshake *p = packet->data;
        TRY_E(cbl_decode_varint(q, &p->protocol_version));
        TRY_E(cbl_decode_string(q, &p->server_address));
        TRY_E(cbl_decode_i16(q, &p->server_port));
        TRY_E(cbl_decode_varint(q, &p->next_state));

        /* TODO: replace with event handler */
        if (p->next_state == 1) client->protocol_state = PROTO_STATUS;
        else if (p->next_state == 2) client->protocol_state = PROTO_LOGIN;

        log_trace(
            "decode: handshake { ver: %d, addr: %s, port: %d, next: %d}",
            p->protocol_version,
            p->server_address,
            p->server_port,
            p->next_state
        );
    } else if (packet->type == PKT_STATUS_REQUEST) {
        log_trace("decode: status request {}");

        /* TODO: replace with event handler */
        struct packet *p;
        TRY_E(packet_new(&p, PKT_STATUS_RESPONSE));
        /* TODO */
        ((struct pkt_status_response*) p->data)->json_response = "{"
            "\"version\": {"
                "\"name\": \"1.16.4\","
                "\"protocol\": 754"
            "},"
            "\"players\": {"
                "\"max\": 5,"
                "\"online\": 0"
            "},"
            "\"description\": {"
                "\"text\": \"Hello from cobble\""
            "}"
        "}";
        TRY_E(cbl_client_send(client, p));
    } else if (packet->type == PKT_STATUS_PING) {
        struct pkt_ping *p = packet->data;
        TRY_E(cbl_decode_i64(q, &p->payload));

        log_trace("decode: ping { payload: %d }", p->payload);

        /* TODO: remove */
        struct packet *op;
        TRY_E(packet_new(&op, PKT_STATUS_PONG));
        ((struct pkt_pong*) op->data)->payload = p->payload;
        TRY_E(cbl_client_send(client, op));
        packet_free(op);
    } else {
        /* this should never happen */
        return E_DECODE_INVALID;
    }

    return E_SUCCESS;
    return PACKET_DECODE_JT[packet->type](q, packet);
}
\ No newline at end of file

M src/protocol/encode.c => src/protocol/encode.c +83 -16
@@ 4,6 4,16 @@

#include <cobble/protocol/encode.h>

#include COBBLE_VERSIONED_ENCODE_PACKET_H

typedef CBL_ERROR (*pkt_func)(struct vector*, struct packet*);

static const pkt_func PACKET_ENCODE_JT[] = {
    #define ENTRY(i,c,s,n,t) [n] = t##_encode,
    PACKET_INFO_TABLE_CB
};


CBL_ERROR
cbl_encode_i8(struct vector *v, int8_t input)
{


@@ 13,16 23,62 @@ cbl_encode_i8(struct vector *v, int8_t input)
}

CBL_ERROR
cbl_encode_i16(struct vector *v, int16_t input)
{
    for (int i = 1; i >= 0;i--) {
        int8_t in = input >> (8 * i);
        TRY_E(vector_push(v, &in));
    }

    return E_SUCCESS;
}

CBL_ERROR
cbl_encode_i32(struct vector *v, int32_t input)
{
    for (int i = 3; i >= 0;i--) {
        int8_t in = input >> (8 * i);
        TRY_E(vector_push(v, &in));
    }

    return E_SUCCESS;
}

CBL_ERROR
cbl_encode_i64(struct vector *v, int64_t input)
{
    for (int i = 0; i < 8;i++) {
        int8_t in = input >> (8 * (7 - i));
    for (int i = 7; i >= 0;i--) {
        int8_t in = input >> (8 * i);
        TRY_E(vector_push(v, &in));
    }

    return E_SUCCESS;
}

inline CBL_ERROR
cbl_encode_u8(struct vector *v, uint8_t input)
{
    return cbl_encode_i8(v, (int8_t) input);
}

CBL_ERROR
cbl_encode_f32(struct vector *v, float input)
{
    return E_NOT_IMPLEMENTED;
}

CBL_ERROR
cbl_encode_f64(struct vector *v, double input)
{
    return E_NOT_IMPLEMENTED;
}

inline CBL_ERROR
cbl_encode_bool(struct vector *v, bool input)
{
    return cbl_encode_i8(v, (int8_t) input);
}

CBL_ERROR
cbl_encode_varint(struct vector *v, mc_varint input)
{


@@ 50,6 106,30 @@ cbl_encode_string(struct vector *v, mc_string input)
    return E_SUCCESS;
}

CBL_ERROR
cbl_encode_slot(struct vector *v, struct slot *slot)
{
    return E_NOT_IMPLEMENTED;
}

CBL_ERROR
cbl_encode_position(struct vector *v, struct position *pos)
{
    return E_NOT_IMPLEMENTED;
}

CBL_ERROR
cbl_encode_uuid(struct vector *v, struct uuid *uuid)
{
    return E_NOT_IMPLEMENTED;
}

CBL_ERROR
cbl_encode_nbt(struct vector *v, struct nbt *nbt)
{
    return E_NOT_IMPLEMENTED;
}

/*!
 * NOTE: Does not write packet lenght
 */


@@ 64,18 144,5 @@ cbl_encode_packet(struct vector *v, struct packet *packet)

    TRY_E(cbl_encode_varint(v, info.id));

    if (packet->type == PKT_STATUS_RESPONSE) {
        struct pkt_status_response *p = packet->data;
        
        TRY_E(cbl_encode_string(v, p->json_response));
    } else if (packet->type == PKT_STATUS_PONG) {
        struct pkt_pong *p = packet->data;

        TRY_E(cbl_encode_i64(v, p->payload));
    } else {
        /* this should never happen */
        return E_ENCODE_INVALID;
    }

    return E_SUCCESS;
    return PACKET_ENCODE_JT[info.id](v, packet); 
}
\ No newline at end of file

M src/server.c => src/server.c +3 -1
@@ 1,5 1,7 @@
/* see LICENSE file for copyright and license details. */

#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <unistd.h>



@@ 67,7 69,7 @@ cbl_server_init(struct cbl_server *server)
    }

    /* no need to error check this */
    //setsockopt(server->fd, SOL_SOCKET, SO_REUSEADDR, 1, 1);
    setsockopt(server->fd, SOL_SOCKET, SO_REUSEADDR, 1, 1);

    /* set noblock */
    int flags = fcntl(server->fd, F_GETFL, 0);

A src/versioned/736/decode_packet.c => src/versioned/736/decode_packet.c +642 -0
@@ 0,0 1,642 @@
/* see LICENSE file for copyright and license details. */

#include <cobble/cobble.h>
#include <cobble/data/queue.h>
#include <cobble/error.h>
#include <cobble/protocol/decode.h>
#include <cobble/protocol/packet.h>

#include COBBLE_VERSIONED_DECODE_PACKET_H

inline CBL_ERROR
pkt_set_protocol_decode(struct queue *q, struct packet *packet)
{
	struct pkt_set_protocol *p = packet->data;

	TRY_E(cbl_decode_varint(q, &p->protocol_version));
	TRY_E(cbl_decode_string(q, &p->server_host));
	TRY_E(cbl_decode_u16(q, &p->server_port));
	TRY_E(cbl_decode_varint(q, &p->next_state));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_legacy_server_list_ping_decode(struct queue *q, struct packet *packet)
{
	struct pkt_legacy_server_list_ping *p = packet->data;

	TRY_E(cbl_decode_u8(q, &p->payload));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_ping_start_decode(struct queue *q, struct packet *packet)
{
	struct pkt_ping_start *p = packet->data;


	return E_SUCCESS;
}

inline CBL_ERROR
pkt_ping_decode(struct queue *q, struct packet *packet)
{
	struct pkt_ping *p = packet->data;

	TRY_E(cbl_decode_i64(q, &p->time));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_login_start_decode(struct queue *q, struct packet *packet)
{
	struct pkt_login_start *p = packet->data;

	TRY_E(cbl_decode_string(q, &p->username));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_encryption_response_decode(struct queue *q, struct packet *packet)
{
	struct pkt_encryption_response *p = packet->data;

	/* {'name': 'sharedSecret', 'type': ['buffer', {'countType': 'varint'}]} */
	/* {'name': 'verifyToken', 'type': ['buffer', {'countType': 'varint'}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_login_plugin_response_decode(struct queue *q, struct packet *packet)
{
	struct pkt_login_plugin_response *p = packet->data;

	TRY_E(cbl_decode_varint(q, &p->message_id));
	/* {'name': 'data', 'type': ['option', 'restBuffer']} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_teleport_confirm_decode(struct queue *q, struct packet *packet)
{
	struct pkt_teleport_confirm *p = packet->data;

	TRY_E(cbl_decode_varint(q, &p->teleport_id));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_query_block_nbt_decode(struct queue *q, struct packet *packet)
{
	struct pkt_query_block_nbt *p = packet->data;

	TRY_E(cbl_decode_varint(q, &p->transaction_id));
	TRY_E(cbl_decode_position(q, &p->location));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_set_difficulty_decode(struct queue *q, struct packet *packet)
{
	struct pkt_set_difficulty *p = packet->data;

	TRY_E(cbl_decode_u8(q, &p->new_difficulty));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_edit_book_decode(struct queue *q, struct packet *packet)
{
	struct pkt_edit_book *p = packet->data;

	TRY_E(cbl_decode_slot(q, &p->new_book));
	TRY_E(cbl_decode_bool(q, &p->signing));
	TRY_E(cbl_decode_varint(q, &p->hand));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_query_entity_nbt_decode(struct queue *q, struct packet *packet)
{
	struct pkt_query_entity_nbt *p = packet->data;

	TRY_E(cbl_decode_varint(q, &p->transaction_id));
	TRY_E(cbl_decode_varint(q, &p->entity_id));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_pick_item_decode(struct queue *q, struct packet *packet)
{
	struct pkt_pick_item *p = packet->data;

	TRY_E(cbl_decode_varint(q, &p->slot));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_name_item_decode(struct queue *q, struct packet *packet)
{
	struct pkt_name_item *p = packet->data;

	TRY_E(cbl_decode_string(q, &p->name));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_select_trade_decode(struct queue *q, struct packet *packet)
{
	struct pkt_select_trade *p = packet->data;

	TRY_E(cbl_decode_varint(q, &p->slot));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_set_beacon_effect_decode(struct queue *q, struct packet *packet)
{
	struct pkt_set_beacon_effect *p = packet->data;

	TRY_E(cbl_decode_varint(q, &p->primary_effect));
	TRY_E(cbl_decode_varint(q, &p->secondary_effect));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_update_command_block_decode(struct queue *q, struct packet *packet)
{
	struct pkt_update_command_block *p = packet->data;

	TRY_E(cbl_decode_position(q, &p->location));
	TRY_E(cbl_decode_string(q, &p->command));
	TRY_E(cbl_decode_varint(q, &p->mode));
	TRY_E(cbl_decode_u8(q, &p->flags));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_update_command_block_minecart_decode(struct queue *q, struct packet *packet)
{
	struct pkt_update_command_block_minecart *p = packet->data;

	TRY_E(cbl_decode_varint(q, &p->entity_id));
	TRY_E(cbl_decode_string(q, &p->command));
	TRY_E(cbl_decode_bool(q, &p->track_output));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_update_structure_block_decode(struct queue *q, struct packet *packet)
{
	struct pkt_update_structure_block *p = packet->data;

	TRY_E(cbl_decode_position(q, &p->location));
	TRY_E(cbl_decode_varint(q, &p->action));
	TRY_E(cbl_decode_varint(q, &p->mode));
	TRY_E(cbl_decode_string(q, &p->name));
	TRY_E(cbl_decode_u8(q, &p->offset_x));
	TRY_E(cbl_decode_u8(q, &p->offset_y));
	TRY_E(cbl_decode_u8(q, &p->offset_z));
	TRY_E(cbl_decode_u8(q, &p->size_x));
	TRY_E(cbl_decode_u8(q, &p->size_y));
	TRY_E(cbl_decode_u8(q, &p->size_z));
	TRY_E(cbl_decode_varint(q, &p->mirror));
	TRY_E(cbl_decode_varint(q, &p->rotation));
	TRY_E(cbl_decode_string(q, &p->metadata));
	TRY_E(cbl_decode_f32(q, &p->integrity));
	TRY_E(cbl_decode_varint(q, &p->seed));
	TRY_E(cbl_decode_u8(q, &p->flags));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_tab_complete_serverbound_decode(struct queue *q, struct packet *packet)
{
	struct pkt_tab_complete_serverbound *p = packet->data;

	TRY_E(cbl_decode_varint(q, &p->transaction_id));
	TRY_E(cbl_decode_string(q, &p->text));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_chat_serverbound_decode(struct queue *q, struct packet *packet)
{
	struct pkt_chat_serverbound *p = packet->data;

	TRY_E(cbl_decode_string(q, &p->message));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_client_command_decode(struct queue *q, struct packet *packet)
{
	struct pkt_client_command *p = packet->data;

	TRY_E(cbl_decode_varint(q, &p->action_id));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_settings_decode(struct queue *q, struct packet *packet)
{
	struct pkt_settings *p = packet->data;

	TRY_E(cbl_decode_string(q, &p->locale));
	TRY_E(cbl_decode_i8(q, &p->view_distance));
	TRY_E(cbl_decode_varint(q, &p->chat_flags));
	TRY_E(cbl_decode_bool(q, &p->chat_colors));
	TRY_E(cbl_decode_u8(q, &p->skin_parts));
	TRY_E(cbl_decode_varint(q, &p->main_hand));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_transaction_serverbound_decode(struct queue *q, struct packet *packet)
{
	struct pkt_transaction_serverbound *p = packet->data;

	TRY_E(cbl_decode_i8(q, &p->window_id));
	TRY_E(cbl_decode_i16(q, &p->action));
	TRY_E(cbl_decode_bool(q, &p->accepted));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_enchant_item_decode(struct queue *q, struct packet *packet)
{
	struct pkt_enchant_item *p = packet->data;

	TRY_E(cbl_decode_i8(q, &p->window_id));
	TRY_E(cbl_decode_i8(q, &p->enchantment));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_window_click_decode(struct queue *q, struct packet *packet)
{
	struct pkt_window_click *p = packet->data;

	TRY_E(cbl_decode_u8(q, &p->window_id));
	TRY_E(cbl_decode_i16(q, &p->slot));
	TRY_E(cbl_decode_i8(q, &p->mouse_button));
	TRY_E(cbl_decode_i16(q, &p->action));
	TRY_E(cbl_decode_i8(q, &p->mode));
	TRY_E(cbl_decode_slot(q, &p->item));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_close_window_serverbound_decode(struct queue *q, struct packet *packet)
{
	struct pkt_close_window_serverbound *p = packet->data;

	TRY_E(cbl_decode_u8(q, &p->window_id));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_plugin_message_serverbound_decode(struct queue *q, struct packet *packet)
{
	struct pkt_plugin_message_serverbound *p = packet->data;

	TRY_E(cbl_decode_string(q, &p->channel));
	/* {'name': 'data', 'type': 'restBuffer'} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_use_entity_decode(struct queue *q, struct packet *packet)
{
	struct pkt_use_entity *p = packet->data;

	TRY_E(cbl_decode_varint(q, &p->target));
	TRY_E(cbl_decode_varint(q, &p->mouse));
	/* {'name': 'x', 'type': ['switch', {'compareTo': 'mouse', 'fields': {'2': 'f32'}, 'default': 'void'}]} */
	/* {'name': 'y', 'type': ['switch', {'compareTo': 'mouse', 'fields': {'2': 'f32'}, 'default': 'void'}]} */
	/* {'name': 'z', 'type': ['switch', {'compareTo': 'mouse', 'fields': {'2': 'f32'}, 'default': 'void'}]} */
	/* {'name': 'hand', 'type': ['switch', {'compareTo': 'mouse', 'fields': {'0': 'varint', '2': 'varint'}, 'default': 'void'}]} */
	TRY_E(cbl_decode_bool(q, &p->sneaking));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_generate_structure_decode(struct queue *q, struct packet *packet)
{
	struct pkt_generate_structure *p = packet->data;

	TRY_E(cbl_decode_position(q, &p->location));
	TRY_E(cbl_decode_varint(q, &p->levels));
	TRY_E(cbl_decode_bool(q, &p->keep_jigsaws));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_keep_alive_serverbound_decode(struct queue *q, struct packet *packet)
{
	struct pkt_keep_alive_serverbound *p = packet->data;

	TRY_E(cbl_decode_i64(q, &p->keep_alive_id));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_lock_difficulty_decode(struct queue *q, struct packet *packet)
{
	struct pkt_lock_difficulty *p = packet->data;

	TRY_E(cbl_decode_bool(q, &p->locked));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_position_decode(struct queue *q, struct packet *packet)
{
	struct pkt_position *p = packet->data;

	TRY_E(cbl_decode_f64(q, &p->x));
	TRY_E(cbl_decode_f64(q, &p->y));
	TRY_E(cbl_decode_f64(q, &p->z));
	TRY_E(cbl_decode_bool(q, &p->on_ground));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_position_look_serverbound_decode(struct queue *q, struct packet *packet)
{
	struct pkt_position_look_serverbound *p = packet->data;

	TRY_E(cbl_decode_f64(q, &p->x));
	TRY_E(cbl_decode_f64(q, &p->y));
	TRY_E(cbl_decode_f64(q, &p->z));
	TRY_E(cbl_decode_f32(q, &p->yaw));
	TRY_E(cbl_decode_f32(q, &p->pitch));
	TRY_E(cbl_decode_bool(q, &p->on_ground));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_look_decode(struct queue *q, struct packet *packet)
{
	struct pkt_look *p = packet->data;

	TRY_E(cbl_decode_f32(q, &p->yaw));
	TRY_E(cbl_decode_f32(q, &p->pitch));
	TRY_E(cbl_decode_bool(q, &p->on_ground));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_flying_decode(struct queue *q, struct packet *packet)
{
	struct pkt_flying *p = packet->data;

	TRY_E(cbl_decode_bool(q, &p->on_ground));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_vehicle_move_serverbound_decode(struct queue *q, struct packet *packet)
{
	struct pkt_vehicle_move_serverbound *p = packet->data;

	TRY_E(cbl_decode_f64(q, &p->x));
	TRY_E(cbl_decode_f64(q, &p->y));
	TRY_E(cbl_decode_f64(q, &p->z));
	TRY_E(cbl_decode_f32(q, &p->yaw));
	TRY_E(cbl_decode_f32(q, &p->pitch));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_steer_boat_decode(struct queue *q, struct packet *packet)
{
	struct pkt_steer_boat *p = packet->data;

	TRY_E(cbl_decode_bool(q, &p->left_paddle));
	TRY_E(cbl_decode_bool(q, &p->right_paddle));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_craft_recipe_request_decode(struct queue *q, struct packet *packet)
{
	struct pkt_craft_recipe_request *p = packet->data;

	TRY_E(cbl_decode_i8(q, &p->window_id));
	TRY_E(cbl_decode_string(q, &p->recipe));
	TRY_E(cbl_decode_bool(q, &p->make_all));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_abilities_serverbound_decode(struct queue *q, struct packet *packet)
{
	struct pkt_abilities_serverbound *p = packet->data;

	TRY_E(cbl_decode_i8(q, &p->flags));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_block_dig_decode(struct queue *q, struct packet *packet)
{
	struct pkt_block_dig *p = packet->data;

	TRY_E(cbl_decode_i8(q, &p->status));
	TRY_E(cbl_decode_position(q, &p->location));
	TRY_E(cbl_decode_i8(q, &p->face));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_entity_action_decode(struct queue *q, struct packet *packet)
{
	struct pkt_entity_action *p = packet->data;

	TRY_E(cbl_decode_varint(q, &p->entity_id));
	TRY_E(cbl_decode_varint(q, &p->action_id));
	TRY_E(cbl_decode_varint(q, &p->jump_boost));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_steer_vehicle_decode(struct queue *q, struct packet *packet)
{
	struct pkt_steer_vehicle *p = packet->data;

	TRY_E(cbl_decode_f32(q, &p->sideways));
	TRY_E(cbl_decode_f32(q, &p->forward));
	TRY_E(cbl_decode_u8(q, &p->jump));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_crafting_book_data_decode(struct queue *q, struct packet *packet)
{
	struct pkt_crafting_book_data *p = packet->data;

	TRY_E(cbl_decode_varint(q, &p->type));
	/* {'anon': True, 'type': ['switch', {'compareTo': 'type', 'fields': {'0': ['container', [{'name': 'displayedRecipe', 'type': 'string'}]], '1': ['container', [{'name': 'craftingBookOpen', 'type': 'bool'}, {'name': 'craftingFilter', 'type': 'bool'}, {'name': 'smeltingBookOpen', 'type': 'bool'}, {'name': 'smeltingFilter', 'type': 'bool'}, {'name': 'blastingBookOpen', 'type': 'bool'}, {'name': 'blastingFilter', 'type': 'bool'}, {'name': 'smokingBookOpen', 'type': 'bool'}, {'name': 'smokingFilter', 'type': 'bool'}]]}}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_resource_pack_receive_decode(struct queue *q, struct packet *packet)
{
	struct pkt_resource_pack_receive *p = packet->data;

	TRY_E(cbl_decode_varint(q, &p->result));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_held_item_change_serverbound_decode(struct queue *q, struct packet *packet)
{
	struct pkt_held_item_change_serverbound *p = packet->data;

	TRY_E(cbl_decode_i16(q, &p->slot_id));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_set_creative_slot_decode(struct queue *q, struct packet *packet)
{
	struct pkt_set_creative_slot *p = packet->data;

	TRY_E(cbl_decode_i16(q, &p->slot));
	TRY_E(cbl_decode_slot(q, &p->item));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_update_jigsaw_block_decode(struct queue *q, struct packet *packet)
{
	struct pkt_update_jigsaw_block *p = packet->data;

	TRY_E(cbl_decode_position(q, &p->location));
	TRY_E(cbl_decode_string(q, &p->name));
	TRY_E(cbl_decode_string(q, &p->target));
	TRY_E(cbl_decode_string(q, &p->pool));
	TRY_E(cbl_decode_string(q, &p->final_state));
	TRY_E(cbl_decode_string(q, &p->joint_type));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_update_sign_decode(struct queue *q, struct packet *packet)
{
	struct pkt_update_sign *p = packet->data;

	TRY_E(cbl_decode_position(q, &p->location));
	TRY_E(cbl_decode_string(q, &p->text1));
	TRY_E(cbl_decode_string(q, &p->text2));
	TRY_E(cbl_decode_string(q, &p->text3));
	TRY_E(cbl_decode_string(q, &p->text4));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_arm_animation_decode(struct queue *q, struct packet *packet)
{
	struct pkt_arm_animation *p = packet->data;

	TRY_E(cbl_decode_varint(q, &p->hand));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_spectate_decode(struct queue *q, struct packet *packet)
{
	struct pkt_spectate *p = packet->data;

	TRY_E(cbl_decode_uuid(q, &p->target));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_block_place_decode(struct queue *q, struct packet *packet)
{
	struct pkt_block_place *p = packet->data;

	TRY_E(cbl_decode_varint(q, &p->hand));
	TRY_E(cbl_decode_position(q, &p->location));
	TRY_E(cbl_decode_varint(q, &p->direction));
	TRY_E(cbl_decode_f32(q, &p->cursor_x));
	TRY_E(cbl_decode_f32(q, &p->cursor_y));
	TRY_E(cbl_decode_f32(q, &p->cursor_z));
	TRY_E(cbl_decode_bool(q, &p->inside_block));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_use_item_decode(struct queue *q, struct packet *packet)
{
	struct pkt_use_item *p = packet->data;

	TRY_E(cbl_decode_varint(q, &p->hand));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_advancement_tab_decode(struct queue *q, struct packet *packet)
{
	struct pkt_advancement_tab *p = packet->data;

	TRY_E(cbl_decode_varint(q, &p->action));
	/* {'name': 'tabId', 'type': ['switch', {'compareTo': 'action', 'fields': {'0': 'string', '1': 'void'}}]} */

	return E_SUCCESS;
}
\ No newline at end of file

A src/versioned/736/encode_packet.c => src/versioned/736/encode_packet.c +1279 -0
@@ 0,0 1,1279 @@
/* see LICENSE file for copyright and license details. */

#include <cobble/cobble.h>
#include <cobble/data/vector.h>
#include <cobble/error.h>
#include <cobble/protocol/encode.h>
#include <cobble/protocol/packet.h>

#include COBBLE_VERSIONED_ENCODE_PACKET_H

inline CBL_ERROR
pkt_server_info_encode(struct vector *v, struct packet *packet)
{
	struct pkt_server_info *p = packet->data;

	TRY_E(cbl_encode_string(v, p->response));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_pong_encode(struct vector *v, struct packet *packet)
{
	struct pkt_pong *p = packet->data;

	TRY_E(cbl_encode_i64(v, p->time));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_disconnect_encode(struct vector *v, struct packet *packet)
{
	struct pkt_disconnect *p = packet->data;

	TRY_E(cbl_encode_string(v, p->reason));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_encryption_request_encode(struct vector *v, struct packet *packet)
{
	struct pkt_encryption_request *p = packet->data;

	TRY_E(cbl_encode_string(v, p->server_id));
	/* {'name': 'publicKey', 'type': ['buffer', {'countType': 'varint'}]} */
	/* {'name': 'verifyToken', 'type': ['buffer', {'countType': 'varint'}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_success_encode(struct vector *v, struct packet *packet)
{
	struct pkt_success *p = packet->data;

	TRY_E(cbl_encode_uuid(v, &p->uuid));
	TRY_E(cbl_encode_string(v, p->username));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_compress_encode(struct vector *v, struct packet *packet)
{
	struct pkt_compress *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->threshold));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_login_plugin_request_encode(struct vector *v, struct packet *packet)
{
	struct pkt_login_plugin_request *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->message_id));
	TRY_E(cbl_encode_string(v, p->channel));
	/* {'name': 'data', 'type': 'restBuffer'} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_spawn_entity_encode(struct vector *v, struct packet *packet)
{
	struct pkt_spawn_entity *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->entity_id));
	TRY_E(cbl_encode_uuid(v, &p->object_u_u_i_d));
	TRY_E(cbl_encode_varint(v, p->type));
	TRY_E(cbl_encode_f64(v, p->x));
	TRY_E(cbl_encode_f64(v, p->y));
	TRY_E(cbl_encode_f64(v, p->z));
	TRY_E(cbl_encode_i8(v, p->pitch));
	TRY_E(cbl_encode_i8(v, p->yaw));
	TRY_E(cbl_encode_i32(v, p->object_data));
	TRY_E(cbl_encode_i16(v, p->velocity_x));
	TRY_E(cbl_encode_i16(v, p->velocity_y));
	TRY_E(cbl_encode_i16(v, p->velocity_z));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_spawn_entity_experience_orb_encode(struct vector *v, struct packet *packet)
{
	struct pkt_spawn_entity_experience_orb *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->entity_id));
	TRY_E(cbl_encode_f64(v, p->x));
	TRY_E(cbl_encode_f64(v, p->y));
	TRY_E(cbl_encode_f64(v, p->z));
	TRY_E(cbl_encode_i16(v, p->count));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_spawn_entity_living_encode(struct vector *v, struct packet *packet)
{
	struct pkt_spawn_entity_living *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->entity_id));
	TRY_E(cbl_encode_uuid(v, &p->entity_u_u_i_d));
	TRY_E(cbl_encode_varint(v, p->type));
	TRY_E(cbl_encode_f64(v, p->x));
	TRY_E(cbl_encode_f64(v, p->y));
	TRY_E(cbl_encode_f64(v, p->z));
	TRY_E(cbl_encode_i8(v, p->yaw));
	TRY_E(cbl_encode_i8(v, p->pitch));
	TRY_E(cbl_encode_i8(v, p->head_pitch));
	TRY_E(cbl_encode_i16(v, p->velocity_x));
	TRY_E(cbl_encode_i16(v, p->velocity_y));
	TRY_E(cbl_encode_i16(v, p->velocity_z));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_spawn_entity_painting_encode(struct vector *v, struct packet *packet)
{
	struct pkt_spawn_entity_painting *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->entity_id));
	TRY_E(cbl_encode_uuid(v, &p->entity_u_u_i_d));
	TRY_E(cbl_encode_varint(v, p->title));
	TRY_E(cbl_encode_position(v, &p->location));
	TRY_E(cbl_encode_u8(v, p->direction));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_named_entity_spawn_encode(struct vector *v, struct packet *packet)
{
	struct pkt_named_entity_spawn *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->entity_id));
	TRY_E(cbl_encode_uuid(v, &p->player_u_u_i_d));
	TRY_E(cbl_encode_f64(v, p->x));
	TRY_E(cbl_encode_f64(v, p->y));
	TRY_E(cbl_encode_f64(v, p->z));
	TRY_E(cbl_encode_i8(v, p->yaw));
	TRY_E(cbl_encode_i8(v, p->pitch));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_animation_encode(struct vector *v, struct packet *packet)
{
	struct pkt_animation *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->entity_id));
	TRY_E(cbl_encode_u8(v, p->animation));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_statistics_encode(struct vector *v, struct packet *packet)
{
	struct pkt_statistics *p = packet->data;

	/* {'name': 'entries', 'type': ['array', {'countType': 'varint', 'type': ['container', [{'name': 'categoryId', 'type': 'varint'}, {'name': 'statisticId', 'type': 'varint'}, {'name': 'value', 'type': 'varint'}]]}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_advancements_encode(struct vector *v, struct packet *packet)
{
	struct pkt_advancements *p = packet->data;

	TRY_E(cbl_encode_bool(v, p->reset));
	/* {'name': 'advancementMapping', 'type': ['array', {'countType': 'varint', 'type': ['container', [{'name': 'key', 'type': 'string'}, {'name': 'value', 'type': ['container', [{'name': 'parentId', 'type': ['option', 'string']}, {'name': 'displayData', 'type': ['option', ['container', [{'name': 'title', 'type': 'string'}, {'name': 'description', 'type': 'string'}, {'name': 'icon', 'type': 'slot'}, {'name': 'frameType', 'type': 'varint'}, {'name': 'flags', 'type': ['bitfield', [{'name': '_unused', 'size': 29, 'signed': False}, {'name': 'hidden', 'size': 1, 'signed': False}, {'name': 'show_toast', 'size': 1, 'signed': False}, {'name': 'has_background_texture', 'size': 1, 'signed': False}]]}, {'name': 'backgroundTexture', 'type': ['switch', {'compareTo': 'flags/has_background_texture', 'fields': {'1': 'string'}, 'default': 'void'}]}, {'name': 'xCord', 'type': 'f32'}, {'name': 'yCord', 'type': 'f32'}]]]}, {'name': 'criteria', 'type': ['array', {'countType': 'varint', 'type': ['container', [{'name': 'key', 'type': 'string'}, {'name': 'value', 'type': 'void'}]]}]}, {'name': 'requirements', 'type': ['array', {'countType': 'varint', 'type': ['array', {'countType': 'varint', 'type': 'string'}]}]}]]}]]}]} */
	/* {'name': 'identifiers', 'type': ['array', {'countType': 'varint', 'type': 'string'}]} */
	/* {'name': 'progressMapping', 'type': ['array', {'countType': 'varint', 'type': ['container', [{'name': 'key', 'type': 'string'}, {'name': 'value', 'type': ['array', {'countType': 'varint', 'type': ['container', [{'name': 'criterionIdentifier', 'type': 'string'}, {'name': 'criterionProgress', 'type': ['option', 'i64']}]]}]}]]}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_block_break_animation_encode(struct vector *v, struct packet *packet)
{
	struct pkt_block_break_animation *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->entity_id));
	TRY_E(cbl_encode_position(v, &p->location));
	TRY_E(cbl_encode_i8(v, p->destroy_stage));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_tile_entity_data_encode(struct vector *v, struct packet *packet)
{
	struct pkt_tile_entity_data *p = packet->data;

	TRY_E(cbl_encode_position(v, &p->location));
	TRY_E(cbl_encode_u8(v, p->action));
	/* {'name': 'nbtData', 'type': 'optionalNbt'} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_block_action_encode(struct vector *v, struct packet *packet)
{
	struct pkt_block_action *p = packet->data;

	TRY_E(cbl_encode_position(v, &p->location));
	TRY_E(cbl_encode_u8(v, p->byte1));
	TRY_E(cbl_encode_u8(v, p->byte2));
	TRY_E(cbl_encode_varint(v, p->block_id));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_block_change_encode(struct vector *v, struct packet *packet)
{
	struct pkt_block_change *p = packet->data;

	TRY_E(cbl_encode_position(v, &p->location));
	TRY_E(cbl_encode_varint(v, p->type));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_boss_bar_encode(struct vector *v, struct packet *packet)
{
	struct pkt_boss_bar *p = packet->data;

	TRY_E(cbl_encode_uuid(v, &p->entity_u_u_i_d));
	TRY_E(cbl_encode_varint(v, p->action));
	/* {'name': 'title', 'type': ['switch', {'compareTo': 'action', 'fields': {'0': 'string', '3': 'string'}, 'default': 'void'}]} */
	/* {'name': 'health', 'type': ['switch', {'compareTo': 'action', 'fields': {'0': 'f32', '2': 'f32'}, 'default': 'void'}]} */
	/* {'name': 'color', 'type': ['switch', {'compareTo': 'action', 'fields': {'0': 'varint', '4': 'varint'}, 'default': 'void'}]} */
	/* {'name': 'dividers', 'type': ['switch', {'compareTo': 'action', 'fields': {'0': 'varint', '4': 'varint'}, 'default': 'void'}]} */
	/* {'name': 'flags', 'type': ['switch', {'compareTo': 'action', 'fields': {'0': 'u8', '5': 'u8'}, 'default': 'void'}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_difficulty_encode(struct vector *v, struct packet *packet)
{
	struct pkt_difficulty *p = packet->data;

	TRY_E(cbl_encode_u8(v, p->difficulty));
	TRY_E(cbl_encode_bool(v, p->difficulty_locked));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_tab_complete_clientbound_encode(struct vector *v, struct packet *packet)
{
	struct pkt_tab_complete_clientbound *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->transaction_id));
	TRY_E(cbl_encode_varint(v, p->start));
	TRY_E(cbl_encode_varint(v, p->length));
	/* {'name': 'matches', 'type': ['array', {'countType': 'varint', 'type': ['container', [{'name': 'match', 'type': 'string'}, {'name': 'tooltip', 'type': ['option', 'string']}]]}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_declare_commands_encode(struct vector *v, struct packet *packet)
{
	struct pkt_declare_commands *p = packet->data;

	/* {'name': 'nodes', 'type': ['array', {'countType': 'varint', 'type': ['container', [{'name': 'flags', 'type': ['bitfield', [{'name': 'unused', 'size': 3, 'signed': False}, {'name': 'has_custom_suggestions', 'size': 1, 'signed': False}, {'name': 'has_redirect_node', 'size': 1, 'signed': False}, {'name': 'has_command', 'size': 1, 'signed': False}, {'name': 'command_node_type', 'size': 2, 'signed': False}]]}, {'name': 'children', 'type': ['array', {'countType': 'varint', 'type': 'varint'}]}, {'name': 'redirectNode', 'type': ['switch', {'compareTo': 'flags/has_redirect_node', 'fields': {'1': 'varint'}, 'default': 'void'}]}, {'name': 'extraNodeData', 'type': ['switch', {'compareTo': 'flags/command_node_type', 'fields': {'0': 'void', '1': 'string', '2': ['container', [{'name': 'name', 'type': 'string'}, {'name': 'parser', 'type': 'string'}, {'name': 'properties', 'type': ['switch', {'compareTo': 'parser', 'fields': {'brigadier:bool': 'void', 'brigadier:double': ['container', [{'name': 'flags', 'type': ['bitfield', [{'name': 'unused', 'size': 6, 'signed': False}, {'name': 'max_present', 'size': 1, 'signed': False}, {'name': 'min_present', 'size': 1, 'signed': False}]]}, {'name': 'min', 'type': ['switch', {'compareTo': 'flags/min_present', 'fields': {'1': 'f64'}, 'default': 'void'}]}, {'name': 'max', 'type': ['switch', {'compareTo': 'flags/max_present', 'fields': {'1': 'f64'}, 'default': 'void'}]}]], 'brigadier:float': ['container', [{'name': 'flags', 'type': ['bitfield', [{'name': 'unused', 'size': 6, 'signed': False}, {'name': 'max_present', 'size': 1, 'signed': False}, {'name': 'min_present', 'size': 1, 'signed': False}]]}, {'name': 'min', 'type': ['switch', {'compareTo': 'flags/min_present', 'fields': {'1': 'f32'}, 'default': 'void'}]}, {'name': 'max', 'type': ['switch', {'compareTo': 'flags/max_present', 'fields': {'1': 'f32'}, 'default': 'void'}]}]], 'brigadier:integer': ['container', [{'name': 'flags', 'type': ['bitfield', [{'name': 'unused', 'size': 6, 'signed': False}, {'name': 'max_present', 'size': 1, 'signed': False}, {'name': 'min_present', 'size': 1, 'signed': False}]]}, {'name': 'min', 'type': ['switch', {'compareTo': 'flags/min_present', 'fields': {'1': 'i32'}, 'default': 'void'}]}, {'name': 'max', 'type': ['switch', {'compareTo': 'flags/max_present', 'fields': {'1': 'i32'}, 'default': 'void'}]}]], 'brigadier:string': 'varint', 'minecraft:entity': 'i8', 'minecraft:score_holder': 'i8'}, 'default': 'void'}]}, {'name': 'suggests', 'type': ['switch', {'compareTo': '../flags/has_custom_suggestions', 'fields': {'1': 'string'}, 'default': 'void'}]}]]}}]}]]}]} */
	TRY_E(cbl_encode_varint(v, p->root_index));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_face_player_encode(struct vector *v, struct packet *packet)
{
	struct pkt_face_player *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->feet_eyes));
	TRY_E(cbl_encode_f64(v, p->x));
	TRY_E(cbl_encode_f64(v, p->y));
	TRY_E(cbl_encode_f64(v, p->z));
	TRY_E(cbl_encode_bool(v, p->is_entity));
	/* {'name': 'entityId', 'type': ['switch', {'compareTo': 'isEntity', 'fields': {'true': 'varint'}, 'default': 'void'}]} */
	/* {'name': 'entity_feet_eyes', 'type': ['switch', {'compareTo': 'isEntity', 'fields': {'true': 'string'}, 'default': 'void'}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_nbt_query_response_encode(struct vector *v, struct packet *packet)
{
	struct pkt_nbt_query_response *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->transaction_id));
	TRY_E(cbl_encode_nbt(v, &p->nbt));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_chat_clientbound_encode(struct vector *v, struct packet *packet)
{
	struct pkt_chat_clientbound *p = packet->data;

	TRY_E(cbl_encode_string(v, p->message));
	TRY_E(cbl_encode_i8(v, p->position));
	TRY_E(cbl_encode_uuid(v, &p->sender));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_multi_block_change_encode(struct vector *v, struct packet *packet)
{
	struct pkt_multi_block_change *p = packet->data;

	TRY_E(cbl_encode_i32(v, p->chunk_x));
	TRY_E(cbl_encode_i32(v, p->chunk_z));
	/* {'name': 'records', 'type': ['array', {'countType': 'varint', 'type': ['container', [{'name': 'horizontalPos', 'type': 'u8'}, {'name': 'y', 'type': 'u8'}, {'name': 'blockId', 'type': 'varint'}]]}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_transaction_clientbound_encode(struct vector *v, struct packet *packet)
{
	struct pkt_transaction_clientbound *p = packet->data;

	TRY_E(cbl_encode_i8(v, p->window_id));
	TRY_E(cbl_encode_i16(v, p->action));
	TRY_E(cbl_encode_bool(v, p->accepted));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_close_window_clientbound_encode(struct vector *v, struct packet *packet)
{
	struct pkt_close_window_clientbound *p = packet->data;

	TRY_E(cbl_encode_u8(v, p->window_id));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_open_window_encode(struct vector *v, struct packet *packet)
{
	struct pkt_open_window *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->window_id));
	TRY_E(cbl_encode_varint(v, p->inventory_type));
	TRY_E(cbl_encode_string(v, p->window_title));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_window_items_encode(struct vector *v, struct packet *packet)
{
	struct pkt_window_items *p = packet->data;

	TRY_E(cbl_encode_u8(v, p->window_id));
	/* {'name': 'items', 'type': ['array', {'countType': 'i16', 'type': 'slot'}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_craft_progress_bar_encode(struct vector *v, struct packet *packet)
{
	struct pkt_craft_progress_bar *p = packet->data;

	TRY_E(cbl_encode_u8(v, p->window_id));
	TRY_E(cbl_encode_i16(v, p->property));
	TRY_E(cbl_encode_i16(v, p->value));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_set_slot_encode(struct vector *v, struct packet *packet)
{
	struct pkt_set_slot *p = packet->data;

	TRY_E(cbl_encode_i8(v, p->window_id));
	TRY_E(cbl_encode_i16(v, p->slot));
	TRY_E(cbl_encode_slot(v, &p->item));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_set_cooldown_encode(struct vector *v, struct packet *packet)
{
	struct pkt_set_cooldown *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->item_i_d));
	TRY_E(cbl_encode_varint(v, p->cooldown_ticks));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_plugin_message_clientbound_encode(struct vector *v, struct packet *packet)
{
	struct pkt_plugin_message_clientbound *p = packet->data;

	TRY_E(cbl_encode_string(v, p->channel));
	/* {'name': 'data', 'type': 'restBuffer'} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_named_sound_effect_encode(struct vector *v, struct packet *packet)
{
	struct pkt_named_sound_effect *p = packet->data;

	TRY_E(cbl_encode_string(v, p->sound_name));
	TRY_E(cbl_encode_varint(v, p->sound_category));
	TRY_E(cbl_encode_i32(v, p->x));
	TRY_E(cbl_encode_i32(v, p->y));
	TRY_E(cbl_encode_i32(v, p->z));
	TRY_E(cbl_encode_f32(v, p->volume));
	TRY_E(cbl_encode_f32(v, p->pitch));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_kick_disconnect_encode(struct vector *v, struct packet *packet)
{
	struct pkt_kick_disconnect *p = packet->data;

	TRY_E(cbl_encode_string(v, p->reason));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_entity_status_encode(struct vector *v, struct packet *packet)
{
	struct pkt_entity_status *p = packet->data;

	TRY_E(cbl_encode_i32(v, p->entity_id));
	TRY_E(cbl_encode_i8(v, p->entity_status));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_explosion_encode(struct vector *v, struct packet *packet)
{
	struct pkt_explosion *p = packet->data;

	TRY_E(cbl_encode_f32(v, p->x));
	TRY_E(cbl_encode_f32(v, p->y));
	TRY_E(cbl_encode_f32(v, p->z));
	TRY_E(cbl_encode_f32(v, p->radius));
	/* {'name': 'affectedBlockOffsets', 'type': ['array', {'countType': 'i32', 'type': ['container', [{'name': 'x', 'type': 'i8'}, {'name': 'y', 'type': 'i8'}, {'name': 'z', 'type': 'i8'}]]}]} */
	TRY_E(cbl_encode_f32(v, p->player_motion_x));
	TRY_E(cbl_encode_f32(v, p->player_motion_y));
	TRY_E(cbl_encode_f32(v, p->player_motion_z));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_unload_chunk_encode(struct vector *v, struct packet *packet)
{
	struct pkt_unload_chunk *p = packet->data;

	TRY_E(cbl_encode_i32(v, p->chunk_x));
	TRY_E(cbl_encode_i32(v, p->chunk_z));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_game_state_change_encode(struct vector *v, struct packet *packet)
{
	struct pkt_game_state_change *p = packet->data;

	TRY_E(cbl_encode_u8(v, p->reason));
	TRY_E(cbl_encode_f32(v, p->game_mode));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_open_horse_window_encode(struct vector *v, struct packet *packet)
{
	struct pkt_open_horse_window *p = packet->data;

	TRY_E(cbl_encode_u8(v, p->window_id));
	TRY_E(cbl_encode_varint(v, p->nb_slots));
	TRY_E(cbl_encode_i32(v, p->entity_id));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_keep_alive_clientbound_encode(struct vector *v, struct packet *packet)
{
	struct pkt_keep_alive_clientbound *p = packet->data;

	TRY_E(cbl_encode_i64(v, p->keep_alive_id));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_map_chunk_encode(struct vector *v, struct packet *packet)
{
	struct pkt_map_chunk *p = packet->data;

	TRY_E(cbl_encode_i32(v, p->x));
	TRY_E(cbl_encode_i32(v, p->z));
	TRY_E(cbl_encode_bool(v, p->ground_up));
	TRY_E(cbl_encode_bool(v, p->ignore_old_data));
	TRY_E(cbl_encode_varint(v, p->bit_map));
	TRY_E(cbl_encode_nbt(v, &p->heightmaps));
	/* {'name': 'biomes', 'type': ['switch', {'compareTo': 'groundUp', 'fields': {'false': 'void', 'true': ['array', {'count': 1024, 'type': 'i32'}]}}]} */
	/* {'name': 'chunkData', 'type': ['buffer', {'countType': 'varint'}]} */
	/* {'name': 'blockEntities', 'type': ['array', {'countType': 'varint', 'type': 'nbt'}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_world_event_encode(struct vector *v, struct packet *packet)
{
	struct pkt_world_event *p = packet->data;

	TRY_E(cbl_encode_i32(v, p->effect_id));
	TRY_E(cbl_encode_position(v, &p->location));
	TRY_E(cbl_encode_i32(v, p->data));
	TRY_E(cbl_encode_bool(v, p->global));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_world_particles_encode(struct vector *v, struct packet *packet)
{
	struct pkt_world_particles *p = packet->data;

	TRY_E(cbl_encode_i32(v, p->particle_id));
	TRY_E(cbl_encode_bool(v, p->long_distance));
	TRY_E(cbl_encode_f64(v, p->x));
	TRY_E(cbl_encode_f64(v, p->y));
	TRY_E(cbl_encode_f64(v, p->z));
	TRY_E(cbl_encode_f32(v, p->offset_x));
	TRY_E(cbl_encode_f32(v, p->offset_y));
	TRY_E(cbl_encode_f32(v, p->offset_z));
	TRY_E(cbl_encode_f32(v, p->particle_data));
	TRY_E(cbl_encode_i32(v, p->particles));
	/* {'name': 'data', 'type': ['particleData', {'compareTo': 'particleId'}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_update_light_encode(struct vector *v, struct packet *packet)
{
	struct pkt_update_light *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->chunk_x));
	TRY_E(cbl_encode_varint(v, p->chunk_z));
	TRY_E(cbl_encode_bool(v, p->trust_edges));
	TRY_E(cbl_encode_varint(v, p->sky_light_mask));
	TRY_E(cbl_encode_varint(v, p->block_light_mask));
	TRY_E(cbl_encode_varint(v, p->empty_sky_light_mask));
	TRY_E(cbl_encode_varint(v, p->empty_block_light_mask));
	/* {'name': 'data', 'type': 'restBuffer'} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_login_encode(struct vector *v, struct packet *packet)
{
	struct pkt_login *p = packet->data;

	TRY_E(cbl_encode_i32(v, p->entity_id));
	TRY_E(cbl_encode_u8(v, p->game_mode));
	TRY_E(cbl_encode_u8(v, p->previous_game_mode));
	/* {'name': 'worldNames', 'type': ['array', {'countType': 'varint', 'type': 'string'}]} */
	TRY_E(cbl_encode_nbt(v, &p->dimension_codec));
	TRY_E(cbl_encode_string(v, p->dimension));
	TRY_E(cbl_encode_string(v, p->world_name));
	TRY_E(cbl_encode_i64(v, p->hashed_seed));
	TRY_E(cbl_encode_u8(v, p->max_players));
	TRY_E(cbl_encode_varint(v, p->view_distance));
	TRY_E(cbl_encode_bool(v, p->reduced_debug_info));
	TRY_E(cbl_encode_bool(v, p->enable_respawn_screen));
	TRY_E(cbl_encode_bool(v, p->is_debug));
	TRY_E(cbl_encode_bool(v, p->is_flat));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_map_encode(struct vector *v, struct packet *packet)
{
	struct pkt_map *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->item_damage));
	TRY_E(cbl_encode_i8(v, p->scale));
	TRY_E(cbl_encode_bool(v, p->tracking_position));
	TRY_E(cbl_encode_bool(v, p->locked));
	/* {'name': 'icons', 'type': ['array', {'countType': 'varint', 'type': ['container', [{'name': 'type', 'type': 'varint'}, {'name': 'x', 'type': 'i8'}, {'name': 'y', 'type': 'i8'}, {'name': 'direction', 'type': 'u8'}, {'name': 'displayName', 'type': ['option', 'string']}]]}]} */
	TRY_E(cbl_encode_i8(v, p->columns));
	/* {'name': 'rows', 'type': ['switch', {'compareTo': 'columns', 'fields': {'0': 'void'}, 'default': 'i8'}]} */
	/* {'name': 'x', 'type': ['switch', {'compareTo': 'columns', 'fields': {'0': 'void'}, 'default': 'i8'}]} */
	/* {'name': 'y', 'type': ['switch', {'compareTo': 'columns', 'fields': {'0': 'void'}, 'default': 'i8'}]} */
	/* {'name': 'data', 'type': ['switch', {'compareTo': 'columns', 'fields': {'0': 'void'}, 'default': ['buffer', {'countType': 'varint'}]}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_trade_list_encode(struct vector *v, struct packet *packet)
{
	struct pkt_trade_list *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->window_id));
	/* {'name': 'trades', 'type': ['array', {'countType': 'u8', 'type': ['container', [{'name': 'inputItem1', 'type': 'slot'}, {'name': 'outputItem', 'type': 'slot'}, {'name': 'inputItem2', 'type': ['option', 'slot']}, {'name': 'tradeDisabled', 'type': 'bool'}, {'name': 'nbTradeUses', 'type': 'i32'}, {'name': 'maximumNbTradeUses', 'type': 'i32'}, {'name': 'xp', 'type': 'i32'}, {'name': 'specialPrice', 'type': 'i32'}, {'name': 'priceMultiplier', 'type': 'f32'}, {'name': 'demand', 'type': 'i32'}]]}]} */
	TRY_E(cbl_encode_varint(v, p->villager_level));
	TRY_E(cbl_encode_varint(v, p->experience));
	TRY_E(cbl_encode_bool(v, p->is_regular_villager));
	TRY_E(cbl_encode_bool(v, p->can_restock));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_rel_entity_move_encode(struct vector *v, struct packet *packet)
{
	struct pkt_rel_entity_move *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->entity_id));
	TRY_E(cbl_encode_i16(v, p->d_x));
	TRY_E(cbl_encode_i16(v, p->d_y));
	TRY_E(cbl_encode_i16(v, p->d_z));
	TRY_E(cbl_encode_bool(v, p->on_ground));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_entity_move_look_encode(struct vector *v, struct packet *packet)
{
	struct pkt_entity_move_look *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->entity_id));
	TRY_E(cbl_encode_i16(v, p->d_x));
	TRY_E(cbl_encode_i16(v, p->d_y));
	TRY_E(cbl_encode_i16(v, p->d_z));
	TRY_E(cbl_encode_i8(v, p->yaw));
	TRY_E(cbl_encode_i8(v, p->pitch));
	TRY_E(cbl_encode_bool(v, p->on_ground));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_entity_look_encode(struct vector *v, struct packet *packet)
{
	struct pkt_entity_look *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->entity_id));
	TRY_E(cbl_encode_i8(v, p->yaw));
	TRY_E(cbl_encode_i8(v, p->pitch));
	TRY_E(cbl_encode_bool(v, p->on_ground));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_entity_encode(struct vector *v, struct packet *packet)
{
	struct pkt_entity *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->entity_id));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_vehicle_move_clientbound_encode(struct vector *v, struct packet *packet)
{
	struct pkt_vehicle_move_clientbound *p = packet->data;

	TRY_E(cbl_encode_f64(v, p->x));
	TRY_E(cbl_encode_f64(v, p->y));
	TRY_E(cbl_encode_f64(v, p->z));
	TRY_E(cbl_encode_f32(v, p->yaw));
	TRY_E(cbl_encode_f32(v, p->pitch));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_open_book_encode(struct vector *v, struct packet *packet)
{
	struct pkt_open_book *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->hand));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_open_sign_entity_encode(struct vector *v, struct packet *packet)
{
	struct pkt_open_sign_entity *p = packet->data;

	TRY_E(cbl_encode_position(v, &p->location));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_craft_recipe_response_encode(struct vector *v, struct packet *packet)
{
	struct pkt_craft_recipe_response *p = packet->data;

	TRY_E(cbl_encode_i8(v, p->window_id));
	TRY_E(cbl_encode_string(v, p->recipe));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_abilities_clientbound_encode(struct vector *v, struct packet *packet)
{
	struct pkt_abilities_clientbound *p = packet->data;

	TRY_E(cbl_encode_i8(v, p->flags));
	TRY_E(cbl_encode_f32(v, p->flying_speed));
	TRY_E(cbl_encode_f32(v, p->walking_speed));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_combat_event_encode(struct vector *v, struct packet *packet)
{
	struct pkt_combat_event *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->event));
	/* {'name': 'duration', 'type': ['switch', {'compareTo': 'event', 'fields': {'1': 'varint'}, 'default': 'void'}]} */
	/* {'name': 'playerId', 'type': ['switch', {'compareTo': 'event', 'fields': {'2': 'varint'}, 'default': 'void'}]} */
	/* {'name': 'entityId', 'type': ['switch', {'compareTo': 'event', 'fields': {'1': 'i32', '2': 'i32'}, 'default': 'void'}]} */
	/* {'name': 'message', 'type': ['switch', {'compareTo': 'event', 'fields': {'2': 'string'}, 'default': 'void'}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_player_info_encode(struct vector *v, struct packet *packet)
{
	struct pkt_player_info *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->action));
	/* {'name': 'data', 'type': ['array', {'countType': 'varint', 'type': ['container', [{'name': 'UUID', 'type': 'UUID'}, {'name': 'name', 'type': ['switch', {'compareTo': '../action', 'fields': {'0': 'string'}, 'default': 'void'}]}, {'name': 'properties', 'type': ['switch', {'compareTo': '../action', 'fields': {'0': ['array', {'countType': 'varint', 'type': ['container', [{'name': 'name', 'type': 'string'}, {'name': 'value', 'type': 'string'}, {'name': 'signature', 'type': ['option', 'string']}]]}]}, 'default': 'void'}]}, {'name': 'gamemode', 'type': ['switch', {'compareTo': '../action', 'fields': {'0': 'varint', '1': 'varint'}, 'default': 'void'}]}, {'name': 'ping', 'type': ['switch', {'compareTo': '../action', 'fields': {'0': 'varint', '2': 'varint'}, 'default': 'void'}]}, {'name': 'displayName', 'type': ['switch', {'compareTo': '../action', 'fields': {'0': ['option', 'string'], '3': ['option', 'string']}, 'default': 'void'}]}]]}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_position_look_clientbound_encode(struct vector *v, struct packet *packet)
{
	struct pkt_position_look_clientbound *p = packet->data;

	TRY_E(cbl_encode_f64(v, p->x));
	TRY_E(cbl_encode_f64(v, p->y));
	TRY_E(cbl_encode_f64(v, p->z));
	TRY_E(cbl_encode_f32(v, p->yaw));
	TRY_E(cbl_encode_f32(v, p->pitch));
	TRY_E(cbl_encode_i8(v, p->flags));
	TRY_E(cbl_encode_varint(v, p->teleport_id));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_unlock_recipes_encode(struct vector *v, struct packet *packet)
{
	struct pkt_unlock_recipes *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->action));
	TRY_E(cbl_encode_bool(v, p->crafting_book_open));
	TRY_E(cbl_encode_bool(v, p->filtering_craftable));
	TRY_E(cbl_encode_bool(v, p->smelting_book_open));
	TRY_E(cbl_encode_bool(v, p->filtering_smeltable));
	/* {'name': 'recipes1', 'type': ['array', {'countType': 'varint', 'type': 'string'}]} */
	/* {'name': 'recipes2', 'type': ['switch', {'compareTo': 'action', 'fields': {'0': ['array', {'countType': 'varint', 'type': 'string'}]}, 'default': 'void'}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_entity_destroy_encode(struct vector *v, struct packet *packet)
{
	struct pkt_entity_destroy *p = packet->data;

	/* {'name': 'entityIds', 'type': ['array', {'countType': 'varint', 'type': 'varint'}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_remove_entity_effect_encode(struct vector *v, struct packet *packet)
{
	struct pkt_remove_entity_effect *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->entity_id));
	TRY_E(cbl_encode_i8(v, p->effect_id));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_resource_pack_send_encode(struct vector *v, struct packet *packet)
{
	struct pkt_resource_pack_send *p = packet->data;

	TRY_E(cbl_encode_string(v, p->url));
	TRY_E(cbl_encode_string(v, p->hash));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_respawn_encode(struct vector *v, struct packet *packet)
{
	struct pkt_respawn *p = packet->data;

	TRY_E(cbl_encode_string(v, p->dimension));
	TRY_E(cbl_encode_string(v, p->world_name));
	TRY_E(cbl_encode_i64(v, p->hashed_seed));
	TRY_E(cbl_encode_u8(v, p->gamemode));
	TRY_E(cbl_encode_u8(v, p->previous_gamemode));
	TRY_E(cbl_encode_bool(v, p->is_debug));
	TRY_E(cbl_encode_bool(v, p->is_flat));
	TRY_E(cbl_encode_bool(v, p->copy_metadata));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_entity_head_rotation_encode(struct vector *v, struct packet *packet)
{
	struct pkt_entity_head_rotation *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->entity_id));
	TRY_E(cbl_encode_i8(v, p->head_yaw));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_world_border_encode(struct vector *v, struct packet *packet)
{
	struct pkt_world_border *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->action));
	/* {'name': 'radius', 'type': ['switch', {'compareTo': 'action', 'fields': {'0': 'f64'}, 'default': 'void'}]} */
	/* {'name': 'x', 'type': ['switch', {'compareTo': 'action', 'fields': {'2': 'f64', '3': 'f64'}, 'default': 'void'}]} */
	/* {'name': 'z', 'type': ['switch', {'compareTo': 'action', 'fields': {'2': 'f64', '3': 'f64'}, 'default': 'void'}]} */
	/* {'name': 'old_radius', 'type': ['switch', {'compareTo': 'action', 'fields': {'1': 'f64', '3': 'f64'}, 'default': 'void'}]} */
	/* {'name': 'new_radius', 'type': ['switch', {'compareTo': 'action', 'fields': {'1': 'f64', '3': 'f64'}, 'default': 'void'}]} */
	/* {'name': 'speed', 'type': ['switch', {'compareTo': 'action', 'fields': {'1': 'varint', '3': 'varint'}, 'default': 'void'}]} */
	/* {'name': 'portalBoundary', 'type': ['switch', {'compareTo': 'action', 'fields': {'3': 'varint'}, 'default': 'void'}]} */
	/* {'name': 'warning_time', 'type': ['switch', {'compareTo': 'action', 'fields': {'3': 'varint', '4': 'varint'}, 'default': 'void'}]} */
	/* {'name': 'warning_blocks', 'type': ['switch', {'compareTo': 'action', 'fields': {'3': 'varint', '5': 'varint'}, 'default': 'void'}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_camera_encode(struct vector *v, struct packet *packet)
{
	struct pkt_camera *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->camera_id));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_held_item_change_clientbound_encode(struct vector *v, struct packet *packet)
{
	struct pkt_held_item_change_clientbound *p = packet->data;

	TRY_E(cbl_encode_i8(v, p->slot));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_update_view_position_encode(struct vector *v, struct packet *packet)
{
	struct pkt_update_view_position *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->chunk_x));
	TRY_E(cbl_encode_varint(v, p->chunk_z));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_update_view_distance_encode(struct vector *v, struct packet *packet)
{
	struct pkt_update_view_distance *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->view_distance));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_scoreboard_display_objective_encode(struct vector *v, struct packet *packet)
{
	struct pkt_scoreboard_display_objective *p = packet->data;

	TRY_E(cbl_encode_i8(v, p->position));
	TRY_E(cbl_encode_string(v, p->name));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_entity_metadata_encode(struct vector *v, struct packet *packet)
{
	struct pkt_entity_metadata *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->entity_id));
	/* {'name': 'metadata', 'type': 'entityMetadata'} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_attach_entity_encode(struct vector *v, struct packet *packet)
{
	struct pkt_attach_entity *p = packet->data;

	TRY_E(cbl_encode_i32(v, p->entity_id));
	TRY_E(cbl_encode_i32(v, p->vehicle_id));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_entity_velocity_encode(struct vector *v, struct packet *packet)
{
	struct pkt_entity_velocity *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->entity_id));
	TRY_E(cbl_encode_i16(v, p->velocity_x));
	TRY_E(cbl_encode_i16(v, p->velocity_y));
	TRY_E(cbl_encode_i16(v, p->velocity_z));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_entity_equipment_encode(struct vector *v, struct packet *packet)
{
	struct pkt_entity_equipment *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->entity_id));
	/* {'name': 'equipments', 'type': ['topBitSetTerminatedArray', {'type': ['container', [{'name': 'slot', 'type': 'i8'}, {'name': 'item', 'type': 'slot'}]]}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_experience_encode(struct vector *v, struct packet *packet)
{
	struct pkt_experience *p = packet->data;

	TRY_E(cbl_encode_f32(v, p->experience_bar));
	TRY_E(cbl_encode_varint(v, p->level));
	TRY_E(cbl_encode_varint(v, p->total_experience));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_update_health_encode(struct vector *v, struct packet *packet)
{
	struct pkt_update_health *p = packet->data;

	TRY_E(cbl_encode_f32(v, p->health));
	TRY_E(cbl_encode_varint(v, p->food));
	TRY_E(cbl_encode_f32(v, p->food_saturation));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_scoreboard_objective_encode(struct vector *v, struct packet *packet)
{
	struct pkt_scoreboard_objective *p = packet->data;

	TRY_E(cbl_encode_string(v, p->name));
	TRY_E(cbl_encode_i8(v, p->action));
	/* {'name': 'displayText', 'type': ['switch', {'compareTo': 'action', 'fields': {'0': 'string', '2': 'string'}, 'default': 'void'}]} */
	/* {'name': 'type', 'type': ['switch', {'compareTo': 'action', 'fields': {'0': 'varint', '2': 'varint'}, 'default': 'void'}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_set_passengers_encode(struct vector *v, struct packet *packet)
{
	struct pkt_set_passengers *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->entity_id));
	/* {'name': 'passengers', 'type': ['array', {'countType': 'varint', 'type': 'varint'}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_teams_encode(struct vector *v, struct packet *packet)
{
	struct pkt_teams *p = packet->data;

	TRY_E(cbl_encode_string(v, p->team));
	TRY_E(cbl_encode_i8(v, p->mode));
	/* {'name': 'name', 'type': ['switch', {'compareTo': 'mode', 'fields': {'0': 'string', '2': 'string'}, 'default': 'void'}]} */
	/* {'name': 'friendlyFire', 'type': ['switch', {'compareTo': 'mode', 'fields': {'0': 'i8', '2': 'i8'}, 'default': 'void'}]} */
	/* {'name': 'nameTagVisibility', 'type': ['switch', {'compareTo': 'mode', 'fields': {'0': 'string', '2': 'string'}, 'default': 'void'}]} */
	/* {'name': 'collisionRule', 'type': ['switch', {'compareTo': 'mode', 'fields': {'0': 'string', '2': 'string'}, 'default': 'void'}]} */
	/* {'name': 'formatting', 'type': ['switch', {'compareTo': 'mode', 'fields': {'0': 'varint', '2': 'varint'}, 'default': 'void'}]} */
	/* {'name': 'prefix', 'type': ['switch', {'compareTo': 'mode', 'fields': {'0': 'string', '2': 'string'}, 'default': 'void'}]} */
	/* {'name': 'suffix', 'type': ['switch', {'compareTo': 'mode', 'fields': {'0': 'string', '2': 'string'}, 'default': 'void'}]} */
	/* {'name': 'players', 'type': ['switch', {'compareTo': 'mode', 'fields': {'0': ['array', {'countType': 'varint', 'type': 'string'}], '3': ['array', {'countType': 'varint', 'type': 'string'}], '4': ['array', {'countType': 'varint', 'type': 'string'}]}, 'default': 'void'}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_scoreboard_score_encode(struct vector *v, struct packet *packet)
{
	struct pkt_scoreboard_score *p = packet->data;

	TRY_E(cbl_encode_string(v, p->item_name));
	TRY_E(cbl_encode_i8(v, p->action));
	TRY_E(cbl_encode_string(v, p->score_name));
	/* {'name': 'value', 'type': ['switch', {'compareTo': 'action', 'fields': {'1': 'void'}, 'default': 'varint'}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_spawn_position_encode(struct vector *v, struct packet *packet)
{
	struct pkt_spawn_position *p = packet->data;

	TRY_E(cbl_encode_position(v, &p->location));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_update_time_encode(struct vector *v, struct packet *packet)
{
	struct pkt_update_time *p = packet->data;

	TRY_E(cbl_encode_i64(v, p->age));
	TRY_E(cbl_encode_i64(v, p->time));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_title_encode(struct vector *v, struct packet *packet)
{
	struct pkt_title *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->action));
	/* {'name': 'text', 'type': ['switch', {'compareTo': 'action', 'fields': {'0': 'string', '1': 'string', '2': 'string'}, 'default': 'void'}]} */
	/* {'name': 'fadeIn', 'type': ['switch', {'compareTo': 'action', 'fields': {'3': 'i32'}, 'default': 'void'}]} */
	/* {'name': 'stay', 'type': ['switch', {'compareTo': 'action', 'fields': {'3': 'i32'}, 'default': 'void'}]} */
	/* {'name': 'fadeOut', 'type': ['switch', {'compareTo': 'action', 'fields': {'3': 'i32'}, 'default': 'void'}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_entity_sound_effect_encode(struct vector *v, struct packet *packet)
{
	struct pkt_entity_sound_effect *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->sound_id));
	TRY_E(cbl_encode_varint(v, p->sound_category));
	TRY_E(cbl_encode_varint(v, p->entity_id));
	TRY_E(cbl_encode_f32(v, p->volume));
	TRY_E(cbl_encode_f32(v, p->pitch));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_stop_sound_encode(struct vector *v, struct packet *packet)
{
	struct pkt_stop_sound *p = packet->data;

	TRY_E(cbl_encode_i8(v, p->flags));
	/* {'name': 'source', 'type': ['switch', {'compareTo': 'flags', 'fields': {'3': 'varint', '1': 'varint'}, 'default': 'void'}]} */
	/* {'name': 'sound', 'type': ['switch', {'compareTo': 'flags', 'fields': {'3': 'string', '2': 'string'}, 'default': 'void'}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_sound_effect_encode(struct vector *v, struct packet *packet)
{
	struct pkt_sound_effect *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->sound_id));
	TRY_E(cbl_encode_varint(v, p->sound_category));
	TRY_E(cbl_encode_i32(v, p->x));
	TRY_E(cbl_encode_i32(v, p->y));
	TRY_E(cbl_encode_i32(v, p->z));
	TRY_E(cbl_encode_f32(v, p->volume));
	TRY_E(cbl_encode_f32(v, p->pitch));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_playerlist_header_encode(struct vector *v, struct packet *packet)
{
	struct pkt_playerlist_header *p = packet->data;

	TRY_E(cbl_encode_string(v, p->header));
	TRY_E(cbl_encode_string(v, p->footer));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_collect_encode(struct vector *v, struct packet *packet)
{
	struct pkt_collect *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->collected_entity_id));
	TRY_E(cbl_encode_varint(v, p->collector_entity_id));
	TRY_E(cbl_encode_varint(v, p->pickup_item_count));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_entity_teleport_encode(struct vector *v, struct packet *packet)
{
	struct pkt_entity_teleport *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->entity_id));
	TRY_E(cbl_encode_f64(v, p->x));
	TRY_E(cbl_encode_f64(v, p->y));
	TRY_E(cbl_encode_f64(v, p->z));
	TRY_E(cbl_encode_i8(v, p->yaw));
	TRY_E(cbl_encode_i8(v, p->pitch));
	TRY_E(cbl_encode_bool(v, p->on_ground));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_entity_update_attributes_encode(struct vector *v, struct packet *packet)
{
	struct pkt_entity_update_attributes *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->entity_id));
	/* {'name': 'properties', 'type': ['array', {'countType': 'i32', 'type': ['container', [{'name': 'key', 'type': 'string'}, {'name': 'value', 'type': 'f64'}, {'name': 'modifiers', 'type': ['array', {'countType': 'varint', 'type': ['container', [{'name': 'uuid', 'type': 'UUID'}, {'name': 'amount', 'type': 'f64'}, {'name': 'operation', 'type': 'i8'}]]}]}]]}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_entity_effect_encode(struct vector *v, struct packet *packet)
{
	struct pkt_entity_effect *p = packet->data;

	TRY_E(cbl_encode_varint(v, p->entity_id));
	TRY_E(cbl_encode_i8(v, p->effect_id));
	TRY_E(cbl_encode_i8(v, p->amplifier));
	TRY_E(cbl_encode_varint(v, p->duration));
	TRY_E(cbl_encode_i8(v, p->hide_particles));

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_select_advancement_tab_encode(struct vector *v, struct packet *packet)
{
	struct pkt_select_advancement_tab *p = packet->data;

	/* {'name': 'id', 'type': ['option', 'string']} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_declare_recipes_encode(struct vector *v, struct packet *packet)
{
	struct pkt_declare_recipes *p = packet->data;

	/* {'name': 'recipes', 'type': ['array', {'countType': 'varint', 'type': ['container', [{'name': 'type', 'type': 'string'}, {'name': 'recipeId', 'type': 'string'}, {'name': 'data', 'type': ['switch', {'compareTo': 'type', 'fields': {'minecraft:crafting_shapeless': ['container', [{'name': 'group', 'type': 'string'}, {'name': 'ingredients', 'type': ['array', {'countType': 'varint', 'type': 'ingredient'}]}, {'name': 'result', 'type': 'slot'}]], 'minecraft:crafting_shaped': ['container', [{'name': 'width', 'type': 'varint'}, {'name': 'height', 'type': 'varint'}, {'name': 'group', 'type': 'string'}, {'name': 'ingredients', 'type': ['array', {'count': 'width', 'type': ['array', {'count': 'height', 'type': 'ingredient'}]}]}, {'name': 'result', 'type': 'slot'}]], 'minecraft:crafting_special_armordye': 'void', 'minecraft:crafting_special_bookcloning': 'void', 'minecraft:crafting_special_mapcloning': 'void', 'minecraft:crafting_special_mapextending': 'void', 'minecraft:crafting_special_firework_rocket': 'void', 'minecraft:crafting_special_firework_star': 'void', 'minecraft:crafting_special_firework_star_fade': 'void', 'minecraft:crafting_special_repairitem': 'void', 'minecraft:crafting_special_tippedarrow': 'void', 'minecraft:crafting_special_bannerduplicate': 'void', 'minecraft:crafting_special_banneraddpattern': 'void', 'minecraft:crafting_special_shielddecoration': 'void', 'minecraft:crafting_special_shulkerboxcoloring': 'void', 'minecraft:crafting_special_suspiciousstew': 'void', 'minecraft:smelting': 'minecraft_smelting_format', 'minecraft:blasting': 'minecraft_smelting_format', 'minecraft:smoking': 'minecraft_smelting_format', 'minecraft:campfire_cooking': 'minecraft_smelting_format', 'minecraft:stonecutting': ['container', [{'name': 'group', 'type': 'string'}, {'name': 'ingredient', 'type': 'ingredient'}, {'name': 'result', 'type': 'slot'}]], 'minecraft:smithing': ['container', [{'name': 'base', 'type': 'ingredient'}, {'name': 'addition', 'type': 'ingredient'}, {'name': 'result', 'type': 'slot'}]]}}]}]]}]} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_tags_encode(struct vector *v, struct packet *packet)
{
	struct pkt_tags *p = packet->data;

	/* {'name': 'blockTags', 'type': 'tags'} */
	/* {'name': 'itemTags', 'type': 'tags'} */
	/* {'name': 'fluidTags', 'type': 'tags'} */
	/* {'name': 'entityTags', 'type': 'tags'} */

	return E_SUCCESS;
}

inline CBL_ERROR
pkt_acknowledge_player_digging_encode(struct vector *v, struct packet *packet)
{
	struct pkt_acknowledge_player_digging *p = packet->data;

	TRY_E(cbl_encode_position(v, &p->location));
	TRY_E(cbl_encode_varint(v, p->block));
	TRY_E(cbl_encode_varint(v, p->status));
	TRY_E(cbl_encode_bool(v, p->successful));

	return E_SUCCESS;
}
\ No newline at end of file

A test/Makefile => test/Makefile +12 -0
@@ 0,0 1,12 @@
CC		:= gcc
CFLAGS	:= -DDEBUG -g3 -gdwarf-2 -flto -O0
LIB		:= -lpthread -luev -linih
INC		:= -I../include

SRC		:= $(shell find ../src ! -name "main.c" -type f -name "*.c")
SRC		+= src/main.c

tests:
	$(CC) $(CFLAGS) $(INC) $(SRC) $(LIB) -o cobble_tests

.PHONY: test tests
\ No newline at end of file

R test/data/buffer.c => test/src/data/buffer.c +3 -3
@@ 43,7 43,7 @@ TEST(buffer_reserve)
    return E_SUCCESS;
}

TEST(buffer_write)
TEST(buffer_set)
{
    struct buffer a, b;



@@ 53,8 53,8 @@ TEST(buffer_write)
    for (int i = 0;i < 1000;i++) {
        size_t n = rand() % 1000;

        buffer_write(&a, i * sizeof(size_t), &n, sizeof(size_t));
        buffer_write(&b, i * sizeof(size_t), &n, sizeof(size_t));
        buffer_set(&a, i * sizeof(size_t), &n, sizeof(size_t));
        buffer_set(&b, i * sizeof(size_t), &n, sizeof(size_t));
    }

    for (int i = 0;i < 1000;i++) {

R test/data/queue.c => test/src/data/queue.c +2 -1
@@ 7,6 7,7 @@

#include "../test.h"

/* TODO: remove randomness */
TEST(queue_size)
{
    struct queue q;


@@ 24,7 25,6 @@ TEST(queue_size)
            size++;
        }

        log_trace("size: %d, qsize: %d, vsize: %d, head: %d, tail: %d", size, queue_size(&q), q.vec.len, q.head, q.tail);
        ASSERT_E(queue_size(&q) == size);
    }



@@ 42,6 42,7 @@ TEST(queue_basic)
        ASSERT_E(queue_size(&q) == i);
        TRY_E(queue_enqueue(&q, &i));
    }

    for (int i = 0;i < 1000;i++) {
        TRY_E(queue_dequeue(&q, &r));
        ASSERT_E(i == r);

R test/data/vector.c => test/src/data/vector.c +1 -1
@@ 35,7 35,7 @@ TEST(vector_insert)
    }

    /* test failures */
    ASSERT_E(vector_insert(&v, __INT_MAX__, &r) == E_VECTOR_OOB);
    ASSERT_E(vector_insert(&v, __INT_MAX__, &r) == E_OOB);
    ASSERT_E(v.buf.capacity < __INT_MAX__);

    vector_destroy(&v);

R test/main.c => test/src/main.c +1 -1
@@ 14,7 14,7 @@
    ENTRY(buffer_resize)\
    ENTRY(buffer_reserve)\
    ENTRY(buffer_reserve)\
    ENTRY(buffer_write)\
    ENTRY(buffer_set)\
    ENTRY(vector_insert)\
    ENTRY(vector_erase)\
    ENTRY(vector_stack)\

R test/protocol/decode.c => test/src/protocol/decode.c +0 -0
R test/protocol/encode.c => test/src/protocol/encode.c +0 -0
R test/test.h => test/src/test.h +0 -0