Allow to see rooms of incompatible versions in the lobby
For the new clients the room version is shown in a separate column.
There is also a hack for previous versions clients: the room vesion
specifier is prepended to the room names for rooms of incompatible versions,
and the server shows 'incompatible version' error if the client tries to join them.
use crate::{
collision::{fppoint_round, CircleBounds, DetectedCollisions},
common::GearId,
};
use fpnum::FPPoint;
use integral_geometry::{GridIndex, Point, PotSize};
struct GridBin {
refs: Vec<GearId>,
entries: Vec<CircleBounds>,
}
impl GridBin {
fn new() -> Self {
Self {
refs: vec![],
entries: vec![],
}
}
fn add(&mut self, gear_id: GearId, bounds: &CircleBounds) {
self.refs.push(gear_id);
self.entries.push(*bounds);
}
fn remove(&mut self, gear_id: GearId) -> bool {
if let Some(pos) = self.refs.iter().position(|id| *id == gear_id) {
self.refs.swap_remove(pos);
self.entries.swap_remove(pos);
true
} else {
false
}
}
}
const GRID_BIN_SIZE: usize = 128;
pub struct Grid {
bins: Vec<GridBin>,
space_size: PotSize,
bins_count: PotSize,
index: GridIndex,
}
impl Grid {
pub fn new(size: PotSize) -> Self {
let bins_count =
PotSize::new(size.width() / GRID_BIN_SIZE, size.height() / GRID_BIN_SIZE).unwrap();
Self {
bins: (0..bins_count.area()).map(|_| GridBin::new()).collect(),
space_size: size,
bins_count,
index: PotSize::square(GRID_BIN_SIZE).unwrap().to_grid_index(),
}
}
fn linear_bin_index(&self, index: Point) -> usize {
self.bins_count
.linear_index(index.x as usize, index.y as usize)
}
fn bin_index(&self, position: &FPPoint) -> Point {
self.index.map(fppoint_round(position))
}
fn get_bin(&mut self, index: Point) -> &mut GridBin {
let index = self.linear_bin_index(index);
&mut self.bins[index]
}
fn try_get_bin(&mut self, index: Point) -> Option<&mut GridBin> {
let index = self.linear_bin_index(index);
self.bins.get_mut(index)
}
fn lookup_bin(&mut self, position: &FPPoint) -> &mut GridBin {
self.get_bin(self.bin_index(position))
}
pub fn insert(&mut self, gear_id: GearId, bounds: &CircleBounds) {
self.lookup_bin(&bounds.center).add(gear_id, bounds);
}
fn remove_all(&mut self, gear_id: GearId) {
for bin in &mut self.bins {
if bin.remove(gear_id) {
break;
}
}
}
pub fn remove(&mut self, gear_id: GearId, bounds: Option<&CircleBounds>) {
if let Some(bounds) = bounds {
if !self.lookup_bin(&bounds.center).remove(gear_id) {
self.remove_all(gear_id);
}
} else {
self.remove_all(gear_id);
}
}
pub fn check_collisions(&self, collisions: &mut DetectedCollisions) {
for bin in &self.bins {
for (index, bounds) in bin.entries.iter().enumerate() {}
}
}
}