Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Boss Bar API #371

Merged
merged 26 commits into from
Jun 20, 2023
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
174bf05
Created valence_boss_bar crates and created the BossBar entity
Jun 16, 2023
9f0e790
Changed BossBarViewers struct's wrapped value
Jun 16, 2023
18924d8
Added boss bar despawn handler; Added project in workspace; Organized…
Jun 17, 2023
cfb7dca
Removed boss_bar test file from the module tree (it's not done yet)
Jun 17, 2023
eeda50f
Turned BossBar component into a Bundle; Edited the despawn handler
Jun 17, 2023
1992d1d
Added unit tests; Changed BossBarViewers component; Added Boss bar at…
Jun 17, 2023
ff97d90
Merge branch 'valence-rs:main' into main
pepperoni21 Jun 17, 2023
8991cc7
Code documentation; Removed useless methods
Jun 17, 2023
9b5039d
Handled player disconnection; Renaming
Jun 17, 2023
fa6a53b
Trying to fix clippy errors
Jun 17, 2023
d78e79a
Merge branch 'valence-rs:main' into main
pepperoni21 Jun 18, 2023
e9314f8
Formatted code
Jun 18, 2023
ac6cd66
Edited BossBarViewers properties names
Jun 18, 2023
1731842
Fixed Cargo.toml file; Boss bar viewers are now stored in BTreeSet; R…
Jun 19, 2023
dad2eab
Ran cargo fmt and fixed clippy warnings
Jun 19, 2023
f8ef4a7
Merge branch 'main' into main
pepperoni21 Jun 19, 2023
e17c859
Updated crates/README.md
Jun 19, 2023
6a42f92
Removed boss_bar dependency from playground
Jun 19, 2023
a79e6ac
Made BossBarViewers' old_viewers field pub(crate)
Jun 19, 2023
e0cd195
Fixed systems; Added client disconnection test
Jun 19, 2023
96a98d1
Improved code
Jun 19, 2023
7826698
Ordered client_disconnection system before boss_bar_viewers_update
Jun 19, 2023
dd3c75f
Exported boss_bar in the main valence crate; Added an example
Jun 20, 2023
6b62de6
Formatted code
Jun 20, 2023
6eb672f
Merge remote-tracking branch 'upstream/main'
Jun 20, 2023
4c77468
Fixed clippy error
Jun 20, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ valence_network.path = "crates/valence_network"
valence_player_list.path = "crates/valence_player_list"
valence_registry.path = "crates/valence_registry"
valence_world_border.path = "crates/valence_world_border"
valence_boss_bar.path = "crates/valence_boss_bar"
valence.path = "crates/valence"

zip = "0.6.3"
Expand Down
4 changes: 3 additions & 1 deletion crates/valence/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ keywords = ["minecraft", "gamedev", "server", "ecs"]
categories = ["game-engines"]

[features]
default = ["network", "player_list", "inventory", "anvil", "advancement", "world_border"]
default = ["network", "player_list", "inventory", "anvil", "advancement", "world_border", "boss_bar"]
network = ["dep:valence_network"]
player_list = ["dep:valence_player_list"]
inventory = ["dep:valence_inventory"]
anvil = ["dep:valence_anvil"]
advancement = ["dep:valence_advancement"]
world_border = ["dep:valence_world_border"]
boss_bar = ["dep:valence_boss_bar"]

[dependencies]
bevy_app.workspace = true
Expand All @@ -39,6 +40,7 @@ valence_inventory = { workspace = true, optional = true }
valence_anvil = { workspace = true, optional = true }
valence_advancement = { workspace = true, optional = true }
valence_world_border = { workspace = true, optional = true }
valence_boss_bar = { workspace = true, optional = true }


[dev-dependencies]
Expand Down
5 changes: 5 additions & 0 deletions crates/valence/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,11 @@ impl PluginGroup for DefaultPlugins {
group = group.add(valence_world_border::WorldBorderPlugin);
}

#[cfg(feature = "boss_bar")]
{
group = group.add(valence_boss_bar::BossBarPlugin);
}

group
}
}
1 change: 1 addition & 0 deletions crates/valence/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ impl_packet_list!(A, B, C, D, E, F, G, H, I);
impl_packet_list!(A, B, C, D, E, F, G, H, I, J);
impl_packet_list!(A, B, C, D, E, F, G, H, I, J, K);

mod boss_bar;
mod client;
mod example;
mod inventory;
Expand Down
178 changes: 178 additions & 0 deletions crates/valence/src/tests/boss_bar.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
use bevy_app::App;
use bevy_ecs::entity::Entity;
use valence_boss_bar::components::{
BossBarBundle, BossBarColor, BossBarDivision, BossBarFlags, BossBarHealth, BossBarStyle,
BossBarTitle, BossBarViewers,
};
use valence_boss_bar::packet::BossBarS2c;
use valence_core::despawn::Despawned;
use valence_core::text::Text;

use super::{scenario_single_client, MockClientHelper};

#[test]
fn test_intialize_on_join() {
let mut app = App::new();
let (client_ent, mut client_helper, instance_ent) = prepare(&mut app);

// Fetch the boss bar component
let mut boss_bar = app.world.get_mut::<BossBarViewers>(instance_ent).unwrap();
// Add our mock client to the viewers list
boss_bar.viewers.push(client_ent);

app.update();

// Check if a boss bar packet was sent
let frames = client_helper.collect_sent();
frames.assert_count::<BossBarS2c>(1);
}

#[test]
fn test_despawn() {
let mut app = App::new();
let (client_ent, mut client_helper, instance_ent) = prepare(&mut app);

// Fetch the boss bar component
let mut boss_bar = app.world.get_mut::<BossBarViewers>(instance_ent).unwrap();
// Add our mock client to the viewers list
boss_bar.viewers.push(client_ent);

app.update();

// Despawn the boss bar
app.world.entity_mut(instance_ent).insert(Despawned);

app.update();

// Check if a boss bar packet was sent in addition to the ADD packet, which
// should be a Remove packet
let frames = client_helper.collect_sent();
frames.assert_count::<BossBarS2c>(2);
pepperoni21 marked this conversation as resolved.
Show resolved Hide resolved
}

#[test]
fn test_title_update() {
let mut app = App::new();
let (client_ent, mut client_helper, instance_ent) = prepare(&mut app);

// Fetch the boss bar component
let mut boss_bar = app.world.get_mut::<BossBarViewers>(instance_ent).unwrap();
// Add our mock client to the viewers list
boss_bar.viewers.push(client_ent);

app.update();

// Update the title
app.world
.entity_mut(instance_ent)
.insert(BossBarTitle(Text::text("Test 2")));

app.update();

// Check if a boss bar packet was sent in addition to the ADD packet, which
// should be an UpdateTitle packet
let frames = client_helper.collect_sent();
frames.assert_count::<BossBarS2c>(2);
}

#[test]
fn test_health_update() {
let mut app = App::new();
let (client_ent, mut client_helper, instance_ent) = prepare(&mut app);

// Fetch the boss bar component
let mut boss_bar = app.world.get_mut::<BossBarViewers>(instance_ent).unwrap();
// Add our mock client to the viewers list
boss_bar.viewers.push(client_ent);

app.update();

// Update the health
app.world
.entity_mut(instance_ent)
.insert(BossBarHealth(0.5));

app.update();

// Check if a boss bar packet was sent in addition to the ADD packet, which
// should be an UpdateHealth packet
let frames = client_helper.collect_sent();
frames.assert_count::<BossBarS2c>(2);
}

#[test]
fn test_style_update() {
let mut app = App::new();
let (client_ent, mut client_helper, instance_ent) = prepare(&mut app);

// Fetch the boss bar component
let mut boss_bar = app.world.get_mut::<BossBarViewers>(instance_ent).unwrap();
// Add our mock client to the viewers list
boss_bar.viewers.push(client_ent);

app.update();

// Update the style
app.world.entity_mut(instance_ent).insert(BossBarStyle {
color: BossBarColor::Red,
division: BossBarDivision::TenNotches,
});

app.update();

// Check if a boss bar packet was sent in addition to the ADD packet, which
// should be an UpdateStyle packet
let frames = client_helper.collect_sent();
frames.assert_count::<BossBarS2c>(2);
}

#[test]
fn test_flags_update() {
let mut app = App::new();
let (client_ent, mut client_helper, instance_ent) = prepare(&mut app);

// Fetch the boss bar component
let mut boss_bar = app.world.get_mut::<BossBarViewers>(instance_ent).unwrap();
// Add our mock client to the viewers list
boss_bar.viewers.push(client_ent);

app.update();

// Update the flags
let mut new_flags = BossBarFlags::new();
new_flags.set_create_fog(true);
app.world.entity_mut(instance_ent).insert(new_flags);

app.update();

// Check if a boss bar packet was sent in addition to the ADD packet, which
// should be an UpdateFlags packet
let frames = client_helper.collect_sent();
frames.assert_count::<BossBarS2c>(2);
}

fn prepare(app: &mut App) -> (Entity, MockClientHelper, Entity) {
let (client_ent, mut client_helper) = scenario_single_client(app);

// Process a tick to get past the "on join" logic.
app.update();
client_helper.clear_sent();

// Insert a boss bar into the world
let boss_bar = app
.world
.spawn(BossBarBundle::new(
Text::text("Test"),
BossBarColor::Blue,
BossBarDivision::SixNotches,
BossBarFlags::new(),
))
.id();

for _ in 0..2 {
app.update();
}

client_helper.clear_sent();
(client_ent, client_helper, boss_bar)
}
20 changes: 20 additions & 0 deletions crates/valence_boss_bar/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[package]
name = "valence_boss_bar"
description = "Boss bar API for Valence"
readme = "README.md"
keywords = ["minecraft", "bossbar", "api"]
documentation.workspace = true
version.workspace = true
edition.workspace = true

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

pepperoni21 marked this conversation as resolved.
Show resolved Hide resolved
[dependencies]
valence_core.workspace = true
valence_network.workspace = true
valence_entity.workspace = true
valence_client.workspace = true
uuid.workspace = true
bitfield-struct.workspace = true
bevy_app.workspace = true
bevy_ecs.workspace = true
3 changes: 3 additions & 0 deletions crates/valence_boss_bar/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# valence_boss_bar

Valence's Boss Bar API
94 changes: 94 additions & 0 deletions crates/valence_boss_bar/src/components.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use bevy_ecs::prelude::{Bundle, Component, Entity};
use bitfield_struct::bitfield;
use valence_core::protocol::{Decode, Encode};
use valence_core::text::Text;
use valence_core::uuid::UniqueId;

/// The bundle of components that make up a boss bar.
#[derive(Bundle)]
pub struct BossBarBundle {
pub id: UniqueId,
pub title: BossBarTitle,
pub health: BossBarHealth,
pub style: BossBarStyle,
pub flags: BossBarFlags,
pub viewers: BossBarViewers,
}

impl BossBarBundle {
pub fn new(
title: Text,
color: BossBarColor,
division: BossBarDivision,
flags: BossBarFlags,
) -> BossBarBundle {
BossBarBundle {
id: UniqueId::default(),
title: BossBarTitle(title),
health: BossBarHealth(1.0),
style: BossBarStyle { color, division },
flags,
viewers: BossBarViewers::default(),
}
}
}

/// The title of a boss bar.
#[derive(Component, Clone)]
pub struct BossBarTitle(pub Text);

/// The health of a boss bar.
#[derive(Component)]
pub struct BossBarHealth(pub f32);

/// The style of a boss bar. This includes the color and division of the boss
/// bar.
#[derive(Component)]
pub struct BossBarStyle {
pub color: BossBarColor,
pub division: BossBarDivision,
}

/// The color of a boss bar.
#[derive(Component, Copy, Clone, PartialEq, Eq, Debug, Encode, Decode)]
pub enum BossBarColor {
Pink,
Blue,
Red,
Green,
Yellow,
Purple,
White,
}

/// The division of a boss bar.
#[derive(Component, Copy, Clone, PartialEq, Eq, Debug, Encode, Decode)]
pub enum BossBarDivision {
NoDivision,
SixNotches,
TenNotches,
TwelveNotches,
TwentyNotches,
}

/// The flags of a boss bar (darken sky, dragon bar, create fog).
#[bitfield(u8)]
#[derive(Component, PartialEq, Eq, Encode, Decode)]
pub struct BossBarFlags {
pub darken_sky: bool,
pub dragon_bar: bool,
pub create_fog: bool,
#[bits(5)]
_pad: u8,
}

/// The viewers of a boss bar.
#[derive(Component, Default)]
pub struct BossBarViewers {
/// The current viewers of the boss bar. It is the list that should be
/// updated.
pub viewers: Vec<Entity>,
/// The viewers of the last tick in order to determine which viewers have
/// been added and removed.
pub old_viewers: Vec<Entity>,
pepperoni21 marked this conversation as resolved.
Show resolved Hide resolved
pepperoni21 marked this conversation as resolved.
Show resolved Hide resolved
}
Loading