Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
daf4709
inv start!
zardoy Mar 15, 2026
c105fd3
local config, make test
zardoy Mar 18, 2026
c8da2a1
final changes by me for now
zardoy Mar 30, 2026
e6b46e1
fix: resolve cherry-pick conflicts and fix TS errors
Apr 2, 2026
59bce8f
feat: rewrite hotbar to React InventoryWindow component
Apr 3, 2026
87805dc
feat: integrate player model rendering in inventory
Apr 4, 2026
12a6b73
fix: use connector for inventory close and cleanup on unmount
Apr 5, 2026
b5a1061
fix: wire hotbarOnly and formatTitle to inventory connectors
Apr 6, 2026
4a04ca5
fix: use renderer/viewer renderSlot path after hotbar cherry-picks
zardoy Apr 7, 2026
f219eae
lint
zardoy Apr 7, 2026
6a28003
upinv
zardoy Apr 7, 2026
0acb7c6
never use remote fallback
zardoy Apr 7, 2026
edfa917
enable notes as was intended
zardoy Apr 7, 2026
a6e1edc
use mineflayer fix
zardoy Apr 7, 2026
d77b270
up mouse
zardoy Apr 7, 2026
ebfe169
Merge remote-tracking branch 'origin/next' into new-inventory
zardoy Apr 7, 2026
78c608e
fix: correct block faces, durability bar and enrich JEI textures
Apr 8, 2026
8612dcb
up inv
zardoy Apr 9, 2026
1cceaf8
fix: remove CDN texture fallback, use local atlases only
Apr 9, 2026
26d0dbd
feat: enrich recipe item textures from local atlas
Apr 9, 2026
ab29c5d
fix: use ImageBitmap atlas for item sprites, keep data URL for block …
Apr 9, 2026
83e7474
feat: enable noPlaceholders to hide armor slot labels
Apr 9, 2026
473d672
feat: restore JEI item giving in creative mode
Apr 10, 2026
5cab51b
refactor: render player model directly inside inventory component
Apr 10, 2026
2b5f46a
up inv
zardoy Apr 11, 2026
a8b8481
a wa y to disable notes
zardoy Apr 11, 2026
e04a9f8
fix: mobile hotbar slot selection and inventory button
Apr 12, 2026
f20a780
up inv
zardoy Apr 12, 2026
5c6c4d4
perf: defer JEI mount and cache JEI items for faster inventory open
Apr 12, 2026
5ead17a
feat: wire up anvil cost client-side computation
Apr 13, 2026
690027e
feat: pass resolveEnchantmentName to inventory provider
Apr 13, 2026
db923c5
FINISH player model display perfect not duplicated code
zardoy Apr 14, 2026
6323783
up mouse
zardoy Apr 14, 2026
62aad92
revert mouse upadte & up inv
zardoy Apr 16, 2026
4ed11b5
re-update
zardoy Apr 16, 2026
f94d944
add settings!
zardoy Apr 16, 2026
3ef6ed8
feat: wire inventory settings gear button to open options menu
Apr 17, 2026
0923e52
Update package.json
zardoy Apr 17, 2026
1343148
fix: hide player model canvas until skin texture is loaded
Apr 19, 2026
fa34c25
Update package.json
zardoy Apr 19, 2026
0364c90
IMPORTANT: update jei textures on texture update
zardoy Apr 19, 2026
6b0e195
Merge branch 'next' into new-inventory
zardoy Apr 19, 2026
b6b0a17
lint all
zardoy Apr 19, 2026
ac0ee83
up mineflayer to use latest Gen's physics changes (fixes physics regr…
zardoy Apr 19, 2026
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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
"lodash-es": "^4.17.21",
"mcraft-fun-mineflayer": "^0.1.23",
"minecraft-data": "3.103.0",
"minecraft-inventory": "^0.1.4",
"minecraft-protocol": "github:PrismarineJS/node-minecraft-protocol#master",
"mineflayer-item-map-downloader": "github:zardoy/mineflayer-item-map-downloader",
"mojangson": "^2.0.4",
Expand Down
41 changes: 32 additions & 9 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

74 changes: 41 additions & 33 deletions src/inventoryWindows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { MessageFormatPart } from './chatUtils'
import { GeneralInputItem, getItemMetadata, getItemModelName, getItemNameRaw, RenderItem } from './mineflayer/items'
import { playerState } from './mineflayer/playerState'
import { modelViewerState } from './react/OverlayModelViewer'
import { openInventoryProxy } from './react/inventory/Inventory'

const loadedImagesCache = new Map<string, HTMLImageElement | ImageBitmap>()
const cleanLoadedImagesCache = () => {
Expand All @@ -45,38 +46,42 @@ export const jeiCustomCategories = proxy({
let remotePlayerSkin: string | undefined | Promise<string>

export const showInventoryPlayer = () => {
modelViewerState.model = {
positioning: {
windowWidth: 176,
windowHeight: 166,
x: 25,
y: 8,
width: 50,
height: 70,
scaled: true,
onlyInitialScale: true,
},
followCursor: true,
followCursorCenter: {
x: 51,
y: 27,
},
// models: ['https://bucket.mcraft.fun/sitarbuckss.glb'],
// debug: true,
steveModelSkin: appViewer.playerState.reactive.playerSkin ?? (typeof remotePlayerSkin === 'string' ? remotePlayerSkin : ''),
}
if (remotePlayerSkin === undefined && !appViewer.playerState.reactive.playerSkin) {
remotePlayerSkin = loadSkinFromUsername(bot.username, 'skin').then(a => {
setTimeout(() => {
// Check if player inventory is still open before updating
if (lastWindowType === null) {
showInventoryPlayer()
}
}, 0) // todo patch instead and make reactive
remotePlayerSkin = a ?? ''
return remotePlayerSkin
})
}
// openInventoryProxy.inventory = {
// type: 'player',
// }

// modelViewerState.model = {
// positioning: {
// windowWidth: 176,
// windowHeight: 166,
// x: 25,
// y: 8,
// width: 50,
// height: 70,
// scaled: true,
// onlyInitialScale: true,
// },
// followCursor: true,
// followCursorCenter: {
// x: 51,
// y: 27,
// },
// // models: ['https://bucket.mcraft.fun/sitarbuckss.glb'],
// // debug: true,
// steveModelSkin: appViewer.playerState.reactive.playerSkin ?? (typeof remotePlayerSkin === 'string' ? remotePlayerSkin : ''),
// }
// if (remotePlayerSkin === undefined && !appViewer.playerState.reactive.playerSkin) {
// remotePlayerSkin = loadSkinFromUsername(bot.username, 'skin').then(a => {
// setTimeout(() => {
// // Check if player inventory is still open before updating
// if (lastWindowType === null) {
// showInventoryPlayer()
// }
// }, 0) // todo patch instead and make reactive
// remotePlayerSkin = a ?? ''
// return remotePlayerSkin
// })
// }
}

export const onGameLoad = () => {
Expand Down Expand Up @@ -577,7 +582,10 @@ const openWindow = (type: string | undefined, title: string | any = undefined) =
let destroyFn = () => { }

export const openPlayerInventory = () => {
openWindow(undefined)
openInventoryProxy.inventory = {
type: 'player',
}
// openWindow(undefined)
}

const getResultingRecipe = (slots: Array<Item | null>, gridRows: number) => {
Expand Down
38 changes: 38 additions & 0 deletions src/react/inventory/Inventory.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { TextureProvider, ScaleProvider, InventoryProvider, InventoryOverlay, createMineflayerConnector, MineflayerBot, InventoryOverlayProps } from 'minecraft-inventory/src'
import { useMemo } from 'react'
import { proxy, useSnapshot } from 'valtio'
import { localTexturesConfig } from 'minecraft-inventory/src/generated/localTextures'
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
import { useAppScale } from '../../scaleInterface'

export const openInventoryProxy = proxy({
inventory: undefined as InventoryOverlayProps | undefined,
})

export const Inventory = () => {
const windowType = 'player'
const connector = useMemo(() => createMineflayerConnector(bot as MineflayerBot), [bot])
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Guard against bot being undefined to prevent runtime crash.

The global bot variable can be undefined during disconnect or before connection (see src/index.ts where bot = undefined and src/globals.js where it starts as undefined). Calling createMineflayerConnector(bot as MineflayerBot) when bot is undefined will likely crash.

Additionally, useMemo with [bot] as a dependency may not re-trigger correctly since bot is a global variable that React doesn't track. When a new bot instance is assigned, this component won't automatically re-render.

🛡️ Proposed fix for null safety
 export const Inventory = () => {
   const windowType = 'player'
+  const { inventory } = useSnapshot(openInventoryProxy) as typeof openInventoryProxy
+
+  // Early return before creating connector if no bot or inventory
+  if (!inventory || !bot) return null
+
   const connector = useMemo(() => createMineflayerConnector(bot as MineflayerBot), [bot])
   const appScale = useAppScale()
-  const { inventory } = useSnapshot(openInventoryProxy) as typeof openInventoryProxy
-
-  if (!inventory) return null

Note: The useMemo dependency on global bot may still not work as expected for re-renders. Consider using a state or context pattern to track the bot instance if reconnection scenarios need to be supported.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/react/inventory/Inventory.tsx` at line 12, Guard against bot being
undefined by only calling createMineflayerConnector when bot is present and
return a safe fallback (e.g., null) otherwise; update the useMemo for connector
(the const connector = useMemo(...) line) to check the global bot before
invoking createMineflayerConnector and ensure connector is typed/handled for
null. Also stop relying solely on the global bot in the dependency array: wire
the Inventory component to a React-tracked source (e.g., local state or context
that holds the bot) or subscribe to bot changes in useEffect so re-renders occur
when a new bot is assigned, and use that tracked value in the useMemo dependency
instead of the raw global.

const appScale = useAppScale()
const { inventory } = useSnapshot(openInventoryProxy) as typeof openInventoryProxy

if (!inventory) return null

return <div style={{
position: 'fixed',
inset: 0,
width: '100%',
height: '100dvh',
zIndex: 1000,
}}>
<TextureProvider config={localTexturesConfig}>
<ScaleProvider scale={appScale}>
<InventoryProvider connector={connector}>
<InventoryOverlay
showJEI
enableNotes
{...inventory}
/>
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
</InventoryProvider>
</ScaleProvider>
</TextureProvider>
</div>
}
2 changes: 2 additions & 0 deletions src/reactUi.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ import AllSettingsEditor from './react/AllSettingsEditor'
import { isPlayground, urlParams } from './playgroundIntegration'
import { withInjectableUi } from './react/extendableSystem'
import { hadReactUiRegistered } from './clientMods'
import { Inventory } from './react/inventory/Inventory'

const isFirefox = ua.getBrowser().name === 'Firefox'
if (isFirefox) {
Expand Down Expand Up @@ -204,6 +205,7 @@ const InGameUi = () => {
<PerComponentErrorBoundary>
<SignEditorProvider />
<DisplayQr />
<Inventory />
</PerComponentErrorBoundary>
<RobustPortal to={document.body}>
{displayFullmap && <MinimapProvider adapter={adapter} displayMode='fullmapOnly' />}
Expand Down
Loading