Skip to content

Commit c5e8408

Browse files
SDFTDusernamep2r3
andauthored
implement player poses (sneak/sprint)
* Added sending player metadata with poses to everyone * Renamed sendPlayerMetadataToAll to broadcastPlayerMetadata * Made entity metadata system flexible * Made broadcastPlayerMetadata create new metadata instead of using a global one * Moved writeEntityData, sizeEntityData and sizeEntityMetadata to procedures * style nitpicks --------- Co-authored-by: p2r3 <p2r3@p2r3.com>
1 parent e5dfe53 commit c5e8408

6 files changed

Lines changed: 131 additions & 1 deletion

File tree

include/globals.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,19 @@ typedef struct {
248248

249249
#pragma pack(pop)
250250

251+
union EntityDataValue {
252+
uint8_t byte;
253+
int pose;
254+
};
255+
256+
typedef struct {
257+
uint8_t index;
258+
// 0 - Byte
259+
// 21 - Pose
260+
int type;
261+
union EntityDataValue value;
262+
} EntityData;
263+
251264
extern BlockChange block_changes[MAX_BLOCK_CHANGES];
252265
extern int block_changes_count;
253266

include/packets.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ int sc_acknowledgeBlockChange (int client_fd, int sequence);
4848
int sc_playerInfoUpdateAddPlayer (int client_fd, PlayerData player);
4949
int sc_spawnEntity (int client_fd, int id, uint8_t *uuid, int type, double x, double y, double z, uint8_t yaw, uint8_t pitch);
5050
int sc_spawnEntityPlayer (int client_fd, PlayerData player);
51+
int sc_setEntityMetadata (int client_fd, int id, EntityData *metadata, size_t length);
5152
int sc_entityAnimation (int client_fd, int id, uint8_t animation);
5253
int sc_teleportEntity (int client_fd, int id, double x, double y, double z, float yaw, float pitch);
5354
int sc_setHeadRotation (int client_fd, int id, uint8_t yaw);

include/procedures.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ void disconnectClient (int *client_fd, int cause);
2020
int givePlayerItem (PlayerData *player, uint16_t item, uint8_t count);
2121
void spawnPlayer (PlayerData *player);
2222

23+
void broadcastPlayerMetadata (PlayerData *player);
24+
2325
uint8_t serverSlotToClientSlot (int window_id, uint8_t slot);
2426
uint8_t clientSlotToServerSlot (int window_id, uint8_t slot);
2527

@@ -47,4 +49,9 @@ void handleServerTick (int64_t time_since_last_tick);
4749

4850
void broadcastChestUpdate (int origin_fd, uint8_t *storage_ptr, uint16_t item, uint8_t count, uint8_t slot);
4951

52+
ssize_t writeEntityData (int client_fd, EntityData *data);
53+
54+
int sizeEntityData (EntityData *data);
55+
int sizeEntityMetadata (EntityData *metadata, size_t length);
56+
5057
#endif

src/packets.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,10 @@ int cs_setPlayerMovementFlags (int client_fd, uint8_t *on_ground) {
764764

765765
*on_ground = readByte(client_fd) & 0x01;
766766

767+
PlayerData *player;
768+
if (!getPlayerData(client_fd, &player))
769+
broadcastPlayerMetadata(player);
770+
767771
return 0;
768772
}
769773

@@ -910,6 +914,26 @@ int sc_spawnEntity (
910914
return 0;
911915
}
912916

917+
// S->C Set Entity Metadata
918+
int sc_setEntityMetadata (int client_fd, int id, EntityData *metadata, size_t length) {
919+
int entity_metadata_size = sizeEntityMetadata(metadata, length);
920+
if (entity_metadata_size == -1) return 1;
921+
922+
writeVarInt(client_fd, 2 + sizeVarInt(id) + entity_metadata_size);
923+
writeByte(client_fd, 0x5C);
924+
925+
writeVarInt(client_fd, id); // Entity ID
926+
927+
for (size_t i = 0; i < length; i ++) {
928+
EntityData *data = &metadata[i];
929+
writeEntityData(client_fd, data);
930+
}
931+
932+
writeByte(client_fd, 0xFF); // End
933+
934+
return 0;
935+
}
936+
913937
// S->C Spawn Entity (from PlayerData)
914938
int sc_spawnEntityPlayer (int client_fd, PlayerData player) {
915939
return sc_spawnEntity(
@@ -1198,6 +1222,8 @@ int cs_playerInput (int client_fd) {
11981222
if (flags & 0x20) player->flags |= 0x04;
11991223
else player->flags &= ~0x04;
12001224

1225+
broadcastPlayerMetadata(player);
1226+
12011227
return 0;
12021228
}
12031229

@@ -1215,6 +1241,8 @@ int cs_playerCommand (int client_fd) {
12151241
if (action == 1) player->flags |= 0x08;
12161242
else if (action == 2) player->flags &= ~0x08;
12171243

1244+
broadcastPlayerMetadata(player);
1245+
12181246
return 0;
12191247
}
12201248

src/procedures.c

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,43 @@ void spawnPlayer (PlayerData *player) {
368368

369369
}
370370

371+
// Broadcasts a player's entity metadata (sneak/sprint state) to other players
372+
void broadcastPlayerMetadata (PlayerData *player) {
373+
uint8_t sneaking = (player->flags & 0x04) != 0;
374+
uint8_t sprinting = (player->flags & 0x08) != 0;
375+
376+
uint8_t player_bit_mask = 0;
377+
if (sneaking) player_bit_mask |= 0x02;
378+
if (sprinting) player_bit_mask |= 0x08;
379+
380+
int pose = 0;
381+
if (sneaking) pose = 5;
382+
383+
EntityData metadata[] = {
384+
{
385+
0, // Index (Bit Mask)
386+
0, // Type (Byte)
387+
player_bit_mask, // Value
388+
},
389+
{
390+
6, // Index (Pose),
391+
21, // Type (Pose),
392+
pose, // Value (Standing)
393+
}
394+
};
395+
396+
for (int i = 0; i < MAX_PLAYERS; i ++) {
397+
PlayerData* other_player = &player_data[i];
398+
int client_fd = other_player->client_fd;
399+
400+
if (client_fd == -1) continue;
401+
if (client_fd == player->client_fd) continue;
402+
if (other_player->flags & 0x20) continue;
403+
404+
sc_setEntityMetadata(client_fd, player->client_fd, metadata, 2);
405+
}
406+
}
407+
371408
uint8_t getBlockChange (short x, uint8_t y, short z) {
372409
for (int i = 0; i < block_changes_count; i ++) {
373410
if (block_changes[i].block == 0xFF) continue;
@@ -1784,3 +1821,47 @@ void broadcastChestUpdate (int origin_fd, uint8_t *storage_ptr, uint16_t item, u
17841821

17851822
}
17861823
#endif
1824+
1825+
ssize_t writeEntityData (int client_fd, EntityData *data) {
1826+
writeByte(client_fd, data->index);
1827+
writeVarInt(client_fd, data->type);
1828+
1829+
switch (data->type) {
1830+
case 0: // Byte
1831+
return writeByte(client_fd, data->value.byte);
1832+
case 21: // Pose
1833+
writeVarInt(client_fd, data->value.pose);
1834+
return 0;
1835+
1836+
default: return -1;
1837+
}
1838+
}
1839+
1840+
// Returns the networked size of an EntityData entry
1841+
int sizeEntityData (EntityData *data) {
1842+
int value_size;
1843+
1844+
switch (data->type) {
1845+
case 0: // Byte
1846+
value_size = 1;
1847+
break;
1848+
case 21: // Pose
1849+
value_size = sizeVarInt(data->value.pose);
1850+
break;
1851+
1852+
default: return -1;
1853+
}
1854+
1855+
return 1 + sizeVarInt(data->type) + value_size;
1856+
}
1857+
1858+
// Returns the networked size of an array of EntityData entries
1859+
int sizeEntityMetadata (EntityData *metadata, size_t length) {
1860+
int total_size = 0;
1861+
for (size_t i = 0; i < length; i ++) {
1862+
int size = sizeEntityData(&metadata[i]);
1863+
if (size == -1) return -1;
1864+
total_size += size;
1865+
}
1866+
return total_size;
1867+
}

src/tools.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ ssize_t send_all (int client_fd, const void *buf, ssize_t len) {
120120
if (err == WSAEWOULDBLOCK || err == WSAEINTR) {
121121
#else
122122
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
123-
#endif
123+
#endif
124124
// handle network timeout
125125
if (get_program_time() - last_update_time > NETWORK_TIMEOUT_TIME) {
126126
disconnectClient(&client_fd, -2);

0 commit comments

Comments
 (0)