diff --git a/.firebase/hosting.cHVibGlj.cache b/.firebase/hosting.cHVibGlj.cache new file mode 100644 index 0000000..b5e2b5d --- /dev/null +++ b/.firebase/hosting.cHVibGlj.cache @@ -0,0 +1 @@ +index.html,1605098090330,6862f53380477419cfcf08992c08121a65dd5d922f404ae142b837c7dc7bc26e diff --git a/.firebaserc b/.firebaserc new file mode 100644 index 0000000..11b7ee0 --- /dev/null +++ b/.firebaserc @@ -0,0 +1,5 @@ +{ + "projects": { + "default": "cathulhu-h5" + } +} diff --git a/.laya/_compile_1605111925205.js b/.laya/_compile_1605111925205.js new file mode 100644 index 0000000..7e8eea7 --- /dev/null +++ b/.laya/_compile_1605111925205.js @@ -0,0 +1,73 @@ +// v1.2.4 +//是否使用IDE自带的node环境和插件,设置false后,则使用自己环境(使用命令行方式执行) +const useIDENode = process.argv[0].indexOf("LayaAir") > -1 ? true : false; +const useCMDNode = process.argv[1].indexOf("layaair2-cmd") > -1 ? true : false; + +function useOtherNode(){ + return useIDENode||useCMDNode; +} +//获取Node插件和工作路径 +let ideModuleDir = useOtherNode() ? process.argv[1].replace("gulp\\bin\\gulp.js", "").replace("gulp/bin/gulp.js", "") : ""; +let workSpaceDir = useOtherNode() ? process.argv[2].replace("--gulpfile=", "").replace("\\.laya\\compile.js", "").replace("/.laya/compile.js", "") : "./../"; + +const gulp = require(ideModuleDir + "gulp"); +const rollup = require(ideModuleDir + "rollup"); +const typescript = require(ideModuleDir + 'rollup-plugin-typescript2');//typescript2 plugin +const glsl = require(ideModuleDir + 'rollup-plugin-glsl'); + +// 如果是发布时调用编译功能,增加prevTasks +let prevTasks = ""; +if (global.publish) { + prevTasks = ["loadConfig"]; +} + +gulp.task("compile", prevTasks, function () { + // 发布时调用编译功能,判断是否点击了编译选项 + if (global.publish && !global.config.compile) { + return; + } else if (global.publish && global.config.compile) { + // 发布时调用编译,workSpaceDir使用publish.js里的变量 + workSpaceDir = global.workSpaceDir; + } + + return rollup.rollup({ + input: workSpaceDir + '/src/Main.ts', + onwarn:(waring,warn)=>{ + if(waring.code == "CIRCULAR_DEPENDENCY"){ + console.log("warnning Circular dependency:"); + console.log(waring); + } + }, + treeshake: false, //建议忽略 + plugins: [ + typescript({ + tsconfig:workSpaceDir + "/tsconfig.json", + check: true, //Set to false to avoid doing any diagnostic checks on the code + tsconfigOverride:{compilerOptions:{removeComments: true}}, + include:/.*.ts/, + }), + glsl({ + // By default, everything gets included + include: /.*(.glsl|.vs|.fs)$/, + sourceMap: false, + compress:false + }), + /*terser({ + output: { + }, + numWorkers:1,//Amount of workers to spawn. Defaults to the number of CPUs minus 1 + sourcemap: false + })*/ + ] + }).then(bundle => { + return bundle.write({ + file: workSpaceDir + '/bin/js/bundle.js', + format: 'iife', + name: 'laya', + sourcemap: false + }); + }).catch(err=>{ + console.log(err); + + }) +}); \ No newline at end of file diff --git a/.laya/_publish_1605111925197.js b/.laya/_publish_1605111925197.js new file mode 100644 index 0000000..6ca104e --- /dev/null +++ b/.laya/_publish_1605111925197.js @@ -0,0 +1,559 @@ +// v1.8.0 +//是否使用IDE自带的node环境和插件,设置false后,则使用自己环境(使用命令行方式执行) +const useIDENode = process.argv[0].indexOf("LayaAir") > -1 ? true : false; +const useCMDNode = process.argv[1].indexOf("layaair2-cmd") > -1 ? true : false; +function useOtherNode(){ + return useIDENode||useCMDNode; +} +//获取Node插件和工作路径 +const ideModuleDir = useOtherNode() ? process.argv[1].replace("gulp\\bin\\gulp.js", "").replace("gulp/bin/gulp.js", "") : ""; +const workSpaceDir = useOtherNode() ? process.argv[2].replace("--gulpfile=", "").replace("\\.laya\\publish.js", "").replace("/.laya/publish.js", "") + "/" : "./../"; +global.ideModuleDir = ideModuleDir; +global.workSpaceDir = workSpaceDir; + +//引用插件模块 +const gulp = require(ideModuleDir + "gulp"); +const fs = require("fs"); +const path = require("path"); +const childProcess = require("child_process"); +const uglify = require(ideModuleDir + 'gulp-uglify-es').default; +const jsonminify = require(ideModuleDir + "gulp-jsonminify"); +const image = require(ideModuleDir + "gulp-image"); +const rev = require(ideModuleDir + "gulp-rev"); +const revdel = require(ideModuleDir + "gulp-rev-delete-original"); +const revCollector = require(ideModuleDir + 'gulp-rev-collector'); +const del = require(ideModuleDir + "del"); +const requireDir = require(ideModuleDir + 'require-dir'); +const babel = require(ideModuleDir + 'gulp-babel'); + +// 结合compile.js使用 +global.publish = true; +const fileList = ["compile.js", "publish_xmgame.js", "publish_oppogame.js", "publish_vivogame.js", "publish_biligame.js", "publish_alipaygame.js", "publish_wxgame.js", "publish_bdgame.js", "publish_qqgame.js", "publish_bytedancegame.js", "publish_hwgame.js"]; +requireDir('./', { + filter: function (fullPath) { + // 只用到了compile.js和publish.js + if (fileList.includes(path.basename(fullPath))) { + return true; + } else { + return false; + } + } +}); + +const QUICKGAMELIST = ["xmgame", "oppogame", "vivogame", "hwgame"]; + +// 清理临时文件夹,加载配置 +let config, + releaseDir, + binPath, + platform = "web", + isOpendataProj = false, + platformCopyTask = [],// 平台脚本拷贝任务 + platformTask = [], // 平台需要执行的任务 + commandSuffix = ".cmd", + adbPath = "adb", + opensslPath = "openssl"; +//任务对照列表 +const copyTasks = { + "hwgame": "copyPlatformFile_HW", + "bytedancegame": "copyPlatformFile_ByteDance", + "biligame": "copyPlatformFile_Bili", + "Alipaygame": "copyPlatformFile_Alipay", + "vivogame": "copyPlatformFile_VIVO", + "oppogame": "copyPlatformFile_OPPO", + "xmgame": "copyPlatformFile_XM", + "bdgame": "copyPlatformFile_BD", + "qqgame": "copyPlatformFile_QQ", + "wxgame": "copyPlatformFile_WX", + "web": "copyPlatformLibsJsFile" +} +const tasks = { + "hwgame": "buildHWProj", + "bytedancegame": "buildByteDanceProj", + "biligame": "buildBiliProj", + "Alipaygame": "buildAlipayProj", + "vivogame": "buildVivoProj", + "oppogame": "buildOPPOProj", + "xmgame": "buildXiaomiProj", + "bdgame": "buildBDProj", + "qqgame": "buildQQProj", + "wxgame": "buildWXProj", + "web": "version2" +} + +if (!useOtherNode() && process.argv.length > 5 && process.argv[4] == "--config") { + platform = process.argv[5].replace(".json", ""); +} +if (useOtherNode() && process.argv.length >= 4 && process.argv[3].startsWith("--config") && process.argv[3].endsWith(".json")) { + platform = process.argv[3].match(/(\w+).json/)[1]; + platformCopyTask.push(copyTasks[platform]); + platformTask.push(tasks[platform]); +} + +gulp.task("loadConfig", function (cb) { + let _path; + if (!useOtherNode()) { + _path = platform + ".json"; + releaseDir = "../release/" + platform; + binPath = "../bin/"; + } + if (useOtherNode()) { + _path = path.join(workSpaceDir, ".laya", `${platform}.json`); + releaseDir = path.join(workSpaceDir, "release", platform).replace(/\\/g, "/"); + binPath = path.join(workSpaceDir, "bin").replace(/\\/g, "/"); + } + global.platform = platform; + let file = fs.readFileSync(_path, "utf-8"); + if (file) { + if (QUICKGAMELIST.includes(platform)) { + file = file.replace(/\$basePath/g, releaseDir + "/temprelease"); + } else { + file = file.replace(/\$basePath/g, releaseDir); + } + config = JSON.parse(file); + global.config = config; + } + // 是否是开放域项目 + let projInfoPath = path.join(workSpaceDir, path.basename(workSpaceDir) + ".laya"); + let isExist = fs.existsSync(projInfoPath); + if (isExist) { + try { + let projInfo = fs.readFileSync(projInfoPath, "utf8"); + projInfo = projInfo && JSON.parse(projInfo); + isOpendataProj = projInfo.layaProType === 12; + } catch (e) {} + } + // 其他变量的初始化 + let layarepublicPath = path.join(ideModuleDir, "../", "code", "layarepublic"); + if (!fs.existsSync(layarepublicPath)) { + layarepublicPath = path.join(ideModuleDir, "../", "out", "layarepublic"); + } + global.layarepublicPath = layarepublicPath; + + if (process.platform === "darwin") { + commandSuffix = ""; + } + global.commandSuffix = commandSuffix; + + // 检查环境中是否存在adb和openssl + let otherLibsPath = path.join(layarepublicPath, "../", "vs", "layaEditor", "libs"); + childProcess.exec("adb version", (error, stdout, stderr) => { + if (error) { + if (process.platform === "darwin") { + adbPath = path.join(otherLibsPath, "adb", "darwin", "adb"); + } else { + adbPath = path.join(otherLibsPath, "adb", "win", "adb.exe"); + } + adbPath = `"${adbPath}"`; + } + global.adbPath = adbPath; + if (global.opensslPath) { + cb(); + } + }); + childProcess.exec("openssl version", (error, stdout, stderr) => { + if (error) { + if (process.platform === "darwin") { + opensslPath = path.join(otherLibsPath, "openssl", "darwin", "bin", "openssl"); + } else { + opensslPath = path.join(otherLibsPath, "openssl", "win", "bin", "openssl.exe"); + } + opensslPath = `"${opensslPath}"`; + } + global.opensslPath = opensslPath; + if (global.adbPath) { + cb(); + } + }); +}); + +// 清理release文件夹 +gulp.task("clearReleaseDir", ["compile"], function (cb) { + if (config.clearReleaseDir) { + let delList = [`${releaseDir}/**`, releaseDir + "_pack"]; + if (config.packfileTargetValue) { + delList.push(config.packfileTargetValue); + } + // 小米快游戏,使用即存的项目,删掉Laya工程文件,保留小米环境项目文件 + if (platform === "xmgame") { + let xmProj = path.join(releaseDir, config.xmInfo.projName); + // 这里不是node-glob语法,详见: https://github.com/sindresorhus/del + delList = [`${xmProj}/**`, `!${xmProj}`, `!${xmProj}/node_modules/**`, `!${xmProj}/sign/**`, `!${xmProj}/{babel.config.js,main.js,manifest.json,package.json,package-lock.json}`]; + } else if (platform === "oppogame") { + let oppoProjSrc = path.join(releaseDir, config.oppoInfo.projName); + delList = [`${oppoProjSrc}/**`, `!${oppoProjSrc}`, `!${oppoProjSrc}/{manifest.json,main.js}`]; + } else if (platform === "vivogame") { + let vvProj = path.join(releaseDir, config.vivoInfo.projName); + let vvProjSrc = path.join(vvProj, "src"); + // 这里不是node-glob语法,详见: https://github.com/sindresorhus/del + delList = [`${vvProj}/engine/**`, `${vvProj}/laya-library/**`, `${vvProj}/config/**`, + `${vvProjSrc}/**`, `!${vvProjSrc}`, `!${vvProjSrc}/{game.js,manifest.json}`]; + } else if (platform === "hwgame") { + let hwProjSrc = path.join(releaseDir, config.hwInfo.projName); + delList = [`${hwProjSrc}/**`, `!${hwProjSrc}`, `!${hwProjSrc}/{game.js,manifest.json}`]; + } + // 保留平台配置文件 + if (config.keepPlatformFile) { + if (["wxgame", "qqgame", "Alipaygame", "bytedancegame"].includes(platform)) { + delList = delList.concat(`!${releaseDir}`, `!${releaseDir}/{game.js,game.json,project.config.json}`); + } else if (platform === "bdgame") { + delList = delList.concat(`!${releaseDir}`, `!${releaseDir}/{game.js,game.json,project.swan.json}`); + } else if (platform === "biligame") { + delList = delList.concat(`!${releaseDir}`, `!${releaseDir}/{game.js,game.json}`); + } + } + del(delList, { force: true }).then(paths => { + cb(); + }); + } else cb(); +}); + +// copy bin文件到release文件夹 +gulp.task("copyFile", ["clearReleaseDir"], function () { + let baseCopyFilter = [`${workSpaceDir}/bin/**/*.*`, `!${workSpaceDir}/bin/indexmodule.html`, `!${workSpaceDir}/bin/import/*.*`]; + // 只拷贝index.js中引用的类库 + if (config.onlyIndexJS) { + baseCopyFilter = baseCopyFilter.concat(`!${workSpaceDir}/bin/libs/**/*.*`); + } + if (platform === "wxgame" && isOpendataProj) { // 开放域项目微信发布,仅拷贝用到的文件 + config.copyFilesFilter = [`${workSpaceDir}/bin/js/bundle.js`, `${workSpaceDir}/bin/index.js`, `${workSpaceDir}/bin/game.js`]; + if (config.projectType !== "as") { // 开放域精简类库 + config.copyFilesFilter.push(`${workSpaceDir}/bin/libs/laya.opendata.js`); + } + } else if (platform === "wxgame") { // 微信项目,不拷贝index.html,不拷贝百度bin目录中的文件 + config.copyFilesFilter = baseCopyFilter.concat([`!${workSpaceDir}/bin/index.html`, `!${workSpaceDir}/bin/{project.swan.json,swan-game-adapter.js}`]); + } else if (platform === "bdgame") { // 百度项目,不拷贝index.html,不拷贝微信bin目录中的文件 + config.copyFilesFilter = baseCopyFilter.concat([`!${workSpaceDir}/bin/index.html`, `!${workSpaceDir}/bin/{project.config.json,weapp-adapter.js}`]); + } else { // web|QQ项目|bili|快游戏,不拷贝微信、百度在bin目录中的文件 + config.copyFilesFilter = baseCopyFilter.concat([`!${workSpaceDir}/bin/{game.js,game.json,project.config.json,weapp-adapter.js,project.swan.json,swan-game-adapter.js}`]); + } + // bili/alipay/qq,不拷贝index.html + if (["biligame", "Alipaygame", "qqgame", "bytedancegame"].includes(platform)) { + config.copyFilesFilter = config.copyFilesFilter.concat([`!${workSpaceDir}/bin/index.html`]); + } + // 快游戏,需要新建一个快游戏项目,拷贝的只是项目的一部分,将文件先拷贝到文件夹的临时目录中去 + if (QUICKGAMELIST.includes(platform)) { + config.copyFilesFilter = config.copyFilesFilter.concat([`!${workSpaceDir}/bin/index.html`]); + releaseDir = global.tempReleaseDir = path.join(releaseDir, "temprelease"); + } + if (config.exclude) { // 排除文件 + config.excludeFilter.forEach(function(item, index, list) { + releaseDir = releaseDir.replace(/\\/g, "/"); + config.excludeFilter[index] = item.replace(releaseDir, binPath); + }); + config.copyFilesFilter = config.copyFilesFilter.concat(config.excludeFilter); + } + global.releaseDir = releaseDir; + var stream = gulp.src(config.copyFilesFilter, { base: `${workSpaceDir}/bin` }); + return stream.pipe(gulp.dest(releaseDir)); +}); + +// 使用min版本引擎 +gulp.task("useMinJsLibs", ["copyFile"], function () { + if (!config.useMinJsLibs) { + return; + } + if (platform === "wxgame" && isOpendataProj) { // 开放域项目微信发布,拷贝文件时已经拷贝类库文件了 + return; + } + // 开放域项目,as语言,没有libs目录,mac系统报错 + let libs = path.join(workSpaceDir, "bin", "libs"); + if (!fs.existsSync(libs)) { + return; + } + // 分析index.js + let indexJSPath = path.join(releaseDir, "index.js"); + let indexJsContent = fs.readFileSync(indexJSPath, "utf8"); + let libsList = indexJsContent.match(/loadLib\(['"]libs\/[\w-./]+\.(js|wasm)['"]\)/g); + if (!libsList) { + return; + } + let + item, + libsName = "", + minLibsName = ""; + for (let i = 0, len = libsList.length; i < len; i++) { + item = libsList[i]; + libsName = item.match(/loadLib\(['"]libs\/([\w-./]+\.(js|wasm))['"]\)/); + minLibsName = `min/${libsName[1].replace(".js", ".min.js")}`; + indexJsContent = indexJsContent.replace(libsName[1], minLibsName); + } + fs.writeFileSync(indexJSPath, indexJsContent); +}); + +// copy libs中的js文件到release文件夹 +gulp.task("copyLibsJsFile", ["useMinJsLibs"], function () { + if (!config.onlyIndexJS) { + return; + } + if (platform === "wxgame" && isOpendataProj) { // 开放域项目微信发布,拷贝文件时已经拷贝类库文件了 + return; + } + // 开放域项目,as语言,没有libs目录,mac系统报错 + let libs = path.join(workSpaceDir, "bin", "libs"); + if (!fs.existsSync(libs)) { + return; + } + // 分析index.js + let indexJSPath = path.join(releaseDir, "index.js"); + let indexJsContent = fs.readFileSync(indexJSPath, "utf8"); + let libsList = indexJsContent.match(/loadLib\(['"]libs\/[\w-./]+\.(js|wasm)['"]\)/g); + if (!libsList) { + libsList = []; + } + let + item, + libsName = "", + libsStr = ""; + for (let i = 0, len = libsList.length; i < len; i++) { + item = libsList[i]; + libsName = item.match(/loadLib\(['"]libs\/([\w-./]+\.(js|wasm))['"]\)/); + libsStr += libsStr ? `,${libsName[1]}` : libsName[1]; + } + // 发布web项目,如果使用了physics3D,默认拷贝runtime + if (platform === "web" && libsStr.includes("laya.physics3D")) { + if (config.useMinJsLibs) { + libsStr += ',min/laya.physics3D.runtime.min.js'; + } else { + libsStr += ',laya.physics3D.runtime.js'; + } + } + let copyLibsList = [`${workSpaceDir}/bin/libs/{${libsStr}}`]; + if (!libsStr.includes(",")) { + copyLibsList = [`${workSpaceDir}/bin/libs/${libsStr}`]; + } + var stream = gulp.src(copyLibsList, { base: `${workSpaceDir}/bin` }); + return stream.pipe(gulp.dest(releaseDir)); +}); + +gulp.task("copyPlatformLibsJsFile", ["copyLibsJsFile"], function () { + if (platform === "wxgame" && isOpendataProj) { // 开放域项目微信发布,拷贝文件时已经拷贝类库文件了 + return; + } + // 开放域项目,as语言,没有libs目录,mac系统报错 + let libs = path.join(workSpaceDir, "bin", "libs"); + if (!fs.existsSync(libs)) { + return; + } + if (platform === "web") { + return; + } + + let platformLibName = ""; + switch (platform) { + case "wxgame": + platformLibName = "laya.wxmini.js"; + break; + case "qqgame": + platformLibName = "laya.qqmini.js"; + break; + case "bdgame": + platformLibName = "laya.bdmini.js"; + break; + case "Alipaygame": + platformLibName = "laya.Alipaymini.js"; + break; + case "biligame": + platformLibName = "laya.bilimini.js"; + break; + case "bytedancegame": + platformLibName = "laya.ttmini.js"; + break; + case "oppogame": + platformLibName = "laya.quickgamemini.js"; + break; + case "vivogame": + platformLibName = "laya.vvmini.js"; + break; + case "xmgame": + platformLibName = "laya.xmmini.js"; + break; + case "hwgame": + platformLibName = "laya.hwmini.js"; + break; + } + let copyPath = `${workSpaceDir}/bin/libs`; + if (config.useMinJsLibs) { + platformLibName = platformLibName.replace(".js", ".min.js"); + copyPath = path.join(copyPath, "min"); + } + let copyLibPath = path.join(copyPath, platformLibName); + var stream = gulp.src(copyLibPath, { base: `${workSpaceDir}/bin` }); + return stream.pipe(gulp.dest(releaseDir)); +}); + +// es6toes5 +gulp.task("es6toes5", platformCopyTask, function() { + if (config.es6toes5) { + return gulp.src(`${releaseDir}/**/*.js`, { base: releaseDir }) + .pipe(babel({ + presets: ['@babel/env'], + compact: true + })) + .on('error', function (err) { + console.warn(err.toString()); + }) + .pipe(gulp.dest(releaseDir)); + } +}) + +// 压缩json +gulp.task("compressJson", ["es6toes5"], function () { + if (config.compressJson) { + return gulp.src(config.compressJsonFilter, { base: releaseDir }) + .pipe(jsonminify()) + .pipe(gulp.dest(releaseDir)); + } +}); + +// 压缩js +gulp.task("compressJs", ["compressJson"], function () { + if (config.compressJs) { + return gulp.src(config.compressJsFilter, { base: releaseDir }) + .pipe(uglify({ + mangle: { + keep_fnames:true + } + })) + .on('error', function (err) { + console.warn(err.toString()); + }) + .pipe(gulp.dest(releaseDir)); + } +}); + +// 压缩png,jpg +gulp.task("compressImage", ["compressJs"], function () { + if (config.compressImage) { + return gulp.src(config.compressImageFilter, { base: releaseDir }) + .pipe(image({ + pngquant: true, //PNG优化工具 + optipng: false, //PNG优化工具 + zopflipng: true, //PNG优化工具 + jpegRecompress: false, //jpg优化工具 + mozjpeg: true, //jpg优化工具 + guetzli: false, //jpg优化工具 + gifsicle: false, //gif优化工具 + svgo: false, //SVG优化工具 + concurrent: 10, //并发线程数 + quiet: true //是否是静默方式 + // optipng: ['-i 1', '-strip all', '-fix', '-o7', '-force'], + // pngquant: ['--speed=1', '--force', 256], + // zopflipng: ['-y', '--lossy_8bit', '--lossy_transparent'], + // jpegRecompress: ['--strip', '--quality', 'medium', '--min', 40, '--max', 80], + // mozjpeg: ['-optimize', '-progressive'], + // guetzli: ['--quality', 85] + })) + .pipe(gulp.dest(releaseDir)); + } +}); + +// 生成版本管理信息 +gulp.task("version1", ["compressImage"], function () { + if (config.version) { + return gulp.src(config.versionFilter, { base: releaseDir }) + .pipe(rev()) + .pipe(gulp.dest(releaseDir)) + .pipe(revdel()) + .pipe(rev.manifest("version.json")) + .pipe(gulp.dest(releaseDir)); + } +}); + +// 更新index.js的hash值 +gulp.task("renameIndexJs", ["version1"], function (cb) { + if (config.version) { + let versionPath = releaseDir + "/version.json"; + let versionCon = fs.readFileSync(versionPath, "utf8"); + versionCon = JSON.parse(versionCon); + let indexJSPath; + let indexJsStr = (versionCon && versionCon["index.js"]) ? versionCon["index.js"] : "index.js"; + indexJSPath = releaseDir + "/" + indexJsStr; + + return new Promise((resolve, reject) => { + let srcList = [versionPath, indexJSPath]; + gulp.src(srcList) + .pipe(revCollector()) + .pipe(gulp.dest(releaseDir)); + setTimeout(resolve, 1500); + }).then(function() { + return new Promise(async function(resolve, reject) { + // index-xxx.js => index.js + let indexJsOrigin = path.join(releaseDir, "index.js") + fs.renameSync(indexJSPath, indexJsOrigin); + gulp.src(indexJsOrigin, { base: releaseDir }) + .pipe(rev()) + .pipe(gulp.dest(releaseDir)) + .pipe(revdel()) + .pipe(rev.manifest({ + path: versionPath, + merge: true + })) + .pipe(gulp.dest("./")); // 注意,这里不能是releaseDir (https://segmentfault.com/q/1010000002876613) + setTimeout(cb, 2000); + }) + }).catch(function(e) { + throw e; + }) + } else { + cb(); + } +}); + +// 替换index.html/game.js/main.js以及index.js里面的变化的文件名 +gulp.task("version2", ["renameIndexJs"], function () { + if (config.version) { + //替换index.html和index.js里面的文件名称 + let htmlPath = releaseDir + "/index.html"; + let versionPath = releaseDir + "/version.json"; + let gameJSPath = releaseDir + "/game.js"; + let mainJSPath = releaseDir + "/main.js"; + let indexJSPath; + let versionCon = fs.readFileSync(versionPath, "utf8"); + versionCon = JSON.parse(versionCon); + let indexJsStr = (versionCon && versionCon["index.js"]) ? versionCon["index.js"] : "index.js"; + indexJSPath = releaseDir + "/" + indexJsStr; + // 替换config.packfileFullValue中的路径 + let packfileStr = JSON.stringify(config.packfileFullValue).replace(/\\\\/g, "/"); + let tempPackfile = `${workSpaceDir}/.laya/configTemp.json`; + fs.writeFileSync(tempPackfile, packfileStr, "utf8"); + + let srcList = [versionPath, indexJSPath, tempPackfile]; + if (fs.existsSync(htmlPath)) { + srcList.push(htmlPath); + } + if (fs.existsSync(gameJSPath)) { + srcList.push(gameJSPath); + } + if (fs.existsSync(mainJSPath)) { + srcList.push(mainJSPath); + } + return gulp.src(srcList) + .pipe(revCollector()) + .pipe(gulp.dest(releaseDir)); + } +}); + +// 筛选4M包 +gulp.task("packfile", platformTask, function() { + if (config.version) { + releaseDir = releaseDir.replace("temprelease", "quickgame"); + // 从release目录取得带有版本号的目录 + let tempPackfile = `${workSpaceDir}/.laya/configTemp.json`; + let releasePackfile = `${releaseDir}/configTemp.json`; + let packfileStr = fs.readFileSync(releasePackfile, "utf8"); + config.packfileFullValue = JSON.parse(packfileStr); + // 删掉临时目录 + fs.unlinkSync(tempPackfile); + fs.unlinkSync(releasePackfile); + } + if (config.packfile) { // 提取本地包(文件列表形式) + return gulp.src(config.packfileFullValue, { base: releaseDir }) + .pipe(gulp.dest(config.packfileTargetValue || releaseDir + "_pack")); + } +}); + +// 起始任务 +gulp.task("publish", ["packfile"] , function () { + console.log("All tasks completed!"); +}); \ No newline at end of file diff --git a/.laya/_publish_hwgame_1605111925152.js b/.laya/_publish_hwgame_1605111925152.js new file mode 100644 index 0000000..d3e8cab --- /dev/null +++ b/.laya/_publish_hwgame_1605111925152.js @@ -0,0 +1,590 @@ +// v1.0.3 +const ideModuleDir = global.ideModuleDir; +const workSpaceDir = global.workSpaceDir; + +//引用插件模块 +const gulp = require(ideModuleDir + "gulp"); +const fs = require("fs"); +const path = require("path"); +const https = require("https"); +const childProcess = require("child_process"); +const del = require(ideModuleDir + "del"); +const revCollector = require(ideModuleDir + 'gulp-rev-collector'); +const iconv = require(ideModuleDir + "iconv-lite"); +const request = require(ideModuleDir + "request"); + +let copyLibsTask = ["copyPlatformLibsJsFile"]; +let versiontask = ["version2"]; + +let + config, + releaseDir, + toolkitPath, + tempReleaseDir, // 华为临时拷贝目录 + projDir; // 华为快游戏工程目录 +let versionCon; // 版本管理version.json +let commandSuffix, + adbPath, + opensslPath, + layarepublicPath; +let isDevices = false; + +// 创建华为项目前,拷贝华为引擎库、修改index.js +gulp.task("preCreate_HW", copyLibsTask, function() { + releaseDir = global.releaseDir; + config = global.config; + commandSuffix = global.commandSuffix; + adbPath = global.adbPath; + opensslPath = global.opensslPath; + layarepublicPath = global.layarepublicPath; + tempReleaseDir = global.tempReleaseDir; + + toolkitPath = path.join(layarepublicPath, "pub_huawei"); +}); + +gulp.task("copyPlatformFile_HW", ["preCreate_HW"], function() { + let hwAdapterPath = path.join(layarepublicPath, "LayaAirProjectPack", "lib", "data", "hwfiles"); + let copyLibsList = [`${hwAdapterPath}/**/*.*`]; + var stream = gulp.src(copyLibsList); + return stream.pipe(gulp.dest(tempReleaseDir)); +}); + +// 新建华为项目-华为项目与其他项目不同,需要安装华为 quickgame node_modules,并打包成.rpk文件 +gulp.task("installModules_HW", versiontask, function() { + releaseDir = path.dirname(releaseDir); + projDir = path.join(releaseDir, config.hwInfo.projName); + // 如果IDE里对应华为包已经install node_modules了,忽略这一步 + if (fs.existsSync(path.join(toolkitPath, "node_modules"))) { + return; + } + // 安装华为 quickgame node_modules + return new Promise((resolve, reject) => { + console.log("开始安装华为 toolkit node_modules,请耐心等待..."); + let cmd = `npm${commandSuffix}`; + let args = ["install"]; + let opts = { + cwd: toolkitPath, + shell: true + }; + let cp = childProcess.spawn(cmd, args, opts); + + cp.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + cp.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + // reject(); + }); + + cp.on('close', (code) => { + console.log(`子进程退出码:${code}`); + resolve(); + }); + }); +}); + +// 拷贝文件到华为快游戏 +gulp.task("copyFileToProj_HW", ["installModules_HW"], function() { + // 将临时文件夹中的文件,拷贝到项目中去 + let originalDir = `${tempReleaseDir}/**/*.*`; + let stream = gulp.src(originalDir); + return stream.pipe(gulp.dest(path.join(projDir))); +}); + +// 拷贝icon到华为快游戏 +gulp.task("copyIconToProj_HW", ["copyFileToProj_HW"], function() { + let originalDir = config.hwInfo.icon; + let stream = gulp.src(originalDir); + return stream.pipe(gulp.dest(path.join(projDir))); +}); + +// 清除华为快游戏临时目录 +gulp.task("clearTempDir_HW", ["copyIconToProj_HW"], function() { + // 删掉临时目录 + return del([tempReleaseDir], { force: true }); +}); + +// 生成release签名(私钥文件 private.pem 和证书文件 certificate.pem ) +gulp.task("generateSign_HW", ["clearTempDir_HW"], function() { + if (!config.hwSign.generateSign) { + return; + } + // https://doc.quickapp.cn/tools/compiling-tools.html + return new Promise((resolve, reject) => { + let cmd = `${opensslPath}`; + let args = ["req", "-newkey", "rsa:2048", "-nodes", "-keyout", "private.pem", + "-x509", "-days", "3650", "-out", "certificate.pem"]; + let opts = { + cwd: projDir, + shell: true + }; + let cp = childProcess.spawn(cmd, args, opts); + cp.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + cp.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + data += ""; + if (data.includes("Country Name")) { + cp.stdin.write(`${config.hwSign.countryName}\n`); + console.log(`Country Name: ${config.hwSign.countryName}`); + } else if (data.includes("Province Name")) { + cp.stdin.write(`${config.hwSign.provinceName}\n`); + console.log(`Province Name: ${config.hwSign.provinceName}`); + } else if (data.includes("Locality Name")) { + cp.stdin.write(`${config.hwSign.localityName}\n`); + console.log(`Locality Name: ${config.hwSign.localityName}`); + } else if (data.includes("Organization Name")) { + cp.stdin.write(`${config.hwSign.orgName}\n`); + console.log(`Organization Name: ${config.hwSign.orgName}`); + } else if (data.includes("Organizational Unit Name")) { + cp.stdin.write(`${config.hwSign.orgUnitName}\n`); + console.log(`Organizational Unit Name: ${config.hwSign.orgUnitName}`); + } else if (data.includes("Common Name")) { + cp.stdin.write(`${config.hwSign.commonName}\n`); + console.log(`Common Name: ${config.hwSign.commonName}`); + } else if (data.includes("Email Address")) { + cp.stdin.write(`${config.hwSign.emailAddr}\n`); + console.log(`Email Address: ${config.hwSign.emailAddr}`); + // cp.stdin.end(); + } + // reject(); + }); + + cp.on('close', (code) => { + console.log(`子进程退出码:${code}`); + resolve(); + }); + }); +}); + +// 拷贝sign文件到指定位置 +gulp.task("copySignFile_HW", ["generateSign_HW"], function() { + // debug签名拷贝,默认拷贝 + let + privatePem = path.join(toolkitPath, "sign", "debug", "private.pem"), + certificatePem = path.join(toolkitPath, "sign", "debug", "certificate.pem"); + let isSignExits = fs.existsSync(privatePem) && fs.existsSync(certificatePem); + if (!isSignExits) { + return; + } + let + signDest = `${projDir}/sign/debug`; + let stream = gulp.src([privatePem, certificatePem]); + stream.pipe(gulp.dest(signDest)); + + if (config.hwSign.generateSign) { // 新生成的签名 + // 移动签名文件到项目中(Laya & 华为快游戏项目中) + let + privatePem = path.join(projDir, "private.pem"), + certificatePem = path.join(projDir, "certificate.pem"); + let isSignExits = fs.existsSync(privatePem) && fs.existsSync(certificatePem); + if (!isSignExits) { + return; + } + let + xiaomiDest = `${projDir}/sign/release`, + layaDest = `${workSpaceDir}/sign/release`; + let stream = gulp.src([privatePem, certificatePem]); + return stream.pipe(gulp.dest(xiaomiDest)) + .pipe(gulp.dest(layaDest)); + } else if (config.hwInfo.useReleaseSign && !config.hwSign.generateSign) { // 使用release签名,并且没有重新生成 + // 从项目中将签名拷贝到华为快游戏项目中 + let + privatePem = path.join(workSpaceDir, "sign", "release", "private.pem"), + certificatePem = path.join(workSpaceDir, "sign", "release", "certificate.pem"); + let isSignExits = fs.existsSync(privatePem) && fs.existsSync(certificatePem); + if (!isSignExits) { + return; + } + let + xiaomiDest = `${projDir}/sign/release`; + let stream = gulp.src([privatePem, certificatePem]); + return stream.pipe(gulp.dest(xiaomiDest)); + } +}); + +gulp.task("deleteSignFile_HW", ["copySignFile_HW"], function() { + if (config.hwSign.generateSign) { // 新生成的签名 + let + privatePem = path.join(projDir, "private.pem"), + certificatePem = path.join(projDir, "certificate.pem"); + return del([privatePem, certificatePem], { force: true }); + } +}); + +gulp.task("modifyFile_HW", ["deleteSignFile_HW"], function() { + // 修改manifest.json文件 + let manifestPath = path.join(projDir, "manifest.json"); + let manifestJson; + if (fs.existsSync(manifestPath)) { + let manifestContent = fs.readFileSync(manifestPath, "utf8"); + manifestJson = JSON.parse(manifestContent); + } else { + manifestJson = { + "package": "", + "name": "", + "appType": "fastgame", + "icon": "", + "versionName": "", + "versionCode": 0, + "minPlatformVersion": 1000, + "config": { + "logLevel": "off" + }, + "display": { + "orientation": "portrait" + } + } + } + manifestJson.package = config.hwInfo.package; + manifestJson.name = config.hwInfo.name; + manifestJson.display.orientation = config.hwInfo.orientation; + manifestJson.config.logLevel = config.hwInfo.logLevel || "off"; + manifestJson.versionName = config.hwInfo.versionName; + manifestJson.versionCode = config.hwInfo.versionCode; + manifestJson.minPlatformVersion = config.hwInfo.minPlatformVersion; + manifestJson.icon = `/${path.basename(config.hwInfo.icon)}`; + if (config.hwInfo.subpack) { + let hwSubpackList = []; + for (let i = 0, len = config.hwSubpack.length; i < len; i++) { + hwSubpackList.push({ + name: config.hwSubpack[i].name, + resource: config.hwSubpack[i].root + }) + } + manifestJson.subpackages = hwSubpackList; + } else { + delete manifestJson.subpackages; + } + + fs.writeFileSync(manifestPath, JSON.stringify(manifestJson, null, 4), "utf8"); + + if (config.version) { + let versionPath = projDir + "/version.json"; + versionCon = fs.readFileSync(versionPath, "utf8"); + versionCon = JSON.parse(versionCon); + } + let indexJsStr = (versionCon && versionCon["index.js"]) ? versionCon["index.js"] : "index.js"; + // 华为项目,修改game.js + let filePath = path.join(projDir, "game.js"); + if (!fs.existsSync(filePath)) { + let fileContent = `require("./huawei-adapter.js");\nrequire("./libs/laya.hwmini.js");\nrequire("index.js");`; + fs.writeFileSync(filePath, fileContent, "utf8"); + } + + // 华为项目,修改index.js + let indexFilePath = path.join(projDir, indexJsStr); + if (!fs.existsSync(indexFilePath)) { + return; + } + let indexFileContent = fs.readFileSync(indexFilePath, "utf8"); + indexFileContent = indexFileContent.replace(/loadLib(\(['"])/gm, "require$1./"); + fs.writeFileSync(indexFilePath, indexFileContent, "utf8"); +}); + +gulp.task("modifyMinJs_HW", ["modifyFile_HW"], function() { + let fileJsPath = path.join(projDir, "game.js"); + let content = fs.readFileSync(fileJsPath, "utf-8"); + if (!config.useMinJsLibs) { // 默认保留了平台文件,如果同时取消使用min类库,就会出现文件引用不正确的问题 + content = content.replace(/min\/laya(-[\w\d]+)?\.hwmini\.min\.js/gm, "laya.hwmini.js"); + } else { + content = content.replace(/(min\/)?laya(-[\w\d]+)?\.hwmini(\.min)?\.js/gm, "min/laya.hwmini.min.js"); + } + fs.writeFileSync(fileJsPath, content, 'utf-8'); +}); + +gulp.task("version_HW", ["modifyMinJs_HW"], function () { + // main.js默认不覆盖,如果同时开启版本管理,就会出现文件引用不正确的问题 + let fileJsPath = path.join(projDir, "game.js"); + let content = fs.readFileSync(fileJsPath, "utf-8"); + content = content.replace(/laya(-[\w\d]+)?\.hwmini/gm, "laya.hwmini"); + content = content.replace(/index(-[\w\d]+)?\.js/gm, "index.js"); + fs.writeFileSync(fileJsPath, content, 'utf-8'); + + if (config.version) { + let versionPath = projDir + "/version.json"; + let mainJSPath = projDir + "/game.js"; + let srcList = [versionPath, mainJSPath]; + return gulp.src(srcList) + .pipe(revCollector()) + .pipe(gulp.dest(projDir)); + } +}); + +// 打包rpk +gulp.task("buildRPK_HW", ["version_HW"], function() { + // 在华为快游戏项目目录中执行: + // node .\signtool\package\index.js .\web .\dist com.demo .\release\private.pem .\release\certificate.pem + let + signtoolPath = path.join(toolkitPath, "index.js"), + releasePath = projDir, + distPath = path.join(projDir, "dist"), + name = config.hwInfo.package, + privatePem = path.join(projDir, "sign", "debug", "private.pem"), + certificatePemPath = path.join(projDir, "sign", "debug", "certificate.pem"); + if (config.hwInfo.useReleaseSign) { + privatePem = path.join(projDir, "sign", "release", "private.pem"), + certificatePemPath = path.join(projDir, "sign", "release", "certificate.pem"); + } + return new Promise((resolve, reject) => { + let cmd = `node`; + let args = [`"${signtoolPath}"`, `"${releasePath}"`, `"${distPath}"`, name, `"${privatePem}"`, `"${certificatePemPath}"`]; + let opts = { + cwd: projDir, + shell: true + }; + let cp = childProcess.spawn(cmd, args, opts); + // let cp = childProcess.spawn('npx.cmd', ['-v']); + cp.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + cp.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + console.log(`stderr(iconv): ${iconv.decode(data, 'gbk')}`); + // reject(); + }); + + cp.on('close', (code) => { + console.log(`子进程退出码:${code}`); + resolve(); + }); + }); +}); + + +gulp.task("getDevices_HW", ["buildRPK_HW"], function(cb) { + let cmd = `${adbPath} devices`; + childProcess.exec(cmd, (error, stdout, stderr) => { + if (error) { + console.error("获取设备失败..."); + return cb(); + } + if (stdout && stdout.match(/\bdevice\b/)) { + isDevices = true; + } + console.log(`检测到设备: ${isDevices}`); + return cb(); + }); +}); + +// 更新快应用加载器 +gulp.task("updateAPK_HW", ["getDevices_HW"], function(cb) { + if (!config.hwInfo.apkUpdate || !isDevices) { + return cb(); + } + let remoteInfo, remoteAPKVer, localAPKVer; + new Promise((resolve, reject) => { + https.get('https://deveco.huawei.com/FastIDE/update/api/update/engineVersion/', (res) => { + res.on('data', (data) => { + remoteInfo = JSON.parse(data); + remoteAPKVer = remoteInfo.version; + console.log("remote apk version: ", remoteAPKVer); + resolve(); + }); + }).on('error', (e) => { + reject(`获取远端快应用加载器失败: ${e}`); + }); + }).then(() => { + return new Promise((resolve, reject) => { + let cmd = `${adbPath} shell dumpsys package com.huawei.fastapp.dev | ${process.platform === "darwin" ? "grep" : "findstr"} versionName`; + childProcess.exec(cmd, (error, stdout, stderr) => { + if (error) { + console.log("获取快应用加载器本地版本号失败: "); + console.log(error); + console.log(stderr); + return resolve(error); + } + let matchList = stdout.match(/versionName=(.+)/); + if (!Array.isArray(matchList)) { + console.log("获取快应用加载器本地版本号失败: "); + return resolve(); + } + localAPKVer = matchList[1]; + console.log("local apk version: ", localAPKVer); + resolve(); + }); + }); + }).then(() => { + return new Promise((resolve, reject) => { + if (remoteAPKVer === localAPKVer) { + console.log("您的快应用加载器是最新版本!"); + return resolve(); + } + let url = remoteInfo.url; + let apkName = path.basename(url); + let apkDownRoot = path.join(toolkitPath, "fastapp"); + let apkDownPath = path.join(apkDownRoot, apkName); + // 1) 如果本地已经有最新版本的快应用加载器,则不再下载 + if (fs.existsSync(apkDownPath)) { + console.log("您本地有最新版本的快应用加载器,将直接安装!"); + return installAPK().then(() => { + return resolve(); + }).catch((err) => { + return reject(err); + }) + } + // 2) 下载并安装快应用加载器 + console.log("正在下载快应用加载器,请稍等..."); + !(fs.existsSync(apkDownRoot)) && fs.mkdirSync(apkDownRoot); + downFileToDir(url, apkDownPath).then(() => { + return installAPK(); + }).then(() => { + return resolve(); + }).catch((err) => { + return reject(err); + }) + + // 安装apk + function installAPK() { + return new Promise((resolve, reject) => { + console.log("正在安装快应用加载器,请稍等..."); + let cmd = `${adbPath} install -r ${apkDownPath}`; + childProcess.exec(cmd, (error, stdout, stderr) => { + if (error) { + console.error("安装快应用加载器本地版本号失败: "); + console.error(error); + console.error(stderr); + return reject(error); + } + console.log("安装快应用加载器成功!"); + resolve(); + }); + }) + } + }); + }).then(() => { + return cb(); + }).catch((re) => { + console.error("更新快应用加载器失败: ", re); + return cb(); + }); +}); + +function downFileToDir(uri, dest){ + return new Promise((resolve, reject) => { + if (!uri || !dest) { + reject(new Error(`downFileToDir 参数不全: ${uri}/${dest}`)); + return; + } + + let + totalLen = 9999, + progress = 0, + layaresponse; + var stream = fs.createWriteStream(dest); + request(uri).on('error', function(err) { + console.log("tool down err:" + err); + reject(err); + }).on("data", function(data) { + progress += data.length; + let downPercent = (progress / totalLen * 100).toFixed(3); + // console.log(`down: ${downPercent}%`); + }).on("response", function(response) { + layaresponse = response; + totalLen = response.caseless.dict['content-length']; + }).pipe(stream).on('close', function() { + if (layaresponse.statusCode == 200) { + console.log("下载成功!"); + resolve(); + } else { + reject(new Error("下载失败,连接关闭")); + } + }); + }); +} + +gulp.task("pushRPK_HW", ["updateAPK_HW"], function() { + if (!config.hwInfo.adbDebug || !isDevices) { + return; + } + // 在华为快游戏项目目录中执行: + // adb shell am force-stop com.huawei.fastapp.dev + // adb push {rpk_file_path} /data/local/tmp/ + // adb shell am start --es rpkpath /data/local/tmp/{rpk_file_name} --ei debugmode 1 --activity-clear-top com.huawei.fastapp.dev/com.huawei.fastapp.app.RpkRunnerActivity + return new Promise((resolve, reject) => { + // adb shell am force-stop com.huawei.fastapp.dev + console.log(`1) force-stop: `); + let cmd = `${adbPath}`; + let args = ["shell", "am", "force-stop", "com.huawei.fastapp.dev"]; + let opts = { + cwd: projDir, + shell: true + }; + let cp = childProcess.spawn(cmd, args, opts); + // let cp = childProcess.spawn('npx.cmd', ['-v']); + cp.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + cp.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + // reject(); + }); + + cp.on('close', (code) => { + console.log(`force-stop 子进程退出码:${code}`); + resolve(); + }); + }).then(() => { + return new Promise((resolve, reject) => { + // adb push {rpk_file_path} /data/local/tmp/ + console.log(`2) push_RPK: `); + let rpkFilePath = path.join(projDir, "dist", `${config.hwInfo.package}.rpk`); + let cmd = `${adbPath}`; + let args = ["push", rpkFilePath, "/data/local/tmp/"]; + let opts = { + cwd: projDir, + shell: true + }; + let cp = childProcess.spawn(cmd, args, opts); + // let cp = childProcess.spawn('npx.cmd', ['-v']); + cp.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + cp.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + // reject(); + }); + + cp.on('close', (code) => { + console.log(`push_RPK 子进程退出码:${code}`); + resolve(); + }); + }); + }).then(() => { + return new Promise((resolve, reject) => { + // adb shell am start --es rpkpath /data/local/tmp/{rpk_file_name} --ei debugmode 1 --activity-clear-top com.huawei.fastapp.dev/com.huawei.fastapp.app.RpkRunnerActivity + console.log(`3) 启动apk,加载rpk: `); + let cmd = `${adbPath}`; + let args = ["shell", "am", "start", "--es", "rpkpath", `file://data/local/tmp/${config.hwInfo.package}.rpk`, "--ei", "debugmode", "1", "--activity-clear-top", "com.huawei.fastapp.dev/com.huawei.fastapp.app.RpkRunnerActivity"]; + let opts = { + cwd: projDir, + shell: true + }; + let cp = childProcess.spawn(cmd, args, opts); + // let cp = childProcess.spawn('npx.cmd', ['-v']); + cp.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + cp.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + // reject(); + }); + + cp.on('close', (code) => { + console.log(`启动apk,加载rpk: 子进程退出码:${code}`); + resolve(); + }); + }); + }); +}); + +gulp.task("buildHWProj", ["pushRPK_HW"], function() { + console.log("all tasks completed"); +}); \ No newline at end of file diff --git a/.laya/_publish_oppogame_1605111925187.js b/.laya/_publish_oppogame_1605111925187.js new file mode 100644 index 0000000..6dbaadf --- /dev/null +++ b/.laya/_publish_oppogame_1605111925187.js @@ -0,0 +1,413 @@ +// v1.8.1 +const ideModuleDir = global.ideModuleDir; +const workSpaceDir = global.workSpaceDir; + +//引用插件模块 +const gulp = require(ideModuleDir + "gulp"); +const fs = require("fs"); +const path = require("path"); +const childProcess = require("child_process"); +const del = require(ideModuleDir + "del"); +const revCollector = require(ideModuleDir + 'gulp-rev-collector'); +const iconv = require(ideModuleDir + "iconv-lite"); + +let copyLibsTask = ["copyPlatformLibsJsFile"]; +let versiontask = ["version2"]; + +let + config, + releaseDir, + toolkitPath, + tempReleaseDir, // OPPO临时拷贝目录 + projDir; // OPPO快游戏工程目录 +let versionCon; // 版本管理version.json +let commandSuffix, + adbPath, + opensslPath, + layarepublicPath; + +// 创建OPPO项目前,拷贝OPPO引擎库、修改index.js +gulp.task("preCreate_OPPO", copyLibsTask, function() { + releaseDir = global.releaseDir; + config = global.config; + commandSuffix = global.commandSuffix; + adbPath = global.adbPath; + opensslPath = global.opensslPath; + layarepublicPath = global.layarepublicPath; + tempReleaseDir = global.tempReleaseDir; + + toolkitPath = path.join(layarepublicPath, "oppo", "quickgame-toolkit"); +}); + +gulp.task("copyPlatformFile_OPPO", ["preCreate_OPPO"], function() { + return; +}); + +// 新建OPPO项目-OPPO项目与其他项目不同,需要安装OPPO quickgame node_modules,并打包成.rpk文件 +gulp.task("installModules_OPPO", versiontask, function() { + releaseDir = path.dirname(releaseDir); + projDir = path.join(releaseDir, config.oppoInfo.projName); + // 如果IDE里对应OPPO包已经install node_modules了,忽略这一步 + if (fs.existsSync(path.join(toolkitPath, "node_modules"))) { + return; + } + // 安装OPPO quickgame node_modules + return new Promise((resolve, reject) => { + console.log("开始安装OPPO quickgame node_modules,请耐心等待..."); + let cmd = `npm${commandSuffix}`; + let args = ["install"]; + let opts = { + cwd: toolkitPath, + shell: true + }; + let cp = childProcess.spawn(cmd, args, opts); + + cp.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + cp.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + // reject(); + }); + + cp.on('close', (code) => { + console.log(`子进程退出码:${code}`); + resolve(); + }); + }); +}); + +// 拷贝文件到OPPO快游戏 +gulp.task("copyFileToProj_OPPO", ["installModules_OPPO"], function() { + // 将临时文件夹中的文件,拷贝到项目中去 + let originalDir = `${tempReleaseDir}/**/*.*`; + let stream = gulp.src(originalDir); + return stream.pipe(gulp.dest(path.join(projDir))); +}); + +// 拷贝icon到OPPO快游戏 +gulp.task("copyIconToProj_OPPO", ["copyFileToProj_OPPO"], function() { + let originalDir = config.oppoInfo.icon; + let stream = gulp.src(originalDir); + return stream.pipe(gulp.dest(path.join(projDir))); +}); + +// 清除OPPO快游戏临时目录 +gulp.task("clearTempDir_OPPO", ["copyIconToProj_OPPO"], function() { + // 删掉临时目录 + return del([tempReleaseDir], { force: true }); +}); + +// 生成release签名(私钥文件 private.pem 和证书文件 certificate.pem ) +gulp.task("generateSign_OPPO", ["clearTempDir_OPPO"], function() { + if (!config.oppoSign.generateSign) { + return; + } + // https://doc.quickapp.cn/tools/compiling-tools.html + return new Promise((resolve, reject) => { + let cmd = `${opensslPath}`; + let args = ["req", "-newkey", "rsa:2048", "-nodes", "-keyout", "private.pem", + "-x509", "-days", "3650", "-out", "certificate.pem"]; + let opts = { + cwd: projDir, + shell: true + }; + let cp = childProcess.spawn(cmd, args, opts); + cp.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + cp.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + data += ""; + if (data.includes("Country Name")) { + cp.stdin.write(`${config.oppoSign.countryName}\n`); + console.log(`Country Name: ${config.oppoSign.countryName}`); + } else if (data.includes("Province Name")) { + cp.stdin.write(`${config.oppoSign.provinceName}\n`); + console.log(`Province Name: ${config.oppoSign.provinceName}`); + } else if (data.includes("Locality Name")) { + cp.stdin.write(`${config.oppoSign.localityName}\n`); + console.log(`Locality Name: ${config.oppoSign.localityName}`); + } else if (data.includes("Organization Name")) { + cp.stdin.write(`${config.oppoSign.orgName}\n`); + console.log(`Organization Name: ${config.oppoSign.orgName}`); + } else if (data.includes("Organizational Unit Name")) { + cp.stdin.write(`${config.oppoSign.orgUnitName}\n`); + console.log(`Organizational Unit Name: ${config.oppoSign.orgUnitName}`); + } else if (data.includes("Common Name")) { + cp.stdin.write(`${config.oppoSign.commonName}\n`); + console.log(`Common Name: ${config.oppoSign.commonName}`); + } else if (data.includes("Email Address")) { + cp.stdin.write(`${config.oppoSign.emailAddr}\n`); + console.log(`Email Address: ${config.oppoSign.emailAddr}`); + // cp.stdin.end(); + } + // reject(); + }); + + cp.on('close', (code) => { + console.log(`子进程退出码:${code}`); + resolve(); + }); + }); +}); + +// 拷贝sign文件到指定位置 +gulp.task("copySignFile_OPPO", ["generateSign_OPPO"], function() { + if (config.oppoSign.generateSign) { // 新生成的签名 + // 移动签名文件到项目中(Laya & OPPO快游戏项目中) + let + privatePem = path.join(projDir, "private.pem"), + certificatePem = path.join(projDir, "certificate.pem"); + let isSignExits = fs.existsSync(privatePem) && fs.existsSync(certificatePem); + if (!isSignExits) { + return; + } + let + xiaomiDest = `${projDir}/sign/release`, + layaDest = `${workSpaceDir}/sign/release`; + let stream = gulp.src([privatePem, certificatePem]); + return stream.pipe(gulp.dest(xiaomiDest)) + .pipe(gulp.dest(layaDest)); + } else if (config.oppoInfo.useReleaseSign && !config.oppoSign.generateSign) { // 使用release签名,并且没有重新生成 + // 从项目中将签名拷贝到OPPO快游戏项目中 + let + privatePem = path.join(workSpaceDir, "sign", "release", "private.pem"), + certificatePem = path.join(workSpaceDir, "sign", "release", "certificate.pem"); + let isSignExits = fs.existsSync(privatePem) && fs.existsSync(certificatePem); + if (!isSignExits) { + return; + } + let + xiaomiDest = `${projDir}/sign/release`; + let stream = gulp.src([privatePem, certificatePem]); + return stream.pipe(gulp.dest(xiaomiDest)); + } +}); + +gulp.task("deleteSignFile_OPPO", ["copySignFile_OPPO"], function() { + if (config.oppoSign.generateSign) { // 新生成的签名 + let + privatePem = path.join(projDir, "private.pem"), + certificatePem = path.join(projDir, "certificate.pem"); + return del([privatePem, certificatePem], { force: true }); + } +}); + +gulp.task("modifyFile_OPPO", ["deleteSignFile_OPPO"], function() { + // 修改manifest.json文件 + let manifestPath = path.join(projDir, "manifest.json"); + let IDEManifestPath = path.join(toolkitPath, "tpl", "manifest.json"); + if (!fs.existsSync(IDEManifestPath) && !fs.existsSync(manifestPath)) { + return; + } + let manifestContent; + if (fs.existsSync(manifestPath)) { + manifestContent = fs.readFileSync(manifestPath, "utf8"); + } else { + manifestContent = fs.readFileSync(IDEManifestPath, "utf8"); + } + let manifestJson = JSON.parse(manifestContent); + manifestJson.package = config.oppoInfo.package; + manifestJson.name = config.oppoInfo.name; + manifestJson.orientation = config.oppoInfo.orientation; + manifestJson.config.logLevel = config.oppoInfo.logLevel || "off"; + manifestJson.versionName = config.oppoInfo.versionName; + manifestJson.versionCode = config.oppoInfo.versionCode; + manifestJson.minPlatformVersion = config.oppoInfo.minPlatformVersion; + manifestJson.icon = `./${path.basename(config.oppoInfo.icon)}`; + if (config.oppoInfo.subpack) { + manifestJson.subpackages = config.oppoSubpack; + } else { + delete manifestJson.subpackages; + } + fs.writeFileSync(manifestPath, JSON.stringify(manifestJson, null, 4), "utf8"); + + if (config.version) { + let versionPath = projDir + "/version.json"; + versionCon = fs.readFileSync(versionPath, "utf8"); + versionCon = JSON.parse(versionCon); + } + let indexJsStr = (versionCon && versionCon["index.js"]) ? versionCon["index.js"] : "index.js"; + // OPPO项目,修改main.js + let filePath = path.join(projDir, "main.js"); + if (!fs.existsSync(filePath)) { + let fileContent = `window.navigator.userAgent = 'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/603.1.30 (KHTML, like Gecko) Mobile/14E8301 OPPO MiniGame NetType/WIFI Language/zh_CN'; +require("./libs/laya.quickgamemini.js");\nrequire("index.js");`; + fs.writeFileSync(filePath, fileContent, "utf8"); + } + + // OPPO项目,修改index.js + let indexFilePath = path.join(projDir, indexJsStr); + if (!fs.existsSync(indexFilePath)) { + return; + } + let indexFileContent = fs.readFileSync(indexFilePath, "utf8"); + indexFileContent = indexFileContent.replace(/loadLib(\(['"])/gm, "require$1./"); + fs.writeFileSync(indexFilePath, indexFileContent, "utf8"); +}); + +gulp.task("modifyMinJs_OPPO", ["modifyFile_OPPO"], function() { + let fileJsPath = path.join(projDir, "main.js"); + let content = fs.readFileSync(fileJsPath, "utf-8"); + if (!config.useMinJsLibs) { // 默认保留了平台文件,如果同时取消使用min类库,就会出现文件引用不正确的问题 + content = content.replace(/min\/laya(-[\w\d]+)?\.quickgamemini\.min\.js/gm, "laya.quickgamemini.js"); + } else { + content = content.replace(/(min\/)?laya(-[\w\d]+)?\.quickgamemini(\.min)?\.js/gm, "min/laya.quickgamemini.min.js"); + } + fs.writeFileSync(fileJsPath, content, 'utf-8'); +}); + +gulp.task("version_OPPO", ["modifyMinJs_OPPO"], function () { + // main.js默认不覆盖,如果同时开启版本管理,就会出现文件引用不正确的问题 + let fileJsPath = path.join(projDir, "main.js"); + let content = fs.readFileSync(fileJsPath, "utf-8"); + content = content.replace(/laya(-[\w\d]+)?\.quickgamemini/gm, "laya.quickgamemini"); + content = content.replace(/index(-[\w\d]+)?\.js/gm, "index.js"); + fs.writeFileSync(fileJsPath, content, 'utf-8'); + + if (config.version) { + let versionPath = projDir + "/version.json"; + let mainJSPath = projDir + "/main.js"; + let srcList = [versionPath, mainJSPath]; + return gulp.src(srcList) + .pipe(revCollector()) + .pipe(gulp.dest(projDir)); + } +}); + +// 打包rpk +gulp.task("buildRPK_OPPO", ["version_OPPO"], function() { + // 在OPPO轻游戏项目目录中执行: + // quickgame pack || quickgame pack release + // quickgame subpack --no-build-js || quickgame subpack release --no-build-js + let cmdStr = ""; + let packStr = "pack"; + let nobuildjs = ""; + if (config.oppoInfo.subpack) { + packStr = "subpack"; + nobuildjs = "--no-build-js"; + } + if (config.oppoInfo.useReleaseSign) { + cmdStr = "release"; + } + return new Promise((resolve, reject) => { + let cmd = path.join(toolkitPath, "lib", "bin", `quickgame${commandSuffix}`); + let args = [packStr, cmdStr, nobuildjs]; + let opts = { + cwd: projDir, + shell: true + }; + let cp = childProcess.spawn(`"${cmd}"`, args, opts); + // let cp = childProcess.spawn('npx.cmd', ['-v']); + cp.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + cp.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + console.log(`stderr(iconv): ${iconv.decode(data, 'gbk')}`); + // reject(); + }); + + cp.on('close', (code) => { + console.log(`子进程退出码:${code}`); + resolve(); + }); + }); +}); + +gulp.task("pushRPK_OPPO", ["buildRPK_OPPO"], function() { + if (!config.oppoInfo.adbDebug) { + return; + } + // 在OPPO轻游戏项目目录中执行: + // adb push dist/game.rpk sdcard/games + // adb push layarepublicPath/oppo/instant_app_settings.properties + // adb shell am start -n com.nearme.instant.platform/com.oppo.autotest.main.InstantAppActivity + return new Promise((resolve, reject) => { + let cmd = `${adbPath}`; + let sdGamesPath = config.oppoInfo.subpack ? "sdcard/subPkg" : "sdcard/games"; + let args = ["push", `dist/${config.oppoInfo.package}${config.oppoInfo.useReleaseSign ? ".signed" : ""}.rpk`, sdGamesPath]; + let opts = { + cwd: projDir, + shell: true + }; + let cp = childProcess.spawn(cmd, args, opts); + // let cp = childProcess.spawn('npx.cmd', ['-v']); + cp.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + cp.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + // reject(); + }); + + cp.on('close', (code) => { + console.log(`1) push_RPK 子进程退出码:${code}`); + resolve(); + }); + }).then(() => { + return new Promise((resolve, reject) => { + // 如果是分包,需要修改里面的内容 + let oppoPropPath = path.join(layarepublicPath, "oppo", "instant_app_settings.properties"); + if (config.oppoInfo.subpack) { + fs.writeFileSync(oppoPropPath, "default_tab_index=4", "utf8"); + } else { + fs.writeFileSync(oppoPropPath, "default_tab_index=2", "utf8"); + } + let cmd = `${adbPath}`; + let args = ["push", oppoPropPath, "sdcard/"]; + let opts = { + cwd: projDir, + shell: true + }; + let cp = childProcess.spawn(cmd, args, opts); + // let cp = childProcess.spawn('npx.cmd', ['-v']); + cp.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + cp.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + // reject(); + }); + + cp.on('close', (code) => { + console.log(`2) push_RPK 子进程退出码:${code}`); + resolve(); + }); + }); + }).then(() => { + return new Promise((resolve, reject) => { + let cmd = `${adbPath}`; + let args = ["shell", "am", "start", "-n", "com.nearme.instant.platform/com.oppo.autotest.main.InstantAppActivity"]; + let opts = { + cwd: projDir, + shell: true + }; + let cp = childProcess.spawn(cmd, args, opts); + // let cp = childProcess.spawn('npx.cmd', ['-v']); + cp.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + cp.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + // reject(); + }); + + cp.on('close', (code) => { + console.log(`3) push_RPK 子进程退出码:${code}`); + resolve(); + }); + }); + }); +}); + +gulp.task("buildOPPOProj", ["pushRPK_OPPO"], function() { + console.log("all tasks completed"); +}); \ No newline at end of file diff --git a/.laya/_publish_vivogame_1605111925181.js b/.laya/_publish_vivogame_1605111925181.js new file mode 100644 index 0000000..9977f37 --- /dev/null +++ b/.laya/_publish_vivogame_1605111925181.js @@ -0,0 +1,1002 @@ +// v1.8.1 +const ideModuleDir = global.ideModuleDir; +const workSpaceDir = global.workSpaceDir; + +//引用插件模块 +const gulp = require(ideModuleDir + "gulp"); +const fs = require("fs"); +const path = require("path"); +const childProcess = require("child_process"); +const del = require(ideModuleDir + "del"); +const iconv = require(ideModuleDir + "iconv-lite"); +const revCollector = require(ideModuleDir + 'gulp-rev-collector'); +const request = require(ideModuleDir + "request"); + +let 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", "laya.d3Plugin.js", "bytebuffer.js", "laya.device.js", "laya.physics.js", "laya.physics3D.js", "laya.tiledmap.js", "worker.js", "workerloader.js"]; + +let copyLibsTask = ["copyPlatformLibsJsFile"]; +let versiontask = ["version2"]; + +let + config, + releaseDir, + tempReleaseDir, // vivo临时拷贝目录 + projDir, // vivo快游戏工程目录 + isDealNoCompile = true, + physicsLibsPathList = [], + isExistEngineFolder = false; // bin目录下是否存在engine文件夹 +let projSrc; +let versionCon; // 版本管理version.json +let commandSuffix, + opensslPath, + layarepublicPath; + +// 创建vivo项目前,拷贝vivo引擎库、修改index.js +gulp.task("preCreate_VIVO", copyLibsTask, function() { + releaseDir = global.releaseDir; + config = global.config; + commandSuffix = global.commandSuffix; + opensslPath = global.opensslPath; + layarepublicPath = global.layarepublicPath; + tempReleaseDir = global.tempReleaseDir; + + if (config.useMinJsLibs) { + fullRemoteEngineList = fullRemoteEngineList.map((item, index) => { + return item.replace(".js", ".min.js"); + }) + } +}); + +gulp.task("copyPlatformFile_VIVO", ["preCreate_VIVO"], function() { + return; +}); + +// 检查是否全局安装了qgame +gulp.task("createGlobalQGame_VIVO", versiontask, function() { + releaseDir = path.dirname(releaseDir); + projDir = path.join(releaseDir, config.vivoInfo.projName); + projSrc = path.join(projDir, "src"); + // npm view @vivo-minigame/cli version + // npm install -g @vivo-minigame/cli + let remoteVersion, localVersion; + let isGetRemote, isGetLocal; + let isUpdateGlobalQGame = true; + return new Promise((resolve, reject) => { // 远程版本号 + childProcess.exec("npm view @vivo-minigame/cli version", function(error, stdout, stderr) { + if (!stdout) { // 获取 @vivo-minigame/cli 远程版本号失败 + console.log("Failed to get the remote version number"); + resolve(); + return; + } + remoteVersion = stdout; + isGetRemote = true; + if (isGetRemote && isGetLocal) { + isUpdateGlobalQGame = remoteVersion != localVersion; + console.log(`remoteVersion: ${remoteVersion}, localVersion: ${localVersion}`); + resolve(); + } + }); + childProcess.exec("mg -v", function(error, stdout, stderr) { + if (!stdout) { // 获取 @vivo-minigame/cli 本地版本号失败 + console.log("Failed to get the local version number"); + resolve(); + return; + } + localVersion = stdout; + isGetLocal = true; + if (isGetRemote && isGetLocal) { + isUpdateGlobalQGame = remoteVersion != localVersion; + console.log(`remoteVersion: ${remoteVersion}, localVersion: ${localVersion}`); + resolve(); + } + }); + setTimeout(() => { + // 如果获取到了本地版本号,但未获取到远程版本号,默认通过 + if (isGetLocal && !isGetRemote) { + isUpdateGlobalQGame = false; + console.log("Gets the version number timeout, does not get the remote version number, but the local version number exists, passes by default"); + resolve(); + return; + } + }, 10000); + }).then(() => { + return new Promise((resolve, reject) => { + if (!isUpdateGlobalQGame) { + resolve(); + return; + } + console.log("全局安装@vivo-minigame/cli"); + // npm install -g @vivo-minigame/cli + let cmd = `npm${commandSuffix}`; + let args = ["install", "@vivo-minigame/cli", "-g"]; + let opts = { + shell: true + }; + let cp = childProcess.spawn(cmd, args, opts); + + cp.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + cp.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + // reject(); + }); + + cp.on('close', (code) => { + console.log(`2 end) npm install -g @vivo-minigame/cli:${code}`); + resolve(); + }); + }); + }).catch((e) => { + console.log("catch e", e); + }); +}); + +gulp.task("createProj_VIVO", ["createGlobalQGame_VIVO"], function() { + // 如果有即存项目,不再新建 + let isProjExist = fs.existsSync(projDir + "/node_modules") && + fs.existsSync(projDir + "/sign"); + if (isProjExist) { + // 检测是否需要升级 + let packageCon = fs.readFileSync(`${projDir}/package.json`, "utf8"); + let minigamePath = path.join(projDir, "minigame.config.js"); + if (packageCon.includes("@vivo-minigame/cli-service") && fs.existsSync(minigamePath)) { + return; + } + } + // 如果有即存项目,但是是旧的项目,删掉后重新创建 + return new Promise((resolve, reject) => { + if (!fs.existsSync(projDir)) { + return resolve(); + } + let delList = [projDir]; + del(delList, { force: true }).then(paths => { + resolve(); + }); + }).then(function() { + // 在项目中创建vivo项目 + return new Promise((resolve, reject) => { + console.log("(proj)开始创建vivo快游戏项目"); + // mg init + let cmd = `mg${commandSuffix}`; + let args = ["init", config.vivoInfo.projName]; + let opts = { + cwd: releaseDir, + shell: true + }; + + let cp = childProcess.spawn(cmd, args, opts); + + cp.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + cp.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + // reject(); + }); + + cp.on('close', (code) => { + cp = null; + console.log(`子进程退出码:${code}`); + resolve(); + }); + }); + }); +}); + +// 检查是否安装了adapter +gulp.task("createAdapter_VIVO", ["createProj_VIVO"], function() { + // npm view @qgame/adapter version + // npm i -S @qgame/adapter@latest + let remoteVersion, localVersion; + let isGetRemote, isGetLocal; + let isUpdateAdapter = true; + return new Promise((resolve, reject) => { // 远程版本号 + childProcess.exec("npm view @qgame/adapter version", function(error, stdout, stderr) { + if (!stdout) { // 获取 @vivo-minigame/cli 远程版本号失败 + console.log("Failed to get the remote adapter version number"); + resolve(); + return; + } + remoteVersion = stdout.replace(/[\r\n]/g, "").trim(); + isGetRemote = true; + if (isGetRemote && isGetLocal) { + isUpdateAdapter = remoteVersion != localVersion; + console.log(`remoteVersion: ${remoteVersion}, localVersion: ${localVersion}`); + resolve(); + } + }); + childProcess.exec("npm ls @qgame/adapter version", { cwd: projDir }, function(error, stdout, stderr) { + if (!stdout) { // 获取 @vivo-minigame/cli 本地版本号失败 + console.log("Failed to get the local adapter version number"); + resolve(); + return; + } + let info = stdout.split("@qgame/adapter@"); //@qgame/adapter@1.0.3 + info = Array.isArray(info) && info[1] && info[1].replace(/[\r\n]/g, "").trim(); + localVersion = info; + isGetLocal = true; + if (isGetRemote && isGetLocal) { + isUpdateAdapter = remoteVersion != localVersion; + console.log(`remoteVersion: ${remoteVersion}, localVersion: ${localVersion}`); + resolve(); + } + }); + setTimeout(() => { + // 如果获取到了本地版本号,但未获取到远程版本号,默认通过 + if (!isGetLocal || !isGetRemote) { + console.log("Failed to get the local or remote version number"); + resolve(); + return; + } + }, 10000); + }).then(() => { + return new Promise((resolve, reject) => { + if (!isUpdateAdapter) { + resolve(); + return; + } + console.log("安装@qgame/adapter"); + // npm i -S @qgame/adapter@latest + let cmd = `npm${commandSuffix}`; + let args = ["install", "-S", "@qgame/adapter@latest"]; + let opts = { + shell: true, + cwd: projDir + }; + let cp = childProcess.spawn(cmd, args, opts); + + cp.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + cp.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + // reject(); + }); + + cp.on('close', (code) => { + console.log(`2 end) npm i -S @qgame/adapter@latest:${code}`); + resolve(); + }); + }); + }).catch((e) => { + console.log("catch e", e); + }); +}); + +// 拷贝文件到vivo快游戏 +gulp.task("copyFileToProj_VIVO", ["createAdapter_VIVO"], function() { + // 如果有js/main.js,将其删除 + let vivoMainPath = path.join(projDir, "src", "js", "main.js"); + if (fs.existsSync(vivoMainPath)) { + fs.unlinkSync(vivoMainPath); + } + // 将临时文件夹中的文件,拷贝到项目中去 + let originalDir = `${tempReleaseDir}/**/*.*`; + let stream = gulp.src(originalDir); + return stream.pipe(gulp.dest(path.join(projSrc))); +}); + +// 拷贝icon到vivo快游戏 +gulp.task("copyIconToProj_VIVO", ["copyFileToProj_VIVO"], function() { + let originalDir = config.vivoInfo.icon; + let stream = gulp.src(originalDir); + return stream.pipe(gulp.dest(projSrc)); +}); + +// 清除vivo快游戏临时目录 +gulp.task("clearTempDir_VIVO", ["copyIconToProj_VIVO"], function() { + // 删掉临时目录 + return del([tempReleaseDir], { force: true }); +}); + +// 生成release签名(私钥文件 private.pem 和证书文件 certificate.pem ) +gulp.task("generateSign_VIVO", ["clearTempDir_VIVO"], function() { + if (!config.vivoSign.generateSign) { + return; + } + // https://doc.quickapp.cn/tools/compiling-tools.html + return new Promise((resolve, reject) => { + let cmd = `${opensslPath}`; + let args = ["req", "-newkey", "rsa:2048", "-nodes", "-keyout", "private.pem", + "-x509", "-days", "3650", "-out", "certificate.pem"]; + let opts = { + cwd: projDir, + shell: true + }; + let cp = childProcess.spawn(cmd, args, opts); + cp.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + cp.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + data += ""; + if (data.includes("Country Name")) { + cp.stdin.write(`${config.vivoSign.countryName}\n`); + console.log(`Country Name: ${config.vivoSign.countryName}`); + } else if (data.includes("Province Name")) { + cp.stdin.write(`${config.vivoSign.provinceName}\n`); + console.log(`Province Name: ${config.vivoSign.provinceName}`); + } else if (data.includes("Locality Name")) { + cp.stdin.write(`${config.vivoSign.localityName}\n`); + console.log(`Locality Name: ${config.vivoSign.localityName}`); + } else if (data.includes("Organization Name")) { + cp.stdin.write(`${config.vivoSign.orgName}\n`); + console.log(`Organization Name: ${config.vivoSign.orgName}`); + } else if (data.includes("Organizational Unit Name")) { + cp.stdin.write(`${config.vivoSign.orgUnitName}\n`); + console.log(`Organizational Unit Name: ${config.vivoSign.orgUnitName}`); + } else if (data.includes("Common Name")) { + cp.stdin.write(`${config.vivoSign.commonName}\n`); + console.log(`Common Name: ${config.vivoSign.commonName}`); + } else if (data.includes("Email Address")) { + cp.stdin.write(`${config.vivoSign.emailAddr}\n`); + console.log(`Email Address: ${config.vivoSign.emailAddr}`); + // cp.stdin.end(); + } + // reject(); + }); + + cp.on('close', (code) => { + console.log(`子进程退出码:${code}`); + resolve(); + }); + }); +}); + +// 拷贝sign文件到指定位置 +gulp.task("copySignFile_VIVO", ["generateSign_VIVO"], function() { + if (config.vivoSign.generateSign) { // 新生成的签名 + // 移动签名文件到项目中(Laya & vivo快游戏项目中) + let + privatePem = path.join(projDir, "private.pem"), + certificatePem = path.join(projDir, "certificate.pem"); + let isSignExits = fs.existsSync(privatePem) && fs.existsSync(certificatePem); + if (!isSignExits) { + return; + } + let + xiaomiDest = `${projDir}/sign/release`, + layaDest = `${workSpaceDir}/sign/release`; + let stream = gulp.src([privatePem, certificatePem]); + return stream.pipe(gulp.dest(xiaomiDest)) + .pipe(gulp.dest(layaDest)); + } else if (config.vivoInfo.useReleaseSign && !config.vivoSign.generateSign) { // 使用release签名,并且没有重新生成 + // 从项目中将签名拷贝到vivo快游戏项目中 + let + privatePem = path.join(workSpaceDir, "sign", "release", "private.pem"), + certificatePem = path.join(workSpaceDir, "sign", "release", "certificate.pem"); + let isSignExits = fs.existsSync(privatePem) && fs.existsSync(certificatePem); + if (!isSignExits) { + return; + } + let + xiaomiDest = `${projDir}/sign/release`; + let stream = gulp.src([privatePem, certificatePem]); + return stream.pipe(gulp.dest(xiaomiDest)); + } +}); + +gulp.task("deleteSignFile_VIVO", ["copySignFile_VIVO"], function() { + if (config.vivoSign.generateSign) { // 新生成的签名 + let + privatePem = path.join(projDir, "private.pem"), + certificatePem = path.join(projDir, "certificate.pem"); + return del([privatePem, certificatePem], { force: true }); + } +}); + +gulp.task("modifyFile_VIVO", ["deleteSignFile_VIVO"], function() { + // 修改manifest.json文件 + let manifestPath = path.join(projSrc, "manifest.json"); + if (!fs.existsSync(manifestPath)) { + return; + } + let manifestContent = fs.readFileSync(manifestPath, "utf8"); + let manifestJson = JSON.parse(manifestContent); + manifestJson.package = config.vivoInfo.package; + manifestJson.name = config.vivoInfo.name; + manifestJson.orientation = config.vivoInfo.orientation; + manifestJson.config.logLevel = config.vivoInfo.logLevel || "off"; + manifestJson.deviceOrientation = config.vivoInfo.orientation; + manifestJson.versionName = config.vivoInfo.versionName; + manifestJson.versionCode = config.vivoInfo.versionCode; + manifestJson.minPlatformVersion = config.vivoInfo.minPlatformVersion; + manifestJson.icon = `/${path.basename(config.vivoInfo.icon)}`; + if (config.vivoInfo.subpack) { // 分包 + manifestJson.subpackages = config.vivoSubpack; + } else { + delete manifestJson.subpackages; + } + // 增加thirdEngine字段 + let EngineVersion = getEngineVersion(); + if (EngineVersion) { + manifestJson.thirdEngine = { + "laya": EngineVersion + }; + } + fs.writeFileSync(manifestPath, JSON.stringify(manifestJson, null, 4), "utf8"); + + if (config.version) { + let versionPath = projSrc + "/version.json"; + versionCon = fs.readFileSync(versionPath, "utf8"); + versionCon = JSON.parse(versionCon); + } + let indexJsStr = (versionCon && versionCon["index.js"]) ? versionCon["index.js"] : "index.js"; + // 修改game.js文件 + let gameJsPath = path.join(projSrc, "game.js"); + let content = fs.existsSync(gameJsPath) && fs.readFileSync(gameJsPath, "utf8"); + let reWriteMainJs = !fs.existsSync(gameJsPath) || !content.includes("vvmini"); + if (reWriteMainJs) { + 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'; +require("./libs/laya.vvmini.js");\nrequire("./index.js");`; + } else { + // 额外的,如果有引擎插件相关代码,需要删掉 + content = content.replace(/if\s\(window\.requirePlugin\)\s{\n[\w\"\.\-\/\(\);\s\n]*\n}\selse\s{\n[\w\"\.\-\/\(\);\s\n]*\n}\n/gm, ""); + } + fs.writeFileSync(gameJsPath, content, "utf8"); + + // vivo项目,修改index.js + let filePath = path.join(projSrc, indexJsStr); + if (!fs.existsSync(filePath)) { + return; + } + let fileContent = fs.readFileSync(filePath, "utf8"); + fileContent = fileContent.replace(/loadLib(\(['"])/gm, "require$1./"); + fs.writeFileSync(filePath, fileContent, "utf8"); +}) + +function getEngineVersion() { + let coreLibPath = path.join(workSpaceDir, "bin", "libs", "laya.core.js"); + let isHasCoreLib = fs.existsSync(coreLibPath); + let isOldAsProj = fs.existsSync(`${workSpaceDir}/asconfig.json`) && !isHasCoreLib; + let isNewTsProj = fs.existsSync(`${workSpaceDir}/src/tsconfig.json`) && !isHasCoreLib; + let EngineVersion; + if (isHasCoreLib) { + let con = fs.readFileSync(coreLibPath, "utf8"); + let matchList = con.match(/Laya\.version\s*=\s*['"]([0-9\.]+(beta)?.*)['"]/); + if (!Array.isArray(matchList)) { + return null; + } + EngineVersion = matchList[1]; + } else { // newts项目和旧版本as项目 + if (isOldAsProj) { + let coreLibFilePath = path.join(workSpaceDir, "libs", "laya", "src", "Laya.as"); + if (!fs.existsSync(coreLibFilePath)) { + return null; + } + let con = fs.readFileSync(coreLibFilePath, "utf8"); + let matchList = con.match(/version:String\s*=\s*['"]([0-9\.]+(beta)?.*)['"]/); + if (!Array.isArray(matchList)) { + return null; + } + EngineVersion = matchList[1]; + } else if (isNewTsProj) { + let coreLibFilePath = path.join(workSpaceDir, "libs", "Laya.ts"); + if (!fs.existsSync(coreLibFilePath)) { + return null; + } + let con = fs.readFileSync(coreLibFilePath, "utf8"); + let matchList = con.match(/static\s*version:\s*string\s*=\s*['"]([0-9\.]+(beta)?.*)['"]/); + if (!Array.isArray(matchList)) { + return null; + } + EngineVersion = matchList[1]; + } + } + return EngineVersion; +} + +gulp.task("modifyMinJs_VIVO", ["modifyFile_VIVO"], function() { + let fileJsPath = path.join(projSrc, "game.js"); + let content = fs.readFileSync(fileJsPath, "utf-8"); + if (!config.useMinJsLibs) { // 默认保留了平台文件,如果同时取消使用min类库,就会出现文件引用不正确的问题 + content = content.replace(/min\/laya(-[\w\d]+)?\.vvmini\.min\.js/gm, "laya.vvmini.js"); + } else { + content = content.replace(/(min\/)?laya(-[\w\d]+)?\.vvmini(\.min)?\.js/gm, "min/laya.vvmini.min.js"); + } + fs.writeFileSync(fileJsPath, content, 'utf-8'); +}); + +gulp.task("version_VIVO", ["modifyMinJs_VIVO"], function () { + // game.js默认不覆盖,如果同时开启版本管理,就会出现文件引用不正确的问题 + let fileJsPath = path.join(projSrc, "game.js"); + let content = fs.readFileSync(fileJsPath, "utf-8"); + content = content.replace(/laya(-[\w\d]+)?\.xmmini/gm, "laya.xmmini"); + content = content.replace(/index(-[\w\d]+)?\.js/gm, "index.js"); + fs.writeFileSync(fileJsPath, content, 'utf-8'); + + if (config.version) { + let versionPath = projSrc + "/version.json"; + let mainJSPath = projSrc + "/game.js"; + let srcList = [versionPath, mainJSPath]; + return gulp.src(srcList) + .pipe(revCollector()) + .pipe(gulp.dest(projSrc)); + } +}); + +// 处理engine文件夹,允许开发者自己在bin下定义engine文件夹,以获得针对性的优化 +gulp.task("dealEngineFolder1_VIVO", ["version_VIVO"], function() { + // 如果项目中有engine文件夹,我们默认该开发者是熟悉VIVO发布流程的,已经处理好所有的逻辑 + // 值得注意的: + // 1) 如果有engine文件夹而未处理2D物理库(box2d.js/physics.js),项目将无法运行 + // 2) 如果未处理3D物理库(physics3D.js),打包时间将会很长 + + let engineFolder = path.join(projDir, "src", "engine"); + isExistEngineFolder = fs.existsSync(engineFolder); + if (!isExistEngineFolder) { + return; + } + + // 不想写一堆task任务,500ms默认拷贝完成吧 + // 未来有了更好的解决方案再修改 + return new Promise(function(resolve, reject) { + // 将engine文件夹拷贝到projRoot下 + setTimeout(resolve, 500); + var stream = gulp.src([`${engineFolder}/**/*.*`], {base: `${projDir}/src`}); + return stream.pipe(gulp.dest(projDir)); + }).then(function() { + return new Promise(function(resolve, reject) { + // 删掉src下的engine和adapter + setTimeout(resolve, 500); + return del([engineFolder], { force: true }); + }); + }).catch(function(err) { + console.log(err); + }); +}); + +gulp.task("dealEngineFolder2_VIVO", ["dealEngineFolder1_VIVO"], function() { + if (!isExistEngineFolder) { + return; + } + + let engineFolder = path.join(projDir, "engine"); + let engineFileList = fs.readdirSync(engineFolder); + // 修改配置文件 + configVivoConfigFile(engineFileList); +}); + +// 如果项目中用到了 box2d.js|laya.physics.js/laya.physics3D.js ,需要特殊处理 +// 之前处理的是有项目中已经存在engine文件夹的情况,现在开始处理没有文件夹的情况 +gulp.task("dealNoCompile1_VIVO", ["dealEngineFolder2_VIVO"], function() { + if (!isDealNoCompile) { + return; + } + + // 将js/bundle.js | libs/*.* 全放到engine文件夹中 + let indexJsStr = (versionCon && versionCon["index.js"]) ? versionCon["index.js"] : "index.js"; + let bundleJsStr = (versionCon && versionCon["js/bundle.js"]) ? versionCon["js/bundle.js"] : "js/bundle.js"; + let layaJsStr = (versionCon && versionCon["laya.js"]) ? versionCon["laya.js"] : "laya.js"; + + // 修改index.js,去掉物理库前面的libs + let filePath = path.join(projSrc, indexJsStr); + let fileContent = fs.readFileSync(filePath, "utf8"); + let physicsNameList = []; + + if (fileContent.includes(bundleJsStr)) { + let adapterJsPath = path.join(projSrc, bundleJsStr); + physicsNameList.push(bundleJsStr); + physicsLibsPathList.push(adapterJsPath); + } + if (fileContent.includes(layaJsStr)) { + let layaJsPath = path.join(projSrc, layaJsStr); + physicsNameList.push(layaJsStr); + physicsLibsPathList.push(layaJsPath); + } + let libsList = fs.readdirSync(path.join(projSrc, "libs")); + let libsFileName, libsFilePath; + for (let i = 0, len = libsList.length; i < len; i++) { + libsFileName = libsList[i]; + libsFilePath = path.join(projSrc, "libs", libsFileName); + physicsNameList.push(`libs/${libsFileName}`); + physicsLibsPathList.push(libsFilePath); + } + let minPath = path.join(projSrc, "libs", "min"); + if (fs.existsSync(minPath)) { + let minLibsList = fs.readdirSync(minPath); + let minLibsFileName, minLibsFilePath; + for (let i = 0, len = minLibsList.length; i < len; i++) { + minLibsFileName = minLibsList[i]; + minLibsFilePath = path.join(minPath, minLibsFileName); + physicsNameList.push(`libs/min/${minLibsFileName}`); + physicsLibsPathList.push(minLibsFilePath); + } + } + + // 修改配置文件 + configVivoConfigFile(physicsNameList); + + // 将物理库拷贝到engine中 + var stream = gulp.src(physicsLibsPathList, {base: projSrc}); + return stream.pipe(gulp.dest(path.join(projDir, "engine"))); +}); + +function configVivoConfigFile(engineFileList, isAppend) { + let vvConfigPath = path.join(projDir, "minigame.config.js"); + let content = fs.readFileSync(vvConfigPath, "utf8"); + let externalsStr = ""; + let libName; + // let engineStr = ''; + let inLayaLibs = false, dirName, newLibPath; + for (let i = 0, len = engineFileList.length; i < len; i++) { + libName = engineFileList[i]; + if (i !== 0) { + externalsStr += ',\n'; + } + newLibPath = libName.replace("libs/min/", "").replace("libs/", ""); + inLayaLibs = config.uesEnginePlugin && fullRemoteEngineList.includes(newLibPath); + dirName = inLayaLibs ? "laya-library" : "engine"; + if (inLayaLibs) { + // engineStr += `{\n\t\tmodule_name:'${dirName}/${newLibPath}',\n\t\tmodule_path:'${dirName}/${newLibPath}',\n\t\tmodule_from:'${dirName}/${newLibPath}'\n\t},`; + externalsStr += `\t{\n\t\tmodule_name:'${dirName}/${newLibPath}',\n\t\tmodule_path:'${dirName}/${newLibPath}',\n\t\tmodule_from:'${dirName}/${newLibPath}'\n\t}`; + } else { + externalsStr += `\t{\n\t\tmodule_name:'./${libName}',\n\t\tmodule_path:'./${libName}',\n\t\tmodule_from:'${dirName}/${libName}'\n\t}`; + } + } + if (isAppend) { // 只有源码项目会走这个逻辑 + let oldExternalsReg = content.match(/const externals = (\[([^*].|\n|\r)*\])/); + if (!oldExternalsReg) { + throw new Error("源码项目适配vivo引擎插件,设置配置文件出错,请与服务提供商联系(code 3)!"); + } + externalsStr = oldExternalsReg[1].replace(/\]$/, `,${externalsStr}\n]`); + externalsStr = `const externals = ${externalsStr}`; + } else { + externalsStr = `const externals = [\n${externalsStr}\n]`; + } + content = content.replace(/const externals = \[([^*].|\n|\r)*\]/gm, externalsStr); + fs.writeFileSync(vvConfigPath, content, "utf8"); +} + +gulp.task("dealNoCompile2_VIVO", ["dealNoCompile1_VIVO"], function() { + if (!isDealNoCompile || physicsLibsPathList.length === 0) { + return; + } + return del(physicsLibsPathList, { force: true }); +}); + +// 处理引擎插件 +// 我们会将所有的libs下的文件放到engine里,但不能认定libs下全是我们的引擎,所以还是要加判断 +gulp.task("pluginEngin_VIVO", ["dealNoCompile2_VIVO"], function(cb) { + let manifestJsonPath = path.join(projSrc, "manifest.json"); + let manifestJsonContent = fs.readFileSync(manifestJsonPath, "utf8"); + let conJson = JSON.parse(manifestJsonContent); + let copyBinPath; + + if (!config.uesEnginePlugin) { // 没有使用引擎插件,还是像以前一样发布 + delete conJson.plugins; + manifestJsonContent = JSON.stringify(conJson, null, 4); + fs.writeFileSync(manifestJsonPath, manifestJsonContent, "utf8"); + return cb(); + } + // 引擎源码项目 + // 将所有的min拷贝进来 + if (config.useMinJsLibs) { + copyBinPath = path.join(workSpaceDir, "bin", "libs", "min"); + } else { // 如果不是min + copyBinPath = path.join(workSpaceDir, "bin", "libs"); + } + // 针对min引擎文件,很多配置文件也需要该,同时改 + if (config.version) { + let versionPath = projSrc + "/version.json"; + versionCon = fs.readFileSync(versionPath, "utf8"); + versionCon = JSON.parse(versionCon); + } + let indexJsStr = (versionCon && versionCon["index.js"]) ? versionCon["index.js"] : "index.js"; + + // 获取version等信息 + let coreLibPath = path.join(workSpaceDir, "bin", "libs", "laya.core.js"); + let isHasCoreLib = fs.existsSync(coreLibPath); + let isOldAsProj = fs.existsSync(`${workSpaceDir}/asconfig.json`) && !isHasCoreLib; + let isNewTsProj = fs.existsSync(`${workSpaceDir}/src/tsconfig.json`) && !isHasCoreLib; + let EngineVersion = getEngineVersion(); + if (isOldAsProj || isNewTsProj) { + // 下载对应版本js引擎,按照普通项目走 + console.log(`ts源码项目(${isNewTsProj})或as源码项目(${isOldAsProj}),开始处理引擎`); + let engineNum = EngineVersion.replace("beta", ""); + let suffix = EngineVersion.includes("beta") ? "_beta" : ""; + let engineURL = `http://ldc.layabox.com/download/LayaAirJS_${engineNum}${suffix}.zip`; + let engineDownPath = path.join(releaseDir, `LayaAirJS_${engineNum}${suffix}.zip`); + let engineExtractPath = path.join(releaseDir, `LayaAirJS_${engineNum}${suffix}`); + if (config.useMinJsLibs) { + copyBinPath = path.join(engineExtractPath, "js", "libs", "min"); + } else { // 如果不是min + copyBinPath = path.join(engineExtractPath, "js", "libs"); + } + // 情况1) 如果已经下载过引擎了,直接开始处理引擎插件 + if (fs.existsSync(copyBinPath)) { + console.log("情况1) 如果已经下载过引擎了,直接开始处理引擎插件"); + return dealPluginEngine().then(() => { + // return cb(); + }).catch((err) => { + console.error("ts源码项目及as源码项目,下载或处理vivo引擎插件项目失败(code 1)!"); + throw err; + }); + } + // 情况2) 下载并解压引擎,然后开始处理引擎插件 + console.log("情况2) 下载并解压引擎,然后开始处理引擎插件"); + return downFileToDir(engineURL, engineDownPath).then(() => { + console.log("下载引擎库成功,开始解压"); + return extractZipFile(engineDownPath, engineExtractPath); + }).then(() => { + console.log("解压成功,开始处理引擎插件"); + return dealPluginEngine(); + }).then(() => { + // return cb(); + }).catch((err) => { + console.error("ts源码项目及as源码项目,下载或处理vivo引擎插件项目失败(code 2)!"); + throw err; + }) + } + // 情况3) 非源码项目,开始处理引擎插件 + console.log("情况3) 非源码项目,开始处理引擎插件"); + return dealPluginEngine().then(() => { + // return cb(); + }).catch((err) => { + throw err; + }); + + function dealPluginEngine() { + // 使用引擎插件 + let localUseEngineList = []; + let copyEnginePathList; + return new Promise(function(resolve, reject) { + console.log(`修改game.js和game.json`); + // 1) 修改game.js和game.json + // 修改game.js + let gameJsPath = path.join(projSrc, "game.js"); + let gameJscontent = fs.readFileSync(gameJsPath, "utf8"); + gameJscontent = gameJscontent.replace(`require("./${indexJsStr}");`, `requirePlugin('layaPlugin');\nrequire("./${indexJsStr}");`); + fs.writeFileSync(gameJsPath, gameJscontent, "utf8"); + + // 修改manifest.json,使其支持引擎插件 + conJson.plugins = { + "laya-library": { + "version": EngineVersion, + "provider": "", + "path": "laya-library" + } + } + manifestJsonContent = JSON.stringify(conJson, null, 4); + fs.writeFileSync(manifestJsonPath, manifestJsonContent, "utf8"); + resolve(); + }).then(function() { + return new Promise(function(resolve, reject) { + console.log(`确定用到的插件引擎`); + // 2) 确定用到了那些插件引擎,并将插件引擎从index.js的引用中去掉 + let indexJsPath = path.join(projSrc, indexJsStr); + let indexJsCon = fs.readFileSync(indexJsPath, "utf8"); + let item, fullRequireItem; + for (let i = 0, len = fullRemoteEngineList.length; i < len; i++) { + item = fullRemoteEngineList[i]; + fullRequireItem = config.useMinJsLibs ? `require("./libs/min/${item}")` : `require("./libs/${item}")`; + if (indexJsCon.includes(fullRequireItem)) { + localUseEngineList.push(item); + indexJsCon = indexJsCon.replace(fullRequireItem + ";", "").replace(fullRequireItem + ",", "").replace(fullRequireItem, ""); + } + } + // 源码项目需要特殊处理 + if (isNewTsProj || isOldAsProj) { + indexJsCon = indexJsCon.replace(`require("./laya.js");`, "").replace(`require("./laya.js"),`, "").replace(`require("./laya.js")`, ""); + let item, libPath, vivoConfigList = []; + for (let i = 0, len = fullRemoteEngineList.length; i < len; i++) { + item = fullRemoteEngineList[i]; + libPath = path.join(copyBinPath, item); + if (fs.existsSync(libPath) && !["bytebuffer", "laya.physics3D", "worker", "workerloader"].includes(item.replace(".min.js", "").replace(".js", ""))) { + localUseEngineList.push(item); + config.useMinJsLibs ? vivoConfigList.push(`libs/min/${item}`) : vivoConfigList.push(`libs/${item}`); + } + } + // let bundleJsStr = (versionCon && versionCon["js/bundle.js"]) ? versionCon["js/bundle.js"] : "js/bundle.js"; + // vivoConfigList.push(bundleJsStr); + configVivoConfigFile(vivoConfigList, true); + } + fs.writeFileSync(indexJsPath, indexJsCon, "utf8"); + // 再次修改game.js,仅引用使用到的类库 + let pluginCon = "", normalCon = ""; + localUseEngineList.forEach(function(item) { + pluginCon += `\trequirePlugin("laya-library/${item}");\n`; + normalCon += `\trequire("laya-library/${item}");\n`; + }); + let finalyPluginCon = `if (window.requirePlugin) {\n${pluginCon}\n} else {\n${normalCon}\n}`; + let gameJsPath = path.join(projSrc, "game.js"); + let gameJsCon = fs.readFileSync(gameJsPath, "utf8"); + gameJsCon = gameJsCon.replace(`requirePlugin('layaPlugin');`, finalyPluginCon); + fs.writeFileSync(gameJsPath, gameJsCon, "utf8"); + resolve(); + }); + }).then(function() { + return new Promise(function(resolve, reject) { + console.log(`将本地的引擎插件移动到laya-libs中`); + // 3) 将本地的引擎插件移动到laya-libs中 + copyEnginePathList = [`${copyBinPath}/{${fullRemoteEngineList.join(",")}}`]; + gulp.src(copyEnginePathList).pipe(gulp.dest(`${projDir}/laya-library`)); + setTimeout(resolve, 500); + }); + }).then(function() { + return new Promise(function(resolve, reject) { + console.log(`将libs中的本地引擎插件删掉`); + // 4) 将libs中的本地引擎插件删掉 + let deleteList = [`${projDir}/engine/libs/{${localUseEngineList.join(",")}}`, `${projDir}/engine/libs/min/{${localUseEngineList.join(",")}}`]; + del(deleteList, { force: true }).then(resolve); + }); + }).then(function() { + return new Promise(async function(resolve, reject) { + console.log(`完善引擎插件目录`); + // 5) 引擎插件目录laya-libs中还需要新建几个文件,使该目录能够使用 + let + layalibsPath = path.join(projDir, "laya-library"), + engineIndex = path.join(layalibsPath, "index.js"), + engineplugin = path.join(layalibsPath, "plugin.json"); + // enginesignature = path.join(layalibsPath, "signature.json"); + // index.js + if (!fs.existsSync(layalibsPath)) { + throw new Error("引擎插件目录创建失败,请与服务提供商联系!"); + } + let layaLibraryList = fs.readdirSync(layalibsPath); + let indexCon = ""; + layaLibraryList.forEach(function(item) { + indexCon += `require("./${item}");\n`; + }); + fs.writeFileSync(engineIndex, indexCon, "utf8"); + // plugin.json + let pluginCon = {"main": "index.js"}; + fs.writeFileSync(engineplugin, JSON.stringify(pluginCon, null, 4), "utf8"); + // signature.json + // let signatureCon = { + // "provider": provider, + // "signature": [] + // }; + // localUseEngineList.unshift("index.js"); + // let fileName, md5Str; + // for (let i = 0, len = localUseEngineList.length; i < len; i++) { + // fileName = localUseEngineList[i]; + // let md5Str = await getFileMd5(path.join(projDir, "laya-library", fileName)); + // signatureCon.signature.push({ + // "path": fileName, + // "md5": md5Str + // }); + // } + // fs.writeFileSync(enginesignature, JSON.stringify(signatureCon, null, 4), "utf8"); + resolve(); + }); + }).catch(function(e) { + throw e; + }) + } +}); + +function downFileToDir(uri, dest){ + return new Promise((resolve, reject) => { + if (!uri || !dest) { + reject(new Error(`downFileToDir 参数不全: ${uri}/${dest}`)); + return; + } + + let + totalLen = 9999, + progress = 0, + layaresponse; + var stream = fs.createWriteStream(dest); + request(uri).on('error', function(err) { + console.log("tool down err:" + err); + reject(err); + }).on("data", function(data) { + progress += data.length; + let downPercent = (progress / totalLen * 100).toFixed(3); + // console.log(`down: ${downPercent}%`); + }).on("response", function(response) { + layaresponse = response; + totalLen = response.caseless.dict['content-length']; + }).pipe(stream).on('close', function() { + if (layaresponse.statusCode == 200) { + console.log("下载成功!"); + resolve(); + } else { + reject(new Error(`下载失败,连接关闭 -> ${uri}`)); + } + }); + }); +} + +function extractZipFile(zipPath, extractDir) { + return new Promise((resolve, reject) => { + if (!zipPath || !extractDir) { + reject(new Error(`extractZipFile 参数不全: ${zipPath}/${extractDir}`)); + return false; + } + + zipPath = `"${zipPath}"`; + let unzipexepath = path.join(ideModuleDir, "../", "out", "codeextension", "updateversion", "tools", "unzip.exe"); + unzipexepath = `"${unzipexepath}"`; + let cmd; + if (process.platform === 'darwin') { + cmd = "unzip -o " + zipPath + " -d " + "\"" + extractDir + "\""; + } else { + cmd = unzipexepath + " -o " + zipPath + " -d " + "\"" + extractDir + "\""; + } + childProcess.exec(cmd, (error, stdout, stderr) => { + if (error || stderr) { + reject(error || stderr); + return; + } + resolve(); + }); + }); +} + +// 打包rpk +gulp.task("buildRPK_VIVO", ["pluginEngin_VIVO"], function() { + // 在vivo轻游戏项目目录中执行: + // npm run build || npm run release + let cmdStr = "build"; + if (config.vivoInfo.useReleaseSign) { + cmdStr = "release"; + } + return new Promise((resolve, reject) => { + let cmd = `npm${commandSuffix}`; + let args = ["run", cmdStr]; + let opts = { + cwd: projDir, + shell: true + }; + let cp = childProcess.spawn(cmd, args, opts); + // let cp = childProcess.spawn(`npx${commandSuffix}`, ['-v']); + cp.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + cp.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + console.log(`stderr(iconv): ${iconv.decode(data, 'gbk')}`); + + // reject(); + }); + + cp.on('close', (code) => { + console.log(`子进程退出码:${code}`); + resolve(); + }); + }); +}); + +gulp.task("showQRCode_VIVO", ["buildRPK_VIVO"], function() { + // 在vivo轻游戏项目目录中执行: + // npm run server + return new Promise((resolve, reject) => { + let cmd = `npm${commandSuffix}`; + let args = ["run", "server"]; + let opts = { + cwd: projDir, + shell: true + }; + let cp = childProcess.spawn(cmd, args, opts); + // let cp = childProcess.spawn(`npx${commandSuffix}`, ['-v']); + cp.stdout.on('data', (data) => { + console.log(`${data}`); + // 输出pid,macos要用: macos无法kill进程树,也无法执行命令获取3000端口pid(没有查询权限),导致无法kill这个进程 + console.log('vv_qrcode_pid:' + cp.pid); + }); + + cp.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + console.log(`stderr(iconv): ${iconv.decode(data, 'gbk')}`); + // reject(); + }); + + cp.on('close', (code) => { + console.log(`子进程退出码:${code}`); + resolve(); + }); + }); +}); + + +gulp.task("buildVivoProj", ["showQRCode_VIVO"], function() { + console.log("all tasks completed"); +}); \ No newline at end of file diff --git a/.laya/_publish_xmgame_1605111925173.js b/.laya/_publish_xmgame_1605111925173.js new file mode 100644 index 0000000..8f8814a --- /dev/null +++ b/.laya/_publish_xmgame_1605111925173.js @@ -0,0 +1,342 @@ +// v1.8.0 +const ideModuleDir = global.ideModuleDir; +const workSpaceDir = global.workSpaceDir; + +//引用插件模块 +const gulp = require(ideModuleDir + "gulp"); +const fs = require("fs"); +const path = require("path"); +const childProcess = require("child_process"); +const del = require(ideModuleDir + "del"); +const revCollector = require(ideModuleDir + 'gulp-rev-collector'); + +let copyLibsTask = ["copyPlatformLibsJsFile"]; +let versiontask = ["version2"]; + +let + config, + releaseDir, + tempReleaseDir, // 小米临时拷贝目录 + projDir; // 小米快游戏工程目录 +let versionCon; // 版本管理version.json +let commandSuffix, + opensslPath, + layarepublicPath; + +// 创建小米项目前,拷贝小米引擎库、修改index.js +gulp.task("preCreate_XM", copyLibsTask, function() { + releaseDir = global.releaseDir; + config = global.config; + commandSuffix = global.commandSuffix; + opensslPath = global.opensslPath; + layarepublicPath = global.layarepublicPath; + tempReleaseDir = global.tempReleaseDir; +}); + +gulp.task("copyPlatformFile_XM", ["preCreate_XM"], function() { + let xmAdapterPath = path.join(layarepublicPath, "LayaAirProjectPack", "lib", "data", "xmfiles"); + let copyLibsList = [`${xmAdapterPath}/**/*.*`]; + var stream = gulp.src(copyLibsList); + return stream.pipe(gulp.dest(tempReleaseDir)); +}); + +gulp.task("createProj_XM", versiontask, function() { + releaseDir = path.dirname(releaseDir); + projDir = path.join(releaseDir, config.xmInfo.projName); + // 如果有即存项目,不再新建 + let isProjExist = fs.existsSync(projDir + "/node_modules") && + fs.existsSync(projDir + "/sign"); + if (isProjExist) { + return; + } + // 在项目中创建小米项目 + return new Promise((resolve, reject) => { + console.log("(proj)开始创建小米快游戏项目,请耐心等待(预计需要10分钟)..."); + let cmd = `npx${commandSuffix}`; + let args = ["create-quickgame", config.xmInfo.projName, `path=${releaseDir}`, + `package=${config.xmInfo.package}`, `versionName=${config.xmInfo.versionName}`, + `versionCode=${config.xmInfo.versionCode}`, `minPlatformVersion=${config.xmInfo.minPlatformVersion}`, + `icon=/layaicon/${path.basename(config.xmInfo.icon)}`, `name=${config.xmInfo.name}`, `rebuild=true`]; + let opts = { + shell: true + }; + let cp = childProcess.spawn(cmd, args, opts); + + cp.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + cp.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + // reject(); + }); + + cp.on('close', (code) => { + console.log(`子进程退出码:${code}`); + resolve(); + }); + }); +}); + +// 拷贝文件到小米快游戏 +gulp.task("copyFileToProj_XM", ["createProj_XM"], function() { + // 将临时文件夹中的文件,拷贝到项目中去 + let originalDir = `${tempReleaseDir}/**/*.*`; + let stream = gulp.src(originalDir); + return stream.pipe(gulp.dest(path.join(projDir))); +}); + +// 拷贝icon到小米快游戏 +gulp.task("copyIconToProj_XM", ["copyFileToProj_XM"], function() { + let originalDir = config.xmInfo.icon; + let stream = gulp.src(originalDir); + return stream.pipe(gulp.dest(path.join(projDir, "layaicon"))); +}); + +// 清除小米快游戏临时目录 +gulp.task("clearTempDir_XM", ["copyIconToProj_XM"], function() { + // 删掉临时目录 + return del([tempReleaseDir], { force: true }); +}); + +// 生成release签名(私钥文件 private.pem 和证书文件 certificate.pem ) +gulp.task("generateSign_XM", ["clearTempDir_XM"], function() { + if (!config.xmSign.generateSign) { + return; + } + // https://doc.quickapp.cn/tools/compiling-tools.html + return new Promise((resolve, reject) => { + let cmd = `${opensslPath}`; + let args = ["req", "-newkey", "rsa:2048", "-nodes", "-keyout", "private.pem", + "-x509", "-days", "3650", "-out", "certificate.pem"]; + let opts = { + cwd: projDir, + shell: true + }; + let cp = childProcess.spawn(cmd, args, opts); + cp.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + cp.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + data += ""; + if (data.includes("Country Name")) { + cp.stdin.write(`${config.xmSign.countryName}\n`); + console.log(`Country Name: ${config.xmSign.countryName}`); + } else if (data.includes("Province Name")) { + cp.stdin.write(`${config.xmSign.provinceName}\n`); + console.log(`Province Name: ${config.xmSign.provinceName}`); + } else if (data.includes("Locality Name")) { + cp.stdin.write(`${config.xmSign.localityName}\n`); + console.log(`Locality Name: ${config.xmSign.localityName}`); + } else if (data.includes("Organization Name")) { + cp.stdin.write(`${config.xmSign.orgName}\n`); + console.log(`Organization Name: ${config.xmSign.orgName}`); + } else if (data.includes("Organizational Unit Name")) { + cp.stdin.write(`${config.xmSign.orgUnitName}\n`); + console.log(`Organizational Unit Name: ${config.xmSign.orgUnitName}`); + } else if (data.includes("Common Name")) { + cp.stdin.write(`${config.xmSign.commonName}\n`); + console.log(`Common Name: ${config.xmSign.commonName}`); + } else if (data.includes("Email Address")) { + cp.stdin.write(`${config.xmSign.emailAddr}\n`); + console.log(`Email Address: ${config.xmSign.emailAddr}`); + // cp.stdin.end(); + } + // reject(); + }); + + cp.on('close', (code) => { + console.log(`子进程退出码:${code}`); + resolve(); + }); + }); +}); + +// 拷贝sign文件到指定位置 +gulp.task("copySignFile_XM", ["generateSign_XM"], function() { + if (config.xmSign.generateSign) { // 新生成的签名 + // 移动签名文件到项目中(Laya & 小米快游戏项目中) + let + privatePem = path.join(projDir, "private.pem"), + certificatePem = path.join(projDir, "certificate.pem"); + let isSignExits = fs.existsSync(privatePem) && fs.existsSync(certificatePem); + if (!isSignExits) { + return; + } + let + xiaomiDest = `${projDir}/sign/release`, + layaDest = `${workSpaceDir}/sign/release`; + let stream = gulp.src([privatePem, certificatePem]); + return stream.pipe(gulp.dest(xiaomiDest)) + .pipe(gulp.dest(layaDest)); + } else if (config.xmInfo.useReleaseSign && !config.xmSign.generateSign) { // 使用release签名,并且没有重新生成 + // 从项目中将签名拷贝到小米快游戏项目中 + let + privatePem = path.join(workSpaceDir, "sign", "release", "private.pem"), + certificatePem = path.join(workSpaceDir, "sign", "release", "certificate.pem"); + let isSignExits = fs.existsSync(privatePem) && fs.existsSync(certificatePem); + if (!isSignExits) { + return; + } + let + xiaomiDest = `${projDir}/sign/release`; + let stream = gulp.src([privatePem, certificatePem]); + return stream.pipe(gulp.dest(xiaomiDest)); + } +}); + +gulp.task("deleteSignFile_XM", ["copySignFile_XM"], function() { + if (config.xmSign.generateSign) { // 新生成的签名 + let + privatePem = path.join(projDir, "private.pem"), + certificatePem = path.join(projDir, "certificate.pem"); + return del([privatePem, certificatePem], { force: true }); + } +}); + +gulp.task("modifyFile_XM", ["deleteSignFile_XM"], function() { + // 修改manifest.json文件 + let manifestPath = path.join(projDir, "manifest.json"); + if (!fs.existsSync(manifestPath)) { + return; + } + let manifestContent = fs.readFileSync(manifestPath, "utf8"); + let manifestJson = JSON.parse(manifestContent); + manifestJson.package = config.xmInfo.package; + manifestJson.name = config.xmInfo.name; + manifestJson.orientation = config.xmInfo.orientation; + manifestJson.config.logLevel = config.xmInfo.logLevel || "off"; + manifestJson.versionName = config.xmInfo.versionName; + manifestJson.versionCode = config.xmInfo.versionCode; + manifestJson.minPlatformVersion = config.xmInfo.minPlatformVersion; + manifestJson.icon = `/layaicon/${path.basename(config.xmInfo.icon)}`; + if (config.xmInfo.subpack) { // 分包 + manifestJson.subpackages = config.xmSubpack; + } else { + delete manifestJson.subpackages; + } + fs.writeFileSync(manifestPath, JSON.stringify(manifestJson, null, 4), "utf8"); + + if (config.version) { + let versionPath = projDir + "/version.json"; + versionCon = fs.readFileSync(versionPath, "utf8"); + versionCon = JSON.parse(versionCon); + } + let indexJsStr = (versionCon && versionCon["index.js"]) ? versionCon["index.js"] : "index.js"; + // 修改main.js文件 + let mainJsPath = path.join(projDir, "main.js"); + let mainJsCon = fs.existsSync(mainJsPath) && fs.readFileSync(mainJsPath, "utf8"); + let reWriteMainJs = !fs.existsSync(mainJsPath) || !mainJsCon.includes("xmmini"); + if (reWriteMainJs) { + mainJsCon = 'require("./qg-adapter.js");\nrequire("./libs/laya.xmmini.js");\nrequire("./index.js");'; + fs.writeFileSync(mainJsPath, mainJsCon, "utf8"); + } + + // 小米项目,修改index.js + let filePath = path.join(projDir, indexJsStr); + if (!fs.existsSync(filePath)) { + return; + } + let fileContent = fs.readFileSync(filePath, "utf8"); + fileContent = fileContent.replace(/loadLib(\(['"])/gm, "require$1./"); + fs.writeFileSync(filePath, fileContent, "utf8"); +}) + +gulp.task("modifyMinJs_XM", ["modifyFile_XM"], function() { + let fileJsPath = path.join(projDir, "main.js"); + let content = fs.readFileSync(fileJsPath, "utf-8"); + if (!config.useMinJsLibs) { // 默认保留了平台文件,如果同时取消使用min类库,就会出现文件引用不正确的问题 + content = content.replace(/min\/laya(-[\w\d]+)?\.xmmini\.min\.js/gm, "laya.xmmini.js"); + } else { + content = content.replace(/(min\/)?laya(-[\w\d]+)?\.xmmini(\.min)?\.js/gm, "min/laya.xmmini.min.js"); + } + fs.writeFileSync(fileJsPath, content, 'utf-8'); +}); + +gulp.task("version_XM", ["modifyMinJs_XM"], function () { + // main.js默认不覆盖,如果同时开启版本管理,就会出现文件引用不正确的问题 + let fileJsPath = path.join(projDir, "main.js"); + let content = fs.readFileSync(fileJsPath, "utf-8"); + content = content.replace(/laya(-[\w\d]+)?\.xmmini/gm, "laya.xmmini"); + content = content.replace(/index(-[\w\d]+)?\.js/gm, "index.js"); + fs.writeFileSync(fileJsPath, content, 'utf-8'); + + if (config.version) { + let versionPath = projDir + "/version.json"; + let mainJSPath = projDir + "/main.js"; + let srcList = [versionPath, mainJSPath]; + return gulp.src(srcList) + .pipe(revCollector()) + .pipe(gulp.dest(projDir)); + } +}); + +// 打包rpk +gulp.task("buildRPK_XM", ["version_XM"], function() { + // 在小米轻游戏项目目录中执行: + // npm run build || npm run release + let cmdStr = "build"; + if (config.xmInfo.useReleaseSign) { + cmdStr = "release"; + } + return new Promise((resolve, reject) => { + let cmd = `npm${commandSuffix}`; + let args = ["run", cmdStr]; + let opts = { + cwd: projDir, + shell: true + }; + let cp = childProcess.spawn(cmd, args, opts); + // let cp = childProcess.spawn(`npx${commandSuffix}`, ['-v']); + cp.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + cp.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + // reject(); + }); + + cp.on('close', (code) => { + console.log(`子进程退出码:${code}`); + resolve(); + }); + }); +}); + +gulp.task("showQRCode_XM", ["buildRPK_XM"], function() { + // 在小米轻游戏项目目录中执行: + // npm run server + return new Promise((resolve, reject) => { + let cmd = `npm${commandSuffix}`; + let args = ["run", "server"]; + let opts = { + cwd: projDir, + shell: true + }; + let cp = childProcess.spawn(cmd, args, opts); + // let cp = childProcess.spawn(`npx${commandSuffix}`, ['-v']); + cp.stdout.on('data', (data) => { + console.log(`${data}`); + // 输出pid,macos要用: macos无法kill进程树,也无法执行命令获取3000端口pid(没有查询权限),导致无法kill这个进程 + console.log('xm_qrcode_pid:' + cp.pid); + }); + + cp.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + // reject(); + }); + + cp.on('close', (code) => { + console.log(`子进程退出码:${code}`); + resolve(); + }); + }); +}); + + +gulp.task("buildXiaomiProj", ["showQRCode_XM"], function() { + console.log("all tasks completed"); +}); \ No newline at end of file diff --git a/.laya/compile.js b/.laya/compile.js index 7e8eea7..e3cb04d 100644 --- a/.laya/compile.js +++ b/.laya/compile.js @@ -1,4 +1,4 @@ -// v1.2.4 +// v1.2.5 //是否使用IDE自带的node环境和插件,设置false后,则使用自己环境(使用命令行方式执行) const useIDENode = process.argv[0].indexOf("LayaAir") > -1 ? true : false; const useCMDNode = process.argv[1].indexOf("layaair2-cmd") > -1 ? true : false; @@ -14,6 +14,8 @@ const gulp = require(ideModuleDir + "gulp"); const rollup = require(ideModuleDir + "rollup"); const typescript = require(ideModuleDir + 'rollup-plugin-typescript2');//typescript2 plugin const glsl = require(ideModuleDir + 'rollup-plugin-glsl'); +const path = require('path'); +const fs = require('fs'); // 如果是发布时调用编译功能,增加prevTasks let prevTasks = ""; @@ -23,12 +25,13 @@ if (global.publish) { gulp.task("compile", prevTasks, function () { // 发布时调用编译功能,判断是否点击了编译选项 - if (global.publish && !global.config.compile) { - return; - } else if (global.publish && global.config.compile) { - // 发布时调用编译,workSpaceDir使用publish.js里的变量 - workSpaceDir = global.workSpaceDir; - } + if (global.publish) { + workSpaceDir = global.workSpaceDir; // 发布时调用编译,workSpaceDir使用publish.js里的变量 + let forceCompile = !fs.existsSync(path.join(workSpaceDir, "bin", "js", "bundle.js")); // 发布时,并且没有编译过,则强制编译 + if (!global.config.compile && !forceCompile) { + return; + } + } return rollup.rollup({ input: workSpaceDir + '/src/Main.ts', diff --git a/.laya/publish.js b/.laya/publish.js index 6ca104e..a45fa56 100644 --- a/.laya/publish.js +++ b/.laya/publish.js @@ -1,4 +1,4 @@ -// v1.8.0 +// v1.8.2 //是否使用IDE自带的node环境和插件,设置false后,则使用自己环境(使用命令行方式执行) const useIDENode = process.argv[0].indexOf("LayaAir") > -1 ? true : false; const useCMDNode = process.argv[1].indexOf("layaair2-cmd") > -1 ? true : false; @@ -28,7 +28,7 @@ const babel = require(ideModuleDir + 'gulp-babel'); // 结合compile.js使用 global.publish = true; -const fileList = ["compile.js", "publish_xmgame.js", "publish_oppogame.js", "publish_vivogame.js", "publish_biligame.js", "publish_alipaygame.js", "publish_wxgame.js", "publish_bdgame.js", "publish_qqgame.js", "publish_bytedancegame.js", "publish_hwgame.js"]; +const fileList = ["compile.js", "publish_xmgame.js", "publish_oppogame.js", "publish_vivogame.js", "publish_biligame.js", "publish_alipaygame.js", "publish_wxgame.js", "publish_bdgame.js", "publish_qqgame.js", "publish_bytedancegame.js", "publish_hwgame.js", "publish_taobaominiapp.js"]; requireDir('./', { filter: function (fullPath) { // 只用到了compile.js和publish.js @@ -55,6 +55,7 @@ let config, opensslPath = "openssl"; //任务对照列表 const copyTasks = { + "taobaominiapp": "copyPlatformFile_TBMini", "hwgame": "copyPlatformFile_HW", "bytedancegame": "copyPlatformFile_ByteDance", "biligame": "copyPlatformFile_Bili", @@ -68,6 +69,7 @@ const copyTasks = { "web": "copyPlatformLibsJsFile" } const tasks = { + "taobaominiapp": "buildTBMiniProj", "hwgame": "buildHWProj", "bytedancegame": "buildByteDanceProj", "biligame": "buildBiliProj", @@ -157,6 +159,11 @@ gulp.task("loadConfig", function (cb) { opensslPath = path.join(otherLibsPath, "openssl", "darwin", "bin", "openssl"); } else { opensslPath = path.join(otherLibsPath, "openssl", "win", "bin", "openssl.exe"); + let opensslCnfPath = path.join(otherLibsPath, "openssl", "win", "bin", "openssl.cfg"); + // 特别的,当windows没有openssl时,需要额外的OPENSSL_CONF设置变量 + // childProcess.execSync(`set OPENSSL_CONF=${opensslCnfPath}`); + process.env.OPENSSL_CONF = opensslCnfPath; + console.log("OPENSSL_CONF: " + childProcess.execSync("echo %OPENSSL_CONF%")); } opensslPath = `"${opensslPath}"`; } @@ -204,7 +211,9 @@ gulp.task("clearReleaseDir", ["compile"], function (cb) { } del(delList, { force: true }).then(paths => { cb(); - }); + }).catch((err) => { + throw err; + }) } else cb(); }); @@ -221,19 +230,18 @@ gulp.task("copyFile", ["clearReleaseDir"], function () { config.copyFilesFilter.push(`${workSpaceDir}/bin/libs/laya.opendata.js`); } } else if (platform === "wxgame") { // 微信项目,不拷贝index.html,不拷贝百度bin目录中的文件 - config.copyFilesFilter = baseCopyFilter.concat([`!${workSpaceDir}/bin/index.html`, `!${workSpaceDir}/bin/{project.swan.json,swan-game-adapter.js}`]); + config.copyFilesFilter = baseCopyFilter.concat([`!${workSpaceDir}/bin/{project.swan.json,swan-game-adapter.js}`]); } else if (platform === "bdgame") { // 百度项目,不拷贝index.html,不拷贝微信bin目录中的文件 - config.copyFilesFilter = baseCopyFilter.concat([`!${workSpaceDir}/bin/index.html`, `!${workSpaceDir}/bin/{project.config.json,weapp-adapter.js}`]); - } else { // web|QQ项目|bili|快游戏,不拷贝微信、百度在bin目录中的文件 + config.copyFilesFilter = baseCopyFilter.concat([`!${workSpaceDir}/bin/{project.config.json,weapp-adapter.js}`]); + } else { // 除微信、百度外,不拷贝微信、百度在bin目录中的文件 config.copyFilesFilter = baseCopyFilter.concat([`!${workSpaceDir}/bin/{game.js,game.json,project.config.json,weapp-adapter.js,project.swan.json,swan-game-adapter.js}`]); } // bili/alipay/qq,不拷贝index.html - if (["biligame", "Alipaygame", "qqgame", "bytedancegame"].includes(platform)) { + if (platform !== "web") { config.copyFilesFilter = config.copyFilesFilter.concat([`!${workSpaceDir}/bin/index.html`]); } // 快游戏,需要新建一个快游戏项目,拷贝的只是项目的一部分,将文件先拷贝到文件夹的临时目录中去 - if (QUICKGAMELIST.includes(platform)) { - config.copyFilesFilter = config.copyFilesFilter.concat([`!${workSpaceDir}/bin/index.html`]); + if ([...QUICKGAMELIST].includes(platform)) { releaseDir = global.tempReleaseDir = path.join(releaseDir, "temprelease"); } if (config.exclude) { // 排除文件 @@ -371,6 +379,9 @@ gulp.task("copyPlatformLibsJsFile", ["copyLibsJsFile"], function () { case "hwgame": platformLibName = "laya.hwmini.js"; break; + case "taobaominiapp": + platformLibName = "laya.tbmini.js"; + break; } let copyPath = `${workSpaceDir}/bin/libs`; if (config.useMinJsLibs) { diff --git a/.laya/publish_hwgame.js b/.laya/publish_hwgame.js index d3e8cab..8f88bda 100644 --- a/.laya/publish_hwgame.js +++ b/.laya/publish_hwgame.js @@ -1,4 +1,4 @@ -// v1.0.3 +// v1.0.5 const ideModuleDir = global.ideModuleDir; const workSpaceDir = global.workSpaceDir; @@ -155,6 +155,14 @@ gulp.task("generateSign_HW", ["clearTempDir_HW"], function() { cp.on('close', (code) => { console.log(`子进程退出码:${code}`); + // 签名是否生成成功 + let + privatePem = path.join(projDir, "private.pem"), + certificatePem = path.join(projDir, "certificate.pem"); + let isSignExits = fs.existsSync(privatePem) && fs.existsSync(certificatePem); + if (!isSignExits) { + throw new Error("签名生成失败,请检查!"); + } resolve(); }); }); @@ -350,6 +358,11 @@ gulp.task("buildRPK_HW", ["version_HW"], function() { cp.on('close', (code) => { console.log(`子进程退出码:${code}`); + // rpk是否生成成功 + let distRpkPath = path.join(distPath, `${name}.rpk`); + if (!fs.existsSync(distRpkPath)) { + throw new Error("rpk生成失败,请检查!"); + } resolve(); }); }); @@ -410,7 +423,7 @@ gulp.task("updateAPK_HW", ["getDevices_HW"], function(cb) { }); }).then(() => { return new Promise((resolve, reject) => { - if (remoteAPKVer === localAPKVer) { + if (remoteAPKVer === localAPKVer || donotUpdate(remoteAPKVer, localAPKVer)) { console.log("您的快应用加载器是最新版本!"); return resolve(); } @@ -535,7 +548,7 @@ gulp.task("pushRPK_HW", ["updateAPK_HW"], function() { console.log(`2) push_RPK: `); let rpkFilePath = path.join(projDir, "dist", `${config.hwInfo.package}.rpk`); let cmd = `${adbPath}`; - let args = ["push", rpkFilePath, "/data/local/tmp/"]; + let args = ["push", `"${rpkFilePath}"`, "/data/local/tmp/"]; let opts = { cwd: projDir, shell: true @@ -585,6 +598,33 @@ gulp.task("pushRPK_HW", ["updateAPK_HW"], function() { }); }); +function donotUpdate(remoteAPKVer, localAPKVer) { + let remoteAPKVerN = remoteAPKVer.match(/^(\d+)\.(\d+)\.(\d+)\.(\d+)/); + let localAPKVerN = localAPKVer.match(/^(\d+)\.(\d+)\.(\d+)\.(\d+)/); + let + l1n = Number(localAPKVerN[1]), // local first number + l2n = Number(localAPKVerN[2]), + l3n = Number(localAPKVerN[3]), + l4n = Number(localAPKVerN[4]), + r1n = Number(remoteAPKVerN[1]), // remote first number + r2n = Number(remoteAPKVerN[2]), + r3n = Number(remoteAPKVerN[3]); + r4n = Number(remoteAPKVerN[4]); + if (l1n > r1n) { + return true; + } + if (l1n === r1n && l2n > r2n) { + return true; + } + if (l1n === r1n && l2n === r2n && l3n > r3n) { + return true; + } + if (l1n === r1n && l2n === r2n && l3n === r3n && l4n >= r4n) { + return true; + } + return false; +} + gulp.task("buildHWProj", ["pushRPK_HW"], function() { console.log("all tasks completed"); }); \ No newline at end of file diff --git a/.laya/publish_oppogame.js b/.laya/publish_oppogame.js index 6dbaadf..7438ef8 100644 --- a/.laya/publish_oppogame.js +++ b/.laya/publish_oppogame.js @@ -1,4 +1,4 @@ -// v1.8.1 +// v1.8.2 const ideModuleDir = global.ideModuleDir; const workSpaceDir = global.workSpaceDir; @@ -149,6 +149,14 @@ gulp.task("generateSign_OPPO", ["clearTempDir_OPPO"], function() { cp.on('close', (code) => { console.log(`子进程退出码:${code}`); + // 签名是否生成成功 + let + privatePem = path.join(projDir, "private.pem"), + certificatePem = path.join(projDir, "certificate.pem"); + let isSignExits = fs.existsSync(privatePem) && fs.existsSync(certificatePem); + if (!isSignExits) { + throw new Error("签名生成失败,请检查!"); + } resolve(); }); }); @@ -314,6 +322,11 @@ gulp.task("buildRPK_OPPO", ["version_OPPO"], function() { cp.on('close', (code) => { console.log(`子进程退出码:${code}`); + // rpk是否生成成功 + let distRpkPath = path.join(projDir, "dist", `${config.oppoInfo.package}${config.oppoInfo.useReleaseSign ? ".signed" : ""}.rpk`); + if (!fs.existsSync(distRpkPath)) { + throw new Error("rpk生成失败,请检查!"); + } resolve(); }); }); diff --git a/.laya/publish_vivogame.js b/.laya/publish_vivogame.js index 9977f37..ae70a90 100644 --- a/.laya/publish_vivogame.js +++ b/.laya/publish_vivogame.js @@ -1,4 +1,4 @@ -// v1.8.1 +// v1.8.2 const ideModuleDir = global.ideModuleDir; const workSpaceDir = global.workSpaceDir; @@ -343,6 +343,14 @@ gulp.task("generateSign_VIVO", ["clearTempDir_VIVO"], function() { cp.on('close', (code) => { console.log(`子进程退出码:${code}`); + // 签名是否生成成功 + let + privatePem = path.join(projDir, "private.pem"), + certificatePem = path.join(projDir, "certificate.pem"); + let isSignExits = fs.existsSync(privatePem) && fs.existsSync(certificatePem); + if (!isSignExits) { + throw new Error("签名生成失败,请检查!"); + } resolve(); }); }); @@ -960,6 +968,11 @@ gulp.task("buildRPK_VIVO", ["pluginEngin_VIVO"], function() { cp.on('close', (code) => { console.log(`子进程退出码:${code}`); + // rpk是否生成成功 + let distRpkPath = path.join(projDir, "dist", `${config.vivoInfo.package}${config.vivoInfo.useReleaseSign ? ".signed" : ""}.rpk`); + if (!fs.existsSync(distRpkPath)) { + throw new Error("rpk生成失败,请检查!"); + } resolve(); }); }); diff --git a/.laya/publish_xmgame.js b/.laya/publish_xmgame.js index 8f8814a..bb01130 100644 --- a/.laya/publish_xmgame.js +++ b/.laya/publish_xmgame.js @@ -1,4 +1,4 @@ -// v1.8.0 +// v1.8.1 const ideModuleDir = global.ideModuleDir; const workSpaceDir = global.workSpaceDir; @@ -149,6 +149,14 @@ gulp.task("generateSign_XM", ["clearTempDir_XM"], function() { cp.on('close', (code) => { console.log(`子进程退出码:${code}`); + // 签名是否生成成功 + let + privatePem = path.join(projDir, "private.pem"), + certificatePem = path.join(projDir, "certificate.pem"); + let isSignExits = fs.existsSync(privatePem) && fs.existsSync(certificatePem); + if (!isSignExits) { + throw new Error("签名生成失败,请检查!"); + } resolve(); }); }); @@ -301,6 +309,11 @@ gulp.task("buildRPK_XM", ["version_XM"], function() { cp.on('close', (code) => { console.log(`子进程退出码:${code}`); + // rpk是否生成成功 + let distRpkPath = path.join(projDir, "dist", `${config.xmInfo.package}${config.xmInfo.useReleaseSign ? ".release" : ".debug"}.rpk`); + if (!fs.existsSync(distRpkPath)) { + throw new Error("rpk生成失败,请检查!"); + } resolve(); }); }); diff --git a/bin/js/bundle.js b/bin/js/bundle.js index 19d991c..e95cddf 100644 --- a/bin/js/bundle.js +++ b/bin/js/bundle.js @@ -776,8 +776,6 @@ } this.clearBloodyUI(); } - clearAllDebuff() { - } getBloodyPoint() { return CharacterInit.playerEnt.m_bloodyPoint; } @@ -799,6 +797,7 @@ } if (!CharacterInit.playerEnt.m_animation.destroyed && this.oathBar != null) this.oathBar.value = CharacterInit.playerEnt.m_bloodyPoint / CharacterInit.playerEnt.m_maxBloodyPoint_hard; + console.log(CharacterInit.playerEnt.m_bloodyPoint); }), 5); Laya.stage.addChild(this.oathBar); } @@ -960,6 +959,14 @@ this.overChargeCount = 0; this.oathBar.skin = "UI/bp_150.png"; this.oathBar.sizeGrid = "0,200,0,20"; + this.addDebuffTimer = setInterval(() => { + if (CharacterInit.playerEnt.m_animation.destroyed) { + clearInterval(this.addDebuffTimer); + return; + } + console.log("執行addDebuffTimer內函式"); + this.randomAddDebuff(); + }, 5000); this.oathState = OathStatus.overCharge; return; } @@ -1143,6 +1150,7 @@ cast(owner, position) { if (!this.m_canUse) return; + this.m_canUse = false; let rightSide = owner.m_isFacingRight; this.m_animation = new Laya.Animation(); this.m_animation.width = 400; @@ -1155,7 +1163,6 @@ this.m_animation.source = "comp/Spike.atlas"; this.m_animation.autoPlay = true; this.m_animation.interval = 20; - this.m_canUse = false; this.castRoar(position); let colorMat = [ 2, 0, 0, 0, -100, @@ -1170,7 +1177,7 @@ owner.delayMove(this.m_lastTime); owner.m_rigidbody.linearVelocity = { x: rightSide ? this.m_spikeVec : -this.m_spikeVec }; owner.updateAnimation(owner.m_state, CharacterStatus.attackOne, null, false, 150); - owner.hurtedEvent(0.5); + owner.hurtedEvent(1.5); this.attackRangeCheck(owner, { "x0": offsetX, "x1": offsetX + this.m_animation.width, @@ -1184,6 +1191,7 @@ }, 200); setTimeout(() => { this.m_canUse = true; + console.log("技能可使用"); }, this.m_cd * 1000); } attackRangeCheck(owner, pos) { @@ -1215,6 +1223,7 @@ cast(owner, position) { if (!this.m_canUse) return; + this.m_canUse = false; let rightSide = owner.m_isFacingRight; this.m_animation = new Laya.Animation(); this.m_animation.width = owner.m_animation.width; @@ -1229,7 +1238,6 @@ this.m_animation.interval = 30; this.m_animation.alpha = 0.8; this.m_animation.zOrder = 5; - this.m_canUse = false; this.castRoar(position); owner.delayMove(this.m_preTime); owner.m_rigidbody.linearVelocity = { x: 0.0, y: 0.0 }; @@ -1327,6 +1335,7 @@ cast(owner, position) { if (!this.m_canUse) return; + this.m_canUse = false; let rightSide = owner.m_isFacingRight; this.m_animation = new Laya.Animation(); this.m_animation.width = 350; @@ -1374,7 +1383,6 @@ let offsetY = position['y'] - this.m_animation.height - 70; let offsetInterval = 40; let rangeY = 0; - this.m_canUse = false; this.castRoar(position); this.m_injuredEnemy = []; setTimeout(() => { @@ -1411,6 +1419,7 @@ cast(owner, position) { if (!this.m_canUse) return; + this.m_canUse = false; let rightSide = owner.m_isFacingRight; let explosion = new Laya.Animation(); this.m_animation = new Laya.Animation(); @@ -1429,7 +1438,6 @@ explosion.pos(this.m_animation.x, this.m_animation.y); let offsetX = rightSide ? position['x'] + 140 : position['x'] - this.m_animation.width - 65; let offsetY = position['y'] - this.m_animation.height / 2; - this.m_canUse = false; this.castRoar(position); let colorMat = [ 4, 0, 2, 0, -150, @@ -1819,12 +1827,10 @@ this.m_canAttack = true; }, this.m_attackCdTime); } - if (this.m_keyDownList[16]) { - console.log(("按下shift")); - } if (this.m_keyDownList[88]) { if (!this.m_oathManager.oathCastSkill(this.m_humanSkill.m_cost)) return; + console.log("施放人技"); this.m_humanSkill.cast(CharacterInit.playerEnt, { x: this.m_animation.x, y: this.m_animation.y, @@ -2312,9 +2318,11 @@ else { let x = Math.round(Math.random()); if (x > 0.5) { + Laya.Scene.closeAll(); Laya.Scene.open("First.scene"); } else { + Laya.Scene.closeAll(); Laya.Scene.open("Town.scene"); } } @@ -2357,7 +2365,7 @@ id: 0, missionName: "新手教學", difficulty: 0, - enemyNum: 1, + enemyNum: 3, enemyHp: 5000, enemyAtk: 0, eliteNum: 0, @@ -2909,7 +2917,7 @@ GameConfig.startScene = "Village.scene"; GameConfig.sceneRoot = ""; GameConfig.debug = false; - GameConfig.stat = true; + GameConfig.stat = false; GameConfig.physicsDebug = false; GameConfig.exportSceneToJson = true; GameConfig.init(); diff --git a/firebase-debug.log b/firebase-debug.log new file mode 100644 index 0000000..9631612 --- /dev/null +++ b/firebase-debug.log @@ -0,0 +1,44 @@ +[debug] [2020-11-11T12:37:27.131Z] ---------------------------------------------------------------------- +[debug] [2020-11-11T12:37:27.133Z] Command: C:\Program Files\nodejs\node.exe C:\Users\LeeDong\AppData\Roaming\npm\node_modules\firebase-tools\lib\bin\firebase.js emulators:start +[debug] [2020-11-11T12:37:27.134Z] CLI Version: 8.15.1 +[debug] [2020-11-11T12:37:27.134Z] Platform: win32 +[debug] [2020-11-11T12:37:27.135Z] Node Version: v12.18.2 +[debug] [2020-11-11T12:37:27.136Z] Time: Wed Nov 11 2020 20:37:27 GMT+0800 (GMT+08:00) +[debug] [2020-11-11T12:37:27.136Z] ---------------------------------------------------------------------- +[debug] [2020-11-11T12:37:27.136Z] +[debug] [2020-11-11T12:37:27.144Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] +[debug] [2020-11-11T12:37:27.144Z] > authorizing via signed-in user +[info] i emulators: Starting emulators: hosting {"metadata":{"emulator":{"name":"hub"},"message":"Starting emulators: hosting"}} +[debug] [2020-11-11T12:37:29.193Z] [hub] writing locator at C:\Users\LeeDong\AppData\Local\Temp\hub-cathulhu-h5.json +[debug] [2020-11-11T12:37:31.238Z] >>> HTTP REQUEST GET https://firebase.googleapis.com/v1beta1/projects/cathulhu-h5/webApps/-/config + +[debug] [2020-11-11T12:37:32.763Z] <<< HTTP RESPONSE 200 {"content-type":"application/json; charset=UTF-8","vary":"X-Origin, Referer, Origin,Accept-Encoding","date":"Wed, 11 Nov 2020 12:37:31 GMT","server":"ESF","cache-control":"private","x-xss-protection":"0","x-frame-options":"SAMEORIGIN","x-content-type-options":"nosniff","alt-svc":"h3-Q050=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000,h3-T051=\":443\"; ma=2592000,h3-T050=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\":443\"; ma=2592000; v=\"46,43\"","accept-ranges":"none","transfer-encoding":"chunked"} +[info] i hosting: Serving hosting files from: public {"metadata":{"emulator":{"name":"hosting"},"message":"Serving hosting files from: \u001b[1mpublic\u001b[22m"}} +[info] + hosting: Local server: http://localhost:5000 {"metadata":{"emulator":{"name":"hosting"},"message":"Local server: \u001b[4m\u001b[1mhttp://localhost:5000\u001b[22m\u001b[24m"}} +[info] +┌──────────────────────────────────────────────────────────────┐ +│ ✔ All emulators ready! It is now safe to connect your apps. │ +└──────────────────────────────────────────────────────────────┘ + +┌──────────┬────────────────┐ +│ Emulator │ Host:Port │ +├──────────┼────────────────┤ +│ Hosting │ localhost:5000 │ +└──────────┴────────────────┘ + Other reserved ports: 4400 + +Issues? Report them at https://github.com/firebase/firebase-tools/issues and attach the *-debug.log files. + +[info] i hosting: 127.0.0.1 - - [11/Nov/2020:12:37:46 +0000] "GET / HTTP/1.1" 200 4526 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36" {"metadata":{"emulator":{"name":"hosting"},"message":"127.0.0.1 - - [11/Nov/2020:12:37:46 +0000] \"GET / HTTP/1.1\" 200 4526 \"-\" \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36\""}} +[info] i hosting: 127.0.0.1 - - [11/Nov/2020:12:37:46 +0000] "GET /__/firebase/8.0.1/firebase-app.js HTTP/1.1" 200 19969 "http://localhost:5000/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36" {"metadata":{"emulator":{"name":"hosting"},"message":"127.0.0.1 - - [11/Nov/2020:12:37:46 +0000] \"GET /__/firebase/8.0.1/firebase-app.js HTTP/1.1\" 200 19969 \"http://localhost:5000/\" \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36\""}} +[info] i hosting: 127.0.0.1 - - [11/Nov/2020:12:37:47 +0000] "GET /__/firebase/8.0.1/firebase-functions.js HTTP/1.1" 200 9993 "http://localhost:5000/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36" {"metadata":{"emulator":{"name":"hosting"},"message":"127.0.0.1 - - [11/Nov/2020:12:37:47 +0000] \"GET /__/firebase/8.0.1/firebase-functions.js HTTP/1.1\" 200 9993 \"http://localhost:5000/\" \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36\""}} +[info] i hosting: 127.0.0.1 - - [11/Nov/2020:12:37:47 +0000] "GET /__/firebase/8.0.1/firebase-auth.js HTTP/1.1" 200 176033 "http://localhost:5000/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36" {"metadata":{"emulator":{"name":"hosting"},"message":"127.0.0.1 - - [11/Nov/2020:12:37:47 +0000] \"GET /__/firebase/8.0.1/firebase-auth.js HTTP/1.1\" 200 176033 \"http://localhost:5000/\" \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36\""}} +[info] i hosting: 127.0.0.1 - - [11/Nov/2020:12:37:47 +0000] "GET /__/firebase/8.0.1/firebase-messaging.js HTTP/1.1" 200 40767 "http://localhost:5000/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36" {"metadata":{"emulator":{"name":"hosting"},"message":"127.0.0.1 - - [11/Nov/2020:12:37:47 +0000] \"GET /__/firebase/8.0.1/firebase-messaging.js HTTP/1.1\" 200 40767 \"http://localhost:5000/\" \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36\""}} +[info] i hosting: 127.0.0.1 - - [11/Nov/2020:12:37:48 +0000] "GET /__/firebase/8.0.1/firebase-database.js HTTP/1.1" 200 190490 "http://localhost:5000/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36" {"metadata":{"emulator":{"name":"hosting"},"message":"127.0.0.1 - - [11/Nov/2020:12:37:48 +0000] \"GET /__/firebase/8.0.1/firebase-database.js HTTP/1.1\" 200 190490 \"http://localhost:5000/\" \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36\""}} +[info] i hosting: 127.0.0.1 - - [11/Nov/2020:12:37:48 +0000] "GET /__/firebase/8.0.1/firebase-analytics.js HTTP/1.1" 200 35654 "http://localhost:5000/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36" {"metadata":{"emulator":{"name":"hosting"},"message":"127.0.0.1 - - [11/Nov/2020:12:37:48 +0000] \"GET /__/firebase/8.0.1/firebase-analytics.js HTTP/1.1\" 200 35654 \"http://localhost:5000/\" \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36\""}} +[info] i hosting: 127.0.0.1 - - [11/Nov/2020:12:37:48 +0000] "GET /__/firebase/8.0.1/firebase-storage.js HTTP/1.1" 200 36030 "http://localhost:5000/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36" {"metadata":{"emulator":{"name":"hosting"},"message":"127.0.0.1 - - [11/Nov/2020:12:37:48 +0000] \"GET /__/firebase/8.0.1/firebase-storage.js HTTP/1.1\" 200 36030 \"http://localhost:5000/\" \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36\""}} +[info] i hosting: 127.0.0.1 - - [11/Nov/2020:12:37:48 +0000] "GET /__/firebase/init.js?useEmulator=true HTTP/1.1" 200 - "http://localhost:5000/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36" {"metadata":{"emulator":{"name":"hosting"},"message":"127.0.0.1 - - [11/Nov/2020:12:37:48 +0000] \"GET /__/firebase/init.js?useEmulator=true HTTP/1.1\" 200 - \"http://localhost:5000/\" \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36\""}} +[info] i hosting: 127.0.0.1 - - [11/Nov/2020:12:37:48 +0000] "GET /__/firebase/8.0.1/firebase-performance.js HTTP/1.1" 200 38467 "http://localhost:5000/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36" {"metadata":{"emulator":{"name":"hosting"},"message":"127.0.0.1 - - [11/Nov/2020:12:37:48 +0000] \"GET /__/firebase/8.0.1/firebase-performance.js HTTP/1.1\" 200 38467 \"http://localhost:5000/\" \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36\""}} +[info] i hosting: 127.0.0.1 - - [11/Nov/2020:12:37:48 +0000] "GET /__/firebase/8.0.1/firebase-remote-config.js HTTP/1.1" 200 36826 "http://localhost:5000/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36" {"metadata":{"emulator":{"name":"hosting"},"message":"127.0.0.1 - - [11/Nov/2020:12:37:48 +0000] \"GET /__/firebase/8.0.1/firebase-remote-config.js HTTP/1.1\" 200 36826 \"http://localhost:5000/\" \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36\""}} +[info] i hosting: 127.0.0.1 - - [11/Nov/2020:12:37:50 +0000] "GET /__/firebase/8.0.1/firebase-firestore.js HTTP/1.1" 200 279682 "http://localhost:5000/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36" {"metadata":{"emulator":{"name":"hosting"},"message":"127.0.0.1 - - [11/Nov/2020:12:37:50 +0000] \"GET /__/firebase/8.0.1/firebase-firestore.js HTTP/1.1\" 200 279682 \"http://localhost:5000/\" \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36\""}} +[info] i hosting: 127.0.0.1 - - [11/Nov/2020:12:37:50 +0000] "GET /favicon.ico HTTP/1.1" 200 4526 "http://localhost:5000/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36" {"metadata":{"emulator":{"name":"hosting"},"message":"127.0.0.1 - - [11/Nov/2020:12:37:50 +0000] \"GET /favicon.ico HTTP/1.1\" 200 4526 \"http://localhost:5000/\" \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36\""}} diff --git a/firebase.json b/firebase.json new file mode 100644 index 0000000..93fb369 --- /dev/null +++ b/firebase.json @@ -0,0 +1,16 @@ +{ + "hosting": { + "public": "public", + "ignore": [ + "firebase.json", + "**/.*", + "**/node_modules/**" + ], + "rewrites": [ + { + "source": "**", + "destination": "/index.html" + } + ] + } +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..67073cf --- /dev/null +++ b/index.html @@ -0,0 +1,89 @@ + + + + + + Welcome to Firebase Hosting + + + + + + + + + + + + + + + + + + + +
+

Welcome

+

Firebase Hosting Setup Complete

+

You're seeing this because you've successfully setup Firebase Hosting. Now it's time to go build something extraordinary!

+ Open Hosting Documentation +
+

Firebase SDK Loading…

+ + + + diff --git a/laya/.laya b/laya/.laya index 258a0db..12929e3 100644 --- a/laya/.laya +++ b/laya/.laya @@ -1,6 +1,6 @@ - img,temp,sound - embed + img,temp,sound + embed png,jpg bin/res/atlas bin @@ -15,7 +15,7 @@ var Dialog=laya.ui.Dialog;]]> 1 - 80 + 80 false 2.0 - true + false false true false diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..67073cf --- /dev/null +++ b/public/index.html @@ -0,0 +1,89 @@ + + + + + + Welcome to Firebase Hosting + + + + + + + + + + + + + + + + + + + +
+

Welcome

+

Firebase Hosting Setup Complete

+

You're seeing this because you've successfully setup Firebase Hosting. Now it's time to go build something extraordinary!

+ Open Hosting Documentation +
+

Firebase SDK Loading…

+ + + + diff --git a/release/web/index.html b/release/web/index.html index af33be5..19ef2b0 100644 --- a/release/web/index.html +++ b/release/web/index.html @@ -27,6 +27,30 @@ } + + + + + + + \ No newline at end of file diff --git a/src/GameConfig.ts b/src/GameConfig.ts index 287e858..8a4d628 100644 --- a/src/GameConfig.ts +++ b/src/GameConfig.ts @@ -18,7 +18,7 @@ export default class GameConfig{ static startScene:any="Village.scene"; static sceneRoot:string=""; static debug:boolean=false; - static stat:boolean=true; + static stat:boolean=false; static physicsDebug:boolean=false; static exportSceneToJson:boolean=true; constructor(){} diff --git a/src/script/CharacterInit.ts b/src/script/CharacterInit.ts index af82f31..1881fb7 100644 --- a/src/script/CharacterInit.ts +++ b/src/script/CharacterInit.ts @@ -455,14 +455,16 @@ export class Character extends Laya.Script { this.m_canAttack = true; }, this.m_attackCdTime); } - if (this.m_keyDownList[16]) { - console.log(("按下shift")); + // if (this.m_keyDownList[16]) { + // console.log(("按下shift")); - // this.m_oathManager.addDebuff(1 << 0); - // this.m_oathManager.setBloodyPoint(100); - } + // // this.m_oathManager.addDebuff(1 << 0); + // // this.m_oathManager.setBloodyPoint(100); + // } if (this.m_keyDownList[88]) { if (!this.m_oathManager.oathCastSkill(this.m_humanSkill.m_cost)) return; + console.log("施放人技"); + this.m_humanSkill.cast(CharacterInit.playerEnt, { x: this.m_animation.x, diff --git a/src/script/MissionManager.ts b/src/script/MissionManager.ts index 3d0260a..ce26705 100644 --- a/src/script/MissionManager.ts +++ b/src/script/MissionManager.ts @@ -135,8 +135,10 @@ export default class MissionManager extends Laya.Script { } else { let x = Math.round(Math.random()); if (x > 0.5) { + Laya.Scene.closeAll(); Laya.Scene.open("First.scene"); } else { + Laya.Scene.closeAll(); Laya.Scene.open("Town.scene"); } } @@ -179,7 +181,7 @@ export default class MissionManager extends Laya.Script { id: 0, missionName: "新手教學", difficulty: 0, - enemyNum: 1, + enemyNum: 3, enemyHp: 5000, enemyAtk: 0, eliteNum: 0, diff --git a/src/script/OathManager.ts b/src/script/OathManager.ts index 32a8d35..c66f0b9 100644 --- a/src/script/OathManager.ts +++ b/src/script/OathManager.ts @@ -30,9 +30,6 @@ export default class OathManager extends Laya.Script { this.removeDebuff(1 << i); } this.clearBloodyUI(); - } - public clearAllDebuff() { - } public getBloodyPoint(){ return CharacterInit.playerEnt.m_bloodyPoint; @@ -55,6 +52,8 @@ export default class OathManager extends Laya.Script { } if (!CharacterInit.playerEnt.m_animation.destroyed && this.oathBar != null) this.oathBar.value = CharacterInit.playerEnt.m_bloodyPoint / CharacterInit.playerEnt.m_maxBloodyPoint_hard; + console.log(CharacterInit.playerEnt.m_bloodyPoint); + }), 5); Laya.stage.addChild(this.oathBar); @@ -237,6 +236,17 @@ export default class OathManager extends Laya.Script { this.overChargeCount = 0; this.oathBar.skin = "UI/bp_150.png"; this.oathBar.sizeGrid = "0,200,0,20"; + + this.addDebuffTimer = setInterval(() => { + if (CharacterInit.playerEnt.m_animation.destroyed) { + clearInterval(this.addDebuffTimer); + return; + } + console.log("執行addDebuffTimer內函式"); + // console.log(this.playerDebuff); + this.randomAddDebuff(); + }, 5000); + this.oathState = OathStatus.overCharge; return; } diff --git a/src/script/SkillCat.ts b/src/script/SkillCat.ts index 1109b15..a2fdf74 100644 --- a/src/script/SkillCat.ts +++ b/src/script/SkillCat.ts @@ -14,9 +14,10 @@ export class Slam extends VirtualSkill { m_iconB = "ui/icon/slamB.png"; m_injuredEnemy: VirtualEnemy[] = []; - + cast(owner: any, position: object): void { if (!this.m_canUse) return; + this.m_canUse = false; let rightSide: boolean = owner.m_isFacingRight; this.m_animation = new Laya.Animation() @@ -74,7 +75,6 @@ export class Slam extends VirtualSkill { let rangeY: number = 0; - this.m_canUse = false; this.castRoar(position); this.m_injuredEnemy = [];//暫時用來記憶被此次技能打中的敵人,並忽略此攻擊 @@ -106,12 +106,13 @@ export class BlackHole extends VirtualSkill { m_cd = 5; m_lastTime = 2; m_radius = 100;//黑洞半徑 - + m_iconA = "ui/icon/blackholeA.png"; m_iconB = "ui/icon/blackholeB.png"; - + cast(owner: any, position: object): void { if (!this.m_canUse) return; + this.m_canUse = false; let rightSide: boolean = owner.m_isFacingRight; let explosion: Laya.Animation = new Laya.Animation(); @@ -137,7 +138,6 @@ export class BlackHole extends VirtualSkill { let offsetX: number = rightSide ? position['x'] + 140 : position['x'] - this.m_animation.width - 65; let offsetY: number = position['y'] - this.m_animation.height / 2; - this.m_canUse = false; this.castRoar(position); let colorMat: Array = diff --git a/src/script/SkillHuman.ts b/src/script/SkillHuman.ts index a542569..3d4a037 100644 --- a/src/script/SkillHuman.ts +++ b/src/script/SkillHuman.ts @@ -22,6 +22,7 @@ export class Spike extends VirtualSkill { cast(owner: any, position: object): void { if (!this.m_canUse) return; + this.m_canUse = false; let rightSide: boolean = owner.m_isFacingRight; this.m_animation = new Laya.Animation() @@ -38,7 +39,6 @@ export class Spike extends VirtualSkill { this.m_animation.autoPlay = true; this.m_animation.interval = 20; - this.m_canUse = false; this.castRoar(position); let colorMat: Array = @@ -77,6 +77,8 @@ export class Spike extends VirtualSkill { }, 200); setTimeout(() => { this.m_canUse = true; + console.log("技能可使用"); + }, this.m_cd * 1000); } @@ -110,6 +112,7 @@ export class Behead extends VirtualSkill { cast(owner: any, position: object): void { if (!this.m_canUse) return; + this.m_canUse = false; let rightSide: boolean = owner.m_isFacingRight; this.m_animation = new Laya.Animation() @@ -128,7 +131,6 @@ export class Behead extends VirtualSkill { this.m_animation.alpha = 0.8; this.m_animation.zOrder = 5; - this.m_canUse = false; this.castRoar(position); owner.delayMove(this.m_preTime);