mirror of
https://github.com/neocturne/MinedMap.git
synced 2025-03-05 17:44:52 +01:00
Store source modified timestamp with processed, lightmap and map tiles
Allows to check whether the source is newer than the last update of the output files.
This commit is contained in:
parent
e18d4cea82
commit
628a702fd7
4 changed files with 75 additions and 15 deletions
|
@ -1,4 +1,4 @@
|
||||||
use std::path::Path;
|
use std::{path::Path, time::SystemTime};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
|
|
||||||
|
@ -65,14 +65,25 @@ impl<'a> RegionProcessor<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_region(&self, coords: TileCoords, processed_region: &ProcessedRegion) -> Result<()> {
|
fn save_region(
|
||||||
|
&self,
|
||||||
|
coords: TileCoords,
|
||||||
|
processed_region: &ProcessedRegion,
|
||||||
|
timestamp: SystemTime,
|
||||||
|
) -> Result<()> {
|
||||||
let output_path = self.config.processed_path(coords);
|
let output_path = self.config.processed_path(coords);
|
||||||
storage::write(&output_path, processed_region)
|
storage::write(&output_path, processed_region, timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_lightmap(&self, coords: TileCoords, lightmap: &image::GrayAlphaImage) -> Result<()> {
|
fn save_lightmap(
|
||||||
fs::create_with_tmpfile(
|
&self,
|
||||||
|
coords: TileCoords,
|
||||||
|
lightmap: &image::GrayAlphaImage,
|
||||||
|
timestamp: SystemTime,
|
||||||
|
) -> Result<()> {
|
||||||
|
fs::create_with_timestamp(
|
||||||
&self.config.tile_path(TileKind::Lightmap, 0, coords),
|
&self.config.tile_path(TileKind::Lightmap, 0, coords),
|
||||||
|
timestamp,
|
||||||
|file| {
|
|file| {
|
||||||
lightmap
|
lightmap
|
||||||
.write_to(file, image::ImageFormat::Png)
|
.write_to(file, image::ImageFormat::Png)
|
||||||
|
@ -90,6 +101,8 @@ impl<'a> RegionProcessor<'a> {
|
||||||
let mut processed_region = ProcessedRegion::default();
|
let mut processed_region = ProcessedRegion::default();
|
||||||
let mut lightmap = image::GrayAlphaImage::new(N, N);
|
let mut lightmap = image::GrayAlphaImage::new(N, N);
|
||||||
|
|
||||||
|
let timestamp = fs::modified_timestamp(path)?;
|
||||||
|
|
||||||
minedmap::io::region::from_file(path)?.foreach_chunk(
|
minedmap::io::region::from_file(path)?.foreach_chunk(
|
||||||
|chunk_coords, data: world::de::Chunk| {
|
|chunk_coords, data: world::de::Chunk| {
|
||||||
let Some(layer::LayerData{ blocks, biomes, block_light, depths }) = self
|
let Some(layer::LayerData{ blocks, biomes, block_light, depths }) = self
|
||||||
|
@ -111,8 +124,8 @@ impl<'a> RegionProcessor<'a> {
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.save_region(coords, &processed_region)?;
|
self.save_region(coords, &processed_region, timestamp)?;
|
||||||
self.save_lightmap(coords, &lightmap)?;
|
self.save_lightmap(coords, &lightmap, timestamp)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::time::SystemTime;
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
|
|
||||||
use minedmap::{
|
use minedmap::{
|
||||||
|
@ -17,9 +19,12 @@ impl<'a> TileRenderer<'a> {
|
||||||
TileRenderer { config }
|
TileRenderer { config }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_region(&self, coords: TileCoords) -> Result<ProcessedRegion> {
|
fn load_region(&self, coords: TileCoords) -> Result<(ProcessedRegion, SystemTime)> {
|
||||||
let processed_path = self.config.processed_path(coords);
|
let processed_path = self.config.processed_path(coords);
|
||||||
storage::read(&processed_path).context("Failed to load processed region data")
|
let timestamp = fs::modified_timestamp(&processed_path)?;
|
||||||
|
let region =
|
||||||
|
storage::read(&processed_path).context("Failed to load processed region data")?;
|
||||||
|
Ok((region, timestamp))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_chunk(image: &mut image::RgbaImage, coords: ChunkCoords, chunk: &ProcessedChunk) {
|
fn render_chunk(image: &mut image::RgbaImage, coords: ChunkCoords, chunk: &ProcessedChunk) {
|
||||||
|
@ -69,11 +74,11 @@ impl<'a> TileRenderer<'a> {
|
||||||
.display(),
|
.display(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let region = self.load_region(coords)?;
|
let (region, timestamp) = self.load_region(coords)?;
|
||||||
let mut image = image::RgbaImage::new(N, N);
|
let mut image = image::RgbaImage::new(N, N);
|
||||||
Self::render_region(&mut image, ®ion);
|
Self::render_region(&mut image, ®ion);
|
||||||
|
|
||||||
fs::create_with_tmpfile(&output_path, |file| {
|
fs::create_with_timestamp(&output_path, timestamp, |file| {
|
||||||
image
|
image
|
||||||
.write_to(file, image::ImageFormat::Png)
|
.write_to(file, image::ImageFormat::Png)
|
||||||
.context("Failed to save image")
|
.context("Failed to save image")
|
||||||
|
|
45
src/io/fs.rs
45
src/io/fs.rs
|
@ -2,19 +2,34 @@ use std::{
|
||||||
fs::{self, File},
|
fs::{self, File},
|
||||||
io::{BufReader, BufWriter, Read, Write},
|
io::{BufReader, BufWriter, Read, Write},
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
|
time::SystemTime,
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{Context, Ok, Result};
|
use anyhow::{Context, Ok, Result};
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
fn tmpfile_name(path: &Path) -> PathBuf {
|
#[derive(Debug, Serialize)]
|
||||||
|
struct FileMeta {
|
||||||
|
timestamp: SystemTime,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn suffix_name(path: &Path, suffix: &str) -> PathBuf {
|
||||||
let mut file_name = path.file_name().unwrap_or_default().to_os_string();
|
let mut file_name = path.file_name().unwrap_or_default().to_os_string();
|
||||||
file_name.push(".tmp");
|
file_name.push(suffix);
|
||||||
|
|
||||||
let mut ret = path.to_path_buf();
|
let mut ret = path.to_path_buf();
|
||||||
ret.set_file_name(file_name);
|
ret.set_file_name(file_name);
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn tmpfile_name(path: &Path) -> PathBuf {
|
||||||
|
suffix_name(path, ".tmp")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn metafile_name(path: &Path) -> PathBuf {
|
||||||
|
suffix_name(path, ".meta")
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_dir_all(path: &Path) -> Result<()> {
|
pub fn create_dir_all(path: &Path) -> Result<()> {
|
||||||
fs::create_dir_all(path)
|
fs::create_dir_all(path)
|
||||||
.with_context(|| format!("Failed to create directory {}", path.display(),))
|
.with_context(|| format!("Failed to create directory {}", path.display(),))
|
||||||
|
@ -84,3 +99,29 @@ where
|
||||||
|
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn modified_timestamp(path: &Path) -> Result<SystemTime> {
|
||||||
|
fs::metadata(path)
|
||||||
|
.and_then(|meta| meta.modified())
|
||||||
|
.with_context(|| {
|
||||||
|
format!(
|
||||||
|
"Failed to get modified timestamp of file {}",
|
||||||
|
path.display()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_with_timestamp<T, F>(path: &Path, timestamp: SystemTime, f: F) -> Result<T>
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut BufWriter<File>) -> Result<T>,
|
||||||
|
{
|
||||||
|
let ret = create_with_tmpfile(path, f)?;
|
||||||
|
|
||||||
|
let meta_path = metafile_name(path);
|
||||||
|
create(&meta_path, |file| {
|
||||||
|
serde_json::to_writer(file, &FileMeta { timestamp })?;
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(ret)
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ use std::{
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{Read, Write},
|
io::{Read, Write},
|
||||||
path::Path,
|
path::Path,
|
||||||
|
time::SystemTime,
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
|
@ -9,8 +10,8 @@ use serde::{de::DeserializeOwned, Serialize};
|
||||||
|
|
||||||
use super::fs;
|
use super::fs;
|
||||||
|
|
||||||
pub fn write<T: Serialize>(path: &Path, value: &T) -> Result<()> {
|
pub fn write<T: Serialize>(path: &Path, value: &T, timestamp: SystemTime) -> Result<()> {
|
||||||
fs::create_with_tmpfile(path, |file| {
|
fs::create_with_timestamp(path, timestamp, |file| {
|
||||||
let data = bincode::serialize(value)?;
|
let data = bincode::serialize(value)?;
|
||||||
let len = u32::try_from(data.len())?;
|
let len = u32::try_from(data.len())?;
|
||||||
let compressed = zstd::bulk::compress(&data, 1)?;
|
let compressed = zstd::bulk::compress(&data, 1)?;
|
||||||
|
|
Loading…
Add table
Reference in a new issue