mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 06:16:04 +00:00
difficulty packet
This commit is contained in:
parent
394f996df2
commit
96eba2b39a
7 changed files with 177 additions and 12 deletions
|
@ -70,6 +70,9 @@ pub async fn join_server(address: &ServerAddress) -> Result<(), String> {
|
||||||
GamePacket::ClientboundCustomPayloadPacket(p) => {
|
GamePacket::ClientboundCustomPayloadPacket(p) => {
|
||||||
println!("Got custom payload packet {:?}", p);
|
println!("Got custom payload packet {:?}", p);
|
||||||
}
|
}
|
||||||
|
GamePacket::ClientboundChangeDifficultyPacket(p) => {
|
||||||
|
println!("Got difficulty packet {:?}", p);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Error: {:?}", e);
|
println!("Error: {:?}", e);
|
||||||
|
|
96
azalea-core/src/difficulty.rs
Normal file
96
azalea-core/src/difficulty.rs
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
use std::fmt::{Debug, Error, Formatter};
|
||||||
|
|
||||||
|
#[derive(Hash, Clone, Debug, PartialEq)]
|
||||||
|
pub enum Difficulty {
|
||||||
|
PEACEFUL,
|
||||||
|
EASY,
|
||||||
|
NORMAL,
|
||||||
|
HARD,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Err {
|
||||||
|
InvalidDifficulty(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for Err {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
|
||||||
|
match self {
|
||||||
|
Err::InvalidDifficulty(s) => write!(f, "Invalid difficulty: {}", s),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Difficulty {
|
||||||
|
pub fn name(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Difficulty::PEACEFUL => "peaceful",
|
||||||
|
Difficulty::EASY => "easy",
|
||||||
|
Difficulty::NORMAL => "normal",
|
||||||
|
Difficulty::HARD => "hard",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_name(name: &str) -> Result<Difficulty, Err> {
|
||||||
|
match name {
|
||||||
|
"peaceful" => Ok(Difficulty::PEACEFUL),
|
||||||
|
"easy" => Ok(Difficulty::EASY),
|
||||||
|
"normal" => Ok(Difficulty::NORMAL),
|
||||||
|
"hard" => Ok(Difficulty::HARD),
|
||||||
|
_ => Err(Err::InvalidDifficulty(name.to_string())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn by_id(id: u8) -> Difficulty {
|
||||||
|
match id % 4 {
|
||||||
|
0 => Difficulty::PEACEFUL,
|
||||||
|
1 => Difficulty::EASY,
|
||||||
|
2 => Difficulty::NORMAL,
|
||||||
|
3 => Difficulty::HARD,
|
||||||
|
// this shouldn't be possible because of the modulo, so panicking is fine
|
||||||
|
_ => panic!("Unknown difficulty id: {}", id),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn id(&self) -> u8 {
|
||||||
|
match self {
|
||||||
|
Difficulty::PEACEFUL => 0,
|
||||||
|
Difficulty::EASY => 1,
|
||||||
|
Difficulty::NORMAL => 2,
|
||||||
|
Difficulty::HARD => 3,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_difficulty_from_name() {
|
||||||
|
assert_eq!(
|
||||||
|
Difficulty::PEACEFUL,
|
||||||
|
Difficulty::from_name("peaceful").unwrap()
|
||||||
|
);
|
||||||
|
assert_eq!(Difficulty::EASY, Difficulty::from_name("easy").unwrap());
|
||||||
|
assert_eq!(Difficulty::NORMAL, Difficulty::from_name("normal").unwrap());
|
||||||
|
assert_eq!(Difficulty::HARD, Difficulty::from_name("hard").unwrap());
|
||||||
|
assert!(Difficulty::from_name("invalid").is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_difficulty_id() {
|
||||||
|
assert_eq!(0, Difficulty::PEACEFUL.id());
|
||||||
|
assert_eq!(1, Difficulty::EASY.id());
|
||||||
|
assert_eq!(2, Difficulty::NORMAL.id());
|
||||||
|
assert_eq!(3, Difficulty::HARD.id());
|
||||||
|
assert_eq!(4, Difficulty::PEACEFUL.id());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_difficulty_name() {
|
||||||
|
assert_eq!("peaceful", Difficulty::PEACEFUL.name());
|
||||||
|
assert_eq!("easy", Difficulty::EASY.name());
|
||||||
|
assert_eq!("normal", Difficulty::NORMAL.name());
|
||||||
|
assert_eq!("hard", Difficulty::HARD.name());
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,14 +1,6 @@
|
||||||
//! Random miscellaneous things like UUIDs that don't deserve their own crate.
|
//! Random miscellaneous things like UUIDs that don't deserve their own crate.
|
||||||
|
|
||||||
|
pub mod difficulty;
|
||||||
pub mod game_type;
|
pub mod game_type;
|
||||||
pub mod resource_location;
|
pub mod resource_location;
|
||||||
pub mod serializable_uuid;
|
pub mod serializable_uuid;
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
#[test]
|
|
||||||
fn it_works() {
|
|
||||||
let result = 2 + 2;
|
|
||||||
assert_eq!(result, 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use azalea_core::{game_type::GameType, resource_location::ResourceLocation};
|
use azalea_core::{
|
||||||
|
difficulty::Difficulty, game_type::GameType, resource_location::ResourceLocation,
|
||||||
|
};
|
||||||
|
use num_traits::FromPrimitive;
|
||||||
use tokio::io::{AsyncRead, AsyncReadExt};
|
use tokio::io::{AsyncRead, AsyncReadExt};
|
||||||
|
|
||||||
use super::MAX_STRING_LENGTH;
|
use super::MAX_STRING_LENGTH;
|
||||||
|
@ -338,6 +341,28 @@ impl McBufReadable for bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// u8
|
||||||
|
#[async_trait]
|
||||||
|
impl McBufReadable for u8 {
|
||||||
|
async fn read_into<R>(buf: &mut R) -> Result<Self, String>
|
||||||
|
where
|
||||||
|
R: AsyncRead + std::marker::Unpin + std::marker::Send,
|
||||||
|
{
|
||||||
|
buf.read_byte().await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// i8
|
||||||
|
#[async_trait]
|
||||||
|
impl McBufReadable for i8 {
|
||||||
|
async fn read_into<R>(buf: &mut R) -> Result<Self, String>
|
||||||
|
where
|
||||||
|
R: AsyncRead + std::marker::Unpin + std::marker::Send,
|
||||||
|
{
|
||||||
|
buf.read_byte().await.map(|i| i as i8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// GameType
|
// GameType
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl McBufReadable for GameType {
|
impl McBufReadable for GameType {
|
||||||
|
@ -386,3 +411,14 @@ impl McBufReadable for azalea_nbt::Tag {
|
||||||
buf.read_nbt().await
|
buf.read_nbt().await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Difficulty
|
||||||
|
#[async_trait]
|
||||||
|
impl McBufReadable for Difficulty {
|
||||||
|
async fn read_into<R>(buf: &mut R) -> Result<Self, String>
|
||||||
|
where
|
||||||
|
R: AsyncRead + std::marker::Unpin + std::marker::Send,
|
||||||
|
{
|
||||||
|
Ok(Difficulty::by_id(u8::read_into(buf).await?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use azalea_core::{game_type::GameType, resource_location::ResourceLocation};
|
use azalea_core::{
|
||||||
|
difficulty::Difficulty, game_type::GameType, resource_location::ResourceLocation,
|
||||||
|
};
|
||||||
use byteorder::{BigEndian, WriteBytesExt};
|
use byteorder::{BigEndian, WriteBytesExt};
|
||||||
|
use num_traits::FromPrimitive;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
use super::MAX_STRING_LENGTH;
|
use super::MAX_STRING_LENGTH;
|
||||||
|
@ -255,6 +258,13 @@ impl McBufWritable for bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// i8
|
||||||
|
impl McBufWritable for i8 {
|
||||||
|
fn write_into(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
||||||
|
buf.write_byte(*self as u8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// GameType
|
// GameType
|
||||||
impl McBufWritable for GameType {
|
impl McBufWritable for GameType {
|
||||||
fn write_into(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
fn write_into(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
||||||
|
@ -284,3 +294,10 @@ impl McBufWritable for azalea_nbt::Tag {
|
||||||
buf.write_nbt(self)
|
buf.write_nbt(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Difficulty
|
||||||
|
impl McBufWritable for Difficulty {
|
||||||
|
fn write_into(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
||||||
|
u8::write_into(&self.id(), buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
use azalea_core::difficulty::Difficulty;
|
||||||
|
use packet_macros::GamePacket;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, GamePacket)]
|
||||||
|
pub struct ClientboundChangeDifficultyPacket {
|
||||||
|
pub difficulty: Difficulty,
|
||||||
|
pub locked: bool,
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
pub mod clientbound_change_difficulty_packet;
|
||||||
pub mod clientbound_custom_payload_packet;
|
pub mod clientbound_custom_payload_packet;
|
||||||
pub mod clientbound_login_packet;
|
pub mod clientbound_login_packet;
|
||||||
pub mod clientbound_update_view_distance_packet;
|
pub mod clientbound_update_view_distance_packet;
|
||||||
|
@ -18,12 +19,16 @@ where
|
||||||
ClientboundCustomPayloadPacket(
|
ClientboundCustomPayloadPacket(
|
||||||
clientbound_custom_payload_packet::ClientboundCustomPayloadPacket,
|
clientbound_custom_payload_packet::ClientboundCustomPayloadPacket,
|
||||||
),
|
),
|
||||||
|
ClientboundChangeDifficultyPacket(
|
||||||
|
clientbound_change_difficulty_packet::ClientboundChangeDifficultyPacket,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl ProtocolPacket for GamePacket {
|
impl ProtocolPacket for GamePacket {
|
||||||
fn id(&self) -> u32 {
|
fn id(&self) -> u32 {
|
||||||
match self {
|
match self {
|
||||||
|
GamePacket::ClientboundChangeDifficultyPacket(_packet) => 0x0e,
|
||||||
GamePacket::ClientboundCustomPayloadPacket(_packet) => 0x18,
|
GamePacket::ClientboundCustomPayloadPacket(_packet) => 0x18,
|
||||||
GamePacket::ClientboundLoginPacket(_packet) => 0x26,
|
GamePacket::ClientboundLoginPacket(_packet) => 0x26,
|
||||||
GamePacket::ClientboundUpdateViewDistancePacket(_packet) => 0x4a,
|
GamePacket::ClientboundUpdateViewDistancePacket(_packet) => 0x4a,
|
||||||
|
@ -31,7 +36,12 @@ impl ProtocolPacket for GamePacket {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
fn write(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
||||||
Ok(())
|
match self {
|
||||||
|
GamePacket::ClientboundChangeDifficultyPacket(packet) => packet.write(buf),
|
||||||
|
GamePacket::ClientboundCustomPayloadPacket(packet) => packet.write(buf),
|
||||||
|
GamePacket::ClientboundLoginPacket(packet) => packet.write(buf),
|
||||||
|
GamePacket::ClientboundUpdateViewDistancePacket(packet) => packet.write(buf),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read a packet by its id, ConnectionProtocol, and flow
|
/// Read a packet by its id, ConnectionProtocol, and flow
|
||||||
|
@ -45,6 +55,9 @@ impl ProtocolPacket for GamePacket {
|
||||||
{
|
{
|
||||||
Ok(match flow {
|
Ok(match flow {
|
||||||
PacketFlow::ServerToClient => match id {
|
PacketFlow::ServerToClient => match id {
|
||||||
|
0x0e => clientbound_change_difficulty_packet::ClientboundChangeDifficultyPacket
|
||||||
|
::read(buf)
|
||||||
|
.await?,
|
||||||
0x18 => clientbound_custom_payload_packet::ClientboundCustomPayloadPacket::read(buf).await?,
|
0x18 => clientbound_custom_payload_packet::ClientboundCustomPayloadPacket::read(buf).await?,
|
||||||
0x26 => clientbound_login_packet::ClientboundLoginPacket::read(buf).await?,
|
0x26 => clientbound_login_packet::ClientboundLoginPacket::read(buf).await?,
|
||||||
0x4a => clientbound_update_view_distance_packet::ClientboundUpdateViewDistancePacket
|
0x4a => clientbound_update_view_distance_packet::ClientboundUpdateViewDistancePacket
|
||||||
|
|
Loading…
Add table
Reference in a new issue