You are viewing a potentially older version of this package. View all versions.
PmodTeam-MapPreviewGenerator-1.0.1 icon

MapPreviewGenerator

Generates real map preview thumbnails for Bopl Battle — vanilla maps and BoplMapMaker custom maps — cached as PNG. Exposes a public API for other mods (used by NextMapVote).

Date uploaded 4 hours ago
Version 1.0.1
Download link PmodTeam-MapPreviewGenerator-1.0.1.zip
Downloads 15
Dependency string PmodTeam-MapPreviewGenerator-1.0.1

This mod requires the following mods to function

BepInEx-BepInExPack-5.4.2305 icon
BepInEx-BepInExPack

BepInEx pack for Mono Unity games. Preconfigured and ready to use.

Preferred version: 5.4.2305

README

PMod Map Preview Generator

Generates real map preview thumbnails for Bopl Battle and exposes them to other mods through a small public API.

What it does

  • Captures real in-game screenshots of every vanilla map (once per map, cached as PNG in BepInEx/plugins/PmodMapPreview/)
  • For BoplMapMaker custom maps: loads the map's biome scene, places the map on it and screenshots it — real thumbnails, not placeholders
  • Installs the previews into the game's map selection UI automatically
  • Re-generates a preview when a map is edited in the Map Maker
  • Shows a progress panel at the top of the screen while previews are being generated

Reference the library

Two options:

Option A — compile-time reference (recommended)

Reference PMod.MapPreviewGenerator.dll from your project and add the dependency to your Thunderstore manifest.json:

"dependencies": ["BepInEx-BepInExPack_BoplBattle-5.4.2100", "PMod-MapPreviewGenerator-1.0.0"]
using PMod.MapPreviewGenerator;

Option B — runtime reflection (no compile-time dependency)

Resolve the type by name and call members via reflection. The type never causes a hard dependency, so your mod still works (without previews) if this one isn't installed.

static Type PreviewLib =
    AppDomain.CurrentDomain.GetAssemblies()
        .Select(a => a.GetType("PMod.MapPreviewGenerator.PreviewLibrary", false))
        .FirstOrDefault(t => t != null);

The vote mod NextMapVote ships a working example of this pattern (PreviewLibAdapter.cs).


API reference

All members are public static on the class PMod.MapPreviewGenerator.PreviewLibrary.

Lifecycle overview

The generator is fully automatic: when you enter a menu scene (buildIndex < 6) it arms a preload, captures every map that lacks a cached PNG (screenshots for vanilla maps, real biome-scene screenshots for custom maps), writes map_N.png / custom_N.png into BepInEx/plugins/PmodMapPreview/, and installs the previews into the game's map selection UI. A mod only needs to call EnsurePrepared before showing a preview and TryGetSprite to fetch it.

Identifiers

Context Identifier Example
Vanilla maps build-settings level id 0, 5, 21
BoplMapMaker custom maps index in 0..CustomMapCount-1 0, 1, 2

The active context is implicit: all methods below take a vanilla mapId; the custom-map section takes a customIndex. There is no overlap — custom maps are only used when CustomMapsAvailable is true.

Status & progress

Member Type Description
Busy bool True while a capture is running or queued. Nothing can be captured then, but previews already installed stay usable.
PreloadTotal int Total previews expected this session — input for a progress bar.
PreloadDone int Previews ready in memory or failed terminally (clamped to PreloadTotal).
InMenu bool True while in a menu scene (captures are only allowed then).
PreviewReady event Action<int> Fired whenever a real preview becomes available — vanilla mapId in vanilla mode, custom customIndex in MapMaker mode. Subscribe to refresh your UI.

Vanilla maps

Member Type Description
VanillaMapCount int Number of vanilla maps in the build.
HasRealPreview(mapId) bool True when a real (captured or cached) preview exists for the map.
EnsurePrepared(mapId) void Makes sure a preview exists for the map. Async: loads the PNG cache, otherwise queues a background capture and shows a procedural placeholder until it lands. Safe to call every frame.
TryGetSprite(mapId, out Sprite sprite) bool Fetches the current preview sprite, if any. Returns false (with sprite == null) when there is none yet.
InstallTexturePreview(mapId, tex) void Replaces the preview of a map with your own Texture2D. The generator tracks it for cleanup.
EnsureRealPreviewSync(mapId) void Synchronous variant of EnsurePrepared for vote-result time: guarantees the real cached screenshot even if its async load has not finished. Blocks briefly (one small PNG read).
StartPreloadAll() void Re-arms the menu preload and queues anything missing. Normally called automatically when a menu is entered.
QueueAllMissing() void Queues every map that still lacks a real preview.

BoplMapMaker custom maps

Member Type Description
CustomMapsAvailable bool True when the BoplMapMaker mod is present with loaded maps.
CustomMapCount int Number of custom maps available.
CustomMapName(customIndex) string Display name of a custom map (from its MetaData.json).
CustomMapType(customIndex) string Biome of a custom map: "grass", "snow" or "space".
CustomMapBaseLevelId(customIndex) int Vanilla base level id a custom map plays on (derived from its biome).
CustomMapJson(customIndex) string Raw .boplmap JSON of a custom map.
EnsureCustomPrepared(customIndex) void Same async semantics as EnsurePrepared, for custom maps.
TryGetCustomSprite(customIndex, out Sprite sprite) bool Fetches the preview sprite of a custom map.
CurrentCustomMapIndex int Custom map index currently being played.
CommitCustomMap(customIndex) void Commits a custom map into the MapMaker's state so the next round loads and renders it (CurrentMapIndex/NextMapIndex/CurrentMapUUID).
EnsureCommitted(customIndex) void Per-frame drift guard: keeps the MapMaker state pointed at the committed map until the level actually starts.

Typical usage

public class MyMapPicker : MonoBehaviour
{
    private void Start()
    {
        PreviewLibrary.PreviewReady += OnPreviewReady;
    }

    private void Update()
    {
        // Show a progress bar while generating
        int total = PreviewLibrary.PreloadTotal;
        int done = PreviewLibrary.PreloadDone;
        // ...

        // Cards: prepare lazily (no-op if already ready), then draw
        foreach (int mapId in myCandidates)
        {
            PreviewLibrary.EnsurePrepared(mapId);
            Sprite sprite;
            if (PreviewLibrary.TryGetSprite(mapId, out sprite))
            {
                // GUI.DrawTextureWithTexCoords(...)
            }
        }
    }

    private void OnPreviewReady(int mapId)
    {
        // A real preview just landed — force a repaint of that card
    }
}

Using custom maps

if (!PreviewLibrary.CustomMapsAvailable)
{
    // fall back to vanilla behaviour
    return;
}

// Show the MapMaker maps
for (int i = 0; i < PreviewLibrary.CustomMapCount; i++)
{
    PreviewLibrary.EnsureCustomPrepared(i);
    Debug.Log($"{PreviewLibrary.CustomMapName(i)} ({PreviewLibrary.CustomMapType(i)})");
}

// Make the next round play custom map #2
PreviewLibrary.CommitCustomMap(2);
// per frame until the level starts:
PreviewLibrary.EnsureCommitted(2);

Preview cache

  • Location: BepInEx/plugins/PmodMapPreview/
  • Vanilla: map_<levelId>.png
  • Custom: custom_<customIndex>.png
  • Screenshots are 640x360. Delete a PNG to force re-capture of that map on the next menu visit.

Requirements