### Install Wally Packages Source: https://github.com/elitriare/bytenet-max/blob/main/docs/getting-started/installation.md Run the install command in your terminal to download the defined dependencies. ```shell wally install ``` -------------------------------- ### Install ByteNet Max with Wally Source: https://github.com/elitriare/bytenet-max/blob/main/README.md Add the package dependency to your wally.toml file. ```toml [dependencies] ByteNetMax = "elitriare/bytenet-max@0.2.7" ``` -------------------------------- ### Using Queries for Request/Response Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/bytenet-module.md Example of defining a query and handling the request/response cycle between server and client. ```lua local GameNamespace = ByteNet.defineNamespace("Game", function() return { packets = {}, queries = { GetPlayerCoins = ByteNet.defineQuery({ request = ByteNet.uint32, -- playerId response = ByteNet.uint32, -- coin count }), }, } end) -- On server, listen for requests GameNamespace.queries.GetPlayerCoins:listen(function(playerId) local coins = 100 -- fetch from database return coins end) -- On client, invoke the query local coins = GameNamespace.queries.GetPlayerCoins:invoke(game.Players.LocalPlayer.UserId) print("I have " .. coins .. " coins") ``` -------------------------------- ### Importing ByteNet Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/bytenet-module.md Standard setup for requiring the ByteNet module from ReplicatedStorage. ```lua local ReplicatedStorage = game:GetService("ReplicatedStorage") local ByteNet = require(ReplicatedStorage.Packages.ByteNetMax) ``` -------------------------------- ### Initialize ByteNet Startup Sequence Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/module-map.md Initializes replication and starts the appropriate message loop based on the execution environment. ```lua local values = require(script.replicated.values) values.start() -- Initialize replication if RunService:IsServer() then serverProcess.start() -- Start server message loop else clientProcess.start() -- Start client message loop end ``` -------------------------------- ### Example namespace definition Source: https://github.com/elitriare/bytenet-max/blob/main/docs/api/namespace.md A practical example of defining a 'Chat' namespace with a SendMessage packet. ```lua local Network = ByteNetMax.defineNamespace("Chat", function() return { packets = { SendMessage = ByteNetMax.definePacket({ value = ByteNetMax.string, }), }, queries = {}, } end) ``` -------------------------------- ### Namespace Data Example Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/namespace.md A concrete example of the namespace data structure containing packet, query, and struct mappings. ```lua { packets = { PlayerSpawned = 1, PlayerDied = 2, }, queries = { GetPlayerStats = 1, }, structs = { [1] = { position = 1, velocity = 2, health = 3 }, -- struct in packet 1 }, } ``` -------------------------------- ### Define and initialize shared networking modules Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/configuration.md Example of defining a namespace in a shared module and initializing listeners or waiters on the server and client. ```lua -- shared/Networking.lua (shared ModuleScript) local ReplicatedStorage = game:GetService("ReplicatedStorage") local ByteNet = require(ReplicatedStorage.Packages.ByteNetMax) return ByteNet.defineNamespace("Game", function() return { packets = { ... }, queries = { ... }, } end) -- server/init.server.lua local Networking = require(ReplicatedStorage.SharedModules.Networking) Networking.packets.SomePacket:listen(function(data) end) -- client/init.client.lua local Networking = require(ReplicatedStorage.SharedModules.Networking) Networking.packets.SomePacket:wait() ``` -------------------------------- ### Using Packets for Networking Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/bytenet-module.md Example of defining a packet within a namespace and performing send/listen operations. ```lua local GameNamespace = ByteNet.defineNamespace("Game", function() return { packets = { PlayerJoined = ByteNet.definePacket({ value = ByteNet.struct({ playerName = ByteNet.string, playerId = ByteNet.uint32, }), }), }, queries = {}, } end) -- On server GameNamespace.packets.PlayerJoined:sendToAll({ playerName = "Alice", playerId = 1, }) -- On client GameNamespace.packets.PlayerJoined:listen(function(data) print(data.playerName .. " joined!") end) -- Wait for next packet local data = GameNamespace.packets.PlayerJoined:wait() ``` -------------------------------- ### Handle Query Timeouts Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/errors.md Example of checking for nil results when a query times out due to player disconnection. ```lua local result = queryWithTimeout(Query, request, 10) if result == nil then print("Query failed or timed out") return defaultValue() end ``` -------------------------------- ### Define a struct schema Source: https://github.com/elitriare/bytenet-max/blob/main/docs/guides/choosing-data-types.md Example of a structured schema definition using various ByteNetMax types. ```lua ByteNetMax.struct({ UserId = ByteNetMax.uint32, DisplayName = ByteNetMax.string, Position = ByteNetMax.vec3, Health = ByteNetMax.uint16, IsAlive = ByteNetMax.bool, Title = ByteNetMax.optional(ByteNetMax.string), }) ``` -------------------------------- ### Initialize ByteNet Max startup Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/configuration.md Automatic startup logic triggered upon requiring the module, handling server and client process initialization. ```lua -- src/init.luau:34-40 values.start() -- Start replicating namespace data if RunService:IsServer() then serverProcess.start() -- Start server message handling else clientProcess.start() -- Start client message handling end ``` -------------------------------- ### Use vec3 in a struct Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/data-types.md Example of defining a structure containing multiple vec3 fields. ```lua ByteNet.struct({ position = ByteNet.vec3, velocity = ByteNet.vec3, lookDirection = ByteNet.vec3, }) ``` -------------------------------- ### Initialize Server Network Source: https://github.com/elitriare/bytenet-max/blob/main/docs/getting-started/initialization.md Require the shared network module on the server to listen for packets during startup. ```lua local ReplicatedStorage = game:GetService("ReplicatedStorage") local Network = require(ReplicatedStorage.Network) Network.packets.Ready.listen(function(IsReady, Player) print(Player.Name, IsReady) end) ``` -------------------------------- ### Use cframe in a packet definition Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/data-types.md Example of including a cframe field within a packet structure. ```lua ByteNet.definePacket({ value = ByteNet.struct({ character_transform = ByteNet.cframe, }), }) ``` -------------------------------- ### View Project File Structure Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/README.md Displays the directory layout of the ByteNet-Max documentation repository. ```text output/ ├── README.md (this file) ├── quick-reference.md ├── types.md ├── configuration.md ├── errors.md ├── internals.md ├── module-map.md └── api-reference/ ├── bytenet-module.md ├── data-types.md └── namespace.md ``` -------------------------------- ### Initialize ByteNet System Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/module-map.md The values system must be initialized before the process system to ensure replication infrastructure is ready. ```lua -- Order in init.luau local values = require(script.replicated.values) values.start() -- Must be FIRST if RunService:IsServer() then serverProcess.start() -- Can be second else clientProcess.start() -- Can be second end ``` -------------------------------- ### Safe Namespace Initialization Pattern Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/namespace.md Demonstrates the required initialization order for server and client modules to ensure namespaces are ready before network communication. ```lua -- server/init.server.lua local ReplicatedStorage = game:GetService("ReplicatedStorage") local ByteNet = require(ReplicatedStorage.Packages.ByteNetMax) local Networking = require(ReplicatedStorage.SharedModules.Networking) -- All namespaces now ready task.wait(0.1) -- Let clients connect Networking.Game.packets.PlayerJoined:sendToAll({...}) -- client/init.client.lua local ReplicatedStorage = game:GetService("ReplicatedStorage") local ByteNet = require(ReplicatedStorage.Packages.ByteNetMax) local Networking = require(ReplicatedStorage.SharedModules.Networking) -- Safe to use Networking.Game.packets.PlayerJoined:listen(function(data) print("Player joined: " .. data.userId) end) ``` -------------------------------- ### Standard Project Layout Source: https://github.com/elitriare/bytenet-max/blob/main/docs/getting-started/installation.md Recommended organization for shared definitions and runtime scripts across server and client. ```text ReplicatedStorage ├── ByteNetMax └── Network.luau # Shared definitions ServerScriptService └── Network.server.luau # Server listeners and sends StarterPlayer └── StarterPlayerScripts └── Network.client.luau # Client listeners and sends ``` -------------------------------- ### Use BufferWriter Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/internals.md Typical workflow for loading a channel, writing data, and exporting the result. ```lua bufferWriter.load(channel) bufferWriter.u8(packetId) bufferWriter.u16(value) channel = bufferWriter.export() ``` -------------------------------- ### ByteNet.inst() Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/data-types.md Represents a Roblox Instance reference. ```APIDOC ## ByteNet.inst() ### Description Serializes a reference to a Roblox Instance. It transmits a uint16 index into a reference table. The instance must be reachable on both client and server. ### Usage ```lua ByteNet.inst() ``` ``` -------------------------------- ### Define a Namespace Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/module-map.md Initializes a namespace by assigning IDs and replicating data between server and client. ```lua return function(name: string, input: () -> namespaceData) -- Server: assign IDs, replicate -- Client: read IDs from server return { packets = { [string] = packet }, queries = { [string] = query }, } end ``` -------------------------------- ### Implement nothing type in packets and queries Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/data-types.md Demonstrates usage of ByteNet.nothing for signaling events and empty request structures. ```lua -- Event that just signals, no data local readyPacket = ByteNet.definePacket({ value = ByteNet.nothing, }) -- Query with no request local getTimeQuery = ByteNet.defineQuery({ request = ByteNet.nothing, response = ByteNet.uint32, }) ``` -------------------------------- ### Define queries Source: https://github.com/elitriare/bytenet-max/blob/main/docs/reference/migration.md Replace manual request/response remotes with the ByteNet Max query system. ```lua GetValue = ByteNetMax.defineQuery({ request = ByteNetMax.string, response = ByteNetMax.uint32, }) ``` -------------------------------- ### Implement request-response pattern Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/README.md Defines a query with request and response types, sets up a server-side listener, and invokes the query. ```lua local query = ByteNet.defineQuery({ request = ByteNet.uint32, -- user ID response = ByteNet.string, -- username }) query:listen(function(userId) return database:getUsername(userId) end) local username = query:invoke(123) ``` -------------------------------- ### Handle Query on Server Source: https://github.com/elitriare/bytenet-max/blob/main/docs/guides/queries.md Register a listener on the server to process incoming requests and return the expected response type. ```lua Network.queries.GetLoadout.listen(function(_, Player) return LoadoutService:GetItemIds(Player) end) ``` -------------------------------- ### Define a namespace Source: https://github.com/elitriare/bytenet-max/blob/main/docs/api/namespace.md Basic syntax for defining a namespace using ByteNetMax. ```lua ByteNetMax.defineNamespace(Name, DefinitionCallback) ``` -------------------------------- ### Initialize Client Network Source: https://github.com/elitriare/bytenet-max/blob/main/docs/getting-started/initialization.md Require the shared network module on the client to send packets using the server-defined schema. ```lua local ReplicatedStorage = game:GetService("ReplicatedStorage") local Network = require(ReplicatedStorage.Network) Network.packets.Ready.send(true) ``` -------------------------------- ### namespace Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/module-map.md Initializes a namespace for organizing packets and queries. ```APIDOC ## namespace(name, input) ### Description Defines a namespace, assigning IDs to packets and queries to ensure synchronization between server and client. ### Signature `namespace(name: string, input: () -> namespaceData) -> { packets: { [string]: packet }, queries: { [string]: query } }` ### Parameters - **name** (string) - Required - The unique name of the namespace. - **input** (function) - Required - A function that returns the packet and query definitions for the namespace. ``` -------------------------------- ### Handle Optional Fields Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/quick-reference.md Define fields that may be nil using ByteNet.optional. ```lua local packet = ByteNet.definePacket({ value = ByteNet.struct({ name = ByteNet.string, nickname = ByteNet.optional(ByteNet.string), }), }) -- Server packet:sendToAll({name = "Alice", nickname = nil}) packet:sendToAll({name = "Bob", nickname = "Bobby"}) -- Client packet:listen(function(data) if data.nickname then print(data.nickname .. " (" .. data.name .. ")") else print(data.name) end end) ``` -------------------------------- ### Create channelData Instance Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/internals.md Initializes a new channelData table with a default buffer size of 256 bytes. ```lua local function create() return { cursor = 0, size = 256, references = {}, buff = buffer.create(256), } end ``` -------------------------------- ### Handle Namespace Readiness Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/quick-reference.md Sending packets before the namespace is fully replicated can cause failures. Ensure the namespace is ready before transmission. ```lua local packet = ... -- Defined packet:sendToAll(data) -- Might fail if namespace not replicated yet -- Better: task.wait(0.1) packet:sendToAll(data) ``` -------------------------------- ### Implement client-side networking Source: https://github.com/elitriare/bytenet-max/blob/main/docs/index.md Listen for incoming packets and invoke server queries from the client. ```lua local ReplicatedStorage = game:GetService("ReplicatedStorage") local Network = require(ReplicatedStorage.Network) Network.packets.ShowToast.listen(function(Data) print(Data.Message) end) local Coins = Network.queries.GetCoins.invoke(nil) print(`You have {Coins} coins`) ``` -------------------------------- ### Creator Store Module Placement Source: https://github.com/elitriare/bytenet-max/blob/main/docs/getting-started/installation.md Recommended file structure when using the Roblox Creator Store version. ```text ReplicatedStorage ├── ByteNetMax └── Network ``` -------------------------------- ### Define a Namespace with Packets and Queries Source: https://github.com/elitriare/bytenet-max/blob/main/docs/api/index.md Use defineNamespace to group and initialize packets and queries within a specific scope. ```lua return ByteNetMax.defineNamespace("Game", function() return { packets = { StatusChanged = ByteNetMax.definePacket({ value = ByteNetMax.string, }), }, queries = { GetStatus = ByteNetMax.defineQuery({ request = ByteNetMax.nothing, response = ByteNetMax.string, }), }, } end) ``` -------------------------------- ### Optimize Query Handlers Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/errors.md Shows how to replace slow, iterative lookup logic with direct database lookups to prevent query timeouts. ```lua -- ❌ Slow handler - database query without optimization Query:listen(function(userId) local allRecords = database:getAllRecords() for _, record in allRecords do if record.userId == userId then return record end end end) -- ✅ Fast handler - direct lookup Query:listen(function(userId) return database:getRecordById(userId) end) ``` -------------------------------- ### Implement Server-Side Rate Limiting Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/configuration.md Reference implementation for the token bucket rate limiting logic used to restrict bytes per second per player. ```lua local rateLimit = { bytesPerSec = MAX_BUFFER_SIZE, refillRate = MAX_BUFFER_SIZE, } local function checkPlayerAllowedToSend(player: Player, size: number) { local now = os.clock() local elapsed = now - playerRateLimits[player].lastTime playerRateLimits[player].currentBytes = math.min( playerRateLimits[player].currentBytes + (elapsed * rateLimit.refillRate), rateLimit.bytesPerSec ) -- ... check if allowed and deduct } ``` -------------------------------- ### Organize Namespace by Feature Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/namespace.md Group related packets and queries within a single namespace definition to maintain logical structure. ```lua local UINamespace = ByteNet.defineNamespace("UI", function() return { packets = { InventoryOpened = ByteNet.definePacket({...}), InventoryClosed = ByteNet.definePacket({...}), ItemSelected = ByteNet.definePacket({...}), }, queries = { GetInventoryContents = ByteNet.defineQuery({...}), }, } end) ``` -------------------------------- ### Implement Server Listener Source: https://github.com/elitriare/bytenet-max/blob/main/docs/getting-started/first-query.md Listen for incoming queries on the server and return a value matching the defined response type. ```lua local ReplicatedStorage = game:GetService("ReplicatedStorage") local Network = require(ReplicatedStorage.Network) Network.queries.GetItemCount.listen(function(Request, Player) -- Replace this with a lookup in server-owned player data. local Inventory = GetInventoryFor(Player) return Inventory[Request.ItemId] or 0 end) ``` -------------------------------- ### Listen for Single Packets Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/quick-reference.md Use listenOnce or wait to handle a single incoming packet. ```lua local packet = ByteNet.definePacket({ value = ByteNet.string, }) -- One-time listener packet:listenOnce(function(data) print("Received: " .. data) end) -- Or wait local data = packet:wait() print("Received: " .. data) ``` -------------------------------- ### Manage Exception Safety in Callbacks Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/errors.md Demonstrates how to handle exceptions in packet listeners, noting that errors propagate by default. ```lua -- ❌ Exception in callback propagates packet:listen(function(data) error("Something went wrong") -- Unhandled exception! end) -- ✅ Wrap in pcall if needed packet:listen(function(data) local ok, err = pcall(function() doSomething(data) end) if not ok then warn("Error handling packet: " .. err) end end) ``` -------------------------------- ### defineNamespace Source: https://github.com/elitriare/bytenet-max/blob/main/docs/api/index.md Initializes a namespace to group packets and queries. ```APIDOC ## defineNamespace(name, definitionFunction) ### Description Groups and initializes packets and queries within a named scope. ### Signature `ByteNetMax.defineNamespace(name: string, definitionFunction: function)` ``` -------------------------------- ### Write a color3 value Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/data-types.md Demonstrates writing a Color3 object to the buffer. ```lua local color = Color3.fromRGB(255, 0, 0) -- Red ByteNet.color3():write(color) -- 3 bytes: [255, 0, 0] ``` -------------------------------- ### ByteNet.int32() Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/data-types.md Constructor for a signed 32-bit integer (-2,147,483,648 to 2,147,483,647). ```APIDOC ## ByteNet.int32() ### Description Creates a signed 32-bit integer data type constructor. This type occupies 4 bytes and supports values from -2,147,483,648 to 2,147,483,647. ### Usage ```lua local int32Type = ByteNet.int32() ``` ``` -------------------------------- ### Manage Namespace Versioning Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/namespace.md Avoid inserting new packets or queries in the middle of existing definitions to prevent ID shifts that break compatibility. ```lua -- v1.0 packets = { Spawn = ..., -- ID 1 Died = ..., -- ID 2 } -- v1.1 - Insert "Moved" in middle packets = { Spawn = ..., -- ID 1 (same) Moved = ..., -- ID 2 (NEW) - Clients won't understand old packets Died = ..., -- ID 3 (CHANGED) } ``` -------------------------------- ### Correct argument order for sendTo Source: https://github.com/elitriare/bytenet-max/blob/main/docs/reference/common-mistakes.md The data payload must be provided as the first argument, followed by the target player. ```lua Packet.sendTo(Data, Player) ``` -------------------------------- ### Define Multiple Namespaces Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/namespace.md Create independent namespaces for different game systems to separate ID spaces and improve maintainability. ```lua -- Shared local GameEvents = ByteNet.defineNamespace("Game", function() return { packets = { ChatMessage = ByteNet.definePacket({...}), PlayerJoined = ByteNet.definePacket({...}), }, queries = {}, } end) local CombatEvents = ByteNet.defineNamespace("Combat", function() return { packets = { PlayerDamaged = ByteNet.definePacket({...}), AttackPerformed = ByteNet.definePacket({...}), }, queries = { CalculateDamage = ByteNet.defineQuery({...}), }, } end) local UIEvents = ByteNet.defineNamespace("UI", function() return { packets = { InventoryChanged = ByteNet.definePacket({...}), }, queries = { GetInventory = ByteNet.defineQuery({...}), }, } end) return { Game = GameEvents, Combat = CombatEvents, UI = UIEvents, } ``` -------------------------------- ### Implement server-side networking Source: https://github.com/elitriare/bytenet-max/blob/main/docs/index.md Listen for queries and send packets from the server using the shared network definition. ```lua local ReplicatedStorage = game:GetService("ReplicatedStorage") local Network = require(ReplicatedStorage.Network) Network.queries.GetCoins.listen(function(_, Player) return Player:GetAttribute("Coins") or 0 end) Network.packets.ShowToast.sendTo({ Message = "Welcome!" }, game.Players:GetPlayers()[1]) ``` -------------------------------- ### Request-Response Query Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/quick-reference.md Perform synchronous-like communication where the client requests data and the server responds. ```lua local query = ByteNet.defineQuery({ request = ByteNet.uint32, response = ByteNet.string, }) -- Server query:listen(function(userId) return "Player" .. tostring(userId) end) -- Client local response = query:invoke(123) print(response) -- "Player123" ``` -------------------------------- ### Send Simple Events Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/quick-reference.md Define and transmit basic string data between server and client. ```lua local packet = ByteNet.definePacket({ value = ByteNet.string, }) -- Server packet:sendToAll("Event happened!") -- Client packet:listen(function(data) print(data) end) ``` -------------------------------- ### Define an optional field Source: https://github.com/elitriare/bytenet-max/blob/main/docs/api/data-types.md Create a schema that includes a 1-byte presence marker before the value. ```lua local Subtitle = ByteNetMax.optional(ByteNetMax.string) ``` -------------------------------- ### ByteNet.uint32() Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/data-types.md Constructor for an unsigned 32-bit integer (0 to 4,294,967,295). ```APIDOC ## ByteNet.uint32() ### Description Creates an unsigned 32-bit integer data type constructor. This type occupies 4 bytes and supports values from 0 to 4,294,967,295. ### Usage ```lua local uint32Type = ByteNet.uint32() ``` ``` -------------------------------- ### Query Listener Execution Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/internals.md Executes a query listener and prepares the result for serialization and return. ```lua local result = runQueryListener(listener, query, decodedData, player) -- Serialize result and send back ``` -------------------------------- ### Validate client purchase requests in Lua Source: https://github.com/elitriare/bytenet-max/blob/main/docs/guides/security.md Verify item existence and player affordability before processing a purchase request to prevent unauthorized transactions. ```lua Network.packets.BuyItem.listen(function(Request, Player) local Item = ItemCatalog[Request.ItemId] if not Item then return end if not EconomyService:CanAfford(Player, Item.Price) then return end EconomyService:Purchase(Player, Request.ItemId) end) ``` -------------------------------- ### Debug Namespace Synchronization in Lua Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/errors.md Use these print statements and assertions to verify that server and client namespace definitions match. ```lua -- Print server's namespace ID mapping print("Server namespace:", serverNamespaceData) -- Print client's received mapping print("Client namespace:", clientNamespaceData) -- Ensure definitions are identical assert( serverNamespaceData.packets == clientNamespaceData.packets, "Packet IDs don't match" ) ``` -------------------------------- ### Handle Listener Disconnection Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/errors.md Demonstrates safe patterns for disconnecting listeners to avoid 'already disconnected' warnings. ```lua -- ❌ Disconnect twice local disconnect = packet:listen(function(data) end) disconnect() disconnect() -- Warning! -- ✅ Only disconnect once local disconnect = packet:listen(function(data) end) disconnect() -- ✅ Safe pattern with flag local disconnect disconnect = packet:listen(function(data) if shouldStop then disconnect() return end end) ``` -------------------------------- ### Initialize Data Type Constructors Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/data-types.md Constructors are called without arguments to create data type instances. ```lua local stringType = ByteNet.string() local uint32Type = ByteNet.uint32() ``` -------------------------------- ### listen Source: https://github.com/elitriare/bytenet-max/blob/main/docs/api/query.md Server-side method to add a persistent request handler. ```APIDOC ## listen(callback) ### Description Server-side method that adds a persistent request handler. The callback receives (Request, Player) and must return a value compatible with the defined response type. ### Returns - **Disconnect function** (Function) - A function to remove the listener. ``` -------------------------------- ### Configure inbound buffer size in Lua Source: https://github.com/elitriare/bytenet-max/blob/main/docs/guides/security.md Set the MAX_BUFFER_SIZE attribute before initializing the ByteNet Max module to adjust the per-client byte budget. ```lua ByteNetMaxModule:SetAttribute("MAX_BUFFER_SIZE", 16 * 1024) local ByteNetMax = require(ByteNetMaxModule) ``` -------------------------------- ### Define Networking Namespace Source: https://github.com/elitriare/bytenet-max/blob/main/README.md Create a shared ModuleScript to define packets and queries. This module must be required on both server and client. ```lua local ReplicatedStorage = game:GetService("ReplicatedStorage") local ByteNetMax = require(ReplicatedStorage.Packages.ByteNetMax) return ByteNetMax.defineNamespace("Game", function() return { packets = { Announcement = ByteNetMax.definePacket({ value = ByteNetMax.string, }), }, queries = { GetCoins = ByteNetMax.defineQuery({ request = ByteNetMax.nothing, response = ByteNetMax.uint32, }), }, } end) ``` -------------------------------- ### Read Processing Entry Point Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/internals.md The main deserialization function used to dispatch incoming buffers to appropriate handlers. ```lua local function read( receivedBuffer: buffer, references: { unknown }?, player: Player?, mode: "packet" | "query"? ): any ``` -------------------------------- ### Define Network Objects Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/README.md Core functions for initializing packets, queries, and namespaces within the ByteNet system. ```lua ByteNet.definePacket(packetProps) → Packet ByteNet.defineQuery(queryProperties) → Query ByteNet.defineNamespace(name, namespaceThunk) → {packets, queries} ``` -------------------------------- ### Define Query Properties Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/types.md Configures the request and response data types along with callback behavior for ByteNet queries. ```lua export type queryProperties = { request: RequestType, response: ResponseType, callbackBehavior: { spawnThread: boolean, allowMultiple: boolean, }?, } ``` -------------------------------- ### Invoke Query from Client Source: https://github.com/elitriare/bytenet-max/blob/main/docs/getting-started/first-query.md Invoke the query from the client; note that this method yields until the server responds. ```lua local ReplicatedStorage = game:GetService("ReplicatedStorage") local Network = require(ReplicatedStorage.Network) local PotionCount = Network.queries.GetItemCount.invoke({ ItemId = "HealthPotion", }) print(`Potions: {PotionCount}`) ``` -------------------------------- ### Listen for packets on the server Source: https://github.com/elitriare/bytenet-max/blob/main/docs/getting-started/first-packet.md Register a listener on the server to handle incoming packets. The callback receives the packet data and the player who sent it. ```lua local ReplicatedStorage = game:GetService("ReplicatedStorage") local Network = require(ReplicatedStorage.Network) Network.packets.RequestAction.listen(function(Data, Player) print(`{Player.Name} requested {Data.Action}`) end) ``` -------------------------------- ### ByteNet.uint8() Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/data-types.md Constructor for an unsigned 8-bit integer (0 to 255). ```APIDOC ## ByteNet.uint8() ### Description Creates an unsigned 8-bit integer data type constructor. This type occupies 1 byte and supports values from 0 to 255. ### Usage ```lua local uint8Type = ByteNet.uint8() ``` ``` -------------------------------- ### ByteNet.optional Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/data-types.md Defines a value that may be nil. ```APIDOC ## ByteNet.optional(itemType) ### Description Creates a definition for a value that can either be present or nil. ### Signature `ByteNet.optional(itemType: dataTypeInterface): dataTypeInterface` ### Serialization Format 1. uint8: 0 = nil (value omitted), 1 = present 2. If present: serialize value according to itemType ``` -------------------------------- ### ByteNet.int16() Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/data-types.md Constructor for a signed 16-bit integer (-32,768 to 32,767). ```APIDOC ## ByteNet.int16() ### Description Creates a signed 16-bit integer data type constructor. This type occupies 2 bytes and supports values from -32,768 to 32,767. ### Usage ```lua local int16Type = ByteNet.int16() ``` ``` -------------------------------- ### Packet Listening Methods Source: https://github.com/elitriare/bytenet-max/blob/main/docs/guides/packets.md Methods for handling incoming packets on both client and server. ```APIDOC ## Packet Listening Methods ### Description Methods to register callbacks or yield execution until a packet is received. ### Methods - **listen(callback)**: Registers a persistent callback. Returns a disconnect function. - **listenOnce(callback)**: Registers a callback that runs only for the next received packet. Returns a disconnect function. - **wait()**: Yields the current thread until the next packet arrives. - **disconnectAll()**: Removes all listeners attached to the packet. ``` -------------------------------- ### Require ByteNet Max Module Source: https://github.com/elitriare/bytenet-max/blob/main/docs/getting-started/installation.md Load the ByteNet Max module from your project's Packages folder in ReplicatedStorage. ```lua local ReplicatedStorage = game:GetService("ReplicatedStorage") local ByteNetMax = require(ReplicatedStorage.Packages.ByteNetMax) ``` -------------------------------- ### Buffer Dump Process Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/internals.md Creates a trimmed buffer containing only written data to avoid extra allocation. ```lua local function dump(channel: types.channelData): (buffer, { unknown }?) local cursor = channel.cursor local dumpBuffer = buffer.create(cursor) buffer.copy(dumpBuffer, 0, channel.buff, 0, cursor) return dumpBuffer, if #channel.references > 0 then channel.references else nil end ``` -------------------------------- ### Managing Buffer Size Limits Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/errors.md Strategies for handling packets that exceed the maximum buffer size limit. ```lua -- ❌ Too large - 100 KB of data local largePacket = ByteNet.definePacket({ value = ByteNet.array(ByteNet.string), -- 100,000 strings }) -- ✅ Split into multiple smaller packets local batchPacket = ByteNet.definePacket({ value = ByteNet.struct({ pageNumber = ByteNet.uint16, items = ByteNet.array(ByteNet.string), }), }) ``` ```lua local ByteNet = require(ReplicatedStorage.Packages.ByteNetMax) ByteNet:SetAttribute("MAX_BUFFER_SIZE", 16384) -- 16 KB -- Now packets up to 16 KB are allowed ``` ```lua -- Send compressed/binary data using buff type instead of uncompressed strings local packet = ByteNet.definePacket({ value = ByteNet.buff, }) ``` -------------------------------- ### Wrap Callbacks with Error Handling Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/quick-reference.md Uses pcall to catch and log errors occurring within packet listener callbacks. ```lua packet:listen(function(data) local ok, err = pcall(function() processData(data) end) if not ok then warn("Error: " .. err) end end) ``` -------------------------------- ### Send a chat message with ByteNet Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/README.md Defines a string packet and demonstrates sending to all clients and listening for incoming messages. ```lua local chatPacket = ByteNet.definePacket({ value = ByteNet.string, }) chatPacket:sendToAll("Hello!") chatPacket:listen(function(msg) print(msg) end) ``` -------------------------------- ### ByteNet.buff() Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/data-types.md Represents raw buffer data. ```APIDOC ## ByteNet.buff() ### Description Serializes raw buffer data. The format consists of a uint16 length header followed by the raw bytes (max 65,535 bytes). ### Usage ```lua ByteNet.buff() ``` ``` -------------------------------- ### Define collections Source: https://github.com/elitriare/bytenet-max/blob/main/docs/guides/choosing-data-types.md Demonstrates the use of array and map types for sequential lists and dictionaries. ```lua Inventory = ByteNetMax.array(ByteNetMax.struct({ ItemId = ByteNetMax.string, Amount = ByteNetMax.uint16, })) Cooldowns = ByteNetMax.map(ByteNetMax.string, ByteNetMax.float32) ``` -------------------------------- ### ByteNet.defineQuery Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/README.md Defines a request-response pattern for synchronous-like data retrieval over the network. ```APIDOC ## ByteNet.defineQuery ### Description Defines a query structure that allows a client to request data from the server and receive a response. ### Usage ```lua local query = ByteNet.defineQuery({ request = ByteNet.uint32, response = ByteNet.string }) query:listen(function(userId) return "username" end) local result = query:invoke(123) ``` ``` -------------------------------- ### ByteNet.uint16() Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/data-types.md Constructor for an unsigned 16-bit integer (0 to 65,535). ```APIDOC ## ByteNet.uint16() ### Description Creates an unsigned 16-bit integer data type constructor. This type occupies 2 bytes and supports values from 0 to 65,535. ### Usage ```lua local uint16Type = ByteNet.uint16() ``` ``` -------------------------------- ### Define queryProperties type Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/bytenet-module.md Defines the configuration options for query definitions. ```lua type queryProperties = { request: RequestType, response: ResponseType, callbackBehavior: { spawnThread: boolean, allowMultiple: boolean, }?, } ``` -------------------------------- ### Handle Struct Field Serialization Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/namespace.md Logic for handling struct field ordering and replication between server and client contexts. ```lua -- Server side if runContext == "server" then local serializedStruct = {} local count = 0 for key in input do count += 1 serializedStruct[key] = count -- Field 1, 2, 3, ... end namespaceReplicator:write(constructedNamespace) end -- Client side if runContext == "client" then local structData = namespaceData.structs[structIndex] -- Use server's field ordering end ``` -------------------------------- ### Update require statement Source: https://github.com/elitriare/bytenet-max/blob/main/docs/reference/migration.md Update the require path to point to the ByteNet Max package. ```lua local ByteNetMax = require(ReplicatedStorage.Packages.ByteNetMax) ``` -------------------------------- ### Client Process Module State Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/module-map.md State variables for client-side message handling and remote function channels. ```lua local reliable: channelData local unreliable: channelData local funcs: { remoteFunctionChannel } = {} ``` -------------------------------- ### ByteNet.int8() Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/data-types.md Constructor for a signed 8-bit integer (-128 to 127). ```APIDOC ## ByteNet.int8() ### Description Creates a signed 8-bit integer data type constructor. This type occupies 1 byte and supports values from -128 to 127. ### Usage ```lua local int8Type = ByteNet.int8() ``` ``` -------------------------------- ### Monitoring Query Timeouts Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/quick-reference.md Be aware that queries will trigger a timeout warning if the server-side listener takes longer than 10 seconds to return. ```lua local query = ByteNet.defineQuery({ request = ByteNet.string, response = ByteNet.string, }) -- Server query:listen(function(request) print("Query received:", request) -- If this takes >10 seconds, timeout warning appears local result = expensiveComputation() return result end) ``` -------------------------------- ### Define a Query Source: https://github.com/elitriare/bytenet-max/blob/main/docs/api/query.md Initializes a new query object by specifying the data types for both the request and the response. ```lua ByteNetMax.defineQuery({ request = RequestDataType, response = ResponseDataType, }) ``` -------------------------------- ### ByteNet.defineQuery Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/README.md Defines a new query structure for request-response communication. ```APIDOC ## ByteNet.defineQuery(queryProperties) ### Description Defines a new query structure for request-response communication. ### Signature `ByteNet.defineQuery(queryProperties) -> Query` ``` -------------------------------- ### Server-side Networking Usage Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/quick-reference.md Send packets to all clients and listen for incoming queries on the server. ```lua local Networking = require(ReplicatedStorage.SharedModules.Networking) Networking.packets.ChatMessage:sendToAll("Hello!") Networking.queries.GetTime:listen(function(request) return tick() end) ``` -------------------------------- ### Send packets from the client Source: https://github.com/elitriare/bytenet-max/blob/main/docs/getting-started/first-packet.md Use the send method on the client to transmit data to the server. Always validate client-sent data on the server for security. ```lua local ReplicatedStorage = game:GetService("ReplicatedStorage") local Network = require(ReplicatedStorage.Network) Network.packets.RequestAction.send({ Action = "Dash", }) ``` -------------------------------- ### Define ByteNet Optional Types Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/data-types.md Use ByteNet.optional to allow a field to be nil, which is serialized with a 1-byte flag. ```lua ByteNet.optional(ByteNet.string) -- string or nil ByteNet.optional(ByteNet.uint32) -- uint32 or nil ByteNet.optional(ByteNet.vec3) -- Vector3 or nil ``` ```lua ByteNet.struct({ name = ByteNet.string, nickname = ByteNet.optional(ByteNet.string), }) -- With nickname: [1] [5, 0] "Alice" (1 + 2 + 5 = 8 bytes) -- Without: [0] (1 byte) ``` -------------------------------- ### Define Query Schema Source: https://github.com/elitriare/bytenet-max/blob/main/docs/getting-started/first-query.md Define the request and response structures within a shared namespace module. ```lua local ReplicatedStorage = game:GetService("ReplicatedStorage") local ByteNetMax = require(ReplicatedStorage.ByteNetMax) return ByteNetMax.defineNamespace("PlayerData", function() return { queries = { GetItemCount = ByteNetMax.defineQuery({ request = ByteNetMax.struct({ ItemId = ByteNetMax.string, }), response = ByteNetMax.uint16, }), }, } end) ``` -------------------------------- ### ByteNet.cframe() Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/data-types.md Represents a 3D transform (CFrame) using 24 bytes. ```APIDOC ## ByteNet.cframe() ### Description Serializes a 3D transform (CFrame) into 24 bytes, storing position as 3 float32 values and rotation as an axis-angle vector. ### Usage ```lua ByteNet.cframe() ``` ### Example ```lua ByteNet.definePacket({ value = ByteNet.struct({ character_transform = ByteNet.cframe, }), }) ``` ``` -------------------------------- ### Printing Packet Data Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/quick-reference.md Use the listen method to inspect incoming packet data and types during development. ```lua packet:listen(function(data) print("Received:", data) print("Type:", typeof(data)) end) ``` -------------------------------- ### Implement a Shared Namespace Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/namespace.md Define a namespace in a shared ModuleScript to ensure both server and client have access to the same packet and query definitions. ```lua -- shared/Networking.lua (shared ModuleScript) local ReplicatedStorage = game:GetService("ReplicatedStorage") local ByteNet = require(ReplicatedStorage.Packages.ByteNetMax) local GameNamespace = ByteNet.defineNamespace("Game", function() return { packets = { PlayerSpawned = ByteNet.definePacket({ value = ByteNet.struct({ userId = ByteNet.uint32, position = ByteNet.vec3, }), }), PlayerDied = ByteNet.definePacket({ value = ByteNet.uint32, -- userId }), }, queries = { GetPlayerStats = ByteNet.defineQuery({ request = ByteNet.uint32, -- userId response = ByteNet.struct({ health = ByteNet.uint8, mana = ByteNet.uint8, level = ByteNet.uint8, }), }), }, } end) return GameNamespace ``` -------------------------------- ### Configure MAX_BUFFER_SIZE Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/configuration.md Set the maximum network payload size. This must be configured after requiring the module but before defining any packets or queries. ```lua local ReplicatedStorage = game:GetService("ReplicatedStorage") local ByteNetMax = require(ReplicatedStorage.Packages.ByteNetMax) -- Set after requiring, before defining any packets/queries ByteNetMax:SetAttribute("MAX_BUFFER_SIZE", 16384) -- 16 KB ``` -------------------------------- ### Perform Dynamic Buffer Allocation Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/internals.md Resizes the buffer by a 1.5x factor when write operations exceed the current capacity. ```lua local function dyn_alloc(bytes: number) while cursor + bytes >= size do size = math.floor(size * 1.5) -- Grow by 50% end local newBuffer = buffer.create(size) buffer.copy(newBuffer, 0, buff) -- Copy old data buff = newBuffer end ``` -------------------------------- ### Define a ByteNet Namespace Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/bytenet-module.md Use this to group packets and queries within a shared ModuleScript. Ensure the namespace name and structure match on both client and server. ```luau -- Shared ModuleScript local ReplicatedStorage = game:GetService("ReplicatedStorage") local ByteNet = require(ReplicatedStorage.Packages.ByteNetMax) local GameEvents = ByteNet.defineNamespace("Game", function() return { packets = { Announcement = ByteNet.definePacket({ value = ByteNet.string, }), PlayerMove = ByteNet.definePacket({ value = ByteNet.struct({ position = ByteNet.vec3, rotation = ByteNet.float32, }), reliabilityType = "unreliable", -- position updates don't need guaranteed delivery }), }, queries = { GetServerTime = ByteNet.defineQuery({ request = ByteNet.nothing, response = ByteNet.uint32, }), }, } end) return GameEvents ``` -------------------------------- ### Define a Namespace Source: https://github.com/elitriare/bytenet-max/blob/main/docs/getting-started/core-concepts.md Groups related packets and queries within a shared ModuleScript. Ensure the namespace name is stable and unique. ```lua ByteNetMax.defineNamespace("Inventory", function() return { packets = { ... }, queries = { ... }, } end) ``` -------------------------------- ### listenOnce Source: https://github.com/elitriare/bytenet-max/blob/main/docs/api/query.md Server-side method to handle a single request, then disconnect. ```APIDOC ## listenOnce(callback) ### Description Server-side method that handles one request, then automatically disconnects the listener. ### Returns - **Disconnect function** (Function) - A function to remove the listener. ``` -------------------------------- ### Define complex data structures Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/README.md Demonstrates how to define a packet containing a struct with arrays, integers, and optional fields. ```lua local dataPacket = ByteNet.definePacket({ value = ByteNet.struct({ items = ByteNet.array(ByteNet.string), count = ByteNet.uint32, owner = ByteNet.optional(ByteNet.string), }), }) ``` -------------------------------- ### Implement Client-Side Query Timeout Handling Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/errors.md Provides a wrapper function to handle nil results returned when a query exceeds the timeout threshold. ```lua -- Client detects timeout and acts accordingly local function queryWithTimeout(query, request, timeoutSeconds) local result = query:invoke(request) if result == nil then warn("Query timed out") return getDefaultValue() end return result end ``` -------------------------------- ### Define a Query Source: https://github.com/elitriare/bytenet-max/blob/main/docs/guides/queries.md Define a query by specifying request and response data types using ByteNetMax primitives. ```lua GetLoadout = ByteNetMax.defineQuery({ request = ByteNetMax.nothing, response = ByteNetMax.array(ByteNetMax.string), }) ``` -------------------------------- ### Listen for packets Source: https://github.com/elitriare/bytenet-max/blob/main/docs/guides/packets.md Register a persistent callback and use the returned function to disconnect. ```lua local Disconnect = Network.packets.Announcement.listen(function(Data) print(Data.Text) end) Disconnect() ``` -------------------------------- ### Implement Simple Data Types Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/internals.md Defines a simple data type interface using a buffer writer and reader function. ```lua return function(): dataTypeInterface return { write = bufferWriter.u32, read = function(b, cursor) return buffer.readu32(b, cursor), 4 end, } end ``` -------------------------------- ### Data Type Export Pattern Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/module-map.md Standard structure for implementing new data types in ByteNet-Max. ```lua return function(): dataTypeInterface return { write = function(value) ... end, read = function(b, cursor, references?) return value, bytesConsumed end, } end ``` -------------------------------- ### Define optional values Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/bytenet-module.md Use optional constructors for values that may be nil, serialized with a uint8 flag. ```lua ByteNet.optional(ByteNet.string) -- string or nil ByteNet.optional(ByteNet.vec3) -- Vector3 or nil ``` -------------------------------- ### ByteNet Exported API Table Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/module-map.md The main API table returned by the package entry point, exposing packet definitions and data type constructors. ```lua return { definePacket = definePacket, defineQuery = defineQuery, defineNamespace = namespace, -- Data type constructors (all call with no args) auto = auto(), array = array, bool = bool(), uint8 = uint8(), -- ... all other data types -- Helper types playerIdentifier = uint8(), playerName = string(), } ``` -------------------------------- ### Configure Maximum Packet Size Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/quick-reference.md Sets the global buffer size limit for network packets. ```lua local ByteNet = require(ReplicatedStorage.Packages.ByteNetMax) ByteNet:SetAttribute("MAX_BUFFER_SIZE", 16384) -- 16 KB ``` -------------------------------- ### Define float32 and float64 types Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/data-types.md Use float32 for standard game values and float64 for high-precision requirements. ```lua ByteNet.float32() ``` ```lua ByteNet.float64() ``` -------------------------------- ### ByteNet.struct Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/data-types.md Defines a fixed structure with named fields. ```APIDOC ## ByteNet.struct(fieldDefinition) ### Description Creates a fixed structure definition with named fields. Field order must be consistent across server and client. ### Signature `ByteNet.struct(definition: {[string]: dataTypeInterface}): dataTypeInterface` ### Serialization Format - Fields are serialized in a consistent order. - No field names are transmitted (implicit). ``` -------------------------------- ### Define maps Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/api-reference/bytenet-module.md Use map constructors for dictionaries with homogeneous keys and values, serialized with a uint16 pair count. ```lua ByteNet.map(ByteNet.uint32, ByteNet.string) -- map of ID -> name ByteNet.map(ByteNet.string, ByteNet.uint32) -- map of name -> count ``` -------------------------------- ### Define Shared Namespace Source: https://github.com/elitriare/bytenet-max/blob/main/docs/getting-started/initialization.md Create a shared module in ReplicatedStorage to define packets or queries accessible by both server and client. ```lua local ReplicatedStorage = game:GetService("ReplicatedStorage") local ByteNetMax = require(ReplicatedStorage.ByteNetMax) return ByteNetMax.defineNamespace("Game", function() return { packets = { Ready = ByteNetMax.definePacket({ value = ByteNetMax.bool, }), }, } end) ``` -------------------------------- ### Wait for packet Source: https://github.com/elitriare/bytenet-max/blob/main/docs/guides/packets.md Yield the current thread until the next packet arrives. ```lua local Data, Player = Network.packets.Ready.wait() ``` -------------------------------- ### Defining Explicit Packet Types Source: https://github.com/elitriare/bytenet-max/blob/main/_autodocs/quick-reference.md Avoid using ByteNet.unknown to maintain type safety and performance. ```lua -- ❌ Bad: Slow, loses type info local dynamicPacket = ByteNet.definePacket({ value = ByteNet.unknown, }) -- ✅ Good: Explicit type local structPacket = ByteNet.definePacket({ value = ByteNet.struct({ x = ByteNet.float32, y = ByteNet.float32, }), }) ``` -------------------------------- ### Define a map schema Source: https://github.com/elitriare/bytenet-max/blob/main/docs/api/data-types.md Create a dictionary schema serialized as key/value pairs with a 2-byte count prefix. ```lua local Scores = ByteNetMax.map(ByteNetMax.string, ByteNetMax.uint32) ```