forked from EXTERNAL/bareiron
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>
This commit is contained in:
@@ -248,6 +248,19 @@ typedef struct {
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
union EntityDataValue {
|
||||
uint8_t byte;
|
||||
int pose;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t index;
|
||||
// 0 - Byte
|
||||
// 21 - Pose
|
||||
int type;
|
||||
union EntityDataValue value;
|
||||
} EntityData;
|
||||
|
||||
extern BlockChange block_changes[MAX_BLOCK_CHANGES];
|
||||
extern int block_changes_count;
|
||||
|
||||
|
@@ -48,6 +48,7 @@ int sc_acknowledgeBlockChange (int client_fd, int sequence);
|
||||
int sc_playerInfoUpdateAddPlayer (int client_fd, PlayerData player);
|
||||
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);
|
||||
int sc_spawnEntityPlayer (int client_fd, PlayerData player);
|
||||
int sc_setEntityMetadata (int client_fd, int id, EntityData *metadata, size_t length);
|
||||
int sc_entityAnimation (int client_fd, int id, uint8_t animation);
|
||||
int sc_teleportEntity (int client_fd, int id, double x, double y, double z, float yaw, float pitch);
|
||||
int sc_setHeadRotation (int client_fd, int id, uint8_t yaw);
|
||||
|
@@ -20,6 +20,8 @@ void disconnectClient (int *client_fd, int cause);
|
||||
int givePlayerItem (PlayerData *player, uint16_t item, uint8_t count);
|
||||
void spawnPlayer (PlayerData *player);
|
||||
|
||||
void broadcastPlayerMetadata (PlayerData *player);
|
||||
|
||||
uint8_t serverSlotToClientSlot (int window_id, uint8_t slot);
|
||||
uint8_t clientSlotToServerSlot (int window_id, uint8_t slot);
|
||||
|
||||
@@ -47,4 +49,9 @@ void handleServerTick (int64_t time_since_last_tick);
|
||||
|
||||
void broadcastChestUpdate (int origin_fd, uint8_t *storage_ptr, uint16_t item, uint8_t count, uint8_t slot);
|
||||
|
||||
ssize_t writeEntityData (int client_fd, EntityData *data);
|
||||
|
||||
int sizeEntityData (EntityData *data);
|
||||
int sizeEntityMetadata (EntityData *metadata, size_t length);
|
||||
|
||||
#endif
|
||||
|
@@ -764,6 +764,10 @@ int cs_setPlayerMovementFlags (int client_fd, uint8_t *on_ground) {
|
||||
|
||||
*on_ground = readByte(client_fd) & 0x01;
|
||||
|
||||
PlayerData *player;
|
||||
if (!getPlayerData(client_fd, &player))
|
||||
broadcastPlayerMetadata(player);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -910,6 +914,26 @@ int sc_spawnEntity (
|
||||
return 0;
|
||||
}
|
||||
|
||||
// S->C Set Entity Metadata
|
||||
int sc_setEntityMetadata (int client_fd, int id, EntityData *metadata, size_t length) {
|
||||
int entity_metadata_size = sizeEntityMetadata(metadata, length);
|
||||
if (entity_metadata_size == -1) return 1;
|
||||
|
||||
writeVarInt(client_fd, 2 + sizeVarInt(id) + entity_metadata_size);
|
||||
writeByte(client_fd, 0x5C);
|
||||
|
||||
writeVarInt(client_fd, id); // Entity ID
|
||||
|
||||
for (size_t i = 0; i < length; i ++) {
|
||||
EntityData *data = &metadata[i];
|
||||
writeEntityData(client_fd, data);
|
||||
}
|
||||
|
||||
writeByte(client_fd, 0xFF); // End
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// S->C Spawn Entity (from PlayerData)
|
||||
int sc_spawnEntityPlayer (int client_fd, PlayerData player) {
|
||||
return sc_spawnEntity(
|
||||
@@ -1198,6 +1222,8 @@ int cs_playerInput (int client_fd) {
|
||||
if (flags & 0x20) player->flags |= 0x04;
|
||||
else player->flags &= ~0x04;
|
||||
|
||||
broadcastPlayerMetadata(player);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1215,6 +1241,8 @@ int cs_playerCommand (int client_fd) {
|
||||
if (action == 1) player->flags |= 0x08;
|
||||
else if (action == 2) player->flags &= ~0x08;
|
||||
|
||||
broadcastPlayerMetadata(player);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -368,6 +368,43 @@ void spawnPlayer (PlayerData *player) {
|
||||
|
||||
}
|
||||
|
||||
// Broadcasts a player's entity metadata (sneak/sprint state) to other players
|
||||
void broadcastPlayerMetadata (PlayerData *player) {
|
||||
uint8_t sneaking = (player->flags & 0x04) != 0;
|
||||
uint8_t sprinting = (player->flags & 0x08) != 0;
|
||||
|
||||
uint8_t player_bit_mask = 0;
|
||||
if (sneaking) player_bit_mask |= 0x02;
|
||||
if (sprinting) player_bit_mask |= 0x08;
|
||||
|
||||
int pose = 0;
|
||||
if (sneaking) pose = 5;
|
||||
|
||||
EntityData metadata[] = {
|
||||
{
|
||||
0, // Index (Bit Mask)
|
||||
0, // Type (Byte)
|
||||
player_bit_mask, // Value
|
||||
},
|
||||
{
|
||||
6, // Index (Pose),
|
||||
21, // Type (Pose),
|
||||
pose, // Value (Standing)
|
||||
}
|
||||
};
|
||||
|
||||
for (int i = 0; i < MAX_PLAYERS; i ++) {
|
||||
PlayerData* other_player = &player_data[i];
|
||||
int client_fd = other_player->client_fd;
|
||||
|
||||
if (client_fd == -1) continue;
|
||||
if (client_fd == player->client_fd) continue;
|
||||
if (other_player->flags & 0x20) continue;
|
||||
|
||||
sc_setEntityMetadata(client_fd, player->client_fd, metadata, 2);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t getBlockChange (short x, uint8_t y, short z) {
|
||||
for (int i = 0; i < block_changes_count; i ++) {
|
||||
if (block_changes[i].block == 0xFF) continue;
|
||||
@@ -1784,3 +1821,47 @@ void broadcastChestUpdate (int origin_fd, uint8_t *storage_ptr, uint16_t item, u
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
ssize_t writeEntityData (int client_fd, EntityData *data) {
|
||||
writeByte(client_fd, data->index);
|
||||
writeVarInt(client_fd, data->type);
|
||||
|
||||
switch (data->type) {
|
||||
case 0: // Byte
|
||||
return writeByte(client_fd, data->value.byte);
|
||||
case 21: // Pose
|
||||
writeVarInt(client_fd, data->value.pose);
|
||||
return 0;
|
||||
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the networked size of an EntityData entry
|
||||
int sizeEntityData (EntityData *data) {
|
||||
int value_size;
|
||||
|
||||
switch (data->type) {
|
||||
case 0: // Byte
|
||||
value_size = 1;
|
||||
break;
|
||||
case 21: // Pose
|
||||
value_size = sizeVarInt(data->value.pose);
|
||||
break;
|
||||
|
||||
default: return -1;
|
||||
}
|
||||
|
||||
return 1 + sizeVarInt(data->type) + value_size;
|
||||
}
|
||||
|
||||
// Returns the networked size of an array of EntityData entries
|
||||
int sizeEntityMetadata (EntityData *metadata, size_t length) {
|
||||
int total_size = 0;
|
||||
for (size_t i = 0; i < length; i ++) {
|
||||
int size = sizeEntityData(&metadata[i]);
|
||||
if (size == -1) return -1;
|
||||
total_size += size;
|
||||
}
|
||||
return total_size;
|
||||
}
|
||||
|
@@ -120,7 +120,7 @@ ssize_t send_all (int client_fd, const void *buf, ssize_t len) {
|
||||
if (err == WSAEWOULDBLOCK || err == WSAEINTR) {
|
||||
#else
|
||||
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
#endif
|
||||
#endif
|
||||
// handle network timeout
|
||||
if (get_program_time() - last_update_time > NETWORK_TIMEOUT_TIME) {
|
||||
disconnectClient(&client_fd, -2);
|
||||
|
Reference in New Issue
Block a user