diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 00000000..698d23ae --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,89 @@ +# Fantasy Map Generator + +Azgaar's Fantasy Map Generator is a client-side JavaScript web application for creating fantasy maps. It generates detailed fantasy worlds with countries, cities, rivers, biomes, and cultural elements. + +Always reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here. + +## Working Effectively + +- **CRITICAL**: This is a static web application - NO build process needed. No npm install, no compilation, no bundling. +- Run the application using HTTP server (required - cannot run with file:// protocol): + - `python3 -m http.server 8000` - takes 2-3 seconds to start +- Access at: `http://localhost:8000` + +## Validation + +- Always manually validate any changes by: + 1. Starting the HTTP server (NEVER CANCEL - wait for full startup) + 2. Navigate to the application in browser + 3. Click the "►" button to open the menu and generate a new map + 4. **CRITICAL VALIDATION**: Verify the map generates with countries, cities, roads, and geographic features + 5. Test UI interaction: click "Layers" button, verify layer controls work + 6. Test regeneration: click "New Map!" button, verify new map generates correctly +- **Known Issues**: Google Analytics and font loading errors are normal (blocked external resources) + +## Repository Structure + +### Core Files + +- `index.html` - Main application entry point +- `main.js` - Core application logic +- `versioning.js` - Version management and update handling + +### Key Directories + +- `modules/` - core functionality modules: + - `modules/ui/` - UI components (editors, tools, style management) + - `modules/dynamic/` - runtime modules (export, installation) + - `modules/renderers/` - drawing and rendering logic +- `utils/` - utility libraries (math, arrays, strings, etc.) +- `styles/` - visual style presets (JSON files) +- `libs/` - Third-party libraries (D3.js, TinyMCE, etc.) +- `images/` - backgrounds, UI elements +- `charges/` - heraldic symbols and coat of arms elements +- `config/` - Heightmap templates and configurations +- `heightmaps/` - Terrain generation data + +## Common Tasks + +### Making Code Changes + +1. Edit JavaScript files directly (no compilation needed) +2. Refresh browser to see changes immediately +3. **ALWAYS test map generation** after making changes +4. Update version in `versioning.js` for all changes +5. Update file hashes in `index.html` for changed files (format: `file.js?v=1.108.1`) + +### Debugging Map Generation + +- Open browser developer tools console +- Look for timing logs, e.g. "TOTAL: ~0.76s" +- Map generation logs show each step (heightmap, rivers, states, etc.) +- Error messages will indicate specific generation failures + +### Testing Different Map Types + +- Use "New Map!" button for quick regeneration +- Access "Layers" menu to change map visualization +- Available presets: Political, Cultural, Religions, Biomes, Heightmap, Physical, Military + +## Troubleshooting + +### Application Won't Load + +- Ensure using HTTP server (not file://) +- Check console for JavaScript errors +- Verify all files are present in repository + +### Map Generation Fails + +- Check browser console for error messages +- Look for specific module failures in generation logs +- Try refreshing page and generating new map + +### Performance Issues + +- Map generation should complete in ~1 second for standard configurations +- If slower, check browser console for errors + +Remember: This is a sophisticated client-side application that generates complete fantasy worlds with political systems, geography, cultures, and detailed cartographic elements. Always validate that your changes preserve the core map generation functionality. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..a2438d37 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,832 @@ +# CLAUDE.md - AI Assistant Guide for Fantasy Map Generator + +## Project Overview + +**Fantasy Map Generator** (FMG) is a free web-based application for creating and editing fantasy maps. It's a massive client-side JavaScript application designed for fantasy writers, game masters, and cartographers. + +- **Repository**: https://github.com/Azgaar/Fantasy-Map-Generator +- **Live App**: https://azgaar.github.io/Fantasy-Map-Generator +- **Language**: Pure JavaScript (ES6+) +- **License**: MIT +- **Primary Author**: Azgaar (azgaar.fmg@yandex.com) + +## Architecture & Technology Stack + +### Core Technologies + +- **Pure JavaScript (ES6+)**: NO build system, transpilation, or bundling +- **D3.js v7**: SVG manipulation, data visualization, zoom/pan interactions +- **jQuery 3.1.1 + jQuery UI**: DOM manipulation, dialogs, UI components +- **Progressive Web App (PWA)**: Service worker caching, offline support, IndexedDB storage + +### Key Libraries (`/libs/`) + +``` +d3.min.js # Main visualization library +delaunator.min.js # Delaunay triangulation for Voronoi mesh +alea.min.js # Seedable random number generator +three.min.js # 3D rendering support +jszip.min.js # ZIP file creation for exports +polylabel.min.js # Label placement optimization +tinymce/ # Rich text editor for notes +``` + +### Architecture Pattern + +**Global Object Pattern**: No module bundler, everything attached to `window` object: + +```javascript +// Global data structures (from main.js:151-158) +let grid = {}; // Initial Voronoi graph +let pack = {}; // Main packed data structure +let seed; // Map generation seed +let mapId; // Unique map identifier +let mapHistory = []; // Undo/redo history +let modules = {}; // Module initialization flags +let notes = []; // User notes +``` + +## Directory Structure + +``` +Fantasy-Map-Generator/ +├── index.html # 8,184-line monolithic HTML (entire UI) +├── main.js # 1,288 lines - initialization, globals, SVG setup +├── versioning.js # Version management (currently v1.108.11) +├── sw.js # Service worker for PWA caching +│ +├── modules/ # Core application logic (232 JS files) +│ ├── dynamic/ # Dynamically imported modules +│ │ ├── editors/ # Advanced editors (states, religions, cultures) +│ │ ├── overview/ # Data visualization tools +│ │ └── *.js # Auto-update, installation, hierarchy-tree +│ ├── io/ # Input/Output operations +│ │ ├── cloud.js # Cloud storage (Dropbox) +│ │ ├── export.js # Map export functionality +│ │ ├── load.js # Map loading +│ │ └── save.js # Map saving +│ ├── renderers/ # SVG rendering (12 files) +│ │ ├── draw-borders.js +│ │ ├── draw-heightmap.js +│ │ ├── draw-markers.js +│ │ └── ... +│ └── ui/ # UI editors and tools (~35 files) +│ ├── editors.js # Common editor functions +│ ├── options.js # Map configuration +│ └── ... +│ +├── utils/ # Utility functions (15 files) +│ ├── arrayUtils.js +│ ├── colorUtils.js +│ ├── commonUtils.js # debounce, throttle +│ ├── graphUtils.js # Graph algorithms (297 lines) +│ ├── pathUtils.js # SVG path operations (222 lines) +│ └── ... +│ +├── charges/ # 400+ SVG heraldic symbols +├── components/ # Reusable UI components +├── config/ # Heightmap template configurations +├── heightmaps/ # Precreated heightmap resources +├── images/ # Application images/icons +├── styles/ # 12 JSON theme presets (default, night, etc.) +│ +└── .github/ + ├── pull_request_template.md + └── ISSUE_TEMPLATE/ +``` + +## Key Files + +### Entry Points + +- **index.html** (line 1-8184): Entire UI structure, loads all scripts +- **main.js** (line 1-1288): Initializes globals, SVG layers, data structures +- **versioning.js**: Current version: `1.108.11` (semantic versioning) + +### Core Generators + +```javascript +modules/burgs-and-states.js # City/state generation (1,018 lines) +modules/cultures-generator.js # Culture system (1,039 lines) +modules/names-generator.js # Name generation (3,371 lines) +modules/heightmap-generator.js # Terrain generation (445 lines) +modules/river-generator.js # River systems (507 lines) +modules/routes-generator.js # Road/trail generation (537 lines) +modules/religions-generator.js # Religion system (757 lines) +modules/military-generator.js # Military units (405 lines) +modules/markers-generator.js # Map markers (1,163 lines) +modules/coa-generator.js # Coat of arms logic (1,015 lines) +modules/coa-renderer.js # COA SVG rendering (2,527 lines) +modules/provinces-generator.js # Province subdivision (302 lines) +modules/zones-generator.js # Zone assignment (430 lines) +``` + +## Data Model + +### Primary Data Structure: `pack` Object + +The `pack` object is the heart of FMG's data model. It contains the entire map state using **typed arrays** for performance: + +```javascript +pack = { + cells: { + i: Uint32Array, // Cell indices + v: Array, // Adjacent vertices + c: Array, // Adjacent cells + b: Uint8Array, // Border flags + h: Uint8Array, // Height (0-100) + temp: Int8Array, // Temperature + prec: Uint8Array, // Precipitation + f: Uint16Array, // Feature (biome) ID + t: Int8Array, // Terrain type + haven: Uint16Array, // Harbor ID + harbor: Uint8Array, // Harbor presence + fl: Uint16Array, // Flux (river flow) + r: Uint16Array, // River ID + conf: Uint8Array, // River confluence + pop: Float32Array, // Population density + culture: Uint16Array, // Culture ID + burg: Uint16Array, // Settlement ID + road: Uint16Array, // Road ID + route: Uint16Array, // Route ID + crossroad: Uint16Array, + province: Uint16Array, + state: Uint16Array, // State ownership + religion: Uint16Array + }, + vertices: { + p: Array, // Point coordinates [x, y] + v: Array, // Adjacent vertices + c: Array // Adjacent cells + }, + features: Array, // Biome/terrain features + cultures: Array, // Culture definitions + states: Array, // Political states + burgs: Array, // Cities/towns/settlements + religions: Array, // Religion definitions + provinces: Array, // Province data + rivers: Array, // River definitions + markers: Array, // Map markers + notes: Array // User notes +} +``` + +### Typed Array Constants + +```javascript +// From main.js:16-20 +const INT8_MAX = 127; +const UINT8_MAX = 255; +const UINT16_MAX = 65535; +const UINT32_MAX = 4294967295; +``` + +### Map Generation Pipeline + +``` +Heightmap Generation + ↓ +Voronoi/Delaunay Mesh + ↓ +Biomes & Climate + ↓ +Rivers & Water Features + ↓ +Cultures Assignment + ↓ +States & Capitals + ↓ +Burgs (Cities/Towns) + ↓ +Provinces Subdivision + ↓ +Routes (Roads/Trails) + ↓ +Religions Distribution + ↓ +Military Units + ↓ +Final Rendering +``` + +## SVG Layer Organization + +FMG uses 70+ predefined SVG layer groups in specific render order (from main.js:40-94): + +```javascript +// Background to foreground rendering order +ocean → oceanLayers → oceanPattern → lakes → landmass → +texture → terrs → biomes → cells → rivers → terrain → +regions → borders → routes → temperature → coastline → +ice → population → emblems → labels → icons → armies → +markers → fogging → ruler → debug +``` + +**Important**: When modifying rendering, respect this layer order to avoid z-index issues. + +## Code Conventions & Style + +### General Style + +1. **Strict Mode**: Every file starts with `"use strict";` +2. **No Semicolons**: Generally omitted (but inconsistent) +3. **Naming Conventions**: + - `camelCase` for variables and functions + - `PascalCase` for classes + - `SCREAMING_SNAKE_CASE` for constants +4. **Comments**: Minimal; code is mostly self-documenting +5. **String Quotes**: Mixed single and double quotes (no standard) + +### Module Patterns + +**IIFE (Immediately Invoked Function Expression)**: + +```javascript +// From burgs-and-states.js:3 +window.BurgsAndStates = (() => { + const generate = () => { + // Implementation + }; + + return { generate }; +})(); + +// Usage elsewhere: +BurgsAndStates.generate(); +``` + +**Global Function Pattern**: + +```javascript +// From draw-borders.js:3 +function drawBorders() { + // Direct global function +} +``` + +**Utility Module Pattern**: + +```javascript +// From utils/commonUtils.js +function debounce(func, ms) { /* ... */ } +function throttle(func, ms) { /* ... */ } +// Directly callable globally +``` + +### Loading Strategy + +**index.html** loads scripts in three phases: + +1. **Libraries** (D3, jQuery, etc.) +2. **Core Modules** (synchronous, no `defer`) +3. **UI Modules** (with `defer` attribute) +4. **Dynamic Imports** (ES6 `import()` for lazy loading) + +Example from index.html: +```html + + + + + + + + + + +``` + +### Debug Flags + +```javascript +// From main.js:5-11 +const PRODUCTION = location.hostname && + location.hostname !== "localhost" && + location.hostname !== "127.0.0.1"; +const DEBUG = JSON.safeParse(localStorage.getItem("debug")) || {}; +const INFO = true; +const TIME = true; // Performance timing +const WARN = true; +const ERROR = true; + +// Usage: +TIME && console.time("placeCapitals"); +// ... expensive operation ... +TIME && console.timeEnd("placeCapitals"); +``` + +## Development Workflow + +### No Build System + +- **Zero build configuration**: No webpack, rollup, or bundlers +- **No package.json**: No npm dependencies +- **No transpilation**: No Babel or TypeScript +- **Direct file editing**: Edit JS → Refresh browser → See changes + +### Local Development + +```bash +# Python simple server +python -m http.server 8080 + +# PHP built-in server +php -S localhost:8080 + +# Then visit: http://localhost:8080 +``` + +### Versioning Process + +**Manual 3-step versioning** (from pull_request_template.md): + +1. **Update VERSION** in `versioning.js`: + ```javascript + const VERSION = "1.108.12"; // Increment using semver + ``` + +2. **Update file hashes** in `index.html` for all changed files: + ```html + + ``` + +3. **Update changelog** in `showUpdateWindow()` function (versioning.js) if user-facing + +### Git Workflow + +**Commit Message Format** (inferred from git log): + +``` +(): + +Examples: +fix(v1.108.11): add external icons to export in base64 format +feat(ai-generator): update supported AI models list +refactor: drawReliefIcons, v1.108.4 +perf: set text-rendering to optimizeSpeed, v1.108.1 +chore: update version to 1.108.8 +``` + +**Types**: +- `feat`: New feature +- `fix`: Bug fix +- `refactor`: Code restructuring +- `perf`: Performance improvement +- `chore`: Maintenance tasks +- `docs`: Documentation changes + +**Scopes**: Optional, often includes version number or component name + +### Pull Request Requirements + +From `.github/pull_request_template.md`: + +**Required**: +- [ ] Description of change and motivation +- [ ] Type of change (bug fix, feature, refactor, docs, other) +- [ ] Version updated in `versioning.js` +- [ ] Changed files hash updated in `index.html` + +**Before submitting**: +1. Test locally (no automated tests) +2. Check console for errors +3. Verify map generation still works +4. Update version following semver + +## Common Development Tasks + +### Adding a New Feature + +1. **Identify the module type**: + - Generator? → `modules/` + - UI Editor? → `modules/ui/` + - Renderer? → `modules/renderers/` + - Utility? → `utils/` + +2. **Create the module file**: + ```javascript + "use strict"; + + window.MyNewFeature = (() => { + const generate = () => { + TIME && console.time("myNewFeature"); + // Implementation + TIME && console.timeEnd("myNewFeature"); + }; + + return { generate }; + })(); + ``` + +3. **Add script tag to index.html**: + ```html + + ``` + +4. **Update versioning**: + - Increment VERSION in `versioning.js` + - Update hash in `index.html` + - Add changelog entry if user-facing + +### Modifying the Data Model + +1. **Update pack structure** in relevant generator +2. **Update save/load** in `modules/io/save.js` and `modules/io/load.js` +3. **Test with existing .map files** to ensure backward compatibility +4. **Update any renderers** that use the new data + +### Adding a New Renderer + +1. **Create renderer file** in `modules/renderers/`: + ```javascript + "use strict"; + + function drawMyFeature() { + const { cells, myFeatures } = pack; + const container = svg.select("#myFeatureLayer"); + + // D3 rendering logic + container.selectAll("path") + .data(myFeatures) + .join("path") + .attr("d", d => d.path) + .attr("fill", d => d.color); + } + ``` + +2. **Create SVG layer** in main.js: + ```javascript + let myFeatureLayer = viewbox.append("g") + .attr("id", "myFeatureLayer"); + ``` + +3. **Add to render pipeline** in appropriate location + +### Debugging Tips + +1. **Use DEBUG flags**: + ```javascript + DEBUG && console.log("Debug info:", data); + TIME && console.time("expensiveOperation"); + ``` + +2. **Check the debug SVG layer**: + ```javascript + debug.append("circle") + .attr("cx", x) + .attr("cy", y) + .attr("r", 5) + .attr("fill", "red"); + ``` + +3. **Use browser DevTools**: + - Network tab: Check script loading + - Console: Look for TIME logs + - Sources: Set breakpoints + +4. **Test map generation**: + - Generate → Verify no console errors + - Save → Load → Verify data integrity + - Export → Check output quality + +## Testing Approach + +**No formal testing framework**: +- No Jest, Mocha, or automated tests +- Manual testing only +- User reports via GitHub issues + +**Manual testing checklist**: +1. Generate new map with default settings +2. Generate with various custom settings +3. Load existing .map files +4. Test all editors (heightmap, states, cultures, etc.) +5. Export in all formats (SVG, PNG, JSON) +6. Check console for errors/warnings +7. Test on multiple browsers (Chrome, Firefox, Safari) + +## Performance Considerations + +### Optimization Strategies + +1. **Typed Arrays**: Use for large datasets + ```javascript + cells.h = new Uint8Array(n); // Heights 0-255 + cells.pop = new Float32Array(n); // Population + ``` + +2. **D3 Data Binding**: Efficient DOM updates + ```javascript + container.selectAll("path") + .data(features, d => d.id) // Key function + .join("path") // Efficient enter/update/exit + ``` + +3. **Debouncing/Throttling**: For frequent events + ```javascript + const onMouseMove = debounce(handleMouseMove, 100); + ``` + +4. **Quadtree for Spatial Queries**: + ```javascript + let burgsTree = d3.quadtree(); + burgsTree.add([x, y]); + const nearest = burgsTree.find(x, y, radius); + ``` + +5. **IndexedDB**: For large map storage + ```javascript + // See libs/indexedDB.js + ``` + +## Important Patterns & Anti-Patterns + +### DO: + +✅ Use typed arrays for cell data +✅ Respect SVG layer rendering order +✅ Use TIME flags for performance monitoring +✅ Follow IIFE pattern for new modules +✅ Update version numbers consistently +✅ Test backward compatibility with old .map files +✅ Use D3 data binding for DOM updates +✅ Check for null/undefined before accessing pack data + +### DON'T: + +❌ Add npm dependencies (no build system) +❌ Use ES6 modules (not supported in current architecture) +❌ Modify global data structures directly without updating renderers +❌ Add large libraries (keep bundle size manageable) +❌ Break backward compatibility without migration logic +❌ Add features without updating save/load functionality +❌ Forget to update version hash in index.html +❌ Mix rendering layers (respect z-order) + +## Common Patterns in Codebase + +### Random Number Generation + +```javascript +// Use seeded random for reproducibility +const rand = aleaPRNG(seed); +const value = rand(); // 0-1 + +// Gaussian distribution +const value = gauss(mean, deviation, min, max, rounds); +``` + +### Cell Iteration + +```javascript +const { cells } = pack; +const n = cells.i.length; + +for (let i = 0; i < n; i++) { + if (cells.h[i] < 20) continue; // Skip water + // Process land cells +} +``` + +### D3 SVG Path Creation + +```javascript +const path = d3.line() + .x(d => d[0]) + .y(d => d[1]) + .curve(d3.curveBasis); + +const pathString = path(points); +``` + +### Graph Traversal + +```javascript +// BFS example from graphUtils.js +const queue = [startCell]; +const visited = new Uint8Array(cells.i.length); + +while (queue.length) { + const cell = queue.shift(); + if (visited[cell]) continue; + visited[cell] = 1; + + cells.c[cell].forEach(neighbor => { + if (!visited[neighbor]) queue.push(neighbor); + }); +} +``` + +## Key Concepts + +### Voronoi/Delaunay Mesh + +FMG uses a Voronoi diagram as the base map structure: + +- **Cells**: Voronoi regions representing map areas +- **Vertices**: Points where 3+ cells meet +- **Edges**: Borders between cells +- **Delaunay Triangulation**: Dual graph for efficient pathfinding + +**Implementation**: Custom `Voronoi` class in `modules/voronoi.js` using Delaunator library + +### Heightmap System + +Heights stored as `Uint8Array` (0-255): +- **0-19**: Ocean depths +- **20**: Sea level +- **21-99**: Land elevations +- **100+**: Mountains/peaks (clamped to 255) + +### Culture & State System + +**Cultures**: Linguistic/ethnic groups with naming patterns +**States**: Political entities with territories, capitals, military + +Both use expansion algorithms based on cell scoring and distance from capitals. + +### Name Generation + +Sophisticated system in `modules/names-generator.js` (3,371 lines): +- Cultural naming patterns +- Procedural phoneme generation +- Linguistic rules for realistic names +- Separate generators for burgs, states, cultures, features + +## File Modification Guidelines + +### When Editing index.html + +- **Line count**: 8,184 lines - VERY large file +- **Structure**: UI components inline (not templated) +- **Script tags**: Update version hash when modifying JS files +- **Dialogs**: jQuery UI dialogs defined inline +- **Be careful**: Easy to break HTML structure + +### When Editing main.js + +- **Global scope**: Everything here is globally accessible +- **SVG layers**: Order matters (lines 40-94) +- **Constants**: Typed array max values defined here +- **Initialization**: Core setup happens here + +### When Editing Generators + +- **Self-contained**: Each generator should be independent +- **Timing**: Wrap in TIME && console.time/timeEnd +- **Error handling**: Use WARN && console.warn for issues +- **Data mutations**: Update pack object directly + +### When Editing Renderers + +- **Layer awareness**: Know which SVG layer you're drawing to +- **Clear old content**: Remove previous render before redrawing +- **D3 data binding**: Use .join() for efficient updates +- **Performance**: Large renders should be optimized + +## Resources + +### Documentation + +- **Project Wiki**: https://github.com/Azgaar/Fantasy-Map-Generator/wiki +- **Data Model**: https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Data-model +- **Trello Board**: https://trello.com/b/7x832DG4/fantasy-map-generator +- **Blog**: https://azgaar.wordpress.com + +### Community + +- **Discord**: https://discordapp.com/invite/X7E84HU +- **Reddit**: https://www.reddit.com/r/FantasyMapGenerator +- **GitHub Issues**: https://github.com/Azgaar/Fantasy-Map-Generator/issues + +### Support + +- **Patreon**: https://www.patreon.com/azgaar +- **Email**: azgaar.fmg@yandex.com + +## Troubleshooting Common Issues + +### Map Won't Generate + +1. Check console for errors +2. Verify all scripts loaded (Network tab) +3. Check localStorage isn't corrupted +4. Try clearing browser cache + +### Save/Load Failures + +1. Check IndexedDB quota +2. Verify .map file format (should be valid JSON) +3. Check version compatibility +4. Look for migration errors in console + +### Performance Issues + +1. Reduce number of cells (Options → Map Size) +2. Disable unused layers +3. Use simpler rendering styles +4. Check for memory leaks in console + +### Rendering Glitches + +1. Verify SVG layer order +2. Check for NaN values in coordinates +3. Ensure paths are valid SVG syntax +4. Test in different browsers + +## Best Practices for AI Assistants + +### When Analyzing Code + +1. **Start with the data model**: Understand `pack` structure +2. **Check dependencies**: See what functions/modules are used +3. **Look for patterns**: IIFE modules, global functions, D3 usage +4. **Trace data flow**: How data moves through generation pipeline + +### When Making Changes + +1. **Test locally first**: No CI/CD, manual testing required +2. **Update version properly**: Follow 3-step process +3. **Maintain backward compatibility**: Old .map files should still load +4. **Document complex logic**: Code is under-commented +5. **Check performance**: Use TIME flags to measure + +### When Refactoring + +1. **Small incremental changes**: Large refactors are risky +2. **Keep the same API**: Don't break existing integrations +3. **Test all features**: Generator, editors, save/load, export +4. **Consider deprecation**: Don't remove features abruptly + +### When Adding Features + +1. **Check existing code**: Similar features might exist +2. **Follow existing patterns**: IIFE for modules, global for utils +3. **Update save/load**: Persist new data properly +4. **Add UI if needed**: Users should access the feature +5. **Update documentation**: At least in comments/changelog + +## Quick Reference + +### File to Edit By Task + +| Task | Files to Edit | +|------|--------------| +| Add new generator | `modules/my-generator.js`, `index.html` (script tag) | +| Modify UI editor | `modules/ui/my-editor.js` | +| Change rendering | `modules/renderers/draw-my-feature.js` | +| Add utility function | `utils/myUtils.js` | +| Update save format | `modules/io/save.js`, `modules/io/load.js` | +| Change map options | `modules/ui/options.js`, `index.html` (UI) | +| Add SVG layer | `main.js` (lines 40-94), renderer file | +| Update version | `versioning.js`, `index.html` (all script tags) | + +### Common Functions + +| Function | Location | Purpose | +|----------|----------|---------| +| `rn(value, decimals)` | `utils/numberUtils.js` | Round number | +| `rand(min, max)` | Random utilities | Random in range | +| `gauss(mean, dev, ...)` | `utils/probabilityUtils.js` | Gaussian distribution | +| `debounce(fn, ms)` | `utils/commonUtils.js` | Debounce function | +| `P(probability)` | Probability utils | Random boolean | +| `ra(array)` | Array utils | Random array element | + +### Common D3 Patterns + +```javascript +// Select SVG layer +const layer = svg.select("#myLayer"); + +// Data binding +layer.selectAll("path") + .data(features, d => d.id) + .join("path") + .attr("d", d => d.path); + +// Zoom/pan +const zoom = d3.zoom() + .scaleExtent([1, 20]) + .on("zoom", zoomed); + +svg.call(zoom); +``` + +--- + +## Summary + +Fantasy Map Generator is a **unique codebase** that prioritizes: + +1. **Accessibility**: Runs anywhere without build tools +2. **Simplicity**: Direct file editing, no complex tooling +3. **Performance**: Typed arrays, efficient algorithms +4. **User experience**: Rich UI with extensive customization + +When working on FMG, embrace its philosophy: **pragmatic simplicity over modern complexity**. The lack of build tools is intentional, making it easy for contributors to jump in without setup overhead. + +--- + +*Last Updated: 2025-11-14* +*Current Version: 1.108.11* +*This guide is for AI assistants working on Fantasy Map Generator codebase.* diff --git a/OBSIDIAN_INTEGRATION.md b/OBSIDIAN_INTEGRATION.md new file mode 100644 index 00000000..5389cd03 --- /dev/null +++ b/OBSIDIAN_INTEGRATION.md @@ -0,0 +1,270 @@ +# Obsidian Vault Integration for Fantasy Map Generator + +## Overview + +Fantasy Map Generator now supports deep integration with your Obsidian vault for managing map lore and notes! This allows you to: + +- Store all your world lore in Markdown format +- Edit notes in a modern Markdown editor (no more Win95-style TinyMCE!) +- Automatically link map elements to Obsidian notes by coordinates +- Keep your notes in sync between FMG and Obsidian +- Use [[wikilinks]] to connect related notes +- Edit in either FMG or Obsidian - changes sync both ways + +## Setup + +### 1. Install Obsidian Local REST API Plugin + +1. Open Obsidian +2. Go to **Settings** → **Community Plugins** +3. Click **Browse** and search for "Local REST API" +4. Install and **Enable** the plugin +5. Go to **Settings** → **Local REST API** +6. Copy your **API Key** (you'll need this!) +7. Note the **Server Port** (default: 27123) + +### 2. Configure in Fantasy Map Generator + +1. Open Fantasy Map Generator +2. Go to **Menu** → **Tools** → **⚙ Obsidian** +3. Enter your settings: + - **API URL**: `http://127.0.0.1:27123` (default) + - **API Key**: Paste from Obsidian plugin settings + - **Vault Name**: Name of your Obsidian vault +4. Click **Test Connection** to verify +5. Click **Save Configuration** + +## Usage + +### Linking Map Elements to Notes + +When you click on a **burg** or **marker** in FMG: + +1. FMG searches your Obsidian vault for notes with matching coordinates in YAML frontmatter +2. Shows you the top 5-8 closest matches +3. You select the note you want, or create a new one + +### Note Format + +Notes in your vault should have YAML frontmatter like this: + +```markdown +--- +fmg-id: burg123 +fmg-type: burg +coordinates: + x: 234.5 + y: 456.7 + lat: 45.23 + lon: -73.45 +tags: + - capital + - settlement + - ancient +aliases: + - Eldoria + - The Ancient City +--- + +# Eldoria + +The ancient capital sits upon the [[River Mystral]], founded in year 1203. + +## History + +The city was established by [[King Aldric the First]]... + +## Notable Locations + +- [[The Grand Library]] +- [[Temple of the Seven Stars]] +- [[Market Square]] +``` + +### Coordinate Matching + +Since your burgs/markers may have been imported from PostgreSQL without FMG IDs, the system matches by **X/Y coordinates**: + +- FMG extracts the coordinates from the clicked element +- Searches all `.md` files in your vault for matching `x:` and `y:` values +- Calculates distance and shows closest matches +- You pick the right one! + +### Supported Coordinate Formats + +The system recognizes these formats in YAML frontmatter: + +```yaml +# Nested object (recommended) +coordinates: + x: 123.4 + y: 567.8 + +# Or flat +x: 123.4 +y: 567.8 + +# Case insensitive +X: 123.4 +Y: 567.8 +``` + +### Creating New Notes + +If no matches are found: + +1. FMG offers to create a new note +2. Enter a name (e.g., "Eldoria") +3. Optionally specify a folder (e.g., "Locations/Cities") +4. FMG generates a template with coordinates +5. Opens in the Markdown editor +6. Saved directly to your Obsidian vault! + +### Editing Notes + +The modern Markdown editor includes: + +- **Live preview**: Toggle between edit/preview modes +- **[[Wikilinks]]**: Link to other notes in your vault +- **Syntax highlighting**: Clean monospace font +- **Open in Obsidian**: Button to jump to the note in Obsidian app +- **Save to Vault**: Changes sync immediately + +### Using Wikilinks + +Create connections between notes: + +```markdown +The [[King Aldric the First]] ruled from [[Eldoria]]. +The city controls access to [[River Mystral]]. +``` + +When you save in FMG, these links work in Obsidian! + +## Migration from PostgreSQL + +If you have existing lore in PostgreSQL with coordinates: + +1. Export your data to Markdown files with YAML frontmatter +2. Include `x`, `y`, `lat`, `lon` in the frontmatter +3. Place files in your Obsidian vault +4. FMG will auto-match by coordinates! + +Example export script template: + +```python +for location in locations: + frontmatter = f"""--- +fmg-type: {location.type} +coordinates: + x: {location.x} + y: {location.y} + lat: {location.lat} + lon: {location.lon} +tags: {location.tags} +--- + +# {location.name} + +{location.description} +""" + with open(f"vault/{location.name}.md", "w") as f: + f.write(frontmatter) +``` + +## Tips & Tricks + +### Organize Your Vault + +Create folders for different types: + +``` +My Vault/ +├── Locations/ +│ ├── Cities/ +│ ├── Landmarks/ +│ └── Regions/ +├── Characters/ +├── History/ +└── Lore/ +``` + +### Use Templates + +Create Obsidian templates for different element types: + +- `Templates/City.md` +- `Templates/Landmark.md` +- `Templates/Character.md` + +### Search and Graph + +In Obsidian: + +- Use **Search** (`Ctrl+Shift+F`) to find notes by coordinates +- Use **Graph View** to see connections between locations +- Use **Tags** to organize by type + +### Sync Across Devices + +Use Obsidian Sync or Git to keep your vault synced across computers! + +## Troubleshooting + +### Connection Failed + +- Make sure Obsidian is running +- Verify the Local REST API plugin is enabled +- Check the port number (default 27123) +- Try restarting Obsidian + +### No Matches Found + +- Check that your notes have `x:` and `y:` fields in frontmatter +- Verify coordinates are numbers, not strings +- Try increasing the search radius + +### Changes Not Appearing in Obsidian + +- Obsidian should auto-detect file changes +- If not, try switching to another note and back +- Or close/reopen the note + +## Advanced + +### Custom Coordinate Systems + +If you use a different coordinate system: + +1. Map your coordinates to FMG's system +2. Store both in frontmatter: +```yaml +coordinates: + x: 234.5 # FMG coordinates + y: 456.7 + custom_x: 1000 # Your system + custom_y: 2000 +``` + +### Database Bridge + +For the future PostgreSQL migration: + +1. Keep coordinates in both Obsidian and database +2. Use coordinates as the join key +3. Sync changes via API +4. Eventually replace file storage with DB + +## Future Features + +Planned enhancements: + +- [ ] Time slider - view notes across historical periods +- [ ] Automatic tagging by region/culture +- [ ] Bulk import from database +- [ ] Real-time collaboration +- [ ] Custom Markdown extensions + +--- + +**Enjoy your modern, Markdown-powered world-building! 🗺️✨** diff --git a/index.html b/index.html index 3c0ba0f3..aa38c555 100644 --- a/index.html +++ b/index.html @@ -1830,6 +1830,7 @@ @@ -2061,6 +2062,9 @@ Namesbase + @@ -4962,6 +4966,107 @@ + + + + + +