From 5170b968b8285ff73c8e937e5e45d8d61d5b8d0e Mon Sep 17 00:00:00 2001 From: Alezito2008 Date: Sun, 8 Mar 2026 15:10:49 -0300 Subject: [PATCH] Implement inventory swapping --- Minecraft.Client/Minecraft.cpp | 67 +++++++++++++++++++++++++++++++--- Minecraft.World/Inventory.h | 2 - 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/Minecraft.Client/Minecraft.cpp b/Minecraft.Client/Minecraft.cpp index fe283d317..f41dbf566 100644 --- a/Minecraft.Client/Minecraft.cpp +++ b/Minecraft.Client/Minecraft.cpp @@ -1479,10 +1479,15 @@ void Minecraft::run_middle() if(g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_RIGHT)) localplayers[i]->ullButtonsPressed|=1LL<hasInfiniteItems() && hitResult && hitResult->type == HitResult::TILE) + if (g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_MIDDLE) && hitResult && hitResult->type == HitResult::TILE) { + auto inventory = localplayers[i]->inventory; + auto inventoryMenu = localplayers[i]->inventoryMenu; + bool isInCreative = gameMode->hasInfiniteItems(); + int x = hitResult->x, y = hitResult->y, z = hitResult->z; + int containerId = inventoryMenu->containerId; int tileId = level->getTile(x, y, z); if (tileId > 0 && tileId < Tile::TILE_NUM_COUNT) @@ -1492,13 +1497,63 @@ void Minecraft::run_middle() int clonedTileId = tile->cloneTileId(level, x, y, z); int clonedTileData = tile->cloneTileData(level, x, y, z); - localplayers[i]->inventory->grabTexture(clonedTileId, clonedTileData, true, true); + int itemSlot = inventory->getSlot(clonedTileId, clonedTileData); + int firstEmpty = inventory->getFreeSlot(); - shared_ptr selectedItem = localplayers[i]->inventory->getSelected(); - if (gameMode && selectedItem) + if (itemSlot >= 0) { - // Hotbar starts at slot 36 - gameMode->handleCreativeModeItemAdd(selectedItem, 36 + player->inventory->selected); + // Item is already in hotbar + if (itemSlot < 9) + { + inventory->selected = itemSlot; + } + // There are free slots in the hotbar + else if (firstEmpty >= 0 && firstEmpty < 9) + { + inventory->selected = firstEmpty; + // Use quick move the item + gameMode->handleInventoryMouseClick( + containerId, + itemSlot, + AbstractContainerMenu::CLICK_QUICK_MOVE, + true, + localplayers[i] + ); + } + // Swap with item in inventory + else { + int currentHotbarSlot = inventory->selected; + short changeUid = inventoryMenu->backup(inventory); + + // Perform client side swap and sync with server using CLICK_SWAP to avoid ghost blocks + shared_ptr clicked = inventoryMenu->clicked( + itemSlot, + currentHotbarSlot, + AbstractContainerMenu::CLICK_SWAP, + localplayers[i] + ); + + localplayers[i]->connection->send(make_shared( + containerId, + itemSlot, + currentHotbarSlot, + AbstractContainerMenu::CLICK_SWAP, + clicked, + changeUid + )); + } + } + else if (isInCreative) + { + localplayers[i]->inventory->grabTexture(clonedTileId, clonedTileData, true, true); + + shared_ptr selectedItem = localplayers[i]->inventory->getSelected(); + if (gameMode && selectedItem) + { + // Hotbar starts at slot 36 + // Sync new item instance with the server in creative mode + gameMode->handleCreativeModeItemAdd(selectedItem, 36 + localplayers[i]->inventory->selected); + } } } } diff --git a/Minecraft.World/Inventory.h b/Minecraft.World/Inventory.h index 539b9f493..95db50516 100644 --- a/Minecraft.World/Inventory.h +++ b/Minecraft.World/Inventory.h @@ -39,13 +39,11 @@ public: bool IsHeldItem(); static int getSelectionSize(); -private: int getSlot(int tileId); int getSlot(int tileId, int data); int getSlotWithRemainingSpace(shared_ptr item); -public: int getFreeSlot(); void grabTexture(int id, int data, bool checkData, bool mayReplace); void swapPaint(int wheel);