~/home/blogs/case-study-game-server-discord-bots.md

Case Study: A Game Server with Discord Bot Integrations

Deploying a Project Zomboid server and developing Discord bots in TypeScript and Lua to drive community engagement and provide real-time server insights.

- Raul G.
2024-06-01

1. The Challenge: Creating a Persistent and Engaging Multiplayer Experience

For many multiplayer games, community engagement is key to a vibrant, long-lasting player base. While hosting a dedicated server for a game like Project Zomboid provides a persistent world, it lacks integration with the community's primary communication platform—in our case, Discord.

The challenge was twofold:

  1. Deploy and manage a stable, 24/7 dedicated game server with custom configurations and mods.
  2. Bridge the gap between the game server and our Discord community by developing custom tools to provide real-time event notifications, player statistics, and server status information.

2. Solution Part I: Dedicated Server Deployment and Management

The foundation of this project was a dedicated Project Zomboid server. I used LinuxGSM to streamline the installation and management process on a Linux VM. This provided a robust command-line interface for handling updates, backups, and server startups/shutdowns.

# Example LinuxGSM commands for server administration
./pzserver start   # Start the server process
./pzserver update  # Check for and apply SteamCMD updates
./pzserver backup  # Create a compressed backup of the server state

Server configuration and mod management were handled by modifying the .ini and .lua files, allowing for a highly customized gameplay experience tailored to our group.

3. Solution Part II: Custom Discord Bot Suite

To enhance community engagement, I developed a suite of TypeScript-based services that parse game logs and interact with the Discord API.

A. Real-Time Death Notifications

Problem: Player deaths are significant events in Project Zomboid. We wanted a way to share these moments with the community in real-time.

Solution: I developed a service that actively monitors the server's PerkLog file. When a new line is added, the script uses a regular expression to check if it's a death event.

// Regex to capture player name and hours survived from a log line
const deadLinePattern = /\[[\d\- :\.]+\] \[\d+\]\[(.+)\]\[\d+,\d+,\d+\]\[Died\]\[Hours Survived: (\d+)\]\./;

If a match is found, the script performs two actions:

  1. Sends a Discord Webhook: A message is immediately sent to a designated channel, announcing the death and how long the character survived.
  2. Logs to SQLite: The event data (player name, hours survived, timestamp) is stored in an SQLite database for future analysis.
sequenceDiagram
    participant Game Server
    participant Log File
    participant TypeScript Service
    participant SQLite DB
    participant Discord Webhook

    Game Server->>Log File: Appends player death event
    TypeScript Service->>Log File: Watches for file changes and reads new line
    TypeScript Service->>TypeScript Service: Matches line with Regex
    TypeScript Service->>SQLite DB: Stores death event data
    TypeScript Service->>Discord Webhook: Sends formatted notification

B. Weekly Leaderboard

Problem: We wanted a fun, competitive way to track player stats and celebrate (or commiserate) our collective efforts.

Solution: A second TypeScript script was created to query the SQLite database. It calculates the total number of deaths and hours survived for each player, ranking them in a "Zombie-Darwin Awards" leaderboard. This script is scheduled to run weekly as a cron job, automatically posting the updated leaderboard to Discord.

C. /online Player Status Command

Problem: Players wanted an easy way to check who was currently online without having to launch the game.

Solution: This required a more integrated approach.

  1. Custom Lua Mod: I wrote a simple in-game mod in Lua that hooks into the server's tick cycle. Every 900 ticks (~15 seconds), it writes the current list of online players and their stats (profession, kills, hours alive) to a dedicated log file.
  2. Watcher Service: A TypeScript service monitors this new log file. When the file is updated, it parses the content and saves the current player list to a structured players.json file.
  3. Discord Bot: A separate Discord bot application was created. It registers a slash command (/online). When a user executes the command, the bot reads the players.json file and presents the data in a clean, embedded format in the Discord channel.

This three-part system effectively provides a near real-time view of the server's status directly within Discord.

4. Results and Impact

This project successfully transformed a standard game server into a deeply integrated community hub.

  • Increased Engagement: The real-time notifications and leaderboards sparked conversations and brought a new level of shared experience to the game.
  • Valuable Automation: The system operates autonomously, requiring no manual intervention to provide continuous, valuable insights to the community.
  • Demonstrated Technical Skills: The project showcases a range of skills, including:
    • Server Administration: Deploying and managing a Linux-based game server.
    • Backend Development: Writing services in TypeScript to parse data, interact with a database, and call external APIs.
    • Game Modding: Creating a custom Lua mod to extract in-game data.
    • DevOps: Using tools like cron for scheduling and SQLite for data persistence.

This case study demonstrates the ability to identify a need within a community and build a full-stack, automated solution to meet that need, creating a more engaging and connected user experience.

Share this post