maps.ts•2.22 kB
import { existsSync, readdirSync } from 'fs';
import { join } from 'path';
import { readDVPLFile } from '../dvpl/reader.js';
import { decodeDDS } from '../decoders/dds.js';
import type { Config } from '../config.js';
export interface MapImage {
data: string;
mimeType: 'image/png';
width: number;
height: number;
}
let maps3dPath = '';
const VALID_MAP_TAG = /^[a-zA-Z0-9_-]+$/;
export function initMapImages(config: Config): void {
maps3dPath = config.paths.maps3d;
}
function findColormap(mapTag: string): string | null {
if (!VALID_MAP_TAG.test(mapTag)) return null;
const tagParts = mapTag.split('_');
const possibleFolders = [
mapTag,
`${tagParts.slice(0, 2).join('_')}_${tagParts.slice(-1)[0]}`,
];
for (const folder of possibleFolders) {
if (!VALID_MAP_TAG.test(folder)) continue;
const landscapePath = join(maps3dPath, folder, 'landscape');
if (!existsSync(landscapePath)) continue;
const files = readdirSync(landscapePath);
for (const file of files) {
if (file.endsWith('_colormap.dx11.dds.dvpl')) {
return join(landscapePath, file);
}
}
}
if (!existsSync(maps3dPath)) return null;
const entries = readdirSync(maps3dPath);
const tagLower = mapTag.toLowerCase();
for (const entry of entries) {
if (!VALID_MAP_TAG.test(entry)) continue;
if (!entry.toLowerCase().includes(tagLower.split('_').slice(-1)[0])) continue;
const landscapePath = join(maps3dPath, entry, 'landscape');
if (!existsSync(landscapePath)) continue;
const files = readdirSync(landscapePath);
for (const file of files) {
if (file.endsWith('_colormap.dx11.dds.dvpl')) {
return join(landscapePath, file);
}
}
}
return null;
}
export async function loadMapImage(mapTag: string): Promise<MapImage | null> {
const path = findColormap(mapTag);
if (!path) return null;
const ddsBuffer = await readDVPLFile(path.replace('.dvpl', ''));
const pngBuffer = await decodeDDS(ddsBuffer);
return {
data: pngBuffer.toString('base64'),
mimeType: 'image/png',
width: 2048,
height: 2048,
};
}
export function hasMapImage(mapTag: string): boolean {
return findColormap(mapTag) !== null;
}