basin/src/packet.c

2026 lines
87 KiB
C

#include "basin/packet.h"
#include <basin/globals.h>
#include <basin/inventory.h>
#include <basin/network.h>
#include <basin/nbt.h>
#include <basin/connection.h>
#include <basin/world.h>
#include <basin/player.h>
#include <avuna/string.h>
#include <stdint.h>
#include <zlib.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <zlib.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#include <math.h>
struct packet* packet_new(struct mempool* pool, int32_t id) {
struct packet* packet = pcalloc(pool, sizeof(struct packet));
packet->pool = pool;
packet->id = id;
return packet;
}
#define ADRX if(rx == 0) goto rer;pbuf += rx;ps -= rx;
#define ADX(x) pbuf += x;ps -= x;
#define CPS(x) if(ps < x) goto rer;
#define CPS_OPT(x) if(ps >= x) {
#define ENS(x) if(ps-pi < x) { ps += (x > 256 ? x + 1024 : 1024); pktbuf = prealloc(packet->pool, pktbuf - 10, ps + 10) + 10; }
ssize_t packet_read(struct connection* conn, unsigned char* buf, size_t buflen, struct packet* packet) {
void* pktbuf = buf;
int32_t pktlen = (int32_t) buflen;
if (conn->compression_state >= 0) {
int32_t decompressed_length = 0;
int read_length = readVarInt(&decompressed_length, pktbuf, buflen);
if (read_length == 0) goto rer;
pktlen -= read_length;
pktbuf += read_length;
if (decompressed_length > 0 && pktlen > 0) {
pktlen = decompressed_length;
void* decompressed = pmalloc(packet->pool, (size_t) decompressed_length);
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
int dr = 0;
if ((dr = inflateInit(&strm)) != Z_OK) {
errlog(conn->server->logger, "Compression initialization error!\n");
goto rer;
}
strm.avail_in = (uInt) pktlen;
strm.next_in = pktbuf;
strm.avail_out = (uInt) decompressed_length;
strm.next_out = decompressed;
do {
dr = inflate(&strm, Z_FINISH);
if (dr == Z_STREAM_ERROR) {
printf("Compression Read Error\n");
goto rer;
}
strm.avail_out = (uInt) (pktlen - strm.total_out);
strm.next_out = decompressed + strm.total_out;
} while (strm.avail_in > 0 || strm.total_out < pktlen);
inflateEnd(&strm);
pktbuf = decompressed;
pktlen = decompressed_length;
}
}
if (pktbuf == NULL) return 0;
unsigned char* pbuf = (unsigned char*) pktbuf;
size_t ps = (size_t) pktlen;
int32_t id = 0;
size_t t = (size_t) readVarInt(&id, pbuf, ps);
pbuf += t;
ps -= t;
packet->id = id;
int rx = 0;
if (conn->protocol_state == STATE_HANDSHAKE) {
if (id == PKT_HANDSHAKE_SERVER_HANDSHAKE) {
//protocol_version
rx = readVarInt(&packet->data.handshake_server.handshake.protocol_version, pbuf, ps);
ADRX
//server_address
rx = readString(packet->pool, &packet->data.handshake_server.handshake.server_address, pbuf, ps);
ADRX
//server_port
CPS(2)
memcpy(&packet->data.handshake_server.handshake.server_port, pbuf, 2);
swapEndian(&packet->data.handshake_server.handshake.server_port, 2);
ADX(2)
//next_state
rx = readVarInt(&packet->data.handshake_server.handshake.next_state, pbuf, ps);
ADRX
}
} else if (conn->protocol_state == STATE_PLAY) {
if (id == PKT_PLAY_SERVER_TELEPORTCONFIRM) {
//teleport_id
rx = readVarInt(&packet->data.play_server.teleportconfirm.teleport_id, pbuf, ps);
ADRX
} else if (id == PKT_PLAY_SERVER_TABCOMPLETE) {
//text
rx = readString(packet->pool, &packet->data.play_server.tabcomplete.text, pbuf, ps);
ADRX
//assume_command
CPS(1)
memcpy(&packet->data.play_server.tabcomplete.assume_command, pbuf, 1);
ADX(1)
//has_position
CPS(1)
memcpy(&packet->data.play_server.tabcomplete.has_position, pbuf, 1);
ADX(1)
//looked_at_block
CPS_OPT(8)
memcpy(&packet->data.play_server.tabcomplete.looked_at_block, pbuf, 8);
swapEndian(&packet->data.play_server.tabcomplete.looked_at_block, 8);
ADX(8)
}
} else if (id == PKT_PLAY_SERVER_CHATMESSAGE) {
//message
rx = readString(packet->pool, &packet->data.play_server.chatmessage.message, pbuf, ps);
ADRX
} else if (id == PKT_PLAY_SERVER_CLIENTSTATUS) {
//action_id
rx = readVarInt(&packet->data.play_server.clientstatus.action_id, pbuf, ps);
ADRX
} else if (id == PKT_PLAY_SERVER_CLIENTSETTINGS) {
//locale
rx = readString(packet->pool, &packet->data.play_server.clientsettings.locale, pbuf, ps);
ADRX
//view_distance
CPS(1)
memcpy(&packet->data.play_server.clientsettings.view_distance, pbuf, 1);
ADX(1)
//chat_mode
rx = readVarInt(&packet->data.play_server.clientsettings.chat_mode, pbuf, ps);
ADRX
//chat_colors
CPS(1)
memcpy(&packet->data.play_server.clientsettings.chat_colors, pbuf, 1);
ADX(1)
//displayed_skin_parts
CPS(1)
memcpy(&packet->data.play_server.clientsettings.displayed_skin_parts, pbuf, 1);
ADX(1)
//main_hand
rx = readVarInt(&packet->data.play_server.clientsettings.main_hand, pbuf, ps);
ADRX
} else if (id == PKT_PLAY_SERVER_CONFIRMTRANSACTION) {
//window_id
CPS(1)
memcpy(&packet->data.play_server.confirmtransaction.window_id, pbuf, 1);
ADX(1)
//action_number
CPS(2)
memcpy(&packet->data.play_server.confirmtransaction.action_number, pbuf, 2);
swapEndian(&packet->data.play_server.confirmtransaction.action_number, 2);
ADX(2)
//accepted
CPS(1)
memcpy(&packet->data.play_server.confirmtransaction.accepted, pbuf, 1);
ADX(1)
} else if (id == PKT_PLAY_SERVER_ENCHANTITEM) {
//window_id
CPS(1)
memcpy(&packet->data.play_server.enchantitem.window_id, pbuf, 1);
ADX(1)
//enchantment
CPS(1)
memcpy(&packet->data.play_server.enchantitem.enchantment, pbuf, 1);
ADX(1)
} else if (id == PKT_PLAY_SERVER_CLICKWINDOW) {
//window_id
CPS(1)
memcpy(&packet->data.play_server.clickwindow.window_id, pbuf, 1);
ADX(1)
//slot
CPS(2)
memcpy(&packet->data.play_server.clickwindow.slot, pbuf, 2);
swapEndian(&packet->data.play_server.clickwindow.slot, 2);
ADX(2)
//button
CPS(1)
memcpy(&packet->data.play_server.clickwindow.button, pbuf, 1);
ADX(1)
//action_number
CPS(2)
memcpy(&packet->data.play_server.clickwindow.action_number, pbuf, 2);
swapEndian(&packet->data.play_server.clickwindow.action_number, 2);
ADX(2)
//mode
rx = readVarInt(&packet->data.play_server.clickwindow.mode, pbuf, ps);
ADRX
//clicked_item
rx = readSlot(packet->pool, &packet->data.play_server.clickwindow.clicked_item, pbuf, ps);
ADRX
} else if (id == PKT_PLAY_SERVER_CLOSEWINDOW) {
//window_id
CPS(1)
memcpy(&packet->data.play_server.closewindow.window_id, pbuf, 1);
ADX(1)
} else if (id == PKT_PLAY_SERVER_PLUGINMESSAGE) {
//channel
rx = readString(packet->pool, &packet->data.play_server.pluginmessage.channel, pbuf, ps);
ADRX
//data
CPS(ps)
packet->data.play_server.pluginmessage.data = pmalloc(packet->pool, ps);
memcpy(packet->data.play_server.pluginmessage.data, pbuf, ps);
ADX(ps)
} else if (id == PKT_PLAY_SERVER_USEENTITY) {
//target
rx = readVarInt(&packet->data.play_server.useentity.target, pbuf, ps);
ADRX
//type
rx = readVarInt(&packet->data.play_server.useentity.type, pbuf, ps);
ADRX
//target_x
CPS_OPT(4)
memcpy(&packet->data.play_server.useentity.target_x, pbuf, 4);
swapEndian(&packet->data.play_server.useentity.target_x, 4);
ADX(4)
}
//target_y
CPS_OPT(4)
memcpy(&packet->data.play_server.useentity.target_y, pbuf, 4);
swapEndian(&packet->data.play_server.useentity.target_y, 4);
ADX(4)
}
//target_z
CPS_OPT(4)
memcpy(&packet->data.play_server.useentity.target_z, pbuf, 4);
swapEndian(&packet->data.play_server.useentity.target_z, 4);
ADX(4)
}
//hand
CPS_OPT(1)
rx = readVarInt(&packet->data.play_server.useentity.hand, pbuf, ps);
ADRX
}
} else if (id == PKT_PLAY_SERVER_KEEPALIVE) {
//keep_alive_id
rx = readVarInt(&packet->data.play_server.keepalive.keep_alive_id, pbuf, ps);
ADRX
} else if (id == PKT_PLAY_SERVER_PLAYERPOSITION) {
//x
CPS(8)
memcpy(&packet->data.play_server.playerposition.x, pbuf, 8);
swapEndian(&packet->data.play_server.playerposition.x, 8);
ADX(8)
//feet_y
CPS(8)
memcpy(&packet->data.play_server.playerposition.feet_y, pbuf, 8);
swapEndian(&packet->data.play_server.playerposition.feet_y, 8);
ADX(8)
//z
CPS(8)
memcpy(&packet->data.play_server.playerposition.z, pbuf, 8);
swapEndian(&packet->data.play_server.playerposition.z, 8);
ADX(8)
//on_ground
CPS(1)
memcpy(&packet->data.play_server.playerposition.on_ground, pbuf, 1);
ADX(1)
} else if (id == PKT_PLAY_SERVER_PLAYERPOSITIONANDLOOK) {
//x
CPS(8)
memcpy(&packet->data.play_server.playerpositionandlook.x, pbuf, 8);
swapEndian(&packet->data.play_server.playerpositionandlook.x, 8);
ADX(8)
//feet_y
CPS(8)
memcpy(&packet->data.play_server.playerpositionandlook.feet_y, pbuf, 8);
swapEndian(&packet->data.play_server.playerpositionandlook.feet_y, 8);
ADX(8)
//z
CPS(8)
memcpy(&packet->data.play_server.playerpositionandlook.z, pbuf, 8);
swapEndian(&packet->data.play_server.playerpositionandlook.z, 8);
ADX(8)
//yaw
CPS(4)
memcpy(&packet->data.play_server.playerpositionandlook.yaw, pbuf, 4);
swapEndian(&packet->data.play_server.playerpositionandlook.yaw, 4);
ADX(4)
//pitch
CPS(4)
memcpy(&packet->data.play_server.playerpositionandlook.pitch, pbuf, 4);
swapEndian(&packet->data.play_server.playerpositionandlook.pitch, 4);
ADX(4)
//on_ground
CPS(1)
memcpy(&packet->data.play_server.playerpositionandlook.on_ground, pbuf, 1);
ADX(1)
} else if (id == PKT_PLAY_SERVER_PLAYERLOOK) {
//yaw
CPS(4)
memcpy(&packet->data.play_server.playerlook.yaw, pbuf, 4);
swapEndian(&packet->data.play_server.playerlook.yaw, 4);
ADX(4)
//pitch
CPS(4)
memcpy(&packet->data.play_server.playerlook.pitch, pbuf, 4);
swapEndian(&packet->data.play_server.playerlook.pitch, 4);
ADX(4)
//on_ground
CPS(1)
memcpy(&packet->data.play_server.playerlook.on_ground, pbuf, 1);
ADX(1)
} else if (id == PKT_PLAY_SERVER_PLAYER) {
//on_ground
CPS(1)
memcpy(&packet->data.play_server.player.on_ground, pbuf, 1);
ADX(1)
} else if (id == PKT_PLAY_SERVER_VEHICLEMOVE) {
//x
CPS(8)
memcpy(&packet->data.play_server.vehiclemove.x, pbuf, 8);
swapEndian(&packet->data.play_server.vehiclemove.x, 8);
ADX(8)
//y
CPS(8)
memcpy(&packet->data.play_server.vehiclemove.y, pbuf, 8);
swapEndian(&packet->data.play_server.vehiclemove.y, 8);
ADX(8)
//z
CPS(8)
memcpy(&packet->data.play_server.vehiclemove.z, pbuf, 8);
swapEndian(&packet->data.play_server.vehiclemove.z, 8);
ADX(8)
//yaw
CPS(4)
memcpy(&packet->data.play_server.vehiclemove.yaw, pbuf, 4);
swapEndian(&packet->data.play_server.vehiclemove.yaw, 4);
ADX(4)
//pitch
CPS(4)
memcpy(&packet->data.play_server.vehiclemove.pitch, pbuf, 4);
swapEndian(&packet->data.play_server.vehiclemove.pitch, 4);
ADX(4)
} else if (id == PKT_PLAY_SERVER_STEERBOAT) {
//right_paddle_turning
CPS(1)
memcpy(&packet->data.play_server.steerboat.right_paddle_turning, pbuf, 1);
ADX(1)
//left_paddle_turning
CPS(1)
memcpy(&packet->data.play_server.steerboat.left_paddle_turning, pbuf, 1);
ADX(1)
} else if (id == PKT_PLAY_SERVER_PLAYERABILITIES) {
//flags
CPS(1)
memcpy(&packet->data.play_server.playerabilities.flags, pbuf, 1);
ADX(1)
//flying_speed
CPS(4)
memcpy(&packet->data.play_server.playerabilities.flying_speed, pbuf, 4);
swapEndian(&packet->data.play_server.playerabilities.flying_speed, 4);
ADX(4)
//walking_speed
CPS(4)
memcpy(&packet->data.play_server.playerabilities.walking_speed, pbuf, 4);
swapEndian(&packet->data.play_server.playerabilities.walking_speed, 4);
ADX(4)
} else if (id == PKT_PLAY_SERVER_PLAYERDIGGING) {
//status
rx = readVarInt(&packet->data.play_server.playerdigging.status, pbuf, ps);
ADRX
//location
CPS(8)
memcpy(&packet->data.play_server.playerdigging.location, pbuf, 8);
swapEndian(&packet->data.play_server.playerdigging.location, 8);
ADX(8)
//face
CPS(1)
memcpy(&packet->data.play_server.playerdigging.face, pbuf, 1);
ADX(1)
} else if (id == PKT_PLAY_SERVER_ENTITYACTION) {
//entity_id
rx = readVarInt(&packet->data.play_server.entityaction.entity_id, pbuf, ps);
ADRX
//action_id
rx = readVarInt(&packet->data.play_server.entityaction.action_id, pbuf, ps);
ADRX
//jump_boost
rx = readVarInt(&packet->data.play_server.entityaction.jump_boost, pbuf, ps);
ADRX
} else if (id == PKT_PLAY_SERVER_STEERVEHICLE) {
//sideways
CPS(4)
memcpy(&packet->data.play_server.steervehicle.sideways, pbuf, 4);
swapEndian(&packet->data.play_server.steervehicle.sideways, 4);
ADX(4)
//forward
CPS(4)
memcpy(&packet->data.play_server.steervehicle.forward, pbuf, 4);
swapEndian(&packet->data.play_server.steervehicle.forward, 4);
ADX(4)
//flags
CPS(1)
memcpy(&packet->data.play_server.steervehicle.flags, pbuf, 1);
ADX(1)
} else if (id == PKT_PLAY_SERVER_RESOURCEPACKSTATUS) {
//result
rx = readVarInt(&packet->data.play_server.resourcepackstatus.result, pbuf, ps);
ADRX
} else if (id == PKT_PLAY_SERVER_HELDITEMCHANGE) {
//slot
CPS(2)
memcpy(&packet->data.play_server.helditemchange.slot, pbuf, 2);
swapEndian(&packet->data.play_server.helditemchange.slot, 2);
ADX(2)
} else if (id == PKT_PLAY_SERVER_CREATIVEINVENTORYACTION) {
//slot
CPS(2)
memcpy(&packet->data.play_server.creativeinventoryaction.slot, pbuf, 2);
swapEndian(&packet->data.play_server.creativeinventoryaction.slot, 2);
ADX(2)
//clicked_item
rx = readSlot(packet->pool, &packet->data.play_server.creativeinventoryaction.clicked_item, pbuf, ps);
ADRX
} else if (id == PKT_PLAY_SERVER_UPDATESIGN) {
//location
CPS(8)
memcpy(&packet->data.play_server.updatesign.location, pbuf, 8);
swapEndian(&packet->data.play_server.updatesign.location, 8);
ADX(8)
//line_1
rx = readString(packet->pool, &packet->data.play_server.updatesign.line_1, pbuf, ps);
ADRX
//line_2
rx = readString(packet->pool, &packet->data.play_server.updatesign.line_2, pbuf, ps);
ADRX
//line_3
rx = readString(packet->pool, &packet->data.play_server.updatesign.line_3, pbuf, ps);
ADRX
//line_4
rx = readString(packet->pool, &packet->data.play_server.updatesign.line_4, pbuf, ps);
ADRX
} else if (id == PKT_PLAY_SERVER_ANIMATION) {
//hand
rx = readVarInt(&packet->data.play_server.animation.hand, pbuf, ps);
ADRX
} else if (id == PKT_PLAY_SERVER_SPECTATE) {
//target_player
CPS(16)
memcpy(&packet->data.play_server.spectate.target_player, pbuf, 16);
swapEndian(&packet->data.play_server.spectate.target_player, 16);
ADX(16)
} else if (id == PKT_PLAY_SERVER_PLAYERBLOCKPLACEMENT) {
//location
CPS(8)
memcpy(&packet->data.play_server.playerblockplacement.location, pbuf, 8);
swapEndian(&packet->data.play_server.playerblockplacement.location, 8);
ADX(8)
//face
rx = readVarInt(&packet->data.play_server.playerblockplacement.face, pbuf, ps);
ADRX
//hand
rx = readVarInt(&packet->data.play_server.playerblockplacement.hand, pbuf, ps);
ADRX
//cursor_position_x
if (conn->protocol_version > 210) {
CPS(4)
memcpy(&packet->data.play_server.playerblockplacement.cursor_position_x, pbuf, 4);
swapEndian(&packet->data.play_server.playerblockplacement.cursor_position_x, 4);
ADX(4)
} else {
CPS(1)
uint8_t tmp = (uint8_t)(packet->data.play_server.playerblockplacement.cursor_position_x * 15.);
memcpy(&tmp, pbuf, 1);
ADX(1)
}
//cursor_position_y
if (conn->protocol_version > 210) {
CPS(4)
memcpy(&packet->data.play_server.playerblockplacement.cursor_position_y, pbuf, 4);
swapEndian(&packet->data.play_server.playerblockplacement.cursor_position_y, 4);
ADX(4)
} else {
CPS(1)
uint8_t tmp = (uint8_t)(packet->data.play_server.playerblockplacement.cursor_position_y * 15.);
memcpy(&tmp, pbuf, 1);
ADX(1)
}
//cursor_position_z
if (conn->protocol_version > 210) {
CPS(4)
memcpy(&packet->data.play_server.playerblockplacement.cursor_position_z, pbuf, 4);
swapEndian(&packet->data.play_server.playerblockplacement.cursor_position_z, 4);
ADX(4)
} else {
CPS(1)
uint8_t tmp = (uint8_t)(packet->data.play_server.playerblockplacement.cursor_position_z * 15.);
memcpy(&tmp, pbuf, 1);
ADX(1)
}
} else if (id == PKT_PLAY_SERVER_USEITEM) {
//hand
rx = readVarInt(&packet->data.play_server.useitem.hand, pbuf, ps);
ADRX
}
} else if (conn->protocol_state == STATE_STATUS) {
if (id == PKT_STATUS_SERVER_REQUEST) {
} else if (id == PKT_STATUS_SERVER_PING) {
//payload
CPS(8)
memcpy(&packet->data.status_server.ping.payload, pbuf, 8);
swapEndian(&packet->data.status_server.ping.payload, 8);
ADX(8)
}
} else if (conn->protocol_state == STATE_LOGIN) {
if (id == PKT_LOGIN_SERVER_LOGINSTART) {
//name
rx = readString(packet->pool, &packet->data.login_server.loginstart.name, pbuf, ps);
ADRX
} else if (id == PKT_LOGIN_SERVER_ENCRYPTIONRESPONSE) {
//shared_secret_length
rx = readVarInt(&packet->data.login_server.encryptionresponse.shared_secret_length, pbuf, ps);
ADRX
//shared_secret
CPS(packet->data.login_server.encryptionresponse.shared_secret_length)
packet->data.login_server.encryptionresponse.shared_secret = pmalloc(packet->pool,
(size_t) packet->data.login_server.encryptionresponse.shared_secret_length);
memcpy(packet->data.login_server.encryptionresponse.shared_secret, pbuf,
(size_t) packet->data.login_server.encryptionresponse.shared_secret_length);
ADX(packet->data.login_server.encryptionresponse.shared_secret_length)
//verify_token_length
rx = readVarInt((int32_t*) &packet->data.login_server.encryptionresponse.verify_token_length, pbuf, ps);
ADRX
//verify_token
CPS(packet->data.login_server.encryptionresponse.verify_token_length)
packet->data.login_server.encryptionresponse.verify_token = pmalloc(packet->pool, packet->data.login_server.encryptionresponse.verify_token_length);
memcpy(packet->data.login_server.encryptionresponse.verify_token, pbuf, packet->data.login_server.encryptionresponse.verify_token_length);
ADX(packet->data.login_server.encryptionresponse.verify_token_length)
}
}
goto rx;
rer: ;
pfree(packet->pool);
return -1;
rx: ;
pfree(packet->pool);
return buflen;
}
ssize_t packet_write(struct connection* conn, struct packet* packet) {
if (conn->protocol_state == STATE_PLAY && packet->id == PKT_PLAY_CLIENT_CHUNKDATA) {
if (world_get_chunk(conn->player->world, packet->data.play_client.chunkdata.cx, packet->data.play_client.chunkdata.cz) == NULL) return 0;
}
unsigned char* pktbuf = pmalloc(packet->pool, 522);
pktbuf += 10;
size_t ps = 512;
size_t pi = 0;
size_t slb = 0;
int32_t id = packet->id;
ENS(4)
pi += writeVarInt(id, pktbuf + pi);
if (conn->protocol_state == STATE_HANDSHAKE) {
} else if (conn->protocol_state == STATE_PLAY) {
//printf("write %i\n", id);
if (id == PKT_PLAY_CLIENT_SPAWNOBJECT) {
//entity_id
ENS(4)
pi += writeVarInt(packet->data.play_client.spawnobject.entity_id, pktbuf + pi);
//object_uuid
ENS(16)
memcpy(pktbuf + pi, &packet->data.play_client.spawnobject.object_uuid, 16);
swapEndian(pktbuf + pi, 16);
pi += 16;
//type
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.spawnobject.type, 1);
pi += 1;
//x
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.spawnobject.x, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//y
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.spawnobject.y, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//z
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.spawnobject.z, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//pitch
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.spawnobject.pitch, 1);
pi += 1;
//yaw
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.spawnobject.yaw, 1);
pi += 1;
//data
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.spawnobject.data, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//velocity_x
ENS(2)
memcpy(pktbuf + pi, &packet->data.play_client.spawnobject.velocity_x, 2);
swapEndian(pktbuf + pi, 2);
pi += 2;
//velocity_y
ENS(2)
memcpy(pktbuf + pi, &packet->data.play_client.spawnobject.velocity_y, 2);
swapEndian(pktbuf + pi, 2);
pi += 2;
//velocity_z
ENS(2)
memcpy(pktbuf + pi, &packet->data.play_client.spawnobject.velocity_z, 2);
swapEndian(pktbuf + pi, 2);
pi += 2;
} else if (id == PKT_PLAY_CLIENT_SPAWNEXPERIENCEORB) {
//entity_id
ENS(4)
pi += writeVarInt(packet->data.play_client.spawnexperienceorb.entity_id, pktbuf + pi);
//x
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.spawnexperienceorb.x, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//y
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.spawnexperienceorb.y, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//z
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.spawnexperienceorb.z, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//count
ENS(2)
memcpy(pktbuf + pi, &packet->data.play_client.spawnexperienceorb.count, 2);
swapEndian(pktbuf + pi, 2);
pi += 2;
} else if (id == PKT_PLAY_CLIENT_SPAWNGLOBALENTITY) {
//entity_id
ENS(4)
pi += writeVarInt(packet->data.play_client.spawnglobalentity.entity_id, pktbuf + pi);
//type
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.spawnglobalentity.type, 1);
pi += 1;
//x
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.spawnglobalentity.x, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//y
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.spawnglobalentity.y, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//z
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.spawnglobalentity.z, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
} else if (id == PKT_PLAY_CLIENT_SPAWNMOB) {
//entity_id
ENS(4)
pi += writeVarInt(packet->data.play_client.spawnmob.entity_id, pktbuf + pi);
//entity_uuid
ENS(16)
memcpy(pktbuf + pi, &packet->data.play_client.spawnmob.entity_uuid, 16);
swapEndian(pktbuf + pi, 16);
pi += 16;
//type
if (conn->protocol_version > 210) {
ENS(4)
pi += writeVarInt(packet->data.play_client.spawnmob.type, pktbuf + pi);
} else {
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.spawnmob.type, 1);
pi += 1;
}
//x
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.spawnmob.x, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//y
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.spawnmob.y, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//z
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.spawnmob.z, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//yaw
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.spawnmob.yaw, 1);
pi += 1;
//pitch
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.spawnmob.pitch, 1);
pi += 1;
//head_pitch
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.spawnmob.head_pitch, 1);
pi += 1;
//velocity_x
ENS(2)
memcpy(pktbuf + pi, &packet->data.play_client.spawnmob.velocity_x, 2);
swapEndian(pktbuf + pi, 2);
pi += 2;
//velocity_y
ENS(2)
memcpy(pktbuf + pi, &packet->data.play_client.spawnmob.velocity_y, 2);
swapEndian(pktbuf + pi, 2);
pi += 2;
//velocity_z
ENS(2)
memcpy(pktbuf + pi, &packet->data.play_client.spawnmob.velocity_z, 2);
swapEndian(pktbuf + pi, 2);
pi += 2;
//metadata
ENS(packet->data.play_client.spawnmob.metadata.metadata_size)
memcpy(pktbuf + pi, packet->data.play_client.spawnmob.metadata.metadata, packet->data.play_client.spawnmob.metadata.metadata_size);
pi += packet->data.play_client.spawnmob.metadata.metadata_size;
} else if (id == PKT_PLAY_CLIENT_SPAWNPAINTING) {
//entity_id
ENS(4)
pi += writeVarInt(packet->data.play_client.spawnpainting.entity_id, pktbuf + pi);
//entity_uuid
ENS(16)
memcpy(pktbuf + pi, &packet->data.play_client.spawnpainting.entity_uuid, 16);
swapEndian(pktbuf + pi, 16);
pi += 16;
//title
slb = strlen(packet->data.play_client.spawnpainting.title) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.spawnpainting.title, pktbuf + pi, ps - pi);
//location
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.spawnpainting.location, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//direction
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.spawnpainting.direction, 1);
pi += 1;
} else if (id == PKT_PLAY_CLIENT_SPAWNPLAYER) {
//entity_id
ENS(4)
pi += writeVarInt(packet->data.play_client.spawnplayer.entity_id, pktbuf + pi);
//player_uuid
ENS(16)
memcpy(pktbuf + pi, &packet->data.play_client.spawnplayer.player_uuid, 16);
swapEndian(pktbuf + pi, 16);
pi += 16;
//x
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.spawnplayer.x, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//y
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.spawnplayer.y, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//z
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.spawnplayer.z, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//yaw
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.spawnplayer.yaw, 1);
pi += 1;
//pitch
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.spawnplayer.pitch, 1);
pi += 1;
//metadata
ENS(packet->data.play_client.spawnplayer.metadata.metadata_size)
memcpy(pktbuf + pi, packet->data.play_client.spawnplayer.metadata.metadata, packet->data.play_client.spawnplayer.metadata.metadata_size);
pi += packet->data.play_client.spawnplayer.metadata.metadata_size;
} else if (id == PKT_PLAY_CLIENT_ANIMATION) {
//entity_id
ENS(4)
pi += writeVarInt(packet->data.play_client.animation.entity_id, pktbuf + pi);
//animation
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.animation.animation, 1);
pi += 1;
} else if (id == PKT_PLAY_CLIENT_STATISTICS) {
//TODO: Manual Implementation
} else if (id == PKT_PLAY_CLIENT_BLOCKBREAKANIMATION) {
//entity_id
ENS(4)
pi += writeVarInt(packet->data.play_client.blockbreakanimation.entity_id, pktbuf + pi);
//location
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.blockbreakanimation.location, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//destroy_stage
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.blockbreakanimation.destroy_stage, 1);
pi += 1;
} else if (id == PKT_PLAY_CLIENT_UPDATEBLOCKENTITY) {
//location
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.updateblockentity.location, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//action
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.updateblockentity.action, 1);
pi += 1;
//nbt_data
ENS(512)
pi += nbt_write(packet->data.play_client.updateblockentity.nbt_data, pktbuf + pi, ps - pi);
} else if (id == PKT_PLAY_CLIENT_BLOCKACTION) {
//location
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.blockaction.location, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//action_id_byte_1
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.blockaction.action_id, 1);
pi += 1;
//action_param_byte_2
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.blockaction.action_param, 1);
pi += 1;
//block_type
ENS(4)
pi += writeVarInt(packet->data.play_client.blockaction.block_type, pktbuf + pi);
} else if (id == PKT_PLAY_CLIENT_BLOCKCHANGE) {
//location
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.blockchange.location, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//block_id
ENS(4)
pi += writeVarInt(packet->data.play_client.blockchange.block_id, pktbuf + pi);
} else if (id == PKT_PLAY_CLIENT_BOSSBAR) {
//TODO: Manual Implementation
} else if (id == PKT_PLAY_CLIENT_SERVERDIFFICULTY) {
//difficulty
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.serverdifficulty.difficulty, 1);
pi += 1;
} else if (id == PKT_PLAY_CLIENT_TABCOMPLETE) {
//count
ENS(4)
pi += writeVarInt(packet->data.play_client.tabcomplete.count, pktbuf + pi);
//matches
for (int32_t i = 0; i < packet->data.play_client.tabcomplete.count; i++) {
slb = strlen(packet->data.play_client.tabcomplete.matches[i]) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.tabcomplete.matches[i], pktbuf + pi, ps - pi);
}
} else if (id == PKT_PLAY_CLIENT_CHATMESSAGE) {
//json_data
slb = strlen(packet->data.play_client.chatmessage.json_data) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.chatmessage.json_data, pktbuf + pi, ps - pi);
//position
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.chatmessage.position, 1);
pi += 1;
} else if (id == PKT_PLAY_CLIENT_MULTIBLOCKCHANGE) {
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.multiblockchange.chunk_x, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.multiblockchange.chunk_z, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
ENS(4)
pi += writeVarInt(packet->data.play_client.multiblockchange.record_count, pktbuf + pi);
for (int32_t i = 0; i < packet->data.play_client.multiblockchange.record_count; i++) {
ENS(2)
memcpy(pktbuf + pi, ((uint8_t*) &packet->data.play_client.multiblockchange.records[i]), 2);
swapEndian(pktbuf + pi, 2);
pi += 2;
ENS(4)
pi += writeVarInt(packet->data.play_client.multiblockchange.records[i].block_id, pktbuf + pi);
}
} else if (id == PKT_PLAY_CLIENT_CONFIRMTRANSACTION) {
//window_id
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.confirmtransaction.window_id, 1);
pi += 1;
//action_number
ENS(2)
memcpy(pktbuf + pi, &packet->data.play_client.confirmtransaction.action_number, 2);
swapEndian(pktbuf + pi, 2);
pi += 2;
//accepted
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.confirmtransaction.accepted, 1);
pi += 1;
} else if (id == PKT_PLAY_CLIENT_CLOSEWINDOW) {
//window_id
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.closewindow.window_id, 1);
pi += 1;
} else if (id == PKT_PLAY_CLIENT_OPENWINDOW) {
//window_id
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.openwindow.window_id, 1);
pi += 1;
//window_type
slb = strlen(packet->data.play_client.openwindow.window_type) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.openwindow.window_type, pktbuf + pi, ps - pi);
//window_title
slb = strlen(packet->data.play_client.openwindow.window_title) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.openwindow.window_title, pktbuf + pi, ps - pi);
//number_of_slots
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.openwindow.number_of_slots, 1);
pi += 1;
//entity_id
if (str_eq(packet->data.play_client.openwindow.window_type, "EntityHorse")) {
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.openwindow.entity_id, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
}
} else if (id == PKT_PLAY_CLIENT_WINDOWITEMS) {
//window_id
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.windowitems.window_id, 1);
pi += 1;
//count
ENS(2)
memcpy(pktbuf + pi, &packet->data.play_client.windowitems.count, 2);
swapEndian(pktbuf + pi, 2);
pi += 2;
//slot_data
for (int16_t i = 0; i < packet->data.play_client.windowitems.count; i++) {
ENS(512)
pi += writeSlot(&packet->data.play_client.windowitems.slot_data[i], pktbuf + pi, ps - pi);
}
} else if (id == PKT_PLAY_CLIENT_WINDOWPROPERTY) {
//window_id
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.windowproperty.window_id, 1);
pi += 1;
//property
ENS(2)
memcpy(pktbuf + pi, &packet->data.play_client.windowproperty.property, 2);
swapEndian(pktbuf + pi, 2);
pi += 2;
//value
ENS(2)
memcpy(pktbuf + pi, &packet->data.play_client.windowproperty.value, 2);
swapEndian(pktbuf + pi, 2);
pi += 2;
} else if (id == PKT_PLAY_CLIENT_SETSLOT) {
//window_id
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.setslot.window_id, 1);
pi += 1;
//slot
ENS(2)
memcpy(pktbuf + pi, &packet->data.play_client.setslot.slot, 2);
swapEndian(pktbuf + pi, 2);
pi += 2;
//slot_data
ENS(512)
pi += writeSlot(&packet->data.play_client.setslot.slot_data, pktbuf + pi, ps - pi);
} else if (id == PKT_PLAY_CLIENT_SETCOOLDOWN) {
//item_id
ENS(4)
pi += writeVarInt(packet->data.play_client.setcooldown.item_id, pktbuf + pi);
//cooldown_ticks
ENS(4)
pi += writeVarInt(packet->data.play_client.setcooldown.cooldown_ticks, pktbuf + pi);
} else if (id == PKT_PLAY_CLIENT_PLUGINMESSAGE) {
//channel
slb = strlen(packet->data.play_client.pluginmessage.channel) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.pluginmessage.channel, pktbuf + pi, ps - pi);
//data
ENS(packet->data.play_client.pluginmessage.data_size)
memcpy(pktbuf + pi, packet->data.play_client.pluginmessage.data, packet->data.play_client.pluginmessage.data_size);
pi += packet->data.play_client.pluginmessage.data_size;
} else if (id == PKT_PLAY_CLIENT_NAMEDSOUNDEFFECT) {
//sound_name
slb = strlen(packet->data.play_client.namedsoundeffect.sound_name) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.namedsoundeffect.sound_name, pktbuf + pi, ps - pi);
//sound_category
ENS(4)
pi += writeVarInt(packet->data.play_client.namedsoundeffect.sound_category, pktbuf + pi);
//effect_position_x
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.namedsoundeffect.effect_position_x, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//effect_position_y
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.namedsoundeffect.effect_position_y, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//effect_position_z
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.namedsoundeffect.effect_position_z, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//volume
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.namedsoundeffect.volume, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//pitch
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.namedsoundeffect.pitch, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
} else if (id == PKT_PLAY_CLIENT_DISCONNECT) {
//reason
slb = strlen(packet->data.play_client.disconnect.reason) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.disconnect.reason, pktbuf + pi, ps - pi);
} else if (id == PKT_PLAY_CLIENT_ENTITYSTATUS) {
//entity_id
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.entitystatus.entity_id, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//entity_status
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.entitystatus.entity_status, 1);
pi += 1;
} else if (id == PKT_PLAY_CLIENT_EXPLOSION) {
//x
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.explosion.x, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//y
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.explosion.y, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//z
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.explosion.z, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//radius
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.explosion.radius, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//record_count
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.explosion.record_count, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//records
ENS(packet->data.play_client.explosion.record_count * 3)
memcpy(pktbuf + pi, packet->data.play_client.explosion.records,
(size_t) (packet->data.play_client.explosion.record_count * 3));
pi += packet->data.play_client.explosion.record_count * 3;
//player_motion_x
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.explosion.player_motion_x, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//player_motion_y
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.explosion.player_motion_y, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//player_motion_z
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.explosion.player_motion_z, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
} else if (id == PKT_PLAY_CLIENT_UNLOADCHUNK) {
//chunk_x
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.unloadchunk.chunk_x, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//chunk_z
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.unloadchunk.chunk_z, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//packet->data.play_client.unloadchunk.ch->playersLoaded--;
} else if (id == PKT_PLAY_CLIENT_CHANGEGAMESTATE) {
//reason
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.changegamestate.reason, 1);
pi += 1;
//value
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.changegamestate.value, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
} else if (id == PKT_PLAY_CLIENT_KEEPALIVE) {
//keep_alive_id
ENS(4)
pi += writeVarInt(packet->data.play_client.keepalive.keep_alive_id, pktbuf + pi);
} else if (id == PKT_PLAY_CLIENT_CHUNKDATA) {
//chunk_x
ENS(4)
int32_t cx = packet->data.play_client.chunkdata.data->x;
int32_t cz = packet->data.play_client.chunkdata.data->z;
memcpy(pktbuf + pi, &cx, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//chunk_z
ENS(4)
memcpy(pktbuf + pi, &cz, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//ground_up_continuous
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.chunkdata.ground_up_continuous, 1);
pi += 1;
//primary_bit_mask
uint16_t primary_bit_mask = 0;
int32_t ccs = 0;
for (int ymj = 0; ymj < 16; ymj++) {
if (packet->data.play_client.chunkdata.data->sections[ymj] == NULL) continue;
primary_bit_mask |= (uint16_t) pow(2, ymj);
ccs += packet->data.play_client.chunkdata.data->sections[ymj]->bits_per_block * 512 + 4 + 2048;
if (packet->data.play_client.chunkdata.data->sections[ymj]->skyLight != NULL) ccs += 2048;
for (int i = 0; i < packet->data.play_client.chunkdata.data->sections[ymj]->palette_count; i++) {
ccs += getVarIntSize(packet->data.play_client.chunkdata.data->sections[ymj]->palette[i]);
}
}
ENS(4)
pi += writeVarInt(primary_bit_mask, pktbuf + pi);
//size
ENS(4)
pi += writeVarInt(ccs + (packet->data.play_client.chunkdata.ground_up_continuous ? 256 : 0), pktbuf + pi);
//data
for (int ymj = 0; ymj < 16; ymj++) {
if (packet->data.play_client.chunkdata.data->sections[ymj] == NULL) continue;
uint8_t bpb = packet->data.play_client.chunkdata.data->sections[ymj]->bits_per_block;
ENS(1)
memcpy(pktbuf + pi, &bpb, 1);
pi += 1;
ENS(4)
pi += writeVarInt(
(int32_t) (bpb < 9 ? packet->data.play_client.chunkdata.data->sections[ymj]->palette_count : 0), pktbuf + pi);
for (int i = 0; i < packet->data.play_client.chunkdata.data->sections[ymj]->palette_count; i++) {
ENS(4)
pi += writeVarInt(packet->data.play_client.chunkdata.data->sections[ymj]->palette[i], pktbuf + pi);
}
ENS(4)
pi += writeVarInt(bpb * 64, pktbuf + pi);
ENS(bpb * 512)
memcpy(pktbuf + pi, packet->data.play_client.chunkdata.data->sections[ymj]->blocks, bpb * 512);
int64_t* es = (int64_t*) (pktbuf + pi);
for (int i = 0; i < bpb * 64; i++) {
swapEndian(&es[i], 8);
}
pi += bpb * 512;
ENS(2048);
memcpy(pktbuf + pi, packet->data.play_client.chunkdata.data->sections[ymj]->blockLight, 2048);
//memset(pktbuf + pi, 0xFF, 2048);
pi += 2048;
if (packet->data.play_client.chunkdata.data->sections[ymj]->skyLight != NULL) {
ENS(2048);
memcpy(pktbuf + pi, packet->data.play_client.chunkdata.data->sections[ymj]->skyLight, 2048);
//memset(pktbuf + pi, 0xFF, 2048);
pi += 2048;
}
}
//biomes
if (packet->data.play_client.chunkdata.ground_up_continuous) {
ENS(256)
memcpy(pktbuf + pi, packet->data.play_client.chunkdata.data->biomes, 256);
pi += 256;
}
//number_of_block_entities
ENS(4)
pi += writeVarInt(packet->data.play_client.chunkdata.number_of_block_entities, pktbuf + pi);
//block_entities
for (int32_t i = 0; i < packet->data.play_client.chunkdata.number_of_block_entities; i++) {
ENS(512)
pi += nbt_write(packet->data.play_client.chunkdata.block_entities[i], pktbuf + pi, ps - pi);
}
} else if (id == PKT_PLAY_CLIENT_EFFECT) {
//effect_id
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.effect.effect_id, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//location
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.effect.location, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//data
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.effect.data, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//disable_relative_volume
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.effect.disable_relative_volume, 1);
pi += 1;
} else if (id == PKT_PLAY_CLIENT_PARTICLE) {
//particle_id
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.particle.particle_id, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//long_distance
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.particle.long_distance, 1);
pi += 1;
//x
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.particle.x, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//y
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.particle.y, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//z
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.particle.z, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//offset_x
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.particle.offset_x, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//offset_y
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.particle.offset_y, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//offset_z
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.particle.offset_z, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//particle_data
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.particle.particle_data, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//particle_count
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.particle.particle_count, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//data
/* TODO: Array
ENS(4)
pi += writeVarInt(packet->data.play_client.particle.data, pktbuf + pi);
*/
} else if (id == PKT_PLAY_CLIENT_JOINGAME) {
//entity_id
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.joingame.entity_id, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//gamemode
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.joingame.gamemode, 1);
pi += 1;
//dimension
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.joingame.dimension, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//difficulty
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.joingame.difficulty, 1);
pi += 1;
//max_players
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.joingame.max_players, 1);
pi += 1;
//level_type
slb = strlen(packet->data.play_client.joingame.level_type) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.joingame.level_type, pktbuf + pi, ps - pi);
//reduced_debug_info
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.joingame.reduced_debug_info, 1);
pi += 1;
} else if (id == PKT_PLAY_CLIENT_MAP) {
//TODO: Manual Implementation
} else if (id == PKT_PLAY_CLIENT_ENTITYRELATIVEMOVE) {
//entity_id
ENS(4)
pi += writeVarInt(packet->data.play_client.entityrelativemove.entity_id, pktbuf + pi);
//delta_x
ENS(2)
memcpy(pktbuf + pi, &packet->data.play_client.entityrelativemove.delta_x, 2);
swapEndian(pktbuf + pi, 2);
pi += 2;
//delta_y
ENS(2)
memcpy(pktbuf + pi, &packet->data.play_client.entityrelativemove.delta_y, 2);
swapEndian(pktbuf + pi, 2);
pi += 2;
//delta_z
ENS(2)
memcpy(pktbuf + pi, &packet->data.play_client.entityrelativemove.delta_z, 2);
swapEndian(pktbuf + pi, 2);
pi += 2;
//on_ground
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.entityrelativemove.on_ground, 1);
pi += 1;
} else if (id == PKT_PLAY_CLIENT_ENTITYLOOKANDRELATIVEMOVE) {
//entity_id
ENS(4)
pi += writeVarInt(packet->data.play_client.entitylookandrelativemove.entity_id, pktbuf + pi);
//delta_x
ENS(2)
memcpy(pktbuf + pi, &packet->data.play_client.entitylookandrelativemove.delta_x, 2);
swapEndian(pktbuf + pi, 2);
pi += 2;
//delta_y
ENS(2)
memcpy(pktbuf + pi, &packet->data.play_client.entitylookandrelativemove.delta_y, 2);
swapEndian(pktbuf + pi, 2);
pi += 2;
//delta_z
ENS(2)
memcpy(pktbuf + pi, &packet->data.play_client.entitylookandrelativemove.delta_z, 2);
swapEndian(pktbuf + pi, 2);
pi += 2;
//yaw
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.entitylookandrelativemove.yaw, 1);
pi += 1;
//pitch
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.entitylookandrelativemove.pitch, 1);
pi += 1;
//on_ground
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.entitylookandrelativemove.on_ground, 1);
pi += 1;
} else if (id == PKT_PLAY_CLIENT_ENTITYLOOK) {
//entity_id
ENS(4)
pi += writeVarInt(packet->data.play_client.entitylook.entity_id, pktbuf + pi);
//yaw
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.entitylook.yaw, 1);
pi += 1;
//pitch
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.entitylook.pitch, 1);
pi += 1;
//on_ground
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.entitylook.on_ground, 1);
pi += 1;
} else if (id == PKT_PLAY_CLIENT_ENTITY) {
//entity_id
ENS(4)
pi += writeVarInt(packet->data.play_client.entity.entity_id, pktbuf + pi);
} else if (id == PKT_PLAY_CLIENT_VEHICLEMOVE) {
//x
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.vehiclemove.x, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//y
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.vehiclemove.y, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//z
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.vehiclemove.z, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//yaw
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.vehiclemove.yaw, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//pitch
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.vehiclemove.pitch, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
} else if (id == PKT_PLAY_CLIENT_OPENSIGNEDITOR) {
//location
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.opensigneditor.location, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
} else if (id == PKT_PLAY_CLIENT_PLAYERABILITIES) {
//flags
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.playerabilities.flags, 1);
pi += 1;
//flying_speed
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.playerabilities.flying_speed, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//field_of_view_modifier
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.playerabilities.field_of_view_modifier, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
} else if (id == PKT_PLAY_CLIENT_COMBATEVENT) {
//TODO: Manual Implementation
} else if (id == PKT_PLAY_CLIENT_PLAYERLISTITEM) {
//action_id
ENS(4)
pi += writeVarInt(packet->data.play_client.playerlistitem.action_id, pktbuf + pi);
//number_of_players
ENS(4)
pi += writeVarInt(packet->data.play_client.playerlistitem.number_of_players, pktbuf + pi);
for (int32_t i = 0; i < packet->data.play_client.playerlistitem.number_of_players; i++) {
ENS(16)
memcpy(pktbuf + pi, &packet->data.play_client.playerlistitem.players[i].uuid, 16);
swapEndian(pktbuf + pi, 16);
pi += 16;
if (packet->data.play_client.playerlistitem.action_id == 0) {
slb = strlen(packet->data.play_client.playerlistitem.players[i].action.addplayer.name) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.playerlistitem.players[i].action.addplayer.name, pktbuf + pi, ps - pi);
ENS(4)
pi += writeVarInt(packet->data.play_client.playerlistitem.players[i].action.addplayer.number_of_properties, pktbuf + pi);
for (int32_t x = 0; x < packet->data.play_client.playerlistitem.players[i].action.addplayer.number_of_properties; x++) {
slb = strlen(packet->data.play_client.playerlistitem.players[i].action.addplayer.properties[x].name) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.playerlistitem.players[i].action.addplayer.properties[x].name, pktbuf + pi, ps - pi);
slb = strlen(packet->data.play_client.playerlistitem.players[i].action.addplayer.properties[x].value) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.playerlistitem.players[i].action.addplayer.properties[x].value, pktbuf + pi, ps - pi);
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.playerlistitem.players[i].action.addplayer.properties[x].isSigned, 1);
pi += 1;
if (packet->data.play_client.playerlistitem.players[i].action.addplayer.properties[x].isSigned) {
slb = strlen(packet->data.play_client.playerlistitem.players[i].action.addplayer.properties[x].signature) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.playerlistitem.players[i].action.addplayer.properties[x].signature, pktbuf + pi, ps - pi);
}
}
ENS(4)
pi += writeVarInt(packet->data.play_client.playerlistitem.players[i].action.addplayer.gamemode, pktbuf + pi);
ENS(4)
pi += writeVarInt(packet->data.play_client.playerlistitem.players[i].action.addplayer.ping, pktbuf + pi);
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.playerlistitem.players[i].action.addplayer.has_display_name, 1);
pi += 1;
if (packet->data.play_client.playerlistitem.players[i].action.addplayer.has_display_name) {
slb = strlen(packet->data.play_client.playerlistitem.players[i].action.addplayer.display_name) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.playerlistitem.players[i].action.addplayer.display_name, pktbuf + pi, ps - pi);
}
} else if (packet->data.play_client.playerlistitem.action_id == 1) {
ENS(4)
pi += writeVarInt(packet->data.play_client.playerlistitem.players[i].action.updategamemode_gamemode, pktbuf + pi);
} else if (packet->data.play_client.playerlistitem.action_id == 2) {
ENS(4)
pi += writeVarInt(packet->data.play_client.playerlistitem.players[i].action.updatelatency_ping, pktbuf + pi);
} else if (packet->data.play_client.playerlistitem.action_id == 3) {
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.playerlistitem.players[i].action.updatedisplayname.has_display_name, 1);
pi += 1;
if (packet->data.play_client.playerlistitem.players[i].action.updatedisplayname.has_display_name) {
slb = strlen(packet->data.play_client.playerlistitem.players[i].action.updatedisplayname.display_name) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.playerlistitem.players[i].action.updatedisplayname.display_name, pktbuf + pi, ps - pi);
}
} else if (packet->data.play_client.playerlistitem.action_id == 4) {
//none
}
}
} else if (id == PKT_PLAY_CLIENT_PLAYERPOSITIONANDLOOK) {
//x
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.playerpositionandlook.x, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//y
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.playerpositionandlook.y, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//z
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.playerpositionandlook.z, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//yaw
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.playerpositionandlook.yaw, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//pitch
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.playerpositionandlook.pitch, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//flags
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.playerpositionandlook.flags, 1);
pi += 1;
//teleport_id
ENS(4)
pi += writeVarInt(packet->data.play_client.playerpositionandlook.teleport_id, pktbuf + pi);
} else if (id == PKT_PLAY_CLIENT_USEBED) {
//entity_id
ENS(4)
pi += writeVarInt(packet->data.play_client.usebed.entity_id, pktbuf + pi);
//location
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.usebed.location, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
} else if (id == PKT_PLAY_CLIENT_DESTROYENTITIES) {
//count
ENS(4)
pi += writeVarInt(packet->data.play_client.destroyentities.count, pktbuf + pi);
//entity_ids
ENS(4 * packet->data.play_client.destroyentities.count)
for (size_t i = 0; i < packet->data.play_client.destroyentities.count; i++)
pi += writeVarInt(packet->data.play_client.destroyentities.entity_ids[i], pktbuf + pi);
} else if (id == PKT_PLAY_CLIENT_REMOVEENTITYEFFECT) {
//entity_id
ENS(4)
pi += writeVarInt(packet->data.play_client.removeentityeffect.entity_id, pktbuf + pi);
//effect_id
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.removeentityeffect.effect_id, 1);
pi += 1;
} else if (id == PKT_PLAY_CLIENT_RESOURCEPACKSEND) {
//url
slb = strlen(packet->data.play_client.resourcepacksend.url) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.resourcepacksend.url, pktbuf + pi, ps - pi);
//hash
slb = strlen(packet->data.play_client.resourcepacksend.hash) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.resourcepacksend.hash, pktbuf + pi, ps - pi);
} else if (id == PKT_PLAY_CLIENT_RESPAWN) {
//dimension
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.respawn.dimension, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//difficulty
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.respawn.difficulty, 1);
pi += 1;
//gamemode
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.respawn.gamemode, 1);
pi += 1;
//level_type
slb = strlen(packet->data.play_client.respawn.level_type) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.respawn.level_type, pktbuf + pi, ps - pi);
} else if (id == PKT_PLAY_CLIENT_ENTITYHEADLOOK) {
//entity_id
ENS(4)
pi += writeVarInt(packet->data.play_client.entityheadlook.entity_id, pktbuf + pi);
//head_yaw
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.entityheadlook.head_yaw, 1);
pi += 1;
} else if (id == PKT_PLAY_CLIENT_WORLDBORDER) {
//TODO: Manual Implementation
} else if (id == PKT_PLAY_CLIENT_CAMERA) {
//camera_id
ENS(4)
pi += writeVarInt(packet->data.play_client.camera.camera_id, pktbuf + pi);
} else if (id == PKT_PLAY_CLIENT_HELDITEMCHANGE) {
//slot
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.helditemchange.slot, 1);
pi += 1;
} else if (id == PKT_PLAY_CLIENT_DISPLAYSCOREBOARD) {
//position
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.displayscoreboard.position, 1);
pi += 1;
//score_name
slb = strlen(packet->data.play_client.displayscoreboard.score_name) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.displayscoreboard.score_name, pktbuf + pi, ps - pi);
} else if (id == PKT_PLAY_CLIENT_ENTITYMETADATA) {
//entity_id
ENS(4)
pi += writeVarInt(packet->data.play_client.entitymetadata.entity_id, pktbuf + pi);
//metadata
ENS(packet->data.play_client.entitymetadata.metadata.metadata_size)
memcpy(pktbuf + pi, packet->data.play_client.entitymetadata.metadata.metadata, packet->data.play_client.entitymetadata.metadata.metadata_size);
pi += packet->data.play_client.entitymetadata.metadata.metadata_size;
} else if (id == PKT_PLAY_CLIENT_ATTACHENTITY) {
//attached_entity_id
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.attachentity.attached_entity_id, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//holding_entity_id
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.attachentity.holding_entity_id, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
} else if (id == PKT_PLAY_CLIENT_ENTITYVELOCITY) {
//entity_id
ENS(4)
pi += writeVarInt(packet->data.play_client.entityvelocity.entity_id, pktbuf + pi);
//velocity_x
ENS(2)
memcpy(pktbuf + pi, &packet->data.play_client.entityvelocity.velocity_x, 2);
swapEndian(pktbuf + pi, 2);
pi += 2;
//velocity_y
ENS(2)
memcpy(pktbuf + pi, &packet->data.play_client.entityvelocity.velocity_y, 2);
swapEndian(pktbuf + pi, 2);
pi += 2;
//velocity_z
ENS(2)
memcpy(pktbuf + pi, &packet->data.play_client.entityvelocity.velocity_z, 2);
swapEndian(pktbuf + pi, 2);
pi += 2;
} else if (id == PKT_PLAY_CLIENT_ENTITYEQUIPMENT) {
//entity_id
ENS(4)
pi += writeVarInt(packet->data.play_client.entityequipment.entity_id, pktbuf + pi);
//slot
ENS(4)
pi += writeVarInt(packet->data.play_client.entityequipment.slot, pktbuf + pi);
//item
ENS(512)
pi += writeSlot(&packet->data.play_client.entityequipment.item, pktbuf + pi, ps - pi);
} else if (id == PKT_PLAY_CLIENT_SETEXPERIENCE) {
//experience_bar
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.setexperience.experience_bar, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//level
ENS(4)
pi += writeVarInt(packet->data.play_client.setexperience.level, pktbuf + pi);
//total_experience
ENS(4)
pi += writeVarInt(packet->data.play_client.setexperience.total_experience, pktbuf + pi);
} else if (id == PKT_PLAY_CLIENT_UPDATEHEALTH) {
//health
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.updatehealth.health, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//food
ENS(4)
pi += writeVarInt(packet->data.play_client.updatehealth.food, pktbuf + pi);
//food_saturation
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.updatehealth.food_saturation, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
} else if (id == PKT_PLAY_CLIENT_SCOREBOARDOBJECTIVE) {
//objective_name
slb = strlen(packet->data.play_client.scoreboardobjective.objective_name) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.scoreboardobjective.objective_name, pktbuf + pi, ps - pi);
//mode
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.scoreboardobjective.mode, 1);
pi += 1;
//objective_value
/* TODO: Optional
slb = strlen(packet->data.play_client.scoreboardobjective.objective_value) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.scoreboardobjective.objective_value, pktbuf + pi, ps - pi);
*/
//type
/* TODO: Optional
slb = strlen(packet->data.play_client.scoreboardobjective.type) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.scoreboardobjective.type, pktbuf + pi, ps - pi);
*/
} else if (id == PKT_PLAY_CLIENT_SETPASSENGERS) {
//entity_id
ENS(4)
pi += writeVarInt(packet->data.play_client.setpassengers.entity_id, pktbuf + pi);
//passenger_count
ENS(4)
pi += writeVarInt(packet->data.play_client.setpassengers.passenger_count, pktbuf + pi);
//passengers
/* TODO: Array
ENS(4)
pi += writeVarInt(packet->data.play_client.setpassengers.passengers, pktbuf + pi);
*/
} else if (id == PKT_PLAY_CLIENT_TEAMS) {
//TODO: Manual Implementation
} else if (id == PKT_PLAY_CLIENT_UPDATESCORE) {
//score_name
slb = strlen(packet->data.play_client.updatescore.score_name) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.updatescore.score_name, pktbuf + pi, ps - pi);
//action
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.updatescore.action, 1);
pi += 1;
//objective_name
slb = strlen(packet->data.play_client.updatescore.objective_name) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.updatescore.objective_name, pktbuf + pi, ps - pi);
//value
/* TODO: Optional
ENS(4)
pi += writeVarInt(packet->data.play_client.updatescore.value, pktbuf + pi);
*/
} else if (id == PKT_PLAY_CLIENT_SPAWNPOSITION) {
//location
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.spawnposition.location, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
} else if (id == PKT_PLAY_CLIENT_TIMEUPDATE) {
//world_age
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.timeupdate.world_age, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//time_of_day
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.timeupdate.time_of_day, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
} else if (id == PKT_PLAY_CLIENT_TITLE) {
//TODO: Manual Implementation
} else if (id == PKT_PLAY_CLIENT_SOUNDEFFECT) {
//sound_id
ENS(4)
pi += writeVarInt(packet->data.play_client.soundeffect.sound_id, pktbuf + pi);
//sound_category
ENS(4)
pi += writeVarInt(packet->data.play_client.soundeffect.sound_category, pktbuf + pi);
//effect_position_x
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.soundeffect.effect_position_x, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//effect_position_y
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.soundeffect.effect_position_y, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//effect_position_z
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.soundeffect.effect_position_z, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//volume
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.soundeffect.volume, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
//pitch
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.soundeffect.pitch, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
} else if (id == PKT_PLAY_CLIENT_PLAYERLISTHEADERANDFOOTER) {
//header
slb = strlen(packet->data.play_client.playerlistheaderandfooter.header) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.playerlistheaderandfooter.header, pktbuf + pi, ps - pi);
//footer
slb = strlen(packet->data.play_client.playerlistheaderandfooter.footer) + 4;
ENS(slb)
pi += writeString(packet->data.play_client.playerlistheaderandfooter.footer, pktbuf + pi, ps - pi);
} else if (id == PKT_PLAY_CLIENT_COLLECTITEM) {
//collected_entity_id
ENS(4)
pi += writeVarInt(packet->data.play_client.collectitem.collected_entity_id, pktbuf + pi);
//collector_entity_id
ENS(4)
pi += writeVarInt(packet->data.play_client.collectitem.collector_entity_id, pktbuf + pi);
//pickup_item_count
if (conn->protocol_version > 210) {
ENS(4)
pi += writeVarInt(packet->data.play_client.collectitem.pickup_item_count, pktbuf + pi);
}
} else if (id == PKT_PLAY_CLIENT_ENTITYTELEPORT) {
//entity_id
ENS(4)
pi += writeVarInt(packet->data.play_client.entityteleport.entity_id, pktbuf + pi);
//x
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.entityteleport.x, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//y
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.entityteleport.y, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//z
ENS(8)
memcpy(pktbuf + pi, &packet->data.play_client.entityteleport.z, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
//yaw
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.entityteleport.yaw, 1);
pi += 1;
//pitch
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.entityteleport.pitch, 1);
pi += 1;
//on_ground
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.entityteleport.on_ground, 1);
pi += 1;
} else if (id == PKT_PLAY_CLIENT_ENTITYPROPERTIES) {
//entity_id
ENS(4)
pi += writeVarInt(packet->data.play_client.entityproperties.entity_id, pktbuf + pi);
ENS(4)
memcpy(pktbuf + pi, &packet->data.play_client.entityproperties.number_of_properties, 4);
swapEndian(pktbuf + pi, 4);
pi += 4;
for (int32_t i = 0; i < packet->data.play_client.entityproperties.number_of_properties; i++) {
struct entity_property* property = &packet->data.play_client.entityproperties.properties[i];
slb = strlen(property->key) + 4;
ENS(slb)
pi += writeString(property->key, pktbuf + pi, ps - pi);
ENS(8)
memcpy(pktbuf + pi, &property->value, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
ENS(4)
pi += writeVarInt(property->number_of_modifiers, pktbuf + pi);
for (int32_t x = 0; x < property->number_of_modifiers; x++) {
struct entity_property_modifier* epm = &property->modifiers[x];
ENS(16)
memcpy(pktbuf + pi, &epm->uuid, 16);
swapEndian(pktbuf + pi, 16);
pi += 16;
ENS(8)
memcpy(pktbuf + pi, &epm->amount, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
ENS(1)
memcpy(pktbuf + pi, &epm->operation, 1);
pi += 1;
}
}
} else if (id == PKT_PLAY_CLIENT_ENTITYEFFECT) {
//entity_id
ENS(4)
pi += writeVarInt(packet->data.play_client.entityeffect.entity_id, pktbuf + pi);
//effect_id
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.entityeffect.effect_id, 1);
pi += 1;
//amplifier
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.entityeffect.amplifier, 1);
pi += 1;
//duration
ENS(4)
pi += writeVarInt(packet->data.play_client.entityeffect.duration, pktbuf + pi);
//flags
ENS(1)
memcpy(pktbuf + pi, &packet->data.play_client.entityeffect.flags, 1);
pi += 1;
}
} else if (conn->protocol_state == STATE_STATUS) {
if (id == PKT_STATUS_CLIENT_RESPONSE) {
//json_response
slb = strlen(packet->data.status_client.response.json_response) + 4;
ENS(slb)
pi += writeString(packet->data.status_client.response.json_response, pktbuf + pi, ps - pi);
} else if (id == PKT_STATUS_CLIENT_PONG) {
//payload
ENS(8)
memcpy(pktbuf + pi, &packet->data.status_client.pong.payload, 8);
swapEndian(pktbuf + pi, 8);
pi += 8;
}
} else if (conn->protocol_state == STATE_LOGIN) {
if (id == PKT_LOGIN_CLIENT_DISCONNECT) {
//reason
slb = strlen(packet->data.login_client.disconnect.reason) + 4;
ENS(slb)
pi += writeString(packet->data.login_client.disconnect.reason, pktbuf + pi, ps - pi);
} else if (id == PKT_LOGIN_CLIENT_ENCRYPTIONREQUEST) {
//server_id
slb = strlen(packet->data.login_client.encryptionrequest.server_id) + 4;
ENS(slb)
pi += writeString(packet->data.login_client.encryptionrequest.server_id, pktbuf + pi, ps - pi);
//public_key_length
ENS(4)
pi += writeVarInt(packet->data.login_client.encryptionrequest.public_key_length, pktbuf + pi);
//public_key
ENS(packet->data.login_client.encryptionrequest.public_key_length)
memcpy(pktbuf + pi, packet->data.login_client.encryptionrequest.public_key,
(size_t) packet->data.login_client.encryptionrequest.public_key_length);
pi += packet->data.login_client.encryptionrequest.public_key_length;
//verify_token_length
ENS(4)
pi += writeVarInt(packet->data.login_client.encryptionrequest.verify_token_length, pktbuf + pi);
//verify_token
ENS(packet->data.login_client.encryptionrequest.verify_token_length)
memcpy(pktbuf + pi, packet->data.login_client.encryptionrequest.verify_token,
(size_t) packet->data.login_client.encryptionrequest.verify_token_length);
pi += packet->data.login_client.encryptionrequest.verify_token_length;
} else if (id == PKT_LOGIN_CLIENT_LOGINSUCCESS) {
//uuid
slb = strlen(packet->data.login_client.loginsuccess.uuid) + 4;
ENS(slb)
pi += writeString(packet->data.login_client.loginsuccess.uuid, pktbuf + pi, ps - pi);
//username
slb = strlen(packet->data.login_client.loginsuccess.username) + 4;
ENS(slb)
pi += writeString(packet->data.login_client.loginsuccess.username, pktbuf + pi, ps - pi);
} else if (id == PKT_LOGIN_CLIENT_SETCOMPRESSION) {
//threshold
ENS(4)
pi += writeVarInt(packet->data.login_client.setcompression.threshold, pktbuf + pi);
}
}
int fpll = getVarIntSize(pi);
void* wrt = NULL;
size_t wrt_s = 0;
unsigned char prep[10];
uint8_t preps = 0;
if (conn->compression_state >= 0 && (pi + fpll > conn->compression_state + 1) && (pi + fpll) <= 2097152) {
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
int dr = 0;
if ((dr = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY)) != Z_OK) { // TODO: configurable level?
goto rret;
}
strm.avail_in = (uInt) pi;
strm.next_in = pktbuf;
size_t cc = pi + 32;
void* cdata = pmalloc(packet->pool, cc + 10);
size_t ts = 0;
strm.avail_out = (uInt) (cc - ts);
strm.next_out = cdata + ts;
do {
dr = deflate(&strm, Z_FINISH);
ts = strm.total_out;
if (ts >= cc) {
cc *= 2;
cdata = prealloc(packet->pool, cdata - 10, cc + 10) + 10;
}
if (dr == Z_STREAM_ERROR) {
goto rret;
}
strm.avail_out = (uInt) (cc - ts);
strm.next_out = cdata + ts;
} while (strm.avail_out == 0);
deflateEnd(&strm);
preps += writeVarInt((int32_t) (ts + getVarIntSize((int32_t) pi)), prep + preps);
preps += writeVarInt((int32_t) pi, prep + preps);
wrt = cdata;
wrt_s = ts;
} else if (conn->compression_state >= 0) {
preps += writeVarInt((int32_t) (pi + getVarIntSize(0)), prep + preps);
preps += writeVarInt(0, prep + preps);
wrt = pktbuf;
wrt_s = pi;
} else {
preps += writeVarInt((int32_t) pi, prep + preps);
wrt = pktbuf;
wrt_s = pi;
}
if (preps >= 10) goto rret;
void* xfer_address = wrt - 10;
// ^ explode
wrt -= preps; // preallocated!
memcpy(wrt, prep, preps);
wrt_s += preps;
if (conn->aes_ctx_enc != NULL) {
size_t encrypted_length = wrt_s + 32; // 16 extra just in case
void* encrypted = pmalloc(packet->pool, encrypted_length);
if (EVP_EncryptUpdate(conn->aes_ctx_enc, encrypted, &encrypted_length, wrt, (int) wrt_s) != 1) {
wrt_s = (size_t) -1;
goto rret;
}
xfer_address = wrt = encrypted;
wrt_s = encrypted_length;
}
pxfer(packet->pool, conn->managed_conn->write_buffer.pool, xfer_address);
buffer_push_partial(&conn->managed_conn->write_buffer, xfer_address, wrt, wrt_s);
rret: ;
return wrt_s;
}