Skip to content

Instantly share code, notes, and snippets.

@agrancini-sc
Created June 24, 2025 17:28
Show Gist options
  • Save agrancini-sc/2c9097ef28a52ee83bb7a8e2c2a73fec to your computer and use it in GitHub Desktop.
Save agrancini-sc/2c9097ef28a52ee83bb7a8e2c2a73fec to your computer and use it in GitHub Desktop.
Sync Entity and Storage
import {SessionController} from "SpectaclesSyncKit.lspkg/Core/SessionController"
import {StorageProperty} from "SpectaclesSyncKit.lspkg/Core/StorageProperty"
import {SyncEntity} from "SpectaclesSyncKit.lspkg/Core/SyncEntity"
@component
export class GridControllerTS extends BaseScriptComponent {
@input()
showLogs: boolean = true
// Grid properties
private height: number = 3
private gridSyncEntity: SyncEntity
private gridReady: boolean = false
// Initialize the array of data (all zeroes on start)
private gridArray: vec2[] = []
// Create a storage property for the gridSyncEntity
private gridData: StorageProperty<vec2[]>
onAwake() {
if (this.showLogs) {
print("GridControllerTS: onAwake started")
}
// Initialize the grid array properly
this.gridArray = []
for (let i = 0; i < this.height * this.height; i++) {
this.gridArray.push(vec2.zero())
}
if (this.showLogs) {
print("GridControllerTS: Grid array initialized with length: " + this.gridArray.length)
print("GridControllerTS: First element: " + this.gridArray[0])
print("GridControllerTS: Elements are independent: " + (this.gridArray[0] !== this.gridArray[1]))
}
// Create the storage property after array initialization
this.gridData = StorageProperty.manualVec2Array("serverGrid", this.gridArray)
if (this.showLogs) {
print("GridControllerTS: Storage property created")
}
// Create new sync entity for this script (exactly like ControllerTS)
this.gridSyncEntity = new SyncEntity(this)
if (this.showLogs) {
print("GridControllerTS: Sync entity created")
}
// Add storage properties for grid data
this.gridSyncEntity.addStorageProperty(this.gridData)
if (this.showLogs) {
print("GridControllerTS: Storage property added to sync entity")
}
// Limit the grid to only send updates out 10 times per second
this.gridData.sendsPerSecondLimit = 10
// Add change listener to debug storage property updates
this.gridData.onAnyChange.add((newVal: vec2[], oldVal: vec2[]) => {
if (this.showLogs) {
print("GridControllerTS: Grid data changed!")
print("GridControllerTS: New value length: " + (newVal ? newVal.length : "undefined"))
print("GridControllerTS: Old value length: " + (oldVal ? oldVal.length : "undefined"))
}
})
if (this.showLogs) {
print("GridControllerTS: Change listener added")
}
// Set up the sync entity notify on ready callback (exactly like ControllerTS)
// Note: Only update the sync entity once it is ready
this.gridSyncEntity.notifyOnReady(() => this.onReady())
if (this.showLogs) {
print("GridControllerTS: Notify on ready callback set")
}
// Fallback: if sync entity doesn't become ready within 5 seconds, force ready state
let fallbackEvent = this.createEvent("DelayedCallbackEvent")
fallbackEvent.bind((eventData) => {
if (!this.gridReady) {
if (this.showLogs) {
print("GridControllerTS: FALLBACK - Sync entity never became ready, forcing ready state")
}
this.onReady()
}
})
fallbackEvent.reset(5)
if (this.showLogs) {
print("GridControllerTS: Fallback timer set for 5 seconds")
}
}
// Called when grid sync entity is ready (like ControllerTS.onReady)
onReady() {
if (this.showLogs) {
print("GridControllerTS: onReady called")
}
// Debug the storage property state
print("GridControllerTS: Grid array length: " + this.gridArray.length)
print("GridControllerTS: Grid data current value: " + this.gridData.currentValue)
print("GridControllerTS: Grid data current value length: " + (this.gridData.currentValue ? this.gridData.currentValue.length : "undefined"))
print("GridControllerTS: Grid data currentOrPendingValue: " + this.gridData.currentOrPendingValue)
print("GridControllerTS: Grid data currentOrPendingValue length: " + (this.gridData.currentOrPendingValue ? this.gridData.currentOrPendingValue.length : "undefined"))
// Make sure all cells are independent (this prints false, which is the desired outcome)
print("GridControllerTS: Elements are independent: " + (this.gridArray[0] === this.gridArray[1])) // Should be false if they're independent
// Set the pending value here
this.gridData.setPendingValue(this.gridArray)
// Set ready flag so grid can be used
this.gridReady = true
if (this.showLogs) {
print("GridControllerTS: Grid is ready!")
}
}
// SEND METHOD - Update a grid position
test() {
if (this.showLogs) {
print("GridControllerTS: TEST - Starting send test")
}
// Hardcoded test values (fixed to be within 3x3 grid bounds)
const testX = 1
const testY = 1
const newValue = new vec2(10, 20)
if (this.showLogs) {
print("GridControllerTS: TEST - Updating position (" + testX + ", " + testY + ") to " + newValue)
}
if (!this.gridReady) {
if (this.showLogs) {
print("GridControllerTS: TEST - Grid not ready, cannot send")
}
return
}
// Use currentOrPendingValue as recommended in documentation
const currentData = this.gridData.currentOrPendingValue
if (!currentData) {
if (this.showLogs) {
print("GridControllerTS: TEST - Grid data is null, cannot send")
}
return
}
let idx = this.height * testY + testX
if (idx < 0 || idx >= currentData.length) {
if (this.showLogs) {
print("GridControllerTS: TEST - Invalid index: " + idx)
}
return
}
// Create a copy of the current array
let newArray = [...currentData]
newArray[idx] = newValue
// Set the new value
this.gridData.setPendingValue(newArray)
if (this.showLogs) {
print("GridControllerTS: TEST - Successfully sent update")
}
}
// TEST RECEIVE METHOD - Test accessing grid data
testReceive() {
if (this.showLogs) {
print("GridControllerTS: TEST RECEIVE - Starting receive test")
}
// Hardcoded test values (fixed to be within 3x3 grid bounds)
const testX = 1
const testY = 1
if (this.showLogs) {
print("GridControllerTS: TEST RECEIVE - Testing position (" + testX + ", " + testY + ")")
}
if (!this.gridReady) {
if (this.showLogs) {
print("GridControllerTS: TEST RECEIVE - Grid not ready, cannot test")
}
return
}
// Calculate the array index based on x and y
let idx = this.height * testY + testX
// Use currentOrPendingValue as recommended in documentation
const currentData = this.gridData.currentOrPendingValue
if (this.showLogs) {
print("GridControllerTS: TEST RECEIVE - Calculated index: " + idx)
print("GridControllerTS: TEST RECEIVE - Grid data currentOrPendingValue: " + currentData)
print("GridControllerTS: TEST RECEIVE - Grid data currentOrPendingValue length: " + (currentData ? currentData.length : "undefined"))
}
if (!currentData) {
print("GridControllerTS: TEST RECEIVE - Grid data is null, cannot test")
return
}
// Check if index is OOB
if (idx < 0 || idx >= currentData.length) {
print("GridControllerTS: TEST RECEIVE - Invalid grid index: " + idx + " for x=" + testX + ", y=" + testY)
return
}
// This is the problem line. Index is valid but grid data always is undefined?
let cellVec = currentData[idx]
if (this.showLogs) {
print("GridControllerTS: TEST RECEIVE - Retrieved cellVec: " + cellVec)
}
if (cellVec === undefined) {
print("GridControllerTS: TEST RECEIVE - ERROR - cellVec is undefined at index " + idx)
} else {
print("GridControllerTS: TEST RECEIVE - SUCCESS - cellVec retrieved: " + cellVec)
}
}
// Convenience method to test the original receivePlayerData function
receivePlayerData(ID: number, xpos: number, ypos: number, zpos: number) {
if (this.showLogs) {
print("GridControllerTS: receivePlayerData called with ID=" + ID + ", x=" + xpos + ", y=" + ypos + ", z=" + zpos)
}
// Return early if grid is not ready
if (!this.gridReady) {
if (this.showLogs) {
print("GridControllerTS: Grid not ready, returning early")
}
return
}
// Calculate the array index based on x and y
let idx = this.height * ypos + xpos
// Use currentOrPendingValue as recommended in documentation
const currentData = this.gridData.currentOrPendingValue
if (this.showLogs) {
print("GridControllerTS: Calculated index: " + idx)
print("GridControllerTS: Grid data currentOrPendingValue: " + currentData)
print("GridControllerTS: Grid data currentOrPendingValue length: " + (currentData ? currentData.length : "undefined"))
}
if (!currentData) {
print("GridControllerTS: Grid data is null, cannot receive")
return
}
// Check if index is OOB
if (idx < 0 || idx >= currentData.length) {
print("GridControllerTS: Invalid grid index: " + idx + " for x=" + xpos + ", y=" + ypos)
return
}
// This is the problem line. Index is valid but grid data always is undefined?
let cellVec = currentData[idx]
if (this.showLogs) {
print("GridControllerTS: Retrieved cellVec: " + cellVec)
}
if (cellVec === undefined) {
print("GridControllerTS: ERROR - cellVec is undefined at index " + idx)
} else {
print("GridControllerTS: SUCCESS - cellVec retrieved: " + cellVec)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment