Moved pointer out of player state and into separate socket event
This commit is contained in:
parent
501fc4377c
commit
b13b46b17d
@ -18,8 +18,6 @@ import MapStageContext, {
|
|||||||
import AuthContext from "../../contexts/AuthContext";
|
import AuthContext from "../../contexts/AuthContext";
|
||||||
import SettingsContext from "../../contexts/SettingsContext";
|
import SettingsContext from "../../contexts/SettingsContext";
|
||||||
import KeyboardContext from "../../contexts/KeyboardContext";
|
import KeyboardContext from "../../contexts/KeyboardContext";
|
||||||
import { PlayerUpdaterContext } from "../../contexts/PlayerContext";
|
|
||||||
import PartyContext from "../../contexts/PartyContext";
|
|
||||||
|
|
||||||
function MapInteraction({
|
function MapInteraction({
|
||||||
map,
|
map,
|
||||||
@ -180,8 +178,6 @@ function MapInteraction({
|
|||||||
|
|
||||||
const auth = useContext(AuthContext);
|
const auth = useContext(AuthContext);
|
||||||
const settings = useContext(SettingsContext);
|
const settings = useContext(SettingsContext);
|
||||||
const player = useContext(PlayerUpdaterContext);
|
|
||||||
const party = useContext(PartyContext);
|
|
||||||
|
|
||||||
const mapInteraction = {
|
const mapInteraction = {
|
||||||
stageScale,
|
stageScale,
|
||||||
@ -223,19 +219,15 @@ function MapInteraction({
|
|||||||
/>
|
/>
|
||||||
{/* Forward auth context to konva elements */}
|
{/* Forward auth context to konva elements */}
|
||||||
<AuthContext.Provider value={auth}>
|
<AuthContext.Provider value={auth}>
|
||||||
<PlayerUpdaterContext.Provider value={player}>
|
<SettingsContext.Provider value={settings}>
|
||||||
<PartyContext.Provider value={party}>
|
<KeyboardContext.Provider value={keyboardValue}>
|
||||||
<SettingsContext.Provider value={settings}>
|
<MapInteractionProvider value={mapInteraction}>
|
||||||
<KeyboardContext.Provider value={keyboardValue}>
|
<MapStageProvider value={mapStageRef}>
|
||||||
<MapInteractionProvider value={mapInteraction}>
|
{mapLoaded && children}
|
||||||
<MapStageProvider value={mapStageRef}>
|
</MapStageProvider>
|
||||||
{mapLoaded && children}
|
</MapInteractionProvider>
|
||||||
</MapStageProvider>
|
</KeyboardContext.Provider>
|
||||||
</MapInteractionProvider>
|
</SettingsContext.Provider>
|
||||||
</KeyboardContext.Provider>
|
|
||||||
</SettingsContext.Provider>
|
|
||||||
</PartyContext.Provider>
|
|
||||||
</PlayerUpdaterContext.Provider>
|
|
||||||
</AuthContext.Provider>
|
</AuthContext.Provider>
|
||||||
</Layer>
|
</Layer>
|
||||||
</Stage>
|
</Stage>
|
||||||
|
@ -17,12 +17,12 @@ import useSetting from "../../helpers/useSetting";
|
|||||||
import PartyContext from "../../contexts/PartyContext";
|
import PartyContext from "../../contexts/PartyContext";
|
||||||
import {
|
import {
|
||||||
PlayerUpdaterContext,
|
PlayerUpdaterContext,
|
||||||
PlayerStateWithoutPointerContext,
|
PlayerStateContext,
|
||||||
} from "../../contexts/PlayerContext";
|
} from "../../contexts/PlayerContext";
|
||||||
|
|
||||||
function Party({ gameId, stream, partyStreams, onStreamStart, onStreamEnd }) {
|
function Party({ gameId, stream, partyStreams, onStreamStart, onStreamEnd }) {
|
||||||
const setPlayerState = useContext(PlayerUpdaterContext);
|
const setPlayerState = useContext(PlayerUpdaterContext);
|
||||||
const playerState = useContext(PlayerStateWithoutPointerContext);
|
const playerState = useContext(PlayerStateContext);
|
||||||
const partyState = useContext(PartyContext);
|
const partyState = useContext(PartyContext);
|
||||||
|
|
||||||
const [fullScreen] = useSetting("map.fullScreen");
|
const [fullScreen] = useSetting("map.fullScreen");
|
||||||
|
@ -9,10 +9,6 @@ import { getRandomMonster } from "../helpers/monsters";
|
|||||||
|
|
||||||
export const PlayerStateContext = React.createContext();
|
export const PlayerStateContext = React.createContext();
|
||||||
export const PlayerUpdaterContext = 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 }) {
|
export function PlayerProvider({ session, children }) {
|
||||||
const { userId } = useContext(AuthContext);
|
const { userId } = useContext(AuthContext);
|
||||||
@ -23,7 +19,6 @@ export function PlayerProvider({ session, children }) {
|
|||||||
nickname: "",
|
nickname: "",
|
||||||
timer: null,
|
timer: null,
|
||||||
dice: { share: false, rolls: [] },
|
dice: { share: false, rolls: [] },
|
||||||
pointer: { position: { x: 0, y: 0 }, visible: false },
|
|
||||||
sessionId: null,
|
sessionId: null,
|
||||||
userId,
|
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 (
|
return (
|
||||||
<PlayerStateContext.Provider value={playerState}>
|
<PlayerStateContext.Provider value={playerState}>
|
||||||
<PlayerUpdaterContext.Provider value={setPlayerState}>
|
<PlayerUpdaterContext.Provider value={setPlayerState}>
|
||||||
<PlayerStateWithoutPointerContext.Provider
|
{children}
|
||||||
value={playerStateWithoutPointer}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</PlayerStateWithoutPointerContext.Provider>
|
|
||||||
</PlayerUpdaterContext.Provider>
|
</PlayerUpdaterContext.Provider>
|
||||||
</PlayerStateContext.Provider>
|
</PlayerStateContext.Provider>
|
||||||
);
|
);
|
||||||
|
@ -2,24 +2,23 @@ import React, { useState, useContext, useEffect, useRef } from "react";
|
|||||||
import { Group } from "react-konva";
|
import { Group } from "react-konva";
|
||||||
|
|
||||||
import AuthContext from "../contexts/AuthContext";
|
import AuthContext from "../contexts/AuthContext";
|
||||||
import PartyContext from "../contexts/PartyContext";
|
|
||||||
import { PlayerUpdaterContext } from "../contexts/PlayerContext";
|
|
||||||
|
|
||||||
import MapPointer from "../components/map/MapPointer";
|
import MapPointer from "../components/map/MapPointer";
|
||||||
import { isEmpty } from "../helpers/shared";
|
import { isEmpty } from "../helpers/shared";
|
||||||
import { lerp, compare } from "../helpers/vector2";
|
import { lerp, compare } from "../helpers/vector2";
|
||||||
|
|
||||||
// Send pointer updates every 33ms
|
// Send pointer updates every 50ms (20fps)
|
||||||
const sendTickRate = 100;
|
const sendTickRate = 50;
|
||||||
|
|
||||||
let t = 0;
|
function NetworkedMapPointer({ session, active, gridSize }) {
|
||||||
|
|
||||||
function NetworkedMapPointer({ active, gridSize }) {
|
|
||||||
const { userId } = useContext(AuthContext);
|
const { userId } = useContext(AuthContext);
|
||||||
const setPlayerState = useContext(PlayerUpdaterContext);
|
|
||||||
const partyState = useContext(PartyContext);
|
|
||||||
const [localPointerState, setLocalPointerState] = useState({});
|
const [localPointerState, setLocalPointerState] = useState({});
|
||||||
|
|
||||||
|
const sessionRef = useRef(session);
|
||||||
|
useEffect(() => {
|
||||||
|
sessionRef.current = session;
|
||||||
|
}, [session]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (userId && !(userId in localPointerState)) {
|
if (userId && !(userId in localPointerState)) {
|
||||||
setLocalPointerState({
|
setLocalPointerState({
|
||||||
@ -44,14 +43,15 @@ function NetworkedMapPointer({ active, gridSize }) {
|
|||||||
|
|
||||||
if (counter > sendTickRate) {
|
if (counter > sendTickRate) {
|
||||||
counter -= sendTickRate;
|
counter -= sendTickRate;
|
||||||
if (ownPointerUpdateRef.current) {
|
if (
|
||||||
const { position, visible } = ownPointerUpdateRef.current;
|
ownPointerUpdateRef.current &&
|
||||||
console.log("send time", performance.now() - t);
|
sessionRef.current &&
|
||||||
t = performance.now();
|
sessionRef.current.socket
|
||||||
setPlayerState((prev) => ({
|
) {
|
||||||
...prev,
|
sessionRef.current.socket.emit(
|
||||||
pointer: { position, visible },
|
"player_pointer",
|
||||||
}));
|
ownPointerUpdateRef.current
|
||||||
|
);
|
||||||
ownPointerUpdateRef.current = null;
|
ownPointerUpdateRef.current = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,13 +86,9 @@ function NetworkedMapPointer({ active, gridSize }) {
|
|||||||
const interpolationsRef = useRef({});
|
const interpolationsRef = useRef({});
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// TODO: Handle player disconnect while pointer visible
|
// TODO: Handle player disconnect while pointer visible
|
||||||
const interpolations = interpolationsRef.current;
|
function handleSocketPlayerPointer(pointer) {
|
||||||
for (let player of Object.values(partyState)) {
|
const interpolations = interpolationsRef.current;
|
||||||
const id = player.userId;
|
const id = pointer.id;
|
||||||
const pointer = player.pointer;
|
|
||||||
if (!id) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!(id in interpolations)) {
|
if (!(id in interpolations)) {
|
||||||
interpolations[id] = {
|
interpolations[id] = {
|
||||||
id,
|
id,
|
||||||
@ -103,8 +99,6 @@ function NetworkedMapPointer({ active, gridSize }) {
|
|||||||
!compare(interpolations[id].to.position, pointer.position, 0.0001) ||
|
!compare(interpolations[id].to.position, pointer.position, 0.0001) ||
|
||||||
interpolations[id].to.visible !== pointer.visible
|
interpolations[id].to.visible !== pointer.visible
|
||||||
) {
|
) {
|
||||||
console.log("receive time", performance.now() - t, pointer.position);
|
|
||||||
t = performance.now();
|
|
||||||
const from = interpolations[id].to;
|
const from = interpolations[id].to;
|
||||||
interpolations[id] = {
|
interpolations[id] = {
|
||||||
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
|
// Animate to the peer pointer positions
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let request = requestAnimationFrame(animate);
|
let request = requestAnimationFrame(animate);
|
||||||
|
|
||||||
function animate(time) {
|
function animate() {
|
||||||
request = requestAnimationFrame(animate);
|
request = requestAnimationFrame(animate);
|
||||||
|
const time = performance.now();
|
||||||
let interpolatedPointerState = {};
|
let interpolatedPointerState = {};
|
||||||
for (let interp of Object.values(interpolationsRef.current)) {
|
for (let interp of Object.values(interpolationsRef.current)) {
|
||||||
if (!interp.from || !interp.to) {
|
if (!interp.from || !interp.to) {
|
||||||
|
Loading…
Reference in New Issue
Block a user