mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 06:16:04 +00:00
rename Component to FormattedText
also start making the metadata use bevy_ecs but bevy_ecs doesn't let you query on Bundles so it's annoying
This commit is contained in:
parent
129e2adf0a
commit
52772afe85
42 changed files with 11094 additions and 10584 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -295,6 +295,7 @@ dependencies = [
|
|||
"azalea-buf",
|
||||
"azalea-chat",
|
||||
"azalea-nbt",
|
||||
"bevy_ecs",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::context::StringRange;
|
|||
#[cfg(feature = "azalea-buf")]
|
||||
use azalea_buf::McBufWritable;
|
||||
#[cfg(feature = "azalea-buf")]
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
#[cfg(feature = "azalea-buf")]
|
||||
use std::io::Write;
|
||||
pub use suggestions::*;
|
||||
|
@ -58,7 +58,7 @@ impl<M: Clone> Suggestion<M> {
|
|||
}
|
||||
|
||||
#[cfg(feature = "azalea-buf")]
|
||||
impl McBufWritable for Suggestion<Component> {
|
||||
impl McBufWritable for Suggestion<FormattedText> {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
self.text.write_into(buf)?;
|
||||
self.tooltip.write_into(buf)?;
|
||||
|
|
|
@ -5,7 +5,7 @@ use azalea_buf::{
|
|||
BufReadError, McBuf, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable,
|
||||
};
|
||||
#[cfg(feature = "azalea-buf")]
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
#[cfg(feature = "azalea-buf")]
|
||||
use std::io::{Cursor, Write};
|
||||
use std::{collections::HashSet, hash::Hash};
|
||||
|
@ -68,12 +68,12 @@ impl<M> Default for Suggestions<M> {
|
|||
}
|
||||
|
||||
#[cfg(feature = "azalea-buf")]
|
||||
impl McBufReadable for Suggestions<Component> {
|
||||
impl McBufReadable for Suggestions<FormattedText> {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
#[derive(McBuf)]
|
||||
struct StandaloneSuggestion {
|
||||
pub text: String,
|
||||
pub tooltip: Option<Component>,
|
||||
pub tooltip: Option<FormattedText>,
|
||||
}
|
||||
|
||||
let start = u32::var_read_from(buf)? as usize;
|
||||
|
@ -97,7 +97,7 @@ impl McBufReadable for Suggestions<Component> {
|
|||
}
|
||||
|
||||
#[cfg(feature = "azalea-buf")]
|
||||
impl McBufWritable for Suggestions<Component> {
|
||||
impl McBufWritable for Suggestions<FormattedText> {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
(self.range.start() as u32).var_write_into(buf)?;
|
||||
(self.range.length() as u32).var_write_into(buf)?;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use crate::{style::Style, Component};
|
||||
use crate::{style::Style, FormattedText};
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize)]
|
||||
pub struct BaseComponent {
|
||||
// implements mutablecomponent
|
||||
#[serde(skip_serializing_if = "Vec::is_empty")]
|
||||
pub siblings: Vec<Component>,
|
||||
pub siblings: Vec<FormattedText>,
|
||||
#[serde(flatten)]
|
||||
pub style: Style,
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ use std::{
|
|||
/// A chat component, basically anything you can see in chat.
|
||||
#[derive(Clone, Debug, PartialEq, Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum Component {
|
||||
pub enum FormattedText {
|
||||
Text(TextComponent),
|
||||
Translatable(TranslatableComponent),
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ pub static DEFAULT_STYLE: Lazy<Style> = Lazy::new(|| Style {
|
|||
});
|
||||
|
||||
/// A chat component
|
||||
impl Component {
|
||||
impl FormattedText {
|
||||
pub fn get_base_mut(&mut self) -> &mut BaseComponent {
|
||||
match self {
|
||||
Self::Text(c) => &mut c.base,
|
||||
|
@ -43,14 +43,16 @@ impl Component {
|
|||
}
|
||||
|
||||
/// Add a component as a sibling of this one
|
||||
fn append(&mut self, sibling: Component) {
|
||||
fn append(&mut self, sibling: FormattedText) {
|
||||
self.get_base_mut().siblings.push(sibling);
|
||||
}
|
||||
|
||||
/// Get the "separator" component from the json
|
||||
fn parse_separator(json: &serde_json::Value) -> Result<Option<Component>, serde_json::Error> {
|
||||
fn parse_separator(
|
||||
json: &serde_json::Value,
|
||||
) -> Result<Option<FormattedText>, serde_json::Error> {
|
||||
if json.get("separator").is_some() {
|
||||
return Ok(Some(Component::deserialize(
|
||||
return Ok(Some(FormattedText::deserialize(
|
||||
json.get("separator").unwrap(),
|
||||
)?));
|
||||
}
|
||||
|
@ -61,16 +63,17 @@ impl Component {
|
|||
/// [ANSI string](https://en.wikipedia.org/wiki/ANSI_escape_code), so you
|
||||
/// can print it to your terminal and get styling.
|
||||
///
|
||||
/// This is technically a shortcut for [`Component::to_ansi_custom_style`]
|
||||
/// with a default [`Style`] colored white.
|
||||
/// This is technically a shortcut for
|
||||
/// [`FormattedText::to_ansi_custom_style`] with a default [`Style`]
|
||||
/// colored white.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use azalea_chat::Component;
|
||||
/// use azalea_chat::FormattedText;
|
||||
/// use serde::de::Deserialize;
|
||||
///
|
||||
/// let component = Component::deserialize(&serde_json::json!({
|
||||
/// let component = FormattedText::deserialize(&serde_json::json!({
|
||||
/// "text": "Hello, world!",
|
||||
/// "color": "red",
|
||||
/// })).unwrap();
|
||||
|
@ -85,7 +88,7 @@ impl Component {
|
|||
/// Convert this component into an
|
||||
/// [ANSI string](https://en.wikipedia.org/wiki/ANSI_escape_code).
|
||||
///
|
||||
/// This is the same as [`Component::to_ansi`], but you can specify a
|
||||
/// This is the same as [`FormattedText::to_ansi`], but you can specify a
|
||||
/// default [`Style`] to use.
|
||||
pub fn to_ansi_custom_style(&self, default_style: &Style) -> String {
|
||||
// this contains the final string will all the ansi escape codes
|
||||
|
@ -116,12 +119,12 @@ impl Component {
|
|||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for Component {
|
||||
impl IntoIterator for FormattedText {
|
||||
/// Recursively call the function for every component in this component
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
let base = self.get_base();
|
||||
let siblings = base.siblings.clone();
|
||||
let mut v: Vec<Component> = Vec::with_capacity(siblings.len() + 1);
|
||||
let mut v: Vec<FormattedText> = Vec::with_capacity(siblings.len() + 1);
|
||||
v.push(self);
|
||||
for sibling in siblings {
|
||||
v.extend(sibling.into_iter());
|
||||
|
@ -130,11 +133,11 @@ impl IntoIterator for Component {
|
|||
v.into_iter()
|
||||
}
|
||||
|
||||
type Item = Component;
|
||||
type Item = FormattedText;
|
||||
type IntoIter = std::vec::IntoIter<Self::Item>;
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Component {
|
||||
impl<'de> Deserialize<'de> for FormattedText {
|
||||
fn deserialize<D>(de: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
|
@ -142,11 +145,11 @@ impl<'de> Deserialize<'de> for Component {
|
|||
let json: serde_json::Value = serde::Deserialize::deserialize(de)?;
|
||||
|
||||
// we create a component that we might add siblings to
|
||||
let mut component: Component;
|
||||
let mut component: FormattedText;
|
||||
|
||||
// if it's primitive, make it a text component
|
||||
if !json.is_array() && !json.is_object() {
|
||||
return Ok(Component::Text(TextComponent::new(
|
||||
return Ok(FormattedText::Text(TextComponent::new(
|
||||
json.as_str().unwrap_or("").to_string(),
|
||||
)));
|
||||
}
|
||||
|
@ -154,7 +157,7 @@ impl<'de> Deserialize<'de> for Component {
|
|||
else if json.is_object() {
|
||||
if let Some(text) = json.get("text") {
|
||||
let text = text.as_str().unwrap_or("").to_string();
|
||||
component = Component::Text(TextComponent::new(text));
|
||||
component = FormattedText::Text(TextComponent::new(text));
|
||||
} else if let Some(translate) = json.get("translate") {
|
||||
let translate = translate
|
||||
.as_str()
|
||||
|
@ -169,8 +172,8 @@ impl<'de> Deserialize<'de> for Component {
|
|||
// if it's a string component with no styling and no siblings, just add a
|
||||
// string to with_array otherwise add the component
|
||||
// to the array
|
||||
let c = Component::deserialize(item).map_err(de::Error::custom)?;
|
||||
if let Component::Text(text_component) = c {
|
||||
let c = FormattedText::deserialize(item).map_err(de::Error::custom)?;
|
||||
if let FormattedText::Text(text_component) = c {
|
||||
if text_component.base.siblings.is_empty()
|
||||
&& text_component.base.style.is_empty()
|
||||
{
|
||||
|
@ -178,16 +181,19 @@ impl<'de> Deserialize<'de> for Component {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
with_array.push(StringOrComponent::Component(
|
||||
Component::deserialize(item).map_err(de::Error::custom)?,
|
||||
with_array.push(StringOrComponent::FormattedText(
|
||||
FormattedText::deserialize(item).map_err(de::Error::custom)?,
|
||||
));
|
||||
}
|
||||
component =
|
||||
Component::Translatable(TranslatableComponent::new(translate, with_array));
|
||||
component = FormattedText::Translatable(TranslatableComponent::new(
|
||||
translate, with_array,
|
||||
));
|
||||
} else {
|
||||
// if it doesn't have a "with", just have the with_array be empty
|
||||
component =
|
||||
Component::Translatable(TranslatableComponent::new(translate, Vec::new()));
|
||||
component = FormattedText::Translatable(TranslatableComponent::new(
|
||||
translate,
|
||||
Vec::new(),
|
||||
));
|
||||
}
|
||||
} else if let Some(score) = json.get("score") {
|
||||
// object = GsonHelper.getAsJsonObject(jsonObject, "score");
|
||||
|
@ -213,10 +219,11 @@ impl<'de> Deserialize<'de> for Component {
|
|||
nbt
|
||||
} else {
|
||||
return Err(de::Error::custom(
|
||||
format!("Don't know how to turn {json} into a Component").as_str(),
|
||||
format!("Don't know how to turn {json} into a FormattedText").as_str(),
|
||||
));
|
||||
};
|
||||
let _separator = Component::parse_separator(&json).map_err(de::Error::custom)?;
|
||||
let _separator =
|
||||
FormattedText::parse_separator(&json).map_err(de::Error::custom)?;
|
||||
|
||||
let _interpret = match json.get("interpret") {
|
||||
Some(v) => v.as_bool().ok_or(Some(false)).unwrap(),
|
||||
|
@ -237,7 +244,7 @@ impl<'de> Deserialize<'de> for Component {
|
|||
}
|
||||
for extra_component in extra {
|
||||
let sibling =
|
||||
Component::deserialize(extra_component).map_err(de::Error::custom)?;
|
||||
FormattedText::deserialize(extra_component).map_err(de::Error::custom)?;
|
||||
component.append(sibling);
|
||||
}
|
||||
}
|
||||
|
@ -250,33 +257,35 @@ impl<'de> Deserialize<'de> for Component {
|
|||
// ok so it's not an object, if it's an array deserialize every item
|
||||
else if !json.is_array() {
|
||||
return Err(de::Error::custom(
|
||||
format!("Don't know how to turn {json} into a Component").as_str(),
|
||||
format!("Don't know how to turn {json} into a FormattedText").as_str(),
|
||||
));
|
||||
}
|
||||
let json_array = json.as_array().unwrap();
|
||||
// the first item in the array is the one that we're gonna return, the others
|
||||
// are siblings
|
||||
let mut component = Component::deserialize(&json_array[0]).map_err(de::Error::custom)?;
|
||||
let mut component =
|
||||
FormattedText::deserialize(&json_array[0]).map_err(de::Error::custom)?;
|
||||
for i in 1..json_array.len() {
|
||||
component.append(
|
||||
Component::deserialize(json_array.get(i).unwrap()).map_err(de::Error::custom)?,
|
||||
FormattedText::deserialize(json_array.get(i).unwrap())
|
||||
.map_err(de::Error::custom)?,
|
||||
);
|
||||
}
|
||||
Ok(component)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for Component {
|
||||
impl McBufReadable for FormattedText {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let string = String::read_from(buf)?;
|
||||
debug!("Component string: {}", string);
|
||||
debug!("FormattedText string: {}", string);
|
||||
let json: serde_json::Value = serde_json::from_str(string.as_str())?;
|
||||
let component = Component::deserialize(json)?;
|
||||
let component = FormattedText::deserialize(json)?;
|
||||
Ok(component)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for Component {
|
||||
impl McBufWritable for FormattedText {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
let json = serde_json::to_string(self).unwrap();
|
||||
json.write_into(buf)?;
|
||||
|
@ -284,31 +293,31 @@ impl McBufWritable for Component {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<String> for Component {
|
||||
impl From<String> for FormattedText {
|
||||
fn from(s: String) -> Self {
|
||||
Component::Text(TextComponent {
|
||||
FormattedText::Text(TextComponent {
|
||||
text: s,
|
||||
base: BaseComponent::default(),
|
||||
})
|
||||
}
|
||||
}
|
||||
impl From<&str> for Component {
|
||||
impl From<&str> for FormattedText {
|
||||
fn from(s: &str) -> Self {
|
||||
Self::from(s.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Component {
|
||||
impl Display for FormattedText {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Component::Text(c) => c.fmt(f),
|
||||
Component::Translatable(c) => c.fmt(f),
|
||||
FormattedText::Text(c) => c.fmt(f),
|
||||
FormattedText::Translatable(c) => c.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Component {
|
||||
impl Default for FormattedText {
|
||||
fn default() -> Self {
|
||||
Component::Text(TextComponent::default())
|
||||
FormattedText::Text(TextComponent::default())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,4 +7,4 @@ pub mod style;
|
|||
pub mod text_component;
|
||||
pub mod translatable_component;
|
||||
|
||||
pub use component::Component;
|
||||
pub use component::FormattedText;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{base_component::BaseComponent, style::ChatFormatting, Component};
|
||||
use crate::{base_component::BaseComponent, style::ChatFormatting, FormattedText};
|
||||
use serde::{ser::SerializeMap, Serialize, Serializer, __private::ser::FlatMapSerializer};
|
||||
use std::fmt::Display;
|
||||
|
||||
|
@ -26,7 +26,7 @@ impl Serialize for TextComponent {
|
|||
|
||||
const LEGACY_FORMATTING_CODE_SYMBOL: char = '§';
|
||||
|
||||
/// Convert a legacy color code string into a Component
|
||||
/// Convert a legacy color code string into a FormattedText
|
||||
/// Technically in Minecraft this is done when displaying the text, but AFAIK
|
||||
/// it's the same as just doing it in TextComponent
|
||||
pub fn legacy_color_code_to_text_component(legacy_color_code: &str) -> TextComponent {
|
||||
|
@ -98,18 +98,18 @@ impl TextComponent {
|
|||
}
|
||||
}
|
||||
|
||||
fn get(self) -> Component {
|
||||
Component::Text(self)
|
||||
fn get(self) -> FormattedText {
|
||||
FormattedText::Text(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for TextComponent {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
// this contains the final string will all the ansi escape codes
|
||||
for component in Component::Text(self.clone()).into_iter() {
|
||||
for component in FormattedText::Text(self.clone()).into_iter() {
|
||||
let component_text = match &component {
|
||||
Component::Text(c) => c.text.to_string(),
|
||||
Component::Translatable(c) => c.read()?.to_string(),
|
||||
FormattedText::Text(c) => c.text.to_string(),
|
||||
FormattedText::Translatable(c) => c.read()?.to_string(),
|
||||
};
|
||||
|
||||
f.write_str(&component_text)?;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::fmt::{self, Display, Formatter};
|
||||
|
||||
use crate::{
|
||||
base_component::BaseComponent, style::Style, text_component::TextComponent, Component,
|
||||
base_component::BaseComponent, style::Style, text_component::TextComponent, FormattedText,
|
||||
};
|
||||
use serde::{ser::SerializeMap, Serialize, Serializer, __private::ser::FlatMapSerializer};
|
||||
|
||||
|
@ -9,7 +9,7 @@ use serde::{ser::SerializeMap, Serialize, Serializer, __private::ser::FlatMapSer
|
|||
#[serde(untagged)]
|
||||
pub enum StringOrComponent {
|
||||
String(String),
|
||||
Component(Component),
|
||||
FormattedText(FormattedText),
|
||||
}
|
||||
|
||||
/// A message whose content depends on the client's language.
|
||||
|
@ -42,7 +42,7 @@ impl TranslatableComponent {
|
|||
}
|
||||
}
|
||||
|
||||
/// Convert the key and args to a Component.
|
||||
/// Convert the key and args to a FormattedText.
|
||||
pub fn read(&self) -> Result<TextComponent, fmt::Error> {
|
||||
let template = azalea_language::get(&self.key).unwrap_or(&self.key);
|
||||
// decode the % things
|
||||
|
@ -122,7 +122,7 @@ impl TranslatableComponent {
|
|||
|
||||
Ok(TextComponent {
|
||||
base: BaseComponent {
|
||||
siblings: components.into_iter().map(Component::Text).collect(),
|
||||
siblings: components.into_iter().map(FormattedText::Text).collect(),
|
||||
style: Style::default(),
|
||||
},
|
||||
text: "".to_string(),
|
||||
|
@ -133,10 +133,10 @@ impl TranslatableComponent {
|
|||
impl Display for TranslatableComponent {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
// this contains the final string will all the ansi escape codes
|
||||
for component in Component::Translatable(self.clone()).into_iter() {
|
||||
for component in FormattedText::Translatable(self.clone()).into_iter() {
|
||||
let component_text = match &component {
|
||||
Component::Text(c) => c.text.to_string(),
|
||||
Component::Translatable(c) => c.read()?.to_string(),
|
||||
FormattedText::Text(c) => c.text.to_string(),
|
||||
FormattedText::Translatable(c) => c.read()?.to_string(),
|
||||
};
|
||||
|
||||
f.write_str(&component_text)?;
|
||||
|
@ -150,7 +150,7 @@ impl Display for StringOrComponent {
|
|||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
match self {
|
||||
StringOrComponent::String(s) => write!(f, "{s}"),
|
||||
StringOrComponent::Component(c) => write!(f, "{c}"),
|
||||
StringOrComponent::FormattedText(c) => write!(f, "{c}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ impl From<StringOrComponent> for TextComponent {
|
|||
fn from(soc: StringOrComponent) -> Self {
|
||||
match soc {
|
||||
StringOrComponent::String(s) => TextComponent::new(s),
|
||||
StringOrComponent::Component(c) => TextComponent::new(c.to_string()),
|
||||
StringOrComponent::FormattedText(c) => TextComponent::new(c.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use azalea_chat::{
|
||||
style::{Ansi, ChatFormatting, TextColor},
|
||||
Component,
|
||||
FormattedText,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use serde_json::Value;
|
||||
|
@ -15,7 +15,7 @@ fn basic_ansi_test() {
|
|||
}"#,
|
||||
)
|
||||
.unwrap();
|
||||
let component = Component::deserialize(&j).unwrap();
|
||||
let component = FormattedText::deserialize(&j).unwrap();
|
||||
assert_eq!(
|
||||
component.to_ansi(),
|
||||
"\u{1b}[1m\u{1b}[38;2;255;85;85mhello\u{1b}[m"
|
||||
|
@ -51,7 +51,7 @@ fn complex_ansi_test() {
|
|||
]"##,
|
||||
)
|
||||
.unwrap();
|
||||
let component = Component::deserialize(&j).unwrap();
|
||||
let component = FormattedText::deserialize(&j).unwrap();
|
||||
assert_eq!(
|
||||
component.to_ansi(),
|
||||
format!(
|
||||
|
@ -70,6 +70,6 @@ fn complex_ansi_test() {
|
|||
#[test]
|
||||
fn component_from_string() {
|
||||
let j: Value = serde_json::from_str("\"foo\"").unwrap();
|
||||
let component = Component::deserialize(&j).unwrap();
|
||||
let component = FormattedText::deserialize(&j).unwrap();
|
||||
assert_eq!(component.to_ansi(), "foo");
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Implementations of chat-related features.
|
||||
|
||||
use crate::Client;
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_protocol::packets::game::{
|
||||
clientbound_player_chat_packet::ClientboundPlayerChatPacket,
|
||||
clientbound_system_chat_packet::ClientboundSystemChatPacket,
|
||||
|
@ -29,7 +29,7 @@ macro_rules! regex {
|
|||
|
||||
impl ChatPacket {
|
||||
/// Get the message shown in chat for this packet.
|
||||
pub fn message(&self) -> Component {
|
||||
pub fn message(&self) -> FormattedText {
|
||||
match self {
|
||||
ChatPacket::System(p) => p.content.clone(),
|
||||
ChatPacket::Player(p) => p.message(),
|
||||
|
@ -83,7 +83,7 @@ impl ChatPacket {
|
|||
/// convenience function for testing.
|
||||
pub fn new(message: &str) -> Self {
|
||||
ChatPacket::System(Arc::new(ClientboundSystemChatPacket {
|
||||
content: Component::from(message),
|
||||
content: FormattedText::from(message),
|
||||
overlay: false,
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use azalea_auth::game_profile::GameProfile;
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_core::GameType;
|
||||
use azalea_world::PartialWorld;
|
||||
use uuid::Uuid;
|
||||
|
@ -13,5 +13,5 @@ pub struct PlayerInfo {
|
|||
pub gamemode: GameType,
|
||||
pub latency: i32,
|
||||
/// The player's display name in the tab list.
|
||||
pub display_name: Option<Component>,
|
||||
pub display_name: Option<FormattedText>,
|
||||
}
|
||||
|
|
|
@ -3,13 +3,17 @@ description = "Miscellaneous things in Azalea."
|
|||
edition = "2021"
|
||||
license = "MIT"
|
||||
name = "azalea-core"
|
||||
version = "0.5.0"
|
||||
repository = "https://github.com/mat-1/azalea/tree/main/azalea-core"
|
||||
version = "0.5.0"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
azalea-buf = {path = "../azalea-buf", version = "^0.5.0" }
|
||||
azalea-chat = {path = "../azalea-chat", version = "^0.5.0" }
|
||||
azalea-nbt = {path = "../azalea-nbt", version = "^0.5.0" }
|
||||
azalea-buf = {path = "../azalea-buf", version = "^0.5.0"}
|
||||
azalea-chat = {path = "../azalea-chat", version = "^0.5.0"}
|
||||
azalea-nbt = {path = "../azalea-nbt", version = "^0.5.0"}
|
||||
bevy_ecs = {version = "0.9.1", default-features = false, optional = true}
|
||||
uuid = "^1.1.2"
|
||||
|
||||
[features]
|
||||
bevy_ecs = ["dep:bevy_ecs"]
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::{BlockPos, Slot};
|
||||
use azalea_buf::McBuf;
|
||||
|
||||
#[cfg_attr(feature = "bevy_ecs", derive(bevy_ecs::component::Component))]
|
||||
#[derive(Debug, Clone, McBuf, Default)]
|
||||
pub struct Particle {
|
||||
#[var]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use azalea_buf::{
|
||||
BufReadError, McBuf, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable,
|
||||
};
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
use std::io::Cursor;
|
||||
use std::io::Write;
|
||||
|
@ -18,7 +18,7 @@ pub enum Operation {
|
|||
Add(AddOperation),
|
||||
Remove,
|
||||
UpdateProgress(f32),
|
||||
UpdateName(Component),
|
||||
UpdateName(FormattedText),
|
||||
UpdateStyle(Style),
|
||||
UpdateProperties(Properties),
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ impl McBufReadable for Operation {
|
|||
0 => Operation::Add(AddOperation::read_from(buf)?),
|
||||
1 => Operation::Remove,
|
||||
2 => Operation::UpdateProgress(f32::read_from(buf)?),
|
||||
3 => Operation::UpdateName(Component::read_from(buf)?),
|
||||
3 => Operation::UpdateName(FormattedText::read_from(buf)?),
|
||||
4 => Operation::UpdateStyle(Style::read_from(buf)?),
|
||||
5 => Operation::UpdateProperties(Properties::read_from(buf)?),
|
||||
_ => {
|
||||
|
@ -75,7 +75,7 @@ impl McBufWritable for Operation {
|
|||
|
||||
#[derive(Clone, Debug, McBuf)]
|
||||
pub struct AddOperation {
|
||||
name: Component,
|
||||
name: FormattedText,
|
||||
progress: f32,
|
||||
style: Style,
|
||||
properties: Properties,
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use azalea_buf::McBuf;
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
|
||||
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
|
||||
pub struct ClientboundChatPreviewPacket {
|
||||
pub query_id: i32,
|
||||
pub preview: Option<Component>,
|
||||
pub preview: Option<FormattedText>,
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use azalea_brigadier::suggestion::Suggestions;
|
||||
use azalea_buf::McBuf;
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
|
||||
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
|
||||
pub struct ClientboundCommandSuggestionsPacket {
|
||||
#[var]
|
||||
pub id: u32,
|
||||
pub suggestions: Suggestions<Component>,
|
||||
pub suggestions: Suggestions<FormattedText>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -24,7 +24,7 @@ mod tests {
|
|||
suggestions: vec![Suggestion {
|
||||
text: "foo".to_string(),
|
||||
range: StringRange::new(1, 4),
|
||||
tooltip: Some(Component::from("bar".to_string())),
|
||||
tooltip: Some(FormattedText::from("bar".to_string())),
|
||||
}],
|
||||
};
|
||||
let mut buf = Vec::new();
|
||||
|
|
|
@ -99,7 +99,7 @@ pub enum BrigadierParser {
|
|||
ItemStack,
|
||||
ItemPredicate,
|
||||
Color,
|
||||
Component,
|
||||
FormattedText,
|
||||
Message,
|
||||
NbtCompoundTag,
|
||||
NbtTag,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use azalea_buf::McBuf;
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
|
||||
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
|
||||
pub struct ClientboundDisconnectPacket {
|
||||
pub reason: Component,
|
||||
pub reason: FormattedText,
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use super::clientbound_player_chat_packet::ChatTypeBound;
|
||||
use azalea_buf::McBuf;
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
|
||||
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
|
||||
pub struct ClientboundDisguisedChatPacket {
|
||||
pub message: Component,
|
||||
pub message: FormattedText,
|
||||
pub chat_type: ChatTypeBound,
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use azalea_buf::{BufReadError, McBuf};
|
||||
use azalea_buf::{McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable};
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
use std::io::{Cursor, Write};
|
||||
|
||||
|
@ -76,7 +76,7 @@ pub struct MapDecoration {
|
|||
/// Minecraft does & 15 on this value, azalea-protocol doesn't. I don't
|
||||
/// think it matters.
|
||||
pub rot: i8,
|
||||
pub name: Option<Component>,
|
||||
pub name: Option<FormattedText>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use azalea_buf::McBuf;
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
|
||||
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
|
||||
|
@ -7,5 +7,5 @@ pub struct ClientboundOpenScreenPacket {
|
|||
#[var]
|
||||
pub container_id: u32,
|
||||
pub menu_type: azalea_registry::Menu,
|
||||
pub title: Component,
|
||||
pub title: FormattedText,
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use azalea_buf::{
|
|||
};
|
||||
use azalea_chat::{
|
||||
translatable_component::{StringOrComponent, TranslatableComponent},
|
||||
Component,
|
||||
FormattedText,
|
||||
};
|
||||
use azalea_core::BitSet;
|
||||
use azalea_crypto::MessageSignature;
|
||||
|
@ -18,7 +18,7 @@ pub struct ClientboundPlayerChatPacket {
|
|||
pub index: u32,
|
||||
pub signature: Option<MessageSignature>,
|
||||
pub body: PackedSignedMessageBody,
|
||||
pub unsigned_content: Option<Component>,
|
||||
pub unsigned_content: Option<FormattedText>,
|
||||
pub filter_mask: FilterMask,
|
||||
pub chat_type: ChatTypeBound,
|
||||
}
|
||||
|
@ -66,8 +66,8 @@ pub enum ChatType {
|
|||
#[derive(Clone, Debug, McBuf, PartialEq)]
|
||||
pub struct ChatTypeBound {
|
||||
pub chat_type: ChatType,
|
||||
pub name: Component,
|
||||
pub target_name: Option<Component>,
|
||||
pub name: FormattedText,
|
||||
pub target_name: Option<FormattedText>,
|
||||
}
|
||||
|
||||
// must be in Client
|
||||
|
@ -87,17 +87,17 @@ pub struct MessageSignatureCache {
|
|||
// {} }
|
||||
|
||||
impl ClientboundPlayerChatPacket {
|
||||
/// Returns the content of the message. If you want to get the Component
|
||||
/// Returns the content of the message. If you want to get the FormattedText
|
||||
/// for the whole message including the sender part, use
|
||||
/// [`ClientboundPlayerChatPacket::message`].
|
||||
pub fn content(&self) -> Component {
|
||||
pub fn content(&self) -> FormattedText {
|
||||
self.unsigned_content
|
||||
.clone()
|
||||
.unwrap_or_else(|| Component::from(self.body.content.clone()))
|
||||
.unwrap_or_else(|| FormattedText::from(self.body.content.clone()))
|
||||
}
|
||||
|
||||
/// Get the full message, including the sender part.
|
||||
pub fn message(&self) -> Component {
|
||||
pub fn message(&self) -> FormattedText {
|
||||
let sender = self.chat_type.name.clone();
|
||||
let content = self.content();
|
||||
let target = self.chat_type.target_name.clone();
|
||||
|
@ -105,16 +105,16 @@ impl ClientboundPlayerChatPacket {
|
|||
let translation_key = self.chat_type.chat_type.chat_translation_key();
|
||||
|
||||
let mut args = vec![
|
||||
StringOrComponent::Component(sender),
|
||||
StringOrComponent::Component(content),
|
||||
StringOrComponent::FormattedText(sender),
|
||||
StringOrComponent::FormattedText(content),
|
||||
];
|
||||
if let Some(target) = target {
|
||||
args.push(StringOrComponent::Component(target));
|
||||
args.push(StringOrComponent::FormattedText(target));
|
||||
}
|
||||
|
||||
let component = TranslatableComponent::new(translation_key.to_string(), args);
|
||||
|
||||
Component::Translatable(component)
|
||||
FormattedText::Translatable(component)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use azalea_buf::McBuf;
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
|
||||
/// Used to send a respawn screen.
|
||||
|
@ -8,5 +8,5 @@ pub struct ClientboundPlayerCombatKillPacket {
|
|||
#[var]
|
||||
pub player_id: u32,
|
||||
pub killer_id: u32,
|
||||
pub message: Component,
|
||||
pub message: FormattedText,
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use azalea_auth::game_profile::{GameProfile, ProfilePropertyValue};
|
|||
use azalea_buf::{
|
||||
BufReadError, McBuf, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable,
|
||||
};
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_core::{BitSet, GameType};
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
use std::{
|
||||
|
@ -25,7 +25,7 @@ pub struct PlayerInfoEntry {
|
|||
pub listed: bool,
|
||||
pub latency: i32,
|
||||
pub game_mode: GameType,
|
||||
pub display_name: Option<Component>,
|
||||
pub display_name: Option<FormattedText>,
|
||||
pub chat_session: Option<RemoteChatSessionData>,
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ pub struct UpdateLatencyAction {
|
|||
}
|
||||
#[derive(Clone, Debug, McBuf)]
|
||||
pub struct UpdateDisplayNameAction {
|
||||
pub display_name: Option<Component>,
|
||||
pub display_name: Option<FormattedText>,
|
||||
}
|
||||
|
||||
impl McBufReadable for ClientboundPlayerInfoUpdatePacket {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use azalea_buf::McBuf;
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
|
||||
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
|
||||
|
@ -7,5 +7,5 @@ pub struct ClientboundResourcePackPacket {
|
|||
pub url: String,
|
||||
pub hash: String,
|
||||
pub required: bool,
|
||||
pub prompt: Option<Component>,
|
||||
pub prompt: Option<FormattedText>,
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use azalea_buf::McBuf;
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
|
||||
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
|
||||
pub struct ClientboundServerDataPacket {
|
||||
pub motd: Option<Component>,
|
||||
pub motd: Option<FormattedText>,
|
||||
pub icon_base64: Option<String>,
|
||||
pub enforces_secure_chat: bool,
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use azalea_buf::McBuf;
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
|
||||
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
|
||||
pub struct ClientboundSetActionBarTextPacket {
|
||||
pub text: Component,
|
||||
pub text: FormattedText,
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use azalea_buf::{BufReadError, McBuf, McBufReadable, McBufWritable};
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
use std::io::{Cursor, Write};
|
||||
|
||||
|
@ -48,7 +48,7 @@ impl McBufWritable for Method {
|
|||
|
||||
#[derive(McBuf, Clone, Debug)]
|
||||
pub struct DisplayInfo {
|
||||
pub display_name: Component,
|
||||
pub display_name: FormattedText,
|
||||
pub render_type: RenderType,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use azalea_buf::{BufReadError, McBuf, McBufReadable, McBufWritable};
|
||||
use azalea_chat::{style::ChatFormatting, Component};
|
||||
use azalea_chat::{style::ChatFormatting, FormattedText};
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
use std::io::{Cursor, Write};
|
||||
|
||||
|
@ -61,13 +61,13 @@ impl McBufWritable for Method {
|
|||
|
||||
#[derive(McBuf, Clone, Debug)]
|
||||
pub struct Parameters {
|
||||
pub display_name: Component,
|
||||
pub display_name: FormattedText,
|
||||
pub options: u8,
|
||||
pub nametag_visibility: String,
|
||||
pub collision_rule: String,
|
||||
pub color: ChatFormatting,
|
||||
pub player_prefix: Component,
|
||||
pub player_suffix: Component,
|
||||
pub player_prefix: FormattedText,
|
||||
pub player_suffix: FormattedText,
|
||||
}
|
||||
|
||||
type PlayerList = Vec<String>;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use azalea_buf::McBuf;
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
|
||||
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
|
||||
pub struct ClientboundSetSubtitleTextPacket {
|
||||
pub text: Component,
|
||||
pub text: FormattedText,
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use azalea_buf::McBuf;
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
|
||||
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
|
||||
pub struct ClientboundSetTitleTextPacket {
|
||||
pub text: Component,
|
||||
pub text: FormattedText,
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use azalea_buf::McBuf;
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
|
||||
#[derive(Clone, Debug, McBuf, ClientboundGamePacket, PartialEq)]
|
||||
pub struct ClientboundSystemChatPacket {
|
||||
pub content: Component,
|
||||
pub content: FormattedText,
|
||||
pub overlay: bool,
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use azalea_buf::McBuf;
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
|
||||
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
|
||||
pub struct ClientboundTabListPacket {
|
||||
pub header: Component,
|
||||
pub footer: Component,
|
||||
pub header: FormattedText,
|
||||
pub footer: FormattedText,
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use azalea_buf::McBuf;
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_core::{ResourceLocation, Slot};
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
use std::collections::HashMap;
|
||||
|
@ -25,8 +25,8 @@ pub struct Advancement {
|
|||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DisplayInfo {
|
||||
pub title: Component,
|
||||
pub description: Component,
|
||||
pub title: FormattedText,
|
||||
pub description: FormattedText,
|
||||
pub icon: Slot,
|
||||
pub frame: FrameType,
|
||||
pub show_toast: bool,
|
||||
|
@ -132,9 +132,9 @@ pub struct CriterionProgress {
|
|||
// Advancement {
|
||||
// parent_id: None,
|
||||
// display: Some(DisplayInfo {
|
||||
// title: Component::from("title".to_string()),
|
||||
// title: FormattedText::from("title".to_string()),
|
||||
// description:
|
||||
// Component::from("description".to_string()), icon:
|
||||
// FormattedText::from("description".to_string()), icon:
|
||||
// Slot::Empty, frame: FrameType::Task,
|
||||
// show_toast: true,
|
||||
// hidden: false,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use azalea_buf::McBuf;
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_protocol_macros::ClientboundLoginPacket;
|
||||
|
||||
#[derive(Clone, Debug, McBuf, ClientboundLoginPacket)]
|
||||
pub struct ClientboundLoginDisconnectPacket {
|
||||
pub reason: Component,
|
||||
pub reason: FormattedText,
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use azalea_buf::{BufReadError, McBufReadable, McBufWritable};
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_protocol_macros::ClientboundStatusPacket;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{value::Serializer, Value};
|
||||
|
@ -28,7 +28,7 @@ pub struct Players {
|
|||
// the entire packet is just json, which is why it has deserialize
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, ClientboundStatusPacket)]
|
||||
pub struct ClientboundStatusResponsePacket {
|
||||
pub description: Component,
|
||||
pub description: FormattedText,
|
||||
#[serde(default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub favicon: Option<String>,
|
||||
|
|
|
@ -1205,7 +1205,7 @@ registry!(CommandArgumentKind, {
|
|||
ItemStack => "minecraft:item_stack",
|
||||
ItemPredicate => "minecraft:item_predicate",
|
||||
Color => "minecraft:color",
|
||||
Component => "minecraft:component",
|
||||
FormattedText => "minecraft:component",
|
||||
Message => "minecraft:message",
|
||||
NbtCompoundTag => "minecraft:nbt_compound_tag",
|
||||
NbtTag => "minecraft:nbt_tag",
|
||||
|
|
|
@ -9,13 +9,13 @@ version = "0.5.0"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
azalea-block = { path = "../azalea-block", default-features = false, version = "^0.5.0" }
|
||||
azalea-buf = { path = "../azalea-buf", version = "^0.5.0" }
|
||||
azalea-chat = { path = "../azalea-chat", version = "^0.5.0" }
|
||||
azalea-core = { path = "../azalea-core", version = "^0.5.0" }
|
||||
azalea-nbt = { path = "../azalea-nbt", version = "^0.5.0" }
|
||||
azalea-registry = { path = "../azalea-registry", version = "^0.5.0" }
|
||||
bevy_ecs = { version = "0.9.1", default-features = false }
|
||||
azalea-block = {path = "../azalea-block", default-features = false, version = "^0.5.0"}
|
||||
azalea-buf = {path = "../azalea-buf", version = "^0.5.0"}
|
||||
azalea-chat = {path = "../azalea-chat", version = "^0.5.0"}
|
||||
azalea-core = {path = "../azalea-core", version = "^0.5.0", features = ["bevy_ecs"]}
|
||||
azalea-nbt = {path = "../azalea-nbt", version = "^0.5.0"}
|
||||
azalea-registry = {path = "../azalea-registry", version = "^0.5.0"}
|
||||
bevy_ecs = {version = "0.9.1", default-features = false}
|
||||
enum-as-inner = "0.5.1"
|
||||
log = "0.4.17"
|
||||
nohash-hasher = "0.2.0"
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use azalea_block::BlockState;
|
||||
use azalea_buf::{BufReadError, McBufVarReadable, McBufVarWritable};
|
||||
use azalea_buf::{McBuf, McBufReadable, McBufWritable};
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_core::{BlockPos, Direction, GlobalPos, Particle, Slot};
|
||||
use bevy_ecs::component::Component;
|
||||
use enum_as_inner::EnumAsInner;
|
||||
use nohash_hasher::IntSet;
|
||||
use std::io::{Cursor, Write};
|
||||
|
@ -52,8 +53,8 @@ pub enum EntityDataValue {
|
|||
Long(i64),
|
||||
Float(f32),
|
||||
String(String),
|
||||
Component(Component),
|
||||
OptionalComponent(Option<Component>),
|
||||
FormattedText(FormattedText),
|
||||
OptionalComponent(Option<FormattedText>),
|
||||
ItemStack(Slot),
|
||||
Boolean(bool),
|
||||
Rotations(Rotations),
|
||||
|
@ -105,7 +106,7 @@ pub struct Rotations {
|
|||
pub z: f32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Copy, McBuf, Default)]
|
||||
#[derive(Clone, Debug, Copy, McBuf, Default, Component)]
|
||||
pub enum Pose {
|
||||
#[default]
|
||||
Standing = 0,
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -15,8 +15,8 @@ def generate_entity_metadata(burger_entity_data: dict, mappings: Mappings):
|
|||
{'name': 'Long', 'type': 'i64'},
|
||||
{'name': 'Float', 'type': 'f32'},
|
||||
{'name': 'String', 'type': 'String'},
|
||||
{'name': 'Component', 'type': 'Component'},
|
||||
{'name': 'OptionalComponent', 'type': 'Option<Component>'},
|
||||
{'name': 'Component', 'type': 'FormattedText'},
|
||||
{'name': 'OptionalComponent', 'type': 'Option<FormattedText>'},
|
||||
{'name': 'ItemStack', 'type': 'Slot'},
|
||||
{'name': 'Boolean', 'type': 'bool'},
|
||||
{'name': 'Rotations', 'type': 'Rotations'},
|
||||
|
@ -45,9 +45,9 @@ use super::{
|
|||
EntityDataValue, EntityMetadataItems, OptionalUnsignedInt, Pose, Rotations, VillagerData,
|
||||
};
|
||||
use azalea_block::BlockState;
|
||||
use azalea_chat::Component;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_core::{BlockPos, Direction, Particle, Slot};
|
||||
use hecs::{Query, EntityBuilder, BuiltEntity};
|
||||
use bevy_ecs::{bundle::Bundle, component::Component};
|
||||
use thiserror::Error;
|
||||
use uuid::Uuid;
|
||||
|
||||
|
@ -160,33 +160,124 @@ impl From<EntityDataValue> for UpdateMetadataError {
|
|||
metadata_type_data = metadata_types[type_id]
|
||||
rust_type = metadata_type_data['type']
|
||||
|
||||
code.append(f'#[derive(Component)]')
|
||||
code.append(f'pub struct {struct_name}(pub {rust_type});')
|
||||
else:
|
||||
# if it's a bitfield just make a struct for each bit
|
||||
for mask, name in name_or_bitfield.items():
|
||||
name = maybe_rename_field(name, index)
|
||||
struct_name = upper_first_letter(to_camel_case(name))
|
||||
code.append(f'#[derive(Component)]')
|
||||
code.append(f'pub struct {struct_name}(pub bool);')
|
||||
|
||||
# add the entity struct and Query struct
|
||||
is_actually_entity = not entity_id.startswith('~')
|
||||
if is_actually_entity:
|
||||
struct_name: str = upper_first_letter(to_camel_case(entity_id))
|
||||
code.append(f'#[derive(Component)]')
|
||||
code.append(f'pub struct {struct_name};')
|
||||
|
||||
# impl Allay {
|
||||
# pub fn default(builder: &mut EntityBuilder) {
|
||||
# builder
|
||||
# .add(OnFire(false))
|
||||
# .add(ShiftKeyDown(false))
|
||||
# .add(Sprinting(false))
|
||||
# .add(Swimming(false));
|
||||
# #[derive(Bundle)]
|
||||
# struct AllayBundle {
|
||||
# health: Health,
|
||||
# ...
|
||||
# dancing: Dancing,
|
||||
# can_duplicate: CanDuplicate,
|
||||
# }
|
||||
bundle_struct_name = f'{struct_name}Bundle'
|
||||
code.append(f'')
|
||||
code.append(f'#[derive(Bundle)]')
|
||||
code.append(f'struct {bundle_struct_name} {{')
|
||||
for index, name_or_bitfield in enumerate(all_field_names_or_bitfields):
|
||||
if isinstance(name_or_bitfield, str):
|
||||
name_or_bitfield = maybe_rename_field(
|
||||
name_or_bitfield, index)
|
||||
struct_name = upper_first_letter(
|
||||
to_camel_case(name_or_bitfield))
|
||||
code.append(
|
||||
f' {name_or_bitfield}: {struct_name},')
|
||||
else:
|
||||
for mask, name in name_or_bitfield.items():
|
||||
name = maybe_rename_field(name, index)
|
||||
|
||||
struct_name = upper_first_letter(to_camel_case(name))
|
||||
code.append(f' {name}: {struct_name},')
|
||||
code.append('}')
|
||||
|
||||
# impl AllayBundle {
|
||||
# pub fn update_metadata(
|
||||
# &mut self,
|
||||
# ecs: bevy_ecs::world::World,
|
||||
# entity: bevy_ecs::world::EntityMut,
|
||||
# data: EntityMetadataItems,
|
||||
# ) -> Result<(), UpdateMetadataError> {
|
||||
# for d in data.0 {
|
||||
# match d.index {
|
||||
# 0 => self.health = Health(d.value.into_float()?),
|
||||
# 1 => self.dancing = Dancing(d.value.into_boolean()?),
|
||||
# 2 => self.can_duplicate = CanDuplicate(d.value.into_boolean()?),
|
||||
# }
|
||||
# }
|
||||
# Ok(())
|
||||
# }
|
||||
# }
|
||||
code.append(f'impl {struct_name} {{')
|
||||
code.append(f'impl {bundle_struct_name} {{')
|
||||
code.append(
|
||||
' pub fn default(builder: &mut EntityBuilder) -> BuiltEntity {')
|
||||
code.append(' builder')
|
||||
f' pub fn update_metadata(&mut self, ecs: bevy_ecs::world::World, entity: bevy_ecs::world::EntityMut, data: EntityMetadataItems) -> Result<(), UpdateMetadataError> {{')
|
||||
code.append(f' for d in data.0 {{')
|
||||
code.append(f' match d.index {{')
|
||||
for index, name_or_bitfield in enumerate(all_field_names_or_bitfields):
|
||||
if isinstance(name_or_bitfield, str):
|
||||
name_or_bitfield = maybe_rename_field(
|
||||
name_or_bitfield, index)
|
||||
|
||||
struct_name = upper_first_letter(
|
||||
to_camel_case(name_or_bitfield))
|
||||
if name_or_bitfield in single_use_imported_types:
|
||||
struct_name = ''
|
||||
|
||||
type_id = next(filter(lambda i: i['index'] == index, entity_metadatas))[
|
||||
'type_id']
|
||||
metadata_type_data = metadata_types[type_id]
|
||||
rust_type = metadata_type_data['type']
|
||||
type_name = metadata_type_data['name']
|
||||
|
||||
type_name_field = to_snake_case(type_name)
|
||||
read_field_code = f'{struct_name}(d.value.into_{type_name_field}()?)' if struct_name else f'd.value.into_{type_name_field}()?'
|
||||
code.append(
|
||||
f' {index} => self.{name_or_bitfield} = {read_field_code},')
|
||||
else:
|
||||
code.append(f' {index} => {{')
|
||||
code.append(
|
||||
f'let bitfield = d.value.into_byte()?;')
|
||||
for mask, name in name_or_bitfield.items():
|
||||
name = maybe_rename_field(name, index)
|
||||
struct_name = upper_first_letter(to_camel_case(name))
|
||||
|
||||
code.append(
|
||||
f'self.{name} = {struct_name}(bitfield & {mask} != 0);')
|
||||
code.append(' },')
|
||||
code.append(' }')
|
||||
code.append(' }')
|
||||
code.append(' Ok(())')
|
||||
code.append(' }')
|
||||
code.append('}')
|
||||
code.append('')
|
||||
|
||||
# impl Default for AllayBundle {
|
||||
# fn default() -> Self {
|
||||
# Self {
|
||||
# on_fire: OnFire(false),
|
||||
# shift_key_down: ShiftKeyDown(false),
|
||||
# sprinting: Sprinting(false),
|
||||
# swimming: Swimming(false)
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
code.append(f'impl Default for {bundle_struct_name} {{')
|
||||
code.append(
|
||||
' fn default() -> Self {')
|
||||
code.append(' Self {')
|
||||
for index, name_or_bitfield in enumerate(all_field_names_or_bitfields):
|
||||
default = next(filter(lambda i: i['index'] == index, entity_metadatas)).get(
|
||||
'default', 'Default::default()')
|
||||
|
@ -212,7 +303,7 @@ impl From<EntityDataValue> for UpdateMetadataError {
|
|||
elif type_name == 'FrogVariant':
|
||||
default = 'azalea_registry::FrogVariant::Temperate'
|
||||
elif type_name == 'VillagerData':
|
||||
default = 'VillagerData { kind: azalea_registry::VillagerType::Plains, profession: azalea_registry::VillagerProfession::None, level: 0 }'
|
||||
default = 'VillagerData { kind: azalea_registry::VillagerKind::Plains, profession: azalea_registry::VillagerProfession::None, level: 0 }'
|
||||
else:
|
||||
default = f'{type_name}::default()' if name in single_use_imported_types else 'Default::default()'
|
||||
else:
|
||||
|
@ -238,10 +329,10 @@ impl From<EntityDataValue> for UpdateMetadataError {
|
|||
elif type_name == 'CompoundTag':
|
||||
default = f'azalea_nbt::Tag::Compound({default})' if default != 'Empty' else 'azalea_nbt::Tag::Compound(Default::default())'
|
||||
if name in single_use_imported_types:
|
||||
code.append(f' .add({default})')
|
||||
code.append(f' {name}: {default},')
|
||||
else:
|
||||
code.append(
|
||||
f' .add({upper_first_letter(to_camel_case(name))}({default}))')
|
||||
f' {name}: {upper_first_letter(to_camel_case(name))}({default}),')
|
||||
else:
|
||||
# if it's a bitfield, we'll have to extract the default for
|
||||
# each bool from each bit in the default
|
||||
|
@ -251,94 +342,8 @@ impl From<EntityDataValue> for UpdateMetadataError {
|
|||
bit_default = 'true' if (
|
||||
default & mask != 0) else 'false'
|
||||
code.append(
|
||||
f' .add({upper_first_letter(to_camel_case(name))}({bit_default}))')
|
||||
code.append(f' .build()')
|
||||
code.append(' }')
|
||||
code.append('}')
|
||||
|
||||
# #[derive(Query)]
|
||||
# struct AllayQuery<'a> {
|
||||
# health: &'a mut Health,
|
||||
# ...
|
||||
# dancing: &'a mut Dancing,
|
||||
# can_duplicate: &'a mut CanDuplicate,
|
||||
# }
|
||||
query_struct_name = f'{struct_name}Query'
|
||||
code.append(f'')
|
||||
code.append(f'#[derive(Query)]')
|
||||
code.append(f'struct {query_struct_name}<\'a> {{')
|
||||
for index, name_or_bitfield in enumerate(all_field_names_or_bitfields):
|
||||
if isinstance(name_or_bitfield, str):
|
||||
name_or_bitfield = maybe_rename_field(
|
||||
name_or_bitfield, index)
|
||||
struct_name = upper_first_letter(
|
||||
to_camel_case(name_or_bitfield))
|
||||
code.append(
|
||||
f' {name_or_bitfield}: &\'a mut {struct_name},')
|
||||
else:
|
||||
for mask, name in name_or_bitfield.items():
|
||||
name = maybe_rename_field(name, index)
|
||||
|
||||
struct_name = upper_first_letter(to_camel_case(name))
|
||||
code.append(f' {name}: &\'a mut {struct_name},')
|
||||
code.append('}')
|
||||
|
||||
# impl AllayQuery<'_> {
|
||||
# pub fn update_metadata(
|
||||
# &mut self,
|
||||
# world: hecs::World,
|
||||
# entity: hecs::Entity,
|
||||
# data: EntityMetadataItems,
|
||||
# ) -> Result<(), UpdateMetadataError> {
|
||||
# for d in data.0 {
|
||||
# match d.index {
|
||||
# 0 => *self.health = Health(d.value.into_float()?),
|
||||
# 1 => *self.dancing = Dancing(d.value.into_boolean()?),
|
||||
# 2 => *self.can_duplicate = CanDuplicate(d.value.into_boolean()?),
|
||||
# }
|
||||
# }
|
||||
# Ok(())
|
||||
# }
|
||||
# }
|
||||
code.append(f'impl {query_struct_name}<\'_> {{')
|
||||
code.append(
|
||||
f' pub fn update_metadata(&mut self, world: hecs::World, entity: hecs::Entity, data: EntityMetadataItems) -> Result<(), UpdateMetadataError> {{')
|
||||
code.append(f' for d in data.0 {{')
|
||||
code.append(f' match d.index {{')
|
||||
for index, name_or_bitfield in enumerate(all_field_names_or_bitfields):
|
||||
if isinstance(name_or_bitfield, str):
|
||||
name_or_bitfield = maybe_rename_field(
|
||||
name_or_bitfield, index)
|
||||
|
||||
struct_name = upper_first_letter(
|
||||
to_camel_case(name_or_bitfield))
|
||||
if name_or_bitfield in single_use_imported_types:
|
||||
struct_name = ''
|
||||
|
||||
type_id = next(filter(lambda i: i['index'] == index, entity_metadatas))[
|
||||
'type_id']
|
||||
metadata_type_data = metadata_types[type_id]
|
||||
rust_type = metadata_type_data['type']
|
||||
type_name = metadata_type_data['name']
|
||||
|
||||
type_name_field = to_snake_case(type_name)
|
||||
read_field_code = f'{struct_name}(d.value.into_{type_name_field}()?)' if struct_name else f'd.value.into_{type_name_field}()?'
|
||||
code.append(
|
||||
f' {index} => *self.{name_or_bitfield} = {read_field_code},')
|
||||
else:
|
||||
code.append(f' {index} => {{')
|
||||
code.append(
|
||||
f'let bitfield = d.value.into_byte()?;')
|
||||
for mask, name in name_or_bitfield.items():
|
||||
name = maybe_rename_field(name, index)
|
||||
struct_name = upper_first_letter(to_camel_case(name))
|
||||
|
||||
code.append(
|
||||
f'*self.{name} = {struct_name}(bitfield & {mask} != 0);')
|
||||
code.append(' },')
|
||||
code.append(' }')
|
||||
f' {name}: {upper_first_letter(to_camel_case(name))}({bit_default}),')
|
||||
code.append(' }')
|
||||
code.append(' Ok(())')
|
||||
code.append(' }')
|
||||
code.append('}')
|
||||
code.append('')
|
||||
|
@ -349,29 +354,29 @@ impl From<EntityDataValue> for UpdateMetadataError {
|
|||
|
||||
# and now make the main update_metadata
|
||||
# fn update_metadata(
|
||||
# world: hecs::World,
|
||||
# entity: hecs::Entity,
|
||||
# ecs: bevy_ecs::world::World,
|
||||
# entity: bevy_ecs::world::EntityMut,
|
||||
# data: EntityMetadataItems,
|
||||
# ) -> Result<(), UpdateMetadataError> {
|
||||
# if let Ok(e) = world.query_one_mut::<AllayQuery>(entity) {
|
||||
# e.update_metadata(world, entity, data)?;
|
||||
# if let Ok(e) = world.query_one_mut::<AllayBundle>(entity) {
|
||||
# e.update_metadata(ecs, entity, data)?;
|
||||
# return Ok(());
|
||||
# }
|
||||
|
||||
# Ok(())
|
||||
# }
|
||||
code.append(
|
||||
f'fn update_metadata(world: hecs::World, entity: hecs::Entity, data: EntityMetadataItems) -> Result<(), UpdateMetadataError> {{')
|
||||
f'fn update_metadata(ecs: bevy_ecs::world::World, entity: bevy_ecs::world::EntityMut, data: EntityMetadataItems) -> Result<(), UpdateMetadataError> {{')
|
||||
for entity_id in burger_entity_data:
|
||||
if entity_id.startswith('~'):
|
||||
# not actually an entiry
|
||||
continue
|
||||
struct_name: str = upper_first_letter(to_camel_case(entity_id))
|
||||
query_struct_name = f'{struct_name}Query'
|
||||
bundle_struct_name = f'{struct_name}Bundle'
|
||||
code.append(
|
||||
f' if let Ok(e) = world.query_one_mut::<{query_struct_name}>(entity) {{')
|
||||
f' if let Ok(e) = ecs.query_one_mut::<{bundle_struct_name}>(entity) {{')
|
||||
code.append(
|
||||
f' e.update_metadata(world, entity, data)?;')
|
||||
f' e.update_metadata(ecs, entity, data)?;')
|
||||
code.append(f' return Ok(());')
|
||||
code.append(' }')
|
||||
code.append(' Ok(())')
|
||||
|
|
|
@ -44,8 +44,8 @@ def burger_type_to_rust_type(burger_type, field_name: Optional[str] = None, inst
|
|||
field_type_rs = 'String'
|
||||
|
||||
elif burger_type == 'chatcomponent':
|
||||
field_type_rs = 'Component'
|
||||
uses.add('azalea_chat::Component')
|
||||
field_type_rs = 'FormattedText'
|
||||
uses.add('azalea_chat::FormattedText')
|
||||
elif burger_type == 'identifier':
|
||||
field_type_rs = 'ResourceLocation'
|
||||
uses.add('azalea_core::ResourceLocation')
|
||||
|
|
Loading…
Add table
Reference in a new issue