A.環境の準備
私が模索されているココスH5正しい姿勢開発など、nodejs、NPMやイサキ足場ツールを、javascriptを現在行ってプロジェクトが不可分となっています。
1.初期化ファイルpackage.json
NPM熱
ときに、プロジェクトのルートディレクトリに使用される新しい良いココス-JSまたは作成者のアイテムNPMのinitコマンド、ラウンドすべての方法は、現在のディレクトリに作成されますpackage.jsonの nodejs三者管理モジュールのファイル。ネットワーク上の詳細については、ここでは詳しく説明していない多くのチュートリアルがありますNPM。
2. protobufjsモジュール
彼は最初cocos2dx 2.xの時代に始まったたprotobufjsの今までいるProtobufを操作するためのモジュール。そこで、以下の内容の全ては、ネイティブプラットフォーム(cocos2d-JSが似ている)を含む、protobufjsココス作成者に使用されています。
protobufjsをインストールするためのプロジェクト
NPM 5 --save @ protobufjsをインストール
NPM私たちがここで使うノートはprotobufjs 5.xのバージョンでは、モジュールをインストールするにはinstallコマンドを使用します。protobufjs最新バージョン6.xが、TS、RPCサポート、およびその他の機能を提供していますが、動的にマイクロ文字のファイルプロト小さなゲームでロードすることができないという問題があります。
グローバルにインストールprotobufjs
ASLインストール-g protobufjs @ 5
グローバルパラメータに取り付けられた-gモジュールをインストールNPM使用し、主な目的は、コンビニエンスpbjs protobufjsコマンドラインツールを提供することです。異なる負荷プロト方法を提供するようにpbjsはプロト元のファイルは、JS、JSONに変換することができ、私たちは自分の状況に応じて選択することができます。
二つ。Protobufjsの使用状況
ここで定義されたデモファイルPlayer.protoの内容は、
syntax = "proto3";
package grace.proto.msg;
message Player {
uint32 id = 1; //唯一ID 首次登录时设置为0,由服务器分配
string name = 2; //显示名字
uint64 enterTime = 3; //登录时间
}
ここでは具体的な構文についてプロトの詳細が言っているのではない、私たちはどのようにJSでインスタンスファイルに定義されたプレイヤオブジェクトPlayer.proto、プロパティの割り当て、シリアライズ、デシリアライゼーションの操作に焦点を当てます。
1.静的言語使用プロトファイル
通常、このようなC ++ / Javaコードに公式プロトファイルをコンパイルしますprotocコマンドを使用するように/ javaの静的言語C ++でいるProtobufを使用します。
xxx.proto protoc --cpp_out =出力経路
Protoc --java_out =出力経路xxx.proto
言語工学に対応するインポートされたファイルの出力パスを使用します。
2.プロジェクトの作成者でプロトファイルを使用します
Javascriptを、実行時にオブジェクトを生成することができ、動的言語であるため、より便利protobufjsに動的コンパイルを提供し、ファイル内のプロト・オブジェクトを簡単に作成者の使用中に、以下の具体的な手順を説明し、JSのオブジェクトを生成しました:
1.ファイルとコンパイル済みのプロトプロト・オブジェクトをロードします
//导入protobufjs模块
let protobuf = require("protobufjs");
//获取一个builder对象
let builder = protobuf.newBuilder();
//使用protobufjs加文件,并与一个builder对象关联
protobuf.protoFromFile('xxx.proto', builder);
protobuf.protoFromFile('yyy.proto', builder);
...
let PB = builder.build('grace.proto.msg');
この操作は、主にprotobufjsロードされ、コンパイル済みのプロトファイルを使用しています。
プロトオブジェクト属性の割り当ての2例
let PB = builder.build('grace.proto.msg')
PBは、機能を構築する次のように返す値オブジェクトは、すべてのメッセージが含まれているオブジェクトをプロトで定義されているが、今、JSオブジェクトをインスタンス化することが可能になります。
//实例化Player
let player = new PB.Player();
//属性赋值
player.name = '张三';
player.enterTime = Date.now();
オブジェクトの直列化および直列化防止3.proto
コードにはでたらめない、または直接
...
//使用实例对象上的toArrayBuffer函数将对象序列化为二进制数据
let data = player.toArrayBuffer();
//使用类型对象上的decode函数将二进制数据反序列化为实例对象
let otherPlayer = PB.player.decode(data);
運がよけれ場合は、上記のコードを実行するとJSB環境の下で、あなたは何が起こっているかの悲しいリマインダーを経験するとき、あなたは、ウェブ上でのみ行う理由をウェブ上でいるProtobuf使用することができます。
III。Protobufjsはココス-JSB節約します
なぜたむろネイティブで実行しますか?この問題を理解するには、ココス、JSB 3つのjavascriptを実行しているホスト環境が一定の理解を持っている\ nodejsブラウザが必要です。
私はnodejsモジュールを選択する際に、限り純粋なJSモジュールは、一般的に容易なように非同期、undersocre、lodashとして、ココスで使用することができるよう、nodejsとウェブをサポートするかどうかに注意を払う前の記事で述べました。
protobufjsこのモジュールは、ブラウザとnodejs環境では非常に良い実行されます。しかし、それはココス-JSB上で実行されている問題になります、私たちは問題にキーコードを検索する必要があります。
protobuf.protoFromFile('xxx.proto', builder);
1.分析
この操作をファイルに関連ロードするファイル、ロードされたファイルのことを考え、APIであるという観点からProtobuf.protoFromFile関数名は、我々は、異なるプラットフォーム上のファイルインタフェースを整理する必要があります。
ホストプラットフォーム | ファイルインタフェース | 説明 |
---|---|---|
ブラウザ | XMLHttpRequestの | 基本的なブラウザは、動的なファイルAJAX操作などのリソースをロードします |
nodejs | fs.readFile / fs.readFileSync | 基礎となるC / C ++で実装されたファイル操作モジュールnodejs、 |
ココスなど | jsb.fileUtils.getStringFromFile | 根本的に異なることによって達成さ無段階のプラットフォームで提供されたファイル・インタフェースココス-JSの内容を読む(IOSは、Android \ WINDOWS \を)API |
私は多くの人がココス-JSBに問題がある理由を理解する必要があると信じてここを参照してください、私たちはprotobufjsソースを読んでみましょう、私たちの分析が確認されました。
2.分析protobufjsソース
メインコードはprotobufjsがファイルをロード発見され、私は、ソースコードに次のようなコメントを追加し、慎重に脚注をお読みください。
Util.fetch = function(path, callback) {
//检查callback参数,callback参数决定是否为异步加载
if (callback && typeof callback != 'function')
callback = null;
//运行环境是否为nodejs
if (Util.IS_NODE) {
//加载nodejs的文件系统模块
var fs = require("fs");
//检查是否有callback,存在使用fs.readFile异步函数读取文件内容
if (callback) {
fs.readFile(path, function(err, data) {
if (err)
callback(null);
else
callback(""+data);
});
} else
//使用fs.readFileSync同步函数读取文件内容
try {
return fs.readFileSync(path);
} catch (e) {
return null;
}
} else {
//当不为nodejs运行环境使用XmlHttpRequest加载文件
var xhr = Util.XHR();
//根据callbcak参数是否存在,使用异步还是同步方式
xhr.open('GET', path, callback ? true : false);
// xhr.setRequestHeader('User-Agent', 'XMLHTTP/1.0');
xhr.setRequestHeader('Accept', 'text/plain');
if (typeof xhr.overrideMimeType === 'function') xhr.overrideMimeType('text/plain');
//通过XmlHttpRequest.onreadystatechange事件函数异步获取文件数据
if (callback) {
xhr.onreadystatechange = function() {
if (xhr.readyState != 4) return;
if (/* remote */ xhr.status == 200 || /* local */ (xhr.status == 0 && typeof xhr.responseText === 'string'))
callback(xhr.responseText);
else
callback(null);
};
if (xhr.readyState == 4)
return;
//调用send方法发起AJAX请求
xhr.send(null);
} else {
////调用send方法发起AJAX请求,同步获取文件数据
xhr.send(null);
if (/* remote */ xhr.status == 200 || /* local */ (xhr.status == 0 && typeof xhr.responseText === 'string'))
return xhr.responseText;
return null;
}
}
};
上記のコードから、protobufjsライブラリは、ブラウザとnodejsの準備ができている見ることができ、さらには、JSBココスの存在を考えられなかった(Tucao:それはnodejsココス公式のオファーを模倣できるインターフェイスは非常に多くの物事が小さいことが推奨される)におけるので、ココス- JSBはprotobufjsを使用方法は、次のようにprotobufjsソースを変更されました:
Util.fetch = function(path, callback) {
if (callback && typeof callback != 'function')
callback = null;
//将平台检查代码改为cocos提供的接口
if (cc.sys.isNative) {
//文件读取使用cocos-jsb提供的函数
try {
let data = jsb.fileUtils.getStringFromFile(path);
cc.log(`proto文件内容: {data}`);
return data;
} catch (e) {
return null;
}
} else {
//web端无需修改,略
...
};
我々は問題をロードし、コードを変更するインターフェイスが解決されたココス、問題が本当に解決しましたか?
次のように申し訳ありませんが、コードを変更する必要がある上記のほかに、コードは、ソースコードは次のとおりです。
BuilderPrototype["import"] = function(json, filename) {
var delim = '/';
// Make sure to skip duplicate imports
if (typeof filename === 'string') {
//这里又出现了平台检查
if (ProtoBuf.Util.IS_NODE)
// require("path")是加载nodejs的path模块,resolve
filename = require("path")['resolve'](filename);
if (this.files[filename] === true)
return this.reset();
this.files[filename] = true;
} else if (typeof filename === 'object') { // Object with root, file.
var root = filename.root;
//这里还要修改
if (ProtoBuf.Util.IS_NODE)
root = require("path")['resolve'](root);
if (root.indexOf("\\") >= 0 || filename.file.indexOf("\\") >= 0)
delim = '\\';
var fname;
//这里还要修改
if (ProtoBuf.Util.IS_NODE)
fname = require("path")['join'](root, filename.file);
else
fname = root + delim + filename.file;
if (this.files[fname] === true)
return this.reset();
this.files[fname] = true;
}
...
}
私たちは自分自身を解決し、コードを変更して貼り付けないであろう。
いるProtobufのための四つの穴を埋めるために継続します
もともと私は問題のほとんどが解決されている、あなたへの書き込みが、この時間は、あなたがprotobufjsソースを変換する場合に使用する自信後、あなたのコードは、その瞬間を実行しますが、私はほとんどの人がモンゴルを探すことを余儀なくされると考えています。
ママは動作しませんでした!!言葉をたくさん読んで、最終的にここ読んで、ウェブ上で稼働してもいない、いないだけではない稼働シミュレータです。
どのように行うには、問題を解決するために、私が書き込みを続けなければなりません。
1.クリエイター動的ローディング方式のリソースを理解します
ココス-JSBそのファイルパスを使用してWeb上のプロジェクトの生みの親絵が同じになり、問題を考えてください?直接protobuf.protoFromFile(「xxx.proto」)プロトファイルをロードするためには成功しますか?
ココス文書は、動的に画像リソースファイルをロードすると、次の方法を使用してロードされ、資産/ resourcesディレクトリに格納する必要があります。
cc.loader.loadRes('resources/xxx')
次のコードを使用し、プロトファイルはリソース/ PB /ディレクトリに格納されてみてください。
protobuf.protoFromFile('resources/pb/xxx.proto')
彼らはまた、それを行う方法、ヒントを得るために失敗しますか?正しいリソースのパスを取得するには?
まあ、子供をオフに購入していない、と疲れ直接書き込むそれに答えるために!
protobuf.protoFromFile(cc.url.raw('resources/pb/xxx.proto'));
ブラウザでこの機能をcc.url.raw、シミュレータ、携帯電話は、これはコードの下で再び正常に実行する必要があり、実際のリソースパス、で、異なるリソースパスを返します。
2.よりよい解決策は、裁判にかけ
あなたがメソッドのソースコードを変更することによって、ココス-JSBのprotobufjsで問題を解決するために実行することができますが、私は、ココスH5正しい開発モードを模索してきたが、これは唯一の解決策ではありません。
どのように稼働してprotobufjsソースコードを変更せずにで取得するには、プリコンパイルされたプロトpbjsツールの使用はJSONファイルとJSファイルを使用するために、「いつクリエーター遭遇protobufjs」の記事の私のシリーズを見に保管してください!