mirror of
https://github.com/italicsjenga/valence.git
synced 2024-12-23 14:31:30 +11:00
Implement title and subtitle
This commit is contained in:
parent
bfba7a1d11
commit
5fcde5f7ae
|
@ -19,16 +19,17 @@ use crate::player_textures::SignedPlayerTextures;
|
|||
use crate::protocol::packets::play::c2s::{
|
||||
C2sPlayPacket, DiggingStatus, InteractKind, PlayerCommandId,
|
||||
};
|
||||
pub use crate::protocol::packets::play::s2c::SetTitleAnimationTimes as TitleAnimationTimes;
|
||||
use crate::protocol::packets::play::s2c::{
|
||||
Animate, Biome as BiomeRegistryBiome, BiomeAdditionsSound, BiomeEffects, BiomeMoodSound,
|
||||
BiomeMusic, BiomeParticle, BiomeParticleOptions, BiomeProperty, BiomeRegistry, BlockChangeAck,
|
||||
ChatType, ChatTypeChat, ChatTypeNarration, ChatTypeRegistry, ChatTypeRegistryEntry,
|
||||
DimensionType, DimensionTypeRegistry, DimensionTypeRegistryEntry, Disconnect, EntityEvent,
|
||||
ForgetLevelChunk, GameEvent, GameEventReason, KeepAlive, Login, MoveEntityPosition,
|
||||
MoveEntityPositionAndRotation, MoveEntityRotation, PlayerPosition, PlayerPositionFlags,
|
||||
RegistryCodec, RemoveEntities, Respawn, RotateHead, S2cPlayPacket, SetChunkCacheCenter,
|
||||
SetChunkCacheRadius, SetEntityMetadata, SetEntityMotion, SpawnPosition, SystemChat,
|
||||
TeleportEntity, ENTITY_EVENT_MAX_BOUND,
|
||||
ClearTitles, DimensionType, DimensionTypeRegistry, DimensionTypeRegistryEntry, Disconnect,
|
||||
EntityEvent, ForgetLevelChunk, GameEvent, GameEventReason, KeepAlive, Login,
|
||||
MoveEntityPosition, MoveEntityPositionAndRotation, MoveEntityRotation, PlayerPosition,
|
||||
PlayerPositionFlags, RegistryCodec, RemoveEntities, Respawn, RotateHead, S2cPlayPacket,
|
||||
SetChunkCacheCenter, SetChunkCacheRadius, SetEntityMetadata, SetEntityMotion, SetSubtitleText,
|
||||
SetTitleText, SpawnPosition, SystemChat, TeleportEntity, ENTITY_EVENT_MAX_BOUND,
|
||||
};
|
||||
use crate::protocol::{BoundedInt, ByteAngle, Nbt, RawBytes, VarInt};
|
||||
use crate::server::C2sPacketChannels;
|
||||
|
@ -310,6 +311,32 @@ impl Client {
|
|||
self.new_game_mode = new_game_mode;
|
||||
}
|
||||
|
||||
pub fn set_title(
|
||||
&mut self,
|
||||
title: impl Into<Text>,
|
||||
subtitle: impl Into<Text>,
|
||||
animation: impl Into<Option<TitleAnimationTimes>>,
|
||||
) {
|
||||
let title = title.into();
|
||||
let subtitle = subtitle.into();
|
||||
|
||||
self.send_packet(SetTitleText { text: title });
|
||||
|
||||
if !subtitle.is_empty() {
|
||||
self.send_packet(SetSubtitleText {
|
||||
subtitle_text: subtitle,
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(anim) = animation.into() {
|
||||
self.send_packet(anim);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear_title(&mut self) {
|
||||
self.send_packet(ClearTitles { reset: true });
|
||||
}
|
||||
|
||||
pub fn on_ground(&self) -> bool {
|
||||
self.flags.on_ground()
|
||||
}
|
||||
|
|
|
@ -724,6 +724,12 @@ pub mod play {
|
|||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
ClearTitles 0x0d {
|
||||
reset: bool,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
Disconnect 0x17 {
|
||||
reason: Text,
|
||||
|
@ -1168,6 +1174,12 @@ pub mod play {
|
|||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
SetSubtitleText 0x58 {
|
||||
subtitle_text: Text,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
SetTime 0x59 {
|
||||
/// The age of the world in 1/20ths of a second.
|
||||
|
@ -1179,6 +1191,24 @@ pub mod play {
|
|||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
SetTitleText 0x5a {
|
||||
text: Text,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
#[derive(Copy, PartialEq, Eq)]
|
||||
SetTitleAnimationTimes 0x5b {
|
||||
/// Ticks to spend fading in.
|
||||
fade_in: u32,
|
||||
/// Ticks to keep the title displayed.
|
||||
stay: u32,
|
||||
/// Ticks to spend fading out.
|
||||
fade_out: u32,
|
||||
}
|
||||
}
|
||||
|
||||
def_struct! {
|
||||
SystemChat 0x5f {
|
||||
chat: Text,
|
||||
|
@ -1216,6 +1246,7 @@ pub mod play {
|
|||
BlockEvent,
|
||||
BlockUpdate,
|
||||
BossEvent,
|
||||
ClearTitles,
|
||||
Disconnect,
|
||||
EntityEvent,
|
||||
ForgetLevelChunk,
|
||||
|
@ -1239,7 +1270,10 @@ pub mod play {
|
|||
SpawnPosition,
|
||||
SetEntityMetadata,
|
||||
SetEntityMotion,
|
||||
SetSubtitleText,
|
||||
SetTime,
|
||||
SetTitleText,
|
||||
SetTitleAnimationTimes,
|
||||
SystemChat,
|
||||
TabList,
|
||||
TeleportEntity,
|
||||
|
|
24
src/text.rs
24
src/text.rs
|
@ -81,6 +81,21 @@ pub struct Text {
|
|||
extra: Vec<Text>,
|
||||
}
|
||||
|
||||
impl Text {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
for extra in &self.extra {
|
||||
if !extra.is_empty() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
match &self.content {
|
||||
TextContent::Text { text } => text.is_empty(),
|
||||
TextContent::Translate { translate } => translate.is_empty(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides the methods necessary for working with [`Text`] objects.
|
||||
///
|
||||
/// This trait exists to allow using `Into<Text>` types without having to first
|
||||
|
@ -539,4 +554,13 @@ mod tests {
|
|||
assert_eq!(color_from_str("#000000"), Some(Color::BLACK));
|
||||
assert_eq!(color_from_str("#"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty() {
|
||||
assert!("".into_text().is_empty());
|
||||
|
||||
let txt = "".into_text() + Text::translate("") + ("".italic().color(Color::RED) + "");
|
||||
assert!(txt.is_empty());
|
||||
assert!(txt.to_plain().is_empty());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue