@vylos/cli 0.2.1 → 0.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vylos/cli",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/DevOpsBenjamin/Vylos"
@@ -17,7 +17,7 @@
17
17
  "tailwindcss": "^4.0.0",
18
18
  "@tailwindcss/vite": "^4.0.0",
19
19
  "tsx": "^4.19.2",
20
- "@vylos/core": "0.2.1"
20
+ "@vylos/core": "0.3.0"
21
21
  },
22
22
  "devDependencies": {
23
23
  "typescript": "^5.7.2"
@@ -1,5 +1,5 @@
1
1
  import { resolve, dirname } from 'path';
2
- import { existsSync, mkdirSync, cpSync } from 'fs';
2
+ import { existsSync, mkdirSync, cpSync, readFileSync, writeFileSync } from 'fs';
3
3
  import { fileURLToPath } from 'url';
4
4
 
5
5
  export async function create(name: string, targetDir?: string) {
@@ -24,6 +24,13 @@ export async function create(name: string, targetDir?: string) {
24
24
  mkdirSync(dest, { recursive: true });
25
25
  cpSync(templateDir, dest, { recursive: true });
26
26
 
27
+ // Replace project name in package.json
28
+ const pkgPath = resolve(dest, 'package.json');
29
+ if (existsSync(pkgPath)) {
30
+ const pkg = readFileSync(pkgPath, 'utf-8');
31
+ writeFileSync(pkgPath, pkg.replace('"my-vylos-game"', `"${name}"`));
32
+ }
33
+
27
34
  console.log(` Project created at: ${dest}`);
28
35
  console.log(`\n Next steps:`);
29
36
  console.log(` cd ${name}`);
@@ -0,0 +1,6 @@
1
+ /// <reference types="vite/client" />
2
+ declare module '*.vue' {
3
+ import type { DefineComponent } from 'vue';
4
+ const component: DefineComponent<{}, {}, any>;
5
+ export default component;
6
+ }
@@ -0,0 +1,11 @@
1
+ import type { VylosAction, BaseGameState } from '@vylos/core';
2
+
3
+ const wait: VylosAction = {
4
+ id: 'wait',
5
+ label: 'Wait 1 Hour',
6
+ execute(state: BaseGameState) {
7
+ state.gameTime += 1;
8
+ },
9
+ };
10
+
11
+ export default wait;
@@ -0,0 +1,25 @@
1
+ import type { VylosEvent, VylosAPI, BaseGameState } from '@vylos/core';
2
+
3
+ const intro: VylosEvent = {
4
+ id: 'intro',
5
+ conditions: (state) => !state.flags['intro_done'],
6
+ async execute(engine: VylosAPI, state: BaseGameState) {
7
+ await engine.say('Welcome to your Vylos game!');
8
+ await engine.say('This is a starter template. Edit the events to build your story.');
9
+
10
+ const pick = await engine.choice([
11
+ { text: 'Sounds good!', value: 'ok' },
12
+ { text: 'Tell me more', value: 'more' },
13
+ ]);
14
+
15
+ if (pick === 'more') {
16
+ await engine.say('Events pause at each say() and choice() call.');
17
+ await engine.say('Add locations, backgrounds, and characters to bring your story to life.');
18
+ }
19
+
20
+ await engine.say('Your adventure begins here. Good luck!');
21
+ state.flags['intro_done'] = true;
22
+ },
23
+ };
24
+
25
+ export default intro;
@@ -0,0 +1,13 @@
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.0, maximum-scale=1.0, user-scalable=no">
6
+ <title>My Vylos Game</title>
7
+ <style>html, body, #app { margin: 0; padding: 0; width: 100%; height: 100%; overflow: hidden; }</style>
8
+ </head>
9
+ <body>
10
+ <div id="app"></div>
11
+ <script type="module" src="./main.ts"></script>
12
+ </body>
13
+ </html>
@@ -0,0 +1,9 @@
1
+ import type { VylosLocation } from '@vylos/core';
2
+
3
+ const home: VylosLocation = {
4
+ id: 'home',
5
+ name: 'Home',
6
+ backgrounds: [{ path: '' }],
7
+ };
8
+
9
+ export default home;
@@ -0,0 +1,118 @@
1
+ import 'reflect-metadata';
2
+ import './style.css';
3
+ import { createApp, watch } from 'vue';
4
+ import { createPinia } from 'pinia';
5
+ import {
6
+ GameShell,
7
+ createEngine,
8
+ useEngineStateStore,
9
+ useGameStateStore,
10
+ ENGINE_INJECT_KEY,
11
+ CONFIG_INJECT_KEY,
12
+ EnginePhase,
13
+ LocationManager,
14
+ ActionManager,
15
+ type EventRunnerCallbacks,
16
+ type TextEntry,
17
+ } from '@vylos/core';
18
+ import config from './vylos.config';
19
+
20
+ // Locations
21
+ import home from './locations/home/location';
22
+
23
+ // Events
24
+ import intro from './global/events/intro';
25
+
26
+ // Actions
27
+ import wait from './global/actions/wait';
28
+
29
+ const app = createApp(GameShell);
30
+ const pinia = createPinia();
31
+ app.use(pinia);
32
+
33
+ const engineState = useEngineStateStore(pinia);
34
+ const gameState = useGameStateStore(pinia);
35
+
36
+ // Location manager
37
+ const locationManager = new LocationManager();
38
+ locationManager.registerAll([home]);
39
+
40
+ // Action manager
41
+ const actionManager = new ActionManager();
42
+ actionManager.registerAll([wait]);
43
+
44
+ const callbacks: EventRunnerCallbacks = {
45
+ onSay(text, speaker) {
46
+ engineState.setDialogue({ text, speaker, isNarration: !speaker });
47
+ },
48
+ onChoice(options) {
49
+ engineState.setChoices({ prompt: null, options });
50
+ },
51
+ onSetBackground(path) { engineState.setBackground(path); },
52
+ onSetForeground(path) { engineState.setForeground(path); },
53
+ onShowOverlay() {},
54
+ onHideOverlay() {},
55
+ onSetLocation(id) {
56
+ gameState.state.locationId = id;
57
+ engineState.setLocation(id);
58
+ const bg = locationManager.resolveBackground(id, gameState.state.gameTime);
59
+ if (bg) engineState.setBackground(bg);
60
+ },
61
+ onClear() {
62
+ engineState.setDialogue(null);
63
+ engineState.setChoices(null);
64
+ },
65
+ resolveText(entry: string | TextEntry) {
66
+ return typeof entry === 'string' ? entry : entry['en'] ?? Object.values(entry)[0] ?? '';
67
+ },
68
+ getState() { return gameState.state; },
69
+ setState(s) { gameState.setState(s); },
70
+ };
71
+
72
+ const engine = createEngine({ callbacks, projectId: config.id });
73
+ app.provide(ENGINE_INJECT_KEY, engine);
74
+ app.provide(CONFIG_INJECT_KEY, config);
75
+ app.mount('#app');
76
+
77
+ engineState.setPhase(EnginePhase.MainMenu);
78
+
79
+ const stopWatch = watch(() => engineState.phase, (newPhase) => {
80
+ if (newPhase === EnginePhase.Running) {
81
+ stopWatch();
82
+ startGame();
83
+ }
84
+ });
85
+
86
+ function startGame() {
87
+ gameState.state.locationId = 'home';
88
+ gameState.state.gameTime = 12;
89
+ engineState.setLocation('home');
90
+
91
+ engine.run([intro], () => gameState.state, {
92
+ onTick(state) {
93
+ const locations = locationManager.getAccessibleFrom(state.locationId, state);
94
+ engineState.setLocations(locations.map(l => ({
95
+ id: l.id,
96
+ name: typeof l.name === 'string' ? l.name : l.name['en'] ?? l.id,
97
+ accessible: true,
98
+ })));
99
+
100
+ const actions = actionManager.getAvailable(state.locationId, state);
101
+ engineState.setActions(actions.map(a => ({
102
+ id: a.id,
103
+ label: typeof a.label === 'string' ? a.label : a.label['en'] ?? a.id,
104
+ locationId: a.locationId ?? '',
105
+ })));
106
+
107
+ const resolveText = (t: string | Record<string, string>) =>
108
+ typeof t === 'string' ? t : t['en'] ?? Object.values(t)[0] ?? '';
109
+ engineState.setDrawableEvents(engine.eventManager.getDrawableEvents(state, resolveText));
110
+
111
+ const bg = locationManager.resolveBackground(state.locationId, state.gameTime);
112
+ if (bg) engineState.setBackground(bg);
113
+ },
114
+ onAction(actionId, state) {
115
+ actionManager.execute(actionId, state);
116
+ },
117
+ }).catch(console.error);
118
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "my-vylos-game",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vylos dev",
8
+ "build": "vylos build"
9
+ },
10
+ "dependencies": {
11
+ "@vylos/core": "^0.2.1",
12
+ "@vylos/cli": "^0.2.1",
13
+ "vue": "^3.5.13",
14
+ "pinia": "^2.3.0",
15
+ "reflect-metadata": "^0.2.2",
16
+ "tailwindcss": "^4.0.0"
17
+ },
18
+ "devDependencies": {
19
+ "typescript": "^5.7.2",
20
+ "vite": "^6.0.7"
21
+ }
22
+ }
@@ -0,0 +1,2 @@
1
+ @import "tailwindcss";
2
+ @source "../node_modules/@vylos/core/src/components";
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
7
+ "strict": true,
8
+ "esModuleInterop": true,
9
+ "skipLibCheck": true,
10
+ "forceConsistentCasingInFileNames": true,
11
+ "resolveJsonModule": true,
12
+ "isolatedModules": true,
13
+ "jsx": "preserve",
14
+ "experimentalDecorators": true,
15
+ "emitDecoratorMetadata": true,
16
+ "baseUrl": "."
17
+ },
18
+ "include": ["./**/*.ts", "./**/*.vue", "./env.d.ts"],
19
+ "exclude": ["node_modules", "dist"]
20
+ }
@@ -0,0 +1,11 @@
1
+ import type { VylosConfig } from '@vylos/core';
2
+
3
+ export default {
4
+ name: 'My Vylos Game',
5
+ id: 'my-game',
6
+ version: '0.1.0',
7
+ languages: ['en'],
8
+ defaultLanguage: 'en',
9
+ defaultLocation: 'home',
10
+ resolution: { width: 1920, height: 1080 },
11
+ } satisfies VylosConfig;