@mpgd/cli 0.4.1 → 0.5.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 +6 -6
- package/templates/phaser-game/README.md +12 -0
- package/templates/phaser-game/agent/acceptance.md +3 -0
- package/templates/phaser-game/agent/brief.md +2 -0
- package/templates/phaser-game/agent/game-manifest.json +4 -0
- package/templates/phaser-game/src/i18n/messages.ts +6 -0
- package/templates/phaser-game/src/main.ts +8 -1
- package/templates/phaser-game/src/scenes/LobbyScene.ts +19 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mpgd/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Gunshi CLI for mpgd-kit starter generation and target workflow orchestration.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -52,15 +52,15 @@
|
|
|
52
52
|
"@mpgd/adapter-ait": "0.3.3",
|
|
53
53
|
"@mpgd/adapter-browser": "0.3.2",
|
|
54
54
|
"@mpgd/adapter-capacitor": "0.3.3",
|
|
55
|
-
"@mpgd/analytics": "0.3.2",
|
|
56
55
|
"@mpgd/adapter-devvit": "0.3.3",
|
|
56
|
+
"@mpgd/analytics": "0.3.2",
|
|
57
57
|
"@mpgd/bridge": "0.4.0",
|
|
58
58
|
"@mpgd/catalog": "0.3.2",
|
|
59
|
+
"@mpgd/game-services": "0.3.3",
|
|
59
60
|
"@mpgd/phaser-assets": "0.4.0",
|
|
60
|
-
"@mpgd/
|
|
61
|
-
"@mpgd/target-config": "0.
|
|
62
|
-
"@mpgd/
|
|
63
|
-
"@mpgd/game-services": "0.3.3"
|
|
61
|
+
"@mpgd/i18n": "0.4.0",
|
|
62
|
+
"@mpgd/target-config": "0.4.0",
|
|
63
|
+
"@mpgd/platform": "0.3.2"
|
|
64
64
|
},
|
|
65
65
|
"main": "./dist/index.js",
|
|
66
66
|
"types": "./dist/index.d.ts",
|
|
@@ -84,6 +84,9 @@ const viewport = resolveTargetViewportPlan({
|
|
|
84
84
|
height: measured.height,
|
|
85
85
|
source: measured.source,
|
|
86
86
|
runtime: runtime.config.runtime,
|
|
87
|
+
orientationPolicy: {
|
|
88
|
+
mode: 'prefer-landscape',
|
|
89
|
+
},
|
|
87
90
|
});
|
|
88
91
|
```
|
|
89
92
|
|
|
@@ -104,6 +107,15 @@ Orientation is measured from the container: height greater than width is
|
|
|
104
107
|
be treated as an embedded webview, so do not assume desktop Reddit always means
|
|
105
108
|
an expanded game surface.
|
|
106
109
|
|
|
110
|
+
Orientation policy is a runtime contract, not a guarantee that every shell can
|
|
111
|
+
hard-lock the device. Use `responsive` when both orientations are playable,
|
|
112
|
+
`prefer-landscape` or `prefer-portrait` when layout guidance should favor one
|
|
113
|
+
orientation, and `lock-landscape` or `lock-portrait` when the game should show a
|
|
114
|
+
soft rotate prompt on mismatch. The generated PWA manifest also declares
|
|
115
|
+
`"orientation": "landscape"` for installed web and Microsoft Store shells; keep
|
|
116
|
+
that manifest value aligned with the runtime policy if you make a portrait-first
|
|
117
|
+
game.
|
|
118
|
+
|
|
107
119
|
## Reddit Devvit
|
|
108
120
|
|
|
109
121
|
This starter owns its Devvit app root in `apps/target-devvit`. That directory
|
|
@@ -21,3 +21,6 @@ after login before upload or playtest.
|
|
|
21
21
|
For Microsoft Store changes, keep the first pass as a PWA/web target that uses
|
|
22
22
|
the browser adapter. Add a dedicated Store commerce adapter only when wiring
|
|
23
23
|
Digital Goods API and Payment Request through backend ledger verification.
|
|
24
|
+
|
|
25
|
+
Verify the first screen reports the viewport orientation policy, and treat
|
|
26
|
+
locked orientation modes as soft prompts instead of unsafe WebView hard locks.
|
|
@@ -9,6 +9,8 @@ Boundaries:
|
|
|
9
9
|
- Purchases, rewarded ad grants, and leaderboard records should go through
|
|
10
10
|
backend ledger APIs before mutating durable game save state.
|
|
11
11
|
- Platform SDK imports belong in adapters or target wrappers.
|
|
12
|
+
- Orientation policy should be chosen before adding resize behavior; treat
|
|
13
|
+
locked modes as soft prompts unless a platform adapter supports hard locks.
|
|
12
14
|
|
|
13
15
|
Useful commands:
|
|
14
16
|
|
|
@@ -4,6 +4,8 @@ export type GameMessageKey =
|
|
|
4
4
|
| 'title'
|
|
5
5
|
| 'target'
|
|
6
6
|
| 'viewport'
|
|
7
|
+
| 'orientationPolicy'
|
|
8
|
+
| 'orientationMismatch'
|
|
7
9
|
| 'backend'
|
|
8
10
|
| 'features'
|
|
9
11
|
| 'featuresNone'
|
|
@@ -21,6 +23,8 @@ const messages = {
|
|
|
21
23
|
title: '__GAME_TITLE__',
|
|
22
24
|
target: 'Target: {target}',
|
|
23
25
|
viewport: 'Viewport: {sizeClass} {orientation} - controls {controls}',
|
|
26
|
+
orientationPolicy: 'Orientation policy: {mode}',
|
|
27
|
+
orientationMismatch: 'Rotate to {orientation} for {mode}',
|
|
24
28
|
backend: 'Game Services: {mode}',
|
|
25
29
|
features: 'Features: {features}',
|
|
26
30
|
featuresNone: 'none',
|
|
@@ -37,6 +41,8 @@ const messages = {
|
|
|
37
41
|
title: '__GAME_TITLE__',
|
|
38
42
|
target: '타깃: {target}',
|
|
39
43
|
viewport: '뷰포트: {sizeClass} {orientation} - 컨트롤 {controls}',
|
|
44
|
+
orientationPolicy: '방향 정책: {mode}',
|
|
45
|
+
orientationMismatch: '{mode}: {orientation} 방향으로 회전',
|
|
40
46
|
backend: 'Game Services: {mode}',
|
|
41
47
|
features: '기능: {features}',
|
|
42
48
|
featuresNone: '없음',
|
|
@@ -2,7 +2,10 @@ import './styles.css';
|
|
|
2
2
|
|
|
3
3
|
import { createAnalyticsReporter, createBufferedAnalyticsSink } from '@mpgd/analytics';
|
|
4
4
|
import { resolveMpgdLocale, type Locale } from '@mpgd/i18n';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
resolveTargetViewportPlan,
|
|
7
|
+
type TargetViewportOrientationPolicy,
|
|
8
|
+
} from '@mpgd/target-config';
|
|
6
9
|
|
|
7
10
|
import { t } from './i18n/messages';
|
|
8
11
|
import { createClientId } from './runtime/id';
|
|
@@ -25,9 +28,13 @@ async function bootstrap(): Promise<void> {
|
|
|
25
28
|
const runtimeConfig = detectRuntime();
|
|
26
29
|
const platform = await installPlatform(runtimeConfig);
|
|
27
30
|
const runtime = await platform.getTargetRuntime();
|
|
31
|
+
const orientationPolicy = {
|
|
32
|
+
mode: 'prefer-landscape',
|
|
33
|
+
} as const satisfies TargetViewportOrientationPolicy;
|
|
28
34
|
const viewport = resolveTargetViewportPlan({
|
|
29
35
|
...measureGameViewport(),
|
|
30
36
|
runtime: runtime.config.runtime,
|
|
37
|
+
orientationPolicy,
|
|
31
38
|
});
|
|
32
39
|
const player =
|
|
33
40
|
(await platform.identity.getPlayer()) ?? {
|
|
@@ -21,6 +21,16 @@ export class LobbyScene extends Phaser.Scene {
|
|
|
21
21
|
.filter((feature) => feature.enabled)
|
|
22
22
|
.map((feature) => feature.feature)
|
|
23
23
|
.join(', ') || t(locale, 'featuresNone');
|
|
24
|
+
const orientation = context.viewport.orientation;
|
|
25
|
+
const orientationText =
|
|
26
|
+
orientation.shouldShowRotatePrompt && orientation.preferredOrientation !== undefined
|
|
27
|
+
? t(locale, 'orientationMismatch', {
|
|
28
|
+
mode: orientation.mode,
|
|
29
|
+
orientation: orientation.preferredOrientation,
|
|
30
|
+
})
|
|
31
|
+
: t(locale, 'orientationPolicy', {
|
|
32
|
+
mode: orientation.mode,
|
|
33
|
+
});
|
|
24
34
|
|
|
25
35
|
this.add
|
|
26
36
|
.text(480, 106, t(locale, 'title'), {
|
|
@@ -61,14 +71,21 @@ export class LobbyScene extends Phaser.Scene {
|
|
|
61
71
|
)
|
|
62
72
|
.setOrigin(0.5);
|
|
63
73
|
this.add
|
|
64
|
-
.text(480, 300,
|
|
74
|
+
.text(480, 300, orientationText, {
|
|
75
|
+
color: orientation.shouldShowRotatePrompt ? '#f59e0b' : '#d6dee8',
|
|
76
|
+
fontFamily: 'Arial, sans-serif',
|
|
77
|
+
fontSize: '18px',
|
|
78
|
+
})
|
|
79
|
+
.setOrigin(0.5);
|
|
80
|
+
this.add
|
|
81
|
+
.text(480, 342, t(locale, 'backend', { mode: context.gameServices.mode }), {
|
|
65
82
|
color: context.gameServices.mode === 'disabled' ? '#f59e0b' : '#2dd4bf',
|
|
66
83
|
fontFamily: 'Arial, sans-serif',
|
|
67
84
|
fontSize: '18px',
|
|
68
85
|
})
|
|
69
86
|
.setOrigin(0.5);
|
|
70
87
|
this.add
|
|
71
|
-
.text(480,
|
|
88
|
+
.text(480, 384, t(locale, 'tapToStart'), {
|
|
72
89
|
color: '#ffffff',
|
|
73
90
|
fontFamily: 'Arial, sans-serif',
|
|
74
91
|
fontSize: '22px',
|