Compare commits
10 commits
f5380927fd
...
b6f81f94f4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6f81f94f4 | ||
|
|
cd50ab17b3 | ||
|
|
697836579b | ||
|
|
e1c46e7ba0 | ||
|
|
90d2257c17 | ||
|
|
1c9de06b66 | ||
|
|
94e85e04d5 | ||
|
|
000b62fd40 | ||
|
|
23dc908344 | ||
|
|
89e2f52063 |
17 changed files with 181 additions and 162 deletions
6
.dockerignore
Normal file
6
.dockerignore
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
**/node_modules
|
||||
**/.cache
|
||||
**/.DS_Store
|
||||
**/storage
|
||||
**/dist
|
||||
**/.env
|
||||
33
Dockerfile
Normal file
33
Dockerfile
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
FROM node:18-alpine
|
||||
|
||||
RUN apk add g++ make py3-pip
|
||||
|
||||
RUN mkdir -p /usr/app
|
||||
WORKDIR /usr/app
|
||||
|
||||
ENV API_PATH="/api"
|
||||
|
||||
COPY game/package*.json ./
|
||||
RUN npm install --quite
|
||||
|
||||
COPY game .
|
||||
RUN npm run build
|
||||
|
||||
FROM node:18-alpine
|
||||
RUN mkdir -p /usr/app/public
|
||||
WORKDIR /usr/app
|
||||
|
||||
ENV STATIC="/usr/app/public"
|
||||
ENV PORT=80
|
||||
EXPOSE 80/tcp
|
||||
|
||||
COPY --from=0 /usr/app/dist ./public
|
||||
|
||||
COPY server/package*.json ./
|
||||
RUN npm install --quite
|
||||
|
||||
COPY server .
|
||||
COPY ./run.sh .
|
||||
|
||||
CMD ./run.sh
|
||||
|
||||
66
README.md
66
README.md
|
|
@ -2,9 +2,67 @@
|
|||
|
||||
Tested on node `v14.17.3`
|
||||
|
||||
You can play the game [here](#)
|
||||
You can play the game [here](https://mystifying-hypatia-4b1cef.netlify.app/) (unfortunelly I can not setup server, so this instance does not provide a ranking 😥).
|
||||
Please be patient waiting for the game to load. My crappy, free hosting need some time to load assets.
|
||||
|
||||
In the `game` directory there game client.
|
||||
In the `server` directory there are authentiaction and ranking server.
|
||||
The game was created for the first edition of [Hackerspace Trójmiasto's Community](https://github.com/hs3city/hs3-jam) Jam.
|
||||
|
||||
To start the app locally, you need... *TODO* :)
|
||||

|
||||
|
||||
## How to start a game
|
||||
|
||||
You need the [NodeJS](https://nodejs.org/en/) installed.
|
||||
|
||||
~~The game's server do not serve game client's files. They are separately apps.~~
|
||||
The server is responsible for authentication and storing records.
|
||||
Data is stored as plain JSON files in `server/storage` directory.
|
||||
You do not have to setup any external database :)
|
||||
|
||||
The game *should* work without server, with some limitations.
|
||||
Space Smasher works fine on desktop, and not on mobile at all.
|
||||
|
||||
Keys: `WSAD + Mouse`
|
||||
|
||||
## Use Docker
|
||||
|
||||
### LETS GO
|
||||
```sh
|
||||
# run as a daemon
|
||||
🐧 docker run -d -p 80:80 --restart=always --name smasher ghcr.io/kgrzeg/space-smasher-9001:latest
|
||||
# or run in foreground
|
||||
🐧 docker run -ti -p 80:80 --rm --name smasher ghcr.io/kgrzeg/space-smasher-9001:latest
|
||||
```
|
||||
|
||||
### Build image locally
|
||||
```sh
|
||||
🐧 docker build -t space-smasher-9001:latest .
|
||||
# run as a daemon
|
||||
🐧 docker run -d -p 80:80 --restart=always --name smasher space-smasher-9001
|
||||
# or run in foreground
|
||||
🐧 docker run -ti -p 80:80 --rm --name smasher space-smasher-9001
|
||||
```
|
||||
|
||||
## Setup for development
|
||||
### run server
|
||||
```sh
|
||||
🐧 cd server
|
||||
🐧 npm install # install dependencies
|
||||
🐧 cp .env.example .env
|
||||
🐧 # edit .env file - UPDATE THE SECRET!
|
||||
🐧 npm start # the server listening on port 3000.
|
||||
```
|
||||
|
||||
### Setup and run client
|
||||
```sh
|
||||
🐧 cd .. # only if your cwd is server directory
|
||||
🐧 cd game
|
||||
🐧 npm install # install dependencies
|
||||
🐧 # edit first line of src/api.ts to match your server
|
||||
🐧 npm start # to run in Dev mode (hot reloading and recompilling)
|
||||
🐧 npm run build
|
||||
🐧 # your app is in dist directory, you need to serve it via www server
|
||||
```
|
||||
|
||||
The most knowledge you can get by reading the sources or dockerfile. I will fill the readme one day... maybe.
|
||||
|
||||
## Enjoy!
|
||||
|
|
|
|||
10
docker-compose.yml
Normal file
10
docker-compose.yml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
version: '3'
|
||||
|
||||
services:
|
||||
smasher:
|
||||
image: ghcr.io/kgrzeg/space-smasher-9001:latest
|
||||
# build: .
|
||||
container_name: space-smasher-9001
|
||||
ports:
|
||||
- "80:80"
|
||||
restart: always
|
||||
5
game/README.md
Normal file
5
game/README.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Start Game Client
|
||||
|
||||
For more info look at main README.md
|
||||
|
||||
I used [phaser3-typescript-parcel-template](https://github.com/ourcade/phaser3-typescript-parcel-template) as startup project (but typescript config was messed up)
|
||||
13
game/package-lock.json
generated
13
game/package-lock.json
generated
|
|
@ -12,6 +12,7 @@
|
|||
"phaser": "^3.55.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.14.2",
|
||||
"@typescript-eslint/eslint-plugin": "^2.29.0",
|
||||
"@typescript-eslint/parser": "^2.29.0",
|
||||
"eslint": "^6.8.0",
|
||||
|
|
@ -1790,6 +1791,12 @@
|
|||
"integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "18.14.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.2.tgz",
|
||||
"integrity": "sha512-1uEQxww3DaghA0RxqHx0O0ppVlo43pJhepY51OxuQIKHpjbnYLA7vcdwioNPzIqmC2u3I/dmylcqjlh0e7AyUA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/q": {
|
||||
"version": "1.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz",
|
||||
|
|
@ -11286,6 +11293,12 @@
|
|||
"integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "18.14.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.2.tgz",
|
||||
"integrity": "sha512-1uEQxww3DaghA0RxqHx0O0ppVlo43pJhepY51OxuQIKHpjbnYLA7vcdwioNPzIqmC2u3I/dmylcqjlh0e7AyUA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/q": {
|
||||
"version": "1.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz",
|
||||
|
|
|
|||
|
|
@ -4,9 +4,7 @@
|
|||
"description": "Simple Phaser 3 game for the Hackerspace Trójmiasto's little game jam",
|
||||
"scripts": {
|
||||
"start": "parcel src/index.html -p 8000",
|
||||
"build": "parcel build src/index.html --out-dir dist --no-source-maps",
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"lint": "eslint ./src --ext .js,.jsx,.ts,.tsx"
|
||||
"build": "parcel build src/index.html --out-dir dist --no-source-maps"
|
||||
},
|
||||
"author": "Grzegorz Kupczyk",
|
||||
"license": "MIT",
|
||||
|
|
@ -16,6 +14,7 @@
|
|||
},
|
||||
"homepage": "https://github.com/ourcade/phaser3-parcel-template",
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.14.2",
|
||||
"@typescript-eslint/eslint-plugin": "^2.29.0",
|
||||
"@typescript-eslint/parser": "^2.29.0",
|
||||
"eslint": "^6.8.0",
|
||||
|
|
|
|||
138
game/readme.md
138
game/readme.md
|
|
@ -1,138 +0,0 @@
|
|||
This is a fork of [phaser3-typescript-parcel-template](https://github.com/ourcade/phaser3-typescript-parcel-template)
|
||||
|
||||

|
||||
|
||||
# Phaser 3 + TypeScript + Parcel Template
|
||||
> For people who want to spend time making Phaser 3 games in TypeScript instead of configuring build tools.
|
||||
|
||||

|
||||
|
||||
This is a TypeScript specific fork of [phaser3-parcel-template](https://github.com/ourcade/phaser3-parcel-template).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You'll need [Node.js](https://nodejs.org/en/), [npm](https://www.npmjs.com/), and [Parcel](https://parceljs.org/) installed.
|
||||
|
||||
It is highly recommended to use [Node Version Manager](https://github.com/nvm-sh/nvm) (nvm) to install Node.js and npm.
|
||||
|
||||
For Windows users there is [Node Version Manager for Windows](https://github.com/coreybutler/nvm-windows).
|
||||
|
||||
Install Node.js and `npm` with `nvm`:
|
||||
|
||||
```bash
|
||||
nvm install node
|
||||
|
||||
nvm use node
|
||||
```
|
||||
|
||||
Replace 'node' with 'latest' for `nvm-windows`.
|
||||
|
||||
Then install Parcel:
|
||||
|
||||
```bash
|
||||
npm install -g parcel-bundler
|
||||
```
|
||||
|
||||
## Getting Started
|
||||
|
||||
Clone this repository to your local machine:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/ourcade/phaser3-typescript-parcel-template.git
|
||||
```
|
||||
|
||||
This will create a folder named `phaser3-typescript-parcel-template`. You can specify a different folder name like this:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/ourcade/phaser3-typescript-parcel-template.git my-folder-name
|
||||
```
|
||||
|
||||
Go into your new project folder and install dependencies:
|
||||
|
||||
```bash
|
||||
cd phaser3-typescript-parcel-template # or 'my-folder-name'
|
||||
npm install
|
||||
```
|
||||
|
||||
Start development server:
|
||||
|
||||
```
|
||||
npm run start
|
||||
```
|
||||
|
||||
To create a production build:
|
||||
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
Production files will be placed in the `dist` folder. Then upload those files to a web server. 🎉
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
.
|
||||
├── dist
|
||||
├── node_modules
|
||||
├── public
|
||||
├── src
|
||||
│ ├── scenes
|
||||
│ │ ├── HelloWorldScene.ts
|
||||
│ ├── index.html
|
||||
│ ├── main.ts
|
||||
├── package.json
|
||||
```
|
||||
|
||||
The contents of this template is the basic [Phaser 3 getting started example](http://phaser.io/tutorials/getting-started-phaser3/part5).
|
||||
|
||||
This template assumes you will want to organize your code into multiple files and use TypeScript.
|
||||
|
||||
TypeScript files are intended for the `src` folder. `main.ts` is the entry point referenced by `index.html`.
|
||||
|
||||
Other than that there is no opinion on how you should structure your project. There is a `scenes` folder in `src` where the `HelloWorldScene.ts` lives but you can do whatever you want.
|
||||
|
||||
## Static Assets
|
||||
|
||||
Any static assets like images or audio files should be placed in the `public` folder. It'll then be served at http://localhost:8000/images/my-image.png
|
||||
|
||||
Example `public` structure:
|
||||
|
||||
```
|
||||
public
|
||||
├── images
|
||||
│ ├── my-image.png
|
||||
├── music
|
||||
│ ├── ...
|
||||
├── sfx
|
||||
│ ├── ...
|
||||
```
|
||||
|
||||
They can then be loaded by Phaser with `this.image.load('my-image', 'images/my-image.png')`.
|
||||
|
||||
## TypeScript ESLint
|
||||
|
||||
This template uses a basic `typescript-eslint` set up for code linting.
|
||||
|
||||
It does not aim to be opinionated.
|
||||
|
||||
## Dev Server Port
|
||||
|
||||
You can change the dev server's port number by modifying the `start` script in `package.json`. We use Parcel's `-p` option to specify the port number.
|
||||
|
||||
The script looks like this:
|
||||
|
||||
```
|
||||
parcel src/index.html -p 8000
|
||||
```
|
||||
|
||||
Change 8000 to whatever you want.
|
||||
|
||||
## Other Notes
|
||||
|
||||
[parcel-plugin-clean-easy](https://github.com/lifuzhao100/parcel-plugin-clean-easy) is used to ensure only the latest files are in the `dist` folder. You can modify this behavior by changing `parcelCleanPaths` in `package.json`.
|
||||
|
||||
[parcel-plugin-static-files](https://github.com/elwin013/parcel-plugin-static-files-copy#readme) is used to copy static files from `public` into the output directory and serve it. You can add additional paths by modifying `staticFiles` in `package.json`.
|
||||
|
||||
## License
|
||||
|
||||
[MIT License](https://github.com/ourcade/phaser3-typescript-parcel-template/blob/master/LICENSE)
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
const baseApiPath = "http://localhost:3000"
|
||||
const baseApiPath = process.env.API_PATH ?? "http://localhost:3000"
|
||||
|
||||
export default {
|
||||
async post(path: string, data?: any) {
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@ declare global {
|
|||
|
||||
function logout() {
|
||||
const sure = confirm("Are you sure you want to log out? " +
|
||||
"You won't be able to login again without #key. " +
|
||||
"Make sure you copied #key before log out!\n\n" +
|
||||
"You won't be able to login again without the #key. " +
|
||||
"Make sure you have copied the #key before log out!\n\n" +
|
||||
"The #key: " + window.myStuff.key)
|
||||
|
||||
if (!sure)
|
||||
|
|
|
|||
11
run.sh
Executable file
11
run.sh
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/sh
|
||||
|
||||
mkdir -p storage
|
||||
|
||||
if [ ! -f ".env" ]; then
|
||||
cp .env.example .env
|
||||
sed -i "s#HVuwh1dmaFhg4q1fef7xI4D6UeV7ImGK6NTp7i9eH6qiyJ9kxsvqPu29JXnhNGQY#$(head -c 12 /dev/random | base64)#" .env
|
||||
fi
|
||||
|
||||
npm run start
|
||||
|
||||
|
|
@ -1,2 +1,3 @@
|
|||
secret = oIMzR4YvM9x9NoPrQfk4
|
||||
secret = HVuwh1dmaFhg4q1fef7xI4D6UeV7ImGK6NTp7i9eH6qiyJ9kxsvqPu29JXnhNGQY
|
||||
enableJusticeGuard = 1
|
||||
PORT = 3001
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export default {
|
|||
error: "Incorrect name"
|
||||
}
|
||||
|
||||
const re = /^[a-zA-z0-9_$][a-zA-z0-9 _$]{,15}$/
|
||||
const re = /^[a-zA-Z0-9_$][a-zA-Z0-9 _$]{1,15}$/
|
||||
if (!re.test(name))
|
||||
return {
|
||||
error: "Incorrect name"
|
||||
|
|
|
|||
5
server/README.md
Normal file
5
server/README.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Start Game Server
|
||||
|
||||
For more info look at main README.md
|
||||
|
||||
I used [phaser3-typescript-parcel-template](https://github.com/ourcade/phaser3-typescript-parcel-template) as startup project (but typescript config was messed up)
|
||||
|
|
@ -4,7 +4,8 @@
|
|||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "nodemon --ignore ./storage/ --exec babel-node server.js"
|
||||
"dedv": "nodemon --ignore ./storage/ --exec babel-node server.js",
|
||||
"start": "babel-node server.js"
|
||||
},
|
||||
"type": "module",
|
||||
"keywords": [],
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import auth from './Auth.js'
|
|||
import db from './Database.js'
|
||||
import jg from './JusticeGuard.js'
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
const protect = (req, res, next) => {
|
||||
const authHeader = req.headers.authorization;
|
||||
|
||||
|
|
@ -42,19 +44,21 @@ const neededArguments = (args) => {
|
|||
|
||||
const app = express()
|
||||
app.use(morgan('combined'))
|
||||
app.use(express.json())
|
||||
app.use(cors())
|
||||
|
||||
app.get("/", (_, res) => {
|
||||
router.use(express.json())
|
||||
|
||||
router.get("/", (_, res) => {
|
||||
res.json({ message: "Hello! API here" })
|
||||
|
||||
});
|
||||
|
||||
app.get("/secured", protect, (req, res) => {
|
||||
router.get("/secured", protect, (req, res) => {
|
||||
res.json({ message: "You can see it!", payload: req.user })
|
||||
})
|
||||
|
||||
app.post("/signup", neededArguments(['name']), async (req, res) => {
|
||||
router.post("/signup", neededArguments(['name']), async (req, res) => {
|
||||
|
||||
const user = await auth.createAccount(req.body.name)
|
||||
|
||||
if (user.error)
|
||||
|
|
@ -65,7 +69,7 @@ app.post("/signup", neededArguments(['name']), async (req, res) => {
|
|||
res.json(user)
|
||||
})
|
||||
|
||||
app.post("/login", neededArguments(['key']), async (req, res) => {
|
||||
router.post("/login", neededArguments(['key']), async (req, res) => {
|
||||
const user = auth.login(req.body.key)
|
||||
|
||||
if (user.error)
|
||||
|
|
@ -76,7 +80,7 @@ app.post("/login", neededArguments(['key']), async (req, res) => {
|
|||
res.json(user)
|
||||
})
|
||||
|
||||
app.post("/record", protect, neededArguments(['points', 'shoots', 'time']), jg, async (req, res) => {
|
||||
router.post("/record", protect, neededArguments(['points', 'shoots', 'time']), jg, async (req, res) => {
|
||||
db.updateRecord(req.user.name, req.body.points)
|
||||
const rank = db.getRank(req.user.name)
|
||||
|
||||
|
|
@ -88,14 +92,14 @@ app.post("/record", protect, neededArguments(['points', 'shoots', 'time']), jg,
|
|||
})
|
||||
})
|
||||
|
||||
app.get("/top", (req, res) => {
|
||||
router.get("/top", (req, res) => {
|
||||
res.json({
|
||||
status: "ok",
|
||||
records: db.getTop()
|
||||
})
|
||||
})
|
||||
|
||||
app.get("/start", protect, async (req, res) => {
|
||||
router.get("/start", protect, async (req, res) => {
|
||||
await db.setLastPlayedToNow(req.user.name)
|
||||
|
||||
res.json({
|
||||
|
|
@ -103,11 +107,22 @@ app.get("/start", protect, async (req, res) => {
|
|||
})
|
||||
})
|
||||
|
||||
if (process.env.STATIC) {
|
||||
app.use(express.static(process.env.STATIC));
|
||||
app.use("/api", router);
|
||||
} else {
|
||||
app.use("/", router);
|
||||
}
|
||||
|
||||
app.use(function (err, req, res, next) {
|
||||
if (err.name === 'UnauthorizedError') {
|
||||
res.status(401).send('invalid token...');
|
||||
}
|
||||
});
|
||||
|
||||
await db.read()
|
||||
app.listen(3000)
|
||||
(async function () { await db.read() })()
|
||||
|
||||
const port = process.env.PORT || 3000
|
||||
app.listen(port, () => {
|
||||
console.log(`Server listening on port ${port}!`);
|
||||
})
|
||||
|
|
|
|||
BIN
ss.jpg
Normal file
BIN
ss.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 131 KiB |
Loading…
Add table
Add a link
Reference in a new issue