diff --git a/Cargo.lock b/Cargo.lock index 5b0e22d..8ceea60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -109,6 +109,37 @@ dependencies = [ "libloading 0.7.4", ] +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8828ec6e544c02b0d6691d21ed9f9218d0384a82542855073c2a3f58304aaf0" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + [[package]] name = "atomic-waker" version = "1.1.2" @@ -121,6 +152,140 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +[[package]] +name = "bevy_derive" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0e01f8343f391e2d6a63b368b82fb5b252ed43c8713fc87f9a8f2d59407dd00" +dependencies = [ + "bevy_macro_utils", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "bevy_ecs" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98e612a8e7962ead849e370f3a7e972b88df879ced05cd9dad6a0286d14650cf" +dependencies = [ + "async-channel", + "bevy_ecs_macros", + "bevy_ptr", + "bevy_reflect", + "bevy_tasks", + "bevy_utils", + "downcast-rs", + "fixedbitset", + "rustc-hash", + "serde", + "thiserror", + "thread_local", +] + +[[package]] +name = "bevy_ecs_macros" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "807b5106c3410e58f4f523b55ea3c071e2a09e31e9510f3c22021c6a04732b5b" +dependencies = [ + "bevy_macro_utils", + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "bevy_macro_utils" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb270c98a96243b29465139ed10bda2f675d00a11904f6588a5f7fc4774119c7" +dependencies = [ + "proc-macro2", + "quote", + "rustc-hash", + "syn 2.0.61", + "toml_edit", +] + +[[package]] +name = "bevy_ptr" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8050e2869fe341db6874203b5a01ff12673807a2c7c80cb829f6c7bea6997268" + +[[package]] +name = "bevy_reflect" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccbd7de21d586457a340a0962ad0747dc5098ff925eb6b27a918c4bdd8252f7b" +dependencies = [ + "bevy_ptr", + "bevy_reflect_derive", + "bevy_utils", + "downcast-rs", + "erased-serde", + "serde", + "thiserror", +] + +[[package]] +name = "bevy_reflect_derive" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ce33051bd49036d4a5a62aa3f2068672ec55f3ebe92aa0d003a341f15cc37ac" +dependencies = [ + "bevy_macro_utils", + "proc-macro2", + "quote", + "syn 2.0.61", + "uuid", +] + +[[package]] +name = "bevy_tasks" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f07fcc4969b357de143509925b39c9a2c56eaa8750828d97f319ca9ed41897cb" +dependencies = [ + "async-channel", + "async-executor", + "async-task", + "concurrent-queue", + "futures-lite", + "wasm-bindgen-futures", +] + +[[package]] +name = "bevy_utils" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9f845a985c00e0ee8dc2d8af3f417be925fb52aad4bda5b96e2e58a2b4d2eb" +dependencies = [ + "ahash", + "bevy_utils_proc_macros", + "getrandom", + "hashbrown", + "nonmax", + "petgraph", + "smallvec", + "thiserror", + "tracing", + "uuid", + "web-time 0.2.4", +] + +[[package]] +name = "bevy_utils_proc_macros" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef158627f30503d5c18c20c60b444829f698d343516eeaf6eeee078c9a45163" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + [[package]] name = "bit-set" version = "0.5.3" @@ -427,6 +592,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "erased-serde" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24e2389d65ab4fab27dc2a5de7b191e1f6617d1f1c8855c0dc569c94a4cbb18d" +dependencies = [ + "serde", + "typeid", +] + [[package]] name = "errno" version = "0.3.9" @@ -438,30 +613,38 @@ dependencies = [ ] [[package]] -name = "evenio" -version = "0.6.0" +name = "event-listener" +version = "5.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ead7361e14542019e9f883d2022399ef419ac240085b29ed23715f7746094e78" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" dependencies = [ - "ahash", - "bumpalo", - "evenio_macros", - "hashbrown", - "indexmap", - "slab", + "concurrent-queue", + "parking", + "pin-project-lite", ] [[package]] -name = "evenio_macros" -version = "0.6.0" +name = "event-listener-strategy" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa8c1192efdb4d5734fbdb3cbab6f018807c335eb52b01b3d1b964467cf0097" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.61", + "event-listener", + "pin-project-lite", ] +[[package]] +name = "fastrand" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + [[package]] name = "foreign-types" version = "0.5.0" @@ -489,6 +672,31 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-lite" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + [[package]] name = "gethostname" version = "0.4.3" @@ -506,8 +714,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -602,6 +812,7 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", + "serde", ] [[package]] @@ -914,6 +1125,12 @@ dependencies = [ "jni-sys", ] +[[package]] +name = "nonmax" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "610a5acd306ec67f907abe5567859a3c693fb9886eb1f012ab8f2a47bef3db51" + [[package]] name = "num-complex" version = "0.4.6" @@ -1061,6 +1278,12 @@ dependencies = [ "ttf-parser", ] +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + [[package]] name = "parking_lot" version = "0.12.2" @@ -1096,6 +1319,16 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap", +] + [[package]] name = "pin-project" version = "1.1.5" @@ -1126,8 +1359,9 @@ checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" name = "pixelgame" version = "0.1.0" dependencies = [ + "bevy_derive", + "bevy_ecs", "bytemuck", - "evenio", "nalgebra", "ndarray", "pollster", @@ -1427,6 +1661,9 @@ name = "smallvec" version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +dependencies = [ + "serde", +] [[package]] name = "smithay-client-toolkit" @@ -1534,6 +1771,16 @@ dependencies = [ "syn 2.0.61", ] +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + [[package]] name = "tiny-skia" version = "0.11.4" @@ -1591,6 +1838,9 @@ name = "tracing-core" version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] [[package]] name = "ttf-parser" @@ -1598,6 +1848,12 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" +[[package]] +name = "typeid" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "059d83cc991e7a42fc37bd50941885db0888e34209f8cfd9aab07ddec03bc9cf" + [[package]] name = "typenum" version = "1.17.0" @@ -1628,6 +1884,16 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +[[package]] +name = "uuid" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +dependencies = [ + "getrandom", + "serde", +] + [[package]] name = "version_check" version = "0.9.4" @@ -1835,6 +2101,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa30049b1c872b72c89866d458eae9f20380ab280ffd1b1e18df2d3e2d98cfe0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "web-time" version = "1.1.0" @@ -2260,7 +2536,7 @@ dependencies = [ "wayland-protocols", "wayland-protocols-plasma", "web-sys", - "web-time", + "web-time 1.1.0", "windows-sys 0.52.0", "x11-dl", "x11rb", diff --git a/Cargo.toml b/Cargo.toml index 2233ec9..d2cb9f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,6 @@ rustflags = ["-Z", "threads=14"] [dependencies] bytemuck = {version="1.14.0", features=["derive"]} -evenio = "0.6.0" nalgebra = {version="0.32.5", features=["bytemuck"]} ndarray = "0.15.6" pollster = "0.3" @@ -18,4 +17,6 @@ rand = "0.8.5" simba = "0.8.1" smaa = "0.14.0" wgpu = "0.20" +bevy_ecs = "0.13.2" +bevy_derive = "0.13.2" winit = {version="0.30", features=["serde"]} diff --git a/src/client/app.rs b/src/client/app.rs index ccccf0c..faaa487 100644 --- a/src/client/app.rs +++ b/src/client/app.rs @@ -1,9 +1,4 @@ -use std::sync::Arc; - -use winit::{ - application::ApplicationHandler, event::WindowEvent, event_loop::ControlFlow, - window::WindowAttributes, -}; +use winit::{application::ApplicationHandler, event::WindowEvent, event_loop::ControlFlow}; use super::Client; @@ -24,13 +19,7 @@ impl ClientApp { impl ApplicationHandler for ClientApp { fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) { if self.client.is_none() { - let window = Arc::new( - event_loop - .create_window(WindowAttributes::default()) - .expect("Failed to create window"), - ); - let client = Client::new(window); - self.client = Some(client); + self.client = Some(Client::new(event_loop)); } event_loop.set_control_flow(ControlFlow::Poll); } @@ -54,8 +43,6 @@ impl ApplicationHandler for ClientApp { } fn about_to_wait(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) { - if self.client().update() { - event_loop.exit(); - } + self.client().update(event_loop); } } diff --git a/src/client/component.rs b/src/client/component.rs index 0ba0f60..8d0beac 100644 --- a/src/client/component.rs +++ b/src/client/component.rs @@ -1,18 +1,18 @@ use std::ops::{Deref, DerefMut}; -use evenio::component::Component; +use bevy_ecs::system::Resource; use super::render::RendererChannel; -#[derive(Component)] -pub struct RenderComponent(pub RendererChannel); -impl Deref for RenderComponent { +#[derive(Resource)] +pub struct RenderResource(pub RendererChannel); +impl Deref for RenderResource { type Target = RendererChannel; fn deref(&self) -> &Self::Target { &self.0 } } -impl DerefMut for RenderComponent { +impl DerefMut for RenderResource { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } diff --git a/src/client/handle_input.rs b/src/client/handle_input.rs index ac51452..96bcf75 100644 --- a/src/client/handle_input.rs +++ b/src/client/handle_input.rs @@ -4,9 +4,9 @@ use nalgebra::Rotation3; use ndarray::Array3; use winit::{dpi::PhysicalPosition, keyboard::KeyCode as Key, window::CursorGrabMode}; -use crate::world::component::VoxelGrid; +use crate::world::component::{VoxelGrid, VoxelGridBundle}; -use super::{render::voxel::VoxelColor, system::voxel_grid::SpawnVoxelGrid, Client}; +use super::{render::voxel::VoxelColor, Client}; impl Client { pub fn handle_input(&mut self, dt: &Duration) { @@ -102,19 +102,18 @@ impl Client { } if state.camera != old_camera { self.renderer - .send(super::render::RenderMessage::ViewUpdate(state.camera)) - .expect("AAAAAAA"); + .send(super::render::RenderMessage::ViewUpdate(state.camera)); } // fun if input.just_pressed(Key::KeyF) { - self.world.send(SpawnVoxelGrid { - pos: state.camera.pos + 135.0 * 2.0 * *state.camera.forward(), - orientation: state.camera.orientation, + self.world.spawn(VoxelGridBundle { + pos: (state.camera.pos + 135.0 * 2.0 * *state.camera.forward()).into(), + orientation: state.camera.orientation.into(), grid: VoxelGrid::new(Array3::from_shape_fn((135, 135, 135), |(..)| { VoxelColor::white() })), - }) + }); } } } diff --git a/src/client/mod.rs b/src/client/mod.rs index 96c8cce..6dea929 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -2,7 +2,6 @@ mod app; mod camera; mod component; mod handle_input; -mod init; mod input; pub mod render; mod rsc; @@ -10,15 +9,20 @@ mod state; mod system; pub use app::*; -use component::RenderComponent; -use evenio::world::World; -use init::init_world; +use bevy_ecs::{system::SystemId, world::World}; +use component::RenderResource; use render::{RenderMessage, RendererChannel}; pub use state::*; +use system::voxel_grid::update_renderer; + +use crate::{server::Server, sync::ServerHandle, world::generation::generate}; use self::{input::Input, render::Renderer, ClientState}; use std::{sync::Arc, thread::JoinHandle, time::Instant}; -use winit::{event::WindowEvent, window::Window}; +use winit::{ + event::WindowEvent, + window::{Window, WindowAttributes}, +}; pub struct Client { window: Arc, @@ -31,19 +35,26 @@ pub struct Client { grabbed_cursor: bool, keep_cursor: bool, world: World, + server: ServerHandle, + bruh: SystemId, } impl Client { - pub fn new(window: Arc) -> Self { + pub fn new(event_loop: &winit::event_loop::ActiveEventLoop) -> Self { let mut world = World::new(); + let window = Arc::new( + event_loop + .create_window(WindowAttributes::default()) + .expect("Failed to create window"), + ); let (render_channel, render_handle) = Renderer::spawn(window.clone()); - let e = world.spawn(); - world.insert(e, RenderComponent(render_channel.clone())); - world.add_handler(system::voxel_grid::handle_create_grid); + world.insert_resource(RenderResource(render_channel.clone())); + let bruh = world.register_system(update_renderer); - init_world(&mut world); let state = ClientState::new(); + let server = Server::spawn(); + generate(&mut world); Self { window, @@ -56,10 +67,12 @@ impl Client { grabbed_cursor: false, keep_cursor: false, world, + server, + bruh, } } - pub fn update(&mut self) -> bool { + pub fn update(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) { let now = Instant::now(); let dt = now - self.prev_update; self.prev_update = now; @@ -67,8 +80,12 @@ impl Client { self.handle_input(&dt); self.input.end(); + self.recv(); + self.world.run_system(self.bruh).expect("WHAT"); + self.world.clear_trackers(); + if self.exit { - let _ = self.renderer.send(RenderMessage::Exit); + self.renderer.send(RenderMessage::Exit); // you know I'd like to do a timeout here... // only because I have an NVIDIA GPU HELP self.render_handle @@ -76,21 +93,19 @@ impl Client { .expect("uh oh") .join() .expect("bruh"); + event_loop.exit(); } - self.exit + } + + pub fn recv(&mut self) { + for msg in self.server.recv() {} } pub fn window_event(&mut self, event: WindowEvent) { match event { WindowEvent::CloseRequested => self.exit = true, - WindowEvent::Resized(size) => self - .renderer - .send(RenderMessage::Resize(size)) - .expect("render broke"), - WindowEvent::RedrawRequested => self - .renderer - .send(RenderMessage::Draw) - .expect("render broke"), + WindowEvent::Resized(size) => self.renderer.send(RenderMessage::Resize(size)), + WindowEvent::RedrawRequested => self.renderer.send(RenderMessage::Draw), WindowEvent::CursorLeft { .. } => { self.input.clear(); } diff --git a/src/client/render/mod.rs b/src/client/render/mod.rs index 46e43ea..e415ee4 100644 --- a/src/client/render/mod.rs +++ b/src/client/render/mod.rs @@ -17,6 +17,7 @@ pub struct Renderer<'a> { surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, + encoder: wgpu::CommandEncoder, config: wgpu::SurfaceConfiguration, staging_belt: wgpu::util::StagingBelt, voxel_pipeline: VoxelPipeline, @@ -96,6 +97,7 @@ impl<'a> Renderer<'a> { voxel_pipeline: VoxelPipeline::new(&device, &config.format), staging_belt, surface, + encoder: Self::create_encoder(&device), device, config, queue, @@ -105,15 +107,14 @@ impl<'a> Renderer<'a> { } } - fn create_encoder(&mut self) -> wgpu::CommandEncoder { - self.device - .create_command_encoder(&wgpu::CommandEncoderDescriptor { - label: Some("Render Encoder"), - }) + fn create_encoder(device: &wgpu::Device) -> wgpu::CommandEncoder { + device.create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some("Render Encoder"), + }) } - pub fn draw(&mut self, encoder: &mut wgpu::CommandEncoder) { - let mut encoder = std::mem::replace(encoder, self.create_encoder()); + pub fn draw(&mut self) { + let mut encoder = std::mem::replace(&mut self.encoder, Self::create_encoder(&self.device)); let output = self.surface.get_current_texture().unwrap(); let view = output .texture @@ -146,7 +147,7 @@ impl<'a> Renderer<'a> { self.staging_belt.recall(); } - pub fn resize(&mut self, size: PhysicalSize, encoder: &mut wgpu::CommandEncoder) { + pub fn resize(&mut self, size: PhysicalSize) { self.size = Vector2::new(size.width, size.height); self.config.width = size.width; self.config.height = size.height; @@ -156,7 +157,7 @@ impl<'a> Renderer<'a> { self.voxel_pipeline.update_view( &self.device, - encoder, + &mut self.encoder, &mut self.staging_belt, self.size, &self.camera, diff --git a/src/client/render/thread.rs b/src/client/render/thread.rs index 81fd061..df28958 100644 --- a/src/client/render/thread.rs +++ b/src/client/render/thread.rs @@ -12,7 +12,7 @@ use std::{ }; use winit::{dpi::PhysicalSize, window::Window}; -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum RenderMessage { Resize(PhysicalSize), Draw, @@ -21,9 +21,7 @@ pub enum RenderMessage { Exit, } -pub type RendererChannel = Sender; - -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct CreateVoxelGrid { pub pos: Vector3, pub orientation: Rotation3, @@ -46,7 +44,7 @@ impl Renderer<'_> { .create_surface(window) .expect("Could not create window surface!"); ( - s, + RendererChannel(s), std::thread::spawn(move || { Self::new(instance, surface, size).start(&mut r); }), @@ -54,25 +52,24 @@ impl Renderer<'_> { } pub fn start(&mut self, reciever: &mut Receiver) { - let mut encoder = self.create_encoder(); let mut new_camera = false; 'main: loop { let now = Instant::now(); - while let Ok(msg) = reciever.try_recv() { + for msg in reciever.try_iter() { match msg { RenderMessage::CreateVoxelGrid(desc) => { self.voxel_pipeline.add_group( &self.device, - &mut encoder, + &mut self.encoder, &mut self.staging_belt, desc, ); } RenderMessage::Draw => { - self.draw(&mut encoder); + self.draw(); } RenderMessage::Resize(size) => { - self.resize(size, &mut encoder); + self.resize(size); } RenderMessage::Exit => { break 'main; @@ -88,15 +85,24 @@ impl Renderer<'_> { if new_camera { self.voxel_pipeline.update_view( &self.device, - &mut encoder, + &mut self.encoder, &mut self.staging_belt, self.size, &self.camera, ); new_camera = false; } - self.draw(&mut encoder); + self.draw(); } } } } + +#[derive(Clone)] +pub struct RendererChannel(Sender); +impl RendererChannel { + pub fn send(&self, msg: RenderMessage) { + // TODO: handle this properly + self.0.send(msg).expect("Failed to send renderer message"); + } +} diff --git a/src/client/system/voxel_grid.rs b/src/client/system/voxel_grid.rs index 1effec8..54ac218 100644 --- a/src/client/system/voxel_grid.rs +++ b/src/client/system/voxel_grid.rs @@ -1,49 +1,36 @@ -use evenio::{ - event::{EventMut, GlobalEvent, Insert, ReceiverMut, Sender, Spawn}, - fetch::Single, +use bevy_ecs::{ + query::{Changed, Or}, + system::{Query, Res}, }; -use nalgebra::{Rotation3, Vector3}; +use nalgebra::Vector3; use ndarray::Axis; use crate::{ client::{ - component::RenderComponent, + component::RenderResource, render::{CreateVoxelGrid, RenderMessage}, }, world::component::{Orientation, Pos, VoxelGrid}, }; -#[derive(GlobalEvent)] -pub struct SpawnVoxelGrid { - pub pos: Vector3, - pub orientation: Rotation3, - pub grid: VoxelGrid, -} - -pub fn handle_create_grid( - r: ReceiverMut, - renderer: Single<&RenderComponent>, - mut s: Sender<(Spawn, Insert, Insert, Insert)>, +pub fn update_renderer( + query: Query< + (&Pos, &Orientation, &VoxelGrid), + Or<(Changed, Changed, Changed)>, + >, + renderer: Res, ) { - let SpawnVoxelGrid { - pos, - orientation, - grid, - } = EventMut::take(r.event); - renderer - .send(RenderMessage::CreateVoxelGrid(CreateVoxelGrid { - pos, - orientation, + for (pos, orientation, grid) in query.iter() { + println!("YAY"); + renderer.send(RenderMessage::CreateVoxelGrid(CreateVoxelGrid { + pos: **pos, + orientation: **orientation, dimensions: Vector3::new( grid.len_of(Axis(0)), grid.len_of(Axis(1)), grid.len_of(Axis(2)), ), grid: grid.iter().cloned().collect(), - })) - .expect("render broke"); - let e = s.spawn(); - s.insert(e, Pos(pos)); - s.insert(e, Orientation(orientation)); - s.insert(e, grid); + })); + } } diff --git a/src/main.rs b/src/main.rs index 3f7c5ba..e58210d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,13 @@ +#![allow(clippy::type_complexity)] + use client::ClientApp; use winit::event_loop::EventLoop; mod client; mod util; mod world; +mod server; +mod sync; fn main() { let event_loop = EventLoop::new().expect("Failed to create event loop"); diff --git a/src/server/mod.rs b/src/server/mod.rs new file mode 100644 index 0000000..3180939 --- /dev/null +++ b/src/server/mod.rs @@ -0,0 +1,52 @@ +mod rsc; + +use crate::{ + sync::{client_server_channel, ClientHandle, ServerHandle}, + world::generation::generate, +}; +use bevy_ecs::world::World; +use rsc::UPDATE_TIME; +use std::time::{Duration, Instant}; + +pub struct Server { + update_time: Duration, + target: Instant, + client: ClientHandle, + world: World, +} + +impl Server { + pub fn new(ch: ClientHandle) -> Self { + Self { + client: ch, + world: World::new(), + target: Instant::now(), + update_time: UPDATE_TIME, + } + } + + pub fn spawn() -> ServerHandle { + let (ch, sh) = client_server_channel(); + std::thread::spawn(|| { + Self::new(ch).run(); + }); + sh + } + + pub fn run(&mut self) { + generate(&mut self.world); + loop { + self.recv(); + let now = Instant::now(); + if now >= self.target { + self.target += self.update_time; + } + } + } + + pub fn recv(&mut self) { + for msg in self.client.recv() { + + } + } +} diff --git a/src/server/rsc.rs b/src/server/rsc.rs new file mode 100644 index 0000000..222e7cb --- /dev/null +++ b/src/server/rsc.rs @@ -0,0 +1,4 @@ +use std::time::Duration; + +pub const UPS: u32 = 60; +pub const UPDATE_TIME: Duration = Duration::from_millis(1000 / UPS as u64); diff --git a/src/sync/mod.rs b/src/sync/mod.rs new file mode 100644 index 0000000..ff06898 --- /dev/null +++ b/src/sync/mod.rs @@ -0,0 +1,48 @@ +use std::sync::mpsc::{channel, Receiver, Sender, TryIter}; + +use bevy_ecs::{ + component::{Component, TableStorage}, + entity::Entity, +}; + +pub enum ServerMessage {} + +pub enum ClientMessage { + LoadWorld(Vec<(Entity, Vec>>)>), +} + +pub struct ServerHandle { + send: Sender, + recv: Receiver, +} + +impl ServerHandle { + pub fn send(&self, msg: ServerMessage) { + self.send.send(msg).expect("BOOOOOO"); + } + pub fn recv(&self) -> TryIter { + self.recv.try_iter() + } +} + +pub struct ClientHandle { + send: Sender, + recv: Receiver, +} + +impl ClientHandle { + pub fn send(&self, msg: ClientMessage) { + self.send.send(msg).expect("YOU HAVE FAILED THE MISSION"); + } + pub fn recv(&self) -> TryIter { + self.recv.try_iter() + } +} + +pub fn client_server_channel() -> (ClientHandle, ServerHandle) { + let (cs, sr) = channel(); + let (ss, cr) = channel(); + let sh = ServerHandle { send: ss, recv: sr }; + let ch = ClientHandle { send: cs, recv: cr }; + (ch, sh) +} diff --git a/src/world/component.rs b/src/world/component.rs index d4c530e..cf110ee 100644 --- a/src/world/component.rs +++ b/src/world/component.rs @@ -1,14 +1,15 @@ -use std::ops::{Deref, DerefMut, Range}; +use std::ops::Range; -use evenio::component::Component; +use bevy_derive::{Deref, DerefMut}; +use bevy_ecs::{bundle::Bundle, component::Component}; use nalgebra::{Rotation3, Vector3}; use ndarray::{Array3, ArrayBase, Dim, SliceArg}; use crate::client::render::voxel::VoxelColor; -#[derive(Debug, Component, Default)] +#[derive(Debug, Component, Default, Deref, DerefMut)] pub struct Pos(pub Vector3); -#[derive(Debug, Component, Default)] +#[derive(Debug, Component, Default, Deref, DerefMut)] pub struct Orientation(pub Rotation3); pub type VoxelGrid = TrackedGrid; @@ -61,31 +62,14 @@ impl From> for Orientation { } } -// reref boilerplate :pensive: +#[derive(Bundle)] +pub struct VoxelGridBundle { + pub pos: Pos, + pub orientation: Orientation, + pub grid: VoxelGrid, +} -impl Deref for Pos { - type Target = Vector3; - fn deref(&self) -> &Self::Target { - &self.0 - } -} -impl DerefMut for Pos { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} -impl Deref for Orientation { - type Target = Rotation3; - fn deref(&self) -> &Self::Target { - &self.0 - } -} -impl DerefMut for Orientation { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} -impl Deref for TrackedGrid { +impl std::ops::Deref for TrackedGrid { type Target = Array3; fn deref(&self) -> &Self::Target { &self.data diff --git a/src/world/ecs/component.rs b/src/world/ecs/component.rs new file mode 100644 index 0000000..7e5fe6e --- /dev/null +++ b/src/world/ecs/component.rs @@ -0,0 +1,64 @@ +use std::{ops::Deref, sync::mpsc::{channel, Receiver, Sender}}; + +pub type EntityID = usize; + +pub struct Component { + id: EntityID, + val: T, +} + +impl Deref for Component { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.val + } +} + +pub struct ComponentVec { + vec: Vec>, + changes: Vec, +} + +impl<'a, T> IntoIterator for &'a ComponentVec { + type Item = &'a Component; + type IntoIter = std::slice::Iter<'a, Component>; + fn into_iter(self) -> Self::IntoIter { + (&self.vec).into_iter() + } +} + +pub struct ComponentMut<'a, T> { + cmp: &'a Component, + send: Sender, +} + +pub struct ComponentMutIter<'a, T> { + iter: std::slice::IterMut<'a, Component>, + recv: Receiver, + send: Sender, + i: usize, +} + +impl<'a, T> Iterator for ComponentMutIter<'a, T> { + type Item = ComponentMut<'a, T>; + fn next(&mut self) -> Option { + self.iter.next().map(|c| ComponentMut { + cmp: c, + send: self.send.clone(), + }) + } +} + +impl<'a, T> IntoIterator for &'a mut ComponentVec { + type Item = ComponentMut<'a, T>; + type IntoIter = ComponentMutIter<'a, T>; + fn into_iter(self) -> Self::IntoIter { + let (send, recv) = channel(); + ComponentMutIter { + iter: (&mut self.vec).into_iter(), + recv, + send, + i: 0, + } + } +} diff --git a/src/world/ecs/mod.rs b/src/world/ecs/mod.rs new file mode 100644 index 0000000..9db673f --- /dev/null +++ b/src/world/ecs/mod.rs @@ -0,0 +1,5 @@ +mod component; +mod world; +pub use component::*; +pub use world::*; + diff --git a/src/world/ecs/world.rs b/src/world/ecs/world.rs new file mode 100644 index 0000000..8f22384 --- /dev/null +++ b/src/world/ecs/world.rs @@ -0,0 +1,8 @@ +pub struct World { +} + +impl World { + pub fn new() -> Self { + Self {} + } +} diff --git a/src/world/event.rs b/src/world/event.rs new file mode 100644 index 0000000..6c8534c --- /dev/null +++ b/src/world/event.rs @@ -0,0 +1,11 @@ +use nalgebra::{Rotation3, Vector3}; + +use super::component::VoxelGrid; + +#[derive(GlobalEvent)] +pub struct SpawnVoxelGrid { + pub pos: Vector3, + pub orientation: Rotation3, + pub grid: VoxelGrid, +} + diff --git a/src/client/init.rs b/src/world/generation/mod.rs similarity index 77% rename from src/client/init.rs rename to src/world/generation/mod.rs index c1e4555..3b4e8b1 100644 --- a/src/client/init.rs +++ b/src/world/generation/mod.rs @@ -1,17 +1,17 @@ use crate::world::component::VoxelGrid; -use evenio::world::World; +use bevy_ecs::world::World; use nalgebra::{Rotation3, UnitVector3, Vector3}; use ndarray::Array3; use crate::client::render::voxel::VoxelColor; -use super::system::voxel_grid::SpawnVoxelGrid; +use super::component::VoxelGridBundle; -pub fn init_world(world: &mut World) { +pub fn generate(world: &mut World) { let dim = (15, 10, 10); - world.send(SpawnVoxelGrid { - pos: Vector3::new(0.0, 0.0, 20.0), - orientation: Rotation3::from_axis_angle(&Vector3::y_axis(), 0.5), + world.spawn(VoxelGridBundle { + pos: Vector3::new(0.0, 0.0, 20.0).into(), + orientation: Rotation3::from_axis_angle(&Vector3::y_axis(), 0.5).into(), grid: VoxelGrid::new(Array3::from_shape_fn(dim, |(x, y, z)| { if x == z && x == y { VoxelColor::white() @@ -36,9 +36,9 @@ pub fn init_world(world: &mut World) { }); let dim = (1000, 2, 1000); - world.send(SpawnVoxelGrid { - pos: Vector3::new(0.0, -2.1, 0.0), - orientation: Rotation3::identity(), + world.spawn(VoxelGridBundle { + pos: Vector3::new(0.0, -2.1, 0.0).into(), + orientation: Rotation3::identity().into(), grid: VoxelGrid::new(Array3::from_shape_fn(dim, |(x, y, z)| { if y == 0 { VoxelColor::random() @@ -56,13 +56,14 @@ pub fn init_world(world: &mut World) { }); let dim = (3, 3, 3); - world.send(SpawnVoxelGrid { - pos: Vector3::new(0.0, 0.0, 16.5), - orientation: Rotation3::from_axis_angle(&Vector3::y_axis(), std::f32::consts::PI / 4.0) + world.spawn(VoxelGridBundle { + pos: Vector3::new(0.0, 0.0, 16.5).into(), + orientation: (Rotation3::from_axis_angle(&Vector3::y_axis(), std::f32::consts::PI / 4.0) * Rotation3::from_axis_angle( &UnitVector3::new_normalize(Vector3::new(1.0, 0.0, 1.0)), std::f32::consts::PI / 4.0, - ), + )) + .into(), grid: VoxelGrid::new(Array3::from_shape_fn(dim, |(..)| VoxelColor { r: 255, g: 0, diff --git a/src/world/mod.rs b/src/world/mod.rs index 9cea807..4e42b45 100644 --- a/src/world/mod.rs +++ b/src/world/mod.rs @@ -1 +1,2 @@ pub mod component; +pub mod generation;