Compare commits
4 commits
c40492c0e3
...
9107c557af
Author | SHA1 | Date | |
---|---|---|---|
9107c557af | |||
e34ae6d1c3 | |||
6df42d2e3f | |||
d87da24d30 |
35 changed files with 99 additions and 862 deletions
|
@ -7,11 +7,14 @@ module.exports = {
|
|||
`plugin:${PluginName}/${PresetName.RecommendedWithTypeChecking}`
|
||||
],
|
||||
env: {
|
||||
node: true
|
||||
node: true,
|
||||
browser: true
|
||||
},
|
||||
parserOptions: {
|
||||
project: [
|
||||
join(__dirname, "eslint.jsconfig.json")
|
||||
join(__dirname, "app.jsconfig.json"),
|
||||
join(__dirname, "eslint.jsconfig.json"),
|
||||
join(__dirname, "gulp.tsconfig.json")
|
||||
]
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,15 +1,6 @@
|
|||
{
|
||||
"folders": [
|
||||
{
|
||||
"name": "ConnectForce",
|
||||
"path": "./packages/game"
|
||||
},
|
||||
{
|
||||
"name": "Server",
|
||||
"path": "./packages/server"
|
||||
},
|
||||
{
|
||||
"name": "Solution Items",
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
|
@ -35,7 +26,7 @@
|
|||
"label": "Build",
|
||||
"type": "shell",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder:Solution Items}"
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
"command": "npm",
|
||||
"args": [
|
||||
|
@ -72,7 +63,7 @@
|
|||
"label": "Rebuild",
|
||||
"type": "shell",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder:Solution Items}"
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
"command": "npm",
|
||||
"args": [
|
||||
|
@ -88,7 +79,7 @@
|
|||
"label": "Lint",
|
||||
"type": "shell",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder:Solution Items}"
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
"command": "npm",
|
||||
"args": [
|
||||
|
@ -113,33 +104,11 @@
|
|||
"request": "launch",
|
||||
"name": "Launch Website in Chrome",
|
||||
"url": "http://localhost:3000",
|
||||
"webRoot": "${workspaceFolder:ConnectForce}/lib/static",
|
||||
"webRoot": "${workspaceFolder}/lib/static",
|
||||
"preLaunchTask": "Build",
|
||||
"pathMapping": {
|
||||
"/": "${workspaceFolder:ConnectForce}/src"
|
||||
},
|
||||
"presentation": {
|
||||
"hidden": true
|
||||
"/": "${workspaceFolder}/src"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Launch Server",
|
||||
"program": "${workspaceFolder:Server}/src/main.js",
|
||||
"console": "integratedTerminal",
|
||||
"presentation": {
|
||||
"hidden": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"compounds": [
|
||||
{
|
||||
"name": "Launch Project in Chrome",
|
||||
"configurations": [
|
||||
"Launch Website in Chrome",
|
||||
"Launch Server"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) <year> <copyright holders>
|
||||
Copyright (c) 2022 Manuel Thalmann
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
|
|
@ -137,7 +137,7 @@ export let Watch: TaskFunction = async (): Promise<void> =>
|
|||
|
||||
syncer.init({
|
||||
open: false,
|
||||
proxy: "http://localhost:1337",
|
||||
server: join(context.StaticPath()),
|
||||
online: false
|
||||
});
|
||||
|
39
package.json
39
package.json
|
@ -1,26 +1,31 @@
|
|||
{
|
||||
"name": "connect-force",
|
||||
"private": true,
|
||||
"files": [],
|
||||
"workspaces": {
|
||||
"packages": [
|
||||
"./packages/*"
|
||||
]
|
||||
},
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"description": "A selfmade Connect Four game.",
|
||||
"author": "Manuel Thalmann <m@nuth.ch>",
|
||||
"scripts": {
|
||||
"rebuild": "npm run --workspaces rebuild",
|
||||
"watch": "concurrently --raw \"npm run --workspaces --if-present watch\"",
|
||||
"clean": "npm run --workspaces clean",
|
||||
"lint-local": "eslint --max-warnings 0 .eslintrc.cjs",
|
||||
"lint-local-ide": "npm run lint-local || exit 0",
|
||||
"lint": "npm run lint-local && npm run --workspaces lint",
|
||||
"lint-ide": "npm run lint-local-ide && npm run --workspaces lint-ide",
|
||||
"test": "npm run --workspaces test",
|
||||
"gulp": "cross-env NODE_OPTIONS=\"--loader ts-node/esm\" gulp --",
|
||||
"build": "npm run gulp Build",
|
||||
"rebuild": "npm run clean && npm run build",
|
||||
"watch": "npm run gulp Watch",
|
||||
"clean": "rimraf ./lib",
|
||||
"lint": "eslint --max-warnings 0 ./src .eslintrc.cjs",
|
||||
"lint-ide": "npm run lint || exit 0",
|
||||
"prepare": "npm run rebuild"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@manuth/eslint-plugin-typescript": "^4.0.1",
|
||||
"concurrently": "^7.6.0",
|
||||
"eslint": "^8.29.0"
|
||||
"@manuth/tsconfig": "^3.0.2",
|
||||
"@types/browser-sync": "^2.26.3",
|
||||
"@types/gulp": "^4.0.10",
|
||||
"@types/node": "^18.11.11",
|
||||
"browser-sync": "^2.27.10",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint": "^8.29.0",
|
||||
"gulp": "^4.0.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-node": "^10.9.1",
|
||||
"upath": "^2.0.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
const { join } = require("node:path");
|
||||
|
||||
module.exports = {
|
||||
env: {
|
||||
browser: true
|
||||
},
|
||||
parserOptions: {
|
||||
project: [
|
||||
join(__dirname, "app.jsconfig.json"),
|
||||
join(__dirname, "eslint.jsconfig.json"),
|
||||
join(__dirname, "gulp.tsconfig.json")
|
||||
]
|
||||
}
|
||||
};
|
|
@ -1,168 +0,0 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and *not* Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
.cache
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
# Source-files
|
||||
[Ss]rc/
|
||||
|
||||
# TypeScript config-files
|
||||
tsconfig.json
|
||||
tsconfig.*.json
|
||||
|
||||
# Lint config-files
|
||||
.eslintrc
|
||||
.eslintrc.*
|
||||
|
||||
# Source-maps
|
||||
[Ll]ib/**/*.map
|
||||
|
||||
# Unit-Tests
|
||||
.mocharc.*
|
||||
[Ll]ib/tests/
|
||||
|
||||
# Visual Studio Code-Environment
|
||||
.vscode/
|
||||
|
||||
# GitHub configuration
|
||||
.github/
|
||||
|
||||
# CI configuration
|
||||
.drone.yml
|
||||
.woodpecker.yml
|
||||
|
||||
# Build Environment
|
||||
gulp/
|
||||
gulpfile.ts
|
||||
|
||||
# Temporary release-assets
|
||||
.tagName.txt
|
||||
.tagHeading.txt
|
||||
.releaseNotes.md
|
||||
.releaseTitle.md
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"checkJs": true
|
||||
},
|
||||
"include": [
|
||||
"./.eslintrc.cjs"
|
||||
]
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
{
|
||||
"name": "connect-force",
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"description": "A selfmade Connect Four game.",
|
||||
"author": "Manuel Thalmann <m@nuth.ch>",
|
||||
"scripts": {
|
||||
"gulp": "cross-env NODE_OPTIONS=\"--loader ts-node/esm\" gulp --",
|
||||
"build": "npm run gulp Build",
|
||||
"rebuild": "npm run clean && npm run build",
|
||||
"watch": "npm run gulp Watch",
|
||||
"clean": "rimraf ./lib",
|
||||
"lint": "eslint --max-warnings 0 ./src .eslintrc.cjs",
|
||||
"lint-ide": "npm run lint || exit 0",
|
||||
"prepare": "npm run rebuild"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@manuth/eslint-plugin-typescript": "^4.0.1",
|
||||
"@manuth/tsconfig": "^3.0.2",
|
||||
"@types/browser-sync": "^2.26.3",
|
||||
"@types/gulp": "^4.0.10",
|
||||
"@types/node": "^18.11.11",
|
||||
"browser-sync": "^2.27.10",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint": "^8.29.0",
|
||||
"gulp": "^4.0.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-node": "^10.9.1",
|
||||
"upath": "^2.0.1"
|
||||
}
|
||||
}
|
|
@ -1,150 +0,0 @@
|
|||
import { Game } from "./Game.js";
|
||||
|
||||
/**
|
||||
* The game that is being played.
|
||||
*
|
||||
* @type {Game}
|
||||
*/
|
||||
let game;
|
||||
|
||||
/**
|
||||
* A value indicating whether a transfer is pending.
|
||||
*/
|
||||
let transferPending = false;
|
||||
|
||||
/**
|
||||
* The id of the save game.
|
||||
*/
|
||||
let id = "";
|
||||
|
||||
/**
|
||||
* Gets the save button.
|
||||
*
|
||||
* @returns {HTMLButtonElement}
|
||||
* The save button.
|
||||
*/
|
||||
function getSaveButton()
|
||||
{
|
||||
return document.querySelector(".save");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the load button.
|
||||
*
|
||||
* @returns {HTMLButtonElement}
|
||||
* The load button.
|
||||
*/
|
||||
function getLoadButton()
|
||||
{
|
||||
return document.querySelector(".load");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an url for storing and loading the save game.
|
||||
*
|
||||
* @returns {URL}
|
||||
* The url for storing and loading the save game.
|
||||
*/
|
||||
function getUrl()
|
||||
{
|
||||
let result = new URL(
|
||||
id,
|
||||
new URL(
|
||||
"/api/data/",
|
||||
window.location.origin));
|
||||
|
||||
result.searchParams.append("token", "c4game");
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the board.
|
||||
*/
|
||||
function initialize()
|
||||
{
|
||||
game = new Game("game");
|
||||
game.initialize();
|
||||
|
||||
(/** @type {HTMLElement} */ (document.querySelector(".new-game"))).onclick = (event) =>
|
||||
{
|
||||
event.preventDefault();
|
||||
game.reset();
|
||||
};
|
||||
|
||||
getSaveButton().onclick = async () =>
|
||||
{
|
||||
if (!transferPending)
|
||||
{
|
||||
transferPending = true;
|
||||
getSaveButton().disabled = true;
|
||||
getLoadButton().disabled = true;
|
||||
|
||||
try
|
||||
{
|
||||
if (id === "")
|
||||
{
|
||||
let result = await (await fetch(
|
||||
getUrl(),
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-type": "application/json"
|
||||
},
|
||||
body: JSON.stringify(game.dump())
|
||||
})).json();
|
||||
|
||||
({ id } = result);
|
||||
}
|
||||
else
|
||||
{
|
||||
await fetch(
|
||||
getUrl(),
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-type": "application/json"
|
||||
},
|
||||
body: JSON.stringify(game.dump())
|
||||
});
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
getSaveButton().disabled = false;
|
||||
getLoadButton().disabled = false;
|
||||
transferPending = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log("Already busy");
|
||||
}
|
||||
};
|
||||
|
||||
getLoadButton().onclick = async () =>
|
||||
{
|
||||
if (!transferPending)
|
||||
{
|
||||
transferPending = true;
|
||||
getSaveButton().disabled = true;
|
||||
getLoadButton().disabled = true;
|
||||
|
||||
try
|
||||
{
|
||||
game.load(
|
||||
await (
|
||||
await fetch(getUrl())).json());
|
||||
}
|
||||
catch { }
|
||||
|
||||
getSaveButton().disabled = false;
|
||||
getLoadButton().disabled = false;
|
||||
transferPending = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log("Already busy");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
initialize();
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"extends": "../../tsconfig.base.json"
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.base.json",
|
||||
"references": [
|
||||
{
|
||||
"path": "./app.jsconfig.json"
|
||||
},
|
||||
{
|
||||
"path": "./eslint.jsconfig.json"
|
||||
},
|
||||
{
|
||||
"path": "./gulp.tsconfig.json"
|
||||
}
|
||||
],
|
||||
"include": []
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
const { join } = require("node:path");
|
||||
|
||||
module.exports = {
|
||||
env: {
|
||||
browser: true
|
||||
},
|
||||
parserOptions: {
|
||||
project: [
|
||||
join(__dirname, "app.jsconfig.json"),
|
||||
join(__dirname, "eslint.jsconfig.json")
|
||||
]
|
||||
}
|
||||
};
|
|
@ -1,168 +0,0 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and *not* Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
.cache
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
# Source-files
|
||||
[Ss]rc/
|
||||
|
||||
# TypeScript config-files
|
||||
tsconfig.json
|
||||
tsconfig.*.json
|
||||
|
||||
# Lint config-files
|
||||
.eslintrc
|
||||
.eslintrc.*
|
||||
|
||||
# Source-maps
|
||||
[Ll]ib/**/*.map
|
||||
|
||||
# Unit-Tests
|
||||
.mocharc.*
|
||||
[Ll]ib/tests/
|
||||
|
||||
# Visual Studio Code-Environment
|
||||
.vscode/
|
||||
|
||||
# GitHub configuration
|
||||
.github/
|
||||
|
||||
# CI configuration
|
||||
.drone.yml
|
||||
.woodpecker.yml
|
||||
|
||||
# Build Environment
|
||||
gulp/
|
||||
gulpfile.ts
|
||||
|
||||
# Temporary release-assets
|
||||
.tagName.txt
|
||||
.tagHeading.txt
|
||||
.releaseNotes.md
|
||||
.releaseTitle.md
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"composite": true
|
||||
},
|
||||
"include": [
|
||||
"./src/**/*"
|
||||
]
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"checkJs": true
|
||||
},
|
||||
"include": [
|
||||
"./.eslintrc.cjs"
|
||||
]
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
{
|
||||
"name": "connect-force-server",
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"description": "A server for Storing ConnectForce Savegames",
|
||||
"author": "Manuel Thalmann <m@nuth.ch>",
|
||||
"scripts": {
|
||||
"start": "noderel -e ./src/main.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"express": "^4.18.2",
|
||||
"randexp": "^0.5.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.17.15",
|
||||
"@types/node": "^18.11.15",
|
||||
"noderel": "^1.0.13"
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
/**
|
||||
* Represents an http error.
|
||||
*/
|
||||
export class HTTPError extends Error
|
||||
{
|
||||
/**
|
||||
* The http status code.
|
||||
*
|
||||
* @type {number}
|
||||
*/
|
||||
status;
|
||||
|
||||
/**
|
||||
* Initializes a new instance of the {@link HTTPError `HTTPError`} class.
|
||||
*
|
||||
* @param {number} status
|
||||
* The http status code.
|
||||
*
|
||||
* @param {string} message
|
||||
* The error message.
|
||||
*/
|
||||
constructor(status, message)
|
||||
{
|
||||
super(message);
|
||||
this.status = status;
|
||||
}
|
||||
}
|
|
@ -1,150 +0,0 @@
|
|||
import { join } from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import express from "express";
|
||||
import RandExp from "randexp";
|
||||
import { HTTPError } from "./HTTPError.js";
|
||||
|
||||
const { randexp } = RandExp;
|
||||
|
||||
const dirname = fileURLToPath(new URL(".", import.meta.url));
|
||||
const app = express();
|
||||
|
||||
const apiKeys = [
|
||||
"c4game"
|
||||
];
|
||||
|
||||
const dataPath = "/api/data";
|
||||
const parametrizedDataPath = "/api/data/:id";
|
||||
|
||||
/**
|
||||
* The data provided by the api.
|
||||
*
|
||||
* @type {Record<string, unknown>}
|
||||
*/
|
||||
let data = {};
|
||||
|
||||
/**
|
||||
* Creates a new guid.
|
||||
*
|
||||
* @returns {string}
|
||||
* The newly created guid.
|
||||
*/
|
||||
function createGuid()
|
||||
{
|
||||
return randexp(/[0-9a-f]{8}(-[0-9a-f]{4}){4}[0-9a-f]{8}/);
|
||||
}
|
||||
|
||||
app.use(express.static(join(dirname, "..", "..", "game", "lib", "static")));
|
||||
app.use("/api", express.json());
|
||||
|
||||
app.use(
|
||||
"/api",
|
||||
(request, response, next) =>
|
||||
{
|
||||
const keyParam = "token";
|
||||
|
||||
if (keyParam in request.query)
|
||||
{
|
||||
let key = request.query[keyParam];
|
||||
|
||||
if (typeof key === "string" && apiKeys.includes(key))
|
||||
{
|
||||
next();
|
||||
}
|
||||
else
|
||||
{
|
||||
next(new HTTPError(401, "The specified API token is invalid"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
next(new HTTPError(401, "An API token is required"));
|
||||
}
|
||||
});
|
||||
|
||||
app.get(
|
||||
parametrizedDataPath,
|
||||
(request, response, next) =>
|
||||
{
|
||||
let id = request.params.id;
|
||||
console.log(`Data ID \`${id}\` requested`);
|
||||
|
||||
if (id in data)
|
||||
{
|
||||
response.send(data[id]);
|
||||
}
|
||||
else
|
||||
{
|
||||
next();
|
||||
}
|
||||
});
|
||||
|
||||
app.post(
|
||||
dataPath,
|
||||
(request, response, next) =>
|
||||
{
|
||||
let id = createGuid();
|
||||
data[id] = request.body;
|
||||
response.send({ id });
|
||||
});
|
||||
|
||||
app.put(
|
||||
parametrizedDataPath,
|
||||
(request, response, next) =>
|
||||
{
|
||||
let id = request.params.id;
|
||||
|
||||
if (id in data)
|
||||
{
|
||||
data[id] = request.body;
|
||||
response.send(data[id]);
|
||||
}
|
||||
else
|
||||
{
|
||||
next();
|
||||
}
|
||||
});
|
||||
|
||||
app.delete(
|
||||
parametrizedDataPath,
|
||||
(request, response, next) =>
|
||||
{
|
||||
let id = request.params.id;
|
||||
|
||||
if (id in data)
|
||||
{
|
||||
delete data[id];
|
||||
response.send();
|
||||
response.status(204);
|
||||
}
|
||||
else
|
||||
{
|
||||
next();
|
||||
}
|
||||
});
|
||||
|
||||
app.use(
|
||||
[
|
||||
(error, request, response, next) =>
|
||||
{
|
||||
response.send(`${error}`);
|
||||
response.status(error instanceof HTTPError ? error.status : 500);
|
||||
}
|
||||
]);
|
||||
|
||||
app.use(
|
||||
"/api",
|
||||
(request, response) =>
|
||||
{
|
||||
response.send({ error: "Not Found" });
|
||||
response.status(404);
|
||||
});
|
||||
|
||||
app.use(
|
||||
(request, response) =>
|
||||
{
|
||||
response.send("Not Found");
|
||||
response.status(404);
|
||||
});
|
||||
|
||||
app.listen(1337);
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"extends": "../../tsconfig.base.json"
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.base.json",
|
||||
"references": [
|
||||
{
|
||||
"path": "./app.jsconfig.json"
|
||||
},
|
||||
{
|
||||
"path": "./eslint.jsconfig.json"
|
||||
}
|
||||
],
|
||||
"include": []
|
||||
}
|
61
src/js/main.js
Normal file
61
src/js/main.js
Normal file
|
@ -0,0 +1,61 @@
|
|||
import { Game } from "./Game.js";
|
||||
|
||||
/**
|
||||
* The game that is being played.
|
||||
*
|
||||
* @type {Game}
|
||||
*/
|
||||
let game;
|
||||
|
||||
const saveGameKey = "connect-force-save";
|
||||
|
||||
/**
|
||||
* Gets the save button.
|
||||
*
|
||||
* @returns {HTMLButtonElement}
|
||||
* The save button.
|
||||
*/
|
||||
function getSaveButton()
|
||||
{
|
||||
return document.querySelector(".save");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the load button.
|
||||
*
|
||||
* @returns {HTMLButtonElement}
|
||||
* The load button.
|
||||
*/
|
||||
function getLoadButton()
|
||||
{
|
||||
return document.querySelector(".load");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the board.
|
||||
*/
|
||||
function initialize()
|
||||
{
|
||||
game = new Game("game");
|
||||
game.initialize();
|
||||
|
||||
(/** @type {HTMLElement} */ (document.querySelector(".new-game"))).onclick = (event) =>
|
||||
{
|
||||
event.preventDefault();
|
||||
game.reset();
|
||||
};
|
||||
|
||||
getSaveButton().onclick = async (event) =>
|
||||
{
|
||||
event.preventDefault();
|
||||
localStorage.setItem(saveGameKey, JSON.stringify(game.dump()));
|
||||
};
|
||||
|
||||
getLoadButton().onclick = async (event) =>
|
||||
{
|
||||
event.preventDefault();
|
||||
game.load(JSON.parse(localStorage.getItem(saveGameKey)));
|
||||
};
|
||||
}
|
||||
|
||||
initialize();
|
|
@ -1,11 +1,14 @@
|
|||
{
|
||||
"extends": "./tsconfig.base.json",
|
||||
"references": [
|
||||
{
|
||||
"path": "./app.jsconfig.json"
|
||||
},
|
||||
{
|
||||
"path": "./eslint.jsconfig.json"
|
||||
},
|
||||
{
|
||||
"path": "./packages/game"
|
||||
"path": "./gulp.tsconfig.json"
|
||||
}
|
||||
],
|
||||
"include": []
|
||||
|
|
Loading…
Reference in a new issue