silphius/app/routes/_main-menu.play.$.$/route.jsx

154 lines
4.4 KiB
React
Raw Normal View History

2024-06-14 15:18:55 -05:00
import {json} from "@remix-run/node";
2024-06-14 12:27:07 -05:00
import {useEffect, useState} from 'react';
import {useOutletContext, useParams} from 'react-router-dom';
2024-07-20 04:32:33 -05:00
import Ui from '@/react/components/ui.jsx';
import AssetsContext from '@/react/context/assets.js';
import ClientContext from '@/react/context/client.js';
import DebugContext from '@/react/context/debug.js';
import EcsContext from '@/react/context/ecs.js';
import MainEntityContext from '@/react/context/main-entity.js';
import RadiansContext from '@/react/context/radians.js';
2024-07-14 21:07:46 -05:00
import {TAU} from '@/util/math.js';
2024-07-20 04:42:10 -05:00
import {juggleSession} from '@/util/session.server';
2024-06-27 10:53:52 -05:00
2024-06-14 15:18:55 -05:00
export async function loader({request}) {
await juggleSession(request);
return json({});
}
2024-06-14 12:27:07 -05:00
export default function PlaySpecific() {
const Client = useOutletContext();
2024-06-27 13:56:43 -05:00
const assetsTuple = useState({});
2024-06-14 12:27:07 -05:00
const [client, setClient] = useState();
const mainEntityTuple = useState();
2024-07-02 20:43:55 -05:00
const setMainEntity = mainEntityTuple[1];
2024-06-25 08:54:19 -05:00
const debugTuple = useState(false);
2024-07-02 20:43:55 -05:00
const ecsTuple = useState();
2024-06-14 12:27:07 -05:00
const [disconnected, setDisconnected] = useState(false);
const params = useParams();
2024-06-15 20:59:11 -05:00
const [type, url] = params['*'].split('/');
2024-07-14 21:07:46 -05:00
const [radians, setRadians] = useState(0);
useEffect(() => {
let handle;
let last;
const spin = (ts) => {
if ('undefined' === typeof last) {
last = ts;
}
const elapsed = (ts - last) / 1000;
last = ts;
setRadians((radians) => radians + (elapsed * TAU));
handle = requestAnimationFrame(spin);
};
handle = requestAnimationFrame(spin);
return () => {
cancelAnimationFrame(handle);
};
}, []);
2024-06-14 12:27:07 -05:00
useEffect(() => {
if (!Client) {
return;
}
const client = new Client();
async function connect() {
await client.connect(url);
setClient(client);
}
connect();
return () => {
client.disconnect();
};
}, [Client, url]);
2024-06-15 20:59:11 -05:00
// Sneakily use beforeunload to snag some time to save.
useEffect(() => {
if ('local' !== type) {
return;
}
2024-06-23 07:35:56 -05:00
async function onBeforeUnload() {
2024-06-15 20:59:11 -05:00
client.disconnect();
2024-06-21 04:43:32 -05:00
function waitForSave() {
return new Promise((resolve) => setTimeout(resolve, 0));
}
while (client.worker) { await waitForSave(); }
2024-06-15 20:59:11 -05:00
}
addEventListener('beforeunload', onBeforeUnload);
return () => {
removeEventListener('beforeunload', onBeforeUnload);
};
});
2024-06-14 12:27:07 -05:00
useEffect(() => {
if (!client) {
return;
}
function onConnectionStatus(status) {
switch (status) {
case 'aborted': {
setDisconnected(true);
break;
}
case 'connected': {
setDisconnected(false);
break;
}
}
}
client.addPacketListener('ConnectionStatus', onConnectionStatus);
return () => {
client.removePacketListener('ConnectionStatus', onConnectionStatus);
};
}, [client]);
useEffect(() => {
2024-07-02 20:43:55 -05:00
if (!client || !disconnected) {
2024-06-14 12:27:07 -05:00
return;
}
2024-07-02 20:43:55 -05:00
setMainEntity(undefined);
2024-06-14 12:27:07 -05:00
async function reconnect() {
await client.connect(url);
}
reconnect();
const handle = setInterval(reconnect, 1000);
return () => {
clearInterval(handle);
};
2024-07-02 20:43:55 -05:00
}, [client, disconnected, setMainEntity, url]);
2024-07-07 17:37:00 -05:00
// useEffect(() => {
// let source = true;
// async function play() {
// const ctx = new AudioContext();
// const response = await fetch(new URL('/assets/yuff.wav', window.location.origin));
// const buffer = await ctx.decodeAudioData(await response.arrayBuffer());
// if (!source) {
// return;
// }
// source = ctx.createBufferSource();
// source.buffer = buffer;
// source.connect(ctx.destination);
// source.loop = true;
// source.start();
// }
// setTimeout(play, 1000);
// return () => {
// if (true !== source) {
// source.stop();
// }
// source = false;
// };
// }, [])
2024-06-14 12:27:07 -05:00
return (
<ClientContext.Provider value={client}>
<MainEntityContext.Provider value={mainEntityTuple}>
2024-06-22 23:32:57 -05:00
<EcsContext.Provider value={ecsTuple}>
2024-06-25 08:54:19 -05:00
<DebugContext.Provider value={debugTuple}>
2024-06-27 13:56:43 -05:00
<AssetsContext.Provider value={assetsTuple}>
2024-07-14 21:07:46 -05:00
<RadiansContext.Provider value={radians}>
<Ui disconnected={disconnected} />
</RadiansContext.Provider>
2024-06-27 13:56:43 -05:00
</AssetsContext.Provider>
2024-06-25 08:54:19 -05:00
</DebugContext.Provider>
2024-06-22 23:32:57 -05:00
</EcsContext.Provider>
</MainEntityContext.Provider>
2024-06-14 12:27:07 -05:00
</ClientContext.Provider>
);
}