diff --git a/build_registries.js b/build_registries.js index 6ae45b4..9c6beaa 100644 --- a/build_registries.js +++ b/build_registries.js @@ -416,6 +416,9 @@ ${Object.entries(itemsAndBlocks.items).map(c => `#define I_${c[0]} ${c[1]}`).joi // Biome identifiers ${biomes.map((c, i) => `#define W_${c} ${i}`).join("\n")} +// Damage type identifiers +${registries["damage_type"].map((c, i) => `#define D_${c} ${i}`).join("\n")} + #endif `; diff --git a/include/globals.h b/include/globals.h index 74fe1f0..27e3216 100644 --- a/include/globals.h +++ b/include/globals.h @@ -65,6 +65,9 @@ typedef struct { #endif int8_t yaw; int8_t pitch; + short grounded_y; + uint8_t health; + uint8_t hunger; uint8_t hotbar; uint16_t inventory_items[41]; uint16_t craft_items[9]; diff --git a/include/packets.h b/include/packets.h index ca60182..8b19753 100644 --- a/include/packets.h +++ b/include/packets.h @@ -7,9 +7,9 @@ int cs_clientInformation (int client_fd); int cs_pluginMessage (int client_fd); int cs_playerAction (int client_fd); int cs_useItemOn (int client_fd); -int cs_setPlayerPositionAndRotation (int client_fd, double *x, double *y, double *z, float *yaw, float *pitch); -int cs_setPlayerPosition (int client_fd, double *x, double *y, double *z); -int cs_setPlayerRotation(int client_fd, float *yaw, float *pitch); +int cs_setPlayerPositionAndRotation (int client_fd, double *x, double *y, double *z, float *yaw, float *pitch, uint8_t *on_ground); +int cs_setPlayerPosition (int client_fd, double *x, double *y, double *z, uint8_t *on_ground); +int cs_setPlayerRotation (int client_fd, float *yaw, float *pitch, uint8_t *on_ground); int cs_setHeldItem (int client_fd); int cs_clickContainer (int client_fd); int cs_closeContainer (int client_fd); @@ -37,6 +37,8 @@ int sc_spawnEntityPlayer (int client_fd, PlayerData player); 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); int sc_updateEntityRotation (int client_fd, int id, uint8_t yaw, uint8_t pitch); +int sc_damageEvent (int client_fd, int id, int type); +int sc_setHealth (int client_fd, uint8_t health, uint8_t food); int sc_registries(int client_fd); #endif diff --git a/src/main.c b/src/main.c index 2d4c0cf..d9c1d19 100644 --- a/src/main.c +++ b/src/main.c @@ -105,6 +105,8 @@ void handlePacket (int client_fd, int length, int packet_id) { } sc_setHeldItem(client_fd, player->hotbar); + sc_setHealth(client_fd, player->health, player->hunger); + sc_playerAbilities(client_fd, 0x01 + 0x04); // invulnerability + flight sc_updateTime(client_fd, world_time); @@ -182,11 +184,12 @@ void handlePacket (int client_fd, int length, int packet_id) { double x, y, z; float yaw, pitch; + uint8_t on_ground; // Read player position (and rotation) - if (packet_id == 0x1D) cs_setPlayerPosition(client_fd, &x, &y, &z); - else if (packet_id == 0x1F) cs_setPlayerRotation (client_fd, &yaw, &pitch); - else cs_setPlayerPositionAndRotation(client_fd, &x, &y, &z, &yaw, &pitch); + if (packet_id == 0x1D) cs_setPlayerPosition(client_fd, &x, &y, &z, &on_ground); + else if (packet_id == 0x1F) cs_setPlayerRotation (client_fd, &yaw, &pitch, &on_ground); + else cs_setPlayerPositionAndRotation(client_fd, &x, &y, &z, &yaw, &pitch, &on_ground); PlayerData *player; if (getPlayerData(client_fd, &player)) break; @@ -197,6 +200,18 @@ void handlePacket (int client_fd, int length, int packet_id) { player->pitch = pitch / 90.0f * 127.0f; } + // Handle fall damage + if (on_ground) { + int8_t damage = player->grounded_y - player->y - 3; + if (damage > 0 && getBlockAt(player->x, player->y, player->z) != B_water) { + if (damage >= player->health) player->health = 0; + else player->health -= damage; + sc_damageEvent(client_fd, client_fd, D_fall); + sc_setHealth(client_fd, player->health, player->hunger); + } + player->grounded_y = player->y; + } + // Broadcast player position to other players #ifdef SCALE_MOVEMENT_UPDATES_TO_PLAYER_COUNT // If applicable, broadcast only every client_count-th movement update diff --git a/src/packets.c b/src/packets.c index 6b96f3d..50fd999 100644 --- a/src/packets.c +++ b/src/packets.c @@ -614,7 +614,7 @@ int cs_clickContainer (int client_fd) { } // C->S Set Player Position And Rotation -int cs_setPlayerPositionAndRotation (int client_fd, double *x, double *y, double *z, float *yaw, float *pitch) { +int cs_setPlayerPositionAndRotation (int client_fd, double *x, double *y, double *z, float *yaw, float *pitch, uint8_t *on_ground) { *x = readDouble(client_fd); *y = readDouble(client_fd); @@ -623,38 +623,32 @@ int cs_setPlayerPositionAndRotation (int client_fd, double *x, double *y, double *yaw = readFloat(client_fd); *pitch = readFloat(client_fd); - // ignore flags - readByte(client_fd); + *on_ground = readByte(client_fd) & 0x01; return 0; - } // C->S Set Player Position -int cs_setPlayerPosition (int client_fd, double *x, double *y, double *z) { +int cs_setPlayerPosition (int client_fd, double *x, double *y, double *z, uint8_t *on_ground) { *x = readDouble(client_fd); *y = readDouble(client_fd); *z = readDouble(client_fd); - // ignore flags - readByte(client_fd); + *on_ground = readByte(client_fd) & 0x01; return 0; - } // C->S Set Player Rotation -int cs_setPlayerRotation (int client_fd, float *yaw, float *pitch) { +int cs_setPlayerRotation (int client_fd, float *yaw, float *pitch, uint8_t *on_ground) { *yaw = readFloat(client_fd); *pitch = readFloat(client_fd); - // ignore flags - readByte(client_fd); + *on_ground = readByte(client_fd) & 0x01; return 0; - } // C->S Set Held Item (serverbound) @@ -797,6 +791,7 @@ int sc_teleportEntity ( return 0; } +// S->C Set Head Rotation int sc_setHeadRotation (int client_fd, int id, uint8_t yaw) { // Packet length and ID @@ -810,6 +805,7 @@ int sc_setHeadRotation (int client_fd, int id, uint8_t yaw) { return 0; } +// S->C Set Head Rotation int sc_updateEntityRotation (int client_fd, int id, uint8_t yaw, uint8_t pitch) { // Packet length and ID @@ -826,6 +822,34 @@ int sc_updateEntityRotation (int client_fd, int id, uint8_t yaw, uint8_t pitch) return 0; } +// S->C Damage Event +int sc_damageEvent (int client_fd, int entity_id, int type) { + + writeVarInt(client_fd, 4 + sizeVarInt(entity_id) + sizeVarInt(type)); + writeByte(client_fd, 0x19); + + writeVarInt(client_fd, entity_id); + writeVarInt(client_fd, type); + writeByte(client_fd, 0); + writeByte(client_fd, 0); + writeByte(client_fd, false); + + return 0; +} + +// S->C Set Health +int sc_setHealth (int client_fd, uint8_t health, uint8_t food) { + + writeVarInt(client_fd, 9 + sizeVarInt(food)); + writeByte(client_fd, 0x61); + + writeFloat(client_fd, (float)health); + writeVarInt(client_fd, food); + writeFloat(client_fd, 5.0f); // saturation + + return 0; +} + // S->C Registry Data (multiple packets) and Update Tags (configuration, multiple packets) int sc_registries (int client_fd) { diff --git a/src/tools.c b/src/tools.c index 7ff678d..0504bbe 100644 --- a/src/tools.c +++ b/src/tools.c @@ -237,6 +237,8 @@ int reservePlayerData (int client_fd, uint8_t *uuid, char *name) { player_data[i].client_fd = client_fd; memcpy(player_data[i].uuid, uuid, 16); memcpy(player_data[i].name, name, 16); + player_data[i].health = 20; + player_data[i].hunger = 20; player_data[i].y = -32767; return 0; }