Merge branch '194_different_colour_tells' into 'master'

Adds colour to tells in chat box, closes #194

Closes #194

See merge request veloren/veloren!342
This commit is contained in:
Joshua Barretto 2019-07-26 11:55:25 +00:00
commit c077c54690
10 changed files with 238 additions and 96 deletions

View File

@ -68,7 +68,7 @@ fn main() {
for event in events {
match event {
Event::Chat(msg) => println!("{}", msg),
Event::Chat { message, .. } => println!("{}", message),
Event::Disconnect => {} // TODO
}
}

View File

@ -14,6 +14,7 @@ use common::{
state::State,
terrain::{block::Block, chonk::ChonkMetrics, TerrainChunk, TerrainChunkSize},
vol::VolSize,
ChatType,
};
use log::{info, log_enabled, warn};
use std::{
@ -28,7 +29,10 @@ use vek::*;
const SERVER_TIMEOUT: Duration = Duration::from_secs(20);
pub enum Event {
Chat(String),
Chat {
chat_type: ChatType,
message: String,
},
Disconnect,
}
@ -187,7 +191,7 @@ impl Client {
/// Send a chat message to the server.
#[allow(dead_code)]
pub fn send_chat(&mut self, msg: String) {
self.postbox.send_message(ClientMsg::Chat(msg))
self.postbox.send_message(ClientMsg::chat(msg))
}
/// Remove all cached terrain
@ -385,7 +389,9 @@ impl Client {
.duration_since(self.last_server_ping)
.as_secs_f64()
}
ServerMsg::Chat(msg) => frontend_events.push(Event::Chat(msg)),
ServerMsg::ChatMsg { chat_type, message } => {
frontend_events.push(Event::Chat { chat_type, message })
}
ServerMsg::SetPlayerEntity(uid) => {
self.entity = self.state.ecs().entity_from_uid(uid).unwrap()
} // TODO: Don't unwrap here!

View File

@ -50,3 +50,12 @@ pub mod volumes;
/// assert_eq!("bar", scon.next_message().unwrap());
/// ```
pub mod net;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ChatType {
Broadcast,
Chat,
GameUpdate,
Private,
Tell,
}

View File

@ -1,6 +1,6 @@
use super::ClientState;
use crate::comp;
use crate::terrain::block::Block;
use crate::{comp, ChatType};
use vek::*;
#[derive(Debug, Clone, Serialize, Deserialize)]
@ -19,7 +19,10 @@ pub enum ClientMsg {
PlaceBlock(Vec3<i32>, Block),
Ping,
Pong,
Chat(String),
ChatMsg {
chat_type: ChatType,
message: String,
},
PlayerPhysics {
pos: comp::Pos,
vel: comp::Vel,
@ -30,3 +33,36 @@ pub enum ClientMsg {
},
Disconnect,
}
impl ClientMsg {
pub fn chat(message: String) -> ClientMsg {
ClientMsg::ChatMsg {
chat_type: ChatType::Chat,
message,
}
}
pub fn tell(message: String) -> ClientMsg {
ClientMsg::ChatMsg {
chat_type: ChatType::Tell,
message,
}
}
pub fn game(message: String) -> ClientMsg {
ClientMsg::ChatMsg {
chat_type: ChatType::GameUpdate,
message,
}
}
pub fn broadcast(message: String) -> ClientMsg {
ClientMsg::ChatMsg {
chat_type: ChatType::Broadcast,
message,
}
}
pub fn private(message: String) -> ClientMsg {
ClientMsg::ChatMsg {
chat_type: ChatType::Private,
message,
}
}
}

View File

@ -2,6 +2,7 @@ use super::{ClientState, EcsCompPacket, EcsResPacket};
use crate::{
comp,
terrain::{Block, TerrainChunk},
ChatType,
};
use fxhash::FxHashMap;
use vek::*;
@ -32,7 +33,10 @@ pub enum ServerMsg {
ForceState(ClientState),
Ping,
Pong,
Chat(String),
ChatMsg {
chat_type: ChatType,
message: String,
},
SetPlayerEntity(u64),
EcsSync(sphynx::SyncPackage<EcsCompPacket, EcsResPacket>),
EntityPhysics {
@ -57,3 +61,36 @@ pub enum ServerError {
TooManyPlayers,
//TODO: InvalidAlias,
}
impl ServerMsg {
pub fn chat(message: String) -> ServerMsg {
ServerMsg::ChatMsg {
chat_type: ChatType::Chat,
message,
}
}
pub fn tell(message: String) -> ServerMsg {
ServerMsg::ChatMsg {
chat_type: ChatType::Tell,
message,
}
}
pub fn game(message: String) -> ServerMsg {
ServerMsg::ChatMsg {
chat_type: ChatType::GameUpdate,
message,
}
}
pub fn broadcast(message: String) -> ServerMsg {
ServerMsg::ChatMsg {
chat_type: ChatType::Broadcast,
message,
}
}
pub fn private(message: String) -> ServerMsg {
ServerMsg::ChatMsg {
chat_type: ChatType::Private,
message,
}
}
}

View File

@ -3,7 +3,6 @@
//! and provide a handler function.
use crate::Server;
use common::comp::object::Body;
use common::{
comp,
msg::ServerMsg,
@ -166,13 +165,13 @@ fn handle_jump(server: &mut Server, entity: EcsEntity, args: String, action: &Ch
}
None => server.clients.notify(
entity,
ServerMsg::Chat(String::from("You have no position!")),
ServerMsg::private(String::from("You have no position!")),
),
}
}
_ => server
.clients
.notify(entity, ServerMsg::Chat(String::from(action.help_string))),
.notify(entity, ServerMsg::private(String::from(action.help_string))),
}
}
@ -188,12 +187,12 @@ fn handle_goto(server: &mut Server, entity: EcsEntity, args: String, action: &Ch
}
_ => server
.clients
.notify(entity, ServerMsg::Chat(String::from(action.help_string))),
.notify(entity, ServerMsg::private(String::from(action.help_string))),
},
None => {
server.clients.notify(
entity,
ServerMsg::Chat(String::from("You don't have any position!")),
ServerMsg::private(String::from("You don't have any position!")),
);
}
}
@ -219,16 +218,17 @@ fn handle_time(server: &mut Server, entity: EcsEntity, args: String, action: &Ch
Some(n) => match n.parse() {
Ok(n) => n,
Err(_) => {
server
.clients
.notify(entity, ServerMsg::Chat(format!("'{}' is not a time!", n)));
server.clients.notify(
entity,
ServerMsg::private(format!("'{}' is not a time!", n)),
);
return;
}
},
None => {
server.clients.notify(
entity,
ServerMsg::Chat("You must specify a time!".to_string()),
ServerMsg::private("You must specify a time!".to_string()),
);
return;
}
@ -249,13 +249,13 @@ fn handle_health(server: &mut Server, entity: EcsEntity, args: String, action: &
None => {
server.clients.notify(
entity,
ServerMsg::Chat(String::from("You must specify health amount!")),
ServerMsg::private(String::from("You must specify health amount!")),
);
}
},
None => server.clients.notify(
entity,
ServerMsg::Chat(String::from("You have no position.")),
ServerMsg::private(String::from("You have no position.")),
),
}
}
@ -273,7 +273,7 @@ fn handle_alias(server: &mut Server, entity: EcsEntity, args: String, action: &C
}
None => server
.clients
.notify(entity, ServerMsg::Chat(String::from(action.help_string))),
.notify(entity, ServerMsg::private(String::from(action.help_string))),
}
}
@ -295,29 +295,32 @@ fn handle_tp(server: &mut Server, entity: EcsEntity, args: String, action: &Chat
}
None => server.clients.notify(
entity,
ServerMsg::Chat(format!("Unable to teleport to player '{}'!", alias)),
ServerMsg::private(format!(
"Unable to teleport to player '{}'!",
alias
)),
),
},
None => {
server.clients.notify(
entity,
ServerMsg::Chat(format!("Player '{}' not found!", alias)),
ServerMsg::private(format!("Player '{}' not found!", alias)),
);
server
.clients
.notify(entity, ServerMsg::Chat(String::from(action.help_string)));
.notify(entity, ServerMsg::private(String::from(action.help_string)));
}
},
None => {
server
.clients
.notify(entity, ServerMsg::Chat(format!("You have no position!")));
.notify(entity, ServerMsg::private(format!("You have no position!")));
}
}
}
None => server
.clients
.notify(entity, ServerMsg::Chat(String::from(action.help_string))),
.notify(entity, ServerMsg::private(String::from(action.help_string))),
}
}
@ -351,17 +354,18 @@ fn handle_spawn(server: &mut Server, entity: EcsEntity, args: String, action: &C
}
server.clients.notify(
entity,
ServerMsg::Chat(format!("Spawned {} entities", amount).to_owned()),
ServerMsg::private(format!("Spawned {} entities", amount).to_owned()),
);
}
None => server
.clients
.notify(entity, ServerMsg::Chat("You have no position!".to_owned())),
None => server.clients.notify(
entity,
ServerMsg::private("You have no position!".to_owned()),
),
}
}
_ => server
.clients
.notify(entity, ServerMsg::Chat(String::from(action.help_string))),
.notify(entity, ServerMsg::private(String::from(action.help_string))),
}
}
@ -381,11 +385,11 @@ fn handle_players(server: &mut Server, entity: EcsEntity, _args: String, _action
server
.clients
.notify(entity, ServerMsg::Chat(header_message + &player_list));
.notify(entity, ServerMsg::private(header_message + &player_list));
} else {
server
.clients
.notify(entity, ServerMsg::Chat(header_message));
.notify(entity, ServerMsg::private(header_message));
}
}
@ -403,7 +407,7 @@ fn handle_build(server: &mut Server, entity: EcsEntity, _args: String, _action:
.remove(entity);
server.clients.notify(
entity,
ServerMsg::Chat(String::from("Toggled off build mode!")),
ServerMsg::private(String::from("Toggled off build mode!")),
);
} else {
let _ = server
@ -413,7 +417,7 @@ fn handle_build(server: &mut Server, entity: EcsEntity, _args: String, _action:
.insert(entity, comp::CanBuild);
server.clients.notify(
entity,
ServerMsg::Chat(String::from("Toggled on build mode!")),
ServerMsg::private(String::from("Toggled on build mode!")),
);
}
}
@ -422,7 +426,7 @@ fn handle_help(server: &mut Server, entity: EcsEntity, _args: String, _action: &
for cmd in CHAT_COMMANDS.iter() {
server
.clients
.notify(entity, ServerMsg::Chat(String::from(cmd.help_string)));
.notify(entity, ServerMsg::private(String::from(cmd.help_string)));
}
}
@ -460,7 +464,7 @@ fn handle_killnpcs(server: &mut Server, entity: EcsEntity, _args: String, _actio
} else {
"No NPCs on server.".to_string()
};
server.clients.notify(entity, ServerMsg::Chat(text));
server.clients.notify(entity, ServerMsg::private(text));
}
fn handle_object(server: &mut Server, entity: EcsEntity, args: String, _action: &ChatCommand) {
@ -512,17 +516,17 @@ fn handle_object(server: &mut Server, entity: EcsEntity, args: String, _action:
_ => {
return server
.clients
.notify(entity, ServerMsg::Chat(String::from("Object not found!")));
.notify(entity, ServerMsg::chat(String::from("Object not found!")));
}
};
server.create_object(pos, obj_type).build();
server
.clients
.notify(entity, ServerMsg::Chat(format!("Spawned object.")));
.notify(entity, ServerMsg::chat(format!("Spawned object.")));
} else {
server
.clients
.notify(entity, ServerMsg::Chat(format!("You have no position!")));
.notify(entity, ServerMsg::chat(format!("You have no position!")));
}
}
@ -558,11 +562,11 @@ fn handle_light(server: &mut Server, entity: EcsEntity, args: String, action: &C
.build();
server
.clients
.notify(entity, ServerMsg::Chat(format!("Spawned object.")));
.notify(entity, ServerMsg::chat(format!("Spawned object.")));
} else {
server
.clients
.notify(entity, ServerMsg::Chat(format!("You have no position!")));
.notify(entity, ServerMsg::chat(format!("You have no position!")));
}
}
fn handle_lantern(server: &mut Server, entity: EcsEntity, _args: String, _action: &ChatCommand) {
@ -579,7 +583,7 @@ fn handle_lantern(server: &mut Server, entity: EcsEntity, _args: String, _action
.remove(entity);
server.clients.notify(
entity,
ServerMsg::Chat(String::from("You put out the lantern.")),
ServerMsg::chat(String::from("You put out the lantern.")),
);
} else {
let _ = server
@ -597,7 +601,7 @@ fn handle_lantern(server: &mut Server, entity: EcsEntity, _args: String, _action
server.clients.notify(
entity,
ServerMsg::Chat(String::from("You lighted your lantern.")),
ServerMsg::chat(String::from("You lighted your lantern.")),
);
}
}
@ -623,24 +627,24 @@ fn handle_tell(server: &mut Server, entity: EcsEntity, args: String, action: &Ch
Some(name) => {
server.clients.notify(
player,
ServerMsg::Chat(format!("{} tells you:{}", name, msg)),
ServerMsg::tell(format!("{} tells you:{}", name, msg)),
);
server.clients.notify(
entity,
ServerMsg::Chat(format!("You tell {}:{}", alias, msg)),
ServerMsg::tell(format!("You tell {}:{}", alias, msg)),
);
}
None => {
server.clients.notify(
entity,
ServerMsg::Chat(String::from("You do not exist!")),
ServerMsg::private(String::from("You do not exist!")),
);
}
}
} else {
server.clients.notify(
entity,
ServerMsg::Chat(format!(
ServerMsg::private(format!(
"You really should say something to {}!",
alias
)),
@ -649,19 +653,19 @@ fn handle_tell(server: &mut Server, entity: EcsEntity, args: String, action: &Ch
} else {
server
.clients
.notify(entity, ServerMsg::Chat(format!("Don't be crazy!")));
.notify(entity, ServerMsg::private(format!("Don't be crazy!")));
}
}
None => {
server.clients.notify(
entity,
ServerMsg::Chat(format!("Player '{}' not found!", alias)),
ServerMsg::private(format!("Player '{}' not found!", alias)),
);
}
}
}
None => server
.clients
.notify(entity, ServerMsg::Chat(String::from(action.help_string))),
.notify(entity, ServerMsg::private(String::from(action.help_string))),
}
}

View File

@ -507,7 +507,10 @@ impl Server {
if let Some(player) =
state.ecs().read_storage::<comp::Player>().get(entity)
{
new_chat_msgs.push((None, format!("{} joined", &player.alias)));
new_chat_msgs.push((
None,
ServerMsg::broadcast(format!("{} joined", &player.alias)),
));
}
}
ClientState::Character => {
@ -526,14 +529,15 @@ impl Server {
}
ClientState::Pending => {}
},
ClientMsg::Chat(msg) => match client.client_state {
ClientMsg::ChatMsg { chat_type, message } => match client.client_state {
ClientState::Connected => {
client.error_state(RequestStateError::Impossible)
}
ClientState::Registered
| ClientState::Spectator
| ClientState::Dead
| ClientState::Character => new_chat_msgs.push((Some(entity), msg)),
| ClientState::Character => new_chat_msgs
.push((Some(entity), ServerMsg::ChatMsg { chat_type, message })),
ClientState::Pending => {}
},
ClientMsg::PlayerPhysics { pos, vel, ori } => match client.client_state {
@ -604,7 +608,10 @@ impl Server {
if disconnect {
if let Some(player) = state.ecs().read_storage::<comp::Player>().get(entity) {
new_chat_msgs.push((None, format!("{} disconnected", &player.alias)));
new_chat_msgs.push((
None,
ServerMsg::broadcast(format!("{} disconnected", &player.alias)),
));
}
disconnected_clients.push(entity);
client.postbox.send_message(ServerMsg::Disconnect);
@ -616,23 +623,31 @@ impl Server {
// Handle new chat messages.
for (entity, msg) in new_chat_msgs {
if let Some(entity) = entity {
// Handle chat commands.
if msg.starts_with("/") && msg.len() > 1 {
let argv = String::from(&msg[1..]);
self.process_chat_cmd(entity, argv);
} else {
self.clients.notify_registered(ServerMsg::Chat(
match self.state.ecs().read_storage::<comp::Player>().get(entity) {
Some(player) => format!("[{}] {}", &player.alias, msg),
None => format!("[<anon>] {}", msg),
},
));
match msg {
ServerMsg::ChatMsg { chat_type, message } => {
if let Some(entity) = entity {
// Handle chat commands.
if message.starts_with("/") && message.len() > 1 {
let argv = String::from(&message[1..]);
self.process_chat_cmd(entity, argv);
} else {
let message =
match self.state.ecs().read_storage::<comp::Player>().get(entity) {
Some(player) => format!("[{}] {}", &player.alias, message),
None => format!("[<anon>] {}", message),
};
self.clients
.notify_registered(ServerMsg::ChatMsg { chat_type, message });
}
} else {
self.clients
.notify_registered(ServerMsg::ChatMsg { chat_type, message });
}
}
_ => {
panic!("Invalid message type.");
}
} else {
self.clients.notify_registered(ServerMsg::Chat(msg.clone()));
}
frontend_events.push(Event::Chat { entity, msg });
}
// Handle client disconnects.
@ -719,7 +734,7 @@ impl Server {
}
.unwrap_or(format!("{} died", &player.alias));
clients.notify_registered(ServerMsg::Chat(msg));
clients.notify_registered(ServerMsg::chat(msg));
}
entity
@ -849,7 +864,7 @@ impl Server {
None => {
self.clients.notify(
entity,
ServerMsg::Chat(format!(
ServerMsg::chat(format!(
"Unrecognised command: '/{}'\ntype '/help' for a list of available commands",
kwd
)),

View File

@ -1,4 +1,8 @@
use super::{img_ids::Imgs, Fonts, TEXT_COLOR};
use super::{
img_ids::Imgs, Fonts, BROADCAST_COLOR, GAME_UPDATE_COLOR, PRIVATE_COLOR, TELL_COLOR, TEXT_COLOR,
};
use client::Event as ClientEvent;
use common::ChatType;
use conrod_core::{
input::Key,
position::Dimension,
@ -22,7 +26,7 @@ const MAX_MESSAGES: usize = 100;
#[derive(WidgetCommon)]
pub struct Chat<'a> {
new_messages: &'a mut VecDeque<String>,
new_messages: &'a mut VecDeque<ClientEvent>,
force_input: Option<String>,
force_cursor: Option<Index>,
@ -34,7 +38,11 @@ pub struct Chat<'a> {
}
impl<'a> Chat<'a> {
pub fn new(new_messages: &'a mut VecDeque<String>, imgs: &'a Imgs, fonts: &'a Fonts) -> Self {
pub fn new(
new_messages: &'a mut VecDeque<ClientEvent>,
imgs: &'a Imgs,
fonts: &'a Fonts,
) -> Self {
Self {
new_messages,
force_input: None,
@ -71,7 +79,7 @@ impl<'a> Chat<'a> {
}
pub struct State {
messages: VecDeque<String>,
messages: VecDeque<ClientEvent>,
input: String,
ids: Ids,
@ -179,27 +187,47 @@ impl<'a> Widget for Chat<'a> {
while let Some(item) = items.next(ui) {
// This would be easier if conrod used the v-metrics from rusttype.
let widget = if item.i < state.messages.len() {
let text = Text::new(&state.messages[item.i])
.font_size(15)
.font_id(self.fonts.opensans)
.w(470.0)
.color(TEXT_COLOR)
.line_spacing(2.0);
// Add space between messages.
let y = match text.get_y_dimension(ui) {
Dimension::Absolute(y) => y + 2.0,
_ => 0.0,
};
text.h(y)
let msg = &state.messages[item.i];
match msg {
ClientEvent::Chat { chat_type, message } => {
let color = match chat_type {
ChatType::Tell => TELL_COLOR,
ChatType::Chat => TEXT_COLOR,
ChatType::Private => PRIVATE_COLOR,
ChatType::Broadcast => BROADCAST_COLOR,
ChatType::GameUpdate => GAME_UPDATE_COLOR,
};
let text = Text::new(&message)
.font_size(15)
.font_id(self.fonts.opensans)
.w(470.0)
.color(color)
.line_spacing(2.0);
// Add space between messages.
let y = match text.get_y_dimension(ui) {
Dimension::Absolute(y) => y + 2.0,
_ => 0.0,
};
Some(text.h(y))
}
_ => None,
}
} else {
// Spacer at bottom of the last message so that it is not cut off.
// Needs to be larger than the space above.
Text::new("")
.font_size(6)
.font_id(self.fonts.opensans)
.w(470.0)
Some(
Text::new("")
.font_size(6)
.font_id(self.fonts.opensans)
.w(470.0),
)
};
item.set(widget, ui);
match widget {
Some(widget) => {
item.set(widget, ui);
}
None => {}
}
}
// Chat Arrow

View File

@ -31,7 +31,7 @@ use crate::{
window::{Event as WinEvent, GameInput, Window},
GlobalState,
};
use client::Client;
use client::{Client, Event as ClientEvent};
use common::{comp, terrain::TerrainChunkSize, vol::VolSize};
use conrod_core::{
text::cursor::Index,
@ -50,6 +50,10 @@ const TEXT_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0);
const TEXT_COLOR_2: Color = Color::Rgba(0.0, 0.0, 0.0, 1.0);
const HP_COLOR: Color = Color::Rgba(0.33, 0.63, 0.0, 1.0);
const MANA_COLOR: Color = Color::Rgba(0.42, 0.41, 0.66, 1.0);
const TELL_COLOR: Color = Color::Rgba(1.0, 1.0, 0.0, 1.0);
const PRIVATE_COLOR: Color = Color::Rgba(1.0, 1.0, 0.0, 1.0);
const BROADCAST_COLOR: Color = Color::Rgba(0.0, 1.0, 0.0, 1.0);
const GAME_UPDATE_COLOR: Color = Color::Rgba(1.0, 1.0, 0.0, 1.0);
widget_ids! {
struct Ids {
@ -269,7 +273,7 @@ pub struct Hud {
ids: Ids,
imgs: Imgs,
fonts: Fonts,
new_messages: VecDeque<String>,
new_messages: VecDeque<ClientEvent>,
inventory_space: usize,
show: Show,
to_focus: Option<Option<widget::Id>>,
@ -743,7 +747,7 @@ impl Hud {
events
}
pub fn new_message(&mut self, msg: String) {
pub fn new_message(&mut self, msg: ClientEvent) {
self.new_messages.push_back(msg);
}

View File

@ -44,8 +44,11 @@ impl SessionState {
fn tick(&mut self, dt: Duration) -> Result<(), Error> {
for event in self.client.borrow_mut().tick(self.controller.clone(), dt)? {
match event {
client::Event::Chat(msg) => {
self.hud.new_message(msg);
client::Event::Chat {
chat_type: _,
message: _,
} => {
self.hud.new_message(event);
}
client::Event::Disconnect => {} // TODO
}