文件系统
文件系统介绍
详情请见文件系统概览
文件系统管理
1. 注入文件系统路径映射规则
通过 injectFileSystemRule 注入对应协议名的文件路径映射。
接口原型
gameHandle.injectFileSystemRule(maskPath, realPath)
参数说明
| 参数 | 数据类型 | 必填 | 属性说明 |
|---|---|---|---|
maskPath | String | 是 | 虚拟路径协议名 |
realPath | String | 是 | 实际文件路径 |
返回值
返回 Promise<void>
代码示例
// Inject new file system rule
// The implementation uses string replacement internally.
// When you need to add a mapping between a virtual path and a real path, use this method.
// Built-in conversion rules:
// 1. tjfile://usr/ -> <host user data path>/fs/usr
// 2. tjfile://save_ -> <host user data path>/fs/store
// 3. tjfile://tmp_ -> <host temp file path>/fs
// Example:
// maskPath: tjfile://usr/
// realPath: /Users/username/Library/Application Support/myapp/userid/appid/
await gameHandle.injectFileSystemRule('tjfile://usr/', '/path/to/user/data/');
// After injection, convertRealPathToMaskPath will return tjfile://usr/
const maskPath = gameHandle.convertRealPathToMaskPath('/path/to/user/data/');
console.log('Mask path:', maskPath); // tjfile://usr/
使用场景
const path = require('path');
const os = require('os');
async function setupCustomFileSystem(gameHandle) {
// Define custom file system paths
const appDataPath = path.join(os.homedir(), '.myapp', 'data');
const cachePath = path.join(os.homedir(), '.myapp', 'cache');
const logPath = path.join(os.homedir(), '.myapp', 'logs');
// Inject custom rules
await gameHandle.injectFileSystemRule('myapp://data/', appDataPath);
await gameHandle.injectFileSystemRule('myapp://cache/', cachePath);
await gameHandle.injectFileSystemRule('myapp://logs/', logPath);
console.log('Custom file system rules injected');
}
2. 真实路径转虚拟路径
将真实文件系统路径转换为虚拟路径(协议路径)。
接口原型
gameHandle.convertRealPathToMaskPath(realPath)
参数说明
| 参数 | 数据类型 | 必填 | 属性说明 |
|---|---|---|---|
realPath | String | 是 | 真实文件路径 |
返回值
返回 String - 虚拟路径(协议路径)
代码示例
// Convert real path to mask path
const realPath = '/Users/username/Library/Application Support/myapp/userid/appid/data.json';
const maskPath = gameHandle.convertRealPathToMaskPath(realPath);
console.log('Real path:', realPath);
console.log('Mask path:', maskPath); // e.g., tjfile://usr/data.json
3. 虚拟路径转真实路径
将虚拟路径(协议路径)转换为真实文件系统路径。
接口原型
gameHandle.convertMaskPathToRealPath(maskPath)
参数说明
| 参数 | 数据类型 | 必填 | 属性说明 |
|---|---|---|---|
maskPath | String | 是 | 虚拟路径协议路径 |
返回值
返回 String - 真实文件路径
代码示例
// Convert mask path to real path
const maskPath = 'tjfile://usr/data.json';
const realPath = gameHandle.convertMaskPathToRealPath(maskPath);
console.log('Mask path:', maskPath);
console.log('Real path:', realPath); // e.g., /Users/username/Library/Application Support/myapp/userid/appid/data.json
文件系统路径规则
默认路径映射
PC 版本默认注册以下转换规则:
| 虚拟路径前缀 | 真实路径 | 说明 |
|---|---|---|
tjfile://usr/ | <用户数据路径>/fs/usr | 用户数据目录 |
tjfile://save_ | <用户数据路径>/fs/store | 存档目录 |
tjfile://tmp_ | <临时文件路径>/fs | 临时文件目录 |
路径示例
macOS:
用户数据路径: /Users/username/Library/Application Support/WebGLHost/userid/appid/
临时文件路径: /Users/username/Library/Caches/WebGLHost/userid/appid/
Windows:
用户数据路径: C:\Users\username\AppData\Roaming\WebGLHost\userid\appid\
临时文件路径: C:\Users\username\AppData\Local\Temp\WebGLHost\userid\appid\
完整示例
const { TJHostHandle } = require('webglhost-runtime-pc');
const path = require('path');
const os = require('os');
const fs = require('fs').promises;
class FileSystemManager {
constructor() {
this.gameHandle = null;
}
async initialize(gameHandle) {
this.gameHandle = gameHandle;
await this.setupCustomPaths();
}
async setupCustomPaths() {
// Define custom application paths
const appName = 'MyGame';
const baseDir = path.join(os.homedir(), `.${appName.toLowerCase()}`);
const paths = {
data: path.join(baseDir, 'data'),
save: path.join(baseDir, 'save'),
cache: path.join(baseDir, 'cache'),
logs: path.join(baseDir, 'logs'),
config: path.join(baseDir, 'config')
};
// Create directories if they don't exist
for (const [key, dirPath] of Object.entries(paths)) {
await fs.mkdir(dirPath, { recursive: true });
console.log(`Created directory: ${dirPath}`);
}
// Inject custom file system rules
await this.gameHandle.injectFileSystemRule('game://data/', paths.data);
await this.gameHandle.injectFileSystemRule('game://save/', paths.save);
await this.gameHandle.injectFileSystemRule('game://cache/', paths.cache);
await this.gameHandle.injectFileSystemRule('game://logs/', paths.logs);
await this.gameHandle.injectFileSystemRule('game://config/', paths.config);
console.log('File system rules injected successfully');
}
// Test path conversions
testPathConversions() {
// Test real path to mask path
const realDataPath = path.join(os.homedir(), '.mygame', 'data', 'player.json');
const maskDataPath = this.gameHandle.convertRealPathToMaskPath(realDataPath);
console.log('Real -> Mask:', realDataPath, '->', maskDataPath);
// Test mask path to real path
const maskSavePath = 'game://save/slot1.dat';
const realSavePath = this.gameHandle.convertMaskPathToRealPath(maskSavePath);
console.log('Mask -> Real:', maskSavePath, '->', realSavePath);
// Test built-in tjfile paths
const tjfilePath = 'tjfile://usr/userdata.json';
const tjfileRealPath = this.gameHandle.convertMaskPathToRealPath(tjfilePath);
console.log('tjfile -> Real:', tjfilePath, '->', tjfileRealPath);
}
// Example: Save player data
async savePlayerData(playerId, data) {
const maskPath = `game://save/player_${playerId}.json`;
const realPath = this.gameHandle.convertMaskPathToRealPath(maskPath);
await fs.writeFile(realPath, JSON.stringify(data, null, 2), 'utf-8');
console.log(`Player data saved to: ${realPath}`);
console.log(`Virtual path: ${maskPath}`);
}
// Example: Load player data
async loadPlayerData(playerId) {
const maskPath = `game://save/player_${playerId}.json`;
const realPath = this.gameHandle.convertMaskPathToRealPath(maskPath);
try {
const content = await fs.readFile(realPath, 'utf-8');
const data = JSON.parse(content);
console.log(`Player data loaded from: ${realPath}`);
return data;
} catch (error) {
console.error(`Failed to load player data:`, error);
return null;
}
}
// Example: Clear cache
async clearCache() {
const maskCachePath = 'game://cache/';
const realCachePath = this.gameHandle.convertMaskPathToRealPath(maskCachePath);
try {
const files = await fs.readdir(realCachePath);
for (const file of files) {
await fs.unlink(path.join(realCachePath, file));
}
console.log(`Cache cleared: ${realCachePath}`);
} catch (error) {
console.error('Failed to clear cache:', error);
}
}
// Example: Write log
async writeLog(message) {
const timestamp = new Date().toISOString();
const logEntry = `[${timestamp}] ${message}\n`;
const maskLogPath = 'game://logs/game.log';
const realLogPath = this.gameHandle.convertMaskPathToRealPath(maskLogPath);
await fs.appendFile(realLogPath, logEntry, 'utf-8');
}
}
// Usage
async function main() {
// Initialize SDK and create game handle
const hostHandle = await new Promise((resolve, reject) => {
TJHostHandle.initialize('sdk-key', 'sdk-secret', (handle, error) => {
if (error) reject(error);
else resolve(handle);
});
});
const gameHandle = await hostHandle.createGameHandle();
// Setup file system manager
const fsManager = new FileSystemManager();
await fsManager.initialize(gameHandle);
// Test path conversions
fsManager.testPathConversions();
// Save player data
await fsManager.savePlayerData('player123', {
name: 'John',
level: 10,
score: 1000
});
// Load player data
const playerData = await fsManager.loadPlayerData('player123');
console.log('Loaded player data:', playerData);
// Write log
await fsManager.writeLog('Game started successfully');
// Clear cache
await fsManager.clearCache();
}
main().catch(console.error);