Forest Logo
search
package_2

place-handoff

By @zenukopublic

Roblox

Mirrored from Wally

place-handoff

Production-grade distributed cross-place session and party teleport handoff using MemoryStore with transactional rollback.

License: MIT Language: Luau Wally: Available


Production Origin: This package was extracted and generalized from infrastructure developed for Kabbrawl, a private competitive multiplayer Roblox experience. Kabbrawl itself remains proprietary; this package contains only reusable infrastructure and no proprietary assets or game-specific content.


🚀 The Multi-Place Problem on Roblox

In competitive Roblox games, separating your Lobby place from dedicated Match arena places (using reserved servers) is essential for server performance and clean memory. However, developers face three notorious production problems:

  1. "Session Locked" DataStore Crashes: ProfileStore locks player profiles in the lobby. If a player teleports to a match server before the lobby confirms the profile save, the match server fails to acquire the profile lock and kicks the player.
  2. TeleportData Spoofing: Exploiters can easily manipulate client-side TeleportData to fake their MMR, inventory, or tournament bracket slot.
  3. Partial Party Teleport Failures: If one player in a 4-player party fails to allocate handoff data, partial matches start with missing teammates.

place-handoff provides an enterprise-grade, distributed handoff protocol backed by MemoryStoreService HashMaps with automatic TTL expiration, single-use token consumption, and transactional rollback.


✨ Features

  • Single-Use Cryptographic GUIDs: Generates secure handoff tokens with automatic 60-second TTL.
  • Instant Replay-Attack Prevention: Destination servers immediately delete the token from MemoryStore upon arrival (RemoveAsync).
  • Transactional Rollback: When teleporting parties, if any member fails to write to MemoryStore, all previously allocated party tokens are deleted instantly.
  • Zero Session Lock Race Conditions: Seamlessly pairs with profile saving (PlayerProfile.waitForConfirmedSave) before teleport.
  • Mockable Adapter: Easily test cross-server handoffs headlessly with Lune or in Studio.

🚀 Installation

Via Wally

Add place-handoff to your wally.toml:

[dependencies]
PlaceHandoff = "zenukopublic/place-handoff@1.0.0"

📖 Quickstart

1. Lobby Server (Before Teleport)

local PlaceHandoff = require(Packages.PlaceHandoff)
local handoff = PlaceHandoff.new()

-- Teleporting a single player or party
local partyResult = handoff:createPartyHandoff({ player1.UserId, player2.UserId }, function(userId)
    return {
        matchMode = "Ranked",
        mmr = 1750,
        teamSlot = "Alpha",
    }
end)

if partyResult.success then
    -- Pack GUID into TeleportOptions and teleport
    local teleportOptions = Instance.new("TeleportOptions")
    teleportOptions:SetTeleportData({
        handoffGuid = partyResult.guids[player1.UserId],
    })
    TeleportService:TeleportAsync(MATCH_PLACE_ID, { player1 }, teleportOptions)
else
    warn("Failed to create match handoff:", partyResult.error)
end

2. Match Server (Upon Player Arrival)

local PlaceHandoff = require(Packages.PlaceHandoff)
local handoff = PlaceHandoff.new()

Players.PlayerAdded:Connect(function(player)
    local joinData = player:GetJoinData()
    local teleportData = joinData.TeleportData
    local guid = if teleportData then teleportData.handoffGuid else nil

    -- Validate identity and consume single-use token
    local ok, payload, err = handoff:consumeHandoff(player.UserId, guid)
    if not ok then
        player:Kick(`Match admission denied: {err}`)
        return
    end

    print(`Admitted {player.Name} to match with MMR {payload.mmr}!`)
end)

🧪 Testing

Run standalone unit tests headlessly with Lune:

lune run tests/handoff.test.luau

📄 License

MIT License. Free for personal and commercial use.

Package Details

Install command (Click to copy)


Version

1.0.0

License

MIT

check_circle

Safe for commercial use

Automated license review — not legal advice.