A real-time multiplayer Belote card game built with ASP.NET Core SignalR, featuring a single lobby system and live game interactions.
This project follows a clean architecture pattern with clear separation of concerns:
- Hub Layer: SignalR communication management
- Service Layer: Business logic and game rules
- Models Layer: Data transfer objects and domain entities
- Singleton Pattern: Single lobby instance for simplified game management
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐ │ Client Web │◄──►│ BeloteHub │◄──►│ LobbyService │ │ (JavaScript) │ │ (SignalR) │ │ │ └─────────────────┘ └──────────────────┘ └─────────────────┘ │ │ │ ▼ │ ┌─────────────────┐ │ │ ILobby │ │ │ (Singleton) │ │ └─────────────────┘ │ ▼ ┌──────────────────┐ │ GameService │ │ │ └──────────────────┘
BeloteGame/ ├── 📁 Models/ # Data models and DTOs │ ├── Player.cs # Player entity │ ├── LobbyInfo.cs # Lobby state information │ ├── JoinResult.cs # Join operation result │ ├── Card.cs # Game card model │ ├── GameState.cs # Current game state │ └── Bid.cs # Bidding information │ ├── 📁 Services/ │ ├── 📁 Contracts/ # Service interfaces │ │ ├── ILobbyService.cs # Lobby management contract │ │ ├── IGameService.cs # Game logic contract │ │ └── ILobby.cs # Singleton lobby contract │ │ │ └── 📁 Implementations/ # Service implementations │ ├── LobbyService.cs # Lobby business logic │ ├── GameService.cs # Game rules and state │ └── Lobby.cs # Singleton lobby instance │ ├── 📁 Hubs/ # SignalR communication │ └── BeloteHub.cs # Real-time communication hub │ └── Program.cs # Application startup and DI
Responsibility: Handle real-time client-server communication
- Manages SignalR connections
- Routes client requests to appropriate services
- Handles connection/disconnection events
- Manages SignalR groups for lobby organization
Key Methods:
JoinLobby()- Add player to lobbyLeaveLobby()- Remove player from lobbyStartGame()- Initiate game sessionPlayCard(Card card)- Process card playsMakeBid(Bid bid)- Handle bidding
Responsibility: Manage lobby state and player sessions
- Player join/leave operations
- Lobby state management
- Game initiation logic
- Connection handling
- Real-time notifications via HubContext
Key Features:
- Thread-safe operations with locking
- Single lobby instance management
- Player limit enforcement (4 players max)
- Disconnection handling
Responsibility: Implement Belote game rules and logic
- Game state management
- Card play validation
- Bidding system
- Score calculation
- Turn management
Responsibility: Maintain single lobby instance
- Player collection management
- Game state tracking
- Thread-safe operations
- Lobby reset functionality
Responsibility: Define data structures and DTOs
- Player: User information and connection details
- LobbyInfo: Current lobby state for client updates
- JoinResult: Operation result with success/error information
- Card: Game card representation
- GameState: Complete game state information
- Bid: Bidding information and validation
- Client calls JoinLobby() → BeloteHub
- BeloteHub → LobbyService.JoinLobby()
- LobbyService updates Lobby singleton
- LobbyService → HubContext.NotifyLobbyUpdate()
- All lobby clients receive LobbyUpdated event
- Client calls StartGame() → BeloteHub
- BeloteHub → LobbyService.StartGame()
- LobbyService validates player count (4 players)
- LobbyService → GameService.StartNewGame()
- GameService creates new game state
- All players receive GameStarted event with initial state
- Client calls PlayCard(card) → BeloteHub
- BeloteHub → GameService.PlayCard()
- GameService validates move and updates state
- All players receive CardPlayed event with new state
- All services registered as singletons
- Clear separation of contracts and implementations
- Testable architecture with interface-based design
- Single lobby instance shared across all connections
- Thread-safe operations with explicit locking
- Simplified state management without ID tracking
- Real-time state synchronization
- Event-driven client updates
- Automatic notification system
- Business logic separated from communication logic
- Reusable services for different endpoints
- Clear responsibility boundaries
builder.Services.AddSignalR();
// Register singleton services
builder.Services.AddSingleton<ILobby, Lobby>();
builder.Services.AddSingleton<ILobbyService, LobbyService>();
builder.Services.AddSingleton<IGameService, GameService>();
// Map SignalR hub
app.MapHub<BeloteHub>("/belotehub");