feat(bedrock): add bossbar & scoreboard
This commit is contained in:
parent
330a68054f
commit
7fe103db67
75
pumpkin-protocol/src/bedrock/client/boss_event.rs
Normal file
75
pumpkin-protocol/src/bedrock/client/boss_event.rs
Normal file
@ -0,0 +1,75 @@
|
||||
use std::io::{Error, Write};
|
||||
|
||||
use crate::{
|
||||
codec::{var_int::VarInt, var_long::VarLong},
|
||||
serial::PacketWrite,
|
||||
};
|
||||
use pumpkin_macros::packet;
|
||||
|
||||
#[packet(74)]
|
||||
pub struct CBossEvent {
|
||||
pub boss_entity_id: VarLong,
|
||||
pub action: BossEventAction,
|
||||
}
|
||||
|
||||
pub enum BossEventAction {
|
||||
Add {
|
||||
title: String,
|
||||
health_percent: f32,
|
||||
screen_darken: u16,
|
||||
color: VarInt,
|
||||
overlay: VarInt,
|
||||
},
|
||||
Remove,
|
||||
UpdateHealth(f32),
|
||||
UpdateTitle(String),
|
||||
UpdateProperties {
|
||||
screen_darken: u16,
|
||||
color: VarInt,
|
||||
overlay: VarInt,
|
||||
},
|
||||
}
|
||||
|
||||
impl PacketWrite for CBossEvent {
|
||||
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
self.boss_entity_id.write(writer)?;
|
||||
match &self.action {
|
||||
BossEventAction::Add {
|
||||
title,
|
||||
health_percent,
|
||||
screen_darken,
|
||||
color,
|
||||
overlay,
|
||||
} => {
|
||||
VarInt(0).write(writer)?;
|
||||
title.write(writer)?;
|
||||
health_percent.write(writer)?;
|
||||
screen_darken.write(writer)?;
|
||||
color.write(writer)?;
|
||||
overlay.write(writer)?;
|
||||
}
|
||||
BossEventAction::Remove => {
|
||||
VarInt(2).write(writer)?;
|
||||
}
|
||||
BossEventAction::UpdateHealth(health) => {
|
||||
VarInt(3).write(writer)?;
|
||||
health.write(writer)?;
|
||||
}
|
||||
BossEventAction::UpdateTitle(title) => {
|
||||
VarInt(4).write(writer)?;
|
||||
title.write(writer)?;
|
||||
}
|
||||
BossEventAction::UpdateProperties {
|
||||
screen_darken,
|
||||
color,
|
||||
overlay,
|
||||
} => {
|
||||
VarInt(5).write(writer)?;
|
||||
screen_darken.write(writer)?;
|
||||
color.write(writer)?;
|
||||
overlay.write(writer)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
pub mod available_commands;
|
||||
pub mod boss_event;
|
||||
pub mod chunk_radius_update;
|
||||
pub mod container_open;
|
||||
pub mod correct_player_move;
|
||||
@ -18,6 +19,7 @@ pub mod player_hotbar;
|
||||
pub mod raknet;
|
||||
pub mod resource_pack_stack;
|
||||
pub mod resource_packs_info;
|
||||
pub mod scoreboard;
|
||||
pub mod set_actor_data;
|
||||
pub mod set_actor_motion;
|
||||
pub mod set_health;
|
||||
@ -29,6 +31,7 @@ pub mod update_abilities;
|
||||
pub mod update_attributes;
|
||||
|
||||
pub use available_commands::*;
|
||||
pub use boss_event::*;
|
||||
pub use chunk_radius_update::*;
|
||||
pub use container_open::*;
|
||||
pub use correct_player_move::*;
|
||||
@ -48,6 +51,7 @@ pub use player_hotbar::*;
|
||||
pub use raknet::*;
|
||||
pub use resource_pack_stack::*;
|
||||
pub use resource_packs_info::*;
|
||||
pub use scoreboard::*;
|
||||
pub use set_actor_data::*;
|
||||
pub use set_actor_motion::*;
|
||||
pub use set_health::*;
|
||||
|
||||
55
pumpkin-protocol/src/bedrock/client/scoreboard.rs
Normal file
55
pumpkin-protocol/src/bedrock/client/scoreboard.rs
Normal file
@ -0,0 +1,55 @@
|
||||
use std::io::{Error, Write};
|
||||
|
||||
use crate::{codec::var_int::VarInt, serial::PacketWrite};
|
||||
use pumpkin_macros::packet;
|
||||
|
||||
#[derive(PacketWrite)]
|
||||
#[packet(107)]
|
||||
pub struct CSetDisplayObjective {
|
||||
pub display_slot: String,
|
||||
pub objective_name: String,
|
||||
pub display_name: String,
|
||||
pub criteria_name: String,
|
||||
pub sort_order: VarInt,
|
||||
}
|
||||
|
||||
#[derive(PacketWrite)]
|
||||
#[packet(108)]
|
||||
pub struct CSetScore {
|
||||
pub action: VarInt, // 0 = change, 1 = remove
|
||||
pub entries: Vec<ScoreEntry>,
|
||||
}
|
||||
|
||||
pub struct ScoreEntry {
|
||||
pub scoreboard_id: i64,
|
||||
pub objective_name: String,
|
||||
pub score: VarInt,
|
||||
pub entry_type: VarInt, // 1 = player, 2 = entity, 3 = fake player
|
||||
pub entity_unique_id: i64,
|
||||
pub custom_name: String,
|
||||
}
|
||||
|
||||
impl PacketWrite for ScoreEntry {
|
||||
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
self.scoreboard_id.write(writer)?;
|
||||
self.objective_name.write(writer)?;
|
||||
self.score.write(writer)?;
|
||||
self.entry_type.write(writer)?;
|
||||
match self.entry_type.0 {
|
||||
1 | 2 => {
|
||||
self.entity_unique_id.write(writer)?;
|
||||
}
|
||||
3 => {
|
||||
self.custom_name.write(writer)?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PacketWrite)]
|
||||
#[packet(106)]
|
||||
pub struct CRemoveObjective {
|
||||
pub objective_name: String,
|
||||
}
|
||||
@ -215,6 +215,7 @@ impl boss_bar::HostBossBar for PluginHostState {
|
||||
&pbb.bossbar.uuid,
|
||||
pbb.bossbar.color,
|
||||
pbb.bossbar.division,
|
||||
pbb.bossbar.flags,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
@ -243,6 +244,7 @@ impl boss_bar::HostBossBar for PluginHostState {
|
||||
&pbb.bossbar.uuid,
|
||||
pbb.bossbar.color,
|
||||
pbb.bossbar.division,
|
||||
pbb.bossbar.flags,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
@ -47,7 +47,8 @@ impl scoreboard::HostScoreboard for PluginHostState {
|
||||
.scoreboard
|
||||
.lock()
|
||||
.await
|
||||
.add_objective(&world, objective);
|
||||
.add_objective(&world, objective)
|
||||
.await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -61,7 +62,8 @@ impl scoreboard::HostScoreboard for PluginHostState {
|
||||
.scoreboard
|
||||
.lock()
|
||||
.await
|
||||
.remove_objective(&world, &name);
|
||||
.remove_objective(&world, &name)
|
||||
.await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -145,7 +147,12 @@ impl scoreboard::HostScoreboard for PluginHostState {
|
||||
None,
|
||||
None,
|
||||
);
|
||||
world.scoreboard.lock().await.update_score(&world, score);
|
||||
world
|
||||
.scoreboard
|
||||
.lock()
|
||||
.await
|
||||
.update_score(&world, score)
|
||||
.await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -160,7 +167,8 @@ impl scoreboard::HostScoreboard for PluginHostState {
|
||||
.scoreboard
|
||||
.lock()
|
||||
.await
|
||||
.remove_score(&world, &entity_name, &objective_name);
|
||||
.remove_score(&world, &entity_name, &objective_name)
|
||||
.await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
use crate::entity::player::Player;
|
||||
use crate::net::ClientPlatform;
|
||||
use bitflags::bitflags;
|
||||
use pumpkin_protocol::bedrock::client::boss_event::{BossEventAction, CBossEvent as BBossEvent};
|
||||
use pumpkin_protocol::codec::var_int::VarInt;
|
||||
use pumpkin_protocol::codec::var_long::VarLong;
|
||||
use pumpkin_protocol::java::client::play::{BosseventAction, CBossEvent};
|
||||
use pumpkin_util::text::TextComponent;
|
||||
use uuid::Uuid;
|
||||
@ -15,6 +19,21 @@ pub enum BossbarColor {
|
||||
White,
|
||||
}
|
||||
|
||||
impl BossbarColor {
|
||||
#[must_use]
|
||||
pub const fn to_bedrock(self) -> VarInt {
|
||||
match self {
|
||||
Self::Pink => VarInt(0),
|
||||
Self::Blue => VarInt(1),
|
||||
Self::Red => VarInt(2),
|
||||
Self::Green => VarInt(3),
|
||||
Self::Yellow => VarInt(4),
|
||||
Self::Purple => VarInt(5),
|
||||
Self::White => VarInt(6),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub enum BossbarDivisions {
|
||||
NoDivision,
|
||||
@ -24,6 +43,19 @@ pub enum BossbarDivisions {
|
||||
Notches20,
|
||||
}
|
||||
|
||||
impl BossbarDivisions {
|
||||
#[must_use]
|
||||
pub const fn to_bedrock(self) -> VarInt {
|
||||
match self {
|
||||
Self::NoDivision => VarInt(0),
|
||||
Self::Notches6 => VarInt(1),
|
||||
Self::Notches10 => VarInt(2),
|
||||
Self::Notches12 => VarInt(3),
|
||||
Self::Notches20 => VarInt(4),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct BossbarFlags: u8 {
|
||||
@ -62,37 +94,87 @@ impl Bossbar {
|
||||
/// Extra methods for [`Player`] to send and manage the bossbar.
|
||||
impl Player {
|
||||
pub async fn send_bossbar(&self, bossbar: &Bossbar) {
|
||||
let boss_action = BosseventAction::Add {
|
||||
title: bossbar.title.clone(),
|
||||
health: bossbar.health,
|
||||
color: (bossbar.color as u8).into(),
|
||||
division: (bossbar.division as u8).into(),
|
||||
flags: bossbar.flags.bits(),
|
||||
};
|
||||
match &self.client {
|
||||
ClientPlatform::Java(java) => {
|
||||
let boss_action = BosseventAction::Add {
|
||||
title: bossbar.title.clone(),
|
||||
health: bossbar.health,
|
||||
color: (bossbar.color as u8).into(),
|
||||
division: (bossbar.division as u8).into(),
|
||||
flags: bossbar.flags.bits(),
|
||||
};
|
||||
|
||||
let packet = CBossEvent::new(&bossbar.uuid, boss_action);
|
||||
self.client.enqueue_packet(&packet).await;
|
||||
let packet = CBossEvent::new(&bossbar.uuid, boss_action);
|
||||
java.enqueue_packet(&packet).await;
|
||||
}
|
||||
ClientPlatform::Bedrock(bedrock) => {
|
||||
let packet = BBossEvent {
|
||||
boss_entity_id: VarLong(bossbar.uuid.as_u128() as i64),
|
||||
action: BossEventAction::Add {
|
||||
title: bossbar.title.clone().get_text(),
|
||||
health_percent: bossbar.health,
|
||||
screen_darken: u16::from(bossbar.flags.contains(BossbarFlags::DARKEN_SKY)),
|
||||
color: bossbar.color.to_bedrock(),
|
||||
overlay: bossbar.division.to_bedrock(),
|
||||
},
|
||||
};
|
||||
bedrock.send_game_packet(&packet).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn remove_bossbar(&self, uuid: Uuid) {
|
||||
let boss_action = BosseventAction::Remove;
|
||||
match &self.client {
|
||||
ClientPlatform::Java(java) => {
|
||||
let boss_action = BosseventAction::Remove;
|
||||
|
||||
let packet = CBossEvent::new(&uuid, boss_action);
|
||||
self.client.enqueue_packet(&packet).await;
|
||||
let packet = CBossEvent::new(&uuid, boss_action);
|
||||
java.enqueue_packet(&packet).await;
|
||||
}
|
||||
ClientPlatform::Bedrock(bedrock) => {
|
||||
let packet = BBossEvent {
|
||||
boss_entity_id: VarLong(uuid.as_u128() as i64),
|
||||
action: BossEventAction::Remove,
|
||||
};
|
||||
bedrock.send_game_packet(&packet).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn update_bossbar_health(&self, uuid: &Uuid, health: f32) {
|
||||
let boss_action = BosseventAction::UpdateHealth(health);
|
||||
match &self.client {
|
||||
ClientPlatform::Java(java) => {
|
||||
let boss_action = BosseventAction::UpdateHealth(health);
|
||||
|
||||
let packet = CBossEvent::new(uuid, boss_action);
|
||||
self.client.enqueue_packet(&packet).await;
|
||||
let packet = CBossEvent::new(uuid, boss_action);
|
||||
java.enqueue_packet(&packet).await;
|
||||
}
|
||||
ClientPlatform::Bedrock(bedrock) => {
|
||||
let packet = BBossEvent {
|
||||
boss_entity_id: VarLong(uuid.as_u128() as i64),
|
||||
action: BossEventAction::UpdateHealth(health),
|
||||
};
|
||||
bedrock.send_game_packet(&packet).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn update_bossbar_title(&self, uuid: &Uuid, title: TextComponent) {
|
||||
let boss_action = BosseventAction::UpdateTile(title);
|
||||
match &self.client {
|
||||
ClientPlatform::Java(java) => {
|
||||
let boss_action = BosseventAction::UpdateTile(title);
|
||||
|
||||
let packet = CBossEvent::new(uuid, boss_action);
|
||||
self.client.enqueue_packet(&packet).await;
|
||||
let packet = CBossEvent::new(uuid, boss_action);
|
||||
java.enqueue_packet(&packet).await;
|
||||
}
|
||||
ClientPlatform::Bedrock(bedrock) => {
|
||||
let packet = BBossEvent {
|
||||
boss_entity_id: VarLong(uuid.as_u128() as i64),
|
||||
action: BossEventAction::UpdateTitle(title.get_text()),
|
||||
};
|
||||
bedrock.send_game_packet(&packet).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn update_bossbar_style(
|
||||
@ -100,20 +182,56 @@ impl Player {
|
||||
uuid: &Uuid,
|
||||
color: BossbarColor,
|
||||
dividers: BossbarDivisions,
|
||||
flags: BossbarFlags,
|
||||
) {
|
||||
let boss_action = BosseventAction::UpdateStyle {
|
||||
color: (color as u8).into(),
|
||||
dividers: (dividers as u8).into(),
|
||||
};
|
||||
match &self.client {
|
||||
ClientPlatform::Java(java) => {
|
||||
let boss_action = BosseventAction::UpdateStyle {
|
||||
color: (color as u8).into(),
|
||||
dividers: (dividers as u8).into(),
|
||||
};
|
||||
|
||||
let packet = CBossEvent::new(uuid, boss_action);
|
||||
self.client.enqueue_packet(&packet).await;
|
||||
let packet = CBossEvent::new(uuid, boss_action);
|
||||
java.enqueue_packet(&packet).await;
|
||||
}
|
||||
ClientPlatform::Bedrock(bedrock) => {
|
||||
let packet = BBossEvent {
|
||||
boss_entity_id: VarLong(uuid.as_u128() as i64),
|
||||
action: BossEventAction::UpdateProperties {
|
||||
screen_darken: u16::from(flags.contains(BossbarFlags::DARKEN_SKY)),
|
||||
color: color.to_bedrock(),
|
||||
overlay: dividers.to_bedrock(),
|
||||
},
|
||||
};
|
||||
bedrock.send_game_packet(&packet).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn update_bossbar_flags(&self, uuid: &Uuid, flags: BossbarFlags) {
|
||||
let boss_action = BosseventAction::UpdateFlags(flags.bits());
|
||||
match &self.client {
|
||||
ClientPlatform::Java(java) => {
|
||||
let boss_action = BosseventAction::UpdateFlags(flags.bits());
|
||||
|
||||
let packet = CBossEvent::new(uuid, boss_action);
|
||||
self.client.enqueue_packet(&packet).await;
|
||||
let packet = CBossEvent::new(uuid, boss_action);
|
||||
java.enqueue_packet(&packet).await;
|
||||
}
|
||||
ClientPlatform::Bedrock(bedrock) => {
|
||||
// For Bedrock, flags are part of properties (screen darken)
|
||||
// We don't have color and dividers here, so we might need more info or just skip if not critical
|
||||
// Actually, properties includes screen_darken, color, and overlay.
|
||||
// Since this method only has flags, we might need to store the current color/division on the player
|
||||
// or retrieve them from the bossbar if we had a reference to it.
|
||||
let packet = BBossEvent {
|
||||
boss_entity_id: VarLong(uuid.as_u128() as i64),
|
||||
action: BossEventAction::UpdateProperties {
|
||||
screen_darken: u16::from(flags.contains(BossbarFlags::DARKEN_SKY)),
|
||||
color: VarInt(0),
|
||||
overlay: VarInt(0),
|
||||
},
|
||||
};
|
||||
bedrock.send_game_packet(&packet).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -294,6 +294,7 @@ impl CustomBossbars {
|
||||
&bossbar.bossbar_data.uuid,
|
||||
bossbar.bossbar_data.color,
|
||||
bossbar.bossbar_data.division,
|
||||
bossbar.bossbar_data.flags,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
@ -333,6 +334,7 @@ impl CustomBossbars {
|
||||
&bossbar.bossbar_data.uuid,
|
||||
bossbar.bossbar_data.color,
|
||||
bossbar.bossbar_data.division,
|
||||
bossbar.bossbar_data.flags,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
@ -2,11 +2,15 @@ use std::collections::HashMap;
|
||||
|
||||
use pumpkin_data::scoreboard::ScoreboardDisplaySlot;
|
||||
use pumpkin_protocol::{
|
||||
NumberFormat,
|
||||
BClientPacket, ClientPacket, NumberFormat,
|
||||
bedrock::client::scoreboard::{
|
||||
CRemoveObjective as BRemoveObjective, CSetDisplayObjective as BSetDisplayObjective,
|
||||
CSetScore as BSetScore, ScoreEntry as BScoreEntry,
|
||||
},
|
||||
codec::var_int::VarInt,
|
||||
java::client::play::{
|
||||
CDisplayObjective, CSetPlayerTeam, CUpdateObjectives, CUpdateScore, RenderType, TeamMethod,
|
||||
TeamParameters,
|
||||
CDisplayObjective, CSetPlayerTeam, CUpdateObjectives, CUpdateScore, Mode, RenderType,
|
||||
TeamMethod, TeamParameters,
|
||||
},
|
||||
};
|
||||
use pumpkin_util::text::{TextComponent, color::NamedColor};
|
||||
@ -22,7 +26,15 @@ pub struct Scoreboard {
|
||||
}
|
||||
|
||||
impl Scoreboard {
|
||||
pub fn add_objective(&mut self, world: &World, objective: ScoreboardObjective<'static>) {
|
||||
async fn broadcast_editioned<J: ClientPacket, B: BClientPacket>(
|
||||
world: &World,
|
||||
je_packet: &J,
|
||||
be_packet: &B,
|
||||
) {
|
||||
world.broadcast_editioned(je_packet, be_packet).await;
|
||||
}
|
||||
|
||||
pub async fn add_objective(&mut self, world: &World, objective: ScoreboardObjective<'static>) {
|
||||
if self.objectives.contains_key(objective.name) {
|
||||
warn!(
|
||||
"Tried to create an objective which already exists: {}",
|
||||
@ -30,22 +42,36 @@ impl Scoreboard {
|
||||
);
|
||||
return;
|
||||
}
|
||||
world.broadcast_packet_all(&CUpdateObjectives::new(
|
||||
|
||||
let je_update = CUpdateObjectives::new(
|
||||
objective.name.to_string(),
|
||||
pumpkin_protocol::java::client::play::Mode::Add,
|
||||
Mode::Add,
|
||||
objective.display_name.clone(),
|
||||
objective.render_type,
|
||||
objective.number_format.clone(),
|
||||
));
|
||||
world.broadcast_packet_all(&CDisplayObjective::new(
|
||||
ScoreboardDisplaySlot::Sidebar,
|
||||
objective.name.to_string(),
|
||||
));
|
||||
);
|
||||
|
||||
let be_update = BSetDisplayObjective {
|
||||
display_slot: "sidebar".to_string(), // Default to sidebar
|
||||
objective_name: objective.name.to_string(),
|
||||
display_name: objective.display_name.clone().get_text(),
|
||||
criteria_name: "dummy".to_string(),
|
||||
sort_order: VarInt(0),
|
||||
};
|
||||
|
||||
Self::broadcast_editioned(world, &je_update, &be_update).await;
|
||||
|
||||
let je_display =
|
||||
CDisplayObjective::new(ScoreboardDisplaySlot::Sidebar, objective.name.to_string());
|
||||
// Bedrock's SetDisplayObjective already sets the slot.
|
||||
|
||||
world.broadcast_packet_all(&je_display);
|
||||
|
||||
self.objectives
|
||||
.insert(objective.name.to_string(), objective);
|
||||
}
|
||||
|
||||
pub fn remove_objective(&mut self, world: &World, name: &str) {
|
||||
pub async fn remove_objective(&mut self, world: &World, name: &str) {
|
||||
if !self.objectives.contains_key(name) {
|
||||
warn!(
|
||||
"Tried to remove an objective which does not exist: {}",
|
||||
@ -53,18 +79,26 @@ impl Scoreboard {
|
||||
);
|
||||
return;
|
||||
}
|
||||
world.broadcast_packet_all(&CUpdateObjectives::new(
|
||||
|
||||
let je_packet = CUpdateObjectives::new(
|
||||
name.to_string(),
|
||||
pumpkin_protocol::java::client::play::Mode::Remove,
|
||||
Mode::Remove,
|
||||
TextComponent::empty(),
|
||||
pumpkin_protocol::java::client::play::RenderType::Integer,
|
||||
RenderType::Integer,
|
||||
None,
|
||||
));
|
||||
);
|
||||
|
||||
let be_packet = BRemoveObjective {
|
||||
objective_name: name.to_string(),
|
||||
};
|
||||
|
||||
Self::broadcast_editioned(world, &je_packet, &be_packet).await;
|
||||
|
||||
self.objectives.remove(name);
|
||||
self.scores.remove(name);
|
||||
}
|
||||
|
||||
pub fn update_score(&mut self, world: &World, score: ScoreboardScore<'static>) {
|
||||
pub async fn update_score(&mut self, world: &World, score: ScoreboardScore<'static>) {
|
||||
if !self.objectives.contains_key(score.objective_name) {
|
||||
warn!(
|
||||
"Tried to place a score into an objective which does not exist: {}",
|
||||
@ -72,13 +106,28 @@ impl Scoreboard {
|
||||
);
|
||||
return;
|
||||
}
|
||||
world.broadcast_packet_all(&CUpdateScore::new(
|
||||
|
||||
let je_packet = CUpdateScore::new(
|
||||
score.entity_name.to_string(),
|
||||
score.objective_name.to_string(),
|
||||
score.value,
|
||||
score.display_name.clone(),
|
||||
score.number_format.clone(),
|
||||
));
|
||||
);
|
||||
|
||||
let be_packet = BSetScore {
|
||||
action: VarInt(0), // Change
|
||||
entries: vec![BScoreEntry {
|
||||
scoreboard_id: score.entity_name.as_ptr() as i64, // Hacky ID
|
||||
objective_name: score.objective_name.to_string(),
|
||||
score: score.value,
|
||||
entry_type: VarInt(3), // Fake player/Literal
|
||||
entity_unique_id: 0,
|
||||
custom_name: score.entity_name.to_string(),
|
||||
}],
|
||||
};
|
||||
|
||||
Self::broadcast_editioned(world, &je_packet, &be_packet).await;
|
||||
|
||||
self.scores
|
||||
.entry(score.objective_name.to_string())
|
||||
@ -86,11 +135,23 @@ impl Scoreboard {
|
||||
.insert(score.entity_name.to_string(), score);
|
||||
}
|
||||
|
||||
pub fn remove_score(&mut self, world: &World, entity_name: &str, objective_name: &str) {
|
||||
world.broadcast_packet_all(&CUpdateScore::new_remove(
|
||||
entity_name.to_string(),
|
||||
objective_name.to_string(),
|
||||
));
|
||||
pub async fn remove_score(&mut self, world: &World, entity_name: &str, objective_name: &str) {
|
||||
let je_packet =
|
||||
CUpdateScore::new_remove(entity_name.to_string(), objective_name.to_string());
|
||||
|
||||
let be_packet = BSetScore {
|
||||
action: VarInt(1), // Remove
|
||||
entries: vec![BScoreEntry {
|
||||
scoreboard_id: entity_name.as_ptr() as i64,
|
||||
objective_name: objective_name.to_string(),
|
||||
score: VarInt(0),
|
||||
entry_type: VarInt(3),
|
||||
entity_unique_id: 0,
|
||||
custom_name: entity_name.to_string(),
|
||||
}],
|
||||
};
|
||||
|
||||
Self::broadcast_editioned(world, &je_packet, &be_packet).await;
|
||||
|
||||
if let Some(objective_scores) = self.scores.get_mut(objective_name) {
|
||||
objective_scores.remove(entity_name);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user