publish_vivogame.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785
  1. // v1.5.0
  2. // publish 2.x 也是用这个文件,需要做兼容
  3. let isPublish2 = process.argv[2].includes("publish_vivogame.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_vivogame.js", "").replace("/.laya/publish_vivogame.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 childProcess = require("child_process");
  20. const del = require(ideModuleDir + "del");
  21. const iconv = require(ideModuleDir + "iconv-lite");
  22. const revCollector = require(ideModuleDir + 'gulp-rev-collector');
  23. let commandSuffix = ".cmd";
  24. let copyLibsTask = ["copyLibsJsFile"];
  25. let packfiletask = ["packfile"];
  26. if (isPublish2) {
  27. copyLibsTask = "";
  28. packfiletask = ["copyPlatformFile_VIVO"];
  29. }
  30. let
  31. config,
  32. platform,
  33. releaseDir,
  34. tempReleaseDir, // vivo临时拷贝目录
  35. projDir, // vivo快游戏工程目录
  36. isDealNoCompile = true,
  37. physicsLibsPathList = [],
  38. isExistEngineFolder = false; // bin目录下是否存在engine文件夹
  39. let projSrc;
  40. let versionCon; // 版本管理version.json
  41. let layarepublicPath = path.join(ideModuleDir, "../", "code", "layarepublic");
  42. if (!fs.existsSync(layarepublicPath)) {
  43. layarepublicPath = path.join(ideModuleDir, "../", "out", "layarepublic");
  44. }
  45. // 创建vivo项目前,拷贝vivo引擎库、修改index.js
  46. // 应该在publish中的,但是为了方便发布2.0及IDE 1.x,放在这里修改
  47. gulp.task("preCreate_VIVO", copyLibsTask, function() {
  48. if (isPublish2) {
  49. let pubsetPath = path.join(workSpaceDir, ".laya", "pubset.json");
  50. let content = fs.readFileSync(pubsetPath, "utf8");
  51. let pubsetJson = JSON.parse(content);
  52. platform = "vivogame";
  53. releaseDir = path.join(workSpaceDir, "release", platform).replace(/\\/g, "/");
  54. releaseDir = tempReleaseDir = path.join(releaseDir, "temprelease");
  55. config = pubsetJson[6]; // 只用到了 config.vivoInfo|config.vivoSign
  56. } else {
  57. platform = global.platform;
  58. releaseDir = global.releaseDir;
  59. tempReleaseDir = global.tempReleaseDir;
  60. config = global.config;
  61. }
  62. // 如果不是vivo快游戏
  63. if (platform !== "vivogame") {
  64. return;
  65. }
  66. if (process.platform === "darwin") {
  67. commandSuffix = "";
  68. }
  69. let copyLibsList = [`${workSpaceDir}/bin/libs/laya.vvmini.js`];
  70. var stream = gulp.src(copyLibsList, { base: `${workSpaceDir}/bin` });
  71. return stream.pipe(gulp.dest(tempReleaseDir));
  72. });
  73. gulp.task("copyPlatformFile_VIVO", ["preCreate_VIVO"], function() {
  74. return;
  75. // 如果不是vivo快游戏
  76. // if (platform !== "vivogame") {
  77. // return;
  78. // }
  79. // let vivoAdapterPath = path.join(layarepublicPath, "LayaAirProjectPack", "lib", "data", "vivofiles");
  80. // let copyLibsList = [`${vivoAdapterPath}/**/*.*`];
  81. // var stream = gulp.src(copyLibsList);
  82. // return stream.pipe(gulp.dest(tempReleaseDir));
  83. });
  84. // 检查是否全局安装了qgame
  85. gulp.task("createGlobalQGame_VIVO", packfiletask, function() {
  86. // 如果不是vivo快游戏
  87. if (platform !== "vivogame") {
  88. return;
  89. }
  90. releaseDir = path.dirname(releaseDir);
  91. projDir = path.join(releaseDir, config.vivoInfo.projName);
  92. projSrc = path.join(projDir, "src");
  93. // npm view @vivo-minigame/cli version
  94. // npm install -g @vivo-minigame/cli
  95. let remoteVersion, localVersion;
  96. let isGetRemote, isGetLocal;
  97. let isUpdateGlobalQGame = true;
  98. return new Promise((resolve, reject) => { // 远程版本号
  99. childProcess.exec("npm view @vivo-minigame/cli version", function(error, stdout, stderr) {
  100. if (!stdout) { // 获取 @vivo-minigame/cli 远程版本号失败
  101. console.log("Failed to get the remote version number");
  102. resolve();
  103. return;
  104. }
  105. remoteVersion = stdout;
  106. isGetRemote = true;
  107. if (isGetRemote && isGetLocal) {
  108. isUpdateGlobalQGame = remoteVersion != localVersion;
  109. console.log(`remoteVersion: ${remoteVersion}, localVersion: ${localVersion}`);
  110. resolve();
  111. }
  112. });
  113. childProcess.exec("mg -v", function(error, stdout, stderr) {
  114. if (!stdout) { // 获取 @vivo-minigame/cli 本地版本号失败
  115. console.log("Failed to get the local version number");
  116. resolve();
  117. return;
  118. }
  119. localVersion = stdout;
  120. isGetLocal = true;
  121. if (isGetRemote && isGetLocal) {
  122. isUpdateGlobalQGame = remoteVersion != localVersion;
  123. console.log(`remoteVersion: ${remoteVersion}, localVersion: ${localVersion}`);
  124. resolve();
  125. }
  126. });
  127. setTimeout(() => {
  128. // 如果获取到了本地版本号,但未获取到远程版本号,默认通过
  129. if (isGetLocal && !isGetRemote) {
  130. isUpdateGlobalQGame = false;
  131. console.log("Gets the version number timeout, does not get the remote version number, but the local version number exists, passes by default");
  132. resolve();
  133. return;
  134. }
  135. }, 10000);
  136. }).then(() => {
  137. return new Promise((resolve, reject) => {
  138. if (!isUpdateGlobalQGame) {
  139. resolve();
  140. return;
  141. }
  142. console.log("全局安装@vivo-minigame/cli");
  143. // npm install -g @vivo-minigame/cli
  144. let cmd = `npm${commandSuffix}`;
  145. let args = ["install", "@vivo-minigame/cli", "-g"];
  146. let opts = {
  147. shell: true
  148. };
  149. let cp = childProcess.spawn(cmd, args, opts);
  150. cp.stdout.on('data', (data) => {
  151. console.log(`stdout: ${data}`);
  152. });
  153. cp.stderr.on('data', (data) => {
  154. console.log(`stderr: ${data}`);
  155. // reject();
  156. });
  157. cp.on('close', (code) => {
  158. console.log(`2 end) npm install -g @vivo-minigame/cli:${code}`);
  159. resolve();
  160. });
  161. });
  162. }).catch((e) => {
  163. console.log("catch e", e);
  164. });
  165. });
  166. gulp.task("createProj_VIVO", ["createGlobalQGame_VIVO"], function() {
  167. // 如果不是vivo快游戏
  168. if (platform !== "vivogame") {
  169. return;
  170. }
  171. // 如果有即存项目,不再新建
  172. let isProjExist = fs.existsSync(projDir + "/node_modules") &&
  173. fs.existsSync(projDir + "/sign");
  174. if (isProjExist) {
  175. // 检测是否需要升级
  176. let packageCon = fs.readFileSync(`${projDir}/package.json`, "utf8");
  177. let minigamePath = path.join(projDir, "minigame.config.js");
  178. if (packageCon.includes("@vivo-minigame/cli-service") && fs.existsSync(minigamePath)) {
  179. return;
  180. }
  181. }
  182. // 如果有即存项目,但是是旧的项目,删掉后重新创建
  183. return new Promise((resolve, reject) => {
  184. if (!fs.existsSync(projDir)) {
  185. return resolve();
  186. }
  187. let delList = [projDir];
  188. del(delList, { force: true }).then(paths => {
  189. resolve();
  190. });
  191. }).then(function() {
  192. // 在项目中创建vivo项目
  193. return new Promise((resolve, reject) => {
  194. console.log("(proj)开始创建vivo快游戏项目");
  195. // mg init <project-name>
  196. let cmd = `mg${commandSuffix}`;
  197. let args = ["init", config.vivoInfo.projName];
  198. let opts = {
  199. cwd: releaseDir,
  200. shell: true
  201. };
  202. let cp = childProcess.spawn(cmd, args, opts);
  203. cp.stdout.on('data', (data) => {
  204. console.log(`stdout: ${data}`);
  205. });
  206. cp.stderr.on('data', (data) => {
  207. console.log(`stderr: ${data}`);
  208. // reject();
  209. });
  210. cp.on('close', (code) => {
  211. cp = null;
  212. console.log(`子进程退出码:${code}`);
  213. resolve();
  214. });
  215. });
  216. });
  217. });
  218. // 检查是否安装了adapter
  219. gulp.task("createAdapter_VIVO", ["createProj_VIVO"], function() {
  220. // 如果不是vivo快游戏
  221. if (platform !== "vivogame") {
  222. return;
  223. }
  224. // npm view @qgame/adapter version
  225. // npm i -S @qgame/adapter@latest
  226. let remoteVersion, localVersion;
  227. let isGetRemote, isGetLocal;
  228. let isUpdateAdapter = true;
  229. return new Promise((resolve, reject) => { // 远程版本号
  230. childProcess.exec("npm view @qgame/adapter version", function(error, stdout, stderr) {
  231. if (!stdout) { // 获取 @vivo-minigame/cli 远程版本号失败
  232. console.log("Failed to get the remote adapter version number");
  233. resolve();
  234. return;
  235. }
  236. remoteVersion = stdout.replace(/[\r\n]/g, "").trim();
  237. isGetRemote = true;
  238. if (isGetRemote && isGetLocal) {
  239. isUpdateAdapter = remoteVersion != localVersion;
  240. console.log(`remoteVersion: ${remoteVersion}, localVersion: ${localVersion}`);
  241. resolve();
  242. }
  243. });
  244. childProcess.exec("npm ls @qgame/adapter version", { cwd: projDir }, function(error, stdout, stderr) {
  245. if (!stdout) { // 获取 @vivo-minigame/cli 本地版本号失败
  246. console.log("Failed to get the local adapter version number");
  247. resolve();
  248. return;
  249. }
  250. let info = stdout.split("@qgame/adapter@"); //@qgame/adapter@1.0.3
  251. info = Array.isArray(info) && info[1] && info[1].replace(/[\r\n]/g, "").trim();
  252. localVersion = info;
  253. isGetLocal = true;
  254. if (isGetRemote && isGetLocal) {
  255. isUpdateAdapter = remoteVersion != localVersion;
  256. console.log(`remoteVersion: ${remoteVersion}, localVersion: ${localVersion}`);
  257. resolve();
  258. }
  259. });
  260. setTimeout(() => {
  261. // 如果获取到了本地版本号,但未获取到远程版本号,默认通过
  262. if (!isGetLocal || !isGetRemote) {
  263. console.log("Failed to get the local or remote version number");
  264. resolve();
  265. return;
  266. }
  267. }, 10000);
  268. }).then(() => {
  269. return new Promise((resolve, reject) => {
  270. if (!isUpdateAdapter) {
  271. resolve();
  272. return;
  273. }
  274. console.log("安装@qgame/adapter");
  275. // npm i -S @qgame/adapter@latest
  276. let cmd = `npm${commandSuffix}`;
  277. let args = ["install", "-S", "@qgame/adapter@latest"];
  278. let opts = {
  279. shell: true,
  280. cwd: projDir
  281. };
  282. let cp = childProcess.spawn(cmd, args, opts);
  283. cp.stdout.on('data', (data) => {
  284. console.log(`stdout: ${data}`);
  285. });
  286. cp.stderr.on('data', (data) => {
  287. console.log(`stderr: ${data}`);
  288. // reject();
  289. });
  290. cp.on('close', (code) => {
  291. console.log(`2 end) npm i -S @qgame/adapter@latest:${code}`);
  292. resolve();
  293. });
  294. });
  295. }).catch((e) => {
  296. console.log("catch e", e);
  297. });
  298. });
  299. // 拷贝文件到vivo快游戏
  300. gulp.task("copyFileToProj_VIVO", ["createAdapter_VIVO"], function() {
  301. // 如果不是vivo快游戏
  302. if (platform !== "vivogame") {
  303. return;
  304. }
  305. // 如果有js/main.js,将其删除
  306. let vivoMainPath = path.join(projDir, "src", "js", "main.js");
  307. if (fs.existsSync(vivoMainPath)) {
  308. fs.unlinkSync(vivoMainPath);
  309. }
  310. // 将临时文件夹中的文件,拷贝到项目中去
  311. let originalDir = `${tempReleaseDir}/**/*.*`;
  312. let stream = gulp.src(originalDir);
  313. return stream.pipe(gulp.dest(path.join(projSrc)));
  314. });
  315. // 拷贝icon到vivo快游戏
  316. gulp.task("copyIconToProj_VIVO", ["copyFileToProj_VIVO"], function() {
  317. // 如果不是vivo快游戏
  318. if (platform !== "vivogame") {
  319. return;
  320. }
  321. let originalDir = config.vivoInfo.icon;
  322. let stream = gulp.src(originalDir);
  323. return stream.pipe(gulp.dest(projSrc));
  324. });
  325. // 清除vivo快游戏临时目录
  326. gulp.task("clearTempDir_VIVO", ["copyIconToProj_VIVO"], function() {
  327. // 如果不是vivo快游戏
  328. if (platform !== "vivogame") {
  329. return;
  330. }
  331. // 删掉临时目录
  332. return del([tempReleaseDir], { force: true });
  333. });
  334. // 生成release签名(私钥文件 private.pem 和证书文件 certificate.pem )
  335. gulp.task("generateSign_VIVO", ["clearTempDir_VIVO"], function() {
  336. // 如果不是vivo快游戏
  337. if (platform !== "vivogame") {
  338. return;
  339. }
  340. if (!config.vivoSign.generateSign) {
  341. return;
  342. }
  343. // https://doc.quickapp.cn/tools/compiling-tools.html
  344. return new Promise((resolve, reject) => {
  345. let cmd = "openssl";
  346. let args = ["req", "-newkey", "rsa:2048", "-nodes", "-keyout", "private.pem",
  347. "-x509", "-days", "3650", "-out", "certificate.pem"];
  348. let opts = {
  349. cwd: projDir,
  350. shell: true
  351. };
  352. let cp = childProcess.spawn(cmd, args, opts);
  353. cp.stdout.on('data', (data) => {
  354. console.log(`stdout: ${data}`);
  355. });
  356. cp.stderr.on('data', (data) => {
  357. console.log(`stderr: ${data}`);
  358. data += "";
  359. if (data.includes("Country Name")) {
  360. cp.stdin.write(`${config.vivoSign.countryName}\n`);
  361. console.log(`Country Name: ${config.vivoSign.countryName}`);
  362. } else if (data.includes("Province Name")) {
  363. cp.stdin.write(`${config.vivoSign.provinceName}\n`);
  364. console.log(`Province Name: ${config.vivoSign.provinceName}`);
  365. } else if (data.includes("Locality Name")) {
  366. cp.stdin.write(`${config.vivoSign.localityName}\n`);
  367. console.log(`Locality Name: ${config.vivoSign.localityName}`);
  368. } else if (data.includes("Organization Name")) {
  369. cp.stdin.write(`${config.vivoSign.orgName}\n`);
  370. console.log(`Organization Name: ${config.vivoSign.orgName}`);
  371. } else if (data.includes("Organizational Unit Name")) {
  372. cp.stdin.write(`${config.vivoSign.orgUnitName}\n`);
  373. console.log(`Organizational Unit Name: ${config.vivoSign.orgUnitName}`);
  374. } else if (data.includes("Common Name")) {
  375. cp.stdin.write(`${config.vivoSign.commonName}\n`);
  376. console.log(`Common Name: ${config.vivoSign.commonName}`);
  377. } else if (data.includes("Email Address")) {
  378. cp.stdin.write(`${config.vivoSign.emailAddr}\n`);
  379. console.log(`Email Address: ${config.vivoSign.emailAddr}`);
  380. // cp.stdin.end();
  381. }
  382. // reject();
  383. });
  384. cp.on('close', (code) => {
  385. console.log(`子进程退出码:${code}`);
  386. resolve();
  387. });
  388. });
  389. });
  390. // 拷贝sign文件到指定位置
  391. gulp.task("copySignFile_VIVO", ["generateSign_VIVO"], function() {
  392. // 如果不是vivo快游戏
  393. if (platform !== "vivogame") {
  394. return;
  395. }
  396. if (config.vivoSign.generateSign) { // 新生成的签名
  397. // 移动签名文件到项目中(Laya & vivo快游戏项目中)
  398. let
  399. privatePem = path.join(projDir, "private.pem"),
  400. certificatePem = path.join(projDir, "certificate.pem");
  401. let isSignExits = fs.existsSync(privatePem) && fs.existsSync(certificatePem);
  402. if (!isSignExits) {
  403. return;
  404. }
  405. let
  406. xiaomiDest = `${projDir}/sign/release`,
  407. layaDest = `${workSpaceDir}/sign/release`;
  408. let stream = gulp.src([privatePem, certificatePem]);
  409. return stream.pipe(gulp.dest(xiaomiDest))
  410. .pipe(gulp.dest(layaDest));
  411. } else if (config.vivoInfo.useReleaseSign && !config.vivoSign.generateSign) { // 使用release签名,并且没有重新生成
  412. // 从项目中将签名拷贝到vivo快游戏项目中
  413. let
  414. privatePem = path.join(workSpaceDir, "sign", "release", "private.pem"),
  415. certificatePem = path.join(workSpaceDir, "sign", "release", "certificate.pem");
  416. let isSignExits = fs.existsSync(privatePem) && fs.existsSync(certificatePem);
  417. if (!isSignExits) {
  418. return;
  419. }
  420. let
  421. xiaomiDest = `${projDir}/sign/release`;
  422. let stream = gulp.src([privatePem, certificatePem]);
  423. return stream.pipe(gulp.dest(xiaomiDest));
  424. }
  425. });
  426. gulp.task("deleteSignFile_VIVO", ["copySignFile_VIVO"], function() {
  427. // 如果不是vivo快游戏
  428. if (platform !== "vivogame") {
  429. return;
  430. }
  431. if (config.vivoSign.generateSign) { // 新生成的签名
  432. let
  433. privatePem = path.join(projDir, "private.pem"),
  434. certificatePem = path.join(projDir, "certificate.pem");
  435. return del([privatePem, certificatePem], { force: true });
  436. }
  437. });
  438. gulp.task("modifyFile_VIVO", ["deleteSignFile_VIVO"], function() {
  439. // 如果不是vivo快游戏
  440. if (platform !== "vivogame") {
  441. return;
  442. }
  443. // 修改manifest.json文件
  444. let manifestPath = path.join(projSrc, "manifest.json");
  445. if (!fs.existsSync(manifestPath)) {
  446. return;
  447. }
  448. let manifestContent = fs.readFileSync(manifestPath, "utf8");
  449. let manifestJson = JSON.parse(manifestContent);
  450. manifestJson.package = config.vivoInfo.package;
  451. manifestJson.name = config.vivoInfo.name;
  452. manifestJson.orientation = config.vivoInfo.orientation;
  453. manifestJson.config.logLevel = config.vivoInfo.logLevel || "off";
  454. manifestJson.deviceOrientation = config.vivoInfo.orientation;
  455. manifestJson.versionName = config.vivoInfo.versionName;
  456. manifestJson.versionCode = config.vivoInfo.versionCode;
  457. manifestJson.minPlatformVersion = config.vivoInfo.minPlatformVersion;
  458. manifestJson.icon = `/${path.basename(config.vivoInfo.icon)}`;
  459. if (config.vivoInfo.subpack) { // 分包
  460. manifestJson.subpackages = config.vivoSubpack;
  461. } else {
  462. delete manifestJson.subpackages;
  463. }
  464. // 增加thirdEngine字段
  465. let EngineVersion = getEngineVersion();
  466. if (EngineVersion) {
  467. manifestJson.thirdEngine = {
  468. "laya": EngineVersion
  469. };
  470. }
  471. fs.writeFileSync(manifestPath, JSON.stringify(manifestJson, null, 4), "utf8");
  472. if (config.version) {
  473. let versionPath = projSrc + "/version.json";
  474. versionCon = fs.readFileSync(versionPath, "utf8");
  475. versionCon = JSON.parse(versionCon);
  476. }
  477. let indexJsStr = (versionCon && versionCon["index.js"]) ? versionCon["index.js"] : "index.js";
  478. // 修改game.js文件
  479. let content = `require("@qgame/adapter");\nif(!window.navigator)\n\twindow.navigator = {};\nwindow.navigator.userAgent = 'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/603.1.30 (KHTML, like Gecko) Mobile/14E8301 VVGame NetType/WIFI Language/zh_CN';
  480. require("./libs/laya.vvmini.js");\nrequire("./index.js");`;
  481. let gameJsPath = path.join(projSrc, "game.js");
  482. fs.writeFileSync(gameJsPath, content, "utf8");
  483. // vivo项目,修改index.js
  484. let filePath = path.join(projSrc, indexJsStr);
  485. if (!fs.existsSync(filePath)) {
  486. return;
  487. }
  488. let fileContent = fs.readFileSync(filePath, "utf8");
  489. fileContent = fileContent.replace(/loadLib(\(['"])/gm, "require$1./");
  490. fs.writeFileSync(filePath, fileContent, "utf8");
  491. })
  492. function getEngineVersion() {
  493. let coreLibPath = path.join(workSpaceDir, "bin", "libs", "laya.core.js");
  494. let isHasCoreLib = fs.existsSync(coreLibPath);
  495. let isOldAsProj = fs.existsSync(`${workSpaceDir}/asconfig.json`) && !isHasCoreLib;
  496. let isNewTsProj = fs.existsSync(`${workSpaceDir}/src/tsconfig.json`) && !isHasCoreLib;
  497. let EngineVersion;
  498. if (isHasCoreLib) {
  499. let con = fs.readFileSync(coreLibPath, "utf8");
  500. let matchList = con.match(/Laya\.version\s*=\s*['"]([0-9\.]+(beta)?.*)['"]/);
  501. if (!Array.isArray(matchList)) {
  502. return null;
  503. }
  504. EngineVersion = matchList[1];
  505. } else { // newts项目和旧版本as项目
  506. if (isOldAsProj) {
  507. let coreLibFilePath = path.join(workSpaceDir, "libs", "laya", "src", "Laya.as");
  508. if (!fs.existsSync(coreLibFilePath)) {
  509. return null;
  510. }
  511. let con = fs.readFileSync(coreLibFilePath, "utf8");
  512. let matchList = con.match(/version:String\s*=\s*['"]([0-9\.]+(beta)?.*)['"]/);
  513. if (!Array.isArray(matchList)) {
  514. return null;
  515. }
  516. EngineVersion = matchList[1];
  517. } else if (isNewTsProj) {
  518. let coreLibFilePath = path.join(workSpaceDir, "libs", "Laya.ts");
  519. if (!fs.existsSync(coreLibFilePath)) {
  520. return null;
  521. }
  522. let con = fs.readFileSync(coreLibFilePath, "utf8");
  523. let matchList = con.match(/static\s*version:\s*string\s*=\s*['"]([0-9\.]+(beta)?.*)['"]/);
  524. if (!Array.isArray(matchList)) {
  525. return null;
  526. }
  527. EngineVersion = matchList[1];
  528. }
  529. }
  530. return EngineVersion;
  531. }
  532. gulp.task("version_VIVO", ["modifyFile_VIVO"], function () {
  533. // 如果不是vivo快游戏
  534. if (platform !== "vivogame") {
  535. return;
  536. }
  537. if (config.version) {
  538. let versionPath = projSrc + "/version.json";
  539. let mainJSPath = projSrc + "/game.js";
  540. let srcList = [versionPath, mainJSPath];
  541. return gulp.src(srcList)
  542. .pipe(revCollector())
  543. .pipe(gulp.dest(projSrc));
  544. }
  545. });
  546. // 处理engine文件夹
  547. gulp.task("dealEngineFolder1_VIVO", ["version_VIVO"], function() {
  548. // 如果项目中有engine文件夹,我们默认该开发者是熟悉VIVO发布流程的,已经处理好所有的逻辑
  549. // 值得注意的:
  550. // 1) 如果有engine文件夹而未处理2D物理库(box2d.js/physics.js),项目将无法运行
  551. // 2) 如果未处理3D物理库(physics3D.js),打包时间将会很长
  552. // 如果不是vivo快游戏
  553. if (platform !== "vivogame") {
  554. return;
  555. }
  556. let engineFolder = path.join(projDir, "src", "engine");
  557. isExistEngineFolder = fs.existsSync(engineFolder);
  558. if (!isExistEngineFolder) {
  559. return;
  560. }
  561. // 不想写一堆task任务,500ms默认拷贝完成吧
  562. // 未来有了更好的解决方案再修改
  563. return new Promise(function(resolve, reject) {
  564. // 将engine文件夹拷贝到projRoot下
  565. setTimeout(resolve, 500);
  566. var stream = gulp.src([`${engineFolder}/**/*.*`], {base: `${projDir}/src`});
  567. return stream.pipe(gulp.dest(projDir));
  568. }).then(function() {
  569. return new Promise(function(resolve, reject) {
  570. // 删掉src下的engine和adapter
  571. setTimeout(resolve, 500);
  572. return del([engineFolder], { force: true });
  573. });
  574. }).catch(function(err) {
  575. console.log(err);
  576. });
  577. });
  578. gulp.task("dealEngineFolder2_VIVO", ["dealEngineFolder1_VIVO"], function() {
  579. // 如果不是vivo快游戏
  580. if (platform !== "vivogame") {
  581. return;
  582. }
  583. if (!isExistEngineFolder) {
  584. return;
  585. }
  586. let engineFolder = path.join(projDir, "engine");
  587. let engineFileList = fs.readdirSync(engineFolder);
  588. // 修改配置文件
  589. configVivoConfigFile(engineFileList);
  590. });
  591. // 如果项目中用到了 box2d.js|laya.physics.js/laya.physics3D.js ,需要特殊处理
  592. // 之前处理的是有项目中已经存在engine文件夹的情况,现在开始处理没有文件夹的情况
  593. gulp.task("dealNoCompile1_VIVO", ["dealEngineFolder2_VIVO"], function() {
  594. // 如果不是vivo快游戏
  595. if (platform !== "vivogame") {
  596. return;
  597. }
  598. if (!isDealNoCompile) {
  599. return;
  600. }
  601. // 将js/bundle.js | libs/*.* 全放到engine文件夹中
  602. let indexJsStr = (versionCon && versionCon["index.js"]) ? versionCon["index.js"] : "index.js";
  603. let bundleJsStr = (versionCon && versionCon["js/bundle.js"]) ? versionCon["js/bundle.js"] : "js/bundle.js";
  604. let layaJsStr = (versionCon && versionCon["laya.js"]) ? versionCon["laya.js"] : "laya.js";
  605. // 修改index.js,去掉物理库前面的libs
  606. let filePath = path.join(projSrc, indexJsStr);
  607. let fileContent = fs.readFileSync(filePath, "utf8");
  608. let physicsNameList = [];
  609. if (fileContent.includes(bundleJsStr)) {
  610. let adapterJsPath = path.join(projSrc, bundleJsStr);
  611. physicsNameList.push(bundleJsStr);
  612. physicsLibsPathList.push(adapterJsPath);
  613. }
  614. if (fileContent.includes(layaJsStr)) {
  615. let layaJsPath = path.join(projSrc, layaJsStr);
  616. physicsNameList.push(layaJsStr);
  617. physicsLibsPathList.push(layaJsPath);
  618. }
  619. let libsList = fs.readdirSync(path.join(projSrc, "libs"));
  620. let libsFileName, libsFilePath;
  621. for (let i = 0, len = libsList.length; i < len; i++) {
  622. libsFileName = libsList[i];
  623. libsFilePath = path.join(projSrc, "libs", libsFileName);
  624. physicsNameList.push(`libs/${libsFileName}`);
  625. physicsLibsPathList.push(libsFilePath);
  626. }
  627. // 修改配置文件
  628. configVivoConfigFile(physicsNameList);
  629. // 将物理库拷贝到engine中
  630. var stream = gulp.src(physicsLibsPathList, {base: projSrc});
  631. return stream.pipe(gulp.dest(path.join(projDir, "engine")));
  632. });
  633. function configVivoConfigFile(engineFileList) {
  634. let vvConfigPath = path.join(projDir, "minigame.config.js");
  635. let content = fs.readFileSync(vvConfigPath, "utf8");
  636. let externalsStr = 'const externals = [\n';
  637. let libName;
  638. for (let i = 0, len = engineFileList.length; i < len; i++) {
  639. libName = engineFileList[i];
  640. if (i !== 0) {
  641. externalsStr += ',\n';
  642. }
  643. // 不要改这里的缩进,否则最终的结果不好看
  644. externalsStr += `{
  645. module_name:'./${libName}',
  646. module_path:'./${libName}',
  647. module_from:'engine/${libName}'
  648. }`;
  649. }
  650. externalsStr += '\t]';
  651. content = content.replace(/const externals = \[([^*].|\n|\r)*\]/gm, externalsStr);
  652. fs.writeFileSync(vvConfigPath, content, "utf8");
  653. }
  654. gulp.task("dealNoCompile2_VIVO", ["dealNoCompile1_VIVO"], function() {
  655. // 如果不是vivo快游戏
  656. if (platform !== "vivogame") {
  657. return;
  658. }
  659. if (!isDealNoCompile || physicsLibsPathList.length === 0) {
  660. return;
  661. }
  662. return del(physicsLibsPathList, { force: true });
  663. });
  664. // 打包rpk
  665. gulp.task("buildRPK_VIVO", ["dealNoCompile2_VIVO"], function() {
  666. // 如果不是vivo快游戏
  667. if (platform !== "vivogame") {
  668. return;
  669. }
  670. // 在vivo轻游戏项目目录中执行:
  671. // npm run build || npm run release
  672. let cmdStr = "build";
  673. if (config.vivoInfo.useReleaseSign) {
  674. cmdStr = "release";
  675. }
  676. return new Promise((resolve, reject) => {
  677. let cmd = `npm${commandSuffix}`;
  678. let args = ["run", cmdStr];
  679. let opts = {
  680. cwd: projDir,
  681. shell: true
  682. };
  683. let cp = childProcess.spawn(cmd, args, opts);
  684. // let cp = childProcess.spawn(`npx${commandSuffix}`, ['-v']);
  685. cp.stdout.on('data', (data) => {
  686. console.log(`stdout: ${data}`);
  687. });
  688. cp.stderr.on('data', (data) => {
  689. console.log(`stderr: ${data}`);
  690. console.log(`stderr(iconv): ${iconv.decode(data, 'gbk')}`);
  691. // reject();
  692. });
  693. cp.on('close', (code) => {
  694. console.log(`子进程退出码:${code}`);
  695. resolve();
  696. });
  697. });
  698. });
  699. gulp.task("showQRCode_VIVO", ["buildRPK_VIVO"], function() {
  700. // 如果不是vivo快游戏
  701. if (platform !== "vivogame") {
  702. return;
  703. }
  704. // 在vivo轻游戏项目目录中执行:
  705. // npm run server
  706. return new Promise((resolve, reject) => {
  707. let cmd = `npm${commandSuffix}`;
  708. let args = ["run", "server"];
  709. let opts = {
  710. cwd: projDir,
  711. shell: true
  712. };
  713. let cp = childProcess.spawn(cmd, args, opts);
  714. // let cp = childProcess.spawn(`npx${commandSuffix}`, ['-v']);
  715. cp.stdout.on('data', (data) => {
  716. console.log(`${data}`);
  717. // 输出pid,macos要用: macos无法kill进程树,也无法执行命令获取3000端口pid(没有查询权限),导致无法kill这个进程
  718. console.log('vv_qrcode_pid:' + cp.pid);
  719. });
  720. cp.stderr.on('data', (data) => {
  721. console.log(`stderr: ${data}`);
  722. console.log(`stderr(iconv): ${iconv.decode(data, 'gbk')}`);
  723. // reject();
  724. });
  725. cp.on('close', (code) => {
  726. console.log(`子进程退出码:${code}`);
  727. resolve();
  728. });
  729. });
  730. });
  731. gulp.task("buildVivoProj", ["showQRCode_VIVO"], function() {
  732. console.log("all tasks completed");
  733. });