diff --git a/src/packets.c b/src/packets.c index 958becd..59c2ebb 100644 --- a/src/packets.c +++ b/src/packets.c @@ -315,18 +315,18 @@ int sc_keepAlive (int client_fd) { } // S->C Set Container Slot -int sc_setContainerSlot (int client_fd, int container, uint16_t slot, uint8_t count, uint16_t item) { +int sc_setContainerSlot (int client_fd, int window_id, uint16_t slot, uint8_t count, uint16_t item) { writeVarInt(client_fd, 1 + - sizeVarInt(container) + + sizeVarInt(window_id) + 1 + 2 + sizeVarInt(count) + (count > 0 ? sizeVarInt(item) + 2 : 0) ); writeByte(client_fd, 0x14); - writeVarInt(client_fd, container); + writeVarInt(client_fd, window_id); writeVarInt(client_fd, 0); writeUint16(client_fd, slot); @@ -381,12 +381,27 @@ int cs_playerAction (int client_fd) { } +// S->C Open Screen +int sc_openScreen (int client_fd, uint8_t window, const char *title, uint16_t length) { + + writeVarInt(client_fd, 1 + 2 * sizeVarInt(window) + 1 + 2 + length); + writeByte(client_fd, 0x34); + + writeVarInt(client_fd, window); + writeVarInt(client_fd, window); + + writeByte(client_fd, 8); // string nbt tag + writeUint16(client_fd, length); // string length + send(client_fd, title, length, 0); + +} + // C->S Use Item On int cs_useItemOn (int client_fd) { uint8_t hand = readByte(client_fd); - uint64_t pos = readUint64(client_fd); + int64_t pos = readInt64(client_fd); int x = pos >> 38; int y = pos << 52 >> 52; int z = pos << 26 >> 38; @@ -404,10 +419,17 @@ int cs_useItemOn (int client_fd) { int sequence = readVarInt(client_fd); + uint8_t target = getBlockAt(x, y, z); + if (target == B_crafting_table) { + sc_openScreen(client_fd, 12, "Crafting", 8); + return 0; + } + PlayerData *player; if (getPlayerData(client_fd, &player)) return 1; - uint8_t block = I_to_B[player->inventory_items[player->hotbar]]; + uint16_t item = player->inventory_items[player->hotbar]; + uint8_t block = item == 320 ? B_crafting_table : I_to_B[item]; // hack!! // if the selected item doesn't correspond to a block, exit if (block == 0) return 0; @@ -454,7 +476,8 @@ int cs_clickContainer (int client_fd) { for (int i = 0; i < changes_count; i ++) { - slot = clientSlotToServerSlot(readUint16(client_fd)); + slot = clientSlotToServerSlot(window_id, readUint16(client_fd)); + // slots outside of the inventory overflow into the crafting buffer if (slot > 40) craft = true; if (!readByte(client_fd)) { // no item? diff --git a/src/packets.h b/src/packets.h index e44d496..fe427b2 100644 --- a/src/packets.h +++ b/src/packets.h @@ -22,8 +22,9 @@ int sc_startWaitingForChunks (int client_fd); int sc_setCenterChunk (int client_fd, int x, int y); int sc_chunkDataAndUpdateLight (int client_fd, int _x, int _z); int sc_keepAlive (int client_fd); -int sc_setContainerSlot (int client_fd, int container, uint16_t slot, uint8_t count, uint16_t item); +int sc_setContainerSlot (int client_fd, int window_id, uint16_t slot, uint8_t count, uint16_t item); int sc_setHeldItem (int client_fd, uint8_t slot); +int sc_openScreen (int client_fd, uint8_t window, const char *title, uint16_t length); int sc_registries(int client_fd); #endif diff --git a/src/tools.c b/src/tools.c index 440f829..8969bc3 100644 --- a/src/tools.c +++ b/src/tools.c @@ -181,18 +181,30 @@ uint8_t serverSlotToClientSlot (uint8_t slot) { return 255; } -uint8_t clientSlotToServerSlot (uint8_t slot) { - if (slot >= 36 && slot <= 44) return slot - 36; - if (slot >= 9 && slot <= 35) return slot; - if (slot == 45) return 40; - if (slot >= 5 && slot <= 8) return 4 - (slot - 5) + 36; +uint8_t clientSlotToServerSlot (int window_id, uint8_t slot) { - // map inventory crafting slots to player data crafting grid (semi-hack) - // this abuses the fact that the buffers are adjacent in player data - if (slot == 1) return 41; - if (slot == 2) return 42; - if (slot == 3) return 44; - if (slot == 4) return 45; + if (window_id == 0) { // player inventory + + if (slot >= 36 && slot <= 44) return slot - 36; + if (slot >= 9 && slot <= 35) return slot; + if (slot == 45) return 40; + if (slot >= 5 && slot <= 8) return 4 - (slot - 5) + 36; + + // map inventory crafting slots to player data crafting grid (semi-hack) + // this abuses the fact that the buffers are adjacent in player data + if (slot == 1) return 41; + if (slot == 2) return 42; + if (slot == 3) return 44; + if (slot == 4) return 45; + + } else if (window_id == 12) { // crafting table + + // same crafting offset overflow hack as above + if (slot >= 1 && slot <= 9) return 40 + slot; + // the rest of the slots are identical, just shifted by one + if (slot >= 10 && slot <= 45) return clientSlotToServerSlot(0, slot - 1); + + } return 255; } diff --git a/src/tools.h b/src/tools.h index 5cd0d90..a60a5c3 100644 --- a/src/tools.h +++ b/src/tools.h @@ -37,7 +37,7 @@ void clearPlayerFD (int client_fd); int givePlayerItem (int client_fd, uint16_t item); uint8_t serverSlotToClientSlot (uint8_t slot); -uint8_t clientSlotToServerSlot (uint8_t slot); +uint8_t clientSlotToServerSlot (int window_id, uint8_t slot); uint8_t getBlockChange (short x, short y, short z); void makeBlockChange (short x, short y, short z, uint8_t block);