@shigureni/minion 0.2.0 → 0.4.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/cli/src/index.ts
CHANGED
|
@@ -20,10 +20,10 @@ Usage:
|
|
|
20
20
|
minion <command> -h Show help for a command
|
|
21
21
|
|
|
22
22
|
Commands:
|
|
23
|
-
start 起動する (
|
|
23
|
+
start 起動する (すでに起動中なら何もしない)
|
|
24
24
|
dev 停止してデバッグビルドで起動し直す
|
|
25
25
|
kill 停止する
|
|
26
|
-
reboot 停止してリリースビルドで起動し直す
|
|
26
|
+
reboot 停止してリリースビルドで起動し直す (デフォルト)
|
|
27
27
|
status 起動状況を表示する
|
|
28
28
|
dex 実績とミニオン図鑑を表示する
|
|
29
29
|
config list 設定値を一覧表示する
|
|
@@ -35,7 +35,8 @@ Global flags:
|
|
|
35
35
|
-v, --version Show version`
|
|
36
36
|
|
|
37
37
|
const argv = process.argv.slice(2)
|
|
38
|
-
|
|
38
|
+
// 引数なしの `minion` は「古いプロセスを止めて起動し直す」= reboot に落とす。
|
|
39
|
+
const args = argv.length === 0 ? ["reboot"] : argv
|
|
39
40
|
|
|
40
41
|
const request = toRequest(args)
|
|
41
42
|
|
|
@@ -13,10 +13,12 @@ export const help = `Usage: minion dev
|
|
|
13
13
|
export default factory.createHandlers(helpGuard(help), bodyValidator(schema), async (c) => {
|
|
14
14
|
const killResult = c.env.minion.app.kill()
|
|
15
15
|
if (killResult instanceof Error) return c.text(killResult.message, 500)
|
|
16
|
+
// 何も止めていないときは kill の行を出さず、起動結果だけを表示する。
|
|
17
|
+
const killLine = killResult.kind === "killed" ? [formatKillResult(killResult)] : []
|
|
16
18
|
const startResult = await c.env.minion.app.start({ debug: true })
|
|
17
19
|
if (startResult instanceof Error) {
|
|
18
|
-
return c.text([
|
|
20
|
+
return c.text([...killLine, startResult.message].join("\n"), 500)
|
|
19
21
|
}
|
|
20
|
-
const text = [
|
|
22
|
+
const text = [...killLine, formatStartResult(startResult)].join("\n")
|
|
21
23
|
return c.text(text, isStartError(startResult) ? 500 : 200)
|
|
22
24
|
})
|
|
@@ -13,10 +13,12 @@ export const help = `Usage: minion reboot
|
|
|
13
13
|
export default factory.createHandlers(helpGuard(help), bodyValidator(schema), async (c) => {
|
|
14
14
|
const killResult = c.env.minion.app.kill()
|
|
15
15
|
if (killResult instanceof Error) return c.text(killResult.message, 500)
|
|
16
|
+
// 何も止めていないときは kill の行を出さず、起動結果だけを表示する。
|
|
17
|
+
const killLine = killResult.kind === "killed" ? [formatKillResult(killResult)] : []
|
|
16
18
|
const startResult = await c.env.minion.app.start()
|
|
17
19
|
if (startResult instanceof Error) {
|
|
18
|
-
return c.text([
|
|
20
|
+
return c.text([...killLine, startResult.message].join("\n"), 500)
|
|
19
21
|
}
|
|
20
|
-
const text = [
|
|
22
|
+
const text = [...killLine, formatStartResult(startResult)].join("\n")
|
|
21
23
|
return c.text(text, isStartError(startResult) ? 500 : 200)
|
|
22
24
|
})
|
|
@@ -21,6 +21,20 @@ export const ACTIONS: { durationMs: [number, number]; weight: number }[] = [
|
|
|
21
21
|
{ weight: 2, durationMs: [2000, 3000] }, // 12 食べる2
|
|
22
22
|
]
|
|
23
23
|
|
|
24
|
+
// 稼働していないセッション用の「静かな」行動だけの部分集合(clipIndexはACTIONS/Swiftの
|
|
25
|
+
// 並びを指す)。移動・ジャンプ・食事は含めず、待機と座り姿勢をゆっくり切り替える。
|
|
26
|
+
export const SLEEPING_ACTIONS: {
|
|
27
|
+
clipIndex: number
|
|
28
|
+
durationMs: [number, number]
|
|
29
|
+
weight: number
|
|
30
|
+
}[] = [
|
|
31
|
+
{ clipIndex: 0, weight: 40, durationMs: [6000, 12000] }, // 待機
|
|
32
|
+
{ clipIndex: 7, weight: 15, durationMs: [6000, 12000] }, // 座る1
|
|
33
|
+
{ clipIndex: 8, weight: 15, durationMs: [6000, 12000] }, // 座る2
|
|
34
|
+
{ clipIndex: 9, weight: 15, durationMs: [6000, 12000] }, // 座る3
|
|
35
|
+
{ clipIndex: 10, weight: 15, durationMs: [6000, 12000] }, // 座る4
|
|
36
|
+
]
|
|
37
|
+
|
|
24
38
|
export type PetAction = { clipIndex: number; durationMs: number }
|
|
25
39
|
|
|
26
40
|
export function pickAction(random: MinionRandomSource): PetAction {
|
|
@@ -43,6 +57,26 @@ export function pickAction(random: MinionRandomSource): PetAction {
|
|
|
43
57
|
return { clipIndex: chosen, durationMs: min + random.next() * (max - min) }
|
|
44
58
|
}
|
|
45
59
|
|
|
60
|
+
export function pickSleepingAction(random: MinionRandomSource): PetAction {
|
|
61
|
+
const roll = random.next() * 100
|
|
62
|
+
let cumulative = 0
|
|
63
|
+
let chosen = SLEEPING_ACTIONS[0]
|
|
64
|
+
|
|
65
|
+
for (const action of SLEEPING_ACTIONS) {
|
|
66
|
+
cumulative += action.weight
|
|
67
|
+
if (roll < cumulative) {
|
|
68
|
+
chosen = action
|
|
69
|
+
break
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const [min, max] = chosen?.durationMs ?? [0, 0]
|
|
74
|
+
return {
|
|
75
|
+
clipIndex: chosen?.clipIndex ?? IDLE_CLIP,
|
|
76
|
+
durationMs: min + random.next() * (max - min),
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
46
80
|
export type PetBehavior = {
|
|
47
81
|
running: boolean
|
|
48
82
|
name: string
|
|
@@ -85,9 +119,7 @@ export class PetBehaviorEngine {
|
|
|
85
119
|
const existing = this.behaviors.get(id)
|
|
86
120
|
|
|
87
121
|
if (!existing) {
|
|
88
|
-
const action = info.running
|
|
89
|
-
? pickAction(this.random)
|
|
90
|
-
: { clipIndex: IDLE_CLIP, durationMs: 0 }
|
|
122
|
+
const action = info.running ? pickAction(this.random) : pickSleepingAction(this.random)
|
|
91
123
|
this.behaviors.set(id, {
|
|
92
124
|
running: info.running,
|
|
93
125
|
name: info.name,
|
|
@@ -105,20 +137,16 @@ export class PetBehaviorEngine {
|
|
|
105
137
|
|
|
106
138
|
if (existing.running !== info.running) {
|
|
107
139
|
existing.running = info.running
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
existing.clipIndex = action.clipIndex
|
|
111
|
-
existing.actionEndsAt = now + action.durationMs
|
|
112
|
-
} else {
|
|
113
|
-
// 稼働が止まったら、直前のアクションの途中コマで固まらないよう待機姿勢に戻す。
|
|
114
|
-
existing.clipIndex = IDLE_CLIP
|
|
115
|
-
}
|
|
116
|
-
dirty = true
|
|
117
|
-
} else if (info.running && now >= existing.actionEndsAt) {
|
|
118
|
-
const action = pickAction(this.random)
|
|
140
|
+
// 稼働が止まったときも静かな姿勢を選び直す(走りの途中コマで固まらないように)。
|
|
141
|
+
const action = info.running ? pickAction(this.random) : pickSleepingAction(this.random)
|
|
119
142
|
existing.clipIndex = action.clipIndex
|
|
120
143
|
existing.actionEndsAt = now + action.durationMs
|
|
121
144
|
dirty = true
|
|
145
|
+
} else if (now >= existing.actionEndsAt) {
|
|
146
|
+
const action = info.running ? pickAction(this.random) : pickSleepingAction(this.random)
|
|
147
|
+
if (action.clipIndex !== existing.clipIndex) dirty = true
|
|
148
|
+
existing.clipIndex = action.clipIndex
|
|
149
|
+
existing.actionEndsAt = now + action.durationMs
|
|
122
150
|
}
|
|
123
151
|
}
|
|
124
152
|
|
package/package.json
CHANGED
package/swift/Package.swift
CHANGED