commit - 244c98552f79a6e0810b5e50b3df391c3eec3807
commit + ba86dfd927b5e2432be797e12095642dc4091fe1
blob - c5942b9ea0c23362acaca9e0cc6e065a5d6fdc4b
blob + 4f07a3ef3f1b6dfc6da80ebc11996b99bbe90669
--- include/globals.h
+++ include/globals.h
uint8_t y;
short z;
// Lower 5 bits: health
- // Middle 1 bit: reserved for future use
+ // Middle 1 bit: sheep sheared, unused for other mobs
// Upper 2 bits: panic timer
uint8_t data;
} MobData;
blob - 62d09f06244a60ebd35fe543924216f2eb7fb58d
blob + f3aa33133e0b13d3946824c2a4ebe4271a82ca63
--- include/procedures.h
+++ include/procedures.h
void spawnPlayer (PlayerData *player);
void broadcastPlayerMetadata (PlayerData *player);
+void broadcastMobMetadata (int client_fd, int entity_id);
uint8_t serverSlotToClientSlot (int window_id, uint8_t slot);
uint8_t clientSlotToServerSlot (int window_id, uint8_t slot);
void checkFluidUpdate (short x, uint8_t y, short z, uint8_t block);
void spawnMob (uint8_t type, short x, uint8_t y, short z, uint8_t health);
+void interactEntity (int entity_id, int interactor_id);
void hurtEntity (int entity_id, int attacker_id, uint8_t damage_type, uint8_t damage);
void handleServerTick (int64_t time_since_last_tick);
blob - dd065d9e1204851ed64c77cb04111a56295c0615
blob + 1d8bddbc91a0d2ff70831ce91a13c193ba40743c
--- src/main.c
+++ src/main.c
mob_data[i].type, mob_data[i].x, mob_data[i].y, mob_data[i].z,
0, 0
);
+ broadcastMobMetadata(client_fd, -2 - i);
}
}
blob - 8b67b5f0f1717df494922a2071a74a58629b77e0
blob + 5cec9d5f195917440195a5cd8a89e4ab4da15f79
--- src/packets.c
+++ src/packets.c
// Ignore sneaking flag
recv_all(client_fd, recv_buffer, 1, false);
- if (type == 1) {
+ if (type == 0) { // Interact
+ interactEntity(entity_id, client_fd);
+ } else if (type == 1) { // Attack
hurtEntity(entity_id, client_fd, D_generic, 1);
}
blob - 7ba75da40d5d01df149e3fe5caa2ec4459485a32
blob + 4048bba6d0431bab6dc4aa1f20f317ff3e957ab6
--- src/procedures.c
+++ src/procedures.c
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;
+ uint8_t entity_bit_mask = 0;
+ if (sneaking) entity_bit_mask |= 0x02;
+ if (sprinting) entity_bit_mask |= 0x08;
int pose = 0;
if (sneaking) pose = 5;
EntityData metadata[] = {
{
- 0, // Index (Bit Mask)
+ 0, // Index (Entity Bit Mask)
0, // Type (Byte)
- player_bit_mask, // Value
+ entity_bit_mask, // Value
},
{
6, // Index (Pose),
}
}
+// Sends a mob's entity metadata to the given player.
+// If client_fd is -1, broadcasts to all player
+void broadcastMobMetadata (int client_fd, int entity_id) {
+
+ MobData *mob = &mob_data[-entity_id - 2];
+
+ EntityData *metadata;
+ size_t length;
+
+ switch (mob->type) {
+ case 106: // Sheep
+ if (!((mob->data >> 5) & 1)) // Don't send metadata if sheep isn't sheared
+ return;
+
+ metadata = malloc(sizeof *metadata);
+ metadata[0] = (EntityData){
+ 17, // Index (Sheep Bit Mask),
+ 0, // Type (Byte),
+ (uint8_t)0x10, // Value
+ };
+ length = 1;
+
+ break;
+
+ default: return;
+ }
+
+ if (client_fd == -1) {
+ for (int i = 0; i < MAX_PLAYERS; i ++) {
+ PlayerData* player = &player_data[i];
+ client_fd = player->client_fd;
+
+ if (client_fd == -1) continue;
+ if (player->flags & 0x20) continue;
+
+ sc_setEntityMetadata(client_fd, entity_id, metadata, length);
+ }
+ } else {
+ sc_setEntityMetadata(client_fd, entity_id, metadata, length);
+ }
+
+ free(metadata);
+}
+
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;
);
}
+ // Freshly spawned mobs currently don't need metadata updates.
+ // If this changes, uncomment this line.
+ // broadcastMobMetadata(-1, i);
+
break;
}
}
+void interactEntity (int entity_id, int interactor_id) {
+
+ PlayerData *player;
+ if (getPlayerData(interactor_id, &player)) return;
+
+ MobData *mob = &mob_data[-entity_id - 2];
+
+ switch (mob->type) {
+ case 106: // Sheep
+ if (player->inventory_items[player->hotbar] != I_shears)
+ return;
+
+ if ((mob->data >> 5) & 1) // Check if sheep has already been sheared
+ return;
+
+ mob->data |= 1 << 5; // Set sheared to true
+
+ bumpToolDurability(player);
+
+ #ifdef ENABLE_PICKUP_ANIMATION
+ playPickupAnimation(player, I_white_wool, mob->x, mob->y, mob->z);
+ #endif
+
+ uint8_t item_count = 1 + (fast_rand() & 1); // 1-2
+ givePlayerItem(player, I_white_wool, item_count);
+
+ for (int i = 0; i < MAX_PLAYERS; i ++) {
+ PlayerData* player = &player_data[i];
+ int client_fd = player->client_fd;
+
+ if (client_fd == -1) continue;
+ if (player->flags & 0x20) continue;
+
+ sc_entityAnimation(client_fd, interactor_id, 0);
+ }
+
+ broadcastMobMetadata(-1, entity_id);
+
+ break;
+ }
+}
+
void hurtEntity (int entity_id, int attacker_id, uint8_t damage_type, uint8_t damage) {
if (attacker_id > 0) { // Attacker is a player