From bc7e9629c1de4e91beafde35ec03af43535af082 Mon Sep 17 00:00:00 2001 From: tuxmain Date: Tue, 22 Feb 2022 11:27:30 +0100 Subject: [PATCH] mapserver: config & readme --- README.md | 30 +++++++++++- index.html | 2 +- mapserver/Cargo.lock | 120 ++++++++++++++++++++++++++++++++++++++++++++++++ mapserver/Cargo.toml | 2 + mapserver/src/config.rs | 44 ------------------ mapserver/src/main.rs | 84 +++++++++++++++++++++++++++++---- 6 files changed, 226 insertions(+), 56 deletions(-) delete mode 100644 mapserver/src/config.rs diff --git a/README.md b/README.md index 0a8cf2e..1a5768a 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,12 @@ The output can be used with [Leaflet](https://leafletjs.com/). ## Use +Choose the strategy you prefer between complete periodic generation and cached on-demand generation: + +### Python generator + +Runs minetestmapper once for a given part of the map. You can run it with cron. You also need an external webserver (e.g. Apache, Nginx) to serve the generated tiles. + Dependencies: * [Python3](https://www.python.org/) @@ -17,12 +23,34 @@ Dependencies: Edit the settings in `mtmapper.py` according to your configuration. -``` +```bash python3 mtmapper.py ``` Depending on the world and the settings (number of zoom levels, number of blocks), it may take a while. +### Rust mapserver + +A program that runs minetestserver automatically and serves cached tiles through an included webserver. You can run it as a daemon. + +Dependencies: + +* [Rust](https://rustup.rs/) (minimal toolchain is enough) (for building only) +* [minetestmapper](https://github.com/minetest/minetestmapper) +* [Colors.txt](https://github.com/MilesBDyson/Colors.txt) (optional -- more complete colorset) + +```bash +cd mapserver +cargo build --release +./target/release/mapserver --help +# Example with arguments: +./target/release/mapserver -w /var/games/minetest-server/.minetest/worlds/juneland-survival/ -p /home/tuxmain/minetestmapper/minetestmapper -- --drawalpha --max-y 2000 --colors /home/tuxmain/Colors.txt/colors.txt +``` + +### Web interface + +Both generation methods need a webpage(can be served by a webserver like Apache, Nginx): + Edit `index.html` (change the tiles URL, title, attribution and points of interest). You can keep my server as a CDN for Leaflet, but it's preferable to host your own copy of Leaflet. diff --git a/index.html b/index.html index 935051d..f4b48a6 100644 --- a/index.html +++ b/index.html @@ -58,7 +58,7 @@ function onMapClick(e) { map.on('click', onMapClick); L.control.layers({ - "Juneland Survival": L.tileLayer(MAP_TILES, {attribution: "CC BY-SA Juneland Players"}).addTo(map) + "Juneland Survival": L.tileLayer(MAP_TILES, {attribution: 'minetest-tiler | CC BY-SA Juneland Players'}).addTo(map) }, { "Points d'intérêt": L.layerGroup(points).addTo(map) }).addTo(map); diff --git a/mapserver/Cargo.lock b/mapserver/Cargo.lock index 604000c..7292d3f 100644 --- a/mapserver/Cargo.lock +++ b/mapserver/Cargo.lock @@ -447,6 +447,33 @@ dependencies = [ ] [[package]] +name = "clap" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d76c22c9b9b215eeb8d016ad3a90417bd13cb24cf8142756e6472445876cab7" +dependencies = [ + "bitflags", + "clap_derive", + "indexmap", + "lazy_static", + "os_str_bytes", + "textwrap", +] + +[[package]] +name = "clap_derive" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd1122e63869df2cb309f449da1ad54a7c6dfeb7c7e6ccd8e0825d9eb93bb72" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "color_quant" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -602,6 +629,26 @@ dependencies = [ ] [[package]] +name = "directories" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] name = "discard" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -770,6 +817,18 @@ dependencies = [ ] [[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + +[[package]] name = "hermit-abi" version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -876,6 +935,16 @@ dependencies = [ ] [[package]] +name = "indexmap" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] name = "infer" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -950,7 +1019,9 @@ name = "mapserver" version = "0.1.0" dependencies = [ "async-std", + "clap", "crossbeam-channel", + "directories", "http-types", "image", "log", @@ -1045,6 +1116,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] +name = "os_str_bytes" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +dependencies = [ + "memchr", +] + +[[package]] name = "parking" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1160,6 +1240,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] name = "proc-macro-hack" version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1264,6 +1368,16 @@ dependencies = [ ] [[package]] +name = "redox_users" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +dependencies = [ + "getrandom 0.2.4", + "redox_syscall", +] + +[[package]] name = "route-recognizer" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1539,6 +1653,12 @@ dependencies = [ ] [[package]] +name = "textwrap" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" + +[[package]] name = "thiserror" version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/mapserver/Cargo.toml b/mapserver/Cargo.toml index a67520e..ea7eb75 100644 --- a/mapserver/Cargo.toml +++ b/mapserver/Cargo.toml @@ -5,7 +5,9 @@ edition = "2021" [dependencies] async-std = { version = "1.6.5", features = ["attributes"] } +clap = { version = "3.1.1", default-features = false, features = ["derive", "std"] } crossbeam-channel = "0.5.2" +directories = "4.0.0" http-types = "2.12.0" image = { version = "0.24.1", default-features = false, features = ["png"] } log = "0.4.14" diff --git a/mapserver/src/config.rs b/mapserver/src/config.rs deleted file mode 100644 index ee8b12a..0000000 --- a/mapserver/src/config.rs +++ /dev/null @@ -1,44 +0,0 @@ -// TODO x,y bounds -pub struct Config { - /// Must start and end with `/` - pub base_url: String, - pub cache_age: u64, - pub listen: String, - pub mapper_threads: usize, - pub minetestmapper_args: Vec, - pub minetestmapper_path: String, - /// Should end with `/` - pub output_path: String, - pub tile_size: usize, - pub world_path: String, - pub zoom_default: i32, - pub zoom_max: i32, - pub zoom_min: i32, -} - -impl Default for Config { - fn default() -> Self { - Self { - base_url: String::from("/"), - cache_age: 86400, - listen: String::from("127.0.0.1:8080"), - mapper_threads: 4, - minetestmapper_args: vec![ - String::from("--drawalpha"), - String::from("--max-y"), - String::from("2000"), - String::from("--colors"), - String::from("/home/tuxmain/Colors.txt/colors.txt"), - ], - minetestmapper_path: String::from("/home/tuxmain/minetestmapper/minetestmapper"), - output_path: String::from("/var/www/html/minetest-map/survival/"), - tile_size: 256, - world_path: String::from( - "/var/games/minetest-server/.minetest/worlds/juneland-survival/", - ), - zoom_default: 7, - zoom_max: 10, - zoom_min: 4, - } - } -} diff --git a/mapserver/src/main.rs b/mapserver/src/main.rs index 96c86a1..4696e03 100644 --- a/mapserver/src/main.rs +++ b/mapserver/src/main.rs @@ -1,13 +1,70 @@ #![feature(try_blocks)] -mod config; +//mod config; +use clap::Parser; use crossbeam_channel::Sender; -use log::{debug, error, warn}; +use log::{debug, error, info, warn}; use parking_lot::RwLock; use std::{collections::HashMap, io::Read, sync::Arc, time::SystemTime}; use tide::Request; +fn get_cache_dir() -> String { + let dir = directories::ProjectDirs::from("tk", "txmn", "minetest-tiler").map_or_else( + String::new, + |o| { + o.cache_dir() + .to_str() + .map_or_else(String::new, String::from) + }, + ); + if dir.ends_with('/') { + dir + } else { + format!("{}/", dir) + } +} + +#[derive(Parser, Debug)] +#[clap( + author = "tuxmain (GNU AGPLv3)", + about = "Map generator & server for MineTest" +)] +struct Args { + /// Must start and end with `/` + #[clap(short = 'b', long, default_value = "/")] + base_url: String, + /// Cache duration in seconds + #[clap(short = 'c', long, default_value_t = 86400)] + cache_age: u64, + /// Address to listen to + #[clap(short = 'l', long, default_value = "0.0.0.0:30800")] + listen: String, + /// Directory that will contain the map (should end with `/`) + #[clap(short='o', long, default_value_t=get_cache_dir())] + output_path: String, + /// World directory + #[clap( + short = 'w', + long, + default_value = "/var/games/minetest-server/.minetest/world/world/" + )] + world_path: String, + #[clap(short = 'z', long, default_value_t = 7)] + zoom_default: i32, + #[clap(short = 'm', long, default_value_t = 4)] + zoom_min: i32, + #[clap(short = 'M', long, default_value_t = 10)] + zoom_max: i32, + #[clap(short = 's', long, default_value_t = 256)] + tile_size: usize, + /// Path to minetestmapper executable + #[clap(short = 'p', long, default_value = "minetestmapper")] + minetestmapper_path: String, + #[clap(last = true)] + minetestmapper_args: Vec, +} + #[derive(Debug)] enum Error { Image(image::ImageError), @@ -17,6 +74,8 @@ enum Error { #[async_std::main] async fn main() -> tide::Result<()> { + let config = Args::parse(); + simplelog::TermLogger::init( simplelog::LevelFilter::Info, simplelog::Config::default(), @@ -25,7 +84,7 @@ async fn main() -> tide::Result<()> { ) .unwrap(); - let config = config::Config::default(); + info!("Output dir: {}", config.output_path); assert!( config.base_url.starts_with('/') && config.base_url.ends_with('/'), "`base_url` must start and end with `/`" @@ -50,7 +109,7 @@ fn run_minetestmapper( y: i32, tile_dir: &str, tile_path: &str, - config: Arc, + config: Arc, ) -> Result<(), Error> { debug!("Generating tile ({},{},{})", z, x, y); std::fs::create_dir_all(tile_dir).map_err(|e| { @@ -97,7 +156,7 @@ fn generate_tile( tile_dir: &str, tile_path: &str, tasks: Arc>>>, - config: Arc, + config: Arc, ) -> Result<(), Error> { let mut generate = true; loop { @@ -195,8 +254,13 @@ fn generate_tile( })?; } std::cmp::Ordering::Greater => { - let ntile_path = - get_dep_tile(z - 1, lock_coord.1 / 2, lock_coord.2 / 2, tasks.clone(), config.clone())?; + let ntile_path = get_dep_tile( + z - 1, + lock_coord.1 / 2, + lock_coord.2 / 2, + tasks.clone(), + config.clone(), + )?; let ntile = image::open(ntile_path).map_err(Error::Image)?; let ntile = image::imageops::resize( &ntile, @@ -310,7 +374,7 @@ fn get_dep_tile( x: i32, y: i32, tasks: Arc>>>, - config: Arc, + config: Arc, ) -> Result { let tile_dir = format!("{}{}/{}", config.output_path, z, x); let tile_path = format!("{}/{}.png", tile_dir, y); @@ -350,7 +414,7 @@ fn resp_tile( tile_dir: &str, tile_path: &str, tasks: Arc>>>, - config: Arc, + config: Arc, ) -> Result, Error> { generate_tile(z, x, y, tile_dir, tile_path, tasks, config)?; read_tile_file(tile_path) @@ -359,7 +423,7 @@ fn resp_tile( async fn req_tile( req: Request<()>, tasks: Arc>>>, - config: Arc, + config: Arc, ) -> tide::Result { let z: i32 = req.param("z")?.parse()?;