Overview
Bolt is a networking package designed to provide strong type safety for networking in Roblox experiences. It originally began as a simple code snippet, which is why it has no external dependencies and fully contained within a single file.
The goal is to simplify networking and get good type checking, decent message size and optional serialization / deserialization. The default serializer is built to handle most of the data developers commonly send, and custom serializers are generally only needed when further reducing message size or optimizing for very specialized cases.
Adding Bolt to a Project
To add the Bolt package to your project, add the following to your wally.toml file:
[dependencies]
SequenceAnimator = "dubit/bolt@^0"
Examples
Example Usage - ReliableEvent
return {
Messages = Bolt.ReliableEvent("Messages") :: Bolt.ReliableEvent<string>,
}
Networking.Messages.OnServerEvent:Connect(function(player, message)
print(`{player.DisplayName} says {message}`) --> Username says Hello world!
end)
Networking.Messages:FireServer("Hello world!")
Example Usage - RemoteFunction
return {
PurchaseItem = Bolt.RemoteFunction("PurchaseItem") :: Bolt.RemoteFunction<(string), (boolean)>,
}
Networking.PurchaseItem.OnServerInvoke = function(player, item)
if typeof(item) ~= "string" then
return false
end
-- some logic
return true
end
local success = Networking.PurchaseItem:InvokeServer("apple")
Example Usage - RemoteProperty
return {
GoldBalance = Bolt.RemoteProperty("GoldBalance", 0) :: Bolt.RemoteProperty<number>,
}
local function playerAdded(player: Player)
Networking.GoldBalance:SetFor(player, 5)
end
Players.PlayerAdded:Connect(playerAdded)
for _, player in Players:GetPlayers() do
task.spawn(playerAdded, player)
end
Networking.GoldBalance:Observe(function(newValue)
print(newValue)
end)
--> 0
--> 5
Example Usage - Custom serialization
Let's say in this example we know that player won't ever have more than 255 bullets in his weapon, we can optimize the message generated by this remote event as the default serializer used internally by Bolt uses 64bit floating point numbers, which are 8 bytes in size, 255 fits within one byte so we can serialize the number into one byte using unsigned 8bit integer and then deserialize it when we receive the given message.
With this simple optimization we've decreased our message size by 87.5%!
return {
PlayerAmmo = Bolt.ReliableEvent("PlayerAmmo", function(bufferWriter: BufferWriter, amount: number)
bufferWriter:WriteU8()
end, function(bufferReader: BufferReader)
return bufferReader:ReadU8()
end) :: Bolt.ReliableEvent<number>,
}
Example Usage - More complex custom serialization
Bolt by default doesn't have a way of serializing ColorSequences, but you can add that functionality using a custom seralization and deserialization!
Bolt.ReliableEvent("Color Sequence Event", function(writer, colorSequence: ColorSequence)
writer:WriteU8(#colorSequence.Keypoints)
for _, keypoint in colorSequence.Keypoints do
writer:WriteU8(math.clamp(keypoint.Time * 255, 0, 255))
writer:WriteColor3(keypoint.Value)
end
end, function(reader)
local keypointsCount = reader:ReadU8()
local keypoints = table.create(keypointsCount)
for i = 1, keypointsCount do
local keypointTime = reader:ReadU8() / 255
local keypointsColor = reader:ReadColor3()
table.insert(keypoints, ColorSequenceKeypoint.new(keypointTime, keypointsColor))
end
return ColorSequence.new(keypoints)
end) :: Bolt.ReliableEvent<ColorSequence>