<commit_before>use std::time::Duration;
use std::{collections::HashMap, net::SocketAddr};

use anyhow::Result;
use crossbeam_channel::Sender;
use laminar::Packet;

use zombenum_shared::components::{Component, GameEntityId, PlayerId};
use zombenum_shared::messages::server::*;

/// This struct is used to accumulate all information that should be sent to users.
/// Each field is a collection of updates sorted by user id.
pub struct ScheduledUpdates {
    /// New entities.
    /// These have to be transmitted reliably.
    pub added_entities: HashMap<PlayerId, Vec<Vec<Component>>>,
    /// Critical components.
    /// These have to be transmitted reliably.
    pub critical_components: HashMap<PlayerId, Vec<(GameEntityId, Component)>>,
    /// Uncritical components.
    /// These updates will be sent, but can go missing.
    /// This is usually stuff that's rapidly updated all the time.
    pub uncritical_components: HashMap<PlayerId, Vec<(GameEntityId, Component)>>,
}

impl ScheduledUpdates {
    pub fn new() -> ScheduledUpdates {
        ScheduledUpdates {
            added_entities: HashMap::new(),
            critical_components: HashMap::new(),
            uncritical_components: HashMap::new(),
        }
    }

    pub fn add_critical_component(
        &mut self,
        player_id: PlayerId,
        entity_id: GameEntityId,
        component: Component,
    ) {
        let components = self
            .critical_components
            .entry(player_id)
            .or_insert(Vec::new());
        components.push((entity_id, component));
    }
}

/// Send all updates to their respective clients.
pub fn send_server_updates(
    sender: &Sender<Packet>,
    connected_users: &HashMap<SocketAddr, PlayerId>,
    session_time: Duration,
    scheduled_updates: &ScheduledUpdates,
) -> Result<()> {
    let mut reliable_messages: HashMap<PlayerId, ServerMessage> = HashMap::new();

    // Handle all new entities
    for (player_id, entities) in scheduled_updates.added_entities.iter() {
        // These entities should be sent to all users
        if *player_id == PlayerId::all_users() {
            // Iterate over all connected uesrs and add these entities to their message
            for player_id in connected_users.values() {
                let entry = reliable_messages
                    .entry(player_id.clone())
                    .or_insert(ServerMessage::new(session_time));

                for entity in entities {
                    entry.new_entities.push(entity.clone())
                }
            }

            continue;
        }

        // Get the user
        let entry = reliable_messages
            .entry(player_id.clone())
            .or_insert(ServerMessage::new(session_time));

        for entity in entities {
            entry.new_entities.push(entity.clone())
        }
    }

    // Handle all critical components
    for (player_id, components) in scheduled_updates.critical_components.iter() {
        // These components should be sent to all users
        if *player_id == PlayerId::all_users() {
            // Iterate over all connected users and add these components to their message
            for player_id in connected_users.values() {
                let entry = reliable_messages
                    .entry(player_id.clone())
                    .or_insert(ServerMessage::new(session_time));

                for component in components {
                    entry.changed_components.push(component.clone())
                }
            }

            continue;
        }

        for component in components {
            let entry = reliable_messages
                .entry(player_id.clone())
                .or_insert(ServerMessage::new(session_time));

            entry.changed_components.push(component.clone())
        }
    }

    // Send all critical messages
    for (addr, player_id) in connected_users {
        if let Some(message) = reliable_messages.get(player_id) {
            sender.send(Packet::reliable_ordered(
                *addr,
                bincode::serialize(message)?,
                None,
            ))?;
        };
    }

    let mut unreliable_messages: HashMap<PlayerId, ServerMessage> = HashMap::new();

    // Handle all non-critical components
    for (player_id, components) in scheduled_updates.uncritical_components.iter() {
        // These components should be sent to all users
        if *player_id == PlayerId::all_users() {
            // Iterate over all connected users and add these components to their message
            for player_id in connected_users.values() {
                let entry = unreliable_messages
                    .entry(player_id.clone())
                    .or_insert(ServerMessage::new(session_time));

                for component in components {
                    entry.changed_components.push(component.clone())
                }
            }

            continue;
        }

        for component in components {
            let entry = unreliable_messages
                .entry(player_id.clone())
                .or_insert(ServerMessage::new(session_time));

            entry.changed_components.push(component.clone())
        }
    }

    // Send all uncritical messages
    for (addr, player_id) in connected_users {
        if let Some(message) = unreliable_messages.get(player_id) {
            sender.send(Packet::reliable_ordered(
                *addr,
                bincode::serialize(message)?,
                None,
            ))?;
        };
    }

    Ok(())
}<commit_msg>Fix copy-paste error and properly send uncritical stuff as unrealiable_sequenced<commit_after>use std::time::Duration;
use std::{collections::HashMap, net::SocketAddr};

use anyhow::Result;
use crossbeam_channel::Sender;
use laminar::Packet;

use zombenum_shared::components::{Component, GameEntityId, PlayerId};
use zombenum_shared::messages::server::*;

/// This struct is used to accumulate all information that should be sent to users.
/// Each field is a collection of updates sorted by user id.
pub struct ScheduledUpdates {
    /// New entities.
    /// These have to be transmitted reliably.
    pub added_entities: HashMap<PlayerId, Vec<Vec<Component>>>,
    /// Critical components.
    /// These have to be transmitted reliably.
    pub critical_components: HashMap<PlayerId, Vec<(GameEntityId, Component)>>,
    /// Uncritical components.
    /// These updates will be sent, but can go missing.
    /// This is usually stuff that's rapidly updated all the time.
    pub uncritical_components: HashMap<PlayerId, Vec<(GameEntityId, Component)>>,
}

impl ScheduledUpdates {
    pub fn new() -> ScheduledUpdates {
        ScheduledUpdates {
            added_entities: HashMap::new(),
            critical_components: HashMap::new(),
            uncritical_components: HashMap::new(),
        }
    }

    pub fn add_critical_component(
        &mut self,
        player_id: PlayerId,
        entity_id: GameEntityId,
        component: Component,
    ) {
        let components = self
            .critical_components
            .entry(player_id)
            .or_insert(Vec::new());
        components.push((entity_id, component));
    }
}

/// Send all updates to their respective clients.
pub fn send_server_updates(
    sender: &Sender<Packet>,
    connected_users: &HashMap<SocketAddr, PlayerId>,
    session_time: Duration,
    scheduled_updates: &ScheduledUpdates,
) -> Result<()> {
    let mut reliable_messages: HashMap<PlayerId, ServerMessage> = HashMap::new();

    // Handle all new entities
    for (player_id, entities) in scheduled_updates.added_entities.iter() {
        // These entities should be sent to all users
        if *player_id == PlayerId::all_users() {
            // Iterate over all connected uesrs and add these entities to their message
            for player_id in connected_users.values() {
                let entry = reliable_messages
                    .entry(player_id.clone())
                    .or_insert(ServerMessage::new(session_time));

                for entity in entities {
                    entry.new_entities.push(entity.clone())
                }
            }

            continue;
        }

        // Get the user
        let entry = reliable_messages
            .entry(player_id.clone())
            .or_insert(ServerMessage::new(session_time));

        for entity in entities {
            entry.new_entities.push(entity.clone())
        }
    }

    // Handle all critical components
    for (player_id, components) in scheduled_updates.critical_components.iter() {
        // These components should be sent to all users
        if *player_id == PlayerId::all_users() {
            // Iterate over all connected users and add these components to their message
            for player_id in connected_users.values() {
                let entry = reliable_messages
                    .entry(player_id.clone())
                    .or_insert(ServerMessage::new(session_time));

                for component in components {
                    entry.changed_components.push(component.clone())
                }
            }

            continue;
        }

        for component in components {
            let entry = reliable_messages
                .entry(player_id.clone())
                .or_insert(ServerMessage::new(session_time));

            entry.changed_components.push(component.clone())
        }
    }

    // Send all critical messages
    for (addr, player_id) in connected_users {
        if let Some(message) = reliable_messages.get(player_id) {
            sender.send(Packet::reliable_ordered(
                *addr,
                bincode::serialize(message)?,
                None,
            ))?;
        };
    }

    let mut unreliable_messages: HashMap<PlayerId, ServerMessage> = HashMap::new();

    // Handle all non-critical components
    for (player_id, components) in scheduled_updates.uncritical_components.iter() {
        // These components should be sent to all users
        if *player_id == PlayerId::all_users() {
            // Iterate over all connected users and add these components to their message
            for player_id in connected_users.values() {
                let entry = unreliable_messages
                    .entry(player_id.clone())
                    .or_insert(ServerMessage::new(session_time));

                for component in components {
                    entry.changed_components.push(component.clone())
                }
            }

            continue;
        }

        for component in components {
            let entry = unreliable_messages
                .entry(player_id.clone())
                .or_insert(ServerMessage::new(session_time));

            entry.changed_components.push(component.clone())
        }
    }

    // Send all uncritical messages
    for (addr, player_id) in connected_users {
        if let Some(message) = unreliable_messages.get(player_id) {
            sender.send(Packet::unreliable_sequenced(
                *addr,
                bincode::serialize(message)?,
                None,
            ))?;
        };
    }

    Ok(())
}
{'fraction_non_alphanumeric': 0.09516575819855241, 'fraction_numerical': 0.0, 'mean_word_length': 2.0705075445816186, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7190491', 'n_tokens_mistral': 2934, 'n_tokens_neox': 2787, 'n_words': 747}