Compare commits

...
Sign in to create a new pull request.

3 commits

Author SHA1 Message Date
Vitaly Turovsky
116102a776 finish decorated pot, todo make version specfiic files reading! 2024-05-27 11:58:27 +03:00
Vitaly Turovsky
eb76f53280 Merge branch 'next' into pr/Wolf2323/132 2024-05-26 18:59:38 +03:00
Wolf2323
0a932b5d35 add decorated-pot WIP 2024-05-24 12:29:09 +02:00
4 changed files with 119 additions and 11 deletions

View file

@ -35,7 +35,7 @@ export type JsonAtlas = {
}
}
export const makeTextureAtlas = (input: string[], getInputData: (name) => { contents: string, tileWidthMult?: number }, tilesCount = input.length, suSvOptimize: 'remove' | null = null): {
export const makeTextureAtlas = (input: string[], getInputData: (name) => { contents: string, tileWidthMult?: number, origSizeTextures?}, tilesCount = input.length, suSvOptimize: 'remove' | null = null): {
image: Buffer,
canvas: Canvas,
json: JsonAtlas
@ -49,6 +49,7 @@ export const makeTextureAtlas = (input: string[], getInputData: (name) => { cont
const texturesIndex = {}
let skipXY = [] as [x: number, y: number][]
let offset = 0
const suSv = tileSize / imgSize
for (const i in input) {
@ -56,20 +57,44 @@ export const makeTextureAtlas = (input: string[], getInputData: (name) => { cont
const x = (pos % texSize) * tileSize
const y = Math.floor(pos / texSize) * tileSize
if (skipXY.some(([sx, sy]) => sx === x + 1 && sy === y)) {
// todo more offsets
offset++
}
const img = new Image()
const keyValue = input[i];
const inputData = getInputData(keyValue);
const keyValue = input[i]
const inputData = getInputData(keyValue)
img.src = inputData.contents
const renderWidth = tileSize * (inputData.tileWidthMult ?? 1)
g.drawImage(img, 0, 0, renderWidth, tileSize, x, y, renderWidth, tileSize)
let su = suSv
let sv = suSv
let renderWidth = tileSize * (inputData.tileWidthMult ?? 1)
let renderHeight = tileSize
if (inputData.origSizeTextures?.[keyValue]) {
// todo check have enough space
renderWidth = Math.ceil(img.width / tileSize) * tileSize
renderHeight = Math.ceil(img.height / tileSize) * tileSize
su = renderWidth / imgSize
sv = renderHeight / imgSize
if (renderWidth > tileSize) {
offset += Math.ceil(renderWidth / tileSize) - 1
}
if (renderHeight > tileSize) {
const skipYs = Math.ceil(renderHeight / tileSize) - 1
for (let i = 1; i <= skipYs; i++) {
skipXY.push([x, y + i])
}
}
}
g.drawImage(img, 0, 0, renderWidth, renderHeight, x, y, renderWidth, renderHeight)
const cleanName = keyValue.split('.').slice(0, -1).join('.') || keyValue
texturesIndex[cleanName] = {
u: x / imgSize,
v: y / imgSize,
...suSvOptimize === 'remove' ? {} : {
su: suSv,
sv: suSv
su: su,
sv: sv
}
}
}
@ -91,7 +116,7 @@ export function makeBlockTextureAtlas (mcAssets: McAssets) {
// const textureFiles = mostEncounteredBlocks.map(x => x + '.png')
textureFiles.unshift(...localTextures)
const { generated: additionalTextures, twoTileTextures } = getAdditionalTextures()
const { generated: additionalTextures, twoTileTextures, origSizeTextures } = getAdditionalTextures()
textureFiles.push(...Object.keys(additionalTextures))
const atlas = makeTextureAtlas(textureFiles, name => {
@ -105,6 +130,7 @@ export function makeBlockTextureAtlas (mcAssets: McAssets) {
return {
contents,
tileWidthMult: twoTileTextures.includes(name) ? 2 : undefined,
origSizeTextures
}
})
return atlas

View file

@ -0,0 +1,47 @@
{
"texture_size": [32, 32],
"textures": {
"0": "entity/decorated_pot/decorated_pot_base"
},
"elements": [
{
"name": "Body",
"from": [1, 0, 1],
"to": [15, 16, 15],
"faces": {
"north": {"uv": [0, 6.5, 7, 13.5], "texture": "#0"},
"east": {"uv": [0, 6.5, 7, 13.5], "texture": "#0"},
"south": {"uv": [0, 6.5, 7, 13.5], "texture": "#0"},
"west": {"uv": [0, 6.5, 7, 13.5], "texture": "#0"},
"up": {"uv": [7, 6.5, 14, 13.5], "texture": "#0"},
"down": {"uv": [7, 6.5, 14, 13.5], "texture": "#0"}
}
},
{
"name": "Neck",
"from": [5, 16, 5],
"to": [11, 17, 11],
"faces": {
"north": {"uv": [6, 5.5, 9, 6], "texture": "#0"},
"east": {"uv": [9, 5.5, 12, 6], "texture": "#0"},
"south": {"uv": [2.5, 5.5, 5.5, 6], "texture": "#0"},
"west": {"uv": [0, 5.5, 3, 6], "texture": "#0"},
"up": {"uv": [0, 0, 3, 3], "texture": "#0"},
"down": {"uv": [0, 0, 3, 3], "texture": "#0"}
}
},
{
"name": "Head",
"from": [4, 17, 4],
"to": [12, 20, 12],
"faces": {
"north": {"uv": [0, 4, 4, 5.5], "texture": "#0"},
"east": {"uv": [4, 4, 8, 5.5], "texture": "#0"},
"south": {"uv": [8, 4, 12, 5.5], "texture": "#0"},
"west": {"uv": [12, 4, 16, 5.5], "texture": "#0"},
"up": {"uv": [4, 0, 8, 4], "texture": "#0"},
"down": {"uv": [8, 0, 12, 4], "texture": "#0"}
}
}
]
}

View file

@ -0,0 +1,19 @@
{
"variants": {
"facing=east": {
"model": "decorated_pot",
"y": 90
},
"facing=south": {
"model": "decorated_pot",
"y": 180
},
"facing=west": {
"model": "decorated_pot",
"y": 270
},
"facing=north": {
"model": "decorated_pot"
}
}
}

View file

@ -7,6 +7,7 @@ import { fileURLToPath } from 'url'
// todo refactor
const twoTileTextures: string[] = []
const origSizeTextures: string[] = []
let currentImage: Jimp
let currentBlockName: string
let currentMcAssets: McAssets
@ -82,7 +83,7 @@ const getBlockTexturesFromJimp = async <T extends Record<string, Jimp>> (sides:
for (const [side, jimp] of Object.entries(sides)) {
const textureName = `${textureNameBase}_${side}`
const sideTexture = withUv ? { uv: [0, 0, jimp.getWidth(), jimp.getHeight()], texture: textureName } : textureName
const base64 = await jimp.getBase64Async(jimp.getMIME())
const base64Url = await jimp.getBase64Async(jimp.getMIME())
if (side === 'side') {
sidesTextures['north'] = sideTexture
sidesTextures['east'] = sideTexture
@ -91,7 +92,7 @@ const getBlockTexturesFromJimp = async <T extends Record<string, Jimp>> (sides:
} else {
sidesTextures[side] = sideTexture
}
generatedImageTextures[textureName] = base64
generatedImageTextures[textureName] = base64Url
}
return sidesTextures
@ -401,6 +402,20 @@ const handleChest = async (dataBase: string, match: RegExpExecArray) => {
currentMcAssets.blocksStates[currentBlockName] = blockStates
}
const handleDecoratedPot = async (dataBase: string, match: RegExpExecArray) => {
currentMcAssets.blocksStates[currentBlockName] = JSON.parse(fs.readFileSync(path.join(__dirname, 'blockStates/decorated_pot.json'), 'utf-8'))
const blockModel = JSON.parse(fs.readFileSync(path.join(__dirname, 'blockModels/decorated_pot.json'), 'utf-8'))
currentImage = await Jimp.read(dataBase + `entity/decorated_pot/decorated_pot_base.png`)
// resize from 32x32 to 16x16 without cropping the image
// const baseBase64 = await currentImage.clone().resize(16, 16).getBase64Async(Jimp.MIME_PNG)
// const baseBase64 = await currentImage.getBase64Async(Jimp.MIME_PNG)
blockModel.textures.particle = 'flower_pot'
generatedImageTextures['decorated_pot_base'] = `data:image/png;base64,${fs.readFileSync(path.join(dataBase, 'entity/decorated_pot/decorated_pot_base.png'), 'base64')}`
// generatedImageTextures['decorated_pot_base'] = baseBase64
origSizeTextures['decorated_pot_base'] = true
currentMcAssets.blocksModels[currentBlockName] = blockModel
}
const handlers = [
[/(.+)_shulker_box$/, handleShulkerBox],
[/^shulker_box$/, handleShulkerBox],
@ -410,6 +425,7 @@ const handlers = [
[/(.+)_wall_sign$/, handleSign],
[/(.+)_sign$/, handleSign],
[/^(?:(ender|trapped)_)?chest$/, handleChest],
[/^decorated_pot$/, handleDecoratedPot],
// [/(^|(.+)_)bed$/, handleBed],
// no-op just suppress warning
[/(^light|^moving_piston$)/, true],
@ -462,5 +478,5 @@ export const prepareMoreGeneratedBlocks = async (mcAssets: McAssets) => {
}
export const getAdditionalTextures = () => {
return { generated: generatedImageTextures, twoTileTextures }
return { generated: generatedImageTextures, twoTileTextures, origSizeTextures }
}