piegamesde / BlockMap

An out-of-game map renderer and viewer for Minecraft 1.13–1.18 worlds [unmaintained]
MIT License
92 stars 22 forks source link

Feature Request: Web map #53

Open unsupervisednn opened 3 years ago

unsupervisednn commented 3 years ago

A leaflet powered web map would be nice.

I already made one, see https://lambdacraft.dev/craft/map/ The source https://github.com/LambdaCraft/LambdaMap

It's in react but can be statically compiled to deliverable html and js. The player positions are handled by a REST api in a fabric mod. The output of blockmap is passed through pngquant for small file delivery.

It would be nice however to have all this bundled into one server fabric mod, with updating player positions, refreshing tiles, etc.

Personally I would prefer if the server mod was lightweight as to not take up too much CPU in a client/server-worker model but perhaps if it hooked into the server instance to find the average TPS/MSPT and only do rendering when there is compute time available that would be great.

piegamesde commented 3 years ago

Thanks for your work on BlockMap! A feature like this is definitively planned, but it may take some time.

There already is some form of server support in BlockMap, even though it's a bit WIP and less documented. You seem to have implemented a few features that are already covered by BlockMap, so I'm very interested in your opinion.

The player positions are handled by a REST api in a fabric mod

When rendering a world in BlockMap, it already generates a lot of information about the world—including player names and positions—, saved into a compressed json file next to the images.

Personally I would prefer if the server mod was lightweight as to not take up too much CPU in a client/server-worker model but perhaps if it hooked into the server instance to find the average TPS/MSPT and only do rendering when there is compute time available that would be great.

How often would you like to update the map? Due to BlockMap only rendering regions modified since the last time, simply calling it in a systemd timer (or cron job) a few times an hour should not have a noticable impact on performance.

unsupervisednn commented 3 years ago

I didn't notice the new server render feature. I tried to use it but every dimension is failing for me on 1.16.1, I'll open a separate issue for that.

Really I'd like a dynmap-like map that is easy to drop into a server. Here's my take so far:

  1. The rendered.json.gz is too large a payload for downloading every so often just for player positions, it's 330KB compared to 1KB payload of only sending POI and player positions through a REST API. Separating the data in separate endpoints, for ex. one /poi and one /players means that the two endpoints can be reverse proxied differently, with poi cached every 5 min or so, and /players cached every few seconds. This is important for me as a server owner because I don't want to be DDoS'd through the exposed TCP http ports on the MC server so I only let a reverse proxy server talk to it and cache the responses to distribute to many web clients.

  2. I don't think the render-many function does zoom levels (full tiles shrunk to smaller and smaller scales), which is kind of important for a leaflet map. Showing the overview of a map should only take a few MB, but sending all the full zoom tiles is going to take 100MB+ for a 10km wide map. So if it were running on a cron job, and a chunk gets updated, that updated tile will have to be propagated up the zoom levels. I'm not sure what kind of algorithm that will take, perhaps it would be faster if the updated chunks could be cut, shrunk, and spliced into the existing higher zoom levels pngs.

  3. I've done testing and pngquant is the most efficient compression for these type of maps. It has no artifacts like jpg while being about the same size a jpg quality 80. The positions of pixels are lossless, only the color space is slightly affected and hard to notice. pngquant is a C lib with JNI bindings so it would add a binary to distribution, and it needs to be included if blockmap is going to handle zoom levels and care about tile payload size.

  4. Having the ability to hook into MC code as a server mod via a platform like fabric will allow rendering while server TPS is healthy, be able to announce on server when these renders are taking place, have in game commands, allow instant player placed POI pins on the map without doing a scan in the render phase, and any other features that requires MC server API.

These features may sound outside of scope for you as just a map tile generator, but it's all the things I have to worry about as a server operator who can't and won't use dynmap for performance or incompatibility reasons.

piegamesde commented 3 years ago
  1. There is the (untested and undocumented) feature I added recently that gives control on which pins are included in the output and which are not. As for the size, the map pins may be the culprit, as they include the image of the map as it is shown in Minecraft. If you are ready to dive into the code, have a look at ServerSettings.PinSettings. All settings are optional and default to include if not set. The following may get you started (this disables everything except player positions, also it's untested ^^ ):

    {
        …
        "show pins": {
            "players": "ALL",
            "maps": "false",
            "slime chunks": "false",
            "force-loaded chunks": "false",
            "barrier": "false",
            "world spawn": "false",
            "POIs": {},
            "structures": {},
        }
    }
    • The finest granularity level in BlockMap is a region file, or 32x32 chunks
    • No, the BlockMap render engine does not do zoom levels, I stripped out this functionality for code simplicity and moved it into the GUI code. I can see that this may pose a problem for web views.
    • A full rendered map can take up quite some space yes, but as the BlockMap GUI caches this and only requests modified tiles after this, it wasn't a big problem for me. But again, this probably isn't really feasible for a web view.
    • The usual way I do MIP mapping is by creating multiple maps, each half the size of the previous. The tiles are still kept at 512x512 pixels, so 2x2 regions files are zoomed down to one of the next level. This forms a simple tree structure that can be invalidated from bottom to top (as a region file changes, all upper levels are updated as well)
  2. I'm a bit reluctant to add this dependency to the source code

  3. These features sound awesome and I'd really like native server support for BlockMap, but I don't own any plugin servers and thus don't really know how to achieve this. I'll try to help out as best as I can though.

These features may sound outside of scope for you as just a map tile generator

The tile renderer is the BlockMap-core sub project. The CLI and GUI are separate projects that build on top of this, though they are all tailored to work together and thus in a single repository. If there's something to the CLI that can be improved for your use case, feel free to request features/changes. But if you want to do something custom that really fits your needs, you may want to consider building your tooling directly on top of BlockMap-core itself instead of the CLI middle layer. The core library has a pretty stable and fairly well documented API, but no standalone releases (e.g. you won't find it on Maven Central) yet.