Initial commit: SSH MUD server with data-driven world
Rust-based MUD server accepting SSH connections on port 2222. Players connect with any SSH client, get dropped into a data-driven world loaded from TOML files at startup. Binary systems: SSH handling (russh), command parser, game state, multiplayer broadcast, ANSI terminal rendering. Data layer: world/ directory with regions, rooms, NPCs, and objects defined as individual TOML files — no recompile needed to modify. Commands: look, movement (n/s/e/w/u/d), say, who, help, quit. Made-with: Cursor
This commit is contained in:
70
src/game.rs
Normal file
70
src/game.rs
Normal file
@@ -0,0 +1,70 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use russh::server::Handle;
|
||||
use russh::ChannelId;
|
||||
|
||||
use crate::world::World;
|
||||
|
||||
pub struct Player {
|
||||
pub name: String,
|
||||
pub room_id: String,
|
||||
}
|
||||
|
||||
pub struct PlayerConnection {
|
||||
pub player: Player,
|
||||
pub channel: ChannelId,
|
||||
pub handle: Handle,
|
||||
}
|
||||
|
||||
pub struct GameState {
|
||||
pub world: World,
|
||||
pub players: HashMap<usize, PlayerConnection>,
|
||||
}
|
||||
|
||||
pub type SharedState = Arc<Mutex<GameState>>;
|
||||
|
||||
impl GameState {
|
||||
pub fn new(world: World) -> Self {
|
||||
GameState {
|
||||
world,
|
||||
players: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn spawn_room(&self) -> &str {
|
||||
&self.world.spawn_room
|
||||
}
|
||||
|
||||
pub fn add_player(&mut self, id: usize, name: String, channel: ChannelId, handle: Handle) {
|
||||
let room_id = self.world.spawn_room.clone();
|
||||
self.players.insert(
|
||||
id,
|
||||
PlayerConnection {
|
||||
player: Player { name, room_id },
|
||||
channel,
|
||||
handle,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
pub fn remove_player(&mut self, id: usize) -> Option<PlayerConnection> {
|
||||
self.players.remove(&id)
|
||||
}
|
||||
|
||||
pub fn players_in_room(&self, room_id: &str, exclude_id: usize) -> Vec<&PlayerConnection> {
|
||||
self.players
|
||||
.iter()
|
||||
.filter(|(&id, conn)| conn.player.room_id == room_id && id != exclude_id)
|
||||
.map(|(_, conn)| conn)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn all_player_names(&self) -> Vec<&str> {
|
||||
self.players
|
||||
.values()
|
||||
.map(|c| c.player.name.as_str())
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user