Fix group chat leak

This commit is contained in:
Maxicarlos08 2023-09-03 20:39:29 +02:00
parent 19742bb930
commit ec92b2c33b
No known key found for this signature in database
2 changed files with 38 additions and 15 deletions

View File

@ -346,10 +346,10 @@ impl<G> GenericChatMsg<G> {
}
}
pub fn get_group(&self) -> Option<&G> {
match &self.chat_type {
ChatType::GroupMeta(g) => Some(g),
ChatType::Group(_, g) => Some(g),
pub fn get_group_mut_sender(&mut self) -> Option<(&mut G, Option<&Uid>)> {
match &mut self.chat_type {
ChatType::GroupMeta(g) => Some((g, None)),
ChatType::Group(sender, g) => Some((g, Some(sender))),
_ => None,
}
}

View File

@ -908,22 +908,46 @@ impl StateExt for State {
/// Send the chat message to the proper players. Say and region are limited
/// by location. Faction and group are limited by component.
fn send_chat(&self, msg: comp::UnresolvedChatMsg) {
fn send_chat(&self, mut msg: comp::UnresolvedChatMsg) {
let ecs = self.ecs();
let is_within =
|target, a: &comp::Pos, b: &comp::Pos| a.0.distance_squared(b.0) < target * target;
let id_maps = ecs.read_resource::<IdMaps>();
let entity_from_uid = |uid| id_maps.uid_entity(uid);
let group_manager = ecs.read_resource::<comp::group::GroupManager>();
let group_info = msg.get_group().and_then(|g| group_manager.group_info(*g));
let group_info = msg.get_group_mut_sender().and_then(|(g, from)| {
// Check if the sender is in the group he is trying to send the message to. If
// it doesn't match, update the message's group accordingly.
// There currently is a bug that can cause group messages to appear in other
// groups. This commonly happens when a player has his [ChatMode] set
// to group and is kicked from his current group or joins another,
// any message sent afterwards appears in the previous group as long
// as his chatmode isn't updated.
// TODO: Find out why sometimes messages from players never previously in the
// group leak.
// FIXME: Another pontential fix could be updating the [ChatMode] as the player
// leaves and joins a new group. Possibly a better solution?
if let Some(from) = from {
let group = ecs
.read_storage::<comp::Group>()
.get(entity_from_uid(*from)?)
.copied()?;
if g != &group {
*g = group;
}
}
group_manager.group_info(*g)
});
let resolved_msg = msg
.clone()
.map_group(|_| group_info.map_or_else(|| "???".to_string(), |i| i.name.clone()));
let id_maps = ecs.read_resource::<IdMaps>();
let entity_from_uid = |uid| id_maps.uid_entity(uid);
if msg.chat_type.uid().map_or(true, |sender| {
entity_from_uid(sender).map_or(false, |e| {
self.validate_chat_msg(
@ -1082,16 +1106,15 @@ impl StateExt for State {
/region to change chat.",
);
if let Some((client, _)) =
(&ecs.read_storage::<Client>(), &ecs.read_storage::<Uid>())
.join()
.find(|(_, uid)| *uid == from)
let clients = ecs.read_storage::<Client>();
if let Some(client) =
entity_from_uid(*from).and_then(|entity| clients.get(entity))
{
client.send_fallible(ServerGeneral::ChatMsg(reply));
}
return;
} else {
send_to_group(g, ecs, &resolved_msg);
}
send_to_group(g, ecs, &resolved_msg);
},
comp::ChatType::GroupMeta(g) => {
send_to_group(g, ecs, &resolved_msg);