diff --git a/gulp/gulpfile.js b/gulp/gulpfile.js index 6771058b..efea71f8 100644 --- a/gulp/gulpfile.js +++ b/gulp/gulpfile.js @@ -164,8 +164,8 @@ function serveHTML({ version = "web-dev" }) { gulp.watch(["../src/**/*.scss"], gulp.series("css.dev")); // Watch .html files, those trigger a html rebuild - gulp.watch("../src/**/*.html", gulp.series("html." + version + ".dev")); - gulp.watch("./preloader/*.*", gulp.series("html." + version + ".dev")); + gulp.watch("../src/**/*.html", gulp.series("html.dev")); + gulp.watch("./preloader/*.*", gulp.series("html.dev")); // Watch translations gulp.watch("../translations/**/*.yaml", gulp.series("translations.convertToJson")); @@ -253,7 +253,7 @@ for (const variant in BUILD_VARIANTS) { gulp.task( buildName + ".all", - gulp.series(buildName + ".resourcesAndCode", "css.prod-standalone", "html." + variant + ".prod") + gulp.series(buildName + ".resourcesAndCode", "css.prod-standalone", "html.prod") ); gulp.task(buildName, gulp.series("utils.cleanup", buildName + ".all", "step.postbuild")); @@ -279,7 +279,7 @@ for (const variant in BUILD_VARIANTS) { // serve gulp.task( "serve." + variant, - gulp.series("build.prepare.dev", "html." + variant + ".dev", () => serveHTML({ version: variant })) + gulp.series("build.prepare.dev", "html.dev", () => serveHTML({ version: variant })) ); } diff --git a/gulp/html.js b/gulp/html.js index 913a3b21..d95e07e3 100644 --- a/gulp/html.js +++ b/gulp/html.js @@ -1,8 +1,7 @@ -import { getRevision, cachebust as cachebustUtil } from "./buildutils.js"; +import { getRevision } from "./buildutils.js"; import fs from "fs"; import path from "path/posix"; import crypto from "crypto"; -import { BUILD_VARIANTS } from "./build_variants.js"; import gulpDom from "gulp-dom"; import gulpHtmlmin from "gulp-htmlmin"; @@ -16,25 +15,16 @@ function computeIntegrityHash(fullPath, algorithm = "sha256") { } /** - * PROVIDES (per ) + * PROVIDES * - * html..dev - * html..prod + * html.dev + * html.prod */ export default function gulptasksHTML(gulp, buildFolder) { const commitHash = getRevision(); - async function buildHtml({ standalone = false, integrity = true, enableCachebust = true }) { - function cachebust(url) { - if (enableCachebust) { - return cachebustUtil(url, commitHash); - } - return url; - } - - const hasLocalFiles = standalone; - + async function buildHtml({ integrity = true }) { return gulp - .src("../src/html/" + (standalone ? "index.standalone.html" : "index.html")) + .src("../src/html/index.html") .pipe( gulpDom( /** @this {Document} **/ function () { @@ -46,7 +36,7 @@ export default function gulptasksHTML(gulp, buildFolder) { css.type = "text/css"; css.media = "none"; css.setAttribute("onload", "this.media='all'"); - css.href = cachebust("main.css"); + css.href = "main.css"; if (integrity) { css.setAttribute( "integrity", @@ -55,40 +45,13 @@ export default function gulptasksHTML(gulp, buildFolder) { } document.head.appendChild(css); - // Do not need to preload in app or standalone - if (!hasLocalFiles) { - // Preload essentials - const preloads = [ - "res/fonts/GameFont.woff2", - // "async-resources.css", - // "res/sounds/music/theme-short.mp3", - ]; - - preloads.forEach(src => { - const preloadLink = document.createElement("link"); - preloadLink.rel = "preload"; - preloadLink.href = cachebust(src); - if (src.endsWith(".woff2")) { - preloadLink.setAttribute("crossorigin", "anonymous"); - preloadLink.setAttribute("as", "font"); - } else if (src.endsWith(".css")) { - preloadLink.setAttribute("as", "style"); - } else if (src.endsWith(".mp3")) { - preloadLink.setAttribute("as", "audio"); - } else { - preloadLink.setAttribute("as", "image"); - } - document.head.appendChild(preloadLink); - }); - } - let fontCss = ` @font-face { font-family: "GameFont"; font-style: normal; font-weight: normal; font-display: swap; - src: url('${cachebust("res/fonts/GameFont.woff2")}') format("woff2"); + src: url('res/fonts/GameFont.woff2') format("woff2"); } `; let loadingCss = @@ -103,40 +66,16 @@ export default function gulptasksHTML(gulp, buildFolder) { .readFileSync(path.join("preloader", "preloader.html")) .toString(); - // Append loader, but not in standalone (directly include bundle there) - if (standalone) { - const bundleScript = document.createElement("script"); - bundleScript.type = "text/javascript"; - bundleScript.src = "bundle.js"; - if (integrity) { - bundleScript.setAttribute( - "integrity", - computeIntegrityHash(path.join(buildFolder, "bundle.js")) - ); - } - document.head.appendChild(bundleScript); - } else { - const loadJs = document.createElement("script"); - loadJs.type = "text/javascript"; - let scriptContent = ""; - scriptContent += `var bundleSrc = '${cachebust("bundle.js")}';\n`; - - if (integrity) { - scriptContent += - "var bundleIntegrity = '" + - computeIntegrityHash(path.join(buildFolder, "bundle.js")) + - "';\n"; - } else { - scriptContent += "var bundleIntegrity = null;\n"; - scriptContent += "var bundleIntegrityTranspiled = null;\n"; - } - - scriptContent += fs - .readFileSync(path.join("preloader", "preloader.js")) - .toString(); - loadJs.textContent = scriptContent; - document.head.appendChild(loadJs); + const bundleScript = document.createElement("script"); + bundleScript.type = "text/javascript"; + bundleScript.src = "bundle.js"; + if (integrity) { + bundleScript.setAttribute( + "integrity", + computeIntegrityHash(path.join(buildFolder, "bundle.js")) + ); } + document.head.appendChild(bundleScript); document.body.innerHTML = bodyContent; } @@ -160,21 +99,14 @@ export default function gulptasksHTML(gulp, buildFolder) { .pipe(gulp.dest(buildFolder)); } - for (const variant in BUILD_VARIANTS) { - const data = BUILD_VARIANTS[variant]; - gulp.task("html." + variant + ".dev", () => { - return buildHtml({ - standalone: data.standalone, - integrity: false, - enableCachebust: false, - }); + gulp.task("html.dev", () => { + return buildHtml({ + integrity: false, }); - gulp.task("html." + variant + ".prod", () => { - return buildHtml({ - standalone: data.standalone, - integrity: true, - enableCachebust: !data.standalone, - }); + }); + gulp.task("html.prod", () => { + return buildHtml({ + integrity: true, }); - } + }); } diff --git a/gulp/preloader/preloader.js b/gulp/preloader/preloader.js index 7e2fe518..553cd9c1 100644 --- a/gulp/preloader/preloader.js +++ b/gulp/preloader/preloader.js @@ -2,20 +2,6 @@ var loadTimeout = null; var callbackDone = false; - var searchString = window.location.search; - if (searchString.includes("steam_sso_auth_token=")) { - var pos = searchString.indexOf("steam_sso_auth_token"); - const authToken = searchString.substring(pos + 21, pos + 57); - try { - window.localStorage.setItem("steam_sso_auth_token", authToken); - window.location.replace(window.location.protocol + "//" + window.location.host); - } catch (ex) { - alert("Failed to login via Steam SSO: " + ex); - window.location.replace("https://shapez.io"); - } - return; - } - // Catch load errors function errorHandler(event, source, lineno, colno, error) { diff --git a/src/css/adinplay.scss b/src/css/adinplay.scss deleted file mode 100644 index 9707a502..00000000 --- a/src/css/adinplay.scss +++ /dev/null @@ -1,110 +0,0 @@ -#aip_gdpr { - &, - * { - text-shadow: none !important; - pointer-events: all; - color: #111 !important; - } - - #aip_gdpr_banner { - padding: 5px 0; - } - - #aip_gdpr_message { - padding: 0px 15px; - } -} - -#adinplayVideoContainer { - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - z-index: 20000; - background: rgba($mainBgColor, 0.9); - pointer-events: all; - cursor: default; - display: flex; - justify-content: center; - align-items: center; - - *, - & { - pointer-events: all; - } - - &:not(.visible) { - display: none; - } - - &.waitingForFinish { - .videoInner { - @include S(border-radius, $globalBorderRadius); - overflow: hidden; - - &::after { - content: " "; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - @include InlineAnimation(0.2s ease-in-out) { - 0% { - opacity: 0; - } - 100% { - opacity: 1; - } - } - - & { - background: rgba($mainBgColor, 0.9) uiResource("loading.svg") center center / #{D(60px)} no-repeat; - } - } - } - } - - @include InlineAnimation(1s ease-in-out) { - 0% { - background: rgba($mainBgColor, 0.1); - } - 100% { - background: rgba($mainBgColor, 0.9); - } - } - - .adInner { - @include BoxShadow3D(lighten($mainBgColor, 15)); - @include S(border-radius, $globalBorderRadius); - @include S(padding, 15px); - // max-width: 960px; - display: block !important; - - .topbar { - display: grid; - grid-template-columns: 1fr auto; - @include S(margin-bottom, 15px); - @include S(grid-column-gap, 10px); - - .desc { - @include TextShadow3D(#fff); - @include PlainText; - } - - button.getOnSteam { - @include Text; - } - } - - .videoInner { - // width: 960px; - // height: 570px; - // min-width: 960px; - // min-height: 570px; - background: darken($mainBgColor, 1); - display: block !important; - } - } -} diff --git a/src/css/common.scss b/src/css/common.scss index 448ebe4f..1ecf419b 100644 --- a/src/css/common.scss +++ b/src/css/common.scss @@ -714,18 +714,6 @@ input.rangeInput { } } -.xpaystation-widget-lightbox { - z-index: 19999; - .xpaystation-widget-lightbox-overlay { - background: rgba($mainBgColor, 0.94); - } - &, - iframe { - pointer-events: all; - user-select: all; - } -} - iframe { pointer-events: all; user-select: all; @@ -744,32 +732,3 @@ iframe { pointer-events: none; z-index: -1; } - -.sentry-error-embed-wrapper { - z-index: 10000; - background: rgba(0, 0, 0, 0.9); - * { - text-shadow: none !important; - pointer-events: all; - } -} - -.cpmsrendertarget { - &, - * { - pointer-events: all; - } - background: rgba($mainBgColor, 0.94) !important; - .cpmsvideoclosebanner { - font-family: GameFont !important; - font-size: 16px !important; - border-radius: 2px !important; - background: $themeColor !important; - @include BoxShadow3D(darken($mainBgColor, 12)); - color: #eee !important; - &:active { - @include BoxShadow3D(darken($mainBgColor, 12), $size: 1px); - transform: translateY(2px); - } - } -} diff --git a/src/css/main.scss b/src/css/main.scss index fedfbc51..103e8c36 100644 --- a/src/css/main.scss +++ b/src/css/main.scss @@ -17,10 +17,8 @@ @import "animations"; @import "game_state"; @import "textual_game_state"; -@import "adinplay"; @import "changelog_skins"; -@import "states/wegame_splash"; @import "states/preload"; @import "states/main_menu"; @import "states/ingame"; diff --git a/src/css/states/main_menu.scss b/src/css/states/main_menu.scss index 6d2f432e..d8ce48d6 100644 --- a/src/css/states/main_menu.scss +++ b/src/css/states/main_menu.scss @@ -252,15 +252,6 @@ font-weight: 700 !important; } - .onlinePlayerCount { - color: #333; - display: none; - @include S(margin-top, 15px); - @include SuperSmallText; - @include S(height, 15px); - text-align: center; - } - h3 { @include Heading; font-weight: bold; @@ -1167,39 +1158,6 @@ @include S(gap, 30px); @include S(padding, 15px, 25px, 15px, 20px); - &.wegameDisclaimer { - @include SuperSmallText; - display: grid; - justify-content: center; - text-align: center; - - > .disclaimer { - grid-column: 2 / 3; - - @include DarkThemeOverride { - color: #fff; - } - } - - > .rating { - grid-column: 3 / 4; - justify-self: end; - align-self: end; - - @include S(width, 32px); - @include S(height, 40px); - background: green; - cursor: pointer !important; - pointer-events: all; - @include S(border-radius, 4px); - overflow: hidden; - - & { - background: #fff uiResource("wegame_isbn_rating.jpg") center center / contain no-repeat; - } - } - } - .author { margin-left: auto; display: flex; diff --git a/src/css/states/wegame_splash.scss b/src/css/states/wegame_splash.scss deleted file mode 100644 index 961cfa67..00000000 --- a/src/css/states/wegame_splash.scss +++ /dev/null @@ -1,38 +0,0 @@ -#state_WegameSplashState { - background: #000 !important; - display: flex; - align-items: center; - justify-content: center; - - .wrapper { - opacity: 0; - @include InlineAnimation(5.9s ease-in-out) { - 0% { - opacity: 0; - } - 20% { - opacity: 1; - } - 90% { - opacity: 1; - } - 100% { - opacity: 0; - } - } - - text-align: center; - color: #fff; - @include Heading; - - strong { - display: block; - @include SuperHeading; - @include S(margin-bottom, 20px); - } - - div { - @include S(margin-bottom, 10px); - } - } -} diff --git a/src/html/index.html b/src/html/index.html index ab32169c..9209c2fc 100644 --- a/src/html/index.html +++ b/src/html/index.html @@ -1,46 +1,22 @@ - + - shapez Demo - Factory Automation Game + shapez - - - - - - - - - - - - - - - diff --git a/src/html/index.standalone.html b/src/html/index.standalone.html deleted file mode 100644 index 9209c2fc..00000000 --- a/src/html/index.standalone.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - shapez - - - - - - - - - - - - - - - diff --git a/src/js/application.js b/src/js/application.js index 4c3c4c9f..68dbc100 100644 --- a/src/js/application.js +++ b/src/js/application.js @@ -10,11 +10,7 @@ import { StateManager } from "./core/state_manager"; import { TrackedState } from "./core/tracked_state"; import { getPlatformName, waitNextFrame } from "./core/utils"; import { Vector } from "./core/vector"; -import { AdProviderInterface } from "./platform/ad_provider"; -import { NoAdProvider } from "./platform/ad_providers/no_ad_provider"; import { NoAchievementProvider } from "./platform/browser/no_achievement_provider"; -import { AnalyticsInterface } from "./platform/analytics"; -import { GoogleAnalyticsImpl } from "./platform/browser/google_analytics"; import { SoundImplBrowser } from "./platform/browser/sound"; import { PlatformWrapperImplBrowser } from "./platform/browser/wrapper"; import { PlatformWrapperImplElectron } from "./platform/electron/wrapper"; @@ -29,11 +25,9 @@ import { MainMenuState } from "./states/main_menu"; import { MobileWarningState } from "./states/mobile_warning"; import { PreloadState } from "./states/preload"; import { SettingsState } from "./states/settings"; -import { ShapezGameAnalytics } from "./platform/browser/game_analytics"; import { PuzzleMenuState } from "./states/puzzle_menu"; import { ClientAPI } from "./platform/api"; import { LoginState } from "./states/login"; -import { WegameSplashState } from "./states/wegame_splash"; import { MODS } from "./mods/modloader"; import { MOD_SIGNALS } from "./mods/mod_signals"; import { ModsState } from "./states/mods"; @@ -107,15 +101,6 @@ export class Application { /** @type {AchievementProviderInterface} */ this.achievementProvider = null; - /** @type {AdProviderInterface} */ - this.adProvider = null; - - /** @type {AnalyticsInterface} */ - this.analytics = null; - - /** @type {ShapezGameAnalytics} */ - this.gameAnalytics = null; - this.initPlatformDependentInstances(); // Track if the window is focused (only relevant for browser) @@ -178,11 +163,7 @@ export class Application { this.platformWrapper = new PlatformWrapperImplBrowser(this); } - // Start with empty ad provider - this.adProvider = new NoAdProvider(this); this.sound = new SoundImplBrowser(this); - this.analytics = new GoogleAnalyticsImpl(this); - this.gameAnalytics = new ShapezGameAnalytics(this); this.achievementProvider = new NoAchievementProvider(this); } @@ -192,7 +173,6 @@ export class Application { registerStates() { /** @type {Array} */ const states = [ - WegameSplashState, PreloadState, MobileWarningState, MainMenuState, @@ -326,11 +306,7 @@ export class Application { } onAppPlayingStateChanged(playing) { - try { - this.adProvider.setPlayStatus(playing); - } catch (ex) { - console.warn("Play status changed"); - } + // TODO: Check for usages and alternatives. This can be turned into a singal. } /** diff --git a/src/js/core/config.js b/src/js/core/config.js index 7fbc4545..4f706cf4 100644 --- a/src/js/core/config.js +++ b/src/js/core/config.js @@ -25,7 +25,6 @@ export const THIRDPARTY_URLS = { patreon: "https://www.patreon.com/tobsprgames", privacyPolicy: "https://tobspr.io/privacy.html", - standaloneCampaignLink: "https://get.shapez.io/bundle/$campaign", puzzleDlcStorePage: "https://get.shapez.io/mm_puzzle_dlc?target=dlc", levelTutorialVideos: { @@ -37,17 +36,6 @@ export const THIRDPARTY_URLS = { modBrowser: "https://shapez.mod.io/", }; -/** - * @param {Application} app - * @param {string} campaign - */ -export function openStandaloneLink(app, campaign) { - const discount = globalConfig.currentDiscount > 0 ? "_discount" + globalConfig.currentDiscount : ""; - const event = campaign + discount; - app.platformWrapper.openExternalLink(THIRDPARTY_URLS.standaloneCampaignLink.replace("$campaign", event)); - app.gameAnalytics.noteMinor("g.stdlink." + event); -} - export const globalConfig = { // Size of a single tile in Pixels. // NOTICE: Update webpack.production.config too! diff --git a/src/js/core/logging.js b/src/js/core/logging.js index dc3510d2..a0227f13 100644 --- a/src/js/core/logging.js +++ b/src/js/core/logging.js @@ -35,32 +35,6 @@ export function createLogger(context) { return new Logger(context); } -function prepareObjectForLogging(obj, maxDepth = 1) { - if (!window.Sentry) { - // Not required without sentry - return obj; - } - - if (typeof obj !== "object" && !Array.isArray(obj)) { - return obj; - } - const result = {}; - for (const key in obj) { - const val = obj[key]; - - if (typeof val === "object") { - if (maxDepth > 0) { - result[key] = prepareObjectForLogging(val, maxDepth - 1); - } else { - result[key] = "[object]"; - } - } else { - result[key] = val; - } - } - return result; -} - /** * Serializes an error * @param {Error|ErrorEvent} err @@ -155,19 +129,12 @@ export function globalError(context, ...args) { args = prepareArgsForLogging(args); // eslint-disable-next-line no-console logInternal(context, console.error, args); - - if (window.Sentry) { - window.Sentry.withScope(scope => { - scope.setExtra("args", args); - window.Sentry.captureMessage(internalBuildStringFromArgs(args), "error"); - }); - } } function prepareArgsForLogging(args) { let result = []; for (let i = 0; i < args.length; ++i) { - result.push(prepareObjectForLogging(args[i])); + result.push(args[i]); } return result; } diff --git a/src/js/core/query_parameters.js b/src/js/core/query_parameters.js deleted file mode 100644 index b8b4fbfd..00000000 --- a/src/js/core/query_parameters.js +++ /dev/null @@ -1,28 +0,0 @@ -const options = Object.fromEntries(new URLSearchParams(location.search).entries()); - -export let queryParamOptions = { - embedProvider: null, - abtVariant: null, - campaign: null, - fbclid: null, - gclid: null, -}; - -if (options.embed) { - queryParamOptions.embedProvider = options.embed; -} - -if (options.abtVariant) { - queryParamOptions.abtVariant = options.abtVariant; -} - -if (options.fbclid) { - queryParamOptions.fbclid = options.fbclid; -} - -if (options.gclid) { - queryParamOptions.gclid = options.gclid; -} -if (options.utm_campaign) { - queryParamOptions.campaign = options.utm_campaign; -} diff --git a/src/js/core/state_manager.js b/src/js/core/state_manager.js index 70b4b7f4..001537cd 100644 --- a/src/js/core/state_manager.js +++ b/src/js/core/state_manager.js @@ -105,8 +105,6 @@ export class StateManager { this.currentState.onResized(this.app.screenWidth, this.app.screenHeight); - this.app.analytics.trackStateEnter(key); - window.history.pushState( { key, diff --git a/src/js/core/steam_sso.js b/src/js/core/steam_sso.js deleted file mode 100644 index 67c6d582..00000000 --- a/src/js/core/steam_sso.js +++ /dev/null @@ -1,89 +0,0 @@ -import { T } from "../translations"; -import { openStandaloneLink } from "./config"; - -export let WEB_STEAM_SSO_AUTHENTICATED = false; - -export async function authorizeViaSSOToken(app, dialogs) { - if (G_IS_STANDALONE) { - return; - } - - if (window.location.search.includes("sso_logout_silent")) { - window.localStorage.setItem("steam_sso_auth_token", ""); - window.location.replace("/"); - return new Promise(() => null); - } - - if (window.location.search.includes("sso_logout")) { - const { ok } = dialogs.showWarning(T.dialogs.steamSsoError.title, T.dialogs.steamSsoError.desc); - window.localStorage.setItem("steam_sso_auth_token", ""); - ok.add(() => window.location.replace("/")); - return new Promise(() => null); - } - - if (window.location.search.includes("steam_sso_no_ownership")) { - const { ok, getStandalone } = dialogs.showWarning( - T.dialogs.steamSsoNoOwnership.title, - T.dialogs.steamSsoNoOwnership.desc, - ["ok", "getStandalone:good"] - ); - window.localStorage.setItem("steam_sso_auth_token", ""); - getStandalone.add(() => { - openStandaloneLink(app, "sso_ownership"); - window.location.replace("/"); - }); - ok.add(() => window.location.replace("/")); - return new Promise(() => null); - } - - const token = window.localStorage.getItem("steam_sso_auth_token"); - if (!token) { - return Promise.resolve(); - } - - const apiUrl = app.clientApi.getEndpoint(); - console.warn("Authorizing via token:", token); - - const verify = async () => { - const token = window.localStorage.getItem("steam_sso_auth_token"); - if (!token) { - window.location.replace("?sso_logout"); - return; - } - - try { - const response = await Promise.race([ - fetch(apiUrl + "/v1/sso/refresh", { - method: "POST", - body: token, - headers: { - "x-api-key": "d5c54aaa491f200709afff082c153ef2", - }, - }), - new Promise((resolve, reject) => { - setTimeout(() => reject("timeout exceeded"), 20000); - }), - ]); - - const responseText = await response.json(); - if (!responseText.token) { - console.warn("Failed to register"); - window.localStorage.setItem("steam_sso_auth_token", ""); - window.location.replace("?sso_logout"); - return; - } - - window.localStorage.setItem("steam_sso_auth_token", responseText.token); - app.clientApi.token = responseText.token; - WEB_STEAM_SSO_AUTHENTICATED = true; - } catch (ex) { - console.warn("Auth failure", ex); - window.localStorage.setItem("steam_sso_auth_token", ""); - window.location.replace("/"); - return new Promise(() => null); - } - }; - - await verify(); - setInterval(verify, 120000); -} diff --git a/src/js/game/hub_goals.js b/src/js/game/hub_goals.js index 23ee3b0b..1bda4b2f 100644 --- a/src/js/game/hub_goals.js +++ b/src/js/game/hub_goals.js @@ -114,7 +114,7 @@ export class HubGoals extends BasicSerializableObject { window.addEventListener("keydown", ev => { if (ev.key === "p") { // root is not guaranteed to exist within ~0.5s after loading in - if (this.root && this.root.app && this.root.app.gameAnalytics) { + if (this.root) { if (!this.isEndOfDemoReached()) { this.onGoalCompleted(); } @@ -262,7 +262,6 @@ export class HubGoals extends BasicSerializableObject { const reward = this.currentGoal.reward; this.gainedRewards[reward] = (this.gainedRewards[reward] || 0) + 1; - this.root.app.gameAnalytics.handleLevelCompleted(this.level); ++this.level; this.computeNextGoal(); @@ -352,8 +351,6 @@ export class HubGoals extends BasicSerializableObject { this.root.signals.upgradePurchased.dispatch(upgradeId); - this.root.app.gameAnalytics.handleUpgradeUnlocked(upgradeId, currentLevel); - return true; } diff --git a/src/js/game/hud/parts/modal_dialogs.js b/src/js/game/hud/parts/modal_dialogs.js index 72624192..c1ceb726 100644 --- a/src/js/game/hud/parts/modal_dialogs.js +++ b/src/js/game/hud/parts/modal_dialogs.js @@ -7,8 +7,6 @@ import { DynamicDomAttach } from "../dynamic_dom_attach"; import { BaseHUDPart } from "../base_hud_part"; import { Dialog, DialogLoading, DialogOptionChooser } from "../../../core/modal_dialog_elements"; import { makeDiv } from "../../../core/utils"; -import { T } from "../../../translations"; -import { openStandaloneLink } from "../../../core/config"; export class HUDModalDialogs extends BaseHUDPart { constructor(root, app) { diff --git a/src/js/game/hud/parts/sandbox_controller.js b/src/js/game/hud/parts/sandbox_controller.js index 3689fa36..0229dccd 100644 --- a/src/js/game/hud/parts/sandbox_controller.js +++ b/src/js/game/hud/parts/sandbox_controller.js @@ -1,4 +1,3 @@ -import { queryParamOptions } from "../../../core/query_parameters"; import { makeDiv } from "../../../core/utils"; import { BaseHUDPart } from "../base_hud_part"; import { DynamicDomAttach } from "../dynamic_dom_attach"; diff --git a/src/js/game/hud/parts/settings_menu.js b/src/js/game/hud/parts/settings_menu.js index f5314cd6..16da0440 100644 --- a/src/js/game/hud/parts/settings_menu.js +++ b/src/js/game/hud/parts/settings_menu.js @@ -61,9 +61,7 @@ export class HUDSettingsMenu extends BaseHUDPart { } returnToMenu() { - this.root.app.adProvider.showVideoAd().then(() => { - this.root.gameState.goBackToMenu(); - }); + this.root.gameState.goBackToMenu(); } goToSettings() { diff --git a/src/js/game/hud/parts/unlock_notification.js b/src/js/game/hud/parts/unlock_notification.js index 0357be9b..305a4813 100644 --- a/src/js/game/hud/parts/unlock_notification.js +++ b/src/js/game/hud/parts/unlock_notification.js @@ -24,8 +24,6 @@ export class HUDUnlockNotification extends BaseHUDPart { } this.buttonShowTimeout = null; - - this.root.app.gameAnalytics.noteMinor("game.started"); } shouldPauseGame() { @@ -69,8 +67,6 @@ export class HUDUnlockNotification extends BaseHUDPart { return; } - this.root.app.gameAnalytics.noteMinor("game.level.complete-" + level); - this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever); this.elemTitle.innerText = T.ingame.levelCompleteNotification.levelTitle.replace( "", @@ -134,33 +130,31 @@ export class HUDUnlockNotification extends BaseHUDPart { } requestClose() { - this.root.app.adProvider.showVideoAd().then(() => { - this.close(); + this.close(); - this.root.hud.signals.unlockNotificationFinished.dispatch(); + this.root.hud.signals.unlockNotificationFinished.dispatch(); - if (!this.root.app.settings.getAllSettings().offerHints) { - return; - } + if (!this.root.app.settings.getAllSettings().offerHints) { + return; + } - if (this.root.hubGoals.level === 3) { - const { showUpgrades } = this.root.hud.parts.dialogs.showInfo( - T.dialogs.upgradesIntroduction.title, - T.dialogs.upgradesIntroduction.desc, - ["showUpgrades:good:timeout"] - ); - showUpgrades.add(() => this.root.hud.parts.shop.show()); - } + if (this.root.hubGoals.level === 3) { + const { showUpgrades } = this.root.hud.parts.dialogs.showInfo( + T.dialogs.upgradesIntroduction.title, + T.dialogs.upgradesIntroduction.desc, + ["showUpgrades:good:timeout"] + ); + showUpgrades.add(() => this.root.hud.parts.shop.show()); + } - if (this.root.hubGoals.level === 5) { - const { showKeybindings } = this.root.hud.parts.dialogs.showInfo( - T.dialogs.keybindingsIntroduction.title, - T.dialogs.keybindingsIntroduction.desc, - ["showKeybindings:misc", "ok:good:timeout"] - ); - showKeybindings.add(() => this.root.gameState.goToKeybindings()); - } - }); + if (this.root.hubGoals.level === 5) { + const { showKeybindings } = this.root.hud.parts.dialogs.showInfo( + T.dialogs.keybindingsIntroduction.title, + T.dialogs.keybindingsIntroduction.desc, + ["showKeybindings:misc", "ok:good:timeout"] + ); + showKeybindings.add(() => this.root.gameState.goToKeybindings()); + } } close() { diff --git a/src/js/game/modes/levels.js b/src/js/game/modes/levels.js index e4e8068b..fe113b39 100644 --- a/src/js/game/modes/levels.js +++ b/src/js/game/modes/levels.js @@ -1,166 +1,8 @@ -/* typehints:start */ -import { Application } from "../../application"; -/* typehints:end */ -import { WEB_STEAM_SSO_AUTHENTICATED } from "../../core/steam_sso"; import { enumHubGoalRewards } from "../tutorial_goals"; export const finalGameShape = "RuCw--Cw:----Ru--"; -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -/** - * - * @param {Application} app - * @returns - */ -const WEB_DEMO_LEVELS = app => { - const levels = [ - // 1 - // Circle - { - shape: "CuCuCuCu", // belts t1 - required: 10, - reward: enumHubGoalRewards.reward_cutter_and_trash, - }, - - // 2 - // Cutter - { - shape: "----CuCu", // - required: 20, - reward: enumHubGoalRewards.no_reward, - }, - - // 3 - // Rectangle - { - shape: "RuRuRuRu", // miners t1 - required: 30, - reward: enumHubGoalRewards.reward_balancer, - }, - - // 4 - { - shape: "RuRu----", // processors t2 - required: 30, - reward: enumHubGoalRewards.reward_rotater, - }, - - // 5 - // Rotater - { - shape: "Cu----Cu", // belts t2 - required: 75, - reward: enumHubGoalRewards.reward_tunnel, - }, - - // 6 - // Painter - { - shape: "Cu------", // miners t2 - required: 50, - reward: enumHubGoalRewards.reward_painter, - }, - - // 7 - { - shape: "CrCrCrCr", // unused - required: 85, - reward: enumHubGoalRewards.reward_rotater_ccw, - }, - - // 8 - { - shape: "RbRb----", // painter t2 - required: 100, - reward: enumHubGoalRewards.reward_mixer, - }, - { - shape: "RpRp----", - required: 0, - reward: enumHubGoalRewards.reward_demo_end, - }, - ]; - - return levels; -}; - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -const STEAM_DEMO_LEVELS = () => [ - // 1 - // Circle - { - shape: "CuCuCuCu", // belts t1 - required: 35, - reward: enumHubGoalRewards.reward_cutter_and_trash, - }, - - // 2 - // Cutter - { - shape: "----CuCu", // - required: 45, - reward: enumHubGoalRewards.no_reward, - }, - - // 3 - // Rectangle - { - shape: "RuRuRuRu", // miners t1 - required: 90, - reward: enumHubGoalRewards.reward_balancer, - }, - - // 4 - { - shape: "RuRu----", // processors t2 - required: 70, - reward: enumHubGoalRewards.reward_rotater, - }, - - // 5 - // Rotater - { - shape: "Cu----Cu", // belts t2 - required: 160, - reward: enumHubGoalRewards.reward_tunnel, - }, - - // 6 - { - shape: "Cu------", // miners t2 - required: 160, - reward: enumHubGoalRewards.reward_painter, - }, - - // 7 - // Painter - { - shape: "CrCrCrCr", // unused - required: 140, - reward: enumHubGoalRewards.reward_rotater_ccw, - }, - // 8 - { - shape: "RbRb----", // painter t2 - required: 225, - reward: enumHubGoalRewards.reward_mixer, - }, - // End of demo - { - shape: "CpCpCpCp", - required: 0, - reward: enumHubGoalRewards.reward_demo_end, - }, -]; - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -const STANDALONE_LEVELS = () => [ +export const REGULAR_MODE_LEVELS = [ // 1 // Circle { @@ -361,13 +203,3 @@ const STANDALONE_LEVELS = () => [ reward: enumHubGoalRewards.reward_freeplay, }, ]; - -/** - * Generates the level definitions - */ -export function generateLevelsForVariant(app) { - if (G_IS_STANDALONE || WEB_STEAM_SSO_AUTHENTICATED) { - return STANDALONE_LEVELS(); - } - return WEB_DEMO_LEVELS(app); -} diff --git a/src/js/game/modes/regular.js b/src/js/game/modes/regular.js index b52f5648..f1e5ac9c 100644 --- a/src/js/game/modes/regular.js +++ b/src/js/game/modes/regular.js @@ -34,8 +34,7 @@ import { HUDInteractiveTutorial } from "../hud/parts/interactive_tutorial"; import { MetaBlockBuilding } from "../buildings/block"; import { MetaItemProducerBuilding } from "../buildings/item_producer"; import { MOD_SIGNALS } from "../../mods/mod_signals"; -import { finalGameShape, generateLevelsForVariant } from "./levels"; -import { WEB_STEAM_SSO_AUTHENTICATED } from "../../core/steam_sso"; +import { finalGameShape, REGULAR_MODE_LEVELS } from "./levels"; /** @typedef {{ * shape: string, @@ -63,16 +62,16 @@ const preparementShape = "CpRpCp--:SwSwSwSw"; // Tiers need % of the previous tier as requirement too const tierGrowth = 2.5; -const upgradesCache = {}; +// TODO: Convert this file to TS and fix types. Maybe split the levels and upgrades as well +let upgradesCache = null; /** * Generates all upgrades * @returns {Object} */ -function generateUpgrades(limitedVersion = false, difficulty = 1) { - // TODO: Remove the limitedVersion parameter - if (upgradesCache[limitedVersion]) { - return upgradesCache[limitedVersion]; +function generateUpgrades() { + if (upgradesCache) { + return upgradesCache; } const fixedImprovements = [0.5, 0.5, 1, 1, 2, 1, 1]; @@ -243,9 +242,6 @@ function generateUpgrades(limitedVersion = false, difficulty = 1) { const tierHandle = upgradeTiers[i]; tierHandle.improvement = fixedImprovements[i]; - tierHandle.required.forEach(required => { - required.amount = Math.round(required.amount * difficulty); - }); const originalRequired = tierHandle.required.slice(); for (let k = currentTierRequirements.length - 1; k >= 0; --k) { @@ -286,7 +282,7 @@ function generateUpgrades(limitedVersion = false, difficulty = 1) { } } - upgradesCache[limitedVersion] = upgrades; + upgradesCache = upgrades; return upgrades; } @@ -295,12 +291,15 @@ let levelDefinitionsCache = null; /** * Generates the level definitions */ -export function generateLevelDefinitions(app) { +export function generateLevelDefinitions() { + // NOTE: This cache is useless in production, but is there because of the G_IS_DEV validation if (levelDefinitionsCache) { return levelDefinitionsCache; } - const levelDefinitions = generateLevelsForVariant(app); + + const levelDefinitions = REGULAR_MODE_LEVELS; MOD_SIGNALS.modifyLevelDefinitions.dispatch(levelDefinitions); + if (G_IS_DEV) { levelDefinitions.forEach(({ shape }) => { try { @@ -310,6 +309,7 @@ export function generateLevelDefinitions(app) { } }); } + levelDefinitionsCache = levelDefinitions; return levelDefinitions; } @@ -366,19 +366,12 @@ export class RegularGameMode extends GameMode { ]; } - get difficultyMultiplicator() { - if (G_IS_STANDALONE || WEB_STEAM_SSO_AUTHENTICATED) { - return 1; - } - return 0.5; - } - /** * Should return all available upgrades * @returns {Object} */ getUpgrades() { - return generateUpgrades(false, this.difficultyMultiplicator); + return generateUpgrades(); } /** @@ -386,7 +379,7 @@ export class RegularGameMode extends GameMode { * @returns {Array} */ getLevelDefinitions() { - return generateLevelDefinitions(this.root.app); + return generateLevelDefinitions(); } /** diff --git a/src/js/globals.d.ts b/src/js/globals.d.ts index 706b83c7..41c2db95 100644 --- a/src/js/globals.d.ts +++ b/src/js/globals.d.ts @@ -46,54 +46,14 @@ declare interface Logger { error(...args); } -// Cordova -declare interface Device { - uuid: string; - platform: string; - available: boolean; - version: string; - cordova: string; - model: string; - manufacturer: string; - isVirtual: boolean; - serial: string; -} - declare interface MobileAccessibility { usePreferredTextZoom(boolean); } declare interface Window { - // Cordova - device: Device; - StatusBar: any; - AndroidFullScreen: any; - AndroidNotch: any; - plugins: any; - - // Adinplay - aiptag: any; - adPlayer: any; - aipPlayer: any; - MobileAccessibility: MobileAccessibility; - LocalFileSystem: any; - // Debugging activeClickDetectors: Array; - // Experimental/Newer apis - FontFace: any; - TouchEvent: undefined | TouchEvent; - - // Thirdparty - XPayStationWidget: any; - Sentry: any; - LogRocket: any; - grecaptcha: any; - gtag: any; - cpmstarAPI: any; - CrazyGames: any; - // Mods $shapez_registerMod: any; anyModLoaded: any; @@ -115,11 +75,6 @@ declare interface Navigator { splashscreen: any; } -// FontFace -declare interface Document { - fonts: any; -} - // Webpack declare interface WebpackContext { keys(): Array; diff --git a/src/js/platform/ad_provider.js b/src/js/platform/ad_provider.js deleted file mode 100644 index 6b96768e..00000000 --- a/src/js/platform/ad_provider.js +++ /dev/null @@ -1,49 +0,0 @@ -/* typehints:start */ -import { Application } from "../application"; -/* typehints:end */ - -export class AdProviderInterface { - /** @param {Application} app */ - constructor(app) { - this.app = app; - } - - /** - * Initializes the storage - * @returns {Promise} - */ - initialize() { - return Promise.resolve(); - } - - /** - * Returns if this provider serves ads at all - * @returns {boolean} - * @abstract - */ - getHasAds() { - abstract; - return false; - } - - /** - * Returns if it would be possible to show a video ad *now*. This can be false if for - * example the last video ad is - * @returns {boolean} - * @abstract - */ - getCanShowVideoAd() { - abstract; - return false; - } - - /** - * Shows an video ad - * @returns {Promise} - */ - showVideoAd() { - return Promise.resolve(); - } - - setPlayStatus(playing) {} -} diff --git a/src/js/platform/ad_providers/adinplay.js b/src/js/platform/ad_providers/adinplay.js deleted file mode 100644 index 3897ec04..00000000 --- a/src/js/platform/ad_providers/adinplay.js +++ /dev/null @@ -1,191 +0,0 @@ -/* typehints:start */ -import { Application } from "../../application"; -/* typehints:end */ - -import { AdProviderInterface } from "../ad_provider"; -import { createLogger } from "../../core/logging"; -import { ClickDetector } from "../../core/click_detector"; -import { clamp } from "../../core/utils"; -import { T } from "../../translations"; - -const logger = createLogger("adprovider/adinplay"); - -const minimumTimeBetweenVideoAdsMs = G_IS_DEV ? 1 : 15 * 60 * 1000; - -export class AdinplayAdProvider extends AdProviderInterface { - /** - * - * @param {Application} app - */ - constructor(app) { - super(app); - - /** @type {ClickDetector} */ - this.getOnSteamClickDetector = null; - - /** @type {Element} */ - this.adContainerMainElement = null; - - /** - * The resolve function to finish the current video ad. Null if none is currently running - * @type {Function} - */ - this.videoAdResolveFunction = null; - - /** - * The current timer which will timeout the resolve - */ - this.videoAdResolveTimer = null; - - /** - * When we showed the last video ad - */ - this.lastVideoAdShowTime = -1e20; - } - - getHasAds() { - return true; - } - - getCanShowVideoAd() { - return ( - this.getHasAds() && - !this.videoAdResolveFunction && - performance.now() - this.lastVideoAdShowTime > minimumTimeBetweenVideoAdsMs - ); - } - - initialize() { - // No point to initialize everything if ads are not supported - if (!this.getHasAds()) { - return Promise.resolve(); - } - - logger.log("🎬 Initializing Adinplay"); - - // Add the preroll element - this.adContainerMainElement = document.createElement("div"); - this.adContainerMainElement.id = "adinplayVideoContainer"; - this.adContainerMainElement.innerHTML = ` -
-
- -
-
- `; - - // Add the setup script - const setupScript = document.createElement("script"); - setupScript.textContent = ` - var aiptag = aiptag || {}; - aiptag.cmd = aiptag.cmd || []; - aiptag.cmd.display = aiptag.cmd.display || []; - aiptag.cmd.player = aiptag.cmd.player || []; - `; - document.head.appendChild(setupScript); - - window.aiptag.gdprShowConsentTool = 0; - window.aiptag.gdprAlternativeConsentTool = 1; - window.aiptag.gdprConsent = 1; - - const scale = this.app.getEffectiveUiScale(); - const targetW = 960; - const targetH = 540; - - const maxScaleX = (window.innerWidth - 100 * scale) / targetW; - const maxScaleY = (window.innerHeight - 150 * scale) / targetH; - - const scaleFactor = clamp(Math.min(maxScaleX, maxScaleY), 0.25, 2); - - const w = Math.round(targetW * scaleFactor); - const h = Math.round(targetH * scaleFactor); - - // Add the player - const videoElement = this.adContainerMainElement.querySelector(".videoInner"); - /** @type {HTMLElement} */ - const adInnerElement = this.adContainerMainElement.querySelector(".adInner"); - - adInnerElement.style.maxWidth = w + "px"; - - const self = this; - window.aiptag.cmd.player.push(function () { - window.adPlayer = new window.aipPlayer({ - AD_WIDTH: w, - AD_HEIGHT: h, - AD_FULLSCREEN: false, - AD_CENTERPLAYER: false, - LOADING_TEXT: T.global.loading, - PREROLL_ELEM: function () { - return videoElement; - }, - AIP_COMPLETE: function () { - logger.log("🎬 ADINPLAY AD: completed"); - self.adContainerMainElement.classList.add("waitingForFinish"); - }, - AIP_REMOVE: function () { - logger.log("🎬 ADINPLAY AD: remove"); - if (self.videoAdResolveFunction) { - self.videoAdResolveFunction(); - } - }, - }); - }); - - // Load the ads - const aipScript = document.createElement("script"); - aipScript.src = "https://api.adinplay.com/libs/aiptag/pub/YRG/shapez.io/tag.min.js"; - aipScript.setAttribute("async", ""); - document.head.appendChild(aipScript); - - return Promise.resolve(); - } - - showVideoAd() { - assert(this.getHasAds(), "Called showVideoAd but ads are not supported!"); - assert(!this.videoAdResolveFunction, "Video ad still running, can not show again!"); - this.lastVideoAdShowTime = performance.now(); - document.body.appendChild(this.adContainerMainElement); - this.adContainerMainElement.classList.add("visible"); - this.adContainerMainElement.classList.remove("waitingForFinish"); - - try { - // @ts-ignore - window.aiptag.cmd.player.push(function () { - console.log("🎬 ADINPLAY AD: Start pre roll"); - window.adPlayer.startPreRoll(); - }); - } catch (ex) { - logger.warn("🎬 Failed to play video ad:", ex); - document.body.removeChild(this.adContainerMainElement); - this.adContainerMainElement.classList.remove("visible"); - return Promise.resolve(); - } - - return new Promise(resolve => { - // So, wait for the remove call but also remove after N seconds - this.videoAdResolveFunction = () => { - this.videoAdResolveFunction = null; - clearTimeout(this.videoAdResolveTimer); - this.videoAdResolveTimer = null; - - // When the ad closed, also set the time - this.lastVideoAdShowTime = performance.now(); - resolve(); - }; - - this.videoAdResolveTimer = setTimeout(() => { - logger.warn(this, "Automatically closing ad after not receiving callback"); - if (this.videoAdResolveFunction) { - this.videoAdResolveFunction(); - } - }, 120 * 1000); - }) - .catch(err => { - logger.error("Error while resolving video ad:", err); - }) - .then(() => { - document.body.removeChild(this.adContainerMainElement); - this.adContainerMainElement.classList.remove("visible"); - }); - } -} diff --git a/src/js/platform/ad_providers/crazygames.js b/src/js/platform/ad_providers/crazygames.js deleted file mode 100644 index 5f70cea4..00000000 --- a/src/js/platform/ad_providers/crazygames.js +++ /dev/null @@ -1,99 +0,0 @@ -import { AdProviderInterface } from "../ad_provider"; -import { createLogger } from "../../core/logging"; -import { timeoutPromise } from "../../core/utils"; - -const logger = createLogger("crazygames"); - -export class CrazygamesAdProvider extends AdProviderInterface { - getHasAds() { - return true; - } - - getCanShowVideoAd() { - return this.getHasAds() && this.sdkInstance; - } - - get sdkInstance() { - try { - return window.CrazyGames.CrazySDK.getInstance(); - } catch (ex) { - return null; - } - } - - initialize() { - if (!this.getHasAds()) { - return Promise.resolve(); - } - - logger.log("🎬 Initializing crazygames SDK"); - - const scriptTag = document.createElement("script"); - scriptTag.type = "text/javascript"; - - return timeoutPromise( - new Promise((resolve, reject) => { - scriptTag.onload = resolve; - scriptTag.onerror = reject; - scriptTag.src = "https://sdk.crazygames.com/crazygames-sdk-v1.js"; - document.head.appendChild(scriptTag); - }) - .then(() => { - logger.log("🎬 Crazygames SDK loaded, now initializing"); - this.sdkInstance.init(); - }) - .catch(ex => { - console.warn("Failed to init crazygames SDK:", ex); - }) - ); - } - - showVideoAd() { - const instance = this.sdkInstance; - if (!instance) { - return Promise.resolve(); - } - - logger.log("Set sound volume to 0"); - this.app.sound.setMusicVolume(0); - this.app.sound.setSoundVolume(0); - - return timeoutPromise( - new Promise(resolve => { - console.log("🎬 crazygames: Start ad"); - document.body.classList.add("externalAdOpen"); - - const finish = () => { - instance.removeEventListener("adError", finish); - instance.removeEventListener("adFinished", finish); - resolve(); - }; - - instance.addEventListener("adError", finish); - instance.addEventListener("adFinished", finish); - - instance.requestAd(); - }), - 60000 - ) - .catch(ex => { - console.warn("Error while resolving video ad:", ex); - }) - .then(() => { - document.body.classList.remove("externalAdOpen"); - - logger.log("Restored sound volume"); - - this.app.sound.setMusicVolume(this.app.settings.getSetting("musicVolume")); - this.app.sound.setSoundVolume(this.app.settings.getSetting("soundVolume")); - }); - } - setPlayStatus(playing) { - console.log("crazygames::playing:", playing); - if (playing) { - this.sdkInstance.gameplayStart(); - } else { - this.sdkInstance.gameplayStop(); - } - } -} diff --git a/src/js/platform/ad_providers/gamedistribution.js b/src/js/platform/ad_providers/gamedistribution.js deleted file mode 100644 index be8e41a3..00000000 --- a/src/js/platform/ad_providers/gamedistribution.js +++ /dev/null @@ -1,131 +0,0 @@ -/* typehints:start */ -import { Application } from "../../application"; -/* typehints:end */ - -import { AdProviderInterface } from "../ad_provider"; -import { createLogger } from "../../core/logging"; - -const minimumTimeBetweenVideoAdsMs = G_IS_DEV ? 1 : 5 * 60 * 1000; - -const logger = createLogger("gamedistribution"); - -export class GamedistributionAdProvider extends AdProviderInterface { - /** - * - * @param {Application} app - */ - constructor(app) { - super(app); - - /** - * The resolve function to finish the current video ad. Null if none is currently running - * @type {Function} - */ - this.videoAdResolveFunction = null; - - /** - * The current timer which will timeout the resolve - */ - this.videoAdResolveTimer = null; - - /** - * When we showed the last video ad - */ - this.lastVideoAdShowTime = -1e20; - } - - getHasAds() { - return true; - } - - getCanShowVideoAd() { - return ( - this.getHasAds() && - !this.videoAdResolveFunction && - performance.now() - this.lastVideoAdShowTime > minimumTimeBetweenVideoAdsMs - ); - } - - initialize() { - // No point to initialize everything if ads are not supported - if (!this.getHasAds()) { - return Promise.resolve(); - } - - logger.log("🎬 Initializing gamedistribution ads"); - - try { - parent.postMessage("shapezio://gd.game_loaded", "*"); - } catch (ex) { - return Promise.reject("Frame communication not allowed"); - } - - window.addEventListener( - "message", - event => { - if (event.data === "shapezio://gd.ad_started") { - console.log("🎬 Got ad started callback"); - } else if (event.data === "shapezio://gd.ad_finished") { - console.log("🎬 Got ad finished callback"); - if (this.videoAdResolveFunction) { - this.videoAdResolveFunction(); - } - } - }, - false - ); - - return Promise.resolve(); - } - - showVideoAd() { - assert(this.getHasAds(), "Called showVideoAd but ads are not supported!"); - assert(!this.videoAdResolveFunction, "Video ad still running, can not show again!"); - this.lastVideoAdShowTime = performance.now(); - - console.log("🎬 Gamedistribution: Start ad"); - try { - parent.postMessage("shapezio://gd.show_ad", "*"); - } catch (ex) { - logger.warn("🎬 Failed to send message for gd ad:", ex); - return Promise.resolve(); - } - - document.body.classList.add("externalAdOpen"); - - logger.log("Set sound volume to 0"); - this.app.sound.setMusicVolume(0); - this.app.sound.setSoundVolume(0); - - return new Promise(resolve => { - // So, wait for the remove call but also remove after N seconds - this.videoAdResolveFunction = () => { - this.videoAdResolveFunction = null; - clearTimeout(this.videoAdResolveTimer); - this.videoAdResolveTimer = null; - - // When the ad closed, also set the time - this.lastVideoAdShowTime = performance.now(); - resolve(); - }; - - this.videoAdResolveTimer = setTimeout(() => { - logger.warn("Automatically closing ad after not receiving callback"); - if (this.videoAdResolveFunction) { - this.videoAdResolveFunction(); - } - }, 35000); - }) - .catch(err => { - logger.error(this, "Error while resolving video ad:", err); - }) - .then(() => { - document.body.classList.remove("externalAdOpen"); - - logger.log("Restored sound volume"); - - this.app.sound.setMusicVolume(this.app.settings.getSetting("musicVolume")); - this.app.sound.setSoundVolume(this.app.settings.getSetting("soundVolume")); - }); - } -} diff --git a/src/js/platform/ad_providers/no_ad_provider.js b/src/js/platform/ad_providers/no_ad_provider.js deleted file mode 100644 index ca7d5db1..00000000 --- a/src/js/platform/ad_providers/no_ad_provider.js +++ /dev/null @@ -1,11 +0,0 @@ -import { AdProviderInterface } from "../ad_provider"; - -export class NoAdProvider extends AdProviderInterface { - getHasAds() { - return false; - } - - getCanShowVideoAd() { - return false; - } -} diff --git a/src/js/platform/analytics.js b/src/js/platform/analytics.js deleted file mode 100644 index 2a844522..00000000 --- a/src/js/platform/analytics.js +++ /dev/null @@ -1,41 +0,0 @@ -/* typehints:start */ -import { Application } from "../application"; -/* typehints:end */ - -export class AnalyticsInterface { - constructor(app) { - /** @type {Application} */ - this.app = app; - } - - /** - * Initializes the analytics - * @returns {Promise} - * @abstract - */ - initialize() { - abstract; - return Promise.reject(); - } - - /** - * Sets the player name for analytics - * @param {string} userName - */ - setUserContext(userName) {} - - /** - * Tracks when a new state is entered - * @param {string} stateId - */ - trackStateEnter(stateId) {} - - /** - * Tracks a new user decision - * @param {string} name - */ - trackDecision(name) {} - - // LEGACY 1.5.3 - trackUiClick() {} -} diff --git a/src/js/platform/api.js b/src/js/platform/api.js index 5dbac1da..2355e10c 100644 --- a/src/js/platform/api.js +++ b/src/js/platform/api.js @@ -1,6 +1,9 @@ /* typehints:start */ import { Application } from "../application"; /* typehints:end */ + +import { DialogWithForm } from "root/core/modal_dialog_elements"; +import { FormElementInput } from "root/core/modal_dialog_forms"; import { createLogger } from "../core/logging"; import { compressX64 } from "../core/lzstring"; import { timeoutPromise } from "../core/utils"; @@ -24,12 +27,7 @@ export class ClientAPI { } getEndpoint() { - if (G_IS_DEV) { - return "http://localhost:15001"; - } - if (window.location.host === "beta.shapez.io") { - return "https://api-staging.shapez.io"; - } + // TODO: Custom Puzzle DLC server / extract API into a mod? return "https://api.shapez.io"; } @@ -100,32 +98,51 @@ export class ClientAPI { * @returns {Promise<{token: string}>} */ apiTryLogin() { - if (!G_IS_STANDALONE) { - let token = window.localStorage.getItem("steam_sso_auth_token"); - if (!token && G_IS_DEV) { - token = window.prompt( - "Please enter the auth token for the puzzle DLC (If you have none, you can't login):" - ); - window.localStorage.setItem("dev_api_auth_token", token); - } + // TODO: Wrap the dialogs hack properly (with a meaningful error at least) + // ...AND REDUCE THIS BOILERPLATE!!! + let token = window.localStorage.getItem("dev_api_auth_token"); + + if (token !== null) { return Promise.resolve({ token }); } - return timeoutPromise(ipcRenderer.invoke("steam:get-ticket"), 15000).then( - ticket => { - logger.log("Got auth ticket:", ticket); - return this._request("/v1/public/login", { - method: "POST", - body: { - token: ticket, - }, + const state = this.app.stateMgr.getCurrentState(); + if (!("dialogs" in state)) { + return Promise.reject(new Error("Failed to show token input dialog")); + } + + /** @type {import("../game/hud/parts/modal_dialogs").HUDModalDialogs} */ + // @ts-ignore + const dialogs = state.dialogs; + + const apiTokenInput = new FormElementInput({ + id: "apiToken", + placeholder: "", + validator: value => value.trim().length > 0, + }); + + const dialog = new DialogWithForm({ + app: this.app, + title: "API Login", + desc: "Enter the Puzzle DLC API token:", + formElements: [apiTokenInput], + buttons: ["cancel", "ok:good"], + closeButton: false, + }); + + return new Promise((resolve, reject) => { + dialog.buttonSignals.ok.add(() => { + resolve({ + token: apiTokenInput.getValue(), }); - }, - err => { - logger.error("Failed to get auth ticket from steam: ", err); - throw err; - } - ); + }); + + dialog.buttonSignals.cancel.add(() => { + reject(new Error("Token input dismissed")); + }); + + dialogs.internalShowDialog(dialog); + }); } /** diff --git a/src/js/platform/browser/game_analytics.js b/src/js/platform/browser/game_analytics.js deleted file mode 100644 index 1aa37dcb..00000000 --- a/src/js/platform/browser/game_analytics.js +++ /dev/null @@ -1,358 +0,0 @@ -import { globalConfig } from "../../core/config"; -import { createLogger } from "../../core/logging"; -import { queryParamOptions } from "../../core/query_parameters"; -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"; -import { GameRoot } from "../../game/root"; -import { InGameState } from "../../states/ingame"; -import { SteamAchievementProvider } from "../electron/steam_achievement_provider"; -import { GameAnalyticsInterface } from "../game_analytics"; -import { FILE_NOT_FOUND } from "../storage"; -import { WEB_STEAM_SSO_AUTHENTICATED } from "../../core/steam_sso"; - -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 -const analyticsLocalFile = "shapez_token_123.bin"; - -const CURRENT_ABT = "abt_bsl2"; -const CURRENT_ABT_COUNT = 1; - -export class ShapezGameAnalytics extends GameAnalyticsInterface { - constructor(app) { - super(app); - this.abtVariant = "0"; - } - - get environment() { - if (G_IS_DEV) { - return "dev"; - } - - if (G_IS_STANDALONE) { - return "steam"; - } - - if (WEB_STEAM_SSO_AUTHENTICATED) { - return "prod-full"; - } - - if (G_IS_RELEASE) { - return "prod"; - } - - if (window.location.host.indexOf("alpha") >= 0) { - return "alpha"; - } else { - return "beta"; - } - } - - fetchABVariant() { - return this.app.storage.readFileAsync("shapez_" + CURRENT_ABT + ".bin").then( - abt => { - if (typeof queryParamOptions.abtVariant === "string") { - this.abtVariant = queryParamOptions.abtVariant; - logger.log("Set", CURRENT_ABT, "to (OVERRIDE) ", this.abtVariant); - } else { - this.abtVariant = abt; - logger.log("Read abtVariant:", abt); - } - }, - err => { - if (err === FILE_NOT_FOUND) { - if (typeof queryParamOptions.abtVariant === "string") { - this.abtVariant = queryParamOptions.abtVariant; - logger.log("Set", CURRENT_ABT, "to (OVERRIDE) ", this.abtVariant); - } else { - this.abtVariant = String(randomInt(0, CURRENT_ABT_COUNT - 1)); - logger.log("Set", CURRENT_ABT, "to", this.abtVariant); - } - this.app.storage.writeFileAsync("shapez_" + CURRENT_ABT + ".bin", this.abtVariant); - } - } - ); - } - - note(action) { - // TODO: Remove game analytics altogether - } - - noteMinor(action, payload = "") {} - - /** - * @returns {Promise} - */ - initialize() { - this.syncKey = null; - - // Retrieve sync key from player - return this.fetchABVariant().then(() => { - setInterval(() => this.sendTimePoints(), 60 * 1000); - - 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"); - - let authTicket = Promise.resolve(undefined); - - if (G_IS_STANDALONE) { - logger.log("Will retrieve auth ticket"); - authTicket = ipcRenderer.invoke("steam:get-ticket"); - } - - authTicket - .then( - ticket => { - logger.log("Got ticket:", ticket); - - // Perform call to get a new key from the API - return this.sendToApi("/v1/register", { - environment: this.environment, - standalone: - G_IS_STANDALONE && - this.app.achievementProvider instanceof SteamAchievementProvider, - commit: G_BUILD_COMMIT_HASH, - ticket, - }); - }, - err => { - logger.warn("Failed to get steam auth ticket for register:", err); - } - ) - .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; - } - ); - }); - } - - /** - * Makes sure a DLC is activated on steam - * @param {string} dlc - */ - activateDlc(dlc) { - logger.log("Activating dlc:", dlc); - return this.sendToApi("/v1/activate-dlc/" + dlc, {}); - } - - /** - * Sends a request to the api - * @param {string} endpoint Endpoint without base url - * @param {object} data payload - * @returns {Promise} - */ - sendToApi(endpoint, data) { - return new Promise((resolve, reject) => { - const timeout = setTimeout(() => reject("Request to " + endpoint + " timed out"), 20000); - - fetch(analyticsUrl + endpoint, { - method: "POST", - mode: "cors", - cache: "no-cache", - referrer: "no-referrer", - credentials: "omit", - headers: { - "Content-Type": "application/json", - "Accept": "application/json", - "x-api-key": globalConfig.info.analyticsApiKey, - }, - body: JSON.stringify(data), - }) - .then(res => { - clearTimeout(timeout); - if (!res.ok || res.status !== 200) { - reject("Fetch error: Bad status " + res.status); - } else { - return res.json(); - } - }) - .then(resolve) - .catch(reason => { - clearTimeout(timeout); - reject(reason); - }); - }); - } - - /** - * Sends a game event to the analytics - * @param {string} category - * @param {string} value - */ - sendGameEvent(category, value) { - if (G_IS_DEV) { - return; - } - - if (!this.syncKey) { - logger.warn("Can not send event due to missing sync key"); - return; - } - - const gameState = this.app.stateMgr.currentState; - if (!(gameState instanceof InGameState)) { - logger.warn("Trying to send analytics event outside of ingame state"); - return; - } - - const savegame = gameState.savegame; - if (!savegame) { - logger.warn("Ingame state has empty savegame"); - return; - } - - const savegameId = savegame.internalId; - if (!gameState.core) { - logger.warn("Game state has no core"); - return; - } - const root = gameState.core.root; - if (!root) { - logger.warn("Root is not initialized"); - return; - } - - if (!(root.gameMode instanceof RegularGameMode)) { - return; - } - - logger.log("Sending event", category, value); - - this.sendToApi("/v1/game-event", { - playerKey: this.syncKey, - gameKey: savegameId, - ingameTime: root.time.now(), - environment: this.environment, - category, - value, - version: G_BUILD_VERSION, - level: root.hubGoals.level, - gameDump: this.generateGameDump(root), - }).catch(err => { - console.warn("Request failed", err); - }); - } - - sendTimePoints() { - const gameState = this.app.stateMgr.currentState; - if (gameState instanceof InGameState) { - logger.log("Syncing analytics"); - this.sendGameEvent("sync", ""); - } - } - - /** - * Returns true if the shape is interesting - * @param {GameRoot} root - * @param {string} key - */ - isInterestingShape(root, key) { - if (key === root.gameMode.getBlueprintShapeKey()) { - return true; - } - - // Check if its a story goal - const levels = root.gameMode.getLevelDefinitions(); - for (let i = 0; i < levels.length; ++i) { - if (key === levels[i].shape) { - return true; - } - } - - // Check if its required to unlock an upgrade - const upgrades = root.gameMode.getUpgrades(); - for (const upgradeKey in upgrades) { - const upgradeTiers = upgrades[upgradeKey]; - for (let i = 0; i < upgradeTiers.length; ++i) { - const tier = upgradeTiers[i]; - const required = tier.required; - for (let k = 0; k < required.length; ++k) { - if (required[k].shape === key) { - return true; - } - } - } - } - - return false; - } - - /** - * Generates a game dump - * @param {GameRoot} root - */ - generateGameDump(root) { - const shapeIds = Object.keys(root.hubGoals.storedShapes).filter(key => - this.isInterestingShape(root, key) - ); - let shapes = {}; - for (let i = 0; i < shapeIds.length; ++i) { - shapes[shapeIds[i]] = root.hubGoals.storedShapes[shapeIds[i]]; - } - return { - shapes, - upgrades: root.hubGoals.upgradeLevels, - belts: root.entityMgr.getAllWithComponent(BeltComponent).length, - buildings: - root.entityMgr.getAllWithComponent(StaticMapEntityComponent).length - - root.entityMgr.getAllWithComponent(BeltComponent).length, - }; - } - - /** - */ - handleGameStarted() { - this.sendGameEvent("game_start", ""); - } - - /** - */ - handleGameResumed() { - this.sendTimePoints(); - } - - /** - * Handles the given level completed - * @param {number} level - */ - handleLevelCompleted(level) { - logger.log("Complete level", level); - this.sendGameEvent("level_complete", "" + level); - } - - /** - * Handles the given upgrade completed - * @param {string} id - * @param {number} level - */ - handleUpgradeUnlocked(id, level) { - logger.log("Unlock upgrade", id, level); - this.sendGameEvent("upgrade_unlock", id + "@" + level); - } -} diff --git a/src/js/platform/browser/google_analytics.js b/src/js/platform/browser/google_analytics.js deleted file mode 100644 index 34b75ce5..00000000 --- a/src/js/platform/browser/google_analytics.js +++ /dev/null @@ -1,78 +0,0 @@ -import { AnalyticsInterface } from "../analytics"; -import { createLogger } from "../../core/logging"; - -const logger = createLogger("ga"); - -export class GoogleAnalyticsImpl extends AnalyticsInterface { - initialize() { - this.lastUiClickTracked = -1000; - - setInterval(() => this.internalTrackAfkEvent(), 120 * 1000); - - // Analytics is already loaded in the html - return Promise.resolve(); - } - - setUserContext(userName) { - try { - if (window.gtag) { - logger.log("📊 Setting user context:", userName); - window.gtag("set", { - player: userName, - }); - } - } catch (ex) { - logger.warn("📊 Failed to set user context:", ex); - } - } - - trackStateEnter(stateId) { - const nonInteractionStates = [ - "LoginState", - "MainMenuState", - "PreloadState", - "RegisterState", - "WatchAdState", - ]; - - try { - if (window.gtag) { - logger.log("📊 Tracking state enter:", stateId); - window.gtag("event", "enter_state", { - event_category: "ui", - event_label: stateId, - non_interaction: nonInteractionStates.indexOf(stateId) >= 0, - }); - } - } catch (ex) { - logger.warn("📊 Failed to track state analytcis:", ex); - } - } - - trackDecision(decisionName) { - try { - if (window.gtag) { - logger.log("📊 Tracking decision:", decisionName); - window.gtag("event", "decision", { - event_category: "ui", - event_label: decisionName, - non_interaction: true, - }); - } - } catch (ex) { - logger.warn("📊 Failed to track state analytcis:", ex); - } - } - - /** - * Tracks an event so GA keeps track of the user - */ - internalTrackAfkEvent() { - if (window.gtag) { - window.gtag("event", "afk", { - event_category: "ping", - event_label: "timed", - }); - } - } -} diff --git a/src/js/platform/browser/wrapper.js b/src/js/platform/browser/wrapper.js index 7e34e5d0..cebb1ed9 100644 --- a/src/js/platform/browser/wrapper.js +++ b/src/js/platform/browser/wrapper.js @@ -1,11 +1,6 @@ import { globalConfig, IS_MOBILE } from "../../core/config"; import { createLogger } from "../../core/logging"; -import { queryParamOptions } from "../../core/query_parameters"; -import { WEB_STEAM_SSO_AUTHENTICATED } from "../../core/steam_sso"; import { clamp } from "../../core/utils"; -import { CrazygamesAdProvider } from "../ad_providers/crazygames"; -import { GamedistributionAdProvider } from "../ad_providers/gamedistribution"; -import { NoAdProvider } from "../ad_providers/no_ad_provider"; import { SteamAchievementProvider } from "../electron/steam_achievement_provider"; import { PlatformWrapperInterface } from "../wrapper"; import { NoAchievementProvider } from "./no_achievement_provider"; @@ -16,63 +11,7 @@ const logger = createLogger("platform/browser"); export class PlatformWrapperImplBrowser extends PlatformWrapperInterface { initialize() { - this.recaptchaTokenCallback = null; - - this.embedProvider = { - id: "shapezio-website", - adProvider: NoAdProvider, - iframed: false, - externalLinks: true, - }; - - if (!G_IS_STANDALONE && !WEB_STEAM_SSO_AUTHENTICATED && queryParamOptions.embedProvider) { - const providerId = queryParamOptions.embedProvider; - this.embedProvider.iframed = true; - - switch (providerId) { - case "armorgames": { - this.embedProvider.id = "armorgames"; - break; - } - - case "iogames.space": { - this.embedProvider.id = "iogames.space"; - break; - } - - case "miniclip": { - this.embedProvider.id = "miniclip"; - break; - } - - case "gamedistribution": { - this.embedProvider.id = "gamedistribution"; - this.embedProvider.externalLinks = false; - this.embedProvider.adProvider = GamedistributionAdProvider; - break; - } - - case "kongregate": { - this.embedProvider.id = "kongregate"; - break; - } - - case "crazygames": { - this.embedProvider.id = "crazygames"; - this.embedProvider.adProvider = CrazygamesAdProvider; - break; - } - - default: { - logger.error("Got unsupported embed provider:", providerId); - } - } - } - - logger.log("Embed provider:", this.embedProvider.id); - return this.detectStorageImplementation() - .then(() => this.initializeAdProvider()) .then(() => this.initializeAchievementProvider()) .then(() => super.initialize()); } @@ -113,7 +52,7 @@ export class PlatformWrapperImplBrowser extends PlatformWrapperInterface { } getId() { - return "browser@" + this.embedProvider.id; + return "browser"; } getUiScale() { @@ -143,54 +82,6 @@ export class PlatformWrapperImplBrowser extends PlatformWrapperInterface { window.location.reload(); } - /** - * Detects if there is an adblocker installed - * @returns {Promise} - */ - detectAdblock() { - return Promise.race([ - new Promise(resolve => { - // If the request wasn't blocked within a very short period of time, this means - // the adblocker is not active and the request was actually made -> ignore it then - setTimeout(() => resolve(false), 30); - }), - new Promise(resolve => { - fetch("https://googleads.g.doubleclick.net/pagead/id", { - method: "HEAD", - mode: "no-cors", - }) - .then(res => { - resolve(false); - }) - .catch(err => { - resolve(true); - }); - }), - ]); - } - - initializeAdProvider() { - if (G_IS_DEV && !globalConfig.debug.testAds) { - logger.log("Ads disabled in local environment"); - return Promise.resolve(); - } - - // First, detect adblocker - return this.detectAdblock().then(hasAdblocker => { - if (hasAdblocker) { - logger.log("Adblock detected"); - return; - } - - const adProvider = this.embedProvider.adProvider; - this.app.adProvider = new adProvider(this.app); - return this.app.adProvider.initialize().catch(err => { - logger.error("Failed to initialize ad provider, disabling ads:", err); - this.app.adProvider = new NoAdProvider(this.app); - }); - }); - } - initializeAchievementProvider() { if (G_IS_DEV && globalConfig.debug.testAchievements) { this.app.achievementProvider = new SteamAchievementProvider(this.app); diff --git a/src/js/platform/electron/wrapper.js b/src/js/platform/electron/wrapper.js index 6ef6de93..c510485f 100644 --- a/src/js/platform/electron/wrapper.js +++ b/src/js/platform/electron/wrapper.js @@ -57,10 +57,6 @@ export class PlatformWrapperImplElectron extends PlatformWrapperImplBrowser { window.location.reload(); } - initializeAdProvider() { - return Promise.resolve(); - } - initializeAchievementProvider() { return this.app.achievementProvider.initialize().catch(err => { logger.error("Failed to initialize achievement provider, disabling:", err); @@ -76,17 +72,6 @@ export class PlatformWrapperImplElectron extends PlatformWrapperImplBrowser { res => { logger.log("Got DLC ownership:", res); this.dlcs.puzzle = Boolean(res); - - if (this.dlcs.puzzle && !G_IS_DEV) { - this.app.gameAnalytics.activateDlc("puzzle").then( - () => { - logger.log("Puzzle DLC successfully activated"); - }, - error => { - logger.error("Failed to activate puzzle DLC:", error); - } - ); - } }, err => { logger.error("Failed to get DLC ownership:", err); diff --git a/src/js/platform/game_analytics.js b/src/js/platform/game_analytics.js deleted file mode 100644 index 19fdf752..00000000 --- a/src/js/platform/game_analytics.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @typedef {import("../application").Application} Application - */ - -export class GameAnalyticsInterface { - constructor(app) { - /** @type {Application} */ - this.app = app; - } - - /** - * Initializes the analytics - * @returns {Promise} - * @abstract - */ - initialize() { - abstract; - return Promise.reject(); - } - - /** - * Handles a new game which was started - */ - handleGameStarted() {} - - /** - * Handles a resumed game - */ - handleGameResumed() {} - - /** - * Handles the given level completed - * @param {number} level - */ - handleLevelCompleted(level) {} - - /** - * Handles the given upgrade completed - * @param {string} id - * @param {number} level - */ - handleUpgradeUnlocked(id, level) {} - - /** - * Activates a DLC - * @param {string} dlc - * @abstract - */ - activateDlc(dlc) { - abstract; - return Promise.resolve(); - } -} diff --git a/src/js/platform/wrapper.js b/src/js/platform/wrapper.js index e0a896fb..0db580d2 100644 --- a/src/js/platform/wrapper.js +++ b/src/js/platform/wrapper.js @@ -42,14 +42,6 @@ export class PlatformWrapperInterface { return Promise.resolve(); } - /** - * Should initialize the apps ad provider in case supported - * @returns {Promise} - */ - initializeAdProvider() { - return Promise.resolve(); - } - /** * Should return the minimum supported zoom level * @returns {number} diff --git a/src/js/profile/setting_types.js b/src/js/profile/setting_types.js index ccc90d70..975d7f99 100644 --- a/src/js/profile/setting_types.js +++ b/src/js/profile/setting_types.js @@ -3,7 +3,6 @@ import { Application } from "../application"; /* typehints:end */ import { createLogger } from "../core/logging"; -import { WEB_STEAM_SSO_AUTHENTICATED } from "../core/steam_sso"; import { T } from "../translations"; const logger = createLogger("setting_types"); @@ -153,13 +152,7 @@ export class EnumSetting extends BaseSetting { return `
- ${ - available - ? "" - : `${ - WEB_STEAM_SSO_AUTHENTICATED ? "" : T.demo.settingNotAvailable - }` - } + ${available ? "" : `${T.demo.settingNotAvailable}`}
@@ -234,16 +227,11 @@ export class BoolSetting extends BaseSetting { * @param {Application} app */ getHtml(app) { + // TODO: Rewrite the settings system entirely const available = this.getIsAvailable(app); return `
- ${ - available - ? "" - : `${ - WEB_STEAM_SSO_AUTHENTICATED ? "" : T.demo.settingNotAvailable - }` - } + ${available ? "" : `${T.demo.settingNotAvailable}`}
@@ -303,13 +291,7 @@ export class RangeSetting extends BaseSetting { const available = this.getIsAvailable(app); return `
- ${ - available - ? "" - : `${ - WEB_STEAM_SSO_AUTHENTICATED ? "" : T.demo.settingNotAvailable - }` - } + ${available ? "" : `${T.demo.settingNotAvailable}`}
diff --git a/src/js/states/ingame.js b/src/js/states/ingame.js index ec410b1a..0621706e 100644 --- a/src/js/states/ingame.js +++ b/src/js/states/ingame.js @@ -262,7 +262,6 @@ export class InGameState extends GameState { if (this.savegame.hasGameDump()) { this.stage4bResumeGame(); } else { - this.app.gameAnalytics.handleGameStarted(); this.stage4aInitEmptyGame(); } }, @@ -300,7 +299,6 @@ export class InGameState extends GameState { this.onInitializationFailure("Savegame is corrupt and can not be restored."); return; } - this.app.gameAnalytics.handleGameResumed(); this.stage5FirstUpdate(); } } diff --git a/src/js/states/main_menu.js b/src/js/states/main_menu.js index 44832414..148a10a7 100644 --- a/src/js/states/main_menu.js +++ b/src/js/states/main_menu.js @@ -1,11 +1,9 @@ import { cachebust } from "../core/cachebust"; -import { globalConfig, openStandaloneLink, THIRDPARTY_URLS } from "../core/config"; +import { globalConfig, THIRDPARTY_URLS } from "../core/config"; import { GameState } from "../core/game_state"; import { DialogWithForm } from "../core/modal_dialog_elements"; import { FormElementInput } from "../core/modal_dialog_forms"; import { ReadWriteProxy } from "../core/read_write_proxy"; -import { STOP_PROPAGATION } from "../core/signal"; -import { WEB_STEAM_SSO_AUTHENTICATED } from "../core/steam_sso"; import { formatSecondsToTimeAgo, generateFileDownload, @@ -19,7 +17,6 @@ import { } from "../core/utils"; import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs"; import { MODS } from "../mods/modloader"; -import { PlatformWrapperImplBrowser } from "../platform/browser/wrapper"; import { PlatformWrapperImplElectron } from "../platform/electron/wrapper"; import { Savegame } from "../savegame/savegame"; import { T } from "../translations"; @@ -32,40 +29,19 @@ import { T } from "../translations"; export class MainMenuState extends GameState { constructor() { super("MainMenuState"); - - this.refreshInterval = null; } getInnerHTML() { - const showExitAppButton = G_IS_STANDALONE; - const showPuzzleDLC = G_IS_STANDALONE || WEB_STEAM_SSO_AUTHENTICATED; const hasMods = MODS.anyModsActive(); - let showExternalLinks = true; - - if (!G_IS_STANDALONE) { - const wrapper = /** @type {PlatformWrapperImplBrowser} */ (this.app.platformWrapper); - if (!wrapper.embedProvider.externalLinks) { - showExternalLinks = false; - } - } - - const ownsPuzzleDLC = - WEB_STEAM_SSO_AUTHENTICATED || - (G_IS_STANDALONE && - /** @type { PlatformWrapperImplElectron}*/ (this.app.platformWrapper).dlcs.puzzle); - - const showShapez2 = showExternalLinks && MODS.mods.length === 0; - return `
- ${showExitAppButton ? `` : ""} +
- @@ -78,84 +54,25 @@ export class MainMenuState extends GameState { ${/*showUpdateLabel ? `MODS UPDATE!` : ""*/ ""}
-
+
- ${ - G_IS_STANDALONE || !WEB_STEAM_SSO_AUTHENTICATED - ? `
- ${ - G_IS_STANDALONE - ? T.mainMenu.playFullVersionStandalone - : T.mainMenu.playFullVersionV2 - } - Sign in -
` - : "" - } - ${ - WEB_STEAM_SSO_AUTHENTICATED - ? ` -
- ${T.mainMenu.playingFullVersion} - ${T.mainMenu.logout} - -
- ` - : "" - } - - -
- ${ - showShapez2 - ? `
-
We are currently prototyping Shapez 2!
- -
` - : "" - } - ${ - showPuzzleDLC + !hasMods ? ` - - ${ - ownsPuzzleDLC && !hasMods - ? ` -
- -
` - : "" - } - - ${ - !ownsPuzzleDLC && !hasMods - ? ` -
-

${T.mainMenu.puzzleDlcText}

- -
` - : "" - } - - - - ` +
+ +
` : "" } - ${ hasMods ? ` -

${T.mods.title}

@@ -177,96 +94,51 @@ export class MainMenuState extends GameState {
${T.mainMenu.mods.warningPuzzleDLC}
- -
` : "" } -
- -
-