MODERN MEDICINE BACKEND

Backend

The core of the backend system uses ProfileService which is an extension module for DataStores. ProfileService is a is a profile object abstraction seperated from the Player instance which streamlines datastore implementation and handles lots of edge cases such as providing protection against item duplication exploits.

Monetization and Transaction Workflows

There are two types of transactions the player can make: Robux transactions and RVU transactions. RVUs (Relative Value Units) are the in-game premium currency.

Developer Products
  1. The client uses a remote event to request developer product purchase
  2. The server recieves event and fires MarketplaceService:PromptProductPurchase with the player and product id
  3. The player purchases the product using the Roblox GUI
  4. If the transaction is successful, the MarketplaceService.ProcessReceipt callback is triggered
    • If verification fails, Enum.ProductPurchaseDecision.NotProcessedYet is returned
  5. The server retrieves and verifies player’s data profile from ProfileService
    • If there is an error verifying the player profile, Enum.ProductPurchaseDecision.NotProcessedYet is returned
  6. The player’s data profile’s metadata is reviewed and written to ensuring the developer product is not being granted multiple times for the same transaction
    • If an error or abnormality is detected, Enum.ProductPurchaseDecision.NotProcessedYet is returned.
  7. The product id is processed and the product is added to the player’s account
  8. A remote event is fired informing the client that the purchase was a success
  9. Enum.ProductPurchaseDecision.PurchaseGranted is returned

Notes:

  • If Enum.ProductPurchaseDecision.NotProcessedYet is fired, MarketplaceService will perform the transaction again if the user makes another purchase or rejoins the server.
A player standing in a doorway.
The RVU boost is a developer product which increases the amount of RVUs the player can earn in a run.
Custom Currency (RVU) Products

A similar workflow is used for RVU purchases, but it does not go through the MarketplaceService due to the currency being proprietary. If a player does not have enough RVU to complete the transaction, they are prompted to purchase more.

A shield with a crystalized color patter design and a medical logo on it.
The RVU curency icon.
Gamepasses

Gamepass purchases rely almost entirely on the Roblox backend, which prevents players from purchasing the same gamepass multiple times. When joining the game, players are sent to a lobby. When they are ready to play the game, players hop in an elevator which moves them to a private server and sets up the match. Gamepasses only purchasesable in the lobby or on the Roblox website and only affect the match servers, therefore there is no need to detect gamepass purchases in real time.

MarketplaceService.PromptGamePassPurchaseFinished could detect real time purchases in game servers, but the player’s gamepasses would still need to be detected when the player loads into the server to account for purchases on the website. So to avoid redundancy, MarketplaceService.PromptGamePassPurchaseFinished is not used and any new gamepasses are detected when players first load into a server and are recorded on the player data profile. These gamepasses are then applied accordingly.

Player Statistics

By using ProfileService, tracking specific player stats is streamlined. The module allows for the tracking of any player-specific statistic that seems interesting, such as deaths to specific monsters, games played, currency collected, etc. Statistic tracking runs through the custom PlayerDataService module, and any corner of the code base that wishes to record data runs through it.

Global Statistics

Global statistics rely solely on Roblox’s DataStoreService rather than running through PlayerService. For leaderboard tracking, ordered data stores are used and are shared throughout all servers. These sort user ids in descending order based on the statistic being tracked. When read from, only the top page in the data store is retrieved. For data stores that don’t need sorting (such as name in the game), only user ids are stored.

There are several globally tracked items:

  • Name in the Game Gamepass Purchases
    • When purchased, the player’s avatar will begin to spawn in hospital beds around the level. This occurs in all games, not just games the specific player is in making it possible for anyone who loads into the game to see the player’s avatar.
  • Lifetime RVU
    • This includes RVU earned by playing matches as well as RVU purchased
  • Lifetime Wins
    • Recorded when a player beats the game
  • Lifetime Games
    • This is recorded every time a player starts a match
A leaderboard showing the top 20 players with the most coins collected.
A picture of the coins leaderboard which is located in the lobby.
Analytics

MODERN MEDICINE’s post launch development relies heavily on use of Roblox’s AnalyticsService to determine player retention and drop off rates through funnels and other analyitics. Throughout the game state logic there are dozens of analytics hooks tracking player progression, monster damage, shop purchases (not with premium currency). Using the data accumulated from thousands of playthroughs on the live servers we are able to pinpoint weak aspects of our game and target them for improvement. Using analytics we were able to improve the tutorial conversion rate to over 87% only a few weeks after launch.

A leaderboard showing the top 20 players with the most coins collected.
Tutorial funnel analytics for September 2024.
Back