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";
|
2020-12-10 21:24:39 -05:00
|
|
|
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 }) {
|
2020-12-10 21:24:39 -05:00
|
|
|
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 },
|
2020-12-10 21:24:39 -05:00
|
|
|
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(() => {
|
2020-12-10 21:24:39 -05:00
|
|
|
setPlayerState((prevState) => ({
|
|
|
|
...prevState,
|
|
|
|
userId,
|
|
|
|
}));
|
2020-12-31 01:56:51 -05:00
|
|
|
}, [userId, setPlayerState]);
|
2020-12-10 21:24:39 -05:00
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
function handleSocketConnect() {
|
2020-12-07 23:58:01 -05:00
|
|
|
// Set the player state to trigger a sync
|
2020-12-10 21:24:39 -05:00
|
|
|
setPlayerState({ ...playerState, sessionId: session.id });
|
2020-12-07 23:58:01 -05:00
|
|
|
}
|
|
|
|
|
2020-12-10 21:24:39 -05:00
|
|
|
session.on("connected", handleSocketConnect);
|
|
|
|
|
2020-12-07 23:58:01 -05:00
|
|
|
if (session.socket) {
|
2020-12-10 21:24:39 -05:00
|
|
|
session.socket.on("connect", handleSocketConnect);
|
|
|
|
session.socket.on("reconnect", handleSocketConnect);
|
2020-12-07 23:58:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return () => {
|
2020-12-10 21:24:39 -05:00
|
|
|
session.off("connected", handleSocketConnect);
|
|
|
|
|
2020-12-07 23:58:01 -05:00
|
|
|
if (session.socket) {
|
2020-12-10 21:24:39 -05:00
|
|
|
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
|
|
|
);
|
|
|
|
}
|