Shadow Instance Implementation 影子实例系统的实现细节

有关影子实例系统的基本设计可以参考 影子实例(Shadow Instance) 章节。 接下来的章节将会默认你知道影子实例的基本状况,进而对如何实现的进行讲解。

对象库(Object Store)

为了实现对象的同步,我们需要有一个机构(Module)对这些对象(Object)进行管理。这个机构就叫做 对象库。在沙箱内(Worker端)和沙箱外(Host端)都需要有一个对象库,而且这两个库需要时刻保持同步, 这才能保障有效的影子实例实现。

唯一的ID(Unique ID)

由于我们需要区分不同的Object,一个便利的方法是通过给对象颁发“身份证”(Unique Identification) 而这个办法ID的机构就是对象库。

对象库会根据:对象类型,生成时间,库序列和随机数生成一个唯一的ID,如果这个ID与库内其余对象没有冲突, 那么ID就会输出。 由于Object一旦注册,库序列就会发生变化,ID就不会产生冲撞。每一毫秒可以产出4096 个非注册ID和无限多个注册ID。生成时间是为了调试便利和增加唯一性。

具体算法请参考 Runtime.generateId()

对应关系(Mapping)

有了ID就需要一个可以入库管理关系的机制。在本质上,对象库就是一个大哈希表(Hash Map)对应ID于对象 以方便迅速查找和派发event。

Runtime定义了基础的可以被管理的对象,必须提供以下三个接口:

  • getId() : 返回该对象的唯一ID
  • serialize() : 返回一个可以表示这个对象的对象,不得超过JSON允许的种类子集。
  • dispatchEvent(event) : 接口用于派发Event。

提供了如下接口的Object就都可以注册入对象库,前提是它们的ID不与前者冲撞。由于生成ID的方式,我们可以 保证新的ID不会与库中既在的ID冲突,所以只要使用generateId()即可保障这个约束条件。 同时,同一个Object不能注册两次,也就是说同一个ID只能注册一次。

特殊对象/元对象(Meta Object)

特殊对象包括播放器,舞台对象等。它们不是由ID派发而出的,因为它们总存在,所以由手写的ID产生。在 Kagerou Engine里面,分别使用了__player__root__self

在Runtime里面,我们的定义是,对于任何ID开头是两个下划线的,视其为特殊对象。这些特殊对象在 clear()reset() 时不会被去掉,依然存在于对象库中。所以非常适合表示一些超脱于正常对象的常在 的对应关系。

事件派发(Event Dispatching)

对于特殊对象,也有特殊的派发方式,我们暂且不讨论。

对于普通的对象,Runtime会打开一个新的信道,监听有关此Object的信息。在信道上传输的信息则会被派发到 Object上。这个信道用于派发监听器,同时也用于接受消息,如外部摧毁Object的消息。