Due to update 2.4.3, some mods may no longer function. FixedConfig may be necessary.
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).
By PmodTeam
| Last updated | 4 hours ago |
| Total downloads | 15 |
| Total rating | 0 |
| Categories | Mods Libraries |
| Dependency string | PmodTeam-MapPreviewGenerator-1.0.1 |
| Dependants | 1 other package depends on this package |
This mod requires the following mods to function
BepInEx-BepInExPack
BepInEx pack for Mono Unity games. Preconfigured and ready to use.
Preferred version: 5.4.2305README
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
NextMapVoteships 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
- BepInExPack for Bopl Battle
- Optional: BoplMapMaker for custom map previews