Skip to content

Map file serving

When your server uses Tiled or LDtk maps, clients need the raw map files to render levels. golem-engine can serve those files over HTTP alongside the WebSocket endpoint—no separate file server process needed.

ApproachWhen to use
bytes tile_data in WorldUpdateSmall maps (< ~500 KB). File travels in the proto frame; clients get it automatically on connect with no extra requests.
HTTP /maps/ + string map_urlLarge maps, or when you want browser caching. Clients fetch the file via HTTP using the URL they receive in the WorldUpdate.

Both approaches are wired from the same source: block in your world YAML—you only change url_prefix. See World schemas for the full YAML reference.

Set MapDir in ServerConfig. The server registers a /maps/ handler using http.FileServer at startup:

srv := golem.NewServer(golem.ServerConfig{
Addr: ":8080",
StaticDir: "public/", // optional, for other static assets
MapDir: "maps/", // serves everything in maps/ at /maps/
})

With this configuration, maps/level1.tmj is reachable at http://yourserver:8080/maps/level1.tmj.

The world schema then uses url_prefix: "/maps/":

schemas/world/level1.yaml
world: Level1
source:
format: tiled
file: maps/level1.tmj
url_prefix: "/maps/"

After golem-bake, LoadLevel1Data(path) sets MapUrl = "/maps/level1.tmj". The client reads that value from the received WorldUpdate and fetches the file:

// JS client (example)
worldManager.onLevel1Update = (d) => {
fetch(d.mapUrl)
.then(r => r.arrayBuffer())
.then(buf => renderer.loadTiledMap(buf));
};

When you omit Addr and mount the WebSocket handler on your own http.Server, use MapFileHandler to get an http.Handler for the same directory:

srv := golem.NewServer(golem.ServerConfig{TickRate: 20})
mux := http.NewServeMux()
mux.Handle("/ws", srv.Handler())
mux.Handle("/maps/", http.StripPrefix("/maps/", srv.MapFileHandler("maps/")))
go http.ListenAndServe(":8080", mux)
if err := srv.Run(ctx); err != nil && err != context.Canceled {
log.Fatal(err)
}

MapFileHandler(dir) returns an http.Handler you mount at the prefix of your choice.

http.FileServer sets standard caching headers based on Last-Modified. Map files change only when you redeploy, so clients that have already fetched a file will validate with a 304 Not Modified response on subsequent connects. No additional configuration is needed for basic caching behavior.

If you need stronger caching guarantees (immutable cache headers, content hashing), serve map files through a CDN or your own static asset pipeline and put the CDN URL in url_prefix instead of a server-relative path.

MapDir and StaticDir are independent:

  • StaticDir serves an arbitrary directory at / as a fallback for all non-WebSocket requests—useful for a built JS client.
  • MapDir serves one directory specifically at /maps/, intended for Tiled/LDtk files.

You can set both at once. They register on different URL prefixes and do not conflict.

See also World schemas for the source: block and url_prefix reference.