102 lines
3.4 KiB
Rust
102 lines
3.4 KiB
Rust
use godot::{classes::RichTextLabel, prelude::*};
|
|
|
|
use crate::{
|
|
announcer::Announcement,
|
|
game_manager::{Game, Player},
|
|
player::DamageSource,
|
|
};
|
|
|
|
#[derive(GodotClass)]
|
|
#[class(base=Node, init)]
|
|
pub struct Chat {
|
|
messages: Vec<ChatMessage>,
|
|
base: Base<Node>,
|
|
}
|
|
|
|
#[godot_api]
|
|
impl Chat {
|
|
#[signal]
|
|
pub fn on_new_message(idx: Gd<RichTextLabel>);
|
|
|
|
pub fn singleton() -> Option<Gd<Chat>> {
|
|
Game::singleton().and_then(|g| g.get_child(0).map(|c| c.cast()))
|
|
}
|
|
|
|
pub fn get_messages(&self) -> Vec<Gd<RichTextLabel>> {
|
|
self.messages.iter().map(|m| m.as_label()).collect()
|
|
}
|
|
|
|
pub fn new_message(&mut self, message: ChatMessage) {
|
|
self.messages.len() as i64;
|
|
self.messages.push(message.clone());
|
|
self.run_deferred(move |s| s.signals().on_new_message().emit(&message.as_label()));
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub enum ChatMessage {
|
|
Death(DamageSource, u16),
|
|
Announcement(u16, Announcement),
|
|
ChatMessage(String, Color, String),
|
|
}
|
|
|
|
impl ChatMessage {
|
|
pub fn as_label(&self) -> Gd<RichTextLabel> {
|
|
let mut label = RichTextLabel::new_alloc();
|
|
label.set_fit_content(true);
|
|
match self {
|
|
ChatMessage::Death(source, player_id) => {
|
|
if let Some(game) = Game::singleton()
|
|
&& let Some(player) = game.bind().find_player(*player_id)
|
|
{
|
|
match source {
|
|
DamageSource::Player(source_id) => {
|
|
if let Some(source) = game.bind().find_player(*source_id) {
|
|
add_player(&mut label, source);
|
|
label.append_text(" fragged ");
|
|
add_player(&mut label, &player);
|
|
}
|
|
}
|
|
DamageSource::Killbox(kind) => {
|
|
add_player(&mut label, &player);
|
|
label.append_text(&kind.as_kill_text());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
ChatMessage::Announcement(player_id, announcement) => {
|
|
if let Some(game) = Game::singleton()
|
|
&& let Some(player) = game.bind().find_player(*player_id)
|
|
{
|
|
add_player(&mut label, &player);
|
|
label.append_text(" got ");
|
|
let what = match announcement {
|
|
Announcement::FirstBlood => "First Blood",
|
|
Announcement::DoubleKill => "a Double Kill",
|
|
Announcement::TripleKill => "a Triple Kill",
|
|
Announcement::MegaKill => "a Mega Kill",
|
|
};
|
|
label.append_text(&format!("[color=red]{}[/color]", what));
|
|
}
|
|
}
|
|
ChatMessage::ChatMessage(name, color, message) => {
|
|
label.push_color(*color);
|
|
label.add_text(&format!("{}: ", name));
|
|
label.pop();
|
|
label.add_text(message);
|
|
}
|
|
}
|
|
label
|
|
}
|
|
}
|
|
|
|
fn add_player(label: &mut Gd<RichTextLabel>, player: &Player) {
|
|
if let Some(game) = Game::singleton()
|
|
&& let Some(team) = game.bind().get_team(player.data.team)
|
|
{
|
|
label.push_color(team.bind().color);
|
|
label.add_text(&player.data.name);
|
|
label.pop();
|
|
}
|
|
}
|