@gamedevland/vite 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/LICENSE +16 -18
- package/README.md +20 -2
- package/dist/cli/GamedevlandCli.js +9 -2
- package/dist/project/ProjectCreator.d.ts +13 -0
- package/dist/project/ProjectCreator.js +65 -0
- package/package.json +14 -4
- package/templates/empty/.env.crazygames +1 -0
- package/templates/empty/AGENTS.md +10 -0
- package/templates/empty/README.md +24 -0
- package/templates/empty/eslint.config.js +8 -0
- package/templates/empty/game/assets/json/configs/audio/sounds-volumes.json +1 -0
- package/templates/empty/game/assets/json/layouts/scenes/main/layout.json +1 -0
- package/templates/empty/game/index.html +18 -0
- package/templates/empty/game/src/config/GameConfiguration.ts +29 -0
- package/templates/empty/game/src/config/ProjectDi.ts +8 -0
- package/templates/empty/game/src/config/ProjectGlobalDi.ts +12 -0
- package/templates/empty/game/src/main.ts +4 -0
- package/templates/empty/game/src/scenes/main/MainScene.ts +3 -0
- package/templates/empty/game/src/scenes/main/MainSceneDefinition.ts +10 -0
- package/templates/empty/game/src/scenes/main/MainSceneDi.ts +7 -0
- package/templates/empty/gitignore +4 -0
- package/templates/empty/package.json +22 -0
- package/templates/empty/tsconfig.json +10 -0
- package/templates/empty/vite.config.ts +7 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.0 — 2026-11-07
|
|
4
|
+
|
|
5
|
+
- Add `gamedevland create <directory>` to generate a blank SDK consumer project and install
|
|
6
|
+
its dependencies, with `--no-install` for offline/custom installation and `--name` for
|
|
7
|
+
an explicit npm package name.
|
|
8
|
+
- Ship the template inside the npm package: strict TypeScript, Vite, ESLint, an empty
|
|
9
|
+
FSM scene with DI/layout registration, manifest-based JSON assets, and audio volume config.
|
|
10
|
+
- Include web and CrazyGames development/build scripts with relative asset paths.
|
|
11
|
+
- Reject nonempty destinations, symlink destinations and invalid names; never overwrite
|
|
12
|
+
existing project files. Invoke dependency installation without interpolating user paths.
|
|
13
|
+
- Update the engine dependency to 0.0.11 and test generated project structure and CLI behavior.
|
|
14
|
+
|
|
15
|
+
## 0.1.2 — 2026-11-04
|
|
16
|
+
|
|
17
|
+
- Release the package and its source under MIT.
|
|
18
|
+
- Add public source, issue tracker and package-directory metadata.
|
|
19
|
+
- Depend on the MIT-licensed engine 0.0.8 release.
|
|
20
|
+
- Make the README configuration example work in native ESM.
|
|
21
|
+
|
|
22
|
+
## 0.1.1 (withdrawn)
|
|
23
|
+
|
|
24
|
+
- Publication withdrawn; this version must not be reused.
|
|
25
|
+
|
|
3
26
|
## 0.1.0
|
|
4
27
|
|
|
5
28
|
- Add the `gamedevland poki pack` and `gamedevland poki upload` CLI commands.
|
|
@@ -8,3 +31,19 @@
|
|
|
8
31
|
- Use the official pinned Poki CLI, per-game private credentials or `POKI_UPLOAD_TOKEN`, and verified upload receipts.
|
|
9
32
|
- Keep authentication out of check/build subprocesses and reject source maps, private files, symlinks and leaked upload tokens in build output.
|
|
10
33
|
- Preserve existing Vite configuration exports and browser SDK injection.
|
|
34
|
+
|
|
35
|
+
## 0.0.4
|
|
36
|
+
|
|
37
|
+
- Update the engine dependency to 0.0.5.
|
|
38
|
+
|
|
39
|
+
## 0.0.3
|
|
40
|
+
|
|
41
|
+
- Update package links and the engine dependency to 0.0.4.
|
|
42
|
+
|
|
43
|
+
## 0.0.2
|
|
44
|
+
|
|
45
|
+
- Update repository metadata and the engine dependency to 0.0.3.
|
|
46
|
+
|
|
47
|
+
## 0.0.1
|
|
48
|
+
|
|
49
|
+
- First npm release of the Vite tooling.
|
package/LICENSE
CHANGED
|
@@ -1,23 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
MIT License
|
|
2
2
|
|
|
3
3
|
Copyright (c) 2026 Gamedev Land
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
6
11
|
|
|
7
|
-
|
|
8
|
-
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
9
14
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
- remove copyright, license, or package identity notices;
|
|
18
|
-
- use the package name, author name, or repository identity to imply endorsement without permission.
|
|
19
|
-
|
|
20
|
-
The SDK is provided "as is", without warranty of any kind, express or implied, including but not limited
|
|
21
|
-
to the warranties of merchantability, fitness for a particular purpose, and noninfringement. In no event
|
|
22
|
-
shall the authors or copyright holders be liable for any claim, damages, or other liability arising from
|
|
23
|
-
the SDK or its use.
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @gamedevland/vite
|
|
2
2
|
|
|
3
|
+
## Create a blank game
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
npx --yes --package @gamedevland/vite@0.2.0 gamedevland create my-game
|
|
7
|
+
cd my-game
|
|
8
|
+
npm run dev
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
When installed locally, run `npx gamedevland create my-game`. The CLI generates a
|
|
12
|
+
strict TypeScript/PixiJS project with an empty FSM scene, scene/global DI, JSON
|
|
13
|
+
layout and audio config, and web/CrazyGames build scripts. Dependencies are installed
|
|
14
|
+
by default. `--no-install` skips installation; `--name my-game` sets the npm name
|
|
15
|
+
when the destination directory has a different name. New or empty directories only;
|
|
16
|
+
nonempty directories and symlink destinations are rejected without overwriting files.
|
|
17
|
+
|
|
3
18
|
Vite build tooling for HTML5 games built with `@gamedevland/engine`.
|
|
4
19
|
|
|
5
20
|
## Install
|
|
@@ -13,12 +28,13 @@ Vite 7 or 8 must be installed in the game project.
|
|
|
13
28
|
## Usage
|
|
14
29
|
|
|
15
30
|
```ts
|
|
31
|
+
import { fileURLToPath } from 'node:url';
|
|
16
32
|
import { createGameViteConfig } from '@gamedevland/vite';
|
|
17
33
|
|
|
18
34
|
export default ({ mode }: { readonly mode: string }) =>
|
|
19
35
|
createGameViteConfig({
|
|
20
36
|
mode,
|
|
21
|
-
repoRoot:
|
|
37
|
+
repoRoot: fileURLToPath(new URL('.', import.meta.url)),
|
|
22
38
|
});
|
|
23
39
|
```
|
|
24
40
|
|
|
@@ -87,4 +103,6 @@ See the [official Poki CLI](https://github.com/poki/poki-cli). The browser runti
|
|
|
87
103
|
|
|
88
104
|
## License
|
|
89
105
|
|
|
90
|
-
|
|
106
|
+
MIT. See [LICENSE](./LICENSE). Source code and contributions: [gamedevland/sdk](https://github.com/gamedevland/sdk).
|
|
107
|
+
|
|
108
|
+
Earlier npm releases retain the license included in their respective archives. Third-party dependencies retain their own licenses.
|
|
@@ -2,19 +2,26 @@ import { parseArgs } from 'node:util';
|
|
|
2
2
|
import { PokiArchive } from '../poki/PokiArchive.js';
|
|
3
3
|
import { PokiProject } from '../poki/PokiProject.js';
|
|
4
4
|
import { PokiUpload } from '../poki/PokiUpload.js';
|
|
5
|
+
import { ProjectCreator } from '../project/ProjectCreator.js';
|
|
5
6
|
/** Public command-line interface; no dependency on a particular game layout. */
|
|
6
7
|
export class GamedevlandCli {
|
|
7
8
|
static async run(argv, cwd) {
|
|
8
9
|
const { values, positionals } = parseArgs({ args: argv, allowPositionals: true, options: {
|
|
9
10
|
help: { type: 'boolean', short: 'h' }, root: { type: 'string' },
|
|
10
11
|
name: { type: 'string' }, notes: { type: 'string' },
|
|
12
|
+
'no-install': { type: 'boolean', default: false },
|
|
11
13
|
} });
|
|
12
14
|
if (values.help || positionals.length === 0) {
|
|
13
|
-
process.stdout.write('Usage: gamedevland poki <pack|upload> [--root <project>] [--name <version>] [--notes <text>]\npack validates/packages an existing build; upload runs configured checks and a fresh build before uploading.\n');
|
|
15
|
+
process.stdout.write('Usage: gamedevland create <directory> [--name <name>] [--no-install]\n gamedevland poki <pack|upload> [--root <project>] [--name <version>] [--notes <text>]\ncreate generates a blank project and installs dependencies.\npack validates/packages an existing build; upload runs configured checks and a fresh build before uploading.\n');
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (positionals[0] === 'create' && positionals.length === 2 && positionals[1]) {
|
|
19
|
+
await ProjectCreator.create({ cwd, directory: positionals[1], install: !values['no-install'],
|
|
20
|
+
...(values.name === undefined ? {} : { name: values.name }) });
|
|
14
21
|
return;
|
|
15
22
|
}
|
|
16
23
|
if (positionals.length !== 2 || positionals[0] !== 'poki' || !['pack', 'upload'].includes(positionals[1] ?? '')) {
|
|
17
|
-
throw new Error('[gamedevland] Expected poki pack or poki upload; use --help');
|
|
24
|
+
throw new Error('[gamedevland] Expected create <directory>, poki pack or poki upload; use --help');
|
|
18
25
|
}
|
|
19
26
|
const project = PokiProject.load(values.root ?? cwd);
|
|
20
27
|
if (positionals[1] === 'pack') {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
interface CreateProjectOptions {
|
|
2
|
+
readonly cwd: string;
|
|
3
|
+
readonly directory: string;
|
|
4
|
+
readonly name?: string;
|
|
5
|
+
readonly install: boolean;
|
|
6
|
+
}
|
|
7
|
+
/** Creates a blank consumer project without overwriting existing files. */
|
|
8
|
+
export declare class ProjectCreator {
|
|
9
|
+
static create(options: CreateProjectOptions): Promise<string>;
|
|
10
|
+
private static copy;
|
|
11
|
+
private static install;
|
|
12
|
+
}
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { lstat, mkdir, readdir, readFile, writeFile } from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { SchemaDecoder as S } from '@gamedevland/engine/validation';
|
|
6
|
+
/** Creates a blank consumer project without overwriting existing files. */
|
|
7
|
+
export class ProjectCreator {
|
|
8
|
+
static async create(options) {
|
|
9
|
+
const root = path.resolve(options.cwd, options.directory);
|
|
10
|
+
const name = options.name ?? path.basename(root);
|
|
11
|
+
if (!/^[a-z0-9][a-z0-9._-]*$/.test(name) || name.length > 214) {
|
|
12
|
+
throw new Error('[create] Use a lowercase npm project name (letters, digits, dots, hyphens).');
|
|
13
|
+
}
|
|
14
|
+
const info = await lstat(root).catch((error) => {
|
|
15
|
+
if (error.code !== 'ENOENT')
|
|
16
|
+
throw error;
|
|
17
|
+
return undefined;
|
|
18
|
+
});
|
|
19
|
+
if (info && (!info.isDirectory() || info.isSymbolicLink() || (await readdir(root)).length > 0)) {
|
|
20
|
+
throw new Error('[create] Destination must be a new or empty directory. Existing files are never overwritten.');
|
|
21
|
+
}
|
|
22
|
+
const pkg = S.decode(JSON.parse(await readFile(new URL('../../package.json', import.meta.url), 'utf8')), S.object({ version: S.string({ nonEmpty: true }), dependencies: S.object({
|
|
23
|
+
'@gamedevland/engine': S.string({ nonEmpty: true }),
|
|
24
|
+
}) }), 'tooling/package.json');
|
|
25
|
+
const replacements = new Map([
|
|
26
|
+
['__PROJECT_NAME__', name], ['__ENGINE_VERSION__', pkg.dependencies['@gamedevland/engine']],
|
|
27
|
+
['__TOOLING_VERSION__', pkg.version],
|
|
28
|
+
]);
|
|
29
|
+
await mkdir(root, { recursive: true });
|
|
30
|
+
await this.copy(fileURLToPath(new URL('../../templates/empty/', import.meta.url)), root, replacements);
|
|
31
|
+
if (options.install)
|
|
32
|
+
await this.install(root);
|
|
33
|
+
process.stdout.write(`[create] Created ${root}\nNext: cd ${JSON.stringify(options.directory)}${options.install ? '' : ' && npm install'} && npm run dev\n`);
|
|
34
|
+
return root;
|
|
35
|
+
}
|
|
36
|
+
static async copy(source, target, replacements) {
|
|
37
|
+
for (const entry of await readdir(source, { withFileTypes: true })) {
|
|
38
|
+
const destination = path.join(target, entry.name === 'gitignore' ? '.gitignore' : entry.name);
|
|
39
|
+
if (entry.isDirectory()) {
|
|
40
|
+
await mkdir(destination);
|
|
41
|
+
await this.copy(path.join(source, entry.name), destination, replacements);
|
|
42
|
+
}
|
|
43
|
+
else if (entry.isFile()) {
|
|
44
|
+
let content = await readFile(path.join(source, entry.name), 'utf8');
|
|
45
|
+
for (const [token, value] of replacements)
|
|
46
|
+
content = content.replaceAll(token, value);
|
|
47
|
+
await writeFile(destination, content, { flag: 'wx' });
|
|
48
|
+
}
|
|
49
|
+
else
|
|
50
|
+
throw new Error('[create] Invalid template entry');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
static async install(root) {
|
|
54
|
+
const npmEntry = process.env.npm_execpath;
|
|
55
|
+
const command = npmEntry ? process.execPath : 'npm';
|
|
56
|
+
const args = npmEntry ? [npmEntry, 'install'] : ['install'];
|
|
57
|
+
await new Promise((resolve, reject) => {
|
|
58
|
+
const child = spawn(command, args, { cwd: root, stdio: 'inherit',
|
|
59
|
+
shell: process.platform === 'win32' && !npmEntry });
|
|
60
|
+
child.once('error', reject);
|
|
61
|
+
child.once('close', (code) => code === 0 ? resolve()
|
|
62
|
+
: reject(new Error('[create] Dependency installation failed; retry npm install in the generated directory.')));
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gamedevland/vite",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Vite build tooling for Gamedev Land HTML5 games.",
|
|
6
|
-
"license": "
|
|
6
|
+
"license": "MIT",
|
|
7
7
|
"author": "Gamedev Land",
|
|
8
8
|
"keywords": [
|
|
9
9
|
"gamedev",
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"dist",
|
|
26
26
|
"README.md",
|
|
27
27
|
"CHANGELOG.md",
|
|
28
|
-
"LICENSE"
|
|
28
|
+
"LICENSE",
|
|
29
|
+
"templates"
|
|
29
30
|
],
|
|
30
31
|
"publishConfig": {
|
|
31
32
|
"access": "public"
|
|
@@ -44,11 +45,20 @@
|
|
|
44
45
|
"build": "npm run clean && tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json --resolve-full-paths"
|
|
45
46
|
},
|
|
46
47
|
"dependencies": {
|
|
47
|
-
"@gamedevland/engine": "0.0.
|
|
48
|
+
"@gamedevland/engine": "0.0.11",
|
|
48
49
|
"@poki/cli": "0.1.19",
|
|
49
50
|
"fflate": "0.8.3"
|
|
50
51
|
},
|
|
51
52
|
"peerDependencies": {
|
|
52
53
|
"vite": "^7.1.0 || ^8.0.0"
|
|
54
|
+
},
|
|
55
|
+
"repository": {
|
|
56
|
+
"type": "git",
|
|
57
|
+
"url": "git+https://github.com/gamedevland/sdk.git",
|
|
58
|
+
"directory": "packages/vite"
|
|
59
|
+
},
|
|
60
|
+
"homepage": "https://github.com/gamedevland/sdk/tree/main/packages/vite#readme",
|
|
61
|
+
"bugs": {
|
|
62
|
+
"url": "https://github.com/gamedevland/sdk/issues"
|
|
53
63
|
}
|
|
54
64
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VITE_PLATFORM=crazygames
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Project instructions
|
|
2
|
+
|
|
3
|
+
- Use public `@gamedevland/engine` subsystem exports; do not deep-import internals.
|
|
4
|
+
- Keep flow in FSM → Command → Service. Components/actions own node visuals and input.
|
|
5
|
+
- Keep static hierarchies and authored visual values in JSON layouts/prefabs/configs.
|
|
6
|
+
- Keep every music/SFX channel and per-asset volume in the audio JSON config.
|
|
7
|
+
- Use SDK autoplay recovery and platform-owned data where available.
|
|
8
|
+
- Use strict TypeScript; avoid unsafe casts and non-null assertions.
|
|
9
|
+
- Run `npm run typecheck`, `npm run lint`, and `npm run build` after changes.
|
|
10
|
+
- Do not claim real-browser/device verification from simulated tests.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# __PROJECT_NAME__
|
|
2
|
+
|
|
3
|
+
A blank TypeScript/PixiJS game using the Gamedev Land SDK. No demo gameplay or media assets.
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
npm run dev
|
|
7
|
+
npm run typecheck
|
|
8
|
+
npm run lint
|
|
9
|
+
npm run build
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
The CLI installs dependencies by default. If created with `--no-install`, run `npm install` first.
|
|
13
|
+
Node.js 22.12+ is required.
|
|
14
|
+
|
|
15
|
+
Entry: `game/src/main.ts`. Configuration: `game/src/config/GameConfiguration.ts`.
|
|
16
|
+
The empty scene uses the SDK's FSM, scene DI, asset manifest and JSON layout.
|
|
17
|
+
Add gameplay through FSM → Command → Service; put visuals in components/actions.
|
|
18
|
+
|
|
19
|
+
All music/SFX channel and per-file levels belong in
|
|
20
|
+
`game/assets/json/configs/audio/sounds-volumes.json`.
|
|
21
|
+
|
|
22
|
+
`npm run dev:crazygames` enables the official CrazyGames v3 SDK on localhost.
|
|
23
|
+
`npm run build:crazygames` produces `dist/crazygames/` with relative asset paths.
|
|
24
|
+
Report gameplay start/stop when actual gameplay is added; a blank scene is not gameplay.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "channel.music": 1, "channel.sfx": 1 }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "root": { "type": "Container", "children": {} } }
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
|
6
|
+
<link rel="icon" href="data:," />
|
|
7
|
+
<title>__PROJECT_NAME__</title>
|
|
8
|
+
<style>
|
|
9
|
+
html, body, #app { margin: 0; width: 100%; height: 100%; overflow: hidden; background: #07111f; }
|
|
10
|
+
body { overscroll-behavior: none; user-select: none; -webkit-user-select: none; }
|
|
11
|
+
canvas { display: block; }
|
|
12
|
+
</style>
|
|
13
|
+
</head>
|
|
14
|
+
<body>
|
|
15
|
+
<div id="app"></div>
|
|
16
|
+
<script type="module" src="./src/main.ts"></script>
|
|
17
|
+
</body>
|
|
18
|
+
</html>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { AssetManifestBuilder } from '@gamedevland/engine/assets';
|
|
2
|
+
import type { GameConfig } from '@gamedevland/engine/core';
|
|
3
|
+
import { MainSceneDefinition } from '../scenes/main/MainSceneDefinition';
|
|
4
|
+
import { ProjectDi } from './ProjectDi';
|
|
5
|
+
|
|
6
|
+
export class GameConfiguration {
|
|
7
|
+
static readonly config: GameConfig = {
|
|
8
|
+
system: {
|
|
9
|
+
canvasBackground: '#07111f',
|
|
10
|
+
screen: {
|
|
11
|
+
land: { width: 960, height: 540, fit: 'height' },
|
|
12
|
+
port: { width: 540, height: 960, fit: 'height' },
|
|
13
|
+
dpr: 'native', maxDpr: 2, render: { maxCanvasPixels: 1500000 },
|
|
14
|
+
},
|
|
15
|
+
boot: { configs: { engineStartBundles: ['configs'] } },
|
|
16
|
+
audio: { volumeConfigId: 'json/configs/audio/sounds-volumes.json' },
|
|
17
|
+
},
|
|
18
|
+
assets: {
|
|
19
|
+
bundles: new AssetManifestBuilder({
|
|
20
|
+
configsJson: import.meta.glob<string>('../../assets/json/configs/**/*.json', { eager: true, query: '?url', import: 'default' }),
|
|
21
|
+
layoutsJson: import.meta.glob<string>('../../assets/json/layouts/**/*.json', { eager: true, query: '?url', import: 'default' }),
|
|
22
|
+
audio: {}, fonts: {}, images: {}, localesJson: {}, prefabsJson: {},
|
|
23
|
+
}).build(),
|
|
24
|
+
preload: ['layouts'],
|
|
25
|
+
},
|
|
26
|
+
scenes: { initial: 'main', map: { main: MainSceneDefinition.config } },
|
|
27
|
+
di: new ProjectDi(),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { GameDiDefinition } from '@gamedevland/engine/di';
|
|
2
|
+
import { MainSceneDi } from '../scenes/main/MainSceneDi';
|
|
3
|
+
import { ProjectGlobalDi } from './ProjectGlobalDi';
|
|
4
|
+
|
|
5
|
+
export class ProjectDi extends GameDiDefinition {
|
|
6
|
+
protected override createGlobalDefinition() { return new ProjectGlobalDi(); }
|
|
7
|
+
protected override createSceneDefinitions() { return [new MainSceneDi()]; }
|
|
8
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { GlobalDiDefinition } from '@gamedevland/engine/di';
|
|
2
|
+
import type { ElementFactoriesGroup } from '@gamedevland/engine/di';
|
|
3
|
+
import { Container, Graphics, Text } from '@gamedevland/engine/layouts';
|
|
4
|
+
|
|
5
|
+
export class ProjectGlobalDi extends GlobalDiDefinition {
|
|
6
|
+
protected override registerElements(group: ElementFactoriesGroup): void {
|
|
7
|
+
group.add('Container', Container).add('Graphics', Graphics).add('Text', Text);
|
|
8
|
+
}
|
|
9
|
+
protected override registerComponents(): void {}
|
|
10
|
+
protected override registerCommands(): void {}
|
|
11
|
+
protected override registerServices(): void {}
|
|
12
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SceneConfig } from '@gamedevland/engine/core';
|
|
2
|
+
import { MainScene } from './MainScene';
|
|
3
|
+
|
|
4
|
+
export class MainSceneDefinition {
|
|
5
|
+
static readonly config: SceneConfig = {
|
|
6
|
+
key: 'main', useClass: MainScene,
|
|
7
|
+
layout: 'json/layouts/scenes/main/layout.json',
|
|
8
|
+
fsm: { initial: 'ready', states: { ready: {} } },
|
|
9
|
+
};
|
|
10
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { SceneDiDefinition } from '@gamedevland/engine/di';
|
|
2
|
+
|
|
3
|
+
export class MainSceneDi extends SceneDiDefinition {
|
|
4
|
+
override getSceneKey(): string { return 'main'; }
|
|
5
|
+
protected override registerProviders(): void {}
|
|
6
|
+
protected override registerServices(): void {}
|
|
7
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "__PROJECT_NAME__",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"engines": { "node": ">=22.12.0" },
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "vite",
|
|
9
|
+
"dev:crazygames": "vite --mode crazygames",
|
|
10
|
+
"build": "vite build",
|
|
11
|
+
"build:crazygames": "vite build --mode crazygames --outDir ../dist/crazygames",
|
|
12
|
+
"typecheck": "tsc --noEmit",
|
|
13
|
+
"lint": "eslint . --max-warnings=0",
|
|
14
|
+
"preview": "vite preview"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": { "@gamedevland/engine": "__ENGINE_VERSION__", "pixi.js": "^8.16.0" },
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@gamedevland/vite": "__TOOLING_VERSION__", "@types/node": "^24.7.0",
|
|
19
|
+
"typescript": "^5.9.3", "vite": "^8.0.16", "eslint": "^9.37.0",
|
|
20
|
+
"@eslint/js": "^9.37.0", "typescript-eslint": "^8.46.0"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022", "lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
4
|
+
"module": "ESNext", "moduleResolution": "Bundler", "strict": true,
|
|
5
|
+
"noUncheckedIndexedAccess": true, "exactOptionalPropertyTypes": true,
|
|
6
|
+
"noImplicitOverride": true, "resolveJsonModule": true, "isolatedModules": true,
|
|
7
|
+
"skipLibCheck": true, "noEmit": true, "types": ["node", "vite/client"]
|
|
8
|
+
},
|
|
9
|
+
"include": ["game", "vite.config.ts"], "exclude": ["dist", "node_modules"]
|
|
10
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { fileURLToPath } from 'node:url';
|
|
2
|
+
import { GameViteConfig } from '@gamedevland/vite';
|
|
3
|
+
|
|
4
|
+
export default ({ mode }: { mode: string }) => ({
|
|
5
|
+
...GameViteConfig.create({ mode, repoRoot: fileURLToPath(new URL('.', import.meta.url)) }),
|
|
6
|
+
server: { open: false },
|
|
7
|
+
});
|