summaryrefslogtreecommitdiff
path: root/shared
diff options
context:
space:
mode:
Diffstat (limited to 'shared')
-rw-r--r--shared/src/packets.rs99
-rw-r--r--shared/src/resources.rs73
-rw-r--r--shared/src/store.rs18
-rw-r--r--shared/src/tree.rs11
4 files changed, 144 insertions, 57 deletions
diff --git a/shared/src/packets.rs b/shared/src/packets.rs
index 9cecbe2..1d3155f 100644
--- a/shared/src/packets.rs
+++ b/shared/src/packets.rs
@@ -14,15 +14,31 @@
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+use crate::resources::{Prefab, PrefabIndex};
use anyhow::{Result, bail};
use glam::Vec3A;
use std::{
fmt::{Debug, Display},
+ hash::Hash,
io::{Read, Write},
+ marker::PhantomData,
};
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
-pub struct Resource(pub [u8; 32]);
+#[derive(Clone, Copy)]
+pub struct Resource<T = ()>(pub [u8; 32], pub PhantomData<T>);
+
+impl<T> PartialEq for Resource<T> {
+ fn eq(&self, other: &Self) -> bool {
+ self.0 == other.0
+ }
+}
+impl<T> Eq for Resource<T> {}
+impl<T> Hash for Resource<T> {
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ self.0.hash(state);
+ }
+}
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Object(pub u128);
@@ -35,12 +51,14 @@ pub enum Packet {
Disconnect,
RequestResource(Resource),
RespondResource(Data),
- Add(Object, Resource),
+ Add(Object, Resource<Prefab>),
Remove(Object),
Position(Object, Vec3A, Vec3A),
Pose(Object, Vec<f32>),
Parent(Object, Object),
Sound(Object, Data),
+ PrefabIndex(Resource<PrefabIndex>),
+ PrefabName(Resource, String),
}
pub trait ReadWrite: Sized {
@@ -84,17 +102,13 @@ impl Packet {
}
Packet::Remove(object) => {
w.write_all(&[0x04])?;
- w.write_all(&object.0.to_be_bytes())?;
+ object.write(w)?;
}
Packet::Position(object, pos, rot) => {
w.write_all(&[0x05])?;
w.write_all(&object.0.to_be_bytes())?;
- w.write_all(&pos.x.to_be_bytes())?;
- w.write_all(&pos.y.to_be_bytes())?;
- w.write_all(&pos.z.to_be_bytes())?;
- w.write_all(&rot.x.to_be_bytes())?;
- w.write_all(&rot.y.to_be_bytes())?;
- w.write_all(&rot.z.to_be_bytes())?;
+ pos.write(w)?;
+ rot.write(w)?;
}
Packet::Pose(object, vec) => {
w.write_all(&[0x06])?;
@@ -111,6 +125,15 @@ impl Packet {
w.write_all(&object.0.to_be_bytes())?;
data.write(w)?;
}
+ Packet::PrefabIndex(resource) => {
+ w.write_all(&[0x09])?;
+ resource.write(w)?;
+ }
+ Packet::PrefabName(resource, name) => {
+ w.write_all(&[0x0a])?;
+ resource.write(w)?;
+ name.write(w)?;
+ }
}
Ok(())
}
@@ -154,21 +177,42 @@ fn read_u128(r: &mut dyn Read) -> Result<u128> {
r.read_exact(&mut buf)?;
Ok(u128::from_be_bytes(buf))
}
-impl ReadWrite for Resource {
+impl<T> ReadWrite for Resource<T> {
fn write(&self, w: &mut dyn Write) -> Result<()> {
w.write_all(&self.0)?;
Ok(())
}
fn read(r: &mut dyn Read) -> Result<Self> {
- let mut s = Self([0; 32]);
+ let mut s = Self([0; 32], PhantomData);
r.read_exact(&mut s.0)?;
Ok(s)
}
}
+impl ReadWrite for Object {
+ fn write(&self, w: &mut dyn Write) -> Result<()> {
+ w.write_all(&self.0.to_be_bytes())?;
+ Ok(())
+ }
+
+ fn read(r: &mut dyn Read) -> Result<Self> {
+ let mut s = [0; 16];
+ r.read_exact(&mut s)?;
+ Ok(Object(u128::from_be_bytes(s)))
+ }
+}
+
impl ReadWrite for Data {
fn write(&self, w: &mut dyn Write) -> Result<()> {
- w.write_all(&(self.0.len() as u32).to_be_bytes())?;
- w.write_all(&self.0)?;
+ self.0.write(w)
+ }
+ fn read(r: &mut dyn Read) -> Result<Self> {
+ Ok(Self(Vec::read(r)?))
+ }
+}
+impl ReadWrite for Vec<u8> {
+ fn write(&self, w: &mut dyn Write) -> Result<()> {
+ w.write_all(&(self.len() as u32).to_be_bytes())?;
+ w.write_all(&self)?;
Ok(())
}
fn read(r: &mut dyn Read) -> Result<Self> {
@@ -177,7 +221,22 @@ impl ReadWrite for Data {
let size = u32::from_be_bytes(size);
let mut buf = vec![0; size as usize];
r.read_exact(&mut buf)?;
- Ok(Data(buf))
+ Ok(buf)
+ }
+}
+impl ReadWrite for String {
+ fn write(&self, w: &mut dyn Write) -> Result<()> {
+ w.write_all(&(self.len() as u32).to_be_bytes())?;
+ w.write_all(self.as_bytes())?;
+ Ok(())
+ }
+ fn read(r: &mut dyn Read) -> Result<Self> {
+ let mut size = [0; 4];
+ r.read_exact(&mut size)?;
+ let size = u32::from_be_bytes(size);
+ let mut buf = vec![0; size as usize];
+ r.read_exact(&mut buf)?;
+ Ok(String::from_utf8(buf)?)
}
}
fn read_params(r: &mut dyn Read) -> Result<Vec<f32>> {
@@ -214,7 +273,7 @@ impl ReadWrite for u32 {
}
}
-impl Display for Resource {
+impl<T> Display for Resource<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
@@ -226,8 +285,7 @@ impl Display for Resource {
)
}
}
-
-impl Debug for Resource {
+impl<T> Debug for Resource<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self)
}
@@ -250,3 +308,8 @@ impl Debug for Data {
f.debug_tuple("Data").finish_non_exhaustive()
}
}
+impl Display for Object {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_tuple("Object").field(&self.0).finish()
+ }
+}
diff --git a/shared/src/resources.rs b/shared/src/resources.rs
index be34b21..d22e3ea 100644
--- a/shared/src/resources.rs
+++ b/shared/src/resources.rs
@@ -19,60 +19,64 @@ use anyhow::Result;
use glam::{Affine3A, Vec3A};
use log::warn;
use std::{
- collections::HashMap,
+ collections::{BTreeMap, HashMap},
io::{Read, Write},
};
#[derive(Debug, Default, Clone)]
pub struct Prefab {
- pub mesh: Vec<(Affine3A, Resource)>,
- pub light: Vec<(Vec3A, Resource)>,
- pub environment: Option<EnvironmentPart>,
+ pub mesh: Vec<(Affine3A, Resource<MeshPart>)>,
+ pub light: Vec<(Vec3A, Resource<LightPart>)>,
+ pub environment: Option<Resource<EnvironmentPart>>,
}
#[derive(Debug, Default, Clone)]
pub struct LightPart {
- emission: Option<Vec3A>,
- radius: Option<f32>,
+ pub emission: Option<Vec3A>,
+ pub radius: Option<f32>,
}
#[derive(Debug, Default, Clone)]
pub struct EnvironmentPart {
- skybox: Option<Resource>,
- sun: Option<(Vec3A, Vec3A)>,
+ pub skybox: Option<Resource>,
+ pub sun: Option<(Vec3A, Vec3A)>,
}
#[derive(Debug, Default, Clone)]
pub struct MeshPart {
- pub index: Option<Resource>,
+ pub index: Option<Resource<IndexArray>>,
pub g_metallic: Option<f32>,
pub g_roughness: Option<f32>,
pub g_albedo: Option<Vec3A>,
pub g_transmission: Option<f32>,
pub g_emission: Option<Vec3A>,
- pub va_position: Option<[Resource; 3]>,
- pub va_normal: Option<[Resource; 3]>,
- pub va_texcoord: Option<[Resource; 2]>,
- pub va_roughness: Option<Resource>,
- pub va_metallic: Option<Resource>,
- pub va_albedo: Option<[Resource; 3]>,
- pub va_transmission: Option<Resource>,
- pub va_emission: Option<[Resource; 3]>,
- pub tex_normal: Option<Resource>,
- pub tex_roughness: Option<Resource>,
- pub tex_metallic: Option<Resource>,
- pub tex_albedo: Option<Resource>,
- pub tex_transmission: Option<Resource>,
- pub tex_emission: Option<Resource>,
+ pub va_position: Option<[Resource<AttributeArray>; 3]>,
+ pub va_normal: Option<[Resource<AttributeArray>; 3]>,
+ pub va_texcoord: Option<[Resource<AttributeArray>; 2]>,
+ pub va_roughness: Option<Resource<AttributeArray>>,
+ pub va_metallic: Option<Resource<AttributeArray>>,
+ pub va_albedo: Option<[Resource<AttributeArray>; 3]>,
+ pub va_transmission: Option<Resource<AttributeArray>>,
+ pub va_emission: Option<[Resource<AttributeArray>; 3]>,
+ pub tex_normal: Option<Resource<Image>>,
+ pub tex_roughness: Option<Resource<Image>>,
+ pub tex_metallic: Option<Resource<Image>>,
+ pub tex_albedo: Option<Resource<Image>>,
+ pub tex_transmission: Option<Resource<Image>>,
+ pub tex_emission: Option<Resource<Image>>,
}
-pub struct PrefabIndex(pub HashMap<String, Resource>);
+#[derive(Debug, Default, Clone)]
+pub struct PrefabIndex(pub BTreeMap<String, Resource>);
#[derive(Debug, Default, Clone)]
pub struct AttributeArray(pub Vec<f32>);
#[derive(Debug, Default, Clone)]
pub struct IndexArray(pub Vec<[u16; 3]>);
+#[derive(Debug, Clone)]
+pub struct Image(pub Vec<u8>);
+
impl ReadWrite for PrefabIndex {
fn write(&self, w: &mut dyn Write) -> Result<()> {
for (k, v) in &self.0 {
@@ -81,7 +85,7 @@ impl ReadWrite for PrefabIndex {
Ok(())
}
fn read(r: &mut dyn Read) -> Result<Self> {
- let mut s = Self(HashMap::new());
+ let mut s = Self(BTreeMap::new());
let mut g = Vec::new();
r.read_to_end(&mut g)?;
let mut g = g.as_slice();
@@ -96,10 +100,10 @@ impl ReadWrite for PrefabIndex {
impl ReadWrite for Prefab {
fn write(&self, w: &mut dyn Write) -> Result<()> {
for x in &self.mesh {
- write_kv_opt(w, b"mesh", &Some(*x))?;
+ write_kv_opt(w, b"mesh", &Some(x.clone()))?;
}
for x in &self.light {
- write_kv_opt(w, b"light", &Some(*x))?;
+ write_kv_opt(w, b"light", &Some(x.clone()))?;
}
write_kv_opt(w, b"environment", &self.environment)?;
Ok(())
@@ -269,9 +273,9 @@ impl ReadWrite for u8 {
impl ReadWrite for Vec3A {
fn write(&self, w: &mut dyn Write) -> Result<()> {
- w.write_all(&self.x.to_be_bytes())?;
- w.write_all(&self.y.to_be_bytes())?;
- w.write_all(&self.z.to_be_bytes())?;
+ self.x.write(w)?;
+ self.y.write(w)?;
+ self.z.write(w)?;
Ok(())
}
fn read(r: &mut dyn Read) -> Result<Self> {
@@ -333,3 +337,12 @@ impl<A: ReadWrite, B: ReadWrite> ReadWrite for (A, B) {
Ok((A::read(r)?, B::read(r)?))
}
}
+impl ReadWrite for Image {
+ fn write(&self, w: &mut dyn Write) -> Result<()> {
+ self.0.write(w)
+ }
+
+ fn read(r: &mut dyn Read) -> Result<Self> {
+ Ok(Self(<Vec<u8> as ReadWrite>::read(r)?))
+ }
+}
diff --git a/shared/src/store.rs b/shared/src/store.rs
index 38402fc..f63ed6c 100644
--- a/shared/src/store.rs
+++ b/shared/src/store.rs
@@ -14,11 +14,11 @@
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-use crate::packets::Resource;
+use crate::packets::{ReadWrite, Resource};
use anyhow::Result;
use redb::{Database, TableDefinition};
use sha2::{Digest, Sha256};
-use std::{collections::HashMap, path::Path, sync::Mutex};
+use std::{collections::HashMap, marker::PhantomData, path::Path, sync::Mutex};
const T_ENTRIES: TableDefinition<[u8; 32], &[u8]> = TableDefinition::new("e");
@@ -33,7 +33,15 @@ impl ResourceStore {
pub fn new_memory() -> Self {
Self::Memory(HashMap::new().into())
}
- pub fn get(&self, key: Resource) -> Result<Option<Vec<u8>>> {
+ pub fn get<T: ReadWrite>(&self, key: Resource<T>) -> Result<Option<T>> {
+ self.get_raw(Resource(key.0, PhantomData))?
+ .map(|b| T::read(&mut b.as_slice()))
+ .transpose()
+ }
+ pub fn set<T: ReadWrite>(&self, value: &T) -> Result<Resource<T>> {
+ Ok(Resource(self.set_raw(&value.write_alloc())?.0, PhantomData))
+ }
+ pub fn get_raw(&self, key: Resource) -> Result<Option<Vec<u8>>> {
match self {
ResourceStore::Redb(database) => {
let txn = database.begin_read()?;
@@ -46,8 +54,8 @@ impl ResourceStore {
ResourceStore::Memory(map) => Ok(map.lock().unwrap().get(&key).map(|x| x.to_vec())),
}
}
- pub fn set(&self, value: &[u8]) -> Result<Resource> {
- let key = Resource(sha256(value));
+ pub fn set_raw(&self, value: &[u8]) -> Result<Resource> {
+ let key = Resource(sha256(value), PhantomData);
match self {
ResourceStore::Redb(database) => {
let txn = database.begin_write()?;
diff --git a/shared/src/tree.rs b/shared/src/tree.rs
index e2c8250..9337cfb 100644
--- a/shared/src/tree.rs
+++ b/shared/src/tree.rs
@@ -14,7 +14,10 @@
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-use crate::packets::{Object, Packet, Resource};
+use crate::{
+ packets::{Object, Packet, Resource},
+ resources::Prefab,
+};
use glam::Vec3A;
use std::collections::HashMap;
@@ -26,7 +29,7 @@ pub struct ObjectData {
pub rot: Vec3A,
pub parent: Object,
pub pose: Vec<f32>,
- pub res: Resource,
+ pub res: Resource<Prefab>,
}
impl Default for SceneTree {
fn default() -> Self {
@@ -44,7 +47,7 @@ impl SceneTree {
pos: Vec3A::ZERO,
rot: Vec3A::ZERO,
pose: Vec::new(),
- res: *res,
+ res: res.clone(),
});
}
Packet::Remove(object) => {
@@ -75,7 +78,7 @@ impl SceneTree {
.iter()
.map(|(object, data)| {
[
- Packet::Add(*object, data.res),
+ Packet::Add(*object, data.res.clone()),
Packet::Parent(*object, data.parent),
Packet::Position(*object, data.pos, data.rot),
Packet::Pose(*object, data.pose.clone()),