Skip to content

ayushmaanbhav/LanGameplayEngine

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

C++23 CMake Platform License

Local Gameplay Engine

A high-performance, modern C++23 multiplayer card game server framework with async networking

FeaturesArchitectureQuick StartDocumentationContributing

Stars Forks Watchers


Overview

Local Gameplay Engine is a production-ready, highly scalable multiplayer card game server framework built with modern C++23. It provides a complete infrastructure for hosting real-time card games over LAN with automatic server discovery, state machine-driven game logic, and thread-safe concurrent operations.

Originally designed for Teen Patti (Indian Poker), the engine's extensible architecture supports any turn-based card game with minimal modifications.

Why Local Gameplay Engine?

Feature Benefit
Modern C++23 Leverages cutting-edge language features for safety and performance
Async I/O Non-blocking networking with ASIO for high concurrency
State Machine Clean, maintainable game logic with 11 distinct states
Auto Discovery UDP multicast for seamless LAN server discovery
Thread-Safe Comprehensive mutex protection and atomic operations
Extensible Strategy pattern for easy game mode additions

Features

Core Capabilities

  • Real-time Multiplayer - Support for up to 8 players per room (5 active at table)
  • TCP Game Server - Reliable message delivery with automatic session management
  • UDP Discovery - Multicast-based server broadcasting for LAN discovery
  • State Machine Logic - 11-state game action system for complex game flows
  • Card Comparison - Extensible ranking system (High Card → Trail)
  • Timeout Handling - Automatic actions on player inactivity

Technical Excellence

  • Zero Raw Pointers - Smart pointers throughout for memory safety
  • RAII Everywhere - Deterministic resource cleanup
  • C++23 Features - std::print, std::expected, std::jthread, ranges, and more
  • Cross-Platform - Linux, macOS, and Windows support
  • Modern CMake - Clean build configuration with vcpkg integration

Game Features

Feature Description
Boot Collection Initial ante collection from all players
Blind/Seen Play Players can bet blind or view their cards
Chaal (Bet) Standard betting with raise capability
Pack (Fold) Fold and exit current hand
Show Reveal cards for comparison
Side Show Private card comparison between two players

Architecture

System Architecture

┌─────────────────────────────────────────────────────────────────────────────┐
│                           CLIENT APPLICATIONS                                │
│                    (Mobile Apps, Desktop Clients, Web)                       │
└──────────────────────────────┬──────────────────────────────────────────────┘
                               │
              ┌────────────────┴────────────────┐
              │                                 │
              ▼                                 ▼
┌─────────────────────────┐       ┌─────────────────────────┐
│    UDP Discovery        │       │     TCP Game Server     │
│    (Port 33407)         │       │    (Port 45400+)        │
│                         │       │                         │
│  • Multicast Broadcast  │       │  • Session Management   │
│  • Server Announcement  │       │  • Message Routing      │
│  • Auto-Discovery       │       │  • Async I/O (ASIO)     │
└─────────────────────────┘       └────────────┬────────────┘
                                               │
                               ┌───────────────┴───────────────┐
                               │                               │
                               ▼                               ▼
              ┌────────────────────────────┐  ┌────────────────────────────┐
              │   LocalGameplayController  │  │   GameServerClientSession  │
              │                            │  │                            │
              │  • Entry Point             │  │  • Per-Client Handler      │
              │  • Lifecycle Management    │  │  • Message Parsing         │
              │  • Delegate Implementation │  │  • Async Read/Write        │
              └─────────────┬──────────────┘  └────────────────────────────┘
                            │
                            ▼
              ┌────────────────────────────┐
              │      RoomController        │
              │                            │
              │  • Game Loop Thread        │
              │  • State Machine Driver    │
              │  • Player Management       │
              │  • Heartbeat Broadcasting  │
              └─────────────┬──────────────┘
                            │
           ┌────────────────┼────────────────┐
           │                │                │
           ▼                ▼                ▼
┌──────────────────┐ ┌─────────────┐ ┌──────────────────┐
│   IGameAction    │ │  GameState  │ │ LocalGameplay    │
│   State Machine  │ │             │ │ Messenger        │
│                  │ │  • Players  │ │                  │
│  • IdleAction    │ │  • Amounts  │ │  • Broadcasts    │
│  • BootCollect   │ │  • Timers   │ │  • Notifications │
│  • UserInput     │ │  • Cards    │ │  • Game Events   │
│  • Chaal/Fold    │ │  • Status   │ │                  │
│  • Show/SideShow │ │             │ │                  │
│  • GameEnd       │ │             │ │                  │
└──────────────────┘ └─────────────┘ └──────────────────┘

State Machine Flow

                                    ┌──────────────┐
                                    │   IDLE       │◄─────────────────────┐
                                    │  (Waiting)   │                      │
                                    └──────┬───────┘                      │
                                           │ ≥2 players                   │
                                           ▼                              │
                                    ┌──────────────┐                      │
                                    │BOOT COLLECT  │                      │
                                    │(Ante + Deal) │                      │
                                    └──────┬───────┘                      │
                                           │                              │
                                           ▼                              │
                              ┌────────────────────────┐                  │
                              │     USER INPUT         │◄──────┐          │
                              │  (Waiting for Action)  │       │          │
                              └───────────┬────────────┘       │          │
                                          │                    │          │
            ┌─────────────────┬───────────┼───────────┬────────┘          │
            │                 │           │           │                   │
            ▼                 ▼           ▼           ▼                   │
     ┌──────────┐      ┌──────────┐ ┌──────────┐ ┌──────────────┐         │
     │  CHAAL   │      │   FOLD   │ │   SHOW   │ │ SIDE SHOW    │         │
     │  (Bet)   │      │  (Pack)  │ │ (Reveal) │ │ (Request)    │         │
     └────┬─────┘      └────┬─────┘ └────┬─────┘ └──────┬───────┘         │
          │                 │            │              │                 │
          │                 │            │              ▼                 │
          │                 │            │       ┌──────────────┐         │
          │                 │            │       │SIDE SHOW     │         │
          │                 │            │       │ACCEPT/REJECT │         │
          │                 │            │       └──────┬───────┘         │
          │                 │            │              │                 │
          └────────┬────────┴────────────┴──────────────┘                 │
                   │                                                      │
                   ▼                                                      │
            ┌──────────────┐                                              │
            │  GAME END    │──────────────────────────────────────────────┘
            │(Winner/Pot)  │
            └──────────────┘

Layer Architecture

┌─────────────────────────────────────────────────────────────┐
│                    APPLICATION LAYER                         │
│         LocalGameplayController, RoomController              │
├─────────────────────────────────────────────────────────────┤
│                    GAME LOGIC LAYER                          │
│    IGameAction States, GameState, ICardComparator            │
├─────────────────────────────────────────────────────────────┤
│                   COMMUNICATION LAYER                        │
│   GameServer, GameServerClientSession, LocalGameplayMessenger│
├─────────────────────────────────────────────────────────────┤
│                      DATA LAYER                              │
│  GamePlayerInfo, CardDeck, UserAction, GameEndDetails        │
├─────────────────────────────────────────────────────────────┤
│                  INFRASTRUCTURE LAYER                        │
│                     ASIO, Threads                            │
└─────────────────────────────────────────────────────────────┘

Quick Start

Prerequisites

Requirement Version Notes
C++ Compiler GCC 14+, Clang 18+, MSVC 19.35+ C++23 support required
CMake 3.28+ Modern CMake features
ASIO Latest Standalone (non-Boost)

Installation

Option 1: CMake FetchContent

include(FetchContent)
FetchContent_Declare(
    local_gameplay
    GIT_REPOSITORY https://github.com/ayushmaanbhav/local_gameplay.git
    GIT_TAG main
)
FetchContent_MakeAvailable(local_gameplay)

target_link_libraries(your_target PRIVATE local_gameplay)

Option 2: Build from Source

# Clone the repository
git clone https://github.com/ayushmaanbhav/local_gameplay.git
cd local_gameplay/cpp23

# Configure
cmake -B build -DCMAKE_BUILD_TYPE=Release

# Build
cmake --build build --parallel

# Install (optional)
sudo cmake --install build

Option 3: vcpkg

# Coming soon
vcpkg install local-gameplay

Basic Usage

#include <local_gameplay/LocalGameplayController.hpp>

int main() {
    using namespace local_gameplay;

    // Get the singleton controller
    auto& controller = LocalGameplayController::getInstance();

    // Start as host
    bool success = controller.startAsHost(
        "player_123",           // Player ID
        "HostPlayer",           // Display name
        1,                      // Avatar ID
        "game_room_456",        // Room ID
        "High Stakes Table"     // Table name
    );

    if (!success) {
        std::println(stderr, "Failed to start game server");
        return 1;
    }

    std::println("Server started on port: {}", controller.tcpPort());
    std::println("Room ID: {}", controller.roomId());

    // Server runs until stopped
    // ... game logic ...

    // Cleanup
    controller.stop();
    return 0;
}

Configuration

// Room configuration
RoomControllerConfiguration config;
config.setRoomInfo({
    .boot_amount = 100,      // Initial ante
    .boot_limit = 1024,      // Maximum boot
    .max_chaal = 2048,       // Maximum bet
    .pot_limit = 100000,     // Pot limit
    .max_blind = 4,          // Max blind rounds
    .countdown_timer = 6000, // Game start countdown (ms)
    .user_timer = 30000,     // Player decision timeout (ms)
    .side_show_timer = 12000 // Side show response timeout (ms)
});
config.setGameMode(GameMode::Normal);

Documentation

Project Structure

local_gameplay/
├── cpp23/                          # Modern C++23 implementation
│   ├── CMakeLists.txt              # Build configuration
│   ├── LocalGameplayController.*   # Main entry point
│   ├── discovery/                  # UDP multicast discovery
│   │   ├── UDPMessage.*            # Discovery message format
│   │   ├── UDPMulticastClient.*    # Discovery client
│   │   └── UDPMulticastServer.*    # Discovery broadcaster
│   └── server/                     # Game server components
│       ├── GameServer.*            # TCP server
│       ├── GameServerClientSession.*
│       ├── LocalGameplayMessenger.*
│       ├── RoomController.*
│       ├── card_comparator/        # Card ranking logic
│       ├── entities/               # Data models
│       └── game_action/            # State machine actions
├── .github/                        # GitHub configuration
│   ├── workflows/                  # CI/CD pipelines
│   ├── ISSUE_TEMPLATE/             # Issue templates
│   └── FUNDING.yml                 # Sponsorship info
├── CONTRIBUTING.md                 # Contribution guidelines
├── CODE_OF_CONDUCT.md              # Community standards
├── SECURITY.md                     # Security policy
└── LICENSE                         # License file

Data Models

GamePlayerInfo

Represents a player in the game:

struct GamePlayerInfo {
    std::string pid;              // Player ID
    std::string name;             // Display name
    UserGameState state;          // Current state (Blind, Seen, Pack, etc.)
    std::array<int, 3> cards;     // Player's 3 cards
    int64_t amount_in_hand;       // Available chips
    int64_t amount_in_game;       // Chips in current pot
    bool seen;                    // Has viewed cards
    bool is_raise;                // Raised this round
    // ... additional fields
};

enum class UserGameState {
    Inactive, Boot, Blind, Seen, Chaal, Pack, Show, SideShow
};

Card Representation

Cards are represented as integers 0-51:

  • Value: card % 13 (0=Ace, 1-9=2-10, 10=J, 11=Q, 12=K)
  • Suit: card / 13 (0=Spades, 1=Hearts, 2=Clubs, 3=Diamonds)

Hand Rankings (Lowest to Highest)

Rank Pattern Description
1 High Card Highest single card
2 Pair Two cards of same value
3 Color (Flush) All three cards same suit
4 Sequence (Straight) Three consecutive values
5 Pure Sequence Consecutive cards, same suit
6 Trail (Three of a Kind) Three cards of same value

Network Protocol

TCP Messages

Messages are delimited by backtick (`) character:

{message_type}|{payload_json}`

UDP Discovery

Multicast address: 239.255.116.91:33407

{game_mode};{server_ip};{table_name};{avatar_id}`

Thread Model

Thread Component Purpose
Main Caller context Application control
I/O Thread GameServer ASIO async operations
Game Thread RoomController Game loop execution
Heartbeat Thread RoomController Periodic broadcasts

Design Patterns

Singleton Pattern

Used for core services requiring single instance:

class GameServer {
public:
    static GameServer& getInstance() {
        static GameServer instance;
        return instance;
    }

    GameServer(const GameServer&) = delete;
    GameServer& operator=(const GameServer&) = delete;

private:
    GameServer() = default;
};

State Pattern

Game actions implement a state machine:

class IGameAction {
public:
    virtual ~IGameAction() = default;
    virtual void processUserInput(GameState&, const UserAction&) = 0;
    virtual void processAction(GameState&) = 0;
    virtual std::unique_ptr<IGameAction> getNextAction(GameState&) = 0;
    virtual void interrupt() = 0;
};

Strategy Pattern

Card comparison is pluggable:

class ICardComparator {
public:
    virtual ~ICardComparator() = default;
    virtual std::vector<std::shared_ptr<GamePlayerInfo>>
        getWinners(const GamePlayerInfoMap& players) = 0;
};

// Implementations: NormalModeCardComparator, JokerModeCardComparator, etc.

Observer/Delegate Pattern

Decoupled message handling:

class GameServerClientSession {
public:
    class Delegate {
    public:
        virtual void processMessage(int session_id, std::string_view msg) = 0;
        virtual void removeClosedSession(int session_id) = 0;
    };
};

C++23 Features

This codebase showcases modern C++23 capabilities:

Feature Usage
std::print/println Type-safe formatted output
std::expected Error handling without exceptions
std::string_view Zero-copy string parameters
std::jthread Auto-joining threads with stop tokens
std::span Non-owning array views
std::ranges Modern algorithm pipelines
<=> operator Defaulted comparisons
[[nodiscard]] Enforce return value checking
Designated initializers Named struct initialization

CMake Options

Option Default Description
BUILD_EXAMPLES OFF Build example applications
BUILD_TESTS OFF Build unit tests
BUILD_SHARED_LIBS OFF Build as shared library
cmake -B build \
    -DCMAKE_BUILD_TYPE=Release \
    -DBUILD_EXAMPLES=ON \
    -DBUILD_TESTS=ON

Performance

Benchmarks

Metric Value Notes
Connection handling 10+ concurrent Per room instance
Message latency < 1ms Local network
Memory per session ~4KB Minimal overhead
State transition < 100μs Fast game logic

Optimization Techniques

  • Zero-copy messaging with std::string_view
  • Object pooling for session management
  • Lock-free atomics where possible
  • Async I/O prevents blocking

Contributing

We welcome contributions! Please see CONTRIBUTING.md for guidelines.

Development Setup

# Clone with submodules
git clone --recursive https://github.com/ayushmaanbhav/local_gameplay.git

# Install dependencies (Ubuntu/Debian)
sudo apt install build-essential cmake ninja-build

# Install ASIO
sudo apt install libasio-dev

# Build with debug symbols
cmake -B build -DCMAKE_BUILD_TYPE=Debug -G Ninja
cmake --build build

Code Style

  • Follow the C++ Core Guidelines
  • Use clang-format with the provided configuration
  • Write self-documenting code with clear naming
  • Add Doxygen comments for public APIs

Roadmap

  • WebSocket support for browser clients
  • Multiple game mode implementations (Joker, AK47)
  • Comprehensive test suite
  • Performance benchmarking suite
  • Docker containerization
  • Kubernetes deployment manifests
  • Documentation website

Support


Sponsors

Sponsor

Support the development of Local Gameplay Engine:

Your sponsorship helps maintain and improve this project!


License

This project is licensed under the MIT License - see the LICENSE file for details.


Acknowledgments

  • ASIO - Excellent async I/O library
  • CMake - Cross-platform build system
  • C++ Standards Committee - For C++23 features

Built with ❤️ by Ayush Jain

⭐ Star this repo🍴 Fork it🐛 Report bugs

Releases

No releases published

Sponsor this project

 

Packages

No packages published