From 058ac24954e4f2aace79450eece1b494f7a74f97 Mon Sep 17 00:00:00 2001 From: AquaWolf <3daquawolf@gmail.com> Date: Fri, 28 Feb 2025 21:30:23 +0100 Subject: [PATCH] added first draft of the play route --- packages/www/package.json | 3 +- packages/www/src/App.tsx | 2 + packages/www/src/index.tsx | 10 ++- packages/www/src/pages/play.tsx | 149 ++++++++++++++++++++++++++++++++ 4 files changed, 160 insertions(+), 4 deletions(-) create mode 100644 packages/www/src/pages/play.tsx diff --git a/packages/www/package.json b/packages/www/package.json index 96c96968..fe20260c 100644 --- a/packages/www/package.json +++ b/packages/www/package.json @@ -27,6 +27,7 @@ "@solid-primitives/storage": "^4.3.1", "@solidjs/router": "^0.15.3", "modern-normalize": "^3.0.1", - "solid-js": "^1.9.5" + "solid-js": "^1.9.5", + "solid-notifications": "^1.1.2" } } \ No newline at end of file diff --git a/packages/www/src/App.tsx b/packages/www/src/App.tsx index efd3487d..59e032ad 100644 --- a/packages/www/src/App.tsx +++ b/packages/www/src/App.tsx @@ -7,6 +7,7 @@ import '@fontsource/geist-sans/700.css'; import '@fontsource/geist-sans/800.css'; import '@fontsource/geist-sans/900.css'; import { TeamCreate } from './pages/new'; +import { PlayComponent } from './pages/play'; import { styled } from "@macaron-css/solid"; import { useStorage } from './providers/account'; import { darkClass, lightClass, theme } from './ui/theme'; @@ -116,6 +117,7 @@ export const App: Component = () => { {WorkspaceRoute} */} + { diff --git a/packages/www/src/index.tsx b/packages/www/src/index.tsx index 608b9165..0bada0f9 100644 --- a/packages/www/src/index.tsx +++ b/packages/www/src/index.tsx @@ -8,6 +8,7 @@ import { render } from "solid-js/web"; import "modern-normalize/modern-normalize.css"; import { App } from "./App"; import { StorageProvider } from "./providers/account"; +import { ToastProvider, Toaster } from "solid-notifications"; const root = document.getElementById("root"); @@ -19,9 +20,12 @@ if (import.meta.env.DEV && !(root instanceof HTMLElement)) { render( () => ( - - - + + + + + + ), root! ); \ No newline at end of file diff --git a/packages/www/src/pages/play.tsx b/packages/www/src/pages/play.tsx new file mode 100644 index 00000000..669f97fe --- /dev/null +++ b/packages/www/src/pages/play.tsx @@ -0,0 +1,149 @@ +import { Text } from "@nestri/www/ui/text"; +import { createSignal, createEffect, onCleanup, onMount } from "solid-js"; +import { useParams } from "@solidjs/router"; +import { Modal } from "@nestri/ui"; +import { Keyboard, Mouse, WebRTCStream } from "@nestri/input"; + +export function PlayComponent() { + const params = useParams(); + const id = params.id; + + const [showBannerModal, setShowBannerModal] = createSignal(false); + const [showButtonModal, setShowButtonModal] = createSignal(false); + const [gamepadConnected, setGamepadConnected] = createSignal(false); + const [buttonPressed, setButtonPressed] = createSignal(null); + const [leftStickX, setLeftStickX] = createSignal(0); + const [leftStickY, setLeftStickY] = createSignal(0); + const [hasStream, setHasStream] = createSignal(false); + const [showOffline, setShowOffline] = createSignal(false); + + const [canvas, setCanvas] = createSignal(undefined); + let video: HTMLVideoElement; + let webrtc: WebRTCStream; + let nestriMouse: Mouse , nestriKeyboard: Keyboard; + + const initializeInputDevices = () => { + const canvasElement = canvas(); + if (!canvasElement || !webrtc) return; + try { + nestriMouse = new Mouse({ canvas: canvasElement, webrtc }); + nestriKeyboard = new Keyboard({ canvas: canvasElement, webrtc }); + console.log("Input devices initialized successfully"); + } catch (error) { + console.error("Failed to initialize input devices:", error); + } + }; + + /*const initializeGamepad = () => { + console.log("Initializing gamepad..."); + + const updateGamepadState = () => { + const gamepads = navigator.getGamepads(); + const gamepad = gamepads[0]; + if (gamepad) { + setButtonPressed(gamepad.buttons.findIndex(btn => btn.pressed) !== -1 ? "Button pressed" : null); + setLeftStickX(Number(gamepad.axes[0].toFixed(2))); + setLeftStickY(Number(gamepad.axes[1].toFixed(2))); + } + requestAnimationFrame(updateGamepadState); + }; + + window.addEventListener("gamepadconnected", () => { + setGamepadConnected(true); + console.log("Gamepad connected!"); + updateGamepadState(); + }); + + window.addEventListener("gamepaddisconnected", () => { + setGamepadConnected(false); + console.log("Gamepad disconnected!"); + }); + };*/ + + const lockPlay = async () => { + const canvasElement = canvas(); + if (!canvasElement || !hasStream()) return; + try { + await canvasElement.requestPointerLock(); + await canvasElement.requestFullscreen(); + //initializeGamepad(); + } catch (error) { + console.error("Error during lock sequence:", error); + } + }; + + const setupPointerLockListener = () => { + document.addEventListener("pointerlockchange", () => { + const canvasElement = canvas(); + if (!canvasElement) return; + if (document.pointerLockElement === canvasElement) { + initializeInputDevices(); + } else { + nestriKeyboard?.dispose(); + nestriMouse?.dispose(); + } + }); + }; + + const handleVideoInput = async () => { + const canvasElement = canvas(); + if (!video || !canvasElement) return; + + try { + + await video.play(); + if (canvasElement && video) { + canvasElement.width = video.videoWidth; + canvasElement.height = video.videoHeight; + + + const ctx = canvasElement.getContext("2d"); + const renderer = () => { + if (ctx && hasStream() && video) { + ctx.drawImage(video, 0, 0); + video.requestVideoFrameCallback(renderer); + } + }; + + video.requestVideoFrameCallback(renderer); + } + } catch (error) { + console.error("Error playing video:", error); + } + }; + + + onMount(() => { + setupPointerLockListener(); + video = document.createElement("video"); + video.style.visibility = "hidden"; + webrtc = new WebRTCStream("https://relay.dathorse.com", id, async (mediaStream) => { + if (video && mediaStream) { + video.srcObject = mediaStream; + setHasStream(true); + setShowOffline(false); + await handleVideoInput(); + } else { + setShowOffline(true); + setHasStream(false); + } + }); + }); + + onCleanup(() => { + nestriKeyboard?.dispose(); + nestriMouse?.dispose(); + }); + + return ( + <> + {showOffline() ? ( +
+ Offline +
+ ) : ( + + )} + + ); + } \ No newline at end of file