Add player metadata to client

This commit is contained in:
Ryan 2022-06-29 13:00:41 -07:00
parent 806ffa4f42
commit 1aa4ca878e
3 changed files with 79 additions and 66 deletions

View file

@ -2105,6 +2105,34 @@ pub fn build() -> anyhow::Result<()> {
})
.collect::<TokenStream>();
let initial_metadata_fields = fields.iter().enumerate().map(|(idx, f)| {
let name = ident(f.name.to_snake_case());
let default = f.typ.default_expr();
let index: u8 = idx.try_into().unwrap();
let type_id = f.typ.type_id();
quote! {
if self.#name != #default {
data.push(#index);
VarInt(#type_id).encode(data).unwrap();
self.#name.encode(data).unwrap();
}
}
}).collect::<TokenStream>();
let updated_metadata_fields = fields.iter().enumerate().map(|(idx, f)| {
let name = ident(f.name.to_snake_case());
let u8_index: u8 = idx.try_into().unwrap();
let u32_index = idx as u32;
let type_id = f.typ.type_id();
quote! {
if (self.modified_flags >> #u32_index) & 1 == 1 {
data.push(#u8_index);
VarInt(#type_id).encode(data).unwrap();
self.#name.encode(data).unwrap();
}
}
}).collect::<TokenStream>();
quote! {
pub struct #name {
/// Contains a set bit for each modified field.
@ -2113,7 +2141,7 @@ pub fn build() -> anyhow::Result<()> {
}
impl #name {
pub(super) fn new() -> Self {
pub(crate) fn new() -> Self {
Self {
modified_flags: 0,
#(#constructor_fields)*
@ -2121,62 +2149,22 @@ pub fn build() -> anyhow::Result<()> {
}
#getter_setters
}
}
});
let initial_metadata_arms = entities.iter().map(|&entity| {
let name = ident(entity.name.to_pascal_case());
let mut fields = Vec::new();
collect_class_fields(entity, &mut fields);
let check_fields = fields.into_iter().enumerate().map(|(idx, f)| {
let name = ident(f.name.to_snake_case());
let default = f.typ.default_expr();
let index: u8 = idx.try_into().unwrap();
let type_id = f.typ.type_id();
quote! {
if m.#name != #default {
data.push(#index);
VarInt(#type_id).encode(&mut data).unwrap();
m.#name.encode(&mut data).unwrap();
}
}
});
quote! {
Self::#name(m) => {
#(#check_fields)*
}
}
});
let updated_metadata_arms = entities.iter().map(|&entity| {
let name = ident(entity.name.to_pascal_case());
let mut fields = Vec::new();
collect_class_fields(entity, &mut fields);
let update_fields = fields.into_iter().enumerate().map(|(idx, f)| {
let name = ident(f.name.to_snake_case());
let u8_index: u8 = idx.try_into().unwrap();
let u32_index = idx as u32;
let type_id = f.typ.type_id();
quote! {
if (m.modified_flags >> #u32_index) & 1 == 1 {
data.push(#u8_index);
VarInt(#type_id).encode(&mut data).unwrap();
m.#name.encode(&mut data).unwrap();
}
}
});
quote! {
Self::#name(m) => {
if m.modified_flags == 0 {
return None;
pub(crate) fn initial_metadata(&self, data: &mut Vec<u8>) {
#initial_metadata_fields
}
#(#update_fields)*
pub(crate) fn updated_metadata(&self, data: &mut Vec<u8>) {
if self.modified_flags == 0 {
return;
}
#updated_metadata_fields
}
pub(crate) fn clear_modifications(&mut self) {
self.modified_flags = 0;
}
}
}
});
@ -2221,7 +2209,7 @@ pub fn build() -> anyhow::Result<()> {
let mut data = Vec::new();
match self {
#(#initial_metadata_arms)*
#(Self::#entity_type_variants(e) => e.initial_metadata(&mut data),)*
}
if data.is_empty() {
@ -2236,7 +2224,7 @@ pub fn build() -> anyhow::Result<()> {
let mut data = Vec::new();
match self {
#(#updated_metadata_arms)*
#(Self::#entity_type_variants(e) => e.updated_metadata(&mut data),)*
}
if data.is_empty() {
@ -2249,7 +2237,7 @@ pub fn build() -> anyhow::Result<()> {
pub(super) fn clear_modifications(&mut self) {
match self {
#(Self::#entity_type_variants(m) => m.modified_flags = 0,)*
#(Self::#entity_type_variants(e) => e.clear_modifications(),)*
}
}
}

View file

@ -9,8 +9,8 @@ use valence::config::{Config, ServerListPing};
use valence::text::Color;
use valence::util::to_yaw_and_pitch;
use valence::{
async_trait, DimensionId, EntityId, EntityType, Server, ShutdownResult, Text,
TextFormat, WorldId, Worlds, Client,
async_trait, Client, DimensionId, EntityId, EntityType, Server, ShutdownResult, Text,
TextFormat, WorldId, Worlds,
};
use vek::{Mat3, Vec3};

View file

@ -13,19 +13,20 @@ use crate::biome::{Biome, BiomeGrassColorModifier, BiomePrecipitation};
use crate::block_pos::BlockPos;
use crate::byte_angle::ByteAngle;
use crate::dimension::{Dimension, DimensionEffects};
use crate::entity::types::Player;
use crate::entity::{velocity_to_packet_units, EntityType};
use crate::packets::play::c2s::{C2sPlayPacket, DiggingStatus};
use crate::packets::play::s2c::{
AcknowledgeBlockChanges, Biome as BiomeRegistryBiome, BiomeAdditionsSound, BiomeEffects,
BiomeMoodSound, BiomeMusic, BiomeParticle, BiomeParticleOptions, BiomeProperty, BiomeRegistry,
ChangeGameState, ChangeGameStateReason, ChatTypeRegistry, DestroyEntities, DimensionType,
DimensionTypeRegistry, DimensionTypeRegistryEntry, Disconnect, EntityHeadLook, EntityPosition,
EntityPositionAndRotation, EntityRotation, EntityTeleport, EntityVelocity, JoinGame, KeepAlive,
PlayerPositionAndLook, PlayerPositionAndLookFlags, RegistryCodec, S2cPlayPacket, SpawnPosition,
UnloadChunk, UpdateViewDistance, UpdateViewPosition,
DimensionTypeRegistry, DimensionTypeRegistryEntry, Disconnect, EntityHeadLook, EntityMetadata,
EntityPosition, EntityPositionAndRotation, EntityRotation, EntityTeleport, EntityVelocity,
JoinGame, KeepAlive, PlayerPositionAndLook, PlayerPositionAndLookFlags, RegistryCodec,
S2cPlayPacket, SpawnPosition, UnloadChunk, UpdateViewDistance, UpdateViewPosition,
};
use crate::player_textures::SignedPlayerTextures;
use crate::protocol::{BoundedInt, Nbt};
use crate::protocol::{BoundedInt, Nbt, RawBytes};
use crate::server::C2sPacketChannels;
use crate::slotmap::{Key, SlotMap};
use crate::util::{chunks_in_view_distance, is_chunk_in_view_distance};
@ -135,8 +136,8 @@ pub struct Client {
old_game_mode: GameMode,
settings: Option<Settings>,
dug_blocks: Vec<i32>,
// /// The metadata for the client's own player entity.
// player_meta: Player,
/// The metadata for the client's own player entity.
player_meta: Player,
}
impl Client {
@ -177,6 +178,7 @@ impl Client {
old_game_mode: GameMode::Survival,
settings: None,
dug_blocks: Vec::new(),
player_meta: Player::new(),
}
}
@ -328,6 +330,14 @@ impl Client {
}
}
pub fn meta(&self) -> &Player {
&self.player_meta
}
pub fn meta_mut(&mut self) -> &mut Player {
&mut self.player_meta
}
/// Attempts to enqueue a play packet to be sent to this client. The client
/// is disconnected if the clientbound packet buffer is full.
pub(crate) fn send_packet(&mut self, packet: impl Into<S2cPlayPacket>) {
@ -813,6 +823,21 @@ impl Client {
});
}
// Update the client's own player metadata.
{
let mut data = Vec::new();
self.player_meta.updated_metadata(&mut data);
if !data.is_empty() {
data.push(0xff);
self.send_packet(EntityMetadata {
entity_id: VarInt(0),
metadata: RawBytes(data),
});
}
}
// Spawn new entities within the view distance.
let pos = self.position();
spatial_index.query::<_, _, ()>(