Basic chat message support

This commit is contained in:
Ryan 2022-06-29 21:33:42 -07:00
parent a182f17c78
commit fa2241c038
4 changed files with 57 additions and 17 deletions

View file

@ -6,7 +6,7 @@ use log::LevelFilter;
use noise::{NoiseFn, Seedable, SuperSimplex}; use noise::{NoiseFn, Seedable, SuperSimplex};
use rayon::iter::ParallelIterator; use rayon::iter::ParallelIterator;
use valence::block::{BlockState, PropName, PropValue}; use valence::block::{BlockState, PropName, PropValue};
use valence::client::GameMode; use valence::client::{ChatMessageType, GameMode};
use valence::config::{Config, ServerListPing}; use valence::config::{Config, ServerListPing};
use valence::text::Color; use valence::text::Color;
use valence::util::chunks_in_view_distance; use valence::util::chunks_in_view_distance;
@ -113,6 +113,8 @@ impl Config for Game {
0, 0,
None, None,
); );
client.send_message("welcome!", ChatMessageType::Chat);
} }
let dist = client.view_distance(); let dist = client.view_distance();

View file

@ -2,6 +2,7 @@
mod event; mod event;
use std::collections::HashSet; use std::collections::HashSet;
use std::iter::FusedIterator; use std::iter::FusedIterator;
use std::time::Duration;
pub use event::*; pub use event::*;
use flume::{Receiver, Sender, TrySendError}; use flume::{Receiver, Sender, TrySendError};
@ -16,6 +17,7 @@ use crate::dimension::{Dimension, DimensionEffects};
use crate::entity::types::Player; use crate::entity::types::Player;
use crate::entity::{velocity_to_packet_units, EntityType}; use crate::entity::{velocity_to_packet_units, EntityType};
use crate::packets::play::c2s::{C2sPlayPacket, DiggingStatus}; use crate::packets::play::c2s::{C2sPlayPacket, DiggingStatus};
pub use crate::packets::play::s2c::ChatMessageType;
use crate::packets::play::s2c::{ use crate::packets::play::s2c::{
AcknowledgeBlockChanges, Biome as BiomeRegistryBiome, BiomeAdditionsSound, BiomeEffects, AcknowledgeBlockChanges, Biome as BiomeRegistryBiome, BiomeAdditionsSound, BiomeEffects,
BiomeMoodSound, BiomeMusic, BiomeParticle, BiomeParticleOptions, BiomeProperty, BiomeRegistry, BiomeMoodSound, BiomeMusic, BiomeParticle, BiomeParticleOptions, BiomeProperty, BiomeRegistry,
@ -23,7 +25,8 @@ use crate::packets::play::s2c::{
DimensionTypeRegistry, DimensionTypeRegistryEntry, Disconnect, EntityHeadLook, EntityMetadata, DimensionTypeRegistry, DimensionTypeRegistryEntry, Disconnect, EntityHeadLook, EntityMetadata,
EntityPosition, EntityPositionAndRotation, EntityRotation, EntityTeleport, EntityVelocity, EntityPosition, EntityPositionAndRotation, EntityRotation, EntityTeleport, EntityVelocity,
JoinGame, KeepAlive, PlayerPositionAndLook, PlayerPositionAndLookFlags, RegistryCodec, JoinGame, KeepAlive, PlayerPositionAndLook, PlayerPositionAndLookFlags, RegistryCodec,
S2cPlayPacket, SpawnPosition, UnloadChunk, UpdateViewDistance, UpdateViewPosition, S2cPlayPacket, SpawnPosition, SystemChatMessage, UnloadChunk, UpdateViewDistance,
UpdateViewPosition,
}; };
use crate::player_textures::SignedPlayerTextures; use crate::player_textures::SignedPlayerTextures;
use crate::protocol::{BoundedInt, Nbt, RawBytes}; use crate::protocol::{BoundedInt, Nbt, RawBytes};
@ -136,6 +139,7 @@ pub struct Client {
old_game_mode: GameMode, old_game_mode: GameMode,
settings: Option<Settings>, settings: Option<Settings>,
dug_blocks: Vec<i32>, dug_blocks: Vec<i32>,
msgs_to_send: Vec<(Text, ChatMessageType)>,
/// The metadata for the client's own player entity. /// The metadata for the client's own player entity.
player_meta: Player, player_meta: Player,
} }
@ -178,6 +182,7 @@ impl Client {
old_game_mode: GameMode::Survival, old_game_mode: GameMode::Survival,
settings: None, settings: None,
dug_blocks: Vec::new(), dug_blocks: Vec::new(),
msgs_to_send: Vec::new(),
player_meta: Player::new(), player_meta: Player::new(),
} }
} }
@ -198,6 +203,10 @@ impl Client {
self.textures.as_ref() self.textures.as_ref()
} }
pub fn send_message(&mut self, msg: impl Into<Text>, typ: ChatMessageType) {
self.msgs_to_send.push((msg.into(), typ));
}
pub fn position(&self) -> Vec3<f64> { pub fn position(&self) -> Vec3<f64> {
self.new_position self.new_position
} }
@ -402,7 +411,10 @@ impl Client {
C2sPlayPacket::QueryBlockNbt(_) => {} C2sPlayPacket::QueryBlockNbt(_) => {}
C2sPlayPacket::SetDifficulty(_) => {} C2sPlayPacket::SetDifficulty(_) => {}
C2sPlayPacket::ChatCommand(_) => {} C2sPlayPacket::ChatCommand(_) => {}
C2sPlayPacket::ChatMessage(_) => {} C2sPlayPacket::ChatMessage(p) => self.events.push(Event::ChatMessage {
message: p.message.0,
timestamp: Duration::from_millis(p.timestamp),
}),
C2sPlayPacket::ChatPreview(_) => {} C2sPlayPacket::ChatPreview(_) => {}
C2sPlayPacket::ClientStatus(_) => {} C2sPlayPacket::ClientStatus(_) => {}
C2sPlayPacket::ClientSettings(p) => { C2sPlayPacket::ClientSettings(p) => {
@ -719,6 +731,11 @@ impl Client {
}); });
} }
for (msg, typ) in self.msgs_to_send.drain(..) {
// TODO: wont work without proper chat registry.
send_packet(&mut self.send, SystemChatMessage { chat: msg, typ });
}
let mut entities_to_unload = Vec::new(); let mut entities_to_unload = Vec::new();
// Update all entities that are visible and unload entities that are no // Update all entities that are visible and unload entities that are no
@ -824,21 +841,18 @@ impl Client {
} }
// Update the client's own player metadata. // Update the client's own player metadata.
{ let mut data = Vec::new();
let mut data = Vec::new(); self.player_meta.updated_metadata(&mut data);
self.player_meta.updated_metadata(&mut data);
if !data.is_empty() { if !data.is_empty() {
data.push(0xff); data.push(0xff);
self.send_packet(EntityMetadata { self.send_packet(EntityMetadata {
entity_id: VarInt(0), entity_id: VarInt(0),
metadata: RawBytes(data), metadata: RawBytes(data),
}); });
}
self.player_meta.clear_modifications();
} }
self.player_meta.clear_modifications();
// Spawn new entities within the view distance. // Spawn new entities within the view distance.
let pos = self.position(); let pos = self.position();

View file

@ -1,3 +1,5 @@
use std::time::Duration;
use vek::Vec3; use vek::Vec3;
use crate::packets::play::c2s::BlockFace; use crate::packets::play::c2s::BlockFace;
@ -7,6 +9,10 @@ use crate::{BlockPos, EntityId};
#[derive(Debug)] #[derive(Debug)]
pub enum Event { pub enum Event {
ChatMessage {
message: String,
timestamp: Duration,
},
/// Settings were changed. The value in this variant is the previous client /// Settings were changed. The value in this variant is the previous client
/// settings. /// settings.
SettingsChanged(Option<Settings>), SettingsChanged(Option<Settings>),

View file

@ -1005,6 +1005,7 @@ pub mod play {
} }
def_enum! { def_enum! {
#[derive(Copy, PartialEq, Eq)]
ChatMessageType: VarInt { ChatMessageType: VarInt {
Chat = 0, Chat = 0,
SystemMessage = 1, SystemMessage = 1,
@ -1017,6 +1018,12 @@ pub mod play {
} }
} }
impl Default for ChatMessageType {
fn default() -> Self {
ChatMessageType::Chat
}
}
def_enum! { def_enum! {
PlayerInfo 0x34: VarInt { PlayerInfo 0x34: VarInt {
AddPlayer: Vec<PlayerInfoAddPlayer> = 0, AddPlayer: Vec<PlayerInfoAddPlayer> = 0,
@ -1132,6 +1139,13 @@ pub mod play {
} }
} }
def_struct! {
SystemChatMessage 0x5f {
chat: Text,
typ: ChatMessageType,
}
}
def_struct! { def_struct! {
PlayerListHeaderFooter 0x60 { PlayerListHeaderFooter 0x60 {
header: Text, header: Text,
@ -1240,6 +1254,7 @@ pub mod play {
EntityMetadata, EntityMetadata,
EntityVelocity, EntityVelocity,
TimeUpdate, TimeUpdate,
SystemChatMessage,
PlayerListHeaderFooter, PlayerListHeaderFooter,
EntityTeleport, EntityTeleport,
} }
@ -1280,8 +1295,11 @@ pub mod play {
def_struct! { def_struct! {
ChatMessage 0x04 { ChatMessage 0x04 {
message: BoundedString<0, 256> message: BoundedString<0, 256>,
// TODO: timestamp: u64,
salt: u64,
signature: Vec<u8>,
signed_preview: bool,
} }
} }