TrailBridge
Connect your Trailmakers mods to the web.
What is TrailBridge?
TrailBridge is a small, safe app that runs in the background. It acts as a "bridge" to let Trailmakers mods connect to the internet.
It allows for mods like cross server chat or online leaderboards to be possible. It automatically finds your mods and just works.
Note: In multiplayer, only the player who is hosting the server needs to run TrailBridge. Other players joining the server do not need to run it. Always activate the in-game mod first.
What It Enables
TrailBridge enables awesome new features. Check out the compatible mod on the Steam Workshop!
Download TrailBridge
This tiny console app is all you need. Just run it in the background while you play. No config needed.
Download for Windows Download for LinuxGet the Example Mod
Subscribe to our cross server chat mod on the Steam Workshop, or download the files to see how it works and build your own.
Subscribe on Workshop Download Mod .zipFor Modders: How to Use
Want to use TrailBridge in your own mod? Just include the trailbridgelib.lua file in your mod's data_static folder. The TrailBridge app will automatically detect it.
1. Load and Initialize the Library
In your main.lua, load the file and call :init() once at the top.
tm.os.DoFile("trailbridgelib")
TrailBridge:init()
-- Optional Settings
TrailBridge.DEBUG = true
TrailBridge.RECEIVE_OWN_MESSAGES = false -- Good for testing
2. Run the Update Loop
Place this in your mod's update() function. This is required.
function update()
TrailBridge:update()
end
3. Send Data (Broadcast)
Send any Lua table to ALL users on any "channel" name you want.
-- Send a full table (recommended)
local myData = {
playerName = "Steve",
score = 100
}
TrailBridge:send("leaderboard_update", myData)
-- or send just a single value
TrailBridge:send("simple_message", "Hello World!")
4. Receive Data (Broadcast)
Register a "callback" function to handle incoming data for a specific channel.
function OnMyData(data)
-- 'data' is the table we just received
if data.value then
-- It was a single value, access it with .value
TrailBridge:log("Received simple message: " .. data.value)
else
-- It was a full table, access by its keys
TrailBridge:log(data.sender .. " got score: " .. data.score)
end
end
TrailBridge:on("leaderboard_update", OnMyData)
TrailBridge:on("simple_message", OnMyData)
5. How to Handle Chat
The handleChatMessage function is special. It both sends the chat message AND checks for message "loops" (when your own message comes back from the server).
This loop check is only necessary if you use chat commands (like "!hello") AND you have RECEIVE_OWN_MESSAGES = true enabled for testing.
-- In your OnChatMessage function
function OnChatMessage(sender, msg, color)
-- This function does two things:
-- 1. It saves your 'sender' name for the chat function.
-- 2. It returns 'true' if the message is a loop.
local isLoop = TrailBridge:handleChatMessage(sender, msg)
-- If RECEIVE_OWN_MESSAGES = true, this check is required
-- to prevent commands from running twice.
if isLoop then
return
end
-- Now you can safely check for local chat commands
if msg == "!hello" then
TrailBridge:log("Hello command received!")
end
end
-- In your "chat" callback
function OnReceiveChat(data)
local chatColor = tm.color.Create(0.5, 1.0, 0.5, 1.0)
local taggedSender = TrailBridge:getTaggedSender(data.sender)
tm.playerUI.SendChatMessage(taggedSender, data.message, chatColor)
end
TrailBridge:on("chat", OnReceiveChat)
tm.playerUI.OnChatMessage.add(OnChatMessage)
6. How to Use the Database
The database is a simple public key-value store. Anyone with your API_KEY can read or write to any key. It can be used at any time.
RATE LIMIT: The server has a rate limit of 1 request per second (per API key). Do not send many requests at once. I'm also providing this service as-is and free-of-charge, I cannot guarantee data will be kept and I cannot guarantee security of data, do not use this to store critical data.
local MY_MOD_API_KEY = "a-unique-string-id"
-- === SET DATA ===
-- This function is called when the server responds
function OnSetResponse(response)
if response and response.status == "success" then
TrailBridge:log("Successfully saved key: " .. response.key)
else
TrailBridge:log("Failed to save data.")
end
end
-- Call this to save your data
local mySave = { level = 10, name = "MySave" }
TrailBridge:setData(MY_MOD_API_KEY, "save_slot_1", mySave, OnSetResponse)
-- === GET DATA ===
-- This function is called when the server responds
function OnGetResponse(response)
if response and response.status == "success" and response.value then
-- response.value is the table we saved: { level = 10, name = "MySave" }
TrailBridge:log("Got data: " .. json.serialize(response.value))
elseif response and response.status == "not_found" then
TrailBridge:log("Key not found.")
else
TrailBridge:log("Could not get data.")
end
end
-- Call this to get your data
-- (Make sure to wait atleast a second after setting (to allow for the server to update)
TrailBridge:getData(MY_MOD_API_KEY, "save_slot_1", OnGetResponse)