diff --git a/src/render/BlockModel.ts b/src/render/BlockModel.ts index 3b19eb7..41774b6 100644 --- a/src/render/BlockModel.ts +++ b/src/render/BlockModel.ts @@ -21,7 +21,7 @@ type BlockModelFace = { tintindex?: number, } -type BlockModelElement = { +export type BlockModelElement = { from: number[], to: number[], rotation?: { diff --git a/src/render/SpecialModel.ts b/src/render/SpecialModel.ts index 9fd1ffb..bee39dd 100644 --- a/src/render/SpecialModel.ts +++ b/src/render/SpecialModel.ts @@ -1,6 +1,6 @@ import { mat4 } from 'gl-matrix' import type { Direction, ItemStack, NbtCompound, TextureAtlasProvider } from '../index.js' -import { Identifier, Json, NbtList, SpecialRenderers } from '../index.js' +import { Identifier, Json, NbtList, NbtType, SpecialRenderers } from '../index.js' import { Mesh } from './Mesh.js' export interface SpecialModel { @@ -80,12 +80,15 @@ export namespace SpecialModel { public getMesh(item: ItemStack, resources: TextureAtlasProvider): Mesh { const patterns = item.getComponent('banner_patterns', undefined) + const patternList = patterns?.isList() && patterns.getType() === NbtType.Compound + ? (patterns as NbtList) + : undefined const t = mat4.create() mat4.translate(t, t, [8, 24, 8]) mat4.rotateY(t, t, Math.PI) mat4.scale(t, t, [2/3, 2/3, 2/3]) mat4.translate(t, t, [-8, -24, -8]) - return this.renderer(resources, patterns instanceof NbtList ? patterns : undefined).transform(t) + return this.renderer(resources, patternList).transform(t) } } @@ -148,7 +151,29 @@ export namespace SpecialModel { class Shield implements SpecialModel { public getMesh(item: ItemStack, resources: TextureAtlasProvider): Mesh { - const shieldMesh = SpecialRenderers.shieldRenderer(resources) + const layers: { color: string; pattern: string }[] = [] + const bannerPatterns = item.getComponent('banner_patterns', undefined) + const patternList = bannerPatterns?.isList() && bannerPatterns.getType() === NbtType.Compound + ? (bannerPatterns as NbtList) + : undefined + let baseColor = item.getComponent('base_color', undefined)?.getAsString() + if (!baseColor && (patternList?.length ?? 0) > 0) { + baseColor = 'white' + } + if (baseColor) { + layers.push({ + color: baseColor, + pattern: 'base', + }) + patternList?.forEach((compound) => { + layers.push({ + pattern: Identifier.parse(compound.getString('pattern')).path, + color: compound.getString('color'), + }) + }) + } + + const shieldMesh = SpecialRenderers.shieldRenderer(resources, layers) const t = mat4.create() mat4.translate(t, t, [-3, 1, 0]) mat4.rotateX(t, t, -10 * Math.PI/180) diff --git a/src/render/SpecialRenderer.ts b/src/render/SpecialRenderer.ts index ab1ddb7..0d0b1cd 100644 --- a/src/render/SpecialRenderer.ts +++ b/src/render/SpecialRenderer.ts @@ -5,7 +5,7 @@ import type { NbtCompound, NbtList } from '../nbt/index.js' import { NbtType } from '../nbt/index.js' import { Color } from '../util/index.js' import { BlockColors } from './BlockColors.js' -import { BlockModel } from './BlockModel.js' +import { BlockModel, BlockModelElement } from './BlockModel.js' import { Cull } from './Cull.js' import { Mesh } from './Mesh.js' import type { TextureAtlasProvider } from './TextureAtlas.js' @@ -136,23 +136,42 @@ export namespace SpecialRenderers { ]).getMesh(atlas, Cull.none()) } - export function shieldRenderer(atlas: TextureAtlasProvider) { - return new BlockModel(undefined, { - 0: 'entity/shield_base_nopattern', - }, [ + const shieldFace = (index: number): BlockModelElement['faces'] => ({ + south: {uv: [0.5, 0.5, 3, 5.5], texture: `#${index}`, tintindex: index}, + }) + + export function shieldRenderer(atlas: TextureAtlasProvider, layers: { color: string; pattern: string }[]) { + const patternFn = (index: number): BlockModelElement => ({ + from: [-5, -10, -0.99], + to: [5, 10, -0.99], + faces: shieldFace(index), + }) + + const textures: Record = { 0: 'entity/shield/shield_base_nopattern' } + const elements: BlockModelElement[] = [ { - from: [-6, -11, -2], - to: [6, 11, -1], - faces: { - north: {uv: [3.5, 0.25, 6.5, 5.75], texture: '#0'}, - east: {uv: [3.25, 0.25, 3.5, 5.75], texture: '#0'}, - south: {uv: [0.25, 0.25, 3.25, 5.75], texture: '#0'}, - west: {uv: [0, 0.25, 0.25, 5.75], texture: '#0'}, - up: {uv: [0.25, 0, 3.25, 0.25], texture: '#0'}, - down: {uv: [3.25, 0, 6.25, 0.25], texture: '#0'}, + from: [-6, -11, -2], + to: [6, 11, -1], + faces: { + north: {uv: [3.5, 0.25, 6.5, 5.75], texture: '#0'}, + east: {uv: [3.25, 0.25, 3.5, 5.75], texture: '#0'}, + south: {uv: [0.25, 0.25, 3.25, 5.75], texture: '#0'}, + west: {uv: [0, 0.25, 0.25, 5.75], texture: '#0'}, + up: {uv: [0.25, 0, 3.25, 0.25], texture: '#0'}, + down: {uv: [3.25, 0, 6.25, 0.25], texture: '#0'}, }, - }, - ]).getMesh(atlas, Cull.none()) + } + ] + const tints: string[] = [''] + + layers?.forEach((layer, index) => { + textures[index + 1] = `entity/shield/${layer.pattern}` + elements.push(patternFn(index + 1)) + tints.push(layer.color) + }) + + return new BlockModel(undefined, textures, elements) + .getMesh(atlas, Cull.none(), (index: number) => DyeColors[tints[index] ?? ''] ?? [1, 1, 1]) } export function headRenderer(texture: Identifier, n: number) { @@ -628,7 +647,7 @@ export namespace SpecialRenderers { function createBannerRenderer(color: string, config: { base: any[], pattern: (index: number) => any }) { return (atlas: TextureAtlasProvider, patterns?: NbtList) => { - const textures: { [key: string]: string } = { 0: 'entity/banner_base' } + const textures: { [key: string]: string } = { 0: 'entity/banner/banner_base' } const elements = [...config.base] const colors: string[] = [color] @@ -869,6 +888,7 @@ export namespace SpecialRenderers { 'dark_oak', 'mangrove', 'cherry', + 'pale_oak', 'bamboo', 'crimson', 'warped', @@ -970,7 +990,6 @@ export namespace SpecialRenderers { const t = mat4.create() mat4.translate(t, t, [8, 8, 8]) mat4.rotateY(t, t, rotation) - mat4.scale(t, t, [2/3, 2/3, 2/3]) mat4.translate(t, t, [-8, -8, -8]) mesh.merge(hangingSignRenderer(attached, atlas).transform(t)) }