From b13b46b17daa5b6ab3ea9527b9a29c3d88507cdf Mon Sep 17 00:00:00 2001 From: Mitchell McCaffrey Date: Fri, 1 Jan 2021 12:37:54 +1100 Subject: [PATCH] Moved pointer out of player state and into separate socket event --- src/components/map/MapInteraction.js | 26 +++++------- src/components/party/Party.js | 4 +- src/contexts/PlayerContext.js | 24 +---------- src/network/NetworkedMapPointer.js | 59 +++++++++++++++------------- 4 files changed, 43 insertions(+), 70 deletions(-) diff --git a/src/components/map/MapInteraction.js b/src/components/map/MapInteraction.js index a55e3c1..8f89ecc 100644 --- a/src/components/map/MapInteraction.js +++ b/src/components/map/MapInteraction.js @@ -18,8 +18,6 @@ import MapStageContext, { import AuthContext from "../../contexts/AuthContext"; import SettingsContext from "../../contexts/SettingsContext"; import KeyboardContext from "../../contexts/KeyboardContext"; -import { PlayerUpdaterContext } from "../../contexts/PlayerContext"; -import PartyContext from "../../contexts/PartyContext"; function MapInteraction({ map, @@ -180,8 +178,6 @@ function MapInteraction({ const auth = useContext(AuthContext); const settings = useContext(SettingsContext); - const player = useContext(PlayerUpdaterContext); - const party = useContext(PartyContext); const mapInteraction = { stageScale, @@ -223,19 +219,15 @@ function MapInteraction({ /> {/* Forward auth context to konva elements */} - - - - - - - {mapLoaded && children} - - - - - - + + + + + {mapLoaded && children} + + + + diff --git a/src/components/party/Party.js b/src/components/party/Party.js index 45eee01..b766946 100644 --- a/src/components/party/Party.js +++ b/src/components/party/Party.js @@ -17,12 +17,12 @@ import useSetting from "../../helpers/useSetting"; import PartyContext from "../../contexts/PartyContext"; import { PlayerUpdaterContext, - PlayerStateWithoutPointerContext, + PlayerStateContext, } from "../../contexts/PlayerContext"; function Party({ gameId, stream, partyStreams, onStreamStart, onStreamEnd }) { const setPlayerState = useContext(PlayerUpdaterContext); - const playerState = useContext(PlayerStateWithoutPointerContext); + const playerState = useContext(PlayerStateContext); const partyState = useContext(PartyContext); const [fullScreen] = useSetting("map.fullScreen"); diff --git a/src/contexts/PlayerContext.js b/src/contexts/PlayerContext.js index 4a756da..c3c1cca 100644 --- a/src/contexts/PlayerContext.js +++ b/src/contexts/PlayerContext.js @@ -9,10 +9,6 @@ import { getRandomMonster } from "../helpers/monsters"; export const PlayerStateContext = React.createContext(); export const PlayerUpdaterContext = React.createContext(() => {}); -/** - * Store the player state without the pointer data to prevent unnecessary updates - */ -export const PlayerStateWithoutPointerContext = React.createContext(); export function PlayerProvider({ session, children }) { const { userId } = useContext(AuthContext); @@ -23,7 +19,6 @@ export function PlayerProvider({ session, children }) { nickname: "", timer: null, dice: { share: false, rolls: [] }, - pointer: { position: { x: 0, y: 0 }, visible: false }, sessionId: null, userId, }, @@ -94,27 +89,10 @@ export function PlayerProvider({ session, children }) { }; }); - const [playerStateWithoutPointer, setPlayerStateWithoutPointer] = useState( - playerState - ); - useEffect(() => { - const { pointer, ...state } = playerState; - if ( - !playerStateWithoutPointer || - !compare(playerStateWithoutPointer, state) - ) { - setPlayerStateWithoutPointer(state); - } - }, [playerState, playerStateWithoutPointer]); - return ( - - {children} - + {children} ); diff --git a/src/network/NetworkedMapPointer.js b/src/network/NetworkedMapPointer.js index afa4374..9494eba 100644 --- a/src/network/NetworkedMapPointer.js +++ b/src/network/NetworkedMapPointer.js @@ -2,24 +2,23 @@ import React, { useState, useContext, useEffect, useRef } from "react"; import { Group } from "react-konva"; import AuthContext from "../contexts/AuthContext"; -import PartyContext from "../contexts/PartyContext"; -import { PlayerUpdaterContext } from "../contexts/PlayerContext"; import MapPointer from "../components/map/MapPointer"; import { isEmpty } from "../helpers/shared"; import { lerp, compare } from "../helpers/vector2"; -// Send pointer updates every 33ms -const sendTickRate = 100; +// Send pointer updates every 50ms (20fps) +const sendTickRate = 50; -let t = 0; - -function NetworkedMapPointer({ active, gridSize }) { +function NetworkedMapPointer({ session, active, gridSize }) { const { userId } = useContext(AuthContext); - const setPlayerState = useContext(PlayerUpdaterContext); - const partyState = useContext(PartyContext); const [localPointerState, setLocalPointerState] = useState({}); + const sessionRef = useRef(session); + useEffect(() => { + sessionRef.current = session; + }, [session]); + useEffect(() => { if (userId && !(userId in localPointerState)) { setLocalPointerState({ @@ -44,14 +43,15 @@ function NetworkedMapPointer({ active, gridSize }) { if (counter > sendTickRate) { counter -= sendTickRate; - if (ownPointerUpdateRef.current) { - const { position, visible } = ownPointerUpdateRef.current; - console.log("send time", performance.now() - t); - t = performance.now(); - setPlayerState((prev) => ({ - ...prev, - pointer: { position, visible }, - })); + if ( + ownPointerUpdateRef.current && + sessionRef.current && + sessionRef.current.socket + ) { + sessionRef.current.socket.emit( + "player_pointer", + ownPointerUpdateRef.current + ); ownPointerUpdateRef.current = null; } } @@ -86,13 +86,9 @@ function NetworkedMapPointer({ active, gridSize }) { const interpolationsRef = useRef({}); useEffect(() => { // TODO: Handle player disconnect while pointer visible - const interpolations = interpolationsRef.current; - for (let player of Object.values(partyState)) { - const id = player.userId; - const pointer = player.pointer; - if (!id) { - continue; - } + function handleSocketPlayerPointer(pointer) { + const interpolations = interpolationsRef.current; + const id = pointer.id; if (!(id in interpolations)) { interpolations[id] = { id, @@ -103,8 +99,6 @@ function NetworkedMapPointer({ active, gridSize }) { !compare(interpolations[id].to.position, pointer.position, 0.0001) || interpolations[id].to.visible !== pointer.visible ) { - console.log("receive time", performance.now() - t, pointer.position); - t = performance.now(); const from = interpolations[id].to; interpolations[id] = { id, @@ -119,14 +113,23 @@ function NetworkedMapPointer({ active, gridSize }) { }; } } - }, [partyState]); + + if (session.socket) { + session.socket.on("player_pointer", handleSocketPlayerPointer); + } + + return () => { + session.socket.off("player_pointer", handleSocketPlayerPointer); + }; + }, [session]); // Animate to the peer pointer positions useEffect(() => { let request = requestAnimationFrame(animate); - function animate(time) { + function animate() { request = requestAnimationFrame(animate); + const time = performance.now(); let interpolatedPointerState = {}; for (let interp of Object.values(interpolationsRef.current)) { if (!interp.from || !interp.to) {