@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 +2 -2
- package/src/commands/create.ts +8 -1
- package/templates/env.d.ts +6 -0
- package/templates/global/actions/wait.ts +11 -0
- package/templates/global/events/intro.ts +25 -0
- package/templates/index.html +13 -0
- package/templates/locations/home/location.ts +9 -0
- package/templates/main.ts +118 -0
- package/templates/package.json +22 -0
- package/templates/style.css +2 -0
- package/templates/tsconfig.json +20 -0
- package/templates/vylos.config.ts +11 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vylos/cli",
|
|
3
|
-
"version": "0.
|
|
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.
|
|
20
|
+
"@vylos/core": "0.3.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"typescript": "^5.7.2"
|
package/src/commands/create.ts
CHANGED
|
@@ -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,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,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,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;
|