2025-11-05 20:24:51 +00:00
|
|
|
// Copyright (C) 2025 Emilis Bliūdžius
|
|
|
|
|
//
|
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
|
// it under the terms of the GNU Affero General Public License as
|
|
|
|
|
// published by the Free Software Foundation, either version 3 of the
|
|
|
|
|
// License, or (at your option) any later version.
|
|
|
|
|
//
|
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
// GNU Affero General Public License for more details.
|
|
|
|
|
//
|
|
|
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
|
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
2025-10-04 09:26:37 +01:00
|
|
|
use core::sync::atomic::{AtomicBool, Ordering};
|
|
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
|
|
|
|
use tokio::sync::Mutex;
|
|
|
|
|
use werewolves_proto::player::PlayerId;
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub struct ConnectUpdate {
|
|
|
|
|
updated: Arc<AtomicBool>,
|
|
|
|
|
connected: Arc<Mutex<Vec<PlayerId>>>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ConnectUpdate {
|
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
updated: Arc::new(AtomicBool::new(false)),
|
|
|
|
|
connected: Arc::new(Mutex::new(Vec::new())),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub async fn connect(&self, pid: PlayerId) {
|
|
|
|
|
let mut connected = self.connected.lock().await;
|
|
|
|
|
if connected.iter().any(|c| c == &pid) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
connected.push(pid);
|
|
|
|
|
self.updated.store(true, Ordering::SeqCst);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub async fn disconnect(&self, pid: PlayerId) {
|
|
|
|
|
let mut connected = self.connected.lock().await;
|
|
|
|
|
if let Some(idx) = connected
|
|
|
|
|
.iter()
|
|
|
|
|
.enumerate()
|
|
|
|
|
.find_map(|(idx, c)| (c == &pid).then_some(idx))
|
|
|
|
|
{
|
|
|
|
|
connected.swap_remove(idx);
|
|
|
|
|
self.updated.store(true, Ordering::SeqCst);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Future for ConnectUpdate {
|
|
|
|
|
type Output = Arc<[PlayerId]>;
|
|
|
|
|
|
|
|
|
|
fn poll(
|
|
|
|
|
self: std::pin::Pin<&mut Self>,
|
|
|
|
|
cx: &mut std::task::Context<'_>,
|
|
|
|
|
) -> std::task::Poll<Self::Output> {
|
|
|
|
|
if self.updated.load(Ordering::SeqCst)
|
|
|
|
|
&& let Ok(connected) = self.connected.try_lock()
|
|
|
|
|
{
|
|
|
|
|
self.updated.store(false, Ordering::SeqCst);
|
|
|
|
|
std::task::Poll::Ready(connected.clone().into())
|
|
|
|
|
} else {
|
|
|
|
|
cx.waker().wake_by_ref();
|
|
|
|
|
std::task::Poll::Pending
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|