Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
FROM mcr.microsoft.com/devcontainers/base:debian

RUN apt-get update && apt-get install -y curl

# install nvm
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.4/install.sh | bash

RUN export NVM_DIR="$HOME/.nvm" \
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" \
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"

# install node
RUN nvm install
RUN nvm use

# install corepack 0.10 only one compatible with node 12
RUN npm install -g corepack@0.10.0 serve@13.0.4
RUN corepack prepare yarn@2.4.1 --activate

# Next steps:
# - yarn install
# - yarn foreach-build-all
28 changes: 28 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/alpine
{
"name": "Alpine",
// More info: https://containers.dev/guide/dockerfile
"build": {
// Path is relative to the devcontainer.json file.
"dockerfile": "Dockerfile"
},
"features": {
// "ghcr.io/devcontainers/features/node:1": {
// "nodeGypDependencies": true,
// "version": "12",
// "pnpmVersion": "none",
// "nvmVersion": "latest"
// }
}
// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "uname -a",
// Configure tool-specific properties.
// "customizations": {},
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}
19 changes: 19 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.dockerignore
.git
.gitignore
.idea
.vscode
**/.DS_Store
**/node_modules
packages/*/dist
packages/*/lib
packages/*/build
**/tmp
**/.angular
**/.venv
**/.storybook/
**/coverage/
**/.env.local
**/.env.test
**/.eslintcache
**/*.log
5 changes: 3 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
"eslint.nodePath": ".yarn/sdks",
"typescript.tsdk": ".yarn/sdks/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true,
"typescript.preferences.includePackageJsonAutoImports": "on"
}
"typescript.preferences.includePackageJsonAutoImports": "on",
"js/ts.tsdk.path": ".yarn/sdks/typescript/lib"
}
64 changes: 64 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# monolith: backend & frontend
FROM alpine:3.23 AS monolith

LABEL org.opencontainers.image.title="Timeflies" \
org.opencontainers.image.description="Web multiplayer game - tactical-RPG." \
org.opencontainers.image.url="https://github.com/Chnapy/timeflies" \
org.opencontainers.image.source="https://github.com/Chnapy/timeflies" \
org.opencontainers.image.version="0.0.1" \
org.opencontainers.image.licenses="MIT" \
org.opencontainers.image.vendor="Timeflies" \
org.opencontainers.image.authors="Richard Haddad" \
org.opencontainers.image.base.name="alpine:3.23"

RUN apk add --no-cache \
nginx \
supervisor \
curl tar xz \
&& curl -fsSL https://unofficial-builds.nodejs.org/download/release/v12.22.12/node-v12.22.12-linux-x64-musl.tar.xz | \
tar -xJ -C /usr/local --strip-components=1 \
&& apk del curl tar xz \
&& rm -rf /var/cache/apk/*

WORKDIR /app

RUN node --version && npm --version

# install corepack 0.10 only one compatible with node 12
RUN npm install -g corepack@0.10.0 serve@13.0.4
RUN corepack prepare yarn@2.4.1 --activate

COPY package.json yarn.lock .yarnrc .yarnrc.yml ./
COPY ./.yarn/releases ./.yarn/releases
COPY ./.yarn/plugins ./.yarn/plugins
COPY ./.yarn/sdks ./.yarn/sdks
COPY ./packages ./packages

RUN yarn -v && yarn install

COPY babel.config.js tsconfig.json ./

RUN yarn workspace @timeflies/backend p:build-recursive

RUN yarn workspace @timeflies/frontend p:build-recursive

# should be defined before frontend final build
ENV REACT_APP_SERVER_URL=/api
ENV REACT_APP_WS_URL=/ws

RUN yarn workspace @timeflies/frontend build

# setup logs folders
RUN mkdir -p /var/log/supervisord /var/log/nginx /var/run/nginx \
&& chown -R 755 /var/log/nginx /var/run/nginx \
&& chmod -R 755 /var/log/supervisord

ENV PORT=40510
ENV HOST_URL=/api

COPY nginx.conf /etc/nginx/nginx.conf
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

EXPOSE 3000

CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
12 changes: 5 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,15 @@

<h1 align="center">Timeflies</h1>

<h6 align="center">
<a href="https://timeflies.fr"><b>PLAY</b></a>
</h6>
<!-- <h6 align="center">
<a href=""><b>PLAY</b></a>
</h6> -->

> Project aborted since 2021

Timeflies is a web multiplayer tactical-RPG.
This game can be played on any modern browser (= chrome or firefox please).

![Code quality](https://www.code-inspector.com/project/23679/score/svg)
[![Netlify Status](https://api.netlify.com/api/v1/badges/249b0bb9-e394-4f23-a7d0-eafbc965b744/deploy-status)](https://app.netlify.com/sites/timeflies-game/deploys)
![Heroku](https://pyheroku-badge.herokuapp.com/?app=timeflies-game)

## Bulk features

- :musical_note: Wonderful sounds & musics
Expand Down
47 changes: 47 additions & 0 deletions nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

server {
listen 3000;

# static files (SPA fallback)
location / {
root /app/packages/frontend/build;
index index.html;
try_files $uri $uri/ /index.html;
}

# proxy backend API calls
location /api/ {
proxy_pass http://localhost:40510/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}

# proxy backend websocket calls
location /ws {
proxy_pass http://localhost:40510;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
}
}
}
2 changes: 1 addition & 1 deletion packages/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"main": "lib/index.js",
"types": "lib/index.d.ts",
"scripts": {
"start": "PORT=40510 HOST_URL=https://localhost:40510 JWT_PRIVATE_KEY=foo ts-node src/index.ts",
"start": "PORT=40510 HOST_URL=http://localhost:40510 ts-node src/index.ts",
"build-all": "yarn p:build-recursive",
"serve": "yarn node lib/index.js"
},
Expand Down
20 changes: 2 additions & 18 deletions packages/backend/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,21 @@ import { json, urlencoded } from 'body-parser';
import cors from "cors";
import express from 'express';
import http from 'http';
import https from 'https';
import WebSocket from 'ws';
import { config } from './main/config';
import { createGlobalEntities } from './main/global-entities';
import { onAllServicesSocketConnect } from './services/services';
import { getEnv } from './utils/env';
import { readFileSync } from 'fs';

const port = Number(getEnv('PORT'));

const isLocalhost = getEnv('HOST_URL').includes('://localhost');

// Express

const app = express();

// TODO do not hardcode
const origin = isLocalhost
? [ 'https://localhost:3000' ]
: [ 'https://timeflies.fr', 'https://timeflies-game.herokuapp.com' ];

app.use(
cors({
origin,
origin: '*',
allowedHeaders: '*'
}),
urlencoded({ extended: false }),
Expand All @@ -41,14 +32,7 @@ const globalEntities = createGlobalEntities();

app.post(authEndpoint, globalEntities.services.authService.httpAuthRoute);

const server = isLocalhost
// https in localhost to simulate Heroku https
? https.createServer({
key: readFileSync('../../localhost-key.pem'),
cert: readFileSync('../../localhost.pem')
}, app)
// Heroku do not need https server (it causes errors)
: http.createServer(app);
const server = http.createServer(app);

// Websocket

Expand Down
10 changes: 4 additions & 6 deletions packages/backend/src/services/auth/auth-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import { PlayerCredentialsTimed } from '../../main/global-entities';
import { getEnv } from '../../utils/env';
import { Service } from '../service';

const privateKey = getEnv('JWT_PRIVATE_KEY');

export class AuthService extends Service {
protected afterSocketConnect = () => { };

Expand Down Expand Up @@ -72,7 +70,7 @@ export class AuthService extends Service {
playerName
};

const token = JWT.sign(tokenPayload, privateKey, { algorithm: 'HS256' });
const token = JWT.sign(tokenPayload, 'none', { algorithm: 'HS256' });

const playerCredentials: PlayerCredentials = {
playerId,
Expand Down Expand Up @@ -100,9 +98,9 @@ export class AuthService extends Service {
}

const token = new URLSearchParams(
url.startsWith('/?') // localhost
? url.substring(2)
: new URL(url).search
url.startsWith('http')
? new URL(url).search
: new URL(url, 'http://localhost').search
).get('token')!;

const socketQueryParams: SocketQueryParams = { token };
Expand Down
3 changes: 1 addition & 2 deletions packages/backend/src/setup-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@ import { applySetupTests } from '@timeflies/devtools';
applySetupTests();

process.env.PORT = '1234';
process.env.HOST_URL = 'https://host.com';
process.env.JWT_PRIVATE_KEY = 'foo';
process.env.HOST_URL = 'http://host.com';
4 changes: 2 additions & 2 deletions packages/backend/src/utils/asset-url.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ describe('asset url', () => {
});

it('to frontend', () => {
expect(assetUrl.toFrontend('foo/bar')).toEqual('https://host.com/static/foo/bar');
expect(assetUrl.toFrontend('/foo/bar')).toEqual('https://host.com/static/foo/bar');
expect(assetUrl.toFrontend('foo/bar')).toEqual('http://host.com/static/foo/bar');
expect(assetUrl.toFrontend('/foo/bar')).toEqual('http://host.com/static/foo/bar');
});
});
2 changes: 1 addition & 1 deletion packages/backend/src/utils/env.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

const requiredKeys = [ 'PORT', 'HOST_URL', 'JWT_PRIVATE_KEY' ] as const;
const requiredKeys = [ 'PORT', 'HOST_URL' ] as const;

console.table(requiredKeys.reduce<Record<string, any>>((acc, key) => {
acc[ key ] = process.env[ key ];
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/.env
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ REACT_APP_TITLE=Timeflies | Multiplayer tactical-RPG game
REACT_APP_DESCRIPTION=Timeflies is a free multiplayer tactical-RPG game, with a time-based gameplay.
REACT_APP_AUTHOR=Richard Haddad
REACT_APP_PREVIEW_IMG=https://repository-images.githubusercontent.com/238224907/2e8aad0f-7446-4cd2-a628-577f86f47174
REACT_APP_URL=https://timeflies.fr
REACT_APP_URL=https://github.com/Chnapy/timeflies
3 changes: 2 additions & 1 deletion packages/frontend/.env.local
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
REACT_APP_SERVER_URL=https://localhost:40510
REACT_APP_SERVER_URL=http://localhost:40510
REACT_APP_WS_URL=http://localhost:40510
3 changes: 2 additions & 1 deletion packages/frontend/.env.test
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
REACT_APP_SERVER_URL=foo
REACT_APP_SERVER_URL=foo
REACT_APP_WS_URL=foo
8 changes: 4 additions & 4 deletions packages/frontend/mock-server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ app.use('/public', express.static('mock-server/public'));
const server = http.createServer(app);

const port = 40510;
const wss = new WebSocketServer({ server });
const ws = new WebSocketServer({ server });

console.log('Mock server started');

server.listen(port, () => {
console.log('server listening address', server.address());
console.log('ws listening address', wss.address());
console.log('ws listening address', ws.address());
});

const turnsOrder = [ 'c2', 'c1', 'c3' ];
Expand Down Expand Up @@ -173,7 +173,7 @@ const battleLoadData: BattleLoadData = {

const sendAll = action => {
console.log('sendAll: %s', JSON.stringify(action));
wss.clients.forEach(ws => {
ws.clients.forEach(ws => {
ws.send(JSON.stringify([ action ]));
});
};
Expand All @@ -194,7 +194,7 @@ const sendAllNextTurnInfos = () => setTimeout(() =>
BattleTurnStartMessage(cycleEngine.getNextTurnInfos())
), 1000);

wss.on('connection', function (ws) {
ws.on('connection', function (ws) {

const startTime = Date.now() + 5000;

Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"main": "lib/index.js",
"types": "lib/index.d.ts",
"scripts": {
"start": "yarn copy-assets && HTTPS=true SSL_CRT_FILE=../../localhost.pem SSL_KEY_FILE=../../localhost-key.pem react-scripts start",
"start": "yarn copy-assets && react-scripts start",
"build": "yarn copy-assets && react-scripts build",
"build-all": "yarn p:build-recursive && yarn build",
"test": "react-scripts test",
Expand Down
Loading
Loading