summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-01-06 18:54:00 +0100
committermetamuffin <metamuffin@disroot.org>2025-01-06 18:54:00 +0100
commit6af8b165fe8cbab35721a8797ca85cda454a5ff4 (patch)
tree05006c8b378dca5f033a72b0f0b3196fb8691423
parent14d348febd549b944d03030bf748f7817a2bedac (diff)
downloadweareserver-6af8b165fe8cbab35721a8797ca85cda454a5ff4.tar
weareserver-6af8b165fe8cbab35721a8797ca85cda454a5ff4.tar.bz2
weareserver-6af8b165fe8cbab35721a8797ca85cda454a5ff4.tar.zst
new network
-rw-r--r--Cargo.lock1
-rw-r--r--a.md5
-rw-r--r--client/src/download.rs4
-rw-r--r--client/src/scene_prepare.rs64
-rw-r--r--client/src/scene_render.rs10
-rw-r--r--server/src/main.rs106
-rw-r--r--server/src/network.rs191
-rw-r--r--shared/src/lib.rs2
-rw-r--r--shared/src/packets.rs62
-rw-r--r--shared/src/tree.rs10
-rw-r--r--world/Cargo.toml1
-rw-r--r--world/src/main.rs75
12 files changed, 396 insertions, 135 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 9c163bf..5930f7c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2474,6 +2474,7 @@ dependencies = [
"env_logger",
"gltf",
"log",
+ "rand",
"weareshared",
]
diff --git a/a.md b/a.md
index 5c1e261..2e00d8a 100644
--- a/a.md
+++ b/a.md
@@ -5,6 +5,8 @@ Vec is stored as `len:u8 *(data:T)`
```rs
type Obj = [u8; 16]
type Res = [u8; 32]
+len 00 connect(identity: u128)
+len ff disconnect()
len 01 request_resource(name: Res)
len 02 respond_resource(data: Vec<u8>)
len 03 add(id: Obj, prefab: Res)
@@ -27,7 +29,8 @@ Prefab = *(pos:f32x3 mat:f32_3x3 part:Res<Part>)
```
Part = *(len_key:u16 len_value:u16 *(key:u8) *(value:u8))
-Attribute = 0x01 value:f32 / 0x02 buffer:Res / 0x03 texture:Res<Texture>
+Attribute = 0x01 constant:f32 / 0x02 buffer:Res / 0x03 texture:Res<Texture>
+NewAttribute = flag:u8 constant:f32 buffer:Res texture:Res<Texture>
```
| Key | Value Type |
diff --git a/client/src/download.rs b/client/src/download.rs
index dfd7ff0..8e1686a 100644
--- a/client/src/download.rs
+++ b/client/src/download.rs
@@ -34,8 +34,8 @@ impl Downloader {
pub fn packet(&mut self, p: &Packet) -> Result<()> {
match p {
Packet::RespondResource(d) => {
- let key = Resource(sha256(&d));
- self.store.set(&d)?;
+ let key = Resource(sha256(&d.0));
+ self.store.set(&d.0)?;
self.need.remove(&key);
self.pending.remove(&key);
if self.have.insert(key) {
diff --git a/client/src/scene_prepare.rs b/client/src/scene_prepare.rs
index 30c1742..5376145 100644
--- a/client/src/scene_prepare.rs
+++ b/client/src/scene_prepare.rs
@@ -1,28 +1,28 @@
+use crate::download::Downloader;
use anyhow::Result;
use std::{
collections::{HashMap, HashSet},
sync::Arc,
};
use weareshared::{
+ Affine3A,
packets::{ReadWrite, Resource},
- resources::Prefab,
- tree::SceneTree,
+ resources::{Attribute, Part, Prefab},
};
use wgpu::Buffer;
-use crate::download::Downloader;
-
pub struct ScenePreparer {
index_buffers: HashMap<Resource, Arc<Buffer>>,
- vertex_buffers_x3: HashMap<[Resource; 1], Arc<Buffer>>,
- vertex_buffers_x2: HashMap<[Resource; 2], Arc<Buffer>>,
- vertex_buffers_x1: HashMap<[Resource; 3], Arc<Buffer>>,
+ index_buffers_needed: HashSet<Resource>,
+ vertex_buffers: HashMap<Resource, Arc<Buffer>>,
+ vertex_buffers_needed: HashSet<Resource>,
parts: HashMap<Resource, Arc<RPart>>,
+ parts_needed: HashSet<Resource>,
prefabs: HashMap<Resource, RPrefab>,
prefabs_needed: HashSet<Resource>,
}
-pub struct RPrefab(pub Vec<Arc<RPart>>);
+pub struct RPrefab(pub Vec<(Affine3A, Arc<RPart>)>);
pub struct RPart {
pub index_count: u32,
pub index: Arc<Buffer>,
@@ -34,19 +34,57 @@ impl ScenePreparer {
pub fn new() -> Self {
Self {
index_buffers: HashMap::new(),
- vertex_buffers_x3: HashMap::new(),
- vertex_buffers_x2: HashMap::new(),
- vertex_buffers_x1: HashMap::new(),
+ vertex_buffers: HashMap::new(),
+ vertex_buffers_needed: HashSet::new(),
parts: HashMap::new(),
+ parts_needed: HashSet::new(),
prefabs: HashMap::new(),
prefabs_needed: HashSet::new(),
+ index_buffers_needed: HashSet::new(),
}
}
- fn update(&mut self, dls: &mut Downloader) -> Result<()> {
+ pub fn update(&mut self, dls: &mut Downloader) -> Result<()> {
+ let mut done = Vec::new();
for pres in &self.prefabs_needed {
if let Some(buf) = dls.try_get(*pres)? {
let prefab = Prefab::read(&mut buf.as_slice())?;
-
+ let mut rprefab = RPrefab(Vec::new());
+ for (aff, partres) in &prefab.0 {
+ if let Some(part) = self.parts.get(partres) {
+ rprefab.0.push((*aff, part.clone()));
+ } else {
+ self.parts_needed.insert(*partres);
+ }
+ }
+ if rprefab.0.len() == prefab.0.len() {
+ self.prefabs.insert(*pres, rprefab);
+ done.push(*pres);
+ }
+ }
+ }
+ for pres in &self.parts_needed {
+ if let Some(buf) = dls.try_get(*pres)? {
+ let part = Part::read(&mut buf.as_slice())?;
+ if let Some(indexres) = part.index {
+ if let Some(vertexres) = part.va_position {
+ let Some(index) = self.index_buffers.get(&indexres) else {
+ self.index_buffers_needed.insert(indexres);
+ continue;
+ };
+ for vr in vertexres {
+ match vr {
+ Attribute::Constant(_) => todo!(),
+ Attribute::Vertex(resource) => {
+ let Some(vertex) = self.index_buffers.get(&resource) else {
+ self.index_buffers_needed.insert(indexres);
+ continue;
+ };
+ }
+ Attribute::Texture(resource) => todo!(),
+ }
+ }
+ }
+ }
}
}
Ok(())
diff --git a/client/src/scene_render.rs b/client/src/scene_render.rs
index f80f6c2..68d0c49 100644
--- a/client/src/scene_render.rs
+++ b/client/src/scene_render.rs
@@ -5,9 +5,9 @@ use wgpu::{
ColorWrites, CommandEncoder, Device, FragmentState, FrontFace, IndexFormat, LoadOp,
MultisampleState, Operations, PipelineCompilationOptions, PipelineLayoutDescriptor,
PolygonMode, PrimitiveState, PrimitiveTopology, RenderPassColorAttachment,
- RenderPassDescriptor, RenderPipeline, RenderPipelineDescriptor, StoreOp, TextureFormat,
- TextureView, VertexAttribute, VertexBufferLayout, VertexFormat, VertexState, VertexStepMode,
- include_wgsl,
+ RenderPassDescriptor, RenderPipeline, RenderPipelineDescriptor, ShaderStages, StoreOp,
+ TextureFormat, TextureView, VertexAttribute, VertexBufferLayout, VertexFormat, VertexState,
+ VertexStepMode, include_wgsl,
};
use crate::scene_prepare::RPrefab;
@@ -113,7 +113,9 @@ impl ScenePipeline {
for ob in scene.objects.values() {
if let Some(prefab) = self.prefabs.get(&ob.res) {
- for part in &prefab.0 {
+ for (affine, part) in &prefab.0 {
+ let affine = affine.to_cols_array().map(|v| v.to_le_bytes());
+ rpass.set_push_constants(ShaderStages::VERTEX, 0, affine.as_flattened());
rpass.set_index_buffer(part.index.slice(..), IndexFormat::Uint16);
rpass.set_vertex_buffer(0, part.positions.slice(..));
rpass.set_vertex_buffer(1, part.normals.slice(..));
diff --git a/server/src/main.rs b/server/src/main.rs
index 6b2911f..a8473c6 100644
--- a/server/src/main.rs
+++ b/server/src/main.rs
@@ -1,18 +1,12 @@
+pub mod network;
+
use anyhow::Result;
use clap::Parser;
-use log::{debug, info};
-use std::{
- collections::HashMap,
- io::{BufReader, BufWriter, Write},
- net::{IpAddr, TcpListener, TcpStream},
- sync::{
- Arc, Mutex,
- mpsc::{Receiver, Sender, channel},
- },
- thread::spawn,
-};
+use log::warn;
+use network::ServerNetwork;
+use std::net::{IpAddr, SocketAddr};
use weareshared::{
- packets::{Packet, ReadWrite},
+ packets::{Data, Packet},
store::ResourceStore,
tree::SceneTree,
};
@@ -26,7 +20,6 @@ struct Args {
}
struct State {
- tx: HashMap<usize, Sender<Packet>>,
store: ResourceStore,
tree: SceneTree,
}
@@ -35,101 +28,64 @@ fn main() -> Result<()> {
env_logger::init_from_env("LOG");
let args = Args::parse();
- let listener = TcpListener::bind((args.bind_addr, args.port))?;
- info!("bound to {}", listener.local_addr()?);
- let state = Arc::new(Mutex::new(State::new()?));
- for conn in 0.. {
- let (sock, addr) = listener.accept()?;
- info!("{addr} connected");
- let (tx, rx) = channel();
- let state2 = state.clone();
- let sock2 = sock.try_clone().unwrap();
- spawn(move || {
- for p in state2.lock().unwrap().tree.prime_client() {
- tx.send(p).unwrap();
- }
- state2.lock().unwrap().tx.insert(conn, tx);
- let _ = handle_conn_read(conn, sock, state2.clone());
- info!("{addr} disconnected");
- state2.lock().unwrap().tx.remove(&conn);
- });
- spawn(move || {
- let _ = handle_conn_write(conn, sock2, rx);
- });
- }
- Ok(())
-}
+ let net = ServerNetwork::new(SocketAddr::new(args.bind_addr, args.port))?;
+ let mut state = State::new()?;
-fn handle_conn_read(conn: usize, sock: TcpStream, state: Arc<Mutex<State>>) -> Result<()> {
- let mut sock = BufReader::new(sock);
- loop {
- let packet = Packet::read(&mut sock)?;
- debug!("{conn} <- {packet:?}");
- state.lock().unwrap().handle_packet(conn, packet)?;
- }
-}
-fn handle_conn_write(conn: usize, sock: TcpStream, rx: Receiver<Packet>) -> Result<()> {
- let mut sock = BufWriter::new(sock);
- for packet in rx {
- debug!("{conn} -> {packet:?}");
- packet.write(&mut sock)?;
- sock.flush()?;
+ while let Ok((conn, packet)) = net.recv.recv() {
+ if let Err(e) = state.handle_packet(conn, packet, &net) {
+ warn!("state handler error: ({conn}) {e}");
+ }
}
+
Ok(())
}
+
impl State {
pub fn new() -> Result<Self> {
Ok(Self {
- tx: HashMap::new(),
store: ResourceStore::new_persistent(
&xdg::BaseDirectories::with_prefix("weareserver")?.place_cache_file("resources")?,
)?,
tree: SceneTree::default(),
})
}
- pub fn broadcast(&self, packet: Packet) -> Result<()> {
- for tx in self.tx.values() {
- tx.send(packet.clone())?;
- }
- Ok(())
- }
- pub fn send(&self, conn: usize, packet: Packet) -> Result<()> {
- if let Some(tx) = self.tx.get(&conn) {
- tx.send(packet)?;
- }
- Ok(())
- }
- pub fn handle_packet(&mut self, conn: usize, packet: Packet) -> Result<()> {
+ pub fn handle_packet(&mut self, conn: u128, packet: Packet, net: &ServerNetwork) -> Result<()> {
self.tree.update(&packet);
match packet {
+ Packet::Connect(_) => {
+ for p in self.tree.prime_client() {
+ net.send(conn, p, true);
+ }
+ }
+ Packet::Disconnect => {}
Packet::RequestResource(resource) => {
if let Some(r) = self.store.get(resource)? {
- self.send(conn, Packet::RespondResource(r))?;
+ net.send(conn, Packet::RespondResource(Data(r)), true);
} else {
- self.broadcast(Packet::RequestResource(resource))?;
+ net.broadcast(Packet::RequestResource(resource), true);
}
}
Packet::RespondResource(data) => {
- self.store.set(&data)?;
- self.broadcast(Packet::RespondResource(data))?;
+ self.store.set(&data.0)?;
+ net.broadcast(Packet::RespondResource(data), true);
}
Packet::Add(object, resource) => {
- self.broadcast(Packet::Add(object, resource))?;
+ net.broadcast(Packet::Add(object, resource), true);
}
Packet::Remove(object) => {
- self.broadcast(Packet::Remove(object))?;
+ net.broadcast(Packet::Remove(object), true);
}
Packet::Position(object, pos, rot) => {
- self.broadcast(Packet::Position(object, pos, rot))?;
+ net.broadcast(Packet::Position(object, pos, rot), true);
}
Packet::Pose(object, vec) => {
- self.broadcast(Packet::Pose(object, vec))?;
+ net.broadcast(Packet::Pose(object, vec), true);
}
Packet::Parent(parent, child) => {
- self.broadcast(Packet::Parent(parent, child))?;
+ net.broadcast(Packet::Parent(parent, child), true);
}
Packet::Sound(object, vec) => {
- self.broadcast(Packet::Sound(object, vec))?;
+ net.broadcast(Packet::Sound(object, vec), true);
}
}
Ok(())
diff --git a/server/src/network.rs b/server/src/network.rs
new file mode 100644
index 0000000..22cbc65
--- /dev/null
+++ b/server/src/network.rs
@@ -0,0 +1,191 @@
+use anyhow::Result;
+use log::{debug, error, info, warn};
+use std::{
+ collections::HashMap,
+ io::{BufReader, BufWriter, Write},
+ net::{SocketAddr, TcpListener, TcpStream, UdpSocket},
+ sync::{
+ Arc, Mutex,
+ mpsc::{Receiver, Sender, SyncSender, channel, sync_channel},
+ },
+ thread::spawn,
+ time::Instant,
+};
+use weareshared::packets::{Packet, ReadWrite};
+
+pub struct ServerNetwork {
+ conns: Arc<Mutex<HashMap<u128, (SyncSender<Arc<Vec<u8>>>, Option<SocketAddr>)>>>,
+ udp_sock: Arc<UdpSocket>,
+ pub recv: Receiver<(u128, Packet)>,
+}
+impl ServerNetwork {
+ pub fn new(addr: SocketAddr) -> Result<Self> {
+ let (recv_tx, recv_rx) = channel();
+ let conns = Arc::new(Mutex::new(HashMap::new()));
+
+ let tcp_listener = TcpListener::bind(addr)?;
+ info!("tcp bound to {}", tcp_listener.local_addr()?);
+ let udp_sock = Arc::new(UdpSocket::bind(addr)?);
+ info!("udp bound to {}", udp_sock.local_addr()?);
+
+ let s = Self {
+ conns: conns.clone(),
+ recv: recv_rx,
+ udp_sock: udp_sock.clone(),
+ };
+ let recv_tx2 = recv_tx.clone();
+ let conns2 = conns.clone();
+ spawn(move || {
+ info!("tcp listener thread started");
+ loop {
+ let (mut sock, addr) = match tcp_listener.accept() {
+ Ok(x) => x,
+ Err(e) => {
+ warn!("cannot accept tcp: {e}");
+ continue;
+ }
+ };
+ info!("TCP connected {addr}");
+
+ let conns = conns.clone();
+ let recv_tx = recv_tx.clone();
+ spawn(move || {
+ let conn = match Packet::read(&mut sock) {
+ Ok(Packet::Connect(x)) => x,
+ Ok(_) => {
+ warn!("client send non-connect packet first");
+ return;
+ }
+ Err(e) => {
+ warn!("client handshake failed: {e}");
+ return;
+ }
+ };
+ let (send_tx, send_rx) = sync_channel(128);
+ conns.lock().unwrap().insert(conn, (send_tx, None));
+
+ let sock2 = match sock.try_clone() {
+ Ok(x) => x,
+ Err(e) => {
+ error!("cannot duplicate client socket: {e}");
+ return;
+ }
+ };
+ spawn(move || {
+ if let Err(e) = handle_conn_write(conn, sock2, send_rx) {
+ warn!("client outbound error: {e}");
+ }
+ });
+ if let Err(e) = handle_conn_read(conn, sock, recv_tx) {
+ warn!("client inbound error: {e}");
+ }
+ conns.lock().unwrap().remove(&conn);
+ });
+ }
+ });
+ spawn(move || {
+ info!("udp listener thread started");
+ let mut buf = [0u8; 8096];
+ struct CState {
+ last_ack: Instant,
+ conn_id: u128,
+ }
+ let mut cstates = HashMap::new();
+ let mut last_check = Instant::now();
+ loop {
+ let (size, addr) = match udp_sock.recv_from(&mut buf) {
+ Err(e) => {
+ warn!("udp recv failed: {e}");
+ continue;
+ }
+ Ok(s) => s,
+ };
+
+ let mut packet = &buf[..size];
+ let packet = match Packet::read(&mut packet) {
+ Ok(p) => p,
+ Err(e) => {
+ warn!("invalid packet from {e}");
+ continue;
+ }
+ };
+ if let Packet::Connect(id) = &packet {
+ if let Some((_send, udp_addr)) = conns2.lock().unwrap().get_mut(id) {
+ *udp_addr = Some(addr);
+ cstates.insert(addr, CState {
+ conn_id: *id,
+ last_ack: Instant::now(),
+ });
+ }
+ }
+ if let Some(conn) = cstates.get(&addr) {
+ let cid = conn.conn_id;
+ if let Packet::Disconnect = &packet {
+ cstates.remove(&addr);
+ }
+ recv_tx2.send((cid, packet)).unwrap();
+ }
+
+ if last_check.elapsed().as_secs() > 10 {
+ cstates.retain(|addr, state| {
+ if state.last_ack.elapsed().as_secs() > 30 {
+ warn!("client dropped: {addr}");
+ recv_tx2.send((state.conn_id, Packet::Disconnect)).unwrap();
+ false
+ } else {
+ true
+ }
+ });
+ last_check = Instant::now();
+ }
+ }
+ });
+ Ok(s)
+ }
+ pub fn broadcast(&self, packet: Packet, reliable: bool) {
+ let ser = Arc::new(packet.write_alloc());
+ for (cid, (tcp, udp)) in self.conns.lock().unwrap().iter() {
+ if !reliable {
+ if let Some(addr) = udp {
+ self.udp_sock.send_to(&ser, addr).unwrap();
+ continue;
+ }
+ }
+ if let Err(_) = tcp.send(ser.clone()) {
+ warn!("{cid}: queue full, packet dropped")
+ }
+ }
+ }
+ pub fn send(&self, conn: u128, packet: Packet, reliable: bool) {
+ let ser = Arc::new(packet.write_alloc());
+ if let Some((tcp, udp)) = self.conns.lock().unwrap().get(&conn) {
+ if !reliable {
+ if let Some(addr) = udp {
+ self.udp_sock.send_to(&ser, addr).unwrap();
+ return;
+ }
+ }
+ if let Err(_) = tcp.send(ser.clone()) {
+ warn!("{conn}: queue full, packet dropped")
+ }
+ }
+ }
+}
+
+fn handle_conn_read(conn: u128, sock: TcpStream, tx: Sender<(u128, Packet)>) -> Result<()> {
+ let mut sock = BufReader::new(sock);
+ loop {
+ let packet = Packet::read(&mut sock)?;
+ debug!("{conn} <- {packet:?}");
+ tx.send((conn, packet)).unwrap();
+ }
+}
+fn handle_conn_write(conn: u128, sock: TcpStream, rx: Receiver<Arc<Vec<u8>>>) -> Result<()> {
+ let mut sock = BufWriter::new(sock);
+ for packet in rx {
+ debug!("{conn} -> {packet:?}");
+ sock.write_all(&packet)?;
+ sock.flush()?;
+ }
+ Ok(())
+}
diff --git a/shared/src/lib.rs b/shared/src/lib.rs
index 56c1fe4..b1da612 100644
--- a/shared/src/lib.rs
+++ b/shared/src/lib.rs
@@ -5,4 +5,4 @@ pub mod resources;
pub mod store;
pub mod tree;
-pub use glam::{Affine3A, Mat3A, Vec3A};
+pub use glam::{Affine3A, Mat3A, Vec3A, vec3a};
diff --git a/shared/src/packets.rs b/shared/src/packets.rs
index 0ceed73..a1636cd 100644
--- a/shared/src/packets.rs
+++ b/shared/src/packets.rs
@@ -1,5 +1,5 @@
use anyhow::{Result, bail};
-use glam::Vec3;
+use glam::Vec3A;
use std::{
fmt::{Debug, Display},
io::{Read, Write},
@@ -10,16 +10,21 @@ pub struct Resource(pub [u8; 32]);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Object(pub u128);
+#[derive(Clone)]
+pub struct Data(pub Vec<u8>);
+
#[derive(Debug, Clone)]
pub enum Packet {
+ Connect(u128),
+ Disconnect,
RequestResource(Resource),
- RespondResource(Vec<u8>),
+ RespondResource(Data),
Add(Object, Resource),
Remove(Object),
- Position(Object, Vec3, Vec3),
+ Position(Object, Vec3A, Vec3A),
Pose(Object, Vec<f32>),
Parent(Object, Object),
- Sound(Object, Vec<u8>),
+ Sound(Object, Data),
}
pub trait ReadWrite: Sized {
@@ -41,14 +46,20 @@ impl Object {
impl Packet {
fn serialize_inner(&self, w: &mut impl Write) -> Result<()> {
match self {
+ Packet::Connect(id) => {
+ w.write_all(&[0x00])?;
+ w.write_all(&id.to_be_bytes())?;
+ }
+ Packet::Disconnect => {
+ w.write_all(&[0xff])?;
+ }
Packet::RequestResource(resource) => {
w.write_all(&[0x01])?;
w.write_all(&resource.0)?;
}
Packet::RespondResource(data) => {
w.write_all(&[0x02])?;
- w.write_all(&(data.len() as u16).to_be_bytes())?;
- w.write_all(&data)?;
+ data.write(w)?;
}
Packet::Add(object, resource) => {
w.write_all(&[0x03])?;
@@ -79,10 +90,10 @@ impl Packet {
w.write_all(&parent.0.to_be_bytes())?;
w.write_all(&child.0.to_be_bytes())?;
}
- Packet::Sound(object, vec) => {
+ Packet::Sound(object, data) => {
w.write_all(&[0x08])?;
w.write_all(&object.0.to_be_bytes())?;
- w.write_all(&(vec.len() as u16).to_be_bytes())?;
+ data.write(w)?;
}
}
Ok(())
@@ -100,18 +111,19 @@ impl ReadWrite for Packet {
let mut size_tag = [0u8; 3];
r.read_exact(&mut size_tag)?;
Ok(match size_tag[2] {
+ 0x00 => Packet::Connect(read_u128(r)?),
0x01 => Packet::RequestResource(Resource::read(r)?),
- 0x02 => Packet::RespondResource(read_data(r)?),
+ 0x02 => Packet::RespondResource(Data::read(r)?),
0x03 => Packet::Add(Object(read_u128(r)?), Resource::read(r)?),
0x04 => Packet::Remove(Object(read_u128(r)?)),
0x05 => Packet::Position(
Object(read_u128(r)?),
- Vec3::new(f32::read(r)?, f32::read(r)?, f32::read(r)?),
- Vec3::new(f32::read(r)?, f32::read(r)?, f32::read(r)?),
+ Vec3A::new(f32::read(r)?, f32::read(r)?, f32::read(r)?),
+ Vec3A::new(f32::read(r)?, f32::read(r)?, f32::read(r)?),
),
0x06 => Packet::Pose(Object(read_u128(r)?), read_params(r)?),
0x07 => Packet::Parent(Object(read_u128(r)?), Object(read_u128(r)?)),
- 0x08 => Packet::Sound(Object(read_u128(r)?), read_data(r)?),
+ 0x08 => Packet::Sound(Object(read_u128(r)?), Data::read(r)?),
_ => {
for _ in 0..u16::from_be_bytes([size_tag[0], size_tag[1]]) - 1 {
r.read_exact(&mut [0])?;
@@ -138,13 +150,20 @@ impl ReadWrite for Resource {
Ok(s)
}
}
-fn read_data(r: &mut dyn Read) -> Result<Vec<u8>> {
- let mut size = [0; 2];
- r.read_exact(&mut size)?;
- let size = u16::from_be_bytes(size);
- let mut buf = vec![0; size as usize];
- r.read_exact(&mut buf)?;
- Ok(buf)
+impl ReadWrite for Data {
+ fn write(&self, w: &mut dyn Write) -> Result<()> {
+ w.write_all(&(self.0.len() as u16).to_be_bytes())?;
+ w.write_all(&self.0)?;
+ Ok(())
+ }
+ fn read(r: &mut dyn Read) -> Result<Self> {
+ let mut size = [0; 2];
+ r.read_exact(&mut size)?;
+ let size = u16::from_be_bytes(size);
+ let mut buf = vec![0; size as usize];
+ r.read_exact(&mut buf)?;
+ Ok(Data(buf))
+ }
}
fn read_params(r: &mut dyn Read) -> Result<Vec<f32>> {
let mut size = [0; 2];
@@ -200,3 +219,8 @@ impl<T: ReadWrite, const N: usize> ReadWrite for [T; N] {
[(); N].try_map(|()| T::read(r))
}
}
+impl Debug for Data {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_tuple("Data").finish_non_exhaustive()
+ }
+}
diff --git a/shared/src/tree.rs b/shared/src/tree.rs
index 4cb7abc..d8d2bfd 100644
--- a/shared/src/tree.rs
+++ b/shared/src/tree.rs
@@ -1,13 +1,13 @@
use crate::packets::{Object, Packet, Resource};
-use glam::Vec3;
+use glam::Vec3A;
use std::collections::HashMap;
pub struct SceneTree {
pub objects: HashMap<Object, ObjectData>,
}
pub struct ObjectData {
- pub pos: Vec3,
- pub rot: Vec3,
+ pub pos: Vec3A,
+ pub rot: Vec3A,
pub parent: Object,
pub pose: Vec<f32>,
pub res: Resource,
@@ -25,8 +25,8 @@ impl SceneTree {
Packet::Add(object, res) => {
self.objects.insert(*object, ObjectData {
parent: Object(0),
- pos: Vec3::ZERO,
- rot: Vec3::ZERO,
+ pos: Vec3A::ZERO,
+ rot: Vec3A::ZERO,
pose: Vec::new(),
res: *res,
});
diff --git a/world/Cargo.toml b/world/Cargo.toml
index ee74e2b..bdfc1f1 100644
--- a/world/Cargo.toml
+++ b/world/Cargo.toml
@@ -10,3 +10,4 @@ env_logger = "0.11.6"
gltf = { version = "1.4.1", features = ["extras", "names"] }
log = "0.4.22"
weareshared = { path = "../shared" }
+rand = "0.9.0-beta.1" \ No newline at end of file
diff --git a/world/src/main.rs b/world/src/main.rs
index fe71e79..4f433ba 100644
--- a/world/src/main.rs
+++ b/world/src/main.rs
@@ -1,21 +1,28 @@
#![feature(iter_array_chunks)]
use anyhow::Result;
use clap::Parser;
+use rand::random;
use std::{
+ io::Write,
net::{SocketAddr, TcpStream},
path::PathBuf,
+ thread::{self, sleep},
+ time::Duration,
};
use weareshared::{
- Affine3A, Mat3A, Vec3A,
- packets::{Object, Packet, ReadWrite},
+ Affine3A, Vec3A,
+ packets::{Data, Object, Packet, ReadWrite},
resources::{Attribute, AttributeArray, IndexArray, Part, Prefab},
store::ResourceStore,
+ vec3a,
};
#[derive(Parser)]
struct Args {
address: SocketAddr,
scene: PathBuf,
+ #[arg(short, long)]
+ push: bool,
}
fn main() -> Result<()> {
@@ -25,6 +32,8 @@ fn main() -> Result<()> {
let mut sock = TcpStream::connect(args.address)?;
let store = ResourceStore::new_memory();
+ Packet::Connect(random()).write(&mut sock)?;
+
let (gltf, buffers, _) = gltf::import(args.scene)?;
let mut prefab = Prefab::default();
@@ -38,6 +47,8 @@ fn main() -> Result<()> {
let mut norm_x = vec![];
let mut norm_y = vec![];
let mut norm_z = vec![];
+ let mut uv_x = vec![];
+ let mut uv_y = vec![];
for p in reader.read_positions().unwrap() {
pos_x.push(p[0]);
pos_y.push(p[1]);
@@ -48,6 +59,10 @@ fn main() -> Result<()> {
norm_y.push(p[1]);
norm_z.push(p[2]);
}
+ for p in reader.read_tex_coords(0).unwrap().into_f32() {
+ uv_x.push(p[0]);
+ uv_y.push(p[1]);
+ }
let index = reader
.read_indices()
.unwrap()
@@ -56,6 +71,8 @@ fn main() -> Result<()> {
.array_chunks::<3>()
.collect::<Vec<_>>();
+ if let Some(tex) = p.material().pbr_metallic_roughness().base_color_texture() {}
+
let part = store.set(
&Part {
va_position: Some([
@@ -68,6 +85,15 @@ fn main() -> Result<()> {
Attribute::Vertex(store.set(&AttributeArray(norm_y).write_alloc())?),
Attribute::Vertex(store.set(&AttributeArray(norm_z).write_alloc())?),
]),
+ va_texcoord: Some([
+ Attribute::Vertex(store.set(&AttributeArray(uv_x).write_alloc())?),
+ Attribute::Vertex(store.set(&AttributeArray(uv_y).write_alloc())?),
+ ]),
+ va_pbr_albedo: Some([
+ Attribute::Constant(0.9),
+ Attribute::Constant(0.1),
+ Attribute::Constant(0.1),
+ ]),
index: Some(store.set(&IndexArray(index).write_alloc())?),
..Part::default()
}
@@ -86,23 +112,42 @@ fn main() -> Result<()> {
}
}
- Packet::Add(Object::new(), store.set(&prefab.write_alloc())?).write(&mut sock)?;
+ let ob = Object::new();
+ Packet::Add(ob, store.set(&prefab.write_alloc())?).write(&mut sock)?;
- store.iter(|d| {
- Packet::RespondResource(d.to_vec())
- .write(&mut sock)
- .unwrap();
- })?;
+ let mut sock2 = sock.try_clone().unwrap();
+ thread::spawn(move || {
+ let mut x = 0.;
+ loop {
+ Packet::Position(ob, Vec3A::ZERO, vec3a(x, x * 0.3, x * 0.1))
+ .write(&mut sock2)
+ .unwrap();
+ sock2.flush().unwrap();
+ x += 0.1;
+ sleep(Duration::from_millis(50));
+ }
+ });
- loop {
- let packet = Packet::read(&mut sock)?;
- match packet {
- Packet::RequestResource(hash) => {
- if let Some(d) = store.get(hash)? {
- Packet::RespondResource(d).write(&mut sock)?;
+ if args.push {
+ store.iter(|d| {
+ Packet::RespondResource(Data(d.to_vec()))
+ .write(&mut sock)
+ .unwrap();
+ })?;
+ sock.flush()?;
+ } else {
+ loop {
+ let packet = Packet::read(&mut sock)?;
+ match packet {
+ Packet::RequestResource(hash) => {
+ if let Some(d) = store.get(hash)? {
+ Packet::RespondResource(Data(d)).write(&mut sock)?;
+ sock.flush()?;
+ }
}
+ _ => (),
}
- _ => (),
}
}
+ Ok(())
}