pub(crate) fn process<T: IntoIterator<Item = Event>>(
  state: &mut crate::realm::RealmPuzzleState,
  links: &mut std::collections::HashMap<crate::PlayerKey, puzzleverse_core::asset::rules::RealmLink>,
  events: T,
) {
  let mut count = 100;
  let mut queue = std::collections::VecDeque::new();
  let mut players_in_transit = Vec::new();
  queue.extend(events);
  // We only do 100 rounds of processing and then we assume the puzzle is some kind of unstable oscillator and give up.
  while count > 0 {
    count -= 1;
    // We're really handling two kinds of events: one based on our input and then knock on effects from having moved players around, so first, drain all our input events
    if let Some(current) = queue.pop_front() {
      // Check each puzzle piece for an input event and gather the output events
      for propagation_rule in state
        .propagation_rules
        .iter()
        .filter(|propagation_rule| propagation_rule.sender == current.sender && propagation_rule.trigger == current.name)
      {
        if let Some(piece) = state.pieces.get_mut(propagation_rule.recipient) {
          if let Some(result) = propagation_rule.propagation_match.apply(&current.value, &state.settings).as_mut() {
            for value in piece.accept(&propagation_rule.causes, result) {
              match value {
                // Any output events that are due to puzzle state, get fed back into out input queue
                OutputEvent::Event(event_name, value) => {
                  queue.push_back(Event { sender: propagation_rule.recipient, name: event_name, value });
                }
                // The puzzle piece wants to move players; if we've already moved the players around, don't move them again
                OutputEvent::Send(link, players) => {
                  for player in players {
                    if !links.contains_key(&player) {
                      players_in_transit.push(player.clone());
                      links.insert(player, link.clone());
                    }
                  }
                }
              }
            }
          }
        }
      }
    } else if !players_in_transit.is_empty() {
      // Given we've processed all the input events, then make sure our players that are leaving exist nowhere on the map and all the pieces no that. If that generates more events, put them in the queue
      for player in players_in_transit.drain(..) {
        for (recipient, piece) in state.pieces.iter_mut().enumerate() {
          queue.extend(piece.walk(&player, PlayerNavigationEvent::Leave).drain(..).map(|(event_name, value)| Event {
            sender: recipient,
            name: event_name,
            value,
          }));
        }
      }
    } else {
      // This means we are done with input events and done with clearing players on the map
      break;
    }
  }
}
/// Update puzzle state based on some player-initiated input event
Update puzzle state based on some player-initiated input event
Update puzzle state based on some player - initiated input event
pub(crate) fn process<T: IntoIterator<Item = Event>>(
  state: &mut crate::realm::RealmPuzzleState,
  links: &mut std::collections::HashMap<crate::PlayerKey, puzzleverse_core::asset::rules::RealmLink>,
  events: T,
) {
  let mut count = 100;
  let mut queue = std::collections::VecDeque::new();
  let mut players_in_transit = Vec::new();
  queue.extend(events);
  // We only do 100 rounds of processing and then we assume the puzzle is some kind of unstable oscillator and give up.
  while count > 0 {
    count -= 1;
    // We're really handling two kinds of events: one based on our input and then knock on effects from having moved players around, so first, drain all our input events
    if let Some(current) = queue.pop_front() {
      // Check each puzzle piece for an input event and gather the output events
      for propagation_rule in state
        .propagation_rules
        .iter()
        .filter(|propagation_rule| propagation_rule.sender == current.sender && propagation_rule.trigger == current.name)
      {
        if let Some(piece) = state.pieces.get_mut(propagation_rule.recipient) {
          if let Some(result) = propagation_rule.propagation_match.apply(&current.value, &state.settings).as_mut() {
            for value in piece.accept(&propagation_rule.causes, result) {
              match value {
                // Any output events that are due to puzzle state, get fed back into out input queue
                OutputEvent::Event(event_name, value) => {
                  queue.push_back(Event { sender: propagation_rule.recipient, name: event_name, value });
                }
                // The puzzle piece wants to move players; if we've already moved the players around, don't move them again
                OutputEvent::Send(link, players) => {
                  for player in players {
                    if !links.contains_key(&player) {
                      players_in_transit.push(player.clone());
                      links.insert(player, link.clone());
                    }
                  }
                }
              }
            }
          }
        }
      }
    } else if !players_in_transit.is_empty() {
      // Given we've processed all the input events, then make sure our players that are leaving exist nowhere on the map and all the pieces no that. If that generates more events, put them in the queue
      for player in players_in_transit.drain(..) {
        for (recipient, piece) in state.pieces.iter_mut().enumerate() {
          queue.extend(piece.walk(&player, PlayerNavigationEvent::Leave).drain(..).map(|(event_name, value)| Event {
            sender: recipient,
            name: event_name,
            value,
          }));
        }
      }
    } else {
      // This means we are done with input events and done with clearing players on the map
      break;
    }
  }
}
pub ( crate ) fn process < T : IntoIterator < Item = Event > > ( state : & mut crate :: realm :: RealmPuzzleState , links : & mut std :: collections :: HashMap < crate :: PlayerKey , puzzleverse_core :: asset :: rules :: RealmLink > , events : T , ) { let mut count = 100 ; let mut queue = std :: collections :: VecDeque :: new ( ) ; let mut players_in_transit = Vec :: new ( ) ; queue . extend ( events ) ; // We only do 100 rounds of processing and then we assume the puzzle is some kind of unstable oscillator and give up. while count > 0 { count -= 1 ; // We're really handling two kinds of events: one based on our input and then knock on effects from having moved players around, so first, drain all our input events if let Some ( current ) = queue . pop_front ( ) { // Check each puzzle piece for an input event and gather the output events for propagation_rule in state . propagation_rules . iter ( ) . filter ( | propagation_rule | propagation_rule . sender == current . sender && propagation_rule . trigger == current . name ) { if let Some ( piece ) = state . pieces . get_mut ( propagation_rule . recipient ) { if let Some ( result ) = propagation_rule . propagation_match . apply ( & current . value , & state . settings ) . as_mut ( ) { for value in piece . accept ( & propagation_rule . causes , result ) { match value { // Any output events that are due to puzzle state, get fed back into out input queue OutputEvent :: Event ( event_name , value ) => { queue . push_back ( Event { sender : propagation_rule . recipient , name : event_name , value } ) ; } // The puzzle piece wants to move players; if we've already moved the players around, don't move them again OutputEvent :: Send ( link , players ) => { for player in players { if ! links . contains_key ( & player ) { players_in_transit . push ( player . clone ( ) ) ; links . insert ( player , link . clone ( ) ) ; } } } } } } } } } else if ! players_in_transit . is_empty ( ) { // Given we've processed all the input events, then make sure our players that are leaving exist nowhere on the map and all the pieces no that. If that generates more events, put them in the queue for player in players_in_transit . drain ( .. ) { for ( recipient , piece ) in state . pieces . iter_mut ( ) . enumerate ( ) { queue . extend ( piece . walk ( & player , PlayerNavigationEvent :: Leave ) . drain ( .. ) . map ( | ( event_name , value ) | Event { sender : recipient , name : event_name , value , } ) ) ; } } } else { // This means we are done with input events and done with clearing players on the map break ; } } }
Update puzzle state based on some player-initiated input event
Update puzzle state based on some player - initiated input event
state
&mut crate::realm::RealmPuzzleState
links
&mut std::collections::HashMap<crate::PlayerKey, puzzleverse_core::asset::rules::RealmLink>
events
T
state
&mut crate::realm::RealmPuzzleState
links
&mut std::collections::HashMap<crate::PlayerKey, puzzleverse_core::asset::rules::RealmLink>
events
T