From e15b39b2a9cf028b12cbe98f56674e58c5a6bd4c Mon Sep 17 00:00:00 2001 From: metamuffin Date: Sun, 5 Jan 2025 22:27:53 +0100 Subject: a --- client/src/download.rs | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ client/src/main.rs | 11 +++++++--- client/src/network.rs | 55 +++++++++++++++++++++++++++++++++++++++++++++++ client/src/part.rs | 36 ++++++++++++++++++------------- client/src/renderer.rs | 2 ++ client/src/state.rs | 33 ++++++++++++++++++++++++++++ client/src/window.rs | 36 ++++++++++++++++++++++--------- 7 files changed, 203 insertions(+), 28 deletions(-) create mode 100644 client/src/download.rs create mode 100644 client/src/network.rs create mode 100644 client/src/state.rs (limited to 'client') diff --git a/client/src/download.rs b/client/src/download.rs new file mode 100644 index 0000000..256c25c --- /dev/null +++ b/client/src/download.rs @@ -0,0 +1,58 @@ +use anyhow::Result; +use std::collections::HashSet; +use weareshared::{ + packets::{Packet, Resource}, + store::{ResourceStore, sha256}, +}; + +use crate::network::Network; + +pub struct Downloader { + have: HashSet, + need: HashSet, + pending: HashSet, + store: ResourceStore, +} + +impl Downloader { + pub fn new(store: ResourceStore) -> Self { + Self { + have: HashSet::new(), + need: HashSet::new(), + pending: HashSet::new(), + store, + } + } + pub fn try_get(&mut self, hash: Resource) -> Result>> { + if self.have.contains(&hash) { + self.store.get(hash) + } else { + self.need.insert(hash); + Ok(None) + } + } + pub fn packet(&mut self, p: &Packet) -> Result<()> { + match p { + Packet::RespondResource(d) => { + let key = Resource(sha256(&d)); + self.store.set(&d)?; + self.need.remove(&key); + self.pending.remove(&key); + self.have.insert(key); + } + _ => (), + } + Ok(()) + } + pub fn update(&mut self, network: &mut Network) { + let mut new_pending = Vec::new(); + for n in self.need.difference(&self.pending) { + network + .packet_send + .send(Packet::RequestResource(*n)) + .unwrap(); + new_pending.push(*n); + } + self.pending.extend(new_pending); + } +} diff --git a/client/src/main.rs b/client/src/main.rs index 543db6d..b90d26b 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -1,9 +1,13 @@ +pub mod download; +pub mod network; +pub mod part; pub mod renderer; +pub mod state; pub mod window; -pub mod part; use anyhow::Result; use clap::Parser; +use log::info; use std::net::{SocketAddr, TcpStream}; use window::WindowState; use winit::event_loop::EventLoop; @@ -17,10 +21,11 @@ fn main() -> Result<()> { env_logger::init_from_env("LOG"); let args = Args::parse(); + info!("connecting..."); let sock = TcpStream::connect(args.address)?; - + info!("connection established"); let evloop = EventLoop::new()?; - evloop.run_app(&mut WindowState::new())?; + evloop.run_app(&mut WindowState::new(sock))?; Ok(()) } diff --git a/client/src/network.rs b/client/src/network.rs new file mode 100644 index 0000000..0fd5f08 --- /dev/null +++ b/client/src/network.rs @@ -0,0 +1,55 @@ +use std::{ + io::{BufReader, BufWriter}, + net::TcpStream, + sync::mpsc::{Receiver, Sender, channel}, + thread::spawn, +}; + +use anyhow::Result; +use log::{debug, info, warn}; +use weareshared::packets::Packet; + +pub struct Network { + pub packet_recv: Receiver, + pub packet_send: Sender, +} +impl Network { + pub fn new(sock: TcpStream) -> Self { + info!("starting network threads"); + let (packet_send, rx) = channel(); + let (tx, packet_recv) = channel(); + + let sock2 = sock.try_clone().unwrap(); + spawn(move || { + if let Err(e) = handle_conn_read(sock, tx) { + warn!("read thread: {e:?}") + } + }); + spawn(move || { + if let Err(e) = handle_conn_write(sock2, rx) { + warn!("write thread: {e:?}") + } + }); + Self { + packet_recv, + packet_send, + } + } +} + +fn handle_conn_read(sock: TcpStream, tx: Sender) -> Result<()> { + let mut sock = BufReader::new(sock); + loop { + let packet = Packet::deserialize(&mut sock)?; + debug!("<- {packet:?}"); + tx.send(packet)?; + } +} +fn handle_conn_write(sock: TcpStream, rx: Receiver) -> Result<()> { + let mut sock = BufWriter::new(sock); + for packet in rx { + debug!("-> {packet:?}"); + packet.serialize(&mut sock)?; + } + Ok(()) +} diff --git a/client/src/part.rs b/client/src/part.rs index 15835d0..0ad714a 100644 --- a/client/src/part.rs +++ b/client/src/part.rs @@ -1,8 +1,6 @@ +use crate::download::Downloader; use anyhow::Result; -use weareshared::{ - packets::Resource, - resources::{Indecies, Part, VertexAttributes}, -}; +use weareshared::resources::{Indecies, Part, VertexAttributes}; use wgpu::{ BindGroup, BindGroupDescriptor, BindGroupLayoutDescriptor, BlendState, Buffer, BufferUsages, ColorTargetState, ColorWrites, CommandEncoder, Device, FragmentState, FrontFace, IndexFormat, @@ -28,16 +26,25 @@ pub struct PartData { } impl PartData { - pub fn update(&mut self, hash: Resource, data: &[u8]) -> Result { - if Some(hash) == self.target.index { - self.index = Some(Indecies::deserialize(data)?) + pub fn update(&mut self, dls: &mut Downloader) -> Result { + let mut ready = true; + if self.index.is_none() { + ready = false; + if let Some(hash) = self.target.index { + if let Some(data) = dls.try_get(hash)? { + self.index = Some(Indecies::deserialize(data.as_slice())?) + } + } } - for (thash, tdata) in self.target.vertex.iter().zip(self.vertex.iter_mut()) { - if hash == *thash { - *tdata = Some(VertexAttributes::deserialize(data)?) + for (hash, slot) in self.target.vertex.iter().zip(self.vertex.iter_mut()) { + if slot.is_none() { + ready = false; + if let Some(data) = dls.try_get(*hash)? { + *slot = Some(VertexAttributes::deserialize(data.as_slice())?) + } } } - Ok(self.vertex.iter().all(|v| v.is_some()) && self.index.is_some()) + Ok(ready) } } @@ -45,11 +52,10 @@ impl RenderPart { pub fn new(device: Device, data: PartData, format: TextureFormat) -> Self { let mut vertex = Vec::new(); let mut index = Vec::new(); - let attrs = data.vertex.unwrap(); for i in 0..data.vertex[0].as_ref().unwrap().0.len() { - vertex.extend(attrs[0].0[i].to_le_bytes()); - vertex.extend(attrs[1].0[i].to_le_bytes()); - vertex.extend(attrs[2].0[i].to_le_bytes()); + vertex.extend(data.vertex[0].as_ref().unwrap().0[i].to_le_bytes()); + vertex.extend(data.vertex[1].as_ref().unwrap().0[i].to_le_bytes()); + vertex.extend(data.vertex[2].as_ref().unwrap().0[i].to_le_bytes()); } let mut n_vertex = 0; for ind in data.index.unwrap().0 { diff --git a/client/src/renderer.rs b/client/src/renderer.rs index b21c139..cc44446 100644 --- a/client/src/renderer.rs +++ b/client/src/renderer.rs @@ -1,4 +1,5 @@ use anyhow::{Result, anyhow}; +use log::info; use pollster::FutureExt; use wgpu::{ Backends, BindGroup, BindGroupDescriptor, BindGroupLayoutDescriptor, BlendState, Color, @@ -22,6 +23,7 @@ pub struct Renderer<'a> { } impl<'a> Renderer<'a> { pub fn new(window: &'a Window) -> Result { + info!("wgpu init"); let instance = Instance::new(InstanceDescriptor { backends: Backends::all(), ..Default::default() diff --git a/client/src/state.rs b/client/src/state.rs new file mode 100644 index 0000000..ef68b85 --- /dev/null +++ b/client/src/state.rs @@ -0,0 +1,33 @@ +use crate::{download::Downloader, network::Network, renderer::Renderer}; +use anyhow::Result; +use log::info; +use std::net::TcpStream; +use weareshared::{store::ResourceStore, tree::SceneTree}; +use winit::window::Window; + +pub struct State<'a> { + pub network: Network, + pub downloader: Downloader, + pub renderer: Renderer<'a>, + pub tree: SceneTree, +} +impl<'a> State<'a> { + pub fn new(conn: TcpStream, window: &'a Window) -> Result> { + info!("new state"); + Ok(Self { + network: Network::new(conn), + tree: SceneTree::default(), + renderer: Renderer::new(window)?, + downloader: Downloader::new(ResourceStore::new_memory()), + }) + } + + pub fn update(&mut self) -> Result<()> { + for p in self.network.packet_recv.try_iter() { + self.downloader.packet(&p)?; + } + self.downloader.update(&mut self.network); + + Ok(()) + } +} diff --git a/client/src/window.rs b/client/src/window.rs index 20300d5..5f2e7f8 100644 --- a/client/src/window.rs +++ b/client/src/window.rs @@ -1,4 +1,6 @@ -use crate::renderer::Renderer; +use crate::state::State; +use log::{info, warn}; +use std::net::TcpStream; use winit::{ application::ApplicationHandler, event::WindowEvent, @@ -7,21 +9,28 @@ use winit::{ }; pub struct WindowState { - window: Option<(Window, Renderer<'static>)>, + init: Option, + window: Option<(Window, State<'static>)>, } impl WindowState { - pub fn new() -> Self { - Self { window: None } + pub fn new(init: TcpStream) -> Self { + Self { + window: None, + init: Some(init), + } } } impl ApplicationHandler for WindowState { fn resumed(&mut self, event_loop: &ActiveEventLoop) { + info!("app resumed"); let win = event_loop .create_window(WindowAttributes::default().with_maximized(true)) .unwrap(); - let ren = Renderer::new(unsafe { std::mem::transmute::<&Window, &'static Window>(&win) }) - .unwrap(); - self.window = Some((win, ren)) + let sta = State::new(self.init.take().unwrap(), unsafe { + std::mem::transmute::<&Window, &'static Window>(&win) + }) + .unwrap(); + self.window = Some((win, sta)) } fn window_event( &mut self, @@ -29,12 +38,12 @@ impl ApplicationHandler for WindowState { _window_id: WindowId, event: WindowEvent, ) { - if let Some((_win, ren)) = &mut self.window { + if let Some((_win, sta)) = &mut self.window { match event { WindowEvent::Resized(size) => { - ren.resize(size.width, size.height); + sta.renderer.resize(size.width, size.height); } - WindowEvent::RedrawRequested => ren.draw().unwrap(), + WindowEvent::RedrawRequested => sta.renderer.draw().unwrap(), WindowEvent::CloseRequested => { event_loop.exit(); } @@ -42,4 +51,11 @@ impl ApplicationHandler for WindowState { } } } + fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) { + if let Some((_win, sta)) = &mut self.window { + if let Err(e) = sta.update() { + warn!("update failed: {e}") + } + } + } } -- cgit v1.2.3-70-g09d2