Coder Social home page Coder Social logo

roblox-aurora / rbx-net Goto Github PK

View Code? Open in Web Editor NEW
91.0 5.0 13.0 4.32 MB

Advanced multi-language networking framework for Roblox

Home Page: https://rbxnet.australis.dev/

License: MIT License

TypeScript 93.39% Lua 4.53% Shell 0.98% PowerShell 1.10%
roblox typescript networking roblox-ts luau

rbx-net's People

Contributors

boatbomber avatar dependabot[bot] avatar howmanysmall avatar iamacup avatar liamlutton avatar monzterdev avatar overhash avatar tigerqaa avatar vorlias avatar zachcurtis avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

rbx-net's Issues

TS2536: Type '"Definitions"' cannot be used to index type 'T'.

node_modules/@rbxts/net/out/definitions/Types.d.ts:62:85 - error TS2536: Type '"Definitions"' cannot be used to index type 'T'.
62 export declare type InferGroupDeclaration = T extends DeclarationNamespaceLike ? T["Definitions"] : {};

Not sure exactly why Typedoc wants to error out like that but hopefully can be resolved

[RFC] Definition API -> Builder pattern?

I feel like the definitions API could be cleaner, perhaps instead of doing something like:

	[InventoryClientFunctionId.MoveEquippedItemToInventorySlot]: ServerAsyncFunction<
		(
			request: MoveEquippedItemToInventorySlotRequest,
		) => Serializer.NetworkResult<MoveEquippedItemToInventorySlotResponse, MoveEquippedItemToInventorySlotError>
	>([
		Net.Middleware.TypeChecking(
			t.interface({
				InventoryId: t.numberMin(0),
				SlotId: t.numberMin(0),
				EquipSlot: t.string,
			}),
		),
	]),

We could do

	[InventoryClientFunctionId.MoveEquippedItemToInventorySlot]: ServerAsyncFunction<
		(
			request: MoveEquippedItemToInventorySlotRequest,
		) => Serializer.NetworkResult<MoveEquippedItemToInventorySlotResponse, MoveEquippedItemToInventorySlotError>
	>().WithMiddleware([
		Net.Middleware.TypeChecking(
			t.interface({
				InventoryId: t.numberMin(0),
				SlotId: t.numberMin(0),
				EquipSlot: t.string,
			}),
		),
	]),

Could simplify this further for built-in middleware, such as .WithTypeChecking(...types) and .WithRateLimit(options)

	[InventoryClientFunctionId.MoveEquippedItemToInventorySlot]: ServerAsyncFunction<
		(
			request: MoveEquippedItemToInventorySlotRequest,
		) => Serializer.NetworkResult<MoveEquippedItemToInventorySlotResponse, MoveEquippedItemToInventorySlotError>
	>().WithTypeChecking(
		t.interface({
			InventoryId: t.numberMin(0),
			SlotId: t.numberMin(0),
			EquipSlot: t.string,
		}),
	),

This could play well with #62.

Connecting a running game to a rojo server deletes events

Problem

When a game is running and calls Net.CreateDefinitions then Events are created under the net.out._NetManaged Instance

When starting a rojo server using a "$path" to load dependencies including rbx-net, the rojo server creates a DataModel with a net.out Instance without the events, as it only knows about what is on the filesystem.

If I attempt to connect a running game to that running rojo server using the rojo plugin, the plugin(?) will overwrite the runtime Instances currently in the game with the ones the server knows about. This removes the Events created by Net.CreateDefinitions.

Then event handlers in the game no longer work.

Workaround

When go into my dependency tree and add a file net/out/init.meta.json with contents

{"ignoreUnknownInstances": true}

the previous setup will keep the Events created by Net.CreateDefinitions, as rojo will ignore the _NetManaged Instance when updating. Then I can use the rewire library to hot reload code as desired.

Potential Fix

Adding this file to the repo might be a solution, but I have not given proper consideration to the ramifications of leaving old events around, and how such a choice could conflict with the intentional design decision mentioned in #78.

Deferred events causes remotes to not be found in Studio

Here's a quick example:

// main.client.ts
import { Remotes } from "shared/remotes";
const PrintMessage = Remotes.Client.Get("PrintMessage");
PrintMessage.SendToServer("Hello there!");
// remotes.ts
import Net from "@rbxts/net";
export const Remotes = Net.Definitions.Create({
	PrintMessage: Net.Definitions.ClientToServerEvent<[message: string]>(),
});
// main.client.ts
import { Remotes } from "shared/remotes";
const PrintMessage = Remotes.Server.Create("PrintMessage");
PrintMessage.Connect((player, message) => {
	print(`Server recieved message: ${message} from player: ${player}`);
});

With Workspace.SignalBehavior set to Immediate, the server prints Server recieved message: Hello there! from player: Player as expected. However, with Workspace.SignalBehavior set to Deferred, the client might throw the following error:
ReplicatedStorage.rbxts_include.node_modules.net.out.internal:188: Could not find Remote of type RemoteEvent called "PrintMessage"

Argument of type 'string' is not assignable to parameter of type 'never'.ts(2345)

I am not able to get my definitions type correctly and since the usage is missing for rbxts(only luau) in the docs I'm unsure on how to fix it.

Remotes.ts

import Net, { Definitions } from '@rbxts/net';
import type { SerializedCharacter } from '../types/Serialized/SerializedCharacter';

const Remotes = Net.CreateDefinitions({
    GetCharacters: Definitions.ServerFunction<(player: Player) => SerializedCharacter[]>()
});

export = Remotes;

main.server.ts

import Remotes from 'shared/Remotes';
import type { SerializedCharacter } from '../types/Serialized/SerializedCharacter';

Remotes.Server.OnFunction('GetCharacters',() => {

})

My types are not resolving and if I'm meant to build the types myself I did it like this though I could of done it wrong.

type CharSelectRemoteDeclarations = {
    [key: string]: DeclarationLike | DeclarationNamespaceLike;
    GetCharacters: FunctionDeclaration<[player: Player],SerializedCharacter[]>
};

const Remotes = Net.CreateDefinitions<CharSelectRemoteDeclarations>({
    GetCharacters: Definitions.ServerFunction<(player: Player) => SerializedCharacter[]>()
});

Server definitions should automatically generate remotes on server when accessed

At the moment remotes need to be manually created on the server for them to be accessible on the client.

This may lead to an issue where you can see that a remote is accessible on a client, but it hasn't been created on the server. This would fix said issue by ensuring the remote is at least created, even if it's not hooked into yet.

Planned removal of ServerFunction.CallPlayerAsync

Even though the rbx-net way of doing it is asynchronous, it may never actually resolve or reject the promise (yield forever) due to how RemoteFunctions work. This can be done by exploiters to wreck havoc on your game. Enough of these promises being created could create unnecessary memory usage and that's an issue that needs to be addressed.

What kinds of use-cases are there for ServerFunction.CallPlayerAsync that people have? I wish to know before I consider actually removing this function.

It will otherwise be removed soon in the next update.

Unable to create ServerFunctions within namespaces

I've noticed you cannot create ServerFunctions within namespaces. It'll throw a type error:

TypeError: Type '{ SpawnUnit: ServerFunctionDefinition }' could not be converted into '{| [string]: ClientAsyncFunctionDefinition | ClientToServerEventDefinition | ServerAsyncFunctionDefinition | ServerToClientEventDefinition |}'
caused by:
  Property 'SpawnUnit' is not compatible. Type 'ClientAsyncFunctionDefinition | ClientToServerEventDefinition | ServerAsyncFunctionDefinition | ServerToClientEventDefinition' could not be converted into 'ServerFunctionDefinition'
caused by:
  Not all union options are compatible. Table type 'ServerToClientEventDefinition' not compatible with type 'ServerFunctionDefinition' because the former has extra field '__nominal_ServerToClientEventDefinition'

Net v2.0.0

Remotes

  • ServerEvent (v2)
    • Middleware Support
    • Contextual events (possibly) - e.g. send only, receive only. (Possibly just type wizardy)
  • ServerFunction (v2)
    • Make use ServerAsyncFunction or remove entirely.
  • ServerAsyncFunction (v2)
    • Middleware Support

Middlewares

  • Type Guard Middleware
  • Rate Limit Middleware
  • Caching Middleware?
  • Logging Middleware?

Serialization

Serialization/Deserialization of objects in RbxNet is an important use case I want to eventually cover.

This would probably involve a slight overhaul of the remote objects used by Net to accompany the ability for functions to serialize values.

The idea would be to have a member Serialize(), then a static deserialize() on the object. It's possible Net could implicitly convert this before sending and when receiving by checking for objects.

Implicit option

  • Net.Serialization.AddSerializableClass(MyClass) which:
  • Would check for an object that inherits MyClass - should have member Serialize and static deserialize.
  • When calling a invoking function (e.g. SendToPlayer) it should look through the arguments and serialize any applicable objects.
  • When recieving, it should check for the serialized representation, then deserialize back to the object.

Serialized representation would be something akin to {"ClassName": "MyClass", "Value": SerializedObjectValue}.

This would also probably be something that gets only enabled if there are actually serializable classes added.

Explicit option

Would involve the remote objects themselves. I am currently thinking up the API idea for this.

Net v4.0

  • New builder API (#63)
    • Requires Type Validation
    • Custom Serialization Handling (custom validation built-in to that too)
  • Unreliable Remotes (#90)

Deprecate Throttled classes in favour of making them part of the base classes

Since both NetServerEvent and NetServerFunction both already have custom callback mechanisms to handle the type checker, the throttling can now be part of that.

Simply put for example

const myThrottledEvent = new Net.ServerThrottledEvent("Test", 10);

would be replaced with

const myThrottledEvent = new Net.ServerEvent("Test");
myThrottledEvent.SetRateLimit(10);

Eventually in the future they will be removed. For now I will be putting warnings in place.

Attempt to call a nil value when Net.CreateDefinitions

this is my Remotes moduleScript in replicated storage

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Net = require(ReplicatedStorage:WaitForChild("build.rbxnet.luau"))

local Remotes = Net.CreateDefinitions({
	Ping = Net.Definitions.ServerFunction({
		Net.Middleware.RateLimit({
			MaxRequestsPerMinute = 30
		})
	}),
})

return Remotes

The error says it all, line 5 attempt to call a nil value
Screen Shot 2022-05-30 at 9 36 09 PM

this is the module in replicated storage

Explicit definitions API overhaul

Deprecate Net.Definitions.Event for Net.Definitions.ServerEvent, Net.Definitions.ClientEvent.

The difference here is

ServerEvent - An event fired by the server and received by a client.
ClientEvent - An event fired by the client and recieved by the server.

The typings are updated so

A ServerEvent grabbed on the server can only fire, and on the client can only recieve.
A ClientEvent on the server can only recieve and on the client can only fire.

This is only a typing difference, behaviorally for Luau it would not matter.

I'm not sure on the naming schemes here though. Are they too ambiguous? what would work better?

[Docs] Custom Middleware - Example of basic Middleware, Middleware with options

basic:

import { Definitions, Middleware } from "@rbxts/net";

export const RateLimitSet = new Set<number>();

export const RateLimit: Middleware = (nextMiddleware) => {
    return (sender, ...args) => {
        if (!RateLimitSet.has(sender.UserId)) {
            RateLimitSet.add(sender.UserId);
            return nextMiddleware(sender, ...args);
        }
    };
};


const def = Definitions.Create({
	Test: Definitions.ServerAsyncFunction([RateLimit]),
})

[compiled]

wrapped:

import { Definitions, Middleware } from "@rbxts/net";

export const RateLimitSet = new Set<number>();

export function createRateLimiter(): Middleware {
	return (nextMiddleware) => {
		return (sender, ...args) => {
			if (!RateLimitSet.has(sender.UserId)) {
				RateLimitSet.add(sender.UserId);
				return nextMiddleware(sender, ...args);
			}
		};
	};
}


const def = Definitions.Create({
	Test: Definitions.ServerAsyncFunction([createRateLimiter()]),
})

[compiled]

Both use cases need to be covered, so that there's no confusion around this. Second example should show an example of passing your own options to change the mw behaviour.

Why is my Remotes.Server.OnFunction complaining about Argument of type 'string' is not assignable to parameter of type 'never'?

Remotes.ts:

import Net, { Definitions } from '@rbxts/net';
import type { SerializedCharacter } from '../types/Serialized/SerializedCharacter';

const Remotes = Net.CreateDefinitions({
    GetCharacters: Definitions.ServerFunction<(player: Player) => SerializedCharacter[]>()
});

export = Remotes;

main.server.ts:

import Remotes from 'shared/Remotes';
import type { SerializedCharacter } from '../types/Serialized/SerializedCharacter';

Remotes.Server.OnFunction('GetCharacters',(player: Player) => {
    return [];
});

image_2023-12-10_070241897

image_2023-12-10_070342989

Compile time _NetManaged folder content

Trying to solve the problem described in #78.
Currently, all networking objects are created when code is run from the definitions object
Not sure this can be done with typescript - to create files from definitions object with typescript transformer in compile time.
But surely we can create separate files and add transform to that?

For example(not actual implementation):
fileName: toggleCampaignStartButton.ts

@Definitions.ServerToClientEvent
interface {
   show: boolean;
}

Namespaced remotes created incorrectly

Version: 3.0.0

Code:

import Net, { Definitions as def } from "@rbxts/net";

export = Net.CreateDefinitions({
    initialize: def.ServerAsyncFunction<() => boolean>(),

    realm: def.Namespace({
        subscribe: def.ServerToClientEvent<[realm: string]>(),
        unsubscribe: def.ServerToClientEvent<[realm: string]>(),
    }),
});

Produces:
image

[RFC] Compiler Transformer for generating runtime typecheck middleware

Currently something like Flamework has an advantage over RbxNet with automatically generating runtime type checking.

We could

  • Implement the transformer, it goes through a definitions & namespaces and add the type checking middleware.
  • This would likely require a redesign of the definitions API, but might allow much more flexibility that way anyway.

Client lockup hard to debug

Experiencing a lockup when using this lib in the following scenario:

shared/netMessages.ts has a defintion for a ServerToClientEvent
client/homeGui.client.ts has a Remotes.Client.Get() for that same event

I forgot to implement any server side Remotes.Server.Create() for this event. So that was my mistake.

But in this scenario, my app silently fails to load, never throws an error, and sits there doing nothing.

To track it down I had to add print() statements in all the chain of imports until I facepalmed when I discovered the unconnected event.

Previously, I have seen an error message from rbx-net in a similar situation, but I think it was actually the opposite, where the Server had tried to send an event, and Client code was not yet written for that. It has a timeout that waits a number of seconds before displaying a warning. Similar behavior in the above-mentioned opposite bug would have been very much appreciated.

Clean up definitions

Clean up all the definition types, remove all the excess properties etc.

This will unfortunately mean the removal of Event, Function and AsyncFunction but will mean there isn't weird "fake" props on definition function returned values.

The updated definition types should just have the readonly unique symbols to keep them nominal.

Definitions Namespacing

I have an idea for the Net.Definitions. For a large project, there may be a crap-load of remotes in a definition.

The idea would be you'd be able to group remotes by feature, which would
A) Visually organize the definitions in larger projects
B) Categorize related remotes in the API

Example API

const Remotes = Net.Definitions.Create({
     FeatureA: Net.Definitions.Namespace({
        DoSomethingWithFeatureA: Net.Definitions.Event(),
        DoAnotherThingWithFeatureA: Net.Definitions.AsyncFunction()
     }),
    FeatureB: Net.Definitions.Namespace({
        DoSomethingWithFeatureB: Net.Definitions.Function()
        DoAnotherThingWithFeatureB: Net.Definitions.Event()
    })
})

Then if I wanted all the remotes relating to FeatureA on the server -

const FeatureA = Remotes.Server.GetNamespace("FeatureA");
const DoSomethingWithFeatureA = FeatureA.Create("DoSomethingWithFeatureA");
const DoAnotherThingWithFeatureA = FeatureA.Create("DoAnotherThingWithFeatureA");

Then if I wanted all the remotes relating to FeatureB on the client -

const FeatureB = Remotes.Client.GetNamespace("FeatureB");
const DoSomethingWithFeatureB = FeatureB.Get("DoSomethingWithFeatureB");
const DoAnotherThingWithFeatureB = FeatureB.Get("DoAnotherThingWithFeatureB");

[BUG] .SetConfiguration("ServerThrottleMessage") sets throttleResetTimer to a string.

RbxNet version: 1.2.6

export function SetConfiguration<K extends keyof RbxNetConfigItem>(key: K, value: RbxNetConfigItem[K]) {
	assert(IS_SERVER, "Cannot set configuration on client!");
	if (key === "ServerThrottleMessage") { // should be "ServerThrottleResetTimer"
		throttleResetTimer = value as number;
	} else if (key === "ServerThrottleMessage") {
		rateLimitReachedMessage = value as string;
	} else if (key === "EnableDebugMessages") {
		DebugEnabled = value as boolean;
	}
}

As you can see, ServerThrottleMessage is duplicated twice and sets both the rateLimitReachedMessage and the throttleResetTimer to the value (string) passed.

Rate limiting features

For requests that use data stores or other APIs with rate limits, it would be useful to be able to implement throttles and rate limits on the events and functions using those APIs. For example, you could rate limit a RemoteFunction that gets profile data from data stores so that there's only 2 requests per 10 seconds, and other requests can be queued or dropped.

How to wait for a Promise in a RemoteFunction callback?

Background info: I'm using rbx-net with roblox-ts to create a turn-based game. A network design pattern that feels idiomatic for the game is to have a RemoteFunction named "AskPlay" that waits for the player to give input and then resolves a Promise. On the server, this is easy to do, as CallPlayerAsync returns a Promise.

However, I can't set the client callback to be an async function, as async functions return a Promise that rbx-net doesn't wait for to be resolved. As a result, I can't await for the player to make their choice. So ideally, I would like my code to look like this:

        askPlay.setCallback(async () => {
            let localPlayer = state.LocalPlayer()
            let playedCards = await this.AskPlay()

            localPlayer.Hand!.RemoveCards(playedCards.Cards)

            return playedCards.Cards.map((card) => localPlayer.Hand!.Cards.indexOf(card))
        })

Here this.AskPlay() returns a Promise that is resolved upon user input. Could it be that this design isn't in line with how rbx-net is designed to work?

Infinite yield error

Using v1.1.0

import Net from "@rbxts/net";
let exampleOne = Net.CreateEvent("NameOfEvent");

Yields

21:31:28.973 - Infinite yield possible on 'ReplicatedStorage.rbxts_include.node_modules.net.out:WaitForChild("Instance")'
21:31:28.974 - Stack Begin
21:31:28.974 - Script 'ReplicatedStorage.rbxts_include.RuntimeLib', Line 91 - field import
21:31:28.974 - Script 'ReplicatedStorage.rbxts_include.node_modules.net.out', Line 7
21:31:28.975 - Stack End

Roblox studio 0.401.0.338533 (Mac)

ps: version 1.1.2 does say "Loaded rbx-net v1.0.13"

[BUG] (v2.x) Throttle counters are not cleared every minute

RbxNet version: 2.0.0-alpha.5
RobloxTS version: 1.0.0-beta.11

Describe the bug
Throttle counters are not cleared every minute so the RateLimiter middleware will never reset its throttle counters making the maxRequestsPerMinute a max requests limit where players cannot call the event at all after calling it above the maxRequestsPerMinute limit.

Expected behavior
Throttle counters should be cleared every minute.

Troubles with luau types

[Edit]: Also lack of BidirectionalEvent, OnEvent and OnFunction

given this

--!strict
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Net = require(ReplicatedStorage.Packages.Net)

return Net.CreateDefinitions({
    Cuffs = Net.Definitions.Namespace({}), --> error here
})
TypeError: Type '{ Cuffs: {ClientAsyncFunctionDefinition | ClientToServerEventDefinition | ServerAsyncFunctionDefinition | ServerFunctionDefinition | ServerToClientEventDefinition} }' could not be converted into 'RemoteDefinitions'
caused by:
  Property 'Cuffs' is not compatible. Type 'ClientAsyncFunctionDefinition | ClientToServerEventDefinition | ServerAsyncFunctionDefinition | ServerFunctionDefinition | ServerToClientEventDefinition' could not be converted into '{ClientAsyncFunctionDefinition | ClientToServerEventDefinition | ServerAsyncFunctionDefinition | ServerFunctionDefinition | ServerToClientEventDefinition}'
caused by:
  Not all union options are compatible. Table type 'ServerToClientEventDefinition' not compatible with type '{ClientAsyncFunctionDefinition | ClientToServerEventDefinition | ServerAsyncFunctionDefinition | ServerFunctionDefinition | ServerToClientEventDefinition}' because the former has extra field '__nominal_ServerToClientEventDefinition'Luau[1000](https://luau-lang.org/typecheck)

currently using luau-lsp

TS2515: Non-abstract class does not implement inherited abstract member from class

node_modules/@rbxts/net/out/server/ServerFunction.d.ts:5:22 - error TS2515: Non-abstract class 'ServerFunction<CallbackArgs, Returns>' does not implement inherited abstract member 'GetInstance' from class 'MiddlewareFunction'.
5 export default class ServerFunction<CallbackArgs extends ReadonlyArray = Array, Returns extends unknown = unknown> extends MiddlewareFunction {

Not sure exactly why Typedoc wants to error out like that but hopefully can be resolved.

Dropped requests from middleware remain in 'Started' state for AsyncFunctions.

When calling the server with a ServerAsyncFunction, there's a possibility that your middleware may not propagate your request and finish it. For a client that is awaiting the promise's fate, the promise never settles.

This can be reproduced by making a middleware that rejects all requests and hooking a :finally() method to your promise. It will never reach it.

Integer keys turn to string

I sent a message from Server to client with array of point data. It's just a normal array with integer keys.

When client received the array, the keys are turned into string. It causes bad problems with iteration.

Here's what server sent:

  16:35:35.624  firing AllP with  ▼  {
                    [1] =  ▼  {
                       ["bs"] =  ▼  {
                          ["ct"] = 32,
                          ["fi"] = -1,
                          ["li"] = -1,
                          ["pts"] =  ▼  {
                             [0] =  ▼  {
                                ["idx"] = -1,
                                ["px"] = -184,
                                ["pz"] = -149,
                                ["stamp"] = 1643733334.642958,
                                ["vx"] = 34.1944465637207,
                                ["vz"] = 27.69006729125977
                             }
                          }
                       },
                       ["color"] = 0.709804, 0, 0.0784314,
                       ["id"] = 2031724732,
                       ["initCFrame"] = -184, 8, -149, -0.629319727, -0, -0.777146518, -0, 1, -0, 0.777146518, 0, -0.629319727,
                       ["wormLength"] = 1
                    }
                 }  -  Server - serverPlayerManager:102

Notice the path to the first player's first point is [1].bs.pts[0] - and the 0 is an integer.

Here's what client received:

  16:35:35.643  client: AllP recd is  ▼  {
                    [1] =  ▼  {
                       ["bs"] =  ▼  {
                          ["ct"] = 32,
                          ["fi"] = -1,
                          ["li"] = -1,
                          ["pts"] =  ▼  {
                             ["0"] =  ▼  {
                                ["idx"] = -1,
                                ["px"] = -184,
                                ["pz"] = -149,
                                ["stamp"] = 1643733334.642958,
                                ["vx"] = 34.1944465637207,
                                ["vz"] = 27.69006729125977
                             }
                          }
                       },
                       ["color"] = 0.709804, 0, 0.0784314,
                       ["id"] = 2031724732,
                       ["initCFrame"] = -184, 8, -149, -0.62928617, 0, -0.777173758, 0, 1, 0, 0.777173758, 0, -0.62928617,
                       ["wormLength"] = 1
                    }
                 }  -  Client - clientPlayerManager:80

the path to the first player's first point is now [1].bs.pts["0"] - and the "0" has turned to a string.

The topmost level was recognized as an array and interpreted correctly. The nested array was the one with the problem.

Here is corresponding type definition of IPlayerInit structure. Payload is array of this. Nested inside is bs: IBufferState with array of IBufferPoint pts

export interface IBufferPoint {
    idx: number;
    stamp: number;
    px: number;
    pz: number;
    vx: number;
    vz: number;
}

export interface IBufferState {
    fi: number;
    li: number;
    ct: number;
    pts: IBufferPoint[];
}

export interface IPlayerInit {
    id: number;
    color: Color3;
    initCFrame: CFrame;
    wormLength: number;
    bs: IBufferState;
}

Unreliable Remotes

image-23.png

Add support for unreliable events through definitions API when released.

Add configurable location for _NetManaged folder.

Currently, definitions are created into this library source code:
Screenshot 2022-09-08 at 11 36 36

Can we make Parent configurable?

const location = script.Parent!;

Would like that _NetManaged folder would be directly under ReplicatedStorage
ReplicatedStorage->_NetManaged->toggleCampaignStartButton

Little bit of background:

I want to implement code Hot Reloading and current problem is that _NetManaged folders gets removed, if I run Rojo and files are synced.

[RFC] [Server|Client]MessagingEvent Definitions API

ServerMessagingEvent would allow sending messages cross-server to the specified player clients in any server with the matching user id.

This technically existed in 2.1.x, however as it was an undocumented (broken) API I want to revisit it.

  • SendToAllServers and SendToServer is essentially the same in ExperienceBroadcastEvent.
  • The only difference here is the specific SendToPlayer(userId, ...) and `SendToPlayers(userIds[], ...)

ClientMessagingEvent would be the client counter-part listening to this.

I am not sure if this API is useful? It could be for something like guild chat, perhaps :?

There's still the issue here of the client not being able to send these messages directly though so maybe it's better to just leave this sort of stuff as more manual. I don't know if I feel like adding that capability unless there's an explicit handler for that the user must specify somehow.

Cannot use namespaces

I'm using luau and it throws a type error, seems like isn't published to wally

current version in wally: 3.0.1
current project version: 3.0.3

Global middleware

Right now there is no way to make a piece of middleware apply to all remotes in a Definition. This would be useful for applications such as logging or analytics; I want to track how much data is going through remotes and at what frequency in production.

Maybe when creating a Definition you could also pass in an array of Middleware as a second parameter. Something like the following:

Net.Definitions.Create({
    SomeEvent = Net.Definitions.Event()
}, [
    Net.Definitions.ReadonlyMiddleware((remoteName, remoteData) => {
        // Do something
    })
])

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.