@flamework-experimental/networking 2.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +66 -0
  2. package/flamework.build +7 -0
  3. package/out/event/createEvent.d.ts +59 -0
  4. package/out/event/createEvent.luau +114 -0
  5. package/out/event/createRemoteInstance.d.ts +1 -0
  6. package/out/event/createRemoteInstance.luau +58 -0
  7. package/out/events/createClientMethod.d.ts +5 -0
  8. package/out/events/createClientMethod.luau +30 -0
  9. package/out/events/createGenericHandler.d.ts +5 -0
  10. package/out/events/createGenericHandler.luau +102 -0
  11. package/out/events/createNetworkingEvent.d.ts +2 -0
  12. package/out/events/createNetworkingEvent.luau +60 -0
  13. package/out/events/createServerMethod.d.ts +13 -0
  14. package/out/events/createServerMethod.luau +63 -0
  15. package/out/events/types.d.ts +220 -0
  16. package/out/function/createFunctionReceiver.d.ts +52 -0
  17. package/out/function/createFunctionReceiver.luau +118 -0
  18. package/out/function/createFunctionSender.d.ts +45 -0
  19. package/out/function/createFunctionSender.luau +135 -0
  20. package/out/function/errors.d.ts +10 -0
  21. package/out/function/errors.luau +25 -0
  22. package/out/functions/createClientMethod.d.ts +15 -0
  23. package/out/functions/createClientMethod.luau +52 -0
  24. package/out/functions/createGenericHandler.d.ts +7 -0
  25. package/out/functions/createGenericHandler.luau +140 -0
  26. package/out/functions/createNetworkingFunction.d.ts +2 -0
  27. package/out/functions/createNetworkingFunction.luau +68 -0
  28. package/out/functions/createServerMethod.d.ts +15 -0
  29. package/out/functions/createServerMethod.luau +52 -0
  30. package/out/functions/types.d.ts +289 -0
  31. package/out/handlers.d.ts +36 -0
  32. package/out/index.d.ts +55 -0
  33. package/out/init.luau +78 -0
  34. package/out/middleware/createGuardMiddleware.d.ts +6 -0
  35. package/out/middleware/createGuardMiddleware.luau +44 -0
  36. package/out/middleware/createMiddlewareProcessor.d.ts +3 -0
  37. package/out/middleware/createMiddlewareProcessor.luau +24 -0
  38. package/out/middleware/skip.d.ts +8 -0
  39. package/out/middleware/skip.luau +22 -0
  40. package/out/middleware/types.d.ts +15 -0
  41. package/out/types.d.ts +78 -0
  42. package/out/util/createSignalContainer.d.ts +5 -0
  43. package/out/util/createSignalContainer.luau +30 -0
  44. package/out/util/getNamespaceConfig.d.ts +10 -0
  45. package/out/util/getNamespaceConfig.luau +15 -0
  46. package/out/util/timeoutPromise.d.ts +1 -0
  47. package/out/util/timeoutPromise.luau +10 -0
  48. package/package.json +32 -0
package/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # Flamework
2
+
3
+ Flamework is an extensible framework for roblox-ts designed around portable, isolated and testable modules.
4
+
5
+ ## Documentation
6
+
7
+ **[docs/](docs/README.md)** -- start there. A ten-part guide that builds up from a working entry
8
+ point to plugins and project layout, plus reference material:
9
+
10
+ | | |
11
+ |---|---|
12
+ | [Guide](docs/README.md#guide) | Getting started, modules, providers, lifecycle events, components, networking, macros, plugins, project structure, migrating from v1. |
13
+ | [Internals](docs/reference/internals.md) | What the transformer does to your code and what the runtime does with the result. |
14
+ | [Transformer plugins](docs/reference/transformer-plugins.md) | Adding macro types of your own. |
15
+
16
+ The Flamework website documents v1, most of which no longer applies:
17
+
18
+ https://flamework.fireboltofdeath.dev/docs/introduction
19
+
20
+ ## Development
21
+
22
+ This repository is a [Bun](https://bun.sh) workspace. It also needs
23
+ [Lune](https://lune-org.github.io/docs) on `PATH` to run the runtime specs.
24
+
25
+ ```sh
26
+ bun install
27
+ bun run build # builds every package in dependency order
28
+ bun run test # build + transformer tests + runtime specs
29
+ bun run lint
30
+ ```
31
+
32
+ ### Packages
33
+
34
+ | Package | Description |
35
+ |---|---|
36
+ | `packages/core` | Modules, dependency injection, plugins and lifecycle events |
37
+ | `packages/components` | CollectionService components, built on the core plugin system |
38
+ | `packages/networking` | Remote events and functions |
39
+ | `packages/testing` | In-place tests: sections, cleanup, a bindable and a remote to run them, a cloud entry; and `flamework-test`, the CLI that runs them in Roblox Studio on this machine or through Open Cloud (`cli/`) |
40
+ | `packages/transformer` | The roblox-ts transformer |
41
+ | `packages/transformer-plugin` | Public API for writing transformer plugins |
42
+ | `packages/specs` | Runtime specs, compiled by `rbxtsc` and executed under Lune |
43
+
44
+ ### Tests
45
+
46
+ Two suites, both run by `bun run test`:
47
+
48
+ - **Transformer tests** (`bun run test:unit`) compile a fixture project with the real `rbxtsc` and
49
+ assert on the emitted Luau — guard generation, identifiers, nested macros and the plugin system.
50
+ - **Runtime specs** (`bun run test:runtime`) execute compiled `@flamework-experimental/core`, `components` and
51
+ `networking` under Lune using the harness in [`tests/runtime`](tests/runtime), which models
52
+ roblox-ts's `TS.import` tree over the filesystem and stubs the Roblox API surface Flamework
53
+ touches (Instances, attributes, CollectionService, RemoteEvents, Players, signals, `task`,
54
+ `Enum`, and a `Heartbeat` pump so `Promise.delay` -- and therefore request timeouts -- runs).
55
+ They cover dependency injection, modules, hooks and the per-frame lifecycle events, component
56
+ construction, dependencies and streaming, and both halves of networking: events, functions,
57
+ middleware and the generated guards.
58
+
59
+ They run twice, once as `Server` and once as `Client`, because realm-dependent code paths --
60
+ `@Provider`'s metadata, component streaming, and the client/server halves of networking -- differ
61
+ between them. Where a spec asserts something realm-specific, running it from both sides is what
62
+ proves the two agree: a function receives on `$name` and sends on `@name` from the server and the
63
+ mirror image from the client, so the pair of runs pins the wire format down from both ends.
64
+
65
+ Specs live in [`packages/specs`](packages/specs) and are compiled by `rbxtsc` like any other
66
+ Flamework consumer, so they exercise the transformer and the runtime together.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 1,
3
+ "flameworkVersion": "2.0.0-alpha.0",
4
+ "identifiers": {},
5
+ "idGenerationMode": "full",
6
+ "identifierPrefix": "$n"
7
+ }
@@ -0,0 +1,59 @@
1
+ import { Serialization } from "@flamework-experimental/core";
2
+ import { MiddlewareFactory, MiddlewareProcessor } from "../middleware/types";
3
+ import { NetworkInfo } from "../types";
4
+ export interface CreateEventOptions {
5
+ /**
6
+ * The namespace this event should be created in.
7
+ */
8
+ namespace: string;
9
+ /**
10
+ * The name of the remote instance, not necessarily unique and used for debugging purposes.
11
+ */
12
+ debugName: string;
13
+ /**
14
+ * The remote's ID which must be unique.
15
+ */
16
+ id: string;
17
+ /**
18
+ * Information about the network, which includes some of the above.
19
+ *
20
+ * Passed to the middleware.
21
+ */
22
+ networkInfo: NetworkInfo;
23
+ /**
24
+ * The reliability of this remote.
25
+ *
26
+ * Defaults to reliable.
27
+ */
28
+ reliability?: "reliable" | "unreliable";
29
+ /**
30
+ * A list of middleware that this event uses when it receives an event.
31
+ */
32
+ incomingMiddleware?: MiddlewareFactory<any[], void>[];
33
+ /**
34
+ * Unpacks the argument list of incoming events. Absent when the project does not enable
35
+ * serialization. Outgoing lists reach `fire*` already packed: the transformer generates the
36
+ * encoding inline at each call site.
37
+ */
38
+ incomingDecoder?: Serialization.Decoder;
39
+ /**
40
+ * Called when an incoming payload cannot be decoded; the event is dropped.
41
+ */
42
+ onMalformed?: (player: Player | undefined, message: string) => void;
43
+ }
44
+ export interface EventInterface {
45
+ fireEither(player: Player | undefined, ...args: unknown[]): void;
46
+ fireServer(...args: unknown[]): void;
47
+ fireClient(player: Player, ...args: unknown[]): void;
48
+ fireAllClients(...args: unknown[]): void;
49
+ connectServer(callback: (player: Player, ...args: unknown[]) => void): RBXScriptConnection;
50
+ connectClient(callback: (...args: unknown[]) => void): RBXScriptConnection;
51
+ invoke: MiddlewareProcessor<any[], void>;
52
+ }
53
+ /**
54
+ * The argument list a remote delivered: `args` as they are without a decoder, otherwise the buffer
55
+ * and blob list unpacked. `undefined` when the payload was malformed, after reporting it through
56
+ * `onMalformed`. Decoding runs under `pcall`: a hostile buffer raises instead of yielding garbage.
57
+ */
58
+ export declare function decodeArguments(decoder: Serialization.Decoder | undefined, player: Player | undefined, args: unknown[], onMalformed?: (player: Player | undefined, message: string) => void): unknown[] | undefined;
59
+ export declare function createEvent(options: CreateEventOptions): EventInterface;
@@ -0,0 +1,114 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local RunService = TS.import(script, TS.getModule(script, "@rbxts", "services")).RunService
4
+ local createRemoteInstance = TS.import(script, script.Parent, "createRemoteInstance").createRemoteInstance
5
+ local createMiddlewareProcessor = TS.import(script, script.Parent.Parent, "middleware", "createMiddlewareProcessor").createMiddlewareProcessor
6
+ --* A sender whose type has blob slots always sends a table; one without never does.
7
+ local NO_BLOBS = {}
8
+ --[[
9
+ *
10
+ * The argument list a remote delivered: `args` as they are without a decoder, otherwise the buffer
11
+ * and blob list unpacked. `undefined` when the payload was malformed, after reporting it through
12
+ * `onMalformed`. Decoding runs under `pcall`: a hostile buffer raises instead of yielding garbage.
13
+
14
+ ]]
15
+ local function decodeArguments(decoder, player, args, onMalformed)
16
+ if not decoder then
17
+ return args
18
+ end
19
+ local _binding = args
20
+ local payload = _binding[1]
21
+ local blobs = _binding[2]
22
+ if not (type(payload) == "buffer") or (blobs ~= nil and not (type(blobs) == "table")) then
23
+ local _result = onMalformed
24
+ if _result ~= nil then
25
+ _result(player, "payload is not a buffer with an optional blob list")
26
+ end
27
+ return nil
28
+ end
29
+ local ok, result = pcall(decoder, payload, (blobs or NO_BLOBS))
30
+ if not ok then
31
+ local _result = onMalformed
32
+ if _result ~= nil then
33
+ _result(player, tostring(result))
34
+ end
35
+ return nil
36
+ end
37
+ return result
38
+ end
39
+ local function createEvent(options)
40
+ local remote = createRemoteInstance(if options.reliability == "unreliable" then "UnreliableRemoteEvent" else "RemoteEvent", options.namespace, options.debugName, options.id)
41
+ local bindable
42
+ local invoke = createMiddlewareProcessor(options.incomingMiddleware, options.networkInfo, function(player, ...)
43
+ local args = { ... }
44
+ if RunService:IsServer() then
45
+ bindable:Fire(player, unpack(args))
46
+ else
47
+ bindable:Fire(unpack(args))
48
+ end
49
+ end)
50
+ local receive = function(player, args)
51
+ local decoded = decodeArguments(options.incomingDecoder, player, args, options.onMalformed)
52
+ if decoded then
53
+ invoke(player, unpack(decoded))
54
+ end
55
+ end
56
+ local createConnection = function(callback)
57
+ if bindable then
58
+ return bindable.Event:Connect(callback)
59
+ end
60
+ bindable = Instance.new("BindableEvent")
61
+ -- We defer to allow any other immediate connections to take place before unloading Roblox's queue.
62
+ task.defer(function()
63
+ if RunService:IsServer() then
64
+ remote.OnServerEvent:Connect(function(player, ...)
65
+ local args = { ... }
66
+ return receive(player, args)
67
+ end)
68
+ else
69
+ remote.OnClientEvent:Connect(function(...)
70
+ local args = { ... }
71
+ return receive(nil, args)
72
+ end)
73
+ end
74
+ end)
75
+ return bindable.Event:Connect(callback)
76
+ end
77
+ return {
78
+ fireEither = function(self, player, ...)
79
+ local args = { ... }
80
+ if player then
81
+ self:fireClient(player, unpack(args))
82
+ else
83
+ self:fireServer(unpack(args))
84
+ end
85
+ end,
86
+ fireServer = function(self, ...)
87
+ local args = { ... }
88
+ remote:FireServer(unpack(args))
89
+ end,
90
+ fireClient = function(self, player, ...)
91
+ local args = { ... }
92
+ remote:FireClient(player, unpack(args))
93
+ end,
94
+ fireAllClients = function(self, ...)
95
+ local args = { ... }
96
+ remote:FireAllClients(unpack(args))
97
+ end,
98
+ connectServer = function(self, callback)
99
+ local _arg0 = RunService:IsServer()
100
+ assert(_arg0)
101
+ return createConnection(callback)
102
+ end,
103
+ connectClient = function(self, callback)
104
+ local _arg0 = RunService:IsClient()
105
+ assert(_arg0)
106
+ return createConnection(callback)
107
+ end,
108
+ invoke = invoke,
109
+ }
110
+ end
111
+ return {
112
+ decodeArguments = decodeArguments,
113
+ createEvent = createEvent,
114
+ }
@@ -0,0 +1 @@
1
+ export declare function createRemoteInstance<T extends "RemoteEvent" | "UnreliableRemoteEvent">(remoteType: T, namespace: string, debugName: string, id: string): CreatableInstances[T];
@@ -0,0 +1,58 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local _services = TS.import(script, TS.getModule(script, "@rbxts", "services"))
4
+ local ReplicatedStorage = _services.ReplicatedStorage
5
+ local RunService = _services.RunService
6
+ local function findByAttribute(parent, id)
7
+ for _, child in parent:GetChildren() do
8
+ if child:GetAttribute("id") == id then
9
+ return child
10
+ end
11
+ end
12
+ end
13
+ local function waitByAttribute(parent, id)
14
+ local instance = findByAttribute(parent, id)
15
+ local watcherThread = task.delay(5, function()
16
+ warn(`Flamework is waiting on '{id}' for`, parent)
17
+ end)
18
+ if not instance then
19
+ -- A connection rather than `ChildAdded.Wait()` in a loop: with deferred signals, children
20
+ -- added while the loop is between waits are never seen, so the wait never ends.
21
+ local thread = coroutine.running()
22
+ local connection
23
+ connection = parent.ChildAdded:Connect(function(child)
24
+ if child:GetAttribute("id") == id then
25
+ connection:Disconnect()
26
+ task.spawn(thread, child)
27
+ end
28
+ end)
29
+ instance = (coroutine.yield())
30
+ end
31
+ task.cancel(watcherThread)
32
+ return instance
33
+ end
34
+ local function createRemoteInstance(remoteType, namespace, debugName, id)
35
+ if not RunService:IsRunning() then
36
+ return Instance.new(remoteType)
37
+ end
38
+ local namespaceFolder = if RunService:IsServer() then findByAttribute(ReplicatedStorage, namespace) else waitByAttribute(ReplicatedStorage, namespace)
39
+ if not namespaceFolder then
40
+ namespaceFolder = Instance.new("Folder")
41
+ namespaceFolder.Name = namespace
42
+ namespaceFolder:SetAttribute("id", namespace)
43
+ namespaceFolder.Parent = ReplicatedStorage
44
+ end
45
+ local existingInstance = if RunService:IsServer() then findByAttribute(namespaceFolder, id) else waitByAttribute(namespaceFolder, id)
46
+ if not existingInstance then
47
+ existingInstance = Instance.new(remoteType)
48
+ existingInstance.Name = debugName
49
+ existingInstance:SetAttribute("id", id)
50
+ existingInstance.Parent = namespaceFolder
51
+ end
52
+ local _arg0 = existingInstance:IsA(remoteType)
53
+ assert(_arg0)
54
+ return existingInstance
55
+ end
56
+ return {
57
+ createRemoteInstance = createRemoteInstance,
58
+ }
@@ -0,0 +1,5 @@
1
+ import { ClientReceiver, ClientSender } from "./types";
2
+ import { EventInterface } from "../event/createEvent";
3
+ type ClientMethod = ClientSender<never[]> & ClientReceiver<never[]>;
4
+ export declare function createClientMethod(receiver: EventInterface, sender: EventInterface): ClientMethod;
5
+ export {};
@@ -0,0 +1,30 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local function createClientMethod(receiver, sender)
3
+ local method = {
4
+ fire = function(self, ...)
5
+ local args = { ... }
6
+ sender:fireServer(unpack(args))
7
+ end,
8
+ _fire = function(self, ...)
9
+ local packed = { ... }
10
+ sender:fireServer(unpack(packed))
11
+ end,
12
+ connect = function(self, callback)
13
+ return receiver:connectClient(callback)
14
+ end,
15
+ predict = function(self, ...)
16
+ local args = { ... }
17
+ return receiver.invoke(nil, unpack(args))
18
+ end,
19
+ }
20
+ setmetatable(method, {
21
+ __call = function(method, ...)
22
+ local args = { ... }
23
+ method:fire(unpack(args))
24
+ end,
25
+ })
26
+ return method
27
+ end
28
+ return {
29
+ createClientMethod = createClientMethod,
30
+ }
@@ -0,0 +1,5 @@
1
+ import { EventNetworkingEvents } from "../handlers";
2
+ import { ClientHandler, EventCreateConfiguration, NamespaceMetadata, ServerHandler } from "./types";
3
+ import { SignalContainer } from "../util/createSignalContainer";
4
+ import { EventInterface } from "../event/createEvent";
5
+ export declare function createGenericHandler<T extends ClientHandler<S, R> | ServerHandler<S, R>, S, R>(globalName: string, namespaceName: string | undefined, metadata: NamespaceMetadata<R, S>, config: EventCreateConfiguration<R>, signals: SignalContainer<EventNetworkingEvents>, method: (receiver: EventInterface, sender: EventInterface) => unknown): T;
@@ -0,0 +1,102 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local createGuardMiddleware = TS.import(script, script.Parent.Parent, "middleware", "createGuardMiddleware").createGuardMiddleware
4
+ local createEvent = TS.import(script, script.Parent.Parent, "event", "createEvent").createEvent
5
+ local getNamespaceConfig = TS.import(script, script.Parent.Parent, "util", "getNamespaceConfig").getNamespaceConfig
6
+ local Players = TS.import(script, TS.getModule(script, "@rbxts", "services")).Players
7
+ local function createGenericHandler(globalName, namespaceName, metadata, config, signals, method)
8
+ local handler = {}
9
+ local _set = {}
10
+ for _, _v in metadata.incomingIds do
11
+ _set[_v] = true
12
+ end
13
+ local receiverNameSet = _set
14
+ local _set_1 = {}
15
+ for _, _v in metadata.outgoingIds do
16
+ _set_1[_v] = true
17
+ end
18
+ local senderNameSet = _set_1
19
+ local _set_2 = {}
20
+ local _array = {}
21
+ local _length = #_array
22
+ local _array_1 = metadata.incomingIds
23
+ local _Length = #_array_1
24
+ table.move(_array_1, 1, _Length, _length + 1, _array)
25
+ _length += _Length
26
+ local _array_2 = metadata.outgoingIds
27
+ table.move(_array_2, 1, #_array_2, _length + 1, _array)
28
+ for _, _v in _array do
29
+ _set_2[_v] = true
30
+ end
31
+ for name in _set_2 do
32
+ local isIncoming = receiverNameSet[name] ~= nil
33
+ local isOutgoing = senderNameSet[name] ~= nil
34
+ -- If there is no incoming/outgoing event, use the same reliability as the other.
35
+ local incomingChannel = if isIncoming then metadata.incomingUnreliable else metadata.outgoingUnreliable
36
+ local outgoingChannel = if isOutgoing then metadata.outgoingUnreliable else metadata.incomingUnreliable
37
+ local isIncomingUnreliable = incomingChannel[name] == true
38
+ local isOutgoingUnreliable = outgoingChannel[name] == true
39
+ local configMiddleware = config.middleware[name]
40
+ local incomingMiddleware = if configMiddleware ~= nil then table.clone(configMiddleware) else {}
41
+ local effectiveName = if namespaceName ~= nil then `{namespaceName}/{name}` else name
42
+ local networkInfo = {
43
+ eventType = "Event",
44
+ name = effectiveName,
45
+ globalName = globalName,
46
+ }
47
+ if not config.disableIncomingGuards and isIncoming then
48
+ local guards = metadata.incoming[name]
49
+ assert(guards)
50
+ local _arg0 = createGuardMiddleware(name, guards[1], guards[2], networkInfo, config.warnOnInvalidGuards, signals)
51
+ table.insert(incomingMiddleware, 1, _arg0)
52
+ end
53
+ -- A malformed serialized payload is reported like a failed guard, with no argument index.
54
+ local onMalformed = function(player, message)
55
+ if config.warnOnInvalidGuards then
56
+ local sender = if player ~= nil then `'{player}'` else "Server"
57
+ warn(`{sender} sent a malformed payload for event '{name}': {message}`)
58
+ end
59
+ signals:fire("onBadRequest", player or Players.LocalPlayer, {
60
+ networkInfo = networkInfo,
61
+ argIndex = -1,
62
+ argValue = message,
63
+ })
64
+ end
65
+ local create = function(unreliable, receives)
66
+ local _object = {
67
+ reliability = if unreliable then "unreliable" else "reliable",
68
+ namespace = globalName,
69
+ id = if unreliable then `unreliable:{effectiveName}` else effectiveName,
70
+ debugName = name,
71
+ networkInfo = networkInfo,
72
+ incomingMiddleware = incomingMiddleware,
73
+ }
74
+ local _left = "incomingDecoder"
75
+ local _result
76
+ if receives then
77
+ local _result_1 = metadata.incomingSerializers
78
+ if _result_1 ~= nil then
79
+ _result_1 = _result_1[name]
80
+ end
81
+ _result = _result_1
82
+ else
83
+ _result = nil
84
+ end
85
+ _object[_left] = _result
86
+ _object.onMalformed = onMalformed
87
+ return createEvent(_object)
88
+ end
89
+ local shared = isOutgoingUnreliable == isIncomingUnreliable
90
+ local receiver = create(isIncomingUnreliable, true)
91
+ local sender = if shared then receiver else create(isOutgoingUnreliable, false)
92
+ handler[name] = method(receiver, sender)
93
+ end
94
+ for _, namespaceId in metadata.namespaceIds do
95
+ local namespace = metadata.namespaces[namespaceId]
96
+ handler[namespaceId] = createGenericHandler(globalName, if namespaceName ~= nil then `{namespaceName}/{namespaceId}` else namespaceId, namespace, getNamespaceConfig(config, namespaceId), signals, method)
97
+ end
98
+ return handler
99
+ end
100
+ return {
101
+ createGenericHandler = createGenericHandler,
102
+ }
@@ -0,0 +1,2 @@
1
+ import { GlobalEvent } from "./types";
2
+ export declare function createNetworkingEvent<S, C>(globalName: string): GlobalEvent<S, C>;
@@ -0,0 +1,60 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local RunService = TS.import(script, TS.getModule(script, "@rbxts", "services")).RunService
4
+ local createClientMethod = TS.import(script, script.Parent, "createClientMethod").createClientMethod
5
+ local createServerMethod = TS.import(script, script.Parent, "createServerMethod").createServerMethod
6
+ local createSignalContainer = TS.import(script, script.Parent.Parent, "util", "createSignalContainer").createSignalContainer
7
+ local createGenericHandler = TS.import(script, script.Parent, "createGenericHandler").createGenericHandler
8
+ local function getDefaultConfiguration(config)
9
+ local _object = {}
10
+ local _left = "middleware"
11
+ local _condition = config.middleware
12
+ if _condition == nil then
13
+ _condition = {}
14
+ end
15
+ _object[_left] = _condition
16
+ local _left_1 = "warnOnInvalidGuards"
17
+ local _condition_1 = config.warnOnInvalidGuards
18
+ if _condition_1 == nil then
19
+ _condition_1 = RunService:IsStudio()
20
+ end
21
+ _object[_left_1] = _condition_1
22
+ local _left_2 = "disableIncomingGuards"
23
+ local _condition_2 = config.disableIncomingGuards
24
+ if _condition_2 == nil then
25
+ _condition_2 = false
26
+ end
27
+ _object[_left_2] = _condition_2
28
+ return _object
29
+ end
30
+ local function createNetworkingEvent(globalName)
31
+ local signals = createSignalContainer()
32
+ local server
33
+ local client
34
+ return {
35
+ createServer = function(self, config, meta)
36
+ if RunService:IsRunning() and not RunService:IsServer() then
37
+ return nil
38
+ end
39
+ if server == nil then
40
+ server = createGenericHandler(globalName, nil, meta, getDefaultConfiguration(config), signals, createServerMethod)
41
+ end
42
+ return server
43
+ end,
44
+ createClient = function(self, config, meta)
45
+ if RunService:IsRunning() and not RunService:IsClient() then
46
+ return nil
47
+ end
48
+ if client == nil then
49
+ client = createGenericHandler(globalName, nil, meta, getDefaultConfiguration(config), signals, createClientMethod)
50
+ end
51
+ return client
52
+ end,
53
+ registerHandler = function(self, key, callback)
54
+ return signals:connect(key, callback)
55
+ end,
56
+ }
57
+ end
58
+ return {
59
+ createNetworkingEvent = createNetworkingEvent,
60
+ }
@@ -0,0 +1,13 @@
1
+ import { EventInterface } from "../event/createEvent";
2
+ export declare function createServerMethod(receiver: EventInterface, sender: EventInterface): {
3
+ readonly _flamework_send?: unknown[] | undefined;
4
+ _fire: (players: Player | Player[], payload?: buffer, blobs?: Array<defined>) => void;
5
+ _except: (players: Player | Player[], payload?: buffer, blobs?: Array<defined>) => void;
6
+ _broadcast: (payload?: buffer, blobs?: Array<defined>) => void;
7
+ fire: (players: Player | Player[], ...args: unknown[]) => void;
8
+ except: (players: Player | Player[], ...args: unknown[]) => void;
9
+ broadcast: (...args: unknown[]) => void;
10
+ readonly _flamework_receive?: unknown[] | undefined;
11
+ connect: (cb: (player: Player, ...args: unknown[]) => void) => RBXScriptConnection;
12
+ predict: (player: Player, ...args: unknown[]) => void;
13
+ };
@@ -0,0 +1,63 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local Players = TS.import(script, TS.getModule(script, "@rbxts", "services")).Players
4
+ local function createServerMethod(receiver, sender)
5
+ local method = {
6
+ fire = function(self, players, ...)
7
+ local args = { ... }
8
+ local _players = players
9
+ if typeof(_players) == "Instance" then
10
+ sender:fireClient(players, unpack(args))
11
+ else
12
+ for _, player in players do
13
+ sender:fireClient(player, unpack(args))
14
+ end
15
+ end
16
+ end,
17
+ broadcast = function(self, ...)
18
+ local args = { ... }
19
+ sender:fireAllClients(unpack(args))
20
+ end,
21
+ except = function(self, players, ...)
22
+ local args = { ... }
23
+ local _players = players
24
+ if typeof(_players) == "Instance" then
25
+ players = { players }
26
+ end
27
+ for _, player in Players:GetPlayers() do
28
+ if not (table.find(players, player) ~= nil) then
29
+ self:fire(player, unpack(args))
30
+ end
31
+ end
32
+ end,
33
+ _fire = function(self, players, ...)
34
+ local packed = { ... }
35
+ self:fire(players, unpack(packed))
36
+ end,
37
+ _broadcast = function(self, ...)
38
+ local packed = { ... }
39
+ self:broadcast(unpack(packed))
40
+ end,
41
+ _except = function(self, players, ...)
42
+ local packed = { ... }
43
+ self:except(players, unpack(packed))
44
+ end,
45
+ connect = function(self, callback)
46
+ return receiver:connectServer(callback)
47
+ end,
48
+ predict = function(self, player, ...)
49
+ local args = { ... }
50
+ receiver.invoke(player, unpack(args))
51
+ end,
52
+ }
53
+ setmetatable(method, {
54
+ __call = function(method, player, ...)
55
+ local args = { ... }
56
+ method:fire(player, unpack(args))
57
+ end,
58
+ })
59
+ return method
60
+ end
61
+ return {
62
+ createServerMethod = createServerMethod,
63
+ }