Sending deltas

This commit is contained in:
IQuant 2024-06-04 20:21:08 +03:00
parent f1573881a0
commit 5419556f88
4 changed files with 70 additions and 5 deletions

View file

@ -41,8 +41,11 @@ mod test {
fn read_replay() {
let mut file = BufReader::new(File::open("worldlog.bin").unwrap());
let mut model = WorldModel::new();
let mut model2 = WorldModel::new();
let mut entry_id = 0;
while let Ok(entry) = bincode::deserialize_from::<_, WorldUpdateKind>(&mut file) {
while let Ok(entry) = bincode::deserialize_from::<_, WorldUpdateKind>(&mut file)
.inspect_err(|e| println!("{}", e))
{
match entry {
WorldUpdateKind::Update(entry) => {
let saved = entry.save();
@ -56,6 +59,7 @@ mod test {
entry.header.w as u32 + 1,
entry.header.h as u32 + 1,
);
// TODO
assert_eq!(entry, new_update);
}
WorldUpdateKind::End => {
@ -65,6 +69,10 @@ mod test {
let img = model.gen_image(x, y, 2048, 2048);
img.save(format!("/tmp/img_{}.png", entry_id)).unwrap();
}
let deltas = model.get_all_deltas();
model.reset_change_tracking();
model2.apply_all_deltas(&deltas);
}
}
}
@ -73,6 +81,9 @@ mod test {
let img = model.gen_image(x, y, 2048 * 2, 2048 * 2);
img.save(format!("/tmp/img_{}.png", entry_id)).unwrap();
let img = model2.gen_image(x, y, 2048 * 2, 2048 * 2);
img.save(format!("/tmp/img_model2.png")).unwrap();
// let mut mats = model.mats.iter().copied().collect::<Vec<_>>();
// mats.sort();
// for mat in mats {

View file

@ -1,5 +1,5 @@
use chunk::{Chunk, Pixel, PixelFlags};
use encoding::{NoitaWorldUpdate, PixelRunner};
use encoding::{NoitaWorldUpdate, PixelRun, PixelRunner};
use image::{Rgb, RgbImage};
use std::collections::{HashMap, HashSet};
@ -21,6 +21,12 @@ struct MatPalette {
colors: Vec<Rgb<u8>>,
}
#[derive(Debug)]
pub struct ChunkDelta {
runs: Vec<PixelRun<Option<Pixel>>>,
chunk_coord: (i32, i32),
}
impl MatPalette {
fn new() -> Self {
let raw_data = include_str!(concat!(
@ -57,6 +63,7 @@ impl WorldModel {
if current != pixel {
chunk.set_pixel(offset, pixel);
}
self.changed_chunks.insert(chunk_coord);
}
fn get_pixel(&self, x: i32, y: i32) -> Pixel {
@ -119,6 +126,53 @@ impl WorldModel {
runner.to_noita(x, y, (w - 1) as u8, (h - 1) as u8)
}
fn apply_chunk_delta(&mut self, delta: &ChunkDelta) {
// TODO: Also mark as updated?
let chunk = self.chunks.entry(delta.chunk_coord).or_default();
let mut offset = 0;
for run in &delta.runs {
for _ in 0..(run.length) {
if let Some(pixel) = run.data {
chunk.set_pixel(offset, pixel)
}
offset += 1;
}
}
assert_eq!(offset, CHUNK_SIZE * CHUNK_SIZE)
}
fn get_chunk_delta(&self, chunk_coord: ChunkCoord) -> Option<ChunkDelta> {
let chunk = self.chunks.get(&chunk_coord)?;
let mut runner = PixelRunner::new();
for i in 0..CHUNK_SIZE * CHUNK_SIZE {
runner.put_pixel(chunk.changed(i).then(|| chunk.pixel(i)))
}
let runs = runner.build();
Some(ChunkDelta { chunk_coord, runs })
}
pub fn apply_all_deltas(&mut self, deltas: &[ChunkDelta]) {
for delta in deltas {
self.apply_chunk_delta(delta)
}
}
pub fn get_all_deltas(&self) -> Vec<ChunkDelta> {
self.changed_chunks
.iter()
.filter_map(|&chunk_coord| self.get_chunk_delta(chunk_coord))
.collect()
}
pub fn reset_change_tracking(&mut self) {
for chunk_pos in &self.changed_chunks {
if let Some(chunk) = self.chunks.get_mut(&chunk_pos) {
chunk.clear_changed();
}
}
self.changed_chunks.clear();
}
pub fn get_start(&self) -> (i32, i32) {
let cx = self.chunks.keys().map(|v| v.0).min().unwrap_or_default();
let cy = self.chunks.keys().map(|v| v.1).min().unwrap_or_default();

View file

@ -1,6 +1,6 @@
use super::{encoding::RawPixel, CHUNK_SIZE};
#[derive(Clone, Copy, Default, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum PixelFlags {
#[default]
Unknown,
@ -8,7 +8,7 @@ pub enum PixelFlags {
Fluid,
}
#[derive(Clone, Copy, Default, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct Pixel {
pub flags: PixelFlags,
pub material: u16,

View file

@ -60,7 +60,7 @@ impl<Pixel: Eq + Copy> PixelRunner<Pixel> {
data: current,
});
self.current_pixel = Some(pixel);
self.current_run_len = 0;
self.current_run_len = 1;
} else {
self.current_run_len += 1;
}