@dcl/sdk 7.29.1-36863326504.commit-aa54c50 → 7.30.1-37783952461.commit-52fa56c
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.
- package/explorer-ui/index.d.ts +118 -0
- package/explorer-ui/index.js +235 -0
- package/internal/transports/rendererTransport.js +2 -5
- package/network/binary-message-bus.d.ts +3 -6
- package/network/binary-message-bus.js +5 -9
- package/network/index.d.ts +2 -8
- package/network/index.js +3 -16
- package/network/message-bus-sync.d.ts +3 -16
- package/network/message-bus-sync.js +103 -164
- package/network/state.js +5 -3
- package/package.json +6 -6
- package/src/explorer-ui/index.ts +398 -0
- package/src/internal/transports/rendererTransport.ts +1 -4
- package/src/network/binary-message-bus.ts +4 -9
- package/src/network/index.ts +3 -40
- package/src/network/message-bus-sync.ts +112 -180
- package/src/network/state.ts +4 -3
- package/atom.d.ts +0 -19
- package/atom.js +0 -83
- package/future.d.ts +0 -8
- package/future.js +0 -26
- package/network/chunking.d.ts +0 -5
- package/network/chunking.js +0 -38
- package/network/events/implementation.d.ts +0 -93
- package/network/events/implementation.js +0 -221
- package/network/events/index.d.ts +0 -42
- package/network/events/index.js +0 -43
- package/network/events/protocol.d.ts +0 -27
- package/network/events/protocol.js +0 -66
- package/network/events/registry.d.ts +0 -8
- package/network/events/registry.js +0 -3
- package/network/server/index.d.ts +0 -14
- package/network/server/index.js +0 -256
- package/network/server/utils.d.ts +0 -18
- package/network/server/utils.js +0 -135
- package/server/env-var.d.ts +0 -15
- package/server/env-var.js +0 -31
- package/server/index.d.ts +0 -2
- package/server/index.js +0 -3
- package/server/storage/constants.d.ts +0 -80
- package/server/storage/constants.js +0 -19
- package/server/storage/error-message.d.ts +0 -1
- package/server/storage/error-message.js +0 -9
- package/server/storage/index.d.ts +0 -54
- package/server/storage/index.js +0 -60
- package/server/storage/player.d.ts +0 -60
- package/server/storage/player.js +0 -244
- package/server/storage/scene.d.ts +0 -55
- package/server/storage/scene.js +0 -232
- package/server/storage/serialize.d.ts +0 -1
- package/server/storage/serialize.js +0 -135
- package/server/storage/value-cache.d.ts +0 -1
- package/server/storage/value-cache.js +0 -67
- package/server/storage/write-queue.d.ts +0 -1
- package/server/storage/write-queue.js +0 -113
- package/server/storage-url.d.ts +0 -13
- package/server/storage-url.js +0 -42
- package/server/utils.d.ts +0 -35
- package/server/utils.js +0 -69
- package/src/atom.ts +0 -98
- package/src/future.ts +0 -38
- package/src/network/chunking.ts +0 -45
- package/src/network/events/implementation.ts +0 -271
- package/src/network/events/index.ts +0 -48
- package/src/network/events/protocol.ts +0 -94
- package/src/network/events/registry.ts +0 -18
- package/src/network/server/index.ts +0 -341
- package/src/network/server/utils.ts +0 -189
- package/src/server/env-var.ts +0 -36
- package/src/server/index.ts +0 -12
- package/src/server/storage/constants.ts +0 -112
- package/src/server/storage/error-message.ts +0 -8
- package/src/server/storage/index.ts +0 -83
- package/src/server/storage/player.ts +0 -345
- package/src/server/storage/scene.ts +0 -324
- package/src/server/storage/serialize.ts +0 -132
- package/src/server/storage/value-cache.ts +0 -119
- package/src/server/storage/write-queue.ts +0 -174
- package/src/server/storage-url.ts +0 -49
- package/src/server/utils.ts +0 -83
|
@@ -1,53 +1,27 @@
|
|
|
1
|
-
import { IEngine, Transport, RealmInfo } from '@dcl/ecs'
|
|
2
|
-
import type
|
|
1
|
+
import { IEngine, Transport, RealmInfo, PlayerIdentityData } from '@dcl/ecs'
|
|
2
|
+
import { type SendBinaryRequest, type SendBinaryResponse } from '~system/CommunicationsController'
|
|
3
3
|
|
|
4
4
|
import { syncFilter } from './filter'
|
|
5
5
|
import { engineToCrdt } from './state'
|
|
6
|
-
import { BinaryMessageBus, CommsMessage } from './binary-message-bus'
|
|
6
|
+
import { BinaryMessageBus, CommsMessage, decodeString, encodeString } from './binary-message-bus'
|
|
7
7
|
import { fetchProfile } from './utils'
|
|
8
8
|
import { entityUtils } from './entities'
|
|
9
|
-
import {
|
|
10
|
-
import type { GetUserDataRequest, GetUserDataResponse } from '~system/UserIdentity'
|
|
9
|
+
import { GetUserDataRequest, GetUserDataResponse } from '~system/UserIdentity'
|
|
11
10
|
import { definePlayerHelper } from '../players'
|
|
12
11
|
import { serializeCrdtMessages } from '../internal/transports/logger'
|
|
13
|
-
import { IsServerRequest, IsServerResponse } from '~system/EngineApi'
|
|
14
|
-
import { Atom } from '../atom'
|
|
15
|
-
import { setGlobalRoom, Room } from './events/implementation'
|
|
16
12
|
|
|
17
13
|
export type IProfile = { networkId: number; userId: string }
|
|
18
14
|
// user that we asked for the inital crdt state
|
|
19
|
-
export const AUTH_SERVER_PEER_ID = 'authoritative-server'
|
|
20
|
-
export const DEBUG_NETWORK_MESSAGES = () => (globalThis as any).DEBUG_NETWORK_MESSAGES ?? false
|
|
21
|
-
|
|
22
|
-
// Test environment detection without 'as any'
|
|
23
|
-
const isTestEnvironment = (): boolean => {
|
|
24
|
-
try {
|
|
25
|
-
if (typeof globalThis === 'undefined') return false
|
|
26
|
-
const globalWithProcess = globalThis as unknown as { process?: { env?: { NODE_ENV?: string } } }
|
|
27
|
-
return globalWithProcess.process?.env?.NODE_ENV === 'test'
|
|
28
|
-
} catch {
|
|
29
|
-
return false
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
15
|
export function addSyncTransport(
|
|
34
16
|
engine: IEngine,
|
|
35
17
|
sendBinary: (msg: SendBinaryRequest) => Promise<SendBinaryResponse>,
|
|
36
|
-
getUserData: (value: GetUserDataRequest) => Promise<GetUserDataResponse
|
|
37
|
-
isServerFn: (request: IsServerRequest) => Promise<IsServerResponse>,
|
|
38
|
-
name: string
|
|
18
|
+
getUserData: (value: GetUserDataRequest) => Promise<GetUserDataResponse>
|
|
39
19
|
) {
|
|
20
|
+
const DEBUG_NETWORK_MESSAGES = () => (globalThis as any).DEBUG_NETWORK_MESSAGES ?? false
|
|
40
21
|
// Profile Info
|
|
41
22
|
const myProfile: IProfile = {} as IProfile
|
|
42
23
|
fetchProfile(myProfile!, getUserData)
|
|
43
24
|
|
|
44
|
-
const isServerAtom = Atom<boolean>()
|
|
45
|
-
const isRoomReadyAtom = Atom<boolean>(false)
|
|
46
|
-
|
|
47
|
-
void isServerFn({}).then(($: IsServerResponse) => {
|
|
48
|
-
return isServerAtom.swap(!!$.isServer)
|
|
49
|
-
})
|
|
50
|
-
|
|
51
25
|
// Entity utils
|
|
52
26
|
const entityDefinitions = entityUtils(engine, myProfile)
|
|
53
27
|
|
|
@@ -66,194 +40,108 @@ export function addSyncTransport(
|
|
|
66
40
|
const players = definePlayerHelper(engine)
|
|
67
41
|
|
|
68
42
|
let stateIsSyncronized = false
|
|
43
|
+
let transportInitialzed = false
|
|
69
44
|
|
|
70
|
-
/**
|
|
71
|
-
* We need to wait till 2 ticks that is when the engine is ready to send new messages.
|
|
72
|
-
* The first tick is for the client engine processing the CRDT messages,
|
|
73
|
-
* and the second one are the messages created by the main() function.
|
|
74
|
-
* So to avoid sending those messages, that all the clients have, through the network we put this validation here.
|
|
75
|
-
*/
|
|
76
|
-
let tick = 0
|
|
77
|
-
const TRANSPORT_INITIALIZED_NUMBER = isTestEnvironment() ? 0 : 2
|
|
78
45
|
// Add Sync Transport
|
|
79
46
|
const transport: Transport = {
|
|
80
47
|
filter: syncFilter(engine),
|
|
81
48
|
send: async (messages) => {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (message.byteLength) {
|
|
49
|
+
for (const message of [messages].flat()) {
|
|
50
|
+
if (message.byteLength && transportInitialzed) {
|
|
85
51
|
DEBUG_NETWORK_MESSAGES() &&
|
|
86
52
|
console.log(...Array.from(serializeCrdtMessages('[NetworkMessage sent]:', message, engine)))
|
|
87
|
-
|
|
88
|
-
// Convert regular messages to network messages for broadcasting with chunking
|
|
89
|
-
for (const chunk of serverValidator.convertRegularToNetworkMessage(message)) {
|
|
90
|
-
binaryMessageBus.emit(CommsMessage.CRDT, chunk)
|
|
91
|
-
}
|
|
53
|
+
binaryMessageBus.emit(CommsMessage.CRDT, message)
|
|
92
54
|
}
|
|
93
55
|
}
|
|
94
56
|
const peerMessages = getMessagesToSend()
|
|
57
|
+
let totalSize = 0
|
|
58
|
+
for (const message of peerMessages) {
|
|
59
|
+
for (const data of message.data) {
|
|
60
|
+
totalSize += data.byteLength
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (totalSize) {
|
|
64
|
+
DEBUG_NETWORK_MESSAGES() && console.log('Sending network messages: ', totalSize / 1024, 'KB')
|
|
65
|
+
}
|
|
95
66
|
const response = await sendBinary({ data: [], peerData: peerMessages })
|
|
96
67
|
binaryMessageBus.__processMessages(response.data)
|
|
68
|
+
transportInitialzed = true
|
|
97
69
|
},
|
|
98
|
-
type:
|
|
70
|
+
type: 'network'
|
|
99
71
|
}
|
|
100
|
-
|
|
101
|
-
// Server validation setup
|
|
102
|
-
const serverValidator = createServerValidator({
|
|
103
|
-
engine,
|
|
104
|
-
binaryMessageBus
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
// Initialize Event Bus with registered schemas
|
|
108
|
-
const eventBus = new Room(engine, binaryMessageBus, isServerAtom, isRoomReadyAtom)
|
|
109
|
-
|
|
110
|
-
// Set global eventBus instance
|
|
111
|
-
setGlobalRoom(eventBus)
|
|
112
|
-
|
|
113
72
|
engine.addTransport(transport)
|
|
114
73
|
// End add sync transport
|
|
115
74
|
|
|
116
75
|
// Receive & Process CRDT_STATE
|
|
117
|
-
binaryMessageBus.on(CommsMessage.
|
|
118
|
-
|
|
119
|
-
if (
|
|
120
|
-
|
|
121
|
-
DEBUG_NETWORK_MESSAGES() && console.log('[REQ_CRDT_STATE]', sender, Date.now())
|
|
122
|
-
const chunks = engineToCrdt(engine)
|
|
123
|
-
if (chunks.length === 0) {
|
|
124
|
-
DEBUG_NETWORK_MESSAGES() && console.log('[Emiting empty state:]', sender, Date.now())
|
|
125
|
-
binaryMessageBus.emit(CommsMessage.RES_CRDT_STATE, new Uint8Array(), [sender])
|
|
126
|
-
} else {
|
|
127
|
-
for (const chunk of chunks) {
|
|
128
|
-
DEBUG_NETWORK_MESSAGES() && console.log('[Emiting:]', sender, Date.now())
|
|
129
|
-
binaryMessageBus.emit(CommsMessage.RES_CRDT_STATE, chunk, [sender])
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
})
|
|
133
|
-
binaryMessageBus.on(CommsMessage.RES_CRDT_STATE, async (data, sender) => {
|
|
134
|
-
if (isServerAtom.getOrNull() || sender !== AUTH_SERVER_PEER_ID) return
|
|
135
|
-
|
|
136
|
-
requestingState = false
|
|
137
|
-
elapsedTimeSinceRequest = 0
|
|
76
|
+
binaryMessageBus.on(CommsMessage.RES_CRDT_STATE, (value) => {
|
|
77
|
+
const { sender, data } = decodeCRDTState(value)
|
|
78
|
+
if (sender !== myProfile.userId) return
|
|
138
79
|
DEBUG_NETWORK_MESSAGES() && console.log('[Processing CRDT State]', data.byteLength / 1024, 'KB')
|
|
139
|
-
|
|
140
|
-
transport.onmessage!(serverValidator.processClientMessages(data, sender))
|
|
141
|
-
}
|
|
80
|
+
transport.onmessage!(data)
|
|
142
81
|
stateIsSyncronized = true
|
|
82
|
+
})
|
|
143
83
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
84
|
+
// Answer to REQ_CRDT_STATE
|
|
85
|
+
binaryMessageBus.on(CommsMessage.REQ_CRDT_STATE, async (_, userId) => {
|
|
86
|
+
DEBUG_NETWORK_MESSAGES() && console.log(`Sending CRDT State to: ${userId}`)
|
|
87
|
+
|
|
88
|
+
for (const chunk of engineToCrdt(engine)) {
|
|
89
|
+
binaryMessageBus.emit(CommsMessage.RES_CRDT_STATE, encodeCRDTState(userId, chunk), [userId])
|
|
150
90
|
}
|
|
151
91
|
})
|
|
152
92
|
|
|
153
|
-
//
|
|
154
|
-
binaryMessageBus.on(CommsMessage.CRDT, (value
|
|
155
|
-
const isServer = isServerAtom.getOrNull()
|
|
93
|
+
// Process CRDT messages here
|
|
94
|
+
binaryMessageBus.on(CommsMessage.CRDT, (value) => {
|
|
156
95
|
DEBUG_NETWORK_MESSAGES() &&
|
|
157
|
-
console.log(
|
|
158
|
-
|
|
159
|
-
...Array.from(serializeCrdtMessages('[NetworkMessage received]:', value, engine)),
|
|
160
|
-
isServer
|
|
161
|
-
)
|
|
162
|
-
if (isServer) {
|
|
163
|
-
transport.onmessage!(serverValidator.processServerMessages(value, sender))
|
|
164
|
-
} else if (sender === AUTH_SERVER_PEER_ID) {
|
|
165
|
-
// Process network messages from server and convert to regular messages
|
|
166
|
-
transport.onmessage!(serverValidator.processClientMessages(value, sender))
|
|
167
|
-
}
|
|
96
|
+
console.log(Array.from(serializeCrdtMessages('[NetworkMessage received]:', value, engine)))
|
|
97
|
+
transport.onmessage!(value)
|
|
168
98
|
})
|
|
169
99
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
if (sender !== AUTH_SERVER_PEER_ID) return
|
|
100
|
+
async function requestState(retryCount: number = 1) {
|
|
101
|
+
let players = Array.from(engine.getEntitiesWith(PlayerIdentityData))
|
|
102
|
+
DEBUG_NETWORK_MESSAGES() && console.log(`Requesting state. Players connected: ${players.length - 1}`)
|
|
174
103
|
|
|
175
|
-
|
|
176
|
-
|
|
104
|
+
if (!RealmInfo.getOrNull(engine.RootEntity)?.isConnectedSceneRoom) {
|
|
105
|
+
DEBUG_NETWORK_MESSAGES() && console.log(`Aborting Requesting state?. Disconnected`)
|
|
106
|
+
return
|
|
107
|
+
}
|
|
177
108
|
|
|
178
|
-
|
|
179
|
-
// but with a timestamp that's guaranteed to be accepted
|
|
180
|
-
const authoritativeBuffer = serverValidator.processClientMessages(value, sender, true)
|
|
181
|
-
if (authoritativeBuffer.byteLength > 0) {
|
|
182
|
-
// Apply authoritative message through normal transport, but the server's messages
|
|
183
|
-
// should be processed as authoritative with special timestamp handling
|
|
184
|
-
transport.onmessage!(authoritativeBuffer)
|
|
109
|
+
binaryMessageBus.emit(CommsMessage.REQ_CRDT_STATE, new Uint8Array())
|
|
185
110
|
|
|
186
|
-
|
|
111
|
+
// Wait ~5s for the response.
|
|
112
|
+
await sleep(5000)
|
|
113
|
+
|
|
114
|
+
players = Array.from(engine.getEntitiesWith(PlayerIdentityData))
|
|
115
|
+
|
|
116
|
+
if (!stateIsSyncronized) {
|
|
117
|
+
if (players.length > 1 && retryCount <= 2) {
|
|
118
|
+
DEBUG_NETWORK_MESSAGES() &&
|
|
119
|
+
console.log(`Requesting state again ${retryCount} (no response). Players connected: ${players.length - 1}`)
|
|
120
|
+
void requestState(retryCount + 1)
|
|
121
|
+
} else {
|
|
122
|
+
DEBUG_NETWORK_MESSAGES() && console.log('No active players. State syncronized')
|
|
123
|
+
stateIsSyncronized = true
|
|
124
|
+
}
|
|
187
125
|
}
|
|
188
|
-
}
|
|
126
|
+
}
|
|
189
127
|
|
|
190
128
|
players.onEnterScene((player) => {
|
|
191
129
|
DEBUG_NETWORK_MESSAGES() && console.log('[onEnterScene]', player.userId)
|
|
192
|
-
if (!isServerAtom.getOrNull() && myProfile.userId === player.userId) {
|
|
193
|
-
requestState()
|
|
194
|
-
}
|
|
195
130
|
})
|
|
196
131
|
|
|
197
132
|
// Asks for the REQ_CRDT_STATE when its connected to comms
|
|
198
133
|
RealmInfo.onChange(engine.RootEntity, (value) => {
|
|
199
|
-
const isServer = isServerAtom.getOrNull()
|
|
200
|
-
|
|
201
134
|
if (!value?.isConnectedSceneRoom) {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
DEBUG_NETWORK_MESSAGES() && console.log('Disconnected from comms')
|
|
205
|
-
isRoomReadyAtom.swap(false)
|
|
206
|
-
if (!isServer) {
|
|
207
|
-
stateIsSyncronized = false
|
|
208
|
-
}
|
|
209
|
-
}
|
|
135
|
+
DEBUG_NETWORK_MESSAGES() && console.log('Disconnected from comms')
|
|
136
|
+
stateIsSyncronized = false
|
|
210
137
|
}
|
|
211
138
|
|
|
212
139
|
if (value?.isConnectedSceneRoom) {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
// For servers, mark as ready immediately when connected
|
|
216
|
-
// (servers don't need to sync state from anyone)
|
|
217
|
-
if (isServer && isRoomReadyAtom.getOrNull() === false) {
|
|
218
|
-
DEBUG_NETWORK_MESSAGES() && console.log('[isRoomReady] Server marking room as ready')
|
|
219
|
-
isRoomReadyAtom.swap(true)
|
|
220
|
-
}
|
|
221
|
-
// For clients, room will be marked ready after receiving CRDT state (above)
|
|
140
|
+
DEBUG_NETWORK_MESSAGES() && console.log('Connected to comms')
|
|
222
141
|
}
|
|
223
|
-
})
|
|
224
|
-
|
|
225
|
-
let requestingState = false
|
|
226
|
-
let elapsedTimeSinceRequest = 0
|
|
227
|
-
const STATE_REQUEST_RETRY_INTERVAL = 2.0 // seconds
|
|
228
142
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
* The thing is that when the server detects a new JOIN_PARTICIPANT on livekit room, it sends automatically the state to that peer.
|
|
232
|
-
* But in unity, it takes more time, so that message is not being delivered to the client.
|
|
233
|
-
* So instead, when we are finally connected to the room, we request the state, and then the server answers with the state :)
|
|
234
|
-
*
|
|
235
|
-
* If no response is received within 2 seconds, the request is automatically retried.
|
|
236
|
-
*/
|
|
237
|
-
function requestState() {
|
|
238
|
-
if (isServerAtom.getOrNull()) return
|
|
239
|
-
if (RealmInfo.getOrNull(engine.RootEntity)?.isConnectedSceneRoom && !requestingState) {
|
|
240
|
-
requestingState = true
|
|
241
|
-
elapsedTimeSinceRequest = 0
|
|
242
|
-
DEBUG_NETWORK_MESSAGES() && console.log('Requesting state...')
|
|
243
|
-
binaryMessageBus.emit(CommsMessage.REQ_CRDT_STATE, new Uint8Array())
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// System to retry state request if no response is received within the retry interval
|
|
248
|
-
engine.addSystem((dt: number) => {
|
|
249
|
-
if (requestingState && !stateIsSyncronized) {
|
|
250
|
-
elapsedTimeSinceRequest += dt
|
|
251
|
-
if (elapsedTimeSinceRequest >= STATE_REQUEST_RETRY_INTERVAL) {
|
|
252
|
-
DEBUG_NETWORK_MESSAGES() && console.log('State request timed out, retrying...')
|
|
253
|
-
elapsedTimeSinceRequest = 0
|
|
254
|
-
requestingState = false
|
|
255
|
-
requestState()
|
|
256
|
-
}
|
|
143
|
+
if (value?.isConnectedSceneRoom && !stateIsSyncronized) {
|
|
144
|
+
void requestState()
|
|
257
145
|
}
|
|
258
146
|
})
|
|
259
147
|
|
|
@@ -265,12 +153,56 @@ export function addSyncTransport(
|
|
|
265
153
|
return stateIsSyncronized
|
|
266
154
|
}
|
|
267
155
|
|
|
156
|
+
function sleep(ms: number) {
|
|
157
|
+
return new Promise<void>((resolve) => {
|
|
158
|
+
let timer = 0
|
|
159
|
+
function sleepSystem(dt: number) {
|
|
160
|
+
timer += dt
|
|
161
|
+
if (timer * 1000 >= ms) {
|
|
162
|
+
engine.removeSystem(sleepSystem)
|
|
163
|
+
resolve()
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
engine.addSystem(sleepSystem)
|
|
167
|
+
})
|
|
168
|
+
}
|
|
169
|
+
|
|
268
170
|
return {
|
|
269
171
|
...entityDefinitions,
|
|
270
172
|
myProfile,
|
|
271
|
-
isStateSyncronized
|
|
272
|
-
binaryMessageBus,
|
|
273
|
-
eventBus,
|
|
274
|
-
isRoomReadyAtom
|
|
173
|
+
isStateSyncronized
|
|
275
174
|
}
|
|
276
175
|
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Messages Protocol Encoding
|
|
179
|
+
*
|
|
180
|
+
* CRDT: Plain Uint8Array
|
|
181
|
+
*
|
|
182
|
+
* CRDT_STATE_RES { sender: string, data: Uint8Array}
|
|
183
|
+
*/
|
|
184
|
+
function decodeCRDTState(data: Uint8Array) {
|
|
185
|
+
let offset = 0
|
|
186
|
+
const r = new Uint8Array(data)
|
|
187
|
+
const view = new DataView(r.buffer)
|
|
188
|
+
const senderLength = view.getUint8(offset)
|
|
189
|
+
offset += 1
|
|
190
|
+
const sender = decodeString(data.subarray(1, senderLength + 1))
|
|
191
|
+
offset += senderLength
|
|
192
|
+
const state = r.subarray(offset)
|
|
193
|
+
|
|
194
|
+
return { sender, data: state }
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function encodeCRDTState(address: string, data: Uint8Array) {
|
|
198
|
+
// address to uint8array
|
|
199
|
+
const addressBuffer = encodeString(address)
|
|
200
|
+
const addressOffset = 1
|
|
201
|
+
const messageLength = addressOffset + addressBuffer.byteLength + data.byteLength
|
|
202
|
+
|
|
203
|
+
const serializedMessage = new Uint8Array(messageLength)
|
|
204
|
+
serializedMessage.set(new Uint8Array([addressBuffer.byteLength]), 0)
|
|
205
|
+
serializedMessage.set(addressBuffer, 1)
|
|
206
|
+
serializedMessage.set(data, addressBuffer.byteLength + 1)
|
|
207
|
+
return serializedMessage
|
|
208
|
+
}
|
package/src/network/state.ts
CHANGED
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
TriggerAreaResult,
|
|
29
29
|
ComponentDefinition
|
|
30
30
|
} from '@dcl/ecs'
|
|
31
|
-
import { LIVEKIT_MAX_SIZE } from '
|
|
31
|
+
import { LIVEKIT_MAX_SIZE } from '@dcl/ecs/dist/systems/crdt'
|
|
32
32
|
|
|
33
33
|
export const NOT_SYNC_COMPONENTS: ComponentDefinition<unknown>[] = [
|
|
34
34
|
VideoEvent,
|
|
@@ -79,9 +79,9 @@ export function engineToCrdt(engine: IEngine): Uint8Array[] {
|
|
|
79
79
|
if (!shouldSyncComponent(itComponentDefinition)) {
|
|
80
80
|
continue
|
|
81
81
|
}
|
|
82
|
-
|
|
83
82
|
itComponentDefinition.dumpCrdtStateToBuffer(crdtBuffer, (entity) => {
|
|
84
|
-
|
|
83
|
+
const isNetworkEntity = NetworkEntity.has(entity)
|
|
84
|
+
return isNetworkEntity
|
|
85
85
|
})
|
|
86
86
|
}
|
|
87
87
|
|
|
@@ -103,6 +103,7 @@ export function engineToCrdt(engine: IEngine): Uint8Array[] {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
// If the message itself is larger than the limit, we need to handle it specially
|
|
106
|
+
// For now, we'll skip it to prevent infinite loops
|
|
106
107
|
if (messageSize / 1024 > LIVEKIT_MAX_SIZE) {
|
|
107
108
|
console.error(
|
|
108
109
|
`Message too large (${messageSize} bytes), skipping component ${message.componentId} for entity ${message.entityId}`
|
package/atom.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
declare class SimpleObservable<T> {
|
|
2
|
-
private observers;
|
|
3
|
-
private onceObservers;
|
|
4
|
-
add(callback: (value: T) => void): (value: T) => void;
|
|
5
|
-
addOnce(callback: (value: T) => void): void;
|
|
6
|
-
remove(callback: (value: T) => void): void;
|
|
7
|
-
notifyObservers(value: T): void;
|
|
8
|
-
}
|
|
9
|
-
declare const EMPTY: unique symbol;
|
|
10
|
-
type EMPTY = typeof EMPTY;
|
|
11
|
-
export type Atom<T> = {
|
|
12
|
-
deref(): Promise<T>;
|
|
13
|
-
getOrNull(): T | null;
|
|
14
|
-
observable: SimpleObservable<T>;
|
|
15
|
-
swap(value: T): T | void;
|
|
16
|
-
pipe(fn: (value: T) => void | Promise<void>): Promise<void>;
|
|
17
|
-
};
|
|
18
|
-
export declare function Atom<T>(initialValue?: T | EMPTY): Atom<T>;
|
|
19
|
-
export {};
|
package/atom.js
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import future from './future';
|
|
2
|
-
// atom value wrapper like in clojure
|
|
3
|
-
// Simple Observable implementation to replace Babylon.js dependency
|
|
4
|
-
class SimpleObservable {
|
|
5
|
-
constructor() {
|
|
6
|
-
this.observers = [];
|
|
7
|
-
this.onceObservers = [];
|
|
8
|
-
}
|
|
9
|
-
add(callback) {
|
|
10
|
-
this.observers.push(callback);
|
|
11
|
-
return callback;
|
|
12
|
-
}
|
|
13
|
-
addOnce(callback) {
|
|
14
|
-
this.onceObservers.push(callback);
|
|
15
|
-
}
|
|
16
|
-
remove(callback) {
|
|
17
|
-
const index = this.observers.indexOf(callback);
|
|
18
|
-
if (index > -1) {
|
|
19
|
-
this.observers.splice(index, 1);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
notifyObservers(value) {
|
|
23
|
-
this.observers.forEach((observer) => observer(value));
|
|
24
|
-
if (this.onceObservers.length > 0) {
|
|
25
|
-
this.onceObservers.forEach((observer) => observer(value));
|
|
26
|
-
this.onceObservers.length = 0;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
const EMPTY = Symbol('empty');
|
|
31
|
-
export function Atom(initialValue = EMPTY) {
|
|
32
|
-
const observable = new SimpleObservable();
|
|
33
|
-
let value = initialValue;
|
|
34
|
-
const valueFutures = [];
|
|
35
|
-
observable.addOnce((value) => {
|
|
36
|
-
valueFutures.forEach(($) => $.resolve(value));
|
|
37
|
-
valueFutures.length = 0;
|
|
38
|
-
});
|
|
39
|
-
return {
|
|
40
|
-
async pipe(fn) {
|
|
41
|
-
observable.add(async (t) => {
|
|
42
|
-
try {
|
|
43
|
-
await fn(t);
|
|
44
|
-
}
|
|
45
|
-
catch (err) {
|
|
46
|
-
console.error(err);
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
if (value !== EMPTY) {
|
|
50
|
-
try {
|
|
51
|
-
await fn(value);
|
|
52
|
-
}
|
|
53
|
-
catch (err) {
|
|
54
|
-
console.error(err);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
deref() {
|
|
59
|
-
if (value === EMPTY) {
|
|
60
|
-
const ret = future();
|
|
61
|
-
valueFutures.push(ret);
|
|
62
|
-
return ret;
|
|
63
|
-
}
|
|
64
|
-
return Promise.resolve(value);
|
|
65
|
-
},
|
|
66
|
-
getOrNull() {
|
|
67
|
-
if (value === EMPTY) {
|
|
68
|
-
return null;
|
|
69
|
-
}
|
|
70
|
-
return value;
|
|
71
|
-
},
|
|
72
|
-
observable,
|
|
73
|
-
swap(newValue) {
|
|
74
|
-
const oldValue = value;
|
|
75
|
-
if (newValue !== value) {
|
|
76
|
-
value = newValue;
|
|
77
|
-
observable.notifyObservers(value);
|
|
78
|
-
}
|
|
79
|
-
return oldValue === EMPTY ? undefined : oldValue;
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXRvbS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInNyYy9hdG9tLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sTUFBbUIsTUFBTSxVQUFVLENBQUE7QUFFMUMscUNBQXFDO0FBRXJDLG9FQUFvRTtBQUNwRSxNQUFNLGdCQUFnQjtJQUF0QjtRQUNVLGNBQVMsR0FBMkIsRUFBRSxDQUFBO1FBQ3RDLGtCQUFhLEdBQTJCLEVBQUUsQ0FBQTtJQTBCcEQsQ0FBQztJQXhCQyxHQUFHLENBQUMsUUFBNEI7UUFDOUIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUE7UUFDN0IsT0FBTyxRQUFRLENBQUE7SUFDakIsQ0FBQztJQUVELE9BQU8sQ0FBQyxRQUE0QjtRQUNsQyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQTtJQUNuQyxDQUFDO0lBRUQsTUFBTSxDQUFDLFFBQTRCO1FBQ2pDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFBO1FBQzlDLElBQUksS0FBSyxHQUFHLENBQUMsQ0FBQyxFQUFFO1lBQ2QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFBO1NBQ2hDO0lBQ0gsQ0FBQztJQUVELGVBQWUsQ0FBQyxLQUFRO1FBQ3RCLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQTtRQUVyRCxJQUFJLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUNqQyxJQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUE7WUFDekQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFBO1NBQzlCO0lBQ0gsQ0FBQztDQUNGO0FBRUQsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFBO0FBVzdCLE1BQU0sVUFBVSxJQUFJLENBQUksZUFBMEIsS0FBSztJQUNyRCxNQUFNLFVBQVUsR0FBRyxJQUFJLGdCQUFnQixFQUFLLENBQUE7SUFDNUMsSUFBSSxLQUFLLEdBQWMsWUFBWSxDQUFBO0lBQ25DLE1BQU0sWUFBWSxHQUFpQixFQUFFLENBQUE7SUFFckMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1FBQzNCLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQTtRQUM3QyxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQTtJQUN6QixDQUFDLENBQUMsQ0FBQTtJQUVGLE9BQU87UUFDTCxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDWCxVQUFVLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsRUFBRTtnQkFDekIsSUFBSTtvQkFDRixNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQTtpQkFDWjtnQkFBQyxPQUFPLEdBQUcsRUFBRTtvQkFDWixPQUFPLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFBO2lCQUNuQjtZQUNILENBQUMsQ0FBQyxDQUFBO1lBQ0YsSUFBSSxLQUFLLEtBQUssS0FBSyxFQUFFO2dCQUNuQixJQUFJO29CQUNGLE1BQU0sRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFBO2lCQUNoQjtnQkFBQyxPQUFPLEdBQUcsRUFBRTtvQkFDWixPQUFPLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFBO2lCQUNuQjthQUNGO1FBQ0gsQ0FBQztRQUNELEtBQUs7WUFDSCxJQUFJLEtBQUssS0FBSyxLQUFLLEVBQUU7Z0JBQ25CLE1BQU0sR0FBRyxHQUFHLE1BQU0sRUFBSyxDQUFBO2dCQUN2QixZQUFZLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFBO2dCQUN0QixPQUFPLEdBQUcsQ0FBQTthQUNYO1lBQ0QsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQy9CLENBQUM7UUFDRCxTQUFTO1lBQ1AsSUFBSSxLQUFLLEtBQUssS0FBSyxFQUFFO2dCQUNuQixPQUFPLElBQUksQ0FBQTthQUNaO1lBQ0QsT0FBTyxLQUFLLENBQUE7UUFDZCxDQUFDO1FBQ0QsVUFBVTtRQUNWLElBQUksQ0FBQyxRQUFRO1lBQ1gsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFBO1lBQ3RCLElBQUksUUFBUSxLQUFLLEtBQUssRUFBRTtnQkFDdEIsS0FBSyxHQUFHLFFBQVEsQ0FBQTtnQkFDaEIsVUFBVSxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQTthQUNsQztZQUNELE9BQU8sUUFBUSxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUE7UUFDbEQsQ0FBQztLQUNGLENBQUE7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGZ1dHVyZSwgeyBJRnV0dXJlIH0gZnJvbSAnLi9mdXR1cmUnXG5cbi8vIGF0b20gdmFsdWUgd3JhcHBlciBsaWtlIGluIGNsb2p1cmVcblxuLy8gU2ltcGxlIE9ic2VydmFibGUgaW1wbGVtZW50YXRpb24gdG8gcmVwbGFjZSBCYWJ5bG9uLmpzIGRlcGVuZGVuY3lcbmNsYXNzIFNpbXBsZU9ic2VydmFibGU8VD4ge1xuICBwcml2YXRlIG9ic2VydmVyczogKCh2YWx1ZTogVCkgPT4gdm9pZClbXSA9IFtdXG4gIHByaXZhdGUgb25jZU9ic2VydmVyczogKCh2YWx1ZTogVCkgPT4gdm9pZClbXSA9IFtdXG5cbiAgYWRkKGNhbGxiYWNrOiAodmFsdWU6IFQpID0+IHZvaWQpOiAodmFsdWU6IFQpID0+IHZvaWQge1xuICAgIHRoaXMub2JzZXJ2ZXJzLnB1c2goY2FsbGJhY2spXG4gICAgcmV0dXJuIGNhbGxiYWNrXG4gIH1cblxuICBhZGRPbmNlKGNhbGxiYWNrOiAodmFsdWU6IFQpID0+IHZvaWQpOiB2b2lkIHtcbiAgICB0aGlzLm9uY2VPYnNlcnZlcnMucHVzaChjYWxsYmFjaylcbiAgfVxuXG4gIHJlbW92ZShjYWxsYmFjazogKHZhbHVlOiBUKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgY29uc3QgaW5kZXggPSB0aGlzLm9ic2VydmVycy5pbmRleE9mKGNhbGxiYWNrKVxuICAgIGlmIChpbmRleCA+IC0xKSB7XG4gICAgICB0aGlzLm9ic2VydmVycy5zcGxpY2UoaW5kZXgsIDEpXG4gICAgfVxuICB9XG5cbiAgbm90aWZ5T2JzZXJ2ZXJzKHZhbHVlOiBUKTogdm9pZCB7XG4gICAgdGhpcy5vYnNlcnZlcnMuZm9yRWFjaCgob2JzZXJ2ZXIpID0+IG9ic2VydmVyKHZhbHVlKSlcblxuICAgIGlmICh0aGlzLm9uY2VPYnNlcnZlcnMubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5vbmNlT2JzZXJ2ZXJzLmZvckVhY2goKG9ic2VydmVyKSA9PiBvYnNlcnZlcih2YWx1ZSkpXG4gICAgICB0aGlzLm9uY2VPYnNlcnZlcnMubGVuZ3RoID0gMFxuICAgIH1cbiAgfVxufVxuXG5jb25zdCBFTVBUWSA9IFN5bWJvbCgnZW1wdHknKVxudHlwZSBFTVBUWSA9IHR5cGVvZiBFTVBUWVxuXG5leHBvcnQgdHlwZSBBdG9tPFQ+ID0ge1xuICBkZXJlZigpOiBQcm9taXNlPFQ+XG4gIGdldE9yTnVsbCgpOiBUIHwgbnVsbFxuICBvYnNlcnZhYmxlOiBTaW1wbGVPYnNlcnZhYmxlPFQ+XG4gIHN3YXAodmFsdWU6IFQpOiBUIHwgdm9pZFxuICBwaXBlKGZuOiAodmFsdWU6IFQpID0+IHZvaWQgfCBQcm9taXNlPHZvaWQ+KTogUHJvbWlzZTx2b2lkPlxufVxuXG5leHBvcnQgZnVuY3Rpb24gQXRvbTxUPihpbml0aWFsVmFsdWU6IFQgfCBFTVBUWSA9IEVNUFRZKTogQXRvbTxUPiB7XG4gIGNvbnN0IG9ic2VydmFibGUgPSBuZXcgU2ltcGxlT2JzZXJ2YWJsZTxUPigpXG4gIGxldCB2YWx1ZTogVCB8IEVNUFRZID0gaW5pdGlhbFZhbHVlXG4gIGNvbnN0IHZhbHVlRnV0dXJlczogSUZ1dHVyZTxUPltdID0gW11cblxuICBvYnNlcnZhYmxlLmFkZE9uY2UoKHZhbHVlKSA9PiB7XG4gICAgdmFsdWVGdXR1cmVzLmZvckVhY2goKCQpID0+ICQucmVzb2x2ZSh2YWx1ZSkpXG4gICAgdmFsdWVGdXR1cmVzLmxlbmd0aCA9IDBcbiAgfSlcblxuICByZXR1cm4ge1xuICAgIGFzeW5jIHBpcGUoZm4pIHtcbiAgICAgIG9ic2VydmFibGUuYWRkKGFzeW5jICh0KSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXdhaXQgZm4odClcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihlcnIpXG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgICBpZiAodmFsdWUgIT09IEVNUFRZKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXdhaXQgZm4odmFsdWUpXG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcbiAgICBkZXJlZigpIHtcbiAgICAgIGlmICh2YWx1ZSA9PT0gRU1QVFkpIHtcbiAgICAgICAgY29uc3QgcmV0ID0gZnV0dXJlPFQ+KClcbiAgICAgICAgdmFsdWVGdXR1cmVzLnB1c2gocmV0KVxuICAgICAgICByZXR1cm4gcmV0XG4gICAgICB9XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHZhbHVlKVxuICAgIH0sXG4gICAgZ2V0T3JOdWxsKCkge1xuICAgICAgaWYgKHZhbHVlID09PSBFTVBUWSkge1xuICAgICAgICByZXR1cm4gbnVsbFxuICAgICAgfVxuICAgICAgcmV0dXJuIHZhbHVlXG4gICAgfSxcbiAgICBvYnNlcnZhYmxlLFxuICAgIHN3YXAobmV3VmFsdWUpIHtcbiAgICAgIGNvbnN0IG9sZFZhbHVlID0gdmFsdWVcbiAgICAgIGlmIChuZXdWYWx1ZSAhPT0gdmFsdWUpIHtcbiAgICAgICAgdmFsdWUgPSBuZXdWYWx1ZVxuICAgICAgICBvYnNlcnZhYmxlLm5vdGlmeU9ic2VydmVycyh2YWx1ZSlcbiAgICAgIH1cbiAgICAgIHJldHVybiBvbGRWYWx1ZSA9PT0gRU1QVFkgPyB1bmRlZmluZWQgOiBvbGRWYWx1ZVxuICAgIH1cbiAgfVxufVxuIl19
|
package/future.d.ts
DELETED
package/future.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
export function future() {
|
|
2
|
-
let resolver;
|
|
3
|
-
let rejecter;
|
|
4
|
-
const promise = new Promise((ok, err) => {
|
|
5
|
-
resolver = (x) => {
|
|
6
|
-
ok(x);
|
|
7
|
-
promise.isPending = false;
|
|
8
|
-
};
|
|
9
|
-
rejecter = (x) => {
|
|
10
|
-
err(x);
|
|
11
|
-
promise.isPending = false;
|
|
12
|
-
};
|
|
13
|
-
}).catch((e) => Promise.reject(e));
|
|
14
|
-
promise.resolve = resolver;
|
|
15
|
-
promise.reject = rejecter;
|
|
16
|
-
if (!('finally' in promise)) {
|
|
17
|
-
promise.finally = (fn) => {
|
|
18
|
-
promise.then(fn);
|
|
19
|
-
promise.catch(fn);
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
promise.isPending = true;
|
|
23
|
-
return promise;
|
|
24
|
-
}
|
|
25
|
-
export default future;
|
|
26
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnV0dXJlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3JjL2Z1dHVyZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFPQSxNQUFNLFVBQVUsTUFBTTtJQUNwQixJQUFJLFFBQXdCLENBQUE7SUFDNUIsSUFBSSxRQUE0QixDQUFBO0lBRWhDLE1BQU0sT0FBTyxHQUFRLElBQUksT0FBTyxDQUFDLENBQUMsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFO1FBQzNDLFFBQVEsR0FBRyxDQUFDLENBQUksRUFBRSxFQUFFO1lBQ2xCLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQTtZQUNMLE9BQU8sQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFBO1FBQzNCLENBQUMsQ0FBQTtRQUNELFFBQVEsR0FBRyxDQUFDLENBQVEsRUFBRSxFQUFFO1lBQ3RCLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQTtZQUNOLE9BQU8sQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFBO1FBQzNCLENBQUMsQ0FBQTtJQUNILENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBO0lBRWxDLE9BQU8sQ0FBQyxPQUFPLEdBQUcsUUFBUyxDQUFBO0lBQzNCLE9BQU8sQ0FBQyxNQUFNLEdBQUcsUUFBUyxDQUFBO0lBRTFCLElBQUksQ0FBQyxDQUFDLFNBQVMsSUFBSSxPQUFPLENBQUMsRUFBRTtRQUMzQixPQUFPLENBQUMsT0FBTyxHQUFHLENBQUMsRUFBTyxFQUFFLEVBQUU7WUFDNUIsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQTtZQUNoQixPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFBO1FBQ25CLENBQUMsQ0FBQTtLQUNGO0lBRUQsT0FBTyxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUE7SUFFeEIsT0FBTyxPQUFxQixDQUFBO0FBQzlCLENBQUM7QUFFRCxlQUFlLE1BQU0sQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCB0eXBlIElGdXR1cmU8VD4gPSBQcm9taXNlPFQ+ICYge1xuICByZXNvbHZlOiAoeDogVCkgPT4gdm9pZFxuICByZWplY3Q6ICh4OiBFcnJvcikgPT4gdm9pZFxuICBmaW5hbGx5OiAoZm46ICgpID0+IHZvaWQpID0+IHZvaWRcbiAgaXNQZW5kaW5nOiBib29sZWFuXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmdXR1cmU8VCA9IGFueT4oKTogSUZ1dHVyZTxUPiB7XG4gIGxldCByZXNvbHZlcjogKHg6IFQpID0+IHZvaWRcbiAgbGV0IHJlamVjdGVyOiAoeDogRXJyb3IpID0+IHZvaWRcblxuICBjb25zdCBwcm9taXNlOiBhbnkgPSBuZXcgUHJvbWlzZSgob2ssIGVycikgPT4ge1xuICAgIHJlc29sdmVyID0gKHg6IFQpID0+IHtcbiAgICAgIG9rKHgpXG4gICAgICBwcm9taXNlLmlzUGVuZGluZyA9IGZhbHNlXG4gICAgfVxuICAgIHJlamVjdGVyID0gKHg6IEVycm9yKSA9PiB7XG4gICAgICBlcnIoeClcbiAgICAgIHByb21pc2UuaXNQZW5kaW5nID0gZmFsc2VcbiAgICB9XG4gIH0pLmNhdGNoKChlKSA9PiBQcm9taXNlLnJlamVjdChlKSlcblxuICBwcm9taXNlLnJlc29sdmUgPSByZXNvbHZlciFcbiAgcHJvbWlzZS5yZWplY3QgPSByZWplY3RlciFcblxuICBpZiAoISgnZmluYWxseScgaW4gcHJvbWlzZSkpIHtcbiAgICBwcm9taXNlLmZpbmFsbHkgPSAoZm46IGFueSkgPT4ge1xuICAgICAgcHJvbWlzZS50aGVuKGZuKVxuICAgICAgcHJvbWlzZS5jYXRjaChmbilcbiAgICB9XG4gIH1cblxuICBwcm9taXNlLmlzUGVuZGluZyA9IHRydWVcblxuICByZXR1cm4gcHJvbWlzZSBhcyBJRnV0dXJlPFQ+XG59XG5cbmV4cG9ydCBkZWZhdWx0IGZ1dHVyZVxuIl19
|
package/network/chunking.d.ts
DELETED
package/network/chunking.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { ReadWriteByteBuffer } from '@dcl/ecs/dist/serialization/ByteBuffer';
|
|
2
|
-
import { readMessages } from './server/utils';
|
|
3
|
-
/**
|
|
4
|
-
* Chunks CRDT messages from a Uint8Array buffer, respecting message boundaries
|
|
5
|
-
* Uses the comprehensive readMessages function that handles all message types
|
|
6
|
-
*/
|
|
7
|
-
export function chunkCrdtMessages(data, maxSizeKB = 12) {
|
|
8
|
-
if (data.length === 0) {
|
|
9
|
-
return [];
|
|
10
|
-
}
|
|
11
|
-
const networkBuffer = new ReadWriteByteBuffer();
|
|
12
|
-
const chunks = [];
|
|
13
|
-
for (const message of readMessages(data)) {
|
|
14
|
-
// Check if adding this message would exceed the size limit
|
|
15
|
-
const currentBufferSize = networkBuffer.toBinary().byteLength;
|
|
16
|
-
const messageSize = message.messageBuffer.byteLength;
|
|
17
|
-
if ((currentBufferSize + messageSize) / 1024 > maxSizeKB) {
|
|
18
|
-
// If the current buffer has content, save it as a chunk
|
|
19
|
-
if (currentBufferSize > 0) {
|
|
20
|
-
chunks.push(networkBuffer.toCopiedBinary());
|
|
21
|
-
networkBuffer.resetBuffer();
|
|
22
|
-
}
|
|
23
|
-
// If the message itself is larger than the limit, skip it
|
|
24
|
-
if (messageSize / 1024 > maxSizeKB) {
|
|
25
|
-
console.error(`Message too large (${messageSize} bytes), skipping CRDT message`);
|
|
26
|
-
continue;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
// Add message to current buffer
|
|
30
|
-
networkBuffer.writeBuffer(message.messageBuffer, false);
|
|
31
|
-
}
|
|
32
|
-
// Add any remaining data as the final chunk
|
|
33
|
-
if (networkBuffer.currentWriteOffset() > 0) {
|
|
34
|
-
chunks.push(networkBuffer.toBinary());
|
|
35
|
-
}
|
|
36
|
-
return chunks;
|
|
37
|
-
}
|
|
38
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2h1bmtpbmcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvbmV0d29yay9jaHVua2luZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQTtBQUM1RSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZ0JBQWdCLENBQUE7QUFFN0M7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLGlCQUFpQixDQUFDLElBQWdCLEVBQUUsWUFBb0IsRUFBRTtJQUN4RSxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1FBQ3JCLE9BQU8sRUFBRSxDQUFBO0tBQ1Y7SUFFRCxNQUFNLGFBQWEsR0FBRyxJQUFJLG1CQUFtQixFQUFFLENBQUE7SUFDL0MsTUFBTSxNQUFNLEdBQWlCLEVBQUUsQ0FBQTtJQUUvQixLQUFLLE1BQU0sT0FBTyxJQUFJLFlBQVksQ0FBQyxJQUFJLENBQUMsRUFBRTtRQUN4QywyREFBMkQ7UUFDM0QsTUFBTSxpQkFBaUIsR0FBRyxhQUFhLENBQUMsUUFBUSxFQUFFLENBQUMsVUFBVSxDQUFBO1FBQzdELE1BQU0sV0FBVyxHQUFHLE9BQU8sQ0FBQyxhQUFhLENBQUMsVUFBVSxDQUFBO1FBRXBELElBQUksQ0FBQyxpQkFBaUIsR0FBRyxXQUFXLENBQUMsR0FBRyxJQUFJLEdBQUcsU0FBUyxFQUFFO1lBQ3hELHdEQUF3RDtZQUN4RCxJQUFJLGlCQUFpQixHQUFHLENBQUMsRUFBRTtnQkFDekIsTUFBTSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQTtnQkFDM0MsYUFBYSxDQUFDLFdBQVcsRUFBRSxDQUFBO2FBQzVCO1lBRUQsMERBQTBEO1lBQzFELElBQUksV0FBVyxHQUFHLElBQUksR0FBRyxTQUFTLEVBQUU7Z0JBQ2xDLE9BQU8sQ0FBQyxLQUFLLENBQUMsc0JBQXNCLFdBQVcsZ0NBQWdDLENBQUMsQ0FBQTtnQkFDaEYsU0FBUTthQUNUO1NBQ0Y7UUFFRCxnQ0FBZ0M7UUFDaEMsYUFBYSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsYUFBYSxFQUFFLEtBQUssQ0FBQyxDQUFBO0tBQ3hEO0lBRUQsNENBQTRDO0lBQzVDLElBQUksYUFBYSxDQUFDLGtCQUFrQixFQUFFLEdBQUcsQ0FBQyxFQUFFO1FBQzFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUE7S0FDdEM7SUFFRCxPQUFPLE1BQU0sQ0FBQTtBQUNmLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBSZWFkV3JpdGVCeXRlQnVmZmVyIH0gZnJvbSAnQGRjbC9lY3MvZGlzdC9zZXJpYWxpemF0aW9uL0J5dGVCdWZmZXInXG5pbXBvcnQgeyByZWFkTWVzc2FnZXMgfSBmcm9tICcuL3NlcnZlci91dGlscydcblxuLyoqXG4gKiBDaHVua3MgQ1JEVCBtZXNzYWdlcyBmcm9tIGEgVWludDhBcnJheSBidWZmZXIsIHJlc3BlY3RpbmcgbWVzc2FnZSBib3VuZGFyaWVzXG4gKiBVc2VzIHRoZSBjb21wcmVoZW5zaXZlIHJlYWRNZXNzYWdlcyBmdW5jdGlvbiB0aGF0IGhhbmRsZXMgYWxsIG1lc3NhZ2UgdHlwZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNodW5rQ3JkdE1lc3NhZ2VzKGRhdGE6IFVpbnQ4QXJyYXksIG1heFNpemVLQjogbnVtYmVyID0gMTIpOiBVaW50OEFycmF5W10ge1xuICBpZiAoZGF0YS5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gW11cbiAgfVxuXG4gIGNvbnN0IG5ldHdvcmtCdWZmZXIgPSBuZXcgUmVhZFdyaXRlQnl0ZUJ1ZmZlcigpXG4gIGNvbnN0IGNodW5rczogVWludDhBcnJheVtdID0gW11cblxuICBmb3IgKGNvbnN0IG1lc3NhZ2Ugb2YgcmVhZE1lc3NhZ2VzKGRhdGEpKSB7XG4gICAgLy8gQ2hlY2sgaWYgYWRkaW5nIHRoaXMgbWVzc2FnZSB3b3VsZCBleGNlZWQgdGhlIHNpemUgbGltaXRcbiAgICBjb25zdCBjdXJyZW50QnVmZmVyU2l6ZSA9IG5ldHdvcmtCdWZmZXIudG9CaW5hcnkoKS5ieXRlTGVuZ3RoXG4gICAgY29uc3QgbWVzc2FnZVNpemUgPSBtZXNzYWdlLm1lc3NhZ2VCdWZmZXIuYnl0ZUxlbmd0aFxuXG4gICAgaWYgKChjdXJyZW50QnVmZmVyU2l6ZSArIG1lc3NhZ2VTaXplKSAvIDEwMjQgPiBtYXhTaXplS0IpIHtcbiAgICAgIC8vIElmIHRoZSBjdXJyZW50IGJ1ZmZlciBoYXMgY29udGVudCwgc2F2ZSBpdCBhcyBhIGNodW5rXG4gICAgICBpZiAoY3VycmVudEJ1ZmZlclNpemUgPiAwKSB7XG4gICAgICAgIGNodW5rcy5wdXNoKG5ldHdvcmtCdWZmZXIudG9Db3BpZWRCaW5hcnkoKSlcbiAgICAgICAgbmV0d29ya0J1ZmZlci5yZXNldEJ1ZmZlcigpXG4gICAgICB9XG5cbiAgICAgIC8vIElmIHRoZSBtZXNzYWdlIGl0c2VsZiBpcyBsYXJnZXIgdGhhbiB0aGUgbGltaXQsIHNraXAgaXRcbiAgICAgIGlmIChtZXNzYWdlU2l6ZSAvIDEwMjQgPiBtYXhTaXplS0IpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihgTWVzc2FnZSB0b28gbGFyZ2UgKCR7bWVzc2FnZVNpemV9IGJ5dGVzKSwgc2tpcHBpbmcgQ1JEVCBtZXNzYWdlYClcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBBZGQgbWVzc2FnZSB0byBjdXJyZW50IGJ1ZmZlclxuICAgIG5ldHdvcmtCdWZmZXIud3JpdGVCdWZmZXIobWVzc2FnZS5tZXNzYWdlQnVmZmVyLCBmYWxzZSlcbiAgfVxuXG4gIC8vIEFkZCBhbnkgcmVtYWluaW5nIGRhdGEgYXMgdGhlIGZpbmFsIGNodW5rXG4gIGlmIChuZXR3b3JrQnVmZmVyLmN1cnJlbnRXcml0ZU9mZnNldCgpID4gMCkge1xuICAgIGNodW5rcy5wdXNoKG5ldHdvcmtCdWZmZXIudG9CaW5hcnkoKSlcbiAgfVxuXG4gIHJldHVybiBjaHVua3Ncbn1cbiJdfQ==
|