Detailed explanation of CocosCreator message distribution mechanism

Detailed explanation of CocosCreator message distribution mechanism

Overview

This article begins to introduce content related to game business architecture. At the game business layer, all systems that need to be isolated and communications between modules can be decoupled through message distribution. For example, network return notifications, data updates synchronized to the interface, etc.

Message distribution is designed based on the observer pattern. The place where the message needs to be processed registers the listening callback with the message center. When the message is dispatched, the dispatch interface of the message center is called to traverse the listening queue of the message and call the corresponding callback method.

Specific plan

First define the listening callback type

/**
 * Message monitoring callback method */
export type NotifyListener = (src: any, data: any) => void;

Save the listening queue by key-value

private static msg2listDict: Dictionary< string, Array<NotifyListenerInfo> > = new Dictionary< string, Array<NotifyListenerInfo> >();

Interface Definition

/**
 * Add multiple listeners, need to remove manually * @param msg
 * @param listener
 * @param target
 */
public static addListener(msg: string, listener: NotifyListener, target?: any): void {}
 
/**
 * Add a one-time listener and remove it after the event is triggered* @param msg
 * @param listener
 * @param target
 */
public static addOnceListener(msg: string, listener: NotifyListener, target?: any): void {}
 
/**
 * Remove the listener specified by the specified message * @param msg
 * @param listener
 */
public static removeMsgListener(msg: string, listener: NotifyListener): void {}
 
/**
 * Remove all listeners of the specified message * @param msg
 */
public static removeMsgAllListeners(msg: string): void {}
 
/**
 * Remove the specified target's monitoring of the specified message * @param msg
 * @param target
 */
public static removeTargetMsgListen(msg: string, target: any): void {}
 
/**
 * Remove all message listeners of the specified target * @param target
 */
public static removeTargetAllMsgListen(target: any): void {}
 
/**
 * Send message * @param msg
 * @param src
 * @param data
 */
public static notify(msg: string, src: any, data: any): void {}

In the add and remove implementation, you need to be aware that a message may be being dispatched.

For a newly added listener of a message, it should be distributed after the current queue message is distributed. Therefore, add a queue to be added

private static listener2add: Array<NotifyListenerInfo> = [];

Make the following judgment when adding a listener

// The message is being dispatched and put into the queue to be added if (NotifyCenter.notifyMsgs.indexOf(msg) >= 0) {
    NotifyCenter.listener2add.push(info);
    return;
}

Similarly, when removing the listener, the message may be dispatched. To avoid the modification of the queue causing the for loop exception, add a queue to be removed. When dispatching the message, if the listener is in the removal queue, it will not be dispatched. After the message is dispatched, remove it from the queue

private static listener2remove: Array<NotifyListenerInfo> = [];

Make the following judgment when removing the listener

// The message is being dispatched and put into the queue to be removed if (NotifyCenter.notifyMsgs.indexOf(msg) >= 0) {
    NotifyCenter.listener2remove.push(list[i]);
} else {
    list.splice(i, 1);
}

When dispatching a message, iterate through the queues under the specified message

// The queue does not exist, no need to process let list = NotifyCenter.msg2listDict.get(msg);
if (!list) {
    return;
}
 
// Mark the message as being dispatched. Multiple messages may be dispatched at the same time. The same message may be marked multiple times. NotifyCenter.notifyMsgs.push(msg);
 
// Process message dispatch for (let i = 0, n = list.length; i < n; i++) {
    NotifyCenter._dispatch(list[i], src, data, false);
}

When dispatching a message, first determine whether the queue is being removed

// In the removal queue, no dispatch if (NotifyCenter.listener2remove.indexOf(info) >= 0) {
    return;
}

After the current queue is dispatched, check the queue to be added

// Process the queue to be added for (let i = 0, n = msg2add.length; i < n; i++) {
    if (listener2add[i].msg == msg) {
        NotifyCenter._dispatch(listener2add[i], src, data, true);
    }
}

A message distribution center is introduced to allow isolated systems and modules to communicate through message monitoring and dispatching to avoid mutual reference coupling.

The above is a detailed explanation of the CocosCreator message distribution mechanism. For more information about CocosCreator message distribution, please pay attention to other related articles on 123WORDPRESS.COM!

You may also be interested in:
  • How to use JSZip in vue.js to decompress files on the front end
  • Interpretation of CocosCreator source code: engine startup and main loop
  • CocosCreator general framework design resource management
  • How to make a List in CocosCreator
  • Analysis of CocosCreator's new resource management system
  • CocosCreator Skeleton Animation Dragon Bones
  • How to draw a cool radar chart in CocosCreator
  • Detailed explanation of CocosCreator MVC architecture
  • How to use JSZip compression in CocosCreator

<<:  Detailed explanation of the order of Mysql query results according to the order of ID in in()

>>:  The best way to start a jar package project under Centos7 server

Recommend

Vue2/vue3 routing permission management method example

1. There are generally two methods for Vue routin...

How to implement Mysql switching data storage directory

How to implement Mysql switching data storage dir...

How to connect to a remote docker server with a certificate

Table of contents 1. Use scripts to encrypt TLS f...

Solution to Element-ui upload file upload restriction

question Adding the type of uploaded file in acce...

Detailed example of MySQL joint table update data

1.MySQL UPDATE JOIN syntax In MySQL, you can use ...

JavaScript implements simple calculator function

This article shares the specific code of JavaScri...

jQuery manipulates cookies

Copy code The code is as follows: jQuery.cookie =...

Example of using nested html pages (frameset usage)

Copy code The code is as follows: <!DOCTYPE ht...

About scroll bar in HTML/removing scroll bar

1. The color of the scroll bar under xhtml In the ...

Practice of using SuperMap in Vue

Table of contents Preface Related Materials Vue p...

Using JS to implement a rotating Christmas tree in HTML

<!DOCTYPE HEML PUBLIC> <html> <hea...