import { getPhaserCharge } from "@thorium/.server/systems/PhasersSystem"; import type { Entity } from "@thorium/utils/ecs"; import { Quaternion, Vector3 } from "three"; const vector = new Vector3(); const quaternion = new Quaternion(); const zAxis = new Vector3(0, 0, 1); export function dataStreamEntity(e: Entity) { // For snapshot interpolation, entities have to be flat, other than quaternions. // See https://github.com/geckosio/snapshot-interpolation#world-state // We're also removing any components of the entity that don't update // frequently to keep packet size down. if (e.components.isReactor) { return { id: e.id.toString(), x: e.components.isReactor.currentOutput, z: e.components.heat?.heat || 0, c: e.components.legacyCoolant?.coolant || 0, }; } if (e.components.isBattery) { return { id: e.id.toString(), x: e.components.isBattery.storage, y: e.components.isBattery.chargeAmount, z: e.components.isBattery.outputAmount, }; } if (e.components.isImpulseEngines) { const { targetSpeed } = e.components.isImpulseEngines; return { id: e.id.toString(), x: targetSpeed, y: e.components.power?.currentPower, z: e.components.heat?.heat || 0, c: e.components.legacyCoolant?.coolant || 0, }; } if (e.components.isWarpEngines) { const { maxVelocity } = e.components.isWarpEngines; return { id: e.id.toString(), x: maxVelocity, y: e.components.power?.currentPower, z: e.components.heat?.heat || 0, c: e.components.legacyCoolant?.coolant || 0, }; } if (e.components.isShields) { return { id: e.id.toString(), x: e.components.isShields.strength, y: e.components.power?.currentPower, z: e.components.heat?.heat || 0, }; } if (e.components.isPhasers) { // We'll count the storage of any attached phase capacitor return { id: e.id.toString(), x: getPhaserCharge(e), f: e.components.isPhasers.arc || 1, y: e.components.power?.currentPower, z: e.components.heat?.heat || 0, c: e.components.legacyCoolant?.coolant || 0, }; } if (e.components.isShortRangeComm) { return { id: e.id.toString(), f: e.components.isShortRangeComm.antennaFrequency, y: e.components.power?.currentPower, }; } if (e.components.isCoolantTank) { return { id: e.id.toString(), x: e.components.heat?.coolantVolume || 1, z: e.components.heat?.heat || 0, c: e.components.legacyCoolant?.coolant || 0, }; } if (e.components.isCoolantRadiator) { return { id: e.id.toString(), z: e.components.heat?.heat || 0, }; } if (e.components.isCoolantPump) { return { id: e.id.toString(), y: e.components.power?.currentPower, z: e.components.heat?.heat || 0, }; } // This needs to go below all the other ship systems if (e.components.power) { return { id: e.id.toString(), y: e.components.power.currentPower, z: e.components.heat?.heat || 0, }; } if (e.components.exocomp) { const { parentId: _, type: __, ...position } = e.components.position || {}; const shouldSnap = e.components.snapInterpolation ? 1 : 0; return { id: e.id.toString(), ...position, f: e.components.exocomp.currentCharge ?? 1, c: e.components.exocomp.instructionProgress || 0, s: shouldSnap, }; } if (e.components.damageControlAssignment) { return { id: e.id.toString(), x: e.components.damageControlAssignment.progress, }; } if (e.components.isTorpedo) { const { parentId: _, type: __, ...position } = e.components.position || {}; const { x, y, z } = e.components.velocity || { x: 0, y: 0, z: 0 }; const shouldSnap = e.components.snapInterpolation ? 1 : 0; e.removeComponent("snapInterpolation"); quaternion.setFromUnitVectors(zAxis, vector.set(x, y, z).normalize()); return { id: e.id.toString(), ...position, f: e.components.isDestroyed ? 1 : 0, s: shouldSnap, r: { x: quaternion.x, y: quaternion.y, z: quaternion.z, w: quaternion.w }, }; } if (e.components.scan) { return { id: e.id.toString(), x: e.components.scan.progress, }; } if (e.components.diagnostic) { return { id: e.id.toString(), x: e.components.diagnostic.progress, }; } const { parentId: _, type: __, ...position } = e.components.position || {}; const shouldSnap = e.components.snapInterpolation ? 1 : 0; e.removeComponent("snapInterpolation"); return { id: e.id.toString(), ...position, f: e.components.velocity?.forwardVelocity || 0, s: shouldSnap, r: e.components.rotation, }; }