You are viewing a potentially older version of this package. View all versions.
f00d4tehg0dz-ValheimWebMap-2.0.0 icon

ValheimWebMap

Live web map for your dedicated server. 3D/2D view with the game's own models, fog of war, players, bases, portals, stats.

Date uploaded 2 weeks ago
Version 2.0.0
Download link f00d4tehg0dz-ValheimWebMap-2.0.0.zip
Downloads 74
Dependency string f00d4tehg0dz-ValheimWebMap-2.0.0

This mod requires the following mods to function

denikson-BepInExPack_Valheim-5.4.2350 icon
denikson-BepInExPack_Valheim

BepInEx pack for Valheim. Preconfigured with the correct entry point for mods and preferred defaults for the community.

Preferred version: 5.4.2350

README

Valheim WebMap

Mod for your Valheim server. Makes a live map of your world you open in a browser. Share http://your_ip:3000. Players install nothing. Server only.

3D view of a player base

What it does

  • Big map, every metre. One pixel is one metre. Seven zoom levels. Shows ground the way players shaped it: flat bases, moats, roads, farms. Trees, bushes and rocks drawn on top as their own layer. Checkbox turns them off. Cut a forest down, map shows the clearing next time it draws.
  • Buildings. Every piece anyone placed, drawn as a footprint in its material colour. Hover to see what it is.
  • 3D view. One click. Real ground, water, and every object drawn with the game's own model: walls, roofs, portals, ruins, trees, rocks, boats. Same spot, same rotation, same size as in the game. Ground has fine grain up close, no seams, no grid. Base looks like your base.
  • Fog of war. Ground nobody walked on is black. No switch to turn it off. Close-up tiles only draw where players walked.
  • Live players. Arrow points where they look. Health bar. Biome. PvP, sleeping, dead. Follow one. Pings and chat pins land on the map.
  • Player card. Click a player, on the map, in 3D, or in the list. Card shows health, stamina, eitr, what they wear and hold, how long they played, deaths, distance walked, visits. Updates live. Buttons: follow, go to, switch view.
  • Markers. Portals with their tags and links, tombstones, player bases, boats, carts, your own markers.json. Boss altars, dungeons, traders and the world seed are never sent out. No spoilers.
  • Stats. Per player: time played, visits, deaths, distance, portal trips, biomes. Per server: day, explored %, pieces built, trees, who was online last 24 h.
  • Events. Joins, leaves, deaths, chat, pings. Saved to events.jsonl.
  • Export. Pick an area, get a 3D file. Ground, water, every building and object, trees, markers. Opens in Blender, Unreal, Unity, Godot. Unreal pack has a heightmap too. See docs/EXPORT.md.
  • Also: share links, search, works on phone, dark UI, Discord webhook, POST /announce to shout at everyone.

Player base in 3D 2D map Stats

Install

  1. Put BepInEx on the server. Copy the WebMap folder to

    <server>/BepInEx/plugins/WebMap
    

    Folder holds WebMap.dll, websocket-sharp.dll, web/.

    Docker (lloesche/valheim-server): with BEPINEX=true, BepInEx lives at /opt/valheim/bepinex/BepInEx on the data volume. /config/bepinex is only config. Plugin goes to /opt/valheim/bepinex/BepInEx/plugins/WebMap. Easiest: bind-mount a host folder there. Example in tools/docker-compose.test.yml. Config lands in <config volume>/bepinex/com.valheimwebmap.server.cfg. Open the port: -p 3000:3000/tcp.

  2. Start server once. It writes the default config to BepInEx/config.

  3. Edit config if you want. Restart. Config is read at start only.

  4. Open port 3000. Visit http://your_ip:3000.

Map data lives in plugins/WebMap/map_data/<World>/. Model library in plugins/WebMap/map_data/models/. Keep both when you update.

Behind Cloudflare or another cache? Purge it after every update, or set a rule to not cache this host. The mod already sends the right headers.

First start

Server draws the zoomed-out map first (zoom 0–5, ~500 tiles, one to two minutes on one core). Then close-up tiles where players walked. Page works right away: missing tiles show the zoomed-out one blown up, swap in when done. Counter bottom-left: drawn / waiting.

First start also exports the 3D models. ~300 prefabs, under a minute. Done once, kept forever. Log: WebMap: models exported N (readable meshes R, ...).

Textures

Server does not let anyone read textures. So the mod reads them straight out of the game's own files instead. Background thread, low priority, starts a few seconds after the first model export. Windows, Linux, Docker. Nothing to install. One to two minutes over ~2 GB of game files, once per game version. Log:

WebMap: extracting 142 textures from the game files in .../valheim_server_Data
WebMap: 139 of 142 textures extracted from 61 files in 74s, 3 not found
WebMap: 180 models to re-export with newly extracted textures

Textures are game files. Not in this repo. Not in the mod zip. Never shared. They only ever sit in your map_data/models/ folder, made from your own server. use_textures = false skips all of it (flat colours). texture_max_size caps them (default 512).

Doing it by hand, same job, plain Python 3, no packages:

python3 tools/extract_textures.py <valheim_server_Data> <plugins>/WebMap/map_data/models

Server load

Map drawing runs on its own thread (render_threads, default 1, low priority). Game thread only does: one slow walk over the world every sweep_interval seconds (3,000 objects per frame), player snapshot once a second, fog, model export within export_ms_per_frame. PNGs are made by the mod's own writer, off the game thread.

If the engine refuses to sample ground off the game thread, the mod does a few rows per frame on it instead. Slower. Never freezes. render_threads = 0 forces that.

Disk: whole world at 1 m/px is ~6,400 tiles, few hundred MB. Only walked ground draws close up, so a normal world is tens of MB. max_render_zoom = 6 cuts that by four.

Config

Section Key Default What
Render render_threads 1 threads drawing tiles (0 = do it on game thread, slowly)
Render prerender_zoom 5 draw the whole world up to this zoom at first start
Render max_render_zoom 7 closest zoom over walked ground (7 = 1 m/px)
Render height_max_zoom 7 closest zoom for height tiles (3D)
Sweep sweep_interval 120 seconds between world walks
Sweep zdos_per_frame 3000 objects looked at per frame during a walk
Markers reveal_all false no fog: whole world shown and sent out. Testing only
User always_map true lift fog where hidden players walk. Their spot stays hidden
User always_visible false ignore players' "hidden" setting
User show_last_seen_position false offline players' last spot in stats
Server server_port 3000 HTTP port
Server map_title (server name) title on the page
Server enable_3d true offer the 3D view
Server event_log true write events to events.jsonl
Server legacy_map true build one big map.png for /map
Models export_models true export prefab meshes for 3D
Models object_categories piece,other,rock,bush,tree what the 3D view and export get
Models use_textures true textures on 3D models (off: flat colours)
Models texture_max_size 512 longest texture edge
Models export_ms_per_frame 6 game-thread ms per frame for export
Texture explore_radius 100 metres revealed around a player
Discord discord_webhook, discord_invite_url webhook for events
Server webmap_url, max_pins_per_user link shown in game, pin limit

Your own markers

Put markers.json next to the world's map data (plugins/WebMap/map_data/<world>/markers.json). Read again when it changes.

{ "sets": [
  { "id": "mines", "label": "Mines", "markers": [
    { "x": 2210, "z": 980, "label": "Silver mine", "icon": "mine", "description": "north face" }
  ] }
] }

Icons: pin dot fire mine house cave boss trader dungeon camp village ruin runestone wreck portal tombstone boat cart poi spawn.

Player card

Click a player. Card pops up next to them. Health, stamina, eitr as bars. State: PvP, sleeping, dead. Biome and coordinates. What they hold in each hand and wear on head, chest, legs, back, belt. Lifetime numbers: played, deaths, walked, visits, portal trips. Follow, go to, switch 2D/3D. Card stays open and updates live. Escape or click away closes it. Works on the 2D map, in 3D, and from the Players list. Game only sends current stamina and eitr, not the max, so those bars fill against 100 or the current value.

Export a 3D scene

Download button, top bar. Pick the area (what you see on the 2D map, or 256 m to 1.5 km around the centre), ground detail, what to include, format:

  • glTF, instanced. One mesh per prefab, placed many times. Small file. Blender, Godot, three.js.
  • glTF, one object per node. Unreal, Unity, anything that lacks the instancing extension. Bigger file, same stuff.
  • Unreal pack. Zip: the flat scene, heightmap_r16.png for a Landscape, instances.csv and markers.csv in Unreal units, an editor Python script, README with the exact Landscape scale and location numbers.

Made in the browser from what the map already shows. Fog applies: nothing undiscovered leaves the server. Meshes and textures are the game's own files from your server. Use the export yourself, do not pass it around. Steps per editor in docs/EXPORT.md.

HTTP API

Path Returns
/tiles/map/{z}/{x}/{y}.png ground tile, zoom 0–7. 404 + X-WebMap-Tile: pending while drawing
/tiles/veg/{z}/{x}/{y}.png tree and rock overlay, zoom 5–7, transparent PNG
/tiles/height/{z}/{x}/{y}.png height tile, Terrarium encoding
/data/structures/index.json, /data/structures/{cx}_{cz}.json pieces per 256 m chunk
/data/veg/{cx}_{cz}.bin vegetation points per chunk (Vegetation.cs)
/data/objects/index.json, /data/objects/{cx}_{cz}.bin every placed object per chunk: prefab, position, rotation, scale (WorldObjects.cs)
/data/prefabs.json model library: which prefabs have a model, bounds, triangles, textures
/models/{hash}.glb, /models/tex_*.png exported models and textures. Cacheable
/data/markers.json marker sets
/data/players.json live players: position, health, stamina, eitr, gear, state
/data/stats.json, /data/events.json, /data/pins.json stats, events, pins
/data/fog.png explored mask, north up
/config, /api/status config, drawing and sweep status
POST /api/sweep walk the world now
POST /api/rerender?zoom=N redraw tiles from zoom N up (token)
POST /api/reexport export every model again (token)
POST /announce message on every player's screen (token)
/map, /map.jpg, /fog, /players, /pins, /messages, /structures, /structures/stats, /structures/refresh, /forest, /forest/stats, /vehicles simple endpoints: one-image map, plain lists

Websocket at /ws. JSON frames: hello, players, events, tiles, world, ping, pin, rmpin, reload.

Tile grid: world is a 20,480 m square around the origin. Zoom 7: one pixel is one metre. Tile (0,0) is the north-west corner. Zoom z has 2^(7-z) metres per pixel. tx = floor((x + 10240) / (256 · 2^(7-z))), ty = floor((10240 − z_world) / (256 · 2^(7-z))).

Token

POST /announce, /api/rerender, /api/reexport need a secret in header X-Announce-Token. Secret is read from file announce.token next to the DLL. No file, no access.

Chat commands

  • !pin [type] [text] — types dot, fire, mine, house, cave
  • !undoPin, !deletePin [text]

Build

Windows: .\build.ps1. Needs .NET SDK and the Steam "Valheim Dedicated Server" tool, or -ValheimManaged <path>. Linux/macOS: ./build.sh. Output: dist/ValheimWebMap-<version>.zip and dist/pkg/WebMap/. -Deploy <plugins dir> or --deploy copies the plugin there.

Try it without a real server

tools/mockserver.js (Node, no packages): serves the web app with a made-up world, fake players, fake events. node tools/mockserver.js, open http://localhost:3000.

tools/docker-compose.test.yml: real dedicated server (lloesche image) with a copy of your world.

# copy world folder to valheim-test\config\worlds_local\<World>\
.\build.ps1 -Deploy valheim-test\plugins
docker compose -f tools\docker-compose.test.yml up      # first run downloads server

Then http://localhost:3000. In game: Join by IP, 127.0.0.1:2456

A copied world starts with no fog lifted. Exploring lives in player files, not the world. Map stays black until someone walks. For tests set reveal_all = true in valheim-test\config\bepinex\com.valheimwebmap.server.cfg and restart: no fog, whole world. Tiles still draw as you look.

Licence

MIT. See LICENSE. Leaflet (BSD-2) and three.js (MIT) vendored under web/vendor.

CHANGELOG

Changelog

2.1.5

  • Keyboard everywhere: WASD/arrows move, Q E turn, R F tilt, Z X zoom, Shift fast, P follow next player, M 2D/3D, L layers, Home spawn. Double click in 3D centres on that spot. README "Controls".
  • Follow works in 3D: camera glides after the player; drag, WASD or Esc lets go. Following carries over when you switch 2D/3D.
  • "Lighting (3D)" heading in Layers for time of day and shadows.

2.1.4

  • Sky, sun, moon and shadows in 3D. Sky dome with sun disc, stars, dawn and dusk colours; fog to the horizon; the sun follows the server's time of day (Layers > "Time of day", or pick a fixed one); buildings, trees and hills cast shadows (toggle, off on phones by default); water ripples and mirrors the sky; filmic tone mapping.

2.1.3

  • Every model, not one in eight. The engine locks most meshes, so the 3D view drew boxes (a cart with its boxes but no cart, a bare beehive). The mod now reads locked meshes out of the game files like it already did textures: extract_meshes config, map_data/models/meshes/, tools/extract_meshes.py by hand. Model library format 5: everything is exported again once.
  • Materials that keep their colour map under _BaseMap and friends get their texture too.

2.1.1

  • Addressed issue #2 with !pin command not working. Pins from the web page. Right click (long press on a phone), pick a type, label, done. Remove your own from the popup. POST /api/pin, POST /api/unpin?id=. web_pins turns it off.
  • Addressed issue #3 with title bar in Mobile not being supported.
  • Addressed issue #1 with Web dir not being included in build, causing mod manager Gale to fail installation
  • Addressed issue #5 with @Aughen PR #6. WebSocket compression off by default, websocket_compression turns it back on.
  • Addressed issue with fog coverage not being 100% on initial load with @clanofartisans PR #7
  • Build script: one -ValheimManaged path works. (#6)
  • POST /api/reload (token): Update the web app without restarting the game.
  • Layer list says "Pins", not "Chat pins".

2.1.0

  • Old trips count. Fog lifts everywhere players have already been, even from before the mod was installed. The world save lists every zone the game built, and it only builds them near a player. Runs at start and once a minute. reveal_visited (on) and reveal_visited_margin (3 zones, about 150 m from where they walked).
  • Player card. Click a player on the map, in 3D or in the list: health, stamina, eitr, what they wear and hold, state, lifetime stats. Updates live. Server now sends stamina, eitr and gear.
  • Export. Pick an area, get a 3D scene: glTF (instanced, or one node per object) or an Unreal pack with a 16-bit heightmap, CSVs in Unreal units and an editor script. Made in the browser. Fog applies.
  • Demo site. tools/Dockerfile.demo and docker-compose.demo.yml run the mock server as a public demo. Mock draws the tree and rock overlay and loops forever.
  • Stats table fits the sidebar. README in plain words.

1.0.1

First public release. Same as 1.0.0 plus README and screenshot fixes.

1.0.0

First release.

  • Tiled map, seven zoom levels, 1 m/px. Rendered from world generator plus player terraforming (levelled ground, moats, paved roads, farmland). Trees, bushes, rocks as a separate overlay layer. Close-zoom tiles render only over explored ground. Re-render when ground changes. Worker thread, own PNG encoder, sliced main-thread fallback.
  • Buildings as vector data per 256 m chunk: footprint, height, material, prefab. Drawn as material-coloured footprints with hover info.
  • 3D view (three.js). Terrain from height tiles with quadtree LOD, seamless between tiles, clean ground tiles with tiled fine grain up close. Water. Players. Markers. World objects as game's own meshes: mod exports each prefab to glTF once (map_data/models/), publishes each chunk's objects with prefab, position, rotation, scale. Browser instances models.
  • Textures pulled from the game's own asset files by the mod itself, in the background, on every platform. tools/extract_textures.py as manual fallback. POST /api/reexport rebuilds models.
  • Fog of war always on. Black over unexplored ground. World locations (bosses, dungeons, traders) never published.
  • Markers: portals with tags and links, tombstones, player bases (clusters of built pieces), boats, carts, custom markers.json sets.
  • Layer toggles drive 2D and 3D: buildings with opacity, players, chat pins, trees and rocks overlay (2D), labels, 256 m grid, marker sets, object categories.
  • Stats per player: playtime, sessions, deaths, distance, portal trips, biomes. Per server: day, explored %, counts, online history.
  • Event feed with events.jsonl history. Deaths carry position.
  • Web app: dark UI, sidebar, search, permalinks, follow mode, mobile layout. No build step.
  • Simple endpoints kept for scripts: /map, /players, /pins, /messages, /structures, /forest, /vehicles. Websocket speaks JSON.
  • Discord webhook, POST /announce, chat pin commands.