Skip to content

Commit

Permalink
Add Scoreboard support
Browse files Browse the repository at this point in the history
  • Loading branch information
Snowiiii committed Oct 18, 2024
1 parent 5d0bb14 commit 406db91
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 2 deletions.
2 changes: 1 addition & 1 deletion docs/troubleshooting/common_issues.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

**Cause:** The server is currently not calculating hit boxes for blocks, we're working on that.

3. The Server is unresponsive
3. ### The Server is unresponsive

**Issue:** You have to wait before reconnecting or can't do basic things while chunks are loading.

Expand Down
2 changes: 1 addition & 1 deletion pumpkin-protocol/src/client/play/c_update_objectives.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use pumpkin_core::text::{style::Style, TextComponent};
use pumpkin_core::text::TextComponent;
use pumpkin_macros::packet;

use crate::{ClientPacket, NumberFormat, VarInt};
Expand Down
2 changes: 2 additions & 0 deletions pumpkin-protocol/src/client/play/c_update_score.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use pumpkin_core::text::TextComponent;
use pumpkin_macros::packet;
use serde::Serialize;

use crate::{NumberFormat, VarInt};

#[derive(Serialize)]
#[packet(0x61)]
pub struct CUpdateScore<'a> {
entity_name: &'a str,
Expand Down
2 changes: 2 additions & 0 deletions pumpkin-protocol/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use bytebuf::{packet_id::Packet, ByteBuffer, DeserializerError};
use bytes::Buf;
use pumpkin_core::text::{style::Style, TextComponent};
use serde::{Deserialize, Serialize};
use std::io::{self, Write};
use thiserror::Error;
Expand Down Expand Up @@ -245,6 +246,7 @@ pub struct KnownPack<'a> {
pub version: &'a str,
}

#[derive(Serialize)]
pub enum NumberFormat<'a> {
/// Show nothing
Blank,
Expand Down
5 changes: 5 additions & 0 deletions pumpkin/src/world/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@ use pumpkin_protocol::{
ClientPacket, VarInt,
};
use pumpkin_world::level::Level;
use scoreboard::Scoreboard;
use tokio::sync::mpsc;

pub mod scoreboard;

/// Represents a Minecraft world, containing entities, players, and the underlying level data.
///
/// Each dimension (Overworld, Nether, End) typically has its own `World`.
Expand All @@ -35,6 +38,7 @@ pub struct World {
pub level: Arc<Mutex<Level>>,
/// A map of active players within the world, keyed by their unique token.
pub current_players: Arc<Mutex<HashMap<usize, Arc<Player>>>>,
pub scoreboard: Mutex<Scoreboard>,
// TODO: entities
}

Expand All @@ -43,6 +47,7 @@ impl World {
Self {
level: Arc::new(Mutex::new(level)),
current_players: Arc::new(Mutex::new(HashMap::new())),
scoreboard: Mutex::new(Scoreboard::new()),
}
}

Expand Down
123 changes: 123 additions & 0 deletions pumpkin/src/world/scoreboard.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
use std::collections::HashMap;

use pumpkin_core::text::TextComponent;
use pumpkin_protocol::{
client::play::{CDisplayObjective, CUpdateObjectives, CUpdateScore, RenderType},
NumberFormat, VarInt,
};

use super::World;

pub struct Scoreboard {
objectives: HashMap<String, ScoreboardObjective<'static>>,
// teams: HashMap<String, Team>,
}

impl Default for Scoreboard {
fn default() -> Self {
Self::new()
}
}

impl Scoreboard {
pub fn new() -> Self {
Self {
objectives: HashMap::new(),
}
}

pub fn add_objective(&mut self, world: &World, objective: ScoreboardObjective) {
if self.objectives.contains_key(objective.name) {
// Maybe make this an error ?
log::warn!(
"Tried to create Objective which does already exist, {}",
&objective.name
);
return;
}
world.broadcast_packet_all(&CUpdateObjectives::new(
objective.name,
pumpkin_protocol::client::play::Mode::Add,
objective.display_name,
objective.render_type,
objective.number_format,
));
world.broadcast_packet_all(&CDisplayObjective::new(
pumpkin_protocol::client::play::DisplaySlot::Sidebar,
"test",
));
}

pub fn update_score(&self, world: &World, score: ScoreboardScore) {
if self.objectives.contains_key(score.objective_name) {
log::warn!(
"Tried to place a score into a Objective which does not exist, {}",
&score.objective_name
);
return;
}
world.broadcast_packet_all(&CUpdateScore::new(
score.entity_name,
score.objective_name,
score.value,
score.display_name,
score.number_format,
));
}

// pub fn add_team(&mut self, name: String) {
// if self.teams.contains_key(&name) {
// // Maybe make this an error ?
// log::warn!("Tried to create Team which does already exist, {}", name);
// }
// }
}

pub struct ScoreboardObjective<'a> {
name: &'a str,
display_name: TextComponent<'a>,
render_type: RenderType,
number_format: Option<NumberFormat<'a>>,
}

impl<'a> ScoreboardObjective<'a> {
pub const fn new(
name: &'a str,
display_name: TextComponent<'a>,
render_type: RenderType,
number_format: Option<NumberFormat<'a>>,
) -> Self {
Self {
name,
display_name,
render_type,
number_format,
}
}
}

pub struct ScoreboardScore<'a> {
entity_name: &'a str,
objective_name: &'a str,
value: VarInt,
display_name: Option<TextComponent<'a>>,
number_format: Option<NumberFormat<'a>>,
}

impl<'a> ScoreboardScore<'a> {
pub const fn new(
entity_name: &'a str,
objective_name: &'a str,
value: VarInt,
display_name: Option<TextComponent<'a>>,
number_format: Option<NumberFormat<'a>>,
) -> Self {
Self {
entity_name,
objective_name,
value,
display_name,
number_format,
}
}
}

0 comments on commit 406db91

Please sign in to comment.