From 78873d0a27bf80c76a83ba1f3ac7d85a30083b5c Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Tue, 22 Sep 2026 11:52:55 +0800 Subject: [PATCH] refactor(04-07): adapt material interfaces (drop big-image, inject state) - delete MaterialManager big-image implementation (IBigImageReturn import, bigImageStore/bigImageData/bigImageId fields, 5 methods, setDefaultFrame coupling) - change 7 consumers getIfBigImage -> getTile (door x2, hero x3, renderer, vertex); drop getOffsetPool big-image offset loop - delete cache.ts legacy big-image path (RenderableDataBase.bigImage, literals, destructuring, enemys special-case, big-image branch, unused enemys decl) - inject state via constructor into MaterialManager/AutotileProcessor/AssetBuilder/TrackedAssetData (from ClientCore; renderer uses manager.state) - add MaterialManager.textures (dedicated TextureStore) - declare @user/data-state in client-base/package.json (lockfile not synced) --- packages-user/client-base/package.json | 3 +- .../client-base/src/material/autotile.ts | 6 +- .../client-base/src/material/builder.ts | 11 +++- .../client-base/src/material/manager.ts | 59 ++----------------- packages-user/client-modules/src/client.ts | 4 +- .../src/render/elements/cache.ts | 53 +---------------- .../src/render/map/extension/door.ts | 4 +- .../src/render/map/extension/hero.ts | 8 +-- .../client-modules/src/render/map/renderer.ts | 11 +--- .../client-modules/src/render/map/vertex.ts | 2 +- 10 files changed, 31 insertions(+), 130 deletions(-) diff --git a/packages-user/client-base/package.json b/packages-user/client-base/package.json index c0e203d..78a0c8b 100644 --- a/packages-user/client-base/package.json +++ b/packages-user/client-base/package.json @@ -4,6 +4,7 @@ "@motajs/audio": "workspace:*", "@motajs/render": "workspace:*", "@motajs/client-base": "workspace:*", - "@user/data-base": "workspace:*" + "@user/data-base": "workspace:*", + "@user/data-state": "workspace:*" } } diff --git a/packages-user/client-base/src/material/autotile.ts b/packages-user/client-base/src/material/autotile.ts index f4d0042..a0e9358 100644 --- a/packages-user/client-base/src/material/autotile.ts +++ b/packages-user/client-base/src/material/autotile.ts @@ -12,6 +12,7 @@ import { IMaterialFramedData, ITextureManager } from './types'; +import { ICoreState } from '@user/data-state'; import { isNil } from 'lodash-es'; interface ConnectedAutotile { @@ -45,7 +46,10 @@ export class AutotileProcessor implements IAutotileProcessor { /** 自动元件父子关系映射,父元件 -> 子元件列表 */ readonly childMap: Map> = new Map(); - constructor(readonly manager: ITextureManager) {} + constructor( + readonly manager: ITextureManager, + readonly state: ICoreState + ) {} private ensureChildSet(num: number) { const set = this.childMap.get(num); diff --git a/packages-user/client-base/src/material/builder.ts b/packages-user/client-base/src/material/builder.ts index 3797688..41df693 100644 --- a/packages-user/client-base/src/material/builder.ts +++ b/packages-user/client-base/src/material/builder.ts @@ -7,6 +7,7 @@ import { SizedCanvasImageSource } from '@motajs/render'; import { IAssetBuilder, ITextureGetter, ITrackedAssetData } from './types'; +import { ICoreState } from '@user/data-state'; import { logger, PrivateListDirtyTracker } from '@motajs/common'; export class AssetBuilder implements IAssetBuilder { @@ -24,8 +25,11 @@ export class AssetBuilder implements IAssetBuilder { /** 贴图更新的 promise */ private pending: Promise = Promise.resolve(); - constructor(readonly materials: ITextureGetter) { - this.trackedData = new TrackedAssetData(materials, this); + constructor( + readonly materials: ITextureGetter, + readonly state: ICoreState + ) { + this.trackedData = new TrackedAssetData(materials, this, state); } pipe(store: ITextureStore): void { @@ -109,7 +113,8 @@ class TrackedAssetData constructor( readonly materials: ITextureGetter, - readonly builder: AssetBuilder + readonly builder: AssetBuilder, + readonly state: ICoreState ) { super(0); } diff --git a/packages-user/client-base/src/material/manager.ts b/packages-user/client-base/src/material/manager.ts index 3062323..f49aaf4 100644 --- a/packages-user/client-base/src/material/manager.ts +++ b/packages-user/client-base/src/material/manager.ts @@ -17,11 +17,11 @@ import { IIndexedIdentifier, IMaterialAssetData, BlockCls, - IBigImageReturn, IAssetBuilder, IMaterialFramedData, ITrackedAssetData } from './types'; +import { ICoreState } from '@user/data-state'; import { logger } from '@motajs/common'; import { getClsByString, getTextureFrame } from './utils'; import { isNil } from 'lodash-es'; @@ -40,7 +40,7 @@ export class MaterialManager implements ITextureManager { readonly tilesetStore: ITextureStore = new TextureStore(); readonly imageStore: ITextureStore = new TextureStore(); readonly assetStore: ITextureStore = new TextureStore(); - readonly bigImageStore: ITextureStore = new TextureStore(); + readonly textures: ITextureStore = new TextureStore(); /** 自动元件图像源映射 */ readonly autotileSource: Map = new Map(); @@ -52,8 +52,6 @@ export class MaterialManager implements ITextureManager { /** 带有脏标记追踪的图集对象 */ readonly trackedAsset: ITrackedAssetData; - /** 大怪物数据 */ - readonly bigImageData: Map = new Map(); /** tileset 中 `Math.floor(id / 10000) + 1` 映射到 tileset 对应索引的映射,用于处理图块超出 10000 的 tileset */ readonly tilesetOffsetMap: Map = new Map(); /** 图集打包器 */ @@ -73,8 +71,6 @@ export class MaterialManager implements ITextureManager { /** 行切分器 */ readonly rowSplitter: TextureRowSplitter = new TextureRowSplitter(); - /** 大怪物贴图的标识符 */ - private bigImageId: number = 0; /** 当前 tileset 索引 */ private nowTilesetIndex: number = -1; /** 当前 tileset 偏移 */ @@ -82,8 +78,8 @@ export class MaterialManager implements ITextureManager { /** 是否已经构建过素材 */ private built: boolean = false; - constructor() { - this.assetBuilder = new AssetBuilder(this); + constructor(readonly state: ICoreState) { + this.assetBuilder = new AssetBuilder(this, state); this.assetBuilder.pipe(this.assetStore); this.trackedAsset = this.assetBuilder.tracked(); } @@ -230,10 +226,6 @@ export class MaterialManager implements ITextureManager { setDefaultFrame(identifier: number, defaultFrame: number): void { this.defaultFrames.set(identifier, defaultFrame); - const bigImageData = this.bigImageData.get(identifier); - if (bigImageData) { - bigImageData.defaultFrame = defaultFrame; - } } getDefaultFrame(identifier: number): number { @@ -549,49 +541,6 @@ export class MaterialManager implements ITextureManager { return this.numIdMap.get(identifier); } - setBigImage( - identifier: number, - image: ITexture, - frames: number - ): IBigImageReturn { - const bigImageId = this.bigImageId++; - this.bigImageStore.addTexture(bigImageId, image); - const cls = this.clsMap.get(identifier) ?? BlockCls.Unknown; - const store: IMaterialFramedData = { - texture: image, - cls, - offset: image.width / 4, - frames, - defaultFrame: this.defaultFrames.get(identifier) ?? -1 - }; - this.bigImageData.set(identifier, store); - const data: IBigImageReturn = { - identifier: bigImageId, - store: this.bigImageStore - }; - return data; - } - - isBigImage(identifier: number): boolean { - return this.bigImageData.has(identifier); - } - - getBigImage(identifier: number): Readonly | null { - return this.bigImageData.get(identifier) ?? null; - } - - getBigImageByAlias(alias: string): Readonly | null { - const identifier = this.idNumMap.get(alias); - if (isNil(identifier)) return null; - return this.bigImageData.get(identifier) ?? null; - } - - getIfBigImage(identifier: number): Readonly | null { - const bigImage = this.bigImageData.get(identifier); - if (bigImage) return bigImage; - else return this.getTile(identifier); - } - assetContainsTexture(texture: ITexture): boolean { return this.trackedAsset.skipRef.has(texture.source); } diff --git a/packages-user/client-modules/src/client.ts b/packages-user/client-modules/src/client.ts index ab97dc0..b70bdfe 100644 --- a/packages-user/client-modules/src/client.ts +++ b/packages-user/client-modules/src/client.ts @@ -81,8 +81,8 @@ export class ClientCore extends CoreState implements IClientCore { //#region 素材系统 - this.materials = new MaterialManager(); - this.autotile = new AutotileProcessor(this.materials); + this.materials = new MaterialManager(this); + this.autotile = new AutotileProcessor(this.materials, this); //#endregion diff --git a/packages-user/client-modules/src/render/elements/cache.ts b/packages-user/client-modules/src/render/elements/cache.ts index 8c57e2c..e81b3c8 100644 --- a/packages-user/client-modules/src/render/elements/cache.ts +++ b/packages-user/client-modules/src/render/elements/cache.ts @@ -32,8 +32,6 @@ interface RenderableDataBase { frame: number; /** 对应图块属性的动画帧数,-1表示没有设定,0表示第一帧 */ animate: number; - /** 是否是大怪物 */ - bigImage: boolean; render: [x: number, y: number, width: number, height: number][]; } @@ -45,7 +43,6 @@ export interface RenderableData extends RenderableDataBase { export interface AutotileRenderable extends RenderableDataBase { image: Record; autotile: true; - bigImage: false; } class TextureCache { @@ -124,7 +121,6 @@ class TextureCache { num: number ): RenderableData | AutotileRenderable | null { const map = maps_90f36752_8815_4be8_b32b_d7fad1d0542e; - const enemys = enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80; const icons = icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1; /** 特判空图块与空气墙 */ @@ -140,8 +136,7 @@ class TextureCache { frame: 1, render: [[x * 32, y * 32, 32, 32]], animate: 0, - autotile: false, - bigImage: false + autotile: false }; this.renderable.set(num, data); return data; @@ -150,48 +145,7 @@ class TextureCache { const data = map[num as Exclude]; // 地狱般的分支if if (data) { - let { faceIds, bigImage } = data; const { cls, id, animate } = data; - if (cls === 'enemys' || cls === 'enemy48') { - // 怪物需要特殊处理,因为它的大怪物信息不在 maps 里面 - ({ bigImage, faceIds } = enemys[id as EnemyIds]); - } - if (bigImage) { - const image = core.material.images.images[bigImage]; - if (!image) { - logger.warn(10, id); - return null; - } - let line = 0; - if (faceIds) { - const arr = ['down', 'left', 'right', 'up']; - for (let i = 0; i < arr.length; i++) { - if (faceIds[arr[i] as Dir] === id) { - line = i; - break; - } - } - } - const totalLines = image.width / image.height >= 2 ? 1 : 4; - const w = Math.round(image.width / 4); - const h = Math.round(image.height / totalLines); - const y = h * line; - const data: RenderableData = { - image, - frame: 4, - render: [ - [0, y, w, h], - [w, y, w, h], - [w * 2, y, w, h], - [w * 3, y, w, h] - ], - animate: (animate ?? 0) - 1, - autotile: false, - bigImage: true - }; - this.renderable.set(num, data); - return data; - } // enemy48和npc48都应该视为大怪物 if (cls === 'enemy48' || cls === 'npc48') { const img = core.material.images[cls]; @@ -211,8 +165,7 @@ class TextureCache { [w * 3, y, w, h] ], animate: (animate ?? 0) - 1, - autotile: false, - bigImage: true + autotile: false }; this.renderable.set(num, data); return data; @@ -240,7 +193,6 @@ class TextureCache { frame: auto.frame, render, autotile: true, - bigImage: false, animate: (animate ?? 0) - 1 }; this.renderable.set(num, data); @@ -273,7 +225,6 @@ class TextureCache { frame: frame, render, autotile: false, - bigImage: false, animate: (animate ?? 0) - 1 }; this.renderable.set(num, data); diff --git a/packages-user/client-modules/src/render/map/extension/door.ts b/packages-user/client-modules/src/render/map/extension/door.ts index 7420ddc..8b76892 100644 --- a/packages-user/client-modules/src/render/map/extension/door.ts +++ b/packages-user/client-modules/src/render/map/extension/door.ts @@ -33,7 +33,7 @@ export class MapDoorRenderer implements IMapDoorRenderer { const array = this.layer.getMapRef().array; const index = y * this.layer.width + x; const num = array[index]; - const data = this.renderer.manager.getIfBigImage(num); + const data = this.renderer.manager.getTile(num); if (!data) return; const frames = data.frames; for (let i = 0; i < frames; i++) { @@ -43,7 +43,7 @@ export class MapDoorRenderer implements IMapDoorRenderer { } async closeDoor(num: number, x: number, y: number): Promise { - const data = this.renderer.manager.getIfBigImage(num); + const data = this.renderer.manager.getTile(num); if (!data) return; const moving = this.renderer.addMovingBlock(this.layer, num, x, y); const frames = data.frames; diff --git a/packages-user/client-modules/src/render/map/extension/hero.ts b/packages-user/client-modules/src/render/map/extension/hero.ts index cec2a6f..0cd69f5 100644 --- a/packages-user/client-modules/src/render/map/extension/hero.ts +++ b/packages-user/client-modules/src/render/map/extension/hero.ts @@ -236,7 +236,7 @@ export class MapHeroRenderer implements IMapHeroRenderer { const tx = block.x + dx; const ty = block.y + dy; const nextTile = state.roleFace.getFaceOf(block.tile, direction); - const nextTex = this.renderer.manager.getIfBigImage( + const nextTex = this.renderer.manager.getTile( nextTile?.identifier ?? block.tile ); entity.animateInterval = time; @@ -361,7 +361,7 @@ export class MapHeroRenderer implements IMapHeroRenderer { const nowFace = degraded === FaceDirection.Unknown ? FaceDirection.Down : degraded; const faced = state.roleFace.getFaceOf(image, nowFace); - const tex = this.renderer.manager.getIfBigImage(faced?.face ?? image); + const tex = this.renderer.manager.getTile(faced?.face ?? image); if (!tex) { logger.warn(91, image.toString()); return; @@ -425,9 +425,7 @@ export class MapHeroRenderer implements IMapHeroRenderer { last.nextDirection ); if (!nextFace) continue; - const tile = this.renderer.manager.getIfBigImage( - nextFace.identifier - ); + const tile = this.renderer.manager.getTile(nextFace.identifier); if (!tile) continue; moving.block.setTexture(tile); moving.direction = last.nextDirection; diff --git a/packages-user/client-modules/src/render/map/renderer.ts b/packages-user/client-modules/src/render/map/renderer.ts index 5850edf..4a879b6 100644 --- a/packages-user/client-modules/src/render/map/renderer.ts +++ b/packages-user/client-modules/src/render/map/renderer.ts @@ -231,7 +231,7 @@ export class MapRenderer ); this.contextData = data; this.vertex = new MapVertexGenerator(this, data); - this.autotile = new AutotileProcessor(manager); + this.autotile = new AutotileProcessor(manager, manager.state); this.tick = this.tick.bind(this); this.viewport = new MapViewport(this); this.tileAnimater = new TextureColumnAnimater(); @@ -648,13 +648,6 @@ export class MapRenderer private getOffsetPool(): number[] { const pool = new Set([32]); - // 其他的都是 bigImage 了,直接遍历获取 - for (const identifier of this.manager.bigImageStore.keys()) { - const data = this.manager.getBigImage(identifier); - if (!data) continue; - const offset = data.texture.width / data.frames; - pool.add(offset); - } // 还有勇士图片 for (const tex of this.manager.imageStore.values()) { if (!this.manager.assetContainsTexture(tex)) continue; @@ -1247,7 +1240,7 @@ export class MapRenderer tile: number ): Promise { // 图块背景 - const tex = this.manager.getIfBigImage(tile); + const tex = this.manager.getTile(tile); if (!tex) { // 图块不存在 logger.error(35); diff --git a/packages-user/client-modules/src/render/map/vertex.ts b/packages-user/client-modules/src/render/map/vertex.ts index a8ca1af..85ff489 100644 --- a/packages-user/client-modules/src/render/map/vertex.ts +++ b/packages-user/client-modules/src/render/map/vertex.ts @@ -543,7 +543,7 @@ export class MapVertexGenerator ) { // 此处仅更新当前图块,不更新周围一圈的自动元件 // 周围一圈的自动元件需要在更新某个图块或者某个区域时处理,不在这里处理 - const tile = this.renderer.manager.getIfBigImage(num); + const tile = this.renderer.manager.getTile(num); if (!tile) { // 不存在可渲染对象,认为是空图块