1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
use basin2_lib::nbt::*; use crate::network::*; use crate::packet::*; use basin2_lib::result::*; use bytes::BytesMut; #[derive(PartialEq, Clone, Debug)] pub struct LevelChunkPacket { pub x: i32, pub z: i32, pub availableSections: i32, pub heightmaps: Nbt, pub biomes: Option<Vec<i32>>, pub buffer: BytesMut, pub blockEntitiesTags: Vec<Nbt>, } impl CodablePacket for LevelChunkPacket { fn encode(self, buf: &mut BytesMut) { buf.set_mc_i32(self.x); buf.set_mc_i32(self.z); buf.set_mc_bool(self.biomes.is_some()); buf.set_mc_var_int(self.availableSections); buf.set_mc_nbt(self.heightmaps); match self.biomes { Some(biomes) => { for biome in biomes.iter() { buf.set_mc_i32(*biome); } } None => (), } buf.set_mc_var_int(self.buffer.len() as i32); buf.unsplit(self.buffer); buf.set_mc_var_int(self.blockEntitiesTags.len() as i32); for blockEntitiesTag in self.blockEntitiesTags { buf.set_mc_nbt(blockEntitiesTag); } } fn decode(buf: &mut BytesMut) -> Result<Self> where Self: Sized, { let x = buf.get_mc_i32()?; let z = buf.get_mc_i32()?; let has_biomes = buf.get_mc_bool()?; let availableSections = buf.get_mc_var_int()?; let heightmaps = buf.get_mc_nbt()?; let biomes = if has_biomes { let mut biomes = vec![0; 1 << 10]; for i in 0..(1 << 10) { biomes[i] = buf.get_mc_i32()?; } Some(biomes) } else { None }; let buffer_size = buf.get_mc_var_int()? as usize; if buffer_size > buf.len() || buffer_size > 2097152 { return Err(Box::new(IoError::from(ErrorKind::InvalidData))); } let buffer = buf.split_to(buffer_size); let mut blockEntitiesTags: Vec<Nbt> = vec![]; let blockEntitiesTags_count = buf.get_mc_var_int()?; for _ in 0..blockEntitiesTags_count { blockEntitiesTags.push(buf.get_mc_nbt()?); } return Ok(LevelChunkPacket { x, z, availableSections, heightmaps, biomes, buffer, blockEntitiesTags, }); } } #[cfg(test)] mod tests { use super::*; use crate::packet::test::*; #[test] fn test_cycle() -> Result<()> { cycle(LevelChunkPacket { x: 12, z: -12, availableSections: 1, heightmaps: Nbt::make_singleton_compound( "test".to_string(), Nbt::List { item_type: NbtType::Int, children: vec![Nbt::Int(65)], }, ), biomes: Some(vec![23; 1 << 10]), buffer: BytesMut::from(&vec![0x1a, 0x2b, 0x3c][..]), blockEntitiesTags: vec![Nbt::make_singleton_compound( "test entity".to_string(), Nbt::Int(7), )], }) } }