minecraft-inventory 0.1.5 → 0.1.7

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.
@@ -28,6 +28,7 @@ export interface MineflayerBotWindow {
28
28
  type: string
29
29
  title?: string
30
30
  slots: Array<{ type: number; count: number; metadata?: number; nbt?: unknown } | null>
31
+ selectedItem?: { type: number; count: number; metadata?: number; nbt?: unknown } | null
31
32
  }
32
33
 
33
34
  /** Villager window from bot.openVillager() — has trade() */
@@ -42,6 +42,9 @@ export interface InventoryContextValue {
42
42
  /** Pending first digit for P-key slot number entry */
43
43
  pKeyDigit: string
44
44
  setPKeyDigit: (d: string) => void
45
+ /** Ref set to true when a drag just ended; cleared on next mouseDown.
46
+ * Used by Slot to suppress spurious click events that fire after endDrag. */
47
+ dragEndedRef: React.MutableRefObject<boolean>
45
48
  }
46
49
 
47
50
  const InventoryContext = createContext<InventoryContextValue | null>(null)
@@ -90,6 +93,10 @@ export function InventoryProvider({ connector, children, noDragSpread = false }:
90
93
  const dragButtonRef = useRef(dragButton)
91
94
  dragButtonRef.current = dragButton
92
95
 
96
+ // Set to true when endDrag fires; cleared on the next mouseDown in Slot.
97
+ // Prevents spurious mouseUp events from sending unwanted clicks after a drag.
98
+ const dragEndedRef = useRef(false)
99
+
93
100
  useEffect(() => {
94
101
  if (!connector) return
95
102
  setWindowState(connector.getWindowState())
@@ -159,6 +166,7 @@ export function InventoryProvider({ connector, children, noDragSpread = false }:
159
166
 
160
167
  const startDrag = useCallback((slotIndex: number, button: 'left' | 'right') => {
161
168
  if (noDragSpread) return
169
+ dragEndedRef.current = false
162
170
  setIsDragging(true)
163
171
  setDragButton(button)
164
172
  setDragSlots([slotIndex])
@@ -175,6 +183,7 @@ export function InventoryProvider({ connector, children, noDragSpread = false }:
175
183
  }, [computeDragPreview, dragButton, heldItem, windowState])
176
184
 
177
185
  const endDrag = useCallback(() => {
186
+ dragEndedRef.current = true
178
187
  setDragSlots((slots) => {
179
188
  const button = dragButtonRef.current
180
189
  const held = heldItemRef.current
@@ -196,7 +205,6 @@ export function InventoryProvider({ connector, children, noDragSpread = false }:
196
205
  })
197
206
  if (compatibleSlots.length > 0) {
198
207
  const perSlot = Math.floor(held.count / compatibleSlots.length)
199
- // Vanilla behavior: if perSlot=0 (more slots than items), nothing is distributed
200
208
  if (perSlot > 0) {
201
209
  let totalPlaced = 0
202
210
  for (const idx of compatibleSlots) {
@@ -302,6 +310,7 @@ export function InventoryProvider({ connector, children, noDragSpread = false }:
302
310
  setFocusedSlot,
303
311
  pKeyDigit,
304
312
  setPKeyDigit,
313
+ dragEndedRef,
305
314
  }
306
315
 
307
316
  return <InventoryContext.Provider value={value}>{children}</InventoryContext.Provider>
@@ -28,6 +28,72 @@ import _gui_widgets from 'mc-assets/dist/other-textures/1.15/gui/widgets.png'
28
28
  import _gui_sprites_container_anvil_text_field from 'mc-assets/dist/other-textures/latest/gui/sprites/container/anvil/text_field.png'
29
29
  import _gui_sprites_container_anvil_text_field_disabled from 'mc-assets/dist/other-textures/latest/gui/sprites/container/anvil/text_field_disabled.png'
30
30
 
31
+ /**
32
+ * Versioned texture path → bundled asset URL (or undefined for remote fallback).
33
+ * Keys are full mc-assets paths e.g. "1.21.11/textures/gui/container/inventory.png"
34
+ */
35
+ export const bundledTextureMap: Record<string, string | undefined> = {
36
+ '1.21.11/textures/gui/container/inventory.png': _gui_container_inventory,
37
+ '1.21.11/textures/gui/container/shulker_box.png': _gui_container_shulker_box,
38
+ '1.21.11/textures/gui/container/generic_54.png': _gui_container_generic_54,
39
+ '1.21.11/textures/gui/container/crafting_table.png': _gui_container_crafting_table,
40
+ '1.21.11/textures/gui/container/furnace.png': _gui_container_furnace,
41
+ '1.21.11/textures/gui/container/blast_furnace.png': _gui_container_blast_furnace,
42
+ '1.21.11/textures/gui/container/smoker.png': _gui_container_smoker,
43
+ '1.21.11/textures/gui/container/brewing_stand.png': _gui_container_brewing_stand,
44
+ '1.21.11/textures/gui/container/anvil.png': _gui_container_anvil,
45
+ '1.21.11/textures/gui/container/grindstone.png': _gui_container_grindstone,
46
+ '1.21.11/textures/gui/container/enchanting_table.png': _gui_container_enchanting_table,
47
+ '1.21.11/textures/gui/container/smithing.png': _gui_container_smithing,
48
+ '1.16.4/textures/gui/container/smithing.png': _gui_container_smithing_2,
49
+ '1.21.11/textures/gui/container/hopper.png': _gui_container_hopper,
50
+ '1.21.11/textures/gui/container/dispenser.png': _gui_container_dispenser,
51
+ '1.21.11/textures/gui/container/beacon.png': _gui_container_beacon,
52
+ '1.21.11/textures/gui/container/horse.png': _gui_container_horse,
53
+ '1.14/textures/gui/container/villager2.png': _gui_container_villager2,
54
+ '1.21.11/textures/gui/container/cartography_table.png': _gui_container_cartography_table,
55
+ '1.21.11/textures/gui/container/loom.png': _gui_container_loom,
56
+ '1.21.11/textures/gui/container/stonecutter.png': _gui_container_stonecutter,
57
+ '1.21.11/textures/gui/container/crafter.png': _gui_container_crafter,
58
+ '1.21.11/textures/gui/container/creative_inventory/tab_items.png': _gui_container_creative_inventory_tab_items,
59
+ '1.15/textures/gui/widgets.png': _gui_widgets,
60
+ '1.21.11/textures/gui/sprites/container/anvil/text_field.png': _gui_sprites_container_anvil_text_field,
61
+ '1.21.11/textures/gui/sprites/container/anvil/text_field_disabled.png': _gui_sprites_container_anvil_text_field_disabled,
62
+ }
63
+
64
+
65
+ /**
66
+ * All texture paths without version prefix (e.g. "gui/container/inventory.png").
67
+ * Same set as bundledTextureMap keys with version stripped.
68
+ */
69
+ export const allTexturePaths: readonly string[] = [
70
+ 'gui/container/inventory.png',
71
+ 'gui/container/shulker_box.png',
72
+ 'gui/container/generic_54.png',
73
+ 'gui/container/crafting_table.png',
74
+ 'gui/container/furnace.png',
75
+ 'gui/container/blast_furnace.png',
76
+ 'gui/container/smoker.png',
77
+ 'gui/container/brewing_stand.png',
78
+ 'gui/container/anvil.png',
79
+ 'gui/container/grindstone.png',
80
+ 'gui/container/enchanting_table.png',
81
+ 'gui/container/smithing.png',
82
+ 'gui/container/hopper.png',
83
+ 'gui/container/dispenser.png',
84
+ 'gui/container/beacon.png',
85
+ 'gui/container/horse.png',
86
+ 'gui/container/villager2.png',
87
+ 'gui/container/cartography_table.png',
88
+ 'gui/container/loom.png',
89
+ 'gui/container/stonecutter.png',
90
+ 'gui/container/crafter.png',
91
+ 'gui/container/creative_inventory/tab_items.png',
92
+ 'gui/widgets.png',
93
+ 'gui/sprites/container/anvil/text_field.png',
94
+ 'gui/sprites/container/anvil/text_field_disabled.png',
95
+ ]
96
+
31
97
  /**
32
98
  * Maps each inventory type name to its texture path (version prefix stripped).
33
99
  */
@@ -68,54 +134,3 @@ export const allContainerPaths: Record<string, string> = {
68
134
  creative: 'gui/container/creative_inventory/tab_items.png',
69
135
  hotbar: 'gui/widgets.png',
70
136
  }
71
-
72
- // Internal: versioned texture key → bundled asset URL (or undefined → remote fallback)
73
- const _map: Record<string, string | undefined> = {
74
- '1.21.11/textures/gui/container/inventory.png': _gui_container_inventory,
75
- '1.21.11/textures/gui/container/shulker_box.png': _gui_container_shulker_box,
76
- '1.21.11/textures/gui/container/generic_54.png': _gui_container_generic_54,
77
- '1.21.11/textures/gui/container/crafting_table.png': _gui_container_crafting_table,
78
- '1.21.11/textures/gui/container/furnace.png': _gui_container_furnace,
79
- '1.21.11/textures/gui/container/blast_furnace.png': _gui_container_blast_furnace,
80
- '1.21.11/textures/gui/container/smoker.png': _gui_container_smoker,
81
- '1.21.11/textures/gui/container/brewing_stand.png': _gui_container_brewing_stand,
82
- '1.21.11/textures/gui/container/anvil.png': _gui_container_anvil,
83
- '1.21.11/textures/gui/container/grindstone.png': _gui_container_grindstone,
84
- '1.21.11/textures/gui/container/enchanting_table.png': _gui_container_enchanting_table,
85
- '1.21.11/textures/gui/container/smithing.png': _gui_container_smithing,
86
- '1.16.4/textures/gui/container/smithing.png': _gui_container_smithing_2,
87
- '1.21.11/textures/gui/container/hopper.png': _gui_container_hopper,
88
- '1.21.11/textures/gui/container/dispenser.png': _gui_container_dispenser,
89
- '1.21.11/textures/gui/container/beacon.png': _gui_container_beacon,
90
- '1.21.11/textures/gui/container/horse.png': _gui_container_horse,
91
- '1.14/textures/gui/container/villager2.png': _gui_container_villager2,
92
- '1.21.11/textures/gui/container/cartography_table.png': _gui_container_cartography_table,
93
- '1.21.11/textures/gui/container/loom.png': _gui_container_loom,
94
- '1.21.11/textures/gui/container/stonecutter.png': _gui_container_stonecutter,
95
- '1.21.11/textures/gui/container/crafter.png': _gui_container_crafter,
96
- '1.21.11/textures/gui/container/creative_inventory/tab_items.png': _gui_container_creative_inventory_tab_items,
97
- '1.15/textures/gui/widgets.png': _gui_widgets,
98
- '1.21.11/textures/gui/sprites/container/anvil/text_field.png': _gui_sprites_container_anvil_text_field,
99
- '1.21.11/textures/gui/sprites/container/anvil/text_field_disabled.png': _gui_sprites_container_anvil_text_field_disabled,
100
- }
101
-
102
- /**
103
- * Partial TextureConfig that resolves inventory GUI textures from locally bundled
104
- * mc-assets assets instead of remote GitHub URLs.
105
- *
106
- * Pass to `<TextureProvider config={localTexturesConfig}>` to use offline/bundled assets.
107
- *
108
- * Unknown paths (not bundled) fall back to the mc-assets remote URL automatically.
109
- */
110
- const _MC_ASSETS_REMOTE = "https://raw.githubusercontent.com/zardoy/mc-assets/refs/heads/gh-pages"
111
- export const localTexturesConfig = {
112
- getGuiTextureUrl(path: string): string {
113
- const local = _map[path] as string | undefined
114
- if (local) return local
115
- // Fall back to remote mc-assets URL for paths not in the bundle
116
- if (path.endsWith('.png') && path.includes('/textures/')) {
117
- return `${_MC_ASSETS_REMOTE}/${path}`
118
- }
119
- return path
120
- },
121
- }
package/src/index.tsx CHANGED
@@ -67,4 +67,22 @@ export type {
67
67
  RecipeGuide,
68
68
  RecipeNavFrame,
69
69
  EntityDisplayArea,
70
+ TextureSlice,
71
+ BlockFaceSlice,
72
+ BlockTextureRender,
70
73
  } from './types'
74
+
75
+ // Bundled textures config
76
+ export {
77
+ createBundledTexturesConfig,
78
+ localBundledTexturesConfig,
79
+ allTexturePaths,
80
+ allContainerPaths,
81
+ } from './bundledTexturesConfig'
82
+ export type {
83
+ BundledTexturesConfig,
84
+ BundledTexturesConfigOptions,
85
+ } from './bundledTexturesConfig'
86
+
87
+ // Texture cache (for resetRenderedSlots / manual invalidation)
88
+ export { clearTextureCache } from './cache/textureCache'
@@ -95,6 +95,7 @@ export const inventoryDefinitions = makeInventoryDefinitions({
95
95
  backgroundWidth: 176,
96
96
  backgroundHeight: 166,
97
97
  entityDisplay: { x: 26, y: 8, width: 49, height: 70 },
98
+ entityPlaceholder: 'player',
98
99
  slots: [
99
100
  // Result (0)
100
101
  { x: 154, y: 28, group: 'result', resultSlot: true },
@@ -140,7 +141,7 @@ export const inventoryDefinitions = makeInventoryDefinitions({
140
141
  containerRows: 1,
141
142
  slots: [
142
143
  ...gridSlots(9, 1, 8, 18, 'container'),
143
- ...playerInv(48), // 1*18 + 30
144
+ ...playerInv(50), // 1*18 + 30 + 2px offset below
144
145
  ],
145
146
  },
146
147
 
@@ -153,7 +154,7 @@ export const inventoryDefinitions = makeInventoryDefinitions({
153
154
  containerRows: 2,
154
155
  slots: [
155
156
  ...gridSlots(9, 2, 8, 18, 'container'),
156
- ...playerInv(66), // 2*18 + 30
157
+ ...playerInv(68), // 2*18 + 30 + 2px offset below
157
158
  ],
158
159
  },
159
160
 
@@ -164,10 +165,10 @@ export const inventoryDefinitions = makeInventoryDefinitions({
164
165
  backgroundWidth: 176,
165
166
  backgroundHeight: 168, // 3*18 + 114
166
167
  containerRows: 3,
167
- playerInventoryOffset: { x: 8, y: 84 },
168
+ playerInventoryOffset: { x: 8, y: 82 },
168
169
  slots: [
169
170
  ...gridSlots(9, 3, 8, 18, 'container'),
170
- ...playerInv(84), // 3*18 + 30
171
+ ...playerInv(86), // 3*18 + 30 + 2px offset below
171
172
  ],
172
173
  },
173
174
 
@@ -180,7 +181,7 @@ export const inventoryDefinitions = makeInventoryDefinitions({
180
181
  containerRows: 4,
181
182
  slots: [
182
183
  ...gridSlots(9, 4, 8, 18, 'container'),
183
- ...playerInv(102), // 4*18 + 30
184
+ ...playerInv(104), // 4*18 + 30 + 2px offset below
184
185
  ],
185
186
  },
186
187
 
@@ -193,7 +194,7 @@ export const inventoryDefinitions = makeInventoryDefinitions({
193
194
  containerRows: 5,
194
195
  slots: [
195
196
  ...gridSlots(9, 5, 8, 18, 'container'),
196
- ...playerInv(120), // 5*18 + 30
197
+ ...playerInv(122), // 5*18 + 30 + 2px offset below
197
198
  ],
198
199
  },
199
200
 
@@ -204,6 +205,7 @@ export const inventoryDefinitions = makeInventoryDefinitions({
204
205
  backgroundWidth: 176,
205
206
  backgroundHeight: 222, // full 6-row texture, no stitching needed (N*18+114 = 222)
206
207
  playerInventoryOffset: { x: 8, y: 140 },
208
+ containerRows: 6,
207
209
  slots: [
208
210
  ...gridSlots(9, 6, 8, 18, 'container'),
209
211
  ...playerInv(140), // matches large_chest
@@ -216,7 +218,8 @@ export const inventoryDefinitions = makeInventoryDefinitions({
216
218
  backgroundTexture: '1.21.11/textures/gui/container/generic_54.png',
217
219
  backgroundWidth: 176,
218
220
  backgroundHeight: 222,
219
- playerInventoryOffset: { x: 8, y: 140 },
221
+ containerRows: 6,
222
+ playerInventoryOffset: { x: 8, y: 138 },
220
223
  slots: [
221
224
  ...gridSlots(9, 6, 8, 18, 'container'),
222
225
  ...playerInv(140),
@@ -550,6 +553,7 @@ export const inventoryDefinitions = makeInventoryDefinitions({
550
553
  backgroundWidth: 176,
551
554
  backgroundHeight: 166,
552
555
  entityDisplay: { x: 26, y: 18, width: 52, height: 52 },
556
+ entityPlaceholder: 'horse',
553
557
  slots: [
554
558
  // Saddle (0); slot 1 (horse armor) is absent for donkeys — gap is intentional
555
559
  { x: 8, y: 18, group: 'saddle', label: 'Saddle' },
@@ -566,6 +570,7 @@ export const inventoryDefinitions = makeInventoryDefinitions({
566
570
  backgroundWidth: 176,
567
571
  backgroundHeight: 166,
568
572
  entityDisplay: { x: 26, y: 18, width: 52, height: 52 },
573
+ entityPlaceholder: 'llama',
569
574
  slots: [
570
575
  { x: 8, y: 18, group: 'saddle', label: 'Carpet' },
571
576
  ...gridSlots(5, 3, 80, 18, 'chest').map((s, i) => i === 0 ? { ...s, index: 2 } : s),
package/src/types.ts CHANGED
@@ -1,3 +1,24 @@
1
+ /** Slice rect [x, y, width, height] in source texture pixels. */
2
+ export type TextureSlice = [x:number, y:number, width:number, height:number]
3
+
4
+ /** Block face slice for isometric block rendering. */
5
+ export interface BlockFaceSlice {
6
+ slice: TextureSlice
7
+ }
8
+
9
+ /**
10
+ * Block-style render config. When set, ItemCanvas uses an aux canvas to composite
11
+ * top/left/right faces into an isometric icon instead of a single texture.
12
+ * Useful for blocks in mineflayer connector where block texture atlas faces differ.
13
+ */
14
+ export interface BlockTextureRender {
15
+ /** Source texture URL or preloaded HTMLImageElement. */
16
+ source: string | HTMLImageElement
17
+ top: BlockFaceSlice
18
+ left: BlockFaceSlice
19
+ right: BlockFaceSlice
20
+ }
21
+
1
22
  export interface ItemStack {
2
23
  type: number
3
24
  count: number
@@ -19,6 +40,17 @@ export interface ItemStack {
19
40
  * Example: `"item/dye_black"` or `"entity/spider/spider"`
20
41
  */
21
42
  textureKey?: string
43
+ /**
44
+ * Direct texture override. When set, bypasses getItemTextureUrl.
45
+ * - `string`: URL (data URL or http) used as img src.
46
+ * - `HTMLImageElement`: preloaded image, drawn directly.
47
+ */
48
+ texture?: string | HTMLImageElement
49
+ /**
50
+ * Block-style isometric render. When set, ItemCanvas uses a canvas pool to composite
51
+ * top/left/right face slices into the icon. Use in mineflayer itemMapper for blocks.
52
+ */
53
+ blockTexture?: BlockTextureRender
22
54
  /**
23
55
  * Arbitrary debug identifier exposed as a `data-debug` attribute on the slot element.
24
56
  * The mineflayer connector sets this to `"<type>:<metadata>"` by default, making it easy
@@ -145,6 +177,11 @@ export interface InventoryTypeDefinition {
145
177
  extraData?: Record<string, unknown>
146
178
  /** Bounds for the entity preview area (e.g. player model, horse model). */
147
179
  entityDisplay?: EntityDisplayArea
180
+ /**
181
+ * Bundled placeholder image for the entity panel when `renderEntity` is not set.
182
+ * Maps to files under `src/assets/entities/`.
183
+ */
184
+ entityPlaceholder?: 'player' | 'horse' | 'llama'
148
185
  /**
149
186
  * When set, InventoryBackground will canvas-stitch the background texture:
150
187
  * top (title + N container rows) + bottom (player inventory section) from