steel_protocol/packets/game/
s_sign_update.rs1use std::io::Cursor;
2
3use steel_macros::ServerPacket;
4use steel_utils::BlockPos;
5use steel_utils::serial::{PrefixedRead, ReadFrom};
6use steel_utils::types::SignTextSlot;
7
8pub const MAX_SIGN_LINE_LENGTH: usize = 384;
10
11#[derive(ServerPacket, Clone, Debug)]
13pub struct SSignUpdate {
14 pub pos: BlockPos,
16 pub lines: [String; 4],
18 pub slot: SignTextSlot,
20}
21
22impl ReadFrom for SSignUpdate {
23 fn read(data: &mut Cursor<&[u8]>) -> std::io::Result<Self> {
24 use steel_utils::codec::VarInt;
25
26 let pos = BlockPos::read(data)?;
27 let lines = [
29 String::read_prefixed_bound::<VarInt>(data, MAX_SIGN_LINE_LENGTH)?,
30 String::read_prefixed_bound::<VarInt>(data, MAX_SIGN_LINE_LENGTH)?,
31 String::read_prefixed_bound::<VarInt>(data, MAX_SIGN_LINE_LENGTH)?,
32 String::read_prefixed_bound::<VarInt>(data, MAX_SIGN_LINE_LENGTH)?,
33 ];
34 let slot = SignTextSlot::read(data)?;
35
36 Ok(Self { pos, lines, slot })
37 }
38}
39
40#[cfg(test)]
41mod tests {
42 use super::*;
43
44 #[test]
45 fn sign_update_reads_lines_before_slot() {
46 let mut bytes = 0x0000_0000_0000_0040u64.to_be_bytes().to_vec();
48 for line in ["a", "b", "c", "d"] {
49 bytes.push(1);
50 bytes.extend_from_slice(line.as_bytes());
51 }
52 bytes.push(1); let packet = SSignUpdate::read(&mut Cursor::new(&bytes[..])).expect("should decode");
55
56 assert_eq!(packet.pos, BlockPos::new(0, 64, 0));
57 assert_eq!(packet.lines, ["a", "b", "c", "d"].map(String::from));
58 assert_eq!(packet.slot, SignTextSlot::Front);
59 }
60}