- Introduced a patchAssets script to apply custom textures to the blocks and items atlases.
- Enhanced the ThreeJsSound class to support sound playback timeout and volume adjustments. - Added a custom sound system to handle named sound effects with metadata.
This commit is contained in:
parent
cc4f705aea
commit
e1293b6cb3
11 changed files with 323 additions and 18 deletions
137
scripts/patchAssets.ts
Normal file
137
scripts/patchAssets.ts
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
import blocksAtlas from 'mc-assets/dist/blocksAtlases.json'
|
||||
import itemsAtlas from 'mc-assets/dist/itemsAtlases.json'
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import sharp from 'sharp'
|
||||
|
||||
interface AtlasFile {
|
||||
latest: {
|
||||
suSv: number
|
||||
tileSize: number
|
||||
width: number
|
||||
height: number
|
||||
textures: {
|
||||
[key: string]: {
|
||||
u: number
|
||||
v: number
|
||||
su: number
|
||||
sv: number
|
||||
tileIndex: number
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function patchTextureAtlas(
|
||||
atlasType: 'blocks' | 'items',
|
||||
atlasData: AtlasFile,
|
||||
customTexturesDir: string,
|
||||
distDir: string
|
||||
) {
|
||||
// Check if custom textures directory exists and has files
|
||||
if (!fs.existsSync(customTexturesDir) || fs.readdirSync(customTexturesDir).length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
// Find the latest atlas file
|
||||
const atlasFiles = fs.readdirSync(distDir)
|
||||
.filter(file => file.startsWith(`${atlasType}AtlasLatest`) && file.endsWith('.png'))
|
||||
.sort()
|
||||
|
||||
if (atlasFiles.length === 0) {
|
||||
console.log(`No ${atlasType}AtlasLatest.png found in ${distDir}`)
|
||||
return
|
||||
}
|
||||
|
||||
const latestAtlasFile = atlasFiles[atlasFiles.length - 1]
|
||||
const atlasPath = path.join(distDir, latestAtlasFile)
|
||||
console.log(`Patching ${atlasPath}`)
|
||||
|
||||
// Get atlas dimensions
|
||||
const atlasMetadata = await sharp(atlasPath).metadata()
|
||||
if (!atlasMetadata.width || !atlasMetadata.height) {
|
||||
throw new Error(`Failed to get atlas dimensions for ${atlasPath}`)
|
||||
}
|
||||
|
||||
// Process each custom texture
|
||||
const customTextureFiles = fs.readdirSync(customTexturesDir)
|
||||
.filter(file => file.endsWith('.png'))
|
||||
|
||||
if (customTextureFiles.length === 0) return
|
||||
|
||||
// Prepare composite operations
|
||||
const composites: sharp.OverlayOptions[] = []
|
||||
|
||||
for (const textureFile of customTextureFiles) {
|
||||
const textureName = path.basename(textureFile, '.png')
|
||||
|
||||
if (atlasData.latest.textures[textureName]) {
|
||||
const textureData = atlasData.latest.textures[textureName]
|
||||
const customTexturePath = path.join(customTexturesDir, textureFile)
|
||||
|
||||
try {
|
||||
// Convert UV coordinates to pixel coordinates
|
||||
const x = Math.round(textureData.u * atlasMetadata.width)
|
||||
const y = Math.round(textureData.v * atlasMetadata.height)
|
||||
const width = Math.round((textureData.su ?? atlasData.latest.suSv) * atlasMetadata.width)
|
||||
const height = Math.round((textureData.sv ?? atlasData.latest.suSv) * atlasMetadata.height)
|
||||
|
||||
// Resize custom texture to match atlas dimensions and add to composite operations
|
||||
const resizedTextureBuffer = await sharp(customTexturePath)
|
||||
.resize(width, height, {
|
||||
fit: 'fill',
|
||||
kernel: 'nearest' // Preserve pixel art quality
|
||||
})
|
||||
.png()
|
||||
.toBuffer()
|
||||
|
||||
composites.push({
|
||||
input: resizedTextureBuffer,
|
||||
left: x,
|
||||
top: y,
|
||||
blend: 'over'
|
||||
})
|
||||
|
||||
console.log(`Prepared ${textureName} at (${x}, ${y}) with size (${width}, ${height})`)
|
||||
} catch (error) {
|
||||
console.error(`Failed to prepare ${textureName}:`, error)
|
||||
}
|
||||
} else {
|
||||
console.warn(`Texture ${textureName} not found in ${atlasType} atlas`)
|
||||
}
|
||||
}
|
||||
|
||||
if (composites.length > 0) {
|
||||
// Apply all patches at once using Sharp's composite
|
||||
await sharp(atlasPath)
|
||||
.composite(composites)
|
||||
.png()
|
||||
.toFile(atlasPath + '.tmp')
|
||||
|
||||
// Replace original with patched version
|
||||
fs.renameSync(atlasPath + '.tmp', atlasPath)
|
||||
console.log(`Saved patched ${atlasType} atlas to ${atlasPath}`)
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const customBlocksDir = './assets/customTextures/blocks'
|
||||
const customItemsDir = './assets/customTextures/items'
|
||||
const distDir = './dist/static/image'
|
||||
|
||||
try {
|
||||
// Patch blocks atlas
|
||||
await patchTextureAtlas('blocks', blocksAtlas as unknown as AtlasFile, customBlocksDir, distDir)
|
||||
|
||||
// Patch items atlas
|
||||
await patchTextureAtlas('items', itemsAtlas as unknown as AtlasFile, customItemsDir, distDir)
|
||||
|
||||
console.log('Texture atlas patching completed!')
|
||||
} catch (error) {
|
||||
console.error('Failed to patch texture atlases:', error)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// Run the script
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue