rust/hedgewars-server/src/handlers/inlobby.rs
author unC0Rr
Wed, 28 Aug 2024 13:41:51 +0200
changeset 16049 9be943326d9c
parent 16031 e915ed28726e
permissions -rw-r--r--
Store all snowflakes in a separate array, achieving performance increase of about 10% for the whole engine on winter maps

use super::{common::rnd_reply, strings::*};
use crate::handlers::{actions::ToPendingMessage, checker};
use crate::{
    core::{
        client::HwClient,
        server::{AccessError, CreateRoomError, HwServer, JoinRoomError},
        types::ClientId,
    },
    utils::is_name_illegal,
};
use hedgewars_network_protocol::{
    messages::{
        add_flags, remove_flags, server_chat, HwProtocolMessage, HwServerMessage::*,
        ProtocolFlags as Flags,
    },
    types::ServerVar,
};
use log::*;
use std::{collections::HashSet, convert::identity};

pub fn handle(
    server: &mut HwServer,
    client_id: ClientId,
    response: &mut super::Response,
    message: HwProtocolMessage,
) {
    use hedgewars_network_protocol::messages::HwProtocolMessage::*;

    //todo!("add kick/ban handlers");
    //todo!("add command for forwarding lobby chat into rooms
    //todo!("report player account age")
    //todo!("port listing rooms for incompatible protocols"))

    match message {
        CreateRoom(name, password) => match server.create_room(client_id, name, password) {
            Err(CreateRoomError::InvalidName) => response.warn(ILLEGAL_ROOM_NAME),
            Err(CreateRoomError::AlreadyExists) => response.warn(ROOM_EXISTS),
            Ok((client, room)) => {
                response.add(
                    RoomAdd(room.info(Some(&client)))
                        .send_all()
                        .with_protocol(room.protocol_number),
                );
                response.add(RoomJoined(vec![client.nick.clone()]).send_self());
                response.add(
                    ClientFlags(
                        add_flags(&[Flags::RoomMaster, Flags::Ready, Flags::InRoom]),
                        vec![client.nick.clone()],
                    )
                    .send_all(),
                );
            }
        },
        Chat(msg) => {
            //todo!("add client quiet flag");
            response.add(
                ChatMsg {
                    nick: server.client(client_id).nick.clone(),
                    msg,
                }
                .send_all()
                .in_lobby()
                .but_self(),
            );
        }
        JoinRoom(name, password) => {
            match server.join_room_by_name(client_id, &name, password.as_deref()) {
                Err(error) => super::common::get_room_join_error(error, response),
                Ok((client, master, room, room_clients)) => {
                    super::common::get_room_join_data(client, master, room, room_clients, response)
                }
            }
        }
        Follow(nick) => {
            if let Some(client) = server.find_client(&nick) {
                if let Some(room_id) = client.room_id {
                    match server.join_room(client_id, room_id, None) {
                        Err(error) => super::common::get_room_join_error(error, response),
                        Ok((client, master, room, room_clients)) => {
                            super::common::get_room_join_data(
                                client,
                                master,
                                room,
                                room_clients,
                                response,
                            )
                        }
                    }
                } else {
                    response.warn(NO_ROOM);
                }
            } else {
                response.warn(NO_USER);
            }
        }
        SetServerVar(var) => match server.set_var(client_id, var) {
            Err(AccessError()) => response.warn(ACCESS_DENIED),
            Ok(()) => response.add(server_chat(VARIABLE_UPDATED.to_string()).send_self()),
        },
        GetServerVar => match server.get_vars(client_id) {
            Err(AccessError()) => response.warn(ACCESS_DENIED),
            Ok(vars) => {
                response.add(
                    ServerVars(vars.iter().flat_map(|v| v.to_protocol()).collect()).send_self(),
                );
            }
        },
        Rnd(v) => {
            response.add(rnd_reply(&v).send_self());
        }
        Stats => match server.get_used_protocols(client_id) {
            Err(AccessError()) => response.warn(ACCESS_DENIED),
            Ok(protocols) => {
                let mut html = Vec::with_capacity(protocols.len() + 2);

                html.push("<table>".to_string());
                for protocol in protocols {
                    html.push(format!(
                        "<tr><td>{}</td><td>{}</td><td>{}</td></tr>",
                        super::utils::protocol_version_string(protocol),
                        server.protocol_client_ids(protocol).count(),
                        server.protocol_room_ids(protocol).count()
                    ));
                }
                html.push("</table>".to_string());

                response.add(Warning(html.join("")).send_self());
            }
        },
        List => warn!("Deprecated LIST message received"),
        _ => warn!("Incorrect command in lobby state"),
    }
}