publish_qqgame.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. // v1.3.0
  2. // publish 2.x 也是用这个文件,需要做兼容
  3. let isPublish2 = process.argv[2].includes("publish_qqgame.js") && process.argv[3].includes("--evn=publish2");
  4. // 获取Node插件和工作路径
  5. let ideModuleDir, workSpaceDir;
  6. if (isPublish2) {
  7. //是否使用IDE自带的node环境和插件,设置false后,则使用自己环境(使用命令行方式执行)
  8. const useIDENode = process.argv[0].indexOf("LayaAir") > -1 ? true : false;
  9. ideModuleDir = useIDENode ? process.argv[1].replace("gulp\\bin\\gulp.js", "").replace("gulp/bin/gulp.js", "") : "";
  10. workSpaceDir = useIDENode ? process.argv[2].replace("--gulpfile=", "").replace("\\.laya\\publish_qqgame.js", "").replace("/.laya/publish_qqgame.js", "") + "/" : "./../";
  11. } else {
  12. ideModuleDir = global.ideModuleDir;
  13. workSpaceDir = global.workSpaceDir;
  14. }
  15. //引用插件模块
  16. const gulp = require(ideModuleDir + "gulp");
  17. const fs = require("fs");
  18. const path = require("path");
  19. const crypto = require("crypto");
  20. const childProcess = require("child_process");
  21. const del = require(ideModuleDir + "del");
  22. const revCollector = require(ideModuleDir + 'gulp-rev-collector');
  23. let commandSuffix = ".cmd";
  24. const provider = "1109625052";
  25. const fullRemoteEngineList = ["laya.core.js", "laya.webgl.js", "laya.filter.js", "laya.ani.js", "laya.d3.js", "laya.html.js", "laya.particle.js", "laya.ui.js", "bytebuffer.js"];
  26. let copyLibsTask = ["copyLibsJsFile"];
  27. let packfiletask = ["packfile"];
  28. if (isPublish2) {
  29. copyLibsTask = "";
  30. packfiletask = ["copyPlatformFile_QQ"];
  31. }
  32. let
  33. config,
  34. platform,
  35. releaseDir;
  36. let isGlobalCli = true;
  37. let versionCon; // 版本管理version.json
  38. // 应该在publish中的,但是为了方便发布2.0及IDE 1.x,放在这里修改
  39. gulp.task("preCreate_QQ", copyLibsTask, function() {
  40. if (isPublish2) {
  41. let pubsetPath = path.join(workSpaceDir, ".laya", "pubset.json");
  42. let content = fs.readFileSync(pubsetPath, "utf8");
  43. let pubsetJson = JSON.parse(content);
  44. platform = "qqgame";
  45. releaseDir = path.join(workSpaceDir, "release", platform).replace(/\\/g, "/");
  46. config = pubsetJson[2];
  47. } else {
  48. platform = global.platform;
  49. releaseDir = global.releaseDir;
  50. config = global.config;
  51. }
  52. // 如果不是QQ小游戏
  53. if (platform !== "qqgame") {
  54. return;
  55. }
  56. if (process.platform === "darwin") {
  57. commandSuffix = "";
  58. }
  59. let copyLibsList = [`${workSpaceDir}/bin/libs/laya.qqmini.js`];
  60. var stream = gulp.src(copyLibsList, { base: `${workSpaceDir}/bin` });
  61. return stream.pipe(gulp.dest(releaseDir));
  62. });
  63. gulp.task("copyPlatformFile_QQ", ["preCreate_QQ"], function() {
  64. // 如果不是QQ小游戏
  65. if (platform !== "qqgame") {
  66. return;
  67. }
  68. let isHasPublish =
  69. fs.existsSync(path.join(releaseDir, "game.js")) &&
  70. fs.existsSync(path.join(releaseDir, "game.json")) &&
  71. fs.existsSync(path.join(releaseDir, "project.config.json")) &&
  72. fs.existsSync(path.join(releaseDir, "weapp-adapter.js"));
  73. if (isHasPublish) {
  74. return;
  75. }
  76. let adapterPath = path.join(ideModuleDir, "../", "out", "layarepublic", "LayaAirProjectPack", "lib", "data", "qqfiles");
  77. let stream = gulp.src(adapterPath + "/*.*");
  78. return stream.pipe(gulp.dest(releaseDir));
  79. });
  80. gulp.task("version_QQ", packfiletask, function() {
  81. // 如果不是QQ小游戏
  82. if (platform !== "qqgame") {
  83. return;
  84. }
  85. if (config.version) {
  86. let versionPath = releaseDir + "/version.json";
  87. let gameJSPath = releaseDir + "/game.js";
  88. let srcList = [versionPath, gameJSPath];
  89. return gulp.src(srcList)
  90. .pipe(revCollector())
  91. .pipe(gulp.dest(releaseDir));
  92. }
  93. });
  94. gulp.task("pluginEngin_QQ", ["version_QQ"], function(cb) {
  95. // 如果不是微信小游戏
  96. if (platform !== "qqgame") {
  97. return cb();
  98. }
  99. if (!config.uesEnginePlugin) { // 没有使用微信引擎插件,还是像以前一样发布
  100. return cb();
  101. }
  102. if (config.version) {
  103. let versionPath = releaseDir + "/version.json";
  104. versionCon = fs.readFileSync(versionPath, "utf8");
  105. versionCon = JSON.parse(versionCon);
  106. }
  107. let indexJsStr = (versionCon && versionCon["index.js"]) ? versionCon["index.js"] : "index.js";
  108. // 获取version等信息
  109. let coreLibPath = path.join(workSpaceDir, "bin", "libs", "laya.core.js");
  110. let isHasCoreLib = fs.existsSync(coreLibPath);
  111. let isOldAsProj = fs.existsSync(`${workSpaceDir}/asconfig.json`) && !isHasCoreLib;
  112. let isNewTsProj = fs.existsSync(`${workSpaceDir}/src/tsconfig.json`) && !isHasCoreLib;
  113. let EngineVersion = getEngineVersion();
  114. if (!EngineVersion) {
  115. throw new Error(`读取引擎版本号失败,请于服务提供商联系!`);
  116. }
  117. if (!EngineVersion || EngineVersion.includes("beta") || !canUsePluginEngine(EngineVersion)) {
  118. throw new Error(`该版本引擎无法使用引擎插件功能(engineVersion: ${EngineVersion})`);
  119. }
  120. console.log(`通过版本号检查: ${EngineVersion}`);
  121. // 使用引擎插件
  122. let localUseEngineList = [];
  123. let copyEnginePathList;
  124. new Promise(function(resolve, reject) {
  125. console.log(`修改game.js和game.json`);
  126. // 1) 修改game.js和game.json
  127. // 修改game.js
  128. let gameJsPath = path.join(releaseDir, "game.js");
  129. let gameJscontent = `require("weapp-adapter.js");\nrequire("./libs/laya.qqmini.js");\nrequirePlugin('layaPlugin');\nwindow.loadLib = require;\nrequire("./${indexJsStr}");`;
  130. fs.writeFileSync(gameJsPath, gameJscontent, "utf8");
  131. // 修改game.json,使其支持引擎插件
  132. let gameJsonPath = path.join(releaseDir, "game.json");
  133. let gameJsonContent = fs.readFileSync(gameJsonPath, "utf8");
  134. let conJson = JSON.parse(gameJsonContent);
  135. conJson.plugins = {
  136. "layaPlugin": {
  137. "version": EngineVersion,
  138. "provider": provider,
  139. "path": "laya-libs"
  140. }
  141. }
  142. gameJsonContent = JSON.stringify(conJson, null, 4);
  143. fs.writeFileSync(gameJsonPath, gameJsonContent, "utf8");
  144. // 修改project.config.json
  145. let projConfigPath = path.join(releaseDir, "project.config.json");
  146. let projConfigcontent = fs.readFileSync(projConfigPath, "utf8");
  147. let projConfigConJson = JSON.parse(projConfigcontent);
  148. projConfigConJson.compileType = "gamePlugin";
  149. projConfigConJson.pluginRoot = "laya-libs";
  150. projConfigcontent = JSON.stringify(projConfigConJson, null, 4);
  151. fs.writeFileSync(projConfigPath, projConfigcontent, "utf8");
  152. resolve();
  153. }).then(function() {
  154. return new Promise(function(resolve, reject) {
  155. console.log(`确定用到的插件引擎`);
  156. // 2) 确定用到了那些插件引擎,并将插件引擎从index.js的引用中去掉
  157. let indexJsPath = path.join(releaseDir, indexJsStr);
  158. let indexJsCon = fs.readFileSync(indexJsPath, "utf8");
  159. let item, fullRequireItem;
  160. for (let i = 0, len = fullRemoteEngineList.length; i < len; i++) {
  161. item = fullRemoteEngineList[i];
  162. fullRequireItem = `loadLib("libs/${item}")`;
  163. if (indexJsCon.includes(fullRequireItem)) {
  164. localUseEngineList.push(item);
  165. indexJsCon = indexJsCon.replace(fullRequireItem, "");
  166. }
  167. }
  168. if (isOldAsProj || isNewTsProj) { // 如果as||ts_new语言,开发者将laya.js也写入index.js中了,将其删掉
  169. fullRequireItem = `loadLib("laya.js")`;
  170. if (indexJsCon.includes(fullRequireItem)) {
  171. indexJsCon = indexJsCon.replace(fullRequireItem, "");
  172. }
  173. }
  174. fs.writeFileSync(indexJsPath, indexJsCon, "utf8");
  175. // ts/js再次修改game.js,仅引用使用到的类库
  176. // as||ts_new因为本地只有laya.js,无法仅引用使用到的类库
  177. if (!isOldAsProj && !isNewTsProj) {
  178. let pluginCon = "";
  179. localUseEngineList.forEach(function(item) {
  180. pluginCon += `requirePlugin("layaPlugin/${item}");\n`;
  181. });
  182. let gameJsPath = path.join(releaseDir, "game.js");
  183. let gameJsCon = fs.readFileSync(gameJsPath, "utf8");
  184. gameJsCon = gameJsCon.replace(`requirePlugin('layaPlugin');`, pluginCon);
  185. fs.writeFileSync(gameJsPath, gameJsCon, "utf8");
  186. }
  187. resolve();
  188. });
  189. }).then(function() {
  190. return new Promise(function(resolve, reject) {
  191. console.log(`将本地的引擎插件移动到laya-libs中`);
  192. // 3) 将本地的引擎插件移动到laya-libs中
  193. copyEnginePathList = [`${releaseDir}/libs/{${localUseEngineList.join(",")}}`];
  194. if (isOldAsProj || isNewTsProj) { // 单独拷贝laya.js
  195. copyEnginePathList = [`${releaseDir}/laya.js`];
  196. }
  197. gulp.src(copyEnginePathList).pipe(gulp.dest(`${releaseDir}/laya-libs`));
  198. setTimeout(resolve, 500);
  199. });
  200. }).then(function() {
  201. return new Promise(function(resolve, reject) {
  202. console.log(`将libs中的本地引擎插件删掉`);
  203. // 4) 将libs中的本地引擎插件删掉
  204. del(copyEnginePathList, { force: true }).then(resolve);
  205. });
  206. }).then(function() {
  207. return new Promise(async function(resolve, reject) {
  208. console.log(`完善引擎插件目录`);
  209. // 5) 引擎插件目录laya-libs中还需要新建几个文件,使该目录能够使用
  210. if (isOldAsProj || isNewTsProj) { // 单独拷贝laya.js
  211. localUseEngineList.push("laya.js");
  212. }
  213. let
  214. layalibsPath = path.join(releaseDir, "laya-libs"),
  215. engineIndex = path.join(layalibsPath, "index.js"),
  216. engineplugin = path.join(layalibsPath, "plugin.json"),
  217. enginesignature = path.join(layalibsPath, "signature.json");
  218. // index.js
  219. if (!fs.existsSync(layalibsPath)) {
  220. throw new Error("引擎插件目录创建失败,请与服务提供商联系!");
  221. }
  222. let indexCon = "";
  223. localUseEngineList.forEach(function(item) {
  224. indexCon += `require("./${item}");\n`;
  225. });
  226. fs.writeFileSync(engineIndex, indexCon, "utf8");
  227. // plugin.json
  228. let pluginCon = {"main": "index.js"};
  229. fs.writeFileSync(engineplugin, JSON.stringify(pluginCon, null, 4), "utf8");
  230. // signature.json
  231. let signatureCon = {
  232. "provider": provider,
  233. "signature": []
  234. };
  235. localUseEngineList.unshift("index.js");
  236. let fileName, md5Str;
  237. for (let i = 0, len = localUseEngineList.length; i < len; i++) {
  238. fileName = localUseEngineList[i];
  239. let md5Str = await getFileMd5(path.join(releaseDir, "laya-libs", fileName));
  240. signatureCon.signature.push({
  241. "path": fileName,
  242. "md5": md5Str
  243. });
  244. }
  245. fs.writeFileSync(enginesignature, JSON.stringify(signatureCon, null, 4), "utf8");
  246. resolve();
  247. });
  248. })
  249. .then(function() {
  250. cb();
  251. }).catch(function(e) {
  252. throw e;
  253. })
  254. });
  255. function getEngineVersion() {
  256. let coreLibPath = path.join(workSpaceDir, "bin", "libs", "laya.core.js");
  257. let isHasCoreLib = fs.existsSync(coreLibPath);
  258. let isOldAsProj = fs.existsSync(`${workSpaceDir}/asconfig.json`) && !isHasCoreLib;
  259. let isNewTsProj = fs.existsSync(`${workSpaceDir}/src/tsconfig.json`) && !isHasCoreLib;
  260. let EngineVersion;
  261. if (isHasCoreLib) {
  262. let con = fs.readFileSync(coreLibPath, "utf8");
  263. let matchList = con.match(/Laya\.version\s*=\s*['"]([0-9\.]+(beta)?.*)['"]/);
  264. if (!Array.isArray(matchList)) {
  265. return null;
  266. }
  267. EngineVersion = matchList[1];
  268. } else { // newts项目和旧版本as项目
  269. if (isOldAsProj) {
  270. let coreLibFilePath = path.join(workSpaceDir, "libs", "laya", "src", "Laya.as");
  271. if (!fs.existsSync(coreLibFilePath)) {
  272. return null;
  273. }
  274. let con = fs.readFileSync(coreLibFilePath, "utf8");
  275. let matchList = con.match(/version:String\s*=\s*['"]([0-9\.]+(beta)?.*)['"]/);
  276. if (!Array.isArray(matchList)) {
  277. return null;
  278. }
  279. EngineVersion = matchList[1];
  280. } else if (isNewTsProj) {
  281. let coreLibFilePath = path.join(workSpaceDir, "libs", "Laya.ts");
  282. if (!fs.existsSync(coreLibFilePath)) {
  283. return null;
  284. }
  285. let con = fs.readFileSync(coreLibFilePath, "utf8");
  286. let matchList = con.match(/static\s*version:\s*string\s*=\s*['"]([0-9\.]+(beta)?.*)['"]/);
  287. if (!Array.isArray(matchList)) {
  288. return null;
  289. }
  290. EngineVersion = matchList[1];
  291. }
  292. }
  293. // 特殊处理,因为历史原因,我们有一些4位的正式版本,调整为3位
  294. if (EngineVersion && /[\d\.]+/.test(EngineVersion) && EngineVersion.split(".").length > 3) {
  295. let verList = EngineVersion.split(".");
  296. verList.length = 3;
  297. EngineVersion = verList.join(".");
  298. }
  299. return EngineVersion;
  300. }
  301. function getFileMd5(filePath) {
  302. return new Promise(function(resolve, reject) {
  303. let md5 = crypto.createHash('md5');
  304. let stream = fs.createReadStream(filePath);
  305. stream.on("data", function(data) {
  306. md5.update(data);
  307. });
  308. stream.on("end", function() {
  309. let md5Str = md5.digest('hex');
  310. return resolve(md5Str);
  311. });
  312. });
  313. }
  314. function canUsePluginEngine(version) {
  315. const minVersionNum = "2.1.1";
  316. let compileMacthList = minVersionNum.match(/^(\d+)\.(\d+)\.(\d+)/);
  317. let matchList = version.match(/^(\d+)\.(\d+)\.(\d+)/);
  318. if (matchList[1] > compileMacthList[1]) {
  319. return true;
  320. }
  321. if (matchList[1] === compileMacthList[1] && matchList[2] > compileMacthList[2]) {
  322. return true;
  323. }
  324. if (matchList[1] === compileMacthList[1] && matchList[2] === compileMacthList[2] && matchList[3] >= compileMacthList[3]) {
  325. return true;
  326. }
  327. return false;
  328. }
  329. gulp.task("buildQQProj", ["pluginEngin_QQ"], function() {
  330. console.log("all tasks completed");
  331. });