Skip to content

Generate the co-op mission previews the API already points at - #330

Open
TimMasalme wants to merge 1 commit into
FAForever:developfrom
TimMasalme:coop-maps/generate-previews
Open

Generate the co-op mission previews the API already points at#330
TimMasalme wants to merge 1 commit into
FAForever:developfrom
TimMasalme:coop-maps/generate-previews

Conversation

@TimMasalme

Copy link
Copy Markdown
Contributor

Every co-op mission has a thumbnail URL and none of them has a file behind it.

CoopMapEnricher mints maps/previews/{small,large}/<folder>.vNNNN.png out of the zip name and never checks that it exists. The vault upload path writes previews in MapService.generatePreview, but co-op missions do not go through it, they come through this deployer, which never wrote one. Measured against the live CDN on 2026-08-21: of 42 mission folders, zero had the file the API points at.

What clients show instead is whatever art happens to sit in the map folder. That is why some missions have a preview, some have none, and two have the wrong one, which is what prompted this:

  • Operation Red Revenge arrived complete in #417 with preview art from an earlier draft of its own terrain. All of its files have exactly one commit, so it was wrong from the moment it was added.
  • Tha Atha Aez is worse. #417 replaced its .scmap and left the .png and .dds untouched; those are still from 2017-09-24. Its preview is seven years older than the map it claims to show, and letterboxed, because the map it does show was not square.

What this does

Previews are produced here, from three sources in a fixed order:

source missions why
the preview embedded in the mission's own .scmap 31 the only source that cannot disagree with the terrain
the .dds beside the map 12 their map is not in this repository, it is part of the game install. Same 256x256 BGRA layout, so the same decoder reads it, and it beats the 100x100 .png next to it
the stock map the mission's _scenario.lua names 1 Novax Station Assault has no image of its own anywhere. Its map is X1MP_012, whose vault preview already sits in this directory

The order is the point. Both missions with wrong art have a matching pair of wrong sidecars, .png and .dds wrong in the same way. A sidecar that could win over a map file would preserve exactly those two bugs.

Why not PreviewGenerator from faf-commons

It is the obvious candidate and it does not survive contact with the co-op missions. Run over all 44, all 44 fail, for two independent reasons:

  • it overlays markers read from images/map_markers, and the published com.faforever.commons:data artifact contains no images at all, so ImageIO.read gets a null stream ("input == null!"). Those files are in the API's own resources.
  • marker positions come from evaluating the mission's _save.lua, and a third of the campaign missions fail that outright ("attempt to index ? (a nil value)"): a co-op save file is a script, not a data table.

Both are the marker overlay, not the picture. So this takes the picture and leaves the overlay, which needs no marker art, no Lua, and nothing that can fail per mission. The .scmap layout it reads is the one ScmapPathFixer already walks and CI already verifies byte for byte, so no new parsing knowledge enters the repo, and no new dependency.

Sizes

128 and 512, matching FafApiProperties. Note the CDN carries two conventions: dualgap_adaptive.v0012 is 128/512 while theta_passage_5.v0001 and x1mp_012 are still 100/256 from before it. That is why the stock map fall back re-renders rather than copies, so an old file cannot leak the old size back in.

Backfill

An unchanged mission is never rezipped, so ensureMapPreviews fills in whatever is missing on any run. The existing missions get their previews on the next deployment without waiting to be edited, and there is no separate migration to run.

Verification

verifyCoopPreviews renders every mission in a MAPS_REPO checkout and reports source, size and colour count per mission:

44 of 44 mission(s) have a preview
  31 from their own map file
  12 from the sidecar .dds, their map not being in this repository
  1 from the stock map their scenario names
all good

It fails if a mission with a real map file produces nothing, if an image is a single flat colour (a map with no embedded preview still yields an image, just a uniformly black one, which would reach the CDN looking like a working file), or if no mission rendered from its own map file at all. Run headless, since the deployment job has no display.

The extraction was checked against the shipped art rather than assumed correct: of the 24 missions that have both, 17 agree to within 1.6 of 255 on a mean per-channel comparison. The outliers are the two above. As a second, independent check, the edge structure of each candidate was correlated against the map's own heightmap, which is the terrain itself and independent of any image:

embedded shipped
Tha Atha Aez 0.53 -0.05
Red Revenge 0.41 0.16
the other 20 equal to within 0.03

Known limits

  • The 12 sidecar missions cannot be verified. Their map is in the game archives, so there is nothing to hold the image against. If one of them has Red Revenge's problem, this will not catch it.
  • Novax rests on its _scenario.lua naming X1MP_012. That the mission is really played on that map is taken from the scenario, not verified.
  • Red Revenge and Tha Atha Aez still carry their wrong .png and .dds in faf-coop-maps. After this they are unused, but replacing them there would be tidier.

Every co-op mission has a thumbnail URL and none of them had a file
behind it. CoopMapEnricher mints
maps/previews/{small,large}/<folder>.vNNNN.png out of the zip name and
never checks that it exists; the vault upload path writes previews in
MapService.generatePreview, but co-op missions do not go through it,
they come through this deployer, which never wrote one. Measured
against the live CDN on 2026-08-21: of 42 mission folders, zero had the
file the API points at.

What clients show instead is whatever art happens to sit in the map
folder, which is why some missions have a preview, some have none, and
two have the wrong one. Operation Red Revenge arrived complete in #417
with preview art from an earlier draft of its own terrain. Tha Atha
Aez is worse: #417 replaced its .scmap and left the .png and .dds from
2017 untouched, so its preview is seven years older than the map and
shows a different one, letterboxed because that map was not square.

Previews are now produced here, from three sources in a fixed order:

  - the preview embedded in the mission's own .scmap (31 missions),
    which is the only source that cannot disagree with the terrain
  - the .dds beside the map (12), for the missions whose map is not in
    this repository at all but part of the game install. Same 256 by
    256 BGRA layout, so the same decoder reads it, and it beats the
    100 by 100 .png next to it
  - the stock map the mission's own _scenario.lua names (1), for Novax
    Station Assault, which has no image of its own anywhere. Its map is
    X1MP_012, whose vault preview already sits in this directory

The order is the point. Both missions with wrong art have a *matching
pair* of wrong sidecars, so a sidecar that could win over a map file
would preserve exactly those two bugs.

Not com.faforever.commons' PreviewGenerator: run over all 44 missions,
all 44 fail. It reads marker art from resources the published data
artifact does not contain (ImageIO gets a null stream), and it takes
marker positions from evaluating _save.lua, which a third of the
campaign missions refuse. Both are the marker overlay, not the picture,
so this takes the picture. The .scmap layout it needs is the one
ScmapPathFixer already walks and CI already verifies byte for byte.

Sizes follow the current vault convention, 128 and 512. The CDN still
carries older 100 and 256 files from before it, which is why the stock
map fall back re-renders rather than copies.

An unchanged mission is never rezipped, so ensureMapPreviews fills in
what is missing on any run: the existing missions get their previews
without waiting to be edited.

verifyCoopPreviews renders every mission in a MAPS_REPO checkout and
reports the source, size and colour count per mission. It fails if a
mission with a real map file produces nothing, if an image is a single
flat colour, or if no mission rendered from its own map file at all.
@coderabbitai

coderabbitai Bot commented Sep 2, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: 08c24d3b-60f5-4d13-b88d-c93abfebca89


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant