From e6e3a383281a239c2f5b7ea0c85147ea83fe3e85 Mon Sep 17 00:00:00 2001 From: Pabloader Date: Sat, 6 Jul 2024 17:26:15 +0000 Subject: [PATCH] Refactor no single games monorepo, add building & deploy --- bun.lockb | Bin 11251 -> 30054 bytes package.json | 7 ++- src/assets/index.html | 11 +---- src/build/build.ts | 34 +++++++++++++ src/{ => build}/dataUrlPlugin.ts | 0 src/build/html.ts | 32 +++++++++++++ src/build/isGame.ts | 25 ++++++++++ src/build/server.ts | 35 ++++++++++++++ src/{ => games/binario}/assets/img/and.png | Bin .../binario}/assets/img/conveyor.png | Bin src/{ => games/binario}/assets/img/empty.png | Bin .../binario}/assets/img/extractor.png | Bin src/{ => games/binario}/assets/img/not.png | Bin src/{ => games/binario}/assets/img/or.png | Bin src/{ => games/binario}/assets/img/select.png | Bin src/{ => games/binario}/assets/img/trash.png | Bin src/{ => games/binario}/assets/ui.module.css | 7 +++ src/{game => games/binario}/game.ts | 9 ++-- src/{game => games/binario}/graphics.ts | 0 src/{game => games/binario}/renderer.ts | 10 ++-- src/{game => games/binario}/ui.tsx | 19 +++++--- src/{game => games/binario}/utils.ts | 0 src/{game => games/binario}/world.ts | 0 src/games/index/game.module.css | 11 +++++ src/games/index/game.tsx | 17 +++++++ src/index.ts | 15 +++--- src/server.ts | 45 ------------------ src/types.d.ts | 8 ++++ 28 files changed, 206 insertions(+), 79 deletions(-) create mode 100644 src/build/build.ts rename src/{ => build}/dataUrlPlugin.ts (100%) create mode 100644 src/build/html.ts create mode 100644 src/build/isGame.ts create mode 100644 src/build/server.ts rename src/{ => games/binario}/assets/img/and.png (100%) rename src/{ => games/binario}/assets/img/conveyor.png (100%) rename src/{ => games/binario}/assets/img/empty.png (100%) rename src/{ => games/binario}/assets/img/extractor.png (100%) rename src/{ => games/binario}/assets/img/not.png (100%) rename src/{ => games/binario}/assets/img/or.png (100%) rename src/{ => games/binario}/assets/img/select.png (100%) rename src/{ => games/binario}/assets/img/trash.png (100%) rename src/{ => games/binario}/assets/ui.module.css (85%) rename src/{game => games/binario}/game.ts (96%) rename src/{game => games/binario}/graphics.ts (100%) rename src/{game => games/binario}/renderer.ts (95%) rename src/{game => games/binario}/ui.tsx (83%) rename src/{game => games/binario}/utils.ts (100%) rename src/{game => games/binario}/world.ts (100%) create mode 100644 src/games/index/game.module.css create mode 100644 src/games/index/game.tsx delete mode 100644 src/server.ts diff --git a/bun.lockb b/bun.lockb index 91b0e3bb2b586aba724705662db05e34858bbc9b..d97726d0f59972a999dd4bf256af65cad8d5fbab 100755 GIT binary patch literal 30054 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 diff --git a/package.json b/package.json index 280514a..14d1839 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,10 @@ { - "name": "binario", + "name": "tsgames", "module": "index.ts", "type": "module", "scripts": { - "start": "bun --hot src/server.ts" + "start": "bun --hot src/build/server.ts", + "build": "bun src/build/build.ts" }, "dependencies": { "classnames": "2.5.1", @@ -11,7 +12,9 @@ }, "devDependencies": { "@types/bun": "latest", + "@types/inquirer": "9.0.7", "bun-lightningcss": "0.2.0", + "inquirer": "9.3.4", "typescript": "5.5.2" } } \ No newline at end of file diff --git a/src/assets/index.html b/src/assets/index.html index 983cdce..59becd0 100644 --- a/src/assets/index.html +++ b/src/assets/index.html @@ -3,14 +3,8 @@ - Binario + $TITLE$ - -
+ $SCRIPT$ \ No newline at end of file diff --git a/src/build/build.ts b/src/build/build.ts new file mode 100644 index 0000000..6006b11 --- /dev/null +++ b/src/build/build.ts @@ -0,0 +1,34 @@ +import { $ } from 'bun'; + +import path from 'path'; +import fs from 'fs/promises'; +import { buildHTML } from "./html"; +import inquirer from 'inquirer'; +import { isGame, getGames } from './isGame'; + +const outDir = path.resolve(import.meta.dir, '..', '..', 'dist'); +await fs.mkdir(outDir, { recursive: true }); + +let game = process.argv[2]; + +while (!await isGame(game)) { + const answer = await inquirer.prompt([{ + type: 'list', + name: 'game', + choices: await getGames(), + }]); + game = answer.game; +} + +const html = await buildHTML(game, true); + +if (!html) { + process.exit(1); +} +const filePath = path.resolve(outDir, `${game}.html`); +await Bun.write(filePath, html); + +const result = await $`scp "${filePath}" "pabloid@games.pafnooty.ru:/var/www/games/${game}.html"`; +if (result.exitCode === 0) { + console.log(`Build successful: https://games.pafnooty.ru/${game}.html`); +} \ No newline at end of file diff --git a/src/dataUrlPlugin.ts b/src/build/dataUrlPlugin.ts similarity index 100% rename from src/dataUrlPlugin.ts rename to src/build/dataUrlPlugin.ts diff --git a/src/build/html.ts b/src/build/html.ts new file mode 100644 index 0000000..6dc39f6 --- /dev/null +++ b/src/build/html.ts @@ -0,0 +1,32 @@ +import path from 'path'; + +import dataUrlPlugin from './dataUrlPlugin'; +import lightningcss from 'bun-lightningcss'; +import { getGames } from './isGame'; + +export async function buildHTML(game: string, production = false) { + const html = await Bun.file(path.resolve(import.meta.dir, '..', 'assets', 'index.html')).text(); + const bundle = await Bun.build({ + entrypoints: [path.resolve(import.meta.dir, '..', 'index.ts')], + sourcemap: production ? 'none' : 'inline', + minify: production, + define: { + global: 'window', + GAME: `"${game}"`, + GAMES: JSON.stringify(await getGames()), + }, + plugins: [ + dataUrlPlugin, + lightningcss(), + ] + }); + + if (bundle.success && bundle.outputs.length === 1) { + const script = await bundle.outputs[0].text(); + return html + .replace('$SCRIPT$', ``) + .replace('$TITLE$', game[0].toUpperCase() + game.slice(1).toLowerCase()); + } else { + console.error('Multiple assets: ', bundle.outputs, 'or fail: ', !bundle.success, bundle); + } +} \ No newline at end of file diff --git a/src/build/isGame.ts b/src/build/isGame.ts new file mode 100644 index 0000000..081d277 --- /dev/null +++ b/src/build/isGame.ts @@ -0,0 +1,25 @@ +import path from 'path'; +import fs from 'fs/promises'; + +export async function isGame(name: string | null | undefined) { + if (!name || name === 'index') return false; + + const dir = path.resolve(import.meta.dir, '..', 'games', name); + + if (!await fs.exists(dir)) return false; + + const stat = await fs.stat(dir); + + return stat.isDirectory(); +} + +export async function getGames() { + const dir = path.resolve(import.meta.dir, '..', 'games'); + if (!await fs.exists(dir)) return []; + + const stat = await fs.stat(dir); + if (!stat.isDirectory()) return []; + + const list = await fs.readdir(dir); + return list.filter(d => d !== 'index'); +} \ No newline at end of file diff --git a/src/build/server.ts b/src/build/server.ts new file mode 100644 index 0000000..d5329d2 --- /dev/null +++ b/src/build/server.ts @@ -0,0 +1,35 @@ +import Bun from 'bun'; +import path from 'path'; +import { buildHTML } from './html'; +import { isGame } from './isGame'; + +Bun.serve({ + async fetch(req) { + const url = new URL(req.url); + const pathname = path.basename(url.pathname); + const gameParam = url.searchParams.get('game'); + const game = (gameParam && await isGame(gameParam)) ? gameParam : 'index'; + + switch (pathname) { + case '': + case '/': + case 'index.html': + try { + const html = await buildHTML(game); + if (html) { + return new Response(html, { + headers: { + 'Content-Type': 'text/html;charset=utf-8' + } + }); + } + } catch (e) { + console.error(e); + } + return new Response(null, { status: 500 }); + default: + console.log(`Pathname: ${pathname}`); + return new Response(null, { status: 404 }); + } + } +}) \ No newline at end of file diff --git a/src/assets/img/and.png b/src/games/binario/assets/img/and.png similarity index 100% rename from src/assets/img/and.png rename to src/games/binario/assets/img/and.png diff --git a/src/assets/img/conveyor.png b/src/games/binario/assets/img/conveyor.png similarity index 100% rename from src/assets/img/conveyor.png rename to src/games/binario/assets/img/conveyor.png diff --git a/src/assets/img/empty.png b/src/games/binario/assets/img/empty.png similarity index 100% rename from src/assets/img/empty.png rename to src/games/binario/assets/img/empty.png diff --git a/src/assets/img/extractor.png b/src/games/binario/assets/img/extractor.png similarity index 100% rename from src/assets/img/extractor.png rename to src/games/binario/assets/img/extractor.png diff --git a/src/assets/img/not.png b/src/games/binario/assets/img/not.png similarity index 100% rename from src/assets/img/not.png rename to src/games/binario/assets/img/not.png diff --git a/src/assets/img/or.png b/src/games/binario/assets/img/or.png similarity index 100% rename from src/assets/img/or.png rename to src/games/binario/assets/img/or.png diff --git a/src/assets/img/select.png b/src/games/binario/assets/img/select.png similarity index 100% rename from src/assets/img/select.png rename to src/games/binario/assets/img/select.png diff --git a/src/assets/img/trash.png b/src/games/binario/assets/img/trash.png similarity index 100% rename from src/assets/img/trash.png rename to src/games/binario/assets/img/trash.png diff --git a/src/assets/ui.module.css b/src/games/binario/assets/ui.module.css similarity index 85% rename from src/assets/ui.module.css rename to src/games/binario/assets/ui.module.css index d2f0655..21abc5c 100644 --- a/src/assets/ui.module.css +++ b/src/games/binario/assets/ui.module.css @@ -1,3 +1,10 @@ +:root { + --slot-size: 64px; + --color-bg-select: rgba(0, 0, 0, 0.1); + --color-bg-select: rgba(0, 200, 0, 0.1); + --color-border-select: rgb(0, 200, 0); +} + .button { display: flex; justify-content: center; diff --git a/src/game/game.ts b/src/games/binario/game.ts similarity index 96% rename from src/game/game.ts rename to src/games/binario/game.ts index ac74e98..c095ba6 100644 --- a/src/game/game.ts +++ b/src/games/binario/game.ts @@ -3,7 +3,7 @@ import UI from "./ui"; import World from "./world"; import { pointsEquals, prevent } from "./utils"; -export default class Game { +export default class Binario implements IGame { private running = false; private mouseDown: false | number = false; private graphics; @@ -13,8 +13,7 @@ export default class Game { private prevFrame: number = performance.now(); private paused = false; - constructor(private canvas: HTMLCanvasElement, controls: HTMLElement) { - + constructor(private canvas: HTMLCanvasElement) { canvas.focus(); canvas.addEventListener('wheel', this.onScroll); @@ -28,7 +27,7 @@ export default class Game { this.graphics = new Graphics(canvas); this.world = new World(); - this.ui = new UI(controls); + this.ui = new UI(); window.addEventListener('resize', this.onResize); this.onResize(); @@ -38,7 +37,7 @@ export default class Game { private onResize = () => { this.canvas.width = window.innerWidth; this.canvas.height = window.innerHeight; - + this.graphics.resetStyle(); } diff --git a/src/game/graphics.ts b/src/games/binario/graphics.ts similarity index 100% rename from src/game/graphics.ts rename to src/games/binario/graphics.ts diff --git a/src/game/renderer.ts b/src/games/binario/renderer.ts similarity index 95% rename from src/game/renderer.ts rename to src/games/binario/renderer.ts index 7f30f83..6e64aa6 100644 --- a/src/game/renderer.ts +++ b/src/games/binario/renderer.ts @@ -2,11 +2,11 @@ import { type Tile, TileType, getPortDirections, PortDirection, LIMITS, type Res import { ALL_DIRECTIONS, Direction, makeImage, movePoint } from "./utils"; -import emptySrc from '../assets/img/empty.png'; -import extractorSrc from '../assets/img/extractor.png'; -import notSrc from '../assets/img/not.png'; -import andSrc from '../assets/img/and.png'; -import orSrc from '../assets/img/or.png'; +import emptySrc from './assets/img/empty.png'; +import extractorSrc from './assets/img/extractor.png'; +import notSrc from './assets/img/not.png'; +import andSrc from './assets/img/and.png'; +import orSrc from './assets/img/or.png'; export interface ViewConfig { tileSize: number; diff --git a/src/game/ui.tsx b/src/games/binario/ui.tsx similarity index 83% rename from src/game/ui.tsx rename to src/games/binario/ui.tsx index 132437b..1ddbdb5 100644 --- a/src/game/ui.tsx +++ b/src/games/binario/ui.tsx @@ -3,12 +3,12 @@ import cn from 'classnames'; import { range } from './utils'; import { TileType } from './world'; -import styles from '../assets/ui.module.css'; -import conveyorSrc from '../assets/img/conveyor.png'; -import extractorSrc from '../assets/img/extractor.png'; -import notSrc from '../assets/img/not.png'; -import andSrc from '../assets/img/and.png'; -import orSrc from '../assets/img/or.png'; +import styles from './assets/ui.module.css'; +import conveyorSrc from './assets/img/conveyor.png'; +import extractorSrc from './assets/img/extractor.png'; +import notSrc from './assets/img/not.png'; +import andSrc from './assets/img/and.png'; +import orSrc from './assets/img/or.png'; export enum ToolType { SELECT, @@ -64,9 +64,14 @@ const TOOLS: (Tool | null)[] = [ ]; export default class UI { + private root: HTMLElement; private currentTool: Tool = TOOLS[0]!; - constructor(private root: HTMLElement) { + constructor() { + this.root = document.createElement('div'); + this.root.id = 'controls'; + document.body.appendChild(this.root); + this.render(); } diff --git a/src/game/utils.ts b/src/games/binario/utils.ts similarity index 100% rename from src/game/utils.ts rename to src/games/binario/utils.ts diff --git a/src/game/world.ts b/src/games/binario/world.ts similarity index 100% rename from src/game/world.ts rename to src/games/binario/world.ts diff --git a/src/games/index/game.module.css b/src/games/index/game.module.css new file mode 100644 index 0000000..25f0caa --- /dev/null +++ b/src/games/index/game.module.css @@ -0,0 +1,11 @@ +body { + display: flex; +} + +.games { + display: flex; + flex-direction: column; + width: 100%; + padding: 40px 20%; + gap: 20px; +} \ No newline at end of file diff --git a/src/games/index/game.tsx b/src/games/index/game.tsx new file mode 100644 index 0000000..bea619d --- /dev/null +++ b/src/games/index/game.tsx @@ -0,0 +1,17 @@ +import { render } from "preact"; +import styles from './game.module.css'; + +declare const GAMES: string[]; + +export default class GameIndex implements IGame { + constructor(canvas: HTMLCanvasElement) { + canvas.remove(); + } + run() { + const root =
+ {GAMES.map(g => {g})} +
; + + render(root, document.body); + } +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 9e3cc92..440fc5e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,14 +1,17 @@ -import Game from './game/game'; +declare const GAME: string; async function main() { - const canvas = document.getElementById('c'); - const controls = document.getElementById('controls'); - if (canvas instanceof HTMLCanvasElement && controls instanceof HTMLElement) { - const game = new Game(canvas, controls); + const { default: Game }: { default: IGameConstructor } = await import(`./games/${GAME}/game`); + const canvas = document.getElementById('canvas'); + if (canvas instanceof HTMLCanvasElement) { + const game = new Game(canvas); game.run(); } else { alert('Something wrong with your canvas!'); } } -main().catch(console.error); \ No newline at end of file +main().catch((e) => { + console.error(e); + // TODO display error page +}); \ No newline at end of file diff --git a/src/server.ts b/src/server.ts deleted file mode 100644 index edbbe4d..0000000 --- a/src/server.ts +++ /dev/null @@ -1,45 +0,0 @@ -import Bun from 'bun'; -import path from 'path'; - -import dataUrlPlugin from './dataUrlPlugin'; -import lightningcss from 'bun-lightningcss' - -Bun.serve({ - async fetch(req) { - const url = new URL(req.url); - const pathname = path.basename(url.pathname); - switch (pathname) { - case '': - case '/': - case 'index.html': - const html = await Bun.file(path.resolve(import.meta.dir, 'assets', 'index.html')).text(); - const bundle = await Bun.build({ - entrypoints: [path.resolve(import.meta.dir, 'index.ts')], - sourcemap: 'inline', - // minify: true, - define: { - global: 'window', - }, - plugins: [ - dataUrlPlugin, - lightningcss(), - ] - }); - - if (bundle.success && bundle.outputs.length === 1) { - const script = await bundle.outputs[0].text(); - return new Response(html.replace('$SCRIPT$', ``), { - headers: { - 'Content-Type': 'text/html;charset=utf-8' - } - }); - } else { - console.error('Multiple assets: ', bundle.outputs, 'or fail: ', !bundle.success, bundle); - } - return new Response(null, { status: 500 }); - default: - console.log(`Pathname: ${pathname}`); - return new Response(null, { status: 404 }); - } - } -}) \ No newline at end of file diff --git a/src/types.d.ts b/src/types.d.ts index 536d762..6ffa60f 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -1,6 +1,14 @@ type Point = [number, number]; type Rect = [number, number, number, number]; +interface IGame { + run(); +} + +interface IGameConstructor { + new(canvas: HTMLCanvasElement): IGame; +} + declare module "*.png" { const content: string; export default content;