@vylos/cli 0.3.0 → 0.4.1
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/build.ts +6 -3
- package/src/commands/create.ts +17 -1
- package/src/commands/dev.ts +6 -3
- package/src/utils/resolveGameAlias.ts +17 -0
- package/templates/.gitattributes +8 -0
- package/templates/global/actions/wait.ts +4 -3
- package/templates/global/events/intro.ts +6 -4
- package/templates/main.ts +4 -3
- package/templates/package.json +2 -2
- package/templates/plugins/my-vylos-game/characters.ts +9 -0
- package/templates/plugins/my-vylos-game/gameState.ts +39 -0
- package/templates/plugins/my-vylos-game/index.ts +3 -0
- package/templates/plugins/my-vylos-game/player.ts +16 -0
- package/templates/tsconfig.json +5 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vylos/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
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.4.1"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"typescript": "^5.7.2"
|
package/src/commands/build.ts
CHANGED
|
@@ -5,12 +5,17 @@ import { viteSingleFile } from 'vite-plugin-singlefile';
|
|
|
5
5
|
import { resolve } from 'path';
|
|
6
6
|
import { vylosProjectPlugin } from '../vite/projectPlugin';
|
|
7
7
|
import { vylosI18nPlugin } from '../vite/i18nPlugin';
|
|
8
|
+
import { resolveGameAlias } from '../utils/resolveGameAlias';
|
|
8
9
|
|
|
9
10
|
export async function build(projectRoot: string, base?: string) {
|
|
10
11
|
console.log(`\n Vylos building...\n Project: ${projectRoot}\n`);
|
|
11
12
|
|
|
12
13
|
const outDir = resolve(projectRoot, 'dist');
|
|
13
14
|
|
|
15
|
+
const alias: Record<string, string> = { '@project': projectRoot };
|
|
16
|
+
const gamePlugin = resolveGameAlias(projectRoot);
|
|
17
|
+
if (gamePlugin) alias['@game'] = gamePlugin;
|
|
18
|
+
|
|
14
19
|
await viteBuild({
|
|
15
20
|
root: projectRoot,
|
|
16
21
|
base: base ?? '/',
|
|
@@ -22,9 +27,7 @@ export async function build(projectRoot: string, base?: string) {
|
|
|
22
27
|
viteSingleFile(),
|
|
23
28
|
],
|
|
24
29
|
resolve: {
|
|
25
|
-
alias
|
|
26
|
-
'@project': projectRoot,
|
|
27
|
-
},
|
|
30
|
+
alias,
|
|
28
31
|
},
|
|
29
32
|
build: {
|
|
30
33
|
outDir,
|
package/src/commands/create.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { resolve, dirname } from 'path';
|
|
2
|
-
import { existsSync, mkdirSync, cpSync, readFileSync, writeFileSync } from 'fs';
|
|
2
|
+
import { existsSync, mkdirSync, cpSync, readFileSync, writeFileSync, renameSync } from 'fs';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
4
|
|
|
5
|
+
const TEMPLATE_PLUGIN_NAME = 'my-vylos-game';
|
|
6
|
+
|
|
5
7
|
export async function create(name: string, targetDir?: string) {
|
|
6
8
|
const dest = resolve(targetDir ?? process.cwd(), name);
|
|
7
9
|
|
|
@@ -24,6 +26,13 @@ export async function create(name: string, targetDir?: string) {
|
|
|
24
26
|
mkdirSync(dest, { recursive: true });
|
|
25
27
|
cpSync(templateDir, dest, { recursive: true });
|
|
26
28
|
|
|
29
|
+
// Rename plugins/my-vylos-game → plugins/<name>
|
|
30
|
+
const oldPluginDir = resolve(dest, 'plugins', TEMPLATE_PLUGIN_NAME);
|
|
31
|
+
const newPluginDir = resolve(dest, 'plugins', name);
|
|
32
|
+
if (existsSync(oldPluginDir)) {
|
|
33
|
+
renameSync(oldPluginDir, newPluginDir);
|
|
34
|
+
}
|
|
35
|
+
|
|
27
36
|
// Replace project name in package.json
|
|
28
37
|
const pkgPath = resolve(dest, 'package.json');
|
|
29
38
|
if (existsSync(pkgPath)) {
|
|
@@ -31,6 +40,13 @@ export async function create(name: string, targetDir?: string) {
|
|
|
31
40
|
writeFileSync(pkgPath, pkg.replace('"my-vylos-game"', `"${name}"`));
|
|
32
41
|
}
|
|
33
42
|
|
|
43
|
+
// Update @game alias in tsconfig.json to point to the renamed plugin
|
|
44
|
+
const tsconfigPath = resolve(dest, 'tsconfig.json');
|
|
45
|
+
if (existsSync(tsconfigPath)) {
|
|
46
|
+
const tsconfig = readFileSync(tsconfigPath, 'utf-8');
|
|
47
|
+
writeFileSync(tsconfigPath, tsconfig.replaceAll(TEMPLATE_PLUGIN_NAME, name));
|
|
48
|
+
}
|
|
49
|
+
|
|
34
50
|
console.log(` Project created at: ${dest}`);
|
|
35
51
|
console.log(`\n Next steps:`);
|
|
36
52
|
console.log(` cd ${name}`);
|
package/src/commands/dev.ts
CHANGED
|
@@ -5,10 +5,15 @@ import { resolve } from 'path';
|
|
|
5
5
|
import { vylosProjectPlugin } from '../vite/projectPlugin';
|
|
6
6
|
import { vylosI18nPlugin } from '../vite/i18nPlugin';
|
|
7
7
|
import { vylosEditorApiPlugin } from '../vite/editorApiPlugin';
|
|
8
|
+
import { resolveGameAlias } from '../utils/resolveGameAlias';
|
|
8
9
|
|
|
9
10
|
export async function dev(projectRoot: string) {
|
|
10
11
|
console.log(`\n Vylos dev server starting...\n Project: ${projectRoot}\n`);
|
|
11
12
|
|
|
13
|
+
const alias: Record<string, string> = { '@project': projectRoot };
|
|
14
|
+
const gamePlugin = resolveGameAlias(projectRoot);
|
|
15
|
+
if (gamePlugin) alias['@game'] = gamePlugin;
|
|
16
|
+
|
|
12
17
|
const server = await createServer({
|
|
13
18
|
root: projectRoot,
|
|
14
19
|
plugins: [
|
|
@@ -19,9 +24,7 @@ export async function dev(projectRoot: string) {
|
|
|
19
24
|
vylosEditorApiPlugin(),
|
|
20
25
|
],
|
|
21
26
|
resolve: {
|
|
22
|
-
alias
|
|
23
|
-
'@project': projectRoot,
|
|
24
|
-
},
|
|
27
|
+
alias,
|
|
25
28
|
dedupe: ['vue', 'pinia'],
|
|
26
29
|
},
|
|
27
30
|
optimizeDeps: {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { resolve } from 'path';
|
|
2
|
+
import { existsSync, readdirSync, statSync } from 'fs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Scans `plugins/` for the first subdirectory and returns its absolute path.
|
|
6
|
+
* Returns null if no plugins directory or no subdirectory exists.
|
|
7
|
+
*/
|
|
8
|
+
export function resolveGameAlias(projectRoot: string): string | null {
|
|
9
|
+
const pluginsDir = resolve(projectRoot, 'plugins');
|
|
10
|
+
if (!existsSync(pluginsDir)) return null;
|
|
11
|
+
|
|
12
|
+
const dirs = readdirSync(pluginsDir).filter(f =>
|
|
13
|
+
statSync(resolve(pluginsDir, f)).isDirectory(),
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
return dirs.length > 0 ? resolve(pluginsDir, dirs[0]) : null;
|
|
17
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
*.png filter=lfs diff=lfs merge=lfs -text
|
|
2
|
+
*.jpg filter=lfs diff=lfs merge=lfs -text
|
|
3
|
+
*.jpeg filter=lfs diff=lfs merge=lfs -text
|
|
4
|
+
*.webp filter=lfs diff=lfs merge=lfs -text
|
|
5
|
+
*.mp4 filter=lfs diff=lfs merge=lfs -text
|
|
6
|
+
*.webm filter=lfs diff=lfs merge=lfs -text
|
|
7
|
+
*.ogg filter=lfs diff=lfs merge=lfs -text
|
|
8
|
+
*.mp3 filter=lfs diff=lfs merge=lfs -text
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import type { VylosAction
|
|
1
|
+
import type { VylosAction } from '@vylos/core';
|
|
2
|
+
import type { GameState } from '@game';
|
|
2
3
|
|
|
3
|
-
const wait: VylosAction = {
|
|
4
|
+
const wait: VylosAction<GameState> = {
|
|
4
5
|
id: 'wait',
|
|
5
6
|
label: 'Wait 1 Hour',
|
|
6
|
-
execute(state:
|
|
7
|
+
execute(state: GameState) {
|
|
7
8
|
state.gameTime += 1;
|
|
8
9
|
},
|
|
9
10
|
};
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import type { VylosEvent, VylosAPI
|
|
1
|
+
import type { VylosEvent, VylosAPI } from '@vylos/core';
|
|
2
|
+
import type { GameState } from '@game';
|
|
3
|
+
import { narrator } from '@game';
|
|
2
4
|
|
|
3
|
-
const intro: VylosEvent = {
|
|
5
|
+
const intro: VylosEvent<GameState> = {
|
|
4
6
|
id: 'intro',
|
|
5
7
|
conditions: (state) => !state.flags['intro_done'],
|
|
6
|
-
async execute(engine: VylosAPI, state:
|
|
7
|
-
await engine.say('Welcome to your Vylos game!');
|
|
8
|
+
async execute(engine: VylosAPI, state: GameState) {
|
|
9
|
+
await engine.say('Welcome to your Vylos game!', { from: narrator });
|
|
8
10
|
await engine.say('This is a starter template. Edit the events to build your story.');
|
|
9
11
|
|
|
10
12
|
const pick = await engine.choice([
|
package/templates/main.ts
CHANGED
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
GameShell,
|
|
7
7
|
createEngine,
|
|
8
8
|
useEngineStateStore,
|
|
9
|
-
useGameStateStore,
|
|
10
9
|
ENGINE_INJECT_KEY,
|
|
11
10
|
CONFIG_INJECT_KEY,
|
|
12
11
|
EnginePhase,
|
|
@@ -14,8 +13,10 @@ import {
|
|
|
14
13
|
ActionManager,
|
|
15
14
|
type EventRunnerCallbacks,
|
|
16
15
|
type TextEntry,
|
|
16
|
+
type VylosCharacter,
|
|
17
17
|
} from '@vylos/core';
|
|
18
18
|
import config from './vylos.config';
|
|
19
|
+
import { useGameStore } from '@game';
|
|
19
20
|
|
|
20
21
|
// Locations
|
|
21
22
|
import home from './locations/home/location';
|
|
@@ -31,7 +32,7 @@ const pinia = createPinia();
|
|
|
31
32
|
app.use(pinia);
|
|
32
33
|
|
|
33
34
|
const engineState = useEngineStateStore(pinia);
|
|
34
|
-
const gameState =
|
|
35
|
+
const gameState = useGameStore(pinia);
|
|
35
36
|
|
|
36
37
|
// Location manager
|
|
37
38
|
const locationManager = new LocationManager();
|
|
@@ -42,7 +43,7 @@ const actionManager = new ActionManager();
|
|
|
42
43
|
actionManager.registerAll([wait]);
|
|
43
44
|
|
|
44
45
|
const callbacks: EventRunnerCallbacks = {
|
|
45
|
-
onSay(text, speaker) {
|
|
46
|
+
onSay(text: string, speaker: VylosCharacter | null) {
|
|
46
47
|
engineState.setDialogue({ text, speaker, isNarration: !speaker });
|
|
47
48
|
},
|
|
48
49
|
onChoice(options) {
|
package/templates/package.json
CHANGED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { VylosCharacter } from '@vylos/core';
|
|
2
|
+
|
|
3
|
+
/** Extend VylosCharacter with your project-specific fields */
|
|
4
|
+
export interface Character extends VylosCharacter {
|
|
5
|
+
// portrait?: string;
|
|
6
|
+
// role?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const narrator: Character = { id: 'narrator', name: 'Narrator' };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { defineStore } from 'pinia';
|
|
2
|
+
import { ref } from 'vue';
|
|
3
|
+
import type { VylosGameState } from '@vylos/core';
|
|
4
|
+
import { deepMerge } from '@vylos/core';
|
|
5
|
+
import { type Player, createPlayer } from './player';
|
|
6
|
+
|
|
7
|
+
/** Your game state — extends VylosGameState with your own fields */
|
|
8
|
+
export interface GameState extends VylosGameState {
|
|
9
|
+
player: Player;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function createState(): GameState {
|
|
13
|
+
return {
|
|
14
|
+
locationId: '',
|
|
15
|
+
gameTime: 8,
|
|
16
|
+
flags: {},
|
|
17
|
+
counters: {},
|
|
18
|
+
player: createPlayer(),
|
|
19
|
+
inventories: {},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const useGameStore = defineStore('gameState', () => {
|
|
24
|
+
const state = ref<GameState>(createState());
|
|
25
|
+
|
|
26
|
+
function getState(): GameState {
|
|
27
|
+
return state.value;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function setState(newState: Partial<GameState>) {
|
|
31
|
+
state.value = deepMerge(createState(), newState) as GameState;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function $reset() {
|
|
35
|
+
state.value = createState();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return { state, getState, setState, $reset };
|
|
39
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Character } from './characters';
|
|
2
|
+
|
|
3
|
+
/** Extend Character with your player-specific fields */
|
|
4
|
+
export interface Player extends Character {
|
|
5
|
+
// health: number;
|
|
6
|
+
// gold: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function createPlayer(): Player {
|
|
10
|
+
return {
|
|
11
|
+
id: 'player',
|
|
12
|
+
name: 'Player',
|
|
13
|
+
// health: 100,
|
|
14
|
+
// gold: 0,
|
|
15
|
+
};
|
|
16
|
+
}
|
package/templates/tsconfig.json
CHANGED
|
@@ -13,7 +13,11 @@
|
|
|
13
13
|
"jsx": "preserve",
|
|
14
14
|
"experimentalDecorators": true,
|
|
15
15
|
"emitDecoratorMetadata": true,
|
|
16
|
-
"baseUrl": "."
|
|
16
|
+
"baseUrl": ".",
|
|
17
|
+
"paths": {
|
|
18
|
+
"@game": ["./plugins/my-vylos-game"],
|
|
19
|
+
"@game/*": ["./plugins/my-vylos-game/*"]
|
|
20
|
+
}
|
|
17
21
|
},
|
|
18
22
|
"include": ["./**/*.ts", "./**/*.vue", "./env.d.ts"],
|
|
19
23
|
"exclude": ["node_modules", "dist"]
|