| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- // 图片文件读取模块
- // 负责处理所有图片文件相关的逻辑
- const fs = require('fs');
- const path = require('path');
- class TextureReader {
- constructor(serverDir) {
- this.serverDir = serverDir;
- this.sequencesPath = path.join(serverDir, 'disk_data');
- }
- /**
- * 获取可用的文件夹列表
- * @returns {Promise<string[]>} 文件夹名称数组
- */
- async getAvailableFolders() {
- return new Promise((resolve, reject) => {
- // 检查目录是否存在
- fs.access(this.sequencesPath, fs.constants.F_OK, (accessErr) => {
- if (accessErr) {
- // 目录不存在,返回空数组而不是错误
- console.log(`[TextureReader] 目录不存在: ${this.sequencesPath},返回空列表`);
- resolve([]);
- return;
- }
-
- fs.readdir(this.sequencesPath, { withFileTypes: true }, (err, files) => {
- if (err) {
- // 读取失败,返回空数组而不是错误
- console.error(`[TextureReader] 读取目录失败: ${this.sequencesPath}`, err);
- resolve([]);
- return;
- }
-
- const folders = files
- .filter(dirent => dirent.isDirectory() && dirent.name.startsWith('player_'))
- .map(dirent => dirent.name)
- .sort();
-
- resolve(folders);
- });
- });
- });
- }
- /**
- * 获取指定文件夹中的帧文件列表
- * @param {string} folderName - 文件夹名称
- * @returns {Promise<{frames: number[], maxFrame: number}>} 帧文件信息
- */
- async getFrameFiles(folderName) {
- return new Promise((resolve, reject) => {
- // 处理URL编码和空格
- const decodedFolderName = decodeURIComponent(folderName).replace(/%20/g, ' ');
- const folderPath = path.join(this.sequencesPath, decodedFolderName);
-
- console.log(`[TextureReader] 请求帧列表: folderName=${folderName}, decoded=${decodedFolderName}, folderPath=${folderPath}`);
-
- // 检查目录是否存在
- fs.access(folderPath, fs.constants.F_OK, (accessErr) => {
- if (accessErr) {
- console.error(`[TextureReader] 文件夹不存在: ${folderPath}`);
- reject(new Error('Folder not found'));
- return;
- }
-
- fs.readdir(folderPath, (err, files) => {
- if (err) {
- console.error(`[TextureReader] 读取文件夹失败: ${err.message}, folderPath=${folderPath}`);
- reject(err);
- return;
- }
-
- // 过滤出 PNG 文件,并按数字排序
- // 支持两种格式:1) 纯数字.png (如 00.png) 2) 任意名称+数字.png (如 动画00.png)
- const pngFiles = files
- .filter(file => file.toLowerCase().endsWith('.png'))
- .map(file => {
- let frameNum = null;
- // 先尝试匹配纯数字格式:00.png, 01.png
- let match = /^(\d+)\.png$/i.exec(file);
- if (match) {
- frameNum = parseInt(match[1], 10);
- } else {
- // 再尝试匹配文件名末尾的数字格式:动画00.png, 生成白色背景长矛刺击动画00.png
- match = /(\d+)\.png$/i.exec(file);
- if (match) {
- frameNum = parseInt(match[1], 10);
- }
- }
-
- if (frameNum !== null) {
- return {
- frameNum: frameNum,
- fileName: file
- };
- }
- return null;
- })
- .filter(item => item !== null)
- .sort((a, b) => a.frameNum - b.frameNum);
-
- const result = {
- frames: pngFiles.map(item => item.frameNum),
- fileNames: pngFiles.map(item => item.fileName),
- maxFrame: pngFiles.length > 0 ? Math.max(...pngFiles.map(item => item.frameNum)) : 0
- };
-
- resolve(result);
- });
- });
- });
- }
- /**
- * 处理获取文件夹列表的 API 请求
- * @param {http.ServerResponse} res - HTTP 响应对象
- */
- handleGetFolders(res) {
- this.getAvailableFolders()
- .then(folders => {
- res.writeHead(200, { 'Content-Type': 'application/json' });
- res.end(JSON.stringify(folders));
- })
- .catch(err => {
- res.writeHead(500, { 'Content-Type': 'application/json' });
- res.end(JSON.stringify({ error: 'Failed to read sequences directory', details: err.message }));
- });
- }
- /**
- * 处理获取帧文件列表的 API 请求
- * @param {string} folderName - 文件夹名称
- * @param {http.ServerResponse} res - HTTP 响应对象
- */
- handleGetFrames(folderName, res) {
- this.getFrameFiles(folderName)
- .then(result => {
- // 检查是否有图片
- if (!result.frames || result.frames.length === 0) {
- res.writeHead(400, { 'Content-Type': 'application/json' });
- res.end(JSON.stringify({
- error: '该文件夹中没有图片',
- frames: []
- }));
- return;
- }
-
- res.writeHead(200, { 'Content-Type': 'application/json' });
- res.end(JSON.stringify(result));
- })
- .catch(err => {
- res.writeHead(404, { 'Content-Type': 'application/json' });
- res.end(JSON.stringify({ error: 'Folder not found', details: err.message }));
- });
- }
- }
- module.exports = TextureReader;
|