hzengine-core 0.1.2-dev

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.
Files changed (103) hide show
  1. package/dist/async/index.js +162 -0
  2. package/dist/async/zeppos_timer.js +58 -0
  3. package/dist/audio/index.js +260 -0
  4. package/dist/config/index.js +57 -0
  5. package/dist/debug/index.js +8 -0
  6. package/dist/index.js +103 -0
  7. package/dist/platform/index.js +1 -0
  8. package/dist/plugins/basic_command/$.js +8 -0
  9. package/dist/plugins/basic_command/audio.js +40 -0
  10. package/dist/plugins/basic_command/basic.js +124 -0
  11. package/dist/plugins/basic_command/character.js +112 -0
  12. package/dist/plugins/basic_command/conditional.js +260 -0
  13. package/dist/plugins/basic_command/config.js +22 -0
  14. package/dist/plugins/basic_command/decorator.js +24 -0
  15. package/dist/plugins/basic_command/eval.js +67 -0
  16. package/dist/plugins/basic_command/img.js +249 -0
  17. package/dist/plugins/basic_command/index.js +22 -0
  18. package/dist/plugins/basic_command/menu.js +140 -0
  19. package/dist/plugins/global_gesture/index.js +25 -0
  20. package/dist/plugins/transform/animation.js +440 -0
  21. package/dist/plugins/transform/commands.js +38 -0
  22. package/dist/plugins/transform/example_profiles.js +32 -0
  23. package/dist/plugins/transform/hz_anime.js +211 -0
  24. package/dist/plugins/transform/index.js +93 -0
  25. package/dist/script/index.js +537 -0
  26. package/dist/script/readscript.js +15 -0
  27. package/dist/script/strtools.js +157 -0
  28. package/dist/storage/decorator.js +260 -0
  29. package/dist/storage/fs.js +96 -0
  30. package/dist/storage/index.js +442 -0
  31. package/dist/system/index.js +144 -0
  32. package/dist/ui/index.js +535 -0
  33. package/dist/utils/path.js +289 -0
  34. package/license.txt +202 -0
  35. package/package.json +26 -0
  36. package/src/async/index.ts +124 -0
  37. package/src/async/zeppos_timer.js +65 -0
  38. package/src/audio/index.ts +224 -0
  39. package/src/config/index.ts +80 -0
  40. package/src/debug/index.ts +11 -0
  41. package/src/index.ts +122 -0
  42. package/src/platform/index.ts +158 -0
  43. package/src/plugins/basic_command/$.ts +11 -0
  44. package/src/plugins/basic_command/audio.ts +53 -0
  45. package/src/plugins/basic_command/basic.ts +145 -0
  46. package/src/plugins/basic_command/character.ts +144 -0
  47. package/src/plugins/basic_command/conditional.ts +349 -0
  48. package/src/plugins/basic_command/config.ts +29 -0
  49. package/src/plugins/basic_command/decorator.ts +29 -0
  50. package/src/plugins/basic_command/eval.ts +88 -0
  51. package/src/plugins/basic_command/img.ts +317 -0
  52. package/src/plugins/basic_command/index.ts +24 -0
  53. package/src/plugins/basic_command/menu.ts +178 -0
  54. package/src/plugins/global_gesture/index.ts +29 -0
  55. package/src/plugins/transform/animation.ts +542 -0
  56. package/src/plugins/transform/commands.ts +53 -0
  57. package/src/plugins/transform/example_profiles.ts +36 -0
  58. package/src/plugins/transform/hz_anime.ts +214 -0
  59. package/src/plugins/transform/index.ts +141 -0
  60. package/src/plugins/transform/readme.md +1 -0
  61. package/src/script/index.ts +623 -0
  62. package/src/script/readscript.ts +17 -0
  63. package/src/script/strtools.ts +159 -0
  64. package/src/storage/decorator.ts +473 -0
  65. package/src/storage/fs.ts +104 -0
  66. package/src/storage/index.ts +541 -0
  67. package/src/system/index.ts +95 -0
  68. package/src/ui/index.ts +699 -0
  69. package/src/utils/path.js +338 -0
  70. package/tsconfig.json +111 -0
  71. package/types/async/index.d.ts +24 -0
  72. package/types/async/zeppos_timer.d.ts +14 -0
  73. package/types/audio/index.d.ts +64 -0
  74. package/types/config/index.d.ts +9 -0
  75. package/types/debug/index.d.ts +6 -0
  76. package/types/index.d.ts +41 -0
  77. package/types/platform/index.d.ts +134 -0
  78. package/types/plugins/basic_command/$.d.ts +2 -0
  79. package/types/plugins/basic_command/audio.d.ts +2 -0
  80. package/types/plugins/basic_command/basic.d.ts +3 -0
  81. package/types/plugins/basic_command/character.d.ts +2 -0
  82. package/types/plugins/basic_command/conditional.d.ts +2 -0
  83. package/types/plugins/basic_command/config.d.ts +2 -0
  84. package/types/plugins/basic_command/decorator.d.ts +2 -0
  85. package/types/plugins/basic_command/eval.d.ts +2 -0
  86. package/types/plugins/basic_command/img.d.ts +2 -0
  87. package/types/plugins/basic_command/index.d.ts +2 -0
  88. package/types/plugins/basic_command/menu.d.ts +2 -0
  89. package/types/plugins/global_gesture/index.d.ts +2 -0
  90. package/types/plugins/transform/animation.d.ts +131 -0
  91. package/types/plugins/transform/commands.d.ts +7 -0
  92. package/types/plugins/transform/example_profiles.d.ts +2 -0
  93. package/types/plugins/transform/hz_anime.d.ts +51 -0
  94. package/types/plugins/transform/index.d.ts +13 -0
  95. package/types/script/index.d.ts +123 -0
  96. package/types/script/readscript.d.ts +2 -0
  97. package/types/script/strtools.d.ts +31 -0
  98. package/types/storage/decorator.d.ts +41 -0
  99. package/types/storage/fs.d.ts +1 -0
  100. package/types/storage/index.d.ts +86 -0
  101. package/types/system/index.d.ts +35 -0
  102. package/types/ui/index.d.ts +167 -0
  103. package/types/utils/path.d.ts +84 -0
@@ -0,0 +1,65 @@
1
+ /**
2
+ * zeppos-timer.js
3
+ * @description An accurate timer for ZeppOS. 一个适用于ZeppOS的准确的计时器
4
+ * @version 1.0.0
5
+ * @date 2023/04/07
6
+ * @author XiaomaiTX
7
+ * @license MIT
8
+ * https://github.com/XiaomaiTX/zeppos-timer
9
+ *
10
+ * */
11
+ import { Time } from "@zos/sensor";
12
+
13
+ export class ZeppTimer {
14
+ constructor(callback, interval) {
15
+ this.callback = callback;
16
+ this.interval = interval;
17
+ this.timerId = null;
18
+ this.startTime = null;
19
+ this.nextTick = null;
20
+ this.time = new Time();
21
+ this.stopped = false
22
+ }
23
+
24
+ start(delay = 0) {
25
+ this.startTime = this.time.getTime() + delay;
26
+ this.nextTick = this.startTime + this.interval;
27
+ this.scheduleTick();
28
+ }
29
+
30
+ stop() {
31
+ this.timerId && clearTimeout(this.timerId);
32
+ this.stopped = true
33
+ }
34
+
35
+ scheduleTick() {
36
+ if(this.stopped) return
37
+ const currentTime = this.time.getTime();
38
+ const delay = Math.max(0, this.nextTick - currentTime);
39
+ this.timerId = setTimeout(() => {
40
+ this.timerId = null
41
+ this.tick();
42
+ }, delay);
43
+ }
44
+
45
+ tick() {
46
+ const currentTime = this.time.getTime();
47
+
48
+ // 计算误差,确保计时器的准确性
49
+ const error = currentTime - this.nextTick;
50
+
51
+ if (error > this.interval) {
52
+ // 如果误差大于一个间隔时间,则将 nextTick 更新为当前时间
53
+ this.nextTick = currentTime;
54
+ } else {
55
+ // 否则将 nextTick 加上一个间隔时间
56
+ this.nextTick += this.interval;
57
+ }
58
+
59
+ // 调用回调函数
60
+ this.callback();
61
+
62
+ // 继续调度下一个 tick
63
+ this.scheduleTick();
64
+ }
65
+ }
@@ -0,0 +1,224 @@
1
+ // / <reference path="./zos_media.d.ts" />
2
+ // import { create, id } from "@zos/media";
3
+ import { CustomSave, Save } from "../storage/decorator.js";
4
+ import { HZEngineCore } from "../index.js";
5
+
6
+ import { Platform } from "../platform/index.js";
7
+
8
+ export class Audio {
9
+ // static _hmPlayer = create(id.PLAYER);
10
+
11
+ constructor(public _core: HZEngineCore) {
12
+ this._channels["audio"] = new Audio.Channel(this);
13
+ }
14
+
15
+ @CustomSave(
16
+ "audio.channels",
17
+ function (channels) {
18
+ let res = <Record<string, Audio.Channel.Serialized>>{};
19
+ for (let key in channels) {
20
+ res[key] = channels[key].serialize();
21
+ }
22
+ return res;
23
+ },
24
+ function (serialized) {
25
+ // clear exist channels
26
+ for (let key in this._channels) {
27
+ this._channels[key].stop();
28
+ this._channels[key].onRelease();
29
+ }
30
+
31
+ let res = <Record<string, Audio.Channel>>{};
32
+ for (let key in serialized) {
33
+ res[key] = Audio.Channel.deserialize(this, serialized[key]);
34
+ }
35
+ return res;
36
+ }
37
+ )
38
+ private accessor _channels: Record<string, Audio.Channel> = {};
39
+ get channels() {
40
+ return this._channels;
41
+ }
42
+
43
+ createChannel(name: string): Audio.Channel {
44
+ // TODO support more audio channels
45
+ if (Object.getOwnPropertyNames(this._channels).length > 0)
46
+ throw "Can't create more than one audio channel on ZeppOS";
47
+
48
+ if (this._channels[name]) throw "Channel Already Exist";
49
+ return (this._channels[name] = new Audio.Channel(this));
50
+ }
51
+ }
52
+
53
+ export namespace Audio {
54
+ export class Channel {
55
+ // platform specific
56
+
57
+ // universal
58
+ _audioPlayer: Platform.AudioPlayer;
59
+ constructor(public _audio: Audio) {
60
+ this._audioPlayer = _audio._core.platform.createAudioPlayer();
61
+
62
+ this._audioPlayer.onPrepared = (success: boolean) => {
63
+ this._onPrepared(success);
64
+ };
65
+
66
+ this._audioPlayer.onCompleted = () => {
67
+ this._onCompleted();
68
+ };
69
+
70
+ // Audio._hmPlayer.addEventListener(Audio._hmPlayer.event.PREPARE, (res) =>
71
+ // this._onPrepared(res)
72
+ // );
73
+ // Audio._hmPlayer.addEventListener(Audio._hmPlayer.event.COMPLETE, () => {
74
+ // this._onCompleted();
75
+ // });
76
+ }
77
+
78
+ onRelease() {
79
+ this._audioPlayer.release() // TODO
80
+ this._audio._core.platform.releaseAudioPlayer(this._audioPlayer);
81
+ }
82
+
83
+ mode: Channel.Mode = Channel.Mode.PlayInOrder;
84
+ status: Channel.Status = Channel.Status.Stopped;
85
+ _playbackList: PlaybackItem[] = [];
86
+ _nowIndex: number | null = null;
87
+
88
+ currentInfo: AudioInfo | null = null;
89
+
90
+ push(item: PlaybackItem) {
91
+ this._playbackList.push(item);
92
+ }
93
+ play() {
94
+ if (this.status !== Channel.Status.Stopped) return;
95
+ this._playNext();
96
+ }
97
+ pause() {
98
+ if (this.status !== Channel.Status.Playing) return;
99
+ this._audioPlayer.stop();
100
+ this.status = Channel.Status.Stopped;
101
+ }
102
+ /**
103
+ * 停止并清空队列
104
+ */
105
+ stop() {
106
+ if (this.status !== Channel.Status.Playing) return;
107
+ this._audio._core.debug.log("audio channel stop");
108
+ this._audioPlayer.stop();
109
+ this._playbackList = [];
110
+ this.currentInfo = null;
111
+ this._nowIndex = null;
112
+ this.status = Channel.Status.Stopped;
113
+ }
114
+
115
+ serialize(): Channel.Serialized {
116
+ return {
117
+ mode: this.mode,
118
+ status: this.status,
119
+ playbackList: this._playbackList,
120
+ nowIndex: this._nowIndex,
121
+ };
122
+ }
123
+ static deserialize(audio: Audio, data: Channel.Serialized): Channel {
124
+ let channel = new Channel(audio);
125
+ channel.mode = data.mode;
126
+ channel.status = data.status;
127
+ channel._playbackList = data.playbackList;
128
+ channel._nowIndex = data.nowIndex;
129
+ if (channel.status === Channel.Status.Playing) channel._playNext();
130
+ return channel;
131
+ }
132
+
133
+ _onPrepared(result: boolean) {
134
+ if (result) {
135
+ let mediaInfo = this._audioPlayer.getMediaInfo();
136
+ this.currentInfo = {
137
+ // placeholder
138
+ artist: mediaInfo.artist ?? "未知",
139
+ title: mediaInfo.title ?? "未知",
140
+ duration: mediaInfo.duration,
141
+ };
142
+ console.log("=== prepare succeed ===");
143
+ this._audioPlayer.start();
144
+ } else {
145
+ console.log("=== prepare fail ===");
146
+ this.status = Channel.Status.Error;
147
+ this._audioPlayer.release();
148
+ }
149
+ }
150
+
151
+ _onCompleted() {
152
+ // update playback list
153
+ if (this.mode === Channel.Mode.PlayInOrder) {
154
+ this._playbackList.shift();
155
+ if (this._playbackList.length > 0) this._nowIndex = 0;
156
+ else this._nowIndex = null;
157
+ } else if (this.mode === Channel.Mode.PlayInOrderRepeat) {
158
+ if (this._playbackList.length > 0) {
159
+ if (this._nowIndex === null) this._nowIndex = 0;
160
+ this._nowIndex = (this._nowIndex + 1) % this._playbackList.length;
161
+ } else this._nowIndex = null;
162
+ }
163
+
164
+ this._playNext();
165
+ }
166
+
167
+ /**
168
+ * Play the next item in the playback list. If there are no items in the
169
+ * playback list, set the channel status to Stopped and return.
170
+ * @private
171
+ */
172
+ _playNext() {
173
+ if (this._playbackList.length === 0) {
174
+ this._nowIndex = null;
175
+ this.status = Channel.Status.Stopped;
176
+ return;
177
+ }
178
+
179
+ if (this.mode === Channel.Mode.PlayInOrder) {
180
+ if (this._nowIndex === null) this._nowIndex = 0;
181
+ // otherwise onCompleted will set _nowIndex to next index
182
+ } else if (this.mode === Channel.Mode.PlayInOrderRepeat) {
183
+ if (this._nowIndex === null) this._nowIndex = 0;
184
+ // otherwise onCompleted will set _nowIndex to next index
185
+ }
186
+
187
+ // Audio._hmPlayer.setSource(Audio._hmPlayer.source.FILE, {
188
+ // file: this._playbackList[this._nowIndex!].path,
189
+ // });
190
+ this._audioPlayer.setSource({
191
+ path: this._playbackList[this._nowIndex!].path,
192
+ });
193
+
194
+ this._audioPlayer.prepare();
195
+
196
+ this.status = Channel.Status.Playing;
197
+ }
198
+ }
199
+ export namespace Channel {
200
+ export enum Mode {
201
+ PlayInOrder,
202
+ PlayInOrderRepeat,
203
+ }
204
+ export enum Status {
205
+ Stopped,
206
+ Playing,
207
+ Error,
208
+ }
209
+ export type Serialized = {
210
+ mode: Channel.Mode;
211
+ status: Channel.Status;
212
+ playbackList: PlaybackItem[];
213
+ nowIndex: number | null;
214
+ };
215
+ }
216
+ export interface PlaybackItem {
217
+ path: string;
218
+ }
219
+ export interface AudioInfo {
220
+ duration: number;
221
+ title: string;
222
+ artist: string;
223
+ }
224
+ }
@@ -0,0 +1,80 @@
1
+ import { HZEngineCore } from "../index.js";
2
+
3
+ export class Config {
4
+ constructor(private _core: HZEngineCore) {
5
+ _core.on("initGlobalData", () => {
6
+ _core.storage.setSaveableData(
7
+ _core.storage.globalData,
8
+ true,
9
+ { ...defaultConfig },
10
+ "config"
11
+ );
12
+ });
13
+ _core.on("afterLoadGlobalData", () => {
14
+ if (!(_core.storage.globalData as any)?.config) {
15
+ _core.storage.setSaveableData(
16
+ _core.storage.globalData,
17
+ true,
18
+ { ...defaultConfig },
19
+ "config"
20
+ );
21
+ }
22
+ _core.storage.saveGlobalData();
23
+ });
24
+ }
25
+
26
+ getConfig(key: string) {
27
+ let keys = this.normalizeKey(key);
28
+ // this._core.debug.log(`getConfig keys = ${JSON.stringify(keys)}`);
29
+
30
+ if (keys == null) return;
31
+ try {
32
+ let res = this._core.storage.getSaveableData(
33
+ this._core.storage.globalData,
34
+ false,
35
+ "config",
36
+ ...keys
37
+ );
38
+ // this._core.debug.log(`getConfig res = ${JSON.stringify(res)}`);
39
+ return res;
40
+ } catch (e) {
41
+ // this._core.debug.log(`getConfig error`,e);
42
+ return;
43
+ }
44
+ }
45
+
46
+ setConfig(key: string, value: any) {
47
+ let keys = this.normalizeKey(key);
48
+ if (keys == null) return;
49
+ this._core.storage.setSaveableData(
50
+ this._core.storage.globalData,
51
+ true,
52
+ value,
53
+ "config",
54
+ ...keys
55
+ );
56
+
57
+ this._core.storage.saveGlobalData();
58
+ }
59
+
60
+ private normalizeKey(key: string): string[] | null {
61
+ let keys = <string[]>[];
62
+ key.split(".").forEach((key) => {
63
+ if (key.trim().length > 0) keys.push(key);
64
+ else return null;
65
+ });
66
+ return keys;
67
+ }
68
+
69
+ resetConfig() {}
70
+ }
71
+
72
+ const defaultConfig = {
73
+ game: {
74
+ autoplay: {
75
+ enable: false,
76
+ ms_per_char: 150,
77
+ extra_delay: 1300,
78
+ },
79
+ },
80
+ };
@@ -0,0 +1,11 @@
1
+ import { HZEngineCore } from "../index.js";
2
+
3
+ export class Debug {
4
+ constructor(private _core: HZEngineCore) {
5
+
6
+ }
7
+
8
+ log(...args: any[]) {
9
+ console.log("[HZEngine]", ...args);
10
+ }
11
+ }
package/src/index.ts ADDED
@@ -0,0 +1,122 @@
1
+ /**
2
+ * HZEngineCore
3
+ * @copyright Copyright (c) 2024 CuberQAQ. All rights reserved.
4
+ */
5
+
6
+ import { Async } from "./async/index.js";
7
+ import { Audio } from "./audio/index.js";
8
+ import { Config } from "./config/index.js";
9
+ import { Debug } from "./debug/index.js";
10
+ import Platform from "./platform/index.js";
11
+ import { basic_command } from "./plugins/basic_command/index.js";
12
+ import { global_gesture } from "./plugins/global_gesture/index.js";
13
+ import { registerPlugin } from "./plugins/transform/index.js";
14
+ import { Script } from "./script/index.js";
15
+ import { Storage } from "./storage/index.js";
16
+ import { System } from "./system/index.js";
17
+ import { UI } from "./ui/index.js";
18
+
19
+ class HZEngineCore<PlatformType extends Platform = any> {
20
+ private _eventCallbacks: Map<string, Set<Function>> = new Map();
21
+ public storage;
22
+ public async;
23
+ public ui;
24
+ public script;
25
+ public system;
26
+ public config;
27
+ public audio;
28
+ public debug;
29
+ constructor(public platform: PlatformType) {
30
+ // 請不要調整這裡的初始化順序,不然會有問題(裝飾器裡有時候要用到前面初始化的東西)
31
+ this.storage = new Storage(this);
32
+ this.async = new Async(this);
33
+ this.ui = new UI(this);
34
+ this.script = new Script(this);
35
+ this.system = new System(this);
36
+ this.config = new Config(this);
37
+ this.audio = new Audio(this);
38
+ this.debug = new Debug(this);
39
+
40
+ // internal plugin
41
+ this.loadPlugin("global_gesture", global_gesture);
42
+ this.loadPlugin("transform", registerPlugin);
43
+ this.loadPlugin("basic_command", basic_command);
44
+ }
45
+ loadProject(options: {
46
+ projectPath: string;
47
+ cachePath: string;
48
+ savePath: string;
49
+ }) {
50
+ this.storage.loadProject(options);
51
+ }
52
+ start(callback?: () => unknown) {
53
+ // this.system.start()
54
+ Async.nextTick(() => {
55
+ this.debug.log("[HZEngine] Game Start");
56
+ let title = this.storage.packageData?.name;
57
+ if (title == null) {
58
+ throw `[HZEngine] project name is null, please loadProject first or check your project.json format`;
59
+ }
60
+ this.ui.getRouter("page")!.push("title", {
61
+ title,
62
+ });
63
+
64
+ // this.on("gameEnd", () => {
65
+ // let router = this.ui.getRouter("page")!;
66
+ // if (router.length > 0) return;
67
+ // router.push("title", {
68
+ // title,
69
+ // });
70
+ // });
71
+ callback?.();
72
+ });
73
+ }
74
+
75
+ end() {
76
+ this.debug.log("[HZEngine] Game End, return to title");
77
+
78
+ let title = this.storage.packageData?.name;
79
+ if (title == null) {
80
+ throw `[HZEngine] project name is null, please loadProject first or check your project.json format`;
81
+ }
82
+
83
+ this.system.condition = System.Condition.Free;
84
+
85
+ this.ui.resetUI();
86
+
87
+ if (this.ui.getRouter("page")!.length > 0) return;
88
+ this.ui.getRouter("page")!.push("title", {
89
+ title,
90
+ });
91
+ }
92
+
93
+ public plugins: Map<string, unknown> = new Map();
94
+ // Load Plugin
95
+ loadPlugin(name: string, plugin: Plugin<PlatformType>) {
96
+ this.debug.log(`[HZEngine] load plugin [${name}]`);
97
+ let slot = plugin(this);
98
+ if (slot != undefined) this.plugins.set(name, slot);
99
+ }
100
+
101
+ // Event Bus
102
+ on(event: string, cb: Function) {
103
+ if (this._eventCallbacks.has(event)) {
104
+ this._eventCallbacks.get(event)!.add(cb);
105
+ } else {
106
+ this._eventCallbacks.set(event, new Set<Function>().add(cb));
107
+ }
108
+ }
109
+ off(event: string, cb: Function): boolean {
110
+ return !!this._eventCallbacks.get(event)?.delete(cb);
111
+ }
112
+ emit(event: string, ...args: any[]) {
113
+ this._eventCallbacks.get(event)?.forEach((cb) => {
114
+ cb(...args);
115
+ });
116
+ }
117
+ }
118
+
119
+ type Plugin<PlatformType extends Platform> = (core: HZEngineCore<PlatformType>) => any;
120
+
121
+ export { HZEngineCore, UI, Storage, Script, System, Async, type Platform };
122
+ export * as TransformPlugin from "./plugins/transform/index.js";
@@ -0,0 +1,158 @@
1
+ export interface Platform<WidgetFactory = any> {
2
+ name: string;
3
+
4
+ // screen
5
+ getScreenSize(): [width: number, height: number];
6
+
7
+ // ui
8
+ createUILayer({ z_index }: { z_index: number }): WidgetFactory;
9
+ deleteUILayer(widgetFactory: WidgetFactory): void;
10
+
11
+ // fs
12
+ isFileSync({ path }: { path: string }): boolean;
13
+ readdirSync(option: Platform.readdirSync.Option): Platform.readdirSync.Result;
14
+ statSync(option: Platform.statSync.Option): Platform.statSync.Result;
15
+ readFileSync(option: Platform.readFileSync.Option): Platform.readFileSync.Result;
16
+ writeFileSync(option: Platform.writeFileSync.Option): void;
17
+
18
+
19
+
20
+ getImageInfo(img_path: string): {
21
+ width: number;
22
+ height: number;
23
+ };
24
+
25
+ // timer & async
26
+ getTime(): number; // in Utc
27
+
28
+ // audio
29
+ createAudioPlayer(): Platform.AudioPlayer;
30
+ releaseAudioPlayer(audio_player: Platform.AudioPlayer): void;
31
+
32
+ setFrameInterval(callback: () => void): void;
33
+ }
34
+
35
+ export declare namespace Platform {
36
+
37
+
38
+ export interface AudioPlayer {
39
+ onPrepared?: (success: boolean) => void | undefined;
40
+ onCompleted?: () => void | undefined;
41
+ prepare(): void;
42
+ start(): void;
43
+ stop(): void;
44
+ release(): void;
45
+ getMediaInfo(): MediaInfo;
46
+ setSource({ path }: { path: string }): void;
47
+ }
48
+
49
+ export interface MediaInfo {
50
+ title: string | undefined;
51
+ artist: string | undefined;
52
+ duration: number;
53
+ }
54
+
55
+ export namespace readdirSync {
56
+ interface Option {
57
+ /**
58
+ * @zh 目录路径
59
+ * @en Directory path
60
+ */
61
+ path: string;
62
+ }
63
+
64
+ /**
65
+ * @zh 如果返回 `undefined` 则目录不存在,否则返回文件名数组
66
+ * @en If `undefined` is returned, the directory does not exist, otherwise an array of filenames is returned
67
+ */
68
+ type Result = Array<string> | undefined;
69
+ }
70
+
71
+ export namespace statSync {
72
+ interface Option {
73
+ /**
74
+ * @zh 路径
75
+ * @en path
76
+ */
77
+ path: string;
78
+ }
79
+
80
+ /**
81
+ * @zh 如果返回 `undefined` 则目标文件不存在,否则返回文件信息对象
82
+ * @en If `undefined` is returned, the target file does not exist, otherwise the file information object is returned
83
+ */
84
+ type Result = FSStat | undefined;
85
+
86
+ /**
87
+ * @output
88
+ */
89
+ interface FSStat {
90
+ /**
91
+ * @zh 文件大小(单位为字节)
92
+ * @en The size of the file in bytes
93
+ */
94
+ size: number;
95
+ }
96
+ }
97
+
98
+ export namespace readFileSync {
99
+ interface Option {
100
+ /**
101
+ * @zh 文件路径
102
+ * @en path
103
+ */
104
+ path: string;
105
+ /**
106
+ * @zh 其他选项
107
+ * @en Other Options
108
+ */
109
+ options?: Options;
110
+ }
111
+
112
+ interface Options {
113
+ /**
114
+ * @zh 当指定了编码方式之后,API 返回结果为 `string`
115
+ * @en When the encoding method is specified, the API returns `string` as the result
116
+ */
117
+ encoding?: string;
118
+ }
119
+
120
+ /**
121
+ * @zh 文件内容。如果返回 `undefined`,则表明读取文件失败
122
+ * @en File content. If `undefined` is returned, the file failed to be read
123
+ */
124
+ type Result = ArrayBuffer | string | undefined;
125
+ }
126
+
127
+ export namespace writeFileSync {
128
+ interface Option {
129
+ /**
130
+ * @zh 文件路径或者文件句柄
131
+ * @en File path or file descriptor
132
+ */
133
+ path: string | number;
134
+ /**
135
+ * @zh 写入目标文件的数据
136
+ * @en Data to be written to the target file
137
+ */
138
+ data: ArrayBuffer | string | DataView;
139
+ /**
140
+ * @zh 其他选项
141
+ * @en Other Options
142
+ */
143
+ options?: Options;
144
+ }
145
+
146
+ interface Options {
147
+ /**
148
+ * @zh 如果数据格式为 `string`,需要指定编码方式
149
+ * @en If the `data` format is `string`, you need to specify the encoding method
150
+ * @defaultValue utf8
151
+ */
152
+ encoding?: string;
153
+ }
154
+ }
155
+ }
156
+
157
+
158
+ export default Platform;
@@ -0,0 +1,11 @@
1
+ import { HZEngineCore } from "../../index.js";
2
+
3
+ export function $_command(core: HZEngineCore) {
4
+
5
+ core.script.use((ctx, next) => {
6
+ if(ctx.rawtext.trim().startsWith("$")) {
7
+ ctx.rawtext = "eval " + ctx.rawtext.trim().slice(1).trim()
8
+ }
9
+ return next()
10
+ })
11
+ }