mirror of
https://github.com/IntQuant/noita_entangled_worlds.git
synced 2025-10-19 07:03:16 +00:00
Sending deltas
This commit is contained in:
parent
f1573881a0
commit
5419556f88
4 changed files with 70 additions and 5 deletions
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue