roblox-aurora / rbx-net

Advanced multi-language networking framework for Roblox
https://rbxnet.australis.dev/
MIT License
94 stars 12 forks source link

Integer keys turn to string #64

Closed FirstVertex closed 2 years ago

FirstVertex commented 2 years ago

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;
}
FirstVertex commented 2 years ago

reopening, as i am still seeing this behavior after further debugging and isolation. please do investigate this, and i apologize for prematurely closing it.

FirstVertex commented 2 years ago

Remote definition and usage

const Remotes = Net.Definitions.Create({
    AllP: Definitions.ServerToClientEvent<[allPlayers: IPlayerInit[]]>()
});

Server fire

AllPEvent.SendToPlayer(player, allPlayersInit);

Client receive

AllPEvent.Connect((allPlayers: IPlayerInit[]) => { 
    print('client: ALLP recd is', allPlayers)
});
OverHash commented 2 years ago

How did you get an array with zero indexes? roblox-ts should be starting from 1. The issue here is that JSON encoding your table produces string keys. I don't think Net has a way around this

FirstVertex commented 2 years ago

hello, this is a message to transfer the state of an infinite Queue, as discussed on this page from Lua handbook https://www.lua.org/pil/11.4.html From this I use pushLeft() to insert new points to the buffer, and popRight() to expire old ones Lua handbook assures me it is ok to use 0 and negative numbers for indexing table. this represents a stream of points emitting from player's motion.

FirstVertex commented 2 years ago

i was able to isolate this to arrays whose indices do not begin with 1. any way to fix that? i have a separate message involving this exact same sub structure who sends points that begin with index 1, and the key received is int. other messages with the same structure who use a negative or zero key to start, have their int keys stringified.

it is not sparse array. the indices sent are always sequential and grouped together, although potentially negative. ipairs to iterate it works.

FirstVertex commented 2 years ago

closing as an issue with my code. i need to change the transmitted DTO to be normalized to an array with positive indices that start with 1 and can be iterated. then the received array always has the correct numeric keys.

Vorlias commented 2 years ago

Yeah this is an issue with how JSON is encoded. Unfortunately not something I can fix.