分类目录归档:js

Cocos Creator3d 中使用 protobuf

pb是个好同学

Cocos Creator 3d目前对 protobuf 支持还不是很好, 用传统集成到2d creator方式会遇到很多问题.
这里提供一种最简单(不一定是最好)的方式.

懒人直达 github

说明

protobufjs内建支持 load() 函数加载.proto文件, 稍微改造一下就可以用了.

集成步骤

1. 安装 protobufjs
npm install protobufjs
2. 复制 protobuf.js 到 cocos 项目中, 以插件方式导入
nodejs\node_modules\protobufjs\dist
3. 应用diff

改动diff

diff --git a/protobuf.js b/protobuf.js
index c3e1c02..2114e24 100644
--- a/protobuf.js
+++ b/protobuf.js
@@ -5279,6 +5279,12 @@ function SYNC() {} // eslint-disable-line no-empty-function
  * @returns {undefined}
  */
 Root.prototype.load = function load(filename, options, callback) {
+    var customPBSource = null;
+    if (typeof filename === "function") {
+        var obj = filename();
+        filename = obj.filename;
+        customPBSource = obj.content;
+    }
     if (typeof options === "function") {
         callback = options;
         options = undefined;
@@ -5371,22 +5377,28 @@ Root.prototype.load = function load(filename, options, callback) {
             }
             process(filename, source);
         } else {
-            ++queued;
-            util.fetch(filename, function(err, source) {
-                --queued;
-                /* istanbul ignore if */
-                if (!callback)
-                    return; // terminated meanwhile
-                if (err) {
-                    /* istanbul ignore else */
-                    if (!weak)
-                        finish(err);
-                    else if (!queued) // can't be covered reliably
-                        finish(null, self);
-                    return;
-                }
+            if (customPBSource != null) {
+                // console.log("I'm good boy", filename, customPBSource);
+                source = customPBSource;
                 process(filename, source);
-            });
+            } else {
+                ++queued;
+                util.fetch(filename, function(err, source) {
+                    --queued;
+                    /* istanbul ignore if */
+                    if (!callback)
+                        return; // terminated meanwhile
+                    if (err) {
+                        /* istanbul ignore else */
+                        if (!weak)
+                            finish(err);
+                        else if (!queued) // can't be covered reliably
+                            finish(null, self);
+                        return;
+                    }
+                    process(filename, source);
+                });
+            }
         }
     }
     var queued = 0;

使用方式

var content = `
        syntax = "proto2";
package game.proto;
message GameRequest {
  required string action  = 1;
  required string key     = 2;
  required string uuid    = 3;
  required int64  userId  = 4;
  optional bytes  data    = 5;
}
        `

        var PBReaderFunc = function() {
            return {
                filename: "game.proto",
                content:  content,
            }
        }

        protobuf.load(PBReaderFunc, function(err, root) {
            // console.error(err, root);
            if (err !== null) {
                console.error('加载错误', err);
                return;
            }
            var GameRequest = root.lookupType("game.proto.GameRequest");
            if(GameRequest === null) { // 解析失败了
                return;
            }
            var gameMessage = {
                action: "gameMatching",
                key:    "my-key",
                uuid:   "my-uuid",
                userId:  282,
            }
            // 编码
            var message    = GameRequest.create(gameMessage);
            var binaryData = GameRequest.encode(message).finish()
            console.log("编码二进制数据:", binaryData);
            // 解码
            var msg = GameRequest.decode(binaryData);
            var obj = GameRequest.toObject(msg);
            console.log("解码成对象", obj);
        })