Skip to main content

NetworkServer

This item only works when running on the server. Server

The server counterpart of network.

Types

DefaultNetworkServerConfig

interface DefaultNetworkServerConfig {
automaticArgumentSerializationAndDeserializationEnabledtrue
promisifyCallbackstrue
}

DefaultNetworkServerMiddleware

interface DefaultNetworkServerMiddleware {
methodCallInbound{}
methodCallOutbound{}
valueDispatch{}
}

NetworkServerConfig

interface NetworkServerConfig {
automaticArgumentSerializationAndDeserializationEnabledboolean--

determines whether or not values sent to clients by the remote signal be internally serialized/deserialized or not.

promisifyCallbacksboolean--

determines whether or not a promise is returned to the client (resolved with the return values of the callback) whenever they call a serverside exposed callback

}
Remote Signal and Remote Property not subject to automatic serialization / deserialization!

RemoteSignal and RemoteProperty objects sent across the network by the network object will never be serialized or deserialized, regardless of automaticArgumentSerializationAndDeserializationEnabled. They're handled internally to ensure they are properly replicated across the network.

  • automaticArgumentSerializationAndDeserializationEnabled -> true

    • Arguments and values sent across the network by the network object will be automatically serialized and deserialized respectively, with the help of an internal library, i.e serializerUtil.

    ::note Serialization and deserialization limitations! While the serializer utility used to accomplish this supports a variety of data types, do keep in mind that not all data types can be supported on the go for serialization and deserialization - check the above hyperlink to the serializer utility on how many data types it supports. ::::

    See the type of the value of abc being TweenInfo on the client:

    -- Server
    local Workspace = game:GetService("Workspace")
    
    local testNetwork = network.Server.new("TestNetwork", nil, {
    	automaticArgumentSerializationAndDeserializationEnabled = true
    })
    testNetwork:append("abc", TweenInfo.new()) -- By default, TweenInfos
    -- are not replicated properlty across the  network, but watch the magic!
    testNetwork:dispatch(Workspace)
    
    -- Client
    local Workspace = game:GetService("Workspace")
    
    local testNetwork = network.client.fromParent("TestNetwork", Workspace):expect()
    print(typeof(testNetwork.abc)) --> "TweenInfo"
    
  • automaticArgumentSerializationAndDeserializationEnabled -> false

    • Arguments and values sent across the network will not be internally serialized and deserialized. Using the same example as above:

    See the type of the value of abc being table on the client instead of TweenInfo:

    -- Server
    local Workspace = game:GetService("Workspace")
    
    local testNetwork = network.Server.new("TestNetwork", nil, {
    	automaticArgumentSerializationAndDeserializationEnabled = false
    })
    testNetwork:append("abc", TweenInfo.new())
    testNetwork:dispatch(Workspace)
    
    -- Client
    local Workspace = game:GetService("Workspace")
    
    local testNetwork = network.client.fromParent("abc", Workspace):expect()
    print(typeof(testNetwork.abc)) --> "table"
    
  • promisifyCallbacks -> true:

    Serverside exposed callback called on the client will immediately return a promise which will be resolved with the return values of the callback.

    -- Server
    local Workspace = game:GetService("Workspace")
    
    local testNetwork = network.Server.new("TestNetwork", nil, {
    	promisifyCallbacks = true
    })
    testNetwork:append("method", function() return task.wait(5) end)
    testNetwork:dispatch(Workspace)
    
    -- Client
    local Workspace = game:GetService("Workspace")
    
    local testNetwork = network.client.fromParent("abc", Workspace):expect()
    testNetwork.method():andThen(function(deltaTime)
    	print(typeof(deltaTime)) --> "number"
    end)
    
  • promisifyCallbacks -> false:

    Serverside exposed callback called on the client will not return a promise and instead will yield the given thread until the callback has returned back to the caller.

    -- Server
    local Workspace = game:GetService("Workspace")
    
    local testNetwork = network.Server.new("TestNetwork", nil, {
    	promisifyCallbacks = false
    })
    testNetwork:append("method", function() return task.wait(5) end)
    testNetwork:dispatch(Workspace)
    
    -- Client
    local Workspace = game:GetService("Workspace")
    
    local testNetwork = network.client.fromParent("abc", Workspace):expect()
    print(typeof(testNetwork.method())) --> "number" (Thread is yielded for approx 5 seconds)
    

NetworkServer

type NetworkServer = NetworkServer

NetworkServerMiddleware

interface NetworkServerMiddleware {
methodCallInbound(
methodNamestring,
clientPlayer,
args{any}
) → boolean--

Before a callback runs.

methodCallOutbound(
methodNamestring,
clientPlayer,
args{any},
methodResponseany
) → any--

After a callback has finished running.

valueDispatch(
clientPlayer,
valueany
) → any--

Affects the return value of the callbacks (to the clients) after they've run.

}
Yielding in middleware callbacks is not allowed

Middleware callbacks aren't allowed to yield. If they do so, their thread will be closed via coroutine.close and an error will be outputted in the console.

Yielding, (especially in network-related code) results in weird bugs and behavior which can be hard to track down!

methodCallInbound

Callbacks in methodCallInbound are called whenever a client tries to call any of the appended methods of the network.

The first argument passed to each callback is the name of the method (the client called), and the second argument, i.e the arguments sent by the client, which are packed into an array.

local methodCallInboundCallbacks = {
	function (methodName, client: Player, arguments)
		print(client:IsA("Player")) --> true 
		print(typeof(arguments)) --> "table"
	end
}
---
More control
  • If any of the callbacks return an explicit false value, then the method which the client tried to call, will not be called. This is useful as you can implement for e.g, implementing rate limits!

  • Additionally, you can modify the arguments table which will be reflected in the method, for e.g:

-- Server
local Workspace = game:GetService("Workspace")
local testNetwork = network.Server.new("TestNetwork", {methodCallInbound = {
	function(_, _, arguments) 
		arguments[2] = "test"
	end
}})
testNetwork:append("method", function(player, a)
	print(a) --> "test" (a ought to be 1, but the middleware modified it!)
end)
testNetwork:dispatch(Workspace)

-- Client
local Workspace = game:GetService("Workspace")

local testNetwork = network.client.fromParent("TestNetwork", Workspace):expect()
testNetwork.method(1) 

methodCallOutbound

Callbacks in methodCallOutbound are called whenever a method (appended to the network) is called by the client, and has finished running.

The first argument passed to each callback is the name of the method (client called), and the second argument, i.e the arguments sent by the client, which are packed into an array.

A third argument i.e methodResponse is passed to each callback as well, which is just the response of the method called.

local methodCallOutboundCallbacks = {
	function (methodName, client: Player, arguments, methodResponse)
		print(client:IsA("Player")) --> true 
		print(typeof(arguments)) --> "table"
	end
}
---

Additionally, these callbacks can return a value that overrides the actual result of the method (which will be sent back to the client). For e.g:

-- Server:
local Workspace = game:GetService("Workspace")

local middleware = {
	{
		function (methodName, arguments, methodResponse)
			print(methodResponse) --> "this"
			return 50
		end
	}
}

local testNetwork = network.Server.new("TestNetwork", middleware)
testNetwork:append("someMethod", function()
	return "this"
end)
testNetwork:dispatch(Workspace)

-- Client:
local Workspace = game:GetService("Workspace")

local testNetwork = network.fromParent("TestNetwork", Workspace):expect()
print(testNetwork.someMethod()) --> 50 

Additionally, if more than 1 callback returns a value, then all those returned values will be packed into an array and then sent back to the client. This is by design, as it isn't ideal to disregard all returned values for just 1.

For e.g:

-- Server:
local Workspace = game:GetService("Workspace")

local middleware = {
	{
		function (methodName, arguments, response)
			return 1
		end,

		function (methodName, arguments, response)
			return 2
		end,

		function (methodName, arguments, response)
			return 3
		end
	}
}

local testNetwork = network.server.new("TestNetwork", middleware)
testNetwork:append("someMethod", function()
	return "this"
end)
testNetwork:dispatch(Workspace)

-- Client:
local Workspace = game:GetService("Workspace")

local testNetwork = network.client.fromParent("TestNetwork", Workspace):expect()
print(testNetwork.someMethod()) --> {1, 2, 3} 

valueDispatch

Callbacks in valueDispatch are called whenever the network object replicates a value (specifically a non function and not a remote signal and not a remote property), e.g a table, number, string, etc.

The first argument passed to each callback is the client itself whom the value is going to replicate to, and the value.

local valueDispatchCallbacks = {
	function (client, value)
		---
	end,
   
}
---

The return value of the callback will be used in favour of the original value. If more than 1 callback returns a value, all of them will be packed into an array and then sent.

local Workspace = game:GetService("Workspace")

-- Server
local valueDispatchCallbacks = {
	function (client, value)
		return {
			test = 1
		}
	end,
   
}

local testNetwork = network.Server.new("TestNetwork", {valueDispatch = valueDispatchCallbacks})
testNetwork:append("someValue", 5)
testNetwork:dispatch(Workspace)

-- Client
local Workspace = game:GetService("Workspace")

local testNetwork = network.client.fromParent("TestNetwork", Workspace):expect()
print(testNetwork.someValue) --> {test = 1} (this thought to be 5, but the middleware returned a table instead)
-- Server
local Workspace = game:GetService("Workspace")

local valueDispatchCallbacks = {
	function (client, value)
		print(value) --> 5
		return 1
	end,
	
	function (client, value)
		print(value) --> 5
	 	return 2
	end
}

local testNetwork = network.Server.new("TestNetwork", {valueDispatch = valueDispatchCallbacks})
testNetwork:append("someValue", 5)
testNetwork:dispatch(Workspace)

-- Client
local Workspace = game:GetService("Workspace")

local testNetwork = network.client.fromParent("TestNetwork", Workspace):expect()
print(testNetwork.someValue) --> {1, 2}
---
More control
  • If any of the callbacks return a nil value, then the value will not be replicated to the client. For e.g:
local Workspace = game:GetService("Workspace")

-- Server
local valueDispatchCallbacks = {
	function (client, value)
		return nil
	end,
   
}

local testNetwork = network.Server.new("TestNetwork", {valueDispatch = valueDispatchCallbacks})
testNetwork:append("someValue", 5)
testNetwork:dispatch(Workspace)

-- Client
local Workspace = game:GetService("Workspace")

local testNetwork = network.client.fromParent("TestNetwork", Workspace):expect()
print(testNetwork.someValue) --> nil (this thought to be 5, but the middleware returned a nil value instead)

Properties

RemoteProperty

Read only
NetworkServer.RemoteProperty: RemoteProperty

RemoteProperty

Read only
NetworkServer.RemoteProperty: RemoteProperty

Functions

new

NetworkServer.new(
namestring,
networkServerConfigNetworkServerConfig?
) → NetworkServer

Creates and returns a new network object of name.

-- Server:
local network = NetworkServer.new("Test")
network:append("key", "some value")
network:dispatch(game:GetService("ReplicatedStorage"))

-- Client:
local network = network.Client.fromParent("Test", game:GetService("ReplicatedStorage")):expect()
print(network.key) --> "some value"
Network object will initially not be accessible to the client!

The network object will initially not be accessible to the client. You need to call NetworkServer:dispatch to render the network object accessible to the client!

fromName

NetworkServer.fromName(namestring) → NetworkServer?

Returns a network of the given name, if found.

-- Script 1:
local network = NetworkServer.new("Test")
network:append("key", "some value")
network:dispatch(game:GetService("ReplicatedStorage"))

-- Script 2:
local testNetwork = NetworkServer.fromName("Test")

fromNamePromise

NetworkServer.fromNamePromise(namestring) → Promise<NetworkServer>

RemotePromisified version of NetworkServer.fromName.

-- Script 1:
local network = NetworkServer.new("Test")
network:append("key", "some value")
network:dispatch(game:GetService("ReplicatedStorage"))

-- Script 2:
NetworkServer.fromNamePromise("Test"):andThen(function(testNetwork)
	print(testNetwork:dispatch()) 
end)

is

NetworkServer.is(selfany) → boolean

Returns a boolean indicating if self is a network object or not.

dispatched

NetworkServer instance
NetworkServer:dispatched() → boolean

Returns a boolean indicating if the network object is dispatched to the client or not.

append

NetworkServer instance
NetworkServer:append(
keystring,
valuestring | number | {number} | {[string]any} | RemoteProperty.RemoteProperty | RemoteSignal.RemoteSignal
) → ()

Appends a key-value pair, key and value, to the network object, so that it is available to the client once the network object is dispatched.

For e.g:

-- Server
local Workspace = game:GetService("Workspace")

local testNetwork = network.Server.new("TestNetwork")
testNetwork:append("key", "the value!")
testNetwork:dispatch(Workspace)

-- Client
local testNetwork = Network.client.fromParent("TestNetwork", Workspace):expect()
print(testNetwork.key) --> "the value!"
More support

You can also append a RemoteSignal and a RemoteProperty as well, they'll be represented as a ClientRemoteSignal and a ClientRemoteProperty to the client respectively!

Precaution!

If the network object does not have a default middleware (AutomaticArgumentSerializationAndDeserialization specifically) set, then argument limitations will apply, as remote functions are internally used the key-value pairs accessible to the clients.

WARNING

This method will error if the network object is dispatched to the client. Always make sure to append keys and values before you dispatch the network object. You can check if a network object is dispatched to the client or not through NetworkServer:dispatched.

dispatch

NetworkServer instance
NetworkServer:dispatch(parentInstance) → ()

Dispatches the network folder of the network object to parent, rendering the network object accessible to the client now.

-- Server
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")

local network = require(ReplicatedStorage.Packages.network) 

local testNetwork = Network.Server.new("Test")
testNetwork:append("method", function(player)
	return string.format("hi, %s!", player.Name)
end)

-- Dispatch the network to workspace:
testNetwork:dispatch(Workspace) 

-- Client
local Workspace = game:GetService("Workspace")

local testNetwork = network.client.fromParent("Test", Workspace):expect()
print(testNetwork.method()) --> "hi, bubshurb!"

destroy

NetworkServer instance
NetworkServer:destroy() → ()

Destroys the network object and all appended remote properties & remote signals within the network object, and renders the network object useless.

Show raw api
{
    "functions": [
        {
            "name": "new",
            "desc": "Creates and returns a new network object of `name`.\n\n```lua\n-- Server:\nlocal network = NetworkServer.new(\"Test\")\nnetwork:append(\"key\", \"some value\")\nnetwork:dispatch(game:GetService(\"ReplicatedStorage\"))\n\n-- Client:\nlocal network = network.Client.fromParent(\"Test\", game:GetService(\"ReplicatedStorage\")):expect()\nprint(network.key) --> \"some value\"\n```\n\n- If the 2nd parameter `middleware` is not specified, then it will default to [DefaultNetworkServerMiddleware] instead.\n- If the 3rd parameter `networkServerConfig` is not specified, then it will default to [DefaultNetworkServerConfig] instead.\n\n:::warning Network object will initially not be accessible to the client!\nThe network object will initially not be accessible to the client. You need to call [NetworkServer:dispatch] \nto render the network object accessible to the client!\n:::",
            "params": [
                {
                    "name": "name",
                    "desc": "",
                    "lua_type": "string"
                },
                {
                    "name": "middleware",
                    "desc": "",
                    "lua_type": "NetworkServerMiddleware?"
                },
                {
                    "name": "networkServerConfig",
                    "desc": "",
                    "lua_type": "NetworkServerConfig?"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "NetworkServer\n"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 450,
                "path": "src/network/Server/init.luau"
            }
        },
        {
            "name": "fromName",
            "desc": "Returns a network of the given name, if found.\n\n```lua\n-- Script 1:\nlocal network = NetworkServer.new(\"Test\")\nnetwork:append(\"key\", \"some value\")\nnetwork:dispatch(game:GetService(\"ReplicatedStorage\"))\n\n-- Script 2:\nlocal testNetwork = NetworkServer.fromName(\"Test\")\n```",
            "params": [
                {
                    "name": "name",
                    "desc": "",
                    "lua_type": "string"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "NetworkServer?"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 513,
                "path": "src/network/Server/init.luau"
            }
        },
        {
            "name": "fromNamePromise",
            "desc": "RemotePromisified version of [NetworkServer.fromName].\n\n```lua\n-- Script 1:\nlocal network = NetworkServer.new(\"Test\")\nnetwork:append(\"key\", \"some value\")\nnetwork:dispatch(game:GetService(\"ReplicatedStorage\"))\n\n-- Script 2:\nNetworkServer.fromNamePromise(\"Test\"):andThen(function(testNetwork)\n\tprint(testNetwork:dispatch()) \nend)\n```",
            "params": [
                {
                    "name": "name",
                    "desc": "",
                    "lua_type": "string"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Promise<NetworkServer>"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 535,
                "path": "src/network/Server/init.luau"
            }
        },
        {
            "name": "is",
            "desc": "Returns a boolean indicating if `self` is a network object or not.",
            "params": [
                {
                    "name": "self",
                    "desc": "",
                    "lua_type": "any"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "boolean\n"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 553,
                "path": "src/network/Server/init.luau"
            }
        },
        {
            "name": "dispatched",
            "desc": "Returns a boolean indicating if the network object is dispatched to the \nclient or not. ",
            "params": [],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "boolean\n"
                }
            ],
            "function_type": "method",
            "tags": [
                "NetworkServer instance"
            ],
            "source": {
                "line": 564,
                "path": "src/network/Server/init.luau"
            }
        },
        {
            "name": "append",
            "desc": "Appends a key-value pair, `key` and `value`, to the network object, so that\nit is available to the client once the network object is dispatched. \n\nFor e.g:\n\n```lua\n-- Server\nlocal Workspace = game:GetService(\"Workspace\")\n\nlocal testNetwork = network.Server.new(\"TestNetwork\")\ntestNetwork:append(\"key\", \"the value!\")\ntestNetwork:dispatch(Workspace)\n\n-- Client\nlocal testNetwork = Network.client.fromParent(\"TestNetwork\", Workspace):expect()\nprint(testNetwork.key) --> \"the value!\"\n```\n\n:::tip More support\nYou can also append a [RemoteSignal] and a [RemoteProperty] as well, they'll be represented as a [ClientRemoteSignal] and a [ClientRemoteProperty]\nto the client respectively!\n::: \n\n:::note Precaution!\nIf the network object does not have a default middleware (`AutomaticArgumentSerializationAndDeserialization` specifically) set, \nthen [argument limitations](https://create.roblox.com/docs/scripting/events/argument-limitations-for-bindables-and-remotes)\nwill apply, as remote functions are internally used the key-value pairs accessible to the clients.\n:::\n\n:::warning\nThis method will error if the network object is dispatched to the client. \nAlways make sure to append keys and values *before* you dispatch the \nnetwork object. You can check if a network object is dispatched to the \nclient or not through [NetworkServer:dispatched].\n:::",
            "params": [
                {
                    "name": "key",
                    "desc": "",
                    "lua_type": "string"
                },
                {
                    "name": "value",
                    "desc": "",
                    "lua_type": "string | number | { number } | { [string]: any } | RemoteProperty.RemoteProperty | RemoteSignal.RemoteSignal\n"
                }
            ],
            "returns": [],
            "function_type": "method",
            "tags": [
                "NetworkServer instance"
            ],
            "source": {
                "line": 608,
                "path": "src/network/Server/init.luau"
            }
        },
        {
            "name": "dispatch",
            "desc": "Dispatches the network folder of the network object to `parent`, rendering\nthe network object accessible to the client now. \n\n```lua\n-- Server\nlocal ReplicatedStorage = game:GetService(\"ReplicatedStorage\")\nlocal Workspace = game:GetService(\"Workspace\")\n\nlocal network = require(ReplicatedStorage.Packages.network) \n\nlocal testNetwork = Network.Server.new(\"Test\")\ntestNetwork:append(\"method\", function(player)\n\treturn string.format(\"hi, %s!\", player.Name)\nend)\n\n-- Dispatch the network to workspace:\ntestNetwork:dispatch(Workspace) \n\n-- Client\nlocal Workspace = game:GetService(\"Workspace\")\n\nlocal testNetwork = network.client.fromParent(\"Test\", Workspace):expect()\nprint(testNetwork.method()) --> \"hi, bubshurb!\"\n```",
            "params": [
                {
                    "name": "parent",
                    "desc": "",
                    "lua_type": "Instance"
                }
            ],
            "returns": [],
            "function_type": "method",
            "tags": [
                "NetworkServer instance"
            ],
            "source": {
                "line": 653,
                "path": "src/network/Server/init.luau"
            }
        },
        {
            "name": "destroy",
            "desc": "Destroys the network object and all appended remote properties &\nremote signals within the network object, and renders the network \nobject useless. ",
            "params": [],
            "returns": [],
            "function_type": "method",
            "tags": [
                "NetworkServer instance"
            ],
            "source": {
                "line": 665,
                "path": "src/network/Server/init.luau"
            }
        }
    ],
    "properties": [
        {
            "name": "RemoteProperty",
            "desc": " ",
            "lua_type": "RemoteProperty",
            "tags": [
                "Read only"
            ],
            "source": {
                "line": 13,
                "path": "src/network/Server/init.luau"
            }
        },
        {
            "name": "RemoteProperty",
            "desc": " ",
            "lua_type": "RemoteProperty",
            "tags": [
                "Read only"
            ],
            "source": {
                "line": 19,
                "path": "src/network/Server/init.luau"
            }
        }
    ],
    "types": [
        {
            "name": "DefaultNetworkServerConfig",
            "desc": " ",
            "fields": [
                {
                    "name": "automaticArgumentSerializationAndDeserializationEnabled",
                    "lua_type": "true",
                    "desc": ""
                },
                {
                    "name": "promisifyCallbacks",
                    "lua_type": "true",
                    "desc": ""
                }
            ],
            "source": {
                "line": 26,
                "path": "src/network/Server/init.luau"
            }
        },
        {
            "name": "DefaultNetworkServerMiddleware",
            "desc": "",
            "fields": [
                {
                    "name": "methodCallInbound",
                    "lua_type": "{}",
                    "desc": ""
                },
                {
                    "name": "methodCallOutbound",
                    "lua_type": "{}",
                    "desc": ""
                },
                {
                    "name": "valueDispatch",
                    "lua_type": "{}",
                    "desc": ""
                }
            ],
            "source": {
                "line": 34,
                "path": "src/network/Server/init.luau"
            }
        },
        {
            "name": "NetworkServerConfig",
            "desc": " \n\n:::warning Remote Signal and Remote Property not subject to automatic serialization / deserialization!\n[RemoteSignal] and [RemoteProperty] objects sent across the network by the network object will never be\nserialized or deserialized, regardless of `automaticArgumentSerializationAndDeserializationEnabled`. They're\nhandled internally to ensure they are properly replicated across the network.\n:::\n\n- `automaticArgumentSerializationAndDeserializationEnabled` -> `true`\n\t- Arguments and values sent across the network by the network object\n\twill be automatically serialized and deserialized respectively, with the\n\thelp of an internal library, i.e [serializerUtil](https://babypatrick100.github.io/libraries/api/serializerUtil/).\n\n\t::note Serialization and deserialization limitations!\n\tWhile the serializer utility used to accomplish this supports a variety of data types, do keep in mind that not all data types\n\tcan be supported on the go for serialization and deserialization - check the above hyperlink to the serializer utility on how\n\tmany data types it supports.\n\t::::\n\n\t**See the type of the value of `abc` being `TweenInfo` on the client**:\n\n\t```lua\n\t-- Server\n\tlocal Workspace = game:GetService(\"Workspace\")\n\n\tlocal testNetwork = network.Server.new(\"TestNetwork\", nil, {\n\t\tautomaticArgumentSerializationAndDeserializationEnabled = true\n\t})\n\ttestNetwork:append(\"abc\", TweenInfo.new()) -- By default, TweenInfos\n\t-- are not replicated properlty across the  network, but watch the magic!\n\ttestNetwork:dispatch(Workspace)\n\n\t-- Client\n\tlocal Workspace = game:GetService(\"Workspace\")\n\n\tlocal testNetwork = network.client.fromParent(\"TestNetwork\", Workspace):expect()\n\tprint(typeof(testNetwork.abc)) --> \"TweenInfo\"\n\t```\n- `automaticArgumentSerializationAndDeserializationEnabled` -> `false`\n\t- Arguments and values sent across the network will not be internally serialized\n\tand deserialized. Using the same example as above:\n\n\t**See the type of the value of `abc` being `table` on the client instead of `TweenInfo`**:\n\n\t```lua\n\t-- Server\n\tlocal Workspace = game:GetService(\"Workspace\")\n\n\tlocal testNetwork = network.Server.new(\"TestNetwork\", nil, {\n\t\tautomaticArgumentSerializationAndDeserializationEnabled = false\n\t})\n\ttestNetwork:append(\"abc\", TweenInfo.new())\n\ttestNetwork:dispatch(Workspace)\n\n\t-- Client\n\tlocal Workspace = game:GetService(\"Workspace\")\n\n\tlocal testNetwork = network.client.fromParent(\"abc\", Workspace):expect()\n\tprint(typeof(testNetwork.abc)) --> \"table\"\n\t```\n\n- `promisifyCallbacks` -> `true`:\n\n\tServerside exposed callback called on the client will immediately return a promise which will be resolved\n\twith the return values of the callback.\n\n\t```lua\n\t-- Server\n\tlocal Workspace = game:GetService(\"Workspace\")\n\n\tlocal testNetwork = network.Server.new(\"TestNetwork\", nil, {\n\t\tpromisifyCallbacks = true\n\t})\n\ttestNetwork:append(\"method\", function() return task.wait(5) end)\n\ttestNetwork:dispatch(Workspace)\n\n\t-- Client\n\tlocal Workspace = game:GetService(\"Workspace\")\n\n\tlocal testNetwork = network.client.fromParent(\"abc\", Workspace):expect()\n\ttestNetwork.method():andThen(function(deltaTime)\n\t\tprint(typeof(deltaTime)) --> \"number\"\n\tend)\n\t```\n- `promisifyCallbacks` -> `false`:\n\n\tServerside exposed callback called on the client will **not** return a promise and instead\n\twill yield the given thread until the callback has returned back to the caller.\n\n\t```lua\n\t-- Server\n\tlocal Workspace = game:GetService(\"Workspace\")\n\n\tlocal testNetwork = network.Server.new(\"TestNetwork\", nil, {\n\t\tpromisifyCallbacks = false\n\t})\n\ttestNetwork:append(\"method\", function() return task.wait(5) end)\n\ttestNetwork:dispatch(Workspace)\n\n\t-- Client\n\tlocal Workspace = game:GetService(\"Workspace\")\n\n\tlocal testNetwork = network.client.fromParent(\"abc\", Workspace):expect()\n\tprint(typeof(testNetwork.method())) --> \"number\" (Thread is yielded for approx 5 seconds)\n\t```",
            "fields": [
                {
                    "name": "automaticArgumentSerializationAndDeserializationEnabled",
                    "lua_type": "boolean",
                    "desc": "determines whether or not values sent to clients by the remote signal be internally serialized/deserialized or not."
                },
                {
                    "name": "promisifyCallbacks",
                    "lua_type": "boolean",
                    "desc": "determines whether or not a promise is returned to the client (resolved with the return values of the callback) whenever they call a serverside exposed callback"
                }
            ],
            "source": {
                "line": 145,
                "path": "src/network/Server/init.luau"
            }
        },
        {
            "name": "NetworkServer",
            "desc": " ",
            "lua_type": "NetworkServer",
            "source": {
                "line": 150,
                "path": "src/network/Server/init.luau"
            }
        },
        {
            "name": "NetworkServerMiddleware",
            "desc": ":::warning Yielding in middleware callbacks is not allowed\nMiddleware callbacks aren't allowed to yield. If they do so, their thread will be closed via\n[coroutine.close](https://create.roblox.com/docs/reference/engine/libraries/coroutine#close) and an\nerror will be outputted in the console.\n\nYielding, (especially in network-related code) results in weird bugs and behavior which can be hard to track down!\n:::\n\n### `methodCallInbound` \n\nCallbacks in `methodCallInbound` are called whenever a client tries to call any of the appended methods of the network. \n\nThe first argument passed to each callback is the name of the method (the client called), and the second argument, i.e \nthe arguments sent by the client, which are packed into an array. \n\n```lua\nlocal methodCallInboundCallbacks = {\n\tfunction (methodName, client: Player, arguments)\n\t\tprint(client:IsA(\"Player\")) --> true \n\t\tprint(typeof(arguments)) --> \"table\"\n\tend\n}\n---\n```\n\n:::tip More control\n- If any of the callbacks return an **explicit** false value, then the method which the client tried to call, will *not* be\ncalled. This is useful as you can implement for e.g, implementing rate limits!\n\n- Additionally, you can modify the `arguments` table which will be reflected in the method, for e.g:\n\n```lua\n-- Server\nlocal Workspace = game:GetService(\"Workspace\")\nlocal testNetwork = network.Server.new(\"TestNetwork\", {methodCallInbound = {\n\tfunction(_, _, arguments) \n\t\targuments[2] = \"test\"\n\tend\n}})\ntestNetwork:append(\"method\", function(player, a)\n\tprint(a) --> \"test\" (a ought to be 1, but the middleware modified it!)\nend)\ntestNetwork:dispatch(Workspace)\n\n-- Client\nlocal Workspace = game:GetService(\"Workspace\")\n\nlocal testNetwork = network.client.fromParent(\"TestNetwork\", Workspace):expect()\ntestNetwork.method(1) \n```\n:::\n\n### `methodCallOutbound` \n\nCallbacks in `methodCallOutbound` are called whenever a method (appended to the network) is called by the client, and \nhas **finished** running.  \n\nThe first argument passed to each callback is the name of the method (client called), and the second argument, i.e \nthe arguments sent by the client, which are packed into an array. \n\nA third argument i.e `methodResponse` is passed to each callback as well, which is just the response of the method called. \n\n```lua\nlocal methodCallOutboundCallbacks = {\n\tfunction (methodName, client: Player, arguments, methodResponse)\n\t\tprint(client:IsA(\"Player\")) --> true \n\t\tprint(typeof(arguments)) --> \"table\"\n\tend\n}\n---\n```\n\nAdditionally, these callbacks can return a value that overrides the actual result of the method (which will be sent\nback to the client). For e.g:\n\n```lua\n-- Server:\nlocal Workspace = game:GetService(\"Workspace\")\n\nlocal middleware = {\n\t{\n\t\tfunction (methodName, arguments, methodResponse)\n\t\t\tprint(methodResponse) --> \"this\"\n\t\t\treturn 50\n\t\tend\n\t}\n}\n\nlocal testNetwork = network.Server.new(\"TestNetwork\", middleware)\ntestNetwork:append(\"someMethod\", function()\n\treturn \"this\"\nend)\ntestNetwork:dispatch(Workspace)\n\n-- Client:\nlocal Workspace = game:GetService(\"Workspace\")\n\nlocal testNetwork = network.fromParent(\"TestNetwork\", Workspace):expect()\nprint(testNetwork.someMethod()) --> 50 \n```\n\nAdditionally, if more than 1 callback returns a value, then all those returned values will be packed into an array and *then* sent\nback to the client. This is by design, as it isn't ideal to disregard all returned values for just 1.\n\nFor e.g: \n\n```lua\n-- Server:\nlocal Workspace = game:GetService(\"Workspace\")\n\nlocal middleware = {\n\t{\n\t\tfunction (methodName, arguments, response)\n\t\t\treturn 1\n\t\tend,\n\n\t\tfunction (methodName, arguments, response)\n\t\t\treturn 2\n\t\tend,\n\n\t\tfunction (methodName, arguments, response)\n\t\t\treturn 3\n\t\tend\n\t}\n}\n\nlocal testNetwork = network.server.new(\"TestNetwork\", middleware)\ntestNetwork:append(\"someMethod\", function()\n\treturn \"this\"\nend)\ntestNetwork:dispatch(Workspace)\n\n-- Client:\nlocal Workspace = game:GetService(\"Workspace\")\n\nlocal testNetwork = network.client.fromParent(\"TestNetwork\", Workspace):expect()\nprint(testNetwork.someMethod()) --> {1, 2, 3} \n```\n\n### `valueDispatch` \n\nCallbacks in `valueDispatch` are called whenever the network object replicates a value (**specifically a non function and not a remote signal\nand not a remote property**), e.g a table, number, string, etc.\n\nThe first argument passed to each callback is the client itself whom the value is going to replicate to, and the value.\n\n```lua\nlocal valueDispatchCallbacks = {\n\tfunction (client, value)\n\t\t---\n\tend,\n   \n}\n---\n```\n\nThe return value of the callback will be used in favour of the original value. If more than 1 callback returns\na value, all of them will be packed into an array and *then* sent.\n\n```lua\nlocal Workspace = game:GetService(\"Workspace\")\n\n-- Server\nlocal valueDispatchCallbacks = {\n\tfunction (client, value)\n\t\treturn {\n\t\t\ttest = 1\n\t\t}\n\tend,\n   \n}\n\nlocal testNetwork = network.Server.new(\"TestNetwork\", {valueDispatch = valueDispatchCallbacks})\ntestNetwork:append(\"someValue\", 5)\ntestNetwork:dispatch(Workspace)\n\n-- Client\nlocal Workspace = game:GetService(\"Workspace\")\n\nlocal testNetwork = network.client.fromParent(\"TestNetwork\", Workspace):expect()\nprint(testNetwork.someValue) --> {test = 1} (this thought to be 5, but the middleware returned a table instead)\n```\n\n```lua\n-- Server\nlocal Workspace = game:GetService(\"Workspace\")\n\nlocal valueDispatchCallbacks = {\n\tfunction (client, value)\n\t\tprint(value) --> 5\n\t\treturn 1\n\tend,\n\t\n\tfunction (client, value)\n\t\tprint(value) --> 5\n\t \treturn 2\n\tend\n}\n\nlocal testNetwork = network.Server.new(\"TestNetwork\", {valueDispatch = valueDispatchCallbacks})\ntestNetwork:append(\"someValue\", 5)\ntestNetwork:dispatch(Workspace)\n\n-- Client\nlocal Workspace = game:GetService(\"Workspace\")\n\nlocal testNetwork = network.client.fromParent(\"TestNetwork\", Workspace):expect()\nprint(testNetwork.someValue) --> {1, 2}\n---\n```\n\n:::tip More control\n- If any of the callbacks return a `nil` value, then the value will not be replicated to the client. For e.g:\n\n```lua\nlocal Workspace = game:GetService(\"Workspace\")\n\n-- Server\nlocal valueDispatchCallbacks = {\n\tfunction (client, value)\n\t\treturn nil\n\tend,\n   \n}\n\nlocal testNetwork = network.Server.new(\"TestNetwork\", {valueDispatch = valueDispatchCallbacks})\ntestNetwork:append(\"someValue\", 5)\ntestNetwork:dispatch(Workspace)\n\n-- Client\nlocal Workspace = game:GetService(\"Workspace\")\n\nlocal testNetwork = network.client.fromParent(\"TestNetwork\", Workspace):expect()\nprint(testNetwork.someValue) --> nil (this thought to be 5, but the middleware returned a nil value instead)\n```\n:::",
            "fields": [
                {
                    "name": "methodCallInbound",
                    "lua_type": "(methodName: string, client: Player, args: {any}) -> boolean",
                    "desc": "Before a callback runs."
                },
                {
                    "name": "methodCallOutbound",
                    "lua_type": "(methodName: string, client: Player, args: {any}, methodResponse: any) -> any",
                    "desc": "After a callback has finished running."
                },
                {
                    "name": "valueDispatch",
                    "lua_type": "(client: Player, value: any) -> any",
                    "desc": "Affects the return value of the callbacks (to the clients) after they've run."
                }
            ],
            "source": {
                "line": 395,
                "path": "src/network/Server/init.luau"
            }
        }
    ],
    "name": "NetworkServer",
    "desc": "The server counterpart of [network].",
    "realm": [
        "Server"
    ],
    "source": {
        "line": 7,
        "path": "src/network/Server/init.luau"
    }
}