diff --git a/apps/client/package.json b/apps/client/package.json index 80bd459..a2efbe5 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -10,11 +10,16 @@ }, "dependencies": { "@repo/shared": "workspace:*", + "@types/react": "^19.2.13", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.1.3", "pixi.js": "^8.16.0", - "preact": "^10.27.2" + "react": "^19.2.4", + "react-dom": "^19.2.4", + "react-joystick-component": "^6.2.1", + "socket.io-client": "^4.8.3" }, "devDependencies": { - "@preact/preset-vite": "^2.10.2", "@types/node": "^24.10.1", "typescript": "~5.9.3", "vite": "^7.2.4" diff --git a/apps/client/src/app.tsx b/apps/client/src/app.tsx index 7077170..b0b5d8a 100644 --- a/apps/client/src/app.tsx +++ b/apps/client/src/app.tsx @@ -1,58 +1,241 @@ -import { useEffect, useRef } from 'preact/hooks'; -import { Application } from 'pixi.js'; +import { useEffect, useState, useRef } from "react"; +import { io, Socket } from "socket.io-client"; -// 👇 ここを変更しました! -// 元: import { Joystick } from './Joystick'; -import { Joystick } from './input/Joystick'; +// 設定:マップの広さ(全員共通) +const MAP_SIZE = 2000; +// ジョイスティックの設定(Joystick.ts のロジックを参考) +const MAX_DIST = 60; +type Player = { + id: string; + x: number; + y: number; + color: string; +}; -import { Player } from './entities/Player'; +function App() { + const [myId, setMyId] = useState(null); + const [players, setPlayers] = useState>({}); + + // 画面サイズ(カメラ計算用) + const [viewport, setViewport] = useState({ w: window.innerWidth, h: window.innerHeight }); + + // 自作ジョイスティックの状態管理 + const [isMoving, setIsMoving] = useState(false); + const [basePos, setBasePos] = useState({ x: 0, y: 0 }); // タッチを開始した中心点 + const [stickPos, setStickPos] = useState({ x: 0, y: 0 }); // スティックの相対移動量 + + // 自分の位置(計算用) + const myPosRef = useRef({ x: MAP_SIZE / 2, y: MAP_SIZE / 2 }); + const socketRef = useRef(null); + const initializedRef = useRef(false); -import './app.css'; + // 1. タッチ/クリック開始:ジョイスティックの拠点を決める + const handleStart = (e: React.TouchEvent | React.MouseEvent) => { + const clientX = 'touches' in e ? e.touches[0].clientX : (e as React.MouseEvent).clientX; + const clientY = 'touches' in e ? e.touches[0].clientY : (e as React.MouseEvent).clientY; + + setBasePos({ x: clientX, y: clientY }); + setStickPos({ x: 0, y: 0 }); + setIsMoving(true); + }; -export function App() { - const containerRef = useRef(null); + // 2. 移動中:スティックを動かし、プレイヤーを移動させる + const handleMove = (e: React.TouchEvent | React.MouseEvent) => { + if (!isMoving) return; + const clientX = 'touches' in e ? e.touches[0].clientX : (e as React.MouseEvent).clientX; + const clientY = 'touches' in e ? e.touches[0].clientY : (e as React.MouseEvent).clientY; + + // 中心からの距離と角度を計算 + const dx = clientX - basePos.x; + const dy = clientY - basePos.y; + const dist = Math.sqrt(dx * dx + dy * dy); + const angle = Math.atan2(dy, dx); + + // スティックが外枠からはみ出さないように制限 (Joystick.ts のロジック) + const limitedDist = Math.min(dist, MAX_DIST); + const moveX = Math.cos(angle) * limitedDist; + const moveY = Math.sin(angle) * limitedDist; + + setStickPos({ x: moveX, y: moveY }); + + // 入力値の正規化 (-1.0 ~ 1.0) + const inputX = moveX / MAX_DIST; + const inputY = moveY / MAX_DIST; + + if (!socketRef.current || !myId) return; + + // 移動の実行 + const speed = 5.0; + let nextX = myPosRef.current.x + (inputX * speed); + let nextY = myPosRef.current.y + (inputY * speed); + + // 壁判定 + if (nextX < 20) nextX = 20; + if (nextX > MAP_SIZE - 20) nextX = MAP_SIZE - 20; + if (nextY < 20) nextY = 20; + if (nextY > MAP_SIZE - 20) nextY = MAP_SIZE - 20; + + myPosRef.current = { x: nextX, y: nextY }; + + // 自分の画面を即座に更新 + setPlayers(prev => { + if (!prev[myId]) return prev; + return { ...prev, [myId]: { ...prev[myId], x: nextX, y: nextY } }; + }); + + // サーバーへ送信 + socketRef.current.emit("move", { x: nextX, y: nextY }); + }; + + // 3. 終了:ジョイスティックをリセット + const handleEnd = () => { + setIsMoving(false); + setStickPos({ x: 0, y: 0 }); + }; + + // 初期位置同期 useEffect(() => { - // 1. PixiJSアプリケーションの作成 - const app = new Application(); + if (!myId || initializedRef.current) return; + const me = players[myId]; + if (me) { + myPosRef.current = { x: me.x, y: me.y }; + initializedRef.current = true; + } + }, [players, myId]); - const initGame = async () => { - await app.init({ - resizeTo: window, - backgroundColor: 0x1099bb, - resolution: window.devicePixelRatio || 1, - autoDensity: true, + // Socket通信設定 + useEffect(() => { + const handleResize = () => setViewport({ w: window.innerWidth, h: window.innerHeight }); + window.addEventListener("resize", handleResize); + + socketRef.current = io(); + const socket = socketRef.current; + + socket.on("connect", () => setMyId(socket.id || null)); + socket.on("current_players", (serverPlayers: Player[]) => { + const pMap: Record = {}; + serverPlayers.forEach(p => pMap[p.id] = p); + setPlayers(pMap); + }); + socket.on("new_player", (p: Player) => setPlayers(prev => ({ ...prev, [p.id]: p }))); + socket.on("update_player", (d: { id: string; x: number; y: number }) => { + if (d.id === socket.id) return; + setPlayers(prev => { + const target = prev[d.id]; + if (!target) return prev; + return { ...prev, [d.id]: { ...target, x: d.x, y: d.y } }; }); - - if (containerRef.current) { - containerRef.current.appendChild(app.canvas); - } - - // 2. プレイヤーの作成 - const player = new Player(0xff0000); - player.x = app.screen.width / 2; - player.y = app.screen.height / 2; - app.stage.addChild(player); - - // 3. ジョイスティックの作成 - const joystick = new Joystick(); - app.stage.addChild(joystick); - - // 4. ゲームループ - app.ticker.add((ticker) => { - if (joystick.input.x !== 0 || joystick.input.y !== 0) { - player.move(joystick.input.x, joystick.input.y, ticker.deltaTime); - } + }); + socket.on("remove_player", (id: string) => { + setPlayers(prev => { + const next = { ...prev }; + delete next[id]; + return next; }); - }; - - initGame(); + }); return () => { - app.destroy(true, { children: true }); + socket.disconnect(); + window.removeEventListener("resize", handleResize); }; }, []); - return
; -} \ No newline at end of file + // カメラ計算 + let cameraX = 0; + let cameraY = 0; + if (myId && players[myId]) { + const me = players[myId]; + cameraX = me.x - viewport.w / 2; + cameraY = me.y - viewport.h / 2; + } + + return ( +
+ + {/* UIレイヤー */} +
+
● Online: {Object.keys(players).length}
+
ID: {myId?.slice(0, 4)}
+
+ + {/* ゲームワールド */} +
+ {Object.values(players).map((p) => ( +
+
+ {p.id.slice(0,4)} +
+
+ ))} +
+ + {/* 自作ジョイスティックのUI */} + {isMoving && ( +
+ {/* 内側の動くスティック部分 */} +
+
+ )} +
+ ); +} + +export default App; \ No newline at end of file diff --git a/apps/client/src/main.tsx b/apps/client/src/main.tsx index bfb172e..1b7c45c 100644 --- a/apps/client/src/main.tsx +++ b/apps/client/src/main.tsx @@ -1,5 +1,10 @@ -import { render } from 'preact' +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './app.tsx' // 小文字のままでOK import './index.css' -import { App } from './app.tsx' -render(, document.getElementById('app')!) +ReactDOM.createRoot(document.getElementById('app')!).render( + + + , +) \ No newline at end of file diff --git a/apps/client/tsconfig.app.json b/apps/client/tsconfig.app.json index 3fe3ab9..ed628d5 100644 --- a/apps/client/tsconfig.app.json +++ b/apps/client/tsconfig.app.json @@ -7,10 +7,6 @@ "lib": ["ES2022", "DOM", "DOM.Iterable"], "types": ["vite/client"], "skipLibCheck": true, - "paths": { - "react": ["./node_modules/preact/compat/"], - "react-dom": ["./node_modules/preact/compat/"] - }, /* Bundler mode */ "moduleResolution": "bundler", @@ -18,8 +14,13 @@ "verbatimModuleSyntax": true, "moduleDetection": "force", "noEmit": true, + + // ↓ ここが重要:React用に設定 "jsx": "react-jsx", - "jsxImportSource": "preact", + + // ⚠️ 削除したもの: + // - "paths": { ... } (Preactへの誘導を削除) + // - "jsxImportSource": "preact" (Preactのルールを削除) /* Linting */ "strict": true, @@ -30,4 +31,4 @@ "noUncheckedSideEffectImports": true }, "include": ["src"] -} +} \ No newline at end of file diff --git a/apps/client/vite.config.ts b/apps/client/vite.config.ts index 2591ed7..dfdf5f7 100644 --- a/apps/client/vite.config.ts +++ b/apps/client/vite.config.ts @@ -1,14 +1,30 @@ -import { defineConfig } from 'vite' -import preact from '@preact/preset-vite' +// src/index.ts +import { Server } from "socket.io"; +import { createServer } from "http"; // Node.js標準 of HTTPサーバー +import { GameManager } from "./managers/GameManager.js"; +import { SocketManager } from "./network/SocketManager.js"; -// https://vite.dev/config/ -export default defineConfig({ - plugins: [preact()], - server: { - host: true, // 0.0.0.0 でリッスンして外部アクセスを許可 - port: 5173, // ポート固定 - watch: { - usePolling: true // WSL2/Docker間のファイル変更検知を確実にする - } - } -}) +const PORT = 3000; + +// HTTPサーバーとSocket.ioサーバーの作成 +const httpServer = createServer(); +const io = new Server(httpServer, { + cors: { + origin: "*", // 開発用:どこからでも許可 + methods: ["GET", "POST"] + }, +}); + +// ゲームマネージャーと通信マネージャーの起動 +const gameManager = new GameManager(); +const socketManager = new SocketManager(io, gameManager); + +socketManager.initialize(); + +// サーバー起動 +httpServer.listen(PORT, () => { + console.log(` + 🚀 Server is running on port ${PORT} + waiting for connections... + `); +}); \ No newline at end of file diff --git a/apps/server/package.json b/apps/server/package.json index be42c55..632e620 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -15,11 +15,11 @@ "packageManager": "pnpm@10.28.2", "dependencies": { "@repo/shared": "workspace:*", - "ws": "^8.19.0" + "socket.io": "^4.8.3" }, "devDependencies": { "@types/node": "^24.10.11", - "@types/ws": "^8.18.1", + "@types/socket.io": "^3.0.2", "tsx": "^4.21.0", "typescript": "^5.9.3" } diff --git a/apps/server/src/entities/Player.ts b/apps/server/src/entities/Player.ts new file mode 100644 index 0000000..efd60a8 --- /dev/null +++ b/apps/server/src/entities/Player.ts @@ -0,0 +1,17 @@ +// src/entities/Player.ts +export class Player { + public id: string; + public x: number = 0; + public y: number = 0; + public color: string; + + constructor(id: string) { + this.id = id; + /* + this.x = Math.floor(Math.random() * 1000) + 500; + this.y = Math.floor(Math.random() * 1000) + 500; + */ + // ランダムな色をつけるとおしゃれです + this.color = '#' + Math.floor(Math.random()*16777215).toString(16); + } +} \ No newline at end of file diff --git a/apps/server/src/index.ts b/apps/server/src/index.ts index 7d8c7af..407cb13 100644 --- a/apps/server/src/index.ts +++ b/apps/server/src/index.ts @@ -1,22 +1,14 @@ -import { WebSocketServer } from "ws"; +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' -// サーバーをポート3000で起動(これで常駐モードになります) -const wss = new WebSocketServer({ port: 3000 }); - -console.log("Pixel Paint War Server started on port 3000"); - -// クライアントからの接続を待ち受けるイベント -wss.on("connection", (ws) => { - console.log("New client connected!"); - - ws.on("message", (message) => { - console.log("Received:", message); - ws.send(`Server received: ${message}`); - }); - - ws.on("close", () => { - console.log("Client disconnected"); - }); - - ws.send("Welcome to Pixel Paint War Server!"); -}); +export default defineConfig({ + plugins: [react()], + server: { + proxy: { + '/socket.io': { + target: 'http://localhost:3000', + ws: true, + }, + }, + }, +}) \ No newline at end of file diff --git a/apps/server/src/managers/GameManager.ts b/apps/server/src/managers/GameManager.ts new file mode 100644 index 0000000..899a6c2 --- /dev/null +++ b/apps/server/src/managers/GameManager.ts @@ -0,0 +1,75 @@ +import { Player } from "../entities/Player.js"; + +export class GameManager { + private players: Map; + + constructor() { + this.players = new Map(); + } + + // プレイヤー追加 + addPlayer(id: string): Player { + const player = new Player(id); + + // ★初期位置をマップの中央(1000, 1000)に設定 + player.x = 1000; + player.y = 1000; + + this.players.set(id, player); + return player; + } + + // プレイヤー削除 + removePlayer(id: string) { + this.players.delete(id); + } + + // プレイヤー取得 + getPlayer(id: string) { + return this.players.get(id); + } + + // プレイヤー移動 + movePlayer(id: string, x: number, y: number) { + const player = this.players.get(id); + if (player) { + + // ▼▼▼ リクエスト通り、ログを残しました ▼▼▼ + // これでサーバーのターミナルを見れば、座標が届いているかわかります + console.log(`Move Request -> ID:${id.slice(0,4)} x:${Math.round(x)} y:${Math.round(y)}`); + + // データチェック + if (typeof x !== "number" || typeof y !== "number" || isNaN(x) || isNaN(y)) { + console.log("⚠️ 無効なデータなので無視しました"); + return; + } + + // ★重要修正★ + // クライアント側で計算済みの座標(x, y)が送られてくるので、 + // ここで speed を掛けたり、+= で足したりしてはいけません。 + // そのまま「代入」するのが正解です。 + + let nextX = x; + let nextY = y; + + const MAP_SIZE = 2000; + const PLAYER_SIZE = 20; + + // 画面端の制限(クランプ処理) + // 0 〜 2000 の範囲からはみ出さないようにする + if (nextX < 0) nextX = 0; + if (nextX > MAP_SIZE - PLAYER_SIZE) nextX = MAP_SIZE - PLAYER_SIZE; + if (nextY < 0) nextY = 0; + if (nextY > MAP_SIZE - PLAYER_SIZE) nextY = MAP_SIZE - PLAYER_SIZE; + + // 位置を更新 + player.x = nextX; + player.y = nextY; + } + } + + // 全プレイヤー情報を返す + getAllPlayers() { + return Array.from(this.players.values()); + } +} \ No newline at end of file diff --git a/apps/server/src/network/SocketManager.ts b/apps/server/src/network/SocketManager.ts new file mode 100644 index 0000000..6536984 --- /dev/null +++ b/apps/server/src/network/SocketManager.ts @@ -0,0 +1,54 @@ +// src/network/SocketManager.ts +import { Server, Socket } from "socket.io"; +import { GameManager } from "../managers/GameManager.js"; + +export class SocketManager { + private io: Server; + private gameManager: GameManager; + + constructor(io: Server, gameManager: GameManager) { + this.io = io; + this.gameManager = gameManager; + } + + public initialize() { + this.io.on("connection", (socket: Socket) => { + console.log(`✅ User connected: ${socket.id}`); + + // 1. ゲームにプレイヤーを追加 + const player = this.gameManager.addPlayer(socket.id); + + // 2. 参加した本人に「現在の全プレイヤー」を教える + socket.emit("current_players", this.gameManager.getAllPlayers()); + + // 3. 他のみんなに「新しい人が来たよ」と教える + socket.broadcast.emit("new_player", player); + + // --- イベント受信 --- + + // 移動データが来た時 + socket.on("move", (data: { x: number; y: number }) => { + // マネージャーの状態を更新 + this.gameManager.movePlayer(socket.id, data.x, data.y); + + // 全員に位置情報を配信 + // (人数が増えたらここを最適化しますが、まずはこれでOK) + const updatedPlayer = this.gameManager.getPlayer(socket.id); + if (updatedPlayer) { + this.io.emit("update_player", { + id: socket.id, + x: updatedPlayer.x, + y: updatedPlayer.y + }); + } + }); + + // 切断した時 + socket.on("disconnect", () => { + console.log(`❌ User disconnected: ${socket.id}`); + this.gameManager.removePlayer(socket.id); + this.io.emit("remove_player", socket.id); + }); + }); + } +} \ No newline at end of file diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index e69de29..9797972 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -0,0 +1 @@ +export * from './config/gameConfig'; \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ab4dacf..a5bc9ba 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,16 +13,31 @@ '@repo/shared': specifier: workspace:* version: link:../../packages/shared + '@types/react': + specifier: ^19.2.13 + version: 19.2.13 + '@types/react-dom': + specifier: ^19.2.3 + version: 19.2.3(@types/react@19.2.13) + '@vitejs/plugin-react': + specifier: ^5.1.3 + version: 5.1.3(vite@7.3.1(@types/node@24.10.11)(tsx@4.21.0)) pixi.js: specifier: ^8.16.0 version: 8.16.0 - preact: - specifier: ^10.27.2 - version: 10.28.3 + react: + specifier: ^19.2.4 + version: 19.2.4 + react-dom: + specifier: ^19.2.4 + version: 19.2.4(react@19.2.4) + react-joystick-component: + specifier: ^6.2.1 + version: 6.2.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + socket.io-client: + specifier: ^4.8.3 + version: 4.8.3 devDependencies: - '@preact/preset-vite': - specifier: ^2.10.2 - version: 2.10.3(@babel/core@7.29.0)(preact@10.28.3)(rollup@4.57.1)(vite@7.3.1(@types/node@24.10.11)(tsx@4.21.0)) '@types/node': specifier: ^24.10.1 version: 24.10.11 @@ -38,16 +53,16 @@ '@repo/shared': specifier: workspace:* version: link:../../packages/shared - ws: - specifier: ^8.19.0 - version: 8.19.0 + socket.io: + specifier: ^4.8.3 + version: 4.8.3 devDependencies: '@types/node': specifier: ^24.10.11 version: 24.10.11 - '@types/ws': - specifier: ^8.18.1 - version: 8.18.1 + '@types/socket.io': + specifier: ^3.0.2 + version: 3.0.2 tsx: specifier: ^4.21.0 version: 4.21.0 @@ -82,10 +97,6 @@ resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} engines: {node: '>=6.9.0'} - '@babel/helper-annotate-as-pure@7.27.3': - resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} - engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.28.6': resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} engines: {node: '>=6.9.0'} @@ -129,20 +140,14 @@ engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-syntax-jsx@7.28.6': - resolution: {integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==} + '@babel/plugin-transform-react-jsx-self@7.27.1': + resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-react-jsx-development@7.27.1': - resolution: {integrity: sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-react-jsx@7.28.6': - resolution: {integrity: sha512-61bxqhiRfAACulXSLd/GxqmAedUSrRZIu/cbaT18T1CetkTmtDN15it7i80ru4DVqRK1WMxQhXs+Lf9kajm5Ow==} + '@babel/plugin-transform-react-jsx-source@7.27.1': + resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -334,41 +339,8 @@ '@pixi/colord@2.9.6': resolution: {integrity: sha512-nezytU2pw587fQstUu1AsJZDVEynjskwOL+kibwcdxsMBFqPsFFNA7xl0ii/gXuDi6M0xj3mfRJj8pBSc2jCfA==} - '@preact/preset-vite@2.10.3': - resolution: {integrity: sha512-1SiS+vFItpkNdBs7q585PSAIln0wBeBdcpJYbzPs1qipsb/FssnkUioNXuRsb8ZnU8YEQHr+3v8+/mzWSnTQmg==} - peerDependencies: - '@babel/core': 7.x - vite: 2.x || 3.x || 4.x || 5.x || 6.x || 7.x - - '@prefresh/babel-plugin@0.5.2': - resolution: {integrity: sha512-AOl4HG6dAxWkJ5ndPHBgBa49oo/9bOiJuRDKHLSTyH+Fd9x00shTXpdiTj1W41l6oQIwUOAgJeHMn4QwIDpHkA==} - - '@prefresh/core@1.5.9': - resolution: {integrity: sha512-IKBKCPaz34OFVC+adiQ2qaTF5qdztO2/4ZPf4KsRTgjKosWqxVXmEbxCiUydYZRY8GVie+DQlKzQr9gt6HQ+EQ==} - peerDependencies: - preact: ^10.0.0 || ^11.0.0-0 - - '@prefresh/utils@1.2.1': - resolution: {integrity: sha512-vq/sIuN5nYfYzvyayXI4C2QkprfNaHUQ9ZX+3xLD8nL3rWyzpxOm1+K7RtMbhd+66QcaISViK7amjnheQ/4WZw==} - - '@prefresh/vite@2.4.11': - resolution: {integrity: sha512-/XjURQqdRiCG3NpMmWqE9kJwrg9IchIOWHzulCfqg2sRe/8oQ1g5De7xrk9lbqPIQLn7ntBkKdqWXIj4E9YXyg==} - peerDependencies: - preact: ^10.4.0 || ^11.0.0-0 - vite: '>=2.0.0' - - '@rollup/pluginutils@4.2.1': - resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} - engines: {node: '>= 8.0.0'} - - '@rollup/pluginutils@5.3.0': - resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true + '@rolldown/pluginutils@1.0.0-rc.2': + resolution: {integrity: sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw==} '@rollup/rollup-android-arm-eabi@4.57.1': resolution: {integrity: sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==} @@ -508,6 +480,24 @@ cpu: [x64] os: [win32] + '@socket.io/component-emitter@3.1.2': + resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.28.0': + resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + + '@types/cors@2.8.19': + resolution: {integrity: sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==} + '@types/earcut@3.0.0': resolution: {integrity: sha512-k/9fOUGO39yd2sCjrbAJvGDEQvRwRnQIZlBz43roGwUZo5SHAmyVvSFyaVVZkicRVCaDXPKlbxrUcBuJoSWunQ==} @@ -517,8 +507,23 @@ '@types/node@24.10.11': resolution: {integrity: sha512-/Af7O8r1frCVgOz0I62jWUtMohJ0/ZQU/ZoketltOJPZpnb17yoNc9BSoVuV9qlaIXJiPNOpsfq4ByFajSArNQ==} - '@types/ws@8.18.1': - resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + '@types/react-dom@19.2.3': + resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} + peerDependencies: + '@types/react': ^19.2.0 + + '@types/react@19.2.13': + resolution: {integrity: sha512-KkiJeU6VbYbUOp5ITMIc7kBfqlYkKA5KhEHVrGMmUUMt7NeaZg65ojdPk+FtNrBAOXNVM5QM72jnADjM+XVRAQ==} + + '@types/socket.io@3.0.2': + resolution: {integrity: sha512-pu0sN9m5VjCxBZVK8hW37ZcMe8rjn4HHggBN5CbaRTvFwv5jOmuIRZEuddsBPa9Th0ts0SIo3Niukq+95cMBbQ==} + deprecated: This is a stub types definition. socket.io provides its own type definitions, so you do not need this installed. + + '@vitejs/plugin-react@5.1.3': + resolution: {integrity: sha512-NVUnA6gQCl8jfoYqKqQU5Clv0aPw14KkZYCsX6T9Lfu9slI0LOU10OTwFHS/WmptsMMpshNd/1tuWsHQ2Uk+cg==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 '@webgpu/types@0.1.69': resolution: {integrity: sha512-RPmm6kgRbI8e98zSD3RVACvnuktIja5+yLgDAkTmxLr90BEwdTXRQWNLF3ETTTyH/8mKhznZuN5AveXYFEsMGQ==} @@ -527,6 +532,10 @@ resolution: {integrity: sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==} engines: {node: '>=10.0.0'} + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + acorn@8.15.0: resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} engines: {node: '>=0.4.0'} @@ -535,18 +544,14 @@ any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} - babel-plugin-transform-hook-names@1.0.2: - resolution: {integrity: sha512-5gafyjyyBTTdX/tQQ0hRgu4AhNHG/hqWi0ZZmg2xvs2FgRkJXzDNKBZCyoYqgFkovfDrgM8OoKg8karoUvWeCw==} - peerDependencies: - '@babel/core': ^7.12.10 + base64id@2.0.0: + resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} + engines: {node: ^4.5.0 || >= 5.9} baseline-browser-mapping@2.9.19: resolution: {integrity: sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==} hasBin: true - boolbase@1.0.0: - resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - browserslist@4.28.1: resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} @@ -583,12 +588,16 @@ convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - css-select@5.2.2: - resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} - css-what@6.2.2: - resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} - engines: {node: '>= 6'} + cors@2.8.6: + resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} + engines: {node: '>= 0.10'} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} @@ -599,28 +608,22 @@ supports-color: optional: true - dom-serializer@2.0.0: - resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} - - domelementtype@2.3.0: - resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - - domhandler@5.0.3: - resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} - engines: {node: '>= 4'} - - domutils@3.2.2: - resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} - earcut@3.0.2: resolution: {integrity: sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==} electron-to-chromium@1.5.286: resolution: {integrity: sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==} - entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} - engines: {node: '>=0.12'} + engine.io-client@6.6.4: + resolution: {integrity: sha512-+kjUJnZGwzewFDw951CDWcwj35vMNf2fcj7xQWOctq1F2i1jkDdVvdFG9kM/BEChymCH36KgjnW0NsL58JYRxw==} + + engine.io-parser@5.2.3: + resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==} + engines: {node: '>=10.0.0'} + + engine.io@6.6.5: + resolution: {integrity: sha512-2RZdgEbXmp5+dVbRm0P7HQUImZpICccJy7rN7Tv+SFa55pH+lxnuw6/K1ZxxBfHoYpSkHLAO92oa8O4SwFXA2A==} + engines: {node: '>=10.2.0'} esbuild@0.27.3: resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==} @@ -631,9 +634,6 @@ resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} - estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - eventemitter3@5.0.4: resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} @@ -664,10 +664,6 @@ gifuct-js@2.1.2: resolution: {integrity: sha512-rI2asw77u0mGgwhV3qA+OEgYqaDn5UNqgs+Bx0FGwSpuqfYn+Ir6RQY5ENNQ8SbIiG/m5gVa7CD5RriO4f4Lsg==} - he@1.2.0: - resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} - hasBin: true - ismobilejs@1.1.1: resolution: {integrity: sha512-VaFW53yt8QO61k2WJui0dHf4SlL8lxBofUuUmwBo0ljPk0Drz2TiuDW4jo3wDcv41qy/SxrJ+VAzJ/qYqsmzRw==} @@ -691,9 +687,6 @@ engines: {node: '>=6'} hasBin: true - kolorist@1.8.0: - resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} - lilconfig@3.1.3: resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} engines: {node: '>=14'} @@ -711,6 +704,14 @@ magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + mlly@1.8.0: resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==} @@ -725,15 +726,13 @@ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - node-html-parser@6.1.13: - resolution: {integrity: sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==} + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} node-releases@2.0.27: resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} - nth-check@2.1.1: - resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -747,10 +746,6 @@ picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - picomatch@4.0.3: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} @@ -787,8 +782,24 @@ resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} - preact@10.28.3: - resolution: {integrity: sha512-tCmoRkPQLpBeWzpmbhryairGnhW9tKV6c6gr/w+RhoRoKEJwsjzipwp//1oCpGPOchvSLaAPlpcJi9MwMmoPyA==} + react-dom@19.2.4: + resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==} + peerDependencies: + react: ^19.2.4 + + react-joystick-component@6.2.1: + resolution: {integrity: sha512-0G5Y5aX4hNuXB3xJCwz6Q+nYQOtC6kprNGKmZxmfoPvhepNYUiid0DbLEGZxmr/UKip3S/LUbcQUobtRCuB8IQ==} + peerDependencies: + react: '>=17.0.2' + react-dom: '>=17.0.2' + + react-refresh@0.18.0: + resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} + engines: {node: '>=0.10.0'} + + react@19.2.4: + resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==} + engines: {node: '>=0.10.0'} readdirp@4.1.2: resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} @@ -806,12 +817,27 @@ engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + scheduler@0.27.0: + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - simple-code-frame@1.3.0: - resolution: {integrity: sha512-MB4pQmETUBlNs62BBeRjIFGeuy/x6gGKh7+eRUemn1rCFhqo7K+4slPqsyizCbcbYLnaYqaoZ2FWsZ/jN06D8w==} + socket.io-adapter@2.5.6: + resolution: {integrity: sha512-DkkO/dz7MGln0dHn5bmN3pPy+JmywNICWrJqVWiVOyvXjWQFIv9c2h24JrQLLFJ2aQVQf/Cvl1vblnd4r2apLQ==} + + socket.io-client@4.8.3: + resolution: {integrity: sha512-uP0bpjWrjQmUt5DTHq9RuoCBdFJF10cdX9X+a368j/Ft0wmaVgxlrjvK3kjvgCODOMMOz9lcaRzxmso0bTWZ/g==} + engines: {node: '>=10.0.0'} + + socket.io-parser@4.2.5: + resolution: {integrity: sha512-bPMmpy/5WWKHea5Y/jYAP6k74A+hvmRCQaJuJB6I/ML5JZq/KfNieUVo/3Mh7SAqn7TyFdIo6wqYHInG1MU1bQ==} + engines: {node: '>=10.0.0'} + + socket.io@4.8.3: + resolution: {integrity: sha512-2Dd78bqzzjE6KPkD5fHZmDAKRNe3J15q+YHDrIsy9WEkqttc7GY+kT9OBLSMaPbQaEd0x1BjcmtMtXkfpc+T5A==} + engines: {node: '>=10.2.0'} source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} @@ -821,10 +847,6 @@ resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} engines: {node: '>= 12'} - stack-trace@1.0.0-pre2: - resolution: {integrity: sha512-2ztBJRek8IVofG9DBJqdy2N5kulaacX30Nz7xmkYF6ale9WBVmIy6mFBchvGX7Vx/MyjBhx+Rcxqrj+dbOnQ6A==} - engines: {node: '>=16'} - sucrase@3.35.1: resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==} engines: {node: '>=16 || 14 >=14.17'} @@ -896,10 +918,9 @@ peerDependencies: browserslist: '>= 4.21.0' - vite-prerender-plugin@0.5.12: - resolution: {integrity: sha512-EiwhbMn+flg14EysbLTmZSzq8NGTxhytgK3bf4aGRF1evWLGwZiHiUJ1KZDvbxgKbMf2pG6fJWGEa3UZXOnR1g==} - peerDependencies: - vite: 5.x || 6.x || 7.x + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} vite@7.3.1: resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==} @@ -941,8 +962,8 @@ yaml: optional: true - ws@8.19.0: - resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==} + ws@8.18.3: + resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -953,6 +974,10 @@ utf-8-validate: optional: true + xmlhttprequest-ssl@2.1.2: + resolution: {integrity: sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==} + engines: {node: '>=0.4.0'} + yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} @@ -994,10 +1019,6 @@ '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 - '@babel/helper-annotate-as-pure@7.27.3': - dependencies: - '@babel/types': 7.29.0 - '@babel/helper-compilation-targets@7.28.6': dependencies: '@babel/compat-data': 7.29.0 @@ -1041,28 +1062,15 @@ dependencies: '@babel/types': 7.29.0 - '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-react-jsx-development@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@7.29.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-react-jsx@7.28.6(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-module-imports': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) - '@babel/types': 7.29.0 - transitivePeerDependencies: - - supports-color '@babel/template@7.28.6': dependencies: @@ -1186,55 +1194,7 @@ '@pixi/colord@2.9.6': {} - '@preact/preset-vite@2.10.3(@babel/core@7.29.0)(preact@10.28.3)(rollup@4.57.1)(vite@7.3.1(@types/node@24.10.11)(tsx@4.21.0))': - dependencies: - '@babel/core': 7.29.0 - '@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.29.0) - '@prefresh/vite': 2.4.11(preact@10.28.3)(vite@7.3.1(@types/node@24.10.11)(tsx@4.21.0)) - '@rollup/pluginutils': 5.3.0(rollup@4.57.1) - babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.29.0) - debug: 4.4.3 - picocolors: 1.1.1 - vite: 7.3.1(@types/node@24.10.11)(tsx@4.21.0) - vite-prerender-plugin: 0.5.12(vite@7.3.1(@types/node@24.10.11)(tsx@4.21.0)) - transitivePeerDependencies: - - preact - - rollup - - supports-color - - '@prefresh/babel-plugin@0.5.2': {} - - '@prefresh/core@1.5.9(preact@10.28.3)': - dependencies: - preact: 10.28.3 - - '@prefresh/utils@1.2.1': {} - - '@prefresh/vite@2.4.11(preact@10.28.3)(vite@7.3.1(@types/node@24.10.11)(tsx@4.21.0))': - dependencies: - '@babel/core': 7.29.0 - '@prefresh/babel-plugin': 0.5.2 - '@prefresh/core': 1.5.9(preact@10.28.3) - '@prefresh/utils': 1.2.1 - '@rollup/pluginutils': 4.2.1 - preact: 10.28.3 - vite: 7.3.1(@types/node@24.10.11)(tsx@4.21.0) - transitivePeerDependencies: - - supports-color - - '@rollup/pluginutils@4.2.1': - dependencies: - estree-walker: 2.0.2 - picomatch: 2.3.1 - - '@rollup/pluginutils@5.3.0(rollup@4.57.1)': - dependencies: - '@types/estree': 1.0.8 - estree-walker: 2.0.2 - picomatch: 4.0.3 - optionalDependencies: - rollup: 4.57.1 + '@rolldown/pluginutils@1.0.0-rc.2': {} '@rollup/rollup-android-arm-eabi@4.57.1': optional: true @@ -1311,6 +1271,33 @@ '@rollup/rollup-win32-x64-msvc@4.57.1': optional: true + '@socket.io/component-emitter@3.1.2': {} + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.28.0 + + '@types/babel__generator@7.27.0': + dependencies: + '@babel/types': 7.29.0 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + + '@types/babel__traverse@7.28.0': + dependencies: + '@babel/types': 7.29.0 + + '@types/cors@2.8.19': + dependencies: + '@types/node': 24.10.11 + '@types/earcut@3.0.0': {} '@types/estree@1.0.8': {} @@ -1319,26 +1306,51 @@ dependencies: undici-types: 7.16.0 - '@types/ws@8.18.1': + '@types/react-dom@19.2.3(@types/react@19.2.13)': dependencies: - '@types/node': 24.10.11 + '@types/react': 19.2.13 + + '@types/react@19.2.13': + dependencies: + csstype: 3.2.3 + + '@types/socket.io@3.0.2': + dependencies: + socket.io: 4.8.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@vitejs/plugin-react@5.1.3(vite@7.3.1(@types/node@24.10.11)(tsx@4.21.0))': + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0) + '@rolldown/pluginutils': 1.0.0-rc.2 + '@types/babel__core': 7.20.5 + react-refresh: 0.18.0 + vite: 7.3.1(@types/node@24.10.11)(tsx@4.21.0) + transitivePeerDependencies: + - supports-color '@webgpu/types@0.1.69': {} '@xmldom/xmldom@0.8.11': {} + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + acorn@8.15.0: {} any-promise@1.3.0: {} - babel-plugin-transform-hook-names@1.0.2(@babel/core@7.29.0): - dependencies: - '@babel/core': 7.29.0 + base64id@2.0.0: {} baseline-browser-mapping@2.9.19: {} - boolbase@1.0.0: {} - browserslist@4.28.1: dependencies: baseline-browser-mapping: 2.9.19 @@ -1368,43 +1380,52 @@ convert-source-map@2.0.0: {} - css-select@5.2.2: - dependencies: - boolbase: 1.0.0 - css-what: 6.2.2 - domhandler: 5.0.3 - domutils: 3.2.2 - nth-check: 2.1.1 + cookie@0.7.2: {} - css-what@6.2.2: {} + cors@2.8.6: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + + csstype@3.2.3: {} debug@4.4.3: dependencies: ms: 2.1.3 - dom-serializer@2.0.0: - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - entities: 4.5.0 - - domelementtype@2.3.0: {} - - domhandler@5.0.3: - dependencies: - domelementtype: 2.3.0 - - domutils@3.2.2: - dependencies: - dom-serializer: 2.0.0 - domelementtype: 2.3.0 - domhandler: 5.0.3 - earcut@3.0.2: {} electron-to-chromium@1.5.286: {} - entities@4.5.0: {} + engine.io-client@6.6.4: + dependencies: + '@socket.io/component-emitter': 3.1.2 + debug: 4.4.3 + engine.io-parser: 5.2.3 + ws: 8.18.3 + xmlhttprequest-ssl: 2.1.2 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + engine.io-parser@5.2.3: {} + + engine.io@6.6.5: + dependencies: + '@types/cors': 2.8.19 + '@types/node': 24.10.11 + accepts: 1.3.8 + base64id: 2.0.0 + cookie: 0.7.2 + cors: 2.8.6 + debug: 4.4.3 + engine.io-parser: 5.2.3 + ws: 8.18.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate esbuild@0.27.3: optionalDependencies: @@ -1437,8 +1458,6 @@ escalade@3.2.0: {} - estree-walker@2.0.2: {} - eventemitter3@5.0.4: {} fdir@6.5.0(picomatch@4.0.3): @@ -1464,8 +1483,6 @@ dependencies: js-binary-schema-parser: 2.0.3 - he@1.2.0: {} - ismobilejs@1.1.1: {} joycon@3.1.1: {} @@ -1478,8 +1495,6 @@ json5@2.2.3: {} - kolorist@1.8.0: {} - lilconfig@3.1.3: {} lines-and-columns@1.2.4: {} @@ -1494,6 +1509,12 @@ dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + mlly@1.8.0: dependencies: acorn: 8.15.0 @@ -1511,17 +1532,10 @@ nanoid@3.3.11: {} - node-html-parser@6.1.13: - dependencies: - css-select: 5.2.2 - he: 1.2.0 + negotiator@0.6.3: {} node-releases@2.0.27: {} - nth-check@2.1.1: - dependencies: - boolbase: 1.0.0 - object-assign@4.1.1: {} parse-svg-path@0.1.2: {} @@ -1530,8 +1544,6 @@ picocolors@1.1.1: {} - picomatch@2.3.1: {} - picomatch@4.0.3: {} pirates@4.0.7: {} @@ -1568,7 +1580,19 @@ picocolors: 1.1.1 source-map-js: 1.2.1 - preact@10.28.3: {} + react-dom@19.2.4(react@19.2.4): + dependencies: + react: 19.2.4 + scheduler: 0.27.0 + + react-joystick-component@6.2.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + dependencies: + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + react-refresh@0.18.0: {} + + react@19.2.4: {} readdirp@4.1.2: {} @@ -1607,18 +1631,55 @@ '@rollup/rollup-win32-x64-msvc': 4.57.1 fsevents: 2.3.3 + scheduler@0.27.0: {} + semver@6.3.1: {} - simple-code-frame@1.3.0: + socket.io-adapter@2.5.6: dependencies: - kolorist: 1.8.0 + debug: 4.4.3 + ws: 8.18.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + socket.io-client@4.8.3: + dependencies: + '@socket.io/component-emitter': 3.1.2 + debug: 4.4.3 + engine.io-client: 6.6.4 + socket.io-parser: 4.2.5 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + socket.io-parser@4.2.5: + dependencies: + '@socket.io/component-emitter': 3.1.2 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + socket.io@4.8.3: + dependencies: + accepts: 1.3.8 + base64id: 2.0.0 + cors: 2.8.6 + debug: 4.4.3 + engine.io: 6.6.5 + socket.io-adapter: 2.5.6 + socket.io-parser: 4.2.5 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate source-map-js@1.2.1: {} source-map@0.7.6: {} - stack-trace@1.0.0-pre2: {} - sucrase@3.35.1: dependencies: '@jridgewell/gen-mapping': 0.3.13 @@ -1697,15 +1758,7 @@ escalade: 3.2.0 picocolors: 1.1.1 - vite-prerender-plugin@0.5.12(vite@7.3.1(@types/node@24.10.11)(tsx@4.21.0)): - dependencies: - kolorist: 1.8.0 - magic-string: 0.30.21 - node-html-parser: 6.1.13 - simple-code-frame: 1.3.0 - source-map: 0.7.6 - stack-trace: 1.0.0-pre2 - vite: 7.3.1(@types/node@24.10.11)(tsx@4.21.0) + vary@1.1.2: {} vite@7.3.1(@types/node@24.10.11)(tsx@4.21.0): dependencies: @@ -1720,6 +1773,8 @@ fsevents: 2.3.3 tsx: 4.21.0 - ws@8.19.0: {} + ws@8.18.3: {} + + xmlhttprequest-ssl@2.1.2: {} yallist@3.1.1: {}