mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 14:26:04 +00:00
203 lines
6 KiB
Rust
Executable file
203 lines
6 KiB
Rust
Executable file
use azalea_buf::McBuf;
|
|
use azalea_chat::FormattedText;
|
|
use azalea_core::resource_location::ResourceLocation;
|
|
use azalea_inventory::ItemSlot;
|
|
use azalea_protocol_macros::ClientboundGamePacket;
|
|
use std::collections::HashMap;
|
|
use std::io::Cursor;
|
|
|
|
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
|
|
pub struct ClientboundUpdateAdvancementsPacket {
|
|
pub reset: bool,
|
|
pub added: Vec<AdvancementHolder>,
|
|
pub removed: Vec<ResourceLocation>,
|
|
pub progress: HashMap<ResourceLocation, AdvancementProgress>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, McBuf)]
|
|
pub struct Advancement {
|
|
pub parent_id: Option<ResourceLocation>,
|
|
pub display: Option<DisplayInfo>,
|
|
pub requirements: Vec<Vec<String>>,
|
|
pub sends_telemetry_event: bool,
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct DisplayInfo {
|
|
pub title: FormattedText,
|
|
pub description: FormattedText,
|
|
pub icon: ItemSlot,
|
|
pub frame: FrameType,
|
|
pub show_toast: bool,
|
|
pub hidden: bool,
|
|
pub background: Option<ResourceLocation>,
|
|
pub x: f32,
|
|
pub y: f32,
|
|
}
|
|
|
|
impl azalea_buf::McBufWritable for DisplayInfo {
|
|
fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
|
|
self.title.write_into(buf)?;
|
|
self.description.write_into(buf)?;
|
|
self.icon.write_into(buf)?;
|
|
self.frame.write_into(buf)?;
|
|
|
|
let mut data: u32 = 0;
|
|
if self.background.is_some() {
|
|
data |= 0b001;
|
|
}
|
|
if self.show_toast {
|
|
data |= 0b010;
|
|
}
|
|
if self.hidden {
|
|
data |= 0b100;
|
|
}
|
|
data.write_into(buf)?;
|
|
|
|
if let Some(background) = &self.background {
|
|
background.write_into(buf)?;
|
|
}
|
|
self.x.write_into(buf)?;
|
|
self.y.write_into(buf)?;
|
|
Ok(())
|
|
}
|
|
}
|
|
impl azalea_buf::McBufReadable for DisplayInfo {
|
|
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> {
|
|
let title = azalea_buf::McBufReadable::read_from(buf)?;
|
|
let description = azalea_buf::McBufReadable::read_from(buf)?;
|
|
let icon = azalea_buf::McBufReadable::read_from(buf)?;
|
|
let frame = azalea_buf::McBufReadable::read_from(buf)?;
|
|
|
|
let data = u32::read_from(buf)?;
|
|
let has_background = (data & 0b1) != 0;
|
|
let show_toast = (data & 0b10) != 0;
|
|
let hidden = (data & 0b100) != 0;
|
|
|
|
let background = if has_background {
|
|
Some(ResourceLocation::read_from(buf)?)
|
|
} else {
|
|
None
|
|
};
|
|
let x = azalea_buf::McBufReadable::read_from(buf)?;
|
|
let y = azalea_buf::McBufReadable::read_from(buf)?;
|
|
Ok(DisplayInfo {
|
|
title,
|
|
description,
|
|
icon,
|
|
frame,
|
|
show_toast,
|
|
hidden,
|
|
background,
|
|
x,
|
|
y,
|
|
})
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, Copy, McBuf)]
|
|
pub enum FrameType {
|
|
Task = 0,
|
|
Challenge = 1,
|
|
Goal = 2,
|
|
}
|
|
|
|
pub type AdvancementProgress = HashMap<String, CriterionProgress>;
|
|
|
|
#[derive(Clone, Debug, McBuf)]
|
|
pub struct CriterionProgress {
|
|
pub date: Option<u64>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, McBuf)]
|
|
pub struct AdvancementHolder {
|
|
pub id: ResourceLocation,
|
|
pub value: Advancement,
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use azalea_buf::{McBufReadable, McBufWritable};
|
|
|
|
#[test]
|
|
fn test() {
|
|
let packet = ClientboundUpdateAdvancementsPacket {
|
|
reset: true,
|
|
added: [AdvancementHolder {
|
|
id: ResourceLocation::new("minecraft:test"),
|
|
value: Advancement {
|
|
parent_id: None,
|
|
display: Some(DisplayInfo {
|
|
title: FormattedText::from("title".to_string()),
|
|
description: FormattedText::from("description".to_string()),
|
|
icon: ItemSlot::Empty,
|
|
frame: FrameType::Task,
|
|
show_toast: true,
|
|
hidden: false,
|
|
background: None,
|
|
x: 0.0,
|
|
y: 0.0,
|
|
}),
|
|
requirements: Vec::new(),
|
|
sends_telemetry_event: false,
|
|
},
|
|
}]
|
|
.into_iter()
|
|
.collect(),
|
|
removed: vec![ResourceLocation::new("minecraft:test2")],
|
|
progress: [(
|
|
ResourceLocation::new("minecraft:test3"),
|
|
[(
|
|
"minecraft:test4".to_string(),
|
|
CriterionProgress {
|
|
date: Some(123456789),
|
|
},
|
|
)]
|
|
.into_iter()
|
|
.collect(),
|
|
)]
|
|
.into_iter()
|
|
.collect(),
|
|
};
|
|
|
|
let mut data = Vec::new();
|
|
packet.write_into(&mut data).unwrap();
|
|
let mut buf: Cursor<&[u8]> = Cursor::new(&data);
|
|
|
|
let read_packet = ClientboundUpdateAdvancementsPacket::read_from(&mut buf).unwrap();
|
|
assert_eq!(packet.reset, read_packet.reset);
|
|
assert_eq!(packet.removed, read_packet.removed);
|
|
|
|
let advancement = packet
|
|
.added
|
|
.into_iter()
|
|
.find_map(|a| {
|
|
if a.id == ResourceLocation::new("minecraft:test") {
|
|
Some(a.value)
|
|
} else {
|
|
None
|
|
}
|
|
})
|
|
.unwrap()
|
|
.clone();
|
|
let read_advancement = read_packet
|
|
.added
|
|
.into_iter()
|
|
.find_map(|a| {
|
|
if a.id == ResourceLocation::new("minecraft:test") {
|
|
Some(a.value)
|
|
} else {
|
|
None
|
|
}
|
|
})
|
|
.unwrap()
|
|
.clone();
|
|
assert_eq!(advancement.parent_id, read_advancement.parent_id);
|
|
|
|
let display = advancement.display.unwrap();
|
|
let read_display = read_advancement.display.unwrap();
|
|
assert_eq!(display.title, read_display.title);
|
|
assert_eq!(display.description, read_display.description);
|
|
}
|
|
}
|