grungnet/src/contexts/PlayerContext.js

122 lines
3.4 KiB
JavaScript
Raw Normal View History

2020-12-31 01:56:51 -05:00
import React, { useEffect, useContext, useState } from "react";
import compare from "fast-deep-equal";
2020-12-07 23:58:01 -05:00
import useNetworkedState from "../helpers/useNetworkedState";
import DatabaseContext from "./DatabaseContext";
import AuthContext from "./AuthContext";
2020-12-07 23:58:01 -05:00
import { getRandomMonster } from "../helpers/monsters";
2020-12-31 01:56:51 -05:00
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();
2020-12-07 23:58:01 -05:00
export function PlayerProvider({ session, children }) {
const { userId } = useContext(AuthContext);
2020-12-07 23:58:01 -05:00
const { database, databaseStatus } = useContext(DatabaseContext);
const [playerState, setPlayerState] = useNetworkedState(
{
nickname: "",
timer: null,
dice: { share: false, rolls: [] },
2020-12-31 01:56:51 -05:00
pointer: { position: { x: 0, y: 0 }, visible: false },
sessionId: null,
userId,
2020-12-07 23:58:01 -05:00
},
session,
"player_state"
);
useEffect(() => {
if (!database || databaseStatus === "loading") {
return;
}
async function loadNickname() {
const storedNickname = await database.table("user").get("nickname");
if (storedNickname !== undefined) {
setPlayerState((prevState) => ({
...prevState,
nickname: storedNickname.value,
}));
} else {
const name = getRandomMonster();
setPlayerState((prevState) => ({ ...prevState, nickname: name }));
database.table("user").add({ key: "nickname", value: name });
}
}
loadNickname();
2020-12-31 01:56:51 -05:00
}, [database, databaseStatus, setPlayerState]);
2020-12-07 23:58:01 -05:00
useEffect(() => {
if (
playerState.nickname &&
database !== undefined &&
databaseStatus !== "loading"
) {
database
.table("user")
.update("nickname", { value: playerState.nickname });
}
}, [playerState, database, databaseStatus]);
useEffect(() => {
setPlayerState((prevState) => ({
...prevState,
userId,
}));
2020-12-31 01:56:51 -05:00
}, [userId, setPlayerState]);
useEffect(() => {
function handleSocketConnect() {
2020-12-07 23:58:01 -05:00
// Set the player state to trigger a sync
setPlayerState({ ...playerState, sessionId: session.id });
2020-12-07 23:58:01 -05:00
}
session.on("connected", handleSocketConnect);
2020-12-07 23:58:01 -05:00
if (session.socket) {
session.socket.on("connect", handleSocketConnect);
session.socket.on("reconnect", handleSocketConnect);
2020-12-07 23:58:01 -05:00
}
return () => {
session.off("connected", handleSocketConnect);
2020-12-07 23:58:01 -05:00
if (session.socket) {
session.socket.off("connect", handleSocketConnect);
session.socket.off("reconnect", handleSocketConnect);
2020-12-07 23:58:01 -05:00
}
};
});
2020-12-31 01:56:51 -05:00
const [playerStateWithoutPointer, setPlayerStateWithoutPointer] = useState(
playerState
);
useEffect(() => {
const { pointer, ...state } = playerState;
if (
!playerStateWithoutPointer ||
!compare(playerStateWithoutPointer, state)
) {
setPlayerStateWithoutPointer(state);
}
}, [playerState, playerStateWithoutPointer]);
2020-12-07 23:58:01 -05:00
return (
2020-12-31 01:56:51 -05:00
<PlayerStateContext.Provider value={playerState}>
<PlayerUpdaterContext.Provider value={setPlayerState}>
<PlayerStateWithoutPointerContext.Provider
value={playerStateWithoutPointer}
>
{children}
</PlayerStateWithoutPointerContext.Provider>
</PlayerUpdaterContext.Provider>
</PlayerStateContext.Provider>
2020-12-07 23:58:01 -05:00
);
}