mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
fix chat-cli name formatting.
This commit is contained in:
parent
4117f2f2a8
commit
aabf9d7b21
@ -84,8 +84,7 @@ fn main() {
|
|||||||
|
|
||||||
for event in events {
|
for event in events {
|
||||||
match event {
|
match event {
|
||||||
// TODO client is now responsible for formatting the `[{player_name}] {}`
|
Event::Chat(m) => println!("{}", client.format_message(&m)),
|
||||||
Event::Chat(m) => println!("{}", m.message),
|
|
||||||
Event::Disconnect => {}, // TODO
|
Event::Disconnect => {}, // TODO
|
||||||
Event::DisconnectionNotification(time) => {
|
Event::DisconnectionNotification(time) => {
|
||||||
let message = match time {
|
let message = match time {
|
||||||
|
@ -1007,6 +1007,50 @@ impl Client {
|
|||||||
|
|
||||||
self.entity = entity_builder.with(uid).build();
|
self.entity = entity_builder.with(uid).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Format a message for the client (voxygen chat box or chat-cli)
|
||||||
|
pub fn format_message(&self, comp::ChatMsg { chat_type, message }: &comp::ChatMsg) -> String {
|
||||||
|
let alias_of_uid = |uid| {
|
||||||
|
self.player_list
|
||||||
|
.get(uid)
|
||||||
|
.map_or("<?>".to_string(), |player_info| {
|
||||||
|
if player_info.is_admin {
|
||||||
|
format!("ADMIN - {}", player_info.player_alias)
|
||||||
|
} else {
|
||||||
|
player_info.player_alias.to_string()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
let message_format = |uid, message, group| {
|
||||||
|
if let Some(group) = group {
|
||||||
|
format!("{{{}}} [{}]: {}", group, alias_of_uid(uid), message)
|
||||||
|
} else {
|
||||||
|
format!("[{}]: {}", alias_of_uid(uid), message)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
match chat_type {
|
||||||
|
comp::ChatType::Private => message.to_string(),
|
||||||
|
comp::ChatType::Broadcast => message.to_string(),
|
||||||
|
comp::ChatType::Kill => message.to_string(),
|
||||||
|
comp::ChatType::Tell(from, to) => {
|
||||||
|
let from_alias = alias_of_uid(from);
|
||||||
|
let to_alias = alias_of_uid(to);
|
||||||
|
if Some(from) == self.state.ecs().read_storage::<Uid>().get(self.entity) {
|
||||||
|
format!("To [{}]: {}", to_alias, message)
|
||||||
|
} else {
|
||||||
|
format!("From [{}]: {}", from_alias, message)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
comp::ChatType::Say(uid) => message_format(uid, message, None),
|
||||||
|
comp::ChatType::Group(uid, s) => message_format(uid, message, Some(s)),
|
||||||
|
comp::ChatType::Faction(uid, s) => message_format(uid, message, Some(s)),
|
||||||
|
comp::ChatType::Region(uid) => message_format(uid, message, None),
|
||||||
|
comp::ChatType::World(uid) => message_format(uid, message, None),
|
||||||
|
// NPCs can't talk. Should be filtered by hud/mod.rs for voxygen and should be filtered
|
||||||
|
// by server for chat-cli
|
||||||
|
comp::ChatType::Npc(_uid, _r) => "".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Client {
|
impl Drop for Client {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{path::Chaser, state::Time};
|
use crate::path::Chaser;
|
||||||
use specs::{Component, Entity as EcsEntity};
|
use specs::{Component, Entity as EcsEntity};
|
||||||
use specs_idvs::IDVStorage;
|
use specs_idvs::IDVStorage;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
@ -107,47 +107,3 @@ impl Activity {
|
|||||||
impl Default for Activity {
|
impl Default for Activity {
|
||||||
fn default() -> Self { Activity::Idle(Vec2::zero()) }
|
fn default() -> Self { Activity::Idle(Vec2::zero()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Default duration in seconds of speech bubbles
|
|
||||||
pub const SPEECH_BUBBLE_DURATION: f64 = 5.0;
|
|
||||||
|
|
||||||
/// The contents of a speech bubble
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub enum SpeechBubbleMessage {
|
|
||||||
/// This message was said by a player and needs no translation
|
|
||||||
Plain(String),
|
|
||||||
/// This message was said by an NPC. The fields are a i18n key and a random
|
|
||||||
/// u16 index
|
|
||||||
Localized(String, u16),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Adds a speech bubble to the entity
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub struct SpeechBubble {
|
|
||||||
pub message: SpeechBubbleMessage,
|
|
||||||
pub timeout: Option<Time>,
|
|
||||||
// TODO add icon enum for player chat type / npc quest+trade
|
|
||||||
}
|
|
||||||
impl SpeechBubble {
|
|
||||||
pub fn npc_new(i18n_key: String, now: Time) -> Self {
|
|
||||||
let message = SpeechBubbleMessage::Localized(i18n_key, rand::random());
|
|
||||||
let timeout = Some(Time(now.0 + SPEECH_BUBBLE_DURATION));
|
|
||||||
Self { message, timeout }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn player_new(message: String, now: Time) -> Self {
|
|
||||||
let message = SpeechBubbleMessage::Plain(message);
|
|
||||||
let timeout = Some(Time(now.0 + SPEECH_BUBBLE_DURATION));
|
|
||||||
Self { message, timeout }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn message<F>(&self, i18n_variation: F) -> String
|
|
||||||
where
|
|
||||||
F: Fn(String, u16) -> String,
|
|
||||||
{
|
|
||||||
match &self.message {
|
|
||||||
SpeechBubbleMessage::Plain(m) => m.to_string(),
|
|
||||||
SpeechBubbleMessage::Localized(k, i) => i18n_variation(k.to_string(), *i),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -24,6 +24,7 @@ fn main() {
|
|||||||
|
|
||||||
// Load settings
|
// Load settings
|
||||||
let settings = ServerSettings::load();
|
let settings = ServerSettings::load();
|
||||||
|
let server_port = &settings.gameserver_address.port();
|
||||||
let metrics_port = &settings.metrics_address.port();
|
let metrics_port = &settings.metrics_address.port();
|
||||||
|
|
||||||
// Create server
|
// Create server
|
||||||
@ -31,6 +32,7 @@ fn main() {
|
|||||||
|
|
||||||
info!("Server is ready to accept connections.");
|
info!("Server is ready to accept connections.");
|
||||||
info!(?metrics_port, "starting metrics at port");
|
info!(?metrics_port, "starting metrics at port");
|
||||||
|
info!(?server_port, "starting server at port");
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let events = server
|
let events = server
|
||||||
|
@ -18,7 +18,6 @@ use conrod_core::{
|
|||||||
widget::{self, Button, Id, Image, List, Rectangle, Text, TextEdit},
|
widget::{self, Button, Id, Image, List, Rectangle, Text, TextEdit},
|
||||||
widget_ids, Color, Colorable, Positionable, Sizeable, Ui, UiCell, Widget, WidgetCommon,
|
widget_ids, Color, Colorable, Positionable, Sizeable, Ui, UiCell, Widget, WidgetCommon,
|
||||||
};
|
};
|
||||||
use specs::world::WorldExt;
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
widget_ids! {
|
widget_ids! {
|
||||||
@ -35,6 +34,7 @@ widget_ids! {
|
|||||||
const MAX_MESSAGES: usize = 100;
|
const MAX_MESSAGES: usize = 100;
|
||||||
|
|
||||||
const CHAT_BOX_WIDTH: f64 = 470.0;
|
const CHAT_BOX_WIDTH: f64 = 470.0;
|
||||||
|
const CHAT_BOX_INPUT_WIDTH: f64 = 460.0;
|
||||||
const CHAT_BOX_HEIGHT: f64 = 174.0;
|
const CHAT_BOX_HEIGHT: f64 = 174.0;
|
||||||
|
|
||||||
#[derive(WidgetCommon)]
|
#[derive(WidgetCommon)]
|
||||||
@ -279,7 +279,7 @@ impl<'a> Widget for Chat<'a> {
|
|||||||
// Any changes to this TextEdit's width and font size must be reflected in
|
// Any changes to this TextEdit's width and font size must be reflected in
|
||||||
// `cursor_offset_to_index` below.
|
// `cursor_offset_to_index` below.
|
||||||
let mut text_edit = TextEdit::new(&state.input)
|
let mut text_edit = TextEdit::new(&state.input)
|
||||||
.w(460.0)
|
.w(CHAT_BOX_INPUT_WIDTH)
|
||||||
.restrict_to_height(false)
|
.restrict_to_height(false)
|
||||||
.color(TEXT_COLOR)
|
.color(TEXT_COLOR)
|
||||||
.line_spacing(2.0)
|
.line_spacing(2.0)
|
||||||
@ -340,8 +340,9 @@ impl<'a> Widget for Chat<'a> {
|
|||||||
while let Some(item) = items.next(ui) {
|
while let Some(item) = items.next(ui) {
|
||||||
// This would be easier if conrod used the v-metrics from rusttype.
|
// This would be easier if conrod used the v-metrics from rusttype.
|
||||||
if item.i < state.messages.len() {
|
if item.i < state.messages.len() {
|
||||||
let (color, msg, icon) =
|
let message = &state.messages[item.i];
|
||||||
render_chat_line(&state.messages[item.i], &self.imgs, &self.client);
|
let (color, icon) = render_chat_line(&message.chat_type, &self.imgs);
|
||||||
|
let msg = self.client.format_message(message);
|
||||||
let text = Text::new(&msg)
|
let text = Text::new(&msg)
|
||||||
.font_size(self.fonts.opensans.scale(15))
|
.font_size(self.fonts.opensans.scale(15))
|
||||||
.font_id(self.fonts.opensans.conrod_id)
|
.font_id(self.fonts.opensans.conrod_id)
|
||||||
@ -471,99 +472,27 @@ fn cursor_offset_to_index(
|
|||||||
fonts: &ConrodVoxygenFonts,
|
fonts: &ConrodVoxygenFonts,
|
||||||
) -> Option<Index> {
|
) -> Option<Index> {
|
||||||
// This moves the cursor to the given offset. Conrod is a pain.
|
// This moves the cursor to the given offset. Conrod is a pain.
|
||||||
//let iter = cursor::xys_per_line_from_text(&text, &[], &font, font_size,
|
//
|
||||||
// Justify::Left, Align::Start, 2.0, Rect{x: Range{start: 0.0, end: width}, y:
|
// Width and font must match that of the chat TextEdit
|
||||||
// Range{start: 0.0, end: 12.345}});
|
|
||||||
// cursor::closest_cursor_index_and_xy([f64::MAX, f64::MAX], iter).map(|(i, _)|
|
|
||||||
// i) Width and font must match that of the chat TextEdit
|
|
||||||
let width = 460.0;
|
|
||||||
let font = ui.fonts.get(fonts.opensans.conrod_id)?;
|
let font = ui.fonts.get(fonts.opensans.conrod_id)?;
|
||||||
let font_size = fonts.opensans.scale(15);
|
let font_size = fonts.opensans.scale(15);
|
||||||
let infos = text::line::infos(&text, &font, font_size).wrap_by_whitespace(width);
|
let infos = text::line::infos(&text, &font, font_size).wrap_by_whitespace(CHAT_BOX_INPUT_WIDTH);
|
||||||
|
|
||||||
cursor::index_before_char(infos, offset)
|
cursor::index_before_char(infos, offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_chat_line(
|
/// Get the color and icon for the current line in the chat box
|
||||||
ChatMsg { chat_type, message }: &ChatMsg,
|
fn render_chat_line(chat_type: &ChatType, imgs: &Imgs) -> (Color, conrod_core::image::Id) {
|
||||||
imgs: &Imgs,
|
|
||||||
client: &Client,
|
|
||||||
) -> (Color, String, conrod_core::image::Id) {
|
|
||||||
let alias_of_uid = |uid| {
|
|
||||||
client
|
|
||||||
.player_list
|
|
||||||
.get(uid)
|
|
||||||
.map_or("<?>".to_string(), |player_info| {
|
|
||||||
if player_info.is_admin {
|
|
||||||
format!("ADMIN - {}", player_info.player_alias)
|
|
||||||
} else {
|
|
||||||
player_info.player_alias.to_string()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
};
|
|
||||||
let message_format = |uid, message, group| {
|
|
||||||
if let Some(group) = group {
|
|
||||||
format!("{{{}}} [{}]: {}", group, alias_of_uid(uid), message)
|
|
||||||
} else {
|
|
||||||
format!("[{}]: {}", alias_of_uid(uid), message)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
match chat_type {
|
match chat_type {
|
||||||
ChatType::Private => (PRIVATE_COLOR, message.to_string(), imgs.chat_private_small),
|
ChatType::Private => (PRIVATE_COLOR, imgs.chat_private_small),
|
||||||
ChatType::Broadcast => (
|
ChatType::Broadcast => (BROADCAST_COLOR, imgs.chat_broadcast_small),
|
||||||
BROADCAST_COLOR,
|
ChatType::Kill => (KILL_COLOR, imgs.chat_kill_small),
|
||||||
message.to_string(),
|
ChatType::Tell(_from, _to) => (TELL_COLOR, imgs.chat_tell_small),
|
||||||
imgs.chat_broadcast_small,
|
ChatType::Say(_uid) => (SAY_COLOR, imgs.chat_say_small),
|
||||||
),
|
ChatType::Group(_uid, _s) => (GROUP_COLOR, imgs.chat_group_small),
|
||||||
ChatType::Kill => (KILL_COLOR, message.to_string(), imgs.chat_kill_small),
|
ChatType::Faction(_uid, _s) => (FACTION_COLOR, imgs.chat_faction_small),
|
||||||
ChatType::Tell(from, to) => {
|
ChatType::Region(_uid) => (REGION_COLOR, imgs.chat_region_small),
|
||||||
let from_alias = alias_of_uid(&from);
|
ChatType::World(_uid) => (WORLD_COLOR, imgs.chat_world_small),
|
||||||
let to_alias = alias_of_uid(&to);
|
|
||||||
if Some(from)
|
|
||||||
== client
|
|
||||||
.state()
|
|
||||||
.ecs()
|
|
||||||
.read_storage::<common::sync::Uid>()
|
|
||||||
.get(client.entity())
|
|
||||||
{
|
|
||||||
(
|
|
||||||
TELL_COLOR,
|
|
||||||
format!("To [{}]: {}", to_alias, message),
|
|
||||||
imgs.chat_tell_small,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
(
|
|
||||||
TELL_COLOR,
|
|
||||||
format!("From [{}]: {}", from_alias, message),
|
|
||||||
imgs.chat_tell_small,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ChatType::Say(uid) => (
|
|
||||||
SAY_COLOR,
|
|
||||||
message_format(uid, message, None),
|
|
||||||
imgs.chat_say_small,
|
|
||||||
),
|
|
||||||
ChatType::Group(uid, s) => (
|
|
||||||
GROUP_COLOR,
|
|
||||||
message_format(uid, message, Some(s)),
|
|
||||||
imgs.chat_group_small,
|
|
||||||
),
|
|
||||||
ChatType::Faction(uid, s) => (
|
|
||||||
FACTION_COLOR,
|
|
||||||
message_format(uid, message, Some(s)),
|
|
||||||
imgs.chat_faction_small,
|
|
||||||
),
|
|
||||||
ChatType::Region(uid) => (
|
|
||||||
REGION_COLOR,
|
|
||||||
message_format(uid, message, None),
|
|
||||||
imgs.chat_region_small,
|
|
||||||
),
|
|
||||||
ChatType::World(uid) => (
|
|
||||||
WORLD_COLOR,
|
|
||||||
message_format(uid, message, None),
|
|
||||||
imgs.chat_world_small,
|
|
||||||
),
|
|
||||||
ChatType::Npc(_uid, _r) => panic!("NPCs can't talk"), // Should be filtered by hud/mod.rs
|
ChatType::Npc(_uid, _r) => panic!("NPCs can't talk"), // Should be filtered by hud/mod.rs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user