1use std::io::{self, Cursor, Write};
2
3use bitflags::bitflags;
4use serde::{Deserialize, Serialize};
5
6use crate::{
7 codec::VarInt,
8 serial::{ReadFrom, WriteTo},
9};
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13#[expect(missing_docs, reason = "variant names are self-explanatory")]
14pub enum GameType {
15 Survival = 0,
16 Creative = 1,
17 Adventure = 2,
18 Spectator = 3,
19}
20
21impl GameType {
22 #[must_use]
24 pub const fn name(self) -> &'static str {
25 match self {
26 GameType::Survival => "survival",
27 GameType::Creative => "creative",
28 GameType::Adventure => "adventure",
29 GameType::Spectator => "spectator",
30 }
31 }
32}
33
34impl ReadFrom for GameType {
35 fn read(data: &mut Cursor<&[u8]>) -> io::Result<Self> {
36 let value = VarInt::read(data)?.0;
37 match value {
38 0 => Ok(GameType::Survival),
39 1 => Ok(GameType::Creative),
40 2 => Ok(GameType::Adventure),
41 3 => Ok(GameType::Spectator),
42 _ => Err(io::Error::new(
43 io::ErrorKind::InvalidData,
44 "Invalid GameType",
45 )),
46 }
47 }
48}
49
50impl From<GameType> for i8 {
51 fn from(value: GameType) -> Self {
52 value as i8
53 }
54}
55
56impl From<GameType> for i32 {
57 fn from(value: GameType) -> Self {
58 value as i32
59 }
60}
61
62impl From<GameType> for f32 {
63 fn from(value: GameType) -> Self {
64 f32::from(value as i8)
65 }
66}
67
68impl From<i8> for GameType {
69 fn from(value: i8) -> Self {
70 match value {
71 1 => GameType::Creative,
72 2 => GameType::Adventure,
73 3 => GameType::Spectator,
74 _ => GameType::Survival,
75 }
76 }
77}
78
79impl From<i32> for GameType {
80 fn from(value: i32) -> Self {
81 match value {
82 1 => GameType::Creative,
83 2 => GameType::Adventure,
84 3 => GameType::Spectator,
85 _ => GameType::Survival,
86 }
87 }
88}
89
90impl From<f32> for GameType {
91 fn from(value: f32) -> Self {
92 match value {
93 1. => GameType::Creative,
94 2. => GameType::Adventure,
95 3. => GameType::Spectator,
96 _ => GameType::Survival,
97 }
98 }
99}
100
101#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
106#[repr(u8)]
107pub enum Difficulty {
108 Peaceful = 0,
110 Easy = 1,
112 #[default]
114 Normal = 2,
115 Hard = 3,
117}
118
119#[expect(clippy::match_same_arms, reason = "cause it looks better")]
120impl From<u8> for Difficulty {
121 fn from(value: u8) -> Self {
122 match value {
123 0 => Difficulty::Peaceful,
124 1 => Difficulty::Easy,
125 2 => Difficulty::Normal,
126 3 => Difficulty::Hard,
127 _ => Difficulty::Normal,
128 }
129 }
130}
131
132impl From<Difficulty> for u8 {
133 fn from(value: Difficulty) -> Self {
134 value as u8
135 }
136}
137
138impl ReadFrom for Difficulty {
139 fn read(data: &mut Cursor<&[u8]>) -> io::Result<Self> {
140 let value = <u8 as ReadFrom>::read(data)?;
141 match value {
142 0 => Ok(Difficulty::Peaceful),
143 1 => Ok(Difficulty::Easy),
144 2 => Ok(Difficulty::Normal),
145 3 => Ok(Difficulty::Hard),
146 _ => Err(io::Error::new(
147 io::ErrorKind::InvalidData,
148 format!("Invalid Difficulty: {value}"),
149 )),
150 }
151 }
152}
153
154impl WriteTo for Difficulty {
155 fn write(&self, writer: &mut impl Write) -> io::Result<()> {
156 (*self as u8).write(writer)
157 }
158}
159
160impl Serialize for Difficulty {
161 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
162 where
163 S: serde::Serializer,
164 {
165 serializer.serialize_u8(*self as u8)
166 }
167}
168
169impl<'de> Deserialize<'de> for Difficulty {
170 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
171 where
172 D: serde::Deserializer<'de>,
173 {
174 let id = u8::deserialize(deserializer)?;
175 Ok(Self::from(id))
176 }
177}
178
179#[derive(Debug, Clone, Copy, PartialEq, Eq)]
181#[repr(u8)]
182pub enum InteractionHand {
183 MainHand = 0,
185 OffHand = 1,
187}
188
189impl WriteTo for InteractionHand {
190 fn write(&self, writer: &mut impl Write) -> io::Result<()> {
191 VarInt(*self as i32).write(writer)
192 }
193}
194
195impl ReadFrom for InteractionHand {
196 fn read(data: &mut Cursor<&[u8]>) -> io::Result<Self> {
197 let id = VarInt::read(data)?.0;
198 match id {
199 0 => Ok(InteractionHand::MainHand),
200 1 => Ok(InteractionHand::OffHand),
201 _ => Err(io::Error::other("Invalid InteractionHand id")),
202 }
203 }
204}
205
206#[derive(Debug, Clone, Copy, PartialEq, Eq)]
208pub enum SignTextSlot {
209 Back = 0,
211 Front = 1,
213}
214
215impl SignTextSlot {
216 #[must_use]
218 pub const fn is_front(self) -> bool {
219 matches!(self, SignTextSlot::Front)
220 }
221}
222
223impl ReadFrom for SignTextSlot {
224 fn read(data: &mut Cursor<&[u8]>) -> io::Result<Self> {
225 Ok(match VarInt::read(data)?.0 {
228 1 => SignTextSlot::Front,
229 _ => SignTextSlot::Back,
230 })
231 }
232}
233
234#[derive(Clone, Copy, Debug, PartialEq, Eq)]
236pub struct UpdateFlags(u16);
237
238bitflags! {
239 impl UpdateFlags: u16 {
240 const UPDATE_NEIGHBORS = 1;
241 const UPDATE_CLIENTS = 1 << 1;
242 const UPDATE_INVISIBLE = 1 << 2;
243 const UPDATE_IMMEDIATE = 1 << 3;
244 const UPDATE_KNOWN_SHAPE = 1 << 4;
245 const UPDATE_SUPPRESS_DROPS = 1 << 5;
246 const UPDATE_MOVE_BY_PISTON = 1 << 6;
247 const UPDATE_SKIP_SHAPE_UPDATE_ON_WIRE = 1 << 7;
248 const UPDATE_SKIP_BLOCK_ENTITY_SIDEEFFECTS = 1 << 8;
249 const UPDATE_SKIP_ON_PLACE = 1 << 9;
250
251 const UPDATE_NONE = Self::UPDATE_INVISIBLE.bits() | Self::UPDATE_SKIP_BLOCK_ENTITY_SIDEEFFECTS.bits();
252 const UPDATE_ALL = Self::UPDATE_NEIGHBORS.bits() | Self::UPDATE_CLIENTS.bits();
253 const UPDATE_ALL_IMMEDIATE = Self::UPDATE_ALL.bits() | Self::UPDATE_IMMEDIATE.bits();
254 }
255}