mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Implement /join_group and /join_faction commands
This commit is contained in:
parent
289ef5d6b2
commit
5cbecb29e6
@ -43,6 +43,8 @@ pub enum ChatCommand {
|
||||
Group,
|
||||
Health,
|
||||
Help,
|
||||
JoinFaction,
|
||||
JoinGroup,
|
||||
Jump,
|
||||
Kill,
|
||||
KillNpcs,
|
||||
@ -81,6 +83,8 @@ pub static CHAT_COMMANDS: &[ChatCommand] = &[
|
||||
ChatCommand::Group,
|
||||
ChatCommand::Health,
|
||||
ChatCommand::Help,
|
||||
ChatCommand::JoinFaction,
|
||||
ChatCommand::JoinGroup,
|
||||
ChatCommand::Jump,
|
||||
ChatCommand::Kill,
|
||||
ChatCommand::KillNpcs,
|
||||
@ -218,6 +222,16 @@ impl ChatCommand {
|
||||
"Display information about commands",
|
||||
NoAdmin,
|
||||
),
|
||||
ChatCommand::JoinFaction => ChatCommandData::new(
|
||||
vec![Any("faction", Optional)],
|
||||
"Join/leave the specified faction",
|
||||
NoAdmin,
|
||||
),
|
||||
ChatCommand::JoinGroup => ChatCommandData::new(
|
||||
vec![Any("group", Optional)],
|
||||
"Join/leave the specified group",
|
||||
NoAdmin,
|
||||
),
|
||||
ChatCommand::Jump => cmd(
|
||||
vec![
|
||||
Float("x", 0.0, Required),
|
||||
@ -336,6 +350,8 @@ impl ChatCommand {
|
||||
ChatCommand::Goto => "goto",
|
||||
ChatCommand::Group => "group",
|
||||
ChatCommand::Health => "health",
|
||||
ChatCommand::JoinFaction => "join_faction",
|
||||
ChatCommand::JoinGroup => "join_group",
|
||||
ChatCommand::Help => "help",
|
||||
ChatCommand::Jump => "jump",
|
||||
ChatCommand::Kill => "kill",
|
||||
|
@ -4,7 +4,7 @@ use specs_idvs::IDVStorage;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
/// A player's current chat mode.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ChatMode {
|
||||
/// Private message to another player (by uuid)
|
||||
Tell(Uid),
|
||||
@ -13,9 +13,9 @@ pub enum ChatMode {
|
||||
/// Talk to players in your region of the world
|
||||
Region,
|
||||
/// Talk to your current group of players
|
||||
Group,
|
||||
Group(String),
|
||||
/// Talk to your faction
|
||||
Faction,
|
||||
Faction(String),
|
||||
/// Talk to every player on the server
|
||||
World,
|
||||
}
|
||||
@ -31,18 +31,22 @@ impl ChatMode {
|
||||
ChatMode::Tell(to) => ChatType::Tell(from, *to),
|
||||
ChatMode::Say => ChatType::Say(from),
|
||||
ChatMode::Region => ChatType::Region(from),
|
||||
ChatMode::Group => ChatType::Group(from),
|
||||
ChatMode::Faction => ChatType::Faction(from),
|
||||
ChatMode::Group(name) => ChatType::Group(from, name.to_string()),
|
||||
ChatMode::Faction(name) => ChatType::Faction(from, name.to_string()),
|
||||
ChatMode::World => ChatType::World(from),
|
||||
};
|
||||
ChatMsg { chat_type, message }
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ChatMode {
|
||||
fn default() -> Self { Self::World }
|
||||
}
|
||||
|
||||
/// List of chat types. Note that this is a superset of `ChatMode`; this is
|
||||
/// because `ChatType::Kill`, `ChatType::Broadcast`, and `ChatType::Private`
|
||||
/// cannot be sent by players.
|
||||
#[derive(Copy, Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum ChatType {
|
||||
/// Tell all players something (such as players connecting or alias changes)
|
||||
Broadcast,
|
||||
@ -55,9 +59,9 @@ pub enum ChatType {
|
||||
/// Chat with nearby players
|
||||
Say(Uid),
|
||||
/// Group chat
|
||||
Group(Uid),
|
||||
Group(Uid, String),
|
||||
/// Factional chat
|
||||
Faction(Uid),
|
||||
Faction(Uid, String),
|
||||
/// Regional chat
|
||||
Region(Uid),
|
||||
/// World chat
|
||||
@ -81,23 +85,23 @@ impl ChatMsg {
|
||||
}
|
||||
|
||||
pub fn to_bubble(&self) -> Option<(SpeechBubble, Uid)> {
|
||||
let tuple = match self.chat_type {
|
||||
let tuple = match &self.chat_type {
|
||||
ChatType::Broadcast => None,
|
||||
ChatType::Private => None,
|
||||
ChatType::Kill => None,
|
||||
ChatType::Tell(u, _) => Some((SpeechBubbleIcon::Tell, u, None)),
|
||||
ChatType::Say(u) => Some((SpeechBubbleIcon::Say, u, None)),
|
||||
ChatType::Group(u) => Some((SpeechBubbleIcon::Group, u, None)),
|
||||
ChatType::Faction(u) => Some((SpeechBubbleIcon::Faction, u, None)),
|
||||
ChatType::Group(u, _s) => Some((SpeechBubbleIcon::Group, u, None)),
|
||||
ChatType::Faction(u, _s) => Some((SpeechBubbleIcon::Faction, u, None)),
|
||||
ChatType::Region(u) => Some((SpeechBubbleIcon::Region, u, None)),
|
||||
ChatType::World(u) => Some((SpeechBubbleIcon::World, u, None)),
|
||||
ChatType::Npc(u, r) => Some((SpeechBubbleIcon::None, u, Some(r))),
|
||||
};
|
||||
tuple.map(|(icon, from, npc_rand)| {
|
||||
if let Some(r) = npc_rand {
|
||||
(SpeechBubble::npc_new(self.message.clone(), r, icon), from)
|
||||
(SpeechBubble::npc_new(self.message.clone(), *r, icon), *from)
|
||||
} else {
|
||||
(SpeechBubble::player_new(self.message.clone(), icon), from)
|
||||
(SpeechBubble::player_new(self.message.clone(), icon), *from)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -107,19 +111,27 @@ impl ChatMsg {
|
||||
/// gameplay.
|
||||
///
|
||||
/// Groups are currently just an associated String (the group's name)
|
||||
pub struct Group(String);
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Group(pub String);
|
||||
impl Component for Group {
|
||||
type Storage = IDVStorage<Self>;
|
||||
}
|
||||
impl From<String> for Group {
|
||||
fn from(s: String) -> Self { Group(s) }
|
||||
}
|
||||
|
||||
/// Player factions are used to coordinate pvp vs hostile factions or segment
|
||||
/// chat from the world
|
||||
///
|
||||
/// Factions are currently just an associated String (the faction's name)
|
||||
pub struct Faction(String);
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Faction(pub String);
|
||||
impl Component for Faction {
|
||||
type Storage = IDVStorage<Self>;
|
||||
}
|
||||
impl From<String> for Faction {
|
||||
fn from(s: String) -> Self { Faction(s) }
|
||||
}
|
||||
|
||||
/// The contents of a speech bubble
|
||||
pub enum SpeechBubbleMessage {
|
||||
|
@ -155,6 +155,8 @@ impl State {
|
||||
ecs.register::<comp::Attacking>();
|
||||
ecs.register::<comp::ItemDrop>();
|
||||
ecs.register::<comp::ChatMode>();
|
||||
ecs.register::<comp::Group>();
|
||||
ecs.register::<comp::Faction>();
|
||||
|
||||
// Register synced resources used by the ECS.
|
||||
ecs.insert(TimeOfDay(0.0));
|
||||
|
@ -8,6 +8,7 @@ use common::{
|
||||
assets,
|
||||
cmd::{ChatCommand, CHAT_COMMANDS},
|
||||
comp,
|
||||
comp::Item,
|
||||
event::{EventBus, ServerEvent},
|
||||
msg::{Notification, PlayerListUpdate, ServerMsg},
|
||||
npc::{self, get_npc_name},
|
||||
@ -75,6 +76,8 @@ fn get_handler(cmd: &ChatCommand) -> CommandHandler {
|
||||
ChatCommand::Group => handle_group,
|
||||
ChatCommand::Health => handle_health,
|
||||
ChatCommand::Help => handle_help,
|
||||
ChatCommand::JoinFaction => handle_join_faction,
|
||||
ChatCommand::JoinGroup => handle_join_group,
|
||||
ChatCommand::Jump => handle_jump,
|
||||
ChatCommand::Kill => handle_kill,
|
||||
ChatCommand::KillNpcs => handle_kill_npcs,
|
||||
@ -1020,13 +1023,20 @@ fn handle_tell(
|
||||
.get(player)
|
||||
.expect("Player must have uid");
|
||||
let mode = comp::ChatMode::Tell(player_uid);
|
||||
let _ = server.state.ecs().write_storage().insert(client, mode);
|
||||
let _ = server
|
||||
.state
|
||||
.ecs()
|
||||
.write_storage()
|
||||
.insert(client, mode.clone());
|
||||
let msg = if msg.is_empty() {
|
||||
format!("{} wants to talk to you.", alias)
|
||||
} else {
|
||||
msg.to_string()
|
||||
};
|
||||
server.notify_client(player, ServerMsg::chat(mode, client_uid, msg.clone()));
|
||||
server.notify_client(
|
||||
player,
|
||||
ServerMsg::chat(mode.clone(), client_uid, msg.clone()),
|
||||
);
|
||||
server.notify_client(client, ServerMsg::chat(mode, client_uid, msg));
|
||||
} else {
|
||||
server.notify_client(
|
||||
@ -1057,14 +1067,24 @@ fn handle_faction(
|
||||
);
|
||||
return;
|
||||
}
|
||||
let mode = comp::ChatMode::Faction;
|
||||
let _ = server.state.ecs().write_storage().insert(client, mode);
|
||||
if !msg.is_empty() {
|
||||
if let Some(uid) = server.state.ecs().read_storage().get(client) {
|
||||
server
|
||||
.state
|
||||
.notify_registered_clients(ServerMsg::chat(mode, *uid, msg.to_string()));
|
||||
let ecs = server.state.ecs();
|
||||
if let Some(comp::Faction(faction)) = ecs.read_storage().get(client) {
|
||||
let mode = comp::ChatMode::Faction(faction.to_string());
|
||||
let _ = ecs.write_storage().insert(client, mode.clone());
|
||||
if !msg.is_empty() {
|
||||
if let Some(uid) = ecs.read_storage().get(client) {
|
||||
server.state.notify_registered_clients(ServerMsg::chat(
|
||||
mode,
|
||||
*uid,
|
||||
msg.to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
server.notify_client(
|
||||
client,
|
||||
ServerMsg::private(String::from("Please join a faction with /join_faction")),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1083,14 +1103,24 @@ fn handle_group(
|
||||
);
|
||||
return;
|
||||
}
|
||||
let mode = comp::ChatMode::Group;
|
||||
let _ = server.state.ecs().write_storage().insert(client, mode);
|
||||
if !msg.is_empty() {
|
||||
if let Some(uid) = server.state.ecs().read_storage().get(client) {
|
||||
server
|
||||
.state
|
||||
.notify_registered_clients(ServerMsg::chat(mode, *uid, msg.to_string()));
|
||||
let ecs = server.state.ecs();
|
||||
if let Some(comp::Group(group)) = ecs.read_storage().get(client) {
|
||||
let mode = comp::ChatMode::Group(group.to_string());
|
||||
let _ = ecs.write_storage().insert(client, mode.clone());
|
||||
if !msg.is_empty() {
|
||||
if let Some(uid) = ecs.read_storage().get(client) {
|
||||
server.state.notify_registered_clients(ServerMsg::chat(
|
||||
mode,
|
||||
*uid,
|
||||
msg.to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
server.notify_client(
|
||||
client,
|
||||
ServerMsg::private(String::from("Please join a group with /join_group")),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1110,7 +1140,11 @@ fn handle_region(
|
||||
return;
|
||||
}
|
||||
let mode = comp::ChatMode::Region;
|
||||
let _ = server.state.ecs().write_storage().insert(client, mode);
|
||||
let _ = server
|
||||
.state
|
||||
.ecs()
|
||||
.write_storage()
|
||||
.insert(client, mode.clone());
|
||||
if !msg.is_empty() {
|
||||
if let Some(uid) = server.state.ecs().read_storage().get(client) {
|
||||
server
|
||||
@ -1136,7 +1170,11 @@ fn handle_say(
|
||||
return;
|
||||
}
|
||||
let mode = comp::ChatMode::Say;
|
||||
let _ = server.state.ecs().write_storage().insert(client, mode);
|
||||
let _ = server
|
||||
.state
|
||||
.ecs()
|
||||
.write_storage()
|
||||
.insert(client, mode.clone());
|
||||
if !msg.is_empty() {
|
||||
if let Some(uid) = server.state.ecs().read_storage().get(client) {
|
||||
server
|
||||
@ -1162,7 +1200,11 @@ fn handle_world(
|
||||
return;
|
||||
}
|
||||
let mode = comp::ChatMode::World;
|
||||
let _ = server.state.ecs().write_storage().insert(client, mode);
|
||||
let _ = server
|
||||
.state
|
||||
.ecs()
|
||||
.write_storage()
|
||||
.insert(client, mode.clone());
|
||||
if !msg.is_empty() {
|
||||
if let Some(uid) = server.state.ecs().read_storage().get(client) {
|
||||
server
|
||||
@ -1172,6 +1214,88 @@ fn handle_world(
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_join_faction(
|
||||
server: &mut Server,
|
||||
client: EcsEntity,
|
||||
target: EcsEntity,
|
||||
args: String,
|
||||
action: &ChatCommand,
|
||||
) {
|
||||
if client != target {
|
||||
// This happens when [ab]using /sudo
|
||||
server.notify_client(
|
||||
client,
|
||||
ServerMsg::private(String::from("It's rude to impersonate people")),
|
||||
);
|
||||
return;
|
||||
}
|
||||
if let Ok(faction) = scan_fmt!(&args, &action.arg_fmt(), String) {
|
||||
let mode = comp::ChatMode::Faction(faction.clone());
|
||||
let _ = server.state.ecs().write_storage().insert(client, mode);
|
||||
let _ = server
|
||||
.state
|
||||
.ecs()
|
||||
.write_storage()
|
||||
.insert(client, comp::Faction(faction.clone()));
|
||||
// TODO notify faction
|
||||
server.notify_client(
|
||||
client,
|
||||
ServerMsg::private(format!("Joined faction {{{}}}", faction)),
|
||||
);
|
||||
} else {
|
||||
let mode = comp::ChatMode::default();
|
||||
let _ = server.state.ecs().write_storage().insert(client, mode);
|
||||
if let Some(comp::Faction(faction)) = server.state.ecs().write_storage().remove(client) {
|
||||
// TODO notify faction
|
||||
server.notify_client(
|
||||
client,
|
||||
ServerMsg::private(format!("Left faction {{{}}}", faction)),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_join_group(
|
||||
server: &mut Server,
|
||||
client: EcsEntity,
|
||||
target: EcsEntity,
|
||||
args: String,
|
||||
action: &ChatCommand,
|
||||
) {
|
||||
if client != target {
|
||||
// This happens when [ab]using /sudo
|
||||
server.notify_client(
|
||||
client,
|
||||
ServerMsg::private(String::from("It's rude to impersonate people")),
|
||||
);
|
||||
return;
|
||||
}
|
||||
if let Ok(group) = scan_fmt!(&args, &action.arg_fmt(), String) {
|
||||
let mode = comp::ChatMode::Group(group.clone());
|
||||
let _ = server.state.ecs().write_storage().insert(client, mode);
|
||||
let _ = server
|
||||
.state
|
||||
.ecs()
|
||||
.write_storage()
|
||||
.insert(client, comp::Group(group.clone()));
|
||||
// TODO notify group
|
||||
server.notify_client(
|
||||
client,
|
||||
ServerMsg::private(format!("Joined group {{{}}}", group)),
|
||||
);
|
||||
} else {
|
||||
let mode = comp::ChatMode::default();
|
||||
let _ = server.state.ecs().write_storage().insert(client, mode);
|
||||
if let Some(comp::Group(group)) = server.state.ecs().write_storage().remove(client) {
|
||||
// TODO notify group
|
||||
server.notify_client(
|
||||
client,
|
||||
ServerMsg::private(format!("Left group {{{}}}", group)),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "worldgen"))]
|
||||
fn handle_debug_column(
|
||||
server: &mut Server,
|
||||
@ -1375,7 +1499,6 @@ fn handle_set_level(
|
||||
}
|
||||
}
|
||||
|
||||
use common::comp::Item;
|
||||
fn handle_debug(
|
||||
server: &mut Server,
|
||||
client: EcsEntity,
|
||||
|
@ -328,8 +328,11 @@ impl<'a> System<'a> for Sys {
|
||||
| ClientState::Character => match validate_chat_msg(&message) {
|
||||
Ok(()) => {
|
||||
if let Some(from) = uids.get(entity) {
|
||||
let mode = chat_modes.get(entity).unwrap_or(&ChatMode::World);
|
||||
let msg = ServerMsg::chat(*mode, *from, message);
|
||||
let mode = chat_modes
|
||||
.get(entity)
|
||||
.map(Clone::clone)
|
||||
.unwrap_or(ChatMode::default());
|
||||
let msg = ServerMsg::chat(mode, *from, message);
|
||||
new_chat_msgs.push((Some(entity), msg));
|
||||
} else {
|
||||
tracing::error!("Could not send message. Missing player uid");
|
||||
|
@ -321,7 +321,13 @@ impl<'a> Widget for Chat<'a> {
|
||||
}
|
||||
})
|
||||
};
|
||||
let message_format = |uid, message| format!("[{}]: {}", alias_of_uid(uid), message);
|
||||
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)
|
||||
}
|
||||
};
|
||||
// Message box
|
||||
Rectangle::fill([470.0, 174.0])
|
||||
.rgba(0.0, 0.0, 0.0, transp)
|
||||
@ -362,11 +368,13 @@ impl<'a> Widget for Chat<'a> {
|
||||
(TELL_COLOR, format!("From [{}]: {}", from_alias, message))
|
||||
}
|
||||
},
|
||||
ChatType::Say(uid) => (SAY_COLOR, message_format(uid, message)),
|
||||
ChatType::Group(uid) => (GROUP_COLOR, message_format(uid, message)),
|
||||
ChatType::Faction(uid) => (FACTION_COLOR, message_format(uid, message)),
|
||||
ChatType::Region(uid) => (REGION_COLOR, message_format(uid, message)),
|
||||
ChatType::World(uid) => (WORLD_COLOR, message_format(uid, message)),
|
||||
ChatType::Say(uid) => (SAY_COLOR, message_format(uid, message, None)),
|
||||
ChatType::Group(uid, s) => (GROUP_COLOR, message_format(uid, message, Some(s))),
|
||||
ChatType::Faction(uid, s) => {
|
||||
(FACTION_COLOR, message_format(uid, message, Some(s)))
|
||||
},
|
||||
ChatType::Region(uid) => (REGION_COLOR, message_format(uid, message, None)),
|
||||
ChatType::World(uid) => (WORLD_COLOR, message_format(uid, message, None)),
|
||||
ChatType::Npc(_uid, _r) => continue, // Should be filtered by hud/mod.rs
|
||||
};
|
||||
let text = Text::new(&msg)
|
||||
|
Loading…
Reference in New Issue
Block a user