diff --git a/src/client/GamePage.tsx b/src/client/GamePage.tsx index 37b9841..ede5891 100644 --- a/src/client/GamePage.tsx +++ b/src/client/GamePage.tsx @@ -1,10 +1,15 @@ import { Link, useParams, useSearchParams } from "react-router-dom"; -import { useEffect, useRef, useState } from "react"; +import { MutableRefObject, useEffect, useRef, useState } from "react"; import { css } from "@emotion/css"; import { useWebsocket } from "./hooks/useWebsocket"; import { Pico8Player } from "@athingperday/react-pico-player"; -// type ConsoleRef = Parameters["0"]["consoleRef"]; +type PicoPlayerHandle = + NonNullable< + Parameters["0"]["consoleRef"] + > extends MutableRefObject + ? NonNullable + : never; type Game = { carts: Parameters["0"]["carts"]; @@ -12,30 +17,37 @@ type Game = { export const GamePage = () => { const { author, slug } = useParams(); - // const [searchParams, setSearchParams] = useSearchParams(); - // const room = searchParams.get('room'); - // const picoRef = useRef(null); - // const socket = useWebsocket({ - // url: `/api/ws/room?room=${room}`, - // // url: "wss://echo.websocket.org", - // onMessage({message}) { - // // const msg = message as any; - // // if (msg.type === "gpio") { - // // if (picoRef.current) { - // // const handle = picoRef.current.getPicoConsoleHandle(); - // // if (handle) { - // // console.log("updating pico gpio"); - // // (handle.gpio as any).dontSend = true; - // // handle.gpio.length = 0; - // // handle.gpio.push(...msg.gpio); - // // (handle.gpio as any).dontSend = false; - // // } - // // } - // // } - // console.log('message', message); - // } - // }) - // const version = searchParams.get('v'); + const [text, setText] = useState(""); + const [prevGpio, setPrevGpio] = useState(null); + const [searchParams, setSearchParams] = useSearchParams(); + const room = searchParams.get("room"); + const picoRef = useRef(null); + const socket = useWebsocket({ + url: `/api/ws/room?room=${room}`, + onMessage({ message }) { + // console.log("message", message); + const msg = message as any; + if (msg.getGpio) { + if (picoRef.current) { + const handle = picoRef.current; + if (handle) { + socket.sendMessage({ gpio: handle.gpio }); + } + } + } + if (msg.gpio) { + if (picoRef.current) { + const handle = picoRef.current; + if (handle) { + // console.log("updating pico gpio"); + handle.gpio.length = 0; + handle.gpio.push(...msg.gpio); + setPrevGpio([...handle.gpio]); + } + } + } + }, + }); const [game, setGame] = useState(null); useEffect(() => { @@ -49,6 +61,28 @@ export const GamePage = () => { fetchInfo(); }, [setGame, slug]); + useEffect(() => { + const interval = setInterval(() => { + const handle = picoRef.current; + if (!handle) { + return; + } + if (JSON.stringify(handle.gpio) !== JSON.stringify(prevGpio)) { + if (prevGpio) { + setPrevGpio([...handle.gpio]); + socket.sendMessage({ gpio: handle.gpio }); + } else { + socket.sendMessage({ getGpio: true }); + setPrevGpio([...handle.gpio]); + } + } + }, 1000 / 60); + + return () => { + clearInterval(interval); + }; + }); + if (!game) { return
LOADING...
; } @@ -90,19 +124,19 @@ export const GamePage = () => { } `} > - { - // console.log("sending gpio"); - // socket.sendMessage({ - // type: "gpio", - // gpio, - // }); - // }} - /> + +
+ setText(x.target.value)} /> + +
{/*

This is a paragraph about this game. It is a cool game. And a cool website to play it on. It automagically connects from GitHub.

*/} diff --git a/src/client/hooks/useWebsocket.ts b/src/client/hooks/useWebsocket.ts index b99c273..a22481e 100644 --- a/src/client/hooks/useWebsocket.ts +++ b/src/client/hooks/useWebsocket.ts @@ -1,46 +1,52 @@ import { useCallback, useEffect, useRef, useState } from "react"; -export const useWebsocket = (props: {url: string; onMessage: (stuff: {socket: WebSocket; message: unknown}) => void}) => { - const {url, onMessage} = props; - const onMessageRef = useRef(onMessage); - const ws = useRef(null); - onMessageRef.current = onMessage; +export const useWebsocket = (props: { + url: string; + onMessage: (stuff: { socket: WebSocket; message: unknown }) => void; +}) => { + const { url, onMessage } = props; + const onMessageRef = useRef(onMessage); + const ws = useRef(null); + onMessageRef.current = onMessage; - useEffect(() => { - const webSocket = new WebSocket(url); + useEffect(() => { + const webSocket = new WebSocket(url); - webSocket.addEventListener("open", () => { - console.log("WebSocket is open now."); - }); + webSocket.addEventListener("open", () => { + console.log("WebSocket is open now."); + }); - webSocket.addEventListener("message", (event: any) => { - onMessageRef.current({socket: webSocket, message: JSON.parse(event.data)}); - }); + webSocket.addEventListener("message", (event: any) => { + onMessageRef.current({ + socket: webSocket, + message: JSON.parse(event.data), + }); + }); webSocket.addEventListener("error", (event) => { - console.log("WebSocket error: ", event); - }); + console.log("WebSocket error: ", event); + }); - webSocket.addEventListener("close", () => { - console.log("WebSocket is closed now."); - ws.current = null; - }); + webSocket.addEventListener("close", () => { + console.log("WebSocket is closed now."); + ws.current = null; + }); - ws.current = webSocket; + ws.current = webSocket; - return () => { - webSocket.close(); - }; + return () => { + webSocket.close(); + }; + }, [url]); - }, [url]); + const sendMessage = useCallback((message: unknown) => { + if (ws.current && ws.current.readyState === WebSocket.OPEN) { + ws.current.send(JSON.stringify(message)); + // console.log("sending", message); + } else { + console.error("WebSocket is not open. Message not sent."); + } + }, []); - const sendMessage = useCallback((message: unknown) => { - if (ws.current && ws.current.readyState === WebSocket.OPEN) { - ws.current.send(JSON.stringify(message)); - } else { - console.error("WebSocket is not open. Message not sent."); - } - }, []); - - return {sendMessage}; -}; \ No newline at end of file + return { sendMessage }; +};