diff --git a/Cargo.lock b/Cargo.lock index 8a635fc..36e10e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,11 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9fe5e32de01730eb1f6b7f5b51c17e03e2325bf40a74f754f04f130043affff" + [[package]] name = "adler" version = "1.0.2" @@ -38,6 +44,19 @@ dependencies = [ "memchr", ] +[[package]] +name = "andrew" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c4afb09dd642feec8408e33f92f3ffc4052946f6b20f32fb99c1f58cd4fa7cf" +dependencies = [ + "bitflags", + "rusttype", + "walkdir", + "xdg", + "xml-rs", +] + [[package]] name = "anyhow" version = "1.0.40" @@ -65,7 +84,7 @@ version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06063a002a77d2734631db74e8f4ce7148b77fe522e6bca46f2ae7774fd48112" dependencies = [ - "libloading", + "libloading 0.7.0", ] [[package]] @@ -150,6 +169,16 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "calloop" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b036167e76041694579972c28cf4877b4f92da222560ddb49008937b6a6727c" +dependencies = [ + "log", + "nix 0.18.0", +] + [[package]] name = "cc" version = "1.0.68" @@ -406,7 +435,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "091ed1b25fe47c7ff129fc440c23650b6114f36aa00bc7212cc8041879294428" dependencies = [ "bitflags", - "libloading", + "libloading 0.7.0", "winapi", ] @@ -472,6 +501,30 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +[[package]] +name = "dlib" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b11f15d1e3268f140f68d390637d5e76d849782d971ae7063e0da69fe9709a76" +dependencies = [ + "libloading 0.6.7", +] + +[[package]] +name = "dlib" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794" +dependencies = [ + "libloading 0.7.0", +] + +[[package]] +name = "downcast-rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" + [[package]] name = "either" version = "1.6.1" @@ -674,7 +727,7 @@ dependencies = [ "bitflags", "gfx-auxil", "gfx-hal", - "libloading", + "libloading 0.7.0", "log", "parking_lot", "range-alloc", @@ -732,7 +785,7 @@ dependencies = [ "glow", "js-sys", "khronos-egl", - "libloading", + "libloading 0.7.0", "log", "naga", "parking_lot", @@ -981,9 +1034,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" dependencies = [ "cfg-if 1.0.0", - "js-sys", - "wasm-bindgen", - "web-sys", ] [[package]] @@ -1050,7 +1100,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" dependencies = [ "libc", - "libloading", + "libloading 0.7.0", ] [[package]] @@ -1065,6 +1115,16 @@ version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36" +[[package]] +name = "libloading" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" +dependencies = [ + "cfg-if 1.0.0", + "winapi", +] + [[package]] name = "libloading" version = "0.7.0" @@ -1114,6 +1174,15 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" +[[package]] +name = "memmap2" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b70ca2a6103ac8b665dc150b142ef0e4e89df640c9e6cf295d189c3caebe5a" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.6.4" @@ -1276,6 +1345,30 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c44922cb3dbb1c70b5e5f443d63b64363a898564d739ba5198e3a9138442868d" +[[package]] +name = "nix" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83450fe6a6142ddd95fb064b746083fc4ef1705fe81f64a64e1d4b39f54a1055" +dependencies = [ + "bitflags", + "cc", + "cfg-if 0.1.10", + "libc", +] + +[[package]] +name = "nix" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a" +dependencies = [ + "bitflags", + "cc", + "cfg-if 1.0.0", + "libc", +] + [[package]] name = "noise" version = "0.7.0" @@ -1287,6 +1380,16 @@ dependencies = [ "rand_xorshift", ] +[[package]] +name = "nom" +version = "6.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2" +dependencies = [ + "memchr", + "version_check", +] + [[package]] name = "ntapi" version = "0.3.6" @@ -1394,6 +1497,15 @@ version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" +[[package]] +name = "owned_ttf_parser" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f923fb806c46266c02ab4a5b239735c144bdeda724a50ed058e5226f594cde3" +dependencies = [ + "ttf-parser", +] + [[package]] name = "parking_lot" version = "0.11.1" @@ -1653,12 +1765,37 @@ dependencies = [ "serde", ] +[[package]] +name = "rusttype" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc7c727aded0be18c5b80c1640eae0ac8e396abf6fa8477d96cb37d18ee5ec59" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + [[package]] name = "ryu" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scoped-tls" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" + [[package]] name = "scoped_threadpool" version = "0.1.9" @@ -1748,6 +1885,25 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" +[[package]] +name = "smithay-client-toolkit" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4750c76fd5d3ac95fa3ed80fe667d6a3d8590a960e5b575b98eea93339a80b80" +dependencies = [ + "andrew", + "bitflags", + "calloop", + "dlib 0.4.2", + "lazy_static", + "log", + "memmap2", + "nix 0.18.0", + "wayland-client", + "wayland-cursor", + "wayland-protocols", +] + [[package]] name = "spirv_cross" version = "0.23.1" @@ -1850,6 +2006,12 @@ dependencies = [ "serde", ] +[[package]] +name = "ttf-parser" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e5d7cd7ab3e47dda6e56542f4bbf3824c15234958c6e1bd6aaa347e93499fdc" + [[package]] name = "unicode-width" version = "0.1.8" @@ -1868,6 +2030,17 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" @@ -1946,6 +2119,79 @@ version = "0.2.74" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f" +[[package]] +name = "wayland-client" +version = "0.28.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ca44d86554b85cf449f1557edc6cc7da935cc748c8e4bf1c507cbd43bae02c" +dependencies = [ + "bitflags", + "downcast-rs", + "libc", + "nix 0.20.0", + "scoped-tls", + "wayland-commons", + "wayland-scanner", + "wayland-sys", +] + +[[package]] +name = "wayland-commons" +version = "0.28.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bd75ae380325dbcff2707f0cd9869827ea1d2d6d534cff076858d3f0460fd5a" +dependencies = [ + "nix 0.20.0", + "once_cell", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-cursor" +version = "0.28.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b37e5455ec72f5de555ec39b5c3704036ac07c2ecd50d0bffe02d5fe2d4e65ab" +dependencies = [ + "nix 0.20.0", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.28.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95df3317872bcf9eec096c864b69aa4769a1d5d6291a5b513f8ba0af0efbd52c" +dependencies = [ + "bitflags", + "wayland-client", + "wayland-commons", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.28.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389d680d7bd67512dc9c37f39560224327038deb0f0e8d33f870900441b68720" +dependencies = [ + "proc-macro2", + "quote", + "xml-rs", +] + +[[package]] +name = "wayland-sys" +version = "0.28.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2907bd297eef464a95ba9349ea771611771aa285b932526c633dc94d5400a8e2" +dependencies = [ + "dlib 0.5.0", + "lazy_static", + "pkg-config", +] + [[package]] name = "web-sys" version = "0.3.50" @@ -2078,8 +2324,8 @@ dependencies = [ "percent-encoding", "raw-window-handle", "scopeguard", - "wasm-bindgen", - "web-sys", + "smithay-client-toolkit", + "wayland-client", "winapi", "x11-dl", ] @@ -2105,6 +2351,27 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "xcursor" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a9a231574ae78801646617cefd13bfe94be907c0e4fa979cfd8b770aa3c5d08" +dependencies = [ + "nom", +] + +[[package]] +name = "xdg" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57" + +[[package]] +name = "xml-rs" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a" + [[package]] name = "zstd" version = "0.5.4+zstd.1.4.7" diff --git a/Cargo.toml b/Cargo.toml index 3d07f11..a8b253d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ log = "0.4.14" noise = "0.7.0" rayon = "1.5.1" wgpu = "0.8.1" -winit = { version = "0.25.0", default_features = false, features = ["x11", "web-sys"] } +winit = { version = "0.25.0" } serde_repr = "0.1.7" rmp-serde = "0.15.4" itertools = "0.10.0" diff --git a/src/main.rs b/src/main.rs index bdf4459..c4bec8d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,7 @@ mod geometry; mod npc; mod quad; mod render_context; +mod renderable; mod state; mod text_renderer; mod texture; @@ -156,25 +157,32 @@ fn main() { frametime_max = Duration::from_secs(0); } + let dt = last_render_time.elapsed(); let now = Instant::now(); - let dt = now - last_render_time; last_render_time = now; - state.update(dt); - match state.render() { - Err(root_cause) => match root_cause.downcast_ref::() { - // Recreate the swap_chain if lost - Some(wgpu::SwapChainError::Lost) => state.resize(state.window_size), - // The system is out of memory, we should probably quit - Some(wgpu::SwapChainError::OutOfMemory) => { - *control_flow = ControlFlow::Exit - } - // All other errors (Outdated, Timeout) should be resolved by the next frame - Some(_) | None => eprintln!("{:?}", root_cause), - }, + let render_time = match state.render() { + Err(root_cause) => { + match root_cause.downcast_ref::() { + // Recreate the swap_chain if lost + Some(wgpu::SwapChainError::Lost) => state.resize(state.window_size), + // The system is out of memory, we should probably quit + Some(wgpu::SwapChainError::OutOfMemory) => { + *control_flow = ControlFlow::Exit + } + // All other errors (Outdated, Timeout) should be resolved by the next frame + Some(_) | None => eprintln!("{:?}", root_cause), + }; + return; + } - Ok(v) => triangle_count = v, - } + Ok((triangle_count_, render_time)) => { + triangle_count = triangle_count_; + render_time + } + }; + + state.update(dt, render_time); } Event::MainEventsCleared => { // RedrawRequested will only trigger once, unless we manually diff --git a/src/renderable.rs b/src/renderable.rs new file mode 100644 index 0000000..4fd2815 --- /dev/null +++ b/src/renderable.rs @@ -0,0 +1,16 @@ +use std::time::Duration; + +use wgpu::RenderPass; + +use crate::{camera::Camera, render_context::RenderContext, view::View}; + +pub trait Renderable { + fn update( + &mut self, + render_context: &RenderContext, + dt: Duration, + render_time: Duration, + camera: &Camera, + ); + fn render<'a>(&'a self, render_pass: &mut RenderPass<'a>, view: &View) -> usize; +} diff --git a/src/state/mod.rs b/src/state/mod.rs index acbc1c9..09f747d 100644 --- a/src/state/mod.rs +++ b/src/state/mod.rs @@ -1,7 +1,7 @@ pub mod hud_state; pub mod world_state; -use std::time::Duration; +use std::time::{Duration, Instant}; use cgmath::EuclideanSpace; use winit::{ @@ -189,30 +189,36 @@ impl State { } } - pub fn update(&mut self, dt: Duration) { - self.world_state.update(dt, &self.render_context); + pub fn update(&mut self, dt: Duration, render_time: Duration) { + self.world_state + .update(dt, render_time, &self.render_context); self.hud_state.update( &self.render_context, &self.world_state.camera.position.to_vec(), ); } - pub fn render(&mut self) -> anyhow::Result { - let frame = self.render_context.swap_chain.get_current_frame()?.output; + pub fn render(&mut self) -> anyhow::Result<(usize, Duration)> { + let render_start = Instant::now(); - let mut render_encoder = self - .render_context - .device - .create_command_encoder(&Default::default()); + Ok({ + let frame = self.render_context.swap_chain.get_current_frame()?.output; - let mut triangle_count = 0; - triangle_count += self.world_state.render(&frame, &mut render_encoder); - triangle_count += self.hud_state.render(&frame, &mut render_encoder)?; + let mut render_encoder = self + .render_context + .device + .create_command_encoder(&Default::default()); - self.render_context - .queue - .submit(std::iter::once(render_encoder.finish())); + let mut triangle_count = 0; + triangle_count += self.world_state.render(&frame, &mut render_encoder); + triangle_count += self.hud_state.render(&frame, &mut render_encoder)?; - Ok(triangle_count) + self.render_context + .queue + .submit(std::iter::once(render_encoder.finish())); + let render_time = render_start.elapsed(); + + (triangle_count, render_time) + }) } } diff --git a/src/state/world_state.rs b/src/state/world_state.rs index 6ef7905..00d7e70 100644 --- a/src/state/world_state.rs +++ b/src/state/world_state.rs @@ -13,6 +13,7 @@ use winit::{ use crate::{ camera::{Camera, Projection}, render_context::RenderContext, + renderable::Renderable, texture::{Texture, TextureManager}, time::Time, vertex::{BlockVertex, Vertex}, @@ -425,10 +426,11 @@ impl WorldState { } } - pub fn update(&mut self, dt: Duration, render_context: &RenderContext) { + pub fn update(&mut self, dt: Duration, render_time: Duration, render_context: &RenderContext) { self.update_position(dt); - self.world.update(dt, render_context, &self.camera); + self.world + .update(render_context, dt, render_time, &self.camera); self.view .update_view_projection(&self.camera, &self.projection); diff --git a/src/world.rs b/src/world.rs index 6874c54..ef2c13e 100644 --- a/src/world.rs +++ b/src/world.rs @@ -1,11 +1,13 @@ +use std::time::Instant; use std::{collections::VecDeque, time::Duration}; use crate::{ camera::Camera, - chunk::{Block, BlockType, Chunk, CHUNK_ISIZE}, + chunk::{self, Block, BlockType, Chunk, CHUNK_ISIZE}, geometry::GeometryBuffers, npc::Npc, render_context::RenderContext, + renderable::Renderable, view::View, }; use ahash::AHashMap; @@ -31,72 +33,14 @@ pub const WORLD_HEIGHT: isize = 16 * 16 / CHUNK_ISIZE; const DEBUG_IO: bool = false; -impl World { - pub fn new() -> Self { - let chunks = AHashMap::new(); - let npc = Npc::load(); - - let chunk_database = sled::Config::new() - .path("chunks") - .mode(sled::Mode::HighThroughput) - .use_compression(true) - .open() - .unwrap(); - - Self { - chunks, - npc, - - chunk_database, - chunk_load_queue: VecDeque::new(), - chunk_save_queue: VecDeque::new(), - chunk_generate_queue: VecDeque::new(), - - highlighted: None, - - unload_timer: Duration::new(0, 0), - } - } - - pub fn update(&mut self, dt: Duration, render_context: &RenderContext, camera: &Camera) { - if let Some(position) = self.chunk_load_queue.pop_front() { - let chunk = self.chunks.entry(position).or_default(); - match chunk.load(position, &self.chunk_database) { - Err(error) => { - eprintln!("Failed to load/generate chunk {:?}: {:?}", position, error) - } - Ok(true) => { - self.update_chunk_geometry(render_context, position); - self.enqueue_chunk_save(position, false); - if DEBUG_IO { - println!("Generated chunk {:?}", position); - } - } - Ok(false) => { - self.update_chunk_geometry(render_context, position); - if DEBUG_IO { - println!("Loaded chunk {:?}", position); - } - } - } - } else if let Some((position, unload)) = self.chunk_save_queue.pop_front() { - if let Some(chunk) = self.chunks.get(&position) { - if let Err(err) = chunk.save(position, &self.chunk_database) { - eprintln!("Failed to save chunk {:?}: {:?}", position, err); - } else if unload { - self.chunks.remove(&position); - - if DEBUG_IO { - println!("Saved and unloaded chunk {:?}", position); - } - } else if DEBUG_IO { - println!("Saved chunk {:?}", position); - } - } else { - eprintln!("Tried to save unloaded chunk {:?}", position); - } - } - +impl Renderable for World { + fn update( + &mut self, + render_context: &RenderContext, + dt: Duration, + render_time: Duration, + camera: &Camera, + ) { self.update_highlight(render_context, camera); // Queue up new chunks for loading, if necessary @@ -142,9 +86,55 @@ impl World { self.enqueue_chunk_save(point, true); } } + + let start = Instant::now() - render_time; + let mut chunk_updates = 0; + while chunk_updates == 0 || start.elapsed() < Duration::from_millis(16) { + if let Some(position) = self.chunk_load_queue.pop_front() { + let chunk = self.chunks.entry(position).or_default(); + match chunk.load(position, &self.chunk_database) { + Err(error) => { + eprintln!("Failed to load/generate chunk {:?}: {:?}", position, error) + } + Ok(true) => { + self.update_chunk_geometry(render_context, position); + self.enqueue_chunk_save(position, false); + if DEBUG_IO { + println!("Generated chunk {:?}", position); + } + } + Ok(false) => { + self.update_chunk_geometry(render_context, position); + if DEBUG_IO { + println!("Loaded chunk {:?}", position); + } + } + } + } else if let Some((position, unload)) = self.chunk_save_queue.pop_front() { + if let Some(chunk) = self.chunks.get(&position) { + if let Err(err) = chunk.save(position, &self.chunk_database) { + eprintln!("Failed to save chunk {:?}: {:?}", position, err); + } else if unload { + self.chunks.remove(&position); + + if DEBUG_IO { + println!("Saved and unloaded chunk {:?}", position); + } + } else if DEBUG_IO { + println!("Saved chunk {:?}", position); + } + } else { + eprintln!("Tried to save unloaded chunk {:?}", position); + } + } else { + break; + } + + chunk_updates += 1; + } } - pub fn render<'a>(&'a self, render_pass: &mut RenderPass<'a>, view: &View) -> usize { + fn render<'a>(&'a self, render_pass: &mut RenderPass<'a>, view: &View) -> usize { let mut triangle_count = 0; for (position, chunk) in &self.chunks { @@ -166,6 +156,34 @@ impl World { triangle_count } +} + +impl World { + pub fn new() -> Self { + let chunks = AHashMap::new(); + let npc = Npc::load(); + + let chunk_database = sled::Config::new() + .path("chunks") + .mode(sled::Mode::HighThroughput) + .use_compression(true) + .open() + .unwrap(); + + Self { + chunks, + npc, + + chunk_database, + chunk_load_queue: VecDeque::new(), + chunk_save_queue: VecDeque::new(), + chunk_generate_queue: VecDeque::new(), + + highlighted: None, + + unload_timer: Duration::new(0, 0), + } + } pub fn enqueue_chunk_save(&mut self, position: Point3, unload: bool) { if let Some((_, unload_)) = self