feat: add SynchedEntityData
also some fixes
This commit is contained in:
parent
8f847ef786
commit
8608ac0361
@ -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"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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")]
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct OptionalInt(pub Option<i32>);
|
||||
|
||||
impl OptionalInt {
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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(),
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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()),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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)]),
|
||||
);
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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> {
|
||||
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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> {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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]
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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()),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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()),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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()),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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()),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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)),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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()),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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)),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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()),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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()),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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()),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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()),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
221
crates/pumpkin/src/entity/synched_entity_data.rs
Normal file
221
crates/pumpkin/src/entity/synched_entity_data.rs
Normal 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())
|
||||
}
|
||||
}
|
||||
@ -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())),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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();
|
||||
};
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
Loading…
Reference in New Issue
Block a user