2023-01-05 15:45:19 +00:00
|
|
|
import { is, Dataspace, Embedded, Reader, Ref, Schemas, Sturdy } from "@syndicate-lang/core";
|
2023-01-05 10:26:06 +00:00
|
|
|
import * as html from "@syndicate-lang/html";
|
2023-01-05 15:45:19 +00:00
|
|
|
import * as timer from "@syndicate-lang/timer";
|
2023-01-05 10:26:06 +00:00
|
|
|
import * as wsRelay from "@syndicate-lang/ws-relay";
|
|
|
|
import * as wakeDetector from './wake-detector.js';
|
2023-01-05 14:47:27 +00:00
|
|
|
import * as Shapes from './gen/shapes.js';
|
2023-01-05 10:26:06 +00:00
|
|
|
|
2023-01-03 13:18:34 +00:00
|
|
|
import {
|
|
|
|
Engine,
|
|
|
|
Mesh,
|
|
|
|
Scene,
|
2023-01-05 15:45:19 +00:00
|
|
|
TargetCamera,
|
|
|
|
WebXRCamera,
|
2023-01-03 13:18:34 +00:00
|
|
|
} from '@babylonjs/core/Legacy/legacy';
|
|
|
|
|
2023-01-05 14:47:27 +00:00
|
|
|
import { activeFloorMeshes, ShapeTree } from './shapes.js';
|
|
|
|
import { startEngine, CreatedScene } from './engine.js';
|
2023-01-05 15:45:19 +00:00
|
|
|
import { uuid } from './uuid.js';
|
2023-01-03 13:18:34 +00:00
|
|
|
|
2023-01-05 14:47:27 +00:00
|
|
|
assertion type SceneHandle(ds: Embedded<Ref>);
|
2023-01-03 13:18:34 +00:00
|
|
|
|
2023-01-05 15:45:19 +00:00
|
|
|
function interpretScene(myId: string, scene: Scene, sceneDs: Ref) {
|
2023-01-05 14:47:27 +00:00
|
|
|
at sceneDs {
|
|
|
|
during Shapes.Sprite({ "name": $name: string }) => spawn named `sprite:${name}` {
|
2023-01-05 15:45:19 +00:00
|
|
|
if (name === myId) {
|
|
|
|
console.log('ignoring sprite', name);
|
|
|
|
} else {
|
|
|
|
console.log('+shape', name);
|
|
|
|
on stop console.log('-shape', name);
|
|
|
|
spriteMain(name, scene, sceneDs);
|
|
|
|
}
|
2023-01-05 14:47:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-01-03 13:18:34 +00:00
|
|
|
|
2023-01-05 14:47:27 +00:00
|
|
|
function spriteMain(name: string, scene: Scene, sceneDs: Ref) {
|
|
|
|
at sceneDs {
|
|
|
|
let currentShape = ShapeTree.empty(name, scene);
|
|
|
|
on stop currentShape.remove();
|
|
|
|
during Shapes.Sprite({ "name": name, "shape": $shape: Shapes.Shape }) => {
|
|
|
|
currentShape = currentShape.reconcile(name, shape);
|
|
|
|
}
|
|
|
|
}
|
2023-01-03 13:18:34 +00:00
|
|
|
}
|
|
|
|
|
2023-01-05 10:26:06 +00:00
|
|
|
function wsurl(): string {
|
|
|
|
const scheme = (document.location.protocol.toLowerCase() === 'https:') ? 'wss' : 'ws';
|
|
|
|
return `${scheme}://${document.location.host}/ws`;
|
|
|
|
}
|
|
|
|
|
2023-01-05 14:47:27 +00:00
|
|
|
function bootApp(ds: Ref, scene: Scene) {
|
2023-01-05 10:26:06 +00:00
|
|
|
spawn named 'app' {
|
|
|
|
at ds {
|
|
|
|
const url = wsurl();
|
|
|
|
const serverCap = Sturdy.asSturdyRef(new Reader<Ref>(
|
|
|
|
'<ref "syndicate" [] #[pkgN9TBmEd3Q04grVG4Zdw==]>').next());
|
|
|
|
const relayAddr = wsRelay.RelayAddress(Schemas.transportAddress.WebSocket(url));
|
|
|
|
|
|
|
|
during wsRelay.Resolved({
|
|
|
|
"addr": relayAddr,
|
|
|
|
"sturdyref": serverCap,
|
|
|
|
"resolved": $remoteDs_e: Embedded,
|
|
|
|
}) => {
|
|
|
|
const remoteDs = remoteDs_e.embeddedValue;
|
|
|
|
|
|
|
|
on message wakeDetector.WakeEvent() => {
|
|
|
|
send message wsRelay.ForceRelayDisconnect(relayAddr);
|
|
|
|
}
|
2023-01-05 14:47:27 +00:00
|
|
|
|
|
|
|
at remoteDs {
|
|
|
|
during SceneHandle($sceneDs_e: Embedded) => {
|
2023-01-05 15:45:19 +00:00
|
|
|
const id = uuid();
|
2023-01-05 14:47:27 +00:00
|
|
|
const sceneDs = sceneDs_e.embeddedValue;
|
2023-01-05 15:45:19 +00:00
|
|
|
interpretScene(id, scene, sceneDs);
|
|
|
|
|
|
|
|
field position: Shapes.Vector3 = Shapes.Vector3({ x:0, y:0, z:0 });
|
|
|
|
field rotation: Shapes.Vector3 = Shapes.Vector3({ x:0, y:0, z:0 });
|
|
|
|
|
|
|
|
at ds {
|
2023-01-05 21:03:35 +00:00
|
|
|
const refreshPeriod = Math.floor(1000 / 30);
|
|
|
|
on message timer.PeriodicTick(refreshPeriod) => {
|
2023-01-05 15:45:19 +00:00
|
|
|
const camera = scene.cameras[0];
|
|
|
|
if (camera && camera instanceof TargetCamera) {
|
|
|
|
const newPosition = Shapes.Vector3(camera.position);
|
|
|
|
const newRotation = Shapes.Vector3(camera instanceof WebXRCamera
|
|
|
|
? camera.rotationQuaternion.toEulerAngles()
|
|
|
|
: camera.rotation);
|
|
|
|
if (!is(Shapes.fromVector3(position.value), Shapes.fromVector3(newPosition))) {
|
|
|
|
position.value = newPosition;
|
|
|
|
}
|
|
|
|
if (!is(Shapes.fromVector3(rotation.value), Shapes.fromVector3(newRotation))) {
|
|
|
|
rotation.value = newRotation;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
at sceneDs {
|
|
|
|
assert Shapes.Sprite({
|
|
|
|
name: id,
|
|
|
|
shape: Shapes.Shape.Nonphysical(Shapes.Nonphysical(
|
|
|
|
Shapes.Shape.Move(Shapes.Move({
|
|
|
|
v: position.value,
|
|
|
|
shape: Shapes.Shape.many([
|
|
|
|
Shapes.Shape.Move(Shapes.Move({
|
|
|
|
v: Shapes.Vector3({ x: 0, y: -0.9, z: 0}),
|
|
|
|
shape: Shapes.Shape.Rotate(Shapes.Rotate.euler({
|
|
|
|
v: Shapes.Vector3({ x: 0, y: rotation.value.y, z: 0 }),
|
|
|
|
shape: Shapes.Shape.Scale(Shapes.Scale({
|
|
|
|
v: Shapes.Vector3({ x: 0.4, y: 1.4, z: 0.1 }),
|
2023-01-05 21:03:35 +00:00
|
|
|
shape: Shapes.Shape.Mesh(Shapes.Mesh.Box(Shapes.Box())),
|
2023-01-05 15:45:19 +00:00
|
|
|
})),
|
|
|
|
})),
|
|
|
|
})),
|
|
|
|
Shapes.Shape.Rotate(Shapes.Rotate.euler({
|
|
|
|
v: rotation.value,
|
|
|
|
shape: Shapes.Shape.Scale(Shapes.Scale({
|
|
|
|
v: Shapes.Vector3({ x:0.15, y:0.23, z:0.18 }),
|
2023-01-05 21:03:35 +00:00
|
|
|
shape: Shapes.Shape.Mesh(Shapes.Mesh.Box(Shapes.Box())),
|
2023-01-05 15:45:19 +00:00
|
|
|
})),
|
|
|
|
})),
|
|
|
|
]),
|
|
|
|
})))),
|
|
|
|
});
|
|
|
|
}
|
2023-01-05 14:47:27 +00:00
|
|
|
}
|
|
|
|
}
|
2023-01-05 10:26:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-03 13:18:34 +00:00
|
|
|
window.addEventListener('load', async () => {
|
2023-01-05 14:47:27 +00:00
|
|
|
const scene = await startEngine(
|
|
|
|
async (_canvas: HTMLCanvasElement, engine: Engine): Promise<CreatedScene> => ({
|
|
|
|
scene: new Scene(engine),
|
|
|
|
floorMeshes: () => activeFloorMeshes,
|
|
|
|
}));
|
2023-01-05 10:26:06 +00:00
|
|
|
Dataspace.boot(ds => {
|
|
|
|
html.boot(ds);
|
2023-01-05 15:45:19 +00:00
|
|
|
timer.boot(ds);
|
|
|
|
wsRelay.boot(ds, false);
|
2023-01-05 10:26:06 +00:00
|
|
|
wakeDetector.boot(ds);
|
2023-01-05 14:47:27 +00:00
|
|
|
bootApp(ds, scene);
|
2023-01-05 10:26:06 +00:00
|
|
|
});
|
2023-01-03 13:18:34 +00:00
|
|
|
});
|