reserved usernames

This commit is contained in:
Adam 2024-08-05 00:08:29 -04:00
parent 959d300455
commit d930583e12
6 changed files with 44 additions and 24 deletions

View file

@ -31,7 +31,7 @@ pub fn Auth() -> impl IntoView {
})
.unwrap(),
);
set_username.set(input.value());
set_username.set("".to_string());
input.set_value("");
}
}

View file

@ -4,12 +4,13 @@ A game master server for the popular game [Cards Against Humanity](https://www.c
This started as a problem trying to play games with friends who are all on different platforms. This shall be as cross-platform as it gets. I want it to work on anything that can establish a connection and allow anyone to write any front-end they can dream up whether it be a web page, chat bot, VR, etc. Any clients who share a master server can play together across any platform.
## Test/Dev:
### Server
With auto-reload:
* [Install cargo-watch](https://github.com/watchexec/cargo-watch?tab=readme-ov-file#install)
- [Install cargo-watch](https://github.com/watchexec/cargo-watch?tab=readme-ov-file#install)
Then:
@ -19,14 +20,15 @@ watch -i client -cx run
or if you're lazy like me just run `./test`
Without auto-reload:
```sh
cargo run
```
### Client
* [Install Trunk](https://trunkrs.dev/#install)
- [Install Trunk](https://trunkrs.dev/#install)
Then:
@ -37,31 +39,33 @@ trunk serve --open
## Build:
### Client
```sh
trunk build --release
```
### Server
```sh
cargo build
```
----------
* The server automatically serves the built client from `/dist` at `0.0.0.0:3030`
---
* Configure any custom clients to connect to `ws://0.0.0.0:3030/websocket`
- The server automatically serves the built client from `/dist` at `0.0.0.0:3030`
- Configure any custom clients to connect to `ws://0.0.0.0:3030/websocket`
## TODO:
* finish game logic
* prevent multiple users claiming the same identity and then all losing it - may create a zombie
* prevent zombie users after browser crash
* figure out proper auth - client's problem?
* use db
* test bincode and probably move away from json
* make typescript sdk
* support card text editing
* prevent import of cards that have been seen already and edited
* handle duplicates
* efficiency
* make demo clients for multiple platforms and screens
- finish game logic
- prevent zombie users after browser crash
- figure out proper auth - client's problem?
- use db
- test bincode and probably move away from json
- make typescript sdk
- support card text editing
- prevent import of cards that have been seen already and edited
- handle duplicates
- efficiency
- make demo clients for multiple platforms and screens

View file

@ -44,7 +44,7 @@ pub async fn on_websocket_connection(stream: WebSocket, state: Arc<AppState>, ad
// Subscribe to receive from global broadcast channel
let mut rx = state.tx.subscribe();
// Submit new messages from this client to broadcast
// Send messages to this client
let mut send_task = tokio::spawn(async move {
while let Ok(msg) = rx.recv().await {
if sender.send(Message::Text(msg)).await.is_err() {
@ -53,7 +53,7 @@ pub async fn on_websocket_connection(stream: WebSocket, state: Arc<AppState>, ad
}
});
// Pass messages from broadcast down to this client
// Receive messages from this client
let mut recv_task = tokio::spawn(async move {
while let Some(Ok(message)) = receiver.next().await {
message_handler(state.clone(), addr, message)

View file

@ -132,6 +132,8 @@ fn handle_user_log_in(
};
tracing::debug!("{msg}");
} else if state.reserved_names.read().unwrap().contains(&new_name) {
tracing::debug!("name is taken");
} else {
state
.online_users
@ -149,8 +151,16 @@ fn handle_user_log_in(
new_name
};
// Reserve name
state
.reserved_names
.write()
.unwrap()
.insert(new_name.clone());
tracing::debug!("{msg}");
tx.send(to_string::<ChatMessage>(&ChatMessage { text: msg })?)?;
tracing::debug!("Name {} reserved.", &new_name);
}
tracing::debug!(
@ -159,6 +169,9 @@ fn handle_user_log_in(
state.offline_users.read().unwrap().len()
);
tx.send(games_update(state))?;
tx.send(chat_meta_update(state))?;
// send the user their new name
Ok(())
}

View file

@ -4,7 +4,7 @@ use rand::prelude::IteratorRandom;
use rand::thread_rng;
use serde::Deserialize;
use std::{
collections::HashMap,
collections::{HashMap, HashSet},
fs::{read_to_string, File},
io::{BufRead, BufReader},
net::SocketAddr,
@ -339,6 +339,7 @@ pub fn load_names(path: &str) -> Result<Vec<String>> {
// Our shared state
pub struct AppState {
// We require unique usernames. This tracks which usernames have been taken.
pub reserved_names: RwLock<HashSet<String>>,
pub online_users: RwLock<HashMap<SocketAddr, Arc<RwLock<User>>>>,
pub offline_users: RwLock<HashMap<String, Arc<RwLock<User>>>>,
// Channel used to send messages to all connected clients.

View file

@ -3,7 +3,7 @@
use anyhow::{Context, Result};
use axum::{routing::get, Router};
use std::{
collections::HashMap,
collections::{HashMap, HashSet},
net::SocketAddr,
sync::{Arc, RwLock},
};
@ -28,6 +28,7 @@ async fn main() -> Result<()> {
// Set up application state for use with with_state().
// Main Broadcast Channel
let (tx, _rx) = broadcast::channel(100);
let reserved_names = RwLock::new(HashSet::<String>::new());
let online_users = RwLock::new(HashMap::<SocketAddr, Arc<RwLock<User>>>::new());
let offline_users = RwLock::new(HashMap::<String, Arc<RwLock<User>>>::new());
let (packs, packs_meta) = load_cards_from_json("data/cah-cards-full.json")?;
@ -36,6 +37,7 @@ async fn main() -> Result<()> {
let last_names = load_names("data/last.txt")?;
let app_state = Arc::new(AppState {
reserved_names,
online_users,
offline_users,
tx,