mirror of
https://github.com/tobspr/shapez.io.git
synced 2025-06-06 17:44:33 +00:00
Allow playing full version in browser via steam sso
This commit is contained in:
parent
b446a4a915
commit
145f734907
@ -2,6 +2,20 @@
|
|||||||
var loadTimeout = null;
|
var loadTimeout = null;
|
||||||
var callbackDone = false;
|
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
|
// Catch load errors
|
||||||
|
|
||||||
function errorHandler(event, source, lineno, colno, error) {
|
function errorHandler(event, source, lineno, colno, error) {
|
||||||
|
BIN
res/ui/steam_signin.png
Normal file
BIN
res/ui/steam_signin.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
@ -49,6 +49,45 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.steamSso {
|
||||||
|
position: fixed;
|
||||||
|
@include S(top, 0px);
|
||||||
|
@include S(left, 10px);
|
||||||
|
background: rgba(88, 92, 102, 0.4);
|
||||||
|
@include SuperSmallText;
|
||||||
|
color: #fff;
|
||||||
|
@include S(max-width, 150px);
|
||||||
|
@include S(border-radius, $globalBorderRadius);
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
@include S(padding, 5px);
|
||||||
|
box-shadow: 0 D(5px) D(15px) rgba(#000, 0.1);
|
||||||
|
display: flex;
|
||||||
|
color: #000;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
a.ssoSignIn {
|
||||||
|
background: #171a23 uiResource("steam_signin.png") center center / contain no-repeat;
|
||||||
|
@include S(width, 110px);
|
||||||
|
@include S(height, 19px);
|
||||||
|
display: inline-flex;
|
||||||
|
@include S(border-radius, $globalBorderRadius);
|
||||||
|
@include S(margin-top, 3px);
|
||||||
|
overflow: hidden;
|
||||||
|
text-indent: -999em;
|
||||||
|
&:hover {
|
||||||
|
opacity: 0.95;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include DarkThemeOverride {
|
||||||
|
color: #333539;
|
||||||
|
a {
|
||||||
|
color: #111;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.fullscreenBackgroundVideo {
|
.fullscreenBackgroundVideo {
|
||||||
// display: none !important;
|
// display: none !important;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
|
@ -24,6 +24,9 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
text-align: center;
|
||||||
|
max-width: 80%;
|
||||||
|
align-self: center;
|
||||||
|
|
||||||
.steamLink {
|
.steamLink {
|
||||||
@include S(height, 50px);
|
@include S(height, 50px);
|
||||||
|
@ -181,10 +181,16 @@
|
|||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
z-index: 100;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
background: rgba(#fff, 0.5);
|
background: rgba(#fff, 0.5);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: $colorRedBright;
|
color: $colorRedBright;
|
||||||
|
@include S(border-radius, $globalBorderRadius);
|
||||||
|
|
||||||
|
@include DarkThemeOverride {
|
||||||
|
background: rgba(#55585f, 0.95);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ import { Application } from "../application";
|
|||||||
/* typehints:end */
|
/* typehints:end */
|
||||||
import { ExplainedResult } from "./explained_result";
|
import { ExplainedResult } from "./explained_result";
|
||||||
import { ReadWriteProxy } from "./read_write_proxy";
|
import { ReadWriteProxy } from "./read_write_proxy";
|
||||||
|
import { WEB_STEAM_SSO_AUTHENTICATED } from "./steam_sso";
|
||||||
|
|
||||||
export class RestrictionManager extends ReadWriteProxy {
|
export class RestrictionManager extends ReadWriteProxy {
|
||||||
/**
|
/**
|
||||||
@ -64,6 +65,10 @@ export class RestrictionManager extends ReadWriteProxy {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (WEB_STEAM_SSO_AUTHENTICATED) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (G_IS_DEV) {
|
if (G_IS_DEV) {
|
||||||
return typeof window !== "undefined" && window.location.search.indexOf("demo") >= 0;
|
return typeof window !== "undefined" && window.location.search.indexOf("demo") >= 0;
|
||||||
}
|
}
|
||||||
|
81
src/js/core/steam_sso.js
Normal file
81
src/js/core/steam_sso.js
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
await verify();
|
||||||
|
setInterval(verify, 120000);
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import { T } from "../translations";
|
import { T } from "../translations";
|
||||||
import { rando } from "@nastyox/rando.js";
|
import { rando } from "@nastyox/rando.js";
|
||||||
|
import { WEB_STEAM_SSO_AUTHENTICATED } from "./steam_sso";
|
||||||
|
|
||||||
const bigNumberSuffixTranslationKeys = ["thousands", "millions", "billions", "trillions"];
|
const bigNumberSuffixTranslationKeys = ["thousands", "millions", "billions", "trillions"];
|
||||||
|
|
||||||
@ -764,7 +765,7 @@ export function getLogoSprite() {
|
|||||||
return "logo_cn.png";
|
return "logo_cn.png";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (G_IS_STANDALONE) {
|
if (G_IS_STANDALONE || WEB_STEAM_SSO_AUTHENTICATED) {
|
||||||
return "logo.png";
|
return "logo.png";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -777,6 +778,7 @@ export function getLogoSprite() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Rejects a promise after X ms
|
* Rejects a promise after X ms
|
||||||
|
* @param {Promise} promise
|
||||||
*/
|
*/
|
||||||
export function timeoutPromise(promise, timeout = 30000) {
|
export function timeoutPromise(promise, timeout = 30000) {
|
||||||
return Promise.race([
|
return Promise.race([
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { WEB_STEAM_SSO_AUTHENTICATED } from "../../core/steam_sso";
|
||||||
import { enumHubGoalRewards } from "../tutorial_goals";
|
import { enumHubGoalRewards } from "../tutorial_goals";
|
||||||
|
|
||||||
export const finalGameShape = "RuCw--Cw:----Ru--";
|
export const finalGameShape = "RuCw--Cw:----Ru--";
|
||||||
@ -356,7 +357,7 @@ const STANDALONE_LEVELS = () => [
|
|||||||
export function generateLevelsForVariant() {
|
export function generateLevelsForVariant() {
|
||||||
if (G_IS_STEAM_DEMO) {
|
if (G_IS_STEAM_DEMO) {
|
||||||
return STEAM_DEMO_LEVELS();
|
return STEAM_DEMO_LEVELS();
|
||||||
} else if (G_IS_STANDALONE) {
|
} else if (G_IS_STANDALONE || WEB_STEAM_SSO_AUTHENTICATED) {
|
||||||
return STANDALONE_LEVELS();
|
return STANDALONE_LEVELS();
|
||||||
}
|
}
|
||||||
return WEB_DEMO_LEVELS();
|
return WEB_DEMO_LEVELS();
|
||||||
|
@ -36,7 +36,8 @@ import { HUDInteractiveTutorial } from "../hud/parts/interactive_tutorial";
|
|||||||
import { MetaBlockBuilding } from "../buildings/block";
|
import { MetaBlockBuilding } from "../buildings/block";
|
||||||
import { MetaItemProducerBuilding } from "../buildings/item_producer";
|
import { MetaItemProducerBuilding } from "../buildings/item_producer";
|
||||||
import { MOD_SIGNALS } from "../../mods/mod_signals";
|
import { MOD_SIGNALS } from "../../mods/mod_signals";
|
||||||
import { finalGameShape, generateLevelsForVariant, LevelSetVariant } from "./levels";
|
import { finalGameShape, generateLevelsForVariant } from "./levels";
|
||||||
|
import { WEB_STEAM_SSO_AUTHENTICATED } from "../../core/steam_sso";
|
||||||
|
|
||||||
/** @typedef {{
|
/** @typedef {{
|
||||||
* shape: string,
|
* shape: string,
|
||||||
@ -377,7 +378,7 @@ export class RegularGameMode extends GameMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get difficultyMultiplicator() {
|
get difficultyMultiplicator() {
|
||||||
if (G_IS_STANDALONE) {
|
if (G_IS_STANDALONE || WEB_STEAM_SSO_AUTHENTICATED) {
|
||||||
if (G_IS_STEAM_DEMO) {
|
if (G_IS_STEAM_DEMO) {
|
||||||
return 0.75;
|
return 0.75;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import { Application } from "../application";
|
|||||||
/* typehints:end */
|
/* typehints:end */
|
||||||
import { createLogger } from "../core/logging";
|
import { createLogger } from "../core/logging";
|
||||||
import { compressX64 } from "../core/lzstring";
|
import { compressX64 } from "../core/lzstring";
|
||||||
|
import { timeoutPromise } from "../core/utils";
|
||||||
import { T } from "../translations";
|
import { T } from "../translations";
|
||||||
|
|
||||||
const logger = createLogger("puzzle-api");
|
const logger = createLogger("puzzle-api");
|
||||||
@ -53,23 +54,23 @@ export class ClientAPI {
|
|||||||
headers["x-token"] = this.token;
|
headers["x-token"] = this.token;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.race([
|
return timeoutPromise(
|
||||||
fetch(this.getEndpoint() + endpoint, {
|
fetch(this.getEndpoint() + endpoint, {
|
||||||
cache: "no-cache",
|
cache: "no-cache",
|
||||||
mode: "cors",
|
mode: "cors",
|
||||||
headers,
|
headers,
|
||||||
method: options.method || "GET",
|
method: options.method || "GET",
|
||||||
body: options.body ? JSON.stringify(options.body) : undefined,
|
body: options.body ? JSON.stringify(options.body) : undefined,
|
||||||
|
}),
|
||||||
|
15000
|
||||||
|
)
|
||||||
|
.then(res => {
|
||||||
|
if (res.status !== 200) {
|
||||||
|
throw "bad-status: " + res.status + " / " + res.statusText;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
})
|
})
|
||||||
.then(res => {
|
.then(res => res.json())
|
||||||
if (res.status !== 200) {
|
|
||||||
throw "bad-status: " + res.status + " / " + res.statusText;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
})
|
|
||||||
.then(res => res.json()),
|
|
||||||
new Promise((resolve, reject) => setTimeout(() => reject("timeout"), 15000)),
|
|
||||||
])
|
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data && data.error) {
|
if (data && data.error) {
|
||||||
logger.warn("Got error from api:", data);
|
logger.warn("Got error from api:", data);
|
||||||
@ -100,22 +101,17 @@ export class ClientAPI {
|
|||||||
*/
|
*/
|
||||||
apiTryLogin() {
|
apiTryLogin() {
|
||||||
if (!G_IS_STANDALONE) {
|
if (!G_IS_STANDALONE) {
|
||||||
let token = window.localStorage.getItem("dev_api_auth_token");
|
let token = window.localStorage.getItem("steam_sso_auth_token");
|
||||||
if (!token) {
|
if (!token && G_IS_DEV) {
|
||||||
token = window.prompt(
|
token = window.prompt(
|
||||||
"Please enter the auth token for the puzzle DLC (If you have none, you can't login):"
|
"Please enter the auth token for the puzzle DLC (If you have none, you can't login):"
|
||||||
);
|
);
|
||||||
}
|
|
||||||
if (token) {
|
|
||||||
window.localStorage.setItem("dev_api_auth_token", token);
|
window.localStorage.setItem("dev_api_auth_token", token);
|
||||||
}
|
}
|
||||||
return Promise.resolve({ token });
|
return Promise.resolve({ token });
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.race([
|
return timeoutPromise(ipcRenderer.invoke("steam:get-ticket"), 15000).then(
|
||||||
ipcRenderer.invoke("steam:get-ticket"),
|
|
||||||
new Promise((resolve, reject) => setTimeout(() => reject("timeout"), 15000)),
|
|
||||||
]).then(
|
|
||||||
ticket => {
|
ticket => {
|
||||||
logger.log("Got auth ticket:", ticket);
|
logger.log("Got auth ticket:", ticket);
|
||||||
return this._request("/v1/public/login", {
|
return this._request("/v1/public/login", {
|
||||||
|
@ -13,6 +13,7 @@ import { FILE_NOT_FOUND } from "../storage";
|
|||||||
|
|
||||||
import OR from "@openreplay/tracker";
|
import OR from "@openreplay/tracker";
|
||||||
import OR_fetch from "@openreplay/tracker-fetch";
|
import OR_fetch from "@openreplay/tracker-fetch";
|
||||||
|
import { WEB_STEAM_SSO_AUTHENTICATED } from "../../core/steam_sso";
|
||||||
|
|
||||||
let eventConnector;
|
let eventConnector;
|
||||||
if (!G_IS_STANDALONE && !G_IS_DEV) {
|
if (!G_IS_STANDALONE && !G_IS_DEV) {
|
||||||
@ -57,6 +58,10 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface {
|
|||||||
return "steam";
|
return "steam";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (WEB_STEAM_SSO_AUTHENTICATED) {
|
||||||
|
return "prod-full";
|
||||||
|
}
|
||||||
|
|
||||||
if (G_IS_RELEASE) {
|
if (G_IS_RELEASE) {
|
||||||
return "prod";
|
return "prod";
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { globalConfig, IS_MOBILE } from "../../core/config";
|
import { globalConfig, IS_MOBILE } from "../../core/config";
|
||||||
import { createLogger } from "../../core/logging";
|
import { createLogger } from "../../core/logging";
|
||||||
import { queryParamOptions } from "../../core/query_parameters";
|
import { queryParamOptions } from "../../core/query_parameters";
|
||||||
|
import { WEB_STEAM_SSO_AUTHENTICATED } from "../../core/steam_sso";
|
||||||
import { clamp } from "../../core/utils";
|
import { clamp } from "../../core/utils";
|
||||||
import { GamedistributionAdProvider } from "../ad_providers/gamedistribution";
|
import { GamedistributionAdProvider } from "../ad_providers/gamedistribution";
|
||||||
import { NoAdProvider } from "../ad_providers/no_ad_provider";
|
import { NoAdProvider } from "../ad_providers/no_ad_provider";
|
||||||
@ -24,7 +25,7 @@ export class PlatformWrapperImplBrowser extends PlatformWrapperInterface {
|
|||||||
iogLink: true,
|
iogLink: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!G_IS_STANDALONE && queryParamOptions.embedProvider) {
|
if (!G_IS_STANDALONE && !WEB_STEAM_SSO_AUTHENTICATED && queryParamOptions.embedProvider) {
|
||||||
const providerId = queryParamOptions.embedProvider;
|
const providerId = queryParamOptions.embedProvider;
|
||||||
this.embedProvider.iframed = true;
|
this.embedProvider.iframed = true;
|
||||||
this.embedProvider.iogLink = false;
|
this.embedProvider.iogLink = false;
|
||||||
|
@ -511,6 +511,12 @@ export class ApplicationSettings extends ReadWriteProxy {
|
|||||||
return ExplainedResult.bad("Bad settings object");
|
return ExplainedResult.bad("Bad settings object");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MODS
|
||||||
|
if (!THEMES[data.settings.theme] || !this.app.restrictionMgr.getHasExtendedSettings()) {
|
||||||
|
console.log("Resetting theme because its no longer available: " + data.settings.theme);
|
||||||
|
data.settings.theme = "light";
|
||||||
|
}
|
||||||
|
|
||||||
const settings = data.settings;
|
const settings = data.settings;
|
||||||
|
|
||||||
for (let i = 0; i < this.settingHandles.length; ++i) {
|
for (let i = 0; i < this.settingHandles.length; ++i) {
|
||||||
|
@ -3,6 +3,7 @@ import { Application } from "../application";
|
|||||||
/* typehints:end */
|
/* typehints:end */
|
||||||
|
|
||||||
import { createLogger } from "../core/logging";
|
import { createLogger } from "../core/logging";
|
||||||
|
import { WEB_STEAM_SSO_AUTHENTICATED } from "../core/steam_sso";
|
||||||
import { T } from "../translations";
|
import { T } from "../translations";
|
||||||
|
|
||||||
const logger = createLogger("setting_types");
|
const logger = createLogger("setting_types");
|
||||||
@ -149,9 +150,16 @@ export class EnumSetting extends BaseSetting {
|
|||||||
*/
|
*/
|
||||||
getHtml(app) {
|
getHtml(app) {
|
||||||
const available = this.getIsAvailable(app);
|
const available = this.getIsAvailable(app);
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="setting cardbox ${available ? "enabled" : "disabled"}">
|
<div class="setting cardbox ${available ? "enabled" : "disabled"}">
|
||||||
${available ? "" : `<span class="standaloneOnlyHint">${T.demo.settingNotAvailable}</span>`}
|
${
|
||||||
|
available
|
||||||
|
? ""
|
||||||
|
: `<span class="standaloneOnlyHint">${
|
||||||
|
WEB_STEAM_SSO_AUTHENTICATED ? "" : T.demo.settingNotAvailable
|
||||||
|
}</span>`
|
||||||
|
}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label>${T.settings.labels[this.id].title}</label>
|
<label>${T.settings.labels[this.id].title}</label>
|
||||||
<div class="value enum" data-setting="${this.id}"></div>
|
<div class="value enum" data-setting="${this.id}"></div>
|
||||||
@ -229,7 +237,13 @@ export class BoolSetting extends BaseSetting {
|
|||||||
const available = this.getIsAvailable(app);
|
const available = this.getIsAvailable(app);
|
||||||
return `
|
return `
|
||||||
<div class="setting cardbox ${available ? "enabled" : "disabled"}">
|
<div class="setting cardbox ${available ? "enabled" : "disabled"}">
|
||||||
${available ? "" : `<span class="standaloneOnlyHint">${T.demo.settingNotAvailable}</span>`}
|
${
|
||||||
|
available
|
||||||
|
? ""
|
||||||
|
: `<span class="standaloneOnlyHint">${
|
||||||
|
WEB_STEAM_SSO_AUTHENTICATED ? "" : T.demo.settingNotAvailable
|
||||||
|
}</span>`
|
||||||
|
}
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label>${T.settings.labels[this.id].title}</label>
|
<label>${T.settings.labels[this.id].title}</label>
|
||||||
@ -289,7 +303,13 @@ export class RangeSetting extends BaseSetting {
|
|||||||
const available = this.getIsAvailable(app);
|
const available = this.getIsAvailable(app);
|
||||||
return `
|
return `
|
||||||
<div class="setting cardbox ${available ? "enabled" : "disabled"}">
|
<div class="setting cardbox ${available ? "enabled" : "disabled"}">
|
||||||
${available ? "" : `<span class="standaloneOnlyHint">${T.demo.settingNotAvailable}</span>`}
|
${
|
||||||
|
available
|
||||||
|
? ""
|
||||||
|
: `<span class="standaloneOnlyHint">${
|
||||||
|
WEB_STEAM_SSO_AUTHENTICATED ? "" : T.demo.settingNotAvailable
|
||||||
|
}</span>`
|
||||||
|
}
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label>${T.settings.labels[this.id].title}</label>
|
<label>${T.settings.labels[this.id].title}</label>
|
||||||
|
@ -4,6 +4,7 @@ import { GameState } from "../core/game_state";
|
|||||||
import { DialogWithForm } from "../core/modal_dialog_elements";
|
import { DialogWithForm } from "../core/modal_dialog_elements";
|
||||||
import { FormElementInput } from "../core/modal_dialog_forms";
|
import { FormElementInput } from "../core/modal_dialog_forms";
|
||||||
import { ReadWriteProxy } from "../core/read_write_proxy";
|
import { ReadWriteProxy } from "../core/read_write_proxy";
|
||||||
|
import { WEB_STEAM_SSO_AUTHENTICATED } from "../core/steam_sso";
|
||||||
import {
|
import {
|
||||||
formatSecondsToTimeAgo,
|
formatSecondsToTimeAgo,
|
||||||
generateFileDownload,
|
generateFileDownload,
|
||||||
@ -39,7 +40,8 @@ export class MainMenuState extends GameState {
|
|||||||
getInnerHTML() {
|
getInnerHTML() {
|
||||||
const showLanguageIcon = !G_CHINA_VERSION && !G_WEGAME_VERSION;
|
const showLanguageIcon = !G_CHINA_VERSION && !G_WEGAME_VERSION;
|
||||||
const showExitAppButton = G_IS_STANDALONE;
|
const showExitAppButton = G_IS_STANDALONE;
|
||||||
const showPuzzleDLC = !G_WEGAME_VERSION && G_IS_STANDALONE && !G_IS_STEAM_DEMO;
|
const showPuzzleDLC =
|
||||||
|
!G_WEGAME_VERSION && (G_IS_STANDALONE || WEB_STEAM_SSO_AUTHENTICATED) && !G_IS_STEAM_DEMO;
|
||||||
const showWegameFooter = G_WEGAME_VERSION;
|
const showWegameFooter = G_WEGAME_VERSION;
|
||||||
const hasMods = MODS.anyModsActive();
|
const hasMods = MODS.anyModsActive();
|
||||||
|
|
||||||
@ -117,6 +119,26 @@ export class MainMenuState extends GameState {
|
|||||||
${showExitAppButton ? `<button class="exitAppButton" aria-label="Exit App"></button>` : ""}
|
${showExitAppButton ? `<button class="exitAppButton" aria-label="Exit App"></button>` : ""}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
${
|
||||||
|
G_IS_STANDALONE || WEB_STEAM_SSO_AUTHENTICATED
|
||||||
|
? ""
|
||||||
|
: `<div class="steamSso">
|
||||||
|
${T.mainMenu.playFullVersion}
|
||||||
|
<a class="ssoSignIn" href="${
|
||||||
|
this.app.clientApi.getEndpoint() + "/v1/noauth/steam-sso"
|
||||||
|
}">Sign in</a>
|
||||||
|
</div>`
|
||||||
|
}
|
||||||
|
${
|
||||||
|
WEB_STEAM_SSO_AUTHENTICATED
|
||||||
|
? `
|
||||||
|
<div class="steamSso">${T.mainMenu.playingFullVersion}
|
||||||
|
<a href="?sso_logout_silent">${T.mainMenu.logout}</a>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
|
||||||
<video autoplay muted loop class="fullscreenBackgroundVideo">
|
<video autoplay muted loop class="fullscreenBackgroundVideo">
|
||||||
<source src="${cachebust("res/bg_render.webm")}" type="video/webm">
|
<source src="${cachebust("res/bg_render.webm")}" type="video/webm">
|
||||||
</video>
|
</video>
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
import { openStandaloneLink, THIRDPARTY_URLS } from "../core/config";
|
import { openStandaloneLink, THIRDPARTY_URLS } from "../core/config";
|
||||||
import { queryParamOptions } from "../core/query_parameters";
|
import { WEB_STEAM_SSO_AUTHENTICATED } from "../core/steam_sso";
|
||||||
import { TextualGameState } from "../core/textual_game_state";
|
import { TextualGameState } from "../core/textual_game_state";
|
||||||
import { MODS } from "../mods/modloader";
|
import { MODS } from "../mods/modloader";
|
||||||
import { T } from "../translations";
|
import { T } from "../translations";
|
||||||
|
|
||||||
const MODS_SUPPORTED =
|
|
||||||
!G_IS_STEAM_DEMO && (G_IS_STANDALONE || (G_IS_DEV && !window.location.href.includes("demo")));
|
|
||||||
|
|
||||||
export class ModsState extends TextualGameState {
|
export class ModsState extends TextualGameState {
|
||||||
constructor() {
|
constructor() {
|
||||||
super("ModsState");
|
super("ModsState");
|
||||||
@ -16,6 +13,14 @@ export class ModsState extends TextualGameState {
|
|||||||
return T.mods.title;
|
return T.mods.title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get modsSupported() {
|
||||||
|
return (
|
||||||
|
!WEB_STEAM_SSO_AUTHENTICATED &&
|
||||||
|
!G_IS_STEAM_DEMO &&
|
||||||
|
(G_IS_STANDALONE || (G_IS_DEV && !window.location.href.includes("demo")))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
internalGetFullHtml() {
|
internalGetFullHtml() {
|
||||||
let headerHtml = `
|
let headerHtml = `
|
||||||
<div class="headerBar">
|
<div class="headerBar">
|
||||||
@ -23,12 +28,12 @@ export class ModsState extends TextualGameState {
|
|||||||
|
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
${
|
${
|
||||||
MODS_SUPPORTED && MODS.mods.length > 0
|
this.modsSupported && MODS.mods.length > 0
|
||||||
? `<button class="styledButton browseMods">${T.mods.browseMods}</button>`
|
? `<button class="styledButton browseMods">${T.mods.browseMods}</button>`
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
${
|
${
|
||||||
MODS_SUPPORTED
|
this.modsSupported
|
||||||
? `<button class="styledButton openModsFolder">${T.mods.openFolder}</button>`
|
? `<button class="styledButton openModsFolder">${T.mods.openFolder}</button>`
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
@ -45,11 +50,11 @@ export class ModsState extends TextualGameState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getMainContentHTML() {
|
getMainContentHTML() {
|
||||||
if (!MODS_SUPPORTED) {
|
if (!this.modsSupported) {
|
||||||
return `
|
return `
|
||||||
<div class="noModSupport">
|
<div class="noModSupport">
|
||||||
|
|
||||||
<p>${T.mods.noModSupport}</p>
|
<p>${WEB_STEAM_SSO_AUTHENTICATED ? T.mods.browserNoSupport : T.mods.noModSupport}</p>
|
||||||
<br>
|
<br>
|
||||||
<button class="styledButton browseMods">${T.mods.browseMods}</button>
|
<button class="styledButton browseMods">${T.mods.browseMods}</button>
|
||||||
<a href="#" class="steamLink steam_dlbtn_0" target="_blank">Get on Steam!</a>
|
<a href="#" class="steamLink steam_dlbtn_0" target="_blank">Get on Steam!</a>
|
||||||
|
@ -3,7 +3,8 @@ import { cachebust } from "../core/cachebust";
|
|||||||
import { globalConfig } from "../core/config";
|
import { globalConfig } from "../core/config";
|
||||||
import { GameState } from "../core/game_state";
|
import { GameState } from "../core/game_state";
|
||||||
import { createLogger } from "../core/logging";
|
import { createLogger } from "../core/logging";
|
||||||
import { getLogoSprite } from "../core/utils";
|
import { authorizeViaSSOToken } from "../core/steam_sso";
|
||||||
|
import { getLogoSprite, timeoutPromise } from "../core/utils";
|
||||||
import { getRandomHint } from "../game/hints";
|
import { getRandomHint } from "../game/hints";
|
||||||
import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs";
|
import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs";
|
||||||
import { PlatformWrapperImplBrowser } from "../platform/browser/wrapper";
|
import { PlatformWrapperImplBrowser } from "../platform/browser/wrapper";
|
||||||
@ -45,12 +46,7 @@ export class PreloadState extends GameState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fetchDiscounts() {
|
async fetchDiscounts() {
|
||||||
await Promise.race([
|
await timeoutPromise(
|
||||||
new Promise((resolve, reject) => {
|
|
||||||
setTimeout(() => {
|
|
||||||
reject("Failed to resolve steam discounts within timeout");
|
|
||||||
}, 2000);
|
|
||||||
}),
|
|
||||||
fetch("https://analytics.shapez.io/v1/discounts")
|
fetch("https://analytics.shapez.io/v1/discounts")
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
@ -59,7 +55,8 @@ export class PreloadState extends GameState {
|
|||||||
);
|
);
|
||||||
logger.log("Fetched current discount:", globalConfig.currentDiscount);
|
logger.log("Fetched current discount:", globalConfig.currentDiscount);
|
||||||
}),
|
}),
|
||||||
]).catch(err => {
|
2000
|
||||||
|
).catch(err => {
|
||||||
logger.warn("Failed to fetch current discount:", err);
|
logger.warn("Failed to fetch current discount:", err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -72,6 +69,8 @@ export class PreloadState extends GameState {
|
|||||||
this.setStatus("Booting")
|
this.setStatus("Booting")
|
||||||
|
|
||||||
.then(() => this.setStatus("Creating platform wrapper", 3))
|
.then(() => this.setStatus("Creating platform wrapper", 3))
|
||||||
|
.then(() => authorizeViaSSOToken(this.app, this.dialogs))
|
||||||
|
|
||||||
.then(() => this.app.platformWrapper.initialize())
|
.then(() => this.app.platformWrapper.initialize())
|
||||||
|
|
||||||
.then(() => this.setStatus("Initializing local storage", 6))
|
.then(() => this.setStatus("Initializing local storage", 6))
|
||||||
|
@ -131,6 +131,10 @@ mainMenu:
|
|||||||
helpTranslate: Help translate!
|
helpTranslate: Help translate!
|
||||||
madeBy: Made by <author-link>
|
madeBy: Made by <author-link>
|
||||||
|
|
||||||
|
playFullVersion: Sign in to play the full version in your Browser!
|
||||||
|
playingFullVersion: You are now playing the full version! Not all features work yet, but I'm working on it!
|
||||||
|
logout: Logout
|
||||||
|
|
||||||
# This is shown when using firefox and other browsers which are not supported.
|
# This is shown when using firefox and other browsers which are not supported.
|
||||||
browserWarning: >-
|
browserWarning: >-
|
||||||
Sorry, but the game is known to run slowly on your browser! Get the full version or download Google Chrome for the full experience.
|
Sorry, but the game is known to run slowly on your browser! Get the full version or download Google Chrome for the full experience.
|
||||||
@ -468,6 +472,19 @@ dialogs:
|
|||||||
<br><br>
|
<br><br>
|
||||||
Error Message:
|
Error Message:
|
||||||
|
|
||||||
|
steamSsoError:
|
||||||
|
title: Full Version Logout
|
||||||
|
desc: >-
|
||||||
|
You have been logged out from the Full Browser Version since either your network connection is unstable or you are playing on another device.<br><br>
|
||||||
|
Please make sure you don't have shapez open in any other browser tab or another computer with the same Steam account.<br><br>
|
||||||
|
You can login again in the main menu.
|
||||||
|
|
||||||
|
steamSsoNoOwnership:
|
||||||
|
title: Full Edition not owned
|
||||||
|
desc: >-
|
||||||
|
In order to play the Full Edition in your Browser, you need to own both the base game and the Puzzle DLC on your Steam account.<br><br>
|
||||||
|
Please make sure you own both, signed in with the correct Steam account and then try again.
|
||||||
|
|
||||||
ingame:
|
ingame:
|
||||||
# This is shown in the top left corner and displays useful keybindings in
|
# This is shown in the top left corner and displays useful keybindings in
|
||||||
# every situation
|
# every situation
|
||||||
@ -1155,6 +1172,7 @@ mods:
|
|||||||
modsInfo: >-
|
modsInfo: >-
|
||||||
To install and manage mods, copy them to the mods folder (use the 'Open Mods Folder' button). Be sure to restart the game afterwards, otherwise the mods will not show up.
|
To install and manage mods, copy them to the mods folder (use the 'Open Mods Folder' button). Be sure to restart the game afterwards, otherwise the mods will not show up.
|
||||||
noModSupport: Get the full version on Steam to install mods!
|
noModSupport: Get the full version on Steam to install mods!
|
||||||
|
browserNoSupport: Due to browser restrictions it is currently only possible to install mods in the Steam version - Sorry!
|
||||||
|
|
||||||
togglingComingSoon:
|
togglingComingSoon:
|
||||||
title: Coming Soon
|
title: Coming Soon
|
||||||
|
Loading…
Reference in New Issue
Block a user