Skip to content

插件机制

Icemic edited this page Feb 1, 2017 · 1 revision

插件机制

[TOC]

AVG.js 的插件系统使用信号(Signals)供外部调用。

信号(Signals)

信号机制只是 AVG.js 中的订阅/发布模式的名称,与其他程序库的同名概念(如 Qt 的信号)并不相同。信号与一般概念上的事件机制十分相似,都由订阅和发布两个部分组成。不同的是,AVG.js 的信号系统采用了 koa2 的中间件模型,每一个发布出去的「信号」等同于网络访问中的一个请求,而插件系统则是信号的监听和处理者(中间件),中间件的执行顺序采用「洋葱」形式,后面会对其优点进行详细解释。

代码示例

import { core } from 'avg-core';

// 监听一个信号
core.use('signal-name', async (ctx, next) => {
  // do something...
  console.log(ctx.hello);
  console.log(1);
  await next();
  // do something else...
  console.log(4);
});

// 第二处监听
core.use('signal-name', async (ctx, next) => {
  console.log(2)
  await next();
  console.log(3)
});

// 发送一个信号
core.post('signal-name', { hello: 'world!' });

发送信号后,控制台将打印:

world!
1
2
3

发送信号时 .post() 方法的第二个参数可以为空,即传输一个空的 ctx = {}

执行顺序

中间件将按照监听(即执行 .use() 方法)的顺序按照洋葱方式逐层执行。

默认信号

AVG.js 提供了一些默认的信号供使用,同时,在你制定自己的信号名时,注意不要与他们重复。原则上,为了风格统一,我们建议使用全小写字母和短线分隔的方式命名信号,如 my-signalsave-archive

script-exec

用于传递剧情脚本内容。各个功能模块必须监听此信号才能获取到脚本内容。

// 背景音乐模块处理 [bgm ...] 形式的脚本行
core.use('script-exec', async (ctx, next) => {
  const { command, flags, params } = ctx;
  
  if (command === 'bgm') {
    // play sound
  }
  
  await next();
});

该信号通常由脚本模块触发,在 AVG.js 默认配置中,该信号由 Storyscript 模块解析脚本后发送。

注:当脚本处在 Auto 或 Skip 模式时,会自动包含 _auto__skip_ flag。

script-trigger

脚本触发信号,该信号用于通知脚本模块发送下一行脚本的 script-exec 信号。如可监听全局点击、空格键按下等事件,令其发送 script-trigger 信号。

有时我们需要「打断」功能,如点击鼠标跳过当前场景变换或点击鼠标立即完成文本打印,也可以监听 script-trigger 信号,此时不要执行 await next()

script-loading

标记脚本及资源开始加载,可监听此信号以启动 Loading 画面

script-loading-progress

通知脚本及资源加载进度,传递的 context 对象为当前使用的 PIXI Resources Loader 实例。

script-loaded

通知脚本及资源加载完成,可监听此信号以关闭 Loading 画面

script-mode

通知脚本模块开启 Auto 或 Skip 模式,如 core.post('script-mode', { mode: 'skip' }) 为开启 Skip 模式。

Auto 或 Skip 模式将在下次 script-trigger 消息投递时终止。

script-set-autointerval / script-get-autointerval

设置/获取 Auto 模式的等待时间,即每句话打印完成后等待多少毫秒打印下一句话,设置和获取都通过 ctx.autoInterval 值为数字,单位是毫秒。

save-archive

存档信号,只用于向各个功能模块收取要存储的数据,并不负责实际的存储功能

只包含脚本位置和存档变量、处于生命周期中的临时变量,不存储全局存档变量,下同。

// 在 bgm 模块中监听
core.use('save-archive', async (ctx, next) => {
  ctx.data.bgm = { ...要存储的状态信息 }
  await next();
});

// 发送信号
core.post('save-archive', { name: 'save-1', extra: { 任意的额外数据,如预览图和预览文本 } });

该信号可在任何时候发出,如在存档界面点击存档按钮时。

前面提到,该信号不包含数据的存储功能,数据存储功能将由存储插件提供,存储插件中包含对该信号的监听,会自动将数据存入。AVG.js 默认配置中,将自动存储到浏览器存储(Localstorage/IndexesDB)中,下同。

load-archive

读取信号,只用于向各个功能模块分发之前存储的数据,并不负责实际的读取功能

// 发送信号
core.post('load-archive', { name: 'save-1' });

// 在 bgm 模块中监听
core.use('load-archive', async (ctx, next) => {
  // 还原状态信息
  restore(ctx.data.bgm);
  console.log(ctx.time);	// 打印存档时间
  console.log(ctx.extra)	// 打印额外数据
  await next();
});

该信号可在任何时候发出,如在存档界面点击读取按钮时。

remove-archive

删除特定名称的存档,名称通过 ctx.name 传递。

exist-archive

判断特定名称的存档是否存在,名称通过 ctx.name 传递,结果通过 ctx.exist 返回。

list-archive

列出当前的存档名列表,以数组的形式在 ctx.list 中返回。

info-archive

获取存档列表及存档信息(存档时间和额外数据),供存档界面等使用。

数据在 ctx.infos 中返回,格式如:

{
  "save-1": {
    "time": 1485927056049,
    "extra": { ... }
  }
}

save-global

存储全局存档变量,该信号应该由脚本模块发出,由存储模块处理。变量表通过 ctx.globalData 传递,下同。

load-global

读取全局存档变量,该信号应该由脚本模块发出,由存储模块处理。

flow-init

流程控制功能的初始化信号,为脚本系统提供 [flow wait time=1000] 等功能。

localstorage-init

AVG.js 默认的存储插件初始化信号。

storyscript-init

AVG.js 默认的脚本插件初始化信号。

sound-init

AVG.js 默认的音频播放插件初始化信号,为脚本系统提供声音播放等功能。

screenshot-init

截屏插件初始化信号。

screenshot-shot

截屏信号,可传递参数

{
  // 返回的格式,备选:canvas, image, pixels,分别为 Canvas 对象,Image 对象,ArrayBuffer,默认为 Base64 字符串
  type: 'base64',
  // 截屏缩放尺寸,默认为不缩放(画面尺寸)
  width: 800,
  height: 600,
  // 名称,指定名称可缓存多个截图在内存中,默认名为 default
  name: 'default'
}

数据通过 ctx.data 返回,格式为参数规定的格式。

screenshot-get

获取之前的截屏对象,通过 ctx.name 指定名称,通过 ctx.data 返回。

编写插件

目前对插件的格式、引入方式没有统一要求,只要符合解耦的原则,正确使用信号机制即可。