diff --git a/.eslintignore b/.eslintignore index 5d8bd0644..f84541c52 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,4 +1,4 @@ public/**/*.js src/components/SliderComponent.vue javascripts/supported-browsers.js -src/steam/PlayFabClientApi.js +src/steam/bindings/PlayFabClientApi.js diff --git a/javascripts/core/achievements/normal-achievement.js b/javascripts/core/achievements/normal-achievement.js index 6e952cbc1..fdae09592 100644 --- a/javascripts/core/achievements/normal-achievement.js +++ b/javascripts/core/achievements/normal-achievement.js @@ -1,3 +1,4 @@ +import { SteamRuntime } from "@/steam"; import { GameMechanicState } from "../game-mechanics/index"; class AchievementState extends GameMechanicState { @@ -70,7 +71,7 @@ class AchievementState extends GameMechanicState { GameUI.notify.reality(`Automatically unlocked: ${this.name}`); } else { GameUI.notify.success(`Achievement: ${this.name}`); - SteamFunctions.GiveAchievement(this.id); + SteamRuntime.activateAchievement(this.id); } if (player.speedrun.isActive && !player.speedrun.achievementTimes[this.id]) { // This stores a lot of data in the savefile and seems particularly suceptible to floating-point rounding issues @@ -173,6 +174,12 @@ export const Achievements = { get power() { if (Pelle.isDisabled("achievementMult")) return 1; return Achievements._power.value; + }, + + updateSteamStatus() { + for (const achievement in Achievements.all.filter(x => x.isUnlocked)) { + SteamRuntime.activateAchievement(achievement.id); + } } }; diff --git a/javascripts/core/app/options.js b/javascripts/core/app/options.js index 74b6ce7ea..a3438506f 100644 --- a/javascripts/core/app/options.js +++ b/javascripts/core/app/options.js @@ -1,3 +1,4 @@ +import { ElectronRuntime } from "@/steam"; import { sha512_256 } from "js-sha512"; import { DEV } from "@/env"; @@ -18,7 +19,7 @@ export class GameOptions { // This is needed because .s-base--dark is on newUI/normal but not on oldUI/normal // So the classes on body need to be updated Themes.find(Theme.currentName()).set(); - SteamFunctions.UIZoom() + ElectronRuntime.updateZoom(); GameStorage.save(); } diff --git a/javascripts/core/crash.js b/javascripts/core/crash.js index b0456b86c..379b5bf70 100644 --- a/javascripts/core/crash.js +++ b/javascripts/core/crash.js @@ -46,3 +46,7 @@ window.onerror = (event, source) => { if (!source.endsWith(".js")) return; GlobalErrorHandler.onerror(event); }; + +window.addEventListener("unhandledrejection", event => { + GlobalErrorHandler.onerror(event); +}); diff --git a/javascripts/core/discord-parser.js b/javascripts/core/discord-parser.js index 7e09e7060..38adb43d2 100644 --- a/javascripts/core/discord-parser.js +++ b/javascripts/core/discord-parser.js @@ -1,14 +1,15 @@ +import { discordRichPresence } from "./secret-formula/discord-rich-presence"; export const RichPresenceInfo = { get gameStage() { - const stageDB = GameDatabase.discordRichPresence.stages; + const stageDB = discordRichPresence.stages; for (let stage = stageDB.length - 1; stage >= 0; stage--) { if (stageDB[stage].hasReached()) return stageDB[stage]; } throw Error("No valid progress stage found"); }, get challengeState() { - const challDB = GameDatabase.discordRichPresence.challenges; + const challDB = discordRichPresence.challenges; for (let index = 0; index < challDB.length; index++) { const chall = challDB[index]; if (chall.activityToken()) return chall; diff --git a/javascripts/core/hotkeys.js b/javascripts/core/hotkeys.js index 5dde35156..a689c0c30 100644 --- a/javascripts/core/hotkeys.js +++ b/javascripts/core/hotkeys.js @@ -1,3 +1,4 @@ +import { ElectronRuntime } from "@/steam"; import Mousetrap from "mousetrap"; import { GameKeyboard } from "./keyboard"; @@ -280,28 +281,28 @@ export const shortcuts = [ name: "Zoom In", keys: ["ctrl", "="], type: "bind", - function: () => {SteamFunctions.SetZoomLevel("Increase")}, + function: () => ElectronRuntime.increaseZoom(), visible: () => false }, { name: "Zoom In", keys: ["ctrl", "+"], type: "bind", - function: () => {SteamFunctions.SetZoomLevel("Increase")}, + function: () => ElectronRuntime.increaseZoom(), visible: () => false }, { name: "Zoom Out", keys: ["ctrl", "-"], type: "bind", - function: () => {SteamFunctions.SetZoomLevel("Decrease")}, + function: () => ElectronRuntime.decreaseZoom(), visible: () => false }, { name: "Reset Zoom", keys: ["ctrl", "0"], type: "bind", - function: () => {SteamFunctions.ResetZoom()}, + function: () => ElectronRuntime.resetZoom(), visible: () => false }, ]; diff --git a/javascripts/core/payments.js b/javascripts/core/payments.js index e023a20f3..877acf111 100644 --- a/javascripts/core/payments.js +++ b/javascripts/core/payments.js @@ -90,7 +90,7 @@ const Payments = { }, // Sends a request to purchase a STD upgrade, returning true if successful (and syncs data), false if not - async buyUpgrade(upgradeKey) { + async buyUpgrade(upgradeKey, cosmeticName) { if (!Cloud.loggedIn) return false; let res; try { @@ -103,7 +103,7 @@ const Payments = { user: Cloud.user.id, upgrade: upgradeKey, extraData: { - requestedSet: GlyphAppearanceHandler.chosenFromModal?.id, + requestedSet: cosmeticName, fullCompletions: player.records.fullGameCompletions } }) @@ -150,4 +150,4 @@ const Payments = { } }; -export default Payments; \ No newline at end of file +export default Payments; diff --git a/javascripts/core/playfab.js b/javascripts/core/playfab.js deleted file mode 100644 index 7ca89f35e..000000000 --- a/javascripts/core/playfab.js +++ /dev/null @@ -1,42 +0,0 @@ -import { PlayFab } from "@/steam/PlayFabClientApi"; - -export function playFabLogin() { - try { - Steam.getAuthSessionTicket(ticket => { - const SteamTicket = ticket.ticket.toString("hex"); - PlayFab.settings.titleId = "59813"; - const requestData = { - TitleId: PlayFab.settings.titleId, - SteamTicket, - CreateAccount: true - }; - try { - PlayFab.ClientApi.LoginWithSteam(requestData, playFabLoginCallback); - } catch (e) { - console.log("Unable to send login request to PlayFab."); - } - }); - } catch (e) { - console.log(e); - } -} - -PlayFab.settings.titleId = "59813"; -let playFabId = -1; - -function playFabLoginCallback(data, error) { - if (error) { - console.log(error.errorMessage); - GameUI.notify.error("Couldn't log in to PlayFab Cloud."); - return; - } - if (data) { - playFabId = data.data.PlayFabId; - PlayFab.PlayFabID = playFabId; - GameUI.notify.info("Logged in to PlayFab Cloud"); - PlayFab.ClientApi.UpdateUserTitleDisplayName({ "DisplayName": Steam.getSteamId().screenName }); - - console.log("Logged in to playFab"); - SteamFunctions.autoLogin(); - } -} diff --git a/javascripts/core/secret-formula/discord-rich-presence.js b/javascripts/core/secret-formula/discord-rich-presence.js index 859ffcc04..28a8e3827 100644 --- a/javascripts/core/secret-formula/discord-rich-presence.js +++ b/javascripts/core/secret-formula/discord-rich-presence.js @@ -21,7 +21,7 @@ function formatMachines(realPart, imagPart) { // This is used for Discord Rich Presence, the information which shows up on a person's profile badge in Discord if // they are playing a game on Steam which has integration that pushes the info to Discord -GameDatabase.discordRichPresence = { +export const discordRichPresence = { /** * List of all challenges to display within DRP, checked from the first entry and iterating forward. It will only * show the first one it finds for space reasons, but this also has the desirable effect of hiding key challenges @@ -261,3 +261,5 @@ GameDatabase.discordRichPresence = { }, ] }; + +GameDatabase.discordRichPresence = discordRichPresence; diff --git a/javascripts/core/shop.js b/javascripts/core/shop.js index 948113a0a..cfe2e0b0b 100644 --- a/javascripts/core/shop.js +++ b/javascripts/core/shop.js @@ -1,3 +1,4 @@ +import { SteamRuntime } from "@/steam"; import { RebuyableMechanicState } from "./game-mechanics/index"; import Payments from "./payments"; @@ -177,8 +178,14 @@ class ShopPurchaseState extends RebuyableMechanicState { if (GameEnd.creditsEverClosed) return false; if (this.config.instantPurchase && ui.$viewModel.modal.progressBar) return false; - // Contact the firebase server to verify the purchase - const success = true//await Payments.buyUpgrade(this.config.key); + const cosmeticName = this.config.key === "singleCosmeticSet" + ? GlyphAppearanceHandler.chosenFromModal?.name + : undefined; + + // Contact the purchase provider to verify the purchase + const success = SteamRuntime.isActive + ? await SteamRuntime.purchaseShopItem(this.cost, this.config.key, cosmeticName) + : await Payments.buyUpgrade(this.config.key, cosmeticName); if (!success) return false; if (player.IAP.enabled) Speedrun.setSTDUse(true); diff --git a/javascripts/core/storage/cloud-saving.js b/javascripts/core/storage/cloud-saving.js index e55125f0f..dac7ef430 100644 --- a/javascripts/core/storage/cloud-saving.js +++ b/javascripts/core/storage/cloud-saving.js @@ -1,4 +1,5 @@ /* eslint-disable import/extensions */ +import { SteamRuntime } from "@/steam"; import pako from "pako/dist/pako.esm.mjs"; /* eslint-enable import/extensions */ @@ -52,6 +53,29 @@ export const Cloud = { } }, + async loginWithSteam(accountId, staticAccountId, screenName) { + if (this.loggedIn) { + Cloud.user.displayName = screenName; + return true; + } + + const email = `${accountId}@ad.com`; + const pass = staticAccountId; + try { + await Cloud.manualCloudCreate(email, pass); + } catch { + try { + await Cloud.manualCloudLogin(email, pass); + } catch (error) { + // eslint-disable-next-line no-console + console.log(`Firebase Login Error: ${error}`); + return false; + } + } + + Cloud.user.displayName = screenName; + return true; + }, async manualCloudLogin(EmailAddress,Password) { //try{ @@ -234,16 +258,15 @@ export const Cloud = { if (user) { this.user = { id: user.uid, - displayName: steamOn ? Steam.getSteamId().screenName : "",//user.displayName, + displayName: SteamRuntime.isActive + ? SteamRuntime.screenName + : user.displayName, email: user.email, }; - SteamFunctions.SyncPlayFabSTD() + SteamRuntime.syncIap(); } else { this.user = null; } }); }, }; - -Cloud.init(); -//this.user.displayName = Steam.getSteamId().screenName diff --git a/javascripts/core/storage/storage.js b/javascripts/core/storage/storage.js index 5837a7cec..6a99254ef 100644 --- a/javascripts/core/storage/storage.js +++ b/javascripts/core/storage/storage.js @@ -1,8 +1,10 @@ +import { SteamRuntime } from "@/steam"; import * as ADNotations from "@antimatter-dimensions/notations"; import { DEV } from "@/env"; import { deepmergeAll } from "@/utility/deepmerge"; +import { Achievement } from "../achievements/normal-achievement"; export const GameStorage = { currentSlot: 0, @@ -30,7 +32,7 @@ export const GameStorage = { const root = GameSaveSerializer.deserialize(save); this.loadRoot(root); - SteamFunctions.BackfillAchievements() + Achievements.updateSteamStatus(); }, loadRoot(root) { @@ -66,7 +68,7 @@ export const GameStorage = { Tabs.all.find(t => t.id === player.options.lastOpenTab).show(true); Cloud.resetTempState(); GameUI.notify.info("Game loaded"); - SteamFunctions.BackfillAchievements() + Achievements.updateSteamStatus(); }, import(saveData) { @@ -93,7 +95,7 @@ export const GameStorage = { // is showing Tab.options.subtabs[0].show(); GameUI.notify.info("Game imported"); - SteamFunctions.BackfillAchievements() + Achievements.updateSteamStatus(); }, importAsFile() { diff --git a/javascripts/game.js b/javascripts/game.js index 66694e4cf..c315b0a36 100644 --- a/javascripts/game.js +++ b/javascripts/game.js @@ -1,10 +1,11 @@ +import { ElectronRuntime, SteamRuntime } from "@/steam"; import TWEEN from "tween.js"; import { DC } from "./core/constants"; import { deepmergeAll } from "@/utility/deepmerge"; -import { playFabLogin } from "./core/playfab"; import { DEV } from "@/env"; import { SpeedrunMilestones } from "./core/speedrun"; +import { Cloud } from "./core/storage"; import { supportedBrowsers } from "./supported-browsers"; import Payments from "./core/payments"; @@ -1022,12 +1023,6 @@ window.onload = function() { GameUI.initialized = supportedBrowser; ui.view.initialized = supportedBrowser; setTimeout(() => { - if(Steam){ - if(Steam.initAPI()){ - playFabLogin(); - if(SteamFunctions.discordOn){SteamFunctions.SetRichPresence()}; - } - } document.getElementById("loading").style.display = "none"; }, 500); if (!supportedBrowser) { @@ -1064,15 +1059,11 @@ export function init() { // eslint-disable-next-line no-console console.log("👨💻 Development Mode 👩💻"); } + ElectronRuntime.initialize(); + SteamRuntime.initialize(); + Cloud.init(); GameStorage.load(); Tabs.all.find(t => t.config.id === player.options.lastOpenTab).show(true); - if(steamOn){ - SteamFunctions.UIZoom(); - if(!Cloud.loggedIn){ - SteamFunctions.autoLogin() - } - } - //shop.init(); Payments.init(); } diff --git a/public/Steam/steam.js b/public/Steam/steam.js deleted file mode 100644 index 8b1a9b419..000000000 --- a/public/Steam/steam.js +++ /dev/null @@ -1,282 +0,0 @@ -"use strict"; - - -const SteamFunctions = { - purchaseChecker: [], - purchasesInitiated: true, - macUser: false, - macInterval: 0, - discordInterval: 0, - richPresenceInterval: 0, - discordOn: false, - macIntervalOn: false, - zoomLevel: 1, - SteamInitialize() { - this.forceRefresh(); - this.EventHandlers(); - if (window.navigator.platform === "MacIntel") { - SteamFunctions.macUser = true; - }else{ - Steam.initDiscordAPI("1057439416819396689",1399720) - SteamFunctions.discordOn = true - SteamFunctions.richPresenceInterval = setInterval(SteamFunctions.SetRichPresence,8000) - SteamFunctions.discordInterval = setInterval(Steam.runDiscordCallbacks, 4000); - } - this.GetZoom() - }, - forceRefresh() { // Canvas workaround to enable overlay - const canvas = document.getElementById("forceRefreshCanvas"); - const ctx = canvas.getContext("2d"); - ctx.clearRect(0, 0, canvas.width, canvas.height); - window.requestAnimationFrame(SteamFunctions.forceRefresh); - }, - SetRichPresence(){ - if(SteamFunctions.discordOn && RichPresenceInfo){ - Steam.setDiscordActivity({ - smallImage: "icon", - largeImage: "icon", - state: RichPresenceInfo.state, - details: RichPresenceInfo.details - }) - } - }, - UIZoom() { - if (nodeOn) { - const setSize = 1020; - const SizeDiff = window.outerHeight / setSize; - require("electron").webFrame.setZoomFactor(SizeDiff*SteamFunctions.zoomLevel); - } - }, - SetZoomLevel(ZoomType){ - const zoomMAXed = SteamFunctions.zoomLevel >= 1.5 && ZoomType==="Increase" - const zoomMINed = SteamFunctions.zoomLevel <= 0.5 && ZoomType==="Decrease" - const zoomPossible = !(zoomMAXed || zoomMINed) - if(zoomPossible){ - ZoomType==="Increase" && !zoomMAXed ? SteamFunctions.zoomLevel += .1 : SteamFunctions.zoomLevel = SteamFunctions.zoomLevel - ZoomType==="Decrease" && !zoomMINed ? SteamFunctions.zoomLevel -= .1 : SteamFunctions.zoomLevel = SteamFunctions.zoomLevel - SteamFunctions.zoomLevel = Math.round(SteamFunctions.zoomLevel * 10) / 10 - localStorage.setItem("Zoom",SteamFunctions.zoomLevel) - SteamFunctions.UIZoom() - GameUI.notify.info(`Size changed to ${Math.round(SteamFunctions.zoomLevel*100)}%`) - }else{ - zoomMAXed ? GameUI.notify.info(`Zoom Level is at Maximum`) : GameUI.notify.info(`Zoom Level is at Minimum`) - } - }, - GetZoom(){ - let zoomGet; - if(localStorage.getItem("Zoom")){ - zoomGet = Number(localStorage.getItem("Zoom")) - }else{ - localStorage.setItem("Zoom",1) - zoomGet = 1 - } - SteamFunctions.zoomLevel = zoomGet - }, - ResetZoom(){ - localStorage.setItem("Zoom",1) - SteamFunctions.zoomLevel = 1 - SteamFunctions.UIZoom() - GameUI.notify.info(`Size reverted to 100%`) - }, - EventHandlers() { - Steam.on("micro-txn-authorization-response", (data, ordered, orderstate) => { - if (orderstate === true) { - SteamFunctions.PurchaseValidation(); - } - }); - }, - GiveAchievement(AchieveID) { - if (Steam && steamOn) { - if (Steam.activateAchievement) { - Steam.activateAchievement(`Achievement${AchieveID}`, - () => console.log(`Successfully Achieved Achievement${AchieveID}`), - err => console.log(`Achievement Error: ${err}`) - ); - } - } - }, - BackfillAchievements() { - if (Steam && steamOn) { - if (Steam.activateAchievement) { - const achAchieved = [] - const achErrored = [] - for (const ach in Achievements.all) { - if (Achievements.all[ach].isUnlocked) { - Steam.activateAchievement(`Achievement${Achievements.all[ach].id}`, - () => achAchieved.push(Achievements.all[ach].id), - err => achErrored.push(Achievements.all[ach].id) - ); - } - } - } - } - }, - async autoLogin(){ - if(!Cloud.loggedIn){ - const AutoEmail = `${Steam.getSteamId().accountId}@ad.com` - const AutoPass = Steam.getSteamId().staticAccountId - try{ - await Cloud.manualCloudCreate(AutoEmail,AutoPass); - }catch(e){ - try{ - await Cloud.manualCloudLogin(AutoEmail,AutoPass) - }catch(LoginError){ - this.error = true; - this.errorMessage = "Unable to login, please recheck email/password"; - console.log(`Login Error, Retrying (${LoginError})`) - return; - } - } - Cloud.user.displayName = Steam.getSteamId().screenName - } - SteamFunctions.SyncPlayFabSTD() - }, - PurchaseIAP(STD, kreds) { - if (!steamOn) return; - const TheItem = { ItemId: `${STD}STD`, Quantity: 1, Annotation: "Purchased via in-game store" }; - PlayFab.settings.titleId = "59813"; - const loginRequest = { - Items: [TheItem] - }; - PlayFab.ClientApi.StartPurchase(loginRequest, (result, error) => { - console.log(result, error); - if (result !== null) { - const TheOrder = result.data.OrderId; - const PurchaseRequest = { - OrderId: TheOrder, - Currency: "RM", - ProviderName: "Steam" - }; - PlayFab.ClientApi.PayForPurchase(PurchaseRequest, (purchaseResult, purchaseError) => { - if (purchaseResult !== null) { - const txnID = purchaseResult.data.ProviderData; - SteamFunctions.purchaseChecker.push(purchaseResult.data.OrderId); - if (window.navigator.platform === "MacIntel") { - shell.openExternal("https://store.steampowered.com/checkout/approvetxn/" + txnID + "/?returnurl=steam"); - SteamFunctions.macInterval = setInterval(async()=>{ - SteamFunctions.PurchaseValidation() - },2000) - SteamFunctions.macIntervalOn = true - setTimeout(()=>{clearInterval(SteamFunctions.macInterval);SteamFunctions.macIntervalOn = false},300000) - } - } else if (purchaseError !== null) { - console.log(purchaseError); - } - }); - } else if (error !== null) { - console.log(error); - } - }); - }, - ConfirmSteamPurchase(OrderIdentifier) { - PlayFab.ClientApi.ConfirmPurchase({ OrderId: OrderIdentifier }, (result, error) => { - if (result !== null && result.data.Items != null) { - const PurchaseName = result.data.Items[0].ItemId; - const PurchaseInstance = result.data.Items[0].ItemInstanceId; - PlayFab.ClientApi.ConsumeItem({ ItemInstanceId: PurchaseInstance, ConsumeCount: 1 }, - (consumeResult, consumeError) => { - if (consumeResult !== null) { - const stdsBought = Number(PurchaseName.replace("STD", "")); - const currencyAddRequest = {Amount: stdsBought,VirtualCurrency: "ST"} - PlayFab.ClientApi.AddUserVirtualCurrency(currencyAddRequest, (result, error) => { - if (result !== null) { - SteamFunctions.SyncPlayFabSTD() - } else if (error !== null) { - console.log(error); - } - }) - SteamFunctions.purchaseChecker = SteamFunctions.purchaseChecker.filter(item => item !== OrderIdentifier); - GameUI.notify.info(`${stdsBought} STDs Obtained!`); - } else if (consumeError !== null) { - console.log(consumeError); - } - }); - } else if (error !== null) { - console.log("Awaiting Payment Confirmation"); - } - }); - }, - PurchaseValidation() { - if (SteamFunctions.purchaseChecker.length > 0) { - SteamFunctions.purchaseChecker.forEach( - anOrder => SteamFunctions.ConfirmSteamPurchase(anOrder) - ); - } - }, - SyncPlayFabSTD(){ - if(PlayFab.ClientApi.IsClientLoggedIn()){ - PlayFab.ClientApi.GetUserInventory({PlayFabId: PlayFab.PlayFabId}, (result, error) => { - if (result !== null) { - const CurrentSTD = result.data.VirtualCurrency.ST - const Inventory = result.data.Inventory - ShopPurchaseData.totalSTD = CurrentSTD - const inventoryData = {} - Inventory.forEach( - ShopItem => inventoryData[ShopItem.ItemId] = ShopItem.RemainingUses - ); - for (const key of Object.keys(GameDatabase.shopPurchases)) ShopPurchaseData[key] = inventoryData[key] ?? 0; - GameUI.update(); - SteamFunctions.GetCosmetics() - } else if (error !== null) { - console.log(error); - } - }) - } - }, - PurchaseShopItem(itemCost,itemKey,itemConfig,chosenSet){ - const itemPurchaseRequest = { - ItemId: itemKey, - Price: typeof itemCost === "function" ? itemCost() : itemCost, - VirtualCurrency: "ST" - } - PlayFab.ClientApi.PurchaseItem(itemPurchaseRequest, (result, error) => { - if (result !== null) { - if (itemConfig.instantPurchase) itemConfig.onPurchase(); - if (itemKey === "singleCosmeticSet") this.StoreCosmetics(chosenSet) - SteamFunctions.SyncPlayFabSTD(); - } else if (error !== null) { - console.log(error); - GameUI.notify.error(error.errorMessage) - } - }) - }, - StoreCosmetics(Cosmetic){ - const CosmeticID = Object.entries(GameDatabase.reality.glyphCosmeticSets).filter(item => item[1]["name"]===Cosmetic)[0][0] - var CosmeticList = [CosmeticID] - PlayFab.ClientApi.GetUserData({PlayFabId: PlayFab.PlayFabId}, (result, error) => { - if (result !== null) { - if(result.data.Data["Cosmetics"]){ - CosmeticList = CosmeticList.concat(result.data.Data["Cosmetics"].Value.split(",")) - } - const updatedCosmetics = [...new Set(CosmeticList)] - const UpdateRequest = { - Data: { - Cosmetics: updatedCosmetics.join(",") - } - } - PlayFab.ClientApi.UpdateUserData(UpdateRequest, (result, error) => { - if (result !== null) { - console.log("Cosmetics Updated on Server"); - ShopPurchaseData.unlockedCosmetics = updatedCosmetics - GameUI.update(); - } else if (error !== null) { - console.log(error); - } - }) - } else if (error !== null) { - console.log("Error Getting User Data"); - } - }) - }, - GetCosmetics(){ - PlayFab.ClientApi.GetUserData({PlayFabId: PlayFab.PlayFabId}, (result, error) => { - if (result !== null) { - const currentCosmetics = result.data.Data["Cosmetics"] ? result.data.Data["Cosmetics"].Value.split(",") : [] - ShopPurchaseData.unlockedCosmetics = currentCosmetics - GameUI.update(); - } else if (error !== null) { - console.log(error); - } - }) - } -}; \ No newline at end of file diff --git a/public/index.html b/public/index.html index 6a5713e16..da4a1a8e6 100644 --- a/public/index.html +++ b/public/index.html @@ -24,7 +24,7 @@