Files
OpenFrontIO/map-generator/README.md
T
Evan 3de5fb4204 Move map metadata into info.json and generate map TypeScript from it (#4227)
**Add approved & assigned issue number here:**

N/A — maintainer refactor.

## Description:

Makes each map's `info.json` the single source of truth for map metadata
— adding a map is now a folder with `image.png` + `info.json`, a
`gen-maps` run, and an en.json display name.

**info.json / manifest.json carry full map metadata.** Every
`map-generator/assets/maps/<map>/info.json` declares `id` (the
`GameMapType` enum key), `name` (the enum value — wire format, unchanged
for all 94 maps), `translation_key`, `categories`, and
`multiplayer_frequency` (the public-playlist weight that used to be the
`FREQUENCY` record in MapPlaylist.ts). The generator validates
everything and mirrors it into `resources/maps/<map>/manifest.json`. 23
stale info.json `name` values were normalized to the canonical enum
value; enum values are byte-identical, so replays and stored game
configs are unaffected.

**The generator emits the TypeScript and discovers maps itself.** New
`map-generator/codegen.go` generates `src/core/game/Maps.gen.ts`
(`GameMapType`, `GameMapName`, `mapCategories`, `mapTranslationKeys`,
`multiplayerFrequency` — now a full `Record<GameMapName, number>`,
killing the old `Partial`) on every run; `Game.ts` re-exports it. The
hardcoded map registry in `main.go` is gone — maps are auto-discovered
from the `assets/maps` / `assets/test_maps` directories. MapConsistency
tests fail with a "run `npm run gen-maps`" message if info.json,
manifest.json, and Maps.gen.ts drift. The tracked
`map-generator/map-generator` binary is rebuilt to match.

**New categories: continents + world/cosmic/tournament/other,
multi-category support.** `continental`/`regional`/`fantasy`/`arcade`
are replaced by `featured`, `world`, `europe`, `asia`, `north_america`,
`africa`, `south_america`, `oceania`, `antarctica`, `cosmic`,
`tournament`, and `other`. Maps can list multiple categories, so
straddlers (Black Sea, Bosphorus, Caucasus, Between Two Seas, Bering
Sea/Strait, Mena, Strait of Gibraltar, Hawaii, Arctic) appear under both
regions. Featured is itself a category (same 7 maps as before).
MapPlaylist keeps its arcade exclusion via an explicit set.

**Map picker UI.** Two tabs: **Featured** (default — featured maps plus
a Favorites section when maps are starred) and **All** (one prominent
collapsible bar per category with a map count, collapsed by default).
The selected map is prepended to the featured grid when it lives
elsewhere. `getMapName()` resolves through the generated
`mapTranslationKeys`, which also fixes tourney maps never resolving a
valid translation key.

## Please complete the following:

- [ ] I have added screenshots for all UI updates (maintainer change —
picker described above)
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory

## Please put your Discord username so you can be contacted if a bug or
regression is found:

evanpelle

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 19:36:53 -07:00

8.3 KiB

MapGenerator

This is a go-based tool to generate map files for OpenFront.

The map generator reads PNG files and converts pixels into terrain based primarily on the Blue channel. Because only blue values are used, grayscale and other formats are fully supported. Many maps in assets/maps/<mapname> are grayscale.

Additional Guides, Tutorials, Scripts, Resources, and Third Party Unofficial Applications can be found on the Official Openfront Wiki

Installation

  1. Install go https://go.dev/doc/install
  2. Go to map-generator folder: cd map-generator
  3. Install dependencies: go mod download
  4. Run the generator for all maps: go run .

Creating a new map

Maps are discovered automatically from the assets/maps/ folders — info.json holds everything the game needs to know about a map.

  1. Create a new folder in assets/maps/<map_name>

  2. Create assets/maps/<map_name>/image.png

  3. Create assets/maps/<map_name>/info.json (see below)

  4. Run the generator for your map: go run . --maps=<map_name>

    By default, go run . will process all defined maps.

    Use --maps to process a single map:

    go run . --maps=fourislands

    To process a subset of maps, pass a comma-separated list:

    go run . --maps=northamerica,world

  5. Find the output folder at ../resources/maps/<map_name>

  6. Go back to the root directory: cd ..

  7. Run Prettier: npm run format This rewrites ALL files in place. Git figures out which files are actually changed, don't worry. Alternatively, you can either run Prettier per file: npx prettier --write resources/maps/<map_name>/<file_name> or in VSCode install the Prettier extension and per file do Show and run Commands > Format Document.

Alternatively, npm run gen-maps (from the root directory) runs the generator for all maps and formats the output in one step.

Output Files

  • ../resources/maps/<map_name>/manifest.json - JSON metadata containing map dimensions and land tile counts for all scales.
  • ../resources/maps/<map_name>/map.bin - Full-scale binary map data packed with terrain type and magnitude.
  • ../resources/maps/<map_name>/map4x.bin - 1/4 scale (half dimensions) binary map data used for mini-maps.
  • ../resources/maps/<map_name>/map16x.bin - 1/16 scale (quarter dimensions) binary map data used for mini-maps.
  • ../resources/maps/<map_name>/thumbnail.webp - WebP image thumbnail of the map.
  • ../src/core/game/Maps.gen.ts - Generated TypeScript (GameMapType, mapCategories, mapTranslationKeys, multiplayerFrequency) built from every map's info.json. Regenerated on every run, even with --maps.

Command Line Flags

  • --maps: Optional comma-separated list of maps to process.
    • ex: go run . --maps=world,eastasia,big_plains

Logging

  • --log-level: Explicitly sets the log level.
    • ex: go run . --log-level=debug
    • values: ALL, DEBUG, INFO (default), WARN, ERROR.
  • --verbose or -v: Adds additional logging and prefixes logs with the [mapname]. Alias of --log-level=DEBUG.
  • --debug-performance: Adds additional logging for performance-based recommendations, sets --log-level=DEBUG.
  • --debug-removal: Adds additional logging of removed island and lake position/size, sets --log-level=DEBUG.

The Generator outputs logs using slog with standard log-levels, and an additional ALL level.

The --verbose, -v, --debug-performance, and --debug-removal flags all set the log level to DEBUG. debug-performance and debug-removal are opt-in on top of the debug log level, as they can produce wordy output. You must pass the specific flag to see the corresponding logs if the log-level is set to DEBUG.

Setting --log-level=ALL will output all possible logs, including all DEBUG tiers, regardless of whether the specific flags are passed.

Create image.png

The map-generator will process your input file at assets/maps/<map_name>/image.png to generate the map thumbnail and binary files. To create this png input file, you can crop the world map:

  1. Download world map (warning very large file)
  2. Crop the file (recommend Gimp)

If you are doing work in image editing software or using automated tools, ./map_generator.go contains documentation for:

  • Pixel -> Terrain Type & Magnitude mapping in GenerateMap
  • Terrain Type -> Thumbnail Color mapping in getThumbnailColor

In-Game, terrain is rendered using themes. The color of a tile is determined dynamically based on its Terrain Type and Magnitude. Theme Files:

  • ../src/core/configuration/PastelTheme.ts (Light)
  • ../src/core/configuration/PastelThemeDark.ts (Dark).

Create info.json

The map-generator will process your input file at assets/maps/<map_name>/info.json to determine the position of Nations, their starting coordinates, and any flags.

Example:

{
  "id": "MySampleMap",
  "name": "My Sample Map",
  "translation_key": "map.mysamplemap",
  "categories": ["europe"],
  "multiplayer_frequency": 4,
  "nations": [
    {
      "coordinates": [396, 364],
      "name": "United States",
      "flag": "us"
    }
  ]
}

coordinates is x/y position of the nation spawn on the map. Origin is at top left, with x extending right and y extending down

id is the CamelCaseName of your map. It must match the assets/maps/<map_name> folder name (lowercased) and becomes the GameMapType enum key.

name is the map's canonical name — the GameMapType enum value. It must never change once the map ships (it is part of the wire format and stored in game records).

translation_key is the key of the map's display name in ../resources/lang/en.json (map.<map_name>).

categories groups the map in the map picker. Each entry must be one of: featured, world, europe, asia, north_america, africa, south_america, oceania, antarctica, cosmic, tournament, other. Maps that straddle regions (e.g. Black Sea, Bering Strait) can list more than one. Add featured to show the map in the featured section of the map picker.

multiplayer_frequency is how many times the map appears in the public multiplayer playlist. Use 0 (or omit) to keep the map out of the regular rotation.

featured_rank (optional, featured maps only) is the map's position in the featured grid (1 = first). Featured maps without a rank sort after ranked ones, alphabetically.

flag is the code for a country

  • The full list of supported codes can be seen in ../src/client/data/countries.json - all ISO_3166 codes are supported, with several additions.

  • For quick reference, Use country codes found here

Update CREDITS.md

Add License & Attribution information to ../CREDITS.md. If you are unsure if a map's license can be used, open an issue or ask in Discord before beginning work.

Adding Flags

Flags can be added to ../resources/flags/<iso_code>.svg

The country will need to be added to ../src/client/data/countries.json

To Enable In-Game

GameMapType, mapCategories, mapTranslationKeys, and multiplayerFrequency are generated from the info.json files into ../src/core/game/Maps.gen.ts when the map-generator runs — do not edit that file by hand. The only step outside info.json is:

  • Add the map's display name to the map translation object in ../resources/lang/en.json (using your translation_key)

Notes

  • Islands smaller than 30 tiles (pixels) are automatically removed by the script.
  • Bodies of water smaller than 200 tiles (pixels) are also removed.
  • The map generator normalizes dimensions to multiples of 4. Any pixels beyond Width - (Width % 4) or Height - (Height % 4) are cropped.

For Performance Reasons:

  • Maps should be between 2 - 3 million pixels square (area).
  • Maps with over 3 million land tiles are not recommended.
  • Average land tile count is around 1 - 2 million.

🛠️ Development Tools

  • Format map-generator code:

    go fmt .
    
  • Output Map Generator Documentation:

    go doc -cmd -u -all
    

    The map-generator is a cli tool, to get any visibility, we pass -cmd. It also does not expose any API, so we use -u and -all to show all documentation for unexposed values.

    Known Bug Using -http does not respect the other flags and only renders the README