@nanoforge-dev/schematics 2.1.4-beta.af6c1e0 → 2.1.4
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/README.md +3 -0
- package/dist/libs/application/application.factory.d.ts +4 -0
- package/dist/libs/application/application.factory.d.ts.map +1 -1
- package/dist/libs/application/application.factory.js +5 -2
- package/dist/libs/application/application.factory.js.map +1 -1
- package/dist/libs/application/files/js/README.md +165 -0
- package/dist/libs/application/files/js/__dot__env +6 -0
- package/dist/libs/application/files/js/__dot__gitignore +134 -0
- package/dist/libs/application/files/ts/README.md +165 -0
- package/dist/libs/application/files/ts/__dot__env +6 -0
- package/dist/libs/application/files/ts/__dot__gitignore +134 -0
- package/dist/libs/application/schema.json +5 -0
- package/dist/libs/component/files/js/__fileName__.component.js +21 -27
- package/dist/libs/component/files/ts/__fileName__.component.ts +21 -27
- package/dist/libs/configuration/configuration.factory.d.ts.map +1 -1
- package/dist/libs/configuration/configuration.factory.js +1 -1
- package/dist/libs/configuration/configuration.factory.js.map +1 -1
- package/dist/libs/part-main/part-main.factory.js +4 -1
- package/dist/libs/part-main/part-main.factory.js.map +1 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -42,6 +42,9 @@ This repository provide multiples schematics, usable with Angular Devkit schemat
|
|
|
42
42
|
- `configuration` : Template of `nanoforge.config.json` with premade fields
|
|
43
43
|
- `part-base` : Base of Nanoforge client or server
|
|
44
44
|
- `part-main` : Client or server `main.ts` from a config
|
|
45
|
+
- `component` : ECS component class for a client or server part
|
|
46
|
+
- `system` : ECS system function for a client or server part
|
|
47
|
+
- `docker` : Dockerfile and `.dockerignore` tailored to your package manager
|
|
45
48
|
|
|
46
49
|
## Contributing
|
|
47
50
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"application.factory.d.ts","names":["name","version","author","description","directory","language","strict","lint","packageManager","server","editor"],"sources":["../../../src/libs/application/application.schema.d.ts","../../../src/libs/application/application.factory.ts"],"mappings":";;;UAAiB,iBAAA;;;AAAjB;EAIEA,IAAAA;EAJgC;;;EAShCC,OAAAA;EAeAG;;;EAVAF,MAAAA;EAmCAO;;;EA9BAN,WAAAA
|
|
1
|
+
{"version":3,"file":"application.factory.d.ts","names":["name","version","author","description","directory","language","strict","lint","packageManager","server","editor","initFunctions"],"sources":["../../../src/libs/application/application.schema.d.ts","../../../src/libs/application/application.factory.ts"],"mappings":";;;UAAiB,iBAAA;;;AAAjB;EAIEA,IAAAA;EAJgC;;;EAShCC,OAAAA;EAeAG;;;EAVAF,MAAAA;EAmCAO;;;EA9BAN,WAAAA;;;;EAKAC,SAAAA;;;;EAKAC,QAAAA;ECqDD;AAAA;;EDhDCC,MAAAA;;;;EAKAC,IAAAA;;;;EAKAC,cAAAA;;;;EAKAC,MAAAA;;;;EAKAC,MAAAA;;;;EAKAC,aAAAA;AAAAA;;;cCJW,IAAA,GAAQ,MAAA,EAAQ,iBAAA,KAAoB,IA2BhD"}
|
|
@@ -14,12 +14,14 @@ const transform = (schema) => {
|
|
|
14
14
|
lint: schema.lint ?? true,
|
|
15
15
|
packageManager: schema.packageManager ?? "npm",
|
|
16
16
|
server: schema.server ?? false,
|
|
17
|
-
editor: schema.editor ?? false
|
|
17
|
+
editor: schema.editor ?? false,
|
|
18
|
+
initFunctions: schema.initFunctions ?? false
|
|
18
19
|
};
|
|
19
20
|
};
|
|
20
21
|
const generate = (options, path) => {
|
|
21
22
|
return apply(url(join("./files", options.language)), [
|
|
22
23
|
template({
|
|
24
|
+
dot: ".",
|
|
23
25
|
...strings,
|
|
24
26
|
...options
|
|
25
27
|
}),
|
|
@@ -37,13 +39,14 @@ const main = (schema) => {
|
|
|
37
39
|
if (typeof tree === "function") return tree;
|
|
38
40
|
tree = await firstValueFrom(tree);
|
|
39
41
|
}
|
|
42
|
+
const basePath = join("/", path);
|
|
40
43
|
if (!options.lint) {
|
|
41
|
-
const basePath = join("/", path);
|
|
42
44
|
tree.delete(join(basePath, "eslint.config.js"));
|
|
43
45
|
tree.delete(join(basePath, "prettier.config.js"));
|
|
44
46
|
tree.delete(join(basePath, ".prettierignore"));
|
|
45
47
|
if (options.language === "js") tree.delete(join(basePath, "jsconfig.json"));
|
|
46
48
|
}
|
|
49
|
+
if (!options.server) tree.delete(join(basePath, ".env"));
|
|
47
50
|
return tree;
|
|
48
51
|
};
|
|
49
52
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"application.factory.js","names":[],"sources":["../../../src/defaults.ts","../../../src/libs/application/application.factory.ts"],"sourcesContent":["export const DEFAULT_APP_NAME = \"nanoforge-app\";\nexport const DEFAULT_VERSION = \"0.0.0\";\nexport const DEFAULT_AUTHOR = \"\";\nexport const DEFAULT_DESCRIPTION = \"\";\nexport const DEFAULT_LANGUAGE = \"ts\";\nexport const DEFAULT_PACKAGE_MANAGER = \"npm\";\n","import { type Path, join, normalize, strings } from \"@angular-devkit/core\";\nimport {\n type Rule,\n type SchematicContext,\n type Source,\n type Tree,\n apply,\n mergeWith,\n move,\n renameTemplateFiles,\n template,\n url,\n} from \"@angular-devkit/schematics\";\nimport { firstValueFrom } from \"rxjs\";\n\nimport {\n DEFAULT_APP_NAME,\n DEFAULT_AUTHOR,\n DEFAULT_DESCRIPTION,\n DEFAULT_LANGUAGE,\n DEFAULT_PACKAGE_MANAGER,\n DEFAULT_VERSION,\n} from \"~/defaults\";\n\nimport { type ApplicationOptions } from \"./application.options\";\nimport { type ApplicationSchema } from \"./application.schema\";\n\nconst transform = (schema: ApplicationSchema): ApplicationOptions => {\n return {\n name: schema.name ?? DEFAULT_APP_NAME,\n version: schema.version ?? DEFAULT_VERSION,\n author: schema.author ?? DEFAULT_AUTHOR,\n description: schema.description ?? DEFAULT_DESCRIPTION,\n language: schema.language ?? DEFAULT_LANGUAGE,\n strict: schema.strict ?? true,\n lint: schema.lint ?? true,\n packageManager: schema.packageManager ?? DEFAULT_PACKAGE_MANAGER,\n server: schema.server ?? false,\n editor: schema.editor ?? false,\n };\n};\n\nconst generate = (options: ApplicationOptions, path: string): Source => {\n return apply(url(join(\"./files\" as Path, options.language)), [\n template({\n ...strings,\n ...options,\n }),\n renameTemplateFiles(),\n move(normalize(path)),\n ]);\n};\n\nexport const main = (schema: ApplicationSchema): Rule => {\n const options = transform(schema);\n const path = schema.directory ?? options.name;\n\n return async (baseTree: Tree, context: SchematicContext) => {\n let tree = await mergeWith(generate(options, path))(baseTree, context);\n if (!tree) return tree;\n if (!(\"delete\" in tree)) {\n if (typeof tree === \"function\") return tree;\n tree = await firstValueFrom(tree);\n }\n\n
|
|
1
|
+
{"version":3,"file":"application.factory.js","names":[],"sources":["../../../src/defaults.ts","../../../src/libs/application/application.factory.ts"],"sourcesContent":["export const DEFAULT_APP_NAME = \"nanoforge-app\";\nexport const DEFAULT_VERSION = \"0.0.0\";\nexport const DEFAULT_AUTHOR = \"\";\nexport const DEFAULT_DESCRIPTION = \"\";\nexport const DEFAULT_LANGUAGE = \"ts\";\nexport const DEFAULT_PACKAGE_MANAGER = \"npm\";\n","import { type Path, join, normalize, strings } from \"@angular-devkit/core\";\nimport {\n type Rule,\n type SchematicContext,\n type Source,\n type Tree,\n apply,\n mergeWith,\n move,\n renameTemplateFiles,\n template,\n url,\n} from \"@angular-devkit/schematics\";\nimport { firstValueFrom } from \"rxjs\";\n\nimport {\n DEFAULT_APP_NAME,\n DEFAULT_AUTHOR,\n DEFAULT_DESCRIPTION,\n DEFAULT_LANGUAGE,\n DEFAULT_PACKAGE_MANAGER,\n DEFAULT_VERSION,\n} from \"~/defaults\";\n\nimport { type ApplicationOptions } from \"./application.options\";\nimport { type ApplicationSchema } from \"./application.schema\";\n\nconst transform = (schema: ApplicationSchema): ApplicationOptions => {\n return {\n name: schema.name ?? DEFAULT_APP_NAME,\n version: schema.version ?? DEFAULT_VERSION,\n author: schema.author ?? DEFAULT_AUTHOR,\n description: schema.description ?? DEFAULT_DESCRIPTION,\n language: schema.language ?? DEFAULT_LANGUAGE,\n strict: schema.strict ?? true,\n lint: schema.lint ?? true,\n packageManager: schema.packageManager ?? DEFAULT_PACKAGE_MANAGER,\n server: schema.server ?? false,\n editor: schema.editor ?? false,\n initFunctions: schema.initFunctions ?? false,\n };\n};\n\nconst generate = (options: ApplicationOptions, path: string): Source => {\n return apply(url(join(\"./files\" as Path, options.language)), [\n template({\n dot: \".\",\n ...strings,\n ...options,\n }),\n renameTemplateFiles(),\n move(normalize(path)),\n ]);\n};\n\nexport const main = (schema: ApplicationSchema): Rule => {\n const options = transform(schema);\n const path = schema.directory ?? options.name;\n\n return async (baseTree: Tree, context: SchematicContext) => {\n let tree = await mergeWith(generate(options, path))(baseTree, context);\n if (!tree) return tree;\n if (!(\"delete\" in tree)) {\n if (typeof tree === \"function\") return tree;\n tree = await firstValueFrom(tree);\n }\n\n const basePath = join(\"/\" as Path, path);\n\n if (!options.lint) {\n tree.delete(join(basePath, \"eslint.config.js\"));\n tree.delete(join(basePath, \"prettier.config.js\"));\n tree.delete(join(basePath, \".prettierignore\"));\n if (options.language === \"js\") tree.delete(join(basePath, \"jsconfig.json\"));\n }\n\n if (!options.server) {\n tree.delete(join(basePath, \".env\"));\n }\n\n return tree;\n };\n};\n"],"mappings":";;;;;AC2BA,MAAM,aAAa,WAAkD;CACnE,OAAO;EACL,MAAM,OAAO,QAAA;EACb,SAAS,OAAO,WAAA;EAChB,QAAQ,OAAO,UAAA;EACf,aAAa,OAAO,eAAA;EACpB,UAAU,OAAO,YAAA;EACjB,QAAQ,OAAO,UAAU;EACzB,MAAM,OAAO,QAAQ;EACrB,gBAAgB,OAAO,kBAAA;EACvB,QAAQ,OAAO,UAAU;EACzB,QAAQ,OAAO,UAAU;EACzB,eAAe,OAAO,iBAAiB;CACzC;AACF;AAEA,MAAM,YAAY,SAA6B,SAAyB;CACtE,OAAO,MAAM,IAAI,KAAK,WAAmB,QAAQ,QAAQ,CAAC,GAAG;EAC3D,SAAS;GACP,KAAK;GACL,GAAG;GACH,GAAG;EACL,CAAC;EACD,oBAAoB;EACpB,KAAK,UAAU,IAAI,CAAC;CACtB,CAAC;AACH;AAEA,MAAa,QAAQ,WAAoC;CACvD,MAAM,UAAU,UAAU,MAAM;CAChC,MAAM,OAAO,OAAO,aAAa,QAAQ;CAEzC,OAAO,OAAO,UAAgB,YAA8B;EAC1D,IAAI,OAAO,MAAM,UAAU,SAAS,SAAS,IAAI,CAAC,EAAE,UAAU,OAAO;EACrE,IAAI,CAAC,MAAM,OAAO;EAClB,IAAI,EAAE,YAAY,OAAO;GACvB,IAAI,OAAO,SAAS,YAAY,OAAO;GACvC,OAAO,MAAM,eAAe,IAAI;EAClC;EAEA,MAAM,WAAW,KAAK,KAAa,IAAI;EAEvC,IAAI,CAAC,QAAQ,MAAM;GACjB,KAAK,OAAO,KAAK,UAAU,kBAAkB,CAAC;GAC9C,KAAK,OAAO,KAAK,UAAU,oBAAoB,CAAC;GAChD,KAAK,OAAO,KAAK,UAAU,iBAAiB,CAAC;GAC7C,IAAI,QAAQ,aAAa,MAAM,KAAK,OAAO,KAAK,UAAU,eAAe,CAAC;EAC5E;EAEA,IAAI,CAAC,QAAQ,QACX,KAAK,OAAO,KAAK,UAAU,MAAM,CAAC;EAGpC,OAAO;CACT;AACF"}
|
|
@@ -1 +1,166 @@
|
|
|
1
1
|
# <%= name %>
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- [Node.js](https://nodejs.org/) 18+
|
|
8
|
+
- Package manager: **<%= packageManager %>**
|
|
9
|
+
- [NanoForge CLI](https://www.npmjs.com/package/@nanoforge-dev/cli): `<%= packageManager %> install -g @nanoforge-dev/cli`
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
<%= packageManager %> install
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Development
|
|
22
|
+
|
|
23
|
+
Start the game in watch mode with hot reload:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
nf dev
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
<% if (editor) { %>Open the visual editor (optional — lets you edit entities, components and systems without touching code):
|
|
30
|
+
```bash
|
|
31
|
+
nf editor
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
<% } %>---
|
|
35
|
+
|
|
36
|
+
## Project structure
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
<%= name %>/
|
|
40
|
+
├── .nanoforge/ # NanoForge internal save files (do not edit manually)
|
|
41
|
+
├── client/ # Client-side code (runs in the browser)
|
|
42
|
+
│ ├── static/ # Static assets
|
|
43
|
+
│ ├── components/ # ECS components
|
|
44
|
+
│ ├── systems/ # ECS systems<% if (initFunctions) { %>
|
|
45
|
+
│ └── init/ # Lifecycle hooks (before-init, after-run, …)<% } %><% if (server) { %>
|
|
46
|
+
├── server/ # Server-side code
|
|
47
|
+
│ ├── static/
|
|
48
|
+
│ ├── components/
|
|
49
|
+
│ ├── systems/<% if (initFunctions) { %>
|
|
50
|
+
│ └── init/<% } %><% } %>
|
|
51
|
+
├── package.json
|
|
52
|
+
├── jsconfig.json
|
|
53
|
+
└── nanoforge.config.json # Game configuration
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Modifying the game
|
|
59
|
+
|
|
60
|
+
### Add a component
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
nf generate component <name> --part client
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
A component is a plain class that holds data for an entity. Edit the generated file in `client/components/`:
|
|
67
|
+
|
|
68
|
+
```js
|
|
69
|
+
export class MyComponent {
|
|
70
|
+
constructor(speed) {
|
|
71
|
+
this.speed = speed;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export default MyComponent.name;
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Add a system
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
nf generate system <name> --part client
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
A system is a function that runs every tick and operates on entities that have specific components. Edit the generated file in `client/systems/`:
|
|
85
|
+
|
|
86
|
+
```js
|
|
87
|
+
import { MyComponent } from "../components/my.component.js";
|
|
88
|
+
|
|
89
|
+
export const mySystem = (registry, ctx) => {
|
|
90
|
+
const entities = registry.getZipper([MyComponent]);
|
|
91
|
+
|
|
92
|
+
entities.forEach((entity) => {
|
|
93
|
+
entity.MyComponent.speed += 1;
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export default mySystem.name;
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
<% if (server) { %>
|
|
101
|
+
### Server-side code
|
|
102
|
+
|
|
103
|
+
Server components and systems live in `server/` and are imported from `@nanoforge-dev/ecs-server`. They follow the same pattern as the client side.
|
|
104
|
+
|
|
105
|
+
Configure the server connection in `.env`:
|
|
106
|
+
|
|
107
|
+
| Variable | Default | Description |
|
|
108
|
+
|---------------------------------------|-------------|---------------------------------|
|
|
109
|
+
| `NANOFORGE_CLIENT_SERVER_ADDRESS` | `127.0.0.1` | Server address (client-side) |
|
|
110
|
+
| `NANOFORGE_CLIENT_SERVER_TCP_PORT` | `4444` | TCP port the client connects to |
|
|
111
|
+
| `NANOFORGE_CLIENT_SERVER_UDP_PORT` | `4445` | UDP port the client connects to |
|
|
112
|
+
| `NANOFORGE_SERVER_LISTENING_TCP_PORT` | `4444` | TCP port the server listens on |
|
|
113
|
+
| `NANOFORGE_SERVER_LISTENING_UDP_PORT` | `4445` | UDP port the server listens on |
|
|
114
|
+
|
|
115
|
+
<% } %>---
|
|
116
|
+
|
|
117
|
+
## Build
|
|
118
|
+
|
|
119
|
+
Compile the game for production:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
<%= packageManager %> run build
|
|
123
|
+
# or
|
|
124
|
+
nf build
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Output is written to the `.nanoforge/` directory.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Run
|
|
132
|
+
|
|
133
|
+
Start the game server and open it in a browser:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
<%= packageManager %> run start
|
|
137
|
+
# or
|
|
138
|
+
nf start
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
<% if (lint) { %>---
|
|
142
|
+
|
|
143
|
+
## Code quality
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
# Check formatting and linting
|
|
147
|
+
<%= packageManager %> run lint
|
|
148
|
+
|
|
149
|
+
# Auto-fix formatting and linting
|
|
150
|
+
<%= packageManager %> run format
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
<% } %>---
|
|
154
|
+
|
|
155
|
+
## CLI reference
|
|
156
|
+
|
|
157
|
+
| Command | Description |
|
|
158
|
+
|--------------------------------|-------------------------------------------|
|
|
159
|
+
| `nf dev` | Start in development mode with hot reload |
|
|
160
|
+
| `nf build` | Build for production |
|
|
161
|
+
| `nf start` | Run the built game |
|
|
162
|
+
| `nf generate component <name>` | Scaffold a new component |
|
|
163
|
+
| `nf generate system <name>` | Scaffold a new system |<% if (editor) { %>
|
|
164
|
+
| `nf editor` | Open the visual editor |<% } %>
|
|
165
|
+
|
|
166
|
+
Full CLI documentation: <https://docs.nanoforge.eu>
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
### VisualStudioCode template
|
|
2
|
+
.vscode/*
|
|
3
|
+
!.vscode/settings.json
|
|
4
|
+
!.vscode/tasks.json
|
|
5
|
+
!.vscode/launch.json
|
|
6
|
+
!.vscode/extensions.json
|
|
7
|
+
!.vscode/*.code-snippets
|
|
8
|
+
|
|
9
|
+
# Local History for Visual Studio Code
|
|
10
|
+
.history/
|
|
11
|
+
|
|
12
|
+
# Built Visual Studio Code Extensions
|
|
13
|
+
*.vsix
|
|
14
|
+
|
|
15
|
+
### JetBrains template
|
|
16
|
+
|
|
17
|
+
# User-specific stuff
|
|
18
|
+
.idea/**/workspace.xml
|
|
19
|
+
.idea/**/tasks.xml
|
|
20
|
+
.idea/**/usage.statistics.xml
|
|
21
|
+
.idea/**/dictionaries
|
|
22
|
+
.idea/**/shelf
|
|
23
|
+
|
|
24
|
+
# Generated files
|
|
25
|
+
.idea/**/contentModel.xml
|
|
26
|
+
|
|
27
|
+
# Sensitive or high-churn files
|
|
28
|
+
.idea/**/dataSources/
|
|
29
|
+
.idea/**/dataSources.ids
|
|
30
|
+
.idea/**/dataSources.local.xml
|
|
31
|
+
.idea/**/sqlDataSources.xml
|
|
32
|
+
.idea/**/dynamic.xml
|
|
33
|
+
.idea/**/uiDesigner.xml
|
|
34
|
+
.idea/**/dbnavigator.xml
|
|
35
|
+
|
|
36
|
+
# File-based project format
|
|
37
|
+
*.iws
|
|
38
|
+
|
|
39
|
+
# Editor-based Rest Client
|
|
40
|
+
.idea/httpRequests
|
|
41
|
+
|
|
42
|
+
### Node template
|
|
43
|
+
# Logs
|
|
44
|
+
logs
|
|
45
|
+
*.log
|
|
46
|
+
npm-debug.log*
|
|
47
|
+
yarn-debug.log*
|
|
48
|
+
yarn-error.log*
|
|
49
|
+
lerna-debug.log*
|
|
50
|
+
.pnpm-debug.log*
|
|
51
|
+
|
|
52
|
+
# Diagnostic reports (https://nodejs.org/api/report.html)
|
|
53
|
+
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
|
54
|
+
|
|
55
|
+
# Runtime data
|
|
56
|
+
pids
|
|
57
|
+
*.pid
|
|
58
|
+
*.seed
|
|
59
|
+
*.pid.lock
|
|
60
|
+
|
|
61
|
+
# Directory for instrumented libs generated by jscoverage/JSCover
|
|
62
|
+
lib-cov
|
|
63
|
+
|
|
64
|
+
# Coverage directory used by tools like istanbul
|
|
65
|
+
coverage
|
|
66
|
+
*.lcov
|
|
67
|
+
|
|
68
|
+
# nyc test coverage
|
|
69
|
+
.nyc_output
|
|
70
|
+
|
|
71
|
+
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
|
72
|
+
.grunt
|
|
73
|
+
|
|
74
|
+
# Bower dependency directory (https://bower.io/)
|
|
75
|
+
bower_components
|
|
76
|
+
|
|
77
|
+
# node-waf configuration
|
|
78
|
+
.lock-wscript
|
|
79
|
+
|
|
80
|
+
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
|
81
|
+
build/Release
|
|
82
|
+
|
|
83
|
+
# Dependency directories
|
|
84
|
+
node_modules/
|
|
85
|
+
jspm_packages/
|
|
86
|
+
|
|
87
|
+
# Snowpack dependency directory (https://snowpack.dev/)
|
|
88
|
+
web_modules/
|
|
89
|
+
|
|
90
|
+
# TypeScript cache
|
|
91
|
+
*.tsbuildinfo
|
|
92
|
+
|
|
93
|
+
# Optional npm cache directory
|
|
94
|
+
.npm
|
|
95
|
+
|
|
96
|
+
# Optional eslint cache
|
|
97
|
+
.eslintcache
|
|
98
|
+
|
|
99
|
+
# Optional stylelint cache
|
|
100
|
+
.stylelintcache
|
|
101
|
+
|
|
102
|
+
# Microbundle cache
|
|
103
|
+
.rpt2_cache/
|
|
104
|
+
.rts2_cache_cjs/
|
|
105
|
+
.rts2_cache_es/
|
|
106
|
+
.rts2_cache_umd/
|
|
107
|
+
|
|
108
|
+
# Optional REPL history
|
|
109
|
+
.node_repl_history
|
|
110
|
+
|
|
111
|
+
# Output of 'npm pack'
|
|
112
|
+
*.tgz
|
|
113
|
+
|
|
114
|
+
# Yarn Integrity file
|
|
115
|
+
.yarn-integrity
|
|
116
|
+
|
|
117
|
+
# dotenv environment variable files
|
|
118
|
+
.env
|
|
119
|
+
.env.development.local
|
|
120
|
+
.env.test.local
|
|
121
|
+
.env.production.local
|
|
122
|
+
.env.local
|
|
123
|
+
|
|
124
|
+
# yarn v2
|
|
125
|
+
.yarn/cache
|
|
126
|
+
.yarn/unplugged
|
|
127
|
+
.yarn/build-state.yml
|
|
128
|
+
.yarn/install-state.gz
|
|
129
|
+
.pnp.*
|
|
130
|
+
|
|
131
|
+
### NanoForge template
|
|
132
|
+
# Compilation directories
|
|
133
|
+
.nanoforge/client
|
|
134
|
+
.nanoforge/server
|
|
@@ -1 +1,166 @@
|
|
|
1
1
|
# <%= name %>
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- [Node.js](https://nodejs.org/) 18+
|
|
8
|
+
- Package manager: **<%= packageManager %>**
|
|
9
|
+
- [NanoForge CLI](https://www.npmjs.com/package/@nanoforge-dev/cli): `<%= packageManager %> install -g @nanoforge-dev/cli`
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
<%= packageManager %> install
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Development
|
|
22
|
+
|
|
23
|
+
Start the game in watch mode with hot reload:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
nf dev
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
<% if (editor) { %>Open the visual editor (optional — lets you edit entities, components and systems without touching code):
|
|
30
|
+
```bash
|
|
31
|
+
nf editor
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
<% } %>---
|
|
35
|
+
|
|
36
|
+
## Project structure
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
<%= name %>/
|
|
40
|
+
├── .nanoforge/ # NanoForge internal save files (do not edit manually)
|
|
41
|
+
├── client/ # Client-side code (runs in the browser)
|
|
42
|
+
│ ├── static/ # Static assets
|
|
43
|
+
│ ├── components/ # ECS components
|
|
44
|
+
│ ├── systems/ # ECS systems<% if (initFunctions) { %>
|
|
45
|
+
│ └── init/ # Lifecycle hooks (before-init, after-run, …)<% } %><% if (server) { %>
|
|
46
|
+
├── server/ # Server-side code
|
|
47
|
+
│ ├── static/
|
|
48
|
+
│ ├── components/
|
|
49
|
+
│ ├── systems/<% if (initFunctions) { %>
|
|
50
|
+
│ └── init/<% } %><% } %>
|
|
51
|
+
├── package.json
|
|
52
|
+
├── tsconfig.json
|
|
53
|
+
└── nanoforge.config.json # Game configuration
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Modifying the game
|
|
59
|
+
|
|
60
|
+
### Add a component
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
nf generate component <name> --part client
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
A component is a plain class that holds data for an entity. Edit the generated file in `client/components/`:
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
export class MyComponent {
|
|
70
|
+
constructor(public speed: number) {}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export default MyComponent.name;
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Add a system
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
nf generate system <name> --part client
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
A system is a function that runs every tick and operates on entities that have specific components. Edit the generated file in `client/systems/`:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
import { type Context } from "@nanoforge-dev/common";
|
|
86
|
+
import { type Registry } from "@nanoforge-dev/ecs-client";
|
|
87
|
+
import { MyComponent } from "../components/my.component";
|
|
88
|
+
|
|
89
|
+
export const mySystem = (registry: Registry, ctx: Context) => {
|
|
90
|
+
const entities = registry.getZipper([MyComponent]);
|
|
91
|
+
|
|
92
|
+
entities.forEach((entity) => {
|
|
93
|
+
entity.MyComponent.speed += 1;
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export default mySystem.name;
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
<% if (server) { %>
|
|
101
|
+
### Server-side code
|
|
102
|
+
|
|
103
|
+
Server components and systems live in `server/` and are imported from `@nanoforge-dev/ecs-server`. They follow the same pattern as the client side.
|
|
104
|
+
|
|
105
|
+
Configure the server connection in `.env`:
|
|
106
|
+
|
|
107
|
+
| Variable | Default | Description |
|
|
108
|
+
|---------------------------------------|-------------|---------------------------------|
|
|
109
|
+
| `NANOFORGE_CLIENT_SERVER_ADDRESS` | `127.0.0.1` | Server address (client-side) |
|
|
110
|
+
| `NANOFORGE_CLIENT_SERVER_TCP_PORT` | `4444` | TCP port the client connects to |
|
|
111
|
+
| `NANOFORGE_CLIENT_SERVER_UDP_PORT` | `4445` | UDP port the client connects to |
|
|
112
|
+
| `NANOFORGE_SERVER_LISTENING_TCP_PORT` | `4444` | TCP port the server listens on |
|
|
113
|
+
| `NANOFORGE_SERVER_LISTENING_UDP_PORT` | `4445` | UDP port the server listens on |
|
|
114
|
+
|
|
115
|
+
<% } %>---
|
|
116
|
+
|
|
117
|
+
## Build
|
|
118
|
+
|
|
119
|
+
Compile the game for production:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
<%= packageManager %> run build
|
|
123
|
+
# or
|
|
124
|
+
nf build
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Output is written to the `.nanoforge/` directory.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Run
|
|
132
|
+
|
|
133
|
+
Start the game server and open it in a browser:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
<%= packageManager %> run start
|
|
137
|
+
# or
|
|
138
|
+
nf start
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
<% if (lint) { %>---
|
|
142
|
+
|
|
143
|
+
## Code quality
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
# Check formatting and linting
|
|
147
|
+
<%= packageManager %> run lint
|
|
148
|
+
|
|
149
|
+
# Auto-fix formatting and linting
|
|
150
|
+
<%= packageManager %> run format
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
<% } %>---
|
|
154
|
+
|
|
155
|
+
## CLI reference
|
|
156
|
+
|
|
157
|
+
| Command | Description |
|
|
158
|
+
|--------------------------------|-------------------------------------------|
|
|
159
|
+
| `nf dev` | Start in development mode with hot reload |
|
|
160
|
+
| `nf build` | Build for production |
|
|
161
|
+
| `nf start` | Run the built game |
|
|
162
|
+
| `nf generate component <name>` | Scaffold a new component |
|
|
163
|
+
| `nf generate system <name>` | Scaffold a new system |<% if (editor) { %>
|
|
164
|
+
| `nf editor` | Open the visual editor |<% } %>
|
|
165
|
+
|
|
166
|
+
Full CLI documentation: <https://docs.nanoforge.eu>
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
### VisualStudioCode template
|
|
2
|
+
.vscode/*
|
|
3
|
+
!.vscode/settings.json
|
|
4
|
+
!.vscode/tasks.json
|
|
5
|
+
!.vscode/launch.json
|
|
6
|
+
!.vscode/extensions.json
|
|
7
|
+
!.vscode/*.code-snippets
|
|
8
|
+
|
|
9
|
+
# Local History for Visual Studio Code
|
|
10
|
+
.history/
|
|
11
|
+
|
|
12
|
+
# Built Visual Studio Code Extensions
|
|
13
|
+
*.vsix
|
|
14
|
+
|
|
15
|
+
### JetBrains template
|
|
16
|
+
|
|
17
|
+
# User-specific stuff
|
|
18
|
+
.idea/**/workspace.xml
|
|
19
|
+
.idea/**/tasks.xml
|
|
20
|
+
.idea/**/usage.statistics.xml
|
|
21
|
+
.idea/**/dictionaries
|
|
22
|
+
.idea/**/shelf
|
|
23
|
+
|
|
24
|
+
# Generated files
|
|
25
|
+
.idea/**/contentModel.xml
|
|
26
|
+
|
|
27
|
+
# Sensitive or high-churn files
|
|
28
|
+
.idea/**/dataSources/
|
|
29
|
+
.idea/**/dataSources.ids
|
|
30
|
+
.idea/**/dataSources.local.xml
|
|
31
|
+
.idea/**/sqlDataSources.xml
|
|
32
|
+
.idea/**/dynamic.xml
|
|
33
|
+
.idea/**/uiDesigner.xml
|
|
34
|
+
.idea/**/dbnavigator.xml
|
|
35
|
+
|
|
36
|
+
# File-based project format
|
|
37
|
+
*.iws
|
|
38
|
+
|
|
39
|
+
# Editor-based Rest Client
|
|
40
|
+
.idea/httpRequests
|
|
41
|
+
|
|
42
|
+
### Node template
|
|
43
|
+
# Logs
|
|
44
|
+
logs
|
|
45
|
+
*.log
|
|
46
|
+
npm-debug.log*
|
|
47
|
+
yarn-debug.log*
|
|
48
|
+
yarn-error.log*
|
|
49
|
+
lerna-debug.log*
|
|
50
|
+
.pnpm-debug.log*
|
|
51
|
+
|
|
52
|
+
# Diagnostic reports (https://nodejs.org/api/report.html)
|
|
53
|
+
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
|
54
|
+
|
|
55
|
+
# Runtime data
|
|
56
|
+
pids
|
|
57
|
+
*.pid
|
|
58
|
+
*.seed
|
|
59
|
+
*.pid.lock
|
|
60
|
+
|
|
61
|
+
# Directory for instrumented libs generated by jscoverage/JSCover
|
|
62
|
+
lib-cov
|
|
63
|
+
|
|
64
|
+
# Coverage directory used by tools like istanbul
|
|
65
|
+
coverage
|
|
66
|
+
*.lcov
|
|
67
|
+
|
|
68
|
+
# nyc test coverage
|
|
69
|
+
.nyc_output
|
|
70
|
+
|
|
71
|
+
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
|
72
|
+
.grunt
|
|
73
|
+
|
|
74
|
+
# Bower dependency directory (https://bower.io/)
|
|
75
|
+
bower_components
|
|
76
|
+
|
|
77
|
+
# node-waf configuration
|
|
78
|
+
.lock-wscript
|
|
79
|
+
|
|
80
|
+
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
|
81
|
+
build/Release
|
|
82
|
+
|
|
83
|
+
# Dependency directories
|
|
84
|
+
node_modules/
|
|
85
|
+
jspm_packages/
|
|
86
|
+
|
|
87
|
+
# Snowpack dependency directory (https://snowpack.dev/)
|
|
88
|
+
web_modules/
|
|
89
|
+
|
|
90
|
+
# TypeScript cache
|
|
91
|
+
*.tsbuildinfo
|
|
92
|
+
|
|
93
|
+
# Optional npm cache directory
|
|
94
|
+
.npm
|
|
95
|
+
|
|
96
|
+
# Optional eslint cache
|
|
97
|
+
.eslintcache
|
|
98
|
+
|
|
99
|
+
# Optional stylelint cache
|
|
100
|
+
.stylelintcache
|
|
101
|
+
|
|
102
|
+
# Microbundle cache
|
|
103
|
+
.rpt2_cache/
|
|
104
|
+
.rts2_cache_cjs/
|
|
105
|
+
.rts2_cache_es/
|
|
106
|
+
.rts2_cache_umd/
|
|
107
|
+
|
|
108
|
+
# Optional REPL history
|
|
109
|
+
.node_repl_history
|
|
110
|
+
|
|
111
|
+
# Output of 'npm pack'
|
|
112
|
+
*.tgz
|
|
113
|
+
|
|
114
|
+
# Yarn Integrity file
|
|
115
|
+
.yarn-integrity
|
|
116
|
+
|
|
117
|
+
# dotenv environment variable files
|
|
118
|
+
.env
|
|
119
|
+
.env.development.local
|
|
120
|
+
.env.test.local
|
|
121
|
+
.env.production.local
|
|
122
|
+
.env.local
|
|
123
|
+
|
|
124
|
+
# yarn v2
|
|
125
|
+
.yarn/cache
|
|
126
|
+
.yarn/unplugged
|
|
127
|
+
.yarn/build-state.yml
|
|
128
|
+
.yarn/install-state.gz
|
|
129
|
+
.pnp.*
|
|
130
|
+
|
|
131
|
+
### NanoForge template
|
|
132
|
+
# Compilation directories
|
|
133
|
+
.nanoforge/client
|
|
134
|
+
.nanoforge/server
|
|
@@ -47,32 +47,26 @@ export const EDITOR_COMPONENT_MANIFEST = {
|
|
|
47
47
|
name: "<%= className %>",
|
|
48
48
|
description: "<%= className %> component description",
|
|
49
49
|
params: [
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
example: true,
|
|
72
|
-
default: false,
|
|
73
|
-
// Not required because it has a default value
|
|
74
|
-
optional: true,
|
|
75
|
-
},
|
|
76
|
-
],
|
|
50
|
+
{
|
|
51
|
+
type: "string",
|
|
52
|
+
name: "paramA",
|
|
53
|
+
description: "Param A description",
|
|
54
|
+
example: "Example value",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
type: "number",
|
|
58
|
+
name: "paramB",
|
|
59
|
+
description: "Param B description",
|
|
60
|
+
example: 3,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
type: "boolean",
|
|
64
|
+
name: "paramC",
|
|
65
|
+
description: "Param C description",
|
|
66
|
+
example: true,
|
|
67
|
+
default: false,
|
|
68
|
+
// Not required because it has a default value
|
|
69
|
+
optional: true,
|
|
70
|
+
},
|
|
77
71
|
],
|
|
78
72
|
};
|
|
@@ -30,32 +30,26 @@ export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = {
|
|
|
30
30
|
name: "<%= className %>",
|
|
31
31
|
description: "<%= className %> component description",
|
|
32
32
|
params: [
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
example: true,
|
|
55
|
-
default: false,
|
|
56
|
-
// Not required because it has a default value
|
|
57
|
-
optional: true,
|
|
58
|
-
},
|
|
59
|
-
],
|
|
33
|
+
{
|
|
34
|
+
type: "string",
|
|
35
|
+
name: "paramA",
|
|
36
|
+
description: "Param A description",
|
|
37
|
+
example: "Example value",
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
type: "number",
|
|
41
|
+
name: "paramB",
|
|
42
|
+
description: "Param B description",
|
|
43
|
+
example: 3,
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
type: "boolean",
|
|
47
|
+
name: "paramC",
|
|
48
|
+
description: "Param C description",
|
|
49
|
+
example: true,
|
|
50
|
+
default: false,
|
|
51
|
+
// Not required because it has a default value
|
|
52
|
+
optional: true,
|
|
53
|
+
},
|
|
60
54
|
],
|
|
61
55
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configuration.factory.d.ts","names":["name","directory","server","language","initFunctions"],"sources":["../../../src/libs/configuration/configuration.schema.d.ts","../../../src/libs/configuration/configuration.factory.ts"],"mappings":";;;UAAiB,mBAAA;;;AAAjB;EAIEA,IAAAA;EAJkC;;;EASlCC,SAAAA;EAeAG;;AAAa;EAVbF,MAAAA;;
|
|
1
|
+
{"version":3,"file":"configuration.factory.d.ts","names":["name","directory","server","language","initFunctions"],"sources":["../../../src/libs/configuration/configuration.schema.d.ts","../../../src/libs/configuration/configuration.factory.ts"],"mappings":";;;UAAiB,mBAAA;;;AAAjB;EAIEA,IAAAA;EAJkC;;;EASlCC,SAAAA;EAeAG;;AAAa;EAVbF,MAAAA;;ACqEF;;EDhEEC,QAAAA;ECgE2B;;;ED3D3BC,aAAAA;AAAAA;;;cC2DW,IAAA,GAAQ,MAAA,EAAQ,mBAAA,KAAsB,IAUlD"}
|
|
@@ -70,10 +70,10 @@ const getConfig = (schema) => {
|
|
|
70
70
|
const res = {
|
|
71
71
|
name: schema.name,
|
|
72
72
|
language: schema.language,
|
|
73
|
-
initFunctions: schema.initFunctions,
|
|
74
73
|
client: { enable: true },
|
|
75
74
|
server: { enable: schema.server ?? false }
|
|
76
75
|
};
|
|
76
|
+
if (schema.initFunctions) res["initFunctions"] = true;
|
|
77
77
|
if (schema.language === "js") {
|
|
78
78
|
if ("client" in res && res.client) {
|
|
79
79
|
res.client["build"] = { entry: "client/main.js" };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configuration.factory.js","names":[],"sources":["../../../src/utils/object.ts","../../../src/utils/config/config.declarator.ts","../../../src/utils/config/config.finder.ts","../../../src/libs/configuration/configuration.factory.ts"],"sourcesContent":["export const isObject = (item: any) => {\n return item && typeof item === \"object\" && !Array.isArray(item);\n};\n\nexport const deepMerge = (target: any, ...sources: [any, ...any[]]): any => {\n if (!sources.length) return target;\n const source = sources.shift();\n\n if (isObject(target) && isObject(source)) {\n for (const key in source) {\n if (isObject(source[key])) {\n if (!target[key]) Object.assign(target, { [key]: {} });\n deepMerge(target[key], source[key]);\n } else {\n Object.assign(target, { [key]: source[key] });\n }\n }\n }\n\n return deepMerge(target, ...sources);\n};\n","import { type Config } from \"@utils/config/config.type\";\nimport { deepMerge } from \"@utils/object\";\nimport { type DeepPartial } from \"@utils/types\";\n\nexport class ConfigDeclarator {\n public declare(baseContent: string, options: DeepPartial<Config>): string {\n const content = JSON.parse(baseContent);\n return JSON.stringify(deepMerge(content, options), null, 2);\n }\n}\n","import { type Path, join } from \"@angular-devkit/core\";\nimport { type DirEntry, type Tree } from \"@angular-devkit/schematics\";\n\nexport interface FindOptions {\n path: Path;\n}\n\nexport class ConfigFinder {\n constructor(private tree: Tree) {}\n\n public find(path: Path): Path | null {\n const dir = this.tree.getDir(path);\n return this.findIn(dir);\n }\n\n /**\n * Recursively searches for the module file in the given directory.\n *\n * @param directory - The directory to search in.\n * @returns The path to the module file, or null if not found.\n */\n private findIn(directory: DirEntry | null): Path | null {\n if (!directory) {\n return null;\n }\n const moduleFilename = directory.subfiles.find((filename) =>\n /^nanoforge.config.json$/.test(filename),\n );\n return moduleFilename !== undefined\n ? join(directory.path, moduleFilename.valueOf())\n : this.findIn(directory.parent);\n }\n}\n","import { type Path, join, normalize, strings } from \"@angular-devkit/core\";\nimport {\n type Rule,\n type Source,\n type Tree,\n apply,\n branchAndMerge,\n chain,\n mergeWith,\n move,\n template,\n url,\n} from \"@angular-devkit/schematics\";\n\nimport { ConfigDeclarator } from \"@utils/config/config.declarator\";\nimport { ConfigFinder } from \"@utils/config/config.finder\";\nimport { type Config } from \"@utils/config/config.type\";\nimport { type DeepPartial } from \"@utils/types\";\n\nimport { type ConfigurationOptions } from \"./configuration.options\";\nimport { type ConfigurationSchema } from \"./configuration.schema\";\n\nconst transform = (schema: ConfigurationSchema): ConfigurationOptions => {\n void schema;\n\n return {};\n};\n\nconst generate = (options: ConfigurationOptions, path: string): Source => {\n return apply(url(join(\"./files\" as Path)), [\n template({\n ...strings,\n ...options,\n }),\n move(normalize(path)),\n ]);\n};\n\nconst addConfiguration = (options: DeepPartial<Config>, path: Path) => {\n return (tree: Tree) => {\n const config = new ConfigFinder(tree).find(path);\n if (!config) return tree;\n\n const content = tree.read(config)?.toString();\n const declarator = new ConfigDeclarator();\n\n if (!content) return tree;\n\n tree.overwrite(config, declarator.declare(content, options));\n return tree;\n };\n};\n\nconst getConfig = (schema: ConfigurationSchema): DeepPartial<Config> => {\n const res: DeepPartial<Config> = {\n name: schema.name,\n language: schema.language,\n
|
|
1
|
+
{"version":3,"file":"configuration.factory.js","names":[],"sources":["../../../src/utils/object.ts","../../../src/utils/config/config.declarator.ts","../../../src/utils/config/config.finder.ts","../../../src/libs/configuration/configuration.factory.ts"],"sourcesContent":["export const isObject = (item: any) => {\n return item && typeof item === \"object\" && !Array.isArray(item);\n};\n\nexport const deepMerge = (target: any, ...sources: [any, ...any[]]): any => {\n if (!sources.length) return target;\n const source = sources.shift();\n\n if (isObject(target) && isObject(source)) {\n for (const key in source) {\n if (isObject(source[key])) {\n if (!target[key]) Object.assign(target, { [key]: {} });\n deepMerge(target[key], source[key]);\n } else {\n Object.assign(target, { [key]: source[key] });\n }\n }\n }\n\n return deepMerge(target, ...sources);\n};\n","import { type Config } from \"@utils/config/config.type\";\nimport { deepMerge } from \"@utils/object\";\nimport { type DeepPartial } from \"@utils/types\";\n\nexport class ConfigDeclarator {\n public declare(baseContent: string, options: DeepPartial<Config>): string {\n const content = JSON.parse(baseContent);\n return JSON.stringify(deepMerge(content, options), null, 2);\n }\n}\n","import { type Path, join } from \"@angular-devkit/core\";\nimport { type DirEntry, type Tree } from \"@angular-devkit/schematics\";\n\nexport interface FindOptions {\n path: Path;\n}\n\nexport class ConfigFinder {\n constructor(private tree: Tree) {}\n\n public find(path: Path): Path | null {\n const dir = this.tree.getDir(path);\n return this.findIn(dir);\n }\n\n /**\n * Recursively searches for the module file in the given directory.\n *\n * @param directory - The directory to search in.\n * @returns The path to the module file, or null if not found.\n */\n private findIn(directory: DirEntry | null): Path | null {\n if (!directory) {\n return null;\n }\n const moduleFilename = directory.subfiles.find((filename) =>\n /^nanoforge.config.json$/.test(filename),\n );\n return moduleFilename !== undefined\n ? join(directory.path, moduleFilename.valueOf())\n : this.findIn(directory.parent);\n }\n}\n","import { type Path, join, normalize, strings } from \"@angular-devkit/core\";\nimport {\n type Rule,\n type Source,\n type Tree,\n apply,\n branchAndMerge,\n chain,\n mergeWith,\n move,\n template,\n url,\n} from \"@angular-devkit/schematics\";\n\nimport { ConfigDeclarator } from \"@utils/config/config.declarator\";\nimport { ConfigFinder } from \"@utils/config/config.finder\";\nimport { type Config } from \"@utils/config/config.type\";\nimport { type DeepPartial } from \"@utils/types\";\n\nimport { type ConfigurationOptions } from \"./configuration.options\";\nimport { type ConfigurationSchema } from \"./configuration.schema\";\n\nconst transform = (schema: ConfigurationSchema): ConfigurationOptions => {\n void schema;\n\n return {};\n};\n\nconst generate = (options: ConfigurationOptions, path: string): Source => {\n return apply(url(join(\"./files\" as Path)), [\n template({\n ...strings,\n ...options,\n }),\n move(normalize(path)),\n ]);\n};\n\nconst addConfiguration = (options: DeepPartial<Config>, path: Path) => {\n return (tree: Tree) => {\n const config = new ConfigFinder(tree).find(path);\n if (!config) return tree;\n\n const content = tree.read(config)?.toString();\n const declarator = new ConfigDeclarator();\n\n if (!content) return tree;\n\n tree.overwrite(config, declarator.declare(content, options));\n return tree;\n };\n};\n\nconst getConfig = (schema: ConfigurationSchema): DeepPartial<Config> => {\n const res: DeepPartial<Config> = {\n name: schema.name,\n language: schema.language,\n client: {\n enable: true,\n },\n server: {\n enable: schema.server ?? false,\n },\n };\n\n if (schema.initFunctions) {\n res[\"initFunctions\"] = true;\n }\n\n if (schema.language === \"js\") {\n if (\"client\" in res && res.client) {\n res.client[\"build\"] = { entry: \"client/main.js\" };\n res.client[\"editor\"] = { entry: \".nanoforge/editor/client/main.js\" };\n }\n if (schema.server && \"server\" in res && res.server) {\n res.server[\"build\"] = { entry: \"server/main.js\" };\n res.server[\"editor\"] = { entry: \".nanoforge/editor/client/main.js\" };\n }\n }\n\n return res;\n};\n\nexport const main = (schema: ConfigurationSchema): Rule => {\n const options = transform(schema);\n const directory = schema.directory;\n\n return branchAndMerge(\n chain([\n mergeWith(generate(options, directory)),\n addConfiguration(getConfig(schema), directory as Path),\n ]),\n );\n};\n"],"mappings":"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"}
|
|
@@ -150,7 +150,10 @@ var MainGenerator = class {
|
|
|
150
150
|
return this;
|
|
151
151
|
}
|
|
152
152
|
generateImports(els, relative) {
|
|
153
|
-
els.sort((a, b) => a.path.localeCompare(b.path)).forEach(({ name, path }) =>
|
|
153
|
+
els.sort((a, b) => a.path.localeCompare(b.path)).forEach(({ name, path }) => {
|
|
154
|
+
path = path.replace(/\.(?:ts|js)$/, "");
|
|
155
|
+
this.writeLine(`import { ${name} } from "${relative ? joinRelative(this.pathToRoot, path) : path}";`);
|
|
156
|
+
});
|
|
154
157
|
this.endSection();
|
|
155
158
|
return this;
|
|
156
159
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"part-main.factory.js","names":["join","join"],"sources":["../../../src/utils/main/enums.ts","../../../src/utils/path.ts","../../../src/utils/main/save.type.ts","../../../src/utils/main/const.ts","../../../src/utils/main/main-utils.ts","../../../src/utils/main/main.generator.ts","../../../src/utils/main/main-functions.ts","../../../src/libs/part-main/part-main.factory.ts"],"sourcesContent":["export enum InitFunctionEnum {\n BEFORE_INIT = \"beforeInit\",\n AFTER_INIT = \"afterInit\",\n BEFORE_REGISTRY_INIT = \"beforeRegistryInit\",\n AFTER_REGISTRY_INIT = \"afterRegistryInit\",\n BEFORE_RUN = \"beforeRun\",\n AFTER_RUN = \"afterRun\",\n}\n","import { join } from \"path\";\n\nexport const joinRelative = (...paths: [string, ...string[]]): string => {\n const path = join(...paths);\n return path.startsWith(\"./\") || path.startsWith(\"../\") ? path : `./${path}`;\n};\n","export enum SaveLibraryTypeEnum {\n COMPONENT_SYSTEM = \"component-system\",\n GRAPHICS = \"graphics\",\n ASSET_MANAGER = \"asset-manager\",\n NETWORK = \"network\",\n INPUT = \"input\",\n SOUND = \"sound\",\n}\n\nexport interface SaveLibrary {\n id: string;\n type: SaveLibraryTypeEnum | string;\n name: string;\n path: string;\n}\n\nexport interface SaveComponent {\n name: string;\n path: string;\n paramsNames: string[];\n}\n\nexport interface SaveSystem {\n name: string;\n path: string;\n}\n\nexport interface SaveEntity {\n id: string;\n components: Record<string, Record<string, any>>;\n}\n\nexport interface Save {\n libraries: SaveLibrary[];\n components: SaveComponent[];\n systems: SaveSystem[];\n entities: SaveEntity[];\n}\n","import { SaveLibraryTypeEnum } from \"@utils/main/save.type\";\n\nexport const LIBS_FUNCTIONS_NAME: Record<SaveLibraryTypeEnum | string, string> = {\n [SaveLibraryTypeEnum.ASSET_MANAGER]: \"useAssetManager\",\n [SaveLibraryTypeEnum.COMPONENT_SYSTEM]: \"useComponentSystem\",\n [SaveLibraryTypeEnum.GRAPHICS]: \"useGraphics\",\n [SaveLibraryTypeEnum.INPUT]: \"useInput\",\n [SaveLibraryTypeEnum.NETWORK]: \"useNetwork\",\n [SaveLibraryTypeEnum.SOUND]: \"useSound\",\n};\n","export const getStringParam = (value: any): string => {\n if (typeof value === \"string\") return `\"${value}\"`;\n if (typeof value === \"number\") return value.toString();\n if (typeof value === \"boolean\") return value ? \"true\" : \"false\";\n if (typeof value === \"object\") return JSON.stringify(value);\n return \"undefined\";\n};\n","import { joinRelative } from \"@utils/path\";\n\nimport { LIBS_FUNCTIONS_NAME } from \"./const\";\nimport { InitFunctionEnum } from \"./enums\";\nimport { getStringParam } from \"./main-utils\";\nimport {\n type SaveComponent,\n type SaveEntity,\n type SaveLibrary,\n SaveLibraryTypeEnum,\n type SaveSystem,\n} from \"./save.type\";\n\nexport class MainGenerator {\n private buffer = \"\";\n private indentation = 0;\n private readonly editor: boolean;\n private readonly pathToRoot: string;\n\n constructor(editor: boolean = false, pathToRoot: string = \"\") {\n this.editor = editor;\n this.pathToRoot = pathToRoot;\n }\n\n toString(): string {\n return this.buffer;\n }\n\n generateBaseImports(hasTypes: boolean): MainGenerator {\n if (this.editor) {\n if (hasTypes)\n this.writeLine(\n `import { type IEditorRunOptions, NanoforgeFactory } from \"@nanoforge-dev/core-editor\";`,\n );\n else this.writeLine(`import { NanoforgeFactory } from \"@nanoforge-dev/core-editor\";`);\n } else {\n if (hasTypes) this.writeLine(`import { type IRunOptions } from \"@nanoforge-dev/common\";`);\n this.writeLine(`import { NanoforgeFactory } from \"@nanoforge-dev/core\";`);\n }\n\n this.endSection();\n return this;\n }\n\n generateLibsImports(libs: SaveLibrary[]): MainGenerator {\n return this.generateImports(libs, false);\n }\n\n generateComponentsImports(libs: SaveComponent[]): MainGenerator {\n return this.generateImports(libs, true);\n }\n\n generateSystemsImports(libs: SaveSystem[]): MainGenerator {\n return this.generateImports(libs, true);\n }\n\n generateMainFunction(hasTypes: boolean, cb: (generator: MainGenerator) => void): MainGenerator {\n if (this.editor)\n this.writeLine(\n `export async function main(options${hasTypes ? \": IEditorRunOptions\" : \"\"}) {`,\n );\n else this.writeLine(`export async function main(options${hasTypes ? \": IRunOptions\" : \"\"}) {`);\n this.indentation += 1;\n cb(this);\n this.indentation -= 1;\n this.writeLine(\"}\");\n return this;\n }\n\n generateApp(isServer: boolean): MainGenerator {\n this.writeLine(`const app = NanoforgeFactory.create${isServer ? \"Server\" : \"Client\"}();`);\n this.endSection();\n return this;\n }\n\n generateAppInit(): MainGenerator {\n this.writeLine(`await app.init(options);`);\n this.endSection();\n return this;\n }\n\n generateAppRun(hasInitFunctions: boolean): MainGenerator {\n this.writeLine(`await app.run();`);\n if (hasInitFunctions) this.endSection();\n return this;\n }\n\n generateLibsInstances(libs: SaveLibrary[]): MainGenerator {\n libs.forEach(({ id, name }) => this.writeLine(`const ${id} = new ${name}();`));\n this.endSection();\n return this;\n }\n\n generateLibsInit(libs: SaveLibrary[]): MainGenerator {\n libs.forEach(({ id, type }) => this.writeLine(this.getInitFunction(id, type)));\n this.endSection();\n return this;\n }\n\n generateRegistry(libs: SaveLibrary[]): MainGenerator {\n const libName =\n libs.find((lib) => lib.type === SaveLibraryTypeEnum.COMPONENT_SYSTEM)?.id ?? \"ecsLibrary\";\n this.writeLine(`const registry = ${libName}.registry;`);\n this.endSection();\n return this;\n }\n\n generateEntities(components: SaveComponent[], entities: SaveEntity[]): MainGenerator {\n entities.forEach((entity, index) => this.generateEntity(components, entity, index));\n return this;\n }\n\n generateSystems(systems: SaveSystem[]): MainGenerator {\n systems.forEach(({ name }) => this.writeLine(`registry.addSystem(${name});`));\n this.endSection();\n return this;\n }\n\n generateInitFunctionIfNeeded(needed: boolean, func: InitFunctionEnum): MainGenerator {\n if (needed) return this.generateInitFunction(func);\n return this;\n }\n\n generateInitFunctionsImportsIfNeeded(needed: boolean): MainGenerator {\n if (!needed) return this;\n return this.generateImports(\n [\n { name: \"afterInit\", path: \"./init/after-init\" },\n { name: \"afterRegistryInit\", path: \"./init/after-registry-init\" },\n { name: \"afterRun\", path: \"./init/after-run\" },\n { name: \"beforeInit\", path: \"./init/before-init\" },\n { name: \"beforeRegistryInit\", path: \"./init/before-registry-init\" },\n { name: \"beforeRun\", path: \"./init/before-run\" },\n ],\n true,\n );\n }\n\n private generateInitFunction(func: InitFunctionEnum): MainGenerator {\n const params = [\"app\"];\n if (\n [InitFunctionEnum.BEFORE_REGISTRY_INIT, InitFunctionEnum.AFTER_REGISTRY_INIT].includes(func)\n )\n params.push(\"registry\");\n this.writeLine(`await ${func}(${params.join(\", \")});`);\n if (func !== InitFunctionEnum.AFTER_RUN) this.endSection();\n return this;\n }\n\n private generateImports(els: { name: string; path: string }[], relative: boolean): MainGenerator {\n els\n .sort((a, b) => a.path.localeCompare(b.path))\n .forEach(({ name, path }) =>\n this.writeLine(\n `import { ${name} } from \"${relative ? joinRelative(this.pathToRoot, path) : path}\";`,\n ),\n );\n this.endSection();\n return this;\n }\n\n private generateEntity(\n components: SaveComponent[],\n entity: SaveEntity,\n entityIndex: number,\n ): void {\n this.writeLine(`const ${entity.id} = registry.spawnEntity();`);\n Object.entries(entity.components).forEach(([componentName, rawParams]) => {\n const originalsParams = components.find(({ name }) => name === componentName)?.paramsNames;\n if (!originalsParams)\n throw new Error(\"Missing component in entity or inexistent saved component\");\n const params: string[] = !this.editor\n ? Object.values(originalsParams).map((ogParam) => {\n return getStringParam(rawParams[ogParam]);\n })\n : Object.values(originalsParams).map((ogParam) => {\n return `options.editor.save.entities[${entityIndex}].components[\"${componentName}\"][\"${ogParam}\"]`;\n });\n this.writeLine(\n `registry.addComponent(${entity.id}, new ${componentName}(${params.join(\", \")}));`,\n );\n });\n if (this.editor) {\n this.writeLine(\n `registry.addComponent(${entity.id}, { name: \"__RESERVED_entityId\", entityId: \"${entity.id}\" });`,\n );\n }\n this.endSection();\n }\n\n private getInitFunction(name: string, type: SaveLibraryTypeEnum | string): string {\n const baseName = LIBS_FUNCTIONS_NAME[type];\n if (baseName) return `app.${baseName}(${name});`;\n return `app.use(Symbol(\"${type}\"), ${name});`;\n }\n\n private writeLine(text: string, indentation = true): void {\n const line = `${\" \".repeat(indentation ? this.indentation * 2 : 0)}${text}\\n`;\n this.buffer += line;\n }\n\n private endSection(): void {\n this.writeLine(\"\");\n }\n}\n","import { join } from \"path\";\n\nimport { InitFunctionEnum } from \"@utils/main/enums\";\n\nimport { MainGenerator } from \"./main.generator\";\nimport { type Save } from \"./save.type\";\n\nexport interface MainOptions {\n part: \"client\" | \"server\";\n language: \"js\" | \"ts\";\n initFunctions: boolean;\n editor: boolean;\n outFile?: string;\n}\n\nexport const generateMain = (options: MainOptions, save: Save) => {\n const isServer = options.part === \"server\";\n const hasTypes = options.language === \"ts\";\n const initFunctions = options.initFunctions;\n\n return (\n !options.editor\n ? new MainGenerator()\n : new MainGenerator(\n true,\n join(\n \"../\".repeat(options.outFile ? options.outFile.split(\"/\").length - 1 : 3),\n options.part,\n ),\n )\n )\n .generateBaseImports(hasTypes)\n .generateLibsImports(save.libraries)\n .generateInitFunctionsImportsIfNeeded(initFunctions)\n .generateComponentsImports(save.components)\n .generateSystemsImports(save.systems)\n\n .generateMainFunction(hasTypes, (generator) => {\n generator\n .generateApp(isServer)\n\n .generateLibsInstances(save.libraries)\n .generateLibsInit(save.libraries)\n\n .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.BEFORE_INIT)\n .generateAppInit()\n .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.AFTER_INIT)\n\n .generateRegistry(save.libraries)\n\n .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.BEFORE_REGISTRY_INIT)\n .generateEntities(save.components, save.entities)\n .generateSystems(save.systems)\n .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.AFTER_REGISTRY_INIT)\n\n .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.BEFORE_RUN)\n .generateAppRun(initFunctions)\n .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.AFTER_RUN);\n })\n .toString();\n};\n","import { type Path, join, normalize, strings } from \"@angular-devkit/core\";\nimport {\n type Rule,\n type Source,\n type Tree,\n apply,\n asSource,\n mergeWith,\n move,\n template,\n} from \"@angular-devkit/schematics\";\nimport * as fs from \"fs\";\n\nimport { generateMain } from \"@utils/main/main-functions\";\nimport { type Save } from \"@utils/main/save.type\";\n\nimport { type PartMainOptions } from \"./part-main.options\";\nimport { type PartMainSchema } from \"./part-main.schema\";\n\nconst transform = (schema: PartMainSchema): PartMainOptions => {\n void schema;\n\n return {};\n};\n\nconst generate = (options: PartMainOptions, path: string, schema: PartMainSchema): Source => {\n const rules = [\n template({\n ...strings,\n ...options,\n }),\n move(normalize(path)),\n ];\n\n return apply(asSource(writeMain(schema, path)), rules);\n};\n\nconst getMainPath = (schema: PartMainSchema): string => {\n if (schema.outFile) return schema.outFile;\n if (schema.editor)\n return join(\".nanoforge/editor\" as Path, schema.part, `main.${schema.language}`);\n return join(schema.part as Path, `main.${schema.language}`);\n};\n\nconst writeMain = (schema: PartMainSchema, path: string) => {\n return (tree: Tree) => {\n const save = getSave(path, schema.part, schema.saveFile);\n\n const resPath = getMainPath(schema);\n\n const content = generateMain(schema, save);\n fs.rmSync(join(path as Path, resPath), { force: true });\n tree.create(resPath, content);\n return tree;\n };\n};\n\nconst getSave = (path: string, part: \"client\" | \"server\", saveFile?: string): Save => {\n return JSON.parse(\n fs.readFileSync(saveFile ?? join(path as Path, `.nanoforge/${part}.save.json`), \"utf-8\"),\n ) as Save;\n};\n\nexport const main = (schema: PartMainSchema): Rule => {\n const options = transform(schema);\n\n return mergeWith(generate(options, schema.directory, schema));\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"part-main.factory.js","names":["join","join"],"sources":["../../../src/utils/main/enums.ts","../../../src/utils/path.ts","../../../src/utils/main/save.type.ts","../../../src/utils/main/const.ts","../../../src/utils/main/main-utils.ts","../../../src/utils/main/main.generator.ts","../../../src/utils/main/main-functions.ts","../../../src/libs/part-main/part-main.factory.ts"],"sourcesContent":["export enum InitFunctionEnum {\n BEFORE_INIT = \"beforeInit\",\n AFTER_INIT = \"afterInit\",\n BEFORE_REGISTRY_INIT = \"beforeRegistryInit\",\n AFTER_REGISTRY_INIT = \"afterRegistryInit\",\n BEFORE_RUN = \"beforeRun\",\n AFTER_RUN = \"afterRun\",\n}\n","import { join } from \"path\";\n\nexport const joinRelative = (...paths: [string, ...string[]]): string => {\n const path = join(...paths);\n return path.startsWith(\"./\") || path.startsWith(\"../\") ? path : `./${path}`;\n};\n","export enum SaveLibraryTypeEnum {\n COMPONENT_SYSTEM = \"component-system\",\n GRAPHICS = \"graphics\",\n ASSET_MANAGER = \"asset-manager\",\n NETWORK = \"network\",\n INPUT = \"input\",\n SOUND = \"sound\",\n}\n\nexport interface SaveLibrary {\n id: string;\n type: SaveLibraryTypeEnum | string;\n name: string;\n path: string;\n}\n\nexport interface SaveComponent {\n name: string;\n path: string;\n paramsNames: string[];\n}\n\nexport interface SaveSystem {\n name: string;\n path: string;\n}\n\nexport interface SaveEntity {\n id: string;\n components: Record<string, Record<string, any>>;\n}\n\nexport interface Save {\n libraries: SaveLibrary[];\n components: SaveComponent[];\n systems: SaveSystem[];\n entities: SaveEntity[];\n}\n","import { SaveLibraryTypeEnum } from \"@utils/main/save.type\";\n\nexport const LIBS_FUNCTIONS_NAME: Record<SaveLibraryTypeEnum | string, string> = {\n [SaveLibraryTypeEnum.ASSET_MANAGER]: \"useAssetManager\",\n [SaveLibraryTypeEnum.COMPONENT_SYSTEM]: \"useComponentSystem\",\n [SaveLibraryTypeEnum.GRAPHICS]: \"useGraphics\",\n [SaveLibraryTypeEnum.INPUT]: \"useInput\",\n [SaveLibraryTypeEnum.NETWORK]: \"useNetwork\",\n [SaveLibraryTypeEnum.SOUND]: \"useSound\",\n};\n","export const getStringParam = (value: any): string => {\n if (typeof value === \"string\") return `\"${value}\"`;\n if (typeof value === \"number\") return value.toString();\n if (typeof value === \"boolean\") return value ? \"true\" : \"false\";\n if (typeof value === \"object\") return JSON.stringify(value);\n return \"undefined\";\n};\n","import { joinRelative } from \"@utils/path\";\n\nimport { LIBS_FUNCTIONS_NAME } from \"./const\";\nimport { InitFunctionEnum } from \"./enums\";\nimport { getStringParam } from \"./main-utils\";\nimport {\n type SaveComponent,\n type SaveEntity,\n type SaveLibrary,\n SaveLibraryTypeEnum,\n type SaveSystem,\n} from \"./save.type\";\n\nexport class MainGenerator {\n private buffer = \"\";\n private indentation = 0;\n private readonly editor: boolean;\n private readonly pathToRoot: string;\n\n constructor(editor: boolean = false, pathToRoot: string = \"\") {\n this.editor = editor;\n this.pathToRoot = pathToRoot;\n }\n\n toString(): string {\n return this.buffer;\n }\n\n generateBaseImports(hasTypes: boolean): MainGenerator {\n if (this.editor) {\n if (hasTypes)\n this.writeLine(\n `import { type IEditorRunOptions, NanoforgeFactory } from \"@nanoforge-dev/core-editor\";`,\n );\n else this.writeLine(`import { NanoforgeFactory } from \"@nanoforge-dev/core-editor\";`);\n } else {\n if (hasTypes) this.writeLine(`import { type IRunOptions } from \"@nanoforge-dev/common\";`);\n this.writeLine(`import { NanoforgeFactory } from \"@nanoforge-dev/core\";`);\n }\n\n this.endSection();\n return this;\n }\n\n generateLibsImports(libs: SaveLibrary[]): MainGenerator {\n return this.generateImports(libs, false);\n }\n\n generateComponentsImports(libs: SaveComponent[]): MainGenerator {\n return this.generateImports(libs, true);\n }\n\n generateSystemsImports(libs: SaveSystem[]): MainGenerator {\n return this.generateImports(libs, true);\n }\n\n generateMainFunction(hasTypes: boolean, cb: (generator: MainGenerator) => void): MainGenerator {\n if (this.editor)\n this.writeLine(\n `export async function main(options${hasTypes ? \": IEditorRunOptions\" : \"\"}) {`,\n );\n else this.writeLine(`export async function main(options${hasTypes ? \": IRunOptions\" : \"\"}) {`);\n this.indentation += 1;\n cb(this);\n this.indentation -= 1;\n this.writeLine(\"}\");\n return this;\n }\n\n generateApp(isServer: boolean): MainGenerator {\n this.writeLine(`const app = NanoforgeFactory.create${isServer ? \"Server\" : \"Client\"}();`);\n this.endSection();\n return this;\n }\n\n generateAppInit(): MainGenerator {\n this.writeLine(`await app.init(options);`);\n this.endSection();\n return this;\n }\n\n generateAppRun(hasInitFunctions: boolean): MainGenerator {\n this.writeLine(`await app.run();`);\n if (hasInitFunctions) this.endSection();\n return this;\n }\n\n generateLibsInstances(libs: SaveLibrary[]): MainGenerator {\n libs.forEach(({ id, name }) => this.writeLine(`const ${id} = new ${name}();`));\n this.endSection();\n return this;\n }\n\n generateLibsInit(libs: SaveLibrary[]): MainGenerator {\n libs.forEach(({ id, type }) => this.writeLine(this.getInitFunction(id, type)));\n this.endSection();\n return this;\n }\n\n generateRegistry(libs: SaveLibrary[]): MainGenerator {\n const libName =\n libs.find((lib) => lib.type === SaveLibraryTypeEnum.COMPONENT_SYSTEM)?.id ?? \"ecsLibrary\";\n this.writeLine(`const registry = ${libName}.registry;`);\n this.endSection();\n return this;\n }\n\n generateEntities(components: SaveComponent[], entities: SaveEntity[]): MainGenerator {\n entities.forEach((entity, index) => this.generateEntity(components, entity, index));\n return this;\n }\n\n generateSystems(systems: SaveSystem[]): MainGenerator {\n systems.forEach(({ name }) => this.writeLine(`registry.addSystem(${name});`));\n this.endSection();\n return this;\n }\n\n generateInitFunctionIfNeeded(needed: boolean, func: InitFunctionEnum): MainGenerator {\n if (needed) return this.generateInitFunction(func);\n return this;\n }\n\n generateInitFunctionsImportsIfNeeded(needed: boolean): MainGenerator {\n if (!needed) return this;\n return this.generateImports(\n [\n { name: \"afterInit\", path: \"./init/after-init\" },\n { name: \"afterRegistryInit\", path: \"./init/after-registry-init\" },\n { name: \"afterRun\", path: \"./init/after-run\" },\n { name: \"beforeInit\", path: \"./init/before-init\" },\n { name: \"beforeRegistryInit\", path: \"./init/before-registry-init\" },\n { name: \"beforeRun\", path: \"./init/before-run\" },\n ],\n true,\n );\n }\n\n private generateInitFunction(func: InitFunctionEnum): MainGenerator {\n const params = [\"app\"];\n if (\n [InitFunctionEnum.BEFORE_REGISTRY_INIT, InitFunctionEnum.AFTER_REGISTRY_INIT].includes(func)\n )\n params.push(\"registry\");\n this.writeLine(`await ${func}(${params.join(\", \")});`);\n if (func !== InitFunctionEnum.AFTER_RUN) this.endSection();\n return this;\n }\n\n private generateImports(els: { name: string; path: string }[], relative: boolean): MainGenerator {\n els\n .sort((a, b) => a.path.localeCompare(b.path))\n .forEach(({ name, path }) => {\n path = path.replace(/\\.(?:ts|js)$/, \"\");\n this.writeLine(\n `import { ${name} } from \"${relative ? joinRelative(this.pathToRoot, path) : path}\";`,\n );\n });\n this.endSection();\n return this;\n }\n\n private generateEntity(\n components: SaveComponent[],\n entity: SaveEntity,\n entityIndex: number,\n ): void {\n this.writeLine(`const ${entity.id} = registry.spawnEntity();`);\n Object.entries(entity.components).forEach(([componentName, rawParams]) => {\n const originalsParams = components.find(({ name }) => name === componentName)?.paramsNames;\n if (!originalsParams)\n throw new Error(\"Missing component in entity or inexistent saved component\");\n const params: string[] = !this.editor\n ? Object.values(originalsParams).map((ogParam) => {\n return getStringParam(rawParams[ogParam]);\n })\n : Object.values(originalsParams).map((ogParam) => {\n return `options.editor.save.entities[${entityIndex}].components[\"${componentName}\"][\"${ogParam}\"]`;\n });\n this.writeLine(\n `registry.addComponent(${entity.id}, new ${componentName}(${params.join(\", \")}));`,\n );\n });\n if (this.editor) {\n this.writeLine(\n `registry.addComponent(${entity.id}, { name: \"__RESERVED_entityId\", entityId: \"${entity.id}\" });`,\n );\n }\n this.endSection();\n }\n\n private getInitFunction(name: string, type: SaveLibraryTypeEnum | string): string {\n const baseName = LIBS_FUNCTIONS_NAME[type];\n if (baseName) return `app.${baseName}(${name});`;\n return `app.use(Symbol(\"${type}\"), ${name});`;\n }\n\n private writeLine(text: string, indentation = true): void {\n const line = `${\" \".repeat(indentation ? this.indentation * 2 : 0)}${text}\\n`;\n this.buffer += line;\n }\n\n private endSection(): void {\n this.writeLine(\"\");\n }\n}\n","import { join } from \"path\";\n\nimport { InitFunctionEnum } from \"@utils/main/enums\";\n\nimport { MainGenerator } from \"./main.generator\";\nimport { type Save } from \"./save.type\";\n\nexport interface MainOptions {\n part: \"client\" | \"server\";\n language: \"js\" | \"ts\";\n initFunctions: boolean;\n editor: boolean;\n outFile?: string;\n}\n\nexport const generateMain = (options: MainOptions, save: Save) => {\n const isServer = options.part === \"server\";\n const hasTypes = options.language === \"ts\";\n const initFunctions = options.initFunctions;\n\n return (\n !options.editor\n ? new MainGenerator()\n : new MainGenerator(\n true,\n join(\n \"../\".repeat(options.outFile ? options.outFile.split(\"/\").length - 1 : 3),\n options.part,\n ),\n )\n )\n .generateBaseImports(hasTypes)\n .generateLibsImports(save.libraries)\n .generateInitFunctionsImportsIfNeeded(initFunctions)\n .generateComponentsImports(save.components)\n .generateSystemsImports(save.systems)\n\n .generateMainFunction(hasTypes, (generator) => {\n generator\n .generateApp(isServer)\n\n .generateLibsInstances(save.libraries)\n .generateLibsInit(save.libraries)\n\n .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.BEFORE_INIT)\n .generateAppInit()\n .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.AFTER_INIT)\n\n .generateRegistry(save.libraries)\n\n .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.BEFORE_REGISTRY_INIT)\n .generateEntities(save.components, save.entities)\n .generateSystems(save.systems)\n .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.AFTER_REGISTRY_INIT)\n\n .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.BEFORE_RUN)\n .generateAppRun(initFunctions)\n .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.AFTER_RUN);\n })\n .toString();\n};\n","import { type Path, join, normalize, strings } from \"@angular-devkit/core\";\nimport {\n type Rule,\n type Source,\n type Tree,\n apply,\n asSource,\n mergeWith,\n move,\n template,\n} from \"@angular-devkit/schematics\";\nimport * as fs from \"fs\";\n\nimport { generateMain } from \"@utils/main/main-functions\";\nimport { type Save } from \"@utils/main/save.type\";\n\nimport { type PartMainOptions } from \"./part-main.options\";\nimport { type PartMainSchema } from \"./part-main.schema\";\n\nconst transform = (schema: PartMainSchema): PartMainOptions => {\n void schema;\n\n return {};\n};\n\nconst generate = (options: PartMainOptions, path: string, schema: PartMainSchema): Source => {\n const rules = [\n template({\n ...strings,\n ...options,\n }),\n move(normalize(path)),\n ];\n\n return apply(asSource(writeMain(schema, path)), rules);\n};\n\nconst getMainPath = (schema: PartMainSchema): string => {\n if (schema.outFile) return schema.outFile;\n if (schema.editor)\n return join(\".nanoforge/editor\" as Path, schema.part, `main.${schema.language}`);\n return join(schema.part as Path, `main.${schema.language}`);\n};\n\nconst writeMain = (schema: PartMainSchema, path: string) => {\n return (tree: Tree) => {\n const save = getSave(path, schema.part, schema.saveFile);\n\n const resPath = getMainPath(schema);\n\n const content = generateMain(schema, save);\n fs.rmSync(join(path as Path, resPath), { force: true });\n tree.create(resPath, content);\n return tree;\n };\n};\n\nconst getSave = (path: string, part: \"client\" | \"server\", saveFile?: string): Save => {\n return JSON.parse(\n fs.readFileSync(saveFile ?? join(path as Path, `.nanoforge/${part}.save.json`), \"utf-8\"),\n ) as Save;\n};\n\nexport const main = (schema: PartMainSchema): Rule => {\n const options = transform(schema);\n\n return mergeWith(generate(options, schema.directory, schema));\n};\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@nanoforge-dev/schematics",
|
|
4
|
-
"version": "2.1.4
|
|
4
|
+
"version": "2.1.4",
|
|
5
5
|
"description": "NanoForge Schematics",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"nanoforge",
|
|
@@ -34,7 +34,8 @@
|
|
|
34
34
|
"default": "./dist/index.js"
|
|
35
35
|
}
|
|
36
36
|
},
|
|
37
|
-
"./package.json": "./package.json"
|
|
37
|
+
"./package.json": "./package.json",
|
|
38
|
+
"./collection.json": "./dist/collection.json"
|
|
38
39
|
},
|
|
39
40
|
"type": "module",
|
|
40
41
|
"directories": {
|
|
@@ -46,7 +47,7 @@
|
|
|
46
47
|
},
|
|
47
48
|
"funding": "https://github.com/NanoForge-dev/schematics?sponsor",
|
|
48
49
|
"dependencies": {
|
|
49
|
-
"@angular-devkit/core": "^
|
|
50
|
+
"@angular-devkit/core": "^22.0.0",
|
|
50
51
|
"@angular-devkit/schematics": "^21.2.13",
|
|
51
52
|
"rxjs": "^7.8.2"
|
|
52
53
|
},
|