Added all files successfully converted

This commit is contained in:
Nicola Thouliss
2021-06-05 13:35:31 +10:00
parent c590adf836
commit bfd0529207
58 changed files with 622 additions and 445 deletions
@@ -1,4 +1,4 @@
import React, { useState, useEffect, useRef } from "react";
import { useState, useEffect, useRef } from "react";
import { useToasts } from "react-toast-notifications";
import { useTokenData } from "../contexts/TokenDataContext";
@@ -14,11 +14,13 @@ import useDebounce from "../hooks/useDebounce";
import useNetworkedState from "../hooks/useNetworkedState";
// Load session for auto complete
// eslint-disable-next-line no-unused-vars
import Session from "./Session";
import Map from "../components/map/Map";
import Map, { MapState, Resolutions, TokenState } from "../components/map/Map";
import Tokens from "../components/token/Tokens";
import { PartyState } from "../components/party/PartyState";
import Action from "../actions/Action";
import { Token } from "../tokens";
const defaultMapActions = {
mapDrawActions: [],
@@ -35,10 +37,10 @@ const defaultMapActions = {
/**
* @param {NetworkedMapProps} props
*/
function NetworkedMapAndTokens({ session }) {
function NetworkedMapAndTokens({ session }: { session: Session }) {
const { addToast } = useToasts();
const { userId } = useAuth();
const partyState = useParty();
const partyState: PartyState = useParty();
const {
assetLoadStart,
assetLoadFinish,
@@ -49,8 +51,8 @@ function NetworkedMapAndTokens({ session }) {
const { putToken, getTokenFromDB } = useTokenData();
const { putMap, updateMap, getMapFromDB, updateMapState } = useMapData();
const [currentMap, setCurrentMap] = useState(null);
const [currentMapState, setCurrentMapState] = useNetworkedState(
const [currentMap, setCurrentMap] = useState<any>(null);
const [currentMapState, setCurrentMapState]: [ currentMapState: MapState, setCurrentMapState: any] = useNetworkedState(
null,
session,
"map_state",
@@ -67,8 +69,8 @@ function NetworkedMapAndTokens({ session }) {
"mapId"
);
async function loadAssetManifestFromMap(map, mapState) {
const assets = {};
async function loadAssetManifestFromMap(map: any, mapState: MapState) {
const assets: any = {};
if (map.type === "file") {
const { id, lastModified, owner } = map;
assets[`map-${id}`] = { type: "map", id, lastModified, owner };
@@ -90,20 +92,20 @@ function NetworkedMapAndTokens({ session }) {
setAssetManifest({ mapId: map.id, assets }, true, true);
}
function compareAssets(a, b) {
function compareAssets(a: any, b: any) {
return a.type === b.type && a.id === b.id;
}
// Return true if an asset is out of date
function assetNeedsUpdate(oldAsset, newAsset) {
function assetNeedsUpdate(oldAsset: any, newAsset: any) {
return (
compareAssets(oldAsset, newAsset) &&
oldAsset.lastModified < newAsset.lastModified
);
}
function addAssetIfNeeded(asset) {
setAssetManifest((prevManifest) => {
function addAssetIfNeeded(asset: any) {
setAssetManifest((prevManifest: any) => {
if (prevManifest?.assets) {
const id =
asset.type === "map" ? `map-${asset.id}` : `token-${asset.id}`;
@@ -133,7 +135,7 @@ function NetworkedMapAndTokens({ session }) {
}
async function requestAssetsIfNeeded() {
for (let asset of Object.values(assetManifest.assets)) {
for (let asset of Object.values(assetManifest.assets) as any) {
if (
asset.owner === userId ||
requestingAssetsRef.current.has(asset.id)
@@ -200,14 +202,14 @@ function NetworkedMapAndTokens({ session }) {
debouncedMapState &&
debouncedMapState.mapId &&
currentMap &&
currentMap.owner === userId &&
currentMap?.owner === userId &&
database
) {
updateMapState(debouncedMapState.mapId, debouncedMapState);
}
}, [currentMap, debouncedMapState, userId, database, updateMapState]);
async function handleMapChange(newMap, newMapState) {
async function handleMapChange(newMap: any, newMapState: any) {
// Clear map before sending new one
setCurrentMap(null);
session.socket?.emit("map", null);
@@ -229,15 +231,15 @@ function NetworkedMapAndTokens({ session }) {
await loadAssetManifestFromMap(newMap, newMapState);
}
function handleMapReset(newMapState) {
function handleMapReset(newMapState: any) {
setCurrentMapState(newMapState, true, true);
setMapActions(defaultMapActions);
}
const [mapActions, setMapActions] = useState(defaultMapActions);
const [mapActions, setMapActions] = useState<any>(defaultMapActions);
function addMapActions(actions, indexKey, actionsKey, shapesKey) {
setMapActions((prevMapActions) => {
function addMapActions(actions: Action[], indexKey: string, actionsKey: any, shapesKey: any) {
setMapActions((prevMapActions: any) => {
const newActions = [
...prevMapActions[actionsKey].slice(0, prevMapActions[indexKey] + 1),
...actions,
@@ -250,7 +252,7 @@ function NetworkedMapAndTokens({ session }) {
};
});
// Update map state by performing the actions on it
setCurrentMapState((prevMapState) => {
setCurrentMapState((prevMapState: any) => {
if (prevMapState) {
let shapes = prevMapState[shapesKey];
for (let action of actions) {
@@ -264,20 +266,20 @@ function NetworkedMapAndTokens({ session }) {
});
}
function updateActionIndex(change, indexKey, actionsKey, shapesKey) {
const prevIndex = mapActions[indexKey];
function updateActionIndex(change: any, indexKey: any, actionsKey: any, shapesKey: any) {
const prevIndex: any = mapActions[indexKey];
const newIndex = Math.min(
Math.max(mapActions[indexKey] + change, -1),
mapActions[actionsKey].length - 1
);
setMapActions((prevMapActions) => ({
setMapActions((prevMapActions: Action[]) => ({
...prevMapActions,
[indexKey]: newIndex,
}));
// Update map state by either performing the actions or undoing them
setCurrentMapState((prevMapState) => {
setCurrentMapState((prevMapState: any) => {
if (prevMapState) {
let shapes = prevMapState[shapesKey];
if (prevIndex < newIndex) {
@@ -303,7 +305,7 @@ function NetworkedMapAndTokens({ session }) {
return newIndex;
}
function handleMapDraw(action) {
function handleMapDraw(action: Action) {
addMapActions(
[action],
"mapDrawActionIndex",
@@ -320,7 +322,7 @@ function NetworkedMapAndTokens({ session }) {
updateActionIndex(1, "mapDrawActionIndex", "mapDrawActions", "drawShapes");
}
function handleFogDraw(action) {
function handleFogDraw(action: Action) {
addMapActions(
[action],
"fogDrawActionIndex",
@@ -338,16 +340,16 @@ function NetworkedMapAndTokens({ session }) {
}
// If map changes clear map actions
const previousMapIdRef = useRef();
const previousMapIdRef = useRef<any>();
useEffect(() => {
if (currentMap && currentMap.id !== previousMapIdRef.current) {
if (currentMap && currentMap?.id !== previousMapIdRef.current) {
setMapActions(defaultMapActions);
previousMapIdRef.current = currentMap.id;
previousMapIdRef.current = currentMap?.id;
}
}, [currentMap]);
function handleNoteChange(note) {
setCurrentMapState((prevMapState) => ({
function handleNoteChange(note: any) {
setCurrentMapState((prevMapState: any) => ({
...prevMapState,
notes: {
...prevMapState.notes,
@@ -356,8 +358,8 @@ function NetworkedMapAndTokens({ session }) {
}));
}
function handleNoteRemove(noteId) {
setCurrentMapState((prevMapState) => ({
function handleNoteRemove(noteId: string) {
setCurrentMapState((prevMapState: any) => ({
...prevMapState,
notes: omit(prevMapState.notes, [noteId]),
}));
@@ -367,17 +369,17 @@ function NetworkedMapAndTokens({ session }) {
* Token state
*/
async function handleMapTokenStateCreate(tokenState) {
async function handleMapTokenStateCreate(tokenState: TokenState) {
if (!currentMap || !currentMapState) {
return;
}
// If file type token send the token to the other peers
const token = await getTokenFromDB(tokenState.tokenId);
const token: Token = await getTokenFromDB(tokenState.tokenId);
if (token && token.type === "file") {
const { id, lastModified, owner } = token;
addAssetIfNeeded({ type: "token", id, lastModified, owner });
}
setCurrentMapState((prevMapState) => ({
setCurrentMapState((prevMapState: any) => ({
...prevMapState,
tokens: {
...prevMapState.tokens,
@@ -386,11 +388,11 @@ function NetworkedMapAndTokens({ session }) {
}));
}
function handleMapTokenStateChange(change) {
function handleMapTokenStateChange(change: any) {
if (!currentMapState) {
return;
}
setCurrentMapState((prevMapState) => {
setCurrentMapState((prevMapState: any) => {
let tokens = { ...prevMapState.tokens };
for (let id in change) {
if (id in tokens) {
@@ -405,22 +407,21 @@ function NetworkedMapAndTokens({ session }) {
});
}
function handleMapTokenStateRemove(tokenState) {
setCurrentMapState((prevMapState) => {
function handleMapTokenStateRemove(tokenState: any) {
setCurrentMapState((prevMapState: any) => {
const { [tokenState.id]: old, ...rest } = prevMapState.tokens;
return { ...prevMapState, tokens: rest };
});
}
useEffect(() => {
async function handlePeerData({ id, data, reply }) {
// TODO: edit Map type with appropriate resolutions
async function handlePeerData({ id, data, reply }: { id: string, data: any, reply: any}) {
if (id === "mapRequest") {
const map = await getMapFromDB(data);
function replyWithMap(preview, resolution) {
function replyWithMap(preview?: string | undefined, resolution?: any) {
let response = {
...map,
resolutions: undefined,
file: undefined,
thumbnail: undefined,
// Remove last modified so if there is an error
// during the map request the cache is invalid
@@ -429,13 +430,13 @@ function NetworkedMapAndTokens({ session }) {
lastUsed: Date.now(),
};
// Send preview if available
if (map.resolutions[preview]) {
response.resolutions = { [preview]: map.resolutions[preview] };
if (preview !== undefined && map.resolutions && map.resolutions[preview]) {
response.resolutions = { [preview]: map.resolutions[preview] } as Resolutions;
reply("mapResponse", response, "map");
}
// Send full map at the desired resolution if available
if (map.resolutions[resolution]) {
response.file = map.resolutions[resolution].file;
if (map.resolutions && map.resolutions[resolution]) {
response.file = map.resolutions[resolution].file as Uint8Array;
} else if (map.file) {
// The resolution might not exist for other users so send the file instead
response.file = map.file;
@@ -506,7 +507,7 @@ function NetworkedMapAndTokens({ session }) {
}
}
function handlePeerDataProgress({ id, total, count }) {
function handlePeerDataProgress({ id, total, count }: { id: string, total: number, count: number}) {
if (count === 1) {
// Corresponding asset load finished called in token and map response
assetLoadStart();
@@ -514,7 +515,7 @@ function NetworkedMapAndTokens({ session }) {
assetProgressUpdate({ id, total, count });
}
async function handleSocketMap(map) {
async function handleSocketMap(map: any) {
if (map) {
if (map.type === "file") {
const fullMap = await getMapFromDB(map.id);
@@ -540,31 +541,31 @@ function NetworkedMapAndTokens({ session }) {
const canChangeMap = !isLoading;
const canEditMapDrawing =
const canEditMapDrawing: any =
currentMap &&
currentMapState &&
(currentMapState.editFlags.includes("drawing") ||
currentMap.owner === userId);
currentMap?.owner === userId);
const canEditFogDrawing =
currentMap &&
currentMapState &&
(currentMapState.editFlags.includes("fog") || currentMap.owner === userId);
(currentMapState.editFlags.includes("fog") || currentMap?.owner === userId);
const canEditNotes =
currentMap &&
currentMapState &&
(currentMapState.editFlags.includes("notes") ||
currentMap.owner === userId);
currentMap?.owner === userId);
const disabledMapTokens = {};
const disabledMapTokens: { [key: string]: any } = {};
// If we have a map and state and have the token permission disabled
// and are not the map owner
if (
currentMapState &&
currentMap &&
!currentMapState.editFlags.includes("tokens") &&
currentMap.owner !== userId
currentMap?.owner !== userId
) {
for (let token of Object.values(currentMapState.tokens)) {
if (token.owner !== userId) {
@@ -8,11 +8,12 @@ import { isEmpty } from "../helpers/shared";
import Vector2 from "../helpers/Vector2";
import useSetting from "../hooks/useSetting";
import Session from "./Session";
// Send pointer updates every 50ms (20fps)
const sendTickRate = 50;
function NetworkedMapPointer({ session, active }) {
function NetworkedMapPointer({ session, active }: { session: Session, active: boolean }) {
const { userId } = useAuth();
const [localPointerState, setLocalPointerState] = useState({});
const [pointerColor] = useSetting("pointer.color");
@@ -38,12 +39,12 @@ function NetworkedMapPointer({ session, active }) {
// Send pointer updates every sendTickRate to peers to save on bandwidth
// We use requestAnimationFrame as setInterval was being blocked during
// re-renders on Chrome with Windows
const ownPointerUpdateRef = useRef();
const ownPointerUpdateRef: React.MutableRefObject<{ position: any; visible: boolean; id: any; color: any; } | undefined | null > = useRef();
useEffect(() => {
let prevTime = performance.now();
let request = requestAnimationFrame(update);
let counter = 0;
function update(time) {
function update(time: any) {
request = requestAnimationFrame(update);
const deltaTime = time - prevTime;
counter += deltaTime;
@@ -70,7 +71,7 @@ function NetworkedMapPointer({ session, active }) {
};
}, []);
function updateOwnPointerState(position, visible) {
function updateOwnPointerState(position: any, visible: boolean) {
setLocalPointerState((prev) => ({
...prev,
[userId]: { position, visible, id: userId, color: pointerColor },
@@ -83,24 +84,24 @@ function NetworkedMapPointer({ session, active }) {
};
}
function handleOwnPointerDown(position) {
function handleOwnPointerDown(position: any) {
updateOwnPointerState(position, true);
}
function handleOwnPointerMove(position) {
function handleOwnPointerMove(position: any) {
updateOwnPointerState(position, true);
}
function handleOwnPointerUp(position) {
function handleOwnPointerUp(position: any) {
updateOwnPointerState(position, false);
}
// Handle pointer data receive
const interpolationsRef = useRef({});
const interpolationsRef: React.MutableRefObject<any> = useRef({});
useEffect(() => {
// TODO: Handle player disconnect while pointer visible
function handleSocketPlayerPointer(pointer) {
const interpolations = interpolationsRef.current;
function handleSocketPlayerPointer(pointer: any) {
const interpolations: any = interpolationsRef.current;
const id = pointer.id;
if (!(id in interpolations)) {
interpolations[id] = {
@@ -145,8 +146,8 @@ function NetworkedMapPointer({ session, active }) {
function animate() {
request = requestAnimationFrame(animate);
const time = performance.now();
let interpolatedPointerState = {};
for (let interp of Object.values(interpolationsRef.current)) {
let interpolatedPointerState: any = {};
for (let interp of Object.values(interpolationsRef.current) as any) {
if (!interp.from || !interp.to) {
continue;
}
@@ -191,7 +192,7 @@ function NetworkedMapPointer({ session, active }) {
return (
<Group>
{Object.values(localPointerState).map((pointer) => (
{Object.values(localPointerState).map((pointer: any) => (
<MapPointer
key={pointer.id}
active={pointer.id === userId ? active : false}
@@ -1,14 +1,14 @@
import React, { useState, useEffect, useCallback, useRef } from "react";
import { useState, useEffect, useCallback, useRef } from "react";
import { useToasts } from "react-toast-notifications";
// Load session for auto complete
// eslint-disable-next-line no-unused-vars
import Session from "./Session";
import Session, { SessionPeer } from "./Session";
import { isStreamStopped, omit } from "../helpers/shared";
import { useParty } from "../contexts/PartyContext";
import Party from "../components/party/Party";
import { PartyState } from "../components/party/PartyState";
/**
* @typedef {object} NetworkedPartyProps
@@ -16,24 +16,26 @@ import Party from "../components/party/Party";
* @property {Session} session
*/
type NetworkedPartyProps = { gameId: string, session: Session }
/**
* @param {NetworkedPartyProps} props
*/
function NetworkedParty({ gameId, session }) {
const partyState = useParty();
const [stream, setStream] = useState(null);
function NetworkedParty(props: NetworkedPartyProps) {
const partyState: PartyState = useParty();
const [stream, setStream] = useState<MediaStream | null>(null);
const [partyStreams, setPartyStreams] = useState({});
const { addToast } = useToasts();
function handleStreamStart(localStream) {
function handleStreamStart(localStream: MediaStream) {
setStream(localStream);
const tracks = localStream.getTracks();
for (let track of tracks) {
// Only add the audio track of the stream to the remote peer
if (track.kind === "audio") {
for (let player of Object.values(partyState)) {
session.startStreamTo(player.sessionId, track, localStream);
props.session.startStreamTo(player.sessionId, track, localStream);
}
}
}
@@ -48,16 +50,16 @@ function NetworkedParty({ gameId, session }) {
// Only sending audio so only remove the audio track
if (track.kind === "audio") {
for (let player of Object.values(partyState)) {
session.endStreamTo(player.sessionId, track, localStream);
props.session.endStreamTo(player.sessionId, track, localStream);
}
}
}
},
[session, partyState]
[props.session, partyState]
);
// Keep a reference to players who have just joined to show the joined notification
const joinedPlayersRef = useRef([]);
const joinedPlayersRef = useRef<string[]>([]);
useEffect(() => {
if (joinedPlayersRef.current.length > 0) {
for (let id of joinedPlayersRef.current) {
@@ -70,12 +72,12 @@ function NetworkedParty({ gameId, session }) {
}, [partyState, addToast]);
useEffect(() => {
function handlePlayerJoined(sessionId) {
function handlePlayerJoined(sessionId: string) {
if (stream) {
const tracks = stream.getTracks();
for (let track of tracks) {
if (track.kind === "audio") {
session.startStreamTo(sessionId, track, stream);
props.session.startStreamTo(sessionId, track, stream);
}
}
}
@@ -84,20 +86,20 @@ function NetworkedParty({ gameId, session }) {
joinedPlayersRef.current.push(sessionId);
}
function handlePlayerLeft(sessionId) {
function handlePlayerLeft(sessionId: string) {
if (partyState[sessionId]) {
addToast(`${partyState[sessionId].nickname} left the party`);
}
}
function handlePeerTrackAdded({ peer, stream: remoteStream }) {
function handlePeerTrackAdded({ peer, stream: remoteStream }: { peer: SessionPeer, stream: MediaStream}) {
setPartyStreams((prevStreams) => ({
...prevStreams,
[peer.id]: remoteStream,
}));
}
function handlePeerTrackRemoved({ peer, stream: remoteStream }) {
function handlePeerTrackRemoved({ peer, stream: remoteStream }: { peer: SessionPeer, stream: MediaStream }) {
if (isStreamStopped(remoteStream)) {
setPartyStreams((prevStreams) => omit(prevStreams, [peer.id]));
} else {
@@ -108,16 +110,16 @@ function NetworkedParty({ gameId, session }) {
}
}
session.on("playerJoined", handlePlayerJoined);
session.on("playerLeft", handlePlayerLeft);
session.on("peerTrackAdded", handlePeerTrackAdded);
session.on("peerTrackRemoved", handlePeerTrackRemoved);
props.session.on("playerJoined", handlePlayerJoined);
props.session.on("playerLeft", handlePlayerLeft);
props.session.on("peerTrackAdded", handlePeerTrackAdded);
props.session.on("peerTrackRemoved", handlePeerTrackRemoved);
return () => {
session.off("playerJoined", handlePlayerJoined);
session.off("playerLeft", handlePlayerLeft);
session.off("peerTrackAdded", handlePeerTrackAdded);
session.off("peerTrackRemoved", handlePeerTrackRemoved);
props.session.off("playerJoined", handlePlayerJoined);
props.session.off("playerLeft", handlePlayerLeft);
props.session.off("peerTrackAdded", handlePeerTrackAdded);
props.session.off("peerTrackRemoved", handlePeerTrackRemoved);
};
});
@@ -140,7 +142,7 @@ function NetworkedParty({ gameId, session }) {
return (
<>
<Party
gameId={gameId}
gameId={props.gameId}
onStreamStart={handleStreamStart}
onStreamEnd={handleStreamEnd}
stream={stream}
+2 -2
View File
@@ -15,7 +15,7 @@ import { SimplePeerData } from "simple-peer";
* @property {boolean} initiator - Is this peer the initiator of the connection
* @property {boolean} ready - Ready for data to be sent
*/
type SessionPeer = {
export type SessionPeer = {
id: string;
connection: Connection;
initiator: boolean;
@@ -137,7 +137,7 @@ class Session extends EventEmitter {
* @param {object} data
* @param {string} channel
*/
sendTo(sessionId: string, eventId: string, data: SimplePeerData, channel: string) {
sendTo(sessionId: string, eventId: string, data: SimplePeerData, channel?: string) {
if (!(sessionId in this.peers)) {
if (!this._addPeer(sessionId, true)) {
return;