mapserver: config & readme
This commit is contained in:
parent
e21c3f825b
commit
bc7e9629c1
30
README.md
30
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.
|
||||
|
|
|
@ -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: '<a href="https://git.p2p.legal/tuxmain/minetest-tiler">minetest-tiler</a> | CC BY-SA <a href="https://juneland.fr">Juneland</a> Players'}).addTo(map)
|
||||
}, {
|
||||
"Points d'intérêt": L.layerGroup(points).addTo(map)
|
||||
}).addTo(map);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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<String>,
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 <t@txmn.tk> (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<String>,
|
||||
}
|
||||
|
||||
#[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::Config>,
|
||||
config: Arc<Args>,
|
||||
) -> 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<RwLock<HashMap<(i32, i32, i32), Sender<()>>>>,
|
||||
config: Arc<config::Config>,
|
||||
config: Arc<Args>,
|
||||
) -> 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<RwLock<HashMap<(i32, i32, i32), Sender<()>>>>,
|
||||
config: Arc<config::Config>,
|
||||
config: Arc<Args>,
|
||||
) -> Result<String, Error> {
|
||||
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<RwLock<HashMap<(i32, i32, i32), Sender<()>>>>,
|
||||
config: Arc<config::Config>,
|
||||
config: Arc<Args>,
|
||||
) -> Result<Vec<u8>, 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<RwLock<HashMap<(i32, i32, i32), Sender<()>>>>,
|
||||
config: Arc<config::Config>,
|
||||
config: Arc<Args>,
|
||||
) -> tide::Result {
|
||||
let z: i32 = req.param("z")?.parse()?;
|
||||
|
||||
|
|
Loading…
Reference in New Issue