2021-01-01 17:13:26 -05:00
|
|
|
import React, { useEffect, useContext } from "react";
|
2020-12-07 23:58:01 -05:00
|
|
|
|
2021-02-05 21:32:38 -05:00
|
|
|
import { useDatabase } from "./DatabaseContext";
|
2021-06-24 02:14:20 -04:00
|
|
|
import { useUserId } from "./UserIdContext";
|
2020-12-07 23:58:01 -05:00
|
|
|
|
|
|
|
import { getRandomMonster } from "../helpers/monsters";
|
|
|
|
|
2021-07-16 00:55:33 -04:00
|
|
|
import useNetworkedState, {
|
|
|
|
SetNetworkedState,
|
|
|
|
} from "../hooks/useNetworkedState";
|
2021-06-03 01:31:18 -04:00
|
|
|
import Session from "../network/Session";
|
2021-07-16 00:55:33 -04:00
|
|
|
import { PlayerState } from "../types/PlayerState";
|
2021-02-03 23:06:34 -05:00
|
|
|
|
2021-07-16 00:55:33 -04:00
|
|
|
export const PlayerStateContext =
|
|
|
|
React.createContext<PlayerState | undefined>(undefined);
|
|
|
|
export const PlayerUpdaterContext =
|
|
|
|
React.createContext<SetNetworkedState<PlayerState> | undefined>(undefined);
|
2020-12-07 23:58:01 -05:00
|
|
|
|
2021-07-16 00:55:33 -04:00
|
|
|
type PlayerProviderProps = {
|
2021-07-02 01:54:54 -04:00
|
|
|
session: Session;
|
|
|
|
children: React.ReactNode;
|
2021-07-16 00:55:33 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
export function PlayerProvider({ session, children }: PlayerProviderProps) {
|
2021-06-24 02:14:20 -04:00
|
|
|
const userId = useUserId();
|
2021-02-05 21:32:38 -05:00
|
|
|
const { database, databaseStatus } = useDatabase();
|
2020-12-07 23:58:01 -05:00
|
|
|
|
2021-07-16 00:55:33 -04:00
|
|
|
const [playerState, setPlayerState] = useNetworkedState<PlayerState>(
|
2020-12-07 23:58:01 -05:00
|
|
|
{
|
|
|
|
nickname: "",
|
2021-07-16 00:55:33 -04:00
|
|
|
timer: undefined,
|
2020-12-07 23:58:01 -05:00
|
|
|
dice: { share: false, rolls: [] },
|
2021-07-16 00:55:33 -04:00
|
|
|
sessionId: undefined,
|
2020-12-10 21:24:39 -05:00
|
|
|
userId,
|
2020-12-07 23:58:01 -05:00
|
|
|
},
|
|
|
|
session,
|
2021-01-02 18:45:24 -05:00
|
|
|
"player_state",
|
2021-01-21 14:59:49 -05:00
|
|
|
500,
|
2021-01-02 18:45:24 -05:00
|
|
|
false
|
2020-12-07 23:58:01 -05:00
|
|
|
);
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
if (!database || databaseStatus === "loading") {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
async function loadNickname() {
|
2021-06-03 01:31:18 -04:00
|
|
|
const storedNickname = await database?.table("user").get("nickname");
|
2020-12-07 23:58:01 -05:00
|
|
|
if (storedNickname !== undefined) {
|
2021-07-16 00:55:33 -04:00
|
|
|
setPlayerState((prevState) => ({
|
2020-12-07 23:58:01 -05:00
|
|
|
...prevState,
|
|
|
|
nickname: storedNickname.value,
|
|
|
|
}));
|
|
|
|
} else {
|
|
|
|
const name = getRandomMonster();
|
2021-07-16 00:55:33 -04:00
|
|
|
setPlayerState((prevState) => ({ ...prevState, nickname: name }));
|
2021-06-03 01:31:18 -04:00
|
|
|
database?.table("user").add({ key: "nickname", value: name });
|
2020-12-07 23:58:01 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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 &&
|
2021-06-24 02:14:20 -04:00
|
|
|
(databaseStatus === "loaded" || databaseStatus === "disabled")
|
2020-12-07 23:58:01 -05:00
|
|
|
) {
|
|
|
|
database
|
|
|
|
.table("user")
|
|
|
|
.update("nickname", { value: playerState.nickname });
|
|
|
|
}
|
|
|
|
}, [playerState, database, databaseStatus]);
|
|
|
|
|
|
|
|
useEffect(() => {
|
2021-04-09 01:13:06 -04:00
|
|
|
if (userId) {
|
2021-07-16 00:55:33 -04:00
|
|
|
setPlayerState((prevState) => {
|
2021-04-09 01:13:06 -04:00
|
|
|
if (prevState) {
|
|
|
|
return {
|
|
|
|
...prevState,
|
|
|
|
userId,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
return prevState;
|
|
|
|
});
|
|
|
|
}
|
2020-12-31 01:56:51 -05:00
|
|
|
}, [userId, setPlayerState]);
|
2020-12-10 21:24:39 -05:00
|
|
|
|
|
|
|
useEffect(() => {
|
2021-04-09 01:13:06 -04:00
|
|
|
function updateSessionId() {
|
2021-07-16 00:55:33 -04:00
|
|
|
setPlayerState((prevState) => {
|
2021-04-09 01:13:06 -04:00
|
|
|
if (prevState) {
|
|
|
|
return {
|
|
|
|
...prevState,
|
|
|
|
sessionId: session.id,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
return prevState;
|
|
|
|
});
|
|
|
|
}
|
2020-12-10 21:24:39 -05:00
|
|
|
function handleSocketConnect() {
|
2020-12-07 23:58:01 -05:00
|
|
|
// Set the player state to trigger a sync
|
2021-04-09 01:13:06 -04:00
|
|
|
updateSessionId();
|
2020-12-07 23:58:01 -05:00
|
|
|
}
|
|
|
|
|
2021-06-03 01:31:18 -04:00
|
|
|
function handleSocketStatus(status: string) {
|
2021-02-20 02:10:00 -05:00
|
|
|
if (status === "joined") {
|
2021-04-09 01:13:06 -04:00
|
|
|
updateSessionId();
|
2021-02-20 02:10:00 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
session.on("status", handleSocketStatus);
|
2020-12-31 20:44:56 -05:00
|
|
|
session.socket?.on("connect", handleSocketConnect);
|
2021-04-09 01:13:06 -04:00
|
|
|
session.socket?.io.on("reconnect", handleSocketConnect);
|
2020-12-07 23:58:01 -05:00
|
|
|
|
|
|
|
return () => {
|
2021-02-20 02:10:00 -05:00
|
|
|
session.off("status", handleSocketStatus);
|
2020-12-31 20:44:56 -05:00
|
|
|
session.socket?.off("connect", handleSocketConnect);
|
2021-04-09 01:13:06 -04:00
|
|
|
session.socket?.io.off("reconnect", handleSocketConnect);
|
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}>
|
2020-12-31 20:37:54 -05:00
|
|
|
{children}
|
2020-12-31 01:56:51 -05:00
|
|
|
</PlayerUpdaterContext.Provider>
|
|
|
|
</PlayerStateContext.Provider>
|
2020-12-07 23:58:01 -05:00
|
|
|
);
|
|
|
|
}
|
2021-02-05 21:32:38 -05:00
|
|
|
|
|
|
|
export function usePlayerState() {
|
|
|
|
const context = useContext(PlayerStateContext);
|
|
|
|
if (context === undefined) {
|
|
|
|
throw new Error("usePlayerState must be used within a PlayerProvider");
|
|
|
|
}
|
|
|
|
return context;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function usePlayerUpdater() {
|
|
|
|
const context = useContext(PlayerUpdaterContext);
|
|
|
|
if (context === undefined) {
|
|
|
|
throw new Error("usePlayerUpdater must be used within a PlayerProvider");
|
|
|
|
}
|
|
|
|
return context;
|
|
|
|
}
|