diff --git a/gulp/.itch.toml b/gulp/.itch.toml deleted file mode 100644 index 2556ac9c..00000000 --- a/gulp/.itch.toml +++ /dev/null @@ -1,9 +0,0 @@ -[[actions]] -name = "play" -path = "shapezio.exe" -platform = "windows" - -[[actions]] -name = "play" -path = "play.sh" -platform = "linux" diff --git a/gulp/build_variants.js b/gulp/build_variants.js new file mode 100644 index 00000000..a0a4ab72 --- /dev/null +++ b/gulp/build_variants.js @@ -0,0 +1,66 @@ +/** + * @type {Record} + */ +const BUILD_VARIANTS = { + "web-localhost": { + standalone: false, + environment: "dev", + buildArgs: {}, + }, + "web-shapezio-beta": { + standalone: false, + environment: "staging", + buildArgs: {}, + }, + "web-shapezio": { + standalone: false, + environment: "prod", + buildArgs: {}, + }, + "standalone-steam": { + standalone: true, + executableName: "shapez", + steamAppId: 1318690, + buildArgs: {}, + }, + "standalone-steam-china": {n + standalone: true, + steamAppId: 1318690, + buildArgs: { + chineseVersion: true, + }, + }, + "standalone-steam-demo": { + standalone: true, + steamAppId: 1930750, + buildArgs: { + steamDemo: true, + }, + }, + "standalone-steam-china-demo": { + standalone: true, + steamAppId: 1930750, + buildArgs: { + steamDemo: true, + chineseVersion: true, + }, + }, + "standalone-wegame": { + standalone: true, + electronBaseDir: "electron_wegame", + buildArgs: { + wegameVersion: true, + }, + }, +}; +module.exports = { BUILD_VARIANTS }; diff --git a/gulp/cordova.js b/gulp/cordova.js deleted file mode 100644 index 22274dba..00000000 --- a/gulp/cordova.js +++ /dev/null @@ -1,139 +0,0 @@ -const path = require("path"); -const fs = require("fs"); -const buildUtils = require("./buildutils"); - -function gulptasksCordova($, gulp, buildFolder) { - const cdvRes = path.join("..", "..", "res"); - - // Cleans up the app assets - // Removes all temporary folders used while optimizing the assets - gulp.task("cleanupAppAssetsBuiltFolder", () => { - return gulp - .src(path.join(cdvRes, "built"), { read: false, allowEmpty: true }) - .pipe($.clean({ force: true })); - }); - - // Optimizes all built assets - gulp.task("optimizeBuiltAppAssets", () => { - return gulp - .src(path.join(cdvRes, "built", "**", "*.png")) - .pipe($.flatten()) - .pipe($.imagemin([$.imagemin.optipng({ optimizationLevel: 1 })])) - .pipe(gulp.dest(path.join(cdvRes, "built"))); - }); - - // Scales the icon resources - gulp.task("scaleIconIos", async () => { - const sizes = [ - 180, - 60, - 120, - 76, - 152, - 40, - 80, - 57, - 114, - 72, - 144, - 167, - 29, - 58, - 87, - 50, - 100, - 167, - 20, - 1024, - 24, - 48, - 55, - 172, - 196, - ]; - for (let i = 0; i < sizes.length; ++i) { - const size = sizes[i]; - console.log("Scaling icon to", size, "x", size); - const img = await $.jimp.read(path.join(cdvRes, "ios", "icon-prefab.png")); - await img.resize(size, size).write(path.join(cdvRes, "built", "ios", "icon@" + size + ".png")); - } - }); - - gulp.task("copyOtherIosResources", () => { - return gulp - .src(path.join(cdvRes, "ios", "splash-prefab.png")) - .pipe($.rename("Default@2x~universal~anyany.png")) - .pipe(gulp.dest(path.join(cdvRes, "built", "ios"))); - }); - - gulp.task("prepareIosRes", gulp.series("scaleIconIos", "copyOtherIosResources")); - - gulp.task("copyAndroidResources", () => { - return gulp - .src(path.join(cdvRes, "android", "**", "*.*")) - .pipe(gulp.dest(path.join(cdvRes, "built", "android"))); - }); - - gulp.task("prepareAndroidRes", gulp.series("copyAndroidResources")); - - gulp.task( - "prepareCordovaAssets", - gulp.series( - "cleanupAppAssetsBuiltFolder", - gulp.parallel("prepareIosRes", "prepareAndroidRes"), - "optimizeBuiltAppAssets" - ) - ); - - // Patches the config.xml by replacing the app id to app_beta - - gulp.task("patchConfigXML", cb => { - const configUrl = path.join("..", "..", "config.xml"); - let configContent = fs.readFileSync(configUrl).toString(); - const version = buildUtils.getVersion(); - configContent = configContent.replace("%VERSION%", version); - configContent = configContent.replace(' id="io.shapez.app" ', ' id="io.shapez.app_beta" '); - configContent = configContent.replace("Shapez.io", "Shapez.io BETA"); - fs.writeFileSync(configUrl, configContent); - cb(); - }); - - gulp.task("patchConfigXMLChangeStagingToProd", cb => { - const configUrl = path.join("..", "..", "config.xml"); - let configContent = fs.readFileSync(configUrl).toString(); - configContent = configContent.replace(' id="io.shapez.app_beta" ', ' id="io.shapez.app" '); - configContent = configContent.replace("Shapez.io BETA", "Shapez.io"); - fs.writeFileSync(configUrl, configContent); - cb(); - }); - - // Triggers a new build on phonegap - gulp.task("triggerPhonegapBuild", () => { - return gulp - .src("src/html/", { dot: false }) - .pipe( - $.phonegapBuild({ - isRepository: true, - appId: "3339820", - platforms: ["android", "ios"], - user: { - token: process.env.SHAPEZ_CLI_PHONEGAP_KEY, - }, - }) - ) - .pipe( - $.phonegapBuild({ - isRepository: true, - appId: "3537816", - platforms: ["android", "ios"], - user: { - token: process.env.SHAPEZ_CLI_PHONEGAP_KEY, - }, - }) - ); - }); -} - -module.exports = { - gulptasksCordova, -}; diff --git a/gulp/gulpfile.js b/gulp/gulpfile.js index 7c210417..4b5b18cf 100644 --- a/gulp/gulpfile.js +++ b/gulp/gulpfile.js @@ -18,7 +18,6 @@ const $ = require("gulp-load-plugins")({ const envVars = [ "SHAPEZ_CLI_SERVER_HOST", - // "SHAPEZ_CLI_PHONEGAP_KEY", "SHAPEZ_CLI_ALPHA_FTP_USER", "SHAPEZ_CLI_ALPHA_FTP_PW", "SHAPEZ_CLI_STAGING_FTP_USER", @@ -33,8 +32,7 @@ const envVars = [ for (let i = 0; i < envVars.length; ++i) { if (!process.env[envVars[i]]) { - console.warn("Please set", envVars[i]); - // process.exit(1); + console.warn("Unset environment variable, might cause issues:", envVars[i]); } } @@ -57,7 +55,7 @@ const js = require("./js"); js.gulptasksJS($, gulp, buildFolder, browserSync); const html = require("./html"); -html.gulptasksHTML($, gulp, buildFolder, browserSync); +html.gulptasksHTML($, gulp, buildFolder); const ftp = require("./ftp"); ftp.gulptasksFTP($, gulp, buildFolder); @@ -66,13 +64,11 @@ const docs = require("./docs"); docs.gulptasksDocs($, gulp, buildFolder); const standalone = require("./standalone"); -standalone.gulptasksStandalone($, gulp, buildFolder); - -const releaseUploader = require("./release-uploader"); -releaseUploader.gulptasksReleaseUploader($, gulp, buildFolder); +standalone.gulptasksStandalone($, gulp); const translations = require("./translations"); -translations.gulptasksTranslations($, gulp, buildFolder); +const { BUILD_VARIANTS } = require("./build_variants"); +translations.gulptasksTranslations($, gulp); ///////////////////// BUILD TASKS ///////////////////// @@ -142,9 +138,9 @@ gulp.task("main.webserver", () => { /** * * @param {object} param0 - * @param {"web"|"standalone"|"china"|"wegame"} param0.version + * @param {keyof typeof BUILD_VARIANTS} param0.version */ -function serve({ version = "web" }) { +function serveHTML({ version = "web-dev" }) { browserSync.init({ server: [buildFolder, path.join(baseDir, "mod_examples")], port: 3005, @@ -168,10 +164,7 @@ function serve({ version = "web" }) { gulp.watch(["../src/**/*.scss"], gulp.series("css.dev")); // Watch .html files, those trigger a html rebuild - gulp.watch("../src/**/*.html", gulp.series(version === "web" ? "html.dev" : "html.standalone-dev")); - - // Watch sound files - // gulp.watch(["../res_raw/sounds/**/*.mp3", "../res_raw/sounds/**/*.wav"], gulp.series("sounds.dev")); + gulp.watch("../src/**/*.html", gulp.series("html." + version + ".dev")); // Watch translations gulp.watch("../translations/**/*.yaml", gulp.series("translations.convertToJson")); @@ -204,27 +197,7 @@ function serve({ version = "web" }) { return gulp.src(path).pipe(browserSync.reload({ stream: true })); }); - switch (version) { - case "web": { - gulp.series("js.dev.watch")(() => true); - break; - } - case "standalone": { - gulp.series("js.standalone-dev.watch")(() => true); - break; - } - case "china": { - gulp.series("china.js.dev.watch")(() => true); - break; - } - case "wegame": { - gulp.series("wegame.js.dev.watch")(() => true); - break; - } - default: { - throw new Error("Unknown version " + version); - } - } + gulp.series("js." + version + ".dev.watch")(() => true); } ///////////////////// RUNNABLE TASKS ///////////////////// @@ -238,9 +211,9 @@ gulp.task("step.deleteEmpty", cb => { gulp.task("step.postbuild", gulp.series("imgres.cleanupUnusedCssInlineImages", "step.deleteEmpty")); -// Builds everything (dev) +// // Builds everything (dev) gulp.task( - "build.dev", + "build.prepare.dev", gulp.series( "utils.cleanup", "utils.copyAdditionalBuildFiles", @@ -252,146 +225,95 @@ gulp.task( "imgres.copyImageResources", "imgres.copyNonImageResources", "translations.fullBuild", - "css.dev", - "html.dev" + "css.dev" ) ); -// Builds everything (standalone -dev) -gulp.task( - "build.standalone.dev", - gulp.series( - "utils.cleanup", - "localConfig.findOrCreate", - "imgres.buildAtlas", - "imgres.atlasToJson", - "imgres.atlas", - "sounds.dev", - "imgres.copyImageResources", - "imgres.copyNonImageResources", - "translations.fullBuild", - "css.dev", - "html.standalone-dev" - ) -); +// // Builds everything (staging) +// gulp.task("step.staging.code", gulp.series("sounds.fullbuild", "translations.fullBuild", "js.staging")); +// gulp.task( +// "step.staging.mainbuild", +// gulp.parallel("utils.copyAdditionalBuildFiles", "step.baseResources", "step.staging.code") +// ); +// gulp.task("step.staging.all", gulp.series("step.staging.mainbuild", "css.prod", "html.staging")); +// gulp.task("build.staging", gulp.series("utils.cleanup", "step.staging.all", "step.postbuild")); -// Builds everything (staging) -gulp.task("step.staging.code", gulp.series("sounds.fullbuild", "translations.fullBuild", "js.staging")); -gulp.task( - "step.staging.mainbuild", - gulp.parallel("utils.copyAdditionalBuildFiles", "step.baseResources", "step.staging.code") -); -gulp.task("step.staging.all", gulp.series("step.staging.mainbuild", "css.prod", "html.staging")); -gulp.task("build.staging", gulp.series("utils.cleanup", "step.staging.all", "step.postbuild")); +// // Builds everything (prod) +// gulp.task("step.prod.code", gulp.series("sounds.fullbuild", "translations.fullBuild", "js.prod")); +// gulp.task( +// "step.prod.mainbuild", +// gulp.parallel("utils.copyAdditionalBuildFiles", "step.baseResources", "step.prod.code") +// ); +// gulp.task("step.prod.all", gulp.series("step.prod.mainbuild", "css.prod", "html.prod")); +// gulp.task("build.prod", gulp.series("utils.cleanup", "step.prod.all", "step.postbuild")); -// Builds everything (prod) -gulp.task("step.prod.code", gulp.series("sounds.fullbuild", "translations.fullBuild", "js.prod")); -gulp.task( - "step.prod.mainbuild", - gulp.parallel("utils.copyAdditionalBuildFiles", "step.baseResources", "step.prod.code") -); -gulp.task("step.prod.all", gulp.series("step.prod.mainbuild", "css.prod", "html.prod")); -gulp.task("build.prod", gulp.series("utils.cleanup", "step.prod.all", "step.postbuild")); +// Builds everything for every variant +for (const variant in BUILD_VARIANTS) { + const data = BUILD_VARIANTS[variant]; + const buildName = "build." + variant; -// Builds everything (standalone-beta) -gulp.task( - "step.standalone-beta.code", - gulp.series("sounds.fullbuildHQ", "translations.fullBuild", "js.standalone-beta") -); -gulp.task("step.standalone-beta.mainbuild", gulp.parallel("step.baseResources", "step.standalone-beta.code")); -gulp.task( - "step.standalone-beta.all", - gulp.series("step.standalone-beta.mainbuild", "css.prod-standalone", "html.standalone-beta") -); -gulp.task( - "build.standalone-beta", - gulp.series("utils.cleanup", "step.standalone-beta.all", "step.postbuild") -); - -// Builds everything (standalone-prod) - -for (const prefix of ["", "china.", "wegame."]) { gulp.task( - prefix + "step.standalone-prod.code", - gulp.series("sounds.fullbuildHQ", "translations.fullBuild", prefix + "js.standalone-prod") + buildName + ".code", + gulp.series( + data.standalone ? "sounds.fullbuildHQ" : "sounds.fullbuild", + "translations.fullBuild", + "js." + variant + ".prod" + ) ); - gulp.task( - prefix + "step.standalone-prod.mainbuild", - gulp.parallel("step.baseResources", prefix + "step.standalone-prod.code") - ); + gulp.task(buildName + ".resourcesAndCode", gulp.parallel("step.baseResources", buildName + ".code")); gulp.task( - prefix + "step.standalone-prod.all", - gulp.series(prefix + "step.standalone-prod.mainbuild", "css.prod-standalone", "html.standalone-prod") + buildName + ".all", + gulp.series(buildName + ".resourcesAndCode", "css.prod-standalone", "html." + variant + ".prod") ); + gulp.task(buildName, gulp.series("utils.cleanup", buildName + ".all", "step.postbuild")); + + // serve gulp.task( - prefix + "build.standalone-prod", - gulp.series("utils.cleanup", prefix + "step.standalone-prod.all", "step.postbuild") + "serve." + variant, + gulp.series("build.prepare.dev", "html." + variant + ".dev", () => serveHTML({ version: variant })) ); } // OS X build and release upload -gulp.task( - "build.darwin64-prod", - gulp.series( - "build.standalone-prod", - "standalone.prepare", - "standalone.package.prod.darwin64.signManually" - ) -); +// gulp.task( +// "build.darwin64-prod", +// gulp.series( +// "build.standalone-prod", +// "standalone.prepare", +// "standalone.package.prod.darwin64.signManually" +// ) +// ); // Deploying! gulp.task( - "main.deploy.alpha", - gulp.series("utils.requireCleanWorkingTree", "build.staging", "ftp.upload.alpha") + "deploy.staging", + gulp.series("utils.requireCleanWorkingTree", "build.web-shapezio-beta", "ftp.upload.staging") ); gulp.task( - "main.deploy.staging", - gulp.series("utils.requireCleanWorkingTree", "build.staging", "ftp.upload.staging") -); -gulp.task("main.deploy.prod", gulp.series("utils.requireCleanWorkingTree", "build.prod", "ftp.upload.prod")); -gulp.task("main.deploy.all", gulp.series("main.deploy.staging", "main.deploy.prod")); - -// steam -gulp.task("regular.main.standalone", gulp.series("build.standalone-prod", "standalone.package.prod")); - -// china -gulp.task( - "china.main.standalone", - gulp.series("china.build.standalone-prod", "china.standalone.package.prod") + "deploy.prod", + gulp.series("utils.requireCleanWorkingTree", "build.web-shapezio", "ftp.upload.prod") ); -// wegame -gulp.task( - "wegame.main.standalone", - gulp.series("wegame.build.standalone-prod", "wegame.standalone.package.prod") -); +// // china +// gulp.task( +// "china.main.standalone", +// gulp.series("china.build.standalone-prod", "china.standalone.package.prod") +// ); -// all (except wegame) -gulp.task("standalone.steam", gulp.series("regular.main.standalone", "china.main.standalone")); -gulp.task( - "standalone.all", - gulp.series("regular.main.standalone", "china.main.standalone", "wegame.main.standalone") -); +// // wegame +// gulp.task( +// "wegame.main.standalone", +// gulp.series("wegame.build.standalone-prod", "wegame.standalone.package.prod") +// ); -// Live-development -gulp.task( - "main.serveDev", - gulp.series("build.dev", () => serve({ version: "web" })) -); -gulp.task( - "main.serveStandalone", - gulp.series("build.standalone.dev", () => serve({ version: "standalone" })) -); -gulp.task( - "china.main.serveDev", - gulp.series("build.dev", () => serve({ version: "china" })) -); -gulp.task( - "wegame.main.serveDev", - gulp.series("build.dev", () => serve({ version: "wegame" })) -); +// // all (except wegame) +// gulp.task("standalone.steam", gulp.series("regular.main.standalone", "china.main.standalone")); +// gulp.task( +// "standalone.all", +// gulp.series("regular.main.standalone", "china.main.standalone", "wegame.main.standalone") +// ); -gulp.task("default", gulp.series("main.serveDev")); +gulp.task("default", gulp.series("serve.web-localhost")); diff --git a/gulp/html.js b/gulp/html.js index 0ba58a15..be638f43 100644 --- a/gulp/html.js +++ b/gulp/html.js @@ -2,6 +2,7 @@ const buildUtils = require("./buildutils"); const fs = require("fs"); const path = require("path"); const crypto = require("crypto"); +const { BUILD_VARIANTS } = require("./build_variants"); function computeIntegrityHash(fullPath, algorithm = "sha256") { const file = fs.readFileSync(fullPath); @@ -9,12 +10,20 @@ function computeIntegrityHash(fullPath, algorithm = "sha256") { return algorithm + "-" + hash; } +/** + * PROVIDES (per ) + * + * html..dev + * html..prod + */ function gulptasksHTML($, gulp, buildFolder) { const commitHash = buildUtils.getRevision(); - async function buildHtml( - apiUrl, - { analytics = false, standalone = false, app = false, integrity = true, enableCachebust = true } - ) { + async function buildHtml({ + googleAnalytics = false, + standalone = false, + integrity = true, + enableCachebust = true, + }) { function cachebust(url) { if (enableCachebust) { return buildUtils.cachebust(url, commitHash); @@ -22,7 +31,7 @@ function gulptasksHTML($, gulp, buildFolder) { return url; } - const hasLocalFiles = standalone || app; + const hasLocalFiles = standalone; return gulp .src("../src/html/" + (standalone ? "index.standalone.html" : "index.html")) @@ -31,13 +40,6 @@ function gulptasksHTML($, gulp, buildFolder) { /** @this {Document} **/ function () { const document = this; - // Preconnect to api - const prefetchLink = document.createElement("link"); - prefetchLink.rel = "preconnect"; - prefetchLink.href = apiUrl; - prefetchLink.setAttribute("crossorigin", "anonymous"); - document.head.appendChild(prefetchLink); - // Append css const css = document.createElement("link"); css.rel = "stylesheet"; @@ -53,31 +55,8 @@ function gulptasksHTML($, gulp, buildFolder) { } document.head.appendChild(css); - // Append async css - // const asyncCss = document.createElement("link"); - // asyncCss.rel = "stylesheet"; - // asyncCss.type = "text/css"; - // asyncCss.media = "none"; - // asyncCss.setAttribute("onload", "this.media='all'"); - // asyncCss.href = cachebust("async-resources.css"); - // if (integrity) { - // asyncCss.setAttribute( - // "integrity", - // computeIntegrityHash(path.join(buildFolder, "async-resources.css")) - // ); - // } - // document.head.appendChild(asyncCss); - - if (app) { - // Append cordova link - const cdv = document.createElement("script"); - cdv.src = "cordova.js"; - cdv.type = "text/javascript"; - document.head.appendChild(cdv); - } - // Google analytics - if (analytics) { + if (googleAnalytics) { const tagManagerScript = document.createElement("script"); tagManagerScript.src = "https://www.googletagmanager.com/gtag/js?id=UA-165342524-1"; @@ -92,14 +71,6 @@ function gulptasksHTML($, gulp, buildFolder) { gtag('config', 'UA-165342524-1', { anonymize_ip: true }); `; document.head.appendChild(initScript); - - const abTestingScript = document.createElement("script"); - abTestingScript.setAttribute( - "src", - "https://www.googleoptimize.com/optimize.js?id=OPT-M5NHCV7" - ); - abTestingScript.setAttribute("async", ""); - document.head.appendChild(abTestingScript); } // Do not need to preload in app or standalone @@ -250,50 +221,25 @@ function gulptasksHTML($, gulp, buildFolder) { .pipe(gulp.dest(buildFolder)); } - gulp.task("html.dev", () => { - return buildHtml("http://localhost:5005", { - analytics: false, - integrity: false, - enableCachebust: false, + for (const variant in BUILD_VARIANTS) { + const data = BUILD_VARIANTS[variant]; + gulp.task("html." + variant + ".dev", () => { + return buildHtml({ + googleAnalytics: false, + standalone: data.standalone, + integrity: false, + enableCachebust: false, + }); }); - }); - - gulp.task("html.staging", () => { - return buildHtml("https://api-staging.shapez.io", { - analytics: true, + gulp.task("html." + variant + ".prod", () => { + return buildHtml({ + googleAnalytics: !data.standalone, + standalone: data.standalone, + integrity: true, + enableCachebust: !data.standalone, + }); }); - }); - - gulp.task("html.prod", () => { - return buildHtml("https://analytics.shapez.io", { - analytics: true, - }); - }); - - gulp.task("html.standalone-dev", () => { - return buildHtml("https://localhost:5005", { - analytics: false, - standalone: true, - integrity: false, - enableCachebust: false, - }); - }); - - gulp.task("html.standalone-beta", () => { - return buildHtml("https://api-staging.shapez.io", { - analytics: false, - standalone: true, - enableCachebust: false, - }); - }); - - gulp.task("html.standalone-prod", () => { - return buildHtml("https://analytics.shapez.io", { - analytics: false, - standalone: true, - enableCachebust: false, - }); - }); + } } module.exports = { diff --git a/gulp/js.js b/gulp/js.js index 93dab464..f3f77ad9 100644 --- a/gulp/js.js +++ b/gulp/js.js @@ -1,260 +1,122 @@ const path = require("path"); +const { BUILD_VARIANTS } = require("./build_variants"); function requireUncached(module) { delete require.cache[require.resolve(module)]; return require(module); } +/** + * PROVIDES (per ) + * + * js..dev.watch + * js..dev + * js..prod + * + */ + function gulptasksJS($, gulp, buildFolder, browserSync) { //// DEV - gulp.task("js.dev.watch", () => { - return gulp - .src("../src/js/main.js") - .pipe( - $.webpackStream( - requireUncached("./webpack.config.js")({ - watch: true, - }) + for (const variant in BUILD_VARIANTS) { + const data = BUILD_VARIANTS[variant]; + + gulp.task("js." + variant + ".dev.watch", () => { + return gulp + .src("../src/js/main.js") + .pipe( + $.webpackStream( + requireUncached("./webpack.config.js")({ + ...data.buildArgs, + standalone: data.standalone, + watch: true, + }) + ) ) - ) - .pipe(gulp.dest(buildFolder)) - .pipe(browserSync.stream()); - }); + .pipe(gulp.dest(buildFolder)) + .pipe(browserSync.stream()); + }); - gulp.task("js.dev", () => { - return gulp - .src("../src/js/main.js") - .pipe($.webpackStream(requireUncached("./webpack.config.js")({}))) - .pipe(gulp.dest(buildFolder)); - }); + if (!data.standalone) { + // WEB - //// DEV CHINA + gulp.task("js." + variant + ".dev", () => { + return gulp + .src("../src/js/main.js") + .pipe( + $.webpackStream( + requireUncached("./webpack.config.js")({ + ...data.buildArgs, + }) + ) + ) + .pipe(gulp.dest(buildFolder)); + }); - gulp.task("china.js.dev.watch", () => { - return gulp - .src("../src/js/main.js") - .pipe( - $.webpackStream( - requireUncached("./webpack.config.js")({ - watch: true, - chineseVersion: true, - }) - ) - ) - .pipe(gulp.dest(buildFolder)) - .pipe(browserSync.stream()); - }); + gulp.task("js." + variant + ".prod.transpiled", () => { + return gulp + .src("../src/js/main.js") + .pipe( + $.webpackStream( + requireUncached("./webpack.production.config.js")({ + es6: false, + ...data.buildArgs, + }) + ) + ) + .pipe($.rename("bundle-transpiled.js")) + .pipe(gulp.dest(buildFolder)); + }); - gulp.task("china.js.dev", () => { - return gulp - .src("../src/js/main.js") - .pipe( - $.webpackStream( - requireUncached("./webpack.config.js")({ - chineseVersion: true, - }) - ) - ) - .pipe(gulp.dest(buildFolder)); - }); - - //// DEV WEGAME - - gulp.task("wegame.js.dev.watch", () => { - return gulp - .src("../src/js/main.js") - .pipe( - $.webpackStream( - requireUncached("./webpack.config.js")({ - watch: true, - wegameVersion: true, - }) - ) - ) - .pipe(gulp.dest(buildFolder)) - .pipe(browserSync.stream()); - }); - - gulp.task("wegame.js.dev", () => { - return gulp - .src("../src/js/main.js") - .pipe( - $.webpackStream( - requireUncached("./webpack.config.js")({ - wegameVersion: true, - }) - ) - ) - .pipe(gulp.dest(buildFolder)); - }); - - //// STAGING - - gulp.task("js.staging.transpiled", () => { - return gulp - .src("../src/js/main.js") - .pipe( - $.webpackStream( - requireUncached("./webpack.production.config.js")({ - enableAssert: true, - environment: "staging", - es6: false, - }) - ) - ) - .pipe($.rename("bundle-transpiled.js")) - .pipe(gulp.dest(buildFolder)); - }); - - gulp.task("js.staging.latest", () => { - return gulp - .src("../src/js/main.js") - .pipe( - $.webpackStream( - requireUncached("./webpack.production.config.js")({ - enableAssert: true, - environment: "staging", - es6: true, - }) - ) - ) - .pipe(gulp.dest(buildFolder)); - }); - gulp.task("js.staging", gulp.parallel("js.staging.transpiled", "js.staging.latest")); - - //// PROD - - gulp.task("js.prod.transpiled", () => { - return gulp - .src("../src/js/main.js") - .pipe( - $.webpackStream( - requireUncached("./webpack.production.config.js")({ - enableAssert: false, - environment: "prod", - es6: false, - }) - ) - ) - .pipe($.rename("bundle-transpiled.js")) - .pipe(gulp.dest(buildFolder)) - .pipe(browserSync.stream()); - }); - - gulp.task("js.prod.latest", () => { - return gulp - .src("../src/js/main.js") - .pipe( - $.webpackStream( - requireUncached("./webpack.production.config.js")({ - enableAssert: false, - environment: "prod", - es6: true, - }) - ) - ) - .pipe(gulp.dest(buildFolder)) - .pipe(browserSync.stream()); - }); - - gulp.task("js.prod", gulp.parallel("js.prod.transpiled", "js.prod.latest")); - - //// STANDALONE - - gulp.task("js.standalone-dev.watch", () => { - return gulp - .src("../src/js/main.js") - .pipe( - $.webpackStream( - requireUncached("./webpack.config.js")({ - watch: true, - standalone: true, - }) - ) - ) - .pipe(gulp.dest(buildFolder)) - .pipe(browserSync.stream()); - }); - - gulp.task("js.standalone-dev", () => { - return gulp - .src("../src/js/main.js") - .pipe( - $.webpackStream( - requireUncached("./webpack.config.js")({ - standalone: true, - }) - ) - ) - .pipe(gulp.dest(buildFolder)); - }); - - gulp.task("js.standalone-beta", () => { - return gulp - .src("../src/js/main.js") - .pipe( - $.webpackStream( - requireUncached("./webpack.production.config.js")({ - enableAssert: true, - environment: "staging", - es6: true, - standalone: true, - }) - ) - ) - .pipe(gulp.dest(buildFolder)); - }); - - gulp.task("js.standalone-prod", () => { - return gulp - .src("../src/js/main.js") - .pipe( - $.webpackStream( - requireUncached("./webpack.production.config.js")({ - enableAssert: false, - environment: "prod", - es6: true, - standalone: true, - }) - ) - ) - .pipe(gulp.dest(buildFolder)); - }); - - gulp.task("china.js.standalone-prod", () => { - return gulp - .src("../src/js/main.js") - .pipe( - $.webpackStream( - requireUncached("./webpack.production.config.js")({ - enableAssert: false, - environment: "prod", - es6: true, - standalone: true, - chineseVersion: true, - }) - ) - ) - .pipe(gulp.dest(buildFolder)); - }); - - gulp.task("wegame.js.standalone-prod", () => { - return gulp - .src("../src/js/main.js") - .pipe( - $.webpackStream( - requireUncached("./webpack.production.config.js")({ - enableAssert: false, - environment: "prod", - es6: false, - standalone: true, - wegameVersion: true, - }) - ) - ) - .pipe(gulp.dest(buildFolder)); - }); + gulp.task("js." + variant + ".prod.es6", () => { + return gulp + .src("../src/js/main.js") + .pipe( + $.webpackStream( + requireUncached("./webpack.production.config.js")({ + es6: true, + ...data.buildArgs, + }) + ) + ) + .pipe(gulp.dest(buildFolder)); + }); + gulp.task( + "js." + variant + ".prod", + gulp.parallel("js." + variant + ".prod.transpiled", "js." + variant + ".prod.es6") + ); + } else { + // STANDALONE + gulp.task("js." + variant + ".dev", () => { + return gulp + .src("../src/js/main.js") + .pipe( + $.webpackStream( + requireUncached("./webpack.config.js")({ + ...data.buildArgs, + standalone: true, + }) + ) + ) + .pipe(gulp.dest(buildFolder)); + }); + gulp.task("js." + variant + ".prod", () => { + return gulp + .src("../src/js/main.js") + .pipe( + $.webpackStream( + requireUncached("./webpack.production.config.js")({ + ...data.buildArgs, + environment: "prod", + es6: true, + standalone: true, + }) + ) + ) + .pipe(gulp.dest(buildFolder)); + }); + } + } } module.exports = { diff --git a/gulp/release-uploader.js b/gulp/release-uploader.js deleted file mode 100644 index eececa4a..00000000 --- a/gulp/release-uploader.js +++ /dev/null @@ -1,66 +0,0 @@ -const path = require("path"); -const fs = require("fs"); -const execSync = require("child_process").execSync; -const { Octokit } = require("@octokit/rest"); -const buildutils = require("./buildutils"); - -function gulptasksReleaseUploader($, gulp, buildFolder) { - const standaloneDir = path.join(__dirname, "..", "tmp_standalone_files"); - const darwinApp = path.join(standaloneDir, "shapez.io-standalone-darwin-x64", "shapez.io-standalone.app"); - const dmgName = "shapez.io-standalone.dmg"; - const dmgPath = path.join(standaloneDir, "shapez.io-standalone-darwin-x64", dmgName); - - gulp.task("standalone.uploadRelease.darwin64.cleanup", () => { - return gulp.src(dmgPath, { read: false, allowEmpty: true }).pipe($.clean({ force: true })); - }); - - gulp.task("standalone.uploadRelease.darwin64.compress", cb => { - console.log("Packaging disk image", dmgPath); - execSync(`hdiutil create -format UDBZ -srcfolder ${darwinApp} ${dmgPath}`); - cb(); - }); - - gulp.task("standalone.uploadRelease.darwin64.upload", async cb => { - const currentTag = buildutils.getTag(); - - const octokit = new Octokit({ - auth: process.env.SHAPEZ_CLI_GITHUB_TOKEN - }); - - const createdRelease = await octokit.request("POST /repos/{owner}/{repo}/releases", { - owner: process.env.SHAPEZ_CLI_GITHUB_USER, - repo: "shapez.io", - tag_name: currentTag, - name: currentTag, - draft: true - }); - - const { data: { id, upload_url } } = createdRelease; - console.log(`Created release ${id} for tag ${currentTag}`); - - const dmgContents = fs.readFileSync(dmgPath); - const dmgSize = fs.statSync(dmgPath).size; - console.log("Uploading", dmgContents.length / 1024 / 1024, "MB to", upload_url); - - await octokit.request({ - method: "POST", - url: upload_url, - headers: { - "content-type": "application/x-apple-diskimage" - }, - name: dmgName, - data: dmgContents - }); - - cb(); - }); - - gulp.task("standalone.uploadRelease.darwin64", - gulp.series( - "standalone.uploadRelease.darwin64.cleanup", - "standalone.uploadRelease.darwin64.compress", - "standalone.uploadRelease.darwin64.upload" - )); -} - -module.exports = { gulptasksReleaseUploader }; diff --git a/gulp/standalone.js b/gulp/standalone.js index ecd393a2..0d4f06c7 100644 --- a/gulp/standalone.js +++ b/gulp/standalone.js @@ -8,6 +8,7 @@ const fse = require("fs-extra"); const buildutils = require("./buildutils"); const execSync = require("child_process").execSync; const electronNotarize = require("electron-notarize"); +const { BUILD_VARIANTS } = require("./build_variants"); let signAsync; try { @@ -17,56 +18,32 @@ try { } function gulptasksStandalone($, gulp) { - const targets = [ - { - tempDestDir: path.join(__dirname, "..", "tmp_standalone_files"), - suffix: "", - taskPrefix: "", - electronBaseDir: path.join(__dirname, "..", "electron"), - steam: true, - }, - { - tempDestDir: path.join(__dirname, "..", "tmp_standalone_files_china"), - suffix: "china", - taskPrefix: "china.", - electronBaseDir: path.join(__dirname, "..", "electron"), - steam: true, - }, - { - tempDestDir: path.join(__dirname, "..", "tmp_standalone_files_wegame"), - suffix: "wegame", - taskPrefix: "wegame.", - electronBaseDir: path.join(__dirname, "..", "electron_wegame"), - steam: false, - }, - ]; - - for (const { tempDestDir, suffix, taskPrefix, electronBaseDir, steam } of targets) { + for (const variant in BUILD_VARIANTS) { + const variantData = BUILD_VARIANTS[variant]; + if (!variantData.standalone) { + continue; + } + const tempDestDir = path.join(__dirname, "..", "build_output", variant); + const taskPrefix = "standalone." + variant; + const electronBaseDir = path.join(__dirname, "..", variantData.electronBaseDir || "electron"); const tempDestBuildDir = path.join(tempDestDir, "built"); - gulp.task(taskPrefix + "standalone.prepare.cleanup", () => { + gulp.task(taskPrefix + ".prepare.cleanup", () => { return gulp.src(tempDestDir, { read: false, allowEmpty: true }).pipe($.clean({ force: true })); }); - gulp.task(taskPrefix + "standalone.prepare.copyPrefab", () => { + gulp.task(taskPrefix + ".prepare.copyPrefab", () => { const requiredFiles = [ path.join(electronBaseDir, "node_modules", "**", "*.*"), path.join(electronBaseDir, "node_modules", "**", ".*"), path.join(electronBaseDir, "wegame_sdk", "**", "*.*"), path.join(electronBaseDir, "wegame_sdk", "**", ".*"), path.join(electronBaseDir, "favicon*"), - - // fails on platforms which support symlinks - // https://github.com/gulpjs/gulp/issues/1427 - // path.join(electronBaseDir, "node_modules", "**", "*"), ]; - if (steam) { - requiredFiles.push(path.join(electronBaseDir, "steam_appid.txt")); - } return gulp.src(requiredFiles, { base: electronBaseDir }).pipe(gulp.dest(tempDestBuildDir)); }); - gulp.task(taskPrefix + "standalone.prepare.writePackageJson", cb => { + gulp.task(taskPrefix + ".prepare.writePackageJson", cb => { const packageJsonString = JSON.stringify( { scripts: { @@ -85,52 +62,15 @@ function gulptasksStandalone($, gulp) { cb(); }); - gulp.task(taskPrefix + "standalone.prepareVDF", cb => { - if (!steam) { - cb(); - return; - } - - const hash = buildutils.getRevision(); - - const steampipeDir = path.join(__dirname, "steampipe", "scripts"); - const templateContents = fs - .readFileSync(path.join(steampipeDir, "app.vdf.template"), { encoding: "utf-8" }) - .toString(); - - const convertedContents = templateContents.replace("$DESC$", "Commit " + hash); - fs.writeFileSync(path.join(steampipeDir, "app.vdf"), convertedContents); - - cb(); - }); - - gulp.task(taskPrefix + "standalone.prepareVDF.darwin", cb => { - if (!steam) { - cb(); - return; - } - - const hash = buildutils.getRevision(); - const steampipeDir = path.join(__dirname, "steampipe-darwin", "scripts"); - const templateContents = fs - .readFileSync(path.join(steampipeDir, "app.vdf.template"), { encoding: "utf-8" }) - .toString(); - - const convertedContents = templateContents.replace("$DESC$", "Commit " + hash); - fs.writeFileSync(path.join(steampipeDir, "app.vdf"), convertedContents); - - cb(); - }); - - gulp.task(taskPrefix + "standalone.prepare.minifyCode", () => { + gulp.task(taskPrefix + ".prepare.minifyCode", () => { return gulp.src(path.join(electronBaseDir, "*.js")).pipe(gulp.dest(tempDestBuildDir)); }); - gulp.task(taskPrefix + "standalone.prepare.copyGamefiles", () => { + gulp.task(taskPrefix + ".prepare.copyGamefiles", () => { return gulp.src("../build/**/*.*", { base: "../build" }).pipe(gulp.dest(tempDestBuildDir)); }); - gulp.task(taskPrefix + "standalone.killRunningInstances", cb => { + gulp.task(taskPrefix + ".killRunningInstances", cb => { try { execSync("taskkill /F /IM shapezio.exe"); } catch (ex) { @@ -140,14 +80,14 @@ function gulptasksStandalone($, gulp) { }); gulp.task( - taskPrefix + "standalone.prepare", + taskPrefix + ".prepare", gulp.series( - taskPrefix + "standalone.killRunningInstances", - taskPrefix + "standalone.prepare.cleanup", - taskPrefix + "standalone.prepare.copyPrefab", - taskPrefix + "standalone.prepare.writePackageJson", - taskPrefix + "standalone.prepare.minifyCode", - taskPrefix + "standalone.prepare.copyGamefiles" + taskPrefix + ".killRunningInstances", + taskPrefix + ".prepare.cleanup", + taskPrefix + ".prepare.copyPrefab", + taskPrefix + ".prepare.writePackageJson", + taskPrefix + ".prepare.minifyCode", + taskPrefix + ".prepare.copyGamefiles" ) ); @@ -158,11 +98,13 @@ function gulptasksStandalone($, gulp) { * @param {function():void} cb */ function packageStandalone(platform, arch, cb, isRelease = true) { - const tomlFile = fs.readFileSync(path.join(__dirname, ".itch.toml")); const privateArtifactsPath = "node_modules/shapez.io-private-artifacts"; - let asar = steam; - if (steam && fs.existsSync(path.join(tempDestBuildDir, privateArtifactsPath))) { + // Only use asar on steam builds (not supported by wegame) + let asar = Boolean(variantData.steamAppId); + + // Unpack private artifacts though + if (asar && fs.existsSync(path.join(tempDestBuildDir, privateArtifactsPath))) { // @ts-expect-error asar = { unpackDir: privateArtifactsPath }; } @@ -177,10 +119,10 @@ function gulptasksStandalone($, gulp) { asar: asar, executableName: "shapezio", icon: path.join(electronBaseDir, "favicon"), - name: "shapez.io-standalone" + suffix, + name: "shapez-" + variant, out: tempDestDir, overwrite: true, - appBundleId: "tobspr.shapezio.standalone", + appBundleId: "tobspr.shapezio." + variant, appCategoryType: "public.app-category.games", ...(isRelease && platform === "darwin" && { @@ -189,6 +131,7 @@ function gulptasksStandalone($, gulp) { "hardenedRuntime": true, "entitlements": "entitlements.plist", "entitlements-inherit": "entitlements.plist", + // @ts-ignore "signatureFlags": ["library"], "version": "16.0.7", }, @@ -202,43 +145,42 @@ function gulptasksStandalone($, gulp) { console.log("Packages created:", appPaths); appPaths.forEach(appPath => { if (!fs.existsSync(appPath)) { - console.error("Bad app path gotten:", appPath); + console.error("Bad app path:", appPath); return; } - if (steam) { + if (variantData.steamAppId) { fs.writeFileSync( path.join(appPath, "LICENSE"), fs.readFileSync(path.join(__dirname, "..", "LICENSE")) ); - fse.copySync( - path.join(tempDestBuildDir, "steam_appid.txt"), - path.join(appPath, "steam_appid.txt") + fs.writeFileSync( + path.join(appPath, "steam_appid.txt"), + String(variantData.steamAppId) ); - fs.writeFileSync(path.join(appPath, ".itch.toml"), tomlFile); - if (platform === "linux") { + // Write launcher script fs.writeFileSync( path.join(appPath, "play.sh"), '#!/usr/bin/env bash\n./shapezio --no-sandbox "$@"\n' ); fs.chmodSync(path.join(appPath, "play.sh"), 0o775); } + if (platform === "darwin") { if (!isRelease) { - fse.copySync( - path.join(tempDestBuildDir, "steam_appid.txt"), + // Needs special location + fs.writeFileSync( path.join( - path.join( - appPath, - "shapez.io-standalone.app", - "Contents", - "MacOS" - ), + appPath, + "shapez.io-standalone.app", + "Contents", + "MacOS", "steam_appid.txt" - ) + ), + String(variantData.steamAppId) ); } } @@ -255,7 +197,7 @@ function gulptasksStandalone($, gulp) { } // Manual signing with patched @electron/osx-sign (we need --no-strict) - gulp.task(taskPrefix + "standalone.package.prod.darwin64.signManually", cb => + gulp.task(taskPrefix + ".package.darwin64", cb => packageStandalone( "darwin", "x64", @@ -327,29 +269,44 @@ function gulptasksStandalone($, gulp) { ) ); - gulp.task(taskPrefix + "standalone.package.prod.win64", cb => packageStandalone("win32", "x64", cb)); - gulp.task(taskPrefix + "standalone.package.prod.linux64", cb => - packageStandalone("linux", "x64", cb) - ); - gulp.task(taskPrefix + "standalone.package.prod.darwin64", cb => - packageStandalone("darwin", "x64", cb) - ); - gulp.task(taskPrefix + "standalone.package.prod.darwin64.unsigned", cb => - packageStandalone("darwin", "x64", cb, false) - ); - + gulp.task(taskPrefix + ".package.win64", cb => packageStandalone("win32", "x64", cb)); + gulp.task(taskPrefix + ".package.linux64", cb => packageStandalone("linux", "x64", cb)); gulp.task( - taskPrefix + "standalone.package.prod", + taskPrefix + ".build-from-windows", gulp.series( - taskPrefix + "standalone.prepare", - gulp.parallel( - taskPrefix + "standalone.package.prod.win64", - taskPrefix + "standalone.package.prod.linux64", - taskPrefix + "standalone.package.prod.darwin64" - ) + taskPrefix + ".prepare", + gulp.parallel(taskPrefix + ".package.win64", taskPrefix + ".package.linux64") ) ); + gulp.task( + taskPrefix + ".build-from-darwin", + gulp.series(taskPrefix + ".prepare", gulp.parallel(taskPrefix + ".package.darwin64")) + ); } + + // Steam helpers + gulp.task("standalone.prepareVDF", cb => { + const hash = buildutils.getRevision(); + const version = buildutils.getVersion(); + + for (const platform of ["steampipe", "steampipe-darwin"]) { + const steampipeDir = path.join(__dirname, platform, "scripts"); + for (const buildVariant of ["app", "app-demo"]) { + const templateContents = fs + .readFileSync(path.join(steampipeDir, buildVariant + ".vdf.template"), { + encoding: "utf-8", + }) + .toString(); + + const convertedContents = templateContents.replace( + "$DESC$", + platform + " " + buildVariant + " version " + version + ", commit " + hash + ); + fs.writeFileSync(path.join(steampipeDir, buildVariant + ".vdf"), convertedContents); + } + } + cb(); + }); } module.exports = { gulptasksStandalone }; diff --git a/gulp/steampipe-darwin/scripts/app-demo.vdf.template b/gulp/steampipe-darwin/scripts/app-demo.vdf.template new file mode 100644 index 00000000..699288d2 --- /dev/null +++ b/gulp/steampipe-darwin/scripts/app-demo.vdf.template @@ -0,0 +1,14 @@ +"appbuild" +{ + "appid" "1930750" + "desc" "$DESC$" + "buildoutput" "$STEAMPIPE_DIR$/steamtmp" + "contentroot" "" + "setlive" "" + "preview" "0" + "local" "" + "depots" + { + "1930756" "$STEAMPIPE_DIR$/scripts/demo-darwin.vdf" + } +} diff --git a/gulp/steampipe-darwin/scripts/app.vdf.template b/gulp/steampipe-darwin/scripts/app.vdf.template index 18ad3457..74a31abe 100644 --- a/gulp/steampipe-darwin/scripts/app.vdf.template +++ b/gulp/steampipe-darwin/scripts/app.vdf.template @@ -2,13 +2,13 @@ { "appid" "1318690" "desc" "$DESC$" - "buildoutput" "/Users/tobiasspringer/work/shapez.io/gulp/steampipe-darwin/steamtmp" + "buildoutput" "$PROJECT_DIR$/gulp/steampipe-darwin/steamtmp" "contentroot" "" "setlive" "" "preview" "0" "local" "" "depots" { - "1318693" "/Users/tobiasspringer/work/shapez.io/gulp/steampipe-darwin/scripts/darwin.vdf" + "1318693" "$PROJECT_DIR$/gulp/steampipe-darwin/scripts/darwin.vdf" } } diff --git a/gulp/steampipe-darwin/scripts/darwin.vdf b/gulp/steampipe-darwin/scripts/darwin.vdf index d92014dc..fe52d8e9 100644 --- a/gulp/steampipe-darwin/scripts/darwin.vdf +++ b/gulp/steampipe-darwin/scripts/darwin.vdf @@ -1,7 +1,7 @@ "DepotBuildConfig" { "DepotID" "1318693" - "contentroot" "/Users/tobiasspringer/work/shapez.io/tmp_standalone_files/shapez.io-standalone-darwin-x64" + "contentroot" "$PROJECT_DIR$/tmp_standalone_files/shapez.io-standalone-darwin-x64" "FileMapping" { "LocalPath" "*" diff --git a/gulp/steampipe-darwin/scripts/demo-darwin.vdf b/gulp/steampipe-darwin/scripts/demo-darwin.vdf new file mode 100644 index 00000000..b6597586 --- /dev/null +++ b/gulp/steampipe-darwin/scripts/demo-darwin.vdf @@ -0,0 +1,12 @@ +"DepotBuildConfig" +{ + "DepotID" "1930756" + "contentroot" "$PROJECT_DIR$/tmp_standalone_files/shapez.io-demo-darwin-x64" + "FileMapping" + { + "LocalPath" "*" + "DepotPath" "." + "recursive" "1" + } + "FileExclusion" "*.pdb" +} \ No newline at end of file diff --git a/gulp/steampipe-darwin/upload.sh b/gulp/steampipe-darwin/upload.sh index f5afd921..551f16bb 100755 --- a/gulp/steampipe-darwin/upload.sh +++ b/gulp/steampipe-darwin/upload.sh @@ -1,3 +1,3 @@ #!/bin/sh -yarn gulp standalone.prepareVDF.darwin +yarn gulp standalone.prepareVDF steamcmd.sh +login $STEAM_UPLOAD_SHAPEZ_ID $STEAM_UPLOAD_SHAPEZ_USER +run_app_build $PWD/scripts/app.vdf +quit diff --git a/gulp/steampipe/scripts/app-demo.vdf.template b/gulp/steampipe/scripts/app-demo.vdf.template new file mode 100644 index 00000000..3e874fbf --- /dev/null +++ b/gulp/steampipe/scripts/app-demo.vdf.template @@ -0,0 +1,17 @@ +"appbuild" +{ + "appid" "1930750" + "desc" "$DESC$" + "buildoutput" "$STEAMPIPE_DIR$\steamtemp" + "contentroot" "" + "setlive" "" + "preview" "0" + "local" "" + "depots" + { + "1930753" "$STEAMPIPE_DIR$\scripts\demo-windows.vdf" + "1930754" "$STEAMPIPE_DIR$\scripts\demo-china-windows.vdf" + "1930752" "$STEAMPIPE_DIR$\scripts\demo-linux.vdf" + "1930755" "$STEAMPIPE_DIR$\scripts\demo-china-linux.vdf" + } +} diff --git a/gulp/steampipe/scripts/app.vdf.template b/gulp/steampipe/scripts/app.vdf.template index 5359acfe..15f9d3ed 100644 --- a/gulp/steampipe/scripts/app.vdf.template +++ b/gulp/steampipe/scripts/app.vdf.template @@ -2,16 +2,16 @@ { "appid" "1318690" "desc" "$DESC$" - "buildoutput" "C:\work\shapez\shapez.io\gulp\steampipe\steamtemp" + "buildoutput" "$STEAMPIPE_DIR$\steamtemp" "contentroot" "" "setlive" "" "preview" "0" "local" "" "depots" { - "1318691" "C:\work\shapez\shapez.io\gulp\steampipe\scripts\windows.vdf" - "1318694" "C:\work\shapez\shapez.io\gulp\steampipe\scripts\china-windows.vdf" - "1318692" "C:\work\shapez\shapez.io\gulp\steampipe\scripts\linux.vdf" - "1318695" "C:\work\shapez\shapez.io\gulp\steampipe\scripts\china-linux.vdf" + "1318691" "$STEAMPIPE_DIR$\scripts\windows.vdf" + "1318694" "$STEAMPIPE_DIR$\scripts\china-windows.vdf" + "1318692" "$STEAMPIPE_DIR$\scripts\linux.vdf" + "1318695" "$STEAMPIPE_DIR$\scripts\china-linux.vdf" } } diff --git a/gulp/steampipe/scripts/china-linux.vdf b/gulp/steampipe/scripts/china-linux.vdf index 3906312b..a68cb592 100644 --- a/gulp/steampipe/scripts/china-linux.vdf +++ b/gulp/steampipe/scripts/china-linux.vdf @@ -1,7 +1,7 @@ "DepotBuildConfig" { "DepotID" "1318695" - "contentroot" "C:\work\shapez\shapez.io\tmp_standalone_files_china\shapez.io-standalonechina-linux-x64" + "contentroot" "$PROJECT_DIR$\tmp_standalone_files_china\shapez.io-standalonechina-linux-x64" "FileMapping" { "LocalPath" "*" diff --git a/gulp/steampipe/scripts/china-windows.vdf b/gulp/steampipe/scripts/china-windows.vdf index 3a098cbc..27cee261 100644 --- a/gulp/steampipe/scripts/china-windows.vdf +++ b/gulp/steampipe/scripts/china-windows.vdf @@ -1,7 +1,7 @@ "DepotBuildConfig" { "DepotID" "1318694" - "contentroot" "C:\work\shapez\shapez.io\tmp_standalone_files_china\shapez.io-standalonechina-win32-x64" + "contentroot" "$PROJECT_DIR$\shapez.io-standalonechina-win32-x64" "FileMapping" { "LocalPath" "*" diff --git a/gulp/steampipe/scripts/demo-china-linux.vdf b/gulp/steampipe/scripts/demo-china-linux.vdf new file mode 100644 index 00000000..b38d16d6 --- /dev/null +++ b/gulp/steampipe/scripts/demo-china-linux.vdf @@ -0,0 +1,12 @@ +"DepotBuildConfig" +{ + "DepotID" "1930755" + "contentroot" "$PROJECT_DIR$\tmp_standalone_files_china\shapez.io-demochina-linux-x64" + "FileMapping" + { + "LocalPath" "*" + "DepotPath" "." + "recursive" "1" + } + "FileExclusion" "*.pdb" +} \ No newline at end of file diff --git a/gulp/steampipe/scripts/demo-china-windows.vdf b/gulp/steampipe/scripts/demo-china-windows.vdf new file mode 100644 index 00000000..a41e9461 --- /dev/null +++ b/gulp/steampipe/scripts/demo-china-windows.vdf @@ -0,0 +1,12 @@ +"DepotBuildConfig" +{ + "DepotID" "1930754" + "contentroot" "$PROJECT_DIR$\tmp_standalone_files_china\shapez.io-demochina-win32-x64" + "FileMapping" + { + "LocalPath" "*" + "DepotPath" "." + "recursive" "1" + } + "FileExclusion" "*.pdb" +} \ No newline at end of file diff --git a/gulp/steampipe/scripts/demo-linux.vdf b/gulp/steampipe/scripts/demo-linux.vdf new file mode 100644 index 00000000..eabd9115 --- /dev/null +++ b/gulp/steampipe/scripts/demo-linux.vdf @@ -0,0 +1,12 @@ +"DepotBuildConfig" +{ + "DepotID" "1930752" + "contentroot" "$PROJECT_DIR$\tmp_standalone_files\shapez.io-demo-linux-x64" + "FileMapping" + { + "LocalPath" "*" + "DepotPath" "." + "recursive" "1" + } + "FileExclusion" "*.pdb" +} \ No newline at end of file diff --git a/gulp/steampipe/scripts/demo-windows.vdf b/gulp/steampipe/scripts/demo-windows.vdf new file mode 100644 index 00000000..a551e51f --- /dev/null +++ b/gulp/steampipe/scripts/demo-windows.vdf @@ -0,0 +1,12 @@ +"DepotBuildConfig" +{ + "DepotID" "1930753" + "contentroot" "$PROJECT_DIR$\tmp_standalone_files\shapez.io-demo-win32-x64" + "FileMapping" + { + "LocalPath" "*" + "DepotPath" "." + "recursive" "1" + } + "FileExclusion" "*.pdb" +} \ No newline at end of file diff --git a/gulp/steampipe/scripts/linux.vdf b/gulp/steampipe/scripts/linux.vdf index 60dfcca5..cc04785b 100644 --- a/gulp/steampipe/scripts/linux.vdf +++ b/gulp/steampipe/scripts/linux.vdf @@ -1,7 +1,7 @@ "DepotBuildConfig" { "DepotID" "1318692" - "contentroot" "C:\work\shapez\shapez.io\tmp_standalone_files\shapez.io-standalone-linux-x64" + "contentroot" "$PROJECT_DIR$\tmp_standalone_files\shapez.io-standalone-linux-x64" "FileMapping" { "LocalPath" "*" diff --git a/gulp/steampipe/scripts/windows.vdf b/gulp/steampipe/scripts/windows.vdf index 7d0db436..e01ebbac 100644 --- a/gulp/steampipe/scripts/windows.vdf +++ b/gulp/steampipe/scripts/windows.vdf @@ -1,7 +1,7 @@ "DepotBuildConfig" { "DepotID" "1318691" - "contentroot" "C:\work\shapez\shapez.io\tmp_standalone_files\shapez.io-standalone-win32-x64" + "contentroot" "$PROJECT_DIR$\tmp_standalone_files\shapez.io-standalone-win32-x64" "FileMapping" { "LocalPath" "*" diff --git a/gulp/steampipe/upload-demo.bat b/gulp/steampipe/upload-demo.bat new file mode 100644 index 00000000..0e01dbef --- /dev/null +++ b/gulp/steampipe/upload-demo.bat @@ -0,0 +1,3 @@ +@echo off +cmd /c yarn gulp standalone.prepareVDF +steamcmd +login %STEAM_UPLOAD_SHAPEZ_ID% %STEAM_UPLOAD_SHAPEZ_USER% +run_app_build %cd%/scripts/app-demo.vdf +quit \ No newline at end of file diff --git a/gulp/steampipe/upload.bat b/gulp/steampipe/upload.bat index 86dcf926..00153ebd 100644 --- a/gulp/steampipe/upload.bat +++ b/gulp/steampipe/upload.bat @@ -1,4 +1,3 @@ @echo off cmd /c yarn gulp standalone.prepareVDF steamcmd +login %STEAM_UPLOAD_SHAPEZ_ID% %STEAM_UPLOAD_SHAPEZ_USER% +run_app_build %cd%/scripts/app.vdf +quit -start https://partner.steamgames.com/apps/builds/1318690 diff --git a/gulp/webpack.config.js b/gulp/webpack.config.js index 3c07d7cc..f1f4b2c0 100644 --- a/gulp/webpack.config.js +++ b/gulp/webpack.config.js @@ -3,10 +3,15 @@ const path = require("path"); const webpack = require("webpack"); const { getRevision, getVersion, getAllResourceImages } = require("./buildutils"); -const lzString = require("lz-string"); const CircularDependencyPlugin = require("circular-dependency-plugin"); -module.exports = ({ watch = false, standalone = false, chineseVersion = false, wegameVersion = false }) => { +module.exports = ({ + watch = false, + standalone = false, + chineseVersion = false, + wegameVersion = false, + steamDemo = false, +}) => { return { mode: "development", devtool: "cheap-source-map", @@ -31,16 +36,13 @@ module.exports = ({ watch = false, standalone = false, chineseVersion = false, w "window.assert(false, 'abstract method called of: ' + (this.name || (this.constructor && this.constructor.name)));", G_HAVE_ASSERT: "true", G_APP_ENVIRONMENT: JSON.stringify("dev"), - G_TRACKING_ENDPOINT: JSON.stringify( - lzString.compressToEncodedURIComponent("http://localhost:10005/v1") - ), G_CHINA_VERSION: JSON.stringify(chineseVersion), G_WEGAME_VERSION: JSON.stringify(wegameVersion), G_IS_DEV: "true", G_IS_RELEASE: "false", - G_IS_MOBILE_APP: "false", G_IS_BROWSER: "true", - G_IS_STANDALONE: standalone ? "true" : "false", + G_IS_STANDALONE: JSON.stringify(standalone), + G_IS_STEAM_DEMO: JSON.stringify(steamDemo), G_BUILD_TIME: "" + new Date().getTime(), G_BUILD_COMMIT_HASH: JSON.stringify(getRevision()), G_BUILD_VERSION: JSON.stringify(getVersion()), diff --git a/gulp/webpack.production.config.js b/gulp/webpack.production.config.js index f56ae609..fa483aba 100644 --- a/gulp/webpack.production.config.js +++ b/gulp/webpack.production.config.js @@ -3,24 +3,24 @@ const path = require("path"); const webpack = require("webpack"); const { getRevision, getVersion, getAllResourceImages } = require("./buildutils"); -const lzString = require("lz-string"); const TerserPlugin = require("terser-webpack-plugin"); const StringReplacePlugin = require("string-replace-webpack-plugin"); const UnusedFilesPlugin = require("unused-files-webpack-plugin").UnusedFilesWebpackPlugin; module.exports = ({ - enableAssert = false, environment, es6 = false, + standalone = false, isBrowser = true, - mobileApp = false, + chineseVersion = false, wegameVersion = false, + steamDemo = false, }) => { const globalDefs = { - assert: enableAssert ? "window.assert" : "false && window.assert", + assert: "false && window.assert", assertAlways: "window.assert", abstract: "window.assert(false, 'abstract method called');", G_IS_DEV: "false", @@ -29,13 +29,10 @@ module.exports = ({ G_WEGAME_VERSION: JSON.stringify(wegameVersion), G_IS_RELEASE: environment === "prod" ? "true" : "false", G_IS_STANDALONE: standalone ? "true" : "false", + G_IS_STEAM_DEMO: JSON.stringify(steamDemo), G_IS_BROWSER: isBrowser ? "true" : "false", - G_IS_MOBILE_APP: mobileApp ? "true" : "false", - G_TRACKING_ENDPOINT: JSON.stringify( - lzString.compressToEncodedURIComponent("https://tracking.shapez.io/v1") - ), G_APP_ENVIRONMENT: JSON.stringify(environment), - G_HAVE_ASSERT: enableAssert ? "true" : "false", + G_HAVE_ASSERT: "false", G_BUILD_TIME: "" + new Date().getTime(), G_BUILD_COMMIT_HASH: JSON.stringify(getRevision()), G_BUILD_VERSION: JSON.stringify(getVersion()), diff --git a/res/ui/memes/cat1.png b/res/ui/memes/cat1.png index 114c3fa0..7ec97051 100644 Binary files a/res/ui/memes/cat1.png and b/res/ui/memes/cat1.png differ diff --git a/src/css/ingame_hud/standalone_advantages.scss b/src/css/ingame_hud/standalone_advantages.scss index 8ab7147c..0357ffeb 100644 --- a/src/css/ingame_hud/standalone_advantages.scss +++ b/src/css/ingame_hud/standalone_advantages.scss @@ -52,6 +52,11 @@ } } + .playtimeDisclaimer { + @include S(margin-bottom, 10px); + @include PlainText; + } + .steamLinkButton { @include IncreasedClickArea(5px); @include S(margin, 0); diff --git a/src/css/ingame_hud/cat_memes.scss b/src/css/ingame_hud/steam_capsule.scss similarity index 50% rename from src/css/ingame_hud/cat_memes.scss rename to src/css/ingame_hud/steam_capsule.scss index ddb0ae3f..6a71fc07 100644 --- a/src/css/ingame_hud/cat_memes.scss +++ b/src/css/ingame_hud/steam_capsule.scss @@ -1,10 +1,16 @@ -#ingame_HUD_CatMemes { +#ingame_HUD_SteamCapsule { position: absolute; @include S(width, 150px); - @include S(height, 150px); - background: transparent center center / contain no-repeat; + @include S(height, 119px); + background: transparent center center / cover no-repeat; - right: 0; + pointer-events: all; + overflow: hidden; + @include S(right, 10px); + + border: D(2px) solid #000; + @include S(border-radius, $globalBorderRadius); + cursor: pointer; @include S(bottom, 150px); & { @@ -12,6 +18,10 @@ background-image: uiResource("res/ui/memes/cat1.png") !important; } + &:hover { + opacity: 0.95; + } + @include InlineAnimation(0.5s ease-in-out) { 0% { transform: translateX(100%); diff --git a/src/css/main.scss b/src/css/main.scss index 764347ac..79319ea3 100644 --- a/src/css/main.scss +++ b/src/css/main.scss @@ -57,7 +57,7 @@ @import "ingame_hud/shape_viewer"; @import "ingame_hud/sandbox_controller"; @import "ingame_hud/standalone_advantages"; -@import "ingame_hud/cat_memes"; +@import "ingame_hud/steam_capsule"; @import "ingame_hud/puzzle_back_to_menu"; @import "ingame_hud/puzzle_editor_review"; @import "ingame_hud/puzzle_dlc_logo"; @@ -105,6 +105,7 @@ ingame_HUD_Waypoints_Hint, ingame_HUD_WatermarkClicker, ingame_HUD_Watermark, ingame_HUD_ColorBlindBelowTileHelper, +ingame_HUD_SteamCapsule, ingame_HUD_SandboxController, // Overlays @@ -118,8 +119,7 @@ ingame_HUD_StandaloneAdvantages, ingame_HUD_UnlockNotification, ingame_HUD_PuzzleCompleteNotification, ingame_HUD_SettingsMenu, -ingame_HUD_ModalDialogs, -ingame_HUD_CatMemes; +ingame_HUD_ModalDialogs; $zindex: 100; @@ -132,7 +132,7 @@ $zindex: 100; } body.uiHidden { - > div { + > div:not(.ingameDialog):not(#ingame_HUD_SettingsMenu):not(#ingame_HUD_ModalDialogs):not(#ingame_HUD_UnlockNotification):not(#ingame_HUD_PuzzleCompleteNotification) { display: none !important; } } diff --git a/src/css/states/main_menu.scss b/src/css/states/main_menu.scss index a6b1a379..41942d53 100644 --- a/src/css/states/main_menu.scss +++ b/src/css/states/main_menu.scss @@ -97,7 +97,7 @@ } .standaloneBanner { - background: rgb(216, 79, 76); + background: rgba(12, 168, 93, 0.957); @include S(border-radius, $globalBorderRadius); box-sizing: border-box; @include S(padding, 15px); @@ -129,8 +129,18 @@ @include S(padding-left, 20px); li { @include Text; + color: #fff; } } + strong { + margin: 0; + } + + .playtimeDisclaimer { + color: #fff; + @include S(margin-top, 15px); + @include SuperSmallText; + } .steamLink { align-self: center; @@ -153,6 +163,12 @@ opacity: 0.9; } + @include InlineAnimation(1s ease-in-out infinite) { + 50% { + transform: scale(1.02, 1.03); + } + } + > .discount { position: absolute; @include S(top, -7px); @@ -186,9 +202,8 @@ img { @include S(width, 300px); } - position: relative; - @include S(left, -22px); + @include S(left, -8px); .updateLabel { position: absolute; @@ -677,25 +692,19 @@ } .footer { - display: grid; + display: flex; flex-grow: 1; justify-content: center; align-items: flex-end; width: 100%; - grid-template-columns: auto auto auto 1fr; @include S(padding, 10px); box-sizing: border-box; @include S(grid-gap, 4px); - &.noLinks { - grid-template-columns: auto 1fr; - } - &.wegameDisclaimer { @include SuperSmallText; display: grid; justify-content: center; - grid-template-columns: 1fr auto 1fr; text-align: center; > .disclaimer { diff --git a/src/css/states/settings.scss b/src/css/states/settings.scss index 15187cda..81632b07 100644 --- a/src/css/states/settings.scss +++ b/src/css/states/settings.scss @@ -47,6 +47,10 @@ align-self: end; margin-top: auto; + &.noabout { + align-self: start; + } + @include StyleBelowWidth($layoutBreak) { margin-top: 0; display: grid; diff --git a/src/js/application.js b/src/js/application.js index 4f3a4c5f..70aa4e4b 100644 --- a/src/js/application.js +++ b/src/js/application.js @@ -41,7 +41,6 @@ import { ModsState } from "./states/mods"; /** * @typedef {import("./platform/achievement_provider").AchievementProviderInterface} AchievementProviderInterface - * @typedef {import("./platform/game_analytics").GameAnalyticsInterface} GameAnalyticsInterface * @typedef {import("./platform/sound").SoundInterface} SoundInterface * @typedef {import("./platform/storage").StorageInterface} StorageInterface */ @@ -118,7 +117,7 @@ export class Application { /** @type {AnalyticsInterface} */ this.analytics = null; - /** @type {GameAnalyticsInterface} */ + /** @type {ShapezGameAnalytics} */ this.gameAnalytics = null; this.initPlatformDependentInstances(); @@ -227,12 +226,10 @@ export class Application { window.addEventListener("resize", () => this.checkResize(), true); window.addEventListener("orientationchange", () => this.checkResize(), true); - if (!G_IS_MOBILE_APP && !IS_MOBILE) { - window.addEventListener("mousemove", this.handleMousemove.bind(this)); - window.addEventListener("mouseout", this.handleMousemove.bind(this)); - window.addEventListener("mouseover", this.handleMousemove.bind(this)); - window.addEventListener("mouseleave", this.handleMousemove.bind(this)); - } + window.addEventListener("mousemove", this.handleMousemove.bind(this)); + window.addEventListener("mouseout", this.handleMousemove.bind(this)); + window.addEventListener("mouseover", this.handleMousemove.bind(this)); + window.addEventListener("mouseleave", this.handleMousemove.bind(this)); // Unload events window.addEventListener("beforeunload", this.onBeforeUnload.bind(this), true); diff --git a/src/js/core/background_resources_loader.js b/src/js/core/background_resources_loader.js index 786a87de..e5fc2ca0 100644 --- a/src/js/core/background_resources_loader.js +++ b/src/js/core/background_resources_loader.js @@ -17,6 +17,10 @@ export function getLogoSprite() { return "logo_wegame.png"; } + if (G_IS_STEAM_DEMO) { + return "logo_demo.png"; + } + if (G_CHINA_VERSION) { return "logo_cn.png"; } diff --git a/src/js/core/config.js b/src/js/core/config.js index f02366f4..33560c12 100644 --- a/src/js/core/config.js +++ b/src/js/core/config.js @@ -117,13 +117,7 @@ export const globalConfig = { rendering: {}, debug: require("./config.local").default, - currentDiscount: { - amount: 50, - from: Date.parse("May 23 2022 17:00 +2:00"), - until: Date.parse("May 30 2022 23:59 +2:00"), - - active: false, // computed later - }, + currentDiscount: 0, // Secret vars info: { @@ -169,8 +163,3 @@ if (G_IS_DEV && globalConfig.debug.noArtificialDelays) { globalConfig.warmupTimeSecondsFast = 0; globalConfig.warmupTimeSecondsRegular = 0; } - -globalConfig.currentDiscount.active = - !G_IS_STANDALONE && - new Date().getTime() < globalConfig.currentDiscount.until && - new Date().getTime() > globalConfig.currentDiscount.from; diff --git a/src/js/core/globals.js b/src/js/core/globals.js index c47abfed..55238e85 100644 --- a/src/js/core/globals.js +++ b/src/js/core/globals.js @@ -19,12 +19,10 @@ export function setGlobalApp(app) { export const BUILD_OPTIONS = { HAVE_ASSERT: G_HAVE_ASSERT, APP_ENVIRONMENT: G_APP_ENVIRONMENT, - TRACKING_ENDPOINT: G_TRACKING_ENDPOINT, CHINA_VERSION: G_CHINA_VERSION, WEGAME_VERSION: G_WEGAME_VERSION, IS_DEV: G_IS_DEV, IS_RELEASE: G_IS_RELEASE, - IS_MOBILE_APP: G_IS_MOBILE_APP, IS_BROWSER: G_IS_BROWSER, IS_STANDALONE: G_IS_STANDALONE, BUILD_TIME: G_BUILD_TIME, diff --git a/src/js/core/restriction_manager.js b/src/js/core/restriction_manager.js index a17d6163..d775c06d 100644 --- a/src/js/core/restriction_manager.js +++ b/src/js/core/restriction_manager.js @@ -2,7 +2,6 @@ import { Application } from "../application"; /* typehints:end */ import { ExplainedResult } from "./explained_result"; -import { queryParamOptions } from "./query_parameters"; import { ReadWriteProxy } from "./read_write_proxy"; export class RestrictionManager extends ReadWriteProxy { @@ -56,13 +55,12 @@ export class RestrictionManager extends ReadWriteProxy { * @returns {boolean} */ isLimitedVersion() { - if (G_IS_STANDALONE) { - // Standalone is never limited - return false; + if (G_IS_STEAM_DEMO) { + return true; } - if (queryParamOptions.embedProvider === "gamedistribution") { - // also full version on gamedistribution + if (G_IS_STANDALONE) { + // Standalone is never limited return false; } diff --git a/src/js/core/utils.js b/src/js/core/utils.js index 35e70310..1f4bfa05 100644 --- a/src/js/core/utils.js +++ b/src/js/core/utils.js @@ -2,29 +2,6 @@ import { T } from "../translations"; const bigNumberSuffixTranslationKeys = ["thousands", "millions", "billions", "trillions"]; -/** - * Returns if this platform is android - * @returns {boolean} - */ -export function isAndroid() { - if (!G_IS_MOBILE_APP) { - return false; - } - const platform = window.device.platform; - return platform === "Android" || platform === "amazon-fireos"; -} - -/** - * Returns if this platform is iOs - * @returns {boolean} - */ -export function isIos() { - if (!G_IS_MOBILE_APP) { - return false; - } - return window.device.platform === "iOS"; -} - /** * Returns a platform name * @returns {"android" | "browser" | "ios" | "standalone" | "unknown"} @@ -34,10 +11,6 @@ export function getPlatformName() { return "standalone"; } else if (G_IS_BROWSER) { return "browser"; - } else if (G_IS_MOBILE_APP && isAndroid()) { - return "android"; - } else if (G_IS_MOBILE_APP && isIos()) { - return "ios"; } return "unknown"; } @@ -456,7 +429,7 @@ export function isSupportedBrowser() { // and if not iOS Chrome check // so use the below updated condition - if (G_IS_MOBILE_APP || G_IS_STANDALONE) { + if (G_IS_STANDALONE) { return true; } diff --git a/src/js/game/hud/parts/cat_memes.js b/src/js/game/hud/parts/cat_memes.js deleted file mode 100644 index f3af2be4..00000000 --- a/src/js/game/hud/parts/cat_memes.js +++ /dev/null @@ -1,21 +0,0 @@ -import { makeDiv } from "../../../core/utils"; -import { BaseHUDPart } from "../base_hud_part"; -import { DynamicDomAttach } from "../dynamic_dom_attach"; - -const memeShowIntervalSeconds = 70 * 60; -const memeShowDuration = 5; - -export class HUDCatMemes extends BaseHUDPart { - createElements(parent) { - this.element = makeDiv(parent, "ingame_HUD_CatMemes"); - } - - initialize() { - this.domAttach = new DynamicDomAttach(this.root, this.element); - } - - update() { - const now = this.root.time.realtimeNow(); - this.domAttach.update(now % memeShowIntervalSeconds > memeShowIntervalSeconds - memeShowDuration); - } -} diff --git a/src/js/game/hud/parts/modal_dialogs.js b/src/js/game/hud/parts/modal_dialogs.js index f86160bc..6ca611e9 100644 --- a/src/js/game/hud/parts/modal_dialogs.js +++ b/src/js/game/hud/parts/modal_dialogs.js @@ -125,7 +125,11 @@ export class HUDModalDialogs extends BaseHUDPart { dialog.buttonSignals.getStandalone.add(() => { this.app.analytics.trackUiClick("demo_dialog_click"); - window.open(THIRDPARTY_URLS.stanaloneCampaignLink + "/shapez_demo_dialog"); + window.open( + THIRDPARTY_URLS.stanaloneCampaignLink + + "/shapez_demo_dialog" + + (G_IS_STEAM_DEMO ? "_steamdemo" : "") + ); }); return dialog.buttonSignals; diff --git a/src/js/game/hud/parts/standalone_advantages.js b/src/js/game/hud/parts/standalone_advantages.js index ea4978a0..18218b34 100644 --- a/src/js/game/hud/parts/standalone_advantages.js +++ b/src/js/game/hud/parts/standalone_advantages.js @@ -5,8 +5,6 @@ import { T } from "../../../translations"; import { BaseHUDPart } from "../base_hud_part"; import { DynamicDomAttach } from "../dynamic_dom_attach"; -const showIntervalSeconds = 9 * 60; - export class HUDStandaloneAdvantages extends BaseHUDPart { createElements(parent) { this.background = makeDiv(parent, "ingame_HUD_StandaloneAdvantages", ["ingameDialog"]); @@ -33,10 +31,11 @@ export class HUDStandaloneAdvantages extends BaseHUDPart {
+
${T.demoBanners.playtimeDisclaimer}
@@ -46,13 +45,15 @@ export class HUDStandaloneAdvantages extends BaseHUDPart { ); this.trackClicks(this.contentDiv.querySelector("button.steamLinkButton"), () => { - const discount = globalConfig.currentDiscount.active - ? "_discount" + globalConfig.currentDiscount.amount - : ""; + const discount = + globalConfig.currentDiscount > 0 ? "_discount" + globalConfig.currentDiscount : ""; this.root.app.analytics.trackUiClick("standalone_advantage_visit_steam"); this.root.app.platformWrapper.openExternalLink( - THIRDPARTY_URLS.stanaloneCampaignLink + "/shapez_std_advg" + discount + THIRDPARTY_URLS.stanaloneCampaignLink + + "/shapez_std_advg" + + discount + + (G_IS_STEAM_DEMO ? "_steamdemo" : "") ); this.close(); }); @@ -62,6 +63,22 @@ export class HUDStandaloneAdvantages extends BaseHUDPart { }); } + get showIntervalSeconds() { + switch (this.root.app.gameAnalytics.abtVariant) { + case "0": + return 5 * 60; + case "1": + return 10 * 60; + case "2": + default: + return 15 * 60; + case "3": + return 20 * 60; + case "4": + return 1e14; + } + } + initialize() { this.domAttach = new DynamicDomAttach(this.root, this.background, { attachClass: "visible", @@ -86,7 +103,7 @@ export class HUDStandaloneAdvantages extends BaseHUDPart { } update() { - if (!this.visible && this.root.time.now() - this.lastShown > showIntervalSeconds) { + if (!this.visible && this.root.time.now() - this.lastShown > this.showIntervalSeconds) { this.show(); } diff --git a/src/js/game/hud/parts/steam_capsule.js b/src/js/game/hud/parts/steam_capsule.js new file mode 100644 index 00000000..ab82fcbe --- /dev/null +++ b/src/js/game/hud/parts/steam_capsule.js @@ -0,0 +1,31 @@ +import { globalConfig, THIRDPARTY_URLS } from "../../../core/config"; +import { makeDiv } from "../../../core/utils"; +import { BaseHUDPart } from "../base_hud_part"; +import { DynamicDomAttach } from "../dynamic_dom_attach"; + +const showCapsuleAfter = 30 * 60; + +export class HUDSteamCapsule extends BaseHUDPart { + createElements(parent) { + this.element = makeDiv(parent, "ingame_HUD_SteamCapsule"); + } + + initialize() { + const discount = globalConfig.currentDiscount > 0 ? "_discount" + globalConfig.currentDiscount : ""; + + this.domAttach = new DynamicDomAttach(this.root, this.element); + + this.trackClicks(this.element, () => { + this.root.app.platformWrapper.openExternalLink( + THIRDPARTY_URLS.stanaloneCampaignLink + + "/shapez_steamcapsule" + + discount + + (G_IS_STEAM_DEMO ? "_steamdemo" : "") + ); + }); + } + + update() { + this.domAttach.update(this.root.time.now() > showCapsuleAfter); + } +} diff --git a/src/js/game/hud/parts/unlock_notification.js b/src/js/game/hud/parts/unlock_notification.js index 98549784..6273e10e 100644 --- a/src/js/game/hud/parts/unlock_notification.js +++ b/src/js/game/hud/parts/unlock_notification.js @@ -75,7 +75,7 @@ export class HUDUnlockNotification extends BaseHUDPart {
${T.ingame.levelCompleteNotification.unlockText.replace("", rewardName)}
- +
${T.storyRewards[reward].desc}
@@ -131,6 +131,13 @@ export class HUDUnlockNotification extends BaseHUDPart { this.root.hud.signals.unlockNotificationFinished.dispatch(); + if ( + this.root.hubGoals.level === 7 && + this.root.app.restrictionMgr.getIsStandaloneMarketingActive() + ) { + this.root.hud.parts.standaloneAdvantages.show(); + } + if (!this.root.app.settings.getAllSettings().offerHints) { return; } diff --git a/src/js/game/hud/parts/watermark.js b/src/js/game/hud/parts/watermark.js index 053e886e..498a140f 100644 --- a/src/js/game/hud/parts/watermark.js +++ b/src/js/game/hud/parts/watermark.js @@ -2,66 +2,35 @@ import { globalConfig, THIRDPARTY_URLS } from "../../../core/config"; import { makeDiv } from "../../../core/utils"; import { T } from "../../../translations"; import { BaseHUDPart } from "../base_hud_part"; -import { DynamicDomAttach } from "../dynamic_dom_attach"; - -const watermarkShowIntervalSeconds = G_IS_DEV ? 120 : 7 * 60; -const watermarkShowDuration = 5; export class HUDWatermark extends BaseHUDPart { createElements(parent) { - this.element = makeDiv( - parent, - "ingame_HUD_Watermark", - [], - ` - ${T.ingame.watermark.title} -

${T.ingame.watermark.desc} -

- - - ` - ); - this.linkElement = makeDiv( parent, "ingame_HUD_WatermarkClicker", - globalConfig.currentDiscount.active ? ["withDiscount"] : [], + globalConfig.currentDiscount > 0 ? ["withDiscount"] : [], T.ingame.watermark.get_on_steam + - (globalConfig.currentDiscount.active - ? `${globalConfig.currentDiscount.amount}% off!` + (globalConfig.currentDiscount > 0 + ? `${globalConfig.currentDiscount}% off!` : "") ); this.trackClicks(this.linkElement, () => { this.root.app.analytics.trackUiClick("watermark_click_2_direct"); - const discount = globalConfig.currentDiscount.active - ? "_discount" + globalConfig.currentDiscount.amount - : ""; + const discount = + globalConfig.currentDiscount > 0 ? "_discount" + globalConfig.currentDiscount : ""; this.root.app.platformWrapper.openExternalLink( - THIRDPARTY_URLS.stanaloneCampaignLink + "/shapez_watermark" + discount + THIRDPARTY_URLS.stanaloneCampaignLink + + "/shapez_watermark" + + discount + + (G_IS_STEAM_DEMO ? "_steamdemo" : "") ); }); } - initialize() { - this.trackClicks(this.element, this.onWatermarkClick); + initialize() {} - this.domAttach = new DynamicDomAttach(this.root, this.element, { - attachClass: "visible", - timeToKeepSeconds: 0.5, - }); - } - - update() { - this.domAttach.update( - this.root.time.realtimeNow() % watermarkShowIntervalSeconds < watermarkShowDuration - ); - } - - onWatermarkClick() { - this.root.app.analytics.trackUiClick("watermark_click_2_new"); - this.root.hud.parts.standaloneAdvantages.show(); - } + update() {} /** * @@ -70,7 +39,7 @@ export class HUDWatermark extends BaseHUDPart { drawOverlays(parameters) { const w = this.root.gameWidth; - parameters.context.fillStyle = "rgba(230, 230, 230, 0.9)"; + parameters.context.fillStyle = "rgba(20, 30, 40, 0.25)"; parameters.context.font = "bold " + this.root.app.getEffectiveUiScale() * 40 + "px GameFont"; parameters.context.textAlign = "center"; parameters.context.fillText( diff --git a/src/js/game/modes/regular.js b/src/js/game/modes/regular.js index 68fbb3ad..022d2d16 100644 --- a/src/js/game/modes/regular.js +++ b/src/js/game/modes/regular.js @@ -31,11 +31,9 @@ import { IS_MOBILE } from "../../core/config"; import { HUDKeybindingOverlay } from "../hud/parts/keybinding_overlay"; import { HUDWatermark } from "../hud/parts/watermark"; import { HUDStandaloneAdvantages } from "../hud/parts/standalone_advantages"; -import { HUDCatMemes } from "../hud/parts/cat_memes"; +import { HUDSteamCapsule } from "../hud/parts/steam_capsule"; import { HUDPartTutorialHints } from "../hud/parts/tutorial_hints"; import { HUDInteractiveTutorial } from "../hud/parts/interactive_tutorial"; -import { HUDSandboxController } from "../hud/parts/sandbox_controller"; -import { queryParamOptions } from "../../core/query_parameters"; import { MetaBlockBuilding } from "../buildings/block"; import { MetaItemProducerBuilding } from "../buildings/item_producer"; import { MOD_SIGNALS } from "../../mods/mod_signals"; @@ -584,7 +582,7 @@ export class RegularGameMode extends GameMode { if (this.root.app.restrictionMgr.getIsStandaloneMarketingActive()) { this.additionalHudParts.watermark = HUDWatermark; this.additionalHudParts.standaloneAdvantages = HUDStandaloneAdvantages; - this.additionalHudParts.catMemes = HUDCatMemes; + this.additionalHudParts.catMemes = HUDSteamCapsule; } if (this.root.app.settings.getAllSettings().offerHints) { diff --git a/src/js/globals.d.ts b/src/js/globals.d.ts index f18d1d61..fcf1dbd5 100644 --- a/src/js/globals.d.ts +++ b/src/js/globals.d.ts @@ -10,11 +10,10 @@ declare const G_APP_ENVIRONMENT: string; declare const G_HAVE_ASSERT: boolean; declare const G_BUILD_TIME: number; declare const G_IS_STANDALONE: boolean; +declare const G_IS_STEAM_DEMO: boolean; declare const G_IS_BROWSER: boolean; -declare const G_IS_MOBILE_APP: boolean; declare const G_BUILD_COMMIT_HASH: string; -declare const G_TRACKING_ENDPOINT: string; declare const G_BUILD_VERSION: string; declare const G_ALL_UI_IMAGES: Array; declare const G_IS_RELEASE: boolean; diff --git a/src/js/mods/modloader.js b/src/js/mods/modloader.js index 3d0985d5..0e876aa4 100644 --- a/src/js/mods/modloader.js +++ b/src/js/mods/modloader.js @@ -105,6 +105,10 @@ export class ModLoader { } exposeExports() { + if (G_IS_STEAM_DEMO) { + return; + } + if (G_IS_DEV || G_IS_STANDALONE) { let exports = {}; const modules = require.context("../", true, /\.js$/); @@ -136,6 +140,11 @@ export class ModLoader { } async initMods() { + if (G_IS_STEAM_DEMO) { + this.initialized = true; + return; + } + if (!G_IS_STANDALONE && !G_IS_DEV) { this.initialized = true; return; diff --git a/src/js/platform/browser/game_analytics.js b/src/js/platform/browser/game_analytics.js index 22ce2def..6f5939d0 100644 --- a/src/js/platform/browser/game_analytics.js +++ b/src/js/platform/browser/game_analytics.js @@ -1,5 +1,6 @@ import { globalConfig } from "../../core/config"; import { createLogger } from "../../core/logging"; +import { randomInt } from "../../core/utils"; import { BeltComponent } from "../../game/components/belt"; import { StaticMapEntityComponent } from "../../game/components/static_map_entity"; import { RegularGameMode } from "../../game/modes/regular"; @@ -13,16 +14,26 @@ const logger = createLogger("game_analytics"); const analyticsUrl = G_IS_DEV ? "http://localhost:8001" : "https://analytics.shapez.io"; -// Be sure to increment the ID whenever it changes to make sure all -// users are tracked -const analyticsLocalFile = "shapez_token_123.bin"; +// Be sure to increment the ID whenever it changes +const analyticsLocalFile = G_IS_STEAM_DEMO ? "shapez_token_steamdemo.bin" : "shapez_token_123.bin"; + +const currentABT = "abt_sa_si"; export class ShapezGameAnalytics extends GameAnalyticsInterface { + constructor(app) { + super(app); + this.abtVariant = "0"; + } + get environment() { if (G_IS_DEV) { return "dev"; } + if (G_IS_STEAM_DEMO) { + return "steam-demo"; + } + if (G_IS_STANDALONE) { return "steam"; } @@ -38,6 +49,22 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface { } } + fetchABVariant() { + return this.app.storage.readFileAsync("shapez_" + currentABT + ".bin").then( + abt => { + this.abtVariant = abt; + logger.log("Got abtVariant:", abt); + }, + err => { + if (err === FILE_NOT_FOUND) { + this.abtVariant = String(randomInt(0, 4)); + logger.log("Determing abt variant to", this.abtVariant); + this.app.storage.writeFileAsync("shapez_" + currentABT + ".bin", this.abtVariant); + } + } + ); + } + /** * @returns {Promise} */ @@ -48,46 +75,68 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface { return; } - setInterval(() => this.sendTimePoints(), 60 * 1000); - // Retrieve sync key from player - return this.app.storage.readFileAsync(analyticsLocalFile).then( - syncKey => { - this.syncKey = syncKey; - logger.log("Player sync key read:", this.syncKey); - }, - error => { - // File was not found, retrieve new key - if (error === FILE_NOT_FOUND) { - logger.log("Retrieving new player key"); + return this.fetchABVariant().then(() => { + setInterval(() => this.sendTimePoints(), 60 * 1000); - // Perform call to get a new key from the API - this.sendToApi("/v1/register", { - environment: this.environment, - standalone: - G_IS_STANDALONE && - this.app.achievementProvider instanceof SteamAchievementProvider, - commit: G_BUILD_COMMIT_HASH, - }) - .then(res => { - // Try to read and parse the key from the api - if (res.key && typeof res.key === "string" && res.key.length === 40) { - this.syncKey = res.key; - logger.log("Key retrieved:", this.syncKey); - this.app.storage.writeFileAsync(analyticsLocalFile, res.key); - } else { - throw new Error("Bad response from analytics server: " + res); - } - }) - .catch(err => { - logger.error("Failed to register on analytics api:", err); - }); - } else { - logger.error("Failed to read ga key:", error); - } - return; + if (this.app.restrictionMgr.isLimitedVersion()) { + fetch( + analyticsUrl + + "/track/shapez_launch_" + + this.environment + + "_" + + currentABT + + "_" + + this.abtVariant, + { + method: "GET", + mode: "no-cors", + cache: "no-cache", + referrer: "no-referrer", + credentials: "omit", + } + ).catch(err => {}); } - ); + + return this.app.storage.readFileAsync(analyticsLocalFile).then( + syncKey => { + this.syncKey = syncKey; + logger.log("Player sync key read:", this.syncKey); + }, + error => { + // File was not found, retrieve new key + if (error === FILE_NOT_FOUND) { + logger.log("Retrieving new player key"); + + // Perform call to get a new key from the API + this.sendToApi("/v1/register", { + environment: this.environment, + standalone: + G_IS_STANDALONE && + !G_IS_STEAM_DEMO && + this.app.achievementProvider instanceof SteamAchievementProvider, + commit: G_BUILD_COMMIT_HASH, + }) + .then(res => { + // Try to read and parse the key from the api + if (res.key && typeof res.key === "string" && res.key.length === 40) { + this.syncKey = res.key; + logger.log("Key retrieved:", this.syncKey); + this.app.storage.writeFileAsync(analyticsLocalFile, res.key); + } else { + throw new Error("Bad response from analytics server: " + res); + } + }) + .catch(err => { + logger.error("Failed to register on analytics api:", err); + }); + } else { + logger.error("Failed to read ga key:", error); + } + return; + } + ); + }); } /** diff --git a/src/js/platform/browser/no_game_analytics.js b/src/js/platform/browser/no_game_analytics.js deleted file mode 100644 index 805e6fb1..00000000 --- a/src/js/platform/browser/no_game_analytics.js +++ /dev/null @@ -1,7 +0,0 @@ -import { GameAnalyticsInterface } from "../game_analytics"; - -export class NoGameAnalytics extends GameAnalyticsInterface { - initialize() { - return Promise.resolve(); - } -} diff --git a/src/js/profile/application_settings.js b/src/js/profile/application_settings.js index 03f4fdcf..2b7d4d63 100644 --- a/src/js/profile/application_settings.js +++ b/src/js/profile/application_settings.js @@ -189,7 +189,7 @@ function initializeSettings() { }, /** * @param {Application} app - */ app => app.restrictionMgr.getHasExtendedSettings() + */ app => G_IS_STANDALONE ), new BoolSetting( @@ -514,7 +514,7 @@ export class ApplicationSettings extends ReadWriteProxy { const settings = data.settings; // MODS - if (!THEMES[settings.theme]) { + if (!THEMES[settings.theme] || !this.app.restrictionMgr.getHasExtendedSettings()) { console.warn("Resetting theme because its no longer available: " + settings.theme); settings.theme = "light"; } @@ -700,7 +700,7 @@ export class ApplicationSettings extends ReadWriteProxy { } // MODS - if (!THEMES[data.settings.theme]) { + if (!THEMES[data.settings.theme] || !this.app.restrictionMgr.getHasExtendedSettings()) { console.warn("Resetting theme because its no longer available: " + data.settings.theme); data.settings.theme = "light"; } diff --git a/src/js/states/main_menu.js b/src/js/states/main_menu.js index adcecd79..c6c0f2e6 100644 --- a/src/js/states/main_menu.js +++ b/src/js/states/main_menu.js @@ -38,9 +38,8 @@ export class MainMenuState extends GameState { getInnerHTML() { const showLanguageIcon = !G_CHINA_VERSION && !G_WEGAME_VERSION; const showExitAppButton = G_IS_STANDALONE; - const showUpdateLabel = !G_WEGAME_VERSION; const showBrowserWarning = !G_IS_STANDALONE && !isSupportedBrowser(); - const showPuzzleDLC = !G_WEGAME_VERSION && G_IS_STANDALONE; + const showPuzzleDLC = !G_WEGAME_VERSION && G_IS_STANDALONE && !G_IS_STEAM_DEMO; const showWegameFooter = G_WEGAME_VERSION; const hasMods = MODS.anyModsActive(); @@ -69,15 +68,17 @@ export class MainMenuState extends GameState { const ownsPuzzleDLC = G_IS_DEV || (G_IS_STANDALONE && + !G_IS_STEAM_DEMO && /** @type { PlatformWrapperImplElectron}*/ (this.app.platformWrapper).dlcs.puzzle); const bannerHtml = `

${T.demoBanners.title}

${T.demoBanners.intro}

+ ${T.demoBanners.playtimeDisclaimer} ${ - globalConfig.currentDiscount.active - ? `${globalConfig.currentDiscount.amount}% off!` + globalConfig.currentDiscount > 0 + ? `${globalConfig.currentDiscount}% off!` : "" } @@ -201,7 +202,7 @@ export class MainMenuState extends GameState {