# Open Data Domain Framework

The Open Data Domain is a closed and independent JavaScript scope. The open data domain is a unique function of WeChat. It allows developers to create a "subdomain", and only in this "subdomain" can they get user-related data.

# Tools to get started quickly

Click Open Data Domain Novice Guide, learn directly in the tool according to the process, and view the Demo.

# Create subdomain entry

To use the open data domain, some configuration is required to specify that certain codes run in the open data domain.

The first part of the work is to create the subdomain entry:

Directory

As shown in the figure, you only need to create a directory (note that this directory must be the openDataContext** directory under the root directory), and write the subdomain code in this directory, and write the code and the main domain in the subdomain There is basically no difference. All the functions of the mini game framework can be used normally, but there will be some restrictions in terms of resources, and some [limitations](#limitations and constraints) will also be generated on the interface. See the following chapters.

After creating the directory and writing the subdomain code, you only need to modify the directory configuration:

Configuration

Check Set as Open Data Domain Folder in the. Then the tool will create a startup template by default, and developers can execute their own logic in the resolve callback of the engineStart() of the corresponding index.ts. For example, engine.loader.load a scene and initialize it. This scenario can only load the code placed in the subdomain folder, and cannot load the main domain. Similarly, the code in the subdomain cannot be used in the main domain.

# Use Scene/Prefab to render content

In order to make it easier for developers to implement rendering, the small game framework supports the direct use of Scene/Prefab rendering in the open data domain, including 2D/3D rendering. This allows developers to easily realize the ability to view friends' 3D skins like the King of Glory.

The framework in the open data domain and the framework in the main domain are two instances, completely isolated. Essentially, the rendering in the open data domain is actually rendered on a cross-domain shared off-screen canvas, and then the content above is drawn as a texture on the canvas of the main screen. Corresponding to the concept of the mini game framework, it is to render the content of the open data field onto a renderTexture, and then in the main field, you can use this renderTexture as a texture to arbitrarily draw on the object in the main field.

Developers can add corresponding script components to Scenes or Prefabs that want to run in the open data domain. These scripts can obtain data such as the relational chain, and then modify the entity in real time to achieve rankings and other capabilities. These codes must be placed in the assets/openDataContext/ directory and can only be used in the open data domain. The code under the directory will run in the open data domain, and the codes in the main domain and the open data domain cannot require each other.

# Download

First, if you want to use Scene/Prefab in the open data domain, you must download the corresponding resources. However, the game resources are relatively large, and it is generally recommended to package them in resource CDN package and deploy them to the developer’s own CDN server. However, due to data security issues, the open data domain cannot download the resources saved by the external CDN, which makes it difficult to realize the capability.

So the small game framework has several solutions for this situation.

-Cloud development storage. Mini game developers can use the official CDN service to upload the completed [resource CDN package] (../../assetworkflow/build.md) to the official cloud development storage. Then any game resource loaded in the open data domain can be downloaded on demand. For example, if you want to realize the ability to view the skin of the King of Glory, because it is impossible to know which skin of your friend is, and it will take a long time to download all the skins in advance, then if you use cloud development and storage, you can click according to the relationship chain data of your friends. Need to download the corresponding skin resources. The developer's code only needs to be loaded just like loading resources in the main domain.

-Put it in the main bag. For the entry resources placed in the main package, the open data field can also be loaded directly. But because it will take up the size of the package, it is recommended not to put it inside.

# Data transfer and sharing texture

The main domain and the subdomain can be considered as completely isolated, but there are still ways to communicate between the two domains.

# Main Domain -> Subdomain

The mini game framework provides a singleton engine.userCrossContextDataBus to manage the communication from the main domain to the subdomain, and its usage is as follows:

// In the main domain, send two messages of type `test` consecutively
engine.userCrossContextDataBus.send('test', {data: 1});
engine.userCrossContextDataBus.send('test', {data: 2});

// In the subdomain, listen for messages of type `test`
engine.userCrossContextDataBus.addReceiver('test', (dataList: {data: number}[]) => {
  console.log(dataList);
});

You can use the singleton send method to send a specific type of message in the main domain, and in the subdomain you can use addReceiver to listen to the message. Each time the message is sent, the frame data will be combined and sent at one time. Of course, there are also removeReceiver method to remove the listener.

# Subdomain -> Main Domain

The subdomain cannot send any message to the main domain through userCrossContextDataBus, and can only share the rendering result by sharing the texture RenderTexture. There are two ways to create a shared texture:

  1. Create and bind within the tool

First, the developer needs to create a rendertexture resource:

Create RT

Then configure it as a shared texture:

Configuration RT

Then set the resource as the rendering target of a camera in the subdomain scene and use it as the texture of the main domain Sprite:

Subdomain Settings RT

Then create a spriteframe resource, set its texture to renderTexture, or use renderTexture as a texture in the material Main Domain Settings RT

You can complete the sharing.

  1. Use code to create bindings
// In the main domain, create a shared RenderTexture
const sharedRT = new engine.RenderTexture({width: 1024, height:1024, isShared: true, uuid: '4444'});

// In the subdomain, also create a shared RenderTexture with the same `uuid`
const sharedRT = new engine.RenderTexture({width: 1024, height:1024, isShared: true, uuid: '4444'});

In this way, the shared textures of the two domains are linked. Developers can use the RenderTexture of the subdomain as the RenderTarget of the camera, and then use the RenderTexture of the subdomain as the Uniform to draw:

// Subdomain, use the shared texture as the rendering target of the UI camera (of course it can be any camera)
game.rootUICamera.renderTarget = shardRT;

// Main domain, use shared texture for rendering of `SpriteFrame`
var ui = game.createEntity2D('ui');
var sp = ui.addComponent(engine.UISprite);
sp.spriteFrame = engine.SpriteFrame.createFromTexture(shardRT);

# Touch event delivery

If you want to draw a leaderboard in the subdomain, you must let the renderTexture also listen to the event, and then pass it to the subdomain, so that the leaderboard can be scrolled with your fingers.

Developers can add two more components to the entity with UISprite components used to render subdomains.

touchInputComponent, originally a component used to monitor touch.

openDataContainer is used to convert touch events into sub-domains according to the size of the main domain's drawing area. The touchInputComponent component used in the scene of the sub-domain can receive a callback.

# Specific operation steps:

-First of all, the developer can right-click any folder under the Project window to create a new >> image >> renderTexture. After selecting it, you can set isShared on in the Inspector window to turn this texture into a cross-domain shared texture.

-Then create an entity with a Camera component in a 3D Scene that you want to render in the subdomain (if it is 2D, create an entity with a UICamera), and set the Camera's renderTarget property to the renderTexture resource, thereby Let the camera draw on this texture. Then you can also create script components in the assets/openDataContext/ directory and add entities to these scripts. These scripts can access the relational chain data and modify the drawing content of the entity. Finally save the scene.

-Right click New >> image >> spriteframe to create a Spriteframe resource, select this SpriteFrame resource, and then assign the renderTexture resource created at the beginning to the Image File property. In this way, the content rendered by the spriteFrame is the content drawn on the renderTexture.

-Create a new entity with a UISprite component in the 2D Scene that will be run in the main domain, and then assign the Spriteframe resource to the spriteFrame property of the UISprite component, indicating that this 2D component will be rendered with the content of this spriteframe, and finally save the scene . (Use openDataContainer as needed)

-Load the scene in the open data domain. First, load the newly created 2D scene in the code of a main domain, and trigger wx.getOpenDataContext(), so that the open data domain will be initialized, and then the Promise returned by engineStart() in assets/openDataContext/index.ts The resolve function will be called back. Developers can add their own code to this callback to load the 2D Scene just now.

engineStart().then(() => {
  engine.loader.load('resource/rank.scene').promise.then((s) => {
    engine.game.playScene(s as engine.Scene)
  })
})

-After completing the above steps, when the game is running, first start the 2D scene from the main domain and trigger the creation of the open data domain. In the creation callback, the 3D scene will be created in the open data domain, and then the camera component will The drawing result is drawn on the renderTexture, and finally drawn on the main screen by the 2D camera of the main domain. The above is just a description of the most basic scenario. Developers can play freely based on the general characteristics of renderTexture. For example, draw the renderTexture on a 3D object through material.

# Restrictions and constraints

In the subdomain, you can use engine.loader.load() to load resources like the main domain, or use new engine.Image() to load images. But there are restrictions on the remote address of the resource.

  • Use engine.loader.load():

    Only the resources uploaded to the storage space of WeChat Cloud Development can be loaded in advance.

  • Use new engine.Image():

    You can load resources in the storage space of WeChat Cloud Development and WeChat user avatar (https://wx.qlogo.cn/mmhead/).

In fact