box drops working and load correct city file
This commit is contained in:
		
							parent
							
								
									a8892467f6
								
							
						
					
					
						commit
						dcc5b57b8e
					
				| @ -217,7 +217,7 @@ struct RawMapObject { | |||||||
| 
 | 
 | ||||||
| impl RawMapObject { | impl RawMapObject { | ||||||
|     fn from_byte_stream<R: Read>(cursor: &mut R) -> Result<RawMapObject, std::io::Error> { |     fn from_byte_stream<R: Read>(cursor: &mut R) -> Result<RawMapObject, std::io::Error> { | ||||||
|         Ok(RawMapObject { |         let o = RawMapObject { | ||||||
|             otype: cursor.read_u16::<LittleEndian>()?, |             otype: cursor.read_u16::<LittleEndian>()?, | ||||||
|             unknown1: cursor.read_u16::<LittleEndian>()?, |             unknown1: cursor.read_u16::<LittleEndian>()?, | ||||||
|             unknown2: cursor.read_u32::<LittleEndian>()?, |             unknown2: cursor.read_u32::<LittleEndian>()?, | ||||||
| @ -238,7 +238,11 @@ impl RawMapObject { | |||||||
|             field5: cursor.read_u32::<LittleEndian>()?, |             field5: cursor.read_u32::<LittleEndian>()?, | ||||||
|             field6: cursor.read_u32::<LittleEndian>()?, |             field6: cursor.read_u32::<LittleEndian>()?, | ||||||
|             field7: cursor.read_u32::<LittleEndian>()?, |             field7: cursor.read_u32::<LittleEndian>()?, | ||||||
|         }) |         }; | ||||||
|  | 
 | ||||||
|  |         println!("{:?}", o); | ||||||
|  | 
 | ||||||
|  |         Ok(o) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -310,6 +314,8 @@ pub enum MapObjectType { | |||||||
| #[derive(Debug, Copy, Clone)] | #[derive(Debug, Copy, Clone)] | ||||||
| pub struct MapObject { | pub struct MapObject { | ||||||
|     pub object: MapObjectType, |     pub object: MapObjectType, | ||||||
|  |     pub map: MapArea, | ||||||
|  |     pub dropped_item: bool, | ||||||
|     //id: u32,
 |     //id: u32,
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -320,7 +326,7 @@ enum MapObjectError { | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| impl MapObject { | impl MapObject { | ||||||
|     fn from_raw(raw: RawMapObject, episode: Episode) -> Result<MapObject, MapObjectError> { |     fn from_raw(raw: RawMapObject, episode: Episode, map_area: &MapArea) -> Result<MapObject, MapObjectError> { | ||||||
|         let object = match (raw, episode) { |         let object = match (raw, episode) { | ||||||
|             (RawMapObject {otype: 136, ..}, _) => MapObjectType::Box, |             (RawMapObject {otype: 136, ..}, _) => MapObjectType::Box, | ||||||
|             (RawMapObject {otype: 145, ..}, _) => MapObjectType::EnemyBox, |             (RawMapObject {otype: 145, ..}, _) => MapObjectType::EnemyBox, | ||||||
| @ -335,8 +341,11 @@ impl MapObject { | |||||||
|             _ => return Err(MapObjectError::UnknownObjectType(raw.otype, raw)) |             _ => return Err(MapObjectError::UnknownObjectType(raw.otype, raw)) | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|  |         println!("{:#?}", object); | ||||||
|         Ok(MapObject { |         Ok(MapObject { | ||||||
|             object: object, |             object: object, | ||||||
|  |             map: map_area.clone(), | ||||||
|  |             dropped_item: false, | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -496,7 +505,7 @@ impl MapVariant { | |||||||
| 
 | 
 | ||||||
|     fn obj_file(&self) -> String { |     fn obj_file(&self) -> String { | ||||||
|         match self.map { |         match self.map { | ||||||
|             MapArea::Pioneer2Ep1 => "data/maps/map_city00_00e.dat".into(), |             MapArea::Pioneer2Ep1 => "data/maps/map_city00_00o.dat".into(), | ||||||
|             MapArea::Forest1 => format!("data/maps/map_forest01_0{}o.dat", self.minor), |             MapArea::Forest1 => format!("data/maps/map_forest01_0{}o.dat", self.minor), | ||||||
|             MapArea::Forest2 => format!("data/maps/map_forest02_0{}o.dat", self.minor), |             MapArea::Forest2 => format!("data/maps/map_forest02_0{}o.dat", self.minor), | ||||||
|             MapArea::Caves1 => format!("data/maps/map_cave01_0{}_0{}o.dat", self.major, self.minor), |             MapArea::Caves1 => format!("data/maps/map_cave01_0{}_0{}o.dat", self.major, self.minor), | ||||||
| @ -520,12 +529,12 @@ impl MapVariant { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| fn objects_from_map_data(path: PathBuf, episode: &Episode) -> Vec<Option<MapObject>> { | fn objects_from_map_data(path: PathBuf, episode: &Episode, map_variant: &MapVariant) -> Vec<Option<MapObject>> { | ||||||
|     let mut cursor = File::open(path.clone()).unwrap(); |     let mut cursor = File::open(path.clone()).unwrap(); | ||||||
|     let mut object_data = Vec::new(); |     let mut object_data = Vec::new(); | ||||||
| 
 | 
 | ||||||
|     while let Ok(raw_object) = RawMapObject::from_byte_stream(&mut cursor) { |     while let Ok(raw_object) = RawMapObject::from_byte_stream(&mut cursor) { | ||||||
|         let object = MapObject::from_raw(raw_object.clone(), *episode); |         let object = MapObject::from_raw(raw_object.clone(), *episode, &map_variant.map); | ||||||
|         object_data.push(object.ok()); |         object_data.push(object.ok()); | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| @ -631,6 +640,7 @@ fn enemy_data_from_map_data(map_variant: &MapVariant, episode: &Episode) -> Vec< | |||||||
| #[error("")] | #[error("")] | ||||||
| pub enum MapsError { | pub enum MapsError { | ||||||
|     InvalidMonsterId(usize), |     InvalidMonsterId(usize), | ||||||
|  |     InvalidObjectId(usize), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| @ -670,7 +680,7 @@ impl Maps { | |||||||
|                 enemy_data |                 enemy_data | ||||||
|             }), |             }), | ||||||
|             object_data: map_variants.iter().map(|map_variant| { |             object_data: map_variants.iter().map(|map_variant| { | ||||||
|                 objects_from_map_data(map_variant.obj_file().into(), &episode) |                 objects_from_map_data(map_variant.obj_file().into(), &episode, &map_variant) | ||||||
|             }).flatten().collect(), |             }).flatten().collect(), | ||||||
|             map_variants: map_variants, |             map_variants: map_variants, | ||||||
|         }; |         }; | ||||||
| @ -682,6 +692,10 @@ impl Maps { | |||||||
|         self.enemy_data[id].ok_or(MapsError::InvalidMonsterId(id)) |         self.enemy_data[id].ok_or(MapsError::InvalidMonsterId(id)) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     pub fn object_by_id(&self, id: usize) -> Result<MapObject, MapsError> { | ||||||
|  |         self.object_data[id].ok_or(MapsError::InvalidObjectId(id)) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     pub fn map_headers(&self) -> [u32; 0x20] { |     pub fn map_headers(&self) -> [u32; 0x20] { | ||||||
|         self.map_variants.iter() |         self.map_variants.iter() | ||||||
|             .enumerate() |             .enumerate() | ||||||
|  | |||||||
| @ -139,3 +139,56 @@ where | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | pub fn request_box_item<EG>(id: ClientId, | ||||||
|  |     box_drop_request: &BoxDropRequest, | ||||||
|  |     entity_gateway: &mut EG, | ||||||
|  |     client_location: &ClientLocation, | ||||||
|  |     clients: &mut Clients, | ||||||
|  |     rooms: &mut Rooms, | ||||||
|  |     item_manager: &mut ItemManager) | ||||||
|  |     -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError> | ||||||
|  | where | ||||||
|  | EG: EntityGateway | ||||||
|  | { | ||||||
|  |     let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?; | ||||||
|  |     let room = rooms.get_mut(room_id.0) | ||||||
|  |         .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))? | ||||||
|  |         .as_mut() | ||||||
|  |         .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))?; | ||||||
|  | 
 | ||||||
|  |     let box_object = room.maps.object_by_id(box_drop_request.object_id as usize)?; | ||||||
|  |     if box_object.dropped_item { | ||||||
|  |         return Err(ShipError::BoxAlreadyDroppedItem(id, box_drop_request.object_id)) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?; | ||||||
|  | 
 | ||||||
|  |     let item_drop_packets = clients_in_area.into_iter() | ||||||
|  |         .filter_map(|area_client| { | ||||||
|  |             room.drop_table.get_box_drop(&box_object.map, &box_object).map(|item_drop_type| { | ||||||
|  |                 warn!("drop is? {:?}", item_drop_type); | ||||||
|  |                 (area_client, item_drop_type) | ||||||
|  |             }) | ||||||
|  |         }) | ||||||
|  |         .map(|(area_client, item_drop_type)| -> Result<_, ShipError> { | ||||||
|  |             let item_drop = ItemDrop { | ||||||
|  |                 map_area: box_object.map, | ||||||
|  |                 x: box_drop_request.x, | ||||||
|  |                 y: 0.0, | ||||||
|  |                 z: box_drop_request.z, | ||||||
|  |                 item: item_drop_type, | ||||||
|  |             }; | ||||||
|  |             let client = clients.get_mut(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client))?; | ||||||
|  |             let floor_item = item_manager.drop_item_on_local_floor(entity_gateway, &client.character, item_drop).unwrap(); // TODO: unwrap
 | ||||||
|  |             let item_drop_msg = builder::message::item_drop(box_drop_request.client, box_drop_request.target, &floor_item)?; | ||||||
|  |             client.floor_items.push(floor_item); | ||||||
|  |             Ok((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg))))) | ||||||
|  |         }) | ||||||
|  |         .filter_map(|item_drop_pkt| { | ||||||
|  |             // TODO: log errors here
 | ||||||
|  |             item_drop_pkt.ok() | ||||||
|  |         }) | ||||||
|  |         .collect::<Vec<_>>(); // TODO: can EntityGateway be Sync?
 | ||||||
|  | 
 | ||||||
|  |     Ok(Box::new(item_drop_packets.into_iter())) | ||||||
|  | } | ||||||
| @ -50,6 +50,7 @@ pub enum ShipError { | |||||||
|     DropInvalidItemId(u32), |     DropInvalidItemId(u32), | ||||||
|     ItemManagerError(#[from] items::ItemManagerError), |     ItemManagerError(#[from] items::ItemManagerError), | ||||||
|     ItemDropLocationNotSet, |     ItemDropLocationNotSet, | ||||||
|  |     BoxAlreadyDroppedItem(ClientId, u16), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| @ -247,6 +248,10 @@ impl<EG: EntityGateway> ShipServerState<EG> { | |||||||
|             GameMessage::PickupItem(pickup_item) => { |             GameMessage::PickupItem(pickup_item) => { | ||||||
|                 handler::direct_message::pickup_item(id, pickup_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).unwrap() |                 handler::direct_message::pickup_item(id, pickup_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).unwrap() | ||||||
|             }, |             }, | ||||||
|  |             GameMessage::BoxDropRequest(box_drop_request) => { | ||||||
|  |                 println!("box drop requested!"); | ||||||
|  |                 handler::direct_message::request_box_item(id, box_drop_request, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_database).unwrap() | ||||||
|  |             } | ||||||
|             _ => { |             _ => { | ||||||
|                 let cmsg = msg.clone(); |                 let cmsg = msg.clone(); | ||||||
|                 Box::new(self.client_location.get_all_clients_by_client(id).unwrap().into_iter() |                 Box::new(self.client_location.get_all_clients_by_client(id).unwrap().into_iter() | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user