Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implement inventory logic for dropping items #330

Merged
merged 1 commit into from
Feb 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions src/callbacks.cob
Original file line number Diff line number Diff line change
Expand Up @@ -367,3 +367,45 @@ PROCEDURE DIVISION USING LK-WINDOW-TYPE LK-CB-PTR.
GOBACK.

END PROGRAM GetCallback-WindowSetSlot.

*> --- SetCallback-WindowDrop ---
IDENTIFICATION DIVISION.
PROGRAM-ID. SetCallback-WindowDrop.

DATA DIVISION.
WORKING-STORAGE SECTION.
COPY DD-CALLBACKS.
LINKAGE SECTION.
01 LK-WINDOW-TYPE BINARY-LONG.
01 LK-CB-PTR PROGRAM-POINTER.

PROCEDURE DIVISION USING LK-WINDOW-TYPE LK-CB-PTR.
IF LK-WINDOW-TYPE < 0
MOVE LK-CB-PTR TO CB-PTR-DROP-PLAYER
GOBACK
END-IF
MOVE LK-CB-PTR TO CB-PTR-DROP(LK-WINDOW-TYPE + 1)
GOBACK.

END PROGRAM SetCallback-WindowDrop.

*> --- GetCallback-WindowDrop ---
IDENTIFICATION DIVISION.
PROGRAM-ID. GetCallback-WindowDrop.

DATA DIVISION.
WORKING-STORAGE SECTION.
COPY DD-CALLBACKS.
LINKAGE SECTION.
01 LK-WINDOW-TYPE BINARY-LONG.
01 LK-CB-PTR PROGRAM-POINTER.

PROCEDURE DIVISION USING LK-WINDOW-TYPE LK-CB-PTR.
IF LK-WINDOW-TYPE < 0
MOVE CB-PTR-DROP-PLAYER TO LK-CB-PTR
GOBACK
END-IF
MOVE CB-PTR-DROP(LK-WINDOW-TYPE + 1) TO LK-CB-PTR
GOBACK.

END PROGRAM GetCallback-WindowDrop.
8 changes: 8 additions & 0 deletions src/copybooks/DD-CALLBACK-WINDOW-DROP.cpy
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
*> --- Copybook: callback parameters for dropping the item in a window-specific slot ---

01 LK-PLAYER BINARY-LONG.
01 LK-INDEX BINARY-SHORT.
*> whether to drop the entire stack, vs. just one item
01 LK-STACK BINARY-CHAR UNSIGNED.
*> whether dropping from the slot affected other slots (e.g. crafting output)
01 LK-SYNC-REQUIRED BINARY-CHAR UNSIGNED.
2 changes: 2 additions & 0 deletions src/copybooks/DD-CALLBACKS.cpy
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@
03 CB-PTR-SYNC USAGE PROGRAM-POINTER.
03 CB-PTR-CLOSE USAGE PROGRAM-POINTER.
03 CB-PTR-SET-SLOT USAGE PROGRAM-POINTER.
03 CB-PTR-DROP USAGE PROGRAM-POINTER.
02 PLAYER-INVENTORY-CALLBACKS.
03 CB-PTR-SYNC-PLAYER USAGE PROGRAM-POINTER.
03 CB-PTR-CLOSE-PLAYER USAGE PROGRAM-POINTER.
03 CB-PTR-SET-SLOT-PLAYER USAGE PROGRAM-POINTER.
03 CB-PTR-DROP-PLAYER USAGE PROGRAM-POINTER.
79 changes: 77 additions & 2 deletions src/inventory/window-crafting.cob
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ WORKING-STORAGE SECTION.
01 SYNC-PTR PROGRAM-POINTER.
01 CLOSE-PTR PROGRAM-POINTER.
01 SET-SLOT-PTR PROGRAM-POINTER.
01 DROP-PTR PROGRAM-POINTER.

PROCEDURE DIVISION.
CALL "Registries-Get-EntryId" USING "minecraft:menu" "minecraft:crafting" WINDOW-TYPE
Expand All @@ -19,9 +20,12 @@ PROCEDURE DIVISION.
SET SYNC-PTR TO ENTRY "Callback-Sync"
SET CLOSE-PTR TO ENTRY "Callback-Close"
SET SET-SLOT-PTR TO ENTRY "Callback-SetSlot"
SET DROP-PTR TO ENTRY "Callback-Drop"

CALL "SetCallback-WindowSync" USING WINDOW-TYPE SYNC-PTR
CALL "SetCallback-WindowClose" USING WINDOW-TYPE CLOSE-PTR
CALL "SetCallback-WindowSetSlot" USING WINDOW-TYPE SET-SLOT-PTR
CALL "SetCallback-WindowDrop" USING WINDOW-TYPE DROP-PTR

GOBACK.

Expand Down Expand Up @@ -74,15 +78,15 @@ PROCEDURE DIVISION.
*> stash the mouse item
CALL "Inventory-StoreItem" USING PLAYER-INVENTORY(LK-PLAYER) PLAYER-MOUSE-ITEM(LK-PLAYER)
IF PLAYER-MOUSE-SLOT-COUNT(LK-PLAYER) > 0
*> TODO drop item
CALL "World-DropItem" USING PLAYER-POSITION(LK-PLAYER) PLAYER-MOUSE-ITEM(LK-PLAYER)
MOVE 0 TO PLAYER-MOUSE-SLOT-COUNT(LK-PLAYER)
END-IF

*> stash crafting input
PERFORM VARYING SLOT FROM 1 BY 1 UNTIL SLOT > 9
CALL "Inventory-StoreItem" USING PLAYER-INVENTORY(LK-PLAYER) PLAYER-WINDOW-SLOT(LK-PLAYER, SLOT + 1)
IF PLAYER-WINDOW-SLOT-COUNT(LK-PLAYER, SLOT + 1) > 0
*> TODO drop item
CALL "World-DropItem" USING PLAYER-POSITION(LK-PLAYER) PLAYER-WINDOW-SLOT(LK-PLAYER, SLOT + 1)
MOVE 0 TO PLAYER-WINDOW-SLOT-COUNT(LK-PLAYER, SLOT + 1)
END-IF
END-PERFORM
Expand Down Expand Up @@ -131,4 +135,75 @@ PROCEDURE DIVISION.

END PROGRAM Callback-SetSlot.

*> --- Callback-Drop ---
IDENTIFICATION DIVISION.
PROGRAM-ID. Callback-Drop.

DATA DIVISION.
WORKING-STORAGE SECTION.
COPY DD-PLAYERS.
01 DROP-SLOT.
COPY DD-INVENTORY-SLOT REPLACING LEADING ==PREFIX== BY ==DROP==.
01 SLOT-INDEX BINARY-LONG UNSIGNED.
*> TODO deduplicate with Callback-SetSlot
01 WINDOW-INVENTORY-LENGTH BINARY-LONG UNSIGNED VALUE 46.
01 CRAFTING-GRID-SIZE BINARY-LONG UNSIGNED VALUE 9.
01 CRAFTING-GRID-START BINARY-LONG UNSIGNED VALUE 1.
01 CRAFTING-OUTPUT-SLOT BINARY-LONG UNSIGNED VALUE 0.
LINKAGE SECTION.
COPY DD-CALLBACK-WINDOW-DROP.

PROCEDURE DIVISION USING LK-PLAYER LK-INDEX LK-STACK LK-SYNC-REQUIRED.
EVALUATE LK-INDEX
WHEN 0 *> crafting output
*> TODO support dropping entire crafting output (LK-STACK = 1)
MOVE PLAYER-WINDOW-SLOT(LK-PLAYER, LK-INDEX + 1) TO DROP-SLOT
IF DROP-SLOT-COUNT > 0
*> crafting output becomes empty, input is reduced by 1 each
MOVE 0 TO PLAYER-WINDOW-SLOT-COUNT(LK-PLAYER, LK-INDEX + 1)
PERFORM VARYING SLOT-INDEX FROM 1 BY 1 UNTIL SLOT-INDEX > 9
IF PLAYER-WINDOW-SLOT-COUNT(LK-PLAYER, SLOT-INDEX + 1) > 0
SUBTRACT 1 FROM PLAYER-WINDOW-SLOT-COUNT(LK-PLAYER, SLOT-INDEX + 1)
END-IF
END-PERFORM
CALL "World-DropItem" USING PLAYER-POSITION(LK-PLAYER) DROP-SLOT
PERFORM UpdateCrafting
END-IF

WHEN 1 THRU 9 *> crafting input
MOVE PLAYER-WINDOW-SLOT(LK-PLAYER, LK-INDEX + 1) TO DROP-SLOT
IF DROP-SLOT-COUNT > 0
IF LK-STACK = 0
MOVE 1 TO DROP-SLOT-COUNT
END-IF
SUBTRACT DROP-SLOT-COUNT FROM PLAYER-WINDOW-SLOT-COUNT(LK-PLAYER, LK-INDEX + 1)
CALL "World-DropItem" USING PLAYER-POSITION(LK-PLAYER) DROP-SLOT
PERFORM UpdateCrafting
END-IF

WHEN 10 THRU 45 *> player inventory
MOVE PLAYER-INVENTORY-SLOT(LK-PLAYER, LK-INDEX) TO DROP-SLOT
IF DROP-SLOT-COUNT > 0
IF LK-STACK = 0
MOVE 1 TO DROP-SLOT-COUNT
END-IF
SUBTRACT DROP-SLOT-COUNT FROM PLAYER-INVENTORY-SLOT-COUNT(LK-PLAYER, LK-INDEX)
CALL "World-DropItem" USING PLAYER-POSITION(LK-PLAYER) DROP-SLOT
END-IF

WHEN OTHER
DISPLAY "Invalid slot number: " LK-INDEX
END-EVALUATE

GOBACK.

UpdateCrafting.
CALL "Inventory-UpdateCraftingOutput" USING WINDOW-INVENTORY-LENGTH PLAYER-WINDOW-SLOTS(LK-PLAYER)
CRAFTING-GRID-SIZE CRAFTING-GRID-START CRAFTING-OUTPUT-SLOT
*> TODO only set this when the output slot is actually changed
MOVE 1 TO LK-SYNC-REQUIRED
.

END PROGRAM Callback-Drop.

END PROGRAM RegisterWindow-Crafting.
81 changes: 79 additions & 2 deletions src/inventory/window-player.cob
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,20 @@ WORKING-STORAGE SECTION.
01 SYNC-PTR PROGRAM-POINTER.
01 CLOSE-PTR PROGRAM-POINTER.
01 SET-SLOT-PTR PROGRAM-POINTER.
01 DROP-PTR PROGRAM-POINTER.

PROCEDURE DIVISION.

SET SYNC-PTR TO ENTRY "Callback-Sync"
SET CLOSE-PTR TO ENTRY "Callback-Close"
SET SET-SLOT-PTR TO ENTRY "Callback-SetSlot"
SET DROP-PTR TO ENTRY "Callback-Drop"

CALL "SetCallback-WindowSync" USING WINDOW-TYPE SYNC-PTR
CALL "SetCallback-WindowClose" USING WINDOW-TYPE CLOSE-PTR
CALL "SetCallback-WindowSetSlot" USING WINDOW-TYPE SET-SLOT-PTR
CALL "SetCallback-WindowDrop" USING WINDOW-TYPE DROP-PTR

GOBACK.

*> --- Callback-Sync ---
Expand Down Expand Up @@ -67,15 +73,15 @@ PROCEDURE DIVISION.
*> stash the mouse item
CALL "Inventory-StoreItem" USING PLAYER-INVENTORY(LK-PLAYER) PLAYER-MOUSE-ITEM(LK-PLAYER)
IF PLAYER-MOUSE-SLOT-COUNT(LK-PLAYER) > 0
*> TODO drop item
CALL "World-DropItem" USING PLAYER-POSITION(LK-PLAYER) PLAYER-MOUSE-ITEM(LK-PLAYER)
MOVE 0 TO PLAYER-MOUSE-SLOT-COUNT(LK-PLAYER)
END-IF

*> stash crafting input
PERFORM VARYING SLOT FROM 1 BY 1 UNTIL SLOT > 4
CALL "Inventory-StoreItem" USING PLAYER-INVENTORY(LK-PLAYER) PLAYER-INVENTORY-SLOT(LK-PLAYER, SLOT + 1)
IF PLAYER-INVENTORY-SLOT-COUNT(LK-PLAYER, SLOT + 1) > 0
*> TODO drop item
CALL "World-DropItem" USING PLAYER-POSITION(LK-PLAYER) PLAYER-INVENTORY-SLOT(LK-PLAYER, SLOT + 1)
MOVE 0 TO PLAYER-INVENTORY-SLOT-COUNT(LK-PLAYER, SLOT + 1)
END-IF
END-PERFORM
Expand Down Expand Up @@ -127,4 +133,75 @@ PROCEDURE DIVISION.

END PROGRAM Callback-SetSlot.

*> --- Callback-Drop ---
IDENTIFICATION DIVISION.
PROGRAM-ID. Callback-Drop.

DATA DIVISION.
WORKING-STORAGE SECTION.
COPY DD-PLAYERS.
01 DROP-SLOT.
COPY DD-INVENTORY-SLOT REPLACING LEADING ==PREFIX== BY ==DROP==.
01 SLOT-INDEX BINARY-LONG UNSIGNED.
*> TODO deduplicate with Callback-SetSlot
01 WINDOW-INVENTORY-LENGTH BINARY-LONG UNSIGNED VALUE 46.
01 CRAFTING-GRID-SIZE BINARY-LONG UNSIGNED VALUE 4.
01 CRAFTING-GRID-START BINARY-LONG UNSIGNED VALUE 1.
01 CRAFTING-OUTPUT-SLOT BINARY-LONG UNSIGNED VALUE 0.
LINKAGE SECTION.
COPY DD-CALLBACK-WINDOW-DROP.

PROCEDURE DIVISION USING LK-PLAYER LK-INDEX LK-STACK LK-SYNC-REQUIRED.
EVALUATE LK-INDEX
WHEN 0 *> crafting output
*> TODO support dropping entire crafting output (LK-STACK = 1)
MOVE PLAYER-INVENTORY-SLOT(LK-PLAYER, LK-INDEX + 1) TO DROP-SLOT
IF DROP-SLOT-COUNT > 0
*> crafting output becomes empty, input is reduced by 1 each
MOVE 0 TO PLAYER-INVENTORY-SLOT-COUNT(LK-PLAYER, LK-INDEX + 1)
PERFORM VARYING SLOT-INDEX FROM 1 BY 1 UNTIL SLOT-INDEX > 4
IF PLAYER-INVENTORY-SLOT-COUNT(LK-PLAYER, SLOT-INDEX + 1) > 0
SUBTRACT 1 FROM PLAYER-INVENTORY-SLOT-COUNT(LK-PLAYER, SLOT-INDEX + 1)
END-IF
END-PERFORM
CALL "World-DropItem" USING PLAYER-POSITION(LK-PLAYER) DROP-SLOT
PERFORM UpdateCrafting
END-IF

WHEN 1 THRU 4 *> crafting input
MOVE PLAYER-INVENTORY-SLOT(LK-PLAYER, LK-INDEX + 1) TO DROP-SLOT
IF DROP-SLOT-COUNT > 0
IF LK-STACK = 0
MOVE 1 TO DROP-SLOT-COUNT
END-IF
SUBTRACT DROP-SLOT-COUNT FROM PLAYER-INVENTORY-SLOT-COUNT(LK-PLAYER, LK-INDEX + 1)
CALL "World-DropItem" USING PLAYER-POSITION(LK-PLAYER) DROP-SLOT
PERFORM UpdateCrafting
END-IF

WHEN 5 THRU 45 *> armor, inventory, offhand
MOVE PLAYER-INVENTORY-SLOT(LK-PLAYER, LK-INDEX + 1) TO DROP-SLOT
IF DROP-SLOT-COUNT > 0
IF LK-STACK = 0
MOVE 1 TO DROP-SLOT-COUNT
END-IF
SUBTRACT DROP-SLOT-COUNT FROM PLAYER-INVENTORY-SLOT-COUNT(LK-PLAYER, LK-INDEX + 1)
CALL "World-DropItem" USING PLAYER-POSITION(LK-PLAYER) DROP-SLOT
END-IF

WHEN OTHER
DISPLAY "Invalid slot number: " LK-INDEX
END-EVALUATE

GOBACK.

UpdateCrafting.
CALL "Inventory-UpdateCraftingOutput" USING WINDOW-INVENTORY-LENGTH PLAYER-WINDOW-SLOTS(LK-PLAYER)
CRAFTING-GRID-SIZE CRAFTING-GRID-START CRAFTING-OUTPUT-SLOT
*> TODO only set this when the output slot is actually changed
MOVE 1 TO LK-SYNC-REQUIRED
.

END PROGRAM Callback-Drop.

END PROGRAM RegisterWindow-Player.
30 changes: 23 additions & 7 deletions src/packets/serverbound/play/container-click.cob
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ WORKING-STORAGE SECTION.
01 STATE-ID BINARY-LONG.
01 SYNC-PTR PROGRAM-POINTER.
01 SET-SLOT-PTR PROGRAM-POINTER.
01 DROP-PTR PROGRAM-POINTER.
01 SLOT-SYNC-REQUIRED BINARY-CHAR UNSIGNED.
01 SYNC-REQUIRED BINARY-CHAR UNSIGNED.
01 SLOT BINARY-SHORT.
Expand Down Expand Up @@ -49,7 +50,8 @@ PROCEDURE DIVISION USING LK-CLIENT LK-BUFFER LK-OFFSET.

CALL "GetCallback-WindowSync" USING PLAYER-WINDOW-TYPE(PLAYER-ID) SYNC-PTR
CALL "GetCallback-WindowSetSlot" USING PLAYER-WINDOW-TYPE(PLAYER-ID) SET-SLOT-PTR
IF SYNC-PTR = NULL OR SET-SLOT-PTR = NULL
CALL "GetCallback-WindowDrop" USING PLAYER-WINDOW-TYPE(PLAYER-ID) DROP-PTR
IF SYNC-PTR = NULL OR SET-SLOT-PTR = NULL OR DROP-PTR = NULL
DISPLAY "RecvPacket-ContainerClick: Unable to handle window type " PLAYER-WINDOW-TYPE(PLAYER-ID)
PERFORM AbortEarly
END-IF
Expand All @@ -60,18 +62,32 @@ PROCEDURE DIVISION USING LK-CLIENT LK-BUFFER LK-OFFSET.
PERFORM AbortEarly
END-IF

*> TODO support dropping items
IF (MODE-ENUM = 0 AND SLOT = -999) OR (MODE-ENUM = 4)
CALL SYNC-PTR USING PLAYER-ID
PERFORM AbortEarly
END-IF

*> TODO handle offhand swap key (F) in containers
If WINDOW-ID > 0 AND MODE-ENUM = 2 AND BUTTON = 40
CALL "Inventory-SyncPlayerInventory" USING PLAYER-ID
PERFORM AbortEarly
END-IF

IF MODE-ENUM = 0 AND SLOT = -999 AND PLAYER-MOUSE-SLOT-COUNT(PLAYER-ID) > 0
*> click outside inventory; button 0: drop stack, button 1: drop single item
MOVE PLAYER-MOUSE-ITEM(PLAYER-ID) TO CLIENT-SLOT
IF BUTTON = 0
MOVE 0 TO PLAYER-MOUSE-SLOT-COUNT(PLAYER-ID)
ELSE
MOVE 1 TO CLIENT-SLOT-COUNT
SUBTRACT 1 FROM PLAYER-MOUSE-SLOT-COUNT(PLAYER-ID)
END-IF
CALL "World-DropItem" USING PLAYER-POSITION(PLAYER-ID) CLIENT-SLOT
END-IF

IF MODE-ENUM = 4
*> drop specific slot
IF SLOT = -999
PERFORM AbortEarly
END-IF
CALL DROP-PTR USING PLAYER-ID SLOT BUTTON SYNC-REQUIRED
END-IF

*> TODO implement painting properly
*> For now we ignore all but the end event, assuming the client will send the changed slots with the end event.
IF MODE-ENUM = 5 AND NOT (BUTTON = 2 OR 6 OR 10)
Expand Down
26 changes: 26 additions & 0 deletions src/packets/serverbound/play/player-action.cob
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ WORKING-STORAGE SECTION.
01 BLOCK-HARDNESS FLOAT-SHORT.
01 CALLBACK-PTR PROGRAM-POINTER.
01 OTHER-CLIENT BINARY-LONG UNSIGNED.
01 SLOT-INDEX BINARY-LONG UNSIGNED.
01 DROP-SLOT.
COPY DD-INVENTORY-SLOT REPLACING LEADING ==PREFIX== BY ==DROP==.
LINKAGE SECTION.
01 LK-CLIENT BINARY-LONG UNSIGNED.
01 LK-BUFFER PIC X ANY LENGTH.
Expand All @@ -45,6 +48,10 @@ PROCEDURE DIVISION USING LK-CLIENT LK-BUFFER LK-OFFSET.
PERFORM CancelledDigging
WHEN ACTION-ENUM = 2
PERFORM FinishedDigging
WHEN ACTION-ENUM = 3
PERFORM DropItemStack
WHEN ACTION-ENUM = 4
PERFORM DropItem
WHEN OTHER
*> TODO The following is a workaround to reset the player's inventory until we support all actions fully
CALL "Inventory-SyncPlayerInventory" USING PLAYER-ID
Expand Down Expand Up @@ -132,4 +139,23 @@ ResetBlockBreaking.
END-PERFORM
.

DropItemStack.
COMPUTE SLOT-INDEX = 36 + PLAYER-HOTBAR(PLAYER-ID)
MOVE PLAYER-INVENTORY-SLOT(PLAYER-ID, SLOT-INDEX + 1) TO DROP-SLOT
IF DROP-SLOT-COUNT > 0
MOVE 0 TO PLAYER-INVENTORY-SLOT-COUNT(PLAYER-ID, SLOT-INDEX + 1)
CALL "World-DropItem" USING PLAYER-POSITION(PLAYER-ID) DROP-SLOT
END-IF
.

DropItem.
COMPUTE SLOT-INDEX = 36 + PLAYER-HOTBAR(PLAYER-ID)
MOVE PLAYER-INVENTORY-SLOT(PLAYER-ID, SLOT-INDEX + 1) TO DROP-SLOT
IF DROP-SLOT-COUNT > 0
MOVE 1 TO DROP-SLOT-COUNT
SUBTRACT 1 FROM PLAYER-INVENTORY-SLOT-COUNT(PLAYER-ID, SLOT-INDEX + 1)
CALL "World-DropItem" USING PLAYER-POSITION(PLAYER-ID) DROP-SLOT
END-IF
.

END PROGRAM RecvPacket-PlayerAction.
Loading