minecraft-inventory 0.1.26 → 0.1.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "minecraft-inventory",
3
- "version": "0.1.26",
3
+ "version": "0.1.27",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "release": {
@@ -133,15 +133,26 @@ export function InventoryOverlay({
133
133
  }, [jeiOnGetRecipes, jeiOnGetUsages, pushRecipeFrame])
134
134
 
135
135
  // Fires for any click that isn't stopped by an interactive panel (inventory, hotbar, JEI, etc.)
136
- const handleBackdropClick = useCallback(() => {
137
- // Clicking the backdrop clears focused slot (regardless of heldItem)
138
- if (focusedSlot !== null) {
139
- setFocusedSlot(null)
140
- return
141
- }
136
+ const handleBackdropClick = useCallback((e: React.MouseEvent) => {
137
+ // Only handle left (drop all) and right (drop one) mouse buttons
138
+ if (e.button !== 0 && e.button !== 2) return
142
139
  if (heldItem) {
143
- sendAction({ type: 'drop', slotIndex: -1, all: true })
144
- setHeldItem(null)
140
+ const dropAll = e.button === 0 // LMB = drop all, RMB = drop one
141
+ sendAction({ type: 'drop', slotIndex: -1, all: dropAll })
142
+ if (dropAll) {
143
+ setHeldItem(null)
144
+ } else {
145
+ // Right click: drop one, keep rest on cursor
146
+ if (heldItem.count > 1) {
147
+ setHeldItem({ ...heldItem, count: heldItem.count - 1 })
148
+ } else {
149
+ setHeldItem(null)
150
+ }
151
+ }
152
+ // Also clear focused slot if any
153
+ if (focusedSlot !== null) setFocusedSlot(null)
154
+ } else if (focusedSlot !== null) {
155
+ setFocusedSlot(null)
145
156
  } else {
146
157
  onClose?.()
147
158
  }
@@ -183,7 +194,8 @@ export function InventoryOverlay({
183
194
  <>
184
195
  <div
185
196
  className={['mc-inv-overlay', className].filter(Boolean).join(' ')}
186
- onClick={handleBackdropClick}
197
+ onMouseDown={handleBackdropClick}
198
+ onContextMenu={(e) => e.preventDefault()}
187
199
  style={{
188
200
  position: 'absolute',
189
201
  inset: 0,
@@ -217,6 +229,7 @@ export function InventoryOverlay({
217
229
  {showJEI && jeiPosition === 'left' && (
218
230
  <div
219
231
  className="mc-inv-overlay-jei mc-inv-overlay-jei-left"
232
+ onMouseDown={(e) => e.stopPropagation()}
220
233
  onClick={(e) => e.stopPropagation()}
221
234
  style={{ flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column', width: '100%' }}
222
235
  >
@@ -237,12 +250,14 @@ export function InventoryOverlay({
237
250
  display: 'flex',
238
251
  justifyContent: 'center',
239
252
  alignItems: 'center',
253
+ pointerEvents: 'none',
240
254
  }}
241
255
  >
242
- <div className="mc-inv-overlay-content" style={{ position: 'relative' }}>
256
+ <div className="mc-inv-overlay-content" style={{ position: 'relative', pointerEvents: 'auto' }}>
243
257
  {/* Inventory / Recipe view — clicks clear focused slot; slots stop propagation themselves */}
244
258
  <div
245
259
  className="mc-inv-overlay-window"
260
+ onMouseDown={(e) => e.stopPropagation()}
246
261
  onClick={(e) => {
247
262
  e.stopPropagation()
248
263
  // Clicking the inventory background (not a slot) clears focused slot
@@ -274,6 +289,7 @@ export function InventoryOverlay({
274
289
  {showJEI && jeiPosition === 'right' && (
275
290
  <div
276
291
  className="mc-inv-overlay-side mc-inv-overlay-side-right"
292
+ onMouseDown={(e) => e.stopPropagation()}
277
293
  onClick={(e) => e.stopPropagation()}
278
294
  style={{ ...sidePanelBase, right: sideGapPx, pointerEvents: 'auto' }}
279
295
  >
@@ -310,7 +326,7 @@ export function InventoryOverlay({
310
326
  lineHeight: 1,
311
327
  }}
312
328
  >
313
- INV 0.1.26
329
+ INV 0.1.27
314
330
  </a>
315
331
  )}
316
332
 
@@ -755,13 +755,39 @@ export function createMineflayerConnector(bot: MineflayerBot, options?: Mineflay
755
755
  }
756
756
  logActionEvent('connector.action.success', action)
757
757
  } else if (action.type === 'drop') {
758
- logHelperIntent(action, 'bot.clickWindow', {
759
- slot: action.slotIndex,
760
- mouseButton: action.all ? 1 : 0,
761
- mode: 4,
762
- })
763
- await bot.clickWindow(action.slotIndex, action.all ? 1 : 0, 4)
764
- onSetSlot()
758
+ if (action.slotIndex === -1) {
759
+ // Drop cursor item by clicking outside the window: slot=-999, mode=0
760
+ // Left click (all=true) drops entire stack, right click (all=false) drops one
761
+ if (!ext._client) {
762
+ logActionEvent('connector.action.skipped', action, { reason: 'missing_client' })
763
+ return
764
+ }
765
+ const windowId = bot.currentWindow ? bot.currentWindow.id : 0
766
+ const mouseButton = action.all ? 0 : 1
767
+ const packet = {
768
+ windowId,
769
+ stateId: dragStateId,
770
+ slot: -999,
771
+ mouseButton,
772
+ mode: 0,
773
+ changedSlots: [],
774
+ cursorItem: { present: false } as any,
775
+ }
776
+ logPacketWrite('window_click', packet)
777
+ ext._client.write('window_click', packet)
778
+ dragStateId++
779
+ // Skip onSetSlot() — mineflayer's selectedItem is not updated yet.
780
+ // The server will send set_slot/window_items to sync the cursor state.
781
+ } else {
782
+ // Drop from specific slot via Q key: mode=4
783
+ logHelperIntent(action, 'bot.clickWindow', {
784
+ slot: action.slotIndex,
785
+ mouseButton: action.all ? 1 : 0,
786
+ mode: 4,
787
+ })
788
+ await bot.clickWindow(action.slotIndex, action.all ? 1 : 0, 4)
789
+ onSetSlot()
790
+ }
765
791
  logActionEvent('connector.action.success', action)
766
792
  } else if (action.type === 'close') {
767
793
  if (win) {