renamed tests dir, moved reusable types to a separate file

This commit is contained in:
ad044 2021-02-22 19:03:43 +04:00
parent c57659fe47
commit d92e259bcc
24 changed files with 310 additions and 229 deletions

50
package-lock.json generated
View file

@ -2766,6 +2766,14 @@
"@types/react": "*"
}
},
"@types/react-test-renderer": {
"version": "17.0.1",
"resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-17.0.1.tgz",
"integrity": "sha512-3Fi2O6Zzq/f3QR9dRnlnHso9bMl7weKCviFmfF6B4LS1Uat6Hkm15k0ZAQuDz+UBq6B3+g+NM6IT2nr5QgPzCw==",
"requires": {
"@types/react": "*"
}
},
"@types/resolve": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz",
@ -8177,9 +8185,9 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"ini": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
},
"inquirer": {
"version": "7.3.3",
@ -14275,6 +14283,42 @@
"workbox-webpack-plugin": "5.1.4"
}
},
"react-shallow-renderer": {
"version": "16.14.1",
"resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.14.1.tgz",
"integrity": "sha512-rkIMcQi01/+kxiTE9D3fdS959U1g7gs+/rborw++42m1O9FAQiNI/UNRZExVUoAOprn4umcXf+pFRou8i4zuBg==",
"requires": {
"object-assign": "^4.1.1",
"react-is": "^16.12.0 || ^17.0.0"
}
},
"react-test-renderer": {
"version": "17.0.1",
"resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-17.0.1.tgz",
"integrity": "sha512-/dRae3mj6aObwkjCcxZPlxDFh73XZLgvwhhyON2haZGUEhiaY5EjfAdw+d/rQmlcFwdTpMXCSGVk374QbCTlrA==",
"requires": {
"object-assign": "^4.1.1",
"react-is": "^17.0.1",
"react-shallow-renderer": "^16.13.1",
"scheduler": "^0.20.1"
},
"dependencies": {
"react-is": {
"version": "17.0.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.1.tgz",
"integrity": "sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA=="
},
"scheduler": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.1.tgz",
"integrity": "sha512-LKTe+2xNJBNxu/QhHvDR14wUXHRQbVY5ZOYpOGWRzhydZUqrLb2JBvLPY7cAqFmqrWuDED0Mjk7013SZiOz6Bw==",
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1"
}
}
}
},
"react-three-fiber": {
"version": "4.2.21",
"resolved": "https://registry.npmjs.org/react-three-fiber/-/react-three-fiber-4.2.21.tgz",

View file

@ -12,9 +12,11 @@
"@types/node": "^12.12.54",
"@types/react": "^16.9.47",
"@types/react-dom": "^16.9.8",
"@types/react-test-renderer": "^17.0.1",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-scripts": "^4.0.0",
"react-test-renderer": "^17.0.1",
"react-three-fiber": "^4.2.20",
"three": "^0.119.1",
"three-plain-animator": "^1.0.2",

View file

@ -17,7 +17,8 @@ import { useFrame } from "react-three-fiber";
import { getRandomIdleLainAnim } from "../helpers/idle-helpers";
import * as audio from "../static/audio/sfx";
import handleEndSceneKeyPress from "../core/scene-keypress-handlers/handleEndSceneKeyPress";
import handleEvent, { GameEvent } from "../core/handleEvent";
import handleEvent from "../core/handleEvent";
import {GameEvent} from "../types/types";
const KeyPressHandler = () => {
const scene = useStore((state) => state.currentScene);

View file

@ -1,35 +1,15 @@
import React, { memo, useEffect, useRef } from "react";
import { useFrame, useLoader } from "react-three-fiber";
import React, {memo, useEffect, useRef} from "react";
import {useFrame, useLoader} from "react-three-fiber";
import * as THREE from "three";
import bigHud from "../../static/sprite/big_hud.png";
import longHud from "../../static/sprite/long_hud.png";
import boringHud from "../../static/sprite/long_hud_boring.png";
import { useStore } from "../../store";
import {useStore} from "../../store";
import lerp from "../../utils/lerp";
import GreenTextRenderer from "../TextRenderer/GreenTextRenderer";
import usePrevious from "../../hooks/usePrevious";
import { getNodeHud } from "../../helpers/node-helpers";
export type HUDType = {
mirrored: number;
long: {
position: number[];
initial_position: number[];
};
boring: {
position: number[];
initial_position: number[];
};
big: {
position: number[];
initial_position: number[];
};
big_text: number[];
medium_text: {
position: number[];
initial_position: number[];
};
};
import {getNodeHud} from "../../helpers/node-helpers";
import {HUDData} from "../../types/types";
const HUD = memo(() => {
const activeRef = useRef(true);
@ -102,7 +82,7 @@ const HUD = memo(() => {
bigHudRef.current!.scale.x = Math.abs(bigHudRef.current!.scale.x);
};
const setPos = (hud: HUDType, pos: string) => {
const setPos = (hud: HUDData, pos: string) => {
longHudRef.current!.position.set(
...(hud.long[pos as keyof typeof hud.long] as [number, number, number])
);

View file

@ -2,8 +2,8 @@ import React, { memo, useEffect, useState } from "react";
import Node from "./Node";
import node_positions from "../../../resources/node_positions.json";
import { useStore } from "../../../store";
import { NodeData, SiteData } from "./Site";
import usePrevious from "../../../hooks/usePrevious";
import {NodeData, SiteData} from "../../../types/types";
type ActiveLevelNodesProps = {
visibleNodes: SiteData;

View file

@ -1,10 +1,10 @@
import React, { memo, useEffect, useState } from "react";
import node_positions from "../../../resources/node_positions.json";
import { useStore } from "../../../store";
import { SiteData } from "./Site";
import InactiveLevelNode from "./InactiveLevelNode";
import usePrevious from "../../../hooks/usePrevious";
import { generateInactiveNodes } from "../../../helpers/node-helpers";
import {SiteData} from "../../../types/types";
type ActiveLevelNodesProps = {
visibleNodes: SiteData;

View file

@ -1,6 +1,6 @@
import React, { Suspense, useEffect, useMemo } from "react";
import { a, useSpring } from "@react-spring/three";
import { useStore } from "../../../store";
import React, {Suspense, useEffect, useMemo} from "react";
import {a, useSpring} from "@react-spring/three";
import {useStore} from "../../../store";
import ActiveLevelNodes from "./ActiveLevelNodes";
import Rings from "./Rings";
import NodeAnimations from "./NodeAnimations";
@ -8,38 +8,9 @@ import InactiveLevelNodes from "./InactiveLevelNodes";
import site_a from "../../../resources/site_a.json";
import site_b from "../../../resources/site_b.json";
import level_y_values from "../../../resources/level_y_values.json";
import { filterInvisibleNodes } from "../../../helpers/node-helpers";
import {filterInvisibleNodes} from "../../../helpers/node-helpers";
import Loading from "../../Loading";
export type NodeData = {
id: string;
image_table_indices: { 1: string; 2: string; 3: string };
triggers_final_video: number;
required_final_video_viewcount: number;
media_file: string;
node_name: string;
site: string;
type: number;
title: string;
unlocked_by: string;
upgrade_requirement: number;
words: { 1: string; 2: string; 3: string };
matrixIndices?: {
matrixIdx: number;
rowIdx: number;
colIdx: number;
};
is_viewed?: number;
};
export type Level = {
[key: string]: NodeData;
};
export type SiteData = {
[key: string]: Level;
};
type SiteProps = {
introFinished: boolean;
};

View file

@ -1,4 +1,3 @@
import { NodeData } from "../components/MainScene/Site/Site";
import * as audio from "../static/audio/sfx";
import {
nodeExplodeAnimation,
@ -10,17 +9,14 @@ import {
import { playMediaElement, resetMediaElement } from "../helpers/media-helpers";
import {
ActiveSite,
EndComponent,
GameProgress,
GameScene,
EndComponent, GameProgress, GameScene,
LeftMediaComponent,
MediaComponent,
MediaSide,
MediaComponent, MediaSide, NodeData,
PromptComponent,
RightMediaComponent,
SiteSaveState,
SsknComponent,
} from "../store";
SsknComponent
} from "../types/types";
export const siteMoveHorizontal = (calculatedState: {
lainMoveAnimation: string;

View file

@ -1,21 +1,6 @@
import { playAudio, useStore } from "../store";
import sleep from "../utils/sleep";
type Mutation = {
mutation: Object;
delay?: number;
};
type EventAudio = {
sfx: HTMLAudioElement[];
delay?: number;
};
export type GameEvent = {
state?: Mutation[];
audio?: EventAudio[];
effects?: (() => void)[];
};
import { GameEvent } from "../types/types";
// the async/await here might be misleading for some, it functions as a setTimeout that fires
// multiple async calls without stopping the execution, which is what we want.

View file

@ -1,6 +1,5 @@
import authorize_user_letters from "../../resources/authorize_user_letters.json";
import handleNameSelection from "../../helpers/name-selection-helpers";
import { BootSceneContext } from "../../store";
import {
changeMainMenuComponent,
changePromptComponent,
@ -15,7 +14,7 @@ import {
updateAuthorizeUserLetterIdx,
updatePlayerName,
} from "../eventTemplates";
import { GameEvent } from "../handleEvent";
import {BootSceneContext, GameEvent} from "../../types/types";
const handleBootSceneKeyPress = (
bootSceneContext: BootSceneContext

View file

@ -1,10 +1,9 @@
import { EndSceneContext } from "../../store";
import {
changeEndComponent,
continueGameAfterEnd,
endGame,
} from "../eventTemplates";
import { GameEvent } from "../handleEvent";
import {EndSceneContext, GameEvent} from "../../types/types";
const handleEndSceneKeyPress = (
endSceneContext: EndSceneContext

View file

@ -4,7 +4,6 @@ import {
isNodeVisible,
unknownNodeTemplate,
} from "../../helpers/node-helpers";
import { MainSceneContext } from "../../store";
import {
changeNode,
changePauseComponent,
@ -32,7 +31,7 @@ import {
siteMoveVertical,
throwNode,
} from "../eventTemplates";
import { GameEvent } from "../handleEvent";
import {GameEvent, MainSceneContext} from "../../types/types";
const handleMainSceneKeyPress = (
mainSceneContext: MainSceneContext
@ -54,7 +53,6 @@ const handleMainSceneKeyPress = (
wordNotFound,
} = mainSceneContext;
console.log(activeNode.matrixIndices);
if (promptVisible) {
switch (keyPress) {
case "LEFT":

View file

@ -1,5 +1,4 @@
import { findNodeFromWord } from "../../helpers/media-helpers";
import { MediaSceneContext, RightMediaComponent } from "../../store";
import {
changeLeftMediaComponent,
changeMediaSide,
@ -9,8 +8,8 @@ import {
selectWord,
wordNotFound,
} from "../eventTemplates";
import { GameEvent } from "../handleEvent";
import { isNodeVisible } from "../../helpers/node-helpers";
import {GameEvent, MediaSceneContext, RightMediaComponent} from "../../types/types";
const handleMediaSceneKeyPress = (
mediaSceneContext: MediaSceneContext

View file

@ -1,6 +1,5 @@
import { SsknSceneContext } from "../../store";
import { changeSsknComponent, exitSskn, upgradeSskn } from "../eventTemplates";
import { GameEvent } from "../handleEvent";
import {GameEvent, SsknSceneContext} from "../../types/types";
const handleSsknSceneKeyPress = (
ssknSceneContext: SsknSceneContext

View file

@ -1,7 +1,7 @@
import site_a from "../resources/site_a.json";
import site_b from "../resources/site_b.json";
import { SiteData } from "../components/MainScene/Site/Site";
import { useStore } from "../store";
import {SiteData} from "../types/types";
export const getRandomIdleMedia = () => {
const siteAIdleNodes = {

View file

@ -1,8 +1,7 @@
import site_a from "../resources/site_a.json";
import site_b from "../resources/site_b.json";
import node_matrices from "../resources/node_matrices.json";
import { SiteData } from "../components/MainScene/Site/Site";
import { ActiveSite } from "../store";
import {ActiveSite, SiteData} from "../types/types";
export const findNodeFromWord = (
wordToFind: string,

View file

@ -1,10 +1,15 @@
import { NodeData, SiteData } from "../components/MainScene/Site/Site";
import site_a from "../resources/site_a.json";
import site_b from "../resources/site_b.json";
import node_huds from "../resources/node_huds.json";
import unlocked_nodes from "../resources/initial_progress.json";
import node_matrices from "../resources/node_matrices.json";
import { ActiveSite, GameProgress } from "../store";
import {
ActiveSite,
GameProgress,
NodeData,
NodeMatrixIndices,
SiteData,
} from "../types/types";
export const generateInactiveNodes = (
visibleNodes: SiteData,
@ -31,11 +36,7 @@ export const getNodeById = (id: string, activeSite: string) => {
const level = id.substr(0, 2);
return (siteData as SiteData)[level][id];
};
export const getNodeHud = (nodeMatrixIndices: {
matrixIdx: number;
rowIdx: number;
colIdx: number;
}) => {
export const getNodeHud = (nodeMatrixIndices: NodeMatrixIndices) => {
const hudAssocs = {
"00": "fg_hud_1",
"10": "fg_hud_2",

View file

@ -3,72 +3,32 @@ import { combine } from "zustand/middleware";
import * as THREE from "three";
import { AudioAnalyser } from "three";
import game_progress from "./resources/initial_progress.json";
import { NodeData } from "./components/MainScene/Site/Site";
import { getNodeById } from "./helpers/node-helpers";
import site_a from "./resources/site_a.json";
export type GameProgress = typeof game_progress;
type NodeAttributes = {
interactedWith: boolean;
exploding: boolean;
shrinking: boolean;
visible: boolean;
};
export type GameScene =
| "main"
| "media"
| "tak"
| "sskn"
| "polytan"
| "idle_media"
| "gate"
| "boot"
| "change_disc"
| "end";
type MainSubscene = "site" | "pause" | "level_selection";
export type ActiveSite = "a" | "b";
export type EndComponent = "end" | "continue";
export type PauseComponent = "load" | "about" | "change" | "save" | "exit";
export type MediaSide = "left" | "right";
export type LeftMediaComponent = "play" | "exit";
export type RightMediaComponent = "fstWord" | "sndWord" | "thirdWord";
export type MediaComponent = LeftMediaComponent | RightMediaComponent;
export type SiteSaveState = {
a: {
activeNode: NodeData;
siteRot: number[];
activeLevel: string;
};
b: {
activeNode: NodeData;
siteRot: number[];
activeLevel: string;
};
};
export type SsknComponent = "ok" | "cancel";
export type MainMenuComponent = "authorize_user" | "load_data";
export type BootSubscene = "main_menu" | "load_data" | "authorize_user";
export type PromptComponent = "yes" | "no";
type PolytanBodyParts = {
body: boolean;
head: boolean;
leftArm: boolean;
rightArm: boolean;
leftLeg: boolean;
rightLeg: boolean;
};
import {
ActiveSite,
BootSceneContext,
BootSubscene,
EndComponent,
EndSceneContext,
GameProgress,
GameScene,
LeftMediaComponent,
MainMenuComponent,
MainSceneContext,
MainSubscene,
MediaComponent,
MediaSceneContext,
MediaSide,
NodeAttributes, NodeData,
PauseComponent,
PolytanBodyParts,
PromptComponent,
RightMediaComponent,
SiteSaveState,
SsknComponent,
SsknSceneContext,
} from "./types/types";
type State = {
currentScene: GameScene;
@ -349,11 +309,6 @@ export const useStore = create(
)
);
type PromptContext = {
activePromptComponent: PromptComponent;
promptVisible: boolean;
};
const getPromptContext = () => {
const state = useStore.getState();
@ -363,21 +318,6 @@ const getPromptContext = () => {
};
};
export interface MainSceneContext extends PromptContext {
keyPress: string;
activeNode: NodeData;
showingAbout: boolean;
level: number;
activePauseComponent: PauseComponent;
gameProgress: GameProgress;
subscene: string;
siteRotY: number;
activeSite: ActiveSite;
selectedLevel: number;
wordNotFound: boolean;
siteSaveState: SiteSaveState;
}
export const getMainSceneContext = (keyPress: string): MainSceneContext => {
const state = useStore.getState();
@ -398,13 +338,6 @@ export const getMainSceneContext = (keyPress: string): MainSceneContext => {
};
};
export type SsknSceneContext = {
keyPress: string;
activeSsknComponent: SsknComponent;
activeNode: NodeData;
gameProgress: GameProgress;
};
export const getSsknSceneContext = (keyPress: string): SsknSceneContext => {
const state = useStore.getState();
return {
@ -415,20 +348,6 @@ export const getSsknSceneContext = (keyPress: string): SsknSceneContext => {
};
};
export type MediaSceneContext = {
keyPress: string;
wordPosStateIdx: number;
currentMediaSide: MediaSide;
activeMediaComponent: MediaComponent;
activeNode: NodeData;
gameProgress: GameProgress;
lastActiveMediaComponents: {
left: LeftMediaComponent;
right: RightMediaComponent;
};
activeSite: ActiveSite;
};
export const getMediaSceneContext = (keyPress: string): MediaSceneContext => {
const state = useStore.getState();
@ -444,14 +363,6 @@ export const getMediaSceneContext = (keyPress: string): MediaSceneContext => {
};
};
export interface BootSceneContext extends PromptContext {
keyPress: string;
playerName: string;
subscene: BootSubscene;
activeMainMenuComponent: MainMenuComponent;
authorizeUserLetterIdx: number;
}
export const getBootSceneContext = (keyPress: string): BootSceneContext => {
const state = useStore.getState();
@ -465,12 +376,6 @@ export const getBootSceneContext = (keyPress: string): BootSceneContext => {
};
};
export type EndSceneContext = {
keyPress: string;
activeEndComponent: EndComponent;
selectionVisible: boolean;
};
export const getEndSceneContext = (keyPress: string): EndSceneContext => {
const state = useStore.getState();

190
src/types/types.ts Normal file
View file

@ -0,0 +1,190 @@
import game_progress from "../resources/initial_progress.json";
export type GameProgress = typeof game_progress;
export type NodeAttributes = {
interactedWith: boolean;
exploding: boolean;
shrinking: boolean;
visible: boolean;
};
export type GameScene =
| "main"
| "media"
| "tak"
| "sskn"
| "polytan"
| "idle_media"
| "gate"
| "boot"
| "change_disc"
| "end";
export type MainSubscene = "site" | "pause" | "level_selection";
export type ActiveSite = "a" | "b";
export type EndComponent = "end" | "continue";
export type PauseComponent = "load" | "about" | "change" | "save" | "exit";
export type MediaSide = "left" | "right";
export type LeftMediaComponent = "play" | "exit";
export type RightMediaComponent = "fstWord" | "sndWord" | "thirdWord";
export type MediaComponent = LeftMediaComponent | RightMediaComponent;
export type NodeMatrixIndices = {
matrixIdx: number;
rowIdx: number;
colIdx: number;
};
export type NodeData = {
id: string;
image_table_indices: { 1: string; 2: string; 3: string };
triggers_final_video: number;
required_final_video_viewcount: number;
media_file: string;
node_name: string;
site: string;
type: number;
title: string;
unlocked_by: string;
upgrade_requirement: number;
words: { 1: string; 2: string; 3: string };
matrixIndices?: NodeMatrixIndices;
is_viewed?: number;
};
export type SiteSaveState = {
a: {
activeNode: NodeData;
siteRot: number[];
activeLevel: string;
};
b: {
activeNode: NodeData;
siteRot: number[];
activeLevel: string;
};
};
export type SsknComponent = "ok" | "cancel";
export type MainMenuComponent = "authorize_user" | "load_data";
export type BootSubscene = "main_menu" | "load_data" | "authorize_user";
export type PromptComponent = "yes" | "no";
export type PolytanBodyParts = {
body: boolean;
head: boolean;
leftArm: boolean;
rightArm: boolean;
leftLeg: boolean;
rightLeg: boolean;
};
type PromptContext = {
activePromptComponent: PromptComponent;
promptVisible: boolean;
};
export interface MainSceneContext extends PromptContext {
keyPress: string;
activeNode: NodeData;
showingAbout: boolean;
level: number;
activePauseComponent: PauseComponent;
gameProgress: GameProgress;
subscene: string;
siteRotY: number;
activeSite: ActiveSite;
selectedLevel: number;
wordNotFound: boolean;
siteSaveState: SiteSaveState;
}
export type SsknSceneContext = {
keyPress: string;
activeSsknComponent: SsknComponent;
activeNode: NodeData;
gameProgress: GameProgress;
};
export type MediaSceneContext = {
keyPress: string;
wordPosStateIdx: number;
currentMediaSide: MediaSide;
activeMediaComponent: MediaComponent;
activeNode: NodeData;
gameProgress: GameProgress;
lastActiveMediaComponents: {
left: LeftMediaComponent;
right: RightMediaComponent;
};
activeSite: ActiveSite;
};
export interface BootSceneContext extends PromptContext {
keyPress: string;
playerName: string;
subscene: BootSubscene;
activeMainMenuComponent: MainMenuComponent;
authorizeUserLetterIdx: number;
}
export type EndSceneContext = {
keyPress: string;
activeEndComponent: EndComponent;
selectionVisible: boolean;
};
export type Level = {
[key: string]: NodeData;
};
export type SiteData = {
[key: string]: Level;
};
type Effect = () => void;
type Mutation = {
mutation: Object;
delay?: number;
};
type EventAudio = {
sfx: HTMLAudioElement[];
delay?: number;
};
export type GameEvent = {
state?: Mutation[];
audio?: EventAudio[];
effects?: Effect[];
};
export type HUDData = {
mirrored: number;
long: {
position: number[];
initial_position: number[];
};
boring: {
position: number[];
initial_position: number[];
};
big: {
position: number[];
initial_position: number[];
};
big_text: number[];
medium_text: {
position: number[];
initial_position: number[];
};
};

13
src/utils/test-utils.tsx Normal file
View file

@ -0,0 +1,13 @@
import React, { FC, ReactElement, Suspense } from "react";
import { render } from "@testing-library/react";
const SuspenseProvider: FC = ({ children }) => {
return <Suspense fallback={null}>{children}</Suspense>;
};
const customRender = (ui: ReactElement) =>
render(ui, { wrapper: SuspenseProvider });
export * from "@testing-library/react";
export { customRender as render };