fix(perf): dont load gui textures on panorama start in singlefile build
fix: update textures in inventory & hotbar after textures load, including jei fix: one row of jei was out of the screen
This commit is contained in:
parent
5af290ac4e
commit
4f45cd072a
9 changed files with 68 additions and 48 deletions
|
|
@ -150,7 +150,7 @@
|
|||
"http-browserify": "^1.7.0",
|
||||
"http-server": "^14.1.1",
|
||||
"https-browserify": "^1.0.0",
|
||||
"mc-assets": "^0.2.48",
|
||||
"mc-assets": "^0.2.49",
|
||||
"mineflayer-mouse": "^0.1.7",
|
||||
"minecraft-inventory-gui": "github:zardoy/minecraft-inventory-gui#next",
|
||||
"mineflayer": "github:zardoy/mineflayer",
|
||||
|
|
|
|||
18
pnpm-lock.yaml
generated
18
pnpm-lock.yaml
generated
|
|
@ -353,11 +353,11 @@ importers:
|
|||
specifier: ^1.0.0
|
||||
version: 1.0.0
|
||||
mc-assets:
|
||||
specifier: ^0.2.48
|
||||
version: 0.2.48
|
||||
specifier: ^0.2.49
|
||||
version: 0.2.49
|
||||
minecraft-inventory-gui:
|
||||
specifier: github:zardoy/minecraft-inventory-gui#next
|
||||
version: https://codeload.github.com/zardoy/minecraft-inventory-gui/tar.gz/69dee6aa15f7c8a6df2a2ab01972e6a7b2f9ee30(@types/react@18.2.20)(react@18.2.0)
|
||||
version: https://codeload.github.com/zardoy/minecraft-inventory-gui/tar.gz/f57dd78ca8e3b7cdd724d4272d8cbf6743b0cf00(@types/react@18.2.20)(react@18.2.0)
|
||||
mineflayer:
|
||||
specifier: github:zardoy/mineflayer
|
||||
version: https://codeload.github.com/zardoy/mineflayer/tar.gz/06e3050ddf4d9aa655fea6e2bed182937a81705d(encoding@0.1.13)
|
||||
|
|
@ -6694,8 +6694,8 @@ packages:
|
|||
maxrects-packer@2.7.3:
|
||||
resolution: {integrity: sha512-bG6qXujJ1QgttZVIH4WDanhoJtvbud/xP/XPyf6A69C9RdA61BM4TomFALCq2nrTa+tARRIBB4LuIFsnUQU2wA==}
|
||||
|
||||
mc-assets@0.2.48:
|
||||
resolution: {integrity: sha512-ixFBAkdWuluBZ3RhWXvD+KyLX5jKAK8ksXJamAuJxc7nXHP6xK5rEAR3qQ7JVYh27USl3mE+GWTFy/aF0CGRYg==}
|
||||
mc-assets@0.2.49:
|
||||
resolution: {integrity: sha512-pFR43FqG1bxiQVLXX8c4LNA/7wcFRGDFFclsBM6tY8tKFNolKhwiSaLmV0xtFHEF6SZGv9g2hkMqxsbAzMD/6A==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
|
||||
mcraft-fun-mineflayer@0.1.14:
|
||||
|
|
@ -6912,8 +6912,8 @@ packages:
|
|||
minecraft-folder-path@1.2.0:
|
||||
resolution: {integrity: sha512-qaUSbKWoOsH9brn0JQuBhxNAzTDMwrOXorwuRxdJKKKDYvZhtml+6GVCUrY5HRiEsieBEjCUnhVpDuQiKsiFaw==}
|
||||
|
||||
minecraft-inventory-gui@https://codeload.github.com/zardoy/minecraft-inventory-gui/tar.gz/69dee6aa15f7c8a6df2a2ab01972e6a7b2f9ee30:
|
||||
resolution: {tarball: https://codeload.github.com/zardoy/minecraft-inventory-gui/tar.gz/69dee6aa15f7c8a6df2a2ab01972e6a7b2f9ee30}
|
||||
minecraft-inventory-gui@https://codeload.github.com/zardoy/minecraft-inventory-gui/tar.gz/f57dd78ca8e3b7cdd724d4272d8cbf6743b0cf00:
|
||||
resolution: {tarball: https://codeload.github.com/zardoy/minecraft-inventory-gui/tar.gz/f57dd78ca8e3b7cdd724d4272d8cbf6743b0cf00}
|
||||
version: 1.0.1
|
||||
|
||||
minecraft-protocol@https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/3bd4dc1b2002cd7badfa5b9cf8dda35cd6cc9ac1:
|
||||
|
|
@ -17605,7 +17605,7 @@ snapshots:
|
|||
|
||||
maxrects-packer@2.7.3: {}
|
||||
|
||||
mc-assets@0.2.48:
|
||||
mc-assets@0.2.49:
|
||||
dependencies:
|
||||
maxrects-packer: 2.7.3
|
||||
zod: 3.24.1
|
||||
|
|
@ -17922,7 +17922,7 @@ snapshots:
|
|||
|
||||
minecraft-folder-path@1.2.0: {}
|
||||
|
||||
minecraft-inventory-gui@https://codeload.github.com/zardoy/minecraft-inventory-gui/tar.gz/69dee6aa15f7c8a6df2a2ab01972e6a7b2f9ee30(@types/react@18.2.20)(react@18.2.0):
|
||||
minecraft-inventory-gui@https://codeload.github.com/zardoy/minecraft-inventory-gui/tar.gz/f57dd78ca8e3b7cdd724d4272d8cbf6743b0cf00(@types/react@18.2.20)(react@18.2.0):
|
||||
dependencies:
|
||||
valtio: 1.11.2(@types/react@18.2.20)(react@18.2.0)
|
||||
transitivePeerDependencies:
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { getItemDefinition } from 'mc-assets/dist/itemDefinitions'
|
|||
|
||||
export const activeGuiAtlas = proxy({
|
||||
atlas: null as null | { json, image },
|
||||
version: 0
|
||||
})
|
||||
|
||||
export const getNonFullBlocksModels = () => {
|
||||
|
|
@ -278,5 +279,6 @@ export const generateGuiAtlas = async () => {
|
|||
const itemImages = await generateItemsGui(itemsModelsResolved, true)
|
||||
console.timeEnd('generate items gui atlas')
|
||||
await generateAtlas({ ...blockImages, ...itemImages })
|
||||
activeGuiAtlas.version++
|
||||
// await generateAtlas(blockImages)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
|
|||
})
|
||||
if (this.wasChunkSentToWorker(chunkKey)) {
|
||||
const [x, y, z] = blockPos.split(',').map(Number)
|
||||
this.setBlockStateId(new Vec3(x, y, z), undefined, false)
|
||||
this.setBlockStateId(new Vec3(x, y, z), undefined)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -722,7 +722,7 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
|
|||
abstract worldStop? ()
|
||||
|
||||
queueAwaited = false
|
||||
messagesQueue = {} as { [workerIndex: string]: any[] }
|
||||
toWorkerMessagesQueue = {} as { [workerIndex: string]: any[] }
|
||||
|
||||
getWorkerNumber (pos: Vec3, updateAction = false) {
|
||||
if (updateAction) {
|
||||
|
|
@ -749,8 +749,8 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
|
|||
// is always dispatched to the same worker
|
||||
const hash = this.getWorkerNumber(pos, useChangeWorker)
|
||||
this.sectionsWaiting.set(key, (this.sectionsWaiting.get(key) ?? 0) + 1)
|
||||
this.messagesQueue[hash] ??= []
|
||||
this.messagesQueue[hash].push({
|
||||
this.toWorkerMessagesQueue[hash] ??= []
|
||||
this.toWorkerMessagesQueue[hash].push({
|
||||
// this.workers[hash].postMessage({
|
||||
type: 'dirty',
|
||||
x: pos.x,
|
||||
|
|
@ -767,11 +767,11 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
|
|||
this.queueAwaited = true
|
||||
setTimeout(() => {
|
||||
// group messages and send as one
|
||||
for (const workerIndex in this.messagesQueue) {
|
||||
for (const workerIndex in this.toWorkerMessagesQueue) {
|
||||
const worker = this.workers[Number(workerIndex)]
|
||||
worker.postMessage(this.messagesQueue[workerIndex])
|
||||
worker.postMessage(this.toWorkerMessagesQueue[workerIndex])
|
||||
}
|
||||
this.messagesQueue = {}
|
||||
this.toWorkerMessagesQueue = {}
|
||||
this.queueAwaited = false
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ export class PanoramaRenderer {
|
|||
|
||||
async worldBlocksPanorama () {
|
||||
const version = '1.21.4'
|
||||
this.options.resourcesManager.currentConfig = { version }
|
||||
this.options.resourcesManager.currentConfig = { version, noInventoryGui: true, }
|
||||
await this.options.resourcesManager.updateAssetsData({ })
|
||||
if (this.abortController.signal.aborted) return
|
||||
console.time('load panorama scene')
|
||||
|
|
|
|||
|
|
@ -299,20 +299,6 @@ export class WorldRendererThree extends WorldRendererCommon {
|
|||
// this.debugRecomputedDeletedObjects++
|
||||
// }
|
||||
|
||||
// if (!this.initialChunksLoad && this.enableChunksLoadDelay) {
|
||||
// const newPromise = new Promise(resolve => {
|
||||
// if (this.droppedFpsPercentage > 0.5) {
|
||||
// setTimeout(resolve, 1000 / 50 * this.droppedFpsPercentage)
|
||||
// } else {
|
||||
// setTimeout(resolve)
|
||||
// }
|
||||
// })
|
||||
// this.promisesQueue.push(newPromise)
|
||||
// for (const promise of this.promisesQueue) {
|
||||
// await promise
|
||||
// }
|
||||
// }
|
||||
|
||||
const geometry = new THREE.BufferGeometry()
|
||||
geometry.setAttribute('position', new THREE.BufferAttribute(data.geometry.positions, 3))
|
||||
geometry.setAttribute('normal', new THREE.BufferAttribute(data.geometry.normals, 3))
|
||||
|
|
|
|||
|
|
@ -702,6 +702,7 @@ export async function connect (connectOptions: ConnectOptions) {
|
|||
}
|
||||
})
|
||||
})
|
||||
await appViewer.resourcesManager.promiseAssetsReady
|
||||
}
|
||||
console.log('try to focus window')
|
||||
window.focus?.()
|
||||
|
|
|
|||
|
|
@ -119,12 +119,13 @@ export const onGameLoad = () => {
|
|||
|
||||
if (!appViewer.resourcesManager['_inventoryChangeTracked']) {
|
||||
appViewer.resourcesManager['_inventoryChangeTracked'] = true
|
||||
const upWindowItems = () => {
|
||||
const texturesChanged = () => {
|
||||
if (!lastWindow) return
|
||||
upWindowItemsLocal()
|
||||
upJei(lastJeiSearch)
|
||||
}
|
||||
appViewer.resourcesManager.on('assetsInventoryReady', () => upWindowItems())
|
||||
appViewer.resourcesManager.on('assetsTexturesUpdated', () => upWindowItems())
|
||||
appViewer.resourcesManager.on('assetsInventoryReady', () => texturesChanged())
|
||||
appViewer.resourcesManager.on('assetsTexturesUpdated', () => texturesChanged())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -176,6 +177,7 @@ const getImage = ({ path = undefined as string | undefined, texture = undefined
|
|||
|
||||
export type ResolvedItemModelRender = {
|
||||
modelName: string,
|
||||
originalItemName?: string
|
||||
}
|
||||
|
||||
export const renderSlot = (model: ResolvedItemModelRender, debugIsQuickbar = false, fullBlockModelSupport = false): {
|
||||
|
|
@ -200,7 +202,8 @@ export const renderSlot = (model: ResolvedItemModelRender, debugIsQuickbar = fal
|
|||
if (!fullBlockModelSupport) {
|
||||
const atlas = activeGuiAtlas.atlas?.json
|
||||
// todo atlas holds all rendered blocks, not all possibly rendered item/block models, need to request this on demand instead (this is how vanilla works)
|
||||
const item = atlas?.textures[itemModelName.replace('minecraft:', '').replace('block/', '').replace('blocks/', '').replace('item/', '').replace('items/', '').replace('_inventory', '').replace('_bottom', '').replace('_height2', '').replace('_stable', '').replace('_unstable', '')]
|
||||
const tryGetAtlasTexture = (name?: string) => name && atlas?.textures[name.replace('minecraft:', '').replace('block/', '').replace('blocks/', '').replace('item/', '').replace('items/', '').replace('_inventory', '')]
|
||||
const item = tryGetAtlasTexture(itemModelName) ?? tryGetAtlasTexture(model.originalItemName)
|
||||
if (item) {
|
||||
const x = item.u * atlas.width
|
||||
const y = item.v * atlas.height
|
||||
|
|
@ -217,6 +220,7 @@ export const renderSlot = (model: ResolvedItemModelRender, debugIsQuickbar = fal
|
|||
assertDefined(appViewer.resourcesManager.currentResources?.itemsRenderer)
|
||||
itemTexture =
|
||||
appViewer.resourcesManager.currentResources.itemsRenderer.getItemTexture(itemModelName, {}, false, fullBlockModelSupport)
|
||||
?? (model.originalItemName ? appViewer.resourcesManager.currentResources.itemsRenderer.getItemTexture(model.originalItemName, {}, false, fullBlockModelSupport) : undefined)
|
||||
?? appViewer.resourcesManager.currentResources.itemsRenderer.getItemTexture('item/missing_texture')!
|
||||
} catch (err) {
|
||||
inGameError(`Failed to render item ${itemModelName} (original: ${originalItemName}) on ${bot.version} (resourcepack: ${options.enabledResourcepack}): ${err.stack}`)
|
||||
|
|
@ -249,20 +253,29 @@ const getItemName = (slot: Item | RenderItem | null) => {
|
|||
return text.join('')
|
||||
}
|
||||
|
||||
let lastMappedSots = [] as any[]
|
||||
let lastMappedSlots = [] as any[]
|
||||
const itemToVisualKey = (slot: RenderItem | Item | null) => {
|
||||
if (!slot) return null
|
||||
return slot.name + slot['count'] + (slot['metadata'] ?? '-') + (slot.nbt ? JSON.stringify(slot.nbt) : '') + (slot['components'] ? JSON.stringify(slot['components']) : '')
|
||||
if (!slot) return ''
|
||||
const keys = [
|
||||
slot.name,
|
||||
slot['count'],
|
||||
slot['metadata'],
|
||||
slot.nbt ? JSON.stringify(slot.nbt) : '',
|
||||
slot['components'] ? JSON.stringify(slot['components']) : '',
|
||||
activeGuiAtlas.version,
|
||||
].join('|')
|
||||
return keys
|
||||
}
|
||||
const mapSlots = (slots: Array<RenderItem | Item | null>, isJei = false) => {
|
||||
const newSlots = slots.map((slot, i) => {
|
||||
// todo stateid
|
||||
if (!slot) return
|
||||
if (!slot) return null
|
||||
|
||||
if (!isJei) {
|
||||
const oldKey = itemToVisualKey(lastMappedSots[i])
|
||||
if (oldKey && oldKey === itemToVisualKey(slot)) {
|
||||
return lastMappedSots[i]
|
||||
const oldKey = lastMappedSlots[i]?.cacheKey
|
||||
const newKey = itemToVisualKey(slot)
|
||||
slot['cacheKey'] = newKey
|
||||
if (oldKey && oldKey === newKey) {
|
||||
return lastMappedSlots[i]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -270,7 +283,7 @@ const mapSlots = (slots: Array<RenderItem | Item | null>, isJei = false) => {
|
|||
if (slot.durabilityUsed && slot.maxDurability) slot.durabilityUsed = Math.min(slot.durabilityUsed, slot.maxDurability)
|
||||
const debugIsQuickbar = !isJei && i === bot.inventory.hotbarStart + bot.quickBarSlot
|
||||
const modelName = getItemModelName(slot, { 'minecraft:display_context': 'gui', }, appViewer.resourcesManager)
|
||||
const slotCustomProps = renderSlot({ modelName }, debugIsQuickbar)
|
||||
const slotCustomProps = renderSlot({ modelName, originalItemName: slot.name }, debugIsQuickbar)
|
||||
const itemCustomName = getItemName(slot)
|
||||
Object.assign(slot, { ...slotCustomProps, displayName: itemCustomName ?? slot.displayName })
|
||||
//@ts-expect-error
|
||||
|
|
@ -285,7 +298,7 @@ const mapSlots = (slots: Array<RenderItem | Item | null>, isJei = false) => {
|
|||
}
|
||||
return slot
|
||||
})
|
||||
lastMappedSots = newSlots
|
||||
lastMappedSlots = newSlots
|
||||
return newSlots
|
||||
}
|
||||
|
||||
|
|
@ -331,7 +344,9 @@ const implementedContainersGuiMap = {
|
|||
'minecraft:villager': 'VillagerWin',
|
||||
}
|
||||
|
||||
let lastJeiSearch = ''
|
||||
const upJei = (search: string) => {
|
||||
lastJeiSearch = search
|
||||
search = search.toLowerCase()
|
||||
// todo fix pre flat
|
||||
const itemsArray = [
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ export interface ResourcesCurrentConfig {
|
|||
version: string
|
||||
texturesVersion?: string
|
||||
noBlockstatesModels?: boolean
|
||||
noInventoryGui?: boolean
|
||||
includeOnlyBlocks?: string[]
|
||||
}
|
||||
|
||||
|
|
@ -58,6 +59,7 @@ export interface UpdateAssetsRequest {
|
|||
_?: false
|
||||
}
|
||||
|
||||
const STABLE_MODELS_VERSION = '1.21.4'
|
||||
export class ResourcesManager extends (EventEmitter as new () => TypedEmitter<ResourceManagerEvents>) {
|
||||
// Source data (imported, not changing)
|
||||
sourceBlockStatesModels: any = null
|
||||
|
|
@ -69,6 +71,10 @@ export class ResourcesManager extends (EventEmitter as new () => TypedEmitter<Re
|
|||
currentResources: LoadedResources | undefined
|
||||
currentConfig: ResourcesCurrentConfig | undefined
|
||||
abortController = new AbortController()
|
||||
_promiseAssetsReadyResolvers = Promise.withResolvers<void>()
|
||||
get promiseAssetsReady () {
|
||||
return this._promiseAssetsReadyResolvers.promise
|
||||
}
|
||||
|
||||
async loadMcData (version: string) {
|
||||
await loadMinecraftData(version)
|
||||
|
|
@ -85,6 +91,7 @@ export class ResourcesManager extends (EventEmitter as new () => TypedEmitter<Re
|
|||
|
||||
async updateAssetsData (request: UpdateAssetsRequest, unstableSkipEvent = false) {
|
||||
if (!this.currentConfig) throw new Error('No config loaded')
|
||||
this._promiseAssetsReadyResolvers = Promise.withResolvers()
|
||||
const abortController = new AbortController()
|
||||
await this.loadSourceData(this.currentConfig.version)
|
||||
if (abortController.signal.aborted) return
|
||||
|
|
@ -165,7 +172,7 @@ export class ResourcesManager extends (EventEmitter as new () => TypedEmitter<Re
|
|||
resources.worldBlockProvider = worldBlockProvider(
|
||||
resources.blockstatesModels,
|
||||
resources.blocksAtlasParser.atlas,
|
||||
'latest'
|
||||
STABLE_MODELS_VERSION
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -174,8 +181,17 @@ export class ResourcesManager extends (EventEmitter as new () => TypedEmitter<Re
|
|||
this.currentResources = resources
|
||||
if (!unstableSkipEvent) { // todo rework resourcepack optimization
|
||||
this.emit('assetsTexturesUpdated')
|
||||
}
|
||||
|
||||
if (this.currentConfig.noInventoryGui) {
|
||||
this._promiseAssetsReadyResolvers.resolve()
|
||||
} else {
|
||||
void this.generateGuiTextures().then(() => {
|
||||
this.emit('assetsInventoryReady')
|
||||
if (abortController.signal.aborted) return
|
||||
if (!unstableSkipEvent) {
|
||||
this.emit('assetsInventoryReady')
|
||||
}
|
||||
this._promiseAssetsReadyResolvers.resolve()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue