Skip to content

Commit

Permalink
Game areas
Browse files Browse the repository at this point in the history
  • Loading branch information
jon-bell committed Oct 22, 2023
1 parent ae52c1f commit cf69be6
Show file tree
Hide file tree
Showing 78 changed files with 5,413 additions and 1,802 deletions.
15 changes: 13 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
{
"jest.jestCommandLine": "npx jest",
"typescript.tsdk": "./townService/node_modules/typescript/lib"
"jest.jestCommandLine": "npx jest",
"typescript.tsdk": "node_modules/typescript/lib",
"prettier.configPath": "./townService/.prettierrc.cjs",
"editor.formatOnSave": false,
// Runs Prettier, then ESLint
"editor.codeActionsOnSave": [
"source.formatDocument",
"source.fixAll.eslint"
],
"eslint.workingDirectories": [
"./frontend",
"./townService",
]
}
28 changes: 28 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Start frontend Development Server",
"type": "npm",
"script": "dev",
"path": "frontend",
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "Start townService",
"type": "npm",
"script": "start",
"path": "townService",
"options": {
"cwd": "${workspaceFolder}/townService"
},
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ The backend will automatically restart if you change any of the files in the `to

Create a `.env` file in the `frontend` directory, with the line: `NEXT_PUBLIC_TOWNS_SERVICE_URL=http://localhost:8081` (if you deploy the towns service to another location, put that location here instead)

For ease of debugging, you might also set the environmental variable `NEXT_PUBLIC_TOWN_DEV_MODE=true`. When set to `true`, the frontend will
automatically connect to the town with the friendly name "DEBUG_TOWN" (creating one if needed), and will *not* try to connect to the Twilio API. This is useful if you want to quickly test changes to the frontend (reloading the page and re-acquiring video devices can be much slower than re-loading without Twilio).

### Running the frontend

In the `frontend` directory, run `npm start` (again, you'll need to run `npm install` the very first time). After several moments (or minutes, depending on the speed of your machine), a browser will open with the frontend running locally.
The frontend will automatically re-compile and reload in your browser if you change any files in the `frontend/src` directory.
In the `frontend` directory, run `npm run dev` (again, you'll need to run `npm install` the very first time). After several moments (or minutes, depending on the speed of your machine), a browser will open with the frontend running locally.
The frontend will automatically re-compile and reload in your browser if you change any files in the `frontend/src` directory.
5 changes: 5 additions & 0 deletions frontend/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ module.exports = {
selector: 'variable',
format: ['camelCase'],
},
{
selector: 'variable',
types: ['function'],
format: ['camelCase', 'PascalCase']
},
{
selector: 'typeLike',
format: ['PascalCase'],
Expand Down
4 changes: 4 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,15 @@
"typed-emitter": "^2.1.0",
"typescript": "^4.9.5"
},
"engines": {
"node": "18.x.x",
"npm": "9.x.x"
},
"scripts": {
"prestart": "npm run client",
"start": "next start",
"build": "next build",
"export": "next export",
"dev": "next dev",
"test": "cross-env DEBUG_PRINT_LIMIT=0 jest",
"test-watch": "jest --watch",
Expand Down
2 changes: 1 addition & 1 deletion frontend/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import './App.css';
import React from 'react';
import dynamic from 'next/dynamic';

//eslint-disable-next-line @typescript-eslint/naming-convention
Expand Down
12 changes: 12 additions & 0 deletions frontend/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';

import dynamic from 'next/dynamic';

//eslint-disable-next-line @typescript-eslint/naming-convention
const DynamicComponentWithNoSSR = dynamic(() => import('../src/App'), { ssr: false });

function NextApp() {
return <DynamicComponentWithNoSSR />;
}

export default NextApp;
416 changes: 285 additions & 131 deletions frontend/public/assets/tilemaps/indoors.json

Large diffs are not rendered by default.

43 changes: 0 additions & 43 deletions frontend/public/index.html

This file was deleted.

10 changes: 5 additions & 5 deletions frontend/public/virtualbackground/twilio-video-processors.js
Original file line number Diff line number Diff line change
Expand Up @@ -447,11 +447,11 @@ documented below.
*/
set: function (radius) {
if (typeof radius !== 'number' || radius < 0) {
console.warn(
'Valid mask blur radius not found. Using ' +
constants_1.MASK_BLUR_RADIUS +
' as default.',
);
// console.warn(
// 'Valid mask blur radius not found. Using ' +
// constants_1.MASK_BLUR_RADIUS +
// ' as default.',
// );
radius = constants_1.MASK_BLUR_RADIUS;
}
this._maskBlurRadius = radius;
Expand Down
10 changes: 5 additions & 5 deletions frontend/public/virtualbackground/twilio-video-processors.min.js
Original file line number Diff line number Diff line change
Expand Up @@ -426,11 +426,11 @@ documented below.
},
set: function (radius) {
if (typeof radius !== 'number' || radius < 0) {
console.warn(
'Valid mask blur radius not found. Using ' +
constants_1.MASK_BLUR_RADIUS +
' as default.',
);
// console.warn(
// 'Valid mask blur radius not found. Using ' +
// constants_1.MASK_BLUR_RADIUS +
// ' as default.',
// );
radius = constants_1.MASK_BLUR_RADIUS;
}
this._maskBlurRadius = radius;
Expand Down
76 changes: 73 additions & 3 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ChakraProvider } from '@chakra-ui/react';
import { MuiThemeProvider } from '@material-ui/core/styles';
import assert from 'assert';
import React, { useCallback, useState } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import { BrowserRouter } from 'react-router-dom';
import TownController from './classes/TownController';
import { ChatProvider } from './components/VideoCall/VideoFrontend/components/ChatProvider';
Expand All @@ -17,6 +17,7 @@ import TownMap from './components/Town/TownMap';
import TownControllerContext from './contexts/TownControllerContext';
import LoginControllerContext from './contexts/LoginControllerContext';
import { TownsServiceClient } from './generated/client';
import { nanoid } from 'nanoid';

function App() {
const [townController, setTownController] = useState<TownController | null>(null);
Expand All @@ -41,7 +42,7 @@ function App() {
page = <PreJoinScreens />;
}
const url = process.env.NEXT_PUBLIC_TOWNS_SERVICE_URL;
assert(url);
assert(url, 'NEXT_PUBLIC_TOWNS_SERVICE_URL must be defined');
const townsService = new TownsServiceClient({ BASE: url }).towns;
return (
<LoginControllerContext.Provider value={{ setTownController, townsService }}>
Expand All @@ -55,13 +56,82 @@ function App() {
);
}

const DEBUG_TOWN_NAME = 'DEBUG_TOWN';
function DebugApp(): JSX.Element {
const [townController, setTownController] = useState<TownController | null>(null);
useEffect(() => {
const url = process.env.NEXT_PUBLIC_TOWNS_SERVICE_URL;
assert(url, 'NEXT_PUBLIC_TOWNS_SERVICE_URL must be defined');
const townsService = new TownsServiceClient({ BASE: url }).towns;
async function getOrCreateDebugTownID() {
const towns = await townsService.listTowns();
const existingTown = towns.find(town => town.friendlyName === DEBUG_TOWN_NAME);
if (existingTown) {
return existingTown.townID;
} else {
try {
const newTown = await townsService.createTown({
friendlyName: DEBUG_TOWN_NAME,
isPubliclyListed: true,
});
return newTown.townID;
} catch (e) {
console.error(e);
//Try one more time to see if the town had been created by another process
const townsRetry = await townsService.listTowns();
const existingTownRetry = townsRetry.find(town => town.friendlyName === DEBUG_TOWN_NAME);
if (!existingTownRetry) {
throw e;
} else {
return existingTownRetry.townID;
}
}
}
}
getOrCreateDebugTownID().then(townID => {
assert(townID);
const newTownController = new TownController({
townID,
loginController: {
setTownController: () => {},
townsService,
},
userName: nanoid(),
});
newTownController.connect().then(() => {
setTownController(newTownController);
});
});
}, []);
if (!townController) {
return <div>Loading...</div>;
} else {
return (
<TownControllerContext.Provider value={townController}>
<ChatProvider>
<TownMap />
</ChatProvider>
</TownControllerContext.Provider>
);
}
}

function AppOrDebugApp(): JSX.Element {
const debugTown = process.env.NEXT_PUBLIC_TOWN_DEV_MODE;
if (debugTown && debugTown.toLowerCase() === 'true') {
return <DebugApp />;
} else {
return <App />;
}
}

export default function AppStateWrapper(): JSX.Element {
return (
<BrowserRouter>
<ChakraProvider>
<MuiThemeProvider theme={theme}>
<AppStateProvider>
<App />
<AppOrDebugApp />
</AppStateProvider>
</MuiThemeProvider>
</ChakraProvider>
Expand Down
30 changes: 21 additions & 9 deletions frontend/src/TestUtils.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { ReservedOrUserListener } from '@socket.io/component-emitter';
import { mock, MockProxy } from 'jest-mock-extended';
import { nanoid } from 'nanoid';
import ConversationAreaController from './classes/ConversationAreaController';
import ConversationAreaController from './classes/interactable/ConversationAreaController';
import PlayerController from './classes/PlayerController';
import TownController, { TownEvents } from './classes/TownController';
import ViewingAreaController from './classes/ViewingAreaController';
import ViewingAreaController from './classes/interactable/ViewingAreaController';
import { TownsService } from './generated/client';
import { CoveyTownSocket, ServerToClientEvents, TownJoinResponse } from './types/CoveyTownSocket';
import {
ConversationArea,
CoveyTownSocket,
ServerToClientEvents,
TownJoinResponse,
ViewingArea,
} from './types/CoveyTownSocket';

//These types copied from socket.io server library so that we don't have to depend on the whole thing to have type-safe tests.
type SocketReservedEventsMap = {
Expand Down Expand Up @@ -118,10 +124,12 @@ export function mockTownController({
Object.defineProperty(mockedController, 'players', { value: players });
}
if (conversationAreas) {
Object.defineProperty(mockedController, 'interactableAreas', { value: conversationAreas });
Object.defineProperty(mockedController, 'conversationAreas', { value: conversationAreas });
}
if (viewingAreas) {
Object.defineProperty(mockedController, 'viewingAreas', { value: viewingAreas });
Object.defineProperty(mockedController, 'interactableAreas', { value: viewingAreas });
Object.defineProperty(mockedController, 'viewingAreas', { value: conversationAreas });
}
return mockedController;
}
Expand Down Expand Up @@ -163,8 +171,9 @@ export async function mockTownControllerConnection(
responseToSendController.interactables.push({
id: nanoid(),
topic: undefined,
occupantsByID: [],
});
occupants: [],
type: 'ConversationArea',
} as ConversationArea);
for (let i = 0; i < 10; i++) {
const playerID = nanoid();
responseToSendController.currentPlayers.push({
Expand All @@ -175,14 +184,17 @@ export async function mockTownControllerConnection(
responseToSendController.interactables.push({
id: nanoid(),
topic: nanoid(),
occupantsByID: [playerID],
});
occupants: [playerID],
type: 'ConversationArea',
} as ConversationArea);
responseToSendController.interactables.push({
id: nanoid(),
video: nanoid(),
elapsedTimeSec: 0,
isPlaying: false,
});
occupants: [],
type: 'ViewingArea',
} as ViewingArea);
}
}
mockSocket.on.mockImplementationOnce((eventName, eventListener) => {
Expand Down
Loading

0 comments on commit cf69be6

Please sign in to comment.