Skip to content

Commit 5658bbe

Browse files
Use UUID-based scene object IDs [SYNTH-309] (#1463)
Co-authored-by: Zach Rutman <92497727+rutmanz@users.noreply.github.com>
2 parents 2697f51 + 8e76f4a commit 5658bbe

15 files changed

Lines changed: 118 additions & 143 deletions

File tree

fission/src/mirabuf/MirabufLoader.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import InitialConfigPanel from "@/panels/configuring/initial-config/InitialConfi
88
import { PAUSE_REF_ASSEMBLY_SPAWNING } from "@/systems/physics/PhysicsTypes.ts"
99
import { createMirabuf } from "@/mirabuf/MirabufSceneObject.ts"
1010
import { getTargetControls } from "@/systems/scene/CameraControls.ts"
11-
import type { EncodedAssembly, LocalSceneObjectId, Message, RemoteSceneObjectId } from "@/systems/multiplayer/types.ts"
11+
import type { EncodedAssembly, Message } from "@/systems/multiplayer/types.ts"
1212
import { ProgressHandle } from "@/components/ProgressNotificationData.ts"
1313

1414
const MIRABUF_LOCALSTORAGE_GENERATION_KEY = "Synthesis Nonce Key"
@@ -496,7 +496,7 @@ export async function spawnCachedMira(
496496
type: "newObject",
497497
timestamp: Date.now(),
498498
data: {
499-
sceneObjectKey: mirabufSceneObject.id as RemoteSceneObjectId,
499+
sceneObjectKey: mirabufSceneObject.id,
500500
assembly: encodedAssembly,
501501
assemblyHash: info.hash,
502502
miraType: info.miraType,
@@ -505,7 +505,7 @@ export async function spawnCachedMira(
505505
},
506506
}
507507
await World.multiplayerSystem?.broadcast(message)
508-
World.multiplayerSystem?.registerOwnSceneObject(mirabufSceneObject.id as LocalSceneObjectId)
508+
World.multiplayerSystem?.registerOwnSceneObject(mirabufSceneObject.id)
509509
}
510510

511511
if (targetControls && (info.miraType === MiraType.ROBOT || !targetControls.focusProvider)) {

fission/src/mirabuf/MirabufSceneObject.ts

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
import type Jolt from "@synthesis.adsk/jolt-physics"
22
import * as THREE from "three"
33
import type { mirabuf } from "@/proto/mirabuf"
4-
import type {
5-
FieldConfiguration,
6-
LocalSceneObjectId,
7-
RemoteSceneObjectId,
8-
RobotConfiguration,
9-
UpdateObjectData,
10-
} from "@/systems/multiplayer/types"
4+
import type { FieldConfiguration, RobotConfiguration, UpdateObjectData } from "@/systems/multiplayer/types"
115
import { BodyAssociate } from "@/systems/physics/BodyAssociate.ts"
126
import EventSystem from "@/systems/EventSystem.ts"
137
import type Mechanism from "@/systems/physics/Mechanism"
@@ -65,6 +59,7 @@ import ProtectedZoneSceneObject from "./ProtectedZoneSceneObject"
6559
import ScoringZoneSceneObject from "./ScoringZoneSceneObject"
6660
import { v4 as uuidV4 } from "uuid"
6761
import { copyVec3, hexStringToUint8Array, yieldToMain } from "@/util/Utility.ts"
62+
import type { SceneObjectId } from "@/systems/scene/SceneRenderer.ts"
6863

6964
const DEBUG_BODIES = false
7065

@@ -79,15 +74,17 @@ interface RnDebugMeshes {
7974
* last spawned in, however, systems (such as the configuration UI) can elect
8075
* assemblies to be in the spotlight when moving from interface to interface.
8176
*/
82-
let spotlightAssembly: number | undefined
77+
let spotlightAssembly: SceneObjectId | undefined
8378

8479
export function setSpotlightAssembly(assembly: MirabufSceneObject) {
8580
spotlightAssembly = assembly.id
8681
}
8782

8883
// TODO: If nothing is in the spotlight, select last entry before defaulting to undefined
8984
export function getSpotlightAssembly(): MirabufSceneObject | undefined {
90-
return World.sceneRenderer.sceneObjects.get(spotlightAssembly ?? 0) as MirabufSceneObject
85+
return spotlightAssembly != null
86+
? (World.sceneRenderer.sceneObjects.get(spotlightAssembly) as MirabufSceneObject)
87+
: undefined
9188
}
9289

9390
type MinMax = { min: number; max: number }
@@ -708,7 +705,7 @@ class MirabufSceneObject extends SceneObject implements ContextSupplier {
708705
}
709706

710707
private removeSceneObjects(objs: SceneObject[]) {
711-
objs.filter(obj => obj.id != -1).forEach(obj => World.sceneRenderer.removeSceneObject(obj.id))
708+
objs.forEach(obj => World.sceneRenderer.removeSceneObject(obj.id))
712709
objs.length = 0
713710
}
714711

@@ -720,7 +717,6 @@ class MirabufSceneObject extends SceneObject implements ContextSupplier {
720717
if (zoneObject == null) return
721718

722719
World.sceneRenderer.removeSceneObject(zoneObject.id)
723-
zoneObject.id = -1
724720
}
725721

726722
public removeProtectedZoneObject(zone: ProtectedZonePreferences) {
@@ -731,7 +727,6 @@ class MirabufSceneObject extends SceneObject implements ContextSupplier {
731727
if (zoneObject == null) return
732728

733729
World.sceneRenderer.removeSceneObject(zoneObject.id)
734-
zoneObject.id = -1
735730
}
736731

737732
/**
@@ -1023,7 +1018,7 @@ class MirabufSceneObject extends SceneObject implements ContextSupplier {
10231018
await World.multiplayerSystem.broadcast({
10241019
type: "configureObject",
10251020
data: {
1026-
sceneObjectKey: this.id as RemoteSceneObjectId,
1021+
sceneObjectKey: this.id,
10271022
objectConfigurationData: data,
10281023
},
10291024
})
@@ -1135,8 +1130,8 @@ class MirabufSceneObject extends SceneObject implements ContextSupplier {
11351130
}
11361131

11371132
public enablePhysics() {
1138-
if (World.multiplayerSystem?.getOwnSceneObjectIDs().includes(this.id as LocalSceneObjectId)) {
1139-
World.multiplayerSystem.broadcast({ type: "enableObjectPhysics", data: this.id as RemoteSceneObjectId })
1133+
if (World.multiplayerSystem?.getOwnSceneObjectIDs().includes(this.id)) {
1134+
World.multiplayerSystem.broadcast({ type: "enableObjectPhysics", data: this.id })
11401135
}
11411136

11421137
this.mirabufInstance.parser.rigidNodes.forEach(rn => {
@@ -1146,8 +1141,8 @@ class MirabufSceneObject extends SceneObject implements ContextSupplier {
11461141
}
11471142

11481143
public disablePhysics() {
1149-
if (World.multiplayerSystem?.getOwnSceneObjectIDs().includes(this.id as LocalSceneObjectId)) {
1150-
World.multiplayerSystem.broadcast({ type: "disableObjectPhysics", data: this.id as RemoteSceneObjectId })
1144+
if (World.multiplayerSystem?.getOwnSceneObjectIDs().includes(this.id)) {
1145+
World.multiplayerSystem.broadcast({ type: "disableObjectPhysics", data: this.id })
11511146
}
11521147

11531148
this.mirabufInstance.parser.rigidNodes.forEach(rn => {
@@ -1333,7 +1328,7 @@ class MirabufSceneObject extends SceneObject implements ContextSupplier {
13331328
.filter(n => n != null)
13341329

13351330
return {
1336-
sceneObjectKey: this.id as RemoteSceneObjectId,
1331+
sceneObjectKey: this.id,
13371332
gamePiecesControlled,
13381333
bodies,
13391334
}

fission/src/systems/EventSystem.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import type { CurrentContactData, OnContactValidateData } from "@/systems/physic
88
import type TaskStatus from "@/util/TaskStatus.ts"
99
import type MirabufSceneObject from "@/mirabuf/MirabufSceneObject.ts"
1010
import type { CameraPoint } from "@/systems/preferences/PreferenceTypes.ts"
11+
import type { SceneObjectId } from "@/systems/scene/SceneRenderer.ts"
1112

1213
interface EventDataMap {
1314
// Mirabuf
@@ -53,7 +54,7 @@ interface EventDataMap {
5354
CameraModeChangedEvent: { mode: string }
5455
CameraFocusChangedEvent: { focusProvider: MirabufSceneObject | undefined }
5556
// Field View: the active camera point changed (the selected point, or undefined when none).
56-
CameraViewChangedEvent: { point: CameraPoint | undefined; focusedRobotId?: number }
57+
CameraViewChangedEvent: { point: CameraPoint | undefined; focusedRobotId?: SceneObjectId }
5758
// The active camera control scheme changed (e.g. "Target" or "FieldView").
5859
CameraControlsTypeChangedEvent: { controlsType: string }
5960

fission/src/systems/match_mode/RobotDimensionTracker.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
import World from "@/systems/World"
22
import MatchMode from "./MatchMode"
3+
import type { SceneObjectId } from "@/systems/scene/SceneRenderer.ts"
34

45
const BUFFER_HEIGHT = 0.1
56
const SIDE_BUFFER = 0.1
67

78
class RobotDimensionTracker {
8-
private static _robotLastFramePenalty: Map<number, boolean> = new Map()
9+
private static _robotLastFramePenalty: Map<SceneObjectId, boolean> = new Map()
910
private static _ignoreRotation: boolean = true
1011
private static _maxHeight: number = Infinity
1112
private static _heightLimitPenalty: number = 0
1213
private static _sideExtensionPenalty: number = 0
13-
private static _robotSize: Map<number, { width: number; depth: number }> = new Map()
14+
private static _robotSize: Map<SceneObjectId, { width: number; depth: number }> = new Map()
1415
private static _sideMaxExtension: number = 0
1516

1617
public static setConfigValues(

fission/src/systems/multiplayer/MessageHandlers.ts

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,14 @@ import type {
1111
ClientInfo,
1212
EncodedAssembly,
1313
InitObjectData,
14-
LocalSceneObjectId,
1514
MatchModePenalty,
1615
MatchModeStateData,
1716
MessageType,
1817
ObjectPreferences,
19-
RemoteSceneObjectId,
2018
UpdateObjectData,
2119
} from "./types"
2220
import EventSystem from "@/systems/EventSystem.ts"
21+
import type { SceneObjectId } from "@/systems/scene/SceneRenderer.ts"
2322

2423
export const peerMessageHandlers = {
2524
info: handlePeerInfo,
@@ -44,7 +43,7 @@ export const peerMessageHandlers = {
4443
}
4544

4645
const pendingOperations: (() => void)[] = []
47-
const progressHandles: Map<number, ProgressHandle> = new Map()
46+
const progressHandles: Map<SceneObjectId, ProgressHandle> = new Map()
4847

4948
async function handleMatchModeState(data: MatchModeStateData) {
5049
console.log(data)
@@ -78,9 +77,7 @@ function handlePeerUpdate(data: UpdateObjectData[], peerId: string, timestamp: n
7877
clientToUpdateMap.set(peerId, timestamp)
7978

8079
data.forEach(({ sceneObjectKey, gamePiecesControlled, bodies }) => {
81-
const sceneObject = World.sceneRenderer.sceneObjects.get(
82-
World.multiplayerSystem!.convertSceneObjectId(peerId, sceneObjectKey)
83-
)
80+
const sceneObject = World.sceneRenderer.sceneObjects.get(sceneObjectKey)
8481
if (sceneObject == null) {
8582
console.warn(
8683
`Multiplayer SceneObject: ${sceneObjectKey} not found in sceneObjects map. Multiplayer SceneObjects must be initialized before being updated.`
@@ -201,13 +198,9 @@ async function handleNewObject(data: InitObjectData, peerId: string) {
201198
object.nameOverride = clientToInfoMap.get(peerId)?.displayName ?? peerId
202199

203200
console.log("Registering object", object, data)
204-
const localSceneObjectKey = World.sceneRenderer.registerSceneObject(object)
205-
console.log("linking object", data.sceneObjectKey, "->", localSceneObjectKey)
206-
207-
World.multiplayerSystem?.setSceneObjectIdMapping(peerId, data.sceneObjectKey, localSceneObjectKey)
201+
World.sceneRenderer.registerSceneObject(object)
208202

209-
clientToObjectMap.get(peerId)?.push(object.id as LocalSceneObjectId) ||
210-
clientToObjectMap.set(peerId, [object.id as LocalSceneObjectId])
203+
clientToObjectMap.get(peerId)?.push(object.id) || clientToObjectMap.set(peerId, [object.id])
211204

212205
// Sets bodyMap
213206
const clientBodyIds = object.getAllBodyIds()
@@ -250,31 +243,28 @@ async function handleAssemblyRequest(data: AssemblyRequestData, peerId: string)
250243
})
251244
}
252245

253-
function handleDeleteObject(sceneObjectKey: RemoteSceneObjectId, peerId: string) {
246+
function handleDeleteObject(sceneObjectKey: SceneObjectId, peerId: string) {
254247
if (!World.multiplayerSystem) return
255248
const clientToObjectMap = World.multiplayerSystem._clientToObjectMap
256-
const localKey = World.multiplayerSystem!.convertSceneObjectId(peerId, sceneObjectKey)
257249

258-
const peerClient = [...clientToObjectMap.entries()].find(([_id, keys]) => keys.includes(localKey))
250+
const peerClient = [...clientToObjectMap.entries()].find(([_id, keys]) => keys.includes(sceneObjectKey))
259251
if (peerClient != null) {
260252
const keys = clientToObjectMap.get(peerClient[0])
261-
const index = keys?.indexOf(World.multiplayerSystem.convertSceneObjectId(peerId, sceneObjectKey)) ?? -1
253+
const index = keys?.indexOf(sceneObjectKey) ?? -1
262254
if (index != -1) {
263255
keys?.splice(index)
264256
}
265257
}
266258

267-
if (!World.sceneRenderer.sceneObjects.has(localKey)) {
259+
if (!World.sceneRenderer.sceneObjects.has(sceneObjectKey)) {
268260
pendingOperations.push(() => handleDeleteObject(sceneObjectKey, peerId))
269261
}
270262

271-
World.sceneRenderer.removeSceneObject(localKey)
263+
World.sceneRenderer.removeSceneObject(sceneObjectKey)
272264
}
273265

274266
function handleObjectConfiguration(data: ObjectPreferences, peerId: string) {
275-
const sceneObject = World.sceneRenderer.sceneObjects.get(
276-
World.multiplayerSystem!.convertSceneObjectId(peerId, data.sceneObjectKey)
277-
)
267+
const sceneObject = World.sceneRenderer.sceneObjects.get(data.sceneObjectKey)
278268
if (sceneObject instanceof MirabufSceneObject) {
279269
if (sceneObject.isOwnObject) {
280270
console.warn("received config for own object")
@@ -287,10 +277,8 @@ function handleObjectConfiguration(data: ObjectPreferences, peerId: string) {
287277
}
288278
}
289279

290-
function disableObjectPhysics(sceneObjectKey: RemoteSceneObjectId, peerId: string) {
291-
const sceneObject = World.sceneRenderer.sceneObjects.get(
292-
World.multiplayerSystem!.convertSceneObjectId(peerId, sceneObjectKey)
293-
)
280+
function disableObjectPhysics(sceneObjectKey: SceneObjectId, peerId: string) {
281+
const sceneObject = World.sceneRenderer.sceneObjects.get(sceneObjectKey)
294282
if (sceneObject instanceof MirabufSceneObject) {
295283
if (sceneObject.isOwnObject) {
296284
console.warn("received disable for own object")
@@ -302,10 +290,8 @@ function disableObjectPhysics(sceneObjectKey: RemoteSceneObjectId, peerId: strin
302290
}
303291
}
304292

305-
function enableObjectPhysics(sceneObjectKey: RemoteSceneObjectId, peerId: string) {
306-
const sceneObject = World.sceneRenderer.sceneObjects.get(
307-
World.multiplayerSystem!.convertSceneObjectId(peerId, sceneObjectKey)
308-
)
293+
function enableObjectPhysics(sceneObjectKey: SceneObjectId, peerId: string) {
294+
const sceneObject = World.sceneRenderer.sceneObjects.get(sceneObjectKey)
309295
if (sceneObject instanceof MirabufSceneObject) {
310296
if (sceneObject.isOwnObject) {
311297
console.warn("received enablephysics for own object")
@@ -318,9 +304,7 @@ function enableObjectPhysics(sceneObjectKey: RemoteSceneObjectId, peerId: string
318304
}
319305

320306
function handleMatchModePenalty(data: MatchModePenalty, peerId: string) {
321-
const obj = World.sceneRenderer.sceneObjects.get(
322-
World.multiplayerSystem!.convertSceneObjectId(peerId, data.objectId)
323-
)
307+
const obj = World.sceneRenderer.sceneObjects.get(data.objectId)
324308
if (!(obj instanceof MirabufSceneObject)) {
325309
console.warn("can't handle penalty for object", data.objectId, obj)
326310
pendingOperations.push(() => handleMatchModePenalty(data, peerId))

fission/src/systems/multiplayer/MultiplayerSystem.ts

Lines changed: 7 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ import { mirabuf } from "@/proto/mirabuf"
77
import PreferencesSystem from "@/systems/preferences/PreferencesSystem.ts"
88
import World from "../World"
99
import { peerMessageHandlers } from "./MessageHandlers"
10-
import type { ClientInfo, LocalSceneObjectId, Message, MessageWithTimestamp, RemoteSceneObjectId } from "./types"
10+
import type { ClientInfo, Message, MessageWithTimestamp } from "./types"
1111
import { hashBuffer } from "@/util/Utility"
1212
import EventSystem from "@/systems/EventSystem.ts"
13+
import type { SceneObjectId } from "@/systems/scene/SceneRenderer.ts"
1314

1415
export const COLLISION_TIMEOUT = 500
1516

@@ -22,9 +23,8 @@ class MultiplayerSystem {
2223

2324
public readonly _clientToInfoMap: Map<string, ClientInfo> = new Map()
2425

25-
public readonly _clientToObjectMap: Map<string, LocalSceneObjectId[]> = new Map()
26+
public readonly _clientToObjectMap: Map<string, SceneObjectId[]> = new Map()
2627
public readonly _clientToBodyMap: Map<string, Map<number, Jolt.BodyID>> = new Map() // Each Map is: peerBodyId -> clientBodyId
27-
public readonly _clientToSceneObjectIdMap: Map<string, Map<RemoteSceneObjectId, LocalSceneObjectId>> = new Map() // Each Map is: peerObjectId -> clientObjectId
2828

2929
readonly info: ClientInfo
3030
private _onDestroyHooks: (() => void)[] = []
@@ -169,7 +169,7 @@ class MultiplayerSystem {
169169
await this.send(conn.peer, {
170170
type: "newObject",
171171
data: {
172-
sceneObjectKey: obj.id as RemoteSceneObjectId,
172+
sceneObjectKey: obj.id,
173173
assemblyHash: await hashBuffer(
174174
mirabuf.Assembly.encode(obj.mirabufInstance.parser.assembly).finish().buffer as ArrayBuffer
175175
),
@@ -190,13 +190,12 @@ class MultiplayerSystem {
190190
this.handlePeerMessage(
191191
{
192192
type: "deleteObject",
193-
data: this.convertSceneObjectIdReverse(conn.peer, obj)!,
193+
data: obj!,
194194
timestamp: Date.now(),
195195
},
196196
conn.peer
197197
).catch(console.error) // TODO Get actual sceneObjectKey
198198
})
199-
this._clientToSceneObjectIdMap.delete(conn.peer)
200199

201200
this._connections.delete(conn.peer)
202201
// TODO: handle host transition
@@ -260,16 +259,15 @@ class MultiplayerSystem {
260259
.filter(obj => obj instanceof MirabufSceneObject)
261260
}
262261

263-
registerOwnSceneObject(objectId: LocalSceneObjectId) {
262+
registerOwnSceneObject(objectId: SceneObjectId) {
264263
const list = this._clientToObjectMap.get(this.clientId)
265-
this.setSceneObjectIdMapping(this.clientId, objectId as RemoteSceneObjectId, objectId)
266264
if (list != null) {
267265
list.push(objectId)
268266
} else {
269267
this._clientToObjectMap.set(this.clientId, [objectId])
270268
}
271269
}
272-
unregisterOwnSceneObject(objectId: LocalSceneObjectId) {
270+
unregisterOwnSceneObject(objectId: SceneObjectId) {
273271
const list = this._clientToObjectMap.get(this.clientId)
274272
if (!list) return
275273
const index = list.indexOf(objectId)
@@ -305,29 +303,11 @@ class MultiplayerSystem {
305303
this._connections.forEach(conn => conn.close())
306304
this._connections.clear()
307305
this.client.destroy()
308-
this._clientToSceneObjectIdMap.clear()
309306
this._onDestroyHooks.forEach(hook => {
310307
hook()
311308
})
312309
World.setMultiplayerSystem(undefined)
313310
}
314-
315-
public convertSceneObjectId(peerId: string, objectId: RemoteSceneObjectId): LocalSceneObjectId {
316-
return this._clientToSceneObjectIdMap.get(peerId)?.get(objectId) ?? (-1 as LocalSceneObjectId)
317-
}
318-
319-
public convertSceneObjectIdReverse(peerId: string, objectId: LocalSceneObjectId): RemoteSceneObjectId | undefined {
320-
return [...this._clientToSceneObjectIdMap.get(peerId)!.entries()].find(([_, l]) => objectId == l)?.[0]
321-
}
322-
323-
public setSceneObjectIdMapping(peerId: string, remoteId: RemoteSceneObjectId, localId: LocalSceneObjectId) {
324-
let peerMap = World.multiplayerSystem?._clientToSceneObjectIdMap.get(peerId)
325-
if (peerMap == null) {
326-
peerMap = new Map()
327-
World.multiplayerSystem?._clientToSceneObjectIdMap.set(peerId, peerMap)
328-
}
329-
peerMap.set(remoteId, localId)
330-
}
331311
}
332312

333313
async function generateId(roomId: string, forceRegen: boolean = false): Promise<string> {

0 commit comments

Comments
 (0)