Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Elitriare/ByteNet-Max/llms.txt

Use this file to discover all available pages before exploring further.

Queries are ByteNet Max’s answer to RemoteFunction. Where packets are fire-and-forget, a query lets a client send a typed request to the server and yield until the server returns a typed response. Both the request and the response are serialized into binary buffers before they cross the network, keeping the payload as compact as possible. This makes queries the right choice whenever you need data back from the server — fetching a player’s stats, requesting inventory contents, or any other read operation.

Defining a query

Queries are defined inside a namespace using ByteNetMax.defineQuery. You must provide both a request type and a response type.
local ByteNetMax = require(path.to.ByteNetMax)

return ByteNetMax.defineNamespace("PlayerData", function()
    return {
        queries = {
            GetCoins = ByteNetMax.defineQuery({
                request = ByteNetMax.struct({
                    message = ByteNetMax.string,
                }),
                response = ByteNetMax.struct({
                    coins = ByteNetMax.uint8,
                }),
            }),
        },
    }
end)
Both request and response are required fields. ByteNet Max uses them to build separate serializers for each direction of the call.

Query API

Client-side method

MethodSignatureDescription
invokeinvoke(request) -> responseSend the request to the server and yield until the response arrives. Returns the deserialized response.

Server-side methods

MethodSignatureDescription
listenlisten(callback) -> disconnectRegister a handler. The callback receives the request data and the player, and must return the response. Returns a function that disconnects the listener when called.
listenOncelistenOnce(callback) -> disconnectRegister a handler that runs exactly once, then disconnects automatically.
disconnectAlldisconnectAll()Remove every handler registered through listen or listenOnce.
waitwait() -> data, playerYield the current thread until the next query arrives, then return the request data and the player.
invoke is client-only. Calling it from a server Script will error. If you need the server to push data to clients, use a packet with sendTo or sendToAll instead.

The disconnect pattern

listen and listenOnce both return a disconnect function. Assign the return value to a variable and call it when you want to remove that specific listener:
local QueryModule = require(game.ReplicatedStorage.QueryModule)

local disconnect = QueryModule.queries.GetCoins.listen(function(data, player)
    print(data.message)
    return { coins = player.leaderstats.Coins.Value }
end)

-- Later, when you want to stop handling this query:
disconnect()
To clear every handler at once:
QueryModule.queries.GetCoins.disconnectAll()

Complete end-to-end example

Query ModuleScript (ReplicatedStorage/QueryModule):
local ByteNetMax = require(path.to.ByteNetMax)

return ByteNetMax.defineNamespace("PlayerData", function()
    return {
        queries = {
            GetCoins = ByteNetMax.defineQuery({
                request = ByteNetMax.struct({
                    message = ByteNetMax.string,
                }),
                response = ByteNetMax.struct({
                    coins = ByteNetMax.uint8,
                }),
            }),
        },
    }
end)
Server Script — register a handler that returns data:
local QueryModule = require(game.ReplicatedStorage.QueryModule)

QueryModule.queries.GetCoins.listen(function(data, player)
    print(data.message) -- "Can I please get the coins value?"
    return { coins = player.leaderstats.Coins.Value }
end)
LocalScript — invoke the query and use the response:
local QueryModule = require(game.ReplicatedStorage.QueryModule)

local result = QueryModule.queries.GetCoins.invoke({
    message = "Can I please get the coins value?",
})

print(result.coins) -- the value returned by the server
invoke yields the LocalScript until the server handler returns, so result is always the fully deserialized response — no callbacks or events needed on the client side.

Build docs developers (and LLMs) love