feat: add SynchedEntityData

also some fixes
This commit is contained in:
Alexander Medvedev 2026-09-02 22:18:45 +02:00
parent 8f847ef786
commit 8608ac0361
94 changed files with 2576 additions and 2853 deletions

View File

@ -231,9 +231,9 @@ pub enum Mirror {
/// No mirroring
#[default]
None,
/// Mirror along the X axis (left-right flip when looking north)
/// Mirror along the Z axis (inverting Z: north <-> south)
LeftRight,
/// Mirror along the Z axis (front-back flip)
/// Mirror along the X axis (inverting X: east <-> west)
FrontBack,
}
@ -249,8 +249,8 @@ impl Mirror {
pub const fn transform_pos(&self, pos: Vector3<i32>, size: Vector3<i32>) -> Vector3<i32> {
match self {
Self::None => pos,
Self::LeftRight => Vector3::new(size.x - 1 - pos.x, pos.y, pos.z),
Self::FrontBack => Vector3::new(pos.x, pos.y, size.z - 1 - pos.z),
Self::LeftRight => Vector3::new(pos.x, pos.y, size.z - 1 - pos.z),
Self::FrontBack => Vector3::new(size.x - 1 - pos.x, pos.y, pos.z),
}
}
@ -266,19 +266,19 @@ impl Mirror {
_ => leak_str(facing),
},
Self::LeftRight => match facing {
"east" => "west",
"west" => "east",
"north" => "north",
"south" => "south",
_ => leak_str(facing),
},
Self::FrontBack => match facing {
"north" => "south",
"south" => "north",
"east" => "east",
"west" => "west",
_ => leak_str(facing),
},
Self::FrontBack => match facing {
"east" => "west",
"west" => "east",
"north" => "north",
"south" => "south",
_ => leak_str(facing),
},
}
}
@ -287,8 +287,8 @@ impl Mirror {
pub const fn mirror_block_rotation(&self, rotation: i32) -> i32 {
match self {
Self::None => rotation,
Self::LeftRight => (16 - rotation) % 16,
Self::FrontBack => (8 - rotation + 16) % 16,
Self::LeftRight => (8 - rotation + 16) % 16,
Self::FrontBack => (16 - rotation) % 16,
}
}
@ -298,17 +298,17 @@ impl Mirror {
match self {
Self::None => rotation,
Self::LeftRight => match rotation {
Rotation::None => Rotation::None,
Rotation::Clockwise90 => Rotation::CounterClockwise90,
Rotation::Rotate180 => Rotation::Rotate180,
Rotation::CounterClockwise90 => Rotation::Clockwise90,
},
Self::FrontBack => match rotation {
Rotation::None => Rotation::Rotate180,
Rotation::Clockwise90 => Rotation::Clockwise90,
Rotation::Rotate180 => Rotation::None,
Rotation::CounterClockwise90 => Rotation::CounterClockwise90,
},
Self::FrontBack => match rotation {
Rotation::None => Rotation::None,
Rotation::Clockwise90 => Rotation::CounterClockwise90,
Rotation::Rotate180 => Rotation::Rotate180,
Rotation::CounterClockwise90 => Rotation::Clockwise90,
},
}
}
@ -383,8 +383,461 @@ impl Mirror {
}
}
/// Transforms rail shape based on rotation and mirror matching vanilla Minecraft BaseRailBlock.
#[must_use]
pub fn transform_rail_shape(shape: &str, rotation: Rotation, mirror: Mirror) -> String {
let mut shape = shape;
match mirror {
Mirror::LeftRight => {
shape = match shape {
"ascending_north" => "ascending_south",
"ascending_south" => "ascending_north",
"south_east" => "north_east",
"south_west" => "north_west",
"north_west" => "south_west",
"north_east" => "south_east",
_ => shape,
};
}
Mirror::FrontBack => {
shape = match shape {
"ascending_east" => "ascending_west",
"ascending_west" => "ascending_east",
"south_east" => "south_west",
"south_west" => "south_east",
"north_west" => "north_east",
"north_east" => "north_west",
_ => shape,
};
}
Mirror::None => {}
}
match rotation {
Rotation::Rotate180 => {
shape = match shape {
"ascending_east" => "ascending_west",
"ascending_west" => "ascending_east",
"ascending_north" => "ascending_south",
"ascending_south" => "ascending_north",
"south_east" => "north_west",
"south_west" => "north_east",
"north_west" => "south_east",
"north_east" => "south_west",
_ => shape,
};
}
Rotation::CounterClockwise90 => {
shape = match shape {
"ascending_east" => "ascending_north",
"ascending_west" => "ascending_south",
"ascending_north" => "ascending_west",
"ascending_south" => "ascending_east",
"north_south" => "east_west",
"east_west" => "north_south",
"south_east" => "north_east",
"south_west" => "south_east",
"north_west" => "south_west",
"north_east" => "north_west",
_ => shape,
};
}
Rotation::Clockwise90 => {
shape = match shape {
"ascending_east" => "ascending_south",
"ascending_west" => "ascending_north",
"ascending_north" => "ascending_east",
"ascending_south" => "ascending_west",
"north_south" => "east_west",
"east_west" => "north_south",
"south_east" => "south_west",
"south_west" => "north_west",
"north_west" => "north_east",
"north_east" => "south_east",
_ => shape,
};
}
Rotation::None => {}
}
shape.to_string()
}
/// Transforms block state properties based on rotation and mirror, exactly matching vanilla Minecraft.
///
/// Vanilla executes mirror first, then rotation.
#[must_use]
pub fn transform_block_properties<K: AsRef<str>, V: AsRef<str>>(
block_name: &str,
properties: &[(K, V)],
rotation: Rotation,
mirror: Mirror,
) -> Vec<(String, String)> {
if rotation == Rotation::None && mirror == Mirror::None {
return properties
.iter()
.map(|(k, v)| (k.as_ref().to_string(), v.as_ref().to_string()))
.collect();
}
let is_stairs = block_name.ends_with("_stairs");
let is_door = block_name.ends_with("_door") && !block_name.ends_with("trapdoor");
let is_rail = block_name == "minecraft:rail"
|| block_name == "rail"
|| block_name == "minecraft:powered_rail"
|| block_name == "powered_rail"
|| block_name == "minecraft:detector_rail"
|| block_name == "detector_rail"
|| block_name == "minecraft:activator_rail"
|| block_name == "activator_rail";
if is_stairs {
let mut facing_opt = None;
let mut shape_opt = None;
for (k, v) in properties {
if k.as_ref() == "facing" {
facing_opt = Some(v.as_ref());
} else if k.as_ref() == "shape" {
shape_opt = Some(v.as_ref());
}
}
let (new_facing, new_shape) = if let Some(facing) = facing_opt {
let shape = shape_opt.unwrap_or("straight");
let mut f = facing;
let mut s = shape;
// Step 1: StairBlock.mirror
match mirror {
Mirror::LeftRight => {
if f == "north" || f == "south" {
f = match f {
"north" => "south",
"south" => "north",
_ => f,
};
s = match s {
"straight" => "straight",
"outer_left" => "outer_right",
"inner_right" => "inner_left",
"inner_left" => "inner_right",
"outer_right" => "outer_left",
_ => s,
};
}
}
Mirror::FrontBack => {
if f == "east" || f == "west" {
f = match f {
"east" => "west",
"west" => "east",
_ => f,
};
s = match s {
"straight" => "straight",
"outer_left" => "outer_right",
"inner_right" => "inner_right",
"inner_left" => "inner_left",
"outer_right" => "outer_left",
_ => s,
};
}
}
Mirror::None => {}
}
// Step 2: StairBlock.rotate (only rotates facing)
f = rotation.rotate_facing(f);
(Some(f.to_string()), Some(s.to_string()))
} else {
(None, None)
};
return properties
.iter()
.map(|(k, v)| {
let k_str = k.as_ref();
if k_str == "facing" {
if let Some(ref nf) = new_facing {
return (k_str.to_string(), nf.clone());
}
} else if k_str == "shape" {
if let Some(ref ns) = new_shape {
return (k_str.to_string(), ns.clone());
}
}
(k_str.to_string(), v.as_ref().to_string())
})
.collect();
}
if is_door {
let mut facing_opt = None;
let mut hinge_opt = None;
for (k, v) in properties {
if k.as_ref() == "facing" {
facing_opt = Some(v.as_ref());
} else if k.as_ref() == "hinge" {
hinge_opt = Some(v.as_ref());
}
}
let (new_facing, new_hinge) = if let Some(facing) = facing_opt {
let hinge = hinge_opt.unwrap_or("left");
let mut f = facing;
let mut h = hinge;
// Step 1: DoorBlock.mirror
if mirror != Mirror::None {
f = mirror.mirror_facing(f);
h = match h {
"left" => "right",
"right" => "left",
_ => h,
};
}
// Step 2: DoorBlock.rotate
f = rotation.rotate_facing(f);
(Some(f.to_string()), Some(h.to_string()))
} else {
(None, None)
};
return properties
.iter()
.map(|(k, v)| {
let k_str = k.as_ref();
if k_str == "facing" {
if let Some(ref nf) = new_facing {
return (k_str.to_string(), nf.clone());
}
} else if k_str == "hinge" {
if let Some(ref nh) = new_hinge {
return (k_str.to_string(), nh.clone());
}
}
(k_str.to_string(), v.as_ref().to_string())
})
.collect();
}
if is_rail {
return properties
.iter()
.map(|(k, v)| {
let k_str = k.as_ref();
if k_str == "shape" {
let s = transform_rail_shape(v.as_ref(), rotation, mirror);
(k_str.to_string(), s)
} else {
(k_str.to_string(), v.as_ref().to_string())
}
})
.collect();
}
// General property transformation
properties
.iter()
.map(|(k, v)| {
let key = k.as_ref();
let val = v.as_ref();
let transformed_key = match key {
"north" | "south" | "east" | "west" => rotation
.rotate_facing(mirror.mirror_facing(key))
.to_string(),
_ => key.to_string(),
};
let transformed_val = match key {
"facing" => {
let mirrored = mirror.mirror_facing(val);
rotation.rotate_facing(mirrored).to_string()
}
"orientation" => {
let mut parts = val.split('_');
if let (Some(front), Some(top)) = (parts.next(), parts.next()) {
let mirrored_front = mirror.mirror_facing(front);
let rotated_front = rotation.rotate_facing(mirrored_front);
let mirrored_top = mirror.mirror_facing(top);
let rotated_top = rotation.rotate_facing(mirrored_top);
format!("{rotated_front}_{rotated_top}")
} else {
val.to_string()
}
}
"axis" => rotation.rotate_axis(val).to_string(),
"rotation" => val.parse::<i32>().map_or_else(
|_| val.to_string(),
|rot_value| {
let mirrored = mirror.mirror_block_rotation(rot_value);
let rotated = rotation.rotate_block_rotation(mirrored);
rotated.to_string()
},
),
_ => val.to_string(),
};
(transformed_key, transformed_val)
})
.collect()
}
/// Leaks a string to get a 'static str.
/// This is used for non-standard property values that aren't covered by static strings.
pub fn leak_str(s: &str) -> &'static str {
s.to_string().leak()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn stairs_mirror_left_right() {
// LeftRight inverts Z (North <-> South)
let props = [("facing", "north"), ("shape", "inner_left")];
let transformed = transform_block_properties(
"minecraft:oak_stairs",
&props,
Rotation::None,
Mirror::LeftRight,
);
let facing = transformed
.iter()
.find(|(k, _)| k == "facing")
.map(|(_, v)| v.as_str());
let shape = transformed
.iter()
.find(|(k, _)| k == "shape")
.map(|(_, v)| v.as_str());
assert_eq!(facing, Some("south"));
assert_eq!(shape, Some("inner_right"));
// LeftRight does not change East/West facing stairs shape or facing
let props = [("facing", "east"), ("shape", "inner_left")];
let transformed = transform_block_properties(
"minecraft:oak_stairs",
&props,
Rotation::None,
Mirror::LeftRight,
);
let facing = transformed
.iter()
.find(|(k, _)| k == "facing")
.map(|(_, v)| v.as_str());
let shape = transformed
.iter()
.find(|(k, _)| k == "shape")
.map(|(_, v)| v.as_str());
assert_eq!(facing, Some("east"));
assert_eq!(shape, Some("inner_left"));
}
#[test]
fn stairs_mirror_front_back() {
// FrontBack inverts X (East <-> West)
let props = [("facing", "east"), ("shape", "outer_left")];
let transformed = transform_block_properties(
"minecraft:oak_stairs",
&props,
Rotation::None,
Mirror::FrontBack,
);
let facing = transformed
.iter()
.find(|(k, _)| k == "facing")
.map(|(_, v)| v.as_str());
let shape = transformed
.iter()
.find(|(k, _)| k == "shape")
.map(|(_, v)| v.as_str());
assert_eq!(facing, Some("west"));
assert_eq!(shape, Some("outer_right"));
// FrontBack does not change North/South facing stairs
let props = [("facing", "north"), ("shape", "outer_left")];
let transformed = transform_block_properties(
"minecraft:oak_stairs",
&props,
Rotation::None,
Mirror::FrontBack,
);
let facing = transformed
.iter()
.find(|(k, _)| k == "facing")
.map(|(_, v)| v.as_str());
let shape = transformed
.iter()
.find(|(k, _)| k == "shape")
.map(|(_, v)| v.as_str());
assert_eq!(facing, Some("north"));
assert_eq!(shape, Some("outer_left"));
}
#[test]
fn stairs_mirror_and_rotate() {
// Mirror LeftRight then Rotate Clockwise90
let props = [("facing", "north"), ("shape", "inner_left")];
let transformed = transform_block_properties(
"minecraft:oak_stairs",
&props,
Rotation::Clockwise90,
Mirror::LeftRight,
);
let facing = transformed
.iter()
.find(|(k, _)| k == "facing")
.map(|(_, v)| v.as_str());
let shape = transformed
.iter()
.find(|(k, _)| k == "shape")
.map(|(_, v)| v.as_str());
// north -> south (via LeftRight mirror) -> west (via Clockwise90 rotation)
assert_eq!(facing, Some("west"));
// inner_left -> inner_right (via LeftRight mirror, unchanged by rotation)
assert_eq!(shape, Some("inner_right"));
}
#[test]
fn door_mirror_and_rotate() {
let props = [("facing", "east"), ("hinge", "left")];
let transformed = transform_block_properties(
"minecraft:oak_door",
&props,
Rotation::None,
Mirror::FrontBack,
);
let facing = transformed
.iter()
.find(|(k, _)| k == "facing")
.map(|(_, v)| v.as_str());
let hinge = transformed
.iter()
.find(|(k, _)| k == "hinge")
.map(|(_, v)| v.as_str());
assert_eq!(facing, Some("west"));
assert_eq!(hinge, Some("right"));
}
#[test]
fn rail_mirror_and_rotate() {
let props = [("shape", "north_east")];
let transformed = transform_block_properties(
"minecraft:rail",
&props,
Rotation::Clockwise90,
Mirror::LeftRight,
);
let shape = transformed
.iter()
.find(|(k, _)| k == "shape")
.map(|(_, v)| v.as_str());
assert_eq!(shape, Some("south_west"));
}
}

View File

@ -214,12 +214,12 @@ impl BlockState {
}
#[must_use]
pub const fn rotate(&self, rotation: crate::block_rotation::Rotation) -> &'static Self {
pub fn rotate(&self, rotation: crate::block_rotation::Rotation) -> &'static Self {
Block::from_state_id(self.id).rotate(self.id, rotation)
}
#[must_use]
pub const fn mirror(&self, mirror: crate::block_rotation::Mirror) -> &'static Self {
pub fn mirror(&self, mirror: crate::block_rotation::Mirror) -> &'static Self {
Block::from_state_id(self.id).mirror(self.id, mirror)
}
}
@ -283,13 +283,13 @@ impl BlockStateId {
#[inline]
#[must_use]
pub const fn rotate(self, rotation: crate::block_rotation::Rotation) -> &'static BlockState {
pub fn rotate(self, rotation: crate::block_rotation::Rotation) -> &'static BlockState {
Block::from_state_id(self).rotate(self, rotation)
}
#[inline]
#[must_use]
pub const fn mirror(self, mirror: crate::block_rotation::Mirror) -> &'static BlockState {
pub fn mirror(self, mirror: crate::block_rotation::Mirror) -> &'static BlockState {
Block::from_state_id(self).mirror(self, mirror)
}
}

View File

@ -208,21 +208,61 @@ impl Block {
}
#[must_use]
pub const fn mirror(
pub fn mirror(
&self,
id: BlockStateId,
_mirror: crate::block_rotation::Mirror,
mirror: crate::block_rotation::Mirror,
) -> &'static BlockState {
BlockState::from_id(id)
if mirror == crate::block_rotation::Mirror::None || self.states.len() <= 1 {
return BlockState::from_id(id);
}
if let Some(props) = self.properties(id) {
let props_vec = props.to_props();
let transformed = crate::block_rotation::transform_block_properties(
self.name,
&props_vec,
crate::block_rotation::Rotation::None,
mirror,
);
let transformed_refs: Vec<(&str, &str)> = transformed
.iter()
.map(|(k, v)| (k.as_str(), v.as_str()))
.collect();
let new_props = self.from_properties(&transformed_refs);
let new_state_id = new_props.to_state_id(self);
BlockState::from_id(new_state_id)
} else {
BlockState::from_id(id)
}
}
#[must_use]
pub const fn rotate(
pub fn rotate(
&self,
id: BlockStateId,
_rotation: crate::block_rotation::Rotation,
rotation: crate::block_rotation::Rotation,
) -> &'static BlockState {
BlockState::from_id(id)
if rotation == crate::block_rotation::Rotation::None || self.states.len() <= 1 {
return BlockState::from_id(id);
}
if let Some(props) = self.properties(id) {
let props_vec = props.to_props();
let transformed = crate::block_rotation::transform_block_properties(
self.name,
&props_vec,
rotation,
crate::block_rotation::Mirror::None,
);
let transformed_refs: Vec<(&str, &str)> = transformed
.iter()
.map(|(k, v)| (k.as_str(), v.as_str()))
.collect();
let new_props = self.from_properties(&transformed_refs);
let new_state_id = new_props.to_state_id(self);
BlockState::from_id(new_state_id)
} else {
BlockState::from_id(id)
}
}
}

View File

@ -403,7 +403,7 @@ mod blocks;
#[cfg(feature = "block")]
pub use block_direction::{BlockDirection, FacingExt, HorizontalFacingExt};
#[cfg(feature = "block")]
pub use block_rotation::{Mirror, Rotation};
pub use block_rotation::{Mirror, Rotation, transform_block_properties, transform_rail_shape};
#[cfg(feature = "block")]
pub use block_state::{BlockState, BlockStateId};
#[cfg(feature = "block")]

View File

@ -1,3 +1,4 @@
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct OptionalInt(pub Option<i32>);
impl OptionalInt {

View File

@ -99,10 +99,8 @@ impl TemplateMirror {
const fn state_mirror(self) -> Mirror {
match self {
Self::None => Mirror::None,
// Mojang names a Z reflection LEFT_RIGHT and an X reflection FRONT_BACK.
// Pumpkin names the axis being reflected, so the variants are exchanged.
Self::LeftRight => Mirror::FrontBack,
Self::FrontBack => Mirror::LeftRight,
Self::LeftRight => Mirror::LeftRight,
Self::FrontBack => Mirror::FrontBack,
}
}
}
@ -298,14 +296,14 @@ impl MansionTemplatePiece {
continue;
}
let mut transformed = transformed_palette(palette, self.mirror, self.rotation);
let mut placed_entry = palette.clone();
if chunk.get_block_state(&position).to_block_id() == Block::WATER.id
&& property(&transformed, "waterlogged").is_some()
&& property(&placed_entry, "waterlogged").is_some()
{
set_property(&mut transformed, "waterlogged", "true");
set_property(&mut placed_entry, "waterlogged", "true");
}
let Some(state) = BlockStateResolver::resolve(
&transformed,
&placed_entry,
self.rotation,
self.mirror.state_mirror(),
) else {
@ -510,48 +508,16 @@ fn transformed_palette(
mirror: TemplateMirror,
rotation: Rotation,
) -> PaletteEntry {
let mut palette = palette.clone();
if palette.name.ends_with("_stairs") {
let facing = property(&palette, "facing");
let shape = property(&palette, "shape");
let mirrored_shape = match (mirror, facing, shape) {
(TemplateMirror::LeftRight, Some("north" | "south"), Some("inner_left")) => {
Some("inner_right")
}
(TemplateMirror::LeftRight, Some("north" | "south"), Some("inner_right")) => {
Some("inner_left")
}
(TemplateMirror::LeftRight, Some("north" | "south"), Some("outer_left"))
| (TemplateMirror::FrontBack, Some("east" | "west"), Some("outer_left")) => {
Some("outer_right")
}
(TemplateMirror::LeftRight, Some("north" | "south"), Some("outer_right"))
| (TemplateMirror::FrontBack, Some("east" | "west"), Some("outer_right")) => {
Some("outer_left")
}
_ => None,
};
if let Some(shape) = mirrored_shape {
set_property(&mut palette, "shape", shape);
}
} else if palette.name.ends_with("_door") && mirror != TemplateMirror::None {
let hinge = match property(&palette, "hinge") {
Some("left") => Some("right"),
Some("right") => Some("left"),
_ => None,
};
if let Some(hinge) = hinge {
set_property(&mut palette, "hinge", hinge);
}
} else if palette.name == "minecraft:rail"
&& let Some(shape) = property(&palette, "shape")
&& let Some(shape) = transform_rail_shape(shape, mirror, rotation)
{
set_property(&mut palette, "shape", shape);
let properties = pumpkin_data::transform_block_properties(
&palette.name,
&palette.properties,
rotation,
mirror.state_mirror(),
);
PaletteEntry {
name: palette.name.clone(),
properties,
}
palette
}
fn property<'a>(palette: &'a PaletteEntry, name: &str) -> Option<&'a str> {
@ -567,70 +533,6 @@ fn set_property(palette: &mut PaletteEntry, name: &str, value: &str) {
}
}
fn transform_rail_shape(
shape: &str,
mirror: TemplateMirror,
rotation: Rotation,
) -> Option<&'static str> {
let ascending = shape.strip_prefix("ascending_");
if let Some(direction) = ascending.and_then(Direction::from_name) {
return Some(match transform_direction(direction, mirror, rotation) {
Direction::North => "ascending_north",
Direction::South => "ascending_south",
Direction::West => "ascending_west",
Direction::East => "ascending_east",
Direction::Up => return None,
});
}
let (first, second) = match shape {
"north_south" => (Direction::North, Direction::South),
"east_west" => (Direction::East, Direction::West),
"north_east" => (Direction::North, Direction::East),
"north_west" => (Direction::North, Direction::West),
"south_east" => (Direction::South, Direction::East),
"south_west" => (Direction::South, Direction::West),
_ => return None,
};
let first = transform_direction(first, mirror, rotation);
let second = transform_direction(second, mirror, rotation);
match (first, second) {
(Direction::North, Direction::South) | (Direction::South, Direction::North) => {
Some("north_south")
}
(Direction::East, Direction::West) | (Direction::West, Direction::East) => {
Some("east_west")
}
(Direction::North, Direction::East) | (Direction::East, Direction::North) => {
Some("north_east")
}
(Direction::North, Direction::West) | (Direction::West, Direction::North) => {
Some("north_west")
}
(Direction::South, Direction::East) | (Direction::East, Direction::South) => {
Some("south_east")
}
(Direction::South, Direction::West) | (Direction::West, Direction::South) => {
Some("south_west")
}
_ => None,
}
}
fn transform_direction(
direction: Direction,
mirror: TemplateMirror,
rotation: Rotation,
) -> Direction {
let mirrored = match (mirror, direction) {
(TemplateMirror::LeftRight, Direction::North) => Direction::South,
(TemplateMirror::LeftRight, Direction::South) => Direction::North,
(TemplateMirror::FrontBack, Direction::East) => Direction::West,
(TemplateMirror::FrontBack, Direction::West) => Direction::East,
_ => direction,
};
rotation.rotate(mirrored)
}
const fn transform(
position: Vector3<i32>,
mirror: TemplateMirror,

View File

@ -442,13 +442,14 @@ impl StructurePiece {
return;
}
// // Apply Mirror and Rotation
// if self.mirror != BlockMirror::None {
// block = block.mirror(self.mirror);
// }
// if self.rotation != BlockRotation::None {
// block = block.rotate(self.rotation);
// }
// Apply Mirror and Rotation
let mut block = block;
if self.mirror != Mirror::None {
block = block.mirror(self.mirror);
}
if self.rotation != Rotation::None {
block = block.rotate(self.rotation);
}
// World interaction
world.set_block_state(block_pos.x, block_pos.y, block_pos.z, block);

View File

@ -43,21 +43,13 @@ impl BlockStateResolver {
return Some(block.default_state);
}
// Transform properties for rotation/mirror
let transformed_props: Vec<(String, String)> = entry
.properties
.iter()
.map(|(key, value)| {
let transformed_key = match key.as_str() {
"north" | "south" | "east" | "west" => rotation
.rotate_facing(mirror.mirror_facing(key))
.to_string(),
_ => key.clone(),
};
let new_value = Self::transform_property(key, value, rotation, mirror);
(transformed_key, new_value)
})
.collect();
// Transform properties for rotation/mirror using the unified vanilla logic
let transformed_props = pumpkin_data::transform_block_properties(
&entry.name,
&entry.properties,
rotation,
mirror,
);
// Convert to the format expected by from_properties
let props_slice = transformed_props
@ -77,56 +69,6 @@ impl BlockStateResolver {
pub fn resolve_simple(entry: &PaletteEntry) -> Option<&'static BlockState> {
Self::resolve(entry, Rotation::None, Mirror::None)
}
/// Transforms a property value based on rotation and mirror.
fn transform_property(key: &str, value: &str, rotation: Rotation, mirror: Mirror) -> String {
match key {
// Horizontal facing properties
"facing" => {
let mirrored = mirror.mirror_facing(value);
rotation.rotate_facing(mirrored).to_string()
}
// Axis properties (for logs, pillars, etc.)
"axis" => rotation.rotate_axis(value).to_string(),
// Block rotation (signs, banners - 0-15 value)
"rotation" => value.parse::<i32>().map_or_else(
|_| value.to_string(),
|rot_value| {
let mirrored = mirror.mirror_block_rotation(rot_value);
let rotated = rotation.rotate_block_rotation(mirrored);
Self::rotation_to_str(rotated).to_string()
},
),
// Half properties don't need rotation (top/bottom stays the same)
// Shape, mode, and most other properties don't need transformation either
_ => value.to_string(),
}
}
/// Converts a rotation value (0-15) to a static string.
const fn rotation_to_str(rotation: i32) -> &'static str {
match rotation % 16 {
1 => "1",
2 => "2",
3 => "3",
4 => "4",
5 => "5",
6 => "6",
7 => "7",
8 => "8",
9 => "9",
10 => "10",
11 => "11",
12 => "12",
13 => "13",
14 => "14",
15 => "15",
_ => "0",
}
}
}
#[cfg(test)]
@ -180,4 +122,66 @@ mod tests {
let state = BlockStateResolver::resolve_simple(&entry);
assert!(state.is_none());
}
#[test]
fn stairs_mirror_and_rotate_resolves_expected_state() {
let entry = PaletteEntry::with_properties(
"minecraft:oak_stairs".to_string(),
vec![
("facing".to_string(), "north".to_string()),
("half".to_string(), "bottom".to_string()),
("shape".to_string(), "inner_left".to_string()),
("waterlogged".to_string(), "false".to_string()),
],
);
// Mirror LeftRight (north -> south, inner_left -> inner_right)
// then rotate Clockwise90 (south -> west)
let resolved =
BlockStateResolver::resolve(&entry, Rotation::Clockwise90, Mirror::LeftRight).unwrap();
// Compare with explicitly resolved target state
let target_entry = PaletteEntry::with_properties(
"minecraft:oak_stairs".to_string(),
vec![
("facing".to_string(), "west".to_string()),
("half".to_string(), "bottom".to_string()),
("shape".to_string(), "inner_right".to_string()),
("waterlogged".to_string(), "false".to_string()),
],
);
let expected = BlockStateResolver::resolve_simple(&target_entry).unwrap();
assert_eq!(resolved.id, expected.id);
}
#[test]
fn door_mirror_resolves_flipped_hinge() {
let entry = PaletteEntry::with_properties(
"minecraft:oak_door".to_string(),
vec![
("facing".to_string(), "east".to_string()),
("half".to_string(), "lower".to_string()),
("hinge".to_string(), "left".to_string()),
("open".to_string(), "false".to_string()),
("powered".to_string(), "false".to_string()),
],
);
// Mirror FrontBack (east -> west, hinge left -> right)
let resolved =
BlockStateResolver::resolve(&entry, Rotation::None, Mirror::FrontBack).unwrap();
let target_entry = PaletteEntry::with_properties(
"minecraft:oak_door".to_string(),
vec![
("facing".to_string(), "west".to_string()),
("half".to_string(), "lower".to_string()),
("hinge".to_string(), "right".to_string()),
("open".to_string(), "false".to_string()),
("powered".to_string(), "false".to_string()),
],
);
let expected = BlockStateResolver::resolve_simple(&target_entry).unwrap();
assert_eq!(resolved.id, expected.id);
}
}

View File

@ -269,49 +269,12 @@ impl PaletteEntry {
return self.clone();
}
let properties: Vec<(String, String)> = self
.properties
.iter()
.map(|(key, value)| {
let transformed_key = match key.as_str() {
"north" | "south" | "east" | "west" => rotation
.rotate_facing(mirror.mirror_facing(key))
.to_string(),
_ => key.clone(),
};
let transformed_value = match key.as_str() {
"facing" => {
let mirrored = mirror.mirror_facing(value);
rotation.rotate_facing(mirrored).to_string()
}
"orientation" => {
let mut parts = value.split('_');
if let (Some(front), Some(top)) = (parts.next(), parts.next()) {
let mirrored_front = mirror.mirror_facing(front);
let rotated_front = rotation.rotate_facing(mirrored_front);
let mirrored_top = mirror.mirror_facing(top);
let rotated_top = rotation.rotate_facing(mirrored_top);
format!("{rotated_front}_{rotated_top}")
} else {
value.clone()
}
}
"axis" => rotation.rotate_axis(value).to_string(),
"rotation" => value.parse::<i32>().map_or_else(
|_| value.clone(),
|rot_value| {
let mirrored = mirror.mirror_block_rotation(rot_value);
let rotated = rotation.rotate_block_rotation(mirrored);
rotated.to_string()
},
),
_ => value.clone(),
};
(transformed_key, transformed_value)
})
.collect();
let properties = pumpkin_data::transform_block_properties(
&self.name,
&self.properties,
rotation,
mirror,
);
Self {
name: self.name.clone(),

View File

@ -88,6 +88,17 @@ impl CommandExecutor for SetBoolExecutor {
context.server().level_info.store(Arc::new(new_info));
if self.0 == GameRule::SpectatorsGenerateChunks {
let server = context.server();
for world in server.worlds.load().iter() {
for player in world.players.load().iter() {
if player.is_spectator() {
player.update_chunk_tickets_for_gamemode();
}
}
}
}
let value_component = TextComponent::text(arg_value.to_string());
context.source.send_feedback(
TextComponent::translate_cross(

View File

@ -1,5 +1,4 @@
use pumpkin_data::tracked_data;
use pumpkin_protocol::java::client::play::Metadata;
use std::sync::atomic::{AtomicBool, AtomicI32, Ordering::Relaxed};
use crate::entity::mob::Mob;
@ -51,13 +50,7 @@ pub trait AgeableMob: Mob {
if (old_age < 0 && new_age >= 0) || (old_age >= 0 && new_age < 0) {
let is_baby = new_age < 0;
entity.send_meta_data(
&[Metadata::new(
tracked_data::ageable_mob::DATA_BABY_ID,
is_baby,
)],
None,
);
entity.set_synced_data(tracked_data::ageable_mob::DATA_BABY_ID, is_baby);
}
}

View File

@ -4,7 +4,6 @@ use crate::entity::mob::Mob;
use crate::entity::player::Player;
use pumpkin_data::item::Item;
use pumpkin_data::tag::{self, Taggable};
use pumpkin_protocol::java::client::play::Metadata;
use rand::RngExt;
use std::sync::Arc;
@ -45,13 +44,10 @@ impl BegGoal {
}
fn set_is_interested(mob: &dyn Mob, value: bool) {
mob.get_mob_entity().living_entity.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::wolf::INTERESTED_ID,
value,
)],
None,
);
mob.get_mob_entity()
.living_entity
.entity
.set_synced_data(pumpkin_data::tracked_data::wolf::INTERESTED_ID, value);
}
}

View File

@ -12,12 +12,13 @@ use pumpkin_util::math::vector3::Vector3;
type EffectEntry = (&'static StatusEffect, i32, u8, bool, bool, bool);
use pumpkin_data::item_stack::ItemStack;
struct ParticleMeta<'a> {
#[derive(Clone)]
struct ParticleMeta {
particle_id: pumpkin_protocol::codec::var_int::VarInt,
data: &'a [u8],
data: Box<[u8]>,
}
impl pumpkin_protocol::java::client::play::MetadataSerializer for ParticleMeta<'_> {
impl pumpkin_protocol::java::client::play::MetadataSerializer for ParticleMeta {
fn write_metadata(
&self,
writer: &mut impl std::io::Write,
@ -25,7 +26,7 @@ impl pumpkin_protocol::java::client::play::MetadataSerializer for ParticleMeta<'
) -> Result<(), pumpkin_protocol::ser::WritingError> {
use pumpkin_protocol::ser::NetworkWriteExt;
writer.write_var_int(&self.particle_id)?;
writer.write_slice(self.data)
writer.write_slice(&self.data)
}
}
@ -179,24 +180,17 @@ impl EntityBase for AreaEffectCloudEntity {
particle_id: pumpkin_protocol::codec::var_int::VarInt(
pumpkin_data::particle::Particle::EntityEffect as i32,
),
data: &data_bytes,
data: Box::new(data_bytes),
};
// Send initial particle and radius
self.entity.send_meta_data(
&[pumpkin_protocol::java::client::play::Metadata::new(
pumpkin_data::tracked_data::area_effect_cloud::PARTICLE,
&meta,
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::area_effect_cloud::PARTICLE,
meta,
);
self.entity.send_meta_data(
&[pumpkin_protocol::java::client::play::Metadata::new(
pumpkin_data::tracked_data::area_effect_cloud::RADIUS,
radius,
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::area_effect_cloud::RADIUS,
radius,
);
// Initial waiting flag
@ -205,12 +199,9 @@ impl EntityBase for AreaEffectCloudEntity {
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let is_waiting = 0 < wait_time;
self.entity.send_meta_data(
&[pumpkin_protocol::java::client::play::Metadata::new(
pumpkin_data::tracked_data::area_effect_cloud::WAITING,
is_waiting,
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::area_effect_cloud::WAITING,
is_waiting,
);
}
@ -247,12 +238,9 @@ impl EntityBase for AreaEffectCloudEntity {
// When the waiting period ends, notify clients so they render full particles
if age == wait_time && wait_time > 0 {
self.entity.send_meta_data(
&[pumpkin_protocol::java::client::play::Metadata::new(
pumpkin_data::tracked_data::area_effect_cloud::WAITING,
false,
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::area_effect_cloud::WAITING,
false,
);
}
@ -280,12 +268,9 @@ impl EntityBase for AreaEffectCloudEntity {
// Send new radius
drop(radius);
self.entity.send_meta_data(
&[pumpkin_protocol::java::client::play::Metadata::new(
pumpkin_data::tracked_data::area_effect_cloud::RADIUS,
current_radius,
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::area_effect_cloud::RADIUS,
current_radius,
);
}
@ -433,12 +418,9 @@ impl EntityBase for AreaEffectCloudEntity {
drop(radius_lock);
// Send updated radius to clients
self.entity.send_meta_data(
&[pumpkin_protocol::java::client::play::Metadata::new(
pumpkin_data::tracked_data::area_effect_cloud::RADIUS,
current_radius,
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::area_effect_cloud::RADIUS,
current_radius,
);
}

View File

@ -15,7 +15,7 @@ use pumpkin_data::{
world::WorldEvent,
};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::{codec::var_int::VarInt, java::client::play::Metadata};
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_util::{
Difficulty,
math::{position::BlockPos, vector3::Vector3},
@ -106,13 +106,10 @@ impl WitherEntity {
pub fn set_invulnerable_ticks(&self, ticks: i32) {
self.invulnerable_ticks.store(ticks, Ordering::Relaxed);
self.mob_entity.living_entity.entity.send_meta_data(
&[Metadata::new(
tracked_data::wither::DATA_ID_INV,
VarInt(ticks),
)],
None,
);
self.mob_entity
.living_entity
.entity
.set_synced_data(tracked_data::wither::DATA_ID_INV, VarInt(ticks));
}
#[must_use]
@ -136,7 +133,7 @@ impl WitherEntity {
self.mob_entity
.living_entity
.entity
.send_meta_data(&[Metadata::new(tracker_id, VarInt(entity_id))], None);
.set_synced_data(tracker_id, VarInt(entity_id));
}
}
}
@ -583,26 +580,21 @@ impl Mob for WitherEntity {
fn mob_init_data_tracker(&self) {
let entity = &self.mob_entity.living_entity.entity;
entity.send_meta_data(
&[
Metadata::new(
tracked_data::wither::DATA_TARGET_A,
VarInt(self.get_alternative_target(0)),
),
Metadata::new(
tracked_data::wither::DATA_TARGET_B,
VarInt(self.get_alternative_target(1)),
),
Metadata::new(
tracked_data::wither::DATA_TARGET_C,
VarInt(self.get_alternative_target(2)),
),
Metadata::new(
tracked_data::wither::DATA_ID_INV,
VarInt(self.get_invulnerable_ticks()),
),
],
None,
entity.set_synced_data(
tracked_data::wither::DATA_TARGET_A,
VarInt(self.get_alternative_target(0)),
);
entity.set_synced_data(
tracked_data::wither::DATA_TARGET_B,
VarInt(self.get_alternative_target(1)),
);
entity.set_synced_data(
tracked_data::wither::DATA_TARGET_C,
VarInt(self.get_alternative_target(2)),
);
entity.set_synced_data(
tracked_data::wither::DATA_ID_INV,
VarInt(self.get_invulnerable_ticks()),
);
}

View File

@ -5,7 +5,6 @@ use pumpkin_data::effect::StatusEffect;
use pumpkin_data::tag;
use pumpkin_data::tag::Taggable;
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::GameMode;
use pumpkin_util::math::position::BlockPos;
use std::sync::atomic::{AtomicI32, Ordering};
@ -162,13 +161,11 @@ impl BreathManager {
pumpkin_protocol::bedrock::client::set_actor_data::MetadataValue::Short(air as i16),
);
player.get_entity().send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::entity::DATA_AIR_SUPPLY_ID,
VarInt(air),
)],
Some(&bedrock_meta),
player.get_entity().set_synced_data(
pumpkin_data::tracked_data::entity::DATA_AIR_SUPPLY_ID,
VarInt(air),
);
player.get_entity().send_bedrock_actor_data(&bedrock_meta);
}
pub fn reset(&self, player: &Player) {

View File

@ -7,7 +7,7 @@ use pumpkin_data::{damage::DamageType, item_stack::ItemStack};
use pumpkin_nbt::{compound::NbtCompound, tag::NbtTag};
use pumpkin_protocol::{
codec::{item_stack_seralizer::ItemStackSerializer, var_int::VarInt},
java::client::play::{Metadata, MetadataSerializer},
java::client::play::MetadataSerializer,
ser::{NetworkWriteExt, WritingError},
};
use pumpkin_util::{math::vector3::Vector3, text::TextComponent};
@ -97,12 +97,9 @@ impl DisplayEntity {
pub fn set_interpolation_start_delta_ticks(&self, ticks: i32) {
self.interpolation_start_delta_ticks
.store(ticks, Ordering::Relaxed);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::START_INTERPOLATION,
VarInt(ticks),
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::display::START_INTERPOLATION,
VarInt(ticks),
);
}
@ -113,12 +110,9 @@ impl DisplayEntity {
pub fn set_interpolation_duration(&self, duration: i32) {
self.interpolation_duration
.store(duration, Ordering::Relaxed);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::INTERPOLATION_DURATION,
VarInt(duration),
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::display::INTERPOLATION_DURATION,
VarInt(duration),
);
}
@ -128,12 +122,9 @@ impl DisplayEntity {
pub fn set_teleport_duration(&self, duration: i32) {
self.teleport_duration.store(duration, Ordering::Relaxed);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::TELEPORT_DURATION,
VarInt(duration),
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::display::TELEPORT_DURATION,
VarInt(duration),
);
}
@ -149,12 +140,9 @@ impl DisplayEntity {
.translation
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner) = translation;
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::TRANSLATION,
Vector3fSerializer(translation.x, translation.y, translation.z),
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::display::TRANSLATION,
Vector3fSerializer(translation.x, translation.y, translation.z),
);
}
@ -170,12 +158,9 @@ impl DisplayEntity {
.scale
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner) = scale;
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::SCALE,
Vector3fSerializer(scale.x, scale.y, scale.z),
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::display::SCALE,
Vector3fSerializer(scale.x, scale.y, scale.z),
);
}
@ -191,17 +176,14 @@ impl DisplayEntity {
.left_rotation
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner) = left_rotation;
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::LEFT_ROTATION,
QuaternionfSerializer(
left_rotation[0],
left_rotation[1],
left_rotation[2],
left_rotation[3],
),
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::display::LEFT_ROTATION,
QuaternionfSerializer(
left_rotation[0],
left_rotation[1],
left_rotation[2],
left_rotation[3],
),
);
}
@ -217,17 +199,14 @@ impl DisplayEntity {
.right_rotation
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner) = right_rotation;
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::RIGHT_ROTATION,
QuaternionfSerializer(
right_rotation[0],
right_rotation[1],
right_rotation[2],
right_rotation[3],
),
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::display::RIGHT_ROTATION,
QuaternionfSerializer(
right_rotation[0],
right_rotation[1],
right_rotation[2],
right_rotation[3],
),
);
}
@ -237,13 +216,8 @@ impl DisplayEntity {
pub fn set_billboard(&self, billboard: u8) {
self.billboard.store(billboard, Ordering::Relaxed);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::BILLBOARD,
billboard,
)],
None,
);
self.entity
.set_synced_data(pumpkin_data::tracked_data::display::BILLBOARD, billboard);
}
pub fn get_brightness(&self) -> i32 {
@ -252,12 +226,9 @@ impl DisplayEntity {
pub fn set_brightness(&self, brightness: i32) {
self.brightness.store(brightness, Ordering::Relaxed);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::BRIGHTNESS,
VarInt(brightness),
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::display::BRIGHTNESS,
VarInt(brightness),
);
}
@ -273,13 +244,8 @@ impl DisplayEntity {
.view_range
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner) = view_range;
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::VIEW_RANGE,
view_range,
)],
None,
);
self.entity
.set_synced_data(pumpkin_data::tracked_data::display::VIEW_RANGE, view_range);
}
pub fn get_shadow_radius(&self) -> f32 {
@ -294,12 +260,9 @@ impl DisplayEntity {
.shadow_radius
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner) = shadow_radius;
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::SHADOW_RADIUS,
shadow_radius,
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::display::SHADOW_RADIUS,
shadow_radius,
);
}
@ -315,12 +278,9 @@ impl DisplayEntity {
.shadow_strength
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner) = shadow_strength;
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::SHADOW_STRENGTH,
shadow_strength,
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::display::SHADOW_STRENGTH,
shadow_strength,
);
}
@ -336,13 +296,8 @@ impl DisplayEntity {
.width
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner) = width;
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::WIDTH,
width,
)],
None,
);
self.entity
.set_synced_data(pumpkin_data::tracked_data::display::WIDTH, width);
}
pub fn get_display_height(&self) -> f32 {
@ -357,13 +312,8 @@ impl DisplayEntity {
.height
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner) = height;
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::HEIGHT,
height,
)],
None,
);
self.entity
.set_synced_data(pumpkin_data::tracked_data::display::HEIGHT, height);
}
pub fn get_glow_color_override(&self) -> i32 {
@ -372,12 +322,9 @@ impl DisplayEntity {
pub fn set_glow_color_override(&self, color: i32) {
self.glow_color_override.store(color, Ordering::Relaxed);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::GLOW_COLOR_OVERRIDE,
VarInt(color),
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::display::GLOW_COLOR_OVERRIDE,
VarInt(color),
);
}
@ -420,120 +367,69 @@ impl DisplayEntity {
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::START_INTERPOLATION,
VarInt(self.interpolation_start_delta_ticks.load(Ordering::Relaxed)),
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::display::START_INTERPOLATION,
VarInt(self.interpolation_start_delta_ticks.load(Ordering::Relaxed)),
);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::INTERPOLATION_DURATION,
VarInt(self.interpolation_duration.load(Ordering::Relaxed)),
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::display::INTERPOLATION_DURATION,
VarInt(self.interpolation_duration.load(Ordering::Relaxed)),
);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::TRANSLATION,
Vector3fSerializer(translation.x, translation.y, translation.z),
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::display::TRANSLATION,
Vector3fSerializer(translation.x, translation.y, translation.z),
);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::SCALE,
Vector3fSerializer(scale.x, scale.y, scale.z),
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::display::SCALE,
Vector3fSerializer(scale.x, scale.y, scale.z),
);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::LEFT_ROTATION,
QuaternionfSerializer(
left_rotation[0],
left_rotation[1],
left_rotation[2],
left_rotation[3],
),
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::display::LEFT_ROTATION,
QuaternionfSerializer(
left_rotation[0],
left_rotation[1],
left_rotation[2],
left_rotation[3],
),
);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::RIGHT_ROTATION,
QuaternionfSerializer(
right_rotation[0],
right_rotation[1],
right_rotation[2],
right_rotation[3],
),
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::display::RIGHT_ROTATION,
QuaternionfSerializer(
right_rotation[0],
right_rotation[1],
right_rotation[2],
right_rotation[3],
),
);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::BILLBOARD,
self.billboard.load(Ordering::Relaxed),
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::display::BILLBOARD,
self.billboard.load(Ordering::Relaxed),
);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::BRIGHTNESS,
VarInt(self.brightness.load(Ordering::Relaxed)),
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::display::BRIGHTNESS,
VarInt(self.brightness.load(Ordering::Relaxed)),
);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::VIEW_RANGE,
view_range,
)],
None,
self.entity
.set_synced_data(pumpkin_data::tracked_data::display::VIEW_RANGE, view_range);
self.entity.set_synced_data(
pumpkin_data::tracked_data::display::SHADOW_RADIUS,
shadow_radius,
);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::SHADOW_RADIUS,
shadow_radius,
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::display::SHADOW_STRENGTH,
shadow_strength,
);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::SHADOW_STRENGTH,
shadow_strength,
)],
None,
self.entity
.set_synced_data(pumpkin_data::tracked_data::display::WIDTH, width);
self.entity
.set_synced_data(pumpkin_data::tracked_data::display::HEIGHT, height);
self.entity.set_synced_data(
pumpkin_data::tracked_data::display::TELEPORT_DURATION,
VarInt(self.teleport_duration.load(Ordering::Relaxed)),
);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::WIDTH,
width,
)],
None,
);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::HEIGHT,
height,
)],
None,
);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::TELEPORT_DURATION,
VarInt(self.teleport_duration.load(Ordering::Relaxed)),
)],
None,
);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::display::GLOW_COLOR_OVERRIDE,
VarInt(self.glow_color_override.load(Ordering::Relaxed)),
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::display::GLOW_COLOR_OVERRIDE,
VarInt(self.glow_color_override.load(Ordering::Relaxed)),
);
}
@ -785,12 +681,9 @@ impl BlockDisplayEntity {
pub fn set_block_state(&self, block_state: i32) {
self.block_state.store(block_state, Ordering::Relaxed);
self.display.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::block_display::BLOCK_STATE,
VarInt(block_state),
)],
None,
self.display.entity.set_synced_data(
pumpkin_data::tracked_data::block_display::BLOCK_STATE,
VarInt(block_state),
);
}
}
@ -812,12 +705,9 @@ impl EntityBase for BlockDisplayEntity {
fn init_data_tracker(&self) {
self.display.init_display_data_tracker();
self.display.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::block_display::BLOCK_STATE,
VarInt(self.block_state.load(Ordering::Relaxed)),
)],
None,
self.display.entity.set_synced_data(
pumpkin_data::tracked_data::block_display::BLOCK_STATE,
VarInt(self.block_state.load(Ordering::Relaxed)),
);
}
@ -889,12 +779,9 @@ impl ItemDisplayEntity {
.item_stack
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner) = item.clone();
self.display.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::item_display::ITEM,
ItemStackSerializer::from(item),
)],
None,
self.display.entity.set_synced_data(
pumpkin_data::tracked_data::item_display::ITEM,
ItemStackSerializer::from(item),
);
}
@ -904,13 +791,9 @@ impl ItemDisplayEntity {
pub fn set_item_display_mode(&self, mode: u8) {
self.item_display.store(mode, Ordering::Relaxed);
self.display.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::item_display::ITEM_DISPLAY,
mode,
)],
None,
);
self.display
.entity
.set_synced_data(pumpkin_data::tracked_data::item_display::ITEM_DISPLAY, mode);
}
}
@ -953,24 +836,18 @@ impl EntityBase for ItemDisplayEntity {
fn init_data_tracker(&self) {
self.display.init_display_data_tracker();
self.display.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::item_display::ITEM,
ItemStackSerializer::from(
self.item_stack
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.clone(),
),
)],
None,
self.display.entity.set_synced_data(
pumpkin_data::tracked_data::item_display::ITEM,
ItemStackSerializer::from(
self.item_stack
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.clone(),
),
);
self.display.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::item_display::ITEM_DISPLAY,
self.item_display.load(Ordering::Relaxed),
)],
None,
self.display.entity.set_synced_data(
pumpkin_data::tracked_data::item_display::ITEM_DISPLAY,
self.item_display.load(Ordering::Relaxed),
);
}
@ -1048,13 +925,9 @@ impl TextDisplayEntity {
.text
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner) = text.clone();
self.display.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::text_display::TEXT,
text,
)],
None,
);
self.display
.entity
.set_synced_data(pumpkin_data::tracked_data::text_display::TEXT, text);
}
pub fn get_line_width(&self) -> i32 {
@ -1063,12 +936,9 @@ impl TextDisplayEntity {
pub fn set_line_width(&self, width: i32) {
self.line_width.store(width, Ordering::Relaxed);
self.display.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::text_display::LINE_WIDTH,
VarInt(width),
)],
None,
self.display.entity.set_synced_data(
pumpkin_data::tracked_data::text_display::LINE_WIDTH,
VarInt(width),
);
}
@ -1078,12 +948,9 @@ impl TextDisplayEntity {
pub fn set_background_color(&self, color: i32) {
self.background.store(color, Ordering::Relaxed);
self.display.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::text_display::BACKGROUND,
VarInt(color),
)],
None,
self.display.entity.set_synced_data(
pumpkin_data::tracked_data::text_display::BACKGROUND,
VarInt(color),
);
}
@ -1093,12 +960,9 @@ impl TextDisplayEntity {
pub fn set_text_opacity(&self, opacity: i8) {
self.text_opacity.store(opacity, Ordering::Relaxed);
self.display.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::text_display::TEXT_OPACITY,
opacity as u8,
)],
None,
self.display.entity.set_synced_data(
pumpkin_data::tracked_data::text_display::TEXT_OPACITY,
opacity as u8,
);
}
@ -1114,12 +978,9 @@ impl TextDisplayEntity {
flags &= !1;
}
self.flags.store(flags, Ordering::Relaxed);
self.display.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::text_display::TEXT_DISPLAY_FLAGS,
flags,
)],
None,
self.display.entity.set_synced_data(
pumpkin_data::tracked_data::text_display::TEXT_DISPLAY_FLAGS,
flags,
);
}
@ -1135,12 +996,9 @@ impl TextDisplayEntity {
flags &= !2;
}
self.flags.store(flags, Ordering::Relaxed);
self.display.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::text_display::TEXT_DISPLAY_FLAGS,
flags,
)],
None,
self.display.entity.set_synced_data(
pumpkin_data::tracked_data::text_display::TEXT_DISPLAY_FLAGS,
flags,
);
}
@ -1156,12 +1014,9 @@ impl TextDisplayEntity {
flags &= !4;
}
self.flags.store(flags, Ordering::Relaxed);
self.display.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::text_display::TEXT_DISPLAY_FLAGS,
flags,
)],
None,
self.display.entity.set_synced_data(
pumpkin_data::tracked_data::text_display::TEXT_DISPLAY_FLAGS,
flags,
);
}
@ -1184,12 +1039,9 @@ impl TextDisplayEntity {
flags |= 16;
}
self.flags.store(flags, Ordering::Relaxed);
self.display.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::text_display::TEXT_DISPLAY_FLAGS,
flags,
)],
None,
self.display.entity.set_synced_data(
pumpkin_data::tracked_data::text_display::TEXT_DISPLAY_FLAGS,
flags,
);
}
}
@ -1273,40 +1125,24 @@ impl EntityBase for TextDisplayEntity {
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.clone();
self.display.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::text_display::TEXT,
text,
)],
None,
self.display
.entity
.set_synced_data(pumpkin_data::tracked_data::text_display::TEXT, text);
self.display.entity.set_synced_data(
pumpkin_data::tracked_data::text_display::LINE_WIDTH,
VarInt(self.line_width.load(Ordering::Relaxed)),
);
self.display.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::text_display::LINE_WIDTH,
VarInt(self.line_width.load(Ordering::Relaxed)),
)],
None,
self.display.entity.set_synced_data(
pumpkin_data::tracked_data::text_display::BACKGROUND,
VarInt(self.background.load(Ordering::Relaxed)),
);
self.display.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::text_display::BACKGROUND,
VarInt(self.background.load(Ordering::Relaxed)),
)],
None,
self.display.entity.set_synced_data(
pumpkin_data::tracked_data::text_display::TEXT_OPACITY,
self.text_opacity.load(Ordering::Relaxed) as u8,
);
self.display.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::text_display::TEXT_OPACITY,
self.text_opacity.load(Ordering::Relaxed) as u8,
)],
None,
);
self.display.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::text_display::TEXT_DISPLAY_FLAGS,
self.flags.load(Ordering::Relaxed),
)],
None,
self.display.entity.set_synced_data(
pumpkin_data::tracked_data::text_display::TEXT_DISPLAY_FLAGS,
self.flags.load(Ordering::Relaxed),
);
}

View File

@ -6,7 +6,6 @@ use pumpkin_data::{
damage::DamageType,
tag::{self, Taggable},
};
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::math::{position::BlockPos, vector3::Vector3};
pub struct EndCrystalEntity {
@ -29,12 +28,9 @@ impl EndCrystalEntity {
pub fn set_show_bottom(&self, show_bottom: bool) {
self.show_bottom.store(show_bottom, Ordering::Relaxed);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::end_crystal::SHOW_BOTTOM,
show_bottom,
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::end_crystal::SHOW_BOTTOM,
show_bottom,
);
}
@ -47,12 +43,9 @@ impl EndCrystalEntity {
.beam_target
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner) = beam_target;
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::end_crystal::BEAM_TARGET,
beam_target,
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::end_crystal::BEAM_TARGET,
beam_target,
);
}

View File

@ -129,12 +129,9 @@ impl ItemFrameEntity {
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner) = item_stack;
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::item_frame::ITEM,
&item_serializer,
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::item_frame::ITEM,
item_serializer,
);
if play_sound {
@ -156,13 +153,8 @@ impl ItemFrameEntity {
let rot = rotation % 8;
self.rotation.store(rot, Ordering::Relaxed);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::item_frame::ROTATION,
rot as i32,
)],
None,
);
self.entity
.set_synced_data(pumpkin_data::tracked_data::item_frame::ROTATION, rot as i32);
if update_neighbours {
let world = self.entity.world.load();
@ -247,12 +239,9 @@ impl ItemFrameEntity {
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner) = ItemStack::EMPTY.clone();
let item_serializer = ItemStackSerializer::from(ItemStack::EMPTY.clone());
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::item_frame::ITEM,
&item_serializer,
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::item_frame::ITEM,
item_serializer,
);
let is_creative_player = caused_by.is_some_and(|s| {
@ -343,20 +332,12 @@ impl EntityBase for ItemFrameEntity {
);
let rotation = self.get_rotation() as i32;
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::item_frame::ITEM,
&item_serializer,
)],
None,
);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::item_frame::ROTATION,
rotation,
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::item_frame::ITEM,
item_serializer,
);
self.entity
.set_synced_data(pumpkin_data::tracked_data::item_frame::ROTATION, rotation);
}
fn send_java_spawn_packet(&self, client: &crate::net::java::JavaClient) {

View File

@ -2,7 +2,6 @@ use pumpkin_data::Block;
use pumpkin_data::BlockStateId;
use pumpkin_data::damage::DamageType;
use pumpkin_data::entity::EntityType;
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::math::position::BlockPos;
use pumpkin_world::world::BlockFlags;
use std::sync::{Arc, atomic::Ordering};
@ -74,12 +73,9 @@ impl EntityBase for FallingEntity {
}
fn init_data_tracker(&self) {
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::falling_block::START_POS,
self.entity.block_pos.load(),
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::falling_block::START_POS,
self.entity.block_pos.load(),
);
}

View File

@ -6,7 +6,6 @@ use uuid::Uuid;
use pumpkin_data::{damage::DamageType, item_stack::ItemStack};
use pumpkin_nbt::{compound::NbtCompound, tag::NbtTag};
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::math::{
boundingbox::{BoundingBox, EntityDimensions},
vector3::Vector3,
@ -82,13 +81,8 @@ impl InteractionEntity {
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner) = width;
self.update_dimensions();
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::interaction::WIDTH,
width,
)],
None,
);
self.entity
.set_synced_data(pumpkin_data::tracked_data::interaction::WIDTH, width);
}
pub fn get_height(&self) -> f32 {
@ -104,13 +98,8 @@ impl InteractionEntity {
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner) = height;
self.update_dimensions();
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::interaction::HEIGHT,
height,
)],
None,
);
self.entity
.set_synced_data(pumpkin_data::tracked_data::interaction::HEIGHT, height);
}
pub fn get_response(&self) -> bool {
@ -119,13 +108,8 @@ impl InteractionEntity {
pub fn set_response(&self, response: bool) {
self.response.store(response, Ordering::Relaxed);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::interaction::RESPONSE,
response,
)],
None,
);
self.entity
.set_synced_data(pumpkin_data::tracked_data::interaction::RESPONSE, response);
}
pub fn update_dimensions(&self) {
@ -249,27 +233,12 @@ impl EntityBase for InteractionEntity {
.unwrap_or_else(std::sync::PoisonError::into_inner);
let response = self.response.load(Ordering::Relaxed);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::interaction::WIDTH,
width,
)],
None,
);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::interaction::HEIGHT,
height,
)],
None,
);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::interaction::RESPONSE,
response,
)],
None,
);
self.entity
.set_synced_data(pumpkin_data::tracked_data::interaction::WIDTH, width);
self.entity
.set_synced_data(pumpkin_data::tracked_data::interaction::HEIGHT, height);
self.entity
.set_synced_data(pumpkin_data::tracked_data::interaction::RESPONSE, response);
}
fn get_entity(&self) -> &Entity {

View File

@ -465,17 +465,14 @@ impl EntityBase for ItemEntity {
}
fn init_data_tracker(&self) {
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::item::ITEM,
&ItemStackSerializer::from(
self.item_stack
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.clone(),
),
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::item::ITEM,
ItemStackSerializer::from(
self.item_stack
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.clone(),
),
);
}

View File

@ -59,7 +59,7 @@ use pumpkin_protocol::java::client::play::{
};
use pumpkin_protocol::{
codec::item_stack_seralizer::ItemStackSerializer,
java::client::play::{CSetEquipment, Metadata, MetadataSerializer},
java::client::play::{CSetEquipment, MetadataSerializer},
ser::{NetworkWriteExt, WritingError},
};
use pumpkin_util::math::boundingbox::BoundingBox;
@ -129,11 +129,13 @@ pub struct LivingEntity {
pub attributes: RwLock<FxHashMap<u8, AttributeInstance>>,
}
#[derive(Clone)]
struct EffectParticle {
particle_id: VarInt,
color: i32,
}
#[derive(Clone)]
struct EffectParticles(Vec<EffectParticle>);
impl MetadataSerializer for EffectParticles {
@ -475,13 +477,11 @@ impl LivingEntity {
meta
});
self.entity.send_meta_data(
&[Metadata::new(
tracked_data::living_entity::DATA_LIVING_ENTITY_FLAGS,
b,
)],
bedrock_meta.as_ref(),
);
self.entity
.set_synced_data(tracked_data::living_entity::DATA_LIVING_ENTITY_FLAGS, b);
if let Some(bedrock_meta) = &bedrock_meta {
self.entity.send_bedrock_actor_data(bedrock_meta);
}
}
pub fn clear_active_hand(&self) {
@ -569,13 +569,8 @@ impl LivingEntity {
let clamped = health.max(0.0).min(max_health);
self.health.store(clamped);
// tell everyone entities health changed
self.entity.send_meta_data(
&[Metadata::new(
tracked_data::living_entity::DATA_HEALTH_ID,
clamped,
)],
None,
);
self.entity
.set_synced_data(tracked_data::living_entity::DATA_HEALTH_ID, clamped);
}
/// Returns the current maximum health for this entity
@ -623,13 +618,8 @@ impl LivingEntity {
// Send absorption metadata for players (visual yellow hearts)
if self.entity.entity_type == &EntityType::PLAYER {
self.entity.send_meta_data(
&[Metadata::new(
tracked_data::player::DATA_PLAYER_ABSORPTION_ID,
new_abs,
)],
None,
);
self.entity
.set_synced_data(tracked_data::player::DATA_PLAYER_ABSORPTION_ID, new_abs);
}
}
@ -900,21 +890,11 @@ impl LivingEntity {
.all(|effect| effect.ambient);
drop(effects);
self.entity.send_meta_data(
&[Metadata::new(
tracked_data::living_entity::EFFECT_PARTICLES,
particles,
)],
None,
);
self.entity
.set_synced_data(tracked_data::living_entity::EFFECT_PARTICLES, particles);
if has_effects {
self.entity.send_meta_data(
&[Metadata::new(
tracked_data::living_entity::EFFECT_AMBIENCE_ID,
ambient,
)],
None,
);
self.entity
.set_synced_data(tracked_data::living_entity::EFFECT_AMBIENCE_ID, ambient);
}
}
@ -2191,13 +2171,8 @@ impl LivingEntity {
// Clear any absorption
self.absorption.store(0.0);
// Send health metadata
self.entity.send_meta_data(
&[Metadata::new(
tracked_data::living_entity::DATA_HEALTH_ID,
max_health,
)],
None,
);
self.entity
.set_synced_data(tracked_data::living_entity::DATA_HEALTH_ID, max_health);
self.reset_effects_and_attributes();
@ -3489,7 +3464,7 @@ mod tests {
show_icon: true,
blend: false,
};
let metadata = Metadata::new(
let metadata = pumpkin_protocol::java::client::play::Metadata::new(
tracked_data::living_entity::EFFECT_PARTICLES,
EffectParticles(vec![EffectParticle::from_effect(&effect)]),
);

View File

@ -7,7 +7,6 @@ use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_data::tag::{self, Taggable};
use pumpkin_data::tracked_data;
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::math::position::BlockPos;
use pumpkin_util::math::vector3::Vector3;
use pumpkin_world::chunk::ChunkHeightmapType;
@ -71,10 +70,10 @@ impl BatEntity {
pub fn set_roosting(&self, roosting: bool) {
self.roosting.store(roosting, Relaxed);
let flags: u8 = if roosting { ROOSTING_FLAG } else { 0 };
self.mob_entity.living_entity.entity.send_meta_data(
&[Metadata::new(tracked_data::bat::DATA_ID_FLAGS, flags)],
None,
);
self.mob_entity
.living_entity
.entity
.set_synced_data(tracked_data::bat::DATA_ID_FLAGS, flags);
}
fn tick_ambient_sound(&self, world: &World, pos: &Vector3<f64>) {
@ -211,10 +210,7 @@ impl Mob for BatEntity {
fn mob_init_data_tracker(&self) {
let entity = self.get_entity();
let flags: u8 = if self.is_roosting() { ROOSTING_FLAG } else { 0 };
entity.send_meta_data(
&[Metadata::new(tracked_data::bat::DATA_ID_FLAGS, flags)],
None,
);
entity.set_synced_data(tracked_data::bat::DATA_ID_FLAGS, flags);
}
fn mob_write_nbt(&self, nbt: &mut NbtCompound) {

View File

@ -3,7 +3,6 @@ use std::sync::{Arc, Weak};
use pumpkin_data::damage::DamageType;
use pumpkin_data::entity::EntityType;
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::math::vector3::Vector3;
use crate::entity::{
@ -78,13 +77,10 @@ impl BlazeEntity {
pub fn set_charged(&self, charged: bool) {
self.is_charged.store(charged, Ordering::Relaxed);
let flags = i8::from(charged);
self.entity.living_entity.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::blaze::DATA_FLAGS_ID,
flags,
)],
None,
);
self.entity
.living_entity
.entity
.set_synced_data(pumpkin_data::tracked_data::blaze::DATA_FLAGS_ID, flags);
}
}

View File

@ -12,7 +12,7 @@ use pumpkin_data::item::Item;
use pumpkin_data::particle::Particle;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::{CEntityStatus, Metadata};
use pumpkin_protocol::java::client::play::CEntityStatus;
use pumpkin_util::math::position::BlockPos;
use pumpkin_util::math::vector3::Vector3;
@ -155,13 +155,10 @@ impl CreakingEntity {
pub fn set_can_move(&self, can_move: bool) {
self.can_move.store(can_move, Ordering::Relaxed);
self.mob_entity.living_entity.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::creaking::CAN_MOVE,
can_move,
)],
None,
);
self.mob_entity
.living_entity
.entity
.set_synced_data(pumpkin_data::tracked_data::creaking::CAN_MOVE, can_move);
}
pub fn is_active(&self) -> bool {
@ -170,13 +167,10 @@ impl CreakingEntity {
pub fn set_is_active(&self, active: bool) {
self.is_active.store(active, Ordering::Relaxed);
self.mob_entity.living_entity.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::creaking::IS_ACTIVE,
active,
)],
None,
);
self.mob_entity
.living_entity
.entity
.set_synced_data(pumpkin_data::tracked_data::creaking::IS_ACTIVE, active);
}
pub fn is_tearing_down(&self) -> bool {
@ -185,13 +179,10 @@ impl CreakingEntity {
pub fn set_tearing_down(&self) {
self.is_tearing_down.store(true, Ordering::Relaxed);
self.mob_entity.living_entity.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::creaking::IS_TEARING_DOWN,
true,
)],
None,
);
self.mob_entity
.living_entity
.entity
.set_synced_data(pumpkin_data::tracked_data::creaking::IS_TEARING_DOWN, true);
}
pub fn get_home_pos(&self) -> Option<BlockPos> {
@ -210,13 +201,10 @@ impl CreakingEntity {
.position_target_range
.store(-1, Ordering::Relaxed);
}
self.mob_entity.living_entity.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::creaking::HOME_POS,
pos,
)],
None,
);
self.mob_entity
.living_entity
.entity
.set_synced_data(pumpkin_data::tracked_data::creaking::HOME_POS, pos);
}
pub fn stop_in_place(&self) {

View File

@ -10,7 +10,7 @@ use pumpkin_data::{
sound::{Sound, SoundCategory},
};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::{codec::var_int::VarInt, java::client::play::Metadata};
use pumpkin_protocol::codec::var_int::VarInt;
use crate::entity::{
Entity, EntityBase,
@ -92,13 +92,10 @@ impl CreeperEntity {
pub fn set_fuse_speed(&self, speed: i32) {
self.fuse_speed.store(speed, Ordering::Relaxed);
self.mob_entity.living_entity.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::creeper::FUSE_ID,
VarInt(speed),
)],
None,
);
self.mob_entity
.living_entity
.entity
.set_synced_data(pumpkin_data::tracked_data::creeper::FUSE_ID, VarInt(speed));
}
pub fn explode(&self) {
@ -162,13 +159,10 @@ impl Mob for CreeperEntity {
lightning: &crate::entity::lightning::LightningBoltEntity,
) {
self.charged.store(true, Ordering::Relaxed);
self.mob_entity.living_entity.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::creeper::CHARGED,
true,
)],
None,
);
self.mob_entity
.living_entity
.entity
.set_synced_data(pumpkin_data::tracked_data::creeper::CHARGED, true);
self.mob_entity
.living_entity
.on_lightning_strike(caller, lightning);
@ -231,13 +225,7 @@ impl Mob for CreeperEntity {
);
self.ignited.store(true, Ordering::Relaxed);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::creeper::IS_IGNITED,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::creeper::IS_IGNITED, true);
if player.gamemode.load() != pumpkin_util::GameMode::Creative {
// TODO: Handle DamageResult::Broken to broadcast item break and update player slot.
@ -256,13 +244,7 @@ impl CreeperEntity {
pub fn set_charged(&self, charged: bool) {
self.charged.store(charged, Ordering::Relaxed);
let entity = &self.mob_entity.living_entity.entity;
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::creeper::CHARGED,
charged,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::creeper::CHARGED, charged);
}
pub fn is_ignited(&self) -> bool {
@ -272,13 +254,7 @@ impl CreeperEntity {
pub fn set_ignited(&self, ignited: bool) {
self.ignited.store(ignited, Ordering::Relaxed);
let entity = &self.mob_entity.living_entity.entity;
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::creeper::IS_IGNITED,
ignited,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::creeper::IS_IGNITED, ignited);
}
pub fn get_fuse(&self) -> i32 {

View File

@ -19,7 +19,7 @@ use pumpkin_data::{
tag::Taggable,
};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::{codec::var_int::VarInt, java::client::play::Metadata};
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_util::math::{boundingbox::BoundingBox, position::BlockPos, vector3::Vector3};
use rand::RngExt;
@ -290,13 +290,10 @@ impl EndermanEntity {
pub fn set_angry(&self, angry: bool) {
self.angry.store(angry, Ordering::Relaxed);
self.mob_entity.living_entity.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::enderman::CREEPY,
angry,
)],
None,
);
self.mob_entity
.living_entity
.entity
.set_synced_data(pumpkin_data::tracked_data::enderman::CREEPY, angry);
}
pub fn is_angry(&self) -> bool {
@ -305,25 +302,19 @@ impl EndermanEntity {
pub fn set_provoked(&self, provoked: bool) {
self.provoked.store(provoked, Ordering::Relaxed);
self.mob_entity.living_entity.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::enderman::STARED_AT,
provoked,
)],
None,
);
self.mob_entity
.living_entity
.entity
.set_synced_data(pumpkin_data::tracked_data::enderman::STARED_AT, provoked);
}
pub fn set_carried_block(&self, block_state: Option<BlockStateId>) {
self.carried_block.store(block_state);
let value = block_state.map_or(VarInt(0), |id| VarInt(id.as_u16() as i32));
self.mob_entity.living_entity.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::enderman::CARRY_STATE,
value,
)],
None,
);
self.mob_entity
.living_entity
.entity
.set_synced_data(pumpkin_data::tracked_data::enderman::CARRY_STATE, value);
}
pub fn get_carried_block(&self) -> Option<BlockStateId> {

View File

@ -6,7 +6,6 @@ use uuid::Uuid;
use pumpkin_data::entity::EntityType;
use pumpkin_data::sound::Sound;
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::math::vector3::Vector3;
use crate::entity::{
@ -129,12 +128,9 @@ impl EvokerEntity {
pub fn set_is_casting_spell(&self, spell: IllagerSpell) {
self.current_spell.store(spell as u8, Ordering::Relaxed);
let entity = &self.mob_entity.living_entity.entity;
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::evoker::SPELL_CASTING_ID,
spell as u8 as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::evoker::SPELL_CASTING_ID,
spell as u8 as i8,
);
}

View File

@ -6,7 +6,6 @@ use pumpkin_data::entity::EntityType;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_data::tracked_data;
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::math::position::BlockPos;
use pumpkin_util::math::vector3::Vector3;
use rand::RngExt;
@ -92,13 +91,7 @@ impl GhastEntity {
pub fn set_charging(&self, charging: bool) {
self.is_charging.store(charging, Ordering::Relaxed);
let entity = &self.mob_entity.living_entity.entity;
entity.send_meta_data(
&[Metadata::new(
tracked_data::ghast::DATA_IS_CHARGING,
charging,
)],
None,
);
entity.set_synced_data(tracked_data::ghast::DATA_IS_CHARGING, charging);
}
#[must_use]
@ -144,10 +137,7 @@ impl Mob for GhastEntity {
fn mob_init_data_tracker(&self) {
let entity = self.get_entity();
if self.is_charging() {
entity.send_meta_data(
&[Metadata::new(tracked_data::ghast::DATA_IS_CHARGING, true)],
None,
);
entity.set_synced_data(tracked_data::ghast::DATA_IS_CHARGING, true);
}
}

View File

@ -6,7 +6,6 @@ use pumpkin_data::dimension::Dimension;
use pumpkin_data::entity::EntityType;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::math::vector3::Vector3;
use crate::entity::{
@ -114,12 +113,9 @@ impl HoglinEntity {
pub fn set_immune_to_zombification(&self, immune: bool) {
self.immune_to_zombification
.store(immune, Ordering::Relaxed);
self.mob_entity.living_entity.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::hoglin::DATA_IMMUNE_TO_ZOMBIFICATION,
immune,
)],
None,
self.mob_entity.living_entity.entity.set_synced_data(
pumpkin_data::tracked_data::hoglin::DATA_IMMUNE_TO_ZOMBIFICATION,
immune,
);
}

View File

@ -16,7 +16,7 @@ use pumpkin_data::tag::{self, Taggable};
use pumpkin_data::tracked_data;
use pumpkin_data::{Block, BlockDirection};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::{CHeadRot, CUpdateEntityRot, Metadata};
use pumpkin_protocol::java::client::play::{CHeadRot, CUpdateEntityRot};
use pumpkin_util::Difficulty;
use pumpkin_util::math::boundingbox::BoundingBox;
use pumpkin_util::math::position::BlockPos;
@ -330,10 +330,9 @@ impl MobEntity {
if new_b != old_b {
self.mob_flags.store(new_b, Ordering::Relaxed);
self.living_entity.entity.send_meta_data(
&[Metadata::new(tracked_data::mob::DATA_MOB_FLAGS_ID, new_b)],
None,
);
self.living_entity
.entity
.set_synced_data(tracked_data::mob::DATA_MOB_FLAGS_ID, new_b);
}
}
@ -669,6 +668,14 @@ pub trait Mob: EntityBase + Send + Sync {
rand::rng()
}
fn requires_custom_persistence(&self) -> bool {
false
}
fn remove_when_far_away(&self, _distance_sq: f64) -> bool {
true
}
fn get_max_look_yaw_change(&self) -> f32 {
10.0
}
@ -1052,10 +1059,7 @@ pub trait Mob: EntityBase + Send + Sync {
let entity = self.get_entity();
let is_baby = entity.age.load(std::sync::atomic::Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(tracked_data::ageable_mob::DATA_BABY_ID, true)],
None,
);
entity.set_synced_data(tracked_data::ageable_mob::DATA_BABY_ID, true);
}
}

View File

@ -13,7 +13,6 @@ use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_data::tracked_data;
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_nbt::tag::NbtTag;
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::math::boundingbox::EntityDimensions;
use pumpkin_util::math::position::BlockPos;
@ -171,13 +170,10 @@ impl PiglinEntity {
pub fn set_immune_to_zombification(&self, immune: bool) {
self.immune_to_zombification
.store(immune, Ordering::Relaxed);
self.mob_entity.living_entity.entity.send_meta_data(
&[Metadata::new(
tracked_data::piglin::DATA_IMMUNE_TO_ZOMBIFICATION,
immune,
)],
None,
);
self.mob_entity
.living_entity
.entity
.set_synced_data(tracked_data::piglin::DATA_IMMUNE_TO_ZOMBIFICATION, immune);
}
#[must_use]
@ -200,10 +196,7 @@ impl PiglinEntity {
pub fn set_baby(&self, baby: bool) {
self.is_baby.store(baby, Ordering::Relaxed);
let entity = &self.mob_entity.living_entity.entity;
entity.send_meta_data(
&[Metadata::new(tracked_data::piglin::DATA_BABY_ID, baby)],
None,
);
entity.set_synced_data(tracked_data::piglin::DATA_BABY_ID, baby);
if baby {
entity.entity_dimension.store(Self::BABY_DIMENSIONS);
} else {
@ -219,13 +212,10 @@ impl PiglinEntity {
pub fn set_charging_crossbow(&self, is_charging: bool) {
self.is_charging_crossbow
.store(is_charging, Ordering::Relaxed);
self.mob_entity.living_entity.entity.send_meta_data(
&[Metadata::new(
tracked_data::piglin::DATA_IS_CHARGING_CROSSBOW,
is_charging,
)],
None,
);
self.mob_entity
.living_entity
.entity
.set_synced_data(tracked_data::piglin::DATA_IS_CHARGING_CROSSBOW, is_charging);
}
#[must_use]
@ -235,13 +225,10 @@ impl PiglinEntity {
pub fn set_dancing(&self, is_dancing: bool) {
self.is_dancing.store(is_dancing, Ordering::Relaxed);
self.mob_entity.living_entity.entity.send_meta_data(
&[Metadata::new(
tracked_data::piglin::DATA_IS_DANCING,
is_dancing,
)],
None,
);
self.mob_entity
.living_entity
.entity
.set_synced_data(tracked_data::piglin::DATA_IS_DANCING, is_dancing);
}
#[must_use]
@ -537,27 +524,17 @@ impl Mob for PiglinEntity {
fn mob_init_data_tracker(&self) {
let entity = self.get_entity();
let mut meta = Vec::new();
if self.is_immune_to_zombification() {
meta.push(Metadata::new(
tracked_data::piglin::DATA_IMMUNE_TO_ZOMBIFICATION,
true,
));
entity.set_synced_data(tracked_data::piglin::DATA_IMMUNE_TO_ZOMBIFICATION, true);
}
if self.is_baby() {
meta.push(Metadata::new(tracked_data::piglin::DATA_BABY_ID, true));
entity.set_synced_data(tracked_data::piglin::DATA_BABY_ID, true);
}
if self.is_charging_crossbow() {
meta.push(Metadata::new(
tracked_data::piglin::DATA_IS_CHARGING_CROSSBOW,
true,
));
entity.set_synced_data(tracked_data::piglin::DATA_IS_CHARGING_CROSSBOW, true);
}
if self.is_dancing() {
meta.push(Metadata::new(tracked_data::piglin::DATA_IS_DANCING, true));
}
if !meta.is_empty() {
entity.send_meta_data(&meta, None);
entity.set_synced_data(tracked_data::piglin::DATA_IS_DANCING, true);
}
}

View File

@ -9,7 +9,6 @@ use pumpkin_data::entity::EntityType;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_data::tracked_data;
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::math::position::BlockPos;
use crate::entity::{
@ -98,12 +97,9 @@ impl PiglinBruteEntity {
pub fn set_immune_to_zombification(&self, immune: bool) {
self.immune_to_zombification
.store(immune, Ordering::Relaxed);
self.mob_entity.living_entity.entity.send_meta_data(
&[Metadata::new(
tracked_data::piglin_brute::DATA_IMMUNE_TO_ZOMBIFICATION,
immune,
)],
None,
self.mob_entity.living_entity.entity.set_synced_data(
tracked_data::piglin_brute::DATA_IMMUNE_TO_ZOMBIFICATION,
immune,
);
}
@ -185,12 +181,9 @@ impl Mob for PiglinBruteEntity {
fn mob_init_data_tracker(&self) {
let entity = self.get_entity();
if self.is_immune_to_zombification() {
entity.send_meta_data(
&[Metadata::new(
tracked_data::piglin_brute::DATA_IMMUNE_TO_ZOMBIFICATION,
true,
)],
None,
entity.set_synced_data(
tracked_data::piglin_brute::DATA_IMMUNE_TO_ZOMBIFICATION,
true,
);
}
}

View File

@ -9,7 +9,6 @@ use pumpkin_data::sound::Sound;
use pumpkin_data::tracked_data;
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_nbt::tag::NbtTag;
use pumpkin_protocol::java::client::play::Metadata;
use crate::entity::{
Entity, EntityBase,
@ -105,13 +104,10 @@ impl PillagerEntity {
pub fn set_charging_crossbow(&self, is_charging: bool) {
self.is_charging_crossbow
.store(is_charging, Ordering::Relaxed);
self.mob_entity.living_entity.entity.send_meta_data(
&[Metadata::new(
tracked_data::pillager::IS_CHARGING_CROSSBOW,
is_charging,
)],
None,
);
self.mob_entity
.living_entity
.entity
.set_synced_data(tracked_data::pillager::IS_CHARGING_CROSSBOW, is_charging);
}
pub fn add_to_inventory(&self, item: ItemStack) -> Option<ItemStack> {

View File

@ -8,7 +8,6 @@ use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::sound::Sound;
use pumpkin_data::tracked_data;
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::math::vector3::Vector3;
use pumpkin_util::text::TextComponent;
@ -93,13 +92,7 @@ pub trait Raider: PatrollingMonster {
.is_celebrating
.store(celebrating, Ordering::Relaxed);
let entity = &self.get_mob_entity().living_entity.entity;
entity.send_meta_data(
&[Metadata::new(
tracked_data::pillager::IS_CELEBRATING,
celebrating,
)],
None,
);
entity.set_synced_data(tracked_data::pillager::IS_CELEBRATING, celebrating);
}
fn has_active_raid(&self) -> bool {

View File

@ -8,7 +8,7 @@ use pumpkin_data::entity::EntityType;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_protocol::java::client::play::{CEntityPositionSync, Metadata};
use pumpkin_protocol::java::client::play::CEntityPositionSync;
use pumpkin_util::math::position::BlockPos;
use pumpkin_util::math::vector3::Vector3;
@ -113,12 +113,9 @@ impl ShulkerEntity {
pub fn set_attach_face(&self, face: BlockDirection) {
self.attach_face.store(face as u8, Ordering::Relaxed);
let entity = &self.mob_entity.living_entity.entity;
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::shulker::ATTACH_FACE_ID,
VarInt(face as i32),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::shulker::ATTACH_FACE_ID,
VarInt(face as i32),
);
}
@ -131,13 +128,7 @@ impl ShulkerEntity {
let val = color.unwrap_or(NO_COLOR);
self.color.store(val, Ordering::Relaxed);
let entity = &self.mob_entity.living_entity.entity;
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::shulker::COLOR,
val as i8,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::shulker::COLOR, val as i8);
}
pub fn get_raw_peek(&self) -> u8 {
@ -169,13 +160,7 @@ impl ShulkerEntity {
self.peek_amount.store(amount, Ordering::Relaxed);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::shulker::PEEK_ID,
amount,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::shulker::PEEK_ID, amount);
}
pub fn is_closed(&self) -> bool {

View File

@ -2,7 +2,6 @@ use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use pumpkin_protocol::java::client::play::Metadata;
use crate::entity::{
Entity, EntityBase,
@ -74,13 +73,10 @@ impl SpiderEntity {
pub fn set_climbing(&self, climbing: bool) {
if self.is_climbing.swap(climbing, Ordering::Relaxed) != climbing {
let flags = i8::from(climbing);
self.mob_entity.living_entity.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::spider::DATA_FLAGS_ID,
flags,
)],
None,
);
self.mob_entity
.living_entity
.entity
.set_synced_data(pumpkin_data::tracked_data::spider::DATA_FLAGS_ID, flags);
}
}
}

View File

@ -10,7 +10,6 @@ use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::potion::Potion;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_data::tracked_data;
use pumpkin_protocol::java::client::play::Metadata;
use crate::entity::{
Entity, EntityBase,
@ -118,13 +117,10 @@ impl WitchEntity {
pub fn set_drinking_potion(&self, drinking: bool) {
self.drinking_potion.store(drinking, Ordering::Relaxed);
self.mob_entity.living_entity.entity.send_meta_data(
&[Metadata::new(
tracked_data::witch::DATA_USING_ITEM,
drinking,
)],
None,
);
self.mob_entity
.living_entity
.entity
.set_synced_data(tracked_data::witch::DATA_USING_ITEM, drinking);
}
#[must_use]

View File

@ -86,12 +86,10 @@ impl ZombieEntity {
.entity
.age
.store(age, std::sync::atomic::Ordering::Relaxed);
self.entity.mob_entity.living_entity.entity.send_meta_data(
&[pumpkin_protocol::java::client::play::Metadata::new(
pumpkin_data::tracked_data::zombie::BABY,
baby,
)],
None,
);
self.entity
.mob_entity
.living_entity
.entity
.set_synced_data(pumpkin_data::tracked_data::zombie::BABY, baby);
}
}

View File

@ -101,6 +101,7 @@ pub mod passive;
pub mod player;
pub mod projectile;
pub mod projectile_deflection;
pub mod synched_entity_data;
pub mod tnt;
pub mod r#type;
pub mod vehicle;
@ -205,10 +206,8 @@ pub trait EntityBase: Send + Sync + std::any::Any {
if is_baby {
let mut bedrock_meta = SyncedActorDataList::new();
bedrock_meta.set_flag(entity_data_key::FLAGS, entity_data_flag::BABY as u8, true);
entity.send_meta_data(
&[Metadata::new(tracked_data::ageable_mob::DATA_BABY_ID, true)],
Some(&bedrock_meta),
);
entity.set_synced_data(tracked_data::ageable_mob::DATA_BABY_ID, true);
entity.send_bedrock_actor_data(&bedrock_meta);
}
}
fn set_variant_name(&self, _name: &str) {}
@ -878,6 +877,7 @@ pub struct Entity {
pub bedrock_flags_two: std::sync::atomic::AtomicI64,
/// If true, the entity bypasses physics, collisions, and block effects (e.g. spectator, markers, display entities)
pub no_physics: AtomicBool,
pub synched_data: synched_entity_data::SynchedEntityData,
/// Multiplies movement for one tick before being reset
pub movement_multiplier: AtomicCell<Vector3<f64>>,
/// Determines whether the entity's velocity needs to be sent
@ -1013,6 +1013,7 @@ impl Entity {
has_no_gravity: AtomicBool::new(false),
scoreboard_tags: std::sync::Mutex::new(HashSet::new()),
no_physics: AtomicBool::new(false),
synched_data: synched_entity_data::SynchedEntityData::new(),
movement_multiplier: AtomicCell::new(Vector3::default()),
velocity_dirty: AtomicBool::new(true),
removed: AtomicBool::new(false),
@ -1142,13 +1143,8 @@ impl Entity {
entity_data_flag::ALWAYS_SHOW_NAME as u8,
visible,
);
self.send_meta_data(
&[Metadata::new(
tracked_data::entity::DATA_CUSTOM_NAME,
Some(name),
)],
Some(&bedrock_meta),
);
self.set_synced_data(tracked_data::entity::DATA_CUSTOM_NAME, Some(name));
self.send_bedrock_actor_data(&bedrock_meta);
}
pub fn set_custom_name_visible(&self, visible: bool) {
@ -1170,13 +1166,8 @@ impl Entity {
entity_data_flag::ALWAYS_SHOW_NAME as u8,
visible,
);
self.send_meta_data(
&[Metadata::new(
tracked_data::entity::DATA_CUSTOM_NAME_VISIBLE,
visible,
)],
Some(&bedrock_meta),
);
self.set_synced_data(tracked_data::entity::DATA_CUSTOM_NAME_VISIBLE, visible);
self.send_bedrock_actor_data(&bedrock_meta);
}
pub fn is_silent(&self) -> bool {
@ -1185,10 +1176,7 @@ impl Entity {
pub fn set_silent(&self, silent: bool) {
self.silent.store(silent, Ordering::Relaxed);
self.send_meta_data(
&[Metadata::new(tracked_data::entity::DATA_SILENT, silent)],
None,
);
self.set_synced_data(tracked_data::entity::DATA_SILENT, silent);
}
pub fn has_no_gravity(&self) -> bool {
@ -1197,13 +1185,7 @@ impl Entity {
pub fn set_has_no_gravity(&self, no_gravity: bool) {
self.has_no_gravity.store(no_gravity, Ordering::Relaxed);
self.send_meta_data(
&[Metadata::new(
tracked_data::entity::DATA_NO_GRAVITY,
no_gravity,
)],
None,
);
self.set_synced_data(tracked_data::entity::DATA_NO_GRAVITY, no_gravity);
}
pub fn send_velocity(&self) {
@ -2618,13 +2600,11 @@ impl Entity {
entity_data_key::FREEZING_EFFECT_STRENGTH,
MetadataValue::Float(new_frozen_ticks as f32),
);
self.send_meta_data(
&[Metadata::new(
tracked_data::entity::DATA_TICKS_FROZEN,
VarInt(new_frozen_ticks),
)],
Some(&bedrock_meta),
self.set_synced_data(
tracked_data::entity::DATA_TICKS_FROZEN,
VarInt(new_frozen_ticks),
);
self.send_bedrock_actor_data(&bedrock_meta);
}
// Vanilla parity: full-freeze damage is tick-phase based.
@ -2648,13 +2628,11 @@ impl Entity {
entity_data_key::FREEZING_EFFECT_STRENGTH,
MetadataValue::Float(new_frozen_ticks as f32),
);
self.send_meta_data(
&[Metadata::new(
tracked_data::entity::DATA_TICKS_FROZEN,
VarInt(new_frozen_ticks),
)],
Some(&bedrock_meta),
self.set_synced_data(
tracked_data::entity::DATA_TICKS_FROZEN,
VarInt(new_frozen_ticks),
);
self.send_bedrock_actor_data(&bedrock_meta);
}
/// Returns the number of ticks the entity has been frozen.
@ -2969,13 +2947,7 @@ impl Entity {
self.flags.fetch_and(!mask, Ordering::Relaxed) & !mask
};
self.send_meta_data(
&[Metadata::new(
tracked_data::entity::DATA_SHARED_FLAGS_ID,
new_je_flags,
)],
None,
);
self.set_synced_data(tracked_data::entity::DATA_SHARED_FLAGS_ID, new_je_flags);
if let Some(bedrock_flag) = flag.to_bedrock() {
let (key, index) = if bedrock_flag >= 64 {
@ -3031,26 +3003,31 @@ impl Entity {
.play_sound(sound, SoundCategory::Neutral, &self.pos.load());
}
pub fn send_meta_data<T: MetadataSerializer>(
pub fn set_synced_data<T: MetadataSerializer + Clone + Send + Sync + 'static>(
&self,
meta: &[Metadata<T>],
bedrock_meta: Option<&SyncedActorDataList>,
) {
tracked: pumpkin_data::tracked_data::TrackedData,
value: T,
) -> bool {
if self.synched_data.set(tracked, value) {
self.send_dirty_entity_data();
true
} else {
false
}
}
pub fn send_bedrock_actor_data(&self, bedrock_meta: &SyncedActorDataList) {
let world = self.world.load();
let players = world.players.load();
let mut java_recipients = Vec::new();
let mut bedrock_recipients = Vec::new();
if let Some(tracked) = world.entity_tracker.get_tracked_entity(self.entity_id) {
for player in players.iter() {
if tracked.seen_by.contains(&player.gameprofile.id)
|| player.entity_id() == self.entity_id
if (tracked.seen_by.contains(&player.gameprofile.id)
|| player.entity_id() == self.entity_id)
&& let ClientPlatform::Bedrock(client) = player.client.as_ref()
{
match player.client.as_ref() {
ClientPlatform::Java(_) => java_recipients.push(player),
ClientPlatform::Bedrock(client) => bedrock_recipients.push(client),
}
bedrock_recipients.push(client);
}
}
} else {
@ -3059,51 +3036,86 @@ impl Entity {
let center = player.get_entity().chunk_pos.load();
let view_distance = crate::world::chunker::get_view_distance(player).get() as i32;
if is_within_view_distance(chunk_pos, center, view_distance) {
match player.client.as_ref() {
ClientPlatform::Java(_) => java_recipients.push(player),
ClientPlatform::Bedrock(client) => bedrock_recipients.push(client),
}
if is_within_view_distance(chunk_pos, center, view_distance)
&& let ClientPlatform::Bedrock(client) = player.client.as_ref()
{
bedrock_recipients.push(client);
}
}
}
let packet = CSetActorData {
target_runtime_id: VarULong(self.entity_id as u64),
actor_data: SyncedActorDataList(bedrock_meta.0.clone()),
synced_properties: PropertySyncData {
int_entries_list: std::collections::HashMap::new(),
float_entries_list: std::collections::HashMap::new(),
},
tick: VarULong(0),
};
for recipient in bedrock_recipients {
if let Ok(packet_data) = recipient.serialize_packet(&packet) {
recipient.try_enqueue_packet(packet_data);
}
}
}
pub fn send_dirty_entity_data(&self) {
if !self.synched_data.is_dirty() {
return;
}
let world = self.world.load();
let players = world.players.load();
let mut java_recipients = Vec::new();
if let Some(tracked) = world.entity_tracker.get_tracked_entity(self.entity_id) {
for player in players.iter() {
if (tracked.seen_by.contains(&player.gameprofile.id)
|| player.entity_id() == self.entity_id)
&& let ClientPlatform::Java(_) = player.client.as_ref()
{
java_recipients.push(player);
}
}
} else {
let chunk_pos = self.chunk_pos.load();
for player in players.iter() {
let center = player.get_entity().chunk_pos.load();
let view_distance = crate::world::chunker::get_view_distance(player).get() as i32;
if is_within_view_distance(chunk_pos, center, view_distance)
&& let ClientPlatform::Java(_) = player.client.as_ref()
{
java_recipients.push(player);
}
}
}
if java_recipients.is_empty() {
return;
}
let recipients_by_version =
World::collect_java_recipients_by_version(java_recipients.into_iter());
for (version, recipients) in recipients_by_version {
if version < JavaMinecraftVersion::V_1_21 {
// TODO: Support older versions
if version < JavaMinecraftVersion::V_26_2 {
continue;
}
let mut buf = Vec::new();
for m in meta {
let _ = m.write(&mut buf, &version);
}
buf.put_u8(255);
let packet = CSetEntityMetadata::new(self.entity_id.into(), buf.into());
if let Ok(packet_data) = JavaClient::serialize_packet_for_version(&packet, version) {
for recipient in recipients {
recipient.try_enqueue_packet(packet_data.clone());
}
}
}
if let Some(bedrock_meta) = bedrock_meta {
let packet = CSetActorData {
target_runtime_id: VarULong(self.entity_id as u64),
actor_data: SyncedActorDataList(bedrock_meta.0.clone()),
synced_properties: PropertySyncData {
int_entries_list: std::collections::HashMap::new(),
float_entries_list: std::collections::HashMap::new(),
},
tick: VarULong(0),
};
for recipient in bedrock_recipients {
if let Ok(packet_data) = recipient.serialize_packet(&packet) {
recipient.try_enqueue_packet(packet_data);
if let Some(buf) = self.synched_data.pack_dirty_for_version(&version) {
let packet = CSetEntityMetadata::new(self.entity_id.into(), buf);
if let Ok(packet_data) = JavaClient::serialize_packet_for_version(&packet, version)
{
for recipient in recipients {
recipient.try_enqueue_packet(packet_data.clone());
}
}
}
}
self.synched_data.clear_dirty();
}
pub fn set_pose(&self, pose: EntityPose) {
@ -3142,10 +3154,8 @@ impl Entity {
entity_data_key::HEIGHT,
MetadataValue::Float(dimension.height),
);
self.send_meta_data(
&[Metadata::new(tracked_data::entity::DATA_POSE, VarInt(pose))],
Some(&bedrock_meta),
);
self.set_synced_data(tracked_data::entity::DATA_POSE, VarInt(pose));
self.send_bedrock_actor_data(&bedrock_meta);
}
/// Checks if the entity is invulnerable to the given damage type, considering both general invulnerability and specific immunities.

View File

@ -10,7 +10,6 @@ use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::particle::Particle;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::math::vector3::Vector3;
use uuid::Uuid;
@ -76,13 +75,7 @@ impl AllayEntity {
pub fn set_dancing(&self, dancing: bool) {
self.dancing.store(dancing, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::allay::DATA_DANCING,
dancing,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::allay::DATA_DANCING, dancing);
}
#[must_use]
@ -93,12 +86,9 @@ impl AllayEntity {
pub fn set_can_duplicate(&self, can_duplicate: bool) {
self.can_duplicate.store(can_duplicate, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::allay::DATA_CAN_DUPLICATE,
can_duplicate,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::allay::DATA_CAN_DUPLICATE,
can_duplicate,
);
}
}
@ -144,19 +134,13 @@ impl Mob for AllayEntity {
fn mob_init_data_tracker(&self) {
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::allay::DATA_DANCING,
self.is_dancing(),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::allay::DATA_DANCING,
self.is_dancing(),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::allay::DATA_CAN_DUPLICATE,
self.can_duplicate(),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::allay::DATA_CAN_DUPLICATE,
self.can_duplicate(),
);
}

View File

@ -11,7 +11,6 @@ use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_data::tag::{self, Taggable};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_protocol::java::client::play::Metadata;
use crate::entity::{
Entity, EntityBase,
@ -171,12 +170,9 @@ impl ArmadilloEntity {
self.state.store(state.id(), Ordering::Relaxed);
self.in_state_ticks.store(0, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::armadillo::ARMADILLO_STATE,
VarInt(state.id()),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::armadillo::ARMADILLO_STATE,
VarInt(state.id()),
);
}
@ -412,20 +408,11 @@ impl Mob for ArmadilloEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::armadillo::BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::armadillo::BABY_ID, true);
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::armadillo::ARMADILLO_STATE,
VarInt(self.get_state().id()),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::armadillo::ARMADILLO_STATE,
VarInt(self.get_state().id()),
);
}

View File

@ -10,7 +10,6 @@ use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_data::tag::{self, Taggable};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_protocol::java::client::play::Metadata;
use rand::RngExt;
use crate::entity::{
@ -184,12 +183,9 @@ impl AxolotlEntity {
pub fn set_variant(&self, variant: AxolotlVariant) {
self.variant.store(variant.id(), Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::axolotl::DATA_VARIANT,
VarInt(variant.id()),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::axolotl::DATA_VARIANT,
VarInt(variant.id()),
);
}
@ -201,12 +197,9 @@ impl AxolotlEntity {
pub fn set_playing_dead(&self, playing_dead: bool) {
self.playing_dead.store(playing_dead, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::axolotl::DATA_PLAYING_DEAD,
playing_dead,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::axolotl::DATA_PLAYING_DEAD,
playing_dead,
);
}
@ -218,12 +211,9 @@ impl AxolotlEntity {
pub fn set_from_bucket(&self, from_bucket: bool) {
self.from_bucket.store(from_bucket, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::axolotl::FROM_BUCKET,
from_bucket,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::axolotl::FROM_BUCKET,
from_bucket,
);
}
}
@ -286,34 +276,19 @@ impl Mob for AxolotlEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::axolotl::DATA_BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::axolotl::DATA_BABY_ID, true);
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::axolotl::DATA_VARIANT,
VarInt(self.get_variant().id()),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::axolotl::DATA_VARIANT,
VarInt(self.get_variant().id()),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::axolotl::DATA_PLAYING_DEAD,
self.is_playing_dead(),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::axolotl::DATA_PLAYING_DEAD,
self.is_playing_dead(),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::axolotl::FROM_BUCKET,
self.is_from_bucket(),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::axolotl::FROM_BUCKET,
self.is_from_bucket(),
);
}

View File

@ -8,7 +8,6 @@ use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::sound::Sound;
use pumpkin_data::tag::{self, Taggable};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use crate::entity::{
Entity, EntityBase,
@ -103,12 +102,9 @@ impl BeeEntity {
let new_flags = if val { current | flag } else { current & !flag };
self.flags.store(new_flags, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::bee::DATA_FLAGS_ID,
new_flags as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::bee::DATA_FLAGS_ID,
new_flags as i8,
);
}
@ -220,20 +216,11 @@ impl Mob for BeeEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::bee::DATA_BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::bee::DATA_BABY_ID, true);
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::bee::DATA_FLAGS_ID,
self.flags.load(Ordering::Relaxed) as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::bee::DATA_FLAGS_ID,
self.flags.load(Ordering::Relaxed) as i8,
);
}

View File

@ -9,7 +9,6 @@ use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_data::tag::{self, Taggable};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use crate::entity::{
Entity, EntityBase,
@ -87,12 +86,9 @@ impl CamelEntity {
let new_flags = if val { current | flag } else { current & !flag };
self.flags.store(new_flags, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::camel::DATA_ID_FLAGS,
new_flags as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::camel::DATA_ID_FLAGS,
new_flags as i8,
);
}
@ -113,13 +109,7 @@ impl CamelEntity {
pub fn set_dashing(&self, dashing: bool) {
self.dashing.store(dashing, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::camel::DASH,
dashing,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::camel::DASH, dashing);
}
}
@ -169,28 +159,13 @@ impl Mob for CamelEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::camel::DATA_BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::camel::DATA_BABY_ID, true);
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::camel::DATA_ID_FLAGS,
self.flags.load(Ordering::Relaxed) as i8,
)],
None,
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::camel::DASH,
self.is_dashing(),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::camel::DATA_ID_FLAGS,
self.flags.load(Ordering::Relaxed) as i8,
);
entity.set_synced_data(pumpkin_data::tracked_data::camel::DASH, self.is_dashing());
}
fn mob_interact(&self, player: &Arc<Player>, item_stack: &mut ItemStack) -> bool {

View File

@ -10,7 +10,6 @@ use pumpkin_data::tag::{self, Taggable};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::bedrock::server::actor_event::ActorEventID;
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_protocol::java::client::play::Metadata;
use rand::RngExt;
use uuid::Uuid;
@ -186,24 +185,18 @@ impl CatEntity {
pub fn set_collar_color(&self, color: u8) {
self.collar_color.store(color, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::cat::CAT_COLLAR_COLOR,
VarInt(color as i32),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::cat::CAT_COLLAR_COLOR,
VarInt(color as i32),
);
}
pub fn set_sitting(&self, sitting: bool) {
self.set_in_sitting_pose(sitting);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::cat::TAMEABLE_FLAGS,
self.get_tame_flags(),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::cat::TAMEABLE_FLAGS,
self.get_tame_flags(),
);
}
@ -211,56 +204,32 @@ impl CatEntity {
self.tamable_data.is_tame.store(tame, Ordering::Relaxed);
self.set_owner(owner);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::cat::TAMEABLE_FLAGS,
self.get_tame_flags(),
)],
None,
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::cat::OWNER_UUID,
owner,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::cat::TAMEABLE_FLAGS,
self.get_tame_flags(),
);
entity.set_synced_data(pumpkin_data::tracked_data::cat::OWNER_UUID, owner);
}
pub fn set_variant(&self, variant: u8) {
self.variant.store(variant, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::cat::CAT_VARIANT,
VarInt(variant as i32),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::cat::CAT_VARIANT,
VarInt(variant as i32),
);
}
pub fn set_lying(&self, lying: bool) {
self.is_lying.store(lying, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::cat::IS_LYING,
lying,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::cat::IS_LYING, lying);
}
pub fn set_relax_state_one(&self, relax: bool) {
self.relax_state_one.store(relax, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::cat::RELAX_STATE_ONE,
relax,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::cat::RELAX_STATE_ONE, relax);
}
pub fn play_eating_sound(&self) {
@ -371,62 +340,35 @@ impl Mob for CatEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::cat::BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::cat::BABY_ID, true);
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::cat::TAMEABLE_FLAGS,
self.get_tame_flags(),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::cat::TAMEABLE_FLAGS,
self.get_tame_flags(),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::cat::OWNER_UUID,
self.get_owner(),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::cat::OWNER_UUID,
self.get_owner(),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::cat::CAT_VARIANT,
VarInt(self.variant.load(Ordering::Relaxed) as i32),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::cat::CAT_VARIANT,
VarInt(self.variant.load(Ordering::Relaxed) as i32),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::cat::IS_LYING,
self.is_lying.load(Ordering::Relaxed),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::cat::IS_LYING,
self.is_lying.load(Ordering::Relaxed),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::cat::RELAX_STATE_ONE,
self.relax_state_one.load(Ordering::Relaxed),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::cat::RELAX_STATE_ONE,
self.relax_state_one.load(Ordering::Relaxed),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::cat::CAT_COLLAR_COLOR,
VarInt(self.collar_color.load(Ordering::Relaxed) as i32),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::cat::CAT_COLLAR_COLOR,
VarInt(self.collar_color.load(Ordering::Relaxed) as i32),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::cat::SOUND_VARIANT,
VarInt(self.sound_variant.load(Ordering::Relaxed) as i32),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::cat::SOUND_VARIANT,
VarInt(self.sound_variant.load(Ordering::Relaxed) as i32),
);
}

View File

@ -150,20 +150,11 @@ impl Mob for ChickenEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[pumpkin_protocol::java::client::play::Metadata::new(
pumpkin_data::tracked_data::chicken::BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::chicken::BABY_ID, true);
}
entity.send_meta_data(
&[pumpkin_protocol::java::client::play::Metadata::new(
pumpkin_data::tracked_data::chicken::VARIANT,
VarInt(self.variant.load(Ordering::Relaxed) as i32),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::chicken::VARIANT,
VarInt(self.variant.load(Ordering::Relaxed) as i32),
);
}

View File

@ -10,7 +10,6 @@ use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_data::tag::{self, Taggable};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_protocol::java::client::play::Metadata;
use crate::entity::{
Entity, EntityBase,
@ -148,12 +147,9 @@ impl CopperGolemEntity {
pub fn set_weather_state(&self, state: WeatherState) {
self.weather_state.store(state.id(), Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::copper_golem::WEATHER_STATE,
VarInt(state.id()),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::copper_golem::WEATHER_STATE,
VarInt(state.id()),
);
}
@ -165,12 +161,9 @@ impl CopperGolemEntity {
pub fn set_state(&self, state: CopperGolemState) {
self.state.store(state.id(), Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::copper_golem::COPPER_GOLEM_STATE,
VarInt(state.id()),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::copper_golem::COPPER_GOLEM_STATE,
VarInt(state.id()),
);
}
@ -237,18 +230,13 @@ impl Mob for CopperGolemEntity {
fn mob_init_data_tracker(&self) {
let entity = self.get_entity();
entity.send_meta_data(
&[
Metadata::new(
pumpkin_data::tracked_data::copper_golem::WEATHER_STATE,
VarInt(self.get_weather_state().id()),
),
Metadata::new(
pumpkin_data::tracked_data::copper_golem::COPPER_GOLEM_STATE,
VarInt(self.get_state().id()),
),
],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::copper_golem::WEATHER_STATE,
VarInt(self.get_weather_state().id()),
);
entity.set_synced_data(
pumpkin_data::tracked_data::copper_golem::COPPER_GOLEM_STATE,
VarInt(self.get_state().id()),
);
}

View File

@ -10,7 +10,6 @@ use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_data::tag::{self, Taggable};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use uuid::Uuid;
use crate::entity::{
@ -98,12 +97,9 @@ impl DonkeyEntity {
let new_flags = if val { current | flag } else { current & !flag };
self.flags.store(new_flags, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::donkey::DATA_ID_FLAGS,
new_flags as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::donkey::DATA_ID_FLAGS,
new_flags as i8,
);
}
@ -133,13 +129,7 @@ impl DonkeyEntity {
pub fn set_has_chest(&self, val: bool) {
self.has_chest.store(val, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::donkey::DATA_ID_CHEST,
val,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::donkey::DATA_ID_CHEST, val);
}
}
@ -209,27 +199,15 @@ impl Mob for DonkeyEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::donkey::DATA_BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::donkey::DATA_BABY_ID, true);
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::donkey::DATA_ID_CHEST,
self.has_chest(),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::donkey::DATA_ID_CHEST,
self.has_chest(),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::donkey::DATA_ID_FLAGS,
self.flags.load(Ordering::Relaxed) as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::donkey::DATA_ID_FLAGS,
self.flags.load(Ordering::Relaxed) as i8,
);
}

View File

@ -10,7 +10,6 @@ use pumpkin_data::sound::Sound;
use pumpkin_data::tag::{self, Taggable};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_protocol::java::client::play::Metadata;
use crate::entity::{
Entity, EntityBase,
@ -122,12 +121,9 @@ impl FoxEntity {
pub fn set_variant(&self, variant: FoxVariant) {
self.variant.store(variant.id(), Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::fox::TYPE_ID,
VarInt(variant.id()),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::fox::TYPE_ID,
VarInt(variant.id()),
);
}
@ -144,13 +140,7 @@ impl FoxEntity {
};
self.flags.store(new_flags, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::fox::FLAGS_ID,
new_flags,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::fox::FLAGS_ID, new_flags);
}
#[must_use]
@ -286,27 +276,15 @@ impl Mob for FoxEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::fox::BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::fox::BABY_ID, true);
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::fox::TYPE_ID,
VarInt(self.get_variant().id()),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::fox::TYPE_ID,
VarInt(self.get_variant().id()),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::fox::FLAGS_ID,
self.flags.load(Ordering::Relaxed),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::fox::FLAGS_ID,
self.flags.load(Ordering::Relaxed),
);
}

View File

@ -10,7 +10,6 @@ use pumpkin_data::sound::Sound;
use pumpkin_data::tag::{self, Taggable};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_protocol::java::client::play::Metadata;
use crate::entity::{
Entity, EntityBase,
@ -122,12 +121,9 @@ impl FrogEntity {
pub fn set_variant(&self, variant: FrogVariant) {
self.variant.store(variant.id(), Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::frog::VARIANT,
VarInt(variant.id()),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::frog::VARIANT,
VarInt(variant.id()),
);
}
}
@ -180,20 +176,11 @@ impl Mob for FrogEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::frog::BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::frog::BABY_ID, true);
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::frog::VARIANT,
VarInt(self.get_variant().id()),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::frog::VARIANT,
VarInt(self.get_variant().id()),
);
}

View File

@ -9,7 +9,6 @@ use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_data::tag::{self, Taggable};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use crate::entity::{
Entity, EntityBase,
@ -81,12 +80,9 @@ impl GoatEntity {
pub fn set_screaming(&self, screaming: bool) {
self.is_screaming.store(screaming, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::goat::DATA_IS_SCREAMING_GOAT,
screaming,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::goat::DATA_IS_SCREAMING_GOAT,
screaming,
);
}
@ -98,12 +94,9 @@ impl GoatEntity {
pub fn set_has_left_horn(&self, has_horn: bool) {
self.has_left_horn.store(has_horn, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::goat::DATA_HAS_LEFT_HORN,
has_horn,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::goat::DATA_HAS_LEFT_HORN,
has_horn,
);
}
@ -115,12 +108,9 @@ impl GoatEntity {
pub fn set_has_right_horn(&self, has_horn: bool) {
self.has_right_horn.store(has_horn, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::goat::DATA_HAS_RIGHT_HORN,
has_horn,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::goat::DATA_HAS_RIGHT_HORN,
has_horn,
);
}
}
@ -177,34 +167,19 @@ impl Mob for GoatEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::goat::DATA_BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::goat::DATA_BABY_ID, true);
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::goat::DATA_IS_SCREAMING_GOAT,
self.is_screaming(),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::goat::DATA_IS_SCREAMING_GOAT,
self.is_screaming(),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::goat::DATA_HAS_LEFT_HORN,
self.has_left_horn(),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::goat::DATA_HAS_LEFT_HORN,
self.has_left_horn(),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::goat::DATA_HAS_RIGHT_HORN,
self.has_right_horn(),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::goat::DATA_HAS_RIGHT_HORN,
self.has_right_horn(),
);
}

View File

@ -9,7 +9,6 @@ use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::sound::Sound;
use pumpkin_data::tag::{self, Taggable};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use crate::entity::{
Entity, EntityBase,
@ -89,12 +88,9 @@ impl HappyGhastEntity {
self.is_leash_holder
.store(is_leash_holder, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::happy_ghast::IS_LEASH_HOLDER,
is_leash_holder,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::happy_ghast::IS_LEASH_HOLDER,
is_leash_holder,
);
}
@ -102,12 +98,9 @@ impl HappyGhastEntity {
let stays_still = self.server_still_timeout.load(Ordering::Relaxed) > 0;
self.stays_still.store(stays_still, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::happy_ghast::STAYS_STILL,
stays_still,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::happy_ghast::STAYS_STILL,
stays_still,
);
}
}
@ -192,26 +185,15 @@ impl Mob for HappyGhastEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::happy_ghast::BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::happy_ghast::BABY_ID, true);
}
entity.send_meta_data(
&[
Metadata::new(
pumpkin_data::tracked_data::happy_ghast::IS_LEASH_HOLDER,
self.is_leash_holder.load(Ordering::Relaxed),
),
Metadata::new(
pumpkin_data::tracked_data::happy_ghast::STAYS_STILL,
self.stays_still.load(Ordering::Relaxed),
),
],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::happy_ghast::IS_LEASH_HOLDER,
self.is_leash_holder.load(Ordering::Relaxed),
);
entity.set_synced_data(
pumpkin_data::tracked_data::happy_ghast::STAYS_STILL,
self.stays_still.load(Ordering::Relaxed),
);
}

View File

@ -11,7 +11,6 @@ use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_data::tag::{self, Taggable};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_protocol::java::client::play::Metadata;
use rand::RngExt;
use uuid::Uuid;
@ -103,12 +102,9 @@ impl HorseEntity {
pub fn set_variant(&self, variant: i32) {
self.variant.store(variant, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::horse::DATA_ID_TYPE_VARIANT,
VarInt(variant),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::horse::DATA_ID_TYPE_VARIANT,
VarInt(variant),
);
}
@ -122,12 +118,9 @@ impl HorseEntity {
let new_flags = if val { current | flag } else { current & !flag };
self.flags.store(new_flags, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::horse::DATA_ID_FLAGS,
new_flags as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::horse::DATA_ID_FLAGS,
new_flags as i8,
);
}
@ -216,27 +209,15 @@ impl Mob for HorseEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::horse::DATA_BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::horse::DATA_BABY_ID, true);
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::horse::DATA_ID_TYPE_VARIANT,
VarInt(self.get_variant()),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::horse::DATA_ID_TYPE_VARIANT,
VarInt(self.get_variant()),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::horse::DATA_ID_FLAGS,
self.flags.load(Ordering::Relaxed) as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::horse::DATA_ID_FLAGS,
self.flags.load(Ordering::Relaxed) as i8,
);
}

View File

@ -8,7 +8,6 @@ use pumpkin_data::item::Item;
use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::GameMode;
use crate::entity::{
@ -93,13 +92,7 @@ impl IronGolemEntity {
self.player_created.store(value, Ordering::Relaxed);
let entity = self.get_entity();
let flag: u8 = u8::from(value);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::iron_golem::FLAGS_ID,
flag,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::iron_golem::FLAGS_ID, flag);
}
pub fn offer_flower(&self, offer: bool) {
@ -150,13 +143,7 @@ impl Mob for IronGolemEntity {
fn mob_init_data_tracker(&self) {
let entity = self.get_entity();
let flag: u8 = u8::from(self.is_player_created());
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::iron_golem::FLAGS_ID,
flag,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::iron_golem::FLAGS_ID, flag);
}
fn mob_interact(&self, player: &Arc<Player>, item_stack: &mut ItemStack) -> bool {

View File

@ -11,7 +11,6 @@ use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_data::tag::{self, Taggable};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_protocol::java::client::play::Metadata;
use rand::RngExt;
use uuid::Uuid;
@ -162,12 +161,9 @@ impl LlamaEntity {
pub fn set_variant(&self, variant: LlamaVariant) {
self.variant.store(variant.id(), Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::llama::DATA_VARIANT_ID,
VarInt(variant.id()),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::llama::DATA_VARIANT_ID,
VarInt(variant.id()),
);
}
@ -179,12 +175,9 @@ impl LlamaEntity {
pub fn set_strength(&self, strength: i32) {
self.strength.store(strength, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::llama::DATA_STRENGTH_ID,
VarInt(strength),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::llama::DATA_STRENGTH_ID,
VarInt(strength),
);
}
@ -198,12 +191,9 @@ impl LlamaEntity {
let new_flags = if val { current | flag } else { current & !flag };
self.flags.store(new_flags, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::llama::DATA_ID_FLAGS,
new_flags as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::llama::DATA_ID_FLAGS,
new_flags as i8,
);
}
@ -224,13 +214,7 @@ impl LlamaEntity {
pub fn set_has_chest(&self, val: bool) {
self.has_chest.store(val, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::llama::DATA_ID_CHEST,
val,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::llama::DATA_ID_CHEST, val);
}
pub fn spit(&self, target: &Arc<dyn EntityBase>) {
@ -334,41 +318,23 @@ impl Mob for LlamaEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::llama::DATA_BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::llama::DATA_BABY_ID, true);
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::llama::DATA_VARIANT_ID,
VarInt(self.get_variant().id()),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::llama::DATA_VARIANT_ID,
VarInt(self.get_variant().id()),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::llama::DATA_STRENGTH_ID,
VarInt(self.get_strength()),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::llama::DATA_STRENGTH_ID,
VarInt(self.get_strength()),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::llama::DATA_ID_CHEST,
self.has_chest(),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::llama::DATA_ID_CHEST,
self.has_chest(),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::llama::DATA_ID_FLAGS,
self.flags.load(Ordering::Relaxed) as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::llama::DATA_ID_FLAGS,
self.flags.load(Ordering::Relaxed) as i8,
);
}

View File

@ -12,7 +12,6 @@ use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_data::tag::{self, Taggable};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::math::vector3::Vector3;
use uuid::Uuid;
@ -126,12 +125,9 @@ impl MooshroomEntity {
pub fn set_variant(&self, variant: MooshroomVariant) {
self.variant.store(variant.id(), Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::mooshroom::DATA_TYPE,
VarInt(variant.id()),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::mooshroom::DATA_TYPE,
VarInt(variant.id()),
);
}
}
@ -180,20 +176,11 @@ impl Mob for MooshroomEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::mooshroom::DATA_BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::mooshroom::DATA_BABY_ID, true);
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::mooshroom::DATA_TYPE,
VarInt(self.get_variant().id()),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::mooshroom::DATA_TYPE,
VarInt(self.get_variant().id()),
);
}

View File

@ -10,7 +10,6 @@ use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_data::tag::{self, Taggable};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use uuid::Uuid;
use crate::entity::{
@ -97,12 +96,9 @@ impl MuleEntity {
let new_flags = if val { current | flag } else { current & !flag };
self.flags.store(new_flags, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::mule::DATA_ID_FLAGS,
new_flags as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::mule::DATA_ID_FLAGS,
new_flags as i8,
);
}
@ -132,13 +128,7 @@ impl MuleEntity {
pub fn set_has_chest(&self, val: bool) {
self.has_chest.store(val, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::mule::DATA_ID_CHEST,
val,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::mule::DATA_ID_CHEST, val);
}
}
@ -208,27 +198,15 @@ impl Mob for MuleEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::mule::DATA_BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::mule::DATA_BABY_ID, true);
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::mule::DATA_ID_CHEST,
self.has_chest(),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::mule::DATA_ID_CHEST,
self.has_chest(),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::mule::DATA_ID_FLAGS,
self.flags.load(Ordering::Relaxed) as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::mule::DATA_ID_FLAGS,
self.flags.load(Ordering::Relaxed) as i8,
);
}

View File

@ -14,7 +14,6 @@ use pumpkin_data::{
sound::{Sound, SoundCategory},
};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::math::vector3::Vector3;
use crate::entity::{
@ -56,13 +55,10 @@ impl NautilusEntity {
pub fn set_dashing(&self, dashing: bool) {
self.is_dashing.store(dashing, Ordering::Relaxed);
self.mob_entity.living_entity.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::nautilus::DASH,
dashing,
)],
None,
);
self.mob_entity
.living_entity
.entity
.set_synced_data(pumpkin_data::tracked_data::nautilus::DASH, dashing);
}
pub fn is_tame(&self) -> bool {
@ -258,12 +254,9 @@ impl Mob for NautilusEntity {
}
fn mob_init_data_tracker(&self) {
self.mob_entity.living_entity.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::nautilus::DASH,
self.is_dashing(),
)],
None,
self.mob_entity.living_entity.entity.set_synced_data(
pumpkin_data::tracked_data::nautilus::DASH,
self.is_dashing(),
);
}

View File

@ -9,7 +9,6 @@ use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::tag::{self, Taggable};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::bedrock::server::actor_event::ActorEventID;
use pumpkin_protocol::java::client::play::Metadata;
use rand::RngExt;
use crate::entity::{
@ -109,13 +108,7 @@ impl OcelotEntity {
pub fn set_trusting(&self, trusting: bool) {
self.is_trusting.store(trusting, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::ocelot::TRUSTING,
trusting,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::ocelot::TRUSTING, trusting);
}
}
@ -151,20 +144,11 @@ impl Mob for OcelotEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::ocelot::BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::ocelot::BABY_ID, true);
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::ocelot::TRUSTING,
self.is_trusting.load(Ordering::Relaxed),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::ocelot::TRUSTING,
self.is_trusting.load(Ordering::Relaxed),
);
}

View File

@ -10,7 +10,6 @@ use pumpkin_data::sound::Sound;
use pumpkin_data::tag::{self, Taggable};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_protocol::java::client::play::Metadata;
use rand::RngExt;
use crate::entity::{
@ -167,12 +166,9 @@ impl PandaEntity {
pub fn set_main_gene(&self, gene: PandaGene) {
self.main_gene.store(gene.id(), Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::panda::MAIN_GENE_ID,
gene.id() as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::panda::MAIN_GENE_ID,
gene.id() as i8,
);
}
@ -184,12 +180,9 @@ impl PandaEntity {
pub fn set_hidden_gene(&self, gene: PandaGene) {
self.hidden_gene.store(gene.id(), Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::panda::HIDDEN_GENE_ID,
gene.id() as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::panda::HIDDEN_GENE_ID,
gene.id() as i8,
);
}
@ -203,12 +196,9 @@ impl PandaEntity {
let new_flags = if val { current | flag } else { current & !flag };
self.flags.store(new_flags, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::panda::DATA_ID_FLAGS,
new_flags as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::panda::DATA_ID_FLAGS,
new_flags as i8,
);
}
@ -300,55 +290,31 @@ impl Mob for PandaEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::panda::DATA_BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::panda::DATA_BABY_ID, true);
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::panda::MAIN_GENE_ID,
self.main_gene.load(Ordering::Relaxed) as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::panda::MAIN_GENE_ID,
self.main_gene.load(Ordering::Relaxed) as i8,
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::panda::HIDDEN_GENE_ID,
self.hidden_gene.load(Ordering::Relaxed) as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::panda::HIDDEN_GENE_ID,
self.hidden_gene.load(Ordering::Relaxed) as i8,
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::panda::DATA_ID_FLAGS,
self.flags.load(Ordering::Relaxed) as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::panda::DATA_ID_FLAGS,
self.flags.load(Ordering::Relaxed) as i8,
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::panda::UNHAPPY_COUNTER,
VarInt(self.unhappy_counter.load(Ordering::Relaxed)),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::panda::UNHAPPY_COUNTER,
VarInt(self.unhappy_counter.load(Ordering::Relaxed)),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::panda::SNEEZE_COUNTER,
VarInt(self.sneeze_counter.load(Ordering::Relaxed)),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::panda::SNEEZE_COUNTER,
VarInt(self.sneeze_counter.load(Ordering::Relaxed)),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::panda::EAT_COUNTER,
VarInt(self.eat_counter.load(Ordering::Relaxed)),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::panda::EAT_COUNTER,
VarInt(self.eat_counter.load(Ordering::Relaxed)),
);
}

View File

@ -7,7 +7,6 @@ use pumpkin_data::entity::EntityType;
use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::sound::Sound;
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use crate::entity::{
Entity, EntityBase,
@ -91,12 +90,9 @@ impl PolarBearEntity {
pub fn set_standing(&self, standing: bool) {
self.standing.store(standing, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::polar_bear::DATA_STANDING_ID,
standing,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::polar_bear::DATA_STANDING_ID,
standing,
);
}
}
@ -142,20 +138,11 @@ impl Mob for PolarBearEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::polar_bear::DATA_BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::polar_bear::DATA_BABY_ID, true);
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::polar_bear::DATA_STANDING_ID,
self.is_standing(),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::polar_bear::DATA_STANDING_ID,
self.is_standing(),
);
}

View File

@ -10,7 +10,6 @@ use pumpkin_data::sound::Sound;
use pumpkin_data::tag::{self, Taggable};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_protocol::java::client::play::Metadata;
use rand::RngExt;
use crate::entity::{
@ -142,12 +141,9 @@ impl RabbitEntity {
pub fn set_variant(&self, variant: RabbitVariant) {
self.variant.store(variant.id(), Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::rabbit::DATA_TYPE_ID,
VarInt(variant.id()),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::rabbit::DATA_TYPE_ID,
VarInt(variant.id()),
);
if variant == RabbitVariant::Evil {
@ -232,20 +228,11 @@ impl Mob for RabbitEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::rabbit::DATA_BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::rabbit::DATA_BABY_ID, true);
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::rabbit::DATA_TYPE_ID,
VarInt(self.get_variant().id()),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::rabbit::DATA_TYPE_ID,
VarInt(self.get_variant().id()),
);
}

View File

@ -5,7 +5,6 @@ use std::sync::{
use pumpkin_data::{entity::EntityType, item::Item};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use rand::RngExt;
use crate::entity::{
@ -85,13 +84,10 @@ impl SheepEntity {
fn set_packed_and_sync(&self, byte: u8) {
self.color_and_sheared.store(byte, Ordering::Relaxed);
self.mob_entity.living_entity.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::sheep::WOOL_ID,
byte as i8,
)],
None,
);
self.mob_entity
.living_entity
.entity
.set_synced_data(pumpkin_data::tracked_data::sheep::WOOL_ID, byte as i8);
}
pub fn set_color(&self, color: u8) {

View File

@ -9,7 +9,6 @@ use pumpkin_data::item::Item;
use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use uuid::Uuid;
use crate::entity::{
@ -84,12 +83,9 @@ impl SkeletonHorseEntity {
let new_flags = if val { current | flag } else { current & !flag };
self.flags.store(new_flags, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::skeleton_horse::DATA_ID_FLAGS,
new_flags as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::skeleton_horse::DATA_ID_FLAGS,
new_flags as i8,
);
}
@ -167,20 +163,14 @@ impl Mob for SkeletonHorseEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::skeleton_horse::DATA_BABY_ID,
true,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::skeleton_horse::DATA_BABY_ID,
true,
);
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::skeleton_horse::DATA_ID_FLAGS,
self.flags.load(Ordering::Relaxed) as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::skeleton_horse::DATA_ID_FLAGS,
self.flags.load(Ordering::Relaxed) as i8,
);
}

View File

@ -10,7 +10,6 @@ use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_data::tag::{self, Taggable};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::math::position::BlockPos;
use pumpkin_util::math::vector3::Vector3;
@ -122,12 +121,9 @@ impl SnifferEntity {
pub fn set_state(&self, state: SnifferState) {
self.state.store(state.id(), Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::sniffer::STATE,
VarInt(state.id()),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::sniffer::STATE,
VarInt(state.id()),
);
}
@ -190,12 +186,9 @@ impl SnifferEntity {
let current_ticks = world.level_time.try_lock().map_or(0, |t| t.world_age);
let drop_tick = current_ticks as i32 + DIGGING_DROP_SEED_OFFSET_TICKS;
self.drop_seed_at_tick.store(drop_tick, Ordering::Relaxed);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::sniffer::DROP_SEED_AT_TICK,
VarInt(drop_tick),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::sniffer::DROP_SEED_AT_TICK,
VarInt(drop_tick),
);
world.send_entity_status(entity, EntityStatus::SnifferDiggingSound, None);
}
@ -384,26 +377,15 @@ impl Mob for SnifferEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::sniffer::BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::sniffer::BABY_ID, true);
}
entity.send_meta_data(
&[
Metadata::new(
pumpkin_data::tracked_data::sniffer::STATE,
VarInt(self.get_state().id()),
),
Metadata::new(
pumpkin_data::tracked_data::sniffer::DROP_SEED_AT_TICK,
VarInt(self.drop_seed_at_tick.load(Ordering::Relaxed)),
),
],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::sniffer::STATE,
VarInt(self.get_state().id()),
);
entity.set_synced_data(
pumpkin_data::tracked_data::sniffer::DROP_SEED_AT_TICK,
VarInt(self.drop_seed_at_tick.load(Ordering::Relaxed)),
);
}

View File

@ -6,7 +6,6 @@ use pumpkin_data::item::Item;
use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use crate::entity::{
Entity, EntityBase,
@ -84,12 +83,9 @@ impl SnowGolemEntity {
self.has_pumpkin.store(has_pumpkin, Ordering::Relaxed);
let entity = self.get_entity();
let flags = if has_pumpkin { 16u8 } else { 0u8 };
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::snow_golem::DATA_PUMPKIN_ID,
flags as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::snow_golem::DATA_PUMPKIN_ID,
flags as i8,
);
}
@ -140,12 +136,9 @@ impl Mob for SnowGolemEntity {
fn mob_init_data_tracker(&self) {
let entity = self.get_entity();
let flags = if self.has_pumpkin() { 16u8 } else { 0u8 };
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::snow_golem::DATA_PUMPKIN_ID,
flags as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::snow_golem::DATA_PUMPKIN_ID,
flags as i8,
);
}

View File

@ -7,7 +7,6 @@ use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_data::tag::{self, Taggable};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use crate::entity::{
Entity, EntityBase,
@ -80,12 +79,9 @@ impl StriderEntity {
pub fn set_suffocating(&self, suffocating: bool) {
self.suffocating.store(suffocating, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::strider::DATA_SUFFOCATING,
suffocating,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::strider::DATA_SUFFOCATING,
suffocating,
);
}
}
@ -154,20 +150,11 @@ impl Mob for StriderEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::strider::DATA_BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::strider::DATA_BABY_ID, true);
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::strider::DATA_SUFFOCATING,
self.is_suffocating(),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::strider::DATA_SUFFOCATING,
self.is_suffocating(),
);
}

View File

@ -2,7 +2,6 @@ use std::sync::atomic::{AtomicBool, Ordering::Relaxed};
use crossbeam::atomic::AtomicCell;
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use uuid::Uuid;
use crate::entity::passive::animal::Animal;
@ -46,12 +45,9 @@ pub trait TamableAnimal: Animal {
if tame {
flags |= TAME_FLAG;
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::tamable_animal::DATA_FLAGS_ID,
flags as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::tamable_animal::DATA_FLAGS_ID,
flags as i8,
);
}
@ -69,12 +65,9 @@ pub trait TamableAnimal: Animal {
if self.is_tame() {
flags |= TAME_FLAG;
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::tamable_animal::DATA_FLAGS_ID,
flags as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::tamable_animal::DATA_FLAGS_ID,
flags as i8,
);
}
@ -94,12 +87,9 @@ pub trait TamableAnimal: Animal {
let mob_entity = self.get_mob_entity();
let entity = &mob_entity.living_entity.entity;
self.get_tamable_data().owner.store(owner);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::tamable_animal::DATA_OWNERUUID_ID,
owner,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::tamable_animal::DATA_OWNERUUID_ID,
owner,
);
}

View File

@ -11,7 +11,6 @@ use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_data::tag::{self, Taggable};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_protocol::java::client::play::Metadata;
use rand::RngExt;
use uuid::Uuid;
@ -162,12 +161,9 @@ impl TraderLlamaEntity {
pub fn set_variant(&self, variant: TraderLlamaVariant) {
self.variant.store(variant.id(), Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::trader_llama::DATA_VARIANT_ID,
VarInt(variant.id()),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::trader_llama::DATA_VARIANT_ID,
VarInt(variant.id()),
);
}
@ -179,12 +175,9 @@ impl TraderLlamaEntity {
pub fn set_strength(&self, strength: i32) {
self.strength.store(strength, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::trader_llama::DATA_STRENGTH_ID,
VarInt(strength),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::trader_llama::DATA_STRENGTH_ID,
VarInt(strength),
);
}
@ -198,12 +191,9 @@ impl TraderLlamaEntity {
let new_flags = if val { current | flag } else { current & !flag };
self.flags.store(new_flags, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::trader_llama::DATA_ID_FLAGS,
new_flags as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::trader_llama::DATA_ID_FLAGS,
new_flags as i8,
);
}
@ -224,13 +214,7 @@ impl TraderLlamaEntity {
pub fn set_has_chest(&self, val: bool) {
self.has_chest.store(val, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::trader_llama::DATA_ID_CHEST,
val,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::trader_llama::DATA_ID_CHEST, val);
}
pub fn spit(&self, target: &Arc<dyn EntityBase>) {
@ -334,41 +318,23 @@ impl Mob for TraderLlamaEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::trader_llama::DATA_BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::trader_llama::DATA_BABY_ID, true);
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::trader_llama::DATA_VARIANT_ID,
VarInt(self.get_variant().id()),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::trader_llama::DATA_VARIANT_ID,
VarInt(self.get_variant().id()),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::trader_llama::DATA_STRENGTH_ID,
VarInt(self.get_strength()),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::trader_llama::DATA_STRENGTH_ID,
VarInt(self.get_strength()),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::trader_llama::DATA_ID_CHEST,
self.has_chest(),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::trader_llama::DATA_ID_CHEST,
self.has_chest(),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::trader_llama::DATA_ID_FLAGS,
self.flags.load(Ordering::Relaxed) as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::trader_llama::DATA_ID_FLAGS,
self.flags.load(Ordering::Relaxed) as i8,
);
}

View File

@ -9,7 +9,6 @@ use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::sound::Sound;
use pumpkin_data::tag::{self, Taggable};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use crate::entity::{
Entity, EntityBase,
@ -79,13 +78,7 @@ impl TurtleEntity {
pub fn set_has_egg(&self, has_egg: bool) {
self.has_egg.store(has_egg, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::turtle::HAS_EGG,
has_egg,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::turtle::HAS_EGG, has_egg);
}
#[must_use]
@ -96,13 +89,7 @@ impl TurtleEntity {
pub fn set_laying_egg(&self, laying_egg: bool) {
self.laying_egg.store(laying_egg, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::turtle::LAYING_EGG,
laying_egg,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::turtle::LAYING_EGG, laying_egg);
}
}
@ -152,27 +139,12 @@ impl Mob for TurtleEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::turtle::DATA_BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::turtle::DATA_BABY_ID, true);
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::turtle::HAS_EGG,
self.has_egg(),
)],
None,
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::turtle::LAYING_EGG,
self.is_laying_egg(),
)],
None,
entity.set_synced_data(pumpkin_data::tracked_data::turtle::HAS_EGG, self.has_egg());
entity.set_synced_data(
pumpkin_data::tracked_data::turtle::LAYING_EGG,
self.is_laying_egg(),
);
}

View File

@ -431,13 +431,12 @@ impl VillagerEntity {
// Send initial metadata
let bedrock_metadata = Self::bedrock_metadata(villager_data, 0);
mob_arc.get_entity().send_meta_data(
&[Metadata::new(
tracked_data::villager::VILLAGER_DATA,
villager_data,
)],
Some(&bedrock_metadata),
);
mob_arc
.get_entity()
.set_synced_data(tracked_data::villager::VILLAGER_DATA, villager_data);
mob_arc
.get_entity()
.send_bedrock_actor_data(&bedrock_metadata);
mob_arc
}
@ -506,10 +505,9 @@ impl VillagerEntity {
old_profession
};
let bedrock_metadata = Self::bedrock_metadata(data, self.xp.load(Ordering::Relaxed));
self.get_entity().send_meta_data(
&[Metadata::new(tracked_data::villager::VILLAGER_DATA, data)],
Some(&bedrock_metadata),
);
self.get_entity()
.set_synced_data(tracked_data::villager::VILLAGER_DATA, data);
self.get_entity().send_bedrock_actor_data(&bedrock_metadata);
if old_profession != data.profession {
self.offers
@ -829,13 +827,9 @@ impl VillagerEntity {
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let bedrock_metadata = Self::bedrock_metadata(villager_data, current_xp);
self.get_entity().send_meta_data(
&[Metadata::new(
tracked_data::villager::VILLAGER_DATA,
villager_data,
)],
Some(&bedrock_metadata),
);
self.get_entity()
.set_synced_data(tracked_data::villager::VILLAGER_DATA, villager_data);
self.get_entity().send_bedrock_actor_data(&bedrock_metadata);
if reward_exp {
ExperienceOrbEntity::spawn(world, self.get_entity().pos.load(), xp_gain as u32);
@ -1278,13 +1272,7 @@ impl VillagerEntity {
pub fn set_unhappy(&self) {
let entity = self.get_entity();
self.unhappy_counter.store(40, Ordering::Relaxed);
entity.send_meta_data(
&[Metadata::new(
tracked_data::villager::UNHAPPY_COUNTER,
VarInt(40),
)],
None,
);
entity.set_synced_data(tracked_data::villager::UNHAPPY_COUNTER, VarInt(40));
entity.world.load().send_entity_status(
entity,
pumpkin_data::entity::EntityStatus::VillagerAngry,
@ -1548,12 +1536,9 @@ impl VillagerEntity {
let unhappy_counter = unhappy_counter - 1;
self.unhappy_counter
.store(unhappy_counter, Ordering::Relaxed);
self.get_entity().send_meta_data(
&[Metadata::new(
tracked_data::villager::UNHAPPY_COUNTER,
VarInt(unhappy_counter),
)],
None,
self.get_entity().set_synced_data(
tracked_data::villager::UNHAPPY_COUNTER,
VarInt(unhappy_counter),
);
}
self.trade_sound_cooldown
@ -1650,12 +1635,9 @@ impl VillagerEntity {
if is_sleeping {
// Wake up if bed was broken
self.get_entity().set_pose(EntityPose::Standing);
self.get_entity().send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::villager::SLEEPING_POS_ID,
None::<BlockPos>,
)],
None,
self.get_entity().set_synced_data(
pumpkin_data::tracked_data::villager::SLEEPING_POS_ID,
None::<BlockPos>,
);
}
}
@ -1749,12 +1731,9 @@ impl VillagerEntity {
BedBlock::set_occupied(true, &world, block, &home_pos, state.id);
self.get_entity().set_pose(EntityPose::Sleeping);
self.get_entity().send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::villager::SLEEPING_POS_ID,
Some(home_pos),
)],
None,
self.get_entity().set_synced_data(
pumpkin_data::tracked_data::villager::SLEEPING_POS_ID,
Some(home_pos),
);
}
}
@ -1771,23 +1750,17 @@ impl VillagerEntity {
}
self.get_entity().set_pose(EntityPose::Standing);
self.get_entity().send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::villager::SLEEPING_POS_ID,
None::<BlockPos>,
)],
None,
self.get_entity().set_synced_data(
pumpkin_data::tracked_data::villager::SLEEPING_POS_ID,
None::<BlockPos>,
);
}
} else if is_sleeping {
// Wake up during the day
self.get_entity().set_pose(EntityPose::Standing);
self.get_entity().send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::villager::SLEEPING_POS_ID,
None::<BlockPos>,
)],
None,
self.get_entity().set_synced_data(
pumpkin_data::tracked_data::villager::SLEEPING_POS_ID,
None::<BlockPos>,
);
}
@ -2249,15 +2222,10 @@ impl Mob for VillagerEntity {
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let bedrock_metadata = Self::bedrock_metadata(data, self.xp.load(Ordering::Relaxed));
entity.send_meta_data(
&[Metadata::new(tracked_data::villager::VILLAGER_DATA, data)],
Some(&bedrock_metadata),
);
entity.set_synced_data(tracked_data::villager::VILLAGER_DATA, data);
entity.send_bedrock_actor_data(&bedrock_metadata);
if entity.age.load(Ordering::Relaxed) < 0 {
entity.send_meta_data(
&[Metadata::new(tracked_data::villager::BABY_ID, true)],
None,
);
entity.set_synced_data(tracked_data::villager::BABY_ID, true);
}
}

View File

@ -9,7 +9,6 @@ use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::tag::{self, Taggable};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_protocol::java::client::play::Metadata;
use rand::RngExt;
use crate::entity::{
@ -292,41 +291,23 @@ impl Mob for WolfEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::wolf::BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::wolf::BABY_ID, true);
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::wolf::TAMEABLE_FLAGS,
self.get_tame_flags(),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::wolf::TAMEABLE_FLAGS,
self.get_tame_flags(),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::wolf::COLLAR_COLOR,
VarInt(self.collar_color.load(Ordering::Relaxed) as i32),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::wolf::COLLAR_COLOR,
VarInt(self.collar_color.load(Ordering::Relaxed) as i32),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::wolf::WOLF_VARIANT_ID,
VarInt(self.variant.load(Ordering::Relaxed) as i32),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::wolf::WOLF_VARIANT_ID,
VarInt(self.variant.load(Ordering::Relaxed) as i32),
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::wolf::OWNER_UUID,
self.get_owner(),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::wolf::OWNER_UUID,
self.get_owner(),
);
}
@ -392,12 +373,9 @@ impl WolfEntity {
pub fn set_collar_color(&self, color: u8) {
self.collar_color.store(color, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::wolf::COLLAR_COLOR,
VarInt(color as i32),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::wolf::COLLAR_COLOR,
VarInt(color as i32),
);
}
}

View File

@ -9,7 +9,6 @@ use pumpkin_data::item::Item;
use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use uuid::Uuid;
use crate::entity::{
@ -84,12 +83,9 @@ impl ZombieHorseEntity {
let new_flags = if val { current | flag } else { current & !flag };
self.flags.store(new_flags, Ordering::Relaxed);
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::zombie_horse::DATA_ID_FLAGS,
new_flags as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::zombie_horse::DATA_ID_FLAGS,
new_flags as i8,
);
}
@ -167,20 +163,11 @@ impl Mob for ZombieHorseEntity {
let entity = self.get_entity();
let is_baby = entity.age.load(Ordering::Relaxed) < 0;
if is_baby {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::zombie_horse::DATA_BABY_ID,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::zombie_horse::DATA_BABY_ID, true);
}
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::zombie_horse::DATA_ID_FLAGS,
self.flags.load(Ordering::Relaxed) as i8,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::zombie_horse::DATA_ID_FLAGS,
self.flags.load(Ordering::Relaxed) as i8,
);
}

View File

@ -269,8 +269,8 @@ use pumpkin_protocol::java::client::play::{
CSetContainerContent, CSetContainerProperty, CSetContainerSlot, CSetCursorItem, CSetExperience,
CSetHealth, CSetPlayerInventory, CSetSelectedSlot, CSoundEffect, CStopSound, CSubtitle,
CSystemChatMessage, CTabList, CTitleAnimation, CTitleText, CUnloadChunk, CUpdateMobEffect,
CUpdateTime, GameEvent, MapIcon, MapPatch, Metadata, PlayerAction, PlayerInfoFlags,
PlayerSpawnData, PreviousMessage, Statistic,
CUpdateTime, GameEvent, MapIcon, MapPatch, PlayerAction, PlayerInfoFlags, PlayerSpawnData,
PreviousMessage, Statistic,
};
use pumpkin_protocol::java::server::play::{
SClickSlot, SContainerButtonClick, SRenameItem, SlotActionType,
@ -487,7 +487,7 @@ pub struct Player {
pub experience_pick_up_delay: Mutex<u32>,
pub chunk_sender: Mutex<crate::net::ChunkSender>,
pub chunk_listener: Mutex<Receiver<(Vector2<i32>, Weak<ChunkData>)>>,
pub held_chunk_tickets: Mutex<Option<(i8, i8)>>,
pub held_chunk_tickets: Mutex<Option<(Option<i8>, Option<i8>)>>,
pub chunk_send_epoch: AtomicU32,
pub has_played_before: AtomicBool,
root_vehicle_uuid: AtomicCell<Option<Uuid>>,
@ -1107,14 +1107,22 @@ impl Player {
.take();
if let Some((view_level, sim_level)) = held {
let center = self.get_entity().chunk_pos.load();
lock.remove_ticket(center, view_level);
lock.remove_ticket(center, sim_level);
if let Some(view) = view_level {
lock.remove_ticket(center, view);
}
if let Some(sim) = sim_level {
lock.remove_ticket(center, sim);
}
}
lock.send_change();
level.should_unload.store(true, Ordering::Relaxed);
level.level_channel.notify();
}
pub fn update_chunk_tickets_for_gamemode(self: &Arc<Self>) {
crate::world::chunker::update_position(self);
}
pub fn change_world_chunks(
&self,
old_level: &Arc<pumpkin_world::level::Level>,
@ -1919,12 +1927,9 @@ impl Player {
self.living_entity
.entity
.set_pos(bed_head_pos.to_f64().add_raw(0.5, 0.6875, 0.5));
self.get_entity().send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::player::SLEEPING_POS_ID,
Some(bed_head_pos),
)],
None,
self.get_entity().set_synced_data(
pumpkin_data::tracked_data::player::SLEEPING_POS_ID,
Some(bed_head_pos),
);
self.get_entity().set_velocity(Vector3::default());
@ -2083,12 +2088,9 @@ impl Player {
self.living_entity.entity.set_pose(EntityPose::Standing);
self.living_entity.entity.set_pos(self.position());
self.living_entity.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::player::SLEEPING_POS_ID,
None::<BlockPos>,
)],
None,
self.living_entity.entity.set_synced_data(
pumpkin_data::tracked_data::player::SLEEPING_POS_ID,
None::<BlockPos>,
);
self.set_stat(
@ -4512,28 +4514,21 @@ impl Player {
/// Send the player's skin layers and used hand to all players.
pub fn send_client_information(&self) {
let config = self.config.load();
self.living_entity.entity.send_meta_data(
&[
// v26.x
Metadata::new(
pumpkin_data::tracked_data::player::PLAYER_MODE_CUSTOMISATION,
config.skin_parts,
),
Metadata::new(
pumpkin_data::tracked_data::player::PLAYER_MAIN_HAND,
config.main_hand as u8,
),
// v1.21.x
Metadata::new(
pumpkin_data::tracked_data::player::PLAYER_MODE_CUSTOMIZATION_ID,
config.skin_parts,
),
Metadata::new(
pumpkin_data::tracked_data::player::MAIN_ARM_ID,
config.main_hand as u8,
),
],
None,
self.living_entity.entity.set_synced_data(
pumpkin_data::tracked_data::player::PLAYER_MODE_CUSTOMISATION,
config.skin_parts,
);
self.living_entity.entity.set_synced_data(
pumpkin_data::tracked_data::player::PLAYER_MAIN_HAND,
config.main_hand as u8,
);
self.living_entity.entity.set_synced_data(
pumpkin_data::tracked_data::player::PLAYER_MODE_CUSTOMIZATION_ID,
config.skin_parts,
);
self.living_entity.entity.set_synced_data(
pumpkin_data::tracked_data::player::MAIN_ARM_ID,
config.main_hand as u8,
);
}

View File

@ -326,25 +326,15 @@ impl ArrowEntity {
pub fn set_critical(&self, critical: bool) {
self.is_critical.store(critical, Ordering::Relaxed);
let flags = self.get_flags();
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::abstract_arrow::ID_FLAGS,
flags,
)],
None,
);
self.entity
.set_synced_data(pumpkin_data::tracked_data::abstract_arrow::ID_FLAGS, flags);
}
pub fn set_no_physics(&self, no_physics: bool) {
self.no_physics.store(no_physics, Ordering::Relaxed);
let flags = self.get_flags();
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::abstract_arrow::ID_FLAGS,
flags,
)],
None,
);
self.entity
.set_synced_data(pumpkin_data::tracked_data::abstract_arrow::ID_FLAGS, flags);
}
#[must_use]
@ -363,12 +353,9 @@ impl ArrowEntity {
pub fn set_pierce_level(&self, level: u8) {
self.pierce_level.store(level, Ordering::Relaxed);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::abstract_arrow::PIERCE_LEVEL,
level,
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::abstract_arrow::PIERCE_LEVEL,
level,
);
}
@ -476,22 +463,14 @@ impl EntityBase for ArrowEntity {
let in_ground = self.in_ground.load(Ordering::Relaxed);
if entity.entity_type.id == EntityType::SPECTRAL_ARROW.id {
entity.send_meta_data(
&[
Metadata::new(pumpkin_data::tracked_data::spectral_arrow::ID_FLAGS, flags),
Metadata::new(
pumpkin_data::tracked_data::spectral_arrow::PIERCE_LEVEL,
pierce,
),
],
None,
entity.set_synced_data(pumpkin_data::tracked_data::spectral_arrow::ID_FLAGS, flags);
entity.set_synced_data(
pumpkin_data::tracked_data::spectral_arrow::PIERCE_LEVEL,
pierce,
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::spectral_arrow::IN_GROUND,
in_ground,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::spectral_arrow::IN_GROUND,
in_ground,
);
} else {
let item_stack = self
@ -499,27 +478,10 @@ impl EntityBase for ArrowEntity {
.read()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let color = Self::get_effect_color(&item_stack);
entity.send_meta_data(
&[
Metadata::new(pumpkin_data::tracked_data::arrow::ID_FLAGS, flags),
Metadata::new(pumpkin_data::tracked_data::arrow::PIERCE_LEVEL, pierce),
],
None,
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::arrow::IN_GROUND,
in_ground,
)],
None,
);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::arrow::ID_EFFECT_COLOR,
color,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::arrow::ID_FLAGS, flags);
entity.set_synced_data(pumpkin_data::tracked_data::arrow::PIERCE_LEVEL, pierce);
entity.set_synced_data(pumpkin_data::tracked_data::arrow::IN_GROUND, in_ground);
entity.set_synced_data(pumpkin_data::tracked_data::arrow::ID_EFFECT_COLOR, color);
}
if self.is_on_fire() {
@ -635,12 +597,9 @@ impl EntityBase for ArrowEntity {
let block = world.get_block(&pos);
if block.is_air() {
self.in_ground.store(false, Ordering::Relaxed);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::abstract_arrow::IN_GROUND,
false,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::abstract_arrow::IN_GROUND,
false,
);
let mut vel = entity.velocity.load();
vel.x *= rand::random::<f64>() * 0.2;
@ -901,13 +860,7 @@ impl EntityBase for ArrowEntity {
entity.velocity.store(Vector3::new(0.0, 0.0, 0.0));
// Notify client that arrow is in ground
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::abstract_arrow::IN_GROUND,
true,
)],
None,
);
entity.set_synced_data(pumpkin_data::tracked_data::abstract_arrow::IN_GROUND, true);
// Play sound with vanilla pitch formula
let sound_pitch = 1.2 / (rand::random::<f32>() * 0.2 + 0.9);

View File

@ -11,7 +11,6 @@ use pumpkin_data::item::Item;
use pumpkin_data::item_stack::ItemStack;
use pumpkin_protocol::bedrock::server::actor_event::ActorEventID;
use pumpkin_protocol::codec::item_stack_seralizer::ItemStackSerializer;
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::math::vector3::Vector3;
use uuid::Uuid;
@ -75,12 +74,9 @@ impl EntityBase for EggEntity {
.unwrap_or_else(std::sync::PoisonError::into_inner);
// Sync the item stack so the client renders the correct color/variant
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::egg::ITEM_STACK,
&ItemStackSerializer::from(stack.clone()),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::egg::ITEM_STACK,
ItemStackSerializer::from(stack.clone()),
);
}

View File

@ -173,17 +173,14 @@ impl EntityBase for EyeOfEnder {
}
fn init_data_tracker(&self) {
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::eye_of_ender::ITEM_STACK,
&ItemStackSerializer::from(
self.item_stack
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.clone(),
),
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::eye_of_ender::ITEM_STACK,
ItemStackSerializer::from(
self.item_stack
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.clone(),
),
);
}

View File

@ -5,7 +5,6 @@ use pumpkin_data::item::Item;
use pumpkin_data::item_stack::ItemStack;
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::codec::item_stack_seralizer::ItemStackSerializer;
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::math::atomic_f32::AtomicF32;
use pumpkin_util::math::vector3::Vector3;
@ -118,12 +117,9 @@ impl FireballEntity {
.write()
.unwrap_or_else(std::sync::PoisonError::into_inner) = new_item.clone();
self.get_entity().send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::fireball::ITEM_STACK,
&ItemStackSerializer::from(new_item),
)],
None,
self.get_entity().set_synced_data(
pumpkin_data::tracked_data::fireball::ITEM_STACK,
ItemStackSerializer::from(new_item),
);
}
@ -200,12 +196,9 @@ impl EntityBase for FireballEntity {
.read()
.unwrap_or_else(std::sync::PoisonError::into_inner);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::fireball::ITEM_STACK,
&ItemStackSerializer::from(stack.clone()),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::fireball::ITEM_STACK,
ItemStackSerializer::from(stack.clone()),
);
}

View File

@ -5,7 +5,7 @@ use crate::{
};
use pumpkin_data::entity::EntityStatus;
use pumpkin_protocol::bedrock::server::actor_event::ActorEventID;
use pumpkin_protocol::{codec::optional_int::OptionalInt, java::client::play::Metadata};
use pumpkin_protocol::codec::optional_int::OptionalInt;
use pumpkin_util::{
math::vector3::Vector3,
random::{RandomGenerator, RandomImpl, get_seed, xoroshiro128::Xoroshiro},
@ -60,12 +60,9 @@ impl FireworkRocketEntity {
.into(),
};
rocket.entity.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::firework_rocket::ATTACHED_TO_TARGET,
OptionalInt(Some(shooter.entity_id)),
)],
None,
rocket.entity.entity.set_synced_data(
pumpkin_data::tracked_data::firework_rocket::ATTACHED_TO_TARGET,
OptionalInt(Some(shooter.entity_id)),
);
rocket

View File

@ -7,7 +7,6 @@ use crate::{
};
use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::math::boundingbox::BoundingBox;
use pumpkin_util::math::vector3::Vector3;
@ -204,12 +203,9 @@ impl FishingBobberEntity {
if ebb.intersects(&search_box) {
self.hooked_entity_id
.store(cand.get_entity().entity_id, Ordering::Relaxed);
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::fishing_bobber::HOOKED_ENTITY,
cand.get_entity().entity_id + 1,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::fishing_bobber::HOOKED_ENTITY,
cand.get_entity().entity_id + 1,
);
return;
}

View File

@ -76,14 +76,9 @@ impl EntityBase for LingeringPotionEntity {
.unwrap_or_else(std::sync::PoisonError::into_inner);
// Sync the item stack so the client renders the correct potion type
entity.send_meta_data(
&[pumpkin_protocol::java::client::play::Metadata::new(
pumpkin_data::tracked_data::lingering_potion::ITEM_STACK,
&pumpkin_protocol::codec::item_stack_seralizer::ItemStackSerializer::from(
stack.clone(),
),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::lingering_potion::ITEM_STACK,
pumpkin_protocol::codec::item_stack_seralizer::ItemStackSerializer::from(stack.clone()),
);
}

View File

@ -111,14 +111,9 @@ impl EntityBase for SplashPotionEntity {
.unwrap_or_else(std::sync::PoisonError::into_inner);
// Sync the item stack
entity.send_meta_data(
&[pumpkin_protocol::java::client::play::Metadata::new(
pumpkin_data::tracked_data::splash_potion::ITEM_STACK,
&pumpkin_protocol::codec::item_stack_seralizer::ItemStackSerializer::from(
stack.clone(),
),
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::splash_potion::ITEM_STACK,
pumpkin_protocol::codec::item_stack_seralizer::ItemStackSerializer::from(stack.clone()),
);
}

View File

@ -2,7 +2,6 @@ use std::sync::atomic::{AtomicBool, Ordering};
use pumpkin_data::{damage::DamageType, effect::StatusEffect, potion::Effect, tracked_data};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::{Difficulty, math::vector3::Vector3};
use crate::{
@ -69,13 +68,9 @@ impl WitherSkullEntity {
pub fn set_dangerous(&self, dangerous: bool) {
self.dangerous.store(dangerous, Ordering::Relaxed);
self.thrown.entity.send_meta_data(
&[Metadata::new(
tracked_data::wither_skull::DATA_DANGEROUS,
dangerous,
)],
None,
);
self.thrown
.entity
.set_synced_data(tracked_data::wither_skull::DATA_DANGEROUS, dangerous);
}
}
@ -96,12 +91,9 @@ impl EntityBase for WitherSkullEntity {
fn init_data_tracker(&self) {
let entity = self.get_entity();
entity.send_meta_data(
&[Metadata::new(
tracked_data::wither_skull::DATA_DANGEROUS,
self.is_dangerous(),
)],
None,
entity.set_synced_data(
tracked_data::wither_skull::DATA_DANGEROUS,
self.is_dangerous(),
);
}

View File

@ -0,0 +1,221 @@
use std::collections::HashMap;
use std::sync::Mutex;
use std::sync::atomic::{AtomicBool, Ordering};
use bytes::BufMut;
use pumpkin_data::meta_data_type::MetaDataType;
use pumpkin_data::tracked_data::{TrackedData, TrackedId};
use pumpkin_protocol::java::client::play::{Metadata, MetadataSerializer};
use pumpkin_protocol::ser::WritingError;
use pumpkin_util::version::JavaMinecraftVersion;
pub trait ErasedSerializer: Send + Sync {
fn write(
&self,
index: TrackedId,
r#type: MetaDataType,
writer: &mut dyn std::io::Write,
version: &JavaMinecraftVersion,
) -> Result<(), WritingError>;
fn write_canonical(&self, index: TrackedId, r#type: MetaDataType) -> Vec<u8>;
}
struct SerializerHolder<T> {
value: T,
}
impl<T: MetadataSerializer + Clone + Send + Sync + 'static> ErasedSerializer
for SerializerHolder<T>
{
fn write(
&self,
index: TrackedId,
r#type: MetaDataType,
writer: &mut dyn std::io::Write,
version: &JavaMinecraftVersion,
) -> Result<(), WritingError> {
let meta = Metadata::new_raw(index, r#type, &self.value);
meta.write(writer, version)
}
fn write_canonical(&self, index: TrackedId, r#type: MetaDataType) -> Vec<u8> {
let mut buf = Vec::new();
let meta = Metadata::new_raw(index, r#type, &self.value);
let _ = meta.write(&mut buf, &JavaMinecraftVersion::V_26_2);
buf
}
}
pub struct DataItem {
pub tracked: TrackedData,
pub serializer: Box<dyn ErasedSerializer>,
pub canonical_bytes: Vec<u8>,
pub dirty: bool,
pub is_default: bool,
}
pub struct SynchedEntityData {
items: Mutex<HashMap<u8, DataItem>>,
is_dirty: AtomicBool,
}
impl Default for SynchedEntityData {
fn default() -> Self {
Self::new()
}
}
impl SynchedEntityData {
#[must_use]
pub fn new() -> Self {
Self {
items: Mutex::new(HashMap::new()),
is_dirty: AtomicBool::new(false),
}
}
pub fn define<T: MetadataSerializer + Clone + Send + Sync + 'static>(
&self,
tracked: TrackedData,
value: T,
) {
let id = tracked.id.v26_2;
let holder = SerializerHolder { value };
let canonical_bytes = holder.write_canonical(tracked.id, tracked.r#type);
let mut items = self
.items
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
items.insert(
id,
DataItem {
tracked,
serializer: Box::new(holder),
canonical_bytes,
dirty: false,
is_default: true,
},
);
}
pub fn set<T: MetadataSerializer + Clone + Send + Sync + 'static>(
&self,
tracked: TrackedData,
value: T,
) -> bool {
let id = tracked.id.v26_2;
let holder = SerializerHolder { value };
let new_canonical = holder.write_canonical(tracked.id, tracked.r#type);
let mut items = self
.items
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if let Some(item) = items.get_mut(&id) {
if item.canonical_bytes == new_canonical {
return false;
}
item.canonical_bytes = new_canonical;
item.serializer = Box::new(holder);
item.dirty = true;
item.is_default = false;
} else {
items.insert(
id,
DataItem {
tracked,
serializer: Box::new(holder),
canonical_bytes: new_canonical,
dirty: true,
is_default: false,
},
);
}
self.is_dirty.store(true, Ordering::Release);
true
}
#[must_use]
pub fn is_dirty(&self) -> bool {
self.is_dirty.load(Ordering::Acquire)
}
pub fn pack_dirty_for_version(&self, version: &JavaMinecraftVersion) -> Option<Box<[u8]>> {
if !self.is_dirty.load(Ordering::Acquire) {
return None;
}
let items = self
.items
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let mut buf = Vec::new();
let mut has_any = false;
for item in items.values() {
if item.dirty {
let before_len = buf.len();
if item
.serializer
.write(item.tracked.id, item.tracked.r#type, &mut buf, version)
.is_ok()
&& buf.len() > before_len
{
has_any = true;
}
}
}
if !has_any {
return None;
}
buf.put_u8(255);
Some(buf.into_boxed_slice())
}
pub fn clear_dirty(&self) {
let mut items = self
.items
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
for item in items.values_mut() {
item.dirty = false;
}
self.is_dirty.store(false, Ordering::Release);
}
pub fn get_non_default_values_for_version(
&self,
version: &JavaMinecraftVersion,
) -> Option<Box<[u8]>> {
let items = self
.items
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let mut buf = Vec::new();
let mut has_any = false;
for item in items.values() {
if !item.is_default {
let before_len = buf.len();
if item
.serializer
.write(item.tracked.id, item.tracked.r#type, &mut buf, version)
.is_ok()
&& buf.len() > before_len
{
has_any = true;
}
}
}
if !has_any {
return None;
}
buf.put_u8(255);
Some(buf.into_boxed_slice())
}
}

View File

@ -2,7 +2,7 @@ use super::{Entity, EntityBase, living::LivingEntity};
use crate::server::Server;
use core::f32;
use pumpkin_data::Block;
use pumpkin_protocol::{codec::var_int::VarInt, java::client::play::Metadata};
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_util::math::vector3::Vector3;
use std::{
f64::consts::TAU,
@ -78,18 +78,13 @@ impl EntityBase for TNTEntity {
self.entity
.set_velocity(Vector3::new(-pos.sin() * 0.02, 0.2, -pos.cos() * 0.02));
self.entity.send_meta_data(
&[
Metadata::new(
pumpkin_data::tracked_data::tnt::FUSE_ID,
VarInt(self.fuse.load(Relaxed) as i32),
),
Metadata::new(
pumpkin_data::tracked_data::tnt::BLOCK_STATE_ID,
VarInt(i32::from(Block::TNT.default_state.id.as_u16())),
),
],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::tnt::FUSE_ID,
VarInt(self.fuse.load(Relaxed) as i32),
);
self.entity.set_synced_data(
pumpkin_data::tracked_data::tnt::BLOCK_STATE_ID,
VarInt(i32::from(Block::TNT.default_state.id.as_u16())),
);
}

View File

@ -10,8 +10,6 @@ use crate::server::Server;
use pumpkin_data::damage::DamageType;
use pumpkin_data::item_stack::ItemStack;
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::math::vector3::Vector3;
use crate::entity::vehicle::vehicle::VehicleEntity;
@ -37,13 +35,12 @@ impl BoatEntity {
self.left_paddle_moving.store(left, Ordering::Relaxed);
self.right_paddle_moving.store(right, Ordering::Relaxed);
self.vehicle.entity.send_meta_data(
&[
Metadata::new(pumpkin_data::tracked_data::boat::ID_PADDLE_LEFT, left),
Metadata::new(pumpkin_data::tracked_data::boat::ID_PADDLE_RIGHT, right),
],
None,
);
self.vehicle
.entity
.set_synced_data(pumpkin_data::tracked_data::boat::ID_PADDLE_LEFT, left);
self.vehicle
.entity
.set_synced_data(pumpkin_data::tracked_data::boat::ID_PADDLE_RIGHT, right);
}
fn send_wobble_metadata(&self) {

View File

@ -5,7 +5,6 @@ use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::particle::Particle;
use pumpkin_data::tag::{self, Taggable};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::math::vector3::Vector3;
use rand::RngExt;
@ -28,12 +27,9 @@ impl FurnaceMinecart {
}
fn set_fueled(entity: &Entity, fueled: bool) {
entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::furnace_minecart::ID_FUEL,
fueled,
)],
None,
entity.set_synced_data(
pumpkin_data::tracked_data::furnace_minecart::ID_FUEL,
fueled,
);
}

View File

@ -2,7 +2,6 @@ use crossbeam::atomic::AtomicCell;
use std::sync::atomic::{AtomicI32, Ordering};
use crate::entity::Entity;
use pumpkin_protocol::java::client::play::Metadata;
use crate::entity::EntityBase;
use pumpkin_protocol::codec::var_int::VarInt;
@ -134,25 +133,17 @@ impl VehicleEntity {
}
pub fn send_wobble_metadata(&self) {
self.entity.send_meta_data(
&[
Metadata::new(
pumpkin_data::tracked_data::boat::ID_HURT,
VarInt(self.get_hurt_time()),
),
Metadata::new(
pumpkin_data::tracked_data::boat::ID_HURTDIR,
VarInt(self.get_hurt_dir()),
),
],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::boat::ID_HURT,
VarInt(self.get_hurt_time()),
);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::boat::ID_DAMAGE,
self.get_damage(),
)],
None,
self.entity.set_synced_data(
pumpkin_data::tracked_data::boat::ID_HURTDIR,
VarInt(self.get_hurt_dir()),
);
self.entity.set_synced_data(
pumpkin_data::tracked_data::boat::ID_DAMAGE,
self.get_damage(),
);
}

View File

@ -184,13 +184,8 @@ impl ItemBehaviour for SpawnEggItem {
mob.get_entity()
.age
.store(-24000, std::sync::atomic::Ordering::Relaxed);
mob.get_entity().send_meta_data(
&[pumpkin_protocol::java::client::play::Metadata::new(
pumpkin_data::tracked_data::ageable_mob::DATA_BABY_ID,
true,
)],
None,
);
mob.get_entity()
.set_synced_data(pumpkin_data::tracked_data::ageable_mob::DATA_BABY_ID, true);
apply_entity_variant(item, mob.as_ref());
world.spawn_entity(mob);
item.decrement_unless_creative(player.gamemode.load(), 1);

View File

@ -40,6 +40,7 @@ pub fn is_within_view_distance(
(target.x - center.x).abs().max((target.y - center.y).abs()) <= view_distance
}
#[allow(clippy::too_many_lines)]
pub fn update_position(player: &Arc<Player>) {
let entity = &player.get_entity();
let new_chunk_center = entity.chunk_pos.load();
@ -85,26 +86,46 @@ pub fn update_position(player: &Arc<Player>) {
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let is_spectator = player.is_spectator();
let spectators_generate_chunks = world
.level_info
.load()
.game_rules
.spectators_generate_chunks;
let new_view_level = (!is_spectator || spectators_generate_chunks).then(|| {
pumpkin_world::chunk_system::ChunkLoading::get_level_from_view_distance(
u8::from(view_distance) + 1,
)
});
let new_sim_level = (!is_spectator).then(|| {
let sim_dist = world.server.upgrade().map_or(10, |s| {
s.advanced_config.networking.java.simulation_distance.get()
});
pumpkin_world::chunk_system::ChunkLoading::get_level_from_simulation_distance(sim_dist)
});
{
let mut lock = level
.chunk_loading
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let new_level = pumpkin_world::chunk_system::ChunkLoading::get_level_from_view_distance(
u8::from(view_distance) + 1,
);
lock.add_ticket(new_chunk_center, new_level);
let sim_dist = world.server.upgrade().map_or(10, |s| {
s.advanced_config.networking.java.simulation_distance.get()
});
let sim_level =
pumpkin_world::chunk_system::ChunkLoading::get_level_from_simulation_distance(sim_dist);
lock.add_ticket(new_chunk_center, sim_level);
if let Some(view) = new_view_level {
lock.add_ticket(new_chunk_center, view);
}
if let Some(sim) = new_sim_level {
lock.add_ticket(new_chunk_center, sim);
}
if let Some((held_view, held_sim)) = held_tickets.replace((new_level, sim_level)) {
lock.remove_ticket(old_cylindrical.center, held_view);
lock.remove_ticket(old_cylindrical.center, held_sim);
if let Some((held_view, held_sim)) = held_tickets.replace((new_view_level, new_sim_level)) {
if let Some(view) = held_view {
lock.remove_ticket(old_cylindrical.center, view);
}
if let Some(sim) = held_sim {
lock.remove_ticket(old_cylindrical.center, sim);
}
}
lock.send_change();
};

View File

@ -1,14 +1,21 @@
use std::sync::Arc;
use bytes::BufMut;
use crossbeam::atomic::AtomicCell;
use dashmap::DashMap;
use dashmap::DashSet;
use pumpkin_protocol::bedrock::client::remove_actor::CRemoveActor;
use pumpkin_protocol::codec::item_stack_seralizer::ItemStackSerializer;
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_protocol::codec::var_long::VarLong;
use pumpkin_protocol::java::client::play::{
CEntityVelocity, CHeadRot, CRemoveEntities, CSetEntityMetadata, Metadata,
CEntityVelocity, CHeadRot, CRemoveEntities, CSetEntityMetadata, CSetEquipment, CSetPassengers,
Metadata,
};
use pumpkin_protocol::{BClientPacket, ClientPacket};
use pumpkin_util::GameMode;
use pumpkin_util::math::get_section_cord;
use pumpkin_util::math::vector3::Vector3;
use pumpkin_util::version::JavaMinecraftVersion;
use uuid::Uuid;
@ -19,8 +26,6 @@ use crate::net::java::JavaClient;
use crate::world::World;
use crate::world::chunker::{get_view_distance, is_within_view_distance};
/// Represents an entity tracked in the world and its current watchers,
/// corresponding to Vanilla's `ChunkMap.TrackedEntity`.
pub struct TrackedEntity {
pub entity: Arc<dyn EntityBase>,
pub entity_id: i32,
@ -28,6 +33,7 @@ pub struct TrackedEntity {
pub update_interval: u32,
pub track_deltas: bool,
pub seen_by: DashSet<Uuid>,
pub last_section_pos: AtomicCell<Vector3<i32>>,
}
impl TrackedEntity {
@ -39,6 +45,12 @@ impl TrackedEntity {
track_deltas: bool,
) -> Self {
let entity_id = entity.get_entity().entity_id;
let pos = entity.get_entity().pos.load();
let last_section_pos = Vector3::new(
get_section_cord(pos.x.floor() as i32),
get_section_cord(pos.y.floor() as i32),
get_section_cord(pos.z.floor() as i32),
);
Self {
entity,
entity_id,
@ -46,25 +58,43 @@ impl TrackedEntity {
update_interval,
track_deltas,
seen_by: DashSet::new(),
last_section_pos: AtomicCell::new(last_section_pos),
}
}
fn collect_indirect_passengers(
entity: &Arc<dyn EntityBase>,
result: &mut Vec<Arc<dyn EntityBase>>,
) {
if let Ok(passengers) = entity.get_entity().passengers.try_lock() {
for passenger in passengers.iter() {
result.push(passenger.clone());
Self::collect_indirect_passengers(passenger, result);
}
}
}
/// Gets the effective tracking range in chunks, taking passengers into account.
#[must_use]
pub fn get_effective_range(&self) -> u32 {
let mut effective_range = self.tracking_range;
if let Ok(passengers) = self.entity.get_entity().passengers.try_lock() {
for passenger in passengers.iter() {
let passenger_range = passenger.get_entity().entity_type.client_tracking_range;
if passenger_range > effective_range {
effective_range = passenger_range;
}
let mut passengers = Vec::new();
Self::collect_indirect_passengers(&self.entity, &mut passengers);
for passenger in passengers {
let passenger_range = passenger.get_entity().entity_type.client_tracking_range;
if passenger_range > effective_range {
effective_range = passenger_range;
}
}
effective_range
}
/// Updates visibility for a single player.
fn broadcast_to_player(&self, player: &Player) -> bool {
self.entity.get_player().is_none_or(|target_player| {
player.gamemode.load() == GameMode::Spectator
|| target_player.gamemode.load() != GameMode::Spectator
})
}
pub fn update_player(&self, player: &Arc<Player>, _world: &World) {
if player.get_entity().entity_id == self.entity_id {
return;
@ -86,7 +116,7 @@ impl TrackedEntity {
let player_chunk = player_entity.chunk_pos.load();
let in_view = is_within_view_distance(entity_chunk, player_chunk, player_vd);
let is_visible = dist_sq <= range_sq && in_view;
let is_visible = dist_sq <= range_sq && self.broadcast_to_player(player) && in_view;
if is_visible {
if self.seen_by.insert(player.gameprofile.id) {
@ -97,14 +127,13 @@ impl TrackedEntity {
}
}
/// Updates visibility for a list of players.
pub fn update_players(&self, players: &[Arc<Player>], world: &World) {
for player in players {
self.update_player(player, world);
}
}
/// Sends spawn and initial state packets to the new watcher.
#[allow(clippy::too_many_lines)]
pub fn add_pairing(&self, player: &Arc<Player>) {
player.client.try_enqueue_spawn_packet(&self.entity);
@ -169,9 +198,81 @@ impl TrackedEntity {
client.try_enqueue_packet(data);
}
}
if let ClientPlatform::Java(client) = player.client.as_ref() {
let version = client.version.load();
// TODO: Support older versions
if version >= JavaMinecraftVersion::V_26_2
&& let Some(non_default) = self
.entity
.get_entity()
.synched_data
.get_non_default_values_for_version(&version)
{
let packet = CSetEntityMetadata::new(self.entity_id.into(), non_default);
if let Ok(packet_data) = JavaClient::serialize_packet_for_version(&packet, version)
{
client.try_enqueue_packet(packet_data);
}
}
}
if let Some(living) = self.entity.get_living_entity()
&& let Ok(equipment_guard) = living.entity_equipment.try_lock()
{
let mut equipment_list = Vec::new();
for (slot, item_stack) in &equipment_guard.equipment {
if !item_stack.is_empty() {
equipment_list.push((slot.discriminant(), item_stack.clone()));
}
}
if !equipment_list.is_empty() {
let equipment: Vec<(i8, ItemStackSerializer)> = equipment_list
.iter()
.map(|(slot, stack)| (*slot, ItemStackSerializer::from(stack.clone())))
.collect();
let packet = CSetEquipment::new(self.entity_id.into(), equipment);
if let ClientPlatform::Java(client) = player.client.as_ref()
&& let Ok(data) = client.serialize_packet(&packet)
{
client.try_enqueue_packet(data);
}
}
}
if let Ok(passengers) = self.entity.get_entity().passengers.try_lock()
&& !passengers.is_empty()
{
let passenger_ids: Vec<VarInt> = passengers
.iter()
.map(|p| VarInt(p.get_entity().entity_id))
.collect();
let packet = CSetPassengers::new(VarInt(self.entity_id), &passenger_ids);
if let ClientPlatform::Java(client) = player.client.as_ref()
&& let Ok(data) = client.serialize_packet(&packet)
{
client.try_enqueue_packet(data);
}
}
if let Ok(vehicle_guard) = self.entity.get_entity().vehicle.try_lock()
&& let Some(vehicle) = vehicle_guard.as_ref()
&& let Ok(vehicle_passengers) = vehicle.get_entity().passengers.try_lock()
{
let passenger_ids: Vec<VarInt> = vehicle_passengers
.iter()
.map(|p| VarInt(p.get_entity().entity_id))
.collect();
let packet =
CSetPassengers::new(VarInt(vehicle.get_entity().entity_id), &passenger_ids);
if let ClientPlatform::Java(client) = player.client.as_ref()
&& let Ok(data) = client.serialize_packet(&packet)
{
client.try_enqueue_packet(data);
}
}
}
/// Sends despawn packet to a player leaving visibility range.
pub fn remove_pairing(&self, player: &Arc<Player>) {
let entity_ids = [self.entity_id.into()];
match player.client.as_ref() {
@ -190,7 +291,6 @@ impl TrackedEntity {
}
}
/// Broadcasts removal of this entity to all current watchers.
pub fn broadcast_removed(&self, world: &World) {
let entity_ids = [self.entity_id.into()];
let je_packet = CRemoveEntities::new(&entity_ids);
@ -217,12 +317,10 @@ impl TrackedEntity {
self.seen_by.clear();
}
/// Removes a player by UUID without sending despawn packet (used on disconnect).
pub fn remove_player(&self, player_uuid: &Uuid) {
self.seen_by.remove(player_uuid);
}
/// Sends a Java client packet to all tracking players.
pub fn send_to_tracking_players<P: ClientPacket + Sync>(&self, packet: &P, world: &World) {
let players = world.players.load();
let recipients = players
@ -232,7 +330,6 @@ impl TrackedEntity {
World::broadcast_java_grouped(packet, recipients_by_version);
}
/// Sends a Bedrock client packet to all tracking players.
pub fn send_to_tracking_players_bedrock<P: BClientPacket + Sync>(
&self,
packet: &P,
@ -250,7 +347,6 @@ impl TrackedEntity {
World::broadcast_bedrock_grouped(packet, recipients);
}
/// Sends an editioned packet (Java + Bedrock) to all tracking players.
pub fn send_to_tracking_players_editioned<J: ClientPacket + Sync, B: BClientPacket + Sync>(
&self,
je_packet: &J,
@ -276,7 +372,6 @@ impl TrackedEntity {
World::broadcast_bedrock_grouped(be_packet, bedrock_recipients.into_iter());
}
/// Sends a packet to all tracking players and the entity itself if it is a player.
pub fn send_to_tracking_players_and_self<P: ClientPacket + Sync>(
&self,
packet: &P,
@ -288,7 +383,6 @@ impl TrackedEntity {
}
}
/// Sends an editioned packet to all tracking players and the entity itself if it is a player.
pub fn send_to_tracking_players_and_self_editioned<
J: ClientPacket + Sync,
B: BClientPacket + Sync,
@ -304,7 +398,6 @@ impl TrackedEntity {
}
}
/// Sends a packet to tracking players filtered by predicate.
pub fn send_to_tracking_players_filtered<P: ClientPacket + Sync, F: Fn(&Player) -> bool>(
&self,
packet: &P,
@ -319,7 +412,6 @@ impl TrackedEntity {
World::broadcast_java_grouped(packet, recipients_by_version);
}
/// Sends an editioned packet to tracking players filtered by predicate.
pub fn send_to_tracking_players_filtered_editioned<
J: ClientPacket + Sync,
B: BClientPacket + Sync,
@ -351,7 +443,6 @@ impl TrackedEntity {
}
}
/// The entity tracking system for a world, corresponding to Vanilla's `ChunkMap.entityMap`.
pub struct EntityTracker {
pub entity_map: DashMap<i32, Arc<TrackedEntity>>,
}
@ -387,6 +478,18 @@ impl EntityTracker {
.is_some_and(|t| !t.seen_by.is_empty())
}
pub fn for_each_entity_tracked_by<F: FnMut(&Arc<dyn EntityBase>)>(
&self,
player: &Player,
mut f: F,
) {
for entry in &self.entity_map {
if entry.value().seen_by.contains(&player.gameprofile.id) {
f(&entry.value().entity);
}
}
}
pub fn add_entity(&self, entity: &Arc<dyn EntityBase>, world: &World) {
let entity_type = entity.get_entity().entity_type;
let range = entity_type.client_tracking_range;
@ -408,7 +511,6 @@ impl EntityTracker {
let players = world.players.load();
tracked.update_players(players.as_ref(), world);
// If the newly added entity is a player, update all other tracked entities for this player
if let Some(player) = entity.get_player()
&& let Some(player_arc) = world.get_player_by_uuid(player.gameprofile.id)
{
@ -435,6 +537,15 @@ impl EntityTracker {
}
pub fn update_player_position(&self, player: &Arc<Player>, world: &World) {
let pos = player.get_entity().pos.load();
let new_pos = Vector3::new(
get_section_cord(pos.x.floor() as i32),
get_section_cord(pos.y.floor() as i32),
get_section_cord(pos.z.floor() as i32),
);
if let Some(tracked) = self.entity_map.get(&player.get_entity().entity_id) {
tracked.last_section_pos.store(new_pos);
}
for entry in &self.entity_map {
if *entry.key() == player.get_entity().entity_id {
let players = world.players.load();
@ -447,6 +558,13 @@ impl EntityTracker {
pub fn update_entity_position(&self, entity: &dyn EntityBase, world: &World) {
if let Some(tracked) = self.entity_map.get(&entity.get_entity().entity_id) {
let pos = entity.get_entity().pos.load();
let new_pos = Vector3::new(
get_section_cord(pos.x.floor() as i32),
get_section_cord(pos.y.floor() as i32),
get_section_cord(pos.z.floor() as i32),
);
tracked.last_section_pos.store(new_pos);
let players = world.players.load();
tracked.update_players(players.as_ref(), world);
}
@ -454,8 +572,39 @@ impl EntityTracker {
pub fn update_all(&self, world: &World) {
let players = world.players.load();
let mut moved_players = Vec::new();
for entry in &self.entity_map {
entry.value().update_players(players.as_ref(), world);
let tracked = entry.value();
let pos = tracked.entity.get_entity().pos.load();
let new_pos = Vector3::new(
get_section_cord(pos.x.floor() as i32),
get_section_cord(pos.y.floor() as i32),
get_section_cord(pos.z.floor() as i32),
);
let old_pos = tracked.last_section_pos.load();
if old_pos != new_pos {
tracked.update_players(players.as_ref(), world);
if let Some(player) = tracked.entity.get_player()
&& let Some(player_arc) = world.get_player_by_uuid(player.gameprofile.id)
{
moved_players.push(player_arc);
}
tracked.last_section_pos.store(new_pos);
}
}
if !moved_players.is_empty() {
for entry in &self.entity_map {
entry.value().update_players(&moved_players, world);
}
}
for entry in &self.entity_map {
let tracked = entry.value();
if tracked.entity.get_entity().synched_data.is_dirty() {
tracked.entity.get_entity().send_dirty_entity_data();
}
}
}
}

View File

@ -419,6 +419,9 @@ impl World {
s.advanced_config.networking.java.simulation_distance.get()
}) as i32;
for player in self.players.load().iter() {
if player.is_spectator() {
continue;
}
let center = player.get_entity().chunk_pos.load();
for dx in -sim_dist..=sim_dist {
for dy in -sim_dist..=sim_dist {

File diff suppressed because it is too large Load Diff