diff --git a/src/map.rs b/src/map.rs
index c43105c..b5a679a 100644
--- a/src/map.rs
+++ b/src/map.rs
@@ -11,7 +11,9 @@ use strafesnet_common::gameplay_modes;
 pub enum Error{
 	InvalidHeader(binrw::Error),
 	InvalidBlockId(BlockId),
-	InvalidRegion(binrw::Error),
+	InvalidMeshId(model::MeshId),
+	InvalidTextureId(model::TextureId),
+	InvalidData(binrw::Error),
 	File(crate::file::Error),
 }
 
@@ -73,17 +75,29 @@ for model_id in 0..num_models{
 //if you hash the resource itself and set the first 8 bits to this, that's the resource uuid
 #[binrw]
 #[brw(little,repr=u8)]
-enum Resource{
+enum ResourceType{
 	Mesh,
 	Texture,
-	Shader,
-	Sound,
-	Video,
-	Animation,
+	//Shader,
+	//Sound,
+	//Video,
+	//Animation,
 }
+const RESOURCE_TYPE_VARIANT_COUNT:u8=2;
 #[binrw]
 #[brw(little)]
 struct ResourceId(u128);
+impl ResourceId{
+	fn resource_type(&self)->Option<ResourceType>{
+		let discriminant=self.0 as u8;
+		//TODO: use this when it is stabilized https://github.com/rust-lang/rust/issues/73662
+		//if (discriminant as usize)<std::mem::variant_count::<ResourceType>(){
+		match discriminant<RESOURCE_TYPE_VARIANT_COUNT{
+			true=>Some(unsafe{std::mem::transmute::<u8,ResourceType>(discriminant)}),
+			false=>None,
+		}
+	}
+}
 
 struct ResourceMap<T>{
 	meshes:HashMap<strafesnet_common::model::MeshId,T>,
@@ -107,7 +121,7 @@ struct SpacialBlockHeader{
 #[binrw]
 #[brw(little)]
 struct ResourceBlockHeader{
-	resource:Resource,
+	resource:ResourceType,
 	id:BlockId,
 }
 #[binrw]
@@ -152,7 +166,7 @@ pub struct StreamableMap<R:BinReaderExt>{
 	bvh:BvhNode<BlockId>,
 	//something something resources hashmaps
 	resource_blocks:ResourceMap<BlockId>,
-	resource_external:ResourceMap<ResourceId>,
+	//resource_external:ResourceMap<ResourceId>,
 }
 impl<R:BinReaderExt> StreamableMap<R>{
 	pub(crate) fn new(mut file:crate::file::File<R>)->Result<Self,Error>{
@@ -162,13 +176,31 @@ impl<R:BinReaderExt> StreamableMap<R>{
 		let bvh=header.spacial_blocks.into_iter().map(|spacial_block|
 			(spacial_block.id,spacial_block.extents.into())
 		).collect();
-		//TODO: generate mesh ids and texture ids from resource list order
+		//generate mesh ids and texture ids from resource list order
+		let mut resource_blocks=ResourceMap::default();
+		for resource_block_header in header.resource_blocks{
+			match resource_block_header.resource{
+				ResourceType::Mesh=>{
+					resource_blocks.meshes.insert(
+						//generate the id from the current length
+						model::MeshId::new(resource_blocks.meshes.len() as u32),
+						resource_block_header.id
+					);
+				},
+				ResourceType::Texture=>{
+					resource_blocks.textures.insert(
+						model::TextureId::new(resource_blocks.textures.len() as u32),
+						resource_block_header.id
+					);
+				},
+			}
+		}
 		Ok(Self{
 			file,
 			modes:strafesnet_common::gameplay_modes::Modes::new(modes),
 			bvh:strafesnet_common::bvh::generate_bvh(bvh),
-			resource_blocks:Default::default(),
-			resource_external:Default::default(),
+			resource_blocks,
+			//resource_external:Default::default(),
 		})
 	}
 	pub fn get_intersecting_region_block_ids(&self,aabb:&Aabb)->Vec<BlockId>{
@@ -182,15 +214,13 @@ impl<R:BinReaderExt> StreamableMap<R>{
 		//load resources into self.resources
 		//return Region
 		let mut block=self.file.block_reader(block_id).map_err(Error::File)?;
-		let region:Region=block.read_le().map_err(Error::InvalidRegion)?;
+		let region:Region=block.read_le().map_err(Error::InvalidData)?;
 		Ok(region.models.into_iter().map(Into::into).collect())
 	}
-	/*
 	pub fn load_mesh(&mut self,mesh_id:model::MeshId)->Result<model::Mesh,Error>{
-		let block_id=self.resource_blocks.meshes.get(mesh_id).ok_or_err(Error::NotFound)?;
+		let block_id=*self.resource_blocks.meshes.get(&mesh_id).ok_or(Error::InvalidMeshId(mesh_id))?;
 		let mut block=self.file.block_reader(block_id).map_err(Error::File)?;
-		let mesh:newtypes::model::Mesh=block.read_le().map_err(Error::InvalidRegion)?;
+		let mesh:newtypes::model::Mesh=block.read_le().map_err(Error::InvalidData)?;
 		Ok(mesh.into())
 	}
-	*/
 }