# BMS BattleMap Generator - Technical Architecture ## System Overview ``` ┌─────────────────────────────────────────────────────────────┐ │ Frontend Application │ ├─────────────────────────────────────────────────────────────┤ │ Editor Interface Preview Canvas Tools Panel │ │ (Monaco Editor) (Konva.js Canvas) (Export/Options) │ ├─────────────────────────────────────────────────────────────┤ │ State Management │ │ (React Hooks/Context) │ ├─────────────────────────────────────────────────────────────┤ │ YAML Parser │ Schema Validator │ Renderer Engine │ │ (js-yaml) │ (Zod) │ (Konva.js Layers) │ └─────────────────────────────────────────────────────────────┘ ``` ## Component Architecture ### 1. BMS Schema Module (`src/schema/`) ``` schema/ ├── types.ts # TypeScript interfaces ├── validators.ts # Zod validation schemas ├── parsers.ts # Coordinate/range parsing ├── transformers.ts # Data transformation └── index.ts # Public API ``` ### 2. Parser Module (`src/parser/`) ``` parser/ ├── yaml-parser.ts # BMS YAML parsing ├── coordinate-parser.ts # Grid coordinate parsing ├── validation.ts # Schema validation logic ├── errors.ts # Error types and messages └── index.ts ``` ### 3. Renderer Module (`src/renderer/`) ``` renderer/ ├── base-renderer.ts # Abstract base class ├── paperly-renderer.ts # Paperly style implementation ├── texture-renderer.ts # Future: texture pack rendering ├── layers/ # Individual layer renderers │ ├── grid-layer.ts │ ├── room-layer.ts │ ├── door-layer.ts │ ├── object-layer.ts │ ├── hazard-layer.ts │ ├── lighting-layer.ts │ └── annotation-layer.ts ├── styles/ # Style definitions │ ├── paperly-style.ts │ └── texture-styles.ts # Future └── utils/ # Rendering utilities ├── geometry.ts ├── colors.ts └── textures.ts ``` ### 4. UI Components (`src/components/`) ``` components/ ├── Editor/ │ ├── YAMLEditor.tsx # Monaco editor wrapper │ └── EditorPanel.tsx # Editor with error display ├── Preview/ │ ├── MapCanvas.tsx # Konva canvas wrapper │ └── PreviewPanel.tsx # Preview with controls ├── Tools/ │ ├── ExportMenu.tsx # Export options │ ├── StylePicker.tsx # Style selection │ └── ValidationPanel.tsx # Validation status ├── Layout/ │ ├── Header.tsx │ ├── Sidebar.tsx │ └── StatusBar.tsx └── Common/ ├── ErrorDisplay.tsx ├── LoadingSpinner.tsx └── Tooltip.tsx ``` ### 5. State Management (`src/hooks/`, `src/context/`) ``` hooks/ ├── useBMS.ts # BMS schema state ├── useRenderer.ts # Renderer instance ├── useExport.ts # Export functionality └── useUndoRedo.ts # Undo/redo history context/ ├── AppContext.tsx # Global app state └── ThemeContext.tsx # Theme/stylesheet ``` ## Data Flow ### 1. Parsing Pipeline ``` User Input (YAML) ↓ YAML Parser (js-yaml) ↓ Schema Validator (Zod) ↓ BMSSchema Object ↓ Renderer Engine ↓ Canvas Output ``` ### 2. Rendering Pipeline ``` BMSSchema ↓ Setup Canvas (grid size, scale) ↓ Render Layers (in order): 1. Grid Layer 2. Room Layer (walls, floors) 3. Door Layer 4. Object Layer 5. Hazard Layer 6. Lighting Layer 7. Annotation Layer ↓ Canvas Output ``` ### 3. Export Pipeline ``` Canvas State ↓ Export Format Selection ↓ Format-Specific Exporter: - PNG: canvas.toDataURL() - JSON: JSON.stringify(BMSSchema) - BMS: serializeBMSToYAML() ↓ File Download ``` ## Key Technical Decisions ### 1. Canvas Library: Konva.js **Why Konva.js over alternatives:** - **React Integration**: react-konva provides React component wrappers - **Performance**: Hardware acceleration, efficient rendering - **Features**: Layers, events, transforms, filters - **Size**: Smaller than PIXI.js, more focused than raw Canvas API - **Maintenance**: Active development, good documentation ### 2. Validation: Zod **Why Zod over alternatives:** - **TypeScript Integration**: Automatic type inference - **Runtime Safety**: Comprehensive validation at runtime - **Error Messages**: Customizable error messages - **Size**: Small bundle size - **Schema Composition**: Easy to compose and extend schemas ### 3. YAML Parsing: js-yaml **Why js-yaml:** - **Browser Support**: Works in browser environments - **Safety**: Secure parsing options - **Performance**: Fast and efficient - **Features**: Full YAML 1.2 support ### 4. State Management: React Hooks **Why React Hooks over Redux/MobX:** - **Simplicity**: Less boilerplate for MVP - **Performance**: Optimized re-renders with useMemo/useCallback - **Scalability**: Can migrate to Context or Zustand if needed - **Learning Curve**: Familiar to React developers ## Performance Considerations ### 1. Rendering Optimization ```typescript // Use Konva.js optimizations const optimizedRender = () => { // Batch updates stage.batchDraw(); // Use caching for static elements shape.cache(); // Implement viewport culling if (isInViewport(element)) { renderElement(element); } }; ``` ### 2. Memory Management ```typescript // Clean up resources useEffect(() => { const renderer = new PaperlyRenderer(); return () => { renderer.destroy(); // Clean up Konva objects }; }, []); ``` ### 3. Large Map Handling ```typescript // Implement level of detail const getDetailLevel = (zoom: number): DetailLevel => { if (zoom < 0.5) return 'low'; if (zoom < 1.0) return 'medium'; return 'high'; }; // Progressive rendering const renderProgressive = async (schema: BMSSchema) => { // Render grid first renderGrid(); // Render rooms await renderRooms(schema.rooms); // Render details progressively requestIdleCallback(() => { renderDoors(schema.doors); renderObjects(schema.objects); }); }; ``` ## Security Considerations ### 1. YAML Parsing Security ```typescript import { load } from 'js-yaml'; // Safe YAML parsing const parseBMSYAML = (yaml: string): BMSSchema => { try { // Use safeLoad to prevent code execution const parsed = load(yaml, { schema: yaml.DEFAULT_SAFE_SCHEMA, onWarning: (warning) => console.warn(warning) }); // Validate structure return bmsSchema.parse(parsed); } catch (error) { throw new BMSValidationError('Invalid BMS YAML', error); } }; ``` ### 2. File Export Security ```typescript // Safe file naming const sanitizeFilename = (name: string): string => { return name.replace(/[^a-z0-9-_.]/gi, '_'); }; // Content security for downloads const downloadFile = (content: string, filename: string) => { const blob = new Blob([content], { type: 'application/octet-stream' }); const url = URL.createObjectURL(blob); // Use safe download pattern const a = document.createElement('a'); a.href = url; a.download = sanitizeFilename(filename); a.click(); URL.revokeObjectURL(url); }; ``` ## Testing Strategy ### 1. Unit Tests ```typescript // Test coordinate parsing describe('parseCoordinate', () => { it('should parse valid coordinates', () => { expect(parseCoordinate('(5,10)')).toEqual([5, 10]); }); it('should throw error for invalid format', () => { expect(() => parseCoordinate('5,10')).toThrow(); }); }); ``` ### 2. Integration Tests ```typescript // Test full parsing pipeline describe('BMS Parser Integration', () => { it('should parse and validate complete BMS', () => { const yaml = sampleBMSYAML; const schema = parseBMSYAML(yaml); expect(schema.mapName).toBe('Guard Room'); expect(schema.rooms).toHaveLength(1); }); }); ``` ### 3. Visual Regression Tests ```typescript // Compare rendered output describe('Renderer Visual Tests', () => { it('should render rooms correctly', async () => { const schema = createTestSchema(); const renderer = new PaperlyRenderer(); const image = await renderer.renderToImage(schema); // Compare with baseline expect(image).toMatchImageSnapshot(); }); }); ``` ## Deployment Architecture ### 1. Development Environment ``` Local Machine → Vite Dev Server → Browser ``` ### 2. Alpha Deployment ``` Git Repository → Build (Vite) → Static Files → maps.bouncypixel.com ``` ### 3. Future Production Deployment ``` GitHub Actions → Build & Test → CDN (Vercel/Netlify) → Custom Domain ↘ Texture Packs → Cloud Storage (S3/Cloudflare) ``` ## Scalability Considerations ### 1. Frontend Scaling - **Code Splitting**: Lazy load components - **Bundle Optimization**: Tree shaking, compression - **CDN**: Static assets via CDN ### 2. Rendering Scaling - **Virtualization**: Only render visible area - **Web Workers**: Offload heavy computation - **Caching**: Cache rendered elements ### 3. Data Scaling - **IndexedDB**: Local storage for large maps - **Compression**: Compress BMS data - **Streaming**: Progressive loading ## Monitoring & Analytics ### 1. Performance Monitoring ```typescript // Track rendering performance const measureRender = (schema: BMSSchema) => { performance.mark('render-start'); renderer.render(schema); performance.mark('render-end'); const measure = performance.measure('render', 'render-start', 'render-end'); console.log(`Render time: ${measure.duration}ms`); }; ``` ### 2. Error Tracking ```typescript // Centralized error handling class ErrorTracker { static track(error: Error, context?: any) { console.error('BMS Error:', error, context); // Send to error tracking service (future) } } ``` ### 3. Usage Analytics (Optional) ```typescript // Basic usage tracking const trackEvent = (event: string, data?: any) => { if (process.env.NODE_ENV === 'production') { // Send to analytics service } }; ``` ## Future Technical Considerations ### 1. Plugin System ```typescript interface BMSPlugin { name: string; version: string; init: (app: BMSApp) => void; render?: (context: RenderContext) => void; export?: (schema: BMSSchema) => any; } ``` ### 2. Collaborative Features - **WebSocket**: Real-time collaboration - **Conflict Resolution**: Operational transforms - **Presence**: User cursor/selection ### 3. Offline Support - **Service Workers**: Offline functionality - **Local Storage**: Save work locally - **Sync**: Background synchronization --- *Last Updated: March 19, 2026*