mirror of
https://github.com/italicsjenga/valence.git
synced 2025-01-11 15:21:31 +11:00
Add player metadata to client
This commit is contained in:
parent
806ffa4f42
commit
1aa4ca878e
102
build/entity.rs
102
build/entity.rs
|
@ -2105,6 +2105,34 @@ pub fn build() -> anyhow::Result<()> {
|
||||||
})
|
})
|
||||||
.collect::<TokenStream>();
|
.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! {
|
quote! {
|
||||||
pub struct #name {
|
pub struct #name {
|
||||||
/// Contains a set bit for each modified field.
|
/// Contains a set bit for each modified field.
|
||||||
|
@ -2113,7 +2141,7 @@ pub fn build() -> anyhow::Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl #name {
|
impl #name {
|
||||||
pub(super) fn new() -> Self {
|
pub(crate) fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
modified_flags: 0,
|
modified_flags: 0,
|
||||||
#(#constructor_fields)*
|
#(#constructor_fields)*
|
||||||
|
@ -2121,62 +2149,22 @@ pub fn build() -> anyhow::Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#getter_setters
|
#getter_setters
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let initial_metadata_arms = entities.iter().map(|&entity| {
|
pub(crate) fn initial_metadata(&self, data: &mut Vec<u8>) {
|
||||||
let name = ident(entity.name.to_pascal_case());
|
#initial_metadata_fields
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#(#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();
|
let mut data = Vec::new();
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
#(#initial_metadata_arms)*
|
#(Self::#entity_type_variants(e) => e.initial_metadata(&mut data),)*
|
||||||
}
|
}
|
||||||
|
|
||||||
if data.is_empty() {
|
if data.is_empty() {
|
||||||
|
@ -2236,7 +2224,7 @@ pub fn build() -> anyhow::Result<()> {
|
||||||
let mut data = Vec::new();
|
let mut data = Vec::new();
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
#(#updated_metadata_arms)*
|
#(Self::#entity_type_variants(e) => e.updated_metadata(&mut data),)*
|
||||||
}
|
}
|
||||||
|
|
||||||
if data.is_empty() {
|
if data.is_empty() {
|
||||||
|
@ -2249,7 +2237,7 @@ pub fn build() -> anyhow::Result<()> {
|
||||||
|
|
||||||
pub(super) fn clear_modifications(&mut self) {
|
pub(super) fn clear_modifications(&mut self) {
|
||||||
match self {
|
match self {
|
||||||
#(Self::#entity_type_variants(m) => m.modified_flags = 0,)*
|
#(Self::#entity_type_variants(e) => e.clear_modifications(),)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,8 @@ use valence::config::{Config, ServerListPing};
|
||||||
use valence::text::Color;
|
use valence::text::Color;
|
||||||
use valence::util::to_yaw_and_pitch;
|
use valence::util::to_yaw_and_pitch;
|
||||||
use valence::{
|
use valence::{
|
||||||
async_trait, DimensionId, EntityId, EntityType, Server, ShutdownResult, Text,
|
async_trait, Client, DimensionId, EntityId, EntityType, Server, ShutdownResult, Text,
|
||||||
TextFormat, WorldId, Worlds, Client,
|
TextFormat, WorldId, Worlds,
|
||||||
};
|
};
|
||||||
use vek::{Mat3, Vec3};
|
use vek::{Mat3, Vec3};
|
||||||
|
|
||||||
|
|
|
@ -13,19 +13,20 @@ use crate::biome::{Biome, BiomeGrassColorModifier, BiomePrecipitation};
|
||||||
use crate::block_pos::BlockPos;
|
use crate::block_pos::BlockPos;
|
||||||
use crate::byte_angle::ByteAngle;
|
use crate::byte_angle::ByteAngle;
|
||||||
use crate::dimension::{Dimension, DimensionEffects};
|
use crate::dimension::{Dimension, DimensionEffects};
|
||||||
|
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};
|
||||||
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,
|
||||||
ChangeGameState, ChangeGameStateReason, ChatTypeRegistry, DestroyEntities, DimensionType,
|
ChangeGameState, ChangeGameStateReason, ChatTypeRegistry, DestroyEntities, DimensionType,
|
||||||
DimensionTypeRegistry, DimensionTypeRegistryEntry, Disconnect, EntityHeadLook, EntityPosition,
|
DimensionTypeRegistry, DimensionTypeRegistryEntry, Disconnect, EntityHeadLook, EntityMetadata,
|
||||||
EntityPositionAndRotation, EntityRotation, EntityTeleport, EntityVelocity, JoinGame, KeepAlive,
|
EntityPosition, EntityPositionAndRotation, EntityRotation, EntityTeleport, EntityVelocity,
|
||||||
PlayerPositionAndLook, PlayerPositionAndLookFlags, RegistryCodec, S2cPlayPacket, SpawnPosition,
|
JoinGame, KeepAlive, PlayerPositionAndLook, PlayerPositionAndLookFlags, RegistryCodec,
|
||||||
UnloadChunk, UpdateViewDistance, UpdateViewPosition,
|
S2cPlayPacket, SpawnPosition, UnloadChunk, UpdateViewDistance, UpdateViewPosition,
|
||||||
};
|
};
|
||||||
use crate::player_textures::SignedPlayerTextures;
|
use crate::player_textures::SignedPlayerTextures;
|
||||||
use crate::protocol::{BoundedInt, Nbt};
|
use crate::protocol::{BoundedInt, Nbt, RawBytes};
|
||||||
use crate::server::C2sPacketChannels;
|
use crate::server::C2sPacketChannels;
|
||||||
use crate::slotmap::{Key, SlotMap};
|
use crate::slotmap::{Key, SlotMap};
|
||||||
use crate::util::{chunks_in_view_distance, is_chunk_in_view_distance};
|
use crate::util::{chunks_in_view_distance, is_chunk_in_view_distance};
|
||||||
|
@ -135,8 +136,8 @@ 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>,
|
||||||
// /// The metadata for the client's own player entity.
|
/// The metadata for the client's own player entity.
|
||||||
// player_meta: Player,
|
player_meta: Player,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
|
@ -177,6 +178,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(),
|
||||||
|
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
|
/// Attempts to enqueue a play packet to be sent to this client. The client
|
||||||
/// is disconnected if the clientbound packet buffer is full.
|
/// is disconnected if the clientbound packet buffer is full.
|
||||||
pub(crate) fn send_packet(&mut self, packet: impl Into<S2cPlayPacket>) {
|
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.
|
// Spawn new entities within the view distance.
|
||||||
let pos = self.position();
|
let pos = self.position();
|
||||||
spatial_index.query::<_, _, ()>(
|
spatial_index.query::<_, _, ()>(
|
||||||
|
|
Loading…
Reference in a new issue