The brainCloud client for Lua games: authentication, cloud data, leaderboards, lobbies, chat, real-time events (RTT) and relay multiplayer.
- LÖVE 11.4+ and LÖVE 12 (LuaJIT). Desktop: macOS, Windows, Linux.
- Plain LuaJIT / Lua 5.1 with LuaSocket + LuaSec (servers, tools, other engines).
- Nothing blocks: requests run in the background and callbacks fire from
update().
- Download
braincloud-lua-<version>.zipfrom the Releases page. - Copy the
braincloud/folder into your game, next tomain.lua.
That's it: the folder includes the native networking pack for each desktop platform
(braincloud/native/), which LÖVE 11 needs for HTTPS and every LÖVE version needs for
real-time features.
Run the setup tool from your game folder. It signs you in to brainCloud in the browser, lets
you pick or create an app, and writes braincloud_config.lua:
love path/to/braincloud-lua/tools/braincloud-setup.love .braincloud_config.lua is added to your .gitignore. Rerun the tool to switch apps, or
luajit tools/setup/cli.lua --refresh in CI (with BRAINCLOUD_APP_ID,
BRAINCLOUD_BUILDER_EMAIL, BRAINCLOUD_BUILDER_API_KEY, BRAINCLOUD_TEAM_ID).
local BrainCloud = require("braincloud")
local bc = BrainCloud.new()
function love.load()
bc:init() -- reads braincloud_config.lua
bc:authenticateAnonymous(function(ok, response)
if ok then
print("profile", response.data.profileId)
bc.leaderboard:postScoreToLeaderboard("highscores", 1200, {}, function(ok2, r)
print("posted", ok2)
end)
else
print("login failed", response.status_message)
end
end)
end
function love.update()
bc:update() -- required: pumps networking and fires callbacks
endEvery call ends with a callback function(success, response); response is the server's
{ status, data } (or { status, reason_code, status_message } on failure). Calls made in
the same frame are bundled into one request.
Without the setup tool you can initialize directly:
bc:initialize(appId, appSecret, appVersion, serverUrl).
The wrapper remembers the profile and anonymous ids (in LÖVE's save directory), so
authenticateAnonymous returns the same player next launch. bc:logout(true) forgets them.
smartSwitchAuthenticate* moves an anonymous player to a real login.
bc.rttService:enableRTT(function()
bc.rttService:registerRTTChatCallback(function(msg) print(msg.operation, msg.data) end)
end, function(err) print("RTT lost", err) end)Lobby, chat, presence, messaging and event callbacks: registerRTTLobbyCallback,
registerRTTChatCallback, registerRTTPresenceCallback, and so on.
Join a lobby, wait for ROOM_READY on the lobby callback, then connect:
bc.relay:registerRelayCallback(function(netId, data) end)
bc.relay:connect(bc.relay.ConnectionType.UDP, {
host = room.connectData.address,
port = room.connectData.ports.udp,
passcode = room.passcode,
lobbyId = room.lobbyId,
}, onConnected, onFailed)
bc.relay:sendToAll("hello", true, false, bc.relay.CHANNEL_HIGH_PRIORITY_1)WebSocket (ws, with ssl = true for wss), TCP and UDP are supported, with reliable and
ordered channels. See the CursorParty example in
lua-examples for a full lobby → relay game.
| REST | RTT / secure WebSocket | Relay TCP / UDP / ws | |
|---|---|---|---|
| LÖVE 12 | built in (love.https) |
native pack | built in (LuaSocket) |
| LÖVE 11.4 / 11.5 | native pack | native pack | built in (LuaSocket) |
| Web (love.js) | browser fetch via the web bridge |
browser WebSocket via the web bridge | wss only |
| iOS (LÖVE 11.5) | LuaSec, built in by platforms/ios |
LuaSec, built in by platforms/ios |
built in (LuaSocket) |
| Android (LÖVE 11.5) | native pack | native pack | built in (LuaSocket) |
| Plain LuaJIT | LuaSec | LuaSec | LuaSocket |
- The native pack ships for macOS (universal), Windows x64, Linux x64 and Android arm64. iOS uses its own LÖVE build (see iOS below).
- Web builds (love.js, compatibility mode): the
SDK detects
love.system.getOS() == "Web"and routes HTTP and WebSockets through the page. Includebraincloud/web/braincloud-web.jsin the love.jsindex.htmlbeforegame.js, and callbraincloudWeb.attach(Module)just beforeLove(Module). Leavebraincloud/native/out of the web.love. Relay connects withssl = trueto the room'ssecureAddress/ports.wss. - Inside a packaged
.loveor fused executable, LÖVE can't load native libraries directly, so the SDK copies them to the save directory on first run.
iOS apps can't load the native pack, so platforms/ios/build.sh builds LÖVE 11.5 for iOS with
LuaSec + OpenSSL compiled in, adds your game and signs it. You need a Mac with Xcode, signed in
to your Apple Developer team (Xcode > Settings > Accounts).
# build and run on a connected iPhone/iPad
braincloud-lua/platforms/ios/build.sh path/to/game --team <TEAM_ID> --bundle-id com.you.game \
--name "My Game" --icon path/to/icon.png --launch
# iOS Simulator (no signing)
braincloud-lua/platforms/ios/build.sh path/to/game --bundle-id com.you.game --simulator --launch
# App Store: .xcarchive + .ipa to upload with Transporter
braincloud-lua/platforms/ios/build.sh path/to/game --team <TEAM_ID> --bundle-id com.you.game \
--version 1.0.0 --build 1 --archiveOutput goes to ./build/ios (--out to change it). The first build downloads the LÖVE iOS
source and takes a few minutes; later builds are incremental. Your game should handle a phone-
sized screen and touch (LÖVE delivers taps as mouse presses); see the CursorParty example.
The native pack includes android-arm64, so the SDK works in any LÖVE 11.5 Android build of your
game. platforms/android/build.sh makes an APK by repackaging the official LÖVE APK with your game,
package name, label and icon. You need Java 17+ and the Android SDK build-tools (Android Studio
installs both).
# build, install and launch on a connected device or running emulator
braincloud-lua/platforms/android/build.sh path/to/game --package com.you.game \
--name "My Game" --icon path/to/icon.png --launch
# signed release APK
BC_KEYSTORE_PASS=... braincloud-lua/platforms/android/build.sh path/to/game --package com.you.game \
--version 1.0.0 --version-code 1 --keystore release.jks --key-alias mygameWithout --keystore the APK is signed with your Android debug key. For Google Play (.aab), build
LÖVE's love-android project with your game.love; the
SDK needs nothing extra there. Set t.window.resizable = false in conf.lua on phones, or the game
follows the device's rotation.
BC_TEST_IDS=path/to/test_ids.txt luajit tests/run.lua [Leaderboard,Relay] [-t testName]
tests/love/run.sh path/to/test_ids.txt # the same flows inside LÖVEApache 2.0 — see LICENSE. Bundled third-party code is listed in THIRD_PARTY_NOTICES.md.