首先我的proto文件结构如下图
按照这样的proto文件夹结构生成对应go/js/ts 代码的话,message 相互调用是不可避免的,而golang 的导入 import和protobufjs的导入的 import是不一样的。
例如:Golang:
import "common/models/user/user.proto";
而 protobufjs 按照这样的 import 导入是找不到 user.proto文件的,所以我们需要把 import改为一个相对路径,如下
import "../user/user.proto";
再次执行 pbjs -t static-module -w commonjs -o chat.js chat.proto 就没有找不到 user.proto的错误了。
当然除此之外也可以把所有 proto文件放在一个文件夹内,用生成所有的proto 文件命令也不会报错。pbjs -t static-module -w commonjs -o all.js *.proto
以上两种方式生成完毕后还需要手动去修改几个地方才可以再cc 中使用
1.修改生成的js文件中的$protobufjs和root
原:
var $protobuf = require("protobufjs/minimal");
修改为:
var $protobuf = protobuf;
原:
var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {});
修改为:
const $root = $protobuf.roots.creator3 || ($protobuf.roots.creator3 = $util.global);
2.如果你的proto文件中有 uint64/int64的变量时需要在ts文件导入 long
import { Long } from "protobufjs";
3.解决proto中引用问题
生成的ts源文件为:
import * as $protobuf from "protobufjs";
export namespace user {
//省略中间代码
}
修改为
import * as $protobuf from "protobufjs";
import { Long } from "protobufjs";
declare global {
export namespace user {
//省略中间代码
}
}
export { user as default };
最后代码中使用
let msg = user.LoginReq.create({LoginName: username, LoginPW: password})
let buffer = user.LoginReq.encode(msg).finish()
let sendData = ProtocolUtils.getInstance().getDataPack(1002, buffer)
NetManager.getInstance().send(sendData)
最后在将上述操作写为脚本
下面的两个shell 脚本路径是和我首图项目中的common处于同级,另外是用于mac,其他操作系统可能有些函数的不兼容,需要自己做下修改
Golang:
# shellcheck disable=SC2239
#!bin/sh
function deleteGoFile(){
for file in `ls $1`
do
if [ -d $1"/"$file ]
then
deleteGoFile $1"/"$file
else
if [ "${file##*.}" = "go" ]
then
rm -f $1"/"$file
fi
fi
done
}
function addGoFile(){
for file in `ls $1`
do
if [ -d $1"/"$file ]
then
addGoFile $1"/"$file
else
if [ "${file##*.}" = "proto" ]
then
echo $1"/"$file
protoc --go_out=. $1"/"$file
fi
fi
done
}
deleteGoFile common/models
addGoFile common/models
cocos creator
# shellcheck disable=SC2239
#!bin/sh
function cpDirs(){
for file in `ls $1`
do
cp -r $1"/"$file "/Users/luffy/Desktop/ts_protos"
done
}
resetProtoFileContent(){
for file in `ls $1`
do
if [ -d $1"/"$file ]
then
resetProtoFileContent $1"/"$file
else
if [ "${file##*.}" = "proto" ]
then
#注意这里是mac的sed用法
sed -i '' 's/import "common\/models/import "../g' $1"/"$file
fi
fi
done
}
function addJsFile(){
for file in `ls $1`
do
if [ -d $1"/"$file ]
then
addJsFile $1"/"$file
else
if [ "${file##*.}" = "proto" ]
then
cd $1 && pbjs -t static-module -w commonjs -o ${file%.*}".js" $file
fi
fi
done
}
function addTsFile(){
for file in `ls $1`
do
if [ -d $1"/"$file ]
then
addTsFile $1"/"$file
else
if [ "${file##*.}" = "proto" ]
then
cd $1 && pbts -o ${file%.*}".d.ts" ${file%.*}".js"
fi
fi
done
}
function resetJsFileContent() {
for file in `ls $1`
do
if [ -d $1"/"$file ]
then
resetJsFileContent $1"/"$file
else
if [ "${file##*.}" = "js" ]
then
sed -i '' 's/require("protobufjs\/minimal");/protobuf;/g' $1"/"$file
sed -i '' '10d' $1"/"$file
sed -i '' '10i\
const $root = $protobuf.roots.creator3 || ($protobuf.roots.creator3 = $util.global);\
' $1"/"$file
sed -i '' '$d' $1"/"$file
fi
fi
done
}
function resetTsFileContent() {
for file in `ls $1`
do
if [ -d $1"/"$file ]
then
resetTsFileContent $1"/"$file
else
if [ "${file##*.}" = "ts" ]
then
sed -i '' '2i\
import { Long } from "protobufjs";\
\
declare global {\
\
' $1"/"$file
sed -i '' "\$a\\
}\\
\\
export {${1##*/} as default};" $1'/'$file
fi
fi
done
}
#在桌面创建一个中间文件夹 生成js/ts
rm -rf /Users/luffy/Desktop/ts_protos
mkdir /Users/luffy/Desktop/ts_protos
cpDirs common/models
resetProtoFileContent /Users/luffy/Desktop/ts_protos #修改原proto文件 import 为相对路径
addJsFile /Users/luffy/Desktop/ts_protos
resetJsFileContent /Users/luffy/Desktop/ts_protos
addTsFile /Users/luffy/Desktop/ts_protos
resetTsFileContent /Users/luffy/Desktop/ts_protos
最后将生成的ts / js文件拖入cocos creator 中就行了。
顺便说一下,这样的情况 ts 文件会报错,原因是有引用其他包message,也会在当前ts 文件中写出来。可以不用去管它,不影响项目,也可以手动或者在脚本中删除。